From f93466522b2b691f66ee71c3d0bdbc3c9e3fb9a1 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Tue, 8 Apr 2025 18:45:46 +0900 Subject: [PATCH 01/75] [c] fix wrong TwoColorAnimation parsing in Json (#2797) --- spine-c/spine-c/src/spine/SkeletonJson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-c/spine-c/src/spine/SkeletonJson.c b/spine-c/spine-c/src/spine/SkeletonJson.c index cdd3a3533..c4e7a6fa8 100644 --- a/spine-c/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/spine-c/src/spine/SkeletonJson.c @@ -391,7 +391,7 @@ static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *ro for (frame = 0, bezier = 0;; ++frame) { float time2; - spRGBA2Timeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a, color2.g, + spRGBA2Timeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); nextMap = keyMap->next; if (!nextMap) { From 294399886aa27c2bdfb39c26789eab7432482726 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Tue, 8 Apr 2025 18:46:35 +0900 Subject: [PATCH 02/75] [cpp] fix bound computation ignores clipping (#2800) --- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index baaa7b53d..d4e78d18b 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -507,6 +507,7 @@ void Skeleton::getBounds(float &outX, float &outY, float &outWidth, } else if (attachment != NULL && attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) { clipper->clipStart(*slot, static_cast(attachment)); + continue; } if (verticesLength > 0) { From 4071565a9cc796f8b24c291a9b514273d5f42292 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Tue, 8 Apr 2025 18:47:32 +0900 Subject: [PATCH 03/75] Update SkeletonBinary.c (#2790) remove making extra copy of cString which cause the existing cString to be leak, and can not be disposed later, --- spine-c/spine-c/src/spine/SkeletonBinary.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index a151c48eb..8f3dad526 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -1178,11 +1178,6 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput return NULL; mesh = SUB_CAST(spMeshAttachment, attachment); mesh->path = (char *) path; - if (mesh->path) { - char *tmp = NULL; - MALLOC_STR(tmp, mesh->path); - mesh->path = tmp; - } spColor_setFromColor(&mesh->color, &color); mesh->sequence = sequence; mesh->width = width; From f037c05b7312dffd7f412ddc6835926dc38aa1e5 Mon Sep 17 00:00:00 2001 From: James Chen Date: Tue, 8 Apr 2025 17:48:47 +0800 Subject: [PATCH 04/75] Fix memory leak of Vector::setSize (#2781) * Fix memory leak of Vector::setSize * Format code --- spine-cpp/spine-cpp/include/spine/Vector.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 771b59791..6247c1d33 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -85,6 +85,10 @@ namespace spine { for (size_t i = oldSize; i < _size; i++) { construct(_buffer + i, defaultValue); } + } else { + for (size_t i = _size; i < oldSize; i++) { + destroy(_buffer + i); + } } } From 093b0d432d000a25749bf537d1133e0bdb9d7212 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Tue, 8 Apr 2025 18:50:18 +0900 Subject: [PATCH 05/75] update package setting to fix compile Error (#2780) since SpineCppLite expose c-interface only and does not expose cpp interface c++ interperability is no-op and just causing compiler crash. So we could add linker flag to ensure SpineCppLite is build with C++ while removing c++ interperability mode --- Package.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index 9dae3df94..a559c8a36 100644 --- a/Package.swift +++ b/Package.swift @@ -21,14 +21,14 @@ let package = Package( dependencies: [ "SpineCppLite", "SpineShadersStructs" ], - path: "spine-ios/Sources/Spine", - swiftSettings: [ - .interoperabilityMode(.Cxx) - ] + path: "spine-ios/Sources/Spine" ), .target( name: "SpineCppLite", - path: "spine-ios/Sources/SpineCppLite" + path: "spine-ios/Sources/SpineCppLite", + linkerSettings: [ + .linkedLibrary("c++"), + ] ), .systemLibrary( name: "SpineShadersStructs", From 6e5da45fa3e8676faf630add38c3efc2b24938d2 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Tue, 8 Apr 2025 18:51:32 +0900 Subject: [PATCH 06/75] [iOS] update Swift inteface for more fine grained control(like external atlas loading) (#2772) * update Swift inteface for more fine grained control - move instance method to static method which does not require spine cpp pointer - implement equality and hashing based on cpp pointer so that it can be stored in collection and compare it - expose Atlas image count property so that the user can load the atlas resource lazily - User can now Create Atlas by using Altas static function, and fetch whole resource path by iterating count of atlas page count * [iOS] fix wrong y-axis alignment --- .../spine-cpp-lite/spine-cpp-lite-codegen.py | 34 ++ spine-ios/Sources/Spine/BoundsProvider.swift | 2 +- .../Spine/Spine.Generated+Extensions.swift | 8 + spine-ios/Sources/Spine/Spine.Generated.swift | 499 +++++++++++++++++- 4 files changed, 540 insertions(+), 3 deletions(-) diff --git a/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py b/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py index e0d0b420c..46d3e4e8a 100644 --- a/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py +++ b/spine-cpp/spine-cpp-lite/spine-cpp-lite-codegen.py @@ -439,6 +439,7 @@ class SwiftFunctionWriter: if spine_params and spine_params[0].type == self.spine_object.name: spine_params_without_ivar = spine_params[1:] else: + function_string = function_string.replace("public func ", "public static func ") spine_params_without_ivar = spine_params swift_params = [ @@ -501,6 +502,39 @@ class SwiftObjectWriter: object_string += "\n" object_string += "\n" + object_string += inset + object_string += "public override func isEqual(_ object: Any?) -> Bool" + object_string += " {" + object_string += "\n" + object_string += inset + inset + object_string += f"guard let other = object as? {class_name} else {{ return false }}" + object_string += "\n" + object_string += inset + inset + object_string += f"return self.{ivar_name} == other.{ivar_name}" + object_string += "\n" + object_string += inset + object_string += "}" + object_string += "\n" + object_string += "\n" + + object_string += inset + object_string += "public override var hash: Int" + object_string += " {" + object_string += "\n" + object_string += inset + inset + object_string += "var hasher = Hasher()" + object_string += "\n" + object_string += inset + inset + object_string += f"hasher.combine(self.{ivar_name})" + object_string += "\n" + object_string += inset + inset + object_string += "return hasher.finalize()" + object_string += "\n" + object_string += inset + object_string += "}" + object_string += "\n" + object_string += "\n" + filtered_spine_functions = [spine_function for spine_function in self.spine_object.functions if not "_get_num_" in spine_function.name] spine_functions_by_name = {} diff --git a/spine-ios/Sources/Spine/BoundsProvider.swift b/spine-ios/Sources/Spine/BoundsProvider.swift index e2b3ca56a..f42aadb5a 100644 --- a/spine-ios/Sources/Spine/BoundsProvider.swift +++ b/spine-ios/Sources/Spine/BoundsProvider.swift @@ -151,7 +151,7 @@ public enum Alignment: Int { switch self { case .topLeft, .topCenter, .topRight: return -1.0 case .centerLeft, .center, .centerRight: return 0.0 - case .bottomLeft, .bottomCenter, .bottomRight: return -1.0 + case .bottomLeft, .bottomCenter, .bottomRight: return 1.0 } } } diff --git a/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift b/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift index 5f616d2c5..eaeabbeca 100644 --- a/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift +++ b/spine-ios/Sources/Spine/Spine.Generated+Extensions.swift @@ -365,3 +365,11 @@ public extension SkeletonBounds { return SkeletonBounds(spine_skeleton_bounds_create()) } } + +@objc public extension Atlas { + + var imagePathCount:Int32 { + spine_atlas_get_num_image_paths(wrappee) + } + +} diff --git a/spine-ios/Sources/Spine/Spine.Generated.swift b/spine-ios/Sources/Spine/Spine.Generated.swift index 94c81c9e1..9bdcca073 100644 --- a/spine-ios/Sources/Spine/Spine.Generated.swift +++ b/spine-ios/Sources/Spine/Spine.Generated.swift @@ -23,6 +23,17 @@ public final class TransformConstraintData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? TransformConstraintData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var bones: [BoneData] { let ptr = spine_transform_constraint_data_get_bones(wrappee) guard let validPtr = ptr else { return [] } @@ -181,6 +192,17 @@ public final class BoundingBoxAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? BoundingBoxAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var color: Color { return .init(spine_bounding_box_attachment_get_color(wrappee)) } @@ -202,6 +224,17 @@ public final class PhysicsConstraintData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? PhysicsConstraintData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var bone: BoneData { get { return .init(spine_physics_constraint_data_get_bone(wrappee)) @@ -413,6 +446,17 @@ public final class AnimationStateEvents: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? AnimationStateEvents else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + @discardableResult public func getEventType(index: Int32) -> EventType { return spine_animation_state_events_get_event_type(wrappee, index) @@ -445,6 +489,17 @@ public final class TransformConstraint: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? TransformConstraint else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var order: Int32 { return spine_transform_constraint_get_order(wrappee) } @@ -552,6 +607,17 @@ public final class PathConstraintData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? PathConstraintData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var bones: [BoneData] { let ptr = spine_path_constraint_data_get_bones(wrappee) guard let validPtr = ptr else { return [] } @@ -665,6 +731,17 @@ public final class AnimationStateData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? AnimationStateData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var skeletonData: SkeletonData { return .init(spine_animation_state_data_get_skeleton_data(wrappee)) } @@ -714,6 +791,17 @@ public final class SkeletonDataResult: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SkeletonDataResult else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var error: String? { return spine_skeleton_data_result_get_error(wrappee).flatMap { String(cString: $0) } } @@ -741,6 +829,17 @@ public final class ClippingAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? ClippingAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var color: Color { return .init(spine_clipping_attachment_get_color(wrappee)) } @@ -771,6 +870,17 @@ public final class IkConstraintData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? IkConstraintData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var bones: [BoneData] { let ptr = spine_ik_constraint_data_get_bones(wrappee) guard let validPtr = ptr else { return [] } @@ -857,6 +967,17 @@ public final class PhysicsConstraint: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? PhysicsConstraint else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var bone: Bone { get { return .init(spine_physics_constraint_get_bone(wrappee)) @@ -1120,6 +1241,17 @@ public final class RegionAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? RegionAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var color: Color { return .init(spine_region_attachment_get_color(wrappee)) } @@ -1236,6 +1368,17 @@ public final class VertexAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? VertexAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var worldVerticesLength: Int32 { return spine_vertex_attachment_get_world_vertices_length(wrappee) } @@ -1279,6 +1422,17 @@ public final class SkeletonDrawable: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SkeletonDrawable else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var skeleton: Skeleton { return .init(spine_skeleton_drawable_get_skeleton(wrappee)) } @@ -1314,6 +1468,17 @@ public final class PointAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? PointAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var color: Color { return .init(spine_point_attachment_get_color(wrappee)) } @@ -1372,6 +1537,17 @@ public final class MeshAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? MeshAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var regionUvs: [Float?] { let ptr = spine_mesh_attachment_get_region_uvs(wrappee) guard let validPtr = ptr else { return [] } @@ -1477,6 +1653,17 @@ public final class PathAttachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? PathAttachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var lengths: [Float?] { let ptr = spine_path_attachment_get_lengths(wrappee) guard let validPtr = ptr else { return [] } @@ -1524,6 +1711,17 @@ public final class ConstraintData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? ConstraintData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var type: ConstraintType { return spine_constraint_data_get_type(wrappee) } @@ -1563,6 +1761,17 @@ public final class PathConstraint: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? PathConstraint else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var order: Int32 { return spine_path_constraint_get_order(wrappee) } @@ -1661,6 +1870,17 @@ public final class AnimationState: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? AnimationState else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var data: AnimationStateData { return .init(spine_animation_state_get_data(wrappee)) } @@ -1743,6 +1963,17 @@ public final class SkeletonBounds: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SkeletonBounds else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var polygons: [Polygon] { let ptr = spine_skeleton_bounds_get_polygons(wrappee) guard let validPtr = ptr else { return [] } @@ -1839,6 +2070,17 @@ public final class TextureRegion: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? TextureRegion else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var texture: UnsafeMutableRawPointer { get { return spine_texture_region_get_texture(wrappee) @@ -1960,6 +2202,17 @@ public final class RenderCommand: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? RenderCommand else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var indices: [UInt16] { let ptr = spine_render_command_get_indices(wrappee) guard let validPtr = ptr else { return [] } @@ -1994,6 +2247,17 @@ public final class SkeletonData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SkeletonData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var name: String? { return spine_skeleton_data_get_name(wrappee).flatMap { String(cString: $0) } } @@ -2217,6 +2481,17 @@ public final class IkConstraint: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? IkConstraint else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var order: Int32 { return spine_ik_constraint_get_order(wrappee) } @@ -2316,6 +2591,17 @@ public final class SkinEntries: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SkinEntries else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + @discardableResult public func getEntry(index: Int32) -> SkinEntry { return .init(spine_skin_entries_get_entry(wrappee, index)) @@ -2340,6 +2626,17 @@ public final class TrackEntry: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? TrackEntry else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var trackIndex: Int32 { return spine_track_entry_get_track_index(wrappee) } @@ -2574,6 +2871,17 @@ public final class Attachment: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Attachment else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var name: String? { return spine_attachment_get_name(wrappee).flatMap { String(cString: $0) } } @@ -2606,6 +2914,17 @@ public final class Constraint: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Constraint else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + } @objc(SpineEventData) @@ -2619,6 +2938,17 @@ public final class EventData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? EventData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var name: String? { return spine_event_data_get_name(wrappee).flatMap { String(cString: $0) } } @@ -2685,6 +3015,17 @@ public final class SkinEntry: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SkinEntry else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var slotIndex: Int32 { return spine_skin_entry_get_slot_index(wrappee) } @@ -2710,6 +3051,17 @@ public final class BoneData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? BoneData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var index: Int32 { return spine_bone_data_get_index(wrappee) } @@ -2842,6 +3194,17 @@ public final class SlotData: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? SlotData else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var index: Int32 { return spine_slot_data_get_index(wrappee) } @@ -2919,6 +3282,17 @@ public final class Animation: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Animation else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var name: String? { return spine_animation_get_name(wrappee).flatMap { String(cString: $0) } } @@ -2940,6 +3314,17 @@ public final class Skeleton: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Skeleton else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var bounds: Bounds { return .init(spine_skeleton_get_bounds(wrappee)) } @@ -3181,6 +3566,17 @@ public final class Sequence: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Sequence else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var regions: [TextureRegion] { let ptr = spine_sequence_get_regions(wrappee) guard let validPtr = ptr else { return [] } @@ -3249,6 +3645,17 @@ public final class Polygon: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Polygon else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var vertices: [Float?] { let ptr = spine_polygon_get_vertices(wrappee) guard let validPtr = ptr else { return [] } @@ -3270,6 +3677,17 @@ public final class Bounds: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Bounds else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var x: Float { return spine_bounds_get_x(wrappee) } @@ -3299,6 +3717,17 @@ public final class Vector: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Vector else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var x: Float { return spine_vector_get_x(wrappee) } @@ -3320,6 +3749,17 @@ public final class Event: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Event else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var data: EventData { return .init(spine_event_get_data(wrappee)) } @@ -3387,6 +3827,17 @@ public final class Atlas: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Atlas else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var isPma: Bool { return spine_atlas_is_pma(wrappee) != 0 } @@ -3396,7 +3847,7 @@ public final class Atlas: NSObject { } @discardableResult - public func load(atlasData: String?) -> Atlas { + public static func load(atlasData: String?) -> Atlas { return .init(spine_atlas_load(atlasData)) } @@ -3424,6 +3875,17 @@ public final class Color: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Color else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var r: Float { return spine_color_get_r(wrappee) } @@ -3453,7 +3915,18 @@ public final class Bone: NSObject { super.init() } - public func setIsYDown(yDown: Bool) { + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Bone else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + + public static func setIsYDown(yDown: Bool) { spine_bone_set_is_y_down(yDown ? -1 : 0) } @@ -3772,6 +4245,17 @@ public final class Slot: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Slot else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var data: SlotData { return .init(spine_slot_get_data(wrappee)) } @@ -3841,6 +4325,17 @@ public final class Skin: NSObject { super.init() } + public override func isEqual(_ object: Any?) -> Bool { + guard let other = object as? Skin else { return false } + return self.wrappee == other.wrappee + } + + public override var hash: Int { + var hasher = Hasher() + hasher.combine(self.wrappee) + return hasher.finalize() + } + public var name: String? { return spine_skin_get_name(wrappee).flatMap { String(cString: $0) } } From 8bd5cf2e8034a33864ab92329cd13a720747a140 Mon Sep 17 00:00:00 2001 From: Jan Niklas Hasse Date: Tue, 8 Apr 2025 11:58:03 +0200 Subject: [PATCH 07/75] Fix warning -Wimplicit-fallthrough (#2771) --- spine-c/spine-c/src/spine/Debug.c | 4 ++-- spine-c/spine-c/src/spine/IkConstraint.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spine-c/spine-c/src/spine/Debug.c b/spine-c/spine-c/src/spine/Debug.c index 6e873060e..ebc4cf860 100644 --- a/spine-c/spine-c/src/spine/Debug.c +++ b/spine-c/spine-c/src/spine/Debug.c @@ -208,11 +208,11 @@ void spDebug_printTimeline(spTimeline *timeline) { case SP_TIMELINE_SEQUENCE: { spSequenceTimeline *t = (spSequenceTimeline *) timeline; _spDebug_printTimelineBase(&t->super); - } + } // fallthrough case SP_TIMELINE_INHERIT: { spInheritTimeline *t = (spInheritTimeline *) timeline; _spDebug_printTimelineBase(&t->super); - } + } // fallthrough default: { _spDebug_printTimelineBase(timeline); } diff --git a/spine-c/spine-c/src/spine/IkConstraint.c b/spine-c/spine-c/src/spine/IkConstraint.c index f7d6fd196..a036239f0 100644 --- a/spine-c/spine-c/src/spine/IkConstraint.c +++ b/spine-c/spine-c/src/spine/IkConstraint.c @@ -98,7 +98,7 @@ void spIkConstraint_apply1(spBone *bone, float targetX, float targetY, int /*boo pb = -sc * s * bone->skeleton->scaleX; pd = sa * s * bone->skeleton->scaleY; rotationIK += ATAN2(sc, sa) * RAD_DEG; - } + } // fallthrough default: { float x = targetX - p->worldX, y = targetY - p->worldY; float d = pa * pd - pb * pc; From a0d28956d2a9511d353c6954cb7b644d30674f0b Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 8 Apr 2025 13:30:24 +0200 Subject: [PATCH 08/75] [godot] Fixes for 4.4, see #2801 --- spine-godot/spine_godot/SpineEditorPlugin.cpp | 12 ++++++++++++ spine-godot/spine_godot/SpineEditorPlugin.h | 18 ++++++++++++++++-- spine-godot/spine_godot/SpineSprite.cpp | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/spine-godot/spine_godot/SpineEditorPlugin.cpp b/spine-godot/spine_godot/SpineEditorPlugin.cpp index 9dec0ac3d..bb4ccb562 100644 --- a/spine-godot/spine_godot/SpineEditorPlugin.cpp +++ b/spine-godot/spine_godot/SpineEditorPlugin.cpp @@ -42,8 +42,12 @@ #ifdef SPINE_GODOT_EXTENSION Error SpineAtlasResourceImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray &platform_variants, const TypedArray &gen_files) const { #else +#if VERSION_MINOR > 3 +Error SpineAtlasResourceImportPlugin::import(ResourceUID::ID p_source_id, const String &source_file, const String &save_path, const HashMap &options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { +#else Error SpineAtlasResourceImportPlugin::import(const String &source_file, const String &save_path, const HashMap &options, List *platform_variants, List *gen_files, Variant *metadata) { #endif +#endif #else Error SpineAtlasResourceImportPlugin::import(const String &source_file, const String &save_path, const Map &options, List *platform_variants, List *gen_files, Variant *metadata) { #endif @@ -98,8 +102,12 @@ void SpineAtlasResourceImportPlugin::get_import_options(List *opti #ifdef SPINE_GODOT_EXTENSION Error SpineJsonResourceImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray &platform_variants, const TypedArray &gen_files) const { #else +#if VERSION_MINOR > 3 +Error SpineJsonResourceImportPlugin::import(ResourceUID::ID p_source_id, const String &source_file, const String &save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { +#else Error SpineJsonResourceImportPlugin::import(const String &source_file, const String &save_path, const HashMap &options, List *platform_variants, List *gen_files, Variant *metadata) { #endif +#endif #else Error SpineJsonResourceImportPlugin::import(const String &source_file, const String &save_path, const Map &options, List *platform_variants, List *gen_files, Variant *metadata) { #endif @@ -126,8 +134,12 @@ Error SpineJsonResourceImportPlugin::import(const String &source_file, const Str #ifdef SPINE_GODOT_EXTENSION Error SpineBinaryResourceImportPlugin::_import(const String &source_file, const String &save_path, const Dictionary &options, const TypedArray &platform_variants, const TypedArray &gen_files) const { #else +#if VERSION_MINOR > 3 +Error SpineBinaryResourceImportPlugin::import(ResourceUID::ID p_source_id, const String &source_file, const String &save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { +#else Error SpineBinaryResourceImportPlugin::import(const String &source_file, const String &save_path, const HashMap &options, List *platform_variants, List *gen_files, Variant *metadata) { #endif +#endif #else Error SpineBinaryResourceImportPlugin::import(const String &source_file, const String &save_path, const Map &options, List *platform_variants, List *gen_files, Variant *metadata) { #endif diff --git a/spine-godot/spine_godot/SpineEditorPlugin.h b/spine-godot/spine_godot/SpineEditorPlugin.h index b80ece51d..54a2592f7 100644 --- a/spine-godot/spine_godot/SpineEditorPlugin.h +++ b/spine-godot/spine_godot/SpineEditorPlugin.h @@ -107,9 +107,12 @@ public: void get_import_options(const String &path, List *options, int preset) const override; virtual bool get_option_visibility(const String &path, const String &option, const HashMap &options) const override { return true; } - +#if VERSION_MINOR > 3 + Error import(ResourceUID::ID p_source_id, const String &source_file, const String &save_path, const HashMap &options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata = nullptr) override; +#else Error import(const String &source_file, const String &save_path, const HashMap &options, List *platform_variants, List *gen_files, Variant *metadata) override; #endif +#endif #else void get_import_options(List *options, int preset) const override; @@ -182,8 +185,12 @@ public: bool get_option_visibility(const String &path, const String &option, const HashMap &options) const override { return true; } +#if VERSION_MINOR > 3 + Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata = nullptr) override; +#else Error import(const String &source_file, const String &save_path, const HashMap &options, List *platform_variants, List *gen_files, Variant *metadata) override; #endif +#endif #else void get_import_options(List *options, int preset) const override {} @@ -255,9 +262,12 @@ public: void get_import_options(const String &path, List *options, int preset) const override {} bool get_option_visibility(const String &path, const String &option, const HashMap &options) const override { return true; } - +#if VERSION_MINOR > 3 + Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata = nullptr) override; +#else Error import(const String &source_file, const String &save_path, const HashMap &options, List *platform_variants, List *gen_files, Variant *metadata) override; #endif +#endif #else void get_import_options(List *options, int preset) const override {} @@ -280,8 +290,12 @@ public: #else explicit SpineEditorPlugin(EditorNode *node); +#if VERSION_MINOR > 3 + String get_plugin_name() const override { return "SpineEditorPlugin"; } +#else String get_name() const override { return "SpineEditorPlugin"; } #endif +#endif }; class SpineSkeletonDataResourceInspectorPlugin : public EditorInspectorPlugin { diff --git a/spine-godot/spine_godot/SpineSprite.cpp b/spine-godot/spine_godot/SpineSprite.cpp index ecf844c9a..0e106988e 100644 --- a/spine-godot/spine_godot/SpineSprite.cpp +++ b/spine-godot/spine_godot/SpineSprite.cpp @@ -59,6 +59,7 @@ #include "core/variant/array.h" #include "scene/resources/mesh.h" #include "servers/rendering_server.h" +#include "scene/resources/canvas_item_material.h" #if VERSION_MINOR > 0 #include "editor/editor_interface.h" #endif From 88a26374fed423a4be263e2d79e80056af9e9392 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 8 Apr 2025 13:51:08 +0200 Subject: [PATCH 09/75] [godot] Fixes extension setup script, closes #2801, closes #2804 --- spine-godot/build/setup-extension.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spine-godot/build/setup-extension.sh b/spine-godot/build/setup-extension.sh index e116f49d0..29e68e83b 100755 --- a/spine-godot/build/setup-extension.sh +++ b/spine-godot/build/setup-extension.sh @@ -66,11 +66,9 @@ if [ $dev == "true" ]; then pushd godot scons target=editor dev_build=true optimize=debug --jobs=$cpus popd - cp spine_godot_extension.dev.gdextension example-v4-extension/bin/spine_godot_extension.gdextension -else - cp spine_godot_extension.gdextension example-v4-extension/bin fi +cp spine_godot_extension.gdextension example-v4-extension/bin cp -r ../spine-cpp/spine-cpp spine_godot popd From b491d8ba4d8223f08f8512d578cb49546ccc41d0 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 8 Apr 2025 13:52:01 +0200 Subject: [PATCH 10/75] [cpp] Formatting --- spine-c/spine-c/src/spine/Debug.c | 4 ++-- spine-c/spine-c/src/spine/IkConstraint.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spine-c/spine-c/src/spine/Debug.c b/spine-c/spine-c/src/spine/Debug.c index ebc4cf860..4c1284c6a 100644 --- a/spine-c/spine-c/src/spine/Debug.c +++ b/spine-c/spine-c/src/spine/Debug.c @@ -208,11 +208,11 @@ void spDebug_printTimeline(spTimeline *timeline) { case SP_TIMELINE_SEQUENCE: { spSequenceTimeline *t = (spSequenceTimeline *) timeline; _spDebug_printTimelineBase(&t->super); - } // fallthrough + }// fallthrough case SP_TIMELINE_INHERIT: { spInheritTimeline *t = (spInheritTimeline *) timeline; _spDebug_printTimelineBase(&t->super); - } // fallthrough + }// fallthrough default: { _spDebug_printTimelineBase(timeline); } diff --git a/spine-c/spine-c/src/spine/IkConstraint.c b/spine-c/spine-c/src/spine/IkConstraint.c index a036239f0..cd994e574 100644 --- a/spine-c/spine-c/src/spine/IkConstraint.c +++ b/spine-c/spine-c/src/spine/IkConstraint.c @@ -98,7 +98,7 @@ void spIkConstraint_apply1(spBone *bone, float targetX, float targetY, int /*boo pb = -sc * s * bone->skeleton->scaleX; pd = sa * s * bone->skeleton->scaleY; rotationIK += ATAN2(sc, sa) * RAD_DEG; - } // fallthrough + }// fallthrough default: { float x = targetX - p->worldX, y = targetY - p->worldY; float d = pa * pd - pb * pc; From 72381a534aa87effbbad612b9468abd861727330 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 8 Apr 2025 14:29:14 +0200 Subject: [PATCH 11/75] [cpp] Fix block allocator compression, closes #2792 --- .../spine-cpp/include/spine/BlockAllocator.h | 5 +++- spine-sdl/CMakeLists.txt | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/spine-cpp/spine-cpp/include/spine/BlockAllocator.h b/spine-cpp/spine-cpp/include/spine/BlockAllocator.h index 422d2a487..98ab1418b 100644 --- a/spine-cpp/spine-cpp/include/spine/BlockAllocator.h +++ b/spine-cpp/spine-cpp/include/spine/BlockAllocator.h @@ -77,7 +77,10 @@ namespace spine { } void compress() { - if (blocks.size() == 1) return; + if (blocks.size() == 1) { + blocks[0].allocated = 0; + return; + } int totalSize = 0; for (int i = 0, n = (int)blocks.size(); i < n; i++) { totalSize += blocks[i].size; diff --git a/spine-sdl/CMakeLists.txt b/spine-sdl/CMakeLists.txt index ad1cba9dd..f87f854ec 100644 --- a/spine-sdl/CMakeLists.txt +++ b/spine-sdl/CMakeLists.txt @@ -57,3 +57,27 @@ add_custom_command(TARGET spine-sdl-c-example PRE_BUILD add_custom_command(TARGET spine-sdl-cpp-example PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/data $/data) + +if(APPLE) + # Create the entitlements file in build directory + file(WRITE ${CMAKE_BINARY_DIR}/debug.entitlements + " + + + + com.apple.security.get-task-allow + + + ") + + # Sign the executables + add_custom_command(TARGET spine-sdl-cpp-example POST_BUILD + COMMAND codesign --force --sign - --entitlements ${CMAKE_BINARY_DIR}/debug.entitlements $ + COMMENT "Signing target with entitlements for Instruments" + ) + + add_custom_command(TARGET spine-sdl-c-example POST_BUILD + COMMAND codesign --force --sign - --entitlements ${CMAKE_BINARY_DIR}/debug.entitlements $ + COMMENT "Signing target with entitlements for Instruments" + ) +endif() \ No newline at end of file From 8e35cb8b6b64a406e909e70e77f302fbf388ebb1 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 9 Apr 2025 12:52:22 +0200 Subject: [PATCH 12/75] [flutter] Update to emscripten 4.0.6, fix build script --- spine-flutter/compile-wasm.sh | 2 +- spine-flutter/lib/assets/libspine_flutter.js | 445 ++++++------------ .../lib/assets/libspine_flutter.wasm | Bin 423529 -> 409435 bytes 3 files changed, 137 insertions(+), 310 deletions(-) diff --git a/spine-flutter/compile-wasm.sh b/spine-flutter/compile-wasm.sh index 4839ede56..9739a9ab8 100755 --- a/spine-flutter/compile-wasm.sh +++ b/spine-flutter/compile-wasm.sh @@ -12,7 +12,7 @@ em++ \ -Isrc/spine-cpp/include \ -O2 --closure 1 -fno-rtti -fno-exceptions \ -s STRICT=1 \ - -s LLD_REPORT_UNDEFINED \ + -s ERROR_ON_UNDEFINED_SYMBOLS=1 \ -s MODULARIZE=1 \ -s ALLOW_MEMORY_GROWTH=1 \ -s ALLOW_TABLE_GROWTH \ diff --git a/spine-flutter/lib/assets/libspine_flutter.js b/spine-flutter/lib/assets/libspine_flutter.js index 738f71293..a52ced31d 100644 --- a/spine-flutter/lib/assets/libspine_flutter.js +++ b/spine-flutter/lib/assets/libspine_flutter.js @@ -1,318 +1,145 @@ const module = {}; - var libspine_flutter = (() => { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined; + if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename; return ( -function(libspine_flutter) { - libspine_flutter = libspine_flutter || {}; +async function(moduleArg = {}) { + var moduleRtn; + +var a=moduleArg,b,h,k=new Promise((c,d)=>{b=c;h=d}),aa="object"==typeof window,l="undefined"!=typeof WorkerGlobalScope,m="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node&&"renderer"!=process.type,p={...a},q="",r,t; +if(m){var fs=require("fs");require("path");q=__dirname+"/";t=c=>{c=u(c)?new URL(c):c;return fs.readFileSync(c)};r=async c=>{c=u(c)?new URL(c):c;return fs.readFileSync(c,void 0)};process.argv.slice(2)}else if(aa||l)l?q=self.location.href:"undefined"!=typeof document&&document.currentScript&&(q=document.currentScript.src),_scriptName&&(q=_scriptName),q.startsWith("blob:")?q="":q=q.slice(0,q.replace(/[?#].*/,"").lastIndexOf("/")+1),l&&(t=c=>{var d=new XMLHttpRequest;d.open("GET",c,!1);d.responseType= +"arraybuffer";d.send(null);return new Uint8Array(d.response)}),r=async c=>{if(u(c))return new Promise((e,g)=>{var f=new XMLHttpRequest;f.open("GET",c,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?e(f.response):g(f.status)};f.onerror=g;f.send(null)});var d=await fetch(c,{credentials:"same-origin"});if(d.ok)return d.arrayBuffer();throw Error(d.status+" : "+d.url);};var ba=console.log.bind(console),v=console.error.bind(console);Object.assign(a,p);p=null; +var w,x=!1,z,A,B,C,D,E,F,G,u=c=>c.startsWith("file://");function H(){var c=w.buffer;a.HEAP8=z=new Int8Array(c);a.HEAP16=B=new Int16Array(c);a.HEAPU8=A=new Uint8Array(c);a.HEAPU16=new Uint16Array(c);a.HEAP32=C=new Int32Array(c);a.HEAPU32=D=new Uint32Array(c);a.HEAPF32=E=new Float32Array(c);a.HEAPF64=G=new Float64Array(c);a.HEAP64=F=new BigInt64Array(c);a.HEAPU64=new BigUint64Array(c)}var I=0,J=null; +function L(c){c="Aborted("+c+")";v(c);x=!0;c=new WebAssembly.RuntimeError(c+". Build with -sASSERTIONS for more info.");h(c);throw c;}var M;async function ca(c){try{var d=await r(c);return new Uint8Array(d)}catch{}if(t)c=t(c);else throw"both async and sync fetching of the wasm failed";return c}async function da(c,d){try{var e=await ca(c);return await WebAssembly.instantiate(e,d)}catch(g){v(`failed to asynchronously prepare wasm: ${g}`),L(g)}} +async function ea(c){var d=M;if("function"==typeof WebAssembly.instantiateStreaming&&!u(d)&&!m)try{var e=fetch(d,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(e,c)}catch(g){v(`wasm streaming compile failed: ${g}`),v("falling back to ArrayBuffer instantiation")}return da(d,c)}class fa{name="ExitStatus";constructor(c){this.message=`Program terminated with exit(${c})`;this.status=c}}a.ExitStatus=fa;a.callRuntimeCallbacks=c=>{for(;0>1];case "i32":return C[c>>2];case "i64":return F[c>>3];case "float":return E[c>>2];case "double":return G[c>>3];case "*":return D[c>>2];default:L(`invalid type for getValue: ${d}`)}}; +a.setValue=function(c,d,e="i8"){e.endsWith("*")&&(e="*");switch(e){case "i1":z[c]=d;break;case "i8":z[c]=d;break;case "i16":B[c>>1]=d;break;case "i32":C[c>>2]=d;break;case "i64":F[c>>3]=BigInt(d);break;case "float":E[c>>2]=d;break;case "double":G[c>>3]=d;break;case "*":D[c>>2]=d;break;default:L(`invalid type for setValue: ${e}`)}};a.stackRestore=c=>ha(c);a.stackSave=()=>ia();var N="undefined"!=typeof TextDecoder?new TextDecoder:void 0;a.UTF8Decoder=N; +var O=(c,d=0,e=NaN)=>{var g=d+e;for(e=d;c[e]&&!(e>=g);)++e;if(16f?g+=String.fromCharCode(f):(f-=65536,g+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else g+=String.fromCharCode(f)}return g};a.UTF8ArrayToString=O;a.UTF8ToString=(c,d)=>c?O(A,c,d):""; +var P=(c,d,e,g)=>L(`Assertion failed: ${c?O(A,c,void 0):""}, at: `+[d?d?O(A,d,void 0):"":"unknown filename",e,g?g?O(A,g,void 0):"":"unknown function"]);a.___assert_fail=P;var Q=()=>L("");a.__abort_js=Q;a.getHeapMax=()=>2147483648;a.alignMemory=(c,d)=>Math.ceil(c/d)*d;var R=c=>{c=(c-w.buffer.byteLength+65535)/65536|0;try{return w.grow(c),H(),1}catch(d){}};a.growMemory=R; +var S=c=>{var d=A.length;c>>>=0;if(2147483648=e;e*=2){var g=d*(1+.2/e);g=Math.min(g,c+100663296);if(R(Math.min(2147483648,65536*Math.ceil(Math.max(c,g)/65536))))return!0}return!1};a._emscripten_resize_heap=S;var T=[null,[],[]];a.printCharBuffers=T;var U=(c,d)=>{var e=T[c];0===d||10===d?((1===c?ba:v)(O(e)),e.length=0):e.push(d)};a.printChar=U;a.flush_NO_FILESYSTEM=()=>{T[1].length&&U(1,10);T[2].length&&U(2,10)};a.SYSCALLS={h:void 0,g(c){return c?O(A,c,void 0):""}}; +var V=(c,d,e,g)=>{for(var f=0,n=0;n>2],W=D[d+4>>2];d+=8;for(var K=0;K>2]=f;return 0};a._fd_write=V;a.ptrToString=c=>"0x"+(c>>>0).toString(16).padStart(8,"0");var X={__assert_fail:P,_abort_js:Q,emscripten_resize_heap:S,fd_write:V},Y=await (async function(){I++;var c={env:X,wasi_snapshot_preview1:X};M??=q+"libspine_flutter.wasm";try{return Y=(await ea(c)).instance.exports,w=Y.memory,H(),I--,0==I&&J&&(c=J,J=null,c()),Y}catch(d){return h(d),Promise.reject(d)}}()); +a._spine_enable_debug_extension=Y.spine_enable_debug_extension;a._spine_major_version=Y.spine_major_version;a._spine_minor_version=Y.spine_minor_version;a._spine_report_leaks=Y.spine_report_leaks;a._spine_color_get_r=Y.spine_color_get_r;a._spine_color_get_g=Y.spine_color_get_g;a._spine_color_get_b=Y.spine_color_get_b;a._spine_color_get_a=Y.spine_color_get_a;a._spine_bounds_get_x=Y.spine_bounds_get_x;a._spine_bounds_get_y=Y.spine_bounds_get_y;a._spine_bounds_get_width=Y.spine_bounds_get_width; +a._spine_bounds_get_height=Y.spine_bounds_get_height;a._spine_vector_get_x=Y.spine_vector_get_x;a._spine_vector_get_y=Y.spine_vector_get_y;a._spine_atlas_load=Y.spine_atlas_load;a._spine_atlas_load_callback=Y.spine_atlas_load_callback;a._spine_atlas_get_num_image_paths=Y.spine_atlas_get_num_image_paths;a._spine_atlas_is_pma=Y.spine_atlas_is_pma;a._spine_atlas_get_image_path=Y.spine_atlas_get_image_path;a._spine_atlas_get_error=Y.spine_atlas_get_error;a._spine_atlas_dispose=Y.spine_atlas_dispose; +a._free=Y.free;a._spine_skeleton_data_load_json=Y.spine_skeleton_data_load_json;a._spine_skeleton_data_load_binary=Y.spine_skeleton_data_load_binary;a._spine_skeleton_data_result_get_error=Y.spine_skeleton_data_result_get_error;a._spine_skeleton_data_result_get_data=Y.spine_skeleton_data_result_get_data;a._spine_skeleton_data_result_dispose=Y.spine_skeleton_data_result_dispose;a._spine_skeleton_data_find_bone=Y.spine_skeleton_data_find_bone;a._spine_skeleton_data_find_slot=Y.spine_skeleton_data_find_slot; +a._spine_skeleton_data_find_skin=Y.spine_skeleton_data_find_skin;a._spine_skeleton_data_find_event=Y.spine_skeleton_data_find_event;a._spine_skeleton_data_find_animation=Y.spine_skeleton_data_find_animation;a._spine_skeleton_data_find_ik_constraint=Y.spine_skeleton_data_find_ik_constraint;a._spine_skeleton_data_find_transform_constraint=Y.spine_skeleton_data_find_transform_constraint;a._spine_skeleton_data_find_path_constraint=Y.spine_skeleton_data_find_path_constraint; +a._spine_skeleton_data_find_physics_constraint=Y.spine_skeleton_data_find_physics_constraint;a._spine_skeleton_data_get_name=Y.spine_skeleton_data_get_name;a._spine_skeleton_data_get_num_bones=Y.spine_skeleton_data_get_num_bones;a._spine_skeleton_data_get_bones=Y.spine_skeleton_data_get_bones;a._spine_skeleton_data_get_num_slots=Y.spine_skeleton_data_get_num_slots;a._spine_skeleton_data_get_slots=Y.spine_skeleton_data_get_slots;a._spine_skeleton_data_get_num_skins=Y.spine_skeleton_data_get_num_skins; +a._spine_skeleton_data_get_skins=Y.spine_skeleton_data_get_skins;a._spine_skeleton_data_get_default_skin=Y.spine_skeleton_data_get_default_skin;a._spine_skeleton_data_set_default_skin=Y.spine_skeleton_data_set_default_skin;a._spine_skeleton_data_get_num_events=Y.spine_skeleton_data_get_num_events;a._spine_skeleton_data_get_events=Y.spine_skeleton_data_get_events;a._spine_skeleton_data_get_num_animations=Y.spine_skeleton_data_get_num_animations;a._spine_skeleton_data_get_animations=Y.spine_skeleton_data_get_animations; +a._spine_skeleton_data_get_num_ik_constraints=Y.spine_skeleton_data_get_num_ik_constraints;a._spine_skeleton_data_get_ik_constraints=Y.spine_skeleton_data_get_ik_constraints;a._spine_skeleton_data_get_num_transform_constraints=Y.spine_skeleton_data_get_num_transform_constraints;a._spine_skeleton_data_get_transform_constraints=Y.spine_skeleton_data_get_transform_constraints;a._spine_skeleton_data_get_num_path_constraints=Y.spine_skeleton_data_get_num_path_constraints; +a._spine_skeleton_data_get_path_constraints=Y.spine_skeleton_data_get_path_constraints;a._spine_skeleton_data_get_num_physics_constraints=Y.spine_skeleton_data_get_num_physics_constraints;a._spine_skeleton_data_get_physics_constraints=Y.spine_skeleton_data_get_physics_constraints;a._spine_skeleton_data_get_x=Y.spine_skeleton_data_get_x;a._spine_skeleton_data_set_x=Y.spine_skeleton_data_set_x;a._spine_skeleton_data_get_y=Y.spine_skeleton_data_get_y;a._spine_skeleton_data_set_y=Y.spine_skeleton_data_set_y; +a._spine_skeleton_data_get_width=Y.spine_skeleton_data_get_width;a._spine_skeleton_data_set_width=Y.spine_skeleton_data_set_width;a._spine_skeleton_data_get_height=Y.spine_skeleton_data_get_height;a._spine_skeleton_data_set_height=Y.spine_skeleton_data_set_height;a._spine_skeleton_data_get_version=Y.spine_skeleton_data_get_version;a._spine_skeleton_data_get_hash=Y.spine_skeleton_data_get_hash;a._spine_skeleton_data_get_images_path=Y.spine_skeleton_data_get_images_path; +a._spine_skeleton_data_get_audio_path=Y.spine_skeleton_data_get_audio_path;a._spine_skeleton_data_get_fps=Y.spine_skeleton_data_get_fps;a._spine_skeleton_data_get_reference_scale=Y.spine_skeleton_data_get_reference_scale;a._spine_skeleton_data_dispose=Y.spine_skeleton_data_dispose;a._spine_skeleton_drawable_create=Y.spine_skeleton_drawable_create;a._spine_skeleton_drawable_dispose=Y.spine_skeleton_drawable_dispose;a._spine_skeleton_drawable_render=Y.spine_skeleton_drawable_render; +a._spine_skeleton_drawable_get_skeleton=Y.spine_skeleton_drawable_get_skeleton;a._spine_skeleton_drawable_get_animation_state=Y.spine_skeleton_drawable_get_animation_state;a._spine_skeleton_drawable_get_animation_state_data=Y.spine_skeleton_drawable_get_animation_state_data;a._spine_skeleton_drawable_get_animation_state_events=Y.spine_skeleton_drawable_get_animation_state_events;a._spine_render_command_get_positions=Y.spine_render_command_get_positions;a._spine_render_command_get_uvs=Y.spine_render_command_get_uvs; +a._spine_render_command_get_colors=Y.spine_render_command_get_colors;a._spine_render_command_get_dark_colors=Y.spine_render_command_get_dark_colors;a._spine_render_command_get_num_vertices=Y.spine_render_command_get_num_vertices;a._spine_render_command_get_indices=Y.spine_render_command_get_indices;a._spine_render_command_get_num_indices=Y.spine_render_command_get_num_indices;a._spine_render_command_get_atlas_page=Y.spine_render_command_get_atlas_page;a._spine_render_command_get_blend_mode=Y.spine_render_command_get_blend_mode; +a._spine_render_command_get_next=Y.spine_render_command_get_next;a._spine_animation_get_name=Y.spine_animation_get_name;a._spine_animation_get_duration=Y.spine_animation_get_duration;a._spine_animation_state_data_get_skeleton_data=Y.spine_animation_state_data_get_skeleton_data;a._spine_animation_state_data_get_default_mix=Y.spine_animation_state_data_get_default_mix;a._spine_animation_state_data_set_default_mix=Y.spine_animation_state_data_set_default_mix;a._spine_animation_state_data_set_mix=Y.spine_animation_state_data_set_mix; +a._spine_animation_state_data_get_mix=Y.spine_animation_state_data_get_mix;a._spine_animation_state_data_set_mix_by_name=Y.spine_animation_state_data_set_mix_by_name;a._spine_animation_state_data_get_mix_by_name=Y.spine_animation_state_data_get_mix_by_name;a._spine_animation_state_data_clear=Y.spine_animation_state_data_clear;a._spine_animation_state_update=Y.spine_animation_state_update;a._spine_animation_state_dispose_track_entry=Y.spine_animation_state_dispose_track_entry; +a._spine_animation_state_apply=Y.spine_animation_state_apply;a._spine_animation_state_clear_tracks=Y.spine_animation_state_clear_tracks;a._spine_animation_state_get_num_tracks=Y.spine_animation_state_get_num_tracks;a._spine_animation_state_clear_track=Y.spine_animation_state_clear_track;a._spine_animation_state_set_animation_by_name=Y.spine_animation_state_set_animation_by_name;a._spine_animation_state_set_animation=Y.spine_animation_state_set_animation; +a._spine_animation_state_add_animation_by_name=Y.spine_animation_state_add_animation_by_name;a._spine_animation_state_add_animation=Y.spine_animation_state_add_animation;a._spine_animation_state_set_empty_animation=Y.spine_animation_state_set_empty_animation;a._spine_animation_state_add_empty_animation=Y.spine_animation_state_add_empty_animation;a._spine_animation_state_set_empty_animations=Y.spine_animation_state_set_empty_animations;a._spine_animation_state_get_current=Y.spine_animation_state_get_current; +a._spine_animation_state_get_data=Y.spine_animation_state_get_data;a._spine_animation_state_get_time_scale=Y.spine_animation_state_get_time_scale;a._spine_animation_state_set_time_scale=Y.spine_animation_state_set_time_scale;a._spine_animation_state_events_get_num_events=Y.spine_animation_state_events_get_num_events;a._spine_animation_state_events_get_event_type=Y.spine_animation_state_events_get_event_type;a._spine_animation_state_events_get_track_entry=Y.spine_animation_state_events_get_track_entry; +a._spine_animation_state_events_get_event=Y.spine_animation_state_events_get_event;a._spine_animation_state_events_reset=Y.spine_animation_state_events_reset;a._spine_track_entry_get_track_index=Y.spine_track_entry_get_track_index;a._spine_track_entry_get_animation=Y.spine_track_entry_get_animation;a._spine_track_entry_get_previous=Y.spine_track_entry_get_previous;a._spine_track_entry_get_loop=Y.spine_track_entry_get_loop;a._spine_track_entry_set_loop=Y.spine_track_entry_set_loop; +a._spine_track_entry_get_hold_previous=Y.spine_track_entry_get_hold_previous;a._spine_track_entry_set_hold_previous=Y.spine_track_entry_set_hold_previous;a._spine_track_entry_get_reverse=Y.spine_track_entry_get_reverse;a._spine_track_entry_set_reverse=Y.spine_track_entry_set_reverse;a._spine_track_entry_get_shortest_rotation=Y.spine_track_entry_get_shortest_rotation;a._spine_track_entry_set_shortest_rotation=Y.spine_track_entry_set_shortest_rotation;a._spine_track_entry_get_delay=Y.spine_track_entry_get_delay; +a._spine_track_entry_set_delay=Y.spine_track_entry_set_delay;a._spine_track_entry_get_track_time=Y.spine_track_entry_get_track_time;a._spine_track_entry_set_track_time=Y.spine_track_entry_set_track_time;a._spine_track_entry_get_track_end=Y.spine_track_entry_get_track_end;a._spine_track_entry_set_track_end=Y.spine_track_entry_set_track_end;a._spine_track_entry_get_animation_start=Y.spine_track_entry_get_animation_start;a._spine_track_entry_set_animation_start=Y.spine_track_entry_set_animation_start; +a._spine_track_entry_get_animation_end=Y.spine_track_entry_get_animation_end;a._spine_track_entry_set_animation_end=Y.spine_track_entry_set_animation_end;a._spine_track_entry_get_animation_last=Y.spine_track_entry_get_animation_last;a._spine_track_entry_set_animation_last=Y.spine_track_entry_set_animation_last;a._spine_track_entry_get_animation_time=Y.spine_track_entry_get_animation_time;a._spine_track_entry_get_time_scale=Y.spine_track_entry_get_time_scale;a._spine_track_entry_set_time_scale=Y.spine_track_entry_set_time_scale; +a._spine_track_entry_get_alpha=Y.spine_track_entry_get_alpha;a._spine_track_entry_set_alpha=Y.spine_track_entry_set_alpha;a._spine_track_entry_get_event_threshold=Y.spine_track_entry_get_event_threshold;a._spine_track_entry_set_event_threshold=Y.spine_track_entry_set_event_threshold;a._spine_track_entry_get_alpha_attachment_threshold=Y.spine_track_entry_get_alpha_attachment_threshold;a._spine_track_entry_set_alpha_attachment_threshold=Y.spine_track_entry_set_alpha_attachment_threshold; +a._spine_track_entry_get_mix_attachment_threshold=Y.spine_track_entry_get_mix_attachment_threshold;a._spine_track_entry_set_mix_attachment_threshold=Y.spine_track_entry_set_mix_attachment_threshold;a._spine_track_entry_get_mix_draw_order_threshold=Y.spine_track_entry_get_mix_draw_order_threshold;a._spine_track_entry_set_mix_draw_order_threshold=Y.spine_track_entry_set_mix_draw_order_threshold;a._spine_track_entry_get_next=Y.spine_track_entry_get_next;a._spine_track_entry_is_complete=Y.spine_track_entry_is_complete; +a._spine_track_entry_get_mix_time=Y.spine_track_entry_get_mix_time;a._spine_track_entry_set_mix_time=Y.spine_track_entry_set_mix_time;a._spine_track_entry_get_mix_duration=Y.spine_track_entry_get_mix_duration;a._spine_track_entry_set_mix_duration=Y.spine_track_entry_set_mix_duration;a._spine_track_entry_get_mix_blend=Y.spine_track_entry_get_mix_blend;a._spine_track_entry_set_mix_blend=Y.spine_track_entry_set_mix_blend;a._spine_track_entry_get_mixing_from=Y.spine_track_entry_get_mixing_from; +a._spine_track_entry_get_mixing_to=Y.spine_track_entry_get_mixing_to;a._spine_track_entry_reset_rotation_directions=Y.spine_track_entry_reset_rotation_directions;a._spine_track_entry_get_track_complete=Y.spine_track_entry_get_track_complete;a._spine_track_entry_was_applied=Y.spine_track_entry_was_applied;a._spine_track_entry_is_next_ready=Y.spine_track_entry_is_next_ready;a._spine_skeleton_update_cache=Y.spine_skeleton_update_cache;a._spine_skeleton_update_world_transform=Y.spine_skeleton_update_world_transform; +a._spine_skeleton_update_world_transform_bone=Y.spine_skeleton_update_world_transform_bone;a._spine_skeleton_set_to_setup_pose=Y.spine_skeleton_set_to_setup_pose;a._spine_skeleton_set_bones_to_setup_pose=Y.spine_skeleton_set_bones_to_setup_pose;a._spine_skeleton_set_slots_to_setup_pose=Y.spine_skeleton_set_slots_to_setup_pose;a._spine_skeleton_find_bone=Y.spine_skeleton_find_bone;a._spine_skeleton_find_slot=Y.spine_skeleton_find_slot;a._spine_skeleton_set_skin_by_name=Y.spine_skeleton_set_skin_by_name; +a._spine_skeleton_set_skin=Y.spine_skeleton_set_skin;a._spine_skeleton_get_attachment_by_name=Y.spine_skeleton_get_attachment_by_name;a._spine_skeleton_get_attachment=Y.spine_skeleton_get_attachment;a._spine_skeleton_set_attachment=Y.spine_skeleton_set_attachment;a._spine_skeleton_find_ik_constraint=Y.spine_skeleton_find_ik_constraint;a._spine_skeleton_find_transform_constraint=Y.spine_skeleton_find_transform_constraint;a._spine_skeleton_find_path_constraint=Y.spine_skeleton_find_path_constraint; +a._spine_skeleton_find_physics_constraint=Y.spine_skeleton_find_physics_constraint;a._spine_skeleton_get_bounds=Y.spine_skeleton_get_bounds;a._spine_skeleton_get_root_bone=Y.spine_skeleton_get_root_bone;a._spine_skeleton_get_data=Y.spine_skeleton_get_data;a._spine_skeleton_get_num_bones=Y.spine_skeleton_get_num_bones;a._spine_skeleton_get_bones=Y.spine_skeleton_get_bones;a._spine_skeleton_get_num_slots=Y.spine_skeleton_get_num_slots;a._spine_skeleton_get_slots=Y.spine_skeleton_get_slots; +a._spine_skeleton_get_num_draw_order=Y.spine_skeleton_get_num_draw_order;a._spine_skeleton_get_draw_order=Y.spine_skeleton_get_draw_order;a._spine_skeleton_get_num_ik_constraints=Y.spine_skeleton_get_num_ik_constraints;a._spine_skeleton_get_ik_constraints=Y.spine_skeleton_get_ik_constraints;a._spine_skeleton_get_num_transform_constraints=Y.spine_skeleton_get_num_transform_constraints;a._spine_skeleton_get_transform_constraints=Y.spine_skeleton_get_transform_constraints; +a._spine_skeleton_get_num_path_constraints=Y.spine_skeleton_get_num_path_constraints;a._spine_skeleton_get_path_constraints=Y.spine_skeleton_get_path_constraints;a._spine_skeleton_get_num_physics_constraints=Y.spine_skeleton_get_num_physics_constraints;a._spine_skeleton_get_physics_constraints=Y.spine_skeleton_get_physics_constraints;a._spine_skeleton_get_skin=Y.spine_skeleton_get_skin;a._spine_skeleton_get_color=Y.spine_skeleton_get_color;a._spine_skeleton_set_color=Y.spine_skeleton_set_color; +a._spine_skeleton_set_position=Y.spine_skeleton_set_position;a._spine_skeleton_get_x=Y.spine_skeleton_get_x;a._spine_skeleton_set_x=Y.spine_skeleton_set_x;a._spine_skeleton_get_y=Y.spine_skeleton_get_y;a._spine_skeleton_set_y=Y.spine_skeleton_set_y;a._spine_skeleton_set_scale=Y.spine_skeleton_set_scale;a._spine_skeleton_get_scale_x=Y.spine_skeleton_get_scale_x;a._spine_skeleton_set_scale_x=Y.spine_skeleton_set_scale_x;a._spine_skeleton_get_scale_y=Y.spine_skeleton_get_scale_y; +a._spine_skeleton_set_scale_y=Y.spine_skeleton_set_scale_y;a._spine_skeleton_get_time=Y.spine_skeleton_get_time;a._spine_skeleton_set_time=Y.spine_skeleton_set_time;a._spine_skeleton_update=Y.spine_skeleton_update;a._spine_event_data_get_name=Y.spine_event_data_get_name;a._spine_event_data_get_int_value=Y.spine_event_data_get_int_value;a._spine_event_data_set_int_value=Y.spine_event_data_set_int_value;a._spine_event_data_get_float_value=Y.spine_event_data_get_float_value; +a._spine_event_data_set_float_value=Y.spine_event_data_set_float_value;a._spine_event_data_get_string_value=Y.spine_event_data_get_string_value;a._spine_event_data_set_string_value=Y.spine_event_data_set_string_value;a._spine_event_data_get_audio_path=Y.spine_event_data_get_audio_path;a._spine_event_data_get_volume=Y.spine_event_data_get_volume;a._spine_event_data_set_volume=Y.spine_event_data_set_volume;a._spine_event_data_get_balance=Y.spine_event_data_get_balance; +a._spine_event_data_set_balance=Y.spine_event_data_set_balance;a._spine_event_get_data=Y.spine_event_get_data;a._spine_event_get_time=Y.spine_event_get_time;a._spine_event_get_int_value=Y.spine_event_get_int_value;a._spine_event_set_int_value=Y.spine_event_set_int_value;a._spine_event_get_float_value=Y.spine_event_get_float_value;a._spine_event_set_float_value=Y.spine_event_set_float_value;a._spine_event_get_string_value=Y.spine_event_get_string_value;a._spine_event_set_string_value=Y.spine_event_set_string_value; +a._spine_event_get_volume=Y.spine_event_get_volume;a._spine_event_set_volume=Y.spine_event_set_volume;a._spine_event_get_balance=Y.spine_event_get_balance;a._spine_event_set_balance=Y.spine_event_set_balance;a._spine_slot_data_get_index=Y.spine_slot_data_get_index;a._spine_slot_data_get_name=Y.spine_slot_data_get_name;a._spine_slot_data_get_bone_data=Y.spine_slot_data_get_bone_data;a._spine_slot_data_get_color=Y.spine_slot_data_get_color;a._spine_slot_data_set_color=Y.spine_slot_data_set_color; +a._spine_slot_data_get_dark_color=Y.spine_slot_data_get_dark_color;a._spine_slot_data_set_dark_color=Y.spine_slot_data_set_dark_color;a._spine_slot_data_get_has_dark_color=Y.spine_slot_data_get_has_dark_color;a._spine_slot_data_set_has_dark_color=Y.spine_slot_data_set_has_dark_color;a._spine_slot_data_get_attachment_name=Y.spine_slot_data_get_attachment_name;a._spine_slot_data_set_attachment_name=Y.spine_slot_data_set_attachment_name;a._spine_slot_data_get_blend_mode=Y.spine_slot_data_get_blend_mode; +a._spine_slot_data_set_blend_mode=Y.spine_slot_data_set_blend_mode;a._spine_slot_data_is_visible=Y.spine_slot_data_is_visible;a._spine_slot_data_set_visible=Y.spine_slot_data_set_visible;a._spine_slot_set_to_setup_pose=Y.spine_slot_set_to_setup_pose;a._spine_slot_get_data=Y.spine_slot_get_data;a._spine_slot_get_bone=Y.spine_slot_get_bone;a._spine_slot_get_skeleton=Y.spine_slot_get_skeleton;a._spine_slot_get_color=Y.spine_slot_get_color;a._spine_slot_set_color=Y.spine_slot_set_color; +a._spine_slot_get_dark_color=Y.spine_slot_get_dark_color;a._spine_slot_set_dark_color=Y.spine_slot_set_dark_color;a._spine_slot_has_dark_color=Y.spine_slot_has_dark_color;a._spine_slot_get_attachment=Y.spine_slot_get_attachment;a._spine_slot_set_attachment=Y.spine_slot_set_attachment;a._spine_slot_get_sequence_index=Y.spine_slot_get_sequence_index;a._spine_slot_set_sequence_index=Y.spine_slot_set_sequence_index;a._spine_bone_data_get_index=Y.spine_bone_data_get_index;a._spine_bone_data_get_name=Y.spine_bone_data_get_name; +a._spine_bone_data_get_parent=Y.spine_bone_data_get_parent;a._spine_bone_data_get_length=Y.spine_bone_data_get_length;a._spine_bone_data_set_length=Y.spine_bone_data_set_length;a._spine_bone_data_get_x=Y.spine_bone_data_get_x;a._spine_bone_data_set_x=Y.spine_bone_data_set_x;a._spine_bone_data_get_y=Y.spine_bone_data_get_y;a._spine_bone_data_set_y=Y.spine_bone_data_set_y;a._spine_bone_data_get_rotation=Y.spine_bone_data_get_rotation;a._spine_bone_data_set_rotation=Y.spine_bone_data_set_rotation; +a._spine_bone_data_get_scale_x=Y.spine_bone_data_get_scale_x;a._spine_bone_data_set_scale_x=Y.spine_bone_data_set_scale_x;a._spine_bone_data_get_scale_y=Y.spine_bone_data_get_scale_y;a._spine_bone_data_set_scale_y=Y.spine_bone_data_set_scale_y;a._spine_bone_data_get_shear_x=Y.spine_bone_data_get_shear_x;a._spine_bone_data_set_shear_x=Y.spine_bone_data_set_shear_x;a._spine_bone_data_get_shear_y=Y.spine_bone_data_get_shear_y;a._spine_bone_data_set_shear_y=Y.spine_bone_data_set_shear_y; +a._spine_bone_data_get_inherit=Y.spine_bone_data_get_inherit;a._spine_bone_data_set_inherit=Y.spine_bone_data_set_inherit;a._spine_bone_data_get_is_skin_required=Y.spine_bone_data_get_is_skin_required;a._spine_bone_data_set_is_skin_required=Y.spine_bone_data_set_is_skin_required;a._spine_bone_data_get_color=Y.spine_bone_data_get_color;a._spine_bone_data_set_color=Y.spine_bone_data_set_color;a._spine_bone_data_is_visible=Y.spine_bone_data_is_visible;a._spine_bone_data_set_visible=Y.spine_bone_data_set_visible; +a._spine_bone_set_is_y_down=Y.spine_bone_set_is_y_down;a._spine_bone_get_is_y_down=Y.spine_bone_get_is_y_down;a._spine_bone_update=Y.spine_bone_update;a._spine_bone_update_world_transform=Y.spine_bone_update_world_transform;a._spine_bone_update_world_transform_with=Y.spine_bone_update_world_transform_with;a._spine_bone_update_applied_transform=Y.spine_bone_update_applied_transform;a._spine_bone_set_to_setup_pose=Y.spine_bone_set_to_setup_pose;a._spine_bone_world_to_local=Y.spine_bone_world_to_local; +a._spine_bone_world_to_parent=Y.spine_bone_world_to_parent;a._spine_bone_local_to_world=Y.spine_bone_local_to_world;a._spine_bone_parent_to_world=Y.spine_bone_parent_to_world;a._spine_bone_world_to_local_rotation=Y.spine_bone_world_to_local_rotation;a._spine_bone_local_to_world_rotation=Y.spine_bone_local_to_world_rotation;a._spine_bone_rotate_world=Y.spine_bone_rotate_world;a._spine_bone_get_world_to_local_rotation_x=Y.spine_bone_get_world_to_local_rotation_x; +a._spine_bone_get_world_to_local_rotation_y=Y.spine_bone_get_world_to_local_rotation_y;a._spine_bone_get_data=Y.spine_bone_get_data;a._spine_bone_get_skeleton=Y.spine_bone_get_skeleton;a._spine_bone_get_parent=Y.spine_bone_get_parent;a._spine_bone_get_num_children=Y.spine_bone_get_num_children;a._spine_bone_get_children=Y.spine_bone_get_children;a._spine_bone_get_x=Y.spine_bone_get_x;a._spine_bone_set_x=Y.spine_bone_set_x;a._spine_bone_get_y=Y.spine_bone_get_y;a._spine_bone_set_y=Y.spine_bone_set_y; +a._spine_bone_get_rotation=Y.spine_bone_get_rotation;a._spine_bone_set_rotation=Y.spine_bone_set_rotation;a._spine_bone_get_scale_x=Y.spine_bone_get_scale_x;a._spine_bone_set_scale_x=Y.spine_bone_set_scale_x;a._spine_bone_get_scale_y=Y.spine_bone_get_scale_y;a._spine_bone_set_scale_y=Y.spine_bone_set_scale_y;a._spine_bone_get_shear_x=Y.spine_bone_get_shear_x;a._spine_bone_set_shear_x=Y.spine_bone_set_shear_x;a._spine_bone_get_shear_y=Y.spine_bone_get_shear_y;a._spine_bone_set_shear_y=Y.spine_bone_set_shear_y; +a._spine_bone_get_applied_rotation=Y.spine_bone_get_applied_rotation;a._spine_bone_set_applied_rotation=Y.spine_bone_set_applied_rotation;a._spine_bone_get_a_x=Y.spine_bone_get_a_x;a._spine_bone_set_a_x=Y.spine_bone_set_a_x;a._spine_bone_get_a_y=Y.spine_bone_get_a_y;a._spine_bone_set_a_y=Y.spine_bone_set_a_y;a._spine_bone_get_a_scale_x=Y.spine_bone_get_a_scale_x;a._spine_bone_set_a_scale_x=Y.spine_bone_set_a_scale_x;a._spine_bone_get_a_scale_y=Y.spine_bone_get_a_scale_y; +a._spine_bone_set_a_scale_y=Y.spine_bone_set_a_scale_y;a._spine_bone_get_a_shear_x=Y.spine_bone_get_a_shear_x;a._spine_bone_set_a_shear_x=Y.spine_bone_set_a_shear_x;a._spine_bone_get_a_shear_y=Y.spine_bone_get_a_shear_y;a._spine_bone_set_a_shear_y=Y.spine_bone_set_a_shear_y;a._spine_bone_get_a=Y.spine_bone_get_a;a._spine_bone_set_a=Y.spine_bone_set_a;a._spine_bone_get_b=Y.spine_bone_get_b;a._spine_bone_set_b=Y.spine_bone_set_b;a._spine_bone_get_c=Y.spine_bone_get_c;a._spine_bone_set_c=Y.spine_bone_set_c; +a._spine_bone_get_d=Y.spine_bone_get_d;a._spine_bone_set_d=Y.spine_bone_set_d;a._spine_bone_get_world_x=Y.spine_bone_get_world_x;a._spine_bone_set_world_x=Y.spine_bone_set_world_x;a._spine_bone_get_world_y=Y.spine_bone_get_world_y;a._spine_bone_set_world_y=Y.spine_bone_set_world_y;a._spine_bone_get_world_rotation_x=Y.spine_bone_get_world_rotation_x;a._spine_bone_get_world_rotation_y=Y.spine_bone_get_world_rotation_y;a._spine_bone_get_world_scale_x=Y.spine_bone_get_world_scale_x; +a._spine_bone_get_world_scale_y=Y.spine_bone_get_world_scale_y;a._spine_bone_get_is_active=Y.spine_bone_get_is_active;a._spine_bone_set_is_active=Y.spine_bone_set_is_active;a._spine_bone_get_inherit=Y.spine_bone_get_inherit;a._spine_bone_set_inherit=Y.spine_bone_set_inherit;a._spine_attachment_get_name=Y.spine_attachment_get_name;a._spine_attachment_get_type=Y.spine_attachment_get_type;a._spine_attachment_copy=Y.spine_attachment_copy;a._spine_attachment_cast_to_bounding_box_attachment=Y.spine_attachment_cast_to_bounding_box_attachment; +a._spine_attachment_dispose=Y.spine_attachment_dispose;a._spine_point_attachment_compute_world_position=Y.spine_point_attachment_compute_world_position;a._spine_point_attachment_compute_world_rotation=Y.spine_point_attachment_compute_world_rotation;a._spine_point_attachment_get_x=Y.spine_point_attachment_get_x;a._spine_point_attachment_set_x=Y.spine_point_attachment_set_x;a._spine_point_attachment_get_y=Y.spine_point_attachment_get_y;a._spine_point_attachment_set_y=Y.spine_point_attachment_set_y; +a._spine_point_attachment_get_rotation=Y.spine_point_attachment_get_rotation;a._spine_point_attachment_set_rotation=Y.spine_point_attachment_set_rotation;a._spine_point_attachment_get_color=Y.spine_point_attachment_get_color;a._spine_point_attachment_set_color=Y.spine_point_attachment_set_color;a._spine_region_attachment_update_region=Y.spine_region_attachment_update_region;a._spine_region_attachment_compute_world_vertices=Y.spine_region_attachment_compute_world_vertices; +a._spine_region_attachment_get_x=Y.spine_region_attachment_get_x;a._spine_region_attachment_set_x=Y.spine_region_attachment_set_x;a._spine_region_attachment_get_y=Y.spine_region_attachment_get_y;a._spine_region_attachment_set_y=Y.spine_region_attachment_set_y;a._spine_region_attachment_get_rotation=Y.spine_region_attachment_get_rotation;a._spine_region_attachment_set_rotation=Y.spine_region_attachment_set_rotation;a._spine_region_attachment_get_scale_x=Y.spine_region_attachment_get_scale_x; +a._spine_region_attachment_set_scale_x=Y.spine_region_attachment_set_scale_x;a._spine_region_attachment_get_scale_y=Y.spine_region_attachment_get_scale_y;a._spine_region_attachment_set_scale_y=Y.spine_region_attachment_set_scale_y;a._spine_region_attachment_get_width=Y.spine_region_attachment_get_width;a._spine_region_attachment_set_width=Y.spine_region_attachment_set_width;a._spine_region_attachment_get_height=Y.spine_region_attachment_get_height;a._spine_region_attachment_set_height=Y.spine_region_attachment_set_height; +a._spine_region_attachment_get_color=Y.spine_region_attachment_get_color;a._spine_region_attachment_set_color=Y.spine_region_attachment_set_color;a._spine_region_attachment_get_path=Y.spine_region_attachment_get_path;a._spine_region_attachment_get_region=Y.spine_region_attachment_get_region;a._spine_region_attachment_get_sequence=Y.spine_region_attachment_get_sequence;a._spine_region_attachment_get_num_offset=Y.spine_region_attachment_get_num_offset;a._spine_region_attachment_get_offset=Y.spine_region_attachment_get_offset; +a._spine_region_attachment_get_num_uvs=Y.spine_region_attachment_get_num_uvs;a._spine_region_attachment_get_uvs=Y.spine_region_attachment_get_uvs;a._spine_vertex_attachment_get_world_vertices_length=Y.spine_vertex_attachment_get_world_vertices_length;a._spine_vertex_attachment_compute_world_vertices=Y.spine_vertex_attachment_compute_world_vertices;a._spine_vertex_attachment_get_num_bones=Y.spine_vertex_attachment_get_num_bones;a._spine_vertex_attachment_get_bones=Y.spine_vertex_attachment_get_bones; +a._spine_vertex_attachment_get_num_vertices=Y.spine_vertex_attachment_get_num_vertices;a._spine_vertex_attachment_get_vertices=Y.spine_vertex_attachment_get_vertices;a._spine_vertex_attachment_get_timeline_attachment=Y.spine_vertex_attachment_get_timeline_attachment;a._spine_vertex_attachment_set_timeline_attachment=Y.spine_vertex_attachment_set_timeline_attachment;a._spine_mesh_attachment_update_region=Y.spine_mesh_attachment_update_region;a._spine_mesh_attachment_get_hull_length=Y.spine_mesh_attachment_get_hull_length; +a._spine_mesh_attachment_set_hull_length=Y.spine_mesh_attachment_set_hull_length;a._spine_mesh_attachment_get_num_region_uvs=Y.spine_mesh_attachment_get_num_region_uvs;a._spine_mesh_attachment_get_region_uvs=Y.spine_mesh_attachment_get_region_uvs;a._spine_mesh_attachment_get_num_uvs=Y.spine_mesh_attachment_get_num_uvs;a._spine_mesh_attachment_get_uvs=Y.spine_mesh_attachment_get_uvs;a._spine_mesh_attachment_get_num_triangles=Y.spine_mesh_attachment_get_num_triangles; +a._spine_mesh_attachment_get_triangles=Y.spine_mesh_attachment_get_triangles;a._spine_mesh_attachment_get_color=Y.spine_mesh_attachment_get_color;a._spine_mesh_attachment_set_color=Y.spine_mesh_attachment_set_color;a._spine_mesh_attachment_get_path=Y.spine_mesh_attachment_get_path;a._spine_mesh_attachment_get_region=Y.spine_mesh_attachment_get_region;a._spine_mesh_attachment_get_sequence=Y.spine_mesh_attachment_get_sequence;a._spine_mesh_attachment_get_parent_mesh=Y.spine_mesh_attachment_get_parent_mesh; +a._spine_mesh_attachment_set_parent_mesh=Y.spine_mesh_attachment_set_parent_mesh;a._spine_mesh_attachment_get_num_edges=Y.spine_mesh_attachment_get_num_edges;a._spine_mesh_attachment_get_edges=Y.spine_mesh_attachment_get_edges;a._spine_mesh_attachment_get_width=Y.spine_mesh_attachment_get_width;a._spine_mesh_attachment_set_width=Y.spine_mesh_attachment_set_width;a._spine_mesh_attachment_get_height=Y.spine_mesh_attachment_get_height;a._spine_mesh_attachment_set_height=Y.spine_mesh_attachment_set_height; +a._spine_clipping_attachment_get_end_slot=Y.spine_clipping_attachment_get_end_slot;a._spine_clipping_attachment_set_end_slot=Y.spine_clipping_attachment_set_end_slot;a._spine_clipping_attachment_get_color=Y.spine_clipping_attachment_get_color;a._spine_clipping_attachment_set_color=Y.spine_clipping_attachment_set_color;a._spine_bounding_box_attachment_get_color=Y.spine_bounding_box_attachment_get_color;a._spine_bounding_box_attachment_set_color=Y.spine_bounding_box_attachment_set_color; +a._spine_path_attachment_get_num_lengths=Y.spine_path_attachment_get_num_lengths;a._spine_path_attachment_get_lengths=Y.spine_path_attachment_get_lengths;a._spine_path_attachment_get_is_closed=Y.spine_path_attachment_get_is_closed;a._spine_path_attachment_set_is_closed=Y.spine_path_attachment_set_is_closed;a._spine_path_attachment_get_is_constant_speed=Y.spine_path_attachment_get_is_constant_speed;a._spine_path_attachment_set_is_constant_speed=Y.spine_path_attachment_set_is_constant_speed; +a._spine_path_attachment_get_color=Y.spine_path_attachment_get_color;a._spine_path_attachment_set_color=Y.spine_path_attachment_set_color;a._spine_skin_set_attachment=Y.spine_skin_set_attachment;a._spine_skin_get_attachment=Y.spine_skin_get_attachment;a._spine_skin_remove_attachment=Y.spine_skin_remove_attachment;a._spine_skin_get_name=Y.spine_skin_get_name;a._spine_skin_add_skin=Y.spine_skin_add_skin;a._spine_skin_copy_skin=Y.spine_skin_copy_skin;a._spine_skin_get_entries=Y.spine_skin_get_entries; +a._spine_skin_entries_get_num_entries=Y.spine_skin_entries_get_num_entries;a._spine_skin_entries_get_entry=Y.spine_skin_entries_get_entry;a._spine_skin_entries_dispose=Y.spine_skin_entries_dispose;a._spine_skin_entry_get_slot_index=Y.spine_skin_entry_get_slot_index;a._spine_skin_entry_get_name=Y.spine_skin_entry_get_name;a._spine_skin_entry_get_attachment=Y.spine_skin_entry_get_attachment;a._spine_skin_get_num_bones=Y.spine_skin_get_num_bones;a._spine_skin_get_bones=Y.spine_skin_get_bones; +a._spine_skin_get_num_constraints=Y.spine_skin_get_num_constraints;a._spine_skin_get_constraints=Y.spine_skin_get_constraints;a._spine_skin_create=Y.spine_skin_create;a._spine_skin_dispose=Y.spine_skin_dispose;a._spine_constraint_data_get_type=Y.spine_constraint_data_get_type;a._spine_constraint_data_get_name=Y.spine_constraint_data_get_name;a._spine_constraint_data_get_order=Y.spine_constraint_data_get_order;a._spine_constraint_data_set_order=Y.spine_constraint_data_set_order; +a._spine_constraint_data_get_is_skin_required=Y.spine_constraint_data_get_is_skin_required;a._spine_constraint_data_set_is_skin_required=Y.spine_constraint_data_set_is_skin_required;a._spine_ik_constraint_data_get_num_bones=Y.spine_ik_constraint_data_get_num_bones;a._spine_ik_constraint_data_get_bones=Y.spine_ik_constraint_data_get_bones;a._spine_ik_constraint_data_get_target=Y.spine_ik_constraint_data_get_target;a._spine_ik_constraint_data_set_target=Y.spine_ik_constraint_data_set_target; +a._spine_ik_constraint_data_get_bend_direction=Y.spine_ik_constraint_data_get_bend_direction;a._spine_ik_constraint_data_set_bend_direction=Y.spine_ik_constraint_data_set_bend_direction;a._spine_ik_constraint_data_get_compress=Y.spine_ik_constraint_data_get_compress;a._spine_ik_constraint_data_set_compress=Y.spine_ik_constraint_data_set_compress;a._spine_ik_constraint_data_get_stretch=Y.spine_ik_constraint_data_get_stretch;a._spine_ik_constraint_data_set_stretch=Y.spine_ik_constraint_data_set_stretch; +a._spine_ik_constraint_data_get_uniform=Y.spine_ik_constraint_data_get_uniform;a._spine_ik_constraint_data_set_uniform=Y.spine_ik_constraint_data_set_uniform;a._spine_ik_constraint_data_get_mix=Y.spine_ik_constraint_data_get_mix;a._spine_ik_constraint_data_set_mix=Y.spine_ik_constraint_data_set_mix;a._spine_ik_constraint_data_get_softness=Y.spine_ik_constraint_data_get_softness;a._spine_ik_constraint_data_set_softness=Y.spine_ik_constraint_data_set_softness;a._spine_ik_constraint_update=Y.spine_ik_constraint_update; +a._spine_ik_constraint_get_order=Y.spine_ik_constraint_get_order;a._spine_ik_constraint_get_data=Y.spine_ik_constraint_get_data;a._spine_ik_constraint_get_num_bones=Y.spine_ik_constraint_get_num_bones;a._spine_ik_constraint_get_bones=Y.spine_ik_constraint_get_bones;a._spine_ik_constraint_get_target=Y.spine_ik_constraint_get_target;a._spine_ik_constraint_set_target=Y.spine_ik_constraint_set_target;a._spine_ik_constraint_get_bend_direction=Y.spine_ik_constraint_get_bend_direction; +a._spine_ik_constraint_set_bend_direction=Y.spine_ik_constraint_set_bend_direction;a._spine_ik_constraint_get_compress=Y.spine_ik_constraint_get_compress;a._spine_ik_constraint_set_compress=Y.spine_ik_constraint_set_compress;a._spine_ik_constraint_get_stretch=Y.spine_ik_constraint_get_stretch;a._spine_ik_constraint_set_stretch=Y.spine_ik_constraint_set_stretch;a._spine_ik_constraint_get_mix=Y.spine_ik_constraint_get_mix;a._spine_ik_constraint_set_mix=Y.spine_ik_constraint_set_mix; +a._spine_ik_constraint_get_softness=Y.spine_ik_constraint_get_softness;a._spine_ik_constraint_set_softness=Y.spine_ik_constraint_set_softness;a._spine_ik_constraint_get_is_active=Y.spine_ik_constraint_get_is_active;a._spine_ik_constraint_set_is_active=Y.spine_ik_constraint_set_is_active;a._spine_transform_constraint_data_get_num_bones=Y.spine_transform_constraint_data_get_num_bones;a._spine_transform_constraint_data_get_bones=Y.spine_transform_constraint_data_get_bones; +a._spine_transform_constraint_data_get_target=Y.spine_transform_constraint_data_get_target;a._spine_transform_constraint_data_set_target=Y.spine_transform_constraint_data_set_target;a._spine_transform_constraint_data_get_mix_rotate=Y.spine_transform_constraint_data_get_mix_rotate;a._spine_transform_constraint_data_set_mix_rotate=Y.spine_transform_constraint_data_set_mix_rotate;a._spine_transform_constraint_data_get_mix_x=Y.spine_transform_constraint_data_get_mix_x; +a._spine_transform_constraint_data_set_mix_x=Y.spine_transform_constraint_data_set_mix_x;a._spine_transform_constraint_data_get_mix_y=Y.spine_transform_constraint_data_get_mix_y;a._spine_transform_constraint_data_set_mix_y=Y.spine_transform_constraint_data_set_mix_y;a._spine_transform_constraint_data_get_mix_scale_x=Y.spine_transform_constraint_data_get_mix_scale_x;a._spine_transform_constraint_data_set_mix_scale_x=Y.spine_transform_constraint_data_set_mix_scale_x; +a._spine_transform_constraint_data_get_mix_scale_y=Y.spine_transform_constraint_data_get_mix_scale_y;a._spine_transform_constraint_data_set_mix_scale_y=Y.spine_transform_constraint_data_set_mix_scale_y;a._spine_transform_constraint_data_get_mix_shear_y=Y.spine_transform_constraint_data_get_mix_shear_y;a._spine_transform_constraint_data_set_mix_shear_y=Y.spine_transform_constraint_data_set_mix_shear_y;a._spine_transform_constraint_data_get_offset_rotation=Y.spine_transform_constraint_data_get_offset_rotation; +a._spine_transform_constraint_data_set_offset_rotation=Y.spine_transform_constraint_data_set_offset_rotation;a._spine_transform_constraint_data_get_offset_x=Y.spine_transform_constraint_data_get_offset_x;a._spine_transform_constraint_data_set_offset_x=Y.spine_transform_constraint_data_set_offset_x;a._spine_transform_constraint_data_get_offset_y=Y.spine_transform_constraint_data_get_offset_y;a._spine_transform_constraint_data_set_offset_y=Y.spine_transform_constraint_data_set_offset_y; +a._spine_transform_constraint_data_get_offset_scale_x=Y.spine_transform_constraint_data_get_offset_scale_x;a._spine_transform_constraint_data_set_offset_scale_x=Y.spine_transform_constraint_data_set_offset_scale_x;a._spine_transform_constraint_data_get_offset_scale_y=Y.spine_transform_constraint_data_get_offset_scale_y;a._spine_transform_constraint_data_set_offset_scale_y=Y.spine_transform_constraint_data_set_offset_scale_y;a._spine_transform_constraint_data_get_offset_shear_y=Y.spine_transform_constraint_data_get_offset_shear_y; +a._spine_transform_constraint_data_set_offset_shear_y=Y.spine_transform_constraint_data_set_offset_shear_y;a._spine_transform_constraint_data_get_is_relative=Y.spine_transform_constraint_data_get_is_relative;a._spine_transform_constraint_data_set_is_relative=Y.spine_transform_constraint_data_set_is_relative;a._spine_transform_constraint_data_get_is_local=Y.spine_transform_constraint_data_get_is_local;a._spine_transform_constraint_data_set_is_local=Y.spine_transform_constraint_data_set_is_local; +a._spine_transform_constraint_update=Y.spine_transform_constraint_update;a._spine_transform_constraint_get_order=Y.spine_transform_constraint_get_order;a._spine_transform_constraint_get_data=Y.spine_transform_constraint_get_data;a._spine_transform_constraint_get_num_bones=Y.spine_transform_constraint_get_num_bones;a._spine_transform_constraint_get_bones=Y.spine_transform_constraint_get_bones;a._spine_transform_constraint_get_target=Y.spine_transform_constraint_get_target; +a._spine_transform_constraint_set_target=Y.spine_transform_constraint_set_target;a._spine_transform_constraint_get_mix_rotate=Y.spine_transform_constraint_get_mix_rotate;a._spine_transform_constraint_set_mix_rotate=Y.spine_transform_constraint_set_mix_rotate;a._spine_transform_constraint_get_mix_x=Y.spine_transform_constraint_get_mix_x;a._spine_transform_constraint_set_mix_x=Y.spine_transform_constraint_set_mix_x;a._spine_transform_constraint_get_mix_y=Y.spine_transform_constraint_get_mix_y; +a._spine_transform_constraint_set_mix_y=Y.spine_transform_constraint_set_mix_y;a._spine_transform_constraint_get_mix_scale_x=Y.spine_transform_constraint_get_mix_scale_x;a._spine_transform_constraint_set_mix_scale_x=Y.spine_transform_constraint_set_mix_scale_x;a._spine_transform_constraint_get_mix_scale_y=Y.spine_transform_constraint_get_mix_scale_y;a._spine_transform_constraint_set_mix_scale_y=Y.spine_transform_constraint_set_mix_scale_y;a._spine_transform_constraint_get_mix_shear_y=Y.spine_transform_constraint_get_mix_shear_y; +a._spine_transform_constraint_set_mix_shear_y=Y.spine_transform_constraint_set_mix_shear_y;a._spine_transform_constraint_get_is_active=Y.spine_transform_constraint_get_is_active;a._spine_transform_constraint_set_is_active=Y.spine_transform_constraint_set_is_active;a._spine_path_constraint_data_get_num_bones=Y.spine_path_constraint_data_get_num_bones;a._spine_path_constraint_data_get_bones=Y.spine_path_constraint_data_get_bones;a._spine_path_constraint_data_get_target=Y.spine_path_constraint_data_get_target; +a._spine_path_constraint_data_set_target=Y.spine_path_constraint_data_set_target;a._spine_path_constraint_data_get_position_mode=Y.spine_path_constraint_data_get_position_mode;a._spine_path_constraint_data_set_position_mode=Y.spine_path_constraint_data_set_position_mode;a._spine_path_constraint_data_get_spacing_mode=Y.spine_path_constraint_data_get_spacing_mode;a._spine_path_constraint_data_set_spacing_mode=Y.spine_path_constraint_data_set_spacing_mode; +a._spine_path_constraint_data_get_rotate_mode=Y.spine_path_constraint_data_get_rotate_mode;a._spine_path_constraint_data_set_rotate_mode=Y.spine_path_constraint_data_set_rotate_mode;a._spine_path_constraint_data_get_offset_rotation=Y.spine_path_constraint_data_get_offset_rotation;a._spine_path_constraint_data_set_offset_rotation=Y.spine_path_constraint_data_set_offset_rotation;a._spine_path_constraint_data_get_position=Y.spine_path_constraint_data_get_position; +a._spine_path_constraint_data_set_position=Y.spine_path_constraint_data_set_position;a._spine_path_constraint_data_get_spacing=Y.spine_path_constraint_data_get_spacing;a._spine_path_constraint_data_set_spacing=Y.spine_path_constraint_data_set_spacing;a._spine_path_constraint_data_get_mix_rotate=Y.spine_path_constraint_data_get_mix_rotate;a._spine_path_constraint_data_set_mix_rotate=Y.spine_path_constraint_data_set_mix_rotate;a._spine_path_constraint_data_get_mix_x=Y.spine_path_constraint_data_get_mix_x; +a._spine_path_constraint_data_set_mix_x=Y.spine_path_constraint_data_set_mix_x;a._spine_path_constraint_data_get_mix_y=Y.spine_path_constraint_data_get_mix_y;a._spine_path_constraint_data_set_mix_y=Y.spine_path_constraint_data_set_mix_y;a._spine_path_constraint_update=Y.spine_path_constraint_update;a._spine_path_constraint_get_order=Y.spine_path_constraint_get_order;a._spine_path_constraint_get_data=Y.spine_path_constraint_get_data;a._spine_path_constraint_get_num_bones=Y.spine_path_constraint_get_num_bones; +a._spine_path_constraint_get_bones=Y.spine_path_constraint_get_bones;a._spine_path_constraint_get_target=Y.spine_path_constraint_get_target;a._spine_path_constraint_set_target=Y.spine_path_constraint_set_target;a._spine_path_constraint_get_position=Y.spine_path_constraint_get_position;a._spine_path_constraint_set_position=Y.spine_path_constraint_set_position;a._spine_path_constraint_get_spacing=Y.spine_path_constraint_get_spacing;a._spine_path_constraint_set_spacing=Y.spine_path_constraint_set_spacing; +a._spine_path_constraint_get_mix_rotate=Y.spine_path_constraint_get_mix_rotate;a._spine_path_constraint_set_mix_rotate=Y.spine_path_constraint_set_mix_rotate;a._spine_path_constraint_get_mix_x=Y.spine_path_constraint_get_mix_x;a._spine_path_constraint_set_mix_x=Y.spine_path_constraint_set_mix_x;a._spine_path_constraint_get_mix_y=Y.spine_path_constraint_get_mix_y;a._spine_path_constraint_set_mix_y=Y.spine_path_constraint_set_mix_y;a._spine_path_constraint_get_is_active=Y.spine_path_constraint_get_is_active; +a._spine_path_constraint_set_is_active=Y.spine_path_constraint_set_is_active;a._spine_physics_constraint_data_set_bone=Y.spine_physics_constraint_data_set_bone;a._spine_physics_constraint_data_get_bone=Y.spine_physics_constraint_data_get_bone;a._spine_physics_constraint_data_set_x=Y.spine_physics_constraint_data_set_x;a._spine_physics_constraint_data_get_x=Y.spine_physics_constraint_data_get_x;a._spine_physics_constraint_data_set_y=Y.spine_physics_constraint_data_set_y; +a._spine_physics_constraint_data_get_y=Y.spine_physics_constraint_data_get_y;a._spine_physics_constraint_data_set_rotate=Y.spine_physics_constraint_data_set_rotate;a._spine_physics_constraint_data_get_rotate=Y.spine_physics_constraint_data_get_rotate;a._spine_physics_constraint_data_set_scale_x=Y.spine_physics_constraint_data_set_scale_x;a._spine_physics_constraint_data_get_scale_x=Y.spine_physics_constraint_data_get_scale_x;a._spine_physics_constraint_data_set_shear_x=Y.spine_physics_constraint_data_set_shear_x; +a._spine_physics_constraint_data_get_shear_x=Y.spine_physics_constraint_data_get_shear_x;a._spine_physics_constraint_data_set_limit=Y.spine_physics_constraint_data_set_limit;a._spine_physics_constraint_data_get_limit=Y.spine_physics_constraint_data_get_limit;a._spine_physics_constraint_data_set_step=Y.spine_physics_constraint_data_set_step;a._spine_physics_constraint_data_get_step=Y.spine_physics_constraint_data_get_step;a._spine_physics_constraint_data_set_inertia=Y.spine_physics_constraint_data_set_inertia; +a._spine_physics_constraint_data_get_inertia=Y.spine_physics_constraint_data_get_inertia;a._spine_physics_constraint_data_set_strength=Y.spine_physics_constraint_data_set_strength;a._spine_physics_constraint_data_get_strength=Y.spine_physics_constraint_data_get_strength;a._spine_physics_constraint_data_set_damping=Y.spine_physics_constraint_data_set_damping;a._spine_physics_constraint_data_get_damping=Y.spine_physics_constraint_data_get_damping;a._spine_physics_constraint_data_set_mass_inverse=Y.spine_physics_constraint_data_set_mass_inverse; +a._spine_physics_constraint_data_get_mass_inverse=Y.spine_physics_constraint_data_get_mass_inverse;a._spine_physics_constraint_data_set_wind=Y.spine_physics_constraint_data_set_wind;a._spine_physics_constraint_data_get_wind=Y.spine_physics_constraint_data_get_wind;a._spine_physics_constraint_data_set_gravity=Y.spine_physics_constraint_data_set_gravity;a._spine_physics_constraint_data_get_gravity=Y.spine_physics_constraint_data_get_gravity;a._spine_physics_constraint_data_set_mix=Y.spine_physics_constraint_data_set_mix; +a._spine_physics_constraint_data_get_mix=Y.spine_physics_constraint_data_get_mix;a._spine_physics_constraint_data_set_inertia_global=Y.spine_physics_constraint_data_set_inertia_global;a._spine_physics_constraint_data_is_inertia_global=Y.spine_physics_constraint_data_is_inertia_global;a._spine_physics_constraint_data_set_strength_global=Y.spine_physics_constraint_data_set_strength_global;a._spine_physics_constraint_data_is_strength_global=Y.spine_physics_constraint_data_is_strength_global; +a._spine_physics_constraint_data_set_damping_global=Y.spine_physics_constraint_data_set_damping_global;a._spine_physics_constraint_data_is_damping_global=Y.spine_physics_constraint_data_is_damping_global;a._spine_physics_constraint_data_set_mass_global=Y.spine_physics_constraint_data_set_mass_global;a._spine_physics_constraint_data_is_mass_global=Y.spine_physics_constraint_data_is_mass_global;a._spine_physics_constraint_data_set_wind_global=Y.spine_physics_constraint_data_set_wind_global; +a._spine_physics_constraint_data_is_wind_global=Y.spine_physics_constraint_data_is_wind_global;a._spine_physics_constraint_data_set_gravity_global=Y.spine_physics_constraint_data_set_gravity_global;a._spine_physics_constraint_data_is_gravity_global=Y.spine_physics_constraint_data_is_gravity_global;a._spine_physics_constraint_data_set_mix_global=Y.spine_physics_constraint_data_set_mix_global;a._spine_physics_constraint_data_is_mix_global=Y.spine_physics_constraint_data_is_mix_global; +a._spine_physics_constraint_set_bone=Y.spine_physics_constraint_set_bone;a._spine_physics_constraint_get_bone=Y.spine_physics_constraint_get_bone;a._spine_physics_constraint_set_inertia=Y.spine_physics_constraint_set_inertia;a._spine_physics_constraint_get_inertia=Y.spine_physics_constraint_get_inertia;a._spine_physics_constraint_set_strength=Y.spine_physics_constraint_set_strength;a._spine_physics_constraint_get_strength=Y.spine_physics_constraint_get_strength; +a._spine_physics_constraint_set_damping=Y.spine_physics_constraint_set_damping;a._spine_physics_constraint_get_damping=Y.spine_physics_constraint_get_damping;a._spine_physics_constraint_set_mass_inverse=Y.spine_physics_constraint_set_mass_inverse;a._spine_physics_constraint_get_mass_inverse=Y.spine_physics_constraint_get_mass_inverse;a._spine_physics_constraint_set_wind=Y.spine_physics_constraint_set_wind;a._spine_physics_constraint_get_wind=Y.spine_physics_constraint_get_wind; +a._spine_physics_constraint_set_gravity=Y.spine_physics_constraint_set_gravity;a._spine_physics_constraint_get_gravity=Y.spine_physics_constraint_get_gravity;a._spine_physics_constraint_set_mix=Y.spine_physics_constraint_set_mix;a._spine_physics_constraint_get_mix=Y.spine_physics_constraint_get_mix;a._spine_physics_constraint_set_reset=Y.spine_physics_constraint_set_reset;a._spine_physics_constraint_get_reset=Y.spine_physics_constraint_get_reset;a._spine_physics_constraint_set_ux=Y.spine_physics_constraint_set_ux; +a._spine_physics_constraint_get_ux=Y.spine_physics_constraint_get_ux;a._spine_physics_constraint_set_uy=Y.spine_physics_constraint_set_uy;a._spine_physics_constraint_get_uy=Y.spine_physics_constraint_get_uy;a._spine_physics_constraint_set_cx=Y.spine_physics_constraint_set_cx;a._spine_physics_constraint_get_cx=Y.spine_physics_constraint_get_cx;a._spine_physics_constraint_set_cy=Y.spine_physics_constraint_set_cy;a._spine_physics_constraint_get_cy=Y.spine_physics_constraint_get_cy; +a._spine_physics_constraint_set_tx=Y.spine_physics_constraint_set_tx;a._spine_physics_constraint_get_tx=Y.spine_physics_constraint_get_tx;a._spine_physics_constraint_set_ty=Y.spine_physics_constraint_set_ty;a._spine_physics_constraint_get_ty=Y.spine_physics_constraint_get_ty;a._spine_physics_constraint_set_x_offset=Y.spine_physics_constraint_set_x_offset;a._spine_physics_constraint_get_x_offset=Y.spine_physics_constraint_get_x_offset;a._spine_physics_constraint_set_x_velocity=Y.spine_physics_constraint_set_x_velocity; +a._spine_physics_constraint_get_x_velocity=Y.spine_physics_constraint_get_x_velocity;a._spine_physics_constraint_set_y_offset=Y.spine_physics_constraint_set_y_offset;a._spine_physics_constraint_get_y_offset=Y.spine_physics_constraint_get_y_offset;a._spine_physics_constraint_set_y_velocity=Y.spine_physics_constraint_set_y_velocity;a._spine_physics_constraint_get_y_velocity=Y.spine_physics_constraint_get_y_velocity;a._spine_physics_constraint_set_rotate_offset=Y.spine_physics_constraint_set_rotate_offset; +a._spine_physics_constraint_get_rotate_offset=Y.spine_physics_constraint_get_rotate_offset;a._spine_physics_constraint_set_rotate_velocity=Y.spine_physics_constraint_set_rotate_velocity;a._spine_physics_constraint_get_rotate_velocity=Y.spine_physics_constraint_get_rotate_velocity;a._spine_physics_constraint_set_scale_offset=Y.spine_physics_constraint_set_scale_offset;a._spine_physics_constraint_get_scale_offset=Y.spine_physics_constraint_get_scale_offset; +a._spine_physics_constraint_set_scale_velocity=Y.spine_physics_constraint_set_scale_velocity;a._spine_physics_constraint_get_scale_velocity=Y.spine_physics_constraint_get_scale_velocity;a._spine_physics_constraint_set_active=Y.spine_physics_constraint_set_active;a._spine_physics_constraint_is_active=Y.spine_physics_constraint_is_active;a._spine_physics_constraint_set_remaining=Y.spine_physics_constraint_set_remaining;a._spine_physics_constraint_get_remaining=Y.spine_physics_constraint_get_remaining; +a._spine_physics_constraint_set_last_time=Y.spine_physics_constraint_set_last_time;a._spine_physics_constraint_get_last_time=Y.spine_physics_constraint_get_last_time;a._spine_physics_constraint_reset_fully=Y.spine_physics_constraint_reset_fully;a._spine_physics_constraint_update=Y.spine_physics_constraint_update;a._spine_physics_constraint_translate=Y.spine_physics_constraint_translate;a._spine_physics_constraint_rotate=Y.spine_physics_constraint_rotate;a._spine_sequence_apply=Y.spine_sequence_apply; +a._spine_sequence_get_path=Y.spine_sequence_get_path;a._spine_sequence_get_id=Y.spine_sequence_get_id;a._spine_sequence_set_id=Y.spine_sequence_set_id;a._spine_sequence_get_start=Y.spine_sequence_get_start;a._spine_sequence_set_start=Y.spine_sequence_set_start;a._spine_sequence_get_digits=Y.spine_sequence_get_digits;a._spine_sequence_set_digits=Y.spine_sequence_set_digits;a._spine_sequence_get_setup_index=Y.spine_sequence_get_setup_index;a._spine_sequence_set_setup_index=Y.spine_sequence_set_setup_index; +a._spine_sequence_get_num_regions=Y.spine_sequence_get_num_regions;a._spine_sequence_get_regions=Y.spine_sequence_get_regions;a._spine_texture_region_get_texture=Y.spine_texture_region_get_texture;a._spine_texture_region_set_texture=Y.spine_texture_region_set_texture;a._spine_texture_region_get_u=Y.spine_texture_region_get_u;a._spine_texture_region_set_u=Y.spine_texture_region_set_u;a._spine_texture_region_get_v=Y.spine_texture_region_get_v;a._spine_texture_region_set_v=Y.spine_texture_region_set_v; +a._spine_texture_region_get_u2=Y.spine_texture_region_get_u2;a._spine_texture_region_set_u2=Y.spine_texture_region_set_u2;a._spine_texture_region_get_v2=Y.spine_texture_region_get_v2;a._spine_texture_region_set_v2=Y.spine_texture_region_set_v2;a._spine_texture_region_get_degrees=Y.spine_texture_region_get_degrees;a._spine_texture_region_set_degrees=Y.spine_texture_region_set_degrees;a._spine_texture_region_get_offset_x=Y.spine_texture_region_get_offset_x;a._spine_texture_region_set_offset_x=Y.spine_texture_region_set_offset_x; +a._spine_texture_region_get_offset_y=Y.spine_texture_region_get_offset_y;a._spine_texture_region_set_offset_y=Y.spine_texture_region_set_offset_y;a._spine_texture_region_get_width=Y.spine_texture_region_get_width;a._spine_texture_region_set_width=Y.spine_texture_region_set_width;a._spine_texture_region_get_height=Y.spine_texture_region_get_height;a._spine_texture_region_set_height=Y.spine_texture_region_set_height;a._spine_texture_region_get_original_width=Y.spine_texture_region_get_original_width; +a._spine_texture_region_set_original_width=Y.spine_texture_region_set_original_width;a._spine_texture_region_get_original_height=Y.spine_texture_region_get_original_height;a._spine_texture_region_set_original_height=Y.spine_texture_region_set_original_height;a._spine_skeleton_bounds_create=Y.spine_skeleton_bounds_create;a._spine_skeleton_bounds_dispose=Y.spine_skeleton_bounds_dispose;a._spine_skeleton_bounds_update=Y.spine_skeleton_bounds_update;a._spine_skeleton_bounds_aabb_contains_point=Y.spine_skeleton_bounds_aabb_contains_point; +a._spine_skeleton_bounds_aabb_intersects_segment=Y.spine_skeleton_bounds_aabb_intersects_segment;a._spine_skeleton_bounds_aabb_intersects_skeleton=Y.spine_skeleton_bounds_aabb_intersects_skeleton;a._spine_skeleton_bounds_contains_point=Y.spine_skeleton_bounds_contains_point;a._spine_skeleton_bounds_contains_point_attachment=Y.spine_skeleton_bounds_contains_point_attachment;a._spine_skeleton_bounds_intersects_segment_attachment=Y.spine_skeleton_bounds_intersects_segment_attachment; +a._spine_skeleton_bounds_intersects_segment=Y.spine_skeleton_bounds_intersects_segment;a._spine_skeleton_bounds_get_polygon=Y.spine_skeleton_bounds_get_polygon;a._spine_skeleton_bounds_get_bounding_box=Y.spine_skeleton_bounds_get_bounding_box;a._spine_skeleton_bounds_get_num_polygons=Y.spine_skeleton_bounds_get_num_polygons;a._spine_skeleton_bounds_get_polygons=Y.spine_skeleton_bounds_get_polygons;a._spine_skeleton_bounds_get_num_bounding_boxes=Y.spine_skeleton_bounds_get_num_bounding_boxes; +a._spine_skeleton_bounds_get_bounding_boxes=Y.spine_skeleton_bounds_get_bounding_boxes;a._spine_skeleton_bounds_get_width=Y.spine_skeleton_bounds_get_width;a._spine_skeleton_bounds_get_height=Y.spine_skeleton_bounds_get_height;a._spine_polygon_get_num_vertices=Y.spine_polygon_get_num_vertices;a._spine_polygon_get_vertices=Y.spine_polygon_get_vertices;a._malloc=Y.malloc;var ha=Y._emscripten_stack_restore,ia=Y.emscripten_stack_get_current; +function Z(){0{b=v.normalize(b);return fs.readFileSync(b,c?void 0:"utf8")};u=b=>{b=r(b,!0);b.buffer||(b=new Uint8Array(b));return b};t=(b,c,d)=>{b=v.normalize(b);fs.readFile(b,function(e,f){e?d(e):c(f.buffer)})};1{var c=new XMLHttpRequest;c.open("GET",b,!1);c.send(null);return c.responseText},n&&(u=b=>{var c=new XMLHttpRequest;c.open("GET",b,!1);c.responseType="arraybuffer";c.send(null);return new Uint8Array(c.response)}), -t=(b,c,d)=>{var e=new XMLHttpRequest;e.open("GET",b,!0);e.responseType="arraybuffer";e.onload=()=>{200==e.status||0==e.status&&e.response?c(e.response):d()};e.onerror=d;e.send(null)};var aa=a.print||console.log.bind(console),x=a.printErr||console.warn.bind(console);Object.assign(a,l);l=null;var y;a.wasmBinary&&(y=a.wasmBinary);var noExitRuntime=a.noExitRuntime||!0;"object"!=typeof WebAssembly&&z("no native wasm support detected"); -var A,B=!1,D="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0; -function E(b,c){for(var d=c+NaN,e=c;b[e]&&!(e>=d);)++e;if(16f?d+=String.fromCharCode(f):(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else d+=String.fromCharCode(f)}return d}var F,G,H,I,J,K,L,M; -function N(){var b=A.buffer;F=b;a.HEAP8=G=new Int8Array(b);a.HEAP16=I=new Int16Array(b);a.HEAP32=J=new Int32Array(b);a.HEAPU8=H=new Uint8Array(b);a.HEAPU16=new Uint16Array(b);a.HEAPU32=K=new Uint32Array(b);a.HEAPF32=L=new Float32Array(b);a.HEAPF64=M=new Float64Array(b)}var ba=[],ca=[],da=[];function ea(){var b=a.preRun.shift();ba.unshift(b)}var O=0,P=null,R=null; -function z(b){if(a.onAbort)a.onAbort(b);b="Aborted("+b+")";x(b);B=!0;b=new WebAssembly.RuntimeError(b+". Build with -sASSERTIONS for more info.");k(b);throw b;}function fa(){return S.startsWith("data:application/octet-stream;base64,")}var S;S="libspine_flutter.wasm";if(!fa()){var ha=S;S=a.locateFile?a.locateFile(ha,q):q+ha}function ia(){var b=S;try{if(b==S&&y)return new Uint8Array(y);if(u)return u(b);throw"both async and sync fetching of the wasm failed";}catch(c){z(c)}} -function ja(){if(!y&&(m||n)){if("function"==typeof fetch&&!S.startsWith("file://"))return fetch(S,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+S+"'";return b.arrayBuffer()}).catch(function(){return ia()});if(t)return new Promise(function(b,c){t(S,function(d){b(new Uint8Array(d))},c)})}return Promise.resolve().then(function(){return ia()})}var T,U; -function w(b){this.name="ExitStatus";this.message="Program terminated with exit("+b+")";this.status=b}a.ExitStatus=w;function V(b){for(;0>0];case "i8":return G[b>>0];case "i16":return I[b>>1];case "i32":return J[b>>2];case "i64":return J[b>>2];case "float":return L[b>>2];case "double":return M[b>>3];case "*":return K[b>>2];default:z("invalid type for getValue: "+c)}return null}; -a.setValue=function(b,c,d="i8"){d.endsWith("*")&&(d="*");switch(d){case "i1":G[b>>0]=c;break;case "i8":G[b>>0]=c;break;case "i16":I[b>>1]=c;break;case "i32":J[b>>2]=c;break;case "i64":U=[c>>>0,(T=c,1<=+Math.abs(T)?0>>0:~~+Math.ceil((T-+(~~T>>>0))/4294967296)>>>0:0)];J[b>>2]=U[0];J[b+4>>2]=U[1];break;case "float":L[b>>2]=c;break;case "double":M[b>>3]=c;break;case "*":K[b>>2]=c;break;default:z("invalid type for setValue: "+d)}}; -function ka(b,c,d,e){z("Assertion failed: "+(b?E(H,b):"")+", at: "+[c?c?E(H,c):"":"unknown filename",d,e?e?E(H,e):"":"unknown function"])}a.___assert_fail=ka;function la(){z("")}a._abort=la;function ma(b,c,d){H.copyWithin(b,c,c+d)}a._emscripten_memcpy_big=ma;a.getHeapMax=function(){return 2147483648};function oa(b){try{return A.grow(b-F.byteLength+65535>>>16),N(),1}catch(c){}}a.emscripten_realloc_buffer=oa; -function pa(b){var c=H.length;b>>>=0;if(2147483648=d;d*=2){var e=c*(1+.2/d);e=Math.min(e,b+100663296);var f=Math;e=Math.max(b,e);if(oa(f.min.call(f,2147483648,e+(65536-e%65536)%65536)))return!0}return!1}a._emscripten_resize_heap=pa;var W=[null,[],[]];a.printCharBuffers=W;function X(b,c){var d=W[b];0===c||10===c?((1===b?aa:x)(E(d,0)),d.length=0):d.push(c)}a.printChar=X;a.flush_NO_FILESYSTEM=function(){W[1].length&&X(1,10);W[2].length&&X(2,10)}; -var Y={g:void 0,get:function(){Y.g+=4;return J[Y.g-4>>2]},h:function(b){return b?E(H,b):""}};a.SYSCALLS=Y;function qa(b,c,d,e){for(var f=0,g=0;g>2],na=K[c+4>>2];c+=8;for(var Q=0;Q>2]=f;return 0}a._fd_write=qa;var ra={__assert_fail:ka,abort:la,emscripten_memcpy_big:ma,emscripten_resize_heap:pa,fd_write:qa}; -(function(){function b(f){a.asm=f.exports;A=a.asm.memory;N();ca.unshift(a.asm.__wasm_call_ctors);O--;a.monitorRunDependencies&&a.monitorRunDependencies(O);0==O&&(null!==P&&(clearInterval(P),P=null),R&&(f=R,R=null,f()))}function c(f){b(f.instance)}function d(f){return ja().then(function(g){return WebAssembly.instantiate(g,e)}).then(function(g){return g}).then(f,function(g){x("failed to asynchronously prepare wasm: "+g);z(g)})}var e={env:ra,wasi_snapshot_preview1:ra};O++;a.monitorRunDependencies&&a.monitorRunDependencies(O); -if(a.instantiateWasm)try{return a.instantiateWasm(e,b)}catch(f){x("Module.instantiateWasm callback failed with error: "+f),k(f)}(function(){return y||"function"!=typeof WebAssembly.instantiateStreaming||fa()||S.startsWith("file://")||p||"function"!=typeof fetch?d(c):fetch(S,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(c,function(g){x("wasm streaming compile failed: "+g);x("falling back to ArrayBuffer instantiation");return d(c)})})})().catch(k);return{}})(); -a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.__wasm_call_ctors).apply(null,arguments)};a._spine_enable_debug_extension=function(){return(a._spine_enable_debug_extension=a.asm.spine_enable_debug_extension).apply(null,arguments)};a._spine_major_version=function(){return(a._spine_major_version=a.asm.spine_major_version).apply(null,arguments)};a._spine_minor_version=function(){return(a._spine_minor_version=a.asm.spine_minor_version).apply(null,arguments)}; -a._spine_report_leaks=function(){return(a._spine_report_leaks=a.asm.spine_report_leaks).apply(null,arguments)};a._spine_color_get_r=function(){return(a._spine_color_get_r=a.asm.spine_color_get_r).apply(null,arguments)};a._spine_color_get_g=function(){return(a._spine_color_get_g=a.asm.spine_color_get_g).apply(null,arguments)};a._spine_color_get_b=function(){return(a._spine_color_get_b=a.asm.spine_color_get_b).apply(null,arguments)}; -a._spine_color_get_a=function(){return(a._spine_color_get_a=a.asm.spine_color_get_a).apply(null,arguments)};a._spine_bounds_get_x=function(){return(a._spine_bounds_get_x=a.asm.spine_bounds_get_x).apply(null,arguments)};a._spine_bounds_get_y=function(){return(a._spine_bounds_get_y=a.asm.spine_bounds_get_y).apply(null,arguments)};a._spine_bounds_get_width=function(){return(a._spine_bounds_get_width=a.asm.spine_bounds_get_width).apply(null,arguments)}; -a._spine_bounds_get_height=function(){return(a._spine_bounds_get_height=a.asm.spine_bounds_get_height).apply(null,arguments)};a._spine_vector_get_x=function(){return(a._spine_vector_get_x=a.asm.spine_vector_get_x).apply(null,arguments)};a._spine_vector_get_y=function(){return(a._spine_vector_get_y=a.asm.spine_vector_get_y).apply(null,arguments)};a._spine_atlas_load=function(){return(a._spine_atlas_load=a.asm.spine_atlas_load).apply(null,arguments)}; -a._spine_atlas_get_num_image_paths=function(){return(a._spine_atlas_get_num_image_paths=a.asm.spine_atlas_get_num_image_paths).apply(null,arguments)};a._spine_atlas_is_pma=function(){return(a._spine_atlas_is_pma=a.asm.spine_atlas_is_pma).apply(null,arguments)};a._spine_atlas_get_image_path=function(){return(a._spine_atlas_get_image_path=a.asm.spine_atlas_get_image_path).apply(null,arguments)}; -a._spine_atlas_get_error=function(){return(a._spine_atlas_get_error=a.asm.spine_atlas_get_error).apply(null,arguments)};a._spine_atlas_dispose=function(){return(a._spine_atlas_dispose=a.asm.spine_atlas_dispose).apply(null,arguments)};a._free=function(){return(a._free=a.asm.free).apply(null,arguments)};a._spine_skeleton_data_load_json=function(){return(a._spine_skeleton_data_load_json=a.asm.spine_skeleton_data_load_json).apply(null,arguments)}; -a._spine_skeleton_data_load_binary=function(){return(a._spine_skeleton_data_load_binary=a.asm.spine_skeleton_data_load_binary).apply(null,arguments)};a._spine_skeleton_data_result_get_error=function(){return(a._spine_skeleton_data_result_get_error=a.asm.spine_skeleton_data_result_get_error).apply(null,arguments)};a._spine_skeleton_data_result_get_data=function(){return(a._spine_skeleton_data_result_get_data=a.asm.spine_skeleton_data_result_get_data).apply(null,arguments)}; -a._spine_skeleton_data_result_dispose=function(){return(a._spine_skeleton_data_result_dispose=a.asm.spine_skeleton_data_result_dispose).apply(null,arguments)};a._spine_skeleton_data_find_bone=function(){return(a._spine_skeleton_data_find_bone=a.asm.spine_skeleton_data_find_bone).apply(null,arguments)};a._spine_skeleton_data_find_slot=function(){return(a._spine_skeleton_data_find_slot=a.asm.spine_skeleton_data_find_slot).apply(null,arguments)}; -a._spine_skeleton_data_find_skin=function(){return(a._spine_skeleton_data_find_skin=a.asm.spine_skeleton_data_find_skin).apply(null,arguments)};a._spine_skeleton_data_find_event=function(){return(a._spine_skeleton_data_find_event=a.asm.spine_skeleton_data_find_event).apply(null,arguments)};a._spine_skeleton_data_find_animation=function(){return(a._spine_skeleton_data_find_animation=a.asm.spine_skeleton_data_find_animation).apply(null,arguments)}; -a._spine_skeleton_data_find_ik_constraint=function(){return(a._spine_skeleton_data_find_ik_constraint=a.asm.spine_skeleton_data_find_ik_constraint).apply(null,arguments)};a._spine_skeleton_data_find_transform_constraint=function(){return(a._spine_skeleton_data_find_transform_constraint=a.asm.spine_skeleton_data_find_transform_constraint).apply(null,arguments)}; -a._spine_skeleton_data_find_path_constraint=function(){return(a._spine_skeleton_data_find_path_constraint=a.asm.spine_skeleton_data_find_path_constraint).apply(null,arguments)};a._spine_skeleton_data_find_physics_constraint=function(){return(a._spine_skeleton_data_find_physics_constraint=a.asm.spine_skeleton_data_find_physics_constraint).apply(null,arguments)};a._spine_skeleton_data_get_name=function(){return(a._spine_skeleton_data_get_name=a.asm.spine_skeleton_data_get_name).apply(null,arguments)}; -a._spine_skeleton_data_get_num_bones=function(){return(a._spine_skeleton_data_get_num_bones=a.asm.spine_skeleton_data_get_num_bones).apply(null,arguments)};a._spine_skeleton_data_get_bones=function(){return(a._spine_skeleton_data_get_bones=a.asm.spine_skeleton_data_get_bones).apply(null,arguments)};a._spine_skeleton_data_get_num_slots=function(){return(a._spine_skeleton_data_get_num_slots=a.asm.spine_skeleton_data_get_num_slots).apply(null,arguments)}; -a._spine_skeleton_data_get_slots=function(){return(a._spine_skeleton_data_get_slots=a.asm.spine_skeleton_data_get_slots).apply(null,arguments)};a._spine_skeleton_data_get_num_skins=function(){return(a._spine_skeleton_data_get_num_skins=a.asm.spine_skeleton_data_get_num_skins).apply(null,arguments)};a._spine_skeleton_data_get_skins=function(){return(a._spine_skeleton_data_get_skins=a.asm.spine_skeleton_data_get_skins).apply(null,arguments)}; -a._spine_skeleton_data_get_default_skin=function(){return(a._spine_skeleton_data_get_default_skin=a.asm.spine_skeleton_data_get_default_skin).apply(null,arguments)};a._spine_skeleton_data_set_default_skin=function(){return(a._spine_skeleton_data_set_default_skin=a.asm.spine_skeleton_data_set_default_skin).apply(null,arguments)};a._spine_skeleton_data_get_num_events=function(){return(a._spine_skeleton_data_get_num_events=a.asm.spine_skeleton_data_get_num_events).apply(null,arguments)}; -a._spine_skeleton_data_get_events=function(){return(a._spine_skeleton_data_get_events=a.asm.spine_skeleton_data_get_events).apply(null,arguments)};a._spine_skeleton_data_get_num_animations=function(){return(a._spine_skeleton_data_get_num_animations=a.asm.spine_skeleton_data_get_num_animations).apply(null,arguments)};a._spine_skeleton_data_get_animations=function(){return(a._spine_skeleton_data_get_animations=a.asm.spine_skeleton_data_get_animations).apply(null,arguments)}; -a._spine_skeleton_data_get_num_ik_constraints=function(){return(a._spine_skeleton_data_get_num_ik_constraints=a.asm.spine_skeleton_data_get_num_ik_constraints).apply(null,arguments)};a._spine_skeleton_data_get_ik_constraints=function(){return(a._spine_skeleton_data_get_ik_constraints=a.asm.spine_skeleton_data_get_ik_constraints).apply(null,arguments)}; -a._spine_skeleton_data_get_num_transform_constraints=function(){return(a._spine_skeleton_data_get_num_transform_constraints=a.asm.spine_skeleton_data_get_num_transform_constraints).apply(null,arguments)};a._spine_skeleton_data_get_transform_constraints=function(){return(a._spine_skeleton_data_get_transform_constraints=a.asm.spine_skeleton_data_get_transform_constraints).apply(null,arguments)}; -a._spine_skeleton_data_get_num_path_constraints=function(){return(a._spine_skeleton_data_get_num_path_constraints=a.asm.spine_skeleton_data_get_num_path_constraints).apply(null,arguments)};a._spine_skeleton_data_get_path_constraints=function(){return(a._spine_skeleton_data_get_path_constraints=a.asm.spine_skeleton_data_get_path_constraints).apply(null,arguments)}; -a._spine_skeleton_data_get_num_physics_constraints=function(){return(a._spine_skeleton_data_get_num_physics_constraints=a.asm.spine_skeleton_data_get_num_physics_constraints).apply(null,arguments)};a._spine_skeleton_data_get_physics_constraints=function(){return(a._spine_skeleton_data_get_physics_constraints=a.asm.spine_skeleton_data_get_physics_constraints).apply(null,arguments)}; -a._spine_skeleton_data_get_x=function(){return(a._spine_skeleton_data_get_x=a.asm.spine_skeleton_data_get_x).apply(null,arguments)};a._spine_skeleton_data_set_x=function(){return(a._spine_skeleton_data_set_x=a.asm.spine_skeleton_data_set_x).apply(null,arguments)};a._spine_skeleton_data_get_y=function(){return(a._spine_skeleton_data_get_y=a.asm.spine_skeleton_data_get_y).apply(null,arguments)}; -a._spine_skeleton_data_set_y=function(){return(a._spine_skeleton_data_set_y=a.asm.spine_skeleton_data_set_y).apply(null,arguments)};a._spine_skeleton_data_get_width=function(){return(a._spine_skeleton_data_get_width=a.asm.spine_skeleton_data_get_width).apply(null,arguments)};a._spine_skeleton_data_set_width=function(){return(a._spine_skeleton_data_set_width=a.asm.spine_skeleton_data_set_width).apply(null,arguments)}; -a._spine_skeleton_data_get_height=function(){return(a._spine_skeleton_data_get_height=a.asm.spine_skeleton_data_get_height).apply(null,arguments)};a._spine_skeleton_data_set_height=function(){return(a._spine_skeleton_data_set_height=a.asm.spine_skeleton_data_set_height).apply(null,arguments)};a._spine_skeleton_data_get_version=function(){return(a._spine_skeleton_data_get_version=a.asm.spine_skeleton_data_get_version).apply(null,arguments)}; -a._spine_skeleton_data_get_hash=function(){return(a._spine_skeleton_data_get_hash=a.asm.spine_skeleton_data_get_hash).apply(null,arguments)};a._spine_skeleton_data_get_images_path=function(){return(a._spine_skeleton_data_get_images_path=a.asm.spine_skeleton_data_get_images_path).apply(null,arguments)};a._spine_skeleton_data_get_audio_path=function(){return(a._spine_skeleton_data_get_audio_path=a.asm.spine_skeleton_data_get_audio_path).apply(null,arguments)}; -a._spine_skeleton_data_get_fps=function(){return(a._spine_skeleton_data_get_fps=a.asm.spine_skeleton_data_get_fps).apply(null,arguments)};a._spine_skeleton_data_get_reference_scale=function(){return(a._spine_skeleton_data_get_reference_scale=a.asm.spine_skeleton_data_get_reference_scale).apply(null,arguments)};a._spine_skeleton_data_dispose=function(){return(a._spine_skeleton_data_dispose=a.asm.spine_skeleton_data_dispose).apply(null,arguments)}; -a._spine_skeleton_drawable_create=function(){return(a._spine_skeleton_drawable_create=a.asm.spine_skeleton_drawable_create).apply(null,arguments)};a._spine_skeleton_drawable_dispose=function(){return(a._spine_skeleton_drawable_dispose=a.asm.spine_skeleton_drawable_dispose).apply(null,arguments)};a._spine_skeleton_drawable_render=function(){return(a._spine_skeleton_drawable_render=a.asm.spine_skeleton_drawable_render).apply(null,arguments)}; -a._spine_skeleton_drawable_get_skeleton=function(){return(a._spine_skeleton_drawable_get_skeleton=a.asm.spine_skeleton_drawable_get_skeleton).apply(null,arguments)};a._spine_skeleton_drawable_get_animation_state=function(){return(a._spine_skeleton_drawable_get_animation_state=a.asm.spine_skeleton_drawable_get_animation_state).apply(null,arguments)}; -a._spine_skeleton_drawable_get_animation_state_data=function(){return(a._spine_skeleton_drawable_get_animation_state_data=a.asm.spine_skeleton_drawable_get_animation_state_data).apply(null,arguments)};a._spine_skeleton_drawable_get_animation_state_events=function(){return(a._spine_skeleton_drawable_get_animation_state_events=a.asm.spine_skeleton_drawable_get_animation_state_events).apply(null,arguments)}; -a._spine_render_command_get_positions=function(){return(a._spine_render_command_get_positions=a.asm.spine_render_command_get_positions).apply(null,arguments)};a._spine_render_command_get_uvs=function(){return(a._spine_render_command_get_uvs=a.asm.spine_render_command_get_uvs).apply(null,arguments)};a._spine_render_command_get_colors=function(){return(a._spine_render_command_get_colors=a.asm.spine_render_command_get_colors).apply(null,arguments)}; -a._spine_render_command_get_dark_colors=function(){return(a._spine_render_command_get_dark_colors=a.asm.spine_render_command_get_dark_colors).apply(null,arguments)};a._spine_render_command_get_num_vertices=function(){return(a._spine_render_command_get_num_vertices=a.asm.spine_render_command_get_num_vertices).apply(null,arguments)};a._spine_render_command_get_indices=function(){return(a._spine_render_command_get_indices=a.asm.spine_render_command_get_indices).apply(null,arguments)}; -a._spine_render_command_get_num_indices=function(){return(a._spine_render_command_get_num_indices=a.asm.spine_render_command_get_num_indices).apply(null,arguments)};a._spine_render_command_get_atlas_page=function(){return(a._spine_render_command_get_atlas_page=a.asm.spine_render_command_get_atlas_page).apply(null,arguments)};a._spine_render_command_get_blend_mode=function(){return(a._spine_render_command_get_blend_mode=a.asm.spine_render_command_get_blend_mode).apply(null,arguments)}; -a._spine_render_command_get_next=function(){return(a._spine_render_command_get_next=a.asm.spine_render_command_get_next).apply(null,arguments)};a._spine_animation_get_name=function(){return(a._spine_animation_get_name=a.asm.spine_animation_get_name).apply(null,arguments)};a._spine_animation_get_duration=function(){return(a._spine_animation_get_duration=a.asm.spine_animation_get_duration).apply(null,arguments)}; -a._spine_animation_state_data_get_skeleton_data=function(){return(a._spine_animation_state_data_get_skeleton_data=a.asm.spine_animation_state_data_get_skeleton_data).apply(null,arguments)};a._spine_animation_state_data_get_default_mix=function(){return(a._spine_animation_state_data_get_default_mix=a.asm.spine_animation_state_data_get_default_mix).apply(null,arguments)}; -a._spine_animation_state_data_set_default_mix=function(){return(a._spine_animation_state_data_set_default_mix=a.asm.spine_animation_state_data_set_default_mix).apply(null,arguments)};a._spine_animation_state_data_set_mix=function(){return(a._spine_animation_state_data_set_mix=a.asm.spine_animation_state_data_set_mix).apply(null,arguments)};a._spine_animation_state_data_get_mix=function(){return(a._spine_animation_state_data_get_mix=a.asm.spine_animation_state_data_get_mix).apply(null,arguments)}; -a._spine_animation_state_data_set_mix_by_name=function(){return(a._spine_animation_state_data_set_mix_by_name=a.asm.spine_animation_state_data_set_mix_by_name).apply(null,arguments)};a._spine_animation_state_data_get_mix_by_name=function(){return(a._spine_animation_state_data_get_mix_by_name=a.asm.spine_animation_state_data_get_mix_by_name).apply(null,arguments)}; -a._spine_animation_state_data_clear=function(){return(a._spine_animation_state_data_clear=a.asm.spine_animation_state_data_clear).apply(null,arguments)};a._spine_animation_state_update=function(){return(a._spine_animation_state_update=a.asm.spine_animation_state_update).apply(null,arguments)};a._spine_animation_state_dispose_track_entry=function(){return(a._spine_animation_state_dispose_track_entry=a.asm.spine_animation_state_dispose_track_entry).apply(null,arguments)}; -a._spine_animation_state_apply=function(){return(a._spine_animation_state_apply=a.asm.spine_animation_state_apply).apply(null,arguments)};a._spine_animation_state_clear_tracks=function(){return(a._spine_animation_state_clear_tracks=a.asm.spine_animation_state_clear_tracks).apply(null,arguments)};a._spine_animation_state_get_num_tracks=function(){return(a._spine_animation_state_get_num_tracks=a.asm.spine_animation_state_get_num_tracks).apply(null,arguments)}; -a._spine_animation_state_clear_track=function(){return(a._spine_animation_state_clear_track=a.asm.spine_animation_state_clear_track).apply(null,arguments)};a._spine_animation_state_set_animation_by_name=function(){return(a._spine_animation_state_set_animation_by_name=a.asm.spine_animation_state_set_animation_by_name).apply(null,arguments)};a._spine_animation_state_set_animation=function(){return(a._spine_animation_state_set_animation=a.asm.spine_animation_state_set_animation).apply(null,arguments)}; -a._spine_animation_state_add_animation_by_name=function(){return(a._spine_animation_state_add_animation_by_name=a.asm.spine_animation_state_add_animation_by_name).apply(null,arguments)};a._spine_animation_state_add_animation=function(){return(a._spine_animation_state_add_animation=a.asm.spine_animation_state_add_animation).apply(null,arguments)}; -a._spine_animation_state_set_empty_animation=function(){return(a._spine_animation_state_set_empty_animation=a.asm.spine_animation_state_set_empty_animation).apply(null,arguments)};a._spine_animation_state_add_empty_animation=function(){return(a._spine_animation_state_add_empty_animation=a.asm.spine_animation_state_add_empty_animation).apply(null,arguments)}; -a._spine_animation_state_set_empty_animations=function(){return(a._spine_animation_state_set_empty_animations=a.asm.spine_animation_state_set_empty_animations).apply(null,arguments)};a._spine_animation_state_get_current=function(){return(a._spine_animation_state_get_current=a.asm.spine_animation_state_get_current).apply(null,arguments)};a._spine_animation_state_get_data=function(){return(a._spine_animation_state_get_data=a.asm.spine_animation_state_get_data).apply(null,arguments)}; -a._spine_animation_state_get_time_scale=function(){return(a._spine_animation_state_get_time_scale=a.asm.spine_animation_state_get_time_scale).apply(null,arguments)};a._spine_animation_state_set_time_scale=function(){return(a._spine_animation_state_set_time_scale=a.asm.spine_animation_state_set_time_scale).apply(null,arguments)}; -a._spine_animation_state_events_get_num_events=function(){return(a._spine_animation_state_events_get_num_events=a.asm.spine_animation_state_events_get_num_events).apply(null,arguments)};a._spine_animation_state_events_get_event_type=function(){return(a._spine_animation_state_events_get_event_type=a.asm.spine_animation_state_events_get_event_type).apply(null,arguments)}; -a._spine_animation_state_events_get_track_entry=function(){return(a._spine_animation_state_events_get_track_entry=a.asm.spine_animation_state_events_get_track_entry).apply(null,arguments)};a._spine_animation_state_events_get_event=function(){return(a._spine_animation_state_events_get_event=a.asm.spine_animation_state_events_get_event).apply(null,arguments)}; -a._spine_animation_state_events_reset=function(){return(a._spine_animation_state_events_reset=a.asm.spine_animation_state_events_reset).apply(null,arguments)};a._spine_track_entry_get_track_index=function(){return(a._spine_track_entry_get_track_index=a.asm.spine_track_entry_get_track_index).apply(null,arguments)};a._spine_track_entry_get_animation=function(){return(a._spine_track_entry_get_animation=a.asm.spine_track_entry_get_animation).apply(null,arguments)}; -a._spine_track_entry_get_previous=function(){return(a._spine_track_entry_get_previous=a.asm.spine_track_entry_get_previous).apply(null,arguments)};a._spine_track_entry_get_loop=function(){return(a._spine_track_entry_get_loop=a.asm.spine_track_entry_get_loop).apply(null,arguments)};a._spine_track_entry_set_loop=function(){return(a._spine_track_entry_set_loop=a.asm.spine_track_entry_set_loop).apply(null,arguments)}; -a._spine_track_entry_get_hold_previous=function(){return(a._spine_track_entry_get_hold_previous=a.asm.spine_track_entry_get_hold_previous).apply(null,arguments)};a._spine_track_entry_set_hold_previous=function(){return(a._spine_track_entry_set_hold_previous=a.asm.spine_track_entry_set_hold_previous).apply(null,arguments)};a._spine_track_entry_get_reverse=function(){return(a._spine_track_entry_get_reverse=a.asm.spine_track_entry_get_reverse).apply(null,arguments)}; -a._spine_track_entry_set_reverse=function(){return(a._spine_track_entry_set_reverse=a.asm.spine_track_entry_set_reverse).apply(null,arguments)};a._spine_track_entry_get_shortest_rotation=function(){return(a._spine_track_entry_get_shortest_rotation=a.asm.spine_track_entry_get_shortest_rotation).apply(null,arguments)};a._spine_track_entry_set_shortest_rotation=function(){return(a._spine_track_entry_set_shortest_rotation=a.asm.spine_track_entry_set_shortest_rotation).apply(null,arguments)}; -a._spine_track_entry_get_delay=function(){return(a._spine_track_entry_get_delay=a.asm.spine_track_entry_get_delay).apply(null,arguments)};a._spine_track_entry_set_delay=function(){return(a._spine_track_entry_set_delay=a.asm.spine_track_entry_set_delay).apply(null,arguments)};a._spine_track_entry_get_track_time=function(){return(a._spine_track_entry_get_track_time=a.asm.spine_track_entry_get_track_time).apply(null,arguments)}; -a._spine_track_entry_set_track_time=function(){return(a._spine_track_entry_set_track_time=a.asm.spine_track_entry_set_track_time).apply(null,arguments)};a._spine_track_entry_get_track_end=function(){return(a._spine_track_entry_get_track_end=a.asm.spine_track_entry_get_track_end).apply(null,arguments)};a._spine_track_entry_set_track_end=function(){return(a._spine_track_entry_set_track_end=a.asm.spine_track_entry_set_track_end).apply(null,arguments)}; -a._spine_track_entry_get_animation_start=function(){return(a._spine_track_entry_get_animation_start=a.asm.spine_track_entry_get_animation_start).apply(null,arguments)};a._spine_track_entry_set_animation_start=function(){return(a._spine_track_entry_set_animation_start=a.asm.spine_track_entry_set_animation_start).apply(null,arguments)};a._spine_track_entry_get_animation_end=function(){return(a._spine_track_entry_get_animation_end=a.asm.spine_track_entry_get_animation_end).apply(null,arguments)}; -a._spine_track_entry_set_animation_end=function(){return(a._spine_track_entry_set_animation_end=a.asm.spine_track_entry_set_animation_end).apply(null,arguments)};a._spine_track_entry_get_animation_last=function(){return(a._spine_track_entry_get_animation_last=a.asm.spine_track_entry_get_animation_last).apply(null,arguments)};a._spine_track_entry_set_animation_last=function(){return(a._spine_track_entry_set_animation_last=a.asm.spine_track_entry_set_animation_last).apply(null,arguments)}; -a._spine_track_entry_get_animation_time=function(){return(a._spine_track_entry_get_animation_time=a.asm.spine_track_entry_get_animation_time).apply(null,arguments)};a._spine_track_entry_get_time_scale=function(){return(a._spine_track_entry_get_time_scale=a.asm.spine_track_entry_get_time_scale).apply(null,arguments)};a._spine_track_entry_set_time_scale=function(){return(a._spine_track_entry_set_time_scale=a.asm.spine_track_entry_set_time_scale).apply(null,arguments)}; -a._spine_track_entry_get_alpha=function(){return(a._spine_track_entry_get_alpha=a.asm.spine_track_entry_get_alpha).apply(null,arguments)};a._spine_track_entry_set_alpha=function(){return(a._spine_track_entry_set_alpha=a.asm.spine_track_entry_set_alpha).apply(null,arguments)};a._spine_track_entry_get_event_threshold=function(){return(a._spine_track_entry_get_event_threshold=a.asm.spine_track_entry_get_event_threshold).apply(null,arguments)}; -a._spine_track_entry_set_event_threshold=function(){return(a._spine_track_entry_set_event_threshold=a.asm.spine_track_entry_set_event_threshold).apply(null,arguments)};a._spine_track_entry_get_alpha_attachment_threshold=function(){return(a._spine_track_entry_get_alpha_attachment_threshold=a.asm.spine_track_entry_get_alpha_attachment_threshold).apply(null,arguments)}; -a._spine_track_entry_set_alpha_attachment_threshold=function(){return(a._spine_track_entry_set_alpha_attachment_threshold=a.asm.spine_track_entry_set_alpha_attachment_threshold).apply(null,arguments)};a._spine_track_entry_get_mix_attachment_threshold=function(){return(a._spine_track_entry_get_mix_attachment_threshold=a.asm.spine_track_entry_get_mix_attachment_threshold).apply(null,arguments)}; -a._spine_track_entry_set_mix_attachment_threshold=function(){return(a._spine_track_entry_set_mix_attachment_threshold=a.asm.spine_track_entry_set_mix_attachment_threshold).apply(null,arguments)};a._spine_track_entry_get_mix_draw_order_threshold=function(){return(a._spine_track_entry_get_mix_draw_order_threshold=a.asm.spine_track_entry_get_mix_draw_order_threshold).apply(null,arguments)}; -a._spine_track_entry_set_mix_draw_order_threshold=function(){return(a._spine_track_entry_set_mix_draw_order_threshold=a.asm.spine_track_entry_set_mix_draw_order_threshold).apply(null,arguments)};a._spine_track_entry_get_next=function(){return(a._spine_track_entry_get_next=a.asm.spine_track_entry_get_next).apply(null,arguments)};a._spine_track_entry_is_complete=function(){return(a._spine_track_entry_is_complete=a.asm.spine_track_entry_is_complete).apply(null,arguments)}; -a._spine_track_entry_get_mix_time=function(){return(a._spine_track_entry_get_mix_time=a.asm.spine_track_entry_get_mix_time).apply(null,arguments)};a._spine_track_entry_set_mix_time=function(){return(a._spine_track_entry_set_mix_time=a.asm.spine_track_entry_set_mix_time).apply(null,arguments)};a._spine_track_entry_get_mix_duration=function(){return(a._spine_track_entry_get_mix_duration=a.asm.spine_track_entry_get_mix_duration).apply(null,arguments)}; -a._spine_track_entry_set_mix_duration=function(){return(a._spine_track_entry_set_mix_duration=a.asm.spine_track_entry_set_mix_duration).apply(null,arguments)};a._spine_track_entry_get_mix_blend=function(){return(a._spine_track_entry_get_mix_blend=a.asm.spine_track_entry_get_mix_blend).apply(null,arguments)};a._spine_track_entry_set_mix_blend=function(){return(a._spine_track_entry_set_mix_blend=a.asm.spine_track_entry_set_mix_blend).apply(null,arguments)}; -a._spine_track_entry_get_mixing_from=function(){return(a._spine_track_entry_get_mixing_from=a.asm.spine_track_entry_get_mixing_from).apply(null,arguments)};a._spine_track_entry_get_mixing_to=function(){return(a._spine_track_entry_get_mixing_to=a.asm.spine_track_entry_get_mixing_to).apply(null,arguments)};a._spine_track_entry_reset_rotation_directions=function(){return(a._spine_track_entry_reset_rotation_directions=a.asm.spine_track_entry_reset_rotation_directions).apply(null,arguments)}; -a._spine_track_entry_get_track_complete=function(){return(a._spine_track_entry_get_track_complete=a.asm.spine_track_entry_get_track_complete).apply(null,arguments)};a._spine_track_entry_was_applied=function(){return(a._spine_track_entry_was_applied=a.asm.spine_track_entry_was_applied).apply(null,arguments)};a._spine_track_entry_is_next_ready=function(){return(a._spine_track_entry_is_next_ready=a.asm.spine_track_entry_is_next_ready).apply(null,arguments)}; -a._spine_skeleton_update_cache=function(){return(a._spine_skeleton_update_cache=a.asm.spine_skeleton_update_cache).apply(null,arguments)};a._spine_skeleton_update_world_transform=function(){return(a._spine_skeleton_update_world_transform=a.asm.spine_skeleton_update_world_transform).apply(null,arguments)};a._spine_skeleton_update_world_transform_bone=function(){return(a._spine_skeleton_update_world_transform_bone=a.asm.spine_skeleton_update_world_transform_bone).apply(null,arguments)}; -a._spine_skeleton_set_to_setup_pose=function(){return(a._spine_skeleton_set_to_setup_pose=a.asm.spine_skeleton_set_to_setup_pose).apply(null,arguments)};a._spine_skeleton_set_bones_to_setup_pose=function(){return(a._spine_skeleton_set_bones_to_setup_pose=a.asm.spine_skeleton_set_bones_to_setup_pose).apply(null,arguments)};a._spine_skeleton_set_slots_to_setup_pose=function(){return(a._spine_skeleton_set_slots_to_setup_pose=a.asm.spine_skeleton_set_slots_to_setup_pose).apply(null,arguments)}; -a._spine_skeleton_find_bone=function(){return(a._spine_skeleton_find_bone=a.asm.spine_skeleton_find_bone).apply(null,arguments)};a._spine_skeleton_find_slot=function(){return(a._spine_skeleton_find_slot=a.asm.spine_skeleton_find_slot).apply(null,arguments)};a._spine_skeleton_set_skin_by_name=function(){return(a._spine_skeleton_set_skin_by_name=a.asm.spine_skeleton_set_skin_by_name).apply(null,arguments)}; -a._spine_skeleton_set_skin=function(){return(a._spine_skeleton_set_skin=a.asm.spine_skeleton_set_skin).apply(null,arguments)};a._spine_skeleton_get_attachment_by_name=function(){return(a._spine_skeleton_get_attachment_by_name=a.asm.spine_skeleton_get_attachment_by_name).apply(null,arguments)};a._spine_skeleton_get_attachment=function(){return(a._spine_skeleton_get_attachment=a.asm.spine_skeleton_get_attachment).apply(null,arguments)}; -a._spine_skeleton_set_attachment=function(){return(a._spine_skeleton_set_attachment=a.asm.spine_skeleton_set_attachment).apply(null,arguments)};a._spine_skeleton_find_ik_constraint=function(){return(a._spine_skeleton_find_ik_constraint=a.asm.spine_skeleton_find_ik_constraint).apply(null,arguments)};a._spine_skeleton_find_transform_constraint=function(){return(a._spine_skeleton_find_transform_constraint=a.asm.spine_skeleton_find_transform_constraint).apply(null,arguments)}; -a._spine_skeleton_find_path_constraint=function(){return(a._spine_skeleton_find_path_constraint=a.asm.spine_skeleton_find_path_constraint).apply(null,arguments)};a._spine_skeleton_find_physics_constraint=function(){return(a._spine_skeleton_find_physics_constraint=a.asm.spine_skeleton_find_physics_constraint).apply(null,arguments)};a._spine_skeleton_get_bounds=function(){return(a._spine_skeleton_get_bounds=a.asm.spine_skeleton_get_bounds).apply(null,arguments)}; -a._spine_skeleton_get_root_bone=function(){return(a._spine_skeleton_get_root_bone=a.asm.spine_skeleton_get_root_bone).apply(null,arguments)};a._spine_skeleton_get_data=function(){return(a._spine_skeleton_get_data=a.asm.spine_skeleton_get_data).apply(null,arguments)};a._spine_skeleton_get_num_bones=function(){return(a._spine_skeleton_get_num_bones=a.asm.spine_skeleton_get_num_bones).apply(null,arguments)}; -a._spine_skeleton_get_bones=function(){return(a._spine_skeleton_get_bones=a.asm.spine_skeleton_get_bones).apply(null,arguments)};a._spine_skeleton_get_num_slots=function(){return(a._spine_skeleton_get_num_slots=a.asm.spine_skeleton_get_num_slots).apply(null,arguments)};a._spine_skeleton_get_slots=function(){return(a._spine_skeleton_get_slots=a.asm.spine_skeleton_get_slots).apply(null,arguments)}; -a._spine_skeleton_get_num_draw_order=function(){return(a._spine_skeleton_get_num_draw_order=a.asm.spine_skeleton_get_num_draw_order).apply(null,arguments)};a._spine_skeleton_get_draw_order=function(){return(a._spine_skeleton_get_draw_order=a.asm.spine_skeleton_get_draw_order).apply(null,arguments)};a._spine_skeleton_get_num_ik_constraints=function(){return(a._spine_skeleton_get_num_ik_constraints=a.asm.spine_skeleton_get_num_ik_constraints).apply(null,arguments)}; -a._spine_skeleton_get_ik_constraints=function(){return(a._spine_skeleton_get_ik_constraints=a.asm.spine_skeleton_get_ik_constraints).apply(null,arguments)};a._spine_skeleton_get_num_transform_constraints=function(){return(a._spine_skeleton_get_num_transform_constraints=a.asm.spine_skeleton_get_num_transform_constraints).apply(null,arguments)}; -a._spine_skeleton_get_transform_constraints=function(){return(a._spine_skeleton_get_transform_constraints=a.asm.spine_skeleton_get_transform_constraints).apply(null,arguments)};a._spine_skeleton_get_num_path_constraints=function(){return(a._spine_skeleton_get_num_path_constraints=a.asm.spine_skeleton_get_num_path_constraints).apply(null,arguments)}; -a._spine_skeleton_get_path_constraints=function(){return(a._spine_skeleton_get_path_constraints=a.asm.spine_skeleton_get_path_constraints).apply(null,arguments)};a._spine_skeleton_get_num_physics_constraints=function(){return(a._spine_skeleton_get_num_physics_constraints=a.asm.spine_skeleton_get_num_physics_constraints).apply(null,arguments)}; -a._spine_skeleton_get_physics_constraints=function(){return(a._spine_skeleton_get_physics_constraints=a.asm.spine_skeleton_get_physics_constraints).apply(null,arguments)};a._spine_skeleton_get_skin=function(){return(a._spine_skeleton_get_skin=a.asm.spine_skeleton_get_skin).apply(null,arguments)};a._spine_skeleton_get_color=function(){return(a._spine_skeleton_get_color=a.asm.spine_skeleton_get_color).apply(null,arguments)}; -a._spine_skeleton_set_color=function(){return(a._spine_skeleton_set_color=a.asm.spine_skeleton_set_color).apply(null,arguments)};a._spine_skeleton_set_position=function(){return(a._spine_skeleton_set_position=a.asm.spine_skeleton_set_position).apply(null,arguments)};a._spine_skeleton_get_x=function(){return(a._spine_skeleton_get_x=a.asm.spine_skeleton_get_x).apply(null,arguments)};a._spine_skeleton_set_x=function(){return(a._spine_skeleton_set_x=a.asm.spine_skeleton_set_x).apply(null,arguments)}; -a._spine_skeleton_get_y=function(){return(a._spine_skeleton_get_y=a.asm.spine_skeleton_get_y).apply(null,arguments)};a._spine_skeleton_set_y=function(){return(a._spine_skeleton_set_y=a.asm.spine_skeleton_set_y).apply(null,arguments)};a._spine_skeleton_set_scale=function(){return(a._spine_skeleton_set_scale=a.asm.spine_skeleton_set_scale).apply(null,arguments)};a._spine_skeleton_get_scale_x=function(){return(a._spine_skeleton_get_scale_x=a.asm.spine_skeleton_get_scale_x).apply(null,arguments)}; -a._spine_skeleton_set_scale_x=function(){return(a._spine_skeleton_set_scale_x=a.asm.spine_skeleton_set_scale_x).apply(null,arguments)};a._spine_skeleton_get_scale_y=function(){return(a._spine_skeleton_get_scale_y=a.asm.spine_skeleton_get_scale_y).apply(null,arguments)};a._spine_skeleton_set_scale_y=function(){return(a._spine_skeleton_set_scale_y=a.asm.spine_skeleton_set_scale_y).apply(null,arguments)}; -a._spine_skeleton_get_time=function(){return(a._spine_skeleton_get_time=a.asm.spine_skeleton_get_time).apply(null,arguments)};a._spine_skeleton_set_time=function(){return(a._spine_skeleton_set_time=a.asm.spine_skeleton_set_time).apply(null,arguments)};a._spine_skeleton_update=function(){return(a._spine_skeleton_update=a.asm.spine_skeleton_update).apply(null,arguments)};a._spine_event_data_get_name=function(){return(a._spine_event_data_get_name=a.asm.spine_event_data_get_name).apply(null,arguments)}; -a._spine_event_data_get_int_value=function(){return(a._spine_event_data_get_int_value=a.asm.spine_event_data_get_int_value).apply(null,arguments)};a._spine_event_data_set_int_value=function(){return(a._spine_event_data_set_int_value=a.asm.spine_event_data_set_int_value).apply(null,arguments)};a._spine_event_data_get_float_value=function(){return(a._spine_event_data_get_float_value=a.asm.spine_event_data_get_float_value).apply(null,arguments)}; -a._spine_event_data_set_float_value=function(){return(a._spine_event_data_set_float_value=a.asm.spine_event_data_set_float_value).apply(null,arguments)};a._spine_event_data_get_string_value=function(){return(a._spine_event_data_get_string_value=a.asm.spine_event_data_get_string_value).apply(null,arguments)};a._spine_event_data_set_string_value=function(){return(a._spine_event_data_set_string_value=a.asm.spine_event_data_set_string_value).apply(null,arguments)}; -a._spine_event_data_get_audio_path=function(){return(a._spine_event_data_get_audio_path=a.asm.spine_event_data_get_audio_path).apply(null,arguments)};a._spine_event_data_get_volume=function(){return(a._spine_event_data_get_volume=a.asm.spine_event_data_get_volume).apply(null,arguments)};a._spine_event_data_set_volume=function(){return(a._spine_event_data_set_volume=a.asm.spine_event_data_set_volume).apply(null,arguments)}; -a._spine_event_data_get_balance=function(){return(a._spine_event_data_get_balance=a.asm.spine_event_data_get_balance).apply(null,arguments)};a._spine_event_data_set_balance=function(){return(a._spine_event_data_set_balance=a.asm.spine_event_data_set_balance).apply(null,arguments)};a._spine_event_get_data=function(){return(a._spine_event_get_data=a.asm.spine_event_get_data).apply(null,arguments)}; -a._spine_event_get_time=function(){return(a._spine_event_get_time=a.asm.spine_event_get_time).apply(null,arguments)};a._spine_event_get_int_value=function(){return(a._spine_event_get_int_value=a.asm.spine_event_get_int_value).apply(null,arguments)};a._spine_event_set_int_value=function(){return(a._spine_event_set_int_value=a.asm.spine_event_set_int_value).apply(null,arguments)}; -a._spine_event_get_float_value=function(){return(a._spine_event_get_float_value=a.asm.spine_event_get_float_value).apply(null,arguments)};a._spine_event_set_float_value=function(){return(a._spine_event_set_float_value=a.asm.spine_event_set_float_value).apply(null,arguments)};a._spine_event_get_string_value=function(){return(a._spine_event_get_string_value=a.asm.spine_event_get_string_value).apply(null,arguments)}; -a._spine_event_set_string_value=function(){return(a._spine_event_set_string_value=a.asm.spine_event_set_string_value).apply(null,arguments)};a._spine_event_get_volume=function(){return(a._spine_event_get_volume=a.asm.spine_event_get_volume).apply(null,arguments)};a._spine_event_set_volume=function(){return(a._spine_event_set_volume=a.asm.spine_event_set_volume).apply(null,arguments)}; -a._spine_event_get_balance=function(){return(a._spine_event_get_balance=a.asm.spine_event_get_balance).apply(null,arguments)};a._spine_event_set_balance=function(){return(a._spine_event_set_balance=a.asm.spine_event_set_balance).apply(null,arguments)};a._spine_slot_data_get_index=function(){return(a._spine_slot_data_get_index=a.asm.spine_slot_data_get_index).apply(null,arguments)}; -a._spine_slot_data_get_name=function(){return(a._spine_slot_data_get_name=a.asm.spine_slot_data_get_name).apply(null,arguments)};a._spine_slot_data_get_bone_data=function(){return(a._spine_slot_data_get_bone_data=a.asm.spine_slot_data_get_bone_data).apply(null,arguments)};a._spine_slot_data_get_color=function(){return(a._spine_slot_data_get_color=a.asm.spine_slot_data_get_color).apply(null,arguments)}; -a._spine_slot_data_set_color=function(){return(a._spine_slot_data_set_color=a.asm.spine_slot_data_set_color).apply(null,arguments)};a._spine_slot_data_get_dark_color=function(){return(a._spine_slot_data_get_dark_color=a.asm.spine_slot_data_get_dark_color).apply(null,arguments)};a._spine_slot_data_set_dark_color=function(){return(a._spine_slot_data_set_dark_color=a.asm.spine_slot_data_set_dark_color).apply(null,arguments)}; -a._spine_slot_data_get_has_dark_color=function(){return(a._spine_slot_data_get_has_dark_color=a.asm.spine_slot_data_get_has_dark_color).apply(null,arguments)};a._spine_slot_data_set_has_dark_color=function(){return(a._spine_slot_data_set_has_dark_color=a.asm.spine_slot_data_set_has_dark_color).apply(null,arguments)};a._spine_slot_data_get_attachment_name=function(){return(a._spine_slot_data_get_attachment_name=a.asm.spine_slot_data_get_attachment_name).apply(null,arguments)}; -a._spine_slot_data_set_attachment_name=function(){return(a._spine_slot_data_set_attachment_name=a.asm.spine_slot_data_set_attachment_name).apply(null,arguments)};a._spine_slot_data_get_blend_mode=function(){return(a._spine_slot_data_get_blend_mode=a.asm.spine_slot_data_get_blend_mode).apply(null,arguments)};a._spine_slot_data_set_blend_mode=function(){return(a._spine_slot_data_set_blend_mode=a.asm.spine_slot_data_set_blend_mode).apply(null,arguments)}; -a._spine_slot_data_is_visible=function(){return(a._spine_slot_data_is_visible=a.asm.spine_slot_data_is_visible).apply(null,arguments)};a._spine_slot_data_set_visible=function(){return(a._spine_slot_data_set_visible=a.asm.spine_slot_data_set_visible).apply(null,arguments)};a._spine_slot_set_to_setup_pose=function(){return(a._spine_slot_set_to_setup_pose=a.asm.spine_slot_set_to_setup_pose).apply(null,arguments)}; -a._spine_slot_get_data=function(){return(a._spine_slot_get_data=a.asm.spine_slot_get_data).apply(null,arguments)};a._spine_slot_get_bone=function(){return(a._spine_slot_get_bone=a.asm.spine_slot_get_bone).apply(null,arguments)};a._spine_slot_get_skeleton=function(){return(a._spine_slot_get_skeleton=a.asm.spine_slot_get_skeleton).apply(null,arguments)};a._spine_slot_get_color=function(){return(a._spine_slot_get_color=a.asm.spine_slot_get_color).apply(null,arguments)}; -a._spine_slot_set_color=function(){return(a._spine_slot_set_color=a.asm.spine_slot_set_color).apply(null,arguments)};a._spine_slot_get_dark_color=function(){return(a._spine_slot_get_dark_color=a.asm.spine_slot_get_dark_color).apply(null,arguments)};a._spine_slot_set_dark_color=function(){return(a._spine_slot_set_dark_color=a.asm.spine_slot_set_dark_color).apply(null,arguments)}; -a._spine_slot_has_dark_color=function(){return(a._spine_slot_has_dark_color=a.asm.spine_slot_has_dark_color).apply(null,arguments)};a._spine_slot_get_attachment=function(){return(a._spine_slot_get_attachment=a.asm.spine_slot_get_attachment).apply(null,arguments)};a._spine_slot_set_attachment=function(){return(a._spine_slot_set_attachment=a.asm.spine_slot_set_attachment).apply(null,arguments)}; -a._spine_slot_get_sequence_index=function(){return(a._spine_slot_get_sequence_index=a.asm.spine_slot_get_sequence_index).apply(null,arguments)};a._spine_slot_set_sequence_index=function(){return(a._spine_slot_set_sequence_index=a.asm.spine_slot_set_sequence_index).apply(null,arguments)};a._spine_bone_data_get_index=function(){return(a._spine_bone_data_get_index=a.asm.spine_bone_data_get_index).apply(null,arguments)}; -a._spine_bone_data_get_name=function(){return(a._spine_bone_data_get_name=a.asm.spine_bone_data_get_name).apply(null,arguments)};a._spine_bone_data_get_parent=function(){return(a._spine_bone_data_get_parent=a.asm.spine_bone_data_get_parent).apply(null,arguments)};a._spine_bone_data_get_length=function(){return(a._spine_bone_data_get_length=a.asm.spine_bone_data_get_length).apply(null,arguments)}; -a._spine_bone_data_set_length=function(){return(a._spine_bone_data_set_length=a.asm.spine_bone_data_set_length).apply(null,arguments)};a._spine_bone_data_get_x=function(){return(a._spine_bone_data_get_x=a.asm.spine_bone_data_get_x).apply(null,arguments)};a._spine_bone_data_set_x=function(){return(a._spine_bone_data_set_x=a.asm.spine_bone_data_set_x).apply(null,arguments)};a._spine_bone_data_get_y=function(){return(a._spine_bone_data_get_y=a.asm.spine_bone_data_get_y).apply(null,arguments)}; -a._spine_bone_data_set_y=function(){return(a._spine_bone_data_set_y=a.asm.spine_bone_data_set_y).apply(null,arguments)};a._spine_bone_data_get_rotation=function(){return(a._spine_bone_data_get_rotation=a.asm.spine_bone_data_get_rotation).apply(null,arguments)};a._spine_bone_data_set_rotation=function(){return(a._spine_bone_data_set_rotation=a.asm.spine_bone_data_set_rotation).apply(null,arguments)}; -a._spine_bone_data_get_scale_x=function(){return(a._spine_bone_data_get_scale_x=a.asm.spine_bone_data_get_scale_x).apply(null,arguments)};a._spine_bone_data_set_scale_x=function(){return(a._spine_bone_data_set_scale_x=a.asm.spine_bone_data_set_scale_x).apply(null,arguments)};a._spine_bone_data_get_scale_y=function(){return(a._spine_bone_data_get_scale_y=a.asm.spine_bone_data_get_scale_y).apply(null,arguments)}; -a._spine_bone_data_set_scale_y=function(){return(a._spine_bone_data_set_scale_y=a.asm.spine_bone_data_set_scale_y).apply(null,arguments)};a._spine_bone_data_get_shear_x=function(){return(a._spine_bone_data_get_shear_x=a.asm.spine_bone_data_get_shear_x).apply(null,arguments)};a._spine_bone_data_set_shear_x=function(){return(a._spine_bone_data_set_shear_x=a.asm.spine_bone_data_set_shear_x).apply(null,arguments)}; -a._spine_bone_data_get_shear_y=function(){return(a._spine_bone_data_get_shear_y=a.asm.spine_bone_data_get_shear_y).apply(null,arguments)};a._spine_bone_data_set_shear_y=function(){return(a._spine_bone_data_set_shear_y=a.asm.spine_bone_data_set_shear_y).apply(null,arguments)};a._spine_bone_data_get_inherit=function(){return(a._spine_bone_data_get_inherit=a.asm.spine_bone_data_get_inherit).apply(null,arguments)}; -a._spine_bone_data_set_inherit=function(){return(a._spine_bone_data_set_inherit=a.asm.spine_bone_data_set_inherit).apply(null,arguments)};a._spine_bone_data_get_is_skin_required=function(){return(a._spine_bone_data_get_is_skin_required=a.asm.spine_bone_data_get_is_skin_required).apply(null,arguments)};a._spine_bone_data_set_is_skin_required=function(){return(a._spine_bone_data_set_is_skin_required=a.asm.spine_bone_data_set_is_skin_required).apply(null,arguments)}; -a._spine_bone_data_get_color=function(){return(a._spine_bone_data_get_color=a.asm.spine_bone_data_get_color).apply(null,arguments)};a._spine_bone_data_set_color=function(){return(a._spine_bone_data_set_color=a.asm.spine_bone_data_set_color).apply(null,arguments)};a._spine_bone_data_is_visible=function(){return(a._spine_bone_data_is_visible=a.asm.spine_bone_data_is_visible).apply(null,arguments)}; -a._spine_bone_data_set_visible=function(){return(a._spine_bone_data_set_visible=a.asm.spine_bone_data_set_visible).apply(null,arguments)};a._spine_bone_set_is_y_down=function(){return(a._spine_bone_set_is_y_down=a.asm.spine_bone_set_is_y_down).apply(null,arguments)};a._spine_bone_get_is_y_down=function(){return(a._spine_bone_get_is_y_down=a.asm.spine_bone_get_is_y_down).apply(null,arguments)};a._spine_bone_update=function(){return(a._spine_bone_update=a.asm.spine_bone_update).apply(null,arguments)}; -a._spine_bone_update_world_transform=function(){return(a._spine_bone_update_world_transform=a.asm.spine_bone_update_world_transform).apply(null,arguments)};a._spine_bone_update_world_transform_with=function(){return(a._spine_bone_update_world_transform_with=a.asm.spine_bone_update_world_transform_with).apply(null,arguments)};a._spine_bone_update_applied_transform=function(){return(a._spine_bone_update_applied_transform=a.asm.spine_bone_update_applied_transform).apply(null,arguments)}; -a._spine_bone_set_to_setup_pose=function(){return(a._spine_bone_set_to_setup_pose=a.asm.spine_bone_set_to_setup_pose).apply(null,arguments)};a._spine_bone_world_to_local=function(){return(a._spine_bone_world_to_local=a.asm.spine_bone_world_to_local).apply(null,arguments)};a._spine_bone_world_to_parent=function(){return(a._spine_bone_world_to_parent=a.asm.spine_bone_world_to_parent).apply(null,arguments)}; -a._spine_bone_local_to_world=function(){return(a._spine_bone_local_to_world=a.asm.spine_bone_local_to_world).apply(null,arguments)};a._spine_bone_parent_to_world=function(){return(a._spine_bone_parent_to_world=a.asm.spine_bone_parent_to_world).apply(null,arguments)};a._spine_bone_world_to_local_rotation=function(){return(a._spine_bone_world_to_local_rotation=a.asm.spine_bone_world_to_local_rotation).apply(null,arguments)}; -a._spine_bone_local_to_world_rotation=function(){return(a._spine_bone_local_to_world_rotation=a.asm.spine_bone_local_to_world_rotation).apply(null,arguments)};a._spine_bone_rotate_world=function(){return(a._spine_bone_rotate_world=a.asm.spine_bone_rotate_world).apply(null,arguments)};a._spine_bone_get_world_to_local_rotation_x=function(){return(a._spine_bone_get_world_to_local_rotation_x=a.asm.spine_bone_get_world_to_local_rotation_x).apply(null,arguments)}; -a._spine_bone_get_world_to_local_rotation_y=function(){return(a._spine_bone_get_world_to_local_rotation_y=a.asm.spine_bone_get_world_to_local_rotation_y).apply(null,arguments)};a._spine_bone_get_data=function(){return(a._spine_bone_get_data=a.asm.spine_bone_get_data).apply(null,arguments)};a._spine_bone_get_skeleton=function(){return(a._spine_bone_get_skeleton=a.asm.spine_bone_get_skeleton).apply(null,arguments)}; -a._spine_bone_get_parent=function(){return(a._spine_bone_get_parent=a.asm.spine_bone_get_parent).apply(null,arguments)};a._spine_bone_get_num_children=function(){return(a._spine_bone_get_num_children=a.asm.spine_bone_get_num_children).apply(null,arguments)};a._spine_bone_get_children=function(){return(a._spine_bone_get_children=a.asm.spine_bone_get_children).apply(null,arguments)};a._spine_bone_get_x=function(){return(a._spine_bone_get_x=a.asm.spine_bone_get_x).apply(null,arguments)}; -a._spine_bone_set_x=function(){return(a._spine_bone_set_x=a.asm.spine_bone_set_x).apply(null,arguments)};a._spine_bone_get_y=function(){return(a._spine_bone_get_y=a.asm.spine_bone_get_y).apply(null,arguments)};a._spine_bone_set_y=function(){return(a._spine_bone_set_y=a.asm.spine_bone_set_y).apply(null,arguments)};a._spine_bone_get_rotation=function(){return(a._spine_bone_get_rotation=a.asm.spine_bone_get_rotation).apply(null,arguments)}; -a._spine_bone_set_rotation=function(){return(a._spine_bone_set_rotation=a.asm.spine_bone_set_rotation).apply(null,arguments)};a._spine_bone_get_scale_x=function(){return(a._spine_bone_get_scale_x=a.asm.spine_bone_get_scale_x).apply(null,arguments)};a._spine_bone_set_scale_x=function(){return(a._spine_bone_set_scale_x=a.asm.spine_bone_set_scale_x).apply(null,arguments)};a._spine_bone_get_scale_y=function(){return(a._spine_bone_get_scale_y=a.asm.spine_bone_get_scale_y).apply(null,arguments)}; -a._spine_bone_set_scale_y=function(){return(a._spine_bone_set_scale_y=a.asm.spine_bone_set_scale_y).apply(null,arguments)};a._spine_bone_get_shear_x=function(){return(a._spine_bone_get_shear_x=a.asm.spine_bone_get_shear_x).apply(null,arguments)};a._spine_bone_set_shear_x=function(){return(a._spine_bone_set_shear_x=a.asm.spine_bone_set_shear_x).apply(null,arguments)};a._spine_bone_get_shear_y=function(){return(a._spine_bone_get_shear_y=a.asm.spine_bone_get_shear_y).apply(null,arguments)}; -a._spine_bone_set_shear_y=function(){return(a._spine_bone_set_shear_y=a.asm.spine_bone_set_shear_y).apply(null,arguments)};a._spine_bone_get_applied_rotation=function(){return(a._spine_bone_get_applied_rotation=a.asm.spine_bone_get_applied_rotation).apply(null,arguments)};a._spine_bone_set_applied_rotation=function(){return(a._spine_bone_set_applied_rotation=a.asm.spine_bone_set_applied_rotation).apply(null,arguments)}; -a._spine_bone_get_a_x=function(){return(a._spine_bone_get_a_x=a.asm.spine_bone_get_a_x).apply(null,arguments)};a._spine_bone_set_a_x=function(){return(a._spine_bone_set_a_x=a.asm.spine_bone_set_a_x).apply(null,arguments)};a._spine_bone_get_a_y=function(){return(a._spine_bone_get_a_y=a.asm.spine_bone_get_a_y).apply(null,arguments)};a._spine_bone_set_a_y=function(){return(a._spine_bone_set_a_y=a.asm.spine_bone_set_a_y).apply(null,arguments)}; -a._spine_bone_get_a_scale_x=function(){return(a._spine_bone_get_a_scale_x=a.asm.spine_bone_get_a_scale_x).apply(null,arguments)};a._spine_bone_set_a_scale_x=function(){return(a._spine_bone_set_a_scale_x=a.asm.spine_bone_set_a_scale_x).apply(null,arguments)};a._spine_bone_get_a_scale_y=function(){return(a._spine_bone_get_a_scale_y=a.asm.spine_bone_get_a_scale_y).apply(null,arguments)}; -a._spine_bone_set_a_scale_y=function(){return(a._spine_bone_set_a_scale_y=a.asm.spine_bone_set_a_scale_y).apply(null,arguments)};a._spine_bone_get_a_shear_x=function(){return(a._spine_bone_get_a_shear_x=a.asm.spine_bone_get_a_shear_x).apply(null,arguments)};a._spine_bone_set_a_shear_x=function(){return(a._spine_bone_set_a_shear_x=a.asm.spine_bone_set_a_shear_x).apply(null,arguments)}; -a._spine_bone_get_a_shear_y=function(){return(a._spine_bone_get_a_shear_y=a.asm.spine_bone_get_a_shear_y).apply(null,arguments)};a._spine_bone_set_a_shear_y=function(){return(a._spine_bone_set_a_shear_y=a.asm.spine_bone_set_a_shear_y).apply(null,arguments)};a._spine_bone_get_a=function(){return(a._spine_bone_get_a=a.asm.spine_bone_get_a).apply(null,arguments)};a._spine_bone_set_a=function(){return(a._spine_bone_set_a=a.asm.spine_bone_set_a).apply(null,arguments)}; -a._spine_bone_get_b=function(){return(a._spine_bone_get_b=a.asm.spine_bone_get_b).apply(null,arguments)};a._spine_bone_set_b=function(){return(a._spine_bone_set_b=a.asm.spine_bone_set_b).apply(null,arguments)};a._spine_bone_get_c=function(){return(a._spine_bone_get_c=a.asm.spine_bone_get_c).apply(null,arguments)};a._spine_bone_set_c=function(){return(a._spine_bone_set_c=a.asm.spine_bone_set_c).apply(null,arguments)}; -a._spine_bone_get_d=function(){return(a._spine_bone_get_d=a.asm.spine_bone_get_d).apply(null,arguments)};a._spine_bone_set_d=function(){return(a._spine_bone_set_d=a.asm.spine_bone_set_d).apply(null,arguments)};a._spine_bone_get_world_x=function(){return(a._spine_bone_get_world_x=a.asm.spine_bone_get_world_x).apply(null,arguments)};a._spine_bone_set_world_x=function(){return(a._spine_bone_set_world_x=a.asm.spine_bone_set_world_x).apply(null,arguments)}; -a._spine_bone_get_world_y=function(){return(a._spine_bone_get_world_y=a.asm.spine_bone_get_world_y).apply(null,arguments)};a._spine_bone_set_world_y=function(){return(a._spine_bone_set_world_y=a.asm.spine_bone_set_world_y).apply(null,arguments)};a._spine_bone_get_world_rotation_x=function(){return(a._spine_bone_get_world_rotation_x=a.asm.spine_bone_get_world_rotation_x).apply(null,arguments)}; -a._spine_bone_get_world_rotation_y=function(){return(a._spine_bone_get_world_rotation_y=a.asm.spine_bone_get_world_rotation_y).apply(null,arguments)};a._spine_bone_get_world_scale_x=function(){return(a._spine_bone_get_world_scale_x=a.asm.spine_bone_get_world_scale_x).apply(null,arguments)};a._spine_bone_get_world_scale_y=function(){return(a._spine_bone_get_world_scale_y=a.asm.spine_bone_get_world_scale_y).apply(null,arguments)}; -a._spine_bone_get_is_active=function(){return(a._spine_bone_get_is_active=a.asm.spine_bone_get_is_active).apply(null,arguments)};a._spine_bone_set_is_active=function(){return(a._spine_bone_set_is_active=a.asm.spine_bone_set_is_active).apply(null,arguments)};a._spine_bone_get_inherit=function(){return(a._spine_bone_get_inherit=a.asm.spine_bone_get_inherit).apply(null,arguments)};a._spine_bone_set_inherit=function(){return(a._spine_bone_set_inherit=a.asm.spine_bone_set_inherit).apply(null,arguments)}; -a._spine_attachment_get_name=function(){return(a._spine_attachment_get_name=a.asm.spine_attachment_get_name).apply(null,arguments)};a._spine_attachment_get_type=function(){return(a._spine_attachment_get_type=a.asm.spine_attachment_get_type).apply(null,arguments)};a._spine_attachment_copy=function(){return(a._spine_attachment_copy=a.asm.spine_attachment_copy).apply(null,arguments)}; -a._spine_attachment_cast_to_bounding_box_attachment=function(){return(a._spine_attachment_cast_to_bounding_box_attachment=a.asm.spine_attachment_cast_to_bounding_box_attachment).apply(null,arguments)};a._spine_attachment_dispose=function(){return(a._spine_attachment_dispose=a.asm.spine_attachment_dispose).apply(null,arguments)}; -a._spine_point_attachment_compute_world_position=function(){return(a._spine_point_attachment_compute_world_position=a.asm.spine_point_attachment_compute_world_position).apply(null,arguments)};a._spine_point_attachment_compute_world_rotation=function(){return(a._spine_point_attachment_compute_world_rotation=a.asm.spine_point_attachment_compute_world_rotation).apply(null,arguments)}; -a._spine_point_attachment_get_x=function(){return(a._spine_point_attachment_get_x=a.asm.spine_point_attachment_get_x).apply(null,arguments)};a._spine_point_attachment_set_x=function(){return(a._spine_point_attachment_set_x=a.asm.spine_point_attachment_set_x).apply(null,arguments)};a._spine_point_attachment_get_y=function(){return(a._spine_point_attachment_get_y=a.asm.spine_point_attachment_get_y).apply(null,arguments)}; -a._spine_point_attachment_set_y=function(){return(a._spine_point_attachment_set_y=a.asm.spine_point_attachment_set_y).apply(null,arguments)};a._spine_point_attachment_get_rotation=function(){return(a._spine_point_attachment_get_rotation=a.asm.spine_point_attachment_get_rotation).apply(null,arguments)};a._spine_point_attachment_set_rotation=function(){return(a._spine_point_attachment_set_rotation=a.asm.spine_point_attachment_set_rotation).apply(null,arguments)}; -a._spine_point_attachment_get_color=function(){return(a._spine_point_attachment_get_color=a.asm.spine_point_attachment_get_color).apply(null,arguments)};a._spine_point_attachment_set_color=function(){return(a._spine_point_attachment_set_color=a.asm.spine_point_attachment_set_color).apply(null,arguments)};a._spine_region_attachment_update_region=function(){return(a._spine_region_attachment_update_region=a.asm.spine_region_attachment_update_region).apply(null,arguments)}; -a._spine_region_attachment_compute_world_vertices=function(){return(a._spine_region_attachment_compute_world_vertices=a.asm.spine_region_attachment_compute_world_vertices).apply(null,arguments)};a._spine_region_attachment_get_x=function(){return(a._spine_region_attachment_get_x=a.asm.spine_region_attachment_get_x).apply(null,arguments)};a._spine_region_attachment_set_x=function(){return(a._spine_region_attachment_set_x=a.asm.spine_region_attachment_set_x).apply(null,arguments)}; -a._spine_region_attachment_get_y=function(){return(a._spine_region_attachment_get_y=a.asm.spine_region_attachment_get_y).apply(null,arguments)};a._spine_region_attachment_set_y=function(){return(a._spine_region_attachment_set_y=a.asm.spine_region_attachment_set_y).apply(null,arguments)};a._spine_region_attachment_get_rotation=function(){return(a._spine_region_attachment_get_rotation=a.asm.spine_region_attachment_get_rotation).apply(null,arguments)}; -a._spine_region_attachment_set_rotation=function(){return(a._spine_region_attachment_set_rotation=a.asm.spine_region_attachment_set_rotation).apply(null,arguments)};a._spine_region_attachment_get_scale_x=function(){return(a._spine_region_attachment_get_scale_x=a.asm.spine_region_attachment_get_scale_x).apply(null,arguments)};a._spine_region_attachment_set_scale_x=function(){return(a._spine_region_attachment_set_scale_x=a.asm.spine_region_attachment_set_scale_x).apply(null,arguments)}; -a._spine_region_attachment_get_scale_y=function(){return(a._spine_region_attachment_get_scale_y=a.asm.spine_region_attachment_get_scale_y).apply(null,arguments)};a._spine_region_attachment_set_scale_y=function(){return(a._spine_region_attachment_set_scale_y=a.asm.spine_region_attachment_set_scale_y).apply(null,arguments)};a._spine_region_attachment_get_width=function(){return(a._spine_region_attachment_get_width=a.asm.spine_region_attachment_get_width).apply(null,arguments)}; -a._spine_region_attachment_set_width=function(){return(a._spine_region_attachment_set_width=a.asm.spine_region_attachment_set_width).apply(null,arguments)};a._spine_region_attachment_get_height=function(){return(a._spine_region_attachment_get_height=a.asm.spine_region_attachment_get_height).apply(null,arguments)};a._spine_region_attachment_set_height=function(){return(a._spine_region_attachment_set_height=a.asm.spine_region_attachment_set_height).apply(null,arguments)}; -a._spine_region_attachment_get_color=function(){return(a._spine_region_attachment_get_color=a.asm.spine_region_attachment_get_color).apply(null,arguments)};a._spine_region_attachment_set_color=function(){return(a._spine_region_attachment_set_color=a.asm.spine_region_attachment_set_color).apply(null,arguments)};a._spine_region_attachment_get_path=function(){return(a._spine_region_attachment_get_path=a.asm.spine_region_attachment_get_path).apply(null,arguments)}; -a._spine_region_attachment_get_region=function(){return(a._spine_region_attachment_get_region=a.asm.spine_region_attachment_get_region).apply(null,arguments)};a._spine_region_attachment_get_sequence=function(){return(a._spine_region_attachment_get_sequence=a.asm.spine_region_attachment_get_sequence).apply(null,arguments)};a._spine_region_attachment_get_num_offset=function(){return(a._spine_region_attachment_get_num_offset=a.asm.spine_region_attachment_get_num_offset).apply(null,arguments)}; -a._spine_region_attachment_get_offset=function(){return(a._spine_region_attachment_get_offset=a.asm.spine_region_attachment_get_offset).apply(null,arguments)};a._spine_region_attachment_get_num_uvs=function(){return(a._spine_region_attachment_get_num_uvs=a.asm.spine_region_attachment_get_num_uvs).apply(null,arguments)};a._spine_region_attachment_get_uvs=function(){return(a._spine_region_attachment_get_uvs=a.asm.spine_region_attachment_get_uvs).apply(null,arguments)}; -a._spine_vertex_attachment_get_world_vertices_length=function(){return(a._spine_vertex_attachment_get_world_vertices_length=a.asm.spine_vertex_attachment_get_world_vertices_length).apply(null,arguments)};a._spine_vertex_attachment_compute_world_vertices=function(){return(a._spine_vertex_attachment_compute_world_vertices=a.asm.spine_vertex_attachment_compute_world_vertices).apply(null,arguments)}; -a._spine_vertex_attachment_get_num_bones=function(){return(a._spine_vertex_attachment_get_num_bones=a.asm.spine_vertex_attachment_get_num_bones).apply(null,arguments)};a._spine_vertex_attachment_get_bones=function(){return(a._spine_vertex_attachment_get_bones=a.asm.spine_vertex_attachment_get_bones).apply(null,arguments)};a._spine_vertex_attachment_get_num_vertices=function(){return(a._spine_vertex_attachment_get_num_vertices=a.asm.spine_vertex_attachment_get_num_vertices).apply(null,arguments)}; -a._spine_vertex_attachment_get_vertices=function(){return(a._spine_vertex_attachment_get_vertices=a.asm.spine_vertex_attachment_get_vertices).apply(null,arguments)};a._spine_vertex_attachment_get_timeline_attachment=function(){return(a._spine_vertex_attachment_get_timeline_attachment=a.asm.spine_vertex_attachment_get_timeline_attachment).apply(null,arguments)}; -a._spine_vertex_attachment_set_timeline_attachment=function(){return(a._spine_vertex_attachment_set_timeline_attachment=a.asm.spine_vertex_attachment_set_timeline_attachment).apply(null,arguments)};a._spine_mesh_attachment_update_region=function(){return(a._spine_mesh_attachment_update_region=a.asm.spine_mesh_attachment_update_region).apply(null,arguments)}; -a._spine_mesh_attachment_get_hull_length=function(){return(a._spine_mesh_attachment_get_hull_length=a.asm.spine_mesh_attachment_get_hull_length).apply(null,arguments)};a._spine_mesh_attachment_set_hull_length=function(){return(a._spine_mesh_attachment_set_hull_length=a.asm.spine_mesh_attachment_set_hull_length).apply(null,arguments)}; -a._spine_mesh_attachment_get_num_region_uvs=function(){return(a._spine_mesh_attachment_get_num_region_uvs=a.asm.spine_mesh_attachment_get_num_region_uvs).apply(null,arguments)};a._spine_mesh_attachment_get_region_uvs=function(){return(a._spine_mesh_attachment_get_region_uvs=a.asm.spine_mesh_attachment_get_region_uvs).apply(null,arguments)};a._spine_mesh_attachment_get_num_uvs=function(){return(a._spine_mesh_attachment_get_num_uvs=a.asm.spine_mesh_attachment_get_num_uvs).apply(null,arguments)}; -a._spine_mesh_attachment_get_uvs=function(){return(a._spine_mesh_attachment_get_uvs=a.asm.spine_mesh_attachment_get_uvs).apply(null,arguments)};a._spine_mesh_attachment_get_num_triangles=function(){return(a._spine_mesh_attachment_get_num_triangles=a.asm.spine_mesh_attachment_get_num_triangles).apply(null,arguments)};a._spine_mesh_attachment_get_triangles=function(){return(a._spine_mesh_attachment_get_triangles=a.asm.spine_mesh_attachment_get_triangles).apply(null,arguments)}; -a._spine_mesh_attachment_get_color=function(){return(a._spine_mesh_attachment_get_color=a.asm.spine_mesh_attachment_get_color).apply(null,arguments)};a._spine_mesh_attachment_set_color=function(){return(a._spine_mesh_attachment_set_color=a.asm.spine_mesh_attachment_set_color).apply(null,arguments)};a._spine_mesh_attachment_get_path=function(){return(a._spine_mesh_attachment_get_path=a.asm.spine_mesh_attachment_get_path).apply(null,arguments)}; -a._spine_mesh_attachment_get_region=function(){return(a._spine_mesh_attachment_get_region=a.asm.spine_mesh_attachment_get_region).apply(null,arguments)};a._spine_mesh_attachment_get_sequence=function(){return(a._spine_mesh_attachment_get_sequence=a.asm.spine_mesh_attachment_get_sequence).apply(null,arguments)};a._spine_mesh_attachment_get_parent_mesh=function(){return(a._spine_mesh_attachment_get_parent_mesh=a.asm.spine_mesh_attachment_get_parent_mesh).apply(null,arguments)}; -a._spine_mesh_attachment_set_parent_mesh=function(){return(a._spine_mesh_attachment_set_parent_mesh=a.asm.spine_mesh_attachment_set_parent_mesh).apply(null,arguments)};a._spine_mesh_attachment_get_num_edges=function(){return(a._spine_mesh_attachment_get_num_edges=a.asm.spine_mesh_attachment_get_num_edges).apply(null,arguments)};a._spine_mesh_attachment_get_edges=function(){return(a._spine_mesh_attachment_get_edges=a.asm.spine_mesh_attachment_get_edges).apply(null,arguments)}; -a._spine_mesh_attachment_get_width=function(){return(a._spine_mesh_attachment_get_width=a.asm.spine_mesh_attachment_get_width).apply(null,arguments)};a._spine_mesh_attachment_set_width=function(){return(a._spine_mesh_attachment_set_width=a.asm.spine_mesh_attachment_set_width).apply(null,arguments)};a._spine_mesh_attachment_get_height=function(){return(a._spine_mesh_attachment_get_height=a.asm.spine_mesh_attachment_get_height).apply(null,arguments)}; -a._spine_mesh_attachment_set_height=function(){return(a._spine_mesh_attachment_set_height=a.asm.spine_mesh_attachment_set_height).apply(null,arguments)};a._spine_clipping_attachment_get_end_slot=function(){return(a._spine_clipping_attachment_get_end_slot=a.asm.spine_clipping_attachment_get_end_slot).apply(null,arguments)};a._spine_clipping_attachment_set_end_slot=function(){return(a._spine_clipping_attachment_set_end_slot=a.asm.spine_clipping_attachment_set_end_slot).apply(null,arguments)}; -a._spine_clipping_attachment_get_color=function(){return(a._spine_clipping_attachment_get_color=a.asm.spine_clipping_attachment_get_color).apply(null,arguments)};a._spine_clipping_attachment_set_color=function(){return(a._spine_clipping_attachment_set_color=a.asm.spine_clipping_attachment_set_color).apply(null,arguments)};a._spine_bounding_box_attachment_get_color=function(){return(a._spine_bounding_box_attachment_get_color=a.asm.spine_bounding_box_attachment_get_color).apply(null,arguments)}; -a._spine_bounding_box_attachment_set_color=function(){return(a._spine_bounding_box_attachment_set_color=a.asm.spine_bounding_box_attachment_set_color).apply(null,arguments)};a._spine_path_attachment_get_num_lengths=function(){return(a._spine_path_attachment_get_num_lengths=a.asm.spine_path_attachment_get_num_lengths).apply(null,arguments)};a._spine_path_attachment_get_lengths=function(){return(a._spine_path_attachment_get_lengths=a.asm.spine_path_attachment_get_lengths).apply(null,arguments)}; -a._spine_path_attachment_get_is_closed=function(){return(a._spine_path_attachment_get_is_closed=a.asm.spine_path_attachment_get_is_closed).apply(null,arguments)};a._spine_path_attachment_set_is_closed=function(){return(a._spine_path_attachment_set_is_closed=a.asm.spine_path_attachment_set_is_closed).apply(null,arguments)};a._spine_path_attachment_get_is_constant_speed=function(){return(a._spine_path_attachment_get_is_constant_speed=a.asm.spine_path_attachment_get_is_constant_speed).apply(null,arguments)}; -a._spine_path_attachment_set_is_constant_speed=function(){return(a._spine_path_attachment_set_is_constant_speed=a.asm.spine_path_attachment_set_is_constant_speed).apply(null,arguments)};a._spine_path_attachment_get_color=function(){return(a._spine_path_attachment_get_color=a.asm.spine_path_attachment_get_color).apply(null,arguments)};a._spine_path_attachment_set_color=function(){return(a._spine_path_attachment_set_color=a.asm.spine_path_attachment_set_color).apply(null,arguments)}; -a._spine_skin_set_attachment=function(){return(a._spine_skin_set_attachment=a.asm.spine_skin_set_attachment).apply(null,arguments)};a._spine_skin_get_attachment=function(){return(a._spine_skin_get_attachment=a.asm.spine_skin_get_attachment).apply(null,arguments)};a._spine_skin_remove_attachment=function(){return(a._spine_skin_remove_attachment=a.asm.spine_skin_remove_attachment).apply(null,arguments)}; -a._spine_skin_get_name=function(){return(a._spine_skin_get_name=a.asm.spine_skin_get_name).apply(null,arguments)};a._spine_skin_add_skin=function(){return(a._spine_skin_add_skin=a.asm.spine_skin_add_skin).apply(null,arguments)};a._spine_skin_copy_skin=function(){return(a._spine_skin_copy_skin=a.asm.spine_skin_copy_skin).apply(null,arguments)};a._spine_skin_get_entries=function(){return(a._spine_skin_get_entries=a.asm.spine_skin_get_entries).apply(null,arguments)}; -a._spine_skin_entries_get_num_entries=function(){return(a._spine_skin_entries_get_num_entries=a.asm.spine_skin_entries_get_num_entries).apply(null,arguments)};a._spine_skin_entries_get_entry=function(){return(a._spine_skin_entries_get_entry=a.asm.spine_skin_entries_get_entry).apply(null,arguments)};a._spine_skin_entries_dispose=function(){return(a._spine_skin_entries_dispose=a.asm.spine_skin_entries_dispose).apply(null,arguments)}; -a._spine_skin_entry_get_slot_index=function(){return(a._spine_skin_entry_get_slot_index=a.asm.spine_skin_entry_get_slot_index).apply(null,arguments)};a._spine_skin_entry_get_name=function(){return(a._spine_skin_entry_get_name=a.asm.spine_skin_entry_get_name).apply(null,arguments)};a._spine_skin_entry_get_attachment=function(){return(a._spine_skin_entry_get_attachment=a.asm.spine_skin_entry_get_attachment).apply(null,arguments)}; -a._spine_skin_get_num_bones=function(){return(a._spine_skin_get_num_bones=a.asm.spine_skin_get_num_bones).apply(null,arguments)};a._spine_skin_get_bones=function(){return(a._spine_skin_get_bones=a.asm.spine_skin_get_bones).apply(null,arguments)};a._spine_skin_get_num_constraints=function(){return(a._spine_skin_get_num_constraints=a.asm.spine_skin_get_num_constraints).apply(null,arguments)}; -a._spine_skin_get_constraints=function(){return(a._spine_skin_get_constraints=a.asm.spine_skin_get_constraints).apply(null,arguments)};a._spine_skin_create=function(){return(a._spine_skin_create=a.asm.spine_skin_create).apply(null,arguments)};a._spine_skin_dispose=function(){return(a._spine_skin_dispose=a.asm.spine_skin_dispose).apply(null,arguments)};a._spine_constraint_data_get_type=function(){return(a._spine_constraint_data_get_type=a.asm.spine_constraint_data_get_type).apply(null,arguments)}; -a._spine_constraint_data_get_name=function(){return(a._spine_constraint_data_get_name=a.asm.spine_constraint_data_get_name).apply(null,arguments)};a._spine_constraint_data_get_order=function(){return(a._spine_constraint_data_get_order=a.asm.spine_constraint_data_get_order).apply(null,arguments)};a._spine_constraint_data_set_order=function(){return(a._spine_constraint_data_set_order=a.asm.spine_constraint_data_set_order).apply(null,arguments)}; -a._spine_constraint_data_get_is_skin_required=function(){return(a._spine_constraint_data_get_is_skin_required=a.asm.spine_constraint_data_get_is_skin_required).apply(null,arguments)};a._spine_constraint_data_set_is_skin_required=function(){return(a._spine_constraint_data_set_is_skin_required=a.asm.spine_constraint_data_set_is_skin_required).apply(null,arguments)}; -a._spine_ik_constraint_data_get_num_bones=function(){return(a._spine_ik_constraint_data_get_num_bones=a.asm.spine_ik_constraint_data_get_num_bones).apply(null,arguments)};a._spine_ik_constraint_data_get_bones=function(){return(a._spine_ik_constraint_data_get_bones=a.asm.spine_ik_constraint_data_get_bones).apply(null,arguments)};a._spine_ik_constraint_data_get_target=function(){return(a._spine_ik_constraint_data_get_target=a.asm.spine_ik_constraint_data_get_target).apply(null,arguments)}; -a._spine_ik_constraint_data_set_target=function(){return(a._spine_ik_constraint_data_set_target=a.asm.spine_ik_constraint_data_set_target).apply(null,arguments)};a._spine_ik_constraint_data_get_bend_direction=function(){return(a._spine_ik_constraint_data_get_bend_direction=a.asm.spine_ik_constraint_data_get_bend_direction).apply(null,arguments)}; -a._spine_ik_constraint_data_set_bend_direction=function(){return(a._spine_ik_constraint_data_set_bend_direction=a.asm.spine_ik_constraint_data_set_bend_direction).apply(null,arguments)};a._spine_ik_constraint_data_get_compress=function(){return(a._spine_ik_constraint_data_get_compress=a.asm.spine_ik_constraint_data_get_compress).apply(null,arguments)}; -a._spine_ik_constraint_data_set_compress=function(){return(a._spine_ik_constraint_data_set_compress=a.asm.spine_ik_constraint_data_set_compress).apply(null,arguments)};a._spine_ik_constraint_data_get_stretch=function(){return(a._spine_ik_constraint_data_get_stretch=a.asm.spine_ik_constraint_data_get_stretch).apply(null,arguments)};a._spine_ik_constraint_data_set_stretch=function(){return(a._spine_ik_constraint_data_set_stretch=a.asm.spine_ik_constraint_data_set_stretch).apply(null,arguments)}; -a._spine_ik_constraint_data_get_uniform=function(){return(a._spine_ik_constraint_data_get_uniform=a.asm.spine_ik_constraint_data_get_uniform).apply(null,arguments)};a._spine_ik_constraint_data_set_uniform=function(){return(a._spine_ik_constraint_data_set_uniform=a.asm.spine_ik_constraint_data_set_uniform).apply(null,arguments)};a._spine_ik_constraint_data_get_mix=function(){return(a._spine_ik_constraint_data_get_mix=a.asm.spine_ik_constraint_data_get_mix).apply(null,arguments)}; -a._spine_ik_constraint_data_set_mix=function(){return(a._spine_ik_constraint_data_set_mix=a.asm.spine_ik_constraint_data_set_mix).apply(null,arguments)};a._spine_ik_constraint_data_get_softness=function(){return(a._spine_ik_constraint_data_get_softness=a.asm.spine_ik_constraint_data_get_softness).apply(null,arguments)};a._spine_ik_constraint_data_set_softness=function(){return(a._spine_ik_constraint_data_set_softness=a.asm.spine_ik_constraint_data_set_softness).apply(null,arguments)}; -a._spine_ik_constraint_update=function(){return(a._spine_ik_constraint_update=a.asm.spine_ik_constraint_update).apply(null,arguments)};a._spine_ik_constraint_get_order=function(){return(a._spine_ik_constraint_get_order=a.asm.spine_ik_constraint_get_order).apply(null,arguments)};a._spine_ik_constraint_get_data=function(){return(a._spine_ik_constraint_get_data=a.asm.spine_ik_constraint_get_data).apply(null,arguments)}; -a._spine_ik_constraint_get_num_bones=function(){return(a._spine_ik_constraint_get_num_bones=a.asm.spine_ik_constraint_get_num_bones).apply(null,arguments)};a._spine_ik_constraint_get_bones=function(){return(a._spine_ik_constraint_get_bones=a.asm.spine_ik_constraint_get_bones).apply(null,arguments)};a._spine_ik_constraint_get_target=function(){return(a._spine_ik_constraint_get_target=a.asm.spine_ik_constraint_get_target).apply(null,arguments)}; -a._spine_ik_constraint_set_target=function(){return(a._spine_ik_constraint_set_target=a.asm.spine_ik_constraint_set_target).apply(null,arguments)};a._spine_ik_constraint_get_bend_direction=function(){return(a._spine_ik_constraint_get_bend_direction=a.asm.spine_ik_constraint_get_bend_direction).apply(null,arguments)};a._spine_ik_constraint_set_bend_direction=function(){return(a._spine_ik_constraint_set_bend_direction=a.asm.spine_ik_constraint_set_bend_direction).apply(null,arguments)}; -a._spine_ik_constraint_get_compress=function(){return(a._spine_ik_constraint_get_compress=a.asm.spine_ik_constraint_get_compress).apply(null,arguments)};a._spine_ik_constraint_set_compress=function(){return(a._spine_ik_constraint_set_compress=a.asm.spine_ik_constraint_set_compress).apply(null,arguments)};a._spine_ik_constraint_get_stretch=function(){return(a._spine_ik_constraint_get_stretch=a.asm.spine_ik_constraint_get_stretch).apply(null,arguments)}; -a._spine_ik_constraint_set_stretch=function(){return(a._spine_ik_constraint_set_stretch=a.asm.spine_ik_constraint_set_stretch).apply(null,arguments)};a._spine_ik_constraint_get_mix=function(){return(a._spine_ik_constraint_get_mix=a.asm.spine_ik_constraint_get_mix).apply(null,arguments)};a._spine_ik_constraint_set_mix=function(){return(a._spine_ik_constraint_set_mix=a.asm.spine_ik_constraint_set_mix).apply(null,arguments)}; -a._spine_ik_constraint_get_softness=function(){return(a._spine_ik_constraint_get_softness=a.asm.spine_ik_constraint_get_softness).apply(null,arguments)};a._spine_ik_constraint_set_softness=function(){return(a._spine_ik_constraint_set_softness=a.asm.spine_ik_constraint_set_softness).apply(null,arguments)};a._spine_ik_constraint_get_is_active=function(){return(a._spine_ik_constraint_get_is_active=a.asm.spine_ik_constraint_get_is_active).apply(null,arguments)}; -a._spine_ik_constraint_set_is_active=function(){return(a._spine_ik_constraint_set_is_active=a.asm.spine_ik_constraint_set_is_active).apply(null,arguments)};a._spine_transform_constraint_data_get_num_bones=function(){return(a._spine_transform_constraint_data_get_num_bones=a.asm.spine_transform_constraint_data_get_num_bones).apply(null,arguments)}; -a._spine_transform_constraint_data_get_bones=function(){return(a._spine_transform_constraint_data_get_bones=a.asm.spine_transform_constraint_data_get_bones).apply(null,arguments)};a._spine_transform_constraint_data_get_target=function(){return(a._spine_transform_constraint_data_get_target=a.asm.spine_transform_constraint_data_get_target).apply(null,arguments)}; -a._spine_transform_constraint_data_set_target=function(){return(a._spine_transform_constraint_data_set_target=a.asm.spine_transform_constraint_data_set_target).apply(null,arguments)};a._spine_transform_constraint_data_get_mix_rotate=function(){return(a._spine_transform_constraint_data_get_mix_rotate=a.asm.spine_transform_constraint_data_get_mix_rotate).apply(null,arguments)}; -a._spine_transform_constraint_data_set_mix_rotate=function(){return(a._spine_transform_constraint_data_set_mix_rotate=a.asm.spine_transform_constraint_data_set_mix_rotate).apply(null,arguments)};a._spine_transform_constraint_data_get_mix_x=function(){return(a._spine_transform_constraint_data_get_mix_x=a.asm.spine_transform_constraint_data_get_mix_x).apply(null,arguments)}; -a._spine_transform_constraint_data_set_mix_x=function(){return(a._spine_transform_constraint_data_set_mix_x=a.asm.spine_transform_constraint_data_set_mix_x).apply(null,arguments)};a._spine_transform_constraint_data_get_mix_y=function(){return(a._spine_transform_constraint_data_get_mix_y=a.asm.spine_transform_constraint_data_get_mix_y).apply(null,arguments)}; -a._spine_transform_constraint_data_set_mix_y=function(){return(a._spine_transform_constraint_data_set_mix_y=a.asm.spine_transform_constraint_data_set_mix_y).apply(null,arguments)};a._spine_transform_constraint_data_get_mix_scale_x=function(){return(a._spine_transform_constraint_data_get_mix_scale_x=a.asm.spine_transform_constraint_data_get_mix_scale_x).apply(null,arguments)}; -a._spine_transform_constraint_data_set_mix_scale_x=function(){return(a._spine_transform_constraint_data_set_mix_scale_x=a.asm.spine_transform_constraint_data_set_mix_scale_x).apply(null,arguments)};a._spine_transform_constraint_data_get_mix_scale_y=function(){return(a._spine_transform_constraint_data_get_mix_scale_y=a.asm.spine_transform_constraint_data_get_mix_scale_y).apply(null,arguments)}; -a._spine_transform_constraint_data_set_mix_scale_y=function(){return(a._spine_transform_constraint_data_set_mix_scale_y=a.asm.spine_transform_constraint_data_set_mix_scale_y).apply(null,arguments)};a._spine_transform_constraint_data_get_mix_shear_y=function(){return(a._spine_transform_constraint_data_get_mix_shear_y=a.asm.spine_transform_constraint_data_get_mix_shear_y).apply(null,arguments)}; -a._spine_transform_constraint_data_set_mix_shear_y=function(){return(a._spine_transform_constraint_data_set_mix_shear_y=a.asm.spine_transform_constraint_data_set_mix_shear_y).apply(null,arguments)};a._spine_transform_constraint_data_get_offset_rotation=function(){return(a._spine_transform_constraint_data_get_offset_rotation=a.asm.spine_transform_constraint_data_get_offset_rotation).apply(null,arguments)}; -a._spine_transform_constraint_data_set_offset_rotation=function(){return(a._spine_transform_constraint_data_set_offset_rotation=a.asm.spine_transform_constraint_data_set_offset_rotation).apply(null,arguments)};a._spine_transform_constraint_data_get_offset_x=function(){return(a._spine_transform_constraint_data_get_offset_x=a.asm.spine_transform_constraint_data_get_offset_x).apply(null,arguments)}; -a._spine_transform_constraint_data_set_offset_x=function(){return(a._spine_transform_constraint_data_set_offset_x=a.asm.spine_transform_constraint_data_set_offset_x).apply(null,arguments)};a._spine_transform_constraint_data_get_offset_y=function(){return(a._spine_transform_constraint_data_get_offset_y=a.asm.spine_transform_constraint_data_get_offset_y).apply(null,arguments)}; -a._spine_transform_constraint_data_set_offset_y=function(){return(a._spine_transform_constraint_data_set_offset_y=a.asm.spine_transform_constraint_data_set_offset_y).apply(null,arguments)};a._spine_transform_constraint_data_get_offset_scale_x=function(){return(a._spine_transform_constraint_data_get_offset_scale_x=a.asm.spine_transform_constraint_data_get_offset_scale_x).apply(null,arguments)}; -a._spine_transform_constraint_data_set_offset_scale_x=function(){return(a._spine_transform_constraint_data_set_offset_scale_x=a.asm.spine_transform_constraint_data_set_offset_scale_x).apply(null,arguments)};a._spine_transform_constraint_data_get_offset_scale_y=function(){return(a._spine_transform_constraint_data_get_offset_scale_y=a.asm.spine_transform_constraint_data_get_offset_scale_y).apply(null,arguments)}; -a._spine_transform_constraint_data_set_offset_scale_y=function(){return(a._spine_transform_constraint_data_set_offset_scale_y=a.asm.spine_transform_constraint_data_set_offset_scale_y).apply(null,arguments)};a._spine_transform_constraint_data_get_offset_shear_y=function(){return(a._spine_transform_constraint_data_get_offset_shear_y=a.asm.spine_transform_constraint_data_get_offset_shear_y).apply(null,arguments)}; -a._spine_transform_constraint_data_set_offset_shear_y=function(){return(a._spine_transform_constraint_data_set_offset_shear_y=a.asm.spine_transform_constraint_data_set_offset_shear_y).apply(null,arguments)};a._spine_transform_constraint_data_get_is_relative=function(){return(a._spine_transform_constraint_data_get_is_relative=a.asm.spine_transform_constraint_data_get_is_relative).apply(null,arguments)}; -a._spine_transform_constraint_data_set_is_relative=function(){return(a._spine_transform_constraint_data_set_is_relative=a.asm.spine_transform_constraint_data_set_is_relative).apply(null,arguments)};a._spine_transform_constraint_data_get_is_local=function(){return(a._spine_transform_constraint_data_get_is_local=a.asm.spine_transform_constraint_data_get_is_local).apply(null,arguments)}; -a._spine_transform_constraint_data_set_is_local=function(){return(a._spine_transform_constraint_data_set_is_local=a.asm.spine_transform_constraint_data_set_is_local).apply(null,arguments)};a._spine_transform_constraint_update=function(){return(a._spine_transform_constraint_update=a.asm.spine_transform_constraint_update).apply(null,arguments)};a._spine_transform_constraint_get_order=function(){return(a._spine_transform_constraint_get_order=a.asm.spine_transform_constraint_get_order).apply(null,arguments)}; -a._spine_transform_constraint_get_data=function(){return(a._spine_transform_constraint_get_data=a.asm.spine_transform_constraint_get_data).apply(null,arguments)};a._spine_transform_constraint_get_num_bones=function(){return(a._spine_transform_constraint_get_num_bones=a.asm.spine_transform_constraint_get_num_bones).apply(null,arguments)};a._spine_transform_constraint_get_bones=function(){return(a._spine_transform_constraint_get_bones=a.asm.spine_transform_constraint_get_bones).apply(null,arguments)}; -a._spine_transform_constraint_get_target=function(){return(a._spine_transform_constraint_get_target=a.asm.spine_transform_constraint_get_target).apply(null,arguments)};a._spine_transform_constraint_set_target=function(){return(a._spine_transform_constraint_set_target=a.asm.spine_transform_constraint_set_target).apply(null,arguments)}; -a._spine_transform_constraint_get_mix_rotate=function(){return(a._spine_transform_constraint_get_mix_rotate=a.asm.spine_transform_constraint_get_mix_rotate).apply(null,arguments)};a._spine_transform_constraint_set_mix_rotate=function(){return(a._spine_transform_constraint_set_mix_rotate=a.asm.spine_transform_constraint_set_mix_rotate).apply(null,arguments)}; -a._spine_transform_constraint_get_mix_x=function(){return(a._spine_transform_constraint_get_mix_x=a.asm.spine_transform_constraint_get_mix_x).apply(null,arguments)};a._spine_transform_constraint_set_mix_x=function(){return(a._spine_transform_constraint_set_mix_x=a.asm.spine_transform_constraint_set_mix_x).apply(null,arguments)};a._spine_transform_constraint_get_mix_y=function(){return(a._spine_transform_constraint_get_mix_y=a.asm.spine_transform_constraint_get_mix_y).apply(null,arguments)}; -a._spine_transform_constraint_set_mix_y=function(){return(a._spine_transform_constraint_set_mix_y=a.asm.spine_transform_constraint_set_mix_y).apply(null,arguments)};a._spine_transform_constraint_get_mix_scale_x=function(){return(a._spine_transform_constraint_get_mix_scale_x=a.asm.spine_transform_constraint_get_mix_scale_x).apply(null,arguments)}; -a._spine_transform_constraint_set_mix_scale_x=function(){return(a._spine_transform_constraint_set_mix_scale_x=a.asm.spine_transform_constraint_set_mix_scale_x).apply(null,arguments)};a._spine_transform_constraint_get_mix_scale_y=function(){return(a._spine_transform_constraint_get_mix_scale_y=a.asm.spine_transform_constraint_get_mix_scale_y).apply(null,arguments)}; -a._spine_transform_constraint_set_mix_scale_y=function(){return(a._spine_transform_constraint_set_mix_scale_y=a.asm.spine_transform_constraint_set_mix_scale_y).apply(null,arguments)};a._spine_transform_constraint_get_mix_shear_y=function(){return(a._spine_transform_constraint_get_mix_shear_y=a.asm.spine_transform_constraint_get_mix_shear_y).apply(null,arguments)}; -a._spine_transform_constraint_set_mix_shear_y=function(){return(a._spine_transform_constraint_set_mix_shear_y=a.asm.spine_transform_constraint_set_mix_shear_y).apply(null,arguments)};a._spine_transform_constraint_get_is_active=function(){return(a._spine_transform_constraint_get_is_active=a.asm.spine_transform_constraint_get_is_active).apply(null,arguments)}; -a._spine_transform_constraint_set_is_active=function(){return(a._spine_transform_constraint_set_is_active=a.asm.spine_transform_constraint_set_is_active).apply(null,arguments)};a._spine_path_constraint_data_get_num_bones=function(){return(a._spine_path_constraint_data_get_num_bones=a.asm.spine_path_constraint_data_get_num_bones).apply(null,arguments)}; -a._spine_path_constraint_data_get_bones=function(){return(a._spine_path_constraint_data_get_bones=a.asm.spine_path_constraint_data_get_bones).apply(null,arguments)};a._spine_path_constraint_data_get_target=function(){return(a._spine_path_constraint_data_get_target=a.asm.spine_path_constraint_data_get_target).apply(null,arguments)};a._spine_path_constraint_data_set_target=function(){return(a._spine_path_constraint_data_set_target=a.asm.spine_path_constraint_data_set_target).apply(null,arguments)}; -a._spine_path_constraint_data_get_position_mode=function(){return(a._spine_path_constraint_data_get_position_mode=a.asm.spine_path_constraint_data_get_position_mode).apply(null,arguments)};a._spine_path_constraint_data_set_position_mode=function(){return(a._spine_path_constraint_data_set_position_mode=a.asm.spine_path_constraint_data_set_position_mode).apply(null,arguments)}; -a._spine_path_constraint_data_get_spacing_mode=function(){return(a._spine_path_constraint_data_get_spacing_mode=a.asm.spine_path_constraint_data_get_spacing_mode).apply(null,arguments)};a._spine_path_constraint_data_set_spacing_mode=function(){return(a._spine_path_constraint_data_set_spacing_mode=a.asm.spine_path_constraint_data_set_spacing_mode).apply(null,arguments)}; -a._spine_path_constraint_data_get_rotate_mode=function(){return(a._spine_path_constraint_data_get_rotate_mode=a.asm.spine_path_constraint_data_get_rotate_mode).apply(null,arguments)};a._spine_path_constraint_data_set_rotate_mode=function(){return(a._spine_path_constraint_data_set_rotate_mode=a.asm.spine_path_constraint_data_set_rotate_mode).apply(null,arguments)}; -a._spine_path_constraint_data_get_offset_rotation=function(){return(a._spine_path_constraint_data_get_offset_rotation=a.asm.spine_path_constraint_data_get_offset_rotation).apply(null,arguments)};a._spine_path_constraint_data_set_offset_rotation=function(){return(a._spine_path_constraint_data_set_offset_rotation=a.asm.spine_path_constraint_data_set_offset_rotation).apply(null,arguments)}; -a._spine_path_constraint_data_get_position=function(){return(a._spine_path_constraint_data_get_position=a.asm.spine_path_constraint_data_get_position).apply(null,arguments)};a._spine_path_constraint_data_set_position=function(){return(a._spine_path_constraint_data_set_position=a.asm.spine_path_constraint_data_set_position).apply(null,arguments)}; -a._spine_path_constraint_data_get_spacing=function(){return(a._spine_path_constraint_data_get_spacing=a.asm.spine_path_constraint_data_get_spacing).apply(null,arguments)};a._spine_path_constraint_data_set_spacing=function(){return(a._spine_path_constraint_data_set_spacing=a.asm.spine_path_constraint_data_set_spacing).apply(null,arguments)}; -a._spine_path_constraint_data_get_mix_rotate=function(){return(a._spine_path_constraint_data_get_mix_rotate=a.asm.spine_path_constraint_data_get_mix_rotate).apply(null,arguments)};a._spine_path_constraint_data_set_mix_rotate=function(){return(a._spine_path_constraint_data_set_mix_rotate=a.asm.spine_path_constraint_data_set_mix_rotate).apply(null,arguments)}; -a._spine_path_constraint_data_get_mix_x=function(){return(a._spine_path_constraint_data_get_mix_x=a.asm.spine_path_constraint_data_get_mix_x).apply(null,arguments)};a._spine_path_constraint_data_set_mix_x=function(){return(a._spine_path_constraint_data_set_mix_x=a.asm.spine_path_constraint_data_set_mix_x).apply(null,arguments)};a._spine_path_constraint_data_get_mix_y=function(){return(a._spine_path_constraint_data_get_mix_y=a.asm.spine_path_constraint_data_get_mix_y).apply(null,arguments)}; -a._spine_path_constraint_data_set_mix_y=function(){return(a._spine_path_constraint_data_set_mix_y=a.asm.spine_path_constraint_data_set_mix_y).apply(null,arguments)};a._spine_path_constraint_update=function(){return(a._spine_path_constraint_update=a.asm.spine_path_constraint_update).apply(null,arguments)};a._spine_path_constraint_get_order=function(){return(a._spine_path_constraint_get_order=a.asm.spine_path_constraint_get_order).apply(null,arguments)}; -a._spine_path_constraint_get_data=function(){return(a._spine_path_constraint_get_data=a.asm.spine_path_constraint_get_data).apply(null,arguments)};a._spine_path_constraint_get_num_bones=function(){return(a._spine_path_constraint_get_num_bones=a.asm.spine_path_constraint_get_num_bones).apply(null,arguments)};a._spine_path_constraint_get_bones=function(){return(a._spine_path_constraint_get_bones=a.asm.spine_path_constraint_get_bones).apply(null,arguments)}; -a._spine_path_constraint_get_target=function(){return(a._spine_path_constraint_get_target=a.asm.spine_path_constraint_get_target).apply(null,arguments)};a._spine_path_constraint_set_target=function(){return(a._spine_path_constraint_set_target=a.asm.spine_path_constraint_set_target).apply(null,arguments)};a._spine_path_constraint_get_position=function(){return(a._spine_path_constraint_get_position=a.asm.spine_path_constraint_get_position).apply(null,arguments)}; -a._spine_path_constraint_set_position=function(){return(a._spine_path_constraint_set_position=a.asm.spine_path_constraint_set_position).apply(null,arguments)};a._spine_path_constraint_get_spacing=function(){return(a._spine_path_constraint_get_spacing=a.asm.spine_path_constraint_get_spacing).apply(null,arguments)};a._spine_path_constraint_set_spacing=function(){return(a._spine_path_constraint_set_spacing=a.asm.spine_path_constraint_set_spacing).apply(null,arguments)}; -a._spine_path_constraint_get_mix_rotate=function(){return(a._spine_path_constraint_get_mix_rotate=a.asm.spine_path_constraint_get_mix_rotate).apply(null,arguments)};a._spine_path_constraint_set_mix_rotate=function(){return(a._spine_path_constraint_set_mix_rotate=a.asm.spine_path_constraint_set_mix_rotate).apply(null,arguments)};a._spine_path_constraint_get_mix_x=function(){return(a._spine_path_constraint_get_mix_x=a.asm.spine_path_constraint_get_mix_x).apply(null,arguments)}; -a._spine_path_constraint_set_mix_x=function(){return(a._spine_path_constraint_set_mix_x=a.asm.spine_path_constraint_set_mix_x).apply(null,arguments)};a._spine_path_constraint_get_mix_y=function(){return(a._spine_path_constraint_get_mix_y=a.asm.spine_path_constraint_get_mix_y).apply(null,arguments)};a._spine_path_constraint_set_mix_y=function(){return(a._spine_path_constraint_set_mix_y=a.asm.spine_path_constraint_set_mix_y).apply(null,arguments)}; -a._spine_path_constraint_get_is_active=function(){return(a._spine_path_constraint_get_is_active=a.asm.spine_path_constraint_get_is_active).apply(null,arguments)};a._spine_path_constraint_set_is_active=function(){return(a._spine_path_constraint_set_is_active=a.asm.spine_path_constraint_set_is_active).apply(null,arguments)};a._spine_physics_constraint_data_set_bone=function(){return(a._spine_physics_constraint_data_set_bone=a.asm.spine_physics_constraint_data_set_bone).apply(null,arguments)}; -a._spine_physics_constraint_data_get_bone=function(){return(a._spine_physics_constraint_data_get_bone=a.asm.spine_physics_constraint_data_get_bone).apply(null,arguments)};a._spine_physics_constraint_data_set_x=function(){return(a._spine_physics_constraint_data_set_x=a.asm.spine_physics_constraint_data_set_x).apply(null,arguments)};a._spine_physics_constraint_data_get_x=function(){return(a._spine_physics_constraint_data_get_x=a.asm.spine_physics_constraint_data_get_x).apply(null,arguments)}; -a._spine_physics_constraint_data_set_y=function(){return(a._spine_physics_constraint_data_set_y=a.asm.spine_physics_constraint_data_set_y).apply(null,arguments)};a._spine_physics_constraint_data_get_y=function(){return(a._spine_physics_constraint_data_get_y=a.asm.spine_physics_constraint_data_get_y).apply(null,arguments)};a._spine_physics_constraint_data_set_rotate=function(){return(a._spine_physics_constraint_data_set_rotate=a.asm.spine_physics_constraint_data_set_rotate).apply(null,arguments)}; -a._spine_physics_constraint_data_get_rotate=function(){return(a._spine_physics_constraint_data_get_rotate=a.asm.spine_physics_constraint_data_get_rotate).apply(null,arguments)};a._spine_physics_constraint_data_set_scale_x=function(){return(a._spine_physics_constraint_data_set_scale_x=a.asm.spine_physics_constraint_data_set_scale_x).apply(null,arguments)}; -a._spine_physics_constraint_data_get_scale_x=function(){return(a._spine_physics_constraint_data_get_scale_x=a.asm.spine_physics_constraint_data_get_scale_x).apply(null,arguments)};a._spine_physics_constraint_data_set_shear_x=function(){return(a._spine_physics_constraint_data_set_shear_x=a.asm.spine_physics_constraint_data_set_shear_x).apply(null,arguments)}; -a._spine_physics_constraint_data_get_shear_x=function(){return(a._spine_physics_constraint_data_get_shear_x=a.asm.spine_physics_constraint_data_get_shear_x).apply(null,arguments)};a._spine_physics_constraint_data_set_limit=function(){return(a._spine_physics_constraint_data_set_limit=a.asm.spine_physics_constraint_data_set_limit).apply(null,arguments)}; -a._spine_physics_constraint_data_get_limit=function(){return(a._spine_physics_constraint_data_get_limit=a.asm.spine_physics_constraint_data_get_limit).apply(null,arguments)};a._spine_physics_constraint_data_set_step=function(){return(a._spine_physics_constraint_data_set_step=a.asm.spine_physics_constraint_data_set_step).apply(null,arguments)}; -a._spine_physics_constraint_data_get_step=function(){return(a._spine_physics_constraint_data_get_step=a.asm.spine_physics_constraint_data_get_step).apply(null,arguments)};a._spine_physics_constraint_data_set_inertia=function(){return(a._spine_physics_constraint_data_set_inertia=a.asm.spine_physics_constraint_data_set_inertia).apply(null,arguments)}; -a._spine_physics_constraint_data_get_inertia=function(){return(a._spine_physics_constraint_data_get_inertia=a.asm.spine_physics_constraint_data_get_inertia).apply(null,arguments)};a._spine_physics_constraint_data_set_strength=function(){return(a._spine_physics_constraint_data_set_strength=a.asm.spine_physics_constraint_data_set_strength).apply(null,arguments)}; -a._spine_physics_constraint_data_get_strength=function(){return(a._spine_physics_constraint_data_get_strength=a.asm.spine_physics_constraint_data_get_strength).apply(null,arguments)};a._spine_physics_constraint_data_set_damping=function(){return(a._spine_physics_constraint_data_set_damping=a.asm.spine_physics_constraint_data_set_damping).apply(null,arguments)}; -a._spine_physics_constraint_data_get_damping=function(){return(a._spine_physics_constraint_data_get_damping=a.asm.spine_physics_constraint_data_get_damping).apply(null,arguments)};a._spine_physics_constraint_data_set_mass_inverse=function(){return(a._spine_physics_constraint_data_set_mass_inverse=a.asm.spine_physics_constraint_data_set_mass_inverse).apply(null,arguments)}; -a._spine_physics_constraint_data_get_mass_inverse=function(){return(a._spine_physics_constraint_data_get_mass_inverse=a.asm.spine_physics_constraint_data_get_mass_inverse).apply(null,arguments)};a._spine_physics_constraint_data_set_wind=function(){return(a._spine_physics_constraint_data_set_wind=a.asm.spine_physics_constraint_data_set_wind).apply(null,arguments)}; -a._spine_physics_constraint_data_get_wind=function(){return(a._spine_physics_constraint_data_get_wind=a.asm.spine_physics_constraint_data_get_wind).apply(null,arguments)};a._spine_physics_constraint_data_set_gravity=function(){return(a._spine_physics_constraint_data_set_gravity=a.asm.spine_physics_constraint_data_set_gravity).apply(null,arguments)}; -a._spine_physics_constraint_data_get_gravity=function(){return(a._spine_physics_constraint_data_get_gravity=a.asm.spine_physics_constraint_data_get_gravity).apply(null,arguments)};a._spine_physics_constraint_data_set_mix=function(){return(a._spine_physics_constraint_data_set_mix=a.asm.spine_physics_constraint_data_set_mix).apply(null,arguments)}; -a._spine_physics_constraint_data_get_mix=function(){return(a._spine_physics_constraint_data_get_mix=a.asm.spine_physics_constraint_data_get_mix).apply(null,arguments)};a._spine_physics_constraint_data_set_inertia_global=function(){return(a._spine_physics_constraint_data_set_inertia_global=a.asm.spine_physics_constraint_data_set_inertia_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_inertia_global=function(){return(a._spine_physics_constraint_data_is_inertia_global=a.asm.spine_physics_constraint_data_is_inertia_global).apply(null,arguments)};a._spine_physics_constraint_data_set_strength_global=function(){return(a._spine_physics_constraint_data_set_strength_global=a.asm.spine_physics_constraint_data_set_strength_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_strength_global=function(){return(a._spine_physics_constraint_data_is_strength_global=a.asm.spine_physics_constraint_data_is_strength_global).apply(null,arguments)};a._spine_physics_constraint_data_set_damping_global=function(){return(a._spine_physics_constraint_data_set_damping_global=a.asm.spine_physics_constraint_data_set_damping_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_damping_global=function(){return(a._spine_physics_constraint_data_is_damping_global=a.asm.spine_physics_constraint_data_is_damping_global).apply(null,arguments)};a._spine_physics_constraint_data_set_mass_global=function(){return(a._spine_physics_constraint_data_set_mass_global=a.asm.spine_physics_constraint_data_set_mass_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_mass_global=function(){return(a._spine_physics_constraint_data_is_mass_global=a.asm.spine_physics_constraint_data_is_mass_global).apply(null,arguments)};a._spine_physics_constraint_data_set_wind_global=function(){return(a._spine_physics_constraint_data_set_wind_global=a.asm.spine_physics_constraint_data_set_wind_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_wind_global=function(){return(a._spine_physics_constraint_data_is_wind_global=a.asm.spine_physics_constraint_data_is_wind_global).apply(null,arguments)};a._spine_physics_constraint_data_set_gravity_global=function(){return(a._spine_physics_constraint_data_set_gravity_global=a.asm.spine_physics_constraint_data_set_gravity_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_gravity_global=function(){return(a._spine_physics_constraint_data_is_gravity_global=a.asm.spine_physics_constraint_data_is_gravity_global).apply(null,arguments)};a._spine_physics_constraint_data_set_mix_global=function(){return(a._spine_physics_constraint_data_set_mix_global=a.asm.spine_physics_constraint_data_set_mix_global).apply(null,arguments)}; -a._spine_physics_constraint_data_is_mix_global=function(){return(a._spine_physics_constraint_data_is_mix_global=a.asm.spine_physics_constraint_data_is_mix_global).apply(null,arguments)};a._spine_physics_constraint_set_bone=function(){return(a._spine_physics_constraint_set_bone=a.asm.spine_physics_constraint_set_bone).apply(null,arguments)};a._spine_physics_constraint_get_bone=function(){return(a._spine_physics_constraint_get_bone=a.asm.spine_physics_constraint_get_bone).apply(null,arguments)}; -a._spine_physics_constraint_set_inertia=function(){return(a._spine_physics_constraint_set_inertia=a.asm.spine_physics_constraint_set_inertia).apply(null,arguments)};a._spine_physics_constraint_get_inertia=function(){return(a._spine_physics_constraint_get_inertia=a.asm.spine_physics_constraint_get_inertia).apply(null,arguments)};a._spine_physics_constraint_set_strength=function(){return(a._spine_physics_constraint_set_strength=a.asm.spine_physics_constraint_set_strength).apply(null,arguments)}; -a._spine_physics_constraint_get_strength=function(){return(a._spine_physics_constraint_get_strength=a.asm.spine_physics_constraint_get_strength).apply(null,arguments)};a._spine_physics_constraint_set_damping=function(){return(a._spine_physics_constraint_set_damping=a.asm.spine_physics_constraint_set_damping).apply(null,arguments)};a._spine_physics_constraint_get_damping=function(){return(a._spine_physics_constraint_get_damping=a.asm.spine_physics_constraint_get_damping).apply(null,arguments)}; -a._spine_physics_constraint_set_mass_inverse=function(){return(a._spine_physics_constraint_set_mass_inverse=a.asm.spine_physics_constraint_set_mass_inverse).apply(null,arguments)};a._spine_physics_constraint_get_mass_inverse=function(){return(a._spine_physics_constraint_get_mass_inverse=a.asm.spine_physics_constraint_get_mass_inverse).apply(null,arguments)}; -a._spine_physics_constraint_set_wind=function(){return(a._spine_physics_constraint_set_wind=a.asm.spine_physics_constraint_set_wind).apply(null,arguments)};a._spine_physics_constraint_get_wind=function(){return(a._spine_physics_constraint_get_wind=a.asm.spine_physics_constraint_get_wind).apply(null,arguments)};a._spine_physics_constraint_set_gravity=function(){return(a._spine_physics_constraint_set_gravity=a.asm.spine_physics_constraint_set_gravity).apply(null,arguments)}; -a._spine_physics_constraint_get_gravity=function(){return(a._spine_physics_constraint_get_gravity=a.asm.spine_physics_constraint_get_gravity).apply(null,arguments)};a._spine_physics_constraint_set_mix=function(){return(a._spine_physics_constraint_set_mix=a.asm.spine_physics_constraint_set_mix).apply(null,arguments)};a._spine_physics_constraint_get_mix=function(){return(a._spine_physics_constraint_get_mix=a.asm.spine_physics_constraint_get_mix).apply(null,arguments)}; -a._spine_physics_constraint_set_reset=function(){return(a._spine_physics_constraint_set_reset=a.asm.spine_physics_constraint_set_reset).apply(null,arguments)};a._spine_physics_constraint_get_reset=function(){return(a._spine_physics_constraint_get_reset=a.asm.spine_physics_constraint_get_reset).apply(null,arguments)};a._spine_physics_constraint_set_ux=function(){return(a._spine_physics_constraint_set_ux=a.asm.spine_physics_constraint_set_ux).apply(null,arguments)}; -a._spine_physics_constraint_get_ux=function(){return(a._spine_physics_constraint_get_ux=a.asm.spine_physics_constraint_get_ux).apply(null,arguments)};a._spine_physics_constraint_set_uy=function(){return(a._spine_physics_constraint_set_uy=a.asm.spine_physics_constraint_set_uy).apply(null,arguments)};a._spine_physics_constraint_get_uy=function(){return(a._spine_physics_constraint_get_uy=a.asm.spine_physics_constraint_get_uy).apply(null,arguments)}; -a._spine_physics_constraint_set_cx=function(){return(a._spine_physics_constraint_set_cx=a.asm.spine_physics_constraint_set_cx).apply(null,arguments)};a._spine_physics_constraint_get_cx=function(){return(a._spine_physics_constraint_get_cx=a.asm.spine_physics_constraint_get_cx).apply(null,arguments)};a._spine_physics_constraint_set_cy=function(){return(a._spine_physics_constraint_set_cy=a.asm.spine_physics_constraint_set_cy).apply(null,arguments)}; -a._spine_physics_constraint_get_cy=function(){return(a._spine_physics_constraint_get_cy=a.asm.spine_physics_constraint_get_cy).apply(null,arguments)};a._spine_physics_constraint_set_tx=function(){return(a._spine_physics_constraint_set_tx=a.asm.spine_physics_constraint_set_tx).apply(null,arguments)};a._spine_physics_constraint_get_tx=function(){return(a._spine_physics_constraint_get_tx=a.asm.spine_physics_constraint_get_tx).apply(null,arguments)}; -a._spine_physics_constraint_set_ty=function(){return(a._spine_physics_constraint_set_ty=a.asm.spine_physics_constraint_set_ty).apply(null,arguments)};a._spine_physics_constraint_get_ty=function(){return(a._spine_physics_constraint_get_ty=a.asm.spine_physics_constraint_get_ty).apply(null,arguments)};a._spine_physics_constraint_set_x_offset=function(){return(a._spine_physics_constraint_set_x_offset=a.asm.spine_physics_constraint_set_x_offset).apply(null,arguments)}; -a._spine_physics_constraint_get_x_offset=function(){return(a._spine_physics_constraint_get_x_offset=a.asm.spine_physics_constraint_get_x_offset).apply(null,arguments)};a._spine_physics_constraint_set_x_velocity=function(){return(a._spine_physics_constraint_set_x_velocity=a.asm.spine_physics_constraint_set_x_velocity).apply(null,arguments)}; -a._spine_physics_constraint_get_x_velocity=function(){return(a._spine_physics_constraint_get_x_velocity=a.asm.spine_physics_constraint_get_x_velocity).apply(null,arguments)};a._spine_physics_constraint_set_y_offset=function(){return(a._spine_physics_constraint_set_y_offset=a.asm.spine_physics_constraint_set_y_offset).apply(null,arguments)};a._spine_physics_constraint_get_y_offset=function(){return(a._spine_physics_constraint_get_y_offset=a.asm.spine_physics_constraint_get_y_offset).apply(null,arguments)}; -a._spine_physics_constraint_set_y_velocity=function(){return(a._spine_physics_constraint_set_y_velocity=a.asm.spine_physics_constraint_set_y_velocity).apply(null,arguments)};a._spine_physics_constraint_get_y_velocity=function(){return(a._spine_physics_constraint_get_y_velocity=a.asm.spine_physics_constraint_get_y_velocity).apply(null,arguments)}; -a._spine_physics_constraint_set_rotate_offset=function(){return(a._spine_physics_constraint_set_rotate_offset=a.asm.spine_physics_constraint_set_rotate_offset).apply(null,arguments)};a._spine_physics_constraint_get_rotate_offset=function(){return(a._spine_physics_constraint_get_rotate_offset=a.asm.spine_physics_constraint_get_rotate_offset).apply(null,arguments)}; -a._spine_physics_constraint_set_rotate_velocity=function(){return(a._spine_physics_constraint_set_rotate_velocity=a.asm.spine_physics_constraint_set_rotate_velocity).apply(null,arguments)};a._spine_physics_constraint_get_rotate_velocity=function(){return(a._spine_physics_constraint_get_rotate_velocity=a.asm.spine_physics_constraint_get_rotate_velocity).apply(null,arguments)}; -a._spine_physics_constraint_set_scale_offset=function(){return(a._spine_physics_constraint_set_scale_offset=a.asm.spine_physics_constraint_set_scale_offset).apply(null,arguments)};a._spine_physics_constraint_get_scale_offset=function(){return(a._spine_physics_constraint_get_scale_offset=a.asm.spine_physics_constraint_get_scale_offset).apply(null,arguments)}; -a._spine_physics_constraint_set_scale_velocity=function(){return(a._spine_physics_constraint_set_scale_velocity=a.asm.spine_physics_constraint_set_scale_velocity).apply(null,arguments)};a._spine_physics_constraint_get_scale_velocity=function(){return(a._spine_physics_constraint_get_scale_velocity=a.asm.spine_physics_constraint_get_scale_velocity).apply(null,arguments)}; -a._spine_physics_constraint_set_active=function(){return(a._spine_physics_constraint_set_active=a.asm.spine_physics_constraint_set_active).apply(null,arguments)};a._spine_physics_constraint_is_active=function(){return(a._spine_physics_constraint_is_active=a.asm.spine_physics_constraint_is_active).apply(null,arguments)};a._spine_physics_constraint_set_remaining=function(){return(a._spine_physics_constraint_set_remaining=a.asm.spine_physics_constraint_set_remaining).apply(null,arguments)}; -a._spine_physics_constraint_get_remaining=function(){return(a._spine_physics_constraint_get_remaining=a.asm.spine_physics_constraint_get_remaining).apply(null,arguments)};a._spine_physics_constraint_set_last_time=function(){return(a._spine_physics_constraint_set_last_time=a.asm.spine_physics_constraint_set_last_time).apply(null,arguments)}; -a._spine_physics_constraint_get_last_time=function(){return(a._spine_physics_constraint_get_last_time=a.asm.spine_physics_constraint_get_last_time).apply(null,arguments)};a._spine_physics_constraint_reset_fully=function(){return(a._spine_physics_constraint_reset_fully=a.asm.spine_physics_constraint_reset_fully).apply(null,arguments)};a._spine_physics_constraint_update=function(){return(a._spine_physics_constraint_update=a.asm.spine_physics_constraint_update).apply(null,arguments)}; -a._spine_physics_constraint_translate=function(){return(a._spine_physics_constraint_translate=a.asm.spine_physics_constraint_translate).apply(null,arguments)};a._spine_physics_constraint_rotate=function(){return(a._spine_physics_constraint_rotate=a.asm.spine_physics_constraint_rotate).apply(null,arguments)};a._spine_sequence_apply=function(){return(a._spine_sequence_apply=a.asm.spine_sequence_apply).apply(null,arguments)}; -a._spine_sequence_get_path=function(){return(a._spine_sequence_get_path=a.asm.spine_sequence_get_path).apply(null,arguments)};a._spine_sequence_get_id=function(){return(a._spine_sequence_get_id=a.asm.spine_sequence_get_id).apply(null,arguments)};a._spine_sequence_set_id=function(){return(a._spine_sequence_set_id=a.asm.spine_sequence_set_id).apply(null,arguments)};a._spine_sequence_get_start=function(){return(a._spine_sequence_get_start=a.asm.spine_sequence_get_start).apply(null,arguments)}; -a._spine_sequence_set_start=function(){return(a._spine_sequence_set_start=a.asm.spine_sequence_set_start).apply(null,arguments)};a._spine_sequence_get_digits=function(){return(a._spine_sequence_get_digits=a.asm.spine_sequence_get_digits).apply(null,arguments)};a._spine_sequence_set_digits=function(){return(a._spine_sequence_set_digits=a.asm.spine_sequence_set_digits).apply(null,arguments)}; -a._spine_sequence_get_setup_index=function(){return(a._spine_sequence_get_setup_index=a.asm.spine_sequence_get_setup_index).apply(null,arguments)};a._spine_sequence_set_setup_index=function(){return(a._spine_sequence_set_setup_index=a.asm.spine_sequence_set_setup_index).apply(null,arguments)};a._spine_sequence_get_num_regions=function(){return(a._spine_sequence_get_num_regions=a.asm.spine_sequence_get_num_regions).apply(null,arguments)}; -a._spine_sequence_get_regions=function(){return(a._spine_sequence_get_regions=a.asm.spine_sequence_get_regions).apply(null,arguments)};a._spine_texture_region_get_texture=function(){return(a._spine_texture_region_get_texture=a.asm.spine_texture_region_get_texture).apply(null,arguments)};a._spine_texture_region_set_texture=function(){return(a._spine_texture_region_set_texture=a.asm.spine_texture_region_set_texture).apply(null,arguments)}; -a._spine_texture_region_get_u=function(){return(a._spine_texture_region_get_u=a.asm.spine_texture_region_get_u).apply(null,arguments)};a._spine_texture_region_set_u=function(){return(a._spine_texture_region_set_u=a.asm.spine_texture_region_set_u).apply(null,arguments)};a._spine_texture_region_get_v=function(){return(a._spine_texture_region_get_v=a.asm.spine_texture_region_get_v).apply(null,arguments)}; -a._spine_texture_region_set_v=function(){return(a._spine_texture_region_set_v=a.asm.spine_texture_region_set_v).apply(null,arguments)};a._spine_texture_region_get_u2=function(){return(a._spine_texture_region_get_u2=a.asm.spine_texture_region_get_u2).apply(null,arguments)};a._spine_texture_region_set_u2=function(){return(a._spine_texture_region_set_u2=a.asm.spine_texture_region_set_u2).apply(null,arguments)}; -a._spine_texture_region_get_v2=function(){return(a._spine_texture_region_get_v2=a.asm.spine_texture_region_get_v2).apply(null,arguments)};a._spine_texture_region_set_v2=function(){return(a._spine_texture_region_set_v2=a.asm.spine_texture_region_set_v2).apply(null,arguments)};a._spine_texture_region_get_degrees=function(){return(a._spine_texture_region_get_degrees=a.asm.spine_texture_region_get_degrees).apply(null,arguments)}; -a._spine_texture_region_set_degrees=function(){return(a._spine_texture_region_set_degrees=a.asm.spine_texture_region_set_degrees).apply(null,arguments)};a._spine_texture_region_get_offset_x=function(){return(a._spine_texture_region_get_offset_x=a.asm.spine_texture_region_get_offset_x).apply(null,arguments)};a._spine_texture_region_set_offset_x=function(){return(a._spine_texture_region_set_offset_x=a.asm.spine_texture_region_set_offset_x).apply(null,arguments)}; -a._spine_texture_region_get_offset_y=function(){return(a._spine_texture_region_get_offset_y=a.asm.spine_texture_region_get_offset_y).apply(null,arguments)};a._spine_texture_region_set_offset_y=function(){return(a._spine_texture_region_set_offset_y=a.asm.spine_texture_region_set_offset_y).apply(null,arguments)};a._spine_texture_region_get_width=function(){return(a._spine_texture_region_get_width=a.asm.spine_texture_region_get_width).apply(null,arguments)}; -a._spine_texture_region_set_width=function(){return(a._spine_texture_region_set_width=a.asm.spine_texture_region_set_width).apply(null,arguments)};a._spine_texture_region_get_height=function(){return(a._spine_texture_region_get_height=a.asm.spine_texture_region_get_height).apply(null,arguments)};a._spine_texture_region_set_height=function(){return(a._spine_texture_region_set_height=a.asm.spine_texture_region_set_height).apply(null,arguments)}; -a._spine_texture_region_get_original_width=function(){return(a._spine_texture_region_get_original_width=a.asm.spine_texture_region_get_original_width).apply(null,arguments)};a._spine_texture_region_set_original_width=function(){return(a._spine_texture_region_set_original_width=a.asm.spine_texture_region_set_original_width).apply(null,arguments)}; -a._spine_texture_region_get_original_height=function(){return(a._spine_texture_region_get_original_height=a.asm.spine_texture_region_get_original_height).apply(null,arguments)};a._spine_texture_region_set_original_height=function(){return(a._spine_texture_region_set_original_height=a.asm.spine_texture_region_set_original_height).apply(null,arguments)};a._spine_skeleton_bounds_create=function(){return(a._spine_skeleton_bounds_create=a.asm.spine_skeleton_bounds_create).apply(null,arguments)}; -a._spine_skeleton_bounds_dispose=function(){return(a._spine_skeleton_bounds_dispose=a.asm.spine_skeleton_bounds_dispose).apply(null,arguments)};a._spine_skeleton_bounds_update=function(){return(a._spine_skeleton_bounds_update=a.asm.spine_skeleton_bounds_update).apply(null,arguments)};a._spine_skeleton_bounds_aabb_contains_point=function(){return(a._spine_skeleton_bounds_aabb_contains_point=a.asm.spine_skeleton_bounds_aabb_contains_point).apply(null,arguments)}; -a._spine_skeleton_bounds_aabb_intersects_segment=function(){return(a._spine_skeleton_bounds_aabb_intersects_segment=a.asm.spine_skeleton_bounds_aabb_intersects_segment).apply(null,arguments)};a._spine_skeleton_bounds_aabb_intersects_skeleton=function(){return(a._spine_skeleton_bounds_aabb_intersects_skeleton=a.asm.spine_skeleton_bounds_aabb_intersects_skeleton).apply(null,arguments)}; -a._spine_skeleton_bounds_contains_point=function(){return(a._spine_skeleton_bounds_contains_point=a.asm.spine_skeleton_bounds_contains_point).apply(null,arguments)};a._spine_skeleton_bounds_contains_point_attachment=function(){return(a._spine_skeleton_bounds_contains_point_attachment=a.asm.spine_skeleton_bounds_contains_point_attachment).apply(null,arguments)}; -a._spine_skeleton_bounds_intersects_segment_attachment=function(){return(a._spine_skeleton_bounds_intersects_segment_attachment=a.asm.spine_skeleton_bounds_intersects_segment_attachment).apply(null,arguments)};a._spine_skeleton_bounds_intersects_segment=function(){return(a._spine_skeleton_bounds_intersects_segment=a.asm.spine_skeleton_bounds_intersects_segment).apply(null,arguments)}; -a._spine_skeleton_bounds_get_polygon=function(){return(a._spine_skeleton_bounds_get_polygon=a.asm.spine_skeleton_bounds_get_polygon).apply(null,arguments)};a._spine_skeleton_bounds_get_bounding_box=function(){return(a._spine_skeleton_bounds_get_bounding_box=a.asm.spine_skeleton_bounds_get_bounding_box).apply(null,arguments)};a._spine_skeleton_bounds_get_num_polygons=function(){return(a._spine_skeleton_bounds_get_num_polygons=a.asm.spine_skeleton_bounds_get_num_polygons).apply(null,arguments)}; -a._spine_skeleton_bounds_get_polygons=function(){return(a._spine_skeleton_bounds_get_polygons=a.asm.spine_skeleton_bounds_get_polygons).apply(null,arguments)};a._spine_skeleton_bounds_get_num_bounding_boxes=function(){return(a._spine_skeleton_bounds_get_num_bounding_boxes=a.asm.spine_skeleton_bounds_get_num_bounding_boxes).apply(null,arguments)}; -a._spine_skeleton_bounds_get_bounding_boxes=function(){return(a._spine_skeleton_bounds_get_bounding_boxes=a.asm.spine_skeleton_bounds_get_bounding_boxes).apply(null,arguments)};a._spine_skeleton_bounds_get_width=function(){return(a._spine_skeleton_bounds_get_width=a.asm.spine_skeleton_bounds_get_width).apply(null,arguments)};a._spine_skeleton_bounds_get_height=function(){return(a._spine_skeleton_bounds_get_height=a.asm.spine_skeleton_bounds_get_height).apply(null,arguments)}; -a._spine_polygon_get_num_vertices=function(){return(a._spine_polygon_get_num_vertices=a.asm.spine_polygon_get_num_vertices).apply(null,arguments)};a._spine_polygon_get_vertices=function(){return(a._spine_polygon_get_vertices=a.asm.spine_polygon_get_vertices).apply(null,arguments)};a._malloc=function(){return(a._malloc=a.asm.malloc).apply(null,arguments)};a.___errno_location=function(){return(a.___errno_location=a.asm.__errno_location).apply(null,arguments)}; -a.stackSave=function(){return(a.stackSave=a.asm.stackSave).apply(null,arguments)};a.stackRestore=function(){return(a.stackRestore=a.asm.stackRestore).apply(null,arguments)};a.stackAlloc=function(){return(a.stackAlloc=a.asm.stackAlloc).apply(null,arguments)};a.dynCall_jiji=function(){return(a.dynCall_jiji=a.asm.dynCall_jiji).apply(null,arguments)};var Z;R=function sa(){Z||ta();Z||(R=sa)}; -function ta(){function b(){if(!Z&&(Z=!0,a.calledRun=!0,!B)){V(ca);h(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var c=a.postRun.shift();da.unshift(c)}V(da)}}if(!(0 libspine_flutter); diff --git a/spine-flutter/lib/assets/libspine_flutter.wasm b/spine-flutter/lib/assets/libspine_flutter.wasm index 901f23fcb04dbf59b0aa499626ec2ec6d3e40505..8645b6ddc051e0cd5753549e52ef655a7513b8e1 100755 GIT binary patch literal 409435 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

_dqzdT=8E+y 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

|-MiMr!~25- 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�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 NVloo+fR42n`(K)!^w0nR literal 423529 zcmeFa3xFL(l{a4fxR05+Gjo$nATOZr%>)KWB)T!?bF*t&5p@M&_hbKmzHix`49P$y zZ)YZu*(GGqAOV7)f`Wjc28e(Ph>D7W7$86tRD7VQsHmujs8LZ7zTfXuRd?UMeecXb zP*H=ssXW^dla0!-G$HZ3jSng5ijfWO2dQ26U?ayBhh!0#a$Ke^4P z;h$Qnlr#hoXwN31L-rbZJO7+r$JRVsq z5p7~0^SX;@)u~9tpHoSjQ_2&+|CAROPh8%6%HY6ozw%gmpG4`w{-J^Y?(bdE-?v^l z%*^$jux@Zz?c;sB_)u{l-=8vNpCbSHj^pGVKi}fukCQk5kSPCh_JO~}R{ftmqacgQ zzhdjYv-X|kx8`!blk>d&_N&fl%@L{32@4m3-gN=X1H1mJ*v` zvCD6H|NU92HAiqKhd+FEoHG71RrvD4j8>)~-Jjz7vwgn{|7Ol?Eus?B1N2);q3i8_ z384H}Vq^KJQER+q)l$mk9CQTf@_$nsU*rFr9R4NVbFHmXo1fc%Zm9)%Q%YS2Pon*#EA zo~tyJ@AGX?f|)?(T(7%ggqiRYD^FYjON(ZL9;&tQ&vOH{k0)Ih0g74>Ujv zfINp$pFDZ;bo_I?MN$$RiGo5FLPThQ+bOYwz*=(m-Pduap;olT(8JUywU(5wxm03T z+_u6r3}^|)w@p&nW<0S%jfzhtKj;4=in5sgkG(+ik;1=t!zgMxsp{f? z`sYa)+Wq$NK~y0b#?Vo@k~bqi1ET~CUfV027G%zmXS^QBboYG3o>w0+b27=$ za>!%_J`0H2X_@jG{^Sqod@Wl4y3Rw9^DoZS%GB2%DVzjC`T41pquwy}=v=Ncb?Ve( zoPDOCK_wTISg*e1W+@O`3`rp6F%|D&$?~+Rc(bIJ?OkSpNDu`H#p*|Nxi)g zZfkm%^{rmryKH#f;E>AA8d^WFw!gQ3ZQlv2`+Jx7pRnPi-u{gcibDhI)~do3oxP@S z<+{P%lluoHwP;fZ)+SP0CTrNi{`HW4y{r5CRt>4vNjh=ay43(Zseib4P_@;iLG0G0 zouJz5()v_~spN!p8`dr#5`-I7XMN&`YTHNGoPa!KVEOP0Rob^MV@3bKNh^j`yTNmE zKZ%nhE3OH@sp?kVo4OAW2+U)?{v zZf)=KzTrM;Wbeu$4C=n7r5X7r46N-N98uG{voJuR;*@Jn?TvN z&&+J|i34kw_nxqBZNHk;IDcsMx?#0{ll)Z!Yt;e!XEj3b_n+Lqc31_OtrUR1wHT6N zPKU~Y4Y3TY>Rq;O?a=UG-vF>x=QRWb#M+?~*9~GC#_+Ry8p4xzlAzs(HU?cWGBmJk zC<#5s%5cGjRR5TnM^@UX7H8(MmJ#(&nRzTXqW-xdmuv0yip+eL z)%i;rvZPURVI}|(7=Tx1st2~*>i<_Y6e=tFhE}M^nv5p=E>peQ^2y zrH&*Pz@m74LlkJn^8P_}WS!WtC`cG9p4Id^=1hV`vY>ZpnC+T8KTUup&|(ItsV|vG z5hKQqGGnFt0{yaPO&>HfTMo-(fVy!=%`jY%0kq-dAvN95Fe6)xL)b@#L>Umv`v$3B zVM7k7sdID>GQenYfk}r4mO*bF6*Po{Ss@^AXk4QhZwBmW!_XNuY71;Vj68KrV5R3tK*?2mDf^P|8GO!+N|Xp2DNc=tdX&CwlImd{*p|l z8DY9nCJn)@)?72NQI(njQ+6bQ|J`s)CT0Q?0O~zqM3d*ZX21qx z1pI#tb7Z!08GM&P^?&Qgt?9X8J+Dh-yvrIs2QlZN5Y#A%kSeTJ>$9No_v zXmvsZoPEoeXW(4c0A~%fTHb)dths;9`r(lnv+8dEON?pQ6B{r}2HqicQUijL?#ng| zVj2&t6-M}{NkkZNfsSf2c*6s0td<&R0LF$Tz*aV(wHDSQl_|Z9?4CR}v_SR_kF4)k zs~QNA1nwkbuQo2=rPvWIz&AJ>T8Uw+Wfdm#didcl!6XNrm zGT?|Q4R>0`cyemTaIAH622?FJLXA3RjyG-`B1*&R^enhqbOQILEV$an3F+VLWYC^) z3AwT*3r0vAi>Nc43?`8JRtr{0p4EzOqfGo1{Qv$TkT-r*IH1DqvlYZf5!qyf)z zj0s#vPgdC5H$2?8Y{eP~=>+n#v&uw`%r0||^CGS8)Ai5-$*g5tRteV9u*A7pB}g5X zSPsj+cikXdi9}D{npMKqky+wACqurm4lzED&X75XQ^MX~k4R#_I^Ss^TiHV4vw;i% z+aLj0X%s;g9V1irZB7Q1MH4~2-N_IImR@3Vt9N99SVS7+0;hr2L7xWJp45Bd;JP*H zUmMp%nBjHm7^7yB{SvJf$>HAR1A_=Gi?4KHqiL&)M+ASTlQANQ;rG&V9Oz%J-j&rs z3>k+Ls-kcCh`PwmN$X_xY6}+20LxbNtBdVaOJ|?5ZV*}x4btIC^=`-5O=AG+fbAt# zm_*Pd`|!G6{A^fHx3OPc>ZD^-gpsIX3i7f{NQoV$Am8H{2P&#J4kBNkohJe0D=ZADhLO+kUdOB))Pbn?)e(_=n2-zBnts0>&S`Io{%~fkEUV+s*Jqa1c{kJ%oOoF_mawYV%+rX5 z(&|WNs~a;Jgh*-zZb*G3v$hn_O-?$VYMYcb!iZC+xq;x>p!3r)HH$gL4+vSO*@lpH zP<1iu2wxrJWW=lmWd`7a^h_k6g!ez1Ig%1OQXi|!=%(Kxgb+gl@^?%I( zBLtjIW+_B})5&Zf0>9~GLL=sz7FkTzfy+-=eO*(puR`R9S*D7DFlzt7yF^_pRR0 zuij7(z#3zKTdk@|p*RuivKGm088F0>g!!zUdMP|u)T5Hut+_n|NC=k%`kYlJDNKEF zWP7LOw-m_9>sD`otF+0O*@;}%VscM2k}#3Wp*^8*bsu8hYIA)y3)}2b%geerOKSOQ zxHC?cQ7sv19w*17pIVd0O5(gbYJ13PlGN^~=^=|IbMLeQJFc~681AagXYrc+U5;7) zkINg{-Cdi*k|yUK%kyy=OR{@wvslPx?Y7KKZ6Smd-qz8I>2_w<q$0qYOUIDIA(W-u019AH^`cto*VP5$;1w_ z@KA03iwyrqGa_SN)#jObWjx&4y!Cw&sy#Y06TEX0mL$Jt*&;5=cA4DoJ4U_5x$M>!A7c73*#HreOYXUC;S)LZMb43NH>_OxskLsUTGO(T-sS5~S*sqa$uqq(c|UW^K07IAOt#0ZnUhHDO-BTNZe7AA zK-iXmne~K~?MX-z!-yRb^@|$*W*2Hj>o04FXPUDPv3anl`c)0_qD(XK_tX@X5=1Uw z>en?zb%{9lH&)9@<0HfxM>O|-TLV>FK|DjBw1$M>lEVF_5x=uOyJT^U8dQbZ^!stc zj;KFaeH7u<)}GNkQEH@lCMV??+hIsJH93ozPWN@$ihCqrWcAC^g@F;7ywfmw*Sh=^gCWnP=&RI1%Y?00x zQQK;A;xd$j(Z*9)a#AJ|fyo>x6G^{hPF#k9FPRgUq0BQe$*4beK1E$Vy#|DZ>p-4% zqP?@GwS5?gP02(lhs4v8iELvZ#$t0aQA3Vkk;9n1anmA_K2wvYOIUJ`x{b= zEHUAQrJQ45v4Ja7TP)54v-4yaz{=S$+h@w;Art@+0c|)`Y0bXZfg^$C{{Q9TZy; zK|Nx_L3Ln6rj4<0HH0B54fAaq)*b9W2@5+(x|>B7ouS_5n)Snaz}f+dwy(Y2HU3e3 z2}|&X0G8qn0W8TI0uTdfZdR+a+YpiS*oI&!s++;dMrSAf-FBqw!HCX+-P0J1-P2$r z>fXj+F}4x4+Zw#}l@goYT)VX~5OHasv#cSQjmhk?-PRb2s0`G(jVolUG!wqVH7l6) z6%v&Oy1+FX0P2B=Nw(x(=$d8MY#5!2HPwcrEp#_tyn3f=R`;^8(Rf^U;)!UXI<#rE z254?m-XS*bGJTiTJK2>Ic;{5>PYPHO=~_?OX=t7Qi|zcaFVtZEzS}i>9qLPv zOl&X}-;lcAj&U}i2D-r-{MkUn#vIwz+H1xq8#DsD(J@=+v*8%~UCpCmu`Yol-LMEb zEvv{6?DSiMtsMzmb`jbz)g_i%X)w}i#Ri;LGf|jJ8v)9!NdR8vnnkZHjHH+05VFLJ z4aKrR6JRef^DGO@GT>oGq-MdeD!aaxl}{X4M(A66(rWOAr>})(4u{NGg4}hE1MC@NcF24!3YoQvxrw)>A7t6 zz3lEYo|NR39_yhle&>VOC^qCV!D=zdMU^^iVp$rt77ZK1M|qL(CQ*d;eMTX4ob zwdYq-r4uBaY$6H*Aru0`YW3ZlqzAKf@{Q3-RYX)2iO+>{J4muiESb!`$%byFN^@B0 zX4k}IB+>TXo^gtc%POPvPdwF6SRIfBp~u?D$1DKZnW(;9Yyd(|)F9s}nq6dBSTNb7 z(NW0#lWqfOGl^=UKV@ZR&32i%pHv2#@V8iYYXGUCK5Yd<11Rhw#)zoTGy!8f4cM(# zAT+>s0tI!nM^N3?1e{n?;GeZ>wE=coso0M=q;78lNW2l?=UihIHNc4V_Wt2zE7Z;= za71X~?q~u>#@?`YfXAZMolW3~&%)hhwP=I(VgDw=r^f5afFUlzoM&}T1`OLZwC==V z*y%&je(?-A>8FJ|%}m)^xM*R;7>KpGtVmCgT~-j+1L(NDQGE5;F?)Z=uD#X+Y0mzz z6+HC-hFkBp;-D6S9W@a5WY0GCB*mNeWATp8$!8 z17%B`>x`?jtb?oBV**?B8`U{u1Cud{nF~JS#>_P!ZnQ zqW4IAd2D!7g@%8?>Xl3$j!YV3C}si)J$Y_P?Xq@qLpW{Vn7Ca-sHB}UR?XJjiO-$Y zPkgq}D4L_2!I3fsZnxV^N)us17k#g(NGH|=aJ1you=@mt@zJd37ALKcW^lHl+-K1Y z&f??Vi)MP;;GYgP5mX>OBGsq;>VT+l7azmtsf-u3FK_+Oe zp0*;eAT$b2E8QqoWTOFQWhM(mt4kBr&jN_$!-twxWtF6fm1JSE`mq5ByBw)TvznWQCSu3$ z+2!vv6fs3m-?zSR8Y(gE)v?KyfP|DJCd;Xj8q7kJ;HF3ors3?E>iG>dXab#SILjg% zvG1S(h()y#dkz|aSS-|X4L~dws4+v+ zhlcytBbZ^eNdrh}EFq&9NuzEFORwdAh(2|ivD6#E5-YYj2<#?fQZ|AW+9Eh8r$t7s zk=O`Yx7R>#9-|pVy}WM?S9%lLvI!+D@aZgT4th5T1RLT?T1HHX?;) zz-C~xQL_;sF&YNyJ!$nioC{Rnu%3LQGLW~aBHy&Tk{T6ZHC##|@7a1D8mn!nCtc=S zW0he=hPiA#-yTPQQboRFgU!wQBTQy!_Hg7EG#EMbB?U*9-42|B2AL;#7c z=z0*r!ecvQVBwjc#vsJ9j7vR@LD(sPoZSROuq2N5WOQ1vaG9uaMZ_|U^E!3qE`NQV@QoLf*fgVe-ft&F6kf;ESSd7#9Iq}dJ{F1z#TPZ zOB476_6YvXV~9)bznG?<+Ss5Y?i$$tvAgcFr>=&LnsJ8H7(7NDfp2NzCXy=VIMG>l zyHEz7!D=v2KW*X=3yJ&J;Nt)^@Za9Vo)+RpkZ)@ONu0a{P+z|CSd-d`Glu+G6Ah@Z zEISeVs7KV}O=PcG`uTYi!bpT0OI!Wwi6)4Q!~BbA$Dq9gfJYTa)Gu9oL4r+ZUl_tr zzp_WG?ABu0%QmoFO*cobqI41p>3i()sVGA@0&%Nhb+p~PXRBcueNE)3~w0hH|cuMpH5QKvq9JpQwnr5b!4E~pi0@9M6f~qdv+$wSB8ig`a5vDjll@z11$5HN$FJ@RbIz zHE0d&XYH0edqf@%k$is0?701{J*t<^k2c?$b%1ofk)lsp-I>ns>pS5DZulLB-oR%Q zc(haf&icKXz<^+kXW1|u|NfJB@u~W~4fl*$zi)vB^eqn_dY(lzG(jUO4%BBXjSG8`jE|r&t}r)k==aufey+)-6-Jisjy3 zd_`)lzP&^4soqg+fyQ07>VNm)1otfvI`RRu?dPTLo~eEF=x7Vix2OmC}qws($quJ=~&Jny^S7Vmug?)Nr4yxn_; zcY$}I_fGFx=OXW2-o@T^&bz(Ky!UvQc;6^)_de)d=Y7t**4yb_IXq-*~_EoRUc zssBm;68}^FyZu}Ii~UdgU-EDFKjYu#-|2tO|AK#?f46_HzuW&jaKFd9AOHU<{{Joi z`~D;T7ViiC5B(qckNQ9LAM=0gKkom^-{b$>|E2$=|2zNJ{%`%K{6G4?_fOBgIkz=; zR&Gn~jNDstXXf7GpO?EZcW&dfU&iyR+^W5XPU*&$2`)zJd z?vJ@Q=eOja&W+|z&!3ThOa836@JIQ5rZ8H(qIh}ny~U3gZ!UhKczdz+nIG@-Q1Quv<8Ahq1S<50t4{d9 zjn2xz3Gc^G)m`W+Jb#@@@{DP{vZ}({)N9&RTR6XbM{!1Y!FK1B>SeA9FSQTnZ+F65 z=A$h0UWG3WtMV1OMR>gk8TkJpu1!D@7K;xnpY{mWU3mI#Tlw9& z@P0g9UkM+$(kWk(3%`!H$E)FP{q`{4J{`S1hPQLOS!NHOZrv|L0?UkE>4abE2p_si z-nQcHH~WX%_1pP)+u3R%FT&d&T0>OMa@+Ct%Q@jqx~}W+cE|qVPW^_&@S_K^u3PZ* zkq85_!*^6Hb~H2ma*r*8E`%SA-X6l+yAH6BkKpYGtsxq~njgd4r`qh>9=zQXy*-7u zOQQO=T!nFr>f465D-N_Rz5s6zM&&NW+YM13x*vXOHrsz4o^FrmdlTMHpKa-T3*PRJ z=(`hd+uAI3cH`}u=|>@EqnZ+CiJRdxL(;SPDM;ES_uOb-3>gT?Z6Rv#MT=I=?w9+}aiPgrjrH z3IgU)Km(y_^C6u0$8EdScXRmKbkx+ip>DdNQjcw@%WD0=H4SxjL#1(DNJT@n6hmVG zs2fU=*EU;)!K$j)tpc~lEmrYEVE;A#63Wbj-L6V5@c1z6WnLLixmN~fz08{yUNk@O z!t%=UMMW2IJ+5DMq=-|+i>f;9s^qq*HX>m*Fe8~_wG9cresC>%R6Pr=BKntkD!lBl zzyo5os7$im@_vrm3=m~=sNBur$L5r;0z!-qM%Cno>a~FU*c^?b93}~=9aB|Xui;L~9Np7>a*@SeRXt1upu@$g5aCfc@o$vx_%cK^x0yGQMJk>b^ zJpkpqNlGsa@DT2LHwjcer#Pc+3V=W}QA?eGJjC@g(ux^rrHr(4Mw(14Xe*gm-+GZd zd9%Ao>I@Yt#L!fH@c4aQ;hj$T%tAF!)wa;>4)SEmAjosZOvBsP|7oGyrBll~wTQP} zNcHi1+hR~1w0=UZs=Dao4f8qZrBEH|g9~y&DZGCE%6ST05FYj#5b+`Pnm4vp+Bw@6 zy2s$hU+5msx4;MUFLaLupZX{bDhkNbKvg`B9f_){1z`fPs{^9K3h*!k0uMQ1>ucKa z0b~$crp|Kxa~v1}Pu@b83HUjV1u?vQlL0+0@G4Fl&=<A-Fik>e=v%-fJ5ef-b znAZY|x?mg3tPkZ-5OeD|&h{Sn*s6bYy9;QPCQ%%h)d*tD3yLptC`rgZ%G3>fbd4G8 zKGTTMF!FKiGfA52HhYM!w<|UT984NZg|^%1q3$*r+jbYYfY@|c*XF$r6w2&(00G$J z9#eHzEp%4|1=J|*B^gUWJEqgh$|MkBC#chj-$g4cW&F%tSs~4Wm6cZfkaQhrq6d*i zQt&}l{kT7Vg+hRstLiA}jR(G>-AE|`Ks|^KDCx7uXl)xv!vFYs1W4s^B2YkiOyqz9 z0S1(e50KZV`Um{X!B2p>0H`9MFb*7o+EL_~|Fw)F$1qgTJ{@}AWIUlA4owZqFN zhgXBf7@QurG|5vkPW)3WpH+lr;M2-bL1YIGMUtn>dch&cJTPigDxKnFX}W4V{;(5`MP5m}9T&A-{5nL@M|}jxc5X z5QeW8LB6Q~N|iu4whE19k9N)kX9g7Hx?cA{ zG^}e9iINMuR#qklE>(cH1fvATOLF4tL>~M#aU!{pQX&$dW=5mi(?V}mhwm!i@nu4m zt0J6!1#1V?gFFa-Y#-h5_x8~Xe;|+GA{akGYx&yZLKkDg*PftFUKf`(zKnMn!r`+(D_R$M}W*`0VyY>-YA|Eku!dbH*sZd2X^`VHQV(1Qs z_b*;a(MN?2-2==JTSvCLC02=@6D$K~VpR$fa5i&=USaC5kkELpyBYBIRT; zETU8!D+eb9=yrDrluJ|UF|<(V=SgGb(Kkc`Y)<-!CN=BA6MwQU^w@^d`#FsFOK}PlZn^YJ5BD z);@wbUKMVp4U`MvTg->8Q*msO-$@aSB3S^otb;KpW9TBNn?)AD&Pp&lo9*b%kc;Kf z6)uMK6OIl2BVY|WqNvf za&{lxFe1M=sRVj!Rf2i|2Q`+G#+Xw^8f)dHrLl-%3a1)vRDdhOwy}elv1q8)O3)TQ z@duMJhIq)4Y*JBfo(hcEHx>OB(^&ezilj-EmbRdUBoOU0%{G|hCL;nja3PF)(Q8Da z_1e=G4>dI*;6n?#Bsn7dR-d+{dhY}+ruSM&CVDRe2Sti;E78Krhea2j*hgNa)Wfg1 zpgQFoJgB4p6FF0MVAw+F$I*>&3DLshQ8TrsMcHyi1$i@y$bu03>yxt5OVpu1y*WfGgwgYiQnBxRqs#9UGOX{)s1#=vZ zAF6yYR)o_Q5kL$Qup-R}{Pei56>}2|SP>h*u(Yk zJfCf+8lxrzZ8y>=vd=fYWIq5WTW9R z1_i1{x-JwgNLwyx6gdIG07P}~LkJu9%D5wFnRQ3t_7S0Q0RU^=5jszhbQmj8-CF`& zK&;&lsSO!)KSYd1ZY5eyw^B>5W5l_tHHWG`MM>>{B)7r5v?p!5jBdb=yCh#hmY9DTu2)*Reic=x-|=e zvRHhkaZ7?ud1d2t_kIXWn1}3M^ymqGN!5mtJZfd`Cp&%PA}eq;LGd1xY=5XBJ&jr0 zsi?#Ye=&$N<9Rx?EEpR`z zRg$nS;102;q@6r!>p~ti(>V~V-@p`{W~gM!k~A{A5LLI2Zb(yCQZ<$2kyJXOopv!K zfc6fi(X@-_07naYmF*z+$)hXWCy%-v^61NKgT#z!yU=|tdX6F`aI#OrcHC1Jw%47Qfph7y}Cc$;z4vU9qXql{6KIhNc3>bQ=b@$35Rc zut2m-3j`w#0Ann)#Kr=Esn1QN1rgv-?63oAFVKF(i%k`rf@o!1Fa_(07@k;3qyOoxqxDH@wu5$zh8Sqa+B zV%Y#bl9*Wq)S952W)?BCKsiK;b$w(O8kMla#LR*TCLuVe50gWjnsSW2VBUJ7<>>ez zJT6=wmKl-03*Cu160M-#1zxc5`IiQ^{TCBSV6^5{R>tc zR7HXBSiFi>pgTuF_Ti}{#jAPJ7t|_WS*(D@gvcY9#7fzC(2}UI7y+g1ceaI>%pw=P z&k28bAeV^B0E4xyBkKTcd%fde9Shu`XqvDuaL}dc^3G-;5q67ow1oV5YKizd^~k5! zA}0fYD^Vm}ZK>@d2P-Xsf*m4N(lZjSV_lPc5F8IBahRO)-Eiyi8qtUIl5i1vK;W5f zpup+Q6QUy12|9pO|D{MPB-702fB>55zp@pJ`QLWo)t+0~+_4EO1@l)`D|)nNhDCz@ z&Ix7;`8jZvnW0nuzGq1%9uKgCex%$?bgxqN!tHlpgfY{@i>8E+D%j{)(D;Q{p#Xvb zJvZ=Zbavy7;k-bn&O$033jDk66)(e_5ug$>AN^;t6SS)s)D5$z%vmWTj`%LfyJ7LFdKaj1e; zbPsf2K|i;P&s{`s!A^NyeKD>cRD_^G%#>vSzQe_QZ6zsyE`U!4KWt_BSNW*I zprC`y#HbB@jZKqZgCpi?-~&BU)+digO0d%#ps#tpOG3Vrge)N$zyzRQp zwClDBwrgj7yFgo+i4pIG5aD1&Jsre9duhgOxapx?&O!yE+W$!D+nmtjVjLdXxp_*3 z3uw{d2{Q_RXvpH%t$^_SLBw9qd`(ZwB$}9Hl4#^XPlP#Px?yxb(()>Wf90KpMeYtq zlI|+TN!RJ5Z%mJquGdKymExqEbkg~WuTss$~?3g}J%A@-CN7Dl+9iFqbNrJLnMLTrx_7JD!# z)IAt21Z9m7qXdkEm==OUX+S&)gn=fO6=IOI?`wyot+1EVfDRRchYA#bWsMaq1N-dt zlma0=fui*UX2+hu?4&190RPhyfIfkr3U;cp8;9UrYyi_LbC#7!z9xRpC%LAPF^hpd3b!V8QVif zbO232tv)axq%zSZ`o%|&iB57r{`iF+0ry8xSP>uSg0Qo+p(rbR1vWPPa;qNNJjc?^ zS^R223>B-jv5~^<(ndWObpK_9v{?f3fLpuG0Aaeygxv0nh8LqsPlujryVMn%L>@Y; zxtU?dcqtO|nbV;_E@Q`PCO=j~wS>X1Hd*vkHKvLNw^OwT!};($W2&@BcJ82?|&GFKpQ^rP! z4S*il#WlPDX2vWKSz9PSldoq8&3tiZFx3n#G?!WNW*LHf8|l=*Xv>4Buj zYT2fDOZs>BjTLc^qR2o)a_hJd3PdZzNB2w6r=YSNXl7>6vp1Sl)?w6!SDlV zVXz}^jgikY>HT8*6|lVx7ErjwB+LjQc*BqFtFvc>pkR1ew|T?!=b6)v8Qlg{+`EA7 zlhZJEcNVb3g_m18%ru6yE0li$Ulcykp1ij8E}6zXRxm=*mL7L$72#in=EyXJ4YVAr z#JOXpA*6S58VVm2$Op%h4+_|hwUV-sl0jVT0?WqS01LF19hM3^a3GCn(9J&sl0url zf>V21P&}%AACX>A16*=}P=ORh5twE$N3i@vF@|PO4(}|{#BSpZK+(Anj#}t58sExg z=ed|m^CA0CCzwrqPtj^ddVgEu9FQgn={*;K#KNWP*02XY2Mg0k6%7RoTCh)8k(j1T zM3MANM3KzL;7?eQ%olaRMN806zZgZLUyLHrFWHI&#D`GfE>I`@r1m9bUMDSh43;=B zvZC0nrHFVgAZesgtkQp}(WqAE_dsO8K#MgB#zkaE87d{R)=>pOCah9q+g@{>GBs+W z6Yir`p0^3g zB-95$4|GZ`dxQ^*a{G$3a{8wFaG$G}=tLa*lL^Y8~zx%p>*&fzZ#) zvQ`mX_HakhT1AEMdRkAgiac0F$6*s1Xc3te$5XdqRrDx^YM|wUHZdzio2P7P+gxi) zL-Cl_Cf(RJ+9F!6h+C2}N_I|98YS!Njgs}SE3lnlLRQK88mr_nl-^5biEYe8?2^?J zu}ip#Wx{reb%@0-(J#g>(J#g>(Jz^HNhi1m-tBFo3J^nvpHm1rBNfCTQ%VI%bRub? z*sz4LP~xz}OS$?3t1)Sz$gUde^U|=T+9_X?gBpHTOeV$Y^ume`Z>LdzN1=QdR#@~XKq?zibtENTR%JzK zN`N*%WWi*|Hhlg_B&7xR7P=4=B$|TF+_XJ8#bwFWL`FDAVXNZ@L}}NNj}{wAAs~`j z$QZzh7oXz8=AixYO9?d~k`hH`KqUmKM9iT7k(mGIGd<)7pctQ5N%0t+t%2GR@V{U8hRM>ao0 z?mZ-yua3?j&VrQRMoTF+vV%Q>h}dsN-VL*0B;8S%i9O2#`#4E>2Ldv$dAZ`2$jCnMzHsPn0=CWd=L^YG)Li_|&wd88C`ic{(^T z3i^gy=-X)lJFf7=DEFkq@rkGQo+S`9XCkJ+sS_~;ws6gA!nOb?l!$hlH)9Q$H)9T% zw@iD0`;EY9W!MCdh)wWCV-t9PYMbCg`MqEhc(pcxm$V5yV-s{zc+(~TXYK`?fLQ)+ z6Ci@y)FuFx_J&Q+nTU4)r8PE9yki_T0d}lS)F$YR1h}rTUVw|Wfnd>iZGssYHUW;n zW$Yj^A+$TSO|UQI#I4#8;D(Zq$L7I@|85?{3%i--f%kXw0P7av!wKcx2X*d+cg>2` z`BF(qF8RDxQsQkK)`U1xmyPyv*z{v0U6zQ<^3So7B1=Rj1!pr*Z*oECcuD!mEQZ>& z=|XeF3$Kk9mZ}Kp&>-=`Ee8d&W$lU9jTe5V1_YK3(%x%9-~i$E{0L-`dpOOMQ)#fY z@CmB7-eQ6Of}<3X#qw}X;NtuYiv>GfTXDK&Vit?+qKz$_!GBU0(hFi zFvHI7a8H};3=XfKgJldJ>Sc;7XyB$Hg*A=&41;!tU+l(q7Y&MEY#@<9EL@TWdPjzo z*NIp`Hi?2tC(8M2?A^dZ39@Ce1?wvcn7`E>K4uz$U)h>6g9|U=HFjSLp0DIS6s)qi zXwf2ILAj&}MVq8E{9v??hNg@}X6H-o!E9?gEzxDqqZuTo5+M(#Td^S2SKh?1hillR z$wX7FGi5T-OzVtIrekRHY=g~nRC|e!P~-LH54@aYz~)EXMHp=+xgx{-xq{};_6eFl zSJVb!()L%Md8b6`Wd6Wx!AUA1gn^Zhf^qD>r5IK7$kf6HKevmFlQfsuK3DT@;9^6mO*wLQP~V4S4G>e^CJ2xye4UtBRw(k`nK1T!eK$!hAoH zu#31nhLohks`oS|cQEQbjoT1MUvlZI6Xy@Gvr#-&AULBvT#TUjjW{c~NHBiwz}T5x zEGhSJN2Z)#p!{d8XC@rp!(&{dJkKD0FtEK=Ag`E%B+&_r+#@ArG;+NcxyMLKGV*_{ zq};&RJ$FDJC$DGO*Z(807unbUE3Z%6?UMf?uUFaJ=C!hNmc^WJ)w%$J<;?@1(IbWacfF%BoyC- zU9hXQUZ4y1-dI~)Y_&y_Jhe(A9_m~Wy-mJ-wjYqNi7pS$VZ;&;&rAFn)Ft1KG7r+ zo#4Qsc-dlt0rRUx6PGN9dP9{k8C(75;Q9~v&pX%epRrbQKr?gc;kmMDf@>uY>PMPO zU(}BjCU@&cY@$oZhrjU&@TnK#1khUv{;U(=n&*E4%*mJl2R54kTQq;~4_1HrP?-yK z9e$%9ITs$+kDLoX)Q^9k3p@~-YZGPgf}9I_k?PMn7p{H&=Yp75bkq~RbEVl_xNffa z&H-3`yPg)D3zzCg&V>u~Bj>_4{rLB}@Is#pI%4@}oeS4J|8rq>hF<7yHWxm3sBA3d zT=-P17d{f}g==HI@czH+h2%QT3sNsI9J45xbX0o>pOyrZBrb!kQYzu;hfm3}hIpOG zI-H9iMMQR&Gno@0|A-~ zuSoX67sH3AV;k4~vuX4P)lM!JIovCpx0j;u7Z4xaFT8-qlB>9`luJAyOk4Op7LyJ7(Hj&0o{q&4kJfqnx{>mYTDfN$vYV7le zm;?LxM3H`^8vC?<#JMUCQ>|a~w-XI+=at((>&DVm`PX?k<=mJrhm*#|x;R^HPPZVg z26tQ!Na6xmbE89wb?YdOGaAt5@0e&49k|cN52{sH|sef z37W9`gm*rE;t)|<^yY7j+5MWB-QU-Q-8&P+wyJz z+Y4mmaG~&0$Zj4xF(Y@T92<<{sKTFepRjz_1)qe&&UxSWb#sp9!W_qs>6x_jJ`N3c_q|b zr0Tn)m|D?m>p0AeeSizG@6W*sdN*#4nh&t#l@Lz(DO`b$vk1 zf&=$LU?R#q>zYn^ntfJWkY#LG6h z+6rDaHhN4%zF;$Joq$Qt-H$}qxdgndvtBM#8{BBM(7m2wq@lpL1#x;Hq|9iH0@u?O zaZQxoB?Gxp3~!W+w`ARu=bRxq%2iLFJ%ton4_(G{&Q#o7wIubpe22vVxjPGoPqm0m z96seaXQJWl=nifv!guOe8aJm>uHjD2pb(!v^~PGY@K6^|pC%eZ%L8}Q%1PJ~v6{x< zA}?O0imJ^;UJ#C}*$NmQQX>z2Va0++j+wR!kNVb4G`Co7lT)C1oJ7TiJx8?9q--6g zpv4L?`akU-9h_){;=nQjUaAA^ILIsO%jCfga>qYTE15N3Al4KF z4dCH$!6l1=ODnulS}y0o{%&4c26&PVoi>9L@)ESd1c9lIw|w_!YEOq5K=+zndM= zWKYX=+Qskzz5Rcodz~Zh&MmSOFV{-}xtzvJaqB3zI&I;kCDq2suA|)C74s`kX?G-7SXW<36S~#;;3O>r!4}LmveT zmG)hbtNm1P4bSqXiUOSthF2`#0jP)3PohHr;W5g8>!fKbCd#4I8o zAt9l(S&A#Sd2gZAjy*nRFEeLaR9!ckSbDj_eji;gGKJ{;1?@yS^5(IqUWyWP;epxc zKzt(0OuZ4tHgP{w7lGJ|-6Hpl*tL76QQJKN4cs$Z-nwUviW~QgZG|z5pE4J@RY-|9 z=4A!Aj9k+r1@?Y+t(H$b}rMc`7E!^AajNL;`|?qjfNLTlm0 z9O4v2CKJL6Njii&E`J>;&CFm3#&T+6Z~%a-P9PU+cKzk8FAZj48}PBw$jlAMk37$v zCNbFEj1Y!eN-1SFMDkt=Eq;sP&v6|CPf0@^LK3GfmiPiX>1o=*fPVdR5MbKgAb^9; z?wX@J&tv2~|5XgXHbjk-}=s3`ajKTw~(INu_aHXS z#cJ_>PfL{Mfri>3LYi0~iam)eVmW^vVg-AHSjF&a&Pv{L2_`d3;T-PHu3qnP2 zr{go5h&U|1+1oE+4b7>|hUih2==I zwuY0~{`4i^yycNs^S*bUthAT$c(J|Zu{C^~z2y;2iS}aFu1Um;M|*Fxp3D#j(UehemfrYRd~mk_*S-n&EH&h5^ZM&y6_>^`Dx+UEa+`;YLkw zj>0wZD7-H*3O!=sq? z<)?871u59kt?e|2!b#=}1Htqqc<)u4zDEn@^vd#;u#I`jhZjRm4tK{3sjZ6 zFUtx>Ap2+OL-HOqd;PNAj%(b4y6czmNgE74+YSiv6lE#65Pd~L24q3C{WbE@P&o^P zMlBj=qvp%SOuTJ*B8^&*ZWOx)O^Uyy;Lh3hgvcU(@DV8&B@T!zfux58%p0S-_;f7n zZ#rIZzM)*vORycd$ge{3nH!_ek~omu^N8EuVKfVb@F^g1zYPQ!SVZ$G=Z&xjcon&t zSG^@XGFh2{5B=PaFS@(<(2q;--A>^0a_pV>4WGnUfo@}S_3eE7;z{nRX5>-tXRgpe zmyMmcI;y~hb;JSp!;@_4sW56Fn-ePg;AvL}a}U6i%(F_Mt3p6ls=SU>-ZCFS3X_0y zDw2U?k2(XvWl2DMM}AK==^ORyYW=g^q%L)rjOV{VzMYA9SFt)3OoGA>tCgWYSn0&$ zllrj(kLSZrMd}nh?$D3z;gfem72~^ZQ0r4U&+#2i8feGkhsMP*m@Pgvx3uz(<8ah~(K=G6>~gAzd%PBD z95M7-`a~@W494HN10SUoNvK0luLiH7ErJ5(MpZsxi<<@CSi$G8D!5h*eQ61OesiWJ zJoSy0Nl3|~n?wh!XvUE%`4{}svJ!a7tAHQGVnH&mEzT=8$tw*u!s+9xLNq1M8w>Nn zBrUnkfstlyVH^qNO8BYbZdoJoVLrL^P4Rchs`Bsh6%c`RBsqn2(s+I()DjQj=`UEy zX%j<=GIS7+F?xJl)qaBYcq3^@dL0_lbho8Zy{z1K@e9;0`KDN%B)eWFaq9Xqes~P3 zExZX=jz@=!8H>ET0F?rk=qkS_FH^iF09=vHm65rZVn$A#Rc4b1uzv;sSBseN%vldcda>h__GjPGr3$=uM4or^U7tQ#QZ!w6! zD9AhmS91{C!sPIw`4BQ7uvzt%hyaM9NW??198jIZ-|L;~f&9J6sUF1No1JP;`B%6P z5Pe_})Ud|vN_Wr(ErJD`bS)5Y=wz}Ma85D2b{06tu=FABsg;9Wkt%duJj^9hzALY#FW{=!DiX2Yf^!7gyRfBatM|< zDsv`Q_2?^5^?|6`A7|Bb8dSYy!d0s!sQMsOU3`vJZv&s!Vjjwla`xnXW$|LqqCmar;;_UA@(quD{mP6;3{D6 zL{iw9(tNs>f2*e{x{;iwd6}kl*lVXLv1d+G>>H)vZ^SokiD}yQY^G^XgSj&HG)-5% zm#66j`dl+f_wHPwK7;|(aIRp?Wo;}=XT4D7$ajoNlWCwQ%9%xNm(Vi#9go;6g+DkE z|NA_3X;L#k$6msypk~I@8kZ!X^=CA5Ni;L8>SmHavPBZy-IJ6AXWI^j1xkXav?Q?B zSC%C3!?)|(jkV$y?*UCVABccj+(Q?Q1~nJj8ZwO4>HNLGsUFPVi=65q{Jqqv9$J1H z_86@ z?GkOurEQI8rSNA@K;bv8S}Xi!qC4GdsQlTn${*9hYFzd52^(0f`Cu?}d0bXbV^C76Y>p9lEnl(388EIPI#(ED$z0<~JUNz`(mU%TL=ro3wJc;o|g9~xP?#gV~ z?6j)IqmG@M=O{vrbMyQgQ#)%!=(Uju%}-c_iZS)vL?{I&1ZWR`AwWftLVzAJ5dmtN zF-`$`=<_T<4{adD#x}*$?ETjuKqoB4_L}^huoN5JTk>;)Qmj^bj%oP*U5ddF)V3=k zqW=Q>N<#6SFx#->mEXY?^9`#6ReU*NRTVcXO$*v93{~0)>28P7&#H&A*upCjGWpoE zVCDW+03X%9ul7q<@lz^09q1*jZt#n{o!E1Npd3#_@y3zjs+FPhMxYYc6}xU)R#q8U ztaQLF_HYOgwNA0oR)GnotPDCBmz8bEh=t;y2@FnM9%WbpQB@j4K%%2vc=v0O_y&nB zMhKSRu46&6vMQK5YKwJfzZxwwU#+2U1j>O{|Dpo~HrQB|fTE6P|{_si}Azo{CszF z;6*{s1^UR5i>*Qkb0Va$K(~fL2e@_Sd+muBI=qENLVI5h9N}|$i(icff>4XvP?bWk z&IX(3%U85*tzZYnI}x~~Gs7>QD!NLs%)gRQE3xpE@4Ac zgRlpqloHJFtCM6z5Q+AyQ~3xc+?OrfS0WvJY7M)v3DUXKDEeF}UXo#dym z%TMj?DAHc(N8@;M+|9@3$T{Q5@etjg*~h&eDf^T4@rH~(e)+GgkMEK%m)muLCn8r? znD$$_B-4(*LWe$IxJ>)IXh6BoE=y_8rmgl$Ip|8`!x4V7gH*>4eZo6xcwj zafmt?+y-2oLj*I{#3b6e%7>^+rbC2a2{uPEh|&^tBm*0IWw46q2uX%Gjf6J1eJt9i zhS8F3Yk?q&n$#t^&Fo5~tGMD>9UKQw_2O*4B4lz|Nn z_HS%p!w-LM0~>z$BOBQ8!|&L@h97=SKPobR<-R$N)9G6SciuI%qg*=WQ=34ZsjyP5zDxf z7o?50i-O7Ow-S;aH6`uJr4A99AWyiN_hNDD@an4Uq{Gv21s~h4_~;hqhX@kJ6c`D? zIZbX((?PAEBuuQ=@vjxJir&NDWIj&*m*0%FZj56rPb;(W8sA-CnS}ME^%Kz+Nz4w00wA?OuqYIu1AC&R5U)*ak&O0TAqEC;xj7qw zRvRGDl2wiyV-KNBU)jAV*GphfdHp>PRW+Ei)I&07O?)>wXS3sy5D_Lu1@1&EbX-ys zRHQNhxcxd6m$Y*h*9h0m*>qfzvu0d#_S9(3Vgmvv4R@1s(h5Dyr1kWqCB-m;X3}zw z$;RNX#uJx!h2&Rb;@;{rM4y~O;Ds>$01;TkPkd^z!gcj6oK}gCI3C11nZRhF!VCsW z$%cc(7aY06^SuWJa{z`V)kDgk^*QJDjuZ)B1qW9S4dztl20fK|;K&yR2UZRXW>+wo zvBHhecWv{$+U6y{1X-DnexZ4o-qF_~tEPD#+fegmNj8XERw42!ih5MW|ACu14tNisC0-WsLxOR#mDc zsB#{vEOKYVII66XI?t-gC9HBTs+7H|Ucm|v zL4~qWMMQce&=c~UX?i5*XD|;GCzVRIBbs}20zJvh1e2AT7qVF2k79j4iuFl&vZh!Y z#9wl?Zft3eMWko5%4DTEF2d$fpXaj51m=*F%38%@Wr^#>Q!sj!E=a_3Fa@hjdGw2` z#j?tTb>H%{S}jIPA#~wXrB;i(^eU5HEk=doSY?`8yUH~61+mJ6!=D)I+STG&T76?W z!9^DJ&DCN|zYoq$t}E7XRqQH3LdR>sJjBpo1z1;7yLP#V_7Cg87yrz)H44hI(XuZ9 z7ex!0i^22H|N5`f2JfH@{)A7k4F_a62@ScQ>~mcOj9Z`S*5~`3Q~b*;^g#BwtcFz!6hx>dC@9dyuMQ|?=a_I z=m_Y}qMr*w_jNDiu0F&-qg=EFi_@%Sh2H9*Tz-3@O7k%3Ay(-j#)c+ND%DtR-FSs1 z*G;4G!14w96ojZpeU5DoEY9xA!7vpMfvE_~4yGb}p(dsxD@fahL|-`&d~Z!aa(=ue zk4M0%Mw1R<+8$HNSiIvk0UKH>s0bSX#!)3qz=NRV{c)Rs-5G`hIz8?RVE`T^TWZAs z9CK4xwwar>RN!<5993=RB+uskML3@Nu#Xn`8VD0+n6F{gTPt@RT4Sw{p(-Y#@wa2G&^W=yY#0|VAGbTQu+stC*@ru%t(0I24^A8B zh{sXeXyhRHHl&K#mz z*f!Y%4gbj9a<1Kd<*4~re3^F)>EVT6iw-u^8fd|P9pUKc zZL0iU+|C+aa2M%DTiOfnF<HxenoVmGuh73qK14R0f{to_Ok}EtRc4uC+Hq&W5`K$DA0g62_U!Wc@jku6YzO6 za=~E2UFL{-!=cVLavQ5b+Q5j!l1ock4f3&*j~M=aIGgt2yqbb1>$mTRIf{EdBboKQ z`|VfxmFjcUg=}!Kx<5rlu>YT;?a>7u-Do-36b>qd{w_#7iX43lML;{X_CMJ%Y`sMt zZ^wlm5F?Sti_2!{xe7{N$|EAr=Y<~a5K`jo(XQl$9zHMh;Q7N6x=rDv?@gGyl1)L> zKH32e_(8;4-j;Ik4FkiGifJ^T@)lh3-;@m@GdjMd}xd$w!YN2b+Jv7)JfJ>@0Ys;yTBHEeWFTGEO zZMbivNY?LbBUwql`WvwggHpRw>TJ_`M}H4nFA4ISPgonIX@{R@HQl&CZWjUdMw@7B z1{FDFNOT8N2#XYR%p4;D?=CPiZoZB?c_FUG;=PNt2L2)lkI!SC#-TzeQoJ3f&k7d^x01A!G$HkQamLoK3oH>`luTP{!lAr@59 zMb$pH+JSp}xyp|nGPvciI%_6U)RDm~-1<9MnJSCJ9b?^}!}UhqpR+IKA>7CNfYkkdI%&^3d#{3UKw=L-{3e` z+G)3Hqn>-Qz_36sJ;k1Uv_L*gAhME35Y2rZ3_V?jv`4pu4JSl>xlfGLXHZptB%v5y z&N~r!w>~WwY~BLqC`|evpbmx%AO6uDLZ^e4*UuysNQ`z5+#a+Xfv@AWo2D~bmE}{h z}f;(1% z#zN?~+vZ{ozeB5sNjT>>8w`LM`X=0INi&;UkZQu6-JnzQN+!I5ex+bPN(el~K}=vX z>)4ZmuAoyqkU-xG1}2p_=9n?QZgE){^MY+DcO*z?sH;u3lX$#a)1~Q3xhJz#2B`U+ zX>#C-i)?1^mj?!8vAq`bhXkQefSMNS8-Hlr`%!{P&4d1ujfq<$`|-iVI@#aSNcR5> zvmE>a*5YA7j3D0rl(JuDgz!UUHYHd%U%R;!&{sh~V|o?C&lQ8&jGN=Li%D_ajn`Yd z!)xd83yffYtNa*+)LIA}>+;sf1xC`CD-J;(jtcfyq2HP^3H1u`rO!_$2*Z!bjOwfS zDH&8k|FENCLQJX_WB3Nl?S z#>=W&?jO{h%2u^y@g>l7_)X8M>F44=Fz0k_)7zOCHC=qNxao4qsWcF>QLF?6!x}f8 z0#sWGI$&U}gsADL%r+fN4r*KCYsH(%DUk?O~9m%+5r8 z2qr$$ZETqHORE3t!kFk2p3diG(a2z94f@=V1=t;6tl-f4)qQAo7TUs_JE*_! za>A!)l`*};OJ?!?eNOnh0~7C0tMC)0#Ctk_-0zIo_|^SUIaUz(h-Cyk9spNq5l@>u zDBjEga52m8%vYwnn_UFw0=&z;tx%>@p*&rhM8|6_cr4y_EX4J{2%P*-ZWPD$TvWOm z3O2jwN(04P2(Z%81DjB`Ubnz|05JBCayO_^s6oprTK8i)Dm;O^SkORE6Db7?7?fcl zSRZZFrm$TfRL1>K~9jB~Oy z39q*b19sJgdcznmPG(Ntj1vi~=uKuv1lxKE)qMyf!cMNBp z<>)sai%K=lkhj5(>CJN6ySWY4GynwCJ!OnMz^`9|-%=2y9) z6Zx4bAi(kim28P&Y<82|qv2KQFm{Py>@rf?(O04aKcY;@hOtXFpa=Lt+!>h6%g1>L zV>ir07`p+^7KX9uYQxWK56aq^!x{StwMvCC*UL)aWF2osW$A#5cL z=Xxd?k;8&XfIF#cB0P!sbs1zvSEp&x;i{0>Vzrkl*Az9X8WiM386;;3E*>T;F3<-{ z1Jwc$fudrj79)!*T#iM;5$!qhHz==nO_4EWbrV0B(JdrO(84(xyZ*vB$D$j^hlhMr zJG#mFBBDVyS7Dxsn$#Bt14YTNR{`Tw5s?beG6KDz1jGrm*P?6Ek_D7%LCfoAQexD^ z8TjGuM5D~Ov2Ey@*?{k0%3=Z^DJ+T!EPS*WQF0Ou+dkPdbC?cOxedkx=Q%=GpqSjE zqwgjuqaq}O7+kt7>S`fNMbo0h>!CS3(BAB(vCcPD41$hm^;qj0#@>LN0BJlumI`}pFCiD;Rt%=z{UDjWnoaG)J z2SNMjT+Xm#!4Pu!R2^f%`Vvg@YZxmTp8?-2(AChiv5ckt6}$ZLZ1y)x=oMK~Dl7rVQms_<1t%+LLn4E1!eQ&@t!kYvl?-7b4FzE12>Tr~+Osv$L?s zrM_&(Cv6DR&F`%Ngv%ia=F(yjr_!IN0^{1?tETMEnGSszn7i7wlW!&Xw5Fy>_&J=$ zOVj0p3AhglQCjNmB5ywvlL}w8NqjK@5VLR)8mr;JXhsy)B(_IGO|iMj@5kWm6jGAk zkLjUe0hPo5}!thPM-_Q znM^d1yAH&T5CD3g6gO}lOvo}oP#mTSkH*bro^?k-u=2gRYBy55|7&JtwwNH$=~A4_ z7;T|^#`kiv2V|0bjcMGn7iK7Cq_O|m858+RNMG2)$6@3^dCo)HO`TI6yK^pUfyXVal6ga4@4aeK?KuR^&;nGl3`hI6+w+d#I zCe<5U**&~Po>ql93PLP zeT+D&!XsuUzNf_5Ss-%;$@2Uv?e#84ptaPsw?<&B5&EmmC%qw_yCFhn@}Z}ECB^{0 zh${agkBM5rS`%q)pCg_!iduRn>Xj65l^CEQa@W{Xh2JKU%Kqs`IRS ztLnYdt9nvNda|A+S-w@4?PpnvpB-6#aRkxrD8Yc-_N?WeWx!#?TK>cHSnI9EZpC{W0>3N$opv^(lr!F*9Lhc=}ey`n(Z=iz#EbL%MvXRGo7eqaz; z1XFtV!|aClpE|{_Q*!j$nm?Vc=fnI%>-#6|?x-E}|*tq-)t#y}D(C9zIw#!(u`C#j_ z0!j74LQ7crTcFN>*o76ev?o)Ue>Mx^KAlKnp*0&g>-1@C3&qDiz;71cn_Nhh&uIA8 zjDHqJ)z6lPpY9^~FdUS>4i*G(#RNh|^@(Cs67w0==gqQFicoVM?lxz^@Tpd67)}z5 zmtiT;C3L!5)!Z8#5LS5vFpl_Q0(WZgMiZby2q0gtG5b%gXoQEt03p#fZoES@#;228 z<*5NYfE#G>yK*zDFm&YCmOfk?_xOb&L-sVSrocvq5$tm7s>7MR{=Si`{>1#}zK2uG zAJ#R}VVun0nz2RLT1mxW4ZdVNx?F>;;eb5Vy3N@ZnH(fM_|%FJ2k;kVQ^ow*B>#UG zSpncKlzeb?`1`^t5STVCC(q_!C<+{Evo?EKRx7;rM6(2hY7r5)1y&0xh2~a}fYmAx znp;5%R;xg0F54y_wS^tR4bFT@+<4rp3Hj~2PH0)kZw1}ZvXI{jbaSOz7V?Ld=cl#& zey_Hv_^uaPUMLDSg_iq8!9r+xP_?XE87Id40dIM+_-+td-dq$chL*P!1)D?5!>Z*i z(^}?&LrraK@!c@AysaqM8d~076l@DEFNK!zl7USeY;B)x{$m?!T>E7m>`-k0hl)!U zoCG9v@=GX%VH|Ajpj#E}EDA26TNNx91v}|h1(#ZZZLi4@&yPB;bw(RB%;A-awuK=7}Fcv*Tl{hFY&Z2Cb6snfTj>4)?~#Od6d zeo$S|^xLok1(;8T#`FpSI?!qnk^OAzzEQ%;k?H#%G6$K$(yB&6jrsfY)6~k6Q>;-` ztzA`1skWJFQ|rlnG<3+|^Bt-;wPLrZc(B#U_uOwC0r7voi z=!{OK+a2ZyG|#N0&O@A-P)a2#n@WfE*CwttM>a8|uqco0!a|EcezXy(ZG_~jwAhG} z8Xaf>XXQ4uPnlUO>{dyk4zz%nY7?5ZoNRRtwA$3FwxC(9B3s%3y@fwYqeq>xQ#`rZ za|{CzGS59a+wz4kjhnL;9=>kpOMv4ZzTxUyA%-AIFue)v2Jmd{Ib^E5m(&|QE#rG7 z^v-(9D~&9eKk&oS_W5-(Z{IggN(iBH=BqCu5(3LA!&43J!yYJtxs8S_zDA#HjXvUZ z&Ni!h;H&BZtg9X*lnSiF?V60NZCn&6?WITCM=3B!g||X^_63B`(*SR^Ly%phXo+{s8Q5fdj3h3%bhHLL*-MphOopF~W2#cEZ^ z5E_nnxHlZ}aBtXocq)&|mGP=r&-`Tj;#-;Z5b<&!dc@1UhlrPZ56;We%o_KTn%dyi z_&#eqV&~p?#Lm6(h@E@m&dw3g4z{*Tj#~jX4Q}oYN8H>Sj<~ru?A+WMCdK^Zg0EV` z#>Lh7Qdn>?a8Otb+#41Hw}MO1m^2nKaCn*O?3~u{A*&^>Zl5iOhIbVOmxhLS7X`aQ z!+WZRcTZ~=37hUOD?Zy38s1wJToxL>yeQZk8qPw)wt<&VHmwaL{~C>t*2kPHGwuVe zY`kd1LXOr1H94{9BFv*MLS#e=PV zVibC>qj1n%_tO_t4tfh#;!}Tfizsoa4#Tf@Sg4?8JL-0z3+!G??)DG7{vB(n6mI8z z;Z;(;a-q#tZ~H1OUk&UlSHkU;aU^SSSjbf{u@mFOB{nl%pzGZI2A8VfKtW)u`7Oot z3>GDNc7i|b%Uz{RRgfTqLZ9wEfrN6gxw8!fC)vW_ey}ge1Gv3&G{_0tS08Mf${rSiXE9WCGfQj0i^OF})LMwT}AA-E#4?$k=he>&1A(9s) zF$8&`!B0(mAaKQ$2Jz*Rp#n%EZ3Y;UZM4cJ(I-YHIsgWOb0yJ-_sKXZsRTE=gJ4x9 z2MiiXsZ`R4W-SK{YGKHUC`7ZG0|xkIlDyu^Mj)|5enORyW@05ae#sOckxWs@2%X_) z=f~;reO)80H3XQT7b2EHZW1Yp>4jeT#3ty4UIh_JU&Zu7uPV?UadjyLXX5@{tAV}C z2sWC;eV8cpzc;GsdHiJN?dd*qJsSQIr*nl7bjZ3u+>`qvQr5xB7njKRiL_YO8Lx^= zcCyvsySo01*oK}xs45QwdjRhAFti7GkSD`GwtH9+l|;S@LY-9Ns30ejG^dKAw%Jjo zu)qy*v{@^xbyFN|R`Yc)#8HDBhGc@JPRI?2K9}5v_Y6=}Xj*`gbZXv0<8L1)t~wVq z{*F40=K!-t<4bq2<5K0){F5#A(NIo4T;P>76!sJ}6N}&k({)34+mf>*ilYgs)bO*g zh-7;k@bK1{O%2*MgDrSC+P3vVjf5Hn4>xT)s)n{*R7`22BB8#A`E2=wsBAka&jEY6P$!(YJ` z7sM7jXJ?DebGL#T7TnlY+|}wADVzKOy85re!idr49%KT|#8oy_Xs1!>#in}6u7RKp%=5TiEJn zN|cL?I*o}_m{k&4pcYS|%0!i-QAZZ2X02${u?4DGtv+hKl@BH6q7qXqHhmF-44m&1 zreM$J;BoOhBua&KA*9N#fTolL`p%q63shzO(*n>_HtM;?NjVSu4lqkywAxilmL@6IiMCr<^h#ep|?=&d#@(5d$8B4=1zeJckjwBs1l{908 zv8-towIO7?DouLqmoa4c5>~sA2_u^3*z~J2Ni$`Q*u2&hLEyDTLp1|ivmU&*s8=_! zH7mkvy<*_CCe96aps_j1&?2$k-uY42Pt7vKF5);$y}_X(%7kQKRWA^uXE#!P=f<^cI1&f!y zpz)1ag2w6Oxk(zQu?y#KlNCc0^c-#YZ#^GT<827w=Pzq8q)00dPeIxUPokm#NO&sA zXwS$f%&%0;C*+MUn7r}l&qLn$g}GPcjZ#W-(fk#8gVRP%yk3zvnmqGj8x>xWH=M$r zo4k>@RPjTxh;f1jdJ-qxX}}~iv2tTVNrQSthu%*D|&%#Vg zfyv+0d&FyOI@hg#&cXub71MY06GCRNY~z3$2#ML%U83sL=~OY zrmCH*P1O%HE11!AC&2}~zjxOAmdtF;J97-Y*fTrgojK~Ej66SdKg*sSm8n-skmy%! zt0r6l{ggYHISSpRfJ$^JS4)znE8sCxO5R#3CCId|XeHGt;X_j5r9VhOkIkQNe~wzo z+ohFkoTpau5T2d_yK{3b+IUWC31f=XlJFGNlJFGNlJImsYRP9zE%}L5{y5Lg4EnDx zm>IO>A3E)L5uZeYvs28VhRH456^5U9#YFmwiS)&H4*D`xSyoCDY4Fsjt1N-f2k(dE zJ{@avEQy?qU9^3l91!(@27{w$*BlWGlVnZ2b$NG+5FZqqHh#B~h><;uE+u;+qczMV#9i;TMFel86LsFZpT)RbLm|AmKa0w=ISCk4Y8d6kg& z=qw@cUC&X-dzXZ~$Ies8d-S}7yvLrCkjI!JAul`yAul`yAul{l2zh?M?f=RS?O_i} zo)MhM-A(GT=OOC7qjRAw&=U2^xQ{L7{azrL%8$ZGj0Ws?;g78-wh)-aTt;Lzkjn)|fqXsqbaAlp)o< za>^-6RV?eBY3OFyu#-ZWHL9WOoKSJq8~}^lWY9MbMvV>1RoM2zJkQJqQ=Jqtk16&! zH%>*2&iPt&$R~%l>X6SGC4oRj614l--zwNGGtDV?yGJtBKBvxVMizBev(Krs*gj_# zt0|rB^UmDvkrqalQst15#b*{7=6q(+RDEWZk;QCsQ#xDm&dy|cyl^u+;GLbxz~4IS1-zkKd=qj`=?5?f2`^&Mxfj59o1NzQxJ0aFkHxH}Uv1K<7Rah{7uTL4h-_ zTfQ@C?z_)0$ogjEa@m&xkHSsE?o-eY^K&tmg2CkMs(rab6#r3NR)fbS(upT$Gv5Ze zXc9e#Z-cymTEsUaA93XdMvOloN)^G~f=rJo1*BrS?eO~u+3t{{Qh*h+eou0Dw_;=I zn+My~i8xr>;sJ4qQE)GtK2Xphi9T=+c7OmflrE555;nZsly_0>8XyU5l(0(Jsw;q$ z{u3Ig6dw4bWMJ&U)+)|VNBG$rp2kg2ukcxUlEtUwn|Q}lf&o}PaxEPnQNZtgTf2ft zDKDPPks8pW;d|Qr#RqM0254(Dy!0&4*8bK9@ye^cG`Gi5yth|AK<5+1i{hJq<~+TP zkDrgN{SF5nSE>Y5Iw0Hm4 zdHrk8L+5%-837w!#_1byB8_rlFs$GjFORAT*Z4r%jM$rcut^4XS6q64Td8S)vw_`H zBUW5`r%?Q&YK7uLwVLA6tXC*5)T=8l&5Gz;KC+;==)KrzOYHK#llu2Zepvb!am8$+ z5;MU0h?lkkNf}n4BVg4K`L%)+W~l;ET7|suk)#YeW9~(&2t-QB6NoVYd&fNw@`D~g zAr7`y`0HWjy(vL{DM5Z|k(B`opeVh4{DEkhf>SkoXxtO)q>I&24>l%36uMYD?=B8` z7m|xY*p1Q%KVTJ@|4VQ7u@uFjS z1euOYHMPt)cOVf#?~RG`6Y@#!bcrT|xwD2jHr*_n&p^S9+%AyhcOTTItdIi6Bm~0L z8(G_m^(_y2g+T6t_M(&yHs^l=Z51;jZ4bdk5}xtF*K(hz=(R<!Opy$SeWL^fnGuf#WXM^|?db0}_>&D{zj@h7BR;FmeP1Gubr2Wm;>yLrv#JH1xA zAdOrw04BM3TBco4MT+%Ns2@ED%gZ-H$MONLD@zKnTX<_CfRnr^jKQpA$`^!qPI{y$ z5@b#Y28MeGrR7K3Dl9*QvF!nBuC9-+p%KL9(Utt~YX0{sPl?tiQ5xyD75d&+%BX!j z`R$5QWJiY`Dmz44NmdYvQih?CWPmOp=3)R&F(qB5Gz5I8v>?Njrd8d7=yuVXSan{u zQ8adI^p?PJUB?*ghhTW#V#-GJ$93|GDN_xYKv5&1MiEmsIyD-_)#$ybmQt;>UN!46 zo}ylxdR1I_vm#8uD+VT@_W)4wADQPQ?g1{O*aWo8Rm1ciE}YWpSlolM?%l zqWPM&f=y0ijbr(m)hgv$`i0&qW&GvYWsUW&aTly!O;8yaFfA}0a(frRRD+U12}~9W z9#yLW$)EzJX1x+d4z$Q|9|2Rd;#>txT}{iQ%NO$GlSm(3~FAz3CqMyF&O zeD_>2US`2}%VU$L`&Gh!8VvHZJ63z{82ebs+83Z4(Cc{R$zl^m-@&0`wWtmP0RvR3bcL2gwBKdtI3z!(O|AnWbM0%it&N z6l@;(GK3sKGBEox_@O#AhG7{z9S{XuN0->T_@O!l+eSOBAfy8#s~>kLXy~5#hZ;+x zORc~&|4^`FM0#>+c;+7pE+MP53PR=|^8SqWSb-<`5p`GiS*w-ZnBByQ{p4n3OWF2p zn*elJ0jOOLu~UVYM1}OXobAbWseE@-ejO(ne* zZ1@&Lu;E(}!G>=^1RK5u5p4JtIBc*5P*dB5)30L}bTRAm-GwdFcj48q>_UEqT}XWw zT1VLhT{wA>cHxFscHvCB(Dq$8s$F=^#oLAJ<6T&g7D_TEID{mfZYGNL>gdYEW- z-RQ<_b#znq>d~R>hS6Gf{pdBwV0N|70K2|4)0dDq^waY$)Jq)tn-@wPItUid!bER^i5@B$C|vg?#z3En80a_V z(c-7+GcOSExsDle11HOoKI3HB^cnc21fCfth}Alq8o#E_rp7nd+0^*8b)9^Cq^^^X zzazV(#<9OsOnjkM^t$0UOOr)!1`~e~m@J+HZJnk}OjtQ47=L|5L7=*o=A_ z_$ng2bysB8#Q1uUJK}n8j8Rwm^b}b^)u%YIgI*(*$pLWfx}Y?80j=-Y#7K$}XH~7qE(G7qE(~W=AgGF5LLaE}Ur>xN6HNl6K)cF5WKO^vW)r zX%}$w&@Q}7yYQVCZx_%}UOBTU4n!xp^PKO()7pjCUA$dbi+5pxum{;`b#kf`Y3#IS zrN!EF6I$*X`U8q4rduquH;it^Qv2HM#?g`NrqOp~heqF-t&LuXjn^%=_*=fj6wm)h zisz_{tJRRW0$i=cp6Br#`27y92YVH|o#v1Jt|k5KWqaR0KKc*1JBt5H-gZ;Fhbb~V zXFSS34X^Owza=p&P69Nh>_IOPP4>)+D+g$?+B05jD6X$*D6Tix)hra*nwo_oi-J&Z z@;inf?=T2ETc3L=E2`(Dm!9|OdqXe1v7wjVROzAePYS2=bv-mXUv)h+QcPVBjTBSY zLnFo1_0UK$bv-mvOkEF+6jRqjBgNG9&`2?LJv35GT@Q^EQ`bWy#nkoCNHKMTcBGiP zK|4}RT?ulZj^w2}ESOZ=VPZi-prH3AR#TxK}?Lwu89(u(Z@Ph3^rH3B+mRSQ9@U(1b zK*3W*IuK$h`p+Q_+SaD(K!xtZwbL&#-RIF><+bv67sqP_f&L60xv!QM(5WdFHw-^3 zEnq006Gin*lbkN}IpDN|+)0m;O2Ec7sSvR1?yr%5u8%P|$IFqx#l7eh(IxKa6wxK_ z$Scw%?nr8P0XverT)>W`b{DWCj_(3?B(=MM9ZBsjU`JBB3)qp=?$TW(wYz{FN$oCI zxYRzM4GWJE*%78KE*>Mn{qp;pI`41D8gdqi{s zZChO0&=c!e^9QowdNz>b|D3KuPP2J#7GtpXHD73i1Y2n>Xaaa-2#PSOHG!OGO@xoA zZ*kbzIn*h~5o2p-Q2S_rF-rZi6dpXMBnm7SOY}ViRQ9vIii=yhjR?GEsADUC_8Prh z&Gv?94eqffG;*+cA}q4`ZFv4>EC1+V*dh^wmKakEe^wOv+RtlABd)7%*}g8mWjng; zdBxTWI#dLKutMb>+a3pEcWe_oM~I#GXD*9d6oktPX$rO!#E|+HuaE7WmeU#wue%p+ zwDZMi*`u?L)(m%Hw4VA+F>nJ7hp#c}HAic&!G#O8wijZw8qOI;3+!L0(Ow8h&~T=Y zRyZ?&B)phLtKpnsv}8lMz@v3KRAQM^>T|%dp%zcWnLb**?q`<^qzNr_s&u8EuFOVy zvLFaT%b;0?!Ju?4plUl*8E+VmE1VhFx&0JAuTix)L^ckpYSx<>*x9Vu4D8hVezrXi znMk%(a?jLR49{s6!&696=P-+Ay_vIUR&35f@3r!xI9hiL4)*X=-79dm@Kn3uIjS^0 zJhfSCMtEwoS`|^I@I$>-NT%+WtcL@aV^{Knnc=Bhm`)TZIU_uE%PEAusM@UX)MmYz z;i=7v&G1ycw^(PkeF0u6;X6N|pwo|=q`xH_4!@-Ii-9ZY2670Vj{=q?>JR_3?v({!yV(|td<4}SN|OfwEAp{ix?1F8 z6|bsr#JExv`548kHfu$Zk8!+ev)Yu%M^^xv{}Sc9KqQ=^eCK0;9hlii(4jK*pVN~VQszNIyp^97iY*gjng({rK z#Z~?!s`7vP4Qc9YzFzB3qgtN}wdfAnCvNM{qgtP@YC(JBT7MPQ`j24&=n-BY*ZN9S z>pxY?1dokt{Y_Ns&#GE!2=8|mHfIPe8P%oxE!kWo-79cW(mmP!&s(~0J5!pJ?zdFZ zJ-wY#x>wGq@wS?jy)B65y%$=#H-%^mCznCGM|@w-hTprG&XCaGo#cOal_c~DiM^Ho z`~8ysGok`KRy#=l5}z-uG=J`LMl8!K7g!}_=ncavBze6gm7Ay({J~|6ZF<_4ZLeeu zBr4~0WnPLR5r$GRlx!E-y~rV;Y)Dli49lMoRjcukC=o`pUX6*w$s?K-OD+Q0J#$Ki zhK%6^n7ij<+A57v41tL8BuW`De+niU(dn9`6cOQOy_$>>li_B?ri`KYQ&xV#vPO`T z0c(1hHKMli9O~bnpC%PTHaG=Gi>lRDexXWq(5zQm`GqKJM6+UZ<@J7o&H0GM=E|Ye z*jzPU<4jSdh|NW#ZPtp|Ts+ohwJB`QIoD5Yl5LP=cz81Z_&lfb(+qJkSO~&PQNaa) zNK|mES0pO9)r%!E(?W>kDiivWX-i_lXp1=tkFHOD)P6{2xR2~syLiHLm4&h=>pcpR z_qHP=oLkf)Bb-~*Hih2ls;2{BNh(!NsgL!Es94Mprlk5?!p=4b?K17WSG(D>-!)N$wWveM0Q%4J^3Gb1q2nW{VL|? z>+K5FE}24iGn(OjT)WEO?7qDFBg6k$se}gzdg%i%3c5Orr1momVy#kbdn322w*@+r z5$hKlpsstK0Ojx#0hC*0YXG$krJ@N?uXcc1WMc(V%6c+Cvb*FOpe1~%ftFyp23i_| zK+EZI04_|7>eEt{c)Ev;(REzO{4oVO(xqQA1x$sggznQ7nGDKWtnfSsd=8&i3Ph)*(7M8dWUP!dy1 z*{C6GS0a>2l~J`>B44xKOp&iyu_^KuVyf0zn5-D{(SA?u^kSC$hW})qBP6UU!(Z>r za9wq4P$cuYH7Jt#TnLP0J{JNj6I@996iIF_s6{+tg3-FOVZ7$EVI#qT^F%E79?(vz6%h)Xzer<5NEijgC(*hhwLCbbNZ56-39Ud#xaH zdc4vKBB#fZ6+}*tV=IW99#^a&a(cYN3ZiJd16E+sc!-&3&Us604*Y@94Ju3B_z=u+ zQY^;j_Y%=w)!r7>eoeMp#8<^TqvD&h%d*R}Ju2Q66~8tcXQS*&74MCT%^!Gob|AY# zZ&so=!7X@@?e83&VX<@wj6m|-)sRwbaR`h+(jhPcNr%8lY$;^F&_<6#18sB!k`93p zNIC>YAn6bofuuuV1dxY z0nhfR_|@4iL8pp$M8!97bPaT>cu!P(eYPU#RPmKj@r~KF*}m+6im!-@BaiDnkoTz` z*L!Uu%+SaL?I(170CI_bMDbn0oJ+5EAbV7MOtH@t@Tu(!;^V@|j z(|6&l@z*c!U8s9pU$k8~Yy9=gdl%XsXLs}{6zR1W4;RiFfBo{_g}TS}MZ<-&#$Ug@ zccJcaebIKI7JogE$2Er{QOxOid0g+eW4Q}x_C9Y1Ha|`@XS>;EZ@JlJSIcg3b(WpW z+2J@g!8FVn)!E_r)M#8;YLpMWw2Rb|J~!*t%o*|7VY6b>oT2yqY@7%GBvSoXn%GoR z(u+EQzPYVFl;}!l4ym~>4S+y^G`L-|nJcVsWnA z$~XwU|CFC|jmc}O7z1hN(eW3_-pk{fD8;t2oMt<)Q&BrgvQ4Jb4LZQ$d8r(P_Pk-H zb6kN`VQrG2)<;|Nvaxy~3hWZm*TiL6_W6_Itzu_Cf=xjitlZn-@$vTiw6MAj|GipaXN}h^$186_J(5?SXD3n#a5qC1;(sBUATd>Tbxgl1;JXnq?&lwV8Hq|MEo( zwm_B@cYw^4ob~zd!j|c~aMn!oFYjHzvSPS!lwCM<@phq>oOKtn_h?r=?2I%18(=4y z60#~Ws}i*8IJukckqRJfq3~+0WPtb0xs-4?Lrz#VAwf|P7uH!)5oRbA_v@}TuF5?_ z=u_-0Y4I!?4BtvLt~pEUWiudSM78lK8^3W;9xjD@Xz4C`wuAJ`V;yMbLHgyVMweGQ z(Co{%n)PNLLpLinkD>KmF#}7S8%Pg2gAVkP@t`y*rqXj1R}uwagab8se0EFkNecpr zDh0`>afw*7R*+B+G%gWqR;%Pzd93QKR$Rd&IL0Yx)6UVO@R*vyQ@GAV3Xku^i#uF{ zN$E<@+yXWJmj$_9;)*@|H{2zhZ9ANra`gHH6_7JnBZj+)a`KE~I z(E4z7>#|OX8D%6pPlD|(T(3S;BlUlrN(EZgmNjJDWOIE(}~xAW=8#PvwrIJzc!m%?1n3j9axuHrQo? zGUbuhP@z5i5+C!(6TGfO%O-4ka@UL4*i>F;zI9Qh>AbF4YX+}tR;%+mbJK%hV<&Fx z#8msLvI~@8GE+v{cWSgRu2$>>mbIFlxLL0x{Mv~anwk}hohU8{)cYbjqaj;daSrQ! z#i`L1@uo~)?`EwT>)otYUvIr7U;F4<)?5KQS12N~Rl$GZxMxO4caM}2vbN^N@9I%K zse%TgNSoRTc+=QD zm=AZ6G{Uu?EH0JK`x?zfyFgTGQjicW5y&mum_B-fm@EDDU1BeL5_>#>bkKRkuG(V1%WRtx+C z3PMhf1#_s}1UVXSuLb^XM~)H*ZDJp3Vem$SKaGhTtZ)btkF1ZSqhVvT#2ymJy0s=a zy0a$2MB-T}Ce z@TTL0b^C{r7tV}CikfV3&?(r@_jq3)mBDQ1QV8QM5qwB!QZPJ~;Yji0;cY~NH zcZX9h{x#ad(^sxPoXVoiat0rt^?ytrDk9mk?Ua1O)#;Xm!| zQtn{O32~eVT(mjW+B2GG*`POXTr{%6im&@+_aeU}$*}-cOFp9FC5LiuCQcZS5o1e% z!}3@+8qR+}XDf%J!5CtYd@J#>Gqh1krxcUBTOE$H4Gad#?xAOC0U@hZE}qpW7mrxt ze#p`)Tig?!HE{9a*qqLm>c$tzmq~tX&Uh4fDrIza4I-*hj|SCAyp&mEI{>8B(g;+M zxNoE8(2{KM-N7E`8;3ZsBYl9iVFO#c!Vdb_X6zp1Xb<&$|MU@SwnHEq?PA~DI1QwW zv7n zjf(@$EZoj;c*4@K#i_}Lw$dbHhErHoZDbT*ypbtN%tzL=fcUsXT;oyoIcvQ16taSY zXNAVPO_3;zH!czyX|N(*Pl_-@vUNb!Fy>*+GGKPkwa}f29oKN3<#*}8CxYWMBa4pb zq623iK;%g81Be{yeE?BxhaccY2hI*9(Sfs{*F^`;eqI+HIQw~Bbl~jgb!R$ob|?7A zk>345qN7H4f{%_G-3dNAYIG-fKWf~`@#Z$TXRDQ6=YOWH=G61+>`GkJEv6zmy%uj> zl8?IfV^p1iXREYM%-l{R}Ri1Z zs^may7KgMF3!1eei$fX-1Z@N*jZ9w#lT{{PDvmLX|Bi+k|Y%+sj>}2)?RpI)FE!QAj2Y5~-v$DoFqi8U?vi z$asdO%VjpRUO*)0W#&L0v8wC&1GesY>w6F$*oKp`Z~&}foH};W05u|9udpQ@PCKkB z76eQfO;kM_6!0+(8b1m{4O6PL5_K@pfZ0PWgeER2Omo6|f%avL03Atrr9|#WSQiMV zGP!iSEe7mM4OoH=z7GduCXg>`Dv>~53n?~%yr>Zint+HR2VhYY>aF^A`=(R-jpr6)5V}SD;yu74V8Rm1G-i5Zl^?|ta6sSO# zY3m!(MtOEYLEgZ@u_J@0blwGrN+DpE7JJ#?Hf)m%2G?#l%pcG;lMe?39H+N(0L!_s zBPbBgOr^$xqKe}MMOhR>(LMNfRk65eAL9JGPkju$M524=9Dn(kOvMEbGqy8Jgng3( zOF`0TlTG3*pA{11CEAWlvR#}Z1F`45Arl+c8nxlBup1V#5JjiR2i$ncjxu5N^Eoy3Hl`-qZ=xhP-V@5v?+-Ys0r<|D@tN*aE`r+{J+auZ57iThR zm!u;`?UHoFs9kf57`1C|5u^6w7THD0la!Qr5u;*a)KwsaQH-ck#Hgdg(q^rQQOAc{ z&1!W|fSJ*;AD*rNmy zTTI*&Z{PnTCi7T80t|s6bn91=6Zipslxp6cVTcZ9Q2)-B29VnJQ1H z2|n5K@YCI~onI+(wYN^nC=q7UUL^u>2$u0zVuKDkp4pxMEyIh{Sk6uM$t>HIZFyN1 zQ8kpYq((d$hqeurR}4#cV^Z)~)S8*Vwi9wD#Cy}0tNzOMWspfo=KD?!^($#5XIhrJj2o1@W z%s7_MX=-XA9t&;y#2AR)jcp)(T$RIWhk<-4DRbx8Kmx5V_CpzGaf+<($12;=B!><+ zG8;xD!`1VMWH?a?I*Y>%h7@603^$%jAX3p?-;PvtZ#c3+ec1+{zS>@+hasl{!Vv%9j3>_Z`w_LYn5#?F)}|SZSeO+`?%tuz=#r#u31TYf>J-`afV45*DIFT zVrqsV;4{S}(eY~^qb+e@}OSFm&MSatF^f?^QAGcZD&B4IE6l;b}vI|9X{3>@uzGX2GkoTT57l_ z=WVvqd>K|+YAmGO=zOXTm3hwY6m9jt(-xv^iF%=>R@IW$#rMol8@;6#ExnLy@SY2{ z1~1@7{`|MYB;Nb&Fp0;%9VYQFza1v=uf827@xE_|Nxc7pO=5e@k%#{Rj@0Yd%l=Q8 zUS~?#pi%YwS1iJ(UgmOTITIze`}+pFW=Sx0GwLrpGCj-e0f8 z0x?VzEId$I_0Z~=W(LLPsYFeXdH)9=Ch*whq$;|cVH ziI%@&pQV|ZP1F3rS07H_;zHs5S*phF<>~7;98T}?(!0I%E}p(f>78DBhnF7b>9dsH z;-$yDl(nDT)fTt%ZUGY+E5b8}1O)ABNp;0e+sifA&DaF4ke+M+TcJeX_;I2{UU!o!=kKI2sTWE+JpH=iySna%vZ2qiHqI%b zD9MuQACQY? zge4lgBHVCUTT=W2bwfKy(q^6P6lG)N{|+WQYVm8}Di$!Ja+y!^ueb95vMvA3mQFJn zMBW;Hp^c3hfnPQFm}%2K7JBxTEP3jzx_ngE<@=>|NS@umwa{YEgB-$gMx!TjBOK-6Xg!^}}=< zG?MU!YB&g&FJ(#B?85qMq^XTGIon9-(X1BLW}#$jq>QuNEUXrDhLGm&NL2vV`}6T= z;5Hbox0DtQAMj!Ct&Me*eSvdOWvhMuZVuVoXFpC*OP!%HAoN%sGKa8^w0s`-jo5Mx zT1uO=Z!Iqn26cyuXwaAi7+Is0)v}dUy*qRctsE-h)J6lGVu9h{6st>s)n7oXr5~A> zZIjFxAV_5}28V_sz@e>RSRcV*l7H4<_zwk#0y)7Bepdzv`PY8Ks2ff8>|A@#1g3XI z1m|N6#SCKv1An&+YlJ6oEQvukU)JR)a~1jn3)MqchSrJ{bn_KziyRfL?qjVD{c+#X zVC6$GIVy8z2ur9)Rb>^1x@r}wcFd+59*wqS^K$fn&WZ_G z_A=;47|t9(MqP0N{tN|Vn58K^KTg26OPs0NNH^6vfg36-PGH9Yg8*bTPQa`KCs1<* zCy-s#&T3$Wl!wKV7dKo22GTS>j@phlN1VAGt?=f2rW8Oh!kc38Cz#tY$D1QzN=Kk` z5pw&K5cXEmW5tvvn43Yb@CFaE=6v*JXJ}f6*4X?S7~7vMhN%l;J4eZ!ai>7f!!z!x23fH~lcoN4)WbPWo`-($#? zhA~hb@sHIA2wuUM3yLwv9b;~PZWt4Q@mw(G4#$||0b`C&!zp&jDlZE-}X1nZTG2&BPe^N;ls~gfL&5i7;Qd@yrPGOOOa-Fop;LVUCpu zb4!UZ$AvJU$?b+Fl6+1ZhdG?SH8X~FKiH$OCIGYjOi^JLAJmSHdIL0rA3LBWg+2#WiOPtqA$2kLMldy&KUai(Fpr*##56`U(8k<@Gg-kucRtSkKB8B2jJVvdC^ z>z+i~Fn3Gmr*}DZIPu)5LqNQ9p$>ODb+{`~hr6axhr0}qXHo~l*;xx|{M4*$P95G{ zQinII)%(wZI^17U2W!WiQ9Hn9XxgPN4tN7(7CId|+t*BI`({BHSP$8dOncKUxu5;G zsck9JnG`^danVxvJDy{YCnN&{n*j&4Zklif(7C9>ft`y=n-d>hL!`1_5Dy$hR0i?b zhZ2 z_5A5%9WBfd)#%HwksjU2KgnNQ6SB@&`Ye5uQE+qgeCO zLtc7-r>{Ljtraic=f!)9;$?np{3h?0`0*K4WIXvZ`q9ew3{C!kL-Q0u6w-x2}*ty0KW@g zS9;+e!PLF^((sRZ^#3&MLtVU|zpcgyI6k*k(Vw!J{E1XH-QNf+{wKe~OUADl`6NG` zskKD&knVt0*Cqog%fF$D7}oMH+ZSf}p??1EUHKPVB79hVdRyE0#z5-$-5T>%(1zTC z*E*YBOygHTG#w4~EdjJ{!2@J@HMn=uo5u%gTG==aJfnpjZgB6qct*l!ZWmK?*2a3D zfw8*9xQWmSIDlgFss-;`zor6%?uyfj%XEK8sTQ1efjkV9YQtfxAsv{AH(Jp6yDTM@vZe3YJzfgD#LaTXOS&#L5AZZ*0A^WBb6M6F z3SM$ebsBU{d>XVs&*CM>_(L`kGrfX*M@hC*-7->}OkgOCng2H;N`0VBy$!}YZSPrt zY-hnxQkzhD&|(YHXLNSxWT&ADMp>c}KHhY>s9HIy7fKlSMKK!UeRP9U;%RLL$ z%lE90b|ME4dHE~&5c1j%;i%1TV*G=oIwt7-$XK89W|4EV{prw70+eikcfGNBx!S~% zmZB|CC<$MWSWNtF2+kB-9!*!*= z*XB!+#%GoCR*qB=fD{J~y&#x?3=*B;ueF&=XNZ+v_HQi>zNiUqxN>LNGW>PGg4Hwd z=xk){V`l>>dEoUM!w=0V6Mw5u z1g-bb8(nLCjEIlg4_QED(w|p_*8^hVH3WY>7_I8{U~~;D?cWaz0JaehXN{0GV}Rfl zUGL@NYqM8vWCzZr_Eu_NmtC`wt)5Hm1A8_~00LU3 z+oj=31JVpZZoZI=x2cS)1w@aYk+%sj_sCz>vP#J$`4LbjQ3~PKQg+8WxcFT&JY$YyG$SFvjK%P;D9N(?$H+W@#$~Hcnqa+qJTViJ5uoyzWu2W0p=niAh*!@f=wMjh3`*?d zPdvv_e!{-~WCFD^v)X1>I~t`s_q*G`C#@=7L)DWkwN+V3DJ@3HuVR!Mzt_w}5l4Ea zld;chbcO!1RV0X5Ngqvg-=el-w3#hU*;0~T-nKZ;f~9$KYD^Z)9uTqpw#7|kk~cG+ zfc5I^3Nu5F_pMWGgAk0Z$PZ^bZ)AMDmBdn4*e7Fd=ek<2uwC9to|( zRx)631xl1%4VaB@*m!tjeDx#Qf$W-$((5uSSkVg-qF=qirRpmi4_ihX7VK7%{B*MM zI_dIxe^~F=%J<4F3Q#gYbiXW<@rAu(!cUMYmAohId)M z)7u;})k6*(*iNyU0JeXZElUjNQ!W1HTNk(RVzU}#)p4=dT)br^w%@ua^WAoPOPzJS zQ+8FB3PE4)5SO}ix}1&HN6Tea3QIJh9PLC3UQTE;M~fteVby>q=1m*q%VRO1n<-Fj z3mW6_Sr;^+f61s|*EAe1tmKFhQ*qd^qcA&z+0)F<8ZPLe;WAPvy^S));j@l1+V*KU zEOZEzW-1QbwilxWhl^1{ehM58iwYGqgki|Zo0O3#qM1y$YGoH>az9hHN`8q#}$H|B)dYdM(f$Z;uXQ1V*yT*jrEFz zk^A)uh`V)ht5)@s!YM}gYA*%`w}F}SgjIO~UFrpnzUE z#Z>_vUZRPD-6|+h*YZIUnF!L_>3xi}^M#-~3u(EQ++d9Fry;G7Fznt`q$TeKQ@(9+ zr=houL@Ox{syP@W8tiE6g=}B4?szF0B*eOP(TwDVdCQa-=J8JS>DEOkthLHVl<3{E zuyQ%VIJBrsC$y-hR`trW&)uGW@Ig@qpxRn z{oa9=1@!qFNw52O!=H>lm&iKHk&cdkt@;uYHpPqqXXnOBQabHP4 zkdA_`cS)q{ag=#UDQHQl#2(xWowfjdQ~T$ztRQDeTkUE5UTSTc(umKdCGJr2S~Eeg zEJVX8klGA9@P0iP;`!cuIouIX$RnCWwxIkwEbV9+P!CZhAT@uqdHnnV|V_4NxCHt(E5YA;^!t9;R$^pN>e&x zU2_R0XjK?ycm~Ca& z5oUY%OXM^v{tH`WmY5Ey9AuEuUXP{0kB3-?Ml_5&DTa^47Bpe$mfF@p*1`nT`Gx2AHi)_P62KQZDmr8LhxVH8VA+>n-(uj~;ZfP+ycyD2|P(YDnexii2RX(f!wHbxJ=f3+wp-==Mohyam>sGDuy!y$C*L?*841phZ1&TBLVEjt#x`& z)=_QQ3UM&jKTl7M7bS--Hp)SxspWI0Cff1vu$iRo_d!!uFUE?pbB}xbo)Y( zUd4zts3VvbB5jprm|?X>SCYt6Lp0R!G}>2^ zjq3UGC{rDq!B4|x!BVqexmiFq0T40@uin!v*w+Z5lKXBM?uFLZvbgO1x%{-qzA@v|kbOf4l@W*Ee>P3KL_K+!d%IdtjZ;F6hq<@Q0CEd+ zZ;SMGM02r|Xn7%yVR40#V@p7CV+iK3MPVDboing3JJXjMO-wH0Q`t6xHcbgA+SL+Z z-3?3Nd*w^ewk5DZ+Oe);@vDX`8%$e131N`7cWjJS{VXtml)~PHkbKo=kichskd|96 z8l-%1CbJ&+ARC}AKqiA`+XM7_AwVAz)6$}HL@#2MbdI*+3L?rn{PxYaoDk_aF~Vra z^}~MuZ`$l%=SQ;^He3GF=Xm0)x&63PBpYT(P@xh>q+WsJYO$8F7SvNkz-;!XIQW=P z^8WPBac?cXgN`XZG2XNx3kz;P;{`+RAEb2-g|hia#`A0G@oe5pF{P)P0tF9^=4GtK z3cEaRQ=2?aeE!H-=HXWBgskocLdSuhO;&anQ_%UurguE7x+gaLs!G-gA4M!dc!^5= zDjq~S0nOomu=}e>Q;U4Tf&q>C;2u68zz#mi2zbeY$;3~*+y3+}dN)CH4}az~-j>$v z7SQ`MW;eDG)0PziE!G2tw(2&)WdPr2CtS;D4J7!FmI*`ssav&+-Pu4{zq6`AdI8P} zA@K&ISs9a44vwz#9*to5?~h(DX7Ck);id_ zQ-C4hlEV#6-Y)21IEax;>?=l9BY_57!~<2pb-O+jG;Ou|`k4*oo5rt0)sfu1z2!?y zYM#&A>W`;v%q#tPOWr0Y6DJsAzxiqC0}FsHlI`N{aEuMb(jm3%D_G_H*xtO&EOlHM zfX-4X{o5%A;o?k;Mc|nVZ+1$;K*6-}#T1TgAH;Q+Yn)eS0$M7!*qA6*{E( z13xTjhF>R<>Bc?tE^PZwzq6c;;60V}A)2PG$U?SobSSK+RM)h91Bml<1hMT1PavKq z8=hFy=!s))NpBq783d<-guak~|Bd`8$Eg?uA%^)oKW=2eKh)~n+~NQ|yYwc$SF_0OEZSj+P)F_i?FdW~ znL^T_hNz_^1?L?$%+V&X##%cf__o^ER3+Df2`jipPAY)t7qPXpyCRNv|$PwrCGVaA4$G=4|eJ zxuc?yaH)dMVoA(N;A`dt0Ib$ZzdW_{K|696eCyzmTNZ~8&Z*-B>^gJD0#A`h7+0cS z;aju|c+|blP=zp|6)D*KgeU`O-LO za|N5v`Z|O4L%_QR<-sbk)u_QVJ_dY(JqNH8FxOVTMut{xi~eJUw%AK>#H(>puPCw+ z3DuWK;w#0&mX3vHz6IgF4-4Vl-J>PGV{MgB3P(t>X>^;<&29L_R8&E#C?tXM0#4{~u3>kRAN&ix;>w_oi60q9FKIU*aqmQW=!#Pmizy4vyvD6)ol z`gK2W-y3Ad_^$iV(6XM1Qp|4W3G85eDSEH3l$TBEtNA^I^n_)rIXO6>(}=i7BI`&t zH~dqxr05yjC9(-A3Ul5Y#Tabu1D}D88Q0L3wnhu|!#u7XZ`P))r0+`LhdtQ};QN%w z_4Hi`W_tIS@yIk6PcI!pmn)vWJcFm}z$t%RB$1(v78ogFyxf!`o-Q*H)3q?{Fc5e; z$f(qPNWWJ0I94Jp2eYEEI*wr_d9TC-mJqtOj@AjpSc_@khmL|UYLta_#>0uV;}P_n z)BD}J28Bh@deoNui|=(8onpn8-~-}f$^F^F@IQs6_r;EAQEiK~)l+tfy`Q;D;!#}p zGyJ@4v2Z$q3bXBN5_t`3*U~$&qm`ME6E6EaE4yi8e*W8+$wT}L?fl)nAz2=q?}f;B zoA+0Og;K;4UY^@Ew1TIRz(`B37Xn>O2l}nGDL{86wUA6(Pq_dY?*i%BPd?Ijz2Psn z2_NVWe-neKngwSg&Q@uh9BeH^Oi}dB}d-E^) zv6Fvkr*>6S=HvG8&*nyeTd5MW`dsiQ1nN|JyR;xzi6!kLfLVGvGhIm03F+xBWoOir zS&Y1O215t^zpmDz8_W{bT3Cq6qsOG4KmMG$@-?P237_o>*Kl{r9^D?cTZgn z>!N>c^=|k@Fd4vm{JlxuVyytbbS+iD6MqO?>EAk|E?dW70ajyM{|(@iSUivZxi?E6 zL2o{8{wKB89@S113MIHRhS)EgmMgRX5ZT=WV?<*RBNbvuQ{=ES)i1IG1QaF*qm3In zUW^+XntHN7_k!`-q@XifGjTJ>C<1BfUTCQF;SXF<9r zLO%=!{r+tV@5kDc9@V4-&#dn){Gl~cIcABDNLW4HX+;qy{9QzFO{sOwM6GM4)Y?B$YyXs5 z*G|;BwyYKH(ec_I9iLX^_F9$Or&YPDR^_f~RgToE9GO<-Xsyc8X;qH(ca+O04$Ep{ zRO|QePEt&C5V|lmJxRb!1ZXZ&@_aN)9vP=rMIt372&fV%Rrg_;u&gL~7=%}Ka0Qen z$u1m+oLXU5qt!c68}W&0Rqn1;xqDib1GOp#rd2sqt8!>smDO66)oE4MYE{;BUQlue z!Kv0m^VUB{9yxJx%8c)=HF0mhd35oX=>72j>-Nh$Xu^zlv50S-*eS>0vfE;Vgewea zlt|F`U&U6Y2)As^JH|;R*d~!+3z_@S2JXbRd+3W9`Xab5t6n)@HF+mndHUDy>R)Sg z#3>R~BwT!}3KHOsKVmz6!l7V56B-)vhyDJOb;>;ukrw5`ha5UB>wck6siADmM8ou& zbl*)ZGScBS>4BSEPP`^PbQ7!J7KKJ`4(1)T_0~G&e``tkF~b$4U$j$JPpS{Lc9BLS zLO(5Npx^&UJ8eJEFAsxExL}BPk60%RyrY4-9)#J50_$u@uTJQnJLQwEG79MCDpS?)QPeiCIYd?AiAFh~-JEUN7;oM{ZRur0TBL7= z^)6EOb4lTyRM|o$uJ+qtoK&)rtZra{f0*|K+cRjs<{}XP@UdjPz>B+ivA`?7!C}Pe z-qTzj*$Ra?+OMv0YKhx=baC4brr5CxA`}#3^rhUkQmA(O^fZ0GZ+@ea@V?dgl}V^0C@gX}qiQ_Y{K_xjB!20FP2vw~J7EL_6umh4twmYTGT?>M zl7=6#{lm7N_ms3Qu z-LR6>A;(atrk^ygD#lMhlWNQ~7to|#?S+Op>*&)z)k5-VU|W1z9Z?rbQGB{>^Dw=r zo$H7iz34Y9_?)q6vJ{lqEZCY@R;;GBta1QhS*LAUTH7>i|7;@xCqlETbz21EN6{jP z)lCAVo&Snz2KDa8yUBcTU0@o9W(F6W6u!hD4){vlWnfOaxi*+dTKc*IA(y=Cs?GgKo}G}cR-4O#IVVTVuVd;Nfe>4%rZDi zh$=+b)c>UUY3Kj^<+99oRm+SiECGvLoGz)(dAnot_-`f{eiV(&6+Qct^=!;cNW0WGr7n zbi;?02hLCMKIP^!GP8`}#_~8l0PlVMv(G;8!01x_d3Lnh|LpNX-Ah(4@baQ^TP&Ss z4rNOPl_0#jcd$joG(GT=M>1F16Wkb^H>BIntQ185GhHL`oYirVkk5ZFl$qFZ1Ta3N zkg>`mpI?I!p*n6tnNt)!J|R{Jr$qu*JX8@y?-HWrE5PSw0QdJQyZ}Y=fjAZhtk4W(+DaITLLx`2<89^dvfq$CbI7o zQAo26FQX`=FsruD3Q67Kyn-hZVhKyl@+%$J79wyV0FtTp zsA1K!WsCRY1eR5%u0*qKa)n~?=$U9;&ZLWIT~Lm|KbxEf{`o4N73KJ*2reb?k7kLb zWiMQrW-T~ppMrExSyiHSp$i~@P~1KR?>t(U!jt^;XkB7zPmYJ7$nbUF{go~_B$-*RFJgAY=^}J zP|dKIYem`xNZNAW3P>?DOtV@z04uvpkP;RSuMKnFuou{;{RL~r3*>p0M_*iCykH%8 zp*`>yi3Vg$n)@;HW`8rIjNt*x*gL1!yo=ynX~ctd4?X45D}^ zyt80lYgO+&3Ki#1`HohQgumC;3EilvE4|#FAteg`gdc`qB=c2Z8#GhrDcCkR%Ez14 za(RroIWgPA;oKeqjP!dKo?pAN-Bcon$0wJIZMr$3hm4AKPTlt3E2FA2{Ldu({mS(sJD=9i zPZNbhkNKyOQVogz1bFo>#MitFmx0`1VOCsk>lqr5{PnaNdYT6KYf(ZWOL*g|K0_zo=y%hJD@lSJBJX&@*zFZKqAmTg!oD*E9o8rzWU z)4kM0sc=snK5-|DB^Ew*ukhEH@(`_x@?T;n${UAkD|NAI1-1+tP7{k#T?i>hAYe;-BPNLNWdTUxH%y+uhNWVC& z>)C_e@-VOmeZj-f9tg?V8Cq5|64BI-uGp$v1BOo@Tx6knHDczXlp3s$Pv`+@C?HiDeh<;q7@R%%u1zEJ>` z$X#!O$h@yx5t;XOFEEj5QnWvsuR8l9vNT^%iWUJcB0PwAtl_;i{Nwp@*#d~`4#i&o zm#ULH&iF4f|Cek*KiDURk_50U3y6~?eL-=Q({#nsK2lUUX{yC(7)`ow91hA{9FKrd& z4o|1#6H_B>fSwC6NQWFWm@WfkO>kkgW+lqCfX|ANTZ0=iT}}q4m4Y zt@VgnA~yUbEV8L3sccZAhPV%h&tBi+|6FFdrB>yZX;tp1Rk>qYm6)$745$b|h&o~e zSUYWXa}dKXwfk2!p^D17@CCf**FE;@;h!p+E$Fq-p8r>b@5#O*KumEF=L~O_i~!b1 zDi^Fo^Eu2@|Gf!`$c2EdTv^;})w7b~KlTlKC<4KZvlQ!RY&R^cNn{U1lqC9ic zAmV<$T)aUAuJ`kd#ft{d>}6h-`e^umz~uXqh{_kuCcN9-eHgYDh>4)B>7PBK6gB!p z;6jaRs8&|tG!#R=WzY{X215dnN>~6^TLD;Y1p%u|7V&jFq_qvcLA3Gr6g2tjHzGNg zyxA94z6k2E3zg(sC)}df6foXez-ACVzlyHZ#4D9eTn)a~zoML+mS4%IQ#(y7AapZ~ zxLl2IqCqQ6qTDjstxFGbS*m!PSe_3@Vh4G-FYNNv35xD7>NST*X6(kGpQ;%cPP3&l zO)#qx?@0ree2AcZ?R*OCRetP{=f}zP=3ej0%zXMSdhAbYZ3pJf)+%`fy;R=4oDc`^-nLBnlis~h>cYF1fC9Nh z%=`I!zC`9bhAgKSHr?aTIy(A>+Lanv5P?>l@>$6${e-2soIZaIo&1u0h!?2y!KgW zN@Q-+!f*(qQ!NX)wM`ggXdx^h4RezcYfT-9T&6pu+e4EPdC{{4q#I7m)QH?Qv4n5p ze8i1}&$P5ibYMn8yjZxf!W>?#elQZcpM;&mQzspWa#q>aJoHlYXbHA-ITnAUE@c94rlZm75|EJj zhV*n{Cf|g9TEjLIYP2}GS8F!GFcWLWra*K$lg{WC8UUD3UrWg%_tqVFY+1Exp0z8Q ziim|z#a)BK(G2ZIBX36|r-Pw}tiQNESeh<()mA%<+}p8{%N-Y*MAap$AB~){J${jw zNY#Mxs+N-~v~BWG1`}{Wsx*3PXr(z~)5%c@gr2BHOVBdJX&F>;4xpr-sg^=8X#OzK z%yHTY1ccXR(|)Rzm_s{T6;4jS*~&jU7}B*IQyYH6&1X&x3+ikBuqO4+SA=Ui^(D|- z5ytc8eBA%)TslXxHw|4fvw5~c9MEG_N^Q^(rBw7X`}! zd@Vaj2g+Bi=aIBvP}D3Hbfy!lFVUSXw|R(B^$`20*?=+(4bcpn3Fskr0fCRug?Zbs z^-eS5QLi;R0a!~8At4QqmdDRq`E|q>is(&f>m2i^?ARF>>)3NyEY|gTEtc)(v2$9i zW4>5N%EdZzhQ&If#X5H8#X4e(1>mqW;nYAE5{*(;46GkPNc5kt-M+Emlz;}r*Nr+3 zPRyU1cdB<#4nC;fDN`!AXx{Zf^)Hn^4tKLnbT=XuW92izdxlqMX4p$_@E$JpD z$`x{oBEgf~Ra!~digNrK9=CemX=t2+9R6gsyJO2esA)

M;x6ufVq1$brrc!i?lGnM&eYf!el(_O@z(2>_E12M$i{qVL4P!f`wcf ztJgS1Av3Y(@_nT_j_w8H%#R^4X@qb7@`3g4px7ev%myW%2>5G7R`|lDI|DmWNYfxl z3*%nq(!k{IEx}vljOh0OfI?$kQs!cAloD&4x2p(Ur_n^sF#ji+LQGcM(2Fl#fikVse7D zk8sIGIV8cP)=fLYyI(G_$%fm1I!U@gqiCULUsdZwa)`=;#erTfB4^`u~ z(;#g@W1?|B7IdNb0DbsVfI{UK26gE-&#EUK9PVsZ`M$;&4z|9pS>^jDs(gR5$`4Fb z`GIDYH%(M|Q?tqsPE`59+5~&?d~xurKQ5JP{`waG=f`V}EctkzO@%R?U`1W6rEi|r z*qf^pgh%jxC_VL{N=Ezqxc{{vF1&?*b-tf))+vpZ2b5kOIPKR1N-7VB{DH#?9@hH( zA1hAr{S>ynG4AM?Sav)PeI%e+qX=fS0P!Qu5GQn$<2yiJ!&E2t9E+0AJMI=1vmx7) zj(#5*x5FSvN}^6_6B(Uf09WmV=&RuN|C*jH$$~Vn!kkehSqRzMYboUesh$?EFVQ7V zDX$oG#>J3_e+}nX%7J9~o*v{|oyn7bm_otD9kKWpSqQ|boOruB_03rQB>(FP%vR41k`{@F? z!&#xqIFxcGJCa^4Mo8jDOp6`G3hA3YswoSL!n)ds9`+>DEv1-Wf=(K8VNyo=A!^c? z0Y2tp2|#l}pEY?$0rg9qDM;gm~^0QFx1$@n|tN9woFD z?wcFx>m^}>B!K^)y|;m~>$>VZ@5lS7s#m3YlFCxqCCB$&%67$+CT3bVYDYo3w&EzU z5__hVS?-1Gs2lYfFG&oRA{eh;a$F4Vi~$AgQVAT|bR5TkyD=ma++c`<4LGz3?ga_Z zr0ERfhV;S{vSyNL1EJ%N=l9?H-23i(RV7tPCL}XNalL!bJslZ`0|1;>!YfQwz?XsSd0Smzb`&WMX-v{D1Uq`MaAcwp2ezpqK{&9tjHXhG$oIn z+-L0+!yhB8DyTJ5PD=A~Phs}#BdI#ovl^0Wr+Sdc&^en9h9pJO7yN;qSYz|mkVHpJ zUK^_zJ}@`B?ZT0ighW;6$U}mNQK3&C~;h8tr$VN zww_){5Q9GL0`v$hCA^JfATV_0Gv!`{x?(VCk-`FtQ!LtsqTwzJ6WFz2$aJkGR}cNr z2qtG1;v}g9^c4j*5bM-Nw$veUE$gx|Ki1YUUJ(6*g86(D#omu2PcS7fa8}cQCOy%1 zZiK6z?ug)XnLb!1*^`RTd{ktQmb{rF?u$pARW}-vMQ|Y8t;M1Q0*4*x7pFq4XQ0CR zhHFs1k+hAR&mo4FLVBpnO5VilCXy8qY@`0;IL}1J{YCnZX9bDWsjIBTz8MSFQBX_Y z6K$yBe>W^5hTpR&+n{SXqHJ;}y@|331!;@2E>p0M=SDYhso7Wm>eW}Dc@_F6!wu}n z-^YK?^14&}Gi0&sbl%MTVg?K;=qiE|kj3woY~c}X914$Eoyt_KRfn|FPCK8Dlg2%@ z3RGqL ztiH(^zQ_0&Ql4KNR2K8b?aFq$$}qpPrMf(wJv1wNmLm{(^LF0amS0*vi?{$%FzS}kSk?kkz9Ir4 zfF`Z!mc>@*eKFyhHB=fC4V}WwsBxx0-pt@ItNS59sO(rJ4y9!{8+zPkGv!c{J2cqX z)E1!7zf6@`ft^egt_}y=PbC~XE)&0rjHe~(siCL1`zaP!a-UtXsJ=dw zV7gIlxG4mR@#%QP?WDGi+?Lp2EH!hQqNp*`zNB5GM zq-vDuoUYkeoVRP>0^F-X@@v@41A(Qp=_mueGK34QZb!U;uAwej*EDe>ejHgO-lQi( zA}_r-<5>bQl@A{nCV{N z3zI1(Z*);yq$gwr){LVF4FM?uhx{P~4?aY;;cJ~ARTv=KM$#6T5P;`J-sUz6Di?)oX(*q#rTYBn#SaW#KOoJVsGwAbqqicIlTY zQ%7wnWq1Mdx|{@d1S$rb(+Y#bq@e8m`2hJ$BLKoOL)xUi>iTTS(a|t7kTh<48yZ6& zL59m`26RSsji{Dk6n$opj;${o)GtR7ozF*+vYHvn{S+TX`G&FDvY%}z>n zi6vLdQeHI)sovBTMf+)7UJd}d8oO}!~1`CL1o+FFR&QKhk zaRk|K?)H;%1`0Dl*%@^JHIRQM@>9WRIA_8`j@ZBOi57${i_>6JpHwAv(Jnns3@|!i zHL-VOEaJ#k=ZHTU`he-#i(5^q090^`p@s#OUI_EbG*N2w-I_;ZWCLDdmI`c&)o%{; z8m2Idhn|J0&PIsIQ-y>TUFu+C67b1V*cx<@$PuYIH2d{82Lv|q^l#Ns^N!nOEaU}B z8B!TyQ68hPn#vFctQso_+{Vhs$?U!ZSY=SGU0I>}Bj|)=2oz2Vqk*^1u=H`%s2hTj zZ)nsuK$_3RK?s`_2I}H5Maq!U>{{bOn^_dxV#7RAB+i zFtDzXh+1Gg*cb694Zi6UF>6DXr8avtZ1$4AE}3JB7ds20Fjnf&LGe3pV4ipg`?bkA zDuNg)8&YI@@2h-*9r&`%W)HOcJni2QIPU)5iOrHoeksI2Cq01Cv+6aY`W#{&7z&xj zu#yi+ra8o}sm2q`Ru{-Z%^}z;Ofvc$()2mReq;}InJB|Ed?wV$u?4i6jO1Mg0Y0Gu zR;vpaO}@IYZ&I_ZTbZUa(*!bR1*T=@CUksIEu)FLqe(xVAz6@0_SvKl611{lHq6?Z z^r@wq^nHR9F%$GzgC==ERS^8}V`EHSjIlYVU+1sg%Q8Y$V_Ws^qgHP;`TmLEvz;x$+`X@JV%m zCOc^qYnRb#+IwBHuTyxWmvWCyz*Ny2O1A|TJS%KomDT|F+|W*sHj$n+n>(9H{2C$J zCB-rqtCkgF#(+lKKZ`myS3zekt|Af8voV)z#P_)Uo*o%0jsA)OXX18$Kd8OReh?ct zrl4v}(2#A%K%z))Q0`F-Uw}6=;+uA0{YD+Okz%2UTFw1Gnx4UYNK^r<F&!(%Q#a zPY+sA@jPdwKP;;s2tYw$PtUfIg^z{*mf9pcOnyn4MYSE#5gR6~T8IxZyIR(7xyi-y zpAi&0Jjbxvz?-ucQW~|(sP~h3_|jw& zMsYY#l})nih+tIfnRXnl0;tvPqId#m9k4yxlaF2>-32cYI_^E!N5_r0;Wgi`DaEtj zDWEwh?*58z4d-LLvaV>+h;3_f!!P%qs5v`JVBKOZW)Nu0MIETxcL`rCByWoE60Tth zO<2JNzieD(juHHjpM&{?ez=!hKfChLBS(m)Sb2>S}$vr6jlJDlet<cAX+GZU=vM>qab0VXsVeIrVPd6lSgo13A*;76!3+DeE6$7%g+n1%?Rb=S`4HfqR zw8U(5!Fh^~rRr>5nw}CG?_*BW2YM==)m?erpVyo{yt5U$ z>eUpDqv~_2KEI|N3`&7*FtguT@1Q;{n=Ve}k}KD7&rS?`uf2nGgK@n}nrI-K<$HN0 zYj9HS_(XgeRG9?^goex$7kKuI)1_7Oe85pD%!mR9Nqo#nd@PW720fO1qhFEN^vc8z zIYI2~bl7@rmvn5?=&&Sd1+mx6L{8!9b3KBtpW-2?YNKT#; zL*TjG2HkWn(I8{xkqA^E;uKZnd-j)woU-$uSJo zd?8+e>&D?aH5<52GiZ?Qw!ou^xV_{$FxlriL1+TsxXxf7nyMUr8a}`CYyFNNB-A6g;DYchsl!U*G zAxss*g54p6MpV*kP@|;EHEzxuRFgH(=%B+;DNMj@O1cy()0l$xfD&KIbytrn*TdB) z3?qn97-|a?=IRkdgTO>#wso@u7ATC7Eh)?tok$I$mIY!$^D8L~O)n&p1NF#y2i&F} z5mZQGn>8xhgDcOSymj+LliQKbH@xTjUJn1Hoeg2wXrBYn#<#JPK)J5ar@m%ylcvUl zjSrI%=RZzzK3M)B=7LDpH<)4X(!>vDSyAzT%%M4%nuUQ<`Lm@)UAwKOIZPvBh z!D+ds-6EPad<>q+!7zM?NxED*{4sbwd}$ad={%M4CkB;(@Zk&7vUK83=g|hI%^;SC zw3y|W_3B9Xr&6A#xwFilc7jKLdOm{D{qeIrrvCU6j}3o3t<`E74Veau`~Ti`$=&>Z zCBmD~0m$2Kc;Mzq^@WJf+Sp?FHfkknS5#8~Gte=W1Fkz&?xf_kt0&D+OiD{x%rOe&<4n<{fJ;y)Bf+30vo=&S}ZPWxX7baf&@oqnL=mn;1#3!Xp7Qk`^UG zxuv`e;{0+FcPf9eMm}1YM`zmZ2>mLfHa6dW5xyxX#!wBVN830qq3M zk+>6(Nvg(-n8`v0nKg+!A$5bEqKE{+0chfc94TRDQZ8Jf5?NzOs#g(*Dy&Iz@Lf&X zUZtvlB~(v)piujWxoAu6Faabfe}pAHD0;gr*{ceqDn!Ge`AmFd7{f^6!=||Af z>=DaI7QlzqY1x(?`3MuCm*bGf-4jkDInx5LiAYHy+;sXHguGdSdIZ!80; z*}7NO2hVL>B-^#%HM14cz5f|i3PS?gfZP?Rj+)Suqy+&IjL0HM*0|8R*^aUiQ~BZ9 z9-_n8#ZSwQl*hR7eE>oxS$VpR%1mlCE8LEqmK7IkW|o(ohue`3!-OV*Z@XqNC)o$=T&Y=f`0ib{uv&B@AmTUx|$bMFv8LR$Z|mrCY-*AswqhW|r%p z1d7nBFS#Vi*tj!|J~o-_t8@`BlRREKM&4Ec@Non5;)}y)=%)S*Y|EaPvxW}@9=7@`Xs5tZD zif&U9Q+m}07!!=b;W)VNOfnG6(=Gyd>xokx+CAfGd$dD$`r6aCUmsoW$Yjyr^8jt_ zA8c#C+A?+jz)EdhOMGH)Ye&^8?OUtX{+xf^qXT>f(_Wq43yZRTs|N>LJ*ZYqBRjlO ztJD@+rMA%5eO0UbciKUA`hTlhUDnpI!M2X6Ei;Rp9B#{c00kLpuSsZ@-K_9J%c%6> zg~o+mjR05BJ9Pd62m;Vw4hY5pc-Bu+!z4ER{)dT$SV5UWtoZ3FMs=G-W=i%zKt^yw zZq(Xl7NK36naLZ5XW>W{1D5YK>>`F!K&VSDQ>3y~R)g9GB36TeQ$QY)NDDPM(oEZZ z%eRaYD5UcHH&)gZVJcKA^-OUk5c76|1ff2R4V5F_1tJF#FKME84Y*-JgAqi)b7e*B z@~^A{Dexr%n>p>twDUtce{Z8|?#I+x=ju?YNitb<5ZH3@g$SxETS>A6vB1h#wgx&; z)h2G~01LSkiuu#I;-Q)1(^2vAw^+C=0X7`~`@=>&ZccORsjLOef2Gg`LBN@Sjpk0mB$L(`NuC3JyD8$)~27%J|cY(ci;X0>wa zh}P~>`6QJ$=3Lb+(|4vVF~A)iiu=c=n`;h<#r>mS zWAeG6@RV>FWdN*@?q(UF|163P%{GlRm(k`ht)B1QX<5##U{|Xeqh(e!DLvqM76l|| za+(6WpRl`v&0Hj$3QzoyEj`f# zpU9g!?YHo3bl)3O1YG8?8E>d>VvX)^NkzAN#}gyI?q?bukutwwt@J0Yq-h}mOR?Dh z6;YDnem4sz+MYK#8aiNh z+Z`+`5D+@3ne^>^N!`xZ7LX{vl%J*=gbO#fYGH%rP1j!P8JohWE-KVBCJwH19J6O^ z6CGVdsC2?)j_dA0;UGsahIV1v(Fz0|X=Lsz-zSK^Z$=UUm`!ljaYDx&B~P+Wzx+s< zpA(FpflxnvfCHrCC8YGg+#&=;*_2gT*5kg%5{mRv2s+yR0~vHYMH`50v6GUPZVs&t zjVQ+6s^Madu+$&3Fifa1OE##y`>5JBD4wVc>7oxTz>_JdN{9yR)9~1qZK!C_b*)Y1 zr}`BH_4%fezwPg^_Ge*j%_qZ*{f9NieyU<@V{7rTe9+lNz{obh%I|`O2Y7P@&P4Np z(HLayfQq$j)cEcGQ3JHDfJVT45is9=9xy*U2xgEzuNj;yq?k+@Y=d*9;r?-G5rwaK z=`nIfd4zWGSa?KB({s__=wJ7bv87@|GT+VaAEvMauhQ|$BaZ0QSZ>{a)4WY%J=;8s zQMP#eF%YNb{}A9c8IPZ6ZO2oGo+zd2$OGwJ^Jh-!u=Mmh}&d7F>yFoT&U zk}oohro2BN(xiaM63Mrh`PQ+^XEKajQRkOpeR~n~m@OKQI!!dlF?Ud=8AsYnUKN73 zAa-sfFa}Go#%5im z60EVcY~qPEHa2|`$1ZEr!fBBJBj8a6UB6~^cdnsUi8J;Ru1WUj&tCo6r$77k=T`kW zpsRIW7)_dX96oFB#Jz^YR6F%GJlzW=~_W*(6u(yCMAxVrHxN$TzMMFC$2%U zW0f+&)qWg+*HJ0l(iZ&=2d+lR#|Y@7dvyHr6u#aVMNi(an6(!(zNY%x)YpTQ<&tLN z{&?=g_MYn9zB4w+g%QLx&0fR3gviuGq$SyCnf8RzjzMYwbr@jyxf9Tsp>&H1lfaUm z4&rsE&_FyM3UzQ?Y6-wY>M_-l(7)uKFeO`GPi|;3-=-c#$(7`o`(7$47c z^3iaYk7%YNjI!qN-X+@%~kz*AjM6;h2jh$CL!-D9R= zL#iRS>0j`-p%jHdsf-z&K)pcV1F4`>5Do2dArKc683kI8fo)+oUXkb^z`IpN?j#}J3Es*MYLrPC6aCn)LKtF7|2v< zAXC{6lO(xNOS+S!J3H5l2gq=UcC0%6#WLv^Sh2$3^_YJDt_6V*3X@AAeyOYi&d6grG;!aT&w%zcGVe|WeWhw z1t>Sw+ntg}{Hhv$4(20EXY!7?mkOzh-!avHNME^MjT_Xwb6nG=kEq8;GYAWDAyf>> zO*UhthbPj*1*OcDG^U=>n8YFg$(5ypR8eYRFZqZ8AYH^GWoZ$3vc~Ch?9Y}${}DA@ zc1HP|;S)3id#SM9_?9jqGQ@J6i-N~fwK`Y7YRJ1`OfEE*P!PwZtlc1?vuzPi1qet3 zx(D;*tmMGQ_kQ`#KfV87f93Pvad-yo!5UVIC(owtR-B%krbyWktwhl>PIqZ}`+H{C z=NMpcd2@)tZT7)lR|3fb2L81vra|q-fp*~?Eo&%s7+OC*cG`*p1kr$#(m|Gzh)eC= zDETn7VB^ER5=xe75Mp7H;Dy>X`63sV&U7TgNzF(i69aw^x@`d*GU*IUSJzrIl~3$Bx>UTTwo&9acWi2|0i#thnj03!o9}WEc830 za7@N--|^aco+;{)ZK=y|&<|z)i_f_uuGMAb%ka+XNXtdn6^tkgKNWj4lE;6IE*j9T zz~2Aut{;Ccjz_{eES-&#J;@%kpXMV)wBMpS+s16c7Hi5R0)oJ&;t7KC?k^A+z-_qZ zR-xrJ1C50cbA%oE*JEa`2bx*6|40kkjv5JuNSzw>J1Ces!f}r=mNAsuD1RFZ9hh;c z1g&ai&(`ZcZM2p)OGWEquen*=`yMC@{__a;Nn+Tc4DE>td1uXEbtG=zK zafg7q|BpPZ(N=h)Z#deO3l6@06`GD&^suIR7pIM^(&r#I6!=e2H@ z%~PQMyHM+w6pyy}qNV+ZkoK1iE`=&~D%*=8=_TDor;xv-{il%jiKf;z_cQh{CuYzZ zSZK3+{>^5d6u%D%%w`(LyWsj`hz&~CNy zEh9)Y7#IJ0Kknp+l?zqrq6RGU6mrbdw;gM8s_Oom=8)HnDxgzR9nLLYw9GXV=T}R2 zkUvt89T9*3pYK0W+jMUf^g{l3Xeq`n2;x`aHq2(nArcwp6a~$=#0K7?%)yU#yQ(q^ zri~pbj0?~Bw1hQObF>>n*>Xwmunmm1wbZ;_(8+$8bWamxL;0q2+2I%{_K28giz~i2 zYaM5XQ5Dh`HL5^j+j%XVjwPsYp=yhDt>jUaB>G2{HA}wJ2Aufb5RL|%Rx(1{F<)uu zZTB}byJM>E>HECC8$4Y7;^)-Z$!L(5A3NkLdrMD(Nkrc&V{fizS>-sH5j}#D1rk_7 zb2euWE*&yJMf6|50$LG$PFA^*ShMoblH{ga>c4TGR1P7?zo<^{vCIOZdfjvb8tJvs z`*QL4TAKpDD~YAjCfBg@mNLGE$Z4G?*Ul}{TSJJcnhR|m#dv90o*mo{We45Q598oo z&UzRjOoS^AdzLPyO=zj+iLezvrRV(8;I)sRAqwJa!gq?*M#PKaygAY3;Y@=d; z?zZ$T`djK2{TSSbn6Frjie0u-%Kjk?_XoPz3-yh$2@=rXy+hi5 z5x;}mQ&nVFk93>j7y)g{Bds+g+16S$=2k9oSVA8UK`-H}Vk^RLCIxn_G^pl67C<&3 zE|6_XMLCmju^D2=Eo}P;xEd@HP9-X4vY8c7F;xBd07izYw~uA@hOy~v%VKX@Yc6w- z$fk{-h)0PVpU@X)TM^3H^x37}mSIfVsO=)+sbdlp-o#!N6TL7Axf&B>Yc@3l7HPXi^UASymKvx(YATGT?T+_n?R#l%()0H8NcC)R**aB6K z&MX?Op6xh+4&XW9H`v)`V8`d=Y$tZq+OL&Q7U?ky>S`(p9MHoQE?q*7Q#|bJGk#n$ z{?@**+PaFc(yHu*vL&_@gI{D_TDfOrOnbxdyDsGn`TUP?0&f+=aGhHH93(u(V&my zS??;BCh9diSqKypCkfFgvMihY*xBAya0OUj*xkE|Wd>R^N&xC0-Lx}~Nul`k?ZOVP zP|0mY`yD3fH`svzwETeifDfrJJA>$!Q)sCyBZxUAphzkVkpSft!&N{AqQ8%fNz^Ai zaW2a;gG;WhH_a^dX25gfXm2w=t)soE;@(~hf=Ab~Yu@l`9sHMucdQsRwL?wLWLN2V zmuXm1t&oU|)Vs;PW!(=o^R3n>BxsZv-9EF}+o~2Mxn@M1+B=8i-ir?t8YY{_g|2Tz zTMtVE51%}PMR5bh$RB7F@AYUVGg)RD>`ZT~OTl|W4cXKxHDqU0u~lW_A?us*Kn$uxR&i{>U6Cnn8PTzV0)teq?n^%C>P{GOrh*@&iP?4p;trew&2#Tp`eZ#%5Y8h4W zY$2EbL3CyWgfUruAjhSN#SZiUV9<^nG82r+D9wz6`jiySoA3!p3e@dUeh8&AMvp{n zIXWO~g=^4Qr48y2&QaH38{yBC{!Hu7HennJiQbC*mL>c4adfWd@w-* z-Xt%z29j0g;zWdTp6HvH^vmf*UqwP}WegG{WMDKTlM(URO;Nzj*BK>4Rf;sfLSI_t ziGM`2BC=W*b__kXmC48&&KgHcoW-KI_24X~sh|*-IJ1h^IL90qoMZZ8m0tG6D(8=m zTIg0d&;F}xzGI0=X^Z7#FKY`gGmB@k zYm{ftcP!<-#l?I!o5d@qnzHhY7xPJ$)c)48k*#W^QvxzwHnJr&l4V=VMwsEUj7Gk- zY-B5qT$NoVb!{%2&3ajHG0PY8s~2+~mzXlQW?L80Z1dSgrpK+ycPY8@j2u^mOw1V> zpZhtkwj5Vcb)Mx*np5~*l{bNWSgu^=2zAUP!jbICY;G~Tbdic_F~3s0$gH5le$%~K zAHTeZKFA7DoN1HE_{2B70ABBekX_lEOZMoWs2bmi0j=#y)7s`Lt!=K8nZgvIFkK1V zu-Qd{Yh7o`vs5}$sVpT@W%!T41HBRQMp5rlZ)v5!l?H`E7&NFno73~Iip-ZFfnLr+ z10710Ll#%M9wk`ndXyGlxwR<`DmMkGiGn2UfI@em@#Ux;q2sZdIh?mkDPYdUTT3}C z((mguI!1*~150YEZ}i#VYUwmr_jQ`9Gt+5I>>n_(-#V6~M95^71Sz037vjmdeZroR z0#v=ho{<8mPLuZR{)CELj<&&k`HqQ=_S`;_Z+^$bCUrn_OU3y!e67^2N;+6;l?oQt zd+J|r@y4J2=g+-qDc@QNiYw0C_!A%a05ao>zM%NgU;m3;OZhf<>(cB}Z30$8Amas5 z?{!y#Lb`lNn?6I1&E?x{*e-yhkdq_T@A4_ zpBo^RY>-+}TkmiWis>3I8!iFL8h4bkAxl2C7}h*D{@WK`c(a&m8urSvYqD=;5}Rc? z&_vv^9Jp#=IiM(E2n`e_JEgH4;$g8bDaVp7n^KM4`w)9gttXngu158YXgx7`{(6S% z{bqa5Ht6sX#{%DiP))U#o7C}9?wXR?hP}y@IQB0#;^3FtG!lI$Q-%!BDwsrkWRB;iB-Q% zOLU_f%Xd1x@XTWN`XxQ=Ud*>(Hv~6^60E*B7irJZw*bsEuobQO3M>=gmg??A!QzT)xB=MYHzd3iE!uQr6lnnRVS143|Sl_?$nEG2qt_I{Z6E&lxqISfIQyc;z3ejC{C{yA0^mji~j zIO~3$cE-NhF|Y&2SlB%9@Z#ElXlB2m|uV1MA#{Efs!=GRcOS$ zsuXz&Z%{6qIfK&In017+6bXi2`B=+eR_H~Zf@7iAWGCnv$2Zl`CFg2Hy|NiLX&6b& zHowp-b`$<0xpZ|bzhT@Yv>lMN&trcp=>1@Wph@iknoL*)y3l+JFh}2c+|2*#S|{V2 zlSgmO$Fb+ASGZ0_86Sk~31Mhl6A2%1ZO7ZaytEBk?L{iWSt$zyt990>?kDQ3U}d%( zYC;t%SS(>(y*X^_8CG<5b(ZqYP`AxDS;RfHO4-OO7La^WFH`b+)5)#&Qod;^zeMhZ zleq8UH@L`Zg4^>LK?i(;25TbQV1SQgRNTrao@7=C-#PN*%}+($e56cjEi>`^l z4sTc$c>&)FM|g%?Uhn%D?KAdhBzEw0J7EaJsZvEG?0hP9Hy>Or?u#+LDS-2W9zO5h zImH4#N4!gaUz4AY_Ek@Yitf@cTT`}vCh*z0oCw`ZE>dyaf(?#C{JuzWYo2wt7neET zqw>I=z~xSMA*Qm59|*;731QXcYJJ%SU<1 z&65n`X3I-*EOAE`%Ry&X@yJib`VVAtph#{yl+ux@Jz1De`v?*3#tH}?>sZ!QWG--mHChu)%t7_uhLvn$E2XL8ZMk&Q#A4gpW+7+rHSeiT z9e$EZ&Cg+UX?_lBGgB%xAwyU?pvUra2vdr7f9H;58({Gn+5N`le#1*IP8lDqeKB}f zQ>pePY%;@V235G4D_MG*QkquNYR+yvQytPY@q<)`6UdO= zc^b3^m^naRZ^G)IK!{R1Ri%()xVBaeLC-kUF`Gmz5dDWm7w&ahY-AYdOOzd{EedwjGN@tRh4cOW1Mw zJ*b>~W)Z_atriGU`~ZXFCbmGR#vZQ{&4n1rHNXSI2zm_Xe07|m~^be4^DL;aMY zeo7rR)U%PEZSIfp0O~W&%LMc}>IoJVP|vBLY}8QCc#p$FHUj1$InO}Y2wdVLuw~f@ zjAT!SP|8cIt)!;`65PDElOzZLr3&jpYcgaj>MSgX1t}ZrWMpO-qf?Lmmu+Uu7E7FE?nJhls1SsLoTT)lFEf#9jhRvs|6yeZH5AwL@EN@ z_rcxrFQC4_im(Domsc`%8#G*o4ZX9Gsw+!vBf)O3ao#hbL}um?!D_O{pwl$j&@QS) zrL(QkZ7z`wZ_MmSMHWUB!$n^AFVX^GmgMp&|Ms=wZN87U`8wXh?ZYMB@TUiFYe1GH zoNRL1&(UUVQf?yyo5VRt7v}223Fi94sqJ@DbJRWCA*5gP48AWAwPF~=9EuY4mYAby z$u|-kBe*a8hM(Ye z^}hQ_(*y5MIr`6`ZIry7XbMYjw3t<51{74KN?W^+)LDK>%{&zoT=6n>vss~VfXund zE3NeOx9J2vPSC~Y9ei|TeFLcCW$Jl|-m0P{ewB{to~(ShKYY+CLmy6&{`;ig?fF?U zDD@a`&yjkkr?L`I>OtO~B=t5=MZs6Aq2P(S+}Z z@jL$b5Rc>bIG4PL>g&=8uuJu$XMWQXat~}NehZth2@|cP$U~iecYQKY0+NsY0&X`2reNRU!J8pAEBHeT1^&OHu;8maoKBEw3oR+3L06 z7(_8-P^b+Iy{O8{0h~)-ic2+L!gl!*F{$7X3ESwupeh}b-?!^7tUsSEA(6`9{h6rs zC)87tQt@=ZJJ0pI^L$y!xsgIQM3)us%vlJib1js|`v@3dt~q$FL;z?C2#|A5xkm2v zOV+qgd$H#(=K(a0t!wtwJ~ZUC%`>Rc9I@+%hWxhT&nzxAQA3CH0&96!%-L)o+%(w#3Tbm+l#!f~vG<76F< ziyxO`=Y->bUB)k`N;uGYUsD1(bxuHja2X({D;*HE{56H-wCjkg@$Pa^9nq&wTx}V)%mPrWk18y79)F11eJY5bC z+e#3(Dg_NCwSfseRrw4X$@18tM8yg**Lm9E5g~aBG1qw_<~v(e8BcpW<~mP%i6Cde z@_5F+BOjiAWKl&@CmmxB2V!gKnWtlf(Gli;{#j4orS!R4dfBSd=WFR0epLTnrC(c1 z7esdQKP}oGxwKu6Tw3D$HHch_FQg7aV41Rwg(`BXIWa38Ph&P2s>r46<$L^4Hfh)% zpRlrc8c)hIS^2TVV;7&a=TWnTvwuSR*pVC?`9^#01kYrpj~~gWWINaM#F6}x;DMXv zoQ@6#?+h1-@R$=E6bc}3*xPStc4eiMXCF39ZN#h+{Z$n!4;w;7Zt-AMyHe!iy~9$} zgi_>f^P7<+2|G&CP8(Jz;>dQ`lx)eXgehEXQRfJ8;uhn@8k>j>w<>XGEm1r;twe5E ztU?5f0WVeJo?4=~?=mIsttGlJK-?^s1a|a!SPXDJak&hzjkI9_U|T)I+;1B^^^RWq zcN;HXcW1I+Ni0rme-3lDB$8s$K9=k1l#;c~(&;`-`sz#@L&+wfJbH&dz`<~{gphyG zVLkTv>?ju>B*Ody!M6MZyv+wJ;NgSZ>Z}Be&WC38!5ofM6G(D(2a=^sJ{r!hdZfqZY!D z7_g@^;%V$X<9pG>FOe5UJLBgt`V2n@@%iBAHXW?@e%rk0ZPvR;*20+i~Nf zz$fT#K5C8MJ`>XALaiK6{>Ea@=*+VJhB;DO`i-PRHiYW!jZ-g^(Fs#HGgYnZKyHmop! zdfjWD9D2G{e=OSYuTCUe?-|u)C!}PC7s5P=xYUpFK56kbg}SZOIXWDEvBz(Zw&~C1 z*6;1nbyiXLQw?dRo|h9N{&b8TQJ$u8A5saNiFj*Jrgw!(X{%XK^rn=K-w{7)7XanoX>;T_ea8PO{@5yU%T-A z5aG0l7(tPB@q(q`gUAY$e*#}GomtF1I}vSI3S_C}*8|r<7$5EaF(o}CmTPm|;>_u6 z0}BIzfYb<}09R{~FaQRD+_!pJHq%pVjU6|t<%mAR{}Xu2n+HK4ACqCkZj)7PR&f! zB*8{#J4k{nkOZ4FZH{)of5hv~MkO2MGmh(dLI7!@x?xdC)oJ;%lf?I>MfnR${Cd-h zj@?w!7`;iPOD{pD1SpmRb@c3#2T`TCdYHG)m}Fge7BpJVRcBifMAb+>N$6^?*A4{f zaBAnlymK0<=fg!16IJ^RBJ?c1mN*L8a|C)@>Fw6li4w4qDbgVt2fF^HhBkU0v)v+C4d(vdm>I| zM4YlUDS|JxV0hTQ^zMAy3_a75mCj__W80j>~o-{GY6tDaBc{PwM5SCQ~|M(D~jw7 zQh+w;Ara(p2}C&L8^f|nZ+r7i>uk$}j<>am^O?v?{n<~e{Mh8x>4aFa^OasTUyCI> zjuKaTGe2MMO`gY{Il?aCJGuPD2xbZ@dg4Xb6-;Z-q4NF5SU2+AlcA4eQnN6k?i`&I zUo94GWu(= zjz=D;u7N;LSp#Tup4gzno=9xgvq6kYaTo-mc3vwyp%Bb-f$6fgNyq3m(0u3DQ$i>T zN!?Eo3>6fbyN9v0Gno!&szN)OtEU~l6`+ca`~s^Zb@#g!HHy+l;9O$BSTqWPV>Hmz z7C*lCzr6Rz(|7o{LW2R3mO5dv5s+LDqqEnBhON#yv^7F$x{ zlf8)lc3YJr@E7SuOWi;^t8N^w)tFG3$JvB!6|H}@`Q^r{mq@_~)`R)Hr9(hQ8#|c5 zOJfvzvybmIGq|0G(%+7KFr@F=QDmDa#fsCo$Hi9G?W9i}XnX}-v3|XSV7gqf9 zQWh_w*)~KMMD^%3lReRjW~Kv|ihqWSTMK^s04TGYqp= zh!7Jn$dHyzkJ(x=1F01j#tbQCYzWHN;B-KSdGnj?odx*|NawAHPEl{z?I=$FeYr3s zo$q2p1kwY|)7neMFMTzGk9|EMn+up#Rj`!8wVs~~{&gDe9koU7*Rd}NCmEPA5#2RW=rycnWosi>|6XfE&J@rwc=OWl~x>{GVPN#X$P zDlIO!E#N$TmI7VX3EUbh`pjCYM=w!b7IteghEx<>FeU@ylXb$GNf~gE)N;gjBnmk= z=)_t9v}D2}m#S_FQI^`Y)P94tf`-+WikeLfUASKqg?;68&%`8(PTpFMbL7SE_vHn% zr|pgwPXu}KBaEfR2zQa888KbeMy#()2n6hkK~Zp=mtnV@NZm&4vP3rG<=~u;sQ)j! z)3|>Rq_6{yW623ED>WS^-9NFZm2kr(qaHSLPS4J3a>t_BYo{tfsCaXv(R`CwOi0W; zI%PXYJP@zTE*oI7;qF((J|X|O!nA3ABDCIoKB53DqYJ;k4NmvSltz1 zRv?M2Vq5V$mlc1Z(EPZazhWp>h%<~1kzlqHgHu`K^=$nz*-G4Y`57~(akhx1?8sr3 z(244=9@%=)F@h;*vcMTSR%_Uzb-s`*Pl{KrE`E7S@rL5Xk!}=qivPo2uMMv&HiTAS zN~=e(@4PQf+GzQHYd~u@s^ePG_JwN^h{&U>sQVUKBIiIKXA|_StA3ij*l-TS!a1YB zzL0Rv)0{5)HJlTeBp_Z?Si`yHXI{5rH=*HKu@dKYLoa37Ng%Alhrz!1tHQZf5Jy-F zO2Yw6q;ds9ybJ`qjROeknS((7aR-?Jxrt4Vf!5`pjNsu9U#)eRlp<4klMydIa=AwQ zXX4_ouhIZ8C2$oGQkCI#huM~26fg!S_*lKM__O+0?F_Heh{mCd=RPO;>D=mzyD#!G zPG4UzqO!q&_?c9N2}Z&R16J7Bpq@Oo88p%gjbjPyO7~Zb|KK&QP)o+${W?v=bLwJk zz`@5_!QOCj%>Y)IqEkETGby#*u{uQq#2#^q!~86$V5nNGI@- z;NGDr!rGpe=A}~JuGFa+7)bkFM0ePE4<-o=7^tXflbC}lu!f$lZ z#W26!Eq=|X6^HUKYfx%~aG&tJ58aiK+g}|%+fRd>?O)gFvwci?9fpO9_Vp5sGU3$T zt*-8tr_c5;JAKybYvQe%CXQ^f(`QU3#lYz^fSXHhWv}J@r_UHSgQq%uwhwYNS~eqq z$P`{Rx)Ul?FR!+sf#{^544ppPXX||mvB7iT`sjc^z3ckuU7-DcaAD*lW!IDYum?Pw zooKJ{ee3z`Ly%dYV*cUZNVS37UWVL0lvD=0J|jE?=4{XUem%VSZ8Fl`t?ugdn8F<> z0YX#)m{T7`rY{9DeGFcX+m1*1EN6e9chze>-;iIFF1WWZ_;Bmp{38Ey`@dSNw&jovZ zG63^5zn!lnF?K`l>~hAPjHqT$X#m3u1AO=HA~YFsM5uE#NNgoAd14l0|@ z)8a>LL6R0vnueMde-yoy*)&mHWdcZx7Uw^f0}k7sXY@AvF|Id7{Uu>4!^D+OoR#~< zh`wF>F?JI9Kv;X;=K49iGFapzJ+Z60|E| zD@GxC=%g|bk`Ywots}n5sKiyEz`_{0g~ReS32tEY5a{q+9zk+9(`IIy1S)>xr{ZBe;eX#7^`A3z9L>za1z ztZQ)qoJG9@UiGby4#i=hpIoqOl#wqh!&c?k^3Fn3*4fy*I@|>|4#)eQo2842o3C+W zyl_;}`!<{@)GM&1E(#$=QLA;a4>On$%&hpzAuI<-#O>ndr_fLjL@r?;)4wlUNO z>CoQz(>^sLBLNI2m;L8+4m|C1luU?+SZq?1cGqqwoT`nU(X7fRg(_De%95v8odI3TH4&=LJnI5Cq#plK2^pdwvfA zrBN=(Z2mv9RvDkE#}^Qp0F|8TD+o9_Rjy`pF1;xD_!@5HjjK)ABS ze3kWr(eP6?Q~9$k*@&*w{Zg}OW}~O$gi65KM8pI3de&#AgeTisl481*P}9s$kcz*; z6ks!fude9K1F?3M60ICh$Fd~QU~!tE1z;q-*0L^XLNE~R%d4iZm6FlCxRHzxXmi3U zv=U_N{@}=E(v-AbZff27FyY$8xrwc7!HT?}JwXd?ieE!u3s2C>7IwHMdE64%k|-C& z(v!;NFgu(57mRfM7g~`GD+vNsl9XW!l9WZwb;%(QcygPL>6qd{+um$7CDC6=*`~g!Uh5tBgr*YeWM0x$ZtFqa{yysV*HL$15OvtPd^W#e)B&6pKx;wW0Y}~b3U&L> zfjSoD)xvl+)cIj}umkIu>}4-e#cUEX)G<@oB(xlL)g;s(UTIq3pGl~sx?^?Joz$Q) z38l{WcNyxkRB}_wpA^XRVG-~ungcXVLWpV69Gk+T8e@gQNeD7xN>S!82|*FWx(t(0 z8YZDW%^kCPtukmXOhQ967bYP(%OoWE3Ib0#u`vmm5DcQ!o?Vn;sr|EHBYxJT=bxJN zM6i_7lSdgPr00Vpq_7J~L|SRYifckrNOK|SO5c!>G<%v0N$NEr2@YIH>H(yew%opu zba87!5?)0}BGlBna1vEQ(v6CxkTlP(()d>i$+(b^q>^ImO50;;dzH4&d}>MK2nT=75q2L?>&^r| zA6Uc{TCe!R>$~~p@9%%VP44Ek@9ws*k_Q*%2SJeoi}>#XCv>pQdK>)q26~PknR<@( zLpL)sKsvKAp`T0#VAS(*6xm0&dZqd@j5CKTQ(pF=|`Uv}j<7LmB$JP`S1ut?r#a;#%b>*PRMJyDPy z4=V!_Ib4x~sbsG_fsAh07@!=;v3z;gu^<8dPK-!9WkZ!+%~sz^y%oJ>T;lkR@C-5O_^`MHLJ+MObw`qj^&UoQ^ zX3p)L2H@;~BKAWy7`M4BBh5DAbwxTuaHkR#R-F~T-qCdsPxhTt9l9(-@Alo^xh&&y z(Yd4Pb)psi+?vhcG{7JH%wIyRivqZ!)CT$xwI1>$0?b;{F_MmPxUJt?>sof{gQST4 zoqZtQ4S~Zs)S@ zy!y|LR@DL``Qdgk%4v|mX+vjEIB4=9-$v|E!PYa2FgwGf0~L->sag-~1sG!8JTfey zKxFsGEPME`0mU1M_bI-;PKq~qIPZi%=Y+ov!mm*{muXAh>#Pyv9w>Yy@WkZGbY2^I z(YaCfL2g;r*h(!Bol8DVLgzRWYg}|Lh2t+3y^k!TcccD|8D`+Dddun#Fj19YF%iJo+fD`)KT1gCtbTpdqQS2al(UmUh4 zh{vU|gz7Y>qRQz6ewe6<8JK}f@#;S*A*Up6tX|IX$0Z>`l2zc4LT;y%=WFi@>= zUf>*`bwd3WAJ|!{h7DU_CLcRpa7RB8Ep%3cSaH{CgNTX4$0)E8r*mu~Yg`Z?l?Q5e zR0nEy)Xs7s)2jnD_rEDDAzp(6H5XKu_UC_MBI&q~UB(sBvr&S4(!VU0TpY>Ux3I3{ zR#lzz9+e@2-IC&SK+ZmhRt)Cci#?1y*XlXN2uB|8gTcVToEm4Zta+=b@2_E+f z(5XX!zNTh7uxPBhBRYbMBj=^rf=%}nocI!~iXGoLNj(OhPM3``LueU{0R&+wcR<~Y zLRWOAdK|Fn=6JBdY#>I*^f8$hKFJYdKw;9~m`1sDR?AEo&DFU0#muEGGUx0^k&6Q! zf}Gn+c*%I>$gcwKj)&v;9A{&kX=;N4u#AycMxAltazr+raXtX27M8-Kev$9vLPG~6 zROj+_(MSNwkjBO$DV9GhRSZI%v!+V+=rv^K@WlBD>7sIFdTN8Z_;2FkYumc=2~_xZ z&L~i^W#OcwX4M~-Zx~4!c9=B4GSKthWx$1Dq14)ugSvxh*Z24h( znZd#36*<`kVK&C&Is3D?GEyZ7WB$E!xL+ zv^GvMT{%Q$h74;(4v-lP^*TCu$>s=Kt658Z98;@EHvvkxBIH8nd~yL%Y;pmfL01<= z(FI49_OzTuF?l$$w2>#vnRbS~zW^j|=L!TPxJF%B0=9w zGC&Yhe#jO2QaTA;5xIb1@jwGuqp?IhSDI@}`vG?iDD#wZxp{Srb~IWt*BCq^5wKH{ zNJDf#wmrg&(JaAuf~e{*FeMqf-N<3yx}qQ5Wf}TsgJcLo`5WqM=%j%UAyC!0`q`*N z4*1bXiwlHi{i3jk9%_SZdH;~1LbB?z{ABVzhSqJQ>74GN%1|e3e1KnjV93#aPnj@6 zPyIG<@2Q0V7L}`t&POZ^B4MM;iPBtmL0&IKridCd)P~~T_Z+dYW^JLNms7iK{a_^- z&&?}7-X7@=NR6QOGaSP*odelMi9vTeSI;4OQfa8RX^MeDRk0{^u2?BDv$+a?I&nWb zBQg)VP1)jU!OuX@;@?y_7P;Sxei6|&%3$FIS`{{)aO{~)IKJV7pZG5?SMGASY-1=+ zZg};-e)X&W`S*V2N6m*0cyUtQ2i(-R*JHjaIcX&zmAC&S7?V^=t3l z9qe0nXOon_zLg6@X8*-Jycmdjl4GX$leyyOr;5)-#ZOJ!^b~b|r4^6f>td~;wRnk4 z(@_|fZN8l%jyAdIgh8M<2!pwbq2xwRh(C-iHb&XQ%5Sg*1^V9*6a8;YnfU%Pu|s4W z9+COL&O(MP?#9e1NR|*HMF}V0nPE}kaz`9v^3~+dv`9cYfGECXNS_!qPB5e_n;Jv? zmLi9P?0trWl|+hCOpr}X?>fNXn>`gnQkNJ`LRSq+!o->gm8xewh{VmEFu+Mh#3zN6 zyV2)TN(FAI8(p=R0a`p>xA6<3Q1T1@cYT-CI^FCHUVVE@MpEVOR9LUP=2Y0HuZZK! zNGQPGv9{78e#Ive@mnkuAZ+Z>6d4FagK3gO3QdWVh&YJs>Q!Q()-7(bqWxmZoD0Pn zX5)j-Tqv+)41K8!ZtqJO@4glv2z1&VG~Zty zShx~`hkc4a8k4YiDJmZBxUgV!1QIIZ4>dcVh;gS)_Bf((7kUSj4bZa?orau8Zv7Ow zYaF0vX=d=8RIXkMp+w0ZNCl&`u{Ft{O=oaoYE-7ICB@YkX7~t>w4$7WlHyuuoV5Eu zzwOYe&U|XcY4yT$WytKIkN`jFr?=fElbS+jAR7~yLYHcqN9QnQ0!V-fImb_W5rg={g# z;3gHaiAA3^n~U3QqJoxeV7yyCdol=|Yol8>-ylpiI>C*?U?ic@i@iOy2I5U(p`6va zj82LkZKW9(_)&Y`0dcfoi-mN1RIUZ7Zv`E}t~ZnxM%4jkp>##CZ8Z9DdnsYudTQ8q zn6(LB4H6=_9HaoT2DLs?f?CG9&StQuDHz_Q*V8(3*ZI+JB%YOR;eU2*NHPR)>2+Ur z^fkA0$=?;#FpeL(B3E7_36iKh><3C*{L{akcGcxEI?D1{k8gG;kaiNF>yf@H-K8Q) zN*iE}t`fAk8c3k$B9BN*X5R(WTQ5d(ffAAWhezZF@7RwxNy@_fEmqfQs*7%n_}}d_ zn0|R$ct(GATUz*Z$4oy@c(Od9ERmIJ8GbvBTlXgSn9Plzmdnn`T=&Xk@zaujPv`Ao z>-QC}#>Y7-^Qty`A?8>4U;B9R{T$+GzfA{S$-RW2jn9f_bfTR~Qo@#m)|Z3?#PEzh zw?cg^NT|nYtk-LW1nD1_5gD0s0wKYXyyrj9ra7@ zaUP#UW(v|A5%+c~&Qih=mE}?|$9lY0PKQeAm4L@SlO??-yRhNaFc z4dUCRr{a6!_Yx_Nflj+WHlhWW|I-dQXz@;_G2}ubX!xu4&CpZy&iBk1PJu~8 z!!5+PZzo`ox6#wGnsk30quNa~7DYHmVo)z$`0Mm&p6dIl<41q> z9PsRWf|k@$t*qbF*$+hJI7Q|VvR%WyH25<|KRPgHS>3xh`9Jv z#jSDomobXaJxvj-9LPm4L5sJE2CYBDiYIXwiIkexQFatza)dmFV{R`7ftFm$Dj7eJ ztr`l|#AsNYP#&uWt+Fs0aJ1!mI#xCXJ4p6OnuoK&#l1l}T;W`>z9G@Mr`GQ34I$rC zg?zVO5E@)Zf^`ugBS9Dm7PyXe;tJUYgM#@m3>L@8CJHv3!t1I*#L$1gmv-Y~^0=?{ zSg()wTAF3F)rJ{2)Nr;RKk|`$>;r-IUn~?%a_nCr+a)O$?q-5K(xcP;e}ebuhE^0O zX``ty8=6Mwk$8f;S)*}t18RK_Plzu~%7nB*5tFxY{5{M`9b_B%kMiEyrvk`n`m4op z4(mt_v3d}5BxkMf(HF<_U~MhVn;%`dPH|V%{b=KF;P46p;WPr_jn-kiQ&D;`{`qE_ zV&PXjAsOIyvCMyv3}lMl0Gqbe!EHxsTXY!-vTCuw4@HeL&Tajp3b%T2Yhx|u-9^_W zRq*Fp@rX+jH|9uQCCMJ+wY;%Cin^!Gtk@t>ktt0L8NB>0C7b3fJ1oMIbbAylH@u35 z!Az9iY+3;iFmbv^wPuNqG9T6X3CqFiJ;Pf$D!4IO`Xlw}3qNQ+%4G{iEo!L+%PTb} zG;2k!muN`TJo*i>O`t7lb(Cur_fj2P(84G{vn;>LegK*J(c;J4xtRczLq<=VLc>nynu^rcCn@w6+3ByHIHeBdvt!$LA zQmS5kq*MJqY8Qr@(OOMrG=xxwpS)xX12x<^4GdMo+CZo2WE{gJn>M}*w$Wn@)L){n z@wp+Rs0PH|fM8W52oMFsGFvke7~gotZh5C{&F&pMPp{|(qjql*F?Ft?Tb*89>k)PY zt?O$&%G#a3lHn(dif6_4l9QS`u3ej(8inJ(}~?Z^(WS9GB|$r&B5T9mB){@_;53)ukU@KYSskuyD_YIo?S+WZ&46uqG+gqigAyhU&=_h4HeW^J$P^;%z^Ijh&8%xMUFXNb zxcmLK7=4R}ydRhaO~e2T7tRzU2Wk!Hkf~}`MI>F$o?K(z98%nYFYTQ?}0~XtJ z+?XnB#0S1H;nK|Vfz(+ABD6RH3IuW=3|2fIFvl?>S@ZnZirZaMxM6jx{ZkY?sRDQB zOqh&x;=Hzi&Icc8tL|I|A4&yzE};fcAGNgZqb5U*j(ky+#?0tkAQ+gngao2L zOI6g07=@8Mpia}CDd`CrrA#RNGi$ca`-5#BK&2&=a0duALm6>YN(0K>3R1QvqU!zB z^rW`CrOI*6(wdV7=X>ERQUz<^kj^i$&b&8%uLeVC$A?Z>wbC*~n&2Gg8yCIC*@koYrUtVn0Z~#AQl^b2(}r9%Qch4cXh6VW_LcIBJqQKWhcGSO ziB=1>iq*%45N#KrKoRQ`8%f0uNdr8Cn^S0$(2{{78@8>S?AU;S$=YvB!~RpMZ|uS| z5>g#i8AcnRBS+TKww|5&quZu7+9oFSq1?0oQ|G#HWCwboqe^2@jv_y7uhFN>NJ-&8 zhBg(}GjQT1+Y<$K&-;Lz%R!~R%4H3`X5MBhn`QI_bVlT5^dZe}qG0yJV;>i2HcW0( zvR$VtRie61RU=-}$4kIqsKe{P=k=9^OHh=TQ>`knVOk5-nwI)+OD*+l&W*w?lPTk9 z3)=Z8LKA&8!lFyhph8Ui5P~dk;d{*Y_Q_&_JXvxAy`YvUEi-A!xq(b8=4zC=*!3Yj>#c->Fi|j1Zsqh&IlX3)*I5b++~Ne2UUe6uPjRl z8FYO_hdMtjy^pQs2e1UOw@f#>?3{NW!;EjyJ(;SyKaI%`uT*}CT_XQ@_G}0@loOaV zf;qM3lcrbPD>lmHWTl7bjQW z+ftZQd^aa&>DAyr8xn9YP=#J$ED^D8GGg5f7B)GtGSLNM<$KKcl2|vN=xwfNa$+S@ zLZ*sXhjTfxk}D-wpIC>pIk7?zMy&eU$u_@bqAg_zBK_+WZ3vQ>)VOcsMb|hyUG={PXMI7%{U@sC%S)y2;^+DsA$#a-2Jf&DC7KwD6f0yoA6Kjg1?PO@QZdr!msC6+uQ^wMAv)6_rh# z;LJ`f8^O!VYzf&aIvdUhRAs)De0@qA&Pcd@&lqS;-wCo+L~pmfUi3BShl>P+H-oN( zAMsTOOagrw^vx3t@c{H8(*W$lxx^z@)ga`<*~BAc3vlZz>VZVb^gFp{U{m*3QhfgP zinroKTTdAh6=RfLegqBUa4%m!^ZXg7mmFo_00lO|W~lizpw>CZzh< zsHnq=N>4Hr$aJv^anb31j@5|^&9I+sV1Nc`rWr`y8XO#=;fxTML$(5Op^=Vi()%VP zuwzbO9}fgZEC6k1L0~6+%#4x zZ(^c4HAqyaL{uiuupXM&`lhC;zY|r%)0b2VW3K^GJDlrc=fczRAX%M;m~_by!iw;{ z-~4p-chYK@V!l3f_3#i~J#2Jk4ndFoe}S$lc~vP^Bfc_ZYBVE;6ff6#QM+Ok2yJ-S zybd{5QwWs}g|N&vAf@Vhp7OEUDD$nZ5Go@Ip=TUW2(^r=t-+gy=_%G1ED~if(swr) z*&4iA;d<&sPx^M1$(L!i255MWc6c$C`w0&(8TM@pe}&b&)m9Z}H7^4cisMvfRtRqUV`SYBQ9Ecw2E|pu z_`o(D8O-nlc=u+T2)HsqJPFwWw0z_6bE9`Dc)x_TdKC4x^LQC%osVJ*Ys)E+H5|u- z8fI3uF|dWUx=LqTvZ!%lRQFEEfaVO_62tm1$<-o^fWAAg@;#{yQ|Clai?6`-E$Wv{ zAX7@FilK*dIj53~%Zh5lG@PyFm2HojvP$Z!4^u~o#S8EH=n1ahGyBdX7Os%fs#pPa z7+oWj>VXk5r#UHz+}k)*hzmYg0<<+okD0@;VmdHLqu24yfiqUEVQm=-(GbavZCUj!a?Au+wty=OKB^j$S_^pN1Uh&Q)Bz~#TkNZO*?=msLV+0M{yKDe zN2)#l;S4nPtQ~@H`5>?Umt(W-;~UyhY;JrTG}dE9*J;758h-LO$~uyhP7qYuAL~va z7{1r}wx!d@6+v_Y)sRV4QxU{)E+-puiER23emI-cO()1leRYCpRRqCQ>jd$D5rmtC zOM)Qi`-%inD^w$hCG*=11i@IK5*k4eyqkf@JIffCA?1b%T?E`Qf)Hhi-s;sm>5AT{ zUKuhk!$N23qQQHp9-W@KEwu7*z>Msibi%?kbGqS9bYH#<) zIx}4xYVA6SZRsmAp)%nq{H+HNA-P?VBh+dKN{0FA5#0)H~if%FEJ#>Sn+Hm z0Ek%3Rm-Kt2J+IZuk>EaB(6zF(=q^zkPkJ*0+%&;+LI$F5!)jynU=teYbWUu@c70- zjUy*T+$T?*;OWG#_O@#kUv^quRuqY61-D{$(rlU3t1_5*{fs_ zXb>jBw3N^nT|~@MLc5e@Edp;TVWdoG_Y~Nbvma%`NN>gx#>#}z-Zo3-iEfXetxg~5Y6S}=`v4l-!!p7dLC2TGe zHubKwgsC!NbMGokxTH*&>RoLKTgrq>dUKYrwM^L3d%Y#tnKIizVkQN(TYJ|y`m}jV!K6$sm<94@mWe#Xn{Cb&OjN)x4R&DrrTrQ z(BaU~ZQjU3OrPG!m~pBWg&wDZXcLkEHYLEP#9$~J;6#DX2IA~7g_VT?EYNB;P3>G& z!e8zifsx&zVVu2uo0qgn5gI;}k7;L&~6wIwpc3$!5X6l&Deu&kimF~!C*1i41+a{W5X-F5wHVmFF5S|e9yV} zy_Z>)Rn_|89}MbNXXbtP-goY~=bn3h-E-Z)WIb6NgtNT69qvo+oS^x=p*ibDxS+X% z8k+--n$ye}Xrp+~QTWU6>tqjEyI3@2>f)@-l-ALJCl;~&A$Z+y<5>G!i+qv zPD2%9)x$f52RvN(Mf8p+V`;}R!R+mHDL7cCl2DX^$k(VDR~NQhqrGgQwnnv+X_LGU z;I)PTIS5IM3)9uw(R-Ml%i;{acpi+PYX@-9M^{fAd`0{{h#w$38ja2#D2eI6CR~~` zD<&NktsfcuyY}E+t?Zx(Y4Df2x)RK@C@pKSb}CpveG}E3MP=9?Rhy`9R=&sBqiPS; zd`fdHJFK?Q!M2mx?`tyfg-FT)gf%itqMPc%Dkngvxh$>78DB znqNCICZ$a)Q35p z2{U1F0j|haF((3iUA9o|6brA1X)HixbE0*<+GNG5=SosswWnGGq0=BITBlp&M6n_g z1%?$gE+&fO)C9#Gj#L*Fa~M@!Sj^#HdlMJEW63eDN1EUlX+69~PknOjX(adXQa#;9 zXmk)HHj>||E;h0d!qO{6InmvW(cOX(XQ`IfbX)YE5K*&m4^rJsB+dw$DY!Eg-Hq3B z5KY6KsnOkdwMrtC?y9G9z>1}~05GMC!w`2bCvPjJ#8vWZO!5H2UV(Rj}Y0_F?>T@Wx=jje`&xe@{0dk~mwm3(dt0do}s z#%t9OFjqssc(qXk=&2AeMW8Yg(x)}N5z_>FIKkVLIsuW=N@6&oT%Z{%ND{xc&}@^2ME6jF#A}irGO-DJ!yEN^-*8pu&UC#+Dp9e) z59M`lOJLNG$M`WLu~9#Cbw*FpCPtYc5lY;csWM%$rm7z%5jIRBM48aV4ZMpZDS8*5 z++xK@HNzQwAK|4;E8>i)P`Yj{4ROar&$=WWqGx+qPc7+bX!NDN@3e3QNzV!)nb9mL zqQtIl(Ztg)D~{D>JpZ{{HuFi*BS0Nvpn;1pRd|5momEtyiyY{GelvkK*So5>HaDZ?s9fDkzmaQV8a@C zIp$d7a`%9>Ri>S2E3hUi8^szg(rsI!3b4kjMTgs9t&?3V0hs|_bmZAtK-zNcML^yq zU@q@o8o{35FfozhE>_sPx5S<`5MFwQF-TuV1%{M& zYx?PW(~FWgXo^k^``E2%u)5KPx61Tis_9yvyS0w?7P)#x{51o3xHhtZl%Q)%<@?&G z0}Kk+0eGJ9JSst^eAg|O!=-=a~)u?gYsSTjo5ZGqJFc5 zU!A|kq+`>-udTc)1I&+X>jzu~ADG-=ay5M7(M0lWcEEISwcgQRLq?eG{599A=TSX8 zcFk25L2$pePwTx{$mYOR)9SSox8kaaL*zB4b-i`!PFoHetQeq(jF~jdY4JyFNu1Wa%>{Vs>Yp7VqDrS-WYk*WFJhPr{UzEq+{)a?BbU4T5==4%6NpXk{k6p zUUf>E`AoL(-P#Yh*NkO_goB2SZQuf5{X`uQ$}c5t+k6f)?4mN!`I?i(Zzyv_wDeI> zd8f)SU#YKd*YogE-ufnjudBD}0+tm;Z6k6^#q61iIp-=SHx(f6iza5WrCaT&i(4T- z)MVogmVgKm+t}B`3b{ubAJciGBc-NIA%s_s6qM1)G`_q&jYmbav;u>XK;xsD=ngc_ zXvWZL6D?$qOtjCub53fc!7mvMC7OvQA{SIzcSB0=Qa{ckspGa}2+i0y1$aiShPw_a z=!A}g>(HnrUseCC|MC8R9eP=^_U>4uR@dmHUASYBg6Z%EcPvsc6W$OUi}+$F#Ob_U z=gYwe{!8CDMsN#wG>h0s^nypHO(T+Y<8BB?Ff?2ALKUAjeGdqzRq{Et=!IH*+ITIW zXp3H`$ES@~^O=s(3wj!ash$~F(Dg0FJ&H3VotypFTyh8%Pb6~7F+5sez3Ry;(c9{k zfVr(?q>mzRySC0XxCp$=G~AOmTfM=*Y3k72sM!#6*f_I@W?Xv|&A9HNiiT2q6m7Wf zv5E#w^|GPO07WjwUyYJWF|NFYP3!&_n`zL|~R+`CmbejgZN zO(EPtlHY!l{AQr_{gKwitI8S)HKOb{Bj;_c8WD{iHzDb7eIB>(NN$$#S& ziD-<071>+o7MZ>^HAPP13npdGIj*zh>4;4=(Vz`ANIf>w%r%2L zMlK95S7A{{Pou|89oRN~>c!gBdv%-owAL0ct+78IYqMamBjF9k7~`P+R%MK}y!7sM5= zjN8#n$3i~|M!dt-(4oXwOl@*SK}&KYSjcOtImgPLP2b$Ws;$u>?h+y*YrQ@tj0O`m z{e~4<3)W%;D=22_&+5myk3H&ybhYro+u73C6lq?zZ(lN_GJl|X>Ek5W(#Jq{<3@3{ zE(#KN6r^NR?}*YfVa9l?>zmKV88eGJB;UyRqnApLlWz?xzC<*!9kaJqx$A{;MrnDG8e{pebuhCIpYVI-=a zbLq1>Wj}Zq59==?Oke2bfPc)aus!#kx7a60dtXQ;;Au<7k_E)RVzPhG`X&Yi`95(C=({K916>{@obv>wy!yT4`VJr@QGj547%g z>Lr1N(I{77N!XCFr)BDt6)2^p3M6b;fueF%AYsD_nlLC8NXoDRu>uvi)1FSH`KrL3 z_7rr6eJe1hy)BMoj(_9uT`EA~o zJ?RG;7<6oHHp1w5|LEwfpguY)sE^JH>Z7xQ`sl2nJ~}I?kIo9FbQdY(cg>v~2iuK; z!ywxYdw3u{p+8w`wSiyn!d%)&QscdYPuZ$b$8G^&fYV|6+yX$sOqf2m08r2i)90bZ z6!gRNd1x^Ovtjx?w3vdqFnu0cOu>AZJ`XLXU=RlAp~Vy|5ZxodJhYgCeZ=Odz(b2E zxP~MgD)7)^3KmH*q5=;sreHtkomAkV#S~miyoL%qw3vbey6TvMgHRrv7NOd5inDzq zvu=k>UB$Q^?lZERWD6p=K}B#Pm?gq>O!!@_l{YsL_1J$+`dnO?!h6jE8qV3QXdSop zTr_!rz;mwR7O&F6CQXLoHp!5|Ca4`Mu^p-vO`-=Xq542gsHOo4!bv2?UQ5zZ_M2gY zj3bB>ia=tm#w$|TTiIr8bE0ZLOZ?x_TcbZHxQf%-wLKtl7tHp zz7@<2=dD15Zw0-`VhF&M{DTyatNmVtp(;*jN#wy6PVsbAEEaPZ<}=Sc^JI4P$@1W{ zEyxDubM0=-r@|ee%A{Q3&I;17SY3~!Ml&o{SKugUg~jR$90l#LSY3gmpc59W8x<*- z3X9d54+VAH*=y^#vw}MAte_W`vonneID*zm%d;JhSOMFiyUyC!A1l_jP-AU1w&dum zu_Z@ejV(Fp)!34gUX3j|>DAbhlU|K2IqB8dl9OJIEjcrSa zBHjA^E$P-x_%_=Z8H>X9)Iio`$FmdOiP=MS;y7`8DCNQS&+~-zZ_yfRhlFdD+*)QQ zj+4q3I$q0JubntfYL?LPYR-^xrqmMbku`Jhg*IAjSTaq`ktvByS#r6wh}3`ykhdb_ zO<8hdjf5Hz_T-+Sa?n}4v(oGN*>t|ilH01FAFtXP`f$@AYwFu*(QVL0xaTB9t&Gk{iO;fj@3V8=tUGlCVJi;(kFvF{=RE9|VRXaI~yX3~;0OR1z;<#?4P z)vi$|Xt18-mGdxmLf_hwwo+|5u-~U+%l-)I($=qcrfDS!BL@q-ki?)N&O+kJKqQG4 zrl(-&0z7uHdd^OSY!OM7g27_qYn2?WR7$B-63KWiM=Q0E*K24UujXh?0##dpJw`yr zNQzN?gi9M`(lQ60qHYJ3!Z4^S3<&ygD>Lr0DBuxZP1>ThJU%B27W zXf!CR1DWFmhDONR^#c$g*{jvmTkL+USY5brwDBq2NX9QYrEudl0#_7nB(Pg*7o&^? zkMWq_Vk&Ulw6bX_@2O#=RNnW75!c#%a3OJG#jE699YuxNLMNiaNF@5i9BCFIU`X3S zAwK^#3K3dHD8!otekJPIq6;Ixa8+W~-e&xh76=X(<3-NyozJs2wq-)pDaRj;lDZQu zFd@a)_-gPD;6OHCekL#Ly4Z^$@O(a-P5G~W@1M5PsRzh6uJsKO+2(->2Iaf9ql{8_ zucGc=ow`THLVta>S=)Z31;io!fjd{+5Mx|bFXn13h+0u;YUg9Z3_%|8GAb=Sp+8w_ z2glB6AJw*%i0ln;y-$a3o6Qr@d5U^OdBgQ0-+k8Mb3=)8%* z5-v2fWoAKYW^y%qNH*g>+bp#(H4|k)oKULWzyLE=|1tpvQSS(tI9MI1JzNa-L^JJ( z3}k{s$AGs94KlgFOoCA2_PFv;%XCEs({(Zcp=0(qSiLA)JfC@q!HE^m7a7=#k(HX+ zl*qu0Zj8Z#6CtAue6`?2kwBsC)F&QLHSz4Q!^9@u#%+#3lW|>q(cUV_gjOBD7)l88 zKoKT;RF1J7acgal7qQwS0?mZ#zLQw>roXvez1gL7Zj3`L)Adl;Ej84vrK1wsxU{+0 z3f=7@qAy)dp7zm8bFU`FyYkzQw!WGdhnpszf`ru7X-4PIeCj4a6(~7R$37PhOWjbx$&mFlZw*C>VtmkG~ z?n7Nr15~r99xPxiXS3%9R9mu3x+k@%1{v<}x2Q7JJ8~?L^C&So&Cy11gs<|GZyaS? zGlQ{6*dApG&-3O+*51sTSE`CCU#pd?S^cU+{765P_x0{o5;~Q`;Jz&#M(PV%V9L{K z;idJ3*ALzgYA?}EOSz84OU3YSBN4LkRgP!hCXXBCQ1tw5vorP`avj`8A^?>`oeQ_k z8XQ@UEEL|$T-hNr17Slras=vkcY|N^v0``Qk-WQ^rB}>aK`g$(O^w-d2pgGKNOh1r z0vsUiM@Sg~)%j4E~Ud&O%8_30_7@m^ot!ea;}4 zRwGGLTj1&7XOt%8XQ2gp)W5MuJ(#u!bj^e5*fmswX&YJ-fTaBys~Fm&;*E73+dJ^| zI1axTg&~Z>3W~aP$9q#iLL3$~1Bl9IcoStJfAOm6P0e?GBt$OsHgm4rq%e(80Q_i& zFRHh_jA;-1+*P}VuQnj_D(iO|#Z$1w?-{>vms$9u8dH3tWQxub#RC=b!cNP*pd)PX z`;Cp&xZO6qP8+N(5@J`8%|s?)zE=l-(t@D3!6cA=Xb+Hnd<;@&-Y)~BYX<4sHjs|q zRhPkHJp`zMgWqlffTgUIch%`i7MHtsxvLI_SoF^$uTJ$K82L6lC0W2lN-yp-P z#)2;92p6*u>o9g#-8T$eVRwFp$-SuoRV0IV%V77RHN`F=%gPXES6VIc>q|Dh_H)Hc z;ep(E#O++`#s4#3e5z5qo$K>l2?L!SO_vm%Z{L=cBFMgFN)MFumUw08wZXw`iwS8A ze!AH^JmG=B{Y1*;5%H2FG+zbDC_3q}j{q%Rt>T^fLI--F3w3M|3=K(>=~LJag(JqI zPPM6a>YFND*rZwHVG^wj0bRs`NXKlur3j72CtTKkyDoFl>eAPA;nh(9_e+FyDJI!&1LO@s6h=Fkg zP)nD*2Qqyx=1p#5!U6z(+hz?E#hV307DU-dfBA+t4bA+3v0vr~8wqb9c#;{hH&9M~ zEox@X!>?&H-p~N^Me=5(LtQ=0*9!=TP1JgOrNqdFCf3|ij0U=qZ9(JEJ49C+#d}BI z!B{2Br9_XQ|FYq}>98oo@W$9Q12QS9GrRstu@5nJj@n^MaWj~2DVQUD#kG_@=SZXX z9WQ**1?JB^@x3oJ(mp+AU=*!zy~{kq>?W;Zz6`( zzVhqxM{c>PzHz+YIWj#EHrufJKkAi0sZ#&st?@!A>a6cEclnFBfkzDe6u(YfaHg4% zVkd8^6cxdw_z>2d6kkxE88U243j%woesF`i0PzB5(RzNnNJu7CQQ=TF0@?6IbjOP+ z?vLZe96>#2qYNdZM9yJ0wez#L|ji@k%<9 zF!-JvNWd>`O`upRohgN&n38ZuAxKkp3g96k*62yTJrgg0y<_L=W5eC8>R_GG(fSyz zk7++^giBxvqjluOgY(--VaOG>%lyA_m-*r}cCY^Zt_xk=zd`_4>dK|Zw^M#!8{h88 z8<93)&2V!4f-x59ZDeV-UoZspObm<--BI^t7##+%0(BQ|5=#b@wBN*SGG&Q&^Ny7I zvP2RY1|&&5yklAB1nG{{kh|1$xHU1eqiIG+7!!L0X@rjz5&Thd+RW+Ksv@n9TJjk_ zRuvINgEzkJZ+`Ol=HMZnqpbaYcUS%anNyIWc(HoHKM*G&>$3A-TLRu$fn61^v z{FQtkN@hSQVeh=B{Q-3}6&g>|IN(_EAXU35+67e0l-~M4HjqN@umKiHp=cUVPqeMS z7ww*Q0sT5|#93yl1?&@2jVnM9;bFIx94G^hUi@*xodL`(5h6w$!hF{q-I>f;2D#C_>zV)wf=JbhW&`>C2GW3m}`Va!k{x&tOzmh#$WT!aMP>}*4 zQ=BLT6;R~yQUR|FKrMLzZw^2mENdvNfVve>0MObhHGQKg-v6b;v%-D=moK_(O~r?9 zD1K&8{Ag1A!R$avD>JI6{lVX~dw-aw-TM=>LEe}5V0JPCH3omlIWl+$cT65l&&peL zG`$Gp;o~mZu8yW>#D9*GCx>-t_daqsRYoR!7CeF8tnr?N@Ks3AW{d5qfs?KHrqX-n!!WNi*z52 z8WmoWn#SHRFCrcD45u#`5ws@A*{iiPwk27bZQmy2lxJ}>3?dT(|FHwio$|jv( z4d&J>%pu5Dm_u6;s1b9=Uo_@|M75*up9=z-$HO-1RLSqavU#Q}0UBw0Ob^G#f%%eo-11|Fy6tFVS?G!y{%*PETk}=oI8hv1<6a z#C3k2f<4&vmaIJx)G}W#i>}hzd7DwM-8kMQf4LcEnk+e-^HTe#1xKG>%0H!db}`CA zTRr}tb;sb$k%l1fKN(INHY!aG+l{2D8Ee{Llh6*9lYR(>$1|ka8NH*=6V$XWW0(uJ z*|xc^q@{g~uq|VX#?3IhknCE)c6|=-q8bcju|uMhMTxjL*80GWcLN#k78r)?0+^OM ztki5u{ z5(oPdvf`1MNl`a7riIj~v6f~G4bP_)rd2bQz@yL$tan>_hICj~>t5D~W1S;Lno&?@ z4}F&QHVI6iPlC;;Zo$U#!Ax*tEQ$+fJmYMTbVH`pj%H(?hZ8X*(+M-u(~R`SW@KyO zq#03gH3CCGu#QLWZASV&g+`98ieMQ>9`sbZ_ zd}UeE>~6oEG1WMdtczimBxm|8F%A56NlHA+j3Q0#(Ck`1+tXM#;m+OOfBx2V#u+wI z4%^&09$DK<|0!x&M}cPBTP_0~l!uw^ngQgLcX=Gwb<)sEqwsh>rEl?x*`*)F&ivD6 zm!|r0^?aIfMqyoH5)|S5B37!fPEP0D!!j1IO+Z!1N9>KGVH7hlj6(E!TCV@f^KPPx zm9ehHZ06-{V?(s;X>3|8^a|{{vOlsaw2fJ~Gb)U@USxTbf+ME2({M_Vph&tAL!k?; z5&-5=>B{l*YAk_%SfVC+r0AJG?^Wf2DDerz4 zSaV9&R9+y71hdPC&VqDmoDg9^2NI6p+J+fLlFVRgv1zdx;v0Aq-7`A3!ZI{ELn2KVIc$>9jK?s_n2ZW=Mrc`%yvrce5@Ip;Syp2FL-r@zL5(&DwaI4Q zG;1b7BN3VPMo2^$4giErbz=e~3Y9V%@Zo9;BhAsha^gTjL9m-CqhtaZZ;K=oPzaNp-}$y6Xr`u?P$+Tddgq4bIjCn=X6?Pj6-W_yl3OxqDOg-Ks$%1z>6q7HAn zIo-;{1_ngB61Jo%$y+c3=(OCSSga*i9Ak&yTC&4$D;Mg@$U+tF<9<SrTA10G+?QNhK?lAW}H)xNI9=`CIzR)@ECZ=w~T-W9~0-Y6qI4VsDLdYoB(2- zu{nG#7ga~#gO@mbL3Fi!7f+P-6`fOPu;Ogry}pF@6%PymGG`kgtvz2 z65e3usl~jG$znlJ9>wV1N%%D-gli>)uN{F960QKNp;sU|PDSC90c3v~nf&C1g8KRr z)SF6BF+tZRe|J!K*t}~ZEhrB3`JxuwYfFIt0Ufg7zP*I|*f`wVFSruL<${|u0Hu|Z zU1E2K&^Oz5^Y`#BOS^neQv844YG$UZjQsw4{JpgJ`$#iQA4u-Qeewy65*(+uP;G5^ zS<}RGDdp@Bs~Le2FuUr0A0l(k{|eiWY)wCO8?|UH3(xciPd)<84WGUJ9Y6KoUAg5wznb@S z`h|-EB#WLnfu^*P&0P85$-nt0=Rb7s#@kh6=7T5S{Kxm7`M&S_82xk9k)FQY{`(Za zb;h@Ig<~?bDWUk)eENfr@or?hE7;etXphvayCYM5?KGJXhnApu^gT}ByON}d;Wc_58`0$$ zCMi!^Cq!o0#TZ>GtEuS~j1-9ZOYE~HS2Z8&3W`hOp4f(*hS0LCz}{Y62^Uz}gEby7 z>B6n?AvSRE2d&=bHylWcuYJ3R=bDEW8WwGqxFHyA54fR0#Ep|VWEWi&YVR%z$7=}o zP(b}Z{yM!_gMM^6?UyG#r{uIQbYzr8S$xS|(;k3i9z!{A^@PE3j6F>Zj`{+kWaKdm5leS?{iTA0lEbfU;-=i!!uY!BEJb?w@ zH07n^65yn$bsJ(m$!I3#_ju4TN{26*_Ul*ZE8{|ND zponRwi0SA;7FGBga&G+OtmgR}nhhN>)-69wI~mO&xq9JXyTYY=#+rxO4^I8yLY|hd zNav3xy);a|QYPb?a?c{5b5az?4vnPRGH*?G97C4Kbtz{)vJPMm2UKa@z}djT_u`;q z7Kl>As@5yA;`a^}e{H9;S|Se4U&vk0D6JV7hOh<{4s^0mood6=!s0G>+X(F|WC@+g zKTVZofV5oLBC2WaHY2_0Diw=wYQI^oqhyOG*7bC9KNuOrDU(&oZ-vqtaMtGJFn4)Ns%)|jZH|#9PS#itrMpe z7Mh)+5@uQ5LbwnGp$rpnoCwFA??r&37fwhC$6B27lr_Iw+gBFO7p1+=B%HqCVdQ&~ zB3gr=$J$~s^{iqJz6}!~0;j8GNc~!1eaL9x5J-L33+D=pu<&Kyb_3v2*jxk`aK!Ca z@%$O-x*SkZ0B36qlg4(L^2ncAwsFIiaOe{No&nA$pykc9!<_IP#(*%Ah+EsPZ*L)o z#WP<&(K*B~HjT^LzlC^Vg1IRYiQ{}+n2)9_xV<(%WS17^Z&rqa<(QBZmm1h7Hcv74 zihy(@ahALlJSqxY)1tWOgpG6-mKBPRRfBz4yCIkPy3l*$i$qK~m-8ote-Q=tIX*mK^ybF7-V~U=k@Tk0$pdaI&B=$Y#lUddUk<`vN({P$LIR(`GdFCB&A*Ac{NKC+?xT2;bf?ZH}kgVQ)mW*-K&Ys87^K+F@RJKFeKEJm**Syu)+7TDXJg!~oYoHXl0ZBVmQNoRCF=&*N8s zB%3EG$58??7Bu@;HuL>pOgWmq{07+9rbh7LEAJ@2WWP4DYZxrG4TX1t<^47*Z5;s8 z4KJMg>BnI!#AK29)8|S3>^a5XI-5w?ocG%ER@+bn#f;U|<_^5q04WpM$@-gD@CH4i zm!AQ_XLtzeZ1#j1eq{O7!-xoh2J^XxSze3T!ADr2kp`{NGDJ!BftC^HVCv+&FM@8t z-v{*Oem1*##i{nJQ|%eEi#T=egVJ=^XoGV{AdhoNBCWFkj_bh>8X2rI@W3H#TJSyc z-n*dd{-)fRn^%NX1Ln?rieEiV0FI8k=tgldT^)8>XNKtIEr=3R0qIkY#wkOih1~EQ zWb`Cs$Wn9B$gAXMDg`=>?&2QDL_04%&1*7j_1w8RbXE)VH&P^|c||yYA|p9KrHDtq zNVrLX@0+;|hnQIn4o=LVStDn_ESTWi-Fa`5`M;Yd2)mmZ^uNg=t21G#u0gp>1!ky@ z&_a*uhd$_BOAiElkLPrjV_gf9-xLbX^kWAe42~DrzJi!e?VWe?CWBBg*z4`hcXJPF z7`Zr(fOEv1iR@%mi|_I+Ska6a!Vu2!88YkFl2Y=q|Ni6sR zV!=P}rGqj!ydyoE9+JUtwTV;O{0%fAuGlQTB<&Dqqco#qSyvnGYSszS-w6B){_boI z{W8*MQoQEDNvjkam)ss`iuG^0nM%}&c)zw$>P`#TBPc# z>;~9BWjUCU@;DPM1}a2(+**jWV6=G%{zfe&hAjqv&jJr<+xC4af-WMmZhg#q*=(>6 z6fZpZ8%@Mbje1=f{9Q9O)`P#Byw;G8)GW&@(XRD9p&TW~8*?gc;ddIB7;2nh}y#jo5AWFeAZY6P4OX zuu@ynXvmB$z1n(Ek>Y#JFd@@|d=nBwd9doy7;6TJ-XZUX*v3>0w{8A2?OeA@ zNNv`$;NWI3_r#RJsI34~iNKRPNYUj2?|HCH zJOR36))5csgXah}LNHs7)}Jj4Of(WbVOM2XIa^5b=C2u2%_#bJ45=87JTTIvIT81Csr{y4EX0f3X@W^aI zjy}KR(@SS^Qq|T5jA@Lhp;z@XLey)d(A3JJ*O!%^VYwwePm3}k@Kvbaf*!{xT1jMW zg^$s6)>1n7I$dv*zU<`=40vL9H>AcK7R*Ta!W-4-nB&Usq?dER9FFo#I<%pPAm@dnck2$a~`EXsD^;F=&!)lSP=AA{M z5Ea{a#g>fnN)M|gjPVYs5=g!K!aS@$8Qhscj>kg#QE^5gd9`vOiYj+^uhJm85E09@ zwb@Fet7FmHyR&=sx7)qw@%;vYr{-HVhzv2&0L{R@7QWT5`HO>L_^(j?em*5bnx6`8 z))l{2@$`S?ya~B|1#$Ut>46fe`B=}){j(<3;>n-^Do5iItgJbv0z$sWbS4M3FXqQj zj)D8BDcQ(sDj?YAuZtz?wzHcG*eX`fo99ipvAVb}tMp>lbUl!rTrw--sD!Ew9hp}F z(hA&V;O7#XTz(g1T3mg>6QZDp=#H?qc9o>KGGMv9-gJSi)q6)+MUIq4#0Krxszt;} z@jWae8pK7!z``QJe5^xvNfhm)%cL&a#~1|`k!)InpN$@mpG!$5CmB(ltl&7+&RRRU zX9w*WYz|xMdX{49meM4q1F>P+p2k4WZrPH#$lVmWD*4x%l)$5?U?=sqicWj(VN_07 zLr&1^eC&Aa5KRF~A_H?{I$UBy!rmhwkWnF=k9A(ae)kp4AA`33whs$pDt*7Q@mcOu z1Eql_#Zemq0~*yGr}BP#k_?xrL)?Tmw}!~i{OHVwI?}??#>a>51`MUP1?mB{@d~=U zu4iT54Do;X&_a`wms)|A-p<35sAQS*b`O)1yN7ku`;*E!=Du2Y9}2FI*a8=h0^H_P z>DtUQAT0_&GzbJLSklI)1z-CAYoMAz#PkPKPb9pX{~x`x@m=zvHN-cR?hVV77V;t> zu&l8^>KE&Q)vf`{qvB2|m1h|Ukh>TqxWFa*{QlyG;u(vb#PJrLq*Y5F6kTYk`79nQ zv$n1WmY^{(i_b&yHI@*To4>A6ESKKZBc*qBC3GNt-aDwT*XUhU+B+ebIF7_YK!+Ex zLrBUOAT;jSgM6GbR3H32_R1+4?Y<1>zHOIuzn=^Yn|KdQ#JkH2z z$!wp4-Mg% zmjkRP4A$lCVSN}_kAeyG(q|9?ioe3bNWke<;*vXVX$ z%0Cp!pVIH=pxF0^2Tz6vkMpSpkE#6K+9ZvWd9Rz{;XCz^w>-?J-tu55zZ}Z%^WuA{ z_0(?~KfA=&&k11{z2)6r<1D`(rv_}~3}2sB4Lly|`%bTMnqN=6UP=<~K9!&Ja@a}n zjH<&)RD8^fVIvZ@SG@3u7cTpdmb?%SB$)dYniY)K{uUi*>3$M~Ko)xZCt+yMYDkws z$fIofTEeKE#pPBov9NfU|7c?2>l3;tO@RpB=m}b{q)#S8KGj$RQZ^QkjE$f4jrZx% z=1*Jm4~;fAb0FrOdh-u?^N)`<|F|{(-O=U|^m_B(RrB8C-=FS(VD|nfVLa#Q3YALf zIXWsHgc!v4ID-cp6BChXhC}vkjqxE*Ut5fv$X=>UL`!uO5vgs=L{vfGN%7X-W2ad zv(?TuU91s(C-`e>VuYWWs?l1NIO6g36+yOqIp7;ay5TgjDzzxHW~;=oD#krB;Y>d8j~#12Q-X(d?tt_ zTy~SUmF<*~70EsMew|-d1&i8(uvMX_gUq%v@5!%~K~WWCsF49t6&96up_?tLhXXpB zj9n5`XU$7_M<&6PywFIiAtIib2d;qS(42bEkL&rd7=Ik%$AR!8zm6Z*#vcbah8a;W zE$+7UhWYZwaF{J;*KG`Qqk!4lXZxCNAHSqS4rAX=A_V~)EuLY>^Ay^U8J(gnEm$9D z@>gW}Cik*e@a5c}%lYNQ*>%~{28jk`n70gn*(@_F9I+v5(tlmD1EE)1tl%jnI3-^gtb{1=Wxyf=pLze!})` z3^oka&Oty_r(mk0XeI(S+}(xs!J0+RVnhW*4v6A|z79wXqP68KfVIgq1XEqL0#x-5 zR*t<`3XA8>Q&=yPW;ZcP8G>BOXH>mI49zO2C)kgzn-!^&_;q-YTfrKJZ{}B{@w?p& z)M$7t??BuGS7%jg7#d;Zj3>>op#pr8&D_oc;~87p1)TL79D7DjOu;rV)ay()X6n2NvDQ61h2mr*cd#>K zO}Ys_w&%F%+H)DiF#Xw>peHod@NY<4$}=uRK>C_CS+BzBBAKzsn8hZ!UFT&SKk%BS zb{m<0v6*W@kuHt64u&?+(9q&+XwI4$S|YA$vFp64J~UW63pNai7h@?Sih|+KXxE{f z97Ou2R7_!T!Iw>-19mKLtRxiO*EA9(zqfDAH#8K2<6}ARox$7OswNJQ^;z;637W?D zJ;Ds@`<`Son8d9t5L zsAM6wOtDacIqExs+ioNaxdQW|b^^I@d?%2%nV}&Wr{6UE-=+f2X(GBpL@6Las01ST zy$=6;Bk_9~CBd~W0#NF{t2{$JoI@<>^8YmRgWZ|XbHp$Bnx%14YHO7aY?Ja0LWHZb zGiFJorQOv*%plBMxyuq7YjNZ#M@ml}JbCt19FTm-o|K@%(KSt{urwt<%F-N8yj zK3La~6M7D3JkP52IrQ8q5wrXr5;wv=Dp=fxAS3EIq9z<*+egm`0_`x8X9!*kh3d}B z5qJ%!f#Y+Hq@>`jsFko~Axd4x$P&17d|k3zgd-Ns;!gM3Hdwq=VUaKpU56mpg_0(H zq`f^L({^)vp`-NP7mCt*4S+qN^zDvPpw~+;M$wADM2*mcw?(U?bP1HU z9hq;JxPJi)6H^9m1fNWCmzcg{Q2h0w;vXu_cT>g)>?5*L$)v6DNQljf#e0C`j0}?c za!v$FBInqnj=(YHXGVKu^Hq;_tqD?tCu4UW#RHaswaYwO8Csn3 zKIup!IGB;nrSF`6L7ka41vBSZ8S19g_yC|ZAGQVwFR4^DHhutRW!1Goj+`T`E1@kh zlhO=T!BjPn7PLW56;eb6R7bRKy+vJuSgCVzV4CQqAJX8;OCqK9*}J0FSE_(g>!JoW zbStx1J%8LMM^K}PnP^1dFSy@HhG>n=ke|<>xYH+{5A>NI+CYt)Df;#U9gGtqMaybr z8#%w1vsY|xTtOwvHaA?I<17b+WIeal)4`4WP_|6aGPg14pB6e`{tElu&km{aLG@8@ z40Qk$oDcQ|tRB!+W&oa~lz>a)MGy{79x)-wd>U3@LX{~|D?zSw-ok+(O+1Y>J%;-1 zppK9W0>6wCM@(6TLnJ&DuN(ocOt3zQQCA%JqL&f&LDA`8eCeswoH7_ zabRtW#e|{t2cCge{d4+IAIn0jgIEUUOac+gireC{+Gd!l!nP>JRZ`^WwwO7H9DOwq zNfzj!$l~M44s>!=-B};nF14^#a>fpcv-cY|&*d7s?o&u$b56Xd`Rx5LHx167+TITq z>U+Q4^X`KzjR2DdS(}Hmg5lhr=HZ+V5`b-xx_F^B53x|)dAZL61Jx@o<#NL_Oq&tk zn(cHX!we#h1Rm%hZcct=Rhay4*@@`mUS}$MB(~a2hTV8CGgXiXN4|yYe(9Y^d0Iw5(S|EOTc`!DF zDz@Ebs^TCTWBOWv2o90f0}c<5gV+yfRuxO#nW@Ux6N}f6gJ@Q$5iF|8*At7jjn^l7 zD;DEs{$goSLSu~<_0pj3u=Ma2IxRXkV5hFQfm5H)z0sa;<`pN9J~F}yMg?l#>SDH5 zwd{&;f|+(2RlI05D21SSknOKVMXROAG;P0PfnAPLwu zW1Jw!lJdx!R6jH;yj3EDTDFtO!alAxp!B;)$jc_9wTyhCelnCU#eIoYxKx>)7ip69 z5>Z<6B@I=Hr79y&Vo%Xq6#YXnk_|1DB$MTH9z{$jw?j{UP=IGt?vvjI@yZmr{2)zS zl{>tF|E(QVx$8Imma!ovrqAWe+4V+11X8u~JX;bKiMHe`q^v)Dr9QgDBaA6wJjCV>QXz#|oLCeBSCqL{ZbIY_MG$EK9YOqch9pOx3>m zB$TP2d(U`;?VWF#Ym50Do35P1B!t(G~eQ@5(PnkE3g8?ri6NC+^{N?_DP@MKEk;DL06hV z2e;I2_6DwR5B}z`+-o}oi>QRtxf^nzQL$P3m}BE^0^L|%*!~_6jYIVMFm0Al02sj4 zfu>~wCVRUs^L_?X)%zkaH3%gbyCSRZ9KW1U6$@q^WJ~zmuNxljx3*d%cQO3Z6o>op zpud2jhNM4D?LkNgTwB0$y6SGP*53TJu5T<(kxHlKV_~dzo*Jj;Fm)!WOAJ#yjz}(; z*u*Vml*wJyFIfbQ2ifceqCIGOfeaO9H@=XwH_G@+^rx(_DKmswjT^w;=FF8eKyvY$ zx0?+BQq(q2mMa*kZA{|2N|~h}9UXCLW^-Ii=%5X9*WPpX(YV{uiG(hS>RmM5L2rzW zM$|{-QQVcBJgiZS@sr;R)thIsQtovE*2oP;dCs8MK{RpUp!J$z-+>bxAqs-Q*OmL1 z#IVm`Y!Pf#3t8%=axWq_ozu3u9Sr;MF@zEA6`FP>>EwIH90^_8Wa;TbPA%D=xutg7 zS+F@Y6AWg81)%S@Bwqgt%9a+wG^RI#{(0GUfK~-b>)ouY> zu)zc($8ZtVITW07KeM$*BgKsPzAM{@Gzs@ctHbJ6AgL&o=dWZ zB;;qp=i}kig8C_c5b@^QsjEKNp7-45i{C-qGc|x1g*V13oY=E2|d0+diCYI5FTH zOVh){>)Ayyp;!)UD1|i2SuZEgi*iE3eecQV6pdl{vSb51VaCISZTFK|W|nTtBWaqiq1IPIK%*A2BzYP3fX}ek3 z8{oUo3Tt-X7YVUcB$ugO z&8*<{CxX_W0Il1;uF0;|pEWc?x5Fubk%a}qt9SZ%hKamxvV1CwNFL9!)bv%3f- z)Jc$L+EPip{NF$pSFti1&e~MMpFx%d{>#Cb?HxVSKB2mGX=Fm_rjOuhXRZ6lx*A`Y zR|M`juV(e&oRr37Au>Uc^FX7BCp)%k(GeJ;=r)$yeUJxBmI8`^6#u!5**P0|B(^V}i>2a&}fMuN#7o)a5PWO8MBX)XpZPm$BOC84kq|2HzGukJz z*z>TVZv+J);5L^ACUVSBmM|tN3&P6gYpp7cO_Otv>lxxPjcy#YwTvkJ! zv$~JZFE>I55ACso&)F~_4GVv*S@MB>Ho(eM{xY_j(u^0kz zbhyiQyR4B0CeI1HG7%!L6!Q)ns3ISH164FfOx73^A%d82Euw(~?5xuY3LWX$9SRym zD11noi$FqZ@2~eoTid@iSA$PRy!~>j`@rt^JenzaG}9sh^v2-#lrOh0Os78Hv4`WUbOG!dXxzOc9|m=0$2n6E+;PYd+7cR^lg9 z3iJ+E(}Z;V_;^AsSF^*Q=YX}SlY}@zX=`qH-XV4%NfXKlO&J#xzD;Wq9jLVrlyF#| zx0Ha;BaPk%x1vnq(l;T>l87?MC7_Jhvb~~gw6&p(evCFsl!0Lq)ZE;-3lcHpZ9{Kt zP~VKmLuLycq(t7!LvNt0SuW8gOSD;75JPQ=rsWcCYKgKW!V*Pr2}`s&x~7zw8(O4K>e%gZwKh_$2y1Pat=>F|@V=CIE2zl<+3zzR!L3`*~4jx15w z5GuIyRC^Q3Vuf%Yl$NLu6ngX9{F+W>pK2#v3{nlT*_UtBSr9O1tZC$pv<;(aXhINF2HL)4C~ae8gHD;EYYQhGq@Ad{FPQ21UTAHy(v$>+?yzDCma0Q++(9az2qN?enq`v~a!b0v+Fuc+{bei887tqtf=vPMuQ1 zN@>a*1^s&ZX_2(-Byxf)L^G9p(M5xj?@S6Ss72Uiv^j$IM889%4)GnR-rf}~Q+gEm z4zgb(N-$jgXYJ7K8fbDz<>K%b?HZ=dz1fPAKrypGp3c<-JPzse><=KWVxnkr&)1s4A zIzh@;JmZQ$Dbwp~g?k6AO&+*J8U*5EQ&Kr;Or@(=h7ocScwR&)_q>N@M}&OeftuU& z=a9r+KW7ul+MwaiYD%!r7#I-IR+EQmF3<+lwlhj<_L-=^d?x5GpNT?urN5L#PqfpN zOCKxWAXb0YBI+8VR0WT7HF+S_<3(GCSnxH|5V78GDSCKZ6SG;F)lBLRU2>enSI@S=PYe3;VHa*0Yiir@sh zL89Vj0nr!NLl#ncO3pTEUPdG;PFe+}2N_0_!yExZDN*?zQ%O{IER^#O#@Prx2ICS* zg5sq?1C~itEJqM4iAwuMRC*+?xkSad2KJ`$)+WK5SiwM%sKVA(O7I-()Hd|d1aUOI zUvF9V1E+~y0t|;3e73`cnz8H@x0m|2ySU;}@{w$8ch~0$F-kKxbykyxeeGVG!ZYDg z*E71O*aX>SO}??)Hr$U*94dfytH~w1ESJdyhtG1z8$bXUDlpmoBCh=2*mod1(s4~vvFo@_o4 z*bp~>9&rGKG?qlT_jK4E2nlS063=m4C#3_s$Y2Nz+)_&96CWqJBb1MIZV%>TZFm4o zwQjWQdHH=J8*G#}6SKM)60WzO<2;J4IUNoJhjnwu6(XeoRmjvK8X|^9&`U(^SInHkS3wS2@DcQkJDe!(D@vHJ#E#?&#C~eiN z65nuIMKc3~dJO#P@#7W~PW~2VsSJgmucGSa>rr(zY2tCvS3JRsC1(?%ZAmuBHfs=z zCE^;YJeaoB1q*jQ7YU9r7~O3S-xJ};muMktmkuK5E}Xa&Ik(KNr~F)_C<6Y=j6;W4 zgeYa;1Zj4Hg`|2}`2igjVIj#bTRX744-=buR~AFa=oEdXb(PI6O+MjFR~w{U-wz3bRn%lVf}};dUyb`wqI174BpFu zHBj0dJlx@huyXcokf(2g$FyAvLHC4??1CG+8~hw0p@ZKN8g<|dqFPB$oC0n-1NnM# z^=SNRJ8j?ZH^YpqhABo2AK_Gr9dH(~cJ|(+4`$nl8-C5?CN|M*bd5mqELR}puUL@# zLe@DCpb_6bn=luATl7=GRAV6grgoeLzUmGcz_}ls@GJ8fuqkQHrHzDaMb-#Ty0V_G z@Cx|ha*oJ=$R3xztMEH5BC|L6S=KTC`~XBTo%J{T z>9IFz5l&NX?YUG~=WC`sWVLT^(6~ZDtoNHDY{6$YY}u0uTr}n}OY}ya0lIsonYivYmDxXx}d}>nM9VWXgV@&w*mY%o&DG$(@`5 z`8g%?q3|OQ^y1bb>Lfco%%jOlkPnXWruuf$hb;O=I_eTKG0zbtq^Vg28>+@BXt+7} zcPwY44E86>{ls0)E^y9p3ate7=VIeQ`r zH!>k>3F#=CMJR!M1=_IX5_=noyf(iRiLC?dQ_8%MLRxJ8(fd&r6Bj&37iTn=OKU#MpTdyW!f#R)f}{-3PEtV&_y2 zGa`vyT0xZ9B_X)PPCt^X#FR%{o5W5(Hc%w?w&~$*m(yXuN U0aT1FB#_O$WyhJ{ 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 Date: Wed, 9 Apr 2025 15:10:19 +0200 Subject: [PATCH 13/75] [flutter] Closes #2809, update web_ffi --- spine-flutter/CHANGELOG.md | 3 ++ spine-flutter/compile-wasm.sh | 1 + spine-flutter/example/pubspec.lock | 6 ++-- spine-flutter/lib/assets/libspine_flutter.js | 31 ++++++++++---------- spine-flutter/pubspec.yaml | 4 +-- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/spine-flutter/CHANGELOG.md b/spine-flutter/CHANGELOG.md index cfaa2bb3e..267a5711b 100644 --- a/spine-flutter/CHANGELOG.md +++ b/spine-flutter/CHANGELOG.md @@ -1,3 +1,6 @@ +# 4.2.34 +- Support latest emscripten SDK (4.0.6+) via update of web_ffi + # 4.2.33 - Merge fixes in spine-cpp(-lite) - Prepare for upcoming Dart/Flutter releases, see https://github.com/EsotericSoftware/spine-runtimes/pull/2690 diff --git a/spine-flutter/compile-wasm.sh b/spine-flutter/compile-wasm.sh index 9739a9ab8..e9e220c4f 100755 --- a/spine-flutter/compile-wasm.sh +++ b/spine-flutter/compile-wasm.sh @@ -12,6 +12,7 @@ em++ \ -Isrc/spine-cpp/include \ -O2 --closure 1 -fno-rtti -fno-exceptions \ -s STRICT=1 \ + -s EXPORTED_RUNTIME_METHODS=wasmExports \ -s ERROR_ON_UNDEFINED_SYMBOLS=1 \ -s MODULARIZE=1 \ -s ALLOW_MEMORY_GROWTH=1 \ diff --git a/spine-flutter/example/pubspec.lock b/spine-flutter/example/pubspec.lock index 6410eeb03..92e911f25 100644 --- a/spine-flutter/example/pubspec.lock +++ b/spine-flutter/example/pubspec.lock @@ -169,7 +169,7 @@ packages: path: ".." relative: true source: path - version: "4.2.29" + version: "4.2.34" string_scanner: dependency: transitive description: @@ -206,10 +206,10 @@ packages: dependency: transitive description: name: web_ffi_fork - sha256: "7466228b7fc6a29ee1b5f6ab7ee2473847367a70fb523eb1a7c1d7a6a9841589" + sha256: "557b3008bb3c8547ee63eac6e53c0ebebb443da9d7558b3f1b98e1ed59989a11" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.5" sdks: dart: ">=3.3.0-0 <4.0.0" flutter: ">=3.16.0" diff --git a/spine-flutter/lib/assets/libspine_flutter.js b/spine-flutter/lib/assets/libspine_flutter.js index a52ced31d..179af7fc3 100644 --- a/spine-flutter/lib/assets/libspine_flutter.js +++ b/spine-flutter/lib/assets/libspine_flutter.js @@ -17,20 +17,21 @@ a.setValue=function(c,d,e="i8"){e.endsWith("*")&&(e="*");switch(e){case "i1":z[c var O=(c,d=0,e=NaN)=>{var g=d+e;for(e=d;c[e]&&!(e>=g);)++e;if(16f?g+=String.fromCharCode(f):(f-=65536,g+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else g+=String.fromCharCode(f)}return g};a.UTF8ArrayToString=O;a.UTF8ToString=(c,d)=>c?O(A,c,d):""; var P=(c,d,e,g)=>L(`Assertion failed: ${c?O(A,c,void 0):""}, at: `+[d?d?O(A,d,void 0):"":"unknown filename",e,g?g?O(A,g,void 0):"":"unknown function"]);a.___assert_fail=P;var Q=()=>L("");a.__abort_js=Q;a.getHeapMax=()=>2147483648;a.alignMemory=(c,d)=>Math.ceil(c/d)*d;var R=c=>{c=(c-w.buffer.byteLength+65535)/65536|0;try{return w.grow(c),H(),1}catch(d){}};a.growMemory=R; var S=c=>{var d=A.length;c>>>=0;if(2147483648=e;e*=2){var g=d*(1+.2/e);g=Math.min(g,c+100663296);if(R(Math.min(2147483648,65536*Math.ceil(Math.max(c,g)/65536))))return!0}return!1};a._emscripten_resize_heap=S;var T=[null,[],[]];a.printCharBuffers=T;var U=(c,d)=>{var e=T[c];0===d||10===d?((1===c?ba:v)(O(e)),e.length=0):e.push(d)};a.printChar=U;a.flush_NO_FILESYSTEM=()=>{T[1].length&&U(1,10);T[2].length&&U(2,10)};a.SYSCALLS={h:void 0,g(c){return c?O(A,c,void 0):""}}; -var V=(c,d,e,g)=>{for(var f=0,n=0;n>2],W=D[d+4>>2];d+=8;for(var K=0;K>2]=f;return 0};a._fd_write=V;a.ptrToString=c=>"0x"+(c>>>0).toString(16).padStart(8,"0");var X={__assert_fail:P,_abort_js:Q,emscripten_resize_heap:S,fd_write:V},Y=await (async function(){I++;var c={env:X,wasi_snapshot_preview1:X};M??=q+"libspine_flutter.wasm";try{return Y=(await ea(c)).instance.exports,w=Y.memory,H(),I--,0==I&&J&&(c=J,J=null,c()),Y}catch(d){return h(d),Promise.reject(d)}}()); -a._spine_enable_debug_extension=Y.spine_enable_debug_extension;a._spine_major_version=Y.spine_major_version;a._spine_minor_version=Y.spine_minor_version;a._spine_report_leaks=Y.spine_report_leaks;a._spine_color_get_r=Y.spine_color_get_r;a._spine_color_get_g=Y.spine_color_get_g;a._spine_color_get_b=Y.spine_color_get_b;a._spine_color_get_a=Y.spine_color_get_a;a._spine_bounds_get_x=Y.spine_bounds_get_x;a._spine_bounds_get_y=Y.spine_bounds_get_y;a._spine_bounds_get_width=Y.spine_bounds_get_width; -a._spine_bounds_get_height=Y.spine_bounds_get_height;a._spine_vector_get_x=Y.spine_vector_get_x;a._spine_vector_get_y=Y.spine_vector_get_y;a._spine_atlas_load=Y.spine_atlas_load;a._spine_atlas_load_callback=Y.spine_atlas_load_callback;a._spine_atlas_get_num_image_paths=Y.spine_atlas_get_num_image_paths;a._spine_atlas_is_pma=Y.spine_atlas_is_pma;a._spine_atlas_get_image_path=Y.spine_atlas_get_image_path;a._spine_atlas_get_error=Y.spine_atlas_get_error;a._spine_atlas_dispose=Y.spine_atlas_dispose; -a._free=Y.free;a._spine_skeleton_data_load_json=Y.spine_skeleton_data_load_json;a._spine_skeleton_data_load_binary=Y.spine_skeleton_data_load_binary;a._spine_skeleton_data_result_get_error=Y.spine_skeleton_data_result_get_error;a._spine_skeleton_data_result_get_data=Y.spine_skeleton_data_result_get_data;a._spine_skeleton_data_result_dispose=Y.spine_skeleton_data_result_dispose;a._spine_skeleton_data_find_bone=Y.spine_skeleton_data_find_bone;a._spine_skeleton_data_find_slot=Y.spine_skeleton_data_find_slot; -a._spine_skeleton_data_find_skin=Y.spine_skeleton_data_find_skin;a._spine_skeleton_data_find_event=Y.spine_skeleton_data_find_event;a._spine_skeleton_data_find_animation=Y.spine_skeleton_data_find_animation;a._spine_skeleton_data_find_ik_constraint=Y.spine_skeleton_data_find_ik_constraint;a._spine_skeleton_data_find_transform_constraint=Y.spine_skeleton_data_find_transform_constraint;a._spine_skeleton_data_find_path_constraint=Y.spine_skeleton_data_find_path_constraint; -a._spine_skeleton_data_find_physics_constraint=Y.spine_skeleton_data_find_physics_constraint;a._spine_skeleton_data_get_name=Y.spine_skeleton_data_get_name;a._spine_skeleton_data_get_num_bones=Y.spine_skeleton_data_get_num_bones;a._spine_skeleton_data_get_bones=Y.spine_skeleton_data_get_bones;a._spine_skeleton_data_get_num_slots=Y.spine_skeleton_data_get_num_slots;a._spine_skeleton_data_get_slots=Y.spine_skeleton_data_get_slots;a._spine_skeleton_data_get_num_skins=Y.spine_skeleton_data_get_num_skins; -a._spine_skeleton_data_get_skins=Y.spine_skeleton_data_get_skins;a._spine_skeleton_data_get_default_skin=Y.spine_skeleton_data_get_default_skin;a._spine_skeleton_data_set_default_skin=Y.spine_skeleton_data_set_default_skin;a._spine_skeleton_data_get_num_events=Y.spine_skeleton_data_get_num_events;a._spine_skeleton_data_get_events=Y.spine_skeleton_data_get_events;a._spine_skeleton_data_get_num_animations=Y.spine_skeleton_data_get_num_animations;a._spine_skeleton_data_get_animations=Y.spine_skeleton_data_get_animations; -a._spine_skeleton_data_get_num_ik_constraints=Y.spine_skeleton_data_get_num_ik_constraints;a._spine_skeleton_data_get_ik_constraints=Y.spine_skeleton_data_get_ik_constraints;a._spine_skeleton_data_get_num_transform_constraints=Y.spine_skeleton_data_get_num_transform_constraints;a._spine_skeleton_data_get_transform_constraints=Y.spine_skeleton_data_get_transform_constraints;a._spine_skeleton_data_get_num_path_constraints=Y.spine_skeleton_data_get_num_path_constraints; -a._spine_skeleton_data_get_path_constraints=Y.spine_skeleton_data_get_path_constraints;a._spine_skeleton_data_get_num_physics_constraints=Y.spine_skeleton_data_get_num_physics_constraints;a._spine_skeleton_data_get_physics_constraints=Y.spine_skeleton_data_get_physics_constraints;a._spine_skeleton_data_get_x=Y.spine_skeleton_data_get_x;a._spine_skeleton_data_set_x=Y.spine_skeleton_data_set_x;a._spine_skeleton_data_get_y=Y.spine_skeleton_data_get_y;a._spine_skeleton_data_set_y=Y.spine_skeleton_data_set_y; -a._spine_skeleton_data_get_width=Y.spine_skeleton_data_get_width;a._spine_skeleton_data_set_width=Y.spine_skeleton_data_set_width;a._spine_skeleton_data_get_height=Y.spine_skeleton_data_get_height;a._spine_skeleton_data_set_height=Y.spine_skeleton_data_set_height;a._spine_skeleton_data_get_version=Y.spine_skeleton_data_get_version;a._spine_skeleton_data_get_hash=Y.spine_skeleton_data_get_hash;a._spine_skeleton_data_get_images_path=Y.spine_skeleton_data_get_images_path; -a._spine_skeleton_data_get_audio_path=Y.spine_skeleton_data_get_audio_path;a._spine_skeleton_data_get_fps=Y.spine_skeleton_data_get_fps;a._spine_skeleton_data_get_reference_scale=Y.spine_skeleton_data_get_reference_scale;a._spine_skeleton_data_dispose=Y.spine_skeleton_data_dispose;a._spine_skeleton_drawable_create=Y.spine_skeleton_drawable_create;a._spine_skeleton_drawable_dispose=Y.spine_skeleton_drawable_dispose;a._spine_skeleton_drawable_render=Y.spine_skeleton_drawable_render; -a._spine_skeleton_drawable_get_skeleton=Y.spine_skeleton_drawable_get_skeleton;a._spine_skeleton_drawable_get_animation_state=Y.spine_skeleton_drawable_get_animation_state;a._spine_skeleton_drawable_get_animation_state_data=Y.spine_skeleton_drawable_get_animation_state_data;a._spine_skeleton_drawable_get_animation_state_events=Y.spine_skeleton_drawable_get_animation_state_events;a._spine_render_command_get_positions=Y.spine_render_command_get_positions;a._spine_render_command_get_uvs=Y.spine_render_command_get_uvs; -a._spine_render_command_get_colors=Y.spine_render_command_get_colors;a._spine_render_command_get_dark_colors=Y.spine_render_command_get_dark_colors;a._spine_render_command_get_num_vertices=Y.spine_render_command_get_num_vertices;a._spine_render_command_get_indices=Y.spine_render_command_get_indices;a._spine_render_command_get_num_indices=Y.spine_render_command_get_num_indices;a._spine_render_command_get_atlas_page=Y.spine_render_command_get_atlas_page;a._spine_render_command_get_blend_mode=Y.spine_render_command_get_blend_mode; -a._spine_render_command_get_next=Y.spine_render_command_get_next;a._spine_animation_get_name=Y.spine_animation_get_name;a._spine_animation_get_duration=Y.spine_animation_get_duration;a._spine_animation_state_data_get_skeleton_data=Y.spine_animation_state_data_get_skeleton_data;a._spine_animation_state_data_get_default_mix=Y.spine_animation_state_data_get_default_mix;a._spine_animation_state_data_set_default_mix=Y.spine_animation_state_data_set_default_mix;a._spine_animation_state_data_set_mix=Y.spine_animation_state_data_set_mix; +var V=(c,d,e,g)=>{for(var f=0,n=0;n>2],W=D[d+4>>2];d+=8;for(var K=0;K>2]=f;return 0};a._fd_write=V;a.ptrToString=c=>"0x"+(c>>>0).toString(16).padStart(8,"0"); +var X={__assert_fail:P,_abort_js:Q,emscripten_resize_heap:S,fd_write:V},Y=await (async function(){I++;var c={env:X,wasi_snapshot_preview1:X};M??=q+"libspine_flutter.wasm";try{return Y=(await ea(c)).instance.exports,a.wasmExports=Y,w=Y.memory,H(),I--,0==I&&J&&(c=J,J=null,c()),Y}catch(d){return h(d),Promise.reject(d)}}());a._spine_enable_debug_extension=Y.spine_enable_debug_extension;a._spine_major_version=Y.spine_major_version;a._spine_minor_version=Y.spine_minor_version; +a._spine_report_leaks=Y.spine_report_leaks;a._spine_color_get_r=Y.spine_color_get_r;a._spine_color_get_g=Y.spine_color_get_g;a._spine_color_get_b=Y.spine_color_get_b;a._spine_color_get_a=Y.spine_color_get_a;a._spine_bounds_get_x=Y.spine_bounds_get_x;a._spine_bounds_get_y=Y.spine_bounds_get_y;a._spine_bounds_get_width=Y.spine_bounds_get_width;a._spine_bounds_get_height=Y.spine_bounds_get_height;a._spine_vector_get_x=Y.spine_vector_get_x;a._spine_vector_get_y=Y.spine_vector_get_y; +a._spine_atlas_load=Y.spine_atlas_load;a._spine_atlas_load_callback=Y.spine_atlas_load_callback;a._spine_atlas_get_num_image_paths=Y.spine_atlas_get_num_image_paths;a._spine_atlas_is_pma=Y.spine_atlas_is_pma;a._spine_atlas_get_image_path=Y.spine_atlas_get_image_path;a._spine_atlas_get_error=Y.spine_atlas_get_error;a._spine_atlas_dispose=Y.spine_atlas_dispose;a._free=Y.free;a._spine_skeleton_data_load_json=Y.spine_skeleton_data_load_json;a._spine_skeleton_data_load_binary=Y.spine_skeleton_data_load_binary; +a._spine_skeleton_data_result_get_error=Y.spine_skeleton_data_result_get_error;a._spine_skeleton_data_result_get_data=Y.spine_skeleton_data_result_get_data;a._spine_skeleton_data_result_dispose=Y.spine_skeleton_data_result_dispose;a._spine_skeleton_data_find_bone=Y.spine_skeleton_data_find_bone;a._spine_skeleton_data_find_slot=Y.spine_skeleton_data_find_slot;a._spine_skeleton_data_find_skin=Y.spine_skeleton_data_find_skin;a._spine_skeleton_data_find_event=Y.spine_skeleton_data_find_event; +a._spine_skeleton_data_find_animation=Y.spine_skeleton_data_find_animation;a._spine_skeleton_data_find_ik_constraint=Y.spine_skeleton_data_find_ik_constraint;a._spine_skeleton_data_find_transform_constraint=Y.spine_skeleton_data_find_transform_constraint;a._spine_skeleton_data_find_path_constraint=Y.spine_skeleton_data_find_path_constraint;a._spine_skeleton_data_find_physics_constraint=Y.spine_skeleton_data_find_physics_constraint;a._spine_skeleton_data_get_name=Y.spine_skeleton_data_get_name; +a._spine_skeleton_data_get_num_bones=Y.spine_skeleton_data_get_num_bones;a._spine_skeleton_data_get_bones=Y.spine_skeleton_data_get_bones;a._spine_skeleton_data_get_num_slots=Y.spine_skeleton_data_get_num_slots;a._spine_skeleton_data_get_slots=Y.spine_skeleton_data_get_slots;a._spine_skeleton_data_get_num_skins=Y.spine_skeleton_data_get_num_skins;a._spine_skeleton_data_get_skins=Y.spine_skeleton_data_get_skins;a._spine_skeleton_data_get_default_skin=Y.spine_skeleton_data_get_default_skin; +a._spine_skeleton_data_set_default_skin=Y.spine_skeleton_data_set_default_skin;a._spine_skeleton_data_get_num_events=Y.spine_skeleton_data_get_num_events;a._spine_skeleton_data_get_events=Y.spine_skeleton_data_get_events;a._spine_skeleton_data_get_num_animations=Y.spine_skeleton_data_get_num_animations;a._spine_skeleton_data_get_animations=Y.spine_skeleton_data_get_animations;a._spine_skeleton_data_get_num_ik_constraints=Y.spine_skeleton_data_get_num_ik_constraints; +a._spine_skeleton_data_get_ik_constraints=Y.spine_skeleton_data_get_ik_constraints;a._spine_skeleton_data_get_num_transform_constraints=Y.spine_skeleton_data_get_num_transform_constraints;a._spine_skeleton_data_get_transform_constraints=Y.spine_skeleton_data_get_transform_constraints;a._spine_skeleton_data_get_num_path_constraints=Y.spine_skeleton_data_get_num_path_constraints;a._spine_skeleton_data_get_path_constraints=Y.spine_skeleton_data_get_path_constraints; +a._spine_skeleton_data_get_num_physics_constraints=Y.spine_skeleton_data_get_num_physics_constraints;a._spine_skeleton_data_get_physics_constraints=Y.spine_skeleton_data_get_physics_constraints;a._spine_skeleton_data_get_x=Y.spine_skeleton_data_get_x;a._spine_skeleton_data_set_x=Y.spine_skeleton_data_set_x;a._spine_skeleton_data_get_y=Y.spine_skeleton_data_get_y;a._spine_skeleton_data_set_y=Y.spine_skeleton_data_set_y;a._spine_skeleton_data_get_width=Y.spine_skeleton_data_get_width; +a._spine_skeleton_data_set_width=Y.spine_skeleton_data_set_width;a._spine_skeleton_data_get_height=Y.spine_skeleton_data_get_height;a._spine_skeleton_data_set_height=Y.spine_skeleton_data_set_height;a._spine_skeleton_data_get_version=Y.spine_skeleton_data_get_version;a._spine_skeleton_data_get_hash=Y.spine_skeleton_data_get_hash;a._spine_skeleton_data_get_images_path=Y.spine_skeleton_data_get_images_path;a._spine_skeleton_data_get_audio_path=Y.spine_skeleton_data_get_audio_path; +a._spine_skeleton_data_get_fps=Y.spine_skeleton_data_get_fps;a._spine_skeleton_data_get_reference_scale=Y.spine_skeleton_data_get_reference_scale;a._spine_skeleton_data_dispose=Y.spine_skeleton_data_dispose;a._spine_skeleton_drawable_create=Y.spine_skeleton_drawable_create;a._spine_skeleton_drawable_dispose=Y.spine_skeleton_drawable_dispose;a._spine_skeleton_drawable_render=Y.spine_skeleton_drawable_render;a._spine_skeleton_drawable_get_skeleton=Y.spine_skeleton_drawable_get_skeleton; +a._spine_skeleton_drawable_get_animation_state=Y.spine_skeleton_drawable_get_animation_state;a._spine_skeleton_drawable_get_animation_state_data=Y.spine_skeleton_drawable_get_animation_state_data;a._spine_skeleton_drawable_get_animation_state_events=Y.spine_skeleton_drawable_get_animation_state_events;a._spine_render_command_get_positions=Y.spine_render_command_get_positions;a._spine_render_command_get_uvs=Y.spine_render_command_get_uvs;a._spine_render_command_get_colors=Y.spine_render_command_get_colors; +a._spine_render_command_get_dark_colors=Y.spine_render_command_get_dark_colors;a._spine_render_command_get_num_vertices=Y.spine_render_command_get_num_vertices;a._spine_render_command_get_indices=Y.spine_render_command_get_indices;a._spine_render_command_get_num_indices=Y.spine_render_command_get_num_indices;a._spine_render_command_get_atlas_page=Y.spine_render_command_get_atlas_page;a._spine_render_command_get_blend_mode=Y.spine_render_command_get_blend_mode;a._spine_render_command_get_next=Y.spine_render_command_get_next; +a._spine_animation_get_name=Y.spine_animation_get_name;a._spine_animation_get_duration=Y.spine_animation_get_duration;a._spine_animation_state_data_get_skeleton_data=Y.spine_animation_state_data_get_skeleton_data;a._spine_animation_state_data_get_default_mix=Y.spine_animation_state_data_get_default_mix;a._spine_animation_state_data_set_default_mix=Y.spine_animation_state_data_set_default_mix;a._spine_animation_state_data_set_mix=Y.spine_animation_state_data_set_mix; a._spine_animation_state_data_get_mix=Y.spine_animation_state_data_get_mix;a._spine_animation_state_data_set_mix_by_name=Y.spine_animation_state_data_set_mix_by_name;a._spine_animation_state_data_get_mix_by_name=Y.spine_animation_state_data_get_mix_by_name;a._spine_animation_state_data_clear=Y.spine_animation_state_data_clear;a._spine_animation_state_update=Y.spine_animation_state_update;a._spine_animation_state_dispose_track_entry=Y.spine_animation_state_dispose_track_entry; a._spine_animation_state_apply=Y.spine_animation_state_apply;a._spine_animation_state_clear_tracks=Y.spine_animation_state_clear_tracks;a._spine_animation_state_get_num_tracks=Y.spine_animation_state_get_num_tracks;a._spine_animation_state_clear_track=Y.spine_animation_state_clear_track;a._spine_animation_state_set_animation_by_name=Y.spine_animation_state_set_animation_by_name;a._spine_animation_state_set_animation=Y.spine_animation_state_set_animation; a._spine_animation_state_add_animation_by_name=Y.spine_animation_state_add_animation_by_name;a._spine_animation_state_add_animation=Y.spine_animation_state_add_animation;a._spine_animation_state_set_empty_animation=Y.spine_animation_state_set_empty_animation;a._spine_animation_state_add_empty_animation=Y.spine_animation_state_add_empty_animation;a._spine_animation_state_set_empty_animations=Y.spine_animation_state_set_empty_animations;a._spine_animation_state_get_current=Y.spine_animation_state_get_current; @@ -128,7 +129,7 @@ a._spine_texture_region_get_offset_y=Y.spine_texture_region_get_offset_y;a._spin a._spine_texture_region_set_original_width=Y.spine_texture_region_set_original_width;a._spine_texture_region_get_original_height=Y.spine_texture_region_get_original_height;a._spine_texture_region_set_original_height=Y.spine_texture_region_set_original_height;a._spine_skeleton_bounds_create=Y.spine_skeleton_bounds_create;a._spine_skeleton_bounds_dispose=Y.spine_skeleton_bounds_dispose;a._spine_skeleton_bounds_update=Y.spine_skeleton_bounds_update;a._spine_skeleton_bounds_aabb_contains_point=Y.spine_skeleton_bounds_aabb_contains_point; a._spine_skeleton_bounds_aabb_intersects_segment=Y.spine_skeleton_bounds_aabb_intersects_segment;a._spine_skeleton_bounds_aabb_intersects_skeleton=Y.spine_skeleton_bounds_aabb_intersects_skeleton;a._spine_skeleton_bounds_contains_point=Y.spine_skeleton_bounds_contains_point;a._spine_skeleton_bounds_contains_point_attachment=Y.spine_skeleton_bounds_contains_point_attachment;a._spine_skeleton_bounds_intersects_segment_attachment=Y.spine_skeleton_bounds_intersects_segment_attachment; a._spine_skeleton_bounds_intersects_segment=Y.spine_skeleton_bounds_intersects_segment;a._spine_skeleton_bounds_get_polygon=Y.spine_skeleton_bounds_get_polygon;a._spine_skeleton_bounds_get_bounding_box=Y.spine_skeleton_bounds_get_bounding_box;a._spine_skeleton_bounds_get_num_polygons=Y.spine_skeleton_bounds_get_num_polygons;a._spine_skeleton_bounds_get_polygons=Y.spine_skeleton_bounds_get_polygons;a._spine_skeleton_bounds_get_num_bounding_boxes=Y.spine_skeleton_bounds_get_num_bounding_boxes; -a._spine_skeleton_bounds_get_bounding_boxes=Y.spine_skeleton_bounds_get_bounding_boxes;a._spine_skeleton_bounds_get_width=Y.spine_skeleton_bounds_get_width;a._spine_skeleton_bounds_get_height=Y.spine_skeleton_bounds_get_height;a._spine_polygon_get_num_vertices=Y.spine_polygon_get_num_vertices;a._spine_polygon_get_vertices=Y.spine_polygon_get_vertices;a._malloc=Y.malloc;var ha=Y._emscripten_stack_restore,ia=Y.emscripten_stack_get_current; +a._spine_skeleton_bounds_get_bounding_boxes=Y.spine_skeleton_bounds_get_bounding_boxes;a._spine_skeleton_bounds_get_width=Y.spine_skeleton_bounds_get_width;a._spine_skeleton_bounds_get_height=Y.spine_skeleton_bounds_get_height;a._spine_polygon_get_num_vertices=Y.spine_polygon_get_num_vertices;a._spine_polygon_get_vertices=Y.spine_polygon_get_vertices;a._malloc=Y.malloc;var ha=Y._emscripten_stack_restore,ia=Y.emscripten_stack_get_current;a.wasmExports=Y; function Z(){0 Date: Wed, 9 Apr 2025 09:13:39 -0400 Subject: [PATCH 14/75] [c][cpp] Port of commit f1e0f0f (#2807) * [c][cpp] Port of commit f1e0f0f: Fixed animation not being mixed out in some cases. #2786 * [c][cpp] Format. --------- Co-authored-by: Davide Tantillo --- spine-c/spine-c/src/spine/AnimationState.c | 20 +++++++++---------- .../spine-cpp/src/spine/AnimationState.cpp | 20 +++++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 97c7fc00d..5ece11b22 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -350,18 +350,16 @@ int /*boolean*/ _spAnimationState_updateMixingFrom(spAnimationState *self, spTra from->animationLast = from->nextAnimationLast; from->trackLast = from->nextTrackLast; - if (to->nextTrackLast != -1) { // The from entry was applied at least once. - int discard = to->mixTime == 0 && from->mixTime == 0;// Discard the from entry when neither have advanced yet. - if (to->mixTime >= to->mixDuration || discard) { - // Require totalAlpha == 0 to ensure mixing is complete or the transition is a single frame or discarded. - if (from->totalAlpha == 0 || to->mixDuration == 0 || discard) { - to->mixingFrom = from->mixingFrom; - if (from->mixingFrom) from->mixingFrom->mixingTo = to; - to->interruptAlpha = from->interruptAlpha; - _spEventQueue_end(internal->queue, from); - } - return finished; + // The from entry was applied at least once and the mix is complete. + if (to->nextTrackLast != -1 && to->mixTime >= to->mixDuration) { + // Mixing is complete for all entries before the from entry or the mix is instantaneous. + if (from->totalAlpha == 0 || to->mixDuration == 0) { + to->mixingFrom = from->mixingFrom; + if (from->mixingFrom) from->mixingFrom->mixingTo = to; + to->interruptAlpha = from->interruptAlpha; + _spEventQueue_end(internal->queue, from); } + return finished; } from->trackTime += delta * from->timeScale; diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 1ffb12ddd..a00c63ce9 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -794,18 +794,16 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) { from->_animationLast = from->_nextAnimationLast; from->_trackLast = from->_nextTrackLast; - if (to->_nextTrackLast != -1) { // The from entry was applied at least once. - bool discard = to->_mixTime == 0 && from->_mixTime == 0;// Discard the from entry when neither have advanced yet. - if (to->_mixTime >= to->_mixDuration || discard) { - // Require totalAlpha == 0 to ensure mixing is complete or the transition is a single frame or discarded. - if (from->_totalAlpha == 0 || to->_mixDuration == 0 || discard) { - to->_mixingFrom = from->_mixingFrom; - if (from->_mixingFrom) from->_mixingFrom->_mixingTo = to; - to->_interruptAlpha = from->_interruptAlpha; - _queue->end(from); - } - return finished; + // The from entry was applied at least once and the mix is complete. + if (to->_nextTrackLast != -1 && to->_mixTime >= to->_mixDuration) { + // Mixing is complete for all entries before the from entry or the mix is instantaneous. + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { + to->_mixingFrom = from->_mixingFrom; + if (from->_mixingFrom) from->_mixingFrom->_mixingTo = to; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); } + return finished; } from->_trackTime += delta * from->_timeScale; From cb28aeeedc202acd87c56987a97074562dc38339 Mon Sep 17 00:00:00 2001 From: Davide Tantillo Date: Wed, 9 Apr 2025 15:57:55 +0200 Subject: [PATCH 15/75] [flutter] Port of commit f1e0f0f: Fixed animation not being mixed out in some cases. --- spine-flutter/CHANGELOG.md | 3 +++ .../lib/assets/libspine_flutter.wasm | Bin 409435 -> 409402 bytes spine-flutter/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/spine-flutter/CHANGELOG.md b/spine-flutter/CHANGELOG.md index 267a5711b..28a8b3e04 100644 --- a/spine-flutter/CHANGELOG.md +++ b/spine-flutter/CHANGELOG.md @@ -1,3 +1,6 @@ +# 4.2.35 + - Port of commit f1e0f0f: Fixed animation not being mixed out in some cases. + # 4.2.34 - Support latest emscripten SDK (4.0.6+) via update of web_ffi diff --git a/spine-flutter/lib/assets/libspine_flutter.wasm b/spine-flutter/lib/assets/libspine_flutter.wasm index 8645b6ddc051e0cd5753549e52ef655a7513b8e1..fa3877811b413184306a2534ab813c39c58222c2 100755 GIT binary patch delta 164 zcmccpPh!_Ui495>jJukZE83MS7=f4xh?%!5SFoH*R5-%O#9Yr*tH7wiB%{Ra%HrV2 z$j`07punuaBygWik!8BzEfzCRS6&7Mc4r14h+%P1VAf(PfpB=4xD^-`m_d43&6s2q zSb?&v3XEn<3Se<9rUDD50tE&QCJzN>fh%kZEYmmMVo_pY;Z|U2zkZ8l`}JF_Ehzw! C!Xy6x delta 197 zcmdn>PvZ7Ji495>jJKPWE83MS7=f4xh?%!5SFoH*RCvnB#9Yr*tH7wiB%{Ra%HrV2 z$j`07punuaBygWik#)M@Ef%vZ1vX~}Ac$e9cVu8yVAf*F0P~}{l~{^gc^MSgAzYA5 z34~dsz*6MMSm?^jsKBVe3^JU>j7dg;g~dUEMS; Date: Thu, 10 Apr 2025 17:26:35 +0800 Subject: [PATCH 16/75] Update CMakeLists.txt (#2811) --- spine-glfw/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-glfw/CMakeLists.txt b/spine-glfw/CMakeLists.txt index 9f1a99c8e..8ff02a105 100644 --- a/spine-glfw/CMakeLists.txt +++ b/spine-glfw/CMakeLists.txt @@ -19,7 +19,7 @@ set(GLFW_INSTALL OFF CACHE BOOL " " FORCE) FetchContent_Declare( glbinding GIT_REPOSITORY https://github.com/cginternals/glbinding.git - GIT_TAG v3.3.0 + GIT_TAG v3.4.0 GIT_SHALLOW 1 ) FetchContent_MakeAvailable(glbinding) @@ -65,4 +65,4 @@ set_property(TARGET spine-glfw-example-cpp-lite PROPERTY VS_DEBUGGER_WORKING_DIR # copy data to build directory add_custom_command(TARGET spine-glfw-example PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory - ${CMAKE_CURRENT_LIST_DIR}/data $/data) \ No newline at end of file + ${CMAKE_CURRENT_LIST_DIR}/data $/data) From 88230582c2f033869814334fb29b5811b034c0c9 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Thu, 10 Apr 2025 18:27:24 +0900 Subject: [PATCH 17/75] [iOS] merge shader header and disable cpp-interp in example project (#2808) * [iOS] disable objc-interp in example project & reuse struct header inside shader * [iOS] support sharing Shader Header on both cocoapods and SPM --- Spine.podspec | 3 +- .../project.pbxproj | 4 +-- .../Sources/Spine/Metal/SpineShaders.metal | 30 ++++++------------- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/Spine.podspec b/Spine.podspec index 8c67181ad..396a18711 100644 --- a/Spine.podspec +++ b/Spine.podspec @@ -18,7 +18,8 @@ Spine runtimes for iOS. s.platform = :ios, '13.0' s.xcconfig = { - 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp/include" "$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp-lite"' + 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp/include" "$(PODS_ROOT)/SpineCppLite/spine-cpp/spine-cpp-lite"', + 'MTL_HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/SpineShadersStructs"' } s.resource_bundles = { diff --git a/spine-ios/Example/Spine iOS Example.xcodeproj/project.pbxproj b/spine-ios/Example/Spine iOS Example.xcodeproj/project.pbxproj index d73405880..7ecf1f5ad 100644 --- a/spine-ios/Example/Spine iOS Example.xcodeproj/project.pbxproj +++ b/spine-ios/Example/Spine iOS Example.xcodeproj/project.pbxproj @@ -462,7 +462,7 @@ SUPPORTS_MACCATALYST = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "Spine iOS Example/Spine iOS Example-Bridging-Header.h"; - SWIFT_OBJC_INTEROP_MODE = objcxx; + SWIFT_OBJC_INTEROP_MODE = objc; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -506,7 +506,7 @@ SUPPORTS_MACCATALYST = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "Spine iOS Example/Spine iOS Example-Bridging-Header.h"; - SWIFT_OBJC_INTEROP_MODE = objcxx; + SWIFT_OBJC_INTEROP_MODE = objc; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/spine-ios/Sources/Spine/Metal/SpineShaders.metal b/spine-ios/Sources/Spine/Metal/SpineShaders.metal index 559077087..964c7f521 100644 --- a/spine-ios/Sources/Spine/Metal/SpineShaders.metal +++ b/spine-ios/Sources/Spine/Metal/SpineShaders.metal @@ -2,27 +2,15 @@ #include using namespace metal; -typedef enum SpineVertexInputIndex { - SpineVertexInputIndexVertices = 0, - SpineVertexInputIndexTransform = 1, - SpineVertexInputIndexViewportSize = 2, -} SpineVertexInputIndex; - -typedef enum SpineTextureIndex { - SpineTextureIndexBaseColor = 0, -} SpineTextureIndex; - -typedef struct { - simd_float2 position; - simd_float4 color; - simd_float2 uv; -} SpineVertex; - -typedef struct { - simd_float2 translation; - simd_float2 scale; - simd_float2 offset; -} SpineTransform; +#if __has_include("spine-ios/Sources/SpineShadersStructs/SpineShadersStructs.h") +// Cocoapods Target + #include "spine-ios/Sources/SpineShadersStructs/SpineShadersStructs.h" +#elif __has_include("../../SpineShadersStructs/SpineShadersStructs.h") +// Swift Package target + #include "../../SpineShadersStructs/SpineShadersStructs.h" +#else + #error "Header not found. Please correct Header search path" +#endif struct RasterizerData { simd_float4 position [[position]]; From f04382bacde56c5cd23ebb5c524b093136e6fa22 Mon Sep 17 00:00:00 2001 From: Byeong Gwan Date: Thu, 10 Apr 2025 18:28:34 +0900 Subject: [PATCH 18/75] expose multiplatform spine-engine target (#2806) --- Package.swift | 23 +++++++++++++++++-- .../Sources/SpineModule/SpineModule.swift | 14 +++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 spine-ios/Sources/SpineModule/SpineModule.swift diff --git a/Package.swift b/Package.swift index a559c8a36..5b2d78785 100644 --- a/Package.swift +++ b/Package.swift @@ -6,16 +6,35 @@ import PackageDescription let package = Package( name: "spine-ios", platforms: [ - .iOS(.v13) + .iOS(.v13), + .tvOS(.v13), + .macCatalyst(.v13), + .visionOS(.v1), + .macOS(.v10_15), + .watchOS(.v6), ], products: [ // Products define the executables and libraries a package produces, making them visible to other packages. .library( name: "Spine", - targets: ["Spine"] + targets: ["SpineModule"] ) ], targets: [ + .target( + name: "SpineModule", + dependencies: [ + .byName( + name: "Spine", + condition: .when(platforms: [ + .iOS, + ]) + ), + "SpineCppLite", + "SpineShadersStructs", + ], + path: "spine-ios/Sources/SpineModule" + ), .target( name: "Spine", dependencies: [ diff --git a/spine-ios/Sources/SpineModule/SpineModule.swift b/spine-ios/Sources/SpineModule/SpineModule.swift new file mode 100644 index 000000000..482e50223 --- /dev/null +++ b/spine-ios/Sources/SpineModule/SpineModule.swift @@ -0,0 +1,14 @@ +// +// SpineModule.swift +// spine-ios +// +// Created by 박병관 on 3/7/25. +// + + +#if canImport(Spine) +@_exported import Spine +#endif + +@_exported import SpineCppLite +@_exported import SpineShadersStructs From c5c71da28cef12fcb0830b96923ad0b401b82e03 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 10 Apr 2025 11:31:25 +0200 Subject: [PATCH 19/75] [godot] Fix 3.5 build --- spine-godot/spine_godot/SpineEditorPlugin.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spine-godot/spine_godot/SpineEditorPlugin.h b/spine-godot/spine_godot/SpineEditorPlugin.h index 54a2592f7..56e7510b0 100644 --- a/spine-godot/spine_godot/SpineEditorPlugin.h +++ b/spine-godot/spine_godot/SpineEditorPlugin.h @@ -290,11 +290,14 @@ public: #else explicit SpineEditorPlugin(EditorNode *node); +#if VERSION_MAJOR > 3 #if VERSION_MINOR > 3 String get_plugin_name() const override { return "SpineEditorPlugin"; } #else String get_name() const override { return "SpineEditorPlugin"; } #endif +#else + String get_name() const override { return "SpineEditorPlugin"; } #endif }; From cd63b83fe4427be6925e882fb11f59652319bacf Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 10 Apr 2025 11:33:12 +0200 Subject: [PATCH 20/75] [godot] Add Godot 4.4 to build matrix --- .github/workflows/spine-godot-v4-all.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/spine-godot-v4-all.yml b/.github/workflows/spine-godot-v4-all.yml index cb10cc40a..64ca66cee 100644 --- a/.github/workflows/spine-godot-v4-all.yml +++ b/.github/workflows/spine-godot-v4-all.yml @@ -14,10 +14,10 @@ jobs: matrix: version: [ + {"tag": "4.4.1-stable", "version": "4.4.1.stable", "mono": false}, + {"tag": "4.4.1-stable", "version": "4.4.1.stable", "mono": true}, {"tag": "4.3-stable", "version": "4.3.stable", "mono": false}, {"tag": "4.3-stable", "version": "4.3.stable", "mono": true}, - {"tag": "4.2.2-stable", "version": "4.2.2.stable", "mono": false}, - {"tag": "4.2.2-stable", "version": "4.2.2.stable", "mono": true}, ] uses: ./.github/workflows/spine-godot-v4.yml with: From f4ba6a9346cfcced75b315fa694eb2ea456581f8 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 10 Apr 2025 11:34:59 +0200 Subject: [PATCH 21/75] [godot] Add 4.4 to extension build matrix --- .github/workflows/spine-godot-extension-v4-all.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spine-godot-extension-v4-all.yml b/.github/workflows/spine-godot-extension-v4-all.yml index 5eab10096..b17f436be 100644 --- a/.github/workflows/spine-godot-extension-v4-all.yml +++ b/.github/workflows/spine-godot-extension-v4-all.yml @@ -14,8 +14,8 @@ jobs: matrix: version: [ + {"tag": "4.4.1-stable", "version": "4.4.1.stable", "dev": false}, {"tag": "4.3-stable", "version": "4.3.stable", "dev": false}, - {"tag": "4.2.2-stable", "version": "4.2.2.stable", "dev": false}, ] uses: ./.github/workflows/spine-godot-extension-v4.yml with: From fa30e51232c697599b05887c0e6de53c18c2616e Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 10 Apr 2025 12:03:27 +0200 Subject: [PATCH 22/75] [godot] Fix preprocessor constructs --- spine-godot/spine_godot/SpineEditorPlugin.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/spine-godot/spine_godot/SpineEditorPlugin.h b/spine-godot/spine_godot/SpineEditorPlugin.h index 56e7510b0..269fe411b 100644 --- a/spine-godot/spine_godot/SpineEditorPlugin.h +++ b/spine-godot/spine_godot/SpineEditorPlugin.h @@ -290,14 +290,11 @@ public: #else explicit SpineEditorPlugin(EditorNode *node); -#if VERSION_MAJOR > 3 -#if VERSION_MINOR > 3 - String get_plugin_name() const override { return "SpineEditorPlugin"; } +#if VERSION_MAJOR > 3 && VERSION_MINOR > 3 + String get_plugin_name() const override { return "SpineEditorPlugin"; } #else - String get_name() const override { return "SpineEditorPlugin"; } + String get_name() const override { return "SpineEditorPlugin"; } #endif -#else - String get_name() const override { return "SpineEditorPlugin"; } #endif }; From 3cc43389b9cfd1c2e258fb65518ed9172bc791fe Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 10 Apr 2025 12:07:08 +0200 Subject: [PATCH 23/75] Formatting --- spine-godot/spine_godot/SpineEditorPlugin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spine-godot/spine_godot/SpineEditorPlugin.h b/spine-godot/spine_godot/SpineEditorPlugin.h index 269fe411b..268c149ee 100644 --- a/spine-godot/spine_godot/SpineEditorPlugin.h +++ b/spine-godot/spine_godot/SpineEditorPlugin.h @@ -291,9 +291,9 @@ public: explicit SpineEditorPlugin(EditorNode *node); #if VERSION_MAJOR > 3 && VERSION_MINOR > 3 - String get_plugin_name() const override { return "SpineEditorPlugin"; } + String get_plugin_name() const override { return "SpineEditorPlugin"; } #else - String get_name() const override { return "SpineEditorPlugin"; } + String get_name() const override { return "SpineEditorPlugin"; } #endif #endif }; From 71ef2d5f986080c106cd5263bde792345d847ba4 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Sat, 12 Apr 2025 20:14:28 -0400 Subject: [PATCH 24/75] [libgdx] Separate pose and applied for bones, slots, and constraints, sliders WIP. --- .../esotericsoftware/spine/BonePlotting.java | 4 +- .../esotericsoftware/spine/Box2DExample.java | 9 +- .../spine/EventTimelineTests.java | 8 +- .../com/esotericsoftware/spine/IKTest.java | 2 +- .../esotericsoftware/spine/NormalMapTest.java | 2 +- .../esotericsoftware/spine/PngExportTest.java | 2 +- .../spine/SkeletonAttachmentTest.java | 4 +- .../spine/TimelineApiTest.java | 15 +- .../com/esotericsoftware/spine/Animation.java | 153 ++++-- .../spine/AnimationState.java | 14 +- .../src/com/esotericsoftware/spine/Bone.java | 458 +----------------- .../esotericsoftware/spine/BoneApplied.java | 372 ++++++++++++++ .../src/com/esotericsoftware/spine/Event.java | 2 +- .../esotericsoftware/spine/IkConstraint.java | 96 ++-- .../spine/PathConstraint.java | 30 +- .../spine/PhysicsConstraint.java | 26 +- .../com/esotericsoftware/spine/Skeleton.java | 204 +++++--- .../esotericsoftware/spine/SkeletonData.java | 20 + .../spine/SkeletonRendererDebug.java | 21 +- .../com/esotericsoftware/spine/Slider.java | 100 ++++ .../esotericsoftware/spine/SliderData.java | 66 +++ .../src/com/esotericsoftware/spine/Slot.java | 35 +- .../spine/TransformConstraint.java | 32 +- .../spine/TransformConstraintData.java | 68 +-- .../spine/attachments/PointAttachment.java | 6 +- .../spine/attachments/RegionAttachment.java | 3 +- .../spine/attachments/VertexAttachment.java | 7 +- .../spine/utils/SkeletonClipping.java | 4 +- 28 files changed, 1044 insertions(+), 719 deletions(-) create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java index 14b853775..f642a6a93 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java @@ -76,14 +76,14 @@ public class BonePlotting { SkeletonData skeletonData = json.readSkeletonData(new FileHandle("assets/spineboy/spineboy-ess.json")); Skeleton skeleton = new Skeleton(skeletonData); - Bone bone = skeleton.findBone("gun-tip"); + BoneApplied bone = skeleton.findBone("gun-tip").getApplied(); // Pose the skeleton at regular intervals throughout each animation. float fps = 1 / 15f; for (Animation animation : skeletonData.getAnimations()) { float time = 0; while (time < animation.getDuration()) { - animation.apply(skeleton, time, time, false, null, 1, MixBlend.first, MixDirection.in); + animation.apply(skeleton, time, time, false, null, 1, MixBlend.first, MixDirection.in, false); skeleton.update(fps); skeleton.updateWorldTransform(Physics.update); diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java index 41fc02a61..c1f174745 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java @@ -149,7 +149,7 @@ public class Box2DExample extends ApplicationAdapter { batch.setTransformMatrix(camera.view); batch.begin(); - animation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in); + animation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in, false); skeleton.x += 8 * delta; skeleton.update(delta); skeleton.updateWorldTransform(Physics.update); @@ -162,9 +162,10 @@ public class Box2DExample extends ApplicationAdapter { if (!(slot.getAttachment() instanceof Box2dAttachment)) continue; Box2dAttachment attachment = (Box2dAttachment)slot.getAttachment(); if (attachment.body == null) continue; - float x = slot.getBone().getWorldX(); - float y = slot.getBone().getWorldY(); - float rotation = slot.getBone().getWorldRotationX(); + BoneApplied bone = slot.getBone().getApplied(); + float x = bone.getWorldX(); + float y = bone.getWorldY(); + float rotation = bone.getWorldRotationX(); attachment.body.setTransform(x, y, rotation * MathUtils.degRad); } diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/EventTimelineTests.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/EventTimelineTests.java index a1ae90cfb..433c98187 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/EventTimelineTests.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/EventTimelineTests.java @@ -177,7 +177,7 @@ public class EventTimelineTests { int beforeCount = firedEvents.size; Array original = new Array(firedEvents); - timeline.apply(skeleton, lastTimeLooped, timeLooped, firedEvents, 1, MixBlend.first, MixDirection.in); + timeline.apply(skeleton, lastTimeLooped, timeLooped, firedEvents, 1, MixBlend.first, MixDirection.in, false); while (beforeCount < firedEvents.size) { char fired = firedEvents.get(beforeCount).getData().getName().charAt(0); @@ -186,7 +186,7 @@ public class EventTimelineTests { } else { if (firedEvents.size > eventsCount) { if (print) System.out.println(lastTimeLooped + "->" + timeLooped + ": " + fired + " == ?"); - timeline.apply(skeleton, lastTimeLooped, timeLooped, original, 1, MixBlend.first, MixDirection.in); + timeline.apply(skeleton, lastTimeLooped, timeLooped, original, 1, MixBlend.first, MixDirection.in, false); fail("Too many events fired."); } } @@ -194,7 +194,7 @@ public class EventTimelineTests { System.out.println(lastTimeLooped + "->" + timeLooped + ": " + fired + " == " + events[eventIndex]); } if (fired != events[eventIndex]) { - timeline.apply(skeleton, lastTimeLooped, timeLooped, original, 1, MixBlend.first, MixDirection.in); + timeline.apply(skeleton, lastTimeLooped, timeLooped, original, 1, MixBlend.first, MixDirection.in, false); fail("Wrong event fired."); } eventIndex++; @@ -206,7 +206,7 @@ public class EventTimelineTests { i++; } if (firedEvents.size < eventsCount) { - timeline.apply(skeleton, lastTimeLooped, timeLooped, firedEvents, 1, MixBlend.first, MixDirection.in); + timeline.apply(skeleton, lastTimeLooped, timeLooped, firedEvents, 1, MixBlend.first, MixDirection.in, false); if (print) System.out.println(firedEvents); fail("Event not fired: " + events[eventIndex] + ", " + frames[eventIndex]); } diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java index 57b6857a7..2c7a04ff3 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java @@ -107,7 +107,7 @@ public class IKTest extends ApplicationAdapter { Bone crosshair = skeleton.findBone("crosshair"); // Should be cached. boneCoords.set(cameraCoords.x, cameraCoords.y); - crosshair.getParent().worldToLocal(boneCoords); // camera space to local bone space + crosshair.getParent().getApplied().worldToLocal(boneCoords); // camera space to local bone space crosshair.setPosition(boneCoords.x, boneCoords.y); // override the crosshair position // Calculate final world transform with the crosshair bone set to the mouse cursor position. Update physics this time. diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java index 2b6b51926..031269d75 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java @@ -137,7 +137,7 @@ public class NormalMapTest extends ApplicationAdapter { float lastTime = time; float delta = Gdx.graphics.getDeltaTime(); time += delta; - if (animation != null) animation.apply(skeleton, lastTime, time, true, null, 1, MixBlend.first, MixDirection.in); + if (animation != null) animation.apply(skeleton, lastTime, time, true, null, 1, MixBlend.first, MixDirection.in, false); skeleton.update(delta); skeleton.updateWorldTransform(Physics.update); diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java index 3842c5a2d..72f9276f8 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java @@ -104,7 +104,7 @@ public class PngExportTest extends ApplicationAdapter { float fps = 1 / 15f, time = 0; int frame = 1; while (time < animation.getDuration()) { - animation.apply(skeleton, time, time, false, null, 1, MixBlend.first, MixDirection.in); + animation.apply(skeleton, time, time, false, null, 1, MixBlend.first, MixDirection.in, false); skeleton.update(fps); skeleton.updateWorldTransform(Physics.update); diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java index 29948653c..0ed28cce7 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java @@ -48,7 +48,7 @@ public class SkeletonAttachmentTest extends ApplicationAdapter { Skeleton spineboy, goblin; AnimationState spineboyState, goblinState; - Bone attachmentBone; + BoneApplied attachmentBone; public void create () { camera = new OrthographicCamera(); @@ -87,7 +87,7 @@ public class SkeletonAttachmentTest extends ApplicationAdapter { skeletonAttachment.setSkeleton(goblin); Slot slot = spineboy.findSlot("front-upper-arm"); slot.setAttachment(skeletonAttachment); - attachmentBone = slot.getBone(); + attachmentBone = slot.getBone().getApplied(); } } diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java index 400c8ff17..4681c65f3 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java @@ -109,23 +109,24 @@ public class TimelineApiTest extends ApplicationAdapter { skeleton.setX(-50); } else if (time > beforeJump + jump) { // just walk after jump - walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in); + walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in, false); } else if (time > blendOutStart) { // blend out jump - walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in); + walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in, false); jumpAnimation.apply(skeleton, time - beforeJump, time - beforeJump, false, events, 1 - (time - blendOutStart) / blendOut, - MixBlend.first, MixDirection.in); + MixBlend.first, MixDirection.in, false); } else if (time > beforeJump + blendIn) { // just jump - jumpAnimation.apply(skeleton, time - beforeJump, time - beforeJump, false, events, 1, MixBlend.first, MixDirection.in); + jumpAnimation.apply(skeleton, time - beforeJump, time - beforeJump, false, events, 1, MixBlend.first, MixDirection.in, + false); } else if (time > beforeJump) { // blend in jump - walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in); + walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in, false); jumpAnimation.apply(skeleton, time - beforeJump, time - beforeJump, false, events, (time - beforeJump) / blendIn, - MixBlend.first, MixDirection.in); + MixBlend.first, MixDirection.in, false); } else { // just walk before jump - walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in); + walkAnimation.apply(skeleton, time, time, true, events, 1, MixBlend.first, MixDirection.in, false); } skeleton.update(delta); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index bfef2c07c..008bac261 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -96,7 +96,7 @@ public class Animation { /** Applies the animation's timelines to the specified skeleton. *

- * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection, boolean)}. * @param skeleton The skeleton the animation is being applied to. This provides access to the bones, slots, and other skeleton * components the timelines may change. * @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at specific times rather @@ -115,7 +115,7 @@ public class Animation { * @param direction Indicates whether the timelines are mixing in or out. Used by timelines which perform instant transitions, * such as {@link DrawOrderTimeline} or {@link AttachmentTimeline}. */ public void apply (Skeleton skeleton, float lastTime, float time, boolean loop, @Null Array events, float alpha, - MixBlend blend, MixDirection direction) { + MixBlend blend, MixDirection direction, boolean appliedPose) { if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); if (loop && duration != 0) { @@ -125,7 +125,7 @@ public class Animation { Object[] timelines = this.timelines.items; for (int i = 0, n = this.timelines.size; i < n; i++) - ((Timeline)timelines[i]).apply(skeleton, lastTime, time, events, alpha, blend, direction); + ((Timeline)timelines[i]).apply(skeleton, lastTime, time, events, alpha, blend, direction, appliedPose); } /** The animation's name, which is unique across all animations in the skeleton. */ @@ -140,7 +140,7 @@ public class Animation { /** Controls how timeline values are mixed with setup pose values or current pose values when a timeline is applied with * alpha < 1. *

- * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */ + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection, boolean)}. */ static public enum MixBlend { /** Transitions from the setup value to the timeline value (the current value is not used). Before the first frame, the * setup value is set. */ @@ -168,7 +168,7 @@ public class Animation { /** Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose value) or * mixing in toward 1 (the timeline's value). Some timelines use this to decide how values are applied. *

- * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */ + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection, boolean)}. */ static public enum MixDirection { in, out } @@ -239,9 +239,10 @@ public class Animation { * apply animations on top of each other (layering). * @param blend Controls how mixing is applied when alpha < 1. * @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions, - * such as {@link DrawOrderTimeline} or {@link AttachmentTimeline}, and others such as {@link ScaleTimeline}. */ + * such as {@link DrawOrderTimeline} or {@link AttachmentTimeline}, and others such as {@link ScaleTimeline}. + * @param appliedPose True to to modify the applied pose. */ abstract public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, - MixBlend blend, MixDirection direction); + MixBlend blend, MixDirection direction, boolean appliedPose); /** Linear search using a stride of 1. * @param time Must be >= the first value in frames. @@ -557,10 +558,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.rotation = getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.rotation = getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation); + } } } @@ -580,10 +584,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; + if (appliedPose) bone = bone.applied; float[] frames = this.frames; if (time < frames[0]) { @@ -650,10 +655,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.x = getRelativeValue(time, alpha, blend, bone.x, bone.data.x); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.x = getRelativeValue(time, alpha, blend, bone.x, bone.data.x); + } } } @@ -671,10 +679,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.y = getRelativeValue(time, alpha, blend, bone.y, bone.data.y); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.y = getRelativeValue(time, alpha, blend, bone.y, bone.data.y); + } } } @@ -694,10 +705,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; + if (appliedPose) bone = bone.applied; float[] frames = this.frames; if (time < frames[0]) { @@ -803,10 +815,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.scaleX = getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.scaleX = getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX); + } } } @@ -824,10 +839,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.scaleY = getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.scaleY = getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY); + } } } @@ -847,10 +865,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; + if (appliedPose) bone = bone.applied; float[] frames = this.frames; if (time < frames[0]) { @@ -917,10 +936,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.shearX = getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.shearX = getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX); + } } } @@ -938,10 +960,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) bone.shearY = getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY); + if (bone.active) { + if (appliedPose) bone = bone.applied; + bone.shearY = getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY); + } } } @@ -975,10 +1000,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; + if (appliedPose) bone = bone.applied; if (direction == out) { if (blend == setup) bone.inherit = bone.data.inherit; @@ -1029,10 +1055,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; float[] frames = this.frames; Color color = slot.color; @@ -1118,10 +1145,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; float[] frames = this.frames; Color color = slot.color; @@ -1197,10 +1225,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; float[] frames = this.frames; Color color = slot.color; @@ -1267,10 +1296,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; float[] frames = this.frames; Color light = slot.color, dark = slot.darkColor; @@ -1393,10 +1423,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; float[] frames = this.frames; Color light = slot.color, dark = slot.darkColor; @@ -1518,10 +1549,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; if (direction == out) { if (blend == setup) setAttachment(skeleton, slot, slot.data.attachmentName); @@ -1636,11 +1668,12 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active || !(slot.attachment instanceof VertexAttachment vertexAttachment) || vertexAttachment.getTimelineAttachment() != attachment) return; + if (appliedPose) slot = slot.applied; FloatArray deformArray = slot.deform; if (deformArray.size == 0) blend = setup; @@ -1838,7 +1871,7 @@ public class Animation { /** Fires events for frames > lastTime and <= time. */ public void apply (Skeleton skeleton, float lastTime, float time, @Null Array firedEvents, float alpha, - MixBlend blend, MixDirection direction) { + MixBlend blend, MixDirection direction, boolean appliedPose) { if (firedEvents == null) return; @@ -1846,7 +1879,7 @@ public class Animation { int frameCount = frames.length; if (lastTime > time) { // Apply after lastTime for looped animations. - apply(skeleton, lastTime, Integer.MAX_VALUE, firedEvents, alpha, blend, direction); + apply(skeleton, lastTime, Integer.MAX_VALUE, firedEvents, alpha, blend, direction, appliedPose); lastTime = -1f; } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. return; @@ -1899,7 +1932,7 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { if (direction == out) { if (blend == setup) arraycopy(skeleton.slots.items, 0, skeleton.drawOrder.items, 0, skeleton.slots.size); @@ -1963,10 +1996,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { IkConstraint constraint = skeleton.ikConstraints.get(constraintIndex); if (!constraint.active) return; + if (appliedPose) constraint = constraint.applied; float[] frames = this.frames; if (time < frames[0]) { @@ -2072,10 +2106,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { TransformConstraint constraint = skeleton.transformConstraints.get(constraintIndex); if (!constraint.active) return; + if (appliedPose) constraint = constraint.applied; float[] frames = this.frames; if (time < frames[0]) { @@ -2171,11 +2206,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex); - if (constraint.active) + if (constraint.active) { + if (appliedPose) constraint = constraint.applied; constraint.position = getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position); + } } } @@ -2195,11 +2232,13 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex); - if (constraint.active) + if (constraint.active) { + if (appliedPose) constraint = constraint.applied; constraint.spacing = getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing); + } } } @@ -2238,10 +2277,11 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex); if (!constraint.active) return; + if (appliedPose) constraint = constraint.applied; float[] frames = this.frames; if (time < frames[0]) { @@ -2314,7 +2354,7 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { PhysicsConstraint constraint; if (constraintIndex == -1) { @@ -2323,12 +2363,17 @@ public class Animation { Object[] constraints = skeleton.physicsConstraints.items; for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) { constraint = (PhysicsConstraint)constraints[i]; - if (constraint.active && global(constraint.data)) + if (constraint.active && global(constraint.data)) { + if (appliedPose) constraint = constraint.applied; set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint), value)); + } } } else { constraint = skeleton.physicsConstraints.get(constraintIndex); - if (constraint.active) set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint))); + if (constraint.active) { + if (appliedPose) constraint = constraint.applied; + set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint))); + } } } @@ -2532,7 +2577,7 @@ public class Animation { /** Resets the physics constraint when frames > lastTime and <= time. */ public void apply (Skeleton skeleton, float lastTime, float time, @Null Array firedEvents, float alpha, - MixBlend blend, MixDirection direction) { + MixBlend blend, MixDirection direction, boolean appliedPose) { PhysicsConstraint constraint = null; if (constraintIndex != -1) { @@ -2543,20 +2588,24 @@ public class Animation { float[] frames = this.frames; if (lastTime > time) { // Apply after lastTime for looped animations. - apply(skeleton, lastTime, Integer.MAX_VALUE, null, alpha, blend, direction); + apply(skeleton, lastTime, Integer.MAX_VALUE, null, alpha, blend, direction, appliedPose); lastTime = -1f; } else if (lastTime >= frames[frames.length - 1]) // Last time is after last frame. return; if (time < frames[0]) return; if (lastTime < frames[0] || time >= frames[search(frames, lastTime) + 1]) { - if (constraint != null) + if (constraint != null) { + if (appliedPose) constraint = constraint.applied; constraint.reset(); - else { + } else { Object[] constraints = skeleton.physicsConstraints.items; for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) { constraint = (PhysicsConstraint)constraints[i]; - if (constraint.active) constraint.reset(); + if (constraint.active) { + if (appliedPose) constraint = constraint.applied; + constraint.reset(); + } } } } @@ -2601,10 +2650,12 @@ public class Animation { } public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, - MixDirection direction) { + MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; + if (appliedPose) slot = slot.applied; + Attachment slotAttachment = slot.attachment; if (slotAttachment != attachment) { if (!(slotAttachment instanceof VertexAttachment vertexAttachment) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index e0a2dd9ec..2f9335c70 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -238,8 +238,10 @@ public class AnimationState { Object timeline = timelines[ii]; if (timeline instanceof AttachmentTimeline attachmentTimeline) applyAttachmentTimeline(attachmentTimeline, skeleton, applyTime, blend, attachments); - else - ((Timeline)timeline).apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.in); + else { + ((Timeline)timeline).apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.in, + false); + } } } else { int[] timelineMode = current.timelineMode.items; @@ -258,7 +260,7 @@ public class AnimationState { } else if (timeline instanceof AttachmentTimeline attachmentTimeline) applyAttachmentTimeline(attachmentTimeline, skeleton, applyTime, blend, attachments); else - timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, MixDirection.in); + timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, MixDirection.in, false); } } queueEvents(current, animationTime); @@ -313,7 +315,7 @@ public class AnimationState { if (blend == MixBlend.add) { for (int i = 0; i < timelineCount; i++) - ((Timeline)timelines[i]).apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.out); + ((Timeline)timelines[i]).apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.out, false); } else { int[] timelineMode = from.timelineMode.items; Object[] timelineHoldMix = from.timelineHoldMix.items; @@ -363,7 +365,7 @@ public class AnimationState { else { if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == MixBlend.setup) direction = MixDirection.in; - timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction, false); } } } @@ -409,7 +411,7 @@ public class AnimationState { if (firstFrame) timelinesRotation[i] = 0; if (alpha == 1) { - timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.in); + timeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.in, false); return; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index ce4a13e2b..a55b32737 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -29,41 +29,45 @@ package com.esotericsoftware.spine; -import static com.badlogic.gdx.math.Matrix3.*; -import static com.esotericsoftware.spine.utils.SpineUtils.*; - -import com.badlogic.gdx.math.Matrix3; -import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.BoneData.Inherit; -import com.esotericsoftware.spine.Skeleton.Physics; /** Stores a bone's current pose. *

* A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a * constraint or application code modifies the world transform after it was computed from the local transform. */ -public class Bone implements Updatable { +public class Bone { final BoneData data; final Skeleton skeleton; @Null final Bone parent; - final Array children = new Array(); + final Array children; + BoneApplied applied; + float x, y, rotation, scaleX, scaleY, shearX, shearY; - float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY; - float a, b, worldX; - float c, d, worldY; Inherit inherit; boolean sorted, active; + Bone (Bone bone) { + this.data = bone.data; + this.skeleton = bone.skeleton; + this.parent = bone.parent; + this.children = bone.children; + } + public Bone (BoneData data, Skeleton skeleton, @Null Bone parent) { if (data == null) throw new IllegalArgumentException("data cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); this.data = data; this.skeleton = skeleton; this.parent = parent; + children = new Array(); + + applied = new BoneApplied(this); + setToSetupPose(); } @@ -73,6 +77,7 @@ public class Bone implements Updatable { if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); this.skeleton = skeleton; this.parent = parent; + children = new Array(); data = bone.data; x = bone.x; y = bone.y; @@ -84,131 +89,6 @@ public class Bone implements Updatable { inherit = bone.inherit; } - /** Computes the world transform using the parent bone and this bone's local applied transform. */ - public void update (Physics physics) { - updateWorldTransform(ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY); - } - - /** Computes the world transform using the parent bone and this bone's local transform. - *

- * See {@link #updateWorldTransform(float, float, float, float, float, float, float)}. */ - public void updateWorldTransform () { - updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); - } - - /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the - * specified local transform. Child bones are not updated. - *

- * See World transforms in the Spine - * Runtimes Guide. */ - public void updateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { - ax = x; - ay = y; - arotation = rotation; - ascaleX = scaleX; - ascaleY = scaleY; - ashearX = shearX; - ashearY = shearY; - - Bone parent = this.parent; - if (parent == null) { // Root bone. - Skeleton skeleton = this.skeleton; - float sx = skeleton.scaleX, sy = skeleton.scaleY; - float rx = (rotation + shearX) * degRad; - float ry = (rotation + 90 + shearY) * degRad; - a = cos(rx) * scaleX * sx; - b = cos(ry) * scaleY * sx; - c = sin(rx) * scaleX * sy; - d = sin(ry) * scaleY * sy; - worldX = x * sx + skeleton.x; - worldY = y * sy + skeleton.y; - return; - } - - float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; - worldX = pa * x + pb * y + parent.worldX; - worldY = pc * x + pd * y + parent.worldY; - - switch (inherit) { - case normal -> { - float rx = (rotation + shearX) * degRad; - float ry = (rotation + 90 + shearY) * degRad; - float la = cos(rx) * scaleX; - float lb = cos(ry) * scaleY; - float lc = sin(rx) * scaleX; - float ld = sin(ry) * scaleY; - a = pa * la + pb * lc; - b = pa * lb + pb * ld; - c = pc * la + pd * lc; - d = pc * lb + pd * ld; - return; - } - case onlyTranslation -> { - float rx = (rotation + shearX) * degRad; - float ry = (rotation + 90 + shearY) * degRad; - a = cos(rx) * scaleX; - b = cos(ry) * scaleY; - c = sin(rx) * scaleX; - d = sin(ry) * scaleY; - } - case noRotationOrReflection -> { - float sx = 1 / skeleton.scaleX, sy = 1 / skeleton.scaleY; - pa *= sx; - pc *= sy; - float s = pa * pa + pc * pc, prx; - if (s > 0.0001f) { - s = Math.abs(pa * pd * sy - pb * sx * pc) / s; - pb = pc * s; - pd = pa * s; - prx = atan2Deg(pc, pa); - } else { - pa = 0; - pc = 0; - prx = 90 - atan2Deg(pd, pb); - } - float rx = (rotation + shearX - prx) * degRad; - float ry = (rotation + shearY - prx + 90) * degRad; - float la = cos(rx) * scaleX; - float lb = cos(ry) * scaleY; - float lc = sin(rx) * scaleX; - float ld = sin(ry) * scaleY; - a = pa * la - pb * lc; - b = pa * lb - pb * ld; - c = pc * la + pd * lc; - d = pc * lb + pd * ld; - } - case noScale, noScaleOrReflection -> { - rotation *= degRad; - float cos = cos(rotation), sin = sin(rotation); - float za = (pa * cos + pb * sin) / skeleton.scaleX; - float zc = (pc * cos + pd * sin) / skeleton.scaleY; - float s = (float)Math.sqrt(za * za + zc * zc); - if (s > 0.00001f) s = 1 / s; - za *= s; - zc *= s; - s = (float)Math.sqrt(za * za + zc * zc); - if (inherit == Inherit.noScale && (pa * pd - pb * pc < 0) != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; - rotation = PI / 2 + atan2(zc, za); - float zb = cos(rotation) * s; - float zd = sin(rotation) * s; - shearX *= degRad; - shearY = (90 + shearY) * degRad; - float la = cos(shearX) * scaleX; - float lb = cos(shearY) * scaleY; - float lc = sin(shearX) * scaleX; - float ld = sin(shearY) * scaleY; - a = za * la + zb * lc; - b = za * lb + zb * ld; - c = zc * la + zd * lc; - d = zc * lb + zd * ld; - } - } - a *= skeleton.scaleX; - b *= skeleton.scaleX; - c *= skeleton.scaleY; - d *= skeleton.scaleY; - } - /** Sets this bone's local transform to the setup pose. */ public void setToSetupPose () { BoneData data = this.data; @@ -246,8 +126,6 @@ public class Bone implements Updatable { return active; } - // -- Local transform - /** The local x translation. */ public float getX () { return x; @@ -336,309 +214,11 @@ public class Bone implements Updatable { this.inherit = inherit; } - // -- Applied transform - - /** The applied local x translation. */ - public float getAX () { - return ax; + /** Returns the bone for applied pose. */ + public BoneApplied getApplied () { + return applied; } - public void setAX (float ax) { - this.ax = ax; - } - - /** The applied local y translation. */ - public float getAY () { - return ay; - } - - public void setAY (float ay) { - this.ay = ay; - } - - /** The applied local rotation in degrees, counter clockwise. */ - public float getARotation () { - return arotation; - } - - public void setARotation (float arotation) { - this.arotation = arotation; - } - - /** The applied local scaleX. */ - public float getAScaleX () { - return ascaleX; - } - - public void setAScaleX (float ascaleX) { - this.ascaleX = ascaleX; - } - - /** The applied local scaleY. */ - public float getAScaleY () { - return ascaleY; - } - - public void setAScaleY (float ascaleY) { - this.ascaleY = ascaleY; - } - - /** The applied local shearX. */ - public float getAShearX () { - return ashearX; - } - - public void setAShearX (float ashearX) { - this.ashearX = ashearX; - } - - /** The applied local shearY. */ - public float getAShearY () { - return ashearY; - } - - public void setAShearY (float ashearY) { - this.ashearY = ashearY; - } - - /** Computes the applied transform values from the world transform. - *

- * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, 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 void updateAppliedTransform () { - Bone parent = this.parent; - if (parent == null) { - ax = worldX - skeleton.x; - ay = worldY - skeleton.y; - float a = this.a, b = this.b, c = this.c, d = this.d; - arotation = atan2Deg(c, a); - ascaleX = (float)Math.sqrt(a * a + c * c); - ascaleY = (float)Math.sqrt(b * b + d * d); - ashearX = 0; - ashearY = atan2Deg(a * b + c * d, a * d - b * c); - return; - } - - float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; - float pid = 1 / (pa * pd - pb * pc); - float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; - float dx = worldX - parent.worldX, dy = worldY - parent.worldY; - ax = (dx * ia - dy * ib); - ay = (dy * id - dx * ic); - - float ra, rb, rc, rd; - if (inherit == Inherit.onlyTranslation) { - ra = a; - rb = b; - rc = c; - rd = d; - } else { - switch (inherit) { - case noRotationOrReflection -> { - float s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); - pb = -pc * skeleton.scaleX * s / skeleton.scaleY; - pd = pa * skeleton.scaleY * s / skeleton.scaleX; - pid = 1 / (pa * pd - pb * pc); - ia = pd * pid; - ib = pb * pid; - } - case noScale, noScaleOrReflection -> { - float r = rotation * degRad, cos = cos(r), sin = sin(r); - pa = (pa * cos + pb * sin) / skeleton.scaleX; - pc = (pc * cos + pd * sin) / skeleton.scaleY; - float s = (float)Math.sqrt(pa * pa + pc * pc); - if (s > 0.00001f) s = 1 / s; - pa *= s; - pc *= s; - s = (float)Math.sqrt(pa * pa + pc * pc); - if (inherit == Inherit.noScale && pid < 0 != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; - r = PI / 2 + atan2(pc, pa); - pb = cos(r) * s; - pd = sin(r) * s; - pid = 1 / (pa * pd - pb * pc); - ia = pd * pid; - ib = pb * pid; - ic = pc * pid; - id = pa * pid; - } - } - ra = ia * a - ib * c; - rb = ia * b - ib * d; - rc = id * c - ic * a; - rd = id * d - ic * b; - } - - ashearX = 0; - ascaleX = (float)Math.sqrt(ra * ra + rc * rc); - if (ascaleX > 0.0001f) { - float det = ra * rd - rb * rc; - ascaleY = det / ascaleX; - ashearY = -atan2Deg(ra * rb + rc * rd, det); - arotation = atan2Deg(rc, ra); - } else { - ascaleX = 0; - ascaleY = (float)Math.sqrt(rb * rb + rd * rd); - ashearY = 0; - arotation = 90 - atan2Deg(rd, rb); - } - } - - // -- World transform - - /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ - public float getA () { - return a; - } - - public void setA (float a) { - this.a = a; - } - - /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ - public float getB () { - return b; - } - - public void setB (float b) { - this.b = b; - } - - /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ - public float getC () { - return c; - } - - public void setC (float c) { - this.c = c; - } - - /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ - public float getD () { - return d; - } - - public void setD (float d) { - this.d = d; - } - - /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ - public float getWorldX () { - return worldX; - } - - public void setWorldX (float worldX) { - this.worldX = worldX; - } - - /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ - public float getWorldY () { - return worldY; - } - - public void setWorldY (float worldY) { - this.worldY = worldY; - } - - /** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */ - public float getWorldRotationX () { - return atan2Deg(c, a); - } - - /** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */ - public float getWorldRotationY () { - return atan2Deg(d, b); - } - - /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */ - public float getWorldScaleX () { - return (float)Math.sqrt(a * a + c * c); - } - - /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */ - public float getWorldScaleY () { - return (float)Math.sqrt(b * b + d * d); - } - - public Matrix3 getWorldTransform (Matrix3 worldTransform) { - if (worldTransform == null) throw new IllegalArgumentException("worldTransform cannot be null."); - float[] val = worldTransform.val; - val[M00] = a; - val[M01] = b; - val[M10] = c; - val[M11] = d; - val[M02] = worldX; - val[M12] = worldY; - val[M20] = 0; - val[M21] = 0; - val[M22] = 1; - return worldTransform; - } - - /** Transforms a point from world coordinates to the bone's local coordinates. */ - public Vector2 worldToLocal (Vector2 world) { - if (world == null) throw new IllegalArgumentException("world cannot be null."); - float det = a * d - b * c; - float x = world.x - worldX, y = world.y - worldY; - world.x = (x * d - y * b) / det; - world.y = (y * a - x * c) / det; - return world; - } - - /** Transforms a point from the bone's local coordinates to world coordinates. */ - public Vector2 localToWorld (Vector2 local) { - if (local == null) throw new IllegalArgumentException("local cannot be null."); - float x = local.x, y = local.y; - local.x = x * a + y * b + worldX; - local.y = x * c + y * d + worldY; - return local; - } - - /** Transforms a point from world coordinates to the parent bone's local coordinates. */ - public Vector2 worldToParent (Vector2 world) { - if (world == null) throw new IllegalArgumentException("world cannot be null."); - return parent == null ? world : parent.worldToLocal(world); - } - - /** Transforms a point from the parent bone's coordinates to world coordinates. */ - public Vector2 parentToWorld (Vector2 world) { - if (world == null) throw new IllegalArgumentException("world cannot be null."); - return parent == null ? world : parent.localToWorld(world); - } - - /** Transforms a world rotation to a local rotation. */ - public float worldToLocalRotation (float worldRotation) { - worldRotation *= degRad; - float sin = sin(worldRotation), cos = cos(worldRotation); - return atan2Deg(a * sin - c * cos, d * cos - b * sin) + rotation - shearX; - } - - /** Transforms a local rotation to a world rotation. */ - public float localToWorldRotation (float localRotation) { - localRotation = (localRotation - rotation - shearX) * degRad; - float sin = sin(localRotation), cos = cos(localRotation); - return atan2Deg(cos * c + sin * d, cos * a + sin * b); - } - - /** Rotates the world transform the specified amount. - *

- * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and - * {@link #update(Physics)} will need to be called on any child bones, recursively. */ - public void rotateWorld (float degrees) { - degrees *= degRad; - float sin = sin(degrees), cos = cos(degrees); - float ra = a, rb = b; - a = cos * ra - sin * c; - b = cos * rb - sin * d; - c = sin * ra + cos * c; - d = sin * rb + cos * d; - } - - // --- - public String toString () { return data.name; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java new file mode 100644 index 000000000..43fff06ca --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java @@ -0,0 +1,372 @@ + +package com.esotericsoftware.spine; + +import static com.badlogic.gdx.math.Matrix3.*; +import static com.esotericsoftware.spine.utils.SpineUtils.*; + +import com.badlogic.gdx.math.Matrix3; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.utils.Null; + +import com.esotericsoftware.spine.BoneData.Inherit; +import com.esotericsoftware.spine.Skeleton.Physics; + +public class BoneApplied extends Bone implements Updatable { + final Bone pose; + @Null final BoneApplied parentApplied; + float a, b, worldX; + float c, d, worldY; + + BoneApplied (Bone bone) { + super(bone); + pose = bone; + parentApplied = parent == null ? null : parent.applied; + } + + /** Computes the world transform using the parent bone and this bone's local applied transform. */ + public void updateWorldTransform () { + updateWorldTransform(); + } + + /** Computes the world transform using the parent bone and this bone's local transform. + *

+ * See {@link #updateWorldTransform(float, float, float, float, float, float, float)}. */ + /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the + * specified local transform. Child bones are not updated. + *

+ * See World transforms in the Spine + * Runtimes Guide. */ + public void update (Physics physics) { + BoneApplied parent = parentApplied; + if (parent == null) { // Root bone. + Skeleton skeleton = this.skeleton; + float sx = skeleton.scaleX, sy = skeleton.scaleY; + float rx = (rotation + shearX) * degRad; + float ry = (rotation + 90 + shearY) * degRad; + a = cos(rx) * scaleX * sx; + b = cos(ry) * scaleY * sx; + c = sin(rx) * scaleX * sy; + d = sin(ry) * scaleY * sy; + worldX = x * sx + skeleton.x; + worldY = y * sy + skeleton.y; + return; + } + + float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + worldX = pa * x + pb * y + parent.worldX; + worldY = pc * x + pd * y + parent.worldY; + + switch (inherit) { + case normal -> { + float rx = (rotation + shearX) * degRad; + float ry = (rotation + 90 + shearY) * degRad; + float la = cos(rx) * scaleX; + float lb = cos(ry) * scaleY; + float lc = sin(rx) * scaleX; + float ld = sin(ry) * scaleY; + a = pa * la + pb * lc; + b = pa * lb + pb * ld; + c = pc * la + pd * lc; + d = pc * lb + pd * ld; + return; + } + case onlyTranslation -> { + float rx = (rotation + shearX) * degRad; + float ry = (rotation + 90 + shearY) * degRad; + a = cos(rx) * scaleX; + b = cos(ry) * scaleY; + c = sin(rx) * scaleX; + d = sin(ry) * scaleY; + } + case noRotationOrReflection -> { + float sx = 1 / skeleton.scaleX, sy = 1 / skeleton.scaleY; + pa *= sx; + pc *= sy; + float s = pa * pa + pc * pc, prx; + if (s > 0.0001f) { + s = Math.abs(pa * pd * sy - pb * sx * pc) / s; + pb = pc * s; + pd = pa * s; + prx = atan2Deg(pc, pa); + } else { + pa = 0; + pc = 0; + prx = 90 - atan2Deg(pd, pb); + } + float rx = (rotation + shearX - prx) * degRad; + float ry = (rotation + shearY - prx + 90) * degRad; + float la = cos(rx) * scaleX; + float lb = cos(ry) * scaleY; + float lc = sin(rx) * scaleX; + float ld = sin(ry) * scaleY; + a = pa * la - pb * lc; + b = pa * lb - pb * ld; + c = pc * la + pd * lc; + d = pc * lb + pd * ld; + } + case noScale, noScaleOrReflection -> { + rotation *= degRad; + float cos = cos(rotation), sin = sin(rotation); + float za = (pa * cos + pb * sin) / skeleton.scaleX; + float zc = (pc * cos + pd * sin) / skeleton.scaleY; + float s = (float)Math.sqrt(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = (float)Math.sqrt(za * za + zc * zc); + if (inherit == Inherit.noScale && (pa * pd - pb * pc < 0) != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; + rotation = PI / 2 + atan2(zc, za); + float zb = cos(rotation) * s; + float zd = sin(rotation) * s; + shearX *= degRad; + shearY = (90 + shearY) * degRad; + float la = cos(shearX) * scaleX; + float lb = cos(shearY) * scaleY; + float lc = sin(shearX) * scaleX; + float ld = sin(shearY) * scaleY; + a = za * la + zb * lc; + b = za * lb + zb * ld; + c = zc * la + zd * lc; + d = zc * lb + zd * ld; + } + } + a *= skeleton.scaleX; + b *= skeleton.scaleX; + c *= skeleton.scaleY; + d *= skeleton.scaleY; + } + + /** Computes the applied transform values from the world transform. + *

+ * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, 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 void updateAppliedTransform () { + BoneApplied parent = parentApplied; + if (parent == null) { + x = worldX - skeleton.x; + y = worldY - skeleton.y; + float a = this.a, b = this.b, c = this.c, d = this.d; + rotation = atan2Deg(c, a); + scaleX = (float)Math.sqrt(a * a + c * c); + scaleY = (float)Math.sqrt(b * b + d * d); + shearX = 0; + shearY = atan2Deg(a * b + c * d, a * d - b * c); + return; + } + + float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + float pid = 1 / (pa * pd - pb * pc); + float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + float dx = worldX - parent.worldX, dy = worldY - parent.worldY; + x = (dx * ia - dy * ib); + y = (dy * id - dx * ic); + + float ra, rb, rc, rd; + if (inherit == Inherit.onlyTranslation) { + ra = a; + rb = b; + rc = c; + rd = d; + } else { + switch (inherit) { + case noRotationOrReflection -> { + float s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + pb = -pc * skeleton.scaleX * s / skeleton.scaleY; + pd = pa * skeleton.scaleY * s / skeleton.scaleX; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + } + case noScale, noScaleOrReflection -> { + float r = rotation * degRad, cos = cos(r), sin = sin(r); + pa = (pa * cos + pb * sin) / skeleton.scaleX; + pc = (pc * cos + pd * sin) / skeleton.scaleY; + float s = (float)Math.sqrt(pa * pa + pc * pc); + if (s > 0.00001f) s = 1 / s; + pa *= s; + pc *= s; + s = (float)Math.sqrt(pa * pa + pc * pc); + if (inherit == Inherit.noScale && pid < 0 != (skeleton.scaleX < 0 != skeleton.scaleY < 0)) s = -s; + r = PI / 2 + atan2(pc, pa); + pb = cos(r) * s; + pd = sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + } + } + ra = ia * a - ib * c; + rb = ia * b - ib * d; + rc = id * c - ic * a; + rd = id * d - ic * b; + } + + shearX = 0; + scaleX = (float)Math.sqrt(ra * ra + rc * rc); + if (scaleX > 0.0001f) { + float det = ra * rd - rb * rc; + scaleY = det / scaleX; + shearY = -atan2Deg(ra * rb + rc * rd, det); + rotation = atan2Deg(rc, ra); + } else { + scaleX = 0; + scaleY = (float)Math.sqrt(rb * rb + rd * rd); + shearY = 0; + rotation = 90 - atan2Deg(rd, rb); + } + } + + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + public float getA () { + return a; + } + + public void setA (float a) { + this.a = a; + } + + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + public float getB () { + return b; + } + + public void setB (float b) { + this.b = b; + } + + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + public float getC () { + return c; + } + + public void setC (float c) { + this.c = c; + } + + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + public float getD () { + return d; + } + + public void setD (float d) { + this.d = d; + } + + /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ + public float getWorldX () { + return worldX; + } + + public void setWorldX (float worldX) { + this.worldX = worldX; + } + + /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ + public float getWorldY () { + return worldY; + } + + public void setWorldY (float worldY) { + this.worldY = worldY; + } + + /** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */ + public float getWorldRotationX () { + return atan2Deg(c, a); + } + + /** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */ + public float getWorldRotationY () { + return atan2Deg(d, b); + } + + /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */ + public float getWorldScaleX () { + return (float)Math.sqrt(a * a + c * c); + } + + /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */ + public float getWorldScaleY () { + return (float)Math.sqrt(b * b + d * d); + } + + public Matrix3 getWorldTransform (Matrix3 worldTransform) { + if (worldTransform == null) throw new IllegalArgumentException("worldTransform cannot be null."); + float[] val = worldTransform.val; + val[M00] = a; + val[M01] = b; + val[M10] = c; + val[M11] = d; + val[M02] = worldX; + val[M12] = worldY; + val[M20] = 0; + val[M21] = 0; + val[M22] = 1; + return worldTransform; + } + + /** Transforms a point from world coordinates to the bone's local coordinates. */ + public Vector2 worldToLocal (Vector2 world) { + if (world == null) throw new IllegalArgumentException("world cannot be null."); + float det = a * d - b * c; + float x = world.x - worldX, y = world.y - worldY; + world.x = (x * d - y * b) / det; + world.y = (y * a - x * c) / det; + return world; + } + + /** Transforms a point from the bone's local coordinates to world coordinates. */ + public Vector2 localToWorld (Vector2 local) { + if (local == null) throw new IllegalArgumentException("local cannot be null."); + float x = local.x, y = local.y; + local.x = x * a + y * b + worldX; + local.y = x * c + y * d + worldY; + return local; + } + + /** Transforms a point from world coordinates to the parent bone's local coordinates. */ + public Vector2 worldToParent (Vector2 world) { + if (world == null) throw new IllegalArgumentException("world cannot be null."); + return parent == null ? world : parentApplied.worldToLocal(world); + } + + /** Transforms a point from the parent bone's coordinates to world coordinates. */ + public Vector2 parentToWorld (Vector2 world) { + if (world == null) throw new IllegalArgumentException("world cannot be null."); + return parent == null ? world : parentApplied.localToWorld(world); + } + + /** Transforms a world rotation to a local rotation. */ + public float worldToLocalRotation (float worldRotation) { + worldRotation *= degRad; + float sin = sin(worldRotation), cos = cos(worldRotation); + return atan2Deg(a * sin - c * cos, d * cos - b * sin) + rotation - shearX; + } + + /** Transforms a local rotation to a world rotation. */ + public float localToWorldRotation (float localRotation) { + localRotation = (localRotation - rotation - shearX) * degRad; + float sin = sin(localRotation), cos = cos(localRotation); + return atan2Deg(cos * c + sin * d, cos * a + sin * b); + } + + /** Rotates the world transform the specified amount. + *

+ * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and + * {@link #update(Physics)} will need to be called on any child bones, recursively. */ + public void rotateWorld (float degrees) { + degrees *= degRad; + float sin = sin(degrees), cos = cos(degrees); + float ra = a, rb = b; + a = cos * ra - sin * c; + b = cos * rb - sin * d; + c = sin * ra + cos * c; + d = sin * rb + cos * d; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java index 8bcd74faa..c5dbf7f47 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Event.java @@ -35,7 +35,7 @@ import com.esotericsoftware.spine.AnimationState.AnimationStateListener; /** Stores the current pose values for an {@link Event}. *

* See Timeline - * {@link Timeline#apply(Skeleton, float, float, com.badlogic.gdx.utils.Array, float, com.esotericsoftware.spine.Animation.MixBlend, com.esotericsoftware.spine.Animation.MixDirection)}, + * {@link Timeline#apply(Skeleton, float, float, com.badlogic.gdx.utils.Array, float, com.esotericsoftware.spine.Animation.MixBlend, com.esotericsoftware.spine.Animation.MixDirection, boolean)}, * AnimationStateListener {@link AnimationStateListener#event(com.esotericsoftware.spine.AnimationState.TrackEntry, Event)}, and * Events in the Spine User Guide. */ public class Event { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index cf91d8c49..256637a5b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -42,13 +42,20 @@ import com.esotericsoftware.spine.Skeleton.Physics; * See IK constraints in the Spine User Guide. */ public class IkConstraint implements Updatable { final IkConstraintData data; - final Array bones; - Bone target; + final Array bones; + BoneApplied target; + IkConstraint applied; + boolean active; + int bendDirection; boolean compress, stretch; float mix = 1, softness; - boolean active; + private IkConstraint (IkConstraintData data, Array bones, BoneApplied target) { + this.data = data; + this.bones = bones; + this.target = target; + } public IkConstraint (IkConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); @@ -57,9 +64,11 @@ public class IkConstraint implements Updatable { bones = new Array(data.bones.size); for (BoneData boneData : data.bones) - bones.add(skeleton.bones.get(boneData.index)); + bones.add(skeleton.bones.get(boneData.index).applied); - target = skeleton.bones.get(data.target.index); + target = skeleton.bones.get(data.target.index).applied; + + applied = new IkConstraint(data, bones, target); setToSetupPose(); } @@ -82,17 +91,18 @@ public class IkConstraint implements Updatable { /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { if (mix == 0) return; - Bone target = this.target; + BoneApplied target = this.target; Object[] bones = this.bones.items; switch (this.bones.size) { - case 1 -> apply((Bone)bones[0], target.worldX, target.worldY, compress, stretch, data.uniform, mix); + case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, compress, stretch, data.uniform, mix); case 2 -> // - apply((Bone)bones[0], (Bone)bones[1], target.worldX, target.worldY, bendDirection, stretch, data.uniform, softness, mix); + apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, bendDirection, stretch, data.uniform, + softness, mix); } } - /** The bones that will be modified by this IK constraint. */ - public Array getBones () { + /** The 1 or 2 bones that will be modified by this IK constraint. */ + public Array getBones () { return bones; } @@ -101,7 +111,7 @@ public class IkConstraint implements Updatable { return target; } - public void setTarget (Bone target) { + public void setTarget (BoneApplied target) { if (target == null) throw new IllegalArgumentException("target cannot be null."); this.target = target; } @@ -171,12 +181,12 @@ public class IkConstraint implements Updatable { } /** Applies 1 bone IK. The target is specified in the world coordinate system. */ - static public void apply (Bone bone, float targetX, float targetY, boolean compress, boolean stretch, boolean uniform, + static public void apply (BoneApplied bone, float targetX, float targetY, boolean compress, boolean stretch, boolean uniform, float alpha) { if (bone == null) throw new IllegalArgumentException("bone cannot be null."); - Bone p = bone.parent; + BoneApplied p = bone.parentApplied; float pa = p.a, pb = p.b, pc = p.c, pd = p.d; - float rotationIK = -bone.ashearX - bone.arotation, tx, ty; + float rotationIK = -bone.shearX - bone.rotation, tx, ty; switch (bone.inherit) { case onlyTranslation: tx = (targetX - bone.worldX) * Math.signum(bone.skeleton.scaleX); @@ -197,17 +207,17 @@ public class IkConstraint implements Updatable { tx = 0; ty = 0; } else { - tx = (x * pd - y * pb) / d - bone.ax; - ty = (y * pa - x * pc) / d - bone.ay; + tx = (x * pd - y * pb) / d - bone.x; + ty = (y * pa - x * pc) / d - bone.y; } } rotationIK += atan2Deg(ty, tx); - if (bone.ascaleX < 0) rotationIK += 180; + if (bone.scaleX < 0) rotationIK += 180; if (rotationIK > 180) rotationIK -= 360; else if (rotationIK < -180) // rotationIK += 360; - float sx = bone.ascaleX, sy = bone.ascaleY; + bone.rotation += rotationIK * alpha; if (compress || stretch) { switch (bone.inherit) { case noScale, noScaleOrReflection -> { @@ -215,27 +225,27 @@ public class IkConstraint implements Updatable { ty = targetY - bone.worldY; } } - float b = bone.data.length * sx; + float b = bone.data.length * bone.scaleX; if (b > 0.0001f) { float dd = tx * tx + ty * ty; if ((compress && dd < b * b) || (stretch && dd > b * b)) { float s = ((float)Math.sqrt(dd) / b - 1) * alpha + 1; - sx *= s; - if (uniform) sy *= s; + bone.scaleX *= s; + if (uniform) bone.scaleY *= s; } } } - bone.updateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); + bone.updateWorldTransform(); } /** Applies 2 bone IK. The target is specified in the world coordinate system. * @param child A direct descendant of the parent bone. */ - static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, boolean stretch, boolean uniform, - float softness, float alpha) { + static public void apply (BoneApplied parent, BoneApplied child, float targetX, float targetY, int bendDir, boolean stretch, + boolean uniform, float softness, float alpha) { if (parent == null) throw new IllegalArgumentException("parent cannot be null."); if (child == null) throw new IllegalArgumentException("child cannot be null."); if (parent.inherit != Inherit.normal || child.inherit != Inherit.normal) return; - float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; + float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX; int os1, os2, s2; if (psx < 0) { psx = -psx; @@ -254,18 +264,17 @@ public class IkConstraint implements Updatable { os2 = 180; } else os2 = 0; - float cx = child.ax, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + float cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d; boolean u = Math.abs(psx - psy) <= 0.0001f; if (!u || stretch) { - cy = 0; - cwx = a * cx + parent.worldX; - cwy = c * cx + parent.worldY; + child.y = 0; + cwx = a * child.x + parent.worldX; + cwy = c * child.x + parent.worldY; } else { - cy = child.ay; - cwx = a * cx + b * cy + parent.worldX; - cwy = c * cx + d * cy + parent.worldY; + cwx = a * child.x + b * child.y + parent.worldX; + cwy = c * child.x + d * child.y + parent.worldY; } - Bone pp = parent.parent; + BoneApplied pp = parent.parentApplied; a = pp.a; b = pp.b; c = pp.c; @@ -276,7 +285,8 @@ public class IkConstraint implements Updatable { float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; if (l1 < 0.0001f) { apply(parent, targetX, targetY, false, stretch, false, alpha); - child.updateWorldTransform(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + child.rotation = 0; + child.updateWorldTransform(); return; } x = targetX - pp.worldX; @@ -306,8 +316,8 @@ public class IkConstraint implements Updatable { a2 = 0; if (stretch) { a = ((float)Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; - sx *= a; - if (uniform) sy *= a; + parent.scaleX *= a; + if (uniform) parent.scaleY *= a; } } else a2 = (float)Math.acos(cos) * bendDir; @@ -364,20 +374,20 @@ public class IkConstraint implements Updatable { a2 = maxAngle * bendDir; } } - float os = atan2(cy, cx) * s2; - float rotation = parent.arotation; - a1 = (a1 - os) * radDeg + os1 - rotation; + float os = atan2(child.y, child.x) * s2; + a1 = (a1 - os) * radDeg + os1 - parent.rotation; if (a1 > 180) a1 -= 360; else if (a1 < -180) // a1 += 360; - parent.updateWorldTransform(px, py, rotation + a1 * alpha, sx, sy, 0, 0); - rotation = child.arotation; - a2 = ((a2 + os) * radDeg - child.ashearX) * s2 + os2 - rotation; + parent.rotation += a1 * alpha; + parent.updateWorldTransform(); + a2 = ((a2 + os) * radDeg - child.shearX) * s2 + os2 - child.rotation; if (a2 > 180) a2 -= 360; else if (a2 < -180) // a2 += 360; - child.updateWorldTransform(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + child.rotation += a2 * alpha; + child.updateWorldTransform(); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index 375faef48..ba0f1ba7b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -35,6 +35,7 @@ import java.util.Arrays; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; +import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.PathConstraintData.PositionMode; import com.esotericsoftware.spine.PathConstraintData.RotateMode; @@ -51,16 +52,23 @@ public class PathConstraint implements Updatable { static final float epsilon = 0.00001f; final PathConstraintData data; - final Array bones; + final Array bones; Slot slot; - float position, spacing, mixRotate, mixX, mixY; - + PathConstraint applied; boolean active; + float position, spacing, mixRotate, mixX, mixY; + private final FloatArray spaces = new FloatArray(), positions = new FloatArray(); private final FloatArray world = new FloatArray(), curves = new FloatArray(), lengths = new FloatArray(); private final float[] segments = new float[10]; + public PathConstraint (PathConstraintData data, Array bones, Slot slot) { + this.data = data; + this.bones = bones; + this.slot = slot; + } + public PathConstraint (PathConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); @@ -68,10 +76,12 @@ public class PathConstraint implements Updatable { bones = new Array(data.bones.size); for (BoneData boneData : data.bones) - bones.add(skeleton.bones.get(boneData.index)); + bones.add(skeleton.bones.get(boneData.index).applied); slot = skeleton.slots.get(data.slot.index); + applied = new PathConstraint(data, bones, slot); + setToSetupPose(); } @@ -108,7 +118,7 @@ public class PathConstraint implements Updatable { case percent -> { if (scale) { for (int i = 0, n = spacesCount - 1; i < n; i++) { - var bone = (Bone)bones[i]; + var bone = (BoneApplied)bones[i]; float setupLength = bone.data.length; float x = setupLength * bone.a, y = setupLength * bone.c; lengths[i] = (float)Math.sqrt(x * x + y * y); @@ -119,7 +129,7 @@ public class PathConstraint implements Updatable { case proportional -> { float sum = 0; for (int i = 0, n = spacesCount - 1; i < n;) { - var bone = (Bone)bones[i]; + var bone = (BoneApplied)bones[i]; float setupLength = bone.data.length; if (setupLength < epsilon) { if (scale) lengths[i] = 0; @@ -141,7 +151,7 @@ public class PathConstraint implements Updatable { default -> { boolean lengthSpacing = data.spacingMode == SpacingMode.length; for (int i = 0, n = spacesCount - 1; i < n;) { - var bone = (Bone)bones[i]; + var bone = (BoneApplied)bones[i]; float setupLength = bone.data.length; if (setupLength < epsilon) { if (scale) lengths[i] = 0; @@ -163,11 +173,11 @@ public class PathConstraint implements Updatable { tip = data.rotateMode == RotateMode.chain; else { tip = false; - Bone p = slot.bone; + BoneApplied p = slot.bone.applied; offsetRotation *= p.a * p.d - p.b * p.c > 0 ? degRad : -degRad; } for (int i = 0, p = 3; i < boneCount; i++, p += 3) { - var bone = (Bone)bones[i]; + var bone = (BoneApplied)bones[i]; bone.worldX += (boneX - bone.worldX) * mixX; bone.worldY += (boneY - bone.worldY) * mixY; float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; @@ -518,7 +528,7 @@ public class PathConstraint implements Updatable { } /** The bones that will be modified by this path constraint. */ - public Array getBones () { + public Array getBones () { return bones; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index e59c7e076..1f8feb3e1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -38,7 +38,11 @@ import com.esotericsoftware.spine.Skeleton.Physics; * See Physics constraints in the Spine User Guide. */ public class PhysicsConstraint implements Updatable { final PhysicsConstraintData data; - Bone bone; + final Skeleton skeleton; + BoneApplied bone; + PhysicsConstraint applied; + boolean active; + float inertia, strength, damping, massInverse, wind, gravity, mix; boolean reset = true; @@ -47,19 +51,23 @@ public class PhysicsConstraint implements Updatable { float yOffset, yVelocity; float rotateOffset, rotateVelocity; float scaleOffset, scaleVelocity; - - boolean active; - - final Skeleton skeleton; float remaining, lastTime; + private PhysicsConstraint (PhysicsConstraintData data, Skeleton skeleton, BoneApplied bone) { + this.data = data; + this.skeleton = skeleton; + this.bone = bone; + } + public PhysicsConstraint (PhysicsConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); this.data = data; this.skeleton = skeleton; - bone = skeleton.bones.get(data.bone.index); + bone = skeleton.bones.get(data.bone.index).applied; + + applied = new PhysicsConstraint(data, skeleton, bone); setToSetupPose(); } @@ -118,7 +126,7 @@ public class PhysicsConstraint implements Updatable { if (mix == 0) return; boolean x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0; - Bone bone = this.bone; + BoneApplied bone = this.bone; float l = bone.data.length; switch (physics) { @@ -278,11 +286,11 @@ public class PhysicsConstraint implements Updatable { } /** The bone constrained by this physics constraint. */ - public Bone getBone () { + public BoneApplied getBone () { return bone; } - public void setBone (Bone bone) { + public void setBone (BoneApplied bone) { this.bone = bone; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index dac59fd07..e07d73978 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -37,6 +37,8 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; +import com.esotericsoftware.spine.Animation.BoneTimeline; +import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Skin.SkinEntry; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.ClippingAttachment; @@ -55,6 +57,7 @@ public class Skeleton { final Array bones; final Array slots; Array drawOrder; + final Array sliders; final Array ikConstraints; final Array transformConstraints; final Array pathConstraints; @@ -85,27 +88,30 @@ public class Skeleton { slots = new Array(data.slots.size); drawOrder = new Array(data.slots.size); for (SlotData slotData : data.slots) { - var bone = (Bone)bones[slotData.boneData.index]; - var slot = new Slot(slotData, bone); + var slot = new Slot(slotData, this); slots.add(slot); drawOrder.add(slot); } + sliders = new Array(data.sliders.size); + for (SliderData constraint : data.sliders) + sliders.add(new Slider(constraint, this)); + ikConstraints = new Array(data.ikConstraints.size); - for (IkConstraintData ikConstraintData : data.ikConstraints) - ikConstraints.add(new IkConstraint(ikConstraintData, this)); + for (IkConstraintData constraint : data.ikConstraints) + ikConstraints.add(new IkConstraint(constraint, this)); transformConstraints = new Array(data.transformConstraints.size); - for (TransformConstraintData transformConstraintData : data.transformConstraints) - transformConstraints.add(new TransformConstraint(transformConstraintData, this)); + for (TransformConstraintData constraint : data.transformConstraints) + transformConstraints.add(new TransformConstraint(constraint, this)); pathConstraints = new Array(data.pathConstraints.size); - for (PathConstraintData pathConstraintData : data.pathConstraints) - pathConstraints.add(new PathConstraint(pathConstraintData, this)); + for (PathConstraintData constraint : data.pathConstraints) + pathConstraints.add(new PathConstraint(constraint, this)); physicsConstraints = new Array(data.physicsConstraints.size); - for (PhysicsConstraintData physicsConstraintData : data.physicsConstraints) - physicsConstraints.add(new PhysicsConstraint(physicsConstraintData, this)); + for (PhysicsConstraintData constraint : data.physicsConstraints) + physicsConstraints.add(new PhysicsConstraint(constraint, this)); color = new Color(1, 1, 1, 1); @@ -140,21 +146,25 @@ public class Skeleton { for (Slot slot : skeleton.drawOrder) drawOrder.add(slots.get(slot.data.index)); + sliders = new Array(skeleton.sliders.size); + for (Slider constraint : skeleton.sliders) + sliders.add(new Slider(constraint, skeleton)); + ikConstraints = new Array(skeleton.ikConstraints.size); - for (IkConstraint ikConstraint : skeleton.ikConstraints) - ikConstraints.add(new IkConstraint(ikConstraint, skeleton)); + for (IkConstraint constraint : skeleton.ikConstraints) + ikConstraints.add(new IkConstraint(constraint, skeleton)); transformConstraints = new Array(skeleton.transformConstraints.size); - for (TransformConstraint transformConstraint : skeleton.transformConstraints) - transformConstraints.add(new TransformConstraint(transformConstraint, skeleton)); + for (TransformConstraint constraint : skeleton.transformConstraints) + transformConstraints.add(new TransformConstraint(constraint, skeleton)); pathConstraints = new Array(skeleton.pathConstraints.size); - for (PathConstraint pathConstraint : skeleton.pathConstraints) - pathConstraints.add(new PathConstraint(pathConstraint, skeleton)); + for (PathConstraint constraint : skeleton.pathConstraints) + pathConstraints.add(new PathConstraint(constraint, skeleton)); physicsConstraints = new Array(skeleton.physicsConstraints.size); - for (PhysicsConstraint physicsConstraint : skeleton.physicsConstraints) - physicsConstraints.add(new PhysicsConstraint(physicsConstraint, skeleton)); + for (PhysicsConstraint constraint : skeleton.physicsConstraints) + physicsConstraints.add(new PhysicsConstraint(constraint, skeleton)); skin = skeleton.skin; color = new Color(skeleton.color); @@ -192,13 +202,21 @@ public class Skeleton { } } - int ikCount = ikConstraints.size, transformCount = transformConstraints.size, pathCount = pathConstraints.size, - physicsCount = physicsConstraints.size; - Object[] ikConstraints = this.ikConstraints.items, transformConstraints = this.transformConstraints.items, - pathConstraints = this.pathConstraints.items, physicsConstraints = this.physicsConstraints.items; + int sliderCount = sliders.size, ikCount = ikConstraints.size, transformCount = transformConstraints.size, + pathCount = pathConstraints.size, physicsCount = physicsConstraints.size; + Object[] sliders = this.sliders.items, ikConstraints = this.ikConstraints.items, + transformConstraints = this.transformConstraints.items, pathConstraints = this.pathConstraints.items, + physicsConstraints = this.physicsConstraints.items; int constraintCount = ikCount + transformCount + pathCount + physicsCount; outer: for (int i = 0; i < constraintCount; i++) { + for (int ii = 0; ii < sliderCount; ii++) { + var constraint = (Slider)sliders[ii]; + if (constraint.data.order == i) { + sortSlider(constraint); + continue outer; + } + } for (int ii = 0; ii < ikCount; ii++) { var constraint = (IkConstraint)ikConstraints[ii]; if (constraint.data.order == i) { @@ -233,21 +251,42 @@ public class Skeleton { sortBone((Bone)bones[i]); } + private void sortSlider (Slider constraint) { + constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)); + if (!constraint.active) return; + + Object[] bones = this.bones.items; + for (Timeline timeline : constraint.animation.timelines) + if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + + updateCache.add(constraint); + + for (Timeline timeline : constraint.animation.timelines) { + if (timeline instanceof BoneTimeline boneTimeline) { + var bone = (Bone)bones[boneTimeline.getBoneIndex()]; + sortReset(bone.children); + bone.sorted = false; + } + } + for (Timeline timeline : constraint.animation.timelines) + if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + } + private void sortIkConstraint (IkConstraint constraint) { constraint.active = constraint.target.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; - sortBone(constraint.target); + sortBone(constraint.target.pose); - Array constrained = constraint.bones; - Bone parent = constrained.first(); + Array constrained = constraint.bones; + Bone parent = constrained.first().pose; sortBone(parent); if (constrained.size == 1) { updateCache.add(constraint); sortReset(parent.children); } else { - Bone child = constrained.peek(); + Bone child = constrained.peek().pose; sortBone(child); updateCache.add(constraint); @@ -262,27 +301,27 @@ public class Skeleton { && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; - sortBone(constraint.source); + sortBone(constraint.source.pose); Object[] constrained = constraint.bones.items; int boneCount = constraint.bones.size; if (constraint.data.localSource) { for (int i = 0; i < boneCount; i++) { - var child = (Bone)constrained[i]; + Bone child = ((BoneApplied)constrained[i]).pose; sortBone(child.parent); sortBone(child); } } else { for (int i = 0; i < boneCount; i++) - sortBone((Bone)constrained[i]); + sortBone(((BoneApplied)constrained[i]).pose); } updateCache.add(constraint); for (int i = 0; i < boneCount; i++) - sortReset(((Bone)constrained[i]).children); + sortReset(((BoneApplied)constrained[i]).children); for (int i = 0; i < boneCount; i++) - ((Bone)constrained[i]).sorted = true; + ((BoneApplied)constrained[i]).pose.sorted = true; } private void sortPathConstraint (PathConstraint constraint) { @@ -302,7 +341,7 @@ public class Skeleton { Object[] constrained = constraint.bones.items; int boneCount = constraint.bones.size; for (int i = 0; i < boneCount; i++) - sortBone((Bone)constrained[i]); + sortBone(((BoneApplied)constrained[i]).pose); updateCache.add(constraint); @@ -331,13 +370,13 @@ public class Skeleton { int nn = pathBones[i++]; nn += i; while (i < nn) - sortBone((Bone)bones[pathBones[i++]]); + sortBone(((BoneApplied)bones[pathBones[i++]]).pose); } } } private void sortPhysicsConstraint (PhysicsConstraint constraint) { - Bone bone = constraint.bone; + Bone bone = constraint.bone.pose; constraint.active = bone.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; @@ -355,7 +394,7 @@ public class Skeleton { Bone parent = bone.parent; if (parent != null) sortBone(parent); bone.sorted = true; - updateCache.add(bone); + updateCache.add(bone.applied); } private void sortReset (Array bones) { @@ -376,14 +415,29 @@ public class Skeleton { Object[] bones = this.bones.items; for (int i = 0, n = this.bones.size; i < n; i++) { var bone = (Bone)bones[i]; - bone.ax = bone.x; - bone.ay = bone.y; - bone.arotation = bone.rotation; - bone.ascaleX = bone.scaleX; - bone.ascaleY = bone.scaleY; - bone.ashearX = bone.shearX; - bone.ashearY = bone.shearY; + if (!bone.active) continue; + BoneApplied applied = bone.applied; + applied.x = bone.x; + applied.y = bone.y; + applied.rotation = bone.rotation; + applied.scaleX = bone.scaleX; + applied.scaleY = bone.scaleY; + applied.shearX = bone.shearX; + applied.shearY = bone.shearY; + applied.inherit = bone.inherit; } + Object[] slots = this.slots.items; + for (int i = 0, n = this.slots.size; i < n; i++) { + var slot = (Slot)slots[i]; + if (!slot.bone.active) continue; + Slot applied = slot.applied; + applied.color.set(slot.color); + if (applied.darkColor != null) applied.darkColor.set(slot.darkColor); + applied.attachment = slot.attachment; + applied.sequenceIndex = slot.sequenceIndex; + applied.deform = slot.deform; + } + // BOZO! - Reset the rest. Object[] updateCache = this.updateCache.items; for (int i = 0, n = this.updateCache.size; i < n; i++) @@ -395,23 +449,26 @@ public class Skeleton { *

* See World transforms in the Spine * Runtimes Guide. */ - public void updateWorldTransform (Physics physics, Bone parent) { + public void updateWorldTransform (Physics physics, BoneApplied parent) { if (parent == null) throw new IllegalArgumentException("parent cannot be null."); Object[] bones = this.bones.items; for (int i = 1, n = this.bones.size; i < n; i++) { // Skip root bone. var bone = (Bone)bones[i]; - bone.ax = bone.x; - bone.ay = bone.y; - bone.arotation = bone.rotation; - bone.ascaleX = bone.scaleX; - bone.ascaleY = bone.scaleY; - bone.ashearX = bone.shearX; - bone.ashearY = bone.shearY; + BoneApplied applied = bone.applied; + applied.x = bone.x; + applied.y = bone.y; + applied.rotation = bone.rotation; + applied.scaleX = bone.scaleX; + applied.scaleY = bone.scaleY; + applied.shearX = bone.shearX; + applied.shearY = bone.shearY; + applied.inherit = bone.inherit; } + // BOZO! - Reset the rest. // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. - Bone rootBone = getRootBone(); + BoneApplied rootBone = getRootBone().applied; float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; rootBone.worldX = pa * x + pb * y + parent.worldX; rootBone.worldY = pc * x + pd * y + parent.worldY; @@ -447,21 +504,25 @@ public class Skeleton { for (int i = 0, n = this.bones.size; i < n; i++) ((Bone)bones[i]).setToSetupPose(); - Object[] ikConstraints = this.ikConstraints.items; - for (int i = 0, n = this.ikConstraints.size; i < n; i++) - ((IkConstraint)ikConstraints[i]).setToSetupPose(); + Object[] constraints = sliders.items; + for (int i = 0, n = sliders.size; i < n; i++) + ((Slider)constraints[i]).setToSetupPose(); - Object[] transformConstraints = this.transformConstraints.items; - for (int i = 0, n = this.transformConstraints.size; i < n; i++) - ((TransformConstraint)transformConstraints[i]).setToSetupPose(); + constraints = ikConstraints.items; + for (int i = 0, n = ikConstraints.size; i < n; i++) + ((IkConstraint)constraints[i]).setToSetupPose(); - Object[] pathConstraints = this.pathConstraints.items; - for (int i = 0, n = this.pathConstraints.size; i < n; i++) - ((PathConstraint)pathConstraints[i]).setToSetupPose(); + constraints = transformConstraints.items; + for (int i = 0, n = transformConstraints.size; i < n; i++) + ((TransformConstraint)constraints[i]).setToSetupPose(); - Object[] physicsConstraints = this.physicsConstraints.items; - for (int i = 0, n = this.physicsConstraints.size; i < n; i++) - ((PhysicsConstraint)physicsConstraints[i]).setToSetupPose(); + constraints = pathConstraints.items; + for (int i = 0, n = pathConstraints.size; i < n; i++) + ((PathConstraint)constraints[i]).setToSetupPose(); + + constraints = physicsConstraints.items; + for (int i = 0, n = physicsConstraints.size; i < n; i++) + ((PhysicsConstraint)constraints[i]).setToSetupPose(); } /** Sets the slots and draw order to their setup pose values. */ @@ -617,6 +678,23 @@ public class Skeleton { slot.setAttachment(attachment); } + /** The skeleton's sliders. */ + public Array getSliders () { + return sliders; + } + + /** Finds a slider by comparing each slider's name. It is more efficient to cache the results of this method than to call it + * repeatedly. */ + public @Null Slider findSlider (String constraintName) { + if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); + Object[] sliders = this.sliders.items; + for (int i = 0, n = this.sliders.size; i < n; i++) { + var slider = (Slider)sliders[i]; + if (slider.data.name.equals(constraintName)) return slider; + } + return null; + } + /** The skeleton's IK constraints. */ public Array getIkConstraints () { return ikConstraints; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java index e11d7420a..21acc90ec 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonData.java @@ -44,6 +44,7 @@ public class SkeletonData { @Null Skin defaultSkin; final Array events = new Array(); final Array animations = new Array(); + final Array sliders = new Array(); final Array ikConstraints = new Array(); final Array transformConstraints = new Array(); final Array pathConstraints = new Array(); @@ -159,6 +160,25 @@ public class SkeletonData { return null; } + // --- Sliders + + /** The skeleton's sliders. */ + public Array getSliders () { + return sliders; + } + + /** Finds a slider by comparing each IK constraint's name. It is more efficient to cache the results of this method than to + * call it multiple times. */ + public @Null SliderData findSlider (String constraintName) { + if (constraintName == null) throw new IllegalArgumentException("constraintName cannot be null."); + Object[] sliders = this.sliders.items; + for (int i = 0, n = this.sliders.size; i < n; i++) { + var constraint = (SliderData)sliders[i]; + if (constraint.name.equals(constraintName)) return constraint; + } + return null; + } + // --- IK constraints /** The skeleton's IK constraints. */ diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java index 3348eff7b..28c6380d8 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java @@ -80,8 +80,8 @@ public class SkeletonRendererDebug { Gdx.gl.glBlendFunc(srcFunc, GL20.GL_ONE_MINUS_SRC_ALPHA); ShapeRenderer shapes = this.shapes; - Array bones = skeleton.getBones(); - Array slots = skeleton.getSlots(); + Array bones = skeleton.bones; + Array slots = skeleton.slots; shapes.begin(ShapeType.Filled); @@ -96,11 +96,12 @@ public class SkeletonRendererDebug { shapes.setColor(boneOriginColor); } else shapes.setColor(boneLineColor); - float x = length * bone.a + bone.worldX; - float y = length * bone.c + bone.worldY; - shapes.rectLine(bone.worldX, bone.worldY, x, y, width * scale); + BoneApplied applied = bone.applied; + float x = length * applied.a + applied.worldX; + float y = length * applied.c + applied.worldY; + shapes.rectLine(applied.worldX, applied.worldY, x, y, width * scale); } - shapes.x(skeleton.getX(), skeleton.getY(), 4 * scale); + shapes.x(skeleton.x, skeleton.y, 4 * scale); } if (drawPoints) { @@ -110,8 +111,8 @@ public class SkeletonRendererDebug { if (!slot.bone.active) continue; Attachment attachment = slot.attachment; if (!(attachment instanceof PointAttachment point)) continue; - point.computeWorldPosition(slot.getBone(), temp1); - temp2.set(8, 0).rotate(point.computeWorldRotation(slot.getBone())); + point.computeWorldPosition(slot.bone.applied, temp1); + temp2.set(8, 0).rotate(point.computeWorldRotation(slot.bone.applied)); shapes.rectLine(temp1, temp2, boneWidth / 2 * scale); } } @@ -244,7 +245,7 @@ public class SkeletonRendererDebug { for (int i = 0, n = bones.size; i < n; i++) { Bone bone = bones.get(i); if (!bone.active) continue; - shapes.circle(bone.worldX, bone.worldY, 3 * scale, 8); + shapes.circle(bone.applied.worldX, bone.applied.worldY, 3 * scale, 8); } } @@ -255,7 +256,7 @@ public class SkeletonRendererDebug { if (!slot.bone.active) continue; Attachment attachment = slot.attachment; if (!(attachment instanceof PointAttachment point)) continue; - point.computeWorldPosition(slot.getBone(), temp1); + point.computeWorldPosition(slot.bone.applied, temp1); shapes.circle(temp1.x, temp1.y, 3 * scale, 8); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java new file mode 100644 index 000000000..d3ce3997a --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +import com.esotericsoftware.spine.Animation.MixBlend; +import com.esotericsoftware.spine.Animation.MixDirection; +import com.esotericsoftware.spine.Skeleton.Physics; + +/** Stores the setup pose for a {@link PhysicsConstraint}. + *

+ * See Physics constraints in the Spine User Guide. */ +public class Slider implements Updatable { + final SliderData data; + final Skeleton skeleton; + Animation animation; + float time, mix; + + boolean active; + + public Slider (SliderData data, Skeleton skeleton) { + if (data == null) throw new IllegalArgumentException("data cannot be null."); + if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + + setToSetupPose(); + } + + /** Copy constructor. */ + public Slider (Slider slider, Skeleton skeleton) { + this(slider.data, skeleton); + setToSetupPose(); + } + + public void update (Physics physics) { + animation.apply(skeleton, time, time, false, null, mix, MixBlend.replace, MixDirection.in, true); + } + + public void setToSetupPose () { + SliderData data = this.data; + animation = data.animation; + time = data.time; + mix = data.mix; + } + + public boolean isActive () { + return true; + } + + public Animation getAnimation () { + return animation; + } + + public void setAnimation (Animation animation) { + this.animation = animation; + } + + public float getTime () { + return time; + } + + public void setTime (float time) { + this.time = time; + } + + public float getMix () { + return mix; + } + + public void setMix (float mix) { + this.mix = mix; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java new file mode 100644 index 000000000..321a11d62 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java @@ -0,0 +1,66 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +/** Stores the setup pose for a {@link PhysicsConstraint}. + *

+ * See Physics constraints in the Spine User Guide. */ +public class SliderData extends ConstraintData { + Animation animation; + float time, mix; + + public SliderData (String name) { + super(name); + } + + public Animation getAnimation () { + return animation; + } + + public void setAnimation (Animation animation) { + this.animation = animation; + } + + public float getTime () { + return time; + } + + public void setTime (float time) { + this.time = time; + } + + public float getMix () { + return mix; + } + + public void setMix (float mix) { + this.mix = mix; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java index 5b35f37e8..bc13a3065 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java @@ -44,20 +44,34 @@ import com.esotericsoftware.spine.attachments.VertexAttachment; public class Slot { final SlotData data; final Bone bone; - Color color = new Color(); + Slot applied; + + final Color color = new Color(); @Null final Color darkColor; @Null Attachment attachment; int sequenceIndex; - FloatArray deform = new FloatArray(); + FloatArray deform; int attachmentState; - public Slot (SlotData data, Bone bone) { - if (data == null) throw new IllegalArgumentException("data cannot be null."); - if (bone == null) throw new IllegalArgumentException("bone cannot be null."); + private Slot (SlotData data, Bone bone) { this.data = data; this.bone = bone; + darkColor = data.darkColor == null ? null : new Color(); + } + + public Slot (SlotData data, Skeleton skeleton) { + if (data == null) throw new IllegalArgumentException("data cannot be null."); + if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); + this.data = data; + this.bone = skeleton.bones.get(data.boneData.index); + + darkColor = data.darkColor == null ? null : new Color(); + deform = new FloatArray(); + + applied = new Slot(data, bone); + setToSetupPose(); } @@ -71,7 +85,7 @@ public class Slot { darkColor = slot.darkColor == null ? null : new Color(slot.darkColor); attachment = slot.attachment; sequenceIndex = slot.sequenceIndex; - deform.addAll(slot.deform); + deform = new FloatArray(slot.deform); } /** The slot's setup pose data. */ @@ -95,10 +109,6 @@ public class Slot { return color; } - public void setColor (Color color) { - this.color = color; - } - /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark * color's alpha is not used. */ public @Null Color getDarkColor () { @@ -158,6 +168,11 @@ public class Slot { } } + /** Returns the bone for applied pose. */ + public Slot getApplied () { + return applied; + } + public String toString () { return data.name; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index 8da1b1d2e..82e5534b4 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -31,8 +31,8 @@ package com.esotericsoftware.spine; import static com.badlogic.gdx.math.MathUtils.*; -import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.TransformConstraintData.FromProperty; @@ -44,12 +44,18 @@ import com.esotericsoftware.spine.TransformConstraintData.ToProperty; * See Transform constraints in the Spine User Guide. */ public class TransformConstraint implements Updatable { final TransformConstraintData data; - final Array bones; - Bone source; + final Array bones; + BoneApplied source; + TransformConstraint applied; + boolean active; + float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY; - boolean active; - final Vector2 temp = new Vector2(); + public TransformConstraint (TransformConstraintData data, Array bones, BoneApplied source) { + this.data = data; + this.bones = bones; + this.source = source; + } public TransformConstraint (TransformConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); @@ -58,9 +64,11 @@ public class TransformConstraint implements Updatable { bones = new Array(data.bones.size); for (BoneData boneData : data.bones) - bones.add(skeleton.bones.get(boneData.index)); + bones.add(skeleton.bones.get(boneData.index).applied); - source = skeleton.bones.get(data.source.index); + source = skeleton.bones.get(data.source.index).applied; + + applied = new TransformConstraint(data, bones, source); setToSetupPose(); } @@ -87,12 +95,12 @@ public class TransformConstraint implements Updatable { TransformConstraintData data = this.data; boolean localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp; - Bone source = this.source; + BoneApplied source = this.source; Object[] fromItems = data.properties.items; int fn = data.properties.size; Object[] bones = this.bones.items; for (int i = 0, n = this.bones.size; i < n; i++) { - var bone = (Bone)bones[i]; + var bone = (BoneApplied)bones[i]; for (int f = 0; f < fn; f++) { var from = (FromProperty)fromItems[f]; float value = from.value(data, source, localFrom) - from.offset; @@ -119,16 +127,16 @@ public class TransformConstraint implements Updatable { } /** The bones that will be modified by this transform constraint. */ - public Array getBones () { + public Array getBones () { return bones; } /** The bone whose world transform will be copied to the constrained bones. */ - public Bone getSource () { + public BoneApplied getSource () { return source; } - public void setSource (Bone source) { + public void setSource (BoneApplied source) { if (source == null) throw new IllegalArgumentException("source cannot be null."); this.source = source; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java index fefb1a483..17c5baebe 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java @@ -221,7 +221,7 @@ public class TransformConstraintData extends ConstraintData { public final Array to = new Array(); /** Reads this property from the specified bone. */ - abstract public float value (TransformConstraintData data, Bone source, boolean local); + abstract public float value (TransformConstraintData data, BoneApplied source, boolean local); } /** Constrained property for a {@link TransformConstraint}. */ @@ -239,12 +239,12 @@ public class TransformConstraintData extends ConstraintData { abstract public float mix (TransformConstraint constraint); /** Applies the value to this property. */ - abstract public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive); + abstract public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive); } static public class FromRotate extends FromProperty { - public float value (TransformConstraintData data, Bone source, boolean local) { - if (local) return source.arotation + data.offsetRotation; + public float value (TransformConstraintData data, BoneApplied source, boolean local) { + if (local) return source.rotation + data.offsetRotation; float value = atan2(source.c, source.a) * radDeg + (source.a * source.d - source.b * source.c > 0 ? data.offsetRotation : -data.offsetRotation); if (value < 0) value += 360; @@ -257,10 +257,10 @@ public class TransformConstraintData extends ConstraintData { return constraint.mixRotate; } - public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { - if (!additive) value -= bone.arotation; - bone.arotation += value * constraint.mixRotate; + if (!additive) value -= bone.rotation; + bone.rotation += value * constraint.mixRotate; } else { float a = bone.a, b = bone.b, c = bone.c, d = bone.d; value *= degRad; @@ -280,8 +280,8 @@ public class TransformConstraintData extends ConstraintData { } static public class FromX extends FromProperty { - public float value (TransformConstraintData data, Bone source, boolean local) { - return local ? source.ax + data.offsetX : data.offsetX * source.a + data.offsetY * source.b + source.worldX; + public float value (TransformConstraintData data, BoneApplied source, boolean local) { + return local ? source.x + data.offsetX : data.offsetX * source.a + data.offsetY * source.b + source.worldX; } } @@ -290,10 +290,10 @@ public class TransformConstraintData extends ConstraintData { return constraint.mixX; } - public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { - if (!additive) value -= bone.ax; - bone.ax += value * constraint.mixX; + if (!additive) value -= bone.x; + bone.x += value * constraint.mixX; } else { if (!additive) value -= bone.worldX; bone.worldX += value * constraint.mixX; @@ -302,8 +302,8 @@ public class TransformConstraintData extends ConstraintData { } static public class FromY extends FromProperty { - public float value (TransformConstraintData data, Bone source, boolean local) { - return local ? source.ay + data.offsetY : data.offsetX * source.c + data.offsetY * source.d + source.worldY; + public float value (TransformConstraintData data, BoneApplied source, boolean local) { + return local ? source.y + data.offsetY : data.offsetX * source.c + data.offsetY * source.d + source.worldY; } } @@ -312,10 +312,10 @@ public class TransformConstraintData extends ConstraintData { return constraint.mixY; } - public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { - if (!additive) value -= bone.ay; - bone.ay += value * constraint.mixY; + if (!additive) value -= bone.y; + bone.y += value * constraint.mixY; } else { if (!additive) value -= bone.worldY; bone.worldY += value * constraint.mixY; @@ -324,8 +324,8 @@ public class TransformConstraintData extends ConstraintData { } static public class FromScaleX extends FromProperty { - public float value (TransformConstraintData data, Bone source, boolean local) { - return (local ? source.ascaleX : (float)Math.sqrt(source.a * source.a + source.c * source.c)) + data.offsetScaleX; + public float value (TransformConstraintData data, BoneApplied source, boolean local) { + return (local ? source.scaleX : (float)Math.sqrt(source.a * source.a + source.c * source.c)) + data.offsetScaleX; } } @@ -334,12 +334,12 @@ public class TransformConstraintData extends ConstraintData { return constraint.mixScaleX; } - public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (additive) - bone.ascaleX *= 1 + ((value - 1) * constraint.mixScaleX); - else if (bone.ascaleX != 0) // - bone.ascaleX = 1 + (value / bone.ascaleX - 1) * constraint.mixScaleX; + bone.scaleX *= 1 + ((value - 1) * constraint.mixScaleX); + else if (bone.scaleX != 0) // + bone.scaleX = 1 + (value / bone.scaleX - 1) * constraint.mixScaleX; } else { float s; if (additive) @@ -355,8 +355,8 @@ public class TransformConstraintData extends ConstraintData { } static public class FromScaleY extends FromProperty { - public float value (TransformConstraintData data, Bone source, boolean local) { - return (local ? source.ascaleY : (float)Math.sqrt(source.b * source.b + source.d * source.d)) + data.offsetScaleY; + public float value (TransformConstraintData data, BoneApplied source, boolean local) { + return (local ? source.scaleY : (float)Math.sqrt(source.b * source.b + source.d * source.d)) + data.offsetScaleY; } } @@ -365,12 +365,12 @@ public class TransformConstraintData extends ConstraintData { return constraint.mixScaleY; } - public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (additive) - bone.ascaleY *= 1 + ((value - 1) * constraint.mixScaleY); - else if (bone.ascaleY != 0) // - bone.ascaleY = 1 + (value / bone.ascaleY - 1) * constraint.mixScaleY; + bone.scaleY *= 1 + ((value - 1) * constraint.mixScaleY); + else if (bone.scaleY != 0) // + bone.scaleY = 1 + (value / bone.scaleY - 1) * constraint.mixScaleY; } else { float s; if (additive) @@ -386,8 +386,8 @@ public class TransformConstraintData extends ConstraintData { } static public class FromShearY extends FromProperty { - public float value (TransformConstraintData data, Bone source, boolean local) { - return (local ? source.ashearY : (atan2(source.d, source.b) - atan2(source.c, source.a)) * radDeg - 90) + public float value (TransformConstraintData data, BoneApplied source, boolean local) { + return (local ? source.shearY : (atan2(source.d, source.b) - atan2(source.c, source.a)) * radDeg - 90) + data.offsetShearY; } } @@ -397,10 +397,10 @@ public class TransformConstraintData extends ConstraintData { return constraint.mixShearY; } - public void apply (TransformConstraint constraint, Bone bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { - if (!additive) value -= bone.ashearY; - bone.ashearY += value * constraint.mixShearY; + if (!additive) value -= bone.shearY; + bone.shearY += value * constraint.mixShearY; } else { float b = bone.b, d = bone.d, by = atan2(d, b); value = (value + 90) * degRad; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java index 87ffb217c..adaf3d05c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/PointAttachment.java @@ -34,7 +34,7 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; -import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BoneApplied; /** An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be * used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a @@ -90,13 +90,13 @@ public class PointAttachment extends Attachment { return color; } - public Vector2 computeWorldPosition (Bone bone, Vector2 point) { + public Vector2 computeWorldPosition (BoneApplied bone, Vector2 point) { point.x = x * bone.getA() + y * bone.getB() + bone.getWorldX(); point.y = x * bone.getC() + y * bone.getD() + bone.getWorldY(); return point; } - public float computeWorldRotation (Bone bone) { + public float computeWorldRotation (BoneApplied bone) { float r = rotation * degRad, cos = cos(r), sin = sin(r); float x = cos * bone.getA() + sin * bone.getB(); float y = cos * bone.getC() + sin * bone.getD(); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java index 381cc4d36..7ee8b85ad 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java @@ -37,6 +37,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BoneApplied; import com.esotericsoftware.spine.Slot; /** An attachment that displays a textured quadrilateral. @@ -179,7 +180,7 @@ public class RegionAttachment extends Attachment implements HasTextureRegion { if (sequence != null) sequence.apply(slot, this); float[] vertexOffset = this.offset; - Bone bone = slot.getBone(); + BoneApplied bone = slot.getBone().getApplied(); float x = bone.getWorldX(), y = bone.getWorldY(); float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); float offsetX, offsetY; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java index 7f69e3d2e..5d39629a1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java @@ -35,6 +35,7 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BoneApplied; import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.Slot; @@ -91,7 +92,7 @@ abstract public class VertexAttachment extends Attachment { int[] bones = this.bones; if (bones == null) { if (deformArray.size > 0) vertices = deformArray.items; - Bone bone = slot.getBone(); + BoneApplied bone = slot.getBone().getApplied(); float x = bone.getWorldX(), y = bone.getWorldY(); float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); for (int v = start, w = offset; w < count; v += 2, w += stride) { @@ -114,7 +115,7 @@ abstract public class VertexAttachment extends Attachment { int n = bones[v++]; n += v; for (; v < n; v++, b += 3) { - var bone = (Bone)skeletonBones[bones[v]]; + BoneApplied bone = ((Bone)skeletonBones[bones[v]]).getApplied(); float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight; wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight; @@ -129,7 +130,7 @@ abstract public class VertexAttachment extends Attachment { int n = bones[v++]; n += v; for (; v < n; v++, b += 3, f += 2) { - var bone = (Bone)skeletonBones[bones[v]]; + BoneApplied bone = ((Bone)skeletonBones[bones[v]]).getApplied(); float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight; wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java index 4b4f6a521..b88a788ac 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java @@ -41,7 +41,7 @@ public class SkeletonClipping { private final FloatArray clippingPolygon = new FloatArray(); private final FloatArray clipOutput = new FloatArray(128); private final FloatArray clippedVertices = new FloatArray(128); - private final FloatArray clippedUvs = new FloatArray(128); + private final FloatArray clippedUvs = new FloatArray(0); private final ShortArray clippedTriangles = new ShortArray(128); private final FloatArray scratch = new FloatArray(); @@ -459,7 +459,7 @@ public class SkeletonClipping { return clippedVertices; } - /** Only returns a non-empty array if clipTrianglesUnpacked() was used **/ + /** Returns an empty array unless {@link #clipTrianglesUnpacked(float[], int, short[], int, float[])} was used. **/ public FloatArray getClippedUvs () { return clippedUvs; } From cab6f73396f91cb4114ec26217420025ffe20579 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Sat, 12 Apr 2025 22:08:54 -0400 Subject: [PATCH 25/75] [libgdx] BonePose/Applied classes. --- .../com/esotericsoftware/spine/Animation.java | 170 +++++++++--------- .../src/com/esotericsoftware/spine/Bone.java | 124 ++----------- .../esotericsoftware/spine/BoneApplied.java | 46 ++--- .../com/esotericsoftware/spine/BoneData.java | 2 +- .../com/esotericsoftware/spine/BonePose.java | 145 +++++++++++++++ .../esotericsoftware/spine/IkConstraint.java | 30 ++-- .../spine/PathConstraint.java | 17 +- .../spine/PhysicsConstraint.java | 11 +- .../com/esotericsoftware/spine/Skeleton.java | 6 +- .../com/esotericsoftware/spine/Slider.java | 9 +- .../spine/TransformConstraint.java | 9 +- .../com/esotericsoftware/spine/Updatable.java | 9 - .../spine/attachments/RegionAttachment.java | 2 +- .../spine/attachments/VertexAttachment.java | 3 +- 14 files changed, 327 insertions(+), 256 deletions(-) create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 008bac261..647d63e7c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -544,7 +544,7 @@ public class Animation { } } - /** Changes a bone's local {@link Bone#getRotation()}. */ + /** Changes a bone's local {@link BonePose#getRotation()}. */ static public class RotateTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -560,15 +560,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.rotation = getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.rotation = getRelativeValue(time, alpha, blend, bone.rotation, pose.data.rotation); } } } - /** Changes a bone's local {@link Bone#getX()} and {@link Bone#getY()}. */ + /** Changes a bone's local {@link BonePose#getX()} and {@link BonePose#getY()}. */ static public class TranslateTimeline extends CurveTimeline2 implements BoneTimeline { final int boneIndex; @@ -586,20 +586,20 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (!bone.active) return; - if (appliedPose) bone = bone.applied; + Bone pose = skeleton.bones.get(boneIndex); + if (!pose.active) return; + BonePose bone = appliedPose ? pose.applied : pose; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - bone.x = bone.data.x; - bone.y = bone.data.y; + bone.x = pose.data.x; + bone.y = pose.data.y; return; case first: - bone.x += (bone.data.x - bone.x) * alpha; - bone.y += (bone.data.y - bone.y) * alpha; + bone.x += (pose.data.x - bone.x) * alpha; + bone.y += (pose.data.y - bone.y) * alpha; } return; } @@ -626,13 +626,13 @@ public class Animation { switch (blend) { case setup: - bone.x = bone.data.x + x * alpha; - bone.y = bone.data.y + y * alpha; + bone.x = pose.data.x + x * alpha; + bone.y = pose.data.y + y * alpha; break; case first: case replace: - bone.x += (bone.data.x + x - bone.x) * alpha; - bone.y += (bone.data.y + y - bone.y) * alpha; + bone.x += (pose.data.x + x - bone.x) * alpha; + bone.y += (pose.data.y + y - bone.y) * alpha; break; case add: bone.x += x * alpha; @@ -641,7 +641,7 @@ public class Animation { } } - /** Changes a bone's local {@link Bone#getX()}. */ + /** Changes a bone's local {@link BonePose#getX()}. */ static public class TranslateXTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -657,15 +657,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.x = getRelativeValue(time, alpha, blend, bone.x, bone.data.x); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.x = getRelativeValue(time, alpha, blend, bone.x, pose.data.x); } } } - /** Changes a bone's local {@link Bone#getY()}. */ + /** Changes a bone's local {@link BonePose#getY()}. */ static public class TranslateYTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -681,15 +681,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.y = getRelativeValue(time, alpha, blend, bone.y, bone.data.y); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.y = getRelativeValue(time, alpha, blend, bone.y, pose.data.y); } } } - /** Changes a bone's local {@link Bone#getScaleX()} and {@link Bone#getScaleY()}. */ + /** Changes a bone's local {@link BonePose#getScaleX()} and {@link BonePose#getScaleY()}. */ static public class ScaleTimeline extends CurveTimeline2 implements BoneTimeline { final int boneIndex; @@ -707,20 +707,20 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (!bone.active) return; - if (appliedPose) bone = bone.applied; + Bone pose = skeleton.bones.get(boneIndex); + if (!pose.active) return; + BonePose bone = appliedPose ? pose.applied : pose; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - bone.scaleX = bone.data.scaleX; - bone.scaleY = bone.data.scaleY; + bone.scaleX = pose.data.scaleX; + bone.scaleY = pose.data.scaleY; return; case first: - bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + bone.scaleX += (pose.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (pose.data.scaleY - bone.scaleY) * alpha; } return; } @@ -744,13 +744,13 @@ public class Animation { x = getBezierValue(time, i, VALUE1, curveType - BEZIER); y = getBezierValue(time, i, VALUE2, curveType + BEZIER_SIZE - BEZIER); } - x *= bone.data.scaleX; - y *= bone.data.scaleY; + x *= pose.data.scaleX; + y *= pose.data.scaleY; if (alpha == 1) { if (blend == add) { - bone.scaleX += x - bone.data.scaleX; - bone.scaleY += y - bone.data.scaleY; + bone.scaleX += x - pose.data.scaleX; + bone.scaleY += y - pose.data.scaleY; } else { bone.scaleX = x; bone.scaleY = y; @@ -761,8 +761,8 @@ public class Animation { if (direction == out) { switch (blend) { case setup: - bx = bone.data.scaleX; - by = bone.data.scaleY; + bx = pose.data.scaleX; + by = pose.data.scaleY; bone.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha; bone.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; break; @@ -774,14 +774,14 @@ public class Animation { bone.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; break; case add: - bone.scaleX += (x - bone.data.scaleX) * alpha; - bone.scaleY += (y - bone.data.scaleY) * alpha; + bone.scaleX += (x - pose.data.scaleX) * alpha; + bone.scaleY += (y - pose.data.scaleY) * alpha; } } else { switch (blend) { case setup: - bx = Math.abs(bone.data.scaleX) * Math.signum(x); - by = Math.abs(bone.data.scaleY) * Math.signum(y); + bx = Math.abs(pose.data.scaleX) * Math.signum(x); + by = Math.abs(pose.data.scaleY) * Math.signum(y); bone.scaleX = bx + (x - bx) * alpha; bone.scaleY = by + (y - by) * alpha; break; @@ -793,15 +793,15 @@ public class Animation { bone.scaleY = by + (y - by) * alpha; break; case add: - bone.scaleX += (x - bone.data.scaleX) * alpha; - bone.scaleY += (y - bone.data.scaleY) * alpha; + bone.scaleX += (x - pose.data.scaleX) * alpha; + bone.scaleY += (y - pose.data.scaleY) * alpha; } } } } } - /** Changes a bone's local {@link Bone#getScaleX()}. */ + /** Changes a bone's local {@link BonePose#getScaleX()}. */ static public class ScaleXTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -817,15 +817,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.scaleX = getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.scaleX = getScaleValue(time, alpha, blend, direction, bone.scaleX, pose.data.scaleX); } } } - /** Changes a bone's local {@link Bone#getScaleY()}. */ + /** Changes a bone's local {@link BonePose#getScaleY()}. */ static public class ScaleYTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -841,15 +841,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.scaleY = getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.scaleY = getScaleValue(time, alpha, blend, direction, bone.scaleY, pose.data.scaleY); } } } - /** Changes a bone's local {@link Bone#getShearX()} and {@link Bone#getShearY()}. */ + /** Changes a bone's local {@link BonePose#getShearX()} and {@link BonePose#getShearY()}. */ static public class ShearTimeline extends CurveTimeline2 implements BoneTimeline { final int boneIndex; @@ -867,20 +867,20 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (!bone.active) return; - if (appliedPose) bone = bone.applied; + Bone pose = skeleton.bones.get(boneIndex); + if (!pose.active) return; + BonePose bone = appliedPose ? pose.applied : pose; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - bone.shearX = bone.data.shearX; - bone.shearY = bone.data.shearY; + bone.shearX = pose.data.shearX; + bone.shearY = pose.data.shearY; return; case first: - bone.shearX += (bone.data.shearX - bone.shearX) * alpha; - bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + bone.shearX += (pose.data.shearX - bone.shearX) * alpha; + bone.shearY += (pose.data.shearY - bone.shearY) * alpha; } return; } @@ -907,13 +907,13 @@ public class Animation { switch (blend) { case setup: - bone.shearX = bone.data.shearX + x * alpha; - bone.shearY = bone.data.shearY + y * alpha; + bone.shearX = pose.data.shearX + x * alpha; + bone.shearY = pose.data.shearY + y * alpha; break; case first: case replace: - bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; - bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + bone.shearX += (pose.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (pose.data.shearY + y - bone.shearY) * alpha; break; case add: bone.shearX += x * alpha; @@ -922,7 +922,7 @@ public class Animation { } } - /** Changes a bone's local {@link Bone#getShearX()}. */ + /** Changes a bone's local {@link BonePose#getShearX()}. */ static public class ShearXTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -938,15 +938,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.shearX = getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.shearX = getRelativeValue(time, alpha, blend, bone.shearX, pose.data.shearX); } } } - /** Changes a bone's local {@link Bone#getShearY()}. */ + /** Changes a bone's local {@link BonePose#getShearY()}. */ static public class ShearYTimeline extends CurveTimeline1 implements BoneTimeline { final int boneIndex; @@ -962,15 +962,15 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (bone.active) { - if (appliedPose) bone = bone.applied; - bone.shearY = getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY); + Bone pose = skeleton.bones.get(boneIndex); + if (pose.active) { + BonePose bone = appliedPose ? pose.applied : pose; + bone.shearY = getRelativeValue(time, alpha, blend, bone.shearY, pose.data.shearY); } } } - /** Changes a bone's {@link Bone#getInherit()}. */ + /** Changes a bone's {@link BonePose#getInherit()}. */ static public class InheritTimeline extends Timeline implements BoneTimeline { static public final int ENTRIES = 2; static private final int INHERIT = 1; @@ -1002,18 +1002,18 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone bone = skeleton.bones.get(boneIndex); - if (!bone.active) return; - if (appliedPose) bone = bone.applied; + Bone pose = skeleton.bones.get(boneIndex); + if (!pose.active) return; + BonePose bone = appliedPose ? pose.applied : pose; if (direction == out) { - if (blend == setup) bone.inherit = bone.data.inherit; + if (blend == setup) bone.inherit = pose.data.inherit; return; } float[] frames = this.frames; if (time < frames[0]) { - if (blend == setup || blend == first) bone.inherit = bone.data.inherit; + if (blend == setup || blend == first) bone.inherit = pose.data.inherit; return; } bone.inherit = Inherit.values[(int)frames[search(frames, time, ENTRIES) + INHERIT]]; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index a55b32737..eb4a7ceb0 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -32,32 +32,20 @@ package com.esotericsoftware.spine; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.BoneData.Inherit; - /** Stores a bone's current pose. *

* A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a * constraint or application code modifies the world transform after it was computed from the local transform. */ -public class Bone { +public class Bone extends BonePose { final BoneData data; final Skeleton skeleton; @Null final Bone parent; final Array children; - BoneApplied applied; - - float x, y, rotation, scaleX, scaleY, shearX, shearY; - Inherit inherit; + final BoneApplied applied = new BoneApplied(this); boolean sorted, active; - Bone (Bone bone) { - this.data = bone.data; - this.skeleton = bone.skeleton; - this.parent = bone.parent; - this.children = bone.children; - } - public Bone (BoneData data, Skeleton skeleton, @Null Bone parent) { if (data == null) throw new IllegalArgumentException("data cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); @@ -66,27 +54,16 @@ public class Bone { this.parent = parent; children = new Array(); - applied = new BoneApplied(this); - setToSetupPose(); } /** Copy constructor. Does not copy the {@link #getChildren()} bones. */ public Bone (Bone bone, Skeleton skeleton, @Null Bone parent) { - if (bone == null) throw new IllegalArgumentException("bone cannot be null."); - if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); + super(bone); this.skeleton = skeleton; this.parent = parent; children = new Array(); data = bone.data; - x = bone.x; - y = bone.y; - rotation = bone.rotation; - scaleX = bone.scaleX; - scaleY = bone.scaleY; - shearX = bone.shearX; - shearY = bone.shearY; - inherit = bone.inherit; } /** Sets this bone's local transform to the setup pose. */ @@ -122,98 +99,17 @@ public class Bone { return children; } + /** Returns false when this bone won't be updated by + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#getSkin() active skin} does not contain this item. + * @see Skin#getBones() + * @see Skin#getConstraints() + * @see BoneData#getSkinRequired() + * @see Skeleton#updateCache() */ public boolean isActive () { return active; } - /** The local x translation. */ - public float getX () { - return x; - } - - public void setX (float x) { - this.x = x; - } - - /** The local y translation. */ - public float getY () { - return y; - } - - public void setY (float y) { - this.y = y; - } - - public void setPosition (float x, float y) { - this.x = x; - this.y = y; - } - - /** The local rotation in degrees, counter clockwise. */ - public float getRotation () { - return rotation; - } - - public void setRotation (float rotation) { - this.rotation = rotation; - } - - /** The local scaleX. */ - public float getScaleX () { - return scaleX; - } - - public void setScaleX (float scaleX) { - this.scaleX = scaleX; - } - - /** The local scaleY. */ - public float getScaleY () { - return scaleY; - } - - public void setScaleY (float scaleY) { - this.scaleY = scaleY; - } - - public void setScale (float scaleX, float scaleY) { - this.scaleX = scaleX; - this.scaleY = scaleY; - } - - public void setScale (float scale) { - scaleX = scale; - scaleY = scale; - } - - /** The local shearX. */ - public float getShearX () { - return shearX; - } - - public void setShearX (float shearX) { - this.shearX = shearX; - } - - /** The local shearY. */ - public float getShearY () { - return shearY; - } - - public void setShearY (float shearY) { - this.shearY = shearY; - } - - /** Determines how parent world transforms affect this bone. */ - public Inherit getInherit () { - return inherit; - } - - public void setInherit (Inherit inherit) { - if (inherit == null) throw new IllegalArgumentException("inherit cannot be null."); - this.inherit = inherit; - } - /** Returns the bone for applied pose. */ public BoneApplied getApplied () { return applied; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java index 43fff06ca..6195c5b2b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java @@ -11,21 +11,20 @@ import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.BoneData.Inherit; import com.esotericsoftware.spine.Skeleton.Physics; -public class BoneApplied extends Bone implements Updatable { +public class BoneApplied extends BonePose implements Updatable { final Bone pose; - @Null final BoneApplied parentApplied; + @Null final BoneApplied parent; float a, b, worldX; float c, d, worldY; BoneApplied (Bone bone) { - super(bone); pose = bone; - parentApplied = parent == null ? null : parent.applied; + parent = bone.parent == null ? null : bone.parent.applied; } /** Computes the world transform using the parent bone and this bone's local applied transform. */ public void updateWorldTransform () { - updateWorldTransform(); + update(null); } /** Computes the world transform using the parent bone and this bone's local transform. @@ -37,9 +36,10 @@ public class BoneApplied extends Bone implements Updatable { * See World transforms in the Spine * Runtimes Guide. */ public void update (Physics physics) { - BoneApplied parent = parentApplied; + Skeleton skeleton = pose.skeleton; + + BoneApplied parent = this.parent; if (parent == null) { // Root bone. - Skeleton skeleton = this.skeleton; float sx = skeleton.scaleX, sy = skeleton.scaleY; float rx = (rotation + shearX) * degRad; float ry = (rotation + 90 + shearY) * degRad; @@ -136,16 +136,18 @@ public class BoneApplied extends Bone implements Updatable { d *= skeleton.scaleY; } - /** Computes the applied transform values from the world transform. + /** Computes the local transform values from the world transform. *

* If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, 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 + * the local transform matches the world transform. The local 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 + * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ - public void updateAppliedTransform () { - BoneApplied parent = parentApplied; + public void updateLocalTransform () { + Skeleton skeleton = pose.skeleton; + + BoneApplied parent = this.parent; if (parent == null) { x = worldX - skeleton.x; y = worldY - skeleton.y; @@ -222,7 +224,7 @@ public class BoneApplied extends Bone implements Updatable { } } - /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + /** Part of the world transform matrix for the X axis. If changed, {@link #updateLocalTransform()} should be called. */ public float getA () { return a; } @@ -231,7 +233,7 @@ public class BoneApplied extends Bone implements Updatable { this.a = a; } - /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateLocalTransform()} should be called. */ public float getB () { return b; } @@ -240,7 +242,7 @@ public class BoneApplied extends Bone implements Updatable { this.b = b; } - /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + /** Part of the world transform matrix for the X axis. If changed, {@link #updateLocalTransform()} should be called. */ public float getC () { return c; } @@ -249,7 +251,7 @@ public class BoneApplied extends Bone implements Updatable { this.c = c; } - /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateLocalTransform()} should be called. */ public float getD () { return d; } @@ -258,7 +260,7 @@ public class BoneApplied extends Bone implements Updatable { this.d = d; } - /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ + /** The world X position. If changed, {@link #updateLocalTransform()} should be called. */ public float getWorldX () { return worldX; } @@ -267,7 +269,7 @@ public class BoneApplied extends Bone implements Updatable { this.worldX = worldX; } - /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ + /** The world Y position. If changed, {@link #updateLocalTransform()} should be called. */ public float getWorldY () { return worldY; } @@ -333,13 +335,13 @@ public class BoneApplied extends Bone implements Updatable { /** Transforms a point from world coordinates to the parent bone's local coordinates. */ public Vector2 worldToParent (Vector2 world) { if (world == null) throw new IllegalArgumentException("world cannot be null."); - return parent == null ? world : parentApplied.worldToLocal(world); + return parent == null ? world : parent.worldToLocal(world); } /** Transforms a point from the parent bone's coordinates to world coordinates. */ public Vector2 parentToWorld (Vector2 world) { if (world == null) throw new IllegalArgumentException("world cannot be null."); - return parent == null ? world : parentApplied.localToWorld(world); + return parent == null ? world : parent.localToWorld(world); } /** Transforms a world rotation to a local rotation. */ @@ -358,8 +360,8 @@ public class BoneApplied extends Bone implements Updatable { /** Rotates the world transform the specified amount. *

- * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and - * {@link #update(Physics)} will need to be called on any child bones, recursively. */ + * After changes are made to the world transform, {@link #updateLocalTransform()} should be called and {@link #update(Physics)} + * will need to be called on any child bones, recursively. */ public void rotateWorld (float degrees) { degrees *= degRad; float sin = sin(degrees), cos = cos(degrees); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java index 3790231d7..dd9eb9c36 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java @@ -34,7 +34,7 @@ import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Skeleton.Physics; -/** Stores the setup pose for a {@link Bone}. */ +/** Stores the setup pose for a {@link BonePose}. */ public class BoneData { final int index; final String name; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java new file mode 100644 index 000000000..0f1a70230 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java @@ -0,0 +1,145 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +import com.esotericsoftware.spine.BoneData.Inherit; + +/** Stores a bone's current pose. + *

+ * A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a + * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a + * constraint or application code modifies the world transform after it was computed from the local transform. */ +public class BonePose { + float x, y, rotation, scaleX, scaleY, shearX, shearY; + Inherit inherit; + + BonePose () { + } + + /** Copy constructor. */ + public BonePose (BonePose bone) { + x = bone.x; + y = bone.y; + rotation = bone.rotation; + scaleX = bone.scaleX; + scaleY = bone.scaleY; + shearX = bone.shearX; + shearY = bone.shearY; + inherit = bone.inherit; + } + + /** The local x translation. */ + public float getX () { + return x; + } + + public void setX (float x) { + this.x = x; + } + + /** The local y translation. */ + public float getY () { + return y; + } + + public void setY (float y) { + this.y = y; + } + + public void setPosition (float x, float y) { + this.x = x; + this.y = y; + } + + /** The local rotation in degrees, counter clockwise. */ + public float getRotation () { + return rotation; + } + + public void setRotation (float rotation) { + this.rotation = rotation; + } + + /** The local scaleX. */ + public float getScaleX () { + return scaleX; + } + + public void setScaleX (float scaleX) { + this.scaleX = scaleX; + } + + /** The local scaleY. */ + public float getScaleY () { + return scaleY; + } + + public void setScaleY (float scaleY) { + this.scaleY = scaleY; + } + + public void setScale (float scaleX, float scaleY) { + this.scaleX = scaleX; + this.scaleY = scaleY; + } + + public void setScale (float scale) { + scaleX = scale; + scaleY = scale; + } + + /** The local shearX. */ + public float getShearX () { + return shearX; + } + + public void setShearX (float shearX) { + this.shearX = shearX; + } + + /** The local shearY. */ + public float getShearY () { + return shearY; + } + + public void setShearY (float shearY) { + this.shearY = shearY; + } + + /** Determines how parent world transforms affect this bone. */ + public Inherit getInherit () { + return inherit; + } + + public void setInherit (Inherit inherit) { + if (inherit == null) throw new IllegalArgumentException("inherit cannot be null."); + this.inherit = inherit; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index 256637a5b..33ecfa55a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -107,7 +107,7 @@ public class IkConstraint implements Updatable { } /** The bone that is the IK target. */ - public Bone getTarget () { + public BoneApplied getTarget () { return target; } @@ -167,6 +167,13 @@ public class IkConstraint implements Updatable { this.stretch = stretch; } + /** Returns false when this constraint won't be updated by + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#getSkin() active skin} does not contain this item. + * @see Skin#getBones() + * @see Skin#getConstraints() + * @see ConstraintData#getSkinRequired() + * @see Skeleton#updateCache() */ public boolean isActive () { return active; } @@ -184,20 +191,21 @@ public class IkConstraint implements Updatable { static public void apply (BoneApplied bone, float targetX, float targetY, boolean compress, boolean stretch, boolean uniform, float alpha) { if (bone == null) throw new IllegalArgumentException("bone cannot be null."); - BoneApplied p = bone.parentApplied; + BoneApplied p = bone.parent; float pa = p.a, pb = p.b, pc = p.c, pd = p.d; float rotationIK = -bone.shearX - bone.rotation, tx, ty; switch (bone.inherit) { case onlyTranslation: - tx = (targetX - bone.worldX) * Math.signum(bone.skeleton.scaleX); - ty = (targetY - bone.worldY) * Math.signum(bone.skeleton.scaleY); + tx = (targetX - bone.worldX) * Math.signum(bone.pose.skeleton.scaleX); + ty = (targetY - bone.worldY) * Math.signum(bone.pose.skeleton.scaleY); break; case noRotationOrReflection: float s = Math.abs(pa * pd - pb * pc) / Math.max(0.0001f, pa * pa + pc * pc); - float sa = pa / bone.skeleton.scaleX; - float sc = pc / bone.skeleton.scaleY; - pb = -sc * s * bone.skeleton.scaleX; - pd = sa * s * bone.skeleton.scaleY; + Skeleton skeleton = bone.pose.skeleton; + float sa = pa / skeleton.scaleX; + float sc = pc / skeleton.scaleY; + pb = -sc * s * skeleton.scaleX; + pd = sa * s * skeleton.scaleY; rotationIK += atan2Deg(sc, sa); // Fall through. default: @@ -225,7 +233,7 @@ public class IkConstraint implements Updatable { ty = targetY - bone.worldY; } } - float b = bone.data.length * bone.scaleX; + float b = bone.pose.data.length * bone.scaleX; if (b > 0.0001f) { float dd = tx * tx + ty * ty; if ((compress && dd < b * b) || (stretch && dd > b * b)) { @@ -274,7 +282,7 @@ public class IkConstraint implements Updatable { cwx = a * child.x + b * child.y + parent.worldX; cwy = c * child.x + d * child.y + parent.worldY; } - BoneApplied pp = parent.parentApplied; + BoneApplied pp = parent.parent; a = pp.a; b = pp.b; c = pp.c; @@ -282,7 +290,7 @@ public class IkConstraint implements Updatable { float id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; id = Math.abs(id) <= 0.0001f ? 0 : 1 / id; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; - float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.pose.data.length * csx, a1, a2; if (l1 < 0.0001f) { apply(parent, targetX, targetY, false, stretch, false, alpha); child.rotation = 0; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index ba0f1ba7b..2a3f399e1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -119,7 +119,7 @@ public class PathConstraint implements Updatable { if (scale) { for (int i = 0, n = spacesCount - 1; i < n; i++) { var bone = (BoneApplied)bones[i]; - float setupLength = bone.data.length; + float setupLength = bone.pose.data.length; float x = setupLength * bone.a, y = setupLength * bone.c; lengths[i] = (float)Math.sqrt(x * x + y * y); } @@ -130,7 +130,7 @@ public class PathConstraint implements Updatable { float sum = 0; for (int i = 0, n = spacesCount - 1; i < n;) { var bone = (BoneApplied)bones[i]; - float setupLength = bone.data.length; + float setupLength = bone.pose.data.length; if (setupLength < epsilon) { if (scale) lengths[i] = 0; spaces[++i] = spacing; @@ -152,7 +152,7 @@ public class PathConstraint implements Updatable { boolean lengthSpacing = data.spacingMode == SpacingMode.length; for (int i = 0, n = spacesCount - 1; i < n;) { var bone = (BoneApplied)bones[i]; - float setupLength = bone.data.length; + float setupLength = bone.pose.data.length; if (setupLength < epsilon) { if (scale) lengths[i] = 0; spaces[++i] = spacing; @@ -203,7 +203,7 @@ public class PathConstraint implements Updatable { if (tip) { cos = cos(r); sin = sin(r); - float length = bone.data.length; + float length = bone.pose.data.length; boneX += (length * (cos * a - sin * c) - dx) * mixRotate; boneY += (length * (sin * a + cos * c) - dy) * mixRotate; } else @@ -220,7 +220,7 @@ public class PathConstraint implements Updatable { bone.c = sin * a + cos * c; bone.d = sin * b + cos * d; } - bone.updateAppliedTransform(); + bone.updateLocalTransform(); } } @@ -542,6 +542,13 @@ public class PathConstraint implements Updatable { this.slot = slot; } + /** Returns false when this constraint won't be updated by + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#getSkin() active skin} does not contain this item. + * @see Skin#getBones() + * @see Skin#getConstraints() + * @see ConstraintData#getSkinRequired() + * @see Skeleton#updateCache() */ public boolean isActive () { return active; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index 1f8feb3e1..6eef08afd 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -127,7 +127,7 @@ public class PhysicsConstraint implements Updatable { boolean x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0; BoneApplied bone = this.bone; - float l = bone.data.length; + float l = bone.pose.data.length; switch (physics) { case none: @@ -282,7 +282,7 @@ public class PhysicsConstraint implements Updatable { tx = l * bone.a; ty = l * bone.c; } - bone.updateAppliedTransform(); + bone.updateLocalTransform(); } /** The bone constrained by this physics constraint. */ @@ -351,6 +351,13 @@ public class PhysicsConstraint implements Updatable { this.mix = mix; } + /** Returns false when this constraint won't be updated by + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#getSkin() active skin} does not contain this item. + * @see Skin#getBones() + * @see Skin#getConstraints() + * @see ConstraintData#getSkinRequired() + * @see Skeleton#updateCache() */ public boolean isActive () { return active; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index e07d73978..462f78649 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -273,7 +273,7 @@ public class Skeleton { } private void sortIkConstraint (IkConstraint constraint) { - constraint.active = constraint.target.active + constraint.active = constraint.target.pose.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; @@ -297,7 +297,7 @@ public class Skeleton { } private void sortTransformConstraint (TransformConstraint constraint) { - constraint.active = constraint.source.active + constraint.active = constraint.source.pose.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; @@ -319,7 +319,7 @@ public class Skeleton { updateCache.add(constraint); for (int i = 0; i < boneCount; i++) - sortReset(((BoneApplied)constrained[i]).children); + sortReset(((BoneApplied)constrained[i]).pose.children); for (int i = 0; i < boneCount; i++) ((BoneApplied)constrained[i]).pose.sorted = true; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java index d3ce3997a..be1eb3a58 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java @@ -70,8 +70,15 @@ public class Slider implements Updatable { mix = data.mix; } + /** Returns false when this constraint won't be updated by + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#getSkin() active skin} does not contain this item. + * @see Skin#getBones() + * @see Skin#getConstraints() + * @see ConstraintData#getSkinRequired() + * @see Skeleton#updateCache() */ public boolean isActive () { - return true; + return active; } public Animation getAnimation () { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index 82e5534b4..daf1e921f 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -122,7 +122,7 @@ public class TransformConstraint implements Updatable { if (localTarget) bone.update(null); else - bone.updateAppliedTransform(); + bone.updateLocalTransform(); } } @@ -195,6 +195,13 @@ public class TransformConstraint implements Updatable { this.mixShearY = mixShearY; } + /** Returns false when this constraint won't be updated by + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#getSkin() active skin} does not contain this item. + * @see Skin#getBones() + * @see Skin#getConstraints() + * @see ConstraintData#getSkinRequired() + * @see Skeleton#updateCache() */ public boolean isActive () { return active; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java index 2efaa2c03..a1e9a584a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java @@ -35,13 +35,4 @@ import com.esotericsoftware.spine.Skeleton.Physics; public interface Updatable { /** @param physics Determines how physics and other non-deterministic updates are applied. */ public void update (Physics physics); - - /** Returns false when this item won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the - * {@link Skeleton#getSkin() active skin} does not contain this item. - * @see Skin#getBones() - * @see Skin#getConstraints() - * @see BoneData#getSkinRequired() - * @see ConstraintData#getSkinRequired() */ - public boolean isActive (); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java index 7ee8b85ad..bb0636fc6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java @@ -36,7 +36,7 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BonePose; import com.esotericsoftware.spine.BoneApplied; import com.esotericsoftware.spine.Slot; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java index 5d39629a1..1560b9b9e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java @@ -34,8 +34,9 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BonePose; import com.esotericsoftware.spine.BoneApplied; +import com.esotericsoftware.spine.Bone; import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.Slot; From 46c3583f763405da500d76b4ae086a4f2951cf91 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 14 Apr 2025 08:29:15 +0200 Subject: [PATCH 26/75] [godot] Up emscripten version --- .github/workflows/spine-godot-v4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spine-godot-v4.yml b/.github/workflows/spine-godot-v4.yml index 8a60a017c..7c8da6d2a 100644 --- a/.github/workflows/spine-godot-v4.yml +++ b/.github/workflows/spine-godot-v4.yml @@ -34,7 +34,7 @@ env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_EC2_METADATA_DISABLED: true - EM_VERSION: 3.1.26 + EM_VERSION: 3.1.64 GODOT_TAG: ${{ inputs.godot_tag }} GODOT_VERSION: ${{ inputs.godot_version }} GODOT_MONO: ${{ inputs.godot_mono }} From cab5944663b8c6007ce8c2fb2b466a3fe1d8b817 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Sun, 13 Apr 2025 22:40:28 -0400 Subject: [PATCH 27/75] [libgdx] SlotPose and other refactoring. --- .../com/esotericsoftware/spine/ActorTest.java | 1 - .../spine/AttachmentTimelineTests.java | 4 +- .../esotericsoftware/spine/BonePlotting.java | 3 +- .../esotericsoftware/spine/Box2DExample.java | 11 +- .../com/esotericsoftware/spine/FboTest.java | 1 - .../com/esotericsoftware/spine/IKTest.java | 5 +- .../spine/MixAndMatchTest.java | 2 - .../esotericsoftware/spine/NormalMapTest.java | 3 +- .../esotericsoftware/spine/PhysicsTest.java | 2 +- .../esotericsoftware/spine/PhysicsTest2.java | 1 - .../esotericsoftware/spine/PhysicsTest3.java | 2 +- .../esotericsoftware/spine/PhysicsTest4.java | 2 +- .../esotericsoftware/spine/PngExportTest.java | 1 - .../esotericsoftware/spine/SimpleTest1.java | 1 - .../esotericsoftware/spine/SimpleTest2.java | 5 +- .../esotericsoftware/spine/SimpleTest3.java | 2 - .../spine/SkeletonAssetManagerTest.java | 1 - .../spine/SkeletonAttachmentTest.java | 7 +- .../esotericsoftware/spine/TestHarness.java | 2 - .../spine/TimelineApiTest.java | 1 - .../com/esotericsoftware/spine/Animation.java | 255 +++++++++--------- .../spine/AnimationState.java | 13 +- .../src/com/esotericsoftware/spine/Bone.java | 50 ++-- .../esotericsoftware/spine/BoneApplied.java | 25 +- .../com/esotericsoftware/spine/BoneData.java | 100 +------ .../com/esotericsoftware/spine/BonePose.java | 10 +- .../spine/ConstraintData.java | 2 - .../esotericsoftware/spine/IkConstraint.java | 19 +- .../spine/PathConstraint.java | 20 +- .../com/esotericsoftware/spine/Physics.java | 17 ++ .../spine/PhysicsConstraint.java | 12 +- .../com/esotericsoftware/spine/Skeleton.java | 109 +++----- .../spine/SkeletonBounds.java | 2 +- .../spine/SkeletonRenderer.java | 17 +- .../spine/SkeletonRendererDebug.java | 20 +- .../src/com/esotericsoftware/spine/Skin.java | 2 +- .../com/esotericsoftware/spine/Slider.java | 9 +- .../src/com/esotericsoftware/spine/Slot.java | 135 ++-------- .../com/esotericsoftware/spine/SlotData.java | 4 +- .../com/esotericsoftware/spine/SlotPose.java | 111 ++++++++ .../spine/TransformConstraint.java | 10 +- .../com/esotericsoftware/spine/Updatable.java | 2 - .../spine/attachments/MeshAttachment.java | 2 +- .../spine/attachments/RegionAttachment.java | 5 +- .../spine/attachments/Sequence.java | 4 +- .../spine/attachments/VertexAttachment.java | 18 +- .../spine/utils/SkeletonActor.java | 2 +- .../spine/utils/SkeletonActorPool.java | 2 +- .../spine/utils/SkeletonDrawable.java | 2 +- .../spine/SkeletonViewer.java | 7 +- .../spine/SkeletonViewerUI.java | 8 +- 51 files changed, 463 insertions(+), 588 deletions(-) create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Physics.java create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/ActorTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/ActorTest.java index bd8139e4b..5d910f597 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/ActorTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/ActorTest.java @@ -37,7 +37,6 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.utils.viewport.ScreenViewport; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.SkeletonActor; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java index 0ab7dbf5e..f57bbc54d 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AttachmentTimelineTests.java @@ -92,8 +92,8 @@ public class AttachmentTimelineTests { private void test (float delta, Attachment attachment) { state.update(delta); state.apply(skeleton); - if (slot.getAttachment() != attachment) - throw new FailException("Wrong attachment: " + slot.getAttachment() + " != " + attachment); + if (slot.getPose().getAttachment() != attachment) + throw new FailException("Wrong attachment: " + slot.getPose().getAttachment() + " != " + attachment); } diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java index f642a6a93..d4ab28113 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/BonePlotting.java @@ -34,7 +34,6 @@ import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.Animation.MixDirection; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.attachments.AttachmentLoader; import com.esotericsoftware.spine.attachments.BoundingBoxAttachment; import com.esotericsoftware.spine.attachments.ClippingAttachment; @@ -76,7 +75,7 @@ public class BonePlotting { SkeletonData skeletonData = json.readSkeletonData(new FileHandle("assets/spineboy/spineboy-ess.json")); Skeleton skeleton = new Skeleton(skeletonData); - BoneApplied bone = skeleton.findBone("gun-tip").getApplied(); + BoneApplied bone = skeleton.findBone("gun-tip").getAppliedPose(); // Pose the skeleton at regular intervals throughout each animation. float fps = 1 / 15f; diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java index c1f174745..07f603ad0 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/Box2DExample.java @@ -54,7 +54,6 @@ import com.badlogic.gdx.utils.ScreenUtils; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.Animation.MixDirection; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.attachments.AtlasAttachmentLoader; import com.esotericsoftware.spine.attachments.RegionAttachment; import com.esotericsoftware.spine.attachments.Sequence; @@ -116,8 +115,8 @@ public class Box2DExample extends ApplicationAdapter { // Create a body for each attachment. Note it is probably better to create just a few bodies rather than one for each // region attachment, but this is just an example. for (Slot slot : skeleton.getSlots()) { - if (!(slot.getAttachment() instanceof Box2dAttachment)) continue; - Box2dAttachment attachment = (Box2dAttachment)slot.getAttachment(); + if (!(slot.getPose().getAttachment() instanceof Box2dAttachment)) continue; + Box2dAttachment attachment = (Box2dAttachment)slot.getPose().getAttachment(); PolygonShape boxPoly = new PolygonShape(); boxPoly.setAsBox(attachment.getWidth() / 2 * attachment.getScaleX(), attachment.getHeight() / 2 * attachment.getScaleY(), @@ -159,10 +158,10 @@ public class Box2DExample extends ApplicationAdapter { // Position the physics body for each attachment. for (Slot slot : skeleton.getSlots()) { - if (!(slot.getAttachment() instanceof Box2dAttachment)) continue; - Box2dAttachment attachment = (Box2dAttachment)slot.getAttachment(); + if (!(slot.getAppliedPose().getAttachment() instanceof Box2dAttachment)) continue; + Box2dAttachment attachment = (Box2dAttachment)slot.getAppliedPose().getAttachment(); if (attachment.body == null) continue; - BoneApplied bone = slot.getBone().getApplied(); + BoneApplied bone = slot.getBone().getAppliedPose(); float x = bone.getWorldX(); float y = bone.getWorldY(); float rotation = bone.getWorldRotationX(); diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/FboTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/FboTest.java index 23afdc9c2..3e91f629f 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/FboTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/FboTest.java @@ -42,7 +42,6 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.FrameBuffer; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates rendering an animation to a frame buffer (FBO) and then rendering the FBO to the screen. */ diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java index 2c7a04ff3..0eb5037dd 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/IKTest.java @@ -38,7 +38,6 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates how to let the target bone of an IK constraint follow the mouse or touch position, which in turn repositions part @@ -107,8 +106,8 @@ public class IKTest extends ApplicationAdapter { Bone crosshair = skeleton.findBone("crosshair"); // Should be cached. boneCoords.set(cameraCoords.x, cameraCoords.y); - crosshair.getParent().getApplied().worldToLocal(boneCoords); // camera space to local bone space - crosshair.setPosition(boneCoords.x, boneCoords.y); // override the crosshair position + crosshair.getParent().getAppliedPose().worldToLocal(boneCoords); // camera space to local bone space + crosshair.getPose().setPosition(boneCoords.x, boneCoords.y); // override the crosshair position // Calculate final world transform with the crosshair bone set to the mouse cursor position. Update physics this time. skeleton.updateWorldTransform(Physics.update); diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/MixAndMatchTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/MixAndMatchTest.java index c015ed395..68127135a 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/MixAndMatchTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/MixAndMatchTest.java @@ -37,8 +37,6 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; - /** Demonstrates creating and configuring a new skin at runtime. */ public class MixAndMatchTest extends ApplicationAdapter { OrthographicCamera camera; diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java index 031269d75..00375bb2c 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/NormalMapTest.java @@ -58,7 +58,6 @@ import com.badlogic.gdx.utils.ScreenUtils; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.Animation.MixDirection; -import com.esotericsoftware.spine.Skeleton.Physics; /** Demonstrates simplistic usage of lighting with normal maps. *

@@ -107,7 +106,7 @@ public class NormalMapTest extends ApplicationAdapter { if (animation == null) animation = skeletonData.getAnimations().first(); skeleton = new Skeleton(skeletonData); - skeleton.setToSetupPose(); + skeleton.setupPose(); skeleton = new Skeleton(skeleton); skeleton.setX(ui.prefs.getFloat("x", Gdx.graphics.getWidth() / 2)); skeleton.setY(ui.prefs.getFloat("y", Gdx.graphics.getHeight() / 4)); diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest.java index 578bd910f..164a14133 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest.java @@ -35,7 +35,7 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.esotericsoftware.spine.Skeleton.Physics; + import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates loading, animating, and rendering a skeleton. diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest2.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest2.java index aeb9673c3..d81cbcf21 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest2.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest2.java @@ -37,7 +37,6 @@ import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates loading, animating, and rendering a skeleton. diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest3.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest3.java index a2a6aa488..ee4a6ee46 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest3.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest3.java @@ -35,7 +35,7 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.esotericsoftware.spine.Skeleton.Physics; + import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates loading, animating, and rendering a skeleton. diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest4.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest4.java index 5264277a5..2f75efbc2 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest4.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PhysicsTest4.java @@ -35,7 +35,7 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.esotericsoftware.spine.Skeleton.Physics; + import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates loading, animating, and rendering a skeleton. diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java index 72f9276f8..f88d061ca 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/PngExportTest.java @@ -48,7 +48,6 @@ import com.badlogic.gdx.utils.ScreenUtils; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.Animation.MixDirection; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates rendering an animation to a frame buffer (FBO) and then writing each frame as a PNG. */ diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest1.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest1.java index 123f4d4e0..a775cbc41 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest1.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest1.java @@ -36,7 +36,6 @@ import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; /** Demonstrates loading, animating, and rendering a skeleton. diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java index a3562d8bb..cf4a667e2 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java @@ -41,7 +41,6 @@ import com.badlogic.gdx.math.Vector3; import com.esotericsoftware.spine.AnimationState.AnimationStateListener; import com.esotericsoftware.spine.AnimationState.TrackEntry; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.attachments.BoundingBoxAttachment; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; @@ -123,14 +122,14 @@ public class SimpleTest2 extends ApplicationAdapter { BoundingBoxAttachment hit = bounds.containsPoint(point.x, point.y); // Check if inside a bounding box. if (hit != null) { System.out.println("hit: " + hit); - skeleton.findSlot("head").getColor().set(Color.RED); // Turn head red until touchUp. + skeleton.findSlot("head").getPose().getColor().set(Color.RED); // Turn head red until touchUp. } } return true; } public boolean touchUp (int screenX, int screenY, int pointer, int button) { - skeleton.findSlot("head").getColor().set(Color.WHITE); + skeleton.findSlot("head").getPose().getColor().set(Color.WHITE); return true; } diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest3.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest3.java index 9a20f98dc..d32362cbf 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest3.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest3.java @@ -37,8 +37,6 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; - /** Demonstrates applying multiple animations at once using {@link AnimationState} tracks. */ public class SimpleTest3 extends ApplicationAdapter { OrthographicCamera camera; diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAssetManagerTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAssetManagerTest.java index 5a227e0c0..4a9fe4411 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAssetManagerTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAssetManagerTest.java @@ -38,7 +38,6 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.SkeletonDataLoader; import com.esotericsoftware.spine.utils.SkeletonDataLoader.SkeletonDataParameter; diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java index 0ed28cce7..07756192d 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SkeletonAttachmentTest.java @@ -37,7 +37,6 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.attachments.SkeletonAttachment; /** Demonstrates using {@link SkeletonAttachment} to use an entire skeleton as an attachment. */ @@ -77,7 +76,7 @@ public class SkeletonAttachmentTest extends ApplicationAdapter { SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal("goblins/goblins-pro.json")); goblin = new Skeleton(skeletonData); goblin.setSkin("goblin"); - goblin.setSlotsToSetupPose(); + goblin.setupPoseSlots(); goblinState = new AnimationState(new AnimationStateData(skeletonData)); goblinState.setAnimation(0, "walk", true); @@ -86,8 +85,8 @@ public class SkeletonAttachmentTest extends ApplicationAdapter { SkeletonAttachment skeletonAttachment = new SkeletonAttachment("goblin"); skeletonAttachment.setSkeleton(goblin); Slot slot = spineboy.findSlot("front-upper-arm"); - slot.setAttachment(skeletonAttachment); - attachmentBone = slot.getBone().getApplied(); + slot.getPose().setAttachment(skeletonAttachment); + attachmentBone = slot.getBone().getAppliedPose(); } } diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TestHarness.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TestHarness.java index 4741f80ba..a5b92125c 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TestHarness.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TestHarness.java @@ -39,8 +39,6 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.utils.ScreenUtils; -import com.esotericsoftware.spine.Skeleton.Physics; - /** Boilerplate for basic skeleton rendering, used for various testing. */ public class TestHarness extends ApplicationAdapter { static String JSON = "raptor/raptor-pro.json"; diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java index 4681c65f3..581530e52 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/TimelineApiTest.java @@ -39,7 +39,6 @@ import com.badlogic.gdx.utils.ScreenUtils; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.Animation.MixDirection; -import com.esotericsoftware.spine.Skeleton.Physics; /** Demonstrates using the timeline API. See {@link SimpleTest1} for a higher level API using {@link AnimationState}. *

diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 647d63e7c..15418d4ce 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -560,10 +560,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.rotation = getRelativeValue(time, alpha, blend, bone.rotation, pose.data.rotation); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, bone.data.rotation); } } } @@ -586,20 +586,20 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (!pose.active) return; - BonePose bone = appliedPose ? pose.applied : pose; + Bone bone = skeleton.bones.get(boneIndex); + if (!bone.active) return; + BonePose pose = appliedPose ? bone.applied : bone.pose; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - bone.x = pose.data.x; - bone.y = pose.data.y; + pose.x = bone.data.x; + pose.y = bone.data.y; return; case first: - bone.x += (pose.data.x - bone.x) * alpha; - bone.y += (pose.data.y - bone.y) * alpha; + pose.x += (bone.data.x - pose.x) * alpha; + pose.y += (bone.data.y - pose.y) * alpha; } return; } @@ -626,17 +626,17 @@ public class Animation { switch (blend) { case setup: - bone.x = pose.data.x + x * alpha; - bone.y = pose.data.y + y * alpha; + pose.x = bone.data.x + x * alpha; + pose.y = bone.data.y + y * alpha; break; case first: case replace: - bone.x += (pose.data.x + x - bone.x) * alpha; - bone.y += (pose.data.y + y - bone.y) * alpha; + pose.x += (bone.data.x + x - pose.x) * alpha; + pose.y += (bone.data.y + y - pose.y) * alpha; break; case add: - bone.x += x * alpha; - bone.y += y * alpha; + pose.x += x * alpha; + pose.y += y * alpha; } } } @@ -657,10 +657,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.x = getRelativeValue(time, alpha, blend, bone.x, pose.data.x); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.x = getRelativeValue(time, alpha, blend, pose.x, bone.data.x); } } } @@ -681,10 +681,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.y = getRelativeValue(time, alpha, blend, bone.y, pose.data.y); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.y = getRelativeValue(time, alpha, blend, pose.y, bone.data.y); } } } @@ -707,20 +707,20 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (!pose.active) return; - BonePose bone = appliedPose ? pose.applied : pose; + Bone bone = skeleton.bones.get(boneIndex); + if (!bone.active) return; + BonePose pose = appliedPose ? bone.applied : bone.pose; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - bone.scaleX = pose.data.scaleX; - bone.scaleY = pose.data.scaleY; + pose.scaleX = bone.data.scaleX; + pose.scaleY = bone.data.scaleY; return; case first: - bone.scaleX += (pose.data.scaleX - bone.scaleX) * alpha; - bone.scaleY += (pose.data.scaleY - bone.scaleY) * alpha; + pose.scaleX += (bone.data.scaleX - pose.scaleX) * alpha; + pose.scaleY += (bone.data.scaleY - pose.scaleY) * alpha; } return; } @@ -744,16 +744,16 @@ public class Animation { x = getBezierValue(time, i, VALUE1, curveType - BEZIER); y = getBezierValue(time, i, VALUE2, curveType + BEZIER_SIZE - BEZIER); } - x *= pose.data.scaleX; - y *= pose.data.scaleY; + x *= bone.data.scaleX; + y *= bone.data.scaleY; if (alpha == 1) { if (blend == add) { - bone.scaleX += x - pose.data.scaleX; - bone.scaleY += y - pose.data.scaleY; + pose.scaleX += x - bone.data.scaleX; + pose.scaleY += y - bone.data.scaleY; } else { - bone.scaleX = x; - bone.scaleY = y; + pose.scaleX = x; + pose.scaleY = y; } } else { // Mixing out uses sign of setup or current pose, else use sign of key. @@ -761,40 +761,40 @@ public class Animation { if (direction == out) { switch (blend) { case setup: - bx = pose.data.scaleX; - by = pose.data.scaleY; - bone.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha; - bone.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; + bx = bone.data.scaleX; + by = bone.data.scaleY; + pose.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha; + pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; break; case first: case replace: - bx = bone.scaleX; - by = bone.scaleY; - bone.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha; - bone.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; + bx = pose.scaleX; + by = pose.scaleY; + pose.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha; + pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; break; case add: - bone.scaleX += (x - pose.data.scaleX) * alpha; - bone.scaleY += (y - pose.data.scaleY) * alpha; + pose.scaleX += (x - bone.data.scaleX) * alpha; + pose.scaleY += (y - bone.data.scaleY) * alpha; } } else { switch (blend) { case setup: - bx = Math.abs(pose.data.scaleX) * Math.signum(x); - by = Math.abs(pose.data.scaleY) * Math.signum(y); - bone.scaleX = bx + (x - bx) * alpha; - bone.scaleY = by + (y - by) * alpha; + bx = Math.abs(bone.data.scaleX) * Math.signum(x); + by = Math.abs(bone.data.scaleY) * Math.signum(y); + pose.scaleX = bx + (x - bx) * alpha; + pose.scaleY = by + (y - by) * alpha; break; case first: case replace: - bx = Math.abs(bone.scaleX) * Math.signum(x); - by = Math.abs(bone.scaleY) * Math.signum(y); - bone.scaleX = bx + (x - bx) * alpha; - bone.scaleY = by + (y - by) * alpha; + bx = Math.abs(pose.scaleX) * Math.signum(x); + by = Math.abs(pose.scaleY) * Math.signum(y); + pose.scaleX = bx + (x - bx) * alpha; + pose.scaleY = by + (y - by) * alpha; break; case add: - bone.scaleX += (x - pose.data.scaleX) * alpha; - bone.scaleY += (y - pose.data.scaleY) * alpha; + pose.scaleX += (x - bone.data.scaleX) * alpha; + pose.scaleY += (y - bone.data.scaleY) * alpha; } } } @@ -817,10 +817,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.scaleX = getScaleValue(time, alpha, blend, direction, bone.scaleX, pose.data.scaleX); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, bone.data.scaleX); } } } @@ -841,10 +841,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.scaleY = getScaleValue(time, alpha, blend, direction, bone.scaleY, pose.data.scaleY); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, bone.data.scaleY); } } } @@ -867,20 +867,20 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (!pose.active) return; - BonePose bone = appliedPose ? pose.applied : pose; + Bone bone = skeleton.bones.get(boneIndex); + if (!bone.active) return; + BonePose pose = appliedPose ? bone.applied : bone.pose; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - bone.shearX = pose.data.shearX; - bone.shearY = pose.data.shearY; + pose.shearX = bone.data.shearX; + pose.shearY = bone.data.shearY; return; case first: - bone.shearX += (pose.data.shearX - bone.shearX) * alpha; - bone.shearY += (pose.data.shearY - bone.shearY) * alpha; + pose.shearX += (bone.data.shearX - pose.shearX) * alpha; + pose.shearY += (bone.data.shearY - pose.shearY) * alpha; } return; } @@ -907,17 +907,17 @@ public class Animation { switch (blend) { case setup: - bone.shearX = pose.data.shearX + x * alpha; - bone.shearY = pose.data.shearY + y * alpha; + pose.shearX = bone.data.shearX + x * alpha; + pose.shearY = bone.data.shearY + y * alpha; break; case first: case replace: - bone.shearX += (pose.data.shearX + x - bone.shearX) * alpha; - bone.shearY += (pose.data.shearY + y - bone.shearY) * alpha; + pose.shearX += (bone.data.shearX + x - pose.shearX) * alpha; + pose.shearY += (bone.data.shearY + y - pose.shearY) * alpha; break; case add: - bone.shearX += x * alpha; - bone.shearY += y * alpha; + pose.shearX += x * alpha; + pose.shearY += y * alpha; } } } @@ -938,10 +938,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.shearX = getRelativeValue(time, alpha, blend, bone.shearX, pose.data.shearX); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, bone.data.shearX); } } } @@ -962,10 +962,10 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (pose.active) { - BonePose bone = appliedPose ? pose.applied : pose; - bone.shearY = getRelativeValue(time, alpha, blend, bone.shearY, pose.data.shearY); + Bone bone = skeleton.bones.get(boneIndex); + if (bone.active) { + BonePose pose = appliedPose ? bone.applied : bone.pose; + pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, bone.data.shearY); } } } @@ -1002,25 +1002,25 @@ public class Animation { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array events, float alpha, MixBlend blend, MixDirection direction, boolean appliedPose) { - Bone pose = skeleton.bones.get(boneIndex); - if (!pose.active) return; - BonePose bone = appliedPose ? pose.applied : pose; + Bone bone = skeleton.bones.get(boneIndex); + if (!bone.active) return; + BonePose pose = appliedPose ? bone.applied : bone.pose; if (direction == out) { - if (blend == setup) bone.inherit = pose.data.inherit; + if (blend == setup) pose.inherit = bone.data.inherit; return; } float[] frames = this.frames; if (time < frames[0]) { - if (blend == setup || blend == first) bone.inherit = pose.data.inherit; + if (blend == setup || blend == first) pose.inherit = bone.data.inherit; return; } - bone.inherit = Inherit.values[(int)frames[search(frames, time, ENTRIES) + INHERIT]]; + pose.inherit = Inherit.values[(int)frames[search(frames, time, ENTRIES) + INHERIT]]; } } - /** Changes a slot's {@link Slot#getColor()}. */ + /** Changes a slot's {@link SlotPose#getColor()}. */ static public class RGBATimeline extends CurveTimeline implements SlotTimeline { static public final int ENTRIES = 5; static private final int R = 1, G = 2, B = 3, A = 4; @@ -1059,10 +1059,10 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; float[] frames = this.frames; - Color color = slot.color; + Color color = pose.color; if (time < frames[0]) { Color setup = slot.data.color; switch (blend) { @@ -1113,7 +1113,7 @@ public class Animation { } } - /** Changes the RGB for a slot's {@link Slot#getColor()}. */ + /** Changes the RGB for a slot's {@link SlotPose#getColor()}. */ static public class RGBTimeline extends CurveTimeline implements SlotTimeline { static public final int ENTRIES = 4; static private final int R = 1, G = 2, B = 3; @@ -1149,10 +1149,10 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; float[] frames = this.frames; - Color color = slot.color; + Color color = pose.color; if (time < frames[0]) { Color setup = slot.data.color; switch (blend) { @@ -1211,7 +1211,7 @@ public class Animation { } } - /** Changes the alpha for a slot's {@link Slot#getColor()}. */ + /** Changes the alpha for a slot's {@link SlotPose#getColor()}. */ static public class AlphaTimeline extends CurveTimeline1 implements SlotTimeline { final int slotIndex; @@ -1229,10 +1229,10 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; float[] frames = this.frames; - Color color = slot.color; + Color color = pose.color; if (time < frames[0]) { Color setup = slot.data.color; switch (blend) { @@ -1255,7 +1255,7 @@ public class Animation { } } - /** Changes a slot's {@link Slot#getColor()} and {@link Slot#getDarkColor()} for two color tinting. */ + /** Changes a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */ static public class RGBA2Timeline extends CurveTimeline implements SlotTimeline { static public final int ENTRIES = 8; static private final int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7; @@ -1275,7 +1275,7 @@ public class Animation { } /** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. The - * {@link Slot#getDarkColor()} must not be null. */ + * {@link SlotPose#getDarkColor()} must not be null. */ public int getSlotIndex () { return slotIndex; } @@ -1300,10 +1300,10 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; float[] frames = this.frames; - Color light = slot.color, dark = slot.darkColor; + Color light = pose.color, dark = pose.darkColor; if (time < frames[0]) { Color setupLight = slot.data.color, setupDark = slot.data.darkColor; switch (blend) { @@ -1384,7 +1384,7 @@ public class Animation { } } - /** Changes the RGB for a slot's {@link Slot#getColor()} and {@link Slot#getDarkColor()} for two color tinting. */ + /** Changes the RGB for a slot's {@link SlotPose#getColor()} and {@link SlotPose#getDarkColor()} for two color tinting. */ static public class RGB2Timeline extends CurveTimeline implements SlotTimeline { static public final int ENTRIES = 7; static private final int R = 1, G = 2, B = 3, R2 = 4, G2 = 5, B2 = 6; @@ -1403,7 +1403,7 @@ public class Animation { } /** The index of the slot in {@link Skeleton#getSlots()} that will be changed when this timeline is applied. The - * {@link Slot#getDarkColor()} must not be null. */ + * {@link SlotPose#getDarkColor()} must not be null. */ public int getSlotIndex () { return slotIndex; } @@ -1427,10 +1427,10 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; float[] frames = this.frames; - Color light = slot.color, dark = slot.darkColor; + Color light = pose.color, dark = pose.darkColor; if (time < frames[0]) { Color setupLight = slot.data.color, setupDark = slot.data.darkColor; switch (blend) { @@ -1516,7 +1516,7 @@ public class Animation { } } - /** Changes a slot's {@link Slot#getAttachment()}. */ + /** Changes a slot's {@link SlotPose#getAttachment()}. */ static public class AttachmentTimeline extends Timeline implements SlotTimeline { final int slotIndex; final String[] attachmentNames; @@ -1553,27 +1553,27 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; if (direction == out) { - if (blend == setup) setAttachment(skeleton, slot, slot.data.attachmentName); + if (blend == setup) setAttachment(skeleton, pose, slot.data.attachmentName); return; } if (time < this.frames[0]) { - if (blend == setup || blend == first) setAttachment(skeleton, slot, slot.data.attachmentName); + if (blend == setup || blend == first) setAttachment(skeleton, pose, slot.data.attachmentName); return; } - setAttachment(skeleton, slot, attachmentNames[search(this.frames, time)]); + setAttachment(skeleton, pose, attachmentNames[search(this.frames, time)]); } - private void setAttachment (Skeleton skeleton, Slot slot, String attachmentName) { - slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slotIndex, attachmentName)); + private void setAttachment (Skeleton skeleton, SlotPose pose, String attachmentName) { + pose.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slotIndex, attachmentName)); } } - /** Changes a slot's {@link Slot#getDeform()} to deform a {@link VertexAttachment}. */ + /** Changes a slot's {@link SlotPose#getDeform()} to deform a {@link VertexAttachment}. */ static public class DeformTimeline extends CurveTimeline implements SlotTimeline { final int slotIndex; final VertexAttachment attachment; @@ -1671,11 +1671,12 @@ public class Animation { MixDirection direction, boolean appliedPose) { Slot slot = skeleton.slots.get(slotIndex); - if (!slot.bone.active || !(slot.attachment instanceof VertexAttachment vertexAttachment) + if (!slot.bone.active) return; + SlotPose pose = appliedPose ? slot.applied : slot.pose; + if (!(pose.attachment instanceof VertexAttachment vertexAttachment) || vertexAttachment.getTimelineAttachment() != attachment) return; - if (appliedPose) slot = slot.applied; - FloatArray deformArray = slot.deform; + FloatArray deformArray = pose.deform; if (deformArray.size == 0) blend = setup; float[][] vertices = this.vertices; @@ -2612,7 +2613,7 @@ public class Animation { } } - /** Changes a slot's {@link Slot#getSequenceIndex()} for an attachment's {@link Sequence}. */ + /** Changes a slot's {@link SlotPose#getSequenceIndex()} for an attachment's {@link Sequence}. */ static public class SequenceTimeline extends Timeline implements SlotTimeline { static public final int ENTRIES = 3; static private final int MODE = 1, DELAY = 2; @@ -2654,9 +2655,9 @@ public class Animation { Slot slot = skeleton.slots.get(slotIndex); if (!slot.bone.active) return; - if (appliedPose) slot = slot.applied; + SlotPose pose = appliedPose ? slot.applied : slot.pose; - Attachment slotAttachment = slot.attachment; + Attachment slotAttachment = pose.attachment; if (slotAttachment != attachment) { if (!(slotAttachment instanceof VertexAttachment vertexAttachment) || vertexAttachment.getTimelineAttachment() != attachment) return; @@ -2665,13 +2666,13 @@ public class Animation { if (sequence == null) return; if (direction == out) { - if (blend == setup) slot.setSequenceIndex(-1); + if (blend == setup) pose.setSequenceIndex(-1); return; } float[] frames = this.frames; if (time < frames[0]) { - if (blend == setup || blend == first) slot.setSequenceIndex(-1); + if (blend == setup || blend == first) pose.setSequenceIndex(-1); return; } @@ -2709,7 +2710,7 @@ public class Animation { if (index >= count) index = n - index; } } - slot.setSequenceIndex(index); + pose.setSequenceIndex(index); } } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index 2f9335c70..35ded5575 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -278,7 +278,7 @@ public class AnimationState { var slot = (Slot)slots[i]; if (slot.attachmentState == setupState) { String attachmentName = slot.data.attachmentName; - slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + slot.getPose().setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); } } unkeyedState += 2; // Increasing after each use avoids the need to reset attachmentState for every slot. @@ -399,7 +399,7 @@ public class AnimationState { } private void setAttachment (Skeleton skeleton, Slot slot, String attachmentName, boolean attachments) { - slot.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + slot.getPose().setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); if (attachments) slot.attachmentState = unkeyedState + CURRENT; } @@ -417,21 +417,22 @@ public class AnimationState { Bone bone = skeleton.bones.get(timeline.boneIndex); if (!bone.active) return; + BonePose pose = bone.getPose(); float[] frames = timeline.frames; float r1, r2; if (time < frames[0]) { // Time is before first frame. switch (blend) { case setup: - bone.rotation = bone.data.rotation; + pose.rotation = bone.data.rotation; // Fall through. default: return; case first: - r1 = bone.rotation; + r1 = pose.rotation; r2 = bone.data.rotation; } } else { - r1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation; + r1 = blend == MixBlend.setup ? bone.data.rotation : pose.rotation; r2 = bone.data.rotation + timeline.getCurveValue(time); } @@ -465,7 +466,7 @@ public class AnimationState { timelinesRotation[i] = total; } timelinesRotation[i + 1] = diff; - bone.rotation = r1 + total * alpha; + pose.rotation = r1 + total * alpha; } private void queueEvents (TrackEntry entry, float animationTime) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index eb4a7ceb0..a85604bba 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -32,18 +32,19 @@ package com.esotericsoftware.spine; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Null; -/** Stores a bone's current pose. +// BOZO - Update javadocs. +/** The current pose for a bone, before constraints are applied. *

* A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a * constraint or application code modifies the world transform after it was computed from the local transform. */ -public class Bone extends BonePose { +public class Bone { final BoneData data; final Skeleton skeleton; @Null final Bone parent; - final Array children; + final Array children = new Array(); + final BonePose pose = new BonePose(); final BoneApplied applied = new BoneApplied(this); - boolean sorted, active; public Bone (BoneData data, Skeleton skeleton, @Null Bone parent) { @@ -52,31 +53,20 @@ public class Bone extends BonePose { this.data = data; this.skeleton = skeleton; this.parent = parent; - children = new Array(); - - setToSetupPose(); + setupPose(); } /** Copy constructor. Does not copy the {@link #getChildren()} bones. */ public Bone (Bone bone, Skeleton skeleton, @Null Bone parent) { - super(bone); + this.data = bone.data; this.skeleton = skeleton; this.parent = parent; - children = new Array(); - data = bone.data; + pose.set(bone.pose); } /** Sets this bone's local transform to the setup pose. */ - public void setToSetupPose () { - BoneData data = this.data; - x = data.x; - y = data.y; - rotation = data.rotation; - scaleX = data.scaleX; - scaleY = data.scaleY; - shearX = data.shearX; - shearY = data.shearY; - inherit = data.inherit; + public void setupPose () { + pose.set(data); } /** The bone's setup pose data. */ @@ -84,6 +74,16 @@ public class Bone extends BonePose { return data; } + /** Returns the bone's pose. */ + public BonePose getPose () { + return pose; + } + + /** Returns the bone's applied pose. */ + public BoneApplied getAppliedPose () { + return applied; + } + /** The skeleton this bone belongs to. */ public Skeleton getSkeleton () { return skeleton; @@ -99,9 +99,8 @@ public class Bone extends BonePose { return children; } - /** Returns false when this bone won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the - * {@link Skeleton#getSkin() active skin} does not contain this item. + /** Returns false when this bone won't be updated by {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} + * because a skin is required and the {@link Skeleton#getSkin() active skin} does not contain this item. * @see Skin#getBones() * @see Skin#getConstraints() * @see BoneData#getSkinRequired() @@ -110,11 +109,6 @@ public class Bone extends BonePose { return active; } - /** Returns the bone for applied pose. */ - public BoneApplied getApplied () { - return applied; - } - public String toString () { return data.name; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java index 6195c5b2b..f86947504 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java @@ -9,16 +9,17 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.BoneData.Inherit; -import com.esotericsoftware.spine.Skeleton.Physics; +/** The applied pose for a bone. This is the {@link Bone} pose with constraints applied and the world transform computed by + * {@link Skeleton#updateWorldTransform(Physics)}. */ public class BoneApplied extends BonePose implements Updatable { - final Bone pose; + final Bone bone; @Null final BoneApplied parent; float a, b, worldX; float c, d, worldY; BoneApplied (Bone bone) { - pose = bone; + this.bone = bone; parent = bone.parent == null ? null : bone.parent.applied; } @@ -36,10 +37,9 @@ public class BoneApplied extends BonePose implements Updatable { * See World transforms in the Spine * Runtimes Guide. */ public void update (Physics physics) { - Skeleton skeleton = pose.skeleton; - BoneApplied parent = this.parent; if (parent == null) { // Root bone. + Skeleton skeleton = bone.skeleton; float sx = skeleton.scaleX, sy = skeleton.scaleY; float rx = (rotation + shearX) * degRad; float ry = (rotation + 90 + shearY) * degRad; @@ -79,7 +79,7 @@ public class BoneApplied extends BonePose implements Updatable { d = sin(ry) * scaleY; } case noRotationOrReflection -> { - float sx = 1 / skeleton.scaleX, sy = 1 / skeleton.scaleY; + float sx = 1 / bone.skeleton.scaleX, sy = 1 / bone.skeleton.scaleY; pa *= sx; pc *= sy; float s = pa * pa + pc * pc, prx; @@ -105,6 +105,7 @@ public class BoneApplied extends BonePose implements Updatable { d = pc * lb + pd * ld; } case noScale, noScaleOrReflection -> { + Skeleton skeleton = bone.skeleton; rotation *= degRad; float cos = cos(rotation), sin = sin(rotation); float za = (pa * cos + pb * sin) / skeleton.scaleX; @@ -130,6 +131,7 @@ public class BoneApplied extends BonePose implements Updatable { d = zc * lb + zd * ld; } } + Skeleton skeleton = bone.skeleton; a *= skeleton.scaleX; b *= skeleton.scaleX; c *= skeleton.scaleY; @@ -145,12 +147,10 @@ public class BoneApplied extends BonePose implements Updatable { * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ public void updateLocalTransform () { - Skeleton skeleton = pose.skeleton; - BoneApplied parent = this.parent; if (parent == null) { - x = worldX - skeleton.x; - y = worldY - skeleton.y; + x = worldX - bone.skeleton.x; + y = worldY - bone.skeleton.y; float a = this.a, b = this.b, c = this.c, d = this.d; rotation = atan2Deg(c, a); scaleX = (float)Math.sqrt(a * a + c * c); @@ -174,6 +174,7 @@ public class BoneApplied extends BonePose implements Updatable { rc = c; rd = d; } else { + Skeleton skeleton = bone.skeleton; switch (inherit) { case noRotationOrReflection -> { float s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); @@ -371,4 +372,8 @@ public class BoneApplied extends BonePose implements Updatable { c = sin * ra + cos * c; d = sin * rb + cos * d; } + + public String toString () { + return bone.data.name; + } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java index dd9eb9c36..166be533b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java @@ -32,16 +32,12 @@ package com.esotericsoftware.spine; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.Skeleton.Physics; - -/** Stores the setup pose for a {@link BonePose}. */ -public class BoneData { +/** The setup pose for a bone. */ +public class BoneData extends BonePose { final int index; final String name; @Null final BoneData parent; float length; - float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY; - Inherit inherit = Inherit.normal; boolean skinRequired; // Nonessential. @@ -59,18 +55,11 @@ public class BoneData { /** Copy constructor. */ public BoneData (BoneData bone, @Null BoneData parent) { - if (bone == null) throw new IllegalArgumentException("bone cannot be null."); index = bone.index; name = bone.name; this.parent = parent; length = bone.length; - x = bone.x; - y = bone.y; - rotation = bone.rotation; - scaleX = bone.scaleX; - scaleY = bone.scaleY; - shearX = bone.shearX; - shearY = bone.shearY; + set(bone); } /** The index of the bone in {@link Skeleton#getBones()}. */ @@ -96,89 +85,6 @@ public class BoneData { this.length = length; } - /** The local x translation. */ - public float getX () { - return x; - } - - public void setX (float x) { - this.x = x; - } - - /** The local y translation. */ - public float getY () { - return y; - } - - public void setY (float y) { - this.y = y; - } - - public void setPosition (float x, float y) { - this.x = x; - this.y = y; - } - - /** The local rotation in degrees, counter clockwise. */ - public float getRotation () { - return rotation; - } - - public void setRotation (float rotation) { - this.rotation = rotation; - } - - /** The local scaleX. */ - public float getScaleX () { - return scaleX; - } - - public void setScaleX (float scaleX) { - this.scaleX = scaleX; - } - - /** The local scaleY. */ - public float getScaleY () { - return scaleY; - } - - public void setScaleY (float scaleY) { - this.scaleY = scaleY; - } - - public void setScale (float scaleX, float scaleY) { - this.scaleX = scaleX; - this.scaleY = scaleY; - } - - /** The local shearX. */ - public float getShearX () { - return shearX; - } - - public void setShearX (float shearX) { - this.shearX = shearX; - } - - /** The local shearX. */ - public float getShearY () { - return shearY; - } - - public void setShearY (float shearY) { - this.shearY = shearY; - } - - /** Determines how parent world transforms affect this bone. */ - public Inherit getInherit () { - return inherit; - } - - public void setInherit (Inherit inherit) { - if (inherit == null) throw new IllegalArgumentException("inherit cannot be null."); - this.inherit = inherit; - } - /** When true, {@link Skeleton#updateWorldTransform(Physics)} only updates this bone if the {@link Skeleton#getSkin()} contains * this bone. *

diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java index 0f1a70230..8d5b1e8fd 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java @@ -31,11 +31,7 @@ package com.esotericsoftware.spine; import com.esotericsoftware.spine.BoneData.Inherit; -/** Stores a bone's current pose. - *

- * A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a - * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a - * constraint or application code modifies the world transform after it was computed from the local transform. */ +/** Stores a bone's local pose. */ public class BonePose { float x, y, rotation, scaleX, scaleY, shearX, shearY; Inherit inherit; @@ -43,8 +39,8 @@ public class BonePose { BonePose () { } - /** Copy constructor. */ - public BonePose (BonePose bone) { + public void set (BonePose bone) { + if (bone == null) throw new IllegalArgumentException("bone cannot be null."); x = bone.x; y = bone.y; rotation = bone.rotation; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java index fd9a293aa..a0d99caa3 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/ConstraintData.java @@ -29,8 +29,6 @@ package com.esotericsoftware.spine; -import com.esotericsoftware.spine.Skeleton.Physics; - /** The base class for all constraint datas. */ abstract public class ConstraintData { final String name; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index 33ecfa55a..a53c35c6e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -34,7 +34,6 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; import com.badlogic.gdx.utils.Array; import com.esotericsoftware.spine.BoneData.Inherit; -import com.esotericsoftware.spine.Skeleton.Physics; /** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of * the last bone is as close to the target bone as possible. @@ -70,16 +69,16 @@ public class IkConstraint implements Updatable { applied = new IkConstraint(data, bones, target); - setToSetupPose(); + setupPose(); } /** Copy constructor. */ public IkConstraint (IkConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setToSetupPose(); + setupPose(); } - public void setToSetupPose () { + public void setupPose () { IkConstraintData data = this.data; mix = data.mix; softness = data.softness; @@ -168,7 +167,7 @@ public class IkConstraint implements Updatable { } /** Returns false when this constraint won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. * @see Skin#getBones() * @see Skin#getConstraints() @@ -196,12 +195,12 @@ public class IkConstraint implements Updatable { float rotationIK = -bone.shearX - bone.rotation, tx, ty; switch (bone.inherit) { case onlyTranslation: - tx = (targetX - bone.worldX) * Math.signum(bone.pose.skeleton.scaleX); - ty = (targetY - bone.worldY) * Math.signum(bone.pose.skeleton.scaleY); + tx = (targetX - bone.worldX) * Math.signum(bone.bone.skeleton.scaleX); + ty = (targetY - bone.worldY) * Math.signum(bone.bone.skeleton.scaleY); break; case noRotationOrReflection: float s = Math.abs(pa * pd - pb * pc) / Math.max(0.0001f, pa * pa + pc * pc); - Skeleton skeleton = bone.pose.skeleton; + Skeleton skeleton = bone.bone.skeleton; float sa = pa / skeleton.scaleX; float sc = pc / skeleton.scaleY; pb = -sc * s * skeleton.scaleX; @@ -233,7 +232,7 @@ public class IkConstraint implements Updatable { ty = targetY - bone.worldY; } } - float b = bone.pose.data.length * bone.scaleX; + float b = bone.bone.data.length * bone.scaleX; if (b > 0.0001f) { float dd = tx * tx + ty * ty; if ((compress && dd < b * b) || (stretch && dd > b * b)) { @@ -290,7 +289,7 @@ public class IkConstraint implements Updatable { float id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; id = Math.abs(id) <= 0.0001f ? 0 : 1 / id; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; - float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.pose.data.length * csx, a1, a2; + float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.bone.data.length * csx, a1, a2; if (l1 < 0.0001f) { apply(parent, targetX, targetY, false, stretch, false, alpha); child.rotation = 0; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index 2a3f399e1..cd6dc4239 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -35,12 +35,10 @@ import java.util.Arrays; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; -import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.PathConstraintData.PositionMode; import com.esotericsoftware.spine.PathConstraintData.RotateMode; import com.esotericsoftware.spine.PathConstraintData.SpacingMode; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.attachments.PathAttachment; /** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the @@ -82,16 +80,16 @@ public class PathConstraint implements Updatable { applied = new PathConstraint(data, bones, slot); - setToSetupPose(); + setupPose(); } /** Copy constructor. */ public PathConstraint (PathConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setToSetupPose(); + setupPose(); } - public void setToSetupPose () { + public void setupPose () { PathConstraintData data = this.data; position = data.position; spacing = data.spacing; @@ -102,7 +100,7 @@ public class PathConstraint implements Updatable { /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { - if (!(slot.attachment instanceof PathAttachment pathAttachment)) return; + if (!(slot.applied.attachment instanceof PathAttachment pathAttachment)) return; float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; if (mixRotate == 0 && mixX == 0 && mixY == 0) return; @@ -119,7 +117,7 @@ public class PathConstraint implements Updatable { if (scale) { for (int i = 0, n = spacesCount - 1; i < n; i++) { var bone = (BoneApplied)bones[i]; - float setupLength = bone.pose.data.length; + float setupLength = bone.bone.data.length; float x = setupLength * bone.a, y = setupLength * bone.c; lengths[i] = (float)Math.sqrt(x * x + y * y); } @@ -130,7 +128,7 @@ public class PathConstraint implements Updatable { float sum = 0; for (int i = 0, n = spacesCount - 1; i < n;) { var bone = (BoneApplied)bones[i]; - float setupLength = bone.pose.data.length; + float setupLength = bone.bone.data.length; if (setupLength < epsilon) { if (scale) lengths[i] = 0; spaces[++i] = spacing; @@ -152,7 +150,7 @@ public class PathConstraint implements Updatable { boolean lengthSpacing = data.spacingMode == SpacingMode.length; for (int i = 0, n = spacesCount - 1; i < n;) { var bone = (BoneApplied)bones[i]; - float setupLength = bone.pose.data.length; + float setupLength = bone.bone.data.length; if (setupLength < epsilon) { if (scale) lengths[i] = 0; spaces[++i] = spacing; @@ -203,7 +201,7 @@ public class PathConstraint implements Updatable { if (tip) { cos = cos(r); sin = sin(r); - float length = bone.pose.data.length; + float length = bone.bone.data.length; boneX += (length * (cos * a - sin * c) - dx) * mixRotate; boneY += (length * (sin * a + cos * c) - dy) * mixRotate; } else @@ -543,7 +541,7 @@ public class PathConstraint implements Updatable { } /** Returns false when this constraint won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. * @see Skin#getBones() * @see Skin#getConstraints() diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Physics.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Physics.java new file mode 100644 index 000000000..7759e888d --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Physics.java @@ -0,0 +1,17 @@ + +package com.esotericsoftware.spine; + +/** Determines how physics and other non-deterministic updates are applied. */ +public enum Physics { + /** Physics are not updated or applied. */ + none, + + /** Physics are reset to the current pose. */ + reset, + + /** Physics are updated and the pose from physics is applied. */ + update, + + /** Physics are not updated but the pose from physics is applied. */ + pose +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index 6eef08afd..09a0ebcd5 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -31,8 +31,6 @@ package com.esotericsoftware.spine; import static com.esotericsoftware.spine.utils.SpineUtils.*; -import com.esotericsoftware.spine.Skeleton.Physics; - /** Stores the current pose for a physics constraint. A physics constraint applies physics to bones. *

* See Physics constraints in the Spine User Guide. */ @@ -69,13 +67,13 @@ public class PhysicsConstraint implements Updatable { applied = new PhysicsConstraint(data, skeleton, bone); - setToSetupPose(); + setupPose(); } /** Copy constructor. */ public PhysicsConstraint (PhysicsConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setToSetupPose(); + setupPose(); } public void reset () { @@ -92,7 +90,7 @@ public class PhysicsConstraint implements Updatable { scaleVelocity = 0; } - public void setToSetupPose () { + public void setupPose () { PhysicsConstraintData data = this.data; inertia = data.inertia; strength = data.strength; @@ -127,7 +125,7 @@ public class PhysicsConstraint implements Updatable { boolean x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0; BoneApplied bone = this.bone; - float l = bone.pose.data.length; + float l = bone.bone.data.length; switch (physics) { case none: @@ -352,7 +350,7 @@ public class PhysicsConstraint implements Updatable { } /** Returns false when this constraint won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. * @see Skin#getBones() * @see Skin#getConstraints() diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 462f78649..13d7e39cb 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -273,20 +273,20 @@ public class Skeleton { } private void sortIkConstraint (IkConstraint constraint) { - constraint.active = constraint.target.pose.active + constraint.active = constraint.target.bone.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; - sortBone(constraint.target.pose); + sortBone(constraint.target.bone); Array constrained = constraint.bones; - Bone parent = constrained.first().pose; + Bone parent = constrained.first().bone; sortBone(parent); if (constrained.size == 1) { updateCache.add(constraint); sortReset(parent.children); } else { - Bone child = constrained.peek().pose; + Bone child = constrained.peek().bone; sortBone(child); updateCache.add(constraint); @@ -297,31 +297,31 @@ public class Skeleton { } private void sortTransformConstraint (TransformConstraint constraint) { - constraint.active = constraint.source.pose.active + constraint.active = constraint.source.bone.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; - sortBone(constraint.source.pose); + sortBone(constraint.source.bone); Object[] constrained = constraint.bones.items; int boneCount = constraint.bones.size; if (constraint.data.localSource) { for (int i = 0; i < boneCount; i++) { - Bone child = ((BoneApplied)constrained[i]).pose; + Bone child = ((BoneApplied)constrained[i]).bone; sortBone(child.parent); sortBone(child); } } else { for (int i = 0; i < boneCount; i++) - sortBone(((BoneApplied)constrained[i]).pose); + sortBone(((BoneApplied)constrained[i]).bone); } updateCache.add(constraint); for (int i = 0; i < boneCount; i++) - sortReset(((BoneApplied)constrained[i]).pose.children); + sortReset(((BoneApplied)constrained[i]).bone.children); for (int i = 0; i < boneCount; i++) - ((BoneApplied)constrained[i]).pose.sorted = true; + ((BoneApplied)constrained[i]).bone.sorted = true; } private void sortPathConstraint (PathConstraint constraint) { @@ -336,12 +336,12 @@ public class Skeleton { if (data.defaultSkin != null && data.defaultSkin != skin) sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); - sortPathConstraintAttachment(slot.attachment, slotBone); + sortPathConstraintAttachment(slot.pose.attachment, slotBone); Object[] constrained = constraint.bones.items; int boneCount = constraint.bones.size; for (int i = 0; i < boneCount; i++) - sortBone(((BoneApplied)constrained[i]).pose); + sortBone(((BoneApplied)constrained[i]).bone); updateCache.add(constraint); @@ -370,13 +370,13 @@ public class Skeleton { int nn = pathBones[i++]; nn += i; while (i < nn) - sortBone(((BoneApplied)bones[pathBones[i++]]).pose); + sortBone(((BoneApplied)bones[pathBones[i++]]).bone); } } } private void sortPhysicsConstraint (PhysicsConstraint constraint) { - Bone bone = constraint.bone.pose; + Bone bone = constraint.bone.bone; constraint.active = bone.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; @@ -415,27 +415,12 @@ public class Skeleton { Object[] bones = this.bones.items; for (int i = 0, n = this.bones.size; i < n; i++) { var bone = (Bone)bones[i]; - if (!bone.active) continue; - BoneApplied applied = bone.applied; - applied.x = bone.x; - applied.y = bone.y; - applied.rotation = bone.rotation; - applied.scaleX = bone.scaleX; - applied.scaleY = bone.scaleY; - applied.shearX = bone.shearX; - applied.shearY = bone.shearY; - applied.inherit = bone.inherit; + if (bone.active) bone.applied.set(bone.pose); } Object[] slots = this.slots.items; for (int i = 0, n = this.slots.size; i < n; i++) { var slot = (Slot)slots[i]; - if (!slot.bone.active) continue; - Slot applied = slot.applied; - applied.color.set(slot.color); - if (applied.darkColor != null) applied.darkColor.set(slot.darkColor); - applied.attachment = slot.attachment; - applied.sequenceIndex = slot.sequenceIndex; - applied.deform = slot.deform; + if (slot.bone.active) slot.applied.set(slot.pose); } // BOZO! - Reset the rest. @@ -455,15 +440,7 @@ public class Skeleton { Object[] bones = this.bones.items; for (int i = 1, n = this.bones.size; i < n; i++) { // Skip root bone. var bone = (Bone)bones[i]; - BoneApplied applied = bone.applied; - applied.x = bone.x; - applied.y = bone.y; - applied.rotation = bone.rotation; - applied.scaleX = bone.scaleX; - applied.scaleY = bone.scaleY; - applied.shearX = bone.shearX; - applied.shearY = bone.shearY; - applied.inherit = bone.inherit; + if (bone.active) bone.applied.set(bone.pose); } // BOZO! - Reset the rest. @@ -493,45 +470,45 @@ public class Skeleton { } /** Sets the bones, constraints, slots, and draw order to their setup pose values. */ - public void setToSetupPose () { - setBonesToSetupPose(); - setSlotsToSetupPose(); + public void setupPose () { + setupPoseBones(); + setupPoseSlots(); } /** Sets the bones and constraints to their setup pose values. */ - public void setBonesToSetupPose () { + public void setupPoseBones () { Object[] bones = this.bones.items; for (int i = 0, n = this.bones.size; i < n; i++) - ((Bone)bones[i]).setToSetupPose(); + ((Bone)bones[i]).setupPose(); Object[] constraints = sliders.items; for (int i = 0, n = sliders.size; i < n; i++) - ((Slider)constraints[i]).setToSetupPose(); + ((Slider)constraints[i]).setupPose(); constraints = ikConstraints.items; for (int i = 0, n = ikConstraints.size; i < n; i++) - ((IkConstraint)constraints[i]).setToSetupPose(); + ((IkConstraint)constraints[i]).setupPose(); constraints = transformConstraints.items; for (int i = 0, n = transformConstraints.size; i < n; i++) - ((TransformConstraint)constraints[i]).setToSetupPose(); + ((TransformConstraint)constraints[i]).setupPose(); constraints = pathConstraints.items; for (int i = 0, n = pathConstraints.size; i < n; i++) - ((PathConstraint)constraints[i]).setToSetupPose(); + ((PathConstraint)constraints[i]).setupPose(); constraints = physicsConstraints.items; for (int i = 0, n = physicsConstraints.size; i < n; i++) - ((PhysicsConstraint)constraints[i]).setToSetupPose(); + ((PhysicsConstraint)constraints[i]).setupPose(); } /** Sets the slots and draw order to their setup pose values. */ - public void setSlotsToSetupPose () { + public void setupPoseSlots () { Object[] slots = this.slots.items; int n = this.slots.size; arraycopy(slots, 0, drawOrder.items, 0, n); for (int i = 0; i < n; i++) - ((Slot)slots[i]).setToSetupPose(); + ((Slot)slots[i]).setupPose(); } /** The skeleton's setup pose data. */ @@ -614,9 +591,8 @@ public class Skeleton { * old skin, each slot's setup mode attachment is attached from the new skin. *

* After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling - * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply(Skeleton)} is called before the next time the - * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new - * skin. */ + * {@link #setupPoseSlots()}. Also, often {@link AnimationState#apply(Skeleton)} is called before the next time the skeleton is + * rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. */ public void setSkin (@Null Skin newSkin) { if (newSkin == skin) return; if (newSkin != null) { @@ -629,7 +605,7 @@ public class Skeleton { String name = slot.data.attachmentName; if (name != null) { Attachment attachment = newSkin.getAttachment(i, name); - if (attachment != null) slot.setAttachment(attachment); + if (attachment != null) slot.pose.setAttachment(attachment); } } } @@ -663,7 +639,7 @@ public class Skeleton { } /** A convenience method to set an attachment by finding the slot with {@link #findSlot(String)}, finding the attachment with - * {@link #getAttachment(int, String)}, then setting the slot's {@link Slot#attachment}. + * {@link #getAttachment(int, String)}, then setting the slot's {@link SlotPose#attachment}. * @param attachmentName May be null to clear the slot's attachment. */ public void setAttachment (String slotName, @Null String attachmentName) { if (slotName == null) throw new IllegalArgumentException("slotName cannot be null."); @@ -675,7 +651,7 @@ public class Skeleton { if (attachment == null) throw new IllegalArgumentException("Attachment not found: " + attachmentName + ", for slot: " + slotName); } - slot.setAttachment(attachment); + slot.pose.setAttachment(attachment); } /** The skeleton's sliders. */ @@ -789,7 +765,7 @@ public class Skeleton { int verticesLength = 0; float[] vertices = null; short[] triangles = null; - Attachment attachment = slot.attachment; + Attachment attachment = slot.pose.attachment; if (attachment instanceof RegionAttachment region) { verticesLength = 8; vertices = temp.setSize(8); @@ -933,19 +909,4 @@ public class Skeleton { public String toString () { return data.name != null ? data.name : super.toString(); } - - /** Determines how physics and other non-deterministic updates are applied. */ - static public enum Physics { - /** Physics are not updated or applied. */ - none, - - /** Physics are reset to the current pose. */ - reset, - - /** Physics are updated and the pose from physics is applied. */ - update, - - /** Physics are not updated but the pose from physics is applied. */ - pose - } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java index 5a6bf6794..c382b3cb0 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBounds.java @@ -67,7 +67,7 @@ public class SkeletonBounds { for (int i = 0; i < slotCount; i++) { var slot = (Slot)slots[i]; if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; + Attachment attachment = slot.applied.attachment; if (attachment instanceof BoundingBoxAttachment boundingBox) { boundingBoxes.add(boundingBox); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java index c0bab40fd..8dd6eacd8 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java @@ -80,10 +80,11 @@ public class SkeletonRenderer { for (int i = 0, n = skeleton.drawOrder.size; i < n; i++) { var slot = (Slot)drawOrder[i]; if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; + SlotPose pose = slot.getAppliedPose(); + Attachment attachment = pose.attachment; if (attachment instanceof RegionAttachment region) { region.computeWorldVertices(slot, vertices, 0, 5); - Color color = region.getColor(), slotColor = slot.getColor(); + Color color = region.getColor(), slotColor = pose.getColor(); float alpha = a * slotColor.a * color.a * 255; float multiplier = pmaColors ? alpha : 255; @@ -148,8 +149,9 @@ public class SkeletonRenderer { clipper.clipEnd(slot); continue; } + SlotPose pose = slot.getAppliedPose(); Texture texture = null; - Attachment attachment = slot.attachment; + Attachment attachment = pose.attachment; if (attachment instanceof RegionAttachment region) { verticesLength = 20; vertices = this.vertices.items; @@ -179,7 +181,7 @@ public class SkeletonRenderer { } if (texture != null) { - Color slotColor = slot.getColor(); + Color slotColor = pose.getColor(); float alpha = a * slotColor.a * color.a * 255; float multiplier = pmaColors ? alpha : 255; @@ -242,8 +244,9 @@ public class SkeletonRenderer { clipper.clipEnd(slot); continue; } + SlotPose pose = slot.getAppliedPose(); Texture texture = null; - Attachment attachment = slot.attachment; + Attachment attachment = pose.attachment; if (attachment instanceof RegionAttachment region) { verticesLength = 24; vertices = this.vertices.items; @@ -273,7 +276,7 @@ public class SkeletonRenderer { } if (texture != null) { - Color lightColor = slot.getColor(); + Color lightColor = pose.getColor(); float alpha = a * lightColor.a * color.a * 255; float multiplier = pmaColors ? alpha : 255; @@ -294,7 +297,7 @@ public class SkeletonRenderer { | (int)(blue * lightColor.b) << 16 // | (int)(green * lightColor.g) << 8 // | (int)(red * lightColor.r)); - Color darkColor = slot.getDarkColor(); + Color darkColor = pose.getDarkColor(); float dark = darkColor == null ? 0 : NumberUtils.intToFloatColor((int)(blue * darkColor.b) << 16 // | (int)(green * darkColor.g) << 8 // diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java index 28c6380d8..5b345a9e2 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRendererDebug.java @@ -38,7 +38,6 @@ import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; -import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.BoundingBoxAttachment; import com.esotericsoftware.spine.attachments.ClippingAttachment; import com.esotericsoftware.spine.attachments.MeshAttachment; @@ -109,8 +108,7 @@ public class SkeletonRendererDebug { for (int i = 0, n = slots.size; i < n; i++) { Slot slot = slots.get(i); if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; - if (!(attachment instanceof PointAttachment point)) continue; + if (!(slot.applied.attachment instanceof PointAttachment point)) continue; point.computeWorldPosition(slot.bone.applied, temp1); temp2.set(8, 0).rotate(point.computeWorldRotation(slot.bone.applied)); shapes.rectLine(temp1, temp2, boneWidth / 2 * scale); @@ -125,8 +123,7 @@ public class SkeletonRendererDebug { for (int i = 0, n = slots.size; i < n; i++) { Slot slot = slots.get(i); if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; - if (attachment instanceof RegionAttachment region) { + if (slot.pose.attachment instanceof RegionAttachment region) { float[] vertices = this.vertices.items; region.computeWorldVertices(slot, vertices, 0, 2); shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]); @@ -141,8 +138,7 @@ public class SkeletonRendererDebug { for (int i = 0, n = slots.size; i < n; i++) { Slot slot = slots.get(i); if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; - if (!(attachment instanceof MeshAttachment mesh)) continue; + if (!(slot.pose.attachment instanceof MeshAttachment mesh)) continue; float[] vertices = this.vertices.setSize(mesh.getWorldVerticesLength()); mesh.computeWorldVertices(slot, 0, mesh.getWorldVerticesLength(), vertices, 0, 2); short[] triangles = mesh.getTriangles(); @@ -188,8 +184,7 @@ public class SkeletonRendererDebug { for (int i = 0, n = slots.size; i < n; i++) { Slot slot = slots.get(i); if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; - if (!(attachment instanceof ClippingAttachment clip)) continue; + if (!(slot.pose.attachment instanceof ClippingAttachment clip)) continue; int nn = clip.getWorldVerticesLength(); float[] vertices = this.vertices.setSize(nn); clip.computeWorldVertices(slot, 0, nn, vertices, 0, 2); @@ -204,8 +199,7 @@ public class SkeletonRendererDebug { for (int i = 0, n = slots.size; i < n; i++) { Slot slot = slots.get(i); if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; - if (!(attachment instanceof PathAttachment path)) continue; + if (!(slot.pose.attachment instanceof PathAttachment path)) continue; int nn = path.getWorldVerticesLength(); float[] vertices = this.vertices.setSize(nn); path.computeWorldVertices(slot, 0, nn, vertices, 0, 2); @@ -254,15 +248,13 @@ public class SkeletonRendererDebug { for (int i = 0, n = slots.size; i < n; i++) { Slot slot = slots.get(i); if (!slot.bone.active) continue; - Attachment attachment = slot.attachment; - if (!(attachment instanceof PointAttachment point)) continue; + if (!(slot.pose.attachment instanceof PointAttachment point)) continue; point.computeWorldPosition(slot.bone.applied, temp1); shapes.circle(temp1.x, temp1.y, 3 * scale, 8); } } shapes.end(); - } public ShapeRenderer getShapeRenderer () { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java index 8a62a01ed..e49c80c95 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java @@ -157,7 +157,7 @@ public class Skin { Object[] slots = skeleton.slots.items; for (SkinEntry entry : oldSkin.attachments.orderedItems()) { int slotIndex = entry.slotIndex; - var slot = (Slot)slots[slotIndex]; + SlotPose slot = ((Slot)slots[slotIndex]).getPose(); if (slot.attachment == entry.attachment) { Attachment attachment = getAttachment(slotIndex, entry.name); if (attachment != null) slot.setAttachment(attachment); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java index be1eb3a58..f1912ab49 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java @@ -31,7 +31,6 @@ package com.esotericsoftware.spine; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.Animation.MixDirection; -import com.esotericsoftware.spine.Skeleton.Physics; /** Stores the setup pose for a {@link PhysicsConstraint}. *

@@ -50,20 +49,20 @@ public class Slider implements Updatable { this.data = data; this.skeleton = skeleton; - setToSetupPose(); + setupPose(); } /** Copy constructor. */ public Slider (Slider slider, Skeleton skeleton) { this(slider.data, skeleton); - setToSetupPose(); + setupPose(); } public void update (Physics physics) { animation.apply(skeleton, time, time, false, null, mix, MixBlend.replace, MixDirection.in, true); } - public void setToSetupPose () { + public void setupPose () { SliderData data = this.data; animation = data.animation; time = data.time; @@ -71,7 +70,7 @@ public class Slider implements Updatable { } /** Returns false when this constraint won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. * @see Skin#getBones() * @see Skin#getConstraints() diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java index bc13a3065..46dbd4931 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java @@ -30,13 +30,6 @@ package com.esotericsoftware.spine; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.utils.FloatArray; -import com.badlogic.gdx.utils.Null; - -import com.esotericsoftware.spine.Animation.DeformTimeline; -import com.esotericsoftware.spine.attachments.Attachment; -import com.esotericsoftware.spine.attachments.Sequence; -import com.esotericsoftware.spine.attachments.VertexAttachment; /** Stores a slot's current pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store * state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared @@ -44,35 +37,19 @@ import com.esotericsoftware.spine.attachments.VertexAttachment; public class Slot { final SlotData data; final Bone bone; - Slot applied; - - final Color color = new Color(); - @Null final Color darkColor; - @Null Attachment attachment; - int sequenceIndex; - FloatArray deform; - + final SlotPose pose = new SlotPose(), applied = new SlotPose(); int attachmentState; - private Slot (SlotData data, Bone bone) { - this.data = data; - this.bone = bone; - - darkColor = data.darkColor == null ? null : new Color(); - } - public Slot (SlotData data, Skeleton skeleton) { - if (data == null) throw new IllegalArgumentException("data cannot be null."); + if (data == null) throw new IllegalArgumentException("slot cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); this.data = data; - this.bone = skeleton.bones.get(data.boneData.index); - - darkColor = data.darkColor == null ? null : new Color(); - deform = new FloatArray(); - - applied = new Slot(data, bone); - - setToSetupPose(); + bone = skeleton.bones.get(data.boneData.index); + if (data.darkColor != null) { + pose.darkColor = new Color(); + applied.darkColor = new Color(); + } + setupPose(); } /** Copy constructor. */ @@ -81,11 +58,17 @@ public class Slot { if (bone == null) throw new IllegalArgumentException("bone cannot be null."); data = slot.data; this.bone = bone; - color.set(slot.color); - darkColor = slot.darkColor == null ? null : new Color(slot.darkColor); - attachment = slot.attachment; - sequenceIndex = slot.sequenceIndex; - deform = new FloatArray(slot.deform); + if (data.darkColor != null) { + pose.darkColor = new Color(); + applied.darkColor = new Color(); + } + pose.set(slot.pose); + } + + /** Sets this slot to the setup pose. */ + public void setupPose () { + pose.set(data); + if (data.attachmentName != null) pose.setAttachment(bone.skeleton.getAttachment(data.index, data.attachmentName)); } /** The slot's setup pose data. */ @@ -93,6 +76,16 @@ public class Slot { return data; } + /** Returns the slot's pose. */ + public SlotPose getPose () { + return pose; + } + + /** Returns the slot's applied pose. */ + public SlotPose getAppliedPose () { + return applied; + } + /** The bone this slot belongs to. */ public Bone getBone () { return bone; @@ -103,76 +96,6 @@ public class Slot { return bone.skeleton; } - /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two - * color tinting. */ - public Color getColor () { - return color; - } - - /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark - * color's alpha is not used. */ - public @Null Color getDarkColor () { - return darkColor; - } - - /** The current attachment for the slot, or null if the slot has no attachment. */ - public @Null Attachment getAttachment () { - return attachment; - } - - /** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}. - * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the - * specified attachment. */ - public void setAttachment (@Null Attachment attachment) { - if (this.attachment == attachment) return; - if (!(attachment instanceof VertexAttachment newAttachment) || !(this.attachment instanceof VertexAttachment oldAttachment) - || newAttachment.getTimelineAttachment() != oldAttachment.getTimelineAttachment()) { - deform.clear(); - } - this.attachment = attachment; - sequenceIndex = -1; - } - - /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the - * {@link Sequence#getSetupIndex()}. */ - public int getSequenceIndex () { - return sequenceIndex; - } - - public void setSequenceIndex (int sequenceIndex) { - this.sequenceIndex = sequenceIndex; - } - - /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a - * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. - *

- * See {@link VertexAttachment#computeWorldVertices(Slot, int, int, float[], int, int)} and {@link DeformTimeline}. */ - public FloatArray getDeform () { - return deform; - } - - public void setDeform (FloatArray deform) { - if (deform == null) throw new IllegalArgumentException("deform cannot be null."); - this.deform = deform; - } - - /** Sets this slot to the setup pose. */ - public void setToSetupPose () { - color.set(data.color); - if (darkColor != null) darkColor.set(data.darkColor); - if (data.attachmentName == null) - setAttachment(null); - else { - attachment = null; - setAttachment(bone.skeleton.getAttachment(data.index, data.attachmentName)); - } - } - - /** Returns the bone for applied pose. */ - public Slot getApplied () { - return applied; - } - public String toString () { return data.name; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java index e21752e0d..c7707e19a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java @@ -33,12 +33,10 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Null; /** Stores the setup pose for a {@link Slot}. */ -public class SlotData { +public class SlotData extends SlotPose { final int index; final String name; final BoneData boneData; - final Color color = new Color(1, 1, 1, 1); - @Null Color darkColor; @Null String attachmentName; BlendMode blendMode; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java new file mode 100644 index 000000000..ab4264c82 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.utils.FloatArray; +import com.badlogic.gdx.utils.Null; + +import com.esotericsoftware.spine.Animation.DeformTimeline; +import com.esotericsoftware.spine.attachments.Attachment; +import com.esotericsoftware.spine.attachments.Sequence; +import com.esotericsoftware.spine.attachments.VertexAttachment; + +/** Stores a slot's pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store state + * for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared across + * multiple skeletons. */ +public class SlotPose { + final Color color = new Color(); + @Null Color darkColor; + @Null Attachment attachment; + int sequenceIndex; + final FloatArray deform = new FloatArray(0); + + SlotPose () { + } + + public void set (SlotPose slot) { + if (slot == null) throw new IllegalArgumentException("slot cannot be null."); + color.set(slot.color); + if (slot.darkColor != null) darkColor.set(slot.darkColor); + attachment = slot.attachment; + sequenceIndex = slot.sequenceIndex; + deform.size = 0; + deform.addAll(slot.deform); + } + + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + public Color getColor () { + return color; + } + + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + public @Null Color getDarkColor () { + return darkColor; + } + + /** The current attachment for the slot, or null if the slot has no attachment. */ + public @Null Attachment getAttachment () { + return attachment; + } + + /** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}. + * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the + * specified attachment. */ + public void setAttachment (@Null Attachment attachment) { + if (this.attachment == attachment) return; + if (!(attachment instanceof VertexAttachment newAttachment) || !(this.attachment instanceof VertexAttachment oldAttachment) + || newAttachment.getTimelineAttachment() != oldAttachment.getTimelineAttachment()) { + deform.clear(); + } + this.attachment = attachment; + sequenceIndex = -1; + } + + /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the + * {@link Sequence#getSetupIndex()}. */ + public int getSequenceIndex () { + return sequenceIndex; + } + + public void setSequenceIndex (int sequenceIndex) { + this.sequenceIndex = sequenceIndex; + } + + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + *

+ * See {@link VertexAttachment#computeWorldVertices(Slot, int, int, float[], int, int)} and {@link DeformTimeline}. */ + public FloatArray getDeform () { + return deform; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index daf1e921f..813eb1688 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -32,9 +32,7 @@ package com.esotericsoftware.spine; import static com.badlogic.gdx.math.MathUtils.*; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.TransformConstraintData.FromProperty; import com.esotericsoftware.spine.TransformConstraintData.ToProperty; @@ -70,16 +68,16 @@ public class TransformConstraint implements Updatable { applied = new TransformConstraint(data, bones, source); - setToSetupPose(); + setupPose(); } /** Copy constructor. */ public TransformConstraint (TransformConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setToSetupPose(); + setupPose(); } - public void setToSetupPose () { + public void setupPose () { TransformConstraintData data = this.data; mixRotate = data.mixRotate; mixX = data.mixX; @@ -196,7 +194,7 @@ public class TransformConstraint implements Updatable { } /** Returns false when this constraint won't be updated by - * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Skeleton.Physics)} because a skin is required and the + * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. * @see Skin#getBones() * @see Skin#getConstraints() diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java index a1e9a584a..0864002f2 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java @@ -29,8 +29,6 @@ package com.esotericsoftware.spine; -import com.esotericsoftware.spine.Skeleton.Physics; - /** The interface for items updated by {@link Skeleton#updateWorldTransform(Physics)}. */ public interface Updatable { /** @param physics Determines how physics and other non-deterministic updates are applied. */ diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java index 49ebc5b16..dda206ff0 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/MeshAttachment.java @@ -165,7 +165,7 @@ public class MeshAttachment extends VertexAttachment implements HasTextureRegion /** If the attachment has a {@link #sequence}, the region may be changed. */ public void computeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset, int stride) { - if (sequence != null) sequence.apply(slot, this); + if (sequence != null) sequence.apply(slot.getAppliedPose(), this); super.computeWorldVertices(slot, start, count, worldVertices, offset, stride); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java index bb0636fc6..6bf813813 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/RegionAttachment.java @@ -36,7 +36,6 @@ import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.BonePose; import com.esotericsoftware.spine.BoneApplied; import com.esotericsoftware.spine.Slot; @@ -177,10 +176,10 @@ public class RegionAttachment extends Attachment implements HasTextureRegion { * @param offset The worldVertices index to begin writing values. * @param stride The number of worldVertices entries between the value pairs written. */ public void computeWorldVertices (Slot slot, float[] worldVertices, int offset, int stride) { - if (sequence != null) sequence.apply(slot, this); + if (sequence != null) sequence.apply(slot.getAppliedPose(), this); float[] vertexOffset = this.offset; - BoneApplied bone = slot.getBone().getApplied(); + BoneApplied bone = slot.getBone().getAppliedPose(); float x = bone.getWorldX(), y = bone.getWorldY(); float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); float offsetX, offsetY; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Sequence.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Sequence.java index e82f9429f..ba9db38b5 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Sequence.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/Sequence.java @@ -33,7 +33,7 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.esotericsoftware.spine.Slot; +import com.esotericsoftware.spine.SlotPose; public class Sequence { static private int nextID; @@ -56,7 +56,7 @@ public class Sequence { setupIndex = other.setupIndex; } - public void apply (Slot slot, HasTextureRegion attachment) { + public void apply (SlotPose slot, HasTextureRegion attachment) { int index = slot.getSequenceIndex(); if (index == -1) index = setupIndex; if (index >= regions.length) index = regions.length - 1; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java index 1560b9b9e..1789cf1ca 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/attachments/VertexAttachment.java @@ -34,14 +34,14 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; -import com.esotericsoftware.spine.BonePose; -import com.esotericsoftware.spine.BoneApplied; import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BoneApplied; import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.Slot; +import com.esotericsoftware.spine.SlotPose; /** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's - * {@link Slot#getDeform()}. */ + * {@link SlotPose#getDeform()}. */ abstract public class VertexAttachment extends Attachment { static private int nextID; @@ -75,8 +75,8 @@ abstract public class VertexAttachment extends Attachment { worldVerticesLength = other.worldVerticesLength; } - /** Transforms the attachment's local {@link #getVertices()} to world coordinates. If the slot's {@link Slot#getDeform()} is - * not empty, it is used to deform the vertices. + /** Transforms the attachment's local {@link #getVertices()} to world coordinates. If the slot's {@link SlotPose#getDeform()} + * is not empty, it is used to deform the vertices. *

* See World transforms in the Spine * Runtimes Guide. @@ -88,12 +88,12 @@ abstract public class VertexAttachment extends Attachment { * @param stride The number of worldVertices entries between the value pairs written. */ public void computeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset, int stride) { count = offset + (count >> 1) * stride; - FloatArray deformArray = slot.getDeform(); + FloatArray deformArray = slot.getAppliedPose().getDeform(); float[] vertices = this.vertices; int[] bones = this.bones; if (bones == null) { if (deformArray.size > 0) vertices = deformArray.items; - BoneApplied bone = slot.getBone().getApplied(); + BoneApplied bone = slot.getBone().getAppliedPose(); float x = bone.getWorldX(), y = bone.getWorldY(); float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD(); for (int v = start, w = offset; w < count; v += 2, w += stride) { @@ -116,7 +116,7 @@ abstract public class VertexAttachment extends Attachment { int n = bones[v++]; n += v; for (; v < n; v++, b += 3) { - BoneApplied bone = ((Bone)skeletonBones[bones[v]]).getApplied(); + BoneApplied bone = ((Bone)skeletonBones[bones[v]]).getAppliedPose(); float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight; wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight; @@ -131,7 +131,7 @@ abstract public class VertexAttachment extends Attachment { int n = bones[v++]; n += v; for (; v < n; v++, b += 3, f += 2) { - BoneApplied bone = ((Bone)skeletonBones[bones[v]]).getApplied(); + BoneApplied bone = ((Bone)skeletonBones[bones[v]]).getAppliedPose(); float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; wx += (vx * bone.getA() + vy * bone.getB() + bone.getWorldX()) * weight; wy += (vx * bone.getC() + vy * bone.getD() + bone.getWorldY()) * weight; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActor.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActor.java index 5842c4ac2..21006907b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActor.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActor.java @@ -34,8 +34,8 @@ import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.scenes.scene2d.Actor; import com.esotericsoftware.spine.AnimationState; +import com.esotericsoftware.spine.Physics; import com.esotericsoftware.spine.Skeleton; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.SkeletonRenderer; /** A scene2d actor that draws a skeleton. */ diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java index b250f7570..8c98d0ba2 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonActorPool.java @@ -73,7 +73,7 @@ public class SkeletonActorPool extends Pool { skeleton.setScale(1, 1); skeleton.setSkin((Skin)null); skeleton.setSkin(SkeletonActorPool.this.skeletonData.getDefaultSkin()); - skeleton.setToSetupPose(); + skeleton.setupPose(); } }; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonDrawable.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonDrawable.java index 14cbe584a..561ef2376 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonDrawable.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonDrawable.java @@ -33,8 +33,8 @@ import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.scenes.scene2d.utils.BaseDrawable; import com.esotericsoftware.spine.AnimationState; +import com.esotericsoftware.spine.Physics; import com.esotericsoftware.spine.Skeleton; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.SkeletonRenderer; /** A scene2d drawable that draws a skeleton. The animation state and skeleton must be updated each frame, or diff --git a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java index 9b9470c2f..07fa08637 100644 --- a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java +++ b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java @@ -52,7 +52,6 @@ import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.esotericsoftware.spine.Animation.MixBlend; import com.esotericsoftware.spine.AnimationState.AnimationStateAdapter; import com.esotericsoftware.spine.AnimationState.TrackEntry; -import com.esotericsoftware.spine.Skeleton.Physics; import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; import org.lwjgl.system.Configuration; @@ -260,11 +259,11 @@ public class SkeletonViewer extends ApplicationAdapter { skeleton.setScale(scaleX, scaleY); if (ui.setupPoseButton.isChecked()) - skeleton.setToSetupPose(); + skeleton.setupPose(); else if (ui.bonesSetupPoseButton.isChecked()) - skeleton.setBonesToSetupPose(); + skeleton.setupPoseBones(); else if (ui.slotsSetupPoseButton.isChecked()) // - skeleton.setSlotsToSetupPose(); + skeleton.setupPoseSlots(); delta = Math.min(delta, 0.032f) * ui.speedSlider.getValue(); state.update(delta); diff --git a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java index e61e74825..017424e58 100644 --- a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java +++ b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewerUI.java @@ -370,17 +370,17 @@ class SkeletonViewerUI { setupPoseButton.addListener(new ChangeListener() { public void changed (ChangeEvent event, Actor actor) { - if (viewer.skeleton != null) viewer.skeleton.setToSetupPose(); + if (viewer.skeleton != null) viewer.skeleton.setupPose(); } }); bonesSetupPoseButton.addListener(new ChangeListener() { public void changed (ChangeEvent event, Actor actor) { - if (viewer.skeleton != null) viewer.skeleton.setBonesToSetupPose(); + if (viewer.skeleton != null) viewer.skeleton.setupPoseBones(); } }); slotsSetupPoseButton.addListener(new ChangeListener() { public void changed (ChangeEvent event, Actor actor) { - if (viewer.skeleton != null) viewer.skeleton.setSlotsToSetupPose(); + if (viewer.skeleton != null) viewer.skeleton.setupPoseSlots(); } }); @@ -547,7 +547,7 @@ class SkeletonViewerUI { viewer.skeleton.setSkin((Skin)null); else viewer.skeleton.setSkin(skinName); - viewer.skeleton.setSlotsToSetupPose(); + viewer.skeleton.setupPoseSlots(); } } }); From 08af7407b320af38587afd410c131665bcf2dcec Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Tue, 15 Apr 2025 14:39:03 -0400 Subject: [PATCH 28/75] [libgdx] Added IkConstraintPose and data classes use a setup pose field. --- .../com/esotericsoftware/spine/Animation.java | 169 +++++++++--------- .../spine/AnimationState.java | 10 +- .../src/com/esotericsoftware/spine/Bone.java | 2 +- .../com/esotericsoftware/spine/BoneData.java | 17 +- .../com/esotericsoftware/spine/BonePose.java | 20 +-- .../esotericsoftware/spine/IkConstraint.java | 81 ++------- .../spine/IkConstraintData.java | 59 +----- .../spine/IkConstraintPose.java | 96 ++++++++++ .../com/esotericsoftware/spine/Skeleton.java | 15 +- .../spine/SkeletonBinary.java | 34 ++-- .../esotericsoftware/spine/SkeletonJson.java | 32 ++-- .../src/com/esotericsoftware/spine/Slot.java | 6 +- .../com/esotericsoftware/spine/SlotData.java | 20 +-- .../com/esotericsoftware/spine/SlotPose.java | 16 +- 14 files changed, 288 insertions(+), 289 deletions(-) create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintPose.java diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 15418d4ce..ba17bb8b3 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -563,7 +563,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, bone.data.rotation); + pose.rotation = getRelativeValue(time, alpha, blend, pose.rotation, bone.data.setup.rotation); } } } @@ -588,18 +588,18 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; - BonePose pose = appliedPose ? bone.applied : bone.pose; + BonePose pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - pose.x = bone.data.x; - pose.y = bone.data.y; + pose.x = setup.x; + pose.y = setup.y; return; case first: - pose.x += (bone.data.x - pose.x) * alpha; - pose.y += (bone.data.y - pose.y) * alpha; + pose.x += (setup.x - pose.x) * alpha; + pose.y += (setup.y - pose.y) * alpha; } return; } @@ -626,13 +626,13 @@ public class Animation { switch (blend) { case setup: - pose.x = bone.data.x + x * alpha; - pose.y = bone.data.y + y * alpha; + pose.x = setup.x + x * alpha; + pose.y = setup.y + y * alpha; break; case first: case replace: - pose.x += (bone.data.x + x - pose.x) * alpha; - pose.y += (bone.data.y + y - pose.y) * alpha; + pose.x += (setup.x + x - pose.x) * alpha; + pose.y += (setup.y + y - pose.y) * alpha; break; case add: pose.x += x * alpha; @@ -660,7 +660,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.x = getRelativeValue(time, alpha, blend, pose.x, bone.data.x); + pose.x = getRelativeValue(time, alpha, blend, pose.x, bone.data.setup.x); } } } @@ -684,7 +684,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.y = getRelativeValue(time, alpha, blend, pose.y, bone.data.y); + pose.y = getRelativeValue(time, alpha, blend, pose.y, bone.data.setup.y); } } } @@ -709,18 +709,18 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; - BonePose pose = appliedPose ? bone.applied : bone.pose; + BonePose pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - pose.scaleX = bone.data.scaleX; - pose.scaleY = bone.data.scaleY; + pose.scaleX = setup.scaleX; + pose.scaleY = setup.scaleY; return; case first: - pose.scaleX += (bone.data.scaleX - pose.scaleX) * alpha; - pose.scaleY += (bone.data.scaleY - pose.scaleY) * alpha; + pose.scaleX += (setup.scaleX - pose.scaleX) * alpha; + pose.scaleY += (setup.scaleY - pose.scaleY) * alpha; } return; } @@ -744,13 +744,13 @@ public class Animation { x = getBezierValue(time, i, VALUE1, curveType - BEZIER); y = getBezierValue(time, i, VALUE2, curveType + BEZIER_SIZE - BEZIER); } - x *= bone.data.scaleX; - y *= bone.data.scaleY; + x *= setup.scaleX; + y *= setup.scaleY; if (alpha == 1) { if (blend == add) { - pose.scaleX += x - bone.data.scaleX; - pose.scaleY += y - bone.data.scaleY; + pose.scaleX += x - setup.scaleX; + pose.scaleY += y - setup.scaleY; } else { pose.scaleX = x; pose.scaleY = y; @@ -761,8 +761,8 @@ public class Animation { if (direction == out) { switch (blend) { case setup: - bx = bone.data.scaleX; - by = bone.data.scaleY; + bx = setup.scaleX; + by = setup.scaleY; pose.scaleX = bx + (Math.abs(x) * Math.signum(bx) - bx) * alpha; pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; break; @@ -774,14 +774,14 @@ public class Animation { pose.scaleY = by + (Math.abs(y) * Math.signum(by) - by) * alpha; break; case add: - pose.scaleX += (x - bone.data.scaleX) * alpha; - pose.scaleY += (y - bone.data.scaleY) * alpha; + pose.scaleX += (x - setup.scaleX) * alpha; + pose.scaleY += (y - setup.scaleY) * alpha; } } else { switch (blend) { case setup: - bx = Math.abs(bone.data.scaleX) * Math.signum(x); - by = Math.abs(bone.data.scaleY) * Math.signum(y); + bx = Math.abs(setup.scaleX) * Math.signum(x); + by = Math.abs(setup.scaleY) * Math.signum(y); pose.scaleX = bx + (x - bx) * alpha; pose.scaleY = by + (y - by) * alpha; break; @@ -793,8 +793,8 @@ public class Animation { pose.scaleY = by + (y - by) * alpha; break; case add: - pose.scaleX += (x - bone.data.scaleX) * alpha; - pose.scaleY += (y - bone.data.scaleY) * alpha; + pose.scaleX += (x - setup.scaleX) * alpha; + pose.scaleY += (y - setup.scaleY) * alpha; } } } @@ -820,7 +820,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, bone.data.scaleX); + pose.scaleX = getScaleValue(time, alpha, blend, direction, pose.scaleX, bone.data.setup.scaleX); } } } @@ -844,7 +844,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, bone.data.scaleY); + pose.scaleY = getScaleValue(time, alpha, blend, direction, pose.scaleY, bone.data.setup.scaleY); } } } @@ -869,18 +869,18 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (!bone.active) return; - BonePose pose = appliedPose ? bone.applied : bone.pose; + BonePose pose = appliedPose ? bone.applied : bone.pose, setup = bone.data.setup; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - pose.shearX = bone.data.shearX; - pose.shearY = bone.data.shearY; + pose.shearX = setup.shearX; + pose.shearY = setup.shearY; return; case first: - pose.shearX += (bone.data.shearX - pose.shearX) * alpha; - pose.shearY += (bone.data.shearY - pose.shearY) * alpha; + pose.shearX += (setup.shearX - pose.shearX) * alpha; + pose.shearY += (setup.shearY - pose.shearY) * alpha; } return; } @@ -907,13 +907,13 @@ public class Animation { switch (blend) { case setup: - pose.shearX = bone.data.shearX + x * alpha; - pose.shearY = bone.data.shearY + y * alpha; + pose.shearX = setup.shearX + x * alpha; + pose.shearY = setup.shearY + y * alpha; break; case first: case replace: - pose.shearX += (bone.data.shearX + x - pose.shearX) * alpha; - pose.shearY += (bone.data.shearY + y - pose.shearY) * alpha; + pose.shearX += (setup.shearX + x - pose.shearX) * alpha; + pose.shearY += (setup.shearY + y - pose.shearY) * alpha; break; case add: pose.shearX += x * alpha; @@ -941,7 +941,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, bone.data.shearX); + pose.shearX = getRelativeValue(time, alpha, blend, pose.shearX, bone.data.setup.shearX); } } } @@ -965,7 +965,7 @@ public class Animation { Bone bone = skeleton.bones.get(boneIndex); if (bone.active) { BonePose pose = appliedPose ? bone.applied : bone.pose; - pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, bone.data.shearY); + pose.shearY = getRelativeValue(time, alpha, blend, pose.shearY, bone.data.setup.shearY); } } } @@ -1007,13 +1007,13 @@ public class Animation { BonePose pose = appliedPose ? bone.applied : bone.pose; if (direction == out) { - if (blend == setup) pose.inherit = bone.data.inherit; + if (blend == setup) pose.inherit = bone.data.setup.inherit; return; } float[] frames = this.frames; if (time < frames[0]) { - if (blend == setup || blend == first) pose.inherit = bone.data.inherit; + if (blend == setup || blend == first) pose.inherit = bone.data.setup.inherit; return; } pose.inherit = Inherit.values[(int)frames[search(frames, time, ENTRIES) + INHERIT]]; @@ -1064,7 +1064,7 @@ public class Animation { float[] frames = this.frames; Color color = pose.color; if (time < frames[0]) { - Color setup = slot.data.color; + Color setup = slot.data.setup.color; switch (blend) { case setup: color.set(setup); @@ -1107,7 +1107,7 @@ public class Animation { if (alpha == 1) color.set(r, g, b, a); else { - if (blend == setup) color.set(slot.data.color); + if (blend == setup) color.set(slot.data.setup.color); color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); } } @@ -1154,7 +1154,7 @@ public class Animation { float[] frames = this.frames; Color color = pose.color; if (time < frames[0]) { - Color setup = slot.data.color; + Color setup = slot.data.setup.color; switch (blend) { case setup: color.r = setup.r; @@ -1199,7 +1199,7 @@ public class Animation { color.b = b; } else { if (blend == setup) { - Color setup = slot.data.color; + Color setup = slot.data.setup.color; color.r = setup.r; color.g = setup.g; color.b = setup.b; @@ -1234,7 +1234,7 @@ public class Animation { float[] frames = this.frames; Color color = pose.color; if (time < frames[0]) { - Color setup = slot.data.color; + Color setup = slot.data.setup.color; switch (blend) { case setup: color.a = setup.a; @@ -1249,7 +1249,7 @@ public class Animation { if (alpha == 1) color.a = a; else { - if (blend == setup) color.a = slot.data.color.a; + if (blend == setup) color.a = slot.data.setup.color.a; color.a += (a - color.a) * alpha; } } @@ -1305,7 +1305,8 @@ public class Animation { float[] frames = this.frames; Color light = pose.color, dark = pose.darkColor; if (time < frames[0]) { - Color setupLight = slot.data.color, setupDark = slot.data.darkColor; + SlotPose setup = slot.data.setup; + Color setupLight = setup.color, setupDark = setup.darkColor; switch (blend) { case setup: light.set(setupLight); @@ -1370,8 +1371,9 @@ public class Animation { dark.b = b2; } else { if (blend == setup) { - light.set(slot.data.color); - Color setupDark = slot.data.darkColor; + SlotPose setup = slot.data.setup; + light.set(setup.color); + Color setupDark = setup.darkColor; dark.r = setupDark.r; dark.g = setupDark.g; dark.b = setupDark.b; @@ -1432,7 +1434,8 @@ public class Animation { float[] frames = this.frames; Color light = pose.color, dark = pose.darkColor; if (time < frames[0]) { - Color setupLight = slot.data.color, setupDark = slot.data.darkColor; + SlotPose setup = slot.data.setup; + Color setupLight = setup.color, setupDark = setup.darkColor; switch (blend) { case setup: light.r = setupLight.r; @@ -1498,7 +1501,8 @@ public class Animation { dark.b = b2; } else { if (blend == setup) { - Color setupLight = slot.data.color, setupDark = slot.data.darkColor; + SlotPose setup = slot.data.setup; + Color setupLight = setup.color, setupDark = setup.darkColor; light.r = setupLight.r; light.g = setupLight.g; light.b = setupLight.b; @@ -1958,8 +1962,9 @@ public class Animation { } } - /** Changes an IK constraint's {@link IkConstraint#getMix()}, {@link IkConstraint#getSoftness()}, - * {@link IkConstraint#getBendDirection()}, {@link IkConstraint#getStretch()}, and {@link IkConstraint#getCompress()}. */ + /** Changes an IK constraint's {@link IkConstraintPose#getMix()}, {@link IkConstraintPose#getSoftness()}, + * {@link IkConstraintPose#getBendDirection()}, {@link IkConstraintPose#getStretch()}, and + * {@link IkConstraintPose#getCompress()}. */ static public class IkConstraintTimeline extends CurveTimeline { static public final int ENTRIES = 6; static private final int MIX = 1, SOFTNESS = 2, BEND_DIRECTION = 3, COMPRESS = 4, STRETCH = 5; @@ -2001,24 +2006,24 @@ public class Animation { IkConstraint constraint = skeleton.ikConstraints.get(constraintIndex); if (!constraint.active) return; - if (appliedPose) constraint = constraint.applied; + IkConstraintPose pose = appliedPose ? constraint.applied : constraint.pose, setup = constraint.data.setup; float[] frames = this.frames; if (time < frames[0]) { switch (blend) { case setup: - constraint.mix = constraint.data.mix; - constraint.softness = constraint.data.softness; - constraint.bendDirection = constraint.data.bendDirection; - constraint.compress = constraint.data.compress; - constraint.stretch = constraint.data.stretch; + pose.mix = setup.mix; + pose.softness = setup.softness; + pose.bendDirection = setup.bendDirection; + pose.compress = setup.compress; + pose.stretch = setup.stretch; return; case first: - constraint.mix += (constraint.data.mix - constraint.mix) * alpha; - constraint.softness += (constraint.data.softness - constraint.softness) * alpha; - constraint.bendDirection = constraint.data.bendDirection; - constraint.compress = constraint.data.compress; - constraint.stretch = constraint.data.stretch; + pose.mix += (setup.mix - pose.mix) * alpha; + pose.softness += (setup.softness - pose.softness) * alpha; + pose.bendDirection = setup.bendDirection; + pose.compress = setup.compress; + pose.stretch = setup.stretch; } return; } @@ -2043,25 +2048,25 @@ public class Animation { softness = getBezierValue(time, i, SOFTNESS, curveType + BEZIER_SIZE - BEZIER); } - if (blend == setup) { - constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha; - constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha; + if (blend == MixBlend.setup) { + pose.mix = setup.mix + (mix - setup.mix) * alpha; + pose.softness = setup.softness + (softness - setup.softness) * alpha; if (direction == out) { - constraint.bendDirection = constraint.data.bendDirection; - constraint.compress = constraint.data.compress; - constraint.stretch = constraint.data.stretch; + pose.bendDirection = setup.bendDirection; + pose.compress = setup.compress; + pose.stretch = setup.stretch; } else { - constraint.bendDirection = (int)frames[i + BEND_DIRECTION]; - constraint.compress = frames[i + COMPRESS] != 0; - constraint.stretch = frames[i + STRETCH] != 0; + pose.bendDirection = (int)frames[i + BEND_DIRECTION]; + pose.compress = frames[i + COMPRESS] != 0; + pose.stretch = frames[i + STRETCH] != 0; } } else { - constraint.mix += (mix - constraint.mix) * alpha; - constraint.softness += (softness - constraint.softness) * alpha; + pose.mix += (mix - pose.mix) * alpha; + pose.softness += (softness - pose.softness) * alpha; if (direction == in) { - constraint.bendDirection = (int)frames[i + BEND_DIRECTION]; - constraint.compress = frames[i + COMPRESS] != 0; - constraint.stretch = frames[i + STRETCH] != 0; + pose.bendDirection = (int)frames[i + BEND_DIRECTION]; + pose.compress = frames[i + COMPRESS] != 0; + pose.stretch = frames[i + STRETCH] != 0; } } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index 35ded5575..0097bdc77 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -417,23 +417,23 @@ public class AnimationState { Bone bone = skeleton.bones.get(timeline.boneIndex); if (!bone.active) return; - BonePose pose = bone.getPose(); + BonePose pose = bone.getPose(), setup = bone.data.setup; float[] frames = timeline.frames; float r1, r2; if (time < frames[0]) { // Time is before first frame. switch (blend) { case setup: - pose.rotation = bone.data.rotation; + pose.rotation = setup.rotation; // Fall through. default: return; case first: r1 = pose.rotation; - r2 = bone.data.rotation; + r2 = setup.rotation; } } else { - r1 = blend == MixBlend.setup ? bone.data.rotation : pose.rotation; - r2 = bone.data.rotation + timeline.getCurveValue(time); + r1 = blend == MixBlend.setup ? setup.rotation : pose.rotation; + r2 = setup.rotation + timeline.getCurveValue(time); } // Mix between rotations using the direction of the shortest route on the first frame. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index a85604bba..9fcc49a6c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -66,7 +66,7 @@ public class Bone { /** Sets this bone's local transform to the setup pose. */ public void setupPose () { - pose.set(data); + pose.set(data.setup); } /** The bone's setup pose data. */ diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java index 166be533b..8432bc5cb 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java @@ -33,10 +33,11 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Null; /** The setup pose for a bone. */ -public class BoneData extends BonePose { +public class BoneData { final int index; final String name; @Null final BoneData parent; + final BonePose setup = new BonePose(); float length; boolean skinRequired; @@ -54,12 +55,12 @@ public class BoneData extends BonePose { } /** Copy constructor. */ - public BoneData (BoneData bone, @Null BoneData parent) { - index = bone.index; - name = bone.name; + public BoneData (BoneData data, @Null BoneData parent) { + index = data.index; + name = data.name; this.parent = parent; - length = bone.length; - set(bone); + length = data.length; + setup.set(data.setup); } /** The index of the bone in {@link Skeleton#getBones()}. */ @@ -76,6 +77,10 @@ public class BoneData extends BonePose { return parent; } + public BonePose getSetupPose () { + return setup; + } + /** The bone's length. */ public float getLength () { return length; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java index 8d5b1e8fd..a74d76969 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BonePose.java @@ -39,16 +39,16 @@ public class BonePose { BonePose () { } - public void set (BonePose bone) { - if (bone == null) throw new IllegalArgumentException("bone cannot be null."); - x = bone.x; - y = bone.y; - rotation = bone.rotation; - scaleX = bone.scaleX; - scaleY = bone.scaleY; - shearX = bone.shearX; - shearY = bone.shearY; - inherit = bone.inherit; + public void set (BonePose pose) { + if (pose == null) throw new IllegalArgumentException("pose cannot be null."); + x = pose.x; + y = pose.y; + rotation = pose.rotation; + scaleX = pose.scaleX; + scaleY = pose.scaleY; + shearX = pose.shearX; + shearY = pose.shearY; + inherit = pose.inherit; } /** The local x translation. */ diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index a53c35c6e..323718227 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -43,19 +43,9 @@ public class IkConstraint implements Updatable { final IkConstraintData data; final Array bones; BoneApplied target; - IkConstraint applied; + final IkConstraintPose pose = new IkConstraintPose(), applied = new IkConstraintPose(); boolean active; - int bendDirection; - boolean compress, stretch; - float mix = 1, softness; - - private IkConstraint (IkConstraintData data, Array bones, BoneApplied target) { - this.data = data; - this.bones = bones; - this.target = target; - } - public IkConstraint (IkConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); @@ -67,8 +57,6 @@ public class IkConstraint implements Updatable { target = skeleton.bones.get(data.target.index).applied; - applied = new IkConstraint(data, bones, target); - setupPose(); } @@ -79,24 +67,20 @@ public class IkConstraint implements Updatable { } public void setupPose () { - IkConstraintData data = this.data; - mix = data.mix; - softness = data.softness; - bendDirection = data.bendDirection; - compress = data.compress; - stretch = data.stretch; + pose.set(data.setup); } /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { - if (mix == 0) return; + IkConstraintPose pose = applied; + if (pose.mix == 0) return; BoneApplied target = this.target; Object[] bones = this.bones.items; switch (this.bones.size) { - case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, compress, stretch, data.uniform, mix); + case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, pose.compress, pose.stretch, data.uniform, pose.mix); case 2 -> // - apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, bendDirection, stretch, data.uniform, - softness, mix); + apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, pose.bendDirection, pose.stretch, + data.uniform, pose.softness, pose.mix); } } @@ -115,55 +99,12 @@ public class IkConstraint implements Updatable { this.target = target; } - /** 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. */ - public float getMix () { - return mix; + public IkConstraintPose getPose () { + return pose; } - public void setMix (float mix) { - this.mix = mix; - } - - /** 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. */ - public float getSoftness () { - return softness; - } - - public void setSoftness (float softness) { - this.softness = softness; - } - - /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */ - public int getBendDirection () { - return bendDirection; - } - - public void setBendDirection (int bendDirection) { - this.bendDirection = bendDirection; - } - - /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */ - public boolean getCompress () { - return compress; - } - - public void setCompress (boolean compress) { - this.compress = compress; - } - - /** 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 {@link #getSoftness()} is - * > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */ - public boolean getStretch () { - return stretch; - } - - public void setStretch (boolean stretch) { - this.stretch = stretch; + public IkConstraintPose getAppliedPose () { + return applied; } /** Returns false when this constraint won't be updated by diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java index 572b7b410..f04a5f9a2 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java @@ -37,9 +37,8 @@ import com.badlogic.gdx.utils.Array; public class IkConstraintData extends ConstraintData { final Array bones = new Array(); BoneData target; - int bendDirection; - boolean compress, stretch, uniform; - float mix, softness; + final IkConstraintPose setup = new IkConstraintPose(); + boolean uniform; public IkConstraintData (String name) { super(name); @@ -60,58 +59,12 @@ public class IkConstraintData extends ConstraintData { this.target = target; } - /** 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. */ - public float getMix () { - return mix; + public IkConstraintPose getSetupPose () { + return setup; } - public void setMix (float mix) { - this.mix = mix; - } - - /** 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. */ - public float getSoftness () { - return softness; - } - - public void setSoftness (float softness) { - this.softness = softness; - } - - /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */ - public int getBendDirection () { - return bendDirection; - } - - public void setBendDirection (int bendDirection) { - this.bendDirection = bendDirection; - } - - /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */ - public boolean getCompress () { - return compress; - } - - public void setCompress (boolean compress) { - this.compress = compress; - } - - /** 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 {@link #getSoftness()} is - * > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */ - public boolean getStretch () { - return stretch; - } - - public void setStretch (boolean stretch) { - this.stretch = stretch; - } - - /** When true and {@link #getCompress()} or {@link #getStretch()} is used, the bone is scaled on both the X and Y axes. */ + /** When true and {@link IkConstraintPose#getCompress()} or {@link IkConstraintPose#getStretch()} is used, the bone is scaled + * on both the X and Y axes. */ public boolean getUniform () { return uniform; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintPose.java new file mode 100644 index 000000000..b1dddc3c4 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintPose.java @@ -0,0 +1,96 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +/** Stores the current pose for an IK constraint. */ +public class IkConstraintPose { + int bendDirection; + boolean compress, stretch; + float mix, softness; + + public void set (IkConstraintPose pose) { + mix = pose.mix; + softness = pose.softness; + bendDirection = pose.bendDirection; + compress = pose.compress; + stretch = pose.stretch; + } + + /** 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. */ + public float getMix () { + return mix; + } + + public void setMix (float mix) { + this.mix = mix; + } + + /** 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. */ + public float getSoftness () { + return softness; + } + + public void setSoftness (float softness) { + this.softness = softness; + } + + /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */ + public int getBendDirection () { + return bendDirection; + } + + public void setBendDirection (int bendDirection) { + this.bendDirection = bendDirection; + } + + /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */ + public boolean getCompress () { + return compress; + } + + public void setCompress (boolean compress) { + this.compress = compress; + } + + /** 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 {@link #getSoftness()} is + * > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */ + public boolean getStretch () { + return stretch; + } + + public void setStretch (boolean stretch) { + this.stretch = stretch; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 13d7e39cb..434f0081c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -53,6 +53,7 @@ import com.esotericsoftware.spine.utils.SkeletonClipping; * Runtimes Guide. */ public class Skeleton { static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0}; + private static final Object IkConstraint = null; final SkeletonData data; final Array bones; final Array slots; @@ -412,16 +413,22 @@ public class Skeleton { * See World transforms in the Spine * Runtimes Guide. */ public void updateWorldTransform (Physics physics) { - Object[] bones = this.bones.items; + Object[] objects = this.bones.items; for (int i = 0, n = this.bones.size; i < n; i++) { - var bone = (Bone)bones[i]; + var bone = (Bone)objects[i]; if (bone.active) bone.applied.set(bone.pose); } - Object[] slots = this.slots.items; + objects = this.slots.items; for (int i = 0, n = this.slots.size; i < n; i++) { - var slot = (Slot)slots[i]; + var slot = (Slot)objects[i]; if (slot.bone.active) slot.applied.set(slot.pose); } + objects = ikConstraints.items; + for (int i = 0, n = ikConstraints.size; i < n; i++) { + var constraint = (IkConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + // BOZO! - Reset the rest. Object[] updateCache = this.updateCache.items; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index 55c66e84b..b25b6d930 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -217,15 +217,16 @@ public class SkeletonBinary extends SkeletonLoader { String name = input.readString(); BoneData parent = i == 0 ? null : (BoneData)bones[input.readInt(true)]; var data = new BoneData(i, name, parent); - data.rotation = input.readFloat(); - data.x = input.readFloat() * scale; - data.y = input.readFloat() * scale; - data.scaleX = input.readFloat(); - data.scaleY = input.readFloat(); - data.shearX = input.readFloat(); - data.shearY = input.readFloat(); + BonePose setup = data.setup; + setup.rotation = input.readFloat(); + setup.x = input.readFloat() * scale; + setup.y = input.readFloat() * scale; + setup.scaleX = input.readFloat(); + setup.scaleY = input.readFloat(); + setup.shearX = input.readFloat(); + setup.shearY = input.readFloat(); + setup.inherit = Inherit.values[input.readByte()]; data.length = input.readFloat() * scale; - data.inherit = Inherit.values[input.readByte()]; data.skinRequired = input.readBoolean(); if (nonessential) { Color.rgba8888ToColor(data.color, input.readInt()); @@ -241,10 +242,10 @@ public class SkeletonBinary extends SkeletonLoader { String slotName = input.readString(); var boneData = (BoneData)bones[input.readInt(true)]; var data = new SlotData(i, slotName, boneData); - Color.rgba8888ToColor(data.color, input.readInt()); + Color.rgba8888ToColor(data.setup.color, input.readInt()); int darkColor = input.readInt(); - if (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor); + if (darkColor != -1) Color.rgb888ToColor(data.setup.darkColor = new Color(), darkColor); data.attachmentName = input.readStringRef(); data.blendMode = BlendMode.values[input.readInt(true)]; @@ -263,12 +264,13 @@ public class SkeletonBinary extends SkeletonLoader { data.target = (BoneData)bones[input.readInt(true)]; int flags = input.read(); data.skinRequired = (flags & 1) != 0; - data.bendDirection = (flags & 2) != 0 ? 1 : -1; - data.compress = (flags & 4) != 0; - data.stretch = (flags & 8) != 0; - data.uniform = (flags & 16) != 0; - if ((flags & 32) != 0) data.mix = (flags & 64) != 0 ? input.readFloat() : 1; - if ((flags & 128) != 0) data.softness = input.readFloat() * scale; + data.uniform = (flags & 2) != 0; + IkConstraintPose setup = data.setup; + setup.bendDirection = (flags & 4) != 0 ? 1 : -1; + setup.compress = (flags & 8) != 0; + setup.stretch = (flags & 16) != 0; + if ((flags & 32) != 0) setup.mix = (flags & 64) != 0 ? input.readFloat() : 1; + if ((flags & 128) != 0) setup.softness = input.readFloat() * scale; o[i] = data; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 01f26c89b..17fad77cb 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -174,14 +174,15 @@ public class SkeletonJson extends SkeletonLoader { } var data = new BoneData(skeletonData.bones.size, boneMap.getString("name"), parent); data.length = boneMap.getFloat("length", 0) * scale; - data.x = boneMap.getFloat("x", 0) * scale; - data.y = boneMap.getFloat("y", 0) * scale; - data.rotation = boneMap.getFloat("rotation", 0); - data.scaleX = boneMap.getFloat("scaleX", 1); - data.scaleY = boneMap.getFloat("scaleY", 1); - data.shearX = boneMap.getFloat("shearX", 0); - data.shearY = boneMap.getFloat("shearY", 0); - data.inherit = Inherit.valueOf(boneMap.getString("inherit", Inherit.normal.name())); + BonePose setup = data.setup; + setup.x = boneMap.getFloat("x", 0) * scale; + setup.y = boneMap.getFloat("y", 0) * scale; + setup.rotation = boneMap.getFloat("rotation", 0); + setup.scaleX = boneMap.getFloat("scaleX", 1); + setup.scaleY = boneMap.getFloat("scaleY", 1); + setup.shearX = boneMap.getFloat("shearX", 0); + setup.shearY = boneMap.getFloat("shearY", 0); + setup.inherit = Inherit.valueOf(boneMap.getString("inherit", Inherit.normal.name())); data.skinRequired = boneMap.getBoolean("skin", false); String color = boneMap.getString("color", null); @@ -203,10 +204,10 @@ public class SkeletonJson extends SkeletonLoader { var data = new SlotData(skeletonData.slots.size, slotName, boneData); String color = slotMap.getString("color", null); - if (color != null) Color.valueOf(color, data.getColor()); + if (color != null) Color.valueOf(color, data.getSetupPose().getColor()); String dark = slotMap.getString("dark", null); - if (dark != null) data.setDarkColor(Color.valueOf(dark)); + if (dark != null) Color.valueOf(dark, data.getSetupPose().getDarkColor()); data.attachmentName = slotMap.getString("attachment", null); data.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name())); @@ -230,12 +231,13 @@ public class SkeletonJson extends SkeletonLoader { data.target = skeletonData.findBone(targetName); if (data.target == null) throw new SerializationException("IK target bone not found: " + targetName); - data.mix = constraintMap.getFloat("mix", 1); - data.softness = constraintMap.getFloat("softness", 0) * scale; - data.bendDirection = constraintMap.getBoolean("bendPositive", true) ? 1 : -1; - data.compress = constraintMap.getBoolean("compress", false); - data.stretch = constraintMap.getBoolean("stretch", false); data.uniform = constraintMap.getBoolean("uniform", false); + IkConstraintPose setup = data.setup; + setup.mix = constraintMap.getFloat("mix", 1); + setup.softness = constraintMap.getFloat("softness", 0) * scale; + setup.bendDirection = constraintMap.getBoolean("bendPositive", true) ? 1 : -1; + setup.compress = constraintMap.getBoolean("compress", false); + setup.stretch = constraintMap.getBoolean("stretch", false); skeletonData.ikConstraints.add(data); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java index 46dbd4931..14893dc37 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java @@ -45,7 +45,7 @@ public class Slot { if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); this.data = data; bone = skeleton.bones.get(data.boneData.index); - if (data.darkColor != null) { + if (data.setup.darkColor != null) { pose.darkColor = new Color(); applied.darkColor = new Color(); } @@ -58,7 +58,7 @@ public class Slot { if (bone == null) throw new IllegalArgumentException("bone cannot be null."); data = slot.data; this.bone = bone; - if (data.darkColor != null) { + if (data.setup.darkColor != null) { pose.darkColor = new Color(); applied.darkColor = new Color(); } @@ -67,7 +67,7 @@ public class Slot { /** Sets this slot to the setup pose. */ public void setupPose () { - pose.set(data); + pose.set(data.setup); if (data.attachmentName != null) pose.setAttachment(bone.skeleton.getAttachment(data.index, data.attachmentName)); } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java index c7707e19a..4cb2bfb5b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotData.java @@ -29,14 +29,14 @@ package com.esotericsoftware.spine; -import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Null; /** Stores the setup pose for a {@link Slot}. */ -public class SlotData extends SlotPose { +public class SlotData { final int index; final String name; final BoneData boneData; + final SlotPose setup = new SlotPose(); @Null String attachmentName; BlendMode blendMode; @@ -67,20 +67,8 @@ public class SlotData extends SlotPose { return boneData; } - /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two - * color tinting. */ - public Color getColor () { - return color; - } - - /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark - * color's alpha is not used. */ - public @Null Color getDarkColor () { - return darkColor; - } - - public void setDarkColor (@Null Color darkColor) { - this.darkColor = darkColor; + public SlotPose getSetupPose () { + return setup; } public void setAttachmentName (@Null String attachmentName) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java index ab4264c82..1044bec40 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SlotPose.java @@ -44,21 +44,21 @@ import com.esotericsoftware.spine.attachments.VertexAttachment; public class SlotPose { final Color color = new Color(); @Null Color darkColor; - @Null Attachment attachment; + @Null Attachment attachment; // Not used in setup pose. int sequenceIndex; final FloatArray deform = new FloatArray(0); SlotPose () { } - public void set (SlotPose slot) { - if (slot == null) throw new IllegalArgumentException("slot cannot be null."); - color.set(slot.color); - if (slot.darkColor != null) darkColor.set(slot.darkColor); - attachment = slot.attachment; - sequenceIndex = slot.sequenceIndex; + public void set (SlotPose pose) { + if (pose == null) throw new IllegalArgumentException("pose cannot be null."); + color.set(pose.color); + if (darkColor != null) darkColor.set(pose.darkColor); + attachment = pose.attachment; + sequenceIndex = pose.sequenceIndex; deform.size = 0; - deform.addAll(slot.deform); + deform.addAll(pose.deform); } /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two From c8069fa85210461f71a6d8df5272b697fe256cb6 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Tue, 15 Apr 2025 17:56:55 -0400 Subject: [PATCH 29/75] [libgdx] Pose classes for all the remaining constraints. --- .../com/esotericsoftware/spine/Animation.java | 228 ++++++++---------- .../esotericsoftware/spine/IkConstraint.java | 12 +- .../spine/IkConstraintData.java | 10 +- .../spine/PathConstraint.java | 75 ++---- .../spine/PathConstraintData.java | 51 +--- .../spine/PathConstraintPose.java | 88 +++++++ .../spine/PhysicsConstraint.java | 102 ++------ .../spine/PhysicsConstraintData.java | 65 +---- .../spine/PhysicsConstraintPose.java | 102 ++++++++ .../com/esotericsoftware/spine/Skeleton.java | 81 +++++-- .../spine/SkeletonBinary.java | 43 ++-- .../esotericsoftware/spine/SkeletonJson.java | 43 ++-- .../com/esotericsoftware/spine/Slider.java | 43 ++-- .../esotericsoftware/spine/SliderData.java | 22 +- .../esotericsoftware/spine/SliderPose.java | 57 +++++ .../spine/TransformConstraint.java | 78 +----- .../spine/TransformConstraintData.java | 144 ++++------- .../spine/TransformConstraintPose.java | 98 ++++++++ 18 files changed, 692 insertions(+), 650 deletions(-) create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintPose.java create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintPose.java create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintPose.java diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index ba17bb8b3..296e1b30a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -2072,9 +2072,9 @@ public class Animation { } } - /** Changes a transform constraint's {@link TransformConstraint#getMixRotate()}, {@link TransformConstraint#getMixX()}, - * {@link TransformConstraint#getMixY()}, {@link TransformConstraint#getMixScaleX()}, - * {@link TransformConstraint#getMixScaleY()}, and {@link TransformConstraint#getMixShearY()}. */ + /** Changes a transform constraint's {@link TransformConstraintPose#getMixRotate()}, {@link TransformConstraintPose#getMixX()}, + * {@link TransformConstraintPose#getMixY()}, {@link TransformConstraintPose#getMixScaleX()}, + * {@link TransformConstraintPose#getMixScaleY()}, and {@link TransformConstraintPose#getMixShearY()}. */ static public class TransformConstraintTimeline extends CurveTimeline { static public final int ENTRIES = 7; static private final int ROTATE = 1, X = 2, Y = 3, SCALEX = 4, SCALEY = 5, SHEARY = 6; @@ -2116,27 +2116,27 @@ public class Animation { TransformConstraint constraint = skeleton.transformConstraints.get(constraintIndex); if (!constraint.active) return; - if (appliedPose) constraint = constraint.applied; + TransformConstraintPose pose = appliedPose ? constraint.applied : constraint.pose; float[] frames = this.frames; if (time < frames[0]) { - TransformConstraintData data = constraint.data; + TransformConstraintPose setup = constraint.data.setup; switch (blend) { case setup: - constraint.mixRotate = data.mixRotate; - constraint.mixX = data.mixX; - constraint.mixY = data.mixY; - constraint.mixScaleX = data.mixScaleX; - constraint.mixScaleY = data.mixScaleY; - constraint.mixShearY = data.mixShearY; + pose.mixRotate = setup.mixRotate; + pose.mixX = setup.mixX; + pose.mixY = setup.mixY; + pose.mixScaleX = setup.mixScaleX; + pose.mixScaleY = setup.mixScaleY; + pose.mixShearY = setup.mixShearY; return; case first: - constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; - constraint.mixX += (data.mixX - constraint.mixX) * alpha; - constraint.mixY += (data.mixY - constraint.mixY) * alpha; - constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha; - constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha; - constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha; + pose.mixRotate += (setup.mixRotate - pose.mixRotate) * alpha; + pose.mixX += (setup.mixX - pose.mixX) * alpha; + pose.mixY += (setup.mixY - pose.mixY) * alpha; + pose.mixScaleX += (setup.mixScaleX - pose.mixScaleX) * alpha; + pose.mixScaleY += (setup.mixScaleY - pose.mixScaleY) * alpha; + pose.mixShearY += (setup.mixShearY - pose.mixShearY) * alpha; } return; } @@ -2178,25 +2178,25 @@ public class Animation { } if (blend == setup) { - TransformConstraintData data = constraint.data; - constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; - constraint.mixX = data.mixX + (x - data.mixX) * alpha; - constraint.mixY = data.mixY + (y - data.mixY) * alpha; - constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha; - constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha; - constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha; + TransformConstraintPose setup = constraint.data.setup; + pose.mixRotate = setup.mixRotate + (rotate - setup.mixRotate) * alpha; + pose.mixX = setup.mixX + (x - setup.mixX) * alpha; + pose.mixY = setup.mixY + (y - setup.mixY) * alpha; + pose.mixScaleX = setup.mixScaleX + (scaleX - setup.mixScaleX) * alpha; + pose.mixScaleY = setup.mixScaleY + (scaleY - setup.mixScaleY) * alpha; + pose.mixShearY = setup.mixShearY + (shearY - setup.mixShearY) * alpha; } else { - constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; - constraint.mixX += (x - constraint.mixX) * alpha; - constraint.mixY += (y - constraint.mixY) * alpha; - constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha; - constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha; - constraint.mixShearY += (shearY - constraint.mixShearY) * alpha; + pose.mixRotate += (rotate - pose.mixRotate) * alpha; + pose.mixX += (x - pose.mixX) * alpha; + pose.mixY += (y - pose.mixY) * alpha; + pose.mixScaleX += (scaleX - pose.mixScaleX) * alpha; + pose.mixScaleY += (scaleY - pose.mixScaleY) * alpha; + pose.mixShearY += (shearY - pose.mixShearY) * alpha; } } } - /** Changes a path constraint's {@link PathConstraint#getPosition()}. */ + /** Changes a path constraint's {@link PathConstraintPose#getPosition()}. */ static public class PathConstraintPositionTimeline extends CurveTimeline1 { final int constraintIndex; @@ -2216,13 +2216,13 @@ public class Animation { PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex); if (constraint.active) { - if (appliedPose) constraint = constraint.applied; - constraint.position = getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position); + PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose; + pose.position = getAbsoluteValue(time, alpha, blend, pose.position, constraint.data.setup.position); } } } - /** Changes a path constraint's {@link PathConstraint#getSpacing()}. */ + /** Changes a path constraint's {@link PathConstraintPose#getSpacing()}. */ static public class PathConstraintSpacingTimeline extends CurveTimeline1 { final int constraintIndex; @@ -2242,14 +2242,14 @@ public class Animation { PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex); if (constraint.active) { - if (appliedPose) constraint = constraint.applied; - constraint.spacing = getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing); + PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose; + pose.spacing = getAbsoluteValue(time, alpha, blend, pose.spacing, constraint.data.setup.spacing); } } } - /** Changes a path constraint's {@link PathConstraint#getMixRotate()}, {@link PathConstraint#getMixX()}, and - * {@link PathConstraint#getMixY()}. */ + /** Changes a path constraint's {@link PathConstraintPose#getMixRotate()}, {@link PathConstraintPose#getMixX()}, and + * {@link PathConstraintPose#getMixY()}. */ static public class PathConstraintMixTimeline extends CurveTimeline { static public final int ENTRIES = 4; static private final int ROTATE = 1, X = 2, Y = 3; @@ -2287,21 +2287,21 @@ public class Animation { PathConstraint constraint = skeleton.pathConstraints.get(constraintIndex); if (!constraint.active) return; - if (appliedPose) constraint = constraint.applied; + PathConstraintPose pose = appliedPose ? constraint.applied : constraint.pose; float[] frames = this.frames; if (time < frames[0]) { - PathConstraintData data = constraint.data; + PathConstraintPose setup = constraint.data.setup; switch (blend) { case setup: - constraint.mixRotate = data.mixRotate; - constraint.mixX = data.mixX; - constraint.mixY = data.mixY; + pose.mixRotate = setup.mixRotate; + pose.mixX = setup.mixX; + pose.mixY = setup.mixY; return; case first: - constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; - constraint.mixX += (data.mixX - constraint.mixX) * alpha; - constraint.mixY += (data.mixY - constraint.mixY) * alpha; + pose.mixRotate += (setup.mixRotate - pose.mixRotate) * alpha; + pose.mixX += (setup.mixX - pose.mixX) * alpha; + pose.mixY += (setup.mixY - pose.mixY) * alpha; } return; } @@ -2331,14 +2331,14 @@ public class Animation { } if (blend == setup) { - PathConstraintData data = constraint.data; - constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; - constraint.mixX = data.mixX + (x - data.mixX) * alpha; - constraint.mixY = data.mixY + (y - data.mixY) * alpha; + PathConstraintPose setup = constraint.data.setup; + pose.mixRotate = setup.mixRotate + (rotate - setup.mixRotate) * alpha; + pose.mixX = setup.mixX + (x - setup.mixX) * alpha; + pose.mixY = setup.mixY + (y - setup.mixY) * alpha; } else { - constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; - constraint.mixX += (x - constraint.mixX) * alpha; - constraint.mixY += (y - constraint.mixY) * alpha; + pose.mixRotate += (rotate - pose.mixRotate) * alpha; + pose.mixX += (x - pose.mixX) * alpha; + pose.mixY += (y - pose.mixY) * alpha; } } } @@ -2370,44 +2370,38 @@ public class Animation { for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) { constraint = (PhysicsConstraint)constraints[i]; if (constraint.active && global(constraint.data)) { - if (appliedPose) constraint = constraint.applied; - set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint), value)); + PhysicsConstraintPose pose = appliedPose ? constraint.applied : constraint.pose; + set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint.data.setup), value)); } } } else { constraint = skeleton.physicsConstraints.get(constraintIndex); if (constraint.active) { - if (appliedPose) constraint = constraint.applied; - set(constraint, getAbsoluteValue(time, alpha, blend, get(constraint), setup(constraint))); + PhysicsConstraintPose pose = appliedPose ? constraint.applied : constraint.pose; + set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint.data.setup))); } } } - abstract protected float setup (PhysicsConstraint constraint); + abstract protected float get (PhysicsConstraintPose pose); - abstract protected float get (PhysicsConstraint constraint); - - abstract protected void set (PhysicsConstraint constraint, float value); + abstract protected void set (PhysicsConstraintPose pose, float value); abstract protected boolean global (PhysicsConstraintData constraint); } - /** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getInertia()}. */ static public class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintInertiaTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); } - protected float setup (PhysicsConstraint constraint) { - return constraint.data.inertia; + protected float get (PhysicsConstraintPose pose) { + return pose.inertia; } - protected float get (PhysicsConstraint constraint) { - return constraint.inertia; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.inertia = value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.inertia = value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2415,22 +2409,18 @@ public class Animation { } } - /** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getStrength()}. */ static public class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintStrengthTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); } - protected float setup (PhysicsConstraint constraint) { - return constraint.data.strength; + protected float get (PhysicsConstraintPose pose) { + return pose.strength; } - protected float get (PhysicsConstraint constraint) { - return constraint.strength; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.strength = value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.strength = value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2438,22 +2428,18 @@ public class Animation { } } - /** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getDamping()}. */ static public class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintDampingTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); } - protected float setup (PhysicsConstraint constraint) { - return constraint.data.damping; + protected float get (PhysicsConstraintPose pose) { + return pose.damping; } - protected float get (PhysicsConstraint constraint) { - return constraint.damping; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.damping = value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.damping = value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2461,22 +2447,18 @@ public class Animation { } } - /** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getMassInverse()}. The timeline values are not inverted. */ static public class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintMassTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); } - protected float setup (PhysicsConstraint constraint) { - return 1 / constraint.data.massInverse; + protected float get (PhysicsConstraintPose pose) { + return 1 / pose.massInverse; } - protected float get (PhysicsConstraint constraint) { - return 1 / constraint.massInverse; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.massInverse = 1 / value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.massInverse = 1 / value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2484,22 +2466,18 @@ public class Animation { } } - /** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getWind()}. */ static public class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintWindTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); } - protected float setup (PhysicsConstraint constraint) { - return constraint.data.wind; + protected float get (PhysicsConstraintPose pose) { + return pose.wind; } - protected float get (PhysicsConstraint constraint) { - return constraint.wind; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.wind = value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.wind = value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2507,22 +2485,18 @@ public class Animation { } } - /** Changes a physics constraint's {@link PhysicsConstraint#getGravity()}. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getGravity()}. */ static public class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintGravityTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); } - protected float setup (PhysicsConstraint constraint) { - return constraint.data.gravity; + protected float get (PhysicsConstraintPose pose) { + return pose.gravity; } - protected float get (PhysicsConstraint constraint) { - return constraint.gravity; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.gravity = value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.gravity = value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2530,22 +2504,18 @@ public class Animation { } } - /** Changes a physics constraint's {@link PhysicsConstraint#getMix()}. */ + /** Changes a physics constraint's {@link PhysicsConstraintPose#getMix()}. */ static public class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline { public PhysicsConstraintMixTimeline (int frameCount, int bezierCount, int physicsConstraintIndex) { super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); } - protected float setup (PhysicsConstraint constraint) { - return constraint.data.mix; + protected float get (PhysicsConstraintPose pose) { + return pose.mix; } - protected float get (PhysicsConstraint constraint) { - return constraint.mix; - } - - protected void set (PhysicsConstraint constraint, float value) { - constraint.mix = value; + protected void set (PhysicsConstraintPose pose, float value) { + pose.mix = value; } protected boolean global (PhysicsConstraintData constraint) { @@ -2601,17 +2571,13 @@ public class Animation { if (time < frames[0]) return; if (lastTime < frames[0] || time >= frames[search(frames, lastTime) + 1]) { - if (constraint != null) { - if (appliedPose) constraint = constraint.applied; + if (constraint != null) constraint.reset(); - } else { + else { Object[] constraints = skeleton.physicsConstraints.items; for (int i = 0, n = skeleton.physicsConstraints.size; i < n; i++) { constraint = (PhysicsConstraint)constraints[i]; - if (constraint.active) { - if (appliedPose) constraint = constraint.applied; - constraint.reset(); - } + if (constraint.active) constraint.reset(); } } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index 323718227..41c6eb707 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -63,7 +63,7 @@ public class IkConstraint implements Updatable { /** Copy constructor. */ public IkConstraint (IkConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setupPose(); + pose.set(constraint.pose); } public void setupPose () { @@ -72,15 +72,15 @@ public class IkConstraint implements Updatable { /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { - IkConstraintPose pose = applied; - if (pose.mix == 0) return; + IkConstraintPose a = applied; + if (a.mix == 0) return; BoneApplied target = this.target; Object[] bones = this.bones.items; switch (this.bones.size) { - case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, pose.compress, pose.stretch, data.uniform, pose.mix); + case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, a.compress, a.stretch, data.uniform, a.mix); case 2 -> // - apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, pose.bendDirection, pose.stretch, - data.uniform, pose.softness, pose.mix); + apply((BoneApplied)bones[0], (BoneApplied)bones[1], target.worldX, target.worldY, a.bendDirection, a.stretch, + data.uniform, a.softness, a.mix); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java index f04a5f9a2..81ea32789 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraintData.java @@ -35,15 +35,19 @@ import com.badlogic.gdx.utils.Array; *

* See IK constraints in the Spine User Guide. */ public class IkConstraintData extends ConstraintData { + final IkConstraintPose setup = new IkConstraintPose(); final Array bones = new Array(); BoneData target; - final IkConstraintPose setup = new IkConstraintPose(); boolean uniform; public IkConstraintData (String name) { super(name); } + public IkConstraintPose getSetupPose () { + return setup; + } + /** The bones that are constrained by this IK constraint. */ public Array getBones () { return bones; @@ -59,10 +63,6 @@ public class IkConstraintData extends ConstraintData { this.target = target; } - public IkConstraintPose getSetupPose () { - return setup; - } - /** When true and {@link IkConstraintPose#getCompress()} or {@link IkConstraintPose#getStretch()} is used, the bone is scaled * on both the X and Y axes. */ public boolean getUniform () { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index cd6dc4239..aa0b7e33f 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -52,11 +52,9 @@ public class PathConstraint implements Updatable { final PathConstraintData data; final Array bones; Slot slot; - PathConstraint applied; + final PathConstraintPose pose = new PathConstraintPose(), applied = new PathConstraintPose(); boolean active; - float position, spacing, mixRotate, mixX, mixY; - private final FloatArray spaces = new FloatArray(), positions = new FloatArray(); private final FloatArray world = new FloatArray(), curves = new FloatArray(), lengths = new FloatArray(); private final float[] segments = new float[10]; @@ -78,31 +76,25 @@ public class PathConstraint implements Updatable { slot = skeleton.slots.get(data.slot.index); - applied = new PathConstraint(data, bones, slot); - setupPose(); } /** Copy constructor. */ public PathConstraint (PathConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setupPose(); + pose.set(constraint.pose); } public void setupPose () { - PathConstraintData data = this.data; - position = data.position; - spacing = data.spacing; - mixRotate = data.mixRotate; - mixX = data.mixX; - mixY = data.mixY; + pose.set(data.setup); } /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { if (!(slot.applied.attachment instanceof PathAttachment pathAttachment)) return; - float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; + PathConstraintPose pose = applied; + float mixRotate = pose.mixRotate, mixX = pose.mixX, mixY = pose.mixY; if (mixRotate == 0 && mixX == 0 && mixY == 0) return; PathConstraintData data = this.data; @@ -110,7 +102,7 @@ public class PathConstraint implements Updatable { int boneCount = this.bones.size, spacesCount = tangents ? boneCount : boneCount + 1; Object[] bones = this.bones.items; float[] spaces = this.spaces.setSize(spacesCount), lengths = scale ? this.lengths.setSize(boneCount) : null; - float spacing = this.spacing; + float spacing = pose.spacing; switch (data.spacingMode) { case percent -> { @@ -224,7 +216,7 @@ public class PathConstraint implements Updatable { float[] computeWorldPositions (PathAttachment path, int spacesCount, boolean tangents) { Slot slot = this.slot; - float position = this.position; + float position = applied.position; float[] spaces = this.spaces.items, out = this.positions.setSize(spacesCount * 3 + 2), world; boolean closed = path.getClosed(); int verticesLength = path.getWorldVerticesLength(), curveCount = verticesLength / 6, prevCurve = NONE; @@ -480,51 +472,6 @@ public class PathConstraint implements Updatable { } } - /** The position along the path. */ - public float getPosition () { - return position; - } - - public void setPosition (float position) { - this.position = position; - } - - /** The spacing between bones. */ - public float getSpacing () { - return spacing; - } - - public void setSpacing (float spacing) { - this.spacing = spacing; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ - public float getMixRotate () { - return mixRotate; - } - - public void setMixRotate (float mixRotate) { - this.mixRotate = mixRotate; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ - public float getMixX () { - return mixX; - } - - public void setMixX (float mixX) { - this.mixX = mixX; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ - public float getMixY () { - return mixY; - } - - public void setMixY (float mixY) { - this.mixY = mixY; - } - /** The bones that will be modified by this path constraint. */ public Array getBones () { return bones; @@ -540,6 +487,14 @@ public class PathConstraint implements Updatable { this.slot = slot; } + public PathConstraintPose getPose () { + return pose; + } + + public PathConstraintPose getAppliedPose () { + return applied; + } + /** Returns false when this constraint won't be updated by * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java index 6285c1fad..455a40672 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintData.java @@ -35,18 +35,22 @@ import com.badlogic.gdx.utils.Array; *

* See Path constraints in the Spine User Guide. */ public class PathConstraintData extends ConstraintData { + final PathConstraintPose setup = new PathConstraintPose(); final Array bones = new Array(); SlotData slot; PositionMode positionMode; SpacingMode spacingMode; RotateMode rotateMode; float offsetRotation; - float position, spacing, mixRotate, mixX, mixY; public PathConstraintData (String name) { super(name); } + public PathConstraintPose getSetupPose () { + return setup; + } + /** The bones that will be modified by this path constraint. */ public Array getBones () { return bones; @@ -101,51 +105,6 @@ public class PathConstraintData extends ConstraintData { this.offsetRotation = offsetRotation; } - /** The position along the path. */ - public float getPosition () { - return position; - } - - public void setPosition (float position) { - this.position = position; - } - - /** The spacing between bones. */ - public float getSpacing () { - return spacing; - } - - public void setSpacing (float spacing) { - this.spacing = spacing; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ - public float getMixRotate () { - return mixRotate; - } - - public void setMixRotate (float mixRotate) { - this.mixRotate = mixRotate; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ - public float getMixX () { - return mixX; - } - - public void setMixX (float mixX) { - this.mixX = mixX; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ - public float getMixY () { - return mixY; - } - - public void setMixY (float mixY) { - this.mixY = mixY; - } - /** Controls how the first bone is positioned along the path. *

* See Position mode in the Spine User diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintPose.java new file mode 100644 index 000000000..e21293f90 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraintPose.java @@ -0,0 +1,88 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +/** Stores a pose for a path constraint. */ +public class PathConstraintPose { + float position, spacing, mixRotate, mixX, mixY; + + public void set (PathConstraintPose pose) { + position = pose.position; + spacing = pose.spacing; + mixRotate = pose.mixRotate; + mixX = pose.mixX; + mixY = pose.mixY; + } + + /** The position along the path. */ + public float getPosition () { + return position; + } + + public void setPosition (float position) { + this.position = position; + } + + /** The spacing between bones. */ + public float getSpacing () { + return spacing; + } + + public void setSpacing (float spacing) { + this.spacing = spacing; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ + public float getMixRotate () { + return mixRotate; + } + + public void setMixRotate (float mixRotate) { + this.mixRotate = mixRotate; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ + public float getMixX () { + return mixX; + } + + public void setMixX (float mixX) { + this.mixX = mixX; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ + public float getMixY () { + return mixY; + } + + public void setMixY (float mixY) { + this.mixY = mixY; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index 09a0ebcd5..8fa8b0cbc 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -38,11 +38,9 @@ public class PhysicsConstraint implements Updatable { final PhysicsConstraintData data; final Skeleton skeleton; BoneApplied bone; - PhysicsConstraint applied; + final PhysicsConstraintPose pose = new PhysicsConstraintPose(), applied = new PhysicsConstraintPose(); boolean active; - float inertia, strength, damping, massInverse, wind, gravity, mix; - boolean reset = true; float ux, uy, cx, cy, tx, ty; float xOffset, xVelocity; @@ -65,15 +63,13 @@ public class PhysicsConstraint implements Updatable { bone = skeleton.bones.get(data.bone.index).applied; - applied = new PhysicsConstraint(data, skeleton, bone); - setupPose(); } /** Copy constructor. */ public PhysicsConstraint (PhysicsConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setupPose(); + pose.set(constraint.pose); } public void reset () { @@ -91,14 +87,7 @@ public class PhysicsConstraint implements Updatable { } public void setupPose () { - PhysicsConstraintData data = this.data; - inertia = data.inertia; - strength = data.strength; - damping = data.damping; - massInverse = data.massInverse; - wind = data.wind; - gravity = data.gravity; - mix = data.mix; + pose.set(data.setup); } /** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional @@ -120,7 +109,8 @@ public class PhysicsConstraint implements Updatable { /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { - float mix = this.mix; + PhysicsConstraintPose pose = applied; + float mix = pose.mix; if (mix == 0) return; boolean x = data.x > 0, y = data.y > 0, rotateOrShearX = data.rotate > 0 || data.shearX > 0, scaleX = data.scaleX > 0; @@ -145,7 +135,7 @@ public class PhysicsConstraint implements Updatable { ux = bx; uy = by; } else { - float a = remaining, i = inertia, t = data.step, f = skeleton.data.referenceScale, d = -1; + float a = remaining, i = pose.inertia, t = data.step, f = skeleton.data.referenceScale, d = -1; float qx = data.limit * delta, qy = qx * Math.abs(skeleton.scaleY); qx *= Math.abs(skeleton.scaleX); if (x || y) { @@ -160,8 +150,9 @@ public class PhysicsConstraint implements Updatable { uy = by; } if (a >= t) { - d = (float)Math.pow(damping, 60 * t); - float m = massInverse * t, e = strength, w = wind * f * skeleton.scaleX, g = gravity * f * skeleton.scaleY; + d = (float)Math.pow(pose.damping, 60 * t); + float m = pose.massInverse * t, e = pose.strength, w = pose.wind * f * skeleton.scaleX, + g = pose.gravity * f * skeleton.scaleY; do { if (x) { xVelocity += (w - xOffset * e) * m; @@ -209,8 +200,8 @@ public class PhysicsConstraint implements Updatable { } a = remaining; if (a >= t) { - if (d == -1) d = (float)Math.pow(damping, 60 * t); - float m = massInverse * t, e = strength, w = wind, g = gravity, h = l / f; + if (d == -1) d = (float)Math.pow(pose.damping, 60 * t); + float m = pose.massInverse * t, e = pose.strength, w = pose.wind, g = pose.gravity, h = l / f; while (true) { a -= t; if (scaleX) { @@ -283,6 +274,15 @@ public class PhysicsConstraint implements Updatable { bone.updateLocalTransform(); } + /** The physics constraint's setup pose data. */ + public PhysicsConstraintData getData () { + return data; + } + + public Skeleton getSkeleton () { + return skeleton; + } + /** The bone constrained by this physics constraint. */ public BoneApplied getBone () { return bone; @@ -292,61 +292,12 @@ public class PhysicsConstraint implements Updatable { this.bone = bone; } - public float getInertia () { - return inertia; + public PhysicsConstraintPose getPose () { + return pose; } - public void setInertia (float inertia) { - this.inertia = inertia; - } - - public float getStrength () { - return strength; - } - - public void setStrength (float strength) { - this.strength = strength; - } - - public float getDamping () { - return damping; - } - - public void setDamping (float damping) { - this.damping = damping; - } - - public float getMassInverse () { - return massInverse; - } - - public void setMassInverse (float massInverse) { - this.massInverse = massInverse; - } - - public float getWind () { - return wind; - } - - public void setWind (float wind) { - this.wind = wind; - } - - public float getGravity () { - return gravity; - } - - public void setGravity (float gravity) { - this.gravity = gravity; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ - public float getMix () { - return mix; - } - - public void setMix (float mix) { - this.mix = mix; + public PhysicsConstraintPose getAppliedPose () { + return applied; } /** Returns false when this constraint won't be updated by @@ -360,11 +311,6 @@ public class PhysicsConstraint implements Updatable { return active; } - /** The physics constraint's setup pose data. */ - public PhysicsConstraintData getData () { - return data; - } - public String toString () { return data.name; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java index ec78e64ed..9ee259251 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java @@ -33,15 +33,19 @@ package com.esotericsoftware.spine; *

* See Physics constraints in the Spine User Guide. */ public class PhysicsConstraintData extends ConstraintData { + final PhysicsConstraintPose setup = new PhysicsConstraintPose(); BoneData bone; - float x, y, rotate, scaleX, shearX, limit; - float step, inertia, strength, damping, massInverse, wind, gravity, mix; + float x, y, rotate, scaleX, shearX, limit, step; boolean inertiaGlobal, strengthGlobal, dampingGlobal, massGlobal, windGlobal, gravityGlobal, mixGlobal; public PhysicsConstraintData (String name) { super(name); } + public PhysicsConstraintPose getSetupPose () { + return setup; + } + /** The bone constrained by this physics constraint. */ public BoneData getBone () { return bone; @@ -107,63 +111,6 @@ public class PhysicsConstraintData extends ConstraintData { this.limit = limit; } - public float getInertia () { - return inertia; - } - - public void setInertia (float inertia) { - this.inertia = inertia; - } - - public float getStrength () { - return strength; - } - - public void setStrength (float strength) { - this.strength = strength; - } - - public float getDamping () { - return damping; - } - - public void setDamping (float damping) { - this.damping = damping; - } - - public float getMassInverse () { - return massInverse; - } - - public void setMassInverse (float massInverse) { - this.massInverse = massInverse; - } - - public float getWind () { - return wind; - } - - public void setWind (float wind) { - this.wind = wind; - } - - public float getGravity () { - return gravity; - } - - public void setGravity (float gravity) { - this.gravity = gravity; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ - public float getMix () { - return mix; - } - - public void setMix (float mix) { - this.mix = mix; - } - public boolean getInertiaGlobal () { return inertiaGlobal; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintPose.java new file mode 100644 index 000000000..2bf89ecc4 --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintPose.java @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +/** Stores a pose for a physics constraint. */ +public class PhysicsConstraintPose { + float inertia, strength, damping, massInverse, wind, gravity, mix; + + public void set (PhysicsConstraintPose pose) { + inertia = pose.inertia; + strength = pose.strength; + damping = pose.damping; + massInverse = pose.massInverse; + wind = pose.wind; + gravity = pose.gravity; + mix = pose.mix; + } + + public float getInertia () { + return inertia; + } + + public void setInertia (float inertia) { + this.inertia = inertia; + } + + public float getStrength () { + return strength; + } + + public void setStrength (float strength) { + this.strength = strength; + } + + public float getDamping () { + return damping; + } + + public void setDamping (float damping) { + this.damping = damping; + } + + public float getMassInverse () { + return massInverse; + } + + public void setMassInverse (float massInverse) { + this.massInverse = massInverse; + } + + public float getWind () { + return wind; + } + + public void setWind (float wind) { + this.wind = wind; + } + + public float getGravity () { + return gravity; + } + + public void setGravity (float gravity) { + this.gravity = gravity; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ + public float getMix () { + return mix; + } + + public void setMix (float mix) { + this.mix = mix; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 434f0081c..9e6c63040 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -38,7 +38,6 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Animation.BoneTimeline; -import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Skin.SkinEntry; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.ClippingAttachment; @@ -256,21 +255,24 @@ public class Skeleton { constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)); if (!constraint.active) return; + Object[] timelines = constraint.data.animation.timelines.items; + int timelineCount = constraint.data.animation.timelines.size; + Object[] bones = this.bones.items; - for (Timeline timeline : constraint.animation.timelines) - if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + for (int i = 0; i < timelineCount; i++) + if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); updateCache.add(constraint); - for (Timeline timeline : constraint.animation.timelines) { - if (timeline instanceof BoneTimeline boneTimeline) { + for (int i = 0; i < timelineCount; i++) { + if (timelines[i] instanceof BoneTimeline boneTimeline) { var bone = (Bone)bones[boneTimeline.getBoneIndex()]; sortReset(bone.children); bone.sorted = false; } } - for (Timeline timeline : constraint.animation.timelines) - if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + for (int i = 0; i < timelineCount; i++) + if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); } private void sortIkConstraint (IkConstraint constraint) { @@ -347,9 +349,9 @@ public class Skeleton { updateCache.add(constraint); for (int i = 0; i < boneCount; i++) - sortReset(((Bone)constrained[i]).children); + sortReset(((BoneApplied)constrained[i]).bone.children); for (int i = 0; i < boneCount; i++) - ((Bone)constrained[i]).sorted = true; + ((BoneApplied)constrained[i]).bone.sorted = true; } private void sortPathConstraintAttachment (Skin skin, int slotIndex, Bone slotBone) { @@ -371,7 +373,7 @@ public class Skeleton { int nn = pathBones[i++]; nn += i; while (i < nn) - sortBone(((BoneApplied)bones[pathBones[i++]]).bone); + sortBone((Bone)bones[pathBones[i++]]); } } } @@ -428,8 +430,26 @@ public class Skeleton { var constraint = (IkConstraint)objects[i]; if (constraint.active) constraint.applied.set(constraint.pose); } - - // BOZO! - Reset the rest. + objects = pathConstraints.items; + for (int i = 0, n = pathConstraints.size; i < n; i++) { + var constraint = (PathConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = transformConstraints.items; + for (int i = 0, n = transformConstraints.size; i < n; i++) { + var constraint = (TransformConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = physicsConstraints.items; + for (int i = 0, n = physicsConstraints.size; i < n; i++) { + var constraint = (PhysicsConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = sliders.items; + for (int i = 0, n = sliders.size; i < n; i++) { + var constraint = (Slider)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } Object[] updateCache = this.updateCache.items; for (int i = 0, n = this.updateCache.size; i < n; i++) @@ -444,12 +464,41 @@ public class Skeleton { public void updateWorldTransform (Physics physics, BoneApplied parent) { if (parent == null) throw new IllegalArgumentException("parent cannot be null."); - Object[] bones = this.bones.items; - for (int i = 1, n = this.bones.size; i < n; i++) { // Skip root bone. - var bone = (Bone)bones[i]; + Object[] objects = this.bones.items; + for (int i = 0, n = this.bones.size; i < n; i++) { + var bone = (Bone)objects[i]; if (bone.active) bone.applied.set(bone.pose); } - // BOZO! - Reset the rest. + objects = this.slots.items; + for (int i = 0, n = this.slots.size; i < n; i++) { + var slot = (Slot)objects[i]; + if (slot.bone.active) slot.applied.set(slot.pose); + } + objects = ikConstraints.items; + for (int i = 0, n = ikConstraints.size; i < n; i++) { + var constraint = (IkConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = pathConstraints.items; + for (int i = 0, n = pathConstraints.size; i < n; i++) { + var constraint = (PathConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = transformConstraints.items; + for (int i = 0, n = transformConstraints.size; i < n; i++) { + var constraint = (TransformConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = physicsConstraints.items; + for (int i = 0, n = physicsConstraints.size; i < n; i++) { + var constraint = (PhysicsConstraint)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } + objects = sliders.items; + for (int i = 0, n = sliders.size; i < n; i++) { + var constraint = (Slider)objects[i]; + if (constraint.active) constraint.applied.set(constraint.pose); + } // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. BoneApplied rootBone = getRootBone().applied; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index b25b6d930..ac72e6884 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -343,12 +343,13 @@ public class SkeletonBinary extends SkeletonLoader { if ((flags & 16) != 0) data.offsetScaleY = input.readFloat(); if ((flags & 32) != 0) data.offsetShearY = input.readFloat(); flags = input.read(); - if ((flags & 1) != 0) data.mixRotate = input.readFloat(); - if ((flags & 2) != 0) data.mixX = input.readFloat(); - if ((flags & 4) != 0) data.mixY = input.readFloat(); - if ((flags & 8) != 0) data.mixScaleX = input.readFloat(); - if ((flags & 16) != 0) data.mixScaleY = input.readFloat(); - if ((flags & 32) != 0) data.mixShearY = input.readFloat(); + TransformConstraintPose setup = data.getSetupPose(); + if ((flags & 1) != 0) setup.mixRotate = input.readFloat(); + if ((flags & 2) != 0) setup.mixX = input.readFloat(); + if ((flags & 4) != 0) setup.mixY = input.readFloat(); + if ((flags & 8) != 0) setup.mixScaleX = input.readFloat(); + if ((flags & 16) != 0) setup.mixScaleY = input.readFloat(); + if ((flags & 32) != 0) setup.mixShearY = input.readFloat(); o[i] = data; } @@ -367,13 +368,14 @@ public class SkeletonBinary extends SkeletonLoader { data.spacingMode = SpacingMode.values[(flags >> 1) & 3]; data.rotateMode = RotateMode.values[(flags >> 3) & 3]; if ((flags & 128) != 0) data.offsetRotation = input.readFloat(); - data.position = input.readFloat(); - if (data.positionMode == PositionMode.fixed) data.position *= scale; - data.spacing = input.readFloat(); - if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) data.spacing *= scale; - data.mixRotate = input.readFloat(); - data.mixX = input.readFloat(); - data.mixY = input.readFloat(); + PathConstraintPose setup = data.setup; + setup.position = input.readFloat(); + if (data.positionMode == PositionMode.fixed) setup.position *= scale; + setup.spacing = input.readFloat(); + if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) setup.spacing *= scale; + setup.mixRotate = input.readFloat(); + setup.mixX = input.readFloat(); + setup.mixY = input.readFloat(); o[i] = data; } @@ -392,12 +394,13 @@ public class SkeletonBinary extends SkeletonLoader { if ((flags & 32) != 0) data.shearX = input.readFloat(); data.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale; data.step = 1f / input.readUnsignedByte(); - data.inertia = input.readFloat(); - data.strength = input.readFloat(); - data.damping = input.readFloat(); - data.massInverse = (flags & 128) != 0 ? input.readFloat() : 1; - data.wind = input.readFloat(); - data.gravity = input.readFloat(); + PhysicsConstraintPose setup = data.getSetupPose(); + setup.inertia = input.readFloat(); + setup.strength = input.readFloat(); + setup.damping = input.readFloat(); + setup.massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + setup.wind = input.readFloat(); + setup.gravity = input.readFloat(); flags = input.read(); if ((flags & 1) != 0) data.inertiaGlobal = true; if ((flags & 2) != 0) data.strengthGlobal = true; @@ -406,7 +409,7 @@ public class SkeletonBinary extends SkeletonLoader { if ((flags & 16) != 0) data.windGlobal = true; if ((flags & 32) != 0) data.gravityGlobal = true; if ((flags & 64) != 0) data.mixGlobal = true; - data.mix = (flags & 128) != 0 ? input.readFloat() : 1; + setup.mix = (flags & 128) != 0 ? input.readFloat() : 1; o[i] = data; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index 17fad77cb..e944bcb55 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -330,12 +330,13 @@ public class SkeletonJson extends SkeletonLoader { data.offsetScaleY = constraintMap.getFloat("scaleY", 0); data.offsetShearY = constraintMap.getFloat("shearY", 0); - if (rotate) data.mixRotate = constraintMap.getFloat("mixRotate", 1); - if (x) data.mixX = constraintMap.getFloat("mixX", 1); - if (y) data.mixY = constraintMap.getFloat("mixY", data.mixX); - if (scaleX) data.mixScaleX = constraintMap.getFloat("mixScaleX", 1); - if (scaleY) data.mixScaleY = constraintMap.getFloat("mixScaleY", data.mixScaleX); - if (shearY) data.mixShearY = constraintMap.getFloat("mixShearY", 1); + TransformConstraintPose setup = data.setup; + if (rotate) setup.mixRotate = constraintMap.getFloat("mixRotate", 1); + if (x) setup.mixX = constraintMap.getFloat("mixX", 1); + if (y) setup.mixY = constraintMap.getFloat("mixY", setup.mixX); + if (scaleX) setup.mixScaleX = constraintMap.getFloat("mixScaleX", 1); + if (scaleY) setup.mixScaleY = constraintMap.getFloat("mixScaleY", setup.mixScaleX); + if (shearY) setup.mixShearY = constraintMap.getFloat("mixShearY", 1); skeletonData.transformConstraints.add(data); } @@ -360,13 +361,14 @@ public class SkeletonJson extends SkeletonLoader { data.spacingMode = SpacingMode.valueOf(constraintMap.getString("spacingMode", "length")); data.rotateMode = RotateMode.valueOf(constraintMap.getString("rotateMode", "tangent")); data.offsetRotation = constraintMap.getFloat("rotation", 0); - data.position = constraintMap.getFloat("position", 0); - if (data.positionMode == PositionMode.fixed) data.position *= scale; - data.spacing = constraintMap.getFloat("spacing", 0); - if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) data.spacing *= scale; - data.mixRotate = constraintMap.getFloat("mixRotate", 1); - data.mixX = constraintMap.getFloat("mixX", 1); - data.mixY = constraintMap.getFloat("mixY", 1); + PathConstraintPose setup = data.setup; + setup.position = constraintMap.getFloat("position", 0); + if (data.positionMode == PositionMode.fixed) setup.position *= scale; + setup.spacing = constraintMap.getFloat("spacing", 0); + if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) setup.spacing *= scale; + setup.mixRotate = constraintMap.getFloat("mixRotate", 1); + setup.mixX = constraintMap.getFloat("mixX", 1); + setup.mixY = constraintMap.getFloat("mixY", 1); skeletonData.pathConstraints.add(data); } @@ -388,13 +390,14 @@ public class SkeletonJson extends SkeletonLoader { data.shearX = constraintMap.getFloat("shearX", 0); data.limit = constraintMap.getFloat("limit", 5000) * scale; data.step = 1f / constraintMap.getInt("fps", 60); - data.inertia = constraintMap.getFloat("inertia", 1); - data.strength = constraintMap.getFloat("strength", 100); - data.damping = constraintMap.getFloat("damping", 1); - data.massInverse = 1 / constraintMap.getFloat("mass", 1); - data.wind = constraintMap.getFloat("wind", 0); - data.gravity = constraintMap.getFloat("gravity", 0); - data.mix = constraintMap.getFloat("mix", 1); + PhysicsConstraintPose setup = data.getSetupPose(); + setup.inertia = constraintMap.getFloat("inertia", 1); + setup.strength = constraintMap.getFloat("strength", 100); + setup.damping = constraintMap.getFloat("damping", 1); + setup.massInverse = 1 / constraintMap.getFloat("mass", 1); + setup.wind = constraintMap.getFloat("wind", 0); + setup.gravity = constraintMap.getFloat("gravity", 0); + setup.mix = constraintMap.getFloat("mix", 1); data.inertiaGlobal = constraintMap.getBoolean("inertiaGlobal", false); data.strengthGlobal = constraintMap.getBoolean("strengthGlobal", false); data.dampingGlobal = constraintMap.getBoolean("dampingGlobal", false); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java index f1912ab49..0dfcbdf31 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java @@ -38,8 +38,7 @@ import com.esotericsoftware.spine.Animation.MixDirection; public class Slider implements Updatable { final SliderData data; final Skeleton skeleton; - Animation animation; - float time, mix; + final SliderPose pose = new SliderPose(), applied = new SliderPose(); boolean active; @@ -59,14 +58,20 @@ public class Slider implements Updatable { } public void update (Physics physics) { - animation.apply(skeleton, time, time, false, null, mix, MixBlend.replace, MixDirection.in, true); + SliderPose pose = applied; + data.animation.apply(skeleton, pose.time, pose.time, false, null, pose.mix, MixBlend.replace, MixDirection.in, true); } public void setupPose () { - SliderData data = this.data; - animation = data.animation; - time = data.time; - mix = data.mix; + pose.set(data.setup); + } + + public SliderPose getPose () { + return pose; + } + + public SliderPose getAppliedPose () { + return applied; } /** Returns false when this constraint won't be updated by @@ -80,27 +85,7 @@ public class Slider implements Updatable { return active; } - public Animation getAnimation () { - return animation; - } - - public void setAnimation (Animation animation) { - this.animation = animation; - } - - public float getTime () { - return time; - } - - public void setTime (float time) { - this.time = time; - } - - public float getMix () { - return mix; - } - - public void setMix (float mix) { - this.mix = mix; + public String toString () { + return data.name; } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java index 321a11d62..38f91740b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderData.java @@ -33,13 +33,17 @@ package com.esotericsoftware.spine; *

* See Physics constraints in the Spine User Guide. */ public class SliderData extends ConstraintData { + final SliderPose setup = new SliderPose(); Animation animation; - float time, mix; public SliderData (String name) { super(name); } + public SliderPose getSetupPose () { + return setup; + } + public Animation getAnimation () { return animation; } @@ -47,20 +51,4 @@ public class SliderData extends ConstraintData { public void setAnimation (Animation animation) { this.animation = animation; } - - public float getTime () { - return time; - } - - public void setTime (float time) { - this.time = time; - } - - public float getMix () { - return mix; - } - - public void setMix (float mix) { - this.mix = mix; - } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java new file mode 100644 index 000000000..b613f6d3c --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +/** Stores a pose for a slider. */ +public class SliderPose { + float time, mix; + + public void set (SliderPose pose) { + time = pose.time; + mix = pose.mix; + } + + + public float getTime () { + return time; + } + + public void setTime (float time) { + this.time = time; + } + + public float getMix () { + return mix; + } + + public void setMix (float mix) { + this.mix = mix; + } +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index 813eb1688..6e2692e8e 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -44,11 +44,9 @@ public class TransformConstraint implements Updatable { final TransformConstraintData data; final Array bones; BoneApplied source; - TransformConstraint applied; + final TransformConstraintPose pose = new TransformConstraintPose(), applied = new TransformConstraintPose(); boolean active; - float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY; - public TransformConstraint (TransformConstraintData data, Array bones, BoneApplied source) { this.data = data; this.bones = bones; @@ -66,30 +64,24 @@ public class TransformConstraint implements Updatable { source = skeleton.bones.get(data.source.index).applied; - applied = new TransformConstraint(data, bones, source); - setupPose(); } /** Copy constructor. */ public TransformConstraint (TransformConstraint constraint, Skeleton skeleton) { this(constraint.data, skeleton); - setupPose(); + pose.set(constraint.pose); } public void setupPose () { - TransformConstraintData data = this.data; - mixRotate = data.mixRotate; - mixX = data.mixX; - mixY = data.mixY; - mixScaleX = data.mixScaleX; - mixScaleY = data.mixScaleY; - mixShearY = data.mixShearY; + pose.set(data.setup); } /** Applies the constraint to the constrained bones. */ public void update (Physics physics) { - if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0) return; + TransformConstraintPose pose = applied; + if (pose.mixRotate == 0 && pose.mixX == 0 && pose.mixY == 0 && pose.mixScaleX == 0 && pose.mixScaleY == 0 + && pose.mixShearY == 0) return; TransformConstraintData data = this.data; boolean localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp; @@ -105,7 +97,7 @@ public class TransformConstraint implements Updatable { Object[] toItems = from.to.items; for (int t = 0, tn = from.to.size; t < tn; t++) { var to = (ToProperty)toItems[t]; - if (to.mix(this) != 0) { + if (to.mix(pose) != 0) { float clamped = to.offset + value * to.scale; if (clamp) { if (to.offset < to.max) @@ -113,7 +105,7 @@ public class TransformConstraint implements Updatable { else clamped = clamp(clamped, to.max, to.offset); } - to.apply(this, bone, clamped, localTarget, additive); + to.apply(pose, bone, clamped, localTarget, additive); } } } @@ -139,58 +131,12 @@ public class TransformConstraint implements Updatable { this.source = source; } - /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ - public float getMixRotate () { - return mixRotate; + public TransformConstraintPose getPose () { + return pose; } - public void setMixRotate (float mixRotate) { - this.mixRotate = mixRotate; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ - public float getMixX () { - return mixX; - } - - public void setMixX (float mixX) { - this.mixX = mixX; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ - public float getMixY () { - return mixY; - } - - public void setMixY (float mixY) { - this.mixY = mixY; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ - public float getMixScaleX () { - return mixScaleX; - } - - public void setMixScaleX (float mixScaleX) { - this.mixScaleX = mixScaleX; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ - public float getMixScaleY () { - return mixScaleY; - } - - public void setMixScaleY (float mixScaleY) { - this.mixScaleY = mixScaleY; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */ - public float getMixShearY () { - return mixShearY; - } - - public void setMixShearY (float mixShearY) { - this.mixShearY = mixShearY; + public TransformConstraintPose getAppliedPose () { + return applied; } /** Returns false when this constraint won't be updated by diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java index 17c5baebe..547ceb699 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintData.java @@ -37,9 +37,9 @@ import com.badlogic.gdx.utils.Array; *

* See Transform constraints in the Spine User Guide. */ public class TransformConstraintData extends ConstraintData { + final TransformConstraintPose setup = new TransformConstraintPose(); final Array bones = new Array(); BoneData source; - float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY; float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY; boolean localSource, localTarget, additive, clamp; final Array properties = new Array(); @@ -48,6 +48,10 @@ public class TransformConstraintData extends ConstraintData { super(name); } + public TransformConstraintPose getSetupPose () { + return setup; + } + /** The bones that will be modified by this transform constraint. */ public Array getBones () { return bones; @@ -63,65 +67,6 @@ public class TransformConstraintData extends ConstraintData { this.source = source; } - /** The mapping of transform properties to other transform properties. */ - public Array getProperties () { - return properties; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ - public float getMixRotate () { - return mixRotate; - } - - public void setMixRotate (float mixRotate) { - this.mixRotate = mixRotate; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ - public float getMixX () { - return mixX; - } - - public void setMixX (float mixX) { - this.mixX = mixX; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ - public float getMixY () { - return mixY; - } - - public void setMixY (float mixY) { - this.mixY = mixY; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ - public float getMixScaleX () { - return mixScaleX; - } - - public void setMixScaleX (float mixScaleX) { - this.mixScaleX = mixScaleX; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y. */ - public float getMixScaleY () { - return mixScaleY; - } - - public void setMixScaleY (float mixScaleY) { - this.mixScaleY = mixScaleY; - } - - /** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */ - public float getMixShearY () { - return mixShearY; - } - - public void setMixShearY (float mixShearY) { - this.mixShearY = mixShearY; - } - /** An offset added to the constrained bone rotation. */ public float getOffsetRotation () { return offsetRotation; @@ -212,6 +157,11 @@ public class TransformConstraintData extends ConstraintData { this.clamp = clamp; } + /** The mapping of transform properties to other transform properties. */ + public Array getProperties () { + return properties; + } + /** Source property for a {@link TransformConstraint}. */ static abstract public class FromProperty { /** The value of this property that corresponds to {@link ToProperty#offset}. */ @@ -235,11 +185,11 @@ public class TransformConstraintData extends ConstraintData { /** The scale of the {@link FromProperty} value in relation to this property. */ public float scale; - /** Reads the mix for this property from the specified constraint. */ - abstract public float mix (TransformConstraint constraint); + /** Reads the mix for this property from the specified pose. */ + abstract public float mix (TransformConstraintPose pose); /** Applies the value to this property. */ - abstract public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive); + abstract public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive); } static public class FromRotate extends FromProperty { @@ -253,14 +203,14 @@ public class TransformConstraintData extends ConstraintData { } static public class ToRotate extends ToProperty { - public float mix (TransformConstraint constraint) { - return constraint.mixRotate; + public float mix (TransformConstraintPose pose) { + return pose.mixRotate; } - public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (!additive) value -= bone.rotation; - bone.rotation += value * constraint.mixRotate; + bone.rotation += value * pose.mixRotate; } else { float a = bone.a, b = bone.b, c = bone.c, d = bone.d; value *= degRad; @@ -269,7 +219,7 @@ public class TransformConstraintData extends ConstraintData { value -= PI2; else if (value < -PI) // value += PI2; - value *= constraint.mixRotate; + value *= pose.mixRotate; float cos = cos(value), sin = sin(value); bone.a = cos * a - sin * c; bone.b = cos * b - sin * d; @@ -286,17 +236,17 @@ public class TransformConstraintData extends ConstraintData { } static public class ToX extends ToProperty { - public float mix (TransformConstraint constraint) { - return constraint.mixX; + public float mix (TransformConstraintPose pose) { + return pose.mixX; } - public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (!additive) value -= bone.x; - bone.x += value * constraint.mixX; + bone.x += value * pose.mixX; } else { if (!additive) value -= bone.worldX; - bone.worldX += value * constraint.mixX; + bone.worldX += value * pose.mixX; } } } @@ -308,17 +258,17 @@ public class TransformConstraintData extends ConstraintData { } static public class ToY extends ToProperty { - public float mix (TransformConstraint constraint) { - return constraint.mixY; + public float mix (TransformConstraintPose pose) { + return pose.mixY; } - public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (!additive) value -= bone.y; - bone.y += value * constraint.mixY; + bone.y += value * pose.mixY; } else { if (!additive) value -= bone.worldY; - bone.worldY += value * constraint.mixY; + bone.worldY += value * pose.mixY; } } } @@ -330,23 +280,23 @@ public class TransformConstraintData extends ConstraintData { } static public class ToScaleX extends ToProperty { - public float mix (TransformConstraint constraint) { - return constraint.mixScaleX; + public float mix (TransformConstraintPose pose) { + return pose.mixScaleX; } - public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (additive) - bone.scaleX *= 1 + ((value - 1) * constraint.mixScaleX); + bone.scaleX *= 1 + ((value - 1) * pose.mixScaleX); else if (bone.scaleX != 0) // - bone.scaleX = 1 + (value / bone.scaleX - 1) * constraint.mixScaleX; + bone.scaleX = 1 + (value / bone.scaleX - 1) * pose.mixScaleX; } else { float s; if (additive) - s = 1 + (value - 1) * constraint.mixScaleX; + s = 1 + (value - 1) * pose.mixScaleX; else { s = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c); - if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleX; + if (s != 0) s = 1 + (value / s - 1) * pose.mixScaleX; } bone.a *= s; bone.c *= s; @@ -361,23 +311,23 @@ public class TransformConstraintData extends ConstraintData { } static public class ToScaleY extends ToProperty { - public float mix (TransformConstraint constraint) { - return constraint.mixScaleY; + public float mix (TransformConstraintPose pose) { + return pose.mixScaleY; } - public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (additive) - bone.scaleY *= 1 + ((value - 1) * constraint.mixScaleY); + bone.scaleY *= 1 + ((value - 1) * pose.mixScaleY); else if (bone.scaleY != 0) // - bone.scaleY = 1 + (value / bone.scaleY - 1) * constraint.mixScaleY; + bone.scaleY = 1 + (value / bone.scaleY - 1) * pose.mixScaleY; } else { float s; if (additive) - s = 1 + (value - 1) * constraint.mixScaleY; + s = 1 + (value - 1) * pose.mixScaleY; else { s = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d); - if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleY; + if (s != 0) s = 1 + (value / s - 1) * pose.mixScaleY; } bone.b *= s; bone.d *= s; @@ -393,14 +343,14 @@ public class TransformConstraintData extends ConstraintData { } static public class ToShearY extends ToProperty { - public float mix (TransformConstraint constraint) { - return constraint.mixShearY; + public float mix (TransformConstraintPose pose) { + return pose.mixShearY; } - public void apply (TransformConstraint constraint, BoneApplied bone, float value, boolean local, boolean additive) { + public void apply (TransformConstraintPose pose, BoneApplied bone, float value, boolean local, boolean additive) { if (local) { if (!additive) value -= bone.shearY; - bone.shearY += value * constraint.mixShearY; + bone.shearY += value * pose.mixShearY; } else { float b = bone.b, d = bone.d, by = atan2(d, b); value = (value + 90) * degRad; @@ -413,7 +363,7 @@ public class TransformConstraintData extends ConstraintData { else if (value < -PI) // value += PI2; } - value = by + value * constraint.mixShearY; + value = by + value * pose.mixShearY; float s = (float)Math.sqrt(b * b + d * d); bone.b = cos(value) * s; bone.d = sin(value) * s; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintPose.java new file mode 100644 index 000000000..5d234addb --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraintPose.java @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +/** Stores a pose for a transform constraint. */ +public class TransformConstraintPose { + float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY; + + public void set (TransformConstraintPose pose) { + mixRotate = pose.mixRotate; + mixX = pose.mixX; + mixY = pose.mixY; + mixScaleX = pose.mixScaleX; + mixScaleY = pose.mixScaleY; + mixShearY = pose.mixShearY; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ + public float getMixRotate () { + return mixRotate; + } + + public void setMixRotate (float mixRotate) { + this.mixRotate = mixRotate; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation X. */ + public float getMixX () { + return mixX; + } + + public void setMixX (float mixX) { + this.mixX = mixX; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y. */ + public float getMixY () { + return mixY; + } + + public void setMixY (float mixY) { + this.mixY = mixY; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ + public float getMixScaleX () { + return mixScaleX; + } + + public void setMixScaleX (float mixScaleX) { + this.mixScaleX = mixScaleX; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained scale X. */ + public float getMixScaleY () { + return mixScaleY; + } + + public void setMixScaleY (float mixScaleY) { + this.mixScaleY = mixScaleY; + } + + /** A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y. */ + public float getMixShearY () { + return mixShearY; + } + + public void setMixShearY (float mixShearY) { + this.mixShearY = mixShearY; + } +} From a8c081dbb14d02128a9ffcd31651c0f5c5aadea3 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Tue, 15 Apr 2025 23:45:34 -0400 Subject: [PATCH 30/75] [libgdx] Optimized setting the applied pose. --- .../spine/AnimationState.java | 6 +- .../src/com/esotericsoftware/spine/Bone.java | 20 +- .../esotericsoftware/spine/BoneApplied.java | 15 +- .../esotericsoftware/spine/Constrained.java | 36 ++++ .../esotericsoftware/spine/IkConstraint.java | 33 ++- .../spine/PathConstraint.java | 19 +- .../spine/PhysicsConstraint.java | 25 ++- .../com/esotericsoftware/spine/Skeleton.java | 190 ++++++++---------- .../spine/SkeletonBinary.java | 4 +- .../esotericsoftware/spine/SkeletonJson.java | 6 +- .../spine/SkeletonRenderer.java | 6 +- .../src/com/esotericsoftware/spine/Skin.java | 2 +- .../com/esotericsoftware/spine/Slider.java | 19 +- .../esotericsoftware/spine/SliderPose.java | 1 - .../src/com/esotericsoftware/spine/Slot.java | 19 +- .../spine/TransformConstraint.java | 32 ++- .../spine/{Updatable.java => Update.java} | 2 +- 17 files changed, 261 insertions(+), 174 deletions(-) create mode 100644 spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constrained.java rename spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/{Updatable.java => Update.java} (98%) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index 0097bdc77..8ca3d121c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -278,7 +278,7 @@ public class AnimationState { var slot = (Slot)slots[i]; if (slot.attachmentState == setupState) { String attachmentName = slot.data.attachmentName; - slot.getPose().setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + slot.pose.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); } } unkeyedState += 2; // Increasing after each use avoids the need to reset attachmentState for every slot. @@ -399,7 +399,7 @@ public class AnimationState { } private void setAttachment (Skeleton skeleton, Slot slot, String attachmentName, boolean attachments) { - slot.getPose().setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + slot.pose.setAttachment(attachmentName == null ? null : skeleton.getAttachment(slot.data.index, attachmentName)); if (attachments) slot.attachmentState = unkeyedState + CURRENT; } @@ -417,7 +417,7 @@ public class AnimationState { Bone bone = skeleton.bones.get(timeline.boneIndex); if (!bone.active) return; - BonePose pose = bone.getPose(), setup = bone.data.setup; + BonePose pose = bone.pose, setup = bone.data.setup; float[] frames = timeline.frames; float r1, r2; if (time < frames[0]) { // Time is before first frame. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java index 9fcc49a6c..3c1acf9a0 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java @@ -38,13 +38,13 @@ import com.badlogic.gdx.utils.Null; * A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a * constraint or application code modifies the world transform after it was computed from the local transform. */ -public class Bone { +public class Bone implements Constrained { final BoneData data; final Skeleton skeleton; @Null final Bone parent; final Array children = new Array(); - final BonePose pose = new BonePose(); - final BoneApplied applied = new BoneApplied(this); + final BoneApplied pose = new BoneApplied(this), constrained = new BoneApplied(this); + BoneApplied applied = pose; boolean sorted, active; public Bone (BoneData data, Skeleton skeleton, @Null Bone parent) { @@ -74,16 +74,26 @@ public class Bone { return data; } - /** Returns the bone's pose. */ public BonePose getPose () { return pose; } - /** Returns the bone's applied pose. */ public BoneApplied getAppliedPose () { return applied; } + public BoneApplied getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** The skeleton this bone belongs to. */ public Skeleton getSkeleton () { return skeleton; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java index f86947504..e3b8efdb6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneApplied.java @@ -6,21 +6,18 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; import com.badlogic.gdx.math.Matrix3; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.BoneData.Inherit; /** The applied pose for a bone. This is the {@link Bone} pose with constraints applied and the world transform computed by * {@link Skeleton#updateWorldTransform(Physics)}. */ -public class BoneApplied extends BonePose implements Updatable { +public class BoneApplied extends BonePose implements Update { final Bone bone; - @Null final BoneApplied parent; float a, b, worldX; float c, d, worldY; BoneApplied (Bone bone) { this.bone = bone; - parent = bone.parent == null ? null : bone.parent.applied; } /** Computes the world transform using the parent bone and this bone's local applied transform. */ @@ -37,8 +34,7 @@ public class BoneApplied extends BonePose implements Updatable { * See World transforms in the Spine * Runtimes Guide. */ public void update (Physics physics) { - BoneApplied parent = this.parent; - if (parent == null) { // Root bone. + if (bone.parent == null) { // Root bone. Skeleton skeleton = bone.skeleton; float sx = skeleton.scaleX, sy = skeleton.scaleY; float rx = (rotation + shearX) * degRad; @@ -52,6 +48,7 @@ public class BoneApplied extends BonePose implements Updatable { return; } + BoneApplied parent = bone.parent.applied; float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; worldX = pa * x + pb * y + parent.worldX; worldY = pc * x + pd * y + parent.worldY; @@ -147,7 +144,7 @@ public class BoneApplied extends BonePose implements Updatable { * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */ public void updateLocalTransform () { - BoneApplied parent = this.parent; + BoneApplied parent = bone.parent.applied; if (parent == null) { x = worldX - bone.skeleton.x; y = worldY - bone.skeleton.y; @@ -336,13 +333,13 @@ public class BoneApplied extends BonePose implements Updatable { /** Transforms a point from world coordinates to the parent bone's local coordinates. */ public Vector2 worldToParent (Vector2 world) { if (world == null) throw new IllegalArgumentException("world cannot be null."); - return parent == null ? world : parent.worldToLocal(world); + return bone.parent == null ? world : bone.parent.applied.worldToLocal(world); } /** Transforms a point from the parent bone's coordinates to world coordinates. */ public Vector2 parentToWorld (Vector2 world) { if (world == null) throw new IllegalArgumentException("world cannot be null."); - return parent == null ? world : parent.localToWorld(world); + return bone.parent == null ? world : bone.parent.applied.localToWorld(world); } /** Transforms a world rotation to a local rotation. */ diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constrained.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constrained.java new file mode 100644 index 000000000..ac8e8100d --- /dev/null +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Constrained.java @@ -0,0 +1,36 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated April 5, 2025. Replaces all prior versions. + * + * Copyright (c) 2013-2025, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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 com.esotericsoftware.spine; + +public interface Constrained { + public void setConstrained (boolean constrained); + + public void resetAppliedPose (); +} diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java index 41c6eb707..4e4f843a6 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/IkConstraint.java @@ -39,11 +39,12 @@ import com.esotericsoftware.spine.BoneData.Inherit; * the last bone is as close to the target bone as possible. *

* See IK constraints in the Spine User Guide. */ -public class IkConstraint implements Updatable { +public class IkConstraint implements Constrained, Update { final IkConstraintData data; final Array bones; - BoneApplied target; - final IkConstraintPose pose = new IkConstraintPose(), applied = new IkConstraintPose(); + Bone target; + final IkConstraintPose pose = new IkConstraintPose(), constrained = new IkConstraintPose(); + IkConstraintPose applied = pose; boolean active; public IkConstraint (IkConstraintData data, Skeleton skeleton) { @@ -53,9 +54,9 @@ public class IkConstraint implements Updatable { bones = new Array(data.bones.size); for (BoneData boneData : data.bones) - bones.add(skeleton.bones.get(boneData.index).applied); + bones.add(skeleton.bones.get(boneData.index).constrained); - target = skeleton.bones.get(data.target.index).applied; + target = skeleton.bones.get(data.target.index); setupPose(); } @@ -74,7 +75,7 @@ public class IkConstraint implements Updatable { public void update (Physics physics) { IkConstraintPose a = applied; if (a.mix == 0) return; - BoneApplied target = this.target; + BoneApplied target = this.target.applied; Object[] bones = this.bones.items; switch (this.bones.size) { case 1 -> apply((BoneApplied)bones[0], target.worldX, target.worldY, a.compress, a.stretch, data.uniform, a.mix); @@ -90,11 +91,11 @@ public class IkConstraint implements Updatable { } /** The bone that is the IK target. */ - public BoneApplied getTarget () { + public Bone getTarget () { return target; } - public void setTarget (BoneApplied target) { + public void setTarget (Bone target) { if (target == null) throw new IllegalArgumentException("target cannot be null."); this.target = target; } @@ -107,6 +108,18 @@ public class IkConstraint implements Updatable { return applied; } + public IkConstraintPose getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** Returns false when this constraint won't be updated by * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. @@ -131,7 +144,7 @@ public class IkConstraint implements Updatable { static public void apply (BoneApplied bone, float targetX, float targetY, boolean compress, boolean stretch, boolean uniform, float alpha) { if (bone == null) throw new IllegalArgumentException("bone cannot be null."); - BoneApplied p = bone.parent; + BoneApplied p = bone.bone.parent.applied; float pa = p.a, pb = p.b, pc = p.c, pd = p.d; float rotationIK = -bone.shearX - bone.rotation, tx, ty; switch (bone.inherit) { @@ -222,7 +235,7 @@ public class IkConstraint implements Updatable { cwx = a * child.x + b * child.y + parent.worldX; cwy = c * child.x + d * child.y + parent.worldY; } - BoneApplied pp = parent.parent; + BoneApplied pp = parent.bone.parent.applied; a = pp.a; b = pp.b; c = pp.c; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java index aa0b7e33f..f2120ec89 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PathConstraint.java @@ -45,14 +45,15 @@ import com.esotericsoftware.spine.attachments.PathAttachment; * constrained bones so they follow a {@link PathAttachment}. *

* See Path constraints in the Spine User Guide. */ -public class PathConstraint implements Updatable { +public class PathConstraint implements Constrained, Update { static final int NONE = -1, BEFORE = -2, AFTER = -3; static final float epsilon = 0.00001f; final PathConstraintData data; final Array bones; Slot slot; - final PathConstraintPose pose = new PathConstraintPose(), applied = new PathConstraintPose(); + final PathConstraintPose pose = new PathConstraintPose(), constrained = new PathConstraintPose(); + PathConstraintPose applied = pose; boolean active; private final FloatArray spaces = new FloatArray(), positions = new FloatArray(); @@ -72,7 +73,7 @@ public class PathConstraint implements Updatable { bones = new Array(data.bones.size); for (BoneData boneData : data.bones) - bones.add(skeleton.bones.get(boneData.index).applied); + bones.add(skeleton.bones.get(boneData.index).constrained); slot = skeleton.slots.get(data.slot.index); @@ -495,6 +496,18 @@ public class PathConstraint implements Updatable { return applied; } + public PathConstraintPose getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** Returns false when this constraint won't be updated by * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index 8fa8b0cbc..e5b7ccba4 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -34,11 +34,12 @@ import static com.esotericsoftware.spine.utils.SpineUtils.*; /** Stores the current pose for a physics constraint. A physics constraint applies physics to bones. *

* See Physics constraints in the Spine User Guide. */ -public class PhysicsConstraint implements Updatable { +public class PhysicsConstraint implements Constrained, Update { final PhysicsConstraintData data; final Skeleton skeleton; BoneApplied bone; - final PhysicsConstraintPose pose = new PhysicsConstraintPose(), applied = new PhysicsConstraintPose(); + final PhysicsConstraintPose pose = new PhysicsConstraintPose(), constrained = new PhysicsConstraintPose(); + PhysicsConstraintPose applied = pose; boolean active; boolean reset = true; @@ -49,19 +50,13 @@ public class PhysicsConstraint implements Updatable { float scaleOffset, scaleVelocity; float remaining, lastTime; - private PhysicsConstraint (PhysicsConstraintData data, Skeleton skeleton, BoneApplied bone) { - this.data = data; - this.skeleton = skeleton; - this.bone = bone; - } - public PhysicsConstraint (PhysicsConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null."); this.data = data; this.skeleton = skeleton; - bone = skeleton.bones.get(data.bone.index).applied; + bone = skeleton.bones.get(data.bone.index).constrained; setupPose(); } @@ -300,6 +295,18 @@ public class PhysicsConstraint implements Updatable { return applied; } + public PhysicsConstraintPose getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** Returns false when this constraint won't be updated by * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 9e6c63040..795bcebd8 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -38,6 +38,7 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.Animation.BoneTimeline; +import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Skin.SkinEntry; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.ClippingAttachment; @@ -52,7 +53,7 @@ import com.esotericsoftware.spine.utils.SkeletonClipping; * Runtimes Guide. */ public class Skeleton { static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0}; - private static final Object IkConstraint = null; + final SkeletonData data; final Array bones; final Array slots; @@ -62,7 +63,8 @@ public class Skeleton { final Array transformConstraints; final Array pathConstraints; final Array physicsConstraints; - final Array updateCache = new Array(); + final Array updateCache = new Array(); + final Array resetCache = new Array(); @Null Skin skin; final Color color; float x, y, scaleX = 1, scaleY = 1, time; @@ -180,8 +182,8 @@ public class Skeleton { /** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones, * constraints, or weighted path attachments are added or removed. */ public void updateCache () { - Array updateCache = this.updateCache; updateCache.clear(); + resetCache.clear(); int boneCount = bones.size; Object[] bones = this.bones.items; @@ -189,6 +191,7 @@ public class Skeleton { var bone = (Bone)bones[i]; bone.sorted = bone.data.skinRequired; bone.active = !bone.sorted; + bone.setConstrained(false); } if (skin != null) { Object[] skinBones = skin.bones.items; @@ -207,6 +210,17 @@ public class Skeleton { Object[] sliders = this.sliders.items, ikConstraints = this.ikConstraints.items, transformConstraints = this.transformConstraints.items, pathConstraints = this.pathConstraints.items, physicsConstraints = this.physicsConstraints.items; + for (int ii = 0; ii < sliderCount; ii++) + ((Slider)sliders[ii]).setConstrained(false); + for (int ii = 0; ii < ikCount; ii++) + ((IkConstraint)ikConstraints[ii]).setConstrained(false); + for (int ii = 0; ii < transformCount; ii++) + ((TransformConstraint)transformConstraints[ii]).setConstrained(false); + for (int ii = 0; ii < pathCount; ii++) + ((PathConstraint)pathConstraints[ii]).setConstrained(false); + for (int ii = 0; ii < physicsCount; ii++) + ((PhysicsConstraint)physicsConstraints[ii]).setConstrained(false); + int constraintCount = ikCount + transformCount + pathCount + physicsCount; outer: for (int i = 0; i < constraintCount; i++) { @@ -249,47 +263,29 @@ public class Skeleton { for (int i = 0; i < boneCount; i++) sortBone((Bone)bones[i]); - } - private void sortSlider (Slider constraint) { - constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)); - if (!constraint.active) return; - - Object[] timelines = constraint.data.animation.timelines.items; - int timelineCount = constraint.data.animation.timelines.size; - - Object[] bones = this.bones.items; - for (int i = 0; i < timelineCount; i++) - if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); - - updateCache.add(constraint); - - for (int i = 0; i < timelineCount; i++) { - if (timelines[i] instanceof BoneTimeline boneTimeline) { - var bone = (Bone)bones[boneTimeline.getBoneIndex()]; - sortReset(bone.children); - bone.sorted = false; - } - } - for (int i = 0; i < timelineCount; i++) - if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + Object[] updateCache = this.updateCache.items; + for (int i = 0, n = this.updateCache.size; i < n; i++) + if (updateCache[i] instanceof Bone bone) updateCache[i] = bone.applied; } private void sortIkConstraint (IkConstraint constraint) { - constraint.active = constraint.target.bone.active + constraint.active = constraint.target.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; - sortBone(constraint.target.bone); + sortBone(constraint.target); Array constrained = constraint.bones; Bone parent = constrained.first().bone; sortBone(parent); + resetCache(parent); if (constrained.size == 1) { updateCache.add(constraint); sortReset(parent.children); } else { Bone child = constrained.peek().bone; + resetCache(child); sortBone(child); updateCache.add(constraint); @@ -300,23 +296,27 @@ public class Skeleton { } private void sortTransformConstraint (TransformConstraint constraint) { - constraint.active = constraint.source.bone.active + constraint.active = constraint.source.active && (!constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true))); if (!constraint.active) return; - sortBone(constraint.source.bone); + sortBone(constraint.source); Object[] constrained = constraint.bones.items; int boneCount = constraint.bones.size; if (constraint.data.localSource) { for (int i = 0; i < boneCount; i++) { Bone child = ((BoneApplied)constrained[i]).bone; + resetCache(child); sortBone(child.parent); sortBone(child); } } else { - for (int i = 0; i < boneCount; i++) - sortBone(((BoneApplied)constrained[i]).bone); + for (int i = 0; i < boneCount; i++) { + Bone bone = ((BoneApplied)constrained[i]).bone; + resetCache(bone); + sortBone(bone); + } } updateCache.add(constraint); @@ -343,8 +343,11 @@ public class Skeleton { Object[] constrained = constraint.bones.items; int boneCount = constraint.bones.size; - for (int i = 0; i < boneCount; i++) - sortBone(((BoneApplied)constrained[i]).bone); + for (int i = 0; i < boneCount; i++) { + Bone bone = ((BoneApplied)constrained[i]).bone; + resetCache(bone); + sortBone(bone); + } updateCache.add(constraint); @@ -386,18 +389,53 @@ public class Skeleton { sortBone(bone); + resetCache(bone); updateCache.add(constraint); sortReset(bone.children); bone.sorted = true; } + private void sortSlider (Slider constraint) { + constraint.active = !constraint.data.skinRequired || (skin != null && skin.constraints.contains(constraint.data, true)); + if (!constraint.active) return; + + Object[] timelines = constraint.data.animation.timelines.items; + int timelineCount = constraint.data.animation.timelines.size; + + Object[] bones = this.bones.items; + for (int i = 0; i < timelineCount; i++) { + var timeline = (Timeline)timelines[i]; + if (timeline instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + } + + updateCache.add(constraint); + + for (int i = 0; i < timelineCount; i++) { + if (timelines[i] instanceof BoneTimeline boneTimeline) { + var bone = (Bone)bones[boneTimeline.getBoneIndex()]; + resetCache(bone); + sortReset(bone.children); + bone.sorted = false; + } + } + for (int i = 0; i < timelineCount; i++) + if (timelines[i] instanceof BoneTimeline boneTimeline) sortBone((Bone)bones[boneTimeline.getBoneIndex()]); + } + + private void resetCache (Constrained object) { + if (!resetCache.contains(object, true)) { + resetCache.add(object); + object.setConstrained(true); + } + } + private void sortBone (Bone bone) { if (bone.sorted) return; Bone parent = bone.parent; if (parent != null) sortBone(parent); bone.sorted = true; - updateCache.add(bone.applied); + updateCache.add(bone); } private void sortReset (Array bones) { @@ -415,45 +453,13 @@ public class Skeleton { * See World transforms in the Spine * Runtimes Guide. */ public void updateWorldTransform (Physics physics) { - Object[] objects = this.bones.items; - for (int i = 0, n = this.bones.size; i < n; i++) { - var bone = (Bone)objects[i]; - if (bone.active) bone.applied.set(bone.pose); - } - objects = this.slots.items; - for (int i = 0, n = this.slots.size; i < n; i++) { - var slot = (Slot)objects[i]; - if (slot.bone.active) slot.applied.set(slot.pose); - } - objects = ikConstraints.items; - for (int i = 0, n = ikConstraints.size; i < n; i++) { - var constraint = (IkConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = pathConstraints.items; - for (int i = 0, n = pathConstraints.size; i < n; i++) { - var constraint = (PathConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = transformConstraints.items; - for (int i = 0, n = transformConstraints.size; i < n; i++) { - var constraint = (TransformConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = physicsConstraints.items; - for (int i = 0, n = physicsConstraints.size; i < n; i++) { - var constraint = (PhysicsConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = sliders.items; - for (int i = 0, n = sliders.size; i < n; i++) { - var constraint = (Slider)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } + Object[] resetCache = this.resetCache.items; + for (int i = 0, n = this.resetCache.size; i < n; i++) + ((Constrained)resetCache[i]).resetAppliedPose(); Object[] updateCache = this.updateCache.items; for (int i = 0, n = this.updateCache.size; i < n; i++) - ((Updatable)updateCache[i]).update(physics); + ((Update)updateCache[i]).update(physics); } /** Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies @@ -464,41 +470,9 @@ public class Skeleton { public void updateWorldTransform (Physics physics, BoneApplied parent) { if (parent == null) throw new IllegalArgumentException("parent cannot be null."); - Object[] objects = this.bones.items; - for (int i = 0, n = this.bones.size; i < n; i++) { - var bone = (Bone)objects[i]; - if (bone.active) bone.applied.set(bone.pose); - } - objects = this.slots.items; - for (int i = 0, n = this.slots.size; i < n; i++) { - var slot = (Slot)objects[i]; - if (slot.bone.active) slot.applied.set(slot.pose); - } - objects = ikConstraints.items; - for (int i = 0, n = ikConstraints.size; i < n; i++) { - var constraint = (IkConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = pathConstraints.items; - for (int i = 0, n = pathConstraints.size; i < n; i++) { - var constraint = (PathConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = transformConstraints.items; - for (int i = 0, n = transformConstraints.size; i < n; i++) { - var constraint = (TransformConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = physicsConstraints.items; - for (int i = 0, n = physicsConstraints.size; i < n; i++) { - var constraint = (PhysicsConstraint)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } - objects = sliders.items; - for (int i = 0, n = sliders.size; i < n; i++) { - var constraint = (Slider)objects[i]; - if (constraint.active) constraint.applied.set(constraint.pose); - } + Object[] resetCache = this.resetCache.items; + for (int i = 0, n = this.resetCache.size; i < n; i++) + ((Constrained)resetCache[i]).resetAppliedPose(); // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. BoneApplied rootBone = getRootBone().applied; @@ -520,7 +494,7 @@ public class Skeleton { // Update everything except root bone. Object[] updateCache = this.updateCache.items; for (int i = 0, n = this.updateCache.size; i < n; i++) { - var updatable = (Updatable)updateCache[i]; + var updatable = (Update)updateCache[i]; if (updatable != rootBone) updatable.update(physics); } } @@ -578,7 +552,7 @@ public class Skeleton { } /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */ - public Array getUpdateCache () { + public Array getUpdateCache () { return updateCache; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index ac72e6884..bf055ba6b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -343,7 +343,7 @@ public class SkeletonBinary extends SkeletonLoader { if ((flags & 16) != 0) data.offsetScaleY = input.readFloat(); if ((flags & 32) != 0) data.offsetShearY = input.readFloat(); flags = input.read(); - TransformConstraintPose setup = data.getSetupPose(); + TransformConstraintPose setup = data.setup; if ((flags & 1) != 0) setup.mixRotate = input.readFloat(); if ((flags & 2) != 0) setup.mixX = input.readFloat(); if ((flags & 4) != 0) setup.mixY = input.readFloat(); @@ -394,7 +394,7 @@ public class SkeletonBinary extends SkeletonLoader { if ((flags & 32) != 0) data.shearX = input.readFloat(); data.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale; data.step = 1f / input.readUnsignedByte(); - PhysicsConstraintPose setup = data.getSetupPose(); + PhysicsConstraintPose setup = data.setup; setup.inertia = input.readFloat(); setup.strength = input.readFloat(); setup.damping = input.readFloat(); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index e944bcb55..ca14c5e06 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -204,10 +204,10 @@ public class SkeletonJson extends SkeletonLoader { var data = new SlotData(skeletonData.slots.size, slotName, boneData); String color = slotMap.getString("color", null); - if (color != null) Color.valueOf(color, data.getSetupPose().getColor()); + if (color != null) Color.valueOf(color, data.setup.getColor()); String dark = slotMap.getString("dark", null); - if (dark != null) Color.valueOf(dark, data.getSetupPose().getDarkColor()); + if (dark != null) Color.valueOf(dark, data.setup.getDarkColor()); data.attachmentName = slotMap.getString("attachment", null); data.blendMode = BlendMode.valueOf(slotMap.getString("blend", BlendMode.normal.name())); @@ -390,7 +390,7 @@ public class SkeletonJson extends SkeletonLoader { data.shearX = constraintMap.getFloat("shearX", 0); data.limit = constraintMap.getFloat("limit", 5000) * scale; data.step = 1f / constraintMap.getInt("fps", 60); - PhysicsConstraintPose setup = data.getSetupPose(); + PhysicsConstraintPose setup = data.setup; setup.inertia = constraintMap.getFloat("inertia", 1); setup.strength = constraintMap.getFloat("strength", 100); setup.damping = constraintMap.getFloat("damping", 1); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java index 8dd6eacd8..4c5c73143 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java @@ -80,7 +80,7 @@ public class SkeletonRenderer { for (int i = 0, n = skeleton.drawOrder.size; i < n; i++) { var slot = (Slot)drawOrder[i]; if (!slot.bone.active) continue; - SlotPose pose = slot.getAppliedPose(); + SlotPose pose = slot.applied; Attachment attachment = pose.attachment; if (attachment instanceof RegionAttachment region) { region.computeWorldVertices(slot, vertices, 0, 5); @@ -149,7 +149,7 @@ public class SkeletonRenderer { clipper.clipEnd(slot); continue; } - SlotPose pose = slot.getAppliedPose(); + SlotPose pose = slot.applied; Texture texture = null; Attachment attachment = pose.attachment; if (attachment instanceof RegionAttachment region) { @@ -244,7 +244,7 @@ public class SkeletonRenderer { clipper.clipEnd(slot); continue; } - SlotPose pose = slot.getAppliedPose(); + SlotPose pose = slot.applied; Texture texture = null; Attachment attachment = pose.attachment; if (attachment instanceof RegionAttachment region) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java index e49c80c95..a4c6f2d49 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skin.java @@ -157,7 +157,7 @@ public class Skin { Object[] slots = skeleton.slots.items; for (SkinEntry entry : oldSkin.attachments.orderedItems()) { int slotIndex = entry.slotIndex; - SlotPose slot = ((Slot)slots[slotIndex]).getPose(); + SlotPose slot = ((Slot)slots[slotIndex]).pose; if (slot.attachment == entry.attachment) { Attachment attachment = getAttachment(slotIndex, entry.name); if (attachment != null) slot.setAttachment(attachment); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java index 0dfcbdf31..f3ca5dd2b 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slider.java @@ -35,10 +35,11 @@ import com.esotericsoftware.spine.Animation.MixDirection; /** Stores the setup pose for a {@link PhysicsConstraint}. *

* See Physics constraints in the Spine User Guide. */ -public class Slider implements Updatable { +public class Slider implements Constrained, Update { final SliderData data; final Skeleton skeleton; - final SliderPose pose = new SliderPose(), applied = new SliderPose(); + final SliderPose pose = new SliderPose(), constrained = new SliderPose(); + SliderPose applied = pose; boolean active; @@ -54,7 +55,7 @@ public class Slider implements Updatable { /** Copy constructor. */ public Slider (Slider slider, Skeleton skeleton) { this(slider.data, skeleton); - setupPose(); + pose.set(slider.pose); } public void update (Physics physics) { @@ -74,6 +75,18 @@ public class Slider implements Updatable { return applied; } + public SliderPose getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** Returns false when this constraint won't be updated by * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java index b613f6d3c..039029584 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SliderPose.java @@ -38,7 +38,6 @@ public class SliderPose { mix = pose.mix; } - public float getTime () { return time; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java index 14893dc37..168a40236 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Slot.java @@ -34,10 +34,11 @@ import com.badlogic.gdx.graphics.Color; /** Stores a slot's current pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store * state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared * across multiple skeletons. */ -public class Slot { +public class Slot implements Constrained { final SlotData data; final Bone bone; - final SlotPose pose = new SlotPose(), applied = new SlotPose(); + final SlotPose pose = new SlotPose(), constrained = new SlotPose(); + SlotPose applied = pose; int attachmentState; public Slot (SlotData data, Skeleton skeleton) { @@ -76,16 +77,26 @@ public class Slot { return data; } - /** Returns the slot's pose. */ public SlotPose getPose () { return pose; } - /** Returns the slot's applied pose. */ public SlotPose getAppliedPose () { return applied; } + public SlotPose getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** The bone this slot belongs to. */ public Bone getBone () { return bone; diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java index 6e2692e8e..54cb02596 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java @@ -40,14 +40,15 @@ import com.esotericsoftware.spine.TransformConstraintData.ToProperty; * bones to match that of the source bone. *

* See Transform constraints in the Spine User Guide. */ -public class TransformConstraint implements Updatable { +public class TransformConstraint implements Constrained, Update { final TransformConstraintData data; final Array bones; - BoneApplied source; - final TransformConstraintPose pose = new TransformConstraintPose(), applied = new TransformConstraintPose(); + Bone source; + final TransformConstraintPose pose = new TransformConstraintPose(), constrained = new TransformConstraintPose(); + TransformConstraintPose applied = pose; boolean active; - public TransformConstraint (TransformConstraintData data, Array bones, BoneApplied source) { + public TransformConstraint (TransformConstraintData data, Array bones, Bone source) { this.data = data; this.bones = bones; this.source = source; @@ -60,9 +61,9 @@ public class TransformConstraint implements Updatable { bones = new Array(data.bones.size); for (BoneData boneData : data.bones) - bones.add(skeleton.bones.get(boneData.index).applied); + bones.add(skeleton.bones.get(boneData.index).constrained); - source = skeleton.bones.get(data.source.index).applied; + source = skeleton.bones.get(data.source.index); setupPose(); } @@ -85,12 +86,13 @@ public class TransformConstraint implements Updatable { TransformConstraintData data = this.data; boolean localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp; - BoneApplied source = this.source; + BoneApplied source = this.source.applied; Object[] fromItems = data.properties.items; int fn = data.properties.size; Object[] bones = this.bones.items; for (int i = 0, n = this.bones.size; i < n; i++) { var bone = (BoneApplied)bones[i]; + if (bone.bone.applied != bone.bone.constrained) System.out.println(); for (int f = 0; f < fn; f++) { var from = (FromProperty)fromItems[f]; float value = from.value(data, source, localFrom) - from.offset; @@ -122,11 +124,11 @@ public class TransformConstraint implements Updatable { } /** The bone whose world transform will be copied to the constrained bones. */ - public BoneApplied getSource () { + public Bone getSource () { return source; } - public void setSource (BoneApplied source) { + public void setSource (Bone source) { if (source == null) throw new IllegalArgumentException("source cannot be null."); this.source = source; } @@ -139,6 +141,18 @@ public class TransformConstraint implements Updatable { return applied; } + public TransformConstraintPose getConstrainedPose () { + return constrained; + } + + public void setConstrained (boolean constrained) { + applied = constrained ? this.constrained : pose; + } + + public void resetAppliedPose () { + applied.set(pose); + } + /** Returns false when this constraint won't be updated by * {@link Skeleton#updateWorldTransform(com.esotericsoftware.spine.Physics)} because a skin is required and the * {@link Skeleton#getSkin() active skin} does not contain this item. diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Update.java similarity index 98% rename from spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java rename to spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Update.java index 0864002f2..f2e933e3a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Updatable.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Update.java @@ -30,7 +30,7 @@ package com.esotericsoftware.spine; /** The interface for items updated by {@link Skeleton#updateWorldTransform(Physics)}. */ -public interface Updatable { +public interface Update { /** @param physics Determines how physics and other non-deterministic updates are applied. */ public void update (Physics physics); } From b2c12b9d06d808c9b30890ac69b8583efa577414 Mon Sep 17 00:00:00 2001 From: Davide <7047501+davidetan@users.noreply.github.com> Date: Wed, 16 Apr 2025 17:01:53 +0200 Subject: [PATCH 31/75] [ts][phaser-v3][phaser-v4] New runtime for phaser-v4. Moved phaser to phaser-v3 (#2815) --- .gitignore | 3 +- examples/export/runtimes.sh | 103 +- spine-ts/README.md | 11 +- spine-ts/index.html | 113 +- spine-ts/package-lock.json | 1464 +- spine-ts/package.json | 20 +- .../{spine-phaser => spine-phaser-v3}/LICENSE | 0 .../README.md | 2 +- .../spine-phaser-v3/dist/SpineGameObject.d.ts | 137 + .../spine-phaser-v3/dist/SpineGameObject.js | 300 + .../spine-phaser-v3/dist/SpinePlugin.d.ts | 95 + spine-ts/spine-phaser-v3/dist/SpinePlugin.js | 350 + .../dist/esm/spine-phaser-v3.mjs | 15405 + .../dist/esm/spine-phaser-v3.mjs.map | 7 + .../dist/iife/spine-phaser-v3.js | 15445 + .../dist/iife/spine-phaser-v3.js.map | 7 + spine-ts/spine-phaser-v3/dist/index.d.ts | 58 + spine-ts/spine-phaser-v3/dist/index.js | 38 + spine-ts/spine-phaser-v3/dist/keys.d.ts | 34 + spine-ts/spine-phaser-v3/dist/keys.js | 35 + spine-ts/spine-phaser-v3/dist/mixins.d.ts | 30 + spine-ts/spine-phaser-v3/dist/mixins.js | 48 + .../spine-phaser-v3/dist/require-shim.d.ts | 32 + spine-ts/spine-phaser-v3/dist/require-shim.js | 39 + .../example/add-existing.html | 2 +- .../example/arcade-physics-example.html | 2 +- .../example/assets/celestial-circus-pma.atlas | 0 .../example/assets/celestial-circus-pma.png | Bin .../example/assets/celestial-circus-pro.json | 0 .../example/assets/celestial-circus-pro.skel | Bin .../example/assets/celestial-circus.atlas | 0 .../example/assets/celestial-circus.png | Bin .../example/assets/cloud-pot.atlas | 0 .../example/assets/cloud-pot.json | 0 .../example/assets/cloud-pot.png | Bin .../example/assets/cloud-pot.skel | Bin .../example/assets/coin-pma.atlas | 0 .../example/assets/coin-pma.png | Bin .../example/assets/coin-pro.skel | Bin .../example/assets/mix-and-match-pma.atlas | 0 .../example/assets/mix-and-match-pma.png | Bin .../example/assets/mix-and-match-pro.skel | Bin .../example/assets/raptor-pma.atlas | 0 .../example/assets/raptor-pma.png | Bin .../example/assets/raptor-pro.json | 0 .../example/assets/sack-pro.json | 0 .../example/assets/sack-pro.skel | Bin .../example/assets/sack.atlas | 0 .../example/assets/sack.png | Bin .../example/assets/snowglobe-pma.atlas | 0 .../example/assets/snowglobe-pma.png | Bin .../example/assets/snowglobe-pma_2.png | Bin .../example/assets/snowglobe-pma_3.png | Bin .../example/assets/snowglobe-pma_4.png | Bin .../example/assets/snowglobe-pma_5.png | Bin .../example/assets/snowglobe-pro.json | 0 .../example/assets/snowglobe-pro.skel | Bin .../example/assets/snowglobe.atlas | 0 .../example/assets/snowglobe.png | Bin .../example/assets/snowglobe_2.png | Bin .../example/assets/snowglobe_3.png | Bin .../example/assets/snowglobe_4.png | Bin .../example/assets/snowglobe_5.png | Bin .../example/assets/spineboy-pma.atlas | 0 .../example/assets/spineboy-pma.png | Bin .../example/assets/spineboy-pro.skel | Bin .../example/assets/stretchyman-pma.atlas | 0 .../example/assets/stretchyman-pma.png | Bin .../example/assets/stretchyman-pro.skel | Bin .../example/basic-example.html | 2 +- .../example/basic-vanilla-js-example.html | 0 .../example/batching-test.html | 2 +- .../example/blend-test.html | 2 +- .../example/bounds-test.html | 2 +- .../example/camera-pipeline-test.html | 2 +- .../example/canvas-test.html | 2 +- .../example/control-bones-example.html | 2 +- .../example/custom-spine-object-type.html | 2 +- .../example/depth-test.html | 2 +- .../example/events-example.html | 2 +- .../example/extended-class-test.html | 2 +- .../example/inline-loading.html | 2 +- .../example/mix-and-match-example.html | 2 +- .../example/multi-scene-test.html | 2 +- .../example/phaser.png | Bin .../example/physics.html | 2 +- .../example/physics2.html | 2 +- .../example/physics3.html | 2 +- .../example/physics4.html | 2 +- .../example/render-to-texture-test.html | 3 +- .../example/typescript/README.md | 0 .../typescript/assets/spineboy-pma.atlas | 0 .../typescript/assets/spineboy-pma.png | Bin .../typescript/assets/spineboy-pro.skel | Bin .../example/typescript/index.html | 0 .../example/typescript/index.ts | 0 .../example/typescript/package-lock.json | 0 .../example/typescript/package.json | 0 .../example/visibility-test-container.html | 4 +- .../example/visibility-test.html | 4 +- .../package.json | 13 +- .../src/SpineGameObject.ts | 0 .../src/SpinePlugin.ts | 0 .../src/index.ts | 0 .../src/keys.ts | 0 .../src/mixins.ts | 0 .../src/require-shim.ts | 0 .../tsconfig.json | 0 spine-ts/spine-phaser-v4/LICENSE | 26 + spine-ts/spine-phaser-v4/README.md | 3 + .../spine-phaser-v4/example/add-existing.html | 60 + .../example/arcade-physics-example.html | 64 + .../example/assets/celestial-circus-pma.atlas | 174 + .../example/assets/celestial-circus-pma.png | Bin 0 -> 818183 bytes .../example/assets/celestial-circus-pro.json | 3758 + .../example/assets/celestial-circus-pro.skel | Bin 0 -> 52572 bytes .../example/assets/celestial-circus.atlas | 173 + .../example/assets/celestial-circus.png | Bin 0 -> 808981 bytes .../example/assets/cloud-pot.atlas | 85 + .../example/assets/cloud-pot.json | 842 + .../example/assets/cloud-pot.png | Bin 0 -> 336346 bytes .../example/assets/cloud-pot.skel | Bin 0 -> 8397 bytes .../example/assets/coin-pma.atlas | 19 + .../example/assets/coin-pma.png | Bin 0 -> 312321 bytes .../example/assets/coin-pro.skel | Bin 0 -> 2790 bytes .../example/assets/mix-and-match-pma.atlas | 359 + .../example/assets/mix-and-match-pma.png | Bin 0 -> 377480 bytes .../example/assets/mix-and-match-pro.skel | Bin 0 -> 259912 bytes .../spine-phaser-v4/example/assets/phaser.js | 246192 +++++++++++++++ .../example/assets/raptor-pma.atlas | 94 + .../example/assets/raptor-pma.png | Bin 0 -> 418814 bytes .../example/assets/raptor-pro.json | 9185 + .../example/assets/sack-pro.json | 4940 + .../example/assets/sack-pro.skel | Bin 0 -> 42777 bytes .../spine-phaser-v4/example/assets/sack.atlas | 10 + .../spine-phaser-v4/example/assets/sack.png | Bin 0 -> 164738 bytes .../example/assets/snowglobe-pma.atlas | 210 + .../example/assets/snowglobe-pma.png | Bin 0 -> 688917 bytes .../example/assets/snowglobe-pma_2.png | Bin 0 -> 803281 bytes .../example/assets/snowglobe-pma_3.png | Bin 0 -> 409360 bytes .../example/assets/snowglobe-pma_4.png | Bin 0 -> 245339 bytes .../example/assets/snowglobe-pma_5.png | Bin 0 -> 401332 bytes .../example/assets/snowglobe-pro.json | 2911 + .../example/assets/snowglobe-pro.skel | Bin 0 -> 43213 bytes .../example/assets/snowglobe.atlas | 205 + .../example/assets/snowglobe.png | Bin 0 -> 1062423 bytes .../example/assets/snowglobe_2.png | Bin 0 -> 1032885 bytes .../example/assets/snowglobe_3.png | Bin 0 -> 550305 bytes .../example/assets/snowglobe_4.png | Bin 0 -> 529645 bytes .../example/assets/snowglobe_5.png | Bin 0 -> 412517 bytes .../example/assets/spineboy-pma.atlas | 95 + .../example/assets/spineboy-pma.png | Bin 0 -> 244861 bytes .../example/assets/spineboy-pro.skel | Bin 0 -> 64463 bytes .../example/assets/stretchyman-pma.atlas | 19 + .../example/assets/stretchyman-pma.png | Bin 0 -> 91986 bytes .../example/assets/stretchyman-pro.skel | Bin 0 -> 24905 bytes .../example/basic-example.html | 55 + .../example/basic-vanilla-js-example.html | 54 + .../example/batching-test.html | 80 + .../spine-phaser-v4/example/blend-test.html | 78 + .../spine-phaser-v4/example/bounds-test.html | 70 + .../example/camera-pipeline-test.html | 126 + .../spine-phaser-v4/example/canvas-test.html | 55 + .../example/control-bones-example.html | 97 + .../example/custom-spine-object-type.html | 57 + .../spine-phaser-v4/example/depth-test.html | 65 + .../example/events-example.html | 86 + .../example/extended-class-test.html | 132 + .../example/inline-loading.html | 173 + .../example/mix-and-match-example.html | 76 + .../example/multi-scene-test.html | 76 + spine-ts/spine-phaser-v4/example/phaser.png | Bin 0 -> 5507 bytes spine-ts/spine-phaser-v4/example/physics.html | 53 + .../spine-phaser-v4/example/physics2.html | 79 + .../spine-phaser-v4/example/physics3.html | 53 + .../spine-phaser-v4/example/physics4.html | 53 + .../example/render-to-texture-test.html | 75 + .../example/typescript/README.md | 6 + .../typescript/assets/spineboy-pma.atlas | 95 + .../typescript/assets/spineboy-pma.png | Bin 0 -> 244861 bytes .../typescript/assets/spineboy-pro.skel | Bin 0 -> 64463 bytes .../example/typescript/index.html | 13 + .../example/typescript/index.ts | 29 + .../example/typescript/package-lock.json | 3091 + .../example/typescript/package.json | 19 + .../example/visibility-test-container.html | 99 + .../example/visibility-test.html | 70 + spine-ts/spine-phaser-v4/package.json | 44 + .../spine-phaser-v4/src/SpineGameObject.ts | 433 + spine-ts/spine-phaser-v4/src/SpinePlugin.ts | 399 + spine-ts/spine-phaser-v4/src/index.ts | 66 + spine-ts/spine-phaser-v4/src/keys.ts | 35 + spine-ts/spine-phaser-v4/src/mixins.ts | 84 + spine-ts/spine-phaser-v4/src/require-shim.ts | 40 + spine-ts/spine-phaser-v4/tsconfig.json | 37 + spine-ts/spine-pixi-v8/src/Spine.ts | 2 +- spine-ts/tsconfig.json | 5 +- 197 files changed, 309104 insertions(+), 320 deletions(-) rename spine-ts/{spine-phaser => spine-phaser-v3}/LICENSE (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/README.md (77%) create mode 100644 spine-ts/spine-phaser-v3/dist/SpineGameObject.d.ts create mode 100644 spine-ts/spine-phaser-v3/dist/SpineGameObject.js create mode 100644 spine-ts/spine-phaser-v3/dist/SpinePlugin.d.ts create mode 100644 spine-ts/spine-phaser-v3/dist/SpinePlugin.js create mode 100644 spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs create mode 100644 spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs.map create mode 100644 spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js create mode 100644 spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js.map create mode 100644 spine-ts/spine-phaser-v3/dist/index.d.ts create mode 100644 spine-ts/spine-phaser-v3/dist/index.js create mode 100644 spine-ts/spine-phaser-v3/dist/keys.d.ts create mode 100644 spine-ts/spine-phaser-v3/dist/keys.js create mode 100644 spine-ts/spine-phaser-v3/dist/mixins.d.ts create mode 100644 spine-ts/spine-phaser-v3/dist/mixins.js create mode 100644 spine-ts/spine-phaser-v3/dist/require-shim.d.ts create mode 100644 spine-ts/spine-phaser-v3/dist/require-shim.js rename spine-ts/{spine-phaser => spine-phaser-v3}/example/add-existing.html (96%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/arcade-physics-example.html (96%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/celestial-circus-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/celestial-circus-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/celestial-circus-pro.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/celestial-circus-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/celestial-circus.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/celestial-circus.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/cloud-pot.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/cloud-pot.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/cloud-pot.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/cloud-pot.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/coin-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/coin-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/coin-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/mix-and-match-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/mix-and-match-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/mix-and-match-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/raptor-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/raptor-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/raptor-pro.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/sack-pro.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/sack-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/sack.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/sack.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pma_2.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pma_3.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pma_4.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pma_5.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pro.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe_2.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe_3.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe_4.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/snowglobe_5.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/spineboy-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/spineboy-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/spineboy-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/stretchyman-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/stretchyman-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/assets/stretchyman-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/basic-example.html (96%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/basic-vanilla-js-example.html (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/batching-test.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/blend-test.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/bounds-test.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/camera-pipeline-test.html (98%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/canvas-test.html (96%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/control-bones-example.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/custom-spine-object-type.html (96%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/depth-test.html (96%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/events-example.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/extended-class-test.html (98%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/inline-loading.html (98%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/mix-and-match-example.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/multi-scene-test.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/phaser.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/physics.html (95%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/physics2.html (97%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/physics3.html (95%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/physics4.html (95%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/render-to-texture-test.html (94%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/README.md (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/assets/spineboy-pma.atlas (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/assets/spineboy-pma.png (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/assets/spineboy-pro.skel (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/index.html (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/index.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/package-lock.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/typescript/package.json (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/visibility-test-container.html (95%) rename spine-ts/{spine-phaser => spine-phaser-v3}/example/visibility-test.html (93%) rename spine-ts/{spine-phaser => spine-phaser-v3}/package.json (74%) rename spine-ts/{spine-phaser => spine-phaser-v3}/src/SpineGameObject.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/src/SpinePlugin.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/src/index.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/src/keys.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/src/mixins.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/src/require-shim.ts (100%) rename spine-ts/{spine-phaser => spine-phaser-v3}/tsconfig.json (100%) create mode 100644 spine-ts/spine-phaser-v4/LICENSE create mode 100644 spine-ts/spine-phaser-v4/README.md create mode 100644 spine-ts/spine-phaser-v4/example/add-existing.html create mode 100644 spine-ts/spine-phaser-v4/example/arcade-physics-example.html create mode 100644 spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.json create mode 100644 spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/celestial-circus.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/celestial-circus.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/cloud-pot.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/cloud-pot.json create mode 100644 spine-ts/spine-phaser-v4/example/assets/cloud-pot.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/cloud-pot.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/coin-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/coin-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/coin-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/mix-and-match-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/phaser.js create mode 100644 spine-ts/spine-phaser-v4/example/assets/raptor-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/raptor-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/raptor-pro.json create mode 100644 spine-ts/spine-phaser-v4/example/assets/sack-pro.json create mode 100644 spine-ts/spine-phaser-v4/example/assets/sack-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/sack.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/sack.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pma_2.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pma_3.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pma_4.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pma_5.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pro.json create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe_2.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe_3.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe_4.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/snowglobe_5.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/spineboy-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/spineboy-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/spineboy-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/assets/stretchyman-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/assets/stretchyman-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/assets/stretchyman-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/basic-example.html create mode 100644 spine-ts/spine-phaser-v4/example/basic-vanilla-js-example.html create mode 100644 spine-ts/spine-phaser-v4/example/batching-test.html create mode 100644 spine-ts/spine-phaser-v4/example/blend-test.html create mode 100644 spine-ts/spine-phaser-v4/example/bounds-test.html create mode 100644 spine-ts/spine-phaser-v4/example/camera-pipeline-test.html create mode 100644 spine-ts/spine-phaser-v4/example/canvas-test.html create mode 100644 spine-ts/spine-phaser-v4/example/control-bones-example.html create mode 100644 spine-ts/spine-phaser-v4/example/custom-spine-object-type.html create mode 100644 spine-ts/spine-phaser-v4/example/depth-test.html create mode 100644 spine-ts/spine-phaser-v4/example/events-example.html create mode 100644 spine-ts/spine-phaser-v4/example/extended-class-test.html create mode 100644 spine-ts/spine-phaser-v4/example/inline-loading.html create mode 100644 spine-ts/spine-phaser-v4/example/mix-and-match-example.html create mode 100644 spine-ts/spine-phaser-v4/example/multi-scene-test.html create mode 100644 spine-ts/spine-phaser-v4/example/phaser.png create mode 100644 spine-ts/spine-phaser-v4/example/physics.html create mode 100644 spine-ts/spine-phaser-v4/example/physics2.html create mode 100644 spine-ts/spine-phaser-v4/example/physics3.html create mode 100644 spine-ts/spine-phaser-v4/example/physics4.html create mode 100644 spine-ts/spine-phaser-v4/example/render-to-texture-test.html create mode 100644 spine-ts/spine-phaser-v4/example/typescript/README.md create mode 100644 spine-ts/spine-phaser-v4/example/typescript/assets/spineboy-pma.atlas create mode 100644 spine-ts/spine-phaser-v4/example/typescript/assets/spineboy-pma.png create mode 100644 spine-ts/spine-phaser-v4/example/typescript/assets/spineboy-pro.skel create mode 100644 spine-ts/spine-phaser-v4/example/typescript/index.html create mode 100644 spine-ts/spine-phaser-v4/example/typescript/index.ts create mode 100644 spine-ts/spine-phaser-v4/example/typescript/package-lock.json create mode 100644 spine-ts/spine-phaser-v4/example/typescript/package.json create mode 100644 spine-ts/spine-phaser-v4/example/visibility-test-container.html create mode 100644 spine-ts/spine-phaser-v4/example/visibility-test.html create mode 100644 spine-ts/spine-phaser-v4/package.json create mode 100644 spine-ts/spine-phaser-v4/src/SpineGameObject.ts create mode 100644 spine-ts/spine-phaser-v4/src/SpinePlugin.ts create mode 100644 spine-ts/spine-phaser-v4/src/index.ts create mode 100644 spine-ts/spine-phaser-v4/src/keys.ts create mode 100644 spine-ts/spine-phaser-v4/src/mixins.ts create mode 100644 spine-ts/spine-phaser-v4/src/require-shim.ts create mode 100644 spine-ts/spine-phaser-v4/tsconfig.json diff --git a/.gitignore b/.gitignore index e31bd8d52..222b356fe 100644 --- a/.gitignore +++ b/.gitignore @@ -145,6 +145,8 @@ spine-ts/spine-canvas/dist spine-ts/spine-webgl/dist spine-ts/spine-player/dist spine-ts/spine-threejs/dist +spine-ts/spine-phaser-v3/dist +spine-ts/spine-phaser-v4/dist spine-ts/spine-pixi-v7/dist spine-ts/spine-pixi-v8/dist spine-libgdx/gradle @@ -189,7 +191,6 @@ spine-flutter/src/spine-cpp spine-godot/.clang-format -spine-ts/spine-phaser/dist spine-godot/.cache spine-godot/build/compile_commands.json diff --git a/examples/export/runtimes.sh b/examples/export/runtimes.sh index d468b684d..b27360b02 100755 --- a/examples/export/runtimes.sh +++ b/examples/export/runtimes.sh @@ -518,46 +518,87 @@ cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-player/example/a cp -f ../celestial-circus/export/* "$ROOT/spine-ts/spine-player/example/assets/" -rm "$ROOT/spine-ts/spine-phaser/example/assets/"* -cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../raptor/export/raptor-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../raptor/export/raptor-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/" +rm "$ROOT/spine-ts/spine-phaser-v3/example/assets/"* +cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../raptor/export/raptor-pma.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../raptor/export/raptor-pma.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser/example/typescript/assets/" -cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser/example/typescript/assets/" -cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser/example/typescript/assets/" +cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/typescript/assets/" +cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser-v3/example/typescript/assets/" +cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser-v3/example/typescript/assets/" -cp -f ../coin/export/coin-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../coin/export/coin-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../coin/export/coin-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../coin/export/coin-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../coin/export/coin-pma.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../coin/export/coin-pma.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../stretchyman/export/stretchyman-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../stretchyman/export/stretchyman-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../stretchyman/export/stretchyman-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../stretchyman/export/stretchyman-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../stretchyman/export/stretchyman-pma.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../stretchyman/export/stretchyman-pma.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../mix-and-match/export/mix-and-match-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../mix-and-match/export/mix-and-match-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../mix-and-match/export/mix-and-match-pma.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../mix-and-match/export/mix-and-match-pma.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../celestial-circus/export/* "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../celestial-circus/export/* "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../cloud-pot/export/cloud-pot.json "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../cloud-pot/export/cloud-pot.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../cloud-pot/export/cloud-pot.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../cloud-pot/export/cloud-pot.png "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.json "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../sack/export/sack-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../sack/export/sack-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../sack/export/sack.atlas "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../sack/export/sack.png "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../sack/export/sack-pro.json "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../sack/export/sack-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../sack/export/sack.atlas "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../sack/export/sack.png "$ROOT/spine-ts/spine-phaser-v3/example/assets/" -cp -f ../snowglobe/export/snowglobe-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../snowglobe/export/snowglobe-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/" -cp -f ../snowglobe/export/snowglobe* "$ROOT/spine-ts/spine-phaser/example/assets/" +cp -f ../snowglobe/export/snowglobe-pro.json "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../snowglobe/export/snowglobe-pro.skel "$ROOT/spine-ts/spine-phaser-v3/example/assets/" +cp -f ../snowglobe/export/snowglobe* "$ROOT/spine-ts/spine-phaser-v3/example/assets/" + +rm "$ROOT/spine-ts/spine-phaser-v4/example/assets/"* +cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../raptor/export/raptor-pma.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../raptor/export/raptor-pma.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../spineboy/export/spineboy-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/typescript/assets/" +cp -f ../spineboy/export/spineboy-pma.atlas "$ROOT/spine-ts/spine-phaser-v4/example/typescript/assets/" +cp -f ../spineboy/export/spineboy-pma.png "$ROOT/spine-ts/spine-phaser-v4/example/typescript/assets/" + +cp -f ../coin/export/coin-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../coin/export/coin-pma.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../coin/export/coin-pma.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../stretchyman/export/stretchyman-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../stretchyman/export/stretchyman-pma.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../stretchyman/export/stretchyman-pma.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../mix-and-match/export/mix-and-match-pma.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../mix-and-match/export/mix-and-match-pma.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../celestial-circus/export/* "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../cloud-pot/export/cloud-pot.json "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../cloud-pot/export/cloud-pot.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../sack/export/sack-pro.json "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../sack/export/sack-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../sack/export/sack.atlas "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../sack/export/sack.png "$ROOT/spine-ts/spine-phaser-v4/example/assets/" + +cp -f ../snowglobe/export/snowglobe-pro.json "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../snowglobe/export/snowglobe-pro.skel "$ROOT/spine-ts/spine-phaser-v4/example/assets/" +cp -f ../snowglobe/export/snowglobe* "$ROOT/spine-ts/spine-phaser-v4/example/assets/" rm "$ROOT/spine-ts/spine-pixi-v7/example/assets/"* cp -f ../raptor/export/raptor-pro.json "$ROOT/spine-ts/spine-pixi-v7/example/assets/" diff --git a/spine-ts/README.md b/spine-ts/README.md index 171b5336b..3d82879db 100644 --- a/spine-ts/README.md +++ b/spine-ts/README.md @@ -17,7 +17,7 @@ In most cases, the `spine-player` module is best suited for your needs. Please r For documentation of the core API in `spine-core`, please refer to our [Spine Runtimes Guide](http://esotericsoftware.com/spine-runtimes-guide). -For documentation of `spine-phaser`, please refer to our [spine-phaser Guide](https://esotericsoftware.com/spine-phaser). +For documentation of `spine-phaser-v3` and `spine-phaser-v4`, please refer to our [spine-phaser Guide](https://esotericsoftware.com/spine-phaser). For documentation of `spine-pixi-v7` and `spine-pixi-v8`, please refer to our [spine-pixi Guide](https://esotericsoftware.com/spine-pixi). @@ -75,10 +75,13 @@ You can include a module in your project via a ` -// spine-phaser - +// spine-phaser-v3 + -// spine-pixi +// spine-phaser-v4 + + +// spine-pixi-v7 // spine-pixi-v8 diff --git a/spine-ts/index.html b/spine-ts/index.html index 735067c01..c07ff9677 100644 --- a/spine-ts/index.html +++ b/spine-ts/index.html @@ -29,130 +29,93 @@

  • Physics
  • Micro Benchmark
  • -
  • PixiJS v7
  • +
  • PixiJS
  • -
  • PixiJS v8
  • -
  • Phaser
  • Player
  • diff --git a/spine-ts/package-lock.json b/spine-ts/package-lock.json index 8c5586c0f..c1944a5a9 100644 --- a/spine-ts/package-lock.json +++ b/spine-ts/package-lock.json @@ -11,7 +11,8 @@ "workspaces": [ "spine-core", "spine-canvas", - "spine-phaser", + "spine-phaser-v3", + "spine-phaser-v4", "spine-player", "spine-threejs", "spine-pixi-v7", @@ -30,7 +31,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -40,8 +43,61 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", "cpu": [ "arm64" ], @@ -55,6 +111,312 @@ "node": ">=12" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esotericsoftware/spine-canvas": { "resolved": "spine-canvas", "link": true @@ -67,8 +429,12 @@ "resolved": "spine-core", "link": true }, - "node_modules/@esotericsoftware/spine-phaser": { - "resolved": "spine-phaser", + "node_modules/@esotericsoftware/spine-phaser-v3": { + "resolved": "spine-phaser-v3", + "link": true + }, + "node_modules/@esotericsoftware/spine-phaser-v4": { + "resolved": "spine-phaser-v4", "link": true }, "node_modules/@esotericsoftware/spine-pixi-v7": { @@ -93,6 +459,8 @@ }, "node_modules/@pdf-lib/upng": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -100,18 +468,22 @@ } }, "node_modules/@pixi/assets": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/assets/-/assets-7.4.3.tgz", + "integrity": "sha512-StvjiJBSp/j9hHkGu8AFHNvwYUazXq64WhyhytztyDMRkg/l/cL7EcttY5T0qZNWlIpccdr60LUKrWDOuMpkiw==", "license": "MIT", "peer": true, "dependencies": { "@types/css-font-loading-module": "^0.0.12" }, "peerDependencies": { - "@pixi/core": "7.4.2" + "@pixi/core": "7.4.3" } }, "node_modules/@pixi/color": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/color/-/color-7.4.3.tgz", + "integrity": "sha512-a6R+bXKeXMDcRmjYQoBIK+v2EYqxSX49wcjAY579EYM/WrFKS98nSees6lqVUcLKrcQh2DT9srJHX7XMny3voQ==", "license": "MIT", "peer": true, "dependencies": { @@ -120,27 +492,33 @@ }, "node_modules/@pixi/colord": { "version": "2.9.6", + "resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz", + "integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==", "license": "MIT", "peer": true }, "node_modules/@pixi/constants": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-7.4.3.tgz", + "integrity": "sha512-QGmwJUNQy/vVEHzL6VGQvnwawLZ1wceZMI8HwJAT4/I2uAzbBeFDdmCS8WsTpSWLZjF/DszDc1D8BFp4pVJ5UQ==", "license": "MIT", "peer": true }, "node_modules/@pixi/core": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/core/-/core-7.4.3.tgz", + "integrity": "sha512-5YDs11faWgVVTL8VZtLU05/Fl47vaP5Tnsbf+y/WRR0VSW3KhRRGTBU1J3Gdc2xEWbJhUK07KGP7eSZpvtPVgA==", "license": "MIT", "peer": true, "dependencies": { - "@pixi/color": "7.4.2", - "@pixi/constants": "7.4.2", - "@pixi/extensions": "7.4.2", - "@pixi/math": "7.4.2", - "@pixi/runner": "7.4.2", - "@pixi/settings": "7.4.2", - "@pixi/ticker": "7.4.2", - "@pixi/utils": "7.4.2" + "@pixi/color": "7.4.3", + "@pixi/constants": "7.4.3", + "@pixi/extensions": "7.4.3", + "@pixi/math": "7.4.3", + "@pixi/runner": "7.4.3", + "@pixi/settings": "7.4.3", + "@pixi/ticker": "7.4.3", + "@pixi/utils": "7.4.3" }, "funding": { "type": "opencollective", @@ -148,102 +526,126 @@ } }, "node_modules/@pixi/display": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/display/-/display-7.4.3.tgz", + "integrity": "sha512-b5m2dAaoNAVdxz1oDaxl3XZ059NEOcNtGkxTOZ4EYCw/jcp9sZXkgSROHRzsGn4k+NugH7+9MP4Id2Z0kkdUhw==", "license": "MIT", "peer": true, "peerDependencies": { - "@pixi/core": "7.4.2" + "@pixi/core": "7.4.3" } }, "node_modules/@pixi/events": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/events/-/events-7.4.3.tgz", + "integrity": "sha512-o3j/5Dxq6WDVS6eHfURB/cf/MP+NcsF/eC5PnbSHjXxJmDE7PoTVwLvxexm5uuvNRpFh/6/Fn0V8Vl4gV8sc8w==", "license": "MIT", "peer": true, "peerDependencies": { - "@pixi/core": "7.4.2", - "@pixi/display": "7.4.2" + "@pixi/core": "7.4.3", + "@pixi/display": "7.4.3" } }, "node_modules/@pixi/extensions": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-7.4.3.tgz", + "integrity": "sha512-FhoiYkHQEDYHUE7wXhqfsTRz6KxLXjuMbSiAwnLb9uG1vAgp6q6qd6HEsf4X30YaZbLFY8a4KY6hFZWjF+4Fdw==", "license": "MIT", "peer": true }, "node_modules/@pixi/graphics": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-7.4.3.tgz", + "integrity": "sha512-wWLivD8/URb8A7X4TqCZGG39C91IE+aOuWY/z9NCz5Z6WvA/VWnsc5fLTlO+ggjGHgKF0cSucCXZfUe1wm0AOQ==", "license": "MIT", "peer": true, "peerDependencies": { - "@pixi/core": "7.4.2", - "@pixi/display": "7.4.2", - "@pixi/sprite": "7.4.2" + "@pixi/core": "7.4.3", + "@pixi/display": "7.4.3", + "@pixi/sprite": "7.4.3" } }, "node_modules/@pixi/math": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.3.tgz", + "integrity": "sha512-/uJOVhR2DOZ+zgdI6Bs/CwcXT4bNRKsS+TqX3ekRIxPCwaLra+Qdm7aDxT5cTToDzdxbKL5+rwiLu3Y1egILDw==", "license": "MIT", "peer": true }, "node_modules/@pixi/mesh": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-7.4.3.tgz", + "integrity": "sha512-CikqFPtKvU3Zj986/MSoC8X39CWv5CEpiEW/tYp47p4tgQNDSkNWYnDiNYgb+4VX6pNsBrgX4DALLdTR17SlSA==", "license": "MIT", "peer": true, "peerDependencies": { - "@pixi/core": "7.4.2", - "@pixi/display": "7.4.2" + "@pixi/core": "7.4.3", + "@pixi/display": "7.4.3" } }, "node_modules/@pixi/runner": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-7.4.3.tgz", + "integrity": "sha512-TJyfp7y23u5vvRAyYhVSa7ytq0PdKSvPLXu4G3meoFh1oxTLHH6g/RIzLuxUAThPG2z7ftthuW3qWq6dRV+dhw==", "license": "MIT", "peer": true }, "node_modules/@pixi/settings": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-7.4.3.tgz", + "integrity": "sha512-SmGK8smc0PxRB9nr0UJioEtE9hl4gvj9OedCvZx3bxBwA3omA5BmP3CyhQfN8XJ29+o2OUL01r3zAPVol4l4lA==", "license": "MIT", "peer": true, "dependencies": { - "@pixi/constants": "7.4.2", + "@pixi/constants": "7.4.3", "@types/css-font-loading-module": "^0.0.12", "ismobilejs": "^1.1.0" } }, "node_modules/@pixi/sprite": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-7.4.3.tgz", + "integrity": "sha512-iNBrpOFF9nXDT6m2jcyYy6l/sRzklLDDck1eFHprHZwvNquY2nzRfh+RGBCecxhBcijiLJ3fsZN33fP0LDXkvw==", "license": "MIT", "peer": true, "peerDependencies": { - "@pixi/core": "7.4.2", - "@pixi/display": "7.4.2" + "@pixi/core": "7.4.3", + "@pixi/display": "7.4.3" } }, "node_modules/@pixi/text": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/text/-/text-7.4.3.tgz", + "integrity": "sha512-IAF0iu04rPg3oiL0HZsEZI44fpJxq3UZ4xTmx8l1RyhhSXiElLvvSlSH57vt/BKMQZtCs+AqEit7yn8heK2+nQ==", "license": "MIT", "peer": true, "peerDependencies": { - "@pixi/core": "7.4.2", - "@pixi/sprite": "7.4.2" + "@pixi/core": "7.4.3", + "@pixi/sprite": "7.4.3" } }, "node_modules/@pixi/ticker": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-7.4.3.tgz", + "integrity": "sha512-tHsAD0iOUb6QSGGw+c8cyRBvxsq/NlfzIFBZLEHhWZ+Bx4a0MmXup6I/yJDGmyPCYE+ctCcAfY13wKAzdiVFgQ==", "license": "MIT", "peer": true, "dependencies": { - "@pixi/extensions": "7.4.2", - "@pixi/settings": "7.4.2", - "@pixi/utils": "7.4.2" + "@pixi/extensions": "7.4.3", + "@pixi/settings": "7.4.3", + "@pixi/utils": "7.4.3" } }, "node_modules/@pixi/utils": { - "version": "7.4.2", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-7.4.3.tgz", + "integrity": "sha512-NO3Y9HAn2UKS1YdxffqsPp+kDpVm8XWvkZcS/E+rBzY9VTLnNOI7cawSRm+dacdET3a8Jad3aDKEDZ0HmAqAFA==", "license": "MIT", "peer": true, "dependencies": { - "@pixi/color": "7.4.2", - "@pixi/constants": "7.4.2", - "@pixi/settings": "7.4.2", + "@pixi/color": "7.4.3", + "@pixi/constants": "7.4.3", + "@pixi/settings": "7.4.3", "@types/earcut": "^2.1.0", "earcut": "^2.2.4", "eventemitter3": "^4.0.0", @@ -252,21 +654,29 @@ }, "node_modules/@tweenjs/tween.js": { "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", "dev": true, "license": "MIT" }, "node_modules/@types/css-font-loading-module": { "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.12.tgz", + "integrity": "sha512-x2tZZYkSxXqWvTDgveSynfjq/T2HyiZHXb00j/+gy19yp70PHCizM48XFdjBCWH7eHBD0R5i/pw9yMBP/BH5uA==", "license": "MIT", "peer": true }, "node_modules/@types/earcut": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.4.tgz", + "integrity": "sha512-qp3m9PPz4gULB9MhjGID7wpo3gJ4bTGXm7ltNDsmOvsPduTeHp8wSW9YckBj3mljeOh4F0m2z/0JKAALRKbmLQ==", "license": "MIT", "peer": true }, "node_modules/@types/node": { "version": "20.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", + "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", "dev": true, "license": "MIT", "dependencies": { @@ -275,16 +685,22 @@ }, "node_modules/@types/offscreencanvas": { "version": "2019.7.3", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", + "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", "dev": true, "license": "MIT" }, "node_modules/@types/stats.js": { "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", + "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==", "dev": true, "license": "MIT" }, "node_modules/@types/three": { "version": "0.162.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.162.0.tgz", + "integrity": "sha512-0j5yZcVukVIhrhSIC7+LmBPkkMoMuEJ1AfYBZfgNytdYqYREMuiyXWhYOMeZLBElTEAlJIZn7r2W3vqTIgjWlg==", "dev": true, "license": "MIT", "dependencies": { @@ -296,16 +712,22 @@ } }, "node_modules/@types/webxr": { - "version": "0.5.20", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.21.tgz", + "integrity": "sha512-geZIAtLzjGmgY2JUi6VxXdCrTb99A7yP49lxLr2Nm/uIK0PkkxcEi4OGhoGDO4pxCf3JwGz2GiJL2Ej4K2bKaA==", "dev": true, "license": "MIT" }, "node_modules/@webgpu/types": { "version": "0.1.21", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.21.tgz", + "integrity": "sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow==", "license": "BSD-3-Clause" }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", "license": "MIT", "peer": true, "engines": { @@ -314,6 +736,8 @@ }, "node_modules/accepts": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", "dependencies": { @@ -324,8 +748,33 @@ "node": ">= 0.6" } }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { @@ -334,6 +783,8 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -348,6 +799,8 @@ }, "node_modules/anymatch": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "license": "ISC", "dependencies": { @@ -357,6 +810,8 @@ }, "node_modules/anymatch/node_modules/normalize-path": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "dev": true, "license": "MIT", "dependencies": { @@ -368,6 +823,8 @@ }, "node_modules/apache-crypt": { "version": "1.2.6", + "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.6.tgz", + "integrity": "sha512-072WetlM4blL8PREJVeY+WHiUh1R5VNt2HfceGS8aKqttPHcmqE5pkKuXPz/ULmJOFkc8Hw3kfKl6vy7Qka6DA==", "dev": true, "license": "MIT", "dependencies": { @@ -379,6 +836,8 @@ }, "node_modules/apache-md5": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.8.tgz", + "integrity": "sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA==", "dev": true, "license": "MIT", "engines": { @@ -387,6 +846,8 @@ }, "node_modules/arr-diff": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", "dev": true, "license": "MIT", "engines": { @@ -395,6 +856,8 @@ }, "node_modules/arr-flatten": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true, "license": "MIT", "engines": { @@ -403,6 +866,8 @@ }, "node_modules/arr-union": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", "dev": true, "license": "MIT", "engines": { @@ -411,6 +876,8 @@ }, "node_modules/array-unique": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", "dev": true, "license": "MIT", "engines": { @@ -419,6 +886,8 @@ }, "node_modules/assign-symbols": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", "dev": true, "license": "MIT", "engines": { @@ -427,6 +896,8 @@ }, "node_modules/async-each": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", "dev": true, "funding": [ { @@ -438,6 +909,8 @@ }, "node_modules/atob": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true, "license": "(MIT OR Apache-2.0)", "bin": { @@ -449,11 +922,15 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/base": { "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "license": "MIT", "dependencies": { @@ -471,6 +948,8 @@ }, "node_modules/base/node_modules/define-property": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "dev": true, "license": "MIT", "dependencies": { @@ -482,6 +961,8 @@ }, "node_modules/basic-auth": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "dev": true, "license": "MIT", "dependencies": { @@ -493,16 +974,22 @@ }, "node_modules/batch": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true, "license": "MIT" }, "node_modules/bcryptjs": { "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", "dev": true, "license": "MIT" }, "node_modules/binary-extensions": { "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true, "license": "MIT", "engines": { @@ -511,6 +998,8 @@ }, "node_modules/bindings": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "license": "MIT", "optional": true, @@ -520,6 +1009,8 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { @@ -529,6 +1020,8 @@ }, "node_modules/braces": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "license": "MIT", "dependencies": { @@ -549,6 +1042,8 @@ }, "node_modules/cache-base": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "license": "MIT", "dependencies": { @@ -566,16 +1061,29 @@ "node": ">=0.10.0" } }, - "node_modules/call-bind": { - "version": "1.0.7", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "peer": true, "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -586,6 +1094,8 @@ }, "node_modules/canvaskit-wasm": { "version": "0.39.1", + "resolved": "https://registry.npmjs.org/canvaskit-wasm/-/canvaskit-wasm-0.39.1.tgz", + "integrity": "sha512-Gy3lCmhUdKq+8bvDrs9t8+qf7RvcjuQn+we7vTVVyqgOVO1UVfHpsnBxkTZw+R4ApEJ3D5fKySl9TU11hmjl/A==", "license": "BSD-3-Clause", "dependencies": { "@webgpu/types": "0.1.21" @@ -593,6 +1103,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -608,6 +1120,8 @@ }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -619,6 +1133,8 @@ }, "node_modules/chokidar": { "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, "license": "MIT", "dependencies": { @@ -640,6 +1156,8 @@ }, "node_modules/class-utils": { "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "license": "MIT", "dependencies": { @@ -654,6 +1172,8 @@ }, "node_modules/class-utils/node_modules/define-property": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "license": "MIT", "dependencies": { @@ -665,6 +1185,8 @@ }, "node_modules/class-utils/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -677,6 +1199,8 @@ }, "node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "license": "ISC", "dependencies": { @@ -690,6 +1214,8 @@ }, "node_modules/collection-visit": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", "dev": true, "license": "MIT", "dependencies": { @@ -702,6 +1228,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -713,11 +1241,15 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/colors": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, "license": "MIT", "engines": { @@ -726,6 +1258,8 @@ }, "node_modules/component-emitter": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", "dev": true, "license": "MIT", "funding": { @@ -734,11 +1268,15 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/concurrently": { "version": "7.6.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", + "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", "dev": true, "license": "MIT", "dependencies": { @@ -765,6 +1303,8 @@ }, "node_modules/connect": { "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "license": "MIT", "dependencies": { @@ -779,6 +1319,8 @@ }, "node_modules/copy-descriptor": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", "dev": true, "license": "MIT", "engines": { @@ -787,6 +1329,8 @@ }, "node_modules/copyfiles": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", "dev": true, "license": "MIT", "dependencies": { @@ -805,6 +1349,8 @@ }, "node_modules/copyfiles/node_modules/cliui": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "license": "ISC", "dependencies": { @@ -815,6 +1361,8 @@ }, "node_modules/copyfiles/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", "dependencies": { @@ -832,6 +1380,8 @@ }, "node_modules/copyfiles/node_modules/yargs-parser": { "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "license": "ISC", "engines": { @@ -840,6 +1390,8 @@ }, "node_modules/core-util-is": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, "license": "MIT" }, @@ -859,6 +1411,8 @@ }, "node_modules/date-fns": { "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dev": true, "license": "MIT", "dependencies": { @@ -874,6 +1428,8 @@ }, "node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -882,30 +1438,18 @@ }, "node_modules/decode-uri-component": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "license": "MIT", - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-property": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -918,43 +1462,61 @@ }, "node_modules/depd": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/destroy": { - "version": "1.2.0", - "dev": true, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">= 0.4" } }, "node_modules/duplexer": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true, "license": "MIT" }, "node_modules/earcut": { "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", "license": "ISC", "peer": true }, "node_modules/ee-first": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, "license": "MIT" }, "node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", "engines": { @@ -962,26 +1524,42 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "peer": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } }, "node_modules/es-errors": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "peer": true, "engines": { "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1018,6 +1596,8 @@ }, "node_modules/escalade": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -1026,11 +1606,15 @@ }, "node_modules/escape-html": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { @@ -1039,6 +1623,8 @@ }, "node_modules/event-stream": { "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", "dev": true, "license": "MIT", "dependencies": { @@ -1053,11 +1639,15 @@ }, "node_modules/eventemitter3": { "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT", "peer": true }, "node_modules/expand-brackets": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", "dev": true, "license": "MIT", "dependencies": { @@ -1075,6 +1665,8 @@ }, "node_modules/expand-brackets/node_modules/define-property": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "license": "MIT", "dependencies": { @@ -1086,6 +1678,8 @@ }, "node_modules/expand-brackets/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -1098,6 +1692,8 @@ }, "node_modules/extend-shallow": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, "license": "MIT", "dependencies": { @@ -1109,6 +1705,8 @@ }, "node_modules/extglob": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "license": "MIT", "dependencies": { @@ -1127,6 +1725,8 @@ }, "node_modules/extglob/node_modules/define-property": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "dev": true, "license": "MIT", "dependencies": { @@ -1138,6 +1738,8 @@ }, "node_modules/faye-websocket": { "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1149,17 +1751,23 @@ }, "node_modules/fflate": { "version": "0.6.10", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", + "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==", "dev": true, "license": "MIT" }, "node_modules/file-uri-to-path": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true, "license": "MIT", "optional": true }, "node_modules/fill-range": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1174,6 +1782,8 @@ }, "node_modules/finalhandler": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "license": "MIT", "dependencies": { @@ -1191,6 +1801,8 @@ }, "node_modules/for-in": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", "dev": true, "license": "MIT", "engines": { @@ -1199,6 +1811,8 @@ }, "node_modules/fragment-cache": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", "dev": true, "license": "MIT", "dependencies": { @@ -1209,25 +1823,34 @@ } }, "node_modules/fresh": { - "version": "0.5.2", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/from": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", "dev": true, "license": "MIT" }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, "license": "ISC" }, "node_modules/fsevents": { "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1245,6 +1868,8 @@ }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1252,6 +1877,8 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", "engines": { @@ -1259,15 +1886,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "peer": true, "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1276,16 +1910,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "peer": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-value": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/gifuct-js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gifuct-js/-/gifuct-js-2.1.2.tgz", + "integrity": "sha512-rI2asw77u0mGgwhV3qA+OEgYqaDn5UNqgs+Bx0FGwSpuqfYn+Ir6RQY5ENNQ8SbIiG/m5gVa7CD5RriO4f4Lsg==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-binary-schema-parser": "^2.0.3" + } + }, "node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -1305,6 +1968,8 @@ }, "node_modules/glob-parent": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dev": true, "license": "ISC", "dependencies": { @@ -1314,6 +1979,8 @@ }, "node_modules/glob-parent/node_modules/is-glob": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "dev": true, "license": "MIT", "dependencies": { @@ -1324,42 +1991,9 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "license": "MIT", - "peer": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "license": "MIT", - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "peer": true, "engines": { @@ -1369,8 +2003,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-symbols": { - "version": "1.0.3", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "peer": true, "engines": { @@ -1382,6 +2035,8 @@ }, "node_modules/has-value": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", "dev": true, "license": "MIT", "dependencies": { @@ -1395,6 +2050,8 @@ }, "node_modules/has-values": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1407,6 +2064,8 @@ }, "node_modules/has-values/node_modules/kind-of": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", "dev": true, "license": "MIT", "dependencies": { @@ -1418,6 +2077,8 @@ }, "node_modules/hasown": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -1428,6 +2089,8 @@ }, "node_modules/http-auth": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", + "integrity": "sha512-Jbx0+ejo2IOx+cRUYAGS1z6RGc6JfYUNkysZM4u4Sfk1uLlGv814F7/PIjQQAuThLdAWxb74JMGd5J8zex1VQg==", "dev": true, "license": "MIT", "dependencies": { @@ -1442,6 +2105,8 @@ }, "node_modules/http-errors": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1457,6 +2122,8 @@ }, "node_modules/http-errors/node_modules/statuses": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", "engines": { @@ -1464,12 +2131,17 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", "dev": true, "license": "MIT" }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", "dependencies": { @@ -1479,11 +2151,15 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC" }, "node_modules/is-accessor-descriptor": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", "dev": true, "license": "MIT", "dependencies": { @@ -1495,6 +2171,8 @@ }, "node_modules/is-binary-path": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1506,11 +2184,15 @@ }, "node_modules/is-buffer": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true, "license": "MIT" }, "node_modules/is-data-descriptor": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", "dev": true, "license": "MIT", "dependencies": { @@ -1522,6 +2204,8 @@ }, "node_modules/is-descriptor": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1534,6 +2218,8 @@ }, "node_modules/is-extendable": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, "license": "MIT", "engines": { @@ -1542,6 +2228,8 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { @@ -1550,6 +2238,8 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { @@ -1558,6 +2248,8 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { @@ -1569,6 +2261,8 @@ }, "node_modules/is-number": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "dev": true, "license": "MIT", "dependencies": { @@ -1580,6 +2274,8 @@ }, "node_modules/is-plain-object": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", "dependencies": { @@ -1591,6 +2287,8 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "license": "MIT", "engines": { @@ -1599,6 +2297,8 @@ }, "node_modules/is-wsl": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", "dev": true, "license": "MIT", "engines": { @@ -1607,24 +2307,39 @@ }, "node_modules/isarray": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true, "license": "MIT" }, "node_modules/ismobilejs": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", + "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", "license": "MIT", "peer": true }, "node_modules/isobject": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/js-binary-schema-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz", + "integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==", + "license": "MIT", + "peer": true + }, "node_modules/kind-of": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1636,6 +2351,8 @@ }, "node_modules/live-server": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/live-server/-/live-server-1.2.2.tgz", + "integrity": "sha512-t28HXLjITRGoMSrCOv4eZ88viHaBVIjKjdI5PO92Vxlu+twbk6aE0t7dVIaz6ZWkjPilYFV6OSdMYl9ybN2B4w==", "dev": true, "license": "MIT", "dependencies": { @@ -1662,11 +2379,15 @@ }, "node_modules/lodash": { "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "license": "MIT" }, "node_modules/map-cache": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", "dev": true, "license": "MIT", "engines": { @@ -1675,10 +2396,14 @@ }, "node_modules/map-stream": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", "dev": true }, "node_modules/map-visit": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", "dev": true, "license": "MIT", "dependencies": { @@ -1688,13 +2413,27 @@ "node": ">=0.10.0" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/meshoptimizer": { "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", "dev": true, "license": "MIT" }, "node_modules/micromatch": { "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "license": "MIT", "dependencies": { @@ -1718,6 +2457,8 @@ }, "node_modules/micromatch/node_modules/extend-shallow": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1730,6 +2471,8 @@ }, "node_modules/micromatch/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "license": "MIT", "dependencies": { @@ -1741,6 +2484,8 @@ }, "node_modules/micromatch/node_modules/kind-of": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", "engines": { @@ -1748,7 +2493,9 @@ } }, "node_modules/mime-db": { - "version": "1.52.0", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { @@ -1756,11 +2503,13 @@ } }, "node_modules/mime-types": { - "version": "2.1.35", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { "node": ">= 0.6" @@ -1768,6 +2517,8 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -1779,6 +2530,8 @@ }, "node_modules/mixin-deep": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "license": "MIT", "dependencies": { @@ -1791,6 +2544,8 @@ }, "node_modules/mixin-deep/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "license": "MIT", "dependencies": { @@ -1802,6 +2557,8 @@ }, "node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", "bin": { @@ -1813,6 +2570,8 @@ }, "node_modules/morgan": { "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1828,17 +2587,23 @@ }, "node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/nan": { - "version": "2.22.0", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", "dev": true, "license": "MIT", "optional": true }, "node_modules/nanomatch": { "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "license": "MIT", "dependencies": { @@ -1860,6 +2625,8 @@ }, "node_modules/nanomatch/node_modules/extend-shallow": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1872,6 +2639,8 @@ }, "node_modules/nanomatch/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "license": "MIT", "dependencies": { @@ -1883,6 +2652,8 @@ }, "node_modules/nanomatch/node_modules/kind-of": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", "engines": { @@ -1891,6 +2662,8 @@ }, "node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", "engines": { @@ -1899,6 +2672,8 @@ }, "node_modules/noms": { "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", "dev": true, "license": "ISC", "dependencies": { @@ -1908,6 +2683,8 @@ }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", "engines": { @@ -1926,6 +2703,8 @@ }, "node_modules/object-copy": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1939,6 +2718,8 @@ }, "node_modules/object-copy/node_modules/define-property": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "license": "MIT", "dependencies": { @@ -1950,6 +2731,8 @@ }, "node_modules/object-copy/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -1961,7 +2744,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "peer": true, "engines": { @@ -1973,6 +2758,8 @@ }, "node_modules/object-visit": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", "dev": true, "license": "MIT", "dependencies": { @@ -1984,6 +2771,8 @@ }, "node_modules/object.pick": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1995,6 +2784,8 @@ }, "node_modules/on-finished": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dev": true, "license": "MIT", "dependencies": { @@ -2006,6 +2797,8 @@ }, "node_modules/on-headers": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, "license": "MIT", "engines": { @@ -2014,6 +2807,8 @@ }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { @@ -2036,16 +2831,22 @@ }, "node_modules/pako": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true, "license": "(MIT AND Zlib)" }, "node_modules/parse-svg-path": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==", "license": "MIT", "peer": true }, "node_modules/parseurl": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "license": "MIT", "engines": { @@ -2054,6 +2855,8 @@ }, "node_modules/pascalcase": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", "dev": true, "license": "MIT", "engines": { @@ -2062,11 +2865,15 @@ }, "node_modules/path-dirname": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", "dev": true, "license": "MIT" }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", "engines": { @@ -2075,6 +2882,8 @@ }, "node_modules/pause-stream": { "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", "dev": true, "license": [ "MIT", @@ -2085,20 +2894,26 @@ } }, "node_modules/phaser": { - "version": "3.87.0", + "version": "4.0.0-rc.1", + "resolved": "https://registry.npmjs.org/phaser/-/phaser-4.0.0-rc.1.tgz", + "integrity": "sha512-OsUvqtTKSDZMjsy4qFlO7uCPklQRcoqi/ihefMnihrSYmAYTk5vqUjnM1yvTMISbNwe/J5VsADWg2stWAm7I5A==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "eventemitter3": "^5.0.1" } }, "node_modules/phaser/node_modules/eventemitter3": { "version": "5.0.1", - "license": "MIT", - "peer": true + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" }, "node_modules/pixi.js": { - "version": "8.4.0", + "version": "8.9.1", + "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.9.1.tgz", + "integrity": "sha512-2vF5Yu9WC/83ly2tCGkjb+ZGnrr+vlKtZezmD0AmJEQoYZO5nL94806l+PVcJBKW6qrF0YHtbh0ubb6CB7/8Rg==", "license": "MIT", "peer": true, "dependencies": { @@ -2109,22 +2924,29 @@ "@xmldom/xmldom": "^0.8.10", "earcut": "^2.2.4", "eventemitter3": "^5.0.1", + "gifuct-js": "^2.1.2", "ismobilejs": "^1.1.1", "parse-svg-path": "^0.1.2" } }, "node_modules/pixi.js/node_modules/@webgpu/types": { - "version": "0.1.51", + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.60.tgz", + "integrity": "sha512-8B/tdfRFKdrnejqmvq95ogp8tf52oZ51p3f4QD5m5Paey/qlX4Rhhy5Y8tgFMi7Ms70HzcMMw3EQjH/jdhTwlA==", "license": "BSD-3-Clause", "peer": true }, "node_modules/pixi.js/node_modules/eventemitter3": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT", "peer": true }, "node_modules/posix-character-classes": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", "dev": true, "license": "MIT", "engines": { @@ -2133,6 +2955,8 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "license": "MIT" }, @@ -2148,15 +2972,19 @@ }, "node_modules/punycode": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "license": "MIT", "peer": true }, "node_modules/qs": { - "version": "6.13.1", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "peer": true, "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -2167,6 +2995,8 @@ }, "node_modules/range-parser": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { @@ -2175,6 +3005,8 @@ }, "node_modules/readable-stream": { "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "dev": true, "license": "MIT", "dependencies": { @@ -2186,6 +3018,8 @@ }, "node_modules/readdirp": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2199,11 +3033,15 @@ }, "node_modules/readdirp/node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, "node_modules/readdirp/node_modules/readable-stream": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { @@ -2218,6 +3056,8 @@ }, "node_modules/readdirp/node_modules/string_decoder": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { @@ -2226,11 +3066,15 @@ }, "node_modules/regenerator-runtime": { "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true, "license": "MIT" }, "node_modules/regex-not": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "license": "MIT", "dependencies": { @@ -2243,6 +3087,8 @@ }, "node_modules/regex-not/node_modules/extend-shallow": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2255,6 +3101,8 @@ }, "node_modules/regex-not/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "license": "MIT", "dependencies": { @@ -2266,11 +3114,15 @@ }, "node_modules/remove-trailing-separator": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", "dev": true, "license": "ISC" }, "node_modules/repeat-element": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", "dev": true, "license": "MIT", "engines": { @@ -2279,6 +3131,8 @@ }, "node_modules/repeat-string": { "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true, "license": "MIT", "engines": { @@ -2287,6 +3141,8 @@ }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", "engines": { @@ -2295,11 +3151,16 @@ }, "node_modules/resolve-url": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", "dev": true, "license": "MIT" }, "node_modules/ret": { "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true, "license": "MIT", "engines": { @@ -2308,6 +3169,9 @@ }, "node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -2321,7 +3185,9 @@ } }, "node_modules/rxjs": { - "version": "7.8.1", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2330,11 +3196,15 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT" }, "node_modules/safe-regex": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", "dev": true, "license": "MIT", "dependencies": { @@ -2342,20 +3212,19 @@ } }, "node_modules/send": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz", - "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.5", - "destroy": "^1.2.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", - "fresh": "^0.5.2", + "fresh": "^2.0.0", "http-errors": "^2.0.0", - "mime-types": "^2.1.35", + "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", @@ -2366,7 +3235,9 @@ } }, "node_modules/send/node_modules/debug": { - "version": "4.3.7", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { @@ -2383,6 +3254,8 @@ }, "node_modules/send/node_modules/encodeurl": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { @@ -2391,11 +3264,15 @@ }, "node_modules/send/node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/send/node_modules/on-finished": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { @@ -2407,6 +3284,8 @@ }, "node_modules/send/node_modules/statuses": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", "engines": { @@ -2415,6 +3294,8 @@ }, "node_modules/serve-index": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, "license": "MIT", "dependencies": { @@ -2432,6 +3313,8 @@ }, "node_modules/serve-index/node_modules/depd": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", "engines": { @@ -2440,6 +3323,8 @@ }, "node_modules/serve-index/node_modules/http-errors": { "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, "license": "MIT", "dependencies": { @@ -2454,32 +3339,45 @@ }, "node_modules/serve-index/node_modules/inherits": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true, "license": "ISC" }, + "node_modules/serve-index/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true, "license": "ISC" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "license": "MIT", - "peer": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/set-value": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "license": "MIT", "dependencies": { @@ -2494,26 +3392,92 @@ }, "node_modules/setprototypeof": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, "license": "ISC" }, "node_modules/shell-quote": { - "version": "1.8.1", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { - "version": "1.0.6", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "peer": true, "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -2524,6 +3488,8 @@ }, "node_modules/snapdragon": { "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "license": "MIT", "dependencies": { @@ -2542,6 +3508,8 @@ }, "node_modules/snapdragon-node": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "license": "MIT", "dependencies": { @@ -2555,6 +3523,8 @@ }, "node_modules/snapdragon-node/node_modules/define-property": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "dev": true, "license": "MIT", "dependencies": { @@ -2566,6 +3536,8 @@ }, "node_modules/snapdragon-util": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2577,6 +3549,8 @@ }, "node_modules/snapdragon/node_modules/define-property": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "license": "MIT", "dependencies": { @@ -2588,6 +3562,8 @@ }, "node_modules/snapdragon/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -2600,6 +3576,8 @@ }, "node_modules/source-map": { "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -2608,6 +3586,9 @@ }, "node_modules/source-map-resolve": { "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", "dev": true, "license": "MIT", "dependencies": { @@ -2620,15 +3601,22 @@ }, "node_modules/source-map-url": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true, "license": "MIT" }, "node_modules/spawn-command": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, "node_modules/split": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", "dev": true, "license": "MIT", "dependencies": { @@ -2640,6 +3628,8 @@ }, "node_modules/split-string": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "license": "MIT", "dependencies": { @@ -2651,6 +3641,8 @@ }, "node_modules/split-string/node_modules/extend-shallow": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2663,6 +3655,8 @@ }, "node_modules/split-string/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "license": "MIT", "dependencies": { @@ -2674,6 +3668,8 @@ }, "node_modules/static-extend": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", "dev": true, "license": "MIT", "dependencies": { @@ -2686,6 +3682,8 @@ }, "node_modules/static-extend/node_modules/define-property": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "license": "MIT", "dependencies": { @@ -2697,6 +3695,8 @@ }, "node_modules/static-extend/node_modules/is-descriptor": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -2709,6 +3709,8 @@ }, "node_modules/statuses": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", "engines": { @@ -2717,6 +3719,8 @@ }, "node_modules/stream-combiner": { "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", "dev": true, "license": "MIT", "dependencies": { @@ -2725,11 +3729,15 @@ }, "node_modules/string_decoder": { "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true, "license": "MIT" }, "node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -2743,6 +3751,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -2754,6 +3764,8 @@ }, "node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2768,16 +3780,22 @@ }, "node_modules/three": { "version": "0.162.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.162.0.tgz", + "integrity": "sha512-xfCYj4RnlozReCmUd+XQzj6/5OjDNHBy5nT6rVwrOKGENAvpXe2z1jL+DZYaMu4/9pNsjH/4Os/VvS9IrH7IOQ==", "license": "MIT", "peer": true }, "node_modules/through": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true, "license": "MIT" }, "node_modules/through2": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2787,11 +3805,15 @@ }, "node_modules/through2/node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, "node_modules/through2/node_modules/readable-stream": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { @@ -2806,6 +3828,8 @@ }, "node_modules/through2/node_modules/string_decoder": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { @@ -2814,6 +3838,8 @@ }, "node_modules/to-object-path": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", "dev": true, "license": "MIT", "dependencies": { @@ -2825,6 +3851,8 @@ }, "node_modules/to-regex": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "license": "MIT", "dependencies": { @@ -2839,6 +3867,8 @@ }, "node_modules/to-regex-range": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "dev": true, "license": "MIT", "dependencies": { @@ -2851,6 +3881,8 @@ }, "node_modules/to-regex/node_modules/extend-shallow": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2863,6 +3895,8 @@ }, "node_modules/to-regex/node_modules/is-extendable": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "license": "MIT", "dependencies": { @@ -2874,6 +3908,8 @@ }, "node_modules/toidentifier": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", "engines": { @@ -2882,6 +3918,8 @@ }, "node_modules/tree-kill": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", "bin": { @@ -2890,11 +3928,15 @@ }, "node_modules/tslib": { "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, "node_modules/typescript": { "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2907,11 +3949,15 @@ }, "node_modules/undici-types": { "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, "license": "MIT" }, "node_modules/union-value": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -2926,11 +3972,15 @@ }, "node_modules/unix-crypt-td-js": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/unpipe": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", "engines": { @@ -2939,6 +3989,8 @@ }, "node_modules/unset-value": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2951,6 +4003,8 @@ }, "node_modules/unset-value/node_modules/has-value": { "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2964,6 +4018,8 @@ }, "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", "dev": true, "license": "MIT", "dependencies": { @@ -2975,6 +4031,8 @@ }, "node_modules/unset-value/node_modules/has-values": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", "dev": true, "license": "MIT", "engines": { @@ -2983,11 +4041,15 @@ }, "node_modules/unset-value/node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, "node_modules/untildify": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "dev": true, "license": "MIT", "engines": { @@ -2996,6 +4058,8 @@ }, "node_modules/upath": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true, "license": "MIT", "engines": { @@ -3005,11 +4069,16 @@ }, "node_modules/urix": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", "dev": true, "license": "MIT" }, "node_modules/url": { "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "license": "MIT", "peer": true, "dependencies": { @@ -3022,6 +4091,8 @@ }, "node_modules/use": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true, "license": "MIT", "engines": { @@ -3030,11 +4101,15 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", "engines": { @@ -3043,6 +4118,9 @@ }, "node_modules/uuid": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, "license": "MIT", "bin": { @@ -3051,6 +4129,8 @@ }, "node_modules/vary": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { @@ -3059,6 +4139,8 @@ }, "node_modules/websocket-driver": { "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3072,6 +4154,8 @@ }, "node_modules/websocket-extensions": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3080,6 +4164,8 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3096,11 +4182,15 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, "node_modules/xtend": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true, "license": "MIT", "engines": { @@ -3109,6 +4199,8 @@ }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { @@ -3117,6 +4209,8 @@ }, "node_modules/yargs": { "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "dependencies": { @@ -3134,6 +4228,8 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { @@ -3166,8 +4262,8 @@ "version": "4.2.76", "license": "LicenseRef-LICENSE" }, - "spine-phaser": { - "name": "@esotericsoftware/spine-phaser", + "spine-phaser-v3": { + "name": "@esotericsoftware/spine-phaser-v3", "version": "4.2.76", "license": "LicenseRef-LICENSE", "dependencies": { @@ -3175,10 +4271,42 @@ "@esotericsoftware/spine-core": "4.2.76", "@esotericsoftware/spine-webgl": "4.2.76" }, + "devDependencies": { + "phaser": "^3.60.0" + }, "peerDependencies": { "phaser": "^3.60.0" } }, + "spine-phaser-v3/node_modules/eventemitter3": { + "version": "5.0.1", + "dev": true, + "license": "MIT" + }, + "spine-phaser-v3/node_modules/phaser": { + "version": "3.88.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1" + } + }, + "spine-phaser-v4": { + "name": "@esotericsoftware/spine-phaser-v4", + "version": "4.2.76", + "license": "LicenseRef-LICENSE", + "dependencies": { + "@esotericsoftware/spine-canvas": "4.2.76", + "@esotericsoftware/spine-core": "4.2.76", + "@esotericsoftware/spine-webgl": "4.2.76" + }, + "devDependencies": { + "phaser": "^4.0.0-rc.1" + }, + "peerDependencies": { + "phaser": "^4.0.0-rc.1" + } + }, "spine-pixi-v7": { "name": "@esotericsoftware/spine-pixi-v7", "version": "4.2.76", diff --git a/spine-ts/package.json b/spine-ts/package.json index cb4110e51..f45e6499b 100644 --- a/spine-ts/package.json +++ b/spine-ts/package.json @@ -8,8 +8,8 @@ ], "scripts": { "prepublish": "npm run clean && npm run build", - "clean": "npx rimraf spine-core/dist spine-canvas/dist spine-canvaskit/dist spine-webgl/dist spine-phaser/dist spine-player/dist spine-threejs/dist spine-pixi-v7/dist spine-pixi-v8/dist", - "build": "npm run clean && npm run build:modules && concurrently 'npm run build:core:iife' 'npm run build:core:esm' 'npm run build:canvas:iife' 'npm run build:canvas:esm' 'npm run build:canvaskit:iife' 'npm run build:canvaskit:esm' 'npm run build:webgl:iife' 'npm run build:webgl:esm' 'npm run build:phaser:iife' 'npm run build:phaser:esm' 'npm run build:player:iife' 'npm run build:player:esm' 'npm run build:player:css' 'npm run build:threejs:iife' 'npm run build:threejs:esm' 'npm run build:pixi-v7:iife' 'npm run build:pixi-v7:esm' 'npm run build:pixi-v8:iife' 'npm run build:pixi-v8:esm'", + "clean": "npx rimraf spine-core/dist spine-canvas/dist spine-canvaskit/dist spine-webgl/dist spine-phaser-v3/dist spine-phaser-v4/dist spine-player/dist spine-threejs/dist spine-pixi-v7/dist spine-pixi-v8/dist", + "build": "npm run clean && npm run build:modules && concurrently 'npm run build:core:iife' 'npm run build:core:esm' 'npm run build:canvas:iife' 'npm run build:canvas:esm' 'npm run build:canvaskit:iife' 'npm run build:canvaskit:esm' 'npm run build:webgl:iife' 'npm run build:webgl:esm' 'npm run build:phaser-v3:iife' 'npm run build:phaser-v4:iife' 'npm run build:phaser-v3:esm' 'npm run build:phaser-v4:esm' 'npm run build:player:iife' 'npm run build:player:esm' 'npm run build:player:css' 'npm run build:threejs:iife' 'npm run build:threejs:esm' 'npm run build:pixi-v7:iife' 'npm run build:pixi-v7:esm' 'npm run build:pixi-v8:iife' 'npm run build:pixi-v8:esm'", "postbuild": "npm run minify", "build:modules": "npx tsc -b -clean && npx tsc -b", "build:core:iife": "npx esbuild --bundle spine-core/src/index.ts --tsconfig=spine-core/tsconfig.json --sourcemap --outfile=spine-core/dist/iife/spine-core.js --format=iife --global-name=spine", @@ -23,21 +23,24 @@ "build:player:iife": "npx esbuild --bundle spine-player/src/index.ts --tsconfig=spine-player/tsconfig.json --sourcemap --outfile=spine-player/dist/iife/spine-player.js --format=iife --global-name=spine", "build:player:esm": "npx esbuild --bundle spine-player/src/index.ts --tsconfig=spine-player/tsconfig.json --sourcemap --outfile=spine-player/dist/esm/spine-player.mjs --format=esm --global-name=spine", "build:player:css": "npx copyfiles -f spine-player/css/spine-player.css spine-player/dist/ && npx esbuild spine-player/dist/spine-player.css --minify --outfile=spine-player/dist/spine-player.min.css", - "build:phaser:iife": "npx esbuild --bundle spine-phaser/src/index.ts --tsconfig=spine-phaser/tsconfig.json --sourcemap --outfile=spine-phaser/dist/iife/spine-phaser.js --external:Phaser --alias:phaser=Phaser --format=iife --global-name=spine", - "build:phaser:esm": "npx esbuild --bundle spine-phaser/src/index.ts --tsconfig=spine-phaser/tsconfig.json --sourcemap --outfile=spine-phaser/dist/esm/spine-phaser.mjs --external:Phaser --alias:phaser=Phaser --format=esm --global-name=spine", + "build:phaser-v3:iife": "npx esbuild --bundle spine-phaser-v3/src/index.ts --tsconfig=spine-phaser-v3/tsconfig.json --sourcemap --outfile=spine-phaser-v3/dist/iife/spine-phaser-v3.js --external:Phaser --alias:phaser=Phaser --format=iife --global-name=spine", + "build:phaser-v3:esm": "npx esbuild --bundle spine-phaser-v3/src/index.ts --tsconfig=spine-phaser-v3/tsconfig.json --sourcemap --outfile=spine-phaser-v3/dist/esm/spine-phaser-v3.mjs --external:Phaser --alias:phaser=Phaser --format=esm --global-name=spine", + "build:phaser-v4:iife": "npx esbuild --bundle spine-phaser-v4/src/index.ts --tsconfig=spine-phaser-v4/tsconfig.json --sourcemap --outfile=spine-phaser-v4/dist/iife/spine-phaser-v4.js --external:Phaser --alias:phaser=Phaser --format=iife --global-name=spine", + "build:phaser-v4:esm": "npx esbuild --bundle spine-phaser-v4/src/index.ts --tsconfig=spine-phaser-v4/tsconfig.json --sourcemap --outfile=spine-phaser-v4/dist/esm/spine-phaser-v4.mjs --external:Phaser --alias:phaser=Phaser --format=esm --global-name=spine", "build:threejs:iife": "npx esbuild --bundle spine-threejs/src/index.ts --tsconfig=spine-threejs/tsconfig.json --sourcemap --outfile=spine-threejs/dist/iife/spine-threejs.js --external:three --format=iife --global-name=spine", "build:threejs:esm": "npx esbuild --bundle spine-threejs/src/index.ts --tsconfig=spine-threejs/tsconfig.json --sourcemap --outfile=spine-threejs/dist/esm/spine-threejs.mjs --external:three --format=esm --global-name=spine", "build:pixi-v7:iife": "npx esbuild --bundle spine-pixi-v7/src/index.ts --tsconfig=spine-pixi-v7/tsconfig.json --sourcemap --outfile=spine-pixi-v7/dist/iife/spine-pixi-v7.js --external:@pixi/* --format=iife --global-name=spine", "build:pixi-v7:esm": "npx esbuild --bundle spine-pixi-v7/src/index.ts --tsconfig=spine-pixi-v7/tsconfig.json --sourcemap --outfile=spine-pixi-v7/dist/esm/spine-pixi-v7.mjs --external:@pixi/* --format=esm --global-name=spine", "build:pixi-v8:iife": "npx esbuild --bundle spine-pixi-v8/src/index.ts --tsconfig=spine-pixi-v8/tsconfig.json --sourcemap --outfile=spine-pixi-v8/dist/iife/spine-pixi-v8.js --external:pixi.js --format=iife --global-name=spine", "build:pixi-v8:esm": "npx esbuild --bundle spine-pixi-v8/src/index.ts --tsconfig=spine-pixi-v8/tsconfig.json --sourcemap --outfile=spine-pixi-v8/dist/esm/spine-pixi-v8.mjs --external:pixi.js --format=esm --global-name=spine", - "minify": "npx esbuild --minify spine-core/dist/iife/spine-core.js --outfile=spine-core/dist/iife/spine-core.min.js && npx esbuild --minify spine-core/dist/esm/spine-core.mjs --outfile=spine-core/dist/esm/spine-core.min.mjs && npx esbuild --minify spine-canvas/dist/iife/spine-canvas.js --outfile=spine-canvas/dist/iife/spine-canvas.min.js && npx esbuild --minify spine-canvas/dist/esm/spine-canvas.mjs --outfile=spine-canvas/dist/esm/spine-canvas.min.mjs && npx esbuild --minify spine-canvaskit/dist/iife/spine-canvaskit.js --outfile=spine-canvaskit/dist/iife/spine-canvaskit.min.js && npx esbuild --minify spine-canvaskit/dist/esm/spine-canvaskit.mjs --outfile=spine-canvaskit/dist/esm/spine-canvaskit.min.mjs && npx esbuild --minify spine-player/dist/iife/spine-player.js --outfile=spine-player/dist/iife/spine-player.min.js && npx esbuild --minify spine-player/dist/esm/spine-player.mjs --outfile=spine-player/dist/esm/spine-player.min.mjs && npx esbuild --minify spine-phaser/dist/iife/spine-phaser.js --outfile=spine-phaser/dist/iife/spine-phaser.min.js && npx esbuild --minify spine-phaser/dist/esm/spine-phaser.mjs --outfile=spine-phaser/dist/esm/spine-phaser.min.mjs && npx esbuild --minify spine-webgl/dist/iife/spine-webgl.js --outfile=spine-webgl/dist/iife/spine-webgl.min.js && npx esbuild --minify spine-webgl/dist/esm/spine-webgl.mjs --outfile=spine-webgl/dist/esm/spine-webgl.min.mjs && npx esbuild --minify spine-threejs/dist/iife/spine-threejs.js --outfile=spine-threejs/dist/iife/spine-threejs.min.js && npx esbuild --minify spine-threejs/dist/esm/spine-threejs.mjs --outfile=spine-threejs/dist/esm/spine-threejs.min.mjs && npx esbuild --minify spine-pixi-v7/dist/iife/spine-pixi-v7.js --outfile=spine-pixi-v7/dist/iife/spine-pixi-v7.min.js && npx esbuild --minify spine-pixi-v7/dist/esm/spine-pixi-v7.mjs --outfile=spine-pixi-v7/dist/esm/spine-pixi-v7.min.mjs && npx esbuild --minify spine-pixi-v8/dist/iife/spine-pixi-v8.js --outfile=spine-pixi-v8/dist/iife/spine-pixi-v8.min.js && npx esbuild --minify spine-pixi-v8/dist/esm/spine-pixi-v8.mjs --outfile=spine-pixi-v8/dist/esm/spine-pixi-v8.min.mjs", - "dev": "concurrently 'npx live-server' 'npm run dev:canvas' 'npm run dev:canvaskit' 'npm run dev:webgl' 'npm run dev:phaser' 'npm run dev:player' 'npm run dev:threejs' 'npm run dev:pixi-v7' 'npm run dev:pixi-v8' 'npm run dev:modules'", + "minify": "npx esbuild --minify spine-core/dist/iife/spine-core.js --outfile=spine-core/dist/iife/spine-core.min.js && npx esbuild --minify spine-core/dist/esm/spine-core.mjs --outfile=spine-core/dist/esm/spine-core.min.mjs && npx esbuild --minify spine-canvas/dist/iife/spine-canvas.js --outfile=spine-canvas/dist/iife/spine-canvas.min.js && npx esbuild --minify spine-canvas/dist/esm/spine-canvas.mjs --outfile=spine-canvas/dist/esm/spine-canvas.min.mjs && npx esbuild --minify spine-canvaskit/dist/iife/spine-canvaskit.js --outfile=spine-canvaskit/dist/iife/spine-canvaskit.min.js && npx esbuild --minify spine-canvaskit/dist/esm/spine-canvaskit.mjs --outfile=spine-canvaskit/dist/esm/spine-canvaskit.min.mjs && npx esbuild --minify spine-player/dist/iife/spine-player.js --outfile=spine-player/dist/iife/spine-player.min.js && npx esbuild --minify spine-player/dist/esm/spine-player.mjs --outfile=spine-player/dist/esm/spine-player.min.mjs && npx esbuild --minify spine-phaser-v3/dist/iife/spine-phaser-v3.js --outfile=spine-phaser-v3/dist/iife/spine-phaser-v3.min.js && npx esbuild --minify spine-phaser-v3/dist/esm/spine-phaser-v3.mjs --outfile=spine-phaser-v3/dist/esm/spine-phaser-v3.min.mjs && npx esbuild --minify spine-phaser-v4/dist/iife/spine-phaser-v4.js --outfile=spine-phaser-v4/dist/iife/spine-phaser-v4.min.js && npx esbuild --minify spine-phaser-v4/dist/esm/spine-phaser-v4.mjs --outfile=spine-phaser-v4/dist/esm/spine-phaser-v4.min.mjs && npx esbuild --minify spine-webgl/dist/iife/spine-webgl.js --outfile=spine-webgl/dist/iife/spine-webgl.min.js && npx esbuild --minify spine-webgl/dist/esm/spine-webgl.mjs --outfile=spine-webgl/dist/esm/spine-webgl.min.mjs && npx esbuild --minify spine-threejs/dist/iife/spine-threejs.js --outfile=spine-threejs/dist/iife/spine-threejs.min.js && npx esbuild --minify spine-threejs/dist/esm/spine-threejs.mjs --outfile=spine-threejs/dist/esm/spine-threejs.min.mjs && npx esbuild --minify spine-pixi-v7/dist/iife/spine-pixi-v7.js --outfile=spine-pixi-v7/dist/iife/spine-pixi-v7.min.js && npx esbuild --minify spine-pixi-v7/dist/esm/spine-pixi-v7.mjs --outfile=spine-pixi-v7/dist/esm/spine-pixi-v7.min.mjs && npx esbuild --minify spine-pixi-v8/dist/iife/spine-pixi-v8.js --outfile=spine-pixi-v8/dist/iife/spine-pixi-v8.min.js && npx esbuild --minify spine-pixi-v8/dist/esm/spine-pixi-v8.mjs --outfile=spine-pixi-v8/dist/esm/spine-pixi-v8.min.mjs", + "dev": "concurrently 'npx live-server' 'npm run dev:canvas' 'npm run dev:canvaskit' 'npm run dev:webgl' 'npm run dev:phaser-v3' 'npm run dev:phaser-v4' 'npm run dev:player' 'npm run dev:threejs' 'npm run dev:pixi-v7' 'npm run dev:pixi-v8' 'npm run dev:modules'", "dev:modules": "npm run build:modules -- --watch", "dev:canvas": "concurrently 'npm run build:canvas:iife -- --watch' 'npm run build:canvas:esm -- --watch'", "dev:canvaskit": "concurrently 'npm run build:canvaskit:iife -- --watch' 'npm run build:canvaskit:esm -- --watch'", "dev:webgl": "concurrently 'npm run build:webgl:iife -- --watch' 'npm run build:webgl:esm -- --watch'", - "dev:phaser": "concurrently 'npm run build:phaser:iife -- --watch' 'npm run build:phaser:esm -- --watch'", + "dev:phaser-v3": "concurrently 'npm run build:phaser-v3:iife -- --watch' 'npm run build:phaser-v3:esm -- --watch'", + "dev:phaser-v4": "concurrently 'npm run build:phaser-v4:iife -- --watch' 'npm run build:phaser-v4:esm -- --watch'", "dev:player": "concurrently 'npm run build:player:iife -- --watch' 'npm run build:player:esm -- --watch' 'npm run build:player:css -- --watch'", "dev:threejs": "concurrently 'npm run build:threejs:iife -- --watch' 'npm run build:threejs:esm -- --watch'", "dev:pixi-v7": "concurrently 'npm run build:pixi-v7:iife -- --watch' 'npm run build:pixi-v7:esm -- --watch'", @@ -65,7 +68,8 @@ "workspaces": [ "spine-core", "spine-canvas", - "spine-phaser", + "spine-phaser-v3", + "spine-phaser-v4", "spine-player", "spine-threejs", "spine-pixi-v7", diff --git a/spine-ts/spine-phaser/LICENSE b/spine-ts/spine-phaser-v3/LICENSE similarity index 100% rename from spine-ts/spine-phaser/LICENSE rename to spine-ts/spine-phaser-v3/LICENSE diff --git a/spine-ts/spine-phaser/README.md b/spine-ts/spine-phaser-v3/README.md similarity index 77% rename from spine-ts/spine-phaser/README.md rename to spine-ts/spine-phaser-v3/README.md index d6add7cde..15b1d0813 100644 --- a/spine-ts/spine-phaser/README.md +++ b/spine-ts/spine-phaser-v3/README.md @@ -1,3 +1,3 @@ -# spine-ts Phaser +# spine-ts Phaser v3 Please see the top-level [README.md](../README.md) for more information. \ No newline at end of file diff --git a/spine-ts/spine-phaser-v3/dist/SpineGameObject.d.ts b/spine-ts/spine-phaser-v3/dist/SpineGameObject.d.ts new file mode 100644 index 000000000..676fc086b --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/SpineGameObject.d.ts @@ -0,0 +1,137 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +import { SpinePlugin } from "./SpinePlugin.js"; +import { AnimationState, AnimationStateData, Bone, Skeleton } from "@esotericsoftware/spine-core"; +declare class BaseSpineGameObject extends Phaser.GameObjects.GameObject { + constructor(scene: Phaser.Scene, type: string); +} +/** A bounds provider calculates the bounding box for a skeleton, which is then assigned as the size of the SpineGameObject. */ +export interface SpineGameObjectBoundsProvider { + calculateBounds(gameObject: SpineGameObject): { + x: number; + y: number; + width: number; + height: number; + }; +} +/** A bounds provider that calculates the bounding box from the setup pose. */ +export declare class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider { + private clipping; + /** + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(clipping?: boolean); + calculateBounds(gameObject: SpineGameObject): { + x: number; + y: number; + width: number; + height: number; + }; +} +/** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */ +export declare class SkinsAndAnimationBoundsProvider implements SpineGameObjectBoundsProvider { + private animation; + private skins; + private timeStep; + private clipping; + /** + * @param animation The animation to use for calculating the bounds. If null, the setup pose is used. + * @param skins The skins to use for calculating the bounds. If empty, the default skin is used. + * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation. + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(animation: string | null, skins?: string[], timeStep?: number, clipping?: boolean); + calculateBounds(gameObject: SpineGameObject): { + x: number; + y: number; + width: number; + height: number; + }; +} +declare const SpineGameObject_base: typeof BaseSpineGameObject & import("./mixins.js").Type & import("./mixins.js").Type & import("./mixins.js").Type & import("./mixins.js").Type & import("./mixins.js").Type & import("./mixins.js").Type & import("./mixins.js").Type & import("./mixins.js").Type; +/** + * A SpineGameObject is a Phaser {@link GameObject} that can be added to a Phaser Scene and render a Spine skeleton. + * + * The Spine GameObject is a thin wrapper around a Spine {@link Skeleton}, {@link AnimationState} and {@link AnimationStateData}. It is responsible for: + * - updating the animation state + * - applying the animation state to the skeleton's bones, slots, attachments, and draw order. + * - updating the skeleton's bone world transforms + * - rendering the skeleton + * + * See the {@link SpinePlugin} class for more information on how to create a `SpineGameObject`. + * + * The skeleton, animation state, and animation state data can be accessed via the repsective fields. They can be manually updated via {@link updatePose}. + * + * To modify the bone hierarchy before the world transforms are computed, a callback can be set via the {@link beforeUpdateWorldTransforms} field. + * + * To modify the bone hierarchy after the world transforms are computed, a callback can be set via the {@link afterUpdateWorldTransforms} field. + * + * The class also features methods to convert between the skeleton coordinate system and the Phaser coordinate system. + * + * See {@link skeletonToPhaserWorldCoordinates}, {@link phaserWorldCoordinatesToSkeleton}, and {@link phaserWorldCoordinatesToBoneLocal.} + */ +export declare class SpineGameObject extends SpineGameObject_base { + private plugin; + boundsProvider: SpineGameObjectBoundsProvider; + blendMode: number; + skeleton: Skeleton; + animationStateData: AnimationStateData; + animationState: AnimationState; + beforeUpdateWorldTransforms: (object: SpineGameObject) => void; + afterUpdateWorldTransforms: (object: SpineGameObject) => void; + private premultipliedAlpha; + constructor(scene: Phaser.Scene, plugin: SpinePlugin, x: number, y: number, dataKey: string, atlasKey: string, boundsProvider?: SpineGameObjectBoundsProvider); + updateSize(): void; + /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */ + skeletonToPhaserWorldCoordinates(point: { + x: number; + y: number; + }): void; + /** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */ + phaserWorldCoordinatesToSkeleton(point: { + x: number; + y: number; + }): void; + /** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */ + phaserWorldCoordinatesToBone(point: { + x: number; + y: number; + }, bone: Bone): void; + /** + * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones. + * @param delta The time delta in milliseconds + */ + updatePose(delta: number): void; + preUpdate(time: number, delta: number): void; + preDestroy(): void; + willRender(camera: Phaser.Cameras.Scene2D.Camera): boolean; + renderWebGL(renderer: Phaser.Renderer.WebGL.WebGLRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix): void; + renderCanvas(renderer: Phaser.Renderer.Canvas.CanvasRenderer, src: SpineGameObject, camera: Phaser.Cameras.Scene2D.Camera, parentMatrix: Phaser.GameObjects.Components.TransformMatrix): void; +} +export {}; diff --git a/spine-ts/spine-phaser-v3/dist/SpineGameObject.js b/spine-ts/spine-phaser-v3/dist/SpineGameObject.js new file mode 100644 index 000000000..bc52619a0 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/SpineGameObject.js @@ -0,0 +1,300 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +import { SPINE_GAME_OBJECT_TYPE } from "./keys.js"; +import { ComputedSizeMixin, DepthMixin, FlipMixin, ScrollFactorMixin, TransformMixin, VisibleMixin, AlphaMixin, OriginMixin, } from "./mixins.js"; +import { AnimationState, AnimationStateData, MathUtils, Physics, Skeleton, SkeletonClipping, Skin, } from "@esotericsoftware/spine-core"; +class BaseSpineGameObject extends Phaser.GameObjects.GameObject { + constructor(scene, type) { + super(scene, type); + } +} +/** A bounds provider that calculates the bounding box from the setup pose. */ +export class SetupPoseBoundsProvider { + clipping; + /** + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(clipping = false) { + this.clipping = clipping; + } + calculateBounds(gameObject) { + if (!gameObject.skeleton) + return { x: 0, y: 0, width: 0, height: 0 }; + // Make a copy of animation state and skeleton as this might be called while + // the skeleton in the GameObject has already been heavily modified. We can not + // reconstruct that state. + const skeleton = new Skeleton(gameObject.skeleton.data); + skeleton.setToSetupPose(); + skeleton.updateWorldTransform(Physics.update); + const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined); + return bounds.width == Number.NEGATIVE_INFINITY + ? { x: 0, y: 0, width: 0, height: 0 } + : bounds; + } +} +/** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */ +export class SkinsAndAnimationBoundsProvider { + animation; + skins; + timeStep; + clipping; + /** + * @param animation The animation to use for calculating the bounds. If null, the setup pose is used. + * @param skins The skins to use for calculating the bounds. If empty, the default skin is used. + * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation. + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(animation, skins = [], timeStep = 0.05, clipping = false) { + this.animation = animation; + this.skins = skins; + this.timeStep = timeStep; + this.clipping = clipping; + } + calculateBounds(gameObject) { + if (!gameObject.skeleton || !gameObject.animationState) + return { x: 0, y: 0, width: 0, height: 0 }; + // Make a copy of animation state and skeleton as this might be called while + // the skeleton in the GameObject has already been heavily modified. We can not + // reconstruct that state. + const animationState = new AnimationState(gameObject.animationState.data); + const skeleton = new Skeleton(gameObject.skeleton.data); + const clipper = this.clipping ? new SkeletonClipping() : undefined; + const data = skeleton.data; + if (this.skins.length > 0) { + let customSkin = new Skin("custom-skin"); + for (const skinName of this.skins) { + const skin = data.findSkin(skinName); + if (skin == null) + continue; + customSkin.addSkin(skin); + } + skeleton.setSkin(customSkin); + } + skeleton.setToSetupPose(); + const animation = this.animation != null ? data.findAnimation(this.animation) : null; + if (animation == null) { + skeleton.updateWorldTransform(Physics.update); + const bounds = skeleton.getBoundsRect(clipper); + return bounds.width == Number.NEGATIVE_INFINITY + ? { x: 0, y: 0, width: 0, height: 0 } + : bounds; + } + else { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + animationState.clearTracks(); + animationState.setAnimationWith(0, animation, false); + const steps = Math.max(animation.duration / this.timeStep, 1.0); + for (let i = 0; i < steps; i++) { + const delta = i > 0 ? this.timeStep : 0; + animationState.update(delta); + animationState.apply(skeleton); + skeleton.update(delta); + skeleton.updateWorldTransform(Physics.update); + const bounds = skeleton.getBoundsRect(clipper); + minX = Math.min(minX, bounds.x); + minY = Math.min(minY, bounds.y); + maxX = Math.max(maxX, bounds.x + bounds.width); + maxY = Math.max(maxY, bounds.y + bounds.height); + } + const bounds = { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY, + }; + return bounds.width == Number.NEGATIVE_INFINITY + ? { x: 0, y: 0, width: 0, height: 0 } + : bounds; + } + } +} +/** + * A SpineGameObject is a Phaser {@link GameObject} that can be added to a Phaser Scene and render a Spine skeleton. + * + * The Spine GameObject is a thin wrapper around a Spine {@link Skeleton}, {@link AnimationState} and {@link AnimationStateData}. It is responsible for: + * - updating the animation state + * - applying the animation state to the skeleton's bones, slots, attachments, and draw order. + * - updating the skeleton's bone world transforms + * - rendering the skeleton + * + * See the {@link SpinePlugin} class for more information on how to create a `SpineGameObject`. + * + * The skeleton, animation state, and animation state data can be accessed via the repsective fields. They can be manually updated via {@link updatePose}. + * + * To modify the bone hierarchy before the world transforms are computed, a callback can be set via the {@link beforeUpdateWorldTransforms} field. + * + * To modify the bone hierarchy after the world transforms are computed, a callback can be set via the {@link afterUpdateWorldTransforms} field. + * + * The class also features methods to convert between the skeleton coordinate system and the Phaser coordinate system. + * + * See {@link skeletonToPhaserWorldCoordinates}, {@link phaserWorldCoordinatesToSkeleton}, and {@link phaserWorldCoordinatesToBoneLocal.} + */ +export class SpineGameObject extends DepthMixin(OriginMixin(ComputedSizeMixin(FlipMixin(ScrollFactorMixin(TransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject)))))))) { + plugin; + boundsProvider; + blendMode = -1; + skeleton; + animationStateData; + animationState; + beforeUpdateWorldTransforms = () => { }; + afterUpdateWorldTransforms = () => { }; + premultipliedAlpha = false; + constructor(scene, plugin, x, y, dataKey, atlasKey, boundsProvider = new SetupPoseBoundsProvider()) { + super(scene, window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE); + this.plugin = plugin; + this.boundsProvider = boundsProvider; + this.setPosition(x, y); + this.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey); + this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey); + this.animationStateData = new AnimationStateData(this.skeleton.data); + this.animationState = new AnimationState(this.animationStateData); + this.skeleton.updateWorldTransform(Physics.update); + this.updateSize(); + } + updateSize() { + if (!this.skeleton) + return; + let bounds = this.boundsProvider.calculateBounds(this); + // For some reason the TS compiler and the ComputedSize mixin don't work well together and we have + // to cast to any. + let self = this; + self.width = bounds.width; + self.height = bounds.height; + this.displayOriginX = -bounds.x; + this.displayOriginY = -bounds.y; + } + /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */ + skeletonToPhaserWorldCoordinates(point) { + let transform = this.getWorldTransformMatrix(); + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + let x = point.x; + let y = point.y; + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + } + /** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */ + phaserWorldCoordinatesToSkeleton(point) { + let transform = this.getWorldTransformMatrix(); + transform = transform.invert(); + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + let x = point.x; + let y = point.y; + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + } + /** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */ + phaserWorldCoordinatesToBone(point, bone) { + this.phaserWorldCoordinatesToSkeleton(point); + if (bone.parent) { + bone.parent.worldToLocal(point); + } + else { + bone.worldToLocal(point); + } + } + /** + * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones. + * @param delta The time delta in milliseconds + */ + updatePose(delta) { + this.animationState.update(delta / 1000); + this.animationState.apply(this.skeleton); + this.beforeUpdateWorldTransforms(this); + this.skeleton.update(delta / 1000); + this.skeleton.updateWorldTransform(Physics.update); + this.afterUpdateWorldTransforms(this); + } + preUpdate(time, delta) { + if (!this.skeleton || !this.animationState) + return; + this.updatePose(delta); + } + preDestroy() { + // FIXME tear down any event emitters + } + willRender(camera) { + var GameObjectRenderMask = 0xf; + var result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id)); + if (!this.visible) + result = false; + if (!result && this.parentContainer && this.plugin.webGLRenderer) { + var sceneRenderer = this.plugin.webGLRenderer; + if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) { + sceneRenderer.end(); + this.plugin.phaserRenderer.pipelines.rebind(); + } + } + return result; + } + renderWebGL(renderer, src, camera, parentMatrix) { + if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer) + return; + let sceneRenderer = this.plugin.webGLRenderer; + if (renderer.newType) { + renderer.pipelines.clear(); + sceneRenderer.begin(); + } + camera.addToRenderList(src); + let transform = Phaser.GameObjects.GetCalcMatrix(src, camera, parentMatrix).calc; + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + sceneRenderer.drawSkeleton(this.skeleton, this.premultipliedAlpha, -1, -1, (vertices, numVertices, stride) => { + for (let i = 0; i < numVertices; i += stride) { + let vx = vertices[i]; + let vy = vertices[i + 1]; + vertices[i] = vx * a + vy * c + tx; + vertices[i + 1] = vx * b + vy * d + ty; + } + }); + if (!renderer.nextTypeMatch) { + sceneRenderer.end(); + renderer.pipelines.rebind(); + } + } + renderCanvas(renderer, src, camera, parentMatrix) { + if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer) + return; + let context = renderer.currentContext; + let skeletonRenderer = this.plugin.canvasRenderer; + skeletonRenderer.ctx = context; + camera.addToRenderList(src); + let transform = Phaser.GameObjects.GetCalcMatrix(src, camera, parentMatrix).calc; + let skeleton = this.skeleton; + skeleton.x = transform.tx; + skeleton.y = transform.ty; + skeleton.scaleX = transform.scaleX; + skeleton.scaleY = transform.scaleY; + let root = skeleton.getRootBone(); + root.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized; + this.skeleton.updateWorldTransform(Physics.update); + context.save(); + skeletonRenderer.draw(skeleton); + context.restore(); + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BpbmVHYW1lT2JqZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NwaW5lR2FtZU9iamVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFFL0UsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRW5ELE9BQU8sRUFDTixpQkFBaUIsRUFDakIsVUFBVSxFQUNWLFNBQVMsRUFDVCxpQkFBaUIsRUFDakIsY0FBYyxFQUNkLFlBQVksRUFDWixVQUFVLEVBQ1YsV0FBVyxHQUNYLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFDTixjQUFjLEVBQ2Qsa0JBQWtCLEVBRWxCLFNBQVMsRUFDVCxPQUFPLEVBQ1AsUUFBUSxFQUNSLGdCQUFnQixFQUNoQixJQUFJLEdBRUosTUFBTSw4QkFBOEIsQ0FBQztBQUV0QyxNQUFNLG1CQUFvQixTQUFRLE1BQU0sQ0FBQyxXQUFXLENBQUMsVUFBVTtJQUM5RCxZQUFhLEtBQW1CLEVBQUUsSUFBWTtRQUM3QyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BCLENBQUM7Q0FDRDtBQWFELDhFQUE4RTtBQUM5RSxNQUFNLE9BQU8sdUJBQXVCO0lBSzFCO0lBSlQ7O09BRUc7SUFDSCxZQUNTLFdBQVcsS0FBSztRQUFoQixhQUFRLEdBQVIsUUFBUSxDQUFRO0lBQ3JCLENBQUM7SUFFTCxlQUFlLENBQUUsVUFBMkI7UUFDM0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRO1lBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNyRSw0RUFBNEU7UUFDNUUsK0VBQStFO1FBQy9FLDBCQUEwQjtRQUMxQixNQUFNLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQyxVQUFV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Y0FBYztZQUN4RSxPQUFPO1FBRVIsSUFBSSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQztRQUN0QyxJQUFJLGdCQUFnQixHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDO1FBQ2pELGdCQUF3QixDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUM7UUFFeEMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM1QixJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FDL0MsR0FBRyxFQUNILE1BQU0sRUFDTixZQUFZLENBQ1osQ0FBQyxJQUFJLENBQUM7UUFDUCxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQzdCLFFBQVEsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUMxQixRQUFRLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDMUIsUUFBUSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ25DLFFBQVEsQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuQyxJQUFJLElBQUksR0FBRyxRQUFRLENBQUMsV0FBVyxFQUFHLENBQUM7UUFDbkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUM7UUFDM0UsSUFBSSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbkQsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2YsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2hDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNuQixDQUFDO0NBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIEp1bHkgMjgsIDIwMjMuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAyMywgRXNvdGVyaWMgU29mdHdhcmUgTExDXG4gKlxuICogSW50ZWdyYXRpb24gb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3Igb3RoZXJ3aXNlIGNyZWF0aW5nXG4gKiBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpcyBwZXJtaXR0ZWQgdW5kZXIgdGhlIHRlcm1zIGFuZFxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcbiAqIGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1lZGl0b3ItbGljZW5zZVxuICpcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvclxuICogb3RoZXJ3aXNlIGNyZWF0ZSBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyAoY29sbGVjdGl2ZWx5LFxuICogXCJQcm9kdWN0c1wiKSwgcHJvdmlkZWQgdGhhdCBlYWNoIHVzZXIgb2YgdGhlIFByb2R1Y3RzIG11c3Qgb2J0YWluIHRoZWlyIG93blxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XG4gKiBpbmNsdWRlIHRoaXMgbGljZW5zZSBhbmQgY29weXJpZ2h0IG5vdGljZS5cbiAqXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMgQVJFIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZXG4gKiBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTLFxuICogQlVTSU5FU1MgSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EXG4gKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRIRVxuICogU1BJTkUgUlVOVElNRVMsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB7IFNQSU5FX0dBTUVfT0JKRUNUX1RZUEUgfSBmcm9tIFwiLi9rZXlzLmpzXCI7XG5pbXBvcnQgeyBTcGluZVBsdWdpbiB9IGZyb20gXCIuL1NwaW5lUGx1Z2luLmpzXCI7XG5pbXBvcnQge1xuXHRDb21wdXRlZFNpemVNaXhpbixcblx0RGVwdGhNaXhpbixcblx0RmxpcE1peGluLFxuXHRTY3JvbGxGYWN0b3JNaXhpbixcblx0VHJhbnNmb3JtTWl4aW4sXG5cdFZpc2libGVNaXhpbixcblx0QWxwaGFNaXhpbixcblx0T3JpZ2luTWl4aW4sXG59IGZyb20gXCIuL21peGlucy5qc1wiO1xuaW1wb3J0IHtcblx0QW5pbWF0aW9uU3RhdGUsXG5cdEFuaW1hdGlvblN0YXRlRGF0YSxcblx0Qm9uZSxcblx0TWF0aFV0aWxzLFxuXHRQaHlzaWNzLFxuXHRTa2VsZXRvbixcblx0U2tlbGV0b25DbGlwcGluZyxcblx0U2tpbixcblx0VmVjdG9yMixcbn0gZnJvbSBcIkBlc290ZXJpY3NvZnR3YXJlL3NwaW5lLWNvcmVcIjtcblxuY2xhc3MgQmFzZVNwaW5lR2FtZU9iamVjdCBleHRlbmRzIFBoYXNlci5HYW1lT2JqZWN0cy5HYW1lT2JqZWN0IHtcblx0Y29uc3RydWN0b3IgKHNjZW5lOiBQaGFzZXIuU2NlbmUsIHR5cGU6IHN0cmluZykge1xuXHRcdHN1cGVyKHNjZW5lLCB0eXBlKTtcblx0fVxufVxuXG4vKiogQSBib3VuZHMgcHJvdmlkZXIgY2FsY3VsYXRlcyB0aGUgYm91bmRpbmcgYm94IGZvciBhIHNrZWxldG9uLCB3aGljaCBpcyB0aGVuIGFzc2lnbmVkIGFzIHRoZSBzaXplIG9mIHRoZSBTcGluZUdhbWVPYmplY3QuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwaW5lR2FtZU9iamVjdEJvdW5kc1Byb3ZpZGVyIHtcblx0Ly8gUmV0dXJucyB0aGUgYm91bmRpbmcgYm94IGZvciB0aGUgc2tlbGV0b24sIGluIHNrZWxldG9uIHNwYWNlLlxuXHRjYWxjdWxhdGVCb3VuZHMgKGdhbWVPYmplY3Q6IFNwaW5lR2FtZU9iamVjdCk6IHtcblx0XHR4OiBudW1iZXI7XG5cdFx0eTogbnVtYmVyO1xuXHRcdHdpZHRoOiBudW1iZXI7XG5cdFx0aGVpZ2h0OiBudW1iZXI7XG5cdH07XG59XG5cbi8qKiBBIGJvdW5kcyBwcm92aWRlciB0aGF0IGNhbGN1bGF0ZXMgdGhlIGJvdW5kaW5nIGJveCBmcm9tIHRoZSBzZXR1cCBwb3NlLiAqL1xuZXhwb3J0IGNsYXNzIFNldHVwUG9zZUJvdW5kc1Byb3ZpZGVyIGltcGxlbWVudHMgU3BpbmVHYW1lT2JqZWN0Qm91bmRzUHJvdmlkZXIge1xuXHQvKipcblx0ICogQHBhcmFtIGNsaXBwaW5nIElmIHRydWUsIGNsaXBwaW5nIGF0dGFjaG1lbnRzIGFyZSB1c2VkIHRvIGNvbXB1dGUgdGhlIGJvdW5kcy4gRmFsc2UsIGJ5IGRlZmF1bHQuXG5cdCAqL1xuXHRjb25zdHJ1Y3RvciAoXG5cdFx0cHJpdmF0ZSBjbGlwcGluZyA9IGZhbHNlLFxuXHQpIHsgfVxuXG5cdGNhbGN1bGF0ZUJvdW5kcyAoZ2FtZU9iamVjdDogU3BpbmVHYW1lT2JqZWN0KSB7XG5cdFx0aWYgKCFnYW1lT2JqZWN0LnNrZWxldG9uKSByZXR1cm4geyB4OiAwLCB5OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH07XG5cdFx0Ly8gTWFrZSBhIGNvcHkgb2YgYW5pbWF0aW9uIHN0YXRlIGFuZCBza2VsZXRvbiBhcyB0aGlzIG1pZ2h0IGJlIGNhbGxlZCB3aGlsZVxuXHRcdC8vIHRoZSBza2VsZXRvbiBpbiB0aGUgR2FtZU9iamVjdCBoYXMgYWxyZWFkeSBiZWVuIGhlYXZpbHkgbW9kaWZpZWQuIFdlIGNhbiBub3Rcblx0XHQvLyByZWNvbnN0cnVjdCB0aGF0IHN0YXRlLlxuXHRcdGNvbnN0IHNrZWxldG9uID0gbmV3IFNrZWxldG9uKGdhbWVPYmplY3Quc2tlbGV0b24uZGF0YSk7XG5cdFx0c2tlbGV0b24uc2V0VG9TZXR1cFBvc2UoKTtcblx0XHRza2VsZXRvbi51cGRhdGVXb3JsZFRyYW5zZm9ybShQaHlzaWNzLnVwZGF0ZSk7XG5cdFx0Y29uc3QgYm91bmRzID0gc2tlbGV0b24uZ2V0Qm91bmRzUmVjdCh0aGlzLmNsaXBwaW5nID8gbmV3IFNrZWxldG9uQ2xpcHBpbmcoKSA6IHVuZGVmaW5lZCk7XG5cdFx0cmV0dXJuIGJvdW5kcy53aWR0aCA9PSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFlcblx0XHRcdD8geyB4OiAwLCB5OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH1cblx0XHRcdDogYm91bmRzO1xuXHR9XG59XG5cbi8qKiBBIGJvdW5kcyBwcm92aWRlciB0aGF0IGNhbGN1bGF0ZXMgdGhlIGJvdW5kaW5nIGJveCBieSB0YWtpbmcgdGhlIG1heGltdW1nIGJvdW5kaW5nIGJveCBmb3IgYSBjb21iaW5hdGlvbiBvZiBza2lucyBhbmQgc3BlY2lmaWMgYW5pbWF0aW9uLiAqL1xuZXhwb3J0IGNsYXNzIFNraW5zQW5kQW5pbWF0aW9uQm91bmRzUHJvdmlkZXJcblx0aW1wbGVtZW50cyBTcGluZUdhbWVPYmplY3RCb3VuZHNQcm92aWRlciB7XG5cdC8qKlxuXHQgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBhbmltYXRpb24gdG8gdXNlIGZvciBjYWxjdWxhdGluZyB0aGUgYm91bmRzLiBJZiBudWxsLCB0aGUgc2V0dXAgcG9zZSBpcyB1c2VkLlxuXHQgKiBAcGFyYW0gc2tpbnMgVGhlIHNraW5zIHRvIHVzZSBmb3IgY2FsY3VsYXRpbmcgdGhlIGJvdW5kcy4gSWYgZW1wdHksIHRoZSBkZWZhdWx0IHNraW4gaXMgdXNlZC5cblx0ICogQHBhcmFtIHRpbWVTdGVwIFRoZSB0aW1lIHN0ZXAgdG8gdXNlIGZvciBjYWxjdWxhdGluZyB0aGUgYm91bmRzLiBBIHNtYWxsZXIgdGltZSBzdGVwIG1lYW5zIG1vcmUgcHJlY2lzaW9uLCBidXQgc2xvd2VyIGNhbGN1bGF0aW9uLlxuXHQgKiBAcGFyYW0gY2xpcHBpbmcgSWYgdHJ1ZSwgY2xpcHBpbmcgYXR0YWNobWVudHMgYXJlIHVzZWQgdG8gY29tcHV0ZSB0aGUgYm91bmRzLiBGYWxzZSwgYnkgZGVmYXVsdC5cblx0ICovXG5cdGNvbnN0cnVjdG9yIChcblx0XHRwcml2YXRlIGFuaW1hdGlvbjogc3RyaW5nIHwgbnVsbCxcblx0XHRwcml2YXRlIHNraW5zOiBzdHJpbmdbXSA9IFtdLFxuXHRcdHByaXZhdGUgdGltZVN0ZXA6IG51bWJlciA9IDAuMDUsXG5cdFx0cHJpdmF0ZSBjbGlwcGluZyA9IGZhbHNlLFxuXHQpIHsgfVxuXG5cdGNhbGN1bGF0ZUJvdW5kcyAoZ2FtZU9iamVjdDogU3BpbmVHYW1lT2JqZWN0KToge1xuXHRcdHg6IG51bWJlcjtcblx0XHR5OiBudW1iZXI7XG5cdFx0d2lkdGg6IG51bWJlcjtcblx0XHRoZWlnaHQ6IG51bWJlcjtcblx0fSB7XG5cdFx0aWYgKCFnYW1lT2JqZWN0LnNrZWxldG9uIHx8ICFnYW1lT2JqZWN0LmFuaW1hdGlvblN0YXRlKVxuXHRcdFx0cmV0dXJuIHsgeDogMCwgeTogMCwgd2lkdGg6IDAsIGhlaWdodDogMCB9O1xuXHRcdC8vIE1ha2UgYSBjb3B5IG9mIGFuaW1hdGlvbiBzdGF0ZSBhbmQgc2tlbGV0b24gYXMgdGhpcyBtaWdodCBiZSBjYWxsZWQgd2hpbGVcblx0XHQvLyB0aGUgc2tlbGV0b24gaW4gdGhlIEdhbWVPYmplY3QgaGFzIGFscmVhZHkgYmVlbiBoZWF2aWx5IG1vZGlmaWVkLiBXZSBjYW4gbm90XG5cdFx0Ly8gcmVjb25zdHJ1Y3QgdGhhdCBzdGF0ZS5cblx0XHRjb25zdCBhbmltYXRpb25TdGF0ZSA9IG5ldyBBbmltYXRpb25TdGF0ZShnYW1lT2JqZWN0LmFuaW1hdGlvblN0YXRlLmRhdGEpO1xuXHRcdGNvbnN0IHNrZWxldG9uID0gbmV3IFNrZWxldG9uKGdhbWVPYmplY3Quc2tlbGV0b24uZGF0YSk7XG5cdFx0Y29uc3QgY2xpcHBlciA9IHRoaXMuY2xpcHBpbmcgPyBuZXcgU2tlbGV0b25DbGlwcGluZygpIDogdW5kZWZpbmVkO1xuXHRcdGNvbnN0IGRhdGEgPSBza2VsZXRvbi5kYXRhO1xuXHRcdGlmICh0aGlzLnNraW5zLmxlbmd0aCA+IDApIHtcblx0XHRcdGxldCBjdXN0b21Ta2luID0gbmV3IFNraW4oXCJjdXN0b20tc2tpblwiKTtcblx0XHRcdGZvciAoY29uc3Qgc2tpbk5hbWUgb2YgdGhpcy5za2lucykge1xuXHRcdFx0XHRjb25zdCBza2luID0gZGF0YS5maW5kU2tpbihza2luTmFtZSk7XG5cdFx0XHRcdGlmIChza2luID09IG51bGwpIGNvbnRpbnVlO1xuXHRcdFx0XHRjdXN0b21Ta2luLmFkZFNraW4oc2tpbik7XG5cdFx0XHR9XG5cdFx0XHRza2VsZXRvbi5zZXRTa2luKGN1c3RvbVNraW4pO1xuXHRcdH1cblx0XHRza2VsZXRvbi5zZXRUb1NldHVwUG9zZSgpO1xuXG5cdFx0Y29uc3QgYW5pbWF0aW9uID1cblx0XHRcdHRoaXMuYW5pbWF0aW9uICE9IG51bGwgPyBkYXRhLmZpbmRBbmltYXRpb24odGhpcy5hbmltYXRpb24hKSA6IG51bGw7XG5cdFx0aWYgKGFuaW1hdGlvbiA9PSBudWxsKSB7XG5cdFx0XHRza2VsZXRvbi51cGRhdGVXb3JsZFRyYW5zZm9ybShQaHlzaWNzLnVwZGF0ZSk7XG5cdFx0XHRjb25zdCBib3VuZHMgPSBza2VsZXRvbi5nZXRCb3VuZHNSZWN0KGNsaXBwZXIpO1xuXHRcdFx0cmV0dXJuIGJvdW5kcy53aWR0aCA9PSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFlcblx0XHRcdFx0PyB7IHg6IDAsIHk6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfVxuXHRcdFx0XHQ6IGJvdW5kcztcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IG1pblggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXG5cdFx0XHRcdG1pblkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXG5cdFx0XHRcdG1heFggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksXG5cdFx0XHRcdG1heFkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XG5cdFx0XHRhbmltYXRpb25TdGF0ZS5jbGVhclRyYWNrcygpO1xuXHRcdFx0YW5pbWF0aW9uU3RhdGUuc2V0QW5pbWF0aW9uV2l0aCgwLCBhbmltYXRpb24sIGZhbHNlKTtcblx0XHRcdGNvbnN0IHN0ZXBzID0gTWF0aC5tYXgoYW5pbWF0aW9uLmR1cmF0aW9uIC8gdGhpcy50aW1lU3RlcCwgMS4wKTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgc3RlcHM7IGkrKykge1xuXHRcdFx0XHRjb25zdCBkZWx0YSA9IGkgPiAwID8gdGhpcy50aW1lU3RlcCA6IDA7XG5cdFx0XHRcdGFuaW1hdGlvblN0YXRlLnVwZGF0ZShkZWx0YSk7XG5cdFx0XHRcdGFuaW1hdGlvblN0YXRlLmFwcGx5KHNrZWxldG9uKTtcblx0XHRcdFx0c2tlbGV0b24udXBkYXRlKGRlbHRhKTtcblx0XHRcdFx0c2tlbGV0b24udXBkYXRlV29ybGRUcmFuc2Zvcm0oUGh5c2ljcy51cGRhdGUpO1xuXG5cdFx0XHRcdGNvbnN0IGJvdW5kcyA9IHNrZWxldG9uLmdldEJvdW5kc1JlY3QoY2xpcHBlcik7XG5cdFx0XHRcdG1pblggPSBNYXRoLm1pbihtaW5YLCBib3VuZHMueCk7XG5cdFx0XHRcdG1pblkgPSBNYXRoLm1pbihtaW5ZLCBib3VuZHMueSk7XG5cdFx0XHRcdG1heFggPSBNYXRoLm1heChtYXhYLCBib3VuZHMueCArIGJvdW5kcy53aWR0aCk7XG5cdFx0XHRcdG1heFkgPSBNYXRoLm1heChtYXhZLCBib3VuZHMueSArIGJvdW5kcy5oZWlnaHQpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgYm91bmRzID0ge1xuXHRcdFx0XHR4OiBtaW5YLFxuXHRcdFx0XHR5OiBtaW5ZLFxuXHRcdFx0XHR3aWR0aDogbWF4WCAtIG1pblgsXG5cdFx0XHRcdGhlaWdodDogbWF4WSAtIG1pblksXG5cdFx0XHR9O1xuXHRcdFx0cmV0dXJuIGJvdW5kcy53aWR0aCA9PSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFlcblx0XHRcdFx0PyB7IHg6IDAsIHk6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfVxuXHRcdFx0XHQ6IGJvdW5kcztcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBBIFNwaW5lR2FtZU9iamVjdCBpcyBhIFBoYXNlciB7QGxpbmsgR2FtZU9iamVjdH0gdGhhdCBjYW4gYmUgYWRkZWQgdG8gYSBQaGFzZXIgU2NlbmUgYW5kIHJlbmRlciBhIFNwaW5lIHNrZWxldG9uLlxuICpcbiAqIFRoZSBTcGluZSBHYW1lT2JqZWN0IGlzIGEgdGhpbiB3cmFwcGVyIGFyb3VuZCBhIFNwaW5lIHtAbGluayBTa2VsZXRvbn0sIHtAbGluayBBbmltYXRpb25TdGF0ZX0gYW5kIHtAbGluayBBbmltYXRpb25TdGF0ZURhdGF9LiBJdCBpcyByZXNwb25zaWJsZSBmb3I6XG4gKiAtIHVwZGF0aW5nIHRoZSBhbmltYXRpb24gc3RhdGVcbiAqIC0gYXBwbHlpbmcgdGhlIGFuaW1hdGlvbiBzdGF0ZSB0byB0aGUgc2tlbGV0b24ncyBib25lcywgc2xvdHMsIGF0dGFjaG1lbnRzLCBhbmQgZHJhdyBvcmRlci5cbiAqIC0gdXBkYXRpbmcgdGhlIHNrZWxldG9uJ3MgYm9uZSB3b3JsZCB0cmFuc2Zvcm1zXG4gKiAtIHJlbmRlcmluZyB0aGUgc2tlbGV0b25cbiAqXG4gKiBTZWUgdGhlIHtAbGluayBTcGluZVBsdWdpbn0gY2xhc3MgZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gaG93IHRvIGNyZWF0ZSBhIGBTcGluZUdhbWVPYmplY3RgLlxuICpcbiAqIFRoZSBza2VsZXRvbiwgYW5pbWF0aW9uIHN0YXRlLCBhbmQgYW5pbWF0aW9uIHN0YXRlIGRhdGEgY2FuIGJlIGFjY2Vzc2VkIHZpYSB0aGUgcmVwc2VjdGl2ZSBmaWVsZHMuIFRoZXkgY2FuIGJlIG1hbnVhbGx5IHVwZGF0ZWQgdmlhIHtAbGluayB1cGRhdGVQb3NlfS5cbiAqXG4gKiBUbyBtb2RpZnkgdGhlIGJvbmUgaGllcmFyY2h5IGJlZm9yZSB0aGUgd29ybGQgdHJhbnNmb3JtcyBhcmUgY29tcHV0ZWQsIGEgY2FsbGJhY2sgY2FuIGJlIHNldCB2aWEgdGhlIHtAbGluayBiZWZvcmVVcGRhdGVXb3JsZFRyYW5zZm9ybXN9IGZpZWxkLlxuICpcbiAqIFRvIG1vZGlmeSB0aGUgYm9uZSBoaWVyYXJjaHkgYWZ0ZXIgdGhlIHdvcmxkIHRyYW5zZm9ybXMgYXJlIGNvbXB1dGVkLCBhIGNhbGxiYWNrIGNhbiBiZSBzZXQgdmlhIHRoZSB7QGxpbmsgYWZ0ZXJVcGRhdGVXb3JsZFRyYW5zZm9ybXN9IGZpZWxkLlxuICpcbiAqIFRoZSBjbGFzcyBhbHNvIGZlYXR1cmVzIG1ldGhvZHMgdG8gY29udmVydCBiZXR3ZWVuIHRoZSBza2VsZXRvbiBjb29yZGluYXRlIHN5c3RlbSBhbmQgdGhlIFBoYXNlciBjb29yZGluYXRlIHN5c3RlbS5cbiAqXG4gKiBTZWUge0BsaW5rIHNrZWxldG9uVG9QaGFzZXJXb3JsZENvb3JkaW5hdGVzfSwge0BsaW5rIHBoYXNlcldvcmxkQ29vcmRpbmF0ZXNUb1NrZWxldG9ufSwgYW5kIHtAbGluayBwaGFzZXJXb3JsZENvb3JkaW5hdGVzVG9Cb25lTG9jYWwufVxuICovXG5leHBvcnQgY2xhc3MgU3BpbmVHYW1lT2JqZWN0IGV4dGVuZHMgRGVwdGhNaXhpbihcblx0T3JpZ2luTWl4aW4oXG5cdFx0Q29tcHV0ZWRTaXplTWl4aW4oXG5cdFx0XHRGbGlwTWl4aW4oXG5cdFx0XHRcdFNjcm9sbEZhY3Rvck1peGluKFxuXHRcdFx0XHRcdFRyYW5zZm9ybU1peGluKFZpc2libGVNaXhpbihBbHBoYU1peGluKEJhc2VTcGluZUdhbWVPYmplY3QpKSlcblx0XHRcdFx0KVxuXHRcdFx0KVxuXHRcdClcblx0KVxuKSB7XG5cdGJsZW5kTW9kZSA9IC0xO1xuXHRza2VsZXRvbjogU2tlbGV0b247XG5cdGFuaW1hdGlvblN0YXRlRGF0YTogQW5pbWF0aW9uU3RhdGVEYXRhO1xuXHRhbmltYXRpb25TdGF0ZTogQW5pbWF0aW9uU3RhdGU7XG5cdGJlZm9yZVVwZGF0ZVdvcmxkVHJhbnNmb3JtczogKG9iamVjdDogU3BpbmVHYW1lT2JqZWN0KSA9PiB2b2lkID0gKCkgPT4geyB9O1xuXHRhZnRlclVwZGF0ZVdvcmxkVHJhbnNmb3JtczogKG9iamVjdDogU3BpbmVHYW1lT2JqZWN0KSA9PiB2b2lkID0gKCkgPT4geyB9O1xuXHRwcml2YXRlIHByZW11bHRpcGxpZWRBbHBoYSA9IGZhbHNlO1xuXG5cdGNvbnN0cnVjdG9yIChcblx0XHRzY2VuZTogUGhhc2VyLlNjZW5lLFxuXHRcdHByaXZhdGUgcGx1Z2luOiBTcGluZVBsdWdpbixcblx0XHR4OiBudW1iZXIsXG5cdFx0eTogbnVtYmVyLFxuXHRcdGRhdGFLZXk6IHN0cmluZyxcblx0XHRhdGxhc0tleTogc3RyaW5nLFxuXHRcdHB1YmxpYyBib3VuZHNQcm92aWRlcjogU3BpbmVHYW1lT2JqZWN0Qm91bmRzUHJvdmlkZXIgPSBuZXcgU2V0dXBQb3NlQm91bmRzUHJvdmlkZXIoKVxuXHQpIHtcblx0XHRzdXBlcihzY2VuZSwgKHdpbmRvdyBhcyBhbnkpLlNQSU5FX0dBTUVfT0JKRUNUX1RZUEUgPyAod2luZG93IGFzIGFueSkuU1BJTkVfR0FNRV9PQkpFQ1RfVFlQRSA6IFNQSU5FX0dBTUVfT0JKRUNUX1RZUEUpO1xuXHRcdHRoaXMuc2V0UG9zaXRpb24oeCwgeSk7XG5cblx0XHR0aGlzLnByZW11bHRpcGxpZWRBbHBoYSA9IHRoaXMucGx1Z2luLmlzQXRsYXNQcmVtdWx0aXBsaWVkKGF0bGFzS2V5KTtcblx0XHR0aGlzLnNrZWxldG9uID0gdGhpcy5wbHVnaW4uY3JlYXRlU2tlbGV0b24oZGF0YUtleSwgYXRsYXNLZXkpO1xuXHRcdHRoaXMuYW5pbWF0aW9uU3RhdGVEYXRhID0gbmV3IEFuaW1hdGlvblN0YXRlRGF0YSh0aGlzLnNrZWxldG9uLmRhdGEpO1xuXHRcdHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBuZXcgQW5pbWF0aW9uU3RhdGUodGhpcy5hbmltYXRpb25TdGF0ZURhdGEpO1xuXHRcdHRoaXMuc2tlbGV0b24udXBkYXRlV29ybGRUcmFuc2Zvcm0oUGh5c2ljcy51cGRhdGUpO1xuXHRcdHRoaXMudXBkYXRlU2l6ZSgpO1xuXHR9XG5cblx0dXBkYXRlU2l6ZSAoKSB7XG5cdFx0aWYgKCF0aGlzLnNrZWxldG9uKSByZXR1cm47XG5cdFx0bGV0IGJvdW5kcyA9IHRoaXMuYm91bmRzUHJvdmlkZXIuY2FsY3VsYXRlQm91bmRzKHRoaXMpO1xuXHRcdC8vIEZvciBzb21lIHJlYXNvbiB0aGUgVFMgY29tcGlsZXIgYW5kIHRoZSBDb21wdXRlZFNpemUgbWl4aW4gZG9uJ3Qgd29yayB3ZWxsIHRvZ2V0aGVyIGFuZCB3ZSBoYXZlXG5cdFx0Ly8gdG8gY2FzdCB0byBhbnkuXG5cdFx0bGV0IHNlbGYgPSB0aGlzIGFzIGFueTtcblx0XHRzZWxmLndpZHRoID0gYm91bmRzLndpZHRoO1xuXHRcdHNlbGYuaGVpZ2h0ID0gYm91bmRzLmhlaWdodDtcblx0XHR0aGlzLmRpc3BsYXlPcmlnaW5YID0gLWJvdW5kcy54O1xuXHRcdHRoaXMuZGlzcGxheU9yaWdpblkgPSAtYm91bmRzLnk7XG5cdH1cblxuXHQvKiogQ29udmVydHMgYSBwb2ludCBmcm9tIHRoZSBza2VsZXRvbiBjb29yZGluYXRlIHN5c3RlbSB0byB0aGUgUGhhc2VyIHdvcmxkIGNvb3JkaW5hdGUgc3lzdGVtLiAqL1xuXHRza2VsZXRvblRvUGhhc2VyV29ybGRDb29yZGluYXRlcyAocG9pbnQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSkge1xuXHRcdGxldCB0cmFuc2Zvcm0gPSB0aGlzLmdldFdvcmxkVHJhbnNmb3JtTWF0cml4KCk7XG5cdFx0bGV0IGEgPSB0cmFuc2Zvcm0uYSxcblx0XHRcdGIgPSB0cmFuc2Zvcm0uYixcblx0XHRcdGMgPSB0cmFuc2Zvcm0uYyxcblx0XHRcdGQgPSB0cmFuc2Zvcm0uZCxcblx0XHRcdHR4ID0gdHJhbnNmb3JtLnR4LFxuXHRcdFx0dHkgPSB0cmFuc2Zvcm0udHk7XG5cdFx0bGV0IHggPSBwb2ludC54O1xuXHRcdGxldCB5ID0gcG9pbnQueTtcblx0XHRwb2ludC54ID0geCAqIGEgKyB5ICogYyArIHR4O1xuXHRcdHBvaW50LnkgPSB4ICogYiArIHkgKiBkICsgdHk7XG5cdH1cblxuXHQvKiogQ29udmVydHMgYSBwb2ludCBmcm9tIHRoZSBQaGFzZXIgd29ybGQgY29vcmRpbmF0ZSBzeXN0ZW0gdG8gdGhlIHNrZWxldG9uIGNvb3JkaW5hdGUgc3lzdGVtLiAqL1xuXHRwaGFzZXJXb3JsZENvb3JkaW5hdGVzVG9Ta2VsZXRvbiAocG9pbnQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSkge1xuXHRcdGxldCB0cmFuc2Zvcm0gPSB0aGlzLmdldFdvcmxkVHJhbnNmb3JtTWF0cml4KCk7XG5cdFx0dHJhbnNmb3JtID0gdHJhbnNmb3JtLmludmVydCgpO1xuXHRcdGxldCBhID0gdHJhbnNmb3JtLmEsXG5cdFx0XHRiID0gdHJhbnNmb3JtLmIsXG5cdFx0XHRjID0gdHJhbnNmb3JtLmMsXG5cdFx0XHRkID0gdHJhbnNmb3JtLmQsXG5cdFx0XHR0eCA9IHRyYW5zZm9ybS50eCxcblx0XHRcdHR5ID0gdHJhbnNmb3JtLnR5O1xuXHRcdGxldCB4ID0gcG9pbnQueDtcblx0XHRsZXQgeSA9IHBvaW50Lnk7XG5cdFx0cG9pbnQueCA9IHggKiBhICsgeSAqIGMgKyB0eDtcblx0XHRwb2ludC55ID0geCAqIGIgKyB5ICogZCArIHR5O1xuXHR9XG5cblx0LyoqIENvbnZlcnRzIGEgcG9pbnQgZnJvbSB0aGUgUGhhc2VyIHdvcmxkIGNvb3JkaW5hdGUgc3lzdGVtIHRvIHRoZSBib25lJ3MgbG9jYWwgY29vcmRpbmF0ZSBzeXN0ZW0uICovXG5cdHBoYXNlcldvcmxkQ29vcmRpbmF0ZXNUb0JvbmUgKHBvaW50OiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0sIGJvbmU6IEJvbmUpIHtcblx0XHR0aGlzLnBoYXNlcldvcmxkQ29vcmRpbmF0ZXNUb1NrZWxldG9uKHBvaW50KTtcblx0XHRpZiAoYm9uZS5wYXJlbnQpIHtcblx0XHRcdGJvbmUucGFyZW50LndvcmxkVG9Mb2NhbChwb2ludCBhcyBWZWN0b3IyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ym9uZS53b3JsZFRvTG9jYWwocG9pbnQgYXMgVmVjdG9yMik7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgdGhlIHtAbGluayBBbmltYXRpb25TdGF0ZX0sIGFwcGxpZXMgaXQgdG8gdGhlIHtAbGluayBTa2VsZXRvbn0sIHRoZW4gdXBkYXRlcyB0aGUgd29ybGQgdHJhbnNmb3JtcyBvZiBhbGwgYm9uZXMuXG5cdCAqIEBwYXJhbSBkZWx0YSBUaGUgdGltZSBkZWx0YSBpbiBtaWxsaXNlY29uZHNcblx0ICovXG5cdHVwZGF0ZVBvc2UgKGRlbHRhOiBudW1iZXIpIHtcblx0XHR0aGlzLmFuaW1hdGlvblN0YXRlLnVwZGF0ZShkZWx0YSAvIDEwMDApO1xuXHRcdHRoaXMuYW5pbWF0aW9uU3RhdGUuYXBwbHkodGhpcy5za2VsZXRvbik7XG5cdFx0dGhpcy5iZWZvcmVVcGRhdGVXb3JsZFRyYW5zZm9ybXModGhpcyk7XG5cdFx0dGhpcy5za2VsZXRvbi51cGRhdGUoZGVsdGEgLyAxMDAwKTtcblx0XHR0aGlzLnNrZWxldG9uLnVwZGF0ZVdvcmxkVHJhbnNmb3JtKFBoeXNpY3MudXBkYXRlKTtcblx0XHR0aGlzLmFmdGVyVXBkYXRlV29ybGRUcmFuc2Zvcm1zKHRoaXMpO1xuXHR9XG5cblx0cHJlVXBkYXRlICh0aW1lOiBudW1iZXIsIGRlbHRhOiBudW1iZXIpIHtcblx0XHRpZiAoIXRoaXMuc2tlbGV0b24gfHwgIXRoaXMuYW5pbWF0aW9uU3RhdGUpIHJldHVybjtcblx0XHR0aGlzLnVwZGF0ZVBvc2UoZGVsdGEpO1xuXHR9XG5cblx0cHJlRGVzdHJveSAoKSB7XG5cdFx0Ly8gRklYTUUgdGVhciBkb3duIGFueSBldmVudCBlbWl0dGVyc1xuXHR9XG5cblx0d2lsbFJlbmRlciAoY2FtZXJhOiBQaGFzZXIuQ2FtZXJhcy5TY2VuZTJELkNhbWVyYSkge1xuXHRcdHZhciBHYW1lT2JqZWN0UmVuZGVyTWFzayA9IDB4Zjtcblx0XHR2YXIgcmVzdWx0ID0gIXRoaXMuc2tlbGV0b24gfHwgIShHYW1lT2JqZWN0UmVuZGVyTWFzayAhPT0gdGhpcy5yZW5kZXJGbGFncyB8fCAodGhpcy5jYW1lcmFGaWx0ZXIgIT09IDAgJiYgdGhpcy5jYW1lcmFGaWx0ZXIgJiBjYW1lcmEuaWQpKTtcblx0XHRpZiAoIXRoaXMudmlzaWJsZSkgcmVzdWx0ID0gZmFsc2U7XG5cblx0XHRpZiAoIXJlc3VsdCAmJiB0aGlzLnBhcmVudENvbnRhaW5lciAmJiB0aGlzLnBsdWdpbi53ZWJHTFJlbmRlcmVyKSB7XG5cdFx0XHR2YXIgc2NlbmVSZW5kZXJlciA9IHRoaXMucGx1Z2luLndlYkdMUmVuZGVyZXI7XG5cblx0XHRcdGlmICh0aGlzLnBsdWdpbi5nbCAmJiB0aGlzLnBsdWdpbi5waGFzZXJSZW5kZXJlciBpbnN0YW5jZW9mIFBoYXNlci5SZW5kZXJlci5XZWJHTC5XZWJHTFJlbmRlcmVyICYmIHNjZW5lUmVuZGVyZXIuYmF0Y2hlci5pc0RyYXdpbmcpIHtcblx0XHRcdFx0c2NlbmVSZW5kZXJlci5lbmQoKTtcblx0XHRcdFx0dGhpcy5wbHVnaW4ucGhhc2VyUmVuZGVyZXIucGlwZWxpbmVzLnJlYmluZCgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHRyZW5kZXJXZWJHTCAoXG5cdFx0cmVuZGVyZXI6IFBoYXNlci5SZW5kZXJlci5XZWJHTC5XZWJHTFJlbmRlcmVyLFxuXHRcdHNyYzogU3BpbmVHYW1lT2JqZWN0LFxuXHRcdGNhbWVyYTogUGhhc2VyLkNhbWVyYXMuU2NlbmUyRC5DYW1lcmEsXG5cdFx0cGFyZW50TWF0cml4OiBQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cy5UcmFuc2Zvcm1NYXRyaXhcblx0KSB7XG5cdFx0aWYgKCF0aGlzLnNrZWxldG9uIHx8ICF0aGlzLmFuaW1hdGlvblN0YXRlIHx8ICF0aGlzLnBsdWdpbi53ZWJHTFJlbmRlcmVyKVxuXHRcdFx0cmV0dXJuO1xuXG5cdFx0bGV0IHNjZW5lUmVuZGVyZXIgPSB0aGlzLnBsdWdpbi53ZWJHTFJlbmRlcmVyO1xuXHRcdGlmIChyZW5kZXJlci5uZXdUeXBlKSB7XG5cdFx0XHRyZW5kZXJlci5waXBlbGluZXMuY2xlYXIoKTtcblx0XHRcdHNjZW5lUmVuZGVyZXIuYmVnaW4oKTtcblx0XHR9XG5cblx0XHRjYW1lcmEuYWRkVG9SZW5kZXJMaXN0KHNyYyk7XG5cdFx0bGV0IHRyYW5zZm9ybSA9IFBoYXNlci5HYW1lT2JqZWN0cy5HZXRDYWxjTWF0cml4KFxuXHRcdFx0c3JjLFxuXHRcdFx0Y2FtZXJhLFxuXHRcdFx0cGFyZW50TWF0cml4XG5cdFx0KS5jYWxjO1xuXHRcdGxldCBhID0gdHJhbnNmb3JtLmEsXG5cdFx0XHRiID0gdHJhbnNmb3JtLmIsXG5cdFx0XHRjID0gdHJhbnNmb3JtLmMsXG5cdFx0XHRkID0gdHJhbnNmb3JtLmQsXG5cdFx0XHR0eCA9IHRyYW5zZm9ybS50eCxcblx0XHRcdHR5ID0gdHJhbnNmb3JtLnR5O1xuXHRcdHNjZW5lUmVuZGVyZXIuZHJhd1NrZWxldG9uKFxuXHRcdFx0dGhpcy5za2VsZXRvbixcblx0XHRcdHRoaXMucHJlbXVsdGlwbGllZEFscGhhLFxuXHRcdFx0LTEsXG5cdFx0XHQtMSxcblx0XHRcdCh2ZXJ0aWNlcywgbnVtVmVydGljZXMsIHN0cmlkZSkgPT4ge1xuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IG51bVZlcnRpY2VzOyBpICs9IHN0cmlkZSkge1xuXHRcdFx0XHRcdGxldCB2eCA9IHZlcnRpY2VzW2ldO1xuXHRcdFx0XHRcdGxldCB2eSA9IHZlcnRpY2VzW2kgKyAxXTtcblx0XHRcdFx0XHR2ZXJ0aWNlc1tpXSA9IHZ4ICogYSArIHZ5ICogYyArIHR4O1xuXHRcdFx0XHRcdHZlcnRpY2VzW2kgKyAxXSA9IHZ4ICogYiArIHZ5ICogZCArIHR5O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0KTtcblxuXHRcdGlmICghcmVuZGVyZXIubmV4dFR5cGVNYXRjaCkge1xuXHRcdFx0c2NlbmVSZW5kZXJlci5lbmQoKTtcblx0XHRcdHJlbmRlcmVyLnBpcGVsaW5lcy5yZWJpbmQoKTtcblx0XHR9XG5cdH1cblxuXHRyZW5kZXJDYW52YXMgKFxuXHRcdHJlbmRlcmVyOiBQaGFzZXIuUmVuZGVyZXIuQ2FudmFzLkNhbnZhc1JlbmRlcmVyLFxuXHRcdHNyYzogU3BpbmVHYW1lT2JqZWN0LFxuXHRcdGNhbWVyYTogUGhhc2VyLkNhbWVyYXMuU2NlbmUyRC5DYW1lcmEsXG5cdFx0cGFyZW50TWF0cml4OiBQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cy5UcmFuc2Zvcm1NYXRyaXhcblx0KSB7XG5cdFx0aWYgKCF0aGlzLnNrZWxldG9uIHx8ICF0aGlzLmFuaW1hdGlvblN0YXRlIHx8ICF0aGlzLnBsdWdpbi5jYW52YXNSZW5kZXJlcilcblx0XHRcdHJldHVybjtcblxuXHRcdGxldCBjb250ZXh0ID0gcmVuZGVyZXIuY3VycmVudENvbnRleHQ7XG5cdFx0bGV0IHNrZWxldG9uUmVuZGVyZXIgPSB0aGlzLnBsdWdpbi5jYW52YXNSZW5kZXJlcjtcblx0XHQoc2tlbGV0b25SZW5kZXJlciBhcyBhbnkpLmN0eCA9IGNvbnRleHQ7XG5cblx0XHRjYW1lcmEuYWRkVG9SZW5kZXJMaXN0KHNyYyk7XG5cdFx0bGV0IHRyYW5zZm9ybSA9IFBoYXNlci5HYW1lT2JqZWN0cy5HZXRDYWxjTWF0cml4KFxuXHRcdFx0c3JjLFxuXHRcdFx0Y2FtZXJhLFxuXHRcdFx0cGFyZW50TWF0cml4XG5cdFx0KS5jYWxjO1xuXHRcdGxldCBza2VsZXRvbiA9IHRoaXMuc2tlbGV0b247XG5cdFx0c2tlbGV0b24ueCA9IHRyYW5zZm9ybS50eDtcblx0XHRza2VsZXRvbi55ID0gdHJhbnNmb3JtLnR5O1xuXHRcdHNrZWxldG9uLnNjYWxlWCA9IHRyYW5zZm9ybS5zY2FsZVg7XG5cdFx0c2tlbGV0b24uc2NhbGVZID0gdHJhbnNmb3JtLnNjYWxlWTtcblx0XHRsZXQgcm9vdCA9IHNrZWxldG9uLmdldFJvb3RCb25lKCkhO1xuXHRcdHJvb3Qucm90YXRpb24gPSAtTWF0aFV0aWxzLnJhZGlhbnNUb0RlZ3JlZXMgKiB0cmFuc2Zvcm0ucm90YXRpb25Ob3JtYWxpemVkO1xuXHRcdHRoaXMuc2tlbGV0b24udXBkYXRlV29ybGRUcmFuc2Zvcm0oUGh5c2ljcy51cGRhdGUpO1xuXG5cdFx0Y29udGV4dC5zYXZlKCk7XG5cdFx0c2tlbGV0b25SZW5kZXJlci5kcmF3KHNrZWxldG9uKTtcblx0XHRjb250ZXh0LnJlc3RvcmUoKTtcblx0fVxufVxuIl19 \ No newline at end of file diff --git a/spine-ts/spine-phaser-v3/dist/SpinePlugin.d.ts b/spine-ts/spine-phaser-v3/dist/SpinePlugin.d.ts new file mode 100644 index 000000000..2fff8afd1 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/SpinePlugin.d.ts @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +import * as Phaser from "phaser"; +import { SceneRenderer, Skeleton, SkeletonData, TextureAtlas } from "@esotericsoftware/spine-webgl"; +import { SpineGameObjectBoundsProvider } from "./SpineGameObject.js"; +import { SkeletonRenderer } from "@esotericsoftware/spine-canvas"; +/** + * Configuration object used when creating {@link SpineGameObject} instances via a scene's + * {@link GameObjectCreator} (`Scene.make`). + */ +export interface SpineGameObjectConfig extends Phaser.Types.GameObjects.GameObjectConfig { + /** The x-position of the object, optional, default: 0 */ + x?: number; + /** The y-position of the object, optional, default: 0 */ + y?: number; + /** The skeleton data key */ + dataKey: string; + /** The atlas key */ + atlasKey: string; + /** The bounds provider, optional, default: `SetupPoseBoundsProvider` */ + boundsProvider?: SpineGameObjectBoundsProvider; +} +/** + * {@link ScenePlugin} implementation adding Spine Runtime capabilities to a scene. + * + * The scene's {@link LoaderPlugin} (`Scene.load`) gets these additional functions: + * * `spineBinary(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`. + * * `spineJson(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`. + * * `spineAtlas(key: string, url: string, premultipliedAlpha: boolean = true, xhrSettings?: XHRSettingsObject)`: loads a texture atlas `.atlas` file from the `url` as well as its correponding texture atlas page images. + * + * The scene's {@link GameObjectFactory} (`Scene.add`) gets these additional functions: + * * `spine(x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider = SetupPoseBoundsProvider())`: + * creates a new {@link SpineGameObject} from the data and atlas at position `(x, y)`, using the {@link BoundsProvider} to calculate its bounding box. The object is automatically added to the scene. + * + * The scene's {@link GameObjectCreator} (`Scene.make`) gets these additional functions: + * * `spine(config: SpineGameObjectConfig)`: creates a new {@link SpineGameObject} from the given configuration object. + * + * The plugin has additional public methods to work with Spine Runtime core API objects: + * * `getAtlas(atlasKey: string)`: returns the {@link TextureAtlas} instance for the given atlas key. + * * `getSkeletonData(skeletonDataKey: string)`: returns the {@link SkeletonData} instance for the given skeleton data key. + * * `createSkeleton(skeletonDataKey: string, atlasKey: string, premultipliedAlpha: boolean = true)`: creates a new {@link Skeleton} instance from the given skeleton data and atlas key. + * * `isPremultipliedAlpha(atlasKey: string)`: returns `true` if the atlas with the given key has premultiplied alpha. + */ +export declare class SpinePlugin extends Phaser.Plugins.ScenePlugin { + game: Phaser.Game; + private isWebGL; + gl: WebGLRenderingContext | null; + static gameWebGLRenderer: SceneRenderer | null; + get webGLRenderer(): SceneRenderer | null; + canvasRenderer: SkeletonRenderer | null; + phaserRenderer: Phaser.Renderer.Canvas.CanvasRenderer | Phaser.Renderer.WebGL.WebGLRenderer; + private skeletonDataCache; + private atlasCache; + constructor(scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string); + static rendererId: number; + boot(): void; + onResize(): void; + shutdown(): void; + destroy(): void; + gameDestroy(): void; + /** Returns the TextureAtlas instance for the given key */ + getAtlas(atlasKey: string): TextureAtlas; + /** Returns whether the TextureAtlas uses premultiplied alpha */ + isAtlasPremultiplied(atlasKey: string): any; + /** Returns the SkeletonData instance for the given data and atlas key */ + getSkeletonData(dataKey: string, atlasKey: string): SkeletonData; + /** Creates a new Skeleton instance from the data and atlas. */ + createSkeleton(dataKey: string, atlasKey: string): Skeleton; +} diff --git a/spine-ts/spine-phaser-v3/dist/SpinePlugin.js b/spine-ts/spine-phaser-v3/dist/SpinePlugin.js new file mode 100644 index 000000000..118ee804a --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/SpinePlugin.js @@ -0,0 +1,350 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +import * as Phaser from "phaser"; +import { SPINE_ATLAS_CACHE_KEY, SPINE_GAME_OBJECT_TYPE, SPINE_SKELETON_DATA_FILE_TYPE, SPINE_ATLAS_FILE_TYPE, SPINE_SKELETON_FILE_CACHE_KEY as SPINE_SKELETON_DATA_CACHE_KEY } from "./keys.js"; +import { AtlasAttachmentLoader, GLTexture, SceneRenderer, Skeleton, SkeletonBinary, SkeletonJson, TextureAtlas } from "@esotericsoftware/spine-webgl"; +import { SpineGameObject } from "./SpineGameObject.js"; +import { CanvasTexture, SkeletonRenderer } from "@esotericsoftware/spine-canvas"; +/** + * {@link ScenePlugin} implementation adding Spine Runtime capabilities to a scene. + * + * The scene's {@link LoaderPlugin} (`Scene.load`) gets these additional functions: + * * `spineBinary(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`. + * * `spineJson(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`. + * * `spineAtlas(key: string, url: string, premultipliedAlpha: boolean = true, xhrSettings?: XHRSettingsObject)`: loads a texture atlas `.atlas` file from the `url` as well as its correponding texture atlas page images. + * + * The scene's {@link GameObjectFactory} (`Scene.add`) gets these additional functions: + * * `spine(x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider = SetupPoseBoundsProvider())`: + * creates a new {@link SpineGameObject} from the data and atlas at position `(x, y)`, using the {@link BoundsProvider} to calculate its bounding box. The object is automatically added to the scene. + * + * The scene's {@link GameObjectCreator} (`Scene.make`) gets these additional functions: + * * `spine(config: SpineGameObjectConfig)`: creates a new {@link SpineGameObject} from the given configuration object. + * + * The plugin has additional public methods to work with Spine Runtime core API objects: + * * `getAtlas(atlasKey: string)`: returns the {@link TextureAtlas} instance for the given atlas key. + * * `getSkeletonData(skeletonDataKey: string)`: returns the {@link SkeletonData} instance for the given skeleton data key. + * * `createSkeleton(skeletonDataKey: string, atlasKey: string, premultipliedAlpha: boolean = true)`: creates a new {@link Skeleton} instance from the given skeleton data and atlas key. + * * `isPremultipliedAlpha(atlasKey: string)`: returns `true` if the atlas with the given key has premultiplied alpha. + */ +export class SpinePlugin extends Phaser.Plugins.ScenePlugin { + game; + isWebGL; + gl; + static gameWebGLRenderer = null; + get webGLRenderer() { + return SpinePlugin.gameWebGLRenderer; + } + canvasRenderer; + phaserRenderer; + skeletonDataCache; + atlasCache; + constructor(scene, pluginManager, pluginKey) { + super(scene, pluginManager, pluginKey); + this.game = pluginManager.game; + this.isWebGL = this.game.config.renderType === 2; + this.gl = this.isWebGL ? this.game.renderer.gl : null; + this.phaserRenderer = this.game.renderer; + this.canvasRenderer = null; + this.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_DATA_CACHE_KEY); + this.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY); + let skeletonJsonFileCallback = function (key, url, xhrSettings) { + let file = new SpineSkeletonDataFile(this, key, url, SpineSkeletonDataFileType.json, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineJson", skeletonJsonFileCallback, scene); + let skeletonBinaryFileCallback = function (key, url, xhrSettings) { + let file = new SpineSkeletonDataFile(this, key, url, SpineSkeletonDataFileType.binary, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineBinary", skeletonBinaryFileCallback, scene); + let atlasFileCallback = function (key, url, premultipliedAlpha, xhrSettings) { + let file = new SpineAtlasFile(this, key, url, premultipliedAlpha, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene); + let addSpineGameObject = function (x, y, dataKey, atlasKey, boundsProvider) { + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + const spinePlugin = this.scene.sys[pluginKey]; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, dataKey, atlasKey, boundsProvider); + this.displayList.add(gameObject); + this.updateList.add(gameObject); + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return gameObject; + }; + let makeSpineGameObject = function (config, addToScene = false) { + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + let x = config.x ? config.x : 0; + let y = config.y ? config.y : 0; + let boundsProvider = config.boundsProvider ? config.boundsProvider : undefined; + const spinePlugin = this.scene.sys[pluginKey]; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, config.dataKey, config.atlasKey, boundsProvider); + if (addToScene !== undefined) { + config.add = addToScene; + } + if (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return Phaser.GameObjects.BuildGameObject(this.scene, gameObject, config); + }; + pluginManager.registerGameObject(window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject); + } + static rendererId = 0; + boot() { + Skeleton.yDown = true; + if (this.isWebGL) { + if (!SpinePlugin.gameWebGLRenderer) { + SpinePlugin.gameWebGLRenderer = new SceneRenderer(this.game.renderer.canvas, this.gl, true); + } + this.onResize(); + this.game.scale.on(Phaser.Scale.Events.RESIZE, this.onResize, this); + } + else { + if (!this.canvasRenderer) { + this.canvasRenderer = new SkeletonRenderer(this.scene.sys.context); + } + } + var eventEmitter = this.systems.events; + eventEmitter.once('shutdown', this.shutdown, this); + eventEmitter.once('destroy', this.destroy, this); + this.game.events.once('destroy', this.gameDestroy, this); + } + onResize() { + var phaserRenderer = this.game.renderer; + var sceneRenderer = this.webGLRenderer; + if (phaserRenderer && sceneRenderer) { + var viewportWidth = phaserRenderer.width; + var viewportHeight = phaserRenderer.height; + sceneRenderer.camera.position.x = viewportWidth / 2; + sceneRenderer.camera.position.y = viewportHeight / 2; + sceneRenderer.camera.up.y = -1; + sceneRenderer.camera.direction.z = 1; + sceneRenderer.camera.setViewport(viewportWidth, viewportHeight); + } + } + shutdown() { + this.systems.events.off("shutdown", this.shutdown, this); + if (this.isWebGL) { + this.game.scale.off(Phaser.Scale.Events.RESIZE, this.onResize, this); + } + } + destroy() { + this.shutdown(); + } + gameDestroy() { + this.pluginManager.removeGameObject(window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, true, true); + if (this.webGLRenderer) + this.webGLRenderer.dispose(); + SpinePlugin.gameWebGLRenderer = null; + } + /** Returns the TextureAtlas instance for the given key */ + getAtlas(atlasKey) { + let atlas; + if (this.atlasCache.exists(atlasKey)) { + atlas = this.atlasCache.get(atlasKey); + } + else { + let atlasFile = this.game.cache.text.get(atlasKey); + atlas = new TextureAtlas(atlasFile.data); + if (this.isWebGL) { + let gl = this.gl; + const phaserUnpackPmaValue = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL); + if (phaserUnpackPmaValue) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + for (let atlasPage of atlas.pages) { + atlasPage.setTexture(new GLTexture(gl, this.game.textures.get(atlasKey + "!" + atlasPage.name).getSourceImage(), false)); + } + if (phaserUnpackPmaValue) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + } + else { + for (let atlasPage of atlas.pages) { + atlasPage.setTexture(new CanvasTexture(this.game.textures.get(atlasKey + "!" + atlasPage.name).getSourceImage())); + } + } + this.atlasCache.add(atlasKey, atlas); + } + return atlas; + } + /** Returns whether the TextureAtlas uses premultiplied alpha */ + isAtlasPremultiplied(atlasKey) { + let atlasFile = this.game.cache.text.get(atlasKey); + if (!atlasFile) + return false; + return atlasFile.premultipliedAlpha; + } + /** Returns the SkeletonData instance for the given data and atlas key */ + getSkeletonData(dataKey, atlasKey) { + const atlas = this.getAtlas(atlasKey); + const combinedKey = dataKey + atlasKey; + let skeletonData; + if (this.skeletonDataCache.exists(combinedKey)) { + skeletonData = this.skeletonDataCache.get(combinedKey); + } + else { + if (this.game.cache.json.exists(dataKey)) { + let jsonFile = this.game.cache.json.get(dataKey); + let json = new SkeletonJson(new AtlasAttachmentLoader(atlas)); + skeletonData = json.readSkeletonData(jsonFile); + } + else { + let binaryFile = this.game.cache.binary.get(dataKey); + let binary = new SkeletonBinary(new AtlasAttachmentLoader(atlas)); + skeletonData = binary.readSkeletonData(new Uint8Array(binaryFile)); + } + this.skeletonDataCache.add(combinedKey, skeletonData); + } + return skeletonData; + } + /** Creates a new Skeleton instance from the data and atlas. */ + createSkeleton(dataKey, atlasKey) { + return new Skeleton(this.getSkeletonData(dataKey, atlasKey)); + } +} +var SpineSkeletonDataFileType; +(function (SpineSkeletonDataFileType) { + SpineSkeletonDataFileType[SpineSkeletonDataFileType["json"] = 0] = "json"; + SpineSkeletonDataFileType[SpineSkeletonDataFileType["binary"] = 1] = "binary"; +})(SpineSkeletonDataFileType || (SpineSkeletonDataFileType = {})); +class SpineSkeletonDataFile extends Phaser.Loader.MultiFile { + fileType; + constructor(loader, key, url, fileType, xhrSettings) { + if (typeof key !== "string") { + const config = key; + key = config.key; + url = config.url; + fileType = config.type === "spineJson" ? SpineSkeletonDataFileType.json : SpineSkeletonDataFileType.binary; + xhrSettings = config.xhrSettings; + } + let file = null; + let isJson = fileType == SpineSkeletonDataFileType.json; + if (isJson) { + file = new Phaser.Loader.FileTypes.JSONFile(loader, { + key: key, + url: url, + extension: "json", + xhrSettings: xhrSettings, + }); + } + else { + file = new Phaser.Loader.FileTypes.BinaryFile(loader, { + key: key, + url: url, + extension: "skel", + xhrSettings: xhrSettings, + }); + } + super(loader, SPINE_SKELETON_DATA_FILE_TYPE, key, [file]); + this.fileType = fileType; + } + onFileComplete(file) { + this.pending--; + } + addToCache() { + if (this.isReadyToProcess()) + this.files[0].addToCache(); + } +} +class SpineAtlasFile extends Phaser.Loader.MultiFile { + premultipliedAlpha; + constructor(loader, key, url, premultipliedAlpha, xhrSettings) { + if (typeof key !== "string") { + const config = key; + key = config.key; + url = config.url; + premultipliedAlpha = config.premultipliedAlpha; + xhrSettings = config.xhrSettings; + } + super(loader, SPINE_ATLAS_FILE_TYPE, key, [ + new Phaser.Loader.FileTypes.TextFile(loader, { + key: key, + url: url, + xhrSettings: xhrSettings, + extension: "atlas" + }) + ]); + this.premultipliedAlpha = premultipliedAlpha; + } + onFileComplete(file) { + if (this.files.indexOf(file) != -1) { + this.pending--; + if (file.type == "text") { + var lines = file.data.split(/\r\n|\r|\n/); + let textures = []; + textures.push(lines[0]); + for (var t = 1; t < lines.length; t++) { + var line = lines[t]; + if (line.trim() === '' && t < lines.length - 1) { + line = lines[t + 1]; + textures.push(line); + } + } + let basePath = file.src.match(/^.*\//) ?? ""; + for (var i = 0; i < textures.length; i++) { + var url = basePath + textures[i]; + var key = file.key + "!" + textures[i]; + var image = new Phaser.Loader.FileTypes.ImageFile(this.loader, key, url); + if (!this.loader.keyExists(image)) { + this.addToMultiFile(image); + this.loader.addFile(image); + } + } + } + } + } + addToCache() { + if (this.isReadyToProcess()) { + let textureManager = this.loader.textureManager; + for (let file of this.files) { + if (file.type == "image") { + if (!textureManager.exists(file.key)) { + textureManager.addImage(file.key, file.data); + } + } + else { + this.premultipliedAlpha = this.premultipliedAlpha ?? (file.data.indexOf("pma: true") >= 0 || file.data.indexOf("pma:true") >= 0); + file.data = { + data: file.data, + premultipliedAlpha: this.premultipliedAlpha, + }; + file.addToCache(); + } + } + } + } +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BpbmVQbHVnaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU3BpbmVQbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRS9FLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxzQkFBc0IsRUFBRSw2QkFBNkIsRUFBRSxxQkFBcUIsRUFBRSw2QkFBNkIsSUFBSSw2QkFBNkIsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNoTSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFnQixZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sK0JBQStCLENBQUE7QUFDbkssT0FBTyxFQUFFLGVBQWUsRUFBaUMsTUFBTSxzQkFBc0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFtQmpGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRztBQUNILE1BQU0sT0FBTyxXQUFZLFNBQVEsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXO0lBQzFELElBQUksQ0FBYztJQUNWLE9BQU8sQ0FBVTtJQUN6QixFQUFFLENBQStCO0lBQ2pDLE1BQU0sQ0FBQyxpQkFBaUIsR0FBeUIsSUFBSSxDQUFDO0lBQ3RELElBQUksYUFBYTtRQUNoQixPQUFPLFdBQVcsQ0FBQyxpQkFBaUIsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsY0FBYyxDQUEwQjtJQUN4QyxjQUFjLENBQThFO0lBQ3BGLGlCQUFpQixDQUF5QjtJQUMxQyxVQUFVLENBQXlCO0lBRTNDLFlBQWEsS0FBbUIsRUFBRSxhQUEyQyxFQUFFLFNBQWlCO1FBQy9GLEtBQUssQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxJ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TyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO29CQUNqSSxJQUFJLENBQUMsSUFBSSxHQUFHO3dCQUNYLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTt3QkFDZixrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO3FCQUMzQyxDQUFDO29CQUNGLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDbkIsQ0FBQztZQUNGLENBQUM7UUFDRixDQUFDO0lBQ0YsQ0FBQztDQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBKdWx5IDI4LCAyMDIzLiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjMsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3JcbiAqIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSEVcbiAqIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5pbXBvcnQgKiBhcyBQaGFzZXIgZnJvbSBcInBoYXNlclwiO1xuaW1wb3J0IHsgU1BJTkVfQVRMQVNfQ0FDSEVfS0VZLCBTUElORV9HQU1FX09CSkVDVF9UWVBFLCBTUElORV9TS0VMRVRPTl9EQVRBX0ZJTEVfVFlQRSwgU1BJTkVfQVRMQVNfRklMRV9UWVBFLCBTUElORV9TS0VMRVRPTl9GSUxFX0NBQ0hFX0tFWSBhcyBTUElORV9TS0VMRVRPTl9EQVRBX0NBQ0hFX0tFWSB9IGZyb20gXCIuL2tleXMuanNcIjtcbmltcG9ydCB7IEF0bGFzQXR0YWNobWVudExvYWRlciwgR0xUZXh0dXJlLCBTY2VuZVJlbmRlcmVyLCBTa2VsZXRvbiwgU2tlbGV0b25CaW5hcnksIFNrZWxldG9uRGF0YSwgU2tlbGV0b25Kc29uLCBUZXh0dXJlQXRsYXMgfSBmcm9tIFwiQGVzb3Rlcmljc29mdHdhcmUvc3BpbmUtd2ViZ2xcIlxuaW1wb3J0IHsgU3BpbmVHYW1lT2JqZWN0LCBTcGluZUdhbWVPYmplY3RCb3VuZHNQcm92aWRlciB9IGZyb20gXCIuL1NwaW5lR2FtZU9iamVjdC5qc1wiO1xuaW1wb3J0IHsgQ2FudmFzVGV4dHVyZSwgU2tlbGV0b25SZW5kZXJlciB9IGZyb20gXCJAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jYW52YXNcIjtcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG9iamVjdCB1c2VkIHdoZW4gY3JlYXRpbmcge0BsaW5rIFNwaW5lR2FtZU9iamVjdH0gaW5zdGFuY2VzIHZpYSBhIHNjZW5lJ3NcbiAqIHtAbGluayBHYW1lT2JqZWN0Q3JlYXRvcn0gKGBTY2VuZS5tYWtlYCkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3BpbmVHYW1lT2JqZWN0Q29uZmlnIGV4dGVuZHMgUGhhc2VyLlR5cGVzLkdhbWVPYmplY3RzLkdhbWVPYmplY3RDb25maWcge1xuXHQvKiogVGhlIHgtcG9zaXRpb24gb2YgdGhlIG9iamVjdCwgb3B0aW9uYWwsIGRlZmF1bHQ6IDAgKi9cblx0eD86IG51bWJlcixcblx0LyoqIFRoZSB5LXBvc2l0aW9uIG9mIHRoZSBvYmplY3QsIG9wdGlvbmFsLCBkZWZhdWx0OiAwICovXG5cdHk/OiBudW1iZXIsXG5cdC8qKiBUaGUgc2tlbGV0b24gZGF0YSBrZXkgKi9cblx0ZGF0YUtleTogc3RyaW5nLFxuXHQvKiogVGhlIGF0bGFzIGtleSAqL1xuXHRhdGxhc0tleTogc3RyaW5nXG5cdC8qKiBUaGUgYm91bmRzIHByb3ZpZGVyLCBvcHRpb25hbCwgZGVmYXVsdDogYFNldHVwUG9zZUJvdW5kc1Byb3ZpZGVyYCAqL1xuXHRib3VuZHNQcm92aWRlcj86IFNwaW5lR2FtZU9iamVjdEJvdW5kc1Byb3ZpZGVyXG59XG5cbi8qKlxuICoge0BsaW5rIFNjZW5lUGx1Z2lufSBpbXBsZW1lbnRhdGlvbiBhZGRpbmcgU3BpbmUgUnVudGltZSBjYXBhYmlsaXRpZXMgdG8gYSBzY2VuZS5cbiAqXG4gKiBUaGUgc2NlbmUncyB7QGxpbmsgTG9hZGVyUGx1Z2lufSAoYFNjZW5lLmxvYWRgKSBnZXRzIHRoZXNlIGFkZGl0aW9uYWwgZnVuY3Rpb25zOlxuICogKiBgc3BpbmVCaW5hcnkoa2V5OiBzdHJpbmcsIHVybDogc3RyaW5nLCB4aHJTZXR0aW5ncz86IFhIUlNldHRpbmdzT2JqZWN0KWA6IGxvYWRzIGEgc2tlbGV0b24gYmluYXJ5IGAuc2tlbGAgZmlsZSBmcm9tIHRoZSBgdXJsYC5cbiAqICogYHNwaW5lSnNvbihrZXk6IHN0cmluZywgdXJsOiBzdHJpbmcsIHhoclNldHRpbmdzPzogWEhSU2V0dGluZ3NPYmplY3QpYDogbG9hZHMgYSBza2VsZXRvbiBiaW5hcnkgYC5za2VsYCBmaWxlIGZyb20gdGhlIGB1cmxgLlxuICogKiBgc3BpbmVBdGxhcyhrZXk6IHN0cmluZywgdXJsOiBzdHJpbmcsIHByZW11bHRpcGxpZWRBbHBoYTogYm9vbGVhbiA9IHRydWUsIHhoclNldHRpbmdzPzogWEhSU2V0dGluZ3NPYmplY3QpYDogbG9hZHMgYSB0ZXh0dXJlIGF0bGFzIGAuYXRsYXNgIGZpbGUgZnJvbSB0aGUgYHVybGAgYXMgd2VsbCBhcyBpdHMgY29ycmVwb25kaW5nIHRleHR1cmUgYXRsYXMgcGFnZSBpbWFnZXMuXG4gKlxuICogVGhlIHNjZW5lJ3Mge0BsaW5rIEdhbWVPYmplY3RGYWN0b3J5fSAoYFNjZW5lLmFkZGApIGdldHMgdGhlc2UgYWRkaXRpb25hbCBmdW5jdGlvbnM6XG4gKiAqIGBzcGluZSh4OiBudW1iZXIsIHk6IG51bWJlciwgZGF0YUtleTogc3RyaW5nLCBhdGxhc0tleTogc3RyaW5nLCBib3VuZHNQcm92aWRlcjogU3BpbmVHYW1lT2JqZWN0Qm91bmRzUHJvdmlkZXIgPSBTZXR1cFBvc2VCb3VuZHNQcm92aWRlcigpKWA6XG4gKiAgICBjcmVhdGVzIGEgbmV3IHtAbGluayBTcGluZUdhbWVPYmplY3R9IGZyb20gdGhlIGRhdGEgYW5kIGF0bGFzIGF0IHBvc2l0aW9uIGAoeCwgeSlgLCB1c2luZyB0aGUge0BsaW5rIEJvdW5kc1Byb3ZpZGVyfSB0byBjYWxjdWxhdGUgaXRzIGJvdW5kaW5nIGJveC4gVGhlIG9iamVjdCBpcyBhdXRvbWF0aWNhbGx5IGFkZGVkIHRvIHRoZSBzY2VuZS5cbiAqXG4gKiBUaGUgc2NlbmUncyB7QGxpbmsgR2FtZU9iamVjdENyZWF0b3J9IChgU2NlbmUubWFrZWApIGdldHMgdGhlc2UgYWRkaXRpb25hbCBmdW5jdGlvbnM6XG4gKiAqIGBzcGluZShjb25maWc6IFNwaW5lR2FtZU9iamVjdENvbmZpZylgOiBjcmVhdGVzIGEgbmV3IHtAbGluayBTcGluZUdhbWVPYmplY3R9IGZyb20gdGhlIGdpdmVuIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxuICpcbiAqIFRoZSBwbHVnaW4gaGFzIGFkZGl0aW9uYWwgcHVibGljIG1ldGhvZHMgdG8gd29yayB3aXRoIFNwaW5lIFJ1bnRpbWUgY29yZSBBUEkgb2JqZWN0czpcbiAqICogYGdldEF0bGFzKGF0bGFzS2V5OiBzdHJpbmcpYDogcmV0dXJucyB0aGUge0BsaW5rIFRleHR1cmVBdGxhc30gaW5zdGFuY2UgZm9yIHRoZSBnaXZlbiBhdGxhcyBrZXkuXG4gKiAqIGBnZXRTa2VsZXRvbkRhdGEoc2tlbGV0b25EYXRhS2V5OiBzdHJpbmcpYDogcmV0dXJucyB0aGUge0BsaW5rIFNrZWxldG9uRGF0YX0gaW5zdGFuY2UgZm9yIHRoZSBnaXZlbiBza2VsZXRvbiBkYXRhIGtleS5cbiAqICogYGNyZWF0ZVNrZWxldG9uKHNrZWxldG9uRGF0YUtleTogc3RyaW5nLCBhdGxhc0tleTogc3RyaW5nLCBwcmVtdWx0aXBsaWVkQWxwaGE6IGJvb2xlYW4gPSB0cnVlKWA6IGNyZWF0ZXMgYSBuZXcge0BsaW5rIFNrZWxldG9ufSBpbnN0YW5jZSBmcm9tIHRoZSBnaXZlbiBza2VsZXRvbiBkYXRhIGFuZCBhdGxhcyBrZXkuXG4gKiAqIGBpc1ByZW11bHRpcGxpZWRBbHBoYShhdGxhc0tleTogc3RyaW5nKWA6IHJldHVybnMgYHRydWVgIGlmIHRoZSBhdGxhcyB3aXRoIHRoZSBnaXZlbiBrZXkgaGFzIHByZW11bHRpcGxpZWQgYWxwaGEuXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGluZVBsdWdpbiBleHRlbmRzIFBoYXNlci5QbHVnaW5zLlNjZW5lUGx1Z2luIHtcblx0Z2FtZTogUGhhc2VyLkdhbWU7XG5cdHByaXZhdGUgaXNXZWJHTDogYm9vbGVhbjtcblx0Z2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCB8IG51bGw7XG5cdHN0YXRpYyBnYW1lV2ViR0xSZW5kZXJlcjogU2NlbmVSZW5kZXJlciB8IG51bGwgPSBudWxsO1xuXHRnZXQgd2ViR0xSZW5kZXJlciAoKTogU2NlbmVSZW5kZXJlciB8IG51bGwge1xuXHRcdHJldHVybiBTcGluZVBsdWdpbi5nYW1lV2ViR0xSZW5kZXJlcjtcblx0fVxuXHRjYW52YXNSZW5kZXJlcjogU2tlbGV0b25SZW5kZXJlciB8IG51bGw7XG5cdHBoYXNlclJlbmRlcmVyOiBQaGFzZXIuUmVuZGVyZXIuQ2FudmFzLkNhbnZhc1JlbmRlcmVyIHwgUGhhc2VyLlJlbmRlcmVyLldlYkdMLldlYkdMUmVuZGVyZXI7XG5cdHByaXZhdGUgc2tlbGV0b25EYXRhQ2FjaGU6IFBoYXNlci5DYWNoZS5CYXNlQ2FjaGU7XG5cdHByaXZhdGUgYXRsYXNDYWNoZTogUGhhc2VyLkNhY2hlLkJhc2VDYWNoZTtcblxuXHRjb25zdHJ1Y3RvciAoc2NlbmU6IFBoYXNlci5TY2VuZSwgcGx1Z2luTWFuYWdlcjogUGhhc2VyLlBsdWdpbnMuUGx1Z2luTWFuYWdlciwgcGx1Z2luS2V5OiBzdHJpbmcpIHtcblx0XHRzdXBlcihzY2VuZSwgcGx1Z2luTWFuYWdlciwgcGx1Z2luS2V5KTtcblx0XHR0aGlzLmdhbWUgPSBwbHVnaW5NYW5hZ2VyLmdhbWU7XG5cdFx0dGhpcy5pc1dlYkdMID0gdGhpcy5nYW1lLmNvbmZpZy5yZW5kZXJUeXBlID09PSAyO1xuXHRcdHRoaXMuZ2wgPSB0aGlzLmlzV2ViR0wgPyAodGhpcy5nYW1lLnJlbmRlcmVyIGFzIFBoYXNlci5SZW5kZXJlci5XZWJHTC5XZWJHTFJlbmRlcmVyKS5nbCA6IG51bGw7XG5cdFx0dGhpcy5waGFzZXJSZW5kZXJlciA9IHRoaXMuZ2FtZS5yZW5kZXJlcjtcblx0XHR0aGlzLmNhbnZhc1JlbmRlcmVyID0gbnVsbDtcblx0XHR0aGlzLnNrZWxldG9uRGF0YUNhY2hlID0gdGhpcy5nYW1lLmNhY2hlLmFkZEN1c3RvbShTUElORV9TS0VMRVRPTl9EQVRBX0NBQ0hFX0tFWSk7XG5cdFx0dGhpcy5hdGxhc0NhY2hlID0gdGhpcy5nYW1lLmNhY2hlLmFkZEN1c3RvbShTUElORV9BVExBU19DQUNIRV9LRVkpO1xuXG5cdFx0bGV0IHNrZWxldG9uSnNvbkZpbGVDYWxsYmFjayA9IGZ1bmN0aW9uICh0aGlzOiBhbnksIGtleTogc3RyaW5nLFxuXHRcdFx0dXJsOiBzdHJpbmcsXG5cdFx0XHR4aHJTZXR0aW5nczogUGhhc2VyLlR5cGVzLkxvYWRlci5YSFJTZXR0aW5nc09iamVjdCkge1xuXHRcdFx0bGV0IGZpbGUgPSBuZXcgU3BpbmVTa2VsZXRvbkRhdGFGaWxlKHRoaXMgYXMgYW55LCBrZXksIHVybCwgU3BpbmVTa2VsZXRvbkRhdGFGaWxlVHlwZS5qc29uLCB4aHJTZXR0aW5ncyk7XG5cdFx0XHR0aGlzLmFkZEZpbGUoZmlsZS5maWxlcyk7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9O1xuXHRcdHBsdWdpbk1hbmFnZXIucmVnaXN0ZXJGaWxlVHlwZShcInNwaW5lSnNvblwiLCBza2VsZXRvbkpzb25GaWxlQ2FsbGJhY2ssIHNjZW5lKTtcblxuXHRcdGxldCBza2VsZXRvbkJpbmFyeUZpbGVDYWxsYmFjayA9IGZ1bmN0aW9uICh0aGlzOiBhbnksIGtleTogc3RyaW5nLFxuXHRcdFx0dXJsOiBzdHJpbmcsXG5cdFx0XHR4aHJTZXR0aW5nczogUGhhc2VyLlR5cGVzLkxvYWRlci5YSFJTZXR0aW5nc09iamVjdCkge1xuXHRcdFx0bGV0IGZpbGUgPSBuZXcgU3BpbmVTa2VsZXRvbkRhdGFGaWxlKHRoaXMgYXMgYW55LCBrZXksIHVybCwgU3BpbmVTa2VsZXRvbkRhdGFGaWxlVHlwZS5iaW5hcnksIHhoclNldHRpbmdzKTtcblx0XHRcdHRoaXMuYWRkRmlsZShmaWxlLmZpbGVzKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH07XG5cdFx0cGx1Z2luTWFuYWdlci5yZWdpc3RlckZpbGVUeXBlKFwic3BpbmVCaW5hcnlcIiwgc2tlbGV0b25CaW5hcnlGaWxlQ2FsbGJhY2ssIHNjZW5lKTtcblxuXHRcdGxldCBhdGxhc0ZpbGVDYWxsYmFjayA9IGZ1bmN0aW9uICh0aGlzOiBhbnksIGtleTogc3RyaW5nLFxuXHRcdFx0dXJsOiBzdHJpbmcsXG5cdFx0XHRwcmVtdWx0aXBsaWVkQWxwaGE6IGJvb2xlYW4sXG5cdFx0XHR4aHJTZXR0aW5nczogUGhhc2VyLlR5cGVzLkxvYWRlci5YSFJTZXR0aW5nc09iamVjdCkge1xuXHRcdFx0bGV0IGZpbGUgPSBuZXcgU3BpbmVBdGxhc0ZpbGUodGhpcyBhcyBhbnksIGtleSwgdXJsLCBwcmVtdWx0aXBsaWVkQWxwaGEsIHhoclNldHRpbmdzKTtcblx0XHRcdHRoaXMuYWRkRmlsZShmaWxlLmZpbGVzKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH07XG5cdFx0cGx1Z2luTWFuYWdlci5yZWdpc3RlckZpbGVUeXBlKFwic3BpbmVBdGxhc1wiLCBhdGxhc0ZpbGVDYWxsYmFjaywgc2NlbmUpO1xuXG5cdFx0bGV0IGFkZFNwaW5lR2FtZU9iamVjdCA9IGZ1bmN0aW9uICh0aGlzOiBQaGFzZXIuR2FtZU9iamVjdHMuR2FtZU9iamVjdEZhY3RvcnksIHg6IG51bWJlciwgeTogbnVtYmVyLCBkYXRhS2V5OiBzdHJpbmcsIGF0bGFzS2V5OiBzdHJpbmcsIGJvdW5kc1Byb3ZpZGVyOiBTcGluZUdhbWVPYmplY3RCb3VuZHNQcm92aWRlcikge1xuXHRcdFx0aWYgKHRoaXMuc2NlbmUuc3lzLnJlbmRlcmVyIGluc3RhbmNlb2YgUGhhc2VyLlJlbmRlcmVyLldlYkdMLldlYkdMUmVuZGVyZXIpIHtcblx0XHRcdFx0dGhpcy5zY2VuZS5zeXMucmVuZGVyZXIucGlwZWxpbmVzLmNsZWFyKCk7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IHNwaW5lUGx1Z2luID0gKHRoaXMuc2NlbmUuc3lzIGFzIGFueSlbcGx1Z2luS2V5XSBhcyBTcGluZVBsdWdpbjtcblx0XHRcdGxldCBnYW1lT2JqZWN0ID0gbmV3IFNwaW5lR2FtZU9iamVjdCh0aGlzLnNjZW5lLCBzcGluZVBsdWdpbiwgeCwgeSwgZGF0YUtleSwgYXRsYXNLZXksIGJvdW5kc1Byb3ZpZGVyKTtcblx0XHRcdHRoaXMuZGlzcGxheUxpc3QuYWRkKGdhbWVPYmplY3QpO1xuXHRcdFx0dGhpcy51cGRhdGVMaXN0LmFkZChnYW1lT2JqZWN0KTtcblxuXHRcdFx0aWYgKHRoaXMuc2NlbmUuc3lzLnJlbmRlcmVyIGluc3RhbmNlb2YgUGhhc2VyLlJlbmRlcmVyLldlYkdMLldlYkdMUmVuZGVyZXIpIHtcblx0XHRcdFx0dGhpcy5zY2VuZS5zeXMucmVuZGVyZXIucGlwZWxpbmVzLnJlYmluZCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZ2FtZU9iamVjdDtcblx0XHR9O1xuXG5cdFx0bGV0IG1ha2VTcGluZUdhbWVPYmplY3QgPSBmdW5jdGlvbiAodGhpczogUGhhc2VyLkdhbWVPYmplY3RzLkdhbWVPYmplY3RGYWN0b3J5LCBjb25maWc6IFNwaW5lR2FtZU9iamVjdENvbmZpZywgYWRkVG9TY2VuZTogYm9vbGVhbiA9IGZhbHNlKSB7XG5cdFx0XHRpZiAodGhpcy5zY2VuZS5zeXMucmVuZGVyZXIgaW5zdGFuY2VvZiBQaGFzZXIuUmVuZGVyZXIuV2ViR0wuV2ViR0xSZW5kZXJlcikge1xuXHRcdFx0XHR0aGlzLnNjZW5lLnN5cy5yZW5kZXJlci5waXBlbGluZXMuY2xlYXIoKTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IHggPSBjb25maWcueCA/IGNvbmZpZy54IDogMDtcblx0XHRcdGxldCB5ID0gY29uZmlnLnkgPyBjb25maWcueSA6IDA7XG5cdFx0XHRsZXQgYm91bmRzUHJvdmlkZXIgPSBjb25maWcuYm91bmRzUHJvdmlkZXIgPyBjb25maWcuYm91bmRzUHJvdmlkZXIgOiB1bmRlZmluZWQ7XG5cblx0XHRcdGNvbnN0IHNwaW5lUGx1Z2luID0gKHRoaXMuc2NlbmUuc3lzIGFzIGFueSlbcGx1Z2luS2V5XSBhcyBTcGluZVBsdWdpbjtcblx0XHRcdGxldCBnYW1lT2JqZWN0ID0gbmV3IFNwaW5lR2FtZU9iamVjdCh0aGlzLnNjZW5lLCBzcGluZVBsdWdpbiwgeCwgeSwgY29uZmlnLmRhdGFLZXksIGNvbmZpZy5hdGxhc0tleSwgYm91bmRzUHJvdmlkZXIpO1xuXHRcdFx0aWYgKGFkZFRvU2NlbmUgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRjb25maWcuYWRkID0gYWRkVG9TY2VuZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHRoaXMuc2NlbmUuc3lzLnJlbmRlcmVyIGluc3RhbmNlb2YgUGhhc2VyLlJlbmRlcmVyLldlYkdMLldlYkdMUmVuZGVyZXIpIHtcblx0XHRcdFx0dGhpcy5zY2VuZS5zeXMucmVuZGVyZXIucGlwZWxpbmVzLnJlYmluZCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gUGhhc2VyLkdhbWVPYmplY3RzLkJ1aWxkR2FtZU9iamVjdCh0aGlzLnNjZW5lLCBnYW1lT2JqZWN0LCBjb25maWcpO1xuXHRcdH1cblx0XHRwbHVnaW5NYW5hZ2VyLnJlZ2lzdGVyR2FtZU9iamVjdCgod2luZG93IGFzIGFueSkuU1BJTkVfR0FNRV9PQkpFQ1RfVFlQRSA/ICh3aW5kb3cgYXMgYW55KS5TUElORV9HQU1FX09CSkVDVF9UWVBFIDogU1BJTkVfR0FNRV9PQkpFQ1RfVFlQRSwgYWRkU3BpbmVHYW1lT2JqZWN0LCBtYWtlU3BpbmVHYW1lT2JqZWN0KTtcblx0fVxuXG5cdHN0YXRpYyByZW5kZXJlcklkID0gMDtcblx0Ym9vdCAoKSB7XG5cdFx0U2tlbGV0b24ueURvd24gPSB0cnVlO1xuXHRcdGlmICh0aGlzLmlzV2ViR0wpIHtcblx0XHRcdGlmICghU3BpbmVQbHVnaW4uZ2FtZVdlYkdMUmVuZGVyZXIpIHtcblx0XHRcdFx0U3BpbmVQbHVnaW4uZ2FtZVdlYkdMUmVuZGVyZXIgPSBuZXcgU2NlbmVSZW5kZXJlcigodGhpcy5nYW1lLnJlbmRlcmVyISBhcyBQaGFzZXIuUmVuZGVyZXIuV2ViR0wuV2ViR0xSZW5kZXJlcikuY2FudmFzLCB0aGlzLmdsISwgdHJ1ZSk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm9uUmVzaXplKCk7XG5cdFx0XHR0aGlzLmdhbWUuc2NhbGUub24oUGhhc2VyLlNjYWxlLkV2ZW50cy5SRVNJWkUsIHRoaXMub25SZXNpemUsIHRoaXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIXRoaXMuY2FudmFzUmVuZGVyZXIpIHtcblx0XHRcdFx0dGhpcy5jYW52YXNSZW5kZXJlciA9IG5ldyBTa2VsZXRvblJlbmRlcmVyKHRoaXMuc2NlbmUhLnN5cy5jb250ZXh0KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR2YXIgZXZlbnRFbWl0dGVyID0gdGhpcy5zeXN0ZW1zIS5ldmVudHM7XG5cdFx0ZXZlbnRFbWl0dGVyLm9uY2UoJ3NodXRkb3duJywgdGhpcy5zaHV0ZG93biwgdGhpcyk7XG5cdFx0ZXZlbnRFbWl0dGVyLm9uY2UoJ2Rlc3Ryb3knLCB0aGlzLmRlc3Ryb3ksIHRoaXMpO1xuXHRcdHRoaXMuZ2FtZS5ldmVudHMub25jZSgnZGVzdHJveScsIHRoaXMuZ2FtZURlc3Ryb3ksIHRoaXMpO1xuXHR9XG5cblx0b25SZXNpemUgKCkge1xuXHRcdHZhciBwaGFzZXJSZW5kZXJlciA9IHRoaXMuZ2FtZS5yZW5kZXJlcjtcblx0XHR2YXIgc2NlbmVSZW5kZXJlciA9IHRoaXMud2ViR0xSZW5kZXJlcjtcblxuXHRcdGlmIChwaGFzZXJSZW5kZXJlciAmJiBzY2VuZVJlbmRlcmVyKSB7XG5cdFx0XHR2YXIgdmlld3BvcnRXaWR0aCA9IHBoYXNlclJlbmRlcmVyLndpZHRoO1xuXHRcdFx0dmFyIHZpZXdwb3J0SGVpZ2h0ID0gcGhhc2VyUmVuZGVyZXIuaGVpZ2h0O1xuXHRcdFx0c2NlbmVSZW5kZXJlci5jYW1lcmEucG9zaXRpb24ueCA9IHZpZXdwb3J0V2lkdGggLyAyO1xuXHRcdFx0c2NlbmVSZW5kZXJlci5jYW1lcmEucG9zaXRpb24ueSA9IHZpZXdwb3J0SGVpZ2h0IC8gMjtcblx0XHRcdHNjZW5lUmVuZGVyZXIuY2FtZXJhLnVwLnkgPSAtMTtcblx0XHRcdHNjZW5lUmVuZGVyZXIuY2FtZXJhLmRpcmVjdGlvbi56ID0gMTtcblx0XHRcdHNjZW5lUmVuZGVyZXIuY2FtZXJhLnNldFZpZXdwb3J0KHZpZXdwb3J0V2lkdGgsIHZpZXdwb3J0SGVpZ2h0KTtcblx0XHR9XG5cdH1cblxuXHRzaHV0ZG93biAoKSB7XG5cdFx0dGhpcy5zeXN0ZW1zIS5ldmVudHMub2ZmKFwic2h1dGRvd25cIiwgdGhpcy5zaHV0ZG93biwgdGhpcyk7XG5cdFx0aWYgKHRoaXMuaXNXZWJHTCkge1xuXHRcdFx0dGhpcy5nYW1lLnNjYWxlLm9mZihQaGFzZXIuU2NhbGUuRXZlbnRzLlJFU0laRSwgdGhpcy5vblJlc2l6ZSwgdGhpcyk7XG5cdFx0fVxuXHR9XG5cblx0ZGVzdHJveSAoKSB7XG5cdFx0dGhpcy5zaHV0ZG93bigpXG5cdH1cblxuXHRnYW1lRGVzdHJveSAoKSB7XG5cdFx0dGhpcy5wbHVnaW5NYW5hZ2VyLnJlbW92ZUdhbWVPYmplY3QoKHdpbmRvdyBhcyBhbnkpLlNQSU5FX0dBTUVfT0JKRUNUX1RZUEUgPyAod2luZG93IGFzIGFueSkuU1BJTkVfR0FNRV9PQkpFQ1RfVFlQRSA6IFNQSU5FX0dBTUVfT0JKRUNUX1RZUEUsIHRydWUsIHRydWUpO1xuXHRcdGlmICh0aGlzLndlYkdMUmVuZGVyZXIpIHRoaXMud2ViR0xSZW5kZXJlci5kaXNwb3NlKCk7XG5cdFx0U3BpbmVQbHVnaW4uZ2FtZVdlYkdMUmVuZGVyZXIgPSBudWxsO1xuXHR9XG5cblx0LyoqIFJldHVybnMgdGhlIFRleHR1cmVBdGxhcyBpbnN0YW5jZSBmb3IgdGhlIGdpdmVuIGtleSAqL1xuXHRnZXRBdGxhcyAoYXRsYXNLZXk6IHN0cmluZykge1xuXHRcdGxldCBhdGxhczogVGV4dHVyZUF0bGFzO1xuXHRcdGlmICh0aGlzLmF0bGFzQ2FjaGUuZXhpc3RzKGF0bGFzS2V5KSkge1xuXHRcdFx0YXRsYXMgPSB0aGlzLmF0bGFzQ2FjaGUuZ2V0KGF0bGFzS2V5KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IGF0bGFzRmlsZSA9IHRoaXMuZ2FtZS5jYWNoZS50ZXh0LmdldChhdGxhc0tleSkgYXMgeyBkYXRhOiBzdHJpbmcsIHByZW11bHRpcGxpZWRBbHBoYTogYm9vbGVhbiB9O1xuXHRcdFx0YXRsYXMgPSBuZXcgVGV4dHVyZUF0bGFzKGF0bGFzRmlsZS5kYXRhKTtcblx0XHRcdGlmICh0aGlzLmlzV2ViR0wpIHtcblx0XHRcdFx0bGV0IGdsID0gdGhpcy5nbCE7XG5cdFx0XHRcdGNvbnN0IHBoYXNlclVucGFja1BtYVZhbHVlID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLlVOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCk7XG5cdFx0XHRcdGlmIChwaGFzZXJVbnBhY2tQbWFWYWx1ZSkgZ2wucGl4ZWxTdG9yZWkoZ2wuVU5QQUNLX1BSRU1VTFRJUExZX0FMUEhBX1dFQkdMLCBmYWxzZSk7XG5cdFx0XHRcdGZvciAobGV0IGF0bGFzUGFnZSBvZiBhdGxhcy5wYWdlcykge1xuXHRcdFx0XHRcdGF0bGFzUGFnZS5zZXRUZXh0dXJlKG5ldyBHTFRleHR1cmUoZ2wsIHRoaXMuZ2FtZS50ZXh0dXJlcy5nZXQoYXRsYXNLZXkgKyBcIiFcIiArIGF0bGFzUGFnZS5uYW1lKS5nZXRTb3VyY2VJbWFnZSgpIGFzIEhUTUxJbWFnZUVsZW1lbnQgfCBJbWFnZUJpdG1hcCwgZmFsc2UpKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAocGhhc2VyVW5wYWNrUG1hVmFsdWUpIGdsLnBpeGVsU3RvcmVpKGdsLlVOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCwgdHJ1ZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKGxldCBhdGxhc1BhZ2Ugb2YgYXRsYXMucGFnZXMpIHtcblx0XHRcdFx0XHRhdGxhc1BhZ2Uuc2V0VGV4dHVyZShuZXcgQ2FudmFzVGV4dHVyZSh0aGlzLmdhbWUudGV4dHVyZXMuZ2V0KGF0bGFzS2V5ICsgXCIhXCIgKyBhdGxhc1BhZ2UubmFtZSkuZ2V0U291cmNlSW1hZ2UoKSBhcyBIVE1MSW1hZ2VFbGVtZW50IHwgSW1hZ2VCaXRtYXApKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0dGhpcy5hdGxhc0NhY2hlLmFkZChhdGxhc0tleSwgYXRsYXMpO1xuXHRcdH1cblx0XHRyZXR1cm4gYXRsYXM7XG5cdH1cblxuXHQvKiogUmV0dXJucyB3aGV0aGVyIHRoZSBUZXh0dXJlQXRsYXMgdXNlcyBwcmVtdWx0aXBsaWVkIGFscGhhICovXG5cdGlzQXRsYXNQcmVtdWx0aXBsaWVkIChhdGxhc0tleTogc3RyaW5nKSB7XG5cdFx0bGV0IGF0bGFzRmlsZSA9IHRoaXMuZ2FtZS5jYWNoZS50ZXh0LmdldChhdGxhc0tleSk7XG5cdFx0aWYgKCFhdGxhc0ZpbGUpIHJldHVybiBmYWxzZTtcblx0XHRyZXR1cm4gYXRsYXNGaWxlLnByZW11bHRpcGxpZWRBbHBoYTtcblx0fVxuXG5cdC8qKiBSZXR1cm5zIHRoZSBTa2VsZXRvbkRhdGEgaW5zdGFuY2UgZm9yIHRoZSBnaXZlbiBkYXRhIGFuZCBhdGxhcyBrZXkgKi9cblx0Z2V0U2tlbGV0b25EYXRhIChkYXRhS2V5OiBzdHJpbmcsIGF0bGFzS2V5OiBzdHJpbmcpIHtcblx0XHRjb25zdCBhdGxhcyA9IHRoaXMuZ2V0QXRsYXMoYXRsYXNLZXkpXG5cdFx0Y29uc3QgY29tYmluZWRLZXkgPSBkYXRhS2V5ICsgYXRsYXNLZXk7XG5cdFx0bGV0IHNrZWxldG9uRGF0YTogU2tlbGV0b25EYXRhO1xuXHRcdGlmICh0aGlzLnNrZWxldG9uRGF0YUNhY2hlLmV4aXN0cyhjb21iaW5lZEtleSkpIHtcblx0XHRcdHNrZWxldG9uRGF0YSA9IHRoaXMuc2tlbGV0b25EYXRhQ2FjaGUuZ2V0KGNvbWJpbmVkS2V5KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKHRoaXMuZ2FtZS5jYWNoZS5qc29uLmV4aXN0cyhkYXRhS2V5KSkge1xuXHRcdFx0XHRsZXQganNvbkZpbGUgPSB0aGlzLmdhbWUuY2FjaGUuanNvbi5nZXQoZGF0YUtleSkgYXMgYW55O1xuXHRcdFx0XHRsZXQganNvbiA9IG5ldyBTa2VsZXRvbkpzb24obmV3IEF0bGFzQXR0YWNobWVudExvYWRlcihhdGxhcykpO1xuXHRcdFx0XHRza2VsZXRvbkRhdGEgPSBqc29uLnJlYWRTa2VsZXRvbkRhdGEoanNvbkZpbGUpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bGV0IGJpbmFyeUZpbGUgPSB0aGlzLmdhbWUuY2FjaGUuYmluYXJ5LmdldChkYXRhS2V5KSBhcyBBcnJheUJ1ZmZlcjtcblx0XHRcdFx0bGV0IGJpbmFyeSA9IG5ldyBTa2VsZXRvbkJpbmFyeShuZXcgQXRsYXNBdHRhY2htZW50TG9hZGVyKGF0bGFzKSk7XG5cdFx0XHRcdHNrZWxldG9uRGF0YSA9IGJpbmFyeS5yZWFkU2tlbGV0b25EYXRhKG5ldyBVaW50OEFycmF5KGJpbmFyeUZpbGUpKTtcblx0XHRcdH1cblx0XHRcdHRoaXMuc2tlbGV0b25EYXRhQ2FjaGUuYWRkKGNvbWJpbmVkS2V5LCBza2VsZXRvbkRhdGEpO1xuXHRcdH1cblx0XHRyZXR1cm4gc2tlbGV0b25EYXRhO1xuXHR9XG5cblx0LyoqIENyZWF0ZXMgYSBuZXcgU2tlbGV0b24gaW5zdGFuY2UgZnJvbSB0aGUgZGF0YSBhbmQgYXRsYXMuICovXG5cdGNyZWF0ZVNrZWxldG9uIChkYXRhS2V5OiBzdHJpbmcsIGF0bGFzS2V5OiBzdHJpbmcpIHtcblx0XHRyZXR1cm4gbmV3IFNrZWxldG9uKHRoaXMuZ2V0U2tlbGV0b25EYXRhKGRhdGFLZXksIGF0bGFzS2V5KSk7XG5cdH1cbn1cblxuZW51bSBTcGluZVNrZWxldG9uRGF0YUZpbGVUeXBlIHtcblx0anNvbixcblx0YmluYXJ5XG59XG5cbmludGVyZmFjZSBTcGluZVNrZWxldG9uRGF0YUZpbGVDb25maWcge1xuXHRrZXk6IHN0cmluZztcblx0dXJsOiBzdHJpbmc7XG5cdHR5cGU6IFwic3BpbmVKc29uXCIgfCBcInNwaW5lQmluYXJ5XCI7XG5cdHhoclNldHRpbmdzPzogUGhhc2VyLlR5cGVzLkxvYWRlci5YSFJTZXR0aW5nc09iamVjdFxufVxuXG5jbGFzcyBTcGluZVNrZWxldG9uRGF0YUZpbGUgZXh0ZW5kcyBQaGFzZXIuTG9hZGVyLk11bHRpRmlsZSB7XG5cdGNvbnN0cnVjdG9yIChsb2FkZXI6IFBoYXNlci5Mb2FkZXIuTG9hZGVyUGx1Z2luLCBrZXk6IHN0cmluZyB8IFNwaW5lU2tlbGV0b25EYXRhRmlsZUNvbmZpZywgdXJsPzogc3RyaW5nLCBwdWJsaWMgZmlsZVR5cGU/OiBTcGluZVNrZWxldG9uRGF0YUZpbGVUeXBlLCB4aHJTZXR0aW5ncz86IFBoYXNlci5UeXBlcy5Mb2FkZXIuWEhSU2V0dGluZ3NPYmplY3QpIHtcblx0XHRpZiAodHlwZW9mIGtleSAhPT0gXCJzdHJpbmdcIikge1xuXHRcdFx0Y29uc3QgY29uZmlnID0ga2V5O1xuXHRcdFx0a2V5ID0gY29uZmlnLmtleTtcblx0XHRcdHVybCA9IGNvbmZpZy51cmw7XG5cdFx0XHRmaWxlVHlwZSA9IGNvbmZpZy50eXBlID09PSBcInNwaW5lSnNvblwiID8gU3BpbmVTa2VsZXRvbkRhdGFGaWxlVHlwZS5qc29uIDogU3BpbmVTa2VsZXRvbkRhdGFGaWxlVHlwZS5iaW5hcnk7XG5cdFx0XHR4aHJTZXR0aW5ncyA9IGNvbmZpZy54aHJTZXR0aW5ncztcblx0XHR9XG5cdFx0bGV0IGZpbGUgPSBudWxsO1xuXHRcdGxldCBpc0pzb24gPSBmaWxlVHlwZSA9PSBTcGluZVNrZWxldG9uRGF0YUZpbGVUeXBlLmpzb247XG5cdFx0aWYgKGlzSnNvbikge1xuXHRcdFx0ZmlsZSA9IG5ldyBQaGFzZXIuTG9hZGVyLkZpbGVUeXBlcy5KU09ORmlsZShsb2FkZXIsIHtcblx0XHRcdFx0a2V5OiBrZXksXG5cdFx0XHRcdHVybDogdXJsLFxuXHRcdFx0XHRleHRlbnNpb246IFwianNvblwiLFxuXHRcdFx0XHR4aHJTZXR0aW5nczogeGhyU2V0dGluZ3MsXG5cdFx0XHR9IGFzIFBoYXNlci5UeXBlcy5Mb2FkZXIuRmlsZVR5cGVzLkpTT05GaWxlQ29uZmlnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZmlsZSA9IG5ldyBQaGFzZXIuTG9hZGVyLkZpbGVUeXBlcy5CaW5hcnlGaWxlKGxvYWRlciwge1xuXHRcdFx0XHRrZXk6IGtleSxcblx0XHRcdFx0dXJsOiB1cmwsXG5cdFx0XHRcdGV4dGVuc2lvbjogXCJza2VsXCIsXG5cdFx0XHRcdHhoclNldHRpbmdzOiB4aHJTZXR0aW5ncyxcblx0XHRcdH0gYXMgUGhhc2VyLlR5cGVzLkxvYWRlci5GaWxlVHlwZXMuQmluYXJ5RmlsZUNvbmZpZyk7XG5cdFx0fVxuXHRcdHN1cGVyKGxvYWRlciwgU1BJTkVfU0tFTEVUT05fREFUQV9GSUxFX1RZUEUsIGtleSwgW2ZpbGVdKTtcblx0fVxuXG5cdG9uRmlsZUNvbXBsZXRlIChmaWxlOiBQaGFzZXIuTG9hZGVyLkZpbGUpIHtcblx0XHR0aGlzLnBlbmRpbmctLTtcblx0fVxuXG5cdGFkZFRvQ2FjaGUgKCkge1xuXHRcdGlmICh0aGlzLmlzUmVhZHlUb1Byb2Nlc3MoKSkgdGhpcy5maWxlc1swXS5hZGRUb0NhY2hlKCk7XG5cdH1cbn1cblxuaW50ZXJmYWNlIFNwaW5lQXRsYXNGaWxlQ29uZmlnIHtcblx0a2V5OiBzdHJpbmc7XG5cdHVybDogc3RyaW5nO1xuXHRwcmVtdWx0aXBsaWVkQWxwaGE/OiBib29sZWFuO1xuXHR4aHJTZXR0aW5ncz86IFBoYXNlci5UeXBlcy5Mb2FkZXIuWEhSU2V0dGluZ3NPYmplY3Q7XG59XG5cbmNsYXNzIFNwaW5lQXRsYXNGaWxlIGV4dGVuZHMgUGhhc2VyLkxvYWRlci5NdWx0aUZpbGUge1xuXHRjb25zdHJ1Y3RvciAobG9hZGVyOiBQaGFzZXIuTG9hZGVyLkxvYWRlclBsdWdpbiwga2V5OiBzdHJpbmcgfCBTcGluZUF0bGFzRmlsZUNvbmZpZywgdXJsPzogc3RyaW5nLCBwdWJsaWMgcHJlbXVsdGlwbGllZEFscGhhPzogYm9vbGVhbiwgeGhyU2V0dGluZ3M/OiBQaGFzZXIuVHlwZXMuTG9hZGVyLlhIUlNldHRpbmdzT2JqZWN0KSB7XG5cdFx0aWYgKHR5cGVvZiBrZXkgIT09IFwic3RyaW5nXCIpIHtcblx0XHRcdGNvbnN0IGNvbmZpZyA9IGtleTtcblx0XHRcdGtleSA9IGNvbmZpZy5rZXk7XG5cdFx0XHR1cmwgPSBjb25maWcudXJsO1xuXHRcdFx0cHJlbXVsdGlwbGllZEFscGhhID0gY29uZmlnLnByZW11bHRpcGxpZWRBbHBoYTtcblx0XHRcdHhoclNldHRpbmdzID0gY29uZmlnLnhoclNldHRpbmdzO1xuXHRcdH1cblxuXHRcdHN1cGVyKGxvYWRlciwgU1BJTkVfQVRMQVNfRklMRV9UWVBFLCBrZXksIFtcblx0XHRcdG5ldyBQaGFzZXIuTG9hZGVyLkZpbGVUeXBlcy5UZXh0RmlsZShsb2FkZXIsIHtcblx0XHRcdFx0a2V5OiBrZXksXG5cdFx0XHRcdHVybDogdXJsLFxuXHRcdFx0XHR4aHJTZXR0aW5nczogeGhyU2V0dGluZ3MsXG5cdFx0XHRcdGV4dGVuc2lvbjogXCJhdGxhc1wiXG5cdFx0XHR9KVxuXHRcdF0pO1xuXHR9XG5cblx0b25GaWxlQ29tcGxldGUgKGZpbGU6IFBoYXNlci5Mb2FkZXIuRmlsZSkge1xuXHRcdGlmICh0aGlzLmZpbGVzLmluZGV4T2YoZmlsZSkgIT0gLTEpIHtcblx0XHRcdHRoaXMucGVuZGluZy0tO1xuXG5cdFx0XHRpZiAoZmlsZS50eXBlID09IFwidGV4dFwiKSB7XG5cdFx0XHRcdHZhciBsaW5lcyA9IGZpbGUuZGF0YS5zcGxpdCgvXFxyXFxufFxccnxcXG4vKTtcblx0XHRcdFx0bGV0IHRleHR1cmVzID0gW107XG5cdFx0XHRcdHRleHR1cmVzLnB1c2gobGluZXNbMF0pO1xuXHRcdFx0XHRmb3IgKHZhciB0ID0gMTsgdCA8IGxpbmVzLmxlbmd0aDsgdCsrKSB7XG5cdFx0XHRcdFx0dmFyIGxpbmUgPSBsaW5lc1t0XTtcblx0XHRcdFx0XHRpZiAobGluZS50cmltKCkgPT09ICcnICYmIHQgPCBsaW5lcy5sZW5ndGggLSAxKSB7XG5cdFx0XHRcdFx0XHRsaW5lID0gbGluZXNbdCArIDFdO1xuXHRcdFx0XHRcdFx0dGV4dHVyZXMucHVzaChsaW5lKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRsZXQgYmFzZVBhdGggPSBmaWxlLnNyYy5tYXRjaCgvXi4qXFwvLykgPz8gXCJcIjtcblx0XHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0ZXh0dXJlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRcdHZhciB1cmwgPSBiYXNlUGF0aCArIHRleHR1cmVzW2ldO1xuXHRcdFx0XHRcdHZhciBrZXkgPSBmaWxlLmtleSArIFwiIVwiICsgdGV4dHVyZXNbaV07XG5cdFx0XHRcdFx0dmFyIGltYWdlID0gbmV3IFBoYXNlci5Mb2FkZXIuRmlsZVR5cGVzLkltYWdlRmlsZSh0aGlzLmxvYWRlciwga2V5LCB1cmwpO1xuXG5cdFx0XHRcdFx0aWYgKCF0aGlzLmxvYWRlci5rZXlFeGlzdHMoaW1hZ2UpKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmFkZFRvTXVsdGlGaWxlKGltYWdlKTtcblx0XHRcdFx0XHRcdHRoaXMubG9hZGVyLmFkZEZpbGUoaW1hZ2UpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGFkZFRvQ2FjaGUgKCkge1xuXHRcdGlmICh0aGlzLmlzUmVhZHlUb1Byb2Nlc3MoKSkge1xuXHRcdFx0bGV0IHRleHR1cmVNYW5hZ2VyID0gdGhpcy5sb2FkZXIudGV4dHVyZU1hbmFnZXI7XG5cdFx0XHRmb3IgKGxldCBmaWxlIG9mIHRoaXMuZmlsZXMpIHtcblx0XHRcdFx0aWYgKGZpbGUudHlwZSA9PSBcImltYWdlXCIpIHtcblx0XHRcdFx0XHRpZiAoIXRleHR1cmVNYW5hZ2VyLmV4aXN0cyhmaWxlLmtleSkpIHtcblx0XHRcdFx0XHRcdHRleHR1cmVNYW5hZ2VyLmFkZEltYWdlKGZpbGUua2V5LCBmaWxlLmRhdGEpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnByZW11bHRpcGxpZWRBbHBoYSA9IHRoaXMucHJlbXVsdGlwbGllZEFscGhhID8/IChmaWxlLmRhdGEuaW5kZXhPZihcInBtYTogdHJ1ZVwiKSA+PSAwIHx8IGZpbGUuZGF0YS5pbmRleE9mKFwicG1hOnRydWVcIikgPj0gMCk7XG5cdFx0XHRcdFx0ZmlsZS5kYXRhID0ge1xuXHRcdFx0XHRcdFx0ZGF0YTogZmlsZS5kYXRhLFxuXHRcdFx0XHRcdFx0cHJlbXVsdGlwbGllZEFscGhhOiB0aGlzLnByZW11bHRpcGxpZWRBbHBoYSxcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdGZpbGUuYWRkVG9DYWNoZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG4iXX0= \ No newline at end of file diff --git a/spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs b/spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs new file mode 100644 index 000000000..2cbfe4079 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs @@ -0,0 +1,15405 @@ +var __defProp = Object.defineProperty; +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; +}; + +// spine-phaser-v3/src/require-shim.ts +if (typeof window !== "undefined" && window.Phaser) { + let prevRequire = window.require; + window.require = (x) => { + if (prevRequire) + return prevRequire(x); + else if (x === "Phaser") + return window.Phaser; + }; +} + +// spine-phaser-v3/src/SpinePlugin.ts +import * as Phaser2 from "Phaser"; + +// spine-phaser-v3/src/keys.ts +var SPINE_SKELETON_FILE_CACHE_KEY = "esotericsoftware.spine.skeletonFile.cache"; +var SPINE_ATLAS_CACHE_KEY = "esotericsoftware.spine.atlas.cache"; +var SPINE_SKELETON_DATA_FILE_TYPE = "spineSkeletonData"; +var SPINE_ATLAS_FILE_TYPE = "spineAtlasData"; +var SPINE_GAME_OBJECT_TYPE = "spine"; + +// spine-core/src/Utils.ts +var IntSet = class { + array = new Array(); + add(value) { + let contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + } + contains(value) { + return this.array[value | 0] != void 0; + } + remove(value) { + this.array[value | 0] = void 0; + } + clear() { + this.array.length = 0; + } +}; +var StringSet = class { + entries = {}; + size = 0; + add(value) { + let contains = this.entries[value]; + this.entries[value] = true; + if (!contains) { + this.size++; + return true; + } + return false; + } + addAll(values) { + let oldSize = this.size; + for (var i = 0, n = values.length; i < n; i++) + this.add(values[i]); + return oldSize != this.size; + } + contains(value) { + return this.entries[value]; + } + clear() { + this.entries = {}; + this.size = 0; + } +}; +var _Color = class { + constructor(r = 0, g = 0, b = 0, a = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + set(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this.clamp(); + } + setFromColor(c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + setFromString(hex) { + hex = hex.charAt(0) == "#" ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255; + this.g = parseInt(hex.substr(2, 2), 16) / 255; + this.b = parseInt(hex.substr(4, 2), 16) / 255; + this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + return this; + } + add(r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + return this.clamp(); + } + clamp() { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + } + static rgba8888ToColor(color, value) { + color.r = ((value & 4278190080) >>> 24) / 255; + color.g = ((value & 16711680) >>> 16) / 255; + color.b = ((value & 65280) >>> 8) / 255; + color.a = (value & 255) / 255; + } + static rgb888ToColor(color, value) { + color.r = ((value & 16711680) >>> 16) / 255; + color.g = ((value & 65280) >>> 8) / 255; + color.b = (value & 255) / 255; + } + toRgb888() { + const hex = (x) => ("0" + (x * 255).toString(16)).slice(-2); + return Number("0x" + hex(this.r) + hex(this.g) + hex(this.b)); + } + static fromString(hex) { + return new _Color().setFromString(hex); + } +}; +var Color = _Color; +__publicField(Color, "WHITE", new _Color(1, 1, 1, 1)); +__publicField(Color, "RED", new _Color(1, 0, 0, 1)); +__publicField(Color, "GREEN", new _Color(0, 1, 0, 1)); +__publicField(Color, "BLUE", new _Color(0, 0, 1, 1)); +__publicField(Color, "MAGENTA", new _Color(1, 0, 1, 1)); +var _MathUtils = class { + static clamp(value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + } + static cosDeg(degrees) { + return Math.cos(degrees * _MathUtils.degRad); + } + static sinDeg(degrees) { + return Math.sin(degrees * _MathUtils.degRad); + } + static atan2Deg(y, x) { + return Math.atan2(y, x) * _MathUtils.degRad; + } + static signum(value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + } + static toInt(x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + } + static cbrt(x) { + let y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + } + static randomTriangular(min, max) { + return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + } + static randomTriangularWith(min, max, mode) { + let u = Math.random(); + let d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + } + static isPowerOfTwo(value) { + return value && (value & value - 1) === 0; + } +}; +var MathUtils = _MathUtils; +__publicField(MathUtils, "PI", 3.1415927); +__publicField(MathUtils, "PI2", _MathUtils.PI * 2); +__publicField(MathUtils, "invPI2", 1 / _MathUtils.PI2); +__publicField(MathUtils, "radiansToDegrees", 180 / _MathUtils.PI); +__publicField(MathUtils, "radDeg", _MathUtils.radiansToDegrees); +__publicField(MathUtils, "degreesToRadians", _MathUtils.PI / 180); +__publicField(MathUtils, "degRad", _MathUtils.degreesToRadians); +var Interpolation = class { + apply(start, end, a) { + return start + (end - start) * this.applyInternal(a); + } +}; +var Pow = class extends Interpolation { + power = 2; + constructor(power) { + super(); + this.power = power; + } + applyInternal(a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + } +}; +var PowOut = class extends Pow { + constructor(power) { + super(power); + } + applyInternal(a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + } +}; +var _Utils = class { + static arrayCopy(source, sourceStart, dest, destStart, numElements) { + for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + } + static arrayFill(array, fromIndex, toIndex, value) { + for (let i = fromIndex; i < toIndex; i++) + array[i] = value; + } + static setArraySize(array, size, value = 0) { + let oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (let i = oldSize; i < size; i++) + array[i] = value; + } + return array; + } + static ensureArrayCapacity(array, size, value = 0) { + if (array.length >= size) + return array; + return _Utils.setArraySize(array, size, value); + } + static newArray(size, defaultValue) { + let array = new Array(size); + for (let i = 0; i < size; i++) + array[i] = defaultValue; + return array; + } + static newFloatArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Float32Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static newShortArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Int16Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static toFloatArray(array) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + } + static toSinglePrecision(value) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + } + // This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109 + static webkit602BugfixHelper(alpha, blend) { + } + static contains(array, element, identity = true) { + for (var i = 0; i < array.length; i++) + if (array[i] == element) + return true; + return false; + } + static enumValue(type, name) { + return type[name[0].toUpperCase() + name.slice(1)]; + } +}; +var Utils = _Utils; +__publicField(Utils, "SUPPORTS_TYPED_ARRAYS", typeof Float32Array !== "undefined"); +var DebugUtils = class { + static logBones(skeleton) { + for (let i = 0; i < skeleton.bones.length; i++) { + let bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + } +}; +var Pool = class { + items = new Array(); + instantiator; + constructor(instantiator) { + this.instantiator = instantiator; + } + obtain() { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + } + free(item) { + if (item.reset) + item.reset(); + this.items.push(item); + } + freeAll(items) { + for (let i = 0; i < items.length; i++) + this.free(items[i]); + } + clear() { + this.items.length = 0; + } +}; +var Vector2 = class { + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + set(x, y) { + this.x = x; + this.y = y; + return this; + } + length() { + let x = this.x; + let y = this.y; + return Math.sqrt(x * x + y * y); + } + normalize() { + let len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + } +}; +var TimeKeeper = class { + maxDelta = 0.064; + framesPerSecond = 0; + delta = 0; + totalTime = 0; + lastTime = Date.now() / 1e3; + frameCount = 0; + frameTime = 0; + update() { + let now = Date.now() / 1e3; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + } +}; +var WindowedMean = class { + values; + addedValues = 0; + lastValue = 0; + mean = 0; + dirty = true; + constructor(windowSize = 32) { + this.values = new Array(windowSize); + } + hasEnoughData() { + return this.addedValues >= this.values.length; + } + addValue(value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + } + getMean() { + if (this.hasEnoughData()) { + if (this.dirty) { + let mean = 0; + for (let i = 0; i < this.values.length; i++) + mean += this.values[i]; + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + return 0; + } +}; + +// spine-core/src/attachments/Attachment.ts +var Attachment = class { + name; + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } +}; +var _VertexAttachment = class extends Attachment { + /** The unique ID for this attachment. */ + id = _VertexAttachment.nextID++; + /** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting + * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null + * if this attachment has no weights. */ + bones = null; + /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y` + * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting + * each vertex. */ + vertices = []; + /** The maximum number of world vertex values that can be output by + * {@link #computeWorldVertices()} using the `count` parameter. */ + worldVerticesLength = 0; + /** Timelines for the timeline attachment are also applied to this attachment. + * May be null if no attachment-specific timelines should be applied. */ + timelineAttachment = this; + constructor(name) { + super(name); + } + /** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is + * not empty, it is used to deform the vertices. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. + * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y. + * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`. + * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` * + * `stride` / 2. + * @param offset The `worldVertices` index to begin writing values. + * @param stride The number of `worldVertices` entries between the value pairs written. */ + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + count = offset + (count >> 1) * stride; + let skeleton = slot.bone.skeleton; + let deformArray = slot.deform; + let vertices = this.vertices; + let bones = this.bones; + if (!bones) { + if (deformArray.length > 0) + vertices = deformArray; + let bone = slot.bone; + let x = bone.worldX; + let y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) { + let vx = vertices[v2], vy = vertices[v2 + 1]; + worldVertices2[w] = vx * a + vy * b + x; + worldVertices2[w + 1] = vx * c + vy * d + y; + } + return; + } + let v = 0, skip = 0; + for (let i = 0; i < start; i += 2) { + let n = bones[v]; + v += n + 1; + skip += n; + } + let skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (let w = offset, b = skip * 3; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } else { + let deform = deformArray; + for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } + } + /** Does not copy id (generated) or name (set on construction). **/ + copyTo(attachment) { + if (this.bones) { + attachment.bones = new Array(this.bones.length); + Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } else + attachment.bones = null; + if (this.vertices) { + attachment.vertices = Utils.newFloatArray(this.vertices.length); + Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.timelineAttachment = this.timelineAttachment; + } +}; +var VertexAttachment = _VertexAttachment; +__publicField(VertexAttachment, "nextID", 0); + +// spine-core/src/attachments/Sequence.ts +var _Sequence = class { + id = _Sequence.nextID(); + regions; + start = 0; + digits = 0; + /** The index of the region to show for the setup pose. */ + setupIndex = 0; + constructor(count) { + this.regions = new Array(count); + } + copy() { + let copy = new _Sequence(this.regions.length); + Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length); + copy.start = this.start; + copy.digits = this.digits; + copy.setupIndex = this.setupIndex; + return copy; + } + apply(slot, attachment) { + let index = slot.sequenceIndex; + if (index == -1) + index = this.setupIndex; + if (index >= this.regions.length) + index = this.regions.length - 1; + let region = this.regions[index]; + if (attachment.region != region) { + attachment.region = region; + attachment.updateRegion(); + } + } + getPath(basePath, index) { + let result = basePath; + let frame = (this.start + index).toString(); + for (let i = this.digits - frame.length; i > 0; i--) + result += "0"; + result += frame; + return result; + } + static nextID() { + return _Sequence._nextID++; + } +}; +var Sequence = _Sequence; +__publicField(Sequence, "_nextID", 0); +var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => { + SequenceMode2[SequenceMode2["hold"] = 0] = "hold"; + SequenceMode2[SequenceMode2["once"] = 1] = "once"; + SequenceMode2[SequenceMode2["loop"] = 2] = "loop"; + SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong"; + SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse"; + SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse"; + SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse"; + return SequenceMode2; +})(SequenceMode || {}); +var SequenceModeValues = [ + 0 /* hold */, + 1 /* once */, + 2 /* loop */, + 3 /* pingpong */, + 4 /* onceReverse */, + 5 /* loopReverse */, + 6 /* pingpongReverse */ +]; + +// spine-core/src/Animation.ts +var Animation = class { + /** The animation's name, which is unique across all animations in the skeleton. */ + name; + timelines = []; + timelineIds = new StringSet(); + /** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */ + duration; + constructor(name, timelines, duration) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + this.setTimelines(timelines); + this.duration = duration; + } + setTimelines(timelines) { + if (!timelines) + throw new Error("timelines cannot be null."); + this.timelines = timelines; + this.timelineIds.clear(); + for (var i = 0; i < timelines.length; i++) + this.timelineIds.addAll(timelines[i].getPropertyIds()); + } + hasTimeline(ids) { + for (let i = 0; i < ids.length; i++) + if (this.timelineIds.contains(ids[i])) + return true; + return false; + } + /** Applies all the animation's timelines to the specified skeleton. + * + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. + * @param loop If true, the animation repeats after {@link #getDuration()}. + * @param events May be null to ignore fired events. */ + apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + let timelines = this.timelines; + for (let i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + } +}; +var MixBlend = /* @__PURE__ */ ((MixBlend2) => { + MixBlend2[MixBlend2["setup"] = 0] = "setup"; + MixBlend2[MixBlend2["first"] = 1] = "first"; + MixBlend2[MixBlend2["replace"] = 2] = "replace"; + MixBlend2[MixBlend2["add"] = 3] = "add"; + return MixBlend2; +})(MixBlend || {}); +var MixDirection = /* @__PURE__ */ ((MixDirection2) => { + MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn"; + MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut"; + return MixDirection2; +})(MixDirection || {}); +var Property = { + rotate: 0, + x: 1, + y: 2, + scaleX: 3, + scaleY: 4, + shearX: 5, + shearY: 6, + inherit: 7, + rgb: 8, + alpha: 9, + rgb2: 10, + attachment: 11, + deform: 12, + event: 13, + drawOrder: 14, + ikConstraint: 15, + transformConstraint: 16, + pathConstraintPosition: 17, + pathConstraintSpacing: 18, + pathConstraintMix: 19, + physicsConstraintInertia: 20, + physicsConstraintStrength: 21, + physicsConstraintDamping: 22, + physicsConstraintMass: 23, + physicsConstraintWind: 24, + physicsConstraintGravity: 25, + physicsConstraintMix: 26, + physicsConstraintReset: 27, + sequence: 28 +}; +var Timeline = class { + propertyIds; + frames; + constructor(frameCount, propertyIds) { + this.propertyIds = propertyIds; + this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries()); + } + getPropertyIds() { + return this.propertyIds; + } + getFrameEntries() { + return 1; + } + getFrameCount() { + return this.frames.length / this.getFrameEntries(); + } + getDuration() { + return this.frames[this.frames.length - this.getFrameEntries()]; + } + static search1(frames, time) { + let n = frames.length; + for (let i = 1; i < n; i++) + if (frames[i] > time) + return i - 1; + return n - 1; + } + static search(frames, time, step) { + let n = frames.length; + for (let i = step; i < n; i += step) + if (frames[i] > time) + return i - step; + return n - step; + } +}; +var CurveTimeline = class extends Timeline { + curves; + // type, x, y, ... + constructor(frameCount, bezierCount, propertyIds) { + super(frameCount, propertyIds); + this.curves = Utils.newFloatArray( + frameCount + bezierCount * 18 + /*BEZIER_SIZE*/ + ); + this.curves[frameCount - 1] = 1; + } + /** Sets the specified key frame to linear interpolation. */ + setLinear(frame) { + this.curves[frame] = 0; + } + /** Sets the specified key frame to stepped interpolation. */ + setStepped(frame) { + this.curves[frame] = 1; + } + /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger + * than the actual number of Bezier curves. */ + shrink(bezierCount) { + let size = this.getFrameCount() + bezierCount * 18; + if (this.curves.length > size) { + let newCurves = Utils.newFloatArray(size); + Utils.arrayCopy(this.curves, 0, newCurves, 0, size); + this.curves = newCurves; + } + } + /** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than + * one curve per frame. + * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified + * in the constructor), inclusive. + * @param frame Between 0 and frameCount - 1, inclusive. + * @param value The index of the value for this frame that this curve is used for. + * @param time1 The time for the first key. + * @param value1 The value for the first key. + * @param cx1 The time for the first Bezier handle. + * @param cy1 The value for the first Bezier handle. + * @param cx2 The time of the second Bezier handle. + * @param cy2 The value for the second Bezier handle. + * @param time2 The time for the second key. + * @param value2 The value for the second key. */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = value1 + dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + /** Returns the Bezier interpolated value for the specified time. + * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time. + * @param valueOffset The offset from frameIndex to the value this curve is used for. + * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */ + getBezierValue(time, frameIndex, valueOffset, i) { + let curves = this.curves; + if (curves[i] > time) { + let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + frameIndex += this.getFrameEntries(); + let x = curves[n - 2], y = curves[n - 1]; + return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); + } +}; +var CurveTimeline1 = class extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId) { + super(frameCount, bezierCount, [propertyId]); + } + getFrameEntries() { + return 2; + } + /** Sets the time and value for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value) { + frame <<= 1; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE*/ + ] = value; + } + /** Returns the interpolated value for the specified time. */ + getCurveValue(time) { + let frames = this.frames; + let i = frames.length - 2; + for (let ii = 2; ii <= i; ii += 2) { + if (frames[ii] > time) { + i = ii - 2; + break; + } + } + let curveType = this.curves[i >> 1]; + switch (curveType) { + case 0: + let before = frames[i], value = frames[ + i + 1 + /*VALUE*/ + ]; + return value + (time - before) / (frames[ + i + 2 + /*ENTRIES*/ + ] - before) * (frames[ + i + 2 + 1 + /*VALUE*/ + ] - value); + case 1: + return frames[ + i + 1 + /*VALUE*/ + ]; + } + return this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + } + getRelativeValue(time, alpha, blend, current, setup) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + return setup + value * alpha; + case 1 /* first */: + case 2 /* replace */: + value += setup - current; + } + return current + value * alpha; + } + getAbsoluteValue(time, alpha, blend, current, setup) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time); + if (blend == 0 /* setup */) + return setup + (value - setup) * alpha; + return current + (value - current) * alpha; + } + getAbsoluteValue2(time, alpha, blend, current, setup, value) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + if (blend == 0 /* setup */) + return setup + (value - setup) * alpha; + return current + (value - current) * alpha; + } + getScaleValue(time, alpha, blend, direction, current, setup) { + const frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time) * setup; + if (alpha == 1) { + if (blend == 3 /* add */) + return current + value - setup; + return value; + } + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha; + case 1 /* first */: + case 2 /* replace */: + return current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha; + } + } else { + let s = 0; + switch (blend) { + case 0 /* setup */: + s = Math.abs(setup) * MathUtils.signum(value); + return s + (value - s) * alpha; + case 1 /* first */: + case 2 /* replace */: + s = Math.abs(current) * MathUtils.signum(value); + return s + (value - s) * alpha; + } + } + return current + (value - setup) * alpha; + } +}; +var CurveTimeline2 = class extends CurveTimeline { + /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. + * @param propertyIds Unique identifiers for the properties the timeline modifies. */ + constructor(frameCount, bezierCount, propertyId1, propertyId2) { + super(frameCount, bezierCount, [propertyId1, propertyId2]); + } + getFrameEntries() { + return 3; + } + /** Sets the time and values for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value1, value2) { + frame *= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE1*/ + ] = value1; + this.frames[ + frame + 2 + /*VALUE2*/ + ] = value2; + } +}; +var RotateTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.rotate + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.rotation = this.getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation); + } +}; +var TranslateTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.x + "|" + boneIndex, + Property.y + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case 1 /* first */: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3 /* add */: + bone.x += x * alpha; + bone.y += y * alpha; + } + } +}; +var TranslateXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.x + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.x = this.getRelativeValue(time, alpha, blend, bone.x, bone.data.x); + } +}; +var TranslateYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.y + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.y = this.getRelativeValue(time, alpha, blend, bone.y, bone.data.y); + } +}; +var ScaleTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.scaleX + "|" + boneIndex, + Property.scaleY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case 1 /* first */: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let x, y; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + x *= bone.data.scaleX; + y *= bone.data.scaleY; + if (alpha == 1) { + if (blend == 3 /* add */) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } else { + bone.scaleX = x; + bone.scaleY = y; + } + } else { + let bx = 0, by = 0; + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0 /* setup */: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } +}; +var ScaleXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.scaleX = this.getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX); + } +}; +var ScaleYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.scaleY = this.getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY); + } +}; +var ShearTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.shearX + "|" + boneIndex, + Property.shearY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case 1 /* first */: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3 /* add */: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + } +}; +var ShearXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.shearX = this.getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX); + } +}; +var ShearYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.shearY = this.getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY); + } +}; +var InheritTimeline = class extends Timeline { + boneIndex = 0; + constructor(frameCount, boneIndex) { + super(frameCount, [Property.inherit + "|" + boneIndex]); + this.boneIndex = boneIndex; + } + getFrameEntries() { + return 2; + } + /** Sets the transform mode for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, inherit) { + frame *= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*INHERIT*/ + ] = inherit; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + bone.inherit = bone.data.inherit; + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + bone.inherit = bone.data.inherit; + return; + } + bone.inherit = this.frames[ + Timeline.search( + frames, + time, + 2 + /*ENTRIES*/ + ) + 1 + /*INHERIT*/ + ]; + } +}; +var RGBATimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 5; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b, a) { + frame *= 5; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.setFromColor(setup); + return; + case 1 /* first */: + color.add( + (setup.r - color.r) * alpha, + (setup.g - color.g) * alpha, + (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha + ); + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + let i = Timeline.search( + frames, + time, + 5 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 5 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + let t = (time - before) / (frames[ + i + 5 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 5 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 5 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 5 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 5 + 4 + /*A*/ + ] - a) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == 0 /* setup */) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + } +}; +var RGBTimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 4; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b) { + frame <<= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + return; + case 1 /* first */: + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 4 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 4 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 4 + 3 + /*B*/ + ] - b) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + color.r = r; + color.g = g; + color.b = b; + } else { + if (blend == 0 /* setup */) { + let setup = slot.data.color; + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + } + color.r += (r - color.r) * alpha; + color.g += (g - color.g) * alpha; + color.b += (b - color.b) * alpha; + } + } +}; +var AlphaTimeline = class extends CurveTimeline1 { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, Property.alpha + "|" + slotIndex); + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let color = slot.color; + if (time < this.frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.a = setup.a; + return; + case 1 /* first */: + color.a += (setup.a - color.a) * alpha; + } + return; + } + let a = this.getCurveValue(time); + if (alpha == 1) + color.a = a; + else { + if (blend == 0 /* setup */) + color.a = slot.data.color.a; + color.a += (a - color.a) * alpha; + } + } +}; +var RGBA2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 8; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, a, r2, g2, b2) { + frame <<= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + this.frames[ + frame + 5 + /*R2*/ + ] = r2; + this.frames[ + frame + 6 + /*G2*/ + ] = g2; + this.frames[ + frame + 7 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.setFromColor(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.add( + (setupLight.r - light.r) * alpha, + (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha + ); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 8 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 3]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 8 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 8 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 8 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 8 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 8 + 4 + /*A*/ + ] - a) * t; + r2 += (frames[ + i + 8 + 5 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 8 + 6 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 8 + 7 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 7, + curveType + 18 * 6 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.set(r, g, b, a); + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + light.setFromColor(slot.data.color); + let setupDark = slot.data.darkColor; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } +}; +var RGB2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 7; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, r2, g2, b2) { + frame *= 7; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*R2*/ + ] = r2; + this.frames[ + frame + 5 + /*G2*/ + ] = g2; + this.frames[ + frame + 6 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 7 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 7 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 7 + 3 + /*B*/ + ] - b) * t; + r2 += (frames[ + i + 7 + 4 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 7 + 5 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 7 + 6 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.r = r; + light.g = g; + light.b = b; + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.r += (r - light.r) * alpha; + light.g += (g - light.g) * alpha; + light.b += (b - light.b) * alpha; + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } +}; +var AttachmentTimeline = class extends Timeline { + slotIndex = 0; + /** The attachment name for each key frame. May contain null values to clear the attachment. */ + attachmentNames; + constructor(frameCount, slotIndex) { + super(frameCount, [ + Property.attachment + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + this.attachmentNames = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the attachment name for the specified key frame. */ + setFrame(frame, time, attachmentName) { + this.frames[frame] = time; + this.attachmentNames[frame] = attachmentName; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]); + } + setAttachment(skeleton, slot, attachmentName) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + } +}; +var DeformTimeline = class extends CurveTimeline { + slotIndex = 0; + /** The attachment that will be deformed. */ + attachment; + /** The vertices for each key frame. */ + vertices; + constructor(frameCount, bezierCount, slotIndex, attachment) { + super(frameCount, bezierCount, [ + Property.deform + "|" + slotIndex + "|" + attachment.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + this.vertices = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the vertices for the specified key frame. + * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ + setFrame(frame, time, vertices) { + this.frames[frame] = time; + this.vertices[frame] = vertices; + } + /** @param value1 Ignored (0 is used for a deform timeline). + * @param value2 Ignored (1 is used for a deform timeline). */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getCurvePercent(time, frame) { + let curves = this.curves; + let i = curves[frame]; + switch (i) { + case 0: + let x2 = this.frames[frame]; + return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2); + case 1: + return 0; + } + i -= 2; + if (curves[i] > time) { + let x2 = this.frames[frame]; + return curves[i + 1] * (time - x2) / (curves[i] - x2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + let x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.getAttachment(); + if (!slotAttachment) + return; + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != this.attachment) + return; + let deform = slot.deform; + if (deform.length == 0) + blend = 0 /* setup */; + let vertices = this.vertices; + let vertexCount = vertices[0].length; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + deform.length = 0; + return; + case 1 /* first */: + if (alpha == 1) { + deform.length = 0; + return; + } + deform.length = vertexCount; + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + return; + } + deform.length = vertexCount; + if (time >= frames[frames.length - 1]) { + let lastVertices = vertices[frames.length - 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] - setupVertices[i2]; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2]; + } + } else + Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount); + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let setup = setupVertices[i2]; + deform[i2] = setup + (lastVertices[i2] - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] = lastVertices[i2] * alpha; + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - deform[i2]) * alpha; + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] * alpha; + } + } + } + return; + } + let frame = Timeline.search1(frames, time); + let percent = this.getCurvePercent(time, frame); + let prevVertices = vertices[frame]; + let nextVertices = vertices[frame + 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2], setup = setupVertices[i2]; + deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha; + } + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + } + } + } +}; +var _EventTimeline = class extends Timeline { + /** The event for each key frame. */ + events; + constructor(frameCount) { + super(frameCount, _EventTimeline.propertyIds); + this.events = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the event for the specified key frame. */ + setFrame(frame, event) { + this.frames[frame] = event.time; + this.events[frame] = event; + } + /** Fires events for frames > `lastTime` and <= `time`. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (!firedEvents) + return; + let frames = this.frames; + let frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + let i = 0; + if (lastTime < frames[0]) + i = 0; + else { + i = Timeline.search1(frames, lastTime) + 1; + let frameTime = frames[i]; + while (i > 0) { + if (frames[i - 1] != frameTime) + break; + i--; + } + } + for (; i < frameCount && time >= frames[i]; i++) + firedEvents.push(this.events[i]); + } +}; +var EventTimeline = _EventTimeline; +__publicField(EventTimeline, "propertyIds", ["" + Property.event]); +var _DrawOrderTimeline = class extends Timeline { + /** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */ + drawOrders; + constructor(frameCount) { + super(frameCount, _DrawOrderTimeline.propertyIds); + this.drawOrders = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the draw order for the specified key frame. + * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose + * draw order. */ + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + let idx = Timeline.search1(this.frames, time); + let drawOrderToSetupIndex = this.drawOrders[idx]; + if (!drawOrderToSetupIndex) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + else { + let drawOrder = skeleton.drawOrder; + let slots = skeleton.slots; + for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + } +}; +var DrawOrderTimeline = _DrawOrderTimeline; +__publicField(DrawOrderTimeline, "propertyIds", ["" + Property.drawOrder]); +var IkConstraintTimeline = class extends CurveTimeline { + /** The index of the IK constraint in {@link Skeleton#getIkConstraints()} that will be changed when this timeline is applied */ + constraintIndex = 0; + constructor(frameCount, bezierCount, ikConstraintIndex) { + super(frameCount, bezierCount, [ + Property.ikConstraint + "|" + ikConstraintIndex + ]); + this.constraintIndex = ikConstraintIndex; + } + getFrameEntries() { + return 6; + } + /** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */ + setFrame(frame, time, mix, softness, bendDirection, compress, stretch) { + frame *= 6; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*MIX*/ + ] = mix; + this.frames[ + frame + 2 + /*SOFTNESS*/ + ] = softness; + this.frames[ + frame + 3 + /*BEND_DIRECTION*/ + ] = bendDirection; + this.frames[ + frame + 4 + /*COMPRESS*/ + ] = compress ? 1 : 0; + this.frames[ + frame + 5 + /*STRETCH*/ + ] = stretch ? 1 : 0; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.ikConstraints[this.constraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case 1 /* first */: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.softness += (constraint.data.softness - constraint.softness) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + let mix = 0, softness = 0; + let i = Timeline.search( + frames, + time, + 6 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 6 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + let t = (time - before) / (frames[ + i + 6 + /*ENTRIES*/ + ] - before); + mix += (frames[ + i + 6 + 1 + /*MIX*/ + ] - mix) * t; + softness += (frames[ + i + 6 + 2 + /*SOFTNESS*/ + ] - softness) * t; + break; + case 1: + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + break; + default: + mix = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + softness = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha; + if (direction == 1 /* mixOut */) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } else { + constraint.mix += (mix - constraint.mix) * alpha; + constraint.softness += (softness - constraint.softness) * alpha; + if (direction == 0 /* mixIn */) { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } + } +}; +var TransformConstraintTimeline = class extends CurveTimeline { + /** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, transformConstraintIndex) { + super(frameCount, bezierCount, [ + Property.transformConstraint + "|" + transformConstraintIndex + ]); + this.constraintIndex = transformConstraintIndex; + } + getFrameEntries() { + return 7; + } + /** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */ + setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) { + let frames = this.frames; + frame *= 7; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + frames[ + frame + 4 + /*SCALEX*/ + ] = mixScaleX; + frames[ + frame + 5 + /*SCALEY*/ + ] = mixScaleY; + frames[ + frame + 6 + /*SHEARY*/ + ] = mixShearY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.transformConstraints[this.constraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + let data = constraint.data; + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + return; + case 1 /* first */: + constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (data.mixX - constraint.mixX) * alpha; + constraint.mixY += (data.mixY - constraint.mixY) * alpha; + constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha; + } + return; + } + let rotate, x, y, scaleX, scaleY, shearY; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 7 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 7 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 7 + 3 + /*Y*/ + ] - y) * t; + scaleX += (frames[ + i + 7 + 4 + /*SCALEX*/ + ] - scaleX) * t; + scaleY += (frames[ + i + 7 + 5 + /*SCALEY*/ + ] - scaleY) * t; + shearY += (frames[ + i + 7 + 6 + /*SHEARY*/ + ] - shearY) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + scaleX = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + scaleY = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + shearY = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha; + constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha; + constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (shearY - constraint.mixShearY) * alpha; + } + } +}; +var PathConstraintPositionTimeline = class extends CurveTimeline1 { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex); + this.constraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (constraint.active) + constraint.position = this.getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position); + } +}; +var PathConstraintSpacingTimeline = class extends CurveTimeline1 { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex); + this.constraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (constraint.active) + constraint.spacing = this.getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing); + } +}; +var PathConstraintMixTimeline = class extends CurveTimeline { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, [ + Property.pathConstraintMix + "|" + pathConstraintIndex + ]); + this.constraintIndex = pathConstraintIndex; + } + getFrameEntries() { + return 4; + } + setFrame(frame, time, mixRotate, mixX, mixY) { + let frames = this.frames; + frame <<= 2; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = constraint.data.mixRotate; + constraint.mixX = constraint.data.mixX; + constraint.mixY = constraint.data.mixY; + return; + case 1 /* first */: + constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha; + constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha; + } + return; + } + let rotate, x, y; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 4 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 4 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 4 + 3 + /*Y*/ + ] - y) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + } + } +}; +var PhysicsConstraintTimeline = class extends CurveTimeline1 { + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline + * is applied, or -1 if all physics constraints in the skeleton will be changed. */ + constraintIndex = 0; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, bezierCount, physicsConstraintIndex, property) { + super(frameCount, bezierCount, property + "|" + physicsConstraintIndex); + this.constraintIndex = physicsConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint; + if (this.constraintIndex == -1) { + const value = time >= this.frames[0] ? this.getCurveValue(time) : 0; + for (const constraint2 of skeleton.physicsConstraints) { + if (constraint2.active && this.global(constraint2.data)) + this.set(constraint2, this.getAbsoluteValue2(time, alpha, blend, this.get(constraint2), this.setup(constraint2), value)); + } + } else { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (constraint.active) + this.set(constraint, this.getAbsoluteValue(time, alpha, blend, this.get(constraint), this.setup(constraint))); + } + } +}; +var PhysicsConstraintInertiaTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); + } + setup(constraint) { + return constraint.data.inertia; + } + get(constraint) { + return constraint.inertia; + } + set(constraint, value) { + constraint.inertia = value; + } + global(constraint) { + return constraint.inertiaGlobal; + } +}; +var PhysicsConstraintStrengthTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); + } + setup(constraint) { + return constraint.data.strength; + } + get(constraint) { + return constraint.strength; + } + set(constraint, value) { + constraint.strength = value; + } + global(constraint) { + return constraint.strengthGlobal; + } +}; +var PhysicsConstraintDampingTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); + } + setup(constraint) { + return constraint.data.damping; + } + get(constraint) { + return constraint.damping; + } + set(constraint, value) { + constraint.damping = value; + } + global(constraint) { + return constraint.dampingGlobal; + } +}; +var PhysicsConstraintMassTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); + } + setup(constraint) { + return 1 / constraint.data.massInverse; + } + get(constraint) { + return 1 / constraint.massInverse; + } + set(constraint, value) { + constraint.massInverse = 1 / value; + } + global(constraint) { + return constraint.massGlobal; + } +}; +var PhysicsConstraintWindTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); + } + setup(constraint) { + return constraint.data.wind; + } + get(constraint) { + return constraint.wind; + } + set(constraint, value) { + constraint.wind = value; + } + global(constraint) { + return constraint.windGlobal; + } +}; +var PhysicsConstraintGravityTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); + } + setup(constraint) { + return constraint.data.gravity; + } + get(constraint) { + return constraint.gravity; + } + set(constraint, value) { + constraint.gravity = value; + } + global(constraint) { + return constraint.gravityGlobal; + } +}; +var PhysicsConstraintMixTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); + } + setup(constraint) { + return constraint.data.mix; + } + get(constraint) { + return constraint.mix; + } + set(constraint, value) { + constraint.mix = value; + } + global(constraint) { + return constraint.mixGlobal; + } +}; +var _PhysicsConstraintResetTimeline = class extends Timeline { + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is + * applied, or -1 if all physics constraints in the skeleton will be reset. */ + constraintIndex; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, physicsConstraintIndex) { + super(frameCount, _PhysicsConstraintResetTimeline.propertyIds); + this.constraintIndex = physicsConstraintIndex; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. */ + setFrame(frame, time) { + this.frames[frame] = time; + } + /** Resets the physics constraint when frames > lastTime and <= time. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint; + if (this.constraintIndex != -1) { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (!constraint.active) + return; + } + const frames = this.frames; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frames.length - 1]) + return; + if (time < frames[0]) + return; + if (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) { + if (constraint != null) + constraint.reset(); + else { + for (const constraint2 of skeleton.physicsConstraints) { + if (constraint2.active) + constraint2.reset(); + } + } + } + } +}; +var PhysicsConstraintResetTimeline = _PhysicsConstraintResetTimeline; +__publicField(PhysicsConstraintResetTimeline, "propertyIds", [Property.physicsConstraintReset.toString()]); +var _SequenceTimeline = class extends Timeline { + slotIndex; + attachment; + constructor(frameCount, slotIndex, attachment) { + super(frameCount, [ + Property.sequence + "|" + slotIndex + "|" + attachment.sequence.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + } + getFrameEntries() { + return _SequenceTimeline.ENTRIES; + } + getSlotIndex() { + return this.slotIndex; + } + getAttachment() { + return this.attachment; + } + /** Sets the time, mode, index, and frame time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time Seconds between frames. */ + setFrame(frame, time, mode, index, delay) { + let frames = this.frames; + frame *= _SequenceTimeline.ENTRIES; + frames[frame] = time; + frames[frame + _SequenceTimeline.MODE] = mode | index << 4; + frames[frame + _SequenceTimeline.DELAY] = delay; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.attachment; + let attachment = this.attachment; + if (slotAttachment != attachment) { + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != attachment) + return; + } + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + slot.sequenceIndex = -1; + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + slot.sequenceIndex = -1; + return; + } + let i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES); + let before = frames[i]; + let modeAndIndex = frames[i + _SequenceTimeline.MODE]; + let delay = frames[i + _SequenceTimeline.DELAY]; + if (!this.attachment.sequence) + return; + let index = modeAndIndex >> 4, count = this.attachment.sequence.regions.length; + let mode = SequenceModeValues[modeAndIndex & 15]; + if (mode != 0 /* hold */) { + index += (time - before) / delay + 1e-5 | 0; + switch (mode) { + case 1 /* once */: + index = Math.min(count - 1, index); + break; + case 2 /* loop */: + index %= count; + break; + case 3 /* pingpong */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) + index = n - index; + break; + } + case 4 /* onceReverse */: + index = Math.max(count - 1 - index, 0); + break; + case 5 /* loopReverse */: + index = count - 1 - index % count; + break; + case 6 /* pingpongReverse */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) + index = n - index; + } + } + } + slot.sequenceIndex = index; + } +}; +var SequenceTimeline = _SequenceTimeline; +__publicField(SequenceTimeline, "ENTRIES", 3); +__publicField(SequenceTimeline, "MODE", 1); +__publicField(SequenceTimeline, "DELAY", 2); + +// spine-core/src/AnimationState.ts +var _AnimationState = class { + static emptyAnimation() { + return _AnimationState._emptyAnimation; + } + /** The AnimationStateData to look up mix durations. */ + data; + /** The list of tracks that currently have animations, which may contain null entries. */ + tracks = new Array(); + /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower + * or faster. Defaults to 1. + * + * See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */ + timeScale = 1; + unkeyedState = 0; + events = new Array(); + listeners = new Array(); + queue = new EventQueue(this); + propertyIDs = new StringSet(); + animationsChanged = false; + trackEntryPool = new Pool(() => new TrackEntry()); + constructor(data) { + this.data = data; + } + /** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */ + update(delta) { + delta *= this.timeScale; + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let current = tracks[i]; + if (!current) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + let currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + let next = current.next; + if (next) { + let nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } else if (current.trackLast >= current.trackEnd && !current.mixingFrom) { + tracks[i] = null; + this.queue.end(current); + this.clearNext(current); + continue; + } + if (current.mixingFrom && this.updateMixingFrom(current, delta)) { + let from = current.mixingFrom; + current.mixingFrom = null; + if (from) + from.mixingTo = null; + while (from) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + } + /** Returns true when all mixing from entries are complete. */ + updateMixingFrom(to, delta) { + let from = to.mixingFrom; + if (!from) + return true; + let finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) + from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + } + /** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + * animation state can be applied to multiple skeletons to pose them identically. + * @returns True if any animations were applied. */ + apply(skeleton) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + let events = this.events; + let tracks = this.tracks; + let applied = false; + for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) { + let current = tracks[i2]; + if (!current || current.delay > 0) + continue; + applied = true; + let blend = i2 == 0 ? 1 /* first */ : current.mixBlend; + let alpha = current.alpha; + if (current.mixingFrom) + alpha *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && !current.next) + alpha = 0; + let attachments = alpha >= current.alphaAttachmentThreshold; + let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime; + let applyEvents = events; + if (current.reverse) { + applyTime = current.animation.duration - applyTime; + applyEvents = null; + } + let timelines = current.animation.timelines; + let timelineCount = timelines.length; + if (i2 == 0 && alpha == 1 || blend == 3 /* add */) { + if (i2 == 0) + attachments = true; + for (let ii = 0; ii < timelineCount; ii++) { + Utils.webkit602BugfixHelper(alpha, blend); + var timeline = timelines[ii]; + if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments); + else + timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, 0 /* mixIn */); + } + } else { + let timelineMode = current.timelineMode; + let shortestRotation = current.shortestRotation; + let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + current.timelinesRotation.length = timelineCount << 1; + for (let ii = 0; ii < timelineCount; ii++) { + let timeline2 = timelines[ii]; + let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : 0 /* setup */; + if (!shortestRotation && timeline2 instanceof RotateTimeline) { + this.applyRotateTimeline(timeline2, skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1, firstFrame); + } else if (timeline2 instanceof AttachmentTimeline) { + this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, attachments); + } else { + Utils.webkit602BugfixHelper(alpha, blend); + timeline2.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, 0 /* mixIn */); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + var setupState = this.unkeyedState + SETUP; + var slots = skeleton.slots; + for (var i = 0, n = skeleton.slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.attachmentState == setupState) { + var attachmentName = slot.data.attachmentName; + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + } + applyMixingFrom(to, skeleton, blend) { + let from = to.mixingFrom; + if (from.mixingFrom) + this.applyMixingFrom(from, skeleton, blend); + let mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == 1 /* first */) + blend = 0 /* setup */; + } else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + if (blend != 1 /* first */) + blend = from.mixBlend; + } + let attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold; + let timelines = from.animation.timelines; + let timelineCount = timelines.length; + let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; + let events = null; + if (from.reverse) + applyTime = from.animation.duration - applyTime; + else if (mix < from.eventThreshold) + events = this.events; + if (blend == 3 /* add */) { + for (let i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, 1 /* mixOut */); + } else { + let timelineMode = from.timelineMode; + let timelineHoldMix = from.timelineHoldMix; + let shortestRotation = from.shortestRotation; + let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + from.timelinesRotation.length = timelineCount << 1; + from.totalAlpha = 0; + for (let i = 0; i < timelineCount; i++) { + let timeline = timelines[i]; + let direction = 1 /* mixOut */; + let timelineBlend; + let alpha = 0; + switch (timelineMode[i]) { + case SUBSEQUENT: + if (!drawOrder && timeline instanceof DrawOrderTimeline) + continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaMix; + break; + case HOLD_SUBSEQUENT: + timelineBlend = blend; + alpha = alphaHold; + break; + case HOLD_FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaHold; + break; + default: + timelineBlend = 0 /* setup */; + let holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (!shortestRotation && timeline instanceof RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame); + else if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments && alpha >= from.alphaAttachmentThreshold); + else { + Utils.webkit602BugfixHelper(alpha, blend); + if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == 0 /* setup */) + direction = 0 /* mixIn */; + timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + } + applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) { + var slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) + return; + if (time < timeline.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); + } else + this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments); + if (slot.attachmentState <= this.unkeyedState) + slot.attachmentState = this.unkeyedState + SETUP; + } + setAttachment(skeleton, slot, attachmentName, attachments) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + if (attachments) + slot.attachmentState = this.unkeyedState + CURRENT; + } + applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, 0 /* mixIn */); + return; + } + let bone = skeleton.bones[timeline.boneIndex]; + if (!bone.active) + return; + let frames = timeline.frames; + let r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.rotation = bone.data.rotation; + default: + return; + case 1 /* first */: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } else { + r1 = blend == 0 /* setup */ ? bone.data.rotation : bone.rotation; + r2 = bone.data.rotation + timeline.getCurveValue(time); + } + let total = 0, diff = r2 - r1; + diff -= Math.ceil(diff / 360 - 0.5) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + let lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + let loops = lastTotal - lastTotal % 360; + total = diff + loops; + let current = diff >= 0, dir = lastTotal >= 0; + if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) { + if (Math.abs(lastTotal - loops) > 180) { + total += 360 * MathUtils.signum(lastTotal); + dir = current; + } else if (loops != 0) + total -= 360 * MathUtils.signum(lastTotal); + else + dir = current; + } + if (dir != current) + total += 360 * MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone.rotation = r1 + total * alpha; + } + queueEvents(entry, animationTime) { + let animationStart = entry.animationStart, animationEnd = entry.animationEnd; + let duration = animationEnd - animationStart; + let trackLastWrapped = entry.trackLast % duration; + let events = this.events; + let i = 0, n = events.length; + for (; i < n; i++) { + let event = events[i]; + if (event.time < trackLastWrapped) + break; + if (event.time > animationEnd) + continue; + this.queue.event(entry, event); + } + let complete = false; + if (entry.loop) { + if (duration == 0) + complete = true; + else { + const cycles = Math.floor(entry.trackTime / duration); + complete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration); + } + } else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + let event = events[i]; + if (event.time < animationStart) + continue; + this.queue.event(entry, event); + } + } + /** Removes all animations from all tracks, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTracks() { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + /** Removes all animations from the track, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTrack(trackIndex) { + if (trackIndex >= this.tracks.length) + return; + let current = this.tracks[trackIndex]; + if (!current) + return; + this.queue.end(current); + this.clearNext(current); + let entry = current; + while (true) { + let from = entry.mixingFrom; + if (!from) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + } + setCurrent(index, current, interrupt) { + let from = this.expandToIndex(index); + this.tracks[index] = current; + current.previous = null; + if (from) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + } + /** Sets an animation by name. + * + * See {@link #setAnimationWith()}. */ + setAnimation(trackIndex, animationName, loop = false) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + } + /** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never + * applied to a skeleton, it is replaced (not mixed from). + * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + setAnimationWith(trackIndex, animation, loop = false) { + if (!animation) + throw new Error("animation cannot be null."); + let interrupt = true; + let current = this.expandToIndex(trackIndex); + if (current) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.clearNext(current); + current = current.mixingFrom; + interrupt = false; + } else + this.clearNext(current); + } + let entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + } + /** Queues an animation by name. + * + * See {@link #addAnimationWith()}. */ + addAnimation(trackIndex, animationName, loop = false, delay = 0) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + } + /** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is + * equivalent to calling {@link #setAnimationWith()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix + * ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the + * previous entry is looping, its next loop completion is used instead of its duration. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addAnimationWith(trackIndex, animation, loop = false, delay = 0) { + if (!animation) + throw new Error("animation cannot be null."); + let last = this.expandToIndex(trackIndex); + if (last) { + while (last.next) + last = last.next; + } + let entry = this.trackEntry(trackIndex, animation, loop, last); + if (!last) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } else { + last.next = entry; + entry.previous = last; + if (delay <= 0) + delay += last.getTrackComplete() - entry.mixDuration; + } + entry.delay = delay; + return entry; + } + /** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + * {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out. + * + * Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()}, + * {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes + * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + * 0 still mixes out over one frame. + * + * Mixing in is done by first setting an empty animation, then adding an animation using + * {@link #addAnimation()} and on the returned track entry, set the + * {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and + * more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the + * setup pose value if no lower tracks key the property to the value keyed in the new animation. */ + setEmptyAnimation(trackIndex, mixDuration = 0) { + let entry = this.setAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling + * {@link #setEmptyAnimation()}. + * + * See {@link #setEmptyAnimation()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or + * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next + * loop completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) { + let entry = this.addAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false, delay); + if (delay <= 0) + entry.delay += entry.mixDuration - mixDuration; + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix + * duration. */ + setEmptyAnimations(mixDuration = 0) { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) { + let current = this.tracks[i]; + if (current) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + expandToIndex(index) { + if (index < this.tracks.length) + return this.tracks[index]; + Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + } + /** @param last May be null. */ + trackEntry(trackIndex, animation, loop, last) { + let entry = this.trackEntryPool.obtain(); + entry.reset(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.reverse = false; + entry.shortestRotation = false; + entry.eventThreshold = 0; + entry.alphaAttachmentThreshold = 0; + entry.mixAttachmentThreshold = 0; + entry.mixDrawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.mixTime = 0; + entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation); + entry.interruptAlpha = 1; + entry.totalAlpha = 0; + entry.mixBlend = 2 /* replace */; + return entry; + } + /** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */ + clearNext(entry) { + let next = entry.next; + while (next) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + } + _animationsChanged() { + this.animationsChanged = false; + this.propertyIDs.clear(); + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let entry = tracks[i]; + if (!entry) + continue; + while (entry.mixingFrom) + entry = entry.mixingFrom; + do { + if (!entry.mixingTo || entry.mixBlend != 3 /* add */) + this.computeHold(entry); + entry = entry.mixingTo; + } while (entry); + } + } + computeHold(entry) { + let to = entry.mixingTo; + let timelines = entry.animation.timelines; + let timelinesCount = entry.animation.timelines.length; + let timelineMode = entry.timelineMode; + timelineMode.length = timelinesCount; + let timelineHoldMix = entry.timelineHoldMix; + timelineHoldMix.length = 0; + let propertyIDs = this.propertyIDs; + if (to && to.holdPrevious) { + for (let i = 0; i < timelinesCount; i++) + timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT; + return; + } + outer: + for (let i = 0; i < timelinesCount; i++) { + let timeline = timelines[i]; + let ids = timeline.getPropertyIds(); + if (!propertyIDs.addAll(ids)) + timelineMode[i] = SUBSEQUENT; + else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) { + timelineMode[i] = FIRST; + } else { + for (let next = to.mixingTo; next; next = next.mixingTo) { + if (next.animation.hasTimeline(ids)) + continue; + if (entry.mixDuration > 0) { + timelineMode[i] = HOLD_MIX; + timelineHoldMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = HOLD_FIRST; + } + } + } + /** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */ + getCurrent(trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + } + /** Adds a listener to receive events for all track entries. */ + addListener(listener) { + if (!listener) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + } + /** Removes the listener added with {@link #addListener()}. */ + removeListener(listener) { + let index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + } + /** Removes all listeners added with {@link #addListener()}. */ + clearListeners() { + this.listeners.length = 0; + } + /** Discards all listener notifications that have not yet been delivered. This can be useful to call from an + * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery + * are not wanted because new animations are being set. */ + clearListenerNotifications() { + this.queue.clear(); + } +}; +var AnimationState = _AnimationState; +__publicField(AnimationState, "_emptyAnimation", new Animation("", [], 0)); +var TrackEntry = class { + /** The animation to apply for this track entry. */ + animation = null; + previous = null; + /** The animation queued to start after this animation, or null. `next` makes up a linked list. */ + next = null; + /** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + * mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */ + mixingFrom = null; + /** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is + * currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */ + mixingTo = null; + /** The listener for events generated by this track entry, or null. + * + * A track entry returned from {@link AnimationState#setAnimation()} is already the current animation + * for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */ + listener = null; + /** The index of the track where this track entry is either current or queued. + * + * See {@link AnimationState#getCurrent()}. */ + trackIndex = 0; + /** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. */ + loop = false; + /** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + * of being mixed out. + * + * When mixing between animations that key the same property, if a lower track also keys that property then the value will + * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + * while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation + * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + * keys the property, only when a higher track also keys the property. + * + * Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the + * previous animation. */ + holdPrevious = false; + reverse = false; + shortestRotation = false; + /** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the + * `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event + * timelines are not applied while this animation is being mixed out. */ + eventThreshold = 0; + /** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the + * `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to + * 0, so attachment timelines are not applied while this animation is being mixed out. */ + mixAttachmentThreshold = 0; + /** When {@link #getAlpha()} is greater than alphaAttachmentThreshold, attachment timelines are applied. + * Defaults to 0, so attachment timelines are always applied. */ + alphaAttachmentThreshold = 0; + /** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the + * mixDrawOrderThreshold, draw order timelines are applied while this animation is being mixed out. Defaults to + * 0, so draw order timelines are not applied while this animation is being mixed out. */ + mixDrawOrderThreshold = 0; + /** Seconds when this animation starts, both initially and after looping. Defaults to 0. + * + * When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same + * value to prevent timeline keys before the start time from triggering. */ + animationStart = 0; + /** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + * loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */ + animationEnd = 0; + /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + * animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and + * `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation + * is applied. */ + animationLast = 0; + nextAnimationLast = 0; + /** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay` + * postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from + * the start of the previous animation to when this track entry will become the current track entry (ie when the previous + * track entry {@link TrackEntry#trackTime} >= this track entry's `delay`). + * + * {@link #timeScale} affects the delay. */ + delay = 0; + /** Current time in seconds this track entry has been the current track entry. The track time determines + * {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting + * looping. */ + trackTime = 0; + trackLast = 0; + nextTrackLast = 0; + /** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + * properties keyed by the animation are set to the setup pose and the track is cleared. + * + * It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation + * abruptly cease being applied. */ + trackEnd = 0; + /** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + * faster. Defaults to 1. + * + * {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to + * match the animation speed. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If + * the time scale is not 1, the delay may need to be adjusted. + * + * See AnimationState {@link AnimationState#timeScale} for affecting all animations. */ + timeScale = 0; + /** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults + * to 1, which overwrites the skeleton's current pose with this animation. + * + * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to + * use alpha on track 0 if the skeleton pose is from the last frame render. */ + alpha = 0; + /** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be + * slightly more than `mixDuration` when the mix is complete. */ + mixTime = 0; + /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData + * {@link AnimationStateData#getMix()} based on the animation before this animation (if any). + * + * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the + * properties it was animating. + * + * The `mixDuration` can be set manually rather than use the value from + * {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new + * track entry only before {@link AnimationState#update(float)} is first called. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set + * afterward. */ + _mixDuration = 0; + interruptAlpha = 0; + totalAlpha = 0; + get mixDuration() { + return this._mixDuration; + } + set mixDuration(mixDuration) { + this._mixDuration = mixDuration; + } + setMixDurationWithDelay(mixDuration, delay) { + this._mixDuration = mixDuration; + if (this.previous != null && delay <= 0) + delay += this.previous.getTrackComplete() - mixDuration; + this.delay = delay; + } + /** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which + * replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to + * the values from the lower tracks. + * + * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first + * called. */ + mixBlend = 2 /* replace */; + timelineMode = new Array(); + timelineHoldMix = new Array(); + timelinesRotation = new Array(); + reset() { + this.next = null; + this.previous = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + } + /** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart} + * and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the + * `animationStart` time. */ + getAnimationTime() { + if (this.loop) { + let duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return this.trackTime % duration + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + } + setAnimationLast(animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + } + /** Returns true if at least one loop has been completed. + * + * See {@link AnimationStateListener#complete()}. */ + isComplete() { + return this.trackTime >= this.animationEnd - this.animationStart; + } + /** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + * long way around when using {@link #alpha} and starting animations on other tracks. + * + * Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions: + * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long + * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the + * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */ + resetRotationDirections() { + this.timelinesRotation.length = 0; + } + getTrackComplete() { + let duration = this.animationEnd - this.animationStart; + if (duration != 0) { + if (this.loop) + return duration * (1 + (this.trackTime / duration | 0)); + if (this.trackTime < duration) + return duration; + } + return this.trackTime; + } + /** Returns true if this track entry has been applied at least once. + *

    + * See {@link AnimationState#apply(Skeleton)}. */ + wasApplied() { + return this.nextTrackLast != -1; + } + /** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next + * {@link AnimationState#update(float)}. */ + isNextReady() { + return this.next != null && this.nextTrackLast - this.next.delay >= 0; + } +}; +var EventQueue = class { + objects = []; + drainDisabled = false; + animState; + constructor(animState) { + this.animState = animState; + } + start(entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + interrupt(entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + } + end(entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + dispose(entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + } + complete(entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + } + event(entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + } + drain() { + if (this.drainDisabled) + return; + this.drainDisabled = true; + let objects = this.objects; + let listeners = this.animState.listeners; + for (let i = 0; i < objects.length; i += 2) { + let type = objects[i]; + let entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener && entry.listener.start) + entry.listener.start(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.start) + listener.start(entry); + } + break; + case EventType.interrupt: + if (entry.listener && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.interrupt) + listener.interrupt(entry); + } + break; + case EventType.end: + if (entry.listener && entry.listener.end) + entry.listener.end(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.end) + listener.end(entry); + } + case EventType.dispose: + if (entry.listener && entry.listener.dispose) + entry.listener.dispose(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.dispose) + listener.dispose(entry); + } + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener && entry.listener.complete) + entry.listener.complete(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.complete) + listener.complete(entry); + } + break; + case EventType.event: + let event = objects[i++ + 2]; + if (entry.listener && entry.listener.event) + entry.listener.event(entry, event); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.event) + listener.event(entry, event); + } + break; + } + } + this.clear(); + this.drainDisabled = false; + } + clear() { + this.objects.length = 0; + } +}; +var EventType = /* @__PURE__ */ ((EventType2) => { + EventType2[EventType2["start"] = 0] = "start"; + EventType2[EventType2["interrupt"] = 1] = "interrupt"; + EventType2[EventType2["end"] = 2] = "end"; + EventType2[EventType2["dispose"] = 3] = "dispose"; + EventType2[EventType2["complete"] = 4] = "complete"; + EventType2[EventType2["event"] = 5] = "event"; + return EventType2; +})(EventType || {}); +var AnimationStateAdapter = class { + start(entry) { + } + interrupt(entry) { + } + end(entry) { + } + dispose(entry) { + } + complete(entry) { + } + event(entry, event) { + } +}; +var SUBSEQUENT = 0; +var FIRST = 1; +var HOLD_SUBSEQUENT = 2; +var HOLD_FIRST = 3; +var HOLD_MIX = 4; +var SETUP = 1; +var CURRENT = 2; + +// spine-core/src/AnimationStateData.ts +var AnimationStateData = class { + /** The SkeletonData to look up animations when they are specified by name. */ + skeletonData; + animationToMixTime = {}; + /** The mix duration to use when no mix duration has been defined between two animations. */ + defaultMix = 0; + constructor(skeletonData) { + if (!skeletonData) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + /** Sets a mix duration by animation name. + * + * See {@link #setMixWith()}. */ + setMix(fromName, toName, duration) { + let from = this.skeletonData.findAnimation(fromName); + if (!from) + throw new Error("Animation not found: " + fromName); + let to = this.skeletonData.findAnimation(toName); + if (!to) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + } + /** Sets the mix duration when changing from the specified animation to the other. + * + * See {@link TrackEntry#mixDuration}. */ + setMixWith(from, to, duration) { + if (!from) + throw new Error("from cannot be null."); + if (!to) + throw new Error("to cannot be null."); + let key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + } + /** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if + * no mix duration has been set. */ + getMix(from, to) { + let key = from.name + "." + to.name; + let value = this.animationToMixTime[key]; + return value === void 0 ? this.defaultMix : value; + } +}; + +// spine-core/src/attachments/BoundingBoxAttachment.ts +var BoundingBoxAttachment = class extends VertexAttachment { + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + } +}; + +// spine-core/src/attachments/ClippingAttachment.ts +var ClippingAttachment = class extends VertexAttachment { + /** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of + * the skeleton's rendering. */ + endSlot = null; + // Nonessential. + /** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons + * are not usually rendered at runtime. */ + color = new Color(0.2275, 0.2275, 0.8078, 1); + // ce3a3aff + constructor(name) { + super(name); + } + copy() { + let copy = new ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.color.setFromColor(this.color); + return copy; + } +}; + +// spine-core/src/Texture.ts +var Texture = class { + _image; + constructor(image) { + this._image = image; + } + getImage() { + return this._image; + } +}; +var TextureFilter = /* @__PURE__ */ ((TextureFilter3) => { + TextureFilter3[TextureFilter3["Nearest"] = 9728] = "Nearest"; + TextureFilter3[TextureFilter3["Linear"] = 9729] = "Linear"; + TextureFilter3[TextureFilter3["MipMap"] = 9987] = "MipMap"; + TextureFilter3[TextureFilter3["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter3[TextureFilter3["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter3[TextureFilter3["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter3[TextureFilter3["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + return TextureFilter3; +})(TextureFilter || {}); +var TextureWrap = /* @__PURE__ */ ((TextureWrap4) => { + TextureWrap4[TextureWrap4["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap4[TextureWrap4["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap4[TextureWrap4["Repeat"] = 10497] = "Repeat"; + return TextureWrap4; +})(TextureWrap || {}); +var TextureRegion = class { + texture; + u = 0; + v = 0; + u2 = 0; + v2 = 0; + width = 0; + height = 0; + degrees = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; +}; +var FakeTexture = class extends Texture { + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } +}; + +// spine-core/src/TextureAtlas.ts +var TextureAtlas = class { + pages = new Array(); + regions = new Array(); + constructor(atlasText) { + let reader = new TextureAtlasReader(atlasText); + let entry = new Array(4); + let pageFields = {}; + pageFields["size"] = (page2) => { + page2.width = parseInt(entry[1]); + page2.height = parseInt(entry[2]); + }; + pageFields["format"] = () => { + }; + pageFields["filter"] = (page2) => { + page2.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page2.magFilter = Utils.enumValue(TextureFilter, entry[2]); + }; + pageFields["repeat"] = (page2) => { + if (entry[1].indexOf("x") != -1) + page2.uWrap = 10497 /* Repeat */; + if (entry[1].indexOf("y") != -1) + page2.vWrap = 10497 /* Repeat */; + }; + pageFields["pma"] = (page2) => { + page2.pma = entry[1] == "true"; + }; + var regionFields = {}; + regionFields["xy"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + }; + regionFields["size"] = (region) => { + region.width = parseInt(entry[1]); + region.height = parseInt(entry[2]); + }; + regionFields["bounds"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + region.width = parseInt(entry[3]); + region.height = parseInt(entry[4]); + }; + regionFields["offset"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + }; + regionFields["orig"] = (region) => { + region.originalWidth = parseInt(entry[1]); + region.originalHeight = parseInt(entry[2]); + }; + regionFields["offsets"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + region.originalWidth = parseInt(entry[3]); + region.originalHeight = parseInt(entry[4]); + }; + regionFields["rotate"] = (region) => { + let value = entry[1]; + if (value == "true") + region.degrees = 90; + else if (value != "false") + region.degrees = parseInt(value); + }; + regionFields["index"] = (region) => { + region.index = parseInt(entry[1]); + }; + let line = reader.readLine(); + while (line && line.trim().length == 0) + line = reader.readLine(); + while (true) { + if (!line || line.trim().length == 0) + break; + if (reader.readEntry(entry, line) == 0) + break; + line = reader.readLine(); + } + let page = null; + let names = null; + let values = null; + while (true) { + if (line === null) + break; + if (line.trim().length == 0) { + page = null; + line = reader.readLine(); + } else if (!page) { + page = new TextureAtlasPage(line.trim()); + while (true) { + if (reader.readEntry(entry, line = reader.readLine()) == 0) + break; + let field = pageFields[entry[0]]; + if (field) + field(page); + } + this.pages.push(page); + } else { + let region = new TextureAtlasRegion(page, line); + while (true) { + let count = reader.readEntry(entry, line = reader.readLine()); + if (count == 0) + break; + let field = regionFields[entry[0]]; + if (field) + field(region); + else { + if (!names) + names = []; + if (!values) + values = []; + names.push(entry[0]); + let entryValues = []; + for (let i = 0; i < count; i++) + entryValues.push(parseInt(entry[i + 1])); + values.push(entryValues); + } + } + if (region.originalWidth == 0 && region.originalHeight == 0) { + region.originalWidth = region.width; + region.originalHeight = region.height; + } + if (names && names.length > 0 && values && values.length > 0) { + region.names = names; + region.values = values; + names = null; + values = null; + } + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.degrees == 90) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + this.regions.push(region); + } + } + } + findRegion(name) { + for (let i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + } + setTextures(assetManager, pathPrefix = "") { + for (let page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name)); + } + dispose() { + for (let i = 0; i < this.pages.length; i++) { + this.pages[i].texture?.dispose(); + } + } +}; +var TextureAtlasReader = class { + lines; + index = 0; + constructor(text) { + this.lines = text.split(/\r\n|\r|\n/); + } + readLine() { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + } + readEntry(entry, line) { + if (!line) + return 0; + line = line.trim(); + if (line.length == 0) + return 0; + let colon = line.indexOf(":"); + if (colon == -1) + return 0; + entry[0] = line.substr(0, colon).trim(); + for (let i = 1, lastMatch = colon + 1; ; i++) { + let comma = line.indexOf(",", lastMatch); + if (comma == -1) { + entry[i] = line.substr(lastMatch).trim(); + return i; + } + entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) + return 4; + } + } +}; +var TextureAtlasPage = class { + name; + minFilter = 9728 /* Nearest */; + magFilter = 9728 /* Nearest */; + uWrap = 33071 /* ClampToEdge */; + vWrap = 33071 /* ClampToEdge */; + texture = null; + width = 0; + height = 0; + pma = false; + regions = new Array(); + constructor(name) { + this.name = name; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + for (let region of this.regions) + region.texture = texture; + } +}; +var TextureAtlasRegion = class extends TextureRegion { + page; + name; + x = 0; + y = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + index = 0; + degrees = 0; + names = null; + values = null; + constructor(page, name) { + super(); + this.page = page; + this.name = name; + page.regions.push(this); + } +}; + +// spine-core/src/attachments/MeshAttachment.ts +var MeshAttachment = class extends VertexAttachment { + region = null; + /** The name of the texture region for this attachment. */ + path; + /** The UV pair for each vertex, normalized within the texture region. */ + regionUVs = []; + /** The UV pair for each vertex, normalized within the entire texture. + * + * See {@link #updateUVs}. */ + uvs = []; + /** Triplets of vertex indices which describe the mesh's triangulation. */ + triangles = []; + /** The color to tint the mesh. */ + color = new Color(1, 1, 1, 1); + /** The width of the mesh's image. Available only when nonessential data was exported. */ + width = 0; + /** The height of the mesh's image. Available only when nonessential data was exported. */ + height = 0; + /** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */ + hullLength = 0; + /** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if + * nonessential data was exported. Triangulation is not performed at runtime. */ + edges = []; + parentMesh = null; + sequence = null; + tempColor = new Color(0, 0, 0, 0); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates {@link #uvs} using the {@link #regionUVs} and region. Must be called if the region, the region's properties, or + * the {@link #regionUVs} are changed. */ + updateRegion() { + if (!this.region) + throw new Error("Region not set."); + let regionUVs = this.regionUVs; + if (!this.uvs || this.uvs.length != regionUVs.length) + this.uvs = Utils.newFloatArray(regionUVs.length); + let uvs = this.uvs; + let n = this.uvs.length; + let u = this.region.u, v = this.region.v, width = 0, height = 0; + if (this.region instanceof TextureAtlasRegion) { + let region = this.region, page = region.page; + let textureWidth = page.width, textureHeight = page.height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } else if (!this.region) { + u = v = 0; + width = height = 1; + } else { + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + /** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices}, + * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the + * parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */ + getParentMesh() { + return this.parentMesh; + } + /** @param parentMesh May be null. */ + setParentMesh(parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + } + copy() { + if (this.parentMesh) + return this.newLinkedMesh(); + let copy = new MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = new Array(this.regionUVs.length); + Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.uvs = new Array(this.uvs.length); + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length); + copy.triangles = new Array(this.triangles.length); + Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + if (this.edges) { + copy.edges = new Array(this.edges.length); + Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + } + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + super.computeWorldVertices(slot, start, count, worldVertices2, offset, stride); + } + /** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/ + newLinkedMesh() { + let copy = new MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + copy.timelineAttachment = this.timelineAttachment; + copy.setParentMesh(this.parentMesh ? this.parentMesh : this); + if (copy.region != null) + copy.updateRegion(); + return copy; + } +}; + +// spine-core/src/attachments/PathAttachment.ts +var PathAttachment = class extends VertexAttachment { + /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */ + lengths = []; + /** If true, the start and end knots are connected. */ + closed = false; + /** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer + * calculations are performed but calculating positions along the path is less accurate. */ + constantSpeed = false; + /** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually + * rendered at runtime. */ + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = new Array(this.lengths.length); + Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + } +}; + +// spine-core/src/attachments/PointAttachment.ts +var PointAttachment = class extends VertexAttachment { + x = 0; + y = 0; + rotation = 0; + /** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments + * are not usually rendered at runtime. */ + color = new Color(0.38, 0.94, 0, 1); + constructor(name) { + super(name); + } + computeWorldPosition(bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + computeWorldRotation(bone) { + const r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const x = cos * bone.a + sin * bone.b; + const y = cos * bone.c + sin * bone.d; + return MathUtils.atan2Deg(y, x); + } + copy() { + let copy = new PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + } +}; + +// spine-core/src/attachments/RegionAttachment.ts +var _RegionAttachment = class extends Attachment { + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local rotation. */ + rotation = 0; + /** The width of the region attachment in Spine. */ + width = 0; + /** The height of the region attachment in Spine. */ + height = 0; + /** The color to tint the region attachment. */ + color = new Color(1, 1, 1, 1); + /** The name of the texture region for this attachment. */ + path; + region = null; + sequence = null; + /** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex. + * + * See {@link #updateOffset()}. */ + offset = Utils.newFloatArray(8); + uvs = Utils.newFloatArray(8); + tempColor = new Color(1, 1, 1, 1); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */ + updateRegion() { + if (!this.region) + throw new Error("Region not set."); + let region = this.region; + let uvs = this.uvs; + if (region == null) { + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + uvs[4] = 1; + uvs[5] = 1; + uvs[6] = 1; + uvs[7] = 0; + return; + } + let regionScaleX = this.width / this.region.originalWidth * this.scaleX; + let regionScaleY = this.height / this.region.originalHeight * this.scaleY; + let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + let localX2 = localX + this.region.width * regionScaleX; + let localY2 = localY + this.region.height * regionScaleY; + let radians = this.rotation * MathUtils.degRad; + let cos = Math.cos(radians); + let sin = Math.sin(radians); + let x = this.x, y = this.y; + let localXCos = localX * cos + x; + let localXSin = localX * sin; + let localYCos = localY * cos + y; + let localYSin = localY * sin; + let localX2Cos = localX2 * cos + x; + let localX2Sin = localX2 * sin; + let localY2Cos = localY2 * cos + y; + let localY2Sin = localY2 * sin; + let offset = this.offset; + offset[0] = localXCos - localYSin; + offset[1] = localYCos + localXSin; + offset[2] = localXCos - localY2Sin; + offset[3] = localY2Cos + localXSin; + offset[4] = localX2Cos - localY2Sin; + offset[5] = localY2Cos + localX2Sin; + offset[6] = localX2Cos - localYSin; + offset[7] = localYCos + localX2Sin; + if (region.degrees == 90) { + uvs[0] = region.u2; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + } else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + } + /** Transforms the attachment's four vertices to world coordinates. If the attachment has a {@link #sequence}, the region may + * be changed. + *

    + * See World transforms in the Spine + * Runtimes Guide. + * @param worldVertices The output world vertices. Must have a length >= offset + 8. + * @param offset The worldVertices index to begin writing values. + * @param stride The number of worldVertices entries between the value pairs written. */ + computeWorldVertices(slot, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + let bone = slot.bone; + let vertexOffset = this.offset; + let x = bone.worldX, y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let offsetX = 0, offsetY = 0; + offsetX = vertexOffset[0]; + offsetY = vertexOffset[1]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[2]; + offsetY = vertexOffset[3]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[4]; + offsetY = vertexOffset[5]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[6]; + offsetY = vertexOffset[7]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + } + copy() { + let copy = new _RegionAttachment(this.name, this.path); + copy.region = this.region; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8); + Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8); + copy.color.setFromColor(this.color); + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + return copy; + } +}; +var RegionAttachment = _RegionAttachment; +__publicField(RegionAttachment, "X1", 0); +__publicField(RegionAttachment, "Y1", 1); +__publicField(RegionAttachment, "C1R", 2); +__publicField(RegionAttachment, "C1G", 3); +__publicField(RegionAttachment, "C1B", 4); +__publicField(RegionAttachment, "C1A", 5); +__publicField(RegionAttachment, "U1", 6); +__publicField(RegionAttachment, "V1", 7); +__publicField(RegionAttachment, "X2", 8); +__publicField(RegionAttachment, "Y2", 9); +__publicField(RegionAttachment, "C2R", 10); +__publicField(RegionAttachment, "C2G", 11); +__publicField(RegionAttachment, "C2B", 12); +__publicField(RegionAttachment, "C2A", 13); +__publicField(RegionAttachment, "U2", 14); +__publicField(RegionAttachment, "V2", 15); +__publicField(RegionAttachment, "X3", 16); +__publicField(RegionAttachment, "Y3", 17); +__publicField(RegionAttachment, "C3R", 18); +__publicField(RegionAttachment, "C3G", 19); +__publicField(RegionAttachment, "C3B", 20); +__publicField(RegionAttachment, "C3A", 21); +__publicField(RegionAttachment, "U3", 22); +__publicField(RegionAttachment, "V3", 23); +__publicField(RegionAttachment, "X4", 24); +__publicField(RegionAttachment, "Y4", 25); +__publicField(RegionAttachment, "C4R", 26); +__publicField(RegionAttachment, "C4G", 27); +__publicField(RegionAttachment, "C4B", 28); +__publicField(RegionAttachment, "C4A", 29); +__publicField(RegionAttachment, "U4", 30); +__publicField(RegionAttachment, "V4", 31); + +// spine-core/src/AtlasAttachmentLoader.ts +var AtlasAttachmentLoader = class { + atlas; + constructor(atlas) { + this.atlas = atlas; + } + loadSequence(name, basePath, sequence) { + let regions = sequence.regions; + for (let i = 0, n = regions.length; i < n; i++) { + let path = sequence.getPath(basePath, i); + let region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")"); + regions[i] = region; + } + } + newRegionAttachment(skin, name, path, sequence) { + let attachment = new RegionAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newMeshAttachment(skin, name, path, sequence) { + let attachment = new MeshAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newBoundingBoxAttachment(skin, name) { + return new BoundingBoxAttachment(name); + } + newPathAttachment(skin, name) { + return new PathAttachment(name); + } + newPointAttachment(skin, name) { + return new PointAttachment(name); + } + newClippingAttachment(skin, name) { + return new ClippingAttachment(name); + } +}; + +// spine-core/src/BoneData.ts +var BoneData = class { + /** The index of the bone in {@link Skeleton#getBones()}. */ + index = 0; + /** The name of the bone, which is unique across all bones in the skeleton. */ + name; + /** @returns May be null. */ + parent = null; + /** The bone's length. */ + length = 0; + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local shearX. */ + shearX = 0; + /** The local shearX. */ + shearY = 0; + /** The transform mode for how parent world transforms affect this bone. */ + inherit = Inherit.Normal; + /** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this + * bone. + * @see Skin#bones */ + skinRequired = false; + /** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually + * rendered at runtime. */ + color = new Color(); + /** The bone icon as it was in Spine, or null if nonessential data was not exported. */ + icon; + /** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = false; + constructor(index, name, parent) { + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } +}; +var Inherit = /* @__PURE__ */ ((Inherit2) => { + Inherit2[Inherit2["Normal"] = 0] = "Normal"; + Inherit2[Inherit2["OnlyTranslation"] = 1] = "OnlyTranslation"; + Inherit2[Inherit2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + Inherit2[Inherit2["NoScale"] = 3] = "NoScale"; + Inherit2[Inherit2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + return Inherit2; +})(Inherit || {}); + +// spine-core/src/Bone.ts +var Bone = class { + /** The bone's setup pose data. */ + data; + /** The skeleton this bone belongs to. */ + skeleton; + /** The parent bone, or null if this is the root bone. */ + parent = null; + /** The immediate children of this bone. */ + children = new Array(); + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 0; + /** The local scaleY. */ + scaleY = 0; + /** The local shearX. */ + shearX = 0; + /** The local shearY. */ + shearY = 0; + /** The applied local x translation. */ + ax = 0; + /** The applied local y translation. */ + ay = 0; + /** The applied local rotation in degrees, counter clockwise. */ + arotation = 0; + /** The applied local scaleX. */ + ascaleX = 0; + /** The applied local scaleY. */ + ascaleY = 0; + /** The applied local shearX. */ + ashearX = 0; + /** The applied local shearY. */ + ashearY = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + a = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + b = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + c = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + d = 0; + /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldY = 0; + /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldX = 0; + inherit = 0 /* Normal */; + sorted = false; + active = false; + /** @param parent May be null. */ + constructor(data, skeleton, parent) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + /** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the + * {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */ + isActive() { + return this.active; + } + /** Computes the world transform using the parent bone and this bone's local applied transform. */ + update(physics) { + this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY); + } + /** Computes the world transform using the parent bone and this bone's local transform. + * + * See {@link #updateWorldTransformWith()}. */ + updateWorldTransform() { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + } + /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the + * specified local transform. Child bones are not updated. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + let parent = this.parent; + if (!parent) { + let skeleton = this.skeleton; + const sx = skeleton.scaleX, sy = skeleton.scaleY; + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX * sx; + this.b = Math.cos(ry) * scaleY * sx; + this.c = Math.sin(rx) * scaleX * sy; + this.d = Math.sin(ry) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.inherit) { + case 0 /* Normal */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case 1 /* OnlyTranslation */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX; + this.b = Math.cos(ry) * scaleY; + this.c = Math.sin(rx) * scaleX; + this.d = Math.sin(ry) * scaleY; + break; + } + case 2 /* NoRotationOrReflection */: { + let sx = 1 / this.skeleton.scaleX, sy = 1 / this.skeleton.scaleY; + pa *= sx; + pc *= sy; + let s = pa * pa + pc * pc; + let prx = 0; + if (s > 1e-4) { + s = Math.abs(pa * pd * sy - pb * sx * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * MathUtils.radDeg; + } else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg; + } + const rx = (rotation + shearX - prx) * MathUtils.degRad; + const ry = (rotation + shearY - prx + 90) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: { + rotation *= MathUtils.degRad; + const cos = Math.cos(rotation), sin = Math.sin(rotation); + let za = (pa * cos + pb * sin) / this.skeleton.scaleX; + let zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(za * za + zc * zc); + if (s > 1e-5) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.inherit == 3 /* NoScale */ && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + rotation = Math.PI / 2 + Math.atan2(zc, za); + const zb = Math.cos(rotation) * s; + const zd = Math.sin(rotation) * s; + shearX *= MathUtils.degRad; + shearY = (90 + shearY) * MathUtils.degRad; + const la = Math.cos(shearX) * scaleX; + const lb = Math.cos(shearY) * scaleY; + const lc = Math.sin(shearX) * scaleX; + const ld = Math.sin(shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + } + /** Sets this bone's local transform to the setup pose. */ + setToSetupPose() { + let data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + this.inherit = data.inherit; + } + /** Computes the applied transform values from the world transform. + * + * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, 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 other + * constraints). + * + * 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. */ + updateAppliedTransform() { + let parent = this.parent; + if (!parent) { + this.ax = this.worldX - this.skeleton.x; + this.ay = this.worldY - this.skeleton.y; + this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + let pid = 1 / (pa * pd - pb * pc); + let ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = dx * ia - dy * ib; + this.ay = dy * id - dx * ic; + let ra, rb, rc, rd; + if (this.inherit == 1 /* OnlyTranslation */) { + ra = this.a; + rb = this.b; + rc = this.c; + rd = this.d; + } else { + switch (this.inherit) { + case 2 /* NoRotationOrReflection */: { + let s2 = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + pb = -pc * this.skeleton.scaleX * s2 / this.skeleton.scaleY; + pd = pa * this.skeleton.scaleY * s2 / this.skeleton.scaleX; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation); + pa = (pa * cos + pb * sin) / this.skeleton.scaleX; + pc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(pa * pa + pc * pc); + if (s > 1e-5) + s = 1 / s; + pa *= s; + pc *= s; + s = Math.sqrt(pa * pa + pc * pc); + if (this.inherit == 3 /* NoScale */ && pid < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + let r = MathUtils.PI / 2 + Math.atan2(pc, pa); + pb = Math.cos(r) * s; + pd = Math.sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + } + ra = ia * this.a - ib * this.c; + rb = ia * this.b - ib * this.d; + rc = id * this.c - ic * this.a; + rd = id * this.d - ic * this.b; + } + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 1e-4) { + let det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = -Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg; + } else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg; + } + } + /** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */ + getWorldRotationX() { + return Math.atan2(this.c, this.a) * MathUtils.radDeg; + } + /** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */ + getWorldRotationY() { + return Math.atan2(this.d, this.b) * MathUtils.radDeg; + } + /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */ + getWorldScaleX() { + return Math.sqrt(this.a * this.a + this.c * this.c); + } + /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */ + getWorldScaleY() { + return Math.sqrt(this.b * this.b + this.d * this.d); + } + /** Transforms a point from world coordinates to the bone's local coordinates. */ + worldToLocal(world) { + let invDet = 1 / (this.a * this.d - this.b * this.c); + let x = world.x - this.worldX, y = world.y - this.worldY; + world.x = x * this.d * invDet - y * this.b * invDet; + world.y = y * this.a * invDet - x * this.c * invDet; + return world; + } + /** Transforms a point from the bone's local coordinates to world coordinates. */ + localToWorld(local) { + let x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + } + /** Transforms a point from world coordinates to the parent bone's local coordinates. */ + worldToParent(world) { + if (world == null) + throw new Error("world cannot be null."); + return this.parent == null ? world : this.parent.worldToLocal(world); + } + /** Transforms a point from the parent bone's coordinates to world coordinates. */ + parentToWorld(world) { + if (world == null) + throw new Error("world cannot be null."); + return this.parent == null ? world : this.parent.localToWorld(world); + } + /** Transforms a world rotation to a local rotation. */ + worldToLocalRotation(worldRotation) { + let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX; + } + /** Transforms a local rotation to a world rotation. */ + localToWorldRotation(localRotation) { + localRotation -= this.rotation - this.shearX; + let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg; + } + /** Rotates the world transform the specified amount. + *

    + * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and + * {@link #update(Physics)} will need to be called on any child bones, recursively. */ + rotateWorld(degrees) { + degrees *= MathUtils.degRad; + const sin = Math.sin(degrees), cos = Math.cos(degrees); + const ra = this.a, rb = this.b; + this.a = cos * ra - sin * this.c; + this.b = cos * rb - sin * this.d; + this.c = sin * ra + cos * this.c; + this.d = sin * rb + cos * this.d; + } +}; + +// spine-core/src/ConstraintData.ts +var ConstraintData = class { + constructor(name, order, skinRequired) { + this.name = name; + this.order = order; + this.skinRequired = skinRequired; + } +}; + +// spine-core/src/AssetManagerBase.ts +var AssetManagerBase = class { + pathPrefix = ""; + textureLoader; + downloader; + assets = {}; + errors = {}; + toLoad = 0; + loaded = 0; + constructor(textureLoader, pathPrefix = "", downloader = new Downloader()) { + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + this.downloader = downloader; + } + start(path) { + this.toLoad++; + return this.pathPrefix + path; + } + success(callback, path, asset) { + this.toLoad--; + this.loaded++; + this.assets[path] = asset; + if (callback) + callback(path, asset); + } + error(callback, path, message) { + this.toLoad--; + this.loaded++; + this.errors[path] = message; + if (callback) + callback(path, message); + } + loadAll() { + let promise = new Promise((resolve, reject) => { + let check = () => { + if (this.isLoadingComplete()) { + if (this.hasErrors()) + reject(this.errors); + else + resolve(this); + return; + } + requestAnimationFrame(check); + }; + requestAnimationFrame(check); + }); + return promise; + } + setRawDataURI(path, data) { + this.downloader.rawDataUris[this.pathPrefix + path] = data; + } + loadBinary(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadBinary(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`); + }); + } + loadText(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadText(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); + }); + } + loadJson(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadJson(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`); + }); + } + loadTexture(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document); + let isWebWorker = !isBrowser; + if (isWebWorker) { + fetch(path, { mode: "cors" }).then((response) => { + if (response.ok) + return response.blob(); + this.error(error, path, `Couldn't load image: ${path}`); + return null; + }).then((blob) => { + return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; + }).then((bitmap) => { + if (bitmap) + this.success(success, path, this.textureLoader(bitmap)); + }); + } else { + let image = new Image(); + image.crossOrigin = "anonymous"; + image.onload = () => { + this.success(success, path, this.textureLoader(image)); + }; + image.onerror = () => { + this.error(error, path, `Couldn't load image: ${path}`); + }; + if (this.downloader.rawDataUris[path]) + path = this.downloader.rawDataUris[path]; + image.src = path; + } + } + loadTextureAtlas(path, success = () => { + }, error = () => { + }, fileAlias) { + let index = path.lastIndexOf("/"); + let parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + this.downloader.downloadText(path, (atlasText) => { + try { + let atlas = new TextureAtlas(atlasText); + let toLoad = atlas.pages.length, abort = false; + for (let page of atlas.pages) { + this.loadTexture( + !fileAlias ? parent + page.name : fileAlias[page.name], + (imagePath, texture) => { + if (!abort) { + page.setTexture(texture); + if (--toLoad == 0) + this.success(success, path, atlas); + } + }, + (imagePath, message) => { + if (!abort) + this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`); + abort = true; + } + ); + } + } catch (e) { + this.error(error, path, `Couldn't parse texture atlas ${path}: ${e.message}`); + } + }, (status, responseText) => { + this.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`); + }); + } + get(path) { + return this.assets[this.pathPrefix + path]; + } + require(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset) + return asset; + let error = this.errors[path]; + throw Error("Asset not found: " + path + (error ? "\n" + error : "")); + } + remove(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + delete this.assets[path]; + return asset; + } + removeAll() { + for (let key in this.assets) { + let asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + } + isLoadingComplete() { + return this.toLoad == 0; + } + getToLoad() { + return this.toLoad; + } + getLoaded() { + return this.loaded; + } + dispose() { + this.removeAll(); + } + hasErrors() { + return Object.keys(this.errors).length > 0; + } + getErrors() { + return this.errors; + } +}; +var Downloader = class { + callbacks = {}; + rawDataUris = {}; + dataUriToString(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx != -1) { + base64Idx += "base64,".length; + return atob(dataUri.substr(base64Idx)); + } else { + return dataUri.substr(dataUri.indexOf(",") + 1); + } + } + base64ToUint8Array(base64) { + var binary_string = window.atob(base64); + var len = binary_string.length; + var bytes = new Uint8Array(len); + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + } + dataUriToUint8Array(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx == -1) + throw new Error("Not a binary data URI."); + base64Idx += "base64,".length; + return this.base64ToUint8Array(dataUri.substr(base64Idx)); + } + downloadText(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToString(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.open("GET", url, true); + let done = () => { + this.finish(url, request.status, request.responseText); + }; + request.onload = done; + request.onerror = done; + request.send(); + } + downloadJson(url, success, error) { + this.downloadText(url, (data) => { + success(JSON.parse(data)); + }, error); + } + downloadBinary(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToUint8Array(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + let onerror = () => { + this.finish(url, request.status, request.response); + }; + request.onload = () => { + if (request.status == 200 || request.status == 0) + this.finish(url, 200, new Uint8Array(request.response)); + else + onerror(); + }; + request.onerror = onerror; + request.send(); + } + start(url, success, error) { + let callbacks = this.callbacks[url]; + try { + if (callbacks) + return true; + this.callbacks[url] = callbacks = []; + } finally { + callbacks.push(success, error); + } + } + finish(url, status, data) { + let callbacks = this.callbacks[url]; + delete this.callbacks[url]; + let args = status == 200 || status == 0 ? [data] : [status, data]; + for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) + callbacks[i].apply(null, args); + } +}; + +// spine-core/src/Event.ts +var Event = class { + data; + intValue = 0; + floatValue = 0; + stringValue = null; + time = 0; + volume = 0; + balance = 0; + constructor(time, data) { + if (!data) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } +}; + +// spine-core/src/EventData.ts +var EventData = class { + name; + intValue = 0; + floatValue = 0; + stringValue = null; + audioPath = null; + volume = 0; + balance = 0; + constructor(name) { + this.name = name; + } +}; + +// spine-core/src/IkConstraint.ts +var IkConstraint = class { + /** The IK constraint's setup pose data. */ + data; + /** The bones that will be modified by this IK constraint. */ + bones; + /** The bone that is the IK target. */ + target; + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 1; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) + throw new Error(`Couldn't find bone ${data.target.name}`); + this.target = target; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + } + update(physics) { + if (this.mix == 0) + return; + let target = this.target; + let bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix); + break; + } + } + /** Applies 1 bone IK. The target is specified in the world coordinate system. */ + apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) { + let p = bone.parent; + if (!p) + throw new Error("IK bone must have parent."); + let pa = p.a, pb = p.b, pc = p.c, pd = p.d; + let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0; + switch (bone.inherit) { + case 1 /* OnlyTranslation */: + tx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX); + ty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY); + break; + case 2 /* NoRotationOrReflection */: + let s = Math.abs(pa * pd - pb * pc) / Math.max(1e-4, pa * pa + pc * pc); + let sa = pa / bone.skeleton.scaleX; + let sc = pc / bone.skeleton.scaleY; + pb = -sc * s * bone.skeleton.scaleX; + pd = sa * s * bone.skeleton.scaleY; + rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg; + default: + let x = targetX - p.worldX, y = targetY - p.worldY; + let d = pa * pd - pb * pc; + if (Math.abs(d) <= 1e-4) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone.ax; + ty = (y * pa - x * pc) / d - bone.ay; + } + } + rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + let sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + switch (bone.inherit) { + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + const b = bone.data.length * sx; + if (b > 1e-4) { + const dd = tx * tx + ty * ty; + if (compress && dd < b * b || stretch && dd > b * b) { + const s = (Math.sqrt(dd) / b - 1) * alpha + 1; + sx *= s; + if (uniform) + sy *= s; + } + } + } + bone.updateWorldTransformWith( + bone.ax, + bone.ay, + bone.arotation + rotationIK * alpha, + sx, + sy, + bone.ashearX, + bone.ashearY + ); + } + /** Applies 2 bone IK. The target is specified in the world coordinate system. + * @param child A direct descendant of the parent bone. */ + apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) { + if (parent.inherit != 0 /* Normal */ || child.inherit != 0 /* Normal */) + return; + let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; + let os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + let u = Math.abs(psx - psy) <= 1e-4; + if (!u || stretch) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + let pp = parent.parent; + if (!pp) + throw new Error("IK parent must itself have a parent."); + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + let id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; + id = Math.abs(id) <= 1e-4 ? 0 : 1 / id; + let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + if (l1 < 1e-4) { + this.apply1(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + let dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5; + let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + let p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: + if (u) { + l2 *= psx; + let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = Math.PI * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) + sy *= a; + } + } else + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + let c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + let q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) * 0.5; + let r0 = q / c2, r1 = c / q; + let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + r0 = dd - r * r; + if (r0 >= 0) { + y = Math.sqrt(r0) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + let os = Math.atan2(cy, cx) * s2; + let rotation = parent.arotation; + a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + } +}; + +// spine-core/src/IkConstraintData.ts +var IkConstraintData = class extends ConstraintData { + /** The bones that are constrained by this IK constraint. */ + bones = new Array(); + /** The bone that is the IK target. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone + * is scaled on both the X and Y axes. */ + uniform = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 0; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + constructor(name) { + super(name, 0, false); + } +}; + +// spine-core/src/PathConstraintData.ts +var PathConstraintData = class extends ConstraintData { + /** The bones that will be modified by this path constraint. */ + bones = new Array(); + /** The slot whose path attachment will be used to constrained the bones. */ + _target = null; + set target(slotData) { + this._target = slotData; + } + get target() { + if (!this._target) + throw new Error("SlotData not set."); + else + return this._target; + } + /** The mode for positioning the first bone on the path. */ + positionMode = PositionMode.Fixed; + /** The mode for positioning the bones after the first bone on the path. */ + spacingMode = SpacingMode.Fixed; + /** The mode for adjusting the rotation of the bones. */ + rotateMode = RotateMode.Chain; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + constructor(name) { + super(name, 0, false); + } +}; +var PositionMode = /* @__PURE__ */ ((PositionMode2) => { + PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed"; + PositionMode2[PositionMode2["Percent"] = 1] = "Percent"; + return PositionMode2; +})(PositionMode || {}); +var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => { + SpacingMode2[SpacingMode2["Length"] = 0] = "Length"; + SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed"; + SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent"; + SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional"; + return SpacingMode2; +})(SpacingMode || {}); +var RotateMode = /* @__PURE__ */ ((RotateMode2) => { + RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent"; + RotateMode2[RotateMode2["Chain"] = 1] = "Chain"; + RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale"; + return RotateMode2; +})(RotateMode || {}); + +// spine-core/src/PathConstraint.ts +var _PathConstraint = class { + /** The path constraint's setup pose data. */ + data; + /** The bones that will be modified by this path constraint. */ + bones; + /** The slot whose path attachment will be used to constrained the bones. */ + target; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + spaces = new Array(); + positions = new Array(); + world = new Array(); + curves = new Array(); + lengths = new Array(); + segments = new Array(); + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0, n = data.bones.length; i < n; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findSlot(data.target.name); + if (!target) + throw new Error(`Couldn't find target bone ${data.target.name}`); + this.target = target; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + update(physics) { + let attachment = this.target.getAttachment(); + if (!(attachment instanceof PathAttachment)) + return; + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) + return; + let data = this.data; + let tangents = data.rotateMode == 0 /* Tangent */, scale = data.rotateMode == 2 /* ChainScale */; + let bones = this.bones; + let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; + let spacing = this.spacing; + switch (data.spacingMode) { + case 2 /* Percent */: + if (scale) { + for (let i = 0, n = spacesCount - 1; i < n; i++) { + let bone = bones[i]; + let setupLength = bone.data.length; + let x = setupLength * bone.a, y = setupLength * bone.c; + lengths[i] = Math.sqrt(x * x + y * y); + } + } + Utils.arrayFill(spaces, 1, spacesCount, spacing); + break; + case 3 /* Proportional */: + let sum = 0; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (let i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + default: + let lengthSpacing = data.spacingMode == 0 /* Length */; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + let positions = this.computeWorldPositions(attachment, spacesCount, tangents); + let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + let tip = false; + if (offsetRotation == 0) + tip = data.rotateMode == 1 /* Chain */; + else { + tip = false; + let p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad; + } + for (let i = 0, p = 3; i < boneCount; i++, p += 3) { + let bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * mixX; + bone.worldY += (boneY - bone.worldY) * mixY; + let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + let length = lengths[i]; + if (length != 0) { + let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + let length = bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else { + r += offsetRotation; + } + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.updateAppliedTransform(); + } + } + computeWorldPositions(path, spacesCount, tangents) { + let target = this.target; + let position = this.position; + let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world; + let closed2 = path.closed; + let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE; + if (!path.constantSpeed) { + let lengths = path.lengths; + curveCount -= closed2 ? 1 : 2; + let pathLength2 = lengths[curveCount]; + if (this.data.positionMode == 1 /* Percent */) + position *= pathLength2; + let multiplier2; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier2 = pathLength2; + break; + case 3 /* Proportional */: + multiplier2 = pathLength2 / spacesCount; + break; + default: + multiplier2 = 1; + } + world = Utils.setArraySize(this.world, 8); + for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier2; + position += space; + let p = position; + if (closed2) { + p %= pathLength2; + if (p < 0) + p += pathLength2; + curve = 0; + } else if (p < 0) { + if (prevCurve != _PathConstraint.BEFORE) { + prevCurve = _PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength2) { + if (prevCurve != _PathConstraint.AFTER) { + prevCurve = _PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength2, world, 0, out, o); + continue; + } + for (; ; curve++) { + let length = lengths[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed2 && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.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 + ); + } + return out; + } + if (closed2) { + verticesLength += 2; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + let curves = Utils.setArraySize(this.curves, curveCount); + let pathLength = 0; + let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (let i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (this.data.positionMode == 1 /* Percent */) + position *= pathLength; + let multiplier; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier = pathLength; + break; + case 3 /* Proportional */: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + let segments = this.segments; + let curveLength = 0; + for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier; + position += space; + let p = position; + if (closed2) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (; ; curve++) { + let length = curves[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + let ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (; ; segment++) { + let length = segments[segment]; + if (p > length) + continue; + if (segment == 0) + p /= length; + else { + let prev = segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0); + } + return out; + } + addBeforePosition(p, temp, i, out, o) { + let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addAfterPosition(p, temp, i, out, o) { + let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 1e-3) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } +}; +var PathConstraint = _PathConstraint; +__publicField(PathConstraint, "NONE", -1); +__publicField(PathConstraint, "BEFORE", -2); +__publicField(PathConstraint, "AFTER", -3); +__publicField(PathConstraint, "epsilon", 1e-5); + +// spine-core/src/PhysicsConstraint.ts +var PhysicsConstraint = class { + data; + _bone = null; + /** The bone constrained by this physics constraint. */ + set bone(bone) { + this._bone = bone; + } + get bone() { + if (!this._bone) + throw new Error("Bone not set."); + else + return this._bone; + } + inertia = 0; + strength = 0; + damping = 0; + massInverse = 0; + wind = 0; + gravity = 0; + mix = 0; + _reset = true; + ux = 0; + uy = 0; + cx = 0; + cy = 0; + tx = 0; + ty = 0; + xOffset = 0; + xVelocity = 0; + yOffset = 0; + yVelocity = 0; + rotateOffset = 0; + rotateVelocity = 0; + scaleOffset = 0; + scaleVelocity = 0; + active = false; + skeleton; + remaining = 0; + lastTime = 0; + constructor(data, skeleton) { + this.data = data; + this.skeleton = skeleton; + this.bone = skeleton.bones[data.bone.index]; + this.inertia = data.inertia; + this.strength = data.strength; + this.damping = data.damping; + this.massInverse = data.massInverse; + this.wind = data.wind; + this.gravity = data.gravity; + this.mix = data.mix; + } + reset() { + this.remaining = 0; + this.lastTime = this.skeleton.time; + this._reset = true; + this.xOffset = 0; + this.xVelocity = 0; + this.yOffset = 0; + this.yVelocity = 0; + this.rotateOffset = 0; + this.rotateVelocity = 0; + this.scaleOffset = 0; + this.scaleVelocity = 0; + } + setToSetupPose() { + const data = this.data; + this.inertia = data.inertia; + this.strength = data.strength; + this.damping = data.damping; + this.massInverse = data.massInverse; + this.wind = data.wind; + this.gravity = data.gravity; + this.mix = data.mix; + } + isActive() { + return this.active; + } + /** Applies the constraint to the constrained bones. */ + update(physics) { + const mix = this.mix; + if (mix == 0) + return; + const x = this.data.x > 0, y = this.data.y > 0, rotateOrShearX = this.data.rotate > 0 || this.data.shearX > 0, scaleX = this.data.scaleX > 0; + const bone = this.bone; + const l = bone.data.length; + switch (physics) { + case 0 /* none */: + return; + case 1 /* reset */: + this.reset(); + case 2 /* update */: + const skeleton = this.skeleton; + const delta = Math.max(this.skeleton.time - this.lastTime, 0); + this.remaining += delta; + this.lastTime = skeleton.time; + const bx = bone.worldX, by = bone.worldY; + if (this._reset) { + this._reset = false; + this.ux = bx; + this.uy = by; + } else { + let a = this.remaining, i = this.inertia, t = this.data.step, f = this.skeleton.data.referenceScale, d = -1; + let qx = this.data.limit * delta, qy = qx * Math.abs(skeleton.scaleY); + qx *= Math.abs(skeleton.scaleX); + if (x || y) { + if (x) { + const u = (this.ux - bx) * i; + this.xOffset += u > qx ? qx : u < -qx ? -qx : u; + this.ux = bx; + } + if (y) { + const u = (this.uy - by) * i; + this.yOffset += u > qy ? qy : u < -qy ? -qy : u; + this.uy = by; + } + if (a >= t) { + d = Math.pow(this.damping, 60 * t); + const m = this.massInverse * t, e = this.strength, w = this.wind * f * skeleton.scaleX, g = this.gravity * f * skeleton.scaleY; + do { + if (x) { + this.xVelocity += (w - this.xOffset * e) * m; + this.xOffset += this.xVelocity * t; + this.xVelocity *= d; + } + if (y) { + this.yVelocity -= (g + this.yOffset * e) * m; + this.yOffset += this.yVelocity * t; + this.yVelocity *= d; + } + a -= t; + } while (a >= t); + } + if (x) + bone.worldX += this.xOffset * mix * this.data.x; + if (y) + bone.worldY += this.yOffset * mix * this.data.y; + } + if (rotateOrShearX || scaleX) { + let ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0; + let dx = this.cx - bone.worldX, dy = this.cy - bone.worldY; + if (dx > qx) + dx = qx; + else if (dx < -qx) + dx = -qx; + if (dy > qy) + dy = qy; + else if (dy < -qy) + dy = -qy; + if (rotateOrShearX) { + mr = (this.data.rotate + this.data.shearX) * mix; + let r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr; + this.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i; + r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + if (scaleX) { + r = l * bone.getWorldScaleX(); + if (r > 0) + this.scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = Math.cos(ca); + s = Math.sin(ca); + const r = l * bone.getWorldScaleX(); + if (r > 0) + this.scaleOffset += (dx * c + dy * s) * i / r; + } + a = this.remaining; + if (a >= t) { + if (d == -1) + d = Math.pow(this.damping, 60 * t); + const m = this.massInverse * t, e = this.strength, w = this.wind, g = Skeleton.yDown ? -this.gravity : this.gravity, h = l / f; + while (true) { + a -= t; + if (scaleX) { + this.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m; + this.scaleOffset += this.scaleVelocity * t; + this.scaleVelocity *= d; + } + if (rotateOrShearX) { + this.rotateVelocity -= ((w * s + g * c) * h + this.rotateOffset * e) * m; + this.rotateOffset += this.rotateVelocity * t; + this.rotateVelocity *= d; + if (a < t) + break; + const r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + } else if (a < t) + break; + } + } + } + this.remaining = a; + } + this.cx = bone.worldX; + this.cy = bone.worldY; + break; + case 3 /* pose */: + if (x) + bone.worldX += this.xOffset * mix * this.data.x; + if (y) + bone.worldY += this.yOffset * mix * this.data.y; + } + if (rotateOrShearX) { + let o = this.rotateOffset * mix, s = 0, c = 0, a = 0; + if (this.data.shearX > 0) { + let r = 0; + if (this.data.rotate > 0) { + r = o * this.data.rotate; + s = Math.sin(r); + c = Math.cos(r); + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + r += o * this.data.shearX; + s = Math.sin(r); + c = Math.cos(r); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + } else { + o *= this.data.rotate; + s = Math.sin(o); + c = Math.cos(o); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + } + if (scaleX) { + const s = 1 + this.scaleOffset * mix * this.data.scaleX; + bone.a *= s; + bone.c *= s; + } + if (physics != 3 /* pose */) { + this.tx = l * bone.a; + this.ty = l * bone.c; + } + bone.updateAppliedTransform(); + } + /** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional + * amount in world space. */ + translate(x, y) { + this.ux -= x; + this.uy -= y; + this.cx -= x; + this.cy -= y; + } + /** Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the + * specified point in world space. */ + rotate(x, y, degrees) { + const r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const dx = this.cx - x, dy = this.cy - y; + this.translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); + } +}; + +// spine-core/src/Slot.ts +var Slot = class { + /** The slot's setup pose data. */ + data; + /** The bone this slot belongs to. */ + bone; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color; + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + attachment = null; + attachmentState = 0; + /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the + * {@link Sequence#getSetupIndex()}. */ + sequenceIndex = -1; + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + * + * See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */ + deform = new Array(); + constructor(data, bone) { + if (!data) + throw new Error("data cannot be null."); + if (!bone) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new Color(); + this.darkColor = !data.darkColor ? null : new Color(); + this.setToSetupPose(); + } + /** The skeleton this slot belongs to. */ + getSkeleton() { + return this.bone.skeleton; + } + /** The current attachment for the slot, or null if the slot has no attachment. */ + getAttachment() { + return this.attachment; + } + /** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}. + * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the + * specified attachment. */ + setAttachment(attachment) { + if (this.attachment == attachment) + return; + if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment != this.attachment.timelineAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.sequenceIndex = -1; + } + /** Sets this slot to the setup pose. */ + setToSetupPose() { + this.color.setFromColor(this.data.color); + if (this.darkColor) + this.darkColor.setFromColor(this.data.darkColor); + if (!this.data.attachmentName) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + } +}; + +// spine-core/src/TransformConstraint.ts +var TransformConstraint = class { + /** The transform constraint's setup pose data. */ + data; + /** The bones that will be modified by this transform constraint. */ + bones; + /** The target bone whose world transform will be copied to the constrained bones. */ + target; + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + temp = new Vector2(); + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) + throw new Error(`Couldn't find target bone ${data.target.name}.`); + this.target = target; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + } + update(physics) { + if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) + return; + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + } + applyAbsoluteWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect; + let offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * mixX; + bone.worldY += (temp.y - bone.worldY) * mixY; + } + if (mixScaleX != 0) { + let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + if (s != 0) + s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + if (s != 0) + s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let b = bone.b, d = bone.d; + let by = Math.atan2(d, b); + let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r = by + (r + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyRelativeWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * mixX; + bone.worldY += temp.y * mixY; + } + if (mixScaleX != 0) { + let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + let b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyAbsoluteLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation; + if (mixRotate != 0) + rotation += (target.arotation - rotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax, y = bone.ay; + x += (target.ax - x + this.data.offsetX) * mixX; + y += (target.ay - y + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY; + let shearY = bone.ashearY; + if (mixShearY != 0) + shearY += (target.ashearY - shearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + applyRelativeLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax + (target.ax + this.data.offsetX) * mixX; + let y = bone.ay + (target.ay + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1); + let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1); + let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } +}; + +// spine-core/src/Skeleton.ts +var _Skeleton = class { + /** The skeleton's setup pose data. */ + data; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones; + /** The skeleton's slots in the setup pose draw order. */ + slots; + /** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */ + drawOrder; + /** The skeleton's IK constraints. */ + ikConstraints; + /** The skeleton's transform constraints. */ + transformConstraints; + /** The skeleton's path constraints. */ + pathConstraints; + /** The skeleton's physics constraints. */ + physicsConstraints; + /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */ + _updateCache = new Array(); + /** The skeleton's current skin. May be null. */ + skin = null; + /** The color to tint all the skeleton's attachments. */ + color; + /** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + scaleX = 1; + /** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + _scaleY = 1; + get scaleY() { + return _Skeleton.yDown ? -this._scaleY : this._scaleY; + } + set scaleY(scaleY) { + this._scaleY = scaleY; + } + /** Sets the skeleton X position, which is added to the root bone worldX position. */ + x = 0; + /** Sets the skeleton Y position, which is added to the root bone worldY position. */ + y = 0; + /** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}. + *

    + * See {@link #update(float)}. */ + time = 0; + constructor(data) { + if (!data) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let boneData = data.bones[i]; + let bone; + if (!boneData.parent) + bone = new Bone(boneData, this, null); + else { + let parent = this.bones[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (let i = 0; i < data.slots.length; i++) { + let slotData = data.slots[i]; + let bone = this.bones[slotData.boneData.index]; + let slot = new Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (let i = 0; i < data.ikConstraints.length; i++) { + let ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (let i = 0; i < data.transformConstraints.length; i++) { + let transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (let i = 0; i < data.pathConstraints.length; i++) { + let pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new PathConstraint(pathConstraintData, this)); + } + this.physicsConstraints = new Array(); + for (let i = 0; i < data.physicsConstraints.length; i++) { + let physicsConstraintData = data.physicsConstraints[i]; + this.physicsConstraints.push(new PhysicsConstraint(physicsConstraintData, this)); + } + this.color = new Color(1, 1, 1, 1); + this.updateCache(); + } + /** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones, + * constraints, or weighted path attachments are added or removed. */ + updateCache() { + let updateCache = this._updateCache; + updateCache.length = 0; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + } + if (this.skin) { + let skinBones = this.skin.bones; + for (let i = 0, n = this.skin.bones.length; i < n; i++) { + let bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone); + } + } + let ikConstraints = this.ikConstraints; + let transformConstraints = this.transformConstraints; + let pathConstraints = this.pathConstraints; + let physicsConstraints = this.physicsConstraints; + let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length, physicsCount = this.physicsConstraints.length; + let constraintCount = ikCount + transformCount + pathCount + physicsCount; + outer: + for (let i = 0; i < constraintCount; i++) { + for (let ii = 0; ii < ikCount; ii++) { + let constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < transformCount; ii++) { + let constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < pathCount; ii++) { + let constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < physicsCount; ii++) { + const constraint = physicsConstraints[ii]; + if (constraint.data.order == i) { + this.sortPhysicsConstraint(constraint); + continue outer; + } + } + } + for (let i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + } + sortIkConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let target = constraint.target; + this.sortBone(target); + let constrained = constraint.bones; + let parent = constrained[0]; + this.sortBone(parent); + if (constrained.length == 1) { + this._updateCache.push(constraint); + this.sortReset(parent.children); + } else { + let child = constrained[constrained.length - 1]; + this.sortBone(child); + this._updateCache.push(constraint); + this.sortReset(parent.children); + child.sorted = true; + } + } + sortPathConstraint(constraint) { + constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let slot = constraint.target; + let slotIndex = slot.data.index; + let slotBone = slot.bone; + if (this.skin) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (let i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + let attachment = slot.getAttachment(); + if (attachment instanceof PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + let constrained = constraint.bones; + let boneCount = constrained.length; + for (let i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortTransformConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + this.sortBone(constraint.target); + let constrained = constraint.bones; + let boneCount = constrained.length; + if (constraint.data.local) { + for (let i = 0; i < boneCount; i++) { + let child = constrained[i]; + this.sortBone(child.parent); + this.sortBone(child); + } + } else { + for (let i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortPathConstraintAttachment(skin, slotIndex, slotBone) { + let attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (let key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + } + sortPathConstraintAttachmentWith(attachment, slotBone) { + if (!(attachment instanceof PathAttachment)) + return; + let pathBones = attachment.bones; + if (!pathBones) + this.sortBone(slotBone); + else { + let bones = this.bones; + for (let i = 0, n = pathBones.length; i < n; ) { + let nn = pathBones[i++]; + nn += i; + while (i < nn) + this.sortBone(bones[pathBones[i++]]); + } + } + } + sortPhysicsConstraint(constraint) { + const bone = constraint.bone; + constraint.active = bone.active && (!constraint.data.skinRequired || this.skin != null && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + this.sortBone(bone); + this._updateCache.push(constraint); + this.sortReset(bone.children); + bone.sorted = true; + } + sortBone(bone) { + if (!bone) + return; + if (bone.sorted) + return; + let parent = bone.parent; + if (parent) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + } + sortReset(bones) { + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (!bone.active) + continue; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + } + /** Updates the world transform for each bone and applies all constraints. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransform(physics) { + if (physics === void 0 || physics === null) + throw new Error("physics is undefined"); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(physics); + } + updateWorldTransformWith(physics, parent) { + if (!parent) + throw new Error("parent cannot be null."); + let bones = this.bones; + for (let i = 1, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let rootBone = this.getRootBone(); + if (!rootBone) + throw new Error("Root bone must not be null."); + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + rootBone.worldX = pa * this.x + pb * this.y + parent.worldX; + rootBone.worldY = pc * this.x + pd * this.y + parent.worldY; + const rx = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad; + const ry = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad; + const la = Math.cos(rx) * rootBone.scaleX; + const lb = Math.cos(ry) * rootBone.scaleY; + const lc = Math.sin(rx) * rootBone.scaleX; + const ld = Math.sin(ry) * rootBone.scaleY; + rootBone.a = (pa * la + pb * lc) * this.scaleX; + rootBone.b = (pa * lb + pb * ld) * this.scaleX; + rootBone.c = (pc * la + pd * lc) * this.scaleY; + rootBone.d = (pc * lb + pd * ld) * this.scaleY; + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) { + let updatable = updateCache[i]; + if (updatable != rootBone) + updatable.update(physics); + } + } + /** Sets the bones, constraints, and slots to their setup pose values. */ + setToSetupPose() { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + } + /** Sets the bones and constraints to their setup pose values. */ + setBonesToSetupPose() { + for (const bone of this.bones) + bone.setToSetupPose(); + for (const constraint of this.ikConstraints) + constraint.setToSetupPose(); + for (const constraint of this.transformConstraints) + constraint.setToSetupPose(); + for (const constraint of this.pathConstraints) + constraint.setToSetupPose(); + for (const constraint of this.physicsConstraints) + constraint.setToSetupPose(); + } + /** Sets the slots and draw order to their setup pose values. */ + setSlotsToSetupPose() { + let slots = this.slots; + Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (let i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + } + /** @returns May return null. */ + getRootBone() { + if (this.bones.length == 0) + return null; + return this.bones[0]; + } + /** @returns May be null. */ + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * repeatedly. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + } + /** Sets a skin by name. + * + * See {@link #setSkin()}. */ + setSkinByName(skinName) { + let skin = this.data.findSkin(skinName); + if (!skin) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + } + /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the + * skin is changed, {@link #updateCache()} is called. + * + * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no + * old skin, each slot's setup mode attachment is attached from the new skin. + * + * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the + * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + * @param newSkin May be null. */ + setSkin(newSkin) { + if (newSkin == this.skin) + return; + if (newSkin) { + if (this.skin) + newSkin.attachAll(this, this.skin); + else { + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let name = slot.data.attachmentName; + if (name) { + let attachment = newSkin.getAttachment(i, name); + if (attachment) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment + * name. + * + * See {@link #getAttachment()}. + * @returns May be null. */ + getAttachmentByName(slotName, attachmentName) { + let slot = this.data.findSlot(slotName); + if (!slot) + throw new Error(`Can't find slot with name ${slotName}`); + return this.getAttachment(slot.index, attachmentName); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and + * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. + * + * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. + * @returns May be null. */ + getAttachment(slotIndex, attachmentName) { + if (!attachmentName) + throw new Error("attachmentName cannot be null."); + if (this.skin) { + let attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) + return attachment; + } + if (this.data.defaultSkin) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + } + /** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with + * {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}. + * @param attachmentName May be null to clear the slot's attachment. */ + setAttachment(slotName, attachmentName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) { + let attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (!attachment) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + return this.ikConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it repeatedly. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + return this.transformConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + return this.pathConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this + * method than to call it repeatedly. */ + findPhysicsConstraint(constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + return this.physicsConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`. + * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */ + getBoundsRect(clipper) { + let offset = new Vector2(); + let size = new Vector2(); + this.getBounds(offset, size, void 0, clipper); + return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. + * @param size An output value, the width and height of the AABB. + * @param temp Working memory to temporarily store attachments' computed world vertices. + * @param clipper {@link SkeletonClipping} to use. If null, no clipping is applied. */ + getBounds(offset, size, temp = new Array(2), clipper = null) { + if (!offset) + throw new Error("offset cannot be null."); + if (!size) + throw new Error("size cannot be null."); + let drawOrder = this.drawOrder; + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + if (!slot.bone.active) + continue; + let verticesLength = 0; + let vertices = null; + let triangles = null; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot, vertices, 0, 2); + triangles = _Skeleton.quadTriangles; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + triangles = mesh.triangles; + } else if (attachment instanceof ClippingAttachment && clipper != null) { + clipper.clipStart(slot, attachment); + continue; + } + if (vertices && triangles) { + if (clipper != null && clipper.isClipping()) { + clipper.clipTriangles(vertices, triangles, triangles.length); + vertices = clipper.clippedVertices; + verticesLength = clipper.clippedVertices.length; + } + for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + if (clipper != null) + clipper.clipEndWithSlot(slot); + } + if (clipper != null) + clipper.clipEnd(); + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + } + /** Increments the skeleton's {@link #time}. */ + update(delta) { + this.time += delta; + } + physicsTranslate(x, y) { + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) + physicsConstraints[i].translate(x, y); + } + /** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */ + physicsRotate(x, y, degrees) { + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) + physicsConstraints[i].rotate(x, y, degrees); + } +}; +var Skeleton = _Skeleton; +__publicField(Skeleton, "quadTriangles", [0, 1, 2, 2, 3, 0]); +__publicField(Skeleton, "yDown", false); +var Physics = /* @__PURE__ */ ((Physics2) => { + Physics2[Physics2["none"] = 0] = "none"; + Physics2[Physics2["reset"] = 1] = "reset"; + Physics2[Physics2["update"] = 2] = "update"; + Physics2[Physics2["pose"] = 3] = "pose"; + return Physics2; +})(Physics || {}); + +// spine-core/src/PhysicsConstraintData.ts +var PhysicsConstraintData = class extends ConstraintData { + _bone = null; + /** The bone constrained by this physics constraint. */ + set bone(boneData) { + this._bone = boneData; + } + get bone() { + if (!this._bone) + throw new Error("BoneData not set."); + else + return this._bone; + } + x = 0; + y = 0; + rotate = 0; + scaleX = 0; + shearX = 0; + limit = 0; + step = 0; + inertia = 0; + strength = 0; + damping = 0; + massInverse = 0; + wind = 0; + gravity = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ + mix = 0; + inertiaGlobal = false; + strengthGlobal = false; + dampingGlobal = false; + massGlobal = false; + windGlobal = false; + gravityGlobal = false; + mixGlobal = false; + constructor(name) { + super(name, 0, false); + } +}; + +// spine-core/src/SkeletonData.ts +var SkeletonData = class { + /** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */ + name = null; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones = new Array(); + // Ordered parents first. + /** The skeleton's slots in the setup pose draw order. */ + slots = new Array(); + // Setup pose draw order. + skins = new Array(); + /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. + * + * See {@link Skeleton#getAttachmentByName()}. + * May be null. */ + defaultSkin = null; + /** The skeleton's events. */ + events = new Array(); + /** The skeleton's animations. */ + animations = new Array(); + /** The skeleton's IK constraints. */ + ikConstraints = new Array(); + /** The skeleton's transform constraints. */ + transformConstraints = new Array(); + /** The skeleton's path constraints. */ + pathConstraints = new Array(); + /** The skeleton's physics constraints. */ + physicsConstraints = new Array(); + /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + x = 0; + /** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + y = 0; + /** The width of the skeleton's axis aligned bounding box in the setup pose. */ + width = 0; + /** The height of the skeleton's axis aligned bounding box in the setup pose. */ + height = 0; + /** Baseline scale factor for applying distance-dependent effects on non-scalable properties, such as angle or scale. Default + * is 100. */ + referenceScale = 100; + /** The Spine version used to export the skeleton data, or null. */ + version = null; + /** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */ + hash = null; + // Nonessential + /** The dopesheet FPS in Spine. Available only when nonessential data was exported. */ + fps = 0; + /** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + imagesPath = null; + /** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + audioPath = null; + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + } + /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSkin(skinName) { + if (!skinName) + throw new Error("skinName cannot be null."); + let skins = this.skins; + for (let i = 0, n = skins.length; i < n; i++) { + let skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + } + /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findEvent(eventDataName) { + if (!eventDataName) + throw new Error("eventDataName cannot be null."); + let events = this.events; + for (let i = 0, n = events.length; i < n; i++) { + let event = events[i]; + if (event.name == eventDataName) + return event; + } + return null; + } + /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to + * call it multiple times. + * @returns May be null. */ + findAnimation(animationName) { + if (!animationName) + throw new Error("animationName cannot be null."); + let animations = this.animations; + for (let i = 0, n = animations.length; i < n; i++) { + let animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + const constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it multiple times. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + const constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + const constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPhysicsConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) { + const constraint = physicsConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } +}; + +// spine-core/src/Skin.ts +var SkinEntry = class { + constructor(slotIndex = 0, name, attachment) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } +}; +var Skin = class { + /** The skin's name, which is unique across all skins in the skeleton. */ + name; + attachments = new Array(); + bones = Array(); + constraints = new Array(); + /** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */ + color = new Color(0.99607843, 0.61960787, 0.30980393, 1); + // fe9e4fff + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + /** Adds an attachment to the skin for the specified slot index and name. */ + setAttachment(slotIndex, name, attachment) { + if (!attachment) + throw new Error("attachment cannot be null."); + let attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + } + /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ + addSkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + /** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not + * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ + copySkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (!attachment.attachment) + continue; + if (attachment.attachment instanceof MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + } + /** Returns the attachment for the specified slot index and name, or null. */ + getAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + } + /** Removes the attachment in the skin for the specified slot index and name, if any. */ + removeAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + if (dictionary) + delete dictionary[name]; + } + /** Returns all attachments in this skin. */ + getAttachments() { + let entries = new Array(); + for (var i = 0; i < this.attachments.length; i++) { + let slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + entries.push(new SkinEntry(i, name, attachment)); + } + } + } + return entries; + } + /** Returns all attachments in this skin for the specified slot index. */ + getAttachmentsForSlot(slotIndex, attachments) { + let slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + attachments.push(new SkinEntry(slotIndex, name, attachment)); + } + } + } + /** Clears all attachments, bones, and constraints. */ + clear() { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + } + /** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */ + attachAll(skeleton, oldSkin) { + let slotIndex = 0; + for (let i = 0; i < skeleton.slots.length; i++) { + let slot = skeleton.slots[i]; + let slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + let dictionary = oldSkin.attachments[slotIndex]; + for (let key in dictionary) { + let skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + let attachment = this.getAttachment(slotIndex, key); + if (attachment) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + } +}; + +// spine-core/src/SlotData.ts +var SlotData = class { + /** The index of the slot in {@link Skeleton#getSlots()}. */ + index = 0; + /** The name of the slot, which is unique across all slots in the skeleton. */ + name; + /** The bone this slot belongs to. */ + boneData; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color = new Color(1, 1, 1, 1); + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */ + attachmentName = null; + /** The blend mode for drawing the slot's attachment. */ + blendMode = BlendMode.Normal; + /** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = true; + constructor(index, name, boneData) { + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + if (!boneData) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } +}; +var BlendMode = /* @__PURE__ */ ((BlendMode4) => { + BlendMode4[BlendMode4["Normal"] = 0] = "Normal"; + BlendMode4[BlendMode4["Additive"] = 1] = "Additive"; + BlendMode4[BlendMode4["Multiply"] = 2] = "Multiply"; + BlendMode4[BlendMode4["Screen"] = 3] = "Screen"; + return BlendMode4; +})(BlendMode || {}); + +// spine-core/src/TransformConstraintData.ts +var TransformConstraintData = class extends ConstraintData { + /** The bones that will be modified by this transform constraint. */ + bones = new Array(); + /** The target bone whose world transform will be copied to the constrained bones. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** An offset added to the constrained bone X translation. */ + offsetX = 0; + /** An offset added to the constrained bone Y translation. */ + offsetY = 0; + /** An offset added to the constrained bone scaleX. */ + offsetScaleX = 0; + /** An offset added to the constrained bone scaleY. */ + offsetScaleY = 0; + /** An offset added to the constrained bone shearY. */ + offsetShearY = 0; + relative = false; + local = false; + constructor(name) { + super(name, 0, false); + } +}; + +// spine-core/src/SkeletonBinary.ts +var SkeletonBinary = class { + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + attachmentLoader; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(binary) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + skeletonData.name = ""; + let input = new BinaryInput(binary); + let lowHash = input.readInt32(); + let highHash = input.readInt32(); + skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16); + skeletonData.version = input.readString(); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + skeletonData.referenceScale = input.readFloat() * scale; + let nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + let n = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let str = input.readString(); + if (!str) + throw new Error("String in string table must not be null."); + input.strings.push(str); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Bone name must not be null."); + let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)]; + let data = new BoneData(i, name, parent); + data.rotation = input.readFloat(); + data.x = input.readFloat() * scale; + data.y = input.readFloat() * scale; + data.scaleX = input.readFloat(); + data.scaleY = input.readFloat(); + data.shearX = input.readFloat(); + data.shearY = input.readFloat(); + data.length = input.readFloat() * scale; + data.inherit = input.readByte(); + data.skinRequired = input.readBoolean(); + if (nonessential) { + Color.rgba8888ToColor(data.color, input.readInt32()); + data.icon = input.readString() ?? void 0; + data.visible = input.readBoolean(); + } + skeletonData.bones.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let slotName = input.readString(); + if (!slotName) + throw new Error("Slot name must not be null."); + let boneData = skeletonData.bones[input.readInt(true)]; + let data = new SlotData(i, slotName, boneData); + Color.rgba8888ToColor(data.color, input.readInt32()); + let darkColor = input.readInt32(); + if (darkColor != -1) + Color.rgb888ToColor(data.darkColor = new Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = input.readInt(true); + if (nonessential) + data.visible = input.readBoolean(); + skeletonData.slots.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("IK constraint data name must not be null."); + let data = new IkConstraintData(name); + data.order = input.readInt(true); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + data.bendDirection = (flags & 2) != 0 ? 1 : -1; + data.compress = (flags & 4) != 0; + data.stretch = (flags & 8) != 0; + data.uniform = (flags & 16) != 0; + if ((flags & 32) != 0) + data.mix = (flags & 64) != 0 ? input.readFloat() : 1; + if ((flags & 128) != 0) + data.softness = input.readFloat() * scale; + skeletonData.ikConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Transform constraint data name must not be null."); + let data = new TransformConstraintData(name); + data.order = input.readInt(true); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + data.local = (flags & 2) != 0; + data.relative = (flags & 4) != 0; + if ((flags & 8) != 0) + data.offsetRotation = input.readFloat(); + if ((flags & 16) != 0) + data.offsetX = input.readFloat() * scale; + if ((flags & 32) != 0) + data.offsetY = input.readFloat() * scale; + if ((flags & 64) != 0) + data.offsetScaleX = input.readFloat(); + if ((flags & 128) != 0) + data.offsetScaleY = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) != 0) + data.offsetShearY = input.readFloat(); + if ((flags & 2) != 0) + data.mixRotate = input.readFloat(); + if ((flags & 4) != 0) + data.mixX = input.readFloat(); + if ((flags & 8) != 0) + data.mixY = input.readFloat(); + if ((flags & 16) != 0) + data.mixScaleX = input.readFloat(); + if ((flags & 32) != 0) + data.mixScaleY = input.readFloat(); + if ((flags & 64) != 0) + data.mixShearY = input.readFloat(); + skeletonData.transformConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Path constraint data name must not be null."); + let data = new PathConstraintData(name); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.slots[input.readInt(true)]; + const flags = input.readByte(); + data.positionMode = flags & 1; + data.spacingMode = flags >> 1 & 3; + data.rotateMode = flags >> 3 & 3; + if ((flags & 128) != 0) + data.offsetRotation = input.readFloat(); + data.position = input.readFloat(); + if (data.positionMode == 0 /* Fixed */) + data.position *= scale; + data.spacing = input.readFloat(); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) + data.spacing *= scale; + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + skeletonData.pathConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + const name = input.readString(); + if (!name) + throw new Error("Physics constraint data name must not be null."); + const data = new PhysicsConstraintData(name); + data.order = input.readInt(true); + data.bone = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) + data.x = input.readFloat(); + if ((flags & 4) != 0) + data.y = input.readFloat(); + if ((flags & 8) != 0) + data.rotate = input.readFloat(); + if ((flags & 16) != 0) + data.scaleX = input.readFloat(); + if ((flags & 32) != 0) + data.shearX = input.readFloat(); + data.limit = ((flags & 64) != 0 ? input.readFloat() : 5e3) * scale; + data.step = 1 / input.readUnsignedByte(); + data.inertia = input.readFloat(); + data.strength = input.readFloat(); + data.damping = input.readFloat(); + data.massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + data.wind = input.readFloat(); + data.gravity = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) != 0) + data.inertiaGlobal = true; + if ((flags & 2) != 0) + data.strengthGlobal = true; + if ((flags & 4) != 0) + data.dampingGlobal = true; + if ((flags & 8) != 0) + data.massGlobal = true; + if ((flags & 16) != 0) + data.windGlobal = true; + if ((flags & 32) != 0) + data.gravityGlobal = true; + if ((flags & 64) != 0) + data.mixGlobal = true; + data.mix = (flags & 128) != 0 ? input.readFloat() : 1; + skeletonData.physicsConstraints.push(data); + } + let defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + let i = skeletonData.skins.length; + Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) { + let skin = this.readSkin(input, skeletonData, false, nonessential); + if (!skin) + throw new Error("readSkin() should not have returned null."); + skeletonData.skins[i] = skin; + } + } + n = this.linkedMeshes.length; + for (let i = 0; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + const skin = skeletonData.skins[linkedMesh.skinIndex]; + if (!linkedMesh.parent) + throw new Error("Linked mesh parent must not be null"); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) + throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) + linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let eventName = input.readString(); + if (!eventName) + throw new Error("Event data name must not be null"); + let data = new EventData(eventName); + data.intValue = input.readInt(false); + data.floatValue = input.readFloat(); + data.stringValue = input.readString(); + data.audioPath = input.readString(); + if (data.audioPath) { + data.volume = input.readFloat(); + data.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let animationName = input.readString(); + if (!animationName) + throw new Error("Animatio name must not be null."); + skeletonData.animations.push(this.readAnimation(input, animationName, skeletonData)); + } + return skeletonData; + } + readSkin(input, skeletonData, defaultSkin, nonessential) { + let skin = null; + let slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) + return null; + skin = new Skin("default"); + } else { + let skinName = input.readString(); + if (!skinName) + throw new Error("Skin name must not be null."); + skin = new Skin(skinName); + if (nonessential) + Color.rgba8888ToColor(skin.color, input.readInt32()); + skin.bones.length = input.readInt(true); + for (let i = 0, n = skin.bones.length; i < n; i++) + skin.bones[i] = skeletonData.bones[input.readInt(true)]; + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.physicsConstraints[input.readInt(true)]); + slotCount = input.readInt(true); + } + for (let i = 0; i < slotCount; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let name = input.readStringRef(); + if (!name) + throw new Error("Attachment name must not be null"); + let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); + if (attachment) + skin.setAttachment(slotIndex, name, attachment); + } + } + return skin; + } + readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) { + let scale = this.scale; + let flags = input.readByte(); + const name = (flags & 8) != 0 ? input.readStringRef() : attachmentName; + if (!name) + throw new Error("Attachment name must not be null"); + switch (flags & 7) { + case AttachmentType.Region: { + let path = (flags & 16) != 0 ? input.readStringRef() : null; + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + let rotation = (flags & 128) != 0 ? input.readFloat() : 0; + let x = input.readFloat(); + let y = input.readFloat(); + let scaleX = input.readFloat(); + let scaleY = input.readFloat(); + let width = input.readFloat(); + let height = input.readFloat(); + if (!path) + path = name; + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) + return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + Color.rgba8888ToColor(region.color, color); + region.sequence = sequence; + if (sequence == null) + region.updateRegion(); + return region; + } + case AttachmentType.BoundingBox: { + let vertices = this.readVertices(input, (flags & 16) != 0); + let color = nonessential ? input.readInt32() : 0; + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + box.worldVerticesLength = vertices.length; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(box.color, color); + return box; + } + case AttachmentType.Mesh: { + let path = (flags & 16) != 0 ? input.readStringRef() : name; + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + const hullLength = input.readInt(true); + const vertices = this.readVertices(input, (flags & 128) != 0); + const uvs = this.readFloatArray(input, vertices.length, 1); + const triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3); + let edges = []; + let width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input, input.readInt(true)); + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) + path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertices.length; + mesh.triangles = triangles; + mesh.regionUVs = uvs; + if (sequence == null) + mesh.updateRegion(); + mesh.hullLength = hullLength << 1; + mesh.sequence = sequence; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + return mesh; + } + case AttachmentType.LinkedMesh: { + const path = (flags & 16) != 0 ? input.readStringRef() : name; + if (path == null) + throw new Error("Path of linked mesh must not be null"); + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + const inheritTimelines = (flags & 128) != 0; + const skinIndex = input.readInt(true); + const parent = input.readStringRef(); + let width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.sequence = sequence; + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinIndex, slotIndex, parent, inheritTimelines)); + return mesh; + } + case AttachmentType.Path: { + const closed2 = (flags & 16) != 0; + const constantSpeed = (flags & 32) != 0; + const vertices = this.readVertices(input, (flags & 64) != 0); + const lengths = Utils.newArray(vertices.length / 6, 0); + for (let i = 0, n = lengths.length; i < n; i++) + lengths[i] = input.readFloat() * scale; + const color = nonessential ? input.readInt32() : 0; + const path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = closed2; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertices.length; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) + Color.rgba8888ToColor(path.color, color); + return path; + } + case AttachmentType.Point: { + const rotation = input.readFloat(); + const x = input.readFloat(); + const y = input.readFloat(); + const color = nonessential ? input.readInt32() : 0; + const point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) + Color.rgba8888ToColor(point.color, color); + return point; + } + case AttachmentType.Clipping: { + const endSlotIndex = input.readInt(true); + const vertices = this.readVertices(input, (flags & 16) != 0); + let color = nonessential ? input.readInt32() : 0; + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.worldVerticesLength = vertices.length; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + return null; + } + readSequence(input) { + let sequence = new Sequence(input.readInt(true)); + sequence.start = input.readInt(true); + sequence.digits = input.readInt(true); + sequence.setupIndex = input.readInt(true); + return sequence; + } + readVertices(input, weighted) { + const scale = this.scale; + const vertexCount = input.readInt(true); + const vertices = new Vertices(); + vertices.length = vertexCount << 1; + if (!weighted) { + vertices.vertices = this.readFloatArray(input, vertices.length, scale); + return vertices; + } + let weights = new Array(); + let bonesArray = new Array(); + for (let i = 0; i < vertexCount; i++) { + let boneCount = input.readInt(true); + bonesArray.push(boneCount); + for (let ii = 0; ii < boneCount; ii++) { + bonesArray.push(input.readInt(true)); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat()); + } + } + vertices.vertices = Utils.toFloatArray(weights); + vertices.bones = bonesArray; + return vertices; + } + readFloatArray(input, n, scale) { + let array = new Array(n); + if (scale == 1) { + for (let i = 0; i < n; i++) + array[i] = input.readFloat(); + } else { + for (let i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + } + readShortArray(input, n) { + let array = new Array(n); + for (let i = 0; i < n; i++) + array[i] = input.readInt(true); + return array; + } + readAnimation(input, name, skeletonData) { + input.readInt(true); + let timelines = new Array(); + let scale = this.scale; + for (let i = 0, n = input.readInt(true); i < n; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + let timeline = new AttachmentTimeline(frameCount, slotIndex); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + break; + } + case SLOT_RGBA: { + let bezierCount = input.readInt(true); + let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB: { + let bezierCount = input.readInt(true); + let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.push(timeline); + break; + } + case SLOT_RGBA2: { + let bezierCount = input.readInt(true); + let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let na = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB2: { + let bezierCount = input.readInt(true); + let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_ALPHA: { + let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + let time = input.readFloat(), a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.push(timeline); + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let boneIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let type = input.readByte(), frameCount = input.readInt(true); + if (type == BONE_INHERIT) { + let timeline = new InheritTimeline(frameCount, boneIndex); + for (let frame = 0; frame < frameCount; frame++) { + timeline.setFrame(frame, input.readFloat(), input.readByte()); + } + timelines.push(timeline); + continue; + } + let bezierCount = input.readInt(true); + switch (type) { + case BONE_ROTATE: + timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_TRANSLATE: + timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEX: + timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEY: + timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_SCALE: + timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEX: + timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEY: + timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEAR: + timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARX: + timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARY: + timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + let flags = input.readByte(); + let time = input.readFloat(), mix = (flags & 1) != 0 ? (flags & 2) != 0 ? input.readFloat() : 1 : 0; + let softness = (flags & 4) != 0 ? input.readFloat() * scale : 0; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0); + if (frame == frameLast) + break; + flags = input.readByte(); + const time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? (flags & 2) != 0 ? input.readFloat() : 1 : 0; + const softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0; + if ((flags & 64) != 0) { + timeline.setStepped(frame); + } else if ((flags & 128) != 0) { + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true); + let data = skeletonData.pathConstraints[index]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case PATH_POSITION: + timelines.push(readTimeline1( + input, + new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data.positionMode == 0 /* Fixed */ ? scale : 1 + )); + break; + case PATH_SPACING: + timelines.push(readTimeline1( + input, + new PathConstraintSpacingTimeline(frameCount, bezierCount, index), + data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */ ? scale : 1 + )); + break; + case PATH_MIX: + let timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.push(timeline); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true) - 1; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true); + if (type == PHYSICS_RESET) { + const timeline = new PhysicsConstraintResetTimeline(frameCount, index); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat()); + timelines.push(timeline); + continue; + } + const bezierCount = input.readInt(true); + switch (type) { + case PHYSICS_INERTIA: + timelines.push(readTimeline1(input, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_STRENGTH: + timelines.push(readTimeline1(input, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_DAMPING: + timelines.push(readTimeline1(input, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_MASS: + timelines.push(readTimeline1(input, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_WIND: + timelines.push(readTimeline1(input, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_GRAVITY: + timelines.push(readTimeline1(input, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_MIX: + timelines.push(readTimeline1(input, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let skin = skeletonData.skins[input.readInt(true)]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let slotIndex = input.readInt(true); + for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + let attachmentName = input.readStringRef(); + if (!attachmentName) + throw new Error("attachmentName must not be null."); + let attachment = skin.getAttachment(slotIndex, attachmentName); + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + let vertexAttachment = attachment; + let weighted = vertexAttachment.bones; + let vertices = vertexAttachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let bezierCount = input.readInt(true); + let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); + let time = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let end = input.readInt(true); + if (end == 0) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = input.readInt(true); + end += start; + if (scale == 1) { + for (let v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (let v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (let v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frame, time, deform); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + timelines.push(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + let timeline = new SequenceTimeline(frameCount, slotIndex, attachment); + for (let frame = 0; frame < frameCount; frame++) { + let time = input.readFloat(); + let modeAndIndex = input.readInt32(); + timeline.setFrame( + frame, + time, + SequenceModeValues[modeAndIndex & 15], + modeAndIndex >> 4, + input.readFloat() + ); + } + timelines.push(timeline); + break; + } + } + } + } + } + let drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + let timeline = new DrawOrderTimeline(drawOrderCount); + let slotCount = skeletonData.slots.length; + for (let i = 0; i < drawOrderCount; i++) { + let time = input.readFloat(); + let offsetCount = input.readInt(true); + let drawOrder = Utils.newArray(slotCount, 0); + for (let ii = slotCount - 1; ii >= 0; ii--) + drawOrder[ii] = -1; + let unchanged = Utils.newArray(slotCount - offsetCount, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsetCount; ii++) { + let slotIndex = input.readInt(true); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + timeline.setFrame(i, time, drawOrder); + } + timelines.push(timeline); + } + let eventCount = input.readInt(true); + if (eventCount > 0) { + let timeline = new EventTimeline(eventCount); + for (let i = 0; i < eventCount; i++) { + let time = input.readFloat(); + let eventData = skeletonData.events[input.readInt(true)]; + let event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readString(); + if (event.stringValue == null) + event.stringValue = eventData.stringValue; + if (event.data.audioPath) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + return new Animation(name, timelines, duration); + } +}; +var BinaryInput = class { + constructor(data, strings = new Array(), index = 0, buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) { + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + readByte() { + return this.buffer.getInt8(this.index++); + } + readUnsignedByte() { + return this.buffer.getUint8(this.index++); + } + readShort() { + let value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + } + readInt32() { + let value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + } + readInt(optimizePositive) { + let b = this.readByte(); + let result = b & 127; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 7; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 14; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 21; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 28; + } + } + } + } + return optimizePositive ? result : result >>> 1 ^ -(result & 1); + } + readStringRef() { + let index = this.readInt(true); + return index == 0 ? null : this.strings[index - 1]; + } + readString() { + let byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + let chars = ""; + let charCount = 0; + for (let i = 0; i < byteCount; ) { + let b = this.readUnsignedByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63); + i += 2; + break; + case 14: + chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + } + readFloat() { + let value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + } + readBoolean() { + return this.readByte() != 0; + } +}; +var LinkedMesh = class { + parent; + skinIndex; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skinIndex, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skinIndex = skinIndex; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } +}; +var Vertices = class { + constructor(bones = null, vertices = null, length = 0) { + this.bones = bones; + this.vertices = vertices; + this.length = length; + } +}; +var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => { + AttachmentType2[AttachmentType2["Region"] = 0] = "Region"; + AttachmentType2[AttachmentType2["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType2[AttachmentType2["Mesh"] = 2] = "Mesh"; + AttachmentType2[AttachmentType2["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType2[AttachmentType2["Path"] = 4] = "Path"; + AttachmentType2[AttachmentType2["Point"] = 5] = "Point"; + AttachmentType2[AttachmentType2["Clipping"] = 6] = "Clipping"; + return AttachmentType2; +})(AttachmentType || {}); +function readTimeline1(input, timeline, scale) { + let time = input.readFloat(), value = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value); + if (frame == frameLast) + break; + let time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; +} +function readTimeline2(input, timeline, scale) { + let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame == frameLast) + break; + let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; +} +function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2); +} +var BONE_ROTATE = 0; +var BONE_TRANSLATE = 1; +var BONE_TRANSLATEX = 2; +var BONE_TRANSLATEY = 3; +var BONE_SCALE = 4; +var BONE_SCALEX = 5; +var BONE_SCALEY = 6; +var BONE_SHEAR = 7; +var BONE_SHEARX = 8; +var BONE_SHEARY = 9; +var BONE_INHERIT = 10; +var SLOT_ATTACHMENT = 0; +var SLOT_RGBA = 1; +var SLOT_RGB = 2; +var SLOT_RGBA2 = 3; +var SLOT_RGB2 = 4; +var SLOT_ALPHA = 5; +var ATTACHMENT_DEFORM = 0; +var ATTACHMENT_SEQUENCE = 1; +var PATH_POSITION = 0; +var PATH_SPACING = 1; +var PATH_MIX = 2; +var PHYSICS_INERTIA = 0; +var PHYSICS_STRENGTH = 1; +var PHYSICS_DAMPING = 2; +var PHYSICS_MASS = 4; +var PHYSICS_WIND = 5; +var PHYSICS_GRAVITY = 6; +var PHYSICS_MIX = 7; +var PHYSICS_RESET = 8; +var CURVE_STEPPED = 1; +var CURVE_BEZIER = 2; + +// spine-core/src/SkeletonBounds.ts +var SkeletonBounds = class { + /** The left edge of the axis aligned bounding box. */ + minX = 0; + /** The bottom edge of the axis aligned bounding box. */ + minY = 0; + /** The right edge of the axis aligned bounding box. */ + maxX = 0; + /** The top edge of the axis aligned bounding box. */ + maxY = 0; + /** The visible bounding boxes. */ + boundingBoxes = new Array(); + /** The world vertices for the bounding box polygons. */ + polygons = new Array(); + polygonPool = new Pool(() => { + return Utils.newFloatArray(16); + }); + /** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding + * box's polygon. + * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the + * SkeletonBounds AABB methods will always return true. */ + update(skeleton, updateAabb) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + let boundingBoxes = this.boundingBoxes; + let polygons = this.polygons; + let polygonPool = this.polygonPool; + let slots = skeleton.slots; + let slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (let i = 0; i < slotCount; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (attachment instanceof BoundingBoxAttachment) { + let boundingBox = attachment; + boundingBoxes.push(boundingBox); + let polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + } + aabbCompute() { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + let vertices = polygon; + for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { + let x = vertices[ii]; + let y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + } + /** Returns true if the axis aligned bounding box contains the point. */ + aabbContainsPoint(x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + } + /** Returns true if the axis aligned bounding box intersects the line segment. */ + aabbIntersectsSegment(x1, y1, x2, y2) { + let minX = this.minX; + let minY = this.minY; + let maxX = this.maxX; + let maxY = this.maxY; + if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY) + return false; + let m = (y2 - y1) / (x2 - x1); + let y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + let x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + } + /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ + aabbIntersectsSkeleton(bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + } + /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more + * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ + containsPoint(x, y) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains the point. */ + containsPointPolygon(polygon, x, y) { + let vertices = polygon; + let nn = polygon.length; + let prevIndex = nn - 2; + let inside = false; + for (let ii = 0; ii < nn; ii += 2) { + let vertexY = vertices[ii + 1]; + let prevY = vertices[prevIndex + 1]; + if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) { + let vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + } + /** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it + * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns + * true. */ + intersectsSegment(x1, y1, x2, y2) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains any part of the line segment. */ + intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { + let vertices = polygon; + let nn = polygon.length; + let width12 = x1 - x2, height12 = y1 - y2; + let det1 = x1 * y2 - y1 * x2; + let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (let ii = 0; ii < nn; ii += 2) { + let x4 = vertices[ii], y4 = vertices[ii + 1]; + let det2 = x3 * y4 - y3 * x4; + let width34 = x3 - x4, height34 = y3 - y4; + let det3 = width12 * height34 - height12 * width34; + let x = (det1 * width34 - width12 * det2) / det3; + if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) { + let y = (det1 * height34 - height12 * det2) / det3; + if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1)) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + } + /** Returns the polygon for the specified bounding box, or null. */ + getPolygon(boundingBox) { + if (!boundingBox) + throw new Error("boundingBox cannot be null."); + let index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + } + /** The width of the axis aligned bounding box. */ + getWidth() { + return this.maxX - this.minX; + } + /** The height of the axis aligned bounding box. */ + getHeight() { + return this.maxY - this.minY; + } +}; + +// spine-core/src/Triangulator.ts +var Triangulator = class { + convexPolygons = new Array(); + convexPolygonsIndices = new Array(); + indicesArray = new Array(); + isConcaveArray = new Array(); + triangles = new Array(); + polygonPool = new Pool(() => { + return new Array(); + }); + polygonIndicesPool = new Pool(() => { + return new Array(); + }); + triangulate(verticesArray) { + let vertices = verticesArray; + let vertexCount = verticesArray.length >> 1; + let indices = this.indicesArray; + indices.length = 0; + for (let i = 0; i < vertexCount; i++) + indices[i] = i; + let isConcave = this.isConcaveArray; + isConcave.length = 0; + for (let i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + let triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + let previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: + if (!isConcave[i]) { + let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + let p1x = vertices[p1], p1y = vertices[p1 + 1]; + let p2x = vertices[p2], p2y = vertices[p2 + 1]; + let p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + let v = indices[ii] << 1; + let vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + let previousIndex = (vertexCount + i - 1) % vertexCount; + let nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + } + decompose(verticesArray, triangles) { + let vertices = verticesArray; + let convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + let convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + let polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + let polygon = this.polygonPool.obtain(); + polygon.length = 0; + let fanBaseIndex = -1, lastWinding = 0; + for (let i = 0, n = triangles.length; i < n; i += 3) { + let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + let x1 = vertices[t1], y1 = vertices[t1 + 1]; + let x2 = vertices[t2], y2 = vertices[t2 + 1]; + let x3 = vertices[t3], y3 = vertices[t3 + 1]; + let merged = false; + if (fanBaseIndex == t1) { + let o = polygon.length - 4; + let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (let i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + let firstIndex = polygonIndices[0]; + let lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + let o = polygon.length - 4; + let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + let prevX = polygon[o + 2], prevY = polygon[o + 3]; + let firstX = polygon[0], firstY = polygon[1]; + let secondX = polygon[2], secondY = polygon[3]; + let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (let ii = 0; ii < n; ii++) { + if (ii == i) + continue; + let otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + let otherFirstIndex = otherIndices[0]; + let otherSecondIndex = otherIndices[1]; + let otherLastIndex = otherIndices[2]; + let otherPoly = convexPolygons[ii]; + let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (let i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + } + static isConcave(index, vertexCount, vertices, indices) { + let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + let current = indices[index] << 1; + let next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea( + vertices[previous], + vertices[previous + 1], + vertices[current], + vertices[current + 1], + vertices[next], + vertices[next + 1] + ); + } + static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + static winding(p1x, p1y, p2x, p2y, p3x, p3y) { + let px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + } +}; + +// spine-core/src/SkeletonClipping.ts +var SkeletonClipping = class { + triangulator = new Triangulator(); + clippingPolygon = new Array(); + clipOutput = new Array(); + clippedVertices = new Array(); + clippedUVs = new Array(); + clippedTriangles = new Array(); + scratch = new Array(); + clipAttachment = null; + clippingPolygons = null; + clipStart(slot, clip) { + if (this.clipAttachment) + return 0; + this.clipAttachment = clip; + let n = clip.worldVerticesLength; + let vertices = Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + let clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) { + let polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + } + clipEndWithSlot(slot) { + if (this.clipAttachment && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + } + clipEnd() { + if (!this.clipAttachment) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + } + isClipping() { + return this.clipAttachment != null; + } + clipTriangles(vertices, verticesLengthOrTriangles, trianglesOrTrianglesLength, trianglesLengthOrUvs, uvsOrLight, lightOrDark, darkOrTwoColor, twoColorParam) { + let triangles; + let trianglesLength; + let uvs; + let light; + let dark; + let twoColor; + if (typeof verticesLengthOrTriangles === "number") { + triangles = trianglesOrTrianglesLength; + trianglesLength = trianglesLengthOrUvs; + uvs = uvsOrLight; + light = lightOrDark; + dark = darkOrTwoColor; + twoColor = twoColorParam; + } else { + triangles = verticesLengthOrTriangles; + trianglesLength = trianglesOrTrianglesLength; + uvs = trianglesLengthOrUvs; + light = uvsOrLight; + dark = lightOrDark; + twoColor = darkOrTwoColor; + } + if (uvs && light && dark && typeof twoColor === "boolean") + this.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor); + else + this.clipTrianglesNoRender(vertices, triangles, trianglesLength); + } + clipTrianglesNoRender(vertices, triangles, trianglesLength) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let vertexSize = twoColor ? 12 : 8; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += vertexSize) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + clipTrianglesUnpacked(vertices, triangles, trianglesLength, uvs) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices, clippedUVs = this.clippedUVs; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let index = 0; + clippedVertices.length = 0; + clippedUVs.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + let clippedUVsItems = Utils.setArraySize(clippedUVs, s + clipOutputCount * 2); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedUVsItems[s] = u1 * a + u2 * b + u3 * c; + clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + let clippedUVSItems = Utils.setArraySize(clippedUVs, s + 3 * 2); + clippedUVSItems[s] = u1; + clippedUVSItems[s + 1] = v1; + clippedUVSItems[s + 2] = u2; + clippedUVSItems[s + 3] = v2; + clippedUVSItems[s + 4] = u3; + clippedUVSItems[s + 5] = v3; + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + clip(x1, y1, x2, y2, x3, y3, clippingArea, output) { + let originalOutput = output; + let clipped = false; + let input; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + let clippingVerticesLast = clippingArea.length - 4; + let clippingVertices = clippingArea; + for (let i = 0; ; i += 2) { + let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + let ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3]; + let outputStart = output.length; + let inputVertices = input; + for (let ii = 0, nn = input.length - 2; ii < nn; ) { + let inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + ii += 2; + let inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1]; + let s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2); + let s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY); + if (s1 > 0) { + if (s2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(inputX + ix * t); + output.push(inputY + iy * t); + } else { + output.push(inputX2); + output.push(inputY2); + continue; + } + } else if (s2) { + let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(inputX + ix * t); + output.push(inputY + iy * t); + output.push(inputX2); + output.push(inputY2); + } else { + output.push(inputX2); + output.push(inputY2); + continue; + } + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + let temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (let i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } else + originalOutput.length = originalOutput.length - 2; + return clipped; + } + static makeClockwise(polygon) { + let vertices = polygon; + let verticeslength = polygon.length; + let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (let i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + let x = vertices[i], y = vertices[i + 1]; + let other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + } +}; + +// spine-core/src/SkeletonJson.ts +var SkeletonJson = class { + attachmentLoader; + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(json) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + let root = typeof json === "string" ? JSON.parse(json) : json; + let skeletonMap = root.skeleton; + if (skeletonMap) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.referenceScale = getValue(skeletonMap, "referenceScale", 100) * scale; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images ?? null; + skeletonData.audioPath = skeletonMap.audio ?? null; + } + if (root.bones) { + for (let i = 0; i < root.bones.length; i++) { + let boneMap = root.bones[i]; + let parent = null; + let parentName = getValue(boneMap, "parent", null); + if (parentName) + parent = skeletonData.findBone(parentName); + let data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + data.length = getValue(boneMap, "length", 0) * scale; + data.x = getValue(boneMap, "x", 0) * scale; + data.y = getValue(boneMap, "y", 0) * scale; + data.rotation = getValue(boneMap, "rotation", 0); + data.scaleX = getValue(boneMap, "scaleX", 1); + data.scaleY = getValue(boneMap, "scaleY", 1); + data.shearX = getValue(boneMap, "shearX", 0); + data.shearY = getValue(boneMap, "shearY", 0); + data.inherit = Utils.enumValue(Inherit, getValue(boneMap, "inherit", "Normal")); + data.skinRequired = getValue(boneMap, "skin", false); + let color = getValue(boneMap, "color", null); + if (color) + data.color.setFromString(color); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (let i = 0; i < root.slots.length; i++) { + let slotMap = root.slots[i]; + let slotName = slotMap.name; + let boneData = skeletonData.findBone(slotMap.bone); + if (!boneData) + throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`); + let data = new SlotData(skeletonData.slots.length, slotName, boneData); + let color = getValue(slotMap, "color", null); + if (color) + data.color.setFromString(color); + let dark = getValue(slotMap, "dark", null); + if (dark) + data.darkColor = Color.fromString(dark); + data.attachmentName = getValue(slotMap, "attachment", null); + data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal")); + data.visible = getValue(slotMap, "visible", true); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (let i = 0; i < root.ik.length; i++) { + let constraintMap = root.ik[i]; + let data = new IkConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let bone = skeletonData.findBone(constraintMap.bones[ii]); + if (!bone) + throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let target = skeletonData.findBone(constraintMap.target); + ; + if (!target) + throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`); + data.target = target; + data.mix = getValue(constraintMap, "mix", 1); + data.softness = getValue(constraintMap, "softness", 0) * scale; + data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = getValue(constraintMap, "compress", false); + data.stretch = getValue(constraintMap, "stretch", false); + data.uniform = getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (let i = 0; i < root.transform.length; i++) { + let constraintMap = root.transform[i]; + let data = new TransformConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findBone(targetName); + if (!target) + throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`); + data.target = target; + data.local = getValue(constraintMap, "local", false); + data.relative = getValue(constraintMap, "relative", false); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.offsetX = getValue(constraintMap, "x", 0) * scale; + data.offsetY = getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = getValue(constraintMap, "scaleY", 0); + data.offsetShearY = getValue(constraintMap, "shearY", 0); + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + data.mixScaleX = getValue(constraintMap, "mixScaleX", 1); + data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX); + data.mixShearY = getValue(constraintMap, "mixShearY", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (let i = 0; i < root.path.length; i++) { + let constraintMap = root.path[i]; + let data = new PathConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findSlot(targetName); + if (!target) + throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`); + data.target = target; + data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent")); + data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length")); + data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent")); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.position = getValue(constraintMap, "position", 0); + if (data.positionMode == 0 /* Fixed */) + data.position *= scale; + data.spacing = getValue(constraintMap, "spacing", 0); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) + data.spacing *= scale; + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + skeletonData.pathConstraints.push(data); + } + } + if (root.physics) { + for (let i = 0; i < root.physics.length; i++) { + const constraintMap = root.physics[i]; + const data = new PhysicsConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + const boneName = constraintMap.bone; + const bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Physics bone not found: " + boneName); + data.bone = bone; + data.x = getValue(constraintMap, "x", 0); + data.y = getValue(constraintMap, "y", 0); + data.rotate = getValue(constraintMap, "rotate", 0); + data.scaleX = getValue(constraintMap, "scaleX", 0); + data.shearX = getValue(constraintMap, "shearX", 0); + data.limit = getValue(constraintMap, "limit", 5e3) * scale; + data.step = 1 / getValue(constraintMap, "fps", 60); + data.inertia = getValue(constraintMap, "inertia", 1); + data.strength = getValue(constraintMap, "strength", 100); + data.damping = getValue(constraintMap, "damping", 1); + data.massInverse = 1 / getValue(constraintMap, "mass", 1); + data.wind = getValue(constraintMap, "wind", 0); + data.gravity = getValue(constraintMap, "gravity", 0); + data.mix = getValue(constraintMap, "mix", 1); + data.inertiaGlobal = getValue(constraintMap, "inertiaGlobal", false); + data.strengthGlobal = getValue(constraintMap, "strengthGlobal", false); + data.dampingGlobal = getValue(constraintMap, "dampingGlobal", false); + data.massGlobal = getValue(constraintMap, "massGlobal", false); + data.windGlobal = getValue(constraintMap, "windGlobal", false); + data.gravityGlobal = getValue(constraintMap, "gravityGlobal", false); + data.mixGlobal = getValue(constraintMap, "mixGlobal", false); + skeletonData.physicsConstraints.push(data); + } + } + if (root.skins) { + for (let i = 0; i < root.skins.length; i++) { + let skinMap = root.skins[i]; + let skin = new Skin(skinMap.name); + if (skinMap.bones) { + for (let ii = 0; ii < skinMap.bones.length; ii++) { + let boneName = skinMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`); + skin.bones.push(bone); + } + } + if (skinMap.ik) { + for (let ii = 0; ii < skinMap.ik.length; ii++) { + let constraintName = skinMap.ik[ii]; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.transform) { + for (let ii = 0; ii < skinMap.transform.length; ii++) { + let constraintName = skinMap.transform[ii]; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.path) { + for (let ii = 0; ii < skinMap.path.length; ii++) { + let constraintName = skinMap.path[ii]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.physics) { + for (let ii = 0; ii < skinMap.physics.length; ii++) { + let constraintName = skinMap.physics[ii]; + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + for (let slotName in skinMap.attachments) { + let slot = skeletonData.findSlot(slotName); + if (!slot) + throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`); + let slotMap = skinMap.attachments[slotName]; + for (let entryName in slotMap) { + let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment) + skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (!skin) + throw new Error(`Skin not found: ${linkedMesh.skin}`); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) + throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) + linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (let eventName in root.events) { + let eventMap = root.events[eventName]; + let data = new EventData(eventName); + data.intValue = getValue(eventMap, "int", 0); + data.floatValue = getValue(eventMap, "float", 0); + data.stringValue = getValue(eventMap, "string", ""); + data.audioPath = getValue(eventMap, "audio", null); + if (data.audioPath) { + data.volume = getValue(eventMap, "volume", 1); + data.balance = getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (let animationName in root.animations) { + let animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + } + readAttachment(map, skin, slotIndex, name, skeletonData) { + let scale = this.scale; + name = getValue(map, "name", name); + switch (getValue(map, "type", "region")) { + case "region": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) + return null; + region.path = path; + region.x = getValue(map, "x", 0) * scale; + region.y = getValue(map, "y", 0) * scale; + region.scaleX = getValue(map, "scaleX", 1); + region.scaleY = getValue(map, "scaleY", 1); + region.rotation = getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + region.sequence = sequence; + let color = getValue(map, "color", null); + if (color) + region.color.setFromString(color); + if (region.region != null) + region.updateRegion(); + return region; + } + case "boundingbox": { + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + this.readVertices(map, box, map.vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + let color = getValue(map, "color", null); + if (color) + mesh.color.setFromString(color); + mesh.width = getValue(map, "width", 0) * scale; + mesh.height = getValue(map, "height", 0) * scale; + mesh.sequence = sequence; + let parent = getValue(map, "parent", null); + if (parent) { + this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true))); + return mesh; + } + let uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + if (mesh.region != null) + mesh.updateRegion(); + mesh.edges = getValue(map, "edges", null); + mesh.hullLength = getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = getValue(map, "closed", false); + path.constantSpeed = getValue(map, "constantSpeed", true); + let vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + let color = getValue(map, "color", null); + if (color) + path.color.setFromString(color); + return path; + } + case "point": { + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = getValue(map, "x", 0) * scale; + point.y = getValue(map, "y", 0) * scale; + point.rotation = getValue(map, "rotation", 0); + let color = getValue(map, "color", null); + if (color) + point.color.setFromString(color); + return point; + } + case "clipping": { + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + let end = getValue(map, "end", null); + if (end) + clip.endSlot = skeletonData.findSlot(end); + let vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + clip.color.setFromString(color); + return clip; + } + } + return null; + } + readSequence(map) { + if (map == null) + return null; + let sequence = new Sequence(getValue(map, "count", 0)); + sequence.start = getValue(map, "start", 1); + sequence.digits = getValue(map, "digits", 0); + sequence.setupIndex = getValue(map, "setup", 0); + return sequence; + } + readVertices(map, attachment, verticesLength) { + let scale = this.scale; + attachment.worldVerticesLength = verticesLength; + let vertices = map.vertices; + if (verticesLength == vertices.length) { + let scaledVertices = Utils.toFloatArray(vertices); + if (scale != 1) { + for (let i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + let weights = new Array(); + let bones = new Array(); + for (let i = 0, n = vertices.length; i < n; ) { + let boneCount = vertices[i++]; + bones.push(boneCount); + for (let nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = Utils.toFloatArray(weights); + } + readAnimation(map, name, skeletonData) { + let scale = this.scale; + let timelines = new Array(); + if (map.slots) { + for (let slotName in map.slots) { + let slotMap = map.slots[slotName]; + let slot = skeletonData.findSlot(slotName); + if (!slot) + throw new Error("Slot not found: " + slotName); + let slotIndex = slot.index; + for (let timelineName in slotMap) { + let timelineMap = slotMap[timelineName]; + if (!timelineMap) + continue; + let frames = timelineMap.length; + if (timelineName == "attachment") { + let timeline = new AttachmentTimeline(frames, slotIndex); + for (let frame = 0; frame < frames; frame++) { + let keyMap = timelineMap[frame]; + timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null)); + } + timelines.push(timeline); + } else if (timelineName == "rgba") { + let timeline = new RGBATimeline(frames, frames << 2, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb") { + let timeline = new RGBTimeline(frames, frames * 3, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "alpha") { + timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1)); + } else if (timelineName == "rgba2") { + let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb2") { + let timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.bones) { + for (let boneName in map.bones) { + let boneMap = map.bones[boneName]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error("Bone not found: " + boneName); + let boneIndex = bone.index; + for (let timelineName in boneMap) { + let timelineMap = boneMap[timelineName]; + let frames = timelineMap.length; + if (frames == 0) + continue; + if (timelineName === "rotate") { + timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1)); + } else if (timelineName === "translate") { + let timeline = new TranslateTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale)); + } else if (timelineName === "translatex") { + let timeline = new TranslateXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "translatey") { + let timeline = new TranslateYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "scale") { + let timeline = new ScaleTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1)); + } else if (timelineName === "scalex") { + let timeline = new ScaleXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "scaley") { + let timeline = new ScaleYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "shear") { + let timeline = new ShearTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1)); + } else if (timelineName === "shearx") { + let timeline = new ShearXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "sheary") { + let timeline = new ShearYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "inherit") { + let timeline = new InheritTimeline(frames, bone.index); + for (let frame = 0; frame < timelineMap.length; frame++) { + let aFrame = timelineMap[frame]; + timeline.setFrame(frame, getValue(aFrame, "time", 0), Utils.enumValue(Inherit, getValue(aFrame, "inherit", "Normal"))); + } + timelines.push(timeline); + } + } + } + } + if (map.ik) { + for (let constraintName in map.ik) { + let constraintMap = map.ik[constraintName]; + let keyMap = constraintMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) + throw new Error("IK Constraint not found: " + constraintName); + let constraintIndex = skeletonData.ikConstraints.indexOf(constraint); + let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mix = getValue(keyMap, "mix", 1); + let softness = getValue(keyMap, "softness", 0) * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); + let nextMap = constraintMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mix2 = getValue(nextMap, "mix", 1); + let softness2 = getValue(nextMap, "softness", 0) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.transform) { + for (let constraintName in map.transform) { + let timelineMap = map.transform[constraintName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) + throw new Error("Transform constraint not found: " + constraintName); + let constraintIndex = skeletonData.transformConstraints.indexOf(constraint); + let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + let mixScaleX = getValue(keyMap, "mixScaleX", 1); + let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX); + let mixShearY = getValue(keyMap, "mixShearY", 1); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let mixScaleX2 = getValue(nextMap, "mixScaleX", 1); + let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2); + let mixShearY2 = getValue(nextMap, "mixShearY", 1); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixScaleX = mixScaleX2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.path) { + for (let constraintName in map.path) { + let constraintMap = map.path[constraintName]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) + throw new Error("Path constraint not found: " + constraintName); + let constraintIndex = skeletonData.pathConstraints.indexOf(constraint); + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let frames = timelineMap.length; + if (timelineName === "position") { + let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == 0 /* Fixed */ ? scale : 1)); + } else if (timelineName === "spacing") { + let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == 0 /* Length */ || constraint.spacingMode == 1 /* Fixed */ ? scale : 1)); + } else if (timelineName === "mix") { + let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.physics) { + for (let constraintName in map.physics) { + let constraintMap = map.physics[constraintName]; + let constraintIndex = -1; + if (constraintName.length > 0) { + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) + throw new Error("Physics constraint not found: " + constraintName); + constraintIndex = skeletonData.physicsConstraints.indexOf(constraint); + } + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let frames = timelineMap.length; + if (timelineName == "reset") { + const timeline2 = new PhysicsConstraintResetTimeline(frames, constraintIndex); + for (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++) + timeline2.setFrame(frame, getValue(keyMap, "time", 0)); + timelines.push(timeline2); + continue; + } + let timeline; + if (timelineName == "inertia") + timeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex); + else if (timelineName == "strength") + timeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex); + else if (timelineName == "damping") + timeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex); + else if (timelineName == "mass") + timeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex); + else if (timelineName == "wind") + timeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex); + else if (timelineName == "gravity") + timeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex); + else if (timelineName == "mix") + timeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex); + else + continue; + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } + } + } + if (map.attachments) { + for (let attachmentsName in map.attachments) { + let attachmentsMap = map.attachments[attachmentsName]; + let skin = skeletonData.findSkin(attachmentsName); + if (!skin) + throw new Error("Skin not found: " + attachmentsName); + for (let slotMapName in attachmentsMap) { + let slotMap = attachmentsMap[slotMapName]; + let slot = skeletonData.findSlot(slotMapName); + if (!slot) + throw new Error("Slot not found: " + slotMapName); + let slotIndex = slot.index; + for (let attachmentMapName in slotMap) { + let attachmentMap = slotMap[attachmentMapName]; + let attachment = skin.getAttachment(slotIndex, attachmentMapName); + for (let timelineMapName in attachmentMap) { + let timelineMap = attachmentMap[timelineMapName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + if (timelineMapName == "deform") { + let weighted = attachment.bones; + let vertices = attachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + let time = getValue(keyMap, "time", 0); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let verticesValue = getValue(keyMap, "vertices", null); + if (!verticesValue) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = getValue(keyMap, "offset", 0); + Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (let i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (let i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frame, time, deform); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let curve = keyMap.curve; + if (curve) + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineMapName == "sequence") { + let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment); + let lastDelay = 0; + for (let frame = 0; frame < timelineMap.length; frame++) { + let delay = getValue(keyMap, "delay", lastDelay); + let time = getValue(keyMap, "time", 0); + let mode = SequenceMode[getValue(keyMap, "mode", "hold")]; + let index = getValue(keyMap, "index", 0); + timeline.setFrame(frame, time, mode, index, delay); + lastDelay = delay; + keyMap = timelineMap[frame + 1]; + } + timelines.push(timeline); + } + } + } + } + } + } + if (map.drawOrder) { + let timeline = new DrawOrderTimeline(map.drawOrder.length); + let slotCount = skeletonData.slots.length; + let frame = 0; + for (let i = 0; i < map.drawOrder.length; i++, frame++) { + let drawOrderMap = map.drawOrder[i]; + let drawOrder = null; + let offsets = getValue(drawOrderMap, "offsets", null); + if (offsets) { + drawOrder = Utils.newArray(slotCount, -1); + let unchanged = Utils.newArray(slotCount - offsets.length, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsets.length; ii++) { + let offsetMap = offsets[ii]; + let slot = skeletonData.findSlot(offsetMap.slot); + if (!slot) + throw new Error("Slot not found: " + slot); + let slotIndex = slot.index; + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder); + } + timelines.push(timeline); + } + if (map.events) { + let timeline = new EventTimeline(map.events.length); + let frame = 0; + for (let i = 0; i < map.events.length; i++, frame++) { + let eventMap = map.events[i]; + let eventData = skeletonData.findEvent(eventMap.name); + if (!eventData) + throw new Error("Event not found: " + eventMap.name); + let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); + event.intValue = getValue(eventMap, "int", eventData.intValue); + event.floatValue = getValue(eventMap, "float", eventData.floatValue); + event.stringValue = getValue(eventMap, "string", eventData.stringValue); + if (event.data.audioPath) { + event.volume = getValue(eventMap, "volume", 1); + event.balance = getValue(eventMap, "balance", 0); + } + timeline.setFrame(frame, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + skeletonData.animations.push(new Animation(name, timelines, duration)); + } +}; +var LinkedMesh2 = class { + parent; + skin; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } +}; +function readTimeline12(keys, timeline, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value = getValue(keyMap, "value", defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let value2 = getValue(nextMap, "value", defaultValue) * scale; + if (keyMap.curve) + bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } +} +function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value1 = getValue(keyMap, name1, defaultValue) * scale; + let value2 = getValue(keyMap, name2, defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let nvalue1 = getValue(nextMap, name1, defaultValue) * scale; + let nvalue2 = getValue(nextMap, name2, defaultValue) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } +} +function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + if (curve == "stepped") { + timeline.setStepped(frame); + return bezier; + } + let i = value << 2; + let cx1 = curve[i]; + let cy1 = curve[i + 1] * scale; + let cx2 = curve[i + 2]; + let cy2 = curve[i + 3] * scale; + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; +} +function getValue(map, property, defaultValue) { + return map[property] !== void 0 ? map[property] : defaultValue; +} + +// spine-core/src/polyfills.ts +(() => { + if (typeof Math.fround === "undefined") { + Math.fround = function(array) { + return function(x) { + return array[0] = x, array[0]; + }; + }(new Float32Array(1)); + } +})(); + +// spine-webgl/src/WebGL.ts +var ManagedWebGLRenderingContext = class { + canvas; + gl; + restorables = new Array(); + constructor(canvasOrContext, contextConfig = { alpha: "true" }) { + if (!(canvasOrContext instanceof WebGLRenderingContext || typeof WebGL2RenderingContext !== "undefined" && canvasOrContext instanceof WebGL2RenderingContext)) { + let canvas = canvasOrContext; + this.gl = canvas.getContext("webgl2", contextConfig) || canvas.getContext("webgl", contextConfig); + this.canvas = canvas; + canvas.addEventListener("webglcontextlost", (e) => { + let event = e; + if (e) + e.preventDefault(); + }); + canvas.addEventListener("webglcontextrestored", (e) => { + for (let i = 0, n = this.restorables.length; i < n; i++) + this.restorables[i].restore(); + }); + } else { + this.gl = canvasOrContext; + this.canvas = this.gl.canvas; + } + } + addRestorable(restorable) { + this.restorables.push(restorable); + } + removeRestorable(restorable) { + let index = this.restorables.indexOf(restorable); + if (index > -1) + this.restorables.splice(index, 1); + } +}; + +// spine-webgl/src/GLTexture.ts +var _GLTexture = class extends Texture { + context; + texture = null; + boundUnit = 0; + useMipMaps = false; + constructor(context, image, useMipMaps = false) { + super(image); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.useMipMaps = useMipMaps; + this.restore(); + this.context.addRestorable(this); + } + setFilters(minFilter, magFilter) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, _GLTexture.validateMagFilter(magFilter)); + this.useMipMaps = _GLTexture.usesMipMaps(minFilter); + if (this.useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + } + static validateMagFilter(magFilter) { + switch (magFilter) { + case 9987 /* MipMapLinearLinear */: + case 9985 /* MipMapLinearNearest */: + case 9986 /* MipMapNearestLinear */: + case 9984 /* MipMapNearestNearest */: + return 9729 /* Linear */; + default: + return magFilter; + } + } + static usesMipMaps(filter) { + switch (filter) { + case 9987 /* MipMapLinearLinear */: + case 9985 /* MipMapLinearNearest */: + case 9986 /* MipMapNearestLinear */: + case 9984 /* MipMapNearestNearest */: + return true; + default: + return false; + } + } + setWraps(uWrap, vWrap) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap); + } + update(useMipMaps) { + let gl = this.context.gl; + if (!this.texture) + this.texture = this.context.gl.createTexture(); + this.bind(); + if (_GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + if (useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + } + restore() { + this.texture = null; + this.update(this.useMipMaps); + } + bind(unit = 0) { + let gl = this.context.gl; + this.boundUnit = unit; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + } + unbind() { + let gl = this.context.gl; + gl.activeTexture(gl.TEXTURE0 + this.boundUnit); + gl.bindTexture(gl.TEXTURE_2D, null); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteTexture(this.texture); + } +}; +var GLTexture = _GLTexture; +__publicField(GLTexture, "DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL", false); + +// spine-webgl/src/AssetManager.ts +var AssetManager = class extends AssetManagerBase { + constructor(context, pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new GLTexture(context, image); + }, pathPrefix, downloader); + } +}; + +// spine-webgl/src/Vector3.ts +var Vector3 = class { + x = 0; + y = 0; + z = 0; + constructor(x = 0, y = 0, z = 0) { + this.x = x; + this.y = y; + this.z = z; + } + setFrom(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + } + set(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + } + scale(s) { + this.x *= s; + this.y *= s; + this.z *= s; + return this; + } + normalize() { + let len = this.length(); + if (len == 0) + return this; + len = 1 / len; + this.x *= len; + this.y *= len; + this.z *= len; + return this; + } + cross(v) { + return this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); + } + multiply(matrix) { + let l_mat = matrix.values; + return this.set( + this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03], + this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13], + this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23] + ); + } + project(matrix) { + let l_mat = matrix.values; + let l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]); + return this.set( + (this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w, + (this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w, + (this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w + ); + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + distance(v) { + let a = v.x - this.x; + let b = v.y - this.y; + let c = v.z - this.z; + return Math.sqrt(a * a + b * b + c * c); + } +}; + +// spine-webgl/src/Matrix4.ts +var M00 = 0; +var M01 = 4; +var M02 = 8; +var M03 = 12; +var M10 = 1; +var M11 = 5; +var M12 = 9; +var M13 = 13; +var M20 = 2; +var M21 = 6; +var M22 = 10; +var M23 = 14; +var M30 = 3; +var M31 = 7; +var M32 = 11; +var M33 = 15; +var _Matrix4 = class { + temp = new Float32Array(16); + values = new Float32Array(16); + constructor() { + let v = this.values; + v[M00] = 1; + v[M11] = 1; + v[M22] = 1; + v[M33] = 1; + } + set(values) { + this.values.set(values); + return this; + } + transpose() { + let t = this.temp; + let v = this.values; + t[M00] = v[M00]; + t[M01] = v[M10]; + t[M02] = v[M20]; + t[M03] = v[M30]; + t[M10] = v[M01]; + t[M11] = v[M11]; + t[M12] = v[M21]; + t[M13] = v[M31]; + t[M20] = v[M02]; + t[M21] = v[M12]; + t[M22] = v[M22]; + t[M23] = v[M32]; + t[M30] = v[M03]; + t[M31] = v[M13]; + t[M32] = v[M23]; + t[M33] = v[M33]; + return this.set(t); + } + identity() { + let v = this.values; + v[M00] = 1; + v[M01] = 0; + v[M02] = 0; + v[M03] = 0; + v[M10] = 0; + v[M11] = 1; + v[M12] = 0; + v[M13] = 0; + v[M20] = 0; + v[M21] = 0; + v[M22] = 1; + v[M23] = 0; + v[M30] = 0; + v[M31] = 0; + v[M32] = 0; + v[M33] = 1; + return this; + } + invert() { + let v = this.values; + let t = this.temp; + let l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + if (l_det == 0) + throw new Error("non-invertible matrix"); + let inv_det = 1 / l_det; + t[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32] - v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33]; + t[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32] + v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33]; + t[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32] - v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33]; + t[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22] + v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23]; + t[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32] + v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33]; + t[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32] - v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33]; + t[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32] + v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33]; + t[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22] - v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23]; + t[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31] - v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33]; + t[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31] + v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33]; + t[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31] - v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33]; + t[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21] + v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23]; + t[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31] + v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32]; + t[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31] - v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32]; + t[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31] + v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32]; + t[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21] - v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22]; + v[M00] = t[M00] * inv_det; + v[M01] = t[M01] * inv_det; + v[M02] = t[M02] * inv_det; + v[M03] = t[M03] * inv_det; + v[M10] = t[M10] * inv_det; + v[M11] = t[M11] * inv_det; + v[M12] = t[M12] * inv_det; + v[M13] = t[M13] * inv_det; + v[M20] = t[M20] * inv_det; + v[M21] = t[M21] * inv_det; + v[M22] = t[M22] * inv_det; + v[M23] = t[M23] * inv_det; + v[M30] = t[M30] * inv_det; + v[M31] = t[M31] * inv_det; + v[M32] = t[M32] * inv_det; + v[M33] = t[M33] * inv_det; + return this; + } + determinant() { + let v = this.values; + return v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + } + translate(x, y, z) { + let v = this.values; + v[M03] += x; + v[M13] += y; + v[M23] += z; + return this; + } + copy() { + return new _Matrix4().set(this.values); + } + projection(near, far, fovy, aspectRatio) { + this.identity(); + let l_fd = 1 / Math.tan(fovy * (Math.PI / 180) / 2); + let l_a1 = (far + near) / (near - far); + let l_a2 = 2 * far * near / (near - far); + let v = this.values; + v[M00] = l_fd / aspectRatio; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = l_fd; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = l_a1; + v[M32] = -1; + v[M03] = 0; + v[M13] = 0; + v[M23] = l_a2; + v[M33] = 0; + return this; + } + ortho2d(x, y, width, height) { + return this.ortho(x, x + width, y, y + height, 0, 1); + } + ortho(left, right, bottom, top, near, far) { + this.identity(); + let x_orth = 2 / (right - left); + let y_orth = 2 / (top - bottom); + let z_orth = -2 / (far - near); + let tx = -(right + left) / (right - left); + let ty = -(top + bottom) / (top - bottom); + let tz = -(far + near) / (far - near); + let v = this.values; + v[M00] = x_orth; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = y_orth; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = z_orth; + v[M32] = 0; + v[M03] = tx; + v[M13] = ty; + v[M23] = tz; + v[M33] = 1; + return this; + } + multiply(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30]; + t[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31]; + t[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32]; + t[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33]; + t[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30]; + t[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31]; + t[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32]; + t[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33]; + t[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30]; + t[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31]; + t[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32]; + t[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33]; + t[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30]; + t[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31]; + t[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32]; + t[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33]; + return this.set(this.temp); + } + multiplyLeft(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30]; + t[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31]; + t[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32]; + t[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33]; + t[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30]; + t[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31]; + t[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32]; + t[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33]; + t[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30]; + t[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31]; + t[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32]; + t[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33]; + t[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30]; + t[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31]; + t[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32]; + t[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33]; + return this.set(this.temp); + } + lookAt(position, direction, up) { + let xAxis = _Matrix4.xAxis, yAxis = _Matrix4.yAxis, zAxis = _Matrix4.zAxis; + zAxis.setFrom(direction).normalize(); + xAxis.setFrom(direction).normalize(); + xAxis.cross(up).normalize(); + yAxis.setFrom(xAxis).cross(zAxis).normalize(); + this.identity(); + let val = this.values; + val[M00] = xAxis.x; + val[M01] = xAxis.y; + val[M02] = xAxis.z; + val[M10] = yAxis.x; + val[M11] = yAxis.y; + val[M12] = yAxis.z; + val[M20] = -zAxis.x; + val[M21] = -zAxis.y; + val[M22] = -zAxis.z; + _Matrix4.tmpMatrix.identity(); + _Matrix4.tmpMatrix.values[M03] = -position.x; + _Matrix4.tmpMatrix.values[M13] = -position.y; + _Matrix4.tmpMatrix.values[M23] = -position.z; + this.multiply(_Matrix4.tmpMatrix); + return this; + } +}; +var Matrix42 = _Matrix4; +__publicField(Matrix42, "xAxis", new Vector3()); +__publicField(Matrix42, "yAxis", new Vector3()); +__publicField(Matrix42, "zAxis", new Vector3()); +__publicField(Matrix42, "tmpMatrix", new _Matrix4()); + +// spine-webgl/src/Camera.ts +var OrthoCamera = class { + position = new Vector3(0, 0, 0); + direction = new Vector3(0, 0, -1); + up = new Vector3(0, 1, 0); + near = 0; + far = 100; + zoom = 1; + viewportWidth = 0; + viewportHeight = 0; + projectionView = new Matrix42(); + inverseProjectionView = new Matrix42(); + projection = new Matrix42(); + view = new Matrix42(); + constructor(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.update(); + } + update() { + let projection = this.projection; + let view = this.view; + let projectionView = this.projectionView; + let inverseProjectionView = this.inverseProjectionView; + let zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight; + projection.ortho( + zoom * (-viewportWidth / 2), + zoom * (viewportWidth / 2), + zoom * (-viewportHeight / 2), + zoom * (viewportHeight / 2), + this.near, + this.far + ); + view.lookAt(this.position, this.direction, this.up); + projectionView.set(projection.values); + projectionView.multiply(view); + inverseProjectionView.set(projectionView.values).invert(); + } + screenToWorld(screenCoords, screenWidth, screenHeight) { + let x = screenCoords.x, y = screenHeight - screenCoords.y - 1; + screenCoords.x = 2 * x / screenWidth - 1; + screenCoords.y = 2 * y / screenHeight - 1; + screenCoords.z = 2 * screenCoords.z - 1; + screenCoords.project(this.inverseProjectionView); + return screenCoords; + } + worldToScreen(worldCoords, screenWidth, screenHeight) { + worldCoords.project(this.projectionView); + worldCoords.x = screenWidth * (worldCoords.x + 1) / 2; + worldCoords.y = screenHeight * (worldCoords.y + 1) / 2; + worldCoords.z = (worldCoords.z + 1) / 2; + return worldCoords; + } + setViewport(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + } +}; + +// spine-webgl/src/Input.ts +var Input = class { + element; + mouseX = 0; + mouseY = 0; + buttonDown = false; + touch0 = null; + touch1 = null; + initialPinchDistance = 0; + listeners = new Array(); + eventListeners = []; + constructor(element) { + this.element = element; + this.setupCallbacks(element); + } + setupCallbacks(element) { + let mouseDown = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) + listener.down(this.mouseX, this.mouseY); + }); + document.addEventListener("mousemove", mouseMove); + document.addEventListener("mouseup", mouseUp); + } + }; + let mouseMove = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.listeners.map((listener) => { + if (this.buttonDown) { + if (listener.dragged) + listener.dragged(this.mouseX, this.mouseY); + } else { + if (listener.moved) + listener.moved(this.mouseX, this.mouseY); + } + }); + } + }; + let mouseUp = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = false; + this.listeners.map((listener) => { + if (listener.up) + listener.up(this.mouseX, this.mouseY); + }); + document.removeEventListener("mousemove", mouseMove); + document.removeEventListener("mouseup", mouseUp); + } + }; + let mouseWheel = (e) => { + e.preventDefault(); + let deltaY = e.deltaY; + if (e.deltaMode == WheelEvent.DOM_DELTA_LINE) + deltaY *= 8; + if (e.deltaMode == WheelEvent.DOM_DELTA_PAGE) + deltaY *= 24; + this.listeners.map((listener) => { + if (listener.wheel) + listener.wheel(e.deltaY); + }); + }; + element.addEventListener("mousedown", mouseDown, true); + element.addEventListener("mousemove", mouseMove, true); + element.addEventListener("mouseup", mouseUp, true); + element.addEventListener("wheel", mouseWheel, true); + element.addEventListener("touchstart", (ev) => { + if (!this.touch0 || !this.touch1) { + var touches = ev.changedTouches; + let nativeTouch = touches.item(0); + if (!nativeTouch) + return; + let rect = element.getBoundingClientRect(); + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + let touch = new Touch(nativeTouch.identifier, x, y); + this.mouseX = x; + this.mouseY = y; + this.buttonDown = true; + if (!this.touch0) { + this.touch0 = touch; + this.listeners.map((listener) => { + if (listener.down) + listener.down(touch.x, touch.y); + }); + } else if (!this.touch1) { + this.touch1 = touch; + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) + listener.zoom(this.initialPinchDistance, this.initialPinchDistance); + }); + } + } + ev.preventDefault(); + }, false); + element.addEventListener("touchmove", (ev) => { + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0.x = this.mouseX = x; + this.touch0.y = this.mouseY = y; + this.listeners.map((listener) => { + if (listener.dragged) + listener.dragged(x, y); + }); + } + if (this.touch1 && this.touch1.identifier === nativeTouch.identifier) { + this.touch1.x = this.mouseX = x; + this.touch1.y = this.mouseY = y; + } + } + if (this.touch0 && this.touch1) { + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + let distance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) + listener.zoom(this.initialPinchDistance, distance); + }); + } + } + ev.preventDefault(); + }, false); + let touchEnd = (ev) => { + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0 = null; + this.mouseX = x; + this.mouseY = y; + this.listeners.map((listener) => { + if (listener.up) + listener.up(x, y); + }); + if (!this.touch1) { + this.buttonDown = false; + break; + } else { + this.touch0 = this.touch1; + this.touch1 = null; + this.mouseX = this.touch0.x; + this.mouseX = this.touch0.x; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) + listener.down(this.touch0.x, this.touch0.y); + }); + } + } + if (this.touch1 && this.touch1.identifier) { + this.touch1 = null; + } + } + } + ev.preventDefault(); + }; + element.addEventListener("touchend", touchEnd, false); + element.addEventListener("touchcancel", touchEnd); + } + addListener(listener) { + this.listeners.push(listener); + } + removeListener(listener) { + let idx = this.listeners.indexOf(listener); + if (idx > -1) { + this.listeners.splice(idx, 1); + } + } +}; +var Touch = class { + constructor(identifier, x, y) { + this.identifier = identifier; + this.x = x; + this.y = y; + } +}; + +// spine-webgl/src/CameraController.ts +var CameraController = class { + constructor(canvas, camera) { + this.canvas = canvas; + this.camera = camera; + let cameraX = 0, cameraY = 0, cameraZoom = 0; + let mouseX = 0, mouseY = 0; + let lastX = 0, lastY = 0; + let initialZoom = 0; + new Input(canvas).addListener({ + down: (x, y) => { + cameraX = camera.position.x; + cameraY = camera.position.y; + mouseX = lastX = x; + mouseY = lastY = y; + initialZoom = camera.zoom; + }, + dragged: (x, y) => { + let deltaX = x - mouseX; + let deltaY = y - mouseY; + let originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight); + let deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld); + camera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0); + camera.update(); + lastX = x; + lastY = y; + }, + wheel: (delta) => { + let zoomAmount = delta / 200 * camera.zoom; + let newZoom = camera.zoom + zoomAmount; + if (newZoom > 0) { + let x = 0, y = 0; + if (delta < 0) { + x = lastX; + y = lastY; + } else { + let viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2); + let mouseToCenterX = lastX - viewCenter.x; + let mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y; + x = viewCenter.x - mouseToCenterX; + y = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY; + } + let oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.zoom = newZoom; + camera.update(); + let newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.position.add(oldDistance.sub(newDistance)); + camera.update(); + } + }, + zoom: (initialDistance, distance) => { + let newZoom = initialDistance / distance; + camera.zoom = initialZoom * newZoom; + }, + up: (x, y) => { + lastX = x; + lastY = y; + }, + moved: (x, y) => { + lastX = x; + lastY = y; + } + }); + } +}; + +// spine-webgl/src/Shader.ts +var _Shader = class { + constructor(context, vertexShader, fragmentShader) { + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + this.vsSource = vertexShader; + this.fsSource = fragmentShader; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.context.addRestorable(this); + this.compile(); + } + context; + vs = null; + vsSource; + fs = null; + fsSource; + program = null; + tmp2x2 = new Float32Array(2 * 2); + tmp3x3 = new Float32Array(3 * 3); + tmp4x4 = new Float32Array(4 * 4); + getProgram() { + return this.program; + } + getVertexShader() { + return this.vertexShader; + } + getFragmentShader() { + return this.fragmentShader; + } + getVertexShaderSource() { + return this.vsSource; + } + getFragmentSource() { + return this.fsSource; + } + compile() { + let gl = this.context.gl; + try { + this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader); + if (!this.vs) + throw new Error("Couldn't compile vertex shader."); + this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader); + if (!this.fs) + throw new Error("Couldn#t compile fragment shader."); + this.program = this.compileProgram(this.vs, this.fs); + } catch (e) { + this.dispose(); + throw e; + } + } + compileShader(type, source) { + let gl = this.context.gl; + let shader = gl.createShader(type); + if (!shader) + throw new Error("Couldn't create shader."); + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + let error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + if (!gl.isContextLost()) + throw new Error(error); + } + return shader; + } + compileProgram(vs, fs) { + let gl = this.context.gl; + let program = gl.createProgram(); + if (!program) + throw new Error("Couldn't compile program."); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + let error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program); + gl.deleteProgram(program); + if (!gl.isContextLost()) + throw new Error(error); + } + return program; + } + restore() { + this.compile(); + } + bind() { + this.context.gl.useProgram(this.program); + } + unbind() { + this.context.gl.useProgram(null); + } + setUniformi(uniform, value) { + this.context.gl.uniform1i(this.getUniformLocation(uniform), value); + } + setUniformf(uniform, value) { + this.context.gl.uniform1f(this.getUniformLocation(uniform), value); + } + setUniform2f(uniform, value, value2) { + this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2); + } + setUniform3f(uniform, value, value2, value3) { + this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3); + } + setUniform4f(uniform, value, value2, value3, value4) { + this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4); + } + setUniform2x2f(uniform, value) { + let gl = this.context.gl; + this.tmp2x2.set(value); + gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2); + } + setUniform3x3f(uniform, value) { + let gl = this.context.gl; + this.tmp3x3.set(value); + gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3); + } + setUniform4x4f(uniform, value) { + let gl = this.context.gl; + this.tmp4x4.set(value); + gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4); + } + getUniformLocation(uniform) { + let gl = this.context.gl; + if (!this.program) + throw new Error("Shader not compiled."); + let location = gl.getUniformLocation(this.program, uniform); + if (!location && !gl.isContextLost()) + throw new Error(`Couldn't find location for uniform ${uniform}`); + return location; + } + getAttributeLocation(attribute) { + let gl = this.context.gl; + if (!this.program) + throw new Error("Shader not compiled."); + let location = gl.getAttribLocation(this.program, attribute); + if (location == -1 && !gl.isContextLost()) + throw new Error(`Couldn't find location for attribute ${attribute}`); + return location; + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + if (this.vs) { + gl.deleteShader(this.vs); + this.vs = null; + } + if (this.fs) { + gl.deleteShader(this.fs); + this.fs = null; + } + if (this.program) { + gl.deleteProgram(this.program); + this.program = null; + } + } + static newColoredTextured(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +attribute vec2 ${_Shader.TEXCOORDS}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_color; +varying vec2 v_texCoords; + +void main () { + v_color = ${_Shader.COLOR}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_color; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +void main () { + gl_FragColor = v_color * texture2D(u_texture, v_texCoords); +} +`; + return new _Shader(context, vs, fs); + } + static newTwoColoredTextured(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +attribute vec4 ${_Shader.COLOR2}; +attribute vec2 ${_Shader.TEXCOORDS}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_light; +varying vec4 v_dark; +varying vec2 v_texCoords; + +void main () { + v_light = ${_Shader.COLOR}; + v_dark = ${_Shader.COLOR2}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_light; +varying LOWP vec4 v_dark; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +void main () { + vec4 texColor = texture2D(u_texture, v_texCoords); + gl_FragColor.a = texColor.a * v_light.a; + gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; +} +`; + return new _Shader(context, vs, fs); + } + static newColored(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_color; + +void main () { + v_color = ${_Shader.COLOR}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_color; + +void main () { + gl_FragColor = v_color; +} +`; + return new _Shader(context, vs, fs); + } +}; +var Shader = _Shader; +__publicField(Shader, "MVP_MATRIX", "u_projTrans"); +__publicField(Shader, "POSITION", "a_position"); +__publicField(Shader, "COLOR", "a_color"); +__publicField(Shader, "COLOR2", "a_color2"); +__publicField(Shader, "TEXCOORDS", "a_texCoords"); +__publicField(Shader, "SAMPLER", "u_texture"); + +// spine-webgl/src/Mesh.ts +var Mesh = class { + constructor(context, attributes, maxVertices, maxIndices) { + this.attributes = attributes; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.elementsPerVertex = 0; + for (let i = 0; i < attributes.length; i++) { + this.elementsPerVertex += attributes[i].numElements; + } + this.vertices = new Float32Array(maxVertices * this.elementsPerVertex); + this.indices = new Uint16Array(maxIndices); + this.context.addRestorable(this); + } + context; + vertices; + verticesBuffer = null; + verticesLength = 0; + dirtyVertices = false; + indices; + indicesBuffer = null; + indicesLength = 0; + dirtyIndices = false; + elementsPerVertex = 0; + getAttributes() { + return this.attributes; + } + maxVertices() { + return this.vertices.length / this.elementsPerVertex; + } + numVertices() { + return this.verticesLength / this.elementsPerVertex; + } + setVerticesLength(length) { + this.dirtyVertices = true; + this.verticesLength = length; + } + getVertices() { + return this.vertices; + } + maxIndices() { + return this.indices.length; + } + numIndices() { + return this.indicesLength; + } + setIndicesLength(length) { + this.dirtyIndices = true; + this.indicesLength = length; + } + getIndices() { + return this.indices; + } + getVertexSizeInFloats() { + let size = 0; + for (var i = 0; i < this.attributes.length; i++) { + let attribute = this.attributes[i]; + size += attribute.numElements; + } + return size; + } + setVertices(vertices) { + this.dirtyVertices = true; + if (vertices.length > this.vertices.length) + throw Error("Mesh can't store more than " + this.maxVertices() + " vertices"); + this.vertices.set(vertices, 0); + this.verticesLength = vertices.length; + } + setIndices(indices) { + this.dirtyIndices = true; + if (indices.length > this.indices.length) + throw Error("Mesh can't store more than " + this.maxIndices() + " indices"); + this.indices.set(indices, 0); + this.indicesLength = indices.length; + } + draw(shader, primitiveType) { + this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex); + } + drawWithOffset(shader, primitiveType, offset, count) { + let gl = this.context.gl; + if (this.dirtyVertices || this.dirtyIndices) + this.update(); + this.bind(shader); + if (this.indicesLength > 0) { + gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2); + } else { + gl.drawArrays(primitiveType, offset, count); + } + this.unbind(shader); + } + bind(shader) { + let gl = this.context.gl; + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + let offset = 0; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.enableVertexAttribArray(location); + gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4); + offset += attrib.numElements; + } + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + } + unbind(shader) { + let gl = this.context.gl; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.disableVertexAttribArray(location); + } + gl.bindBuffer(gl.ARRAY_BUFFER, null); + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + } + update() { + let gl = this.context.gl; + if (this.dirtyVertices) { + if (!this.verticesBuffer) { + this.verticesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW); + this.dirtyVertices = false; + } + if (this.dirtyIndices) { + if (!this.indicesBuffer) { + this.indicesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW); + this.dirtyIndices = false; + } + } + restore() { + this.verticesBuffer = null; + this.indicesBuffer = null; + this.update(); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteBuffer(this.verticesBuffer); + gl.deleteBuffer(this.indicesBuffer); + } +}; +var VertexAttribute = class { + constructor(name, type, numElements) { + this.name = name; + this.type = type; + this.numElements = numElements; + } +}; +var Position2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, VertexAttributeType.Float, 2); + } +}; +var Position3Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, VertexAttributeType.Float, 3); + } +}; +var TexCoordAttribute = class extends VertexAttribute { + constructor(unit = 0) { + super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2); + } +}; +var ColorAttribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR, VertexAttributeType.Float, 4); + } +}; +var Color2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR2, VertexAttributeType.Float, 4); + } +}; +var VertexAttributeType = /* @__PURE__ */ ((VertexAttributeType2) => { + VertexAttributeType2[VertexAttributeType2["Float"] = 0] = "Float"; + return VertexAttributeType2; +})(VertexAttributeType || {}); + +// spine-webgl/src/PolygonBatcher.ts +var GL_ONE = 1; +var GL_ONE_MINUS_SRC_COLOR = 769; +var GL_SRC_ALPHA = 770; +var GL_ONE_MINUS_SRC_ALPHA = 771; +var GL_DST_COLOR = 774; +var _PolygonBatcher = class { + context; + drawCalls = 0; + isDrawing = false; + mesh; + shader = null; + lastTexture = null; + verticesLength = 0; + indicesLength = 0; + srcColorBlend; + srcAlphaBlend; + dstBlend; + cullWasEnabled = false; + constructor(context, twoColorTint = true, maxVertices = 10920) { + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + let attributes = twoColorTint ? [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] : [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()]; + this.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) + throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()"); + this.drawCalls = 0; + this.shader = shader; + this.lastTexture = null; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + if (_PolygonBatcher.disableCulling) { + this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE); + if (this.cullWasEnabled) + gl.disable(gl.CULL_FACE); + } + } + setBlendMode(blendMode, premultipliedAlpha) { + const blendModeGL = _PolygonBatcher.blendModesGL[blendMode]; + const srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb; + const srcAlphaBlend = blendModeGL.srcAlpha; + const dstBlend = blendModeGL.dstRgb; + if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) + return; + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + } + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + draw(texture, vertices, indices) { + if (texture != this.lastTexture) { + this.flush(); + this.lastTexture = texture; + } else if (this.verticesLength + vertices.length > this.mesh.getVertices().length || this.indicesLength + indices.length > this.mesh.getIndices().length) { + this.flush(); + } + let indexStart = this.mesh.numVertices(); + this.mesh.getVertices().set(vertices, this.verticesLength); + this.verticesLength += vertices.length; + this.mesh.setVerticesLength(this.verticesLength); + let indicesArray = this.mesh.getIndices(); + for (let i = this.indicesLength, j = 0; j < indices.length; i++, j++) + indicesArray[i] = indices[j] + indexStart; + this.indicesLength += indices.length; + this.mesh.setIndicesLength(this.indicesLength); + } + flush() { + if (this.verticesLength == 0) + return; + if (!this.lastTexture) + throw new Error("No texture set."); + if (!this.shader) + throw new Error("No shader set."); + this.lastTexture.bind(); + this.mesh.draw(this.shader, this.context.gl.TRIANGLES); + this.verticesLength = 0; + this.indicesLength = 0; + this.mesh.setVerticesLength(0); + this.mesh.setIndicesLength(0); + this.drawCalls++; + _PolygonBatcher.globalDrawCalls++; + } + end() { + if (!this.isDrawing) + throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()"); + if (this.verticesLength > 0 || this.indicesLength > 0) + this.flush(); + this.shader = null; + this.lastTexture = null; + this.isDrawing = false; + let gl = this.context.gl; + gl.disable(gl.BLEND); + if (_PolygonBatcher.disableCulling) { + if (this.cullWasEnabled) + gl.enable(gl.CULL_FACE); + } + } + getDrawCalls() { + return this.drawCalls; + } + static getAndResetGlobalDrawCalls() { + let result = _PolygonBatcher.globalDrawCalls; + _PolygonBatcher.globalDrawCalls = 0; + return result; + } + dispose() { + this.mesh.dispose(); + } +}; +var PolygonBatcher = _PolygonBatcher; +__publicField(PolygonBatcher, "disableCulling", false); +__publicField(PolygonBatcher, "globalDrawCalls", 0); +__publicField(PolygonBatcher, "blendModesGL", [ + { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE }, + { srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + { srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE } +]); + +// spine-webgl/src/ShapeRenderer.ts +var ShapeRenderer = class { + context; + isDrawing = false; + mesh; + shapeType = ShapeType.Filled; + color = new Color(1, 1, 1, 1); + shader = null; + vertexIndex = 0; + tmp = new Vector2(); + srcColorBlend; + srcAlphaBlend; + dstBlend; + constructor(context, maxVertices = 10920) { + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) + throw new Error("ShapeRenderer.begin() has already been called"); + this.shader = shader; + this.vertexIndex = 0; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + } + setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) { + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + } + setColor(color) { + this.color.setFromColor(color); + } + setColorWith(r, g, b, a) { + this.color.set(r, g, b, a); + } + point(x, y, color) { + this.check(ShapeType.Point, 1); + if (!color) + color = this.color; + this.vertex(x, y, color); + } + line(x, y, x2, y2, color) { + this.check(ShapeType.Line, 2); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + this.vertex(x, y, color); + this.vertex(x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + if (!color2) + color2 = this.color; + if (!color3) + color3 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color); + this.vertex(x3, y3, color2); + this.vertex(x3, y3, color); + this.vertex(x, y, color2); + } + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + if (!color2) + color2 = this.color; + if (!color3) + color3 = this.color; + if (!color4) + color4 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } + } + rect(filled, x, y, width, height, color) { + this.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 8); + if (!color) + color = this.color; + let t = this.tmp.set(y2 - y1, x1 - x2); + t.normalize(); + width *= 0.5; + let tx = t.x * width; + let ty = t.y * width; + if (!filled) { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } else { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } + } + x(x, y, size) { + this.line(x - size, y - size, x + size, y + size); + this.line(x - size, y + size, x + size, y - size); + } + polygon(polygonVertices, offset, count, color) { + if (count < 3) + throw new Error("Polygon must contain at least 3 vertices"); + this.check(ShapeType.Line, count * 2); + if (!color) + color = this.color; + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + offset <<= 1; + count <<= 1; + let firstX = polygonVertices[offset]; + let firstY = polygonVertices[offset + 1]; + let last = offset + count; + for (let i = offset, n = offset + count - 2; i < n; i += 2) { + let x1 = polygonVertices[i]; + let y1 = polygonVertices[i + 1]; + let x2 = 0; + let y2 = 0; + if (i + 2 >= last) { + x2 = firstX; + y2 = firstY; + } else { + x2 = polygonVertices[i + 2]; + y2 = polygonVertices[i + 3]; + } + this.vertex(x1, y1, color); + this.vertex(x2, y2, color); + } + } + circle(filled, x, y, radius, color, segments = 0) { + if (segments == 0) + segments = Math.max(1, 6 * MathUtils.cbrt(radius) | 0); + if (segments <= 0) + throw new Error("segments must be > 0."); + if (!color) + color = this.color; + let angle = 2 * MathUtils.PI / segments; + let cos = Math.cos(angle); + let sin = Math.sin(angle); + let cx = radius, cy = 0; + if (!filled) { + this.check(ShapeType.Line, segments * 2 + 2); + for (let i = 0; i < segments; i++) { + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x + cx, y + cy, color); + } else { + this.check(ShapeType.Filled, segments * 3 + 3); + segments--; + for (let i = 0; i < segments; i++) { + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + } + let temp = cx; + cx = radius; + cy = 0; + this.vertex(x + cx, y + cy, color); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.check(ShapeType.Line, segments * 2 + 2); + if (!color) + color = this.color; + let subdiv_step = 1 / segments; + let subdiv_step2 = subdiv_step * subdiv_step; + let subdiv_step3 = subdiv_step * subdiv_step * subdiv_step; + let pre1 = 3 * subdiv_step; + let pre2 = 3 * subdiv_step2; + let pre4 = 6 * subdiv_step2; + let pre5 = 6 * subdiv_step3; + let tmp1x = x1 - cx1 * 2 + cx2; + let tmp1y = y1 - cy1 * 2 + cy2; + let tmp2x = (cx1 - cx2) * 3 - x1 + x2; + let tmp2y = (cy1 - cy2) * 3 - y1 + y2; + let fx = x1; + let fy = y1; + let dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + let dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + let ddfx = tmp1x * pre4 + tmp2x * pre5; + let ddfy = tmp1y * pre4 + tmp2y * pre5; + let dddfx = tmp2x * pre5; + let dddfy = tmp2y * pre5; + while (segments-- > 0) { + this.vertex(fx, fy, color); + fx += dfx; + fy += dfy; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + this.vertex(fx, fy, color); + } + this.vertex(fx, fy, color); + this.vertex(x2, y2, color); + } + vertex(x, y, color) { + let idx = this.vertexIndex; + let vertices = this.mesh.getVertices(); + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color.r; + vertices[idx++] = color.g; + vertices[idx++] = color.b; + vertices[idx++] = color.a; + this.vertexIndex = idx; + } + end() { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + this.flush(); + let gl = this.context.gl; + gl.disable(gl.BLEND); + this.isDrawing = false; + } + flush() { + if (this.vertexIndex == 0) + return; + if (!this.shader) + throw new Error("No shader set."); + this.mesh.setVerticesLength(this.vertexIndex); + this.mesh.draw(this.shader, this.shapeType); + this.vertexIndex = 0; + } + check(shapeType, numVertices) { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + if (this.shapeType == shapeType) { + if (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) + this.flush(); + else + return; + } else { + this.flush(); + this.shapeType = shapeType; + } + } + dispose() { + this.mesh.dispose(); + } +}; +var ShapeType = /* @__PURE__ */ ((ShapeType2) => { + ShapeType2[ShapeType2["Point"] = 0] = "Point"; + ShapeType2[ShapeType2["Line"] = 1] = "Line"; + ShapeType2[ShapeType2["Filled"] = 4] = "Filled"; + return ShapeType2; +})(ShapeType || {}); + +// spine-webgl/src/SkeletonDebugRenderer.ts +var _SkeletonDebugRenderer = class { + boneLineColor = new Color(1, 0, 0, 1); + boneOriginColor = new Color(0, 1, 0, 1); + attachmentLineColor = new Color(0, 0, 1, 0.5); + triangleLineColor = new Color(1, 0.64, 0, 0.5); + pathColor = new Color().setFromString("FF7F00"); + clipColor = new Color(0.8, 0, 0, 2); + aabbColor = new Color(0, 1, 0, 0.5); + drawBones = true; + drawRegionAttachments = true; + drawBoundingBoxes = true; + drawMeshHull = true; + drawMeshTriangles = true; + drawPaths = true; + drawSkeletonXY = false; + drawClipping = true; + premultipliedAlpha = false; + scale = 1; + boneWidth = 2; + context; + bounds = new SkeletonBounds(); + temp = new Array(); + vertices = Utils.newFloatArray(2 * 1024); + constructor(context) { + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + } + draw(shapes, skeleton, ignoredBones) { + let skeletonX = skeleton.x; + let skeletonY = skeleton.y; + let gl = this.context.gl; + let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA; + shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + let bones = skeleton.bones; + if (this.drawBones) { + shapes.setColor(this.boneLineColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + if (!bone.parent) + continue; + let x = bone.data.length * bone.a + bone.worldX; + let y = bone.data.length * bone.c + bone.worldY; + shapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale); + } + if (this.drawSkeletonXY) + shapes.x(skeletonX, skeletonY, 4 * this.scale); + } + if (this.drawRegionAttachments) { + shapes.setColor(this.attachmentLineColor); + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + let vertices = this.vertices; + regionAttachment.computeWorldVertices(slot, vertices, 0, 2); + shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]); + shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]); + shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]); + shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]); + } + } + } + if (this.drawMeshHull || this.drawMeshTriangles) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof MeshAttachment)) + continue; + let mesh = attachment; + let vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2); + let triangles = mesh.triangles; + let hullLength = mesh.hullLength; + if (this.drawMeshTriangles) { + shapes.setColor(this.triangleLineColor); + for (let ii = 0, nn = triangles.length; ii < nn; ii += 3) { + let v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2; + shapes.triangle( + false, + vertices[v1], + vertices[v1 + 1], + // + vertices[v2], + vertices[v2 + 1], + // + vertices[v3], + vertices[v3 + 1] + // + ); + } + } + if (this.drawMeshHull && hullLength > 0) { + shapes.setColor(this.attachmentLineColor); + hullLength = (hullLength >> 1) * 2; + let lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1]; + for (let ii = 0, nn = hullLength; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + shapes.line(x, y, lastX, lastY); + lastX = x; + lastY = y; + } + } + } + } + if (this.drawBoundingBoxes) { + let bounds = this.bounds; + bounds.update(skeleton, true); + shapes.setColor(this.aabbColor); + shapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight()); + let polygons = bounds.polygons; + let boxes = bounds.boundingBoxes; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + shapes.setColor(boxes[i].color); + shapes.polygon(polygon, 0, polygon.length); + } + } + if (this.drawPaths) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof PathAttachment)) + continue; + let path = attachment; + let nn = path.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + path.computeWorldVertices(slot, 0, nn, world, 0, 2); + let color = this.pathColor; + let x1 = world[2], y1 = world[3], x2 = 0, y2 = 0; + if (path.closed) { + shapes.setColor(color); + let cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1]; + x2 = world[nn - 4]; + y2 = world[nn - 3]; + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + } + nn -= 4; + for (let ii = 4; ii < nn; ii += 6) { + let cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3]; + x2 = world[ii + 4]; + y2 = world[ii + 5]; + shapes.setColor(color); + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + x1 = x2; + y1 = y2; + } + } + } + if (this.drawBones) { + shapes.setColor(this.boneOriginColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + shapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8); + } + } + if (this.drawClipping) { + let slots = skeleton.slots; + shapes.setColor(this.clipColor); + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof ClippingAttachment)) + continue; + let clip = attachment; + let nn = clip.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + clip.computeWorldVertices(slot, 0, nn, world, 0, 2); + for (let i2 = 0, n2 = world.length; i2 < n2; i2 += 2) { + let x = world[i2]; + let y = world[i2 + 1]; + let x2 = world[(i2 + 2) % world.length]; + let y2 = world[(i2 + 3) % world.length]; + shapes.line(x, y, x2, y2); + } + } + } + } + dispose() { + } +}; +var SkeletonDebugRenderer = _SkeletonDebugRenderer; +__publicField(SkeletonDebugRenderer, "LIGHT_GRAY", new Color(192 / 255, 192 / 255, 192 / 255, 1)); +__publicField(SkeletonDebugRenderer, "GREEN", new Color(0, 1, 0, 1)); + +// spine-webgl/src/SkeletonRenderer.ts +var Renderable = class { + constructor(vertices, numVertices, numFloats) { + this.vertices = vertices; + this.numVertices = numVertices; + this.numFloats = numFloats; + } +}; +var _SkeletonRenderer = class { + premultipliedAlpha = false; + tempColor = new Color(); + tempColor2 = new Color(); + vertices; + vertexSize = 2 + 2 + 4; + twoColorTint = false; + renderable = new Renderable([], 0, 0); + clipper = new SkeletonClipping(); + temp = new Vector2(); + temp2 = new Vector2(); + temp3 = new Color(); + temp4 = new Color(); + constructor(context, twoColorTint = true) { + this.twoColorTint = twoColorTint; + if (twoColorTint) + this.vertexSize += 4; + this.vertices = Utils.newFloatArray(this.vertexSize * 1024); + } + draw(batcher, skeleton, slotRangeStart = -1, slotRangeEnd = -1, transformer = null) { + let clipper = this.clipper; + let premultipliedAlpha = this.premultipliedAlpha; + let twoColorTint = this.twoColorTint; + let blendMode = null; + let renderable = this.renderable; + let uvs; + let triangles; + let drawOrder = skeleton.drawOrder; + let attachmentColor; + let skeletonColor = skeleton.color; + let vertexSize = twoColorTint ? 12 : 8; + let inRange = false; + if (slotRangeStart == -1) + inRange = true; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize; + let slot = drawOrder[i]; + if (!slot.bone.active) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeStart >= 0 && slotRangeStart == slot.data.index) { + inRange = true; + } + if (!inRange) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) { + inRange = false; + } + let attachment = slot.getAttachment(); + let texture; + if (attachment instanceof RegionAttachment) { + let region = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = 4; + renderable.numFloats = clippedVertexSize << 2; + region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + uvs = region.uvs; + texture = region.region.texture; + attachmentColor = region.color; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = mesh.worldVerticesLength >> 1; + renderable.numFloats = renderable.numVertices * clippedVertexSize; + if (renderable.numFloats > renderable.vertices.length) { + renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats); + } + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize); + triangles = mesh.triangles; + texture = mesh.region.texture; + uvs = mesh.uvs; + attachmentColor = mesh.color; + } else if (attachment instanceof ClippingAttachment) { + let clip = attachment; + clipper.clipStart(slot, clip); + continue; + } else { + clipper.clipEndWithSlot(slot); + continue; + } + if (texture) { + let slotColor = slot.color; + let finalColor = this.tempColor; + finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r; + finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g; + finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b; + finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a; + if (premultipliedAlpha) { + finalColor.r *= finalColor.a; + finalColor.g *= finalColor.a; + finalColor.b *= finalColor.a; + } + let darkColor = this.tempColor2; + if (!slot.darkColor) + darkColor.set(0, 0, 0, 1); + else { + if (premultipliedAlpha) { + darkColor.r = slot.darkColor.r * finalColor.a; + darkColor.g = slot.darkColor.g * finalColor.a; + darkColor.b = slot.darkColor.b * finalColor.a; + } else { + darkColor.setFromColor(slot.darkColor); + } + darkColor.a = premultipliedAlpha ? 1 : 0; + } + let slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + batcher.setBlendMode(blendMode, premultipliedAlpha); + } + if (clipper.isClipping()) { + clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint); + let clippedVertices = new Float32Array(clipper.clippedVertices); + let clippedTriangles = clipper.clippedTriangles; + if (transformer) + transformer(clippedVertices, clippedVertices.length, vertexSize); + batcher.draw(texture, clippedVertices, clippedTriangles); + } else { + let verts = renderable.vertices; + if (!twoColorTint) { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + } + } else { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + verts[v + 6] = darkColor.r; + verts[v + 7] = darkColor.g; + verts[v + 8] = darkColor.b; + verts[v + 9] = darkColor.a; + } + } + let view = renderable.vertices.subarray(0, renderable.numFloats); + if (transformer) + transformer(renderable.vertices, renderable.numFloats, vertexSize); + batcher.draw(texture, view, triangles); + } + } + clipper.clipEndWithSlot(slot); + } + clipper.clipEnd(); + } + /** Returns the {@link SkeletonClipping} used by this renderer for use with e.g. {@link Skeleton.getBounds} **/ + getSkeletonClipping() { + return this.clipper; + } +}; +var SkeletonRenderer = _SkeletonRenderer; +__publicField(SkeletonRenderer, "QUAD_TRIANGLES", [0, 1, 2, 2, 3, 0]); + +// spine-webgl/src/SceneRenderer.ts +var quad = [ + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0 +]; +var QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; +var WHITE = new Color(1, 1, 1, 1); +var SceneRenderer = class { + context; + canvas; + camera; + batcher; + twoColorTint = false; + batcherShader; + shapes; + shapesShader; + activeRenderer = null; + skeletonRenderer; + skeletonDebugRenderer; + constructor(canvas, context, twoColorTint = true) { + this.canvas = canvas; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.twoColorTint = twoColorTint; + this.camera = new OrthoCamera(canvas.width, canvas.height); + this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context); + this.batcher = new PolygonBatcher(this.context, twoColorTint); + this.shapesShader = Shader.newColored(this.context); + this.shapes = new ShapeRenderer(this.context); + this.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint); + this.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context); + } + dispose() { + this.batcher.dispose(); + this.batcherShader.dispose(); + this.shapes.dispose(); + this.shapesShader.dispose(); + this.skeletonDebugRenderer.dispose(); + } + begin() { + this.camera.update(); + this.enableRenderer(this.batcher); + } + drawSkeleton(skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform = null) { + this.enableRenderer(this.batcher); + this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform); + } + drawSkeletonDebug(skeleton, premultipliedAlpha = false, ignoredBones) { + this.enableRenderer(this.shapes); + this.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones); + } + drawTexture(texture, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureUV(texture, x, y, width, height, u, v, u2, v2, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureRotated(texture, x, y, width, height, pivotX, pivotY, angle, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + let worldOriginX = x + pivotX; + let worldOriginY = y + pivotY; + let fx = -pivotX; + let fy = -pivotY; + let fx2 = width - pivotX; + let fy2 = height - pivotY; + let p1x = fx; + let p1y = fy; + let p2x = fx; + let p2y = fy2; + let p3x = fx2; + let p3y = fy2; + let p4x = fx2; + let p4y = fy; + let x1 = 0; + let y1 = 0; + let x2 = 0; + let y2 = 0; + let x3 = 0; + let y3 = 0; + let x4 = 0; + let y4 = 0; + if (angle != 0) { + let cos = MathUtils.cosDeg(angle); + let sin = MathUtils.sinDeg(angle); + x1 = cos * p1x - sin * p1y; + y1 = sin * p1x + cos * p1y; + x4 = cos * p2x - sin * p2y; + y4 = sin * p2x + cos * p2y; + x3 = cos * p3x - sin * p3y; + y3 = sin * p3x + cos * p3y; + x2 = x3 + (x1 - x4); + y2 = y3 + (y1 - y4); + } else { + x1 = p1x; + y1 = p1y; + x4 = p2x; + y4 = p2y; + x3 = p3x; + y3 = p3y; + x2 = p4x; + y2 = p4y; + } + x1 += worldOriginX; + y1 += worldOriginY; + x2 += worldOriginX; + y2 += worldOriginY; + x3 += worldOriginX; + y3 += worldOriginY; + x4 += worldOriginX; + y4 += worldOriginY; + var i = 0; + quad[i++] = x1; + quad[i++] = y1; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x2; + quad[i++] = y2; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x3; + quad[i++] = y3; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x4; + quad[i++] = y4; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawRegion(region, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES); + } + line(x, y, x2, y2, color, color2) { + this.enableRenderer(this.shapes); + this.shapes.line(x, y, x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.enableRenderer(this.shapes); + this.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3); + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.enableRenderer(this.shapes); + this.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4); + } + rect(filled, x, y, width, height, color) { + this.enableRenderer(this.shapes); + this.shapes.rect(filled, x, y, width, height, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.enableRenderer(this.shapes); + this.shapes.rectLine(filled, x1, y1, x2, y2, width, color); + } + polygon(polygonVertices, offset, count, color) { + this.enableRenderer(this.shapes); + this.shapes.polygon(polygonVertices, offset, count, color); + } + circle(filled, x, y, radius, color, segments = 0) { + this.enableRenderer(this.shapes); + this.shapes.circle(filled, x, y, radius, color, segments); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.enableRenderer(this.shapes); + this.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color); + } + end() { + if (this.activeRenderer === this.batcher) + this.batcher.end(); + else if (this.activeRenderer === this.shapes) + this.shapes.end(); + this.activeRenderer = null; + } + resize(resizeMode) { + let canvas = this.canvas; + var dpr = window.devicePixelRatio || 1; + var w = Math.round(canvas.clientWidth * dpr); + var h = Math.round(canvas.clientHeight * dpr); + if (canvas.width != w || canvas.height != h) { + canvas.width = w; + canvas.height = h; + } + this.context.gl.viewport(0, 0, canvas.width, canvas.height); + if (resizeMode === ResizeMode.Expand) + this.camera.setViewport(w, h); + else if (resizeMode === ResizeMode.Fit) { + let sourceWidth = canvas.width, sourceHeight = canvas.height; + let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight; + let targetRatio = targetHeight / targetWidth; + let sourceRatio = sourceHeight / sourceWidth; + let scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight; + this.camera.setViewport(sourceWidth * scale, sourceHeight * scale); + } + this.camera.update(); + } + enableRenderer(renderer) { + if (this.activeRenderer === renderer) + return; + this.end(); + if (renderer instanceof PolygonBatcher) { + this.batcherShader.bind(); + this.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.batcherShader.setUniformi("u_texture", 0); + this.batcher.begin(this.batcherShader); + this.activeRenderer = this.batcher; + } else if (renderer instanceof ShapeRenderer) { + this.shapesShader.bind(); + this.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.shapes.begin(this.shapesShader); + this.activeRenderer = this.shapes; + } else + this.activeRenderer = this.skeletonDebugRenderer; + } +}; +var ResizeMode = /* @__PURE__ */ ((ResizeMode2) => { + ResizeMode2[ResizeMode2["Stretch"] = 0] = "Stretch"; + ResizeMode2[ResizeMode2["Expand"] = 1] = "Expand"; + ResizeMode2[ResizeMode2["Fit"] = 2] = "Fit"; + return ResizeMode2; +})(ResizeMode || {}); + +// spine-webgl/src/LoadingScreen.ts +var spinnerImage; +var logoImage; +var loaded = 0; +var FADE_IN = 1; +var FADE_OUT = 1; +var logoWidth = 165; +var logoHeight = 108; +var spinnerSize = 163; +var LoadingScreen = class { + renderer; + logo = null; + spinner = null; + angle = 0; + fadeOut = 0; + fadeIn = 0; + timeKeeper = new TimeKeeper(); + backgroundColor = new Color(0.135, 0.135, 0.135, 1); + tempColor = new Color(); + constructor(renderer) { + this.renderer = renderer; + this.timeKeeper.maxDelta = 9; + if (!logoImage) { + let isSafari = navigator.userAgent.indexOf("Safari") > -1; + let onload = () => loaded++; + logoImage = new Image(); + logoImage.src = SPINE_LOGO_DATA; + if (!isSafari) + logoImage.crossOrigin = "anonymous"; + logoImage.onload = onload; + spinnerImage = new Image(); + spinnerImage.src = SPINNER_DATA; + if (!isSafari) + spinnerImage.crossOrigin = "anonymous"; + spinnerImage.onload = onload; + } + } + dispose() { + this.logo?.dispose(); + this.spinner?.dispose(); + } + draw(complete = false) { + if (loaded < 2 || complete && this.fadeOut > FADE_OUT) + return; + this.timeKeeper.update(); + let a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25)); + this.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5)); + let tempColor = this.tempColor; + let renderer = this.renderer; + let canvas = renderer.canvas; + let gl = renderer.context.gl; + renderer.resize(1 /* Expand */); + renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); + renderer.batcher.setBlendMode(0 /* Normal */, true); + if (complete) { + this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); + if (this.fadeOut > FADE_OUT) + return; + tempColor.setFromColor(this.backgroundColor); + a = 1 - this.fadeOut / FADE_OUT; + a = 1 - (a - 1) * (a - 1); + tempColor.a *= a; + if (tempColor.a > 0) { + renderer.camera.zoom = 1; + renderer.begin(); + renderer.quad( + true, + 0, + 0, + canvas.width, + 0, + canvas.width, + canvas.height, + 0, + canvas.height, + tempColor, + tempColor, + tempColor, + tempColor + ); + renderer.end(); + } + } else { + this.fadeIn += this.timeKeeper.delta; + if (this.backgroundColor.a > 0) { + gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a); + gl.clear(gl.COLOR_BUFFER_BIT); + } + a = 1; + } + a *= Math.min(this.fadeIn / FADE_IN, 1); + tempColor.set(a, a, a, a); + if (!this.logo) { + this.logo = new GLTexture(renderer.context, logoImage); + this.spinner = new GLTexture(renderer.context, spinnerImage); + } + renderer.camera.zoom = Math.max(1, spinnerSize / canvas.height); + renderer.begin(); + renderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor); + if (this.spinner) + renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor); + renderer.end(); + } +}; +var SPINNER_DATA = "data:image/png;base64,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"; +var SPINE_LOGO_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAABsCAYAAAALzHKmAAAQ7klEQVR42u3da4xdVRUA4D0zd2Y6nZY59DVtZ1puS9+lzC0YAi2UQ8AAQczFpPgA9VIeIQbirRqJ0cBUBVGjDr/QCKSNRSMmpuODxAdxqhgwxkhFjf6Sxh/+UUNVNGJCzR7uTvas7LXX2q9zzp3em6y0gTN3Zu75utZe5+yztxC9V+/Ve5X9En1Vjd7J6SFbLNF7naPw+l2jh7YHMBWssqMHtlsRdim4qsLtIawaPiHEQOLoNrA9iIkQDnRrVA1qD2LZ8ISoxYqKo13sQAtBWBayQWZUAXGRQM9JjCngDVY0UqJNDbQrMcaGmArdUKpIjbYiQLsCZCyIMQBy8QwnilR4Q5AuCpxFYvRFmBLbEiwKwpsSaWycVQGZBKMrwBjA9BhxDe57u2L2hOoKNCbOrgAZitEVYUxoKSMErQvSxYIzCkguRg5EF4AUhqUlhy/YUKSxcRaKsioYOQhD4I0yYxkR3PcJBcuFysmgsXAWBTMJyBCMIQh9kGGxXIXvexCQXbHGAMrBWTbM2CCpMSMLIxehC77lSJwXGth7M0FzoVJIXXDWQnGmhOkL0ic7YhhtWdGGkAuPAjUWGoF4faCmwBkbZmyUqUCyMqMLRA4+E6IsdTjidUHKBYrh9CnpRcH0ypKxsyOGEYNIIeTCOz91OIJ1QYoB5eAMyZo+MFNnyVTZ0YiRC9EGEMOyAgshxErHsL2XK1gOUgwohtM1a5YNM7Rsu4K0ZkcbRm4mpPBRwFZ5hg9eCqkrUB+csWGGogzNkqEgrdnRhpGLkINudaLgwvVB6oqzCjCTZElb2Y4B0gUjBtEG0ARnDRLjjoG9DwcshtQGlIPTljVjwUySLWNkyRCQVHa0ZUUTRAwgF91a33BEy0VKAcVwwqwZC2bqbOlUurllOxQkJzNyINoAYqjWhYYjWg5SCiiG05Q1U8FMjTIoS8YE6YORi1BHtJ4KIcQEEtTXUWAxpK44YVlPBdO1jCdFWTZIE8bVGEYMIRPcZGBw4HKQcoBiOE1ZMzbMgVQwU6JMAdKEEcuIJogUvg1YCCE2gsCO42DlIIVAKZwpYJaSLVNnSU6XjYHUmxhTmXaFaMO3EYkLqMC+FsLlIoVAKZzMrEnBhJeLfLNlKMrYWRIDCbOkFSSVHbHM6AKRC6/ODUewNqQ+OLlZkxpjUmV8MBbMUJSxyzY3Q1IgTRgxiBRCHdem0KDAUkBh9sRwwjEnAXMMgTnKhFlUtiwkS5rGka4g9SaGgxFmRC7AzTCEEBcyA36dDSsXqAtOLkysjGMwY5XxVChjZ0kuSCo7YlkRQsQQYtDEFsegsLoCxUp7Kpgps2UslFGzJGccSYHUmxhOZqwzEZqAbfUMCisHKIZzgsCpl3MTzMwTpi1bYp2477gyFKUxS7qWbdjY2EBS2dGE0QQRA7gNCyHEdhjE8RhUDlBT9tzgmjWZMFNlSy+Urk1OzCyJlW0XkK4YOQh1cDtcgwBrQmoDWkdgboBZE8mYsJSHlnFbJ+5bwmOPJ7lZkirbC8aRsMvmgtTHjBhGE0QbwJ2egUE1ITVlUC5OmDVdYNrKuN70xM6WoShjlW4464dbtiFIWK6x7GjESEHUUe0iYncnbMdQSE0Z1ITTNOb0hRmjjLtmS9dmJ2rp1jtuKktyyrb6YLEMCUHq2dGG0QQRQ7f72kzc+cJecerne8Wvv7JNPHPvenEkz8Sh3UtFc92QyGt9Yko/HgOLAIUZlItTz5ouMF3KuE+2jFLCQ1D6lm6fLMkBacuOJowYRBUXyfjuHjF3NhdnsfjvAfH6E9vFt9XxKgikEKgJZyyYalzOLeMu2bLbULI6bh+QGwmQ+rgRlumdGEQAao+K56bEL2woVUwOiev0r8OAUjiJrMmFCbvykGxZRAmPitK1dHM7bohyMsuyi/I8f0+e57fJYIKEZXpXo9E4mOf5XTKyLLvCBLETF8uY2SKepkC+dpX4T02Ivepr4HvZcOZ5fmee54fyPL+DmTUhzAs6n4n8bN5dr9f3YdkSg8nsxG0lPBVKVpNjG0/aGhzfLDmRZdnumZmZp8+c+cdZPV555fSr7Xb7s0jJ3i5Pcue4MxKkPPkvvXTqz/B92u32l0wYOzG1fkhcd/py8Rcbyq/vFM/KY1WA95h/3zzP71bfU6JsNpsfgj+P/FlbrdaDGExYyuXvLz8H+DudODH700ajcSM3W6Yu4alQ1spCOTd38jcKocTZbh9+9NixY99XJ8AEUkcpo9W64yH197m5k7+bnZ19QT+J09NHntQhwji/Jg58qi6++ofLxJ8gSFneVw2Ka4QQDfh1Ok4dZavVmtZ/nrm5k7/Vf55O1tRhboUw5+ZOvqyOl5+R/FyOHj32PYVU/tloNG5IXcKrhJIzngwp3fNjomazea/64BuNxts646f50lWv169utw9/DmtqdJQyZFaSJVuV6nq9fqMEof5/vV6/CYBqgJDlee+yAbF/+4i4ZWqZeNfaIfHWzn+Hx0KcEuU9+s8jv3ej0bhVlXOZydX/k0iRMeb8P0D5e6tj8zy/Xb9UJIc56h/yqVOnXul8lmuZ2bJslKmbHG7XrbpCmCXFRLvdfqQD6jTS3Jiy5I4OykM6ADV+1Eu1DmV6evopBORexzDi1L+X/HnGxsb2w3Hm9PSRJ9QxWPOTZdmlKht2hi+w6dkox5bqffI8fye3hDteGqKaHVsHXihKl0tB+h0cY+lute54AGRKDCW89LNTRynHb7ChUWVVjetOnJh9EYBUyPZeNCoOtsbFQwdXi4/esELcd+tq8cCHJ8UXp+viy9efLz7AgamjlKXc1AA1m83DoIRDlFubzeb96hhZLVTlgJ24gttutx+ONa50bHZKRenaeTs1OfpAfnr6yOOdE7EZdNwmlKocntXLNkA5JTGq47Ds+Lf94lWsyfnXleLfnIwJUN4DOnNYwuUxh2A3Ln9XULrfK8t3J27Tu3BVwiOjXJqoAy8UZej1yclGo3GTLN+gu3w+z/P3YaWbQqk3Ne12e4ZC+c8rxWsYytcPiP9RpZxCqWDKnxOiBNlyAUpOnGsoh4tA2Rm8X9xqtT6md5wyZmYe+0YRKL+1S/wYQ3n8zctBl5SBUv5djivfjMOPduIzcizeiYfr9foVvUwZG+XCuzibZKnSceZ5/v4QlKp8y7ElhnJlTeTP7BI/kllRYfzrfvHqFy4UX1vaL/aVlSmROzwbwdS29T2UcEwZF+V8ozM2lu1VY812u/15akypGh3TmFJesJbHHD167IdUxz3YJy5bNySuX1mbvy55CbMLtzU6tjGlsdFptVqfUMc0Go23F4wy1l2dSnbfvpMwVPe9WWVLDsrOJaF9MFu2Wq1PqmNkGce67xiXhTjdNwdlvV6/BgxfbPfBfVCetxi6b9/rlCup65QzM48dl2OjLMv26CibzeZ96sTIzEFdpwQXz9U1yrtVlpR/Zll2Fec65Y6l4pbbx8XHH9kknvzJlPjlHy8Tp29eKT5ou0aJoIT3w3dBlLDzVpfAJEZ1XOdaJZxnOSlvPMjPzxFljIvng914RwebsjYO7uhMyHu46sOfnf3Oz2TXDW6vvYxdFoIXz3Wc8J5zs9n8iOn2IrxTc2BM3Glqdp7dI553uaOjxrhwcob+MyuUpjs6WZZdon8OcigjPx8V+u+GTWFTSWEx3WYcdJ225jNDSE4q0GHCzlueHOyujn6bUWYgeb9ZZUaQPe+GzQ+Gc8+oOGhC+c1d4gfI16n3XDAhQ7+9qE9l01E2Go132GYKyXE1NiFDTcpoNpv3LOYJGWXNErJNW9sEp63p2RKiVPMn1bS1DgxsyhoGdGpmizj+xtXiDYnx7/vFmce3iWdW1cTVGEY4hQ2ZW0nNq8Qm/M6XbXm3S100lwGedFybuvNOibLI+ZS2ceU4eAxiEuvCkfmU8ycToDxETe6FgCBQHeqyAbFvfEhcO7BwDuXFCEbTZF840XeHK0jYcbs2OIGle0mVJ/mmnClEPQqxyTY5I8/zFhif7fSZee4bnrPOU4AssnRXHaVTCTd14dRDY3UbTIiSeFhsN/aMjgnqthFx880rxX3yATL5p3y4LPXzOaBkUyBjZMlYpbtQlIOBD475ZEusjMNSvkXe6VEoJVDkeZ2dzIfIFsRzU+JF2OyM9M9fTC/6SUYOyFQPjQ2nWiUjxnPfw5EeHqMWIqAeIFsAU847lJM2JM6xsewt1OIDLs99P7ZFHNdB/upS8XtPiD7PfLuCXJNolYyyFiNI/Zit65ItrOVafFbHcFohY7hPTN21Tjz4uc3iqfsnxKdX1MTl1OoYRFaMsToGB6Trw2JFP/OdZC2hJZ7ZkrMoAbbSGmelDJ91hFKuJeS7jlBMkJnrAqqJlgMUZS/dArPlGHNdSg5M3xXXtvquuEatvIYtDRhpxbUJuIgqsU5lGWtUploK0KuEU9mSW8YpmFQ556xNuYW7NiW13B+FkMiKHIy+C6eGgBxJvMR0oSv5hi6+z4HJyZoU0M2RVvDlrOQbcxVfX5AhZbuqy0v7ZstYMLHlAVlLTF9ALLbvu9Y5Zylpn/XOsd0ibIvxr2KCLHpp6SCUIdnSZSF+WzfOhem6GD+1KwR3Z4jNjrtDpNoZwmWd8yrupZN6Hx3fbMmFSe0Swdq2ZIPjxk1112Duo8OBGLrBkw/IoncdK2XHsdC9dHz204m50xh3tzFq1zFqtzHXrfCw7OgDsqyNnZLszVijsmXgrmNcmGtS78lIoMX2aJz03fKO2sDJddPQSCDPiQ1DfWBycY6XtXstc2PQKuxgG2McmXTPb9/9vmuJYXKyJrWjbeg+3xPM4O73nWqvbyw7xgZZSJbEUBa157cNJjdr2vb+5iA1YV3HxYscj30PDCEHIgcjtfm8K8hSsmRotkwFk5s1TTghUAopB6xrjHMBBkI0YYTZ0dZlxwLpkiWDULpmy5gwqayZgZNkA7oKQQCxctByYg0XIIEQQuRitGVHblMTA2ShKGPDpC6wu+DEgJqg2rDGDBtAF4Q6RAojp1xXGmSMbImVcR+YWNY04eQCtUG1ofUJ2/uvcETIgUhhdAE5GAlkKShjwHTNmhhODKgJqQ2sC14uOgyfD0IbRF+MlQaZAiZWyn2yJsTJATqGnHQO2Jhh+xlsACFCG0QbRtdyzQFZCZSxYPpmTS7Q5cjJHYNBYIkZpu99HoUQ/o4QIYSIZUZfjJ4ZMjZI32wZBDMU5yhy8pZTULl4XYP5fagMyEVoy4oupTpGduwnkloSlKEwY+AcQU4MhRTD6ovXBRwFzwWgCSEF0QVjJUGmgEllTS5OLlCIlIN1mS9mx/cZ5eLDALpCTI2RAhkTZQqYoTgpoCPECbaBHQ2ETL3PUl98ECAXYijG0OyYAmQoTG7W5ODkAF1CnVgm2JQx4okPA+gCMTbGskBGgRmaOblAh5GTORIrfKFx4VH4EIAxIXIxlg2SBbMvECY3e7oApbDaIgQu5/2HmeEKEINYiwSRi7EQkLFgumZOCuggctKGI4ULZN/vMeSLj0AYMytWEqMLzFg4fYDaoKaC6wvOFR4FkIPQFaILxrJAOsHsc/zlfYDWXE8qF22s8Pz5KHxcgEVALBtjJXBSSEOwFhk1Zgy4hitCT4hVw+gFs8/zwxqIBbUgyK7fcyA0PD9XX4iVxhiC0xdof6STWCsoBmKF7+cVCWFXQYyBMxRpf+STX1b0x45AhN0OMSrOGEirhrY/dfQAdjvS7oy+WCF6r1RIFxXWvlTRg1YVqFWBmxZbD99ig9pt0YPQw9rD1nstVri9V+/Ve3XrS/wfim4P5fIFxLoAAAAASUVORK5CYII="; + +// spine-webgl/src/SpineCanvas.ts +var SpineCanvas = class { + /** Constructs a new spine canvas, rendering to the provided HTML canvas. */ + constructor(canvas, config) { + this.config = config; + if (!config.pathPrefix) + config.pathPrefix = ""; + if (!config.app) + config.app = { + loadAssets: () => { + }, + initialize: () => { + }, + update: () => { + }, + render: () => { + }, + error: () => { + }, + dispose: () => { + } + }; + if (!config.webglConfig) + config.webglConfig = { alpha: true }; + this.htmlCanvas = canvas; + this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig); + this.renderer = new SceneRenderer(canvas, this.context); + this.gl = this.context.gl; + this.assetManager = new AssetManager(this.context, config.pathPrefix); + this.input = new Input(canvas); + if (config.app.loadAssets) + config.app.loadAssets(this); + let loop = () => { + if (this.disposed) + return; + requestAnimationFrame(loop); + this.time.update(); + if (config.app.update) + config.app.update(this, this.time.delta); + if (config.app.render) + config.app.render(this); + }; + let waitForAssets = () => { + if (this.disposed) + return; + if (this.assetManager.isLoadingComplete()) { + if (this.assetManager.hasErrors()) { + if (config.app.error) + config.app.error(this, this.assetManager.getErrors()); + } else { + if (config.app.initialize) + config.app.initialize(this); + loop(); + } + return; + } + requestAnimationFrame(waitForAssets); + }; + requestAnimationFrame(waitForAssets); + } + context; + /** Tracks the current time, delta, and other time related statistics. */ + time = new TimeKeeper(); + /** The HTML canvas to render to. */ + htmlCanvas; + /** The WebGL rendering context. */ + gl; + /** The scene renderer for easy drawing of skeletons, shapes, and images. */ + renderer; + /** The asset manager to load assets with. */ + assetManager; + /** The input processor used to listen to mouse, touch, and keyboard events. */ + input; + disposed = false; + /** Clears the canvas with the given color. The color values are given in the range [0,1]. */ + clear(r, g, b, a) { + this.gl.clearColor(r, g, b, a); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + } + /** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/ + dispose() { + if (this.config.app.dispose) + this.config.app.dispose(this); + this.disposed = true; + } +}; + +// spine-phaser-v3/src/mixins.ts +var components = Phaser.GameObjects.Components; +var ComputedSize = components.ComputedSize; +var Depth = components.Depth; +var Flip = components.Flip; +var ScrollFactor = components.ScrollFactor; +var Transform = components.Transform; +var Visible = components.Visible; +var Origin = components.Origin; +var Alpha = components.Alpha; +function createMixin(...component) { + return (BaseGameObject) => { + Phaser.Class.mixin(BaseGameObject, component); + return BaseGameObject; + }; +} +var ComputedSizeMixin = createMixin(ComputedSize); +var DepthMixin = createMixin(Depth); +var FlipMixin = createMixin(Flip); +var ScrollFactorMixin = createMixin(ScrollFactor); +var TransformMixin = createMixin(Transform); +var VisibleMixin = createMixin(Visible); +var OriginMixin = createMixin(Origin); +var AlphaMixin = createMixin(Alpha); + +// spine-phaser-v3/src/SpineGameObject.ts +var BaseSpineGameObject = class extends Phaser.GameObjects.GameObject { + constructor(scene, type) { + super(scene, type); + } +}; +var SetupPoseBoundsProvider = class { + /** + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(clipping = false) { + this.clipping = clipping; + } + calculateBounds(gameObject) { + if (!gameObject.skeleton) + return { x: 0, y: 0, width: 0, height: 0 }; + const skeleton = new Skeleton(gameObject.skeleton.data); + skeleton.setToSetupPose(); + skeleton.updateWorldTransform(2 /* update */); + const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : void 0); + return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; + } +}; +var SkinsAndAnimationBoundsProvider = class { + /** + * @param animation The animation to use for calculating the bounds. If null, the setup pose is used. + * @param skins The skins to use for calculating the bounds. If empty, the default skin is used. + * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation. + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(animation, skins = [], timeStep = 0.05, clipping = false) { + this.animation = animation; + this.skins = skins; + this.timeStep = timeStep; + this.clipping = clipping; + } + calculateBounds(gameObject) { + if (!gameObject.skeleton || !gameObject.animationState) + return { x: 0, y: 0, width: 0, height: 0 }; + const animationState = new AnimationState(gameObject.animationState.data); + const skeleton = new Skeleton(gameObject.skeleton.data); + const clipper = this.clipping ? new SkeletonClipping() : void 0; + const data = skeleton.data; + if (this.skins.length > 0) { + let customSkin = new Skin("custom-skin"); + for (const skinName of this.skins) { + const skin = data.findSkin(skinName); + if (skin == null) + continue; + customSkin.addSkin(skin); + } + skeleton.setSkin(customSkin); + } + skeleton.setToSetupPose(); + const animation = this.animation != null ? data.findAnimation(this.animation) : null; + if (animation == null) { + skeleton.updateWorldTransform(2 /* update */); + const bounds = skeleton.getBoundsRect(clipper); + return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; + } else { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + animationState.clearTracks(); + animationState.setAnimationWith(0, animation, false); + const steps = Math.max(animation.duration / this.timeStep, 1); + for (let i = 0; i < steps; i++) { + const delta = i > 0 ? this.timeStep : 0; + animationState.update(delta); + animationState.apply(skeleton); + skeleton.update(delta); + skeleton.updateWorldTransform(2 /* update */); + const bounds2 = skeleton.getBoundsRect(clipper); + minX = Math.min(minX, bounds2.x); + minY = Math.min(minY, bounds2.y); + maxX = Math.max(maxX, bounds2.x + bounds2.width); + maxY = Math.max(maxY, bounds2.y + bounds2.height); + } + const bounds = { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + }; + return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; + } + } +}; +var SpineGameObject = class extends DepthMixin( + OriginMixin( + ComputedSizeMixin( + FlipMixin( + ScrollFactorMixin( + TransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject))) + ) + ) + ) + ) +) { + constructor(scene, plugin, x, y, dataKey, atlasKey, boundsProvider = new SetupPoseBoundsProvider()) { + super(scene, window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE); + this.plugin = plugin; + this.boundsProvider = boundsProvider; + this.setPosition(x, y); + this.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey); + this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey); + this.animationStateData = new AnimationStateData(this.skeleton.data); + this.animationState = new AnimationState(this.animationStateData); + this.skeleton.updateWorldTransform(2 /* update */); + this.updateSize(); + } + blendMode = -1; + skeleton; + animationStateData; + animationState; + beforeUpdateWorldTransforms = () => { + }; + afterUpdateWorldTransforms = () => { + }; + premultipliedAlpha = false; + updateSize() { + if (!this.skeleton) + return; + let bounds = this.boundsProvider.calculateBounds(this); + let self = this; + self.width = bounds.width; + self.height = bounds.height; + this.displayOriginX = -bounds.x; + this.displayOriginY = -bounds.y; + } + /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */ + skeletonToPhaserWorldCoordinates(point) { + let transform = this.getWorldTransformMatrix(); + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + let x = point.x; + let y = point.y; + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + } + /** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */ + phaserWorldCoordinatesToSkeleton(point) { + let transform = this.getWorldTransformMatrix(); + transform = transform.invert(); + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + let x = point.x; + let y = point.y; + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + } + /** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */ + phaserWorldCoordinatesToBone(point, bone) { + this.phaserWorldCoordinatesToSkeleton(point); + if (bone.parent) { + bone.parent.worldToLocal(point); + } else { + bone.worldToLocal(point); + } + } + /** + * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones. + * @param delta The time delta in milliseconds + */ + updatePose(delta) { + this.animationState.update(delta / 1e3); + this.animationState.apply(this.skeleton); + this.beforeUpdateWorldTransforms(this); + this.skeleton.update(delta / 1e3); + this.skeleton.updateWorldTransform(2 /* update */); + this.afterUpdateWorldTransforms(this); + } + preUpdate(time, delta) { + if (!this.skeleton || !this.animationState) + return; + this.updatePose(delta); + } + preDestroy() { + } + willRender(camera) { + var GameObjectRenderMask = 15; + var result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || this.cameraFilter !== 0 && this.cameraFilter & camera.id); + if (!this.visible) + result = false; + if (!result && this.parentContainer && this.plugin.webGLRenderer) { + var sceneRenderer = this.plugin.webGLRenderer; + if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) { + sceneRenderer.end(); + this.plugin.phaserRenderer.pipelines.rebind(); + } + } + return result; + } + renderWebGL(renderer, src, camera, parentMatrix) { + if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer) + return; + let sceneRenderer = this.plugin.webGLRenderer; + if (renderer.newType) { + renderer.pipelines.clear(); + sceneRenderer.begin(); + } + camera.addToRenderList(src); + let transform = Phaser.GameObjects.GetCalcMatrix( + src, + camera, + parentMatrix + ).calc; + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + sceneRenderer.drawSkeleton( + this.skeleton, + this.premultipliedAlpha, + -1, + -1, + (vertices, numVertices, stride) => { + for (let i = 0; i < numVertices; i += stride) { + let vx = vertices[i]; + let vy = vertices[i + 1]; + vertices[i] = vx * a + vy * c + tx; + vertices[i + 1] = vx * b + vy * d + ty; + } + } + ); + if (!renderer.nextTypeMatch) { + sceneRenderer.end(); + renderer.pipelines.rebind(); + } + } + renderCanvas(renderer, src, camera, parentMatrix) { + if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer) + return; + let context = renderer.currentContext; + let skeletonRenderer = this.plugin.canvasRenderer; + skeletonRenderer.ctx = context; + camera.addToRenderList(src); + let transform = Phaser.GameObjects.GetCalcMatrix( + src, + camera, + parentMatrix + ).calc; + let skeleton = this.skeleton; + skeleton.x = transform.tx; + skeleton.y = transform.ty; + skeleton.scaleX = transform.scaleX; + skeleton.scaleY = transform.scaleY; + let root = skeleton.getRootBone(); + root.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized; + this.skeleton.updateWorldTransform(2 /* update */); + context.save(); + skeletonRenderer.draw(skeleton); + context.restore(); + } +}; + +// spine-canvas/src/CanvasTexture.ts +var CanvasTexture = class extends Texture { + constructor(image) { + super(image); + } + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } +}; + +// spine-canvas/src/SkeletonRenderer.ts +var worldVertices = Utils.newFloatArray(8); +var _SkeletonRenderer2 = class { + ctx; + triangleRendering = false; + debugRendering = false; + vertices = Utils.newFloatArray(8 * 1024); + tempColor = new Color(); + constructor(context) { + this.ctx = context; + } + draw(skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + } + drawImages(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let bone = slot.bone; + if (!bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof RegionAttachment)) + continue; + attachment.computeWorldVertices(slot, worldVertices, 0, 2); + let region = attachment.region; + let image = region.texture.getImage(); + let slotColor = slot.color; + let regionColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * regionColor.r, + skeletonColor.g * slotColor.g * regionColor.g, + skeletonColor.b * slotColor.b * regionColor.b, + skeletonColor.a * slotColor.a * regionColor.a + ); + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + let atlasScale = attachment.width / region.originalWidth; + ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY); + let w = region.width, h = region.height; + ctx.translate(w / 2, h / 2); + if (attachment.region.degrees == 90) { + let t = w; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + } + drawTriangles(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + let blendMode = null; + let vertices = this.vertices; + let triangles = null; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let attachment = slot.getAttachment(); + let texture; + let region; + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = _SkeletonRenderer2.QUAD_TRIANGLES; + texture = regionAttachment.region.texture.getImage(); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.texture.getImage(); + } else + continue; + if (texture) { + if (slot.data.blendMode != blendMode) + blendMode = slot.data.blendMode; + let slotColor = slot.color; + let attachmentColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * attachmentColor.r, + skeletonColor.g * slotColor.g * attachmentColor.g, + skeletonColor.b * slotColor.b * attachmentColor.b, + skeletonColor.a * slotColor.a * attachmentColor.a + ); + ctx.globalAlpha = color.a; + for (var j = 0; j < triangles.length; j += 3) { + let t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7]; + this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + } + // Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 + // Apache 2 licensed + drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + let ctx = this.ctx; + const width = img.width - 1; + const height = img.height - 1; + u0 *= width; + v0 *= height; + u1 *= width; + v1 *= height; + u2 *= width; + v2 *= height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + let det = u1 * v2 - u2 * v1; + if (det == 0) + return; + det = 1 / det; + const a = (v2 * x1 - v1 * x2) * det; + const b = (v2 * y1 - v1 * y2) * det; + const c = (u1 * x2 - u2 * x1) * det; + const d = (u1 * y2 - u2 * y1) * det; + const e = x0 - a * u0 - c * v0; + const f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + } + computeRegionVertices(slot, region, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = region.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let color = this.tempColor; + color.set( + skeletonColor.r * slotColor.r * regionColor.r * multiplier, + skeletonColor.g * slotColor.g * regionColor.g * multiplier, + skeletonColor.b * slotColor.b * regionColor.b * multiplier, + alpha + ); + region.computeWorldVertices(slot, this.vertices, 0, _SkeletonRenderer2.VERTEX_SIZE); + let vertices = this.vertices; + let uvs = region.uvs; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + vertices[RegionAttachment.U1] = uvs[0]; + vertices[RegionAttachment.V1] = uvs[1]; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + vertices[RegionAttachment.U2] = uvs[2]; + vertices[RegionAttachment.V2] = uvs[3]; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + vertices[RegionAttachment.U3] = uvs[4]; + vertices[RegionAttachment.V3] = uvs[5]; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + vertices[RegionAttachment.U4] = uvs[6]; + vertices[RegionAttachment.V4] = uvs[7]; + return vertices; + } + computeMeshVertices(slot, mesh, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = mesh.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let color = this.tempColor; + color.set( + skeletonColor.r * slotColor.r * regionColor.r * multiplier, + skeletonColor.g * slotColor.g * regionColor.g * multiplier, + skeletonColor.b * slotColor.b * regionColor.b * multiplier, + alpha + ); + let vertexCount = mesh.worldVerticesLength / 2; + let vertices = this.vertices; + if (vertices.length < mesh.worldVerticesLength) + this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength); + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, _SkeletonRenderer2.VERTEX_SIZE); + let uvs = mesh.uvs; + for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + } +}; +var SkeletonRenderer2 = _SkeletonRenderer2; +__publicField(SkeletonRenderer2, "QUAD_TRIANGLES", [0, 1, 2, 2, 3, 0]); +__publicField(SkeletonRenderer2, "VERTEX_SIZE", 2 + 2 + 4); + +// spine-phaser-v3/src/SpinePlugin.ts +var _SpinePlugin = class extends Phaser2.Plugins.ScenePlugin { + game; + isWebGL; + gl; + get webGLRenderer() { + return _SpinePlugin.gameWebGLRenderer; + } + canvasRenderer; + phaserRenderer; + skeletonDataCache; + atlasCache; + constructor(scene, pluginManager, pluginKey) { + super(scene, pluginManager, pluginKey); + this.game = pluginManager.game; + this.isWebGL = this.game.config.renderType === 2; + this.gl = this.isWebGL ? this.game.renderer.gl : null; + this.phaserRenderer = this.game.renderer; + this.canvasRenderer = null; + this.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_FILE_CACHE_KEY); + this.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY); + let skeletonJsonFileCallback = function(key, url, xhrSettings) { + let file = new SpineSkeletonDataFile(this, key, url, SpineSkeletonDataFileType.json, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineJson", skeletonJsonFileCallback, scene); + let skeletonBinaryFileCallback = function(key, url, xhrSettings) { + let file = new SpineSkeletonDataFile(this, key, url, SpineSkeletonDataFileType.binary, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineBinary", skeletonBinaryFileCallback, scene); + let atlasFileCallback = function(key, url, premultipliedAlpha, xhrSettings) { + let file = new SpineAtlasFile(this, key, url, premultipliedAlpha, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene); + let addSpineGameObject = function(x, y, dataKey, atlasKey, boundsProvider) { + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + const spinePlugin = this.scene.sys[pluginKey]; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, dataKey, atlasKey, boundsProvider); + this.displayList.add(gameObject); + this.updateList.add(gameObject); + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return gameObject; + }; + let makeSpineGameObject = function(config, addToScene = false) { + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + let x = config.x ? config.x : 0; + let y = config.y ? config.y : 0; + let boundsProvider = config.boundsProvider ? config.boundsProvider : void 0; + const spinePlugin = this.scene.sys[pluginKey]; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, config.dataKey, config.atlasKey, boundsProvider); + if (addToScene !== void 0) { + config.add = addToScene; + } + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return Phaser2.GameObjects.BuildGameObject(this.scene, gameObject, config); + }; + pluginManager.registerGameObject(window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject); + } + boot() { + Skeleton.yDown = true; + if (this.isWebGL) { + if (!_SpinePlugin.gameWebGLRenderer) { + _SpinePlugin.gameWebGLRenderer = new SceneRenderer(this.game.renderer.canvas, this.gl, true); + } + this.onResize(); + this.game.scale.on(Phaser2.Scale.Events.RESIZE, this.onResize, this); + } else { + if (!this.canvasRenderer) { + this.canvasRenderer = new SkeletonRenderer2(this.scene.sys.context); + } + } + var eventEmitter = this.systems.events; + eventEmitter.once("shutdown", this.shutdown, this); + eventEmitter.once("destroy", this.destroy, this); + this.game.events.once("destroy", this.gameDestroy, this); + } + onResize() { + var phaserRenderer = this.game.renderer; + var sceneRenderer = this.webGLRenderer; + if (phaserRenderer && sceneRenderer) { + var viewportWidth = phaserRenderer.width; + var viewportHeight = phaserRenderer.height; + sceneRenderer.camera.position.x = viewportWidth / 2; + sceneRenderer.camera.position.y = viewportHeight / 2; + sceneRenderer.camera.up.y = -1; + sceneRenderer.camera.direction.z = 1; + sceneRenderer.camera.setViewport(viewportWidth, viewportHeight); + } + } + shutdown() { + this.systems.events.off("shutdown", this.shutdown, this); + if (this.isWebGL) { + this.game.scale.off(Phaser2.Scale.Events.RESIZE, this.onResize, this); + } + } + destroy() { + this.shutdown(); + } + gameDestroy() { + this.pluginManager.removeGameObject(window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, true, true); + if (this.webGLRenderer) + this.webGLRenderer.dispose(); + _SpinePlugin.gameWebGLRenderer = null; + } + /** Returns the TextureAtlas instance for the given key */ + getAtlas(atlasKey) { + let atlas; + if (this.atlasCache.exists(atlasKey)) { + atlas = this.atlasCache.get(atlasKey); + } else { + let atlasFile = this.game.cache.text.get(atlasKey); + atlas = new TextureAtlas(atlasFile.data); + if (this.isWebGL) { + let gl = this.gl; + const phaserUnpackPmaValue = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL); + if (phaserUnpackPmaValue) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + for (let atlasPage of atlas.pages) { + atlasPage.setTexture(new GLTexture(gl, this.game.textures.get(atlasKey + "!" + atlasPage.name).getSourceImage(), false)); + } + if (phaserUnpackPmaValue) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + } else { + for (let atlasPage of atlas.pages) { + atlasPage.setTexture(new CanvasTexture(this.game.textures.get(atlasKey + "!" + atlasPage.name).getSourceImage())); + } + } + this.atlasCache.add(atlasKey, atlas); + } + return atlas; + } + /** Returns whether the TextureAtlas uses premultiplied alpha */ + isAtlasPremultiplied(atlasKey) { + let atlasFile = this.game.cache.text.get(atlasKey); + if (!atlasFile) + return false; + return atlasFile.premultipliedAlpha; + } + /** Returns the SkeletonData instance for the given data and atlas key */ + getSkeletonData(dataKey, atlasKey) { + const atlas = this.getAtlas(atlasKey); + const combinedKey = dataKey + atlasKey; + let skeletonData; + if (this.skeletonDataCache.exists(combinedKey)) { + skeletonData = this.skeletonDataCache.get(combinedKey); + } else { + if (this.game.cache.json.exists(dataKey)) { + let jsonFile = this.game.cache.json.get(dataKey); + let json = new SkeletonJson(new AtlasAttachmentLoader(atlas)); + skeletonData = json.readSkeletonData(jsonFile); + } else { + let binaryFile = this.game.cache.binary.get(dataKey); + let binary = new SkeletonBinary(new AtlasAttachmentLoader(atlas)); + skeletonData = binary.readSkeletonData(new Uint8Array(binaryFile)); + } + this.skeletonDataCache.add(combinedKey, skeletonData); + } + return skeletonData; + } + /** Creates a new Skeleton instance from the data and atlas. */ + createSkeleton(dataKey, atlasKey) { + return new Skeleton(this.getSkeletonData(dataKey, atlasKey)); + } +}; +var SpinePlugin = _SpinePlugin; +__publicField(SpinePlugin, "gameWebGLRenderer", null); +__publicField(SpinePlugin, "rendererId", 0); +var SpineSkeletonDataFileType = /* @__PURE__ */ ((SpineSkeletonDataFileType2) => { + SpineSkeletonDataFileType2[SpineSkeletonDataFileType2["json"] = 0] = "json"; + SpineSkeletonDataFileType2[SpineSkeletonDataFileType2["binary"] = 1] = "binary"; + return SpineSkeletonDataFileType2; +})(SpineSkeletonDataFileType || {}); +var SpineSkeletonDataFile = class extends Phaser2.Loader.MultiFile { + constructor(loader, key, url, fileType, xhrSettings) { + if (typeof key !== "string") { + const config = key; + key = config.key; + url = config.url; + fileType = config.type === "spineJson" ? 0 /* json */ : 1 /* binary */; + xhrSettings = config.xhrSettings; + } + let file = null; + let isJson = fileType == 0 /* json */; + if (isJson) { + file = new Phaser2.Loader.FileTypes.JSONFile(loader, { + key, + url, + extension: "json", + xhrSettings + }); + } else { + file = new Phaser2.Loader.FileTypes.BinaryFile(loader, { + key, + url, + extension: "skel", + xhrSettings + }); + } + super(loader, SPINE_SKELETON_DATA_FILE_TYPE, key, [file]); + this.fileType = fileType; + } + onFileComplete(file) { + this.pending--; + } + addToCache() { + if (this.isReadyToProcess()) + this.files[0].addToCache(); + } +}; +var SpineAtlasFile = class extends Phaser2.Loader.MultiFile { + constructor(loader, key, url, premultipliedAlpha, xhrSettings) { + if (typeof key !== "string") { + const config = key; + key = config.key; + url = config.url; + premultipliedAlpha = config.premultipliedAlpha; + xhrSettings = config.xhrSettings; + } + super(loader, SPINE_ATLAS_FILE_TYPE, key, [ + new Phaser2.Loader.FileTypes.TextFile(loader, { + key, + url, + xhrSettings, + extension: "atlas" + }) + ]); + this.premultipliedAlpha = premultipliedAlpha; + } + onFileComplete(file) { + if (this.files.indexOf(file) != -1) { + this.pending--; + if (file.type == "text") { + var lines = file.data.split(/\r\n|\r|\n/); + let textures = []; + textures.push(lines[0]); + for (var t = 1; t < lines.length; t++) { + var line = lines[t]; + if (line.trim() === "" && t < lines.length - 1) { + line = lines[t + 1]; + textures.push(line); + } + } + let basePath = file.src.match(/^.*\//) ?? ""; + for (var i = 0; i < textures.length; i++) { + var url = basePath + textures[i]; + var key = file.key + "!" + textures[i]; + var image = new Phaser2.Loader.FileTypes.ImageFile(this.loader, key, url); + if (!this.loader.keyExists(image)) { + this.addToMultiFile(image); + this.loader.addFile(image); + } + } + } + } + } + addToCache() { + if (this.isReadyToProcess()) { + let textureManager = this.loader.textureManager; + for (let file of this.files) { + if (file.type == "image") { + if (!textureManager.exists(file.key)) { + textureManager.addImage(file.key, file.data); + } + } else { + this.premultipliedAlpha = this.premultipliedAlpha ?? (file.data.indexOf("pma: true") >= 0 || file.data.indexOf("pma:true") >= 0); + file.data = { + data: file.data, + premultipliedAlpha: this.premultipliedAlpha + }; + file.addToCache(); + } + } + } + } +}; + +// spine-phaser-v3/src/index.ts +window.spine = { SpinePlugin }; +window["spine.SpinePlugin"] = SpinePlugin; +export { + Alpha, + AlphaMixin, + AlphaTimeline, + Animation, + AnimationState, + AnimationStateAdapter, + AnimationStateData, + AssetManager, + AssetManagerBase, + AtlasAttachmentLoader, + Attachment, + AttachmentTimeline, + BinaryInput, + BlendMode, + Bone, + BoneData, + BoundingBoxAttachment, + CURRENT, + CameraController, + ClippingAttachment, + Color, + Color2Attribute, + ColorAttribute, + ComputedSize, + ComputedSizeMixin, + ConstraintData, + CurveTimeline, + CurveTimeline1, + CurveTimeline2, + DebugUtils, + DeformTimeline, + Depth, + DepthMixin, + Downloader, + DrawOrderTimeline, + Event, + EventData, + EventQueue, + EventTimeline, + EventType, + FIRST, + FakeTexture, + Flip, + FlipMixin, + GLTexture, + HOLD_FIRST, + HOLD_MIX, + HOLD_SUBSEQUENT, + IkConstraint, + IkConstraintData, + IkConstraintTimeline, + Inherit, + InheritTimeline, + Input, + IntSet, + Interpolation, + LoadingScreen, + M00, + M01, + M02, + M03, + M10, + M11, + M12, + M13, + M20, + M21, + M22, + M23, + M30, + M31, + M32, + M33, + ManagedWebGLRenderingContext, + MathUtils, + Matrix42 as Matrix4, + Mesh, + MeshAttachment, + MixBlend, + MixDirection, + Origin, + OriginMixin, + OrthoCamera, + PathAttachment, + PathConstraint, + PathConstraintData, + PathConstraintMixTimeline, + PathConstraintPositionTimeline, + PathConstraintSpacingTimeline, + Physics, + PhysicsConstraintDampingTimeline, + PhysicsConstraintGravityTimeline, + PhysicsConstraintInertiaTimeline, + PhysicsConstraintMassTimeline, + PhysicsConstraintMixTimeline, + PhysicsConstraintResetTimeline, + PhysicsConstraintStrengthTimeline, + PhysicsConstraintTimeline, + PhysicsConstraintWindTimeline, + PointAttachment, + PolygonBatcher, + Pool, + Position2Attribute, + Position3Attribute, + PositionMode, + Pow, + PowOut, + RGB2Timeline, + RGBA2Timeline, + RGBATimeline, + RGBTimeline, + RegionAttachment, + ResizeMode, + RotateMode, + RotateTimeline, + SETUP, + SUBSEQUENT, + ScaleTimeline, + ScaleXTimeline, + ScaleYTimeline, + SceneRenderer, + ScrollFactor, + ScrollFactorMixin, + SequenceTimeline, + SetupPoseBoundsProvider, + Shader, + ShapeRenderer, + ShapeType, + ShearTimeline, + ShearXTimeline, + ShearYTimeline, + Skeleton, + SkeletonBinary, + SkeletonBounds, + SkeletonClipping, + SkeletonData, + SkeletonDebugRenderer, + SkeletonJson, + SkeletonRenderer, + Skin, + SkinEntry, + SkinsAndAnimationBoundsProvider, + Slot, + SlotData, + SpacingMode, + SpineCanvas, + SpineGameObject, + SpinePlugin, + StringSet, + TexCoordAttribute, + Texture, + TextureAtlas, + TextureAtlasPage, + TextureAtlasRegion, + TextureFilter, + TextureRegion, + TextureWrap, + TimeKeeper, + Timeline, + Touch, + TrackEntry, + Transform, + TransformConstraint, + TransformConstraintData, + TransformConstraintTimeline, + TransformMixin, + TranslateTimeline, + TranslateXTimeline, + TranslateYTimeline, + Triangulator, + Utils, + Vector2, + Vector3, + VertexAttachment, + VertexAttribute, + VertexAttributeType, + Visible, + VisibleMixin, + WindowedMean, + createMixin +}; +//# sourceMappingURL=spine-phaser-v3.mjs.map diff --git a/spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs.map b/spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs.map new file mode 100644 index 000000000..39f6ed318 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/esm/spine-phaser-v3.mjs.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../src/require-shim.ts", "../../src/SpinePlugin.ts", "../../src/keys.ts", "../../../spine-core/src/Utils.ts", "../../../spine-core/src/attachments/Attachment.ts", "../../../spine-core/src/attachments/Sequence.ts", "../../../spine-core/src/Animation.ts", "../../../spine-core/src/AnimationState.ts", "../../../spine-core/src/AnimationStateData.ts", "../../../spine-core/src/attachments/BoundingBoxAttachment.ts", "../../../spine-core/src/attachments/ClippingAttachment.ts", "../../../spine-core/src/Texture.ts", "../../../spine-core/src/TextureAtlas.ts", "../../../spine-core/src/attachments/MeshAttachment.ts", "../../../spine-core/src/attachments/PathAttachment.ts", "../../../spine-core/src/attachments/PointAttachment.ts", "../../../spine-core/src/attachments/RegionAttachment.ts", "../../../spine-core/src/AtlasAttachmentLoader.ts", "../../../spine-core/src/BoneData.ts", "../../../spine-core/src/Bone.ts", "../../../spine-core/src/ConstraintData.ts", "../../../spine-core/src/AssetManagerBase.ts", "../../../spine-core/src/Event.ts", "../../../spine-core/src/EventData.ts", "../../../spine-core/src/IkConstraint.ts", "../../../spine-core/src/IkConstraintData.ts", "../../../spine-core/src/PathConstraintData.ts", "../../../spine-core/src/PathConstraint.ts", "../../../spine-core/src/PhysicsConstraint.ts", "../../../spine-core/src/Slot.ts", "../../../spine-core/src/TransformConstraint.ts", "../../../spine-core/src/Skeleton.ts", "../../../spine-core/src/PhysicsConstraintData.ts", "../../../spine-core/src/SkeletonData.ts", "../../../spine-core/src/Skin.ts", "../../../spine-core/src/SlotData.ts", "../../../spine-core/src/TransformConstraintData.ts", "../../../spine-core/src/SkeletonBinary.ts", "../../../spine-core/src/SkeletonBounds.ts", "../../../spine-core/src/Triangulator.ts", "../../../spine-core/src/SkeletonClipping.ts", "../../../spine-core/src/SkeletonJson.ts", "../../../spine-core/src/polyfills.ts", "../../../spine-webgl/src/WebGL.ts", "../../../spine-webgl/src/GLTexture.ts", "../../../spine-webgl/src/AssetManager.ts", "../../../spine-webgl/src/Vector3.ts", "../../../spine-webgl/src/Matrix4.ts", "../../../spine-webgl/src/Camera.ts", "../../../spine-webgl/src/Input.ts", "../../../spine-webgl/src/CameraController.ts", "../../../spine-webgl/src/Shader.ts", "../../../spine-webgl/src/Mesh.ts", "../../../spine-webgl/src/PolygonBatcher.ts", "../../../spine-webgl/src/ShapeRenderer.ts", "../../../spine-webgl/src/SkeletonDebugRenderer.ts", "../../../spine-webgl/src/SkeletonRenderer.ts", "../../../spine-webgl/src/SceneRenderer.ts", "../../../spine-webgl/src/LoadingScreen.ts", "../../../spine-webgl/src/SpineCanvas.ts", "../../src/mixins.ts", "../../src/SpineGameObject.ts", "../../../spine-canvas/src/CanvasTexture.ts", "../../../spine-canvas/src/SkeletonRenderer.ts", "../../src/index.ts"], + "sourcesContent": ["/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\ndeclare global {\n\tvar require: any;\n}\nif (typeof window !== 'undefined' && window.Phaser) {\n\tlet prevRequire = window.require;\n\twindow.require = (x: string) => {\n\t\tif (prevRequire) return prevRequire(x);\n\t\telse if (x === \"Phaser\") return window.Phaser;\n\t}\n}\nexport { }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport * as Phaser from \"phaser\";\nimport { SPINE_ATLAS_CACHE_KEY, SPINE_GAME_OBJECT_TYPE, SPINE_SKELETON_DATA_FILE_TYPE, SPINE_ATLAS_FILE_TYPE, SPINE_SKELETON_FILE_CACHE_KEY as SPINE_SKELETON_DATA_CACHE_KEY } from \"./keys.js\";\nimport { AtlasAttachmentLoader, GLTexture, SceneRenderer, Skeleton, SkeletonBinary, SkeletonData, SkeletonJson, TextureAtlas } from \"@esotericsoftware/spine-webgl\"\nimport { SpineGameObject, SpineGameObjectBoundsProvider } from \"./SpineGameObject.js\";\nimport { CanvasTexture, SkeletonRenderer } from \"@esotericsoftware/spine-canvas\";\n\n/**\n * Configuration object used when creating {@link SpineGameObject} instances via a scene's\n * {@link GameObjectCreator} (`Scene.make`).\n */\nexport interface SpineGameObjectConfig extends Phaser.Types.GameObjects.GameObjectConfig {\n\t/** The x-position of the object, optional, default: 0 */\n\tx?: number,\n\t/** The y-position of the object, optional, default: 0 */\n\ty?: number,\n\t/** The skeleton data key */\n\tdataKey: string,\n\t/** The atlas key */\n\tatlasKey: string\n\t/** The bounds provider, optional, default: `SetupPoseBoundsProvider` */\n\tboundsProvider?: SpineGameObjectBoundsProvider\n}\n\n/**\n * {@link ScenePlugin} implementation adding Spine Runtime capabilities to a scene.\n *\n * The scene's {@link LoaderPlugin} (`Scene.load`) gets these additional functions:\n * * `spineBinary(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`.\n * * `spineJson(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`.\n * * `spineAtlas(key: string, url: string, premultipliedAlpha: boolean = true, xhrSettings?: XHRSettingsObject)`: loads a texture atlas `.atlas` file from the `url` as well as its correponding texture atlas page images.\n *\n * The scene's {@link GameObjectFactory} (`Scene.add`) gets these additional functions:\n * * `spine(x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider = SetupPoseBoundsProvider())`:\n * creates a new {@link SpineGameObject} from the data and atlas at position `(x, y)`, using the {@link BoundsProvider} to calculate its bounding box. The object is automatically added to the scene.\n *\n * The scene's {@link GameObjectCreator} (`Scene.make`) gets these additional functions:\n * * `spine(config: SpineGameObjectConfig)`: creates a new {@link SpineGameObject} from the given configuration object.\n *\n * The plugin has additional public methods to work with Spine Runtime core API objects:\n * * `getAtlas(atlasKey: string)`: returns the {@link TextureAtlas} instance for the given atlas key.\n * * `getSkeletonData(skeletonDataKey: string)`: returns the {@link SkeletonData} instance for the given skeleton data key.\n * * `createSkeleton(skeletonDataKey: string, atlasKey: string, premultipliedAlpha: boolean = true)`: creates a new {@link Skeleton} instance from the given skeleton data and atlas key.\n * * `isPremultipliedAlpha(atlasKey: string)`: returns `true` if the atlas with the given key has premultiplied alpha.\n */\nexport class SpinePlugin extends Phaser.Plugins.ScenePlugin {\n\tgame: Phaser.Game;\n\tprivate isWebGL: boolean;\n\tgl: WebGLRenderingContext | null;\n\tstatic gameWebGLRenderer: SceneRenderer | null = null;\n\tget webGLRenderer (): SceneRenderer | null {\n\t\treturn SpinePlugin.gameWebGLRenderer;\n\t}\n\tcanvasRenderer: SkeletonRenderer | null;\n\tphaserRenderer: Phaser.Renderer.Canvas.CanvasRenderer | Phaser.Renderer.WebGL.WebGLRenderer;\n\tprivate skeletonDataCache: Phaser.Cache.BaseCache;\n\tprivate atlasCache: Phaser.Cache.BaseCache;\n\n\tconstructor (scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) {\n\t\tsuper(scene, pluginManager, pluginKey);\n\t\tthis.game = pluginManager.game;\n\t\tthis.isWebGL = this.game.config.renderType === 2;\n\t\tthis.gl = this.isWebGL ? (this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).gl : null;\n\t\tthis.phaserRenderer = this.game.renderer;\n\t\tthis.canvasRenderer = null;\n\t\tthis.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_DATA_CACHE_KEY);\n\t\tthis.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY);\n\n\t\tlet skeletonJsonFileCallback = function (this: any, key: string,\n\t\t\turl: string,\n\t\t\txhrSettings: Phaser.Types.Loader.XHRSettingsObject) {\n\t\t\tlet file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.json, xhrSettings);\n\t\t\tthis.addFile(file.files);\n\t\t\treturn this;\n\t\t};\n\t\tpluginManager.registerFileType(\"spineJson\", skeletonJsonFileCallback, scene);\n\n\t\tlet skeletonBinaryFileCallback = function (this: any, key: string,\n\t\t\turl: string,\n\t\t\txhrSettings: Phaser.Types.Loader.XHRSettingsObject) {\n\t\t\tlet file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.binary, xhrSettings);\n\t\t\tthis.addFile(file.files);\n\t\t\treturn this;\n\t\t};\n\t\tpluginManager.registerFileType(\"spineBinary\", skeletonBinaryFileCallback, scene);\n\n\t\tlet atlasFileCallback = function (this: any, key: string,\n\t\t\turl: string,\n\t\t\tpremultipliedAlpha: boolean,\n\t\t\txhrSettings: Phaser.Types.Loader.XHRSettingsObject) {\n\t\t\tlet file = new SpineAtlasFile(this as any, key, url, premultipliedAlpha, xhrSettings);\n\t\t\tthis.addFile(file.files);\n\t\t\treturn this;\n\t\t};\n\t\tpluginManager.registerFileType(\"spineAtlas\", atlasFileCallback, scene);\n\n\t\tlet addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider) {\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.clear();\n\t\t\t}\n\n\t\t\tconst spinePlugin = (this.scene.sys as any)[pluginKey] as SpinePlugin;\n\t\t\tlet gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, dataKey, atlasKey, boundsProvider);\n\t\t\tthis.displayList.add(gameObject);\n\t\t\tthis.updateList.add(gameObject);\n\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.rebind();\n\t\t\t}\n\n\t\t\treturn gameObject;\n\t\t};\n\n\t\tlet makeSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, config: SpineGameObjectConfig, addToScene: boolean = false) {\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.clear();\n\t\t\t}\n\n\t\t\tlet x = config.x ? config.x : 0;\n\t\t\tlet y = config.y ? config.y : 0;\n\t\t\tlet boundsProvider = config.boundsProvider ? config.boundsProvider : undefined;\n\n\t\t\tconst spinePlugin = (this.scene.sys as any)[pluginKey] as SpinePlugin;\n\t\t\tlet gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, config.dataKey, config.atlasKey, boundsProvider);\n\t\t\tif (addToScene !== undefined) {\n\t\t\t\tconfig.add = addToScene;\n\t\t\t}\n\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.rebind();\n\t\t\t}\n\n\t\t\treturn Phaser.GameObjects.BuildGameObject(this.scene, gameObject, config);\n\t\t}\n\t\tpluginManager.registerGameObject((window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject);\n\t}\n\n\tstatic rendererId = 0;\n\tboot () {\n\t\tSkeleton.yDown = true;\n\t\tif (this.isWebGL) {\n\t\t\tif (!SpinePlugin.gameWebGLRenderer) {\n\t\t\t\tSpinePlugin.gameWebGLRenderer = new SceneRenderer((this.game.renderer! as Phaser.Renderer.WebGL.WebGLRenderer).canvas, this.gl!, true);\n\t\t\t}\n\t\t\tthis.onResize();\n\t\t\tthis.game.scale.on(Phaser.Scale.Events.RESIZE, this.onResize, this);\n\t\t} else {\n\t\t\tif (!this.canvasRenderer) {\n\t\t\t\tthis.canvasRenderer = new SkeletonRenderer(this.scene!.sys.context);\n\t\t\t}\n\t\t}\n\n\t\tvar eventEmitter = this.systems!.events;\n\t\teventEmitter.once('shutdown', this.shutdown, this);\n\t\teventEmitter.once('destroy', this.destroy, this);\n\t\tthis.game.events.once('destroy', this.gameDestroy, this);\n\t}\n\n\tonResize () {\n\t\tvar phaserRenderer = this.game.renderer;\n\t\tvar sceneRenderer = this.webGLRenderer;\n\n\t\tif (phaserRenderer && sceneRenderer) {\n\t\t\tvar viewportWidth = phaserRenderer.width;\n\t\t\tvar viewportHeight = phaserRenderer.height;\n\t\t\tsceneRenderer.camera.position.x = viewportWidth / 2;\n\t\t\tsceneRenderer.camera.position.y = viewportHeight / 2;\n\t\t\tsceneRenderer.camera.up.y = -1;\n\t\t\tsceneRenderer.camera.direction.z = 1;\n\t\t\tsceneRenderer.camera.setViewport(viewportWidth, viewportHeight);\n\t\t}\n\t}\n\n\tshutdown () {\n\t\tthis.systems!.events.off(\"shutdown\", this.shutdown, this);\n\t\tif (this.isWebGL) {\n\t\t\tthis.game.scale.off(Phaser.Scale.Events.RESIZE, this.onResize, this);\n\t\t}\n\t}\n\n\tdestroy () {\n\t\tthis.shutdown()\n\t}\n\n\tgameDestroy () {\n\t\tthis.pluginManager.removeGameObject((window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, true, true);\n\t\tif (this.webGLRenderer) this.webGLRenderer.dispose();\n\t\tSpinePlugin.gameWebGLRenderer = null;\n\t}\n\n\t/** Returns the TextureAtlas instance for the given key */\n\tgetAtlas (atlasKey: string) {\n\t\tlet atlas: TextureAtlas;\n\t\tif (this.atlasCache.exists(atlasKey)) {\n\t\t\tatlas = this.atlasCache.get(atlasKey);\n\t\t} else {\n\t\t\tlet atlasFile = this.game.cache.text.get(atlasKey) as { data: string, premultipliedAlpha: boolean };\n\t\t\tatlas = new TextureAtlas(atlasFile.data);\n\t\t\tif (this.isWebGL) {\n\t\t\t\tlet gl = this.gl!;\n\t\t\t\tconst phaserUnpackPmaValue = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL);\n\t\t\t\tif (phaserUnpackPmaValue) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\t\t\t\tfor (let atlasPage of atlas.pages) {\n\t\t\t\t\tatlasPage.setTexture(new GLTexture(gl, this.game.textures.get(atlasKey + \"!\" + atlasPage.name).getSourceImage() as HTMLImageElement | ImageBitmap, false));\n\t\t\t\t}\n\t\t\t\tif (phaserUnpackPmaValue) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);\n\t\t\t} else {\n\t\t\t\tfor (let atlasPage of atlas.pages) {\n\t\t\t\t\tatlasPage.setTexture(new CanvasTexture(this.game.textures.get(atlasKey + \"!\" + atlasPage.name).getSourceImage() as HTMLImageElement | ImageBitmap));\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.atlasCache.add(atlasKey, atlas);\n\t\t}\n\t\treturn atlas;\n\t}\n\n\t/** Returns whether the TextureAtlas uses premultiplied alpha */\n\tisAtlasPremultiplied (atlasKey: string) {\n\t\tlet atlasFile = this.game.cache.text.get(atlasKey);\n\t\tif (!atlasFile) return false;\n\t\treturn atlasFile.premultipliedAlpha;\n\t}\n\n\t/** Returns the SkeletonData instance for the given data and atlas key */\n\tgetSkeletonData (dataKey: string, atlasKey: string) {\n\t\tconst atlas = this.getAtlas(atlasKey)\n\t\tconst combinedKey = dataKey + atlasKey;\n\t\tlet skeletonData: SkeletonData;\n\t\tif (this.skeletonDataCache.exists(combinedKey)) {\n\t\t\tskeletonData = this.skeletonDataCache.get(combinedKey);\n\t\t} else {\n\t\t\tif (this.game.cache.json.exists(dataKey)) {\n\t\t\t\tlet jsonFile = this.game.cache.json.get(dataKey) as any;\n\t\t\t\tlet json = new SkeletonJson(new AtlasAttachmentLoader(atlas));\n\t\t\t\tskeletonData = json.readSkeletonData(jsonFile);\n\t\t\t} else {\n\t\t\t\tlet binaryFile = this.game.cache.binary.get(dataKey) as ArrayBuffer;\n\t\t\t\tlet binary = new SkeletonBinary(new AtlasAttachmentLoader(atlas));\n\t\t\t\tskeletonData = binary.readSkeletonData(new Uint8Array(binaryFile));\n\t\t\t}\n\t\t\tthis.skeletonDataCache.add(combinedKey, skeletonData);\n\t\t}\n\t\treturn skeletonData;\n\t}\n\n\t/** Creates a new Skeleton instance from the data and atlas. */\n\tcreateSkeleton (dataKey: string, atlasKey: string) {\n\t\treturn new Skeleton(this.getSkeletonData(dataKey, atlasKey));\n\t}\n}\n\nenum SpineSkeletonDataFileType {\n\tjson,\n\tbinary\n}\n\ninterface SpineSkeletonDataFileConfig {\n\tkey: string;\n\turl: string;\n\ttype: \"spineJson\" | \"spineBinary\";\n\txhrSettings?: Phaser.Types.Loader.XHRSettingsObject\n}\n\nclass SpineSkeletonDataFile extends Phaser.Loader.MultiFile {\n\tconstructor (loader: Phaser.Loader.LoaderPlugin, key: string | SpineSkeletonDataFileConfig, url?: string, public fileType?: SpineSkeletonDataFileType, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject) {\n\t\tif (typeof key !== \"string\") {\n\t\t\tconst config = key;\n\t\t\tkey = config.key;\n\t\t\turl = config.url;\n\t\t\tfileType = config.type === \"spineJson\" ? SpineSkeletonDataFileType.json : SpineSkeletonDataFileType.binary;\n\t\t\txhrSettings = config.xhrSettings;\n\t\t}\n\t\tlet file = null;\n\t\tlet isJson = fileType == SpineSkeletonDataFileType.json;\n\t\tif (isJson) {\n\t\t\tfile = new Phaser.Loader.FileTypes.JSONFile(loader, {\n\t\t\t\tkey: key,\n\t\t\t\turl: url,\n\t\t\t\textension: \"json\",\n\t\t\t\txhrSettings: xhrSettings,\n\t\t\t} as Phaser.Types.Loader.FileTypes.JSONFileConfig);\n\t\t} else {\n\t\t\tfile = new Phaser.Loader.FileTypes.BinaryFile(loader, {\n\t\t\t\tkey: key,\n\t\t\t\turl: url,\n\t\t\t\textension: \"skel\",\n\t\t\t\txhrSettings: xhrSettings,\n\t\t\t} as Phaser.Types.Loader.FileTypes.BinaryFileConfig);\n\t\t}\n\t\tsuper(loader, SPINE_SKELETON_DATA_FILE_TYPE, key, [file]);\n\t}\n\n\tonFileComplete (file: Phaser.Loader.File) {\n\t\tthis.pending--;\n\t}\n\n\taddToCache () {\n\t\tif (this.isReadyToProcess()) this.files[0].addToCache();\n\t}\n}\n\ninterface SpineAtlasFileConfig {\n\tkey: string;\n\turl: string;\n\tpremultipliedAlpha?: boolean;\n\txhrSettings?: Phaser.Types.Loader.XHRSettingsObject;\n}\n\nclass SpineAtlasFile extends Phaser.Loader.MultiFile {\n\tconstructor (loader: Phaser.Loader.LoaderPlugin, key: string | SpineAtlasFileConfig, url?: string, public premultipliedAlpha?: boolean, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject) {\n\t\tif (typeof key !== \"string\") {\n\t\t\tconst config = key;\n\t\t\tkey = config.key;\n\t\t\turl = config.url;\n\t\t\tpremultipliedAlpha = config.premultipliedAlpha;\n\t\t\txhrSettings = config.xhrSettings;\n\t\t}\n\n\t\tsuper(loader, SPINE_ATLAS_FILE_TYPE, key, [\n\t\t\tnew Phaser.Loader.FileTypes.TextFile(loader, {\n\t\t\t\tkey: key,\n\t\t\t\turl: url,\n\t\t\t\txhrSettings: xhrSettings,\n\t\t\t\textension: \"atlas\"\n\t\t\t})\n\t\t]);\n\t}\n\n\tonFileComplete (file: Phaser.Loader.File) {\n\t\tif (this.files.indexOf(file) != -1) {\n\t\t\tthis.pending--;\n\n\t\t\tif (file.type == \"text\") {\n\t\t\t\tvar lines = file.data.split(/\\r\\n|\\r|\\n/);\n\t\t\t\tlet textures = [];\n\t\t\t\ttextures.push(lines[0]);\n\t\t\t\tfor (var t = 1; t < lines.length; t++) {\n\t\t\t\t\tvar line = lines[t];\n\t\t\t\t\tif (line.trim() === '' && t < lines.length - 1) {\n\t\t\t\t\t\tline = lines[t + 1];\n\t\t\t\t\t\ttextures.push(line);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet basePath = file.src.match(/^.*\\//) ?? \"\";\n\t\t\t\tfor (var i = 0; i < textures.length; i++) {\n\t\t\t\t\tvar url = basePath + textures[i];\n\t\t\t\t\tvar key = file.key + \"!\" + textures[i];\n\t\t\t\t\tvar image = new Phaser.Loader.FileTypes.ImageFile(this.loader, key, url);\n\n\t\t\t\t\tif (!this.loader.keyExists(image)) {\n\t\t\t\t\t\tthis.addToMultiFile(image);\n\t\t\t\t\t\tthis.loader.addFile(image);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\taddToCache () {\n\t\tif (this.isReadyToProcess()) {\n\t\t\tlet textureManager = this.loader.textureManager;\n\t\t\tfor (let file of this.files) {\n\t\t\t\tif (file.type == \"image\") {\n\t\t\t\t\tif (!textureManager.exists(file.key)) {\n\t\t\t\t\t\ttextureManager.addImage(file.key, file.data);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.premultipliedAlpha = this.premultipliedAlpha ?? (file.data.indexOf(\"pma: true\") >= 0 || file.data.indexOf(\"pma:true\") >= 0);\n\t\t\t\t\tfile.data = {\n\t\t\t\t\t\tdata: file.data,\n\t\t\t\t\t\tpremultipliedAlpha: this.premultipliedAlpha,\n\t\t\t\t\t};\n\t\t\t\t\tfile.addToCache();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport const SPINE_SKELETON_FILE_CACHE_KEY = \"esotericsoftware.spine.skeletonFile.cache\";\nexport const SPINE_ATLAS_CACHE_KEY = \"esotericsoftware.spine.atlas.cache\";\nexport const SPINE_LOADER_TYPE = \"spine\";\nexport const SPINE_SKELETON_DATA_FILE_TYPE = \"spineSkeletonData\";\nexport const SPINE_ATLAS_FILE_TYPE = \"spineAtlasData\";\nexport const SPINE_GAME_OBJECT_TYPE = \"spine\";\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Skeleton } from \"./Skeleton.js\";\nimport { MixBlend } from \"./Animation.js\";\n\nexport interface StringMap {\n\t[key: string]: T;\n}\n\nexport class IntSet {\n\tarray = new Array();\n\n\tadd (value: number): boolean {\n\t\tlet contains = this.contains(value);\n\t\tthis.array[value | 0] = value | 0;\n\t\treturn !contains;\n\t}\n\n\tcontains (value: number) {\n\t\treturn this.array[value | 0] != undefined;\n\t}\n\n\tremove (value: number) {\n\t\tthis.array[value | 0] = undefined;\n\t}\n\n\tclear () {\n\t\tthis.array.length = 0;\n\t}\n}\n\nexport class StringSet {\n\tentries: StringMap = {};\n\tsize = 0;\n\n\tadd (value: string): boolean {\n\t\tlet contains = this.entries[value];\n\t\tthis.entries[value] = true;\n\t\tif (!contains) {\n\t\t\tthis.size++;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\taddAll (values: string[]): boolean {\n\t\tlet oldSize = this.size;\n\t\tfor (var i = 0, n = values.length; i < n; i++)\n\t\t\tthis.add(values[i]);\n\t\treturn oldSize != this.size;\n\t}\n\n\tcontains (value: string) {\n\t\treturn this.entries[value];\n\t}\n\n\tclear () {\n\t\tthis.entries = {};\n\t\tthis.size = 0;\n\t}\n}\n\nexport type NumberArrayLike = Array | Float32Array;\nexport type IntArrayLike = Array | Int16Array;\n\nexport interface Disposable {\n\tdispose (): void;\n}\n\nexport interface Restorable {\n\trestore (): void;\n}\n\nexport class Color {\n\tpublic static WHITE = new Color(1, 1, 1, 1);\n\tpublic static RED = new Color(1, 0, 0, 1);\n\tpublic static GREEN = new Color(0, 1, 0, 1);\n\tpublic static BLUE = new Color(0, 0, 1, 1);\n\tpublic static MAGENTA = new Color(1, 0, 1, 1);\n\n\tconstructor (public r: number = 0, public g: number = 0, public b: number = 0, public a: number = 0) {\n\t}\n\n\tset (r: number, g: number, b: number, a: number) {\n\t\tthis.r = r;\n\t\tthis.g = g;\n\t\tthis.b = b;\n\t\tthis.a = a;\n\t\treturn this.clamp();\n\t}\n\n\tsetFromColor (c: Color) {\n\t\tthis.r = c.r;\n\t\tthis.g = c.g;\n\t\tthis.b = c.b;\n\t\tthis.a = c.a;\n\t\treturn this;\n\t}\n\n\tsetFromString (hex: string) {\n\t\thex = hex.charAt(0) == '#' ? hex.substr(1) : hex;\n\t\tthis.r = parseInt(hex.substr(0, 2), 16) / 255;\n\t\tthis.g = parseInt(hex.substr(2, 2), 16) / 255;\n\t\tthis.b = parseInt(hex.substr(4, 2), 16) / 255;\n\t\tthis.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255;\n\t\treturn this;\n\t}\n\n\tadd (r: number, g: number, b: number, a: number) {\n\t\tthis.r += r;\n\t\tthis.g += g;\n\t\tthis.b += b;\n\t\tthis.a += a;\n\t\treturn this.clamp();\n\t}\n\n\tclamp () {\n\t\tif (this.r < 0) this.r = 0;\n\t\telse if (this.r > 1) this.r = 1;\n\n\t\tif (this.g < 0) this.g = 0;\n\t\telse if (this.g > 1) this.g = 1;\n\n\t\tif (this.b < 0) this.b = 0;\n\t\telse if (this.b > 1) this.b = 1;\n\n\t\tif (this.a < 0) this.a = 0;\n\t\telse if (this.a > 1) this.a = 1;\n\t\treturn this;\n\t}\n\n\tstatic rgba8888ToColor (color: Color, value: number) {\n\t\tcolor.r = ((value & 0xff000000) >>> 24) / 255;\n\t\tcolor.g = ((value & 0x00ff0000) >>> 16) / 255;\n\t\tcolor.b = ((value & 0x0000ff00) >>> 8) / 255;\n\t\tcolor.a = ((value & 0x000000ff)) / 255;\n\t}\n\n\tstatic rgb888ToColor (color: Color, value: number) {\n\t\tcolor.r = ((value & 0x00ff0000) >>> 16) / 255;\n\t\tcolor.g = ((value & 0x0000ff00) >>> 8) / 255;\n\t\tcolor.b = ((value & 0x000000ff)) / 255;\n\t}\n\n\ttoRgb888 () {\n\t\tconst hex = (x: number) => (\"0\" + (x * 255).toString(16)).slice(-2);\n\t\treturn Number(\"0x\" + hex(this.r) + hex(this.g) + hex(this.b));\n\t}\n\n\tstatic fromString (hex: string): Color {\n\t\treturn new Color().setFromString(hex);\n\t}\n}\n\nexport class MathUtils {\n\tstatic PI = 3.1415927;\n\tstatic PI2 = MathUtils.PI * 2;\n\tstatic invPI2 = 1 / MathUtils.PI2;\n\tstatic radiansToDegrees = 180 / MathUtils.PI;\n\tstatic radDeg = MathUtils.radiansToDegrees;\n\tstatic degreesToRadians = MathUtils.PI / 180;\n\tstatic degRad = MathUtils.degreesToRadians;\n\n\tstatic clamp (value: number, min: number, max: number) {\n\t\tif (value < min) return min;\n\t\tif (value > max) return max;\n\t\treturn value;\n\t}\n\n\tstatic cosDeg (degrees: number) {\n\t\treturn Math.cos(degrees * MathUtils.degRad);\n\t}\n\n\tstatic sinDeg (degrees: number) {\n\t\treturn Math.sin(degrees * MathUtils.degRad);\n\t}\n\n\tstatic atan2Deg (y: number, x: number) {\n\t\treturn Math.atan2(y, x) * MathUtils.degRad;\n\t}\n\n\tstatic signum (value: number): number {\n\t\treturn value > 0 ? 1 : value < 0 ? -1 : 0;\n\t}\n\n\tstatic toInt (x: number) {\n\t\treturn x > 0 ? Math.floor(x) : Math.ceil(x);\n\t}\n\n\tstatic cbrt (x: number) {\n\t\tlet y = Math.pow(Math.abs(x), 1 / 3);\n\t\treturn x < 0 ? -y : y;\n\t}\n\n\tstatic randomTriangular (min: number, max: number): number {\n\t\treturn MathUtils.randomTriangularWith(min, max, (min + max) * 0.5);\n\t}\n\n\tstatic randomTriangularWith (min: number, max: number, mode: number): number {\n\t\tlet u = Math.random();\n\t\tlet d = max - min;\n\t\tif (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min));\n\t\treturn max - Math.sqrt((1 - u) * d * (max - mode));\n\t}\n\n\tstatic isPowerOfTwo (value: number) {\n\t\treturn value && (value & (value - 1)) === 0;\n\t}\n}\n\nexport abstract class Interpolation {\n\tprotected abstract applyInternal (a: number): number;\n\tapply (start: number, end: number, a: number): number {\n\t\treturn start + (end - start) * this.applyInternal(a);\n\t}\n}\n\nexport class Pow extends Interpolation {\n\tprotected power = 2;\n\n\tconstructor (power: number) {\n\t\tsuper();\n\t\tthis.power = power;\n\t}\n\n\tapplyInternal (a: number): number {\n\t\tif (a <= 0.5) return Math.pow(a * 2, this.power) / 2;\n\t\treturn Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1;\n\t}\n}\n\nexport class PowOut extends Pow {\n\tconstructor (power: number) {\n\t\tsuper(power);\n\t}\n\n\tapplyInternal (a: number): number {\n\t\treturn Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1;\n\t}\n}\n\nexport class Utils {\n\tstatic SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== \"undefined\";\n\n\tstatic arrayCopy (source: ArrayLike, sourceStart: number, dest: ArrayLike, destStart: number, numElements: number) {\n\t\tfor (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) {\n\t\t\tdest[j] = source[i];\n\t\t}\n\t}\n\n\tstatic arrayFill (array: ArrayLike, fromIndex: number, toIndex: number, value: T) {\n\t\tfor (let i = fromIndex; i < toIndex; i++)\n\t\t\tarray[i] = value;\n\t}\n\n\tstatic setArraySize (array: Array, size: number, value: any = 0): Array {\n\t\tlet oldSize = array.length;\n\t\tif (oldSize == size) return array;\n\t\tarray.length = size;\n\t\tif (oldSize < size) {\n\t\t\tfor (let i = oldSize; i < size; i++) array[i] = value;\n\t\t}\n\t\treturn array;\n\t}\n\n\tstatic ensureArrayCapacity (array: Array, size: number, value: any = 0): Array {\n\t\tif (array.length >= size) return array;\n\t\treturn Utils.setArraySize(array, size, value);\n\t}\n\n\tstatic newArray (size: number, defaultValue: T): Array {\n\t\tlet array = new Array(size);\n\t\tfor (let i = 0; i < size; i++) array[i] = defaultValue;\n\t\treturn array;\n\t}\n\n\tstatic newFloatArray (size: number): NumberArrayLike {\n\t\tif (Utils.SUPPORTS_TYPED_ARRAYS)\n\t\t\treturn new Float32Array(size)\n\t\telse {\n\t\t\tlet array = new Array(size);\n\t\t\tfor (let i = 0; i < array.length; i++) array[i] = 0;\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tstatic newShortArray (size: number): IntArrayLike {\n\t\tif (Utils.SUPPORTS_TYPED_ARRAYS)\n\t\t\treturn new Int16Array(size)\n\t\telse {\n\t\t\tlet array = new Array(size);\n\t\t\tfor (let i = 0; i < array.length; i++) array[i] = 0;\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tstatic toFloatArray (array: Array) {\n\t\treturn Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;\n\t}\n\n\tstatic toSinglePrecision (value: number) {\n\t\treturn Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value;\n\t}\n\n\t// This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\tstatic webkit602BugfixHelper (alpha: number, blend: MixBlend) {\n\t}\n\n\tstatic contains (array: Array, element: T, identity = true) {\n\t\tfor (var i = 0; i < array.length; i++)\n\t\t\tif (array[i] == element) return true;\n\t\treturn false;\n\t}\n\n\tstatic enumValue (type: any, name: string) {\n\t\treturn type[name[0].toUpperCase() + name.slice(1)];\n\t}\n}\n\nexport class DebugUtils {\n\tstatic logBones (skeleton: Skeleton) {\n\t\tfor (let i = 0; i < skeleton.bones.length; i++) {\n\t\t\tlet bone = skeleton.bones[i];\n\t\t\tconsole.log(bone.data.name + \", \" + bone.a + \", \" + bone.b + \", \" + bone.c + \", \" + bone.d + \", \" + bone.worldX + \", \" + bone.worldY);\n\t\t}\n\t}\n}\n\nexport class Pool {\n\tprivate items = new Array();\n\tprivate instantiator: () => T;\n\n\tconstructor (instantiator: () => T) {\n\t\tthis.instantiator = instantiator;\n\t}\n\n\tobtain () {\n\t\treturn this.items.length > 0 ? this.items.pop()! : this.instantiator();\n\t}\n\n\tfree (item: T) {\n\t\tif ((item as any).reset) (item as any).reset();\n\t\tthis.items.push(item);\n\t}\n\n\tfreeAll (items: ArrayLike) {\n\t\tfor (let i = 0; i < items.length; i++)\n\t\t\tthis.free(items[i]);\n\t}\n\n\tclear () {\n\t\tthis.items.length = 0;\n\t}\n}\n\nexport class Vector2 {\n\tconstructor (public x = 0, public y = 0) {\n\t}\n\n\tset (x: number, y: number): Vector2 {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\treturn this;\n\t}\n\n\tlength () {\n\t\tlet x = this.x;\n\t\tlet y = this.y;\n\t\treturn Math.sqrt(x * x + y * y);\n\t}\n\n\tnormalize () {\n\t\tlet len = this.length();\n\t\tif (len != 0) {\n\t\t\tthis.x /= len;\n\t\t\tthis.y /= len;\n\t\t}\n\t\treturn this;\n\t}\n}\n\nexport class TimeKeeper {\n\tmaxDelta = 0.064;\n\tframesPerSecond = 0;\n\tdelta = 0;\n\ttotalTime = 0;\n\n\tprivate lastTime = Date.now() / 1000;\n\tprivate frameCount = 0;\n\tprivate frameTime = 0;\n\n\tupdate () {\n\t\tlet now = Date.now() / 1000;\n\t\tthis.delta = now - this.lastTime;\n\t\tthis.frameTime += this.delta;\n\t\tthis.totalTime += this.delta;\n\t\tif (this.delta > this.maxDelta) this.delta = this.maxDelta;\n\t\tthis.lastTime = now;\n\n\t\tthis.frameCount++;\n\t\tif (this.frameTime > 1) {\n\t\t\tthis.framesPerSecond = this.frameCount / this.frameTime;\n\t\t\tthis.frameTime = 0;\n\t\t\tthis.frameCount = 0;\n\t\t}\n\t}\n}\n\nexport interface ArrayLike {\n\tlength: number;\n\t[n: number]: T;\n}\n\nexport class WindowedMean {\n\tvalues: Array;\n\taddedValues = 0;\n\tlastValue = 0;\n\tmean = 0;\n\tdirty = true;\n\n\tconstructor (windowSize: number = 32) {\n\t\tthis.values = new Array(windowSize);\n\t}\n\n\thasEnoughData () {\n\t\treturn this.addedValues >= this.values.length;\n\t}\n\n\taddValue (value: number) {\n\t\tif (this.addedValues < this.values.length) this.addedValues++;\n\t\tthis.values[this.lastValue++] = value;\n\t\tif (this.lastValue > this.values.length - 1) this.lastValue = 0;\n\t\tthis.dirty = true;\n\t}\n\n\tgetMean () {\n\t\tif (this.hasEnoughData()) {\n\t\t\tif (this.dirty) {\n\t\t\t\tlet mean = 0;\n\t\t\t\tfor (let i = 0; i < this.values.length; i++)\n\t\t\t\t\tmean += this.values[i];\n\t\t\t\tthis.mean = mean / this.values.length;\n\t\t\t\tthis.dirty = false;\n\t\t\t}\n\t\t\treturn this.mean;\n\t\t}\n\t\treturn 0;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Slot } from \"../Slot.js\";\nimport { NumberArrayLike, Utils } from \"../Utils.js\";\n\n/** The base class for all attachments. */\nexport abstract class Attachment {\n\tname: string;\n\n\tconstructor (name: string) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t}\n\n\tabstract copy (): Attachment;\n}\n\n/** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's\n * {@link Slot#deform}. */\nexport abstract class VertexAttachment extends Attachment {\n\tprivate static nextID = 0;\n\n\t/** The unique ID for this attachment. */\n\tid = VertexAttachment.nextID++;\n\n\t/** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting\n\t * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null\n\t * if this attachment has no weights. */\n\tbones: Array | null = null;\n\n\t/** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y`\n\t * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting\n\t * each vertex. */\n\tvertices: NumberArrayLike = [];\n\n\t/** The maximum number of world vertex values that can be output by\n\t * {@link #computeWorldVertices()} using the `count` parameter. */\n\tworldVerticesLength = 0;\n\n\t/** Timelines for the timeline attachment are also applied to this attachment.\n\t * May be null if no attachment-specific timelines should be applied. */\n\ttimelineAttachment: Attachment = this;\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\t/** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is\n\t * not empty, it is used to deform the vertices.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide.\n\t * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y.\n\t * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`.\n\t * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` *\n\t * `stride` / 2.\n\t * @param offset The `worldVertices` index to begin writing values.\n\t * @param stride The number of `worldVertices` entries between the value pairs written. */\n\tcomputeWorldVertices (slot: Slot, start: number, count: number, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tcount = offset + (count >> 1) * stride;\n\t\tlet skeleton = slot.bone.skeleton;\n\t\tlet deformArray = slot.deform;\n\t\tlet vertices = this.vertices;\n\t\tlet bones = this.bones;\n\t\tif (!bones) {\n\t\t\tif (deformArray.length > 0) vertices = deformArray;\n\t\t\tlet bone = slot.bone;\n\t\t\tlet x = bone.worldX;\n\t\t\tlet y = bone.worldY;\n\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\tfor (let v = start, w = offset; w < count; v += 2, w += stride) {\n\t\t\t\tlet vx = vertices[v], vy = vertices[v + 1];\n\t\t\t\tworldVertices[w] = vx * a + vy * b + x;\n\t\t\t\tworldVertices[w + 1] = vx * c + vy * d + y;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet v = 0, skip = 0;\n\t\tfor (let i = 0; i < start; i += 2) {\n\t\t\tlet n = bones[v];\n\t\t\tv += n + 1;\n\t\t\tskip += n;\n\t\t}\n\t\tlet skeletonBones = skeleton.bones;\n\t\tif (deformArray.length == 0) {\n\t\t\tfor (let w = offset, b = skip * 3; w < count; w += stride) {\n\t\t\t\tlet wx = 0, wy = 0;\n\t\t\t\tlet n = bones[v++];\n\t\t\t\tn += v;\n\t\t\t\tfor (; v < n; v++, b += 3) {\n\t\t\t\t\tlet bone = skeletonBones[bones[v]];\n\t\t\t\t\tlet vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];\n\t\t\t\t\twx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;\n\t\t\t\t\twy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;\n\t\t\t\t}\n\t\t\t\tworldVertices[w] = wx;\n\t\t\t\tworldVertices[w + 1] = wy;\n\t\t\t}\n\t\t} else {\n\t\t\tlet deform = deformArray;\n\t\t\tfor (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {\n\t\t\t\tlet wx = 0, wy = 0;\n\t\t\t\tlet n = bones[v++];\n\t\t\t\tn += v;\n\t\t\t\tfor (; v < n; v++, b += 3, f += 2) {\n\t\t\t\t\tlet bone = skeletonBones[bones[v]];\n\t\t\t\t\tlet vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];\n\t\t\t\t\twx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;\n\t\t\t\t\twy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;\n\t\t\t\t}\n\t\t\t\tworldVertices[w] = wx;\n\t\t\t\tworldVertices[w + 1] = wy;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Does not copy id (generated) or name (set on construction). **/\n\tcopyTo (attachment: VertexAttachment) {\n\t\tif (this.bones) {\n\t\t\tattachment.bones = new Array(this.bones.length);\n\t\t\tUtils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length);\n\t\t} else\n\t\t\tattachment.bones = null;\n\n\t\tif (this.vertices) {\n\t\t\tattachment.vertices = Utils.newFloatArray(this.vertices.length);\n\t\t\tUtils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length);\n\t\t}\n\n\t\tattachment.worldVerticesLength = this.worldVerticesLength;\n\t\tattachment.timelineAttachment = this.timelineAttachment;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TextureRegion } from \"../Texture.js\";\nimport { Slot } from \"../Slot.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Utils } from \"../Utils.js\";\n\n\nexport class Sequence {\n\tprivate static _nextID = 0;\n\n\tid = Sequence.nextID();\n\tregions: TextureRegion[];\n\tstart = 0;\n\tdigits = 0;\n\t/** The index of the region to show for the setup pose. */\n\tsetupIndex = 0;\n\n\tconstructor (count: number) {\n\t\tthis.regions = new Array(count);\n\t}\n\n\tcopy (): Sequence {\n\t\tlet copy = new Sequence(this.regions.length);\n\t\tUtils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length);\n\t\tcopy.start = this.start;\n\t\tcopy.digits = this.digits;\n\t\tcopy.setupIndex = this.setupIndex;\n\t\treturn copy;\n\t}\n\n\tapply (slot: Slot, attachment: HasTextureRegion) {\n\t\tlet index = slot.sequenceIndex;\n\t\tif (index == -1) index = this.setupIndex;\n\t\tif (index >= this.regions.length) index = this.regions.length - 1;\n\t\tlet region = this.regions[index];\n\t\tif (attachment.region != region) {\n\t\t\tattachment.region = region;\n\t\t\tattachment.updateRegion();\n\t\t}\n\t}\n\n\tgetPath (basePath: string, index: number): string {\n\t\tlet result = basePath;\n\t\tlet frame = (this.start + index).toString();\n\t\tfor (let i = this.digits - frame.length; i > 0; i--)\n\t\t\tresult += \"0\";\n\t\tresult += frame;\n\t\treturn result;\n\t}\n\n\tprivate static nextID (): number {\n\t\treturn Sequence._nextID++;\n\t}\n}\n\nexport enum SequenceMode {\n\thold = 0,\n\tonce = 1,\n\tloop = 2,\n\tpingpong = 3,\n\tonceReverse = 4,\n\tloopReverse = 5,\n\tpingpongReverse = 6\n}\n\nexport const SequenceModeValues = [\n\tSequenceMode.hold,\n\tSequenceMode.once,\n\tSequenceMode.loop,\n\tSequenceMode.pingpong,\n\tSequenceMode.onceReverse,\n\tSequenceMode.loopReverse,\n\tSequenceMode.pingpongReverse\n];\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { IkConstraint } from \"./IkConstraint.js\";\nimport { PathConstraint } from \"./PathConstraint.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { TransformConstraint } from \"./TransformConstraint.js\";\nimport { StringSet, Utils, MathUtils, NumberArrayLike } from \"./Utils.js\";\nimport { Event } from \"./Event.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { SequenceMode, SequenceModeValues } from \"./attachments/Sequence.js\";\nimport { PhysicsConstraint } from \"./PhysicsConstraint.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Inherit } from \"./BoneData.js\";\n\n/** A simple container for a list of timelines and a name. */\nexport class Animation {\n\t/** The animation's name, which is unique across all animations in the skeleton. */\n\tname: string;\n\ttimelines: Array = [];\n\ttimelineIds: StringSet = new StringSet();\n\n\t/** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */\n\tduration: number;\n\n\tconstructor (name: string, timelines: Array, duration: number) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t\tthis.setTimelines(timelines);\n\t\tthis.duration = duration;\n\t}\n\n\tsetTimelines (timelines: Array) {\n\t\tif (!timelines) throw new Error(\"timelines cannot be null.\");\n\t\tthis.timelines = timelines;\n\t\tthis.timelineIds.clear();\n\t\tfor (var i = 0; i < timelines.length; i++)\n\t\t\tthis.timelineIds.addAll(timelines[i].getPropertyIds());\n\t}\n\n\thasTimeline (ids: string[]): boolean {\n\t\tfor (let i = 0; i < ids.length; i++)\n\t\t\tif (this.timelineIds.contains(ids[i])) return true;\n\t\treturn false;\n\t}\n\n\t/** Applies all the animation's timelines to the specified skeleton.\n\t *\n\t * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}.\n\t * @param loop If true, the animation repeats after {@link #getDuration()}.\n\t * @param events May be null to ignore fired events. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\n\t\tif (loop && this.duration != 0) {\n\t\t\ttime %= this.duration;\n\t\t\tif (lastTime > 0) lastTime %= this.duration;\n\t\t}\n\n\t\tlet timelines = this.timelines;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\ttimelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);\n\t}\n}\n\n/** Controls how a timeline value is mixed with the setup pose value or current pose value when a timeline's `alpha`\n * < 1.\n *\n * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */\nexport enum MixBlend {\n\t/** Transitions from the setup value to the timeline value (the current value is not used). Before the first key, the setup\n\t * value is set. */\n\tsetup,\n\t/** Transitions from the current value to the timeline value. Before the first key, transitions from the current value to\n\t * the setup value. Timelines which perform instant transitions, such as {@link DrawOrderTimeline} or\n\t * {@link AttachmentTimeline}, use the setup value before the first key.\n\t *\n\t * `first` is intended for the first animations applied, not for animations layered on top of those. */\n\tfirst,\n\t/** Transitions from the current value to the timeline value. No change is made before the first key (the current value is\n\t * kept until the first key).\n\t *\n\t * `replace` is intended for animations layered on top of others, not for the first animations applied. */\n\treplace,\n\t/** Transitions from the current value to the current value plus the timeline value. No change is made before the first key\n\t * (the current value is kept until the first key).\n\t *\n\t * `add` is intended for animations layered on top of others, not for the first animations applied. Properties\n\t * keyed by additive animations must be set manually or by another animation before applying the additive animations, else\n\t * the property values will increase continually. */\n\tadd\n}\n\n/** Indicates whether a timeline's `alpha` is mixing out over time toward 0 (the setup or current pose value) or\n * mixing in toward 1 (the timeline's value).\n *\n * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */\nexport enum MixDirection {\n\tmixIn, mixOut\n}\n\nconst Property = {\n\trotate: 0,\n\tx: 1,\n\ty: 2,\n\tscaleX: 3,\n\tscaleY: 4,\n\tshearX: 5,\n\tshearY: 6,\n\tinherit: 7,\n\n\trgb: 8,\n\talpha: 9,\n\trgb2: 10,\n\n\tattachment: 11,\n\tdeform: 12,\n\n\tevent: 13,\n\tdrawOrder: 14,\n\n\tikConstraint: 15,\n\ttransformConstraint: 16,\n\n\tpathConstraintPosition: 17,\n\tpathConstraintSpacing: 18,\n\tpathConstraintMix: 19,\n\n\tphysicsConstraintInertia: 20,\n\tphysicsConstraintStrength: 21,\n\tphysicsConstraintDamping: 22,\n\tphysicsConstraintMass: 23,\n\tphysicsConstraintWind: 24,\n\tphysicsConstraintGravity: 25,\n\tphysicsConstraintMix: 26,\n\tphysicsConstraintReset: 27,\n\n\tsequence: 28,\n}\n\n/** The interface for all timelines. */\nexport abstract class Timeline {\n\tpropertyIds: string[];\n\tframes: NumberArrayLike;\n\n\tconstructor (frameCount: number, propertyIds: string[]) {\n\t\tthis.propertyIds = propertyIds;\n\t\tthis.frames = Utils.newFloatArray(frameCount * this.getFrameEntries());\n\t}\n\n\tgetPropertyIds () {\n\t\treturn this.propertyIds;\n\t}\n\n\tgetFrameEntries (): number {\n\t\treturn 1;\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length / this.getFrameEntries();\n\t}\n\n\tgetDuration (): number {\n\t\treturn this.frames[this.frames.length - this.getFrameEntries()];\n\t}\n\n\tabstract apply (skeleton: Skeleton, lastTime: number, time: number, events: Array | null, alpha: number, blend: MixBlend, direction: MixDirection): void;\n\n\tstatic search1 (frames: NumberArrayLike, time: number) {\n\t\tlet n = frames.length;\n\t\tfor (let i = 1; i < n; i++)\n\t\t\tif (frames[i] > time) return i - 1;\n\t\treturn n - 1;\n\t}\n\n\tstatic search (frames: NumberArrayLike, time: number, step: number) {\n\t\tlet n = frames.length;\n\t\tfor (let i = step; i < n; i += step)\n\t\t\tif (frames[i] > time) return i - step;\n\t\treturn n - step;\n\t}\n}\n\nexport interface BoneTimeline {\n\t/** The index of the bone in {@link Skeleton#bones} that will be changed. */\n\tboneIndex: number;\n}\n\nexport interface SlotTimeline {\n\t/** The index of the slot in {@link Skeleton#slots} that will be changed. */\n\tslotIndex: number;\n}\n\n/** The base class for timelines that use interpolation between key frame values. */\nexport abstract class CurveTimeline extends Timeline {\n\tprotected curves: NumberArrayLike; // type, x, y, ...\n\n\tconstructor (frameCount: number, bezierCount: number, propertyIds: string[]) {\n\t\tsuper(frameCount, propertyIds);\n\t\tthis.curves = Utils.newFloatArray(frameCount + bezierCount * 18/*BEZIER_SIZE*/);\n\t\tthis.curves[frameCount - 1] = 1/*STEPPED*/;\n\t}\n\n\t/** Sets the specified key frame to linear interpolation. */\n\tsetLinear (frame: number) {\n\t\tthis.curves[frame] = 0/*LINEAR*/;\n\t}\n\n\t/** Sets the specified key frame to stepped interpolation. */\n\tsetStepped (frame: number) {\n\t\tthis.curves[frame] = 1/*STEPPED*/;\n\t}\n\n\t/** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger\n\t * than the actual number of Bezier curves. */\n\tshrink (bezierCount: number) {\n\t\tlet size = this.getFrameCount() + bezierCount * 18/*BEZIER_SIZE*/;\n\t\tif (this.curves.length > size) {\n\t\t\tlet newCurves = Utils.newFloatArray(size);\n\t\t\tUtils.arrayCopy(this.curves, 0, newCurves, 0, size);\n\t\t\tthis.curves = newCurves;\n\t\t}\n\t}\n\n\t/** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than\n\t * one curve per frame.\n\t * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified\n\t * in the constructor), inclusive.\n\t * @param frame Between 0 and frameCount - 1, inclusive.\n\t * @param value The index of the value for this frame that this curve is used for.\n\t * @param time1 The time for the first key.\n\t * @param value1 The value for the first key.\n\t * @param cx1 The time for the first Bezier handle.\n\t * @param cy1 The value for the first Bezier handle.\n\t * @param cx2 The time of the second Bezier handle.\n\t * @param cy2 The value for the second Bezier handle.\n\t * @param time2 The time for the second key.\n\t * @param value2 The value for the second key. */\n\tsetBezier (bezier: number, frame: number, value: number, time1: number, value1: number, cx1: number, cy1: number, cx2: number,\n\t\tcy2: number, time2: number, value2: number) {\n\t\tlet curves = this.curves;\n\t\tlet i = this.getFrameCount() + bezier * 18/*BEZIER_SIZE*/;\n\t\tif (value == 0) curves[frame] = 2/*BEZIER*/ + i;\n\t\tlet tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;\n\t\tlet dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006;\n\t\tlet ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;\n\t\tlet dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;\n\t\tlet x = time1 + dx, y = value1 + dy;\n\t\tfor (let n = i + 18/*BEZIER_SIZE*/; i < n; i += 2) {\n\t\t\tcurves[i] = x;\n\t\t\tcurves[i + 1] = y;\n\t\t\tdx += ddx;\n\t\t\tdy += ddy;\n\t\t\tddx += dddx;\n\t\t\tddy += dddy;\n\t\t\tx += dx;\n\t\t\ty += dy;\n\t\t}\n\t}\n\n\t/** Returns the Bezier interpolated value for the specified time.\n\t * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time.\n\t * @param valueOffset The offset from frameIndex to the value this curve is used for.\n\t * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */\n\tgetBezierValue (time: number, frameIndex: number, valueOffset: number, i: number) {\n\t\tlet curves = this.curves;\n\t\tif (curves[i] > time) {\n\t\t\tlet x = this.frames[frameIndex], y = this.frames[frameIndex + valueOffset];\n\t\t\treturn y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);\n\t\t}\n\t\tlet n = i + 18/*BEZIER_SIZE*/;\n\t\tfor (i += 2; i < n; i += 2) {\n\t\t\tif (curves[i] >= time) {\n\t\t\t\tlet x = curves[i - 2], y = curves[i - 1];\n\t\t\t\treturn y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);\n\t\t\t}\n\t\t}\n\t\tframeIndex += this.getFrameEntries();\n\t\tlet x = curves[n - 2], y = curves[n - 1];\n\t\treturn y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y);\n\t}\n}\n\nexport abstract class CurveTimeline1 extends CurveTimeline {\n\tconstructor (frameCount: number, bezierCount: number, propertyId: string) {\n\t\tsuper(frameCount, bezierCount, [propertyId]);\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 2/*ENTRIES*/;\n\t}\n\n\t/** Sets the time and value for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time The frame time in seconds. */\n\tsetFrame (frame: number, time: number, value: number) {\n\t\tframe <<= 1;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*VALUE*/] = value;\n\t}\n\n\t/** Returns the interpolated value for the specified time. */\n\tgetCurveValue (time: number) {\n\t\tlet frames = this.frames;\n\t\tlet i = frames.length - 2;\n\t\tfor (let ii = 2; ii <= i; ii += 2) {\n\t\t\tif (frames[ii] > time) {\n\t\t\t\ti = ii - 2;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tlet curveType = this.curves[i >> 1];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i], value = frames[i + 1/*VALUE*/];\n\t\t\t\treturn value + (time - before) / (frames[i + 2/*ENTRIES*/] - before) * (frames[i + 2/*ENTRIES*/ + 1/*VALUE*/] - value);\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\treturn frames[i + 1/*VALUE*/];\n\t\t}\n\t\treturn this.getBezierValue(time, i, 1/*VALUE*/, curveType - 2/*BEZIER*/);\n\t}\n\n\tgetRelativeValue (time: number, alpha: number, blend: MixBlend, current: number, setup: number) {\n\t\tif (time < this.frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tlet value = this.getCurveValue(time);\n\t\tswitch (blend) {\n\t\t\tcase MixBlend.setup:\n\t\t\t\treturn setup + value * alpha;\n\t\t\tcase MixBlend.first:\n\t\t\tcase MixBlend.replace:\n\t\t\t\tvalue += setup - current;\n\t\t}\n\t\treturn current + value * alpha;\n\t}\n\n\tgetAbsoluteValue (time: number, alpha: number, blend: MixBlend, current: number, setup: number) {\n\t\tif (time < this.frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tlet value = this.getCurveValue(time);\n\t\tif (blend == MixBlend.setup) return setup + (value - setup) * alpha;\n\t\treturn current + (value - current) * alpha;\n\t}\n\n\tgetAbsoluteValue2 (time: number, alpha: number, blend: MixBlend, current: number, setup: number, value: number) {\n\t\tif (time < this.frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tif (blend == MixBlend.setup) return setup + (value - setup) * alpha;\n\t\treturn current + (value - current) * alpha;\n\t}\n\n\tgetScaleValue (time: number, alpha: number, blend: MixBlend, direction: MixDirection, current: number, setup: number) {\n\t\tconst frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tlet value = this.getCurveValue(time) * setup;\n\t\tif (alpha == 1) {\n\t\t\tif (blend == MixBlend.add) return current + value - setup;\n\t\t\treturn value;\n\t\t}\n\t\t// Mixing out uses sign of setup or current pose, else use sign of key.\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\treturn current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha;\n\t\t\t}\n\t\t} else {\n\t\t\tlet s = 0;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\ts = Math.abs(setup) * MathUtils.signum(value);\n\t\t\t\t\treturn s + (value - s) * alpha;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\ts = Math.abs(current) * MathUtils.signum(value);\n\t\t\t\t\treturn s + (value - s) * alpha;\n\t\t\t}\n\t\t}\n\t\treturn current + (value - setup) * alpha;\n\t}\n}\n\n/** The base class for a {@link CurveTimeline} which sets two properties. */\nexport abstract class CurveTimeline2 extends CurveTimeline {\n\t/** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}.\n\t * @param propertyIds Unique identifiers for the properties the timeline modifies. */\n\tconstructor (frameCount: number, bezierCount: number, propertyId1: string, propertyId2: string) {\n\t\tsuper(frameCount, bezierCount, [propertyId1, propertyId2]);\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 3/*ENTRIES*/;\n\t}\n\n\t/** Sets the time and values for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time The frame time in seconds. */\n\tsetFrame (frame: number, time: number, value1: number, value2: number) {\n\t\tframe *= 3/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*VALUE1*/] = value1;\n\t\tthis.frames[frame + 2/*VALUE2*/] = value2;\n\t}\n}\n\n/** Changes a bone's local {@link Bone#rotation}. */\nexport class RotateTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.rotate + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array | null, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.rotation = this.getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#x} and {@link Bone#y}. */\nexport class TranslateTimeline extends CurveTimeline2 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount,\n\t\t\tProperty.x + \"|\" + boneIndex,\n\t\t\tProperty.y + \"|\" + boneIndex,\n\t\t);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.x = bone.data.x;\n\t\t\t\t\tbone.y = bone.data.y;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tbone.x += (bone.data.x - bone.x) * alpha;\n\t\t\t\t\tbone.y += (bone.data.y - bone.y) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet x = 0, y = 0;\n\t\tlet i = Timeline.search(frames, time, 3/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 3/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 3/*ENTRIES*/] - before);\n\t\t\t\tx += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t;\n\t\t\t\ty += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tx = this.getBezierValue(time, i, 1/*VALUE1*/, curveType - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 2/*VALUE2*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\n\t\tswitch (blend) {\n\t\t\tcase MixBlend.setup:\n\t\t\t\tbone.x = bone.data.x + x * alpha;\n\t\t\t\tbone.y = bone.data.y + y * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.first:\n\t\t\tcase MixBlend.replace:\n\t\t\t\tbone.x += (bone.data.x + x - bone.x) * alpha;\n\t\t\t\tbone.y += (bone.data.y + y - bone.y) * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.add:\n\t\t\t\tbone.x += x * alpha;\n\t\t\t\tbone.y += y * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#x}. */\nexport class TranslateXTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.x + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.x = this.getRelativeValue(time, alpha, blend, bone.x, bone.data.x);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#x}. */\nexport class TranslateYTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.y + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.y = this.getRelativeValue(time, alpha, blend, bone.y, bone.data.y);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */\nexport class ScaleTimeline extends CurveTimeline2 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount,\n\t\t\tProperty.scaleX + \"|\" + boneIndex,\n\t\t\tProperty.scaleY + \"|\" + boneIndex\n\t\t);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.scaleX = bone.data.scaleX;\n\t\t\t\t\tbone.scaleY = bone.data.scaleY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tbone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;\n\t\t\t\t\tbone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet x, y;\n\t\tlet i = Timeline.search(frames, time, 3/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 3/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 3/*ENTRIES*/] - before);\n\t\t\t\tx += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t;\n\t\t\t\ty += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tx = this.getBezierValue(time, i, 1/*VALUE1*/, curveType - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 2/*VALUE2*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\t\tx *= bone.data.scaleX;\n\t\ty *= bone.data.scaleY;\n\n\t\tif (alpha == 1) {\n\t\t\tif (blend == MixBlend.add) {\n\t\t\t\tbone.scaleX += x - bone.data.scaleX;\n\t\t\t\tbone.scaleY += y - bone.data.scaleY;\n\t\t\t} else {\n\t\t\t\tbone.scaleX = x;\n\t\t\t\tbone.scaleY = y;\n\t\t\t}\n\t\t} else {\n\t\t\tlet bx = 0, by = 0;\n\t\t\tif (direction == MixDirection.mixOut) {\n\t\t\t\tswitch (blend) {\n\t\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\t\tbx = bone.data.scaleX;\n\t\t\t\t\t\tby = bone.data.scaleY;\n\t\t\t\t\t\tbone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\t\tbx = bone.scaleX;\n\t\t\t\t\t\tby = bone.scaleY;\n\t\t\t\t\t\tbone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.add:\n\t\t\t\t\t\tbone.scaleX += (x - bone.data.scaleX) * alpha;\n\t\t\t\t\t\tbone.scaleY += (y - bone.data.scaleY) * alpha;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch (blend) {\n\t\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\t\tbx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);\n\t\t\t\t\t\tby = Math.abs(bone.data.scaleY) * MathUtils.signum(y);\n\t\t\t\t\t\tbone.scaleX = bx + (x - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (y - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\t\tbx = Math.abs(bone.scaleX) * MathUtils.signum(x);\n\t\t\t\t\t\tby = Math.abs(bone.scaleY) * MathUtils.signum(y);\n\t\t\t\t\t\tbone.scaleX = bx + (x - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (y - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.add:\n\t\t\t\t\t\tbone.scaleX += (x - bone.data.scaleX) * alpha;\n\t\t\t\t\t\tbone.scaleY += (y - bone.data.scaleY) * alpha;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */\nexport class ScaleXTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.scaleX + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.scaleX = this.getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */\nexport class ScaleYTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.scaleY + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.scaleY = this.getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class ShearTimeline extends CurveTimeline2 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount,\n\t\t\tProperty.shearX + \"|\" + boneIndex,\n\t\t\tProperty.shearY + \"|\" + boneIndex\n\t\t);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.shearX = bone.data.shearX;\n\t\t\t\t\tbone.shearY = bone.data.shearY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tbone.shearX += (bone.data.shearX - bone.shearX) * alpha;\n\t\t\t\t\tbone.shearY += (bone.data.shearY - bone.shearY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet x = 0, y = 0;\n\t\tlet i = Timeline.search(frames, time, 3/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 3/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 3/*ENTRIES*/] - before);\n\t\t\t\tx += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t;\n\t\t\t\ty += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tx = this.getBezierValue(time, i, 1/*VALUE1*/, curveType - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 2/*VALUE2*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\n\t\tswitch (blend) {\n\t\t\tcase MixBlend.setup:\n\t\t\t\tbone.shearX = bone.data.shearX + x * alpha;\n\t\t\t\tbone.shearY = bone.data.shearY + y * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.first:\n\t\t\tcase MixBlend.replace:\n\t\t\t\tbone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;\n\t\t\t\tbone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.add:\n\t\t\t\tbone.shearX += x * alpha;\n\t\t\t\tbone.shearY += y * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class ShearXTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.shearX + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.shearX = this.getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class ShearYTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.shearY + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.shearY = this.getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY);\n\t}\n}\n\nexport class InheritTimeline extends Timeline implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, boneIndex: number) {\n\t\tsuper(frameCount, [Property.inherit + \"|\" + boneIndex]);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tpublic getFrameEntries () {\n\t\treturn 2/*ENTRIES*/;\n\t}\n\n\t/** Sets the transform mode for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time The frame time in seconds. */\n\tpublic setFrame (frame: number, time: number, inherit: Inherit) {\n\t\tframe *= 2/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*INHERIT*/] = inherit;\n\t}\n\n\tpublic apply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) bone.inherit = bone.data.inherit;\n\t\t\treturn;\n\t\t}\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) bone.inherit = bone.data.inherit;\n\t\t\treturn;\n\t\t}\n\t\tbone.inherit = this.frames[Timeline.search(frames, time, 2/*ENTRIES*/) + 1/*INHERIT*/];\n\t}\n}\n\n/** Changes a slot's {@link Slot#color}. */\nexport class RGBATimeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex,\n\t\t\tProperty.alpha + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 5/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number, a: number) {\n\t\tframe *= 5/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t\tthis.frames[frame + 4/*A*/] = a;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet color = slot.color;\n\t\tif (time < frames[0]) {\n\t\t\tlet setup = slot.data.color;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tcolor.setFromColor(setup);\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcolor.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,\n\t\t\t\t\t\t(setup.a - color.a) * alpha);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0, a = 0;\n\t\tlet i = Timeline.search(frames, time, 5/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 5/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 5/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 5/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 5/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 5/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\ta += (frames[i + 5/*ENTRIES*/ + 4/*A*/] - a) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\ta = this.getBezierValue(time, i, 4/*A*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t}\n\t\tif (alpha == 1)\n\t\t\tcolor.set(r, g, b, a);\n\t\telse {\n\t\t\tif (blend == MixBlend.setup) color.setFromColor(slot.data.color);\n\t\t\tcolor.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#color}. */\nexport class RGBTimeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 4/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number) {\n\t\tframe <<= 2;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet color = slot.color;\n\t\tif (time < frames[0]) {\n\t\t\tlet setup = slot.data.color;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tcolor.r = setup.r;\n\t\t\t\t\tcolor.g = setup.g;\n\t\t\t\t\tcolor.b = setup.b;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcolor.r += (setup.r - color.r) * alpha;\n\t\t\t\t\tcolor.g += (setup.g - color.g) * alpha;\n\t\t\t\t\tcolor.b += (setup.b - color.b) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0;\n\t\tlet i = Timeline.search(frames, time, 4/*ENTRIES*/);\n\t\tlet curveType = this.curves[i >> 2];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 4/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 4/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 4/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 4/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t}\n\t\tif (alpha == 1) {\n\t\t\tcolor.r = r;\n\t\t\tcolor.g = g;\n\t\t\tcolor.b = b;\n\t\t} else {\n\t\t\tif (blend == MixBlend.setup) {\n\t\t\t\tlet setup = slot.data.color;\n\t\t\t\tcolor.r = setup.r;\n\t\t\t\tcolor.g = setup.g;\n\t\t\t\tcolor.b = setup.b;\n\t\t\t}\n\t\t\tcolor.r += (r - color.r) * alpha;\n\t\t\tcolor.g += (g - color.g) * alpha;\n\t\t\tcolor.b += (b - color.b) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class AlphaTimeline extends CurveTimeline1 implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.alpha + \"|\" + slotIndex);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet color = slot.color;\n\t\tif (time < this.frames[0]) {\n\t\t\tlet setup = slot.data.color;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tcolor.a = setup.a;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcolor.a += (setup.a - color.a) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet a = this.getCurveValue(time);\n\t\tif (alpha == 1)\n\t\t\tcolor.a = a;\n\t\telse {\n\t\t\tif (blend == MixBlend.setup) color.a = slot.data.color.a;\n\t\t\tcolor.a += (a - color.a) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#color} and {@link Slot#darkColor} for two color tinting. */\nexport class RGBA2Timeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex,\n\t\t\tProperty.alpha + \"|\" + slotIndex,\n\t\t\tProperty.rgb2 + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 8/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, light, and dark colors for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number, a: number, r2: number, g2: number, b2: number) {\n\t\tframe <<= 3;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t\tthis.frames[frame + 4/*A*/] = a;\n\t\tthis.frames[frame + 5/*R2*/] = r2;\n\t\tthis.frames[frame + 6/*G2*/] = g2;\n\t\tthis.frames[frame + 7/*B2*/] = b2;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet light = slot.color, dark = slot.darkColor!;\n\t\tif (time < frames[0]) {\n\t\t\tlet setupLight = slot.data.color, setupDark = slot.data.darkColor!;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tlight.setFromColor(setupLight);\n\t\t\t\t\tdark.r = setupDark.r;\n\t\t\t\t\tdark.g = setupDark.g;\n\t\t\t\t\tdark.b = setupDark.b;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tlight.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha,\n\t\t\t\t\t\t(setupLight.a - light.a) * alpha);\n\t\t\t\t\tdark.r += (setupDark.r - dark.r) * alpha;\n\t\t\t\t\tdark.g += (setupDark.g - dark.g) * alpha;\n\t\t\t\t\tdark.b += (setupDark.b - dark.b) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;\n\t\tlet i = Timeline.search(frames, time, 8/*ENTRIES*/);\n\t\tlet curveType = this.curves[i >> 3];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tr2 = frames[i + 5/*R2*/];\n\t\t\t\tg2 = frames[i + 6/*G2*/];\n\t\t\t\tb2 = frames[i + 7/*B2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 8/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 8/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 8/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 8/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\ta += (frames[i + 8/*ENTRIES*/ + 4/*A*/] - a) * t;\n\t\t\t\tr2 += (frames[i + 8/*ENTRIES*/ + 5/*R2*/] - r2) * t;\n\t\t\t\tg2 += (frames[i + 8/*ENTRIES*/ + 6/*G2*/] - g2) * t;\n\t\t\t\tb2 += (frames[i + 8/*ENTRIES*/ + 7/*B2*/] - b2) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tr2 = frames[i + 5/*R2*/];\n\t\t\t\tg2 = frames[i + 6/*G2*/];\n\t\t\t\tb2 = frames[i + 7/*B2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\ta = this.getBezierValue(time, i, 4/*A*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t\t\tr2 = this.getBezierValue(time, i, 5/*R2*/, curveType + 18/*BEZIER_SIZE*/ * 4 - 2/*BEZIER*/);\n\t\t\t\tg2 = this.getBezierValue(time, i, 6/*G2*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/);\n\t\t\t\tb2 = this.getBezierValue(time, i, 7/*B2*/, curveType + 18/*BEZIER_SIZE*/ * 6 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (alpha == 1) {\n\t\t\tlight.set(r, g, b, a);\n\t\t\tdark.r = r2;\n\t\t\tdark.g = g2;\n\t\t\tdark.b = b2;\n\t\t} else {\n\t\t\tif (blend == MixBlend.setup) {\n\t\t\t\tlight.setFromColor(slot.data.color);\n\t\t\t\tlet setupDark = slot.data.darkColor!;\n\t\t\t\tdark.r = setupDark.r;\n\t\t\t\tdark.g = setupDark.g;\n\t\t\t\tdark.b = setupDark.b;\n\t\t\t}\n\t\t\tlight.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);\n\t\t\tdark.r += (r2 - dark.r) * alpha;\n\t\t\tdark.g += (g2 - dark.g) * alpha;\n\t\t\tdark.b += (b2 - dark.b) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#color} and {@link Slot#darkColor} for two color tinting. */\nexport class RGB2Timeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex,\n\t\t\tProperty.rgb2 + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 7/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, light, and dark colors for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number, r2: number, g2: number, b2: number) {\n\t\tframe *= 7/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t\tthis.frames[frame + 4/*R2*/] = r2;\n\t\tthis.frames[frame + 5/*G2*/] = g2;\n\t\tthis.frames[frame + 6/*B2*/] = b2;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet light = slot.color, dark = slot.darkColor!;\n\t\tif (time < frames[0]) {\n\t\t\tlet setupLight = slot.data.color, setupDark = slot.data.darkColor!;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tlight.r = setupLight.r;\n\t\t\t\t\tlight.g = setupLight.g;\n\t\t\t\t\tlight.b = setupLight.b;\n\t\t\t\t\tdark.r = setupDark.r;\n\t\t\t\t\tdark.g = setupDark.g;\n\t\t\t\t\tdark.b = setupDark.b;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tlight.r += (setupLight.r - light.r) * alpha;\n\t\t\t\t\tlight.g += (setupLight.g - light.g) * alpha;\n\t\t\t\t\tlight.b += (setupLight.b - light.b) * alpha;\n\t\t\t\t\tdark.r += (setupDark.r - dark.r) * alpha;\n\t\t\t\t\tdark.g += (setupDark.g - dark.g) * alpha;\n\t\t\t\t\tdark.b += (setupDark.b - dark.b) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;\n\t\tlet i = Timeline.search(frames, time, 7/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 7/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tr2 = frames[i + 4/*R2*/];\n\t\t\t\tg2 = frames[i + 5/*G2*/];\n\t\t\t\tb2 = frames[i + 6/*B2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 7/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 7/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 7/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 7/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\tr2 += (frames[i + 7/*ENTRIES*/ + 4/*R2*/] - r2) * t;\n\t\t\t\tg2 += (frames[i + 7/*ENTRIES*/ + 5/*G2*/] - g2) * t;\n\t\t\t\tb2 += (frames[i + 7/*ENTRIES*/ + 6/*B2*/] - b2) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tr2 = frames[i + 4/*R2*/];\n\t\t\t\tg2 = frames[i + 5/*G2*/];\n\t\t\t\tb2 = frames[i + 6/*B2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\tr2 = this.getBezierValue(time, i, 4/*R2*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t\t\tg2 = this.getBezierValue(time, i, 5/*G2*/, curveType + 18/*BEZIER_SIZE*/ * 4 - 2/*BEZIER*/);\n\t\t\t\tb2 = this.getBezierValue(time, i, 6/*B2*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (alpha == 1) {\n\t\t\tlight.r = r;\n\t\t\tlight.g = g;\n\t\t\tlight.b = b;\n\t\t\tdark.r = r2;\n\t\t\tdark.g = g2;\n\t\t\tdark.b = b2;\n\t\t} else {\n\t\t\tif (blend == MixBlend.setup) {\n\t\t\t\tlet setupLight = slot.data.color, setupDark = slot.data.darkColor!;\n\t\t\t\tlight.r = setupLight.r;\n\t\t\t\tlight.g = setupLight.g;\n\t\t\t\tlight.b = setupLight.b;\n\t\t\t\tdark.r = setupDark.r;\n\t\t\t\tdark.g = setupDark.g;\n\t\t\t\tdark.b = setupDark.b;\n\t\t\t}\n\t\t\tlight.r += (r - light.r) * alpha;\n\t\t\tlight.g += (g - light.g) * alpha;\n\t\t\tlight.b += (b - light.b) * alpha;\n\t\t\tdark.r += (r2 - dark.r) * alpha;\n\t\t\tdark.g += (g2 - dark.g) * alpha;\n\t\t\tdark.b += (b2 - dark.b) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#attachment}. */\nexport class AttachmentTimeline extends Timeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\t/** The attachment name for each key frame. May contain null values to clear the attachment. */\n\tattachmentNames: Array;\n\n\tconstructor (frameCount: number, slotIndex: number) {\n\t\tsuper(frameCount, [\n\t\t\tProperty.attachment + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.attachmentNames = new Array(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the attachment name for the specified key frame. */\n\tsetFrame (frame: number, time: number, attachmentName: string | null) {\n\t\tthis.frames[frame] = time;\n\t\tthis.attachmentNames[frame] = attachmentName;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) this.setAttachment(skeleton, slot, slot.data.attachmentName);\n\t\t\treturn;\n\t\t}\n\n\t\tif (time < this.frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) this.setAttachment(skeleton, slot, slot.data.attachmentName);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]);\n\t}\n\n\tsetAttachment (skeleton: Skeleton, slot: Slot, attachmentName: string | null) {\n\t\tslot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName));\n\t}\n}\n\n/** Changes a slot's {@link Slot#deform} to deform a {@link VertexAttachment}. */\nexport class DeformTimeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\t/** The attachment that will be deformed. */\n\tattachment: VertexAttachment;\n\n\t/** The vertices for each key frame. */\n\tvertices: Array;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number, attachment: VertexAttachment) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.deform + \"|\" + slotIndex + \"|\" + attachment.id\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.attachment = attachment;\n\t\tthis.vertices = new Array(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the vertices for the specified key frame.\n\t * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */\n\tsetFrame (frame: number, time: number, vertices: NumberArrayLike) {\n\t\tthis.frames[frame] = time;\n\t\tthis.vertices[frame] = vertices;\n\t}\n\n\t/** @param value1 Ignored (0 is used for a deform timeline).\n\t * @param value2 Ignored (1 is used for a deform timeline). */\n\tsetBezier (bezier: number, frame: number, value: number, time1: number, value1: number, cx1: number, cy1: number, cx2: number,\n\t\tcy2: number, time2: number, value2: number) {\n\t\tlet curves = this.curves;\n\t\tlet i = this.getFrameCount() + bezier * 18/*BEZIER_SIZE*/;\n\t\tif (value == 0) curves[frame] = 2/*BEZIER*/ + i;\n\t\tlet tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06;\n\t\tlet dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018;\n\t\tlet ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;\n\t\tlet dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667;\n\t\tlet x = time1 + dx, y = dy;\n\t\tfor (let n = i + 18/*BEZIER_SIZE*/; i < n; i += 2) {\n\t\t\tcurves[i] = x;\n\t\t\tcurves[i + 1] = y;\n\t\t\tdx += ddx;\n\t\t\tdy += ddy;\n\t\t\tddx += dddx;\n\t\t\tddy += dddy;\n\t\t\tx += dx;\n\t\t\ty += dy;\n\t\t}\n\t}\n\n\tgetCurvePercent (time: number, frame: number) {\n\t\tlet curves = this.curves;\n\t\tlet i = curves[frame];\n\t\tswitch (i) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet x = this.frames[frame];\n\t\t\t\treturn (time - x) / (this.frames[frame + this.getFrameEntries()] - x);\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\treturn 0;\n\t\t}\n\t\ti -= 2/*BEZIER*/;\n\t\tif (curves[i] > time) {\n\t\t\tlet x = this.frames[frame];\n\t\t\treturn curves[i + 1] * (time - x) / (curves[i] - x);\n\t\t}\n\t\tlet n = i + 18/*BEZIER_SIZE*/;\n\t\tfor (i += 2; i < n; i += 2) {\n\t\t\tif (curves[i] >= time) {\n\t\t\t\tlet x = curves[i - 2], y = curves[i - 1];\n\t\t\t\treturn y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);\n\t\t\t}\n\t\t}\n\t\tlet x = curves[n - 2], y = curves[n - 1];\n\t\treturn y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x);\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot: Slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\t\tlet slotAttachment: Attachment | null = slot.getAttachment();\n\t\tif (!slotAttachment) return;\n\t\tif (!(slotAttachment instanceof VertexAttachment) || (slotAttachment).timelineAttachment != this.attachment) return;\n\n\t\tlet deform: Array = slot.deform;\n\t\tif (deform.length == 0) blend = MixBlend.setup;\n\n\t\tlet vertices = this.vertices;\n\t\tlet vertexCount = vertices[0].length;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tdeform.length = 0;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tif (alpha == 1) {\n\t\t\t\t\t\tdeform.length = 0;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdeform.length = vertexCount;\n\t\t\t\t\tlet vertexAttachment = slotAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (var i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += (setupVertices[i] - deform[i]) * alpha;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets.\n\t\t\t\t\t\talpha = 1 - alpha;\n\t\t\t\t\t\tfor (var i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] *= alpha;\n\t\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tdeform.length = vertexCount;\n\t\tif (time >= frames[frames.length - 1]) {\n\t\t\tlet lastVertices = vertices[frames.length - 1];\n\t\t\tif (alpha == 1) {\n\t\t\t\tif (blend == MixBlend.add) {\n\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += lastVertices[i] - setupVertices[i];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += lastVertices[i];\n\t\t\t\t\t}\n\t\t\t\t} else\n\t\t\t\t\tUtils.arrayCopy(lastVertices, 0, deform, 0, vertexCount);\n\t\t\t} else {\n\t\t\t\tswitch (blend) {\n\t\t\t\t\tcase MixBlend.setup: {\n\t\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\t\tlet setup = setupVertices[i];\n\t\t\t\t\t\t\t\tdeform[i] = setup + (lastVertices[i] - setup) * alpha;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\t\tdeform[i] = lastVertices[i] * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += (lastVertices[i] - deform[i]) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.add:\n\t\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\t\tdeform[i] += (lastVertices[i] - setupVertices[i]) * alpha;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\t\tdeform[i] += lastVertices[i] * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Interpolate between the previous frame and the current frame.\n\t\tlet frame = Timeline.search1(frames, time);\n\t\tlet percent = this.getCurvePercent(time, frame);\n\t\tlet prevVertices = vertices[frame];\n\t\tlet nextVertices = vertices[frame + 1];\n\n\t\tif (alpha == 1) {\n\t\t\tif (blend == MixBlend.add) {\n\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\tdeform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\tdeform[i] += prev + (nextVertices[i] - prev) * percent;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\tdeform[i] = prev + (nextVertices[i] - prev) * percent;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup: {\n\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i], setup = setupVertices[i];\n\t\t\t\t\t\t\tdeform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\t\tdeform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase MixBlend.first:\n\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\tdeform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MixBlend.add:\n\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\t\tdeform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\t\tdeform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Fires an {@link Event} when specific animation times are reached. */\nexport class EventTimeline extends Timeline {\n\tstatic propertyIds = [\"\" + Property.event];\n\n\t/** The event for each key frame. */\n\tevents: Array;\n\n\tconstructor (frameCount: number) {\n\t\tsuper(frameCount, EventTimeline.propertyIds);\n\n\t\tthis.events = new Array(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the event for the specified key frame. */\n\tsetFrame (frame: number, event: Event) {\n\t\tthis.frames[frame] = event.time;\n\t\tthis.events[frame] = event;\n\t}\n\n\t/** Fires events for frames > `lastTime` and <= `time`. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (!firedEvents) return;\n\n\t\tlet frames = this.frames;\n\t\tlet frameCount = this.frames.length;\n\n\t\tif (lastTime > time) { // Apply after lastTime for looped animations.\n\t\t\tthis.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction);\n\t\t\tlastTime = -1;\n\t\t} else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame.\n\t\t\treturn;\n\t\tif (time < frames[0]) return;\n\n\t\tlet i = 0;\n\t\tif (lastTime < frames[0])\n\t\t\ti = 0;\n\t\telse {\n\t\t\ti = Timeline.search1(frames, lastTime) + 1;\n\t\t\tlet frameTime = frames[i];\n\t\t\twhile (i > 0) { // Fire multiple events with the same frame.\n\t\t\t\tif (frames[i - 1] != frameTime) break;\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t\tfor (; i < frameCount && time >= frames[i]; i++)\n\t\t\tfiredEvents.push(this.events[i]);\n\t}\n}\n\n/** Changes a skeleton's {@link Skeleton#drawOrder}. */\nexport class DrawOrderTimeline extends Timeline {\n\tstatic propertyIds = [\"\" + Property.drawOrder];\n\n\t/** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */\n\tdrawOrders: Array | null>;\n\n\tconstructor (frameCount: number) {\n\t\tsuper(frameCount, DrawOrderTimeline.propertyIds);\n\t\tthis.drawOrders = new Array | null>(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the draw order for the specified key frame.\n\t * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose\n\t * draw order. */\n\tsetFrame (frame: number, time: number, drawOrder: Array | null) {\n\t\tthis.frames[frame] = time;\n\t\tthis.drawOrders[frame] = drawOrder;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);\n\t\t\treturn;\n\t\t}\n\n\t\tif (time < this.frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);\n\t\t\treturn;\n\t\t}\n\n\t\tlet idx = Timeline.search1(this.frames, time);\n\t\tlet drawOrderToSetupIndex = this.drawOrders[idx];\n\t\tif (!drawOrderToSetupIndex)\n\t\t\tUtils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);\n\t\telse {\n\t\t\tlet drawOrder: Array = skeleton.drawOrder;\n\t\t\tlet slots: Array = skeleton.slots;\n\t\t\tfor (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++)\n\t\t\t\tdrawOrder[i] = slots[drawOrderToSetupIndex[i]];\n\t\t}\n\t}\n}\n\n/** Changes an IK constraint's {@link IkConstraint#mix}, {@link IkConstraint#softness},\n * {@link IkConstraint#bendDirection}, {@link IkConstraint#stretch}, and {@link IkConstraint#compress}. */\nexport class IkConstraintTimeline extends CurveTimeline {\n\t/** The index of the IK constraint in {@link Skeleton#getIkConstraints()} that will be changed when this timeline is applied */\n\tconstraintIndex: number = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, ikConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.ikConstraint + \"|\" + ikConstraintIndex\n\t\t]);\n\t\tthis.constraintIndex = ikConstraintIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 6/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */\n\tsetFrame (frame: number, time: number, mix: number, softness: number, bendDirection: number, compress: boolean, stretch: boolean) {\n\t\tframe *= 6/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*MIX*/] = mix;\n\t\tthis.frames[frame + 2/*SOFTNESS*/] = softness;\n\t\tthis.frames[frame + 3/*BEND_DIRECTION*/] = bendDirection;\n\t\tthis.frames[frame + 4/*COMPRESS*/] = compress ? 1 : 0;\n\t\tthis.frames[frame + 5/*STRETCH*/] = stretch ? 1 : 0;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: IkConstraint = skeleton.ikConstraints[this.constraintIndex];\n\t\tif (!constraint.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tconstraint.mix = constraint.data.mix;\n\t\t\t\t\tconstraint.softness = constraint.data.softness;\n\t\t\t\t\tconstraint.bendDirection = constraint.data.bendDirection;\n\t\t\t\t\tconstraint.compress = constraint.data.compress;\n\t\t\t\t\tconstraint.stretch = constraint.data.stretch;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tconstraint.mix += (constraint.data.mix - constraint.mix) * alpha;\n\t\t\t\t\tconstraint.softness += (constraint.data.softness - constraint.softness) * alpha;\n\t\t\t\t\tconstraint.bendDirection = constraint.data.bendDirection;\n\t\t\t\t\tconstraint.compress = constraint.data.compress;\n\t\t\t\t\tconstraint.stretch = constraint.data.stretch;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet mix = 0, softness = 0;\n\t\tlet i = Timeline.search(frames, time, 6/*ENTRIES*/)\n\t\tlet curveType = this.curves[i / 6/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tmix = frames[i + 1/*MIX*/];\n\t\t\t\tsoftness = frames[i + 2/*SOFTNESS*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 6/*ENTRIES*/] - before);\n\t\t\t\tmix += (frames[i + 6/*ENTRIES*/ + 1/*MIX*/] - mix) * t;\n\t\t\t\tsoftness += (frames[i + 6/*ENTRIES*/ + 2/*SOFTNESS*/] - softness) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tmix = frames[i + 1/*MIX*/];\n\t\t\t\tsoftness = frames[i + 2/*SOFTNESS*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tmix = this.getBezierValue(time, i, 1/*MIX*/, curveType - 2/*BEZIER*/);\n\t\t\t\tsoftness = this.getBezierValue(time, i, 2/*SOFTNESS*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (blend == MixBlend.setup) {\n\t\t\tconstraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha;\n\t\t\tconstraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha;\n\n\t\t\tif (direction == MixDirection.mixOut) {\n\t\t\t\tconstraint.bendDirection = constraint.data.bendDirection;\n\t\t\t\tconstraint.compress = constraint.data.compress;\n\t\t\t\tconstraint.stretch = constraint.data.stretch;\n\t\t\t} else {\n\t\t\t\tconstraint.bendDirection = frames[i + 3/*BEND_DIRECTION*/];\n\t\t\t\tconstraint.compress = frames[i + 4/*COMPRESS*/] != 0;\n\t\t\t\tconstraint.stretch = frames[i + 5/*STRETCH*/] != 0;\n\t\t\t}\n\t\t} else {\n\t\t\tconstraint.mix += (mix - constraint.mix) * alpha;\n\t\t\tconstraint.softness += (softness - constraint.softness) * alpha;\n\t\t\tif (direction == MixDirection.mixIn) {\n\t\t\t\tconstraint.bendDirection = frames[i + 3/*BEND_DIRECTION*/];\n\t\t\t\tconstraint.compress = frames[i + 4/*COMPRESS*/] != 0;\n\t\t\t\tconstraint.stretch = frames[i + 5/*STRETCH*/] != 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Changes a transform constraint's {@link TransformConstraint#rotateMix}, {@link TransformConstraint#translateMix},\n * {@link TransformConstraint#scaleMix}, and {@link TransformConstraint#shearMix}. */\nexport class TransformConstraintTimeline extends CurveTimeline {\n\t/** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */\n\tconstraintIndex: number = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, transformConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.transformConstraint + \"|\" + transformConstraintIndex\n\t\t]);\n\t\tthis.constraintIndex = transformConstraintIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 7/*ENTRIES*/;\n\t}\n\n\t/** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */\n\tsetFrame (frame: number, time: number, mixRotate: number, mixX: number, mixY: number, mixScaleX: number, mixScaleY: number,\n\t\tmixShearY: number) {\n\t\tlet frames = this.frames;\n\t\tframe *= 7/*ENTRIES*/;\n\t\tframes[frame] = time;\n\t\tframes[frame + 1/*ROTATE*/] = mixRotate;\n\t\tframes[frame + 2/*X*/] = mixX;\n\t\tframes[frame + 3/*Y*/] = mixY;\n\t\tframes[frame + 4/*SCALEX*/] = mixScaleX;\n\t\tframes[frame + 5/*SCALEY*/] = mixScaleY;\n\t\tframes[frame + 6/*SHEARY*/] = mixShearY;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: TransformConstraint = skeleton.transformConstraints[this.constraintIndex];\n\t\tif (!constraint.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tlet data = constraint.data;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tconstraint.mixRotate = data.mixRotate;\n\t\t\t\t\tconstraint.mixX = data.mixX;\n\t\t\t\t\tconstraint.mixY = data.mixY;\n\t\t\t\t\tconstraint.mixScaleX = data.mixScaleX;\n\t\t\t\t\tconstraint.mixScaleY = data.mixScaleY;\n\t\t\t\t\tconstraint.mixShearY = data.mixShearY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tconstraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;\n\t\t\t\t\tconstraint.mixX += (data.mixX - constraint.mixX) * alpha;\n\t\t\t\t\tconstraint.mixY += (data.mixY - constraint.mixY) * alpha;\n\t\t\t\t\tconstraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha;\n\t\t\t\t\tconstraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha;\n\t\t\t\t\tconstraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet rotate, x, y, scaleX, scaleY, shearY;\n\t\tlet i = Timeline.search(frames, time, 7/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 7/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tscaleX = frames[i + 4/*SCALEX*/];\n\t\t\t\tscaleY = frames[i + 5/*SCALEY*/];\n\t\t\t\tshearY = frames[i + 6/*SHEARY*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 7/*ENTRIES*/] - before);\n\t\t\t\trotate += (frames[i + 7/*ENTRIES*/ + 1/*ROTATE*/] - rotate) * t;\n\t\t\t\tx += (frames[i + 7/*ENTRIES*/ + 2/*X*/] - x) * t;\n\t\t\t\ty += (frames[i + 7/*ENTRIES*/ + 3/*Y*/] - y) * t;\n\t\t\t\tscaleX += (frames[i + 7/*ENTRIES*/ + 4/*SCALEX*/] - scaleX) * t;\n\t\t\t\tscaleY += (frames[i + 7/*ENTRIES*/ + 5/*SCALEY*/] - scaleY) * t;\n\t\t\t\tshearY += (frames[i + 7/*ENTRIES*/ + 6/*SHEARY*/] - shearY) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tscaleX = frames[i + 4/*SCALEX*/];\n\t\t\t\tscaleY = frames[i + 5/*SCALEY*/];\n\t\t\t\tshearY = frames[i + 6/*SHEARY*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\trotate = this.getBezierValue(time, i, 1/*ROTATE*/, curveType - 2/*BEZIER*/);\n\t\t\t\tx = this.getBezierValue(time, i, 2/*X*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 3/*Y*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\tscaleX = this.getBezierValue(time, i, 4/*SCALEX*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t\t\tscaleY = this.getBezierValue(time, i, 5/*SCALEY*/, curveType + 18/*BEZIER_SIZE*/ * 4 - 2/*BEZIER*/);\n\t\t\t\tshearY = this.getBezierValue(time, i, 6/*SHEARY*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (blend == MixBlend.setup) {\n\t\t\tlet data = constraint.data;\n\t\t\tconstraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;\n\t\t\tconstraint.mixX = data.mixX + (x - data.mixX) * alpha;\n\t\t\tconstraint.mixY = data.mixY + (y - data.mixY) * alpha;\n\t\t\tconstraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha;\n\t\t\tconstraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha;\n\t\t\tconstraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha;\n\t\t} else {\n\t\t\tconstraint.mixRotate += (rotate - constraint.mixRotate) * alpha;\n\t\t\tconstraint.mixX += (x - constraint.mixX) * alpha;\n\t\t\tconstraint.mixY += (y - constraint.mixY) * alpha;\n\t\t\tconstraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha;\n\t\t\tconstraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha;\n\t\t\tconstraint.mixShearY += (shearY - constraint.mixShearY) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a path constraint's {@link PathConstraint#position}. */\nexport class PathConstraintPositionTimeline extends CurveTimeline1 {\n\t/** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is\n\t * applied. */\n\tconstraintIndex: number = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.pathConstraintPosition + \"|\" + pathConstraintIndex);\n\t\tthis.constraintIndex = pathConstraintIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PathConstraint = skeleton.pathConstraints[this.constraintIndex];\n\t\tif (constraint.active)\n\t\t\tconstraint.position = this.getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position);\n\t}\n}\n\n/** Changes a path constraint's {@link PathConstraint#spacing}. */\nexport class PathConstraintSpacingTimeline extends CurveTimeline1 {\n\t/** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is\n\t * applied. */\n\tconstraintIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.pathConstraintSpacing + \"|\" + pathConstraintIndex);\n\t\tthis.constraintIndex = pathConstraintIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PathConstraint = skeleton.pathConstraints[this.constraintIndex];\n\t\tif (constraint.active)\n\t\t\tconstraint.spacing = this.getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing);\n\t}\n}\n\n/** Changes a transform constraint's {@link PathConstraint#getMixRotate()}, {@link PathConstraint#getMixX()}, and\n * {@link PathConstraint#getMixY()}. */\nexport class PathConstraintMixTimeline extends CurveTimeline {\n\t/** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is\n\t * applied. */\n\tconstraintIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.pathConstraintMix + \"|\" + pathConstraintIndex\n\t\t]);\n\t\tthis.constraintIndex = pathConstraintIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 4/*ENTRIES*/;\n\t}\n\n\tsetFrame (frame: number, time: number, mixRotate: number, mixX: number, mixY: number) {\n\t\tlet frames = this.frames;\n\t\tframe <<= 2;\n\t\tframes[frame] = time;\n\t\tframes[frame + 1/*ROTATE*/] = mixRotate;\n\t\tframes[frame + 2/*X*/] = mixX;\n\t\tframes[frame + 3/*Y*/] = mixY;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PathConstraint = skeleton.pathConstraints[this.constraintIndex];\n\t\tif (!constraint.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tconstraint.mixRotate = constraint.data.mixRotate;\n\t\t\t\t\tconstraint.mixX = constraint.data.mixX;\n\t\t\t\t\tconstraint.mixY = constraint.data.mixY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tconstraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha;\n\t\t\t\t\tconstraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha;\n\t\t\t\t\tconstraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet rotate, x, y;\n\t\tlet i = Timeline.search(frames, time, 4/*ENTRIES*/);\n\t\tlet curveType = this.curves[i >> 2];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 4/*ENTRIES*/] - before);\n\t\t\t\trotate += (frames[i + 4/*ENTRIES*/ + 1/*ROTATE*/] - rotate) * t;\n\t\t\t\tx += (frames[i + 4/*ENTRIES*/ + 2/*X*/] - x) * t;\n\t\t\t\ty += (frames[i + 4/*ENTRIES*/ + 3/*Y*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\trotate = this.getBezierValue(time, i, 1/*ROTATE*/, curveType - 2/*BEZIER*/);\n\t\t\t\tx = this.getBezierValue(time, i, 2/*X*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 3/*Y*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (blend == MixBlend.setup) {\n\t\t\tlet data = constraint.data;\n\t\t\tconstraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;\n\t\t\tconstraint.mixX = data.mixX + (x - data.mixX) * alpha;\n\t\t\tconstraint.mixY = data.mixY + (y - data.mixY) * alpha;\n\t\t} else {\n\t\t\tconstraint.mixRotate += (rotate - constraint.mixRotate) * alpha;\n\t\t\tconstraint.mixX += (x - constraint.mixX) * alpha;\n\t\t\tconstraint.mixY += (y - constraint.mixY) * alpha;\n\t\t}\n\t}\n}\n\n/** The base class for most {@link PhysicsConstraint} timelines. */\nexport abstract class PhysicsConstraintTimeline extends CurveTimeline1 {\n\t/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline\n\t * is applied, or -1 if all physics constraints in the skeleton will be changed. */\n\tconstraintIndex = 0;\n\n\t/** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) {\n\t\tsuper(frameCount, bezierCount, property + \"|\" + physicsConstraintIndex);\n\t\tthis.constraintIndex = physicsConstraintIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PhysicsConstraint;\n\t\tif (this.constraintIndex == -1) {\n\t\t\tconst value = time >= this.frames[0] ? this.getCurveValue(time) : 0;\n\n\t\t\tfor (const constraint of skeleton.physicsConstraints) {\n\t\t\t\tif (constraint.active && this.global(constraint.data))\n\t\t\t\t\tthis.set(constraint, this.getAbsoluteValue2(time, alpha, blend, this.get(constraint), this.setup(constraint), value));\n\t\t\t}\n\t\t} else {\n\t\t\tconstraint = skeleton.physicsConstraints[this.constraintIndex];\n\t\t\tif (constraint.active) this.set(constraint, this.getAbsoluteValue(time, alpha, blend, this.get(constraint), this.setup(constraint)));\n\t\t}\n\t}\n\n\tabstract setup (constraint: PhysicsConstraint): number;\n\n\tabstract get (constraint: PhysicsConstraint): number;\n\n\tabstract set (constraint: PhysicsConstraint, value: number): void;\n\n\tabstract global (constraint: PhysicsConstraintData): boolean;\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */\nexport class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.inertia;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.inertia;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.inertia = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.inertiaGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */\nexport class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.strength;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.strength;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.strength = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.strengthGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */\nexport class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.damping;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.damping;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.damping = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.dampingGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */\nexport class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn 1 / constraint.data.massInverse;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn 1 / constraint.massInverse;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.massInverse = 1 / value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.massGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */\nexport class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.wind;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.wind;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.wind = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.windGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getGravity()}. */\nexport class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.gravity;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.gravity;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.gravity = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.gravityGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getMix()}. */\nexport class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.mix;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.mix;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.mix = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.mixGlobal;\n\t}\n}\n\n/** Resets a physics constraint when specific animation times are reached. */\nexport class PhysicsConstraintResetTimeline extends Timeline {\n\tprivate static propertyIds: string[] = [Property.physicsConstraintReset.toString()];\n\n\t/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is\n\t* applied, or -1 if all physics constraints in the skeleton will be reset. */\n\tconstraintIndex: number;\n\n\t/** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */\n\tconstructor (frameCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, PhysicsConstraintResetTimeline.propertyIds);\n\t\tthis.constraintIndex = physicsConstraintIndex;\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive. */\n\tsetFrame (frame: number, time: number) {\n\t\tthis.frames[frame] = time;\n\t}\n\n\t/** Resets the physics constraint when frames > lastTime and <= time. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\n\t\tlet constraint: PhysicsConstraint | undefined;\n\t\tif (this.constraintIndex != -1) {\n\t\t\tconstraint = skeleton.physicsConstraints[this.constraintIndex];\n\t\t\tif (!constraint.active) return;\n\t\t}\n\n\t\tconst frames = this.frames;\n\n\t\tif (lastTime > time) { // Apply after lastTime for looped animations.\n\t\t\tthis.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction);\n\t\t\tlastTime = -1;\n\t\t} else if (lastTime >= frames[frames.length - 1]) // Last time is after last frame.\n\t\t\treturn;\n\t\tif (time < frames[0]) return;\n\n\t\tif (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) {\n\t\t\tif (constraint != null)\n\t\t\t\tconstraint.reset();\n\t\t\telse {\n\t\t\t\tfor (const constraint of skeleton.physicsConstraints) {\n\t\t\t\t\tif (constraint.active) constraint.reset();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#getSequenceIndex()} for an attachment's {@link Sequence}. */\nexport class SequenceTimeline extends Timeline implements SlotTimeline {\n\tstatic ENTRIES = 3;\n\tstatic MODE = 1;\n\tstatic DELAY = 2;\n\n\tslotIndex: number;\n\tattachment: HasTextureRegion;\n\n\tconstructor (frameCount: number, slotIndex: number, attachment: HasTextureRegion) {\n\t\tsuper(frameCount, [\n\t\t\tProperty.sequence + \"|\" + slotIndex + \"|\" + attachment.sequence!.id\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.attachment = attachment;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn SequenceTimeline.ENTRIES;\n\t}\n\n\tgetSlotIndex () {\n\t\treturn this.slotIndex;\n\t}\n\n\tgetAttachment () {\n\t\treturn this.attachment as unknown as Attachment;\n\t}\n\n\t/** Sets the time, mode, index, and frame time for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time Seconds between frames. */\n\tsetFrame (frame: number, time: number, mode: SequenceMode, index: number, delay: number) {\n\t\tlet frames = this.frames;\n\t\tframe *= SequenceTimeline.ENTRIES;\n\t\tframes[frame] = time;\n\t\tframes[frame + SequenceTimeline.MODE] = mode | (index << 4);\n\t\tframes[frame + SequenceTimeline.DELAY] = delay;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\t\tlet slotAttachment = slot.attachment;\n\t\tlet attachment = this.attachment as unknown as Attachment;\n\t\tif (slotAttachment != attachment) {\n\t\t\tif (!(slotAttachment instanceof VertexAttachment)\n\t\t\t\t|| (slotAttachment as VertexAttachment).timelineAttachment != attachment) return;\n\t\t}\n\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) slot.sequenceIndex = -1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) slot.sequenceIndex = -1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet i = Timeline.search(frames, time, SequenceTimeline.ENTRIES);\n\t\tlet before = frames[i];\n\t\tlet modeAndIndex = frames[i + SequenceTimeline.MODE];\n\t\tlet delay = frames[i + SequenceTimeline.DELAY];\n\n\t\tif (!this.attachment.sequence) return;\n\t\tlet index = modeAndIndex >> 4, count = this.attachment.sequence!.regions.length;\n\t\tlet mode = SequenceModeValues[modeAndIndex & 0xf];\n\t\tif (mode != SequenceMode.hold) {\n\t\t\tindex += (((time - before) / delay + 0.00001) | 0);\n\t\t\tswitch (mode) {\n\t\t\t\tcase SequenceMode.once:\n\t\t\t\t\tindex = Math.min(count - 1, index);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.loop:\n\t\t\t\t\tindex %= count;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.pingpong: {\n\t\t\t\t\tlet n = (count << 1) - 2;\n\t\t\t\t\tindex = n == 0 ? 0 : index % n;\n\t\t\t\t\tif (index >= count) index = n - index;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SequenceMode.onceReverse:\n\t\t\t\t\tindex = Math.max(count - 1 - index, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.loopReverse:\n\t\t\t\t\tindex = count - 1 - (index % count);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.pingpongReverse: {\n\t\t\t\t\tlet n = (count << 1) - 2;\n\t\t\t\t\tindex = n == 0 ? 0 : (index + count - 1) % n;\n\t\t\t\t\tif (index >= count) index = n - index;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tslot.sequenceIndex = index;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation, MixBlend, AttachmentTimeline, MixDirection, RotateTimeline, DrawOrderTimeline, Timeline, EventTimeline } from \"./Animation.js\";\nimport { AnimationStateData } from \"./AnimationStateData.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { StringSet, Pool, Utils, MathUtils } from \"./Utils.js\";\nimport { Event } from \"./Event.js\";\n\n\n/** Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies\n * multiple animations on top of each other (layering).\n *\n * See [Applying Animations](http://esotericsoftware.com/spine-applying-animations/) in the Spine Runtimes Guide. */\nexport class AnimationState {\n\tstatic _emptyAnimation = new Animation(\"\", [], 0);\n\tprivate static emptyAnimation (): Animation {\n\t\treturn AnimationState._emptyAnimation;\n\t}\n\n\t/** The AnimationStateData to look up mix durations. */\n\tdata: AnimationStateData;\n\n\t/** The list of tracks that currently have animations, which may contain null entries. */\n\ttracks = new Array();\n\n\t/** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower\n\t * or faster. Defaults to 1.\n\t *\n\t * See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */\n\ttimeScale = 1;\n\tunkeyedState = 0;\n\n\tevents = new Array();\n\tlisteners = new Array();\n\tqueue = new EventQueue(this);\n\tpropertyIDs = new StringSet();\n\tanimationsChanged = false;\n\n\ttrackEntryPool = new Pool(() => new TrackEntry());\n\n\tconstructor (data: AnimationStateData) {\n\t\tthis.data = data;\n\t}\n\n\t/** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */\n\tupdate (delta: number) {\n\t\tdelta *= this.timeScale;\n\t\tlet tracks = this.tracks;\n\t\tfor (let i = 0, n = tracks.length; i < n; i++) {\n\t\t\tlet current = tracks[i];\n\t\t\tif (!current) continue;\n\n\t\t\tcurrent.animationLast = current.nextAnimationLast;\n\t\t\tcurrent.trackLast = current.nextTrackLast;\n\n\t\t\tlet currentDelta = delta * current.timeScale;\n\n\t\t\tif (current.delay > 0) {\n\t\t\t\tcurrent.delay -= currentDelta;\n\t\t\t\tif (current.delay > 0) continue;\n\t\t\t\tcurrentDelta = -current.delay;\n\t\t\t\tcurrent.delay = 0;\n\t\t\t}\n\n\t\t\tlet next = current.next;\n\t\t\tif (next) {\n\t\t\t\t// When the next entry's delay is passed, change to the next entry, preserving leftover time.\n\t\t\t\tlet nextTime = current.trackLast - next.delay;\n\t\t\t\tif (nextTime >= 0) {\n\t\t\t\t\tnext.delay = 0;\n\t\t\t\t\tnext.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale;\n\t\t\t\t\tcurrent.trackTime += currentDelta;\n\t\t\t\t\tthis.setCurrent(i, next, true);\n\t\t\t\t\twhile (next.mixingFrom) {\n\t\t\t\t\t\tnext.mixTime += delta;\n\t\t\t\t\t\tnext = next.mixingFrom;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (current.trackLast >= current.trackEnd && !current.mixingFrom) {\n\t\t\t\ttracks[i] = null;\n\t\t\t\tthis.queue.end(current);\n\t\t\t\tthis.clearNext(current);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (current.mixingFrom && this.updateMixingFrom(current, delta)) {\n\t\t\t\t// End mixing from entries once all have completed.\n\t\t\t\tlet from: TrackEntry | null = current.mixingFrom;\n\t\t\t\tcurrent.mixingFrom = null;\n\t\t\t\tif (from) from.mixingTo = null;\n\t\t\t\twhile (from) {\n\t\t\t\t\tthis.queue.end(from);\n\t\t\t\t\tfrom = from.mixingFrom;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrent.trackTime += currentDelta;\n\t\t}\n\n\t\tthis.queue.drain();\n\t}\n\n\t/** Returns true when all mixing from entries are complete. */\n\tupdateMixingFrom (to: TrackEntry, delta: number): boolean {\n\t\tlet from = to.mixingFrom;\n\t\tif (!from) return true;\n\n\t\tlet finished = this.updateMixingFrom(from, delta);\n\n\t\tfrom.animationLast = from.nextAnimationLast;\n\t\tfrom.trackLast = from.nextTrackLast;\n\n\t\t// The from entry was applied at least once and the mix is complete.\n\t\tif (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) {\n\t\t\t// Mixing is complete for all entries before the from entry or the mix is instantaneous.\n\t\t\tif (from.totalAlpha == 0 || to.mixDuration == 0) {\n\t\t\t\tto.mixingFrom = from.mixingFrom;\n\t\t\t\tif (from.mixingFrom != null) from.mixingFrom.mixingTo = to;\n\t\t\t\tto.interruptAlpha = from.interruptAlpha;\n\t\t\t\tthis.queue.end(from);\n\t\t\t}\n\t\t\treturn finished;\n\t\t}\n\n\t\tfrom.trackTime += delta * from.timeScale;\n\t\tto.mixTime += delta;\n\t\treturn false;\n\t}\n\n\t/** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the\n\t * animation state can be applied to multiple skeletons to pose them identically.\n\t * @returns True if any animations were applied. */\n\tapply (skeleton: Skeleton): boolean {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tif (this.animationsChanged) this._animationsChanged();\n\n\t\tlet events = this.events;\n\t\tlet tracks = this.tracks;\n\t\tlet applied = false;\n\n\t\tfor (let i = 0, n = tracks.length; i < n; i++) {\n\t\t\tlet current = tracks[i];\n\t\t\tif (!current || current.delay > 0) continue;\n\t\t\tapplied = true;\n\t\t\tlet blend: MixBlend = i == 0 ? MixBlend.first : current.mixBlend;\n\n\t\t\t// Apply mixing from entries first.\n\t\t\tlet alpha = current.alpha;\n\t\t\tif (current.mixingFrom)\n\t\t\t\talpha *= this.applyMixingFrom(current, skeleton, blend);\n\t\t\telse if (current.trackTime >= current.trackEnd && !current.next)\n\t\t\t\talpha = 0;\n\t\t\tlet attachments = alpha >= current.alphaAttachmentThreshold;\n\n\n\t\t\t// Apply current entry.\n\t\t\tlet animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime;\n\t\t\tlet applyEvents: Event[] | null = events;\n\t\t\tif (current.reverse) {\n\t\t\t\tapplyTime = current.animation!.duration - applyTime;\n\t\t\t\tapplyEvents = null;\n\t\t\t}\n\t\t\tlet timelines = current.animation!.timelines;\n\t\t\tlet timelineCount = timelines.length;\n\t\t\tif ((i == 0 && alpha == 1) || blend == MixBlend.add) {\n\t\t\t\tif (i == 0) attachments = true;\n\t\t\t\tfor (let ii = 0; ii < timelineCount; ii++) {\n\t\t\t\t\t// Fixes issue #302 on IOS9 where mix, blend sometimes became undefined and caused assets\n\t\t\t\t\t// to sometimes stop rendering when using color correction, as their RGBA values become NaN.\n\t\t\t\t\t// (https://github.com/pixijs/pixi-spine/issues/302)\n\t\t\t\t\tUtils.webkit602BugfixHelper(alpha, blend);\n\t\t\t\t\tvar timeline = timelines[ii];\n\t\t\t\t\tif (timeline instanceof AttachmentTimeline)\n\t\t\t\t\t\tthis.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments);\n\t\t\t\t\telse\n\t\t\t\t\t\ttimeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.mixIn);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlet timelineMode = current.timelineMode;\n\n\t\t\t\tlet shortestRotation = current.shortestRotation;\n\t\t\t\tlet firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1;\n\t\t\t\tif (firstFrame) current.timelinesRotation.length = timelineCount << 1;\n\n\t\t\t\tfor (let ii = 0; ii < timelineCount; ii++) {\n\t\t\t\t\tlet timeline = timelines[ii];\n\t\t\t\t\tlet timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;\n\t\t\t\t\tif (!shortestRotation && timeline instanceof RotateTimeline) {\n\t\t\t\t\t\tthis.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1, firstFrame);\n\t\t\t\t\t} else if (timeline instanceof AttachmentTimeline) {\n\t\t\t\t\t\tthis.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This fixes the WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\t\t\t\t\t\tUtils.webkit602BugfixHelper(alpha, blend);\n\t\t\t\t\t\ttimeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, MixDirection.mixIn);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.queueEvents(current, animationTime);\n\t\t\tevents.length = 0;\n\t\t\tcurrent.nextAnimationLast = animationTime;\n\t\t\tcurrent.nextTrackLast = current.trackTime;\n\t\t}\n\n\t\t// Set slots attachments to the setup pose, if needed. This occurs if an animation that is mixing out sets attachments so\n\t\t// subsequent timelines see any deform, but the subsequent timelines don't set an attachment (eg they are also mixing out or\n\t\t// the time is before the first key).\n\t\tvar setupState = this.unkeyedState + SETUP;\n\t\tvar slots = skeleton.slots;\n\t\tfor (var i = 0, n = skeleton.slots.length; i < n; i++) {\n\t\t\tvar slot = slots[i];\n\t\t\tif (slot.attachmentState == setupState) {\n\t\t\t\tvar attachmentName = slot.data.attachmentName;\n\t\t\t\tslot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));\n\t\t\t}\n\t\t}\n\t\tthis.unkeyedState += 2; // Increasing after each use avoids the need to reset attachmentState for every slot.\n\n\t\tthis.queue.drain();\n\t\treturn applied;\n\t}\n\n\tapplyMixingFrom (to: TrackEntry, skeleton: Skeleton, blend: MixBlend) {\n\t\tlet from = to.mixingFrom!;\n\t\tif (from.mixingFrom) this.applyMixingFrom(from, skeleton, blend);\n\n\t\tlet mix = 0;\n\t\tif (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes.\n\t\t\tmix = 1;\n\t\t\tif (blend == MixBlend.first) blend = MixBlend.setup;\n\t\t} else {\n\t\t\tmix = to.mixTime / to.mixDuration;\n\t\t\tif (mix > 1) mix = 1;\n\t\t\tif (blend != MixBlend.first) blend = from.mixBlend;\n\t\t}\n\n\t\tlet attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold;\n\t\tlet timelines = from.animation!.timelines;\n\t\tlet timelineCount = timelines.length;\n\t\tlet alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix);\n\t\tlet animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime;\n\t\tlet events = null;\n\t\tif (from.reverse)\n\t\t\tapplyTime = from.animation!.duration - applyTime;\n\t\telse if (mix < from.eventThreshold)\n\t\t\tevents = this.events;\n\n\t\tif (blend == MixBlend.add) {\n\t\t\tfor (let i = 0; i < timelineCount; i++)\n\t\t\t\ttimelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.mixOut);\n\t\t} else {\n\t\t\tlet timelineMode = from.timelineMode;\n\t\t\tlet timelineHoldMix = from.timelineHoldMix;\n\n\t\t\tlet shortestRotation = from.shortestRotation;\n\t\t\tlet firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1;\n\t\t\tif (firstFrame) from.timelinesRotation.length = timelineCount << 1;\n\n\t\t\tfrom.totalAlpha = 0;\n\t\t\tfor (let i = 0; i < timelineCount; i++) {\n\t\t\t\tlet timeline = timelines[i];\n\t\t\t\tlet direction = MixDirection.mixOut;\n\t\t\t\tlet timelineBlend: MixBlend;\n\t\t\t\tlet alpha = 0;\n\t\t\t\tswitch (timelineMode[i]) {\n\t\t\t\t\tcase SUBSEQUENT:\n\t\t\t\t\t\tif (!drawOrder && timeline instanceof DrawOrderTimeline) continue;\n\t\t\t\t\t\ttimelineBlend = blend;\n\t\t\t\t\t\talpha = alphaMix;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase FIRST:\n\t\t\t\t\t\ttimelineBlend = MixBlend.setup;\n\t\t\t\t\t\talpha = alphaMix;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HOLD_SUBSEQUENT:\n\t\t\t\t\t\ttimelineBlend = blend;\n\t\t\t\t\t\talpha = alphaHold;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HOLD_FIRST:\n\t\t\t\t\t\ttimelineBlend = MixBlend.setup;\n\t\t\t\t\t\talpha = alphaHold;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\ttimelineBlend = MixBlend.setup;\n\t\t\t\t\t\tlet holdMix = timelineHoldMix[i];\n\t\t\t\t\t\talpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfrom.totalAlpha += alpha;\n\n\t\t\t\tif (!shortestRotation && timeline instanceof RotateTimeline)\n\t\t\t\t\tthis.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame);\n\t\t\t\telse if (timeline instanceof AttachmentTimeline)\n\t\t\t\t\tthis.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments && alpha >= from.alphaAttachmentThreshold);\n\t\t\t\telse {\n\t\t\t\t\t// This fixes the WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\t\t\t\t\tUtils.webkit602BugfixHelper(alpha, blend);\n\t\t\t\t\tif (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == MixBlend.setup)\n\t\t\t\t\t\tdirection = MixDirection.mixIn;\n\t\t\t\t\ttimeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (to.mixDuration > 0) this.queueEvents(from, animationTime);\n\t\tthis.events.length = 0;\n\t\tfrom.nextAnimationLast = animationTime;\n\t\tfrom.nextTrackLast = from.trackTime;\n\n\t\treturn mix;\n\t}\n\n\tapplyAttachmentTimeline (timeline: AttachmentTimeline, skeleton: Skeleton, time: number, blend: MixBlend, attachments: boolean) {\n\t\tvar slot = skeleton.slots[timeline.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tif (time < timeline.frames[0]) { // Time is before first frame.\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first)\n\t\t\t\tthis.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);\n\t\t} else\n\t\t\tthis.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments);\n\n\t\t// If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.\n\t\tif (slot.attachmentState <= this.unkeyedState) slot.attachmentState = this.unkeyedState + SETUP;\n\t}\n\n\tsetAttachment (skeleton: Skeleton, slot: Slot, attachmentName: string | null, attachments: boolean) {\n\t\tslot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));\n\t\tif (attachments) slot.attachmentState = this.unkeyedState + CURRENT;\n\t}\n\n\tapplyRotateTimeline (timeline: RotateTimeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend,\n\t\ttimelinesRotation: Array, i: number, firstFrame: boolean) {\n\n\t\tif (firstFrame) timelinesRotation[i] = 0;\n\n\t\tif (alpha == 1) {\n\t\t\ttimeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.mixIn);\n\t\t\treturn;\n\t\t}\n\n\t\tlet bone = skeleton.bones[timeline.boneIndex];\n\t\tif (!bone.active) return;\n\t\tlet frames = timeline.frames;\n\t\tlet r1 = 0, r2 = 0;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.rotation = bone.data.rotation;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tr1 = bone.rotation;\n\t\t\t\t\tr2 = bone.data.rotation;\n\t\t\t}\n\t\t} else {\n\t\t\tr1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;\n\t\t\tr2 = bone.data.rotation + timeline.getCurveValue(time);\n\t\t}\n\n\t\t// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.\n\t\tlet total = 0, diff = r2 - r1;\n\t\tdiff -= Math.ceil(diff / 360 - 0.5) * 360;\n\t\tif (diff == 0) {\n\t\t\ttotal = timelinesRotation[i];\n\t\t} else {\n\t\t\tlet lastTotal = 0, lastDiff = 0;\n\t\t\tif (firstFrame) {\n\t\t\t\tlastTotal = 0;\n\t\t\t\tlastDiff = diff;\n\t\t\t} else {\n\t\t\t\tlastTotal = timelinesRotation[i];\n\t\t\t\tlastDiff = timelinesRotation[i + 1];\n\t\t\t}\n\t\t\tlet loops = lastTotal - lastTotal % 360;\n\t\t\ttotal = diff + loops;\n\t\t\tlet current = diff >= 0, dir = lastTotal >= 0;\n\t\t\tif (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) {\n\t\t\t\tif (Math.abs(lastTotal - loops) > 180) {\n\t\t\t\t\ttotal += 360 * MathUtils.signum(lastTotal);\n\t\t\t\t\tdir = current;\n\t\t\t\t} else if (loops != 0)\n\t\t\t\t\ttotal -= 360 * MathUtils.signum(lastTotal);\n\t\t\t\telse\n\t\t\t\t\tdir = current;\n\t\t\t}\n\t\t\tif (dir != current) total += 360 * MathUtils.signum(lastTotal);\n\t\t\ttimelinesRotation[i] = total;\n\t\t}\n\t\ttimelinesRotation[i + 1] = diff;\n\t\tbone.rotation = r1 + total * alpha;\n\t}\n\n\tqueueEvents (entry: TrackEntry, animationTime: number) {\n\t\tlet animationStart = entry.animationStart, animationEnd = entry.animationEnd;\n\t\tlet duration = animationEnd - animationStart;\n\t\tlet trackLastWrapped = entry.trackLast % duration;\n\n\t\t// Queue events before complete.\n\t\tlet events = this.events;\n\t\tlet i = 0, n = events.length;\n\t\tfor (; i < n; i++) {\n\t\t\tlet event = events[i];\n\t\t\tif (event.time < trackLastWrapped) break;\n\t\t\tif (event.time > animationEnd) continue; // Discard events outside animation start/end.\n\t\t\tthis.queue.event(entry, event);\n\t\t}\n\n\t\t// Queue complete if completed a loop iteration or the animation.\n\t\tlet complete = false;\n\t\tif (entry.loop) {\n\t\t\tif (duration == 0)\n\t\t\t\tcomplete = true;\n\t\t\telse {\n\t\t\t\tconst cycles = Math.floor(entry.trackTime / duration);\n\t\t\t\tcomplete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration);\n\t\t\t}\n\t\t} else\n\t\t\tcomplete = animationTime >= animationEnd && entry.animationLast < animationEnd;\n\t\tif (complete) this.queue.complete(entry);\n\n\t\t// Queue events after complete.\n\t\tfor (; i < n; i++) {\n\t\t\tlet event = events[i];\n\t\t\tif (event.time < animationStart) continue; // Discard events outside animation start/end.\n\t\t\tthis.queue.event(entry, event);\n\t\t}\n\t}\n\n\t/** Removes all animations from all tracks, leaving skeletons in their current pose.\n\t *\n\t * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose,\n\t * rather than leaving them in their current pose. */\n\tclearTracks () {\n\t\tlet oldDrainDisabled = this.queue.drainDisabled;\n\t\tthis.queue.drainDisabled = true;\n\t\tfor (let i = 0, n = this.tracks.length; i < n; i++)\n\t\t\tthis.clearTrack(i);\n\t\tthis.tracks.length = 0;\n\t\tthis.queue.drainDisabled = oldDrainDisabled;\n\t\tthis.queue.drain();\n\t}\n\n\t/** Removes all animations from the track, leaving skeletons in their current pose.\n\t *\n\t * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose,\n\t * rather than leaving them in their current pose. */\n\tclearTrack (trackIndex: number) {\n\t\tif (trackIndex >= this.tracks.length) return;\n\t\tlet current = this.tracks[trackIndex];\n\t\tif (!current) return;\n\n\t\tthis.queue.end(current);\n\n\t\tthis.clearNext(current);\n\n\t\tlet entry = current;\n\t\twhile (true) {\n\t\t\tlet from = entry.mixingFrom;\n\t\t\tif (!from) break;\n\t\t\tthis.queue.end(from);\n\t\t\tentry.mixingFrom = null;\n\t\t\tentry.mixingTo = null;\n\t\t\tentry = from;\n\t\t}\n\n\t\tthis.tracks[current.trackIndex] = null;\n\n\t\tthis.queue.drain();\n\t}\n\n\tsetCurrent (index: number, current: TrackEntry, interrupt: boolean) {\n\t\tlet from = this.expandToIndex(index);\n\t\tthis.tracks[index] = current;\n\t\tcurrent.previous = null;\n\n\t\tif (from) {\n\t\t\tif (interrupt) this.queue.interrupt(from);\n\t\t\tcurrent.mixingFrom = from;\n\t\t\tfrom.mixingTo = current;\n\t\t\tcurrent.mixTime = 0;\n\n\t\t\t// Store the interrupted mix percentage.\n\t\t\tif (from.mixingFrom && from.mixDuration > 0)\n\t\t\t\tcurrent.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration);\n\n\t\t\tfrom.timelinesRotation.length = 0; // Reset rotation for mixing out, in case entry was mixed in.\n\t\t}\n\n\t\tthis.queue.start(current);\n\t}\n\n\t/** Sets an animation by name.\n\t *\n\t * See {@link #setAnimationWith()}. */\n\tsetAnimation (trackIndex: number, animationName: string, loop: boolean = false) {\n\t\tlet animation = this.data.skeletonData.findAnimation(animationName);\n\t\tif (!animation) throw new Error(\"Animation not found: \" + animationName);\n\t\treturn this.setAnimationWith(trackIndex, animation, loop);\n\t}\n\n\t/** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never\n\t * applied to a skeleton, it is replaced (not mixed from).\n\t * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its\n\t * duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared.\n\t * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept\n\t * after the {@link AnimationStateListener#dispose()} event occurs. */\n\tsetAnimationWith (trackIndex: number, animation: Animation, loop: boolean = false) {\n\t\tif (!animation) throw new Error(\"animation cannot be null.\");\n\t\tlet interrupt = true;\n\t\tlet current = this.expandToIndex(trackIndex);\n\t\tif (current) {\n\t\t\tif (current.nextTrackLast == -1) {\n\t\t\t\t// Don't mix from an entry that was never applied.\n\t\t\t\tthis.tracks[trackIndex] = current.mixingFrom;\n\t\t\t\tthis.queue.interrupt(current);\n\t\t\t\tthis.queue.end(current);\n\t\t\t\tthis.clearNext(current);\n\t\t\t\tcurrent = current.mixingFrom;\n\t\t\t\tinterrupt = false;\n\t\t\t} else\n\t\t\t\tthis.clearNext(current);\n\t\t}\n\t\tlet entry = this.trackEntry(trackIndex, animation, loop, current);\n\t\tthis.setCurrent(trackIndex, entry, interrupt);\n\t\tthis.queue.drain();\n\t\treturn entry;\n\t}\n\n\t/** Queues an animation by name.\n\t *\n\t * See {@link #addAnimationWith()}. */\n\taddAnimation (trackIndex: number, animationName: string, loop: boolean = false, delay: number = 0) {\n\t\tlet animation = this.data.skeletonData.findAnimation(animationName);\n\t\tif (!animation) throw new Error(\"Animation not found: \" + animationName);\n\t\treturn this.addAnimationWith(trackIndex, animation, loop, delay);\n\t}\n\n\t/** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is\n\t * equivalent to calling {@link #setAnimationWith()}.\n\t * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry\n\t * minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix\n\t * ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the\n\t * previous entry is looping, its next loop completion is used instead of its duration.\n\t * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept\n\t * after the {@link AnimationStateListener#dispose()} event occurs. */\n\taddAnimationWith (trackIndex: number, animation: Animation, loop: boolean = false, delay: number = 0) {\n\t\tif (!animation) throw new Error(\"animation cannot be null.\");\n\n\t\tlet last = this.expandToIndex(trackIndex);\n\t\tif (last) {\n\t\t\twhile (last.next)\n\t\t\t\tlast = last.next;\n\t\t}\n\n\t\tlet entry = this.trackEntry(trackIndex, animation, loop, last);\n\n\t\tif (!last) {\n\t\t\tthis.setCurrent(trackIndex, entry, true);\n\t\t\tthis.queue.drain();\n\t\t} else {\n\t\t\tlast.next = entry;\n\t\t\tentry.previous = last;\n\t\t\tif (delay <= 0) delay += last.getTrackComplete() - entry.mixDuration;\n\t\t}\n\n\t\tentry.delay = delay;\n\t\treturn entry;\n\t}\n\n\t/** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's\n\t * {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out.\n\t *\n\t * Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()},\n\t * {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes\n\t * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation\n\t * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of\n\t * 0 still mixes out over one frame.\n\t *\n\t * Mixing in is done by first setting an empty animation, then adding an animation using\n\t * {@link #addAnimation()} and on the returned track entry, set the\n\t * {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and\n\t * more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the\n\t * setup pose value if no lower tracks key the property to the value keyed in the new animation. */\n\tsetEmptyAnimation (trackIndex: number, mixDuration: number = 0) {\n\t\tlet entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation(), false);\n\t\tentry.mixDuration = mixDuration;\n\t\tentry.trackEnd = mixDuration;\n\t\treturn entry;\n\t}\n\n\t/** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's\n\t * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling\n\t * {@link #setEmptyAnimation()}.\n\t *\n\t * See {@link #setEmptyAnimation()}.\n\t * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry\n\t * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or\n\t * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next\n\t * loop completion is used instead of its duration.\n\t * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept\n\t * after the {@link AnimationStateListener#dispose()} event occurs. */\n\taddEmptyAnimation (trackIndex: number, mixDuration: number = 0, delay: number = 0) {\n\t\tlet entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation(), false, delay);\n\t\tif (delay <= 0) entry.delay += entry.mixDuration - mixDuration;\n\t\tentry.mixDuration = mixDuration;\n\t\tentry.trackEnd = mixDuration;\n\t\treturn entry;\n\t}\n\n\t/** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix\n\t * duration. */\n\tsetEmptyAnimations (mixDuration: number = 0) {\n\t\tlet oldDrainDisabled = this.queue.drainDisabled;\n\t\tthis.queue.drainDisabled = true;\n\t\tfor (let i = 0, n = this.tracks.length; i < n; i++) {\n\t\t\tlet current = this.tracks[i];\n\t\t\tif (current) this.setEmptyAnimation(current.trackIndex, mixDuration);\n\t\t}\n\t\tthis.queue.drainDisabled = oldDrainDisabled;\n\t\tthis.queue.drain();\n\t}\n\n\texpandToIndex (index: number) {\n\t\tif (index < this.tracks.length) return this.tracks[index];\n\t\tUtils.ensureArrayCapacity(this.tracks, index + 1, null);\n\t\tthis.tracks.length = index + 1;\n\t\treturn null;\n\t}\n\n\t/** @param last May be null. */\n\ttrackEntry (trackIndex: number, animation: Animation, loop: boolean, last: TrackEntry | null) {\n\t\tlet entry = this.trackEntryPool.obtain();\n\t\tentry.reset();\n\t\tentry.trackIndex = trackIndex;\n\t\tentry.animation = animation;\n\t\tentry.loop = loop;\n\t\tentry.holdPrevious = false;\n\n\t\tentry.reverse = false;\n\t\tentry.shortestRotation = false;\n\n\t\tentry.eventThreshold = 0;\n\t\tentry.alphaAttachmentThreshold = 0;\n\t\tentry.mixAttachmentThreshold = 0;\n\t\tentry.mixDrawOrderThreshold = 0;\n\n\t\tentry.animationStart = 0;\n\t\tentry.animationEnd = animation.duration;\n\t\tentry.animationLast = -1;\n\t\tentry.nextAnimationLast = -1;\n\n\t\tentry.delay = 0;\n\t\tentry.trackTime = 0;\n\t\tentry.trackLast = -1;\n\t\tentry.nextTrackLast = -1;\n\t\tentry.trackEnd = Number.MAX_VALUE;\n\t\tentry.timeScale = 1;\n\n\t\tentry.alpha = 1;\n\t\tentry.mixTime = 0;\n\t\tentry.mixDuration = !last ? 0 : this.data.getMix(last.animation!, animation);\n\t\tentry.interruptAlpha = 1;\n\t\tentry.totalAlpha = 0;\n\t\tentry.mixBlend = MixBlend.replace;\n\t\treturn entry;\n\t}\n\n\t/** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */\n\tclearNext (entry: TrackEntry) {\n\t\tlet next = entry.next;\n\t\twhile (next) {\n\t\t\tthis.queue.dispose(next);\n\t\t\tnext = next.next;\n\t\t}\n\t\tentry.next = null;\n\t}\n\n\t_animationsChanged () {\n\t\tthis.animationsChanged = false;\n\n\t\tthis.propertyIDs.clear();\n\t\tlet tracks = this.tracks;\n\t\tfor (let i = 0, n = tracks.length; i < n; i++) {\n\t\t\tlet entry = tracks[i];\n\t\t\tif (!entry) continue;\n\t\t\twhile (entry.mixingFrom)\n\t\t\t\tentry = entry.mixingFrom;\n\t\t\tdo {\n\t\t\t\tif (!entry.mixingTo || entry.mixBlend != MixBlend.add) this.computeHold(entry);\n\t\t\t\tentry = entry.mixingTo;\n\t\t\t} while (entry);\n\t\t}\n\t}\n\n\tcomputeHold (entry: TrackEntry) {\n\t\tlet to = entry.mixingTo;\n\t\tlet timelines = entry.animation!.timelines;\n\t\tlet timelinesCount = entry.animation!.timelines.length;\n\t\tlet timelineMode = entry.timelineMode;\n\t\ttimelineMode.length = timelinesCount;\n\t\tlet timelineHoldMix = entry.timelineHoldMix;\n\t\ttimelineHoldMix.length = 0;\n\t\tlet propertyIDs = this.propertyIDs;\n\n\t\tif (to && to.holdPrevious) {\n\t\t\tfor (let i = 0; i < timelinesCount; i++)\n\t\t\t\ttimelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT;\n\t\t\treturn;\n\t\t}\n\n\t\touter:\n\t\tfor (let i = 0; i < timelinesCount; i++) {\n\t\t\tlet timeline = timelines[i];\n\t\t\tlet ids = timeline.getPropertyIds();\n\t\t\tif (!propertyIDs.addAll(ids))\n\t\t\t\ttimelineMode[i] = SUBSEQUENT;\n\t\t\telse if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline\n\t\t\t\t|| timeline instanceof EventTimeline || !to.animation!.hasTimeline(ids)) {\n\t\t\t\ttimelineMode[i] = FIRST;\n\t\t\t} else {\n\t\t\t\tfor (let next = to.mixingTo; next; next = next!.mixingTo) {\n\t\t\t\t\tif (next.animation!.hasTimeline(ids)) continue;\n\t\t\t\t\tif (entry.mixDuration > 0) {\n\t\t\t\t\t\ttimelineMode[i] = HOLD_MIX;\n\t\t\t\t\t\ttimelineHoldMix[i] = next;\n\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttimelineMode[i] = HOLD_FIRST;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */\n\tgetCurrent (trackIndex: number) {\n\t\tif (trackIndex >= this.tracks.length) return null;\n\t\treturn this.tracks[trackIndex];\n\t}\n\n\t/** Adds a listener to receive events for all track entries. */\n\taddListener (listener: AnimationStateListener) {\n\t\tif (!listener) throw new Error(\"listener cannot be null.\");\n\t\tthis.listeners.push(listener);\n\t}\n\n\t/** Removes the listener added with {@link #addListener()}. */\n\tremoveListener (listener: AnimationStateListener) {\n\t\tlet index = this.listeners.indexOf(listener);\n\t\tif (index >= 0) this.listeners.splice(index, 1);\n\t}\n\n\t/** Removes all listeners added with {@link #addListener()}. */\n\tclearListeners () {\n\t\tthis.listeners.length = 0;\n\t}\n\n\t/** Discards all listener notifications that have not yet been delivered. This can be useful to call from an\n\t * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery\n\t * are not wanted because new animations are being set. */\n\tclearListenerNotifications () {\n\t\tthis.queue.clear();\n\t}\n}\n\n/** Stores settings and other state for the playback of an animation on an {@link AnimationState} track.\n *\n * References to a track entry must not be kept after the {@link AnimationStateListener#dispose()} event occurs. */\nexport class TrackEntry {\n\t/** The animation to apply for this track entry. */\n\tanimation: Animation | null = null;\n\n\tprevious: TrackEntry | null = null;\n\n\t/** The animation queued to start after this animation, or null. `next` makes up a linked list. */\n\tnext: TrackEntry | null = null;\n\n\t/** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no\n\t * mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */\n\tmixingFrom: TrackEntry | null = null;\n\n\t/** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is\n\t * currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */\n\tmixingTo: TrackEntry | null = null;\n\n\t/** The listener for events generated by this track entry, or null.\n\t *\n\t * A track entry returned from {@link AnimationState#setAnimation()} is already the current animation\n\t * for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */\n\tlistener: AnimationStateListener | null = null;\n\n\t/** The index of the track where this track entry is either current or queued.\n\t *\n\t * See {@link AnimationState#getCurrent()}. */\n\ttrackIndex: number = 0;\n\n\t/** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its\n\t * duration. */\n\tloop: boolean = false;\n\n\t/** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead\n\t * of being mixed out.\n\t *\n\t * When mixing between animations that key the same property, if a lower track also keys that property then the value will\n\t * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0%\n\t * while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation\n\t * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which\n\t * keys the property, only when a higher track also keys the property.\n\t *\n\t * Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the\n\t * previous animation. */\n\tholdPrevious: boolean = false;\n\n\treverse: boolean = false;\n\n\tshortestRotation: boolean = false;\n\n\t/** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the\n\t * `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event\n\t * timelines are not applied while this animation is being mixed out. */\n\teventThreshold: number = 0;\n\n\t/** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the\n\t * `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to\n\t * 0, so attachment timelines are not applied while this animation is being mixed out. */\n\tmixAttachmentThreshold: number = 0;\n\n\t/** When {@link #getAlpha()} is greater than alphaAttachmentThreshold, attachment timelines are applied.\n\t * Defaults to 0, so attachment timelines are always applied. */\n\talphaAttachmentThreshold: number = 0;\n\n\t/** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the\n\t * mixDrawOrderThreshold, draw order timelines are applied while this animation is being mixed out. Defaults to\n\t * 0, so draw order timelines are not applied while this animation is being mixed out. */\n\tmixDrawOrderThreshold: number = 0;\n\n\t/** Seconds when this animation starts, both initially and after looping. Defaults to 0.\n\t *\n\t * When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same\n\t * value to prevent timeline keys before the start time from triggering. */\n\tanimationStart: number = 0;\n\n\t/** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will\n\t * loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */\n\tanimationEnd: number = 0;\n\n\n\t/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this\n\t * animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and\n\t * `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation\n\t * is applied. */\n\tanimationLast: number = 0;\n\n\tnextAnimationLast: number = 0;\n\n\t/** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay`\n\t * postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from\n\t * the start of the previous animation to when this track entry will become the current track entry (ie when the previous\n\t * track entry {@link TrackEntry#trackTime} >= this track entry's `delay`).\n\t *\n\t * {@link #timeScale} affects the delay. */\n\tdelay: number = 0;\n\n\t/** Current time in seconds this track entry has been the current track entry. The track time determines\n\t * {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting\n\t * looping. */\n\ttrackTime: number = 0;\n\n\ttrackLast: number = 0; nextTrackLast: number = 0;\n\n\t/** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float\n\t * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time\n\t * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the\n\t * properties keyed by the animation are set to the setup pose and the track is cleared.\n\t *\n\t * It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation\n\t * abruptly cease being applied. */\n\ttrackEnd: number = 0;\n\n\t/** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or\n\t * faster. Defaults to 1.\n\t *\n\t * {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to\n\t * match the animation speed.\n\t *\n\t * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the\n\t * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If\n\t * the time scale is not 1, the delay may need to be adjusted.\n\t *\n\t * See AnimationState {@link AnimationState#timeScale} for affecting all animations. */\n\ttimeScale: number = 0;\n\n\t/** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults\n\t * to 1, which overwrites the skeleton's current pose with this animation.\n\t *\n\t * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to\n\t * use alpha on track 0 if the skeleton pose is from the last frame render. */\n\talpha: number = 0;\n\n\t/** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be\n\t * slightly more than `mixDuration` when the mix is complete. */\n\tmixTime: number = 0;\n\n\t/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData\n\t * {@link AnimationStateData#getMix()} based on the animation before this animation (if any).\n\t *\n\t * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the\n\t * properties it was animating.\n\t *\n\t * The `mixDuration` can be set manually rather than use the value from\n\t * {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new\n\t * track entry only before {@link AnimationState#update(float)} is first called.\n\t *\n\t * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the\n\t * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set\n\t * afterward. */\n\t_mixDuration: number = 0; interruptAlpha: number = 0; totalAlpha: number = 0;\n\n\tget mixDuration () {\n\t\treturn this._mixDuration;\n\t}\n\n\tset mixDuration (mixDuration: number) {\n\t\tthis._mixDuration = mixDuration;\n\t}\n\n\tsetMixDurationWithDelay (mixDuration: number, delay: number) {\n\t\tthis._mixDuration = mixDuration;\n\t\tif (this.previous != null && delay <= 0) delay += this.previous.getTrackComplete() - mixDuration;\n\t\tthis.delay = delay;\n\t}\n\n\t/** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which\n\t * replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to\n\t * the values from the lower tracks.\n\t *\n\t * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first\n\t * called. */\n\tmixBlend = MixBlend.replace;\n\ttimelineMode = new Array();\n\ttimelineHoldMix = new Array();\n\ttimelinesRotation = new Array();\n\n\treset () {\n\t\tthis.next = null;\n\t\tthis.previous = null;\n\t\tthis.mixingFrom = null;\n\t\tthis.mixingTo = null;\n\t\tthis.animation = null;\n\t\tthis.listener = null;\n\t\tthis.timelineMode.length = 0;\n\t\tthis.timelineHoldMix.length = 0;\n\t\tthis.timelinesRotation.length = 0;\n\t}\n\n\t/** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart}\n\t * and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the\n\t * `animationStart` time. */\n\tgetAnimationTime () {\n\t\tif (this.loop) {\n\t\t\tlet duration = this.animationEnd - this.animationStart;\n\t\t\tif (duration == 0) return this.animationStart;\n\t\t\treturn (this.trackTime % duration) + this.animationStart;\n\t\t}\n\t\treturn Math.min(this.trackTime + this.animationStart, this.animationEnd);\n\t}\n\n\tsetAnimationLast (animationLast: number) {\n\t\tthis.animationLast = animationLast;\n\t\tthis.nextAnimationLast = animationLast;\n\t}\n\n\t/** Returns true if at least one loop has been completed.\n\t *\n\t * See {@link AnimationStateListener#complete()}. */\n\tisComplete () {\n\t\treturn this.trackTime >= this.animationEnd - this.animationStart;\n\t}\n\n\t/** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the\n\t * long way around when using {@link #alpha} and starting animations on other tracks.\n\t *\n\t * Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions:\n\t * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long\n\t * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the\n\t * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */\n\tresetRotationDirections () {\n\t\tthis.timelinesRotation.length = 0;\n\t}\n\n\tgetTrackComplete () {\n\t\tlet duration = this.animationEnd - this.animationStart;\n\t\tif (duration != 0) {\n\t\t\tif (this.loop) return duration * (1 + ((this.trackTime / duration) | 0)); // Completion of next loop.\n\t\t\tif (this.trackTime < duration) return duration; // Before duration.\n\t\t}\n\t\treturn this.trackTime; // Next update.\n\t}\n\n\t/** Returns true if this track entry has been applied at least once.\n\t *

    \n\t * See {@link AnimationState#apply(Skeleton)}. */\n\twasApplied () {\n\t\treturn this.nextTrackLast != -1;\n\t}\n\n\t/** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next\n\t * {@link AnimationState#update(float)}. */\n\tisNextReady () {\n\t\treturn this.next != null && this.nextTrackLast - this.next.delay >= 0;\n\t}\n}\n\nexport class EventQueue {\n\tobjects: Array = [];\n\tdrainDisabled = false;\n\tanimState: AnimationState;\n\n\tconstructor (animState: AnimationState) {\n\t\tthis.animState = animState;\n\t}\n\n\tstart (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.start);\n\t\tthis.objects.push(entry);\n\t\tthis.animState.animationsChanged = true;\n\t}\n\n\tinterrupt (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.interrupt);\n\t\tthis.objects.push(entry);\n\t}\n\n\tend (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.end);\n\t\tthis.objects.push(entry);\n\t\tthis.animState.animationsChanged = true;\n\t}\n\n\tdispose (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.dispose);\n\t\tthis.objects.push(entry);\n\t}\n\n\tcomplete (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.complete);\n\t\tthis.objects.push(entry);\n\t}\n\n\tevent (entry: TrackEntry, event: Event) {\n\t\tthis.objects.push(EventType.event);\n\t\tthis.objects.push(entry);\n\t\tthis.objects.push(event);\n\t}\n\n\tdrain () {\n\t\tif (this.drainDisabled) return;\n\t\tthis.drainDisabled = true;\n\n\t\tlet objects = this.objects;\n\t\tlet listeners = this.animState.listeners;\n\n\t\tfor (let i = 0; i < objects.length; i += 2) {\n\t\t\tlet type = objects[i] as EventType;\n\t\t\tlet entry = objects[i + 1] as TrackEntry;\n\t\t\tswitch (type) {\n\t\t\t\tcase EventType.start:\n\t\t\t\t\tif (entry.listener && entry.listener.start) entry.listener.start(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.start) listener.start(entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.interrupt:\n\t\t\t\t\tif (entry.listener && entry.listener.interrupt) entry.listener.interrupt(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.interrupt) listener.interrupt(entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.end:\n\t\t\t\t\tif (entry.listener && entry.listener.end) entry.listener.end(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.end) listener.end(entry);\n\t\t\t\t\t}\n\t\t\t\t// Fall through.\n\t\t\t\tcase EventType.dispose:\n\t\t\t\t\tif (entry.listener && entry.listener.dispose) entry.listener.dispose(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.dispose) listener.dispose(entry);\n\t\t\t\t\t}\n\t\t\t\t\tthis.animState.trackEntryPool.free(entry);\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.complete:\n\t\t\t\t\tif (entry.listener && entry.listener.complete) entry.listener.complete(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.complete) listener.complete(entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.event:\n\t\t\t\t\tlet event = objects[i++ + 2] as Event;\n\t\t\t\t\tif (entry.listener && entry.listener.event) entry.listener.event(entry, event);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.event) listener.event(entry, event);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.clear();\n\n\t\tthis.drainDisabled = false;\n\t}\n\n\tclear () {\n\t\tthis.objects.length = 0;\n\t}\n}\n\nexport enum EventType {\n\tstart, interrupt, end, dispose, complete, event\n}\n\n/** The interface to implement for receiving TrackEntry events. It is always safe to call AnimationState methods when receiving\n * events.\n *\n * See TrackEntry {@link TrackEntry#listener} and AnimationState\n * {@link AnimationState#addListener()}. */\nexport interface AnimationStateListener {\n\t/** Invoked when this entry has been set as the current entry. */\n\tstart?: (entry: TrackEntry) => void;\n\n\t/** Invoked when another entry has replaced this entry as the current entry. This entry may continue being applied for\n\t * mixing. */\n\tinterrupt?: (entry: TrackEntry) => void;\n\n\t/** Invoked when this entry is no longer the current entry and will never be applied again. */\n\tend?: (entry: TrackEntry) => void;\n\n\t/** Invoked when this entry will be disposed. This may occur without the entry ever being set as the current entry.\n\t * References to the entry should not be kept after dispose is called, as it may be destroyed or reused. */\n\tdispose?: (entry: TrackEntry) => void;\n\n\t/** Invoked every time this entry's animation completes a loop. */\n\tcomplete?: (entry: TrackEntry) => void;\n\n\t/** Invoked when this entry's animation triggers an event. */\n\tevent?: (entry: TrackEntry, event: Event) => void;\n}\n\nexport abstract class AnimationStateAdapter implements AnimationStateListener {\n\tstart (entry: TrackEntry) {\n\t}\n\n\tinterrupt (entry: TrackEntry) {\n\t}\n\n\tend (entry: TrackEntry) {\n\t}\n\n\tdispose (entry: TrackEntry) {\n\t}\n\n\tcomplete (entry: TrackEntry) {\n\t}\n\n\tevent (entry: TrackEntry, event: Event) {\n\t}\n}\n\n/** 1. A previously applied timeline has set this property.\n *\n * Result: Mix from the current pose to the timeline pose. */\nexport const SUBSEQUENT = 0;\n/** 1. This is the first timeline to set this property.\n * 2. The next track entry applied after this one does not have a timeline to set this property.\n *\n * Result: Mix from the setup pose to the timeline pose. */\nexport const FIRST = 1;\n/** 1) A previously applied timeline has set this property.
    \n * 2) The next track entry to be applied does have a timeline to set this property.
    \n * 3) The next track entry after that one does not have a timeline to set this property.
    \n * Result: Mix from the current pose to the timeline pose, but do not mix out. This avoids \"dipping\" when crossfading\n * animations that key the same property. A subsequent timeline will set this property using a mix. */\nexport const HOLD_SUBSEQUENT = 2;\n/** 1) This is the first timeline to set this property.
    \n * 2) The next track entry to be applied does have a timeline to set this property.
    \n * 3) The next track entry after that one does not have a timeline to set this property.
    \n * Result: Mix from the setup pose to the timeline pose, but do not mix out. This avoids \"dipping\" when crossfading animations\n * that key the same property. A subsequent timeline will set this property using a mix. */\nexport const HOLD_FIRST = 3;\n/** 1. This is the first timeline to set this property.\n * 2. The next track entry to be applied does have a timeline to set this property.\n * 3. The next track entry after that one does have a timeline to set this property.\n * 4. timelineHoldMix stores the first subsequent track entry that does not have a timeline to set this property.\n *\n * Result: The same as HOLD except the mix percentage from the timelineHoldMix track entry is used. This handles when more than\n * 2 track entries in a row have a timeline that sets the same property.\n *\n * Eg, A -> B -> C -> D where A, B, and C have a timeline setting same property, but D does not. When A is applied, to avoid\n * \"dipping\" A is not mixed out, however D (the first entry that doesn't set the property) mixing in is used to mix out A\n * (which affects B and C). Without using D to mix out, A would be applied fully until mixing completes, then snap into\n * place. */\nexport const HOLD_MIX = 4;\n\nexport const SETUP = 1;\nexport const CURRENT = 2;\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation } from \"./Animation.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { StringMap } from \"./Utils.js\";\n\n\n/** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed. */\nexport class AnimationStateData {\n\t/** The SkeletonData to look up animations when they are specified by name. */\n\tskeletonData: SkeletonData;\n\n\tanimationToMixTime: StringMap = {};\n\n\t/** The mix duration to use when no mix duration has been defined between two animations. */\n\tdefaultMix = 0;\n\n\tconstructor (skeletonData: SkeletonData) {\n\t\tif (!skeletonData) throw new Error(\"skeletonData cannot be null.\");\n\t\tthis.skeletonData = skeletonData;\n\t}\n\n\t/** Sets a mix duration by animation name.\n\t *\n\t * See {@link #setMixWith()}. */\n\tsetMix (fromName: string, toName: string, duration: number) {\n\t\tlet from = this.skeletonData.findAnimation(fromName);\n\t\tif (!from) throw new Error(\"Animation not found: \" + fromName);\n\t\tlet to = this.skeletonData.findAnimation(toName);\n\t\tif (!to) throw new Error(\"Animation not found: \" + toName);\n\t\tthis.setMixWith(from, to, duration);\n\t}\n\n\t/** Sets the mix duration when changing from the specified animation to the other.\n\t *\n\t * See {@link TrackEntry#mixDuration}. */\n\tsetMixWith (from: Animation, to: Animation, duration: number) {\n\t\tif (!from) throw new Error(\"from cannot be null.\");\n\t\tif (!to) throw new Error(\"to cannot be null.\");\n\t\tlet key = from.name + \".\" + to.name;\n\t\tthis.animationToMixTime[key] = duration;\n\t}\n\n\t/** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if\n\t * no mix duration has been set. */\n\tgetMix (from: Animation, to: Animation) {\n\t\tlet key = from.name + \".\" + to.name;\n\t\tlet value = this.animationToMixTime[key];\n\t\treturn value === undefined ? this.defaultMix : value;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle\n * effects, and more.\n *\n * See {@link SkeletonBounds} and [Bounding Boxes](http://esotericsoftware.com/spine-bounding-boxes) in the Spine User\n * Guide. */\nexport class BoundingBoxAttachment extends VertexAttachment {\n\tcolor = new Color(1, 1, 1, 1);\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new BoundingBoxAttachment(this.name);\n\t\tthis.copyTo(copy);\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { SlotData } from \"../SlotData.js\";\nimport { Color } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment with vertices that make up a polygon used for clipping the rendering of other attachments. */\nexport class ClippingAttachment extends VertexAttachment {\n\t/** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of\n\t * the skeleton's rendering. */\n\tendSlot: SlotData | null = null;\n\n\t// Nonessential.\n\t/** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons\n\t * are not usually rendered at runtime. */\n\tcolor = new Color(0.2275, 0.2275, 0.8078, 1); // ce3a3aff\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new ClippingAttachment(this.name);\n\t\tthis.copyTo(copy);\n\t\tcopy.endSlot = this.endSlot;\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport abstract class Texture {\n\tprotected _image: HTMLImageElement | ImageBitmap | any;\n\n\tconstructor (image: HTMLImageElement | ImageBitmap | any) {\n\t\tthis._image = image;\n\t}\n\n\tgetImage (): HTMLImageElement | ImageBitmap | any {\n\t\treturn this._image;\n\t}\n\n\tabstract setFilters (minFilter: TextureFilter, magFilter: TextureFilter): void;\n\tabstract setWraps (uWrap: TextureWrap, vWrap: TextureWrap): void;\n\tabstract dispose (): void;\n}\n\nexport enum TextureFilter {\n\tNearest = 9728, // WebGLRenderingContext.NEAREST\n\tLinear = 9729, // WebGLRenderingContext.LINEAR\n\tMipMap = 9987, // WebGLRenderingContext.LINEAR_MIPMAP_LINEAR\n\tMipMapNearestNearest = 9984, // WebGLRenderingContext.NEAREST_MIPMAP_NEAREST\n\tMipMapLinearNearest = 9985, // WebGLRenderingContext.LINEAR_MIPMAP_NEAREST\n\tMipMapNearestLinear = 9986, // WebGLRenderingContext.NEAREST_MIPMAP_LINEAR\n\tMipMapLinearLinear = 9987 // WebGLRenderingContext.LINEAR_MIPMAP_LINEAR\n}\n\nexport enum TextureWrap {\n\tMirroredRepeat = 33648, // WebGLRenderingContext.MIRRORED_REPEAT\n\tClampToEdge = 33071, // WebGLRenderingContext.CLAMP_TO_EDGE\n\tRepeat = 10497 // WebGLRenderingContext.REPEAT\n}\n\nexport class TextureRegion {\n\ttexture: any;\n\tu = 0; v = 0;\n\tu2 = 0; v2 = 0;\n\twidth = 0; height = 0;\n\tdegrees = 0;\n\toffsetX = 0; offsetY = 0;\n\toriginalWidth = 0; originalHeight = 0;\n}\n\nexport class FakeTexture extends Texture {\n\tsetFilters (minFilter: TextureFilter, magFilter: TextureFilter) { }\n\tsetWraps (uWrap: TextureWrap, vWrap: TextureWrap) { }\n\tdispose () { }\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { AssetManagerBase } from \"./AssetManagerBase.js\";\nimport { TextureFilter, TextureWrap, Texture, TextureRegion } from \"./Texture.js\";\nimport { Disposable, Utils, StringMap } from \"./Utils.js\";\n\nexport class TextureAtlas implements Disposable {\n\tpages = new Array();\n\tregions = new Array();\n\n\tconstructor (atlasText: string) {\n\t\tlet reader = new TextureAtlasReader(atlasText);\n\t\tlet entry = new Array(4);\n\n\t\tlet pageFields: StringMap<(page: TextureAtlasPage) => void> = {};\n\t\tpageFields[\"size\"] = (page: TextureAtlasPage) => {\n\t\t\tpage!.width = parseInt(entry[1]);\n\t\t\tpage!.height = parseInt(entry[2]);\n\t\t};\n\t\tpageFields[\"format\"] = () => {\n\t\t\t// page.format = Format[tuple[0]]; we don't need format in WebGL\n\t\t};\n\t\tpageFields[\"filter\"] = (page: TextureAtlasPage) => {\n\t\t\tpage!.minFilter = Utils.enumValue(TextureFilter, entry[1]);\n\t\t\tpage!.magFilter = Utils.enumValue(TextureFilter, entry[2]);\n\t\t};\n\t\tpageFields[\"repeat\"] = (page: TextureAtlasPage) => {\n\t\t\tif (entry[1].indexOf('x') != -1) page!.uWrap = TextureWrap.Repeat;\n\t\t\tif (entry[1].indexOf('y') != -1) page!.vWrap = TextureWrap.Repeat;\n\t\t};\n\t\tpageFields[\"pma\"] = (page: TextureAtlasPage) => {\n\t\t\tpage!.pma = entry[1] == \"true\";\n\t\t};\n\n\t\tvar regionFields: StringMap<(region: TextureAtlasRegion) => void> = {};\n\t\tregionFields[\"xy\"] = (region: TextureAtlasRegion) => { // Deprecated, use bounds.\n\t\t\tregion.x = parseInt(entry[1]);\n\t\t\tregion.y = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"size\"] = (region: TextureAtlasRegion) => { // Deprecated, use bounds.\n\t\t\tregion.width = parseInt(entry[1]);\n\t\t\tregion.height = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"bounds\"] = (region: TextureAtlasRegion) => {\n\t\t\tregion.x = parseInt(entry[1]);\n\t\t\tregion.y = parseInt(entry[2]);\n\t\t\tregion.width = parseInt(entry[3]);\n\t\t\tregion.height = parseInt(entry[4]);\n\t\t};\n\t\tregionFields[\"offset\"] = (region: TextureAtlasRegion) => { // Deprecated, use offsets.\n\t\t\tregion.offsetX = parseInt(entry[1]);\n\t\t\tregion.offsetY = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"orig\"] = (region: TextureAtlasRegion) => { // Deprecated, use offsets.\n\t\t\tregion.originalWidth = parseInt(entry[1]);\n\t\t\tregion.originalHeight = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"offsets\"] = (region: TextureAtlasRegion) => {\n\t\t\tregion.offsetX = parseInt(entry[1]);\n\t\t\tregion.offsetY = parseInt(entry[2]);\n\t\t\tregion.originalWidth = parseInt(entry[3]);\n\t\t\tregion.originalHeight = parseInt(entry[4]);\n\t\t};\n\t\tregionFields[\"rotate\"] = (region: TextureAtlasRegion) => {\n\t\t\tlet value = entry[1];\n\t\t\tif (value == \"true\")\n\t\t\t\tregion.degrees = 90;\n\t\t\telse if (value != \"false\")\n\t\t\t\tregion.degrees = parseInt(value);\n\t\t};\n\t\tregionFields[\"index\"] = (region: TextureAtlasRegion) => {\n\t\t\tregion.index = parseInt(entry[1]);\n\t\t};\n\n\t\tlet line = reader.readLine();\n\t\t// Ignore empty lines before first entry.\n\t\twhile (line && line.trim().length == 0)\n\t\t\tline = reader.readLine();\n\t\t// Header entries.\n\t\twhile (true) {\n\t\t\tif (!line || line.trim().length == 0) break;\n\t\t\tif (reader.readEntry(entry, line) == 0) break; // Silently ignore all header fields.\n\t\t\tline = reader.readLine();\n\t\t}\n\n\t\t// Page and region entries.\n\t\tlet page: TextureAtlasPage | null = null;\n\t\tlet names: string[] | null = null;\n\t\tlet values: number[][] | null = null;\n\t\twhile (true) {\n\t\t\tif (line === null) break;\n\t\t\tif (line.trim().length == 0) {\n\t\t\t\tpage = null;\n\t\t\t\tline = reader.readLine();\n\t\t\t} else if (!page) {\n\t\t\t\tpage = new TextureAtlasPage(line.trim());\n\t\t\t\twhile (true) {\n\t\t\t\t\tif (reader.readEntry(entry, line = reader.readLine()) == 0) break;\n\t\t\t\t\tlet field = pageFields[entry[0]];\n\t\t\t\t\tif (field) field(page);\n\t\t\t\t}\n\t\t\t\tthis.pages.push(page);\n\t\t\t} else {\n\t\t\t\tlet region = new TextureAtlasRegion(page, line);\n\n\t\t\t\twhile (true) {\n\t\t\t\t\tlet count = reader.readEntry(entry, line = reader.readLine());\n\t\t\t\t\tif (count == 0) break;\n\t\t\t\t\tlet field = regionFields[entry[0]];\n\t\t\t\t\tif (field)\n\t\t\t\t\t\tfield(region);\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (!names) names = [];\n\t\t\t\t\t\tif (!values) values = [];\n\t\t\t\t\t\tnames.push(entry[0]);\n\t\t\t\t\t\tlet entryValues: number[] = [];\n\t\t\t\t\t\tfor (let i = 0; i < count; i++)\n\t\t\t\t\t\t\tentryValues.push(parseInt(entry[i + 1]));\n\t\t\t\t\t\tvalues.push(entryValues);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (region.originalWidth == 0 && region.originalHeight == 0) {\n\t\t\t\t\tregion.originalWidth = region.width;\n\t\t\t\t\tregion.originalHeight = region.height;\n\t\t\t\t}\n\t\t\t\tif (names && names.length > 0 && values && values.length > 0) {\n\t\t\t\t\tregion.names = names;\n\t\t\t\t\tregion.values = values;\n\t\t\t\t\tnames = null;\n\t\t\t\t\tvalues = null;\n\t\t\t\t}\n\t\t\t\tregion.u = region.x / page.width;\n\t\t\t\tregion.v = region.y / page.height;\n\t\t\t\tif (region.degrees == 90) {\n\t\t\t\t\tregion.u2 = (region.x + region.height) / page.width;\n\t\t\t\t\tregion.v2 = (region.y + region.width) / page.height;\n\t\t\t\t} else {\n\t\t\t\t\tregion.u2 = (region.x + region.width) / page.width;\n\t\t\t\t\tregion.v2 = (region.y + region.height) / page.height;\n\t\t\t\t}\n\t\t\t\tthis.regions.push(region);\n\t\t\t}\n\t\t}\n\t}\n\n\tfindRegion (name: string): TextureAtlasRegion | null {\n\t\tfor (let i = 0; i < this.regions.length; i++) {\n\t\t\tif (this.regions[i].name == name) {\n\t\t\t\treturn this.regions[i];\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tsetTextures (assetManager: AssetManagerBase, pathPrefix: string = \"\") {\n\t\tfor (let page of this.pages)\n\t\t\tpage.setTexture(assetManager.get(pathPrefix + page.name));\n\t}\n\n\tdispose () {\n\t\tfor (let i = 0; i < this.pages.length; i++) {\n\t\t\tthis.pages[i].texture?.dispose();\n\t\t}\n\t}\n}\n\nclass TextureAtlasReader {\n\tlines: Array;\n\tindex: number = 0;\n\n\tconstructor (text: string) {\n\t\tthis.lines = text.split(/\\r\\n|\\r|\\n/);\n\t}\n\n\treadLine (): string | null {\n\t\tif (this.index >= this.lines.length)\n\t\t\treturn null;\n\t\treturn this.lines[this.index++];\n\t}\n\n\treadEntry (entry: string[], line: string | null): number {\n\t\tif (!line) return 0;\n\t\tline = line.trim();\n\t\tif (line.length == 0) return 0;\n\n\t\tlet colon = line.indexOf(':');\n\t\tif (colon == -1) return 0;\n\t\tentry[0] = line.substr(0, colon).trim();\n\t\tfor (let i = 1, lastMatch = colon + 1; ; i++) {\n\t\t\tlet comma = line.indexOf(',', lastMatch);\n\t\t\tif (comma == -1) {\n\t\t\t\tentry[i] = line.substr(lastMatch).trim();\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tentry[i] = line.substr(lastMatch, comma - lastMatch).trim();\n\t\t\tlastMatch = comma + 1;\n\t\t\tif (i == 4) return 4;\n\t\t}\n\t}\n}\n\nexport class TextureAtlasPage {\n\tname: string;\n\tminFilter: TextureFilter = TextureFilter.Nearest;\n\tmagFilter: TextureFilter = TextureFilter.Nearest;\n\tuWrap: TextureWrap = TextureWrap.ClampToEdge;\n\tvWrap: TextureWrap = TextureWrap.ClampToEdge;\n\ttexture: Texture | null = null;\n\twidth: number = 0;\n\theight: number = 0;\n\tpma: boolean = false;\n\tregions = new Array();\n\n\tconstructor (name: string) {\n\t\tthis.name = name;\n\t}\n\n\tsetTexture (texture: Texture) {\n\t\tthis.texture = texture;\n\t\ttexture.setFilters(this.minFilter, this.magFilter);\n\t\ttexture.setWraps(this.uWrap, this.vWrap);\n\t\tfor (let region of this.regions)\n\t\t\tregion.texture = texture;\n\t}\n}\n\nexport class TextureAtlasRegion extends TextureRegion {\n\tpage: TextureAtlasPage;\n\tname: string;\n\tx: number = 0;\n\ty: number = 0;\n\toffsetX: number = 0;\n\toffsetY: number = 0;\n\toriginalWidth: number = 0;\n\toriginalHeight: number = 0;\n\tindex: number = 0;\n\tdegrees: number = 0;\n\tnames: string[] | null = null;\n\tvalues: number[][] | null = null;\n\n\tconstructor (page: TextureAtlasPage, name: string) {\n\t\tsuper();\n\t\tthis.page = page;\n\t\tthis.name = name;\n\t\tpage.regions.push(this);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TextureRegion } from \"../Texture.js\";\nimport { TextureAtlasRegion } from \"../TextureAtlas.js\";\nimport { Color, NumberArrayLike, Utils } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Sequence } from \"./Sequence.js\";\nimport { Slot } from \"../Slot.js\";\n\n/** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not\n * supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh.\n *\n * See [Mesh attachments](http://esotericsoftware.com/spine-meshes) in the Spine User Guide. */\nexport class MeshAttachment extends VertexAttachment implements HasTextureRegion {\n\tregion: TextureRegion | null = null;\n\n\t/** The name of the texture region for this attachment. */\n\tpath: string;\n\n\t/** The UV pair for each vertex, normalized within the texture region. */\n\tregionUVs: NumberArrayLike = [];\n\n\t/** The UV pair for each vertex, normalized within the entire texture.\n\t *\n\t * See {@link #updateUVs}. */\n\tuvs: NumberArrayLike = [];\n\n\t/** Triplets of vertex indices which describe the mesh's triangulation. */\n\ttriangles: Array = [];\n\n\t/** The color to tint the mesh. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\t/** The width of the mesh's image. Available only when nonessential data was exported. */\n\twidth: number = 0;\n\n\t/** The height of the mesh's image. Available only when nonessential data was exported. */\n\theight: number = 0;\n\n\t/** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */\n\thullLength: number = 0;\n\n\t/** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if\n\t * nonessential data was exported. Triangulation is not performed at runtime. */\n\tedges: Array = [];\n\n\tprivate parentMesh: MeshAttachment | null = null;\n\n\tsequence: Sequence | null = null;\n\n\ttempColor = new Color(0, 0, 0, 0);\n\n\tconstructor (name: string, path: string) {\n\t\tsuper(name);\n\t\tthis.path = path;\n\t}\n\n\t/** Calculates {@link #uvs} using the {@link #regionUVs} and region. Must be called if the region, the region's properties, or\n\t * the {@link #regionUVs} are changed. */\n\tupdateRegion () {\n\t\tif (!this.region) throw new Error(\"Region not set.\");\n\t\tlet regionUVs = this.regionUVs;\n\t\tif (!this.uvs || this.uvs.length != regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length);\n\t\tlet uvs = this.uvs;\n\t\tlet n = this.uvs.length;\n\t\tlet u = this.region.u, v = this.region.v, width = 0, height = 0;\n\t\tif (this.region instanceof TextureAtlasRegion) {\n\t\t\tlet region = this.region, page = region.page;\n\t\t\tlet textureWidth = page.width, textureHeight = page.height;\n\t\t\tswitch (region.degrees) {\n\t\t\t\tcase 90:\n\t\t\t\t\tu -= (region.originalHeight - region.offsetY - region.height) / textureWidth;\n\t\t\t\t\tv -= (region.originalWidth - region.offsetX - region.width) / textureHeight;\n\t\t\t\t\twidth = region.originalHeight / textureWidth;\n\t\t\t\t\theight = region.originalWidth / textureHeight;\n\t\t\t\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\t\t\t\tuvs[i] = u + regionUVs[i + 1] * width;\n\t\t\t\t\t\tuvs[i + 1] = v + (1 - regionUVs[i]) * height;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\tcase 180:\n\t\t\t\t\tu -= (region.originalWidth - region.offsetX - region.width) / textureWidth;\n\t\t\t\t\tv -= region.offsetY / textureHeight;\n\t\t\t\t\twidth = region.originalWidth / textureWidth;\n\t\t\t\t\theight = region.originalHeight / textureHeight;\n\t\t\t\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\t\t\t\tuvs[i] = u + (1 - regionUVs[i]) * width;\n\t\t\t\t\t\tuvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\tcase 270:\n\t\t\t\t\tu -= region.offsetY / textureWidth;\n\t\t\t\t\tv -= region.offsetX / textureHeight;\n\t\t\t\t\twidth = region.originalHeight / textureWidth;\n\t\t\t\t\theight = region.originalWidth / textureHeight;\n\t\t\t\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\t\t\t\tuvs[i] = u + (1 - regionUVs[i + 1]) * width;\n\t\t\t\t\t\tuvs[i + 1] = v + regionUVs[i] * height;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tu -= region.offsetX / textureWidth;\n\t\t\tv -= (region.originalHeight - region.offsetY - region.height) / textureHeight;\n\t\t\twidth = region.originalWidth / textureWidth;\n\t\t\theight = region.originalHeight / textureHeight;\n\t\t} else if (!this.region) {\n\t\t\tu = v = 0;\n\t\t\twidth = height = 1;\n\t\t} else {\n\t\t\twidth = this.region.u2 - u;\n\t\t\theight = this.region.v2 - v;\n\t\t}\n\n\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\tuvs[i] = u + regionUVs[i] * width;\n\t\t\tuvs[i + 1] = v + regionUVs[i + 1] * height;\n\t\t}\n\t}\n\n\t/** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices},\n\t * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the\n\t * parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */\n\tgetParentMesh () {\n\t\treturn this.parentMesh;\n\t}\n\n\t/** @param parentMesh May be null. */\n\tsetParentMesh (parentMesh: MeshAttachment) {\n\t\tthis.parentMesh = parentMesh;\n\t\tif (parentMesh) {\n\t\t\tthis.bones = parentMesh.bones;\n\t\t\tthis.vertices = parentMesh.vertices;\n\t\t\tthis.worldVerticesLength = parentMesh.worldVerticesLength;\n\t\t\tthis.regionUVs = parentMesh.regionUVs;\n\t\t\tthis.triangles = parentMesh.triangles;\n\t\t\tthis.hullLength = parentMesh.hullLength;\n\t\t\tthis.worldVerticesLength = parentMesh.worldVerticesLength\n\t\t}\n\t}\n\n\tcopy (): Attachment {\n\t\tif (this.parentMesh) return this.newLinkedMesh();\n\n\t\tlet copy = new MeshAttachment(this.name, this.path);\n\t\tcopy.region = this.region;\n\t\tcopy.color.setFromColor(this.color);\n\n\t\tthis.copyTo(copy);\n\t\tcopy.regionUVs = new Array(this.regionUVs.length);\n\t\tUtils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length);\n\t\tcopy.uvs = new Array(this.uvs.length);\n\t\tUtils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length);\n\t\tcopy.triangles = new Array(this.triangles.length);\n\t\tUtils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length);\n\t\tcopy.hullLength = this.hullLength;\n\n\t\tcopy.sequence = this.sequence != null ? this.sequence.copy() : null;\n\n\t\t// Nonessential.\n\t\tif (this.edges) {\n\t\t\tcopy.edges = new Array(this.edges.length);\n\t\t\tUtils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length);\n\t\t}\n\t\tcopy.width = this.width;\n\t\tcopy.height = this.height;\n\n\t\treturn copy;\n\t}\n\n\tcomputeWorldVertices (slot: Slot, start: number, count: number, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tif (this.sequence != null) this.sequence.apply(slot, this);\n\t\tsuper.computeWorldVertices(slot, start, count, worldVertices, offset, stride);\n\t}\n\n\t/** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/\n\tnewLinkedMesh (): MeshAttachment {\n\t\tlet copy = new MeshAttachment(this.name, this.path);\n\t\tcopy.region = this.region;\n\t\tcopy.color.setFromColor(this.color);\n\t\tcopy.timelineAttachment = this.timelineAttachment;\n\t\tcopy.setParentMesh(this.parentMesh ? this.parentMesh : this);\n\t\tif (copy.region != null) copy.updateRegion();\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color, Utils } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment whose vertices make up a composite Bezier curve.\n *\n * See {@link PathConstraint} and [Paths](http://esotericsoftware.com/spine-paths) in the Spine User Guide. */\nexport class PathAttachment extends VertexAttachment {\n\n\t/** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */\n\tlengths: Array = [];\n\n\t/** If true, the start and end knots are connected. */\n\tclosed = false;\n\n\t/** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer\n\t * calculations are performed but calculating positions along the path is less accurate. */\n\tconstantSpeed = false;\n\n\t/** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually\n\t * rendered at runtime. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new PathAttachment(this.name);\n\t\tthis.copyTo(copy);\n\t\tcopy.lengths = new Array(this.lengths.length);\n\t\tUtils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length);\n\t\tcopy.closed = closed;\n\t\tcopy.constantSpeed = this.constantSpeed;\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"../Bone.js\";\nimport { Color, Vector2, MathUtils } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be\n * used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a\n * skin.\n *\n * See [Point Attachments](http://esotericsoftware.com/spine-point-attachments) in the Spine User Guide. */\nexport class PointAttachment extends VertexAttachment {\n\tx: number = 0;\n\ty: number = 0;\n\trotation: number = 0;\n\n\t/** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments\n\t * are not usually rendered at runtime. */\n\tcolor = new Color(0.38, 0.94, 0, 1);\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcomputeWorldPosition (bone: Bone, point: Vector2) {\n\t\tpoint.x = this.x * bone.a + this.y * bone.b + bone.worldX;\n\t\tpoint.y = this.x * bone.c + this.y * bone.d + bone.worldY;\n\t\treturn point;\n\t}\n\n\tcomputeWorldRotation (bone: Bone) {\n\t\tconst r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);\n\t\tconst x = cos * bone.a + sin * bone.b;\n\t\tconst y = cos * bone.c + sin * bone.d;\n\t\treturn MathUtils.atan2Deg(y, x);\t\t\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new PointAttachment(this.name);\n\t\tcopy.x = this.x;\n\t\tcopy.y = this.y;\n\t\tcopy.rotation = this.rotation;\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"../Bone.js\";\nimport { TextureRegion } from \"../Texture.js\";\nimport { Color, MathUtils, NumberArrayLike, Utils } from \"../Utils.js\";\nimport { Attachment } from \"./Attachment.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Sequence } from \"./Sequence.js\";\nimport { Slot } from \"../Slot.js\";\n\n/** An attachment that displays a textured quadrilateral.\n *\n * See [Region attachments](http://esotericsoftware.com/spine-regions) in the Spine User Guide. */\nexport class RegionAttachment extends Attachment implements HasTextureRegion {\n\t/** The local x translation. */\n\tx = 0;\n\n\t/** The local y translation. */\n\ty = 0;\n\n\t/** The local scaleX. */\n\tscaleX = 1;\n\n\t/** The local scaleY. */\n\tscaleY = 1;\n\n\t/** The local rotation. */\n\trotation = 0;\n\n\t/** The width of the region attachment in Spine. */\n\twidth = 0;\n\n\t/** The height of the region attachment in Spine. */\n\theight = 0;\n\n\t/** The color to tint the region attachment. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\t/** The name of the texture region for this attachment. */\n\tpath: string;\n\n\tregion: TextureRegion | null = null;\n\tsequence: Sequence | null = null;\n\n\t/** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex.\n\t *\n\t * See {@link #updateOffset()}. */\n\toffset = Utils.newFloatArray(8);\n\n\tuvs = Utils.newFloatArray(8);\n\n\ttempColor = new Color(1, 1, 1, 1);\n\n\tconstructor (name: string, path: string) {\n\t\tsuper(name);\n\t\tthis.path = path;\n\t}\n\n\t/** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */\n\tupdateRegion (): void {\n\t\tif (!this.region) throw new Error(\"Region not set.\");\n\t\tlet region = this.region;\n\t\tlet uvs = this.uvs;\n\n\t\tif (region == null) {\n\t\t\tuvs[0] = 0;\n\t\t\tuvs[1] = 0;\n\t\t\tuvs[2] = 0;\n\t\t\tuvs[3] = 1;\n\t\t\tuvs[4] = 1;\n\t\t\tuvs[5] = 1;\n\t\t\tuvs[6] = 1;\n\t\t\tuvs[7] = 0;\n\t\t\treturn;\n\t\t}\n\n\t\tlet regionScaleX = this.width / this.region.originalWidth * this.scaleX;\n\t\tlet regionScaleY = this.height / this.region.originalHeight * this.scaleY;\n\t\tlet localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX;\n\t\tlet localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY;\n\t\tlet localX2 = localX + this.region.width * regionScaleX;\n\t\tlet localY2 = localY + this.region.height * regionScaleY;\n\t\tlet radians = this.rotation * MathUtils.degRad;\n\t\tlet cos = Math.cos(radians);\n\t\tlet sin = Math.sin(radians);\n\t\tlet x = this.x, y = this.y;\n\t\tlet localXCos = localX * cos + x;\n\t\tlet localXSin = localX * sin;\n\t\tlet localYCos = localY * cos + y;\n\t\tlet localYSin = localY * sin;\n\t\tlet localX2Cos = localX2 * cos + x;\n\t\tlet localX2Sin = localX2 * sin;\n\t\tlet localY2Cos = localY2 * cos + y;\n\t\tlet localY2Sin = localY2 * sin;\n\t\tlet offset = this.offset;\n\t\toffset[0] = localXCos - localYSin;\n\t\toffset[1] = localYCos + localXSin;\n\t\toffset[2] = localXCos - localY2Sin;\n\t\toffset[3] = localY2Cos + localXSin;\n\t\toffset[4] = localX2Cos - localY2Sin;\n\t\toffset[5] = localY2Cos + localX2Sin;\n\t\toffset[6] = localX2Cos - localYSin;\n\t\toffset[7] = localYCos + localX2Sin;\n\n\t\tif (region.degrees == 90) {\n\t\t\tuvs[0] = region.u2;\n\t\t\tuvs[1] = region.v2;\n\t\t\tuvs[2] = region.u;\n\t\t\tuvs[3] = region.v2;\n\t\t\tuvs[4] = region.u;\n\t\t\tuvs[5] = region.v;\n\t\t\tuvs[6] = region.u2;\n\t\t\tuvs[7] = region.v;\n\t\t} else {\n\t\t\tuvs[0] = region.u;\n\t\t\tuvs[1] = region.v2;\n\t\t\tuvs[2] = region.u;\n\t\t\tuvs[3] = region.v;\n\t\t\tuvs[4] = region.u2;\n\t\t\tuvs[5] = region.v;\n\t\t\tuvs[6] = region.u2;\n\t\t\tuvs[7] = region.v2;\n\t\t}\n\t}\n\n\t/** Transforms the attachment's four vertices to world coordinates. If the attachment has a {@link #sequence}, the region may\n\t * be changed.\n\t *

    \n\t * See World transforms in the Spine\n\t * Runtimes Guide.\n\t * @param worldVertices The output world vertices. Must have a length >= offset + 8.\n\t * @param offset The worldVertices index to begin writing values.\n\t * @param stride The number of worldVertices entries between the value pairs written. */\n\tcomputeWorldVertices (slot: Slot, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tif (this.sequence != null)\n\t\t\tthis.sequence.apply(slot, this);\n\n\t\tlet bone = slot.bone;\n\t\tlet vertexOffset = this.offset;\n\t\tlet x = bone.worldX, y = bone.worldY;\n\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\tlet offsetX = 0, offsetY = 0;\n\n\t\toffsetX = vertexOffset[0];\n\t\toffsetY = vertexOffset[1];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // br\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t\toffset += stride;\n\n\t\toffsetX = vertexOffset[2];\n\t\toffsetY = vertexOffset[3];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // bl\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t\toffset += stride;\n\n\t\toffsetX = vertexOffset[4];\n\t\toffsetY = vertexOffset[5];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // ul\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t\toffset += stride;\n\n\t\toffsetX = vertexOffset[6];\n\t\toffsetY = vertexOffset[7];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // ur\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new RegionAttachment(this.name, this.path);\n\t\tcopy.region = this.region;\n\t\tcopy.x = this.x;\n\t\tcopy.y = this.y;\n\t\tcopy.scaleX = this.scaleX;\n\t\tcopy.scaleY = this.scaleY;\n\t\tcopy.rotation = this.rotation;\n\t\tcopy.width = this.width;\n\t\tcopy.height = this.height;\n\t\tUtils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8);\n\t\tUtils.arrayCopy(this.offset, 0, copy.offset, 0, 8);\n\t\tcopy.color.setFromColor(this.color);\n\t\tcopy.sequence = this.sequence != null ? this.sequence.copy() : null;\n\t\treturn copy;\n\t}\n\n\tstatic X1 = 0;\n\tstatic Y1 = 1;\n\tstatic C1R = 2;\n\tstatic C1G = 3;\n\tstatic C1B = 4;\n\tstatic C1A = 5;\n\tstatic U1 = 6;\n\tstatic V1 = 7;\n\n\tstatic X2 = 8;\n\tstatic Y2 = 9;\n\tstatic C2R = 10;\n\tstatic C2G = 11;\n\tstatic C2B = 12;\n\tstatic C2A = 13;\n\tstatic U2 = 14;\n\tstatic V2 = 15;\n\n\tstatic X3 = 16;\n\tstatic Y3 = 17;\n\tstatic C3R = 18;\n\tstatic C3G = 19;\n\tstatic C3B = 20;\n\tstatic C3A = 21;\n\tstatic U3 = 22;\n\tstatic V3 = 23;\n\n\tstatic X4 = 24;\n\tstatic Y4 = 25;\n\tstatic C4R = 26;\n\tstatic C4G = 27;\n\tstatic C4B = 28;\n\tstatic C4A = 29;\n\tstatic U4 = 30;\n\tstatic V4 = 31;\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { AttachmentLoader } from \"./attachments/AttachmentLoader.js\";\nimport { BoundingBoxAttachment } from \"./attachments/BoundingBoxAttachment.js\";\nimport { ClippingAttachment } from \"./attachments/ClippingAttachment.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { PathAttachment } from \"./attachments/PathAttachment.js\";\nimport { PointAttachment } from \"./attachments/PointAttachment.js\";\nimport { RegionAttachment } from \"./attachments/RegionAttachment.js\";\nimport { Skin } from \"./Skin.js\";\nimport { TextureAtlas } from \"./TextureAtlas.js\";\nimport { Sequence } from \"./attachments/Sequence.js\"\n\n/** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link TextureAtlas}.\n *\n * See [Loading skeleton data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the\n * Spine Runtimes Guide. */\nexport class AtlasAttachmentLoader implements AttachmentLoader {\n\tatlas: TextureAtlas;\n\n\tconstructor (atlas: TextureAtlas) {\n\t\tthis.atlas = atlas;\n\t}\n\n\tloadSequence (name: string, basePath: string, sequence: Sequence) {\n\t\tlet regions = sequence.regions;\n\t\tfor (let i = 0, n = regions.length; i < n; i++) {\n\t\t\tlet path = sequence.getPath(basePath, i);\n\t\t\tlet region = this.atlas.findRegion(path);\n\t\t\tif (region == null) throw new Error(\"Region not found in atlas: \" + path + \" (sequence: \" + name + \")\");\n\t\t\tregions[i] = region;\n\t\t}\n\t}\n\n\tnewRegionAttachment (skin: Skin, name: string, path: string, sequence: Sequence): RegionAttachment {\n\t\tlet attachment = new RegionAttachment(name, path);\n\t\tif (sequence != null) {\n\t\t\tthis.loadSequence(name, path, sequence);\n\t\t} else {\n\t\t\tlet region = this.atlas.findRegion(path);\n\t\t\tif (!region) throw new Error(\"Region not found in atlas: \" + path + \" (region attachment: \" + name + \")\");\n\t\t\tattachment.region = region;\n\t\t}\n\t\treturn attachment;\n\t}\n\n\tnewMeshAttachment (skin: Skin, name: string, path: string, sequence: Sequence): MeshAttachment {\n\t\tlet attachment = new MeshAttachment(name, path);\n\t\tif (sequence != null) {\n\t\t\tthis.loadSequence(name, path, sequence);\n\t\t} else {\n\t\t\tlet region = this.atlas.findRegion(path);\n\t\t\tif (!region) throw new Error(\"Region not found in atlas: \" + path + \" (mesh attachment: \" + name + \")\");\n\t\t\tattachment.region = region;\n\t\t}\n\t\treturn attachment;\n\t}\n\n\tnewBoundingBoxAttachment (skin: Skin, name: string): BoundingBoxAttachment {\n\t\treturn new BoundingBoxAttachment(name);\n\t}\n\n\tnewPathAttachment (skin: Skin, name: string): PathAttachment {\n\t\treturn new PathAttachment(name);\n\t}\n\n\tnewPointAttachment (skin: Skin, name: string): PointAttachment {\n\t\treturn new PointAttachment(name);\n\t}\n\n\tnewClippingAttachment (skin: Skin, name: string): ClippingAttachment {\n\t\treturn new ClippingAttachment(name);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color } from \"./Utils.js\";\n\n/** Stores the setup pose for a {@link Bone}. */\nexport class BoneData {\n\t/** The index of the bone in {@link Skeleton#getBones()}. */\n\tindex: number = 0;\n\n\t/** The name of the bone, which is unique across all bones in the skeleton. */\n\tname: string;\n\n\t/** @returns May be null. */\n\tparent: BoneData | null = null;\n\n\t/** The bone's length. */\n\tlength: number = 0;\n\n\t/** The local x translation. */\n\tx = 0;\n\n\t/** The local y translation. */\n\ty = 0;\n\n\t/** The local rotation in degrees, counter clockwise. */\n\trotation = 0;\n\n\t/** The local scaleX. */\n\tscaleX = 1;\n\n\t/** The local scaleY. */\n\tscaleY = 1;\n\n\t/** The local shearX. */\n\tshearX = 0;\n\n\t/** The local shearX. */\n\tshearY = 0;\n\n\t/** The transform mode for how parent world transforms affect this bone. */\n\tinherit = Inherit.Normal;\n\n\t/** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this\n\t * bone.\n\t * @see Skin#bones */\n\tskinRequired = false;\n\n\t/** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually\n\t * rendered at runtime. */\n\tcolor = new Color();\n\n\t/** The bone icon as it was in Spine, or null if nonessential data was not exported. */\n\ticon?: string;\n\n\t/** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */\n\tvisible = false;\n\n\tconstructor (index: number, name: string, parent: BoneData | null) {\n\t\tif (index < 0) throw new Error(\"index must be >= 0.\");\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.index = index;\n\t\tthis.name = name;\n\t\tthis.parent = parent;\n\t}\n}\n\n/** Determines how a bone inherits world transforms from parent bones. */\nexport enum Inherit { Normal, OnlyTranslation, NoRotationOrReflection, NoScale, NoScaleOrReflection }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData, Inherit } from \"./BoneData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { MathUtils, Vector2 } from \"./Utils.js\";\n\n/** Stores a bone's current pose.\n *\n * A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a\n * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a\n * constraint or application code modifies the world transform after it was computed from the local transform. */\nexport class Bone implements Updatable {\n\t/** The bone's setup pose data. */\n\tdata: BoneData;\n\n\t/** The skeleton this bone belongs to. */\n\tskeleton: Skeleton;\n\n\t/** The parent bone, or null if this is the root bone. */\n\tparent: Bone | null = null;\n\n\t/** The immediate children of this bone. */\n\tchildren = new Array();\n\n\t/** The local x translation. */\n\tx = 0;\n\n\t/** The local y translation. */\n\ty = 0;\n\n\t/** The local rotation in degrees, counter clockwise. */\n\trotation = 0;\n\n\t/** The local scaleX. */\n\tscaleX = 0;\n\n\t/** The local scaleY. */\n\tscaleY = 0;\n\n\t/** The local shearX. */\n\tshearX = 0;\n\n\t/** The local shearY. */\n\tshearY = 0;\n\n\t/** The applied local x translation. */\n\tax = 0;\n\n\t/** The applied local y translation. */\n\tay = 0;\n\n\t/** The applied local rotation in degrees, counter clockwise. */\n\tarotation = 0;\n\n\t/** The applied local scaleX. */\n\tascaleX = 0;\n\n\t/** The applied local scaleY. */\n\tascaleY = 0;\n\n\t/** The applied local shearX. */\n\tashearX = 0;\n\n\t/** The applied local shearY. */\n\tashearY = 0;\n\n\t/** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\ta = 0;\n\n\t/** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\tb = 0;\n\n\t/** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\tc = 0;\n\n\t/** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\td = 0;\n\n\t/** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */\n\tworldY = 0;\n\n\t/** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */\n\tworldX = 0;\n\n\tinherit: Inherit = Inherit.Normal;\n\n\tsorted = false;\n\tactive = false;\n\n\t/** @param parent May be null. */\n\tconstructor (data: BoneData, skeleton: Skeleton, parent: Bone | null) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\t\tthis.skeleton = skeleton;\n\t\tthis.parent = parent;\n\t\tthis.setToSetupPose();\n\t}\n\n\t/** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the\n\t * {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\t/** Computes the world transform using the parent bone and this bone's local applied transform. */\n\tupdate (physics: Physics) {\n\t\tthis.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY);\n\t}\n\n\t/** Computes the world transform using the parent bone and this bone's local transform.\n\t *\n\t * See {@link #updateWorldTransformWith()}. */\n\tupdateWorldTransform () {\n\t\tthis.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);\n\t}\n\n\t/** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the\n\t * specified local transform. Child bones are not updated.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide. */\n\tupdateWorldTransformWith (x: number, y: number, rotation: number, scaleX: number, scaleY: number, shearX: number, shearY: number) {\n\t\tthis.ax = x;\n\t\tthis.ay = y;\n\t\tthis.arotation = rotation;\n\t\tthis.ascaleX = scaleX;\n\t\tthis.ascaleY = scaleY;\n\t\tthis.ashearX = shearX;\n\t\tthis.ashearY = shearY;\n\n\t\tlet parent = this.parent;\n\t\tif (!parent) { // Root bone.\n\t\t\tlet skeleton = this.skeleton;\n\t\t\tconst sx = skeleton.scaleX, sy = skeleton.scaleY;\n\t\t\tconst rx = (rotation + shearX) * MathUtils.degRad;\n\t\t\tconst ry = (rotation + 90 + shearY) * MathUtils.degRad;\n\t\t\tthis.a = Math.cos(rx) * scaleX * sx;\n\t\t\tthis.b = Math.cos(ry) * scaleY * sx;\n\t\t\tthis.c = Math.sin(rx) * scaleX * sy;\n\t\t\tthis.d = Math.sin(ry) * scaleY * sy;\n\t\t\tthis.worldX = x * sx + skeleton.x;\n\t\t\tthis.worldY = y * sy + skeleton.y;\n\t\t\treturn;\n\t\t}\n\n\t\tlet pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;\n\t\tthis.worldX = pa * x + pb * y + parent.worldX;\n\t\tthis.worldY = pc * x + pd * y + parent.worldY;\n\n\t\tswitch (this.inherit) {\n\t\t\tcase Inherit.Normal: {\n\t\t\t\tconst rx = (rotation + shearX) * MathUtils.degRad;\n\t\t\t\tconst ry = (rotation + 90 + shearY) * MathUtils.degRad;\n\t\t\t\tconst la = Math.cos(rx) * scaleX;\n\t\t\t\tconst lb = Math.cos(ry) * scaleY;\n\t\t\t\tconst lc = Math.sin(rx) * scaleX;\n\t\t\t\tconst ld = Math.sin(ry) * scaleY;\n\t\t\t\tthis.a = pa * la + pb * lc;\n\t\t\t\tthis.b = pa * lb + pb * ld;\n\t\t\t\tthis.c = pc * la + pd * lc;\n\t\t\t\tthis.d = pc * lb + pd * ld;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase Inherit.OnlyTranslation: {\n\t\t\t\tconst rx = (rotation + shearX) * MathUtils.degRad;\n\t\t\t\tconst ry = (rotation + 90 + shearY) * MathUtils.degRad;\n\t\t\t\tthis.a = Math.cos(rx) * scaleX;\n\t\t\t\tthis.b = Math.cos(ry) * scaleY;\n\t\t\t\tthis.c = Math.sin(rx) * scaleX;\n\t\t\t\tthis.d = Math.sin(ry) * scaleY;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Inherit.NoRotationOrReflection: {\n\t\t\t\tlet sx = 1 / this.skeleton.scaleX, sy = 1 / this.skeleton.scaleY;\n\t\t\t\tpa *= sx;\n\t\t\t\tpc *= sy;\n\t\t\t\tlet s = pa * pa + pc * pc;\n\t\t\t\tlet prx = 0;\n\t\t\t\tif (s > 0.0001) {\n\t\t\t\t\ts = Math.abs(pa * pd * sy - pb * sx * pc) / s;\n\t\t\t\t\tpb = pc * s;\n\t\t\t\t\tpd = pa * s;\n\t\t\t\t\tprx = Math.atan2(pc, pa) * MathUtils.radDeg;\n\t\t\t\t} else {\n\t\t\t\t\tpa = 0;\n\t\t\t\t\tpc = 0;\n\t\t\t\t\tprx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg;\n\t\t\t\t}\n\t\t\t\tconst rx = (rotation + shearX - prx) * MathUtils.degRad;\n\t\t\t\tconst ry = (rotation + shearY - prx + 90) * MathUtils.degRad;\n\t\t\t\tconst la = Math.cos(rx) * scaleX;\n\t\t\t\tconst lb = Math.cos(ry) * scaleY;\n\t\t\t\tconst lc = Math.sin(rx) * scaleX;\n\t\t\t\tconst ld = Math.sin(ry) * scaleY;\n\t\t\t\tthis.a = pa * la - pb * lc;\n\t\t\t\tthis.b = pa * lb - pb * ld;\n\t\t\t\tthis.c = pc * la + pd * lc;\n\t\t\t\tthis.d = pc * lb + pd * ld;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Inherit.NoScale:\n\t\t\tcase Inherit.NoScaleOrReflection: {\n\t\t\t\trotation *= MathUtils.degRad;\n\t\t\t\tconst cos = Math.cos(rotation), sin = Math.sin(rotation);\n\t\t\t\tlet za = (pa * cos + pb * sin) / this.skeleton.scaleX;\n\t\t\t\tlet zc = (pc * cos + pd * sin) / this.skeleton.scaleY;\n\t\t\t\tlet s = Math.sqrt(za * za + zc * zc);\n\t\t\t\tif (s > 0.00001) s = 1 / s;\n\t\t\t\tza *= s;\n\t\t\t\tzc *= s;\n\t\t\t\ts = Math.sqrt(za * za + zc * zc);\n\t\t\t\tif (this.inherit == Inherit.NoScale\n\t\t\t\t\t&& (pa * pd - pb * pc < 0) != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) s = -s;\n\t\t\t\trotation = Math.PI / 2 + Math.atan2(zc, za);\n\t\t\t\tconst zb = Math.cos(rotation) * s;\n\t\t\t\tconst zd = Math.sin(rotation) * s;\n\t\t\t\tshearX *= MathUtils.degRad;\n\t\t\t\tshearY = (90 + shearY) * MathUtils.degRad;\n\t\t\t\tconst la = Math.cos(shearX) * scaleX;\n\t\t\t\tconst lb = Math.cos(shearY) * scaleY;\n\t\t\t\tconst lc = Math.sin(shearX) * scaleX;\n\t\t\t\tconst ld = Math.sin(shearY) * scaleY;\n\t\t\t\tthis.a = za * la + zb * lc;\n\t\t\t\tthis.b = za * lb + zb * ld;\n\t\t\t\tthis.c = zc * la + zd * lc;\n\t\t\t\tthis.d = zc * lb + zd * ld;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.a *= this.skeleton.scaleX;\n\t\tthis.b *= this.skeleton.scaleX;\n\t\tthis.c *= this.skeleton.scaleY;\n\t\tthis.d *= this.skeleton.scaleY;\n\t}\n\n\t/** Sets this bone's local transform to the setup pose. */\n\tsetToSetupPose () {\n\t\tlet data = this.data;\n\t\tthis.x = data.x;\n\t\tthis.y = data.y;\n\t\tthis.rotation = data.rotation;\n\t\tthis.scaleX = data.scaleX;\n\t\tthis.scaleY = data.scaleY;\n\t\tthis.shearX = data.shearX;\n\t\tthis.shearY = data.shearY;\n\t\tthis.inherit = data.inherit;\n\t}\n\n\t/** Computes the applied transform values from the world transform.\n\t *\n\t * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, etc) then this method should be called so\n\t * the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply other\n\t * constraints).\n\t *\n\t * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after\n\t * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */\n\tupdateAppliedTransform () {\n\t\tlet parent = this.parent;\n\t\tif (!parent) {\n\t\t\tthis.ax = this.worldX - this.skeleton.x;\n\t\t\tthis.ay = this.worldY - this.skeleton.y;\n\t\t\tthis.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg;\n\t\t\tthis.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c);\n\t\t\tthis.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d);\n\t\t\tthis.ashearX = 0;\n\t\t\tthis.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg;\n\t\t\treturn;\n\t\t}\n\t\tlet pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;\n\t\tlet pid = 1 / (pa * pd - pb * pc);\n\t\tlet ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;\n\t\tlet dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY;\n\t\tthis.ax = (dx * ia - dy * ib);\n\t\tthis.ay = (dy * id - dx * ic);\n\n\t\tlet ra, rb, rc, rd;\n\t\tif (this.inherit == Inherit.OnlyTranslation) {\n\t\t\tra = this.a;\n\t\t\trb = this.b;\n\t\t\trc = this.c;\n\t\t\trd = this.d;\n\t\t} else {\n\t\t\tswitch (this.inherit) {\n\t\t\t\tcase Inherit.NoRotationOrReflection: {\n\t\t\t\t\tlet s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);\n\t\t\t\t\tpb = -pc * this.skeleton.scaleX * s / this.skeleton.scaleY;\n\t\t\t\t\tpd = pa * this.skeleton.scaleY * s / this.skeleton.scaleX;\n\t\t\t\t\tpid = 1 / (pa * pd - pb * pc);\n\t\t\t\t\tia = pd * pid;\n\t\t\t\t\tib = pb * pid;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase Inherit.NoScale:\n\t\t\t\tcase Inherit.NoScaleOrReflection:\n\t\t\t\t\tlet cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation);\n\t\t\t\t\tpa = (pa * cos + pb * sin) / this.skeleton.scaleX;\n\t\t\t\t\tpc = (pc * cos + pd * sin) / this.skeleton.scaleY;\n\t\t\t\t\tlet s = Math.sqrt(pa * pa + pc * pc);\n\t\t\t\t\tif (s > 0.00001) s = 1 / s;\n\t\t\t\t\tpa *= s;\n\t\t\t\t\tpc *= s;\n\t\t\t\t\ts = Math.sqrt(pa * pa + pc * pc);\n\t\t\t\t\tif (this.inherit == Inherit.NoScale && pid < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) s = -s;\n\t\t\t\t\tlet r = MathUtils.PI / 2 + Math.atan2(pc, pa);\n\t\t\t\t\tpb = Math.cos(r) * s;\n\t\t\t\t\tpd = Math.sin(r) * s;\n\t\t\t\t\tpid = 1 / (pa * pd - pb * pc);\n\t\t\t\t\tia = pd * pid;\n\t\t\t\t\tib = pb * pid;\n\t\t\t\t\tic = pc * pid;\n\t\t\t\t\tid = pa * pid;\n\t\t\t}\n\t\t\tra = ia * this.a - ib * this.c;\n\t\t\trb = ia * this.b - ib * this.d;\n\t\t\trc = id * this.c - ic * this.a;\n\t\t\trd = id * this.d - ic * this.b;\n\t\t}\n\n\t\tthis.ashearX = 0;\n\t\tthis.ascaleX = Math.sqrt(ra * ra + rc * rc);\n\t\tif (this.ascaleX > 0.0001) {\n\t\t\tlet det = ra * rd - rb * rc;\n\t\t\tthis.ascaleY = det / this.ascaleX;\n\t\t\tthis.ashearY = -Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;\n\t\t\tthis.arotation = Math.atan2(rc, ra) * MathUtils.radDeg;\n\t\t} else {\n\t\t\tthis.ascaleX = 0;\n\t\t\tthis.ascaleY = Math.sqrt(rb * rb + rd * rd);\n\t\t\tthis.ashearY = 0;\n\t\t\tthis.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;\n\t\t}\n\t}\n\n\n\t/** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */\n\tgetWorldRotationX () {\n\t\treturn Math.atan2(this.c, this.a) * MathUtils.radDeg;\n\t}\n\n\t/** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */\n\tgetWorldRotationY () {\n\t\treturn Math.atan2(this.d, this.b) * MathUtils.radDeg;\n\t}\n\n\t/** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */\n\tgetWorldScaleX () {\n\t\treturn Math.sqrt(this.a * this.a + this.c * this.c);\n\t}\n\n\t/** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */\n\tgetWorldScaleY () {\n\t\treturn Math.sqrt(this.b * this.b + this.d * this.d);\n\t}\n\n\t/** Transforms a point from world coordinates to the bone's local coordinates. */\n\tworldToLocal (world: Vector2) {\n\t\tlet invDet = 1 / (this.a * this.d - this.b * this.c);\n\t\tlet x = world.x - this.worldX, y = world.y - this.worldY;\n\t\tworld.x = x * this.d * invDet - y * this.b * invDet;\n\t\tworld.y = y * this.a * invDet - x * this.c * invDet;\n\t\treturn world;\n\t}\n\n\t/** Transforms a point from the bone's local coordinates to world coordinates. */\n\tlocalToWorld (local: Vector2) {\n\t\tlet x = local.x, y = local.y;\n\t\tlocal.x = x * this.a + y * this.b + this.worldX;\n\t\tlocal.y = x * this.c + y * this.d + this.worldY;\n\t\treturn local;\n\t}\n\n\t/** Transforms a point from world coordinates to the parent bone's local coordinates. */\n\tworldToParent (world: Vector2) {\n\t\tif (world == null) throw new Error(\"world cannot be null.\");\n\t\treturn this.parent == null ? world : this.parent.worldToLocal(world);\n\t}\n\n\t/** Transforms a point from the parent bone's coordinates to world coordinates. */\n\tparentToWorld (world: Vector2) {\n\t\tif (world == null) throw new Error(\"world cannot be null.\");\n\t\treturn this.parent == null ? world : this.parent.localToWorld(world);\n\t}\n\n\t/** Transforms a world rotation to a local rotation. */\n\tworldToLocalRotation (worldRotation: number) {\n\t\tlet sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation);\n\t\treturn Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX;\n\t}\n\n\t/** Transforms a local rotation to a world rotation. */\n\tlocalToWorldRotation (localRotation: number) {\n\t\tlocalRotation -= this.rotation - this.shearX;\n\t\tlet sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation);\n\t\treturn Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg;\n\t}\n\n\t/** Rotates the world transform the specified amount.\n\t *

    \n\t * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and\n\t * {@link #update(Physics)} will need to be called on any child bones, recursively. */\n\trotateWorld (degrees: number) {\n\t\tdegrees *= MathUtils.degRad;\n\t\tconst sin = Math.sin(degrees), cos = Math.cos(degrees);\n\t\tconst ra = this.a, rb = this.b;\n\t\tthis.a = cos * ra - sin * this.c;\n\t\tthis.b = cos * rb - sin * this.d;\n\t\tthis.c = sin * ra + cos * this.c;\n\t\tthis.d = sin * rb + cos * this.d;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\n/** The base class for all constraint datas. */\nexport abstract class ConstraintData {\n\tconstructor (public name: string, public order: number, public skinRequired: boolean) { }\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture } from \"./Texture.js\";\nimport { TextureAtlas } from \"./TextureAtlas.js\";\nimport { Disposable, StringMap } from \"./Utils.js\";\n\nexport class AssetManagerBase implements Disposable {\n\tprivate pathPrefix: string = \"\";\n\tprivate textureLoader: (image: HTMLImageElement | ImageBitmap) => Texture;\n\tprivate downloader: Downloader;\n\tprivate assets: StringMap = {};\n\tprivate errors: StringMap = {};\n\tprivate toLoad = 0;\n\tprivate loaded = 0;\n\n\tconstructor (textureLoader: (image: HTMLImageElement | ImageBitmap) => Texture, pathPrefix: string = \"\", downloader: Downloader = new Downloader()) {\n\t\tthis.textureLoader = textureLoader;\n\t\tthis.pathPrefix = pathPrefix;\n\t\tthis.downloader = downloader;\n\t}\n\n\tprivate start (path: string): string {\n\t\tthis.toLoad++;\n\t\treturn this.pathPrefix + path;\n\t}\n\n\tprivate success (callback: (path: string, data: any) => void, path: string, asset: any) {\n\t\tthis.toLoad--;\n\t\tthis.loaded++;\n\t\tthis.assets[path] = asset;\n\t\tif (callback) callback(path, asset);\n\t}\n\n\tprivate error (callback: (path: string, message: string) => void, path: string, message: string) {\n\t\tthis.toLoad--;\n\t\tthis.loaded++;\n\t\tthis.errors[path] = message;\n\t\tif (callback) callback(path, message);\n\t}\n\n\tloadAll () {\n\t\tlet promise = new Promise((resolve: (assetManager: AssetManagerBase) => void, reject: (errors: StringMap) => void) => {\n\t\t\tlet check = () => {\n\t\t\t\tif (this.isLoadingComplete()) {\n\t\t\t\t\tif (this.hasErrors()) reject(this.errors);\n\t\t\t\t\telse resolve(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\trequestAnimationFrame(check);\n\t\t\t}\n\t\t\trequestAnimationFrame(check);\n\t\t});\n\t\treturn promise;\n\t}\n\n\tsetRawDataURI (path: string, data: string) {\n\t\tthis.downloader.rawDataUris[this.pathPrefix + path] = data;\n\t}\n\n\tloadBinary (path: string,\n\t\tsuccess: (path: string, binary: Uint8Array) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadBinary(path, (data: Uint8Array): void => {\n\t\t\tthis.success(success, path, data);\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tloadText (path: string,\n\t\tsuccess: (path: string, text: string) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadText(path, (data: string): void => {\n\t\t\tthis.success(success, path, data);\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tloadJson (path: string,\n\t\tsuccess: (path: string, object: object) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadJson(path, (data: object): void => {\n\t\t\tthis.success(success, path, data);\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tloadTexture (path: string,\n\t\tsuccess: (path: string, texture: Texture) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tlet isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document);\n\t\tlet isWebWorker = !isBrowser; // && typeof importScripts !== 'undefined';\n\t\tif (isWebWorker) {\n\t\t\tfetch(path, { mode: \"cors\" }).then((response) => {\n\t\t\t\tif (response.ok) return response.blob();\n\t\t\t\tthis.error(error, path, `Couldn't load image: ${path}`);\n\t\t\t\treturn null;\n\t\t\t}).then((blob) => {\n\t\t\t\treturn blob ? createImageBitmap(blob, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" }) : null;\n\t\t\t}).then((bitmap) => {\n\t\t\t\tif (bitmap) this.success(success, path, this.textureLoader(bitmap));\n\t\t\t});\n\t\t} else {\n\t\t\tlet image = new Image();\n\t\t\timage.crossOrigin = \"anonymous\";\n\t\t\timage.onload = () => {\n\t\t\t\tthis.success(success, path, this.textureLoader(image));\n\t\t\t};\n\t\t\timage.onerror = () => {\n\t\t\t\tthis.error(error, path, `Couldn't load image: ${path}`);\n\t\t\t};\n\t\t\tif (this.downloader.rawDataUris[path]) path = this.downloader.rawDataUris[path];\n\t\t\timage.src = path;\n\t\t}\n\t}\n\n\tloadTextureAtlas (path: string,\n\t\tsuccess: (path: string, atlas: TextureAtlas) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { },\n\t\tfileAlias?: { [keyword: string]: string }\n\t) {\n\t\tlet index = path.lastIndexOf(\"/\");\n\t\tlet parent = index >= 0 ? path.substring(0, index + 1) : \"\";\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadText(path, (atlasText: string): void => {\n\t\t\ttry {\n\t\t\t\tlet atlas = new TextureAtlas(atlasText);\n\t\t\t\tlet toLoad = atlas.pages.length, abort = false;\n\t\t\t\tfor (let page of atlas.pages) {\n\t\t\t\t\tthis.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name!],\n\t\t\t\t\t\t(imagePath: string, texture: Texture) => {\n\t\t\t\t\t\t\tif (!abort) {\n\t\t\t\t\t\t\t\tpage.setTexture(texture);\n\t\t\t\t\t\t\t\tif (--toLoad == 0) this.success(success, path, atlas);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(imagePath: string, message: string) => {\n\t\t\t\t\t\t\tif (!abort) this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`);\n\t\t\t\t\t\t\tabort = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tthis.error(error, path, `Couldn't parse texture atlas ${path}: ${(e as any).message}`);\n\t\t\t}\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tget (path: string) {\n\t\treturn this.assets[this.pathPrefix + path];\n\t}\n\n\trequire (path: string) {\n\t\tpath = this.pathPrefix + path;\n\t\tlet asset = this.assets[path];\n\t\tif (asset) return asset;\n\t\tlet error = this.errors[path];\n\t\tthrow Error(\"Asset not found: \" + path + (error ? \"\\n\" + error : \"\"));\n\t}\n\n\tremove (path: string) {\n\t\tpath = this.pathPrefix + path;\n\t\tlet asset = this.assets[path];\n\t\tif ((asset).dispose) (asset).dispose();\n\t\tdelete this.assets[path];\n\t\treturn asset;\n\t}\n\n\tremoveAll () {\n\t\tfor (let key in this.assets) {\n\t\t\tlet asset = this.assets[key];\n\t\t\tif ((asset).dispose) (asset).dispose();\n\t\t}\n\t\tthis.assets = {};\n\t}\n\n\tisLoadingComplete (): boolean {\n\t\treturn this.toLoad == 0;\n\t}\n\n\tgetToLoad (): number {\n\t\treturn this.toLoad;\n\t}\n\n\tgetLoaded (): number {\n\t\treturn this.loaded;\n\t}\n\n\tdispose () {\n\t\tthis.removeAll();\n\t}\n\n\thasErrors () {\n\t\treturn Object.keys(this.errors).length > 0;\n\t}\n\n\tgetErrors () {\n\t\treturn this.errors;\n\t}\n}\n\nexport class Downloader {\n\tprivate callbacks: StringMap> = {};\n\trawDataUris: StringMap = {};\n\n\tdataUriToString (dataUri: string) {\n\t\tif (!dataUri.startsWith(\"data:\")) {\n\t\t\tthrow new Error(\"Not a data URI.\");\n\t\t}\n\n\t\tlet base64Idx = dataUri.indexOf(\"base64,\");\n\t\tif (base64Idx != -1) {\n\t\t\tbase64Idx += \"base64,\".length;\n\t\t\treturn atob(dataUri.substr(base64Idx));\n\t\t} else {\n\t\t\treturn dataUri.substr(dataUri.indexOf(\",\") + 1);\n\t\t}\n\t}\n\n\tbase64ToUint8Array (base64: string) {\n\t\tvar binary_string = window.atob(base64);\n\t\tvar len = binary_string.length;\n\t\tvar bytes = new Uint8Array(len);\n\t\tfor (var i = 0; i < len; i++) {\n\t\t\tbytes[i] = binary_string.charCodeAt(i);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tdataUriToUint8Array (dataUri: string) {\n\t\tif (!dataUri.startsWith(\"data:\")) {\n\t\t\tthrow new Error(\"Not a data URI.\");\n\t\t}\n\n\t\tlet base64Idx = dataUri.indexOf(\"base64,\");\n\t\tif (base64Idx == -1) throw new Error(\"Not a binary data URI.\");\n\t\tbase64Idx += \"base64,\".length;\n\t\treturn this.base64ToUint8Array(dataUri.substr(base64Idx));\n\t}\n\n\tdownloadText (url: string, success: (data: string) => void, error: (status: number, responseText: string) => void) {\n\t\tif (this.start(url, success, error)) return;\n\t\tif (this.rawDataUris[url]) {\n\t\t\ttry {\n\t\t\t\tlet dataUri = this.rawDataUris[url];\n\t\t\t\tthis.finish(url, 200, this.dataUriToString(dataUri));\n\t\t\t} catch (e) {\n\t\t\t\tthis.finish(url, 400, JSON.stringify(e));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet request = new XMLHttpRequest();\n\t\trequest.overrideMimeType(\"text/html\");\n\t\trequest.open(\"GET\", url, true);\n\t\tlet done = () => {\n\t\t\tthis.finish(url, request.status, request.responseText);\n\t\t};\n\t\trequest.onload = done;\n\t\trequest.onerror = done;\n\t\trequest.send();\n\t}\n\n\tdownloadJson (url: string, success: (data: object) => void, error: (status: number, responseText: string) => void) {\n\t\tthis.downloadText(url, (data: string): void => {\n\t\t\tsuccess(JSON.parse(data));\n\t\t}, error);\n\t}\n\n\tdownloadBinary (url: string, success: (data: Uint8Array) => void, error: (status: number, responseText: string) => void) {\n\t\tif (this.start(url, success, error)) return;\n\t\tif (this.rawDataUris[url]) {\n\t\t\ttry {\n\t\t\t\tlet dataUri = this.rawDataUris[url];\n\t\t\t\tthis.finish(url, 200, this.dataUriToUint8Array(dataUri));\n\t\t\t} catch (e) {\n\t\t\t\tthis.finish(url, 400, JSON.stringify(e));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\t\tlet onerror = () => {\n\t\t\tthis.finish(url, request.status, request.response);\n\t\t};\n\t\trequest.onload = () => {\n\t\t\tif (request.status == 200 || request.status == 0)\n\t\t\t\tthis.finish(url, 200, new Uint8Array(request.response as ArrayBuffer));\n\t\t\telse\n\t\t\t\tonerror();\n\t\t};\n\t\trequest.onerror = onerror;\n\t\trequest.send();\n\t}\n\n\tprivate start (url: string, success: any, error: any) {\n\t\tlet callbacks = this.callbacks[url];\n\t\ttry {\n\t\t\tif (callbacks) return true;\n\t\t\tthis.callbacks[url] = callbacks = [];\n\t\t} finally {\n\t\t\tcallbacks.push(success, error);\n\t\t}\n\t}\n\n\tprivate finish (url: string, status: number, data: any) {\n\t\tlet callbacks = this.callbacks[url];\n\t\tdelete this.callbacks[url];\n\t\tlet args = status == 200 || status == 0 ? [data] : [status, data];\n\t\tfor (let i = args.length - 1, n = callbacks.length; i < n; i += 2)\n\t\t\tcallbacks[i].apply(null, args);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { EventData } from \"./EventData.js\";\n\n/** Stores the current pose values for an {@link Event}.\n *\n * See Timeline {@link Timeline#apply()},\n * AnimationStateListener {@link AnimationStateListener#event()}, and\n * [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */\nexport class Event {\n\tdata: EventData;\n\tintValue: number = 0;\n\tfloatValue: number = 0;\n\tstringValue: string | null = null;\n\ttime: number = 0;\n\tvolume: number = 0;\n\tbalance: number = 0;\n\n\tconstructor (time: number, data: EventData) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tthis.time = time;\n\t\tthis.data = data;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\n/** Stores the setup pose values for an {@link Event}.\n *\n * See [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */\nexport class EventData {\n\tname: string;\n\tintValue: number = 0;\n\tfloatValue: number = 0;\n\tstringValue: string | null = null;\n\taudioPath: string | null = null;\n\tvolume: number = 0;\n\tbalance: number = 0;\n\n\tconstructor (name: string) {\n\t\tthis.name = name;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"./Bone.js\";\nimport { Inherit } from \"./BoneData.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { MathUtils } from \"./Utils.js\";\n\n/** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of\n * the last bone is as close to the target bone as possible.\n *\n * See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */\nexport class IkConstraint implements Updatable {\n\t/** The IK constraint's setup pose data. */\n\tdata: IkConstraintData;\n\n\t/** The bones that will be modified by this IK constraint. */\n\tbones: Array;\n\n\t/** The bone that is the IK target. */\n\ttarget: Bone;\n\n\t/** Controls the bend direction of the IK bones, either 1 or -1. */\n\tbendDirection = 0;\n\n\t/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */\n\tcompress = false;\n\n\t/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained\n\t * and the parent bone has local nonuniform scale, stretch is not applied. */\n\tstretch = false;\n\n\t/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */\n\tmix = 1;\n\n\t/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */\n\tsoftness = 0;\n\tactive = false;\n\n\tconstructor (data: IkConstraintData, skeleton: Skeleton) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0; i < data.bones.length; i++) {\n\t\t\tlet bone = skeleton.findBone(data.bones[i].name);\n\t\t\tif (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}`);\n\t\t\tthis.bones.push(bone);\n\t\t}\n\t\tlet target = skeleton.findBone(data.target.name);\n\t\tif (!target) throw new Error(`Couldn't find bone ${data.target.name}`);\n\n\t\tthis.target = target;\n\t\tthis.mix = data.mix;\n\t\tthis.softness = data.softness;\n\t\tthis.bendDirection = data.bendDirection;\n\t\tthis.compress = data.compress;\n\t\tthis.stretch = data.stretch;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.mix = data.mix;\n\t\tthis.softness = data.softness;\n\t\tthis.bendDirection = data.bendDirection;\n\t\tthis.compress = data.compress;\n\t\tthis.stretch = data.stretch;\n\t}\n\n\tupdate (physics: Physics) {\n\t\tif (this.mix == 0) return;\n\t\tlet target = this.target;\n\t\tlet bones = this.bones;\n\t\tswitch (bones.length) {\n\t\t\tcase 1:\n\t\t\t\tthis.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tthis.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/** Applies 1 bone IK. The target is specified in the world coordinate system. */\n\tapply1 (bone: Bone, targetX: number, targetY: number, compress: boolean, stretch: boolean, uniform: boolean, alpha: number) {\n\t\tlet p = bone.parent;\n\t\tif (!p) throw new Error(\"IK bone must have parent.\");\n\t\tlet pa = p.a, pb = p.b, pc = p.c, pd = p.d;\n\t\tlet rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;\n\n\t\tswitch (bone.inherit) {\n\t\t\tcase Inherit.OnlyTranslation:\n\t\t\t\ttx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX);\n\t\t\t\tty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY);\n\t\t\t\tbreak;\n\t\t\tcase Inherit.NoRotationOrReflection:\n\t\t\t\tlet s = Math.abs(pa * pd - pb * pc) / Math.max(0.0001, pa * pa + pc * pc);\n\t\t\t\tlet sa = pa / bone.skeleton.scaleX;\n\t\t\t\tlet sc = pc / bone.skeleton.scaleY;\n\t\t\t\tpb = -sc * s * bone.skeleton.scaleX;\n\t\t\t\tpd = sa * s * bone.skeleton.scaleY;\n\t\t\t\trotationIK += Math.atan2(sc, sa) * MathUtils.radDeg;\n\t\t\t// Fall through\n\t\t\tdefault:\n\t\t\t\tlet x = targetX - p.worldX, y = targetY - p.worldY;\n\t\t\t\tlet d = pa * pd - pb * pc;\n\t\t\t\tif (Math.abs(d) <= 0.0001) {\n\t\t\t\t\ttx = 0;\n\t\t\t\t\tty = 0;\n\t\t\t\t} else {\n\t\t\t\t\ttx = (x * pd - y * pb) / d - bone.ax;\n\t\t\t\t\tty = (y * pa - x * pc) / d - bone.ay;\n\t\t\t\t}\n\t\t}\n\t\trotationIK += Math.atan2(ty, tx) * MathUtils.radDeg;\n\t\tif (bone.ascaleX < 0) rotationIK += 180;\n\t\tif (rotationIK > 180)\n\t\t\trotationIK -= 360;\n\t\telse if (rotationIK < -180)\n\t\t\trotationIK += 360;\n\t\tlet sx = bone.ascaleX, sy = bone.ascaleY;\n\t\tif (compress || stretch) {\n\t\t\tswitch (bone.inherit) {\n\t\t\t\tcase Inherit.NoScale:\n\t\t\t\tcase Inherit.NoScaleOrReflection:\n\t\t\t\t\ttx = targetX - bone.worldX;\n\t\t\t\t\tty = targetY - bone.worldY;\n\t\t\t}\n\t\t\tconst b = bone.data.length * sx;\n\t\t\tif (b > 0.0001) {\n\t\t\t\tconst dd = tx * tx + ty * ty;\n\t\t\t\tif ((compress && dd < b * b) || (stretch && dd > b * b)) {\n\t\t\t\t\tconst s = (Math.sqrt(dd) / b - 1) * alpha + 1;\n\t\t\t\t\tsx *= s;\n\t\t\t\t\tif (uniform) sy *= s;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX,\n\t\t\tbone.ashearY);\n\t}\n\n\t/** Applies 2 bone IK. The target is specified in the world coordinate system.\n\t * @param child A direct descendant of the parent bone. */\n\tapply2 (parent: Bone, child: Bone, targetX: number, targetY: number, bendDir: number, stretch: boolean, uniform: boolean, softness: number, alpha: number) {\n\t\tif (parent.inherit != Inherit.Normal || child.inherit != Inherit.Normal) return;\n\t\tlet px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX;\n\t\tlet os1 = 0, os2 = 0, s2 = 0;\n\t\tif (psx < 0) {\n\t\t\tpsx = -psx;\n\t\t\tos1 = 180;\n\t\t\ts2 = -1;\n\t\t} else {\n\t\t\tos1 = 0;\n\t\t\ts2 = 1;\n\t\t}\n\t\tif (psy < 0) {\n\t\t\tpsy = -psy;\n\t\t\ts2 = -s2;\n\t\t}\n\t\tif (csx < 0) {\n\t\t\tcsx = -csx;\n\t\t\tos2 = 180;\n\t\t} else\n\t\t\tos2 = 0;\n\t\tlet cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d;\n\t\tlet u = Math.abs(psx - psy) <= 0.0001;\n\t\tif (!u || stretch) {\n\t\t\tcy = 0;\n\t\t\tcwx = a * cx + parent.worldX;\n\t\t\tcwy = c * cx + parent.worldY;\n\t\t} else {\n\t\t\tcy = child.ay;\n\t\t\tcwx = a * cx + b * cy + parent.worldX;\n\t\t\tcwy = c * cx + d * cy + parent.worldY;\n\t\t}\n\t\tlet pp = parent.parent;\n\t\tif (!pp) throw new Error(\"IK parent must itself have a parent.\");\n\t\ta = pp.a;\n\t\tb = pp.b;\n\t\tc = pp.c;\n\t\td = pp.d;\n\t\tlet id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY;\n\t\tid = Math.abs(id) <= 0.0001 ? 0 : 1 / id;\n\t\tlet dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;\n\t\tlet l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;\n\t\tif (l1 < 0.0001) {\n\t\t\tthis.apply1(parent, targetX, targetY, false, stretch, false, alpha);\n\t\t\tchild.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);\n\t\t\treturn;\n\t\t}\n\t\tx = targetX - pp.worldX;\n\t\ty = targetY - pp.worldY;\n\t\tlet tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;\n\t\tlet dd = tx * tx + ty * ty;\n\t\tif (softness != 0) {\n\t\t\tsoftness *= psx * (csx + 1) * 0.5;\n\t\t\tlet td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness;\n\t\t\tif (sd > 0) {\n\t\t\t\tlet p = Math.min(1, sd / (softness * 2)) - 1;\n\t\t\t\tp = (sd - softness * (1 - p * p)) / td;\n\t\t\t\ttx -= p * tx;\n\t\t\t\tty -= p * ty;\n\t\t\t\tdd = tx * tx + ty * ty;\n\t\t\t}\n\t\t}\n\t\touter:\n\t\tif (u) {\n\t\t\tl2 *= psx;\n\t\t\tlet cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);\n\t\t\tif (cos < -1) {\n\t\t\t\tcos = -1;\n\t\t\t\ta2 = Math.PI * bendDir;\n\t\t\t} else if (cos > 1) {\n\t\t\t\tcos = 1;\n\t\t\t\ta2 = 0;\n\t\t\t\tif (stretch) {\n\t\t\t\t\ta = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;\n\t\t\t\t\tsx *= a;\n\t\t\t\t\tif (uniform) sy *= a;\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\ta2 = Math.acos(cos) * bendDir;\n\t\t\ta = l1 + l2 * cos;\n\t\t\tb = l2 * Math.sin(a2);\n\t\t\ta1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);\n\t\t} else {\n\t\t\ta = psx * l2;\n\t\t\tb = psy * l2;\n\t\t\tlet aa = a * a, bb = b * b, ta = Math.atan2(ty, tx);\n\t\t\tc = bb * l1 * l1 + aa * dd - aa * bb;\n\t\t\tlet c1 = -2 * bb * l1, c2 = bb - aa;\n\t\t\td = c1 * c1 - 4 * c2 * c;\n\t\t\tif (d >= 0) {\n\t\t\t\tlet q = Math.sqrt(d);\n\t\t\t\tif (c1 < 0) q = -q;\n\t\t\t\tq = -(c1 + q) * 0.5;\n\t\t\t\tlet r0 = q / c2, r1 = c / q;\n\t\t\t\tlet r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;\n\t\t\t\tr0 = dd - r * r;\n\t\t\t\tif (r0 >= 0) {\n\t\t\t\t\ty = Math.sqrt(r0) * bendDir;\n\t\t\t\t\ta1 = ta - Math.atan2(y, r);\n\t\t\t\t\ta2 = Math.atan2(y / psy, (r - l1) / psx);\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0;\n\t\t\tlet maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;\n\t\t\tc = -a * l1 / (aa - bb);\n\t\t\tif (c >= -1 && c <= 1) {\n\t\t\t\tc = Math.acos(c);\n\t\t\t\tx = a * Math.cos(c) + l1;\n\t\t\t\ty = b * Math.sin(c);\n\t\t\t\td = x * x + y * y;\n\t\t\t\tif (d < minDist) {\n\t\t\t\t\tminAngle = c;\n\t\t\t\t\tminDist = d;\n\t\t\t\t\tminX = x;\n\t\t\t\t\tminY = y;\n\t\t\t\t}\n\t\t\t\tif (d > maxDist) {\n\t\t\t\t\tmaxAngle = c;\n\t\t\t\t\tmaxDist = d;\n\t\t\t\t\tmaxX = x;\n\t\t\t\t\tmaxY = y;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (dd <= (minDist + maxDist) * 0.5) {\n\t\t\t\ta1 = ta - Math.atan2(minY * bendDir, minX);\n\t\t\t\ta2 = minAngle * bendDir;\n\t\t\t} else {\n\t\t\t\ta1 = ta - Math.atan2(maxY * bendDir, maxX);\n\t\t\t\ta2 = maxAngle * bendDir;\n\t\t\t}\n\t\t}\n\t\tlet os = Math.atan2(cy, cx) * s2;\n\t\tlet rotation = parent.arotation;\n\t\ta1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;\n\t\tif (a1 > 180)\n\t\t\ta1 -= 360;\n\t\telse if (a1 < -180) //\n\t\t\ta1 += 360;\n\t\tparent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0);\n\t\trotation = child.arotation;\n\t\ta2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation;\n\t\tif (a2 > 180)\n\t\t\ta2 -= 360;\n\t\telse if (a2 < -180) //\n\t\t\ta2 += 360;\n\t\tchild.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\n\n\n/** Stores the setup pose for an {@link IkConstraint}.\n *

    \n * See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */\nexport class IkConstraintData extends ConstraintData {\n\t/** The bones that are constrained by this IK constraint. */\n\tbones = new Array();\n\n\t/** The bone that is the IK target. */\n\tprivate _target: BoneData | null = null;\n\tpublic set target (boneData: BoneData) { this._target = boneData; }\n\tpublic get target () {\n\t\tif (!this._target) throw new Error(\"BoneData not set.\")\n\t\telse return this._target;\n\t}\n\n\t/** Controls the bend direction of the IK bones, either 1 or -1. */\n\tbendDirection = 0;\n\n\t/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */\n\tcompress = false;\n\n\t/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained\n\t * and the parent bone has local nonuniform scale, stretch is not applied. */\n\tstretch = false;\n\n\t/** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone\n\t * is scaled on both the X and Y axes. */\n\tuniform = false;\n\n\t/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */\n\tmix = 0;\n\n\t/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */\n\tsoftness = 0;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\nimport { SlotData } from \"./SlotData.js\";\n\n\n/** Stores the setup pose for a {@link PathConstraint}.\n *\n * See [path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide. */\nexport class PathConstraintData extends ConstraintData {\n\n\t/** The bones that will be modified by this path constraint. */\n\tbones = new Array();\n\n\t/** The slot whose path attachment will be used to constrained the bones. */\n\tprivate _target: SlotData | null = null;\n\tpublic set target (slotData: SlotData) { this._target = slotData; }\n\tpublic get target () {\n\t\tif (!this._target) throw new Error(\"SlotData not set.\")\n\t\telse return this._target;\n\t}\n\n\t/** The mode for positioning the first bone on the path. */\n\tpositionMode: PositionMode = PositionMode.Fixed;\n\n\t/** The mode for positioning the bones after the first bone on the path. */\n\tspacingMode: SpacingMode = SpacingMode.Fixed;\n\n\t/** The mode for adjusting the rotation of the bones. */\n\trotateMode: RotateMode = RotateMode.Chain;\n\n\t/** An offset added to the constrained bone rotation. */\n\toffsetRotation: number = 0;\n\n\t/** The position along the path. */\n\tposition: number = 0;\n\n\t/** The spacing between bones. */\n\tspacing: number = 0;\n\n\tmixRotate = 0;\n\tmixX = 0;\n\tmixY = 0;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n\n/** Controls how the first bone is positioned along the path.\n *\n * See [position](http://esotericsoftware.com/spine-path-constraints#Position) in the Spine User Guide. */\nexport enum PositionMode { Fixed, Percent }\n\n/** Controls how bones after the first bone are positioned along the path.\n *\n * See [spacing](http://esotericsoftware.com/spine-path-constraints#Spacing) in the Spine User Guide. */\nexport enum SpacingMode { Length, Fixed, Percent, Proportional }\n\n/** Controls how bones are rotated, translated, and scaled to match the path.\n *\n * See [rotate mix](http://esotericsoftware.com/spine-path-constraints#Rotate-mix) in the Spine User Guide. */\nexport enum RotateMode { Tangent, Chain, ChainScale }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { PathAttachment } from \"./attachments/PathAttachment.js\";\nimport { Bone } from \"./Bone.js\";\nimport { PathConstraintData, RotateMode, SpacingMode, PositionMode } from \"./PathConstraintData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { Utils, MathUtils } from \"./Utils.js\";\n\n\n/** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the\n * constrained bones so they follow a {@link PathAttachment}.\n *\n * See [Path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide. */\nexport class PathConstraint implements Updatable {\n\tstatic NONE = -1; static BEFORE = -2; static AFTER = -3;\n\tstatic epsilon = 0.00001;\n\n\t/** The path constraint's setup pose data. */\n\tdata: PathConstraintData;\n\n\t/** The bones that will be modified by this path constraint. */\n\tbones: Array;\n\n\t/** The slot whose path attachment will be used to constrained the bones. */\n\ttarget: Slot;\n\n\t/** The position along the path. */\n\tposition = 0;\n\n\t/** The spacing between bones. */\n\tspacing = 0;\n\n\tmixRotate = 0;\n\n\tmixX = 0;\n\n\tmixY = 0;\n\n\tspaces = new Array(); positions = new Array();\n\tworld = new Array(); curves = new Array(); lengths = new Array();\n\tsegments = new Array();\n\n\tactive = false;\n\n\tconstructor (data: PathConstraintData, skeleton: Skeleton) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0, n = data.bones.length; i < n; i++) {\n\t\t\tlet bone = skeleton.findBone(data.bones[i].name);\n\t\t\tif (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`);\n\t\t\tthis.bones.push(bone);\n\t\t}\n\t\tlet target = skeleton.findSlot(data.target.name);\n\t\tif (!target) throw new Error(`Couldn't find target bone ${data.target.name}`);\n\t\tthis.target = target;\n\n\t\tthis.position = data.position;\n\t\tthis.spacing = data.spacing;\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.position = data.position;\n\t\tthis.spacing = data.spacing;\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t}\n\n\tupdate (physics: Physics) {\n\t\tlet attachment = this.target.getAttachment();\n\t\tif (!(attachment instanceof PathAttachment)) return;\n\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;\n\t\tif (mixRotate == 0 && mixX == 0 && mixY == 0) return;\n\n\t\tlet data = this.data;\n\t\tlet tangents = data.rotateMode == RotateMode.Tangent, scale = data.rotateMode == RotateMode.ChainScale;\n\n\t\tlet bones = this.bones;\n\t\tlet boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1;\n\t\tlet spaces = Utils.setArraySize(this.spaces, spacesCount), lengths: Array = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : [];\n\t\tlet spacing = this.spacing;\n\n\t\tswitch (data.spacingMode) {\n\t\t\tcase SpacingMode.Percent:\n\t\t\t\tif (scale) {\n\t\t\t\t\tfor (let i = 0, n = spacesCount - 1; i < n; i++) {\n\t\t\t\t\t\tlet bone = bones[i];\n\t\t\t\t\t\tlet setupLength = bone.data.length;\n\t\t\t\t\t\tlet x = setupLength * bone.a, y = setupLength * bone.c;\n\t\t\t\t\t\tlengths[i] = Math.sqrt(x * x + y * y);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tUtils.arrayFill(spaces, 1, spacesCount, spacing);\n\t\t\t\tbreak;\n\t\t\tcase SpacingMode.Proportional:\n\t\t\t\tlet sum = 0;\n\t\t\t\tfor (let i = 0, n = spacesCount - 1; i < n;) {\n\t\t\t\t\tlet bone = bones[i];\n\t\t\t\t\tlet setupLength = bone.data.length;\n\t\t\t\t\tif (setupLength < PathConstraint.epsilon) {\n\t\t\t\t\t\tif (scale) lengths[i] = 0;\n\t\t\t\t\t\tspaces[++i] = spacing;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet x = setupLength * bone.a, y = setupLength * bone.c;\n\t\t\t\t\t\tlet length = Math.sqrt(x * x + y * y);\n\t\t\t\t\t\tif (scale) lengths[i] = length;\n\t\t\t\t\t\tspaces[++i] = length;\n\t\t\t\t\t\tsum += length;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (sum > 0) {\n\t\t\t\t\tsum = spacesCount / sum * spacing;\n\t\t\t\t\tfor (let i = 1; i < spacesCount; i++)\n\t\t\t\t\t\tspaces[i] *= sum;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tlet lengthSpacing = data.spacingMode == SpacingMode.Length;\n\t\t\t\tfor (let i = 0, n = spacesCount - 1; i < n;) {\n\t\t\t\t\tlet bone = bones[i];\n\t\t\t\t\tlet setupLength = bone.data.length;\n\t\t\t\t\tif (setupLength < PathConstraint.epsilon) {\n\t\t\t\t\t\tif (scale) lengths[i] = 0;\n\t\t\t\t\t\tspaces[++i] = spacing;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet x = setupLength * bone.a, y = setupLength * bone.c;\n\t\t\t\t\t\tlet length = Math.sqrt(x * x + y * y);\n\t\t\t\t\t\tif (scale) lengths[i] = length;\n\t\t\t\t\t\tspaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\n\t\tlet positions = this.computeWorldPositions(attachment, spacesCount, tangents);\n\t\tlet boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;\n\t\tlet tip = false;\n\t\tif (offsetRotation == 0)\n\t\t\ttip = data.rotateMode == RotateMode.Chain;\n\t\telse {\n\t\t\ttip = false;\n\t\t\tlet p = this.target.bone;\n\t\t\toffsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad;\n\t\t}\n\t\tfor (let i = 0, p = 3; i < boneCount; i++, p += 3) {\n\t\t\tlet bone = bones[i];\n\t\t\tbone.worldX += (boneX - bone.worldX) * mixX;\n\t\t\tbone.worldY += (boneY - bone.worldY) * mixY;\n\t\t\tlet x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;\n\t\t\tif (scale) {\n\t\t\t\tlet length = lengths[i];\n\t\t\t\tif (length != 0) {\n\t\t\t\t\tlet s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;\n\t\t\t\t\tbone.a *= s;\n\t\t\t\t\tbone.c *= s;\n\t\t\t\t}\n\t\t\t}\n\t\t\tboneX = x;\n\t\t\tboneY = y;\n\t\t\tif (mixRotate > 0) {\n\t\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0;\n\t\t\t\tif (tangents)\n\t\t\t\t\tr = positions[p - 1];\n\t\t\t\telse if (spaces[i + 1] == 0)\n\t\t\t\t\tr = positions[p + 2];\n\t\t\t\telse\n\t\t\t\t\tr = Math.atan2(dy, dx);\n\t\t\t\tr -= Math.atan2(c, a);\n\t\t\t\tif (tip) {\n\t\t\t\t\tcos = Math.cos(r);\n\t\t\t\t\tsin = Math.sin(r);\n\t\t\t\t\tlet length = bone.data.length;\n\t\t\t\t\tboneX += (length * (cos * a - sin * c) - dx) * mixRotate;\n\t\t\t\t\tboneY += (length * (sin * a + cos * c) - dy) * mixRotate;\n\t\t\t\t} else {\n\t\t\t\t\tr += offsetRotation;\n\t\t\t\t}\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr *= mixRotate;\n\t\t\t\tcos = Math.cos(r);\n\t\t\t\tsin = Math.sin(r);\n\t\t\t\tbone.a = cos * a - sin * c;\n\t\t\t\tbone.b = cos * b - sin * d;\n\t\t\t\tbone.c = sin * a + cos * c;\n\t\t\t\tbone.d = sin * b + cos * d;\n\t\t\t}\n\t\t\tbone.updateAppliedTransform();\n\t\t}\n\t}\n\n\tcomputeWorldPositions (path: PathAttachment, spacesCount: number, tangents: boolean) {\n\t\tlet target = this.target;\n\t\tlet position = this.position;\n\t\tlet spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world: Array = this.world;\n\t\tlet closed = path.closed;\n\t\tlet verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE;\n\n\t\tif (!path.constantSpeed) {\n\t\t\tlet lengths = path.lengths;\n\t\t\tcurveCount -= closed ? 1 : 2;\n\t\t\tlet pathLength = lengths[curveCount];\n\t\t\tif (this.data.positionMode == PositionMode.Percent) position *= pathLength;\n\n\t\t\tlet multiplier;\n\t\t\tswitch (this.data.spacingMode) {\n\t\t\t\tcase SpacingMode.Percent:\n\t\t\t\t\tmultiplier = pathLength;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SpacingMode.Proportional:\n\t\t\t\t\tmultiplier = pathLength / spacesCount;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tmultiplier = 1;\n\t\t\t}\n\t\t\tworld = Utils.setArraySize(this.world, 8);\n\t\t\tfor (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {\n\t\t\t\tlet space = spaces[i] * multiplier;\n\t\t\t\tposition += space;\n\t\t\t\tlet p = position;\n\n\t\t\t\tif (closed) {\n\t\t\t\t\tp %= pathLength;\n\t\t\t\t\tif (p < 0) p += pathLength;\n\t\t\t\t\tcurve = 0;\n\t\t\t\t} else if (p < 0) {\n\t\t\t\t\tif (prevCurve != PathConstraint.BEFORE) {\n\t\t\t\t\t\tprevCurve = PathConstraint.BEFORE;\n\t\t\t\t\t\tpath.computeWorldVertices(target, 2, 4, world, 0, 2);\n\t\t\t\t\t}\n\t\t\t\t\tthis.addBeforePosition(p, world, 0, out, o);\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (p > pathLength) {\n\t\t\t\t\tif (prevCurve != PathConstraint.AFTER) {\n\t\t\t\t\t\tprevCurve = PathConstraint.AFTER;\n\t\t\t\t\t\tpath.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);\n\t\t\t\t\t}\n\t\t\t\t\tthis.addAfterPosition(p - pathLength, world, 0, out, o);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Determine curve containing position.\n\t\t\t\tfor (; ; curve++) {\n\t\t\t\t\tlet length = lengths[curve];\n\t\t\t\t\tif (p > length) continue;\n\t\t\t\t\tif (curve == 0)\n\t\t\t\t\t\tp /= length;\n\t\t\t\t\telse {\n\t\t\t\t\t\tlet prev = lengths[curve - 1];\n\t\t\t\t\t\tp = (p - prev) / (length - prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (curve != prevCurve) {\n\t\t\t\t\tprevCurve = curve;\n\t\t\t\t\tif (closed && curve == curveCount) {\n\t\t\t\t\t\tpath.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);\n\t\t\t\t\t\tpath.computeWorldVertices(target, 0, 4, world, 4, 2);\n\t\t\t\t\t} else\n\t\t\t\t\t\tpath.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);\n\t\t\t\t}\n\t\t\t\tthis.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,\n\t\t\t\t\ttangents || (i > 0 && space == 0));\n\t\t\t}\n\t\t\treturn out;\n\t\t}\n\n\t\t// World vertices.\n\t\tif (closed) {\n\t\t\tverticesLength += 2;\n\t\t\tworld = Utils.setArraySize(this.world, verticesLength);\n\t\t\tpath.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);\n\t\t\tpath.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);\n\t\t\tworld[verticesLength - 2] = world[0];\n\t\t\tworld[verticesLength - 1] = world[1];\n\t\t} else {\n\t\t\tcurveCount--;\n\t\t\tverticesLength -= 4;\n\t\t\tworld = Utils.setArraySize(this.world, verticesLength);\n\t\t\tpath.computeWorldVertices(target, 2, verticesLength, world, 0, 2);\n\t\t}\n\n\t\t// Curve lengths.\n\t\tlet curves = Utils.setArraySize(this.curves, curveCount);\n\t\tlet pathLength = 0;\n\t\tlet x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;\n\t\tlet tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0;\n\t\tfor (let i = 0, w = 2; i < curveCount; i++, w += 6) {\n\t\t\tcx1 = world[w];\n\t\t\tcy1 = world[w + 1];\n\t\t\tcx2 = world[w + 2];\n\t\t\tcy2 = world[w + 3];\n\t\t\tx2 = world[w + 4];\n\t\t\ty2 = world[w + 5];\n\t\t\ttmpx = (x1 - cx1 * 2 + cx2) * 0.1875;\n\t\t\ttmpy = (y1 - cy1 * 2 + cy2) * 0.1875;\n\t\t\tdddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;\n\t\t\tdddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;\n\t\t\tddfx = tmpx * 2 + dddfx;\n\t\t\tddfy = tmpy * 2 + dddfy;\n\t\t\tdfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;\n\t\t\tdfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tdfx += ddfx;\n\t\t\tdfy += ddfy;\n\t\t\tddfx += dddfx;\n\t\t\tddfy += dddfy;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tdfx += ddfx;\n\t\t\tdfy += ddfy;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tdfx += ddfx + dddfx;\n\t\t\tdfy += ddfy + dddfy;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tcurves[i] = pathLength;\n\t\t\tx1 = x2;\n\t\t\ty1 = y2;\n\t\t}\n\n\t\tif (this.data.positionMode == PositionMode.Percent) position *= pathLength;\n\n\t\tlet multiplier;\n\t\tswitch (this.data.spacingMode) {\n\t\t\tcase SpacingMode.Percent:\n\t\t\t\tmultiplier = pathLength;\n\t\t\t\tbreak;\n\t\t\tcase SpacingMode.Proportional:\n\t\t\t\tmultiplier = pathLength / spacesCount;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tmultiplier = 1;\n\t\t}\n\n\t\tlet segments = this.segments;\n\t\tlet curveLength = 0;\n\t\tfor (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {\n\t\t\tlet space = spaces[i] * multiplier;\n\t\t\tposition += space;\n\t\t\tlet p = position;\n\n\t\t\tif (closed) {\n\t\t\t\tp %= pathLength;\n\t\t\t\tif (p < 0) p += pathLength;\n\t\t\t\tcurve = 0;\n\t\t\t} else if (p < 0) {\n\t\t\t\tthis.addBeforePosition(p, world, 0, out, o);\n\t\t\t\tcontinue;\n\t\t\t} else if (p > pathLength) {\n\t\t\t\tthis.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Determine curve containing position.\n\t\t\tfor (; ; curve++) {\n\t\t\t\tlet length = curves[curve];\n\t\t\t\tif (p > length) continue;\n\t\t\t\tif (curve == 0)\n\t\t\t\t\tp /= length;\n\t\t\t\telse {\n\t\t\t\t\tlet prev = curves[curve - 1];\n\t\t\t\t\tp = (p - prev) / (length - prev);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Curve segment lengths.\n\t\t\tif (curve != prevCurve) {\n\t\t\t\tprevCurve = curve;\n\t\t\t\tlet ii = curve * 6;\n\t\t\t\tx1 = world[ii];\n\t\t\t\ty1 = world[ii + 1];\n\t\t\t\tcx1 = world[ii + 2];\n\t\t\t\tcy1 = world[ii + 3];\n\t\t\t\tcx2 = world[ii + 4];\n\t\t\t\tcy2 = world[ii + 5];\n\t\t\t\tx2 = world[ii + 6];\n\t\t\t\ty2 = world[ii + 7];\n\t\t\t\ttmpx = (x1 - cx1 * 2 + cx2) * 0.03;\n\t\t\t\ttmpy = (y1 - cy1 * 2 + cy2) * 0.03;\n\t\t\t\tdddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006;\n\t\t\t\tdddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006;\n\t\t\t\tddfx = tmpx * 2 + dddfx;\n\t\t\t\tddfy = tmpy * 2 + dddfy;\n\t\t\t\tdfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;\n\t\t\t\tdfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;\n\t\t\t\tcurveLength = Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\tsegments[0] = curveLength;\n\t\t\t\tfor (ii = 1; ii < 8; ii++) {\n\t\t\t\t\tdfx += ddfx;\n\t\t\t\t\tdfy += ddfy;\n\t\t\t\t\tddfx += dddfx;\n\t\t\t\t\tddfy += dddfy;\n\t\t\t\t\tcurveLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\t\tsegments[ii] = curveLength;\n\t\t\t\t}\n\t\t\t\tdfx += ddfx;\n\t\t\t\tdfy += ddfy;\n\t\t\t\tcurveLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\tsegments[8] = curveLength;\n\t\t\t\tdfx += ddfx + dddfx;\n\t\t\t\tdfy += ddfy + dddfy;\n\t\t\t\tcurveLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\tsegments[9] = curveLength;\n\t\t\t\tsegment = 0;\n\t\t\t}\n\n\t\t\t// Weight by segment length.\n\t\t\tp *= curveLength;\n\t\t\tfor (; ; segment++) {\n\t\t\t\tlet length = segments[segment];\n\t\t\t\tif (p > length) continue;\n\t\t\t\tif (segment == 0)\n\t\t\t\t\tp /= length;\n\t\t\t\telse {\n\t\t\t\t\tlet prev = segments[segment - 1];\n\t\t\t\t\tp = segment + (p - prev) / (length - prev);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));\n\t\t}\n\t\treturn out;\n\t}\n\n\taddBeforePosition (p: number, temp: Array, i: number, out: Array, o: number) {\n\t\tlet x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx);\n\t\tout[o] = x1 + p * Math.cos(r);\n\t\tout[o + 1] = y1 + p * Math.sin(r);\n\t\tout[o + 2] = r;\n\t}\n\n\taddAfterPosition (p: number, temp: Array, i: number, out: Array, o: number) {\n\t\tlet x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx);\n\t\tout[o] = x1 + p * Math.cos(r);\n\t\tout[o + 1] = y1 + p * Math.sin(r);\n\t\tout[o + 2] = r;\n\t}\n\n\taddCurvePosition (p: number, x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number,\n\t\tout: Array, o: number, tangents: boolean) {\n\t\tif (p == 0 || isNaN(p)) {\n\t\t\tout[o] = x1;\n\t\t\tout[o + 1] = y1;\n\t\t\tout[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);\n\t\t\treturn;\n\t\t}\n\t\tlet tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;\n\t\tlet ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;\n\t\tlet x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;\n\t\tout[o] = x;\n\t\tout[o + 1] = y;\n\t\tif (tangents) {\n\t\t\tif (p < 0.001)\n\t\t\t\tout[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);\n\t\t\telse\n\t\t\t\tout[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"./Bone.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { MathUtils } from \"./Utils.js\";\n\n\n/** Stores the current pose for a physics constraint. A physics constraint applies physics to bones.\n *

    \n * See Physics constraints in the Spine User Guide. */\nexport class PhysicsConstraint implements Updatable {\n\treadonly data: PhysicsConstraintData;\n\tprivate _bone: Bone | null = null;\n\t/** The bone constrained by this physics constraint. */\n\tpublic set bone (bone: Bone) { this._bone = bone; }\n\tpublic get bone () {\n\t\tif (!this._bone) throw new Error(\"Bone not set.\")\n\t\telse return this._bone;\n\t}\n\tinertia = 0;\n\tstrength = 0;\n\tdamping = 0;\n\tmassInverse = 0;\n\twind = 0;\n\tgravity = 0;\n\tmix = 0;\n\n\t_reset = true;\n\tux = 0;\n\tuy = 0;\n\tcx = 0;\n\tcy = 0;\n\ttx = 0;\n\tty = 0;\n\txOffset = 0;\n\txVelocity = 0;\n\tyOffset = 0;\n\tyVelocity = 0;\n\trotateOffset = 0;\n\trotateVelocity = 0;\n\tscaleOffset = 0\n\tscaleVelocity = 0;\n\n\tactive = false;\n\n\treadonly skeleton: Skeleton;\n\tremaining = 0;\n\tlastTime = 0;\n\n\tconstructor (data: PhysicsConstraintData, skeleton: Skeleton) {\n\t\tthis.data = data;\n\t\tthis.skeleton = skeleton;\n\n\t\tthis.bone = skeleton.bones[data.bone.index];\n\n\t\tthis.inertia = data.inertia;\n\t\tthis.strength = data.strength;\n\t\tthis.damping = data.damping;\n\t\tthis.massInverse = data.massInverse;\n\t\tthis.wind = data.wind;\n\t\tthis.gravity = data.gravity;\n\t\tthis.mix = data.mix;\n\t}\n\n\treset () {\n\t\tthis.remaining = 0;\n\t\tthis.lastTime = this.skeleton.time;\n\t\tthis._reset = true;\n\t\tthis.xOffset = 0;\n\t\tthis.xVelocity = 0;\n\t\tthis.yOffset = 0;\n\t\tthis.yVelocity = 0;\n\t\tthis.rotateOffset = 0;\n\t\tthis.rotateVelocity = 0;\n\t\tthis.scaleOffset = 0;\n\t\tthis.scaleVelocity = 0;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.inertia = data.inertia;\n\t\tthis.strength = data.strength;\n\t\tthis.damping = data.damping;\n\t\tthis.massInverse = data.massInverse;\n\t\tthis.wind = data.wind;\n\t\tthis.gravity = data.gravity;\n\t\tthis.mix = data.mix;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\t/** Applies the constraint to the constrained bones. */\n\tupdate (physics: Physics) {\n\t\tconst mix = this.mix;\n\t\tif (mix == 0) return;\n\n\t\tconst x = this.data.x > 0, y = this.data.y > 0, rotateOrShearX = this.data.rotate > 0 || this.data.shearX > 0, scaleX = this.data.scaleX > 0;\n\t\tconst bone = this.bone;\n\t\tconst l = bone.data.length;\n\n\t\tswitch (physics) {\n\t\t\tcase Physics.none:\n\t\t\t\treturn;\n\t\t\tcase Physics.reset:\n\t\t\t\tthis.reset();\n\t\t\t// Fall through.\n\t\t\tcase Physics.update:\n\t\t\t\tconst skeleton = this.skeleton;\n\t\t\t\tconst delta = Math.max(this.skeleton.time - this.lastTime, 0);\n\t\t\t\tthis.remaining += delta;\n\t\t\t\tthis.lastTime = skeleton.time;\n\n\t\t\t\tconst bx = bone.worldX, by = bone.worldY;\n\t\t\t\tif (this._reset) {\n\t\t\t\t\tthis._reset = false;\n\t\t\t\t\tthis.ux = bx;\n\t\t\t\t\tthis.uy = by;\n\t\t\t\t} else {\n\t\t\t\t\tlet a = this.remaining, i = this.inertia, t = this.data.step, f = this.skeleton.data.referenceScale, d = -1;\n\t\t\t\t\tlet qx = this.data.limit * delta, qy = qx * Math.abs(skeleton.scaleY);\n\t\t\t\t\tqx *= Math.abs(skeleton.scaleX);\n\t\t\t\t\tif (x || y) {\n\t\t\t\t\t\tif (x) {\n\t\t\t\t\t\t\tconst u = (this.ux - bx) * i;\n\t\t\t\t\t\t\tthis.xOffset += u > qx ? qx : u < -qx ? -qx : u;\n\t\t\t\t\t\t\tthis.ux = bx;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (y) {\n\t\t\t\t\t\t\tconst u = (this.uy - by) * i;\n\t\t\t\t\t\t\tthis.yOffset += u > qy ? qy : u < -qy ? -qy : u;\n\t\t\t\t\t\t\tthis.uy = by;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (a >= t) {\n\t\t\t\t\t\t\td = Math.pow(this.damping, 60 * t);\n\t\t\t\t\t\t\tconst m = this.massInverse * t, e = this.strength, w = this.wind * f * skeleton.scaleX, g = this.gravity * f * skeleton.scaleY;\n\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\tif (x) {\n\t\t\t\t\t\t\t\t\tthis.xVelocity += (w - this.xOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.xOffset += this.xVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.xVelocity *= d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (y) {\n\t\t\t\t\t\t\t\t\tthis.yVelocity -= (g + this.yOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.yOffset += this.yVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.yVelocity *= d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ta -= t;\n\t\t\t\t\t\t\t} while (a >= t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (x) bone.worldX += this.xOffset * mix * this.data.x;\n\t\t\t\t\t\tif (y) bone.worldY += this.yOffset * mix * this.data.y;\n\t\t\t\t\t}\n\t\t\t\t\tif (rotateOrShearX || scaleX) {\n\t\t\t\t\t\tlet ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0;\n\t\t\t\t\t\tlet dx = this.cx - bone.worldX, dy = this.cy - bone.worldY;\n\t\t\t\t\t\tif (dx > qx)\n\t\t\t\t\t\t\tdx = qx;\n\t\t\t\t\t\telse if (dx < -qx) //\n\t\t\t\t\t\t\tdx = -qx;\n\t\t\t\t\t\tif (dy > qy)\n\t\t\t\t\t\t\tdy = qy;\n\t\t\t\t\t\telse if (dy < -qy) //\n\t\t\t\t\t\t\tdy = -qy;\n\t\t\t\t\t\tif (rotateOrShearX) {\n\t\t\t\t\t\t\tmr = (this.data.rotate + this.data.shearX) * mix;\n\t\t\t\t\t\t\tlet r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr;\n\t\t\t\t\t\t\tthis.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i;\n\t\t\t\t\t\t\tr = this.rotateOffset * mr + ca;\n\t\t\t\t\t\t\tc = Math.cos(r);\n\t\t\t\t\t\t\ts = Math.sin(r);\n\t\t\t\t\t\t\tif (scaleX) {\n\t\t\t\t\t\t\t\tr = l * bone.getWorldScaleX();\n\t\t\t\t\t\t\t\tif (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tc = Math.cos(ca);\n\t\t\t\t\t\t\ts = Math.sin(ca);\n\t\t\t\t\t\t\tconst r = l * bone.getWorldScaleX();\n\t\t\t\t\t\t\tif (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ta = this.remaining;\n\t\t\t\t\t\tif (a >= t) {\n\t\t\t\t\t\t\tif (d == -1) d = Math.pow(this.damping, 60 * t);\n\t\t\t\t\t\t\tconst m = this.massInverse * t, e = this.strength, w = this.wind, g = (Skeleton.yDown ? -this.gravity : this.gravity), h = l / f;\n\t\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\t\ta -= t;\n\t\t\t\t\t\t\t\tif (scaleX) {\n\t\t\t\t\t\t\t\t\tthis.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.scaleOffset += this.scaleVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.scaleVelocity *= d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (rotateOrShearX) {\n\t\t\t\t\t\t\t\t\tthis.rotateVelocity -= ((w * s + g * c) * h + this.rotateOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.rotateOffset += this.rotateVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.rotateVelocity *= d;\n\t\t\t\t\t\t\t\t\tif (a < t) break;\n\t\t\t\t\t\t\t\t\tconst r = this.rotateOffset * mr + ca;\n\t\t\t\t\t\t\t\t\tc = Math.cos(r);\n\t\t\t\t\t\t\t\t\ts = Math.sin(r);\n\t\t\t\t\t\t\t\t} else if (a < t) //\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.remaining = a;\n\t\t\t\t}\n\t\t\t\tthis.cx = bone.worldX;\n\t\t\t\tthis.cy = bone.worldY;\n\t\t\t\tbreak;\n\t\t\tcase Physics.pose:\n\t\t\t\tif (x) bone.worldX += this.xOffset * mix * this.data.x;\n\t\t\t\tif (y) bone.worldY += this.yOffset * mix * this.data.y;\n\t\t}\n\n\t\tif (rotateOrShearX) {\n\t\t\tlet o = this.rotateOffset * mix, s = 0, c = 0, a = 0;\n\t\t\tif (this.data.shearX > 0) {\n\t\t\t\tlet r = 0;\n\t\t\t\tif (this.data.rotate > 0) {\n\t\t\t\t\tr = o * this.data.rotate;\n\t\t\t\t\ts = Math.sin(r);\n\t\t\t\t\tc = Math.cos(r);\n\t\t\t\t\ta = bone.b;\n\t\t\t\t\tbone.b = c * a - s * bone.d;\n\t\t\t\t\tbone.d = s * a + c * bone.d;\n\t\t\t\t}\n\t\t\t\tr += o * this.data.shearX;\n\t\t\t\ts = Math.sin(r);\n\t\t\t\tc = Math.cos(r);\n\t\t\t\ta = bone.a;\n\t\t\t\tbone.a = c * a - s * bone.c;\n\t\t\t\tbone.c = s * a + c * bone.c;\n\t\t\t} else {\n\t\t\t\to *= this.data.rotate;\n\t\t\t\ts = Math.sin(o);\n\t\t\t\tc = Math.cos(o);\n\t\t\t\ta = bone.a;\n\t\t\t\tbone.a = c * a - s * bone.c;\n\t\t\t\tbone.c = s * a + c * bone.c;\n\t\t\t\ta = bone.b;\n\t\t\t\tbone.b = c * a - s * bone.d;\n\t\t\t\tbone.d = s * a + c * bone.d;\n\t\t\t}\n\t\t}\n\t\tif (scaleX) {\n\t\t\tconst s = 1 + this.scaleOffset * mix * this.data.scaleX;\n\t\t\tbone.a *= s;\n\t\t\tbone.c *= s;\n\t\t}\n\t\tif (physics != Physics.pose) {\n\t\t\tthis.tx = l * bone.a;\n\t\t\tthis.ty = l * bone.c;\n\t\t}\n\t\tbone.updateAppliedTransform();\n\t}\n\n\t/** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional\n\t * amount in world space. */\n\ttranslate (x: number, y: number) {\n\t\tthis.ux -= x;\n\t\tthis.uy -= y;\n\t\tthis.cx -= x;\n\t\tthis.cy -= y;\n\t}\n\n\t/** Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the\n\t * specified point in world space. */\n\trotate (x: number, y: number, degrees: number) {\n\t\tconst r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);\n\t\tconst dx = this.cx - x, dy = this.cy - y;\n\t\tthis.translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Attachment, VertexAttachment } from \"./attachments/Attachment.js\";\nimport { Bone } from \"./Bone.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { SlotData } from \"./SlotData.js\";\nimport { Color } from \"./Utils.js\";\n\n/** Stores a slot's current pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store\n * state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared\n * across multiple skeletons. */\nexport class Slot {\n\t/** The slot's setup pose data. */\n\tdata: SlotData;\n\n\t/** The bone this slot belongs to. */\n\tbone: Bone;\n\n\t/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two\n\t * color tinting. */\n\tcolor: Color;\n\n\t/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark\n\t * color's alpha is not used. */\n\tdarkColor: Color | null = null;\n\n\tattachment: Attachment | null = null;\n\n\tattachmentState: number = 0;\n\n\t/** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the\n\t * {@link Sequence#getSetupIndex()}. */\n\tsequenceIndex: number = -1;\n\n\t/** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a\n\t * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions.\n\t *\n\t * See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */\n\tdeform = new Array();\n\n\tconstructor (data: SlotData, bone: Bone) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!bone) throw new Error(\"bone cannot be null.\");\n\t\tthis.data = data;\n\t\tthis.bone = bone;\n\t\tthis.color = new Color();\n\t\tthis.darkColor = !data.darkColor ? null : new Color();\n\t\tthis.setToSetupPose();\n\t}\n\n\t/** The skeleton this slot belongs to. */\n\tgetSkeleton (): Skeleton {\n\t\treturn this.bone.skeleton;\n\t}\n\n\t/** The current attachment for the slot, or null if the slot has no attachment. */\n\tgetAttachment (): Attachment | null {\n\t\treturn this.attachment;\n\t}\n\n\t/** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}.\n\t * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the\n\t * specified attachment. */\n\tsetAttachment (attachment: Attachment | null) {\n\t\tif (this.attachment == attachment) return;\n\t\tif (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment)\n\t\t\t|| (attachment).timelineAttachment != (this.attachment).timelineAttachment) {\n\t\t\tthis.deform.length = 0;\n\t\t}\n\t\tthis.attachment = attachment;\n\t\tthis.sequenceIndex = -1;\n\t}\n\n\t/** Sets this slot to the setup pose. */\n\tsetToSetupPose () {\n\t\tthis.color.setFromColor(this.data.color);\n\t\tif (this.darkColor) this.darkColor.setFromColor(this.data.darkColor!);\n\t\tif (!this.data.attachmentName)\n\t\t\tthis.attachment = null;\n\t\telse {\n\t\t\tthis.attachment = null;\n\t\t\tthis.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName));\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"./Bone.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { Vector2, MathUtils } from \"./Utils.js\";\n\n\n/** Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained\n * bones to match that of the target bone.\n *\n * See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */\nexport class TransformConstraint implements Updatable {\n\n\t/** The transform constraint's setup pose data. */\n\tdata: TransformConstraintData;\n\n\t/** The bones that will be modified by this transform constraint. */\n\tbones: Array;\n\n\t/** The target bone whose world transform will be copied to the constrained bones. */\n\ttarget: Bone;\n\n\tmixRotate = 0; mixX = 0; mixY = 0; mixScaleX = 0; mixScaleY = 0; mixShearY = 0;\n\n\ttemp = new Vector2();\n\tactive = false;\n\n\tconstructor (data: TransformConstraintData, skeleton: Skeleton) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0; i < data.bones.length; i++) {\n\t\t\tlet bone = skeleton.findBone(data.bones[i].name);\n\t\t\tif (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`);\n\t\t\tthis.bones.push(bone);\n\t\t}\n\t\tlet target = skeleton.findBone(data.target.name);\n\t\tif (!target) throw new Error(`Couldn't find target bone ${data.target.name}.`);\n\t\tthis.target = target;\n\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t\tthis.mixScaleX = data.mixScaleX;\n\t\tthis.mixScaleY = data.mixScaleY;\n\t\tthis.mixShearY = data.mixShearY;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t\tthis.mixScaleX = data.mixScaleX;\n\t\tthis.mixScaleY = data.mixScaleY;\n\t\tthis.mixShearY = data.mixShearY;\n\t}\n\n\tupdate (physics: Physics) {\n\t\tif (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) return;\n\n\t\tif (this.data.local) {\n\t\t\tif (this.data.relative)\n\t\t\t\tthis.applyRelativeLocal();\n\t\t\telse\n\t\t\t\tthis.applyAbsoluteLocal();\n\t\t} else {\n\t\t\tif (this.data.relative)\n\t\t\t\tthis.applyRelativeWorld();\n\t\t\telse\n\t\t\t\tthis.applyAbsoluteWorld();\n\t\t}\n\t}\n\n\tapplyAbsoluteWorld () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\t\tlet translate = mixX != 0 || mixY != 0;\n\n\t\tlet target = this.target;\n\t\tlet ta = target.a, tb = target.b, tc = target.c, td = target.d;\n\t\tlet degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;\n\t\tlet offsetRotation = this.data.offsetRotation * degRadReflect;\n\t\tlet offsetShearY = this.data.offsetShearY * degRadReflect;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tif (mixRotate != 0) {\n\t\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\t\tlet r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation;\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr *= mixRotate;\n\t\t\t\tlet cos = Math.cos(r), sin = Math.sin(r);\n\t\t\t\tbone.a = cos * a - sin * c;\n\t\t\t\tbone.b = cos * b - sin * d;\n\t\t\t\tbone.c = sin * a + cos * c;\n\t\t\t\tbone.d = sin * b + cos * d;\n\t\t\t}\n\n\t\t\tif (translate) {\n\t\t\t\tlet temp = this.temp;\n\t\t\t\ttarget.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));\n\t\t\t\tbone.worldX += (temp.x - bone.worldX) * mixX;\n\t\t\t\tbone.worldY += (temp.y - bone.worldY) * mixY;\n\t\t\t}\n\n\t\t\tif (mixScaleX != 0) {\n\t\t\t\tlet s = Math.sqrt(bone.a * bone.a + bone.c * bone.c);\n\t\t\t\tif (s != 0) s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s;\n\t\t\t\tbone.a *= s;\n\t\t\t\tbone.c *= s;\n\t\t\t}\n\t\t\tif (mixScaleY != 0) {\n\t\t\t\tlet s = Math.sqrt(bone.b * bone.b + bone.d * bone.d);\n\t\t\t\tif (s != 0) s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s;\n\t\t\t\tbone.b *= s;\n\t\t\t\tbone.d *= s;\n\t\t\t}\n\n\t\t\tif (mixShearY > 0) {\n\t\t\t\tlet b = bone.b, d = bone.d;\n\t\t\t\tlet by = Math.atan2(d, b);\n\t\t\t\tlet r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr = by + (r + offsetShearY) * mixShearY;\n\t\t\t\tlet s = Math.sqrt(b * b + d * d);\n\t\t\t\tbone.b = Math.cos(r) * s;\n\t\t\t\tbone.d = Math.sin(r) * s;\n\t\t\t}\n\n\t\t\tbone.updateAppliedTransform();\n\t\t}\n\t}\n\n\tapplyRelativeWorld () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\t\tlet translate = mixX != 0 || mixY != 0;\n\n\t\tlet target = this.target;\n\t\tlet ta = target.a, tb = target.b, tc = target.c, td = target.d;\n\t\tlet degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;\n\t\tlet offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tif (mixRotate != 0) {\n\t\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\t\tlet r = Math.atan2(tc, ta) + offsetRotation;\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr *= mixRotate;\n\t\t\t\tlet cos = Math.cos(r), sin = Math.sin(r);\n\t\t\t\tbone.a = cos * a - sin * c;\n\t\t\t\tbone.b = cos * b - sin * d;\n\t\t\t\tbone.c = sin * a + cos * c;\n\t\t\t\tbone.d = sin * b + cos * d;\n\t\t\t}\n\n\t\t\tif (translate) {\n\t\t\t\tlet temp = this.temp;\n\t\t\t\ttarget.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));\n\t\t\t\tbone.worldX += temp.x * mixX;\n\t\t\t\tbone.worldY += temp.y * mixY;\n\t\t\t}\n\n\t\t\tif (mixScaleX != 0) {\n\t\t\t\tlet s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1;\n\t\t\t\tbone.a *= s;\n\t\t\t\tbone.c *= s;\n\t\t\t}\n\t\t\tif (mixScaleY != 0) {\n\t\t\t\tlet s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1;\n\t\t\t\tbone.b *= s;\n\t\t\t\tbone.d *= s;\n\t\t\t}\n\n\t\t\tif (mixShearY > 0) {\n\t\t\t\tlet r = Math.atan2(td, tb) - Math.atan2(tc, ta);\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tlet b = bone.b, d = bone.d;\n\t\t\t\tr = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY;\n\t\t\t\tlet s = Math.sqrt(b * b + d * d);\n\t\t\t\tbone.b = Math.cos(r) * s;\n\t\t\t\tbone.d = Math.sin(r) * s;\n\t\t\t}\n\n\t\t\tbone.updateAppliedTransform();\n\t\t}\n\t}\n\n\tapplyAbsoluteLocal () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\n\t\tlet target = this.target;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tlet rotation = bone.arotation;\n\t\t\tif (mixRotate != 0) rotation += (target.arotation - rotation + this.data.offsetRotation) * mixRotate;\n\n\t\t\tlet x = bone.ax, y = bone.ay;\n\t\t\tx += (target.ax - x + this.data.offsetX) * mixX;\n\t\t\ty += (target.ay - y + this.data.offsetY) * mixY;\n\n\t\t\tlet scaleX = bone.ascaleX, scaleY = bone.ascaleY;\n\t\t\tif (mixScaleX != 0 && scaleX != 0)\n\t\t\t\tscaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX;\n\t\t\tif (mixScaleY != 0 && scaleY != 0)\n\t\t\t\tscaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY;\n\n\t\t\tlet shearY = bone.ashearY;\n\t\t\tif (mixShearY != 0) shearY += (target.ashearY - shearY + this.data.offsetShearY) * mixShearY;\n\n\t\t\tbone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);\n\t\t}\n\t}\n\n\tapplyRelativeLocal () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\n\t\tlet target = this.target;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tlet rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate;\n\t\t\tlet x = bone.ax + (target.ax + this.data.offsetX) * mixX;\n\t\t\tlet y = bone.ay + (target.ay + this.data.offsetY) * mixY;\n\t\t\tlet scaleX = bone.ascaleX * (((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX) + 1);\n\t\t\tlet scaleY = bone.ascaleY * (((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY) + 1);\n\t\t\tlet shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY;\n\n\t\t\tbone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Attachment } from \"./attachments/Attachment.js\";\nimport { ClippingAttachment } from \"./attachments/ClippingAttachment.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { PathAttachment } from \"./attachments/PathAttachment.js\";\nimport { RegionAttachment } from \"./attachments/RegionAttachment.js\";\nimport { Bone } from \"./Bone.js\";\nimport { IkConstraint } from \"./IkConstraint.js\";\nimport { PathConstraint } from \"./PathConstraint.js\";\nimport { PhysicsConstraint } from \"./PhysicsConstraint.js\";\nimport { SkeletonClipping } from \"./SkeletonClipping.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { Slot } from \"./Slot.js\";\nimport { TransformConstraint } from \"./TransformConstraint.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { Color, Utils, MathUtils, Vector2, NumberArrayLike } from \"./Utils.js\";\n\n/** Stores the current pose for a skeleton.\n *\n * See [Instance objects](http://esotericsoftware.com/spine-runtime-architecture#Instance-objects) in the Spine Runtimes Guide. */\nexport class Skeleton {\n\tprivate static quadTriangles = [0, 1, 2, 2, 3, 0];\n\tstatic yDown = false;\n\n\t/** The skeleton's setup pose data. */\n\tdata: SkeletonData;\n\n\t/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */\n\tbones: Array;\n\n\t/** The skeleton's slots in the setup pose draw order. */\n\tslots: Array;\n\n\t/** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */\n\tdrawOrder: Array;\n\n\t/** The skeleton's IK constraints. */\n\tikConstraints: Array;\n\n\t/** The skeleton's transform constraints. */\n\ttransformConstraints: Array;\n\n\t/** The skeleton's path constraints. */\n\tpathConstraints: Array;\n\n\n\t/** The skeleton's physics constraints. */\n\tphysicsConstraints: Array;\n\n\t/** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */\n\t_updateCache = new Array();\n\n\t/** The skeleton's current skin. May be null. */\n\tskin: Skin | null = null;\n\n\t/** The color to tint all the skeleton's attachments. */\n\tcolor: Color;\n\n\t/** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale\n\t * inheritance. */\n\tscaleX = 1;\n\n\t/** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale\n\t * inheritance. */\n\tprivate _scaleY = 1;\n\n\tpublic get scaleY () {\n\t\treturn Skeleton.yDown ? -this._scaleY : this._scaleY;\n\t}\n\n\tpublic set scaleY (scaleY: number) {\n\t\tthis._scaleY = scaleY;\n\t}\n\n\t/** Sets the skeleton X position, which is added to the root bone worldX position. */\n\tx = 0;\n\n\t/** Sets the skeleton Y position, which is added to the root bone worldY position. */\n\ty = 0;\n\n\t/** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}.\n\t *

    \n\t * See {@link #update(float)}. */\n\ttime = 0;\n\n\tconstructor (data: SkeletonData) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0; i < data.bones.length; i++) {\n\t\t\tlet boneData = data.bones[i];\n\t\t\tlet bone: Bone;\n\t\t\tif (!boneData.parent)\n\t\t\t\tbone = new Bone(boneData, this, null);\n\t\t\telse {\n\t\t\t\tlet parent = this.bones[boneData.parent.index];\n\t\t\t\tbone = new Bone(boneData, this, parent);\n\t\t\t\tparent.children.push(bone);\n\t\t\t}\n\t\t\tthis.bones.push(bone);\n\t\t}\n\n\t\tthis.slots = new Array();\n\t\tthis.drawOrder = new Array();\n\t\tfor (let i = 0; i < data.slots.length; i++) {\n\t\t\tlet slotData = data.slots[i];\n\t\t\tlet bone = this.bones[slotData.boneData.index];\n\t\t\tlet slot = new Slot(slotData, bone);\n\t\t\tthis.slots.push(slot);\n\t\t\tthis.drawOrder.push(slot);\n\t\t}\n\n\t\tthis.ikConstraints = new Array();\n\t\tfor (let i = 0; i < data.ikConstraints.length; i++) {\n\t\t\tlet ikConstraintData = data.ikConstraints[i];\n\t\t\tthis.ikConstraints.push(new IkConstraint(ikConstraintData, this));\n\t\t}\n\n\t\tthis.transformConstraints = new Array();\n\t\tfor (let i = 0; i < data.transformConstraints.length; i++) {\n\t\t\tlet transformConstraintData = data.transformConstraints[i];\n\t\t\tthis.transformConstraints.push(new TransformConstraint(transformConstraintData, this));\n\t\t}\n\n\t\tthis.pathConstraints = new Array();\n\t\tfor (let i = 0; i < data.pathConstraints.length; i++) {\n\t\t\tlet pathConstraintData = data.pathConstraints[i];\n\t\t\tthis.pathConstraints.push(new PathConstraint(pathConstraintData, this));\n\t\t}\n\n\t\tthis.physicsConstraints = new Array();\n\t\tfor (let i = 0; i < data.physicsConstraints.length; i++) {\n\t\t\tlet physicsConstraintData = data.physicsConstraints[i];\n\t\t\tthis.physicsConstraints.push(new PhysicsConstraint(physicsConstraintData, this));\n\t\t}\n\n\t\tthis.color = new Color(1, 1, 1, 1);\n\t\tthis.updateCache();\n\t}\n\n\t/** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones,\n\t * constraints, or weighted path attachments are added or removed. */\n\tupdateCache () {\n\t\tlet updateCache = this._updateCache;\n\t\tupdateCache.length = 0;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tbone.sorted = bone.data.skinRequired;\n\t\t\tbone.active = !bone.sorted;\n\t\t}\n\n\t\tif (this.skin) {\n\t\t\tlet skinBones = this.skin.bones;\n\t\t\tfor (let i = 0, n = this.skin.bones.length; i < n; i++) {\n\t\t\t\tlet bone: Bone | null = this.bones[skinBones[i].index];\n\t\t\t\tdo {\n\t\t\t\t\tbone.sorted = false;\n\t\t\t\t\tbone.active = true;\n\t\t\t\t\tbone = bone.parent;\n\t\t\t\t} while (bone);\n\t\t\t}\n\t\t}\n\n\t\t// IK first, lowest hierarchy depth first.\n\t\tlet ikConstraints = this.ikConstraints;\n\t\tlet transformConstraints = this.transformConstraints;\n\t\tlet pathConstraints = this.pathConstraints;\n\t\tlet physicsConstraints = this.physicsConstraints;\n\t\tlet ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length, physicsCount = this.physicsConstraints.length;\n\t\tlet constraintCount = ikCount + transformCount + pathCount + physicsCount;\n\n\t\touter:\n\t\tfor (let i = 0; i < constraintCount; i++) {\n\t\t\tfor (let ii = 0; ii < ikCount; ii++) {\n\t\t\t\tlet constraint = ikConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortIkConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let ii = 0; ii < transformCount; ii++) {\n\t\t\t\tlet constraint = transformConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortTransformConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let ii = 0; ii < pathCount; ii++) {\n\t\t\t\tlet constraint = pathConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortPathConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let ii = 0; ii < physicsCount; ii++) {\n\t\t\t\tconst constraint = physicsConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortPhysicsConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = 0, n = bones.length; i < n; i++)\n\t\t\tthis.sortBone(bones[i]);\n\t}\n\n\tsortIkConstraint (constraint: IkConstraint) {\n\t\tconstraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;\n\t\tif (!constraint.active) return;\n\n\t\tlet target = constraint.target;\n\t\tthis.sortBone(target);\n\n\t\tlet constrained = constraint.bones;\n\t\tlet parent = constrained[0];\n\t\tthis.sortBone(parent);\n\n\t\tif (constrained.length == 1) {\n\t\t\tthis._updateCache.push(constraint);\n\t\t\tthis.sortReset(parent.children);\n\t\t} else {\n\t\t\tlet child = constrained[constrained.length - 1];\n\t\t\tthis.sortBone(child);\n\n\t\t\tthis._updateCache.push(constraint);\n\n\t\t\tthis.sortReset(parent.children);\n\t\t\tchild.sorted = true;\n\t\t}\n\t}\n\n\tsortPathConstraint (constraint: PathConstraint) {\n\t\tconstraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;\n\t\tif (!constraint.active) return;\n\n\t\tlet slot = constraint.target;\n\t\tlet slotIndex = slot.data.index;\n\t\tlet slotBone = slot.bone;\n\t\tif (this.skin) this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);\n\t\tif (this.data.defaultSkin && this.data.defaultSkin != this.skin)\n\t\t\tthis.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);\n\t\tfor (let i = 0, n = this.data.skins.length; i < n; i++)\n\t\t\tthis.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);\n\n\t\tlet attachment = slot.getAttachment();\n\t\tif (attachment instanceof PathAttachment) this.sortPathConstraintAttachmentWith(attachment, slotBone);\n\n\t\tlet constrained = constraint.bones;\n\t\tlet boneCount = constrained.length;\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tthis.sortBone(constrained[i]);\n\n\t\tthis._updateCache.push(constraint);\n\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tthis.sortReset(constrained[i].children);\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tconstrained[i].sorted = true;\n\t}\n\n\tsortTransformConstraint (constraint: TransformConstraint) {\n\t\tconstraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;\n\t\tif (!constraint.active) return;\n\n\t\tthis.sortBone(constraint.target);\n\n\t\tlet constrained = constraint.bones;\n\t\tlet boneCount = constrained.length;\n\t\tif (constraint.data.local) {\n\t\t\tfor (let i = 0; i < boneCount; i++) {\n\t\t\t\tlet child = constrained[i];\n\t\t\t\tthis.sortBone(child.parent!);\n\t\t\t\tthis.sortBone(child);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (let i = 0; i < boneCount; i++) {\n\t\t\t\tthis.sortBone(constrained[i]);\n\t\t\t}\n\t\t}\n\n\t\tthis._updateCache.push(constraint);\n\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tthis.sortReset(constrained[i].children);\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tconstrained[i].sorted = true;\n\t}\n\n\tsortPathConstraintAttachment (skin: Skin, slotIndex: number, slotBone: Bone) {\n\t\tlet attachments = skin.attachments[slotIndex];\n\t\tif (!attachments) return;\n\t\tfor (let key in attachments) {\n\t\t\tthis.sortPathConstraintAttachmentWith(attachments[key], slotBone);\n\t\t}\n\t}\n\n\tsortPathConstraintAttachmentWith (attachment: Attachment, slotBone: Bone) {\n\t\tif (!(attachment instanceof PathAttachment)) return;\n\t\tlet pathBones = (attachment).bones;\n\t\tif (!pathBones)\n\t\t\tthis.sortBone(slotBone);\n\t\telse {\n\t\t\tlet bones = this.bones;\n\t\t\tfor (let i = 0, n = pathBones.length; i < n;) {\n\t\t\t\tlet nn = pathBones[i++];\n\t\t\t\tnn += i;\n\t\t\t\twhile (i < nn)\n\t\t\t\t\tthis.sortBone(bones[pathBones[i++]]);\n\t\t\t}\n\t\t}\n\t}\n\n\tsortPhysicsConstraint (constraint: PhysicsConstraint) {\n\t\tconst bone = constraint.bone;\n\t\tconstraint.active = bone.active && (!constraint.data.skinRequired || (this.skin != null && Utils.contains(this.skin.constraints, constraint.data, true)));\n\t\tif (!constraint.active) return;\n\n\t\tthis.sortBone(bone);\n\n\t\tthis._updateCache.push(constraint);\n\n\t\tthis.sortReset(bone.children);\n\t\tbone.sorted = true;\n\t}\n\n\tsortBone (bone: Bone) {\n\t\tif (!bone) return;\n\t\tif (bone.sorted) return;\n\t\tlet parent = bone.parent;\n\t\tif (parent) this.sortBone(parent);\n\t\tbone.sorted = true;\n\t\tthis._updateCache.push(bone);\n\t}\n\n\tsortReset (bones: Array) {\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tif (!bone.active) continue;\n\t\t\tif (bone.sorted) this.sortReset(bone.children);\n\t\t\tbone.sorted = false;\n\t\t}\n\t}\n\n\t/** Updates the world transform for each bone and applies all constraints.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide. */\n\tupdateWorldTransform (physics: Physics) {\n\t\tif (physics === undefined || physics === null) throw new Error(\"physics is undefined\");\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tbone.ax = bone.x;\n\t\t\tbone.ay = bone.y;\n\t\t\tbone.arotation = bone.rotation;\n\t\t\tbone.ascaleX = bone.scaleX;\n\t\t\tbone.ascaleY = bone.scaleY;\n\t\t\tbone.ashearX = bone.shearX;\n\t\t\tbone.ashearY = bone.shearY;\n\t\t}\n\n\t\tlet updateCache = this._updateCache;\n\t\tfor (let i = 0, n = updateCache.length; i < n; i++)\n\t\t\tupdateCache[i].update(physics);\n\t}\n\n\tupdateWorldTransformWith (physics: Physics, parent: Bone) {\n\t\tif (!parent) throw new Error(\"parent cannot be null.\");\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 1, n = bones.length; i < n; i++) { // Skip root bone.\n\t\t\tlet bone = bones[i];\n\t\t\tbone.ax = bone.x;\n\t\t\tbone.ay = bone.y;\n\t\t\tbone.arotation = bone.rotation;\n\t\t\tbone.ascaleX = bone.scaleX;\n\t\t\tbone.ascaleY = bone.scaleY;\n\t\t\tbone.ashearX = bone.shearX;\n\t\t\tbone.ashearY = bone.shearY;\n\t\t}\n\n\t\t// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.\n\t\tlet rootBone = this.getRootBone();\n\t\tif (!rootBone) throw new Error(\"Root bone must not be null.\");\n\t\tlet pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;\n\t\trootBone.worldX = pa * this.x + pb * this.y + parent.worldX;\n\t\trootBone.worldY = pc * this.x + pd * this.y + parent.worldY;\n\n\t\tconst rx = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad;\n\t\tconst ry = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad;\n\t\tconst la = Math.cos(rx) * rootBone.scaleX;\n\t\tconst lb = Math.cos(ry) * rootBone.scaleY;\n\t\tconst lc = Math.sin(rx) * rootBone.scaleX;\n\t\tconst ld = Math.sin(ry) * rootBone.scaleY;\n\t\trootBone.a = (pa * la + pb * lc) * this.scaleX;\n\t\trootBone.b = (pa * lb + pb * ld) * this.scaleX;\n\t\trootBone.c = (pc * la + pd * lc) * this.scaleY;\n\t\trootBone.d = (pc * lb + pd * ld) * this.scaleY;\n\n\t\t// Update everything except root bone.\n\t\tlet updateCache = this._updateCache;\n\t\tfor (let i = 0, n = updateCache.length; i < n; i++) {\n\t\t\tlet updatable = updateCache[i];\n\t\t\tif (updatable != rootBone) updatable.update(physics);\n\t\t}\n\t}\n\n\t/** Sets the bones, constraints, and slots to their setup pose values. */\n\tsetToSetupPose () {\n\t\tthis.setBonesToSetupPose();\n\t\tthis.setSlotsToSetupPose();\n\t}\n\n\t/** Sets the bones and constraints to their setup pose values. */\n\tsetBonesToSetupPose () {\n\t\tfor (const bone of this.bones) bone.setToSetupPose();\n\t\tfor (const constraint of this.ikConstraints) constraint.setToSetupPose();\n\t\tfor (const constraint of this.transformConstraints) constraint.setToSetupPose();\n\t\tfor (const constraint of this.pathConstraints) constraint.setToSetupPose();\n\t\tfor (const constraint of this.physicsConstraints) constraint.setToSetupPose();\n\t}\n\n\t/** Sets the slots and draw order to their setup pose values. */\n\tsetSlotsToSetupPose () {\n\t\tlet slots = this.slots;\n\t\tUtils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);\n\t\tfor (let i = 0, n = slots.length; i < n; i++)\n\t\t\tslots[i].setToSetupPose();\n\t}\n\n\t/** @returns May return null. */\n\tgetRootBone () {\n\t\tif (this.bones.length == 0) return null;\n\t\treturn this.bones[0];\n\t}\n\n\t/** @returns May be null. */\n\tfindBone (boneName: string) {\n\t\tif (!boneName) throw new Error(\"boneName cannot be null.\");\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tif (bone.data.name == boneName) return bone;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it\n\t * repeatedly.\n\t * @returns May be null. */\n\tfindSlot (slotName: string) {\n\t\tif (!slotName) throw new Error(\"slotName cannot be null.\");\n\t\tlet slots = this.slots;\n\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (slot.data.name == slotName) return slot;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Sets a skin by name.\n\t *\n\t * See {@link #setSkin()}. */\n\tsetSkinByName (skinName: string) {\n\t\tlet skin = this.data.findSkin(skinName);\n\t\tif (!skin) throw new Error(\"Skin not found: \" + skinName);\n\t\tthis.setSkin(skin);\n\t}\n\n\t/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the\n\t * skin is changed, {@link #updateCache()} is called.\n\t *\n\t * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no\n\t * old skin, each slot's setup mode attachment is attached from the new skin.\n\t *\n\t * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling\n\t * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the\n\t * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.\n\t * @param newSkin May be null. */\n\tsetSkin (newSkin: Skin) {\n\t\tif (newSkin == this.skin) return;\n\t\tif (newSkin) {\n\t\t\tif (this.skin)\n\t\t\t\tnewSkin.attachAll(this, this.skin);\n\t\t\telse {\n\t\t\t\tlet slots = this.slots;\n\t\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\t\tlet slot = slots[i];\n\t\t\t\t\tlet name = slot.data.attachmentName;\n\t\t\t\t\tif (name) {\n\t\t\t\t\t\tlet attachment = newSkin.getAttachment(i, name);\n\t\t\t\t\t\tif (attachment) slot.setAttachment(attachment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.skin = newSkin;\n\t\tthis.updateCache();\n\t}\n\n\n\t/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment\n\t * name.\n\t *\n\t * See {@link #getAttachment()}.\n\t * @returns May be null. */\n\tgetAttachmentByName (slotName: string, attachmentName: string): Attachment | null {\n\t\tlet slot = this.data.findSlot(slotName);\n\t\tif (!slot) throw new Error(`Can't find slot with name ${slotName}`);\n\t\treturn this.getAttachment(slot.index, attachmentName);\n\t}\n\n\t/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and\n\t * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked.\n\t *\n\t * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide.\n\t * @returns May be null. */\n\tgetAttachment (slotIndex: number, attachmentName: string): Attachment | null {\n\t\tif (!attachmentName) throw new Error(\"attachmentName cannot be null.\");\n\t\tif (this.skin) {\n\t\t\tlet attachment = this.skin.getAttachment(slotIndex, attachmentName);\n\t\t\tif (attachment) return attachment;\n\t\t}\n\t\tif (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);\n\t\treturn null;\n\t}\n\n\t/** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with\n\t * {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}.\n\t * @param attachmentName May be null to clear the slot's attachment. */\n\tsetAttachment (slotName: string, attachmentName: string) {\n\t\tif (!slotName) throw new Error(\"slotName cannot be null.\");\n\t\tlet slots = this.slots;\n\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (slot.data.name == slotName) {\n\t\t\t\tlet attachment: Attachment | null = null;\n\t\t\t\tif (attachmentName) {\n\t\t\t\t\tattachment = this.getAttachment(i, attachmentName);\n\t\t\t\t\tif (!attachment) throw new Error(\"Attachment not found: \" + attachmentName + \", for slot: \" + slotName);\n\t\t\t\t}\n\t\t\t\tslot.setAttachment(attachment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthrow new Error(\"Slot not found: \" + slotName);\n\t}\n\n\n\t/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method\n\t * than to call it repeatedly.\n\t * @return May be null. */\n\tfindIkConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.ikConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of\n\t * this method than to call it repeatedly.\n\t * @return May be null. */\n\tfindTransformConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.transformConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method\n\t * than to call it repeatedly.\n\t * @return May be null. */\n\tfindPathConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.pathConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this\n\t * method than to call it repeatedly. */\n\tfindPhysicsConstraint (constraintName: string) {\n\t\tif (constraintName == null) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.physicsConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`.\n\t * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */\n\tgetBoundsRect (clipper?: SkeletonClipping) {\n\t\tlet offset = new Vector2();\n\t\tlet size = new Vector2();\n\t\tthis.getBounds(offset, size, undefined, clipper);\n\t\treturn { x: offset.x, y: offset.y, width: size.x, height: size.y };\n\t}\n\n\t/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.\n\t * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.\n\t * @param size An output value, the width and height of the AABB.\n\t * @param temp Working memory to temporarily store attachments' computed world vertices.\n\t * @param clipper {@link SkeletonClipping} to use. If null, no clipping is applied. */\n\tgetBounds (offset: Vector2, size: Vector2, temp: Array = new Array(2), clipper: SkeletonClipping | null = null) {\n\t\tif (!offset) throw new Error(\"offset cannot be null.\");\n\t\tif (!size) throw new Error(\"size cannot be null.\");\n\t\tlet drawOrder = this.drawOrder;\n\t\tlet minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet slot = drawOrder[i];\n\t\t\tif (!slot.bone.active) continue;\n\t\t\tlet verticesLength = 0;\n\t\t\tlet vertices: NumberArrayLike | null = null;\n\t\t\tlet triangles: NumberArrayLike | null = null;\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\tverticesLength = 8;\n\t\t\t\tvertices = Utils.setArraySize(temp, verticesLength, 0);\n\t\t\t\tattachment.computeWorldVertices(slot, vertices, 0, 2);\n\t\t\t\ttriangles = Skeleton.quadTriangles;\n\t\t\t} else if (attachment instanceof MeshAttachment) {\n\t\t\t\tlet mesh = (attachment);\n\t\t\t\tverticesLength = mesh.worldVerticesLength;\n\t\t\t\tvertices = Utils.setArraySize(temp, verticesLength, 0);\n\t\t\t\tmesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);\n\t\t\t\ttriangles = mesh.triangles;\n\t\t\t} else if (attachment instanceof ClippingAttachment && clipper != null) {\n\t\t\t\tclipper.clipStart(slot, attachment);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (vertices && triangles) {\n\t\t\t\tif (clipper != null && clipper.isClipping()) {\n\t\t\t\t\tclipper.clipTriangles(vertices, triangles, triangles.length);\n\t\t\t\t\tvertices = clipper.clippedVertices;\n\t\t\t\t\tverticesLength = clipper.clippedVertices.length;\n\t\t\t\t}\n\t\t\t\tfor (let ii = 0, nn = vertices.length; ii < nn; ii += 2) {\n\t\t\t\t\tlet x = vertices[ii], y = vertices[ii + 1];\n\t\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (clipper != null) clipper.clipEndWithSlot(slot);\n\t\t}\n\t\tif (clipper != null) clipper.clipEnd();\n\t\toffset.set(minX, minY);\n\t\tsize.set(maxX - minX, maxY - minY);\n\t}\n\n\t/** Increments the skeleton's {@link #time}. */\n\tupdate (delta: number) {\n\t\tthis.time += delta;\n\t}\n\n\tphysicsTranslate (x: number, y: number) {\n\t\tconst physicsConstraints = this.physicsConstraints;\n\t\tfor (let i = 0, n = physicsConstraints.length; i < n; i++)\n\t\t\tphysicsConstraints[i].translate(x, y);\n\t}\n\n\t/** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */\n\tphysicsRotate (x: number, y: number, degrees: number) {\n\t\tconst physicsConstraints = this.physicsConstraints;\n\t\tfor (let i = 0, n = physicsConstraints.length; i < n; i++)\n\t\t\tphysicsConstraints[i].rotate(x, y, degrees);\n\t}\n}\n\n/** Determines how physics and other non-deterministic updates are applied. */\nexport enum Physics {\n\t/** Physics are not updated or applied. */\n\tnone,\n\n\t/** Physics are reset to the current pose. */\n\treset,\n\n\t/** Physics are updated and the pose from physics is applied. */\n\tupdate,\n\n\t/** Physics are not updated but the pose from physics is applied. */\n\tpose\n}", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\n\n\n/** Stores the setup pose for a {@link PhysicsConstraint}.\n *

    \n * See Physics constraints in the Spine User Guide. */\nexport class PhysicsConstraintData extends ConstraintData {\n\tprivate _bone: BoneData | null = null;\n\t/** The bone constrained by this physics constraint. */\n\tpublic set bone (boneData: BoneData) { this._bone = boneData; }\n\tpublic get bone () {\n\t\tif (!this._bone) throw new Error(\"BoneData not set.\")\n\t\telse return this._bone;\n\t}\n\n\tx = 0;\n\ty = 0;\n\trotate = 0;\n\tscaleX = 0;\n\tshearX = 0;\n\tlimit = 0;\n\tstep = 0;\n\tinertia = 0;\n\tstrength = 0;\n\tdamping = 0;\n\tmassInverse = 0;\n\twind = 0;\n\tgravity = 0;\n\t/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */\n\tmix = 0;\n\tinertiaGlobal = false;\n\tstrengthGlobal = false;\n\tdampingGlobal = false;\n\tmassGlobal = false;\n\twindGlobal = false;\n\tgravityGlobal = false;\n\tmixGlobal = false;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation } from \"./Animation\"\nimport { BoneData } from \"./BoneData.js\";\nimport { EventData } from \"./EventData.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { PathConstraintData } from \"./PathConstraintData.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { SlotData } from \"./SlotData.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\n\n/** Stores the setup pose and all of the stateless data for a skeleton.\n *\n * See [Data objects](http://esotericsoftware.com/spine-runtime-architecture#Data-objects) in the Spine Runtimes\n * Guide. */\nexport class SkeletonData {\n\n\t/** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */\n\tname: string | null = null;\n\n\t/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */\n\tbones = new Array(); // Ordered parents first.\n\n\t/** The skeleton's slots in the setup pose draw order. */\n\tslots = new Array(); // Setup pose draw order.\n\n\tskins = new Array();\n\n\t/** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine.\n\t *\n\t * See {@link Skeleton#getAttachmentByName()}.\n\t * May be null. */\n\tdefaultSkin: Skin | null = null;\n\n\t/** The skeleton's events. */\n\tevents = new Array();\n\n\t/** The skeleton's animations. */\n\tanimations = new Array();\n\n\t/** The skeleton's IK constraints. */\n\tikConstraints = new Array();\n\n\t/** The skeleton's transform constraints. */\n\ttransformConstraints = new Array();\n\n\t/** The skeleton's path constraints. */\n\tpathConstraints = new Array();\n\n\t/** The skeleton's physics constraints. */\n\tphysicsConstraints = new Array();\n\n\t/** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */\n\tx: number = 0;\n\n\t/** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */\n\ty: number = 0;\n\n\t/** The width of the skeleton's axis aligned bounding box in the setup pose. */\n\twidth: number = 0;\n\n\t/** The height of the skeleton's axis aligned bounding box in the setup pose. */\n\theight: number = 0;\n\n\t/** Baseline scale factor for applying distance-dependent effects on non-scalable properties, such as angle or scale. Default\n\t * is 100. */\n\treferenceScale = 100;\n\n\t/** The Spine version used to export the skeleton data, or null. */\n\tversion: string | null = null;\n\n\t/** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */\n\thash: string | null = null;\n\n\t// Nonessential\n\t/** The dopesheet FPS in Spine. Available only when nonessential data was exported. */\n\tfps = 0;\n\n\t/** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */\n\timagesPath: string | null = null;\n\n\t/** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */\n\taudioPath: string | null = null;\n\n\t/** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindBone (boneName: string) {\n\t\tif (!boneName) throw new Error(\"boneName cannot be null.\");\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tif (bone.name == boneName) return bone;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindSlot (slotName: string) {\n\t\tif (!slotName) throw new Error(\"slotName cannot be null.\");\n\t\tlet slots = this.slots;\n\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (slot.name == slotName) return slot;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindSkin (skinName: string) {\n\t\tif (!skinName) throw new Error(\"skinName cannot be null.\");\n\t\tlet skins = this.skins;\n\t\tfor (let i = 0, n = skins.length; i < n; i++) {\n\t\t\tlet skin = skins[i];\n\t\t\tif (skin.name == skinName) return skin;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindEvent (eventDataName: string) {\n\t\tif (!eventDataName) throw new Error(\"eventDataName cannot be null.\");\n\t\tlet events = this.events;\n\t\tfor (let i = 0, n = events.length; i < n; i++) {\n\t\t\tlet event = events[i];\n\t\t\tif (event.name == eventDataName) return event;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to\n\t * call it multiple times.\n\t * @returns May be null. */\n\tfindAnimation (animationName: string) {\n\t\tif (!animationName) throw new Error(\"animationName cannot be null.\");\n\t\tlet animations = this.animations;\n\t\tfor (let i = 0, n = animations.length; i < n; i++) {\n\t\t\tlet animation = animations[i];\n\t\t\tif (animation.name == animationName) return animation;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method\n\t * than to call it multiple times.\n\t * @return May be null. */\n\tfindIkConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst ikConstraints = this.ikConstraints;\n\t\tfor (let i = 0, n = ikConstraints.length; i < n; i++) {\n\t\t\tconst constraint = ikConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of\n\t * this method than to call it multiple times.\n\t * @return May be null. */\n\tfindTransformConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst transformConstraints = this.transformConstraints;\n\t\tfor (let i = 0, n = transformConstraints.length; i < n; i++) {\n\t\t\tconst constraint = transformConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method\n\t * than to call it multiple times.\n\t * @return May be null. */\n\tfindPathConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst pathConstraints = this.pathConstraints;\n\t\tfor (let i = 0, n = pathConstraints.length; i < n; i++) {\n\t\t\tconst constraint = pathConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this method\n\t * than to call it multiple times.\n\t * @return May be null. */\n\tfindPhysicsConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst physicsConstraints = this.physicsConstraints;\n\t\tfor (let i = 0, n = physicsConstraints.length; i < n; i++) {\n\t\t\tconst constraint = physicsConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Attachment } from \"./attachments/Attachment.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Color, StringMap } from \"./Utils.js\";\n\n/** Stores an entry in the skin consisting of the slot index, name, and attachment **/\nexport class SkinEntry {\n\tconstructor (public slotIndex: number = 0, public name: string, public attachment: Attachment) { }\n}\n\n/** Stores attachments by slot index and attachment name.\n *\n * See SkeletonData {@link SkeletonData#defaultSkin}, Skeleton {@link Skeleton#skin}, and\n * [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. */\nexport class Skin {\n\t/** The skin's name, which is unique across all skins in the skeleton. */\n\tname: string;\n\n\tattachments = new Array>();\n\tbones = Array();\n\tconstraints = new Array();\n\n\t/** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */\n\tcolor = new Color(0.99607843, 0.61960787, 0.30980393, 1); // fe9e4fff\n\n\tconstructor (name: string) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t}\n\n\t/** Adds an attachment to the skin for the specified slot index and name. */\n\tsetAttachment (slotIndex: number, name: string, attachment: Attachment) {\n\t\tif (!attachment) throw new Error(\"attachment cannot be null.\");\n\t\tlet attachments = this.attachments;\n\t\tif (slotIndex >= attachments.length) attachments.length = slotIndex + 1;\n\t\tif (!attachments[slotIndex]) attachments[slotIndex] = {};\n\t\tattachments[slotIndex][name] = attachment;\n\t}\n\n\t/** Adds all attachments, bones, and constraints from the specified skin to this skin. */\n\taddSkin (skin: Skin) {\n\t\tfor (let i = 0; i < skin.bones.length; i++) {\n\t\t\tlet bone = skin.bones[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.bones.length; ii++) {\n\t\t\t\tif (this.bones[ii] == bone) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.bones.push(bone);\n\t\t}\n\n\t\tfor (let i = 0; i < skin.constraints.length; i++) {\n\t\t\tlet constraint = skin.constraints[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.constraints.length; ii++) {\n\t\t\t\tif (this.constraints[ii] == constraint) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.constraints.push(constraint);\n\t\t}\n\n\t\tlet attachments = skin.getAttachments();\n\t\tfor (let i = 0; i < attachments.length; i++) {\n\t\t\tvar attachment = attachments[i];\n\t\t\tthis.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);\n\t\t}\n\t}\n\n\t/** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not\n\t * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */\n\tcopySkin (skin: Skin) {\n\t\tfor (let i = 0; i < skin.bones.length; i++) {\n\t\t\tlet bone = skin.bones[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.bones.length; ii++) {\n\t\t\t\tif (this.bones[ii] == bone) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.bones.push(bone);\n\t\t}\n\n\t\tfor (let i = 0; i < skin.constraints.length; i++) {\n\t\t\tlet constraint = skin.constraints[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.constraints.length; ii++) {\n\t\t\t\tif (this.constraints[ii] == constraint) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.constraints.push(constraint);\n\t\t}\n\n\t\tlet attachments = skin.getAttachments();\n\t\tfor (let i = 0; i < attachments.length; i++) {\n\t\t\tvar attachment = attachments[i];\n\t\t\tif (!attachment.attachment) continue;\n\t\t\tif (attachment.attachment instanceof MeshAttachment) {\n\t\t\t\tattachment.attachment = attachment.attachment.newLinkedMesh();\n\t\t\t\tthis.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);\n\t\t\t} else {\n\t\t\t\tattachment.attachment = attachment.attachment.copy();\n\t\t\t\tthis.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Returns the attachment for the specified slot index and name, or null. */\n\tgetAttachment (slotIndex: number, name: string): Attachment | null {\n\t\tlet dictionary = this.attachments[slotIndex];\n\t\treturn dictionary ? dictionary[name] : null;\n\t}\n\n\t/** Removes the attachment in the skin for the specified slot index and name, if any. */\n\tremoveAttachment (slotIndex: number, name: string) {\n\t\tlet dictionary = this.attachments[slotIndex];\n\t\tif (dictionary) delete dictionary[name];\n\t}\n\n\t/** Returns all attachments in this skin. */\n\tgetAttachments (): Array {\n\t\tlet entries = new Array();\n\t\tfor (var i = 0; i < this.attachments.length; i++) {\n\t\t\tlet slotAttachments = this.attachments[i];\n\t\t\tif (slotAttachments) {\n\t\t\t\tfor (let name in slotAttachments) {\n\t\t\t\t\tlet attachment = slotAttachments[name];\n\t\t\t\t\tif (attachment) entries.push(new SkinEntry(i, name, attachment));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t}\n\n\t/** Returns all attachments in this skin for the specified slot index. */\n\tgetAttachmentsForSlot (slotIndex: number, attachments: Array) {\n\t\tlet slotAttachments = this.attachments[slotIndex];\n\t\tif (slotAttachments) {\n\t\t\tfor (let name in slotAttachments) {\n\t\t\t\tlet attachment = slotAttachments[name];\n\t\t\t\tif (attachment) attachments.push(new SkinEntry(slotIndex, name, attachment));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Clears all attachments, bones, and constraints. */\n\tclear () {\n\t\tthis.attachments.length = 0;\n\t\tthis.bones.length = 0;\n\t\tthis.constraints.length = 0;\n\t}\n\n\t/** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */\n\tattachAll (skeleton: Skeleton, oldSkin: Skin) {\n\t\tlet slotIndex = 0;\n\t\tfor (let i = 0; i < skeleton.slots.length; i++) {\n\t\t\tlet slot = skeleton.slots[i];\n\t\t\tlet slotAttachment = slot.getAttachment();\n\t\t\tif (slotAttachment && slotIndex < oldSkin.attachments.length) {\n\t\t\t\tlet dictionary = oldSkin.attachments[slotIndex];\n\t\t\t\tfor (let key in dictionary) {\n\t\t\t\t\tlet skinAttachment: Attachment = dictionary[key];\n\t\t\t\t\tif (slotAttachment == skinAttachment) {\n\t\t\t\t\t\tlet attachment = this.getAttachment(slotIndex, key);\n\t\t\t\t\t\tif (attachment) slot.setAttachment(attachment);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tslotIndex++;\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { Color } from \"./Utils.js\";\n\n/** Stores the setup pose for a {@link Slot}. */\nexport class SlotData {\n\t/** The index of the slot in {@link Skeleton#getSlots()}. */\n\tindex: number = 0;\n\n\t/** The name of the slot, which is unique across all slots in the skeleton. */\n\tname: string;\n\n\t/** The bone this slot belongs to. */\n\tboneData: BoneData;\n\n\t/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two\n\t * color tinting. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\t/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark\n\t * color's alpha is not used. */\n\tdarkColor: Color | null = null;\n\n\t/** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */\n\tattachmentName: string | null = null;\n\n\t/** The blend mode for drawing the slot's attachment. */\n\tblendMode: BlendMode = BlendMode.Normal;\n\n\t/** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */\n\tvisible = true;\n\n\tconstructor (index: number, name: string, boneData: BoneData) {\n\t\tif (index < 0) throw new Error(\"index must be >= 0.\");\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tif (!boneData) throw new Error(\"boneData cannot be null.\");\n\t\tthis.index = index;\n\t\tthis.name = name;\n\t\tthis.boneData = boneData;\n\t}\n}\n\n/** Determines how images are blended with existing pixels when drawn. */\nexport enum BlendMode { Normal, Additive, Multiply, Screen }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { ConstraintData } from \"./ConstraintData.js\";\nimport { BoneData } from \"./BoneData.js\";\n\n/** Stores the setup pose for a {@link TransformConstraint}.\n *\n * See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */\nexport class TransformConstraintData extends ConstraintData {\n\n\t/** The bones that will be modified by this transform constraint. */\n\tbones = new Array();\n\n\t/** The target bone whose world transform will be copied to the constrained bones. */\n\tprivate _target: BoneData | null = null;\n\tpublic set target (boneData: BoneData) { this._target = boneData; }\n\tpublic get target () {\n\t\tif (!this._target) throw new Error(\"BoneData not set.\")\n\t\telse return this._target;\n\t}\n\n\tmixRotate = 0;\n\tmixX = 0;\n\tmixY = 0;\n\tmixScaleX = 0;\n\tmixScaleY = 0;\n\tmixShearY = 0;\n\n\t/** An offset added to the constrained bone rotation. */\n\toffsetRotation = 0;\n\n\t/** An offset added to the constrained bone X translation. */\n\toffsetX = 0;\n\n\t/** An offset added to the constrained bone Y translation. */\n\toffsetY = 0;\n\n\t/** An offset added to the constrained bone scaleX. */\n\toffsetScaleX = 0;\n\n\t/** An offset added to the constrained bone scaleY. */\n\toffsetScaleY = 0;\n\n\t/** An offset added to the constrained bone shearY. */\n\toffsetShearY = 0;\n\n\trelative = false;\n\tlocal = false;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation, Timeline, InheritTimeline, AttachmentTimeline, RGBATimeline, RGBTimeline, RGBA2Timeline, RGB2Timeline, AlphaTimeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline2, CurveTimeline, SequenceTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline } from \"./Animation.js\";\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { AttachmentLoader } from \"./attachments/AttachmentLoader.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { Sequence, SequenceModeValues } from \"./attachments/Sequence.js\";\nimport { BoneData } from \"./BoneData.js\";\nimport { Event } from \"./Event.js\";\nimport { EventData } from \"./EventData.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { PathConstraintData, PositionMode, SpacingMode } from \"./PathConstraintData.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { SlotData } from \"./SlotData.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\nimport { Color, Utils } from \"./Utils.js\";\n\n/** Loads skeleton data in the Spine binary format.\n *\n * See [Spine binary format](http://esotericsoftware.com/spine-binary-format) and\n * [JSON and binary data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the Spine\n * Runtimes Guide. */\nexport class SkeletonBinary {\n\t/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at\n\t * runtime than were used in Spine.\n\t *\n\t * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */\n\tscale = 1;\n\n\tattachmentLoader: AttachmentLoader;\n\tprivate linkedMeshes = new Array();\n\n\tconstructor (attachmentLoader: AttachmentLoader) {\n\t\tthis.attachmentLoader = attachmentLoader;\n\t}\n\n\treadSkeletonData (binary: Uint8Array | ArrayBuffer): SkeletonData {\n\t\tlet scale = this.scale;\n\n\t\tlet skeletonData = new SkeletonData();\n\t\tskeletonData.name = \"\"; // BOZO\n\n\t\tlet input = new BinaryInput(binary);\n\n\t\tlet lowHash = input.readInt32();\n\t\tlet highHash = input.readInt32();\n\t\tskeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16);\n\t\tskeletonData.version = input.readString();\n\t\tskeletonData.x = input.readFloat();\n\t\tskeletonData.y = input.readFloat();\n\t\tskeletonData.width = input.readFloat();\n\t\tskeletonData.height = input.readFloat();\n\t\tskeletonData.referenceScale = input.readFloat() * scale;\n\n\t\tlet nonessential = input.readBoolean();\n\t\tif (nonessential) {\n\t\t\tskeletonData.fps = input.readFloat();\n\t\t\tskeletonData.imagesPath = input.readString();\n\t\t\tskeletonData.audioPath = input.readString();\n\t\t}\n\n\t\tlet n = 0;\n\t\t// Strings.\n\t\tn = input.readInt(true)\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet str = input.readString();\n\t\t\tif (!str) throw new Error(\"String in string table must not be null.\");\n\t\t\tinput.strings.push(str);\n\t\t}\n\n\t\t// Bones.\n\t\tn = input.readInt(true)\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"Bone name must not be null.\");\n\t\t\tlet parent = i == 0 ? null : skeletonData.bones[input.readInt(true)];\n\t\t\tlet data = new BoneData(i, name, parent);\n\t\t\tdata.rotation = input.readFloat();\n\t\t\tdata.x = input.readFloat() * scale;\n\t\t\tdata.y = input.readFloat() * scale;\n\t\t\tdata.scaleX = input.readFloat();\n\t\t\tdata.scaleY = input.readFloat();\n\t\t\tdata.shearX = input.readFloat();\n\t\t\tdata.shearY = input.readFloat();\n\t\t\tdata.length = input.readFloat() * scale;\n\t\t\tdata.inherit = input.readByte();\n\t\t\tdata.skinRequired = input.readBoolean();\n\t\t\tif (nonessential) {\n\t\t\t\tColor.rgba8888ToColor(data.color, input.readInt32());\n\t\t\t\tdata.icon = input.readString() ?? undefined;\n\t\t\t\tdata.visible = input.readBoolean();\n\t\t\t}\n\t\t\tskeletonData.bones.push(data);\n\t\t}\n\n\t\t// Slots.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet slotName = input.readString();\n\t\t\tif (!slotName) throw new Error(\"Slot name must not be null.\");\n\t\t\tlet boneData = skeletonData.bones[input.readInt(true)];\n\t\t\tlet data = new SlotData(i, slotName, boneData);\n\t\t\tColor.rgba8888ToColor(data.color, input.readInt32());\n\n\t\t\tlet darkColor = input.readInt32();\n\t\t\tif (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor);\n\n\t\t\tdata.attachmentName = input.readStringRef();\n\t\t\tdata.blendMode = input.readInt(true);\n\t\t\tif (nonessential) data.visible = input.readBoolean();\n\t\t\tskeletonData.slots.push(data);\n\t\t}\n\n\t\t// IK constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"IK constraint data name must not be null.\");\n\t\t\tlet data = new IkConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tnn = input.readInt(true);\n\t\t\tfor (let ii = 0; ii < nn; ii++)\n\t\t\t\tdata.bones.push(skeletonData.bones[input.readInt(true)]);\n\t\t\tdata.target = skeletonData.bones[input.readInt(true)];\n\t\t\tlet flags = input.readByte();\n\t\t\tdata.skinRequired = (flags & 1) != 0;\n\t\t\tdata.bendDirection = (flags & 2) != 0 ? 1 : -1;\n\t\t\tdata.compress = (flags & 4) != 0;\n\t\t\tdata.stretch = (flags & 8) != 0;\n\t\t\tdata.uniform = (flags & 16) != 0;\n\t\t\tif ((flags & 32) != 0) data.mix = (flags & 64) != 0 ? input.readFloat() : 1;\n\t\t\tif ((flags & 128) != 0) data.softness = input.readFloat() * scale;\n\t\t\tskeletonData.ikConstraints.push(data);\n\t\t}\n\n\t\t// Transform constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"Transform constraint data name must not be null.\");\n\t\t\tlet data = new TransformConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tnn = input.readInt(true);\n\t\t\tfor (let ii = 0; ii < nn; ii++)\n\t\t\t\tdata.bones.push(skeletonData.bones[input.readInt(true)]);\n\t\t\tdata.target = skeletonData.bones[input.readInt(true)];\n\t\t\tlet flags = input.readByte();\n\t\t\tdata.skinRequired = (flags & 1) != 0;\n\t\t\tdata.local = (flags & 2) != 0;\n\t\t\tdata.relative = (flags & 4) != 0;\n\t\t\tif ((flags & 8) != 0) data.offsetRotation = input.readFloat();\n\t\t\tif ((flags & 16) != 0) data.offsetX = input.readFloat() * scale;\n\t\t\tif ((flags & 32) != 0) data.offsetY = input.readFloat() * scale;\n\t\t\tif ((flags & 64) != 0) data.offsetScaleX = input.readFloat();\n\t\t\tif ((flags & 128) != 0) data.offsetScaleY = input.readFloat();\n\t\t\tflags = input.readByte();\n\t\t\tif ((flags & 1) != 0) data.offsetShearY = input.readFloat();\n\t\t\tif ((flags & 2) != 0) data.mixRotate = input.readFloat();\n\t\t\tif ((flags & 4) != 0) data.mixX = input.readFloat();\n\t\t\tif ((flags & 8) != 0) data.mixY = input.readFloat();\n\t\t\tif ((flags & 16) != 0) data.mixScaleX = input.readFloat();\n\t\t\tif ((flags & 32) != 0) data.mixScaleY = input.readFloat();\n\t\t\tif ((flags & 64) != 0) data.mixShearY = input.readFloat();\n\t\t\tskeletonData.transformConstraints.push(data);\n\t\t}\n\n\t\t// Path constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"Path constraint data name must not be null.\");\n\t\t\tlet data = new PathConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tdata.skinRequired = input.readBoolean();\n\t\t\tnn = input.readInt(true);\n\t\t\tfor (let ii = 0; ii < nn; ii++)\n\t\t\t\tdata.bones.push(skeletonData.bones[input.readInt(true)]);\n\t\t\tdata.target = skeletonData.slots[input.readInt(true)];\n\t\t\tconst flags = input.readByte();\n\t\t\tdata.positionMode = flags & 1;\n\t\t\tdata.spacingMode = (flags >> 1) & 3;\n\t\t\tdata.rotateMode = (flags >> 3) & 3;\n\t\t\tif ((flags & 128) != 0) data.offsetRotation = input.readFloat();\n\t\t\tdata.position = input.readFloat();\n\t\t\tif (data.positionMode == PositionMode.Fixed) data.position *= scale;\n\t\t\tdata.spacing = input.readFloat();\n\t\t\tif (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) data.spacing *= scale;\n\t\t\tdata.mixRotate = input.readFloat();\n\t\t\tdata.mixX = input.readFloat();\n\t\t\tdata.mixY = input.readFloat();\n\t\t\tskeletonData.pathConstraints.push(data);\n\t\t}\n\n\t\t// Physics constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tconst name = input.readString();\n\t\t\tif (!name) throw new Error(\"Physics constraint data name must not be null.\");\n\t\t\tconst data = new PhysicsConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tdata.bone = skeletonData.bones[input.readInt(true)];\n\t\t\tlet flags = input.readByte();\n\t\t\tdata.skinRequired = (flags & 1) != 0;\n\t\t\tif ((flags & 2) != 0) data.x = input.readFloat();\n\t\t\tif ((flags & 4) != 0) data.y = input.readFloat();\n\t\t\tif ((flags & 8) != 0) data.rotate = input.readFloat();\n\t\t\tif ((flags & 16) != 0) data.scaleX = input.readFloat();\n\t\t\tif ((flags & 32) != 0) data.shearX = input.readFloat();\n\t\t\tdata.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale;\n\t\t\tdata.step = 1 / input.readUnsignedByte();\n\t\t\tdata.inertia = input.readFloat();\n\t\t\tdata.strength = input.readFloat();\n\t\t\tdata.damping = input.readFloat();\n\t\t\tdata.massInverse = (flags & 128) != 0 ? input.readFloat() : 1;\n\t\t\tdata.wind = input.readFloat();\n\t\t\tdata.gravity = input.readFloat();\n\t\t\tflags = input.readByte();\n\t\t\tif ((flags & 1) != 0) data.inertiaGlobal = true;\n\t\t\tif ((flags & 2) != 0) data.strengthGlobal = true;\n\t\t\tif ((flags & 4) != 0) data.dampingGlobal = true;\n\t\t\tif ((flags & 8) != 0) data.massGlobal = true;\n\t\t\tif ((flags & 16) != 0) data.windGlobal = true;\n\t\t\tif ((flags & 32) != 0) data.gravityGlobal = true;\n\t\t\tif ((flags & 64) != 0) data.mixGlobal = true;\n\t\t\tdata.mix = (flags & 128) != 0 ? input.readFloat() : 1;\n\t\t\tskeletonData.physicsConstraints.push(data);\n\t\t}\n\n\t\t// Default skin.\n\t\tlet defaultSkin = this.readSkin(input, skeletonData, true, nonessential);\n\t\tif (defaultSkin) {\n\t\t\tskeletonData.defaultSkin = defaultSkin;\n\t\t\tskeletonData.skins.push(defaultSkin);\n\t\t}\n\n\t\t// Skins.\n\t\t{\n\t\t\tlet i = skeletonData.skins.length;\n\t\t\tUtils.setArraySize(skeletonData.skins, n = i + input.readInt(true));\n\t\t\tfor (; i < n; i++) {\n\t\t\t\tlet skin = this.readSkin(input, skeletonData, false, nonessential);\n\t\t\t\tif (!skin) throw new Error(\"readSkin() should not have returned null.\");\n\t\t\t\tskeletonData.skins[i] = skin;\n\t\t\t}\n\t\t}\n\n\t\t// Linked meshes.\n\t\tn = this.linkedMeshes.length;\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet linkedMesh = this.linkedMeshes[i];\n\t\t\tconst skin = skeletonData.skins[linkedMesh.skinIndex];\n\t\t\tif (!linkedMesh.parent) throw new Error(\"Linked mesh parent must not be null\");\n\t\t\tlet parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);\n\t\t\tif (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);\n\t\t\tlinkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent as VertexAttachment : linkedMesh.mesh;\n\t\t\tlinkedMesh.mesh.setParentMesh(parent as MeshAttachment);\n\t\t\tif (linkedMesh.mesh.region != null) linkedMesh.mesh.updateRegion();\n\t\t}\n\t\tthis.linkedMeshes.length = 0;\n\n\t\t// Events.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet eventName = input.readString();\n\t\t\tif (!eventName) throw new Error(\"Event data name must not be null\");\n\t\t\tlet data = new EventData(eventName);\n\t\t\tdata.intValue = input.readInt(false);\n\t\t\tdata.floatValue = input.readFloat();\n\t\t\tdata.stringValue = input.readString();\n\t\t\tdata.audioPath = input.readString();\n\t\t\tif (data.audioPath) {\n\t\t\t\tdata.volume = input.readFloat();\n\t\t\t\tdata.balance = input.readFloat();\n\t\t\t}\n\t\t\tskeletonData.events.push(data);\n\t\t}\n\n\t\t// Animations.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet animationName = input.readString();\n\t\t\tif (!animationName) throw new Error(\"Animatio name must not be null.\");\n\t\t\tskeletonData.animations.push(this.readAnimation(input, animationName, skeletonData));\n\t\t}\n\t\treturn skeletonData;\n\t}\n\n\tprivate readSkin (input: BinaryInput, skeletonData: SkeletonData, defaultSkin: boolean, nonessential: boolean): Skin | null {\n\t\tlet skin = null;\n\t\tlet slotCount = 0;\n\n\t\tif (defaultSkin) {\n\t\t\tslotCount = input.readInt(true)\n\t\t\tif (slotCount == 0) return null;\n\t\t\tskin = new Skin(\"default\");\n\t\t} else {\n\t\t\tlet skinName = input.readString();\n\t\t\tif (!skinName) throw new Error(\"Skin name must not be null.\");\n\t\t\tskin = new Skin(skinName);\n\t\t\tif (nonessential) Color.rgba8888ToColor(skin.color, input.readInt32());\n\t\t\tskin.bones.length = input.readInt(true);\n\t\t\tfor (let i = 0, n = skin.bones.length; i < n; i++)\n\t\t\t\tskin.bones[i] = skeletonData.bones[input.readInt(true)];\n\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]);\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]);\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]);\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.physicsConstraints[input.readInt(true)]);\n\n\t\t\tslotCount = input.readInt(true);\n\t\t}\n\n\t\tfor (let i = 0; i < slotCount; i++) {\n\t\t\tlet slotIndex = input.readInt(true);\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet name = input.readStringRef();\n\t\t\t\tif (!name)\n\t\t\t\t\tthrow new Error(\"Attachment name must not be null\");\n\t\t\t\tlet attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential);\n\t\t\t\tif (attachment) skin.setAttachment(slotIndex, name, attachment);\n\t\t\t}\n\t\t}\n\t\treturn skin;\n\t}\n\n\tprivate readAttachment (input: BinaryInput, skeletonData: SkeletonData, skin: Skin, slotIndex: number, attachmentName: string | null | undefined, nonessential: boolean): Attachment | null {\n\t\tlet scale = this.scale;\n\n\t\tlet flags = input.readByte();\n\t\tconst name = (flags & 8) != 0 ? input.readStringRef() : attachmentName;\n\t\tif (!name) throw new Error(\"Attachment name must not be null\");\n\t\tswitch ((flags & 0b111) as AttachmentType) { // BUG?\n\t\t\tcase AttachmentType.Region: {\n\t\t\t\tlet path = (flags & 16) != 0 ? input.readStringRef() : null;\n\t\t\t\tconst color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff;\n\t\t\t\tconst sequence = (flags & 64) != 0 ? this.readSequence(input) : null;\n\t\t\t\tlet rotation = (flags & 128) != 0 ? input.readFloat() : 0;\n\t\t\t\tlet x = input.readFloat();\n\t\t\t\tlet y = input.readFloat();\n\t\t\t\tlet scaleX = input.readFloat();\n\t\t\t\tlet scaleY = input.readFloat();\n\t\t\t\tlet width = input.readFloat();\n\t\t\t\tlet height = input.readFloat();\n\n\t\t\t\tif (!path) path = name;\n\t\t\t\tlet region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);\n\t\t\t\tif (!region) return null;\n\t\t\t\tregion.path = path;\n\t\t\t\tregion.x = x * scale;\n\t\t\t\tregion.y = y * scale;\n\t\t\t\tregion.scaleX = scaleX;\n\t\t\t\tregion.scaleY = scaleY;\n\t\t\t\tregion.rotation = rotation;\n\t\t\t\tregion.width = width * scale;\n\t\t\t\tregion.height = height * scale;\n\t\t\t\tColor.rgba8888ToColor(region.color, color);\n\t\t\t\tregion.sequence = sequence;\n\t\t\t\tif (sequence == null) region.updateRegion();\n\t\t\t\treturn region;\n\t\t\t}\n\t\t\tcase AttachmentType.BoundingBox: {\n\t\t\t\tlet vertices = this.readVertices(input, (flags & 16) != 0);\n\t\t\t\tlet color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tlet box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);\n\t\t\t\tif (!box) return null;\n\t\t\t\tbox.worldVerticesLength = vertices.length;\n\t\t\t\tbox.vertices = vertices.vertices!;\n\t\t\t\tbox.bones = vertices.bones;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(box.color, color);\n\t\t\t\treturn box;\n\t\t\t}\n\t\t\tcase AttachmentType.Mesh: {\n\t\t\t\tlet path = (flags & 16) != 0 ? input.readStringRef() : name;\n\t\t\t\tconst color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff;\n\t\t\t\tconst sequence = (flags & 64) != 0 ? this.readSequence(input) : null;\n\t\t\t\tconst hullLength = input.readInt(true);\n\t\t\t\tconst vertices = this.readVertices(input, (flags & 128) != 0);\n\t\t\t\tconst uvs = this.readFloatArray(input, vertices.length, 1);\n\t\t\t\tconst triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3);\n\t\t\t\tlet edges: number[] = [];\n\t\t\t\tlet width = 0, height = 0;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\tedges = this.readShortArray(input, input.readInt(true));\n\t\t\t\t\twidth = input.readFloat();\n\t\t\t\t\theight = input.readFloat();\n\t\t\t\t}\n\n\t\t\t\tif (!path) path = name;\n\t\t\t\tlet mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);\n\t\t\t\tif (!mesh) return null;\n\t\t\t\tmesh.path = path;\n\t\t\t\tColor.rgba8888ToColor(mesh.color, color);\n\t\t\t\tmesh.bones = vertices.bones;\n\t\t\t\tmesh.vertices = vertices.vertices!;\n\t\t\t\tmesh.worldVerticesLength = vertices.length;\n\t\t\t\tmesh.triangles = triangles;\n\t\t\t\tmesh.regionUVs = uvs;\n\t\t\t\tif (sequence == null) mesh.updateRegion();\n\t\t\t\tmesh.hullLength = hullLength << 1;\n\t\t\t\tmesh.sequence = sequence;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\tmesh.edges = edges;\n\t\t\t\t\tmesh.width = width * scale;\n\t\t\t\t\tmesh.height = height * scale;\n\t\t\t\t}\n\t\t\t\treturn mesh;\n\t\t\t}\n\t\t\tcase AttachmentType.LinkedMesh: {\n\t\t\t\tconst path = (flags & 16) != 0 ? input.readStringRef() : name;\n\t\t\t\tif (path == null) throw new Error(\"Path of linked mesh must not be null\");\n\t\t\t\tconst color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff;\n\t\t\t\tconst sequence = (flags & 64) != 0 ? this.readSequence(input) : null;\n\t\t\t\tconst inheritTimelines = (flags & 128) != 0;\n\t\t\t\tconst skinIndex = input.readInt(true);\n\t\t\t\tconst parent = input.readStringRef();\n\t\t\t\tlet width = 0, height = 0;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\twidth = input.readFloat();\n\t\t\t\t\theight = input.readFloat();\n\t\t\t\t}\n\n\t\t\t\tlet mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);\n\t\t\t\tif (!mesh) return null;\n\t\t\t\tmesh.path = path;\n\t\t\t\tColor.rgba8888ToColor(mesh.color, color);\n\t\t\t\tmesh.sequence = sequence;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\tmesh.width = width * scale;\n\t\t\t\t\tmesh.height = height * scale;\n\t\t\t\t}\n\t\t\t\tthis.linkedMeshes.push(new LinkedMesh(mesh, skinIndex, slotIndex, parent, inheritTimelines));\n\t\t\t\treturn mesh;\n\t\t\t}\n\t\t\tcase AttachmentType.Path: {\n\t\t\t\tconst closed = (flags & 16) != 0;\n\t\t\t\tconst constantSpeed = (flags & 32) != 0;\n\t\t\t\tconst vertices = this.readVertices(input, (flags & 64) != 0);\n\n\t\t\t\tconst lengths = Utils.newArray(vertices.length / 6, 0);\n\t\t\t\tfor (let i = 0, n = lengths.length; i < n; i++)\n\t\t\t\t\tlengths[i] = input.readFloat() * scale;\n\t\t\t\tconst color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tconst path = this.attachmentLoader.newPathAttachment(skin, name);\n\t\t\t\tif (!path) return null;\n\t\t\t\tpath.closed = closed;\n\t\t\t\tpath.constantSpeed = constantSpeed;\n\t\t\t\tpath.worldVerticesLength = vertices.length;\n\t\t\t\tpath.vertices = vertices.vertices!;\n\t\t\t\tpath.bones = vertices.bones;\n\t\t\t\tpath.lengths = lengths;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(path.color, color);\n\t\t\t\treturn path;\n\t\t\t}\n\t\t\tcase AttachmentType.Point: {\n\t\t\t\tconst rotation = input.readFloat();\n\t\t\t\tconst x = input.readFloat();\n\t\t\t\tconst y = input.readFloat();\n\t\t\t\tconst color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tconst point = this.attachmentLoader.newPointAttachment(skin, name);\n\t\t\t\tif (!point) return null;\n\t\t\t\tpoint.x = x * scale;\n\t\t\t\tpoint.y = y * scale;\n\t\t\t\tpoint.rotation = rotation;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(point.color, color);\n\t\t\t\treturn point;\n\t\t\t}\n\t\t\tcase AttachmentType.Clipping: {\n\t\t\t\tconst endSlotIndex = input.readInt(true);\n\t\t\t\tconst vertices = this.readVertices(input, (flags & 16) != 0);\n\t\t\t\tlet color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tlet clip = this.attachmentLoader.newClippingAttachment(skin, name);\n\t\t\t\tif (!clip) return null;\n\t\t\t\tclip.endSlot = skeletonData.slots[endSlotIndex];\n\t\t\t\tclip.worldVerticesLength = vertices.length;\n\t\t\t\tclip.vertices = vertices.vertices!;\n\t\t\t\tclip.bones = vertices.bones;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(clip.color, color);\n\t\t\t\treturn clip;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate readSequence (input: BinaryInput) {\n\t\tlet sequence = new Sequence(input.readInt(true));\n\t\tsequence.start = input.readInt(true);\n\t\tsequence.digits = input.readInt(true);\n\t\tsequence.setupIndex = input.readInt(true);\n\t\treturn sequence;\n\t}\n\n\tprivate readVertices (input: BinaryInput, weighted: boolean): Vertices {\n\t\tconst scale = this.scale;\n\t\tconst vertexCount = input.readInt(true);\n\t\tconst vertices = new Vertices();\n\t\tvertices.length = vertexCount << 1;\n\t\tif (!weighted) {\n\t\t\tvertices.vertices = this.readFloatArray(input, vertices.length, scale);\n\t\t\treturn vertices;\n\t\t}\n\t\tlet weights = new Array();\n\t\tlet bonesArray = new Array();\n\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\tlet boneCount = input.readInt(true);\n\t\t\tbonesArray.push(boneCount);\n\t\t\tfor (let ii = 0; ii < boneCount; ii++) {\n\t\t\t\tbonesArray.push(input.readInt(true));\n\t\t\t\tweights.push(input.readFloat() * scale);\n\t\t\t\tweights.push(input.readFloat() * scale);\n\t\t\t\tweights.push(input.readFloat());\n\t\t\t}\n\t\t}\n\t\tvertices.vertices = Utils.toFloatArray(weights);\n\t\tvertices.bones = bonesArray;\n\t\treturn vertices;\n\t}\n\n\tprivate readFloatArray (input: BinaryInput, n: number, scale: number): number[] {\n\t\tlet array = new Array(n);\n\t\tif (scale == 1) {\n\t\t\tfor (let i = 0; i < n; i++)\n\t\t\t\tarray[i] = input.readFloat();\n\t\t} else {\n\t\t\tfor (let i = 0; i < n; i++)\n\t\t\t\tarray[i] = input.readFloat() * scale;\n\t\t}\n\t\treturn array;\n\t}\n\n\tprivate readShortArray (input: BinaryInput, n: number): number[] {\n\t\tlet array = new Array(n);\n\t\tfor (let i = 0; i < n; i++)\n\t\t\tarray[i] = input.readInt(true);\n\t\treturn array;\n\t}\n\n\tprivate readAnimation (input: BinaryInput, name: string, skeletonData: SkeletonData): Animation {\n\t\tinput.readInt(true); // Number of timelines.\n\t\tlet timelines = new Array();\n\t\tlet scale = this.scale;\n\n\t\t// Slot timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet slotIndex = input.readInt(true);\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet timelineType = input.readByte();\n\t\t\t\tlet frameCount = input.readInt(true);\n\t\t\t\tlet frameLast = frameCount - 1;\n\t\t\t\tswitch (timelineType) {\n\t\t\t\t\tcase SLOT_ATTACHMENT: {\n\t\t\t\t\t\tlet timeline = new AttachmentTimeline(frameCount, slotIndex);\n\t\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++)\n\t\t\t\t\t\t\ttimeline.setFrame(frame, input.readFloat(), input.readStringRef());\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGBA: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGBATimeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet a = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b, a);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet a2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = r2;\n\t\t\t\t\t\t\tg = g2;\n\t\t\t\t\t\t\tb = b2;\n\t\t\t\t\t\t\ta = a2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGB: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGBTimeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = r2;\n\t\t\t\t\t\t\tg = g2;\n\t\t\t\t\t\t\tb = b2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGBA2: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet a = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b, a, r2, g2, b2);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet nr = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet na = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nr2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = nr;\n\t\t\t\t\t\t\tg = ng;\n\t\t\t\t\t\t\tb = nb;\n\t\t\t\t\t\t\ta = na;\n\t\t\t\t\t\t\tr2 = nr2;\n\t\t\t\t\t\t\tg2 = ng2;\n\t\t\t\t\t\t\tb2 = nb2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGB2: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b, r2, g2, b2);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet nr = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nr2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = nr;\n\t\t\t\t\t\t\tg = ng;\n\t\t\t\t\t\t\tb = nb;\n\t\t\t\t\t\t\tr2 = nr2;\n\t\t\t\t\t\t\tg2 = ng2;\n\t\t\t\t\t\t\tb2 = nb2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_ALPHA: {\n\t\t\t\t\t\tlet timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex);\n\t\t\t\t\t\tlet time = input.readFloat(), a = input.readUnsignedByte() / 255;\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, a);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet a2 = input.readUnsignedByte() / 255;\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\ta = a2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Bone timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet boneIndex = input.readInt(true);\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet type = input.readByte(), frameCount = input.readInt(true);\n\t\t\t\tif (type == BONE_INHERIT) {\n\t\t\t\t\tlet timeline = new InheritTimeline(frameCount, boneIndex);\n\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++) {\n\t\t\t\t\t\ttimeline.setFrame(frame, input.readFloat(), input.readByte());\n\t\t\t\t\t}\n\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase BONE_ROTATE:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_TRANSLATE:\n\t\t\t\t\t\ttimelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_TRANSLATEX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_TRANSLATEY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SCALE:\n\t\t\t\t\t\ttimelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SCALEX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SCALEY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SHEAR:\n\t\t\t\t\t\ttimelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SHEARX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SHEARY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IK constraint timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;\n\t\t\tlet timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index);\n\t\t\tlet flags = input.readByte();\n\t\t\tlet time = input.readFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0;\n\t\t\tlet softness = (flags & 4) != 0 ? input.readFloat() * scale : 0;\n\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\ttimeline.setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0);\n\t\t\t\tif (frame == frameLast) break;\n\t\t\t\tflags = input.readByte();\n\t\t\t\tconst time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0;\n\t\t\t\tconst softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0;\n\t\t\t\tif ((flags & 64) != 0) {\n\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t} else if ((flags & 128) != 0) {\n\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);\n\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);\n\t\t\t\t}\n\t\t\t\ttime = time2;\n\t\t\t\tmix = mix2;\n\t\t\t\tsoftness = softness2;\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Transform constraint timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;\n\t\t\tlet timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index);\n\t\t\tlet time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(),\n\t\t\t\tmixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat();\n\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);\n\t\t\t\tif (frame == frameLast) break;\n\t\t\t\tlet time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(),\n\t\t\t\t\tmixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat();\n\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1);\n\t\t\t\t}\n\t\t\t\ttime = time2;\n\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\tmixX = mixX2;\n\t\t\t\tmixY = mixY2;\n\t\t\t\tmixScaleX = mixScaleX2;\n\t\t\t\tmixScaleY = mixScaleY2;\n\t\t\t\tmixShearY = mixShearY2;\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Path constraint timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet index = input.readInt(true);\n\t\t\tlet data = skeletonData.pathConstraints[index];\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tconst type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase PATH_POSITION:\n\t\t\t\t\t\ttimelines\n\t\t\t\t\t\t\t.push(readTimeline1(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index),\n\t\t\t\t\t\t\t\tdata.positionMode == PositionMode.Fixed ? scale : 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PATH_SPACING:\n\t\t\t\t\t\ttimelines\n\t\t\t\t\t\t\t.push(readTimeline1(input, new PathConstraintSpacingTimeline(frameCount, bezierCount, index),\n\t\t\t\t\t\t\t\tdata.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PATH_MIX:\n\t\t\t\t\t\tlet timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index);\n\t\t\t\t\t\tlet time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat();\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(),\n\t\t\t\t\t\t\t\tmixY2 = input.readFloat();\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\t\t\t\tmixX = mixX2;\n\t\t\t\t\t\t\tmixY = mixY2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Physics timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tconst index = input.readInt(true) - 1;\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tconst type = input.readByte(), frameCount = input.readInt(true);\n\t\t\t\tif (type == PHYSICS_RESET) {\n\t\t\t\t\tconst timeline = new PhysicsConstraintResetTimeline(frameCount, index);\n\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++)\n\t\t\t\t\t\ttimeline.setFrame(frame, input.readFloat());\n\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst bezierCount = input.readInt(true);\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase PHYSICS_INERTIA:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_STRENGTH:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_DAMPING:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_MASS:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_WIND:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_GRAVITY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_MIX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Deform timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet skin = skeletonData.skins[input.readInt(true)];\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet slotIndex = input.readInt(true);\n\t\t\t\tfor (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) {\n\t\t\t\t\tlet attachmentName = input.readStringRef();\n\t\t\t\t\tif (!attachmentName) throw new Error(\"attachmentName must not be null.\");\n\t\t\t\t\tlet attachment = skin.getAttachment(slotIndex, attachmentName);\n\t\t\t\t\tlet timelineType = input.readByte();\n\t\t\t\t\tlet frameCount = input.readInt(true);\n\t\t\t\t\tlet frameLast = frameCount - 1;\n\n\t\t\t\t\tswitch (timelineType) {\n\t\t\t\t\t\tcase ATTACHMENT_DEFORM: {\n\t\t\t\t\t\t\tlet vertexAttachment = attachment as VertexAttachment;\n\t\t\t\t\t\t\tlet weighted = vertexAttachment.bones;\n\t\t\t\t\t\t\tlet vertices = vertexAttachment.vertices;\n\t\t\t\t\t\t\tlet deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;\n\n\n\t\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\t\tlet timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment);\n\n\t\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\t\tlet deform;\n\t\t\t\t\t\t\t\tlet end = input.readInt(true);\n\t\t\t\t\t\t\t\tif (end == 0)\n\t\t\t\t\t\t\t\t\tdeform = weighted ? Utils.newFloatArray(deformLength) : vertices;\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tdeform = Utils.newFloatArray(deformLength);\n\t\t\t\t\t\t\t\t\tlet start = input.readInt(true);\n\t\t\t\t\t\t\t\t\tend += start;\n\t\t\t\t\t\t\t\t\tif (scale == 1) {\n\t\t\t\t\t\t\t\t\t\tfor (let v = start; v < end; v++)\n\t\t\t\t\t\t\t\t\t\t\tdeform[v] = input.readFloat();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tfor (let v = start; v < end; v++)\n\t\t\t\t\t\t\t\t\t\t\tdeform[v] = input.readFloat() * scale;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (!weighted) {\n\t\t\t\t\t\t\t\t\t\tfor (let v = 0, vn = deform.length; v < vn; v++)\n\t\t\t\t\t\t\t\t\t\t\tdeform[v] += vertices[v];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, deform);\n\t\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase ATTACHMENT_SEQUENCE: {\n\t\t\t\t\t\t\tlet timeline = new SequenceTimeline(frameCount, slotIndex, attachment as unknown as HasTextureRegion);\n\t\t\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++) {\n\t\t\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\t\t\tlet modeAndIndex = input.readInt32();\n\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, SequenceModeValues[modeAndIndex & 0xf], modeAndIndex >> 4,\n\t\t\t\t\t\t\t\t\tinput.readFloat());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Draw order timeline.\n\t\tlet drawOrderCount = input.readInt(true);\n\t\tif (drawOrderCount > 0) {\n\t\t\tlet timeline = new DrawOrderTimeline(drawOrderCount);\n\t\t\tlet slotCount = skeletonData.slots.length;\n\t\t\tfor (let i = 0; i < drawOrderCount; i++) {\n\t\t\t\tlet time = input.readFloat();\n\t\t\t\tlet offsetCount = input.readInt(true);\n\t\t\t\tlet drawOrder = Utils.newArray(slotCount, 0);\n\t\t\t\tfor (let ii = slotCount - 1; ii >= 0; ii--)\n\t\t\t\t\tdrawOrder[ii] = -1;\n\t\t\t\tlet unchanged = Utils.newArray(slotCount - offsetCount, 0);\n\t\t\t\tlet originalIndex = 0, unchangedIndex = 0;\n\t\t\t\tfor (let ii = 0; ii < offsetCount; ii++) {\n\t\t\t\t\tlet slotIndex = input.readInt(true);\n\t\t\t\t\t// Collect unchanged items.\n\t\t\t\t\twhile (originalIndex != slotIndex)\n\t\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t\t// Set changed items.\n\t\t\t\t\tdrawOrder[originalIndex + input.readInt(true)] = originalIndex++;\n\t\t\t\t}\n\t\t\t\t// Collect remaining unchanged items.\n\t\t\t\twhile (originalIndex < slotCount)\n\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t// Fill in unchanged items.\n\t\t\t\tfor (let ii = slotCount - 1; ii >= 0; ii--)\n\t\t\t\t\tif (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];\n\t\t\t\ttimeline.setFrame(i, time, drawOrder);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Event timeline.\n\t\tlet eventCount = input.readInt(true);\n\t\tif (eventCount > 0) {\n\t\t\tlet timeline = new EventTimeline(eventCount);\n\t\t\tfor (let i = 0; i < eventCount; i++) {\n\t\t\t\tlet time = input.readFloat();\n\t\t\t\tlet eventData = skeletonData.events[input.readInt(true)];\n\t\t\t\tlet event = new Event(time, eventData);\n\t\t\t\tevent.intValue = input.readInt(false);\n\t\t\t\tevent.floatValue = input.readFloat();\n\t\t\t\tevent.stringValue = input.readString();\n\t\t\t\tif (event.stringValue == null) event.stringValue = eventData.stringValue;\n\t\t\t\tif (event.data.audioPath) {\n\t\t\t\t\tevent.volume = input.readFloat();\n\t\t\t\t\tevent.balance = input.readFloat();\n\t\t\t\t}\n\t\t\t\ttimeline.setFrame(i, event);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\tlet duration = 0;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\tduration = Math.max(duration, timelines[i].getDuration());\n\t\treturn new Animation(name, timelines, duration);\n\t}\n}\n\nexport class BinaryInput {\n\tconstructor (data: Uint8Array | ArrayBuffer, public strings = new Array(), private index: number = 0, private buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) {\n\t}\n\n\treadByte (): number {\n\t\treturn this.buffer.getInt8(this.index++);\n\t}\n\n\treadUnsignedByte (): number {\n\t\treturn this.buffer.getUint8(this.index++);\n\t}\n\n\treadShort (): number {\n\t\tlet value = this.buffer.getInt16(this.index);\n\t\tthis.index += 2;\n\t\treturn value;\n\t}\n\n\treadInt32 (): number {\n\t\tlet value = this.buffer.getInt32(this.index)\n\t\tthis.index += 4;\n\t\treturn value;\n\t}\n\n\treadInt (optimizePositive: boolean) {\n\t\tlet b = this.readByte();\n\t\tlet result = b & 0x7F;\n\t\tif ((b & 0x80) != 0) {\n\t\t\tb = this.readByte();\n\t\t\tresult |= (b & 0x7F) << 7;\n\t\t\tif ((b & 0x80) != 0) {\n\t\t\t\tb = this.readByte();\n\t\t\t\tresult |= (b & 0x7F) << 14;\n\t\t\t\tif ((b & 0x80) != 0) {\n\t\t\t\t\tb = this.readByte();\n\t\t\t\t\tresult |= (b & 0x7F) << 21;\n\t\t\t\t\tif ((b & 0x80) != 0) {\n\t\t\t\t\t\tb = this.readByte();\n\t\t\t\t\t\tresult |= (b & 0x7F) << 28;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn optimizePositive ? result : ((result >>> 1) ^ -(result & 1));\n\t}\n\n\treadStringRef (): string | null {\n\t\tlet index = this.readInt(true);\n\t\treturn index == 0 ? null : this.strings[index - 1];\n\t}\n\n\treadString (): string | null {\n\t\tlet byteCount = this.readInt(true);\n\t\tswitch (byteCount) {\n\t\t\tcase 0:\n\t\t\t\treturn null;\n\t\t\tcase 1:\n\t\t\t\treturn \"\";\n\t\t}\n\t\tbyteCount--;\n\t\tlet chars = \"\";\n\t\tlet charCount = 0;\n\t\tfor (let i = 0; i < byteCount;) {\n\t\t\tlet b = this.readUnsignedByte();\n\t\t\tswitch (b >> 4) {\n\t\t\t\tcase 12:\n\t\t\t\tcase 13:\n\t\t\t\t\tchars += String.fromCharCode(((b & 0x1F) << 6 | this.readByte() & 0x3F));\n\t\t\t\t\ti += 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 14:\n\t\t\t\t\tchars += String.fromCharCode(((b & 0x0F) << 12 | (this.readByte() & 0x3F) << 6 | this.readByte() & 0x3F));\n\t\t\t\t\ti += 3;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tchars += String.fromCharCode(b);\n\t\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn chars;\n\t}\n\n\treadFloat (): number {\n\t\tlet value = this.buffer.getFloat32(this.index);\n\t\tthis.index += 4;\n\t\treturn value;\n\t}\n\n\treadBoolean (): boolean {\n\t\treturn this.readByte() != 0;\n\t}\n}\n\nclass LinkedMesh {\n\tparent: string | null; skinIndex: number;\n\tslotIndex: number;\n\tmesh: MeshAttachment;\n\tinheritTimeline: boolean;\n\n\tconstructor (mesh: MeshAttachment, skinIndex: number, slotIndex: number, parent: string | null, inheritDeform: boolean) {\n\t\tthis.mesh = mesh;\n\t\tthis.skinIndex = skinIndex;\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.parent = parent;\n\t\tthis.inheritTimeline = inheritDeform;\n\t}\n}\n\nclass Vertices {\n\tconstructor (public bones: Array | null = null, public vertices: Array | Float32Array | null = null, public length: number = 0) { }\n}\n\nenum AttachmentType { Region, BoundingBox, Mesh, LinkedMesh, Path, Point, Clipping }\n\nfunction readTimeline1 (input: BinaryInput, timeline: CurveTimeline1, scale: number): CurveTimeline1 {\n\tlet time = input.readFloat(), value = input.readFloat() * scale;\n\tfor (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value);\n\t\tif (frame == frameLast) break;\n\t\tlet time2 = input.readFloat(), value2 = input.readFloat() * scale;\n\t\tswitch (input.readByte()) {\n\t\t\tcase CURVE_STEPPED:\n\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\tbreak;\n\t\t\tcase CURVE_BEZIER:\n\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale);\n\t\t}\n\t\ttime = time2;\n\t\tvalue = value2;\n\t}\n\treturn timeline;\n}\n\nfunction readTimeline2 (input: BinaryInput, timeline: CurveTimeline2, scale: number): CurveTimeline2 {\n\tlet time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale;\n\tfor (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value1, value2);\n\t\tif (frame == frameLast) break;\n\t\tlet time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale;\n\t\tswitch (input.readByte()) {\n\t\t\tcase CURVE_STEPPED:\n\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\tbreak;\n\t\t\tcase CURVE_BEZIER:\n\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale);\n\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale);\n\t\t}\n\t\ttime = time2;\n\t\tvalue1 = nvalue1;\n\t\tvalue2 = nvalue2;\n\t}\n\treturn timeline;\n}\n\nfunction setBezier (input: BinaryInput, timeline: CurveTimeline, bezier: number, frame: number, value: number,\n\ttime1: number, time2: number, value1: number, value2: number, scale: number) {\n\ttimeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2);\n}\n\nconst BONE_ROTATE = 0;\nconst BONE_TRANSLATE = 1;\nconst BONE_TRANSLATEX = 2;\nconst BONE_TRANSLATEY = 3;\nconst BONE_SCALE = 4;\nconst BONE_SCALEX = 5;\nconst BONE_SCALEY = 6;\nconst BONE_SHEAR = 7;\nconst BONE_SHEARX = 8;\nconst BONE_SHEARY = 9;\nconst BONE_INHERIT = 10;\n\nconst SLOT_ATTACHMENT = 0;\nconst SLOT_RGBA = 1;\nconst SLOT_RGB = 2;\nconst SLOT_RGBA2 = 3;\nconst SLOT_RGB2 = 4;\nconst SLOT_ALPHA = 5;\n\nconst ATTACHMENT_DEFORM = 0;\nconst ATTACHMENT_SEQUENCE = 1;\n\nconst PATH_POSITION = 0;\nconst PATH_SPACING = 1;\nconst PATH_MIX = 2;\n\nconst PHYSICS_INERTIA = 0;\nconst PHYSICS_STRENGTH = 1;\nconst PHYSICS_DAMPING = 2;\nconst PHYSICS_MASS = 4;\nconst PHYSICS_WIND = 5;\nconst PHYSICS_GRAVITY = 6;\nconst PHYSICS_MIX = 7;\nconst PHYSICS_RESET = 8;\n\nconst CURVE_LINEAR = 0;\nconst CURVE_STEPPED = 1;\nconst CURVE_BEZIER = 2;\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoundingBoxAttachment } from \"./attachments/BoundingBoxAttachment.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { NumberArrayLike, Pool, Utils } from \"./Utils.js\";\n\n/** Collects each visible {@link BoundingBoxAttachment} and computes the world vertices for its polygon. The polygon vertices are\n * provided along with convenience methods for doing hit detection. */\nexport class SkeletonBounds {\n\n\t/** The left edge of the axis aligned bounding box. */\n\tminX = 0;\n\n\t/** The bottom edge of the axis aligned bounding box. */\n\tminY = 0;\n\n\t/** The right edge of the axis aligned bounding box. */\n\tmaxX = 0;\n\n\t/** The top edge of the axis aligned bounding box. */\n\tmaxY = 0;\n\n\t/** The visible bounding boxes. */\n\tboundingBoxes = new Array();\n\n\t/** The world vertices for the bounding box polygons. */\n\tpolygons = new Array();\n\n\tprivate polygonPool = new Pool(() => {\n\t\treturn Utils.newFloatArray(16);\n\t});\n\n\t/** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding\n\t * box's polygon.\n\t * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the\n\t * SkeletonBounds AABB methods will always return true. */\n\tupdate (skeleton: Skeleton, updateAabb: boolean) {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tlet boundingBoxes = this.boundingBoxes;\n\t\tlet polygons = this.polygons;\n\t\tlet polygonPool = this.polygonPool;\n\t\tlet slots = skeleton.slots;\n\t\tlet slotCount = slots.length;\n\n\t\tboundingBoxes.length = 0;\n\t\tpolygonPool.freeAll(polygons);\n\t\tpolygons.length = 0;\n\n\t\tfor (let i = 0; i < slotCount; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (!slot.bone.active) continue;\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tif (attachment instanceof BoundingBoxAttachment) {\n\t\t\t\tlet boundingBox = attachment as BoundingBoxAttachment;\n\t\t\t\tboundingBoxes.push(boundingBox);\n\n\t\t\t\tlet polygon = polygonPool.obtain();\n\t\t\t\tif (polygon.length != boundingBox.worldVerticesLength) {\n\t\t\t\t\tpolygon = Utils.newFloatArray(boundingBox.worldVerticesLength);\n\t\t\t\t}\n\t\t\t\tpolygons.push(polygon);\n\t\t\t\tboundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);\n\t\t\t}\n\t\t}\n\n\t\tif (updateAabb) {\n\t\t\tthis.aabbCompute();\n\t\t} else {\n\t\t\tthis.minX = Number.POSITIVE_INFINITY;\n\t\t\tthis.minY = Number.POSITIVE_INFINITY;\n\t\t\tthis.maxX = Number.NEGATIVE_INFINITY;\n\t\t\tthis.maxY = Number.NEGATIVE_INFINITY;\n\t\t}\n\t}\n\n\taabbCompute () {\n\t\tlet minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;\n\t\tlet polygons = this.polygons;\n\t\tfor (let i = 0, n = polygons.length; i < n; i++) {\n\t\t\tlet polygon = polygons[i];\n\t\t\tlet vertices = polygon;\n\t\t\tfor (let ii = 0, nn = polygon.length; ii < nn; ii += 2) {\n\t\t\t\tlet x = vertices[ii];\n\t\t\t\tlet y = vertices[ii + 1];\n\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t}\n\t\t}\n\t\tthis.minX = minX;\n\t\tthis.minY = minY;\n\t\tthis.maxX = maxX;\n\t\tthis.maxY = maxY;\n\t}\n\n\t/** Returns true if the axis aligned bounding box contains the point. */\n\taabbContainsPoint (x: number, y: number) {\n\t\treturn x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;\n\t}\n\n\t/** Returns true if the axis aligned bounding box intersects the line segment. */\n\taabbIntersectsSegment (x1: number, y1: number, x2: number, y2: number) {\n\t\tlet minX = this.minX;\n\t\tlet minY = this.minY;\n\t\tlet maxX = this.maxX;\n\t\tlet maxY = this.maxY;\n\t\tif ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))\n\t\t\treturn false;\n\t\tlet m = (y2 - y1) / (x2 - x1);\n\t\tlet y = m * (minX - x1) + y1;\n\t\tif (y > minY && y < maxY) return true;\n\t\ty = m * (maxX - x1) + y1;\n\t\tif (y > minY && y < maxY) return true;\n\t\tlet x = (minY - y1) / m + x1;\n\t\tif (x > minX && x < maxX) return true;\n\t\tx = (maxY - y1) / m + x1;\n\t\tif (x > minX && x < maxX) return true;\n\t\treturn false;\n\t}\n\n\t/** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */\n\taabbIntersectsSkeleton (bounds: SkeletonBounds) {\n\t\treturn this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;\n\t}\n\n\t/** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more\n\t * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */\n\tcontainsPoint (x: number, y: number): BoundingBoxAttachment | null {\n\t\tlet polygons = this.polygons;\n\t\tfor (let i = 0, n = polygons.length; i < n; i++)\n\t\t\tif (this.containsPointPolygon(polygons[i], x, y)) return this.boundingBoxes[i];\n\t\treturn null;\n\t}\n\n\t/** Returns true if the polygon contains the point. */\n\tcontainsPointPolygon (polygon: NumberArrayLike, x: number, y: number) {\n\t\tlet vertices = polygon;\n\t\tlet nn = polygon.length;\n\n\t\tlet prevIndex = nn - 2;\n\t\tlet inside = false;\n\t\tfor (let ii = 0; ii < nn; ii += 2) {\n\t\t\tlet vertexY = vertices[ii + 1];\n\t\t\tlet prevY = vertices[prevIndex + 1];\n\t\t\tif ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {\n\t\t\t\tlet vertexX = vertices[ii];\n\t\t\t\tif (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside;\n\t\t\t}\n\t\t\tprevIndex = ii;\n\t\t}\n\t\treturn inside;\n\t}\n\n\t/** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it\n\t * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns\n\t * true. */\n\tintersectsSegment (x1: number, y1: number, x2: number, y2: number) {\n\t\tlet polygons = this.polygons;\n\t\tfor (let i = 0, n = polygons.length; i < n; i++)\n\t\t\tif (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) return this.boundingBoxes[i];\n\t\treturn null;\n\t}\n\n\t/** Returns true if the polygon contains any part of the line segment. */\n\tintersectsSegmentPolygon (polygon: NumberArrayLike, x1: number, y1: number, x2: number, y2: number) {\n\t\tlet vertices = polygon;\n\t\tlet nn = polygon.length;\n\n\t\tlet width12 = x1 - x2, height12 = y1 - y2;\n\t\tlet det1 = x1 * y2 - y1 * x2;\n\t\tlet x3 = vertices[nn - 2], y3 = vertices[nn - 1];\n\t\tfor (let ii = 0; ii < nn; ii += 2) {\n\t\t\tlet x4 = vertices[ii], y4 = vertices[ii + 1];\n\t\t\tlet det2 = x3 * y4 - y3 * x4;\n\t\t\tlet width34 = x3 - x4, height34 = y3 - y4;\n\t\t\tlet det3 = width12 * height34 - height12 * width34;\n\t\t\tlet x = (det1 * width34 - width12 * det2) / det3;\n\t\t\tif (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {\n\t\t\t\tlet y = (det1 * height34 - height12 * det2) / det3;\n\t\t\t\tif (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true;\n\t\t\t}\n\t\t\tx3 = x4;\n\t\t\ty3 = y4;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/** Returns the polygon for the specified bounding box, or null. */\n\tgetPolygon (boundingBox: BoundingBoxAttachment) {\n\t\tif (!boundingBox) throw new Error(\"boundingBox cannot be null.\");\n\t\tlet index = this.boundingBoxes.indexOf(boundingBox);\n\t\treturn index == -1 ? null : this.polygons[index];\n\t}\n\n\t/** The width of the axis aligned bounding box. */\n\tgetWidth () {\n\t\treturn this.maxX - this.minX;\n\t}\n\n\t/** The height of the axis aligned bounding box. */\n\tgetHeight () {\n\t\treturn this.maxY - this.minY;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { NumberArrayLike, Pool } from \"./Utils.js\";\n\nexport class Triangulator {\n\tprivate convexPolygons = new Array>();\n\tprivate convexPolygonsIndices = new Array>();\n\n\tprivate indicesArray = new Array();\n\tprivate isConcaveArray = new Array();\n\tprivate triangles = new Array();\n\n\tprivate polygonPool = new Pool>(() => {\n\t\treturn new Array();\n\t});\n\n\tprivate polygonIndicesPool = new Pool>(() => {\n\t\treturn new Array();\n\t});\n\n\tpublic triangulate (verticesArray: NumberArrayLike): Array {\n\t\tlet vertices = verticesArray;\n\t\tlet vertexCount = verticesArray.length >> 1;\n\n\t\tlet indices = this.indicesArray;\n\t\tindices.length = 0;\n\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\tindices[i] = i;\n\n\t\tlet isConcave = this.isConcaveArray;\n\t\tisConcave.length = 0;\n\t\tfor (let i = 0, n = vertexCount; i < n; ++i)\n\t\t\tisConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices);\n\n\t\tlet triangles = this.triangles;\n\t\ttriangles.length = 0;\n\n\t\twhile (vertexCount > 3) {\n\t\t\t// Find ear tip.\n\t\t\tlet previous = vertexCount - 1, i = 0, next = 1;\n\t\t\twhile (true) {\n\t\t\t\touter:\n\t\t\t\tif (!isConcave[i]) {\n\t\t\t\t\tlet p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;\n\t\t\t\t\tlet p1x = vertices[p1], p1y = vertices[p1 + 1];\n\t\t\t\t\tlet p2x = vertices[p2], p2y = vertices[p2 + 1];\n\t\t\t\t\tlet p3x = vertices[p3], p3y = vertices[p3 + 1];\n\t\t\t\t\tfor (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {\n\t\t\t\t\t\tif (!isConcave[ii]) continue;\n\t\t\t\t\t\tlet v = indices[ii] << 1;\n\t\t\t\t\t\tlet vx = vertices[v], vy = vertices[v + 1];\n\t\t\t\t\t\tif (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {\n\t\t\t\t\t\t\tif (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {\n\t\t\t\t\t\t\t\tif (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) break outer;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (next == 0) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif (!isConcave[i]) break;\n\t\t\t\t\t\ti--;\n\t\t\t\t\t} while (i > 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tprevious = i;\n\t\t\t\ti = next;\n\t\t\t\tnext = (next + 1) % vertexCount;\n\t\t\t}\n\n\t\t\t// Cut ear tip.\n\t\t\ttriangles.push(indices[(vertexCount + i - 1) % vertexCount]);\n\t\t\ttriangles.push(indices[i]);\n\t\t\ttriangles.push(indices[(i + 1) % vertexCount]);\n\t\t\tindices.splice(i, 1);\n\t\t\tisConcave.splice(i, 1);\n\t\t\tvertexCount--;\n\n\t\t\tlet previousIndex = (vertexCount + i - 1) % vertexCount;\n\t\t\tlet nextIndex = i == vertexCount ? 0 : i;\n\t\t\tisConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices);\n\t\t\tisConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices);\n\t\t}\n\n\t\tif (vertexCount == 3) {\n\t\t\ttriangles.push(indices[2]);\n\t\t\ttriangles.push(indices[0]);\n\t\t\ttriangles.push(indices[1]);\n\t\t}\n\n\t\treturn triangles;\n\t}\n\n\tdecompose (verticesArray: Array, triangles: Array): Array> {\n\t\tlet vertices = verticesArray;\n\t\tlet convexPolygons = this.convexPolygons;\n\t\tthis.polygonPool.freeAll(convexPolygons);\n\t\tconvexPolygons.length = 0;\n\n\t\tlet convexPolygonsIndices = this.convexPolygonsIndices;\n\t\tthis.polygonIndicesPool.freeAll(convexPolygonsIndices);\n\t\tconvexPolygonsIndices.length = 0;\n\n\t\tlet polygonIndices = this.polygonIndicesPool.obtain();\n\t\tpolygonIndices.length = 0;\n\n\t\tlet polygon = this.polygonPool.obtain();\n\t\tpolygon.length = 0;\n\n\t\t// Merge subsequent triangles if they form a triangle fan.\n\t\tlet fanBaseIndex = -1, lastWinding = 0;\n\t\tfor (let i = 0, n = triangles.length; i < n; i += 3) {\n\t\t\tlet t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;\n\t\t\tlet x1 = vertices[t1], y1 = vertices[t1 + 1];\n\t\t\tlet x2 = vertices[t2], y2 = vertices[t2 + 1];\n\t\t\tlet x3 = vertices[t3], y3 = vertices[t3 + 1];\n\n\t\t\t// If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan).\n\t\t\tlet merged = false;\n\t\t\tif (fanBaseIndex == t1) {\n\t\t\t\tlet o = polygon.length - 4;\n\t\t\t\tlet winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);\n\t\t\t\tlet winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);\n\t\t\t\tif (winding1 == lastWinding && winding2 == lastWinding) {\n\t\t\t\t\tpolygon.push(x3);\n\t\t\t\t\tpolygon.push(y3);\n\t\t\t\t\tpolygonIndices.push(t3);\n\t\t\t\t\tmerged = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Otherwise make this triangle the new base.\n\t\t\tif (!merged) {\n\t\t\t\tif (polygon.length > 0) {\n\t\t\t\t\tconvexPolygons.push(polygon);\n\t\t\t\t\tconvexPolygonsIndices.push(polygonIndices);\n\t\t\t\t} else {\n\t\t\t\t\tthis.polygonPool.free(polygon)\n\t\t\t\t\tthis.polygonIndicesPool.free(polygonIndices);\n\t\t\t\t}\n\t\t\t\tpolygon = this.polygonPool.obtain();\n\t\t\t\tpolygon.length = 0;\n\t\t\t\tpolygon.push(x1);\n\t\t\t\tpolygon.push(y1);\n\t\t\t\tpolygon.push(x2);\n\t\t\t\tpolygon.push(y2);\n\t\t\t\tpolygon.push(x3);\n\t\t\t\tpolygon.push(y3);\n\t\t\t\tpolygonIndices = this.polygonIndicesPool.obtain();\n\t\t\t\tpolygonIndices.length = 0;\n\t\t\t\tpolygonIndices.push(t1);\n\t\t\t\tpolygonIndices.push(t2);\n\t\t\t\tpolygonIndices.push(t3);\n\t\t\t\tlastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3);\n\t\t\t\tfanBaseIndex = t1;\n\t\t\t}\n\t\t}\n\n\t\tif (polygon.length > 0) {\n\t\t\tconvexPolygons.push(polygon);\n\t\t\tconvexPolygonsIndices.push(polygonIndices);\n\t\t}\n\n\t\t// Go through the list of polygons and try to merge the remaining triangles with the found triangle fans.\n\t\tfor (let i = 0, n = convexPolygons.length; i < n; i++) {\n\t\t\tpolygonIndices = convexPolygonsIndices[i];\n\t\t\tif (polygonIndices.length == 0) continue;\n\t\t\tlet firstIndex = polygonIndices[0];\n\t\t\tlet lastIndex = polygonIndices[polygonIndices.length - 1];\n\n\t\t\tpolygon = convexPolygons[i];\n\t\t\tlet o = polygon.length - 4;\n\t\t\tlet prevPrevX = polygon[o], prevPrevY = polygon[o + 1];\n\t\t\tlet prevX = polygon[o + 2], prevY = polygon[o + 3];\n\t\t\tlet firstX = polygon[0], firstY = polygon[1];\n\t\t\tlet secondX = polygon[2], secondY = polygon[3];\n\t\t\tlet winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);\n\n\t\t\tfor (let ii = 0; ii < n; ii++) {\n\t\t\t\tif (ii == i) continue;\n\t\t\t\tlet otherIndices = convexPolygonsIndices[ii];\n\t\t\t\tif (otherIndices.length != 3) continue;\n\t\t\t\tlet otherFirstIndex = otherIndices[0];\n\t\t\t\tlet otherSecondIndex = otherIndices[1];\n\t\t\t\tlet otherLastIndex = otherIndices[2];\n\n\t\t\t\tlet otherPoly = convexPolygons[ii];\n\t\t\t\tlet x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];\n\n\t\t\t\tif (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;\n\t\t\t\tlet winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);\n\t\t\t\tlet winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY);\n\t\t\t\tif (winding1 == winding && winding2 == winding) {\n\t\t\t\t\totherPoly.length = 0;\n\t\t\t\t\totherIndices.length = 0;\n\t\t\t\t\tpolygon.push(x3);\n\t\t\t\t\tpolygon.push(y3);\n\t\t\t\t\tpolygonIndices.push(otherLastIndex);\n\t\t\t\t\tprevPrevX = prevX;\n\t\t\t\t\tprevPrevY = prevY;\n\t\t\t\t\tprevX = x3;\n\t\t\t\t\tprevY = y3;\n\t\t\t\t\tii = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove empty polygons that resulted from the merge step above.\n\t\tfor (let i = convexPolygons.length - 1; i >= 0; i--) {\n\t\t\tpolygon = convexPolygons[i];\n\t\t\tif (polygon.length == 0) {\n\t\t\t\tconvexPolygons.splice(i, 1);\n\t\t\t\tthis.polygonPool.free(polygon);\n\t\t\t\tpolygonIndices = convexPolygonsIndices[i]\n\t\t\t\tconvexPolygonsIndices.splice(i, 1)\n\t\t\t\tthis.polygonIndicesPool.free(polygonIndices);\n\t\t\t}\n\t\t}\n\n\t\treturn convexPolygons;\n\t}\n\n\tprivate static isConcave (index: number, vertexCount: number, vertices: NumberArrayLike, indices: NumberArrayLike): boolean {\n\t\tlet previous = indices[(vertexCount + index - 1) % vertexCount] << 1;\n\t\tlet current = indices[index] << 1;\n\t\tlet next = indices[(index + 1) % vertexCount] << 1;\n\t\treturn !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next],\n\t\t\tvertices[next + 1]);\n\t}\n\n\tprivate static positiveArea (p1x: number, p1y: number, p2x: number, p2y: number, p3x: number, p3y: number): boolean {\n\t\treturn p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;\n\t}\n\n\tprivate static winding (p1x: number, p1y: number, p2x: number, p2y: number, p3x: number, p3y: number): number {\n\t\tlet px = p2x - p1x, py = p2y - p1y;\n\t\treturn p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { ClippingAttachment } from \"./attachments/ClippingAttachment.js\";\nimport { Slot } from \"./Slot.js\";\nimport { Triangulator } from \"./Triangulator.js\";\nimport { Utils, Color, NumberArrayLike } from \"./Utils.js\";\n\nexport class SkeletonClipping {\n\tprivate triangulator = new Triangulator();\n\tprivate clippingPolygon = new Array();\n\tprivate clipOutput = new Array();\n\tclippedVertices = new Array();\n\tclippedUVs = new Array();\n\tclippedTriangles = new Array();\n\tprivate scratch = new Array();\n\n\tprivate clipAttachment: ClippingAttachment | null = null;\n\tprivate clippingPolygons: Array> | null = null;\n\n\tclipStart (slot: Slot, clip: ClippingAttachment): number {\n\t\tif (this.clipAttachment) return 0;\n\t\tthis.clipAttachment = clip;\n\n\t\tlet n = clip.worldVerticesLength;\n\t\tlet vertices = Utils.setArraySize(this.clippingPolygon, n);\n\t\tclip.computeWorldVertices(slot, 0, n, vertices, 0, 2);\n\t\tlet clippingPolygon = this.clippingPolygon;\n\t\tSkeletonClipping.makeClockwise(clippingPolygon);\n\t\tlet clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));\n\t\tfor (let i = 0, n = clippingPolygons.length; i < n; i++) {\n\t\t\tlet polygon = clippingPolygons[i];\n\t\t\tSkeletonClipping.makeClockwise(polygon);\n\t\t\tpolygon.push(polygon[0]);\n\t\t\tpolygon.push(polygon[1]);\n\t\t}\n\n\t\treturn clippingPolygons.length;\n\t}\n\n\tclipEndWithSlot (slot: Slot) {\n\t\tif (this.clipAttachment && this.clipAttachment.endSlot == slot.data) this.clipEnd();\n\t}\n\n\tclipEnd () {\n\t\tif (!this.clipAttachment) return;\n\t\tthis.clipAttachment = null;\n\t\tthis.clippingPolygons = null;\n\t\tthis.clippedVertices.length = 0;\n\t\tthis.clippedTriangles.length = 0;\n\t\tthis.clippingPolygon.length = 0;\n\t}\n\n\tisClipping (): boolean {\n\t\treturn this.clipAttachment != null;\n\t}\n\n\t/**\n\t* @deprecated Use clipTriangles without verticesLength parameter. Mark for removal in 4.3.\n\t*/\n\tclipTriangles (vertices: NumberArrayLike, verticesLength: number, triangles: NumberArrayLike, trianglesLength: number): void;\n\n\t/**\n\t * @deprecated Use clipTriangles without verticesLength parameter. Mark for removal in 4.3.\n\t */\n\tclipTriangles (vertices: NumberArrayLike, verticesLength: number, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean): void;\n\n\tclipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number): void;\n\tclipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean): void;\n\tclipTriangles (\n\t\tvertices: NumberArrayLike,\n\t\tverticesLengthOrTriangles: number | NumberArrayLike,\n\t\ttrianglesOrTrianglesLength: NumberArrayLike | number,\n\t\ttrianglesLengthOrUvs?: number | NumberArrayLike,\n\t\tuvsOrLight?: NumberArrayLike | Color,\n\t\tlightOrDark?: Color,\n\t\tdarkOrTwoColor?: Color | boolean,\n\t\ttwoColorParam?: boolean\n\t): void {\n\t\t// Determine which overload is being used\n\t\tlet triangles: NumberArrayLike;\n\t\tlet trianglesLength: number;\n\t\tlet uvs: NumberArrayLike | undefined;\n\t\tlet light: Color | undefined;\n\t\tlet dark: Color | undefined;\n\t\tlet twoColor: boolean | undefined;\n\n\t\tif (typeof verticesLengthOrTriangles === 'number') {\n\t\t\ttriangles = trianglesOrTrianglesLength as NumberArrayLike;\n\t\t\ttrianglesLength = trianglesLengthOrUvs as number;\n\t\t\tuvs = uvsOrLight as NumberArrayLike;\n\t\t\tlight = lightOrDark as Color | undefined;\n\t\t\tdark = darkOrTwoColor as Color | undefined;\n\t\t\ttwoColor = twoColorParam;\n\t\t} else {\n\t\t\ttriangles = verticesLengthOrTriangles;\n\t\t\ttrianglesLength = trianglesOrTrianglesLength as number;\n\t\t\tuvs = trianglesLengthOrUvs as NumberArrayLike;\n\t\t\tlight = uvsOrLight as Color | undefined;\n\t\t\tdark = lightOrDark as Color | undefined;\n\t\t\ttwoColor = darkOrTwoColor as boolean;\n\t\t}\n\n\t\tif (uvs && light && dark && typeof twoColor === 'boolean')\n\t\t\tthis.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor);\n\t\telse\n\t\t\tthis.clipTrianglesNoRender(vertices, triangles, trianglesLength);\n\t}\n\n\tprivate clipTrianglesNoRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number) {\n\n\t\tlet clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;\n\t\tlet clippedTriangles = this.clippedTriangles;\n\t\tlet polygons = this.clippingPolygons!;\n\t\tlet polygonsCount = polygons.length;\n\n\t\tlet index = 0;\n\t\tclippedVertices.length = 0;\n\t\tclippedTriangles.length = 0;\n\t\tfor (let i = 0; i < trianglesLength; i += 3) {\n\t\t\tlet vertexOffset = triangles[i] << 1;\n\t\t\tlet x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 1] << 1;\n\t\t\tlet x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 2] << 1;\n\t\t\tlet x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];\n\n\t\t\tfor (let p = 0; p < polygonsCount; p++) {\n\t\t\t\tlet s = clippedVertices.length;\n\t\t\t\tif (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {\n\t\t\t\t\tlet clipOutputLength = clipOutput.length;\n\t\t\t\t\tif (clipOutputLength == 0) continue;\n\n\t\t\t\t\tlet clipOutputCount = clipOutputLength >> 1;\n\t\t\t\t\tlet clipOutputItems = this.clipOutput;\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2);\n\t\t\t\t\tfor (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) {\n\t\t\t\t\t\tlet x = clipOutputItems[ii], y = clipOutputItems[ii + 1];\n\t\t\t\t\t\tclippedVerticesItems[s] = x;\n\t\t\t\t\t\tclippedVerticesItems[s + 1] = y;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));\n\t\t\t\t\tclipOutputCount--;\n\t\t\t\t\tfor (let ii = 1; ii < clipOutputCount; ii++, s += 3) {\n\t\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + ii);\n\t\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + ii + 1);\n\t\t\t\t\t}\n\t\t\t\t\tindex += clipOutputCount + 1;\n\n\t\t\t\t} else {\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2);\n\t\t\t\t\tclippedVerticesItems[s] = x1;\n\t\t\t\t\tclippedVerticesItems[s + 1] = y1;\n\n\t\t\t\t\tclippedVerticesItems[s + 2] = x2;\n\t\t\t\t\tclippedVerticesItems[s + 3] = y2;\n\n\t\t\t\t\tclippedVerticesItems[s + 4] = x3;\n\t\t\t\t\tclippedVerticesItems[s + 5] = y3;\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);\n\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + 1);\n\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + 2);\n\t\t\t\t\tindex += 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate clipTrianglesRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike,\n\t\tlight: Color, dark: Color, twoColor: boolean) {\n\n\t\tlet clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;\n\t\tlet clippedTriangles = this.clippedTriangles;\n\t\tlet polygons = this.clippingPolygons!;\n\t\tlet polygonsCount = polygons.length;\n\t\tlet vertexSize = twoColor ? 12 : 8;\n\n\t\tlet index = 0;\n\t\tclippedVertices.length = 0;\n\t\tclippedTriangles.length = 0;\n\t\tfor (let i = 0; i < trianglesLength; i += 3) {\n\t\t\tlet vertexOffset = triangles[i] << 1;\n\t\t\tlet x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];\n\t\t\tlet u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 1] << 1;\n\t\t\tlet x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];\n\t\t\tlet u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 2] << 1;\n\t\t\tlet x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];\n\t\t\tlet u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];\n\n\t\t\tfor (let p = 0; p < polygonsCount; p++) {\n\t\t\t\tlet s = clippedVertices.length;\n\t\t\t\tif (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {\n\t\t\t\t\tlet clipOutputLength = clipOutput.length;\n\t\t\t\t\tif (clipOutputLength == 0) continue;\n\t\t\t\t\tlet d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;\n\t\t\t\t\tlet d = 1 / (d0 * d2 + d1 * (y1 - y3));\n\n\t\t\t\t\tlet clipOutputCount = clipOutputLength >> 1;\n\t\t\t\t\tlet clipOutputItems = this.clipOutput;\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);\n\t\t\t\t\tfor (let ii = 0; ii < clipOutputLength; ii += 2, s += vertexSize) {\n\t\t\t\t\t\tlet x = clipOutputItems[ii], y = clipOutputItems[ii + 1];\n\t\t\t\t\t\tclippedVerticesItems[s] = x;\n\t\t\t\t\t\tclippedVerticesItems[s + 1] = y;\n\t\t\t\t\t\tclippedVerticesItems[s + 2] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 3] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 4] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 5] = light.a;\n\t\t\t\t\t\tlet c0 = x - x3, c1 = y - y3;\n\t\t\t\t\t\tlet a = (d0 * c0 + d1 * c1) * d;\n\t\t\t\t\t\tlet b = (d4 * c0 + d2 * c1) * d;\n\t\t\t\t\t\tlet c = 1 - a - b;\n\t\t\t\t\t\tclippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;\n\t\t\t\t\t\tclippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;\n\t\t\t\t\t\tif (twoColor) {\n\t\t\t\t\t\t\tclippedVerticesItems[s + 8] = dark.r;\n\t\t\t\t\t\t\tclippedVerticesItems[s + 9] = dark.g;\n\t\t\t\t\t\t\tclippedVerticesItems[s + 10] = dark.b;\n\t\t\t\t\t\t\tclippedVerticesItems[s + 11] = dark.a;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));\n\t\t\t\t\tclipOutputCount--;\n\t\t\t\t\tfor (let ii = 1; ii < clipOutputCount; ii++, s += 3) {\n\t\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + ii);\n\t\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + ii + 1);\n\t\t\t\t\t}\n\t\t\t\t\tindex += clipOutputCount + 1;\n\n\t\t\t\t} else {\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize);\n\t\t\t\t\tclippedVerticesItems[s] = x1;\n\t\t\t\t\tclippedVerticesItems[s + 1] = y1;\n\t\t\t\t\tclippedVerticesItems[s + 2] = light.r;\n\t\t\t\t\tclippedVerticesItems[s + 3] = light.g;\n\t\t\t\t\tclippedVerticesItems[s + 4] = light.b;\n\t\t\t\t\tclippedVerticesItems[s + 5] = light.a;\n\t\t\t\t\tif (!twoColor) {\n\t\t\t\t\t\tclippedVerticesItems[s + 6] = u1;\n\t\t\t\t\t\tclippedVerticesItems[s + 7] = v1;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 8] = x2;\n\t\t\t\t\t\tclippedVerticesItems[s + 9] = y2;\n\t\t\t\t\t\tclippedVerticesItems[s + 10] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 11] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 12] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 13] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 14] = u2;\n\t\t\t\t\t\tclippedVerticesItems[s + 15] = v2;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 16] = x3;\n\t\t\t\t\t\tclippedVerticesItems[s + 17] = y3;\n\t\t\t\t\t\tclippedVerticesItems[s + 18] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 19] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 20] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 21] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 22] = u3;\n\t\t\t\t\t\tclippedVerticesItems[s + 23] = v3;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclippedVerticesItems[s + 6] = u1;\n\t\t\t\t\t\tclippedVerticesItems[s + 7] = v1;\n\t\t\t\t\t\tclippedVerticesItems[s + 8] = dark.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 9] = dark.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 10] = dark.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 11] = dark.a;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 12] = x2;\n\t\t\t\t\t\tclippedVerticesItems[s + 13] = y2;\n\t\t\t\t\t\tclippedVerticesItems[s + 14] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 15] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 16] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 17] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 18] = u2;\n\t\t\t\t\t\tclippedVerticesItems[s + 19] = v2;\n\t\t\t\t\t\tclippedVerticesItems[s + 20] = dark.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 21] = dark.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 22] = dark.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 23] = dark.a;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 24] = x3;\n\t\t\t\t\t\tclippedVerticesItems[s + 25] = y3;\n\t\t\t\t\t\tclippedVerticesItems[s + 26] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 27] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 28] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 29] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 30] = u3;\n\t\t\t\t\t\tclippedVerticesItems[s + 31] = v3;\n\t\t\t\t\t\tclippedVerticesItems[s + 32] = dark.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 33] = dark.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 34] = dark.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 35] = dark.a;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);\n\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + 1);\n\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + 2);\n\t\t\t\t\tindex += 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic clipTrianglesUnpacked (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike) {\n\t\tlet clipOutput = this.clipOutput, clippedVertices = this.clippedVertices, clippedUVs = this.clippedUVs;\n\t\tlet clippedTriangles = this.clippedTriangles;\n\t\tlet polygons = this.clippingPolygons!;\n\t\tlet polygonsCount = polygons.length;\n\n\t\tlet index = 0;\n\t\tclippedVertices.length = 0;\n\t\tclippedUVs.length = 0;\n\t\tclippedTriangles.length = 0;\n\t\tfor (let i = 0; i < trianglesLength; i += 3) {\n\t\t\tlet vertexOffset = triangles[i] << 1;\n\t\t\tlet x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];\n\t\t\tlet u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 1] << 1;\n\t\t\tlet x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];\n\t\t\tlet u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 2] << 1;\n\t\t\tlet x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];\n\t\t\tlet u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];\n\n\t\t\tfor (let p = 0; p < polygonsCount; p++) {\n\t\t\t\tlet s = clippedVertices.length;\n\t\t\t\tif (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {\n\t\t\t\t\tlet clipOutputLength = clipOutput.length;\n\t\t\t\t\tif (clipOutputLength == 0) continue;\n\t\t\t\t\tlet d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;\n\t\t\t\t\tlet d = 1 / (d0 * d2 + d1 * (y1 - y3));\n\n\t\t\t\t\tlet clipOutputCount = clipOutputLength >> 1;\n\t\t\t\t\tlet clipOutputItems = this.clipOutput;\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2);\n\t\t\t\t\tlet clippedUVsItems = Utils.setArraySize(clippedUVs, s + clipOutputCount * 2);\n\t\t\t\t\tfor (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) {\n\t\t\t\t\t\tlet x = clipOutputItems[ii], y = clipOutputItems[ii + 1];\n\t\t\t\t\t\tclippedVerticesItems[s] = x;\n\t\t\t\t\t\tclippedVerticesItems[s + 1] = y;\n\t\t\t\t\t\tlet c0 = x - x3, c1 = y - y3;\n\t\t\t\t\t\tlet a = (d0 * c0 + d1 * c1) * d;\n\t\t\t\t\t\tlet b = (d4 * c0 + d2 * c1) * d;\n\t\t\t\t\t\tlet c = 1 - a - b;\n\t\t\t\t\t\tclippedUVsItems[s] = u1 * a + u2 * b + u3 * c;\n\t\t\t\t\t\tclippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));\n\t\t\t\t\tclipOutputCount--;\n\t\t\t\t\tfor (let ii = 1; ii < clipOutputCount; ii++, s += 3) {\n\t\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + ii);\n\t\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + ii + 1);\n\t\t\t\t\t}\n\t\t\t\t\tindex += clipOutputCount + 1;\n\n\t\t\t\t} else {\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2);\n\t\t\t\t\tclippedVerticesItems[s] = x1;\n\t\t\t\t\tclippedVerticesItems[s + 1] = y1;\n\t\t\t\t\tclippedVerticesItems[s + 2] = x2;\n\t\t\t\t\tclippedVerticesItems[s + 3] = y2;\n\t\t\t\t\tclippedVerticesItems[s + 4] = x3;\n\t\t\t\t\tclippedVerticesItems[s + 5] = y3;\n\n\t\t\t\t\tlet clippedUVSItems = Utils.setArraySize(clippedUVs, s + 3 * 2);\n\t\t\t\t\tclippedUVSItems[s] = u1;\n\t\t\t\t\tclippedUVSItems[s + 1] = v1;\n\t\t\t\t\tclippedUVSItems[s + 2] = u2;\n\t\t\t\t\tclippedUVSItems[s + 3] = v2;\n\t\t\t\t\tclippedUVSItems[s + 4] = u3;\n\t\t\t\t\tclippedUVSItems[s + 5] = v3;\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);\n\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + 1);\n\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + 2);\n\t\t\t\t\tindex += 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping\n\t * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */\n\tclip (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array, output: Array) {\n\t\tlet originalOutput = output;\n\t\tlet clipped = false;\n\n\t\t// Avoid copy at the end.\n\t\tlet input: Array;\n\t\tif (clippingArea.length % 4 >= 2) {\n\t\t\tinput = output;\n\t\t\toutput = this.scratch;\n\t\t} else\n\t\t\tinput = this.scratch;\n\n\t\tinput.length = 0;\n\t\tinput.push(x1);\n\t\tinput.push(y1);\n\t\tinput.push(x2);\n\t\tinput.push(y2);\n\t\tinput.push(x3);\n\t\tinput.push(y3);\n\t\tinput.push(x1);\n\t\tinput.push(y1);\n\t\toutput.length = 0;\n\n\t\tlet clippingVerticesLast = clippingArea.length - 4;\n\t\tlet clippingVertices = clippingArea;\n\t\tfor (let i = 0; ; i += 2) {\n\t\t\tlet edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];\n\t\t\tlet ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3];\n\n\t\t\tlet outputStart = output.length;\n\t\t\tlet inputVertices = input;\n\t\t\tfor (let ii = 0, nn = input.length - 2; ii < nn;) {\n\t\t\t\tlet inputX = inputVertices[ii], inputY = inputVertices[ii + 1];\n\t\t\t\tii += 2;\n\t\t\t\tlet inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1];\n\t\t\t\tlet s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2);\n\t\t\t\tlet s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY);\n\t\t\t\tif (s1 > 0) {\n\t\t\t\t\tif (s2) { // v1 inside, v2 inside\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// v1 inside, v2 outside\n\t\t\t\t\tlet ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex);\n\t\t\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\t\t\toutput.push(inputX + ix * t);\n\t\t\t\t\t\toutput.push(inputY + iy * t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} else if (s2) { // v1 outside, v2 inside\n\t\t\t\t\tlet ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex);\n\t\t\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\t\t\toutput.push(inputX + ix * t);\n\t\t\t\t\t\toutput.push(inputY + iy * t);\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclipped = true;\n\t\t\t}\n\n\t\t\tif (outputStart == output.length) { // All edges outside.\n\t\t\t\toriginalOutput.length = 0;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\toutput.push(output[0]);\n\t\t\toutput.push(output[1]);\n\n\t\t\tif (i == clippingVerticesLast) break;\n\t\t\tlet temp = output;\n\t\t\toutput = input;\n\t\t\toutput.length = 0;\n\t\t\tinput = temp;\n\t\t}\n\n\t\tif (originalOutput != output) {\n\t\t\toriginalOutput.length = 0;\n\t\t\tfor (let i = 0, n = output.length - 2; i < n; i++)\n\t\t\t\toriginalOutput[i] = output[i];\n\t\t} else\n\t\t\toriginalOutput.length = originalOutput.length - 2;\n\n\t\treturn clipped;\n\t}\n\n\tpublic static makeClockwise (polygon: NumberArrayLike) {\n\t\tlet vertices = polygon;\n\t\tlet verticeslength = polygon.length;\n\n\t\tlet area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;\n\t\tfor (let i = 0, n = verticeslength - 3; i < n; i += 2) {\n\t\t\tp1x = vertices[i];\n\t\t\tp1y = vertices[i + 1];\n\t\t\tp2x = vertices[i + 2];\n\t\t\tp2y = vertices[i + 3];\n\t\t\tarea += p1x * p2y - p2x * p1y;\n\t\t}\n\t\tif (area < 0) return;\n\n\t\tfor (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {\n\t\t\tlet x = vertices[i], y = vertices[i + 1];\n\t\t\tlet other = lastX - i;\n\t\t\tvertices[i] = vertices[other];\n\t\t\tvertices[i + 1] = vertices[other + 1];\n\t\t\tvertices[other] = x;\n\t\t\tvertices[other + 1] = y;\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation, Timeline, InheritTimeline, AttachmentTimeline, RGBATimeline, RGBTimeline, AlphaTimeline, RGBA2Timeline, RGB2Timeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline2, CurveTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline } from \"./Animation.js\";\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { AttachmentLoader } from \"./attachments/AttachmentLoader.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { BoneData, Inherit } from \"./BoneData.js\";\nimport { EventData } from \"./EventData.js\";\nimport { Event } from \"./Event.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { PathConstraintData, PositionMode, SpacingMode, RotateMode } from \"./PathConstraintData.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { SlotData, BlendMode } from \"./SlotData.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\nimport { Utils, Color, NumberArrayLike } from \"./Utils.js\";\nimport { Sequence, SequenceMode } from \"./attachments/Sequence.js\";\nimport { SequenceTimeline } from \"./Animation.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\n\n/** Loads skeleton data in the Spine JSON format.\n *\n * See [Spine JSON format](http://esotericsoftware.com/spine-json-format) and\n * [JSON and binary data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the Spine\n * Runtimes Guide. */\nexport class SkeletonJson {\n\tattachmentLoader: AttachmentLoader;\n\n\t/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at\n\t * runtime than were used in Spine.\n\t *\n\t * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */\n\tscale = 1;\n\tprivate linkedMeshes = new Array();\n\n\tconstructor (attachmentLoader: AttachmentLoader) {\n\t\tthis.attachmentLoader = attachmentLoader;\n\t}\n\n\treadSkeletonData (json: string | any): SkeletonData {\n\t\tlet scale = this.scale;\n\t\tlet skeletonData = new SkeletonData();\n\t\tlet root = typeof (json) === \"string\" ? JSON.parse(json) : json;\n\n\t\t// Skeleton\n\t\tlet skeletonMap = root.skeleton;\n\t\tif (skeletonMap) {\n\t\t\tskeletonData.hash = skeletonMap.hash;\n\t\t\tskeletonData.version = skeletonMap.spine;\n\t\t\tskeletonData.x = skeletonMap.x;\n\t\t\tskeletonData.y = skeletonMap.y;\n\t\t\tskeletonData.width = skeletonMap.width;\n\t\t\tskeletonData.height = skeletonMap.height;\n\t\t\tskeletonData.referenceScale = getValue(skeletonMap, \"referenceScale\", 100) * scale;\n\t\t\tskeletonData.fps = skeletonMap.fps;\n\t\t\tskeletonData.imagesPath = skeletonMap.images ?? null;\n\t\t\tskeletonData.audioPath = skeletonMap.audio ?? null;\n\t\t}\n\n\t\t// Bones\n\t\tif (root.bones) {\n\t\t\tfor (let i = 0; i < root.bones.length; i++) {\n\t\t\t\tlet boneMap = root.bones[i];\n\n\t\t\t\tlet parent: BoneData | null = null;\n\t\t\t\tlet parentName: string = getValue(boneMap, \"parent\", null);\n\t\t\t\tif (parentName) parent = skeletonData.findBone(parentName);\n\t\t\t\tlet data = new BoneData(skeletonData.bones.length, boneMap.name, parent);\n\t\t\t\tdata.length = getValue(boneMap, \"length\", 0) * scale;\n\t\t\t\tdata.x = getValue(boneMap, \"x\", 0) * scale;\n\t\t\t\tdata.y = getValue(boneMap, \"y\", 0) * scale;\n\t\t\t\tdata.rotation = getValue(boneMap, \"rotation\", 0);\n\t\t\t\tdata.scaleX = getValue(boneMap, \"scaleX\", 1);\n\t\t\t\tdata.scaleY = getValue(boneMap, \"scaleY\", 1);\n\t\t\t\tdata.shearX = getValue(boneMap, \"shearX\", 0);\n\t\t\t\tdata.shearY = getValue(boneMap, \"shearY\", 0);\n\t\t\t\tdata.inherit = Utils.enumValue(Inherit, getValue(boneMap, \"inherit\", \"Normal\"));\n\t\t\t\tdata.skinRequired = getValue(boneMap, \"skin\", false);\n\n\t\t\t\tlet color = getValue(boneMap, \"color\", null);\n\t\t\t\tif (color) data.color.setFromString(color);\n\n\t\t\t\tskeletonData.bones.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Slots.\n\t\tif (root.slots) {\n\t\t\tfor (let i = 0; i < root.slots.length; i++) {\n\t\t\t\tlet slotMap = root.slots[i];\n\t\t\t\tlet slotName = slotMap.name;\n\n\t\t\t\tlet boneData = skeletonData.findBone(slotMap.bone);\n\t\t\t\tif (!boneData) throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`);\n\t\t\t\tlet data = new SlotData(skeletonData.slots.length, slotName, boneData);\n\n\t\t\t\tlet color: string = getValue(slotMap, \"color\", null);\n\t\t\t\tif (color) data.color.setFromString(color);\n\n\t\t\t\tlet dark: string = getValue(slotMap, \"dark\", null);\n\t\t\t\tif (dark) data.darkColor = Color.fromString(dark);\n\n\t\t\t\tdata.attachmentName = getValue(slotMap, \"attachment\", null);\n\t\t\t\tdata.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, \"blend\", \"normal\"));\n\t\t\t\tdata.visible = getValue(slotMap, \"visible\", true);\n\t\t\t\tskeletonData.slots.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// IK constraints\n\t\tif (root.ik) {\n\t\t\tfor (let i = 0; i < root.ik.length; i++) {\n\t\t\t\tlet constraintMap = root.ik[i];\n\t\t\t\tlet data = new IkConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tfor (let ii = 0; ii < constraintMap.bones.length; ii++) {\n\t\t\t\t\tlet bone = skeletonData.findBone(constraintMap.bones[ii]);\n\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`);\n\t\t\t\t\tdata.bones.push(bone);\n\t\t\t\t}\n\n\t\t\t\tlet target = skeletonData.findBone(constraintMap.target);;\n\t\t\t\tif (!target) throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`);\n\t\t\t\tdata.target = target;\n\n\t\t\t\tdata.mix = getValue(constraintMap, \"mix\", 1);\n\t\t\t\tdata.softness = getValue(constraintMap, \"softness\", 0) * scale;\n\t\t\t\tdata.bendDirection = getValue(constraintMap, \"bendPositive\", true) ? 1 : -1;\n\t\t\t\tdata.compress = getValue(constraintMap, \"compress\", false);\n\t\t\t\tdata.stretch = getValue(constraintMap, \"stretch\", false);\n\t\t\t\tdata.uniform = getValue(constraintMap, \"uniform\", false);\n\n\t\t\t\tskeletonData.ikConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Transform constraints.\n\t\tif (root.transform) {\n\t\t\tfor (let i = 0; i < root.transform.length; i++) {\n\t\t\t\tlet constraintMap = root.transform[i];\n\t\t\t\tlet data = new TransformConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tfor (let ii = 0; ii < constraintMap.bones.length; ii++) {\n\t\t\t\t\tlet boneName = constraintMap.bones[ii];\n\t\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`);\n\t\t\t\t\tdata.bones.push(bone);\n\t\t\t\t}\n\n\t\t\t\tlet targetName: string = constraintMap.target;\n\t\t\t\tlet target = skeletonData.findBone(targetName);\n\t\t\t\tif (!target) throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`);\n\t\t\t\tdata.target = target;\n\n\t\t\t\tdata.local = getValue(constraintMap, \"local\", false);\n\t\t\t\tdata.relative = getValue(constraintMap, \"relative\", false);\n\t\t\t\tdata.offsetRotation = getValue(constraintMap, \"rotation\", 0);\n\t\t\t\tdata.offsetX = getValue(constraintMap, \"x\", 0) * scale;\n\t\t\t\tdata.offsetY = getValue(constraintMap, \"y\", 0) * scale;\n\t\t\t\tdata.offsetScaleX = getValue(constraintMap, \"scaleX\", 0);\n\t\t\t\tdata.offsetScaleY = getValue(constraintMap, \"scaleY\", 0);\n\t\t\t\tdata.offsetShearY = getValue(constraintMap, \"shearY\", 0);\n\n\t\t\t\tdata.mixRotate = getValue(constraintMap, \"mixRotate\", 1);\n\t\t\t\tdata.mixX = getValue(constraintMap, \"mixX\", 1);\n\t\t\t\tdata.mixY = getValue(constraintMap, \"mixY\", data.mixX);\n\t\t\t\tdata.mixScaleX = getValue(constraintMap, \"mixScaleX\", 1);\n\t\t\t\tdata.mixScaleY = getValue(constraintMap, \"mixScaleY\", data.mixScaleX);\n\t\t\t\tdata.mixShearY = getValue(constraintMap, \"mixShearY\", 1);\n\n\t\t\t\tskeletonData.transformConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Path constraints.\n\t\tif (root.path) {\n\t\t\tfor (let i = 0; i < root.path.length; i++) {\n\t\t\t\tlet constraintMap = root.path[i];\n\t\t\t\tlet data = new PathConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tfor (let ii = 0; ii < constraintMap.bones.length; ii++) {\n\t\t\t\t\tlet boneName = constraintMap.bones[ii];\n\t\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`);\n\t\t\t\t\tdata.bones.push(bone);\n\t\t\t\t}\n\n\t\t\t\tlet targetName: string = constraintMap.target;\n\t\t\t\tlet target = skeletonData.findSlot(targetName);\n\t\t\t\tif (!target) throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`);\n\t\t\t\tdata.target = target;\n\n\t\t\t\tdata.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, \"positionMode\", \"Percent\"));\n\t\t\t\tdata.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, \"spacingMode\", \"Length\"));\n\t\t\t\tdata.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, \"rotateMode\", \"Tangent\"));\n\t\t\t\tdata.offsetRotation = getValue(constraintMap, \"rotation\", 0);\n\t\t\t\tdata.position = getValue(constraintMap, \"position\", 0);\n\t\t\t\tif (data.positionMode == PositionMode.Fixed) data.position *= scale;\n\t\t\t\tdata.spacing = getValue(constraintMap, \"spacing\", 0);\n\t\t\t\tif (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) data.spacing *= scale;\n\t\t\t\tdata.mixRotate = getValue(constraintMap, \"mixRotate\", 1);\n\t\t\t\tdata.mixX = getValue(constraintMap, \"mixX\", 1);\n\t\t\t\tdata.mixY = getValue(constraintMap, \"mixY\", data.mixX);\n\n\t\t\t\tskeletonData.pathConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Physics constraints.\n\t\tif (root.physics) {\n\t\t\tfor (let i = 0; i < root.physics.length; i++) {\n\t\t\t\tconst constraintMap = root.physics[i];\n\t\t\t\tconst data = new PhysicsConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tconst boneName = constraintMap.bone;\n\t\t\t\tconst bone = skeletonData.findBone(boneName);\n\t\t\t\tif (bone == null) throw new Error(\"Physics bone not found: \" + boneName);\n\t\t\t\tdata.bone = bone;\n\n\t\t\t\tdata.x = getValue(constraintMap, \"x\", 0);\n\t\t\t\tdata.y = getValue(constraintMap, \"y\", 0);\n\t\t\t\tdata.rotate = getValue(constraintMap, \"rotate\", 0);\n\t\t\t\tdata.scaleX = getValue(constraintMap, \"scaleX\", 0);\n\t\t\t\tdata.shearX = getValue(constraintMap, \"shearX\", 0);\n\t\t\t\tdata.limit = getValue(constraintMap, \"limit\", 5000) * scale;\n\t\t\t\tdata.step = 1 / getValue(constraintMap, \"fps\", 60);\n\t\t\t\tdata.inertia = getValue(constraintMap, \"inertia\", 1);\n\t\t\t\tdata.strength = getValue(constraintMap, \"strength\", 100);\n\t\t\t\tdata.damping = getValue(constraintMap, \"damping\", 1);\n\t\t\t\tdata.massInverse = 1 / getValue(constraintMap, \"mass\", 1);\n\t\t\t\tdata.wind = getValue(constraintMap, \"wind\", 0);\n\t\t\t\tdata.gravity = getValue(constraintMap, \"gravity\", 0);\n\t\t\t\tdata.mix = getValue(constraintMap, \"mix\", 1);\n\t\t\t\tdata.inertiaGlobal = getValue(constraintMap, \"inertiaGlobal\", false);\n\t\t\t\tdata.strengthGlobal = getValue(constraintMap, \"strengthGlobal\", false);\n\t\t\t\tdata.dampingGlobal = getValue(constraintMap, \"dampingGlobal\", false);\n\t\t\t\tdata.massGlobal = getValue(constraintMap, \"massGlobal\", false);\n\t\t\t\tdata.windGlobal = getValue(constraintMap, \"windGlobal\", false);\n\t\t\t\tdata.gravityGlobal = getValue(constraintMap, \"gravityGlobal\", false);\n\t\t\t\tdata.mixGlobal = getValue(constraintMap, \"mixGlobal\", false);\n\n\t\t\t\tskeletonData.physicsConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Skins.\n\t\tif (root.skins) {\n\t\t\tfor (let i = 0; i < root.skins.length; i++) {\n\t\t\t\tlet skinMap = root.skins[i]\n\t\t\t\tlet skin = new Skin(skinMap.name);\n\n\t\t\t\tif (skinMap.bones) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.bones.length; ii++) {\n\t\t\t\t\t\tlet boneName = skinMap.bones[ii];\n\t\t\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.bones.push(bone);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.ik) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.ik.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.ik[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findIkConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.transform) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.transform.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.transform[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findTransformConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.path) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.path.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.path[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findPathConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.physics) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.physics.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.physics[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findPhysicsConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (let slotName in skinMap.attachments) {\n\t\t\t\t\tlet slot = skeletonData.findSlot(slotName);\n\t\t\t\t\tif (!slot) throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`);\n\t\t\t\t\tlet slotMap = skinMap.attachments[slotName];\n\t\t\t\t\tfor (let entryName in slotMap) {\n\t\t\t\t\t\tlet attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData);\n\t\t\t\t\t\tif (attachment) skin.setAttachment(slot.index, entryName, attachment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tskeletonData.skins.push(skin);\n\t\t\t\tif (skin.name == \"default\") skeletonData.defaultSkin = skin;\n\t\t\t}\n\t\t}\n\n\t\t// Linked meshes.\n\t\tfor (let i = 0, n = this.linkedMeshes.length; i < n; i++) {\n\t\t\tlet linkedMesh = this.linkedMeshes[i];\n\t\t\tlet skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);\n\t\t\tif (!skin) throw new Error(`Skin not found: ${linkedMesh.skin}`);\n\t\t\tlet parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);\n\t\t\tif (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);\n\t\t\tlinkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh;\n\t\t\tlinkedMesh.mesh.setParentMesh(parent);\n\t\t\tif (linkedMesh.mesh.region != null) linkedMesh.mesh.updateRegion();\n\t\t}\n\t\tthis.linkedMeshes.length = 0;\n\n\t\t// Events.\n\t\tif (root.events) {\n\t\t\tfor (let eventName in root.events) {\n\t\t\t\tlet eventMap = root.events[eventName];\n\t\t\t\tlet data = new EventData(eventName);\n\t\t\t\tdata.intValue = getValue(eventMap, \"int\", 0);\n\t\t\t\tdata.floatValue = getValue(eventMap, \"float\", 0);\n\t\t\t\tdata.stringValue = getValue(eventMap, \"string\", \"\");\n\t\t\t\tdata.audioPath = getValue(eventMap, \"audio\", null);\n\t\t\t\tif (data.audioPath) {\n\t\t\t\t\tdata.volume = getValue(eventMap, \"volume\", 1);\n\t\t\t\t\tdata.balance = getValue(eventMap, \"balance\", 0);\n\t\t\t\t}\n\t\t\t\tskeletonData.events.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Animations.\n\t\tif (root.animations) {\n\t\t\tfor (let animationName in root.animations) {\n\t\t\t\tlet animationMap = root.animations[animationName];\n\t\t\t\tthis.readAnimation(animationMap, animationName, skeletonData);\n\t\t\t}\n\t\t}\n\n\t\treturn skeletonData;\n\t}\n\n\treadAttachment (map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment | null {\n\t\tlet scale = this.scale;\n\t\tname = getValue(map, \"name\", name);\n\n\t\tswitch (getValue(map, \"type\", \"region\")) {\n\t\t\tcase \"region\": {\n\t\t\t\tlet path = getValue(map, \"path\", name);\n\t\t\t\tlet sequence = this.readSequence(getValue(map, \"sequence\", null));\n\t\t\t\tlet region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);\n\t\t\t\tif (!region) return null;\n\t\t\t\tregion.path = path;\n\t\t\t\tregion.x = getValue(map, \"x\", 0) * scale;\n\t\t\t\tregion.y = getValue(map, \"y\", 0) * scale;\n\t\t\t\tregion.scaleX = getValue(map, \"scaleX\", 1);\n\t\t\t\tregion.scaleY = getValue(map, \"scaleY\", 1);\n\t\t\t\tregion.rotation = getValue(map, \"rotation\", 0);\n\t\t\t\tregion.width = map.width * scale;\n\t\t\t\tregion.height = map.height * scale;\n\t\t\t\tregion.sequence = sequence;\n\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) region.color.setFromString(color);\n\n\t\t\t\tif (region.region != null) region.updateRegion();\n\t\t\t\treturn region;\n\t\t\t}\n\t\t\tcase \"boundingbox\": {\n\t\t\t\tlet box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);\n\t\t\t\tif (!box) return null;\n\t\t\t\tthis.readVertices(map, box, map.vertexCount << 1);\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) box.color.setFromString(color);\n\t\t\t\treturn box;\n\t\t\t}\n\t\t\tcase \"mesh\":\n\t\t\tcase \"linkedmesh\": {\n\t\t\t\tlet path = getValue(map, \"path\", name);\n\t\t\t\tlet sequence = this.readSequence(getValue(map, \"sequence\", null));\n\t\t\t\tlet mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);\n\t\t\t\tif (!mesh) return null;\n\t\t\t\tmesh.path = path;\n\n\t\t\t\tlet color = getValue(map, \"color\", null);\n\t\t\t\tif (color) mesh.color.setFromString(color);\n\n\t\t\t\tmesh.width = getValue(map, \"width\", 0) * scale;\n\t\t\t\tmesh.height = getValue(map, \"height\", 0) * scale;\n\t\t\t\tmesh.sequence = sequence;\n\n\t\t\t\tlet parent: string = getValue(map, \"parent\", null);\n\t\t\t\tif (parent) {\n\t\t\t\t\tthis.linkedMeshes.push(new LinkedMesh(mesh, getValue(map, \"skin\", null), slotIndex, parent, getValue(map, \"timelines\", true)));\n\t\t\t\t\treturn mesh;\n\t\t\t\t}\n\n\t\t\t\tlet uvs: Array = map.uvs;\n\t\t\t\tthis.readVertices(map, mesh, uvs.length);\n\t\t\t\tmesh.triangles = map.triangles;\n\t\t\t\tmesh.regionUVs = uvs;\n\t\t\t\tif (mesh.region != null) mesh.updateRegion();\n\n\t\t\t\tmesh.edges = getValue(map, \"edges\", null);\n\t\t\t\tmesh.hullLength = getValue(map, \"hull\", 0) * 2;\n\t\t\t\treturn mesh;\n\t\t\t}\n\t\t\tcase \"path\": {\n\t\t\t\tlet path = this.attachmentLoader.newPathAttachment(skin, name);\n\t\t\t\tif (!path) return null;\n\t\t\t\tpath.closed = getValue(map, \"closed\", false);\n\t\t\t\tpath.constantSpeed = getValue(map, \"constantSpeed\", true);\n\n\t\t\t\tlet vertexCount = map.vertexCount;\n\t\t\t\tthis.readVertices(map, path, vertexCount << 1);\n\n\t\t\t\tlet lengths: Array = Utils.newArray(vertexCount / 3, 0);\n\t\t\t\tfor (let i = 0; i < map.lengths.length; i++)\n\t\t\t\t\tlengths[i] = map.lengths[i] * scale;\n\t\t\t\tpath.lengths = lengths;\n\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) path.color.setFromString(color);\n\t\t\t\treturn path;\n\t\t\t}\n\t\t\tcase \"point\": {\n\t\t\t\tlet point = this.attachmentLoader.newPointAttachment(skin, name);\n\t\t\t\tif (!point) return null;\n\t\t\t\tpoint.x = getValue(map, \"x\", 0) * scale;\n\t\t\t\tpoint.y = getValue(map, \"y\", 0) * scale;\n\t\t\t\tpoint.rotation = getValue(map, \"rotation\", 0);\n\n\t\t\t\tlet color = getValue(map, \"color\", null);\n\t\t\t\tif (color) point.color.setFromString(color);\n\t\t\t\treturn point;\n\t\t\t}\n\t\t\tcase \"clipping\": {\n\t\t\t\tlet clip = this.attachmentLoader.newClippingAttachment(skin, name);\n\t\t\t\tif (!clip) return null;\n\n\t\t\t\tlet end = getValue(map, \"end\", null);\n\t\t\t\tif (end) clip.endSlot = skeletonData.findSlot(end);\n\n\t\t\t\tlet vertexCount = map.vertexCount;\n\t\t\t\tthis.readVertices(map, clip, vertexCount << 1);\n\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) clip.color.setFromString(color);\n\t\t\t\treturn clip;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\treadSequence (map: any) {\n\t\tif (map == null) return null;\n\t\tlet sequence = new Sequence(getValue(map, \"count\", 0));\n\t\tsequence.start = getValue(map, \"start\", 1);\n\t\tsequence.digits = getValue(map, \"digits\", 0);\n\t\tsequence.setupIndex = getValue(map, \"setup\", 0);\n\t\treturn sequence;\n\t}\n\n\treadVertices (map: any, attachment: VertexAttachment, verticesLength: number) {\n\t\tlet scale = this.scale;\n\t\tattachment.worldVerticesLength = verticesLength;\n\t\tlet vertices: Array = map.vertices;\n\t\tif (verticesLength == vertices.length) {\n\t\t\tlet scaledVertices = Utils.toFloatArray(vertices);\n\t\t\tif (scale != 1) {\n\t\t\t\tfor (let i = 0, n = vertices.length; i < n; i++)\n\t\t\t\t\tscaledVertices[i] *= scale;\n\t\t\t}\n\t\t\tattachment.vertices = scaledVertices;\n\t\t\treturn;\n\t\t}\n\t\tlet weights = new Array();\n\t\tlet bones = new Array();\n\t\tfor (let i = 0, n = vertices.length; i < n;) {\n\t\t\tlet boneCount = vertices[i++];\n\t\t\tbones.push(boneCount);\n\t\t\tfor (let nn = i + boneCount * 4; i < nn; i += 4) {\n\t\t\t\tbones.push(vertices[i]);\n\t\t\t\tweights.push(vertices[i + 1] * scale);\n\t\t\t\tweights.push(vertices[i + 2] * scale);\n\t\t\t\tweights.push(vertices[i + 3]);\n\t\t\t}\n\t\t}\n\t\tattachment.bones = bones;\n\t\tattachment.vertices = Utils.toFloatArray(weights);\n\t}\n\n\treadAnimation (map: any, name: string, skeletonData: SkeletonData) {\n\t\tlet scale = this.scale;\n\t\tlet timelines = new Array();\n\n\t\t// Slot timelines.\n\t\tif (map.slots) {\n\t\t\tfor (let slotName in map.slots) {\n\t\t\t\tlet slotMap = map.slots[slotName];\n\t\t\t\tlet slot = skeletonData.findSlot(slotName);\n\t\t\t\tif (!slot) throw new Error(\"Slot not found: \" + slotName);\n\t\t\t\tlet slotIndex = slot.index;\n\t\t\t\tfor (let timelineName in slotMap) {\n\t\t\t\t\tlet timelineMap = slotMap[timelineName];\n\t\t\t\t\tif (!timelineMap) continue;\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (timelineName == \"attachment\") {\n\t\t\t\t\t\tlet timeline = new AttachmentTimeline(frames, slotIndex);\n\t\t\t\t\t\tfor (let frame = 0; frame < frames; frame++) {\n\t\t\t\t\t\t\tlet keyMap = timelineMap[frame];\n\t\t\t\t\t\t\ttimeline.setFrame(frame, getValue(keyMap, \"time\", 0), getValue(keyMap, \"name\", null));\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"rgba\") {\n\t\t\t\t\t\tlet timeline = new RGBATimeline(frames, frames << 2, slotIndex);\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.color);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b, color.a);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.color);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"rgb\") {\n\t\t\t\t\t\tlet timeline = new RGBTimeline(frames, frames * 3, slotIndex);\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.color);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.color);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"alpha\") {\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1));\n\t\t\t\t\t} else if (timelineName == \"rgba2\") {\n\t\t\t\t\t\tlet timeline = new RGBA2Timeline(frames, frames * 7, slotIndex);\n\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.light);\n\t\t\t\t\t\tlet color2 = Color.fromString(keyMap.dark);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.light);\n\t\t\t\t\t\t\tlet newColor2 = Color.fromString(nextMap.dark);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tcolor2 = newColor2;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"rgb2\") {\n\t\t\t\t\t\tlet timeline = new RGB2Timeline(frames, frames * 6, slotIndex);\n\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.light);\n\t\t\t\t\t\tlet color2 = Color.fromString(keyMap.dark);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.light);\n\t\t\t\t\t\t\tlet newColor2 = Color.fromString(nextMap.dark);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tcolor2 = newColor2;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Bone timelines.\n\t\tif (map.bones) {\n\t\t\tfor (let boneName in map.bones) {\n\t\t\t\tlet boneMap = map.bones[boneName];\n\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\tif (!bone) throw new Error(\"Bone not found: \" + boneName);\n\t\t\t\tlet boneIndex = bone.index;\n\t\t\t\tfor (let timelineName in boneMap) {\n\t\t\t\t\tlet timelineMap = boneMap[timelineName];\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (frames == 0) continue;\n\n\t\t\t\t\tif (timelineName === \"rotate\") {\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1));\n\t\t\t\t\t} else if (timelineName === \"translate\") {\n\t\t\t\t\t\tlet timeline = new TranslateTimeline(frames, frames << 1, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline2(timelineMap, timeline, \"x\", \"y\", 0, scale));\n\t\t\t\t\t} else if (timelineName === \"translatex\") {\n\t\t\t\t\t\tlet timeline = new TranslateXTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, scale));\n\t\t\t\t\t} else if (timelineName === \"translatey\") {\n\t\t\t\t\t\tlet timeline = new TranslateYTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, scale));\n\t\t\t\t\t} else if (timelineName === \"scale\") {\n\t\t\t\t\t\tlet timeline = new ScaleTimeline(frames, frames << 1, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline2(timelineMap, timeline, \"x\", \"y\", 1, 1));\n\t\t\t\t\t} else if (timelineName === \"scalex\") {\n\t\t\t\t\t\tlet timeline = new ScaleXTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 1, 1));\n\t\t\t\t\t} else if (timelineName === \"scaley\") {\n\t\t\t\t\t\tlet timeline = new ScaleYTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 1, 1));\n\t\t\t\t\t} else if (timelineName === \"shear\") {\n\t\t\t\t\t\tlet timeline = new ShearTimeline(frames, frames << 1, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline2(timelineMap, timeline, \"x\", \"y\", 0, 1));\n\t\t\t\t\t} else if (timelineName === \"shearx\") {\n\t\t\t\t\t\tlet timeline = new ShearXTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, 1));\n\t\t\t\t\t} else if (timelineName === \"sheary\") {\n\t\t\t\t\t\tlet timeline = new ShearYTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, 1));\n\t\t\t\t\t} else if (timelineName === \"inherit\") {\n\t\t\t\t\t\tlet timeline = new InheritTimeline(frames, bone.index);\n\t\t\t\t\t\tfor (let frame = 0; frame < timelineMap.length; frame++) {\n\t\t\t\t\t\t\tlet aFrame = timelineMap[frame];\n\t\t\t\t\t\t\ttimeline.setFrame(frame, getValue(aFrame, \"time\", 0), Utils.enumValue(Inherit, getValue(aFrame, \"inherit\", \"Normal\")));\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IK constraint timelines.\n\t\tif (map.ik) {\n\t\t\tfor (let constraintName in map.ik) {\n\t\t\t\tlet constraintMap = map.ik[constraintName];\n\t\t\t\tlet keyMap = constraintMap[0];\n\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\tlet constraint = skeletonData.findIkConstraint(constraintName);\n\t\t\t\tif (!constraint) throw new Error(\"IK Constraint not found: \" + constraintName);\n\t\t\t\tlet constraintIndex = skeletonData.ikConstraints.indexOf(constraint);\n\t\t\t\tlet timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex);\n\n\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\tlet mix = getValue(keyMap, \"mix\", 1);\n\t\t\t\tlet softness = getValue(keyMap, \"softness\", 0) * scale;\n\n\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\ttimeline.setFrame(frame, time, mix, softness, getValue(keyMap, \"bendPositive\", true) ? 1 : -1, getValue(keyMap, \"compress\", false), getValue(keyMap, \"stretch\", false));\n\t\t\t\t\tlet nextMap = constraintMap[frame + 1];\n\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\tlet mix2 = getValue(nextMap, \"mix\", 1);\n\t\t\t\t\tlet softness2 = getValue(nextMap, \"softness\", 0) * scale;\n\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\tif (curve) {\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale);\n\t\t\t\t\t}\n\n\t\t\t\t\ttime = time2;\n\t\t\t\t\tmix = mix2;\n\t\t\t\t\tsoftness = softness2;\n\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t}\n\t\t\t\ttimelines.push(timeline);\n\t\t\t}\n\t\t}\n\n\t\t// Transform constraint timelines.\n\t\tif (map.transform) {\n\t\t\tfor (let constraintName in map.transform) {\n\t\t\t\tlet timelineMap = map.transform[constraintName];\n\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\tlet constraint = skeletonData.findTransformConstraint(constraintName);\n\t\t\t\tif (!constraint) throw new Error(\"Transform constraint not found: \" + constraintName);\n\t\t\t\tlet constraintIndex = skeletonData.transformConstraints.indexOf(constraint);\n\t\t\t\tlet timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex);\n\n\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\tlet mixRotate = getValue(keyMap, \"mixRotate\", 1);\n\t\t\t\tlet mixX = getValue(keyMap, \"mixX\", 1);\n\t\t\t\tlet mixY = getValue(keyMap, \"mixY\", mixX);\n\t\t\t\tlet mixScaleX = getValue(keyMap, \"mixScaleX\", 1);\n\t\t\t\tlet mixScaleY = getValue(keyMap, \"mixScaleY\", mixScaleX);\n\t\t\t\tlet mixShearY = getValue(keyMap, \"mixShearY\", 1);\n\n\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);\n\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\tlet mixRotate2 = getValue(nextMap, \"mixRotate\", 1);\n\t\t\t\t\tlet mixX2 = getValue(nextMap, \"mixX\", 1);\n\t\t\t\t\tlet mixY2 = getValue(nextMap, \"mixY\", mixX2);\n\t\t\t\t\tlet mixScaleX2 = getValue(nextMap, \"mixScaleX\", 1);\n\t\t\t\t\tlet mixScaleY2 = getValue(nextMap, \"mixScaleY\", mixScaleX2);\n\t\t\t\t\tlet mixShearY2 = getValue(nextMap, \"mixShearY\", 1);\n\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\tif (curve) {\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1);\n\t\t\t\t\t}\n\n\t\t\t\t\ttime = time2;\n\t\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\t\tmixX = mixX2;\n\t\t\t\t\tmixY = mixY2;\n\t\t\t\t\tmixScaleX = mixScaleX2;\n\t\t\t\t\tmixScaleY = mixScaleY2;\n\t\t\t\t\tmixScaleX = mixScaleX2;\n\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t}\n\t\t\t\ttimelines.push(timeline);\n\t\t\t}\n\t\t}\n\n\t\t// Path constraint timelines.\n\t\tif (map.path) {\n\t\t\tfor (let constraintName in map.path) {\n\t\t\t\tlet constraintMap = map.path[constraintName];\n\t\t\t\tlet constraint = skeletonData.findPathConstraint(constraintName);\n\t\t\t\tif (!constraint) throw new Error(\"Path constraint not found: \" + constraintName);\n\t\t\t\tlet constraintIndex = skeletonData.pathConstraints.indexOf(constraint);\n\t\t\t\tfor (let timelineName in constraintMap) {\n\t\t\t\t\tlet timelineMap = constraintMap[timelineName];\n\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (timelineName === \"position\") {\n\t\t\t\t\t\tlet timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, constraint.positionMode == PositionMode.Fixed ? scale : 1));\n\t\t\t\t\t} else if (timelineName === \"spacing\") {\n\t\t\t\t\t\tlet timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, constraint.spacingMode == SpacingMode.Length || constraint.spacingMode == SpacingMode.Fixed ? scale : 1));\n\t\t\t\t\t} else if (timelineName === \"mix\") {\n\t\t\t\t\t\tlet timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex);\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet mixRotate = getValue(keyMap, \"mixRotate\", 1);\n\t\t\t\t\t\tlet mixX = getValue(keyMap, \"mixX\", 1);\n\t\t\t\t\t\tlet mixY = getValue(keyMap, \"mixY\", mixX);\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet mixRotate2 = getValue(nextMap, \"mixRotate\", 1);\n\t\t\t\t\t\t\tlet mixX2 = getValue(nextMap, \"mixX\", 1);\n\t\t\t\t\t\t\tlet mixY2 = getValue(nextMap, \"mixY\", mixX2);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\t\t\t\tmixX = mixX2;\n\t\t\t\t\t\t\tmixY = mixY2;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Physics constraint timelines.\n\t\tif (map.physics) {\n\t\t\tfor (let constraintName in map.physics) {\n\t\t\t\tlet constraintMap = map.physics[constraintName];\n\t\t\t\tlet constraintIndex = -1;\n\t\t\t\tif (constraintName.length > 0) {\n\t\t\t\t\tlet constraint = skeletonData.findPhysicsConstraint(constraintName);\n\t\t\t\t\tif (!constraint) throw new Error(\"Physics constraint not found: \" + constraintName);\n\t\t\t\t\tconstraintIndex = skeletonData.physicsConstraints.indexOf(constraint);\n\t\t\t\t}\n\t\t\t\tfor (let timelineName in constraintMap) {\n\t\t\t\t\tlet timelineMap = constraintMap[timelineName];\n\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (timelineName == \"reset\") {\n\t\t\t\t\t\tconst timeline = new PhysicsConstraintResetTimeline(frames, constraintIndex);\n\t\t\t\t\t\tfor (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++)\n\t\t\t\t\t\t\ttimeline.setFrame(frame, getValue(keyMap, \"time\", 0));\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet timeline;\n\t\t\t\t\tif (timelineName == \"inertia\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"strength\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"damping\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"mass\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"wind\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"gravity\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"mix\") //\n\t\t\t\t\t\ttimeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, 1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attachment timelines.\n\t\tif (map.attachments) {\n\t\t\tfor (let attachmentsName in map.attachments) {\n\t\t\t\tlet attachmentsMap = map.attachments[attachmentsName];\n\t\t\t\tlet skin = skeletonData.findSkin(attachmentsName);\n\t\t\t\tif (!skin) throw new Error(\"Skin not found: \" + attachmentsName);\n\t\t\t\tfor (let slotMapName in attachmentsMap) {\n\t\t\t\t\tlet slotMap = attachmentsMap[slotMapName];\n\t\t\t\t\tlet slot = skeletonData.findSlot(slotMapName);\n\t\t\t\t\tif (!slot) throw new Error(\"Slot not found: \" + slotMapName);\n\t\t\t\t\tlet slotIndex = slot.index;\n\t\t\t\t\tfor (let attachmentMapName in slotMap) {\n\t\t\t\t\t\tlet attachmentMap = slotMap[attachmentMapName];\n\t\t\t\t\t\tlet attachment = skin.getAttachment(slotIndex, attachmentMapName);\n\n\t\t\t\t\t\tfor (let timelineMapName in attachmentMap) {\n\t\t\t\t\t\t\tlet timelineMap = attachmentMap[timelineMapName];\n\t\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\t\t\t\tif (timelineMapName == \"deform\") {\n\t\t\t\t\t\t\t\tlet weighted = attachment.bones;\n\t\t\t\t\t\t\t\tlet vertices = attachment.vertices;\n\t\t\t\t\t\t\t\tlet deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;\n\n\t\t\t\t\t\t\t\tlet timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment);\n\t\t\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\t\t\tlet deform: NumberArrayLike;\n\t\t\t\t\t\t\t\t\tlet verticesValue: Array = getValue(keyMap, \"vertices\", null);\n\t\t\t\t\t\t\t\t\tif (!verticesValue)\n\t\t\t\t\t\t\t\t\t\tdeform = weighted ? Utils.newFloatArray(deformLength) : vertices;\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tdeform = Utils.newFloatArray(deformLength);\n\t\t\t\t\t\t\t\t\t\tlet start = getValue(keyMap, \"offset\", 0);\n\t\t\t\t\t\t\t\t\t\tUtils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length);\n\t\t\t\t\t\t\t\t\t\tif (scale != 1) {\n\t\t\t\t\t\t\t\t\t\t\tfor (let i = start, n = i + verticesValue.length; i < n; i++)\n\t\t\t\t\t\t\t\t\t\t\t\tdeform[i] *= scale;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (!weighted) {\n\t\t\t\t\t\t\t\t\t\t\tfor (let i = 0; i < deformLength; i++)\n\t\t\t\t\t\t\t\t\t\t\t\tdeform[i] += vertices[i];\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, deform);\n\t\t\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\t\t\tif (curve) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);\n\t\t\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\t} else if (timelineMapName == \"sequence\") {\n\t\t\t\t\t\t\t\tlet timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment as unknown as HasTextureRegion);\n\t\t\t\t\t\t\t\tlet lastDelay = 0;\n\t\t\t\t\t\t\t\tfor (let frame = 0; frame < timelineMap.length; frame++) {\n\t\t\t\t\t\t\t\t\tlet delay = getValue(keyMap, \"delay\", lastDelay);\n\t\t\t\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\t\t\t\tlet mode = SequenceMode[getValue(keyMap, \"mode\", \"hold\")] as unknown as number;\n\t\t\t\t\t\t\t\t\tlet index = getValue(keyMap, \"index\", 0);\n\t\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, mode, index, delay);\n\t\t\t\t\t\t\t\t\tlastDelay = delay;\n\t\t\t\t\t\t\t\t\tkeyMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Draw order timelines.\n\t\tif (map.drawOrder) {\n\t\t\tlet timeline = new DrawOrderTimeline(map.drawOrder.length);\n\t\t\tlet slotCount = skeletonData.slots.length;\n\t\t\tlet frame = 0;\n\t\t\tfor (let i = 0; i < map.drawOrder.length; i++, frame++) {\n\t\t\t\tlet drawOrderMap = map.drawOrder[i];\n\t\t\t\tlet drawOrder: Array | null = null;\n\t\t\t\tlet offsets = getValue(drawOrderMap, \"offsets\", null);\n\t\t\t\tif (offsets) {\n\t\t\t\t\tdrawOrder = Utils.newArray(slotCount, -1);\n\t\t\t\t\tlet unchanged = Utils.newArray(slotCount - offsets.length, 0);\n\t\t\t\t\tlet originalIndex = 0, unchangedIndex = 0;\n\t\t\t\t\tfor (let ii = 0; ii < offsets.length; ii++) {\n\t\t\t\t\t\tlet offsetMap = offsets[ii];\n\t\t\t\t\t\tlet slot = skeletonData.findSlot(offsetMap.slot);\n\t\t\t\t\t\tif (!slot) throw new Error(\"Slot not found: \" + slot);\n\t\t\t\t\t\tlet slotIndex = slot.index;\n\t\t\t\t\t\t// Collect unchanged items.\n\t\t\t\t\t\twhile (originalIndex != slotIndex)\n\t\t\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t\t\t// Set changed items.\n\t\t\t\t\t\tdrawOrder[originalIndex + offsetMap.offset] = originalIndex++;\n\t\t\t\t\t}\n\t\t\t\t\t// Collect remaining unchanged items.\n\t\t\t\t\twhile (originalIndex < slotCount)\n\t\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t\t// Fill in unchanged items.\n\t\t\t\t\tfor (let ii = slotCount - 1; ii >= 0; ii--)\n\t\t\t\t\t\tif (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];\n\t\t\t\t}\n\t\t\t\ttimeline.setFrame(frame, getValue(drawOrderMap, \"time\", 0), drawOrder);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Event timelines.\n\t\tif (map.events) {\n\t\t\tlet timeline = new EventTimeline(map.events.length);\n\t\t\tlet frame = 0;\n\t\t\tfor (let i = 0; i < map.events.length; i++, frame++) {\n\t\t\t\tlet eventMap = map.events[i];\n\t\t\t\tlet eventData = skeletonData.findEvent(eventMap.name);\n\t\t\t\tif (!eventData) throw new Error(\"Event not found: \" + eventMap.name);\n\t\t\t\tlet event = new Event(Utils.toSinglePrecision(getValue(eventMap, \"time\", 0)), eventData);\n\t\t\t\tevent.intValue = getValue(eventMap, \"int\", eventData.intValue);\n\t\t\t\tevent.floatValue = getValue(eventMap, \"float\", eventData.floatValue);\n\t\t\t\tevent.stringValue = getValue(eventMap, \"string\", eventData.stringValue);\n\t\t\t\tif (event.data.audioPath) {\n\t\t\t\t\tevent.volume = getValue(eventMap, \"volume\", 1);\n\t\t\t\t\tevent.balance = getValue(eventMap, \"balance\", 0);\n\t\t\t\t}\n\t\t\t\ttimeline.setFrame(frame, event);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\tlet duration = 0;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\tduration = Math.max(duration, timelines[i].getDuration());\n\t\tskeletonData.animations.push(new Animation(name, timelines, duration));\n\t}\n}\n\nclass LinkedMesh {\n\tparent: string; skin: string;\n\tslotIndex: number;\n\tmesh: MeshAttachment;\n\tinheritTimeline: boolean;\n\n\tconstructor (mesh: MeshAttachment, skin: string, slotIndex: number, parent: string, inheritDeform: boolean) {\n\t\tthis.mesh = mesh;\n\t\tthis.skin = skin;\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.parent = parent;\n\t\tthis.inheritTimeline = inheritDeform;\n\t}\n}\n\nfunction readTimeline1 (keys: any[], timeline: CurveTimeline1, defaultValue: number, scale: number) {\n\tlet keyMap = keys[0];\n\tlet time = getValue(keyMap, \"time\", 0);\n\tlet value = getValue(keyMap, \"value\", defaultValue) * scale;\n\tlet bezier = 0;\n\tfor (let frame = 0; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value);\n\t\tlet nextMap = keys[frame + 1];\n\t\tif (!nextMap) {\n\t\t\ttimeline.shrink(bezier);\n\t\t\treturn timeline;\n\t\t}\n\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\tlet value2 = getValue(nextMap, \"value\", defaultValue) * scale;\n\t\tif (keyMap.curve) bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale);\n\t\ttime = time2;\n\t\tvalue = value2;\n\t\tkeyMap = nextMap;\n\t}\n}\n\nfunction readTimeline2 (keys: any[], timeline: CurveTimeline2, name1: string, name2: string, defaultValue: number, scale: number) {\n\tlet keyMap = keys[0];\n\tlet time = getValue(keyMap, \"time\", 0);\n\tlet value1 = getValue(keyMap, name1, defaultValue) * scale;\n\tlet value2 = getValue(keyMap, name2, defaultValue) * scale;\n\tlet bezier = 0;\n\tfor (let frame = 0; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value1, value2);\n\t\tlet nextMap = keys[frame + 1];\n\t\tif (!nextMap) {\n\t\t\ttimeline.shrink(bezier);\n\t\t\treturn timeline;\n\t\t}\n\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\tlet nvalue1 = getValue(nextMap, name1, defaultValue) * scale;\n\t\tlet nvalue2 = getValue(nextMap, name2, defaultValue) * scale;\n\t\tlet curve = keyMap.curve;\n\t\tif (curve) {\n\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale);\n\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale);\n\t\t}\n\t\ttime = time2;\n\t\tvalue1 = nvalue1;\n\t\tvalue2 = nvalue2;\n\t\tkeyMap = nextMap;\n\t}\n}\n\nfunction readCurve (curve: any, timeline: CurveTimeline, bezier: number, frame: number, value: number, time1: number, time2: number,\n\tvalue1: number, value2: number, scale: number) {\n\tif (curve == \"stepped\") {\n\t\ttimeline.setStepped(frame);\n\t\treturn bezier;\n\t}\n\tlet i = value << 2;\n\tlet cx1 = curve[i];\n\tlet cy1 = curve[i + 1] * scale;\n\tlet cx2 = curve[i + 2];\n\tlet cy2 = curve[i + 3] * scale;\n\ttimeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);\n\treturn bezier + 1;\n}\n\nfunction getValue (map: any, property: string, defaultValue: any) {\n\treturn map[property] !== undefined ? map[property] : defaultValue;\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\n(() => {\n\tif (typeof Math.fround === \"undefined\") {\n\t\tMath.fround = (function (array) {\n\t\t\treturn function (x: number) {\n\t\t\t\treturn array[0] = x, array[0];\n\t\t\t};\n\t\t})(new Float32Array(1));\n\t}\n})();\n\nexport { }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Restorable, BlendMode } from \"@esotericsoftware/spine-core\";\n\nexport class ManagedWebGLRenderingContext {\n\tpublic canvas: HTMLCanvasElement | OffscreenCanvas;\n\tpublic gl: WebGLRenderingContext;\n\tprivate restorables = new Array();\n\n\tconstructor (canvasOrContext: HTMLCanvasElement | WebGLRenderingContext, contextConfig: any = { alpha: \"true\" }) {\n\t\tif (!((canvasOrContext instanceof WebGLRenderingContext) || (typeof WebGL2RenderingContext !== 'undefined' && canvasOrContext instanceof WebGL2RenderingContext))) {\n\t\t\tlet canvas: HTMLCanvasElement = canvasOrContext;\n\t\t\tthis.gl = (canvas.getContext(\"webgl2\", contextConfig) || canvas.getContext(\"webgl\", contextConfig));\n\t\t\tthis.canvas = canvas;\n\t\t\tcanvas.addEventListener(\"webglcontextlost\", (e: any) => {\n\t\t\t\tlet event = e;\n\t\t\t\tif (e) e.preventDefault();\n\t\t\t});\n\t\t\tcanvas.addEventListener(\"webglcontextrestored\", (e: any) => {\n\t\t\t\tfor (let i = 0, n = this.restorables.length; i < n; i++)\n\t\t\t\t\tthis.restorables[i].restore();\n\t\t\t});\n\t\t} else {\n\t\t\tthis.gl = canvasOrContext;\n\t\t\tthis.canvas = this.gl.canvas;\n\t\t}\n\t}\n\n\taddRestorable (restorable: Restorable) {\n\t\tthis.restorables.push(restorable);\n\t}\n\n\tremoveRestorable (restorable: Restorable) {\n\t\tlet index = this.restorables.indexOf(restorable);\n\t\tif (index > -1) this.restorables.splice(index, 1);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture, Disposable, Restorable, TextureFilter, TextureWrap } from \"@esotericsoftware/spine-core\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class GLTexture extends Texture implements Disposable, Restorable {\n\tcontext: ManagedWebGLRenderingContext;\n\tprivate texture: WebGLTexture | null = null;\n\tprivate boundUnit = 0;\n\tprivate useMipMaps = false;\n\n\tpublic static DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false;\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, image: HTMLImageElement | ImageBitmap, useMipMaps: boolean = false) {\n\t\tsuper(image);\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.useMipMaps = useMipMaps;\n\t\tthis.restore();\n\t\tthis.context.addRestorable(this);\n\t}\n\n\tsetFilters (minFilter: TextureFilter, magFilter: TextureFilter) {\n\t\tlet gl = this.context.gl;\n\t\tthis.bind();\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, GLTexture.validateMagFilter(magFilter));\n\t\tthis.useMipMaps = GLTexture.usesMipMaps(minFilter);\n\t\tif (this.useMipMaps) gl.generateMipmap(gl.TEXTURE_2D);\n\t}\n\n\tstatic validateMagFilter (magFilter: TextureFilter) {\n\t\tswitch (magFilter) {\n\t\t\tcase TextureFilter.MipMapLinearLinear:\n\t\t\tcase TextureFilter.MipMapLinearNearest:\n\t\t\tcase TextureFilter.MipMapNearestLinear:\n\t\t\tcase TextureFilter.MipMapNearestNearest:\n\t\t\t\treturn TextureFilter.Linear;\n\t\t\tdefault:\n\t\t\t\treturn magFilter;\n\t\t}\n\t}\n\n\tstatic usesMipMaps (filter: TextureFilter) {\n\t\tswitch (filter) {\n\t\t\tcase TextureFilter.MipMapLinearLinear:\n\t\t\tcase TextureFilter.MipMapLinearNearest:\n\t\t\tcase TextureFilter.MipMapNearestLinear:\n\t\t\tcase TextureFilter.MipMapNearestNearest:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tsetWraps (uWrap: TextureWrap, vWrap: TextureWrap) {\n\t\tlet gl = this.context.gl;\n\t\tthis.bind();\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap);\n\t}\n\n\tupdate (useMipMaps: boolean) {\n\t\tlet gl = this.context.gl;\n\t\tif (!this.texture) this.texture = this.context.gl.createTexture();\n\t\tthis.bind();\n\t\tif (GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tif (useMipMaps) gl.generateMipmap(gl.TEXTURE_2D);\n\t}\n\n\trestore () {\n\t\tthis.texture = null;\n\t\tthis.update(this.useMipMaps);\n\t}\n\n\tbind (unit: number = 0) {\n\t\tlet gl = this.context.gl;\n\t\tthis.boundUnit = unit;\n\t\tgl.activeTexture(gl.TEXTURE0 + unit);\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.texture);\n\t}\n\n\tunbind () {\n\t\tlet gl = this.context.gl;\n\t\tgl.activeTexture(gl.TEXTURE0 + this.boundUnit);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t}\n\n\tdispose () {\n\t\tthis.context.removeRestorable(this);\n\t\tlet gl = this.context.gl;\n\t\tgl.deleteTexture(this.texture);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { AssetManagerBase, Downloader } from \"@esotericsoftware/spine-core\"\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\nimport { GLTexture } from \"./GLTexture.js\";\n\n\nexport class AssetManager extends AssetManagerBase {\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, pathPrefix: string = \"\", downloader: Downloader = new Downloader()) {\n\t\tsuper((image: HTMLImageElement | ImageBitmap) => {\n\t\t\treturn new GLTexture(context, image);\n\t\t}, pathPrefix, downloader);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Matrix4, M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33 } from \"./Matrix4.js\";\n\nexport class Vector3 {\n\tx = 0;\n\ty = 0;\n\tz = 0;\n\n\tconstructor (x: number = 0, y: number = 0, z: number = 0) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t}\n\n\tsetFrom (v: Vector3): Vector3 {\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\t\tthis.z = v.z;\n\t\treturn this;\n\t}\n\n\tset (x: number, y: number, z: number): Vector3 {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t\treturn this;\n\t}\n\n\tadd (v: Vector3): Vector3 {\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\t\tthis.z += v.z;\n\t\treturn this;\n\t}\n\n\tsub (v: Vector3): Vector3 {\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\t\tthis.z -= v.z;\n\t\treturn this;\n\t}\n\n\tscale (s: number): Vector3 {\n\t\tthis.x *= s;\n\t\tthis.y *= s;\n\t\tthis.z *= s;\n\t\treturn this;\n\t}\n\n\tnormalize (): Vector3 {\n\t\tlet len = this.length();\n\t\tif (len == 0) return this;\n\t\tlen = 1 / len;\n\t\tthis.x *= len;\n\t\tthis.y *= len;\n\t\tthis.z *= len;\n\t\treturn this;\n\t}\n\n\tcross (v: Vector3): Vector3 {\n\t\treturn this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x)\n\t}\n\n\tmultiply (matrix: Matrix4): Vector3 {\n\t\tlet l_mat = matrix.values;\n\t\treturn this.set(this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03],\n\t\t\tthis.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13],\n\t\t\tthis.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]);\n\t}\n\n\tproject (matrix: Matrix4): Vector3 {\n\t\tlet l_mat = matrix.values;\n\t\tlet l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]);\n\t\treturn this.set((this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w,\n\t\t\t(this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w,\n\t\t\t(this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w);\n\t}\n\n\tdot (v: Vector3): number {\n\t\treturn this.x * v.x + this.y * v.y + this.z * v.z;\n\t}\n\n\tlength (): number {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\n\t}\n\n\tdistance (v: Vector3): number {\n\t\tlet a = v.x - this.x;\n\t\tlet b = v.y - this.y;\n\t\tlet c = v.z - this.z;\n\t\treturn Math.sqrt(a * a + b * b + c * c);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Vector3 } from \"./Vector3.js\";\n\nexport const M00 = 0;\nexport const M01 = 4;\nexport const M02 = 8;\nexport const M03 = 12;\nexport const M10 = 1;\nexport const M11 = 5;\nexport const M12 = 9;\nexport const M13 = 13;\nexport const M20 = 2;\nexport const M21 = 6;\nexport const M22 = 10;\nexport const M23 = 14;\nexport const M30 = 3;\nexport const M31 = 7;\nexport const M32 = 11;\nexport const M33 = 15;\n\nexport class Matrix4 {\n\ttemp: Float32Array = new Float32Array(16);\n\tvalues: Float32Array = new Float32Array(16);\n\n\tprivate static xAxis = new Vector3();\n\tprivate static yAxis = new Vector3();\n\tprivate static zAxis = new Vector3();\n\tprivate static tmpMatrix = new Matrix4();\n\n\tconstructor () {\n\t\tlet v = this.values;\n\t\tv[M00] = 1;\n\t\tv[M11] = 1;\n\t\tv[M22] = 1;\n\t\tv[M33] = 1;\n\t}\n\n\tset (values: ArrayLike): Matrix4 {\n\t\tthis.values.set(values);\n\t\treturn this;\n\t}\n\n\ttranspose (): Matrix4 {\n\t\tlet t = this.temp;\n\t\tlet v = this.values;\n\t\tt[M00] = v[M00];\n\t\tt[M01] = v[M10];\n\t\tt[M02] = v[M20];\n\t\tt[M03] = v[M30];\n\t\tt[M10] = v[M01];\n\t\tt[M11] = v[M11];\n\t\tt[M12] = v[M21];\n\t\tt[M13] = v[M31];\n\t\tt[M20] = v[M02];\n\t\tt[M21] = v[M12];\n\t\tt[M22] = v[M22];\n\t\tt[M23] = v[M32];\n\t\tt[M30] = v[M03];\n\t\tt[M31] = v[M13];\n\t\tt[M32] = v[M23];\n\t\tt[M33] = v[M33];\n\t\treturn this.set(t);\n\t}\n\n\tidentity (): Matrix4 {\n\t\tlet v = this.values;\n\t\tv[M00] = 1;\n\t\tv[M01] = 0;\n\t\tv[M02] = 0;\n\t\tv[M03] = 0;\n\t\tv[M10] = 0;\n\t\tv[M11] = 1;\n\t\tv[M12] = 0;\n\t\tv[M13] = 0;\n\t\tv[M20] = 0;\n\t\tv[M21] = 0;\n\t\tv[M22] = 1;\n\t\tv[M23] = 0;\n\t\tv[M30] = 0;\n\t\tv[M31] = 0;\n\t\tv[M32] = 0;\n\t\tv[M33] = 1;\n\t\treturn this;\n\t}\n\n\tinvert (): Matrix4 {\n\t\tlet v = this.values;\n\t\tlet t = this.temp;\n\t\tlet l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03]\n\t\t\t+ v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03]\n\t\t\t- v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13]\n\t\t\t- v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13]\n\t\t\t+ v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23]\n\t\t\t+ v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23]\n\t\t\t- v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33]\n\t\t\t- v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33];\n\t\tif (l_det == 0) throw new Error(\"non-invertible matrix\");\n\t\tlet inv_det = 1.0 / l_det;\n\t\tt[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32]\n\t\t\t- v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33];\n\t\tt[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32]\n\t\t\t+ v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33];\n\t\tt[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32]\n\t\t\t- v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33];\n\t\tt[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22]\n\t\t\t+ v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23];\n\t\tt[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32]\n\t\t\t+ v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33];\n\t\tt[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32]\n\t\t\t- v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33];\n\t\tt[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32]\n\t\t\t+ v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33];\n\t\tt[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22]\n\t\t\t- v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23];\n\t\tt[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31]\n\t\t\t- v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33];\n\t\tt[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31]\n\t\t\t+ v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33];\n\t\tt[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31]\n\t\t\t- v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33];\n\t\tt[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21]\n\t\t\t+ v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23];\n\t\tt[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31]\n\t\t\t+ v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32];\n\t\tt[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31]\n\t\t\t- v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32];\n\t\tt[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31]\n\t\t\t+ v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32];\n\t\tt[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21]\n\t\t\t- v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22];\n\t\tv[M00] = t[M00] * inv_det;\n\t\tv[M01] = t[M01] * inv_det;\n\t\tv[M02] = t[M02] * inv_det;\n\t\tv[M03] = t[M03] * inv_det;\n\t\tv[M10] = t[M10] * inv_det;\n\t\tv[M11] = t[M11] * inv_det;\n\t\tv[M12] = t[M12] * inv_det;\n\t\tv[M13] = t[M13] * inv_det;\n\t\tv[M20] = t[M20] * inv_det;\n\t\tv[M21] = t[M21] * inv_det;\n\t\tv[M22] = t[M22] * inv_det;\n\t\tv[M23] = t[M23] * inv_det;\n\t\tv[M30] = t[M30] * inv_det;\n\t\tv[M31] = t[M31] * inv_det;\n\t\tv[M32] = t[M32] * inv_det;\n\t\tv[M33] = t[M33] * inv_det;\n\t\treturn this;\n\t}\n\n\tdeterminant (): number {\n\t\tlet v = this.values;\n\t\treturn v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03]\n\t\t\t+ v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03]\n\t\t\t- v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13]\n\t\t\t- v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13]\n\t\t\t+ v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23]\n\t\t\t+ v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23]\n\t\t\t- v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33]\n\t\t\t- v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33];\n\t}\n\n\ttranslate (x: number, y: number, z: number): Matrix4 {\n\t\tlet v = this.values;\n\t\tv[M03] += x;\n\t\tv[M13] += y;\n\t\tv[M23] += z;\n\t\treturn this;\n\t}\n\n\tcopy (): Matrix4 {\n\t\treturn new Matrix4().set(this.values);\n\t}\n\n\tprojection (near: number, far: number, fovy: number, aspectRatio: number): Matrix4 {\n\t\tthis.identity();\n\t\tlet l_fd = (1.0 / Math.tan((fovy * (Math.PI / 180)) / 2.0));\n\t\tlet l_a1 = (far + near) / (near - far);\n\t\tlet l_a2 = (2 * far * near) / (near - far);\n\t\tlet v = this.values;\n\t\tv[M00] = l_fd / aspectRatio;\n\t\tv[M10] = 0;\n\t\tv[M20] = 0;\n\t\tv[M30] = 0;\n\t\tv[M01] = 0;\n\t\tv[M11] = l_fd;\n\t\tv[M21] = 0;\n\t\tv[M31] = 0;\n\t\tv[M02] = 0;\n\t\tv[M12] = 0;\n\t\tv[M22] = l_a1;\n\t\tv[M32] = -1;\n\t\tv[M03] = 0;\n\t\tv[M13] = 0;\n\t\tv[M23] = l_a2;\n\t\tv[M33] = 0;\n\t\treturn this;\n\t}\n\n\tortho2d (x: number, y: number, width: number, height: number): Matrix4 {\n\t\treturn this.ortho(x, x + width, y, y + height, 0, 1);\n\t}\n\n\tortho (left: number, right: number, bottom: number, top: number, near: number, far: number): Matrix4 {\n\t\tthis.identity();\n\t\tlet x_orth = 2 / (right - left);\n\t\tlet y_orth = 2 / (top - bottom);\n\t\tlet z_orth = -2 / (far - near);\n\n\t\tlet tx = -(right + left) / (right - left);\n\t\tlet ty = -(top + bottom) / (top - bottom);\n\t\tlet tz = -(far + near) / (far - near);\n\n\t\tlet v = this.values;\n\t\tv[M00] = x_orth;\n\t\tv[M10] = 0;\n\t\tv[M20] = 0;\n\t\tv[M30] = 0;\n\t\tv[M01] = 0;\n\t\tv[M11] = y_orth;\n\t\tv[M21] = 0;\n\t\tv[M31] = 0;\n\t\tv[M02] = 0;\n\t\tv[M12] = 0;\n\t\tv[M22] = z_orth;\n\t\tv[M32] = 0;\n\t\tv[M03] = tx;\n\t\tv[M13] = ty;\n\t\tv[M23] = tz;\n\t\tv[M33] = 1;\n\t\treturn this;\n\t}\n\n\tmultiply (matrix: Matrix4): Matrix4 {\n\t\tlet t = this.temp;\n\t\tlet v = this.values;\n\t\tlet m = matrix.values;\n\t\tt[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30];\n\t\tt[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31];\n\t\tt[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32];\n\t\tt[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33];\n\t\tt[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30];\n\t\tt[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31];\n\t\tt[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32];\n\t\tt[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33];\n\t\tt[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30];\n\t\tt[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31];\n\t\tt[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32];\n\t\tt[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33];\n\t\tt[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30];\n\t\tt[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31];\n\t\tt[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32];\n\t\tt[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33];\n\t\treturn this.set(this.temp);\n\t}\n\n\tmultiplyLeft (matrix: Matrix4): Matrix4 {\n\t\tlet t = this.temp;\n\t\tlet v = this.values;\n\t\tlet m = matrix.values;\n\t\tt[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30];\n\t\tt[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31];\n\t\tt[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32];\n\t\tt[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33];\n\t\tt[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30];\n\t\tt[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31];\n\t\tt[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32];\n\t\tt[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33];\n\t\tt[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30];\n\t\tt[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31];\n\t\tt[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32];\n\t\tt[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33];\n\t\tt[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30];\n\t\tt[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31];\n\t\tt[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32];\n\t\tt[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33];\n\t\treturn this.set(this.temp);\n\t}\n\n\tlookAt (position: Vector3, direction: Vector3, up: Vector3) {\n\t\tlet xAxis = Matrix4.xAxis, yAxis = Matrix4.yAxis, zAxis = Matrix4.zAxis;\n\t\tzAxis.setFrom(direction).normalize();\n\t\txAxis.setFrom(direction).normalize();\n\t\txAxis.cross(up).normalize();\n\t\tyAxis.setFrom(xAxis).cross(zAxis).normalize();\n\t\tthis.identity();\n\t\tlet val = this.values;\n\t\tval[M00] = xAxis.x;\n\t\tval[M01] = xAxis.y;\n\t\tval[M02] = xAxis.z;\n\t\tval[M10] = yAxis.x;\n\t\tval[M11] = yAxis.y;\n\t\tval[M12] = yAxis.z;\n\t\tval[M20] = -zAxis.x;\n\t\tval[M21] = -zAxis.y;\n\t\tval[M22] = -zAxis.z;\n\n\t\tMatrix4.tmpMatrix.identity();\n\t\tMatrix4.tmpMatrix.values[M03] = -position.x;\n\t\tMatrix4.tmpMatrix.values[M13] = -position.y;\n\t\tMatrix4.tmpMatrix.values[M23] = -position.z;\n\t\tthis.multiply(Matrix4.tmpMatrix)\n\n\t\treturn this;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Matrix4 } from \"./Matrix4.js\";\nimport { Vector3 } from \"./Vector3.js\";\n\nexport class OrthoCamera {\n\tposition = new Vector3(0, 0, 0);\n\tdirection = new Vector3(0, 0, -1);\n\tup = new Vector3(0, 1, 0);\n\tnear = 0;\n\tfar = 100;\n\tzoom = 1;\n\tviewportWidth = 0;\n\tviewportHeight = 0;\n\tprojectionView = new Matrix4();\n\tinverseProjectionView = new Matrix4();\n\tprojection = new Matrix4();\n\tview = new Matrix4();\n\n\tconstructor (viewportWidth: number, viewportHeight: number) {\n\t\tthis.viewportWidth = viewportWidth;\n\t\tthis.viewportHeight = viewportHeight;\n\t\tthis.update();\n\t}\n\n\tupdate () {\n\t\tlet projection = this.projection;\n\t\tlet view = this.view;\n\t\tlet projectionView = this.projectionView;\n\t\tlet inverseProjectionView = this.inverseProjectionView;\n\t\tlet zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight;\n\t\tprojection.ortho(zoom * (-viewportWidth / 2), zoom * (viewportWidth / 2),\n\t\t\tzoom * (-viewportHeight / 2), zoom * (viewportHeight / 2),\n\t\t\tthis.near, this.far);\n\t\tview.lookAt(this.position, this.direction, this.up);\n\t\tprojectionView.set(projection.values);\n\t\tprojectionView.multiply(view);\n\t\tinverseProjectionView.set(projectionView.values).invert();\n\t}\n\n\tscreenToWorld (screenCoords: Vector3, screenWidth: number, screenHeight: number) {\n\t\tlet x = screenCoords.x, y = screenHeight - screenCoords.y - 1;\n\t\tscreenCoords.x = (2 * x) / screenWidth - 1;\n\t\tscreenCoords.y = (2 * y) / screenHeight - 1;\n\t\tscreenCoords.z = (2 * screenCoords.z) - 1;\n\t\tscreenCoords.project(this.inverseProjectionView);\n\t\treturn screenCoords;\n\t}\n\n\tworldToScreen (worldCoords: Vector3, screenWidth: number, screenHeight: number) {\n\t\tworldCoords.project(this.projectionView);\n\t\tworldCoords.x = screenWidth * (worldCoords.x + 1) / 2;\n\t\tworldCoords.y = screenHeight * (worldCoords.y + 1) / 2;\n\t\tworldCoords.z = (worldCoords.z + 1) / 2;\n\t\treturn worldCoords;\n\t}\n\n\tsetViewport (viewportWidth: number, viewportHeight: number) {\n\t\tthis.viewportWidth = viewportWidth;\n\t\tthis.viewportHeight = viewportHeight;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport class Input {\n\telement: HTMLElement;\n\tmouseX = 0;\n\tmouseY = 0;\n\tbuttonDown = false;\n\ttouch0: Touch | null = null;\n\ttouch1: Touch | null = null;\n\tinitialPinchDistance = 0;\n\tprivate listeners = new Array();\n\tprivate eventListeners: Array<{ target: any, event: any, func: any }> = [];\n\n\tconstructor (element: HTMLElement) {\n\t\tthis.element = element;\n\t\tthis.setupCallbacks(element);\n\t}\n\n\tprivate setupCallbacks (element: HTMLElement) {\n\t\tlet mouseDown = (ev: UIEvent) => {\n\t\t\tif (ev instanceof MouseEvent) {\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tthis.mouseX = ev.clientX - rect.left;;\n\t\t\t\tthis.mouseY = ev.clientY - rect.top;\n\t\t\t\tthis.buttonDown = true;\n\t\t\t\tthis.listeners.map((listener) => { if (listener.down) listener.down(this.mouseX, this.mouseY); });\n\n\t\t\t\tdocument.addEventListener(\"mousemove\", mouseMove);\n\t\t\t\tdocument.addEventListener(\"mouseup\", mouseUp);\n\t\t\t}\n\t\t}\n\n\t\tlet mouseMove = (ev: UIEvent) => {\n\t\t\tif (ev instanceof MouseEvent) {\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tthis.mouseX = ev.clientX - rect.left;;\n\t\t\t\tthis.mouseY = ev.clientY - rect.top;\n\n\t\t\t\tthis.listeners.map((listener) => {\n\t\t\t\t\tif (this.buttonDown) {\n\t\t\t\t\t\tif (listener.dragged) listener.dragged(this.mouseX, this.mouseY);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (listener.moved) listener.moved(this.mouseX, this.mouseY);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tlet mouseUp = (ev: UIEvent) => {\n\t\t\tif (ev instanceof MouseEvent) {\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tthis.mouseX = ev.clientX - rect.left;;\n\t\t\t\tthis.mouseY = ev.clientY - rect.top;\n\t\t\t\tthis.buttonDown = false;\n\t\t\t\tthis.listeners.map((listener) => { if (listener.up) listener.up(this.mouseX, this.mouseY); });\n\n\t\t\t\tdocument.removeEventListener(\"mousemove\", mouseMove);\n\t\t\t\tdocument.removeEventListener(\"mouseup\", mouseUp);\n\t\t\t}\n\t\t}\n\n\t\tlet mouseWheel = (e: WheelEvent) => {\n\t\t\te.preventDefault();\n\t\t\tlet deltaY = e.deltaY;\n\t\t\tif (e.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8;\n\t\t\tif (e.deltaMode == WheelEvent.DOM_DELTA_PAGE) deltaY *= 24;\n\t\t\tthis.listeners.map((listener) => { if (listener.wheel) listener.wheel(e.deltaY); });\n\t\t};\n\n\t\telement.addEventListener(\"mousedown\", mouseDown, true);\n\t\telement.addEventListener(\"mousemove\", mouseMove, true);\n\t\telement.addEventListener(\"mouseup\", mouseUp, true);\n\t\telement.addEventListener(\"wheel\", mouseWheel, true);\n\n\n\t\telement.addEventListener(\"touchstart\", (ev: TouchEvent) => {\n\t\t\tif (!this.touch0 || !this.touch1) {\n\t\t\t\tvar touches = ev.changedTouches;\n\t\t\t\tlet nativeTouch = touches.item(0);\n\t\t\t\tif (!nativeTouch) return;\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tlet x = nativeTouch.clientX - rect.left;\n\t\t\t\tlet y = nativeTouch.clientY - rect.top;\n\t\t\t\tlet touch = new Touch(nativeTouch.identifier, x, y);\n\t\t\t\tthis.mouseX = x;\n\t\t\t\tthis.mouseY = y;\n\t\t\t\tthis.buttonDown = true;\n\n\t\t\t\tif (!this.touch0) {\n\t\t\t\t\tthis.touch0 = touch;\n\t\t\t\t\tthis.listeners.map((listener) => { if (listener.down) listener.down(touch.x, touch.y) })\n\t\t\t\t} else if (!this.touch1) {\n\t\t\t\t\tthis.touch1 = touch;\n\t\t\t\t\tlet dx = this.touch1.x - this.touch0.x;\n\t\t\t\t\tlet dy = this.touch1.x - this.touch0.x;\n\t\t\t\t\tthis.initialPinchDistance = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\t\tthis.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tev.preventDefault();\n\t\t}, false);\n\n\t\telement.addEventListener(\"touchmove\", (ev: TouchEvent) => {\n\t\t\tif (this.touch0) {\n\t\t\t\tvar touches = ev.changedTouches;\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tfor (var i = 0; i < touches.length; i++) {\n\t\t\t\t\tvar nativeTouch = touches[i];\n\t\t\t\t\tlet x = nativeTouch.clientX - rect.left;\n\t\t\t\t\tlet y = nativeTouch.clientY - rect.top;\n\n\t\t\t\t\tif (this.touch0.identifier === nativeTouch.identifier) {\n\t\t\t\t\t\tthis.touch0.x = this.mouseX = x;\n\t\t\t\t\t\tthis.touch0.y = this.mouseY = y;\n\t\t\t\t\t\tthis.listeners.map((listener) => { if (listener.dragged) listener.dragged(x, y) });\n\t\t\t\t\t}\n\t\t\t\t\tif (this.touch1 && this.touch1.identifier === nativeTouch.identifier) {\n\t\t\t\t\t\tthis.touch1.x = this.mouseX = x;\n\t\t\t\t\t\tthis.touch1.y = this.mouseY = y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.touch0 && this.touch1) {\n\t\t\t\t\tlet dx = this.touch1.x - this.touch0.x;\n\t\t\t\t\tlet dy = this.touch1.x - this.touch0.x;\n\t\t\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\t\tthis.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tev.preventDefault();\n\t\t}, false);\n\n\t\tlet touchEnd = (ev: TouchEvent) => {\n\t\t\tif (this.touch0) {\n\t\t\t\tvar touches = ev.changedTouches;\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\n\t\t\t\tfor (var i = 0; i < touches.length; i++) {\n\t\t\t\t\tvar nativeTouch = touches[i];\n\t\t\t\t\tlet x = nativeTouch.clientX - rect.left;\n\t\t\t\t\tlet y = nativeTouch.clientY - rect.top;\n\n\t\t\t\t\tif (this.touch0.identifier === nativeTouch.identifier) {\n\t\t\t\t\t\tthis.touch0 = null;\n\t\t\t\t\t\tthis.mouseX = x;\n\t\t\t\t\t\tthis.mouseY = y;\n\t\t\t\t\t\tthis.listeners.map((listener) => { if (listener.up) listener.up(x, y) });\n\n\t\t\t\t\t\tif (!this.touch1) {\n\t\t\t\t\t\t\tthis.buttonDown = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.touch0 = this.touch1;\n\t\t\t\t\t\t\tthis.touch1 = null;\n\t\t\t\t\t\t\tthis.mouseX = this.touch0.x;\n\t\t\t\t\t\t\tthis.mouseX = this.touch0.x;\n\t\t\t\t\t\t\tthis.buttonDown = true;\n\t\t\t\t\t\t\tthis.listeners.map((listener) => { if (listener.down) listener.down(this.touch0!.x, this.touch0!.y) });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.touch1 && this.touch1.identifier) {\n\t\t\t\t\t\tthis.touch1 = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tev.preventDefault();\n\t\t};\n\t\telement.addEventListener(\"touchend\", touchEnd, false);\n\t\telement.addEventListener(\"touchcancel\", touchEnd);\n\t}\n\n\taddListener (listener: InputListener) {\n\t\tthis.listeners.push(listener);\n\t}\n\n\tremoveListener (listener: InputListener) {\n\t\tlet idx = this.listeners.indexOf(listener);\n\t\tif (idx > -1) {\n\t\t\tthis.listeners.splice(idx, 1);\n\t\t}\n\t}\n}\n\nexport class Touch {\n\tconstructor (public identifier: number, public x: number, public y: number) {\n\t}\n}\n\nexport interface InputListener {\n\tdown?(x: number, y: number): void;\n\tup?(x: number, y: number): void;\n\tmoved?(x: number, y: number): void;\n\tdragged?(x: number, y: number): void;\n\twheel?(delta: number): void;\n\tzoom?(initialDistance: number, distance: number): void;\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Input } from \"./Input.js\";\nimport { OrthoCamera } from \"./Camera.js\";\nimport { Vector3 } from \"./Vector3.js\";\n\nexport class CameraController {\n\tconstructor (public canvas: HTMLElement, public camera: OrthoCamera) {\n\t\tlet cameraX = 0, cameraY = 0, cameraZoom = 0;\n\t\tlet mouseX = 0, mouseY = 0;\n\t\tlet lastX = 0, lastY = 0;\n\t\tlet initialZoom = 0;\n\n\t\tnew Input(canvas).addListener({\n\t\t\tdown: (x: number, y: number) => {\n\t\t\t\tcameraX = camera.position.x;\n\t\t\t\tcameraY = camera.position.y;\n\t\t\t\tmouseX = lastX = x;\n\t\t\t\tmouseY = lastY = y;\n\t\t\t\tinitialZoom = camera.zoom;\n\t\t\t},\n\t\t\tdragged: (x: number, y: number) => {\n\t\t\t\tlet deltaX = x - mouseX;\n\t\t\t\tlet deltaY = y - mouseY;\n\t\t\t\tlet originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight);\n\t\t\t\tlet deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld);\n\t\t\t\tcamera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0);\n\t\t\t\tcamera.update();\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t},\n\t\t\twheel: (delta: number) => {\n\t\t\t\tlet zoomAmount = delta / 200 * camera.zoom;\n\t\t\t\tlet newZoom = camera.zoom + zoomAmount;\n\t\t\t\tif (newZoom > 0) {\n\t\t\t\t\tlet x = 0, y = 0;\n\t\t\t\t\tif (delta < 0) {\n\t\t\t\t\t\tx = lastX; y = lastY;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2);\n\t\t\t\t\t\tlet mouseToCenterX = lastX - viewCenter.x;\n\t\t\t\t\t\tlet mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y;\n\t\t\t\t\t\tx = viewCenter.x - mouseToCenterX;\n\t\t\t\t\t\ty = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY;\n\t\t\t\t\t}\n\t\t\t\t\tlet oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight);\n\t\t\t\t\tcamera.zoom = newZoom;\n\t\t\t\t\tcamera.update();\n\t\t\t\t\tlet newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight);\n\t\t\t\t\tcamera.position.add(oldDistance.sub(newDistance));\n\t\t\t\t\tcamera.update();\n\t\t\t\t}\n\t\t\t},\n\t\t\tzoom: (initialDistance, distance) => {\n\t\t\t\tlet newZoom = initialDistance / distance;\n\t\t\t\tcamera.zoom = initialZoom * newZoom;\n\t\t\t},\n\t\t\tup: (x: number, y: number) => {\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t},\n\t\t\tmoved: (x: number, y: number) => {\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t},\n\t\t});\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Restorable } from \"@esotericsoftware/spine-core\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class Shader implements Disposable, Restorable {\n\tpublic static MVP_MATRIX = \"u_projTrans\";\n\tpublic static POSITION = \"a_position\";\n\tpublic static COLOR = \"a_color\";\n\tpublic static COLOR2 = \"a_color2\";\n\tpublic static TEXCOORDS = \"a_texCoords\";\n\tpublic static SAMPLER = \"u_texture\";\n\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate vs: WebGLShader | null = null;\n\tprivate vsSource: string;\n\tprivate fs: WebGLShader | null = null;\n\tprivate fsSource: string;\n\tprivate program: WebGLProgram | null = null;\n\tprivate tmp2x2: Float32Array = new Float32Array(2 * 2);\n\tprivate tmp3x3: Float32Array = new Float32Array(3 * 3);\n\tprivate tmp4x4: Float32Array = new Float32Array(4 * 4);\n\n\tpublic getProgram () { return this.program; }\n\tpublic getVertexShader () { return this.vertexShader; }\n\tpublic getFragmentShader () { return this.fragmentShader; }\n\tpublic getVertexShaderSource () { return this.vsSource; }\n\tpublic getFragmentSource () { return this.fsSource; }\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, private vertexShader: string, private fragmentShader: string) {\n\t\tthis.vsSource = vertexShader;\n\t\tthis.fsSource = fragmentShader;\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.context.addRestorable(this);\n\t\tthis.compile();\n\t}\n\n\tprivate compile () {\n\t\tlet gl = this.context.gl;\n\t\ttry {\n\t\t\tthis.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader);\n\t\t\tif (!this.vs) throw new Error(\"Couldn't compile vertex shader.\");\n\t\t\tthis.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader);\n\t\t\tif (!this.fs) throw new Error(\"Couldn#t compile fragment shader.\");\n\t\t\tthis.program = this.compileProgram(this.vs, this.fs);\n\t\t} catch (e) {\n\t\t\tthis.dispose();\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tprivate compileShader (type: number, source: string) {\n\t\tlet gl = this.context.gl;\n\t\tlet shader = gl.createShader(type);\n\t\tif (!shader) throw new Error(\"Couldn't create shader.\");\n\t\tgl.shaderSource(shader, source);\n\t\tgl.compileShader(shader);\n\t\tif (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n\t\t\tlet error = \"Couldn't compile shader: \" + gl.getShaderInfoLog(shader);\n\t\t\tgl.deleteShader(shader);\n\t\t\tif (!gl.isContextLost()) throw new Error(error);\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate compileProgram (vs: WebGLShader, fs: WebGLShader) {\n\t\tlet gl = this.context.gl;\n\t\tlet program = gl.createProgram();\n\t\tif (!program) throw new Error(\"Couldn't compile program.\");\n\t\tgl.attachShader(program, vs);\n\t\tgl.attachShader(program, fs);\n\t\tgl.linkProgram(program);\n\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tlet error = \"Couldn't compile shader program: \" + gl.getProgramInfoLog(program);\n\t\t\tgl.deleteProgram(program);\n\t\t\tif (!gl.isContextLost()) throw new Error(error);\n\t\t}\n\t\treturn program;\n\t}\n\n\trestore () {\n\t\tthis.compile();\n\t}\n\n\tpublic bind () {\n\t\tthis.context.gl.useProgram(this.program);\n\t}\n\n\tpublic unbind () {\n\t\tthis.context.gl.useProgram(null);\n\t}\n\n\tpublic setUniformi (uniform: string, value: number) {\n\t\tthis.context.gl.uniform1i(this.getUniformLocation(uniform), value);\n\t}\n\n\tpublic setUniformf (uniform: string, value: number) {\n\t\tthis.context.gl.uniform1f(this.getUniformLocation(uniform), value);\n\t}\n\n\tpublic setUniform2f (uniform: string, value: number, value2: number) {\n\t\tthis.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2);\n\t}\n\n\tpublic setUniform3f (uniform: string, value: number, value2: number, value3: number) {\n\t\tthis.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3);\n\t}\n\n\tpublic setUniform4f (uniform: string, value: number, value2: number, value3: number, value4: number) {\n\t\tthis.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4);\n\t}\n\n\tpublic setUniform2x2f (uniform: string, value: ArrayLike) {\n\t\tlet gl = this.context.gl;\n\t\tthis.tmp2x2.set(value);\n\t\tgl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2);\n\t}\n\n\tpublic setUniform3x3f (uniform: string, value: ArrayLike) {\n\t\tlet gl = this.context.gl;\n\t\tthis.tmp3x3.set(value);\n\t\tgl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3);\n\t}\n\n\tpublic setUniform4x4f (uniform: string, value: ArrayLike) {\n\t\tlet gl = this.context.gl;\n\t\tthis.tmp4x4.set(value);\n\t\tgl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4);\n\t}\n\n\tpublic getUniformLocation (uniform: string): WebGLUniformLocation | null {\n\t\tlet gl = this.context.gl;\n\t\tif (!this.program) throw new Error(\"Shader not compiled.\");\n\t\tlet location = gl.getUniformLocation(this.program, uniform);\n\t\tif (!location && !gl.isContextLost()) throw new Error(`Couldn't find location for uniform ${uniform}`);\n\t\treturn location;\n\t}\n\n\tpublic getAttributeLocation (attribute: string): number {\n\t\tlet gl = this.context.gl;\n\t\tif (!this.program) throw new Error(\"Shader not compiled.\");\n\t\tlet location = gl.getAttribLocation(this.program, attribute);\n\t\tif (location == -1 && !gl.isContextLost()) throw new Error(`Couldn't find location for attribute ${attribute}`);\n\t\treturn location;\n\t}\n\n\tpublic dispose () {\n\t\tthis.context.removeRestorable(this);\n\n\t\tlet gl = this.context.gl;\n\t\tif (this.vs) {\n\t\t\tgl.deleteShader(this.vs);\n\t\t\tthis.vs = null;\n\t\t}\n\n\t\tif (this.fs) {\n\t\t\tgl.deleteShader(this.fs);\n\t\t\tthis.fs = null;\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tgl.deleteProgram(this.program);\n\t\t\tthis.program = null;\n\t\t}\n\t}\n\n\tpublic static newColoredTextured (context: ManagedWebGLRenderingContext | WebGLRenderingContext): Shader {\n\t\tlet vs = `\nattribute vec4 ${Shader.POSITION};\nattribute vec4 ${Shader.COLOR};\nattribute vec2 ${Shader.TEXCOORDS};\nuniform mat4 ${Shader.MVP_MATRIX};\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvoid main () {\n\tv_color = ${Shader.COLOR};\n\tv_texCoords = ${Shader.TEXCOORDS};\n\tgl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};\n}\n`;\n\n\t\tlet fs = `\n#ifdef GL_ES\n\t#define LOWP lowp\n\tprecision mediump float;\n#else\n\t#define LOWP\n#endif\nvarying LOWP vec4 v_color;\nvarying vec2 v_texCoords;\nuniform sampler2D u_texture;\n\nvoid main () {\n\tgl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n}\n`;\n\n\t\treturn new Shader(context, vs, fs);\n\t}\n\n\tpublic static newTwoColoredTextured (context: ManagedWebGLRenderingContext | WebGLRenderingContext): Shader {\n\t\tlet vs = `\nattribute vec4 ${Shader.POSITION};\nattribute vec4 ${Shader.COLOR};\nattribute vec4 ${Shader.COLOR2};\nattribute vec2 ${Shader.TEXCOORDS};\nuniform mat4 ${Shader.MVP_MATRIX};\nvarying vec4 v_light;\nvarying vec4 v_dark;\nvarying vec2 v_texCoords;\n\nvoid main () {\n\tv_light = ${Shader.COLOR};\n\tv_dark = ${Shader.COLOR2};\n\tv_texCoords = ${Shader.TEXCOORDS};\n\tgl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};\n}\n`;\n\n\t\tlet fs = `\n#ifdef GL_ES\n\t#define LOWP lowp\n\tprecision mediump float;\n#else\n\t#define LOWP\n#endif\nvarying LOWP vec4 v_light;\nvarying LOWP vec4 v_dark;\nvarying vec2 v_texCoords;\nuniform sampler2D u_texture;\n\nvoid main () {\n\tvec4 texColor = texture2D(u_texture, v_texCoords);\n\tgl_FragColor.a = texColor.a * v_light.a;\n\tgl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n}\n`;\n\n\t\treturn new Shader(context, vs, fs);\n\t}\n\n\tpublic static newColored (context: ManagedWebGLRenderingContext | WebGLRenderingContext): Shader {\n\t\tlet vs = `\nattribute vec4 ${Shader.POSITION};\nattribute vec4 ${Shader.COLOR};\nuniform mat4 ${Shader.MVP_MATRIX};\nvarying vec4 v_color;\n\nvoid main () {\n\tv_color = ${Shader.COLOR};\n\tgl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};\n}\n`;\n\n\t\tlet fs = `\n#ifdef GL_ES\n\t#define LOWP lowp\n\tprecision mediump float;\n#else\n\t#define LOWP\n#endif\nvarying LOWP vec4 v_color;\n\nvoid main () {\n\tgl_FragColor = v_color;\n}\n`;\n\n\t\treturn new Shader(context, vs, fs);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Restorable } from \"@esotericsoftware/spine-core\";\nimport { Shader } from \"./Shader.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\n\nexport class Mesh implements Disposable, Restorable {\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate vertices: Float32Array;\n\tprivate verticesBuffer: WebGLBuffer | null = null;\n\tprivate verticesLength = 0;\n\tprivate dirtyVertices = false;\n\tprivate indices: Uint16Array;\n\tprivate indicesBuffer: WebGLBuffer | null = null;\n\tprivate indicesLength = 0;\n\tprivate dirtyIndices = false;\n\tprivate elementsPerVertex = 0;\n\n\tgetAttributes (): VertexAttribute[] { return this.attributes; }\n\n\tmaxVertices (): number { return this.vertices.length / this.elementsPerVertex; }\n\tnumVertices (): number { return this.verticesLength / this.elementsPerVertex; }\n\tsetVerticesLength (length: number) {\n\t\tthis.dirtyVertices = true;\n\t\tthis.verticesLength = length;\n\t}\n\tgetVertices (): Float32Array { return this.vertices; }\n\n\tmaxIndices (): number { return this.indices.length; }\n\tnumIndices (): number { return this.indicesLength; }\n\tsetIndicesLength (length: number) {\n\t\tthis.dirtyIndices = true;\n\t\tthis.indicesLength = length;\n\t}\n\tgetIndices (): Uint16Array { return this.indices };\n\n\tgetVertexSizeInFloats (): number {\n\t\tlet size = 0;\n\t\tfor (var i = 0; i < this.attributes.length; i++) {\n\t\t\tlet attribute = this.attributes[i];\n\t\t\tsize += attribute.numElements;\n\t\t}\n\t\treturn size;\n\t}\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, private attributes: VertexAttribute[], maxVertices: number, maxIndices: number) {\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.elementsPerVertex = 0;\n\t\tfor (let i = 0; i < attributes.length; i++) {\n\t\t\tthis.elementsPerVertex += attributes[i].numElements;\n\t\t}\n\t\tthis.vertices = new Float32Array(maxVertices * this.elementsPerVertex);\n\t\tthis.indices = new Uint16Array(maxIndices);\n\t\tthis.context.addRestorable(this);\n\t}\n\n\tsetVertices (vertices: Array) {\n\t\tthis.dirtyVertices = true;\n\t\tif (vertices.length > this.vertices.length) throw Error(\"Mesh can't store more than \" + this.maxVertices() + \" vertices\");\n\t\tthis.vertices.set(vertices, 0);\n\t\tthis.verticesLength = vertices.length;\n\t}\n\n\tsetIndices (indices: Array) {\n\t\tthis.dirtyIndices = true;\n\t\tif (indices.length > this.indices.length) throw Error(\"Mesh can't store more than \" + this.maxIndices() + \" indices\");\n\t\tthis.indices.set(indices, 0);\n\t\tthis.indicesLength = indices.length;\n\t}\n\n\tdraw (shader: Shader, primitiveType: number) {\n\t\tthis.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex);\n\t}\n\n\tdrawWithOffset (shader: Shader, primitiveType: number, offset: number, count: number) {\n\t\tlet gl = this.context.gl;\n\t\tif (this.dirtyVertices || this.dirtyIndices) this.update();\n\t\tthis.bind(shader);\n\t\tif (this.indicesLength > 0) {\n\t\t\tgl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2);\n\t\t} else {\n\t\t\tgl.drawArrays(primitiveType, offset, count);\n\t\t}\n\t\tthis.unbind(shader);\n\t}\n\n\tbind (shader: Shader) {\n\t\tlet gl = this.context.gl;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);\n\t\tlet offset = 0;\n\t\tfor (let i = 0; i < this.attributes.length; i++) {\n\t\t\tlet attrib = this.attributes[i];\n\t\t\tlet location = shader.getAttributeLocation(attrib.name);\n\t\t\tgl.enableVertexAttribArray(location);\n\t\t\tgl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4);\n\t\t\toffset += attrib.numElements;\n\t\t}\n\t\tif (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);\n\t}\n\n\tunbind (shader: Shader) {\n\t\tlet gl = this.context.gl;\n\t\tfor (let i = 0; i < this.attributes.length; i++) {\n\t\t\tlet attrib = this.attributes[i];\n\t\t\tlet location = shader.getAttributeLocation(attrib.name);\n\t\t\tgl.disableVertexAttribArray(location);\n\t\t}\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\tif (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\t}\n\n\tprivate update () {\n\t\tlet gl = this.context.gl;\n\t\tif (this.dirtyVertices) {\n\t\t\tif (!this.verticesBuffer) {\n\t\t\t\tthis.verticesBuffer = gl.createBuffer();\n\t\t\t}\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);\n\t\t\tgl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);\n\t\t\tthis.dirtyVertices = false;\n\t\t}\n\n\t\tif (this.dirtyIndices) {\n\t\t\tif (!this.indicesBuffer) {\n\t\t\t\tthis.indicesBuffer = gl.createBuffer();\n\t\t\t}\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);\n\t\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);\n\t\t\tthis.dirtyIndices = false;\n\t\t}\n\t}\n\n\trestore () {\n\t\tthis.verticesBuffer = null;\n\t\tthis.indicesBuffer = null;\n\t\tthis.update();\n\t}\n\n\tdispose () {\n\t\tthis.context.removeRestorable(this);\n\t\tlet gl = this.context.gl;\n\t\tgl.deleteBuffer(this.verticesBuffer);\n\t\tgl.deleteBuffer(this.indicesBuffer);\n\t}\n}\n\nexport class VertexAttribute {\n\tconstructor (public name: string, public type: VertexAttributeType, public numElements: number) { }\n}\n\nexport class Position2Attribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.POSITION, VertexAttributeType.Float, 2);\n\t}\n}\n\nexport class Position3Attribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.POSITION, VertexAttributeType.Float, 3);\n\t}\n}\n\nexport class TexCoordAttribute extends VertexAttribute {\n\tconstructor (unit: number = 0) {\n\t\tsuper(Shader.TEXCOORDS + (unit == 0 ? \"\" : unit), VertexAttributeType.Float, 2);\n\t}\n}\n\nexport class ColorAttribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.COLOR, VertexAttributeType.Float, 4);\n\t}\n}\n\nexport class Color2Attribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.COLOR2, VertexAttributeType.Float, 4);\n\t}\n}\n\nexport enum VertexAttributeType {\n\tFloat\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BlendMode, Disposable } from \"@esotericsoftware/spine-core\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { Mesh, Position2Attribute, ColorAttribute, TexCoordAttribute, Color2Attribute } from \"./Mesh.js\";\nimport { Shader } from \"./Shader.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nconst GL_ONE = 1;\nconst GL_ONE_MINUS_SRC_COLOR = 0x0301;\nconst GL_SRC_ALPHA = 0x0302;\nconst GL_ONE_MINUS_SRC_ALPHA = 0x0303;\nconst GL_ONE_MINUS_DST_ALPHA = 0x0305;\nconst GL_DST_COLOR = 0x0306;\n\nexport class PolygonBatcher implements Disposable {\n\tpublic static disableCulling = false;\n\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate drawCalls = 0;\n\tprivate static globalDrawCalls = 0;\n\tisDrawing = false;\n\tprivate mesh: Mesh;\n\tprivate shader: Shader | null = null;\n\tprivate lastTexture: GLTexture | null = null;\n\tprivate verticesLength = 0;\n\tprivate indicesLength = 0;\n\tprivate srcColorBlend: number;\n\tprivate srcAlphaBlend: number;\n\tprivate dstBlend: number;\n\tprivate cullWasEnabled = false;\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true, maxVertices: number = 10920) {\n\t\tif (maxVertices > 10920) throw new Error(\"Can't have more than 10920 triangles per batch: \" + maxVertices);\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tlet attributes = twoColorTint ?\n\t\t\t[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] :\n\t\t\t[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()];\n\t\tthis.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3);\n\t\tlet gl = this.context.gl;\n\t\tthis.srcColorBlend = gl.SRC_ALPHA;\n\t\tthis.srcAlphaBlend = gl.ONE;\n\t\tthis.dstBlend = gl.ONE_MINUS_SRC_ALPHA;\n\t}\n\n\tbegin (shader: Shader) {\n\t\tif (this.isDrawing) throw new Error(\"PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()\");\n\t\tthis.drawCalls = 0;\n\t\tthis.shader = shader;\n\t\tthis.lastTexture = null;\n\t\tthis.isDrawing = true;\n\n\t\tlet gl = this.context.gl;\n\t\tgl.enable(gl.BLEND);\n\t\tgl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);\n\n\t\tif (PolygonBatcher.disableCulling) {\n\t\t\tthis.cullWasEnabled = gl.isEnabled(gl.CULL_FACE);\n\t\t\tif (this.cullWasEnabled) gl.disable(gl.CULL_FACE);\n\t\t}\n\t}\n\n\tprivate static blendModesGL: { srcRgb: number, srcRgbPma: number, dstRgb: number, srcAlpha: number }[] = [\n\t\t{ srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },\n\t\t{ srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE },\n\t\t{ srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },\n\t\t{ srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE }\n\t]\n\n\tsetBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean) {\n\t\tconst blendModeGL = PolygonBatcher.blendModesGL[blendMode];\n\t\tconst srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb;\n\t\tconst srcAlphaBlend = blendModeGL.srcAlpha;\n\t\tconst dstBlend = blendModeGL.dstRgb;\n\n\t\tif (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) return;\n\t\tthis.srcColorBlend = srcColorBlend;\n\t\tthis.srcAlphaBlend = srcAlphaBlend;\n\t\tthis.dstBlend = dstBlend;\n\t\tif (this.isDrawing) {\n\t\t\tthis.flush();\n\t\t}\n\t\tlet gl = this.context.gl;\n\t\tgl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);\n\t}\n\n\tdraw (texture: GLTexture, vertices: ArrayLike, indices: Array) {\n\t\tif (texture != this.lastTexture) {\n\t\t\tthis.flush();\n\t\t\tthis.lastTexture = texture;\n\t\t} else if (this.verticesLength + vertices.length > this.mesh.getVertices().length ||\n\t\t\tthis.indicesLength + indices.length > this.mesh.getIndices().length) {\n\t\t\tthis.flush();\n\t\t}\n\n\t\tlet indexStart = this.mesh.numVertices();\n\t\tthis.mesh.getVertices().set(vertices, this.verticesLength);\n\t\tthis.verticesLength += vertices.length;\n\t\tthis.mesh.setVerticesLength(this.verticesLength)\n\n\t\tlet indicesArray = this.mesh.getIndices();\n\t\tfor (let i = this.indicesLength, j = 0; j < indices.length; i++, j++)\n\t\t\tindicesArray[i] = indices[j] + indexStart;\n\t\tthis.indicesLength += indices.length;\n\t\tthis.mesh.setIndicesLength(this.indicesLength);\n\t}\n\n\tflush () {\n\t\tif (this.verticesLength == 0) return;\n\t\tif (!this.lastTexture) throw new Error(\"No texture set.\");\n\t\tif (!this.shader) throw new Error(\"No shader set.\");\n\t\tthis.lastTexture.bind();\n\t\tthis.mesh.draw(this.shader, this.context.gl.TRIANGLES);\n\n\t\tthis.verticesLength = 0;\n\t\tthis.indicesLength = 0;\n\t\tthis.mesh.setVerticesLength(0);\n\t\tthis.mesh.setIndicesLength(0);\n\t\tthis.drawCalls++;\n\t\tPolygonBatcher.globalDrawCalls++;\n\t}\n\n\tend () {\n\t\tif (!this.isDrawing) throw new Error(\"PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()\");\n\t\tif (this.verticesLength > 0 || this.indicesLength > 0) this.flush();\n\t\tthis.shader = null;\n\t\tthis.lastTexture = null;\n\t\tthis.isDrawing = false;\n\n\t\tlet gl = this.context.gl;\n\t\tgl.disable(gl.BLEND);\n\t\tif (PolygonBatcher.disableCulling) {\n\t\t\tif (this.cullWasEnabled) gl.enable(gl.CULL_FACE);\n\t\t}\n\t}\n\n\tgetDrawCalls () {\n\t\treturn this.drawCalls;\n\t}\n\n\tstatic getAndResetGlobalDrawCalls () {\n\t\tlet result = PolygonBatcher.globalDrawCalls;\n\t\tPolygonBatcher.globalDrawCalls = 0;\n\t\treturn result;\n\t}\n\n\tdispose () {\n\t\tthis.mesh.dispose();\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Color, Vector2, MathUtils } from \"@esotericsoftware/spine-core\";\nimport { Mesh, Position2Attribute, ColorAttribute } from \"./Mesh.js\";\nimport { Shader } from \"./Shader.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class ShapeRenderer implements Disposable {\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate isDrawing = false;\n\tprivate mesh: Mesh;\n\tprivate shapeType = ShapeType.Filled;\n\tprivate color = new Color(1, 1, 1, 1);\n\tprivate shader: Shader | null = null;\n\tprivate vertexIndex = 0;\n\tprivate tmp = new Vector2();\n\tprivate srcColorBlend: number;\n\tprivate srcAlphaBlend: number;\n\tprivate dstBlend: number;\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, maxVertices: number = 10920) {\n\t\tif (maxVertices > 10920) throw new Error(\"Can't have more than 10920 triangles per batch: \" + maxVertices);\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0);\n\t\tlet gl = this.context.gl;\n\t\tthis.srcColorBlend = gl.SRC_ALPHA;\n\t\tthis.srcAlphaBlend = gl.ONE;\n\t\tthis.dstBlend = gl.ONE_MINUS_SRC_ALPHA;\n\t}\n\n\tbegin (shader: Shader) {\n\t\tif (this.isDrawing) throw new Error(\"ShapeRenderer.begin() has already been called\");\n\t\tthis.shader = shader;\n\t\tthis.vertexIndex = 0;\n\t\tthis.isDrawing = true;\n\n\t\tlet gl = this.context.gl;\n\t\tgl.enable(gl.BLEND);\n\t\tgl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);\n\t}\n\n\tsetBlendMode (srcColorBlend: number, srcAlphaBlend: number, dstBlend: number) {\n\t\tthis.srcColorBlend = srcColorBlend;\n\t\tthis.srcAlphaBlend = srcAlphaBlend;\n\t\tthis.dstBlend = dstBlend;\n\t\tif (this.isDrawing) {\n\t\t\tthis.flush();\n\t\t\tlet gl = this.context.gl;\n\t\t\tgl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);\n\t\t}\n\t}\n\n\tsetColor (color: Color) {\n\t\tthis.color.setFromColor(color);\n\t}\n\n\tsetColorWith (r: number, g: number, b: number, a: number) {\n\t\tthis.color.set(r, g, b, a);\n\t}\n\n\tpoint (x: number, y: number, color?: Color) {\n\t\tthis.check(ShapeType.Point, 1);\n\t\tif (!color) color = this.color;\n\t\tthis.vertex(x, y, color);\n\t}\n\n\tline (x: number, y: number, x2: number, y2: number, color?: Color) {\n\t\tthis.check(ShapeType.Line, 2);\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\t\tif (!color) color = this.color;\n\t\tthis.vertex(x, y, color);\n\t\tthis.vertex(x2, y2, color);\n\t}\n\n\ttriangle (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, color?: Color, color2?: Color, color3?: Color) {\n\t\tthis.check(filled ? ShapeType.Filled : ShapeType.Line, 3);\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\t\tif (!color) color = this.color;\n\t\tif (!color2) color2 = this.color;\n\t\tif (!color3) color3 = this.color;\n\t\tif (filled) {\n\t\t\tthis.vertex(x, y, color);\n\t\t\tthis.vertex(x2, y2, color2);\n\t\t\tthis.vertex(x3, y3, color3);\n\t\t} else {\n\t\t\tthis.vertex(x, y, color);\n\t\t\tthis.vertex(x2, y2, color2);\n\n\t\t\tthis.vertex(x2, y2, color);\n\t\t\tthis.vertex(x3, y3, color2);\n\n\t\t\tthis.vertex(x3, y3, color);\n\t\t\tthis.vertex(x, y, color2);\n\t\t}\n\t}\n\n\tquad (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, color?: Color, color2?: Color, color3?: Color, color4?: Color) {\n\t\tthis.check(filled ? ShapeType.Filled : ShapeType.Line, 3);\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\t\tif (!color) color = this.color;\n\t\tif (!color2) color2 = this.color;\n\t\tif (!color3) color3 = this.color;\n\t\tif (!color4) color4 = this.color;\n\t\tif (filled) {\n\t\t\tthis.vertex(x, y, color); this.vertex(x2, y2, color2); this.vertex(x3, y3, color3);\n\t\t\tthis.vertex(x3, y3, color3); this.vertex(x4, y4, color4); this.vertex(x, y, color);\n\t\t} else {\n\t\t\tthis.vertex(x, y, color); this.vertex(x2, y2, color2);\n\t\t\tthis.vertex(x2, y2, color2); this.vertex(x3, y3, color3);\n\t\t\tthis.vertex(x3, y3, color3); this.vertex(x4, y4, color4);\n\t\t\tthis.vertex(x4, y4, color4); this.vertex(x, y, color);\n\t\t}\n\t}\n\n\trect (filled: boolean, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color);\n\t}\n\n\trectLine (filled: boolean, x1: number, y1: number, x2: number, y2: number, width: number, color?: Color) {\n\t\tthis.check(filled ? ShapeType.Filled : ShapeType.Line, 8);\n\t\tif (!color) color = this.color;\n\t\tlet t = this.tmp.set(y2 - y1, x1 - x2);\n\t\tt.normalize();\n\t\twidth *= 0.5;\n\t\tlet tx = t.x * width;\n\t\tlet ty = t.y * width;\n\t\tif (!filled) {\n\t\t\tthis.vertex(x1 + tx, y1 + ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\t\t\tthis.vertex(x2 - tx, y2 - ty, color);\n\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\t\t\tthis.vertex(x1 + tx, y1 + ty, color);\n\n\t\t\tthis.vertex(x2 - tx, y2 - ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t} else {\n\t\t\tthis.vertex(x1 + tx, y1 + ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\n\t\t\tthis.vertex(x2 - tx, y2 - ty, color);\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t}\n\t}\n\n\tx (x: number, y: number, size: number) {\n\t\tthis.line(x - size, y - size, x + size, y + size);\n\t\tthis.line(x - size, y + size, x + size, y - size);\n\t}\n\n\tpolygon (polygonVertices: ArrayLike, offset: number, count: number, color?: Color) {\n\t\tif (count < 3) throw new Error(\"Polygon must contain at least 3 vertices\");\n\t\tthis.check(ShapeType.Line, count * 2);\n\t\tif (!color) color = this.color;\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\n\t\toffset <<= 1;\n\t\tcount <<= 1;\n\n\t\tlet firstX = polygonVertices[offset];\n\t\tlet firstY = polygonVertices[offset + 1];\n\t\tlet last = offset + count;\n\n\t\tfor (let i = offset, n = offset + count - 2; i < n; i += 2) {\n\t\t\tlet x1 = polygonVertices[i];\n\t\t\tlet y1 = polygonVertices[i + 1];\n\n\t\t\tlet x2 = 0;\n\t\t\tlet y2 = 0;\n\n\t\t\tif (i + 2 >= last) {\n\t\t\t\tx2 = firstX;\n\t\t\t\ty2 = firstY;\n\t\t\t} else {\n\t\t\t\tx2 = polygonVertices[i + 2];\n\t\t\t\ty2 = polygonVertices[i + 3];\n\t\t\t}\n\n\t\t\tthis.vertex(x1, y1, color!);\n\t\t\tthis.vertex(x2, y2, color!);\n\t\t}\n\t}\n\n\tcircle (filled: boolean, x: number, y: number, radius: number, color?: Color, segments: number = 0) {\n\t\tif (segments == 0) segments = Math.max(1, (6 * MathUtils.cbrt(radius)) | 0);\n\t\tif (segments <= 0) throw new Error(\"segments must be > 0.\");\n\t\tif (!color) color = this.color;\n\t\tlet angle = 2 * MathUtils.PI / segments;\n\t\tlet cos = Math.cos(angle);\n\t\tlet sin = Math.sin(angle);\n\t\tlet cx = radius, cy = 0;\n\t\tif (!filled) {\n\t\t\tthis.check(ShapeType.Line, segments * 2 + 2);\n\t\t\tfor (let i = 0; i < segments; i++) {\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t\tlet temp = cx;\n\t\t\t\tcx = cos * cx - sin * cy;\n\t\t\t\tcy = sin * temp + cos * cy;\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t}\n\t\t\t// Ensure the last segment is identical to the first.\n\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t} else {\n\t\t\tthis.check(ShapeType.Filled, segments * 3 + 3);\n\t\t\tsegments--;\n\t\t\tfor (let i = 0; i < segments; i++) {\n\t\t\t\tthis.vertex(x, y, color);\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t\tlet temp = cx;\n\t\t\t\tcx = cos * cx - sin * cy;\n\t\t\t\tcy = sin * temp + cos * cy;\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t}\n\t\t\t// Ensure the last segment is identical to the first.\n\t\t\tthis.vertex(x, y, color);\n\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t}\n\n\t\tlet temp = cx;\n\t\tcx = radius;\n\t\tcy = 0;\n\t\tthis.vertex(x + cx, y + cy, color);\n\t}\n\n\tcurve (x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color) {\n\t\tthis.check(ShapeType.Line, segments * 2 + 2);\n\t\tif (!color) color = this.color;\n\n\t\t// Algorithm from: http://www.antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION\n\t\tlet subdiv_step = 1 / segments;\n\t\tlet subdiv_step2 = subdiv_step * subdiv_step;\n\t\tlet subdiv_step3 = subdiv_step * subdiv_step * subdiv_step;\n\n\t\tlet pre1 = 3 * subdiv_step;\n\t\tlet pre2 = 3 * subdiv_step2;\n\t\tlet pre4 = 6 * subdiv_step2;\n\t\tlet pre5 = 6 * subdiv_step3;\n\n\t\tlet tmp1x = x1 - cx1 * 2 + cx2;\n\t\tlet tmp1y = y1 - cy1 * 2 + cy2;\n\n\t\tlet tmp2x = (cx1 - cx2) * 3 - x1 + x2;\n\t\tlet tmp2y = (cy1 - cy2) * 3 - y1 + y2;\n\n\t\tlet fx = x1;\n\t\tlet fy = y1;\n\n\t\tlet dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;\n\t\tlet dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;\n\n\t\tlet ddfx = tmp1x * pre4 + tmp2x * pre5;\n\t\tlet ddfy = tmp1y * pre4 + tmp2y * pre5;\n\n\t\tlet dddfx = tmp2x * pre5;\n\t\tlet dddfy = tmp2y * pre5;\n\n\t\twhile (segments-- > 0) {\n\t\t\tthis.vertex(fx, fy, color!);\n\t\t\tfx += dfx;\n\t\t\tfy += dfy;\n\t\t\tdfx += ddfx;\n\t\t\tdfy += ddfy;\n\t\t\tddfx += dddfx;\n\t\t\tddfy += dddfy;\n\t\t\tthis.vertex(fx, fy, color!);\n\t\t}\n\t\tthis.vertex(fx, fy, color!);\n\t\tthis.vertex(x2, y2, color!);\n\t}\n\n\tprivate vertex (x: number, y: number, color: Color) {\n\t\tlet idx = this.vertexIndex;\n\t\tlet vertices = this.mesh.getVertices();\n\t\tvertices[idx++] = x;\n\t\tvertices[idx++] = y;\n\t\tvertices[idx++] = color.r;\n\t\tvertices[idx++] = color.g;\n\t\tvertices[idx++] = color.b;\n\t\tvertices[idx++] = color.a;\n\t\tthis.vertexIndex = idx;\n\t}\n\n\tend () {\n\t\tif (!this.isDrawing) throw new Error(\"ShapeRenderer.begin() has not been called\");\n\t\tthis.flush();\n\t\tlet gl = this.context.gl;\n\t\tgl.disable(gl.BLEND);\n\t\tthis.isDrawing = false;\n\t}\n\n\tprivate flush () {\n\t\tif (this.vertexIndex == 0) return;\n\t\tif (!this.shader) throw new Error(\"No shader set.\");\n\t\tthis.mesh.setVerticesLength(this.vertexIndex);\n\t\tthis.mesh.draw(this.shader, this.shapeType);\n\t\tthis.vertexIndex = 0;\n\t}\n\n\tprivate check (shapeType: ShapeType, numVertices: number) {\n\t\tif (!this.isDrawing) throw new Error(\"ShapeRenderer.begin() has not been called\");\n\t\tif (this.shapeType == shapeType) {\n\t\t\tif (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) this.flush();\n\t\t\telse return;\n\t\t} else {\n\t\t\tthis.flush();\n\t\t\tthis.shapeType = shapeType;\n\t\t}\n\t}\n\n\tdispose () {\n\t\tthis.mesh.dispose();\n\t}\n}\n\nexport enum ShapeType {\n\tPoint = 0x0000,\n\tLine = 0x0001,\n\tFilled = 0x0004\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Color, SkeletonBounds, Utils, Skeleton, RegionAttachment, MeshAttachment, PathAttachment, ClippingAttachment } from \"@esotericsoftware/spine-core\";\nimport { ShapeRenderer } from \"./ShapeRenderer.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class SkeletonDebugRenderer implements Disposable {\n\tboneLineColor = new Color(1, 0, 0, 1);\n\tboneOriginColor = new Color(0, 1, 0, 1);\n\tattachmentLineColor = new Color(0, 0, 1, 0.5);\n\ttriangleLineColor = new Color(1, 0.64, 0, 0.5);\n\tpathColor = new Color().setFromString(\"FF7F00\");\n\tclipColor = new Color(0.8, 0, 0, 2);\n\taabbColor = new Color(0, 1, 0, 0.5);\n\tdrawBones = true;\n\tdrawRegionAttachments = true;\n\tdrawBoundingBoxes = true;\n\tdrawMeshHull = true;\n\tdrawMeshTriangles = true;\n\tdrawPaths = true;\n\tdrawSkeletonXY = false;\n\tdrawClipping = true;\n\tpremultipliedAlpha = false;\n\tscale = 1;\n\tboneWidth = 2;\n\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate bounds = new SkeletonBounds();\n\tprivate temp = new Array();\n\tprivate vertices = Utils.newFloatArray(2 * 1024);\n\tprivate static LIGHT_GRAY = new Color(192 / 255, 192 / 255, 192 / 255, 1);\n\tprivate static GREEN = new Color(0, 1, 0, 1);\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext) {\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t}\n\n\tdraw (shapes: ShapeRenderer, skeleton: Skeleton, ignoredBones?: Array) {\n\t\tlet skeletonX = skeleton.x;\n\t\tlet skeletonY = skeleton.y;\n\t\tlet gl = this.context.gl;\n\t\tlet srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA;\n\t\tshapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n\t\tlet bones = skeleton.bones;\n\t\tif (this.drawBones) {\n\t\t\tshapes.setColor(this.boneLineColor);\n\t\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\t\tlet bone = bones[i];\n\t\t\t\tif (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) continue;\n\t\t\t\tif (!bone.parent) continue;\n\t\t\t\tlet x = bone.data.length * bone.a + bone.worldX;\n\t\t\t\tlet y = bone.data.length * bone.c + bone.worldY;\n\t\t\t\tshapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale);\n\t\t\t}\n\t\t\tif (this.drawSkeletonXY) shapes.x(skeletonX, skeletonY, 4 * this.scale);\n\t\t}\n\n\t\tif (this.drawRegionAttachments) {\n\t\t\tshapes.setColor(this.attachmentLineColor);\n\t\t\tlet slots = skeleton.slots;\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\t\tlet regionAttachment = attachment;\n\t\t\t\t\tlet vertices = this.vertices;\n\t\t\t\t\tregionAttachment.computeWorldVertices(slot, vertices, 0, 2);\n\t\t\t\t\tshapes.line(vertices[0], vertices[1], vertices[2], vertices[3]);\n\t\t\t\t\tshapes.line(vertices[2], vertices[3], vertices[4], vertices[5]);\n\t\t\t\t\tshapes.line(vertices[4], vertices[5], vertices[6], vertices[7]);\n\t\t\t\t\tshapes.line(vertices[6], vertices[7], vertices[0], vertices[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawMeshHull || this.drawMeshTriangles) {\n\t\t\tlet slots = skeleton.slots;\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tif (!slot.bone.active) continue;\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (!(attachment instanceof MeshAttachment)) continue;\n\t\t\t\tlet mesh = attachment;\n\t\t\t\tlet vertices = this.vertices;\n\t\t\t\tmesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2);\n\t\t\t\tlet triangles = mesh.triangles;\n\t\t\t\tlet hullLength = mesh.hullLength;\n\t\t\t\tif (this.drawMeshTriangles) {\n\t\t\t\t\tshapes.setColor(this.triangleLineColor);\n\t\t\t\t\tfor (let ii = 0, nn = triangles.length; ii < nn; ii += 3) {\n\t\t\t\t\t\tlet v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2;\n\t\t\t\t\t\tshapes.triangle(false, vertices[v1], vertices[v1 + 1], //\n\t\t\t\t\t\t\tvertices[v2], vertices[v2 + 1], //\n\t\t\t\t\t\t\tvertices[v3], vertices[v3 + 1] //\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.drawMeshHull && hullLength > 0) {\n\t\t\t\t\tshapes.setColor(this.attachmentLineColor);\n\t\t\t\t\thullLength = (hullLength >> 1) * 2;\n\t\t\t\t\tlet lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1];\n\t\t\t\t\tfor (let ii = 0, nn = hullLength; ii < nn; ii += 2) {\n\t\t\t\t\t\tlet x = vertices[ii], y = vertices[ii + 1];\n\t\t\t\t\t\tshapes.line(x, y, lastX, lastY);\n\t\t\t\t\t\tlastX = x;\n\t\t\t\t\t\tlastY = y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawBoundingBoxes) {\n\t\t\tlet bounds = this.bounds;\n\t\t\tbounds.update(skeleton, true);\n\t\t\tshapes.setColor(this.aabbColor);\n\t\t\tshapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight());\n\t\t\tlet polygons = bounds.polygons;\n\t\t\tlet boxes = bounds.boundingBoxes;\n\t\t\tfor (let i = 0, n = polygons.length; i < n; i++) {\n\t\t\t\tlet polygon = polygons[i];\n\t\t\t\tshapes.setColor(boxes[i].color);\n\t\t\t\tshapes.polygon(polygon, 0, polygon.length);\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawPaths) {\n\t\t\tlet slots = skeleton.slots;\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tif (!slot.bone.active) continue;\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (!(attachment instanceof PathAttachment)) continue;\n\t\t\t\tlet path = attachment;\n\t\t\t\tlet nn = path.worldVerticesLength;\n\t\t\t\tlet world = this.temp = Utils.setArraySize(this.temp, nn, 0);\n\t\t\t\tpath.computeWorldVertices(slot, 0, nn, world, 0, 2);\n\t\t\t\tlet color = this.pathColor;\n\t\t\t\tlet x1 = world[2], y1 = world[3], x2 = 0, y2 = 0;\n\t\t\t\tif (path.closed) {\n\t\t\t\t\tshapes.setColor(color);\n\t\t\t\t\tlet cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1];\n\t\t\t\t\tx2 = world[nn - 4];\n\t\t\t\t\ty2 = world[nn - 3];\n\t\t\t\t\tshapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);\n\t\t\t\t\tshapes.setColor(SkeletonDebugRenderer.LIGHT_GRAY);\n\t\t\t\t\tshapes.line(x1, y1, cx1, cy1);\n\t\t\t\t\tshapes.line(x2, y2, cx2, cy2);\n\t\t\t\t}\n\t\t\t\tnn -= 4;\n\t\t\t\tfor (let ii = 4; ii < nn; ii += 6) {\n\t\t\t\t\tlet cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3];\n\t\t\t\t\tx2 = world[ii + 4];\n\t\t\t\t\ty2 = world[ii + 5];\n\t\t\t\t\tshapes.setColor(color);\n\t\t\t\t\tshapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);\n\t\t\t\t\tshapes.setColor(SkeletonDebugRenderer.LIGHT_GRAY);\n\t\t\t\t\tshapes.line(x1, y1, cx1, cy1);\n\t\t\t\t\tshapes.line(x2, y2, cx2, cy2);\n\t\t\t\t\tx1 = x2;\n\t\t\t\t\ty1 = y2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawBones) {\n\t\t\tshapes.setColor(this.boneOriginColor);\n\t\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\t\tlet bone = bones[i];\n\t\t\t\tif (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) continue;\n\t\t\t\tshapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8);\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawClipping) {\n\t\t\tlet slots = skeleton.slots;\n\t\t\tshapes.setColor(this.clipColor)\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tif (!slot.bone.active) continue;\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (!(attachment instanceof ClippingAttachment)) continue;\n\t\t\t\tlet clip = attachment;\n\t\t\t\tlet nn = clip.worldVerticesLength;\n\t\t\t\tlet world = this.temp = Utils.setArraySize(this.temp, nn, 0);\n\t\t\t\tclip.computeWorldVertices(slot, 0, nn, world, 0, 2);\n\t\t\t\tfor (let i = 0, n = world.length; i < n; i += 2) {\n\t\t\t\t\tlet x = world[i];\n\t\t\t\t\tlet y = world[i + 1];\n\t\t\t\t\tlet x2 = world[(i + 2) % world.length];\n\t\t\t\t\tlet y2 = world[(i + 3) % world.length];\n\t\t\t\t\tshapes.line(x, y, x2, y2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdispose () {\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { NumberArrayLike, Color, SkeletonClipping, Vector2, Utils, Skeleton, BlendMode, RegionAttachment, TextureAtlasRegion, MeshAttachment, ClippingAttachment } from \"@esotericsoftware/spine-core\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { PolygonBatcher } from \"./PolygonBatcher.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\n\nclass Renderable {\n\tconstructor (public vertices: NumberArrayLike, public numVertices: number, public numFloats: number) { }\n};\n\nexport type VertexTransformer = (vertices: NumberArrayLike, numVertices: number, stride: number) => void;\n\nexport class SkeletonRenderer {\n\tstatic QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];\n\n\tpremultipliedAlpha = false;\n\tprivate tempColor = new Color();\n\tprivate tempColor2 = new Color();\n\tprivate vertices: NumberArrayLike;\n\tprivate vertexSize = 2 + 2 + 4;\n\tprivate twoColorTint = false;\n\tprivate renderable: Renderable = new Renderable([], 0, 0);\n\tprivate clipper: SkeletonClipping = new SkeletonClipping();\n\tprivate temp = new Vector2();\n\tprivate temp2 = new Vector2();\n\tprivate temp3 = new Color();\n\tprivate temp4 = new Color();\n\n\tconstructor (context: ManagedWebGLRenderingContext, twoColorTint: boolean = true) {\n\t\tthis.twoColorTint = twoColorTint;\n\t\tif (twoColorTint)\n\t\t\tthis.vertexSize += 4;\n\t\tthis.vertices = Utils.newFloatArray(this.vertexSize * 1024);\n\t}\n\n\tdraw (batcher: PolygonBatcher, skeleton: Skeleton, slotRangeStart: number = -1, slotRangeEnd: number = -1, transformer: VertexTransformer | null = null) {\n\t\tlet clipper = this.clipper;\n\t\tlet premultipliedAlpha = this.premultipliedAlpha;\n\t\tlet twoColorTint = this.twoColorTint;\n\t\tlet blendMode: BlendMode | null = null;\n\n\t\tlet renderable: Renderable = this.renderable;\n\t\tlet uvs: NumberArrayLike;\n\t\tlet triangles: Array;\n\t\tlet drawOrder = skeleton.drawOrder;\n\t\tlet attachmentColor: Color;\n\t\tlet skeletonColor = skeleton.color;\n\t\tlet vertexSize = twoColorTint ? 12 : 8;\n\t\tlet inRange = false;\n\t\tif (slotRangeStart == -1) inRange = true;\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;\n\t\t\tlet slot = drawOrder[i];\n\t\t\tif (!slot.bone.active) {\n\t\t\t\tclipper.clipEndWithSlot(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (slotRangeStart >= 0 && slotRangeStart == slot.data.index) {\n\t\t\t\tinRange = true;\n\t\t\t}\n\n\t\t\tif (!inRange) {\n\t\t\t\tclipper.clipEndWithSlot(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) {\n\t\t\t\tinRange = false;\n\t\t\t}\n\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tlet texture: GLTexture;\n\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\tlet region = attachment;\n\t\t\t\trenderable.vertices = this.vertices;\n\t\t\t\trenderable.numVertices = 4;\n\t\t\t\trenderable.numFloats = clippedVertexSize << 2;\n\t\t\t\tregion.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize);\n\t\t\t\ttriangles = SkeletonRenderer.QUAD_TRIANGLES;\n\t\t\t\tuvs = region.uvs;\n\t\t\t\ttexture = region.region!.texture;\n\t\t\t\tattachmentColor = region.color;\n\t\t\t} else if (attachment instanceof MeshAttachment) {\n\t\t\t\tlet mesh = attachment;\n\t\t\t\trenderable.vertices = this.vertices;\n\t\t\t\trenderable.numVertices = (mesh.worldVerticesLength >> 1);\n\t\t\t\trenderable.numFloats = renderable.numVertices * clippedVertexSize;\n\t\t\t\tif (renderable.numFloats > renderable.vertices.length) {\n\t\t\t\t\trenderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats);\n\t\t\t\t}\n\t\t\t\tmesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);\n\t\t\t\ttriangles = mesh.triangles;\n\t\t\t\ttexture = mesh.region!.texture;\n\t\t\t\tuvs = mesh.uvs;\n\t\t\t\tattachmentColor = mesh.color;\n\t\t\t} else if (attachment instanceof ClippingAttachment) {\n\t\t\t\tlet clip = (attachment);\n\t\t\t\tclipper.clipStart(slot, clip);\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tclipper.clipEndWithSlot(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (texture) {\n\t\t\t\tlet slotColor = slot.color;\n\t\t\t\tlet finalColor = this.tempColor;\n\t\t\t\tfinalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r;\n\t\t\t\tfinalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g;\n\t\t\t\tfinalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b;\n\t\t\t\tfinalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;\n\t\t\t\tif (premultipliedAlpha) {\n\t\t\t\t\tfinalColor.r *= finalColor.a;\n\t\t\t\t\tfinalColor.g *= finalColor.a;\n\t\t\t\t\tfinalColor.b *= finalColor.a;\n\t\t\t\t}\n\t\t\t\tlet darkColor = this.tempColor2;\n\t\t\t\tif (!slot.darkColor)\n\t\t\t\t\tdarkColor.set(0, 0, 0, 1.0);\n\t\t\t\telse {\n\t\t\t\t\tif (premultipliedAlpha) {\n\t\t\t\t\t\tdarkColor.r = slot.darkColor.r * finalColor.a;\n\t\t\t\t\t\tdarkColor.g = slot.darkColor.g * finalColor.a;\n\t\t\t\t\t\tdarkColor.b = slot.darkColor.b * finalColor.a;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdarkColor.setFromColor(slot.darkColor);\n\t\t\t\t\t}\n\t\t\t\t\tdarkColor.a = premultipliedAlpha ? 1.0 : 0.0;\n\t\t\t\t}\n\n\t\t\t\tlet slotBlendMode = slot.data.blendMode;\n\t\t\t\tif (slotBlendMode != blendMode) {\n\t\t\t\t\tblendMode = slotBlendMode;\n\t\t\t\t\tbatcher.setBlendMode(blendMode, premultipliedAlpha);\n\t\t\t\t}\n\n\t\t\t\tif (clipper.isClipping()) {\n\t\t\t\t\tclipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);\n\t\t\t\t\tlet clippedVertices = new Float32Array(clipper.clippedVertices);\n\t\t\t\t\tlet clippedTriangles = clipper.clippedTriangles;\n\t\t\t\t\tif (transformer) transformer(clippedVertices, clippedVertices.length, vertexSize);\n\t\t\t\t\tbatcher.draw(texture, clippedVertices, clippedTriangles);\n\t\t\t\t} else {\n\t\t\t\t\tlet verts = renderable.vertices;\n\t\t\t\t\tif (!twoColorTint) {\n\t\t\t\t\t\tfor (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) {\n\t\t\t\t\t\t\tverts[v] = finalColor.r;\n\t\t\t\t\t\t\tverts[v + 1] = finalColor.g;\n\t\t\t\t\t\t\tverts[v + 2] = finalColor.b;\n\t\t\t\t\t\t\tverts[v + 3] = finalColor.a;\n\t\t\t\t\t\t\tverts[v + 4] = uvs[u];\n\t\t\t\t\t\t\tverts[v + 5] = uvs[u + 1];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) {\n\t\t\t\t\t\t\tverts[v] = finalColor.r;\n\t\t\t\t\t\t\tverts[v + 1] = finalColor.g;\n\t\t\t\t\t\t\tverts[v + 2] = finalColor.b;\n\t\t\t\t\t\t\tverts[v + 3] = finalColor.a;\n\t\t\t\t\t\t\tverts[v + 4] = uvs[u];\n\t\t\t\t\t\t\tverts[v + 5] = uvs[u + 1];\n\t\t\t\t\t\t\tverts[v + 6] = darkColor.r;\n\t\t\t\t\t\t\tverts[v + 7] = darkColor.g;\n\t\t\t\t\t\t\tverts[v + 8] = darkColor.b;\n\t\t\t\t\t\t\tverts[v + 9] = darkColor.a;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlet view = (renderable.vertices as Float32Array).subarray(0, renderable.numFloats);\n\t\t\t\t\tif (transformer) transformer(renderable.vertices, renderable.numFloats, vertexSize);\n\t\t\t\t\tbatcher.draw(texture, view, triangles);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclipper.clipEndWithSlot(slot);\n\t\t}\n\t\tclipper.clipEnd();\n\t}\n\n\t/** Returns the {@link SkeletonClipping} used by this renderer for use with e.g. {@link Skeleton.getBounds} **/\n\tpublic getSkeletonClipping (): SkeletonClipping {\n\t\treturn this.clipper;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color, Disposable, Skeleton, MathUtils, TextureAtlasRegion } from \"@esotericsoftware/spine-core\";\nimport { OrthoCamera } from \"./Camera.js\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { PolygonBatcher } from \"./PolygonBatcher.js\";\nimport { Shader } from \"./Shader.js\";\nimport { ShapeRenderer } from \"./ShapeRenderer.js\";\nimport { SkeletonDebugRenderer } from \"./SkeletonDebugRenderer.js\";\nimport { SkeletonRenderer, VertexTransformer } from \"./SkeletonRenderer.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n;\n\nconst quad = [\n\t0, 0, 1, 1, 1, 1, 0, 0,\n\t0, 0, 1, 1, 1, 1, 0, 0,\n\t0, 0, 1, 1, 1, 1, 0, 0,\n\t0, 0, 1, 1, 1, 1, 0, 0,\n];\nconst QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];\nconst WHITE = new Color(1, 1, 1, 1);\n\nexport class SceneRenderer implements Disposable {\n\tcontext: ManagedWebGLRenderingContext;\n\tcanvas: HTMLCanvasElement;\n\tcamera: OrthoCamera;\n\tbatcher: PolygonBatcher;\n\tprivate twoColorTint = false;\n\tprivate batcherShader: Shader;\n\tprivate shapes: ShapeRenderer;\n\tprivate shapesShader: Shader;\n\tprivate activeRenderer: PolygonBatcher | ShapeRenderer | SkeletonDebugRenderer | null = null;\n\tskeletonRenderer: SkeletonRenderer;\n\tskeletonDebugRenderer: SkeletonDebugRenderer;\n\n\tconstructor (canvas: HTMLCanvasElement, context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true) {\n\t\tthis.canvas = canvas;\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.twoColorTint = twoColorTint;\n\t\tthis.camera = new OrthoCamera(canvas.width, canvas.height);\n\t\tthis.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context);\n\t\tthis.batcher = new PolygonBatcher(this.context, twoColorTint);\n\t\tthis.shapesShader = Shader.newColored(this.context);\n\t\tthis.shapes = new ShapeRenderer(this.context);\n\t\tthis.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint);\n\t\tthis.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context);\n\t}\n\n\tdispose () {\n\t\tthis.batcher.dispose();\n\t\tthis.batcherShader.dispose();\n\t\tthis.shapes.dispose();\n\t\tthis.shapesShader.dispose();\n\t\tthis.skeletonDebugRenderer.dispose();\n\t}\n\n\tbegin () {\n\t\tthis.camera.update();\n\t\tthis.enableRenderer(this.batcher);\n\t}\n\n\tdrawSkeleton (skeleton: Skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform: VertexTransformer | null = null) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tthis.skeletonRenderer.premultipliedAlpha = premultipliedAlpha;\n\t\tthis.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform);\n\t}\n\n\tdrawSkeletonDebug (skeleton: Skeleton, premultipliedAlpha = false, ignoredBones?: Array) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha;\n\t\tthis.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones);\n\t}\n\n\tdrawTexture (texture: GLTexture, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\t\tvar i = 0;\n\t\tquad[i++] = x;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tdrawTextureUV (texture: GLTexture, x: number, y: number, width: number, height: number, u: number, v: number, u2: number, v2: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\t\tvar i = 0;\n\t\tquad[i++] = x;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u;\n\t\tquad[i++] = v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u2;\n\t\tquad[i++] = v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u2;\n\t\tquad[i++] = v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u;\n\t\tquad[i++] = v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tdrawTextureRotated (texture: GLTexture, x: number, y: number, width: number, height: number, pivotX: number, pivotY: number, angle: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\n\t\t// bottom left and top right corner points relative to origin\n\t\tlet worldOriginX = x + pivotX;\n\t\tlet worldOriginY = y + pivotY;\n\t\tlet fx = -pivotX;\n\t\tlet fy = -pivotY;\n\t\tlet fx2 = width - pivotX;\n\t\tlet fy2 = height - pivotY;\n\n\t\t// construct corner points, start from top left and go counter clockwise\n\t\tlet p1x = fx;\n\t\tlet p1y = fy;\n\t\tlet p2x = fx;\n\t\tlet p2y = fy2;\n\t\tlet p3x = fx2;\n\t\tlet p3y = fy2;\n\t\tlet p4x = fx2;\n\t\tlet p4y = fy;\n\n\t\tlet x1 = 0;\n\t\tlet y1 = 0;\n\t\tlet x2 = 0;\n\t\tlet y2 = 0;\n\t\tlet x3 = 0;\n\t\tlet y3 = 0;\n\t\tlet x4 = 0;\n\t\tlet y4 = 0;\n\n\t\t// rotate\n\t\tif (angle != 0) {\n\t\t\tlet cos = MathUtils.cosDeg(angle);\n\t\t\tlet sin = MathUtils.sinDeg(angle);\n\n\t\t\tx1 = cos * p1x - sin * p1y;\n\t\t\ty1 = sin * p1x + cos * p1y;\n\n\t\t\tx4 = cos * p2x - sin * p2y;\n\t\t\ty4 = sin * p2x + cos * p2y;\n\n\t\t\tx3 = cos * p3x - sin * p3y;\n\t\t\ty3 = sin * p3x + cos * p3y;\n\n\t\t\tx2 = x3 + (x1 - x4);\n\t\t\ty2 = y3 + (y1 - y4);\n\t\t} else {\n\t\t\tx1 = p1x;\n\t\t\ty1 = p1y;\n\n\t\t\tx4 = p2x;\n\t\t\ty4 = p2y;\n\n\t\t\tx3 = p3x;\n\t\t\ty3 = p3y;\n\n\t\t\tx2 = p4x;\n\t\t\ty2 = p4y;\n\t\t}\n\n\t\tx1 += worldOriginX;\n\t\ty1 += worldOriginY;\n\t\tx2 += worldOriginX;\n\t\ty2 += worldOriginY;\n\t\tx3 += worldOriginX;\n\t\ty3 += worldOriginY;\n\t\tx4 += worldOriginX;\n\t\ty4 += worldOriginY;\n\n\t\tvar i = 0;\n\t\tquad[i++] = x1;\n\t\tquad[i++] = y1;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x2;\n\t\tquad[i++] = y2;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x3;\n\t\tquad[i++] = y3;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x4;\n\t\tquad[i++] = y4;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tdrawRegion (region: TextureAtlasRegion, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\t\tvar i = 0;\n\t\tquad[i++] = x;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u;\n\t\tquad[i++] = region.v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u2;\n\t\tquad[i++] = region.v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u2;\n\t\tquad[i++] = region.v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u;\n\t\tquad[i++] = region.v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tline (x: number, y: number, x2: number, y2: number, color?: Color, color2?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.line(x, y, x2, y2, color);\n\t}\n\n\ttriangle (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, color?: Color, color2?: Color, color3?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3);\n\t}\n\n\tquad (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, color?: Color, color2?: Color, color3?: Color, color4?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4);\n\t}\n\n\trect (filled: boolean, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.rect(filled, x, y, width, height, color);\n\t}\n\n\trectLine (filled: boolean, x1: number, y1: number, x2: number, y2: number, width: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.rectLine(filled, x1, y1, x2, y2, width, color);\n\t}\n\n\tpolygon (polygonVertices: ArrayLike, offset: number, count: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.polygon(polygonVertices, offset, count, color);\n\t}\n\n\tcircle (filled: boolean, x: number, y: number, radius: number, color?: Color, segments: number = 0) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.circle(filled, x, y, radius, color, segments);\n\t}\n\n\tcurve (x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color);\n\t}\n\n\tend () {\n\t\tif (this.activeRenderer === this.batcher) this.batcher.end();\n\t\telse if (this.activeRenderer === this.shapes) this.shapes.end();\n\t\tthis.activeRenderer = null;\n\t}\n\n\tresize (resizeMode: ResizeMode) {\n\t\tlet canvas = this.canvas;\n\t\tvar dpr = window.devicePixelRatio || 1;\n\t\tvar w = Math.round(canvas.clientWidth * dpr);\n\t\tvar h = Math.round(canvas.clientHeight * dpr);\n\n\t\tif (canvas.width != w || canvas.height != h) {\n\t\t\tcanvas.width = w;\n\t\t\tcanvas.height = h;\n\t\t}\n\t\tthis.context.gl.viewport(0, 0, canvas.width, canvas.height);\n\n\t\t// Nothing to do for stretch, we simply apply the viewport size of the camera.\n\t\tif (resizeMode === ResizeMode.Expand)\n\t\t\tthis.camera.setViewport(w, h);\n\t\telse if (resizeMode === ResizeMode.Fit) {\n\t\t\tlet sourceWidth = canvas.width, sourceHeight = canvas.height;\n\t\t\tlet targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight;\n\t\t\tlet targetRatio = targetHeight / targetWidth;\n\t\t\tlet sourceRatio = sourceHeight / sourceWidth;\n\t\t\tlet scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight;\n\t\t\tthis.camera.setViewport(sourceWidth * scale, sourceHeight * scale);\n\t\t}\n\t\tthis.camera.update();\n\t}\n\n\tprivate enableRenderer (renderer: PolygonBatcher | ShapeRenderer | SkeletonDebugRenderer) {\n\t\tif (this.activeRenderer === renderer) return;\n\t\tthis.end();\n\t\tif (renderer instanceof PolygonBatcher) {\n\t\t\tthis.batcherShader.bind();\n\t\t\tthis.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values);\n\t\t\tthis.batcherShader.setUniformi(\"u_texture\", 0);\n\t\t\tthis.batcher.begin(this.batcherShader);\n\t\t\tthis.activeRenderer = this.batcher;\n\t\t} else if (renderer instanceof ShapeRenderer) {\n\t\t\tthis.shapesShader.bind();\n\t\t\tthis.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values);\n\t\t\tthis.shapes.begin(this.shapesShader);\n\t\t\tthis.activeRenderer = this.shapes;\n\t\t} else\n\t\t\tthis.activeRenderer = this.skeletonDebugRenderer;\n\t}\n}\n\nexport enum ResizeMode {\n\tStretch,\n\tExpand,\n\tFit\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BlendMode, Color, Disposable, TimeKeeper } from \"@esotericsoftware/spine-core\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { ResizeMode, SceneRenderer } from \"./SceneRenderer.js\";\n\nlet spinnerImage: HTMLImageElement;\nlet logoImage: HTMLImageElement;\nlet loaded = 0;\n\nconst FADE_IN = 1, FADE_OUT = 1;\nconst logoWidth = 165, logoHeight = 108, spinnerSize = 163;\n\nexport class LoadingScreen implements Disposable {\n\tprivate renderer: SceneRenderer;\n\tprivate logo: GLTexture | null = null;\n\tprivate spinner: GLTexture | null = null;\n\tprivate angle = 0;\n\tprivate fadeOut = 0;\n\tprivate fadeIn = 0;\n\tprivate timeKeeper = new TimeKeeper();\n\tbackgroundColor = new Color(0.135, 0.135, 0.135, 1);\n\tprivate tempColor = new Color();\n\n\tconstructor (renderer: SceneRenderer) {\n\t\tthis.renderer = renderer;\n\n\t\tthis.timeKeeper.maxDelta = 9;\n\n\t\tif (!logoImage) {\n\t\t\tlet isSafari = navigator.userAgent.indexOf(\"Safari\") > -1; // Thank you Apple Inc.\n\t\t\tlet onload = () => loaded++;\n\n\t\t\tlogoImage = new Image();\n\t\t\tlogoImage.src = SPINE_LOGO_DATA;\n\t\t\tif (!isSafari) logoImage.crossOrigin = \"anonymous\";\n\t\t\tlogoImage.onload = onload;\n\n\t\t\tspinnerImage = new Image();\n\t\t\tspinnerImage.src = SPINNER_DATA;\n\t\t\tif (!isSafari) spinnerImage.crossOrigin = \"anonymous\";\n\t\t\tspinnerImage.onload = onload;\n\t\t}\n\t}\n\tdispose (): void {\n\t\tthis.logo?.dispose();\n\t\tthis.spinner?.dispose();\n\t}\n\n\tdraw (complete = false) {\n\t\tif (loaded < 2 || (complete && this.fadeOut > FADE_OUT)) return;\n\n\t\tthis.timeKeeper.update();\n\t\tlet a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25));\n\t\tthis.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5));\n\n\t\tlet tempColor = this.tempColor;\n\t\tlet renderer = this.renderer;\n\t\tlet canvas = renderer.canvas;\n\t\tlet gl = renderer.context.gl;\n\n\t\trenderer.resize(ResizeMode.Expand);\n\t\trenderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0);\n\t\trenderer.batcher.setBlendMode(BlendMode.Normal, true);\n\n\t\tif (complete) {\n\t\t\tthis.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1);\n\t\t\tif (this.fadeOut > FADE_OUT) return;\n\t\t\ttempColor.setFromColor(this.backgroundColor);\n\t\t\ta = 1 - this.fadeOut / FADE_OUT;\n\t\t\ta = 1 - (a - 1) * (a - 1);\n\t\t\ttempColor.a *= a;\n\t\t\tif (tempColor.a > 0) {\n\t\t\t\trenderer.camera.zoom = 1;\n\t\t\t\trenderer.begin();\n\t\t\t\trenderer.quad(true, 0, 0, canvas.width, 0, canvas.width, canvas.height, 0, canvas.height,\n\t\t\t\t\ttempColor, tempColor, tempColor, tempColor);\n\t\t\t\trenderer.end();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.fadeIn += this.timeKeeper.delta;\n\t\t\tif (this.backgroundColor.a > 0) {\n\t\t\t\tgl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a);\n\t\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\t}\n\t\t\ta = 1;\n\t\t}\n\t\ta *= Math.min(this.fadeIn / FADE_IN, 1);\n\t\ttempColor.set(a, a, a, a);\n\n\t\tif (!this.logo) {\n\t\t\tthis.logo = new GLTexture(renderer.context, logoImage);\n\t\t\tthis.spinner = new GLTexture(renderer.context, spinnerImage);\n\t\t}\n\t\trenderer.camera.zoom = Math.max(1, spinnerSize / canvas.height);\n\t\trenderer.begin();\n\t\trenderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor);\n\t\tif (this.spinner) renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor);\n\t\trenderer.end();\n\t}\n}\n\nlet SPINNER_DATA = \"data:image/png;base64,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\";\n\nlet SPINE_LOGO_DATA = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAABsCAYAAAALzHKmAAAQ7klEQVR42u3da4xdVRUA4D0zd2Y6nZY59DVtZ1puS9+lzC0YAi2UQ8AAQczFpPgA9VIeIQbirRqJ0cBUBVGjDr/QCKSNRSMmpuODxAdxqhgwxkhFjf6Sxh/+UUNVNGJCzR7uTvas7LXX2q9zzp3em6y0gTN3Zu75utZe5+yztxC9V+/Ve5X9En1Vjd7J6SFbLNF7naPw+l2jh7YHMBWssqMHtlsRdim4qsLtIawaPiHEQOLoNrA9iIkQDnRrVA1qD2LZ8ISoxYqKo13sQAtBWBayQWZUAXGRQM9JjCngDVY0UqJNDbQrMcaGmArdUKpIjbYiQLsCZCyIMQBy8QwnilR4Q5AuCpxFYvRFmBLbEiwKwpsSaWycVQGZBKMrwBjA9BhxDe57u2L2hOoKNCbOrgAZitEVYUxoKSMErQvSxYIzCkguRg5EF4AUhqUlhy/YUKSxcRaKsioYOQhD4I0yYxkR3PcJBcuFysmgsXAWBTMJyBCMIQh9kGGxXIXvexCQXbHGAMrBWTbM2CCpMSMLIxehC77lSJwXGth7M0FzoVJIXXDWQnGmhOkL0ic7YhhtWdGGkAuPAjUWGoF4faCmwBkbZmyUqUCyMqMLRA4+E6IsdTjidUHKBYrh9CnpRcH0ypKxsyOGEYNIIeTCOz91OIJ1QYoB5eAMyZo+MFNnyVTZ0YiRC9EGEMOyAgshxErHsL2XK1gOUgwohtM1a5YNM7Rsu4K0ZkcbRm4mpPBRwFZ5hg9eCqkrUB+csWGGogzNkqEgrdnRhpGLkINudaLgwvVB6oqzCjCTZElb2Y4B0gUjBtEG0ARnDRLjjoG9DwcshtQGlIPTljVjwUySLWNkyRCQVHa0ZUUTRAwgF91a33BEy0VKAcVwwqwZC2bqbOlUurllOxQkJzNyINoAYqjWhYYjWg5SCiiG05Q1U8FMjTIoS8YE6YORi1BHtJ4KIcQEEtTXUWAxpK44YVlPBdO1jCdFWTZIE8bVGEYMIRPcZGBw4HKQcoBiOE1ZMzbMgVQwU6JMAdKEEcuIJogUvg1YCCE2gsCO42DlIIVAKZwpYJaSLVNnSU6XjYHUmxhTmXaFaMO3EYkLqMC+FsLlIoVAKZzMrEnBhJeLfLNlKMrYWRIDCbOkFSSVHbHM6AKRC6/ODUewNqQ+OLlZkxpjUmV8MBbMUJSxyzY3Q1IgTRgxiBRCHdem0KDAUkBh9sRwwjEnAXMMgTnKhFlUtiwkS5rGka4g9SaGgxFmRC7AzTCEEBcyA36dDSsXqAtOLkysjGMwY5XxVChjZ0kuSCo7YlkRQsQQYtDEFsegsLoCxUp7Kpgps2UslFGzJGccSYHUmxhOZqwzEZqAbfUMCisHKIZzgsCpl3MTzMwTpi1bYp2477gyFKUxS7qWbdjY2EBS2dGE0QQRA7gNCyHEdhjE8RhUDlBT9tzgmjWZMFNlSy+Urk1OzCyJlW0XkK4YOQh1cDtcgwBrQmoDWkdgboBZE8mYsJSHlnFbJ+5bwmOPJ7lZkirbC8aRsMvmgtTHjBhGE0QbwJ2egUE1ITVlUC5OmDVdYNrKuN70xM6WoShjlW4464dbtiFIWK6x7GjESEHUUe0iYncnbMdQSE0Z1ITTNOb0hRmjjLtmS9dmJ2rp1jtuKktyyrb6YLEMCUHq2dGG0QQRQ7f72kzc+cJecerne8Wvv7JNPHPvenEkz8Sh3UtFc92QyGt9Yko/HgOLAIUZlItTz5ouMF3KuE+2jFLCQ1D6lm6fLMkBacuOJowYRBUXyfjuHjF3NhdnsfjvAfH6E9vFt9XxKgikEKgJZyyYalzOLeMu2bLbULI6bh+QGwmQ+rgRlumdGEQAao+K56bEL2woVUwOiev0r8OAUjiJrMmFCbvykGxZRAmPitK1dHM7bohyMsuyi/I8f0+e57fJYIKEZXpXo9E4mOf5XTKyLLvCBLETF8uY2SKepkC+dpX4T02Ivepr4HvZcOZ5fmee54fyPL+DmTUhzAs6n4n8bN5dr9f3YdkSg8nsxG0lPBVKVpNjG0/aGhzfLDmRZdnumZmZp8+c+cdZPV555fSr7Xb7s0jJ3i5Pcue4MxKkPPkvvXTqz/B92u32l0wYOzG1fkhcd/py8Rcbyq/vFM/KY1WA95h/3zzP71bfU6JsNpsfgj+P/FlbrdaDGExYyuXvLz8H+DudODH700ajcSM3W6Yu4alQ1spCOTd38jcKocTZbh9+9NixY99XJ8AEUkcpo9W64yH197m5k7+bnZ19QT+J09NHntQhwji/Jg58qi6++ofLxJ8gSFneVw2Ka4QQDfh1Ok4dZavVmtZ/nrm5k7/Vf55O1tRhboUw5+ZOvqyOl5+R/FyOHj32PYVU/tloNG5IXcKrhJIzngwp3fNjomazea/64BuNxts646f50lWv169utw9/DmtqdJQyZFaSJVuV6nq9fqMEof5/vV6/CYBqgJDlee+yAbF/+4i4ZWqZeNfaIfHWzn+Hx0KcEuU9+s8jv3ej0bhVlXOZydX/k0iRMeb8P0D5e6tj8zy/Xb9UJIc56h/yqVOnXul8lmuZ2bJslKmbHG7XrbpCmCXFRLvdfqQD6jTS3Jiy5I4OykM6ADV+1Eu1DmV6evopBORexzDi1L+X/HnGxsb2w3Hm9PSRJ9QxWPOTZdmlKht2hi+w6dkox5bqffI8fye3hDteGqKaHVsHXihKl0tB+h0cY+lute54AGRKDCW89LNTRynHb7ChUWVVjetOnJh9EYBUyPZeNCoOtsbFQwdXi4/esELcd+tq8cCHJ8UXp+viy9efLz7AgamjlKXc1AA1m83DoIRDlFubzeb96hhZLVTlgJ24gttutx+ONa50bHZKRenaeTs1OfpAfnr6yOOdE7EZdNwmlKocntXLNkA5JTGq47Ds+Lf94lWsyfnXleLfnIwJUN4DOnNYwuUxh2A3Ln9XULrfK8t3J27Tu3BVwiOjXJqoAy8UZej1yclGo3GTLN+gu3w+z/P3YaWbQqk3Ne12e4ZC+c8rxWsYytcPiP9RpZxCqWDKnxOiBNlyAUpOnGsoh4tA2Rm8X9xqtT6md5wyZmYe+0YRKL+1S/wYQ3n8zctBl5SBUv5djivfjMOPduIzcizeiYfr9foVvUwZG+XCuzibZKnSceZ5/v4QlKp8y7ElhnJlTeTP7BI/kllRYfzrfvHqFy4UX1vaL/aVlSmROzwbwdS29T2UcEwZF+V8ozM2lu1VY812u/15akypGh3TmFJesJbHHD167IdUxz3YJy5bNySuX1mbvy55CbMLtzU6tjGlsdFptVqfUMc0Go23F4wy1l2dSnbfvpMwVPe9WWVLDsrOJaF9MFu2Wq1PqmNkGce67xiXhTjdNwdlvV6/BgxfbPfBfVCetxi6b9/rlCup65QzM48dl2OjLMv26CibzeZ96sTIzEFdpwQXz9U1yrtVlpR/Zll2Fec65Y6l4pbbx8XHH9kknvzJlPjlHy8Tp29eKT5ou0aJoIT3w3dBlLDzVpfAJEZ1XOdaJZxnOSlvPMjPzxFljIvng914RwebsjYO7uhMyHu46sOfnf3Oz2TXDW6vvYxdFoIXz3Wc8J5zs9n8iOn2IrxTc2BM3Glqdp7dI553uaOjxrhwcob+MyuUpjs6WZZdon8OcigjPx8V+u+GTWFTSWEx3WYcdJ225jNDSE4q0GHCzlueHOyujn6bUWYgeb9ZZUaQPe+GzQ+Gc8+oOGhC+c1d4gfI16n3XDAhQ7+9qE9l01E2Go132GYKyXE1NiFDTcpoNpv3LOYJGWXNErJNW9sEp63p2RKiVPMn1bS1DgxsyhoGdGpmizj+xtXiDYnx7/vFmce3iWdW1cTVGEY4hQ2ZW0nNq8Qm/M6XbXm3S100lwGedFybuvNOibLI+ZS2ceU4eAxiEuvCkfmU8ycToDxETe6FgCBQHeqyAbFvfEhcO7BwDuXFCEbTZF840XeHK0jYcbs2OIGle0mVJ/mmnClEPQqxyTY5I8/zFhif7fSZee4bnrPOU4AssnRXHaVTCTd14dRDY3UbTIiSeFhsN/aMjgnqthFx880rxX3yATL5p3y4LPXzOaBkUyBjZMlYpbtQlIOBD475ZEusjMNSvkXe6VEoJVDkeZ2dzIfIFsRzU+JF2OyM9M9fTC/6SUYOyFQPjQ2nWiUjxnPfw5EeHqMWIqAeIFsAU847lJM2JM6xsewt1OIDLs99P7ZFHNdB/upS8XtPiD7PfLuCXJNolYyyFiNI/Zit65ItrOVafFbHcFohY7hPTN21Tjz4uc3iqfsnxKdX1MTl1OoYRFaMsToGB6Trw2JFP/OdZC2hJZ7ZkrMoAbbSGmelDJ91hFKuJeS7jlBMkJnrAqqJlgMUZS/dArPlGHNdSg5M3xXXtvquuEatvIYtDRhpxbUJuIgqsU5lGWtUploK0KuEU9mSW8YpmFQ556xNuYW7NiW13B+FkMiKHIy+C6eGgBxJvMR0oSv5hi6+z4HJyZoU0M2RVvDlrOQbcxVfX5AhZbuqy0v7ZstYMLHlAVlLTF9ALLbvu9Y5Zylpn/XOsd0ibIvxr2KCLHpp6SCUIdnSZSF+WzfOhem6GD+1KwR3Z4jNjrtDpNoZwmWd8yrupZN6Hx3fbMmFSe0Swdq2ZIPjxk1112Duo8OBGLrBkw/IoncdK2XHsdC9dHz204m50xh3tzFq1zFqtzHXrfCw7OgDsqyNnZLszVijsmXgrmNcmGtS78lIoMX2aJz03fKO2sDJddPQSCDPiQ1DfWBycY6XtXstc2PQKuxgG2McmXTPb9/9vmuJYXKyJrWjbeg+3xPM4O73nWqvbyw7xgZZSJbEUBa157cNJjdr2vb+5iA1YV3HxYscj30PDCEHIgcjtfm8K8hSsmRotkwFk5s1TTghUAopB6xrjHMBBkI0YYTZ0dZlxwLpkiWDULpmy5gwqayZgZNkA7oKQQCxctByYg0XIIEQQuRitGVHblMTA2ShKGPDpC6wu+DEgJqg2rDGDBtAF4Q6RAojp1xXGmSMbImVcR+YWNY04eQCtUG1ofUJ2/uvcETIgUhhdAE5GAlkKShjwHTNmhhODKgJqQ2sC14uOgyfD0IbRF+MlQaZAiZWyn2yJsTJATqGnHQO2Jhh+xlsACFCG0QbRtdyzQFZCZSxYPpmTS7Q5cjJHYNBYIkZpu99HoUQ/o4QIYSIZUZfjJ4ZMjZI32wZBDMU5yhy8pZTULl4XYP5fagMyEVoy4oupTpGduwnkloSlKEwY+AcQU4MhRTD6ovXBRwFzwWgCSEF0QVjJUGmgEllTS5OLlCIlIN1mS9mx/cZ5eLDALpCTI2RAhkTZQqYoTgpoCPECbaBHQ2ETL3PUl98ECAXYijG0OyYAmQoTG7W5ODkAF1CnVgm2JQx4okPA+gCMTbGskBGgRmaOblAh5GTORIrfKFx4VH4EIAxIXIxlg2SBbMvECY3e7oApbDaIgQu5/2HmeEKEINYiwSRi7EQkLFgumZOCuggctKGI4ULZN/vMeSLj0AYMytWEqMLzFg4fYDaoKaC6wvOFR4FkIPQFaILxrJAOsHsc/zlfYDWXE8qF22s8Pz5KHxcgEVALBtjJXBSSEOwFhk1Zgy4hitCT4hVw+gFs8/zwxqIBbUgyK7fcyA0PD9XX4iVxhiC0xdof6STWCsoBmKF7+cVCWFXQYyBMxRpf+STX1b0x45AhN0OMSrOGEirhrY/dfQAdjvS7oy+WCF6r1RIFxXWvlTRg1YVqFWBmxZbD99ig9pt0YPQw9rD1nstVri9V+/Ve3XrS/wfim4P5fIFxLoAAAAASUVORK5CYII=\";\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TimeKeeper, AssetManager, ManagedWebGLRenderingContext, SceneRenderer, Input, StringMap } from \"./index.js\";\n\n/** An app running inside a {@link SpineCanvas}. The app life-cycle\n * is as follows:\n *\n * 1. `loadAssets()` is called. The app can queue assets for loading via {@link SpineCanvas.assetManager}.\n * 2. `initialize()` is called when all assets are loaded. The app can setup anything it needs to enter the main application logic.\n * 3. `update()` is called periodically at screen refresh rate. The app can update its state.\n * 4. `render()` is called periodically at screen refresh rate. The app can render its state via {@link SpineCanvas.renderer} or directly via the WebGL context in {@link SpineCanvas.gl}.\n *\n * The `error()` method is called in case the assets could not be loaded. The `dispose()` method is called in case the canvas has been disposed via {@link SpineCanvas.dispose}.\n */\nexport interface SpineCanvasApp {\n\tloadAssets?(canvas: SpineCanvas): void;\n\tinitialize?(canvas: SpineCanvas): void;\n\tupdate?(canvas: SpineCanvas, delta: number): void;\n\trender?(canvas: SpineCanvas): void;\n\terror?(canvas: SpineCanvas, errors: StringMap): void;\n\tdispose?(canvas: SpineCanvas): void;\n}\n\n/** Configuration passed to the {@link SpineCanvas} constructor */\nexport interface SpineCanvasConfig {\n\t/* The {@link SpineCanvasApp} to be run in the canvas. */\n\tapp: SpineCanvasApp;\n\t/* The path prefix to be used by the {@link AssetManager}. */\n\tpathPrefix?: string;\n\t/* The WebGL context configuration */\n\twebglConfig?: any;\n}\n\n/** Manages the life-cycle and WebGL context of a {@link SpineCanvasApp}. The app loads\n * assets and initializes itself, then updates and renders its state at the screen refresh rate. */\nexport class SpineCanvas {\n\treadonly context: ManagedWebGLRenderingContext;\n\n\t/** Tracks the current time, delta, and other time related statistics. */\n\treadonly time = new TimeKeeper();\n\t/** The HTML canvas to render to. */\n\treadonly htmlCanvas: HTMLCanvasElement;\n\t/** The WebGL rendering context. */\n\treadonly gl: WebGLRenderingContext;\n\t/** The scene renderer for easy drawing of skeletons, shapes, and images. */\n\treadonly renderer: SceneRenderer;\n\t/** The asset manager to load assets with. */\n\treadonly assetManager: AssetManager;\n\t/** The input processor used to listen to mouse, touch, and keyboard events. */\n\treadonly input: Input;\n\n\tprivate disposed = false;\n\n\t/** Constructs a new spine canvas, rendering to the provided HTML canvas. */\n\tconstructor (canvas: HTMLCanvasElement, private config: SpineCanvasConfig) {\n\t\tif (!config.pathPrefix) config.pathPrefix = \"\";\n\t\tif (!config.app) config.app = {\n\t\t\tloadAssets: () => { },\n\t\t\tinitialize: () => { },\n\t\t\tupdate: () => { },\n\t\t\trender: () => { },\n\t\t\terror: () => { },\n\t\t\tdispose: () => { },\n\t\t}\n\t\tif (!config.webglConfig) config.webglConfig = { alpha: true };\n\n\t\tthis.htmlCanvas = canvas;\n\t\tthis.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig);\n\t\tthis.renderer = new SceneRenderer(canvas, this.context);\n\t\tthis.gl = this.context.gl;\n\t\tthis.assetManager = new AssetManager(this.context, config.pathPrefix);\n\t\tthis.input = new Input(canvas);\n\n\t\tif (config.app.loadAssets) config.app.loadAssets(this);\n\n\t\tlet loop = () => {\n\t\t\tif (this.disposed) return;\n\t\t\trequestAnimationFrame(loop);\n\t\t\tthis.time.update();\n\t\t\tif (config.app.update) config.app.update(this, this.time.delta);\n\t\t\tif (config.app.render) config.app.render(this);\n\t\t}\n\n\t\tlet waitForAssets = () => {\n\t\t\tif (this.disposed) return;\n\t\t\tif (this.assetManager.isLoadingComplete()) {\n\t\t\t\tif (this.assetManager.hasErrors()) {\n\t\t\t\t\tif (config.app.error) config.app.error(this, this.assetManager.getErrors());\n\t\t\t\t} else {\n\t\t\t\t\tif (config.app.initialize) config.app.initialize(this);\n\t\t\t\t\tloop();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\trequestAnimationFrame(waitForAssets);\n\t\t}\n\t\trequestAnimationFrame(waitForAssets);\n\t}\n\n\t/** Clears the canvas with the given color. The color values are given in the range [0,1]. */\n\tclear (r: number, g: number, b: number, a: number) {\n\t\tthis.gl.clearColor(r, g, b, a);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\t}\n\n\t/** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/\n\tdispose () {\n\t\tif (this.config.app.dispose) this.config.app.dispose(this);\n\t\tthis.disposed = true;\n\t}\n}\n", "/*\nThe MIT License (MIT)\n\nCopyright (c) 2021-present AgogPixel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n// Adapted from https://github.com/agogpixel/phaser3-ts-utils/tree/main\n\nlet components = (Phaser.GameObjects.Components as any);\nexport const ComputedSize = components.ComputedSize;\nexport const Depth = components.Depth;\nexport const Flip = components.Flip;\nexport const ScrollFactor = components.ScrollFactor;\nexport const Transform = components.Transform;\nexport const Visible = components.Visible;\nexport const Origin = components.Origin;\nexport const Alpha = components.Alpha;\n\nexport interface Type<\n\tT,\n\tP extends any[] = any[]\n\t> extends Function {\n\tnew(...args: P): T;\n}\n\nexport type Mixin = <\n\tGameObjectType extends Type\n\t>(\n\tBaseGameObject: GameObjectType\n) => GameObjectType & Type;\n\nexport function createMixin<\n\tGameObjectComponent,\n\tGameObjectConstraint extends Phaser.GameObjects.GameObject = Phaser.GameObjects.GameObject\n> (\n\t...component: GameObjectComponent[]\n): Mixin {\n\treturn (BaseGameObject) => {\n\t\t(Phaser as any).Class.mixin(BaseGameObject, component);\n\t\treturn BaseGameObject as any;\n\t};\n}\n\ntype ComputedSizeMixin = Mixin;\nexport const ComputedSizeMixin: ComputedSizeMixin = createMixin(ComputedSize);\n\ntype DepthMixin = Mixin;\nexport const DepthMixin: DepthMixin = createMixin(Depth);\n\ntype FlipMixin = Mixin;\nexport const FlipMixin: FlipMixin = createMixin(Flip);\n\ntype ScrollFactorMixin = Mixin;\nexport const ScrollFactorMixin: ScrollFactorMixin = createMixin(ScrollFactor);\n\ntype TransformMixin = Mixin;\nexport const TransformMixin: TransformMixin = createMixin(Transform);\n\ntype VisibleMixin = Mixin;\nexport const VisibleMixin: VisibleMixin = createMixin(Visible);\n\ntype OriginMixin = Mixin;\nexport const OriginMixin: OriginMixin = createMixin(Origin);\n\ntype AlphaMixin = Mixin;\nexport const AlphaMixin: AlphaMixin = createMixin(Alpha);", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { SPINE_GAME_OBJECT_TYPE } from \"./keys.js\";\nimport { SpinePlugin } from \"./SpinePlugin.js\";\nimport {\n\tComputedSizeMixin,\n\tDepthMixin,\n\tFlipMixin,\n\tScrollFactorMixin,\n\tTransformMixin,\n\tVisibleMixin,\n\tAlphaMixin,\n\tOriginMixin,\n} from \"./mixins.js\";\nimport {\n\tAnimationState,\n\tAnimationStateData,\n\tBone,\n\tMathUtils,\n\tPhysics,\n\tSkeleton,\n\tSkeletonClipping,\n\tSkin,\n\tVector2,\n} from \"@esotericsoftware/spine-core\";\n\nclass BaseSpineGameObject extends Phaser.GameObjects.GameObject {\n\tconstructor (scene: Phaser.Scene, type: string) {\n\t\tsuper(scene, type);\n\t}\n}\n\n/** A bounds provider calculates the bounding box for a skeleton, which is then assigned as the size of the SpineGameObject. */\nexport interface SpineGameObjectBoundsProvider {\n\t// Returns the bounding box for the skeleton, in skeleton space.\n\tcalculateBounds (gameObject: SpineGameObject): {\n\t\tx: number;\n\t\ty: number;\n\t\twidth: number;\n\t\theight: number;\n\t};\n}\n\n/** A bounds provider that calculates the bounding box from the setup pose. */\nexport class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider {\n\t/**\n\t * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.\n\t */\n\tconstructor (\n\t\tprivate clipping = false,\n\t) { }\n\n\tcalculateBounds (gameObject: SpineGameObject) {\n\t\tif (!gameObject.skeleton) return { x: 0, y: 0, width: 0, height: 0 };\n\t\t// Make a copy of animation state and skeleton as this might be called while\n\t\t// the skeleton in the GameObject has already been heavily modified. We can not\n\t\t// reconstruct that state.\n\t\tconst skeleton = new Skeleton(gameObject.skeleton.data);\n\t\tskeleton.setToSetupPose();\n\t\tskeleton.updateWorldTransform(Physics.update);\n\t\tconst bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined);\n\t\treturn bounds.width == Number.NEGATIVE_INFINITY\n\t\t\t? { x: 0, y: 0, width: 0, height: 0 }\n\t\t\t: bounds;\n\t}\n}\n\n/** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */\nexport class SkinsAndAnimationBoundsProvider\n\timplements SpineGameObjectBoundsProvider {\n\t/**\n\t * @param animation The animation to use for calculating the bounds. If null, the setup pose is used.\n\t * @param skins The skins to use for calculating the bounds. If empty, the default skin is used.\n\t * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.\n\t * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.\n\t */\n\tconstructor (\n\t\tprivate animation: string | null,\n\t\tprivate skins: string[] = [],\n\t\tprivate timeStep: number = 0.05,\n\t\tprivate clipping = false,\n\t) { }\n\n\tcalculateBounds (gameObject: SpineGameObject): {\n\t\tx: number;\n\t\ty: number;\n\t\twidth: number;\n\t\theight: number;\n\t} {\n\t\tif (!gameObject.skeleton || !gameObject.animationState)\n\t\t\treturn { x: 0, y: 0, width: 0, height: 0 };\n\t\t// Make a copy of animation state and skeleton as this might be called while\n\t\t// the skeleton in the GameObject has already been heavily modified. We can not\n\t\t// reconstruct that state.\n\t\tconst animationState = new AnimationState(gameObject.animationState.data);\n\t\tconst skeleton = new Skeleton(gameObject.skeleton.data);\n\t\tconst clipper = this.clipping ? new SkeletonClipping() : undefined;\n\t\tconst data = skeleton.data;\n\t\tif (this.skins.length > 0) {\n\t\t\tlet customSkin = new Skin(\"custom-skin\");\n\t\t\tfor (const skinName of this.skins) {\n\t\t\t\tconst skin = data.findSkin(skinName);\n\t\t\t\tif (skin == null) continue;\n\t\t\t\tcustomSkin.addSkin(skin);\n\t\t\t}\n\t\t\tskeleton.setSkin(customSkin);\n\t\t}\n\t\tskeleton.setToSetupPose();\n\n\t\tconst animation =\n\t\t\tthis.animation != null ? data.findAnimation(this.animation!) : null;\n\t\tif (animation == null) {\n\t\t\tskeleton.updateWorldTransform(Physics.update);\n\t\t\tconst bounds = skeleton.getBoundsRect(clipper);\n\t\t\treturn bounds.width == Number.NEGATIVE_INFINITY\n\t\t\t\t? { x: 0, y: 0, width: 0, height: 0 }\n\t\t\t\t: bounds;\n\t\t} else {\n\t\t\tlet minX = Number.POSITIVE_INFINITY,\n\t\t\t\tminY = Number.POSITIVE_INFINITY,\n\t\t\t\tmaxX = Number.NEGATIVE_INFINITY,\n\t\t\t\tmaxY = Number.NEGATIVE_INFINITY;\n\t\t\tanimationState.clearTracks();\n\t\t\tanimationState.setAnimationWith(0, animation, false);\n\t\t\tconst steps = Math.max(animation.duration / this.timeStep, 1.0);\n\t\t\tfor (let i = 0; i < steps; i++) {\n\t\t\t\tconst delta = i > 0 ? this.timeStep : 0;\n\t\t\t\tanimationState.update(delta);\n\t\t\t\tanimationState.apply(skeleton);\n\t\t\t\tskeleton.update(delta);\n\t\t\t\tskeleton.updateWorldTransform(Physics.update);\n\n\t\t\t\tconst bounds = skeleton.getBoundsRect(clipper);\n\t\t\t\tminX = Math.min(minX, bounds.x);\n\t\t\t\tminY = Math.min(minY, bounds.y);\n\t\t\t\tmaxX = Math.max(maxX, bounds.x + bounds.width);\n\t\t\t\tmaxY = Math.max(maxY, bounds.y + bounds.height);\n\t\t\t}\n\t\t\tconst bounds = {\n\t\t\t\tx: minX,\n\t\t\t\ty: minY,\n\t\t\t\twidth: maxX - minX,\n\t\t\t\theight: maxY - minY,\n\t\t\t};\n\t\t\treturn bounds.width == Number.NEGATIVE_INFINITY\n\t\t\t\t? { x: 0, y: 0, width: 0, height: 0 }\n\t\t\t\t: bounds;\n\t\t}\n\t}\n}\n\n/**\n * A SpineGameObject is a Phaser {@link GameObject} that can be added to a Phaser Scene and render a Spine skeleton.\n *\n * The Spine GameObject is a thin wrapper around a Spine {@link Skeleton}, {@link AnimationState} and {@link AnimationStateData}. It is responsible for:\n * - updating the animation state\n * - applying the animation state to the skeleton's bones, slots, attachments, and draw order.\n * - updating the skeleton's bone world transforms\n * - rendering the skeleton\n *\n * See the {@link SpinePlugin} class for more information on how to create a `SpineGameObject`.\n *\n * The skeleton, animation state, and animation state data can be accessed via the repsective fields. They can be manually updated via {@link updatePose}.\n *\n * To modify the bone hierarchy before the world transforms are computed, a callback can be set via the {@link beforeUpdateWorldTransforms} field.\n *\n * To modify the bone hierarchy after the world transforms are computed, a callback can be set via the {@link afterUpdateWorldTransforms} field.\n *\n * The class also features methods to convert between the skeleton coordinate system and the Phaser coordinate system.\n *\n * See {@link skeletonToPhaserWorldCoordinates}, {@link phaserWorldCoordinatesToSkeleton}, and {@link phaserWorldCoordinatesToBoneLocal.}\n */\nexport class SpineGameObject extends DepthMixin(\n\tOriginMixin(\n\t\tComputedSizeMixin(\n\t\t\tFlipMixin(\n\t\t\t\tScrollFactorMixin(\n\t\t\t\t\tTransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject)))\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t)\n) {\n\tblendMode = -1;\n\tskeleton: Skeleton;\n\tanimationStateData: AnimationStateData;\n\tanimationState: AnimationState;\n\tbeforeUpdateWorldTransforms: (object: SpineGameObject) => void = () => { };\n\tafterUpdateWorldTransforms: (object: SpineGameObject) => void = () => { };\n\tprivate premultipliedAlpha = false;\n\n\tconstructor (\n\t\tscene: Phaser.Scene,\n\t\tprivate plugin: SpinePlugin,\n\t\tx: number,\n\t\ty: number,\n\t\tdataKey: string,\n\t\tatlasKey: string,\n\t\tpublic boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider()\n\t) {\n\t\tsuper(scene, (window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE);\n\t\tthis.setPosition(x, y);\n\n\t\tthis.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey);\n\t\tthis.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);\n\t\tthis.animationStateData = new AnimationStateData(this.skeleton.data);\n\t\tthis.animationState = new AnimationState(this.animationStateData);\n\t\tthis.skeleton.updateWorldTransform(Physics.update);\n\t\tthis.updateSize();\n\t}\n\n\tupdateSize () {\n\t\tif (!this.skeleton) return;\n\t\tlet bounds = this.boundsProvider.calculateBounds(this);\n\t\t// For some reason the TS compiler and the ComputedSize mixin don't work well together and we have\n\t\t// to cast to any.\n\t\tlet self = this as any;\n\t\tself.width = bounds.width;\n\t\tself.height = bounds.height;\n\t\tthis.displayOriginX = -bounds.x;\n\t\tthis.displayOriginY = -bounds.y;\n\t}\n\n\t/** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */\n\tskeletonToPhaserWorldCoordinates (point: { x: number; y: number }) {\n\t\tlet transform = this.getWorldTransformMatrix();\n\t\tlet a = transform.a,\n\t\t\tb = transform.b,\n\t\t\tc = transform.c,\n\t\t\td = transform.d,\n\t\t\ttx = transform.tx,\n\t\t\tty = transform.ty;\n\t\tlet x = point.x;\n\t\tlet y = point.y;\n\t\tpoint.x = x * a + y * c + tx;\n\t\tpoint.y = x * b + y * d + ty;\n\t}\n\n\t/** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */\n\tphaserWorldCoordinatesToSkeleton (point: { x: number; y: number }) {\n\t\tlet transform = this.getWorldTransformMatrix();\n\t\ttransform = transform.invert();\n\t\tlet a = transform.a,\n\t\t\tb = transform.b,\n\t\t\tc = transform.c,\n\t\t\td = transform.d,\n\t\t\ttx = transform.tx,\n\t\t\tty = transform.ty;\n\t\tlet x = point.x;\n\t\tlet y = point.y;\n\t\tpoint.x = x * a + y * c + tx;\n\t\tpoint.y = x * b + y * d + ty;\n\t}\n\n\t/** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */\n\tphaserWorldCoordinatesToBone (point: { x: number; y: number }, bone: Bone) {\n\t\tthis.phaserWorldCoordinatesToSkeleton(point);\n\t\tif (bone.parent) {\n\t\t\tbone.parent.worldToLocal(point as Vector2);\n\t\t} else {\n\t\t\tbone.worldToLocal(point as Vector2);\n\t\t}\n\t}\n\n\t/**\n\t * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones.\n\t * @param delta The time delta in milliseconds\n\t */\n\tupdatePose (delta: number) {\n\t\tthis.animationState.update(delta / 1000);\n\t\tthis.animationState.apply(this.skeleton);\n\t\tthis.beforeUpdateWorldTransforms(this);\n\t\tthis.skeleton.update(delta / 1000);\n\t\tthis.skeleton.updateWorldTransform(Physics.update);\n\t\tthis.afterUpdateWorldTransforms(this);\n\t}\n\n\tpreUpdate (time: number, delta: number) {\n\t\tif (!this.skeleton || !this.animationState) return;\n\t\tthis.updatePose(delta);\n\t}\n\n\tpreDestroy () {\n\t\t// FIXME tear down any event emitters\n\t}\n\n\twillRender (camera: Phaser.Cameras.Scene2D.Camera) {\n\t\tvar GameObjectRenderMask = 0xf;\n\t\tvar result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id));\n\t\tif (!this.visible) result = false;\n\n\t\tif (!result && this.parentContainer && this.plugin.webGLRenderer) {\n\t\t\tvar sceneRenderer = this.plugin.webGLRenderer;\n\n\t\t\tif (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) {\n\t\t\t\tsceneRenderer.end();\n\t\t\t\tthis.plugin.phaserRenderer.pipelines.rebind();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\trenderWebGL (\n\t\trenderer: Phaser.Renderer.WebGL.WebGLRenderer,\n\t\tsrc: SpineGameObject,\n\t\tcamera: Phaser.Cameras.Scene2D.Camera,\n\t\tparentMatrix: Phaser.GameObjects.Components.TransformMatrix\n\t) {\n\t\tif (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer)\n\t\t\treturn;\n\n\t\tlet sceneRenderer = this.plugin.webGLRenderer;\n\t\tif (renderer.newType) {\n\t\t\trenderer.pipelines.clear();\n\t\t\tsceneRenderer.begin();\n\t\t}\n\n\t\tcamera.addToRenderList(src);\n\t\tlet transform = Phaser.GameObjects.GetCalcMatrix(\n\t\t\tsrc,\n\t\t\tcamera,\n\t\t\tparentMatrix\n\t\t).calc;\n\t\tlet a = transform.a,\n\t\t\tb = transform.b,\n\t\t\tc = transform.c,\n\t\t\td = transform.d,\n\t\t\ttx = transform.tx,\n\t\t\tty = transform.ty;\n\t\tsceneRenderer.drawSkeleton(\n\t\t\tthis.skeleton,\n\t\t\tthis.premultipliedAlpha,\n\t\t\t-1,\n\t\t\t-1,\n\t\t\t(vertices, numVertices, stride) => {\n\t\t\t\tfor (let i = 0; i < numVertices; i += stride) {\n\t\t\t\t\tlet vx = vertices[i];\n\t\t\t\t\tlet vy = vertices[i + 1];\n\t\t\t\t\tvertices[i] = vx * a + vy * c + tx;\n\t\t\t\t\tvertices[i + 1] = vx * b + vy * d + ty;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tif (!renderer.nextTypeMatch) {\n\t\t\tsceneRenderer.end();\n\t\t\trenderer.pipelines.rebind();\n\t\t}\n\t}\n\n\trenderCanvas (\n\t\trenderer: Phaser.Renderer.Canvas.CanvasRenderer,\n\t\tsrc: SpineGameObject,\n\t\tcamera: Phaser.Cameras.Scene2D.Camera,\n\t\tparentMatrix: Phaser.GameObjects.Components.TransformMatrix\n\t) {\n\t\tif (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer)\n\t\t\treturn;\n\n\t\tlet context = renderer.currentContext;\n\t\tlet skeletonRenderer = this.plugin.canvasRenderer;\n\t\t(skeletonRenderer as any).ctx = context;\n\n\t\tcamera.addToRenderList(src);\n\t\tlet transform = Phaser.GameObjects.GetCalcMatrix(\n\t\t\tsrc,\n\t\t\tcamera,\n\t\t\tparentMatrix\n\t\t).calc;\n\t\tlet skeleton = this.skeleton;\n\t\tskeleton.x = transform.tx;\n\t\tskeleton.y = transform.ty;\n\t\tskeleton.scaleX = transform.scaleX;\n\t\tskeleton.scaleY = transform.scaleY;\n\t\tlet root = skeleton.getRootBone()!;\n\t\troot.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized;\n\t\tthis.skeleton.updateWorldTransform(Physics.update);\n\n\t\tcontext.save();\n\t\tskeletonRenderer.draw(skeleton);\n\t\tcontext.restore();\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture, TextureFilter, TextureWrap } from \"@esotericsoftware/spine-core\";\n\nexport class CanvasTexture extends Texture {\n\tconstructor (image: HTMLImageElement | ImageBitmap) {\n\t\tsuper(image);\n\t}\n\n\tsetFilters (minFilter: TextureFilter, magFilter: TextureFilter) { }\n\tsetWraps (uWrap: TextureWrap, vWrap: TextureWrap) { }\n\tdispose () { }\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Utils, Color, Skeleton, RegionAttachment, BlendMode, MeshAttachment, Slot, TextureRegion, TextureAtlasRegion } from \"@esotericsoftware/spine-core\";\nimport { CanvasTexture } from \"./CanvasTexture.js\";\n\nconst worldVertices = Utils.newFloatArray(8);\n\nexport class SkeletonRenderer {\n\tstatic QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];\n\tstatic VERTEX_SIZE = 2 + 2 + 4;\n\n\tprivate ctx: CanvasRenderingContext2D;\n\n\tpublic triangleRendering = false;\n\tpublic debugRendering = false;\n\tprivate vertices = Utils.newFloatArray(8 * 1024);\n\tprivate tempColor = new Color();\n\n\tconstructor (context: CanvasRenderingContext2D) {\n\t\tthis.ctx = context;\n\t}\n\n\tdraw (skeleton: Skeleton) {\n\t\tif (this.triangleRendering) this.drawTriangles(skeleton);\n\t\telse this.drawImages(skeleton);\n\t}\n\n\tprivate drawImages (skeleton: Skeleton) {\n\t\tlet ctx = this.ctx;\n\t\tlet color = this.tempColor;\n\t\tlet skeletonColor = skeleton.color;\n\t\tlet drawOrder = skeleton.drawOrder;\n\n\t\tif (this.debugRendering) ctx.strokeStyle = \"green\";\n\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet slot = drawOrder[i];\n\t\t\tlet bone = slot.bone;\n\t\t\tif (!bone.active) continue;\n\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tif (!(attachment instanceof RegionAttachment)) continue;\n\t\t\tattachment.computeWorldVertices(slot, worldVertices, 0, 2);\n\t\t\tlet region: TextureRegion = attachment.region;\n\n\t\t\tlet image: HTMLImageElement = (region.texture).getImage() as HTMLImageElement;\n\n\t\t\tlet slotColor = slot.color;\n\t\t\tlet regionColor = attachment.color;\n\t\t\tcolor.set(skeletonColor.r * slotColor.r * regionColor.r,\n\t\t\t\tskeletonColor.g * slotColor.g * regionColor.g,\n\t\t\t\tskeletonColor.b * slotColor.b * regionColor.b,\n\t\t\t\tskeletonColor.a * slotColor.a * regionColor.a);\n\n\t\t\tctx.save();\n\t\t\tctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);\n\t\t\tctx.translate(attachment.offset[0], attachment.offset[1]);\n\t\t\tctx.rotate(attachment.rotation * Math.PI / 180);\n\n\t\t\tlet atlasScale = attachment.width / region.originalWidth;\n\t\t\tctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);\n\n\t\t\tlet w = region.width, h = region.height;\n\t\t\tctx.translate(w / 2, h / 2);\n\t\t\tif (attachment.region!.degrees == 90) {\n\t\t\t\tlet t = w;\n\t\t\t\tw = h;\n\t\t\t\th = t;\n\t\t\t\tctx.rotate(-Math.PI / 2);\n\t\t\t}\n\t\t\tctx.scale(1, -1);\n\t\t\tctx.translate(-w / 2, -h / 2);\n\n\t\t\tctx.globalAlpha = color.a;\n\t\t\tctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);\n\t\t\tif (this.debugRendering) ctx.strokeRect(0, 0, w, h);\n\t\t\tctx.restore();\n\t\t}\n\t}\n\n\tprivate drawTriangles (skeleton: Skeleton) {\n\t\tlet ctx = this.ctx;\n\t\tlet color = this.tempColor;\n\t\tlet skeletonColor = skeleton.color;\n\t\tlet drawOrder = skeleton.drawOrder;\n\n\t\tlet blendMode: BlendMode | null = null;\n\t\tlet vertices: ArrayLike = this.vertices;\n\t\tlet triangles: Array | null = null;\n\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet slot = drawOrder[i];\n\t\t\tlet attachment = slot.getAttachment();\n\n\t\t\tlet texture: HTMLImageElement;\n\t\t\tlet region: TextureAtlasRegion;\n\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\tlet regionAttachment = attachment;\n\t\t\t\tvertices = this.computeRegionVertices(slot, regionAttachment, false);\n\t\t\t\ttriangles = SkeletonRenderer.QUAD_TRIANGLES;\n\t\t\t\ttexture = (regionAttachment.region!.texture).getImage() as HTMLImageElement;\n\t\t\t} else if (attachment instanceof MeshAttachment) {\n\t\t\t\tlet mesh = attachment;\n\t\t\t\tvertices = this.computeMeshVertices(slot, mesh, false);\n\t\t\t\ttriangles = mesh.triangles;\n\t\t\t\ttexture = (mesh.region!.texture).getImage() as HTMLImageElement;\n\t\t\t} else\n\t\t\t\tcontinue;\n\n\t\t\tif (texture) {\n\t\t\t\tif (slot.data.blendMode != blendMode) blendMode = slot.data.blendMode;\n\n\t\t\t\tlet slotColor = slot.color;\n\t\t\t\tlet attachmentColor = attachment.color;\n\t\t\t\tcolor.set(skeletonColor.r * slotColor.r * attachmentColor.r,\n\t\t\t\t\tskeletonColor.g * slotColor.g * attachmentColor.g,\n\t\t\t\t\tskeletonColor.b * slotColor.b * attachmentColor.b,\n\t\t\t\t\tskeletonColor.a * slotColor.a * attachmentColor.a);\n\n\t\t\t\tctx.globalAlpha = color.a;\n\n\t\t\t\tfor (var j = 0; j < triangles.length; j += 3) {\n\t\t\t\t\tlet t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8;\n\n\t\t\t\t\tlet x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];\n\t\t\t\t\tlet x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];\n\t\t\t\t\tlet x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];\n\n\t\t\t\t\tthis.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);\n\n\t\t\t\t\tif (this.debugRendering) {\n\t\t\t\t\t\tctx.strokeStyle = \"green\";\n\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\tctx.moveTo(x0, y0);\n\t\t\t\t\t\tctx.lineTo(x1, y1);\n\t\t\t\t\t\tctx.lineTo(x2, y2);\n\t\t\t\t\t\tctx.lineTo(x0, y0);\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.ctx.globalAlpha = 1;\n\t}\n\n\t// Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120\n\t// Apache 2 licensed\n\tprivate drawTriangle (img: HTMLImageElement, x0: number, y0: number, u0: number, v0: number,\n\t\tx1: number, y1: number, u1: number, v1: number,\n\t\tx2: number, y2: number, u2: number, v2: number) {\n\t\tlet ctx = this.ctx;\n\n\t\tconst width = img.width - 1;\n\t\tconst height = img.height - 1;\n\t\tu0 *= width;\n\t\tv0 *= height;\n\t\tu1 *= width;\n\t\tv1 *= height;\n\t\tu2 *= width;\n\t\tv2 *= height;\n\n\t\tctx.beginPath();\n\t\tctx.moveTo(x0, y0);\n\t\tctx.lineTo(x1, y1);\n\t\tctx.lineTo(x2, y2);\n\t\tctx.closePath();\n\n\t\tx1 -= x0;\n\t\ty1 -= y0;\n\t\tx2 -= x0;\n\t\ty2 -= y0;\n\n\t\tu1 -= u0;\n\t\tv1 -= v0;\n\t\tu2 -= u0;\n\t\tv2 -= v0;\n\n\t\tlet det = u1 * v2 - u2 * v1;\n\t\tif (det == 0) return;\n\t\tdet = 1 / det;\n\n\t\t// linear transformation\n\t\tconst a = (v2 * x1 - v1 * x2) * det;\n\t\tconst b = (v2 * y1 - v1 * y2) * det;\n\t\tconst c = (u1 * x2 - u2 * x1) * det;\n\t\tconst d = (u1 * y2 - u2 * y1) * det;\n\n\t\t// translation\n\t\tconst e = x0 - a * u0 - c * v0;\n\t\tconst f = y0 - b * u0 - d * v0;\n\n\t\tctx.save();\n\t\tctx.transform(a, b, c, d, e, f);\n\t\tctx.clip();\n\t\tctx.drawImage(img, 0, 0);\n\t\tctx.restore();\n\t}\n\n\tprivate computeRegionVertices (slot: Slot, region: RegionAttachment, pma: boolean) {\n\t\tlet skeletonColor = slot.bone.skeleton.color;\n\t\tlet slotColor = slot.color;\n\t\tlet regionColor = region.color;\n\t\tlet alpha = skeletonColor.a * slotColor.a * regionColor.a;\n\t\tlet multiplier = pma ? alpha : 1;\n\t\tlet color = this.tempColor;\n\t\tcolor.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,\n\t\t\tskeletonColor.g * slotColor.g * regionColor.g * multiplier,\n\t\t\tskeletonColor.b * slotColor.b * regionColor.b * multiplier,\n\t\t\talpha);\n\n\t\tregion.computeWorldVertices(slot, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE);\n\n\t\tlet vertices = this.vertices;\n\t\tlet uvs = region.uvs;\n\n\t\tvertices[RegionAttachment.C1R] = color.r;\n\t\tvertices[RegionAttachment.C1G] = color.g;\n\t\tvertices[RegionAttachment.C1B] = color.b;\n\t\tvertices[RegionAttachment.C1A] = color.a;\n\t\tvertices[RegionAttachment.U1] = uvs[0];\n\t\tvertices[RegionAttachment.V1] = uvs[1];\n\n\t\tvertices[RegionAttachment.C2R] = color.r;\n\t\tvertices[RegionAttachment.C2G] = color.g;\n\t\tvertices[RegionAttachment.C2B] = color.b;\n\t\tvertices[RegionAttachment.C2A] = color.a;\n\t\tvertices[RegionAttachment.U2] = uvs[2];\n\t\tvertices[RegionAttachment.V2] = uvs[3];\n\n\t\tvertices[RegionAttachment.C3R] = color.r;\n\t\tvertices[RegionAttachment.C3G] = color.g;\n\t\tvertices[RegionAttachment.C3B] = color.b;\n\t\tvertices[RegionAttachment.C3A] = color.a;\n\t\tvertices[RegionAttachment.U3] = uvs[4];\n\t\tvertices[RegionAttachment.V3] = uvs[5];\n\n\t\tvertices[RegionAttachment.C4R] = color.r;\n\t\tvertices[RegionAttachment.C4G] = color.g;\n\t\tvertices[RegionAttachment.C4B] = color.b;\n\t\tvertices[RegionAttachment.C4A] = color.a;\n\t\tvertices[RegionAttachment.U4] = uvs[6];\n\t\tvertices[RegionAttachment.V4] = uvs[7];\n\n\t\treturn vertices;\n\t}\n\n\tprivate computeMeshVertices (slot: Slot, mesh: MeshAttachment, pma: boolean) {\n\t\tlet skeletonColor = slot.bone.skeleton.color;\n\t\tlet slotColor = slot.color;\n\t\tlet regionColor = mesh.color;\n\t\tlet alpha = skeletonColor.a * slotColor.a * regionColor.a;\n\t\tlet multiplier = pma ? alpha : 1;\n\t\tlet color = this.tempColor;\n\t\tcolor.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,\n\t\t\tskeletonColor.g * slotColor.g * regionColor.g * multiplier,\n\t\t\tskeletonColor.b * slotColor.b * regionColor.b * multiplier,\n\t\t\talpha);\n\n\t\tlet vertexCount = mesh.worldVerticesLength / 2;\n\t\tlet vertices = this.vertices;\n\t\tif (vertices.length < mesh.worldVerticesLength) this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength);\n\t\tmesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);\n\n\t\tlet uvs = mesh.uvs;\n\t\tfor (let i = 0, u = 0, v = 2; i < vertexCount; i++) {\n\t\t\tvertices[v++] = color.r;\n\t\t\tvertices[v++] = color.g;\n\t\t\tvertices[v++] = color.b;\n\t\t\tvertices[v++] = color.a;\n\t\t\tvertices[v++] = uvs[u++];\n\t\t\tvertices[v++] = uvs[u++];\n\t\t\tv += 2;\n\t\t}\n\n\t\treturn vertices;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport * from \"./require-shim.js\"\nexport * from \"./SpinePlugin.js\"\nexport * from \"./SpineGameObject.js\"\nexport * from \"./mixins.js\"\nexport * from \"@esotericsoftware/spine-core\";\nexport * from \"@esotericsoftware/spine-webgl\";\nimport { SpineGameObjectConfig, SpinePlugin } from \"./SpinePlugin.js\";\n(window as any).spine = { SpinePlugin: SpinePlugin };\n(window as any)[\"spine.SpinePlugin\"] = SpinePlugin;\n\nimport { SpineGameObject, SpineGameObjectBoundsProvider } from \"./SpineGameObject.js\";\n\ndeclare global {\n\tnamespace Phaser.Loader {\n\t\texport interface LoaderPlugin {\n\t\t\tspineJson (key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin;\n\t\t\tspineBinary (key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin;\n\t\t\tspineAtlas (key: string, url: string, premultipliedAlpha?: boolean, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin;\n\t\t}\n\t}\n\n\tnamespace Phaser.GameObjects {\n\t\texport interface GameObjectFactory {\n\t\t\tspine (x: number, y: number, dataKey: string, atlasKey: string, boundsProvider?: SpineGameObjectBoundsProvider): SpineGameObject;\n\t\t}\n\n\t\texport interface GameObjectCreator {\n\t\t\tspine (config: SpineGameObjectConfig, addToScene?: boolean): SpineGameObject;\n\t\t}\n\t}\n\n\tnamespace Phaser {\n\t\texport interface Scene {\n\t\t\tspine: SpinePlugin;\n\t\t}\n\t}\n}\n"], + "mappings": "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AE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,MAA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G,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,WAAO,KAAK,IAAI,KAAK,IAAI;AAAA,EAC1B;AAAA,EAEA,aAAc,QAA0B;AACvC,QAAI,IAAI,KAAK;AACb,QAAI,IAAI,KAAK;AACb,QAAI,IAAI,OAAO;AACf,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,MAAE,GAAG,IAAI,EAAE,GAAG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", + "names": ["Phaser", "worldVertices", "v", "SequenceMode", "MixBlend", "MixDirection", "x", "y", "i", "vertexAttachment", "constraint", "i", "n", "timeline", "EventType", "TextureFilter", "TextureWrap", "page", "worldVertices", "worldVertices", "Inherit", "s", "PositionMode", "SpacingMode", "RotateMode", "closed", "pathLength", "multiplier", "Physics", "BlendMode", "closed", "AttachmentType", "n", "LinkedMesh", "readTimeline1", "readTimeline2", "timeline", "Matrix4", "Matrix4", "VertexAttributeType", "temp", "ShapeType", "i", "n", "n", "ResizeMode", "bounds", "_SkeletonRenderer", "SkeletonRenderer", "SkeletonRenderer", "SpineSkeletonDataFileType"] +} diff --git a/spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js b/spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js new file mode 100644 index 000000000..34beadeb2 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js @@ -0,0 +1,15445 @@ +"use strict"; +var spine = (() => { + var __create = Object.create; + var __defProp = Object.defineProperty; + var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + var __getOwnPropNames = Object.getOwnPropertyNames; + var __getProtoOf = Object.getPrototypeOf; + var __hasOwnProp = Object.prototype.hasOwnProperty; + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { + get: (a, b) => (typeof require !== "undefined" ? require : a)[b] + }) : x)(function(x) { + if (typeof require !== "undefined") + return require.apply(this, arguments); + throw new Error('Dynamic require of "' + x + '" is not supported'); + }); + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; + }; + var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod + )); + var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; + }; + + // spine-phaser-v3/src/index.ts + var src_exports = {}; + __export(src_exports, { + Alpha: () => Alpha, + AlphaMixin: () => AlphaMixin, + AlphaTimeline: () => AlphaTimeline, + Animation: () => Animation, + AnimationState: () => AnimationState, + AnimationStateAdapter: () => AnimationStateAdapter, + AnimationStateData: () => AnimationStateData, + AssetManager: () => AssetManager, + AssetManagerBase: () => AssetManagerBase, + AtlasAttachmentLoader: () => AtlasAttachmentLoader, + Attachment: () => Attachment, + AttachmentTimeline: () => AttachmentTimeline, + BinaryInput: () => BinaryInput, + BlendMode: () => BlendMode, + Bone: () => Bone, + BoneData: () => BoneData, + BoundingBoxAttachment: () => BoundingBoxAttachment, + CURRENT: () => CURRENT, + CameraController: () => CameraController, + ClippingAttachment: () => ClippingAttachment, + Color: () => Color, + Color2Attribute: () => Color2Attribute, + ColorAttribute: () => ColorAttribute, + ComputedSize: () => ComputedSize, + ComputedSizeMixin: () => ComputedSizeMixin, + ConstraintData: () => ConstraintData, + CurveTimeline: () => CurveTimeline, + CurveTimeline1: () => CurveTimeline1, + CurveTimeline2: () => CurveTimeline2, + DebugUtils: () => DebugUtils, + DeformTimeline: () => DeformTimeline, + Depth: () => Depth, + DepthMixin: () => DepthMixin, + Downloader: () => Downloader, + DrawOrderTimeline: () => DrawOrderTimeline, + Event: () => Event, + EventData: () => EventData, + EventQueue: () => EventQueue, + EventTimeline: () => EventTimeline, + EventType: () => EventType, + FIRST: () => FIRST, + FakeTexture: () => FakeTexture, + Flip: () => Flip, + FlipMixin: () => FlipMixin, + GLTexture: () => GLTexture, + HOLD_FIRST: () => HOLD_FIRST, + HOLD_MIX: () => HOLD_MIX, + HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT, + IkConstraint: () => IkConstraint, + IkConstraintData: () => IkConstraintData, + IkConstraintTimeline: () => IkConstraintTimeline, + Inherit: () => Inherit, + InheritTimeline: () => InheritTimeline, + Input: () => Input, + IntSet: () => IntSet, + Interpolation: () => Interpolation, + LoadingScreen: () => LoadingScreen, + M00: () => M00, + M01: () => M01, + M02: () => M02, + M03: () => M03, + M10: () => M10, + M11: () => M11, + M12: () => M12, + M13: () => M13, + M20: () => M20, + M21: () => M21, + M22: () => M22, + M23: () => M23, + M30: () => M30, + M31: () => M31, + M32: () => M32, + M33: () => M33, + ManagedWebGLRenderingContext: () => ManagedWebGLRenderingContext, + MathUtils: () => MathUtils, + Matrix4: () => Matrix42, + Mesh: () => Mesh, + MeshAttachment: () => MeshAttachment, + MixBlend: () => MixBlend, + MixDirection: () => MixDirection, + Origin: () => Origin, + OriginMixin: () => OriginMixin, + OrthoCamera: () => OrthoCamera, + PathAttachment: () => PathAttachment, + PathConstraint: () => PathConstraint, + PathConstraintData: () => PathConstraintData, + PathConstraintMixTimeline: () => PathConstraintMixTimeline, + PathConstraintPositionTimeline: () => PathConstraintPositionTimeline, + PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline, + Physics: () => Physics, + PhysicsConstraintDampingTimeline: () => PhysicsConstraintDampingTimeline, + PhysicsConstraintGravityTimeline: () => PhysicsConstraintGravityTimeline, + PhysicsConstraintInertiaTimeline: () => PhysicsConstraintInertiaTimeline, + PhysicsConstraintMassTimeline: () => PhysicsConstraintMassTimeline, + PhysicsConstraintMixTimeline: () => PhysicsConstraintMixTimeline, + PhysicsConstraintResetTimeline: () => PhysicsConstraintResetTimeline, + PhysicsConstraintStrengthTimeline: () => PhysicsConstraintStrengthTimeline, + PhysicsConstraintTimeline: () => PhysicsConstraintTimeline, + PhysicsConstraintWindTimeline: () => PhysicsConstraintWindTimeline, + PointAttachment: () => PointAttachment, + PolygonBatcher: () => PolygonBatcher, + Pool: () => Pool, + Position2Attribute: () => Position2Attribute, + Position3Attribute: () => Position3Attribute, + PositionMode: () => PositionMode, + Pow: () => Pow, + PowOut: () => PowOut, + RGB2Timeline: () => RGB2Timeline, + RGBA2Timeline: () => RGBA2Timeline, + RGBATimeline: () => RGBATimeline, + RGBTimeline: () => RGBTimeline, + RegionAttachment: () => RegionAttachment, + ResizeMode: () => ResizeMode, + RotateMode: () => RotateMode, + RotateTimeline: () => RotateTimeline, + SETUP: () => SETUP, + SUBSEQUENT: () => SUBSEQUENT, + ScaleTimeline: () => ScaleTimeline, + ScaleXTimeline: () => ScaleXTimeline, + ScaleYTimeline: () => ScaleYTimeline, + SceneRenderer: () => SceneRenderer, + ScrollFactor: () => ScrollFactor, + ScrollFactorMixin: () => ScrollFactorMixin, + SequenceTimeline: () => SequenceTimeline, + SetupPoseBoundsProvider: () => SetupPoseBoundsProvider, + Shader: () => Shader, + ShapeRenderer: () => ShapeRenderer, + ShapeType: () => ShapeType, + ShearTimeline: () => ShearTimeline, + ShearXTimeline: () => ShearXTimeline, + ShearYTimeline: () => ShearYTimeline, + Skeleton: () => Skeleton, + SkeletonBinary: () => SkeletonBinary, + SkeletonBounds: () => SkeletonBounds, + SkeletonClipping: () => SkeletonClipping, + SkeletonData: () => SkeletonData, + SkeletonDebugRenderer: () => SkeletonDebugRenderer, + SkeletonJson: () => SkeletonJson, + SkeletonRenderer: () => SkeletonRenderer, + Skin: () => Skin, + SkinEntry: () => SkinEntry, + SkinsAndAnimationBoundsProvider: () => SkinsAndAnimationBoundsProvider, + Slot: () => Slot, + SlotData: () => SlotData, + SpacingMode: () => SpacingMode, + SpineCanvas: () => SpineCanvas, + SpineGameObject: () => SpineGameObject, + SpinePlugin: () => SpinePlugin, + StringSet: () => StringSet, + TexCoordAttribute: () => TexCoordAttribute, + Texture: () => Texture, + TextureAtlas: () => TextureAtlas, + TextureAtlasPage: () => TextureAtlasPage, + TextureAtlasRegion: () => TextureAtlasRegion, + TextureFilter: () => TextureFilter, + TextureRegion: () => TextureRegion, + TextureWrap: () => TextureWrap, + TimeKeeper: () => TimeKeeper, + Timeline: () => Timeline, + Touch: () => Touch, + TrackEntry: () => TrackEntry, + Transform: () => Transform, + TransformConstraint: () => TransformConstraint, + TransformConstraintData: () => TransformConstraintData, + TransformConstraintTimeline: () => TransformConstraintTimeline, + TransformMixin: () => TransformMixin, + TranslateTimeline: () => TranslateTimeline, + TranslateXTimeline: () => TranslateXTimeline, + TranslateYTimeline: () => TranslateYTimeline, + Triangulator: () => Triangulator, + Utils: () => Utils, + Vector2: () => Vector2, + Vector3: () => Vector3, + VertexAttachment: () => VertexAttachment, + VertexAttribute: () => VertexAttribute, + VertexAttributeType: () => VertexAttributeType, + Visible: () => Visible, + VisibleMixin: () => VisibleMixin, + WindowedMean: () => WindowedMean, + createMixin: () => createMixin + }); + + // spine-phaser-v3/src/require-shim.ts + if (typeof window !== "undefined" && window.Phaser) { + let prevRequire = window.require; + window.require = (x) => { + if (prevRequire) + return prevRequire(x); + else if (x === "Phaser") + return window.Phaser; + }; + } + + // spine-phaser-v3/src/SpinePlugin.ts + var Phaser2 = __toESM(__require("Phaser"), 1); + + // spine-phaser-v3/src/keys.ts + var SPINE_SKELETON_FILE_CACHE_KEY = "esotericsoftware.spine.skeletonFile.cache"; + var SPINE_ATLAS_CACHE_KEY = "esotericsoftware.spine.atlas.cache"; + var SPINE_SKELETON_DATA_FILE_TYPE = "spineSkeletonData"; + var SPINE_ATLAS_FILE_TYPE = "spineAtlasData"; + var SPINE_GAME_OBJECT_TYPE = "spine"; + + // spine-core/src/Utils.ts + var IntSet = class { + array = new Array(); + add(value) { + let contains = this.contains(value); + this.array[value | 0] = value | 0; + return !contains; + } + contains(value) { + return this.array[value | 0] != void 0; + } + remove(value) { + this.array[value | 0] = void 0; + } + clear() { + this.array.length = 0; + } + }; + var StringSet = class { + entries = {}; + size = 0; + add(value) { + let contains = this.entries[value]; + this.entries[value] = true; + if (!contains) { + this.size++; + return true; + } + return false; + } + addAll(values) { + let oldSize = this.size; + for (var i = 0, n = values.length; i < n; i++) + this.add(values[i]); + return oldSize != this.size; + } + contains(value) { + return this.entries[value]; + } + clear() { + this.entries = {}; + this.size = 0; + } + }; + var _Color = class { + constructor(r = 0, g = 0, b = 0, a = 0) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + set(r, g, b, a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this.clamp(); + } + setFromColor(c) { + this.r = c.r; + this.g = c.g; + this.b = c.b; + this.a = c.a; + return this; + } + setFromString(hex) { + hex = hex.charAt(0) == "#" ? hex.substr(1) : hex; + this.r = parseInt(hex.substr(0, 2), 16) / 255; + this.g = parseInt(hex.substr(2, 2), 16) / 255; + this.b = parseInt(hex.substr(4, 2), 16) / 255; + this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255; + return this; + } + add(r, g, b, a) { + this.r += r; + this.g += g; + this.b += b; + this.a += a; + return this.clamp(); + } + clamp() { + if (this.r < 0) + this.r = 0; + else if (this.r > 1) + this.r = 1; + if (this.g < 0) + this.g = 0; + else if (this.g > 1) + this.g = 1; + if (this.b < 0) + this.b = 0; + else if (this.b > 1) + this.b = 1; + if (this.a < 0) + this.a = 0; + else if (this.a > 1) + this.a = 1; + return this; + } + static rgba8888ToColor(color, value) { + color.r = ((value & 4278190080) >>> 24) / 255; + color.g = ((value & 16711680) >>> 16) / 255; + color.b = ((value & 65280) >>> 8) / 255; + color.a = (value & 255) / 255; + } + static rgb888ToColor(color, value) { + color.r = ((value & 16711680) >>> 16) / 255; + color.g = ((value & 65280) >>> 8) / 255; + color.b = (value & 255) / 255; + } + toRgb888() { + const hex = (x) => ("0" + (x * 255).toString(16)).slice(-2); + return Number("0x" + hex(this.r) + hex(this.g) + hex(this.b)); + } + static fromString(hex) { + return new _Color().setFromString(hex); + } + }; + var Color = _Color; + __publicField(Color, "WHITE", new _Color(1, 1, 1, 1)); + __publicField(Color, "RED", new _Color(1, 0, 0, 1)); + __publicField(Color, "GREEN", new _Color(0, 1, 0, 1)); + __publicField(Color, "BLUE", new _Color(0, 0, 1, 1)); + __publicField(Color, "MAGENTA", new _Color(1, 0, 1, 1)); + var _MathUtils = class { + static clamp(value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + } + static cosDeg(degrees) { + return Math.cos(degrees * _MathUtils.degRad); + } + static sinDeg(degrees) { + return Math.sin(degrees * _MathUtils.degRad); + } + static atan2Deg(y, x) { + return Math.atan2(y, x) * _MathUtils.degRad; + } + static signum(value) { + return value > 0 ? 1 : value < 0 ? -1 : 0; + } + static toInt(x) { + return x > 0 ? Math.floor(x) : Math.ceil(x); + } + static cbrt(x) { + let y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; + } + static randomTriangular(min, max) { + return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5); + } + static randomTriangularWith(min, max, mode) { + let u = Math.random(); + let d = max - min; + if (u <= (mode - min) / d) + return min + Math.sqrt(u * d * (mode - min)); + return max - Math.sqrt((1 - u) * d * (max - mode)); + } + static isPowerOfTwo(value) { + return value && (value & value - 1) === 0; + } + }; + var MathUtils = _MathUtils; + __publicField(MathUtils, "PI", 3.1415927); + __publicField(MathUtils, "PI2", _MathUtils.PI * 2); + __publicField(MathUtils, "invPI2", 1 / _MathUtils.PI2); + __publicField(MathUtils, "radiansToDegrees", 180 / _MathUtils.PI); + __publicField(MathUtils, "radDeg", _MathUtils.radiansToDegrees); + __publicField(MathUtils, "degreesToRadians", _MathUtils.PI / 180); + __publicField(MathUtils, "degRad", _MathUtils.degreesToRadians); + var Interpolation = class { + apply(start, end, a) { + return start + (end - start) * this.applyInternal(a); + } + }; + var Pow = class extends Interpolation { + power = 2; + constructor(power) { + super(); + this.power = power; + } + applyInternal(a) { + if (a <= 0.5) + return Math.pow(a * 2, this.power) / 2; + return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1; + } + }; + var PowOut = class extends Pow { + constructor(power) { + super(power); + } + applyInternal(a) { + return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1; + } + }; + var _Utils = class { + static arrayCopy(source, sourceStart, dest, destStart, numElements) { + for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) { + dest[j] = source[i]; + } + } + static arrayFill(array, fromIndex, toIndex, value) { + for (let i = fromIndex; i < toIndex; i++) + array[i] = value; + } + static setArraySize(array, size, value = 0) { + let oldSize = array.length; + if (oldSize == size) + return array; + array.length = size; + if (oldSize < size) { + for (let i = oldSize; i < size; i++) + array[i] = value; + } + return array; + } + static ensureArrayCapacity(array, size, value = 0) { + if (array.length >= size) + return array; + return _Utils.setArraySize(array, size, value); + } + static newArray(size, defaultValue) { + let array = new Array(size); + for (let i = 0; i < size; i++) + array[i] = defaultValue; + return array; + } + static newFloatArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Float32Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static newShortArray(size) { + if (_Utils.SUPPORTS_TYPED_ARRAYS) + return new Int16Array(size); + else { + let array = new Array(size); + for (let i = 0; i < array.length; i++) + array[i] = 0; + return array; + } + } + static toFloatArray(array) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array; + } + static toSinglePrecision(value) { + return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value; + } + // This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109 + static webkit602BugfixHelper(alpha, blend) { + } + static contains(array, element, identity = true) { + for (var i = 0; i < array.length; i++) + if (array[i] == element) + return true; + return false; + } + static enumValue(type, name) { + return type[name[0].toUpperCase() + name.slice(1)]; + } + }; + var Utils = _Utils; + __publicField(Utils, "SUPPORTS_TYPED_ARRAYS", typeof Float32Array !== "undefined"); + var DebugUtils = class { + static logBones(skeleton) { + for (let i = 0; i < skeleton.bones.length; i++) { + let bone = skeleton.bones[i]; + console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY); + } + } + }; + var Pool = class { + items = new Array(); + instantiator; + constructor(instantiator) { + this.instantiator = instantiator; + } + obtain() { + return this.items.length > 0 ? this.items.pop() : this.instantiator(); + } + free(item) { + if (item.reset) + item.reset(); + this.items.push(item); + } + freeAll(items) { + for (let i = 0; i < items.length; i++) + this.free(items[i]); + } + clear() { + this.items.length = 0; + } + }; + var Vector2 = class { + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } + set(x, y) { + this.x = x; + this.y = y; + return this; + } + length() { + let x = this.x; + let y = this.y; + return Math.sqrt(x * x + y * y); + } + normalize() { + let len = this.length(); + if (len != 0) { + this.x /= len; + this.y /= len; + } + return this; + } + }; + var TimeKeeper = class { + maxDelta = 0.064; + framesPerSecond = 0; + delta = 0; + totalTime = 0; + lastTime = Date.now() / 1e3; + frameCount = 0; + frameTime = 0; + update() { + let now = Date.now() / 1e3; + this.delta = now - this.lastTime; + this.frameTime += this.delta; + this.totalTime += this.delta; + if (this.delta > this.maxDelta) + this.delta = this.maxDelta; + this.lastTime = now; + this.frameCount++; + if (this.frameTime > 1) { + this.framesPerSecond = this.frameCount / this.frameTime; + this.frameTime = 0; + this.frameCount = 0; + } + } + }; + var WindowedMean = class { + values; + addedValues = 0; + lastValue = 0; + mean = 0; + dirty = true; + constructor(windowSize = 32) { + this.values = new Array(windowSize); + } + hasEnoughData() { + return this.addedValues >= this.values.length; + } + addValue(value) { + if (this.addedValues < this.values.length) + this.addedValues++; + this.values[this.lastValue++] = value; + if (this.lastValue > this.values.length - 1) + this.lastValue = 0; + this.dirty = true; + } + getMean() { + if (this.hasEnoughData()) { + if (this.dirty) { + let mean = 0; + for (let i = 0; i < this.values.length; i++) + mean += this.values[i]; + this.mean = mean / this.values.length; + this.dirty = false; + } + return this.mean; + } + return 0; + } + }; + + // spine-core/src/attachments/Attachment.ts + var Attachment = class { + name; + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + }; + var _VertexAttachment = class extends Attachment { + /** The unique ID for this attachment. */ + id = _VertexAttachment.nextID++; + /** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting + * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null + * if this attachment has no weights. */ + bones = null; + /** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y` + * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting + * each vertex. */ + vertices = []; + /** The maximum number of world vertex values that can be output by + * {@link #computeWorldVertices()} using the `count` parameter. */ + worldVerticesLength = 0; + /** Timelines for the timeline attachment are also applied to this attachment. + * May be null if no attachment-specific timelines should be applied. */ + timelineAttachment = this; + constructor(name) { + super(name); + } + /** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is + * not empty, it is used to deform the vertices. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. + * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y. + * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`. + * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` * + * `stride` / 2. + * @param offset The `worldVertices` index to begin writing values. + * @param stride The number of `worldVertices` entries between the value pairs written. */ + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + count = offset + (count >> 1) * stride; + let skeleton = slot.bone.skeleton; + let deformArray = slot.deform; + let vertices = this.vertices; + let bones = this.bones; + if (!bones) { + if (deformArray.length > 0) + vertices = deformArray; + let bone = slot.bone; + let x = bone.worldX; + let y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) { + let vx = vertices[v2], vy = vertices[v2 + 1]; + worldVertices2[w] = vx * a + vy * b + x; + worldVertices2[w + 1] = vx * c + vy * d + y; + } + return; + } + let v = 0, skip = 0; + for (let i = 0; i < start; i += 2) { + let n = bones[v]; + v += n + 1; + skip += n; + } + let skeletonBones = skeleton.bones; + if (deformArray.length == 0) { + for (let w = offset, b = skip * 3; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } else { + let deform = deformArray; + for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { + let wx = 0, wy = 0; + let n = bones[v++]; + n += v; + for (; v < n; v++, b += 3, f += 2) { + let bone = skeletonBones[bones[v]]; + let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; + wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; + wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; + } + worldVertices2[w] = wx; + worldVertices2[w + 1] = wy; + } + } + } + /** Does not copy id (generated) or name (set on construction). **/ + copyTo(attachment) { + if (this.bones) { + attachment.bones = new Array(this.bones.length); + Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length); + } else + attachment.bones = null; + if (this.vertices) { + attachment.vertices = Utils.newFloatArray(this.vertices.length); + Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length); + } + attachment.worldVerticesLength = this.worldVerticesLength; + attachment.timelineAttachment = this.timelineAttachment; + } + }; + var VertexAttachment = _VertexAttachment; + __publicField(VertexAttachment, "nextID", 0); + + // spine-core/src/attachments/Sequence.ts + var _Sequence = class { + id = _Sequence.nextID(); + regions; + start = 0; + digits = 0; + /** The index of the region to show for the setup pose. */ + setupIndex = 0; + constructor(count) { + this.regions = new Array(count); + } + copy() { + let copy = new _Sequence(this.regions.length); + Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length); + copy.start = this.start; + copy.digits = this.digits; + copy.setupIndex = this.setupIndex; + return copy; + } + apply(slot, attachment) { + let index = slot.sequenceIndex; + if (index == -1) + index = this.setupIndex; + if (index >= this.regions.length) + index = this.regions.length - 1; + let region = this.regions[index]; + if (attachment.region != region) { + attachment.region = region; + attachment.updateRegion(); + } + } + getPath(basePath, index) { + let result = basePath; + let frame = (this.start + index).toString(); + for (let i = this.digits - frame.length; i > 0; i--) + result += "0"; + result += frame; + return result; + } + static nextID() { + return _Sequence._nextID++; + } + }; + var Sequence = _Sequence; + __publicField(Sequence, "_nextID", 0); + var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => { + SequenceMode2[SequenceMode2["hold"] = 0] = "hold"; + SequenceMode2[SequenceMode2["once"] = 1] = "once"; + SequenceMode2[SequenceMode2["loop"] = 2] = "loop"; + SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong"; + SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse"; + SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse"; + SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse"; + return SequenceMode2; + })(SequenceMode || {}); + var SequenceModeValues = [ + 0 /* hold */, + 1 /* once */, + 2 /* loop */, + 3 /* pingpong */, + 4 /* onceReverse */, + 5 /* loopReverse */, + 6 /* pingpongReverse */ + ]; + + // spine-core/src/Animation.ts + var Animation = class { + /** The animation's name, which is unique across all animations in the skeleton. */ + name; + timelines = []; + timelineIds = new StringSet(); + /** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */ + duration; + constructor(name, timelines, duration) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + this.setTimelines(timelines); + this.duration = duration; + } + setTimelines(timelines) { + if (!timelines) + throw new Error("timelines cannot be null."); + this.timelines = timelines; + this.timelineIds.clear(); + for (var i = 0; i < timelines.length; i++) + this.timelineIds.addAll(timelines[i].getPropertyIds()); + } + hasTimeline(ids) { + for (let i = 0; i < ids.length; i++) + if (this.timelineIds.contains(ids[i])) + return true; + return false; + } + /** Applies all the animation's timelines to the specified skeleton. + * + * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. + * @param loop If true, the animation repeats after {@link #getDuration()}. + * @param events May be null to ignore fired events. */ + apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (loop && this.duration != 0) { + time %= this.duration; + if (lastTime > 0) + lastTime %= this.duration; + } + let timelines = this.timelines; + for (let i = 0, n = timelines.length; i < n; i++) + timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction); + } + }; + var MixBlend = /* @__PURE__ */ ((MixBlend2) => { + MixBlend2[MixBlend2["setup"] = 0] = "setup"; + MixBlend2[MixBlend2["first"] = 1] = "first"; + MixBlend2[MixBlend2["replace"] = 2] = "replace"; + MixBlend2[MixBlend2["add"] = 3] = "add"; + return MixBlend2; + })(MixBlend || {}); + var MixDirection = /* @__PURE__ */ ((MixDirection2) => { + MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn"; + MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut"; + return MixDirection2; + })(MixDirection || {}); + var Property = { + rotate: 0, + x: 1, + y: 2, + scaleX: 3, + scaleY: 4, + shearX: 5, + shearY: 6, + inherit: 7, + rgb: 8, + alpha: 9, + rgb2: 10, + attachment: 11, + deform: 12, + event: 13, + drawOrder: 14, + ikConstraint: 15, + transformConstraint: 16, + pathConstraintPosition: 17, + pathConstraintSpacing: 18, + pathConstraintMix: 19, + physicsConstraintInertia: 20, + physicsConstraintStrength: 21, + physicsConstraintDamping: 22, + physicsConstraintMass: 23, + physicsConstraintWind: 24, + physicsConstraintGravity: 25, + physicsConstraintMix: 26, + physicsConstraintReset: 27, + sequence: 28 + }; + var Timeline = class { + propertyIds; + frames; + constructor(frameCount, propertyIds) { + this.propertyIds = propertyIds; + this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries()); + } + getPropertyIds() { + return this.propertyIds; + } + getFrameEntries() { + return 1; + } + getFrameCount() { + return this.frames.length / this.getFrameEntries(); + } + getDuration() { + return this.frames[this.frames.length - this.getFrameEntries()]; + } + static search1(frames, time) { + let n = frames.length; + for (let i = 1; i < n; i++) + if (frames[i] > time) + return i - 1; + return n - 1; + } + static search(frames, time, step) { + let n = frames.length; + for (let i = step; i < n; i += step) + if (frames[i] > time) + return i - step; + return n - step; + } + }; + var CurveTimeline = class extends Timeline { + curves; + // type, x, y, ... + constructor(frameCount, bezierCount, propertyIds) { + super(frameCount, propertyIds); + this.curves = Utils.newFloatArray( + frameCount + bezierCount * 18 + /*BEZIER_SIZE*/ + ); + this.curves[frameCount - 1] = 1; + } + /** Sets the specified key frame to linear interpolation. */ + setLinear(frame) { + this.curves[frame] = 0; + } + /** Sets the specified key frame to stepped interpolation. */ + setStepped(frame) { + this.curves[frame] = 1; + } + /** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger + * than the actual number of Bezier curves. */ + shrink(bezierCount) { + let size = this.getFrameCount() + bezierCount * 18; + if (this.curves.length > size) { + let newCurves = Utils.newFloatArray(size); + Utils.arrayCopy(this.curves, 0, newCurves, 0, size); + this.curves = newCurves; + } + } + /** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than + * one curve per frame. + * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified + * in the constructor), inclusive. + * @param frame Between 0 and frameCount - 1, inclusive. + * @param value The index of the value for this frame that this curve is used for. + * @param time1 The time for the first key. + * @param value1 The value for the first key. + * @param cx1 The time for the first Bezier handle. + * @param cy1 The value for the first Bezier handle. + * @param cx2 The time of the second Bezier handle. + * @param cy2 The value for the second Bezier handle. + * @param time2 The time for the second key. + * @param value2 The value for the second key. */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = value1 + dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + /** Returns the Bezier interpolated value for the specified time. + * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time. + * @param valueOffset The offset from frameIndex to the value this curve is used for. + * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */ + getBezierValue(time, frameIndex, valueOffset, i) { + let curves = this.curves; + if (curves[i] > time) { + let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + frameIndex += this.getFrameEntries(); + let x = curves[n - 2], y = curves[n - 1]; + return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y); + } + }; + var CurveTimeline1 = class extends CurveTimeline { + constructor(frameCount, bezierCount, propertyId) { + super(frameCount, bezierCount, [propertyId]); + } + getFrameEntries() { + return 2; + } + /** Sets the time and value for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value) { + frame <<= 1; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE*/ + ] = value; + } + /** Returns the interpolated value for the specified time. */ + getCurveValue(time) { + let frames = this.frames; + let i = frames.length - 2; + for (let ii = 2; ii <= i; ii += 2) { + if (frames[ii] > time) { + i = ii - 2; + break; + } + } + let curveType = this.curves[i >> 1]; + switch (curveType) { + case 0: + let before = frames[i], value = frames[ + i + 1 + /*VALUE*/ + ]; + return value + (time - before) / (frames[ + i + 2 + /*ENTRIES*/ + ] - before) * (frames[ + i + 2 + 1 + /*VALUE*/ + ] - value); + case 1: + return frames[ + i + 1 + /*VALUE*/ + ]; + } + return this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + } + getRelativeValue(time, alpha, blend, current, setup) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time); + switch (blend) { + case 0 /* setup */: + return setup + value * alpha; + case 1 /* first */: + case 2 /* replace */: + value += setup - current; + } + return current + value * alpha; + } + getAbsoluteValue(time, alpha, blend, current, setup) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time); + if (blend == 0 /* setup */) + return setup + (value - setup) * alpha; + return current + (value - current) * alpha; + } + getAbsoluteValue2(time, alpha, blend, current, setup, value) { + if (time < this.frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + if (blend == 0 /* setup */) + return setup + (value - setup) * alpha; + return current + (value - current) * alpha; + } + getScaleValue(time, alpha, blend, direction, current, setup) { + const frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + return setup; + case 1 /* first */: + return current + (setup - current) * alpha; + } + return current; + } + let value = this.getCurveValue(time) * setup; + if (alpha == 1) { + if (blend == 3 /* add */) + return current + value - setup; + return value; + } + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + return setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha; + case 1 /* first */: + case 2 /* replace */: + return current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha; + } + } else { + let s = 0; + switch (blend) { + case 0 /* setup */: + s = Math.abs(setup) * MathUtils.signum(value); + return s + (value - s) * alpha; + case 1 /* first */: + case 2 /* replace */: + s = Math.abs(current) * MathUtils.signum(value); + return s + (value - s) * alpha; + } + } + return current + (value - setup) * alpha; + } + }; + var CurveTimeline2 = class extends CurveTimeline { + /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. + * @param propertyIds Unique identifiers for the properties the timeline modifies. */ + constructor(frameCount, bezierCount, propertyId1, propertyId2) { + super(frameCount, bezierCount, [propertyId1, propertyId2]); + } + getFrameEntries() { + return 3; + } + /** Sets the time and values for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, value1, value2) { + frame *= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*VALUE1*/ + ] = value1; + this.frames[ + frame + 2 + /*VALUE2*/ + ] = value2; + } + }; + var RotateTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.rotate + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.rotation = this.getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation); + } + }; + var TranslateTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.x + "|" + boneIndex, + Property.y + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case 1 /* first */: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + break; + case 3 /* add */: + bone.x += x * alpha; + bone.y += y * alpha; + } + } + }; + var TranslateXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.x + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.x = this.getRelativeValue(time, alpha, blend, bone.x, bone.data.x); + } + }; + var TranslateYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.y + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.y = this.getRelativeValue(time, alpha, blend, bone.y, bone.data.y); + } + }; + var ScaleTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.scaleX + "|" + boneIndex, + Property.scaleY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case 1 /* first */: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + } + return; + } + let x, y; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + x *= bone.data.scaleX; + y *= bone.data.scaleY; + if (alpha == 1) { + if (blend == 3 /* add */) { + bone.scaleX += x - bone.data.scaleX; + bone.scaleY += y - bone.data.scaleY; + } else { + bone.scaleX = x; + bone.scaleY = y; + } + } else { + let bx = 0, by = 0; + if (direction == 1 /* mixOut */) { + switch (blend) { + case 0 /* setup */: + bx = bone.data.scaleX; + by = bone.data.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = bone.scaleX; + by = bone.scaleY; + bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha; + bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } else { + switch (blend) { + case 0 /* setup */: + bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.data.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bx = Math.abs(bone.scaleX) * MathUtils.signum(x); + by = Math.abs(bone.scaleY) * MathUtils.signum(y); + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + break; + case 3 /* add */: + bone.scaleX += (x - bone.data.scaleX) * alpha; + bone.scaleY += (y - bone.data.scaleY) * alpha; + } + } + } + } + }; + var ScaleXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.scaleX = this.getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX); + } + }; + var ScaleYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.scaleY = this.getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY); + } + }; + var ShearTimeline = class extends CurveTimeline2 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super( + frameCount, + bezierCount, + Property.shearX + "|" + boneIndex, + Property.shearY + "|" + boneIndex + ); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case 1 /* first */: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + } + return; + } + let x = 0, y = 0; + let i = Timeline.search( + frames, + time, + 3 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 3 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + let t = (time - before) / (frames[ + i + 3 + /*ENTRIES*/ + ] - before); + x += (frames[ + i + 3 + 1 + /*VALUE1*/ + ] - x) * t; + y += (frames[ + i + 3 + 2 + /*VALUE2*/ + ] - y) * t; + break; + case 1: + x = frames[ + i + 1 + /*VALUE1*/ + ]; + y = frames[ + i + 2 + /*VALUE2*/ + ]; + break; + default: + x = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + switch (blend) { + case 0 /* setup */: + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + break; + case 1 /* first */: + case 2 /* replace */: + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + break; + case 3 /* add */: + bone.shearX += x * alpha; + bone.shearY += y * alpha; + } + } + }; + var ShearXTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearX + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.shearX = this.getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX); + } + }; + var ShearYTimeline = class extends CurveTimeline1 { + boneIndex = 0; + constructor(frameCount, bezierCount, boneIndex) { + super(frameCount, bezierCount, Property.shearY + "|" + boneIndex); + this.boneIndex = boneIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (bone.active) + bone.shearY = this.getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY); + } + }; + var InheritTimeline = class extends Timeline { + boneIndex = 0; + constructor(frameCount, boneIndex) { + super(frameCount, [Property.inherit + "|" + boneIndex]); + this.boneIndex = boneIndex; + } + getFrameEntries() { + return 2; + } + /** Sets the transform mode for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time The frame time in seconds. */ + setFrame(frame, time, inherit) { + frame *= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*INHERIT*/ + ] = inherit; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let bone = skeleton.bones[this.boneIndex]; + if (!bone.active) + return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + bone.inherit = bone.data.inherit; + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + bone.inherit = bone.data.inherit; + return; + } + bone.inherit = this.frames[ + Timeline.search( + frames, + time, + 2 + /*ENTRIES*/ + ) + 1 + /*INHERIT*/ + ]; + } + }; + var RGBATimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 5; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b, a) { + frame *= 5; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.setFromColor(setup); + return; + case 1 /* first */: + color.add( + (setup.r - color.r) * alpha, + (setup.g - color.g) * alpha, + (setup.b - color.b) * alpha, + (setup.a - color.a) * alpha + ); + } + return; + } + let r = 0, g = 0, b = 0, a = 0; + let i = Timeline.search( + frames, + time, + 5 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 5 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + let t = (time - before) / (frames[ + i + 5 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 5 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 5 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 5 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 5 + 4 + /*A*/ + ] - a) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) + color.set(r, g, b, a); + else { + if (blend == 0 /* setup */) + color.setFromColor(slot.data.color); + color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha); + } + } + }; + var RGBTimeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 4; + } + /** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */ + setFrame(frame, time, r, g, b) { + frame <<= 2; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let color = slot.color; + if (time < frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + return; + case 1 /* first */: + color.r += (setup.r - color.r) * alpha; + color.g += (setup.g - color.g) * alpha; + color.b += (setup.b - color.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 4 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 4 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 4 + 3 + /*B*/ + ] - b) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + color.r = r; + color.g = g; + color.b = b; + } else { + if (blend == 0 /* setup */) { + let setup = slot.data.color; + color.r = setup.r; + color.g = setup.g; + color.b = setup.b; + } + color.r += (r - color.r) * alpha; + color.g += (g - color.g) * alpha; + color.b += (b - color.b) * alpha; + } + } + }; + var AlphaTimeline = class extends CurveTimeline1 { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, Property.alpha + "|" + slotIndex); + this.slotIndex = slotIndex; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let color = slot.color; + if (time < this.frames[0]) { + let setup = slot.data.color; + switch (blend) { + case 0 /* setup */: + color.a = setup.a; + return; + case 1 /* first */: + color.a += (setup.a - color.a) * alpha; + } + return; + } + let a = this.getCurveValue(time); + if (alpha == 1) + color.a = a; + else { + if (blend == 0 /* setup */) + color.a = slot.data.color.a; + color.a += (a - color.a) * alpha; + } + } + }; + var RGBA2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.alpha + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 8; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, a, r2, g2, b2) { + frame <<= 3; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*A*/ + ] = a; + this.frames[ + frame + 5 + /*R2*/ + ] = r2; + this.frames[ + frame + 6 + /*G2*/ + ] = g2; + this.frames[ + frame + 7 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.setFromColor(setupLight); + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.add( + (setupLight.r - light.r) * alpha, + (setupLight.g - light.g) * alpha, + (setupLight.b - light.b) * alpha, + (setupLight.a - light.a) * alpha + ); + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 8 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 3]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 8 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 8 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 8 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 8 + 3 + /*B*/ + ] - b) * t; + a += (frames[ + i + 8 + 4 + /*A*/ + ] - a) * t; + r2 += (frames[ + i + 8 + 5 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 8 + 6 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 8 + 7 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + a = frames[ + i + 4 + /*A*/ + ]; + r2 = frames[ + i + 5 + /*R2*/ + ]; + g2 = frames[ + i + 6 + /*G2*/ + ]; + b2 = frames[ + i + 7 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + a = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 7, + curveType + 18 * 6 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.set(r, g, b, a); + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + light.setFromColor(slot.data.color); + let setupDark = slot.data.darkColor; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha); + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var RGB2Timeline = class extends CurveTimeline { + slotIndex = 0; + constructor(frameCount, bezierCount, slotIndex) { + super(frameCount, bezierCount, [ + Property.rgb + "|" + slotIndex, + Property.rgb2 + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + } + getFrameEntries() { + return 7; + } + /** Sets the time in seconds, light, and dark colors for the specified key frame. */ + setFrame(frame, time, r, g, b, r2, g2, b2) { + frame *= 7; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*R*/ + ] = r; + this.frames[ + frame + 2 + /*G*/ + ] = g; + this.frames[ + frame + 3 + /*B*/ + ] = b; + this.frames[ + frame + 4 + /*R2*/ + ] = r2; + this.frames[ + frame + 5 + /*G2*/ + ] = g2; + this.frames[ + frame + 6 + /*B2*/ + ] = b2; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let frames = this.frames; + let light = slot.color, dark = slot.darkColor; + if (time < frames[0]) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + switch (blend) { + case 0 /* setup */: + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + return; + case 1 /* first */: + light.r += (setupLight.r - light.r) * alpha; + light.g += (setupLight.g - light.g) * alpha; + light.b += (setupLight.b - light.b) * alpha; + dark.r += (setupDark.r - dark.r) * alpha; + dark.g += (setupDark.g - dark.g) * alpha; + dark.b += (setupDark.b - dark.b) * alpha; + } + return; + } + let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + r += (frames[ + i + 7 + 1 + /*R*/ + ] - r) * t; + g += (frames[ + i + 7 + 2 + /*G*/ + ] - g) * t; + b += (frames[ + i + 7 + 3 + /*B*/ + ] - b) * t; + r2 += (frames[ + i + 7 + 4 + /*R2*/ + ] - r2) * t; + g2 += (frames[ + i + 7 + 5 + /*G2*/ + ] - g2) * t; + b2 += (frames[ + i + 7 + 6 + /*B2*/ + ] - b2) * t; + break; + case 1: + r = frames[ + i + 1 + /*R*/ + ]; + g = frames[ + i + 2 + /*G*/ + ]; + b = frames[ + i + 3 + /*B*/ + ]; + r2 = frames[ + i + 4 + /*R2*/ + ]; + g2 = frames[ + i + 5 + /*G2*/ + ]; + b2 = frames[ + i + 6 + /*B2*/ + ]; + break; + default: + r = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + g = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + b = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + r2 = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + g2 = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + b2 = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (alpha == 1) { + light.r = r; + light.g = g; + light.b = b; + dark.r = r2; + dark.g = g2; + dark.b = b2; + } else { + if (blend == 0 /* setup */) { + let setupLight = slot.data.color, setupDark = slot.data.darkColor; + light.r = setupLight.r; + light.g = setupLight.g; + light.b = setupLight.b; + dark.r = setupDark.r; + dark.g = setupDark.g; + dark.b = setupDark.b; + } + light.r += (r - light.r) * alpha; + light.g += (g - light.g) * alpha; + light.b += (b - light.b) * alpha; + dark.r += (r2 - dark.r) * alpha; + dark.g += (g2 - dark.g) * alpha; + dark.b += (b2 - dark.b) * alpha; + } + } + }; + var AttachmentTimeline = class extends Timeline { + slotIndex = 0; + /** The attachment name for each key frame. May contain null values to clear the attachment. */ + attachmentNames; + constructor(frameCount, slotIndex) { + super(frameCount, [ + Property.attachment + "|" + slotIndex + ]); + this.slotIndex = slotIndex; + this.attachmentNames = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the attachment name for the specified key frame. */ + setFrame(frame, time, attachmentName) { + this.frames[frame] = time; + this.attachmentNames[frame] = attachmentName; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName); + return; + } + this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]); + } + setAttachment(skeleton, slot, attachmentName) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName)); + } + }; + var DeformTimeline = class extends CurveTimeline { + slotIndex = 0; + /** The attachment that will be deformed. */ + attachment; + /** The vertices for each key frame. */ + vertices; + constructor(frameCount, bezierCount, slotIndex, attachment) { + super(frameCount, bezierCount, [ + Property.deform + "|" + slotIndex + "|" + attachment.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + this.vertices = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the vertices for the specified key frame. + * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */ + setFrame(frame, time, vertices) { + this.frames[frame] = time; + this.vertices[frame] = vertices; + } + /** @param value1 Ignored (0 is used for a deform timeline). + * @param value2 Ignored (1 is used for a deform timeline). */ + setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) { + let curves = this.curves; + let i = this.getFrameCount() + bezier * 18; + if (value == 0) + curves[frame] = 2 + i; + let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06; + let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018; + let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy; + let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667; + let x = time1 + dx, y = dy; + for (let n = i + 18; i < n; i += 2) { + curves[i] = x; + curves[i + 1] = y; + dx += ddx; + dy += ddy; + ddx += dddx; + ddy += dddy; + x += dx; + y += dy; + } + } + getCurvePercent(time, frame) { + let curves = this.curves; + let i = curves[frame]; + switch (i) { + case 0: + let x2 = this.frames[frame]; + return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2); + case 1: + return 0; + } + i -= 2; + if (curves[i] > time) { + let x2 = this.frames[frame]; + return curves[i + 1] * (time - x2) / (curves[i] - x2); + } + let n = i + 18; + for (i += 2; i < n; i += 2) { + if (curves[i] >= time) { + let x2 = curves[i - 2], y2 = curves[i - 1]; + return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2); + } + } + let x = curves[n - 2], y = curves[n - 1]; + return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x); + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.getAttachment(); + if (!slotAttachment) + return; + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != this.attachment) + return; + let deform = slot.deform; + if (deform.length == 0) + blend = 0 /* setup */; + let vertices = this.vertices; + let vertexCount = vertices[0].length; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + deform.length = 0; + return; + case 1 /* first */: + if (alpha == 1) { + deform.length = 0; + return; + } + deform.length = vertexCount; + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (var i = 0; i < vertexCount; i++) + deform[i] += (setupVertices[i] - deform[i]) * alpha; + } else { + alpha = 1 - alpha; + for (var i = 0; i < vertexCount; i++) + deform[i] *= alpha; + } + } + return; + } + deform.length = vertexCount; + if (time >= frames[frames.length - 1]) { + let lastVertices = vertices[frames.length - 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] - setupVertices[i2]; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2]; + } + } else + Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount); + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let setup = setupVertices[i2]; + deform[i2] = setup + (lastVertices[i2] - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] = lastVertices[i2] * alpha; + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - deform[i2]) * alpha; + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha; + } else { + for (let i2 = 0; i2 < vertexCount; i2++) + deform[i2] += lastVertices[i2] * alpha; + } + } + } + return; + } + let frame = Timeline.search1(frames, time); + let percent = this.getCurvePercent(time, frame); + let prevVertices = vertices[frame]; + let nextVertices = vertices[frame + 1]; + if (alpha == 1) { + if (blend == 3 /* add */) { + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = prev + (nextVertices[i2] - prev) * percent; + } + } + } else { + switch (blend) { + case 0 /* setup */: { + let vertexAttachment2 = slotAttachment; + if (!vertexAttachment2.bones) { + let setupVertices = vertexAttachment2.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2], setup = setupVertices[i2]; + deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + break; + } + case 1 /* first */: + case 2 /* replace */: + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha; + } + break; + case 3 /* add */: + let vertexAttachment = slotAttachment; + if (!vertexAttachment.bones) { + let setupVertices = vertexAttachment.vertices; + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha; + } + } else { + for (let i2 = 0; i2 < vertexCount; i2++) { + let prev = prevVertices[i2]; + deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha; + } + } + } + } + } + }; + var _EventTimeline = class extends Timeline { + /** The event for each key frame. */ + events; + constructor(frameCount) { + super(frameCount, _EventTimeline.propertyIds); + this.events = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the event for the specified key frame. */ + setFrame(frame, event) { + this.frames[frame] = event.time; + this.events[frame] = event; + } + /** Fires events for frames > `lastTime` and <= `time`. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (!firedEvents) + return; + let frames = this.frames; + let frameCount = this.frames.length; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frameCount - 1]) + return; + if (time < frames[0]) + return; + let i = 0; + if (lastTime < frames[0]) + i = 0; + else { + i = Timeline.search1(frames, lastTime) + 1; + let frameTime = frames[i]; + while (i > 0) { + if (frames[i - 1] != frameTime) + break; + i--; + } + } + for (; i < frameCount && time >= frames[i]; i++) + firedEvents.push(this.events[i]); + } + }; + var EventTimeline = _EventTimeline; + __publicField(EventTimeline, "propertyIds", ["" + Property.event]); + var _DrawOrderTimeline = class extends Timeline { + /** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */ + drawOrders; + constructor(frameCount) { + super(frameCount, _DrawOrderTimeline.propertyIds); + this.drawOrders = new Array(frameCount); + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time in seconds and the draw order for the specified key frame. + * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose + * draw order. */ + setFrame(frame, time, drawOrder) { + this.frames[frame] = time; + this.drawOrders[frame] = drawOrder; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + if (time < this.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + return; + } + let idx = Timeline.search1(this.frames, time); + let drawOrderToSetupIndex = this.drawOrders[idx]; + if (!drawOrderToSetupIndex) + Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length); + else { + let drawOrder = skeleton.drawOrder; + let slots = skeleton.slots; + for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++) + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + } + }; + var DrawOrderTimeline = _DrawOrderTimeline; + __publicField(DrawOrderTimeline, "propertyIds", ["" + Property.drawOrder]); + var IkConstraintTimeline = class extends CurveTimeline { + /** The index of the IK constraint in {@link Skeleton#getIkConstraints()} that will be changed when this timeline is applied */ + constraintIndex = 0; + constructor(frameCount, bezierCount, ikConstraintIndex) { + super(frameCount, bezierCount, [ + Property.ikConstraint + "|" + ikConstraintIndex + ]); + this.constraintIndex = ikConstraintIndex; + } + getFrameEntries() { + return 6; + } + /** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */ + setFrame(frame, time, mix, softness, bendDirection, compress, stretch) { + frame *= 6; + this.frames[frame] = time; + this.frames[ + frame + 1 + /*MIX*/ + ] = mix; + this.frames[ + frame + 2 + /*SOFTNESS*/ + ] = softness; + this.frames[ + frame + 3 + /*BEND_DIRECTION*/ + ] = bendDirection; + this.frames[ + frame + 4 + /*COMPRESS*/ + ] = compress ? 1 : 0; + this.frames[ + frame + 5 + /*STRETCH*/ + ] = stretch ? 1 : 0; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.ikConstraints[this.constraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mix = constraint.data.mix; + constraint.softness = constraint.data.softness; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + return; + case 1 /* first */: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.softness += (constraint.data.softness - constraint.softness) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } + return; + } + let mix = 0, softness = 0; + let i = Timeline.search( + frames, + time, + 6 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 6 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + let t = (time - before) / (frames[ + i + 6 + /*ENTRIES*/ + ] - before); + mix += (frames[ + i + 6 + 1 + /*MIX*/ + ] - mix) * t; + softness += (frames[ + i + 6 + 2 + /*SOFTNESS*/ + ] - softness) * t; + break; + case 1: + mix = frames[ + i + 1 + /*MIX*/ + ]; + softness = frames[ + i + 2 + /*SOFTNESS*/ + ]; + break; + default: + mix = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + softness = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha; + constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha; + if (direction == 1 /* mixOut */) { + constraint.bendDirection = constraint.data.bendDirection; + constraint.compress = constraint.data.compress; + constraint.stretch = constraint.data.stretch; + } else { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } else { + constraint.mix += (mix - constraint.mix) * alpha; + constraint.softness += (softness - constraint.softness) * alpha; + if (direction == 0 /* mixIn */) { + constraint.bendDirection = frames[ + i + 3 + /*BEND_DIRECTION*/ + ]; + constraint.compress = frames[ + i + 4 + /*COMPRESS*/ + ] != 0; + constraint.stretch = frames[ + i + 5 + /*STRETCH*/ + ] != 0; + } + } + } + }; + var TransformConstraintTimeline = class extends CurveTimeline { + /** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, transformConstraintIndex) { + super(frameCount, bezierCount, [ + Property.transformConstraint + "|" + transformConstraintIndex + ]); + this.constraintIndex = transformConstraintIndex; + } + getFrameEntries() { + return 7; + } + /** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */ + setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) { + let frames = this.frames; + frame *= 7; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + frames[ + frame + 4 + /*SCALEX*/ + ] = mixScaleX; + frames[ + frame + 5 + /*SCALEY*/ + ] = mixScaleY; + frames[ + frame + 6 + /*SHEARY*/ + ] = mixShearY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.transformConstraints[this.constraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + let data = constraint.data; + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = data.mixRotate; + constraint.mixX = data.mixX; + constraint.mixY = data.mixY; + constraint.mixScaleX = data.mixScaleX; + constraint.mixScaleY = data.mixScaleY; + constraint.mixShearY = data.mixShearY; + return; + case 1 /* first */: + constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (data.mixX - constraint.mixX) * alpha; + constraint.mixY += (data.mixY - constraint.mixY) * alpha; + constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha; + } + return; + } + let rotate, x, y, scaleX, scaleY, shearY; + let i = Timeline.search( + frames, + time, + 7 + /*ENTRIES*/ + ); + let curveType = this.curves[ + i / 7 + /*ENTRIES*/ + ]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + let t = (time - before) / (frames[ + i + 7 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 7 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 7 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 7 + 3 + /*Y*/ + ] - y) * t; + scaleX += (frames[ + i + 7 + 4 + /*SCALEX*/ + ] - scaleX) * t; + scaleY += (frames[ + i + 7 + 5 + /*SCALEY*/ + ] - scaleY) * t; + shearY += (frames[ + i + 7 + 6 + /*SHEARY*/ + ] - shearY) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + scaleX = frames[ + i + 4 + /*SCALEX*/ + ]; + scaleY = frames[ + i + 5 + /*SCALEY*/ + ]; + shearY = frames[ + i + 6 + /*SHEARY*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + scaleX = this.getBezierValue( + time, + i, + 4, + curveType + 18 * 3 - 2 + /*BEZIER*/ + ); + scaleY = this.getBezierValue( + time, + i, + 5, + curveType + 18 * 4 - 2 + /*BEZIER*/ + ); + shearY = this.getBezierValue( + time, + i, + 6, + curveType + 18 * 5 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha; + constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha; + constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha; + constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha; + constraint.mixShearY += (shearY - constraint.mixShearY) * alpha; + } + } + }; + var PathConstraintPositionTimeline = class extends CurveTimeline1 { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex); + this.constraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (constraint.active) + constraint.position = this.getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position); + } + }; + var PathConstraintSpacingTimeline = class extends CurveTimeline1 { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex); + this.constraintIndex = pathConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (constraint.active) + constraint.spacing = this.getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing); + } + }; + var PathConstraintMixTimeline = class extends CurveTimeline { + /** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is + * applied. */ + constraintIndex = 0; + constructor(frameCount, bezierCount, pathConstraintIndex) { + super(frameCount, bezierCount, [ + Property.pathConstraintMix + "|" + pathConstraintIndex + ]); + this.constraintIndex = pathConstraintIndex; + } + getFrameEntries() { + return 4; + } + setFrame(frame, time, mixRotate, mixX, mixY) { + let frames = this.frames; + frame <<= 2; + frames[frame] = time; + frames[ + frame + 1 + /*ROTATE*/ + ] = mixRotate; + frames[ + frame + 2 + /*X*/ + ] = mixX; + frames[ + frame + 3 + /*Y*/ + ] = mixY; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint = skeleton.pathConstraints[this.constraintIndex]; + if (!constraint.active) + return; + let frames = this.frames; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + constraint.mixRotate = constraint.data.mixRotate; + constraint.mixX = constraint.data.mixX; + constraint.mixY = constraint.data.mixY; + return; + case 1 /* first */: + constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha; + constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha; + constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha; + } + return; + } + let rotate, x, y; + let i = Timeline.search( + frames, + time, + 4 + /*ENTRIES*/ + ); + let curveType = this.curves[i >> 2]; + switch (curveType) { + case 0: + let before = frames[i]; + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + let t = (time - before) / (frames[ + i + 4 + /*ENTRIES*/ + ] - before); + rotate += (frames[ + i + 4 + 1 + /*ROTATE*/ + ] - rotate) * t; + x += (frames[ + i + 4 + 2 + /*X*/ + ] - x) * t; + y += (frames[ + i + 4 + 3 + /*Y*/ + ] - y) * t; + break; + case 1: + rotate = frames[ + i + 1 + /*ROTATE*/ + ]; + x = frames[ + i + 2 + /*X*/ + ]; + y = frames[ + i + 3 + /*Y*/ + ]; + break; + default: + rotate = this.getBezierValue( + time, + i, + 1, + curveType - 2 + /*BEZIER*/ + ); + x = this.getBezierValue( + time, + i, + 2, + curveType + 18 - 2 + /*BEZIER*/ + ); + y = this.getBezierValue( + time, + i, + 3, + curveType + 18 * 2 - 2 + /*BEZIER*/ + ); + } + if (blend == 0 /* setup */) { + let data = constraint.data; + constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha; + constraint.mixX = data.mixX + (x - data.mixX) * alpha; + constraint.mixY = data.mixY + (y - data.mixY) * alpha; + } else { + constraint.mixRotate += (rotate - constraint.mixRotate) * alpha; + constraint.mixX += (x - constraint.mixX) * alpha; + constraint.mixY += (y - constraint.mixY) * alpha; + } + } + }; + var PhysicsConstraintTimeline = class extends CurveTimeline1 { + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline + * is applied, or -1 if all physics constraints in the skeleton will be changed. */ + constraintIndex = 0; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, bezierCount, physicsConstraintIndex, property) { + super(frameCount, bezierCount, property + "|" + physicsConstraintIndex); + this.constraintIndex = physicsConstraintIndex; + } + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint; + if (this.constraintIndex == -1) { + const value = time >= this.frames[0] ? this.getCurveValue(time) : 0; + for (const constraint2 of skeleton.physicsConstraints) { + if (constraint2.active && this.global(constraint2.data)) + this.set(constraint2, this.getAbsoluteValue2(time, alpha, blend, this.get(constraint2), this.setup(constraint2), value)); + } + } else { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (constraint.active) + this.set(constraint, this.getAbsoluteValue(time, alpha, blend, this.get(constraint), this.setup(constraint))); + } + } + }; + var PhysicsConstraintInertiaTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia); + } + setup(constraint) { + return constraint.data.inertia; + } + get(constraint) { + return constraint.inertia; + } + set(constraint, value) { + constraint.inertia = value; + } + global(constraint) { + return constraint.inertiaGlobal; + } + }; + var PhysicsConstraintStrengthTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength); + } + setup(constraint) { + return constraint.data.strength; + } + get(constraint) { + return constraint.strength; + } + set(constraint, value) { + constraint.strength = value; + } + global(constraint) { + return constraint.strengthGlobal; + } + }; + var PhysicsConstraintDampingTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping); + } + setup(constraint) { + return constraint.data.damping; + } + get(constraint) { + return constraint.damping; + } + set(constraint, value) { + constraint.damping = value; + } + global(constraint) { + return constraint.dampingGlobal; + } + }; + var PhysicsConstraintMassTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass); + } + setup(constraint) { + return 1 / constraint.data.massInverse; + } + get(constraint) { + return 1 / constraint.massInverse; + } + set(constraint, value) { + constraint.massInverse = 1 / value; + } + global(constraint) { + return constraint.massGlobal; + } + }; + var PhysicsConstraintWindTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind); + } + setup(constraint) { + return constraint.data.wind; + } + get(constraint) { + return constraint.wind; + } + set(constraint, value) { + constraint.wind = value; + } + global(constraint) { + return constraint.windGlobal; + } + }; + var PhysicsConstraintGravityTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity); + } + setup(constraint) { + return constraint.data.gravity; + } + get(constraint) { + return constraint.gravity; + } + set(constraint, value) { + constraint.gravity = value; + } + global(constraint) { + return constraint.gravityGlobal; + } + }; + var PhysicsConstraintMixTimeline = class extends PhysicsConstraintTimeline { + constructor(frameCount, bezierCount, physicsConstraintIndex) { + super(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix); + } + setup(constraint) { + return constraint.data.mix; + } + get(constraint) { + return constraint.mix; + } + set(constraint, value) { + constraint.mix = value; + } + global(constraint) { + return constraint.mixGlobal; + } + }; + var _PhysicsConstraintResetTimeline = class extends Timeline { + /** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is + * applied, or -1 if all physics constraints in the skeleton will be reset. */ + constraintIndex; + /** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */ + constructor(frameCount, physicsConstraintIndex) { + super(frameCount, _PhysicsConstraintResetTimeline.propertyIds); + this.constraintIndex = physicsConstraintIndex; + } + getFrameCount() { + return this.frames.length; + } + /** Sets the time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. */ + setFrame(frame, time) { + this.frames[frame] = time; + } + /** Resets the physics constraint when frames > lastTime and <= time. */ + apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) { + let constraint; + if (this.constraintIndex != -1) { + constraint = skeleton.physicsConstraints[this.constraintIndex]; + if (!constraint.active) + return; + } + const frames = this.frames; + if (lastTime > time) { + this.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction); + lastTime = -1; + } else if (lastTime >= frames[frames.length - 1]) + return; + if (time < frames[0]) + return; + if (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) { + if (constraint != null) + constraint.reset(); + else { + for (const constraint2 of skeleton.physicsConstraints) { + if (constraint2.active) + constraint2.reset(); + } + } + } + } + }; + var PhysicsConstraintResetTimeline = _PhysicsConstraintResetTimeline; + __publicField(PhysicsConstraintResetTimeline, "propertyIds", [Property.physicsConstraintReset.toString()]); + var _SequenceTimeline = class extends Timeline { + slotIndex; + attachment; + constructor(frameCount, slotIndex, attachment) { + super(frameCount, [ + Property.sequence + "|" + slotIndex + "|" + attachment.sequence.id + ]); + this.slotIndex = slotIndex; + this.attachment = attachment; + } + getFrameEntries() { + return _SequenceTimeline.ENTRIES; + } + getSlotIndex() { + return this.slotIndex; + } + getAttachment() { + return this.attachment; + } + /** Sets the time, mode, index, and frame time for the specified frame. + * @param frame Between 0 and frameCount, inclusive. + * @param time Seconds between frames. */ + setFrame(frame, time, mode, index, delay) { + let frames = this.frames; + frame *= _SequenceTimeline.ENTRIES; + frames[frame] = time; + frames[frame + _SequenceTimeline.MODE] = mode | index << 4; + frames[frame + _SequenceTimeline.DELAY] = delay; + } + apply(skeleton, lastTime, time, events, alpha, blend, direction) { + let slot = skeleton.slots[this.slotIndex]; + if (!slot.bone.active) + return; + let slotAttachment = slot.attachment; + let attachment = this.attachment; + if (slotAttachment != attachment) { + if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != attachment) + return; + } + if (direction == 1 /* mixOut */) { + if (blend == 0 /* setup */) + slot.sequenceIndex = -1; + return; + } + let frames = this.frames; + if (time < frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + slot.sequenceIndex = -1; + return; + } + let i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES); + let before = frames[i]; + let modeAndIndex = frames[i + _SequenceTimeline.MODE]; + let delay = frames[i + _SequenceTimeline.DELAY]; + if (!this.attachment.sequence) + return; + let index = modeAndIndex >> 4, count = this.attachment.sequence.regions.length; + let mode = SequenceModeValues[modeAndIndex & 15]; + if (mode != 0 /* hold */) { + index += (time - before) / delay + 1e-5 | 0; + switch (mode) { + case 1 /* once */: + index = Math.min(count - 1, index); + break; + case 2 /* loop */: + index %= count; + break; + case 3 /* pingpong */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : index % n; + if (index >= count) + index = n - index; + break; + } + case 4 /* onceReverse */: + index = Math.max(count - 1 - index, 0); + break; + case 5 /* loopReverse */: + index = count - 1 - index % count; + break; + case 6 /* pingpongReverse */: { + let n = (count << 1) - 2; + index = n == 0 ? 0 : (index + count - 1) % n; + if (index >= count) + index = n - index; + } + } + } + slot.sequenceIndex = index; + } + }; + var SequenceTimeline = _SequenceTimeline; + __publicField(SequenceTimeline, "ENTRIES", 3); + __publicField(SequenceTimeline, "MODE", 1); + __publicField(SequenceTimeline, "DELAY", 2); + + // spine-core/src/AnimationState.ts + var _AnimationState = class { + static emptyAnimation() { + return _AnimationState._emptyAnimation; + } + /** The AnimationStateData to look up mix durations. */ + data; + /** The list of tracks that currently have animations, which may contain null entries. */ + tracks = new Array(); + /** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower + * or faster. Defaults to 1. + * + * See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */ + timeScale = 1; + unkeyedState = 0; + events = new Array(); + listeners = new Array(); + queue = new EventQueue(this); + propertyIDs = new StringSet(); + animationsChanged = false; + trackEntryPool = new Pool(() => new TrackEntry()); + constructor(data) { + this.data = data; + } + /** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */ + update(delta) { + delta *= this.timeScale; + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let current = tracks[i]; + if (!current) + continue; + current.animationLast = current.nextAnimationLast; + current.trackLast = current.nextTrackLast; + let currentDelta = delta * current.timeScale; + if (current.delay > 0) { + current.delay -= currentDelta; + if (current.delay > 0) + continue; + currentDelta = -current.delay; + current.delay = 0; + } + let next = current.next; + if (next) { + let nextTime = current.trackLast - next.delay; + if (nextTime >= 0) { + next.delay = 0; + next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale; + current.trackTime += currentDelta; + this.setCurrent(i, next, true); + while (next.mixingFrom) { + next.mixTime += delta; + next = next.mixingFrom; + } + continue; + } + } else if (current.trackLast >= current.trackEnd && !current.mixingFrom) { + tracks[i] = null; + this.queue.end(current); + this.clearNext(current); + continue; + } + if (current.mixingFrom && this.updateMixingFrom(current, delta)) { + let from = current.mixingFrom; + current.mixingFrom = null; + if (from) + from.mixingTo = null; + while (from) { + this.queue.end(from); + from = from.mixingFrom; + } + } + current.trackTime += currentDelta; + } + this.queue.drain(); + } + /** Returns true when all mixing from entries are complete. */ + updateMixingFrom(to, delta) { + let from = to.mixingFrom; + if (!from) + return true; + let finished = this.updateMixingFrom(from, delta); + from.animationLast = from.nextAnimationLast; + from.trackLast = from.nextTrackLast; + if (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) { + if (from.totalAlpha == 0 || to.mixDuration == 0) { + to.mixingFrom = from.mixingFrom; + if (from.mixingFrom != null) + from.mixingFrom.mixingTo = to; + to.interruptAlpha = from.interruptAlpha; + this.queue.end(from); + } + return finished; + } + from.trackTime += delta * from.timeScale; + to.mixTime += delta; + return false; + } + /** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + * animation state can be applied to multiple skeletons to pose them identically. + * @returns True if any animations were applied. */ + apply(skeleton) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + if (this.animationsChanged) + this._animationsChanged(); + let events = this.events; + let tracks = this.tracks; + let applied = false; + for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) { + let current = tracks[i2]; + if (!current || current.delay > 0) + continue; + applied = true; + let blend = i2 == 0 ? 1 /* first */ : current.mixBlend; + let alpha = current.alpha; + if (current.mixingFrom) + alpha *= this.applyMixingFrom(current, skeleton, blend); + else if (current.trackTime >= current.trackEnd && !current.next) + alpha = 0; + let attachments = alpha >= current.alphaAttachmentThreshold; + let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime; + let applyEvents = events; + if (current.reverse) { + applyTime = current.animation.duration - applyTime; + applyEvents = null; + } + let timelines = current.animation.timelines; + let timelineCount = timelines.length; + if (i2 == 0 && alpha == 1 || blend == 3 /* add */) { + if (i2 == 0) + attachments = true; + for (let ii = 0; ii < timelineCount; ii++) { + Utils.webkit602BugfixHelper(alpha, blend); + var timeline = timelines[ii]; + if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments); + else + timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, 0 /* mixIn */); + } + } else { + let timelineMode = current.timelineMode; + let shortestRotation = current.shortestRotation; + let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + current.timelinesRotation.length = timelineCount << 1; + for (let ii = 0; ii < timelineCount; ii++) { + let timeline2 = timelines[ii]; + let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : 0 /* setup */; + if (!shortestRotation && timeline2 instanceof RotateTimeline) { + this.applyRotateTimeline(timeline2, skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1, firstFrame); + } else if (timeline2 instanceof AttachmentTimeline) { + this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, attachments); + } else { + Utils.webkit602BugfixHelper(alpha, blend); + timeline2.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, 0 /* mixIn */); + } + } + } + this.queueEvents(current, animationTime); + events.length = 0; + current.nextAnimationLast = animationTime; + current.nextTrackLast = current.trackTime; + } + var setupState = this.unkeyedState + SETUP; + var slots = skeleton.slots; + for (var i = 0, n = skeleton.slots.length; i < n; i++) { + var slot = slots[i]; + if (slot.attachmentState == setupState) { + var attachmentName = slot.data.attachmentName; + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + } + } + this.unkeyedState += 2; + this.queue.drain(); + return applied; + } + applyMixingFrom(to, skeleton, blend) { + let from = to.mixingFrom; + if (from.mixingFrom) + this.applyMixingFrom(from, skeleton, blend); + let mix = 0; + if (to.mixDuration == 0) { + mix = 1; + if (blend == 1 /* first */) + blend = 0 /* setup */; + } else { + mix = to.mixTime / to.mixDuration; + if (mix > 1) + mix = 1; + if (blend != 1 /* first */) + blend = from.mixBlend; + } + let attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold; + let timelines = from.animation.timelines; + let timelineCount = timelines.length; + let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix); + let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime; + let events = null; + if (from.reverse) + applyTime = from.animation.duration - applyTime; + else if (mix < from.eventThreshold) + events = this.events; + if (blend == 3 /* add */) { + for (let i = 0; i < timelineCount; i++) + timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, 1 /* mixOut */); + } else { + let timelineMode = from.timelineMode; + let timelineHoldMix = from.timelineHoldMix; + let shortestRotation = from.shortestRotation; + let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1; + if (firstFrame) + from.timelinesRotation.length = timelineCount << 1; + from.totalAlpha = 0; + for (let i = 0; i < timelineCount; i++) { + let timeline = timelines[i]; + let direction = 1 /* mixOut */; + let timelineBlend; + let alpha = 0; + switch (timelineMode[i]) { + case SUBSEQUENT: + if (!drawOrder && timeline instanceof DrawOrderTimeline) + continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaMix; + break; + case HOLD_SUBSEQUENT: + timelineBlend = blend; + alpha = alphaHold; + break; + case HOLD_FIRST: + timelineBlend = 0 /* setup */; + alpha = alphaHold; + break; + default: + timelineBlend = 0 /* setup */; + let holdMix = timelineHoldMix[i]; + alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration); + break; + } + from.totalAlpha += alpha; + if (!shortestRotation && timeline instanceof RotateTimeline) + this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame); + else if (timeline instanceof AttachmentTimeline) + this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments && alpha >= from.alphaAttachmentThreshold); + else { + Utils.webkit602BugfixHelper(alpha, blend); + if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == 0 /* setup */) + direction = 0 /* mixIn */; + timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction); + } + } + } + if (to.mixDuration > 0) + this.queueEvents(from, animationTime); + this.events.length = 0; + from.nextAnimationLast = animationTime; + from.nextTrackLast = from.trackTime; + return mix; + } + applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) { + var slot = skeleton.slots[timeline.slotIndex]; + if (!slot.bone.active) + return; + if (time < timeline.frames[0]) { + if (blend == 0 /* setup */ || blend == 1 /* first */) + this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments); + } else + this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments); + if (slot.attachmentState <= this.unkeyedState) + slot.attachmentState = this.unkeyedState + SETUP; + } + setAttachment(skeleton, slot, attachmentName, attachments) { + slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName)); + if (attachments) + slot.attachmentState = this.unkeyedState + CURRENT; + } + applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) { + if (firstFrame) + timelinesRotation[i] = 0; + if (alpha == 1) { + timeline.apply(skeleton, 0, time, null, 1, blend, 0 /* mixIn */); + return; + } + let bone = skeleton.bones[timeline.boneIndex]; + if (!bone.active) + return; + let frames = timeline.frames; + let r1 = 0, r2 = 0; + if (time < frames[0]) { + switch (blend) { + case 0 /* setup */: + bone.rotation = bone.data.rotation; + default: + return; + case 1 /* first */: + r1 = bone.rotation; + r2 = bone.data.rotation; + } + } else { + r1 = blend == 0 /* setup */ ? bone.data.rotation : bone.rotation; + r2 = bone.data.rotation + timeline.getCurveValue(time); + } + let total = 0, diff = r2 - r1; + diff -= Math.ceil(diff / 360 - 0.5) * 360; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + let lastTotal = 0, lastDiff = 0; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; + lastDiff = timelinesRotation[i + 1]; + } + let loops = lastTotal - lastTotal % 360; + total = diff + loops; + let current = diff >= 0, dir = lastTotal >= 0; + if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) { + if (Math.abs(lastTotal - loops) > 180) { + total += 360 * MathUtils.signum(lastTotal); + dir = current; + } else if (loops != 0) + total -= 360 * MathUtils.signum(lastTotal); + else + dir = current; + } + if (dir != current) + total += 360 * MathUtils.signum(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + bone.rotation = r1 + total * alpha; + } + queueEvents(entry, animationTime) { + let animationStart = entry.animationStart, animationEnd = entry.animationEnd; + let duration = animationEnd - animationStart; + let trackLastWrapped = entry.trackLast % duration; + let events = this.events; + let i = 0, n = events.length; + for (; i < n; i++) { + let event = events[i]; + if (event.time < trackLastWrapped) + break; + if (event.time > animationEnd) + continue; + this.queue.event(entry, event); + } + let complete = false; + if (entry.loop) { + if (duration == 0) + complete = true; + else { + const cycles = Math.floor(entry.trackTime / duration); + complete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration); + } + } else + complete = animationTime >= animationEnd && entry.animationLast < animationEnd; + if (complete) + this.queue.complete(entry); + for (; i < n; i++) { + let event = events[i]; + if (event.time < animationStart) + continue; + this.queue.event(entry, event); + } + } + /** Removes all animations from all tracks, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTracks() { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) + this.clearTrack(i); + this.tracks.length = 0; + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + /** Removes all animations from the track, leaving skeletons in their current pose. + * + * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose, + * rather than leaving them in their current pose. */ + clearTrack(trackIndex) { + if (trackIndex >= this.tracks.length) + return; + let current = this.tracks[trackIndex]; + if (!current) + return; + this.queue.end(current); + this.clearNext(current); + let entry = current; + while (true) { + let from = entry.mixingFrom; + if (!from) + break; + this.queue.end(from); + entry.mixingFrom = null; + entry.mixingTo = null; + entry = from; + } + this.tracks[current.trackIndex] = null; + this.queue.drain(); + } + setCurrent(index, current, interrupt) { + let from = this.expandToIndex(index); + this.tracks[index] = current; + current.previous = null; + if (from) { + if (interrupt) + this.queue.interrupt(from); + current.mixingFrom = from; + from.mixingTo = current; + current.mixTime = 0; + if (from.mixingFrom && from.mixDuration > 0) + current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration); + from.timelinesRotation.length = 0; + } + this.queue.start(current); + } + /** Sets an animation by name. + * + * See {@link #setAnimationWith()}. */ + setAnimation(trackIndex, animationName, loop = false) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.setAnimationWith(trackIndex, animation, loop); + } + /** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never + * applied to a skeleton, it is replaced (not mixed from). + * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + setAnimationWith(trackIndex, animation, loop = false) { + if (!animation) + throw new Error("animation cannot be null."); + let interrupt = true; + let current = this.expandToIndex(trackIndex); + if (current) { + if (current.nextTrackLast == -1) { + this.tracks[trackIndex] = current.mixingFrom; + this.queue.interrupt(current); + this.queue.end(current); + this.clearNext(current); + current = current.mixingFrom; + interrupt = false; + } else + this.clearNext(current); + } + let entry = this.trackEntry(trackIndex, animation, loop, current); + this.setCurrent(trackIndex, entry, interrupt); + this.queue.drain(); + return entry; + } + /** Queues an animation by name. + * + * See {@link #addAnimationWith()}. */ + addAnimation(trackIndex, animationName, loop = false, delay = 0) { + let animation = this.data.skeletonData.findAnimation(animationName); + if (!animation) + throw new Error("Animation not found: " + animationName); + return this.addAnimationWith(trackIndex, animation, loop, delay); + } + /** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is + * equivalent to calling {@link #setAnimationWith()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix + * ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the + * previous entry is looping, its next loop completion is used instead of its duration. + * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addAnimationWith(trackIndex, animation, loop = false, delay = 0) { + if (!animation) + throw new Error("animation cannot be null."); + let last = this.expandToIndex(trackIndex); + if (last) { + while (last.next) + last = last.next; + } + let entry = this.trackEntry(trackIndex, animation, loop, last); + if (!last) { + this.setCurrent(trackIndex, entry, true); + this.queue.drain(); + } else { + last.next = entry; + entry.previous = last; + if (delay <= 0) + delay += last.getTrackComplete() - entry.mixDuration; + } + entry.delay = delay; + return entry; + } + /** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's + * {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out. + * + * Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()}, + * {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes + * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation + * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of + * 0 still mixes out over one frame. + * + * Mixing in is done by first setting an empty animation, then adding an animation using + * {@link #addAnimation()} and on the returned track entry, set the + * {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and + * more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the + * setup pose value if no lower tracks key the property to the value keyed in the new animation. */ + setEmptyAnimation(trackIndex, mixDuration = 0) { + let entry = this.setAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's + * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling + * {@link #setEmptyAnimation()}. + * + * See {@link #setEmptyAnimation()}. + * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry + * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or + * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next + * loop completion is used instead of its duration. + * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + * after the {@link AnimationStateListener#dispose()} event occurs. */ + addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) { + let entry = this.addAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false, delay); + if (delay <= 0) + entry.delay += entry.mixDuration - mixDuration; + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix + * duration. */ + setEmptyAnimations(mixDuration = 0) { + let oldDrainDisabled = this.queue.drainDisabled; + this.queue.drainDisabled = true; + for (let i = 0, n = this.tracks.length; i < n; i++) { + let current = this.tracks[i]; + if (current) + this.setEmptyAnimation(current.trackIndex, mixDuration); + } + this.queue.drainDisabled = oldDrainDisabled; + this.queue.drain(); + } + expandToIndex(index) { + if (index < this.tracks.length) + return this.tracks[index]; + Utils.ensureArrayCapacity(this.tracks, index + 1, null); + this.tracks.length = index + 1; + return null; + } + /** @param last May be null. */ + trackEntry(trackIndex, animation, loop, last) { + let entry = this.trackEntryPool.obtain(); + entry.reset(); + entry.trackIndex = trackIndex; + entry.animation = animation; + entry.loop = loop; + entry.holdPrevious = false; + entry.reverse = false; + entry.shortestRotation = false; + entry.eventThreshold = 0; + entry.alphaAttachmentThreshold = 0; + entry.mixAttachmentThreshold = 0; + entry.mixDrawOrderThreshold = 0; + entry.animationStart = 0; + entry.animationEnd = animation.duration; + entry.animationLast = -1; + entry.nextAnimationLast = -1; + entry.delay = 0; + entry.trackTime = 0; + entry.trackLast = -1; + entry.nextTrackLast = -1; + entry.trackEnd = Number.MAX_VALUE; + entry.timeScale = 1; + entry.alpha = 1; + entry.mixTime = 0; + entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation); + entry.interruptAlpha = 1; + entry.totalAlpha = 0; + entry.mixBlend = 2 /* replace */; + return entry; + } + /** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */ + clearNext(entry) { + let next = entry.next; + while (next) { + this.queue.dispose(next); + next = next.next; + } + entry.next = null; + } + _animationsChanged() { + this.animationsChanged = false; + this.propertyIDs.clear(); + let tracks = this.tracks; + for (let i = 0, n = tracks.length; i < n; i++) { + let entry = tracks[i]; + if (!entry) + continue; + while (entry.mixingFrom) + entry = entry.mixingFrom; + do { + if (!entry.mixingTo || entry.mixBlend != 3 /* add */) + this.computeHold(entry); + entry = entry.mixingTo; + } while (entry); + } + } + computeHold(entry) { + let to = entry.mixingTo; + let timelines = entry.animation.timelines; + let timelinesCount = entry.animation.timelines.length; + let timelineMode = entry.timelineMode; + timelineMode.length = timelinesCount; + let timelineHoldMix = entry.timelineHoldMix; + timelineHoldMix.length = 0; + let propertyIDs = this.propertyIDs; + if (to && to.holdPrevious) { + for (let i = 0; i < timelinesCount; i++) + timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT; + return; + } + outer: + for (let i = 0; i < timelinesCount; i++) { + let timeline = timelines[i]; + let ids = timeline.getPropertyIds(); + if (!propertyIDs.addAll(ids)) + timelineMode[i] = SUBSEQUENT; + else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) { + timelineMode[i] = FIRST; + } else { + for (let next = to.mixingTo; next; next = next.mixingTo) { + if (next.animation.hasTimeline(ids)) + continue; + if (entry.mixDuration > 0) { + timelineMode[i] = HOLD_MIX; + timelineHoldMix[i] = next; + continue outer; + } + break; + } + timelineMode[i] = HOLD_FIRST; + } + } + } + /** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */ + getCurrent(trackIndex) { + if (trackIndex >= this.tracks.length) + return null; + return this.tracks[trackIndex]; + } + /** Adds a listener to receive events for all track entries. */ + addListener(listener) { + if (!listener) + throw new Error("listener cannot be null."); + this.listeners.push(listener); + } + /** Removes the listener added with {@link #addListener()}. */ + removeListener(listener) { + let index = this.listeners.indexOf(listener); + if (index >= 0) + this.listeners.splice(index, 1); + } + /** Removes all listeners added with {@link #addListener()}. */ + clearListeners() { + this.listeners.length = 0; + } + /** Discards all listener notifications that have not yet been delivered. This can be useful to call from an + * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery + * are not wanted because new animations are being set. */ + clearListenerNotifications() { + this.queue.clear(); + } + }; + var AnimationState = _AnimationState; + __publicField(AnimationState, "_emptyAnimation", new Animation("", [], 0)); + var TrackEntry = class { + /** The animation to apply for this track entry. */ + animation = null; + previous = null; + /** The animation queued to start after this animation, or null. `next` makes up a linked list. */ + next = null; + /** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + * mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */ + mixingFrom = null; + /** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is + * currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */ + mixingTo = null; + /** The listener for events generated by this track entry, or null. + * + * A track entry returned from {@link AnimationState#setAnimation()} is already the current animation + * for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */ + listener = null; + /** The index of the track where this track entry is either current or queued. + * + * See {@link AnimationState#getCurrent()}. */ + trackIndex = 0; + /** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its + * duration. */ + loop = false; + /** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead + * of being mixed out. + * + * When mixing between animations that key the same property, if a lower track also keys that property then the value will + * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0% + * while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation + * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which + * keys the property, only when a higher track also keys the property. + * + * Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the + * previous animation. */ + holdPrevious = false; + reverse = false; + shortestRotation = false; + /** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the + * `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event + * timelines are not applied while this animation is being mixed out. */ + eventThreshold = 0; + /** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the + * `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to + * 0, so attachment timelines are not applied while this animation is being mixed out. */ + mixAttachmentThreshold = 0; + /** When {@link #getAlpha()} is greater than alphaAttachmentThreshold, attachment timelines are applied. + * Defaults to 0, so attachment timelines are always applied. */ + alphaAttachmentThreshold = 0; + /** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the + * mixDrawOrderThreshold, draw order timelines are applied while this animation is being mixed out. Defaults to + * 0, so draw order timelines are not applied while this animation is being mixed out. */ + mixDrawOrderThreshold = 0; + /** Seconds when this animation starts, both initially and after looping. Defaults to 0. + * + * When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same + * value to prevent timeline keys before the start time from triggering. */ + animationStart = 0; + /** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + * loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */ + animationEnd = 0; + /** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + * animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and + * `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation + * is applied. */ + animationLast = 0; + nextAnimationLast = 0; + /** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay` + * postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from + * the start of the previous animation to when this track entry will become the current track entry (ie when the previous + * track entry {@link TrackEntry#trackTime} >= this track entry's `delay`). + * + * {@link #timeScale} affects the delay. */ + delay = 0; + /** Current time in seconds this track entry has been the current track entry. The track time determines + * {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting + * looping. */ + trackTime = 0; + trackLast = 0; + nextTrackLast = 0; + /** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float + * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time + * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the + * properties keyed by the animation are set to the setup pose and the track is cleared. + * + * It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation + * abruptly cease being applied. */ + trackEnd = 0; + /** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or + * faster. Defaults to 1. + * + * {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to + * match the animation speed. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If + * the time scale is not 1, the delay may need to be adjusted. + * + * See AnimationState {@link AnimationState#timeScale} for affecting all animations. */ + timeScale = 0; + /** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults + * to 1, which overwrites the skeleton's current pose with this animation. + * + * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to + * use alpha on track 0 if the skeleton pose is from the last frame render. */ + alpha = 0; + /** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be + * slightly more than `mixDuration` when the mix is complete. */ + mixTime = 0; + /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData + * {@link AnimationStateData#getMix()} based on the animation before this animation (if any). + * + * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the + * properties it was animating. + * + * The `mixDuration` can be set manually rather than use the value from + * {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new + * track entry only before {@link AnimationState#update(float)} is first called. + * + * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the + * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set + * afterward. */ + _mixDuration = 0; + interruptAlpha = 0; + totalAlpha = 0; + get mixDuration() { + return this._mixDuration; + } + set mixDuration(mixDuration) { + this._mixDuration = mixDuration; + } + setMixDurationWithDelay(mixDuration, delay) { + this._mixDuration = mixDuration; + if (this.previous != null && delay <= 0) + delay += this.previous.getTrackComplete() - mixDuration; + this.delay = delay; + } + /** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which + * replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to + * the values from the lower tracks. + * + * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first + * called. */ + mixBlend = 2 /* replace */; + timelineMode = new Array(); + timelineHoldMix = new Array(); + timelinesRotation = new Array(); + reset() { + this.next = null; + this.previous = null; + this.mixingFrom = null; + this.mixingTo = null; + this.animation = null; + this.listener = null; + this.timelineMode.length = 0; + this.timelineHoldMix.length = 0; + this.timelinesRotation.length = 0; + } + /** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart} + * and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the + * `animationStart` time. */ + getAnimationTime() { + if (this.loop) { + let duration = this.animationEnd - this.animationStart; + if (duration == 0) + return this.animationStart; + return this.trackTime % duration + this.animationStart; + } + return Math.min(this.trackTime + this.animationStart, this.animationEnd); + } + setAnimationLast(animationLast) { + this.animationLast = animationLast; + this.nextAnimationLast = animationLast; + } + /** Returns true if at least one loop has been completed. + * + * See {@link AnimationStateListener#complete()}. */ + isComplete() { + return this.trackTime >= this.animationEnd - this.animationStart; + } + /** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + * long way around when using {@link #alpha} and starting animations on other tracks. + * + * Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions: + * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long + * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the + * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */ + resetRotationDirections() { + this.timelinesRotation.length = 0; + } + getTrackComplete() { + let duration = this.animationEnd - this.animationStart; + if (duration != 0) { + if (this.loop) + return duration * (1 + (this.trackTime / duration | 0)); + if (this.trackTime < duration) + return duration; + } + return this.trackTime; + } + /** Returns true if this track entry has been applied at least once. + *

    + * See {@link AnimationState#apply(Skeleton)}. */ + wasApplied() { + return this.nextTrackLast != -1; + } + /** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next + * {@link AnimationState#update(float)}. */ + isNextReady() { + return this.next != null && this.nextTrackLast - this.next.delay >= 0; + } + }; + var EventQueue = class { + objects = []; + drainDisabled = false; + animState; + constructor(animState) { + this.animState = animState; + } + start(entry) { + this.objects.push(EventType.start); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + interrupt(entry) { + this.objects.push(EventType.interrupt); + this.objects.push(entry); + } + end(entry) { + this.objects.push(EventType.end); + this.objects.push(entry); + this.animState.animationsChanged = true; + } + dispose(entry) { + this.objects.push(EventType.dispose); + this.objects.push(entry); + } + complete(entry) { + this.objects.push(EventType.complete); + this.objects.push(entry); + } + event(entry, event) { + this.objects.push(EventType.event); + this.objects.push(entry); + this.objects.push(event); + } + drain() { + if (this.drainDisabled) + return; + this.drainDisabled = true; + let objects = this.objects; + let listeners = this.animState.listeners; + for (let i = 0; i < objects.length; i += 2) { + let type = objects[i]; + let entry = objects[i + 1]; + switch (type) { + case EventType.start: + if (entry.listener && entry.listener.start) + entry.listener.start(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.start) + listener.start(entry); + } + break; + case EventType.interrupt: + if (entry.listener && entry.listener.interrupt) + entry.listener.interrupt(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.interrupt) + listener.interrupt(entry); + } + break; + case EventType.end: + if (entry.listener && entry.listener.end) + entry.listener.end(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.end) + listener.end(entry); + } + case EventType.dispose: + if (entry.listener && entry.listener.dispose) + entry.listener.dispose(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.dispose) + listener.dispose(entry); + } + this.animState.trackEntryPool.free(entry); + break; + case EventType.complete: + if (entry.listener && entry.listener.complete) + entry.listener.complete(entry); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.complete) + listener.complete(entry); + } + break; + case EventType.event: + let event = objects[i++ + 2]; + if (entry.listener && entry.listener.event) + entry.listener.event(entry, event); + for (let ii = 0; ii < listeners.length; ii++) { + let listener = listeners[ii]; + if (listener.event) + listener.event(entry, event); + } + break; + } + } + this.clear(); + this.drainDisabled = false; + } + clear() { + this.objects.length = 0; + } + }; + var EventType = /* @__PURE__ */ ((EventType2) => { + EventType2[EventType2["start"] = 0] = "start"; + EventType2[EventType2["interrupt"] = 1] = "interrupt"; + EventType2[EventType2["end"] = 2] = "end"; + EventType2[EventType2["dispose"] = 3] = "dispose"; + EventType2[EventType2["complete"] = 4] = "complete"; + EventType2[EventType2["event"] = 5] = "event"; + return EventType2; + })(EventType || {}); + var AnimationStateAdapter = class { + start(entry) { + } + interrupt(entry) { + } + end(entry) { + } + dispose(entry) { + } + complete(entry) { + } + event(entry, event) { + } + }; + var SUBSEQUENT = 0; + var FIRST = 1; + var HOLD_SUBSEQUENT = 2; + var HOLD_FIRST = 3; + var HOLD_MIX = 4; + var SETUP = 1; + var CURRENT = 2; + + // spine-core/src/AnimationStateData.ts + var AnimationStateData = class { + /** The SkeletonData to look up animations when they are specified by name. */ + skeletonData; + animationToMixTime = {}; + /** The mix duration to use when no mix duration has been defined between two animations. */ + defaultMix = 0; + constructor(skeletonData) { + if (!skeletonData) + throw new Error("skeletonData cannot be null."); + this.skeletonData = skeletonData; + } + /** Sets a mix duration by animation name. + * + * See {@link #setMixWith()}. */ + setMix(fromName, toName, duration) { + let from = this.skeletonData.findAnimation(fromName); + if (!from) + throw new Error("Animation not found: " + fromName); + let to = this.skeletonData.findAnimation(toName); + if (!to) + throw new Error("Animation not found: " + toName); + this.setMixWith(from, to, duration); + } + /** Sets the mix duration when changing from the specified animation to the other. + * + * See {@link TrackEntry#mixDuration}. */ + setMixWith(from, to, duration) { + if (!from) + throw new Error("from cannot be null."); + if (!to) + throw new Error("to cannot be null."); + let key = from.name + "." + to.name; + this.animationToMixTime[key] = duration; + } + /** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if + * no mix duration has been set. */ + getMix(from, to) { + let key = from.name + "." + to.name; + let value = this.animationToMixTime[key]; + return value === void 0 ? this.defaultMix : value; + } + }; + + // spine-core/src/attachments/BoundingBoxAttachment.ts + var BoundingBoxAttachment = class extends VertexAttachment { + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new BoundingBoxAttachment(this.name); + this.copyTo(copy); + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/ClippingAttachment.ts + var ClippingAttachment = class extends VertexAttachment { + /** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of + * the skeleton's rendering. */ + endSlot = null; + // Nonessential. + /** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons + * are not usually rendered at runtime. */ + color = new Color(0.2275, 0.2275, 0.8078, 1); + // ce3a3aff + constructor(name) { + super(name); + } + copy() { + let copy = new ClippingAttachment(this.name); + this.copyTo(copy); + copy.endSlot = this.endSlot; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/Texture.ts + var Texture = class { + _image; + constructor(image) { + this._image = image; + } + getImage() { + return this._image; + } + }; + var TextureFilter = /* @__PURE__ */ ((TextureFilter3) => { + TextureFilter3[TextureFilter3["Nearest"] = 9728] = "Nearest"; + TextureFilter3[TextureFilter3["Linear"] = 9729] = "Linear"; + TextureFilter3[TextureFilter3["MipMap"] = 9987] = "MipMap"; + TextureFilter3[TextureFilter3["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest"; + TextureFilter3[TextureFilter3["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest"; + TextureFilter3[TextureFilter3["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear"; + TextureFilter3[TextureFilter3["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear"; + return TextureFilter3; + })(TextureFilter || {}); + var TextureWrap = /* @__PURE__ */ ((TextureWrap4) => { + TextureWrap4[TextureWrap4["MirroredRepeat"] = 33648] = "MirroredRepeat"; + TextureWrap4[TextureWrap4["ClampToEdge"] = 33071] = "ClampToEdge"; + TextureWrap4[TextureWrap4["Repeat"] = 10497] = "Repeat"; + return TextureWrap4; + })(TextureWrap || {}); + var TextureRegion = class { + texture; + u = 0; + v = 0; + u2 = 0; + v2 = 0; + width = 0; + height = 0; + degrees = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + }; + var FakeTexture = class extends Texture { + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-core/src/TextureAtlas.ts + var TextureAtlas = class { + pages = new Array(); + regions = new Array(); + constructor(atlasText) { + let reader = new TextureAtlasReader(atlasText); + let entry = new Array(4); + let pageFields = {}; + pageFields["size"] = (page2) => { + page2.width = parseInt(entry[1]); + page2.height = parseInt(entry[2]); + }; + pageFields["format"] = () => { + }; + pageFields["filter"] = (page2) => { + page2.minFilter = Utils.enumValue(TextureFilter, entry[1]); + page2.magFilter = Utils.enumValue(TextureFilter, entry[2]); + }; + pageFields["repeat"] = (page2) => { + if (entry[1].indexOf("x") != -1) + page2.uWrap = 10497 /* Repeat */; + if (entry[1].indexOf("y") != -1) + page2.vWrap = 10497 /* Repeat */; + }; + pageFields["pma"] = (page2) => { + page2.pma = entry[1] == "true"; + }; + var regionFields = {}; + regionFields["xy"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + }; + regionFields["size"] = (region) => { + region.width = parseInt(entry[1]); + region.height = parseInt(entry[2]); + }; + regionFields["bounds"] = (region) => { + region.x = parseInt(entry[1]); + region.y = parseInt(entry[2]); + region.width = parseInt(entry[3]); + region.height = parseInt(entry[4]); + }; + regionFields["offset"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + }; + regionFields["orig"] = (region) => { + region.originalWidth = parseInt(entry[1]); + region.originalHeight = parseInt(entry[2]); + }; + regionFields["offsets"] = (region) => { + region.offsetX = parseInt(entry[1]); + region.offsetY = parseInt(entry[2]); + region.originalWidth = parseInt(entry[3]); + region.originalHeight = parseInt(entry[4]); + }; + regionFields["rotate"] = (region) => { + let value = entry[1]; + if (value == "true") + region.degrees = 90; + else if (value != "false") + region.degrees = parseInt(value); + }; + regionFields["index"] = (region) => { + region.index = parseInt(entry[1]); + }; + let line = reader.readLine(); + while (line && line.trim().length == 0) + line = reader.readLine(); + while (true) { + if (!line || line.trim().length == 0) + break; + if (reader.readEntry(entry, line) == 0) + break; + line = reader.readLine(); + } + let page = null; + let names = null; + let values = null; + while (true) { + if (line === null) + break; + if (line.trim().length == 0) { + page = null; + line = reader.readLine(); + } else if (!page) { + page = new TextureAtlasPage(line.trim()); + while (true) { + if (reader.readEntry(entry, line = reader.readLine()) == 0) + break; + let field = pageFields[entry[0]]; + if (field) + field(page); + } + this.pages.push(page); + } else { + let region = new TextureAtlasRegion(page, line); + while (true) { + let count = reader.readEntry(entry, line = reader.readLine()); + if (count == 0) + break; + let field = regionFields[entry[0]]; + if (field) + field(region); + else { + if (!names) + names = []; + if (!values) + values = []; + names.push(entry[0]); + let entryValues = []; + for (let i = 0; i < count; i++) + entryValues.push(parseInt(entry[i + 1])); + values.push(entryValues); + } + } + if (region.originalWidth == 0 && region.originalHeight == 0) { + region.originalWidth = region.width; + region.originalHeight = region.height; + } + if (names && names.length > 0 && values && values.length > 0) { + region.names = names; + region.values = values; + names = null; + values = null; + } + region.u = region.x / page.width; + region.v = region.y / page.height; + if (region.degrees == 90) { + region.u2 = (region.x + region.height) / page.width; + region.v2 = (region.y + region.width) / page.height; + } else { + region.u2 = (region.x + region.width) / page.width; + region.v2 = (region.y + region.height) / page.height; + } + this.regions.push(region); + } + } + } + findRegion(name) { + for (let i = 0; i < this.regions.length; i++) { + if (this.regions[i].name == name) { + return this.regions[i]; + } + } + return null; + } + setTextures(assetManager, pathPrefix = "") { + for (let page of this.pages) + page.setTexture(assetManager.get(pathPrefix + page.name)); + } + dispose() { + for (let i = 0; i < this.pages.length; i++) { + this.pages[i].texture?.dispose(); + } + } + }; + var TextureAtlasReader = class { + lines; + index = 0; + constructor(text) { + this.lines = text.split(/\r\n|\r|\n/); + } + readLine() { + if (this.index >= this.lines.length) + return null; + return this.lines[this.index++]; + } + readEntry(entry, line) { + if (!line) + return 0; + line = line.trim(); + if (line.length == 0) + return 0; + let colon = line.indexOf(":"); + if (colon == -1) + return 0; + entry[0] = line.substr(0, colon).trim(); + for (let i = 1, lastMatch = colon + 1; ; i++) { + let comma = line.indexOf(",", lastMatch); + if (comma == -1) { + entry[i] = line.substr(lastMatch).trim(); + return i; + } + entry[i] = line.substr(lastMatch, comma - lastMatch).trim(); + lastMatch = comma + 1; + if (i == 4) + return 4; + } + } + }; + var TextureAtlasPage = class { + name; + minFilter = 9728 /* Nearest */; + magFilter = 9728 /* Nearest */; + uWrap = 33071 /* ClampToEdge */; + vWrap = 33071 /* ClampToEdge */; + texture = null; + width = 0; + height = 0; + pma = false; + regions = new Array(); + constructor(name) { + this.name = name; + } + setTexture(texture) { + this.texture = texture; + texture.setFilters(this.minFilter, this.magFilter); + texture.setWraps(this.uWrap, this.vWrap); + for (let region of this.regions) + region.texture = texture; + } + }; + var TextureAtlasRegion = class extends TextureRegion { + page; + name; + x = 0; + y = 0; + offsetX = 0; + offsetY = 0; + originalWidth = 0; + originalHeight = 0; + index = 0; + degrees = 0; + names = null; + values = null; + constructor(page, name) { + super(); + this.page = page; + this.name = name; + page.regions.push(this); + } + }; + + // spine-core/src/attachments/MeshAttachment.ts + var MeshAttachment = class extends VertexAttachment { + region = null; + /** The name of the texture region for this attachment. */ + path; + /** The UV pair for each vertex, normalized within the texture region. */ + regionUVs = []; + /** The UV pair for each vertex, normalized within the entire texture. + * + * See {@link #updateUVs}. */ + uvs = []; + /** Triplets of vertex indices which describe the mesh's triangulation. */ + triangles = []; + /** The color to tint the mesh. */ + color = new Color(1, 1, 1, 1); + /** The width of the mesh's image. Available only when nonessential data was exported. */ + width = 0; + /** The height of the mesh's image. Available only when nonessential data was exported. */ + height = 0; + /** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */ + hullLength = 0; + /** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if + * nonessential data was exported. Triangulation is not performed at runtime. */ + edges = []; + parentMesh = null; + sequence = null; + tempColor = new Color(0, 0, 0, 0); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates {@link #uvs} using the {@link #regionUVs} and region. Must be called if the region, the region's properties, or + * the {@link #regionUVs} are changed. */ + updateRegion() { + if (!this.region) + throw new Error("Region not set."); + let regionUVs = this.regionUVs; + if (!this.uvs || this.uvs.length != regionUVs.length) + this.uvs = Utils.newFloatArray(regionUVs.length); + let uvs = this.uvs; + let n = this.uvs.length; + let u = this.region.u, v = this.region.v, width = 0, height = 0; + if (this.region instanceof TextureAtlasRegion) { + let region = this.region, page = region.page; + let textureWidth = page.width, textureHeight = page.height; + switch (region.degrees) { + case 90: + u -= (region.originalHeight - region.offsetY - region.height) / textureWidth; + v -= (region.originalWidth - region.offsetX - region.width) / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i + 1] * width; + uvs[i + 1] = v + (1 - regionUVs[i]) * height; + } + return; + case 180: + u -= (region.originalWidth - region.offsetX - region.width) / textureWidth; + v -= region.offsetY / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i]) * width; + uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height; + } + return; + case 270: + u -= region.offsetY / textureWidth; + v -= region.offsetX / textureHeight; + width = region.originalHeight / textureWidth; + height = region.originalWidth / textureHeight; + for (let i = 0; i < n; i += 2) { + uvs[i] = u + (1 - regionUVs[i + 1]) * width; + uvs[i + 1] = v + regionUVs[i] * height; + } + return; + } + u -= region.offsetX / textureWidth; + v -= (region.originalHeight - region.offsetY - region.height) / textureHeight; + width = region.originalWidth / textureWidth; + height = region.originalHeight / textureHeight; + } else if (!this.region) { + u = v = 0; + width = height = 1; + } else { + width = this.region.u2 - u; + height = this.region.v2 - v; + } + for (let i = 0; i < n; i += 2) { + uvs[i] = u + regionUVs[i] * width; + uvs[i + 1] = v + regionUVs[i + 1] * height; + } + } + /** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices}, + * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the + * parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */ + getParentMesh() { + return this.parentMesh; + } + /** @param parentMesh May be null. */ + setParentMesh(parentMesh) { + this.parentMesh = parentMesh; + if (parentMesh) { + this.bones = parentMesh.bones; + this.vertices = parentMesh.vertices; + this.worldVerticesLength = parentMesh.worldVerticesLength; + this.regionUVs = parentMesh.regionUVs; + this.triangles = parentMesh.triangles; + this.hullLength = parentMesh.hullLength; + this.worldVerticesLength = parentMesh.worldVerticesLength; + } + } + copy() { + if (this.parentMesh) + return this.newLinkedMesh(); + let copy = new MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + this.copyTo(copy); + copy.regionUVs = new Array(this.regionUVs.length); + Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length); + copy.uvs = new Array(this.uvs.length); + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length); + copy.triangles = new Array(this.triangles.length); + Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length); + copy.hullLength = this.hullLength; + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + if (this.edges) { + copy.edges = new Array(this.edges.length); + Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length); + } + copy.width = this.width; + copy.height = this.height; + return copy; + } + computeWorldVertices(slot, start, count, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + super.computeWorldVertices(slot, start, count, worldVertices2, offset, stride); + } + /** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/ + newLinkedMesh() { + let copy = new MeshAttachment(this.name, this.path); + copy.region = this.region; + copy.color.setFromColor(this.color); + copy.timelineAttachment = this.timelineAttachment; + copy.setParentMesh(this.parentMesh ? this.parentMesh : this); + if (copy.region != null) + copy.updateRegion(); + return copy; + } + }; + + // spine-core/src/attachments/PathAttachment.ts + var PathAttachment = class extends VertexAttachment { + /** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */ + lengths = []; + /** If true, the start and end knots are connected. */ + closed = false; + /** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer + * calculations are performed but calculating positions along the path is less accurate. */ + constantSpeed = false; + /** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually + * rendered at runtime. */ + color = new Color(1, 1, 1, 1); + constructor(name) { + super(name); + } + copy() { + let copy = new PathAttachment(this.name); + this.copyTo(copy); + copy.lengths = new Array(this.lengths.length); + Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length); + copy.closed = closed; + copy.constantSpeed = this.constantSpeed; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/PointAttachment.ts + var PointAttachment = class extends VertexAttachment { + x = 0; + y = 0; + rotation = 0; + /** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments + * are not usually rendered at runtime. */ + color = new Color(0.38, 0.94, 0, 1); + constructor(name) { + super(name); + } + computeWorldPosition(bone, point) { + point.x = this.x * bone.a + this.y * bone.b + bone.worldX; + point.y = this.x * bone.c + this.y * bone.d + bone.worldY; + return point; + } + computeWorldRotation(bone) { + const r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const x = cos * bone.a + sin * bone.b; + const y = cos * bone.c + sin * bone.d; + return MathUtils.atan2Deg(y, x); + } + copy() { + let copy = new PointAttachment(this.name); + copy.x = this.x; + copy.y = this.y; + copy.rotation = this.rotation; + copy.color.setFromColor(this.color); + return copy; + } + }; + + // spine-core/src/attachments/RegionAttachment.ts + var _RegionAttachment = class extends Attachment { + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local rotation. */ + rotation = 0; + /** The width of the region attachment in Spine. */ + width = 0; + /** The height of the region attachment in Spine. */ + height = 0; + /** The color to tint the region attachment. */ + color = new Color(1, 1, 1, 1); + /** The name of the texture region for this attachment. */ + path; + region = null; + sequence = null; + /** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex. + * + * See {@link #updateOffset()}. */ + offset = Utils.newFloatArray(8); + uvs = Utils.newFloatArray(8); + tempColor = new Color(1, 1, 1, 1); + constructor(name, path) { + super(name); + this.path = path; + } + /** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */ + updateRegion() { + if (!this.region) + throw new Error("Region not set."); + let region = this.region; + let uvs = this.uvs; + if (region == null) { + uvs[0] = 0; + uvs[1] = 0; + uvs[2] = 0; + uvs[3] = 1; + uvs[4] = 1; + uvs[5] = 1; + uvs[6] = 1; + uvs[7] = 0; + return; + } + let regionScaleX = this.width / this.region.originalWidth * this.scaleX; + let regionScaleY = this.height / this.region.originalHeight * this.scaleY; + let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX; + let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY; + let localX2 = localX + this.region.width * regionScaleX; + let localY2 = localY + this.region.height * regionScaleY; + let radians = this.rotation * MathUtils.degRad; + let cos = Math.cos(radians); + let sin = Math.sin(radians); + let x = this.x, y = this.y; + let localXCos = localX * cos + x; + let localXSin = localX * sin; + let localYCos = localY * cos + y; + let localYSin = localY * sin; + let localX2Cos = localX2 * cos + x; + let localX2Sin = localX2 * sin; + let localY2Cos = localY2 * cos + y; + let localY2Sin = localY2 * sin; + let offset = this.offset; + offset[0] = localXCos - localYSin; + offset[1] = localYCos + localXSin; + offset[2] = localXCos - localY2Sin; + offset[3] = localY2Cos + localXSin; + offset[4] = localX2Cos - localY2Sin; + offset[5] = localY2Cos + localX2Sin; + offset[6] = localX2Cos - localYSin; + offset[7] = localYCos + localX2Sin; + if (region.degrees == 90) { + uvs[0] = region.u2; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v2; + uvs[4] = region.u; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v; + } else { + uvs[0] = region.u; + uvs[1] = region.v2; + uvs[2] = region.u; + uvs[3] = region.v; + uvs[4] = region.u2; + uvs[5] = region.v; + uvs[6] = region.u2; + uvs[7] = region.v2; + } + } + /** Transforms the attachment's four vertices to world coordinates. If the attachment has a {@link #sequence}, the region may + * be changed. + *

    + * See World transforms in the Spine + * Runtimes Guide. + * @param worldVertices The output world vertices. Must have a length >= offset + 8. + * @param offset The worldVertices index to begin writing values. + * @param stride The number of worldVertices entries between the value pairs written. */ + computeWorldVertices(slot, worldVertices2, offset, stride) { + if (this.sequence != null) + this.sequence.apply(slot, this); + let bone = slot.bone; + let vertexOffset = this.offset; + let x = bone.worldX, y = bone.worldY; + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let offsetX = 0, offsetY = 0; + offsetX = vertexOffset[0]; + offsetY = vertexOffset[1]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[2]; + offsetY = vertexOffset[3]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[4]; + offsetY = vertexOffset[5]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + offset += stride; + offsetX = vertexOffset[6]; + offsetY = vertexOffset[7]; + worldVertices2[offset] = offsetX * a + offsetY * b + x; + worldVertices2[offset + 1] = offsetX * c + offsetY * d + y; + } + copy() { + let copy = new _RegionAttachment(this.name, this.path); + copy.region = this.region; + copy.x = this.x; + copy.y = this.y; + copy.scaleX = this.scaleX; + copy.scaleY = this.scaleY; + copy.rotation = this.rotation; + copy.width = this.width; + copy.height = this.height; + Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8); + Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8); + copy.color.setFromColor(this.color); + copy.sequence = this.sequence != null ? this.sequence.copy() : null; + return copy; + } + }; + var RegionAttachment = _RegionAttachment; + __publicField(RegionAttachment, "X1", 0); + __publicField(RegionAttachment, "Y1", 1); + __publicField(RegionAttachment, "C1R", 2); + __publicField(RegionAttachment, "C1G", 3); + __publicField(RegionAttachment, "C1B", 4); + __publicField(RegionAttachment, "C1A", 5); + __publicField(RegionAttachment, "U1", 6); + __publicField(RegionAttachment, "V1", 7); + __publicField(RegionAttachment, "X2", 8); + __publicField(RegionAttachment, "Y2", 9); + __publicField(RegionAttachment, "C2R", 10); + __publicField(RegionAttachment, "C2G", 11); + __publicField(RegionAttachment, "C2B", 12); + __publicField(RegionAttachment, "C2A", 13); + __publicField(RegionAttachment, "U2", 14); + __publicField(RegionAttachment, "V2", 15); + __publicField(RegionAttachment, "X3", 16); + __publicField(RegionAttachment, "Y3", 17); + __publicField(RegionAttachment, "C3R", 18); + __publicField(RegionAttachment, "C3G", 19); + __publicField(RegionAttachment, "C3B", 20); + __publicField(RegionAttachment, "C3A", 21); + __publicField(RegionAttachment, "U3", 22); + __publicField(RegionAttachment, "V3", 23); + __publicField(RegionAttachment, "X4", 24); + __publicField(RegionAttachment, "Y4", 25); + __publicField(RegionAttachment, "C4R", 26); + __publicField(RegionAttachment, "C4G", 27); + __publicField(RegionAttachment, "C4B", 28); + __publicField(RegionAttachment, "C4A", 29); + __publicField(RegionAttachment, "U4", 30); + __publicField(RegionAttachment, "V4", 31); + + // spine-core/src/AtlasAttachmentLoader.ts + var AtlasAttachmentLoader = class { + atlas; + constructor(atlas) { + this.atlas = atlas; + } + loadSequence(name, basePath, sequence) { + let regions = sequence.regions; + for (let i = 0, n = regions.length; i < n; i++) { + let path = sequence.getPath(basePath, i); + let region = this.atlas.findRegion(path); + if (region == null) + throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")"); + regions[i] = region; + } + } + newRegionAttachment(skin, name, path, sequence) { + let attachment = new RegionAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newMeshAttachment(skin, name, path, sequence) { + let attachment = new MeshAttachment(name, path); + if (sequence != null) { + this.loadSequence(name, path, sequence); + } else { + let region = this.atlas.findRegion(path); + if (!region) + throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")"); + attachment.region = region; + } + return attachment; + } + newBoundingBoxAttachment(skin, name) { + return new BoundingBoxAttachment(name); + } + newPathAttachment(skin, name) { + return new PathAttachment(name); + } + newPointAttachment(skin, name) { + return new PointAttachment(name); + } + newClippingAttachment(skin, name) { + return new ClippingAttachment(name); + } + }; + + // spine-core/src/BoneData.ts + var BoneData = class { + /** The index of the bone in {@link Skeleton#getBones()}. */ + index = 0; + /** The name of the bone, which is unique across all bones in the skeleton. */ + name; + /** @returns May be null. */ + parent = null; + /** The bone's length. */ + length = 0; + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 1; + /** The local scaleY. */ + scaleY = 1; + /** The local shearX. */ + shearX = 0; + /** The local shearX. */ + shearY = 0; + /** The transform mode for how parent world transforms affect this bone. */ + inherit = Inherit.Normal; + /** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this + * bone. + * @see Skin#bones */ + skinRequired = false; + /** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually + * rendered at runtime. */ + color = new Color(); + /** The bone icon as it was in Spine, or null if nonessential data was not exported. */ + icon; + /** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = false; + constructor(index, name, parent) { + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + this.index = index; + this.name = name; + this.parent = parent; + } + }; + var Inherit = /* @__PURE__ */ ((Inherit2) => { + Inherit2[Inherit2["Normal"] = 0] = "Normal"; + Inherit2[Inherit2["OnlyTranslation"] = 1] = "OnlyTranslation"; + Inherit2[Inherit2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection"; + Inherit2[Inherit2["NoScale"] = 3] = "NoScale"; + Inherit2[Inherit2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection"; + return Inherit2; + })(Inherit || {}); + + // spine-core/src/Bone.ts + var Bone = class { + /** The bone's setup pose data. */ + data; + /** The skeleton this bone belongs to. */ + skeleton; + /** The parent bone, or null if this is the root bone. */ + parent = null; + /** The immediate children of this bone. */ + children = new Array(); + /** The local x translation. */ + x = 0; + /** The local y translation. */ + y = 0; + /** The local rotation in degrees, counter clockwise. */ + rotation = 0; + /** The local scaleX. */ + scaleX = 0; + /** The local scaleY. */ + scaleY = 0; + /** The local shearX. */ + shearX = 0; + /** The local shearY. */ + shearY = 0; + /** The applied local x translation. */ + ax = 0; + /** The applied local y translation. */ + ay = 0; + /** The applied local rotation in degrees, counter clockwise. */ + arotation = 0; + /** The applied local scaleX. */ + ascaleX = 0; + /** The applied local scaleY. */ + ascaleY = 0; + /** The applied local shearX. */ + ashearX = 0; + /** The applied local shearY. */ + ashearY = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + a = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + b = 0; + /** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */ + c = 0; + /** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */ + d = 0; + /** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldY = 0; + /** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */ + worldX = 0; + inherit = 0 /* Normal */; + sorted = false; + active = false; + /** @param parent May be null. */ + constructor(data, skeleton, parent) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + this.setToSetupPose(); + } + /** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the + * {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */ + isActive() { + return this.active; + } + /** Computes the world transform using the parent bone and this bone's local applied transform. */ + update(physics) { + this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY); + } + /** Computes the world transform using the parent bone and this bone's local transform. + * + * See {@link #updateWorldTransformWith()}. */ + updateWorldTransform() { + this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY); + } + /** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the + * specified local transform. Child bones are not updated. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) { + this.ax = x; + this.ay = y; + this.arotation = rotation; + this.ascaleX = scaleX; + this.ascaleY = scaleY; + this.ashearX = shearX; + this.ashearY = shearY; + let parent = this.parent; + if (!parent) { + let skeleton = this.skeleton; + const sx = skeleton.scaleX, sy = skeleton.scaleY; + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX * sx; + this.b = Math.cos(ry) * scaleY * sx; + this.c = Math.sin(rx) * scaleX * sy; + this.d = Math.sin(ry) * scaleY * sy; + this.worldX = x * sx + skeleton.x; + this.worldY = y * sy + skeleton.y; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + this.worldX = pa * x + pb * y + parent.worldX; + this.worldY = pc * x + pd * y + parent.worldY; + switch (this.inherit) { + case 0 /* Normal */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la + pb * lc; + this.b = pa * lb + pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + return; + } + case 1 /* OnlyTranslation */: { + const rx = (rotation + shearX) * MathUtils.degRad; + const ry = (rotation + 90 + shearY) * MathUtils.degRad; + this.a = Math.cos(rx) * scaleX; + this.b = Math.cos(ry) * scaleY; + this.c = Math.sin(rx) * scaleX; + this.d = Math.sin(ry) * scaleY; + break; + } + case 2 /* NoRotationOrReflection */: { + let sx = 1 / this.skeleton.scaleX, sy = 1 / this.skeleton.scaleY; + pa *= sx; + pc *= sy; + let s = pa * pa + pc * pc; + let prx = 0; + if (s > 1e-4) { + s = Math.abs(pa * pd * sy - pb * sx * pc) / s; + pb = pc * s; + pd = pa * s; + prx = Math.atan2(pc, pa) * MathUtils.radDeg; + } else { + pa = 0; + pc = 0; + prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg; + } + const rx = (rotation + shearX - prx) * MathUtils.degRad; + const ry = (rotation + shearY - prx + 90) * MathUtils.degRad; + const la = Math.cos(rx) * scaleX; + const lb = Math.cos(ry) * scaleY; + const lc = Math.sin(rx) * scaleX; + const ld = Math.sin(ry) * scaleY; + this.a = pa * la - pb * lc; + this.b = pa * lb - pb * ld; + this.c = pc * la + pd * lc; + this.d = pc * lb + pd * ld; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: { + rotation *= MathUtils.degRad; + const cos = Math.cos(rotation), sin = Math.sin(rotation); + let za = (pa * cos + pb * sin) / this.skeleton.scaleX; + let zc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(za * za + zc * zc); + if (s > 1e-5) + s = 1 / s; + za *= s; + zc *= s; + s = Math.sqrt(za * za + zc * zc); + if (this.inherit == 3 /* NoScale */ && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + rotation = Math.PI / 2 + Math.atan2(zc, za); + const zb = Math.cos(rotation) * s; + const zd = Math.sin(rotation) * s; + shearX *= MathUtils.degRad; + shearY = (90 + shearY) * MathUtils.degRad; + const la = Math.cos(shearX) * scaleX; + const lb = Math.cos(shearY) * scaleY; + const lc = Math.sin(shearX) * scaleX; + const ld = Math.sin(shearY) * scaleY; + this.a = za * la + zb * lc; + this.b = za * lb + zb * ld; + this.c = zc * la + zd * lc; + this.d = zc * lb + zd * ld; + break; + } + } + this.a *= this.skeleton.scaleX; + this.b *= this.skeleton.scaleX; + this.c *= this.skeleton.scaleY; + this.d *= this.skeleton.scaleY; + } + /** Sets this bone's local transform to the setup pose. */ + setToSetupPose() { + let data = this.data; + this.x = data.x; + this.y = data.y; + this.rotation = data.rotation; + this.scaleX = data.scaleX; + this.scaleY = data.scaleY; + this.shearX = data.shearX; + this.shearY = data.shearY; + this.inherit = data.inherit; + } + /** Computes the applied transform values from the world transform. + * + * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, 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 other + * constraints). + * + * 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. */ + updateAppliedTransform() { + let parent = this.parent; + if (!parent) { + this.ax = this.worldX - this.skeleton.x; + this.ay = this.worldY - this.skeleton.y; + this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg; + this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c); + this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d); + this.ashearX = 0; + this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg; + return; + } + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + let pid = 1 / (pa * pd - pb * pc); + let ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid; + let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY; + this.ax = dx * ia - dy * ib; + this.ay = dy * id - dx * ic; + let ra, rb, rc, rd; + if (this.inherit == 1 /* OnlyTranslation */) { + ra = this.a; + rb = this.b; + rc = this.c; + rd = this.d; + } else { + switch (this.inherit) { + case 2 /* NoRotationOrReflection */: { + let s2 = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc); + pb = -pc * this.skeleton.scaleX * s2 / this.skeleton.scaleY; + pd = pa * this.skeleton.scaleY * s2 / this.skeleton.scaleX; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + break; + } + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation); + pa = (pa * cos + pb * sin) / this.skeleton.scaleX; + pc = (pc * cos + pd * sin) / this.skeleton.scaleY; + let s = Math.sqrt(pa * pa + pc * pc); + if (s > 1e-5) + s = 1 / s; + pa *= s; + pc *= s; + s = Math.sqrt(pa * pa + pc * pc); + if (this.inherit == 3 /* NoScale */ && pid < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) + s = -s; + let r = MathUtils.PI / 2 + Math.atan2(pc, pa); + pb = Math.cos(r) * s; + pd = Math.sin(r) * s; + pid = 1 / (pa * pd - pb * pc); + ia = pd * pid; + ib = pb * pid; + ic = pc * pid; + id = pa * pid; + } + ra = ia * this.a - ib * this.c; + rb = ia * this.b - ib * this.d; + rc = id * this.c - ic * this.a; + rd = id * this.d - ic * this.b; + } + this.ashearX = 0; + this.ascaleX = Math.sqrt(ra * ra + rc * rc); + if (this.ascaleX > 1e-4) { + let det = ra * rd - rb * rc; + this.ascaleY = det / this.ascaleX; + this.ashearY = -Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg; + this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg; + } else { + this.ascaleX = 0; + this.ascaleY = Math.sqrt(rb * rb + rd * rd); + this.ashearY = 0; + this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg; + } + } + /** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */ + getWorldRotationX() { + return Math.atan2(this.c, this.a) * MathUtils.radDeg; + } + /** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */ + getWorldRotationY() { + return Math.atan2(this.d, this.b) * MathUtils.radDeg; + } + /** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */ + getWorldScaleX() { + return Math.sqrt(this.a * this.a + this.c * this.c); + } + /** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */ + getWorldScaleY() { + return Math.sqrt(this.b * this.b + this.d * this.d); + } + /** Transforms a point from world coordinates to the bone's local coordinates. */ + worldToLocal(world) { + let invDet = 1 / (this.a * this.d - this.b * this.c); + let x = world.x - this.worldX, y = world.y - this.worldY; + world.x = x * this.d * invDet - y * this.b * invDet; + world.y = y * this.a * invDet - x * this.c * invDet; + return world; + } + /** Transforms a point from the bone's local coordinates to world coordinates. */ + localToWorld(local) { + let x = local.x, y = local.y; + local.x = x * this.a + y * this.b + this.worldX; + local.y = x * this.c + y * this.d + this.worldY; + return local; + } + /** Transforms a point from world coordinates to the parent bone's local coordinates. */ + worldToParent(world) { + if (world == null) + throw new Error("world cannot be null."); + return this.parent == null ? world : this.parent.worldToLocal(world); + } + /** Transforms a point from the parent bone's coordinates to world coordinates. */ + parentToWorld(world) { + if (world == null) + throw new Error("world cannot be null."); + return this.parent == null ? world : this.parent.localToWorld(world); + } + /** Transforms a world rotation to a local rotation. */ + worldToLocalRotation(worldRotation) { + let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation); + return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX; + } + /** Transforms a local rotation to a world rotation. */ + localToWorldRotation(localRotation) { + localRotation -= this.rotation - this.shearX; + let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation); + return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg; + } + /** Rotates the world transform the specified amount. + *

    + * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and + * {@link #update(Physics)} will need to be called on any child bones, recursively. */ + rotateWorld(degrees) { + degrees *= MathUtils.degRad; + const sin = Math.sin(degrees), cos = Math.cos(degrees); + const ra = this.a, rb = this.b; + this.a = cos * ra - sin * this.c; + this.b = cos * rb - sin * this.d; + this.c = sin * ra + cos * this.c; + this.d = sin * rb + cos * this.d; + } + }; + + // spine-core/src/ConstraintData.ts + var ConstraintData = class { + constructor(name, order, skinRequired) { + this.name = name; + this.order = order; + this.skinRequired = skinRequired; + } + }; + + // spine-core/src/AssetManagerBase.ts + var AssetManagerBase = class { + pathPrefix = ""; + textureLoader; + downloader; + assets = {}; + errors = {}; + toLoad = 0; + loaded = 0; + constructor(textureLoader, pathPrefix = "", downloader = new Downloader()) { + this.textureLoader = textureLoader; + this.pathPrefix = pathPrefix; + this.downloader = downloader; + } + start(path) { + this.toLoad++; + return this.pathPrefix + path; + } + success(callback, path, asset) { + this.toLoad--; + this.loaded++; + this.assets[path] = asset; + if (callback) + callback(path, asset); + } + error(callback, path, message) { + this.toLoad--; + this.loaded++; + this.errors[path] = message; + if (callback) + callback(path, message); + } + loadAll() { + let promise = new Promise((resolve, reject) => { + let check = () => { + if (this.isLoadingComplete()) { + if (this.hasErrors()) + reject(this.errors); + else + resolve(this); + return; + } + requestAnimationFrame(check); + }; + requestAnimationFrame(check); + }); + return promise; + } + setRawDataURI(path, data) { + this.downloader.rawDataUris[this.pathPrefix + path] = data; + } + loadBinary(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadBinary(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`); + }); + } + loadText(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadText(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`); + }); + } + loadJson(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + this.downloader.downloadJson(path, (data) => { + this.success(success, path, data); + }, (status, responseText) => { + this.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`); + }); + } + loadTexture(path, success = () => { + }, error = () => { + }) { + path = this.start(path); + let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document); + let isWebWorker = !isBrowser; + if (isWebWorker) { + fetch(path, { mode: "cors" }).then((response) => { + if (response.ok) + return response.blob(); + this.error(error, path, `Couldn't load image: ${path}`); + return null; + }).then((blob) => { + return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null; + }).then((bitmap) => { + if (bitmap) + this.success(success, path, this.textureLoader(bitmap)); + }); + } else { + let image = new Image(); + image.crossOrigin = "anonymous"; + image.onload = () => { + this.success(success, path, this.textureLoader(image)); + }; + image.onerror = () => { + this.error(error, path, `Couldn't load image: ${path}`); + }; + if (this.downloader.rawDataUris[path]) + path = this.downloader.rawDataUris[path]; + image.src = path; + } + } + loadTextureAtlas(path, success = () => { + }, error = () => { + }, fileAlias) { + let index = path.lastIndexOf("/"); + let parent = index >= 0 ? path.substring(0, index + 1) : ""; + path = this.start(path); + this.downloader.downloadText(path, (atlasText) => { + try { + let atlas = new TextureAtlas(atlasText); + let toLoad = atlas.pages.length, abort = false; + for (let page of atlas.pages) { + this.loadTexture( + !fileAlias ? parent + page.name : fileAlias[page.name], + (imagePath, texture) => { + if (!abort) { + page.setTexture(texture); + if (--toLoad == 0) + this.success(success, path, atlas); + } + }, + (imagePath, message) => { + if (!abort) + this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`); + abort = true; + } + ); + } + } catch (e) { + this.error(error, path, `Couldn't parse texture atlas ${path}: ${e.message}`); + } + }, (status, responseText) => { + this.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`); + }); + } + get(path) { + return this.assets[this.pathPrefix + path]; + } + require(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset) + return asset; + let error = this.errors[path]; + throw Error("Asset not found: " + path + (error ? "\n" + error : "")); + } + remove(path) { + path = this.pathPrefix + path; + let asset = this.assets[path]; + if (asset.dispose) + asset.dispose(); + delete this.assets[path]; + return asset; + } + removeAll() { + for (let key in this.assets) { + let asset = this.assets[key]; + if (asset.dispose) + asset.dispose(); + } + this.assets = {}; + } + isLoadingComplete() { + return this.toLoad == 0; + } + getToLoad() { + return this.toLoad; + } + getLoaded() { + return this.loaded; + } + dispose() { + this.removeAll(); + } + hasErrors() { + return Object.keys(this.errors).length > 0; + } + getErrors() { + return this.errors; + } + }; + var Downloader = class { + callbacks = {}; + rawDataUris = {}; + dataUriToString(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx != -1) { + base64Idx += "base64,".length; + return atob(dataUri.substr(base64Idx)); + } else { + return dataUri.substr(dataUri.indexOf(",") + 1); + } + } + base64ToUint8Array(base64) { + var binary_string = window.atob(base64); + var len = binary_string.length; + var bytes = new Uint8Array(len); + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + } + dataUriToUint8Array(dataUri) { + if (!dataUri.startsWith("data:")) { + throw new Error("Not a data URI."); + } + let base64Idx = dataUri.indexOf("base64,"); + if (base64Idx == -1) + throw new Error("Not a binary data URI."); + base64Idx += "base64,".length; + return this.base64ToUint8Array(dataUri.substr(base64Idx)); + } + downloadText(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToString(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.overrideMimeType("text/html"); + request.open("GET", url, true); + let done = () => { + this.finish(url, request.status, request.responseText); + }; + request.onload = done; + request.onerror = done; + request.send(); + } + downloadJson(url, success, error) { + this.downloadText(url, (data) => { + success(JSON.parse(data)); + }, error); + } + downloadBinary(url, success, error) { + if (this.start(url, success, error)) + return; + if (this.rawDataUris[url]) { + try { + let dataUri = this.rawDataUris[url]; + this.finish(url, 200, this.dataUriToUint8Array(dataUri)); + } catch (e) { + this.finish(url, 400, JSON.stringify(e)); + } + return; + } + let request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "arraybuffer"; + let onerror = () => { + this.finish(url, request.status, request.response); + }; + request.onload = () => { + if (request.status == 200 || request.status == 0) + this.finish(url, 200, new Uint8Array(request.response)); + else + onerror(); + }; + request.onerror = onerror; + request.send(); + } + start(url, success, error) { + let callbacks = this.callbacks[url]; + try { + if (callbacks) + return true; + this.callbacks[url] = callbacks = []; + } finally { + callbacks.push(success, error); + } + } + finish(url, status, data) { + let callbacks = this.callbacks[url]; + delete this.callbacks[url]; + let args = status == 200 || status == 0 ? [data] : [status, data]; + for (let i = args.length - 1, n = callbacks.length; i < n; i += 2) + callbacks[i].apply(null, args); + } + }; + + // spine-core/src/Event.ts + var Event = class { + data; + intValue = 0; + floatValue = 0; + stringValue = null; + time = 0; + volume = 0; + balance = 0; + constructor(time, data) { + if (!data) + throw new Error("data cannot be null."); + this.time = time; + this.data = data; + } + }; + + // spine-core/src/EventData.ts + var EventData = class { + name; + intValue = 0; + floatValue = 0; + stringValue = null; + audioPath = null; + volume = 0; + balance = 0; + constructor(name) { + this.name = name; + } + }; + + // spine-core/src/IkConstraint.ts + var IkConstraint = class { + /** The IK constraint's setup pose data. */ + data; + /** The bones that will be modified by this IK constraint. */ + bones; + /** The bone that is the IK target. */ + target; + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 1; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) + throw new Error(`Couldn't find bone ${data.target.name}`); + this.target = target; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.mix = data.mix; + this.softness = data.softness; + this.bendDirection = data.bendDirection; + this.compress = data.compress; + this.stretch = data.stretch; + } + update(physics) { + if (this.mix == 0) + return; + let target = this.target; + let bones = this.bones; + switch (bones.length) { + case 1: + this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix); + break; + case 2: + this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix); + break; + } + } + /** Applies 1 bone IK. The target is specified in the world coordinate system. */ + apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) { + let p = bone.parent; + if (!p) + throw new Error("IK bone must have parent."); + let pa = p.a, pb = p.b, pc = p.c, pd = p.d; + let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0; + switch (bone.inherit) { + case 1 /* OnlyTranslation */: + tx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX); + ty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY); + break; + case 2 /* NoRotationOrReflection */: + let s = Math.abs(pa * pd - pb * pc) / Math.max(1e-4, pa * pa + pc * pc); + let sa = pa / bone.skeleton.scaleX; + let sc = pc / bone.skeleton.scaleY; + pb = -sc * s * bone.skeleton.scaleX; + pd = sa * s * bone.skeleton.scaleY; + rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg; + default: + let x = targetX - p.worldX, y = targetY - p.worldY; + let d = pa * pd - pb * pc; + if (Math.abs(d) <= 1e-4) { + tx = 0; + ty = 0; + } else { + tx = (x * pd - y * pb) / d - bone.ax; + ty = (y * pa - x * pc) / d - bone.ay; + } + } + rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg; + if (bone.ascaleX < 0) + rotationIK += 180; + if (rotationIK > 180) + rotationIK -= 360; + else if (rotationIK < -180) + rotationIK += 360; + let sx = bone.ascaleX, sy = bone.ascaleY; + if (compress || stretch) { + switch (bone.inherit) { + case 3 /* NoScale */: + case 4 /* NoScaleOrReflection */: + tx = targetX - bone.worldX; + ty = targetY - bone.worldY; + } + const b = bone.data.length * sx; + if (b > 1e-4) { + const dd = tx * tx + ty * ty; + if (compress && dd < b * b || stretch && dd > b * b) { + const s = (Math.sqrt(dd) / b - 1) * alpha + 1; + sx *= s; + if (uniform) + sy *= s; + } + } + } + bone.updateWorldTransformWith( + bone.ax, + bone.ay, + bone.arotation + rotationIK * alpha, + sx, + sy, + bone.ashearX, + bone.ashearY + ); + } + /** Applies 2 bone IK. The target is specified in the world coordinate system. + * @param child A direct descendant of the parent bone. */ + apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) { + if (parent.inherit != 0 /* Normal */ || child.inherit != 0 /* Normal */) + return; + let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; + let os1 = 0, os2 = 0, s2 = 0; + if (psx < 0) { + psx = -psx; + os1 = 180; + s2 = -1; + } else { + os1 = 0; + s2 = 1; + } + if (psy < 0) { + psy = -psy; + s2 = -s2; + } + if (csx < 0) { + csx = -csx; + os2 = 180; + } else + os2 = 0; + let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d; + let u = Math.abs(psx - psy) <= 1e-4; + if (!u || stretch) { + cy = 0; + cwx = a * cx + parent.worldX; + cwy = c * cx + parent.worldY; + } else { + cy = child.ay; + cwx = a * cx + b * cy + parent.worldX; + cwy = c * cx + d * cy + parent.worldY; + } + let pp = parent.parent; + if (!pp) + throw new Error("IK parent must itself have a parent."); + a = pp.a; + b = pp.b; + c = pp.c; + d = pp.d; + let id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY; + id = Math.abs(id) <= 1e-4 ? 0 : 1 / id; + let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; + if (l1 < 1e-4) { + this.apply1(parent, targetX, targetY, false, stretch, false, alpha); + child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + return; + } + x = targetX - pp.worldX; + y = targetY - pp.worldY; + let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + let dd = tx * tx + ty * ty; + if (softness != 0) { + softness *= psx * (csx + 1) * 0.5; + let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness; + if (sd > 0) { + let p = Math.min(1, sd / (softness * 2)) - 1; + p = (sd - softness * (1 - p * p)) / td; + tx -= p * tx; + ty -= p * ty; + dd = tx * tx + ty * ty; + } + } + outer: + if (u) { + l2 *= psx; + let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) { + cos = -1; + a2 = Math.PI * bendDir; + } else if (cos > 1) { + cos = 1; + a2 = 0; + if (stretch) { + a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) + sy *= a; + } + } else + a2 = Math.acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * Math.sin(a2); + a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b); + } else { + a = psx * l2; + b = psy * l2; + let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + let c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) { + let q = Math.sqrt(d); + if (c1 < 0) + q = -q; + q = -(c1 + q) * 0.5; + let r0 = q / c2, r1 = c / q; + let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1; + r0 = dd - r * r; + if (r0 >= 0) { + y = Math.sqrt(r0) * bendDir; + a1 = ta - Math.atan2(y, r); + a2 = Math.atan2(y / psy, (r - l1) / psx); + break outer; + } + } + let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; + let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) { + c = Math.acos(c); + x = a * Math.cos(c) + l1; + y = b * Math.sin(c); + d = x * x + y * y; + if (d < minDist) { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + if (d > maxDist) { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + if (dd <= (minDist + maxDist) * 0.5) { + a1 = ta - Math.atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } else { + a1 = ta - Math.atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + let os = Math.atan2(cy, cx) * s2; + let rotation = parent.arotation; + a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation; + if (a1 > 180) + a1 -= 360; + else if (a1 < -180) + a1 += 360; + parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0); + rotation = child.arotation; + a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation; + if (a2 > 180) + a2 -= 360; + else if (a2 < -180) + a2 += 360; + child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); + } + }; + + // spine-core/src/IkConstraintData.ts + var IkConstraintData = class extends ConstraintData { + /** The bones that are constrained by this IK constraint. */ + bones = new Array(); + /** The bone that is the IK target. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + /** Controls the bend direction of the IK bones, either 1 or -1. */ + bendDirection = 0; + /** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ + compress = false; + /** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained + * and the parent bone has local nonuniform scale, stretch is not applied. */ + stretch = false; + /** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone + * is scaled on both the X and Y axes. */ + uniform = false; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */ + mix = 0; + /** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ + softness = 0; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/PathConstraintData.ts + var PathConstraintData = class extends ConstraintData { + /** The bones that will be modified by this path constraint. */ + bones = new Array(); + /** The slot whose path attachment will be used to constrained the bones. */ + _target = null; + set target(slotData) { + this._target = slotData; + } + get target() { + if (!this._target) + throw new Error("SlotData not set."); + else + return this._target; + } + /** The mode for positioning the first bone on the path. */ + positionMode = PositionMode.Fixed; + /** The mode for positioning the bones after the first bone on the path. */ + spacingMode = SpacingMode.Fixed; + /** The mode for adjusting the rotation of the bones. */ + rotateMode = RotateMode.Chain; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + constructor(name) { + super(name, 0, false); + } + }; + var PositionMode = /* @__PURE__ */ ((PositionMode2) => { + PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed"; + PositionMode2[PositionMode2["Percent"] = 1] = "Percent"; + return PositionMode2; + })(PositionMode || {}); + var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => { + SpacingMode2[SpacingMode2["Length"] = 0] = "Length"; + SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed"; + SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent"; + SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional"; + return SpacingMode2; + })(SpacingMode || {}); + var RotateMode = /* @__PURE__ */ ((RotateMode2) => { + RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent"; + RotateMode2[RotateMode2["Chain"] = 1] = "Chain"; + RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale"; + return RotateMode2; + })(RotateMode || {}); + + // spine-core/src/PathConstraint.ts + var _PathConstraint = class { + /** The path constraint's setup pose data. */ + data; + /** The bones that will be modified by this path constraint. */ + bones; + /** The slot whose path attachment will be used to constrained the bones. */ + target; + /** The position along the path. */ + position = 0; + /** The spacing between bones. */ + spacing = 0; + mixRotate = 0; + mixX = 0; + mixY = 0; + spaces = new Array(); + positions = new Array(); + world = new Array(); + curves = new Array(); + lengths = new Array(); + segments = new Array(); + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0, n = data.bones.length; i < n; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findSlot(data.target.name); + if (!target) + throw new Error(`Couldn't find target bone ${data.target.name}`); + this.target = target; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.position = data.position; + this.spacing = data.spacing; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + } + update(physics) { + let attachment = this.target.getAttachment(); + if (!(attachment instanceof PathAttachment)) + return; + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY; + if (mixRotate == 0 && mixX == 0 && mixY == 0) + return; + let data = this.data; + let tangents = data.rotateMode == 0 /* Tangent */, scale = data.rotateMode == 2 /* ChainScale */; + let bones = this.bones; + let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1; + let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : []; + let spacing = this.spacing; + switch (data.spacingMode) { + case 2 /* Percent */: + if (scale) { + for (let i = 0, n = spacesCount - 1; i < n; i++) { + let bone = bones[i]; + let setupLength = bone.data.length; + let x = setupLength * bone.a, y = setupLength * bone.c; + lengths[i] = Math.sqrt(x * x + y * y); + } + } + Utils.arrayFill(spaces, 1, spacesCount, spacing); + break; + case 3 /* Proportional */: + let sum = 0; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (let i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + default: + let lengthSpacing = data.spacingMode == 0 /* Length */; + for (let i = 0, n = spacesCount - 1; i < n; ) { + let bone = bones[i]; + let setupLength = bone.data.length; + if (setupLength < _PathConstraint.epsilon) { + if (scale) + lengths[i] = 0; + spaces[++i] = spacing; + } else { + let x = setupLength * bone.a, y = setupLength * bone.c; + let length = Math.sqrt(x * x + y * y); + if (scale) + lengths[i] = length; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + let positions = this.computeWorldPositions(attachment, spacesCount, tangents); + let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + let tip = false; + if (offsetRotation == 0) + tip = data.rotateMode == 1 /* Chain */; + else { + tip = false; + let p = this.target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad; + } + for (let i = 0, p = 3; i < boneCount; i++, p += 3) { + let bone = bones[i]; + bone.worldX += (boneX - bone.worldX) * mixX; + bone.worldY += (boneY - bone.worldY) * mixY; + let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) { + let length = lengths[i]; + if (length != 0) { + let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1; + bone.a *= s; + bone.c *= s; + } + } + boneX = x; + boneY = y; + if (mixRotate > 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0; + if (tangents) + r = positions[p - 1]; + else if (spaces[i + 1] == 0) + r = positions[p + 2]; + else + r = Math.atan2(dy, dx); + r -= Math.atan2(c, a); + if (tip) { + cos = Math.cos(r); + sin = Math.sin(r); + let length = bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * mixRotate; + boneY += (length * (sin * a + cos * c) - dy) * mixRotate; + } else { + r += offsetRotation; + } + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + cos = Math.cos(r); + sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.updateAppliedTransform(); + } + } + computeWorldPositions(path, spacesCount, tangents) { + let target = this.target; + let position = this.position; + let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world; + let closed2 = path.closed; + let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE; + if (!path.constantSpeed) { + let lengths = path.lengths; + curveCount -= closed2 ? 1 : 2; + let pathLength2 = lengths[curveCount]; + if (this.data.positionMode == 1 /* Percent */) + position *= pathLength2; + let multiplier2; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier2 = pathLength2; + break; + case 3 /* Proportional */: + multiplier2 = pathLength2 / spacesCount; + break; + default: + multiplier2 = 1; + } + world = Utils.setArraySize(this.world, 8); + for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier2; + position += space; + let p = position; + if (closed2) { + p %= pathLength2; + if (p < 0) + p += pathLength2; + curve = 0; + } else if (p < 0) { + if (prevCurve != _PathConstraint.BEFORE) { + prevCurve = _PathConstraint.BEFORE; + path.computeWorldVertices(target, 2, 4, world, 0, 2); + } + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength2) { + if (prevCurve != _PathConstraint.AFTER) { + prevCurve = _PathConstraint.AFTER; + path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2); + } + this.addAfterPosition(p - pathLength2, world, 0, out, o); + continue; + } + for (; ; curve++) { + let length = lengths[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = lengths[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + if (closed2 && curve == curveCount) { + path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2); + path.computeWorldVertices(target, 0, 4, world, 4, 2); + } else + path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2); + } + this.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 + ); + } + return out; + } + if (closed2) { + verticesLength += 2; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2); + path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } else { + curveCount--; + verticesLength -= 4; + world = Utils.setArraySize(this.world, verticesLength); + path.computeWorldVertices(target, 2, verticesLength, world, 0, 2); + } + let curves = Utils.setArraySize(this.curves, curveCount); + let pathLength = 0; + let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0; + for (let i = 0, w = 2; i < curveCount; i++, w += 6) { + cx1 = world[w]; + cy1 = world[w + 1]; + cx2 = world[w + 2]; + cy2 = world[w + 3]; + x2 = world[w + 4]; + y2 = world[w + 5]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.1875; + tmpy = (y1 - cy1 * 2 + cy2) * 0.1875; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += Math.sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + if (this.data.positionMode == 1 /* Percent */) + position *= pathLength; + let multiplier; + switch (this.data.spacingMode) { + case 2 /* Percent */: + multiplier = pathLength; + break; + case 3 /* Proportional */: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + let segments = this.segments; + let curveLength = 0; + for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { + let space = spaces[i] * multiplier; + position += space; + let p = position; + if (closed2) { + p %= pathLength; + if (p < 0) + p += pathLength; + curve = 0; + } else if (p < 0) { + this.addBeforePosition(p, world, 0, out, o); + continue; + } else if (p > pathLength) { + this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o); + continue; + } + for (; ; curve++) { + let length = curves[curve]; + if (p > length) + continue; + if (curve == 0) + p /= length; + else { + let prev = curves[curve - 1]; + p = (p - prev) / (length - prev); + } + break; + } + if (curve != prevCurve) { + prevCurve = curve; + let ii = curve * 6; + x1 = world[ii]; + y1 = world[ii + 1]; + cx1 = world[ii + 2]; + cy1 = world[ii + 3]; + cx2 = world[ii + 4]; + cy2 = world[ii + 5]; + x2 = world[ii + 6]; + y2 = world[ii + 7]; + tmpx = (x1 - cx1 * 2 + cx2) * 0.03; + tmpy = (y1 - cy1 * 2 + cy2) * 0.03; + dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3; + dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3; + ddfx = tmpx * 2 + dddfx; + ddfy = tmpy * 2 + dddfy; + dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667; + dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667; + curveLength = Math.sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += Math.sqrt(dfx * dfx + dfy * dfy); + segments[9] = curveLength; + segment = 0; + } + p *= curveLength; + for (; ; segment++) { + let length = segments[segment]; + if (p > length) + continue; + if (segment == 0) + p /= length; + else { + let prev = segments[segment - 1]; + p = segment + (p - prev) / (length - prev); + } + break; + } + this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0); + } + return out; + } + addBeforePosition(p, temp, i, out, o) { + let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addAfterPosition(p, temp, i, out, o) { + let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx); + out[o] = x1 + p * Math.cos(r); + out[o + 1] = y1 + p * Math.sin(r); + out[o + 2] = r; + } + addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) { + if (p == 0 || isNaN(p)) { + out[o] = x1; + out[o + 1] = y1; + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + return; + } + let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + out[o] = x; + out[o + 1] = y; + if (tangents) { + if (p < 1e-3) + out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1); + else + out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } + }; + var PathConstraint = _PathConstraint; + __publicField(PathConstraint, "NONE", -1); + __publicField(PathConstraint, "BEFORE", -2); + __publicField(PathConstraint, "AFTER", -3); + __publicField(PathConstraint, "epsilon", 1e-5); + + // spine-core/src/PhysicsConstraint.ts + var PhysicsConstraint = class { + data; + _bone = null; + /** The bone constrained by this physics constraint. */ + set bone(bone) { + this._bone = bone; + } + get bone() { + if (!this._bone) + throw new Error("Bone not set."); + else + return this._bone; + } + inertia = 0; + strength = 0; + damping = 0; + massInverse = 0; + wind = 0; + gravity = 0; + mix = 0; + _reset = true; + ux = 0; + uy = 0; + cx = 0; + cy = 0; + tx = 0; + ty = 0; + xOffset = 0; + xVelocity = 0; + yOffset = 0; + yVelocity = 0; + rotateOffset = 0; + rotateVelocity = 0; + scaleOffset = 0; + scaleVelocity = 0; + active = false; + skeleton; + remaining = 0; + lastTime = 0; + constructor(data, skeleton) { + this.data = data; + this.skeleton = skeleton; + this.bone = skeleton.bones[data.bone.index]; + this.inertia = data.inertia; + this.strength = data.strength; + this.damping = data.damping; + this.massInverse = data.massInverse; + this.wind = data.wind; + this.gravity = data.gravity; + this.mix = data.mix; + } + reset() { + this.remaining = 0; + this.lastTime = this.skeleton.time; + this._reset = true; + this.xOffset = 0; + this.xVelocity = 0; + this.yOffset = 0; + this.yVelocity = 0; + this.rotateOffset = 0; + this.rotateVelocity = 0; + this.scaleOffset = 0; + this.scaleVelocity = 0; + } + setToSetupPose() { + const data = this.data; + this.inertia = data.inertia; + this.strength = data.strength; + this.damping = data.damping; + this.massInverse = data.massInverse; + this.wind = data.wind; + this.gravity = data.gravity; + this.mix = data.mix; + } + isActive() { + return this.active; + } + /** Applies the constraint to the constrained bones. */ + update(physics) { + const mix = this.mix; + if (mix == 0) + return; + const x = this.data.x > 0, y = this.data.y > 0, rotateOrShearX = this.data.rotate > 0 || this.data.shearX > 0, scaleX = this.data.scaleX > 0; + const bone = this.bone; + const l = bone.data.length; + switch (physics) { + case 0 /* none */: + return; + case 1 /* reset */: + this.reset(); + case 2 /* update */: + const skeleton = this.skeleton; + const delta = Math.max(this.skeleton.time - this.lastTime, 0); + this.remaining += delta; + this.lastTime = skeleton.time; + const bx = bone.worldX, by = bone.worldY; + if (this._reset) { + this._reset = false; + this.ux = bx; + this.uy = by; + } else { + let a = this.remaining, i = this.inertia, t = this.data.step, f = this.skeleton.data.referenceScale, d = -1; + let qx = this.data.limit * delta, qy = qx * Math.abs(skeleton.scaleY); + qx *= Math.abs(skeleton.scaleX); + if (x || y) { + if (x) { + const u = (this.ux - bx) * i; + this.xOffset += u > qx ? qx : u < -qx ? -qx : u; + this.ux = bx; + } + if (y) { + const u = (this.uy - by) * i; + this.yOffset += u > qy ? qy : u < -qy ? -qy : u; + this.uy = by; + } + if (a >= t) { + d = Math.pow(this.damping, 60 * t); + const m = this.massInverse * t, e = this.strength, w = this.wind * f * skeleton.scaleX, g = this.gravity * f * skeleton.scaleY; + do { + if (x) { + this.xVelocity += (w - this.xOffset * e) * m; + this.xOffset += this.xVelocity * t; + this.xVelocity *= d; + } + if (y) { + this.yVelocity -= (g + this.yOffset * e) * m; + this.yOffset += this.yVelocity * t; + this.yVelocity *= d; + } + a -= t; + } while (a >= t); + } + if (x) + bone.worldX += this.xOffset * mix * this.data.x; + if (y) + bone.worldY += this.yOffset * mix * this.data.y; + } + if (rotateOrShearX || scaleX) { + let ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0; + let dx = this.cx - bone.worldX, dy = this.cy - bone.worldY; + if (dx > qx) + dx = qx; + else if (dx < -qx) + dx = -qx; + if (dy > qy) + dy = qy; + else if (dy < -qy) + dy = -qy; + if (rotateOrShearX) { + mr = (this.data.rotate + this.data.shearX) * mix; + let r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr; + this.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i; + r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + if (scaleX) { + r = l * bone.getWorldScaleX(); + if (r > 0) + this.scaleOffset += (dx * c + dy * s) * i / r; + } + } else { + c = Math.cos(ca); + s = Math.sin(ca); + const r = l * bone.getWorldScaleX(); + if (r > 0) + this.scaleOffset += (dx * c + dy * s) * i / r; + } + a = this.remaining; + if (a >= t) { + if (d == -1) + d = Math.pow(this.damping, 60 * t); + const m = this.massInverse * t, e = this.strength, w = this.wind, g = Skeleton.yDown ? -this.gravity : this.gravity, h = l / f; + while (true) { + a -= t; + if (scaleX) { + this.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m; + this.scaleOffset += this.scaleVelocity * t; + this.scaleVelocity *= d; + } + if (rotateOrShearX) { + this.rotateVelocity -= ((w * s + g * c) * h + this.rotateOffset * e) * m; + this.rotateOffset += this.rotateVelocity * t; + this.rotateVelocity *= d; + if (a < t) + break; + const r = this.rotateOffset * mr + ca; + c = Math.cos(r); + s = Math.sin(r); + } else if (a < t) + break; + } + } + } + this.remaining = a; + } + this.cx = bone.worldX; + this.cy = bone.worldY; + break; + case 3 /* pose */: + if (x) + bone.worldX += this.xOffset * mix * this.data.x; + if (y) + bone.worldY += this.yOffset * mix * this.data.y; + } + if (rotateOrShearX) { + let o = this.rotateOffset * mix, s = 0, c = 0, a = 0; + if (this.data.shearX > 0) { + let r = 0; + if (this.data.rotate > 0) { + r = o * this.data.rotate; + s = Math.sin(r); + c = Math.cos(r); + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + r += o * this.data.shearX; + s = Math.sin(r); + c = Math.cos(r); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + } else { + o *= this.data.rotate; + s = Math.sin(o); + c = Math.cos(o); + a = bone.a; + bone.a = c * a - s * bone.c; + bone.c = s * a + c * bone.c; + a = bone.b; + bone.b = c * a - s * bone.d; + bone.d = s * a + c * bone.d; + } + } + if (scaleX) { + const s = 1 + this.scaleOffset * mix * this.data.scaleX; + bone.a *= s; + bone.c *= s; + } + if (physics != 3 /* pose */) { + this.tx = l * bone.a; + this.ty = l * bone.c; + } + bone.updateAppliedTransform(); + } + /** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional + * amount in world space. */ + translate(x, y) { + this.ux -= x; + this.uy -= y; + this.cx -= x; + this.cy -= y; + } + /** Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the + * specified point in world space. */ + rotate(x, y, degrees) { + const r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r); + const dx = this.cx - x, dy = this.cy - y; + this.translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy); + } + }; + + // spine-core/src/Slot.ts + var Slot = class { + /** The slot's setup pose data. */ + data; + /** The bone this slot belongs to. */ + bone; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color; + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + attachment = null; + attachmentState = 0; + /** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the + * {@link Sequence#getSetupIndex()}. */ + sequenceIndex = -1; + /** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a + * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions. + * + * See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */ + deform = new Array(); + constructor(data, bone) { + if (!data) + throw new Error("data cannot be null."); + if (!bone) + throw new Error("bone cannot be null."); + this.data = data; + this.bone = bone; + this.color = new Color(); + this.darkColor = !data.darkColor ? null : new Color(); + this.setToSetupPose(); + } + /** The skeleton this slot belongs to. */ + getSkeleton() { + return this.bone.skeleton; + } + /** The current attachment for the slot, or null if the slot has no attachment. */ + getAttachment() { + return this.attachment; + } + /** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}. + * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the + * specified attachment. */ + setAttachment(attachment) { + if (this.attachment == attachment) + return; + if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment != this.attachment.timelineAttachment) { + this.deform.length = 0; + } + this.attachment = attachment; + this.sequenceIndex = -1; + } + /** Sets this slot to the setup pose. */ + setToSetupPose() { + this.color.setFromColor(this.data.color); + if (this.darkColor) + this.darkColor.setFromColor(this.data.darkColor); + if (!this.data.attachmentName) + this.attachment = null; + else { + this.attachment = null; + this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName)); + } + } + }; + + // spine-core/src/TransformConstraint.ts + var TransformConstraint = class { + /** The transform constraint's setup pose data. */ + data; + /** The bones that will be modified by this transform constraint. */ + bones; + /** The target bone whose world transform will be copied to the constrained bones. */ + target; + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + temp = new Vector2(); + active = false; + constructor(data, skeleton) { + if (!data) + throw new Error("data cannot be null."); + if (!skeleton) + throw new Error("skeleton cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let bone = skeleton.findBone(data.bones[i].name); + if (!bone) + throw new Error(`Couldn't find bone ${data.bones[i].name}.`); + this.bones.push(bone); + } + let target = skeleton.findBone(data.target.name); + if (!target) + throw new Error(`Couldn't find target bone ${data.target.name}.`); + this.target = target; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + } + isActive() { + return this.active; + } + setToSetupPose() { + const data = this.data; + this.mixRotate = data.mixRotate; + this.mixX = data.mixX; + this.mixY = data.mixY; + this.mixScaleX = data.mixScaleX; + this.mixScaleY = data.mixScaleY; + this.mixShearY = data.mixShearY; + } + update(physics) { + if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) + return; + if (this.data.local) { + if (this.data.relative) + this.applyRelativeLocal(); + else + this.applyAbsoluteLocal(); + } else { + if (this.data.relative) + this.applyRelativeWorld(); + else + this.applyAbsoluteWorld(); + } + } + applyAbsoluteWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect; + let offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += (temp.x - bone.worldX) * mixX; + bone.worldY += (temp.y - bone.worldY) * mixY; + } + if (mixScaleX != 0) { + let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c); + if (s != 0) + s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d); + if (s != 0) + s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let b = bone.b, d = bone.d; + let by = Math.atan2(d, b); + let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a)); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r = by + (r + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyRelativeWorld() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let translate = mixX != 0 || mixY != 0; + let target = this.target; + let ta = target.a, tb = target.b, tc = target.c, td = target.d; + let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad; + let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (mixRotate != 0) { + let a = bone.a, b = bone.b, c = bone.c, d = bone.d; + let r = Math.atan2(tc, ta) + offsetRotation; + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + r *= mixRotate; + let cos = Math.cos(r), sin = Math.sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + if (translate) { + let temp = this.temp; + target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY)); + bone.worldX += temp.x * mixX; + bone.worldY += temp.y * mixY; + } + if (mixScaleX != 0) { + let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1; + bone.a *= s; + bone.c *= s; + } + if (mixScaleY != 0) { + let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1; + bone.b *= s; + bone.d *= s; + } + if (mixShearY > 0) { + let r = Math.atan2(td, tb) - Math.atan2(tc, ta); + if (r > MathUtils.PI) + r -= MathUtils.PI2; + else if (r < -MathUtils.PI) + r += MathUtils.PI2; + let b = bone.b, d = bone.d; + r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY; + let s = Math.sqrt(b * b + d * d); + bone.b = Math.cos(r) * s; + bone.d = Math.sin(r) * s; + } + bone.updateAppliedTransform(); + } + } + applyAbsoluteLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation; + if (mixRotate != 0) + rotation += (target.arotation - rotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax, y = bone.ay; + x += (target.ax - x + this.data.offsetX) * mixX; + y += (target.ay - y + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX, scaleY = bone.ascaleY; + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY; + let shearY = bone.ashearY; + if (mixShearY != 0) + shearY += (target.ashearY - shearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + applyRelativeLocal() { + let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; + let target = this.target; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate; + let x = bone.ax + (target.ax + this.data.offsetX) * mixX; + let y = bone.ay + (target.ay + this.data.offsetY) * mixY; + let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1); + let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1); + let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY; + bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); + } + } + }; + + // spine-core/src/Skeleton.ts + var _Skeleton = class { + /** The skeleton's setup pose data. */ + data; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones; + /** The skeleton's slots in the setup pose draw order. */ + slots; + /** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */ + drawOrder; + /** The skeleton's IK constraints. */ + ikConstraints; + /** The skeleton's transform constraints. */ + transformConstraints; + /** The skeleton's path constraints. */ + pathConstraints; + /** The skeleton's physics constraints. */ + physicsConstraints; + /** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */ + _updateCache = new Array(); + /** The skeleton's current skin. May be null. */ + skin = null; + /** The color to tint all the skeleton's attachments. */ + color; + /** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + scaleX = 1; + /** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale + * inheritance. */ + _scaleY = 1; + get scaleY() { + return _Skeleton.yDown ? -this._scaleY : this._scaleY; + } + set scaleY(scaleY) { + this._scaleY = scaleY; + } + /** Sets the skeleton X position, which is added to the root bone worldX position. */ + x = 0; + /** Sets the skeleton Y position, which is added to the root bone worldY position. */ + y = 0; + /** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}. + *

    + * See {@link #update(float)}. */ + time = 0; + constructor(data) { + if (!data) + throw new Error("data cannot be null."); + this.data = data; + this.bones = new Array(); + for (let i = 0; i < data.bones.length; i++) { + let boneData = data.bones[i]; + let bone; + if (!boneData.parent) + bone = new Bone(boneData, this, null); + else { + let parent = this.bones[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.push(bone); + } + this.bones.push(bone); + } + this.slots = new Array(); + this.drawOrder = new Array(); + for (let i = 0; i < data.slots.length; i++) { + let slotData = data.slots[i]; + let bone = this.bones[slotData.boneData.index]; + let slot = new Slot(slotData, bone); + this.slots.push(slot); + this.drawOrder.push(slot); + } + this.ikConstraints = new Array(); + for (let i = 0; i < data.ikConstraints.length; i++) { + let ikConstraintData = data.ikConstraints[i]; + this.ikConstraints.push(new IkConstraint(ikConstraintData, this)); + } + this.transformConstraints = new Array(); + for (let i = 0; i < data.transformConstraints.length; i++) { + let transformConstraintData = data.transformConstraints[i]; + this.transformConstraints.push(new TransformConstraint(transformConstraintData, this)); + } + this.pathConstraints = new Array(); + for (let i = 0; i < data.pathConstraints.length; i++) { + let pathConstraintData = data.pathConstraints[i]; + this.pathConstraints.push(new PathConstraint(pathConstraintData, this)); + } + this.physicsConstraints = new Array(); + for (let i = 0; i < data.physicsConstraints.length; i++) { + let physicsConstraintData = data.physicsConstraints[i]; + this.physicsConstraints.push(new PhysicsConstraint(physicsConstraintData, this)); + } + this.color = new Color(1, 1, 1, 1); + this.updateCache(); + } + /** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones, + * constraints, or weighted path attachments are added or removed. */ + updateCache() { + let updateCache = this._updateCache; + updateCache.length = 0; + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.sorted = bone.data.skinRequired; + bone.active = !bone.sorted; + } + if (this.skin) { + let skinBones = this.skin.bones; + for (let i = 0, n = this.skin.bones.length; i < n; i++) { + let bone = this.bones[skinBones[i].index]; + do { + bone.sorted = false; + bone.active = true; + bone = bone.parent; + } while (bone); + } + } + let ikConstraints = this.ikConstraints; + let transformConstraints = this.transformConstraints; + let pathConstraints = this.pathConstraints; + let physicsConstraints = this.physicsConstraints; + let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length, physicsCount = this.physicsConstraints.length; + let constraintCount = ikCount + transformCount + pathCount + physicsCount; + outer: + for (let i = 0; i < constraintCount; i++) { + for (let ii = 0; ii < ikCount; ii++) { + let constraint = ikConstraints[ii]; + if (constraint.data.order == i) { + this.sortIkConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < transformCount; ii++) { + let constraint = transformConstraints[ii]; + if (constraint.data.order == i) { + this.sortTransformConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < pathCount; ii++) { + let constraint = pathConstraints[ii]; + if (constraint.data.order == i) { + this.sortPathConstraint(constraint); + continue outer; + } + } + for (let ii = 0; ii < physicsCount; ii++) { + const constraint = physicsConstraints[ii]; + if (constraint.data.order == i) { + this.sortPhysicsConstraint(constraint); + continue outer; + } + } + } + for (let i = 0, n = bones.length; i < n; i++) + this.sortBone(bones[i]); + } + sortIkConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let target = constraint.target; + this.sortBone(target); + let constrained = constraint.bones; + let parent = constrained[0]; + this.sortBone(parent); + if (constrained.length == 1) { + this._updateCache.push(constraint); + this.sortReset(parent.children); + } else { + let child = constrained[constrained.length - 1]; + this.sortBone(child); + this._updateCache.push(constraint); + this.sortReset(parent.children); + child.sorted = true; + } + } + sortPathConstraint(constraint) { + constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + let slot = constraint.target; + let slotIndex = slot.data.index; + let slotBone = slot.bone; + if (this.skin) + this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone); + if (this.data.defaultSkin && this.data.defaultSkin != this.skin) + this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone); + for (let i = 0, n = this.data.skins.length; i < n; i++) + this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone); + let attachment = slot.getAttachment(); + if (attachment instanceof PathAttachment) + this.sortPathConstraintAttachmentWith(attachment, slotBone); + let constrained = constraint.bones; + let boneCount = constrained.length; + for (let i = 0; i < boneCount; i++) + this.sortBone(constrained[i]); + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortTransformConstraint(constraint) { + constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + this.sortBone(constraint.target); + let constrained = constraint.bones; + let boneCount = constrained.length; + if (constraint.data.local) { + for (let i = 0; i < boneCount; i++) { + let child = constrained[i]; + this.sortBone(child.parent); + this.sortBone(child); + } + } else { + for (let i = 0; i < boneCount; i++) { + this.sortBone(constrained[i]); + } + } + this._updateCache.push(constraint); + for (let i = 0; i < boneCount; i++) + this.sortReset(constrained[i].children); + for (let i = 0; i < boneCount; i++) + constrained[i].sorted = true; + } + sortPathConstraintAttachment(skin, slotIndex, slotBone) { + let attachments = skin.attachments[slotIndex]; + if (!attachments) + return; + for (let key in attachments) { + this.sortPathConstraintAttachmentWith(attachments[key], slotBone); + } + } + sortPathConstraintAttachmentWith(attachment, slotBone) { + if (!(attachment instanceof PathAttachment)) + return; + let pathBones = attachment.bones; + if (!pathBones) + this.sortBone(slotBone); + else { + let bones = this.bones; + for (let i = 0, n = pathBones.length; i < n; ) { + let nn = pathBones[i++]; + nn += i; + while (i < nn) + this.sortBone(bones[pathBones[i++]]); + } + } + } + sortPhysicsConstraint(constraint) { + const bone = constraint.bone; + constraint.active = bone.active && (!constraint.data.skinRequired || this.skin != null && Utils.contains(this.skin.constraints, constraint.data, true)); + if (!constraint.active) + return; + this.sortBone(bone); + this._updateCache.push(constraint); + this.sortReset(bone.children); + bone.sorted = true; + } + sortBone(bone) { + if (!bone) + return; + if (bone.sorted) + return; + let parent = bone.parent; + if (parent) + this.sortBone(parent); + bone.sorted = true; + this._updateCache.push(bone); + } + sortReset(bones) { + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (!bone.active) + continue; + if (bone.sorted) + this.sortReset(bone.children); + bone.sorted = false; + } + } + /** Updates the world transform for each bone and applies all constraints. + * + * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine + * Runtimes Guide. */ + updateWorldTransform(physics) { + if (physics === void 0 || physics === null) + throw new Error("physics is undefined"); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) + updateCache[i].update(physics); + } + updateWorldTransformWith(physics, parent) { + if (!parent) + throw new Error("parent cannot be null."); + let bones = this.bones; + for (let i = 1, n = bones.length; i < n; i++) { + let bone = bones[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + } + let rootBone = this.getRootBone(); + if (!rootBone) + throw new Error("Root bone must not be null."); + let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + rootBone.worldX = pa * this.x + pb * this.y + parent.worldX; + rootBone.worldY = pc * this.x + pd * this.y + parent.worldY; + const rx = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad; + const ry = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad; + const la = Math.cos(rx) * rootBone.scaleX; + const lb = Math.cos(ry) * rootBone.scaleY; + const lc = Math.sin(rx) * rootBone.scaleX; + const ld = Math.sin(ry) * rootBone.scaleY; + rootBone.a = (pa * la + pb * lc) * this.scaleX; + rootBone.b = (pa * lb + pb * ld) * this.scaleX; + rootBone.c = (pc * la + pd * lc) * this.scaleY; + rootBone.d = (pc * lb + pd * ld) * this.scaleY; + let updateCache = this._updateCache; + for (let i = 0, n = updateCache.length; i < n; i++) { + let updatable = updateCache[i]; + if (updatable != rootBone) + updatable.update(physics); + } + } + /** Sets the bones, constraints, and slots to their setup pose values. */ + setToSetupPose() { + this.setBonesToSetupPose(); + this.setSlotsToSetupPose(); + } + /** Sets the bones and constraints to their setup pose values. */ + setBonesToSetupPose() { + for (const bone of this.bones) + bone.setToSetupPose(); + for (const constraint of this.ikConstraints) + constraint.setToSetupPose(); + for (const constraint of this.transformConstraints) + constraint.setToSetupPose(); + for (const constraint of this.pathConstraints) + constraint.setToSetupPose(); + for (const constraint of this.physicsConstraints) + constraint.setToSetupPose(); + } + /** Sets the slots and draw order to their setup pose values. */ + setSlotsToSetupPose() { + let slots = this.slots; + Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length); + for (let i = 0, n = slots.length; i < n; i++) + slots[i].setToSetupPose(); + } + /** @returns May return null. */ + getRootBone() { + if (this.bones.length == 0) + return null; + return this.bones[0]; + } + /** @returns May be null. */ + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.data.name == boneName) + return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * repeatedly. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) + return slot; + } + return null; + } + /** Sets a skin by name. + * + * See {@link #setSkin()}. */ + setSkinByName(skinName) { + let skin = this.data.findSkin(skinName); + if (!skin) + throw new Error("Skin not found: " + skinName); + this.setSkin(skin); + } + /** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the + * skin is changed, {@link #updateCache()} is called. + * + * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no + * old skin, each slot's setup mode attachment is attached from the new skin. + * + * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the + * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + * @param newSkin May be null. */ + setSkin(newSkin) { + if (newSkin == this.skin) + return; + if (newSkin) { + if (this.skin) + newSkin.attachAll(this, this.skin); + else { + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let name = slot.data.attachmentName; + if (name) { + let attachment = newSkin.getAttachment(i, name); + if (attachment) + slot.setAttachment(attachment); + } + } + } + } + this.skin = newSkin; + this.updateCache(); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment + * name. + * + * See {@link #getAttachment()}. + * @returns May be null. */ + getAttachmentByName(slotName, attachmentName) { + let slot = this.data.findSlot(slotName); + if (!slot) + throw new Error(`Can't find slot with name ${slotName}`); + return this.getAttachment(slot.index, attachmentName); + } + /** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and + * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked. + * + * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. + * @returns May be null. */ + getAttachment(slotIndex, attachmentName) { + if (!attachmentName) + throw new Error("attachmentName cannot be null."); + if (this.skin) { + let attachment = this.skin.getAttachment(slotIndex, attachmentName); + if (attachment) + return attachment; + } + if (this.data.defaultSkin) + return this.data.defaultSkin.getAttachment(slotIndex, attachmentName); + return null; + } + /** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with + * {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}. + * @param attachmentName May be null to clear the slot's attachment. */ + setAttachment(slotName, attachmentName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.data.name == slotName) { + let attachment = null; + if (attachmentName) { + attachment = this.getAttachment(i, attachmentName); + if (!attachment) + throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + slot.setAttachment(attachment); + return; + } + } + throw new Error("Slot not found: " + slotName); + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + return this.ikConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it repeatedly. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + return this.transformConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it repeatedly. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + return this.pathConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this + * method than to call it repeatedly. */ + findPhysicsConstraint(constraintName) { + if (constraintName == null) + throw new Error("constraintName cannot be null."); + return this.physicsConstraints.find((constraint) => constraint.data.name == constraintName) ?? null; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`. + * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */ + getBoundsRect(clipper) { + let offset = new Vector2(); + let size = new Vector2(); + this.getBounds(offset, size, void 0, clipper); + return { x: offset.x, y: offset.y, width: size.x, height: size.y }; + } + /** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB. + * @param size An output value, the width and height of the AABB. + * @param temp Working memory to temporarily store attachments' computed world vertices. + * @param clipper {@link SkeletonClipping} to use. If null, no clipping is applied. */ + getBounds(offset, size, temp = new Array(2), clipper = null) { + if (!offset) + throw new Error("offset cannot be null."); + if (!size) + throw new Error("size cannot be null."); + let drawOrder = this.drawOrder; + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + if (!slot.bone.active) + continue; + let verticesLength = 0; + let vertices = null; + let triangles = null; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + verticesLength = 8; + vertices = Utils.setArraySize(temp, verticesLength, 0); + attachment.computeWorldVertices(slot, vertices, 0, 2); + triangles = _Skeleton.quadTriangles; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + verticesLength = mesh.worldVerticesLength; + vertices = Utils.setArraySize(temp, verticesLength, 0); + mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2); + triangles = mesh.triangles; + } else if (attachment instanceof ClippingAttachment && clipper != null) { + clipper.clipStart(slot, attachment); + continue; + } + if (vertices && triangles) { + if (clipper != null && clipper.isClipping()) { + clipper.clipTriangles(vertices, triangles, triangles.length); + vertices = clipper.clippedVertices; + verticesLength = clipper.clippedVertices.length; + } + for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + if (clipper != null) + clipper.clipEndWithSlot(slot); + } + if (clipper != null) + clipper.clipEnd(); + offset.set(minX, minY); + size.set(maxX - minX, maxY - minY); + } + /** Increments the skeleton's {@link #time}. */ + update(delta) { + this.time += delta; + } + physicsTranslate(x, y) { + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) + physicsConstraints[i].translate(x, y); + } + /** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */ + physicsRotate(x, y, degrees) { + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) + physicsConstraints[i].rotate(x, y, degrees); + } + }; + var Skeleton = _Skeleton; + __publicField(Skeleton, "quadTriangles", [0, 1, 2, 2, 3, 0]); + __publicField(Skeleton, "yDown", false); + var Physics = /* @__PURE__ */ ((Physics2) => { + Physics2[Physics2["none"] = 0] = "none"; + Physics2[Physics2["reset"] = 1] = "reset"; + Physics2[Physics2["update"] = 2] = "update"; + Physics2[Physics2["pose"] = 3] = "pose"; + return Physics2; + })(Physics || {}); + + // spine-core/src/PhysicsConstraintData.ts + var PhysicsConstraintData = class extends ConstraintData { + _bone = null; + /** The bone constrained by this physics constraint. */ + set bone(boneData) { + this._bone = boneData; + } + get bone() { + if (!this._bone) + throw new Error("BoneData not set."); + else + return this._bone; + } + x = 0; + y = 0; + rotate = 0; + scaleX = 0; + shearX = 0; + limit = 0; + step = 0; + inertia = 0; + strength = 0; + damping = 0; + massInverse = 0; + wind = 0; + gravity = 0; + /** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */ + mix = 0; + inertiaGlobal = false; + strengthGlobal = false; + dampingGlobal = false; + massGlobal = false; + windGlobal = false; + gravityGlobal = false; + mixGlobal = false; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/SkeletonData.ts + var SkeletonData = class { + /** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */ + name = null; + /** The skeleton's bones, sorted parent first. The root bone is always the first bone. */ + bones = new Array(); + // Ordered parents first. + /** The skeleton's slots in the setup pose draw order. */ + slots = new Array(); + // Setup pose draw order. + skins = new Array(); + /** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine. + * + * See {@link Skeleton#getAttachmentByName()}. + * May be null. */ + defaultSkin = null; + /** The skeleton's events. */ + events = new Array(); + /** The skeleton's animations. */ + animations = new Array(); + /** The skeleton's IK constraints. */ + ikConstraints = new Array(); + /** The skeleton's transform constraints. */ + transformConstraints = new Array(); + /** The skeleton's path constraints. */ + pathConstraints = new Array(); + /** The skeleton's physics constraints. */ + physicsConstraints = new Array(); + /** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + x = 0; + /** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */ + y = 0; + /** The width of the skeleton's axis aligned bounding box in the setup pose. */ + width = 0; + /** The height of the skeleton's axis aligned bounding box in the setup pose. */ + height = 0; + /** Baseline scale factor for applying distance-dependent effects on non-scalable properties, such as angle or scale. Default + * is 100. */ + referenceScale = 100; + /** The Spine version used to export the skeleton data, or null. */ + version = null; + /** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */ + hash = null; + // Nonessential + /** The dopesheet FPS in Spine. Available only when nonessential data was exported. */ + fps = 0; + /** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + imagesPath = null; + /** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */ + audioPath = null; + /** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findBone(boneName) { + if (!boneName) + throw new Error("boneName cannot be null."); + let bones = this.bones; + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (bone.name == boneName) + return bone; + } + return null; + } + /** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSlot(slotName) { + if (!slotName) + throw new Error("slotName cannot be null."); + let slots = this.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (slot.name == slotName) + return slot; + } + return null; + } + /** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findSkin(skinName) { + if (!skinName) + throw new Error("skinName cannot be null."); + let skins = this.skins; + for (let i = 0, n = skins.length; i < n; i++) { + let skin = skins[i]; + if (skin.name == skinName) + return skin; + } + return null; + } + /** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it + * multiple times. + * @returns May be null. */ + findEvent(eventDataName) { + if (!eventDataName) + throw new Error("eventDataName cannot be null."); + let events = this.events; + for (let i = 0, n = events.length; i < n; i++) { + let event = events[i]; + if (event.name == eventDataName) + return event; + } + return null; + } + /** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to + * call it multiple times. + * @returns May be null. */ + findAnimation(animationName) { + if (!animationName) + throw new Error("animationName cannot be null."); + let animations = this.animations; + for (let i = 0, n = animations.length; i < n; i++) { + let animation = animations[i]; + if (animation.name == animationName) + return animation; + } + return null; + } + /** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findIkConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const ikConstraints = this.ikConstraints; + for (let i = 0, n = ikConstraints.length; i < n; i++) { + const constraint = ikConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of + * this method than to call it multiple times. + * @return May be null. */ + findTransformConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const transformConstraints = this.transformConstraints; + for (let i = 0, n = transformConstraints.length; i < n; i++) { + const constraint = transformConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPathConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const pathConstraints = this.pathConstraints; + for (let i = 0, n = pathConstraints.length; i < n; i++) { + const constraint = pathConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + /** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this method + * than to call it multiple times. + * @return May be null. */ + findPhysicsConstraint(constraintName) { + if (!constraintName) + throw new Error("constraintName cannot be null."); + const physicsConstraints = this.physicsConstraints; + for (let i = 0, n = physicsConstraints.length; i < n; i++) { + const constraint = physicsConstraints[i]; + if (constraint.name == constraintName) + return constraint; + } + return null; + } + }; + + // spine-core/src/Skin.ts + var SkinEntry = class { + constructor(slotIndex = 0, name, attachment) { + this.slotIndex = slotIndex; + this.name = name; + this.attachment = attachment; + } + }; + var Skin = class { + /** The skin's name, which is unique across all skins in the skeleton. */ + name; + attachments = new Array(); + bones = Array(); + constraints = new Array(); + /** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */ + color = new Color(0.99607843, 0.61960787, 0.30980393, 1); + // fe9e4fff + constructor(name) { + if (!name) + throw new Error("name cannot be null."); + this.name = name; + } + /** Adds an attachment to the skin for the specified slot index and name. */ + setAttachment(slotIndex, name, attachment) { + if (!attachment) + throw new Error("attachment cannot be null."); + let attachments = this.attachments; + if (slotIndex >= attachments.length) + attachments.length = slotIndex + 1; + if (!attachments[slotIndex]) + attachments[slotIndex] = {}; + attachments[slotIndex][name] = attachment; + } + /** Adds all attachments, bones, and constraints from the specified skin to this skin. */ + addSkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + /** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not + * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */ + copySkin(skin) { + for (let i = 0; i < skin.bones.length; i++) { + let bone = skin.bones[i]; + let contained = false; + for (let ii = 0; ii < this.bones.length; ii++) { + if (this.bones[ii] == bone) { + contained = true; + break; + } + } + if (!contained) + this.bones.push(bone); + } + for (let i = 0; i < skin.constraints.length; i++) { + let constraint = skin.constraints[i]; + let contained = false; + for (let ii = 0; ii < this.constraints.length; ii++) { + if (this.constraints[ii] == constraint) { + contained = true; + break; + } + } + if (!contained) + this.constraints.push(constraint); + } + let attachments = skin.getAttachments(); + for (let i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (!attachment.attachment) + continue; + if (attachment.attachment instanceof MeshAttachment) { + attachment.attachment = attachment.attachment.newLinkedMesh(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } else { + attachment.attachment = attachment.attachment.copy(); + this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment); + } + } + } + /** Returns the attachment for the specified slot index and name, or null. */ + getAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + return dictionary ? dictionary[name] : null; + } + /** Removes the attachment in the skin for the specified slot index and name, if any. */ + removeAttachment(slotIndex, name) { + let dictionary = this.attachments[slotIndex]; + if (dictionary) + delete dictionary[name]; + } + /** Returns all attachments in this skin. */ + getAttachments() { + let entries = new Array(); + for (var i = 0; i < this.attachments.length; i++) { + let slotAttachments = this.attachments[i]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + entries.push(new SkinEntry(i, name, attachment)); + } + } + } + return entries; + } + /** Returns all attachments in this skin for the specified slot index. */ + getAttachmentsForSlot(slotIndex, attachments) { + let slotAttachments = this.attachments[slotIndex]; + if (slotAttachments) { + for (let name in slotAttachments) { + let attachment = slotAttachments[name]; + if (attachment) + attachments.push(new SkinEntry(slotIndex, name, attachment)); + } + } + } + /** Clears all attachments, bones, and constraints. */ + clear() { + this.attachments.length = 0; + this.bones.length = 0; + this.constraints.length = 0; + } + /** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */ + attachAll(skeleton, oldSkin) { + let slotIndex = 0; + for (let i = 0; i < skeleton.slots.length; i++) { + let slot = skeleton.slots[i]; + let slotAttachment = slot.getAttachment(); + if (slotAttachment && slotIndex < oldSkin.attachments.length) { + let dictionary = oldSkin.attachments[slotIndex]; + for (let key in dictionary) { + let skinAttachment = dictionary[key]; + if (slotAttachment == skinAttachment) { + let attachment = this.getAttachment(slotIndex, key); + if (attachment) + slot.setAttachment(attachment); + break; + } + } + } + slotIndex++; + } + } + }; + + // spine-core/src/SlotData.ts + var SlotData = class { + /** The index of the slot in {@link Skeleton#getSlots()}. */ + index = 0; + /** The name of the slot, which is unique across all slots in the skeleton. */ + name; + /** The bone this slot belongs to. */ + boneData; + /** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two + * color tinting. */ + color = new Color(1, 1, 1, 1); + /** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark + * color's alpha is not used. */ + darkColor = null; + /** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */ + attachmentName = null; + /** The blend mode for drawing the slot's attachment. */ + blendMode = BlendMode.Normal; + /** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */ + visible = true; + constructor(index, name, boneData) { + if (index < 0) + throw new Error("index must be >= 0."); + if (!name) + throw new Error("name cannot be null."); + if (!boneData) + throw new Error("boneData cannot be null."); + this.index = index; + this.name = name; + this.boneData = boneData; + } + }; + var BlendMode = /* @__PURE__ */ ((BlendMode4) => { + BlendMode4[BlendMode4["Normal"] = 0] = "Normal"; + BlendMode4[BlendMode4["Additive"] = 1] = "Additive"; + BlendMode4[BlendMode4["Multiply"] = 2] = "Multiply"; + BlendMode4[BlendMode4["Screen"] = 3] = "Screen"; + return BlendMode4; + })(BlendMode || {}); + + // spine-core/src/TransformConstraintData.ts + var TransformConstraintData = class extends ConstraintData { + /** The bones that will be modified by this transform constraint. */ + bones = new Array(); + /** The target bone whose world transform will be copied to the constrained bones. */ + _target = null; + set target(boneData) { + this._target = boneData; + } + get target() { + if (!this._target) + throw new Error("BoneData not set."); + else + return this._target; + } + mixRotate = 0; + mixX = 0; + mixY = 0; + mixScaleX = 0; + mixScaleY = 0; + mixShearY = 0; + /** An offset added to the constrained bone rotation. */ + offsetRotation = 0; + /** An offset added to the constrained bone X translation. */ + offsetX = 0; + /** An offset added to the constrained bone Y translation. */ + offsetY = 0; + /** An offset added to the constrained bone scaleX. */ + offsetScaleX = 0; + /** An offset added to the constrained bone scaleY. */ + offsetScaleY = 0; + /** An offset added to the constrained bone shearY. */ + offsetShearY = 0; + relative = false; + local = false; + constructor(name) { + super(name, 0, false); + } + }; + + // spine-core/src/SkeletonBinary.ts + var SkeletonBinary = class { + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + attachmentLoader; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(binary) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + skeletonData.name = ""; + let input = new BinaryInput(binary); + let lowHash = input.readInt32(); + let highHash = input.readInt32(); + skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16); + skeletonData.version = input.readString(); + skeletonData.x = input.readFloat(); + skeletonData.y = input.readFloat(); + skeletonData.width = input.readFloat(); + skeletonData.height = input.readFloat(); + skeletonData.referenceScale = input.readFloat() * scale; + let nonessential = input.readBoolean(); + if (nonessential) { + skeletonData.fps = input.readFloat(); + skeletonData.imagesPath = input.readString(); + skeletonData.audioPath = input.readString(); + } + let n = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let str = input.readString(); + if (!str) + throw new Error("String in string table must not be null."); + input.strings.push(str); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Bone name must not be null."); + let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)]; + let data = new BoneData(i, name, parent); + data.rotation = input.readFloat(); + data.x = input.readFloat() * scale; + data.y = input.readFloat() * scale; + data.scaleX = input.readFloat(); + data.scaleY = input.readFloat(); + data.shearX = input.readFloat(); + data.shearY = input.readFloat(); + data.length = input.readFloat() * scale; + data.inherit = input.readByte(); + data.skinRequired = input.readBoolean(); + if (nonessential) { + Color.rgba8888ToColor(data.color, input.readInt32()); + data.icon = input.readString() ?? void 0; + data.visible = input.readBoolean(); + } + skeletonData.bones.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let slotName = input.readString(); + if (!slotName) + throw new Error("Slot name must not be null."); + let boneData = skeletonData.bones[input.readInt(true)]; + let data = new SlotData(i, slotName, boneData); + Color.rgba8888ToColor(data.color, input.readInt32()); + let darkColor = input.readInt32(); + if (darkColor != -1) + Color.rgb888ToColor(data.darkColor = new Color(), darkColor); + data.attachmentName = input.readStringRef(); + data.blendMode = input.readInt(true); + if (nonessential) + data.visible = input.readBoolean(); + skeletonData.slots.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("IK constraint data name must not be null."); + let data = new IkConstraintData(name); + data.order = input.readInt(true); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + data.bendDirection = (flags & 2) != 0 ? 1 : -1; + data.compress = (flags & 4) != 0; + data.stretch = (flags & 8) != 0; + data.uniform = (flags & 16) != 0; + if ((flags & 32) != 0) + data.mix = (flags & 64) != 0 ? input.readFloat() : 1; + if ((flags & 128) != 0) + data.softness = input.readFloat() * scale; + skeletonData.ikConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Transform constraint data name must not be null."); + let data = new TransformConstraintData(name); + data.order = input.readInt(true); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + data.local = (flags & 2) != 0; + data.relative = (flags & 4) != 0; + if ((flags & 8) != 0) + data.offsetRotation = input.readFloat(); + if ((flags & 16) != 0) + data.offsetX = input.readFloat() * scale; + if ((flags & 32) != 0) + data.offsetY = input.readFloat() * scale; + if ((flags & 64) != 0) + data.offsetScaleX = input.readFloat(); + if ((flags & 128) != 0) + data.offsetScaleY = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) != 0) + data.offsetShearY = input.readFloat(); + if ((flags & 2) != 0) + data.mixRotate = input.readFloat(); + if ((flags & 4) != 0) + data.mixX = input.readFloat(); + if ((flags & 8) != 0) + data.mixY = input.readFloat(); + if ((flags & 16) != 0) + data.mixScaleX = input.readFloat(); + if ((flags & 32) != 0) + data.mixScaleY = input.readFloat(); + if ((flags & 64) != 0) + data.mixShearY = input.readFloat(); + skeletonData.transformConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + let name = input.readString(); + if (!name) + throw new Error("Path constraint data name must not be null."); + let data = new PathConstraintData(name); + data.order = input.readInt(true); + data.skinRequired = input.readBoolean(); + nn = input.readInt(true); + for (let ii = 0; ii < nn; ii++) + data.bones.push(skeletonData.bones[input.readInt(true)]); + data.target = skeletonData.slots[input.readInt(true)]; + const flags = input.readByte(); + data.positionMode = flags & 1; + data.spacingMode = flags >> 1 & 3; + data.rotateMode = flags >> 3 & 3; + if ((flags & 128) != 0) + data.offsetRotation = input.readFloat(); + data.position = input.readFloat(); + if (data.positionMode == 0 /* Fixed */) + data.position *= scale; + data.spacing = input.readFloat(); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) + data.spacing *= scale; + data.mixRotate = input.readFloat(); + data.mixX = input.readFloat(); + data.mixY = input.readFloat(); + skeletonData.pathConstraints.push(data); + } + n = input.readInt(true); + for (let i = 0, nn; i < n; i++) { + const name = input.readString(); + if (!name) + throw new Error("Physics constraint data name must not be null."); + const data = new PhysicsConstraintData(name); + data.order = input.readInt(true); + data.bone = skeletonData.bones[input.readInt(true)]; + let flags = input.readByte(); + data.skinRequired = (flags & 1) != 0; + if ((flags & 2) != 0) + data.x = input.readFloat(); + if ((flags & 4) != 0) + data.y = input.readFloat(); + if ((flags & 8) != 0) + data.rotate = input.readFloat(); + if ((flags & 16) != 0) + data.scaleX = input.readFloat(); + if ((flags & 32) != 0) + data.shearX = input.readFloat(); + data.limit = ((flags & 64) != 0 ? input.readFloat() : 5e3) * scale; + data.step = 1 / input.readUnsignedByte(); + data.inertia = input.readFloat(); + data.strength = input.readFloat(); + data.damping = input.readFloat(); + data.massInverse = (flags & 128) != 0 ? input.readFloat() : 1; + data.wind = input.readFloat(); + data.gravity = input.readFloat(); + flags = input.readByte(); + if ((flags & 1) != 0) + data.inertiaGlobal = true; + if ((flags & 2) != 0) + data.strengthGlobal = true; + if ((flags & 4) != 0) + data.dampingGlobal = true; + if ((flags & 8) != 0) + data.massGlobal = true; + if ((flags & 16) != 0) + data.windGlobal = true; + if ((flags & 32) != 0) + data.gravityGlobal = true; + if ((flags & 64) != 0) + data.mixGlobal = true; + data.mix = (flags & 128) != 0 ? input.readFloat() : 1; + skeletonData.physicsConstraints.push(data); + } + let defaultSkin = this.readSkin(input, skeletonData, true, nonessential); + if (defaultSkin) { + skeletonData.defaultSkin = defaultSkin; + skeletonData.skins.push(defaultSkin); + } + { + let i = skeletonData.skins.length; + Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true)); + for (; i < n; i++) { + let skin = this.readSkin(input, skeletonData, false, nonessential); + if (!skin) + throw new Error("readSkin() should not have returned null."); + skeletonData.skins[i] = skin; + } + } + n = this.linkedMeshes.length; + for (let i = 0; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + const skin = skeletonData.skins[linkedMesh.skinIndex]; + if (!linkedMesh.parent) + throw new Error("Linked mesh parent must not be null"); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) + throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) + linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let eventName = input.readString(); + if (!eventName) + throw new Error("Event data name must not be null"); + let data = new EventData(eventName); + data.intValue = input.readInt(false); + data.floatValue = input.readFloat(); + data.stringValue = input.readString(); + data.audioPath = input.readString(); + if (data.audioPath) { + data.volume = input.readFloat(); + data.balance = input.readFloat(); + } + skeletonData.events.push(data); + } + n = input.readInt(true); + for (let i = 0; i < n; i++) { + let animationName = input.readString(); + if (!animationName) + throw new Error("Animatio name must not be null."); + skeletonData.animations.push(this.readAnimation(input, animationName, skeletonData)); + } + return skeletonData; + } + readSkin(input, skeletonData, defaultSkin, nonessential) { + let skin = null; + let slotCount = 0; + if (defaultSkin) { + slotCount = input.readInt(true); + if (slotCount == 0) + return null; + skin = new Skin("default"); + } else { + let skinName = input.readString(); + if (!skinName) + throw new Error("Skin name must not be null."); + skin = new Skin(skinName); + if (nonessential) + Color.rgba8888ToColor(skin.color, input.readInt32()); + skin.bones.length = input.readInt(true); + for (let i = 0, n = skin.bones.length; i < n; i++) + skin.bones[i] = skeletonData.bones[input.readInt(true)]; + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]); + for (let i = 0, n = input.readInt(true); i < n; i++) + skin.constraints.push(skeletonData.physicsConstraints[input.readInt(true)]); + slotCount = input.readInt(true); + } + for (let i = 0; i < slotCount; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let name = input.readStringRef(); + if (!name) + throw new Error("Attachment name must not be null"); + let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential); + if (attachment) + skin.setAttachment(slotIndex, name, attachment); + } + } + return skin; + } + readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) { + let scale = this.scale; + let flags = input.readByte(); + const name = (flags & 8) != 0 ? input.readStringRef() : attachmentName; + if (!name) + throw new Error("Attachment name must not be null"); + switch (flags & 7) { + case AttachmentType.Region: { + let path = (flags & 16) != 0 ? input.readStringRef() : null; + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + let rotation = (flags & 128) != 0 ? input.readFloat() : 0; + let x = input.readFloat(); + let y = input.readFloat(); + let scaleX = input.readFloat(); + let scaleY = input.readFloat(); + let width = input.readFloat(); + let height = input.readFloat(); + if (!path) + path = name; + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) + return null; + region.path = path; + region.x = x * scale; + region.y = y * scale; + region.scaleX = scaleX; + region.scaleY = scaleY; + region.rotation = rotation; + region.width = width * scale; + region.height = height * scale; + Color.rgba8888ToColor(region.color, color); + region.sequence = sequence; + if (sequence == null) + region.updateRegion(); + return region; + } + case AttachmentType.BoundingBox: { + let vertices = this.readVertices(input, (flags & 16) != 0); + let color = nonessential ? input.readInt32() : 0; + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + box.worldVerticesLength = vertices.length; + box.vertices = vertices.vertices; + box.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(box.color, color); + return box; + } + case AttachmentType.Mesh: { + let path = (flags & 16) != 0 ? input.readStringRef() : name; + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + const hullLength = input.readInt(true); + const vertices = this.readVertices(input, (flags & 128) != 0); + const uvs = this.readFloatArray(input, vertices.length, 1); + const triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3); + let edges = []; + let width = 0, height = 0; + if (nonessential) { + edges = this.readShortArray(input, input.readInt(true)); + width = input.readFloat(); + height = input.readFloat(); + } + if (!path) + path = name; + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.bones = vertices.bones; + mesh.vertices = vertices.vertices; + mesh.worldVerticesLength = vertices.length; + mesh.triangles = triangles; + mesh.regionUVs = uvs; + if (sequence == null) + mesh.updateRegion(); + mesh.hullLength = hullLength << 1; + mesh.sequence = sequence; + if (nonessential) { + mesh.edges = edges; + mesh.width = width * scale; + mesh.height = height * scale; + } + return mesh; + } + case AttachmentType.LinkedMesh: { + const path = (flags & 16) != 0 ? input.readStringRef() : name; + if (path == null) + throw new Error("Path of linked mesh must not be null"); + const color = (flags & 32) != 0 ? input.readInt32() : 4294967295; + const sequence = (flags & 64) != 0 ? this.readSequence(input) : null; + const inheritTimelines = (flags & 128) != 0; + const skinIndex = input.readInt(true); + const parent = input.readStringRef(); + let width = 0, height = 0; + if (nonessential) { + width = input.readFloat(); + height = input.readFloat(); + } + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + Color.rgba8888ToColor(mesh.color, color); + mesh.sequence = sequence; + if (nonessential) { + mesh.width = width * scale; + mesh.height = height * scale; + } + this.linkedMeshes.push(new LinkedMesh(mesh, skinIndex, slotIndex, parent, inheritTimelines)); + return mesh; + } + case AttachmentType.Path: { + const closed2 = (flags & 16) != 0; + const constantSpeed = (flags & 32) != 0; + const vertices = this.readVertices(input, (flags & 64) != 0); + const lengths = Utils.newArray(vertices.length / 6, 0); + for (let i = 0, n = lengths.length; i < n; i++) + lengths[i] = input.readFloat() * scale; + const color = nonessential ? input.readInt32() : 0; + const path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = closed2; + path.constantSpeed = constantSpeed; + path.worldVerticesLength = vertices.length; + path.vertices = vertices.vertices; + path.bones = vertices.bones; + path.lengths = lengths; + if (nonessential) + Color.rgba8888ToColor(path.color, color); + return path; + } + case AttachmentType.Point: { + const rotation = input.readFloat(); + const x = input.readFloat(); + const y = input.readFloat(); + const color = nonessential ? input.readInt32() : 0; + const point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = x * scale; + point.y = y * scale; + point.rotation = rotation; + if (nonessential) + Color.rgba8888ToColor(point.color, color); + return point; + } + case AttachmentType.Clipping: { + const endSlotIndex = input.readInt(true); + const vertices = this.readVertices(input, (flags & 16) != 0); + let color = nonessential ? input.readInt32() : 0; + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + clip.endSlot = skeletonData.slots[endSlotIndex]; + clip.worldVerticesLength = vertices.length; + clip.vertices = vertices.vertices; + clip.bones = vertices.bones; + if (nonessential) + Color.rgba8888ToColor(clip.color, color); + return clip; + } + } + return null; + } + readSequence(input) { + let sequence = new Sequence(input.readInt(true)); + sequence.start = input.readInt(true); + sequence.digits = input.readInt(true); + sequence.setupIndex = input.readInt(true); + return sequence; + } + readVertices(input, weighted) { + const scale = this.scale; + const vertexCount = input.readInt(true); + const vertices = new Vertices(); + vertices.length = vertexCount << 1; + if (!weighted) { + vertices.vertices = this.readFloatArray(input, vertices.length, scale); + return vertices; + } + let weights = new Array(); + let bonesArray = new Array(); + for (let i = 0; i < vertexCount; i++) { + let boneCount = input.readInt(true); + bonesArray.push(boneCount); + for (let ii = 0; ii < boneCount; ii++) { + bonesArray.push(input.readInt(true)); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat() * scale); + weights.push(input.readFloat()); + } + } + vertices.vertices = Utils.toFloatArray(weights); + vertices.bones = bonesArray; + return vertices; + } + readFloatArray(input, n, scale) { + let array = new Array(n); + if (scale == 1) { + for (let i = 0; i < n; i++) + array[i] = input.readFloat(); + } else { + for (let i = 0; i < n; i++) + array[i] = input.readFloat() * scale; + } + return array; + } + readShortArray(input, n) { + let array = new Array(n); + for (let i = 0; i < n; i++) + array[i] = input.readInt(true); + return array; + } + readAnimation(input, name, skeletonData) { + input.readInt(true); + let timelines = new Array(); + let scale = this.scale; + for (let i = 0, n = input.readInt(true); i < n; i++) { + let slotIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + let timeline = new AttachmentTimeline(frameCount, slotIndex); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat(), input.readStringRef()); + timelines.push(timeline); + break; + } + case SLOT_RGBA: { + let bezierCount = input.readInt(true); + let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + a = a2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB: { + let bezierCount = input.readInt(true); + let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1); + } + time = time2; + r = r2; + g = g2; + b = b2; + } + timelines.push(timeline); + break; + } + case SLOT_RGBA2: { + let bezierCount = input.readInt(true); + let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let a = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let na = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + a = na; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_RGB2: { + let bezierCount = input.readInt(true); + let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex); + let time = input.readFloat(); + let r = input.readUnsignedByte() / 255; + let g = input.readUnsignedByte() / 255; + let b = input.readUnsignedByte() / 255; + let r2 = input.readUnsignedByte() / 255; + let g2 = input.readUnsignedByte() / 255; + let b2 = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, r, g, b, r2, g2, b2); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let nr = input.readUnsignedByte() / 255; + let ng = input.readUnsignedByte() / 255; + let nb = input.readUnsignedByte() / 255; + let nr2 = input.readUnsignedByte() / 255; + let ng2 = input.readUnsignedByte() / 255; + let nb2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1); + } + time = time2; + r = nr; + g = ng; + b = nb; + r2 = nr2; + g2 = ng2; + b2 = nb2; + } + timelines.push(timeline); + break; + } + case SLOT_ALPHA: { + let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex); + let time = input.readFloat(), a = input.readUnsignedByte() / 255; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, a); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + let a2 = input.readUnsignedByte() / 255; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1); + } + time = time2; + a = a2; + } + timelines.push(timeline); + } + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let boneIndex = input.readInt(true); + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let type = input.readByte(), frameCount = input.readInt(true); + if (type == BONE_INHERIT) { + let timeline = new InheritTimeline(frameCount, boneIndex); + for (let frame = 0; frame < frameCount; frame++) { + timeline.setFrame(frame, input.readFloat(), input.readByte()); + } + timelines.push(timeline); + continue; + } + let bezierCount = input.readInt(true); + switch (type) { + case BONE_ROTATE: + timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_TRANSLATE: + timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEX: + timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_TRANSLATEY: + timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale)); + break; + case BONE_SCALE: + timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEX: + timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SCALEY: + timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEAR: + timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARX: + timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1)); + break; + case BONE_SHEARY: + timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + let flags = input.readByte(); + let time = input.readFloat(), mix = (flags & 1) != 0 ? (flags & 2) != 0 ? input.readFloat() : 1 : 0; + let softness = (flags & 4) != 0 ? input.readFloat() * scale : 0; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0); + if (frame == frameLast) + break; + flags = input.readByte(); + const time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? (flags & 2) != 0 ? input.readFloat() : 1 : 0; + const softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0; + if ((flags & 64) != 0) { + timeline.setStepped(frame); + } else if ((flags & 128) != 0) { + setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixShearY = mixShearY2; + } + timelines.push(timeline); + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let index = input.readInt(true); + let data = skeletonData.pathConstraints[index]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); + switch (type) { + case PATH_POSITION: + timelines.push(readTimeline1( + input, + new PathConstraintPositionTimeline(frameCount, bezierCount, index), + data.positionMode == 0 /* Fixed */ ? scale : 1 + )); + break; + case PATH_SPACING: + timelines.push(readTimeline1( + input, + new PathConstraintSpacingTimeline(frameCount, bezierCount, index), + data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */ ? scale : 1 + )); + break; + case PATH_MIX: + let timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index); + let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(); + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + if (frame == frameLast) + break; + let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1); + setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1); + setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + } + timelines.push(timeline); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + const index = input.readInt(true) - 1; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + const type = input.readByte(), frameCount = input.readInt(true); + if (type == PHYSICS_RESET) { + const timeline = new PhysicsConstraintResetTimeline(frameCount, index); + for (let frame = 0; frame < frameCount; frame++) + timeline.setFrame(frame, input.readFloat()); + timelines.push(timeline); + continue; + } + const bezierCount = input.readInt(true); + switch (type) { + case PHYSICS_INERTIA: + timelines.push(readTimeline1(input, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_STRENGTH: + timelines.push(readTimeline1(input, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_DAMPING: + timelines.push(readTimeline1(input, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_MASS: + timelines.push(readTimeline1(input, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_WIND: + timelines.push(readTimeline1(input, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_GRAVITY: + timelines.push(readTimeline1(input, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1)); + break; + case PHYSICS_MIX: + timelines.push(readTimeline1(input, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1)); + } + } + } + for (let i = 0, n = input.readInt(true); i < n; i++) { + let skin = skeletonData.skins[input.readInt(true)]; + for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) { + let slotIndex = input.readInt(true); + for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + let attachmentName = input.readStringRef(); + if (!attachmentName) + throw new Error("attachmentName must not be null."); + let attachment = skin.getAttachment(slotIndex, attachmentName); + let timelineType = input.readByte(); + let frameCount = input.readInt(true); + let frameLast = frameCount - 1; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + let vertexAttachment = attachment; + let weighted = vertexAttachment.bones; + let vertices = vertexAttachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let bezierCount = input.readInt(true); + let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment); + let time = input.readFloat(); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let end = input.readInt(true); + if (end == 0) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = input.readInt(true); + end += start; + if (scale == 1) { + for (let v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (let v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (let v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frame, time, deform); + if (frame == frameLast) + break; + let time2 = input.readFloat(); + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; + } + timelines.push(timeline); + break; + } + case ATTACHMENT_SEQUENCE: { + let timeline = new SequenceTimeline(frameCount, slotIndex, attachment); + for (let frame = 0; frame < frameCount; frame++) { + let time = input.readFloat(); + let modeAndIndex = input.readInt32(); + timeline.setFrame( + frame, + time, + SequenceModeValues[modeAndIndex & 15], + modeAndIndex >> 4, + input.readFloat() + ); + } + timelines.push(timeline); + break; + } + } + } + } + } + let drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + let timeline = new DrawOrderTimeline(drawOrderCount); + let slotCount = skeletonData.slots.length; + for (let i = 0; i < drawOrderCount; i++) { + let time = input.readFloat(); + let offsetCount = input.readInt(true); + let drawOrder = Utils.newArray(slotCount, 0); + for (let ii = slotCount - 1; ii >= 0; ii--) + drawOrder[ii] = -1; + let unchanged = Utils.newArray(slotCount - offsetCount, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsetCount; ii++) { + let slotIndex = input.readInt(true); + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + timeline.setFrame(i, time, drawOrder); + } + timelines.push(timeline); + } + let eventCount = input.readInt(true); + if (eventCount > 0) { + let timeline = new EventTimeline(eventCount); + for (let i = 0; i < eventCount; i++) { + let time = input.readFloat(); + let eventData = skeletonData.events[input.readInt(true)]; + let event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readString(); + if (event.stringValue == null) + event.stringValue = eventData.stringValue; + if (event.data.audioPath) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + return new Animation(name, timelines, duration); + } + }; + var BinaryInput = class { + constructor(data, strings = new Array(), index = 0, buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) { + this.strings = strings; + this.index = index; + this.buffer = buffer; + } + readByte() { + return this.buffer.getInt8(this.index++); + } + readUnsignedByte() { + return this.buffer.getUint8(this.index++); + } + readShort() { + let value = this.buffer.getInt16(this.index); + this.index += 2; + return value; + } + readInt32() { + let value = this.buffer.getInt32(this.index); + this.index += 4; + return value; + } + readInt(optimizePositive) { + let b = this.readByte(); + let result = b & 127; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 7; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 14; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 21; + if ((b & 128) != 0) { + b = this.readByte(); + result |= (b & 127) << 28; + } + } + } + } + return optimizePositive ? result : result >>> 1 ^ -(result & 1); + } + readStringRef() { + let index = this.readInt(true); + return index == 0 ? null : this.strings[index - 1]; + } + readString() { + let byteCount = this.readInt(true); + switch (byteCount) { + case 0: + return null; + case 1: + return ""; + } + byteCount--; + let chars = ""; + let charCount = 0; + for (let i = 0; i < byteCount; ) { + let b = this.readUnsignedByte(); + switch (b >> 4) { + case 12: + case 13: + chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63); + i += 2; + break; + case 14: + chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63); + i += 3; + break; + default: + chars += String.fromCharCode(b); + i++; + } + } + return chars; + } + readFloat() { + let value = this.buffer.getFloat32(this.index); + this.index += 4; + return value; + } + readBoolean() { + return this.readByte() != 0; + } + }; + var LinkedMesh = class { + parent; + skinIndex; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skinIndex, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skinIndex = skinIndex; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } + }; + var Vertices = class { + constructor(bones = null, vertices = null, length = 0) { + this.bones = bones; + this.vertices = vertices; + this.length = length; + } + }; + var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => { + AttachmentType2[AttachmentType2["Region"] = 0] = "Region"; + AttachmentType2[AttachmentType2["BoundingBox"] = 1] = "BoundingBox"; + AttachmentType2[AttachmentType2["Mesh"] = 2] = "Mesh"; + AttachmentType2[AttachmentType2["LinkedMesh"] = 3] = "LinkedMesh"; + AttachmentType2[AttachmentType2["Path"] = 4] = "Path"; + AttachmentType2[AttachmentType2["Point"] = 5] = "Point"; + AttachmentType2[AttachmentType2["Clipping"] = 6] = "Clipping"; + return AttachmentType2; + })(AttachmentType || {}); + function readTimeline1(input, timeline, scale) { + let time = input.readFloat(), value = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value); + if (frame == frameLast) + break; + let time2 = input.readFloat(), value2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale); + } + time = time2; + value = value2; + } + return timeline; + } + function readTimeline2(input, timeline, scale) { + let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; + for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + if (frame == frameLast) + break; + let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale; + switch (input.readByte()) { + case CURVE_STEPPED: + timeline.setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale); + setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + } + return timeline; + } + function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2); + } + var BONE_ROTATE = 0; + var BONE_TRANSLATE = 1; + var BONE_TRANSLATEX = 2; + var BONE_TRANSLATEY = 3; + var BONE_SCALE = 4; + var BONE_SCALEX = 5; + var BONE_SCALEY = 6; + var BONE_SHEAR = 7; + var BONE_SHEARX = 8; + var BONE_SHEARY = 9; + var BONE_INHERIT = 10; + var SLOT_ATTACHMENT = 0; + var SLOT_RGBA = 1; + var SLOT_RGB = 2; + var SLOT_RGBA2 = 3; + var SLOT_RGB2 = 4; + var SLOT_ALPHA = 5; + var ATTACHMENT_DEFORM = 0; + var ATTACHMENT_SEQUENCE = 1; + var PATH_POSITION = 0; + var PATH_SPACING = 1; + var PATH_MIX = 2; + var PHYSICS_INERTIA = 0; + var PHYSICS_STRENGTH = 1; + var PHYSICS_DAMPING = 2; + var PHYSICS_MASS = 4; + var PHYSICS_WIND = 5; + var PHYSICS_GRAVITY = 6; + var PHYSICS_MIX = 7; + var PHYSICS_RESET = 8; + var CURVE_STEPPED = 1; + var CURVE_BEZIER = 2; + + // spine-core/src/SkeletonBounds.ts + var SkeletonBounds = class { + /** The left edge of the axis aligned bounding box. */ + minX = 0; + /** The bottom edge of the axis aligned bounding box. */ + minY = 0; + /** The right edge of the axis aligned bounding box. */ + maxX = 0; + /** The top edge of the axis aligned bounding box. */ + maxY = 0; + /** The visible bounding boxes. */ + boundingBoxes = new Array(); + /** The world vertices for the bounding box polygons. */ + polygons = new Array(); + polygonPool = new Pool(() => { + return Utils.newFloatArray(16); + }); + /** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding + * box's polygon. + * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the + * SkeletonBounds AABB methods will always return true. */ + update(skeleton, updateAabb) { + if (!skeleton) + throw new Error("skeleton cannot be null."); + let boundingBoxes = this.boundingBoxes; + let polygons = this.polygons; + let polygonPool = this.polygonPool; + let slots = skeleton.slots; + let slotCount = slots.length; + boundingBoxes.length = 0; + polygonPool.freeAll(polygons); + polygons.length = 0; + for (let i = 0; i < slotCount; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (attachment instanceof BoundingBoxAttachment) { + let boundingBox = attachment; + boundingBoxes.push(boundingBox); + let polygon = polygonPool.obtain(); + if (polygon.length != boundingBox.worldVerticesLength) { + polygon = Utils.newFloatArray(boundingBox.worldVerticesLength); + } + polygons.push(polygon); + boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2); + } + } + if (updateAabb) { + this.aabbCompute(); + } else { + this.minX = Number.POSITIVE_INFINITY; + this.minY = Number.POSITIVE_INFINITY; + this.maxX = Number.NEGATIVE_INFINITY; + this.maxY = Number.NEGATIVE_INFINITY; + } + } + aabbCompute() { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + let vertices = polygon; + for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) { + let x = vertices[ii]; + let y = vertices[ii + 1]; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + } + } + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + } + /** Returns true if the axis aligned bounding box contains the point. */ + aabbContainsPoint(x, y) { + return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY; + } + /** Returns true if the axis aligned bounding box intersects the line segment. */ + aabbIntersectsSegment(x1, y1, x2, y2) { + let minX = this.minX; + let minY = this.minY; + let maxX = this.maxX; + let maxY = this.maxY; + if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY) + return false; + let m = (y2 - y1) / (x2 - x1); + let y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + return true; + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + return true; + let x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + return true; + return false; + } + /** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */ + aabbIntersectsSkeleton(bounds) { + return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY; + } + /** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more + * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */ + containsPoint(x, y) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.containsPointPolygon(polygons[i], x, y)) + return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains the point. */ + containsPointPolygon(polygon, x, y) { + let vertices = polygon; + let nn = polygon.length; + let prevIndex = nn - 2; + let inside = false; + for (let ii = 0; ii < nn; ii += 2) { + let vertexY = vertices[ii + 1]; + let prevY = vertices[prevIndex + 1]; + if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) { + let vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + inside = !inside; + } + prevIndex = ii; + } + return inside; + } + /** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it + * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns + * true. */ + intersectsSegment(x1, y1, x2, y2) { + let polygons = this.polygons; + for (let i = 0, n = polygons.length; i < n; i++) + if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) + return this.boundingBoxes[i]; + return null; + } + /** Returns true if the polygon contains any part of the line segment. */ + intersectsSegmentPolygon(polygon, x1, y1, x2, y2) { + let vertices = polygon; + let nn = polygon.length; + let width12 = x1 - x2, height12 = y1 - y2; + let det1 = x1 * y2 - y1 * x2; + let x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (let ii = 0; ii < nn; ii += 2) { + let x4 = vertices[ii], y4 = vertices[ii + 1]; + let det2 = x3 * y4 - y3 * x4; + let width34 = x3 - x4, height34 = y3 - y4; + let det3 = width12 * height34 - height12 * width34; + let x = (det1 * width34 - width12 * det2) / det3; + if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) { + let y = (det1 * height34 - height12 * det2) / det3; + if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1)) + return true; + } + x3 = x4; + y3 = y4; + } + return false; + } + /** Returns the polygon for the specified bounding box, or null. */ + getPolygon(boundingBox) { + if (!boundingBox) + throw new Error("boundingBox cannot be null."); + let index = this.boundingBoxes.indexOf(boundingBox); + return index == -1 ? null : this.polygons[index]; + } + /** The width of the axis aligned bounding box. */ + getWidth() { + return this.maxX - this.minX; + } + /** The height of the axis aligned bounding box. */ + getHeight() { + return this.maxY - this.minY; + } + }; + + // spine-core/src/Triangulator.ts + var Triangulator = class { + convexPolygons = new Array(); + convexPolygonsIndices = new Array(); + indicesArray = new Array(); + isConcaveArray = new Array(); + triangles = new Array(); + polygonPool = new Pool(() => { + return new Array(); + }); + polygonIndicesPool = new Pool(() => { + return new Array(); + }); + triangulate(verticesArray) { + let vertices = verticesArray; + let vertexCount = verticesArray.length >> 1; + let indices = this.indicesArray; + indices.length = 0; + for (let i = 0; i < vertexCount; i++) + indices[i] = i; + let isConcave = this.isConcaveArray; + isConcave.length = 0; + for (let i = 0, n = vertexCount; i < n; ++i) + isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); + let triangles = this.triangles; + triangles.length = 0; + while (vertexCount > 3) { + let previous = vertexCount - 1, i = 0, next = 1; + while (true) { + outer: + if (!isConcave[i]) { + let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1; + let p1x = vertices[p1], p1y = vertices[p1 + 1]; + let p2x = vertices[p2], p2y = vertices[p2 + 1]; + let p3x = vertices[p3], p3y = vertices[p3 + 1]; + for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcave[ii]) + continue; + let v = indices[ii] << 1; + let vx = vertices[v], vy = vertices[v + 1]; + if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { + if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { + if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) + break outer; + } + } + } + break; + } + if (next == 0) { + do { + if (!isConcave[i]) + break; + i--; + } while (i > 0); + break; + } + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + triangles.push(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push(indices[i]); + triangles.push(indices[(i + 1) % vertexCount]); + indices.splice(i, 1); + isConcave.splice(i, 1); + vertexCount--; + let previousIndex = (vertexCount + i - 1) % vertexCount; + let nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); + } + if (vertexCount == 3) { + triangles.push(indices[2]); + triangles.push(indices[0]); + triangles.push(indices[1]); + } + return triangles; + } + decompose(verticesArray, triangles) { + let vertices = verticesArray; + let convexPolygons = this.convexPolygons; + this.polygonPool.freeAll(convexPolygons); + convexPolygons.length = 0; + let convexPolygonsIndices = this.convexPolygonsIndices; + this.polygonIndicesPool.freeAll(convexPolygonsIndices); + convexPolygonsIndices.length = 0; + let polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + let polygon = this.polygonPool.obtain(); + polygon.length = 0; + let fanBaseIndex = -1, lastWinding = 0; + for (let i = 0, n = triangles.length; i < n; i += 3) { + let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; + let x1 = vertices[t1], y1 = vertices[t1 + 1]; + let x2 = vertices[t2], y2 = vertices[t2 + 1]; + let x3 = vertices[t3], y3 = vertices[t3 + 1]; + let merged = false; + if (fanBaseIndex == t1) { + let o = polygon.length - 4; + let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); + let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); + if (winding1 == lastWinding && winding2 == lastWinding) { + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(t3); + merged = true; + } + } + if (!merged) { + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } else { + this.polygonPool.free(polygon); + this.polygonIndicesPool.free(polygonIndices); + } + polygon = this.polygonPool.obtain(); + polygon.length = 0; + polygon.push(x1); + polygon.push(y1); + polygon.push(x2); + polygon.push(y2); + polygon.push(x3); + polygon.push(y3); + polygonIndices = this.polygonIndicesPool.obtain(); + polygonIndices.length = 0; + polygonIndices.push(t1); + polygonIndices.push(t2); + polygonIndices.push(t3); + lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + if (polygon.length > 0) { + convexPolygons.push(polygon); + convexPolygonsIndices.push(polygonIndices); + } + for (let i = 0, n = convexPolygons.length; i < n; i++) { + polygonIndices = convexPolygonsIndices[i]; + if (polygonIndices.length == 0) + continue; + let firstIndex = polygonIndices[0]; + let lastIndex = polygonIndices[polygonIndices.length - 1]; + polygon = convexPolygons[i]; + let o = polygon.length - 4; + let prevPrevX = polygon[o], prevPrevY = polygon[o + 1]; + let prevX = polygon[o + 2], prevY = polygon[o + 3]; + let firstX = polygon[0], firstY = polygon[1]; + let secondX = polygon[2], secondY = polygon[3]; + let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + for (let ii = 0; ii < n; ii++) { + if (ii == i) + continue; + let otherIndices = convexPolygonsIndices[ii]; + if (otherIndices.length != 3) + continue; + let otherFirstIndex = otherIndices[0]; + let otherSecondIndex = otherIndices[1]; + let otherLastIndex = otherIndices[2]; + let otherPoly = convexPolygons[ii]; + let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1]; + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + continue; + let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) { + otherPoly.length = 0; + otherIndices.length = 0; + polygon.push(x3); + polygon.push(y3); + polygonIndices.push(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + for (let i = convexPolygons.length - 1; i >= 0; i--) { + polygon = convexPolygons[i]; + if (polygon.length == 0) { + convexPolygons.splice(i, 1); + this.polygonPool.free(polygon); + polygonIndices = convexPolygonsIndices[i]; + convexPolygonsIndices.splice(i, 1); + this.polygonIndicesPool.free(polygonIndices); + } + } + return convexPolygons; + } + static isConcave(index, vertexCount, vertices, indices) { + let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; + let current = indices[index] << 1; + let next = indices[(index + 1) % vertexCount] << 1; + return !this.positiveArea( + vertices[previous], + vertices[previous + 1], + vertices[current], + vertices[current + 1], + vertices[next], + vertices[next + 1] + ); + } + static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + static winding(p1x, p1y, p2x, p2y, p3x, p3y) { + let px = p2x - p1x, py = p2y - p1y; + return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; + } + }; + + // spine-core/src/SkeletonClipping.ts + var SkeletonClipping = class { + triangulator = new Triangulator(); + clippingPolygon = new Array(); + clipOutput = new Array(); + clippedVertices = new Array(); + clippedUVs = new Array(); + clippedTriangles = new Array(); + scratch = new Array(); + clipAttachment = null; + clippingPolygons = null; + clipStart(slot, clip) { + if (this.clipAttachment) + return 0; + this.clipAttachment = clip; + let n = clip.worldVerticesLength; + let vertices = Utils.setArraySize(this.clippingPolygon, n); + clip.computeWorldVertices(slot, 0, n, vertices, 0, 2); + let clippingPolygon = this.clippingPolygon; + SkeletonClipping.makeClockwise(clippingPolygon); + let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)); + for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) { + let polygon = clippingPolygons[i]; + SkeletonClipping.makeClockwise(polygon); + polygon.push(polygon[0]); + polygon.push(polygon[1]); + } + return clippingPolygons.length; + } + clipEndWithSlot(slot) { + if (this.clipAttachment && this.clipAttachment.endSlot == slot.data) + this.clipEnd(); + } + clipEnd() { + if (!this.clipAttachment) + return; + this.clipAttachment = null; + this.clippingPolygons = null; + this.clippedVertices.length = 0; + this.clippedTriangles.length = 0; + this.clippingPolygon.length = 0; + } + isClipping() { + return this.clipAttachment != null; + } + clipTriangles(vertices, verticesLengthOrTriangles, trianglesOrTrianglesLength, trianglesLengthOrUvs, uvsOrLight, lightOrDark, darkOrTwoColor, twoColorParam) { + let triangles; + let trianglesLength; + let uvs; + let light; + let dark; + let twoColor; + if (typeof verticesLengthOrTriangles === "number") { + triangles = trianglesOrTrianglesLength; + trianglesLength = trianglesLengthOrUvs; + uvs = uvsOrLight; + light = lightOrDark; + dark = darkOrTwoColor; + twoColor = twoColorParam; + } else { + triangles = verticesLengthOrTriangles; + trianglesLength = trianglesOrTrianglesLength; + uvs = trianglesLengthOrUvs; + light = uvsOrLight; + dark = lightOrDark; + twoColor = darkOrTwoColor; + } + if (uvs && light && dark && typeof twoColor === "boolean") + this.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor); + else + this.clipTrianglesNoRender(vertices, triangles, trianglesLength); + } + clipTrianglesNoRender(vertices, triangles, trianglesLength) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let vertexSize = twoColor ? 12 : 8; + let index = 0; + clippedVertices.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += vertexSize) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c; + clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c; + if (twoColor) { + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + } + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = light.r; + clippedVerticesItems[s + 3] = light.g; + clippedVerticesItems[s + 4] = light.b; + clippedVerticesItems[s + 5] = light.a; + if (!twoColor) { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = x2; + clippedVerticesItems[s + 9] = y2; + clippedVerticesItems[s + 10] = light.r; + clippedVerticesItems[s + 11] = light.g; + clippedVerticesItems[s + 12] = light.b; + clippedVerticesItems[s + 13] = light.a; + clippedVerticesItems[s + 14] = u2; + clippedVerticesItems[s + 15] = v2; + clippedVerticesItems[s + 16] = x3; + clippedVerticesItems[s + 17] = y3; + clippedVerticesItems[s + 18] = light.r; + clippedVerticesItems[s + 19] = light.g; + clippedVerticesItems[s + 20] = light.b; + clippedVerticesItems[s + 21] = light.a; + clippedVerticesItems[s + 22] = u3; + clippedVerticesItems[s + 23] = v3; + } else { + clippedVerticesItems[s + 6] = u1; + clippedVerticesItems[s + 7] = v1; + clippedVerticesItems[s + 8] = dark.r; + clippedVerticesItems[s + 9] = dark.g; + clippedVerticesItems[s + 10] = dark.b; + clippedVerticesItems[s + 11] = dark.a; + clippedVerticesItems[s + 12] = x2; + clippedVerticesItems[s + 13] = y2; + clippedVerticesItems[s + 14] = light.r; + clippedVerticesItems[s + 15] = light.g; + clippedVerticesItems[s + 16] = light.b; + clippedVerticesItems[s + 17] = light.a; + clippedVerticesItems[s + 18] = u2; + clippedVerticesItems[s + 19] = v2; + clippedVerticesItems[s + 20] = dark.r; + clippedVerticesItems[s + 21] = dark.g; + clippedVerticesItems[s + 22] = dark.b; + clippedVerticesItems[s + 23] = dark.a; + clippedVerticesItems[s + 24] = x3; + clippedVerticesItems[s + 25] = y3; + clippedVerticesItems[s + 26] = light.r; + clippedVerticesItems[s + 27] = light.g; + clippedVerticesItems[s + 28] = light.b; + clippedVerticesItems[s + 29] = light.a; + clippedVerticesItems[s + 30] = u3; + clippedVerticesItems[s + 31] = v3; + clippedVerticesItems[s + 32] = dark.r; + clippedVerticesItems[s + 33] = dark.g; + clippedVerticesItems[s + 34] = dark.b; + clippedVerticesItems[s + 35] = dark.a; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + clipTrianglesUnpacked(vertices, triangles, trianglesLength, uvs) { + let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices, clippedUVs = this.clippedUVs; + let clippedTriangles = this.clippedTriangles; + let polygons = this.clippingPolygons; + let polygonsCount = polygons.length; + let index = 0; + clippedVertices.length = 0; + clippedUVs.length = 0; + clippedTriangles.length = 0; + for (let i = 0; i < trianglesLength; i += 3) { + let vertexOffset = triangles[i] << 1; + let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 1] << 1; + let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + vertexOffset = triangles[i + 2] << 1; + let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + for (let p = 0; p < polygonsCount; p++) { + let s = clippedVertices.length; + if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + let clipOutputLength = clipOutput.length; + if (clipOutputLength == 0) + continue; + let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + let d = 1 / (d0 * d2 + d1 * (y1 - y3)); + let clipOutputCount = clipOutputLength >> 1; + let clipOutputItems = this.clipOutput; + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2); + let clippedUVsItems = Utils.setArraySize(clippedUVs, s + clipOutputCount * 2); + for (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) { + let x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + let c0 = x - x3, c1 = y - y3; + let a = (d0 * c0 + d1 * c1) * d; + let b = (d4 * c0 + d2 * c1) * d; + let c = 1 - a - b; + clippedUVsItems[s] = u1 * a + u2 * b + u3 * c; + clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c; + } + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (let ii = 1; ii < clipOutputCount; ii++, s += 3) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + ii; + clippedTrianglesItems[s + 2] = index + ii + 1; + } + index += clipOutputCount + 1; + } else { + let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2); + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + let clippedUVSItems = Utils.setArraySize(clippedUVs, s + 3 * 2); + clippedUVSItems[s] = u1; + clippedUVSItems[s + 1] = v1; + clippedUVSItems[s + 2] = u2; + clippedUVSItems[s + 3] = v2; + clippedUVSItems[s + 4] = u3; + clippedUVSItems[s + 5] = v3; + s = clippedTriangles.length; + let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3); + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = index + 1; + clippedTrianglesItems[s + 2] = index + 2; + index += 3; + break; + } + } + } + } + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + clip(x1, y1, x2, y2, x3, y3, clippingArea, output) { + let originalOutput = output; + let clipped = false; + let input; + if (clippingArea.length % 4 >= 2) { + input = output; + output = this.scratch; + } else + input = this.scratch; + input.length = 0; + input.push(x1); + input.push(y1); + input.push(x2); + input.push(y2); + input.push(x3); + input.push(y3); + input.push(x1); + input.push(y1); + output.length = 0; + let clippingVerticesLast = clippingArea.length - 4; + let clippingVertices = clippingArea; + for (let i = 0; ; i += 2) { + let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + let ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3]; + let outputStart = output.length; + let inputVertices = input; + for (let ii = 0, nn = input.length - 2; ii < nn; ) { + let inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + ii += 2; + let inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1]; + let s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2); + let s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY); + if (s1 > 0) { + if (s2) { + output.push(inputX2); + output.push(inputY2); + continue; + } + let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(inputX + ix * t); + output.push(inputY + iy * t); + } else { + output.push(inputX2); + output.push(inputY2); + continue; + } + } else if (s2) { + let ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex); + if (t >= 0 && t <= 1) { + output.push(inputX + ix * t); + output.push(inputY + iy * t); + output.push(inputX2); + output.push(inputY2); + } else { + output.push(inputX2); + output.push(inputY2); + continue; + } + } + clipped = true; + } + if (outputStart == output.length) { + originalOutput.length = 0; + return true; + } + output.push(output[0]); + output.push(output[1]); + if (i == clippingVerticesLast) + break; + let temp = output; + output = input; + output.length = 0; + input = temp; + } + if (originalOutput != output) { + originalOutput.length = 0; + for (let i = 0, n = output.length - 2; i < n; i++) + originalOutput[i] = output[i]; + } else + originalOutput.length = originalOutput.length - 2; + return clipped; + } + static makeClockwise(polygon) { + let vertices = polygon; + let verticeslength = polygon.length; + let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0; + for (let i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) + return; + for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + let x = vertices[i], y = vertices[i + 1]; + let other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } + } + }; + + // spine-core/src/SkeletonJson.ts + var SkeletonJson = class { + attachmentLoader; + /** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at + * runtime than were used in Spine. + * + * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */ + scale = 1; + linkedMeshes = new Array(); + constructor(attachmentLoader) { + this.attachmentLoader = attachmentLoader; + } + readSkeletonData(json) { + let scale = this.scale; + let skeletonData = new SkeletonData(); + let root = typeof json === "string" ? JSON.parse(json) : json; + let skeletonMap = root.skeleton; + if (skeletonMap) { + skeletonData.hash = skeletonMap.hash; + skeletonData.version = skeletonMap.spine; + skeletonData.x = skeletonMap.x; + skeletonData.y = skeletonMap.y; + skeletonData.width = skeletonMap.width; + skeletonData.height = skeletonMap.height; + skeletonData.referenceScale = getValue(skeletonMap, "referenceScale", 100) * scale; + skeletonData.fps = skeletonMap.fps; + skeletonData.imagesPath = skeletonMap.images ?? null; + skeletonData.audioPath = skeletonMap.audio ?? null; + } + if (root.bones) { + for (let i = 0; i < root.bones.length; i++) { + let boneMap = root.bones[i]; + let parent = null; + let parentName = getValue(boneMap, "parent", null); + if (parentName) + parent = skeletonData.findBone(parentName); + let data = new BoneData(skeletonData.bones.length, boneMap.name, parent); + data.length = getValue(boneMap, "length", 0) * scale; + data.x = getValue(boneMap, "x", 0) * scale; + data.y = getValue(boneMap, "y", 0) * scale; + data.rotation = getValue(boneMap, "rotation", 0); + data.scaleX = getValue(boneMap, "scaleX", 1); + data.scaleY = getValue(boneMap, "scaleY", 1); + data.shearX = getValue(boneMap, "shearX", 0); + data.shearY = getValue(boneMap, "shearY", 0); + data.inherit = Utils.enumValue(Inherit, getValue(boneMap, "inherit", "Normal")); + data.skinRequired = getValue(boneMap, "skin", false); + let color = getValue(boneMap, "color", null); + if (color) + data.color.setFromString(color); + skeletonData.bones.push(data); + } + } + if (root.slots) { + for (let i = 0; i < root.slots.length; i++) { + let slotMap = root.slots[i]; + let slotName = slotMap.name; + let boneData = skeletonData.findBone(slotMap.bone); + if (!boneData) + throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`); + let data = new SlotData(skeletonData.slots.length, slotName, boneData); + let color = getValue(slotMap, "color", null); + if (color) + data.color.setFromString(color); + let dark = getValue(slotMap, "dark", null); + if (dark) + data.darkColor = Color.fromString(dark); + data.attachmentName = getValue(slotMap, "attachment", null); + data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal")); + data.visible = getValue(slotMap, "visible", true); + skeletonData.slots.push(data); + } + } + if (root.ik) { + for (let i = 0; i < root.ik.length; i++) { + let constraintMap = root.ik[i]; + let data = new IkConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let bone = skeletonData.findBone(constraintMap.bones[ii]); + if (!bone) + throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let target = skeletonData.findBone(constraintMap.target); + ; + if (!target) + throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`); + data.target = target; + data.mix = getValue(constraintMap, "mix", 1); + data.softness = getValue(constraintMap, "softness", 0) * scale; + data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1; + data.compress = getValue(constraintMap, "compress", false); + data.stretch = getValue(constraintMap, "stretch", false); + data.uniform = getValue(constraintMap, "uniform", false); + skeletonData.ikConstraints.push(data); + } + } + if (root.transform) { + for (let i = 0; i < root.transform.length; i++) { + let constraintMap = root.transform[i]; + let data = new TransformConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findBone(targetName); + if (!target) + throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`); + data.target = target; + data.local = getValue(constraintMap, "local", false); + data.relative = getValue(constraintMap, "relative", false); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.offsetX = getValue(constraintMap, "x", 0) * scale; + data.offsetY = getValue(constraintMap, "y", 0) * scale; + data.offsetScaleX = getValue(constraintMap, "scaleX", 0); + data.offsetScaleY = getValue(constraintMap, "scaleY", 0); + data.offsetShearY = getValue(constraintMap, "shearY", 0); + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + data.mixScaleX = getValue(constraintMap, "mixScaleX", 1); + data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX); + data.mixShearY = getValue(constraintMap, "mixShearY", 1); + skeletonData.transformConstraints.push(data); + } + } + if (root.path) { + for (let i = 0; i < root.path.length; i++) { + let constraintMap = root.path[i]; + let data = new PathConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + for (let ii = 0; ii < constraintMap.bones.length; ii++) { + let boneName = constraintMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`); + data.bones.push(bone); + } + let targetName = constraintMap.target; + let target = skeletonData.findSlot(targetName); + if (!target) + throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`); + data.target = target; + data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent")); + data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length")); + data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent")); + data.offsetRotation = getValue(constraintMap, "rotation", 0); + data.position = getValue(constraintMap, "position", 0); + if (data.positionMode == 0 /* Fixed */) + data.position *= scale; + data.spacing = getValue(constraintMap, "spacing", 0); + if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */) + data.spacing *= scale; + data.mixRotate = getValue(constraintMap, "mixRotate", 1); + data.mixX = getValue(constraintMap, "mixX", 1); + data.mixY = getValue(constraintMap, "mixY", data.mixX); + skeletonData.pathConstraints.push(data); + } + } + if (root.physics) { + for (let i = 0; i < root.physics.length; i++) { + const constraintMap = root.physics[i]; + const data = new PhysicsConstraintData(constraintMap.name); + data.order = getValue(constraintMap, "order", 0); + data.skinRequired = getValue(constraintMap, "skin", false); + const boneName = constraintMap.bone; + const bone = skeletonData.findBone(boneName); + if (bone == null) + throw new Error("Physics bone not found: " + boneName); + data.bone = bone; + data.x = getValue(constraintMap, "x", 0); + data.y = getValue(constraintMap, "y", 0); + data.rotate = getValue(constraintMap, "rotate", 0); + data.scaleX = getValue(constraintMap, "scaleX", 0); + data.shearX = getValue(constraintMap, "shearX", 0); + data.limit = getValue(constraintMap, "limit", 5e3) * scale; + data.step = 1 / getValue(constraintMap, "fps", 60); + data.inertia = getValue(constraintMap, "inertia", 1); + data.strength = getValue(constraintMap, "strength", 100); + data.damping = getValue(constraintMap, "damping", 1); + data.massInverse = 1 / getValue(constraintMap, "mass", 1); + data.wind = getValue(constraintMap, "wind", 0); + data.gravity = getValue(constraintMap, "gravity", 0); + data.mix = getValue(constraintMap, "mix", 1); + data.inertiaGlobal = getValue(constraintMap, "inertiaGlobal", false); + data.strengthGlobal = getValue(constraintMap, "strengthGlobal", false); + data.dampingGlobal = getValue(constraintMap, "dampingGlobal", false); + data.massGlobal = getValue(constraintMap, "massGlobal", false); + data.windGlobal = getValue(constraintMap, "windGlobal", false); + data.gravityGlobal = getValue(constraintMap, "gravityGlobal", false); + data.mixGlobal = getValue(constraintMap, "mixGlobal", false); + skeletonData.physicsConstraints.push(data); + } + } + if (root.skins) { + for (let i = 0; i < root.skins.length; i++) { + let skinMap = root.skins[i]; + let skin = new Skin(skinMap.name); + if (skinMap.bones) { + for (let ii = 0; ii < skinMap.bones.length; ii++) { + let boneName = skinMap.bones[ii]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`); + skin.bones.push(bone); + } + } + if (skinMap.ik) { + for (let ii = 0; ii < skinMap.ik.length; ii++) { + let constraintName = skinMap.ik[ii]; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.transform) { + for (let ii = 0; ii < skinMap.transform.length; ii++) { + let constraintName = skinMap.transform[ii]; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.path) { + for (let ii = 0; ii < skinMap.path.length; ii++) { + let constraintName = skinMap.path[ii]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + if (skinMap.physics) { + for (let ii = 0; ii < skinMap.physics.length; ii++) { + let constraintName = skinMap.physics[ii]; + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) + throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`); + skin.constraints.push(constraint); + } + } + for (let slotName in skinMap.attachments) { + let slot = skeletonData.findSlot(slotName); + if (!slot) + throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`); + let slotMap = skinMap.attachments[slotName]; + for (let entryName in slotMap) { + let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData); + if (attachment) + skin.setAttachment(slot.index, entryName, attachment); + } + } + skeletonData.skins.push(skin); + if (skin.name == "default") + skeletonData.defaultSkin = skin; + } + } + for (let i = 0, n = this.linkedMeshes.length; i < n; i++) { + let linkedMesh = this.linkedMeshes[i]; + let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin); + if (!skin) + throw new Error(`Skin not found: ${linkedMesh.skin}`); + let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent); + if (!parent) + throw new Error(`Parent mesh not found: ${linkedMesh.parent}`); + linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh; + linkedMesh.mesh.setParentMesh(parent); + if (linkedMesh.mesh.region != null) + linkedMesh.mesh.updateRegion(); + } + this.linkedMeshes.length = 0; + if (root.events) { + for (let eventName in root.events) { + let eventMap = root.events[eventName]; + let data = new EventData(eventName); + data.intValue = getValue(eventMap, "int", 0); + data.floatValue = getValue(eventMap, "float", 0); + data.stringValue = getValue(eventMap, "string", ""); + data.audioPath = getValue(eventMap, "audio", null); + if (data.audioPath) { + data.volume = getValue(eventMap, "volume", 1); + data.balance = getValue(eventMap, "balance", 0); + } + skeletonData.events.push(data); + } + } + if (root.animations) { + for (let animationName in root.animations) { + let animationMap = root.animations[animationName]; + this.readAnimation(animationMap, animationName, skeletonData); + } + } + return skeletonData; + } + readAttachment(map, skin, slotIndex, name, skeletonData) { + let scale = this.scale; + name = getValue(map, "name", name); + switch (getValue(map, "type", "region")) { + case "region": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence); + if (!region) + return null; + region.path = path; + region.x = getValue(map, "x", 0) * scale; + region.y = getValue(map, "y", 0) * scale; + region.scaleX = getValue(map, "scaleX", 1); + region.scaleY = getValue(map, "scaleY", 1); + region.rotation = getValue(map, "rotation", 0); + region.width = map.width * scale; + region.height = map.height * scale; + region.sequence = sequence; + let color = getValue(map, "color", null); + if (color) + region.color.setFromString(color); + if (region.region != null) + region.updateRegion(); + return region; + } + case "boundingbox": { + let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name); + if (!box) + return null; + this.readVertices(map, box, map.vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + box.color.setFromString(color); + return box; + } + case "mesh": + case "linkedmesh": { + let path = getValue(map, "path", name); + let sequence = this.readSequence(getValue(map, "sequence", null)); + let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence); + if (!mesh) + return null; + mesh.path = path; + let color = getValue(map, "color", null); + if (color) + mesh.color.setFromString(color); + mesh.width = getValue(map, "width", 0) * scale; + mesh.height = getValue(map, "height", 0) * scale; + mesh.sequence = sequence; + let parent = getValue(map, "parent", null); + if (parent) { + this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true))); + return mesh; + } + let uvs = map.uvs; + this.readVertices(map, mesh, uvs.length); + mesh.triangles = map.triangles; + mesh.regionUVs = uvs; + if (mesh.region != null) + mesh.updateRegion(); + mesh.edges = getValue(map, "edges", null); + mesh.hullLength = getValue(map, "hull", 0) * 2; + return mesh; + } + case "path": { + let path = this.attachmentLoader.newPathAttachment(skin, name); + if (!path) + return null; + path.closed = getValue(map, "closed", false); + path.constantSpeed = getValue(map, "constantSpeed", true); + let vertexCount = map.vertexCount; + this.readVertices(map, path, vertexCount << 1); + let lengths = Utils.newArray(vertexCount / 3, 0); + for (let i = 0; i < map.lengths.length; i++) + lengths[i] = map.lengths[i] * scale; + path.lengths = lengths; + let color = getValue(map, "color", null); + if (color) + path.color.setFromString(color); + return path; + } + case "point": { + let point = this.attachmentLoader.newPointAttachment(skin, name); + if (!point) + return null; + point.x = getValue(map, "x", 0) * scale; + point.y = getValue(map, "y", 0) * scale; + point.rotation = getValue(map, "rotation", 0); + let color = getValue(map, "color", null); + if (color) + point.color.setFromString(color); + return point; + } + case "clipping": { + let clip = this.attachmentLoader.newClippingAttachment(skin, name); + if (!clip) + return null; + let end = getValue(map, "end", null); + if (end) + clip.endSlot = skeletonData.findSlot(end); + let vertexCount = map.vertexCount; + this.readVertices(map, clip, vertexCount << 1); + let color = getValue(map, "color", null); + if (color) + clip.color.setFromString(color); + return clip; + } + } + return null; + } + readSequence(map) { + if (map == null) + return null; + let sequence = new Sequence(getValue(map, "count", 0)); + sequence.start = getValue(map, "start", 1); + sequence.digits = getValue(map, "digits", 0); + sequence.setupIndex = getValue(map, "setup", 0); + return sequence; + } + readVertices(map, attachment, verticesLength) { + let scale = this.scale; + attachment.worldVerticesLength = verticesLength; + let vertices = map.vertices; + if (verticesLength == vertices.length) { + let scaledVertices = Utils.toFloatArray(vertices); + if (scale != 1) { + for (let i = 0, n = vertices.length; i < n; i++) + scaledVertices[i] *= scale; + } + attachment.vertices = scaledVertices; + return; + } + let weights = new Array(); + let bones = new Array(); + for (let i = 0, n = vertices.length; i < n; ) { + let boneCount = vertices[i++]; + bones.push(boneCount); + for (let nn = i + boneCount * 4; i < nn; i += 4) { + bones.push(vertices[i]); + weights.push(vertices[i + 1] * scale); + weights.push(vertices[i + 2] * scale); + weights.push(vertices[i + 3]); + } + } + attachment.bones = bones; + attachment.vertices = Utils.toFloatArray(weights); + } + readAnimation(map, name, skeletonData) { + let scale = this.scale; + let timelines = new Array(); + if (map.slots) { + for (let slotName in map.slots) { + let slotMap = map.slots[slotName]; + let slot = skeletonData.findSlot(slotName); + if (!slot) + throw new Error("Slot not found: " + slotName); + let slotIndex = slot.index; + for (let timelineName in slotMap) { + let timelineMap = slotMap[timelineName]; + if (!timelineMap) + continue; + let frames = timelineMap.length; + if (timelineName == "attachment") { + let timeline = new AttachmentTimeline(frames, slotIndex); + for (let frame = 0; frame < frames; frame++) { + let keyMap = timelineMap[frame]; + timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null)); + } + timelines.push(timeline); + } else if (timelineName == "rgba") { + let timeline = new RGBATimeline(frames, frames << 2, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb") { + let timeline = new RGBTimeline(frames, frames * 3, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.color); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.color); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + } + time = time2; + color = newColor; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "alpha") { + timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1)); + } else if (timelineName == "rgba2") { + let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineName == "rgb2") { + let timeline = new RGB2Timeline(frames, frames * 6, slotIndex); + let keyMap = timelineMap[0]; + let time = getValue(keyMap, "time", 0); + let color = Color.fromString(keyMap.light); + let color2 = Color.fromString(keyMap.dark); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let newColor = Color.fromString(nextMap.light); + let newColor2 = Color.fromString(nextMap.dark); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + time = time2; + color = newColor; + color2 = newColor2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.bones) { + for (let boneName in map.bones) { + let boneMap = map.bones[boneName]; + let bone = skeletonData.findBone(boneName); + if (!bone) + throw new Error("Bone not found: " + boneName); + let boneIndex = bone.index; + for (let timelineName in boneMap) { + let timelineMap = boneMap[timelineName]; + let frames = timelineMap.length; + if (frames == 0) + continue; + if (timelineName === "rotate") { + timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1)); + } else if (timelineName === "translate") { + let timeline = new TranslateTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale)); + } else if (timelineName === "translatex") { + let timeline = new TranslateXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "translatey") { + let timeline = new TranslateYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, scale)); + } else if (timelineName === "scale") { + let timeline = new ScaleTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1)); + } else if (timelineName === "scalex") { + let timeline = new ScaleXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "scaley") { + let timeline = new ScaleYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 1, 1)); + } else if (timelineName === "shear") { + let timeline = new ShearTimeline(frames, frames << 1, boneIndex); + timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1)); + } else if (timelineName === "shearx") { + let timeline = new ShearXTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "sheary") { + let timeline = new ShearYTimeline(frames, frames, boneIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } else if (timelineName === "inherit") { + let timeline = new InheritTimeline(frames, bone.index); + for (let frame = 0; frame < timelineMap.length; frame++) { + let aFrame = timelineMap[frame]; + timeline.setFrame(frame, getValue(aFrame, "time", 0), Utils.enumValue(Inherit, getValue(aFrame, "inherit", "Normal"))); + } + timelines.push(timeline); + } + } + } + } + if (map.ik) { + for (let constraintName in map.ik) { + let constraintMap = map.ik[constraintName]; + let keyMap = constraintMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findIkConstraint(constraintName); + if (!constraint) + throw new Error("IK Constraint not found: " + constraintName); + let constraintIndex = skeletonData.ikConstraints.indexOf(constraint); + let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mix = getValue(keyMap, "mix", 1); + let softness = getValue(keyMap, "softness", 0) * scale; + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false)); + let nextMap = constraintMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mix2 = getValue(nextMap, "mix", 1); + let softness2 = getValue(nextMap, "softness", 0) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale); + } + time = time2; + mix = mix2; + softness = softness2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.transform) { + for (let constraintName in map.transform) { + let timelineMap = map.transform[constraintName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let constraint = skeletonData.findTransformConstraint(constraintName); + if (!constraint) + throw new Error("Transform constraint not found: " + constraintName); + let constraintIndex = skeletonData.transformConstraints.indexOf(constraint); + let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + let mixScaleX = getValue(keyMap, "mixScaleX", 1); + let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX); + let mixShearY = getValue(keyMap, "mixShearY", 1); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let mixScaleX2 = getValue(nextMap, "mixScaleX", 1); + let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2); + let mixShearY2 = getValue(nextMap, "mixShearY", 1); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + mixScaleX = mixScaleX2; + mixScaleY = mixScaleY2; + mixScaleX = mixScaleX2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + if (map.path) { + for (let constraintName in map.path) { + let constraintMap = map.path[constraintName]; + let constraint = skeletonData.findPathConstraint(constraintName); + if (!constraint) + throw new Error("Path constraint not found: " + constraintName); + let constraintIndex = skeletonData.pathConstraints.indexOf(constraint); + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let frames = timelineMap.length; + if (timelineName === "position") { + let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == 0 /* Fixed */ ? scale : 1)); + } else if (timelineName === "spacing") { + let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex); + timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == 0 /* Length */ || constraint.spacingMode == 1 /* Fixed */ ? scale : 1)); + } else if (timelineName === "mix") { + let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex); + let time = getValue(keyMap, "time", 0); + let mixRotate = getValue(keyMap, "mixRotate", 1); + let mixX = getValue(keyMap, "mixX", 1); + let mixY = getValue(keyMap, "mixY", mixX); + for (let frame = 0, bezier = 0; ; frame++) { + timeline.setFrame(frame, time, mixRotate, mixX, mixY); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let mixRotate2 = getValue(nextMap, "mixRotate", 1); + let mixX2 = getValue(nextMap, "mixX", 1); + let mixY2 = getValue(nextMap, "mixY", mixX2); + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1); + bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + timelines.push(timeline); + } + } + } + } + if (map.physics) { + for (let constraintName in map.physics) { + let constraintMap = map.physics[constraintName]; + let constraintIndex = -1; + if (constraintName.length > 0) { + let constraint = skeletonData.findPhysicsConstraint(constraintName); + if (!constraint) + throw new Error("Physics constraint not found: " + constraintName); + constraintIndex = skeletonData.physicsConstraints.indexOf(constraint); + } + for (let timelineName in constraintMap) { + let timelineMap = constraintMap[timelineName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + let frames = timelineMap.length; + if (timelineName == "reset") { + const timeline2 = new PhysicsConstraintResetTimeline(frames, constraintIndex); + for (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++) + timeline2.setFrame(frame, getValue(keyMap, "time", 0)); + timelines.push(timeline2); + continue; + } + let timeline; + if (timelineName == "inertia") + timeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex); + else if (timelineName == "strength") + timeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex); + else if (timelineName == "damping") + timeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex); + else if (timelineName == "mass") + timeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex); + else if (timelineName == "wind") + timeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex); + else if (timelineName == "gravity") + timeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex); + else if (timelineName == "mix") + timeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex); + else + continue; + timelines.push(readTimeline12(timelineMap, timeline, 0, 1)); + } + } + } + if (map.attachments) { + for (let attachmentsName in map.attachments) { + let attachmentsMap = map.attachments[attachmentsName]; + let skin = skeletonData.findSkin(attachmentsName); + if (!skin) + throw new Error("Skin not found: " + attachmentsName); + for (let slotMapName in attachmentsMap) { + let slotMap = attachmentsMap[slotMapName]; + let slot = skeletonData.findSlot(slotMapName); + if (!slot) + throw new Error("Slot not found: " + slotMapName); + let slotIndex = slot.index; + for (let attachmentMapName in slotMap) { + let attachmentMap = slotMap[attachmentMapName]; + let attachment = skin.getAttachment(slotIndex, attachmentMapName); + for (let timelineMapName in attachmentMap) { + let timelineMap = attachmentMap[timelineMapName]; + let keyMap = timelineMap[0]; + if (!keyMap) + continue; + if (timelineMapName == "deform") { + let weighted = attachment.bones; + let vertices = attachment.vertices; + let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment); + let time = getValue(keyMap, "time", 0); + for (let frame = 0, bezier = 0; ; frame++) { + let deform; + let verticesValue = getValue(keyMap, "vertices", null); + if (!verticesValue) + deform = weighted ? Utils.newFloatArray(deformLength) : vertices; + else { + deform = Utils.newFloatArray(deformLength); + let start = getValue(keyMap, "offset", 0); + Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length); + if (scale != 1) { + for (let i = start, n = i + verticesValue.length; i < n; i++) + deform[i] *= scale; + } + if (!weighted) { + for (let i = 0; i < deformLength; i++) + deform[i] += vertices[i]; + } + } + timeline.setFrame(frame, time, deform); + let nextMap = timelineMap[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + break; + } + let time2 = getValue(nextMap, "time", 0); + let curve = keyMap.curve; + if (curve) + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1); + time = time2; + keyMap = nextMap; + } + timelines.push(timeline); + } else if (timelineMapName == "sequence") { + let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment); + let lastDelay = 0; + for (let frame = 0; frame < timelineMap.length; frame++) { + let delay = getValue(keyMap, "delay", lastDelay); + let time = getValue(keyMap, "time", 0); + let mode = SequenceMode[getValue(keyMap, "mode", "hold")]; + let index = getValue(keyMap, "index", 0); + timeline.setFrame(frame, time, mode, index, delay); + lastDelay = delay; + keyMap = timelineMap[frame + 1]; + } + timelines.push(timeline); + } + } + } + } + } + } + if (map.drawOrder) { + let timeline = new DrawOrderTimeline(map.drawOrder.length); + let slotCount = skeletonData.slots.length; + let frame = 0; + for (let i = 0; i < map.drawOrder.length; i++, frame++) { + let drawOrderMap = map.drawOrder[i]; + let drawOrder = null; + let offsets = getValue(drawOrderMap, "offsets", null); + if (offsets) { + drawOrder = Utils.newArray(slotCount, -1); + let unchanged = Utils.newArray(slotCount - offsets.length, 0); + let originalIndex = 0, unchangedIndex = 0; + for (let ii = 0; ii < offsets.length; ii++) { + let offsetMap = offsets[ii]; + let slot = skeletonData.findSlot(offsetMap.slot); + if (!slot) + throw new Error("Slot not found: " + slot); + let slotIndex = slot.index; + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + drawOrder[originalIndex + offsetMap.offset] = originalIndex++; + } + while (originalIndex < slotCount) + unchanged[unchangedIndex++] = originalIndex++; + for (let ii = slotCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) + drawOrder[ii] = unchanged[--unchangedIndex]; + } + timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder); + } + timelines.push(timeline); + } + if (map.events) { + let timeline = new EventTimeline(map.events.length); + let frame = 0; + for (let i = 0; i < map.events.length; i++, frame++) { + let eventMap = map.events[i]; + let eventData = skeletonData.findEvent(eventMap.name); + if (!eventData) + throw new Error("Event not found: " + eventMap.name); + let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData); + event.intValue = getValue(eventMap, "int", eventData.intValue); + event.floatValue = getValue(eventMap, "float", eventData.floatValue); + event.stringValue = getValue(eventMap, "string", eventData.stringValue); + if (event.data.audioPath) { + event.volume = getValue(eventMap, "volume", 1); + event.balance = getValue(eventMap, "balance", 0); + } + timeline.setFrame(frame, event); + } + timelines.push(timeline); + } + let duration = 0; + for (let i = 0, n = timelines.length; i < n; i++) + duration = Math.max(duration, timelines[i].getDuration()); + skeletonData.animations.push(new Animation(name, timelines, duration)); + } + }; + var LinkedMesh2 = class { + parent; + skin; + slotIndex; + mesh; + inheritTimeline; + constructor(mesh, skin, slotIndex, parent, inheritDeform) { + this.mesh = mesh; + this.skin = skin; + this.slotIndex = slotIndex; + this.parent = parent; + this.inheritTimeline = inheritDeform; + } + }; + function readTimeline12(keys, timeline, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value = getValue(keyMap, "value", defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let value2 = getValue(nextMap, "value", defaultValue) * scale; + if (keyMap.curve) + bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale); + time = time2; + value = value2; + keyMap = nextMap; + } + } + function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) { + let keyMap = keys[0]; + let time = getValue(keyMap, "time", 0); + let value1 = getValue(keyMap, name1, defaultValue) * scale; + let value2 = getValue(keyMap, name2, defaultValue) * scale; + let bezier = 0; + for (let frame = 0; ; frame++) { + timeline.setFrame(frame, time, value1, value2); + let nextMap = keys[frame + 1]; + if (!nextMap) { + timeline.shrink(bezier); + return timeline; + } + let time2 = getValue(nextMap, "time", 0); + let nvalue1 = getValue(nextMap, name1, defaultValue) * scale; + let nvalue2 = getValue(nextMap, name2, defaultValue) * scale; + let curve = keyMap.curve; + if (curve) { + bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale); + bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale); + } + time = time2; + value1 = nvalue1; + value2 = nvalue2; + keyMap = nextMap; + } + } + function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) { + if (curve == "stepped") { + timeline.setStepped(frame); + return bezier; + } + let i = value << 2; + let cx1 = curve[i]; + let cy1 = curve[i + 1] * scale; + let cx2 = curve[i + 2]; + let cy2 = curve[i + 3] * scale; + timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2); + return bezier + 1; + } + function getValue(map, property, defaultValue) { + return map[property] !== void 0 ? map[property] : defaultValue; + } + + // spine-core/src/polyfills.ts + (() => { + if (typeof Math.fround === "undefined") { + Math.fround = function(array) { + return function(x) { + return array[0] = x, array[0]; + }; + }(new Float32Array(1)); + } + })(); + + // spine-webgl/src/WebGL.ts + var ManagedWebGLRenderingContext = class { + canvas; + gl; + restorables = new Array(); + constructor(canvasOrContext, contextConfig = { alpha: "true" }) { + if (!(canvasOrContext instanceof WebGLRenderingContext || typeof WebGL2RenderingContext !== "undefined" && canvasOrContext instanceof WebGL2RenderingContext)) { + let canvas = canvasOrContext; + this.gl = canvas.getContext("webgl2", contextConfig) || canvas.getContext("webgl", contextConfig); + this.canvas = canvas; + canvas.addEventListener("webglcontextlost", (e) => { + let event = e; + if (e) + e.preventDefault(); + }); + canvas.addEventListener("webglcontextrestored", (e) => { + for (let i = 0, n = this.restorables.length; i < n; i++) + this.restorables[i].restore(); + }); + } else { + this.gl = canvasOrContext; + this.canvas = this.gl.canvas; + } + } + addRestorable(restorable) { + this.restorables.push(restorable); + } + removeRestorable(restorable) { + let index = this.restorables.indexOf(restorable); + if (index > -1) + this.restorables.splice(index, 1); + } + }; + + // spine-webgl/src/GLTexture.ts + var _GLTexture = class extends Texture { + context; + texture = null; + boundUnit = 0; + useMipMaps = false; + constructor(context, image, useMipMaps = false) { + super(image); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.useMipMaps = useMipMaps; + this.restore(); + this.context.addRestorable(this); + } + setFilters(minFilter, magFilter) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, _GLTexture.validateMagFilter(magFilter)); + this.useMipMaps = _GLTexture.usesMipMaps(minFilter); + if (this.useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + } + static validateMagFilter(magFilter) { + switch (magFilter) { + case 9987 /* MipMapLinearLinear */: + case 9985 /* MipMapLinearNearest */: + case 9986 /* MipMapNearestLinear */: + case 9984 /* MipMapNearestNearest */: + return 9729 /* Linear */; + default: + return magFilter; + } + } + static usesMipMaps(filter) { + switch (filter) { + case 9987 /* MipMapLinearLinear */: + case 9985 /* MipMapLinearNearest */: + case 9986 /* MipMapNearestLinear */: + case 9984 /* MipMapNearestNearest */: + return true; + default: + return false; + } + } + setWraps(uWrap, vWrap) { + let gl = this.context.gl; + this.bind(); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap); + } + update(useMipMaps) { + let gl = this.context.gl; + if (!this.texture) + this.texture = this.context.gl.createTexture(); + this.bind(); + if (_GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + if (useMipMaps) + gl.generateMipmap(gl.TEXTURE_2D); + } + restore() { + this.texture = null; + this.update(this.useMipMaps); + } + bind(unit = 0) { + let gl = this.context.gl; + this.boundUnit = unit; + gl.activeTexture(gl.TEXTURE0 + unit); + gl.bindTexture(gl.TEXTURE_2D, this.texture); + } + unbind() { + let gl = this.context.gl; + gl.activeTexture(gl.TEXTURE0 + this.boundUnit); + gl.bindTexture(gl.TEXTURE_2D, null); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteTexture(this.texture); + } + }; + var GLTexture = _GLTexture; + __publicField(GLTexture, "DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL", false); + + // spine-webgl/src/AssetManager.ts + var AssetManager = class extends AssetManagerBase { + constructor(context, pathPrefix = "", downloader = new Downloader()) { + super((image) => { + return new GLTexture(context, image); + }, pathPrefix, downloader); + } + }; + + // spine-webgl/src/Vector3.ts + var Vector3 = class { + x = 0; + y = 0; + z = 0; + constructor(x = 0, y = 0, z = 0) { + this.x = x; + this.y = y; + this.z = z; + } + setFrom(v) { + this.x = v.x; + this.y = v.y; + this.z = v.z; + return this; + } + set(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } + add(v) { + this.x += v.x; + this.y += v.y; + this.z += v.z; + return this; + } + sub(v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + return this; + } + scale(s) { + this.x *= s; + this.y *= s; + this.z *= s; + return this; + } + normalize() { + let len = this.length(); + if (len == 0) + return this; + len = 1 / len; + this.x *= len; + this.y *= len; + this.z *= len; + return this; + } + cross(v) { + return this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x); + } + multiply(matrix) { + let l_mat = matrix.values; + return this.set( + this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03], + this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13], + this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23] + ); + } + project(matrix) { + let l_mat = matrix.values; + let l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]); + return this.set( + (this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w, + (this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w, + (this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w + ); + } + dot(v) { + return this.x * v.x + this.y * v.y + this.z * v.z; + } + length() { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + distance(v) { + let a = v.x - this.x; + let b = v.y - this.y; + let c = v.z - this.z; + return Math.sqrt(a * a + b * b + c * c); + } + }; + + // spine-webgl/src/Matrix4.ts + var M00 = 0; + var M01 = 4; + var M02 = 8; + var M03 = 12; + var M10 = 1; + var M11 = 5; + var M12 = 9; + var M13 = 13; + var M20 = 2; + var M21 = 6; + var M22 = 10; + var M23 = 14; + var M30 = 3; + var M31 = 7; + var M32 = 11; + var M33 = 15; + var _Matrix4 = class { + temp = new Float32Array(16); + values = new Float32Array(16); + constructor() { + let v = this.values; + v[M00] = 1; + v[M11] = 1; + v[M22] = 1; + v[M33] = 1; + } + set(values) { + this.values.set(values); + return this; + } + transpose() { + let t = this.temp; + let v = this.values; + t[M00] = v[M00]; + t[M01] = v[M10]; + t[M02] = v[M20]; + t[M03] = v[M30]; + t[M10] = v[M01]; + t[M11] = v[M11]; + t[M12] = v[M21]; + t[M13] = v[M31]; + t[M20] = v[M02]; + t[M21] = v[M12]; + t[M22] = v[M22]; + t[M23] = v[M32]; + t[M30] = v[M03]; + t[M31] = v[M13]; + t[M32] = v[M23]; + t[M33] = v[M33]; + return this.set(t); + } + identity() { + let v = this.values; + v[M00] = 1; + v[M01] = 0; + v[M02] = 0; + v[M03] = 0; + v[M10] = 0; + v[M11] = 1; + v[M12] = 0; + v[M13] = 0; + v[M20] = 0; + v[M21] = 0; + v[M22] = 1; + v[M23] = 0; + v[M30] = 0; + v[M31] = 0; + v[M32] = 0; + v[M33] = 1; + return this; + } + invert() { + let v = this.values; + let t = this.temp; + let l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + if (l_det == 0) + throw new Error("non-invertible matrix"); + let inv_det = 1 / l_det; + t[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32] - v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33]; + t[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32] + v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33]; + t[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32] - v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33]; + t[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22] + v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23]; + t[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32] + v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33]; + t[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32] - v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33]; + t[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32] + v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33]; + t[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22] - v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23]; + t[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31] - v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33]; + t[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31] + v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33]; + t[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31] - v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33]; + t[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21] + v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23]; + t[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31] + v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32]; + t[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31] - v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32]; + t[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31] + v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32]; + t[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21] - v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22]; + v[M00] = t[M00] * inv_det; + v[M01] = t[M01] * inv_det; + v[M02] = t[M02] * inv_det; + v[M03] = t[M03] * inv_det; + v[M10] = t[M10] * inv_det; + v[M11] = t[M11] * inv_det; + v[M12] = t[M12] * inv_det; + v[M13] = t[M13] * inv_det; + v[M20] = t[M20] * inv_det; + v[M21] = t[M21] * inv_det; + v[M22] = t[M22] * inv_det; + v[M23] = t[M23] * inv_det; + v[M30] = t[M30] * inv_det; + v[M31] = t[M31] * inv_det; + v[M32] = t[M32] * inv_det; + v[M33] = t[M33] * inv_det; + return this; + } + determinant() { + let v = this.values; + return v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33]; + } + translate(x, y, z) { + let v = this.values; + v[M03] += x; + v[M13] += y; + v[M23] += z; + return this; + } + copy() { + return new _Matrix4().set(this.values); + } + projection(near, far, fovy, aspectRatio) { + this.identity(); + let l_fd = 1 / Math.tan(fovy * (Math.PI / 180) / 2); + let l_a1 = (far + near) / (near - far); + let l_a2 = 2 * far * near / (near - far); + let v = this.values; + v[M00] = l_fd / aspectRatio; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = l_fd; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = l_a1; + v[M32] = -1; + v[M03] = 0; + v[M13] = 0; + v[M23] = l_a2; + v[M33] = 0; + return this; + } + ortho2d(x, y, width, height) { + return this.ortho(x, x + width, y, y + height, 0, 1); + } + ortho(left, right, bottom, top, near, far) { + this.identity(); + let x_orth = 2 / (right - left); + let y_orth = 2 / (top - bottom); + let z_orth = -2 / (far - near); + let tx = -(right + left) / (right - left); + let ty = -(top + bottom) / (top - bottom); + let tz = -(far + near) / (far - near); + let v = this.values; + v[M00] = x_orth; + v[M10] = 0; + v[M20] = 0; + v[M30] = 0; + v[M01] = 0; + v[M11] = y_orth; + v[M21] = 0; + v[M31] = 0; + v[M02] = 0; + v[M12] = 0; + v[M22] = z_orth; + v[M32] = 0; + v[M03] = tx; + v[M13] = ty; + v[M23] = tz; + v[M33] = 1; + return this; + } + multiply(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30]; + t[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31]; + t[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32]; + t[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33]; + t[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30]; + t[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31]; + t[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32]; + t[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33]; + t[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30]; + t[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31]; + t[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32]; + t[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33]; + t[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30]; + t[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31]; + t[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32]; + t[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33]; + return this.set(this.temp); + } + multiplyLeft(matrix) { + let t = this.temp; + let v = this.values; + let m = matrix.values; + t[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30]; + t[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31]; + t[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32]; + t[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33]; + t[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30]; + t[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31]; + t[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32]; + t[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33]; + t[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30]; + t[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31]; + t[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32]; + t[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33]; + t[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30]; + t[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31]; + t[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32]; + t[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33]; + return this.set(this.temp); + } + lookAt(position, direction, up) { + let xAxis = _Matrix4.xAxis, yAxis = _Matrix4.yAxis, zAxis = _Matrix4.zAxis; + zAxis.setFrom(direction).normalize(); + xAxis.setFrom(direction).normalize(); + xAxis.cross(up).normalize(); + yAxis.setFrom(xAxis).cross(zAxis).normalize(); + this.identity(); + let val = this.values; + val[M00] = xAxis.x; + val[M01] = xAxis.y; + val[M02] = xAxis.z; + val[M10] = yAxis.x; + val[M11] = yAxis.y; + val[M12] = yAxis.z; + val[M20] = -zAxis.x; + val[M21] = -zAxis.y; + val[M22] = -zAxis.z; + _Matrix4.tmpMatrix.identity(); + _Matrix4.tmpMatrix.values[M03] = -position.x; + _Matrix4.tmpMatrix.values[M13] = -position.y; + _Matrix4.tmpMatrix.values[M23] = -position.z; + this.multiply(_Matrix4.tmpMatrix); + return this; + } + }; + var Matrix42 = _Matrix4; + __publicField(Matrix42, "xAxis", new Vector3()); + __publicField(Matrix42, "yAxis", new Vector3()); + __publicField(Matrix42, "zAxis", new Vector3()); + __publicField(Matrix42, "tmpMatrix", new _Matrix4()); + + // spine-webgl/src/Camera.ts + var OrthoCamera = class { + position = new Vector3(0, 0, 0); + direction = new Vector3(0, 0, -1); + up = new Vector3(0, 1, 0); + near = 0; + far = 100; + zoom = 1; + viewportWidth = 0; + viewportHeight = 0; + projectionView = new Matrix42(); + inverseProjectionView = new Matrix42(); + projection = new Matrix42(); + view = new Matrix42(); + constructor(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.update(); + } + update() { + let projection = this.projection; + let view = this.view; + let projectionView = this.projectionView; + let inverseProjectionView = this.inverseProjectionView; + let zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight; + projection.ortho( + zoom * (-viewportWidth / 2), + zoom * (viewportWidth / 2), + zoom * (-viewportHeight / 2), + zoom * (viewportHeight / 2), + this.near, + this.far + ); + view.lookAt(this.position, this.direction, this.up); + projectionView.set(projection.values); + projectionView.multiply(view); + inverseProjectionView.set(projectionView.values).invert(); + } + screenToWorld(screenCoords, screenWidth, screenHeight) { + let x = screenCoords.x, y = screenHeight - screenCoords.y - 1; + screenCoords.x = 2 * x / screenWidth - 1; + screenCoords.y = 2 * y / screenHeight - 1; + screenCoords.z = 2 * screenCoords.z - 1; + screenCoords.project(this.inverseProjectionView); + return screenCoords; + } + worldToScreen(worldCoords, screenWidth, screenHeight) { + worldCoords.project(this.projectionView); + worldCoords.x = screenWidth * (worldCoords.x + 1) / 2; + worldCoords.y = screenHeight * (worldCoords.y + 1) / 2; + worldCoords.z = (worldCoords.z + 1) / 2; + return worldCoords; + } + setViewport(viewportWidth, viewportHeight) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + } + }; + + // spine-webgl/src/Input.ts + var Input = class { + element; + mouseX = 0; + mouseY = 0; + buttonDown = false; + touch0 = null; + touch1 = null; + initialPinchDistance = 0; + listeners = new Array(); + eventListeners = []; + constructor(element) { + this.element = element; + this.setupCallbacks(element); + } + setupCallbacks(element) { + let mouseDown = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) + listener.down(this.mouseX, this.mouseY); + }); + document.addEventListener("mousemove", mouseMove); + document.addEventListener("mouseup", mouseUp); + } + }; + let mouseMove = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.listeners.map((listener) => { + if (this.buttonDown) { + if (listener.dragged) + listener.dragged(this.mouseX, this.mouseY); + } else { + if (listener.moved) + listener.moved(this.mouseX, this.mouseY); + } + }); + } + }; + let mouseUp = (ev) => { + if (ev instanceof MouseEvent) { + let rect = element.getBoundingClientRect(); + this.mouseX = ev.clientX - rect.left; + ; + this.mouseY = ev.clientY - rect.top; + this.buttonDown = false; + this.listeners.map((listener) => { + if (listener.up) + listener.up(this.mouseX, this.mouseY); + }); + document.removeEventListener("mousemove", mouseMove); + document.removeEventListener("mouseup", mouseUp); + } + }; + let mouseWheel = (e) => { + e.preventDefault(); + let deltaY = e.deltaY; + if (e.deltaMode == WheelEvent.DOM_DELTA_LINE) + deltaY *= 8; + if (e.deltaMode == WheelEvent.DOM_DELTA_PAGE) + deltaY *= 24; + this.listeners.map((listener) => { + if (listener.wheel) + listener.wheel(e.deltaY); + }); + }; + element.addEventListener("mousedown", mouseDown, true); + element.addEventListener("mousemove", mouseMove, true); + element.addEventListener("mouseup", mouseUp, true); + element.addEventListener("wheel", mouseWheel, true); + element.addEventListener("touchstart", (ev) => { + if (!this.touch0 || !this.touch1) { + var touches = ev.changedTouches; + let nativeTouch = touches.item(0); + if (!nativeTouch) + return; + let rect = element.getBoundingClientRect(); + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + let touch = new Touch(nativeTouch.identifier, x, y); + this.mouseX = x; + this.mouseY = y; + this.buttonDown = true; + if (!this.touch0) { + this.touch0 = touch; + this.listeners.map((listener) => { + if (listener.down) + listener.down(touch.x, touch.y); + }); + } else if (!this.touch1) { + this.touch1 = touch; + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) + listener.zoom(this.initialPinchDistance, this.initialPinchDistance); + }); + } + } + ev.preventDefault(); + }, false); + element.addEventListener("touchmove", (ev) => { + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0.x = this.mouseX = x; + this.touch0.y = this.mouseY = y; + this.listeners.map((listener) => { + if (listener.dragged) + listener.dragged(x, y); + }); + } + if (this.touch1 && this.touch1.identifier === nativeTouch.identifier) { + this.touch1.x = this.mouseX = x; + this.touch1.y = this.mouseY = y; + } + } + if (this.touch0 && this.touch1) { + let dx = this.touch1.x - this.touch0.x; + let dy = this.touch1.x - this.touch0.x; + let distance = Math.sqrt(dx * dx + dy * dy); + this.listeners.map((listener) => { + if (listener.zoom) + listener.zoom(this.initialPinchDistance, distance); + }); + } + } + ev.preventDefault(); + }, false); + let touchEnd = (ev) => { + if (this.touch0) { + var touches = ev.changedTouches; + let rect = element.getBoundingClientRect(); + for (var i = 0; i < touches.length; i++) { + var nativeTouch = touches[i]; + let x = nativeTouch.clientX - rect.left; + let y = nativeTouch.clientY - rect.top; + if (this.touch0.identifier === nativeTouch.identifier) { + this.touch0 = null; + this.mouseX = x; + this.mouseY = y; + this.listeners.map((listener) => { + if (listener.up) + listener.up(x, y); + }); + if (!this.touch1) { + this.buttonDown = false; + break; + } else { + this.touch0 = this.touch1; + this.touch1 = null; + this.mouseX = this.touch0.x; + this.mouseX = this.touch0.x; + this.buttonDown = true; + this.listeners.map((listener) => { + if (listener.down) + listener.down(this.touch0.x, this.touch0.y); + }); + } + } + if (this.touch1 && this.touch1.identifier) { + this.touch1 = null; + } + } + } + ev.preventDefault(); + }; + element.addEventListener("touchend", touchEnd, false); + element.addEventListener("touchcancel", touchEnd); + } + addListener(listener) { + this.listeners.push(listener); + } + removeListener(listener) { + let idx = this.listeners.indexOf(listener); + if (idx > -1) { + this.listeners.splice(idx, 1); + } + } + }; + var Touch = class { + constructor(identifier, x, y) { + this.identifier = identifier; + this.x = x; + this.y = y; + } + }; + + // spine-webgl/src/CameraController.ts + var CameraController = class { + constructor(canvas, camera) { + this.canvas = canvas; + this.camera = camera; + let cameraX = 0, cameraY = 0, cameraZoom = 0; + let mouseX = 0, mouseY = 0; + let lastX = 0, lastY = 0; + let initialZoom = 0; + new Input(canvas).addListener({ + down: (x, y) => { + cameraX = camera.position.x; + cameraY = camera.position.y; + mouseX = lastX = x; + mouseY = lastY = y; + initialZoom = camera.zoom; + }, + dragged: (x, y) => { + let deltaX = x - mouseX; + let deltaY = y - mouseY; + let originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight); + let deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld); + camera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0); + camera.update(); + lastX = x; + lastY = y; + }, + wheel: (delta) => { + let zoomAmount = delta / 200 * camera.zoom; + let newZoom = camera.zoom + zoomAmount; + if (newZoom > 0) { + let x = 0, y = 0; + if (delta < 0) { + x = lastX; + y = lastY; + } else { + let viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2); + let mouseToCenterX = lastX - viewCenter.x; + let mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y; + x = viewCenter.x - mouseToCenterX; + y = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY; + } + let oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.zoom = newZoom; + camera.update(); + let newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight); + camera.position.add(oldDistance.sub(newDistance)); + camera.update(); + } + }, + zoom: (initialDistance, distance) => { + let newZoom = initialDistance / distance; + camera.zoom = initialZoom * newZoom; + }, + up: (x, y) => { + lastX = x; + lastY = y; + }, + moved: (x, y) => { + lastX = x; + lastY = y; + } + }); + } + }; + + // spine-webgl/src/Shader.ts + var _Shader = class { + constructor(context, vertexShader, fragmentShader) { + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + this.vsSource = vertexShader; + this.fsSource = fragmentShader; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.context.addRestorable(this); + this.compile(); + } + context; + vs = null; + vsSource; + fs = null; + fsSource; + program = null; + tmp2x2 = new Float32Array(2 * 2); + tmp3x3 = new Float32Array(3 * 3); + tmp4x4 = new Float32Array(4 * 4); + getProgram() { + return this.program; + } + getVertexShader() { + return this.vertexShader; + } + getFragmentShader() { + return this.fragmentShader; + } + getVertexShaderSource() { + return this.vsSource; + } + getFragmentSource() { + return this.fsSource; + } + compile() { + let gl = this.context.gl; + try { + this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader); + if (!this.vs) + throw new Error("Couldn't compile vertex shader."); + this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader); + if (!this.fs) + throw new Error("Couldn#t compile fragment shader."); + this.program = this.compileProgram(this.vs, this.fs); + } catch (e) { + this.dispose(); + throw e; + } + } + compileShader(type, source) { + let gl = this.context.gl; + let shader = gl.createShader(type); + if (!shader) + throw new Error("Couldn't create shader."); + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + let error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + if (!gl.isContextLost()) + throw new Error(error); + } + return shader; + } + compileProgram(vs, fs) { + let gl = this.context.gl; + let program = gl.createProgram(); + if (!program) + throw new Error("Couldn't compile program."); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + let error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program); + gl.deleteProgram(program); + if (!gl.isContextLost()) + throw new Error(error); + } + return program; + } + restore() { + this.compile(); + } + bind() { + this.context.gl.useProgram(this.program); + } + unbind() { + this.context.gl.useProgram(null); + } + setUniformi(uniform, value) { + this.context.gl.uniform1i(this.getUniformLocation(uniform), value); + } + setUniformf(uniform, value) { + this.context.gl.uniform1f(this.getUniformLocation(uniform), value); + } + setUniform2f(uniform, value, value2) { + this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2); + } + setUniform3f(uniform, value, value2, value3) { + this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3); + } + setUniform4f(uniform, value, value2, value3, value4) { + this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4); + } + setUniform2x2f(uniform, value) { + let gl = this.context.gl; + this.tmp2x2.set(value); + gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2); + } + setUniform3x3f(uniform, value) { + let gl = this.context.gl; + this.tmp3x3.set(value); + gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3); + } + setUniform4x4f(uniform, value) { + let gl = this.context.gl; + this.tmp4x4.set(value); + gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4); + } + getUniformLocation(uniform) { + let gl = this.context.gl; + if (!this.program) + throw new Error("Shader not compiled."); + let location = gl.getUniformLocation(this.program, uniform); + if (!location && !gl.isContextLost()) + throw new Error(`Couldn't find location for uniform ${uniform}`); + return location; + } + getAttributeLocation(attribute) { + let gl = this.context.gl; + if (!this.program) + throw new Error("Shader not compiled."); + let location = gl.getAttribLocation(this.program, attribute); + if (location == -1 && !gl.isContextLost()) + throw new Error(`Couldn't find location for attribute ${attribute}`); + return location; + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + if (this.vs) { + gl.deleteShader(this.vs); + this.vs = null; + } + if (this.fs) { + gl.deleteShader(this.fs); + this.fs = null; + } + if (this.program) { + gl.deleteProgram(this.program); + this.program = null; + } + } + static newColoredTextured(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +attribute vec2 ${_Shader.TEXCOORDS}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_color; +varying vec2 v_texCoords; + +void main () { + v_color = ${_Shader.COLOR}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_color; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +void main () { + gl_FragColor = v_color * texture2D(u_texture, v_texCoords); +} +`; + return new _Shader(context, vs, fs); + } + static newTwoColoredTextured(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +attribute vec4 ${_Shader.COLOR2}; +attribute vec2 ${_Shader.TEXCOORDS}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_light; +varying vec4 v_dark; +varying vec2 v_texCoords; + +void main () { + v_light = ${_Shader.COLOR}; + v_dark = ${_Shader.COLOR2}; + v_texCoords = ${_Shader.TEXCOORDS}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_light; +varying LOWP vec4 v_dark; +varying vec2 v_texCoords; +uniform sampler2D u_texture; + +void main () { + vec4 texColor = texture2D(u_texture, v_texCoords); + gl_FragColor.a = texColor.a * v_light.a; + gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; +} +`; + return new _Shader(context, vs, fs); + } + static newColored(context) { + let vs = ` +attribute vec4 ${_Shader.POSITION}; +attribute vec4 ${_Shader.COLOR}; +uniform mat4 ${_Shader.MVP_MATRIX}; +varying vec4 v_color; + +void main () { + v_color = ${_Shader.COLOR}; + gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION}; +} +`; + let fs = ` +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif +varying LOWP vec4 v_color; + +void main () { + gl_FragColor = v_color; +} +`; + return new _Shader(context, vs, fs); + } + }; + var Shader = _Shader; + __publicField(Shader, "MVP_MATRIX", "u_projTrans"); + __publicField(Shader, "POSITION", "a_position"); + __publicField(Shader, "COLOR", "a_color"); + __publicField(Shader, "COLOR2", "a_color2"); + __publicField(Shader, "TEXCOORDS", "a_texCoords"); + __publicField(Shader, "SAMPLER", "u_texture"); + + // spine-webgl/src/Mesh.ts + var Mesh = class { + constructor(context, attributes, maxVertices, maxIndices) { + this.attributes = attributes; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.elementsPerVertex = 0; + for (let i = 0; i < attributes.length; i++) { + this.elementsPerVertex += attributes[i].numElements; + } + this.vertices = new Float32Array(maxVertices * this.elementsPerVertex); + this.indices = new Uint16Array(maxIndices); + this.context.addRestorable(this); + } + context; + vertices; + verticesBuffer = null; + verticesLength = 0; + dirtyVertices = false; + indices; + indicesBuffer = null; + indicesLength = 0; + dirtyIndices = false; + elementsPerVertex = 0; + getAttributes() { + return this.attributes; + } + maxVertices() { + return this.vertices.length / this.elementsPerVertex; + } + numVertices() { + return this.verticesLength / this.elementsPerVertex; + } + setVerticesLength(length) { + this.dirtyVertices = true; + this.verticesLength = length; + } + getVertices() { + return this.vertices; + } + maxIndices() { + return this.indices.length; + } + numIndices() { + return this.indicesLength; + } + setIndicesLength(length) { + this.dirtyIndices = true; + this.indicesLength = length; + } + getIndices() { + return this.indices; + } + getVertexSizeInFloats() { + let size = 0; + for (var i = 0; i < this.attributes.length; i++) { + let attribute = this.attributes[i]; + size += attribute.numElements; + } + return size; + } + setVertices(vertices) { + this.dirtyVertices = true; + if (vertices.length > this.vertices.length) + throw Error("Mesh can't store more than " + this.maxVertices() + " vertices"); + this.vertices.set(vertices, 0); + this.verticesLength = vertices.length; + } + setIndices(indices) { + this.dirtyIndices = true; + if (indices.length > this.indices.length) + throw Error("Mesh can't store more than " + this.maxIndices() + " indices"); + this.indices.set(indices, 0); + this.indicesLength = indices.length; + } + draw(shader, primitiveType) { + this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex); + } + drawWithOffset(shader, primitiveType, offset, count) { + let gl = this.context.gl; + if (this.dirtyVertices || this.dirtyIndices) + this.update(); + this.bind(shader); + if (this.indicesLength > 0) { + gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2); + } else { + gl.drawArrays(primitiveType, offset, count); + } + this.unbind(shader); + } + bind(shader) { + let gl = this.context.gl; + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + let offset = 0; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.enableVertexAttribArray(location); + gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4); + offset += attrib.numElements; + } + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + } + unbind(shader) { + let gl = this.context.gl; + for (let i = 0; i < this.attributes.length; i++) { + let attrib = this.attributes[i]; + let location = shader.getAttributeLocation(attrib.name); + gl.disableVertexAttribArray(location); + } + gl.bindBuffer(gl.ARRAY_BUFFER, null); + if (this.indicesLength > 0) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + } + update() { + let gl = this.context.gl; + if (this.dirtyVertices) { + if (!this.verticesBuffer) { + this.verticesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); + gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW); + this.dirtyVertices = false; + } + if (this.dirtyIndices) { + if (!this.indicesBuffer) { + this.indicesBuffer = gl.createBuffer(); + } + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW); + this.dirtyIndices = false; + } + } + restore() { + this.verticesBuffer = null; + this.indicesBuffer = null; + this.update(); + } + dispose() { + this.context.removeRestorable(this); + let gl = this.context.gl; + gl.deleteBuffer(this.verticesBuffer); + gl.deleteBuffer(this.indicesBuffer); + } + }; + var VertexAttribute = class { + constructor(name, type, numElements) { + this.name = name; + this.type = type; + this.numElements = numElements; + } + }; + var Position2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, VertexAttributeType.Float, 2); + } + }; + var Position3Attribute = class extends VertexAttribute { + constructor() { + super(Shader.POSITION, VertexAttributeType.Float, 3); + } + }; + var TexCoordAttribute = class extends VertexAttribute { + constructor(unit = 0) { + super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2); + } + }; + var ColorAttribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR, VertexAttributeType.Float, 4); + } + }; + var Color2Attribute = class extends VertexAttribute { + constructor() { + super(Shader.COLOR2, VertexAttributeType.Float, 4); + } + }; + var VertexAttributeType = /* @__PURE__ */ ((VertexAttributeType2) => { + VertexAttributeType2[VertexAttributeType2["Float"] = 0] = "Float"; + return VertexAttributeType2; + })(VertexAttributeType || {}); + + // spine-webgl/src/PolygonBatcher.ts + var GL_ONE = 1; + var GL_ONE_MINUS_SRC_COLOR = 769; + var GL_SRC_ALPHA = 770; + var GL_ONE_MINUS_SRC_ALPHA = 771; + var GL_DST_COLOR = 774; + var _PolygonBatcher = class { + context; + drawCalls = 0; + isDrawing = false; + mesh; + shader = null; + lastTexture = null; + verticesLength = 0; + indicesLength = 0; + srcColorBlend; + srcAlphaBlend; + dstBlend; + cullWasEnabled = false; + constructor(context, twoColorTint = true, maxVertices = 10920) { + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + let attributes = twoColorTint ? [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] : [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()]; + this.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) + throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()"); + this.drawCalls = 0; + this.shader = shader; + this.lastTexture = null; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + if (_PolygonBatcher.disableCulling) { + this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE); + if (this.cullWasEnabled) + gl.disable(gl.CULL_FACE); + } + } + setBlendMode(blendMode, premultipliedAlpha) { + const blendModeGL = _PolygonBatcher.blendModesGL[blendMode]; + const srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb; + const srcAlphaBlend = blendModeGL.srcAlpha; + const dstBlend = blendModeGL.dstRgb; + if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) + return; + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + } + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + draw(texture, vertices, indices) { + if (texture != this.lastTexture) { + this.flush(); + this.lastTexture = texture; + } else if (this.verticesLength + vertices.length > this.mesh.getVertices().length || this.indicesLength + indices.length > this.mesh.getIndices().length) { + this.flush(); + } + let indexStart = this.mesh.numVertices(); + this.mesh.getVertices().set(vertices, this.verticesLength); + this.verticesLength += vertices.length; + this.mesh.setVerticesLength(this.verticesLength); + let indicesArray = this.mesh.getIndices(); + for (let i = this.indicesLength, j = 0; j < indices.length; i++, j++) + indicesArray[i] = indices[j] + indexStart; + this.indicesLength += indices.length; + this.mesh.setIndicesLength(this.indicesLength); + } + flush() { + if (this.verticesLength == 0) + return; + if (!this.lastTexture) + throw new Error("No texture set."); + if (!this.shader) + throw new Error("No shader set."); + this.lastTexture.bind(); + this.mesh.draw(this.shader, this.context.gl.TRIANGLES); + this.verticesLength = 0; + this.indicesLength = 0; + this.mesh.setVerticesLength(0); + this.mesh.setIndicesLength(0); + this.drawCalls++; + _PolygonBatcher.globalDrawCalls++; + } + end() { + if (!this.isDrawing) + throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()"); + if (this.verticesLength > 0 || this.indicesLength > 0) + this.flush(); + this.shader = null; + this.lastTexture = null; + this.isDrawing = false; + let gl = this.context.gl; + gl.disable(gl.BLEND); + if (_PolygonBatcher.disableCulling) { + if (this.cullWasEnabled) + gl.enable(gl.CULL_FACE); + } + } + getDrawCalls() { + return this.drawCalls; + } + static getAndResetGlobalDrawCalls() { + let result = _PolygonBatcher.globalDrawCalls; + _PolygonBatcher.globalDrawCalls = 0; + return result; + } + dispose() { + this.mesh.dispose(); + } + }; + var PolygonBatcher = _PolygonBatcher; + __publicField(PolygonBatcher, "disableCulling", false); + __publicField(PolygonBatcher, "globalDrawCalls", 0); + __publicField(PolygonBatcher, "blendModesGL", [ + { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + { srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE }, + { srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE }, + { srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE } + ]); + + // spine-webgl/src/ShapeRenderer.ts + var ShapeRenderer = class { + context; + isDrawing = false; + mesh; + shapeType = ShapeType.Filled; + color = new Color(1, 1, 1, 1); + shader = null; + vertexIndex = 0; + tmp = new Vector2(); + srcColorBlend; + srcAlphaBlend; + dstBlend; + constructor(context, maxVertices = 10920) { + if (maxVertices > 10920) + throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices); + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0); + let gl = this.context.gl; + this.srcColorBlend = gl.SRC_ALPHA; + this.srcAlphaBlend = gl.ONE; + this.dstBlend = gl.ONE_MINUS_SRC_ALPHA; + } + begin(shader) { + if (this.isDrawing) + throw new Error("ShapeRenderer.begin() has already been called"); + this.shader = shader; + this.vertexIndex = 0; + this.isDrawing = true; + let gl = this.context.gl; + gl.enable(gl.BLEND); + gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend); + } + setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) { + this.srcColorBlend = srcColorBlend; + this.srcAlphaBlend = srcAlphaBlend; + this.dstBlend = dstBlend; + if (this.isDrawing) { + this.flush(); + let gl = this.context.gl; + gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend); + } + } + setColor(color) { + this.color.setFromColor(color); + } + setColorWith(r, g, b, a) { + this.color.set(r, g, b, a); + } + point(x, y, color) { + this.check(ShapeType.Point, 1); + if (!color) + color = this.color; + this.vertex(x, y, color); + } + line(x, y, x2, y2, color) { + this.check(ShapeType.Line, 2); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + this.vertex(x, y, color); + this.vertex(x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + if (!color2) + color2 = this.color; + if (!color3) + color3 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color); + this.vertex(x3, y3, color2); + this.vertex(x3, y3, color); + this.vertex(x, y, color2); + } + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 3); + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + if (!color) + color = this.color; + if (!color2) + color2 = this.color; + if (!color3) + color3 = this.color; + if (!color4) + color4 = this.color; + if (filled) { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } else { + this.vertex(x, y, color); + this.vertex(x2, y2, color2); + this.vertex(x2, y2, color2); + this.vertex(x3, y3, color3); + this.vertex(x3, y3, color3); + this.vertex(x4, y4, color4); + this.vertex(x4, y4, color4); + this.vertex(x, y, color); + } + } + rect(filled, x, y, width, height, color) { + this.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.check(filled ? ShapeType.Filled : ShapeType.Line, 8); + if (!color) + color = this.color; + let t = this.tmp.set(y2 - y1, x1 - x2); + t.normalize(); + width *= 0.5; + let tx = t.x * width; + let ty = t.y * width; + if (!filled) { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } else { + this.vertex(x1 + tx, y1 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x2 - tx, y2 - ty, color); + this.vertex(x2 + tx, y2 + ty, color); + this.vertex(x1 - tx, y1 - ty, color); + } + } + x(x, y, size) { + this.line(x - size, y - size, x + size, y + size); + this.line(x - size, y + size, x + size, y - size); + } + polygon(polygonVertices, offset, count, color) { + if (count < 3) + throw new Error("Polygon must contain at least 3 vertices"); + this.check(ShapeType.Line, count * 2); + if (!color) + color = this.color; + let vertices = this.mesh.getVertices(); + let idx = this.vertexIndex; + offset <<= 1; + count <<= 1; + let firstX = polygonVertices[offset]; + let firstY = polygonVertices[offset + 1]; + let last = offset + count; + for (let i = offset, n = offset + count - 2; i < n; i += 2) { + let x1 = polygonVertices[i]; + let y1 = polygonVertices[i + 1]; + let x2 = 0; + let y2 = 0; + if (i + 2 >= last) { + x2 = firstX; + y2 = firstY; + } else { + x2 = polygonVertices[i + 2]; + y2 = polygonVertices[i + 3]; + } + this.vertex(x1, y1, color); + this.vertex(x2, y2, color); + } + } + circle(filled, x, y, radius, color, segments = 0) { + if (segments == 0) + segments = Math.max(1, 6 * MathUtils.cbrt(radius) | 0); + if (segments <= 0) + throw new Error("segments must be > 0."); + if (!color) + color = this.color; + let angle = 2 * MathUtils.PI / segments; + let cos = Math.cos(angle); + let sin = Math.sin(angle); + let cx = radius, cy = 0; + if (!filled) { + this.check(ShapeType.Line, segments * 2 + 2); + for (let i = 0; i < segments; i++) { + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x + cx, y + cy, color); + } else { + this.check(ShapeType.Filled, segments * 3 + 3); + segments--; + for (let i = 0; i < segments; i++) { + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + let temp2 = cx; + cx = cos * cx - sin * cy; + cy = sin * temp2 + cos * cy; + this.vertex(x + cx, y + cy, color); + } + this.vertex(x, y, color); + this.vertex(x + cx, y + cy, color); + } + let temp = cx; + cx = radius; + cy = 0; + this.vertex(x + cx, y + cy, color); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.check(ShapeType.Line, segments * 2 + 2); + if (!color) + color = this.color; + let subdiv_step = 1 / segments; + let subdiv_step2 = subdiv_step * subdiv_step; + let subdiv_step3 = subdiv_step * subdiv_step * subdiv_step; + let pre1 = 3 * subdiv_step; + let pre2 = 3 * subdiv_step2; + let pre4 = 6 * subdiv_step2; + let pre5 = 6 * subdiv_step3; + let tmp1x = x1 - cx1 * 2 + cx2; + let tmp1y = y1 - cy1 * 2 + cy2; + let tmp2x = (cx1 - cx2) * 3 - x1 + x2; + let tmp2y = (cy1 - cy2) * 3 - y1 + y2; + let fx = x1; + let fy = y1; + let dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + let dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + let ddfx = tmp1x * pre4 + tmp2x * pre5; + let ddfy = tmp1y * pre4 + tmp2y * pre5; + let dddfx = tmp2x * pre5; + let dddfy = tmp2y * pre5; + while (segments-- > 0) { + this.vertex(fx, fy, color); + fx += dfx; + fy += dfy; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + this.vertex(fx, fy, color); + } + this.vertex(fx, fy, color); + this.vertex(x2, y2, color); + } + vertex(x, y, color) { + let idx = this.vertexIndex; + let vertices = this.mesh.getVertices(); + vertices[idx++] = x; + vertices[idx++] = y; + vertices[idx++] = color.r; + vertices[idx++] = color.g; + vertices[idx++] = color.b; + vertices[idx++] = color.a; + this.vertexIndex = idx; + } + end() { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + this.flush(); + let gl = this.context.gl; + gl.disable(gl.BLEND); + this.isDrawing = false; + } + flush() { + if (this.vertexIndex == 0) + return; + if (!this.shader) + throw new Error("No shader set."); + this.mesh.setVerticesLength(this.vertexIndex); + this.mesh.draw(this.shader, this.shapeType); + this.vertexIndex = 0; + } + check(shapeType, numVertices) { + if (!this.isDrawing) + throw new Error("ShapeRenderer.begin() has not been called"); + if (this.shapeType == shapeType) { + if (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) + this.flush(); + else + return; + } else { + this.flush(); + this.shapeType = shapeType; + } + } + dispose() { + this.mesh.dispose(); + } + }; + var ShapeType = /* @__PURE__ */ ((ShapeType2) => { + ShapeType2[ShapeType2["Point"] = 0] = "Point"; + ShapeType2[ShapeType2["Line"] = 1] = "Line"; + ShapeType2[ShapeType2["Filled"] = 4] = "Filled"; + return ShapeType2; + })(ShapeType || {}); + + // spine-webgl/src/SkeletonDebugRenderer.ts + var _SkeletonDebugRenderer = class { + boneLineColor = new Color(1, 0, 0, 1); + boneOriginColor = new Color(0, 1, 0, 1); + attachmentLineColor = new Color(0, 0, 1, 0.5); + triangleLineColor = new Color(1, 0.64, 0, 0.5); + pathColor = new Color().setFromString("FF7F00"); + clipColor = new Color(0.8, 0, 0, 2); + aabbColor = new Color(0, 1, 0, 0.5); + drawBones = true; + drawRegionAttachments = true; + drawBoundingBoxes = true; + drawMeshHull = true; + drawMeshTriangles = true; + drawPaths = true; + drawSkeletonXY = false; + drawClipping = true; + premultipliedAlpha = false; + scale = 1; + boneWidth = 2; + context; + bounds = new SkeletonBounds(); + temp = new Array(); + vertices = Utils.newFloatArray(2 * 1024); + constructor(context) { + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + } + draw(shapes, skeleton, ignoredBones) { + let skeletonX = skeleton.x; + let skeletonY = skeleton.y; + let gl = this.context.gl; + let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA; + shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + let bones = skeleton.bones; + if (this.drawBones) { + shapes.setColor(this.boneLineColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + if (!bone.parent) + continue; + let x = bone.data.length * bone.a + bone.worldX; + let y = bone.data.length * bone.c + bone.worldY; + shapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale); + } + if (this.drawSkeletonXY) + shapes.x(skeletonX, skeletonY, 4 * this.scale); + } + if (this.drawRegionAttachments) { + shapes.setColor(this.attachmentLineColor); + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + let attachment = slot.getAttachment(); + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + let vertices = this.vertices; + regionAttachment.computeWorldVertices(slot, vertices, 0, 2); + shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]); + shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]); + shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]); + shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]); + } + } + } + if (this.drawMeshHull || this.drawMeshTriangles) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof MeshAttachment)) + continue; + let mesh = attachment; + let vertices = this.vertices; + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2); + let triangles = mesh.triangles; + let hullLength = mesh.hullLength; + if (this.drawMeshTriangles) { + shapes.setColor(this.triangleLineColor); + for (let ii = 0, nn = triangles.length; ii < nn; ii += 3) { + let v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2; + shapes.triangle( + false, + vertices[v1], + vertices[v1 + 1], + // + vertices[v2], + vertices[v2 + 1], + // + vertices[v3], + vertices[v3 + 1] + // + ); + } + } + if (this.drawMeshHull && hullLength > 0) { + shapes.setColor(this.attachmentLineColor); + hullLength = (hullLength >> 1) * 2; + let lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1]; + for (let ii = 0, nn = hullLength; ii < nn; ii += 2) { + let x = vertices[ii], y = vertices[ii + 1]; + shapes.line(x, y, lastX, lastY); + lastX = x; + lastY = y; + } + } + } + } + if (this.drawBoundingBoxes) { + let bounds = this.bounds; + bounds.update(skeleton, true); + shapes.setColor(this.aabbColor); + shapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight()); + let polygons = bounds.polygons; + let boxes = bounds.boundingBoxes; + for (let i = 0, n = polygons.length; i < n; i++) { + let polygon = polygons[i]; + shapes.setColor(boxes[i].color); + shapes.polygon(polygon, 0, polygon.length); + } + } + if (this.drawPaths) { + let slots = skeleton.slots; + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof PathAttachment)) + continue; + let path = attachment; + let nn = path.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + path.computeWorldVertices(slot, 0, nn, world, 0, 2); + let color = this.pathColor; + let x1 = world[2], y1 = world[3], x2 = 0, y2 = 0; + if (path.closed) { + shapes.setColor(color); + let cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1]; + x2 = world[nn - 4]; + y2 = world[nn - 3]; + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + } + nn -= 4; + for (let ii = 4; ii < nn; ii += 6) { + let cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3]; + x2 = world[ii + 4]; + y2 = world[ii + 5]; + shapes.setColor(color); + shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32); + shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY); + shapes.line(x1, y1, cx1, cy1); + shapes.line(x2, y2, cx2, cy2); + x1 = x2; + y1 = y2; + } + } + } + if (this.drawBones) { + shapes.setColor(this.boneOriginColor); + for (let i = 0, n = bones.length; i < n; i++) { + let bone = bones[i]; + if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) + continue; + shapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8); + } + } + if (this.drawClipping) { + let slots = skeleton.slots; + shapes.setColor(this.clipColor); + for (let i = 0, n = slots.length; i < n; i++) { + let slot = slots[i]; + if (!slot.bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof ClippingAttachment)) + continue; + let clip = attachment; + let nn = clip.worldVerticesLength; + let world = this.temp = Utils.setArraySize(this.temp, nn, 0); + clip.computeWorldVertices(slot, 0, nn, world, 0, 2); + for (let i2 = 0, n2 = world.length; i2 < n2; i2 += 2) { + let x = world[i2]; + let y = world[i2 + 1]; + let x2 = world[(i2 + 2) % world.length]; + let y2 = world[(i2 + 3) % world.length]; + shapes.line(x, y, x2, y2); + } + } + } + } + dispose() { + } + }; + var SkeletonDebugRenderer = _SkeletonDebugRenderer; + __publicField(SkeletonDebugRenderer, "LIGHT_GRAY", new Color(192 / 255, 192 / 255, 192 / 255, 1)); + __publicField(SkeletonDebugRenderer, "GREEN", new Color(0, 1, 0, 1)); + + // spine-webgl/src/SkeletonRenderer.ts + var Renderable = class { + constructor(vertices, numVertices, numFloats) { + this.vertices = vertices; + this.numVertices = numVertices; + this.numFloats = numFloats; + } + }; + var _SkeletonRenderer = class { + premultipliedAlpha = false; + tempColor = new Color(); + tempColor2 = new Color(); + vertices; + vertexSize = 2 + 2 + 4; + twoColorTint = false; + renderable = new Renderable([], 0, 0); + clipper = new SkeletonClipping(); + temp = new Vector2(); + temp2 = new Vector2(); + temp3 = new Color(); + temp4 = new Color(); + constructor(context, twoColorTint = true) { + this.twoColorTint = twoColorTint; + if (twoColorTint) + this.vertexSize += 4; + this.vertices = Utils.newFloatArray(this.vertexSize * 1024); + } + draw(batcher, skeleton, slotRangeStart = -1, slotRangeEnd = -1, transformer = null) { + let clipper = this.clipper; + let premultipliedAlpha = this.premultipliedAlpha; + let twoColorTint = this.twoColorTint; + let blendMode = null; + let renderable = this.renderable; + let uvs; + let triangles; + let drawOrder = skeleton.drawOrder; + let attachmentColor; + let skeletonColor = skeleton.color; + let vertexSize = twoColorTint ? 12 : 8; + let inRange = false; + if (slotRangeStart == -1) + inRange = true; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize; + let slot = drawOrder[i]; + if (!slot.bone.active) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeStart >= 0 && slotRangeStart == slot.data.index) { + inRange = true; + } + if (!inRange) { + clipper.clipEndWithSlot(slot); + continue; + } + if (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) { + inRange = false; + } + let attachment = slot.getAttachment(); + let texture; + if (attachment instanceof RegionAttachment) { + let region = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = 4; + renderable.numFloats = clippedVertexSize << 2; + region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize); + triangles = _SkeletonRenderer.QUAD_TRIANGLES; + uvs = region.uvs; + texture = region.region.texture; + attachmentColor = region.color; + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + renderable.vertices = this.vertices; + renderable.numVertices = mesh.worldVerticesLength >> 1; + renderable.numFloats = renderable.numVertices * clippedVertexSize; + if (renderable.numFloats > renderable.vertices.length) { + renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats); + } + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize); + triangles = mesh.triangles; + texture = mesh.region.texture; + uvs = mesh.uvs; + attachmentColor = mesh.color; + } else if (attachment instanceof ClippingAttachment) { + let clip = attachment; + clipper.clipStart(slot, clip); + continue; + } else { + clipper.clipEndWithSlot(slot); + continue; + } + if (texture) { + let slotColor = slot.color; + let finalColor = this.tempColor; + finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r; + finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g; + finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b; + finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a; + if (premultipliedAlpha) { + finalColor.r *= finalColor.a; + finalColor.g *= finalColor.a; + finalColor.b *= finalColor.a; + } + let darkColor = this.tempColor2; + if (!slot.darkColor) + darkColor.set(0, 0, 0, 1); + else { + if (premultipliedAlpha) { + darkColor.r = slot.darkColor.r * finalColor.a; + darkColor.g = slot.darkColor.g * finalColor.a; + darkColor.b = slot.darkColor.b * finalColor.a; + } else { + darkColor.setFromColor(slot.darkColor); + } + darkColor.a = premultipliedAlpha ? 1 : 0; + } + let slotBlendMode = slot.data.blendMode; + if (slotBlendMode != blendMode) { + blendMode = slotBlendMode; + batcher.setBlendMode(blendMode, premultipliedAlpha); + } + if (clipper.isClipping()) { + clipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint); + let clippedVertices = new Float32Array(clipper.clippedVertices); + let clippedTriangles = clipper.clippedTriangles; + if (transformer) + transformer(clippedVertices, clippedVertices.length, vertexSize); + batcher.draw(texture, clippedVertices, clippedTriangles); + } else { + let verts = renderable.vertices; + if (!twoColorTint) { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + } + } else { + for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) { + verts[v] = finalColor.r; + verts[v + 1] = finalColor.g; + verts[v + 2] = finalColor.b; + verts[v + 3] = finalColor.a; + verts[v + 4] = uvs[u]; + verts[v + 5] = uvs[u + 1]; + verts[v + 6] = darkColor.r; + verts[v + 7] = darkColor.g; + verts[v + 8] = darkColor.b; + verts[v + 9] = darkColor.a; + } + } + let view = renderable.vertices.subarray(0, renderable.numFloats); + if (transformer) + transformer(renderable.vertices, renderable.numFloats, vertexSize); + batcher.draw(texture, view, triangles); + } + } + clipper.clipEndWithSlot(slot); + } + clipper.clipEnd(); + } + /** Returns the {@link SkeletonClipping} used by this renderer for use with e.g. {@link Skeleton.getBounds} **/ + getSkeletonClipping() { + return this.clipper; + } + }; + var SkeletonRenderer = _SkeletonRenderer; + __publicField(SkeletonRenderer, "QUAD_TRIANGLES", [0, 1, 2, 2, 3, 0]); + + // spine-webgl/src/SceneRenderer.ts + var quad = [ + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0 + ]; + var QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0]; + var WHITE = new Color(1, 1, 1, 1); + var SceneRenderer = class { + context; + canvas; + camera; + batcher; + twoColorTint = false; + batcherShader; + shapes; + shapesShader; + activeRenderer = null; + skeletonRenderer; + skeletonDebugRenderer; + constructor(canvas, context, twoColorTint = true) { + this.canvas = canvas; + this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); + this.twoColorTint = twoColorTint; + this.camera = new OrthoCamera(canvas.width, canvas.height); + this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context); + this.batcher = new PolygonBatcher(this.context, twoColorTint); + this.shapesShader = Shader.newColored(this.context); + this.shapes = new ShapeRenderer(this.context); + this.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint); + this.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context); + } + dispose() { + this.batcher.dispose(); + this.batcherShader.dispose(); + this.shapes.dispose(); + this.shapesShader.dispose(); + this.skeletonDebugRenderer.dispose(); + } + begin() { + this.camera.update(); + this.enableRenderer(this.batcher); + } + drawSkeleton(skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform = null) { + this.enableRenderer(this.batcher); + this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform); + } + drawSkeletonDebug(skeleton, premultipliedAlpha = false, ignoredBones) { + this.enableRenderer(this.shapes); + this.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha; + this.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones); + } + drawTexture(texture, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureUV(texture, x, y, width, height, u, v, u2, v2, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u2; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = u; + quad[i++] = v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawTextureRotated(texture, x, y, width, height, pivotX, pivotY, angle, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + let worldOriginX = x + pivotX; + let worldOriginY = y + pivotY; + let fx = -pivotX; + let fy = -pivotY; + let fx2 = width - pivotX; + let fy2 = height - pivotY; + let p1x = fx; + let p1y = fy; + let p2x = fx; + let p2y = fy2; + let p3x = fx2; + let p3y = fy2; + let p4x = fx2; + let p4y = fy; + let x1 = 0; + let y1 = 0; + let x2 = 0; + let y2 = 0; + let x3 = 0; + let y3 = 0; + let x4 = 0; + let y4 = 0; + if (angle != 0) { + let cos = MathUtils.cosDeg(angle); + let sin = MathUtils.sinDeg(angle); + x1 = cos * p1x - sin * p1y; + y1 = sin * p1x + cos * p1y; + x4 = cos * p2x - sin * p2y; + y4 = sin * p2x + cos * p2y; + x3 = cos * p3x - sin * p3y; + y3 = sin * p3x + cos * p3y; + x2 = x3 + (x1 - x4); + y2 = y3 + (y1 - y4); + } else { + x1 = p1x; + y1 = p1y; + x4 = p2x; + y4 = p2y; + x3 = p3x; + y3 = p3y; + x2 = p4x; + y2 = p4y; + } + x1 += worldOriginX; + y1 += worldOriginY; + x2 += worldOriginX; + y2 += worldOriginY; + x3 += worldOriginX; + y3 += worldOriginY; + x4 += worldOriginX; + y4 += worldOriginY; + var i = 0; + quad[i++] = x1; + quad[i++] = y1; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x2; + quad[i++] = y2; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 1; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x3; + quad[i++] = y3; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 1; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x4; + quad[i++] = y4; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = 0; + quad[i++] = 0; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(texture, quad, QUAD_TRIANGLES); + } + drawRegion(region, x, y, width, height, color) { + this.enableRenderer(this.batcher); + if (!color) + color = WHITE; + var i = 0; + quad[i++] = x; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v2; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x + width; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u2; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + } + quad[i++] = x; + quad[i++] = y + height; + quad[i++] = color.r; + quad[i++] = color.g; + quad[i++] = color.b; + quad[i++] = color.a; + quad[i++] = region.u; + quad[i++] = region.v; + if (this.twoColorTint) { + quad[i++] = 0; + quad[i++] = 0; + quad[i++] = 0; + quad[i] = 0; + } + this.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES); + } + line(x, y, x2, y2, color, color2) { + this.enableRenderer(this.shapes); + this.shapes.line(x, y, x2, y2, color); + } + triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) { + this.enableRenderer(this.shapes); + this.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3); + } + quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) { + this.enableRenderer(this.shapes); + this.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4); + } + rect(filled, x, y, width, height, color) { + this.enableRenderer(this.shapes); + this.shapes.rect(filled, x, y, width, height, color); + } + rectLine(filled, x1, y1, x2, y2, width, color) { + this.enableRenderer(this.shapes); + this.shapes.rectLine(filled, x1, y1, x2, y2, width, color); + } + polygon(polygonVertices, offset, count, color) { + this.enableRenderer(this.shapes); + this.shapes.polygon(polygonVertices, offset, count, color); + } + circle(filled, x, y, radius, color, segments = 0) { + this.enableRenderer(this.shapes); + this.shapes.circle(filled, x, y, radius, color, segments); + } + curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) { + this.enableRenderer(this.shapes); + this.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color); + } + end() { + if (this.activeRenderer === this.batcher) + this.batcher.end(); + else if (this.activeRenderer === this.shapes) + this.shapes.end(); + this.activeRenderer = null; + } + resize(resizeMode) { + let canvas = this.canvas; + var dpr = window.devicePixelRatio || 1; + var w = Math.round(canvas.clientWidth * dpr); + var h = Math.round(canvas.clientHeight * dpr); + if (canvas.width != w || canvas.height != h) { + canvas.width = w; + canvas.height = h; + } + this.context.gl.viewport(0, 0, canvas.width, canvas.height); + if (resizeMode === ResizeMode.Expand) + this.camera.setViewport(w, h); + else if (resizeMode === ResizeMode.Fit) { + let sourceWidth = canvas.width, sourceHeight = canvas.height; + let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight; + let targetRatio = targetHeight / targetWidth; + let sourceRatio = sourceHeight / sourceWidth; + let scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight; + this.camera.setViewport(sourceWidth * scale, sourceHeight * scale); + } + this.camera.update(); + } + enableRenderer(renderer) { + if (this.activeRenderer === renderer) + return; + this.end(); + if (renderer instanceof PolygonBatcher) { + this.batcherShader.bind(); + this.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.batcherShader.setUniformi("u_texture", 0); + this.batcher.begin(this.batcherShader); + this.activeRenderer = this.batcher; + } else if (renderer instanceof ShapeRenderer) { + this.shapesShader.bind(); + this.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values); + this.shapes.begin(this.shapesShader); + this.activeRenderer = this.shapes; + } else + this.activeRenderer = this.skeletonDebugRenderer; + } + }; + var ResizeMode = /* @__PURE__ */ ((ResizeMode2) => { + ResizeMode2[ResizeMode2["Stretch"] = 0] = "Stretch"; + ResizeMode2[ResizeMode2["Expand"] = 1] = "Expand"; + ResizeMode2[ResizeMode2["Fit"] = 2] = "Fit"; + return ResizeMode2; + })(ResizeMode || {}); + + // spine-webgl/src/LoadingScreen.ts + var spinnerImage; + var logoImage; + var loaded = 0; + var FADE_IN = 1; + var FADE_OUT = 1; + var logoWidth = 165; + var logoHeight = 108; + var spinnerSize = 163; + var LoadingScreen = class { + renderer; + logo = null; + spinner = null; + angle = 0; + fadeOut = 0; + fadeIn = 0; + timeKeeper = new TimeKeeper(); + backgroundColor = new Color(0.135, 0.135, 0.135, 1); + tempColor = new Color(); + constructor(renderer) { + this.renderer = renderer; + this.timeKeeper.maxDelta = 9; + if (!logoImage) { + let isSafari = navigator.userAgent.indexOf("Safari") > -1; + let onload = () => loaded++; + logoImage = new Image(); + logoImage.src = SPINE_LOGO_DATA; + if (!isSafari) + logoImage.crossOrigin = "anonymous"; + logoImage.onload = onload; + spinnerImage = new Image(); + spinnerImage.src = SPINNER_DATA; + if (!isSafari) + spinnerImage.crossOrigin = "anonymous"; + spinnerImage.onload = onload; + } + } + dispose() { + this.logo?.dispose(); + this.spinner?.dispose(); + } + draw(complete = false) { + if (loaded < 2 || complete && this.fadeOut > FADE_OUT) + return; + this.timeKeeper.update(); + let a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25)); + this.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5)); + let tempColor = this.tempColor; + let renderer = this.renderer; + let canvas = renderer.canvas; + let gl = renderer.context.gl; + renderer.resize(1 /* Expand */); + renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0); + renderer.batcher.setBlendMode(0 /* Normal */, true); + if (complete) { + this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1); + if (this.fadeOut > FADE_OUT) + return; + tempColor.setFromColor(this.backgroundColor); + a = 1 - this.fadeOut / FADE_OUT; + a = 1 - (a - 1) * (a - 1); + tempColor.a *= a; + if (tempColor.a > 0) { + renderer.camera.zoom = 1; + renderer.begin(); + renderer.quad( + true, + 0, + 0, + canvas.width, + 0, + canvas.width, + canvas.height, + 0, + canvas.height, + tempColor, + tempColor, + tempColor, + tempColor + ); + renderer.end(); + } + } else { + this.fadeIn += this.timeKeeper.delta; + if (this.backgroundColor.a > 0) { + gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a); + gl.clear(gl.COLOR_BUFFER_BIT); + } + a = 1; + } + a *= Math.min(this.fadeIn / FADE_IN, 1); + tempColor.set(a, a, a, a); + if (!this.logo) { + this.logo = new GLTexture(renderer.context, logoImage); + this.spinner = new GLTexture(renderer.context, spinnerImage); + } + renderer.camera.zoom = Math.max(1, spinnerSize / canvas.height); + renderer.begin(); + renderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor); + if (this.spinner) + renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor); + renderer.end(); + } + }; + var SPINNER_DATA = "data:image/png;base64,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"; + var SPINE_LOGO_DATA = "data:image/png;base64,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"; + + // spine-webgl/src/SpineCanvas.ts + var SpineCanvas = class { + /** Constructs a new spine canvas, rendering to the provided HTML canvas. */ + constructor(canvas, config) { + this.config = config; + if (!config.pathPrefix) + config.pathPrefix = ""; + if (!config.app) + config.app = { + loadAssets: () => { + }, + initialize: () => { + }, + update: () => { + }, + render: () => { + }, + error: () => { + }, + dispose: () => { + } + }; + if (!config.webglConfig) + config.webglConfig = { alpha: true }; + this.htmlCanvas = canvas; + this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig); + this.renderer = new SceneRenderer(canvas, this.context); + this.gl = this.context.gl; + this.assetManager = new AssetManager(this.context, config.pathPrefix); + this.input = new Input(canvas); + if (config.app.loadAssets) + config.app.loadAssets(this); + let loop = () => { + if (this.disposed) + return; + requestAnimationFrame(loop); + this.time.update(); + if (config.app.update) + config.app.update(this, this.time.delta); + if (config.app.render) + config.app.render(this); + }; + let waitForAssets = () => { + if (this.disposed) + return; + if (this.assetManager.isLoadingComplete()) { + if (this.assetManager.hasErrors()) { + if (config.app.error) + config.app.error(this, this.assetManager.getErrors()); + } else { + if (config.app.initialize) + config.app.initialize(this); + loop(); + } + return; + } + requestAnimationFrame(waitForAssets); + }; + requestAnimationFrame(waitForAssets); + } + context; + /** Tracks the current time, delta, and other time related statistics. */ + time = new TimeKeeper(); + /** The HTML canvas to render to. */ + htmlCanvas; + /** The WebGL rendering context. */ + gl; + /** The scene renderer for easy drawing of skeletons, shapes, and images. */ + renderer; + /** The asset manager to load assets with. */ + assetManager; + /** The input processor used to listen to mouse, touch, and keyboard events. */ + input; + disposed = false; + /** Clears the canvas with the given color. The color values are given in the range [0,1]. */ + clear(r, g, b, a) { + this.gl.clearColor(r, g, b, a); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); + } + /** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/ + dispose() { + if (this.config.app.dispose) + this.config.app.dispose(this); + this.disposed = true; + } + }; + + // spine-phaser-v3/src/mixins.ts + var components = Phaser.GameObjects.Components; + var ComputedSize = components.ComputedSize; + var Depth = components.Depth; + var Flip = components.Flip; + var ScrollFactor = components.ScrollFactor; + var Transform = components.Transform; + var Visible = components.Visible; + var Origin = components.Origin; + var Alpha = components.Alpha; + function createMixin(...component) { + return (BaseGameObject) => { + Phaser.Class.mixin(BaseGameObject, component); + return BaseGameObject; + }; + } + var ComputedSizeMixin = createMixin(ComputedSize); + var DepthMixin = createMixin(Depth); + var FlipMixin = createMixin(Flip); + var ScrollFactorMixin = createMixin(ScrollFactor); + var TransformMixin = createMixin(Transform); + var VisibleMixin = createMixin(Visible); + var OriginMixin = createMixin(Origin); + var AlphaMixin = createMixin(Alpha); + + // spine-phaser-v3/src/SpineGameObject.ts + var BaseSpineGameObject = class extends Phaser.GameObjects.GameObject { + constructor(scene, type) { + super(scene, type); + } + }; + var SetupPoseBoundsProvider = class { + /** + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(clipping = false) { + this.clipping = clipping; + } + calculateBounds(gameObject) { + if (!gameObject.skeleton) + return { x: 0, y: 0, width: 0, height: 0 }; + const skeleton = new Skeleton(gameObject.skeleton.data); + skeleton.setToSetupPose(); + skeleton.updateWorldTransform(2 /* update */); + const bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : void 0); + return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; + } + }; + var SkinsAndAnimationBoundsProvider = class { + /** + * @param animation The animation to use for calculating the bounds. If null, the setup pose is used. + * @param skins The skins to use for calculating the bounds. If empty, the default skin is used. + * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation. + * @param clipping If true, clipping attachments are used to compute the bounds. False, by default. + */ + constructor(animation, skins = [], timeStep = 0.05, clipping = false) { + this.animation = animation; + this.skins = skins; + this.timeStep = timeStep; + this.clipping = clipping; + } + calculateBounds(gameObject) { + if (!gameObject.skeleton || !gameObject.animationState) + return { x: 0, y: 0, width: 0, height: 0 }; + const animationState = new AnimationState(gameObject.animationState.data); + const skeleton = new Skeleton(gameObject.skeleton.data); + const clipper = this.clipping ? new SkeletonClipping() : void 0; + const data = skeleton.data; + if (this.skins.length > 0) { + let customSkin = new Skin("custom-skin"); + for (const skinName of this.skins) { + const skin = data.findSkin(skinName); + if (skin == null) + continue; + customSkin.addSkin(skin); + } + skeleton.setSkin(customSkin); + } + skeleton.setToSetupPose(); + const animation = this.animation != null ? data.findAnimation(this.animation) : null; + if (animation == null) { + skeleton.updateWorldTransform(2 /* update */); + const bounds = skeleton.getBoundsRect(clipper); + return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; + } else { + let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY; + animationState.clearTracks(); + animationState.setAnimationWith(0, animation, false); + const steps = Math.max(animation.duration / this.timeStep, 1); + for (let i = 0; i < steps; i++) { + const delta = i > 0 ? this.timeStep : 0; + animationState.update(delta); + animationState.apply(skeleton); + skeleton.update(delta); + skeleton.updateWorldTransform(2 /* update */); + const bounds2 = skeleton.getBoundsRect(clipper); + minX = Math.min(minX, bounds2.x); + minY = Math.min(minY, bounds2.y); + maxX = Math.max(maxX, bounds2.x + bounds2.width); + maxY = Math.max(maxY, bounds2.y + bounds2.height); + } + const bounds = { + x: minX, + y: minY, + width: maxX - minX, + height: maxY - minY + }; + return bounds.width == Number.NEGATIVE_INFINITY ? { x: 0, y: 0, width: 0, height: 0 } : bounds; + } + } + }; + var SpineGameObject = class extends DepthMixin( + OriginMixin( + ComputedSizeMixin( + FlipMixin( + ScrollFactorMixin( + TransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject))) + ) + ) + ) + ) + ) { + constructor(scene, plugin, x, y, dataKey, atlasKey, boundsProvider = new SetupPoseBoundsProvider()) { + super(scene, window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE); + this.plugin = plugin; + this.boundsProvider = boundsProvider; + this.setPosition(x, y); + this.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey); + this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey); + this.animationStateData = new AnimationStateData(this.skeleton.data); + this.animationState = new AnimationState(this.animationStateData); + this.skeleton.updateWorldTransform(2 /* update */); + this.updateSize(); + } + blendMode = -1; + skeleton; + animationStateData; + animationState; + beforeUpdateWorldTransforms = () => { + }; + afterUpdateWorldTransforms = () => { + }; + premultipliedAlpha = false; + updateSize() { + if (!this.skeleton) + return; + let bounds = this.boundsProvider.calculateBounds(this); + let self = this; + self.width = bounds.width; + self.height = bounds.height; + this.displayOriginX = -bounds.x; + this.displayOriginY = -bounds.y; + } + /** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */ + skeletonToPhaserWorldCoordinates(point) { + let transform = this.getWorldTransformMatrix(); + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + let x = point.x; + let y = point.y; + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + } + /** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */ + phaserWorldCoordinatesToSkeleton(point) { + let transform = this.getWorldTransformMatrix(); + transform = transform.invert(); + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + let x = point.x; + let y = point.y; + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + } + /** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */ + phaserWorldCoordinatesToBone(point, bone) { + this.phaserWorldCoordinatesToSkeleton(point); + if (bone.parent) { + bone.parent.worldToLocal(point); + } else { + bone.worldToLocal(point); + } + } + /** + * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones. + * @param delta The time delta in milliseconds + */ + updatePose(delta) { + this.animationState.update(delta / 1e3); + this.animationState.apply(this.skeleton); + this.beforeUpdateWorldTransforms(this); + this.skeleton.update(delta / 1e3); + this.skeleton.updateWorldTransform(2 /* update */); + this.afterUpdateWorldTransforms(this); + } + preUpdate(time, delta) { + if (!this.skeleton || !this.animationState) + return; + this.updatePose(delta); + } + preDestroy() { + } + willRender(camera) { + var GameObjectRenderMask = 15; + var result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || this.cameraFilter !== 0 && this.cameraFilter & camera.id); + if (!this.visible) + result = false; + if (!result && this.parentContainer && this.plugin.webGLRenderer) { + var sceneRenderer = this.plugin.webGLRenderer; + if (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) { + sceneRenderer.end(); + this.plugin.phaserRenderer.pipelines.rebind(); + } + } + return result; + } + renderWebGL(renderer, src, camera, parentMatrix) { + if (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer) + return; + let sceneRenderer = this.plugin.webGLRenderer; + if (renderer.newType) { + renderer.pipelines.clear(); + sceneRenderer.begin(); + } + camera.addToRenderList(src); + let transform = Phaser.GameObjects.GetCalcMatrix( + src, + camera, + parentMatrix + ).calc; + let a = transform.a, b = transform.b, c = transform.c, d = transform.d, tx = transform.tx, ty = transform.ty; + sceneRenderer.drawSkeleton( + this.skeleton, + this.premultipliedAlpha, + -1, + -1, + (vertices, numVertices, stride) => { + for (let i = 0; i < numVertices; i += stride) { + let vx = vertices[i]; + let vy = vertices[i + 1]; + vertices[i] = vx * a + vy * c + tx; + vertices[i + 1] = vx * b + vy * d + ty; + } + } + ); + if (!renderer.nextTypeMatch) { + sceneRenderer.end(); + renderer.pipelines.rebind(); + } + } + renderCanvas(renderer, src, camera, parentMatrix) { + if (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer) + return; + let context = renderer.currentContext; + let skeletonRenderer = this.plugin.canvasRenderer; + skeletonRenderer.ctx = context; + camera.addToRenderList(src); + let transform = Phaser.GameObjects.GetCalcMatrix( + src, + camera, + parentMatrix + ).calc; + let skeleton = this.skeleton; + skeleton.x = transform.tx; + skeleton.y = transform.ty; + skeleton.scaleX = transform.scaleX; + skeleton.scaleY = transform.scaleY; + let root = skeleton.getRootBone(); + root.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized; + this.skeleton.updateWorldTransform(2 /* update */); + context.save(); + skeletonRenderer.draw(skeleton); + context.restore(); + } + }; + + // spine-canvas/src/CanvasTexture.ts + var CanvasTexture = class extends Texture { + constructor(image) { + super(image); + } + setFilters(minFilter, magFilter) { + } + setWraps(uWrap, vWrap) { + } + dispose() { + } + }; + + // spine-canvas/src/SkeletonRenderer.ts + var worldVertices = Utils.newFloatArray(8); + var _SkeletonRenderer2 = class { + ctx; + triangleRendering = false; + debugRendering = false; + vertices = Utils.newFloatArray(8 * 1024); + tempColor = new Color(); + constructor(context) { + this.ctx = context; + } + draw(skeleton) { + if (this.triangleRendering) + this.drawTriangles(skeleton); + else + this.drawImages(skeleton); + } + drawImages(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + if (this.debugRendering) + ctx.strokeStyle = "green"; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let bone = slot.bone; + if (!bone.active) + continue; + let attachment = slot.getAttachment(); + if (!(attachment instanceof RegionAttachment)) + continue; + attachment.computeWorldVertices(slot, worldVertices, 0, 2); + let region = attachment.region; + let image = region.texture.getImage(); + let slotColor = slot.color; + let regionColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * regionColor.r, + skeletonColor.g * slotColor.g * regionColor.g, + skeletonColor.b * slotColor.b * regionColor.b, + skeletonColor.a * slotColor.a * regionColor.a + ); + ctx.save(); + ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY); + ctx.translate(attachment.offset[0], attachment.offset[1]); + ctx.rotate(attachment.rotation * Math.PI / 180); + let atlasScale = attachment.width / region.originalWidth; + ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY); + let w = region.width, h = region.height; + ctx.translate(w / 2, h / 2); + if (attachment.region.degrees == 90) { + let t = w; + w = h; + h = t; + ctx.rotate(-Math.PI / 2); + } + ctx.scale(1, -1); + ctx.translate(-w / 2, -h / 2); + ctx.globalAlpha = color.a; + ctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h); + if (this.debugRendering) + ctx.strokeRect(0, 0, w, h); + ctx.restore(); + } + } + drawTriangles(skeleton) { + let ctx = this.ctx; + let color = this.tempColor; + let skeletonColor = skeleton.color; + let drawOrder = skeleton.drawOrder; + let blendMode = null; + let vertices = this.vertices; + let triangles = null; + for (let i = 0, n = drawOrder.length; i < n; i++) { + let slot = drawOrder[i]; + let attachment = slot.getAttachment(); + let texture; + let region; + if (attachment instanceof RegionAttachment) { + let regionAttachment = attachment; + vertices = this.computeRegionVertices(slot, regionAttachment, false); + triangles = _SkeletonRenderer2.QUAD_TRIANGLES; + texture = regionAttachment.region.texture.getImage(); + } else if (attachment instanceof MeshAttachment) { + let mesh = attachment; + vertices = this.computeMeshVertices(slot, mesh, false); + triangles = mesh.triangles; + texture = mesh.region.texture.getImage(); + } else + continue; + if (texture) { + if (slot.data.blendMode != blendMode) + blendMode = slot.data.blendMode; + let slotColor = slot.color; + let attachmentColor = attachment.color; + color.set( + skeletonColor.r * slotColor.r * attachmentColor.r, + skeletonColor.g * slotColor.g * attachmentColor.g, + skeletonColor.b * slotColor.b * attachmentColor.b, + skeletonColor.a * slotColor.a * attachmentColor.a + ); + ctx.globalAlpha = color.a; + for (var j = 0; j < triangles.length; j += 3) { + let t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8; + let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7]; + let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7]; + let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7]; + this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2); + if (this.debugRendering) { + ctx.strokeStyle = "green"; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x0, y0); + ctx.stroke(); + } + } + } + } + this.ctx.globalAlpha = 1; + } + // Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120 + // Apache 2 licensed + drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) { + let ctx = this.ctx; + const width = img.width - 1; + const height = img.height - 1; + u0 *= width; + v0 *= height; + u1 *= width; + v1 *= height; + u2 *= width; + v2 *= height; + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.closePath(); + x1 -= x0; + y1 -= y0; + x2 -= x0; + y2 -= y0; + u1 -= u0; + v1 -= v0; + u2 -= u0; + v2 -= v0; + let det = u1 * v2 - u2 * v1; + if (det == 0) + return; + det = 1 / det; + const a = (v2 * x1 - v1 * x2) * det; + const b = (v2 * y1 - v1 * y2) * det; + const c = (u1 * x2 - u2 * x1) * det; + const d = (u1 * y2 - u2 * y1) * det; + const e = x0 - a * u0 - c * v0; + const f = y0 - b * u0 - d * v0; + ctx.save(); + ctx.transform(a, b, c, d, e, f); + ctx.clip(); + ctx.drawImage(img, 0, 0); + ctx.restore(); + } + computeRegionVertices(slot, region, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = region.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let color = this.tempColor; + color.set( + skeletonColor.r * slotColor.r * regionColor.r * multiplier, + skeletonColor.g * slotColor.g * regionColor.g * multiplier, + skeletonColor.b * slotColor.b * regionColor.b * multiplier, + alpha + ); + region.computeWorldVertices(slot, this.vertices, 0, _SkeletonRenderer2.VERTEX_SIZE); + let vertices = this.vertices; + let uvs = region.uvs; + vertices[RegionAttachment.C1R] = color.r; + vertices[RegionAttachment.C1G] = color.g; + vertices[RegionAttachment.C1B] = color.b; + vertices[RegionAttachment.C1A] = color.a; + vertices[RegionAttachment.U1] = uvs[0]; + vertices[RegionAttachment.V1] = uvs[1]; + vertices[RegionAttachment.C2R] = color.r; + vertices[RegionAttachment.C2G] = color.g; + vertices[RegionAttachment.C2B] = color.b; + vertices[RegionAttachment.C2A] = color.a; + vertices[RegionAttachment.U2] = uvs[2]; + vertices[RegionAttachment.V2] = uvs[3]; + vertices[RegionAttachment.C3R] = color.r; + vertices[RegionAttachment.C3G] = color.g; + vertices[RegionAttachment.C3B] = color.b; + vertices[RegionAttachment.C3A] = color.a; + vertices[RegionAttachment.U3] = uvs[4]; + vertices[RegionAttachment.V3] = uvs[5]; + vertices[RegionAttachment.C4R] = color.r; + vertices[RegionAttachment.C4G] = color.g; + vertices[RegionAttachment.C4B] = color.b; + vertices[RegionAttachment.C4A] = color.a; + vertices[RegionAttachment.U4] = uvs[6]; + vertices[RegionAttachment.V4] = uvs[7]; + return vertices; + } + computeMeshVertices(slot, mesh, pma) { + let skeletonColor = slot.bone.skeleton.color; + let slotColor = slot.color; + let regionColor = mesh.color; + let alpha = skeletonColor.a * slotColor.a * regionColor.a; + let multiplier = pma ? alpha : 1; + let color = this.tempColor; + color.set( + skeletonColor.r * slotColor.r * regionColor.r * multiplier, + skeletonColor.g * slotColor.g * regionColor.g * multiplier, + skeletonColor.b * slotColor.b * regionColor.b * multiplier, + alpha + ); + let vertexCount = mesh.worldVerticesLength / 2; + let vertices = this.vertices; + if (vertices.length < mesh.worldVerticesLength) + this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength); + mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, _SkeletonRenderer2.VERTEX_SIZE); + let uvs = mesh.uvs; + for (let i = 0, u = 0, v = 2; i < vertexCount; i++) { + vertices[v++] = color.r; + vertices[v++] = color.g; + vertices[v++] = color.b; + vertices[v++] = color.a; + vertices[v++] = uvs[u++]; + vertices[v++] = uvs[u++]; + v += 2; + } + return vertices; + } + }; + var SkeletonRenderer2 = _SkeletonRenderer2; + __publicField(SkeletonRenderer2, "QUAD_TRIANGLES", [0, 1, 2, 2, 3, 0]); + __publicField(SkeletonRenderer2, "VERTEX_SIZE", 2 + 2 + 4); + + // spine-phaser-v3/src/SpinePlugin.ts + var _SpinePlugin = class extends Phaser2.Plugins.ScenePlugin { + game; + isWebGL; + gl; + get webGLRenderer() { + return _SpinePlugin.gameWebGLRenderer; + } + canvasRenderer; + phaserRenderer; + skeletonDataCache; + atlasCache; + constructor(scene, pluginManager, pluginKey) { + super(scene, pluginManager, pluginKey); + this.game = pluginManager.game; + this.isWebGL = this.game.config.renderType === 2; + this.gl = this.isWebGL ? this.game.renderer.gl : null; + this.phaserRenderer = this.game.renderer; + this.canvasRenderer = null; + this.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_FILE_CACHE_KEY); + this.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY); + let skeletonJsonFileCallback = function(key, url, xhrSettings) { + let file = new SpineSkeletonDataFile(this, key, url, SpineSkeletonDataFileType.json, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineJson", skeletonJsonFileCallback, scene); + let skeletonBinaryFileCallback = function(key, url, xhrSettings) { + let file = new SpineSkeletonDataFile(this, key, url, SpineSkeletonDataFileType.binary, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineBinary", skeletonBinaryFileCallback, scene); + let atlasFileCallback = function(key, url, premultipliedAlpha, xhrSettings) { + let file = new SpineAtlasFile(this, key, url, premultipliedAlpha, xhrSettings); + this.addFile(file.files); + return this; + }; + pluginManager.registerFileType("spineAtlas", atlasFileCallback, scene); + let addSpineGameObject = function(x, y, dataKey, atlasKey, boundsProvider) { + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + const spinePlugin = this.scene.sys[pluginKey]; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, dataKey, atlasKey, boundsProvider); + this.displayList.add(gameObject); + this.updateList.add(gameObject); + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return gameObject; + }; + let makeSpineGameObject = function(config, addToScene = false) { + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.clear(); + } + let x = config.x ? config.x : 0; + let y = config.y ? config.y : 0; + let boundsProvider = config.boundsProvider ? config.boundsProvider : void 0; + const spinePlugin = this.scene.sys[pluginKey]; + let gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, config.dataKey, config.atlasKey, boundsProvider); + if (addToScene !== void 0) { + config.add = addToScene; + } + if (this.scene.sys.renderer instanceof Phaser2.Renderer.WebGL.WebGLRenderer) { + this.scene.sys.renderer.pipelines.rebind(); + } + return Phaser2.GameObjects.BuildGameObject(this.scene, gameObject, config); + }; + pluginManager.registerGameObject(window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject); + } + boot() { + Skeleton.yDown = true; + if (this.isWebGL) { + if (!_SpinePlugin.gameWebGLRenderer) { + _SpinePlugin.gameWebGLRenderer = new SceneRenderer(this.game.renderer.canvas, this.gl, true); + } + this.onResize(); + this.game.scale.on(Phaser2.Scale.Events.RESIZE, this.onResize, this); + } else { + if (!this.canvasRenderer) { + this.canvasRenderer = new SkeletonRenderer2(this.scene.sys.context); + } + } + var eventEmitter = this.systems.events; + eventEmitter.once("shutdown", this.shutdown, this); + eventEmitter.once("destroy", this.destroy, this); + this.game.events.once("destroy", this.gameDestroy, this); + } + onResize() { + var phaserRenderer = this.game.renderer; + var sceneRenderer = this.webGLRenderer; + if (phaserRenderer && sceneRenderer) { + var viewportWidth = phaserRenderer.width; + var viewportHeight = phaserRenderer.height; + sceneRenderer.camera.position.x = viewportWidth / 2; + sceneRenderer.camera.position.y = viewportHeight / 2; + sceneRenderer.camera.up.y = -1; + sceneRenderer.camera.direction.z = 1; + sceneRenderer.camera.setViewport(viewportWidth, viewportHeight); + } + } + shutdown() { + this.systems.events.off("shutdown", this.shutdown, this); + if (this.isWebGL) { + this.game.scale.off(Phaser2.Scale.Events.RESIZE, this.onResize, this); + } + } + destroy() { + this.shutdown(); + } + gameDestroy() { + this.pluginManager.removeGameObject(window.SPINE_GAME_OBJECT_TYPE ? window.SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, true, true); + if (this.webGLRenderer) + this.webGLRenderer.dispose(); + _SpinePlugin.gameWebGLRenderer = null; + } + /** Returns the TextureAtlas instance for the given key */ + getAtlas(atlasKey) { + let atlas; + if (this.atlasCache.exists(atlasKey)) { + atlas = this.atlasCache.get(atlasKey); + } else { + let atlasFile = this.game.cache.text.get(atlasKey); + atlas = new TextureAtlas(atlasFile.data); + if (this.isWebGL) { + let gl = this.gl; + const phaserUnpackPmaValue = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL); + if (phaserUnpackPmaValue) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + for (let atlasPage of atlas.pages) { + atlasPage.setTexture(new GLTexture(gl, this.game.textures.get(atlasKey + "!" + atlasPage.name).getSourceImage(), false)); + } + if (phaserUnpackPmaValue) + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + } else { + for (let atlasPage of atlas.pages) { + atlasPage.setTexture(new CanvasTexture(this.game.textures.get(atlasKey + "!" + atlasPage.name).getSourceImage())); + } + } + this.atlasCache.add(atlasKey, atlas); + } + return atlas; + } + /** Returns whether the TextureAtlas uses premultiplied alpha */ + isAtlasPremultiplied(atlasKey) { + let atlasFile = this.game.cache.text.get(atlasKey); + if (!atlasFile) + return false; + return atlasFile.premultipliedAlpha; + } + /** Returns the SkeletonData instance for the given data and atlas key */ + getSkeletonData(dataKey, atlasKey) { + const atlas = this.getAtlas(atlasKey); + const combinedKey = dataKey + atlasKey; + let skeletonData; + if (this.skeletonDataCache.exists(combinedKey)) { + skeletonData = this.skeletonDataCache.get(combinedKey); + } else { + if (this.game.cache.json.exists(dataKey)) { + let jsonFile = this.game.cache.json.get(dataKey); + let json = new SkeletonJson(new AtlasAttachmentLoader(atlas)); + skeletonData = json.readSkeletonData(jsonFile); + } else { + let binaryFile = this.game.cache.binary.get(dataKey); + let binary = new SkeletonBinary(new AtlasAttachmentLoader(atlas)); + skeletonData = binary.readSkeletonData(new Uint8Array(binaryFile)); + } + this.skeletonDataCache.add(combinedKey, skeletonData); + } + return skeletonData; + } + /** Creates a new Skeleton instance from the data and atlas. */ + createSkeleton(dataKey, atlasKey) { + return new Skeleton(this.getSkeletonData(dataKey, atlasKey)); + } + }; + var SpinePlugin = _SpinePlugin; + __publicField(SpinePlugin, "gameWebGLRenderer", null); + __publicField(SpinePlugin, "rendererId", 0); + var SpineSkeletonDataFileType = /* @__PURE__ */ ((SpineSkeletonDataFileType2) => { + SpineSkeletonDataFileType2[SpineSkeletonDataFileType2["json"] = 0] = "json"; + SpineSkeletonDataFileType2[SpineSkeletonDataFileType2["binary"] = 1] = "binary"; + return SpineSkeletonDataFileType2; + })(SpineSkeletonDataFileType || {}); + var SpineSkeletonDataFile = class extends Phaser2.Loader.MultiFile { + constructor(loader, key, url, fileType, xhrSettings) { + if (typeof key !== "string") { + const config = key; + key = config.key; + url = config.url; + fileType = config.type === "spineJson" ? 0 /* json */ : 1 /* binary */; + xhrSettings = config.xhrSettings; + } + let file = null; + let isJson = fileType == 0 /* json */; + if (isJson) { + file = new Phaser2.Loader.FileTypes.JSONFile(loader, { + key, + url, + extension: "json", + xhrSettings + }); + } else { + file = new Phaser2.Loader.FileTypes.BinaryFile(loader, { + key, + url, + extension: "skel", + xhrSettings + }); + } + super(loader, SPINE_SKELETON_DATA_FILE_TYPE, key, [file]); + this.fileType = fileType; + } + onFileComplete(file) { + this.pending--; + } + addToCache() { + if (this.isReadyToProcess()) + this.files[0].addToCache(); + } + }; + var SpineAtlasFile = class extends Phaser2.Loader.MultiFile { + constructor(loader, key, url, premultipliedAlpha, xhrSettings) { + if (typeof key !== "string") { + const config = key; + key = config.key; + url = config.url; + premultipliedAlpha = config.premultipliedAlpha; + xhrSettings = config.xhrSettings; + } + super(loader, SPINE_ATLAS_FILE_TYPE, key, [ + new Phaser2.Loader.FileTypes.TextFile(loader, { + key, + url, + xhrSettings, + extension: "atlas" + }) + ]); + this.premultipliedAlpha = premultipliedAlpha; + } + onFileComplete(file) { + if (this.files.indexOf(file) != -1) { + this.pending--; + if (file.type == "text") { + var lines = file.data.split(/\r\n|\r|\n/); + let textures = []; + textures.push(lines[0]); + for (var t = 1; t < lines.length; t++) { + var line = lines[t]; + if (line.trim() === "" && t < lines.length - 1) { + line = lines[t + 1]; + textures.push(line); + } + } + let basePath = file.src.match(/^.*\//) ?? ""; + for (var i = 0; i < textures.length; i++) { + var url = basePath + textures[i]; + var key = file.key + "!" + textures[i]; + var image = new Phaser2.Loader.FileTypes.ImageFile(this.loader, key, url); + if (!this.loader.keyExists(image)) { + this.addToMultiFile(image); + this.loader.addFile(image); + } + } + } + } + } + addToCache() { + if (this.isReadyToProcess()) { + let textureManager = this.loader.textureManager; + for (let file of this.files) { + if (file.type == "image") { + if (!textureManager.exists(file.key)) { + textureManager.addImage(file.key, file.data); + } + } else { + this.premultipliedAlpha = this.premultipliedAlpha ?? (file.data.indexOf("pma: true") >= 0 || file.data.indexOf("pma:true") >= 0); + file.data = { + data: file.data, + premultipliedAlpha: this.premultipliedAlpha + }; + file.addToCache(); + } + } + } + } + }; + + // spine-phaser-v3/src/index.ts + window.spine = { SpinePlugin }; + window["spine.SpinePlugin"] = SpinePlugin; + return __toCommonJS(src_exports); +})(); +//# sourceMappingURL=spine-phaser-v3.js.map diff --git a/spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js.map b/spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js.map new file mode 100644 index 000000000..394b78976 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/iife/spine-phaser-v3.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../src/index.ts", "../../src/require-shim.ts", "../../src/SpinePlugin.ts", "../../src/keys.ts", "../../../spine-core/src/Utils.ts", "../../../spine-core/src/attachments/Attachment.ts", "../../../spine-core/src/attachments/Sequence.ts", "../../../spine-core/src/Animation.ts", "../../../spine-core/src/AnimationState.ts", "../../../spine-core/src/AnimationStateData.ts", "../../../spine-core/src/attachments/BoundingBoxAttachment.ts", "../../../spine-core/src/attachments/ClippingAttachment.ts", "../../../spine-core/src/Texture.ts", "../../../spine-core/src/TextureAtlas.ts", "../../../spine-core/src/attachments/MeshAttachment.ts", "../../../spine-core/src/attachments/PathAttachment.ts", "../../../spine-core/src/attachments/PointAttachment.ts", "../../../spine-core/src/attachments/RegionAttachment.ts", "../../../spine-core/src/AtlasAttachmentLoader.ts", "../../../spine-core/src/BoneData.ts", "../../../spine-core/src/Bone.ts", "../../../spine-core/src/ConstraintData.ts", "../../../spine-core/src/AssetManagerBase.ts", "../../../spine-core/src/Event.ts", "../../../spine-core/src/EventData.ts", "../../../spine-core/src/IkConstraint.ts", "../../../spine-core/src/IkConstraintData.ts", "../../../spine-core/src/PathConstraintData.ts", "../../../spine-core/src/PathConstraint.ts", "../../../spine-core/src/PhysicsConstraint.ts", "../../../spine-core/src/Slot.ts", "../../../spine-core/src/TransformConstraint.ts", "../../../spine-core/src/Skeleton.ts", "../../../spine-core/src/PhysicsConstraintData.ts", "../../../spine-core/src/SkeletonData.ts", "../../../spine-core/src/Skin.ts", "../../../spine-core/src/SlotData.ts", "../../../spine-core/src/TransformConstraintData.ts", "../../../spine-core/src/SkeletonBinary.ts", "../../../spine-core/src/SkeletonBounds.ts", "../../../spine-core/src/Triangulator.ts", "../../../spine-core/src/SkeletonClipping.ts", "../../../spine-core/src/SkeletonJson.ts", "../../../spine-core/src/polyfills.ts", "../../../spine-webgl/src/WebGL.ts", "../../../spine-webgl/src/GLTexture.ts", "../../../spine-webgl/src/AssetManager.ts", "../../../spine-webgl/src/Vector3.ts", "../../../spine-webgl/src/Matrix4.ts", "../../../spine-webgl/src/Camera.ts", "../../../spine-webgl/src/Input.ts", "../../../spine-webgl/src/CameraController.ts", "../../../spine-webgl/src/Shader.ts", "../../../spine-webgl/src/Mesh.ts", "../../../spine-webgl/src/PolygonBatcher.ts", "../../../spine-webgl/src/ShapeRenderer.ts", "../../../spine-webgl/src/SkeletonDebugRenderer.ts", "../../../spine-webgl/src/SkeletonRenderer.ts", "../../../spine-webgl/src/SceneRenderer.ts", "../../../spine-webgl/src/LoadingScreen.ts", "../../../spine-webgl/src/SpineCanvas.ts", "../../src/mixins.ts", "../../src/SpineGameObject.ts", "../../../spine-canvas/src/CanvasTexture.ts", "../../../spine-canvas/src/SkeletonRenderer.ts"], + "sourcesContent": ["/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport * from \"./require-shim.js\"\nexport * from \"./SpinePlugin.js\"\nexport * from \"./SpineGameObject.js\"\nexport * from \"./mixins.js\"\nexport * from \"@esotericsoftware/spine-core\";\nexport * from \"@esotericsoftware/spine-webgl\";\nimport { SpineGameObjectConfig, SpinePlugin } from \"./SpinePlugin.js\";\n(window as any).spine = { SpinePlugin: SpinePlugin };\n(window as any)[\"spine.SpinePlugin\"] = SpinePlugin;\n\nimport { SpineGameObject, SpineGameObjectBoundsProvider } from \"./SpineGameObject.js\";\n\ndeclare global {\n\tnamespace Phaser.Loader {\n\t\texport interface LoaderPlugin {\n\t\t\tspineJson (key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin;\n\t\t\tspineBinary (key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin;\n\t\t\tspineAtlas (key: string, url: string, premultipliedAlpha?: boolean, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin;\n\t\t}\n\t}\n\n\tnamespace Phaser.GameObjects {\n\t\texport interface GameObjectFactory {\n\t\t\tspine (x: number, y: number, dataKey: string, atlasKey: string, boundsProvider?: SpineGameObjectBoundsProvider): SpineGameObject;\n\t\t}\n\n\t\texport interface GameObjectCreator {\n\t\t\tspine (config: SpineGameObjectConfig, addToScene?: boolean): SpineGameObject;\n\t\t}\n\t}\n\n\tnamespace Phaser {\n\t\texport interface Scene {\n\t\t\tspine: SpinePlugin;\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\ndeclare global {\n\tvar require: any;\n}\nif (typeof window !== 'undefined' && window.Phaser) {\n\tlet prevRequire = window.require;\n\twindow.require = (x: string) => {\n\t\tif (prevRequire) return prevRequire(x);\n\t\telse if (x === \"Phaser\") return window.Phaser;\n\t}\n}\nexport { }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport * as Phaser from \"phaser\";\nimport { SPINE_ATLAS_CACHE_KEY, SPINE_GAME_OBJECT_TYPE, SPINE_SKELETON_DATA_FILE_TYPE, SPINE_ATLAS_FILE_TYPE, SPINE_SKELETON_FILE_CACHE_KEY as SPINE_SKELETON_DATA_CACHE_KEY } from \"./keys.js\";\nimport { AtlasAttachmentLoader, GLTexture, SceneRenderer, Skeleton, SkeletonBinary, SkeletonData, SkeletonJson, TextureAtlas } from \"@esotericsoftware/spine-webgl\"\nimport { SpineGameObject, SpineGameObjectBoundsProvider } from \"./SpineGameObject.js\";\nimport { CanvasTexture, SkeletonRenderer } from \"@esotericsoftware/spine-canvas\";\n\n/**\n * Configuration object used when creating {@link SpineGameObject} instances via a scene's\n * {@link GameObjectCreator} (`Scene.make`).\n */\nexport interface SpineGameObjectConfig extends Phaser.Types.GameObjects.GameObjectConfig {\n\t/** The x-position of the object, optional, default: 0 */\n\tx?: number,\n\t/** The y-position of the object, optional, default: 0 */\n\ty?: number,\n\t/** The skeleton data key */\n\tdataKey: string,\n\t/** The atlas key */\n\tatlasKey: string\n\t/** The bounds provider, optional, default: `SetupPoseBoundsProvider` */\n\tboundsProvider?: SpineGameObjectBoundsProvider\n}\n\n/**\n * {@link ScenePlugin} implementation adding Spine Runtime capabilities to a scene.\n *\n * The scene's {@link LoaderPlugin} (`Scene.load`) gets these additional functions:\n * * `spineBinary(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`.\n * * `spineJson(key: string, url: string, xhrSettings?: XHRSettingsObject)`: loads a skeleton binary `.skel` file from the `url`.\n * * `spineAtlas(key: string, url: string, premultipliedAlpha: boolean = true, xhrSettings?: XHRSettingsObject)`: loads a texture atlas `.atlas` file from the `url` as well as its correponding texture atlas page images.\n *\n * The scene's {@link GameObjectFactory} (`Scene.add`) gets these additional functions:\n * * `spine(x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider = SetupPoseBoundsProvider())`:\n * creates a new {@link SpineGameObject} from the data and atlas at position `(x, y)`, using the {@link BoundsProvider} to calculate its bounding box. The object is automatically added to the scene.\n *\n * The scene's {@link GameObjectCreator} (`Scene.make`) gets these additional functions:\n * * `spine(config: SpineGameObjectConfig)`: creates a new {@link SpineGameObject} from the given configuration object.\n *\n * The plugin has additional public methods to work with Spine Runtime core API objects:\n * * `getAtlas(atlasKey: string)`: returns the {@link TextureAtlas} instance for the given atlas key.\n * * `getSkeletonData(skeletonDataKey: string)`: returns the {@link SkeletonData} instance for the given skeleton data key.\n * * `createSkeleton(skeletonDataKey: string, atlasKey: string, premultipliedAlpha: boolean = true)`: creates a new {@link Skeleton} instance from the given skeleton data and atlas key.\n * * `isPremultipliedAlpha(atlasKey: string)`: returns `true` if the atlas with the given key has premultiplied alpha.\n */\nexport class SpinePlugin extends Phaser.Plugins.ScenePlugin {\n\tgame: Phaser.Game;\n\tprivate isWebGL: boolean;\n\tgl: WebGLRenderingContext | null;\n\tstatic gameWebGLRenderer: SceneRenderer | null = null;\n\tget webGLRenderer (): SceneRenderer | null {\n\t\treturn SpinePlugin.gameWebGLRenderer;\n\t}\n\tcanvasRenderer: SkeletonRenderer | null;\n\tphaserRenderer: Phaser.Renderer.Canvas.CanvasRenderer | Phaser.Renderer.WebGL.WebGLRenderer;\n\tprivate skeletonDataCache: Phaser.Cache.BaseCache;\n\tprivate atlasCache: Phaser.Cache.BaseCache;\n\n\tconstructor (scene: Phaser.Scene, pluginManager: Phaser.Plugins.PluginManager, pluginKey: string) {\n\t\tsuper(scene, pluginManager, pluginKey);\n\t\tthis.game = pluginManager.game;\n\t\tthis.isWebGL = this.game.config.renderType === 2;\n\t\tthis.gl = this.isWebGL ? (this.game.renderer as Phaser.Renderer.WebGL.WebGLRenderer).gl : null;\n\t\tthis.phaserRenderer = this.game.renderer;\n\t\tthis.canvasRenderer = null;\n\t\tthis.skeletonDataCache = this.game.cache.addCustom(SPINE_SKELETON_DATA_CACHE_KEY);\n\t\tthis.atlasCache = this.game.cache.addCustom(SPINE_ATLAS_CACHE_KEY);\n\n\t\tlet skeletonJsonFileCallback = function (this: any, key: string,\n\t\t\turl: string,\n\t\t\txhrSettings: Phaser.Types.Loader.XHRSettingsObject) {\n\t\t\tlet file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.json, xhrSettings);\n\t\t\tthis.addFile(file.files);\n\t\t\treturn this;\n\t\t};\n\t\tpluginManager.registerFileType(\"spineJson\", skeletonJsonFileCallback, scene);\n\n\t\tlet skeletonBinaryFileCallback = function (this: any, key: string,\n\t\t\turl: string,\n\t\t\txhrSettings: Phaser.Types.Loader.XHRSettingsObject) {\n\t\t\tlet file = new SpineSkeletonDataFile(this as any, key, url, SpineSkeletonDataFileType.binary, xhrSettings);\n\t\t\tthis.addFile(file.files);\n\t\t\treturn this;\n\t\t};\n\t\tpluginManager.registerFileType(\"spineBinary\", skeletonBinaryFileCallback, scene);\n\n\t\tlet atlasFileCallback = function (this: any, key: string,\n\t\t\turl: string,\n\t\t\tpremultipliedAlpha: boolean,\n\t\t\txhrSettings: Phaser.Types.Loader.XHRSettingsObject) {\n\t\t\tlet file = new SpineAtlasFile(this as any, key, url, premultipliedAlpha, xhrSettings);\n\t\t\tthis.addFile(file.files);\n\t\t\treturn this;\n\t\t};\n\t\tpluginManager.registerFileType(\"spineAtlas\", atlasFileCallback, scene);\n\n\t\tlet addSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, x: number, y: number, dataKey: string, atlasKey: string, boundsProvider: SpineGameObjectBoundsProvider) {\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.clear();\n\t\t\t}\n\n\t\t\tconst spinePlugin = (this.scene.sys as any)[pluginKey] as SpinePlugin;\n\t\t\tlet gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, dataKey, atlasKey, boundsProvider);\n\t\t\tthis.displayList.add(gameObject);\n\t\t\tthis.updateList.add(gameObject);\n\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.rebind();\n\t\t\t}\n\n\t\t\treturn gameObject;\n\t\t};\n\n\t\tlet makeSpineGameObject = function (this: Phaser.GameObjects.GameObjectFactory, config: SpineGameObjectConfig, addToScene: boolean = false) {\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.clear();\n\t\t\t}\n\n\t\t\tlet x = config.x ? config.x : 0;\n\t\t\tlet y = config.y ? config.y : 0;\n\t\t\tlet boundsProvider = config.boundsProvider ? config.boundsProvider : undefined;\n\n\t\t\tconst spinePlugin = (this.scene.sys as any)[pluginKey] as SpinePlugin;\n\t\t\tlet gameObject = new SpineGameObject(this.scene, spinePlugin, x, y, config.dataKey, config.atlasKey, boundsProvider);\n\t\t\tif (addToScene !== undefined) {\n\t\t\t\tconfig.add = addToScene;\n\t\t\t}\n\n\t\t\tif (this.scene.sys.renderer instanceof Phaser.Renderer.WebGL.WebGLRenderer) {\n\t\t\t\tthis.scene.sys.renderer.pipelines.rebind();\n\t\t\t}\n\n\t\t\treturn Phaser.GameObjects.BuildGameObject(this.scene, gameObject, config);\n\t\t}\n\t\tpluginManager.registerGameObject((window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, addSpineGameObject, makeSpineGameObject);\n\t}\n\n\tstatic rendererId = 0;\n\tboot () {\n\t\tSkeleton.yDown = true;\n\t\tif (this.isWebGL) {\n\t\t\tif (!SpinePlugin.gameWebGLRenderer) {\n\t\t\t\tSpinePlugin.gameWebGLRenderer = new SceneRenderer((this.game.renderer! as Phaser.Renderer.WebGL.WebGLRenderer).canvas, this.gl!, true);\n\t\t\t}\n\t\t\tthis.onResize();\n\t\t\tthis.game.scale.on(Phaser.Scale.Events.RESIZE, this.onResize, this);\n\t\t} else {\n\t\t\tif (!this.canvasRenderer) {\n\t\t\t\tthis.canvasRenderer = new SkeletonRenderer(this.scene!.sys.context);\n\t\t\t}\n\t\t}\n\n\t\tvar eventEmitter = this.systems!.events;\n\t\teventEmitter.once('shutdown', this.shutdown, this);\n\t\teventEmitter.once('destroy', this.destroy, this);\n\t\tthis.game.events.once('destroy', this.gameDestroy, this);\n\t}\n\n\tonResize () {\n\t\tvar phaserRenderer = this.game.renderer;\n\t\tvar sceneRenderer = this.webGLRenderer;\n\n\t\tif (phaserRenderer && sceneRenderer) {\n\t\t\tvar viewportWidth = phaserRenderer.width;\n\t\t\tvar viewportHeight = phaserRenderer.height;\n\t\t\tsceneRenderer.camera.position.x = viewportWidth / 2;\n\t\t\tsceneRenderer.camera.position.y = viewportHeight / 2;\n\t\t\tsceneRenderer.camera.up.y = -1;\n\t\t\tsceneRenderer.camera.direction.z = 1;\n\t\t\tsceneRenderer.camera.setViewport(viewportWidth, viewportHeight);\n\t\t}\n\t}\n\n\tshutdown () {\n\t\tthis.systems!.events.off(\"shutdown\", this.shutdown, this);\n\t\tif (this.isWebGL) {\n\t\t\tthis.game.scale.off(Phaser.Scale.Events.RESIZE, this.onResize, this);\n\t\t}\n\t}\n\n\tdestroy () {\n\t\tthis.shutdown()\n\t}\n\n\tgameDestroy () {\n\t\tthis.pluginManager.removeGameObject((window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE, true, true);\n\t\tif (this.webGLRenderer) this.webGLRenderer.dispose();\n\t\tSpinePlugin.gameWebGLRenderer = null;\n\t}\n\n\t/** Returns the TextureAtlas instance for the given key */\n\tgetAtlas (atlasKey: string) {\n\t\tlet atlas: TextureAtlas;\n\t\tif (this.atlasCache.exists(atlasKey)) {\n\t\t\tatlas = this.atlasCache.get(atlasKey);\n\t\t} else {\n\t\t\tlet atlasFile = this.game.cache.text.get(atlasKey) as { data: string, premultipliedAlpha: boolean };\n\t\t\tatlas = new TextureAtlas(atlasFile.data);\n\t\t\tif (this.isWebGL) {\n\t\t\t\tlet gl = this.gl!;\n\t\t\t\tconst phaserUnpackPmaValue = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL);\n\t\t\t\tif (phaserUnpackPmaValue) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\t\t\t\tfor (let atlasPage of atlas.pages) {\n\t\t\t\t\tatlasPage.setTexture(new GLTexture(gl, this.game.textures.get(atlasKey + \"!\" + atlasPage.name).getSourceImage() as HTMLImageElement | ImageBitmap, false));\n\t\t\t\t}\n\t\t\t\tif (phaserUnpackPmaValue) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);\n\t\t\t} else {\n\t\t\t\tfor (let atlasPage of atlas.pages) {\n\t\t\t\t\tatlasPage.setTexture(new CanvasTexture(this.game.textures.get(atlasKey + \"!\" + atlasPage.name).getSourceImage() as HTMLImageElement | ImageBitmap));\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.atlasCache.add(atlasKey, atlas);\n\t\t}\n\t\treturn atlas;\n\t}\n\n\t/** Returns whether the TextureAtlas uses premultiplied alpha */\n\tisAtlasPremultiplied (atlasKey: string) {\n\t\tlet atlasFile = this.game.cache.text.get(atlasKey);\n\t\tif (!atlasFile) return false;\n\t\treturn atlasFile.premultipliedAlpha;\n\t}\n\n\t/** Returns the SkeletonData instance for the given data and atlas key */\n\tgetSkeletonData (dataKey: string, atlasKey: string) {\n\t\tconst atlas = this.getAtlas(atlasKey)\n\t\tconst combinedKey = dataKey + atlasKey;\n\t\tlet skeletonData: SkeletonData;\n\t\tif (this.skeletonDataCache.exists(combinedKey)) {\n\t\t\tskeletonData = this.skeletonDataCache.get(combinedKey);\n\t\t} else {\n\t\t\tif (this.game.cache.json.exists(dataKey)) {\n\t\t\t\tlet jsonFile = this.game.cache.json.get(dataKey) as any;\n\t\t\t\tlet json = new SkeletonJson(new AtlasAttachmentLoader(atlas));\n\t\t\t\tskeletonData = json.readSkeletonData(jsonFile);\n\t\t\t} else {\n\t\t\t\tlet binaryFile = this.game.cache.binary.get(dataKey) as ArrayBuffer;\n\t\t\t\tlet binary = new SkeletonBinary(new AtlasAttachmentLoader(atlas));\n\t\t\t\tskeletonData = binary.readSkeletonData(new Uint8Array(binaryFile));\n\t\t\t}\n\t\t\tthis.skeletonDataCache.add(combinedKey, skeletonData);\n\t\t}\n\t\treturn skeletonData;\n\t}\n\n\t/** Creates a new Skeleton instance from the data and atlas. */\n\tcreateSkeleton (dataKey: string, atlasKey: string) {\n\t\treturn new Skeleton(this.getSkeletonData(dataKey, atlasKey));\n\t}\n}\n\nenum SpineSkeletonDataFileType {\n\tjson,\n\tbinary\n}\n\ninterface SpineSkeletonDataFileConfig {\n\tkey: string;\n\turl: string;\n\ttype: \"spineJson\" | \"spineBinary\";\n\txhrSettings?: Phaser.Types.Loader.XHRSettingsObject\n}\n\nclass SpineSkeletonDataFile extends Phaser.Loader.MultiFile {\n\tconstructor (loader: Phaser.Loader.LoaderPlugin, key: string | SpineSkeletonDataFileConfig, url?: string, public fileType?: SpineSkeletonDataFileType, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject) {\n\t\tif (typeof key !== \"string\") {\n\t\t\tconst config = key;\n\t\t\tkey = config.key;\n\t\t\turl = config.url;\n\t\t\tfileType = config.type === \"spineJson\" ? SpineSkeletonDataFileType.json : SpineSkeletonDataFileType.binary;\n\t\t\txhrSettings = config.xhrSettings;\n\t\t}\n\t\tlet file = null;\n\t\tlet isJson = fileType == SpineSkeletonDataFileType.json;\n\t\tif (isJson) {\n\t\t\tfile = new Phaser.Loader.FileTypes.JSONFile(loader, {\n\t\t\t\tkey: key,\n\t\t\t\turl: url,\n\t\t\t\textension: \"json\",\n\t\t\t\txhrSettings: xhrSettings,\n\t\t\t} as Phaser.Types.Loader.FileTypes.JSONFileConfig);\n\t\t} else {\n\t\t\tfile = new Phaser.Loader.FileTypes.BinaryFile(loader, {\n\t\t\t\tkey: key,\n\t\t\t\turl: url,\n\t\t\t\textension: \"skel\",\n\t\t\t\txhrSettings: xhrSettings,\n\t\t\t} as Phaser.Types.Loader.FileTypes.BinaryFileConfig);\n\t\t}\n\t\tsuper(loader, SPINE_SKELETON_DATA_FILE_TYPE, key, [file]);\n\t}\n\n\tonFileComplete (file: Phaser.Loader.File) {\n\t\tthis.pending--;\n\t}\n\n\taddToCache () {\n\t\tif (this.isReadyToProcess()) this.files[0].addToCache();\n\t}\n}\n\ninterface SpineAtlasFileConfig {\n\tkey: string;\n\turl: string;\n\tpremultipliedAlpha?: boolean;\n\txhrSettings?: Phaser.Types.Loader.XHRSettingsObject;\n}\n\nclass SpineAtlasFile extends Phaser.Loader.MultiFile {\n\tconstructor (loader: Phaser.Loader.LoaderPlugin, key: string | SpineAtlasFileConfig, url?: string, public premultipliedAlpha?: boolean, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject) {\n\t\tif (typeof key !== \"string\") {\n\t\t\tconst config = key;\n\t\t\tkey = config.key;\n\t\t\turl = config.url;\n\t\t\tpremultipliedAlpha = config.premultipliedAlpha;\n\t\t\txhrSettings = config.xhrSettings;\n\t\t}\n\n\t\tsuper(loader, SPINE_ATLAS_FILE_TYPE, key, [\n\t\t\tnew Phaser.Loader.FileTypes.TextFile(loader, {\n\t\t\t\tkey: key,\n\t\t\t\turl: url,\n\t\t\t\txhrSettings: xhrSettings,\n\t\t\t\textension: \"atlas\"\n\t\t\t})\n\t\t]);\n\t}\n\n\tonFileComplete (file: Phaser.Loader.File) {\n\t\tif (this.files.indexOf(file) != -1) {\n\t\t\tthis.pending--;\n\n\t\t\tif (file.type == \"text\") {\n\t\t\t\tvar lines = file.data.split(/\\r\\n|\\r|\\n/);\n\t\t\t\tlet textures = [];\n\t\t\t\ttextures.push(lines[0]);\n\t\t\t\tfor (var t = 1; t < lines.length; t++) {\n\t\t\t\t\tvar line = lines[t];\n\t\t\t\t\tif (line.trim() === '' && t < lines.length - 1) {\n\t\t\t\t\t\tline = lines[t + 1];\n\t\t\t\t\t\ttextures.push(line);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet basePath = file.src.match(/^.*\\//) ?? \"\";\n\t\t\t\tfor (var i = 0; i < textures.length; i++) {\n\t\t\t\t\tvar url = basePath + textures[i];\n\t\t\t\t\tvar key = file.key + \"!\" + textures[i];\n\t\t\t\t\tvar image = new Phaser.Loader.FileTypes.ImageFile(this.loader, key, url);\n\n\t\t\t\t\tif (!this.loader.keyExists(image)) {\n\t\t\t\t\t\tthis.addToMultiFile(image);\n\t\t\t\t\t\tthis.loader.addFile(image);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\taddToCache () {\n\t\tif (this.isReadyToProcess()) {\n\t\t\tlet textureManager = this.loader.textureManager;\n\t\t\tfor (let file of this.files) {\n\t\t\t\tif (file.type == \"image\") {\n\t\t\t\t\tif (!textureManager.exists(file.key)) {\n\t\t\t\t\t\ttextureManager.addImage(file.key, file.data);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.premultipliedAlpha = this.premultipliedAlpha ?? (file.data.indexOf(\"pma: true\") >= 0 || file.data.indexOf(\"pma:true\") >= 0);\n\t\t\t\t\tfile.data = {\n\t\t\t\t\t\tdata: file.data,\n\t\t\t\t\t\tpremultipliedAlpha: this.premultipliedAlpha,\n\t\t\t\t\t};\n\t\t\t\t\tfile.addToCache();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport const SPINE_SKELETON_FILE_CACHE_KEY = \"esotericsoftware.spine.skeletonFile.cache\";\nexport const SPINE_ATLAS_CACHE_KEY = \"esotericsoftware.spine.atlas.cache\";\nexport const SPINE_LOADER_TYPE = \"spine\";\nexport const SPINE_SKELETON_DATA_FILE_TYPE = \"spineSkeletonData\";\nexport const SPINE_ATLAS_FILE_TYPE = \"spineAtlasData\";\nexport const SPINE_GAME_OBJECT_TYPE = \"spine\";\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Skeleton } from \"./Skeleton.js\";\nimport { MixBlend } from \"./Animation.js\";\n\nexport interface StringMap {\n\t[key: string]: T;\n}\n\nexport class IntSet {\n\tarray = new Array();\n\n\tadd (value: number): boolean {\n\t\tlet contains = this.contains(value);\n\t\tthis.array[value | 0] = value | 0;\n\t\treturn !contains;\n\t}\n\n\tcontains (value: number) {\n\t\treturn this.array[value | 0] != undefined;\n\t}\n\n\tremove (value: number) {\n\t\tthis.array[value | 0] = undefined;\n\t}\n\n\tclear () {\n\t\tthis.array.length = 0;\n\t}\n}\n\nexport class StringSet {\n\tentries: StringMap = {};\n\tsize = 0;\n\n\tadd (value: string): boolean {\n\t\tlet contains = this.entries[value];\n\t\tthis.entries[value] = true;\n\t\tif (!contains) {\n\t\t\tthis.size++;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\taddAll (values: string[]): boolean {\n\t\tlet oldSize = this.size;\n\t\tfor (var i = 0, n = values.length; i < n; i++)\n\t\t\tthis.add(values[i]);\n\t\treturn oldSize != this.size;\n\t}\n\n\tcontains (value: string) {\n\t\treturn this.entries[value];\n\t}\n\n\tclear () {\n\t\tthis.entries = {};\n\t\tthis.size = 0;\n\t}\n}\n\nexport type NumberArrayLike = Array | Float32Array;\nexport type IntArrayLike = Array | Int16Array;\n\nexport interface Disposable {\n\tdispose (): void;\n}\n\nexport interface Restorable {\n\trestore (): void;\n}\n\nexport class Color {\n\tpublic static WHITE = new Color(1, 1, 1, 1);\n\tpublic static RED = new Color(1, 0, 0, 1);\n\tpublic static GREEN = new Color(0, 1, 0, 1);\n\tpublic static BLUE = new Color(0, 0, 1, 1);\n\tpublic static MAGENTA = new Color(1, 0, 1, 1);\n\n\tconstructor (public r: number = 0, public g: number = 0, public b: number = 0, public a: number = 0) {\n\t}\n\n\tset (r: number, g: number, b: number, a: number) {\n\t\tthis.r = r;\n\t\tthis.g = g;\n\t\tthis.b = b;\n\t\tthis.a = a;\n\t\treturn this.clamp();\n\t}\n\n\tsetFromColor (c: Color) {\n\t\tthis.r = c.r;\n\t\tthis.g = c.g;\n\t\tthis.b = c.b;\n\t\tthis.a = c.a;\n\t\treturn this;\n\t}\n\n\tsetFromString (hex: string) {\n\t\thex = hex.charAt(0) == '#' ? hex.substr(1) : hex;\n\t\tthis.r = parseInt(hex.substr(0, 2), 16) / 255;\n\t\tthis.g = parseInt(hex.substr(2, 2), 16) / 255;\n\t\tthis.b = parseInt(hex.substr(4, 2), 16) / 255;\n\t\tthis.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255;\n\t\treturn this;\n\t}\n\n\tadd (r: number, g: number, b: number, a: number) {\n\t\tthis.r += r;\n\t\tthis.g += g;\n\t\tthis.b += b;\n\t\tthis.a += a;\n\t\treturn this.clamp();\n\t}\n\n\tclamp () {\n\t\tif (this.r < 0) this.r = 0;\n\t\telse if (this.r > 1) this.r = 1;\n\n\t\tif (this.g < 0) this.g = 0;\n\t\telse if (this.g > 1) this.g = 1;\n\n\t\tif (this.b < 0) this.b = 0;\n\t\telse if (this.b > 1) this.b = 1;\n\n\t\tif (this.a < 0) this.a = 0;\n\t\telse if (this.a > 1) this.a = 1;\n\t\treturn this;\n\t}\n\n\tstatic rgba8888ToColor (color: Color, value: number) {\n\t\tcolor.r = ((value & 0xff000000) >>> 24) / 255;\n\t\tcolor.g = ((value & 0x00ff0000) >>> 16) / 255;\n\t\tcolor.b = ((value & 0x0000ff00) >>> 8) / 255;\n\t\tcolor.a = ((value & 0x000000ff)) / 255;\n\t}\n\n\tstatic rgb888ToColor (color: Color, value: number) {\n\t\tcolor.r = ((value & 0x00ff0000) >>> 16) / 255;\n\t\tcolor.g = ((value & 0x0000ff00) >>> 8) / 255;\n\t\tcolor.b = ((value & 0x000000ff)) / 255;\n\t}\n\n\ttoRgb888 () {\n\t\tconst hex = (x: number) => (\"0\" + (x * 255).toString(16)).slice(-2);\n\t\treturn Number(\"0x\" + hex(this.r) + hex(this.g) + hex(this.b));\n\t}\n\n\tstatic fromString (hex: string): Color {\n\t\treturn new Color().setFromString(hex);\n\t}\n}\n\nexport class MathUtils {\n\tstatic PI = 3.1415927;\n\tstatic PI2 = MathUtils.PI * 2;\n\tstatic invPI2 = 1 / MathUtils.PI2;\n\tstatic radiansToDegrees = 180 / MathUtils.PI;\n\tstatic radDeg = MathUtils.radiansToDegrees;\n\tstatic degreesToRadians = MathUtils.PI / 180;\n\tstatic degRad = MathUtils.degreesToRadians;\n\n\tstatic clamp (value: number, min: number, max: number) {\n\t\tif (value < min) return min;\n\t\tif (value > max) return max;\n\t\treturn value;\n\t}\n\n\tstatic cosDeg (degrees: number) {\n\t\treturn Math.cos(degrees * MathUtils.degRad);\n\t}\n\n\tstatic sinDeg (degrees: number) {\n\t\treturn Math.sin(degrees * MathUtils.degRad);\n\t}\n\n\tstatic atan2Deg (y: number, x: number) {\n\t\treturn Math.atan2(y, x) * MathUtils.degRad;\n\t}\n\n\tstatic signum (value: number): number {\n\t\treturn value > 0 ? 1 : value < 0 ? -1 : 0;\n\t}\n\n\tstatic toInt (x: number) {\n\t\treturn x > 0 ? Math.floor(x) : Math.ceil(x);\n\t}\n\n\tstatic cbrt (x: number) {\n\t\tlet y = Math.pow(Math.abs(x), 1 / 3);\n\t\treturn x < 0 ? -y : y;\n\t}\n\n\tstatic randomTriangular (min: number, max: number): number {\n\t\treturn MathUtils.randomTriangularWith(min, max, (min + max) * 0.5);\n\t}\n\n\tstatic randomTriangularWith (min: number, max: number, mode: number): number {\n\t\tlet u = Math.random();\n\t\tlet d = max - min;\n\t\tif (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min));\n\t\treturn max - Math.sqrt((1 - u) * d * (max - mode));\n\t}\n\n\tstatic isPowerOfTwo (value: number) {\n\t\treturn value && (value & (value - 1)) === 0;\n\t}\n}\n\nexport abstract class Interpolation {\n\tprotected abstract applyInternal (a: number): number;\n\tapply (start: number, end: number, a: number): number {\n\t\treturn start + (end - start) * this.applyInternal(a);\n\t}\n}\n\nexport class Pow extends Interpolation {\n\tprotected power = 2;\n\n\tconstructor (power: number) {\n\t\tsuper();\n\t\tthis.power = power;\n\t}\n\n\tapplyInternal (a: number): number {\n\t\tif (a <= 0.5) return Math.pow(a * 2, this.power) / 2;\n\t\treturn Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1;\n\t}\n}\n\nexport class PowOut extends Pow {\n\tconstructor (power: number) {\n\t\tsuper(power);\n\t}\n\n\tapplyInternal (a: number): number {\n\t\treturn Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1;\n\t}\n}\n\nexport class Utils {\n\tstatic SUPPORTS_TYPED_ARRAYS = typeof (Float32Array) !== \"undefined\";\n\n\tstatic arrayCopy (source: ArrayLike, sourceStart: number, dest: ArrayLike, destStart: number, numElements: number) {\n\t\tfor (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) {\n\t\t\tdest[j] = source[i];\n\t\t}\n\t}\n\n\tstatic arrayFill (array: ArrayLike, fromIndex: number, toIndex: number, value: T) {\n\t\tfor (let i = fromIndex; i < toIndex; i++)\n\t\t\tarray[i] = value;\n\t}\n\n\tstatic setArraySize (array: Array, size: number, value: any = 0): Array {\n\t\tlet oldSize = array.length;\n\t\tif (oldSize == size) return array;\n\t\tarray.length = size;\n\t\tif (oldSize < size) {\n\t\t\tfor (let i = oldSize; i < size; i++) array[i] = value;\n\t\t}\n\t\treturn array;\n\t}\n\n\tstatic ensureArrayCapacity (array: Array, size: number, value: any = 0): Array {\n\t\tif (array.length >= size) return array;\n\t\treturn Utils.setArraySize(array, size, value);\n\t}\n\n\tstatic newArray (size: number, defaultValue: T): Array {\n\t\tlet array = new Array(size);\n\t\tfor (let i = 0; i < size; i++) array[i] = defaultValue;\n\t\treturn array;\n\t}\n\n\tstatic newFloatArray (size: number): NumberArrayLike {\n\t\tif (Utils.SUPPORTS_TYPED_ARRAYS)\n\t\t\treturn new Float32Array(size)\n\t\telse {\n\t\t\tlet array = new Array(size);\n\t\t\tfor (let i = 0; i < array.length; i++) array[i] = 0;\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tstatic newShortArray (size: number): IntArrayLike {\n\t\tif (Utils.SUPPORTS_TYPED_ARRAYS)\n\t\t\treturn new Int16Array(size)\n\t\telse {\n\t\t\tlet array = new Array(size);\n\t\t\tfor (let i = 0; i < array.length; i++) array[i] = 0;\n\t\t\treturn array;\n\t\t}\n\t}\n\n\tstatic toFloatArray (array: Array) {\n\t\treturn Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;\n\t}\n\n\tstatic toSinglePrecision (value: number) {\n\t\treturn Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value;\n\t}\n\n\t// This function is used to fix WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\tstatic webkit602BugfixHelper (alpha: number, blend: MixBlend) {\n\t}\n\n\tstatic contains (array: Array, element: T, identity = true) {\n\t\tfor (var i = 0; i < array.length; i++)\n\t\t\tif (array[i] == element) return true;\n\t\treturn false;\n\t}\n\n\tstatic enumValue (type: any, name: string) {\n\t\treturn type[name[0].toUpperCase() + name.slice(1)];\n\t}\n}\n\nexport class DebugUtils {\n\tstatic logBones (skeleton: Skeleton) {\n\t\tfor (let i = 0; i < skeleton.bones.length; i++) {\n\t\t\tlet bone = skeleton.bones[i];\n\t\t\tconsole.log(bone.data.name + \", \" + bone.a + \", \" + bone.b + \", \" + bone.c + \", \" + bone.d + \", \" + bone.worldX + \", \" + bone.worldY);\n\t\t}\n\t}\n}\n\nexport class Pool {\n\tprivate items = new Array();\n\tprivate instantiator: () => T;\n\n\tconstructor (instantiator: () => T) {\n\t\tthis.instantiator = instantiator;\n\t}\n\n\tobtain () {\n\t\treturn this.items.length > 0 ? this.items.pop()! : this.instantiator();\n\t}\n\n\tfree (item: T) {\n\t\tif ((item as any).reset) (item as any).reset();\n\t\tthis.items.push(item);\n\t}\n\n\tfreeAll (items: ArrayLike) {\n\t\tfor (let i = 0; i < items.length; i++)\n\t\t\tthis.free(items[i]);\n\t}\n\n\tclear () {\n\t\tthis.items.length = 0;\n\t}\n}\n\nexport class Vector2 {\n\tconstructor (public x = 0, public y = 0) {\n\t}\n\n\tset (x: number, y: number): Vector2 {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\treturn this;\n\t}\n\n\tlength () {\n\t\tlet x = this.x;\n\t\tlet y = this.y;\n\t\treturn Math.sqrt(x * x + y * y);\n\t}\n\n\tnormalize () {\n\t\tlet len = this.length();\n\t\tif (len != 0) {\n\t\t\tthis.x /= len;\n\t\t\tthis.y /= len;\n\t\t}\n\t\treturn this;\n\t}\n}\n\nexport class TimeKeeper {\n\tmaxDelta = 0.064;\n\tframesPerSecond = 0;\n\tdelta = 0;\n\ttotalTime = 0;\n\n\tprivate lastTime = Date.now() / 1000;\n\tprivate frameCount = 0;\n\tprivate frameTime = 0;\n\n\tupdate () {\n\t\tlet now = Date.now() / 1000;\n\t\tthis.delta = now - this.lastTime;\n\t\tthis.frameTime += this.delta;\n\t\tthis.totalTime += this.delta;\n\t\tif (this.delta > this.maxDelta) this.delta = this.maxDelta;\n\t\tthis.lastTime = now;\n\n\t\tthis.frameCount++;\n\t\tif (this.frameTime > 1) {\n\t\t\tthis.framesPerSecond = this.frameCount / this.frameTime;\n\t\t\tthis.frameTime = 0;\n\t\t\tthis.frameCount = 0;\n\t\t}\n\t}\n}\n\nexport interface ArrayLike {\n\tlength: number;\n\t[n: number]: T;\n}\n\nexport class WindowedMean {\n\tvalues: Array;\n\taddedValues = 0;\n\tlastValue = 0;\n\tmean = 0;\n\tdirty = true;\n\n\tconstructor (windowSize: number = 32) {\n\t\tthis.values = new Array(windowSize);\n\t}\n\n\thasEnoughData () {\n\t\treturn this.addedValues >= this.values.length;\n\t}\n\n\taddValue (value: number) {\n\t\tif (this.addedValues < this.values.length) this.addedValues++;\n\t\tthis.values[this.lastValue++] = value;\n\t\tif (this.lastValue > this.values.length - 1) this.lastValue = 0;\n\t\tthis.dirty = true;\n\t}\n\n\tgetMean () {\n\t\tif (this.hasEnoughData()) {\n\t\t\tif (this.dirty) {\n\t\t\t\tlet mean = 0;\n\t\t\t\tfor (let i = 0; i < this.values.length; i++)\n\t\t\t\t\tmean += this.values[i];\n\t\t\t\tthis.mean = mean / this.values.length;\n\t\t\t\tthis.dirty = false;\n\t\t\t}\n\t\t\treturn this.mean;\n\t\t}\n\t\treturn 0;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Slot } from \"../Slot.js\";\nimport { NumberArrayLike, Utils } from \"../Utils.js\";\n\n/** The base class for all attachments. */\nexport abstract class Attachment {\n\tname: string;\n\n\tconstructor (name: string) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t}\n\n\tabstract copy (): Attachment;\n}\n\n/** Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's\n * {@link Slot#deform}. */\nexport abstract class VertexAttachment extends Attachment {\n\tprivate static nextID = 0;\n\n\t/** The unique ID for this attachment. */\n\tid = VertexAttachment.nextID++;\n\n\t/** The bones which affect the {@link #getVertices()}. The array entries are, for each vertex, the number of bones affecting\n\t * the vertex followed by that many bone indices, which is the index of the bone in {@link Skeleton#bones}. Will be null\n\t * if this attachment has no weights. */\n\tbones: Array | null = null;\n\n\t/** The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y`\n\t * entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting\n\t * each vertex. */\n\tvertices: NumberArrayLike = [];\n\n\t/** The maximum number of world vertex values that can be output by\n\t * {@link #computeWorldVertices()} using the `count` parameter. */\n\tworldVerticesLength = 0;\n\n\t/** Timelines for the timeline attachment are also applied to this attachment.\n\t * May be null if no attachment-specific timelines should be applied. */\n\ttimelineAttachment: Attachment = this;\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\t/** Transforms the attachment's local {@link #vertices} to world coordinates. If the slot's {@link Slot#deform} is\n\t * not empty, it is used to deform the vertices.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide.\n\t * @param start The index of the first {@link #vertices} value to transform. Each vertex has 2 values, x and y.\n\t * @param count The number of world vertex values to output. Must be <= {@link #worldVerticesLength} - `start`.\n\t * @param worldVertices The output world vertices. Must have a length >= `offset` + `count` *\n\t * `stride` / 2.\n\t * @param offset The `worldVertices` index to begin writing values.\n\t * @param stride The number of `worldVertices` entries between the value pairs written. */\n\tcomputeWorldVertices (slot: Slot, start: number, count: number, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tcount = offset + (count >> 1) * stride;\n\t\tlet skeleton = slot.bone.skeleton;\n\t\tlet deformArray = slot.deform;\n\t\tlet vertices = this.vertices;\n\t\tlet bones = this.bones;\n\t\tif (!bones) {\n\t\t\tif (deformArray.length > 0) vertices = deformArray;\n\t\t\tlet bone = slot.bone;\n\t\t\tlet x = bone.worldX;\n\t\t\tlet y = bone.worldY;\n\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\tfor (let v = start, w = offset; w < count; v += 2, w += stride) {\n\t\t\t\tlet vx = vertices[v], vy = vertices[v + 1];\n\t\t\t\tworldVertices[w] = vx * a + vy * b + x;\n\t\t\t\tworldVertices[w + 1] = vx * c + vy * d + y;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet v = 0, skip = 0;\n\t\tfor (let i = 0; i < start; i += 2) {\n\t\t\tlet n = bones[v];\n\t\t\tv += n + 1;\n\t\t\tskip += n;\n\t\t}\n\t\tlet skeletonBones = skeleton.bones;\n\t\tif (deformArray.length == 0) {\n\t\t\tfor (let w = offset, b = skip * 3; w < count; w += stride) {\n\t\t\t\tlet wx = 0, wy = 0;\n\t\t\t\tlet n = bones[v++];\n\t\t\t\tn += v;\n\t\t\t\tfor (; v < n; v++, b += 3) {\n\t\t\t\t\tlet bone = skeletonBones[bones[v]];\n\t\t\t\t\tlet vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];\n\t\t\t\t\twx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;\n\t\t\t\t\twy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;\n\t\t\t\t}\n\t\t\t\tworldVertices[w] = wx;\n\t\t\t\tworldVertices[w + 1] = wy;\n\t\t\t}\n\t\t} else {\n\t\t\tlet deform = deformArray;\n\t\t\tfor (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {\n\t\t\t\tlet wx = 0, wy = 0;\n\t\t\t\tlet n = bones[v++];\n\t\t\t\tn += v;\n\t\t\t\tfor (; v < n; v++, b += 3, f += 2) {\n\t\t\t\t\tlet bone = skeletonBones[bones[v]];\n\t\t\t\t\tlet vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];\n\t\t\t\t\twx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;\n\t\t\t\t\twy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;\n\t\t\t\t}\n\t\t\t\tworldVertices[w] = wx;\n\t\t\t\tworldVertices[w + 1] = wy;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Does not copy id (generated) or name (set on construction). **/\n\tcopyTo (attachment: VertexAttachment) {\n\t\tif (this.bones) {\n\t\t\tattachment.bones = new Array(this.bones.length);\n\t\t\tUtils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length);\n\t\t} else\n\t\t\tattachment.bones = null;\n\n\t\tif (this.vertices) {\n\t\t\tattachment.vertices = Utils.newFloatArray(this.vertices.length);\n\t\t\tUtils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length);\n\t\t}\n\n\t\tattachment.worldVerticesLength = this.worldVerticesLength;\n\t\tattachment.timelineAttachment = this.timelineAttachment;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TextureRegion } from \"../Texture.js\";\nimport { Slot } from \"../Slot.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Utils } from \"../Utils.js\";\n\n\nexport class Sequence {\n\tprivate static _nextID = 0;\n\n\tid = Sequence.nextID();\n\tregions: TextureRegion[];\n\tstart = 0;\n\tdigits = 0;\n\t/** The index of the region to show for the setup pose. */\n\tsetupIndex = 0;\n\n\tconstructor (count: number) {\n\t\tthis.regions = new Array(count);\n\t}\n\n\tcopy (): Sequence {\n\t\tlet copy = new Sequence(this.regions.length);\n\t\tUtils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length);\n\t\tcopy.start = this.start;\n\t\tcopy.digits = this.digits;\n\t\tcopy.setupIndex = this.setupIndex;\n\t\treturn copy;\n\t}\n\n\tapply (slot: Slot, attachment: HasTextureRegion) {\n\t\tlet index = slot.sequenceIndex;\n\t\tif (index == -1) index = this.setupIndex;\n\t\tif (index >= this.regions.length) index = this.regions.length - 1;\n\t\tlet region = this.regions[index];\n\t\tif (attachment.region != region) {\n\t\t\tattachment.region = region;\n\t\t\tattachment.updateRegion();\n\t\t}\n\t}\n\n\tgetPath (basePath: string, index: number): string {\n\t\tlet result = basePath;\n\t\tlet frame = (this.start + index).toString();\n\t\tfor (let i = this.digits - frame.length; i > 0; i--)\n\t\t\tresult += \"0\";\n\t\tresult += frame;\n\t\treturn result;\n\t}\n\n\tprivate static nextID (): number {\n\t\treturn Sequence._nextID++;\n\t}\n}\n\nexport enum SequenceMode {\n\thold = 0,\n\tonce = 1,\n\tloop = 2,\n\tpingpong = 3,\n\tonceReverse = 4,\n\tloopReverse = 5,\n\tpingpongReverse = 6\n}\n\nexport const SequenceModeValues = [\n\tSequenceMode.hold,\n\tSequenceMode.once,\n\tSequenceMode.loop,\n\tSequenceMode.pingpong,\n\tSequenceMode.onceReverse,\n\tSequenceMode.loopReverse,\n\tSequenceMode.pingpongReverse\n];\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { IkConstraint } from \"./IkConstraint.js\";\nimport { PathConstraint } from \"./PathConstraint.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { TransformConstraint } from \"./TransformConstraint.js\";\nimport { StringSet, Utils, MathUtils, NumberArrayLike } from \"./Utils.js\";\nimport { Event } from \"./Event.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { SequenceMode, SequenceModeValues } from \"./attachments/Sequence.js\";\nimport { PhysicsConstraint } from \"./PhysicsConstraint.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Inherit } from \"./BoneData.js\";\n\n/** A simple container for a list of timelines and a name. */\nexport class Animation {\n\t/** The animation's name, which is unique across all animations in the skeleton. */\n\tname: string;\n\ttimelines: Array = [];\n\ttimelineIds: StringSet = new StringSet();\n\n\t/** The duration of the animation in seconds, which is the highest time of all keys in the timeline. */\n\tduration: number;\n\n\tconstructor (name: string, timelines: Array, duration: number) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t\tthis.setTimelines(timelines);\n\t\tthis.duration = duration;\n\t}\n\n\tsetTimelines (timelines: Array) {\n\t\tif (!timelines) throw new Error(\"timelines cannot be null.\");\n\t\tthis.timelines = timelines;\n\t\tthis.timelineIds.clear();\n\t\tfor (var i = 0; i < timelines.length; i++)\n\t\t\tthis.timelineIds.addAll(timelines[i].getPropertyIds());\n\t}\n\n\thasTimeline (ids: string[]): boolean {\n\t\tfor (let i = 0; i < ids.length; i++)\n\t\t\tif (this.timelineIds.contains(ids[i])) return true;\n\t\treturn false;\n\t}\n\n\t/** Applies all the animation's timelines to the specified skeleton.\n\t *\n\t * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}.\n\t * @param loop If true, the animation repeats after {@link #getDuration()}.\n\t * @param events May be null to ignore fired events. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\n\t\tif (loop && this.duration != 0) {\n\t\t\ttime %= this.duration;\n\t\t\tif (lastTime > 0) lastTime %= this.duration;\n\t\t}\n\n\t\tlet timelines = this.timelines;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\ttimelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);\n\t}\n}\n\n/** Controls how a timeline value is mixed with the setup pose value or current pose value when a timeline's `alpha`\n * < 1.\n *\n * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */\nexport enum MixBlend {\n\t/** Transitions from the setup value to the timeline value (the current value is not used). Before the first key, the setup\n\t * value is set. */\n\tsetup,\n\t/** Transitions from the current value to the timeline value. Before the first key, transitions from the current value to\n\t * the setup value. Timelines which perform instant transitions, such as {@link DrawOrderTimeline} or\n\t * {@link AttachmentTimeline}, use the setup value before the first key.\n\t *\n\t * `first` is intended for the first animations applied, not for animations layered on top of those. */\n\tfirst,\n\t/** Transitions from the current value to the timeline value. No change is made before the first key (the current value is\n\t * kept until the first key).\n\t *\n\t * `replace` is intended for animations layered on top of others, not for the first animations applied. */\n\treplace,\n\t/** Transitions from the current value to the current value plus the timeline value. No change is made before the first key\n\t * (the current value is kept until the first key).\n\t *\n\t * `add` is intended for animations layered on top of others, not for the first animations applied. Properties\n\t * keyed by additive animations must be set manually or by another animation before applying the additive animations, else\n\t * the property values will increase continually. */\n\tadd\n}\n\n/** Indicates whether a timeline's `alpha` is mixing out over time toward 0 (the setup or current pose value) or\n * mixing in toward 1 (the timeline's value).\n *\n * See Timeline {@link Timeline#apply(Skeleton, float, float, Array, float, MixBlend, MixDirection)}. */\nexport enum MixDirection {\n\tmixIn, mixOut\n}\n\nconst Property = {\n\trotate: 0,\n\tx: 1,\n\ty: 2,\n\tscaleX: 3,\n\tscaleY: 4,\n\tshearX: 5,\n\tshearY: 6,\n\tinherit: 7,\n\n\trgb: 8,\n\talpha: 9,\n\trgb2: 10,\n\n\tattachment: 11,\n\tdeform: 12,\n\n\tevent: 13,\n\tdrawOrder: 14,\n\n\tikConstraint: 15,\n\ttransformConstraint: 16,\n\n\tpathConstraintPosition: 17,\n\tpathConstraintSpacing: 18,\n\tpathConstraintMix: 19,\n\n\tphysicsConstraintInertia: 20,\n\tphysicsConstraintStrength: 21,\n\tphysicsConstraintDamping: 22,\n\tphysicsConstraintMass: 23,\n\tphysicsConstraintWind: 24,\n\tphysicsConstraintGravity: 25,\n\tphysicsConstraintMix: 26,\n\tphysicsConstraintReset: 27,\n\n\tsequence: 28,\n}\n\n/** The interface for all timelines. */\nexport abstract class Timeline {\n\tpropertyIds: string[];\n\tframes: NumberArrayLike;\n\n\tconstructor (frameCount: number, propertyIds: string[]) {\n\t\tthis.propertyIds = propertyIds;\n\t\tthis.frames = Utils.newFloatArray(frameCount * this.getFrameEntries());\n\t}\n\n\tgetPropertyIds () {\n\t\treturn this.propertyIds;\n\t}\n\n\tgetFrameEntries (): number {\n\t\treturn 1;\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length / this.getFrameEntries();\n\t}\n\n\tgetDuration (): number {\n\t\treturn this.frames[this.frames.length - this.getFrameEntries()];\n\t}\n\n\tabstract apply (skeleton: Skeleton, lastTime: number, time: number, events: Array | null, alpha: number, blend: MixBlend, direction: MixDirection): void;\n\n\tstatic search1 (frames: NumberArrayLike, time: number) {\n\t\tlet n = frames.length;\n\t\tfor (let i = 1; i < n; i++)\n\t\t\tif (frames[i] > time) return i - 1;\n\t\treturn n - 1;\n\t}\n\n\tstatic search (frames: NumberArrayLike, time: number, step: number) {\n\t\tlet n = frames.length;\n\t\tfor (let i = step; i < n; i += step)\n\t\t\tif (frames[i] > time) return i - step;\n\t\treturn n - step;\n\t}\n}\n\nexport interface BoneTimeline {\n\t/** The index of the bone in {@link Skeleton#bones} that will be changed. */\n\tboneIndex: number;\n}\n\nexport interface SlotTimeline {\n\t/** The index of the slot in {@link Skeleton#slots} that will be changed. */\n\tslotIndex: number;\n}\n\n/** The base class for timelines that use interpolation between key frame values. */\nexport abstract class CurveTimeline extends Timeline {\n\tprotected curves: NumberArrayLike; // type, x, y, ...\n\n\tconstructor (frameCount: number, bezierCount: number, propertyIds: string[]) {\n\t\tsuper(frameCount, propertyIds);\n\t\tthis.curves = Utils.newFloatArray(frameCount + bezierCount * 18/*BEZIER_SIZE*/);\n\t\tthis.curves[frameCount - 1] = 1/*STEPPED*/;\n\t}\n\n\t/** Sets the specified key frame to linear interpolation. */\n\tsetLinear (frame: number) {\n\t\tthis.curves[frame] = 0/*LINEAR*/;\n\t}\n\n\t/** Sets the specified key frame to stepped interpolation. */\n\tsetStepped (frame: number) {\n\t\tthis.curves[frame] = 1/*STEPPED*/;\n\t}\n\n\t/** Shrinks the storage for Bezier curves, for use when bezierCount (specified in the constructor) was larger\n\t * than the actual number of Bezier curves. */\n\tshrink (bezierCount: number) {\n\t\tlet size = this.getFrameCount() + bezierCount * 18/*BEZIER_SIZE*/;\n\t\tif (this.curves.length > size) {\n\t\t\tlet newCurves = Utils.newFloatArray(size);\n\t\t\tUtils.arrayCopy(this.curves, 0, newCurves, 0, size);\n\t\t\tthis.curves = newCurves;\n\t\t}\n\t}\n\n\t/** Stores the segments for the specified Bezier curve. For timelines that modify multiple values, there may be more than\n\t * one curve per frame.\n\t * @param bezier The ordinal of this Bezier curve for this timeline, between 0 and bezierCount - 1 (specified\n\t * in the constructor), inclusive.\n\t * @param frame Between 0 and frameCount - 1, inclusive.\n\t * @param value The index of the value for this frame that this curve is used for.\n\t * @param time1 The time for the first key.\n\t * @param value1 The value for the first key.\n\t * @param cx1 The time for the first Bezier handle.\n\t * @param cy1 The value for the first Bezier handle.\n\t * @param cx2 The time of the second Bezier handle.\n\t * @param cy2 The value for the second Bezier handle.\n\t * @param time2 The time for the second key.\n\t * @param value2 The value for the second key. */\n\tsetBezier (bezier: number, frame: number, value: number, time1: number, value1: number, cx1: number, cy1: number, cx2: number,\n\t\tcy2: number, time2: number, value2: number) {\n\t\tlet curves = this.curves;\n\t\tlet i = this.getFrameCount() + bezier * 18/*BEZIER_SIZE*/;\n\t\tif (value == 0) curves[frame] = 2/*BEZIER*/ + i;\n\t\tlet tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;\n\t\tlet dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006;\n\t\tlet ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;\n\t\tlet dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;\n\t\tlet x = time1 + dx, y = value1 + dy;\n\t\tfor (let n = i + 18/*BEZIER_SIZE*/; i < n; i += 2) {\n\t\t\tcurves[i] = x;\n\t\t\tcurves[i + 1] = y;\n\t\t\tdx += ddx;\n\t\t\tdy += ddy;\n\t\t\tddx += dddx;\n\t\t\tddy += dddy;\n\t\t\tx += dx;\n\t\t\ty += dy;\n\t\t}\n\t}\n\n\t/** Returns the Bezier interpolated value for the specified time.\n\t * @param frameIndex The index into {@link #getFrames()} for the values of the frame before time.\n\t * @param valueOffset The offset from frameIndex to the value this curve is used for.\n\t * @param i The index of the Bezier segments. See {@link #getCurveType(int)}. */\n\tgetBezierValue (time: number, frameIndex: number, valueOffset: number, i: number) {\n\t\tlet curves = this.curves;\n\t\tif (curves[i] > time) {\n\t\t\tlet x = this.frames[frameIndex], y = this.frames[frameIndex + valueOffset];\n\t\t\treturn y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);\n\t\t}\n\t\tlet n = i + 18/*BEZIER_SIZE*/;\n\t\tfor (i += 2; i < n; i += 2) {\n\t\t\tif (curves[i] >= time) {\n\t\t\t\tlet x = curves[i - 2], y = curves[i - 1];\n\t\t\t\treturn y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);\n\t\t\t}\n\t\t}\n\t\tframeIndex += this.getFrameEntries();\n\t\tlet x = curves[n - 2], y = curves[n - 1];\n\t\treturn y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y);\n\t}\n}\n\nexport abstract class CurveTimeline1 extends CurveTimeline {\n\tconstructor (frameCount: number, bezierCount: number, propertyId: string) {\n\t\tsuper(frameCount, bezierCount, [propertyId]);\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 2/*ENTRIES*/;\n\t}\n\n\t/** Sets the time and value for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time The frame time in seconds. */\n\tsetFrame (frame: number, time: number, value: number) {\n\t\tframe <<= 1;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*VALUE*/] = value;\n\t}\n\n\t/** Returns the interpolated value for the specified time. */\n\tgetCurveValue (time: number) {\n\t\tlet frames = this.frames;\n\t\tlet i = frames.length - 2;\n\t\tfor (let ii = 2; ii <= i; ii += 2) {\n\t\t\tif (frames[ii] > time) {\n\t\t\t\ti = ii - 2;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tlet curveType = this.curves[i >> 1];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i], value = frames[i + 1/*VALUE*/];\n\t\t\t\treturn value + (time - before) / (frames[i + 2/*ENTRIES*/] - before) * (frames[i + 2/*ENTRIES*/ + 1/*VALUE*/] - value);\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\treturn frames[i + 1/*VALUE*/];\n\t\t}\n\t\treturn this.getBezierValue(time, i, 1/*VALUE*/, curveType - 2/*BEZIER*/);\n\t}\n\n\tgetRelativeValue (time: number, alpha: number, blend: MixBlend, current: number, setup: number) {\n\t\tif (time < this.frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tlet value = this.getCurveValue(time);\n\t\tswitch (blend) {\n\t\t\tcase MixBlend.setup:\n\t\t\t\treturn setup + value * alpha;\n\t\t\tcase MixBlend.first:\n\t\t\tcase MixBlend.replace:\n\t\t\t\tvalue += setup - current;\n\t\t}\n\t\treturn current + value * alpha;\n\t}\n\n\tgetAbsoluteValue (time: number, alpha: number, blend: MixBlend, current: number, setup: number) {\n\t\tif (time < this.frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tlet value = this.getCurveValue(time);\n\t\tif (blend == MixBlend.setup) return setup + (value - setup) * alpha;\n\t\treturn current + (value - current) * alpha;\n\t}\n\n\tgetAbsoluteValue2 (time: number, alpha: number, blend: MixBlend, current: number, setup: number, value: number) {\n\t\tif (time < this.frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tif (blend == MixBlend.setup) return setup + (value - setup) * alpha;\n\t\treturn current + (value - current) * alpha;\n\t}\n\n\tgetScaleValue (time: number, alpha: number, blend: MixBlend, direction: MixDirection, current: number, setup: number) {\n\t\tconst frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\treturn current + (setup - current) * alpha;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\t\tlet value = this.getCurveValue(time) * setup;\n\t\tif (alpha == 1) {\n\t\t\tif (blend == MixBlend.add) return current + value - setup;\n\t\t\treturn value;\n\t\t}\n\t\t// Mixing out uses sign of setup or current pose, else use sign of key.\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\treturn setup + (Math.abs(value) * MathUtils.signum(setup) - setup) * alpha;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\treturn current + (Math.abs(value) * MathUtils.signum(current) - current) * alpha;\n\t\t\t}\n\t\t} else {\n\t\t\tlet s = 0;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\ts = Math.abs(setup) * MathUtils.signum(value);\n\t\t\t\t\treturn s + (value - s) * alpha;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\ts = Math.abs(current) * MathUtils.signum(value);\n\t\t\t\t\treturn s + (value - s) * alpha;\n\t\t\t}\n\t\t}\n\t\treturn current + (value - setup) * alpha;\n\t}\n}\n\n/** The base class for a {@link CurveTimeline} which sets two properties. */\nexport abstract class CurveTimeline2 extends CurveTimeline {\n\t/** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}.\n\t * @param propertyIds Unique identifiers for the properties the timeline modifies. */\n\tconstructor (frameCount: number, bezierCount: number, propertyId1: string, propertyId2: string) {\n\t\tsuper(frameCount, bezierCount, [propertyId1, propertyId2]);\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 3/*ENTRIES*/;\n\t}\n\n\t/** Sets the time and values for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time The frame time in seconds. */\n\tsetFrame (frame: number, time: number, value1: number, value2: number) {\n\t\tframe *= 3/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*VALUE1*/] = value1;\n\t\tthis.frames[frame + 2/*VALUE2*/] = value2;\n\t}\n}\n\n/** Changes a bone's local {@link Bone#rotation}. */\nexport class RotateTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.rotate + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array | null, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.rotation = this.getRelativeValue(time, alpha, blend, bone.rotation, bone.data.rotation);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#x} and {@link Bone#y}. */\nexport class TranslateTimeline extends CurveTimeline2 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount,\n\t\t\tProperty.x + \"|\" + boneIndex,\n\t\t\tProperty.y + \"|\" + boneIndex,\n\t\t);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.x = bone.data.x;\n\t\t\t\t\tbone.y = bone.data.y;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tbone.x += (bone.data.x - bone.x) * alpha;\n\t\t\t\t\tbone.y += (bone.data.y - bone.y) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet x = 0, y = 0;\n\t\tlet i = Timeline.search(frames, time, 3/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 3/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 3/*ENTRIES*/] - before);\n\t\t\t\tx += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t;\n\t\t\t\ty += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tx = this.getBezierValue(time, i, 1/*VALUE1*/, curveType - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 2/*VALUE2*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\n\t\tswitch (blend) {\n\t\t\tcase MixBlend.setup:\n\t\t\t\tbone.x = bone.data.x + x * alpha;\n\t\t\t\tbone.y = bone.data.y + y * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.first:\n\t\t\tcase MixBlend.replace:\n\t\t\t\tbone.x += (bone.data.x + x - bone.x) * alpha;\n\t\t\t\tbone.y += (bone.data.y + y - bone.y) * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.add:\n\t\t\t\tbone.x += x * alpha;\n\t\t\t\tbone.y += y * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#x}. */\nexport class TranslateXTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.x + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.x = this.getRelativeValue(time, alpha, blend, bone.x, bone.data.x);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#x}. */\nexport class TranslateYTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.y + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.y = this.getRelativeValue(time, alpha, blend, bone.y, bone.data.y);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */\nexport class ScaleTimeline extends CurveTimeline2 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount,\n\t\t\tProperty.scaleX + \"|\" + boneIndex,\n\t\t\tProperty.scaleY + \"|\" + boneIndex\n\t\t);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.scaleX = bone.data.scaleX;\n\t\t\t\t\tbone.scaleY = bone.data.scaleY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tbone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;\n\t\t\t\t\tbone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet x, y;\n\t\tlet i = Timeline.search(frames, time, 3/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 3/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 3/*ENTRIES*/] - before);\n\t\t\t\tx += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t;\n\t\t\t\ty += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tx = this.getBezierValue(time, i, 1/*VALUE1*/, curveType - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 2/*VALUE2*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\t\tx *= bone.data.scaleX;\n\t\ty *= bone.data.scaleY;\n\n\t\tif (alpha == 1) {\n\t\t\tif (blend == MixBlend.add) {\n\t\t\t\tbone.scaleX += x - bone.data.scaleX;\n\t\t\t\tbone.scaleY += y - bone.data.scaleY;\n\t\t\t} else {\n\t\t\t\tbone.scaleX = x;\n\t\t\t\tbone.scaleY = y;\n\t\t\t}\n\t\t} else {\n\t\t\tlet bx = 0, by = 0;\n\t\t\tif (direction == MixDirection.mixOut) {\n\t\t\t\tswitch (blend) {\n\t\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\t\tbx = bone.data.scaleX;\n\t\t\t\t\t\tby = bone.data.scaleY;\n\t\t\t\t\t\tbone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\t\tbx = bone.scaleX;\n\t\t\t\t\t\tby = bone.scaleY;\n\t\t\t\t\t\tbone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.add:\n\t\t\t\t\t\tbone.scaleX += (x - bone.data.scaleX) * alpha;\n\t\t\t\t\t\tbone.scaleY += (y - bone.data.scaleY) * alpha;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch (blend) {\n\t\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\t\tbx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);\n\t\t\t\t\t\tby = Math.abs(bone.data.scaleY) * MathUtils.signum(y);\n\t\t\t\t\t\tbone.scaleX = bx + (x - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (y - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\t\tbx = Math.abs(bone.scaleX) * MathUtils.signum(x);\n\t\t\t\t\t\tby = Math.abs(bone.scaleY) * MathUtils.signum(y);\n\t\t\t\t\t\tbone.scaleX = bx + (x - bx) * alpha;\n\t\t\t\t\t\tbone.scaleY = by + (y - by) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.add:\n\t\t\t\t\t\tbone.scaleX += (x - bone.data.scaleX) * alpha;\n\t\t\t\t\t\tbone.scaleY += (y - bone.data.scaleY) * alpha;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */\nexport class ScaleXTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.scaleX + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.scaleX = this.getScaleValue(time, alpha, blend, direction, bone.scaleX, bone.data.scaleX);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#scaleX)} and {@link Bone#scaleY}. */\nexport class ScaleYTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.scaleY + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.scaleY = this.getScaleValue(time, alpha, blend, direction, bone.scaleY, bone.data.scaleY);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class ShearTimeline extends CurveTimeline2 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount,\n\t\t\tProperty.shearX + \"|\" + boneIndex,\n\t\t\tProperty.shearY + \"|\" + boneIndex\n\t\t);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.shearX = bone.data.shearX;\n\t\t\t\t\tbone.shearY = bone.data.shearY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tbone.shearX += (bone.data.shearX - bone.shearX) * alpha;\n\t\t\t\t\tbone.shearY += (bone.data.shearY - bone.shearY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet x = 0, y = 0;\n\t\tlet i = Timeline.search(frames, time, 3/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 3/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 3/*ENTRIES*/] - before);\n\t\t\t\tx += (frames[i + 3/*ENTRIES*/ + 1/*VALUE1*/] - x) * t;\n\t\t\t\ty += (frames[i + 3/*ENTRIES*/ + 2/*VALUE2*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tx = frames[i + 1/*VALUE1*/];\n\t\t\t\ty = frames[i + 2/*VALUE2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tx = this.getBezierValue(time, i, 1/*VALUE1*/, curveType - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 2/*VALUE2*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\n\t\tswitch (blend) {\n\t\t\tcase MixBlend.setup:\n\t\t\t\tbone.shearX = bone.data.shearX + x * alpha;\n\t\t\t\tbone.shearY = bone.data.shearY + y * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.first:\n\t\t\tcase MixBlend.replace:\n\t\t\t\tbone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;\n\t\t\t\tbone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;\n\t\t\t\tbreak;\n\t\t\tcase MixBlend.add:\n\t\t\t\tbone.shearX += x * alpha;\n\t\t\t\tbone.shearY += y * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class ShearXTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.shearX + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.shearX = this.getRelativeValue(time, alpha, blend, bone.shearX, bone.data.shearX);\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class ShearYTimeline extends CurveTimeline1 implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, boneIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.shearY + \"|\" + boneIndex);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (bone.active) bone.shearY = this.getRelativeValue(time, alpha, blend, bone.shearY, bone.data.shearY);\n\t}\n}\n\nexport class InheritTimeline extends Timeline implements BoneTimeline {\n\tboneIndex = 0;\n\n\tconstructor (frameCount: number, boneIndex: number) {\n\t\tsuper(frameCount, [Property.inherit + \"|\" + boneIndex]);\n\t\tthis.boneIndex = boneIndex;\n\t}\n\n\tpublic getFrameEntries () {\n\t\treturn 2/*ENTRIES*/;\n\t}\n\n\t/** Sets the transform mode for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time The frame time in seconds. */\n\tpublic setFrame (frame: number, time: number, inherit: Inherit) {\n\t\tframe *= 2/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*INHERIT*/] = inherit;\n\t}\n\n\tpublic apply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet bone = skeleton.bones[this.boneIndex];\n\t\tif (!bone.active) return;\n\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) bone.inherit = bone.data.inherit;\n\t\t\treturn;\n\t\t}\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) bone.inherit = bone.data.inherit;\n\t\t\treturn;\n\t\t}\n\t\tbone.inherit = this.frames[Timeline.search(frames, time, 2/*ENTRIES*/) + 1/*INHERIT*/];\n\t}\n}\n\n/** Changes a slot's {@link Slot#color}. */\nexport class RGBATimeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex,\n\t\t\tProperty.alpha + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 5/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number, a: number) {\n\t\tframe *= 5/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t\tthis.frames[frame + 4/*A*/] = a;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet color = slot.color;\n\t\tif (time < frames[0]) {\n\t\t\tlet setup = slot.data.color;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tcolor.setFromColor(setup);\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcolor.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha,\n\t\t\t\t\t\t(setup.a - color.a) * alpha);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0, a = 0;\n\t\tlet i = Timeline.search(frames, time, 5/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 5/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 5/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 5/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 5/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 5/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\ta += (frames[i + 5/*ENTRIES*/ + 4/*A*/] - a) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\ta = this.getBezierValue(time, i, 4/*A*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t}\n\t\tif (alpha == 1)\n\t\t\tcolor.set(r, g, b, a);\n\t\telse {\n\t\t\tif (blend == MixBlend.setup) color.setFromColor(slot.data.color);\n\t\t\tcolor.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#color}. */\nexport class RGBTimeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 4/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, red, green, blue, and alpha for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number) {\n\t\tframe <<= 2;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet color = slot.color;\n\t\tif (time < frames[0]) {\n\t\t\tlet setup = slot.data.color;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tcolor.r = setup.r;\n\t\t\t\t\tcolor.g = setup.g;\n\t\t\t\t\tcolor.b = setup.b;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcolor.r += (setup.r - color.r) * alpha;\n\t\t\t\t\tcolor.g += (setup.g - color.g) * alpha;\n\t\t\t\t\tcolor.b += (setup.b - color.b) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0;\n\t\tlet i = Timeline.search(frames, time, 4/*ENTRIES*/);\n\t\tlet curveType = this.curves[i >> 2];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 4/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 4/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 4/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 4/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t}\n\t\tif (alpha == 1) {\n\t\t\tcolor.r = r;\n\t\t\tcolor.g = g;\n\t\t\tcolor.b = b;\n\t\t} else {\n\t\t\tif (blend == MixBlend.setup) {\n\t\t\t\tlet setup = slot.data.color;\n\t\t\t\tcolor.r = setup.r;\n\t\t\t\tcolor.g = setup.g;\n\t\t\t\tcolor.b = setup.b;\n\t\t\t}\n\t\t\tcolor.r += (r - color.r) * alpha;\n\t\t\tcolor.g += (g - color.g) * alpha;\n\t\t\tcolor.b += (b - color.b) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a bone's local {@link Bone#shearX} and {@link Bone#shearY}. */\nexport class AlphaTimeline extends CurveTimeline1 implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.alpha + \"|\" + slotIndex);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet color = slot.color;\n\t\tif (time < this.frames[0]) {\n\t\t\tlet setup = slot.data.color;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tcolor.a = setup.a;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcolor.a += (setup.a - color.a) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet a = this.getCurveValue(time);\n\t\tif (alpha == 1)\n\t\t\tcolor.a = a;\n\t\telse {\n\t\t\tif (blend == MixBlend.setup) color.a = slot.data.color.a;\n\t\t\tcolor.a += (a - color.a) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#color} and {@link Slot#darkColor} for two color tinting. */\nexport class RGBA2Timeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex,\n\t\t\tProperty.alpha + \"|\" + slotIndex,\n\t\t\tProperty.rgb2 + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 8/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, light, and dark colors for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number, a: number, r2: number, g2: number, b2: number) {\n\t\tframe <<= 3;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t\tthis.frames[frame + 4/*A*/] = a;\n\t\tthis.frames[frame + 5/*R2*/] = r2;\n\t\tthis.frames[frame + 6/*G2*/] = g2;\n\t\tthis.frames[frame + 7/*B2*/] = b2;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet light = slot.color, dark = slot.darkColor!;\n\t\tif (time < frames[0]) {\n\t\t\tlet setupLight = slot.data.color, setupDark = slot.data.darkColor!;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tlight.setFromColor(setupLight);\n\t\t\t\t\tdark.r = setupDark.r;\n\t\t\t\t\tdark.g = setupDark.g;\n\t\t\t\t\tdark.b = setupDark.b;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tlight.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha,\n\t\t\t\t\t\t(setupLight.a - light.a) * alpha);\n\t\t\t\t\tdark.r += (setupDark.r - dark.r) * alpha;\n\t\t\t\t\tdark.g += (setupDark.g - dark.g) * alpha;\n\t\t\t\t\tdark.b += (setupDark.b - dark.b) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;\n\t\tlet i = Timeline.search(frames, time, 8/*ENTRIES*/);\n\t\tlet curveType = this.curves[i >> 3];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tr2 = frames[i + 5/*R2*/];\n\t\t\t\tg2 = frames[i + 6/*G2*/];\n\t\t\t\tb2 = frames[i + 7/*B2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 8/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 8/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 8/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 8/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\ta += (frames[i + 8/*ENTRIES*/ + 4/*A*/] - a) * t;\n\t\t\t\tr2 += (frames[i + 8/*ENTRIES*/ + 5/*R2*/] - r2) * t;\n\t\t\t\tg2 += (frames[i + 8/*ENTRIES*/ + 6/*G2*/] - g2) * t;\n\t\t\t\tb2 += (frames[i + 8/*ENTRIES*/ + 7/*B2*/] - b2) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\ta = frames[i + 4/*A*/];\n\t\t\t\tr2 = frames[i + 5/*R2*/];\n\t\t\t\tg2 = frames[i + 6/*G2*/];\n\t\t\t\tb2 = frames[i + 7/*B2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\ta = this.getBezierValue(time, i, 4/*A*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t\t\tr2 = this.getBezierValue(time, i, 5/*R2*/, curveType + 18/*BEZIER_SIZE*/ * 4 - 2/*BEZIER*/);\n\t\t\t\tg2 = this.getBezierValue(time, i, 6/*G2*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/);\n\t\t\t\tb2 = this.getBezierValue(time, i, 7/*B2*/, curveType + 18/*BEZIER_SIZE*/ * 6 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (alpha == 1) {\n\t\t\tlight.set(r, g, b, a);\n\t\t\tdark.r = r2;\n\t\t\tdark.g = g2;\n\t\t\tdark.b = b2;\n\t\t} else {\n\t\t\tif (blend == MixBlend.setup) {\n\t\t\t\tlight.setFromColor(slot.data.color);\n\t\t\t\tlet setupDark = slot.data.darkColor!;\n\t\t\t\tdark.r = setupDark.r;\n\t\t\t\tdark.g = setupDark.g;\n\t\t\t\tdark.b = setupDark.b;\n\t\t\t}\n\t\t\tlight.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);\n\t\t\tdark.r += (r2 - dark.r) * alpha;\n\t\t\tdark.g += (g2 - dark.g) * alpha;\n\t\t\tdark.b += (b2 - dark.b) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#color} and {@link Slot#darkColor} for two color tinting. */\nexport class RGB2Timeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.rgb + \"|\" + slotIndex,\n\t\t\tProperty.rgb2 + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 7/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, light, and dark colors for the specified key frame. */\n\tsetFrame (frame: number, time: number, r: number, g: number, b: number, r2: number, g2: number, b2: number) {\n\t\tframe *= 7/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*R*/] = r;\n\t\tthis.frames[frame + 2/*G*/] = g;\n\t\tthis.frames[frame + 3/*B*/] = b;\n\t\tthis.frames[frame + 4/*R2*/] = r2;\n\t\tthis.frames[frame + 5/*G2*/] = g2;\n\t\tthis.frames[frame + 6/*B2*/] = b2;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tlet frames = this.frames;\n\t\tlet light = slot.color, dark = slot.darkColor!;\n\t\tif (time < frames[0]) {\n\t\t\tlet setupLight = slot.data.color, setupDark = slot.data.darkColor!;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tlight.r = setupLight.r;\n\t\t\t\t\tlight.g = setupLight.g;\n\t\t\t\t\tlight.b = setupLight.b;\n\t\t\t\t\tdark.r = setupDark.r;\n\t\t\t\t\tdark.g = setupDark.g;\n\t\t\t\t\tdark.b = setupDark.b;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tlight.r += (setupLight.r - light.r) * alpha;\n\t\t\t\t\tlight.g += (setupLight.g - light.g) * alpha;\n\t\t\t\t\tlight.b += (setupLight.b - light.b) * alpha;\n\t\t\t\t\tdark.r += (setupDark.r - dark.r) * alpha;\n\t\t\t\t\tdark.g += (setupDark.g - dark.g) * alpha;\n\t\t\t\t\tdark.b += (setupDark.b - dark.b) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;\n\t\tlet i = Timeline.search(frames, time, 7/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 7/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tr2 = frames[i + 4/*R2*/];\n\t\t\t\tg2 = frames[i + 5/*G2*/];\n\t\t\t\tb2 = frames[i + 6/*B2*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 7/*ENTRIES*/] - before);\n\t\t\t\tr += (frames[i + 7/*ENTRIES*/ + 1/*R*/] - r) * t;\n\t\t\t\tg += (frames[i + 7/*ENTRIES*/ + 2/*G*/] - g) * t;\n\t\t\t\tb += (frames[i + 7/*ENTRIES*/ + 3/*B*/] - b) * t;\n\t\t\t\tr2 += (frames[i + 7/*ENTRIES*/ + 4/*R2*/] - r2) * t;\n\t\t\t\tg2 += (frames[i + 7/*ENTRIES*/ + 5/*G2*/] - g2) * t;\n\t\t\t\tb2 += (frames[i + 7/*ENTRIES*/ + 6/*B2*/] - b2) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tr = frames[i + 1/*R*/];\n\t\t\t\tg = frames[i + 2/*G*/];\n\t\t\t\tb = frames[i + 3/*B*/];\n\t\t\t\tr2 = frames[i + 4/*R2*/];\n\t\t\t\tg2 = frames[i + 5/*G2*/];\n\t\t\t\tb2 = frames[i + 6/*B2*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = this.getBezierValue(time, i, 1/*R*/, curveType - 2/*BEZIER*/);\n\t\t\t\tg = this.getBezierValue(time, i, 2/*G*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\tb = this.getBezierValue(time, i, 3/*B*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\tr2 = this.getBezierValue(time, i, 4/*R2*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t\t\tg2 = this.getBezierValue(time, i, 5/*G2*/, curveType + 18/*BEZIER_SIZE*/ * 4 - 2/*BEZIER*/);\n\t\t\t\tb2 = this.getBezierValue(time, i, 6/*B2*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (alpha == 1) {\n\t\t\tlight.r = r;\n\t\t\tlight.g = g;\n\t\t\tlight.b = b;\n\t\t\tdark.r = r2;\n\t\t\tdark.g = g2;\n\t\t\tdark.b = b2;\n\t\t} else {\n\t\t\tif (blend == MixBlend.setup) {\n\t\t\t\tlet setupLight = slot.data.color, setupDark = slot.data.darkColor!;\n\t\t\t\tlight.r = setupLight.r;\n\t\t\t\tlight.g = setupLight.g;\n\t\t\t\tlight.b = setupLight.b;\n\t\t\t\tdark.r = setupDark.r;\n\t\t\t\tdark.g = setupDark.g;\n\t\t\t\tdark.b = setupDark.b;\n\t\t\t}\n\t\t\tlight.r += (r - light.r) * alpha;\n\t\t\tlight.g += (g - light.g) * alpha;\n\t\t\tlight.b += (b - light.b) * alpha;\n\t\t\tdark.r += (r2 - dark.r) * alpha;\n\t\t\tdark.g += (g2 - dark.g) * alpha;\n\t\t\tdark.b += (b2 - dark.b) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#attachment}. */\nexport class AttachmentTimeline extends Timeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\t/** The attachment name for each key frame. May contain null values to clear the attachment. */\n\tattachmentNames: Array;\n\n\tconstructor (frameCount: number, slotIndex: number) {\n\t\tsuper(frameCount, [\n\t\t\tProperty.attachment + \"|\" + slotIndex\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.attachmentNames = new Array(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the attachment name for the specified key frame. */\n\tsetFrame (frame: number, time: number, attachmentName: string | null) {\n\t\tthis.frames[frame] = time;\n\t\tthis.attachmentNames[frame] = attachmentName;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) this.setAttachment(skeleton, slot, slot.data.attachmentName);\n\t\t\treturn;\n\t\t}\n\n\t\tif (time < this.frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) this.setAttachment(skeleton, slot, slot.data.attachmentName);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]);\n\t}\n\n\tsetAttachment (skeleton: Skeleton, slot: Slot, attachmentName: string | null) {\n\t\tslot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName));\n\t}\n}\n\n/** Changes a slot's {@link Slot#deform} to deform a {@link VertexAttachment}. */\nexport class DeformTimeline extends CurveTimeline implements SlotTimeline {\n\tslotIndex = 0;\n\n\t/** The attachment that will be deformed. */\n\tattachment: VertexAttachment;\n\n\t/** The vertices for each key frame. */\n\tvertices: Array;\n\n\tconstructor (frameCount: number, bezierCount: number, slotIndex: number, attachment: VertexAttachment) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.deform + \"|\" + slotIndex + \"|\" + attachment.id\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.attachment = attachment;\n\t\tthis.vertices = new Array(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the vertices for the specified key frame.\n\t * @param vertices Vertex positions for an unweighted VertexAttachment, or deform offsets if it has weights. */\n\tsetFrame (frame: number, time: number, vertices: NumberArrayLike) {\n\t\tthis.frames[frame] = time;\n\t\tthis.vertices[frame] = vertices;\n\t}\n\n\t/** @param value1 Ignored (0 is used for a deform timeline).\n\t * @param value2 Ignored (1 is used for a deform timeline). */\n\tsetBezier (bezier: number, frame: number, value: number, time1: number, value1: number, cx1: number, cy1: number, cx2: number,\n\t\tcy2: number, time2: number, value2: number) {\n\t\tlet curves = this.curves;\n\t\tlet i = this.getFrameCount() + bezier * 18/*BEZIER_SIZE*/;\n\t\tif (value == 0) curves[frame] = 2/*BEZIER*/ + i;\n\t\tlet tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06;\n\t\tlet dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = (cy1 - cy2 + 0.33333333) * 0.018;\n\t\tlet ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;\n\t\tlet dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667;\n\t\tlet x = time1 + dx, y = dy;\n\t\tfor (let n = i + 18/*BEZIER_SIZE*/; i < n; i += 2) {\n\t\t\tcurves[i] = x;\n\t\t\tcurves[i + 1] = y;\n\t\t\tdx += ddx;\n\t\t\tdy += ddy;\n\t\t\tddx += dddx;\n\t\t\tddy += dddy;\n\t\t\tx += dx;\n\t\t\ty += dy;\n\t\t}\n\t}\n\n\tgetCurvePercent (time: number, frame: number) {\n\t\tlet curves = this.curves;\n\t\tlet i = curves[frame];\n\t\tswitch (i) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet x = this.frames[frame];\n\t\t\t\treturn (time - x) / (this.frames[frame + this.getFrameEntries()] - x);\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\treturn 0;\n\t\t}\n\t\ti -= 2/*BEZIER*/;\n\t\tif (curves[i] > time) {\n\t\t\tlet x = this.frames[frame];\n\t\t\treturn curves[i + 1] * (time - x) / (curves[i] - x);\n\t\t}\n\t\tlet n = i + 18/*BEZIER_SIZE*/;\n\t\tfor (i += 2; i < n; i += 2) {\n\t\t\tif (curves[i] >= time) {\n\t\t\t\tlet x = curves[i - 2], y = curves[i - 1];\n\t\t\t\treturn y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);\n\t\t\t}\n\t\t}\n\t\tlet x = curves[n - 2], y = curves[n - 1];\n\t\treturn y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x);\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot: Slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\t\tlet slotAttachment: Attachment | null = slot.getAttachment();\n\t\tif (!slotAttachment) return;\n\t\tif (!(slotAttachment instanceof VertexAttachment) || (slotAttachment).timelineAttachment != this.attachment) return;\n\n\t\tlet deform: Array = slot.deform;\n\t\tif (deform.length == 0) blend = MixBlend.setup;\n\n\t\tlet vertices = this.vertices;\n\t\tlet vertexCount = vertices[0].length;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tdeform.length = 0;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tif (alpha == 1) {\n\t\t\t\t\t\tdeform.length = 0;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdeform.length = vertexCount;\n\t\t\t\t\tlet vertexAttachment = slotAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (var i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += (setupVertices[i] - deform[i]) * alpha;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets.\n\t\t\t\t\t\talpha = 1 - alpha;\n\t\t\t\t\t\tfor (var i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] *= alpha;\n\t\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tdeform.length = vertexCount;\n\t\tif (time >= frames[frames.length - 1]) {\n\t\t\tlet lastVertices = vertices[frames.length - 1];\n\t\t\tif (alpha == 1) {\n\t\t\t\tif (blend == MixBlend.add) {\n\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += lastVertices[i] - setupVertices[i];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += lastVertices[i];\n\t\t\t\t\t}\n\t\t\t\t} else\n\t\t\t\t\tUtils.arrayCopy(lastVertices, 0, deform, 0, vertexCount);\n\t\t\t} else {\n\t\t\t\tswitch (blend) {\n\t\t\t\t\tcase MixBlend.setup: {\n\t\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\t\tlet setup = setupVertices[i];\n\t\t\t\t\t\t\t\tdeform[i] = setup + (lastVertices[i] - setup) * alpha;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\t\tdeform[i] = lastVertices[i] * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\tdeform[i] += (lastVertices[i] - deform[i]) * alpha;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MixBlend.add:\n\t\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\t\tdeform[i] += (lastVertices[i] - setupVertices[i]) * alpha;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\t\t\t\t\t\tdeform[i] += lastVertices[i] * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Interpolate between the previous frame and the current frame.\n\t\tlet frame = Timeline.search1(frames, time);\n\t\tlet percent = this.getCurvePercent(time, frame);\n\t\tlet prevVertices = vertices[frame];\n\t\tlet nextVertices = vertices[frame + 1];\n\n\t\tif (alpha == 1) {\n\t\t\tif (blend == MixBlend.add) {\n\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\tdeform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\tdeform[i] += prev + (nextVertices[i] - prev) * percent;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\tdeform[i] = prev + (nextVertices[i] - prev) * percent;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup: {\n\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i], setup = setupVertices[i];\n\t\t\t\t\t\t\tdeform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\t\tdeform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase MixBlend.first:\n\t\t\t\tcase MixBlend.replace:\n\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\tdeform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MixBlend.add:\n\t\t\t\t\tlet vertexAttachment = slotAttachment as VertexAttachment;\n\t\t\t\t\tif (!vertexAttachment.bones) {\n\t\t\t\t\t\t// Unweighted vertex positions, with alpha.\n\t\t\t\t\t\tlet setupVertices = vertexAttachment.vertices;\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\t\tdeform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Weighted deform offsets, with alpha.\n\t\t\t\t\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\t\t\t\t\tlet prev = prevVertices[i];\n\t\t\t\t\t\t\tdeform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Fires an {@link Event} when specific animation times are reached. */\nexport class EventTimeline extends Timeline {\n\tstatic propertyIds = [\"\" + Property.event];\n\n\t/** The event for each key frame. */\n\tevents: Array;\n\n\tconstructor (frameCount: number) {\n\t\tsuper(frameCount, EventTimeline.propertyIds);\n\n\t\tthis.events = new Array(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the event for the specified key frame. */\n\tsetFrame (frame: number, event: Event) {\n\t\tthis.frames[frame] = event.time;\n\t\tthis.events[frame] = event;\n\t}\n\n\t/** Fires events for frames > `lastTime` and <= `time`. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (!firedEvents) return;\n\n\t\tlet frames = this.frames;\n\t\tlet frameCount = this.frames.length;\n\n\t\tif (lastTime > time) { // Apply after lastTime for looped animations.\n\t\t\tthis.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction);\n\t\t\tlastTime = -1;\n\t\t} else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame.\n\t\t\treturn;\n\t\tif (time < frames[0]) return;\n\n\t\tlet i = 0;\n\t\tif (lastTime < frames[0])\n\t\t\ti = 0;\n\t\telse {\n\t\t\ti = Timeline.search1(frames, lastTime) + 1;\n\t\t\tlet frameTime = frames[i];\n\t\t\twhile (i > 0) { // Fire multiple events with the same frame.\n\t\t\t\tif (frames[i - 1] != frameTime) break;\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t\tfor (; i < frameCount && time >= frames[i]; i++)\n\t\t\tfiredEvents.push(this.events[i]);\n\t}\n}\n\n/** Changes a skeleton's {@link Skeleton#drawOrder}. */\nexport class DrawOrderTimeline extends Timeline {\n\tstatic propertyIds = [\"\" + Property.drawOrder];\n\n\t/** The draw order for each key frame. See {@link #setFrame(int, float, int[])}. */\n\tdrawOrders: Array | null>;\n\n\tconstructor (frameCount: number) {\n\t\tsuper(frameCount, DrawOrderTimeline.propertyIds);\n\t\tthis.drawOrders = new Array | null>(frameCount);\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time in seconds and the draw order for the specified key frame.\n\t * @param drawOrder For each slot in {@link Skeleton#slots}, the index of the new draw order. May be null to use setup pose\n\t * draw order. */\n\tsetFrame (frame: number, time: number, drawOrder: Array | null) {\n\t\tthis.frames[frame] = time;\n\t\tthis.drawOrders[frame] = drawOrder;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);\n\t\t\treturn;\n\t\t}\n\n\t\tif (time < this.frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);\n\t\t\treturn;\n\t\t}\n\n\t\tlet idx = Timeline.search1(this.frames, time);\n\t\tlet drawOrderToSetupIndex = this.drawOrders[idx];\n\t\tif (!drawOrderToSetupIndex)\n\t\t\tUtils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);\n\t\telse {\n\t\t\tlet drawOrder: Array = skeleton.drawOrder;\n\t\t\tlet slots: Array = skeleton.slots;\n\t\t\tfor (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++)\n\t\t\t\tdrawOrder[i] = slots[drawOrderToSetupIndex[i]];\n\t\t}\n\t}\n}\n\n/** Changes an IK constraint's {@link IkConstraint#mix}, {@link IkConstraint#softness},\n * {@link IkConstraint#bendDirection}, {@link IkConstraint#stretch}, and {@link IkConstraint#compress}. */\nexport class IkConstraintTimeline extends CurveTimeline {\n\t/** The index of the IK constraint in {@link Skeleton#getIkConstraints()} that will be changed when this timeline is applied */\n\tconstraintIndex: number = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, ikConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.ikConstraint + \"|\" + ikConstraintIndex\n\t\t]);\n\t\tthis.constraintIndex = ikConstraintIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 6/*ENTRIES*/;\n\t}\n\n\t/** Sets the time in seconds, mix, softness, bend direction, compress, and stretch for the specified key frame. */\n\tsetFrame (frame: number, time: number, mix: number, softness: number, bendDirection: number, compress: boolean, stretch: boolean) {\n\t\tframe *= 6/*ENTRIES*/;\n\t\tthis.frames[frame] = time;\n\t\tthis.frames[frame + 1/*MIX*/] = mix;\n\t\tthis.frames[frame + 2/*SOFTNESS*/] = softness;\n\t\tthis.frames[frame + 3/*BEND_DIRECTION*/] = bendDirection;\n\t\tthis.frames[frame + 4/*COMPRESS*/] = compress ? 1 : 0;\n\t\tthis.frames[frame + 5/*STRETCH*/] = stretch ? 1 : 0;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: IkConstraint = skeleton.ikConstraints[this.constraintIndex];\n\t\tif (!constraint.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tconstraint.mix = constraint.data.mix;\n\t\t\t\t\tconstraint.softness = constraint.data.softness;\n\t\t\t\t\tconstraint.bendDirection = constraint.data.bendDirection;\n\t\t\t\t\tconstraint.compress = constraint.data.compress;\n\t\t\t\t\tconstraint.stretch = constraint.data.stretch;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tconstraint.mix += (constraint.data.mix - constraint.mix) * alpha;\n\t\t\t\t\tconstraint.softness += (constraint.data.softness - constraint.softness) * alpha;\n\t\t\t\t\tconstraint.bendDirection = constraint.data.bendDirection;\n\t\t\t\t\tconstraint.compress = constraint.data.compress;\n\t\t\t\t\tconstraint.stretch = constraint.data.stretch;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet mix = 0, softness = 0;\n\t\tlet i = Timeline.search(frames, time, 6/*ENTRIES*/)\n\t\tlet curveType = this.curves[i / 6/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\tmix = frames[i + 1/*MIX*/];\n\t\t\t\tsoftness = frames[i + 2/*SOFTNESS*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 6/*ENTRIES*/] - before);\n\t\t\t\tmix += (frames[i + 6/*ENTRIES*/ + 1/*MIX*/] - mix) * t;\n\t\t\t\tsoftness += (frames[i + 6/*ENTRIES*/ + 2/*SOFTNESS*/] - softness) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\tmix = frames[i + 1/*MIX*/];\n\t\t\t\tsoftness = frames[i + 2/*SOFTNESS*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tmix = this.getBezierValue(time, i, 1/*MIX*/, curveType - 2/*BEZIER*/);\n\t\t\t\tsoftness = this.getBezierValue(time, i, 2/*SOFTNESS*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (blend == MixBlend.setup) {\n\t\t\tconstraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha;\n\t\t\tconstraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha;\n\n\t\t\tif (direction == MixDirection.mixOut) {\n\t\t\t\tconstraint.bendDirection = constraint.data.bendDirection;\n\t\t\t\tconstraint.compress = constraint.data.compress;\n\t\t\t\tconstraint.stretch = constraint.data.stretch;\n\t\t\t} else {\n\t\t\t\tconstraint.bendDirection = frames[i + 3/*BEND_DIRECTION*/];\n\t\t\t\tconstraint.compress = frames[i + 4/*COMPRESS*/] != 0;\n\t\t\t\tconstraint.stretch = frames[i + 5/*STRETCH*/] != 0;\n\t\t\t}\n\t\t} else {\n\t\t\tconstraint.mix += (mix - constraint.mix) * alpha;\n\t\t\tconstraint.softness += (softness - constraint.softness) * alpha;\n\t\t\tif (direction == MixDirection.mixIn) {\n\t\t\t\tconstraint.bendDirection = frames[i + 3/*BEND_DIRECTION*/];\n\t\t\t\tconstraint.compress = frames[i + 4/*COMPRESS*/] != 0;\n\t\t\t\tconstraint.stretch = frames[i + 5/*STRETCH*/] != 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Changes a transform constraint's {@link TransformConstraint#rotateMix}, {@link TransformConstraint#translateMix},\n * {@link TransformConstraint#scaleMix}, and {@link TransformConstraint#shearMix}. */\nexport class TransformConstraintTimeline extends CurveTimeline {\n\t/** The index of the transform constraint slot in {@link Skeleton#transformConstraints} that will be changed. */\n\tconstraintIndex: number = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, transformConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.transformConstraint + \"|\" + transformConstraintIndex\n\t\t]);\n\t\tthis.constraintIndex = transformConstraintIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 7/*ENTRIES*/;\n\t}\n\n\t/** The time in seconds, rotate mix, translate mix, scale mix, and shear mix for the specified key frame. */\n\tsetFrame (frame: number, time: number, mixRotate: number, mixX: number, mixY: number, mixScaleX: number, mixScaleY: number,\n\t\tmixShearY: number) {\n\t\tlet frames = this.frames;\n\t\tframe *= 7/*ENTRIES*/;\n\t\tframes[frame] = time;\n\t\tframes[frame + 1/*ROTATE*/] = mixRotate;\n\t\tframes[frame + 2/*X*/] = mixX;\n\t\tframes[frame + 3/*Y*/] = mixY;\n\t\tframes[frame + 4/*SCALEX*/] = mixScaleX;\n\t\tframes[frame + 5/*SCALEY*/] = mixScaleY;\n\t\tframes[frame + 6/*SHEARY*/] = mixShearY;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: TransformConstraint = skeleton.transformConstraints[this.constraintIndex];\n\t\tif (!constraint.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tlet data = constraint.data;\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tconstraint.mixRotate = data.mixRotate;\n\t\t\t\t\tconstraint.mixX = data.mixX;\n\t\t\t\t\tconstraint.mixY = data.mixY;\n\t\t\t\t\tconstraint.mixScaleX = data.mixScaleX;\n\t\t\t\t\tconstraint.mixScaleY = data.mixScaleY;\n\t\t\t\t\tconstraint.mixShearY = data.mixShearY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tconstraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;\n\t\t\t\t\tconstraint.mixX += (data.mixX - constraint.mixX) * alpha;\n\t\t\t\t\tconstraint.mixY += (data.mixY - constraint.mixY) * alpha;\n\t\t\t\t\tconstraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha;\n\t\t\t\t\tconstraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha;\n\t\t\t\t\tconstraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet rotate, x, y, scaleX, scaleY, shearY;\n\t\tlet i = Timeline.search(frames, time, 7/*ENTRIES*/);\n\t\tlet curveType = this.curves[i / 7/*ENTRIES*/];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tscaleX = frames[i + 4/*SCALEX*/];\n\t\t\t\tscaleY = frames[i + 5/*SCALEY*/];\n\t\t\t\tshearY = frames[i + 6/*SHEARY*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 7/*ENTRIES*/] - before);\n\t\t\t\trotate += (frames[i + 7/*ENTRIES*/ + 1/*ROTATE*/] - rotate) * t;\n\t\t\t\tx += (frames[i + 7/*ENTRIES*/ + 2/*X*/] - x) * t;\n\t\t\t\ty += (frames[i + 7/*ENTRIES*/ + 3/*Y*/] - y) * t;\n\t\t\t\tscaleX += (frames[i + 7/*ENTRIES*/ + 4/*SCALEX*/] - scaleX) * t;\n\t\t\t\tscaleY += (frames[i + 7/*ENTRIES*/ + 5/*SCALEY*/] - scaleY) * t;\n\t\t\t\tshearY += (frames[i + 7/*ENTRIES*/ + 6/*SHEARY*/] - shearY) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tscaleX = frames[i + 4/*SCALEX*/];\n\t\t\t\tscaleY = frames[i + 5/*SCALEY*/];\n\t\t\t\tshearY = frames[i + 6/*SHEARY*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\trotate = this.getBezierValue(time, i, 1/*ROTATE*/, curveType - 2/*BEZIER*/);\n\t\t\t\tx = this.getBezierValue(time, i, 2/*X*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 3/*Y*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t\t\tscaleX = this.getBezierValue(time, i, 4/*SCALEX*/, curveType + 18/*BEZIER_SIZE*/ * 3 - 2/*BEZIER*/);\n\t\t\t\tscaleY = this.getBezierValue(time, i, 5/*SCALEY*/, curveType + 18/*BEZIER_SIZE*/ * 4 - 2/*BEZIER*/);\n\t\t\t\tshearY = this.getBezierValue(time, i, 6/*SHEARY*/, curveType + 18/*BEZIER_SIZE*/ * 5 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (blend == MixBlend.setup) {\n\t\t\tlet data = constraint.data;\n\t\t\tconstraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;\n\t\t\tconstraint.mixX = data.mixX + (x - data.mixX) * alpha;\n\t\t\tconstraint.mixY = data.mixY + (y - data.mixY) * alpha;\n\t\t\tconstraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha;\n\t\t\tconstraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha;\n\t\t\tconstraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha;\n\t\t} else {\n\t\t\tconstraint.mixRotate += (rotate - constraint.mixRotate) * alpha;\n\t\t\tconstraint.mixX += (x - constraint.mixX) * alpha;\n\t\t\tconstraint.mixY += (y - constraint.mixY) * alpha;\n\t\t\tconstraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha;\n\t\t\tconstraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha;\n\t\t\tconstraint.mixShearY += (shearY - constraint.mixShearY) * alpha;\n\t\t}\n\t}\n}\n\n/** Changes a path constraint's {@link PathConstraint#position}. */\nexport class PathConstraintPositionTimeline extends CurveTimeline1 {\n\t/** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is\n\t * applied. */\n\tconstraintIndex: number = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.pathConstraintPosition + \"|\" + pathConstraintIndex);\n\t\tthis.constraintIndex = pathConstraintIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PathConstraint = skeleton.pathConstraints[this.constraintIndex];\n\t\tif (constraint.active)\n\t\t\tconstraint.position = this.getAbsoluteValue(time, alpha, blend, constraint.position, constraint.data.position);\n\t}\n}\n\n/** Changes a path constraint's {@link PathConstraint#spacing}. */\nexport class PathConstraintSpacingTimeline extends CurveTimeline1 {\n\t/** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is\n\t * applied. */\n\tconstraintIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, Property.pathConstraintSpacing + \"|\" + pathConstraintIndex);\n\t\tthis.constraintIndex = pathConstraintIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PathConstraint = skeleton.pathConstraints[this.constraintIndex];\n\t\tif (constraint.active)\n\t\t\tconstraint.spacing = this.getAbsoluteValue(time, alpha, blend, constraint.spacing, constraint.data.spacing);\n\t}\n}\n\n/** Changes a transform constraint's {@link PathConstraint#getMixRotate()}, {@link PathConstraint#getMixX()}, and\n * {@link PathConstraint#getMixY()}. */\nexport class PathConstraintMixTimeline extends CurveTimeline {\n\t/** The index of the path constraint in {@link Skeleton#getPathConstraints()} that will be changed when this timeline is\n\t * applied. */\n\tconstraintIndex = 0;\n\n\tconstructor (frameCount: number, bezierCount: number, pathConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, [\n\t\t\tProperty.pathConstraintMix + \"|\" + pathConstraintIndex\n\t\t]);\n\t\tthis.constraintIndex = pathConstraintIndex;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn 4/*ENTRIES*/;\n\t}\n\n\tsetFrame (frame: number, time: number, mixRotate: number, mixX: number, mixY: number) {\n\t\tlet frames = this.frames;\n\t\tframe <<= 2;\n\t\tframes[frame] = time;\n\t\tframes[frame + 1/*ROTATE*/] = mixRotate;\n\t\tframes[frame + 2/*X*/] = mixX;\n\t\tframes[frame + 3/*Y*/] = mixY;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PathConstraint = skeleton.pathConstraints[this.constraintIndex];\n\t\tif (!constraint.active) return;\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tconstraint.mixRotate = constraint.data.mixRotate;\n\t\t\t\t\tconstraint.mixX = constraint.data.mixX;\n\t\t\t\t\tconstraint.mixY = constraint.data.mixY;\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tconstraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha;\n\t\t\t\t\tconstraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha;\n\t\t\t\t\tconstraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tlet rotate, x, y;\n\t\tlet i = Timeline.search(frames, time, 4/*ENTRIES*/);\n\t\tlet curveType = this.curves[i >> 2];\n\t\tswitch (curveType) {\n\t\t\tcase 0/*LINEAR*/:\n\t\t\t\tlet before = frames[i];\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tlet t = (time - before) / (frames[i + 4/*ENTRIES*/] - before);\n\t\t\t\trotate += (frames[i + 4/*ENTRIES*/ + 1/*ROTATE*/] - rotate) * t;\n\t\t\t\tx += (frames[i + 4/*ENTRIES*/ + 2/*X*/] - x) * t;\n\t\t\t\ty += (frames[i + 4/*ENTRIES*/ + 3/*Y*/] - y) * t;\n\t\t\t\tbreak;\n\t\t\tcase 1/*STEPPED*/:\n\t\t\t\trotate = frames[i + 1/*ROTATE*/];\n\t\t\t\tx = frames[i + 2/*X*/];\n\t\t\t\ty = frames[i + 3/*Y*/];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\trotate = this.getBezierValue(time, i, 1/*ROTATE*/, curveType - 2/*BEZIER*/);\n\t\t\t\tx = this.getBezierValue(time, i, 2/*X*/, curveType + 18/*BEZIER_SIZE*/ - 2/*BEZIER*/);\n\t\t\t\ty = this.getBezierValue(time, i, 3/*Y*/, curveType + 18/*BEZIER_SIZE*/ * 2 - 2/*BEZIER*/);\n\t\t}\n\n\t\tif (blend == MixBlend.setup) {\n\t\t\tlet data = constraint.data;\n\t\t\tconstraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;\n\t\t\tconstraint.mixX = data.mixX + (x - data.mixX) * alpha;\n\t\t\tconstraint.mixY = data.mixY + (y - data.mixY) * alpha;\n\t\t} else {\n\t\t\tconstraint.mixRotate += (rotate - constraint.mixRotate) * alpha;\n\t\t\tconstraint.mixX += (x - constraint.mixX) * alpha;\n\t\t\tconstraint.mixY += (y - constraint.mixY) * alpha;\n\t\t}\n\t}\n}\n\n/** The base class for most {@link PhysicsConstraint} timelines. */\nexport abstract class PhysicsConstraintTimeline extends CurveTimeline1 {\n\t/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be changed when this timeline\n\t * is applied, or -1 if all physics constraints in the skeleton will be changed. */\n\tconstraintIndex = 0;\n\n\t/** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number, property: number) {\n\t\tsuper(frameCount, bezierCount, property + \"|\" + physicsConstraintIndex);\n\t\tthis.constraintIndex = physicsConstraintIndex;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet constraint: PhysicsConstraint;\n\t\tif (this.constraintIndex == -1) {\n\t\t\tconst value = time >= this.frames[0] ? this.getCurveValue(time) : 0;\n\n\t\t\tfor (const constraint of skeleton.physicsConstraints) {\n\t\t\t\tif (constraint.active && this.global(constraint.data))\n\t\t\t\t\tthis.set(constraint, this.getAbsoluteValue2(time, alpha, blend, this.get(constraint), this.setup(constraint), value));\n\t\t\t}\n\t\t} else {\n\t\t\tconstraint = skeleton.physicsConstraints[this.constraintIndex];\n\t\t\tif (constraint.active) this.set(constraint, this.getAbsoluteValue(time, alpha, blend, this.get(constraint), this.setup(constraint)));\n\t\t}\n\t}\n\n\tabstract setup (constraint: PhysicsConstraint): number;\n\n\tabstract get (constraint: PhysicsConstraint): number;\n\n\tabstract set (constraint: PhysicsConstraint, value: number): void;\n\n\tabstract global (constraint: PhysicsConstraintData): boolean;\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getInertia()}. */\nexport class PhysicsConstraintInertiaTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintInertia);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.inertia;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.inertia;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.inertia = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.inertiaGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getStrength()}. */\nexport class PhysicsConstraintStrengthTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintStrength);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.strength;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.strength;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.strength = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.strengthGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getDamping()}. */\nexport class PhysicsConstraintDampingTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintDamping);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.damping;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.damping;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.damping = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.dampingGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getMassInverse()}. The timeline values are not inverted. */\nexport class PhysicsConstraintMassTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMass);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn 1 / constraint.data.massInverse;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn 1 / constraint.massInverse;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.massInverse = 1 / value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.massGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getWind()}. */\nexport class PhysicsConstraintWindTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintWind);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.wind;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.wind;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.wind = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.windGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getGravity()}. */\nexport class PhysicsConstraintGravityTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintGravity);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.gravity;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.gravity;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.gravity = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.gravityGlobal;\n\t}\n}\n\n/** Changes a physics constraint's {@link PhysicsConstraint#getMix()}. */\nexport class PhysicsConstraintMixTimeline extends PhysicsConstraintTimeline {\n\tconstructor (frameCount: number, bezierCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, bezierCount, physicsConstraintIndex, Property.physicsConstraintMix);\n\t}\n\n\tsetup (constraint: PhysicsConstraint): number {\n\t\treturn constraint.data.mix;\n\t}\n\n\tget (constraint: PhysicsConstraint): number {\n\t\treturn constraint.mix;\n\t}\n\n\tset (constraint: PhysicsConstraint, value: number): void {\n\t\tconstraint.mix = value;\n\t}\n\n\tglobal (constraint: PhysicsConstraintData): boolean {\n\t\treturn constraint.mixGlobal;\n\t}\n}\n\n/** Resets a physics constraint when specific animation times are reached. */\nexport class PhysicsConstraintResetTimeline extends Timeline {\n\tprivate static propertyIds: string[] = [Property.physicsConstraintReset.toString()];\n\n\t/** The index of the physics constraint in {@link Skeleton#getPhysicsConstraints()} that will be reset when this timeline is\n\t* applied, or -1 if all physics constraints in the skeleton will be reset. */\n\tconstraintIndex: number;\n\n\t/** @param physicsConstraintIndex -1 for all physics constraints in the skeleton. */\n\tconstructor (frameCount: number, physicsConstraintIndex: number) {\n\t\tsuper(frameCount, PhysicsConstraintResetTimeline.propertyIds);\n\t\tthis.constraintIndex = physicsConstraintIndex;\n\t}\n\n\tgetFrameCount () {\n\t\treturn this.frames.length;\n\t}\n\n\t/** Sets the time for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive. */\n\tsetFrame (frame: number, time: number) {\n\t\tthis.frames[frame] = time;\n\t}\n\n\t/** Resets the physics constraint when frames > lastTime and <= time. */\n\tapply (skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\n\t\tlet constraint: PhysicsConstraint | undefined;\n\t\tif (this.constraintIndex != -1) {\n\t\t\tconstraint = skeleton.physicsConstraints[this.constraintIndex];\n\t\t\tif (!constraint.active) return;\n\t\t}\n\n\t\tconst frames = this.frames;\n\n\t\tif (lastTime > time) { // Apply after lastTime for looped animations.\n\t\t\tthis.apply(skeleton, lastTime, Number.MAX_VALUE, [], alpha, blend, direction);\n\t\t\tlastTime = -1;\n\t\t} else if (lastTime >= frames[frames.length - 1]) // Last time is after last frame.\n\t\t\treturn;\n\t\tif (time < frames[0]) return;\n\n\t\tif (lastTime < frames[0] || time >= frames[Timeline.search1(frames, lastTime) + 1]) {\n\t\t\tif (constraint != null)\n\t\t\t\tconstraint.reset();\n\t\t\telse {\n\t\t\t\tfor (const constraint of skeleton.physicsConstraints) {\n\t\t\t\t\tif (constraint.active) constraint.reset();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Changes a slot's {@link Slot#getSequenceIndex()} for an attachment's {@link Sequence}. */\nexport class SequenceTimeline extends Timeline implements SlotTimeline {\n\tstatic ENTRIES = 3;\n\tstatic MODE = 1;\n\tstatic DELAY = 2;\n\n\tslotIndex: number;\n\tattachment: HasTextureRegion;\n\n\tconstructor (frameCount: number, slotIndex: number, attachment: HasTextureRegion) {\n\t\tsuper(frameCount, [\n\t\t\tProperty.sequence + \"|\" + slotIndex + \"|\" + attachment.sequence!.id\n\t\t]);\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.attachment = attachment;\n\t}\n\n\tgetFrameEntries () {\n\t\treturn SequenceTimeline.ENTRIES;\n\t}\n\n\tgetSlotIndex () {\n\t\treturn this.slotIndex;\n\t}\n\n\tgetAttachment () {\n\t\treturn this.attachment as unknown as Attachment;\n\t}\n\n\t/** Sets the time, mode, index, and frame time for the specified frame.\n\t * @param frame Between 0 and frameCount, inclusive.\n\t * @param time Seconds between frames. */\n\tsetFrame (frame: number, time: number, mode: SequenceMode, index: number, delay: number) {\n\t\tlet frames = this.frames;\n\t\tframe *= SequenceTimeline.ENTRIES;\n\t\tframes[frame] = time;\n\t\tframes[frame + SequenceTimeline.MODE] = mode | (index << 4);\n\t\tframes[frame + SequenceTimeline.DELAY] = delay;\n\t}\n\n\tapply (skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection) {\n\t\tlet slot = skeleton.slots[this.slotIndex];\n\t\tif (!slot.bone.active) return;\n\t\tlet slotAttachment = slot.attachment;\n\t\tlet attachment = this.attachment as unknown as Attachment;\n\t\tif (slotAttachment != attachment) {\n\t\t\tif (!(slotAttachment instanceof VertexAttachment)\n\t\t\t\t|| (slotAttachment as VertexAttachment).timelineAttachment != attachment) return;\n\t\t}\n\n\t\tif (direction == MixDirection.mixOut) {\n\t\t\tif (blend == MixBlend.setup) slot.sequenceIndex = -1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet frames = this.frames;\n\t\tif (time < frames[0]) {\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first) slot.sequenceIndex = -1;\n\t\t\treturn;\n\t\t}\n\n\t\tlet i = Timeline.search(frames, time, SequenceTimeline.ENTRIES);\n\t\tlet before = frames[i];\n\t\tlet modeAndIndex = frames[i + SequenceTimeline.MODE];\n\t\tlet delay = frames[i + SequenceTimeline.DELAY];\n\n\t\tif (!this.attachment.sequence) return;\n\t\tlet index = modeAndIndex >> 4, count = this.attachment.sequence!.regions.length;\n\t\tlet mode = SequenceModeValues[modeAndIndex & 0xf];\n\t\tif (mode != SequenceMode.hold) {\n\t\t\tindex += (((time - before) / delay + 0.00001) | 0);\n\t\t\tswitch (mode) {\n\t\t\t\tcase SequenceMode.once:\n\t\t\t\t\tindex = Math.min(count - 1, index);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.loop:\n\t\t\t\t\tindex %= count;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.pingpong: {\n\t\t\t\t\tlet n = (count << 1) - 2;\n\t\t\t\t\tindex = n == 0 ? 0 : index % n;\n\t\t\t\t\tif (index >= count) index = n - index;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SequenceMode.onceReverse:\n\t\t\t\t\tindex = Math.max(count - 1 - index, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.loopReverse:\n\t\t\t\t\tindex = count - 1 - (index % count);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SequenceMode.pingpongReverse: {\n\t\t\t\t\tlet n = (count << 1) - 2;\n\t\t\t\t\tindex = n == 0 ? 0 : (index + count - 1) % n;\n\t\t\t\t\tif (index >= count) index = n - index;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tslot.sequenceIndex = index;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation, MixBlend, AttachmentTimeline, MixDirection, RotateTimeline, DrawOrderTimeline, Timeline, EventTimeline } from \"./Animation.js\";\nimport { AnimationStateData } from \"./AnimationStateData.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { StringSet, Pool, Utils, MathUtils } from \"./Utils.js\";\nimport { Event } from \"./Event.js\";\n\n\n/** Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies\n * multiple animations on top of each other (layering).\n *\n * See [Applying Animations](http://esotericsoftware.com/spine-applying-animations/) in the Spine Runtimes Guide. */\nexport class AnimationState {\n\tstatic _emptyAnimation = new Animation(\"\", [], 0);\n\tprivate static emptyAnimation (): Animation {\n\t\treturn AnimationState._emptyAnimation;\n\t}\n\n\t/** The AnimationStateData to look up mix durations. */\n\tdata: AnimationStateData;\n\n\t/** The list of tracks that currently have animations, which may contain null entries. */\n\ttracks = new Array();\n\n\t/** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower\n\t * or faster. Defaults to 1.\n\t *\n\t * See TrackEntry {@link TrackEntry#timeScale} for affecting a single animation. */\n\ttimeScale = 1;\n\tunkeyedState = 0;\n\n\tevents = new Array();\n\tlisteners = new Array();\n\tqueue = new EventQueue(this);\n\tpropertyIDs = new StringSet();\n\tanimationsChanged = false;\n\n\ttrackEntryPool = new Pool(() => new TrackEntry());\n\n\tconstructor (data: AnimationStateData) {\n\t\tthis.data = data;\n\t}\n\n\t/** Increments each track entry {@link TrackEntry#trackTime()}, setting queued animations as current if needed. */\n\tupdate (delta: number) {\n\t\tdelta *= this.timeScale;\n\t\tlet tracks = this.tracks;\n\t\tfor (let i = 0, n = tracks.length; i < n; i++) {\n\t\t\tlet current = tracks[i];\n\t\t\tif (!current) continue;\n\n\t\t\tcurrent.animationLast = current.nextAnimationLast;\n\t\t\tcurrent.trackLast = current.nextTrackLast;\n\n\t\t\tlet currentDelta = delta * current.timeScale;\n\n\t\t\tif (current.delay > 0) {\n\t\t\t\tcurrent.delay -= currentDelta;\n\t\t\t\tif (current.delay > 0) continue;\n\t\t\t\tcurrentDelta = -current.delay;\n\t\t\t\tcurrent.delay = 0;\n\t\t\t}\n\n\t\t\tlet next = current.next;\n\t\t\tif (next) {\n\t\t\t\t// When the next entry's delay is passed, change to the next entry, preserving leftover time.\n\t\t\t\tlet nextTime = current.trackLast - next.delay;\n\t\t\t\tif (nextTime >= 0) {\n\t\t\t\t\tnext.delay = 0;\n\t\t\t\t\tnext.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale;\n\t\t\t\t\tcurrent.trackTime += currentDelta;\n\t\t\t\t\tthis.setCurrent(i, next, true);\n\t\t\t\t\twhile (next.mixingFrom) {\n\t\t\t\t\t\tnext.mixTime += delta;\n\t\t\t\t\t\tnext = next.mixingFrom;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (current.trackLast >= current.trackEnd && !current.mixingFrom) {\n\t\t\t\ttracks[i] = null;\n\t\t\t\tthis.queue.end(current);\n\t\t\t\tthis.clearNext(current);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (current.mixingFrom && this.updateMixingFrom(current, delta)) {\n\t\t\t\t// End mixing from entries once all have completed.\n\t\t\t\tlet from: TrackEntry | null = current.mixingFrom;\n\t\t\t\tcurrent.mixingFrom = null;\n\t\t\t\tif (from) from.mixingTo = null;\n\t\t\t\twhile (from) {\n\t\t\t\t\tthis.queue.end(from);\n\t\t\t\t\tfrom = from.mixingFrom;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrent.trackTime += currentDelta;\n\t\t}\n\n\t\tthis.queue.drain();\n\t}\n\n\t/** Returns true when all mixing from entries are complete. */\n\tupdateMixingFrom (to: TrackEntry, delta: number): boolean {\n\t\tlet from = to.mixingFrom;\n\t\tif (!from) return true;\n\n\t\tlet finished = this.updateMixingFrom(from, delta);\n\n\t\tfrom.animationLast = from.nextAnimationLast;\n\t\tfrom.trackLast = from.nextTrackLast;\n\n\t\t// The from entry was applied at least once and the mix is complete.\n\t\tif (to.nextTrackLast != -1 && to.mixTime >= to.mixDuration) {\n\t\t\t// Mixing is complete for all entries before the from entry or the mix is instantaneous.\n\t\t\tif (from.totalAlpha == 0 || to.mixDuration == 0) {\n\t\t\t\tto.mixingFrom = from.mixingFrom;\n\t\t\t\tif (from.mixingFrom != null) from.mixingFrom.mixingTo = to;\n\t\t\t\tto.interruptAlpha = from.interruptAlpha;\n\t\t\t\tthis.queue.end(from);\n\t\t\t}\n\t\t\treturn finished;\n\t\t}\n\n\t\tfrom.trackTime += delta * from.timeScale;\n\t\tto.mixTime += delta;\n\t\treturn false;\n\t}\n\n\t/** Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the\n\t * animation state can be applied to multiple skeletons to pose them identically.\n\t * @returns True if any animations were applied. */\n\tapply (skeleton: Skeleton): boolean {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tif (this.animationsChanged) this._animationsChanged();\n\n\t\tlet events = this.events;\n\t\tlet tracks = this.tracks;\n\t\tlet applied = false;\n\n\t\tfor (let i = 0, n = tracks.length; i < n; i++) {\n\t\t\tlet current = tracks[i];\n\t\t\tif (!current || current.delay > 0) continue;\n\t\t\tapplied = true;\n\t\t\tlet blend: MixBlend = i == 0 ? MixBlend.first : current.mixBlend;\n\n\t\t\t// Apply mixing from entries first.\n\t\t\tlet alpha = current.alpha;\n\t\t\tif (current.mixingFrom)\n\t\t\t\talpha *= this.applyMixingFrom(current, skeleton, blend);\n\t\t\telse if (current.trackTime >= current.trackEnd && !current.next)\n\t\t\t\talpha = 0;\n\t\t\tlet attachments = alpha >= current.alphaAttachmentThreshold;\n\n\n\t\t\t// Apply current entry.\n\t\t\tlet animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime;\n\t\t\tlet applyEvents: Event[] | null = events;\n\t\t\tif (current.reverse) {\n\t\t\t\tapplyTime = current.animation!.duration - applyTime;\n\t\t\t\tapplyEvents = null;\n\t\t\t}\n\t\t\tlet timelines = current.animation!.timelines;\n\t\t\tlet timelineCount = timelines.length;\n\t\t\tif ((i == 0 && alpha == 1) || blend == MixBlend.add) {\n\t\t\t\tif (i == 0) attachments = true;\n\t\t\t\tfor (let ii = 0; ii < timelineCount; ii++) {\n\t\t\t\t\t// Fixes issue #302 on IOS9 where mix, blend sometimes became undefined and caused assets\n\t\t\t\t\t// to sometimes stop rendering when using color correction, as their RGBA values become NaN.\n\t\t\t\t\t// (https://github.com/pixijs/pixi-spine/issues/302)\n\t\t\t\t\tUtils.webkit602BugfixHelper(alpha, blend);\n\t\t\t\t\tvar timeline = timelines[ii];\n\t\t\t\t\tif (timeline instanceof AttachmentTimeline)\n\t\t\t\t\t\tthis.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments);\n\t\t\t\t\telse\n\t\t\t\t\t\ttimeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection.mixIn);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlet timelineMode = current.timelineMode;\n\n\t\t\t\tlet shortestRotation = current.shortestRotation;\n\t\t\t\tlet firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1;\n\t\t\t\tif (firstFrame) current.timelinesRotation.length = timelineCount << 1;\n\n\t\t\t\tfor (let ii = 0; ii < timelineCount; ii++) {\n\t\t\t\t\tlet timeline = timelines[ii];\n\t\t\t\t\tlet timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;\n\t\t\t\t\tif (!shortestRotation && timeline instanceof RotateTimeline) {\n\t\t\t\t\t\tthis.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, current.timelinesRotation, ii << 1, firstFrame);\n\t\t\t\t\t} else if (timeline instanceof AttachmentTimeline) {\n\t\t\t\t\t\tthis.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, attachments);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// This fixes the WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\t\t\t\t\t\tUtils.webkit602BugfixHelper(alpha, blend);\n\t\t\t\t\t\ttimeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, MixDirection.mixIn);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.queueEvents(current, animationTime);\n\t\t\tevents.length = 0;\n\t\t\tcurrent.nextAnimationLast = animationTime;\n\t\t\tcurrent.nextTrackLast = current.trackTime;\n\t\t}\n\n\t\t// Set slots attachments to the setup pose, if needed. This occurs if an animation that is mixing out sets attachments so\n\t\t// subsequent timelines see any deform, but the subsequent timelines don't set an attachment (eg they are also mixing out or\n\t\t// the time is before the first key).\n\t\tvar setupState = this.unkeyedState + SETUP;\n\t\tvar slots = skeleton.slots;\n\t\tfor (var i = 0, n = skeleton.slots.length; i < n; i++) {\n\t\t\tvar slot = slots[i];\n\t\t\tif (slot.attachmentState == setupState) {\n\t\t\t\tvar attachmentName = slot.data.attachmentName;\n\t\t\t\tslot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));\n\t\t\t}\n\t\t}\n\t\tthis.unkeyedState += 2; // Increasing after each use avoids the need to reset attachmentState for every slot.\n\n\t\tthis.queue.drain();\n\t\treturn applied;\n\t}\n\n\tapplyMixingFrom (to: TrackEntry, skeleton: Skeleton, blend: MixBlend) {\n\t\tlet from = to.mixingFrom!;\n\t\tif (from.mixingFrom) this.applyMixingFrom(from, skeleton, blend);\n\n\t\tlet mix = 0;\n\t\tif (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes.\n\t\t\tmix = 1;\n\t\t\tif (blend == MixBlend.first) blend = MixBlend.setup;\n\t\t} else {\n\t\t\tmix = to.mixTime / to.mixDuration;\n\t\t\tif (mix > 1) mix = 1;\n\t\t\tif (blend != MixBlend.first) blend = from.mixBlend;\n\t\t}\n\n\t\tlet attachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold;\n\t\tlet timelines = from.animation!.timelines;\n\t\tlet timelineCount = timelines.length;\n\t\tlet alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix);\n\t\tlet animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime;\n\t\tlet events = null;\n\t\tif (from.reverse)\n\t\t\tapplyTime = from.animation!.duration - applyTime;\n\t\telse if (mix < from.eventThreshold)\n\t\t\tevents = this.events;\n\n\t\tif (blend == MixBlend.add) {\n\t\t\tfor (let i = 0; i < timelineCount; i++)\n\t\t\t\ttimelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection.mixOut);\n\t\t} else {\n\t\t\tlet timelineMode = from.timelineMode;\n\t\t\tlet timelineHoldMix = from.timelineHoldMix;\n\n\t\t\tlet shortestRotation = from.shortestRotation;\n\t\t\tlet firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1;\n\t\t\tif (firstFrame) from.timelinesRotation.length = timelineCount << 1;\n\n\t\t\tfrom.totalAlpha = 0;\n\t\t\tfor (let i = 0; i < timelineCount; i++) {\n\t\t\t\tlet timeline = timelines[i];\n\t\t\t\tlet direction = MixDirection.mixOut;\n\t\t\t\tlet timelineBlend: MixBlend;\n\t\t\t\tlet alpha = 0;\n\t\t\t\tswitch (timelineMode[i]) {\n\t\t\t\t\tcase SUBSEQUENT:\n\t\t\t\t\t\tif (!drawOrder && timeline instanceof DrawOrderTimeline) continue;\n\t\t\t\t\t\ttimelineBlend = blend;\n\t\t\t\t\t\talpha = alphaMix;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase FIRST:\n\t\t\t\t\t\ttimelineBlend = MixBlend.setup;\n\t\t\t\t\t\talpha = alphaMix;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HOLD_SUBSEQUENT:\n\t\t\t\t\t\ttimelineBlend = blend;\n\t\t\t\t\t\talpha = alphaHold;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase HOLD_FIRST:\n\t\t\t\t\t\ttimelineBlend = MixBlend.setup;\n\t\t\t\t\t\talpha = alphaHold;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\ttimelineBlend = MixBlend.setup;\n\t\t\t\t\t\tlet holdMix = timelineHoldMix[i];\n\t\t\t\t\t\talpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfrom.totalAlpha += alpha;\n\n\t\t\t\tif (!shortestRotation && timeline instanceof RotateTimeline)\n\t\t\t\t\tthis.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame);\n\t\t\t\telse if (timeline instanceof AttachmentTimeline)\n\t\t\t\t\tthis.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments && alpha >= from.alphaAttachmentThreshold);\n\t\t\t\telse {\n\t\t\t\t\t// This fixes the WebKit 602 specific issue described at http://esotericsoftware.com/forum/iOS-10-disappearing-graphics-10109\n\t\t\t\t\tUtils.webkit602BugfixHelper(alpha, blend);\n\t\t\t\t\tif (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == MixBlend.setup)\n\t\t\t\t\t\tdirection = MixDirection.mixIn;\n\t\t\t\t\ttimeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (to.mixDuration > 0) this.queueEvents(from, animationTime);\n\t\tthis.events.length = 0;\n\t\tfrom.nextAnimationLast = animationTime;\n\t\tfrom.nextTrackLast = from.trackTime;\n\n\t\treturn mix;\n\t}\n\n\tapplyAttachmentTimeline (timeline: AttachmentTimeline, skeleton: Skeleton, time: number, blend: MixBlend, attachments: boolean) {\n\t\tvar slot = skeleton.slots[timeline.slotIndex];\n\t\tif (!slot.bone.active) return;\n\n\t\tif (time < timeline.frames[0]) { // Time is before first frame.\n\t\t\tif (blend == MixBlend.setup || blend == MixBlend.first)\n\t\t\t\tthis.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);\n\t\t} else\n\t\t\tthis.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments);\n\n\t\t// If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.\n\t\tif (slot.attachmentState <= this.unkeyedState) slot.attachmentState = this.unkeyedState + SETUP;\n\t}\n\n\tsetAttachment (skeleton: Skeleton, slot: Slot, attachmentName: string | null, attachments: boolean) {\n\t\tslot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));\n\t\tif (attachments) slot.attachmentState = this.unkeyedState + CURRENT;\n\t}\n\n\tapplyRotateTimeline (timeline: RotateTimeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend,\n\t\ttimelinesRotation: Array, i: number, firstFrame: boolean) {\n\n\t\tif (firstFrame) timelinesRotation[i] = 0;\n\n\t\tif (alpha == 1) {\n\t\t\ttimeline.apply(skeleton, 0, time, null, 1, blend, MixDirection.mixIn);\n\t\t\treturn;\n\t\t}\n\n\t\tlet bone = skeleton.bones[timeline.boneIndex];\n\t\tif (!bone.active) return;\n\t\tlet frames = timeline.frames;\n\t\tlet r1 = 0, r2 = 0;\n\t\tif (time < frames[0]) {\n\t\t\tswitch (blend) {\n\t\t\t\tcase MixBlend.setup:\n\t\t\t\t\tbone.rotation = bone.data.rotation;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t\tcase MixBlend.first:\n\t\t\t\t\tr1 = bone.rotation;\n\t\t\t\t\tr2 = bone.data.rotation;\n\t\t\t}\n\t\t} else {\n\t\t\tr1 = blend == MixBlend.setup ? bone.data.rotation : bone.rotation;\n\t\t\tr2 = bone.data.rotation + timeline.getCurveValue(time);\n\t\t}\n\n\t\t// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.\n\t\tlet total = 0, diff = r2 - r1;\n\t\tdiff -= Math.ceil(diff / 360 - 0.5) * 360;\n\t\tif (diff == 0) {\n\t\t\ttotal = timelinesRotation[i];\n\t\t} else {\n\t\t\tlet lastTotal = 0, lastDiff = 0;\n\t\t\tif (firstFrame) {\n\t\t\t\tlastTotal = 0;\n\t\t\t\tlastDiff = diff;\n\t\t\t} else {\n\t\t\t\tlastTotal = timelinesRotation[i];\n\t\t\t\tlastDiff = timelinesRotation[i + 1];\n\t\t\t}\n\t\t\tlet loops = lastTotal - lastTotal % 360;\n\t\t\ttotal = diff + loops;\n\t\t\tlet current = diff >= 0, dir = lastTotal >= 0;\n\t\t\tif (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) != MathUtils.signum(diff)) {\n\t\t\t\tif (Math.abs(lastTotal - loops) > 180) {\n\t\t\t\t\ttotal += 360 * MathUtils.signum(lastTotal);\n\t\t\t\t\tdir = current;\n\t\t\t\t} else if (loops != 0)\n\t\t\t\t\ttotal -= 360 * MathUtils.signum(lastTotal);\n\t\t\t\telse\n\t\t\t\t\tdir = current;\n\t\t\t}\n\t\t\tif (dir != current) total += 360 * MathUtils.signum(lastTotal);\n\t\t\ttimelinesRotation[i] = total;\n\t\t}\n\t\ttimelinesRotation[i + 1] = diff;\n\t\tbone.rotation = r1 + total * alpha;\n\t}\n\n\tqueueEvents (entry: TrackEntry, animationTime: number) {\n\t\tlet animationStart = entry.animationStart, animationEnd = entry.animationEnd;\n\t\tlet duration = animationEnd - animationStart;\n\t\tlet trackLastWrapped = entry.trackLast % duration;\n\n\t\t// Queue events before complete.\n\t\tlet events = this.events;\n\t\tlet i = 0, n = events.length;\n\t\tfor (; i < n; i++) {\n\t\t\tlet event = events[i];\n\t\t\tif (event.time < trackLastWrapped) break;\n\t\t\tif (event.time > animationEnd) continue; // Discard events outside animation start/end.\n\t\t\tthis.queue.event(entry, event);\n\t\t}\n\n\t\t// Queue complete if completed a loop iteration or the animation.\n\t\tlet complete = false;\n\t\tif (entry.loop) {\n\t\t\tif (duration == 0)\n\t\t\t\tcomplete = true;\n\t\t\telse {\n\t\t\t\tconst cycles = Math.floor(entry.trackTime / duration);\n\t\t\t\tcomplete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration);\n\t\t\t}\n\t\t} else\n\t\t\tcomplete = animationTime >= animationEnd && entry.animationLast < animationEnd;\n\t\tif (complete) this.queue.complete(entry);\n\n\t\t// Queue events after complete.\n\t\tfor (; i < n; i++) {\n\t\t\tlet event = events[i];\n\t\t\tif (event.time < animationStart) continue; // Discard events outside animation start/end.\n\t\t\tthis.queue.event(entry, event);\n\t\t}\n\t}\n\n\t/** Removes all animations from all tracks, leaving skeletons in their current pose.\n\t *\n\t * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose,\n\t * rather than leaving them in their current pose. */\n\tclearTracks () {\n\t\tlet oldDrainDisabled = this.queue.drainDisabled;\n\t\tthis.queue.drainDisabled = true;\n\t\tfor (let i = 0, n = this.tracks.length; i < n; i++)\n\t\t\tthis.clearTrack(i);\n\t\tthis.tracks.length = 0;\n\t\tthis.queue.drainDisabled = oldDrainDisabled;\n\t\tthis.queue.drain();\n\t}\n\n\t/** Removes all animations from the track, leaving skeletons in their current pose.\n\t *\n\t * It may be desired to use {@link AnimationState#setEmptyAnimation()} to mix the skeletons back to the setup pose,\n\t * rather than leaving them in their current pose. */\n\tclearTrack (trackIndex: number) {\n\t\tif (trackIndex >= this.tracks.length) return;\n\t\tlet current = this.tracks[trackIndex];\n\t\tif (!current) return;\n\n\t\tthis.queue.end(current);\n\n\t\tthis.clearNext(current);\n\n\t\tlet entry = current;\n\t\twhile (true) {\n\t\t\tlet from = entry.mixingFrom;\n\t\t\tif (!from) break;\n\t\t\tthis.queue.end(from);\n\t\t\tentry.mixingFrom = null;\n\t\t\tentry.mixingTo = null;\n\t\t\tentry = from;\n\t\t}\n\n\t\tthis.tracks[current.trackIndex] = null;\n\n\t\tthis.queue.drain();\n\t}\n\n\tsetCurrent (index: number, current: TrackEntry, interrupt: boolean) {\n\t\tlet from = this.expandToIndex(index);\n\t\tthis.tracks[index] = current;\n\t\tcurrent.previous = null;\n\n\t\tif (from) {\n\t\t\tif (interrupt) this.queue.interrupt(from);\n\t\t\tcurrent.mixingFrom = from;\n\t\t\tfrom.mixingTo = current;\n\t\t\tcurrent.mixTime = 0;\n\n\t\t\t// Store the interrupted mix percentage.\n\t\t\tif (from.mixingFrom && from.mixDuration > 0)\n\t\t\t\tcurrent.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration);\n\n\t\t\tfrom.timelinesRotation.length = 0; // Reset rotation for mixing out, in case entry was mixed in.\n\t\t}\n\n\t\tthis.queue.start(current);\n\t}\n\n\t/** Sets an animation by name.\n\t *\n\t * See {@link #setAnimationWith()}. */\n\tsetAnimation (trackIndex: number, animationName: string, loop: boolean = false) {\n\t\tlet animation = this.data.skeletonData.findAnimation(animationName);\n\t\tif (!animation) throw new Error(\"Animation not found: \" + animationName);\n\t\treturn this.setAnimationWith(trackIndex, animation, loop);\n\t}\n\n\t/** Sets the current animation for a track, discarding any queued animations. If the formerly current track entry was never\n\t * applied to a skeleton, it is replaced (not mixed from).\n\t * @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its\n\t * duration. In either case {@link TrackEntry#trackEnd} determines when the track is cleared.\n\t * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept\n\t * after the {@link AnimationStateListener#dispose()} event occurs. */\n\tsetAnimationWith (trackIndex: number, animation: Animation, loop: boolean = false) {\n\t\tif (!animation) throw new Error(\"animation cannot be null.\");\n\t\tlet interrupt = true;\n\t\tlet current = this.expandToIndex(trackIndex);\n\t\tif (current) {\n\t\t\tif (current.nextTrackLast == -1) {\n\t\t\t\t// Don't mix from an entry that was never applied.\n\t\t\t\tthis.tracks[trackIndex] = current.mixingFrom;\n\t\t\t\tthis.queue.interrupt(current);\n\t\t\t\tthis.queue.end(current);\n\t\t\t\tthis.clearNext(current);\n\t\t\t\tcurrent = current.mixingFrom;\n\t\t\t\tinterrupt = false;\n\t\t\t} else\n\t\t\t\tthis.clearNext(current);\n\t\t}\n\t\tlet entry = this.trackEntry(trackIndex, animation, loop, current);\n\t\tthis.setCurrent(trackIndex, entry, interrupt);\n\t\tthis.queue.drain();\n\t\treturn entry;\n\t}\n\n\t/** Queues an animation by name.\n\t *\n\t * See {@link #addAnimationWith()}. */\n\taddAnimation (trackIndex: number, animationName: string, loop: boolean = false, delay: number = 0) {\n\t\tlet animation = this.data.skeletonData.findAnimation(animationName);\n\t\tif (!animation) throw new Error(\"Animation not found: \" + animationName);\n\t\treturn this.addAnimationWith(trackIndex, animation, loop, delay);\n\t}\n\n\t/** Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is\n\t * equivalent to calling {@link #setAnimationWith()}.\n\t * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry\n\t * minus any mix duration (from the {@link AnimationStateData}) plus the specified `delay` (ie the mix\n\t * ends at (`delay` = 0) or before (`delay` < 0) the previous track entry duration). If the\n\t * previous entry is looping, its next loop completion is used instead of its duration.\n\t * @returns A track entry to allow further customization of animation playback. References to the track entry must not be kept\n\t * after the {@link AnimationStateListener#dispose()} event occurs. */\n\taddAnimationWith (trackIndex: number, animation: Animation, loop: boolean = false, delay: number = 0) {\n\t\tif (!animation) throw new Error(\"animation cannot be null.\");\n\n\t\tlet last = this.expandToIndex(trackIndex);\n\t\tif (last) {\n\t\t\twhile (last.next)\n\t\t\t\tlast = last.next;\n\t\t}\n\n\t\tlet entry = this.trackEntry(trackIndex, animation, loop, last);\n\n\t\tif (!last) {\n\t\t\tthis.setCurrent(trackIndex, entry, true);\n\t\t\tthis.queue.drain();\n\t\t} else {\n\t\t\tlast.next = entry;\n\t\t\tentry.previous = last;\n\t\t\tif (delay <= 0) delay += last.getTrackComplete() - entry.mixDuration;\n\t\t}\n\n\t\tentry.delay = delay;\n\t\treturn entry;\n\t}\n\n\t/** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's\n\t * {@link TrackEntry#mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out.\n\t *\n\t * Mixing out is done by setting an empty animation with a mix duration using either {@link #setEmptyAnimation()},\n\t * {@link #setEmptyAnimations()}, or {@link #addEmptyAnimation()}. Mixing to an empty animation causes\n\t * the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation\n\t * transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of\n\t * 0 still mixes out over one frame.\n\t *\n\t * Mixing in is done by first setting an empty animation, then adding an animation using\n\t * {@link #addAnimation()} and on the returned track entry, set the\n\t * {@link TrackEntry#setMixDuration()}. Mixing from an empty animation causes the new animation to be applied more and\n\t * more over the mix duration. Properties keyed in the new animation transition from the value from lower tracks or from the\n\t * setup pose value if no lower tracks key the property to the value keyed in the new animation. */\n\tsetEmptyAnimation (trackIndex: number, mixDuration: number = 0) {\n\t\tlet entry = this.setAnimationWith(trackIndex, AnimationState.emptyAnimation(), false);\n\t\tentry.mixDuration = mixDuration;\n\t\tentry.trackEnd = mixDuration;\n\t\treturn entry;\n\t}\n\n\t/** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's\n\t * {@link TrackEntry#mixDuration}. If the track is empty, it is equivalent to calling\n\t * {@link #setEmptyAnimation()}.\n\t *\n\t * See {@link #setEmptyAnimation()}.\n\t * @param delay If > 0, sets {@link TrackEntry#delay}. If <= 0, the delay set is the duration of the previous track entry\n\t * minus any mix duration plus the specified `delay` (ie the mix ends at (`delay` = 0) or\n\t * before (`delay` < 0) the previous track entry duration). If the previous entry is looping, its next\n\t * loop completion is used instead of its duration.\n\t * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept\n\t * after the {@link AnimationStateListener#dispose()} event occurs. */\n\taddEmptyAnimation (trackIndex: number, mixDuration: number = 0, delay: number = 0) {\n\t\tlet entry = this.addAnimationWith(trackIndex, AnimationState.emptyAnimation(), false, delay);\n\t\tif (delay <= 0) entry.delay += entry.mixDuration - mixDuration;\n\t\tentry.mixDuration = mixDuration;\n\t\tentry.trackEnd = mixDuration;\n\t\treturn entry;\n\t}\n\n\t/** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix\n\t * duration. */\n\tsetEmptyAnimations (mixDuration: number = 0) {\n\t\tlet oldDrainDisabled = this.queue.drainDisabled;\n\t\tthis.queue.drainDisabled = true;\n\t\tfor (let i = 0, n = this.tracks.length; i < n; i++) {\n\t\t\tlet current = this.tracks[i];\n\t\t\tif (current) this.setEmptyAnimation(current.trackIndex, mixDuration);\n\t\t}\n\t\tthis.queue.drainDisabled = oldDrainDisabled;\n\t\tthis.queue.drain();\n\t}\n\n\texpandToIndex (index: number) {\n\t\tif (index < this.tracks.length) return this.tracks[index];\n\t\tUtils.ensureArrayCapacity(this.tracks, index + 1, null);\n\t\tthis.tracks.length = index + 1;\n\t\treturn null;\n\t}\n\n\t/** @param last May be null. */\n\ttrackEntry (trackIndex: number, animation: Animation, loop: boolean, last: TrackEntry | null) {\n\t\tlet entry = this.trackEntryPool.obtain();\n\t\tentry.reset();\n\t\tentry.trackIndex = trackIndex;\n\t\tentry.animation = animation;\n\t\tentry.loop = loop;\n\t\tentry.holdPrevious = false;\n\n\t\tentry.reverse = false;\n\t\tentry.shortestRotation = false;\n\n\t\tentry.eventThreshold = 0;\n\t\tentry.alphaAttachmentThreshold = 0;\n\t\tentry.mixAttachmentThreshold = 0;\n\t\tentry.mixDrawOrderThreshold = 0;\n\n\t\tentry.animationStart = 0;\n\t\tentry.animationEnd = animation.duration;\n\t\tentry.animationLast = -1;\n\t\tentry.nextAnimationLast = -1;\n\n\t\tentry.delay = 0;\n\t\tentry.trackTime = 0;\n\t\tentry.trackLast = -1;\n\t\tentry.nextTrackLast = -1;\n\t\tentry.trackEnd = Number.MAX_VALUE;\n\t\tentry.timeScale = 1;\n\n\t\tentry.alpha = 1;\n\t\tentry.mixTime = 0;\n\t\tentry.mixDuration = !last ? 0 : this.data.getMix(last.animation!, animation);\n\t\tentry.interruptAlpha = 1;\n\t\tentry.totalAlpha = 0;\n\t\tentry.mixBlend = MixBlend.replace;\n\t\treturn entry;\n\t}\n\n\t/** Removes the {@link TrackEntry#getNext() next entry} and all entries after it for the specified entry. */\n\tclearNext (entry: TrackEntry) {\n\t\tlet next = entry.next;\n\t\twhile (next) {\n\t\t\tthis.queue.dispose(next);\n\t\t\tnext = next.next;\n\t\t}\n\t\tentry.next = null;\n\t}\n\n\t_animationsChanged () {\n\t\tthis.animationsChanged = false;\n\n\t\tthis.propertyIDs.clear();\n\t\tlet tracks = this.tracks;\n\t\tfor (let i = 0, n = tracks.length; i < n; i++) {\n\t\t\tlet entry = tracks[i];\n\t\t\tif (!entry) continue;\n\t\t\twhile (entry.mixingFrom)\n\t\t\t\tentry = entry.mixingFrom;\n\t\t\tdo {\n\t\t\t\tif (!entry.mixingTo || entry.mixBlend != MixBlend.add) this.computeHold(entry);\n\t\t\t\tentry = entry.mixingTo;\n\t\t\t} while (entry);\n\t\t}\n\t}\n\n\tcomputeHold (entry: TrackEntry) {\n\t\tlet to = entry.mixingTo;\n\t\tlet timelines = entry.animation!.timelines;\n\t\tlet timelinesCount = entry.animation!.timelines.length;\n\t\tlet timelineMode = entry.timelineMode;\n\t\ttimelineMode.length = timelinesCount;\n\t\tlet timelineHoldMix = entry.timelineHoldMix;\n\t\ttimelineHoldMix.length = 0;\n\t\tlet propertyIDs = this.propertyIDs;\n\n\t\tif (to && to.holdPrevious) {\n\t\t\tfor (let i = 0; i < timelinesCount; i++)\n\t\t\t\ttimelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT;\n\t\t\treturn;\n\t\t}\n\n\t\touter:\n\t\tfor (let i = 0; i < timelinesCount; i++) {\n\t\t\tlet timeline = timelines[i];\n\t\t\tlet ids = timeline.getPropertyIds();\n\t\t\tif (!propertyIDs.addAll(ids))\n\t\t\t\ttimelineMode[i] = SUBSEQUENT;\n\t\t\telse if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline\n\t\t\t\t|| timeline instanceof EventTimeline || !to.animation!.hasTimeline(ids)) {\n\t\t\t\ttimelineMode[i] = FIRST;\n\t\t\t} else {\n\t\t\t\tfor (let next = to.mixingTo; next; next = next!.mixingTo) {\n\t\t\t\t\tif (next.animation!.hasTimeline(ids)) continue;\n\t\t\t\t\tif (entry.mixDuration > 0) {\n\t\t\t\t\t\ttimelineMode[i] = HOLD_MIX;\n\t\t\t\t\t\ttimelineHoldMix[i] = next;\n\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttimelineMode[i] = HOLD_FIRST;\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */\n\tgetCurrent (trackIndex: number) {\n\t\tif (trackIndex >= this.tracks.length) return null;\n\t\treturn this.tracks[trackIndex];\n\t}\n\n\t/** Adds a listener to receive events for all track entries. */\n\taddListener (listener: AnimationStateListener) {\n\t\tif (!listener) throw new Error(\"listener cannot be null.\");\n\t\tthis.listeners.push(listener);\n\t}\n\n\t/** Removes the listener added with {@link #addListener()}. */\n\tremoveListener (listener: AnimationStateListener) {\n\t\tlet index = this.listeners.indexOf(listener);\n\t\tif (index >= 0) this.listeners.splice(index, 1);\n\t}\n\n\t/** Removes all listeners added with {@link #addListener()}. */\n\tclearListeners () {\n\t\tthis.listeners.length = 0;\n\t}\n\n\t/** Discards all listener notifications that have not yet been delivered. This can be useful to call from an\n\t * {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery\n\t * are not wanted because new animations are being set. */\n\tclearListenerNotifications () {\n\t\tthis.queue.clear();\n\t}\n}\n\n/** Stores settings and other state for the playback of an animation on an {@link AnimationState} track.\n *\n * References to a track entry must not be kept after the {@link AnimationStateListener#dispose()} event occurs. */\nexport class TrackEntry {\n\t/** The animation to apply for this track entry. */\n\tanimation: Animation | null = null;\n\n\tprevious: TrackEntry | null = null;\n\n\t/** The animation queued to start after this animation, or null. `next` makes up a linked list. */\n\tnext: TrackEntry | null = null;\n\n\t/** The track entry for the previous animation when mixing from the previous animation to this animation, or null if no\n\t * mixing is currently occuring. When mixing from multiple animations, `mixingFrom` makes up a linked list. */\n\tmixingFrom: TrackEntry | null = null;\n\n\t/** The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is\n\t * currently occuring. When mixing to multiple animations, `mixingTo` makes up a linked list. */\n\tmixingTo: TrackEntry | null = null;\n\n\t/** The listener for events generated by this track entry, or null.\n\t *\n\t * A track entry returned from {@link AnimationState#setAnimation()} is already the current animation\n\t * for the track, so the track entry listener {@link AnimationStateListener#start()} will not be called. */\n\tlistener: AnimationStateListener | null = null;\n\n\t/** The index of the track where this track entry is either current or queued.\n\t *\n\t * See {@link AnimationState#getCurrent()}. */\n\ttrackIndex: number = 0;\n\n\t/** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its\n\t * duration. */\n\tloop: boolean = false;\n\n\t/** If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead\n\t * of being mixed out.\n\t *\n\t * When mixing between animations that key the same property, if a lower track also keys that property then the value will\n\t * briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0%\n\t * while the second animation mixes from 0% to 100%. Setting `holdPrevious` to true applies the first animation\n\t * at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which\n\t * keys the property, only when a higher track also keys the property.\n\t *\n\t * Snapping will occur if `holdPrevious` is true and this animation does not key all the same properties as the\n\t * previous animation. */\n\tholdPrevious: boolean = false;\n\n\treverse: boolean = false;\n\n\tshortestRotation: boolean = false;\n\n\t/** When the mix percentage ({@link #mixTime} / {@link #mixDuration}) is less than the\n\t * `eventThreshold`, event timelines are applied while this animation is being mixed out. Defaults to 0, so event\n\t * timelines are not applied while this animation is being mixed out. */\n\teventThreshold: number = 0;\n\n\t/** When the mix percentage ({@link #mixtime} / {@link #mixDuration}) is less than the\n\t * `attachmentThreshold`, attachment timelines are applied while this animation is being mixed out. Defaults to\n\t * 0, so attachment timelines are not applied while this animation is being mixed out. */\n\tmixAttachmentThreshold: number = 0;\n\n\t/** When {@link #getAlpha()} is greater than alphaAttachmentThreshold, attachment timelines are applied.\n\t * Defaults to 0, so attachment timelines are always applied. */\n\talphaAttachmentThreshold: number = 0;\n\n\t/** When the mix percentage ({@link #getMixTime()} / {@link #getMixDuration()}) is less than the\n\t * mixDrawOrderThreshold, draw order timelines are applied while this animation is being mixed out. Defaults to\n\t * 0, so draw order timelines are not applied while this animation is being mixed out. */\n\tmixDrawOrderThreshold: number = 0;\n\n\t/** Seconds when this animation starts, both initially and after looping. Defaults to 0.\n\t *\n\t * When changing the `animationStart` time, it often makes sense to set {@link #animationLast} to the same\n\t * value to prevent timeline keys before the start time from triggering. */\n\tanimationStart: number = 0;\n\n\t/** Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will\n\t * loop back to {@link #animationStart} at this time. Defaults to the animation {@link Animation#duration}. */\n\tanimationEnd: number = 0;\n\n\n\t/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this\n\t * animation is applied, event timelines will fire all events between the `animationLast` time (exclusive) and\n\t * `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation\n\t * is applied. */\n\tanimationLast: number = 0;\n\n\tnextAnimationLast: number = 0;\n\n\t/** Seconds to postpone playing the animation. When this track entry is the current track entry, `delay`\n\t * postpones incrementing the {@link #trackTime}. When this track entry is queued, `delay` is the time from\n\t * the start of the previous animation to when this track entry will become the current track entry (ie when the previous\n\t * track entry {@link TrackEntry#trackTime} >= this track entry's `delay`).\n\t *\n\t * {@link #timeScale} affects the delay. */\n\tdelay: number = 0;\n\n\t/** Current time in seconds this track entry has been the current track entry. The track time determines\n\t * {@link #animationTime}. The track time can be set to start the animation at a time other than 0, without affecting\n\t * looping. */\n\ttrackTime: number = 0;\n\n\ttrackLast: number = 0; nextTrackLast: number = 0;\n\n\t/** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float\n\t * value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time\n\t * is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the\n\t * properties keyed by the animation are set to the setup pose and the track is cleared.\n\t *\n\t * It may be desired to use {@link AnimationState#addEmptyAnimation()} rather than have the animation\n\t * abruptly cease being applied. */\n\ttrackEnd: number = 0;\n\n\t/** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or\n\t * faster. Defaults to 1.\n\t *\n\t * {@link #mixTime} is not affected by track entry time scale, so {@link #mixDuration} may need to be adjusted to\n\t * match the animation speed.\n\t *\n\t * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the\n\t * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, assuming time scale to be 1. If\n\t * the time scale is not 1, the delay may need to be adjusted.\n\t *\n\t * See AnimationState {@link AnimationState#timeScale} for affecting all animations. */\n\ttimeScale: number = 0;\n\n\t/** Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults\n\t * to 1, which overwrites the skeleton's current pose with this animation.\n\t *\n\t * Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to\n\t * use alpha on track 0 if the skeleton pose is from the last frame render. */\n\talpha: number = 0;\n\n\t/** Seconds from 0 to the {@link #getMixDuration()} when mixing from the previous animation to this animation. May be\n\t * slightly more than `mixDuration` when the mix is complete. */\n\tmixTime: number = 0;\n\n\t/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData\n\t * {@link AnimationStateData#getMix()} based on the animation before this animation (if any).\n\t *\n\t * A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the\n\t * properties it was animating.\n\t *\n\t * The `mixDuration` can be set manually rather than use the value from\n\t * {@link AnimationStateData#getMix()}. In that case, the `mixDuration` can be set for a new\n\t * track entry only before {@link AnimationState#update(float)} is first called.\n\t *\n\t * When using {@link AnimationState#addAnimation()} with a `delay` <= 0, note the\n\t * {@link #delay} is set using the mix duration from the {@link AnimationStateData}, not a mix duration set\n\t * afterward. */\n\t_mixDuration: number = 0; interruptAlpha: number = 0; totalAlpha: number = 0;\n\n\tget mixDuration () {\n\t\treturn this._mixDuration;\n\t}\n\n\tset mixDuration (mixDuration: number) {\n\t\tthis._mixDuration = mixDuration;\n\t}\n\n\tsetMixDurationWithDelay (mixDuration: number, delay: number) {\n\t\tthis._mixDuration = mixDuration;\n\t\tif (this.previous != null && delay <= 0) delay += this.previous.getTrackComplete() - mixDuration;\n\t\tthis.delay = delay;\n\t}\n\n\t/** Controls how properties keyed in the animation are mixed with lower tracks. Defaults to {@link MixBlend#replace}, which\n\t * replaces the values from the lower tracks with the animation values. {@link MixBlend#add} adds the animation values to\n\t * the values from the lower tracks.\n\t *\n\t * The `mixBlend` can be set for a new track entry only before {@link AnimationState#apply()} is first\n\t * called. */\n\tmixBlend = MixBlend.replace;\n\ttimelineMode = new Array();\n\ttimelineHoldMix = new Array();\n\ttimelinesRotation = new Array();\n\n\treset () {\n\t\tthis.next = null;\n\t\tthis.previous = null;\n\t\tthis.mixingFrom = null;\n\t\tthis.mixingTo = null;\n\t\tthis.animation = null;\n\t\tthis.listener = null;\n\t\tthis.timelineMode.length = 0;\n\t\tthis.timelineHoldMix.length = 0;\n\t\tthis.timelinesRotation.length = 0;\n\t}\n\n\t/** Uses {@link #trackTime} to compute the `animationTime`, which is between {@link #animationStart}\n\t * and {@link #animationEnd}. When the `trackTime` is 0, the `animationTime` is equal to the\n\t * `animationStart` time. */\n\tgetAnimationTime () {\n\t\tif (this.loop) {\n\t\t\tlet duration = this.animationEnd - this.animationStart;\n\t\t\tif (duration == 0) return this.animationStart;\n\t\t\treturn (this.trackTime % duration) + this.animationStart;\n\t\t}\n\t\treturn Math.min(this.trackTime + this.animationStart, this.animationEnd);\n\t}\n\n\tsetAnimationLast (animationLast: number) {\n\t\tthis.animationLast = animationLast;\n\t\tthis.nextAnimationLast = animationLast;\n\t}\n\n\t/** Returns true if at least one loop has been completed.\n\t *\n\t * See {@link AnimationStateListener#complete()}. */\n\tisComplete () {\n\t\treturn this.trackTime >= this.animationEnd - this.animationStart;\n\t}\n\n\t/** Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the\n\t * long way around when using {@link #alpha} and starting animations on other tracks.\n\t *\n\t * Mixing with {@link MixBlend#replace} involves finding a rotation between two others, which has two possible solutions:\n\t * the short way or the long way around. The two rotations likely change over time, so which direction is the short or long\n\t * way also changes. If the short way was always chosen, bones would flip to the other side when that direction became the\n\t * long way. TrackEntry chooses the short way the first time it is applied and remembers that direction. */\n\tresetRotationDirections () {\n\t\tthis.timelinesRotation.length = 0;\n\t}\n\n\tgetTrackComplete () {\n\t\tlet duration = this.animationEnd - this.animationStart;\n\t\tif (duration != 0) {\n\t\t\tif (this.loop) return duration * (1 + ((this.trackTime / duration) | 0)); // Completion of next loop.\n\t\t\tif (this.trackTime < duration) return duration; // Before duration.\n\t\t}\n\t\treturn this.trackTime; // Next update.\n\t}\n\n\t/** Returns true if this track entry has been applied at least once.\n\t *

    \n\t * See {@link AnimationState#apply(Skeleton)}. */\n\twasApplied () {\n\t\treturn this.nextTrackLast != -1;\n\t}\n\n\t/** Returns true if there is a {@link #getNext()} track entry and it will become the current track entry during the next\n\t * {@link AnimationState#update(float)}. */\n\tisNextReady () {\n\t\treturn this.next != null && this.nextTrackLast - this.next.delay >= 0;\n\t}\n}\n\nexport class EventQueue {\n\tobjects: Array = [];\n\tdrainDisabled = false;\n\tanimState: AnimationState;\n\n\tconstructor (animState: AnimationState) {\n\t\tthis.animState = animState;\n\t}\n\n\tstart (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.start);\n\t\tthis.objects.push(entry);\n\t\tthis.animState.animationsChanged = true;\n\t}\n\n\tinterrupt (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.interrupt);\n\t\tthis.objects.push(entry);\n\t}\n\n\tend (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.end);\n\t\tthis.objects.push(entry);\n\t\tthis.animState.animationsChanged = true;\n\t}\n\n\tdispose (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.dispose);\n\t\tthis.objects.push(entry);\n\t}\n\n\tcomplete (entry: TrackEntry) {\n\t\tthis.objects.push(EventType.complete);\n\t\tthis.objects.push(entry);\n\t}\n\n\tevent (entry: TrackEntry, event: Event) {\n\t\tthis.objects.push(EventType.event);\n\t\tthis.objects.push(entry);\n\t\tthis.objects.push(event);\n\t}\n\n\tdrain () {\n\t\tif (this.drainDisabled) return;\n\t\tthis.drainDisabled = true;\n\n\t\tlet objects = this.objects;\n\t\tlet listeners = this.animState.listeners;\n\n\t\tfor (let i = 0; i < objects.length; i += 2) {\n\t\t\tlet type = objects[i] as EventType;\n\t\t\tlet entry = objects[i + 1] as TrackEntry;\n\t\t\tswitch (type) {\n\t\t\t\tcase EventType.start:\n\t\t\t\t\tif (entry.listener && entry.listener.start) entry.listener.start(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.start) listener.start(entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.interrupt:\n\t\t\t\t\tif (entry.listener && entry.listener.interrupt) entry.listener.interrupt(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.interrupt) listener.interrupt(entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.end:\n\t\t\t\t\tif (entry.listener && entry.listener.end) entry.listener.end(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.end) listener.end(entry);\n\t\t\t\t\t}\n\t\t\t\t// Fall through.\n\t\t\t\tcase EventType.dispose:\n\t\t\t\t\tif (entry.listener && entry.listener.dispose) entry.listener.dispose(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.dispose) listener.dispose(entry);\n\t\t\t\t\t}\n\t\t\t\t\tthis.animState.trackEntryPool.free(entry);\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.complete:\n\t\t\t\t\tif (entry.listener && entry.listener.complete) entry.listener.complete(entry);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.complete) listener.complete(entry);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase EventType.event:\n\t\t\t\t\tlet event = objects[i++ + 2] as Event;\n\t\t\t\t\tif (entry.listener && entry.listener.event) entry.listener.event(entry, event);\n\t\t\t\t\tfor (let ii = 0; ii < listeners.length; ii++) {\n\t\t\t\t\t\tlet listener = listeners[ii];\n\t\t\t\t\t\tif (listener.event) listener.event(entry, event);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.clear();\n\n\t\tthis.drainDisabled = false;\n\t}\n\n\tclear () {\n\t\tthis.objects.length = 0;\n\t}\n}\n\nexport enum EventType {\n\tstart, interrupt, end, dispose, complete, event\n}\n\n/** The interface to implement for receiving TrackEntry events. It is always safe to call AnimationState methods when receiving\n * events.\n *\n * See TrackEntry {@link TrackEntry#listener} and AnimationState\n * {@link AnimationState#addListener()}. */\nexport interface AnimationStateListener {\n\t/** Invoked when this entry has been set as the current entry. */\n\tstart?: (entry: TrackEntry) => void;\n\n\t/** Invoked when another entry has replaced this entry as the current entry. This entry may continue being applied for\n\t * mixing. */\n\tinterrupt?: (entry: TrackEntry) => void;\n\n\t/** Invoked when this entry is no longer the current entry and will never be applied again. */\n\tend?: (entry: TrackEntry) => void;\n\n\t/** Invoked when this entry will be disposed. This may occur without the entry ever being set as the current entry.\n\t * References to the entry should not be kept after dispose is called, as it may be destroyed or reused. */\n\tdispose?: (entry: TrackEntry) => void;\n\n\t/** Invoked every time this entry's animation completes a loop. */\n\tcomplete?: (entry: TrackEntry) => void;\n\n\t/** Invoked when this entry's animation triggers an event. */\n\tevent?: (entry: TrackEntry, event: Event) => void;\n}\n\nexport abstract class AnimationStateAdapter implements AnimationStateListener {\n\tstart (entry: TrackEntry) {\n\t}\n\n\tinterrupt (entry: TrackEntry) {\n\t}\n\n\tend (entry: TrackEntry) {\n\t}\n\n\tdispose (entry: TrackEntry) {\n\t}\n\n\tcomplete (entry: TrackEntry) {\n\t}\n\n\tevent (entry: TrackEntry, event: Event) {\n\t}\n}\n\n/** 1. A previously applied timeline has set this property.\n *\n * Result: Mix from the current pose to the timeline pose. */\nexport const SUBSEQUENT = 0;\n/** 1. This is the first timeline to set this property.\n * 2. The next track entry applied after this one does not have a timeline to set this property.\n *\n * Result: Mix from the setup pose to the timeline pose. */\nexport const FIRST = 1;\n/** 1) A previously applied timeline has set this property.
    \n * 2) The next track entry to be applied does have a timeline to set this property.
    \n * 3) The next track entry after that one does not have a timeline to set this property.
    \n * Result: Mix from the current pose to the timeline pose, but do not mix out. This avoids \"dipping\" when crossfading\n * animations that key the same property. A subsequent timeline will set this property using a mix. */\nexport const HOLD_SUBSEQUENT = 2;\n/** 1) This is the first timeline to set this property.
    \n * 2) The next track entry to be applied does have a timeline to set this property.
    \n * 3) The next track entry after that one does not have a timeline to set this property.
    \n * Result: Mix from the setup pose to the timeline pose, but do not mix out. This avoids \"dipping\" when crossfading animations\n * that key the same property. A subsequent timeline will set this property using a mix. */\nexport const HOLD_FIRST = 3;\n/** 1. This is the first timeline to set this property.\n * 2. The next track entry to be applied does have a timeline to set this property.\n * 3. The next track entry after that one does have a timeline to set this property.\n * 4. timelineHoldMix stores the first subsequent track entry that does not have a timeline to set this property.\n *\n * Result: The same as HOLD except the mix percentage from the timelineHoldMix track entry is used. This handles when more than\n * 2 track entries in a row have a timeline that sets the same property.\n *\n * Eg, A -> B -> C -> D where A, B, and C have a timeline setting same property, but D does not. When A is applied, to avoid\n * \"dipping\" A is not mixed out, however D (the first entry that doesn't set the property) mixing in is used to mix out A\n * (which affects B and C). Without using D to mix out, A would be applied fully until mixing completes, then snap into\n * place. */\nexport const HOLD_MIX = 4;\n\nexport const SETUP = 1;\nexport const CURRENT = 2;\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation } from \"./Animation.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { StringMap } from \"./Utils.js\";\n\n\n/** Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed. */\nexport class AnimationStateData {\n\t/** The SkeletonData to look up animations when they are specified by name. */\n\tskeletonData: SkeletonData;\n\n\tanimationToMixTime: StringMap = {};\n\n\t/** The mix duration to use when no mix duration has been defined between two animations. */\n\tdefaultMix = 0;\n\n\tconstructor (skeletonData: SkeletonData) {\n\t\tif (!skeletonData) throw new Error(\"skeletonData cannot be null.\");\n\t\tthis.skeletonData = skeletonData;\n\t}\n\n\t/** Sets a mix duration by animation name.\n\t *\n\t * See {@link #setMixWith()}. */\n\tsetMix (fromName: string, toName: string, duration: number) {\n\t\tlet from = this.skeletonData.findAnimation(fromName);\n\t\tif (!from) throw new Error(\"Animation not found: \" + fromName);\n\t\tlet to = this.skeletonData.findAnimation(toName);\n\t\tif (!to) throw new Error(\"Animation not found: \" + toName);\n\t\tthis.setMixWith(from, to, duration);\n\t}\n\n\t/** Sets the mix duration when changing from the specified animation to the other.\n\t *\n\t * See {@link TrackEntry#mixDuration}. */\n\tsetMixWith (from: Animation, to: Animation, duration: number) {\n\t\tif (!from) throw new Error(\"from cannot be null.\");\n\t\tif (!to) throw new Error(\"to cannot be null.\");\n\t\tlet key = from.name + \".\" + to.name;\n\t\tthis.animationToMixTime[key] = duration;\n\t}\n\n\t/** Returns the mix duration to use when changing from the specified animation to the other, or the {@link #defaultMix} if\n\t * no mix duration has been set. */\n\tgetMix (from: Animation, to: Animation) {\n\t\tlet key = from.name + \".\" + to.name;\n\t\tlet value = this.animationToMixTime[key];\n\t\treturn value === undefined ? this.defaultMix : value;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle\n * effects, and more.\n *\n * See {@link SkeletonBounds} and [Bounding Boxes](http://esotericsoftware.com/spine-bounding-boxes) in the Spine User\n * Guide. */\nexport class BoundingBoxAttachment extends VertexAttachment {\n\tcolor = new Color(1, 1, 1, 1);\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new BoundingBoxAttachment(this.name);\n\t\tthis.copyTo(copy);\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { SlotData } from \"../SlotData.js\";\nimport { Color } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment with vertices that make up a polygon used for clipping the rendering of other attachments. */\nexport class ClippingAttachment extends VertexAttachment {\n\t/** Clipping is performed between the clipping polygon's slot and the end slot. Returns null if clipping is done until the end of\n\t * the skeleton's rendering. */\n\tendSlot: SlotData | null = null;\n\n\t// Nonessential.\n\t/** The color of the clipping polygon as it was in Spine. Available only when nonessential data was exported. Clipping polygons\n\t * are not usually rendered at runtime. */\n\tcolor = new Color(0.2275, 0.2275, 0.8078, 1); // ce3a3aff\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new ClippingAttachment(this.name);\n\t\tthis.copyTo(copy);\n\t\tcopy.endSlot = this.endSlot;\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport abstract class Texture {\n\tprotected _image: HTMLImageElement | ImageBitmap | any;\n\n\tconstructor (image: HTMLImageElement | ImageBitmap | any) {\n\t\tthis._image = image;\n\t}\n\n\tgetImage (): HTMLImageElement | ImageBitmap | any {\n\t\treturn this._image;\n\t}\n\n\tabstract setFilters (minFilter: TextureFilter, magFilter: TextureFilter): void;\n\tabstract setWraps (uWrap: TextureWrap, vWrap: TextureWrap): void;\n\tabstract dispose (): void;\n}\n\nexport enum TextureFilter {\n\tNearest = 9728, // WebGLRenderingContext.NEAREST\n\tLinear = 9729, // WebGLRenderingContext.LINEAR\n\tMipMap = 9987, // WebGLRenderingContext.LINEAR_MIPMAP_LINEAR\n\tMipMapNearestNearest = 9984, // WebGLRenderingContext.NEAREST_MIPMAP_NEAREST\n\tMipMapLinearNearest = 9985, // WebGLRenderingContext.LINEAR_MIPMAP_NEAREST\n\tMipMapNearestLinear = 9986, // WebGLRenderingContext.NEAREST_MIPMAP_LINEAR\n\tMipMapLinearLinear = 9987 // WebGLRenderingContext.LINEAR_MIPMAP_LINEAR\n}\n\nexport enum TextureWrap {\n\tMirroredRepeat = 33648, // WebGLRenderingContext.MIRRORED_REPEAT\n\tClampToEdge = 33071, // WebGLRenderingContext.CLAMP_TO_EDGE\n\tRepeat = 10497 // WebGLRenderingContext.REPEAT\n}\n\nexport class TextureRegion {\n\ttexture: any;\n\tu = 0; v = 0;\n\tu2 = 0; v2 = 0;\n\twidth = 0; height = 0;\n\tdegrees = 0;\n\toffsetX = 0; offsetY = 0;\n\toriginalWidth = 0; originalHeight = 0;\n}\n\nexport class FakeTexture extends Texture {\n\tsetFilters (minFilter: TextureFilter, magFilter: TextureFilter) { }\n\tsetWraps (uWrap: TextureWrap, vWrap: TextureWrap) { }\n\tdispose () { }\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { AssetManagerBase } from \"./AssetManagerBase.js\";\nimport { TextureFilter, TextureWrap, Texture, TextureRegion } from \"./Texture.js\";\nimport { Disposable, Utils, StringMap } from \"./Utils.js\";\n\nexport class TextureAtlas implements Disposable {\n\tpages = new Array();\n\tregions = new Array();\n\n\tconstructor (atlasText: string) {\n\t\tlet reader = new TextureAtlasReader(atlasText);\n\t\tlet entry = new Array(4);\n\n\t\tlet pageFields: StringMap<(page: TextureAtlasPage) => void> = {};\n\t\tpageFields[\"size\"] = (page: TextureAtlasPage) => {\n\t\t\tpage!.width = parseInt(entry[1]);\n\t\t\tpage!.height = parseInt(entry[2]);\n\t\t};\n\t\tpageFields[\"format\"] = () => {\n\t\t\t// page.format = Format[tuple[0]]; we don't need format in WebGL\n\t\t};\n\t\tpageFields[\"filter\"] = (page: TextureAtlasPage) => {\n\t\t\tpage!.minFilter = Utils.enumValue(TextureFilter, entry[1]);\n\t\t\tpage!.magFilter = Utils.enumValue(TextureFilter, entry[2]);\n\t\t};\n\t\tpageFields[\"repeat\"] = (page: TextureAtlasPage) => {\n\t\t\tif (entry[1].indexOf('x') != -1) page!.uWrap = TextureWrap.Repeat;\n\t\t\tif (entry[1].indexOf('y') != -1) page!.vWrap = TextureWrap.Repeat;\n\t\t};\n\t\tpageFields[\"pma\"] = (page: TextureAtlasPage) => {\n\t\t\tpage!.pma = entry[1] == \"true\";\n\t\t};\n\n\t\tvar regionFields: StringMap<(region: TextureAtlasRegion) => void> = {};\n\t\tregionFields[\"xy\"] = (region: TextureAtlasRegion) => { // Deprecated, use bounds.\n\t\t\tregion.x = parseInt(entry[1]);\n\t\t\tregion.y = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"size\"] = (region: TextureAtlasRegion) => { // Deprecated, use bounds.\n\t\t\tregion.width = parseInt(entry[1]);\n\t\t\tregion.height = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"bounds\"] = (region: TextureAtlasRegion) => {\n\t\t\tregion.x = parseInt(entry[1]);\n\t\t\tregion.y = parseInt(entry[2]);\n\t\t\tregion.width = parseInt(entry[3]);\n\t\t\tregion.height = parseInt(entry[4]);\n\t\t};\n\t\tregionFields[\"offset\"] = (region: TextureAtlasRegion) => { // Deprecated, use offsets.\n\t\t\tregion.offsetX = parseInt(entry[1]);\n\t\t\tregion.offsetY = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"orig\"] = (region: TextureAtlasRegion) => { // Deprecated, use offsets.\n\t\t\tregion.originalWidth = parseInt(entry[1]);\n\t\t\tregion.originalHeight = parseInt(entry[2]);\n\t\t};\n\t\tregionFields[\"offsets\"] = (region: TextureAtlasRegion) => {\n\t\t\tregion.offsetX = parseInt(entry[1]);\n\t\t\tregion.offsetY = parseInt(entry[2]);\n\t\t\tregion.originalWidth = parseInt(entry[3]);\n\t\t\tregion.originalHeight = parseInt(entry[4]);\n\t\t};\n\t\tregionFields[\"rotate\"] = (region: TextureAtlasRegion) => {\n\t\t\tlet value = entry[1];\n\t\t\tif (value == \"true\")\n\t\t\t\tregion.degrees = 90;\n\t\t\telse if (value != \"false\")\n\t\t\t\tregion.degrees = parseInt(value);\n\t\t};\n\t\tregionFields[\"index\"] = (region: TextureAtlasRegion) => {\n\t\t\tregion.index = parseInt(entry[1]);\n\t\t};\n\n\t\tlet line = reader.readLine();\n\t\t// Ignore empty lines before first entry.\n\t\twhile (line && line.trim().length == 0)\n\t\t\tline = reader.readLine();\n\t\t// Header entries.\n\t\twhile (true) {\n\t\t\tif (!line || line.trim().length == 0) break;\n\t\t\tif (reader.readEntry(entry, line) == 0) break; // Silently ignore all header fields.\n\t\t\tline = reader.readLine();\n\t\t}\n\n\t\t// Page and region entries.\n\t\tlet page: TextureAtlasPage | null = null;\n\t\tlet names: string[] | null = null;\n\t\tlet values: number[][] | null = null;\n\t\twhile (true) {\n\t\t\tif (line === null) break;\n\t\t\tif (line.trim().length == 0) {\n\t\t\t\tpage = null;\n\t\t\t\tline = reader.readLine();\n\t\t\t} else if (!page) {\n\t\t\t\tpage = new TextureAtlasPage(line.trim());\n\t\t\t\twhile (true) {\n\t\t\t\t\tif (reader.readEntry(entry, line = reader.readLine()) == 0) break;\n\t\t\t\t\tlet field = pageFields[entry[0]];\n\t\t\t\t\tif (field) field(page);\n\t\t\t\t}\n\t\t\t\tthis.pages.push(page);\n\t\t\t} else {\n\t\t\t\tlet region = new TextureAtlasRegion(page, line);\n\n\t\t\t\twhile (true) {\n\t\t\t\t\tlet count = reader.readEntry(entry, line = reader.readLine());\n\t\t\t\t\tif (count == 0) break;\n\t\t\t\t\tlet field = regionFields[entry[0]];\n\t\t\t\t\tif (field)\n\t\t\t\t\t\tfield(region);\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (!names) names = [];\n\t\t\t\t\t\tif (!values) values = [];\n\t\t\t\t\t\tnames.push(entry[0]);\n\t\t\t\t\t\tlet entryValues: number[] = [];\n\t\t\t\t\t\tfor (let i = 0; i < count; i++)\n\t\t\t\t\t\t\tentryValues.push(parseInt(entry[i + 1]));\n\t\t\t\t\t\tvalues.push(entryValues);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (region.originalWidth == 0 && region.originalHeight == 0) {\n\t\t\t\t\tregion.originalWidth = region.width;\n\t\t\t\t\tregion.originalHeight = region.height;\n\t\t\t\t}\n\t\t\t\tif (names && names.length > 0 && values && values.length > 0) {\n\t\t\t\t\tregion.names = names;\n\t\t\t\t\tregion.values = values;\n\t\t\t\t\tnames = null;\n\t\t\t\t\tvalues = null;\n\t\t\t\t}\n\t\t\t\tregion.u = region.x / page.width;\n\t\t\t\tregion.v = region.y / page.height;\n\t\t\t\tif (region.degrees == 90) {\n\t\t\t\t\tregion.u2 = (region.x + region.height) / page.width;\n\t\t\t\t\tregion.v2 = (region.y + region.width) / page.height;\n\t\t\t\t} else {\n\t\t\t\t\tregion.u2 = (region.x + region.width) / page.width;\n\t\t\t\t\tregion.v2 = (region.y + region.height) / page.height;\n\t\t\t\t}\n\t\t\t\tthis.regions.push(region);\n\t\t\t}\n\t\t}\n\t}\n\n\tfindRegion (name: string): TextureAtlasRegion | null {\n\t\tfor (let i = 0; i < this.regions.length; i++) {\n\t\t\tif (this.regions[i].name == name) {\n\t\t\t\treturn this.regions[i];\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tsetTextures (assetManager: AssetManagerBase, pathPrefix: string = \"\") {\n\t\tfor (let page of this.pages)\n\t\t\tpage.setTexture(assetManager.get(pathPrefix + page.name));\n\t}\n\n\tdispose () {\n\t\tfor (let i = 0; i < this.pages.length; i++) {\n\t\t\tthis.pages[i].texture?.dispose();\n\t\t}\n\t}\n}\n\nclass TextureAtlasReader {\n\tlines: Array;\n\tindex: number = 0;\n\n\tconstructor (text: string) {\n\t\tthis.lines = text.split(/\\r\\n|\\r|\\n/);\n\t}\n\n\treadLine (): string | null {\n\t\tif (this.index >= this.lines.length)\n\t\t\treturn null;\n\t\treturn this.lines[this.index++];\n\t}\n\n\treadEntry (entry: string[], line: string | null): number {\n\t\tif (!line) return 0;\n\t\tline = line.trim();\n\t\tif (line.length == 0) return 0;\n\n\t\tlet colon = line.indexOf(':');\n\t\tif (colon == -1) return 0;\n\t\tentry[0] = line.substr(0, colon).trim();\n\t\tfor (let i = 1, lastMatch = colon + 1; ; i++) {\n\t\t\tlet comma = line.indexOf(',', lastMatch);\n\t\t\tif (comma == -1) {\n\t\t\t\tentry[i] = line.substr(lastMatch).trim();\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tentry[i] = line.substr(lastMatch, comma - lastMatch).trim();\n\t\t\tlastMatch = comma + 1;\n\t\t\tif (i == 4) return 4;\n\t\t}\n\t}\n}\n\nexport class TextureAtlasPage {\n\tname: string;\n\tminFilter: TextureFilter = TextureFilter.Nearest;\n\tmagFilter: TextureFilter = TextureFilter.Nearest;\n\tuWrap: TextureWrap = TextureWrap.ClampToEdge;\n\tvWrap: TextureWrap = TextureWrap.ClampToEdge;\n\ttexture: Texture | null = null;\n\twidth: number = 0;\n\theight: number = 0;\n\tpma: boolean = false;\n\tregions = new Array();\n\n\tconstructor (name: string) {\n\t\tthis.name = name;\n\t}\n\n\tsetTexture (texture: Texture) {\n\t\tthis.texture = texture;\n\t\ttexture.setFilters(this.minFilter, this.magFilter);\n\t\ttexture.setWraps(this.uWrap, this.vWrap);\n\t\tfor (let region of this.regions)\n\t\t\tregion.texture = texture;\n\t}\n}\n\nexport class TextureAtlasRegion extends TextureRegion {\n\tpage: TextureAtlasPage;\n\tname: string;\n\tx: number = 0;\n\ty: number = 0;\n\toffsetX: number = 0;\n\toffsetY: number = 0;\n\toriginalWidth: number = 0;\n\toriginalHeight: number = 0;\n\tindex: number = 0;\n\tdegrees: number = 0;\n\tnames: string[] | null = null;\n\tvalues: number[][] | null = null;\n\n\tconstructor (page: TextureAtlasPage, name: string) {\n\t\tsuper();\n\t\tthis.page = page;\n\t\tthis.name = name;\n\t\tpage.regions.push(this);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TextureRegion } from \"../Texture.js\";\nimport { TextureAtlasRegion } from \"../TextureAtlas.js\";\nimport { Color, NumberArrayLike, Utils } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Sequence } from \"./Sequence.js\";\nimport { Slot } from \"../Slot.js\";\n\n/** An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not\n * supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh.\n *\n * See [Mesh attachments](http://esotericsoftware.com/spine-meshes) in the Spine User Guide. */\nexport class MeshAttachment extends VertexAttachment implements HasTextureRegion {\n\tregion: TextureRegion | null = null;\n\n\t/** The name of the texture region for this attachment. */\n\tpath: string;\n\n\t/** The UV pair for each vertex, normalized within the texture region. */\n\tregionUVs: NumberArrayLike = [];\n\n\t/** The UV pair for each vertex, normalized within the entire texture.\n\t *\n\t * See {@link #updateUVs}. */\n\tuvs: NumberArrayLike = [];\n\n\t/** Triplets of vertex indices which describe the mesh's triangulation. */\n\ttriangles: Array = [];\n\n\t/** The color to tint the mesh. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\t/** The width of the mesh's image. Available only when nonessential data was exported. */\n\twidth: number = 0;\n\n\t/** The height of the mesh's image. Available only when nonessential data was exported. */\n\theight: number = 0;\n\n\t/** The number of entries at the beginning of {@link #vertices} that make up the mesh hull. */\n\thullLength: number = 0;\n\n\t/** Vertex index pairs describing edges for controling triangulation. Mesh triangles will never cross edges. Only available if\n\t * nonessential data was exported. Triangulation is not performed at runtime. */\n\tedges: Array = [];\n\n\tprivate parentMesh: MeshAttachment | null = null;\n\n\tsequence: Sequence | null = null;\n\n\ttempColor = new Color(0, 0, 0, 0);\n\n\tconstructor (name: string, path: string) {\n\t\tsuper(name);\n\t\tthis.path = path;\n\t}\n\n\t/** Calculates {@link #uvs} using the {@link #regionUVs} and region. Must be called if the region, the region's properties, or\n\t * the {@link #regionUVs} are changed. */\n\tupdateRegion () {\n\t\tif (!this.region) throw new Error(\"Region not set.\");\n\t\tlet regionUVs = this.regionUVs;\n\t\tif (!this.uvs || this.uvs.length != regionUVs.length) this.uvs = Utils.newFloatArray(regionUVs.length);\n\t\tlet uvs = this.uvs;\n\t\tlet n = this.uvs.length;\n\t\tlet u = this.region.u, v = this.region.v, width = 0, height = 0;\n\t\tif (this.region instanceof TextureAtlasRegion) {\n\t\t\tlet region = this.region, page = region.page;\n\t\t\tlet textureWidth = page.width, textureHeight = page.height;\n\t\t\tswitch (region.degrees) {\n\t\t\t\tcase 90:\n\t\t\t\t\tu -= (region.originalHeight - region.offsetY - region.height) / textureWidth;\n\t\t\t\t\tv -= (region.originalWidth - region.offsetX - region.width) / textureHeight;\n\t\t\t\t\twidth = region.originalHeight / textureWidth;\n\t\t\t\t\theight = region.originalWidth / textureHeight;\n\t\t\t\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\t\t\t\tuvs[i] = u + regionUVs[i + 1] * width;\n\t\t\t\t\t\tuvs[i + 1] = v + (1 - regionUVs[i]) * height;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\tcase 180:\n\t\t\t\t\tu -= (region.originalWidth - region.offsetX - region.width) / textureWidth;\n\t\t\t\t\tv -= region.offsetY / textureHeight;\n\t\t\t\t\twidth = region.originalWidth / textureWidth;\n\t\t\t\t\theight = region.originalHeight / textureHeight;\n\t\t\t\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\t\t\t\tuvs[i] = u + (1 - regionUVs[i]) * width;\n\t\t\t\t\t\tuvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\tcase 270:\n\t\t\t\t\tu -= region.offsetY / textureWidth;\n\t\t\t\t\tv -= region.offsetX / textureHeight;\n\t\t\t\t\twidth = region.originalHeight / textureWidth;\n\t\t\t\t\theight = region.originalWidth / textureHeight;\n\t\t\t\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\t\t\t\tuvs[i] = u + (1 - regionUVs[i + 1]) * width;\n\t\t\t\t\t\tuvs[i + 1] = v + regionUVs[i] * height;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tu -= region.offsetX / textureWidth;\n\t\t\tv -= (region.originalHeight - region.offsetY - region.height) / textureHeight;\n\t\t\twidth = region.originalWidth / textureWidth;\n\t\t\theight = region.originalHeight / textureHeight;\n\t\t} else if (!this.region) {\n\t\t\tu = v = 0;\n\t\t\twidth = height = 1;\n\t\t} else {\n\t\t\twidth = this.region.u2 - u;\n\t\t\theight = this.region.v2 - v;\n\t\t}\n\n\t\tfor (let i = 0; i < n; i += 2) {\n\t\t\tuvs[i] = u + regionUVs[i] * width;\n\t\t\tuvs[i + 1] = v + regionUVs[i + 1] * height;\n\t\t}\n\t}\n\n\t/** The parent mesh if this is a linked mesh, else null. A linked mesh shares the {@link #bones}, {@link #vertices},\n\t * {@link #regionUVs}, {@link #triangles}, {@link #hullLength}, {@link #edges}, {@link #width}, and {@link #height} with the\n\t * parent mesh, but may have a different {@link #name} or {@link #path} (and therefore a different texture). */\n\tgetParentMesh () {\n\t\treturn this.parentMesh;\n\t}\n\n\t/** @param parentMesh May be null. */\n\tsetParentMesh (parentMesh: MeshAttachment) {\n\t\tthis.parentMesh = parentMesh;\n\t\tif (parentMesh) {\n\t\t\tthis.bones = parentMesh.bones;\n\t\t\tthis.vertices = parentMesh.vertices;\n\t\t\tthis.worldVerticesLength = parentMesh.worldVerticesLength;\n\t\t\tthis.regionUVs = parentMesh.regionUVs;\n\t\t\tthis.triangles = parentMesh.triangles;\n\t\t\tthis.hullLength = parentMesh.hullLength;\n\t\t\tthis.worldVerticesLength = parentMesh.worldVerticesLength\n\t\t}\n\t}\n\n\tcopy (): Attachment {\n\t\tif (this.parentMesh) return this.newLinkedMesh();\n\n\t\tlet copy = new MeshAttachment(this.name, this.path);\n\t\tcopy.region = this.region;\n\t\tcopy.color.setFromColor(this.color);\n\n\t\tthis.copyTo(copy);\n\t\tcopy.regionUVs = new Array(this.regionUVs.length);\n\t\tUtils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length);\n\t\tcopy.uvs = new Array(this.uvs.length);\n\t\tUtils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length);\n\t\tcopy.triangles = new Array(this.triangles.length);\n\t\tUtils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length);\n\t\tcopy.hullLength = this.hullLength;\n\n\t\tcopy.sequence = this.sequence != null ? this.sequence.copy() : null;\n\n\t\t// Nonessential.\n\t\tif (this.edges) {\n\t\t\tcopy.edges = new Array(this.edges.length);\n\t\t\tUtils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length);\n\t\t}\n\t\tcopy.width = this.width;\n\t\tcopy.height = this.height;\n\n\t\treturn copy;\n\t}\n\n\tcomputeWorldVertices (slot: Slot, start: number, count: number, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tif (this.sequence != null) this.sequence.apply(slot, this);\n\t\tsuper.computeWorldVertices(slot, start, count, worldVertices, offset, stride);\n\t}\n\n\t/** Returns a new mesh with the {@link #parentMesh} set to this mesh's parent mesh, if any, else to this mesh. **/\n\tnewLinkedMesh (): MeshAttachment {\n\t\tlet copy = new MeshAttachment(this.name, this.path);\n\t\tcopy.region = this.region;\n\t\tcopy.color.setFromColor(this.color);\n\t\tcopy.timelineAttachment = this.timelineAttachment;\n\t\tcopy.setParentMesh(this.parentMesh ? this.parentMesh : this);\n\t\tif (copy.region != null) copy.updateRegion();\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color, Utils } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment whose vertices make up a composite Bezier curve.\n *\n * See {@link PathConstraint} and [Paths](http://esotericsoftware.com/spine-paths) in the Spine User Guide. */\nexport class PathAttachment extends VertexAttachment {\n\n\t/** The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve. */\n\tlengths: Array = [];\n\n\t/** If true, the start and end knots are connected. */\n\tclosed = false;\n\n\t/** If true, additional calculations are performed to make calculating positions along the path more accurate. If false, fewer\n\t * calculations are performed but calculating positions along the path is less accurate. */\n\tconstantSpeed = false;\n\n\t/** The color of the path as it was in Spine. Available only when nonessential data was exported. Paths are not usually\n\t * rendered at runtime. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new PathAttachment(this.name);\n\t\tthis.copyTo(copy);\n\t\tcopy.lengths = new Array(this.lengths.length);\n\t\tUtils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length);\n\t\tcopy.closed = closed;\n\t\tcopy.constantSpeed = this.constantSpeed;\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"../Bone.js\";\nimport { Color, Vector2, MathUtils } from \"../Utils.js\";\nimport { VertexAttachment, Attachment } from \"./Attachment.js\";\n\n/** An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be\n * used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a\n * skin.\n *\n * See [Point Attachments](http://esotericsoftware.com/spine-point-attachments) in the Spine User Guide. */\nexport class PointAttachment extends VertexAttachment {\n\tx: number = 0;\n\ty: number = 0;\n\trotation: number = 0;\n\n\t/** The color of the point attachment as it was in Spine. Available only when nonessential data was exported. Point attachments\n\t * are not usually rendered at runtime. */\n\tcolor = new Color(0.38, 0.94, 0, 1);\n\n\tconstructor (name: string) {\n\t\tsuper(name);\n\t}\n\n\tcomputeWorldPosition (bone: Bone, point: Vector2) {\n\t\tpoint.x = this.x * bone.a + this.y * bone.b + bone.worldX;\n\t\tpoint.y = this.x * bone.c + this.y * bone.d + bone.worldY;\n\t\treturn point;\n\t}\n\n\tcomputeWorldRotation (bone: Bone) {\n\t\tconst r = this.rotation * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);\n\t\tconst x = cos * bone.a + sin * bone.b;\n\t\tconst y = cos * bone.c + sin * bone.d;\n\t\treturn MathUtils.atan2Deg(y, x);\t\t\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new PointAttachment(this.name);\n\t\tcopy.x = this.x;\n\t\tcopy.y = this.y;\n\t\tcopy.rotation = this.rotation;\n\t\tcopy.color.setFromColor(this.color);\n\t\treturn copy;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"../Bone.js\";\nimport { TextureRegion } from \"../Texture.js\";\nimport { Color, MathUtils, NumberArrayLike, Utils } from \"../Utils.js\";\nimport { Attachment } from \"./Attachment.js\";\nimport { HasTextureRegion } from \"./HasTextureRegion.js\";\nimport { Sequence } from \"./Sequence.js\";\nimport { Slot } from \"../Slot.js\";\n\n/** An attachment that displays a textured quadrilateral.\n *\n * See [Region attachments](http://esotericsoftware.com/spine-regions) in the Spine User Guide. */\nexport class RegionAttachment extends Attachment implements HasTextureRegion {\n\t/** The local x translation. */\n\tx = 0;\n\n\t/** The local y translation. */\n\ty = 0;\n\n\t/** The local scaleX. */\n\tscaleX = 1;\n\n\t/** The local scaleY. */\n\tscaleY = 1;\n\n\t/** The local rotation. */\n\trotation = 0;\n\n\t/** The width of the region attachment in Spine. */\n\twidth = 0;\n\n\t/** The height of the region attachment in Spine. */\n\theight = 0;\n\n\t/** The color to tint the region attachment. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\t/** The name of the texture region for this attachment. */\n\tpath: string;\n\n\tregion: TextureRegion | null = null;\n\tsequence: Sequence | null = null;\n\n\t/** For each of the 4 vertices, a pair of x,y values that is the local position of the vertex.\n\t *\n\t * See {@link #updateOffset()}. */\n\toffset = Utils.newFloatArray(8);\n\n\tuvs = Utils.newFloatArray(8);\n\n\ttempColor = new Color(1, 1, 1, 1);\n\n\tconstructor (name: string, path: string) {\n\t\tsuper(name);\n\t\tthis.path = path;\n\t}\n\n\t/** Calculates the {@link #offset} using the region settings. Must be called after changing region settings. */\n\tupdateRegion (): void {\n\t\tif (!this.region) throw new Error(\"Region not set.\");\n\t\tlet region = this.region;\n\t\tlet uvs = this.uvs;\n\n\t\tif (region == null) {\n\t\t\tuvs[0] = 0;\n\t\t\tuvs[1] = 0;\n\t\t\tuvs[2] = 0;\n\t\t\tuvs[3] = 1;\n\t\t\tuvs[4] = 1;\n\t\t\tuvs[5] = 1;\n\t\t\tuvs[6] = 1;\n\t\t\tuvs[7] = 0;\n\t\t\treturn;\n\t\t}\n\n\t\tlet regionScaleX = this.width / this.region.originalWidth * this.scaleX;\n\t\tlet regionScaleY = this.height / this.region.originalHeight * this.scaleY;\n\t\tlet localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX;\n\t\tlet localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY;\n\t\tlet localX2 = localX + this.region.width * regionScaleX;\n\t\tlet localY2 = localY + this.region.height * regionScaleY;\n\t\tlet radians = this.rotation * MathUtils.degRad;\n\t\tlet cos = Math.cos(radians);\n\t\tlet sin = Math.sin(radians);\n\t\tlet x = this.x, y = this.y;\n\t\tlet localXCos = localX * cos + x;\n\t\tlet localXSin = localX * sin;\n\t\tlet localYCos = localY * cos + y;\n\t\tlet localYSin = localY * sin;\n\t\tlet localX2Cos = localX2 * cos + x;\n\t\tlet localX2Sin = localX2 * sin;\n\t\tlet localY2Cos = localY2 * cos + y;\n\t\tlet localY2Sin = localY2 * sin;\n\t\tlet offset = this.offset;\n\t\toffset[0] = localXCos - localYSin;\n\t\toffset[1] = localYCos + localXSin;\n\t\toffset[2] = localXCos - localY2Sin;\n\t\toffset[3] = localY2Cos + localXSin;\n\t\toffset[4] = localX2Cos - localY2Sin;\n\t\toffset[5] = localY2Cos + localX2Sin;\n\t\toffset[6] = localX2Cos - localYSin;\n\t\toffset[7] = localYCos + localX2Sin;\n\n\t\tif (region.degrees == 90) {\n\t\t\tuvs[0] = region.u2;\n\t\t\tuvs[1] = region.v2;\n\t\t\tuvs[2] = region.u;\n\t\t\tuvs[3] = region.v2;\n\t\t\tuvs[4] = region.u;\n\t\t\tuvs[5] = region.v;\n\t\t\tuvs[6] = region.u2;\n\t\t\tuvs[7] = region.v;\n\t\t} else {\n\t\t\tuvs[0] = region.u;\n\t\t\tuvs[1] = region.v2;\n\t\t\tuvs[2] = region.u;\n\t\t\tuvs[3] = region.v;\n\t\t\tuvs[4] = region.u2;\n\t\t\tuvs[5] = region.v;\n\t\t\tuvs[6] = region.u2;\n\t\t\tuvs[7] = region.v2;\n\t\t}\n\t}\n\n\t/** Transforms the attachment's four vertices to world coordinates. If the attachment has a {@link #sequence}, the region may\n\t * be changed.\n\t *

    \n\t * See World transforms in the Spine\n\t * Runtimes Guide.\n\t * @param worldVertices The output world vertices. Must have a length >= offset + 8.\n\t * @param offset The worldVertices index to begin writing values.\n\t * @param stride The number of worldVertices entries between the value pairs written. */\n\tcomputeWorldVertices (slot: Slot, worldVertices: NumberArrayLike, offset: number, stride: number) {\n\t\tif (this.sequence != null)\n\t\t\tthis.sequence.apply(slot, this);\n\n\t\tlet bone = slot.bone;\n\t\tlet vertexOffset = this.offset;\n\t\tlet x = bone.worldX, y = bone.worldY;\n\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\tlet offsetX = 0, offsetY = 0;\n\n\t\toffsetX = vertexOffset[0];\n\t\toffsetY = vertexOffset[1];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // br\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t\toffset += stride;\n\n\t\toffsetX = vertexOffset[2];\n\t\toffsetY = vertexOffset[3];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // bl\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t\toffset += stride;\n\n\t\toffsetX = vertexOffset[4];\n\t\toffsetY = vertexOffset[5];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // ul\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t\toffset += stride;\n\n\t\toffsetX = vertexOffset[6];\n\t\toffsetY = vertexOffset[7];\n\t\tworldVertices[offset] = offsetX * a + offsetY * b + x; // ur\n\t\tworldVertices[offset + 1] = offsetX * c + offsetY * d + y;\n\t}\n\n\tcopy (): Attachment {\n\t\tlet copy = new RegionAttachment(this.name, this.path);\n\t\tcopy.region = this.region;\n\t\tcopy.x = this.x;\n\t\tcopy.y = this.y;\n\t\tcopy.scaleX = this.scaleX;\n\t\tcopy.scaleY = this.scaleY;\n\t\tcopy.rotation = this.rotation;\n\t\tcopy.width = this.width;\n\t\tcopy.height = this.height;\n\t\tUtils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8);\n\t\tUtils.arrayCopy(this.offset, 0, copy.offset, 0, 8);\n\t\tcopy.color.setFromColor(this.color);\n\t\tcopy.sequence = this.sequence != null ? this.sequence.copy() : null;\n\t\treturn copy;\n\t}\n\n\tstatic X1 = 0;\n\tstatic Y1 = 1;\n\tstatic C1R = 2;\n\tstatic C1G = 3;\n\tstatic C1B = 4;\n\tstatic C1A = 5;\n\tstatic U1 = 6;\n\tstatic V1 = 7;\n\n\tstatic X2 = 8;\n\tstatic Y2 = 9;\n\tstatic C2R = 10;\n\tstatic C2G = 11;\n\tstatic C2B = 12;\n\tstatic C2A = 13;\n\tstatic U2 = 14;\n\tstatic V2 = 15;\n\n\tstatic X3 = 16;\n\tstatic Y3 = 17;\n\tstatic C3R = 18;\n\tstatic C3G = 19;\n\tstatic C3B = 20;\n\tstatic C3A = 21;\n\tstatic U3 = 22;\n\tstatic V3 = 23;\n\n\tstatic X4 = 24;\n\tstatic Y4 = 25;\n\tstatic C4R = 26;\n\tstatic C4G = 27;\n\tstatic C4B = 28;\n\tstatic C4A = 29;\n\tstatic U4 = 30;\n\tstatic V4 = 31;\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { AttachmentLoader } from \"./attachments/AttachmentLoader.js\";\nimport { BoundingBoxAttachment } from \"./attachments/BoundingBoxAttachment.js\";\nimport { ClippingAttachment } from \"./attachments/ClippingAttachment.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { PathAttachment } from \"./attachments/PathAttachment.js\";\nimport { PointAttachment } from \"./attachments/PointAttachment.js\";\nimport { RegionAttachment } from \"./attachments/RegionAttachment.js\";\nimport { Skin } from \"./Skin.js\";\nimport { TextureAtlas } from \"./TextureAtlas.js\";\nimport { Sequence } from \"./attachments/Sequence.js\"\n\n/** An {@link AttachmentLoader} that configures attachments using texture regions from an {@link TextureAtlas}.\n *\n * See [Loading skeleton data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the\n * Spine Runtimes Guide. */\nexport class AtlasAttachmentLoader implements AttachmentLoader {\n\tatlas: TextureAtlas;\n\n\tconstructor (atlas: TextureAtlas) {\n\t\tthis.atlas = atlas;\n\t}\n\n\tloadSequence (name: string, basePath: string, sequence: Sequence) {\n\t\tlet regions = sequence.regions;\n\t\tfor (let i = 0, n = regions.length; i < n; i++) {\n\t\t\tlet path = sequence.getPath(basePath, i);\n\t\t\tlet region = this.atlas.findRegion(path);\n\t\t\tif (region == null) throw new Error(\"Region not found in atlas: \" + path + \" (sequence: \" + name + \")\");\n\t\t\tregions[i] = region;\n\t\t}\n\t}\n\n\tnewRegionAttachment (skin: Skin, name: string, path: string, sequence: Sequence): RegionAttachment {\n\t\tlet attachment = new RegionAttachment(name, path);\n\t\tif (sequence != null) {\n\t\t\tthis.loadSequence(name, path, sequence);\n\t\t} else {\n\t\t\tlet region = this.atlas.findRegion(path);\n\t\t\tif (!region) throw new Error(\"Region not found in atlas: \" + path + \" (region attachment: \" + name + \")\");\n\t\t\tattachment.region = region;\n\t\t}\n\t\treturn attachment;\n\t}\n\n\tnewMeshAttachment (skin: Skin, name: string, path: string, sequence: Sequence): MeshAttachment {\n\t\tlet attachment = new MeshAttachment(name, path);\n\t\tif (sequence != null) {\n\t\t\tthis.loadSequence(name, path, sequence);\n\t\t} else {\n\t\t\tlet region = this.atlas.findRegion(path);\n\t\t\tif (!region) throw new Error(\"Region not found in atlas: \" + path + \" (mesh attachment: \" + name + \")\");\n\t\t\tattachment.region = region;\n\t\t}\n\t\treturn attachment;\n\t}\n\n\tnewBoundingBoxAttachment (skin: Skin, name: string): BoundingBoxAttachment {\n\t\treturn new BoundingBoxAttachment(name);\n\t}\n\n\tnewPathAttachment (skin: Skin, name: string): PathAttachment {\n\t\treturn new PathAttachment(name);\n\t}\n\n\tnewPointAttachment (skin: Skin, name: string): PointAttachment {\n\t\treturn new PointAttachment(name);\n\t}\n\n\tnewClippingAttachment (skin: Skin, name: string): ClippingAttachment {\n\t\treturn new ClippingAttachment(name);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color } from \"./Utils.js\";\n\n/** Stores the setup pose for a {@link Bone}. */\nexport class BoneData {\n\t/** The index of the bone in {@link Skeleton#getBones()}. */\n\tindex: number = 0;\n\n\t/** The name of the bone, which is unique across all bones in the skeleton. */\n\tname: string;\n\n\t/** @returns May be null. */\n\tparent: BoneData | null = null;\n\n\t/** The bone's length. */\n\tlength: number = 0;\n\n\t/** The local x translation. */\n\tx = 0;\n\n\t/** The local y translation. */\n\ty = 0;\n\n\t/** The local rotation in degrees, counter clockwise. */\n\trotation = 0;\n\n\t/** The local scaleX. */\n\tscaleX = 1;\n\n\t/** The local scaleY. */\n\tscaleY = 1;\n\n\t/** The local shearX. */\n\tshearX = 0;\n\n\t/** The local shearX. */\n\tshearY = 0;\n\n\t/** The transform mode for how parent world transforms affect this bone. */\n\tinherit = Inherit.Normal;\n\n\t/** When true, {@link Skeleton#updateWorldTransform()} only updates this bone if the {@link Skeleton#skin} contains this\n\t * bone.\n\t * @see Skin#bones */\n\tskinRequired = false;\n\n\t/** The color of the bone as it was in Spine. Available only when nonessential data was exported. Bones are not usually\n\t * rendered at runtime. */\n\tcolor = new Color();\n\n\t/** The bone icon as it was in Spine, or null if nonessential data was not exported. */\n\ticon?: string;\n\n\t/** False if the bone was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */\n\tvisible = false;\n\n\tconstructor (index: number, name: string, parent: BoneData | null) {\n\t\tif (index < 0) throw new Error(\"index must be >= 0.\");\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.index = index;\n\t\tthis.name = name;\n\t\tthis.parent = parent;\n\t}\n}\n\n/** Determines how a bone inherits world transforms from parent bones. */\nexport enum Inherit { Normal, OnlyTranslation, NoRotationOrReflection, NoScale, NoScaleOrReflection }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData, Inherit } from \"./BoneData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { MathUtils, Vector2 } from \"./Utils.js\";\n\n/** Stores a bone's current pose.\n *\n * A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a\n * local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a\n * constraint or application code modifies the world transform after it was computed from the local transform. */\nexport class Bone implements Updatable {\n\t/** The bone's setup pose data. */\n\tdata: BoneData;\n\n\t/** The skeleton this bone belongs to. */\n\tskeleton: Skeleton;\n\n\t/** The parent bone, or null if this is the root bone. */\n\tparent: Bone | null = null;\n\n\t/** The immediate children of this bone. */\n\tchildren = new Array();\n\n\t/** The local x translation. */\n\tx = 0;\n\n\t/** The local y translation. */\n\ty = 0;\n\n\t/** The local rotation in degrees, counter clockwise. */\n\trotation = 0;\n\n\t/** The local scaleX. */\n\tscaleX = 0;\n\n\t/** The local scaleY. */\n\tscaleY = 0;\n\n\t/** The local shearX. */\n\tshearX = 0;\n\n\t/** The local shearY. */\n\tshearY = 0;\n\n\t/** The applied local x translation. */\n\tax = 0;\n\n\t/** The applied local y translation. */\n\tay = 0;\n\n\t/** The applied local rotation in degrees, counter clockwise. */\n\tarotation = 0;\n\n\t/** The applied local scaleX. */\n\tascaleX = 0;\n\n\t/** The applied local scaleY. */\n\tascaleY = 0;\n\n\t/** The applied local shearX. */\n\tashearX = 0;\n\n\t/** The applied local shearY. */\n\tashearY = 0;\n\n\t/** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\ta = 0;\n\n\t/** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\tb = 0;\n\n\t/** Part of the world transform matrix for the X axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\tc = 0;\n\n\t/** Part of the world transform matrix for the Y axis. If changed, {@link #updateAppliedTransform()} should be called. */\n\td = 0;\n\n\t/** The world X position. If changed, {@link #updateAppliedTransform()} should be called. */\n\tworldY = 0;\n\n\t/** The world Y position. If changed, {@link #updateAppliedTransform()} should be called. */\n\tworldX = 0;\n\n\tinherit: Inherit = Inherit.Normal;\n\n\tsorted = false;\n\tactive = false;\n\n\t/** @param parent May be null. */\n\tconstructor (data: BoneData, skeleton: Skeleton, parent: Bone | null) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\t\tthis.skeleton = skeleton;\n\t\tthis.parent = parent;\n\t\tthis.setToSetupPose();\n\t}\n\n\t/** Returns false when the bone has not been computed because {@link BoneData#skinRequired} is true and the\n\t * {@link Skeleton#skin active skin} does not {@link Skin#bones contain} this bone. */\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\t/** Computes the world transform using the parent bone and this bone's local applied transform. */\n\tupdate (physics: Physics) {\n\t\tthis.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY);\n\t}\n\n\t/** Computes the world transform using the parent bone and this bone's local transform.\n\t *\n\t * See {@link #updateWorldTransformWith()}. */\n\tupdateWorldTransform () {\n\t\tthis.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);\n\t}\n\n\t/** Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the\n\t * specified local transform. Child bones are not updated.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide. */\n\tupdateWorldTransformWith (x: number, y: number, rotation: number, scaleX: number, scaleY: number, shearX: number, shearY: number) {\n\t\tthis.ax = x;\n\t\tthis.ay = y;\n\t\tthis.arotation = rotation;\n\t\tthis.ascaleX = scaleX;\n\t\tthis.ascaleY = scaleY;\n\t\tthis.ashearX = shearX;\n\t\tthis.ashearY = shearY;\n\n\t\tlet parent = this.parent;\n\t\tif (!parent) { // Root bone.\n\t\t\tlet skeleton = this.skeleton;\n\t\t\tconst sx = skeleton.scaleX, sy = skeleton.scaleY;\n\t\t\tconst rx = (rotation + shearX) * MathUtils.degRad;\n\t\t\tconst ry = (rotation + 90 + shearY) * MathUtils.degRad;\n\t\t\tthis.a = Math.cos(rx) * scaleX * sx;\n\t\t\tthis.b = Math.cos(ry) * scaleY * sx;\n\t\t\tthis.c = Math.sin(rx) * scaleX * sy;\n\t\t\tthis.d = Math.sin(ry) * scaleY * sy;\n\t\t\tthis.worldX = x * sx + skeleton.x;\n\t\t\tthis.worldY = y * sy + skeleton.y;\n\t\t\treturn;\n\t\t}\n\n\t\tlet pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;\n\t\tthis.worldX = pa * x + pb * y + parent.worldX;\n\t\tthis.worldY = pc * x + pd * y + parent.worldY;\n\n\t\tswitch (this.inherit) {\n\t\t\tcase Inherit.Normal: {\n\t\t\t\tconst rx = (rotation + shearX) * MathUtils.degRad;\n\t\t\t\tconst ry = (rotation + 90 + shearY) * MathUtils.degRad;\n\t\t\t\tconst la = Math.cos(rx) * scaleX;\n\t\t\t\tconst lb = Math.cos(ry) * scaleY;\n\t\t\t\tconst lc = Math.sin(rx) * scaleX;\n\t\t\t\tconst ld = Math.sin(ry) * scaleY;\n\t\t\t\tthis.a = pa * la + pb * lc;\n\t\t\t\tthis.b = pa * lb + pb * ld;\n\t\t\t\tthis.c = pc * la + pd * lc;\n\t\t\t\tthis.d = pc * lb + pd * ld;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase Inherit.OnlyTranslation: {\n\t\t\t\tconst rx = (rotation + shearX) * MathUtils.degRad;\n\t\t\t\tconst ry = (rotation + 90 + shearY) * MathUtils.degRad;\n\t\t\t\tthis.a = Math.cos(rx) * scaleX;\n\t\t\t\tthis.b = Math.cos(ry) * scaleY;\n\t\t\t\tthis.c = Math.sin(rx) * scaleX;\n\t\t\t\tthis.d = Math.sin(ry) * scaleY;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Inherit.NoRotationOrReflection: {\n\t\t\t\tlet sx = 1 / this.skeleton.scaleX, sy = 1 / this.skeleton.scaleY;\n\t\t\t\tpa *= sx;\n\t\t\t\tpc *= sy;\n\t\t\t\tlet s = pa * pa + pc * pc;\n\t\t\t\tlet prx = 0;\n\t\t\t\tif (s > 0.0001) {\n\t\t\t\t\ts = Math.abs(pa * pd * sy - pb * sx * pc) / s;\n\t\t\t\t\tpb = pc * s;\n\t\t\t\t\tpd = pa * s;\n\t\t\t\t\tprx = Math.atan2(pc, pa) * MathUtils.radDeg;\n\t\t\t\t} else {\n\t\t\t\t\tpa = 0;\n\t\t\t\t\tpc = 0;\n\t\t\t\t\tprx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg;\n\t\t\t\t}\n\t\t\t\tconst rx = (rotation + shearX - prx) * MathUtils.degRad;\n\t\t\t\tconst ry = (rotation + shearY - prx + 90) * MathUtils.degRad;\n\t\t\t\tconst la = Math.cos(rx) * scaleX;\n\t\t\t\tconst lb = Math.cos(ry) * scaleY;\n\t\t\t\tconst lc = Math.sin(rx) * scaleX;\n\t\t\t\tconst ld = Math.sin(ry) * scaleY;\n\t\t\t\tthis.a = pa * la - pb * lc;\n\t\t\t\tthis.b = pa * lb - pb * ld;\n\t\t\t\tthis.c = pc * la + pd * lc;\n\t\t\t\tthis.d = pc * lb + pd * ld;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase Inherit.NoScale:\n\t\t\tcase Inherit.NoScaleOrReflection: {\n\t\t\t\trotation *= MathUtils.degRad;\n\t\t\t\tconst cos = Math.cos(rotation), sin = Math.sin(rotation);\n\t\t\t\tlet za = (pa * cos + pb * sin) / this.skeleton.scaleX;\n\t\t\t\tlet zc = (pc * cos + pd * sin) / this.skeleton.scaleY;\n\t\t\t\tlet s = Math.sqrt(za * za + zc * zc);\n\t\t\t\tif (s > 0.00001) s = 1 / s;\n\t\t\t\tza *= s;\n\t\t\t\tzc *= s;\n\t\t\t\ts = Math.sqrt(za * za + zc * zc);\n\t\t\t\tif (this.inherit == Inherit.NoScale\n\t\t\t\t\t&& (pa * pd - pb * pc < 0) != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) s = -s;\n\t\t\t\trotation = Math.PI / 2 + Math.atan2(zc, za);\n\t\t\t\tconst zb = Math.cos(rotation) * s;\n\t\t\t\tconst zd = Math.sin(rotation) * s;\n\t\t\t\tshearX *= MathUtils.degRad;\n\t\t\t\tshearY = (90 + shearY) * MathUtils.degRad;\n\t\t\t\tconst la = Math.cos(shearX) * scaleX;\n\t\t\t\tconst lb = Math.cos(shearY) * scaleY;\n\t\t\t\tconst lc = Math.sin(shearX) * scaleX;\n\t\t\t\tconst ld = Math.sin(shearY) * scaleY;\n\t\t\t\tthis.a = za * la + zb * lc;\n\t\t\t\tthis.b = za * lb + zb * ld;\n\t\t\t\tthis.c = zc * la + zd * lc;\n\t\t\t\tthis.d = zc * lb + zd * ld;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.a *= this.skeleton.scaleX;\n\t\tthis.b *= this.skeleton.scaleX;\n\t\tthis.c *= this.skeleton.scaleY;\n\t\tthis.d *= this.skeleton.scaleY;\n\t}\n\n\t/** Sets this bone's local transform to the setup pose. */\n\tsetToSetupPose () {\n\t\tlet data = this.data;\n\t\tthis.x = data.x;\n\t\tthis.y = data.y;\n\t\tthis.rotation = data.rotation;\n\t\tthis.scaleX = data.scaleX;\n\t\tthis.scaleY = data.scaleY;\n\t\tthis.shearX = data.shearX;\n\t\tthis.shearY = data.shearY;\n\t\tthis.inherit = data.inherit;\n\t}\n\n\t/** Computes the applied transform values from the world transform.\n\t *\n\t * If the world transform is modified (by a constraint, {@link #rotateWorld(float)}, etc) then this method should be called so\n\t * the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply other\n\t * constraints).\n\t *\n\t * Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after\n\t * calling this method is equivalent to the local transform used to compute the world transform, but may not be identical. */\n\tupdateAppliedTransform () {\n\t\tlet parent = this.parent;\n\t\tif (!parent) {\n\t\t\tthis.ax = this.worldX - this.skeleton.x;\n\t\t\tthis.ay = this.worldY - this.skeleton.y;\n\t\t\tthis.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg;\n\t\t\tthis.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c);\n\t\t\tthis.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d);\n\t\t\tthis.ashearX = 0;\n\t\t\tthis.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg;\n\t\t\treturn;\n\t\t}\n\t\tlet pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;\n\t\tlet pid = 1 / (pa * pd - pb * pc);\n\t\tlet ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;\n\t\tlet dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY;\n\t\tthis.ax = (dx * ia - dy * ib);\n\t\tthis.ay = (dy * id - dx * ic);\n\n\t\tlet ra, rb, rc, rd;\n\t\tif (this.inherit == Inherit.OnlyTranslation) {\n\t\t\tra = this.a;\n\t\t\trb = this.b;\n\t\t\trc = this.c;\n\t\t\trd = this.d;\n\t\t} else {\n\t\t\tswitch (this.inherit) {\n\t\t\t\tcase Inherit.NoRotationOrReflection: {\n\t\t\t\t\tlet s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);\n\t\t\t\t\tpb = -pc * this.skeleton.scaleX * s / this.skeleton.scaleY;\n\t\t\t\t\tpd = pa * this.skeleton.scaleY * s / this.skeleton.scaleX;\n\t\t\t\t\tpid = 1 / (pa * pd - pb * pc);\n\t\t\t\t\tia = pd * pid;\n\t\t\t\t\tib = pb * pid;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase Inherit.NoScale:\n\t\t\t\tcase Inherit.NoScaleOrReflection:\n\t\t\t\t\tlet cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation);\n\t\t\t\t\tpa = (pa * cos + pb * sin) / this.skeleton.scaleX;\n\t\t\t\t\tpc = (pc * cos + pd * sin) / this.skeleton.scaleY;\n\t\t\t\t\tlet s = Math.sqrt(pa * pa + pc * pc);\n\t\t\t\t\tif (s > 0.00001) s = 1 / s;\n\t\t\t\t\tpa *= s;\n\t\t\t\t\tpc *= s;\n\t\t\t\t\ts = Math.sqrt(pa * pa + pc * pc);\n\t\t\t\t\tif (this.inherit == Inherit.NoScale && pid < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0)) s = -s;\n\t\t\t\t\tlet r = MathUtils.PI / 2 + Math.atan2(pc, pa);\n\t\t\t\t\tpb = Math.cos(r) * s;\n\t\t\t\t\tpd = Math.sin(r) * s;\n\t\t\t\t\tpid = 1 / (pa * pd - pb * pc);\n\t\t\t\t\tia = pd * pid;\n\t\t\t\t\tib = pb * pid;\n\t\t\t\t\tic = pc * pid;\n\t\t\t\t\tid = pa * pid;\n\t\t\t}\n\t\t\tra = ia * this.a - ib * this.c;\n\t\t\trb = ia * this.b - ib * this.d;\n\t\t\trc = id * this.c - ic * this.a;\n\t\t\trd = id * this.d - ic * this.b;\n\t\t}\n\n\t\tthis.ashearX = 0;\n\t\tthis.ascaleX = Math.sqrt(ra * ra + rc * rc);\n\t\tif (this.ascaleX > 0.0001) {\n\t\t\tlet det = ra * rd - rb * rc;\n\t\t\tthis.ascaleY = det / this.ascaleX;\n\t\t\tthis.ashearY = -Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;\n\t\t\tthis.arotation = Math.atan2(rc, ra) * MathUtils.radDeg;\n\t\t} else {\n\t\t\tthis.ascaleX = 0;\n\t\t\tthis.ascaleY = Math.sqrt(rb * rb + rd * rd);\n\t\t\tthis.ashearY = 0;\n\t\t\tthis.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;\n\t\t}\n\t}\n\n\n\t/** The world rotation for the X axis, calculated using {@link #a} and {@link #c}. */\n\tgetWorldRotationX () {\n\t\treturn Math.atan2(this.c, this.a) * MathUtils.radDeg;\n\t}\n\n\t/** The world rotation for the Y axis, calculated using {@link #b} and {@link #d}. */\n\tgetWorldRotationY () {\n\t\treturn Math.atan2(this.d, this.b) * MathUtils.radDeg;\n\t}\n\n\t/** The magnitude (always positive) of the world scale X, calculated using {@link #a} and {@link #c}. */\n\tgetWorldScaleX () {\n\t\treturn Math.sqrt(this.a * this.a + this.c * this.c);\n\t}\n\n\t/** The magnitude (always positive) of the world scale Y, calculated using {@link #b} and {@link #d}. */\n\tgetWorldScaleY () {\n\t\treturn Math.sqrt(this.b * this.b + this.d * this.d);\n\t}\n\n\t/** Transforms a point from world coordinates to the bone's local coordinates. */\n\tworldToLocal (world: Vector2) {\n\t\tlet invDet = 1 / (this.a * this.d - this.b * this.c);\n\t\tlet x = world.x - this.worldX, y = world.y - this.worldY;\n\t\tworld.x = x * this.d * invDet - y * this.b * invDet;\n\t\tworld.y = y * this.a * invDet - x * this.c * invDet;\n\t\treturn world;\n\t}\n\n\t/** Transforms a point from the bone's local coordinates to world coordinates. */\n\tlocalToWorld (local: Vector2) {\n\t\tlet x = local.x, y = local.y;\n\t\tlocal.x = x * this.a + y * this.b + this.worldX;\n\t\tlocal.y = x * this.c + y * this.d + this.worldY;\n\t\treturn local;\n\t}\n\n\t/** Transforms a point from world coordinates to the parent bone's local coordinates. */\n\tworldToParent (world: Vector2) {\n\t\tif (world == null) throw new Error(\"world cannot be null.\");\n\t\treturn this.parent == null ? world : this.parent.worldToLocal(world);\n\t}\n\n\t/** Transforms a point from the parent bone's coordinates to world coordinates. */\n\tparentToWorld (world: Vector2) {\n\t\tif (world == null) throw new Error(\"world cannot be null.\");\n\t\treturn this.parent == null ? world : this.parent.localToWorld(world);\n\t}\n\n\t/** Transforms a world rotation to a local rotation. */\n\tworldToLocalRotation (worldRotation: number) {\n\t\tlet sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation);\n\t\treturn Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX;\n\t}\n\n\t/** Transforms a local rotation to a world rotation. */\n\tlocalToWorldRotation (localRotation: number) {\n\t\tlocalRotation -= this.rotation - this.shearX;\n\t\tlet sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation);\n\t\treturn Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg;\n\t}\n\n\t/** Rotates the world transform the specified amount.\n\t *

    \n\t * After changes are made to the world transform, {@link #updateAppliedTransform()} should be called and\n\t * {@link #update(Physics)} will need to be called on any child bones, recursively. */\n\trotateWorld (degrees: number) {\n\t\tdegrees *= MathUtils.degRad;\n\t\tconst sin = Math.sin(degrees), cos = Math.cos(degrees);\n\t\tconst ra = this.a, rb = this.b;\n\t\tthis.a = cos * ra - sin * this.c;\n\t\tthis.b = cos * rb - sin * this.d;\n\t\tthis.c = sin * ra + cos * this.c;\n\t\tthis.d = sin * rb + cos * this.d;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\n/** The base class for all constraint datas. */\nexport abstract class ConstraintData {\n\tconstructor (public name: string, public order: number, public skinRequired: boolean) { }\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture } from \"./Texture.js\";\nimport { TextureAtlas } from \"./TextureAtlas.js\";\nimport { Disposable, StringMap } from \"./Utils.js\";\n\nexport class AssetManagerBase implements Disposable {\n\tprivate pathPrefix: string = \"\";\n\tprivate textureLoader: (image: HTMLImageElement | ImageBitmap) => Texture;\n\tprivate downloader: Downloader;\n\tprivate assets: StringMap = {};\n\tprivate errors: StringMap = {};\n\tprivate toLoad = 0;\n\tprivate loaded = 0;\n\n\tconstructor (textureLoader: (image: HTMLImageElement | ImageBitmap) => Texture, pathPrefix: string = \"\", downloader: Downloader = new Downloader()) {\n\t\tthis.textureLoader = textureLoader;\n\t\tthis.pathPrefix = pathPrefix;\n\t\tthis.downloader = downloader;\n\t}\n\n\tprivate start (path: string): string {\n\t\tthis.toLoad++;\n\t\treturn this.pathPrefix + path;\n\t}\n\n\tprivate success (callback: (path: string, data: any) => void, path: string, asset: any) {\n\t\tthis.toLoad--;\n\t\tthis.loaded++;\n\t\tthis.assets[path] = asset;\n\t\tif (callback) callback(path, asset);\n\t}\n\n\tprivate error (callback: (path: string, message: string) => void, path: string, message: string) {\n\t\tthis.toLoad--;\n\t\tthis.loaded++;\n\t\tthis.errors[path] = message;\n\t\tif (callback) callback(path, message);\n\t}\n\n\tloadAll () {\n\t\tlet promise = new Promise((resolve: (assetManager: AssetManagerBase) => void, reject: (errors: StringMap) => void) => {\n\t\t\tlet check = () => {\n\t\t\t\tif (this.isLoadingComplete()) {\n\t\t\t\t\tif (this.hasErrors()) reject(this.errors);\n\t\t\t\t\telse resolve(this);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\trequestAnimationFrame(check);\n\t\t\t}\n\t\t\trequestAnimationFrame(check);\n\t\t});\n\t\treturn promise;\n\t}\n\n\tsetRawDataURI (path: string, data: string) {\n\t\tthis.downloader.rawDataUris[this.pathPrefix + path] = data;\n\t}\n\n\tloadBinary (path: string,\n\t\tsuccess: (path: string, binary: Uint8Array) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadBinary(path, (data: Uint8Array): void => {\n\t\t\tthis.success(success, path, data);\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tloadText (path: string,\n\t\tsuccess: (path: string, text: string) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadText(path, (data: string): void => {\n\t\t\tthis.success(success, path, data);\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tloadJson (path: string,\n\t\tsuccess: (path: string, object: object) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadJson(path, (data: object): void => {\n\t\t\tthis.success(success, path, data);\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tloadTexture (path: string,\n\t\tsuccess: (path: string, texture: Texture) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { }) {\n\t\tpath = this.start(path);\n\n\t\tlet isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document);\n\t\tlet isWebWorker = !isBrowser; // && typeof importScripts !== 'undefined';\n\t\tif (isWebWorker) {\n\t\t\tfetch(path, { mode: \"cors\" }).then((response) => {\n\t\t\t\tif (response.ok) return response.blob();\n\t\t\t\tthis.error(error, path, `Couldn't load image: ${path}`);\n\t\t\t\treturn null;\n\t\t\t}).then((blob) => {\n\t\t\t\treturn blob ? createImageBitmap(blob, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" }) : null;\n\t\t\t}).then((bitmap) => {\n\t\t\t\tif (bitmap) this.success(success, path, this.textureLoader(bitmap));\n\t\t\t});\n\t\t} else {\n\t\t\tlet image = new Image();\n\t\t\timage.crossOrigin = \"anonymous\";\n\t\t\timage.onload = () => {\n\t\t\t\tthis.success(success, path, this.textureLoader(image));\n\t\t\t};\n\t\t\timage.onerror = () => {\n\t\t\t\tthis.error(error, path, `Couldn't load image: ${path}`);\n\t\t\t};\n\t\t\tif (this.downloader.rawDataUris[path]) path = this.downloader.rawDataUris[path];\n\t\t\timage.src = path;\n\t\t}\n\t}\n\n\tloadTextureAtlas (path: string,\n\t\tsuccess: (path: string, atlas: TextureAtlas) => void = () => { },\n\t\terror: (path: string, message: string) => void = () => { },\n\t\tfileAlias?: { [keyword: string]: string }\n\t) {\n\t\tlet index = path.lastIndexOf(\"/\");\n\t\tlet parent = index >= 0 ? path.substring(0, index + 1) : \"\";\n\t\tpath = this.start(path);\n\n\t\tthis.downloader.downloadText(path, (atlasText: string): void => {\n\t\t\ttry {\n\t\t\t\tlet atlas = new TextureAtlas(atlasText);\n\t\t\t\tlet toLoad = atlas.pages.length, abort = false;\n\t\t\t\tfor (let page of atlas.pages) {\n\t\t\t\t\tthis.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name!],\n\t\t\t\t\t\t(imagePath: string, texture: Texture) => {\n\t\t\t\t\t\t\tif (!abort) {\n\t\t\t\t\t\t\t\tpage.setTexture(texture);\n\t\t\t\t\t\t\t\tif (--toLoad == 0) this.success(success, path, atlas);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(imagePath: string, message: string) => {\n\t\t\t\t\t\t\tif (!abort) this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`);\n\t\t\t\t\t\t\tabort = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tthis.error(error, path, `Couldn't parse texture atlas ${path}: ${(e as any).message}`);\n\t\t\t}\n\t\t}, (status: number, responseText: string): void => {\n\t\t\tthis.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`);\n\t\t});\n\t}\n\n\tget (path: string) {\n\t\treturn this.assets[this.pathPrefix + path];\n\t}\n\n\trequire (path: string) {\n\t\tpath = this.pathPrefix + path;\n\t\tlet asset = this.assets[path];\n\t\tif (asset) return asset;\n\t\tlet error = this.errors[path];\n\t\tthrow Error(\"Asset not found: \" + path + (error ? \"\\n\" + error : \"\"));\n\t}\n\n\tremove (path: string) {\n\t\tpath = this.pathPrefix + path;\n\t\tlet asset = this.assets[path];\n\t\tif ((asset).dispose) (asset).dispose();\n\t\tdelete this.assets[path];\n\t\treturn asset;\n\t}\n\n\tremoveAll () {\n\t\tfor (let key in this.assets) {\n\t\t\tlet asset = this.assets[key];\n\t\t\tif ((asset).dispose) (asset).dispose();\n\t\t}\n\t\tthis.assets = {};\n\t}\n\n\tisLoadingComplete (): boolean {\n\t\treturn this.toLoad == 0;\n\t}\n\n\tgetToLoad (): number {\n\t\treturn this.toLoad;\n\t}\n\n\tgetLoaded (): number {\n\t\treturn this.loaded;\n\t}\n\n\tdispose () {\n\t\tthis.removeAll();\n\t}\n\n\thasErrors () {\n\t\treturn Object.keys(this.errors).length > 0;\n\t}\n\n\tgetErrors () {\n\t\treturn this.errors;\n\t}\n}\n\nexport class Downloader {\n\tprivate callbacks: StringMap> = {};\n\trawDataUris: StringMap = {};\n\n\tdataUriToString (dataUri: string) {\n\t\tif (!dataUri.startsWith(\"data:\")) {\n\t\t\tthrow new Error(\"Not a data URI.\");\n\t\t}\n\n\t\tlet base64Idx = dataUri.indexOf(\"base64,\");\n\t\tif (base64Idx != -1) {\n\t\t\tbase64Idx += \"base64,\".length;\n\t\t\treturn atob(dataUri.substr(base64Idx));\n\t\t} else {\n\t\t\treturn dataUri.substr(dataUri.indexOf(\",\") + 1);\n\t\t}\n\t}\n\n\tbase64ToUint8Array (base64: string) {\n\t\tvar binary_string = window.atob(base64);\n\t\tvar len = binary_string.length;\n\t\tvar bytes = new Uint8Array(len);\n\t\tfor (var i = 0; i < len; i++) {\n\t\t\tbytes[i] = binary_string.charCodeAt(i);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tdataUriToUint8Array (dataUri: string) {\n\t\tif (!dataUri.startsWith(\"data:\")) {\n\t\t\tthrow new Error(\"Not a data URI.\");\n\t\t}\n\n\t\tlet base64Idx = dataUri.indexOf(\"base64,\");\n\t\tif (base64Idx == -1) throw new Error(\"Not a binary data URI.\");\n\t\tbase64Idx += \"base64,\".length;\n\t\treturn this.base64ToUint8Array(dataUri.substr(base64Idx));\n\t}\n\n\tdownloadText (url: string, success: (data: string) => void, error: (status: number, responseText: string) => void) {\n\t\tif (this.start(url, success, error)) return;\n\t\tif (this.rawDataUris[url]) {\n\t\t\ttry {\n\t\t\t\tlet dataUri = this.rawDataUris[url];\n\t\t\t\tthis.finish(url, 200, this.dataUriToString(dataUri));\n\t\t\t} catch (e) {\n\t\t\t\tthis.finish(url, 400, JSON.stringify(e));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet request = new XMLHttpRequest();\n\t\trequest.overrideMimeType(\"text/html\");\n\t\trequest.open(\"GET\", url, true);\n\t\tlet done = () => {\n\t\t\tthis.finish(url, request.status, request.responseText);\n\t\t};\n\t\trequest.onload = done;\n\t\trequest.onerror = done;\n\t\trequest.send();\n\t}\n\n\tdownloadJson (url: string, success: (data: object) => void, error: (status: number, responseText: string) => void) {\n\t\tthis.downloadText(url, (data: string): void => {\n\t\t\tsuccess(JSON.parse(data));\n\t\t}, error);\n\t}\n\n\tdownloadBinary (url: string, success: (data: Uint8Array) => void, error: (status: number, responseText: string) => void) {\n\t\tif (this.start(url, success, error)) return;\n\t\tif (this.rawDataUris[url]) {\n\t\t\ttry {\n\t\t\t\tlet dataUri = this.rawDataUris[url];\n\t\t\t\tthis.finish(url, 200, this.dataUriToUint8Array(dataUri));\n\t\t\t} catch (e) {\n\t\t\t\tthis.finish(url, 400, JSON.stringify(e));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet request = new XMLHttpRequest();\n\t\trequest.open(\"GET\", url, true);\n\t\trequest.responseType = \"arraybuffer\";\n\t\tlet onerror = () => {\n\t\t\tthis.finish(url, request.status, request.response);\n\t\t};\n\t\trequest.onload = () => {\n\t\t\tif (request.status == 200 || request.status == 0)\n\t\t\t\tthis.finish(url, 200, new Uint8Array(request.response as ArrayBuffer));\n\t\t\telse\n\t\t\t\tonerror();\n\t\t};\n\t\trequest.onerror = onerror;\n\t\trequest.send();\n\t}\n\n\tprivate start (url: string, success: any, error: any) {\n\t\tlet callbacks = this.callbacks[url];\n\t\ttry {\n\t\t\tif (callbacks) return true;\n\t\t\tthis.callbacks[url] = callbacks = [];\n\t\t} finally {\n\t\t\tcallbacks.push(success, error);\n\t\t}\n\t}\n\n\tprivate finish (url: string, status: number, data: any) {\n\t\tlet callbacks = this.callbacks[url];\n\t\tdelete this.callbacks[url];\n\t\tlet args = status == 200 || status == 0 ? [data] : [status, data];\n\t\tfor (let i = args.length - 1, n = callbacks.length; i < n; i += 2)\n\t\t\tcallbacks[i].apply(null, args);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { EventData } from \"./EventData.js\";\n\n/** Stores the current pose values for an {@link Event}.\n *\n * See Timeline {@link Timeline#apply()},\n * AnimationStateListener {@link AnimationStateListener#event()}, and\n * [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */\nexport class Event {\n\tdata: EventData;\n\tintValue: number = 0;\n\tfloatValue: number = 0;\n\tstringValue: string | null = null;\n\ttime: number = 0;\n\tvolume: number = 0;\n\tbalance: number = 0;\n\n\tconstructor (time: number, data: EventData) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tthis.time = time;\n\t\tthis.data = data;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\n/** Stores the setup pose values for an {@link Event}.\n *\n * See [Events](http://esotericsoftware.com/spine-events) in the Spine User Guide. */\nexport class EventData {\n\tname: string;\n\tintValue: number = 0;\n\tfloatValue: number = 0;\n\tstringValue: string | null = null;\n\taudioPath: string | null = null;\n\tvolume: number = 0;\n\tbalance: number = 0;\n\n\tconstructor (name: string) {\n\t\tthis.name = name;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"./Bone.js\";\nimport { Inherit } from \"./BoneData.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { MathUtils } from \"./Utils.js\";\n\n/** Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of\n * the last bone is as close to the target bone as possible.\n *\n * See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */\nexport class IkConstraint implements Updatable {\n\t/** The IK constraint's setup pose data. */\n\tdata: IkConstraintData;\n\n\t/** The bones that will be modified by this IK constraint. */\n\tbones: Array;\n\n\t/** The bone that is the IK target. */\n\ttarget: Bone;\n\n\t/** Controls the bend direction of the IK bones, either 1 or -1. */\n\tbendDirection = 0;\n\n\t/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */\n\tcompress = false;\n\n\t/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained\n\t * and the parent bone has local nonuniform scale, stretch is not applied. */\n\tstretch = false;\n\n\t/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */\n\tmix = 1;\n\n\t/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */\n\tsoftness = 0;\n\tactive = false;\n\n\tconstructor (data: IkConstraintData, skeleton: Skeleton) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0; i < data.bones.length; i++) {\n\t\t\tlet bone = skeleton.findBone(data.bones[i].name);\n\t\t\tif (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}`);\n\t\t\tthis.bones.push(bone);\n\t\t}\n\t\tlet target = skeleton.findBone(data.target.name);\n\t\tif (!target) throw new Error(`Couldn't find bone ${data.target.name}`);\n\n\t\tthis.target = target;\n\t\tthis.mix = data.mix;\n\t\tthis.softness = data.softness;\n\t\tthis.bendDirection = data.bendDirection;\n\t\tthis.compress = data.compress;\n\t\tthis.stretch = data.stretch;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.mix = data.mix;\n\t\tthis.softness = data.softness;\n\t\tthis.bendDirection = data.bendDirection;\n\t\tthis.compress = data.compress;\n\t\tthis.stretch = data.stretch;\n\t}\n\n\tupdate (physics: Physics) {\n\t\tif (this.mix == 0) return;\n\t\tlet target = this.target;\n\t\tlet bones = this.bones;\n\t\tswitch (bones.length) {\n\t\t\tcase 1:\n\t\t\t\tthis.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tthis.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/** Applies 1 bone IK. The target is specified in the world coordinate system. */\n\tapply1 (bone: Bone, targetX: number, targetY: number, compress: boolean, stretch: boolean, uniform: boolean, alpha: number) {\n\t\tlet p = bone.parent;\n\t\tif (!p) throw new Error(\"IK bone must have parent.\");\n\t\tlet pa = p.a, pb = p.b, pc = p.c, pd = p.d;\n\t\tlet rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;\n\n\t\tswitch (bone.inherit) {\n\t\t\tcase Inherit.OnlyTranslation:\n\t\t\t\ttx = (targetX - bone.worldX) * MathUtils.signum(bone.skeleton.scaleX);\n\t\t\t\tty = (targetY - bone.worldY) * MathUtils.signum(bone.skeleton.scaleY);\n\t\t\t\tbreak;\n\t\t\tcase Inherit.NoRotationOrReflection:\n\t\t\t\tlet s = Math.abs(pa * pd - pb * pc) / Math.max(0.0001, pa * pa + pc * pc);\n\t\t\t\tlet sa = pa / bone.skeleton.scaleX;\n\t\t\t\tlet sc = pc / bone.skeleton.scaleY;\n\t\t\t\tpb = -sc * s * bone.skeleton.scaleX;\n\t\t\t\tpd = sa * s * bone.skeleton.scaleY;\n\t\t\t\trotationIK += Math.atan2(sc, sa) * MathUtils.radDeg;\n\t\t\t// Fall through\n\t\t\tdefault:\n\t\t\t\tlet x = targetX - p.worldX, y = targetY - p.worldY;\n\t\t\t\tlet d = pa * pd - pb * pc;\n\t\t\t\tif (Math.abs(d) <= 0.0001) {\n\t\t\t\t\ttx = 0;\n\t\t\t\t\tty = 0;\n\t\t\t\t} else {\n\t\t\t\t\ttx = (x * pd - y * pb) / d - bone.ax;\n\t\t\t\t\tty = (y * pa - x * pc) / d - bone.ay;\n\t\t\t\t}\n\t\t}\n\t\trotationIK += Math.atan2(ty, tx) * MathUtils.radDeg;\n\t\tif (bone.ascaleX < 0) rotationIK += 180;\n\t\tif (rotationIK > 180)\n\t\t\trotationIK -= 360;\n\t\telse if (rotationIK < -180)\n\t\t\trotationIK += 360;\n\t\tlet sx = bone.ascaleX, sy = bone.ascaleY;\n\t\tif (compress || stretch) {\n\t\t\tswitch (bone.inherit) {\n\t\t\t\tcase Inherit.NoScale:\n\t\t\t\tcase Inherit.NoScaleOrReflection:\n\t\t\t\t\ttx = targetX - bone.worldX;\n\t\t\t\t\tty = targetY - bone.worldY;\n\t\t\t}\n\t\t\tconst b = bone.data.length * sx;\n\t\t\tif (b > 0.0001) {\n\t\t\t\tconst dd = tx * tx + ty * ty;\n\t\t\t\tif ((compress && dd < b * b) || (stretch && dd > b * b)) {\n\t\t\t\t\tconst s = (Math.sqrt(dd) / b - 1) * alpha + 1;\n\t\t\t\t\tsx *= s;\n\t\t\t\t\tif (uniform) sy *= s;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbone.updateWorldTransformWith(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX,\n\t\t\tbone.ashearY);\n\t}\n\n\t/** Applies 2 bone IK. The target is specified in the world coordinate system.\n\t * @param child A direct descendant of the parent bone. */\n\tapply2 (parent: Bone, child: Bone, targetX: number, targetY: number, bendDir: number, stretch: boolean, uniform: boolean, softness: number, alpha: number) {\n\t\tif (parent.inherit != Inherit.Normal || child.inherit != Inherit.Normal) return;\n\t\tlet px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX;\n\t\tlet os1 = 0, os2 = 0, s2 = 0;\n\t\tif (psx < 0) {\n\t\t\tpsx = -psx;\n\t\t\tos1 = 180;\n\t\t\ts2 = -1;\n\t\t} else {\n\t\t\tos1 = 0;\n\t\t\ts2 = 1;\n\t\t}\n\t\tif (psy < 0) {\n\t\t\tpsy = -psy;\n\t\t\ts2 = -s2;\n\t\t}\n\t\tif (csx < 0) {\n\t\t\tcsx = -csx;\n\t\t\tos2 = 180;\n\t\t} else\n\t\t\tos2 = 0;\n\t\tlet cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d;\n\t\tlet u = Math.abs(psx - psy) <= 0.0001;\n\t\tif (!u || stretch) {\n\t\t\tcy = 0;\n\t\t\tcwx = a * cx + parent.worldX;\n\t\t\tcwy = c * cx + parent.worldY;\n\t\t} else {\n\t\t\tcy = child.ay;\n\t\t\tcwx = a * cx + b * cy + parent.worldX;\n\t\t\tcwy = c * cx + d * cy + parent.worldY;\n\t\t}\n\t\tlet pp = parent.parent;\n\t\tif (!pp) throw new Error(\"IK parent must itself have a parent.\");\n\t\ta = pp.a;\n\t\tb = pp.b;\n\t\tc = pp.c;\n\t\td = pp.d;\n\t\tlet id = a * d - b * c, x = cwx - pp.worldX, y = cwy - pp.worldY;\n\t\tid = Math.abs(id) <= 0.0001 ? 0 : 1 / id;\n\t\tlet dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;\n\t\tlet l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;\n\t\tif (l1 < 0.0001) {\n\t\t\tthis.apply1(parent, targetX, targetY, false, stretch, false, alpha);\n\t\t\tchild.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);\n\t\t\treturn;\n\t\t}\n\t\tx = targetX - pp.worldX;\n\t\ty = targetY - pp.worldY;\n\t\tlet tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;\n\t\tlet dd = tx * tx + ty * ty;\n\t\tif (softness != 0) {\n\t\t\tsoftness *= psx * (csx + 1) * 0.5;\n\t\t\tlet td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness;\n\t\t\tif (sd > 0) {\n\t\t\t\tlet p = Math.min(1, sd / (softness * 2)) - 1;\n\t\t\t\tp = (sd - softness * (1 - p * p)) / td;\n\t\t\t\ttx -= p * tx;\n\t\t\t\tty -= p * ty;\n\t\t\t\tdd = tx * tx + ty * ty;\n\t\t\t}\n\t\t}\n\t\touter:\n\t\tif (u) {\n\t\t\tl2 *= psx;\n\t\t\tlet cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);\n\t\t\tif (cos < -1) {\n\t\t\t\tcos = -1;\n\t\t\t\ta2 = Math.PI * bendDir;\n\t\t\t} else if (cos > 1) {\n\t\t\t\tcos = 1;\n\t\t\t\ta2 = 0;\n\t\t\t\tif (stretch) {\n\t\t\t\t\ta = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;\n\t\t\t\t\tsx *= a;\n\t\t\t\t\tif (uniform) sy *= a;\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\ta2 = Math.acos(cos) * bendDir;\n\t\t\ta = l1 + l2 * cos;\n\t\t\tb = l2 * Math.sin(a2);\n\t\t\ta1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);\n\t\t} else {\n\t\t\ta = psx * l2;\n\t\t\tb = psy * l2;\n\t\t\tlet aa = a * a, bb = b * b, ta = Math.atan2(ty, tx);\n\t\t\tc = bb * l1 * l1 + aa * dd - aa * bb;\n\t\t\tlet c1 = -2 * bb * l1, c2 = bb - aa;\n\t\t\td = c1 * c1 - 4 * c2 * c;\n\t\t\tif (d >= 0) {\n\t\t\t\tlet q = Math.sqrt(d);\n\t\t\t\tif (c1 < 0) q = -q;\n\t\t\t\tq = -(c1 + q) * 0.5;\n\t\t\t\tlet r0 = q / c2, r1 = c / q;\n\t\t\t\tlet r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;\n\t\t\t\tr0 = dd - r * r;\n\t\t\t\tif (r0 >= 0) {\n\t\t\t\t\ty = Math.sqrt(r0) * bendDir;\n\t\t\t\t\ta1 = ta - Math.atan2(y, r);\n\t\t\t\t\ta2 = Math.atan2(y / psy, (r - l1) / psx);\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0;\n\t\t\tlet maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;\n\t\t\tc = -a * l1 / (aa - bb);\n\t\t\tif (c >= -1 && c <= 1) {\n\t\t\t\tc = Math.acos(c);\n\t\t\t\tx = a * Math.cos(c) + l1;\n\t\t\t\ty = b * Math.sin(c);\n\t\t\t\td = x * x + y * y;\n\t\t\t\tif (d < minDist) {\n\t\t\t\t\tminAngle = c;\n\t\t\t\t\tminDist = d;\n\t\t\t\t\tminX = x;\n\t\t\t\t\tminY = y;\n\t\t\t\t}\n\t\t\t\tif (d > maxDist) {\n\t\t\t\t\tmaxAngle = c;\n\t\t\t\t\tmaxDist = d;\n\t\t\t\t\tmaxX = x;\n\t\t\t\t\tmaxY = y;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (dd <= (minDist + maxDist) * 0.5) {\n\t\t\t\ta1 = ta - Math.atan2(minY * bendDir, minX);\n\t\t\t\ta2 = minAngle * bendDir;\n\t\t\t} else {\n\t\t\t\ta1 = ta - Math.atan2(maxY * bendDir, maxX);\n\t\t\t\ta2 = maxAngle * bendDir;\n\t\t\t}\n\t\t}\n\t\tlet os = Math.atan2(cy, cx) * s2;\n\t\tlet rotation = parent.arotation;\n\t\ta1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;\n\t\tif (a1 > 180)\n\t\t\ta1 -= 360;\n\t\telse if (a1 < -180) //\n\t\t\ta1 += 360;\n\t\tparent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0);\n\t\trotation = child.arotation;\n\t\ta2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation;\n\t\tif (a2 > 180)\n\t\t\ta2 -= 360;\n\t\telse if (a2 < -180) //\n\t\t\ta2 += 360;\n\t\tchild.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\n\n\n/** Stores the setup pose for an {@link IkConstraint}.\n *

    \n * See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide. */\nexport class IkConstraintData extends ConstraintData {\n\t/** The bones that are constrained by this IK constraint. */\n\tbones = new Array();\n\n\t/** The bone that is the IK target. */\n\tprivate _target: BoneData | null = null;\n\tpublic set target (boneData: BoneData) { this._target = boneData; }\n\tpublic get target () {\n\t\tif (!this._target) throw new Error(\"BoneData not set.\")\n\t\telse return this._target;\n\t}\n\n\t/** Controls the bend direction of the IK bones, either 1 or -1. */\n\tbendDirection = 0;\n\n\t/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */\n\tcompress = false;\n\n\t/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained\n\t * and the parent bone has local nonuniform scale, stretch is not applied. */\n\tstretch = false;\n\n\t/** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone\n\t * is scaled on both the X and Y axes. */\n\tuniform = false;\n\n\t/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotations. */\n\tmix = 0;\n\n\t/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */\n\tsoftness = 0;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\nimport { SlotData } from \"./SlotData.js\";\n\n\n/** Stores the setup pose for a {@link PathConstraint}.\n *\n * See [path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide. */\nexport class PathConstraintData extends ConstraintData {\n\n\t/** The bones that will be modified by this path constraint. */\n\tbones = new Array();\n\n\t/** The slot whose path attachment will be used to constrained the bones. */\n\tprivate _target: SlotData | null = null;\n\tpublic set target (slotData: SlotData) { this._target = slotData; }\n\tpublic get target () {\n\t\tif (!this._target) throw new Error(\"SlotData not set.\")\n\t\telse return this._target;\n\t}\n\n\t/** The mode for positioning the first bone on the path. */\n\tpositionMode: PositionMode = PositionMode.Fixed;\n\n\t/** The mode for positioning the bones after the first bone on the path. */\n\tspacingMode: SpacingMode = SpacingMode.Fixed;\n\n\t/** The mode for adjusting the rotation of the bones. */\n\trotateMode: RotateMode = RotateMode.Chain;\n\n\t/** An offset added to the constrained bone rotation. */\n\toffsetRotation: number = 0;\n\n\t/** The position along the path. */\n\tposition: number = 0;\n\n\t/** The spacing between bones. */\n\tspacing: number = 0;\n\n\tmixRotate = 0;\n\tmixX = 0;\n\tmixY = 0;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n\n/** Controls how the first bone is positioned along the path.\n *\n * See [position](http://esotericsoftware.com/spine-path-constraints#Position) in the Spine User Guide. */\nexport enum PositionMode { Fixed, Percent }\n\n/** Controls how bones after the first bone are positioned along the path.\n *\n * See [spacing](http://esotericsoftware.com/spine-path-constraints#Spacing) in the Spine User Guide. */\nexport enum SpacingMode { Length, Fixed, Percent, Proportional }\n\n/** Controls how bones are rotated, translated, and scaled to match the path.\n *\n * See [rotate mix](http://esotericsoftware.com/spine-path-constraints#Rotate-mix) in the Spine User Guide. */\nexport enum RotateMode { Tangent, Chain, ChainScale }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { PathAttachment } from \"./attachments/PathAttachment.js\";\nimport { Bone } from \"./Bone.js\";\nimport { PathConstraintData, RotateMode, SpacingMode, PositionMode } from \"./PathConstraintData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Slot } from \"./Slot.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { Utils, MathUtils } from \"./Utils.js\";\n\n\n/** Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the\n * constrained bones so they follow a {@link PathAttachment}.\n *\n * See [Path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide. */\nexport class PathConstraint implements Updatable {\n\tstatic NONE = -1; static BEFORE = -2; static AFTER = -3;\n\tstatic epsilon = 0.00001;\n\n\t/** The path constraint's setup pose data. */\n\tdata: PathConstraintData;\n\n\t/** The bones that will be modified by this path constraint. */\n\tbones: Array;\n\n\t/** The slot whose path attachment will be used to constrained the bones. */\n\ttarget: Slot;\n\n\t/** The position along the path. */\n\tposition = 0;\n\n\t/** The spacing between bones. */\n\tspacing = 0;\n\n\tmixRotate = 0;\n\n\tmixX = 0;\n\n\tmixY = 0;\n\n\tspaces = new Array(); positions = new Array();\n\tworld = new Array(); curves = new Array(); lengths = new Array();\n\tsegments = new Array();\n\n\tactive = false;\n\n\tconstructor (data: PathConstraintData, skeleton: Skeleton) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0, n = data.bones.length; i < n; i++) {\n\t\t\tlet bone = skeleton.findBone(data.bones[i].name);\n\t\t\tif (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`);\n\t\t\tthis.bones.push(bone);\n\t\t}\n\t\tlet target = skeleton.findSlot(data.target.name);\n\t\tif (!target) throw new Error(`Couldn't find target bone ${data.target.name}`);\n\t\tthis.target = target;\n\n\t\tthis.position = data.position;\n\t\tthis.spacing = data.spacing;\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.position = data.position;\n\t\tthis.spacing = data.spacing;\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t}\n\n\tupdate (physics: Physics) {\n\t\tlet attachment = this.target.getAttachment();\n\t\tif (!(attachment instanceof PathAttachment)) return;\n\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;\n\t\tif (mixRotate == 0 && mixX == 0 && mixY == 0) return;\n\n\t\tlet data = this.data;\n\t\tlet tangents = data.rotateMode == RotateMode.Tangent, scale = data.rotateMode == RotateMode.ChainScale;\n\n\t\tlet bones = this.bones;\n\t\tlet boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1;\n\t\tlet spaces = Utils.setArraySize(this.spaces, spacesCount), lengths: Array = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : [];\n\t\tlet spacing = this.spacing;\n\n\t\tswitch (data.spacingMode) {\n\t\t\tcase SpacingMode.Percent:\n\t\t\t\tif (scale) {\n\t\t\t\t\tfor (let i = 0, n = spacesCount - 1; i < n; i++) {\n\t\t\t\t\t\tlet bone = bones[i];\n\t\t\t\t\t\tlet setupLength = bone.data.length;\n\t\t\t\t\t\tlet x = setupLength * bone.a, y = setupLength * bone.c;\n\t\t\t\t\t\tlengths[i] = Math.sqrt(x * x + y * y);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tUtils.arrayFill(spaces, 1, spacesCount, spacing);\n\t\t\t\tbreak;\n\t\t\tcase SpacingMode.Proportional:\n\t\t\t\tlet sum = 0;\n\t\t\t\tfor (let i = 0, n = spacesCount - 1; i < n;) {\n\t\t\t\t\tlet bone = bones[i];\n\t\t\t\t\tlet setupLength = bone.data.length;\n\t\t\t\t\tif (setupLength < PathConstraint.epsilon) {\n\t\t\t\t\t\tif (scale) lengths[i] = 0;\n\t\t\t\t\t\tspaces[++i] = spacing;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet x = setupLength * bone.a, y = setupLength * bone.c;\n\t\t\t\t\t\tlet length = Math.sqrt(x * x + y * y);\n\t\t\t\t\t\tif (scale) lengths[i] = length;\n\t\t\t\t\t\tspaces[++i] = length;\n\t\t\t\t\t\tsum += length;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (sum > 0) {\n\t\t\t\t\tsum = spacesCount / sum * spacing;\n\t\t\t\t\tfor (let i = 1; i < spacesCount; i++)\n\t\t\t\t\t\tspaces[i] *= sum;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tlet lengthSpacing = data.spacingMode == SpacingMode.Length;\n\t\t\t\tfor (let i = 0, n = spacesCount - 1; i < n;) {\n\t\t\t\t\tlet bone = bones[i];\n\t\t\t\t\tlet setupLength = bone.data.length;\n\t\t\t\t\tif (setupLength < PathConstraint.epsilon) {\n\t\t\t\t\t\tif (scale) lengths[i] = 0;\n\t\t\t\t\t\tspaces[++i] = spacing;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet x = setupLength * bone.a, y = setupLength * bone.c;\n\t\t\t\t\t\tlet length = Math.sqrt(x * x + y * y);\n\t\t\t\t\t\tif (scale) lengths[i] = length;\n\t\t\t\t\t\tspaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\n\t\tlet positions = this.computeWorldPositions(attachment, spacesCount, tangents);\n\t\tlet boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;\n\t\tlet tip = false;\n\t\tif (offsetRotation == 0)\n\t\t\ttip = data.rotateMode == RotateMode.Chain;\n\t\telse {\n\t\t\ttip = false;\n\t\t\tlet p = this.target.bone;\n\t\t\toffsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad;\n\t\t}\n\t\tfor (let i = 0, p = 3; i < boneCount; i++, p += 3) {\n\t\t\tlet bone = bones[i];\n\t\t\tbone.worldX += (boneX - bone.worldX) * mixX;\n\t\t\tbone.worldY += (boneY - bone.worldY) * mixY;\n\t\t\tlet x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;\n\t\t\tif (scale) {\n\t\t\t\tlet length = lengths[i];\n\t\t\t\tif (length != 0) {\n\t\t\t\t\tlet s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;\n\t\t\t\t\tbone.a *= s;\n\t\t\t\t\tbone.c *= s;\n\t\t\t\t}\n\t\t\t}\n\t\t\tboneX = x;\n\t\t\tboneY = y;\n\t\t\tif (mixRotate > 0) {\n\t\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0;\n\t\t\t\tif (tangents)\n\t\t\t\t\tr = positions[p - 1];\n\t\t\t\telse if (spaces[i + 1] == 0)\n\t\t\t\t\tr = positions[p + 2];\n\t\t\t\telse\n\t\t\t\t\tr = Math.atan2(dy, dx);\n\t\t\t\tr -= Math.atan2(c, a);\n\t\t\t\tif (tip) {\n\t\t\t\t\tcos = Math.cos(r);\n\t\t\t\t\tsin = Math.sin(r);\n\t\t\t\t\tlet length = bone.data.length;\n\t\t\t\t\tboneX += (length * (cos * a - sin * c) - dx) * mixRotate;\n\t\t\t\t\tboneY += (length * (sin * a + cos * c) - dy) * mixRotate;\n\t\t\t\t} else {\n\t\t\t\t\tr += offsetRotation;\n\t\t\t\t}\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr *= mixRotate;\n\t\t\t\tcos = Math.cos(r);\n\t\t\t\tsin = Math.sin(r);\n\t\t\t\tbone.a = cos * a - sin * c;\n\t\t\t\tbone.b = cos * b - sin * d;\n\t\t\t\tbone.c = sin * a + cos * c;\n\t\t\t\tbone.d = sin * b + cos * d;\n\t\t\t}\n\t\t\tbone.updateAppliedTransform();\n\t\t}\n\t}\n\n\tcomputeWorldPositions (path: PathAttachment, spacesCount: number, tangents: boolean) {\n\t\tlet target = this.target;\n\t\tlet position = this.position;\n\t\tlet spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world: Array = this.world;\n\t\tlet closed = path.closed;\n\t\tlet verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PathConstraint.NONE;\n\n\t\tif (!path.constantSpeed) {\n\t\t\tlet lengths = path.lengths;\n\t\t\tcurveCount -= closed ? 1 : 2;\n\t\t\tlet pathLength = lengths[curveCount];\n\t\t\tif (this.data.positionMode == PositionMode.Percent) position *= pathLength;\n\n\t\t\tlet multiplier;\n\t\t\tswitch (this.data.spacingMode) {\n\t\t\t\tcase SpacingMode.Percent:\n\t\t\t\t\tmultiplier = pathLength;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SpacingMode.Proportional:\n\t\t\t\t\tmultiplier = pathLength / spacesCount;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tmultiplier = 1;\n\t\t\t}\n\t\t\tworld = Utils.setArraySize(this.world, 8);\n\t\t\tfor (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {\n\t\t\t\tlet space = spaces[i] * multiplier;\n\t\t\t\tposition += space;\n\t\t\t\tlet p = position;\n\n\t\t\t\tif (closed) {\n\t\t\t\t\tp %= pathLength;\n\t\t\t\t\tif (p < 0) p += pathLength;\n\t\t\t\t\tcurve = 0;\n\t\t\t\t} else if (p < 0) {\n\t\t\t\t\tif (prevCurve != PathConstraint.BEFORE) {\n\t\t\t\t\t\tprevCurve = PathConstraint.BEFORE;\n\t\t\t\t\t\tpath.computeWorldVertices(target, 2, 4, world, 0, 2);\n\t\t\t\t\t}\n\t\t\t\t\tthis.addBeforePosition(p, world, 0, out, o);\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (p > pathLength) {\n\t\t\t\t\tif (prevCurve != PathConstraint.AFTER) {\n\t\t\t\t\t\tprevCurve = PathConstraint.AFTER;\n\t\t\t\t\t\tpath.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);\n\t\t\t\t\t}\n\t\t\t\t\tthis.addAfterPosition(p - pathLength, world, 0, out, o);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Determine curve containing position.\n\t\t\t\tfor (; ; curve++) {\n\t\t\t\t\tlet length = lengths[curve];\n\t\t\t\t\tif (p > length) continue;\n\t\t\t\t\tif (curve == 0)\n\t\t\t\t\t\tp /= length;\n\t\t\t\t\telse {\n\t\t\t\t\t\tlet prev = lengths[curve - 1];\n\t\t\t\t\t\tp = (p - prev) / (length - prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (curve != prevCurve) {\n\t\t\t\t\tprevCurve = curve;\n\t\t\t\t\tif (closed && curve == curveCount) {\n\t\t\t\t\t\tpath.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);\n\t\t\t\t\t\tpath.computeWorldVertices(target, 0, 4, world, 4, 2);\n\t\t\t\t\t} else\n\t\t\t\t\t\tpath.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);\n\t\t\t\t}\n\t\t\t\tthis.addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,\n\t\t\t\t\ttangents || (i > 0 && space == 0));\n\t\t\t}\n\t\t\treturn out;\n\t\t}\n\n\t\t// World vertices.\n\t\tif (closed) {\n\t\t\tverticesLength += 2;\n\t\t\tworld = Utils.setArraySize(this.world, verticesLength);\n\t\t\tpath.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);\n\t\t\tpath.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);\n\t\t\tworld[verticesLength - 2] = world[0];\n\t\t\tworld[verticesLength - 1] = world[1];\n\t\t} else {\n\t\t\tcurveCount--;\n\t\t\tverticesLength -= 4;\n\t\t\tworld = Utils.setArraySize(this.world, verticesLength);\n\t\t\tpath.computeWorldVertices(target, 2, verticesLength, world, 0, 2);\n\t\t}\n\n\t\t// Curve lengths.\n\t\tlet curves = Utils.setArraySize(this.curves, curveCount);\n\t\tlet pathLength = 0;\n\t\tlet x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;\n\t\tlet tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0;\n\t\tfor (let i = 0, w = 2; i < curveCount; i++, w += 6) {\n\t\t\tcx1 = world[w];\n\t\t\tcy1 = world[w + 1];\n\t\t\tcx2 = world[w + 2];\n\t\t\tcy2 = world[w + 3];\n\t\t\tx2 = world[w + 4];\n\t\t\ty2 = world[w + 5];\n\t\t\ttmpx = (x1 - cx1 * 2 + cx2) * 0.1875;\n\t\t\ttmpy = (y1 - cy1 * 2 + cy2) * 0.1875;\n\t\t\tdddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;\n\t\t\tdddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;\n\t\t\tddfx = tmpx * 2 + dddfx;\n\t\t\tddfy = tmpy * 2 + dddfy;\n\t\t\tdfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;\n\t\t\tdfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tdfx += ddfx;\n\t\t\tdfy += ddfy;\n\t\t\tddfx += dddfx;\n\t\t\tddfy += dddfy;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tdfx += ddfx;\n\t\t\tdfy += ddfy;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tdfx += ddfx + dddfx;\n\t\t\tdfy += ddfy + dddfy;\n\t\t\tpathLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\tcurves[i] = pathLength;\n\t\t\tx1 = x2;\n\t\t\ty1 = y2;\n\t\t}\n\n\t\tif (this.data.positionMode == PositionMode.Percent) position *= pathLength;\n\n\t\tlet multiplier;\n\t\tswitch (this.data.spacingMode) {\n\t\t\tcase SpacingMode.Percent:\n\t\t\t\tmultiplier = pathLength;\n\t\t\t\tbreak;\n\t\t\tcase SpacingMode.Proportional:\n\t\t\t\tmultiplier = pathLength / spacesCount;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tmultiplier = 1;\n\t\t}\n\n\t\tlet segments = this.segments;\n\t\tlet curveLength = 0;\n\t\tfor (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {\n\t\t\tlet space = spaces[i] * multiplier;\n\t\t\tposition += space;\n\t\t\tlet p = position;\n\n\t\t\tif (closed) {\n\t\t\t\tp %= pathLength;\n\t\t\t\tif (p < 0) p += pathLength;\n\t\t\t\tcurve = 0;\n\t\t\t} else if (p < 0) {\n\t\t\t\tthis.addBeforePosition(p, world, 0, out, o);\n\t\t\t\tcontinue;\n\t\t\t} else if (p > pathLength) {\n\t\t\t\tthis.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Determine curve containing position.\n\t\t\tfor (; ; curve++) {\n\t\t\t\tlet length = curves[curve];\n\t\t\t\tif (p > length) continue;\n\t\t\t\tif (curve == 0)\n\t\t\t\t\tp /= length;\n\t\t\t\telse {\n\t\t\t\t\tlet prev = curves[curve - 1];\n\t\t\t\t\tp = (p - prev) / (length - prev);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Curve segment lengths.\n\t\t\tif (curve != prevCurve) {\n\t\t\t\tprevCurve = curve;\n\t\t\t\tlet ii = curve * 6;\n\t\t\t\tx1 = world[ii];\n\t\t\t\ty1 = world[ii + 1];\n\t\t\t\tcx1 = world[ii + 2];\n\t\t\t\tcy1 = world[ii + 3];\n\t\t\t\tcx2 = world[ii + 4];\n\t\t\t\tcy2 = world[ii + 5];\n\t\t\t\tx2 = world[ii + 6];\n\t\t\t\ty2 = world[ii + 7];\n\t\t\t\ttmpx = (x1 - cx1 * 2 + cx2) * 0.03;\n\t\t\t\ttmpy = (y1 - cy1 * 2 + cy2) * 0.03;\n\t\t\t\tdddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006;\n\t\t\t\tdddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006;\n\t\t\t\tddfx = tmpx * 2 + dddfx;\n\t\t\t\tddfy = tmpy * 2 + dddfy;\n\t\t\t\tdfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;\n\t\t\t\tdfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;\n\t\t\t\tcurveLength = Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\tsegments[0] = curveLength;\n\t\t\t\tfor (ii = 1; ii < 8; ii++) {\n\t\t\t\t\tdfx += ddfx;\n\t\t\t\t\tdfy += ddfy;\n\t\t\t\t\tddfx += dddfx;\n\t\t\t\t\tddfy += dddfy;\n\t\t\t\t\tcurveLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\t\tsegments[ii] = curveLength;\n\t\t\t\t}\n\t\t\t\tdfx += ddfx;\n\t\t\t\tdfy += ddfy;\n\t\t\t\tcurveLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\tsegments[8] = curveLength;\n\t\t\t\tdfx += ddfx + dddfx;\n\t\t\t\tdfy += ddfy + dddfy;\n\t\t\t\tcurveLength += Math.sqrt(dfx * dfx + dfy * dfy);\n\t\t\t\tsegments[9] = curveLength;\n\t\t\t\tsegment = 0;\n\t\t\t}\n\n\t\t\t// Weight by segment length.\n\t\t\tp *= curveLength;\n\t\t\tfor (; ; segment++) {\n\t\t\t\tlet length = segments[segment];\n\t\t\t\tif (p > length) continue;\n\t\t\t\tif (segment == 0)\n\t\t\t\t\tp /= length;\n\t\t\t\telse {\n\t\t\t\t\tlet prev = segments[segment - 1];\n\t\t\t\t\tp = segment + (p - prev) / (length - prev);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));\n\t\t}\n\t\treturn out;\n\t}\n\n\taddBeforePosition (p: number, temp: Array, i: number, out: Array, o: number) {\n\t\tlet x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx);\n\t\tout[o] = x1 + p * Math.cos(r);\n\t\tout[o + 1] = y1 + p * Math.sin(r);\n\t\tout[o + 2] = r;\n\t}\n\n\taddAfterPosition (p: number, temp: Array, i: number, out: Array, o: number) {\n\t\tlet x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx);\n\t\tout[o] = x1 + p * Math.cos(r);\n\t\tout[o + 1] = y1 + p * Math.sin(r);\n\t\tout[o + 2] = r;\n\t}\n\n\taddCurvePosition (p: number, x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number,\n\t\tout: Array, o: number, tangents: boolean) {\n\t\tif (p == 0 || isNaN(p)) {\n\t\t\tout[o] = x1;\n\t\t\tout[o + 1] = y1;\n\t\t\tout[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);\n\t\t\treturn;\n\t\t}\n\t\tlet tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;\n\t\tlet ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;\n\t\tlet x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;\n\t\tout[o] = x;\n\t\tout[o + 1] = y;\n\t\tif (tangents) {\n\t\t\tif (p < 0.001)\n\t\t\t\tout[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);\n\t\t\telse\n\t\t\t\tout[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"./Bone.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { MathUtils } from \"./Utils.js\";\n\n\n/** Stores the current pose for a physics constraint. A physics constraint applies physics to bones.\n *

    \n * See Physics constraints in the Spine User Guide. */\nexport class PhysicsConstraint implements Updatable {\n\treadonly data: PhysicsConstraintData;\n\tprivate _bone: Bone | null = null;\n\t/** The bone constrained by this physics constraint. */\n\tpublic set bone (bone: Bone) { this._bone = bone; }\n\tpublic get bone () {\n\t\tif (!this._bone) throw new Error(\"Bone not set.\")\n\t\telse return this._bone;\n\t}\n\tinertia = 0;\n\tstrength = 0;\n\tdamping = 0;\n\tmassInverse = 0;\n\twind = 0;\n\tgravity = 0;\n\tmix = 0;\n\n\t_reset = true;\n\tux = 0;\n\tuy = 0;\n\tcx = 0;\n\tcy = 0;\n\ttx = 0;\n\tty = 0;\n\txOffset = 0;\n\txVelocity = 0;\n\tyOffset = 0;\n\tyVelocity = 0;\n\trotateOffset = 0;\n\trotateVelocity = 0;\n\tscaleOffset = 0\n\tscaleVelocity = 0;\n\n\tactive = false;\n\n\treadonly skeleton: Skeleton;\n\tremaining = 0;\n\tlastTime = 0;\n\n\tconstructor (data: PhysicsConstraintData, skeleton: Skeleton) {\n\t\tthis.data = data;\n\t\tthis.skeleton = skeleton;\n\n\t\tthis.bone = skeleton.bones[data.bone.index];\n\n\t\tthis.inertia = data.inertia;\n\t\tthis.strength = data.strength;\n\t\tthis.damping = data.damping;\n\t\tthis.massInverse = data.massInverse;\n\t\tthis.wind = data.wind;\n\t\tthis.gravity = data.gravity;\n\t\tthis.mix = data.mix;\n\t}\n\n\treset () {\n\t\tthis.remaining = 0;\n\t\tthis.lastTime = this.skeleton.time;\n\t\tthis._reset = true;\n\t\tthis.xOffset = 0;\n\t\tthis.xVelocity = 0;\n\t\tthis.yOffset = 0;\n\t\tthis.yVelocity = 0;\n\t\tthis.rotateOffset = 0;\n\t\tthis.rotateVelocity = 0;\n\t\tthis.scaleOffset = 0;\n\t\tthis.scaleVelocity = 0;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.inertia = data.inertia;\n\t\tthis.strength = data.strength;\n\t\tthis.damping = data.damping;\n\t\tthis.massInverse = data.massInverse;\n\t\tthis.wind = data.wind;\n\t\tthis.gravity = data.gravity;\n\t\tthis.mix = data.mix;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\t/** Applies the constraint to the constrained bones. */\n\tupdate (physics: Physics) {\n\t\tconst mix = this.mix;\n\t\tif (mix == 0) return;\n\n\t\tconst x = this.data.x > 0, y = this.data.y > 0, rotateOrShearX = this.data.rotate > 0 || this.data.shearX > 0, scaleX = this.data.scaleX > 0;\n\t\tconst bone = this.bone;\n\t\tconst l = bone.data.length;\n\n\t\tswitch (physics) {\n\t\t\tcase Physics.none:\n\t\t\t\treturn;\n\t\t\tcase Physics.reset:\n\t\t\t\tthis.reset();\n\t\t\t// Fall through.\n\t\t\tcase Physics.update:\n\t\t\t\tconst skeleton = this.skeleton;\n\t\t\t\tconst delta = Math.max(this.skeleton.time - this.lastTime, 0);\n\t\t\t\tthis.remaining += delta;\n\t\t\t\tthis.lastTime = skeleton.time;\n\n\t\t\t\tconst bx = bone.worldX, by = bone.worldY;\n\t\t\t\tif (this._reset) {\n\t\t\t\t\tthis._reset = false;\n\t\t\t\t\tthis.ux = bx;\n\t\t\t\t\tthis.uy = by;\n\t\t\t\t} else {\n\t\t\t\t\tlet a = this.remaining, i = this.inertia, t = this.data.step, f = this.skeleton.data.referenceScale, d = -1;\n\t\t\t\t\tlet qx = this.data.limit * delta, qy = qx * Math.abs(skeleton.scaleY);\n\t\t\t\t\tqx *= Math.abs(skeleton.scaleX);\n\t\t\t\t\tif (x || y) {\n\t\t\t\t\t\tif (x) {\n\t\t\t\t\t\t\tconst u = (this.ux - bx) * i;\n\t\t\t\t\t\t\tthis.xOffset += u > qx ? qx : u < -qx ? -qx : u;\n\t\t\t\t\t\t\tthis.ux = bx;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (y) {\n\t\t\t\t\t\t\tconst u = (this.uy - by) * i;\n\t\t\t\t\t\t\tthis.yOffset += u > qy ? qy : u < -qy ? -qy : u;\n\t\t\t\t\t\t\tthis.uy = by;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (a >= t) {\n\t\t\t\t\t\t\td = Math.pow(this.damping, 60 * t);\n\t\t\t\t\t\t\tconst m = this.massInverse * t, e = this.strength, w = this.wind * f * skeleton.scaleX, g = this.gravity * f * skeleton.scaleY;\n\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\tif (x) {\n\t\t\t\t\t\t\t\t\tthis.xVelocity += (w - this.xOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.xOffset += this.xVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.xVelocity *= d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (y) {\n\t\t\t\t\t\t\t\t\tthis.yVelocity -= (g + this.yOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.yOffset += this.yVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.yVelocity *= d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ta -= t;\n\t\t\t\t\t\t\t} while (a >= t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (x) bone.worldX += this.xOffset * mix * this.data.x;\n\t\t\t\t\t\tif (y) bone.worldY += this.yOffset * mix * this.data.y;\n\t\t\t\t\t}\n\t\t\t\t\tif (rotateOrShearX || scaleX) {\n\t\t\t\t\t\tlet ca = Math.atan2(bone.c, bone.a), c = 0, s = 0, mr = 0;\n\t\t\t\t\t\tlet dx = this.cx - bone.worldX, dy = this.cy - bone.worldY;\n\t\t\t\t\t\tif (dx > qx)\n\t\t\t\t\t\t\tdx = qx;\n\t\t\t\t\t\telse if (dx < -qx) //\n\t\t\t\t\t\t\tdx = -qx;\n\t\t\t\t\t\tif (dy > qy)\n\t\t\t\t\t\t\tdy = qy;\n\t\t\t\t\t\telse if (dy < -qy) //\n\t\t\t\t\t\t\tdy = -qy;\n\t\t\t\t\t\tif (rotateOrShearX) {\n\t\t\t\t\t\t\tmr = (this.data.rotate + this.data.shearX) * mix;\n\t\t\t\t\t\t\tlet r = Math.atan2(dy + this.ty, dx + this.tx) - ca - this.rotateOffset * mr;\n\t\t\t\t\t\t\tthis.rotateOffset += (r - Math.ceil(r * MathUtils.invPI2 - 0.5) * MathUtils.PI2) * i;\n\t\t\t\t\t\t\tr = this.rotateOffset * mr + ca;\n\t\t\t\t\t\t\tc = Math.cos(r);\n\t\t\t\t\t\t\ts = Math.sin(r);\n\t\t\t\t\t\t\tif (scaleX) {\n\t\t\t\t\t\t\t\tr = l * bone.getWorldScaleX();\n\t\t\t\t\t\t\t\tif (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tc = Math.cos(ca);\n\t\t\t\t\t\t\ts = Math.sin(ca);\n\t\t\t\t\t\t\tconst r = l * bone.getWorldScaleX();\n\t\t\t\t\t\t\tif (r > 0) this.scaleOffset += (dx * c + dy * s) * i / r;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ta = this.remaining;\n\t\t\t\t\t\tif (a >= t) {\n\t\t\t\t\t\t\tif (d == -1) d = Math.pow(this.damping, 60 * t);\n\t\t\t\t\t\t\tconst m = this.massInverse * t, e = this.strength, w = this.wind, g = (Skeleton.yDown ? -this.gravity : this.gravity), h = l / f;\n\t\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\t\ta -= t;\n\t\t\t\t\t\t\t\tif (scaleX) {\n\t\t\t\t\t\t\t\t\tthis.scaleVelocity += (w * c - g * s - this.scaleOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.scaleOffset += this.scaleVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.scaleVelocity *= d;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (rotateOrShearX) {\n\t\t\t\t\t\t\t\t\tthis.rotateVelocity -= ((w * s + g * c) * h + this.rotateOffset * e) * m;\n\t\t\t\t\t\t\t\t\tthis.rotateOffset += this.rotateVelocity * t;\n\t\t\t\t\t\t\t\t\tthis.rotateVelocity *= d;\n\t\t\t\t\t\t\t\t\tif (a < t) break;\n\t\t\t\t\t\t\t\t\tconst r = this.rotateOffset * mr + ca;\n\t\t\t\t\t\t\t\t\tc = Math.cos(r);\n\t\t\t\t\t\t\t\t\ts = Math.sin(r);\n\t\t\t\t\t\t\t\t} else if (a < t) //\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.remaining = a;\n\t\t\t\t}\n\t\t\t\tthis.cx = bone.worldX;\n\t\t\t\tthis.cy = bone.worldY;\n\t\t\t\tbreak;\n\t\t\tcase Physics.pose:\n\t\t\t\tif (x) bone.worldX += this.xOffset * mix * this.data.x;\n\t\t\t\tif (y) bone.worldY += this.yOffset * mix * this.data.y;\n\t\t}\n\n\t\tif (rotateOrShearX) {\n\t\t\tlet o = this.rotateOffset * mix, s = 0, c = 0, a = 0;\n\t\t\tif (this.data.shearX > 0) {\n\t\t\t\tlet r = 0;\n\t\t\t\tif (this.data.rotate > 0) {\n\t\t\t\t\tr = o * this.data.rotate;\n\t\t\t\t\ts = Math.sin(r);\n\t\t\t\t\tc = Math.cos(r);\n\t\t\t\t\ta = bone.b;\n\t\t\t\t\tbone.b = c * a - s * bone.d;\n\t\t\t\t\tbone.d = s * a + c * bone.d;\n\t\t\t\t}\n\t\t\t\tr += o * this.data.shearX;\n\t\t\t\ts = Math.sin(r);\n\t\t\t\tc = Math.cos(r);\n\t\t\t\ta = bone.a;\n\t\t\t\tbone.a = c * a - s * bone.c;\n\t\t\t\tbone.c = s * a + c * bone.c;\n\t\t\t} else {\n\t\t\t\to *= this.data.rotate;\n\t\t\t\ts = Math.sin(o);\n\t\t\t\tc = Math.cos(o);\n\t\t\t\ta = bone.a;\n\t\t\t\tbone.a = c * a - s * bone.c;\n\t\t\t\tbone.c = s * a + c * bone.c;\n\t\t\t\ta = bone.b;\n\t\t\t\tbone.b = c * a - s * bone.d;\n\t\t\t\tbone.d = s * a + c * bone.d;\n\t\t\t}\n\t\t}\n\t\tif (scaleX) {\n\t\t\tconst s = 1 + this.scaleOffset * mix * this.data.scaleX;\n\t\t\tbone.a *= s;\n\t\t\tbone.c *= s;\n\t\t}\n\t\tif (physics != Physics.pose) {\n\t\t\tthis.tx = l * bone.a;\n\t\t\tthis.ty = l * bone.c;\n\t\t}\n\t\tbone.updateAppliedTransform();\n\t}\n\n\t/** Translates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone moved an additional\n\t * amount in world space. */\n\ttranslate (x: number, y: number) {\n\t\tthis.ux -= x;\n\t\tthis.uy -= y;\n\t\tthis.cx -= x;\n\t\tthis.cy -= y;\n\t}\n\n\t/** Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the\n\t * specified point in world space. */\n\trotate (x: number, y: number, degrees: number) {\n\t\tconst r = degrees * MathUtils.degRad, cos = Math.cos(r), sin = Math.sin(r);\n\t\tconst dx = this.cx - x, dy = this.cy - y;\n\t\tthis.translate(dx * cos - dy * sin - dx, dx * sin + dy * cos - dy);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Attachment, VertexAttachment } from \"./attachments/Attachment.js\";\nimport { Bone } from \"./Bone.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { SlotData } from \"./SlotData.js\";\nimport { Color } from \"./Utils.js\";\n\n/** Stores a slot's current pose. Slots organize attachments for {@link Skeleton#drawOrder} purposes and provide a place to store\n * state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared\n * across multiple skeletons. */\nexport class Slot {\n\t/** The slot's setup pose data. */\n\tdata: SlotData;\n\n\t/** The bone this slot belongs to. */\n\tbone: Bone;\n\n\t/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two\n\t * color tinting. */\n\tcolor: Color;\n\n\t/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark\n\t * color's alpha is not used. */\n\tdarkColor: Color | null = null;\n\n\tattachment: Attachment | null = null;\n\n\tattachmentState: number = 0;\n\n\t/** The index of the texture region to display when the slot's attachment has a {@link Sequence}. -1 represents the\n\t * {@link Sequence#getSetupIndex()}. */\n\tsequenceIndex: number = -1;\n\n\t/** Values to deform the slot's attachment. For an unweighted mesh, the entries are local positions for each vertex. For a\n\t * weighted mesh, the entries are an offset for each vertex which will be added to the mesh's local vertex positions.\n\t *\n\t * See {@link VertexAttachment#computeWorldVertices()} and {@link DeformTimeline}. */\n\tdeform = new Array();\n\n\tconstructor (data: SlotData, bone: Bone) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!bone) throw new Error(\"bone cannot be null.\");\n\t\tthis.data = data;\n\t\tthis.bone = bone;\n\t\tthis.color = new Color();\n\t\tthis.darkColor = !data.darkColor ? null : new Color();\n\t\tthis.setToSetupPose();\n\t}\n\n\t/** The skeleton this slot belongs to. */\n\tgetSkeleton (): Skeleton {\n\t\treturn this.bone.skeleton;\n\t}\n\n\t/** The current attachment for the slot, or null if the slot has no attachment. */\n\tgetAttachment (): Attachment | null {\n\t\treturn this.attachment;\n\t}\n\n\t/** Sets the slot's attachment and, if the attachment changed, resets {@link #sequenceIndex} and clears the {@link #deform}.\n\t * The deform is not cleared if the old attachment has the same {@link VertexAttachment#getTimelineAttachment()} as the\n\t * specified attachment. */\n\tsetAttachment (attachment: Attachment | null) {\n\t\tif (this.attachment == attachment) return;\n\t\tif (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment)\n\t\t\t|| (attachment).timelineAttachment != (this.attachment).timelineAttachment) {\n\t\t\tthis.deform.length = 0;\n\t\t}\n\t\tthis.attachment = attachment;\n\t\tthis.sequenceIndex = -1;\n\t}\n\n\t/** Sets this slot to the setup pose. */\n\tsetToSetupPose () {\n\t\tthis.color.setFromColor(this.data.color);\n\t\tif (this.darkColor) this.darkColor.setFromColor(this.data.darkColor!);\n\t\tif (!this.data.attachmentName)\n\t\t\tthis.attachment = null;\n\t\telse {\n\t\t\tthis.attachment = null;\n\t\t\tthis.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName));\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Bone } from \"./Bone.js\";\nimport { Physics, Skeleton } from \"./Skeleton.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { Vector2, MathUtils } from \"./Utils.js\";\n\n\n/** Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained\n * bones to match that of the target bone.\n *\n * See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */\nexport class TransformConstraint implements Updatable {\n\n\t/** The transform constraint's setup pose data. */\n\tdata: TransformConstraintData;\n\n\t/** The bones that will be modified by this transform constraint. */\n\tbones: Array;\n\n\t/** The target bone whose world transform will be copied to the constrained bones. */\n\ttarget: Bone;\n\n\tmixRotate = 0; mixX = 0; mixY = 0; mixScaleX = 0; mixScaleY = 0; mixShearY = 0;\n\n\ttemp = new Vector2();\n\tactive = false;\n\n\tconstructor (data: TransformConstraintData, skeleton: Skeleton) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0; i < data.bones.length; i++) {\n\t\t\tlet bone = skeleton.findBone(data.bones[i].name);\n\t\t\tif (!bone) throw new Error(`Couldn't find bone ${data.bones[i].name}.`);\n\t\t\tthis.bones.push(bone);\n\t\t}\n\t\tlet target = skeleton.findBone(data.target.name);\n\t\tif (!target) throw new Error(`Couldn't find target bone ${data.target.name}.`);\n\t\tthis.target = target;\n\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t\tthis.mixScaleX = data.mixScaleX;\n\t\tthis.mixScaleY = data.mixScaleY;\n\t\tthis.mixShearY = data.mixShearY;\n\t}\n\n\tisActive () {\n\t\treturn this.active;\n\t}\n\n\tsetToSetupPose () {\n\t\tconst data = this.data;\n\t\tthis.mixRotate = data.mixRotate;\n\t\tthis.mixX = data.mixX;\n\t\tthis.mixY = data.mixY;\n\t\tthis.mixScaleX = data.mixScaleX;\n\t\tthis.mixScaleY = data.mixScaleY;\n\t\tthis.mixShearY = data.mixShearY;\n\t}\n\n\tupdate (physics: Physics) {\n\t\tif (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0) return;\n\n\t\tif (this.data.local) {\n\t\t\tif (this.data.relative)\n\t\t\t\tthis.applyRelativeLocal();\n\t\t\telse\n\t\t\t\tthis.applyAbsoluteLocal();\n\t\t} else {\n\t\t\tif (this.data.relative)\n\t\t\t\tthis.applyRelativeWorld();\n\t\t\telse\n\t\t\t\tthis.applyAbsoluteWorld();\n\t\t}\n\t}\n\n\tapplyAbsoluteWorld () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\t\tlet translate = mixX != 0 || mixY != 0;\n\n\t\tlet target = this.target;\n\t\tlet ta = target.a, tb = target.b, tc = target.c, td = target.d;\n\t\tlet degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;\n\t\tlet offsetRotation = this.data.offsetRotation * degRadReflect;\n\t\tlet offsetShearY = this.data.offsetShearY * degRadReflect;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tif (mixRotate != 0) {\n\t\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\t\tlet r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation;\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr *= mixRotate;\n\t\t\t\tlet cos = Math.cos(r), sin = Math.sin(r);\n\t\t\t\tbone.a = cos * a - sin * c;\n\t\t\t\tbone.b = cos * b - sin * d;\n\t\t\t\tbone.c = sin * a + cos * c;\n\t\t\t\tbone.d = sin * b + cos * d;\n\t\t\t}\n\n\t\t\tif (translate) {\n\t\t\t\tlet temp = this.temp;\n\t\t\t\ttarget.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));\n\t\t\t\tbone.worldX += (temp.x - bone.worldX) * mixX;\n\t\t\t\tbone.worldY += (temp.y - bone.worldY) * mixY;\n\t\t\t}\n\n\t\t\tif (mixScaleX != 0) {\n\t\t\t\tlet s = Math.sqrt(bone.a * bone.a + bone.c * bone.c);\n\t\t\t\tif (s != 0) s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s;\n\t\t\t\tbone.a *= s;\n\t\t\t\tbone.c *= s;\n\t\t\t}\n\t\t\tif (mixScaleY != 0) {\n\t\t\t\tlet s = Math.sqrt(bone.b * bone.b + bone.d * bone.d);\n\t\t\t\tif (s != 0) s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s;\n\t\t\t\tbone.b *= s;\n\t\t\t\tbone.d *= s;\n\t\t\t}\n\n\t\t\tif (mixShearY > 0) {\n\t\t\t\tlet b = bone.b, d = bone.d;\n\t\t\t\tlet by = Math.atan2(d, b);\n\t\t\t\tlet r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr = by + (r + offsetShearY) * mixShearY;\n\t\t\t\tlet s = Math.sqrt(b * b + d * d);\n\t\t\t\tbone.b = Math.cos(r) * s;\n\t\t\t\tbone.d = Math.sin(r) * s;\n\t\t\t}\n\n\t\t\tbone.updateAppliedTransform();\n\t\t}\n\t}\n\n\tapplyRelativeWorld () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\t\tlet translate = mixX != 0 || mixY != 0;\n\n\t\tlet target = this.target;\n\t\tlet ta = target.a, tb = target.b, tc = target.c, td = target.d;\n\t\tlet degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;\n\t\tlet offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tif (mixRotate != 0) {\n\t\t\t\tlet a = bone.a, b = bone.b, c = bone.c, d = bone.d;\n\t\t\t\tlet r = Math.atan2(tc, ta) + offsetRotation;\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tr *= mixRotate;\n\t\t\t\tlet cos = Math.cos(r), sin = Math.sin(r);\n\t\t\t\tbone.a = cos * a - sin * c;\n\t\t\t\tbone.b = cos * b - sin * d;\n\t\t\t\tbone.c = sin * a + cos * c;\n\t\t\t\tbone.d = sin * b + cos * d;\n\t\t\t}\n\n\t\t\tif (translate) {\n\t\t\t\tlet temp = this.temp;\n\t\t\t\ttarget.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));\n\t\t\t\tbone.worldX += temp.x * mixX;\n\t\t\t\tbone.worldY += temp.y * mixY;\n\t\t\t}\n\n\t\t\tif (mixScaleX != 0) {\n\t\t\t\tlet s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1;\n\t\t\t\tbone.a *= s;\n\t\t\t\tbone.c *= s;\n\t\t\t}\n\t\t\tif (mixScaleY != 0) {\n\t\t\t\tlet s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1;\n\t\t\t\tbone.b *= s;\n\t\t\t\tbone.d *= s;\n\t\t\t}\n\n\t\t\tif (mixShearY > 0) {\n\t\t\t\tlet r = Math.atan2(td, tb) - Math.atan2(tc, ta);\n\t\t\t\tif (r > MathUtils.PI)\n\t\t\t\t\tr -= MathUtils.PI2;\n\t\t\t\telse if (r < -MathUtils.PI) //\n\t\t\t\t\tr += MathUtils.PI2;\n\t\t\t\tlet b = bone.b, d = bone.d;\n\t\t\t\tr = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY;\n\t\t\t\tlet s = Math.sqrt(b * b + d * d);\n\t\t\t\tbone.b = Math.cos(r) * s;\n\t\t\t\tbone.d = Math.sin(r) * s;\n\t\t\t}\n\n\t\t\tbone.updateAppliedTransform();\n\t\t}\n\t}\n\n\tapplyAbsoluteLocal () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\n\t\tlet target = this.target;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tlet rotation = bone.arotation;\n\t\t\tif (mixRotate != 0) rotation += (target.arotation - rotation + this.data.offsetRotation) * mixRotate;\n\n\t\t\tlet x = bone.ax, y = bone.ay;\n\t\t\tx += (target.ax - x + this.data.offsetX) * mixX;\n\t\t\ty += (target.ay - y + this.data.offsetY) * mixY;\n\n\t\t\tlet scaleX = bone.ascaleX, scaleY = bone.ascaleY;\n\t\t\tif (mixScaleX != 0 && scaleX != 0)\n\t\t\t\tscaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX;\n\t\t\tif (mixScaleY != 0 && scaleY != 0)\n\t\t\t\tscaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY;\n\n\t\t\tlet shearY = bone.ashearY;\n\t\t\tif (mixShearY != 0) shearY += (target.ashearY - shearY + this.data.offsetShearY) * mixShearY;\n\n\t\t\tbone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);\n\t\t}\n\t}\n\n\tapplyRelativeLocal () {\n\t\tlet mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,\n\t\t\tmixScaleY = this.mixScaleY, mixShearY = this.mixShearY;\n\n\t\tlet target = this.target;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\n\t\t\tlet rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate;\n\t\t\tlet x = bone.ax + (target.ax + this.data.offsetX) * mixX;\n\t\t\tlet y = bone.ay + (target.ay + this.data.offsetY) * mixY;\n\t\t\tlet scaleX = bone.ascaleX * (((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX) + 1);\n\t\t\tlet scaleY = bone.ascaleY * (((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY) + 1);\n\t\t\tlet shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY;\n\n\t\t\tbone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Attachment } from \"./attachments/Attachment.js\";\nimport { ClippingAttachment } from \"./attachments/ClippingAttachment.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { PathAttachment } from \"./attachments/PathAttachment.js\";\nimport { RegionAttachment } from \"./attachments/RegionAttachment.js\";\nimport { Bone } from \"./Bone.js\";\nimport { IkConstraint } from \"./IkConstraint.js\";\nimport { PathConstraint } from \"./PathConstraint.js\";\nimport { PhysicsConstraint } from \"./PhysicsConstraint.js\";\nimport { SkeletonClipping } from \"./SkeletonClipping.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { Slot } from \"./Slot.js\";\nimport { TransformConstraint } from \"./TransformConstraint.js\";\nimport { Updatable } from \"./Updatable.js\";\nimport { Color, Utils, MathUtils, Vector2, NumberArrayLike } from \"./Utils.js\";\n\n/** Stores the current pose for a skeleton.\n *\n * See [Instance objects](http://esotericsoftware.com/spine-runtime-architecture#Instance-objects) in the Spine Runtimes Guide. */\nexport class Skeleton {\n\tprivate static quadTriangles = [0, 1, 2, 2, 3, 0];\n\tstatic yDown = false;\n\n\t/** The skeleton's setup pose data. */\n\tdata: SkeletonData;\n\n\t/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */\n\tbones: Array;\n\n\t/** The skeleton's slots in the setup pose draw order. */\n\tslots: Array;\n\n\t/** The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order. */\n\tdrawOrder: Array;\n\n\t/** The skeleton's IK constraints. */\n\tikConstraints: Array;\n\n\t/** The skeleton's transform constraints. */\n\ttransformConstraints: Array;\n\n\t/** The skeleton's path constraints. */\n\tpathConstraints: Array;\n\n\n\t/** The skeleton's physics constraints. */\n\tphysicsConstraints: Array;\n\n\t/** The list of bones and constraints, sorted in the order they should be updated, as computed by {@link #updateCache()}. */\n\t_updateCache = new Array();\n\n\t/** The skeleton's current skin. May be null. */\n\tskin: Skin | null = null;\n\n\t/** The color to tint all the skeleton's attachments. */\n\tcolor: Color;\n\n\t/** Scales the entire skeleton on the X axis. This affects all bones, even if the bone's transform mode disallows scale\n\t * inheritance. */\n\tscaleX = 1;\n\n\t/** Scales the entire skeleton on the Y axis. This affects all bones, even if the bone's transform mode disallows scale\n\t * inheritance. */\n\tprivate _scaleY = 1;\n\n\tpublic get scaleY () {\n\t\treturn Skeleton.yDown ? -this._scaleY : this._scaleY;\n\t}\n\n\tpublic set scaleY (scaleY: number) {\n\t\tthis._scaleY = scaleY;\n\t}\n\n\t/** Sets the skeleton X position, which is added to the root bone worldX position. */\n\tx = 0;\n\n\t/** Sets the skeleton Y position, which is added to the root bone worldY position. */\n\ty = 0;\n\n\t/** Returns the skeleton's time. This is used for time-based manipulations, such as {@link PhysicsConstraint}.\n\t *

    \n\t * See {@link #update(float)}. */\n\ttime = 0;\n\n\tconstructor (data: SkeletonData) {\n\t\tif (!data) throw new Error(\"data cannot be null.\");\n\t\tthis.data = data;\n\n\t\tthis.bones = new Array();\n\t\tfor (let i = 0; i < data.bones.length; i++) {\n\t\t\tlet boneData = data.bones[i];\n\t\t\tlet bone: Bone;\n\t\t\tif (!boneData.parent)\n\t\t\t\tbone = new Bone(boneData, this, null);\n\t\t\telse {\n\t\t\t\tlet parent = this.bones[boneData.parent.index];\n\t\t\t\tbone = new Bone(boneData, this, parent);\n\t\t\t\tparent.children.push(bone);\n\t\t\t}\n\t\t\tthis.bones.push(bone);\n\t\t}\n\n\t\tthis.slots = new Array();\n\t\tthis.drawOrder = new Array();\n\t\tfor (let i = 0; i < data.slots.length; i++) {\n\t\t\tlet slotData = data.slots[i];\n\t\t\tlet bone = this.bones[slotData.boneData.index];\n\t\t\tlet slot = new Slot(slotData, bone);\n\t\t\tthis.slots.push(slot);\n\t\t\tthis.drawOrder.push(slot);\n\t\t}\n\n\t\tthis.ikConstraints = new Array();\n\t\tfor (let i = 0; i < data.ikConstraints.length; i++) {\n\t\t\tlet ikConstraintData = data.ikConstraints[i];\n\t\t\tthis.ikConstraints.push(new IkConstraint(ikConstraintData, this));\n\t\t}\n\n\t\tthis.transformConstraints = new Array();\n\t\tfor (let i = 0; i < data.transformConstraints.length; i++) {\n\t\t\tlet transformConstraintData = data.transformConstraints[i];\n\t\t\tthis.transformConstraints.push(new TransformConstraint(transformConstraintData, this));\n\t\t}\n\n\t\tthis.pathConstraints = new Array();\n\t\tfor (let i = 0; i < data.pathConstraints.length; i++) {\n\t\t\tlet pathConstraintData = data.pathConstraints[i];\n\t\t\tthis.pathConstraints.push(new PathConstraint(pathConstraintData, this));\n\t\t}\n\n\t\tthis.physicsConstraints = new Array();\n\t\tfor (let i = 0; i < data.physicsConstraints.length; i++) {\n\t\t\tlet physicsConstraintData = data.physicsConstraints[i];\n\t\t\tthis.physicsConstraints.push(new PhysicsConstraint(physicsConstraintData, this));\n\t\t}\n\n\t\tthis.color = new Color(1, 1, 1, 1);\n\t\tthis.updateCache();\n\t}\n\n\t/** Caches information about bones and constraints. Must be called if the {@link #getSkin()} is modified or if bones,\n\t * constraints, or weighted path attachments are added or removed. */\n\tupdateCache () {\n\t\tlet updateCache = this._updateCache;\n\t\tupdateCache.length = 0;\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tbone.sorted = bone.data.skinRequired;\n\t\t\tbone.active = !bone.sorted;\n\t\t}\n\n\t\tif (this.skin) {\n\t\t\tlet skinBones = this.skin.bones;\n\t\t\tfor (let i = 0, n = this.skin.bones.length; i < n; i++) {\n\t\t\t\tlet bone: Bone | null = this.bones[skinBones[i].index];\n\t\t\t\tdo {\n\t\t\t\t\tbone.sorted = false;\n\t\t\t\t\tbone.active = true;\n\t\t\t\t\tbone = bone.parent;\n\t\t\t\t} while (bone);\n\t\t\t}\n\t\t}\n\n\t\t// IK first, lowest hierarchy depth first.\n\t\tlet ikConstraints = this.ikConstraints;\n\t\tlet transformConstraints = this.transformConstraints;\n\t\tlet pathConstraints = this.pathConstraints;\n\t\tlet physicsConstraints = this.physicsConstraints;\n\t\tlet ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length, physicsCount = this.physicsConstraints.length;\n\t\tlet constraintCount = ikCount + transformCount + pathCount + physicsCount;\n\n\t\touter:\n\t\tfor (let i = 0; i < constraintCount; i++) {\n\t\t\tfor (let ii = 0; ii < ikCount; ii++) {\n\t\t\t\tlet constraint = ikConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortIkConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let ii = 0; ii < transformCount; ii++) {\n\t\t\t\tlet constraint = transformConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortTransformConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let ii = 0; ii < pathCount; ii++) {\n\t\t\t\tlet constraint = pathConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortPathConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let ii = 0; ii < physicsCount; ii++) {\n\t\t\t\tconst constraint = physicsConstraints[ii];\n\t\t\t\tif (constraint.data.order == i) {\n\t\t\t\t\tthis.sortPhysicsConstraint(constraint);\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = 0, n = bones.length; i < n; i++)\n\t\t\tthis.sortBone(bones[i]);\n\t}\n\n\tsortIkConstraint (constraint: IkConstraint) {\n\t\tconstraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;\n\t\tif (!constraint.active) return;\n\n\t\tlet target = constraint.target;\n\t\tthis.sortBone(target);\n\n\t\tlet constrained = constraint.bones;\n\t\tlet parent = constrained[0];\n\t\tthis.sortBone(parent);\n\n\t\tif (constrained.length == 1) {\n\t\t\tthis._updateCache.push(constraint);\n\t\t\tthis.sortReset(parent.children);\n\t\t} else {\n\t\t\tlet child = constrained[constrained.length - 1];\n\t\t\tthis.sortBone(child);\n\n\t\t\tthis._updateCache.push(constraint);\n\n\t\t\tthis.sortReset(parent.children);\n\t\t\tchild.sorted = true;\n\t\t}\n\t}\n\n\tsortPathConstraint (constraint: PathConstraint) {\n\t\tconstraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;\n\t\tif (!constraint.active) return;\n\n\t\tlet slot = constraint.target;\n\t\tlet slotIndex = slot.data.index;\n\t\tlet slotBone = slot.bone;\n\t\tif (this.skin) this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);\n\t\tif (this.data.defaultSkin && this.data.defaultSkin != this.skin)\n\t\t\tthis.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);\n\t\tfor (let i = 0, n = this.data.skins.length; i < n; i++)\n\t\t\tthis.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);\n\n\t\tlet attachment = slot.getAttachment();\n\t\tif (attachment instanceof PathAttachment) this.sortPathConstraintAttachmentWith(attachment, slotBone);\n\n\t\tlet constrained = constraint.bones;\n\t\tlet boneCount = constrained.length;\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tthis.sortBone(constrained[i]);\n\n\t\tthis._updateCache.push(constraint);\n\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tthis.sortReset(constrained[i].children);\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tconstrained[i].sorted = true;\n\t}\n\n\tsortTransformConstraint (constraint: TransformConstraint) {\n\t\tconstraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || (this.skin && Utils.contains(this.skin.constraints, constraint.data, true)))!;\n\t\tif (!constraint.active) return;\n\n\t\tthis.sortBone(constraint.target);\n\n\t\tlet constrained = constraint.bones;\n\t\tlet boneCount = constrained.length;\n\t\tif (constraint.data.local) {\n\t\t\tfor (let i = 0; i < boneCount; i++) {\n\t\t\t\tlet child = constrained[i];\n\t\t\t\tthis.sortBone(child.parent!);\n\t\t\t\tthis.sortBone(child);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (let i = 0; i < boneCount; i++) {\n\t\t\t\tthis.sortBone(constrained[i]);\n\t\t\t}\n\t\t}\n\n\t\tthis._updateCache.push(constraint);\n\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tthis.sortReset(constrained[i].children);\n\t\tfor (let i = 0; i < boneCount; i++)\n\t\t\tconstrained[i].sorted = true;\n\t}\n\n\tsortPathConstraintAttachment (skin: Skin, slotIndex: number, slotBone: Bone) {\n\t\tlet attachments = skin.attachments[slotIndex];\n\t\tif (!attachments) return;\n\t\tfor (let key in attachments) {\n\t\t\tthis.sortPathConstraintAttachmentWith(attachments[key], slotBone);\n\t\t}\n\t}\n\n\tsortPathConstraintAttachmentWith (attachment: Attachment, slotBone: Bone) {\n\t\tif (!(attachment instanceof PathAttachment)) return;\n\t\tlet pathBones = (attachment).bones;\n\t\tif (!pathBones)\n\t\t\tthis.sortBone(slotBone);\n\t\telse {\n\t\t\tlet bones = this.bones;\n\t\t\tfor (let i = 0, n = pathBones.length; i < n;) {\n\t\t\t\tlet nn = pathBones[i++];\n\t\t\t\tnn += i;\n\t\t\t\twhile (i < nn)\n\t\t\t\t\tthis.sortBone(bones[pathBones[i++]]);\n\t\t\t}\n\t\t}\n\t}\n\n\tsortPhysicsConstraint (constraint: PhysicsConstraint) {\n\t\tconst bone = constraint.bone;\n\t\tconstraint.active = bone.active && (!constraint.data.skinRequired || (this.skin != null && Utils.contains(this.skin.constraints, constraint.data, true)));\n\t\tif (!constraint.active) return;\n\n\t\tthis.sortBone(bone);\n\n\t\tthis._updateCache.push(constraint);\n\n\t\tthis.sortReset(bone.children);\n\t\tbone.sorted = true;\n\t}\n\n\tsortBone (bone: Bone) {\n\t\tif (!bone) return;\n\t\tif (bone.sorted) return;\n\t\tlet parent = bone.parent;\n\t\tif (parent) this.sortBone(parent);\n\t\tbone.sorted = true;\n\t\tthis._updateCache.push(bone);\n\t}\n\n\tsortReset (bones: Array) {\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tif (!bone.active) continue;\n\t\t\tif (bone.sorted) this.sortReset(bone.children);\n\t\t\tbone.sorted = false;\n\t\t}\n\t}\n\n\t/** Updates the world transform for each bone and applies all constraints.\n\t *\n\t * See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine\n\t * Runtimes Guide. */\n\tupdateWorldTransform (physics: Physics) {\n\t\tif (physics === undefined || physics === null) throw new Error(\"physics is undefined\");\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tbone.ax = bone.x;\n\t\t\tbone.ay = bone.y;\n\t\t\tbone.arotation = bone.rotation;\n\t\t\tbone.ascaleX = bone.scaleX;\n\t\t\tbone.ascaleY = bone.scaleY;\n\t\t\tbone.ashearX = bone.shearX;\n\t\t\tbone.ashearY = bone.shearY;\n\t\t}\n\n\t\tlet updateCache = this._updateCache;\n\t\tfor (let i = 0, n = updateCache.length; i < n; i++)\n\t\t\tupdateCache[i].update(physics);\n\t}\n\n\tupdateWorldTransformWith (physics: Physics, parent: Bone) {\n\t\tif (!parent) throw new Error(\"parent cannot be null.\");\n\n\t\tlet bones = this.bones;\n\t\tfor (let i = 1, n = bones.length; i < n; i++) { // Skip root bone.\n\t\t\tlet bone = bones[i];\n\t\t\tbone.ax = bone.x;\n\t\t\tbone.ay = bone.y;\n\t\t\tbone.arotation = bone.rotation;\n\t\t\tbone.ascaleX = bone.scaleX;\n\t\t\tbone.ascaleY = bone.scaleY;\n\t\t\tbone.ashearX = bone.shearX;\n\t\t\tbone.ashearY = bone.shearY;\n\t\t}\n\n\t\t// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.\n\t\tlet rootBone = this.getRootBone();\n\t\tif (!rootBone) throw new Error(\"Root bone must not be null.\");\n\t\tlet pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;\n\t\trootBone.worldX = pa * this.x + pb * this.y + parent.worldX;\n\t\trootBone.worldY = pc * this.x + pd * this.y + parent.worldY;\n\n\t\tconst rx = (rootBone.rotation + rootBone.shearX) * MathUtils.degRad;\n\t\tconst ry = (rootBone.rotation + 90 + rootBone.shearY) * MathUtils.degRad;\n\t\tconst la = Math.cos(rx) * rootBone.scaleX;\n\t\tconst lb = Math.cos(ry) * rootBone.scaleY;\n\t\tconst lc = Math.sin(rx) * rootBone.scaleX;\n\t\tconst ld = Math.sin(ry) * rootBone.scaleY;\n\t\trootBone.a = (pa * la + pb * lc) * this.scaleX;\n\t\trootBone.b = (pa * lb + pb * ld) * this.scaleX;\n\t\trootBone.c = (pc * la + pd * lc) * this.scaleY;\n\t\trootBone.d = (pc * lb + pd * ld) * this.scaleY;\n\n\t\t// Update everything except root bone.\n\t\tlet updateCache = this._updateCache;\n\t\tfor (let i = 0, n = updateCache.length; i < n; i++) {\n\t\t\tlet updatable = updateCache[i];\n\t\t\tif (updatable != rootBone) updatable.update(physics);\n\t\t}\n\t}\n\n\t/** Sets the bones, constraints, and slots to their setup pose values. */\n\tsetToSetupPose () {\n\t\tthis.setBonesToSetupPose();\n\t\tthis.setSlotsToSetupPose();\n\t}\n\n\t/** Sets the bones and constraints to their setup pose values. */\n\tsetBonesToSetupPose () {\n\t\tfor (const bone of this.bones) bone.setToSetupPose();\n\t\tfor (const constraint of this.ikConstraints) constraint.setToSetupPose();\n\t\tfor (const constraint of this.transformConstraints) constraint.setToSetupPose();\n\t\tfor (const constraint of this.pathConstraints) constraint.setToSetupPose();\n\t\tfor (const constraint of this.physicsConstraints) constraint.setToSetupPose();\n\t}\n\n\t/** Sets the slots and draw order to their setup pose values. */\n\tsetSlotsToSetupPose () {\n\t\tlet slots = this.slots;\n\t\tUtils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);\n\t\tfor (let i = 0, n = slots.length; i < n; i++)\n\t\t\tslots[i].setToSetupPose();\n\t}\n\n\t/** @returns May return null. */\n\tgetRootBone () {\n\t\tif (this.bones.length == 0) return null;\n\t\treturn this.bones[0];\n\t}\n\n\t/** @returns May be null. */\n\tfindBone (boneName: string) {\n\t\tif (!boneName) throw new Error(\"boneName cannot be null.\");\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tif (bone.data.name == boneName) return bone;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it\n\t * repeatedly.\n\t * @returns May be null. */\n\tfindSlot (slotName: string) {\n\t\tif (!slotName) throw new Error(\"slotName cannot be null.\");\n\t\tlet slots = this.slots;\n\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (slot.data.name == slotName) return slot;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Sets a skin by name.\n\t *\n\t * See {@link #setSkin()}. */\n\tsetSkinByName (skinName: string) {\n\t\tlet skin = this.data.findSkin(skinName);\n\t\tif (!skin) throw new Error(\"Skin not found: \" + skinName);\n\t\tthis.setSkin(skin);\n\t}\n\n\t/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#defaultSkin default skin}. If the\n\t * skin is changed, {@link #updateCache()} is called.\n\t *\n\t * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no\n\t * old skin, each slot's setup mode attachment is attached from the new skin.\n\t *\n\t * After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling\n\t * {@link #setSlotsToSetupPose()}. Also, often {@link AnimationState#apply()} is called before the next time the\n\t * skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.\n\t * @param newSkin May be null. */\n\tsetSkin (newSkin: Skin) {\n\t\tif (newSkin == this.skin) return;\n\t\tif (newSkin) {\n\t\t\tif (this.skin)\n\t\t\t\tnewSkin.attachAll(this, this.skin);\n\t\t\telse {\n\t\t\t\tlet slots = this.slots;\n\t\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\t\tlet slot = slots[i];\n\t\t\t\t\tlet name = slot.data.attachmentName;\n\t\t\t\t\tif (name) {\n\t\t\t\t\t\tlet attachment = newSkin.getAttachment(i, name);\n\t\t\t\t\t\tif (attachment) slot.setAttachment(attachment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.skin = newSkin;\n\t\tthis.updateCache();\n\t}\n\n\n\t/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment\n\t * name.\n\t *\n\t * See {@link #getAttachment()}.\n\t * @returns May be null. */\n\tgetAttachmentByName (slotName: string, attachmentName: string): Attachment | null {\n\t\tlet slot = this.data.findSlot(slotName);\n\t\tif (!slot) throw new Error(`Can't find slot with name ${slotName}`);\n\t\treturn this.getAttachment(slot.index, attachmentName);\n\t}\n\n\t/** Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot index and\n\t * attachment name. First the skin is checked and if the attachment was not found, the default skin is checked.\n\t *\n\t * See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide.\n\t * @returns May be null. */\n\tgetAttachment (slotIndex: number, attachmentName: string): Attachment | null {\n\t\tif (!attachmentName) throw new Error(\"attachmentName cannot be null.\");\n\t\tif (this.skin) {\n\t\t\tlet attachment = this.skin.getAttachment(slotIndex, attachmentName);\n\t\t\tif (attachment) return attachment;\n\t\t}\n\t\tif (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);\n\t\treturn null;\n\t}\n\n\t/** A convenience method to set an attachment by finding the slot with {@link #findSlot()}, finding the attachment with\n\t * {@link #getAttachment()}, then setting the slot's {@link Slot#attachment}.\n\t * @param attachmentName May be null to clear the slot's attachment. */\n\tsetAttachment (slotName: string, attachmentName: string) {\n\t\tif (!slotName) throw new Error(\"slotName cannot be null.\");\n\t\tlet slots = this.slots;\n\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (slot.data.name == slotName) {\n\t\t\t\tlet attachment: Attachment | null = null;\n\t\t\t\tif (attachmentName) {\n\t\t\t\t\tattachment = this.getAttachment(i, attachmentName);\n\t\t\t\t\tif (!attachment) throw new Error(\"Attachment not found: \" + attachmentName + \", for slot: \" + slotName);\n\t\t\t\t}\n\t\t\t\tslot.setAttachment(attachment);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthrow new Error(\"Slot not found: \" + slotName);\n\t}\n\n\n\t/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method\n\t * than to call it repeatedly.\n\t * @return May be null. */\n\tfindIkConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.ikConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of\n\t * this method than to call it repeatedly.\n\t * @return May be null. */\n\tfindTransformConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.transformConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method\n\t * than to call it repeatedly.\n\t * @return May be null. */\n\tfindPathConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.pathConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this\n\t * method than to call it repeatedly. */\n\tfindPhysicsConstraint (constraintName: string) {\n\t\tif (constraintName == null) throw new Error(\"constraintName cannot be null.\");\n\t\treturn this.physicsConstraints.find((constraint) => constraint.data.name == constraintName) ?? null;\n\t}\n\n\t/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`.\n\t * Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */\n\tgetBoundsRect (clipper?: SkeletonClipping) {\n\t\tlet offset = new Vector2();\n\t\tlet size = new Vector2();\n\t\tthis.getBounds(offset, size, undefined, clipper);\n\t\treturn { x: offset.x, y: offset.y, width: size.x, height: size.y };\n\t}\n\n\t/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.\n\t * @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.\n\t * @param size An output value, the width and height of the AABB.\n\t * @param temp Working memory to temporarily store attachments' computed world vertices.\n\t * @param clipper {@link SkeletonClipping} to use. If null, no clipping is applied. */\n\tgetBounds (offset: Vector2, size: Vector2, temp: Array = new Array(2), clipper: SkeletonClipping | null = null) {\n\t\tif (!offset) throw new Error(\"offset cannot be null.\");\n\t\tif (!size) throw new Error(\"size cannot be null.\");\n\t\tlet drawOrder = this.drawOrder;\n\t\tlet minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet slot = drawOrder[i];\n\t\t\tif (!slot.bone.active) continue;\n\t\t\tlet verticesLength = 0;\n\t\t\tlet vertices: NumberArrayLike | null = null;\n\t\t\tlet triangles: NumberArrayLike | null = null;\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\tverticesLength = 8;\n\t\t\t\tvertices = Utils.setArraySize(temp, verticesLength, 0);\n\t\t\t\tattachment.computeWorldVertices(slot, vertices, 0, 2);\n\t\t\t\ttriangles = Skeleton.quadTriangles;\n\t\t\t} else if (attachment instanceof MeshAttachment) {\n\t\t\t\tlet mesh = (attachment);\n\t\t\t\tverticesLength = mesh.worldVerticesLength;\n\t\t\t\tvertices = Utils.setArraySize(temp, verticesLength, 0);\n\t\t\t\tmesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);\n\t\t\t\ttriangles = mesh.triangles;\n\t\t\t} else if (attachment instanceof ClippingAttachment && clipper != null) {\n\t\t\t\tclipper.clipStart(slot, attachment);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (vertices && triangles) {\n\t\t\t\tif (clipper != null && clipper.isClipping()) {\n\t\t\t\t\tclipper.clipTriangles(vertices, triangles, triangles.length);\n\t\t\t\t\tvertices = clipper.clippedVertices;\n\t\t\t\t\tverticesLength = clipper.clippedVertices.length;\n\t\t\t\t}\n\t\t\t\tfor (let ii = 0, nn = vertices.length; ii < nn; ii += 2) {\n\t\t\t\t\tlet x = vertices[ii], y = vertices[ii + 1];\n\t\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (clipper != null) clipper.clipEndWithSlot(slot);\n\t\t}\n\t\tif (clipper != null) clipper.clipEnd();\n\t\toffset.set(minX, minY);\n\t\tsize.set(maxX - minX, maxY - minY);\n\t}\n\n\t/** Increments the skeleton's {@link #time}. */\n\tupdate (delta: number) {\n\t\tthis.time += delta;\n\t}\n\n\tphysicsTranslate (x: number, y: number) {\n\t\tconst physicsConstraints = this.physicsConstraints;\n\t\tfor (let i = 0, n = physicsConstraints.length; i < n; i++)\n\t\t\tphysicsConstraints[i].translate(x, y);\n\t}\n\n\t/** Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */\n\tphysicsRotate (x: number, y: number, degrees: number) {\n\t\tconst physicsConstraints = this.physicsConstraints;\n\t\tfor (let i = 0, n = physicsConstraints.length; i < n; i++)\n\t\t\tphysicsConstraints[i].rotate(x, y, degrees);\n\t}\n}\n\n/** Determines how physics and other non-deterministic updates are applied. */\nexport enum Physics {\n\t/** Physics are not updated or applied. */\n\tnone,\n\n\t/** Physics are reset to the current pose. */\n\treset,\n\n\t/** Physics are updated and the pose from physics is applied. */\n\tupdate,\n\n\t/** Physics are not updated but the pose from physics is applied. */\n\tpose\n}", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\n\n\n/** Stores the setup pose for a {@link PhysicsConstraint}.\n *

    \n * See Physics constraints in the Spine User Guide. */\nexport class PhysicsConstraintData extends ConstraintData {\n\tprivate _bone: BoneData | null = null;\n\t/** The bone constrained by this physics constraint. */\n\tpublic set bone (boneData: BoneData) { this._bone = boneData; }\n\tpublic get bone () {\n\t\tif (!this._bone) throw new Error(\"BoneData not set.\")\n\t\telse return this._bone;\n\t}\n\n\tx = 0;\n\ty = 0;\n\trotate = 0;\n\tscaleX = 0;\n\tshearX = 0;\n\tlimit = 0;\n\tstep = 0;\n\tinertia = 0;\n\tstrength = 0;\n\tdamping = 0;\n\tmassInverse = 0;\n\twind = 0;\n\tgravity = 0;\n\t/** A percentage (0-1) that controls the mix between the constrained and unconstrained poses. */\n\tmix = 0;\n\tinertiaGlobal = false;\n\tstrengthGlobal = false;\n\tdampingGlobal = false;\n\tmassGlobal = false;\n\twindGlobal = false;\n\tgravityGlobal = false;\n\tmixGlobal = false;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation } from \"./Animation\"\nimport { BoneData } from \"./BoneData.js\";\nimport { EventData } from \"./EventData.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { PathConstraintData } from \"./PathConstraintData.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { SlotData } from \"./SlotData.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\n\n/** Stores the setup pose and all of the stateless data for a skeleton.\n *\n * See [Data objects](http://esotericsoftware.com/spine-runtime-architecture#Data-objects) in the Spine Runtimes\n * Guide. */\nexport class SkeletonData {\n\n\t/** The skeleton's name, which by default is the name of the skeleton data file, if possible. May be null. */\n\tname: string | null = null;\n\n\t/** The skeleton's bones, sorted parent first. The root bone is always the first bone. */\n\tbones = new Array(); // Ordered parents first.\n\n\t/** The skeleton's slots in the setup pose draw order. */\n\tslots = new Array(); // Setup pose draw order.\n\n\tskins = new Array();\n\n\t/** The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine.\n\t *\n\t * See {@link Skeleton#getAttachmentByName()}.\n\t * May be null. */\n\tdefaultSkin: Skin | null = null;\n\n\t/** The skeleton's events. */\n\tevents = new Array();\n\n\t/** The skeleton's animations. */\n\tanimations = new Array();\n\n\t/** The skeleton's IK constraints. */\n\tikConstraints = new Array();\n\n\t/** The skeleton's transform constraints. */\n\ttransformConstraints = new Array();\n\n\t/** The skeleton's path constraints. */\n\tpathConstraints = new Array();\n\n\t/** The skeleton's physics constraints. */\n\tphysicsConstraints = new Array();\n\n\t/** The X coordinate of the skeleton's axis aligned bounding box in the setup pose. */\n\tx: number = 0;\n\n\t/** The Y coordinate of the skeleton's axis aligned bounding box in the setup pose. */\n\ty: number = 0;\n\n\t/** The width of the skeleton's axis aligned bounding box in the setup pose. */\n\twidth: number = 0;\n\n\t/** The height of the skeleton's axis aligned bounding box in the setup pose. */\n\theight: number = 0;\n\n\t/** Baseline scale factor for applying distance-dependent effects on non-scalable properties, such as angle or scale. Default\n\t * is 100. */\n\treferenceScale = 100;\n\n\t/** The Spine version used to export the skeleton data, or null. */\n\tversion: string | null = null;\n\n\t/** The skeleton data hash. This value will change if any of the skeleton data has changed. May be null. */\n\thash: string | null = null;\n\n\t// Nonessential\n\t/** The dopesheet FPS in Spine. Available only when nonessential data was exported. */\n\tfps = 0;\n\n\t/** The path to the images directory as defined in Spine. Available only when nonessential data was exported. May be null. */\n\timagesPath: string | null = null;\n\n\t/** The path to the audio directory as defined in Spine. Available only when nonessential data was exported. May be null. */\n\taudioPath: string | null = null;\n\n\t/** Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindBone (boneName: string) {\n\t\tif (!boneName) throw new Error(\"boneName cannot be null.\");\n\t\tlet bones = this.bones;\n\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\tlet bone = bones[i];\n\t\t\tif (bone.name == boneName) return bone;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindSlot (slotName: string) {\n\t\tif (!slotName) throw new Error(\"slotName cannot be null.\");\n\t\tlet slots = this.slots;\n\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (slot.name == slotName) return slot;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindSkin (skinName: string) {\n\t\tif (!skinName) throw new Error(\"skinName cannot be null.\");\n\t\tlet skins = this.skins;\n\t\tfor (let i = 0, n = skins.length; i < n; i++) {\n\t\t\tlet skin = skins[i];\n\t\t\tif (skin.name == skinName) return skin;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it\n\t * multiple times.\n\t * @returns May be null. */\n\tfindEvent (eventDataName: string) {\n\t\tif (!eventDataName) throw new Error(\"eventDataName cannot be null.\");\n\t\tlet events = this.events;\n\t\tfor (let i = 0, n = events.length; i < n; i++) {\n\t\t\tlet event = events[i];\n\t\t\tif (event.name == eventDataName) return event;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to\n\t * call it multiple times.\n\t * @returns May be null. */\n\tfindAnimation (animationName: string) {\n\t\tif (!animationName) throw new Error(\"animationName cannot be null.\");\n\t\tlet animations = this.animations;\n\t\tfor (let i = 0, n = animations.length; i < n; i++) {\n\t\t\tlet animation = animations[i];\n\t\t\tif (animation.name == animationName) return animation;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method\n\t * than to call it multiple times.\n\t * @return May be null. */\n\tfindIkConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst ikConstraints = this.ikConstraints;\n\t\tfor (let i = 0, n = ikConstraints.length; i < n; i++) {\n\t\t\tconst constraint = ikConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of\n\t * this method than to call it multiple times.\n\t * @return May be null. */\n\tfindTransformConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst transformConstraints = this.transformConstraints;\n\t\tfor (let i = 0, n = transformConstraints.length; i < n; i++) {\n\t\t\tconst constraint = transformConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method\n\t * than to call it multiple times.\n\t * @return May be null. */\n\tfindPathConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst pathConstraints = this.pathConstraints;\n\t\tfor (let i = 0, n = pathConstraints.length; i < n; i++) {\n\t\t\tconst constraint = pathConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Finds a physics constraint by comparing each physics constraint's name. It is more efficient to cache the results of this method\n\t * than to call it multiple times.\n\t * @return May be null. */\n\tfindPhysicsConstraint (constraintName: string) {\n\t\tif (!constraintName) throw new Error(\"constraintName cannot be null.\");\n\t\tconst physicsConstraints = this.physicsConstraints;\n\t\tfor (let i = 0, n = physicsConstraints.length; i < n; i++) {\n\t\t\tconst constraint = physicsConstraints[i];\n\t\t\tif (constraint.name == constraintName) return constraint;\n\t\t}\n\t\treturn null;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Attachment } from \"./attachments/Attachment.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { BoneData } from \"./BoneData.js\";\nimport { ConstraintData } from \"./ConstraintData.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { Color, StringMap } from \"./Utils.js\";\n\n/** Stores an entry in the skin consisting of the slot index, name, and attachment **/\nexport class SkinEntry {\n\tconstructor (public slotIndex: number = 0, public name: string, public attachment: Attachment) { }\n}\n\n/** Stores attachments by slot index and attachment name.\n *\n * See SkeletonData {@link SkeletonData#defaultSkin}, Skeleton {@link Skeleton#skin}, and\n * [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide. */\nexport class Skin {\n\t/** The skin's name, which is unique across all skins in the skeleton. */\n\tname: string;\n\n\tattachments = new Array>();\n\tbones = Array();\n\tconstraints = new Array();\n\n\t/** The color of the skin as it was in Spine, or a default color if nonessential data was not exported. */\n\tcolor = new Color(0.99607843, 0.61960787, 0.30980393, 1); // fe9e4fff\n\n\tconstructor (name: string) {\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tthis.name = name;\n\t}\n\n\t/** Adds an attachment to the skin for the specified slot index and name. */\n\tsetAttachment (slotIndex: number, name: string, attachment: Attachment) {\n\t\tif (!attachment) throw new Error(\"attachment cannot be null.\");\n\t\tlet attachments = this.attachments;\n\t\tif (slotIndex >= attachments.length) attachments.length = slotIndex + 1;\n\t\tif (!attachments[slotIndex]) attachments[slotIndex] = {};\n\t\tattachments[slotIndex][name] = attachment;\n\t}\n\n\t/** Adds all attachments, bones, and constraints from the specified skin to this skin. */\n\taddSkin (skin: Skin) {\n\t\tfor (let i = 0; i < skin.bones.length; i++) {\n\t\t\tlet bone = skin.bones[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.bones.length; ii++) {\n\t\t\t\tif (this.bones[ii] == bone) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.bones.push(bone);\n\t\t}\n\n\t\tfor (let i = 0; i < skin.constraints.length; i++) {\n\t\t\tlet constraint = skin.constraints[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.constraints.length; ii++) {\n\t\t\t\tif (this.constraints[ii] == constraint) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.constraints.push(constraint);\n\t\t}\n\n\t\tlet attachments = skin.getAttachments();\n\t\tfor (let i = 0; i < attachments.length; i++) {\n\t\t\tvar attachment = attachments[i];\n\t\t\tthis.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);\n\t\t}\n\t}\n\n\t/** Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not\n\t * copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals. */\n\tcopySkin (skin: Skin) {\n\t\tfor (let i = 0; i < skin.bones.length; i++) {\n\t\t\tlet bone = skin.bones[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.bones.length; ii++) {\n\t\t\t\tif (this.bones[ii] == bone) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.bones.push(bone);\n\t\t}\n\n\t\tfor (let i = 0; i < skin.constraints.length; i++) {\n\t\t\tlet constraint = skin.constraints[i];\n\t\t\tlet contained = false;\n\t\t\tfor (let ii = 0; ii < this.constraints.length; ii++) {\n\t\t\t\tif (this.constraints[ii] == constraint) {\n\t\t\t\t\tcontained = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contained) this.constraints.push(constraint);\n\t\t}\n\n\t\tlet attachments = skin.getAttachments();\n\t\tfor (let i = 0; i < attachments.length; i++) {\n\t\t\tvar attachment = attachments[i];\n\t\t\tif (!attachment.attachment) continue;\n\t\t\tif (attachment.attachment instanceof MeshAttachment) {\n\t\t\t\tattachment.attachment = attachment.attachment.newLinkedMesh();\n\t\t\t\tthis.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);\n\t\t\t} else {\n\t\t\t\tattachment.attachment = attachment.attachment.copy();\n\t\t\t\tthis.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Returns the attachment for the specified slot index and name, or null. */\n\tgetAttachment (slotIndex: number, name: string): Attachment | null {\n\t\tlet dictionary = this.attachments[slotIndex];\n\t\treturn dictionary ? dictionary[name] : null;\n\t}\n\n\t/** Removes the attachment in the skin for the specified slot index and name, if any. */\n\tremoveAttachment (slotIndex: number, name: string) {\n\t\tlet dictionary = this.attachments[slotIndex];\n\t\tif (dictionary) delete dictionary[name];\n\t}\n\n\t/** Returns all attachments in this skin. */\n\tgetAttachments (): Array {\n\t\tlet entries = new Array();\n\t\tfor (var i = 0; i < this.attachments.length; i++) {\n\t\t\tlet slotAttachments = this.attachments[i];\n\t\t\tif (slotAttachments) {\n\t\t\t\tfor (let name in slotAttachments) {\n\t\t\t\t\tlet attachment = slotAttachments[name];\n\t\t\t\t\tif (attachment) entries.push(new SkinEntry(i, name, attachment));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t}\n\n\t/** Returns all attachments in this skin for the specified slot index. */\n\tgetAttachmentsForSlot (slotIndex: number, attachments: Array) {\n\t\tlet slotAttachments = this.attachments[slotIndex];\n\t\tif (slotAttachments) {\n\t\t\tfor (let name in slotAttachments) {\n\t\t\t\tlet attachment = slotAttachments[name];\n\t\t\t\tif (attachment) attachments.push(new SkinEntry(slotIndex, name, attachment));\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Clears all attachments, bones, and constraints. */\n\tclear () {\n\t\tthis.attachments.length = 0;\n\t\tthis.bones.length = 0;\n\t\tthis.constraints.length = 0;\n\t}\n\n\t/** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */\n\tattachAll (skeleton: Skeleton, oldSkin: Skin) {\n\t\tlet slotIndex = 0;\n\t\tfor (let i = 0; i < skeleton.slots.length; i++) {\n\t\t\tlet slot = skeleton.slots[i];\n\t\t\tlet slotAttachment = slot.getAttachment();\n\t\t\tif (slotAttachment && slotIndex < oldSkin.attachments.length) {\n\t\t\t\tlet dictionary = oldSkin.attachments[slotIndex];\n\t\t\t\tfor (let key in dictionary) {\n\t\t\t\t\tlet skinAttachment: Attachment = dictionary[key];\n\t\t\t\t\tif (slotAttachment == skinAttachment) {\n\t\t\t\t\t\tlet attachment = this.getAttachment(slotIndex, key);\n\t\t\t\t\t\tif (attachment) slot.setAttachment(attachment);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tslotIndex++;\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoneData } from \"./BoneData.js\";\nimport { Color } from \"./Utils.js\";\n\n/** Stores the setup pose for a {@link Slot}. */\nexport class SlotData {\n\t/** The index of the slot in {@link Skeleton#getSlots()}. */\n\tindex: number = 0;\n\n\t/** The name of the slot, which is unique across all slots in the skeleton. */\n\tname: string;\n\n\t/** The bone this slot belongs to. */\n\tboneData: BoneData;\n\n\t/** The color used to tint the slot's attachment. If {@link #getDarkColor()} is set, this is used as the light color for two\n\t * color tinting. */\n\tcolor = new Color(1, 1, 1, 1);\n\n\t/** The dark color used to tint the slot's attachment for two color tinting, or null if two color tinting is not used. The dark\n\t * color's alpha is not used. */\n\tdarkColor: Color | null = null;\n\n\t/** The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible. */\n\tattachmentName: string | null = null;\n\n\t/** The blend mode for drawing the slot's attachment. */\n\tblendMode: BlendMode = BlendMode.Normal;\n\n\t/** False if the slot was hidden in Spine and nonessential data was exported. Does not affect runtime rendering. */\n\tvisible = true;\n\n\tconstructor (index: number, name: string, boneData: BoneData) {\n\t\tif (index < 0) throw new Error(\"index must be >= 0.\");\n\t\tif (!name) throw new Error(\"name cannot be null.\");\n\t\tif (!boneData) throw new Error(\"boneData cannot be null.\");\n\t\tthis.index = index;\n\t\tthis.name = name;\n\t\tthis.boneData = boneData;\n\t}\n}\n\n/** Determines how images are blended with existing pixels when drawn. */\nexport enum BlendMode { Normal, Additive, Multiply, Screen }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { ConstraintData } from \"./ConstraintData.js\";\nimport { BoneData } from \"./BoneData.js\";\n\n/** Stores the setup pose for a {@link TransformConstraint}.\n *\n * See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide. */\nexport class TransformConstraintData extends ConstraintData {\n\n\t/** The bones that will be modified by this transform constraint. */\n\tbones = new Array();\n\n\t/** The target bone whose world transform will be copied to the constrained bones. */\n\tprivate _target: BoneData | null = null;\n\tpublic set target (boneData: BoneData) { this._target = boneData; }\n\tpublic get target () {\n\t\tif (!this._target) throw new Error(\"BoneData not set.\")\n\t\telse return this._target;\n\t}\n\n\tmixRotate = 0;\n\tmixX = 0;\n\tmixY = 0;\n\tmixScaleX = 0;\n\tmixScaleY = 0;\n\tmixShearY = 0;\n\n\t/** An offset added to the constrained bone rotation. */\n\toffsetRotation = 0;\n\n\t/** An offset added to the constrained bone X translation. */\n\toffsetX = 0;\n\n\t/** An offset added to the constrained bone Y translation. */\n\toffsetY = 0;\n\n\t/** An offset added to the constrained bone scaleX. */\n\toffsetScaleX = 0;\n\n\t/** An offset added to the constrained bone scaleY. */\n\toffsetScaleY = 0;\n\n\t/** An offset added to the constrained bone shearY. */\n\toffsetShearY = 0;\n\n\trelative = false;\n\tlocal = false;\n\n\tconstructor (name: string) {\n\t\tsuper(name, 0, false);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation, Timeline, InheritTimeline, AttachmentTimeline, RGBATimeline, RGBTimeline, RGBA2Timeline, RGB2Timeline, AlphaTimeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline2, CurveTimeline, SequenceTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline } from \"./Animation.js\";\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { AttachmentLoader } from \"./attachments/AttachmentLoader.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { Sequence, SequenceModeValues } from \"./attachments/Sequence.js\";\nimport { BoneData } from \"./BoneData.js\";\nimport { Event } from \"./Event.js\";\nimport { EventData } from \"./EventData.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { PathConstraintData, PositionMode, SpacingMode } from \"./PathConstraintData.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { SlotData } from \"./SlotData.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\nimport { Color, Utils } from \"./Utils.js\";\n\n/** Loads skeleton data in the Spine binary format.\n *\n * See [Spine binary format](http://esotericsoftware.com/spine-binary-format) and\n * [JSON and binary data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the Spine\n * Runtimes Guide. */\nexport class SkeletonBinary {\n\t/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at\n\t * runtime than were used in Spine.\n\t *\n\t * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */\n\tscale = 1;\n\n\tattachmentLoader: AttachmentLoader;\n\tprivate linkedMeshes = new Array();\n\n\tconstructor (attachmentLoader: AttachmentLoader) {\n\t\tthis.attachmentLoader = attachmentLoader;\n\t}\n\n\treadSkeletonData (binary: Uint8Array | ArrayBuffer): SkeletonData {\n\t\tlet scale = this.scale;\n\n\t\tlet skeletonData = new SkeletonData();\n\t\tskeletonData.name = \"\"; // BOZO\n\n\t\tlet input = new BinaryInput(binary);\n\n\t\tlet lowHash = input.readInt32();\n\t\tlet highHash = input.readInt32();\n\t\tskeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16);\n\t\tskeletonData.version = input.readString();\n\t\tskeletonData.x = input.readFloat();\n\t\tskeletonData.y = input.readFloat();\n\t\tskeletonData.width = input.readFloat();\n\t\tskeletonData.height = input.readFloat();\n\t\tskeletonData.referenceScale = input.readFloat() * scale;\n\n\t\tlet nonessential = input.readBoolean();\n\t\tif (nonessential) {\n\t\t\tskeletonData.fps = input.readFloat();\n\t\t\tskeletonData.imagesPath = input.readString();\n\t\t\tskeletonData.audioPath = input.readString();\n\t\t}\n\n\t\tlet n = 0;\n\t\t// Strings.\n\t\tn = input.readInt(true)\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet str = input.readString();\n\t\t\tif (!str) throw new Error(\"String in string table must not be null.\");\n\t\t\tinput.strings.push(str);\n\t\t}\n\n\t\t// Bones.\n\t\tn = input.readInt(true)\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"Bone name must not be null.\");\n\t\t\tlet parent = i == 0 ? null : skeletonData.bones[input.readInt(true)];\n\t\t\tlet data = new BoneData(i, name, parent);\n\t\t\tdata.rotation = input.readFloat();\n\t\t\tdata.x = input.readFloat() * scale;\n\t\t\tdata.y = input.readFloat() * scale;\n\t\t\tdata.scaleX = input.readFloat();\n\t\t\tdata.scaleY = input.readFloat();\n\t\t\tdata.shearX = input.readFloat();\n\t\t\tdata.shearY = input.readFloat();\n\t\t\tdata.length = input.readFloat() * scale;\n\t\t\tdata.inherit = input.readByte();\n\t\t\tdata.skinRequired = input.readBoolean();\n\t\t\tif (nonessential) {\n\t\t\t\tColor.rgba8888ToColor(data.color, input.readInt32());\n\t\t\t\tdata.icon = input.readString() ?? undefined;\n\t\t\t\tdata.visible = input.readBoolean();\n\t\t\t}\n\t\t\tskeletonData.bones.push(data);\n\t\t}\n\n\t\t// Slots.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet slotName = input.readString();\n\t\t\tif (!slotName) throw new Error(\"Slot name must not be null.\");\n\t\t\tlet boneData = skeletonData.bones[input.readInt(true)];\n\t\t\tlet data = new SlotData(i, slotName, boneData);\n\t\t\tColor.rgba8888ToColor(data.color, input.readInt32());\n\n\t\t\tlet darkColor = input.readInt32();\n\t\t\tif (darkColor != -1) Color.rgb888ToColor(data.darkColor = new Color(), darkColor);\n\n\t\t\tdata.attachmentName = input.readStringRef();\n\t\t\tdata.blendMode = input.readInt(true);\n\t\t\tif (nonessential) data.visible = input.readBoolean();\n\t\t\tskeletonData.slots.push(data);\n\t\t}\n\n\t\t// IK constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"IK constraint data name must not be null.\");\n\t\t\tlet data = new IkConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tnn = input.readInt(true);\n\t\t\tfor (let ii = 0; ii < nn; ii++)\n\t\t\t\tdata.bones.push(skeletonData.bones[input.readInt(true)]);\n\t\t\tdata.target = skeletonData.bones[input.readInt(true)];\n\t\t\tlet flags = input.readByte();\n\t\t\tdata.skinRequired = (flags & 1) != 0;\n\t\t\tdata.bendDirection = (flags & 2) != 0 ? 1 : -1;\n\t\t\tdata.compress = (flags & 4) != 0;\n\t\t\tdata.stretch = (flags & 8) != 0;\n\t\t\tdata.uniform = (flags & 16) != 0;\n\t\t\tif ((flags & 32) != 0) data.mix = (flags & 64) != 0 ? input.readFloat() : 1;\n\t\t\tif ((flags & 128) != 0) data.softness = input.readFloat() * scale;\n\t\t\tskeletonData.ikConstraints.push(data);\n\t\t}\n\n\t\t// Transform constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"Transform constraint data name must not be null.\");\n\t\t\tlet data = new TransformConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tnn = input.readInt(true);\n\t\t\tfor (let ii = 0; ii < nn; ii++)\n\t\t\t\tdata.bones.push(skeletonData.bones[input.readInt(true)]);\n\t\t\tdata.target = skeletonData.bones[input.readInt(true)];\n\t\t\tlet flags = input.readByte();\n\t\t\tdata.skinRequired = (flags & 1) != 0;\n\t\t\tdata.local = (flags & 2) != 0;\n\t\t\tdata.relative = (flags & 4) != 0;\n\t\t\tif ((flags & 8) != 0) data.offsetRotation = input.readFloat();\n\t\t\tif ((flags & 16) != 0) data.offsetX = input.readFloat() * scale;\n\t\t\tif ((flags & 32) != 0) data.offsetY = input.readFloat() * scale;\n\t\t\tif ((flags & 64) != 0) data.offsetScaleX = input.readFloat();\n\t\t\tif ((flags & 128) != 0) data.offsetScaleY = input.readFloat();\n\t\t\tflags = input.readByte();\n\t\t\tif ((flags & 1) != 0) data.offsetShearY = input.readFloat();\n\t\t\tif ((flags & 2) != 0) data.mixRotate = input.readFloat();\n\t\t\tif ((flags & 4) != 0) data.mixX = input.readFloat();\n\t\t\tif ((flags & 8) != 0) data.mixY = input.readFloat();\n\t\t\tif ((flags & 16) != 0) data.mixScaleX = input.readFloat();\n\t\t\tif ((flags & 32) != 0) data.mixScaleY = input.readFloat();\n\t\t\tif ((flags & 64) != 0) data.mixShearY = input.readFloat();\n\t\t\tskeletonData.transformConstraints.push(data);\n\t\t}\n\n\t\t// Path constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tlet name = input.readString();\n\t\t\tif (!name) throw new Error(\"Path constraint data name must not be null.\");\n\t\t\tlet data = new PathConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tdata.skinRequired = input.readBoolean();\n\t\t\tnn = input.readInt(true);\n\t\t\tfor (let ii = 0; ii < nn; ii++)\n\t\t\t\tdata.bones.push(skeletonData.bones[input.readInt(true)]);\n\t\t\tdata.target = skeletonData.slots[input.readInt(true)];\n\t\t\tconst flags = input.readByte();\n\t\t\tdata.positionMode = flags & 1;\n\t\t\tdata.spacingMode = (flags >> 1) & 3;\n\t\t\tdata.rotateMode = (flags >> 3) & 3;\n\t\t\tif ((flags & 128) != 0) data.offsetRotation = input.readFloat();\n\t\t\tdata.position = input.readFloat();\n\t\t\tif (data.positionMode == PositionMode.Fixed) data.position *= scale;\n\t\t\tdata.spacing = input.readFloat();\n\t\t\tif (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) data.spacing *= scale;\n\t\t\tdata.mixRotate = input.readFloat();\n\t\t\tdata.mixX = input.readFloat();\n\t\t\tdata.mixY = input.readFloat();\n\t\t\tskeletonData.pathConstraints.push(data);\n\t\t}\n\n\t\t// Physics constraints.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0, nn; i < n; i++) {\n\t\t\tconst name = input.readString();\n\t\t\tif (!name) throw new Error(\"Physics constraint data name must not be null.\");\n\t\t\tconst data = new PhysicsConstraintData(name);\n\t\t\tdata.order = input.readInt(true);\n\t\t\tdata.bone = skeletonData.bones[input.readInt(true)];\n\t\t\tlet flags = input.readByte();\n\t\t\tdata.skinRequired = (flags & 1) != 0;\n\t\t\tif ((flags & 2) != 0) data.x = input.readFloat();\n\t\t\tif ((flags & 4) != 0) data.y = input.readFloat();\n\t\t\tif ((flags & 8) != 0) data.rotate = input.readFloat();\n\t\t\tif ((flags & 16) != 0) data.scaleX = input.readFloat();\n\t\t\tif ((flags & 32) != 0) data.shearX = input.readFloat();\n\t\t\tdata.limit = ((flags & 64) != 0 ? input.readFloat() : 5000) * scale;\n\t\t\tdata.step = 1 / input.readUnsignedByte();\n\t\t\tdata.inertia = input.readFloat();\n\t\t\tdata.strength = input.readFloat();\n\t\t\tdata.damping = input.readFloat();\n\t\t\tdata.massInverse = (flags & 128) != 0 ? input.readFloat() : 1;\n\t\t\tdata.wind = input.readFloat();\n\t\t\tdata.gravity = input.readFloat();\n\t\t\tflags = input.readByte();\n\t\t\tif ((flags & 1) != 0) data.inertiaGlobal = true;\n\t\t\tif ((flags & 2) != 0) data.strengthGlobal = true;\n\t\t\tif ((flags & 4) != 0) data.dampingGlobal = true;\n\t\t\tif ((flags & 8) != 0) data.massGlobal = true;\n\t\t\tif ((flags & 16) != 0) data.windGlobal = true;\n\t\t\tif ((flags & 32) != 0) data.gravityGlobal = true;\n\t\t\tif ((flags & 64) != 0) data.mixGlobal = true;\n\t\t\tdata.mix = (flags & 128) != 0 ? input.readFloat() : 1;\n\t\t\tskeletonData.physicsConstraints.push(data);\n\t\t}\n\n\t\t// Default skin.\n\t\tlet defaultSkin = this.readSkin(input, skeletonData, true, nonessential);\n\t\tif (defaultSkin) {\n\t\t\tskeletonData.defaultSkin = defaultSkin;\n\t\t\tskeletonData.skins.push(defaultSkin);\n\t\t}\n\n\t\t// Skins.\n\t\t{\n\t\t\tlet i = skeletonData.skins.length;\n\t\t\tUtils.setArraySize(skeletonData.skins, n = i + input.readInt(true));\n\t\t\tfor (; i < n; i++) {\n\t\t\t\tlet skin = this.readSkin(input, skeletonData, false, nonessential);\n\t\t\t\tif (!skin) throw new Error(\"readSkin() should not have returned null.\");\n\t\t\t\tskeletonData.skins[i] = skin;\n\t\t\t}\n\t\t}\n\n\t\t// Linked meshes.\n\t\tn = this.linkedMeshes.length;\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet linkedMesh = this.linkedMeshes[i];\n\t\t\tconst skin = skeletonData.skins[linkedMesh.skinIndex];\n\t\t\tif (!linkedMesh.parent) throw new Error(\"Linked mesh parent must not be null\");\n\t\t\tlet parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);\n\t\t\tif (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);\n\t\t\tlinkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent as VertexAttachment : linkedMesh.mesh;\n\t\t\tlinkedMesh.mesh.setParentMesh(parent as MeshAttachment);\n\t\t\tif (linkedMesh.mesh.region != null) linkedMesh.mesh.updateRegion();\n\t\t}\n\t\tthis.linkedMeshes.length = 0;\n\n\t\t// Events.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet eventName = input.readString();\n\t\t\tif (!eventName) throw new Error(\"Event data name must not be null\");\n\t\t\tlet data = new EventData(eventName);\n\t\t\tdata.intValue = input.readInt(false);\n\t\t\tdata.floatValue = input.readFloat();\n\t\t\tdata.stringValue = input.readString();\n\t\t\tdata.audioPath = input.readString();\n\t\t\tif (data.audioPath) {\n\t\t\t\tdata.volume = input.readFloat();\n\t\t\t\tdata.balance = input.readFloat();\n\t\t\t}\n\t\t\tskeletonData.events.push(data);\n\t\t}\n\n\t\t// Animations.\n\t\tn = input.readInt(true);\n\t\tfor (let i = 0; i < n; i++) {\n\t\t\tlet animationName = input.readString();\n\t\t\tif (!animationName) throw new Error(\"Animatio name must not be null.\");\n\t\t\tskeletonData.animations.push(this.readAnimation(input, animationName, skeletonData));\n\t\t}\n\t\treturn skeletonData;\n\t}\n\n\tprivate readSkin (input: BinaryInput, skeletonData: SkeletonData, defaultSkin: boolean, nonessential: boolean): Skin | null {\n\t\tlet skin = null;\n\t\tlet slotCount = 0;\n\n\t\tif (defaultSkin) {\n\t\t\tslotCount = input.readInt(true)\n\t\t\tif (slotCount == 0) return null;\n\t\t\tskin = new Skin(\"default\");\n\t\t} else {\n\t\t\tlet skinName = input.readString();\n\t\t\tif (!skinName) throw new Error(\"Skin name must not be null.\");\n\t\t\tskin = new Skin(skinName);\n\t\t\tif (nonessential) Color.rgba8888ToColor(skin.color, input.readInt32());\n\t\t\tskin.bones.length = input.readInt(true);\n\t\t\tfor (let i = 0, n = skin.bones.length; i < n; i++)\n\t\t\t\tskin.bones[i] = skeletonData.bones[input.readInt(true)];\n\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]);\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]);\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]);\n\t\t\tfor (let i = 0, n = input.readInt(true); i < n; i++)\n\t\t\t\tskin.constraints.push(skeletonData.physicsConstraints[input.readInt(true)]);\n\n\t\t\tslotCount = input.readInt(true);\n\t\t}\n\n\t\tfor (let i = 0; i < slotCount; i++) {\n\t\t\tlet slotIndex = input.readInt(true);\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet name = input.readStringRef();\n\t\t\t\tif (!name)\n\t\t\t\t\tthrow new Error(\"Attachment name must not be null\");\n\t\t\t\tlet attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential);\n\t\t\t\tif (attachment) skin.setAttachment(slotIndex, name, attachment);\n\t\t\t}\n\t\t}\n\t\treturn skin;\n\t}\n\n\tprivate readAttachment (input: BinaryInput, skeletonData: SkeletonData, skin: Skin, slotIndex: number, attachmentName: string | null | undefined, nonessential: boolean): Attachment | null {\n\t\tlet scale = this.scale;\n\n\t\tlet flags = input.readByte();\n\t\tconst name = (flags & 8) != 0 ? input.readStringRef() : attachmentName;\n\t\tif (!name) throw new Error(\"Attachment name must not be null\");\n\t\tswitch ((flags & 0b111) as AttachmentType) { // BUG?\n\t\t\tcase AttachmentType.Region: {\n\t\t\t\tlet path = (flags & 16) != 0 ? input.readStringRef() : null;\n\t\t\t\tconst color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff;\n\t\t\t\tconst sequence = (flags & 64) != 0 ? this.readSequence(input) : null;\n\t\t\t\tlet rotation = (flags & 128) != 0 ? input.readFloat() : 0;\n\t\t\t\tlet x = input.readFloat();\n\t\t\t\tlet y = input.readFloat();\n\t\t\t\tlet scaleX = input.readFloat();\n\t\t\t\tlet scaleY = input.readFloat();\n\t\t\t\tlet width = input.readFloat();\n\t\t\t\tlet height = input.readFloat();\n\n\t\t\t\tif (!path) path = name;\n\t\t\t\tlet region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);\n\t\t\t\tif (!region) return null;\n\t\t\t\tregion.path = path;\n\t\t\t\tregion.x = x * scale;\n\t\t\t\tregion.y = y * scale;\n\t\t\t\tregion.scaleX = scaleX;\n\t\t\t\tregion.scaleY = scaleY;\n\t\t\t\tregion.rotation = rotation;\n\t\t\t\tregion.width = width * scale;\n\t\t\t\tregion.height = height * scale;\n\t\t\t\tColor.rgba8888ToColor(region.color, color);\n\t\t\t\tregion.sequence = sequence;\n\t\t\t\tif (sequence == null) region.updateRegion();\n\t\t\t\treturn region;\n\t\t\t}\n\t\t\tcase AttachmentType.BoundingBox: {\n\t\t\t\tlet vertices = this.readVertices(input, (flags & 16) != 0);\n\t\t\t\tlet color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tlet box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);\n\t\t\t\tif (!box) return null;\n\t\t\t\tbox.worldVerticesLength = vertices.length;\n\t\t\t\tbox.vertices = vertices.vertices!;\n\t\t\t\tbox.bones = vertices.bones;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(box.color, color);\n\t\t\t\treturn box;\n\t\t\t}\n\t\t\tcase AttachmentType.Mesh: {\n\t\t\t\tlet path = (flags & 16) != 0 ? input.readStringRef() : name;\n\t\t\t\tconst color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff;\n\t\t\t\tconst sequence = (flags & 64) != 0 ? this.readSequence(input) : null;\n\t\t\t\tconst hullLength = input.readInt(true);\n\t\t\t\tconst vertices = this.readVertices(input, (flags & 128) != 0);\n\t\t\t\tconst uvs = this.readFloatArray(input, vertices.length, 1);\n\t\t\t\tconst triangles = this.readShortArray(input, (vertices.length - hullLength - 2) * 3);\n\t\t\t\tlet edges: number[] = [];\n\t\t\t\tlet width = 0, height = 0;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\tedges = this.readShortArray(input, input.readInt(true));\n\t\t\t\t\twidth = input.readFloat();\n\t\t\t\t\theight = input.readFloat();\n\t\t\t\t}\n\n\t\t\t\tif (!path) path = name;\n\t\t\t\tlet mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);\n\t\t\t\tif (!mesh) return null;\n\t\t\t\tmesh.path = path;\n\t\t\t\tColor.rgba8888ToColor(mesh.color, color);\n\t\t\t\tmesh.bones = vertices.bones;\n\t\t\t\tmesh.vertices = vertices.vertices!;\n\t\t\t\tmesh.worldVerticesLength = vertices.length;\n\t\t\t\tmesh.triangles = triangles;\n\t\t\t\tmesh.regionUVs = uvs;\n\t\t\t\tif (sequence == null) mesh.updateRegion();\n\t\t\t\tmesh.hullLength = hullLength << 1;\n\t\t\t\tmesh.sequence = sequence;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\tmesh.edges = edges;\n\t\t\t\t\tmesh.width = width * scale;\n\t\t\t\t\tmesh.height = height * scale;\n\t\t\t\t}\n\t\t\t\treturn mesh;\n\t\t\t}\n\t\t\tcase AttachmentType.LinkedMesh: {\n\t\t\t\tconst path = (flags & 16) != 0 ? input.readStringRef() : name;\n\t\t\t\tif (path == null) throw new Error(\"Path of linked mesh must not be null\");\n\t\t\t\tconst color = (flags & 32) != 0 ? input.readInt32() : 0xffffffff;\n\t\t\t\tconst sequence = (flags & 64) != 0 ? this.readSequence(input) : null;\n\t\t\t\tconst inheritTimelines = (flags & 128) != 0;\n\t\t\t\tconst skinIndex = input.readInt(true);\n\t\t\t\tconst parent = input.readStringRef();\n\t\t\t\tlet width = 0, height = 0;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\twidth = input.readFloat();\n\t\t\t\t\theight = input.readFloat();\n\t\t\t\t}\n\n\t\t\t\tlet mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);\n\t\t\t\tif (!mesh) return null;\n\t\t\t\tmesh.path = path;\n\t\t\t\tColor.rgba8888ToColor(mesh.color, color);\n\t\t\t\tmesh.sequence = sequence;\n\t\t\t\tif (nonessential) {\n\t\t\t\t\tmesh.width = width * scale;\n\t\t\t\t\tmesh.height = height * scale;\n\t\t\t\t}\n\t\t\t\tthis.linkedMeshes.push(new LinkedMesh(mesh, skinIndex, slotIndex, parent, inheritTimelines));\n\t\t\t\treturn mesh;\n\t\t\t}\n\t\t\tcase AttachmentType.Path: {\n\t\t\t\tconst closed = (flags & 16) != 0;\n\t\t\t\tconst constantSpeed = (flags & 32) != 0;\n\t\t\t\tconst vertices = this.readVertices(input, (flags & 64) != 0);\n\n\t\t\t\tconst lengths = Utils.newArray(vertices.length / 6, 0);\n\t\t\t\tfor (let i = 0, n = lengths.length; i < n; i++)\n\t\t\t\t\tlengths[i] = input.readFloat() * scale;\n\t\t\t\tconst color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tconst path = this.attachmentLoader.newPathAttachment(skin, name);\n\t\t\t\tif (!path) return null;\n\t\t\t\tpath.closed = closed;\n\t\t\t\tpath.constantSpeed = constantSpeed;\n\t\t\t\tpath.worldVerticesLength = vertices.length;\n\t\t\t\tpath.vertices = vertices.vertices!;\n\t\t\t\tpath.bones = vertices.bones;\n\t\t\t\tpath.lengths = lengths;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(path.color, color);\n\t\t\t\treturn path;\n\t\t\t}\n\t\t\tcase AttachmentType.Point: {\n\t\t\t\tconst rotation = input.readFloat();\n\t\t\t\tconst x = input.readFloat();\n\t\t\t\tconst y = input.readFloat();\n\t\t\t\tconst color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tconst point = this.attachmentLoader.newPointAttachment(skin, name);\n\t\t\t\tif (!point) return null;\n\t\t\t\tpoint.x = x * scale;\n\t\t\t\tpoint.y = y * scale;\n\t\t\t\tpoint.rotation = rotation;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(point.color, color);\n\t\t\t\treturn point;\n\t\t\t}\n\t\t\tcase AttachmentType.Clipping: {\n\t\t\t\tconst endSlotIndex = input.readInt(true);\n\t\t\t\tconst vertices = this.readVertices(input, (flags & 16) != 0);\n\t\t\t\tlet color = nonessential ? input.readInt32() : 0;\n\n\t\t\t\tlet clip = this.attachmentLoader.newClippingAttachment(skin, name);\n\t\t\t\tif (!clip) return null;\n\t\t\t\tclip.endSlot = skeletonData.slots[endSlotIndex];\n\t\t\t\tclip.worldVerticesLength = vertices.length;\n\t\t\t\tclip.vertices = vertices.vertices!;\n\t\t\t\tclip.bones = vertices.bones;\n\t\t\t\tif (nonessential) Color.rgba8888ToColor(clip.color, color);\n\t\t\t\treturn clip;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate readSequence (input: BinaryInput) {\n\t\tlet sequence = new Sequence(input.readInt(true));\n\t\tsequence.start = input.readInt(true);\n\t\tsequence.digits = input.readInt(true);\n\t\tsequence.setupIndex = input.readInt(true);\n\t\treturn sequence;\n\t}\n\n\tprivate readVertices (input: BinaryInput, weighted: boolean): Vertices {\n\t\tconst scale = this.scale;\n\t\tconst vertexCount = input.readInt(true);\n\t\tconst vertices = new Vertices();\n\t\tvertices.length = vertexCount << 1;\n\t\tif (!weighted) {\n\t\t\tvertices.vertices = this.readFloatArray(input, vertices.length, scale);\n\t\t\treturn vertices;\n\t\t}\n\t\tlet weights = new Array();\n\t\tlet bonesArray = new Array();\n\t\tfor (let i = 0; i < vertexCount; i++) {\n\t\t\tlet boneCount = input.readInt(true);\n\t\t\tbonesArray.push(boneCount);\n\t\t\tfor (let ii = 0; ii < boneCount; ii++) {\n\t\t\t\tbonesArray.push(input.readInt(true));\n\t\t\t\tweights.push(input.readFloat() * scale);\n\t\t\t\tweights.push(input.readFloat() * scale);\n\t\t\t\tweights.push(input.readFloat());\n\t\t\t}\n\t\t}\n\t\tvertices.vertices = Utils.toFloatArray(weights);\n\t\tvertices.bones = bonesArray;\n\t\treturn vertices;\n\t}\n\n\tprivate readFloatArray (input: BinaryInput, n: number, scale: number): number[] {\n\t\tlet array = new Array(n);\n\t\tif (scale == 1) {\n\t\t\tfor (let i = 0; i < n; i++)\n\t\t\t\tarray[i] = input.readFloat();\n\t\t} else {\n\t\t\tfor (let i = 0; i < n; i++)\n\t\t\t\tarray[i] = input.readFloat() * scale;\n\t\t}\n\t\treturn array;\n\t}\n\n\tprivate readShortArray (input: BinaryInput, n: number): number[] {\n\t\tlet array = new Array(n);\n\t\tfor (let i = 0; i < n; i++)\n\t\t\tarray[i] = input.readInt(true);\n\t\treturn array;\n\t}\n\n\tprivate readAnimation (input: BinaryInput, name: string, skeletonData: SkeletonData): Animation {\n\t\tinput.readInt(true); // Number of timelines.\n\t\tlet timelines = new Array();\n\t\tlet scale = this.scale;\n\n\t\t// Slot timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet slotIndex = input.readInt(true);\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet timelineType = input.readByte();\n\t\t\t\tlet frameCount = input.readInt(true);\n\t\t\t\tlet frameLast = frameCount - 1;\n\t\t\t\tswitch (timelineType) {\n\t\t\t\t\tcase SLOT_ATTACHMENT: {\n\t\t\t\t\t\tlet timeline = new AttachmentTimeline(frameCount, slotIndex);\n\t\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++)\n\t\t\t\t\t\t\ttimeline.setFrame(frame, input.readFloat(), input.readStringRef());\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGBA: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGBATimeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet a = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b, a);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet a2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = r2;\n\t\t\t\t\t\t\tg = g2;\n\t\t\t\t\t\t\tb = b2;\n\t\t\t\t\t\t\ta = a2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGB: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGBTimeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = r2;\n\t\t\t\t\t\t\tg = g2;\n\t\t\t\t\t\t\tb = b2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGBA2: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet a = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b, a, r2, g2, b2);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet nr = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet na = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nr2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = nr;\n\t\t\t\t\t\t\tg = ng;\n\t\t\t\t\t\t\tb = nb;\n\t\t\t\t\t\t\ta = na;\n\t\t\t\t\t\t\tr2 = nr2;\n\t\t\t\t\t\t\tg2 = ng2;\n\t\t\t\t\t\t\tb2 = nb2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_RGB2: {\n\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\tlet timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex);\n\n\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\tlet r = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet r2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet g2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\tlet b2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, r, g, b, r2, g2, b2);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet nr = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nr2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet ng2 = input.readUnsignedByte() / 255.0;\n\t\t\t\t\t\t\tlet nb2 = input.readUnsignedByte() / 255.0;\n\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tr = nr;\n\t\t\t\t\t\t\tg = ng;\n\t\t\t\t\t\t\tb = nb;\n\t\t\t\t\t\t\tr2 = nr2;\n\t\t\t\t\t\t\tg2 = ng2;\n\t\t\t\t\t\t\tb2 = nb2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase SLOT_ALPHA: {\n\t\t\t\t\t\tlet timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex);\n\t\t\t\t\t\tlet time = input.readFloat(), a = input.readUnsignedByte() / 255;\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, a);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\tlet a2 = input.readUnsignedByte() / 255;\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\ta = a2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Bone timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet boneIndex = input.readInt(true);\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet type = input.readByte(), frameCount = input.readInt(true);\n\t\t\t\tif (type == BONE_INHERIT) {\n\t\t\t\t\tlet timeline = new InheritTimeline(frameCount, boneIndex);\n\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++) {\n\t\t\t\t\t\ttimeline.setFrame(frame, input.readFloat(), input.readByte());\n\t\t\t\t\t}\n\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase BONE_ROTATE:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_TRANSLATE:\n\t\t\t\t\t\ttimelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_TRANSLATEX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_TRANSLATEY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SCALE:\n\t\t\t\t\t\ttimelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SCALEX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SCALEY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SHEAR:\n\t\t\t\t\t\ttimelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SHEARX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BONE_SHEARY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IK constraint timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;\n\t\t\tlet timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index);\n\t\t\tlet flags = input.readByte();\n\t\t\tlet time = input.readFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0;\n\t\t\tlet softness = (flags & 4) != 0 ? input.readFloat() * scale : 0;\n\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\ttimeline.setFrame(frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0);\n\t\t\t\tif (frame == frameLast) break;\n\t\t\t\tflags = input.readByte();\n\t\t\t\tconst time2 = input.readFloat(), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.readFloat() : 1) : 0;\n\t\t\t\tconst softness2 = (flags & 4) != 0 ? input.readFloat() * scale : 0;\n\t\t\t\tif ((flags & 64) != 0) {\n\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t} else if ((flags & 128) != 0) {\n\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);\n\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);\n\t\t\t\t}\n\t\t\t\ttime = time2;\n\t\t\t\tmix = mix2;\n\t\t\t\tsoftness = softness2;\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Transform constraint timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;\n\t\t\tlet timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index);\n\t\t\tlet time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(),\n\t\t\t\tmixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat();\n\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);\n\t\t\t\tif (frame == frameLast) break;\n\t\t\t\tlet time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(),\n\t\t\t\t\tmixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat();\n\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);\n\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1);\n\t\t\t\t}\n\t\t\t\ttime = time2;\n\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\tmixX = mixX2;\n\t\t\t\tmixY = mixY2;\n\t\t\t\tmixScaleX = mixScaleX2;\n\t\t\t\tmixScaleY = mixScaleY2;\n\t\t\t\tmixShearY = mixShearY2;\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Path constraint timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet index = input.readInt(true);\n\t\t\tlet data = skeletonData.pathConstraints[index];\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tconst type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase PATH_POSITION:\n\t\t\t\t\t\ttimelines\n\t\t\t\t\t\t\t.push(readTimeline1(input, new PathConstraintPositionTimeline(frameCount, bezierCount, index),\n\t\t\t\t\t\t\t\tdata.positionMode == PositionMode.Fixed ? scale : 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PATH_SPACING:\n\t\t\t\t\t\ttimelines\n\t\t\t\t\t\t\t.push(readTimeline1(input, new PathConstraintSpacingTimeline(frameCount, bezierCount, index),\n\t\t\t\t\t\t\t\tdata.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PATH_MIX:\n\t\t\t\t\t\tlet timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index);\n\t\t\t\t\t\tlet time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat();\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY);\n\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\tlet time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(),\n\t\t\t\t\t\t\t\tmixY2 = input.readFloat();\n\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\t\t\t\tmixX = mixX2;\n\t\t\t\t\t\t\tmixY = mixY2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Physics timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tconst index = input.readInt(true) - 1;\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tconst type = input.readByte(), frameCount = input.readInt(true);\n\t\t\t\tif (type == PHYSICS_RESET) {\n\t\t\t\t\tconst timeline = new PhysicsConstraintResetTimeline(frameCount, index);\n\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++)\n\t\t\t\t\t\ttimeline.setFrame(frame, input.readFloat());\n\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst bezierCount = input.readInt(true);\n\t\t\t\tswitch (type) {\n\t\t\t\t\tcase PHYSICS_INERTIA:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_STRENGTH:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_DAMPING:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_MASS:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_WIND:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_GRAVITY:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase PHYSICS_MIX:\n\t\t\t\t\t\ttimelines.push(readTimeline1(input, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Deform timelines.\n\t\tfor (let i = 0, n = input.readInt(true); i < n; i++) {\n\t\t\tlet skin = skeletonData.skins[input.readInt(true)];\n\t\t\tfor (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {\n\t\t\t\tlet slotIndex = input.readInt(true);\n\t\t\t\tfor (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) {\n\t\t\t\t\tlet attachmentName = input.readStringRef();\n\t\t\t\t\tif (!attachmentName) throw new Error(\"attachmentName must not be null.\");\n\t\t\t\t\tlet attachment = skin.getAttachment(slotIndex, attachmentName);\n\t\t\t\t\tlet timelineType = input.readByte();\n\t\t\t\t\tlet frameCount = input.readInt(true);\n\t\t\t\t\tlet frameLast = frameCount - 1;\n\n\t\t\t\t\tswitch (timelineType) {\n\t\t\t\t\t\tcase ATTACHMENT_DEFORM: {\n\t\t\t\t\t\t\tlet vertexAttachment = attachment as VertexAttachment;\n\t\t\t\t\t\t\tlet weighted = vertexAttachment.bones;\n\t\t\t\t\t\t\tlet vertices = vertexAttachment.vertices;\n\t\t\t\t\t\t\tlet deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;\n\n\n\t\t\t\t\t\t\tlet bezierCount = input.readInt(true);\n\t\t\t\t\t\t\tlet timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment);\n\n\t\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\t\tlet deform;\n\t\t\t\t\t\t\t\tlet end = input.readInt(true);\n\t\t\t\t\t\t\t\tif (end == 0)\n\t\t\t\t\t\t\t\t\tdeform = weighted ? Utils.newFloatArray(deformLength) : vertices;\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tdeform = Utils.newFloatArray(deformLength);\n\t\t\t\t\t\t\t\t\tlet start = input.readInt(true);\n\t\t\t\t\t\t\t\t\tend += start;\n\t\t\t\t\t\t\t\t\tif (scale == 1) {\n\t\t\t\t\t\t\t\t\t\tfor (let v = start; v < end; v++)\n\t\t\t\t\t\t\t\t\t\t\tdeform[v] = input.readFloat();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tfor (let v = start; v < end; v++)\n\t\t\t\t\t\t\t\t\t\t\tdeform[v] = input.readFloat() * scale;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (!weighted) {\n\t\t\t\t\t\t\t\t\t\tfor (let v = 0, vn = deform.length; v < vn; v++)\n\t\t\t\t\t\t\t\t\t\t\tdeform[v] += vertices[v];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, deform);\n\t\t\t\t\t\t\t\tif (frame == frameLast) break;\n\t\t\t\t\t\t\t\tlet time2 = input.readFloat();\n\t\t\t\t\t\t\t\tswitch (input.readByte()) {\n\t\t\t\t\t\t\t\t\tcase CURVE_STEPPED:\n\t\t\t\t\t\t\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase CURVE_BEZIER:\n\t\t\t\t\t\t\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase ATTACHMENT_SEQUENCE: {\n\t\t\t\t\t\t\tlet timeline = new SequenceTimeline(frameCount, slotIndex, attachment as unknown as HasTextureRegion);\n\t\t\t\t\t\t\tfor (let frame = 0; frame < frameCount; frame++) {\n\t\t\t\t\t\t\t\tlet time = input.readFloat();\n\t\t\t\t\t\t\t\tlet modeAndIndex = input.readInt32();\n\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, SequenceModeValues[modeAndIndex & 0xf], modeAndIndex >> 4,\n\t\t\t\t\t\t\t\t\tinput.readFloat());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Draw order timeline.\n\t\tlet drawOrderCount = input.readInt(true);\n\t\tif (drawOrderCount > 0) {\n\t\t\tlet timeline = new DrawOrderTimeline(drawOrderCount);\n\t\t\tlet slotCount = skeletonData.slots.length;\n\t\t\tfor (let i = 0; i < drawOrderCount; i++) {\n\t\t\t\tlet time = input.readFloat();\n\t\t\t\tlet offsetCount = input.readInt(true);\n\t\t\t\tlet drawOrder = Utils.newArray(slotCount, 0);\n\t\t\t\tfor (let ii = slotCount - 1; ii >= 0; ii--)\n\t\t\t\t\tdrawOrder[ii] = -1;\n\t\t\t\tlet unchanged = Utils.newArray(slotCount - offsetCount, 0);\n\t\t\t\tlet originalIndex = 0, unchangedIndex = 0;\n\t\t\t\tfor (let ii = 0; ii < offsetCount; ii++) {\n\t\t\t\t\tlet slotIndex = input.readInt(true);\n\t\t\t\t\t// Collect unchanged items.\n\t\t\t\t\twhile (originalIndex != slotIndex)\n\t\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t\t// Set changed items.\n\t\t\t\t\tdrawOrder[originalIndex + input.readInt(true)] = originalIndex++;\n\t\t\t\t}\n\t\t\t\t// Collect remaining unchanged items.\n\t\t\t\twhile (originalIndex < slotCount)\n\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t// Fill in unchanged items.\n\t\t\t\tfor (let ii = slotCount - 1; ii >= 0; ii--)\n\t\t\t\t\tif (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];\n\t\t\t\ttimeline.setFrame(i, time, drawOrder);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Event timeline.\n\t\tlet eventCount = input.readInt(true);\n\t\tif (eventCount > 0) {\n\t\t\tlet timeline = new EventTimeline(eventCount);\n\t\t\tfor (let i = 0; i < eventCount; i++) {\n\t\t\t\tlet time = input.readFloat();\n\t\t\t\tlet eventData = skeletonData.events[input.readInt(true)];\n\t\t\t\tlet event = new Event(time, eventData);\n\t\t\t\tevent.intValue = input.readInt(false);\n\t\t\t\tevent.floatValue = input.readFloat();\n\t\t\t\tevent.stringValue = input.readString();\n\t\t\t\tif (event.stringValue == null) event.stringValue = eventData.stringValue;\n\t\t\t\tif (event.data.audioPath) {\n\t\t\t\t\tevent.volume = input.readFloat();\n\t\t\t\t\tevent.balance = input.readFloat();\n\t\t\t\t}\n\t\t\t\ttimeline.setFrame(i, event);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\tlet duration = 0;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\tduration = Math.max(duration, timelines[i].getDuration());\n\t\treturn new Animation(name, timelines, duration);\n\t}\n}\n\nexport class BinaryInput {\n\tconstructor (data: Uint8Array | ArrayBuffer, public strings = new Array(), private index: number = 0, private buffer = new DataView(data instanceof ArrayBuffer ? data : data.buffer)) {\n\t}\n\n\treadByte (): number {\n\t\treturn this.buffer.getInt8(this.index++);\n\t}\n\n\treadUnsignedByte (): number {\n\t\treturn this.buffer.getUint8(this.index++);\n\t}\n\n\treadShort (): number {\n\t\tlet value = this.buffer.getInt16(this.index);\n\t\tthis.index += 2;\n\t\treturn value;\n\t}\n\n\treadInt32 (): number {\n\t\tlet value = this.buffer.getInt32(this.index)\n\t\tthis.index += 4;\n\t\treturn value;\n\t}\n\n\treadInt (optimizePositive: boolean) {\n\t\tlet b = this.readByte();\n\t\tlet result = b & 0x7F;\n\t\tif ((b & 0x80) != 0) {\n\t\t\tb = this.readByte();\n\t\t\tresult |= (b & 0x7F) << 7;\n\t\t\tif ((b & 0x80) != 0) {\n\t\t\t\tb = this.readByte();\n\t\t\t\tresult |= (b & 0x7F) << 14;\n\t\t\t\tif ((b & 0x80) != 0) {\n\t\t\t\t\tb = this.readByte();\n\t\t\t\t\tresult |= (b & 0x7F) << 21;\n\t\t\t\t\tif ((b & 0x80) != 0) {\n\t\t\t\t\t\tb = this.readByte();\n\t\t\t\t\t\tresult |= (b & 0x7F) << 28;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn optimizePositive ? result : ((result >>> 1) ^ -(result & 1));\n\t}\n\n\treadStringRef (): string | null {\n\t\tlet index = this.readInt(true);\n\t\treturn index == 0 ? null : this.strings[index - 1];\n\t}\n\n\treadString (): string | null {\n\t\tlet byteCount = this.readInt(true);\n\t\tswitch (byteCount) {\n\t\t\tcase 0:\n\t\t\t\treturn null;\n\t\t\tcase 1:\n\t\t\t\treturn \"\";\n\t\t}\n\t\tbyteCount--;\n\t\tlet chars = \"\";\n\t\tlet charCount = 0;\n\t\tfor (let i = 0; i < byteCount;) {\n\t\t\tlet b = this.readUnsignedByte();\n\t\t\tswitch (b >> 4) {\n\t\t\t\tcase 12:\n\t\t\t\tcase 13:\n\t\t\t\t\tchars += String.fromCharCode(((b & 0x1F) << 6 | this.readByte() & 0x3F));\n\t\t\t\t\ti += 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 14:\n\t\t\t\t\tchars += String.fromCharCode(((b & 0x0F) << 12 | (this.readByte() & 0x3F) << 6 | this.readByte() & 0x3F));\n\t\t\t\t\ti += 3;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tchars += String.fromCharCode(b);\n\t\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn chars;\n\t}\n\n\treadFloat (): number {\n\t\tlet value = this.buffer.getFloat32(this.index);\n\t\tthis.index += 4;\n\t\treturn value;\n\t}\n\n\treadBoolean (): boolean {\n\t\treturn this.readByte() != 0;\n\t}\n}\n\nclass LinkedMesh {\n\tparent: string | null; skinIndex: number;\n\tslotIndex: number;\n\tmesh: MeshAttachment;\n\tinheritTimeline: boolean;\n\n\tconstructor (mesh: MeshAttachment, skinIndex: number, slotIndex: number, parent: string | null, inheritDeform: boolean) {\n\t\tthis.mesh = mesh;\n\t\tthis.skinIndex = skinIndex;\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.parent = parent;\n\t\tthis.inheritTimeline = inheritDeform;\n\t}\n}\n\nclass Vertices {\n\tconstructor (public bones: Array | null = null, public vertices: Array | Float32Array | null = null, public length: number = 0) { }\n}\n\nenum AttachmentType { Region, BoundingBox, Mesh, LinkedMesh, Path, Point, Clipping }\n\nfunction readTimeline1 (input: BinaryInput, timeline: CurveTimeline1, scale: number): CurveTimeline1 {\n\tlet time = input.readFloat(), value = input.readFloat() * scale;\n\tfor (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value);\n\t\tif (frame == frameLast) break;\n\t\tlet time2 = input.readFloat(), value2 = input.readFloat() * scale;\n\t\tswitch (input.readByte()) {\n\t\t\tcase CURVE_STEPPED:\n\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\tbreak;\n\t\t\tcase CURVE_BEZIER:\n\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale);\n\t\t}\n\t\ttime = time2;\n\t\tvalue = value2;\n\t}\n\treturn timeline;\n}\n\nfunction readTimeline2 (input: BinaryInput, timeline: CurveTimeline2, scale: number): CurveTimeline2 {\n\tlet time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale;\n\tfor (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value1, value2);\n\t\tif (frame == frameLast) break;\n\t\tlet time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale;\n\t\tswitch (input.readByte()) {\n\t\t\tcase CURVE_STEPPED:\n\t\t\t\ttimeline.setStepped(frame);\n\t\t\t\tbreak;\n\t\t\tcase CURVE_BEZIER:\n\t\t\t\tsetBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale);\n\t\t\t\tsetBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale);\n\t\t}\n\t\ttime = time2;\n\t\tvalue1 = nvalue1;\n\t\tvalue2 = nvalue2;\n\t}\n\treturn timeline;\n}\n\nfunction setBezier (input: BinaryInput, timeline: CurveTimeline, bezier: number, frame: number, value: number,\n\ttime1: number, time2: number, value1: number, value2: number, scale: number) {\n\ttimeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2);\n}\n\nconst BONE_ROTATE = 0;\nconst BONE_TRANSLATE = 1;\nconst BONE_TRANSLATEX = 2;\nconst BONE_TRANSLATEY = 3;\nconst BONE_SCALE = 4;\nconst BONE_SCALEX = 5;\nconst BONE_SCALEY = 6;\nconst BONE_SHEAR = 7;\nconst BONE_SHEARX = 8;\nconst BONE_SHEARY = 9;\nconst BONE_INHERIT = 10;\n\nconst SLOT_ATTACHMENT = 0;\nconst SLOT_RGBA = 1;\nconst SLOT_RGB = 2;\nconst SLOT_RGBA2 = 3;\nconst SLOT_RGB2 = 4;\nconst SLOT_ALPHA = 5;\n\nconst ATTACHMENT_DEFORM = 0;\nconst ATTACHMENT_SEQUENCE = 1;\n\nconst PATH_POSITION = 0;\nconst PATH_SPACING = 1;\nconst PATH_MIX = 2;\n\nconst PHYSICS_INERTIA = 0;\nconst PHYSICS_STRENGTH = 1;\nconst PHYSICS_DAMPING = 2;\nconst PHYSICS_MASS = 4;\nconst PHYSICS_WIND = 5;\nconst PHYSICS_GRAVITY = 6;\nconst PHYSICS_MIX = 7;\nconst PHYSICS_RESET = 8;\n\nconst CURVE_LINEAR = 0;\nconst CURVE_STEPPED = 1;\nconst CURVE_BEZIER = 2;\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BoundingBoxAttachment } from \"./attachments/BoundingBoxAttachment.js\";\nimport { Skeleton } from \"./Skeleton.js\";\nimport { NumberArrayLike, Pool, Utils } from \"./Utils.js\";\n\n/** Collects each visible {@link BoundingBoxAttachment} and computes the world vertices for its polygon. The polygon vertices are\n * provided along with convenience methods for doing hit detection. */\nexport class SkeletonBounds {\n\n\t/** The left edge of the axis aligned bounding box. */\n\tminX = 0;\n\n\t/** The bottom edge of the axis aligned bounding box. */\n\tminY = 0;\n\n\t/** The right edge of the axis aligned bounding box. */\n\tmaxX = 0;\n\n\t/** The top edge of the axis aligned bounding box. */\n\tmaxY = 0;\n\n\t/** The visible bounding boxes. */\n\tboundingBoxes = new Array();\n\n\t/** The world vertices for the bounding box polygons. */\n\tpolygons = new Array();\n\n\tprivate polygonPool = new Pool(() => {\n\t\treturn Utils.newFloatArray(16);\n\t});\n\n\t/** Clears any previous polygons, finds all visible bounding box attachments, and computes the world vertices for each bounding\n\t * box's polygon.\n\t * @param updateAabb If true, the axis aligned bounding box containing all the polygons is computed. If false, the\n\t * SkeletonBounds AABB methods will always return true. */\n\tupdate (skeleton: Skeleton, updateAabb: boolean) {\n\t\tif (!skeleton) throw new Error(\"skeleton cannot be null.\");\n\t\tlet boundingBoxes = this.boundingBoxes;\n\t\tlet polygons = this.polygons;\n\t\tlet polygonPool = this.polygonPool;\n\t\tlet slots = skeleton.slots;\n\t\tlet slotCount = slots.length;\n\n\t\tboundingBoxes.length = 0;\n\t\tpolygonPool.freeAll(polygons);\n\t\tpolygons.length = 0;\n\n\t\tfor (let i = 0; i < slotCount; i++) {\n\t\t\tlet slot = slots[i];\n\t\t\tif (!slot.bone.active) continue;\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tif (attachment instanceof BoundingBoxAttachment) {\n\t\t\t\tlet boundingBox = attachment as BoundingBoxAttachment;\n\t\t\t\tboundingBoxes.push(boundingBox);\n\n\t\t\t\tlet polygon = polygonPool.obtain();\n\t\t\t\tif (polygon.length != boundingBox.worldVerticesLength) {\n\t\t\t\t\tpolygon = Utils.newFloatArray(boundingBox.worldVerticesLength);\n\t\t\t\t}\n\t\t\t\tpolygons.push(polygon);\n\t\t\t\tboundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);\n\t\t\t}\n\t\t}\n\n\t\tif (updateAabb) {\n\t\t\tthis.aabbCompute();\n\t\t} else {\n\t\t\tthis.minX = Number.POSITIVE_INFINITY;\n\t\t\tthis.minY = Number.POSITIVE_INFINITY;\n\t\t\tthis.maxX = Number.NEGATIVE_INFINITY;\n\t\t\tthis.maxY = Number.NEGATIVE_INFINITY;\n\t\t}\n\t}\n\n\taabbCompute () {\n\t\tlet minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;\n\t\tlet polygons = this.polygons;\n\t\tfor (let i = 0, n = polygons.length; i < n; i++) {\n\t\t\tlet polygon = polygons[i];\n\t\t\tlet vertices = polygon;\n\t\t\tfor (let ii = 0, nn = polygon.length; ii < nn; ii += 2) {\n\t\t\t\tlet x = vertices[ii];\n\t\t\t\tlet y = vertices[ii + 1];\n\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t}\n\t\t}\n\t\tthis.minX = minX;\n\t\tthis.minY = minY;\n\t\tthis.maxX = maxX;\n\t\tthis.maxY = maxY;\n\t}\n\n\t/** Returns true if the axis aligned bounding box contains the point. */\n\taabbContainsPoint (x: number, y: number) {\n\t\treturn x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;\n\t}\n\n\t/** Returns true if the axis aligned bounding box intersects the line segment. */\n\taabbIntersectsSegment (x1: number, y1: number, x2: number, y2: number) {\n\t\tlet minX = this.minX;\n\t\tlet minY = this.minY;\n\t\tlet maxX = this.maxX;\n\t\tlet maxY = this.maxY;\n\t\tif ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))\n\t\t\treturn false;\n\t\tlet m = (y2 - y1) / (x2 - x1);\n\t\tlet y = m * (minX - x1) + y1;\n\t\tif (y > minY && y < maxY) return true;\n\t\ty = m * (maxX - x1) + y1;\n\t\tif (y > minY && y < maxY) return true;\n\t\tlet x = (minY - y1) / m + x1;\n\t\tif (x > minX && x < maxX) return true;\n\t\tx = (maxY - y1) / m + x1;\n\t\tif (x > minX && x < maxX) return true;\n\t\treturn false;\n\t}\n\n\t/** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */\n\taabbIntersectsSkeleton (bounds: SkeletonBounds) {\n\t\treturn this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;\n\t}\n\n\t/** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more\n\t * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */\n\tcontainsPoint (x: number, y: number): BoundingBoxAttachment | null {\n\t\tlet polygons = this.polygons;\n\t\tfor (let i = 0, n = polygons.length; i < n; i++)\n\t\t\tif (this.containsPointPolygon(polygons[i], x, y)) return this.boundingBoxes[i];\n\t\treturn null;\n\t}\n\n\t/** Returns true if the polygon contains the point. */\n\tcontainsPointPolygon (polygon: NumberArrayLike, x: number, y: number) {\n\t\tlet vertices = polygon;\n\t\tlet nn = polygon.length;\n\n\t\tlet prevIndex = nn - 2;\n\t\tlet inside = false;\n\t\tfor (let ii = 0; ii < nn; ii += 2) {\n\t\t\tlet vertexY = vertices[ii + 1];\n\t\t\tlet prevY = vertices[prevIndex + 1];\n\t\t\tif ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {\n\t\t\t\tlet vertexX = vertices[ii];\n\t\t\t\tif (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside;\n\t\t\t}\n\t\t\tprevIndex = ii;\n\t\t}\n\t\treturn inside;\n\t}\n\n\t/** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it\n\t * is usually more efficient to only call this method if {@link #aabbIntersectsSegment()} returns\n\t * true. */\n\tintersectsSegment (x1: number, y1: number, x2: number, y2: number) {\n\t\tlet polygons = this.polygons;\n\t\tfor (let i = 0, n = polygons.length; i < n; i++)\n\t\t\tif (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2)) return this.boundingBoxes[i];\n\t\treturn null;\n\t}\n\n\t/** Returns true if the polygon contains any part of the line segment. */\n\tintersectsSegmentPolygon (polygon: NumberArrayLike, x1: number, y1: number, x2: number, y2: number) {\n\t\tlet vertices = polygon;\n\t\tlet nn = polygon.length;\n\n\t\tlet width12 = x1 - x2, height12 = y1 - y2;\n\t\tlet det1 = x1 * y2 - y1 * x2;\n\t\tlet x3 = vertices[nn - 2], y3 = vertices[nn - 1];\n\t\tfor (let ii = 0; ii < nn; ii += 2) {\n\t\t\tlet x4 = vertices[ii], y4 = vertices[ii + 1];\n\t\t\tlet det2 = x3 * y4 - y3 * x4;\n\t\t\tlet width34 = x3 - x4, height34 = y3 - y4;\n\t\t\tlet det3 = width12 * height34 - height12 * width34;\n\t\t\tlet x = (det1 * width34 - width12 * det2) / det3;\n\t\t\tif (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {\n\t\t\t\tlet y = (det1 * height34 - height12 * det2) / det3;\n\t\t\t\tif (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true;\n\t\t\t}\n\t\t\tx3 = x4;\n\t\t\ty3 = y4;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/** Returns the polygon for the specified bounding box, or null. */\n\tgetPolygon (boundingBox: BoundingBoxAttachment) {\n\t\tif (!boundingBox) throw new Error(\"boundingBox cannot be null.\");\n\t\tlet index = this.boundingBoxes.indexOf(boundingBox);\n\t\treturn index == -1 ? null : this.polygons[index];\n\t}\n\n\t/** The width of the axis aligned bounding box. */\n\tgetWidth () {\n\t\treturn this.maxX - this.minX;\n\t}\n\n\t/** The height of the axis aligned bounding box. */\n\tgetHeight () {\n\t\treturn this.maxY - this.minY;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { NumberArrayLike, Pool } from \"./Utils.js\";\n\nexport class Triangulator {\n\tprivate convexPolygons = new Array>();\n\tprivate convexPolygonsIndices = new Array>();\n\n\tprivate indicesArray = new Array();\n\tprivate isConcaveArray = new Array();\n\tprivate triangles = new Array();\n\n\tprivate polygonPool = new Pool>(() => {\n\t\treturn new Array();\n\t});\n\n\tprivate polygonIndicesPool = new Pool>(() => {\n\t\treturn new Array();\n\t});\n\n\tpublic triangulate (verticesArray: NumberArrayLike): Array {\n\t\tlet vertices = verticesArray;\n\t\tlet vertexCount = verticesArray.length >> 1;\n\n\t\tlet indices = this.indicesArray;\n\t\tindices.length = 0;\n\t\tfor (let i = 0; i < vertexCount; i++)\n\t\t\tindices[i] = i;\n\n\t\tlet isConcave = this.isConcaveArray;\n\t\tisConcave.length = 0;\n\t\tfor (let i = 0, n = vertexCount; i < n; ++i)\n\t\t\tisConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices);\n\n\t\tlet triangles = this.triangles;\n\t\ttriangles.length = 0;\n\n\t\twhile (vertexCount > 3) {\n\t\t\t// Find ear tip.\n\t\t\tlet previous = vertexCount - 1, i = 0, next = 1;\n\t\t\twhile (true) {\n\t\t\t\touter:\n\t\t\t\tif (!isConcave[i]) {\n\t\t\t\t\tlet p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;\n\t\t\t\t\tlet p1x = vertices[p1], p1y = vertices[p1 + 1];\n\t\t\t\t\tlet p2x = vertices[p2], p2y = vertices[p2 + 1];\n\t\t\t\t\tlet p3x = vertices[p3], p3y = vertices[p3 + 1];\n\t\t\t\t\tfor (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {\n\t\t\t\t\t\tif (!isConcave[ii]) continue;\n\t\t\t\t\t\tlet v = indices[ii] << 1;\n\t\t\t\t\t\tlet vx = vertices[v], vy = vertices[v + 1];\n\t\t\t\t\t\tif (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {\n\t\t\t\t\t\t\tif (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {\n\t\t\t\t\t\t\t\tif (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) break outer;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (next == 0) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif (!isConcave[i]) break;\n\t\t\t\t\t\ti--;\n\t\t\t\t\t} while (i > 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tprevious = i;\n\t\t\t\ti = next;\n\t\t\t\tnext = (next + 1) % vertexCount;\n\t\t\t}\n\n\t\t\t// Cut ear tip.\n\t\t\ttriangles.push(indices[(vertexCount + i - 1) % vertexCount]);\n\t\t\ttriangles.push(indices[i]);\n\t\t\ttriangles.push(indices[(i + 1) % vertexCount]);\n\t\t\tindices.splice(i, 1);\n\t\t\tisConcave.splice(i, 1);\n\t\t\tvertexCount--;\n\n\t\t\tlet previousIndex = (vertexCount + i - 1) % vertexCount;\n\t\t\tlet nextIndex = i == vertexCount ? 0 : i;\n\t\t\tisConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices);\n\t\t\tisConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices);\n\t\t}\n\n\t\tif (vertexCount == 3) {\n\t\t\ttriangles.push(indices[2]);\n\t\t\ttriangles.push(indices[0]);\n\t\t\ttriangles.push(indices[1]);\n\t\t}\n\n\t\treturn triangles;\n\t}\n\n\tdecompose (verticesArray: Array, triangles: Array): Array> {\n\t\tlet vertices = verticesArray;\n\t\tlet convexPolygons = this.convexPolygons;\n\t\tthis.polygonPool.freeAll(convexPolygons);\n\t\tconvexPolygons.length = 0;\n\n\t\tlet convexPolygonsIndices = this.convexPolygonsIndices;\n\t\tthis.polygonIndicesPool.freeAll(convexPolygonsIndices);\n\t\tconvexPolygonsIndices.length = 0;\n\n\t\tlet polygonIndices = this.polygonIndicesPool.obtain();\n\t\tpolygonIndices.length = 0;\n\n\t\tlet polygon = this.polygonPool.obtain();\n\t\tpolygon.length = 0;\n\n\t\t// Merge subsequent triangles if they form a triangle fan.\n\t\tlet fanBaseIndex = -1, lastWinding = 0;\n\t\tfor (let i = 0, n = triangles.length; i < n; i += 3) {\n\t\t\tlet t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;\n\t\t\tlet x1 = vertices[t1], y1 = vertices[t1 + 1];\n\t\t\tlet x2 = vertices[t2], y2 = vertices[t2 + 1];\n\t\t\tlet x3 = vertices[t3], y3 = vertices[t3 + 1];\n\n\t\t\t// If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan).\n\t\t\tlet merged = false;\n\t\t\tif (fanBaseIndex == t1) {\n\t\t\t\tlet o = polygon.length - 4;\n\t\t\t\tlet winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);\n\t\t\t\tlet winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);\n\t\t\t\tif (winding1 == lastWinding && winding2 == lastWinding) {\n\t\t\t\t\tpolygon.push(x3);\n\t\t\t\t\tpolygon.push(y3);\n\t\t\t\t\tpolygonIndices.push(t3);\n\t\t\t\t\tmerged = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Otherwise make this triangle the new base.\n\t\t\tif (!merged) {\n\t\t\t\tif (polygon.length > 0) {\n\t\t\t\t\tconvexPolygons.push(polygon);\n\t\t\t\t\tconvexPolygonsIndices.push(polygonIndices);\n\t\t\t\t} else {\n\t\t\t\t\tthis.polygonPool.free(polygon)\n\t\t\t\t\tthis.polygonIndicesPool.free(polygonIndices);\n\t\t\t\t}\n\t\t\t\tpolygon = this.polygonPool.obtain();\n\t\t\t\tpolygon.length = 0;\n\t\t\t\tpolygon.push(x1);\n\t\t\t\tpolygon.push(y1);\n\t\t\t\tpolygon.push(x2);\n\t\t\t\tpolygon.push(y2);\n\t\t\t\tpolygon.push(x3);\n\t\t\t\tpolygon.push(y3);\n\t\t\t\tpolygonIndices = this.polygonIndicesPool.obtain();\n\t\t\t\tpolygonIndices.length = 0;\n\t\t\t\tpolygonIndices.push(t1);\n\t\t\t\tpolygonIndices.push(t2);\n\t\t\t\tpolygonIndices.push(t3);\n\t\t\t\tlastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3);\n\t\t\t\tfanBaseIndex = t1;\n\t\t\t}\n\t\t}\n\n\t\tif (polygon.length > 0) {\n\t\t\tconvexPolygons.push(polygon);\n\t\t\tconvexPolygonsIndices.push(polygonIndices);\n\t\t}\n\n\t\t// Go through the list of polygons and try to merge the remaining triangles with the found triangle fans.\n\t\tfor (let i = 0, n = convexPolygons.length; i < n; i++) {\n\t\t\tpolygonIndices = convexPolygonsIndices[i];\n\t\t\tif (polygonIndices.length == 0) continue;\n\t\t\tlet firstIndex = polygonIndices[0];\n\t\t\tlet lastIndex = polygonIndices[polygonIndices.length - 1];\n\n\t\t\tpolygon = convexPolygons[i];\n\t\t\tlet o = polygon.length - 4;\n\t\t\tlet prevPrevX = polygon[o], prevPrevY = polygon[o + 1];\n\t\t\tlet prevX = polygon[o + 2], prevY = polygon[o + 3];\n\t\t\tlet firstX = polygon[0], firstY = polygon[1];\n\t\t\tlet secondX = polygon[2], secondY = polygon[3];\n\t\t\tlet winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);\n\n\t\t\tfor (let ii = 0; ii < n; ii++) {\n\t\t\t\tif (ii == i) continue;\n\t\t\t\tlet otherIndices = convexPolygonsIndices[ii];\n\t\t\t\tif (otherIndices.length != 3) continue;\n\t\t\t\tlet otherFirstIndex = otherIndices[0];\n\t\t\t\tlet otherSecondIndex = otherIndices[1];\n\t\t\t\tlet otherLastIndex = otherIndices[2];\n\n\t\t\t\tlet otherPoly = convexPolygons[ii];\n\t\t\t\tlet x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];\n\n\t\t\t\tif (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;\n\t\t\t\tlet winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);\n\t\t\t\tlet winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY);\n\t\t\t\tif (winding1 == winding && winding2 == winding) {\n\t\t\t\t\totherPoly.length = 0;\n\t\t\t\t\totherIndices.length = 0;\n\t\t\t\t\tpolygon.push(x3);\n\t\t\t\t\tpolygon.push(y3);\n\t\t\t\t\tpolygonIndices.push(otherLastIndex);\n\t\t\t\t\tprevPrevX = prevX;\n\t\t\t\t\tprevPrevY = prevY;\n\t\t\t\t\tprevX = x3;\n\t\t\t\t\tprevY = y3;\n\t\t\t\t\tii = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove empty polygons that resulted from the merge step above.\n\t\tfor (let i = convexPolygons.length - 1; i >= 0; i--) {\n\t\t\tpolygon = convexPolygons[i];\n\t\t\tif (polygon.length == 0) {\n\t\t\t\tconvexPolygons.splice(i, 1);\n\t\t\t\tthis.polygonPool.free(polygon);\n\t\t\t\tpolygonIndices = convexPolygonsIndices[i]\n\t\t\t\tconvexPolygonsIndices.splice(i, 1)\n\t\t\t\tthis.polygonIndicesPool.free(polygonIndices);\n\t\t\t}\n\t\t}\n\n\t\treturn convexPolygons;\n\t}\n\n\tprivate static isConcave (index: number, vertexCount: number, vertices: NumberArrayLike, indices: NumberArrayLike): boolean {\n\t\tlet previous = indices[(vertexCount + index - 1) % vertexCount] << 1;\n\t\tlet current = indices[index] << 1;\n\t\tlet next = indices[(index + 1) % vertexCount] << 1;\n\t\treturn !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next],\n\t\t\tvertices[next + 1]);\n\t}\n\n\tprivate static positiveArea (p1x: number, p1y: number, p2x: number, p2y: number, p3x: number, p3y: number): boolean {\n\t\treturn p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;\n\t}\n\n\tprivate static winding (p1x: number, p1y: number, p2x: number, p2y: number, p3x: number, p3y: number): number {\n\t\tlet px = p2x - p1x, py = p2y - p1y;\n\t\treturn p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { ClippingAttachment } from \"./attachments/ClippingAttachment.js\";\nimport { Slot } from \"./Slot.js\";\nimport { Triangulator } from \"./Triangulator.js\";\nimport { Utils, Color, NumberArrayLike } from \"./Utils.js\";\n\nexport class SkeletonClipping {\n\tprivate triangulator = new Triangulator();\n\tprivate clippingPolygon = new Array();\n\tprivate clipOutput = new Array();\n\tclippedVertices = new Array();\n\tclippedUVs = new Array();\n\tclippedTriangles = new Array();\n\tprivate scratch = new Array();\n\n\tprivate clipAttachment: ClippingAttachment | null = null;\n\tprivate clippingPolygons: Array> | null = null;\n\n\tclipStart (slot: Slot, clip: ClippingAttachment): number {\n\t\tif (this.clipAttachment) return 0;\n\t\tthis.clipAttachment = clip;\n\n\t\tlet n = clip.worldVerticesLength;\n\t\tlet vertices = Utils.setArraySize(this.clippingPolygon, n);\n\t\tclip.computeWorldVertices(slot, 0, n, vertices, 0, 2);\n\t\tlet clippingPolygon = this.clippingPolygon;\n\t\tSkeletonClipping.makeClockwise(clippingPolygon);\n\t\tlet clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));\n\t\tfor (let i = 0, n = clippingPolygons.length; i < n; i++) {\n\t\t\tlet polygon = clippingPolygons[i];\n\t\t\tSkeletonClipping.makeClockwise(polygon);\n\t\t\tpolygon.push(polygon[0]);\n\t\t\tpolygon.push(polygon[1]);\n\t\t}\n\n\t\treturn clippingPolygons.length;\n\t}\n\n\tclipEndWithSlot (slot: Slot) {\n\t\tif (this.clipAttachment && this.clipAttachment.endSlot == slot.data) this.clipEnd();\n\t}\n\n\tclipEnd () {\n\t\tif (!this.clipAttachment) return;\n\t\tthis.clipAttachment = null;\n\t\tthis.clippingPolygons = null;\n\t\tthis.clippedVertices.length = 0;\n\t\tthis.clippedTriangles.length = 0;\n\t\tthis.clippingPolygon.length = 0;\n\t}\n\n\tisClipping (): boolean {\n\t\treturn this.clipAttachment != null;\n\t}\n\n\t/**\n\t* @deprecated Use clipTriangles without verticesLength parameter. Mark for removal in 4.3.\n\t*/\n\tclipTriangles (vertices: NumberArrayLike, verticesLength: number, triangles: NumberArrayLike, trianglesLength: number): void;\n\n\t/**\n\t * @deprecated Use clipTriangles without verticesLength parameter. Mark for removal in 4.3.\n\t */\n\tclipTriangles (vertices: NumberArrayLike, verticesLength: number, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean): void;\n\n\tclipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number): void;\n\tclipTriangles (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike, light: Color, dark: Color, twoColor: boolean): void;\n\tclipTriangles (\n\t\tvertices: NumberArrayLike,\n\t\tverticesLengthOrTriangles: number | NumberArrayLike,\n\t\ttrianglesOrTrianglesLength: NumberArrayLike | number,\n\t\ttrianglesLengthOrUvs?: number | NumberArrayLike,\n\t\tuvsOrLight?: NumberArrayLike | Color,\n\t\tlightOrDark?: Color,\n\t\tdarkOrTwoColor?: Color | boolean,\n\t\ttwoColorParam?: boolean\n\t): void {\n\t\t// Determine which overload is being used\n\t\tlet triangles: NumberArrayLike;\n\t\tlet trianglesLength: number;\n\t\tlet uvs: NumberArrayLike | undefined;\n\t\tlet light: Color | undefined;\n\t\tlet dark: Color | undefined;\n\t\tlet twoColor: boolean | undefined;\n\n\t\tif (typeof verticesLengthOrTriangles === 'number') {\n\t\t\ttriangles = trianglesOrTrianglesLength as NumberArrayLike;\n\t\t\ttrianglesLength = trianglesLengthOrUvs as number;\n\t\t\tuvs = uvsOrLight as NumberArrayLike;\n\t\t\tlight = lightOrDark as Color | undefined;\n\t\t\tdark = darkOrTwoColor as Color | undefined;\n\t\t\ttwoColor = twoColorParam;\n\t\t} else {\n\t\t\ttriangles = verticesLengthOrTriangles;\n\t\t\ttrianglesLength = trianglesOrTrianglesLength as number;\n\t\t\tuvs = trianglesLengthOrUvs as NumberArrayLike;\n\t\t\tlight = uvsOrLight as Color | undefined;\n\t\t\tdark = lightOrDark as Color | undefined;\n\t\t\ttwoColor = darkOrTwoColor as boolean;\n\t\t}\n\n\t\tif (uvs && light && dark && typeof twoColor === 'boolean')\n\t\t\tthis.clipTrianglesRender(vertices, triangles, trianglesLength, uvs, light, dark, twoColor);\n\t\telse\n\t\t\tthis.clipTrianglesNoRender(vertices, triangles, trianglesLength);\n\t}\n\n\tprivate clipTrianglesNoRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number) {\n\n\t\tlet clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;\n\t\tlet clippedTriangles = this.clippedTriangles;\n\t\tlet polygons = this.clippingPolygons!;\n\t\tlet polygonsCount = polygons.length;\n\n\t\tlet index = 0;\n\t\tclippedVertices.length = 0;\n\t\tclippedTriangles.length = 0;\n\t\tfor (let i = 0; i < trianglesLength; i += 3) {\n\t\t\tlet vertexOffset = triangles[i] << 1;\n\t\t\tlet x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 1] << 1;\n\t\t\tlet x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 2] << 1;\n\t\t\tlet x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];\n\n\t\t\tfor (let p = 0; p < polygonsCount; p++) {\n\t\t\t\tlet s = clippedVertices.length;\n\t\t\t\tif (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {\n\t\t\t\t\tlet clipOutputLength = clipOutput.length;\n\t\t\t\t\tif (clipOutputLength == 0) continue;\n\n\t\t\t\t\tlet clipOutputCount = clipOutputLength >> 1;\n\t\t\t\t\tlet clipOutputItems = this.clipOutput;\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2);\n\t\t\t\t\tfor (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) {\n\t\t\t\t\t\tlet x = clipOutputItems[ii], y = clipOutputItems[ii + 1];\n\t\t\t\t\t\tclippedVerticesItems[s] = x;\n\t\t\t\t\t\tclippedVerticesItems[s + 1] = y;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));\n\t\t\t\t\tclipOutputCount--;\n\t\t\t\t\tfor (let ii = 1; ii < clipOutputCount; ii++, s += 3) {\n\t\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + ii);\n\t\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + ii + 1);\n\t\t\t\t\t}\n\t\t\t\t\tindex += clipOutputCount + 1;\n\n\t\t\t\t} else {\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2);\n\t\t\t\t\tclippedVerticesItems[s] = x1;\n\t\t\t\t\tclippedVerticesItems[s + 1] = y1;\n\n\t\t\t\t\tclippedVerticesItems[s + 2] = x2;\n\t\t\t\t\tclippedVerticesItems[s + 3] = y2;\n\n\t\t\t\t\tclippedVerticesItems[s + 4] = x3;\n\t\t\t\t\tclippedVerticesItems[s + 5] = y3;\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);\n\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + 1);\n\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + 2);\n\t\t\t\t\tindex += 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate clipTrianglesRender (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike,\n\t\tlight: Color, dark: Color, twoColor: boolean) {\n\n\t\tlet clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;\n\t\tlet clippedTriangles = this.clippedTriangles;\n\t\tlet polygons = this.clippingPolygons!;\n\t\tlet polygonsCount = polygons.length;\n\t\tlet vertexSize = twoColor ? 12 : 8;\n\n\t\tlet index = 0;\n\t\tclippedVertices.length = 0;\n\t\tclippedTriangles.length = 0;\n\t\tfor (let i = 0; i < trianglesLength; i += 3) {\n\t\t\tlet vertexOffset = triangles[i] << 1;\n\t\t\tlet x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];\n\t\t\tlet u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 1] << 1;\n\t\t\tlet x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];\n\t\t\tlet u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 2] << 1;\n\t\t\tlet x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];\n\t\t\tlet u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];\n\n\t\t\tfor (let p = 0; p < polygonsCount; p++) {\n\t\t\t\tlet s = clippedVertices.length;\n\t\t\t\tif (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {\n\t\t\t\t\tlet clipOutputLength = clipOutput.length;\n\t\t\t\t\tif (clipOutputLength == 0) continue;\n\t\t\t\t\tlet d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;\n\t\t\t\t\tlet d = 1 / (d0 * d2 + d1 * (y1 - y3));\n\n\t\t\t\t\tlet clipOutputCount = clipOutputLength >> 1;\n\t\t\t\t\tlet clipOutputItems = this.clipOutput;\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);\n\t\t\t\t\tfor (let ii = 0; ii < clipOutputLength; ii += 2, s += vertexSize) {\n\t\t\t\t\t\tlet x = clipOutputItems[ii], y = clipOutputItems[ii + 1];\n\t\t\t\t\t\tclippedVerticesItems[s] = x;\n\t\t\t\t\t\tclippedVerticesItems[s + 1] = y;\n\t\t\t\t\t\tclippedVerticesItems[s + 2] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 3] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 4] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 5] = light.a;\n\t\t\t\t\t\tlet c0 = x - x3, c1 = y - y3;\n\t\t\t\t\t\tlet a = (d0 * c0 + d1 * c1) * d;\n\t\t\t\t\t\tlet b = (d4 * c0 + d2 * c1) * d;\n\t\t\t\t\t\tlet c = 1 - a - b;\n\t\t\t\t\t\tclippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;\n\t\t\t\t\t\tclippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;\n\t\t\t\t\t\tif (twoColor) {\n\t\t\t\t\t\t\tclippedVerticesItems[s + 8] = dark.r;\n\t\t\t\t\t\t\tclippedVerticesItems[s + 9] = dark.g;\n\t\t\t\t\t\t\tclippedVerticesItems[s + 10] = dark.b;\n\t\t\t\t\t\t\tclippedVerticesItems[s + 11] = dark.a;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));\n\t\t\t\t\tclipOutputCount--;\n\t\t\t\t\tfor (let ii = 1; ii < clipOutputCount; ii++, s += 3) {\n\t\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + ii);\n\t\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + ii + 1);\n\t\t\t\t\t}\n\t\t\t\t\tindex += clipOutputCount + 1;\n\n\t\t\t\t} else {\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize);\n\t\t\t\t\tclippedVerticesItems[s] = x1;\n\t\t\t\t\tclippedVerticesItems[s + 1] = y1;\n\t\t\t\t\tclippedVerticesItems[s + 2] = light.r;\n\t\t\t\t\tclippedVerticesItems[s + 3] = light.g;\n\t\t\t\t\tclippedVerticesItems[s + 4] = light.b;\n\t\t\t\t\tclippedVerticesItems[s + 5] = light.a;\n\t\t\t\t\tif (!twoColor) {\n\t\t\t\t\t\tclippedVerticesItems[s + 6] = u1;\n\t\t\t\t\t\tclippedVerticesItems[s + 7] = v1;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 8] = x2;\n\t\t\t\t\t\tclippedVerticesItems[s + 9] = y2;\n\t\t\t\t\t\tclippedVerticesItems[s + 10] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 11] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 12] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 13] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 14] = u2;\n\t\t\t\t\t\tclippedVerticesItems[s + 15] = v2;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 16] = x3;\n\t\t\t\t\t\tclippedVerticesItems[s + 17] = y3;\n\t\t\t\t\t\tclippedVerticesItems[s + 18] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 19] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 20] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 21] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 22] = u3;\n\t\t\t\t\t\tclippedVerticesItems[s + 23] = v3;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclippedVerticesItems[s + 6] = u1;\n\t\t\t\t\t\tclippedVerticesItems[s + 7] = v1;\n\t\t\t\t\t\tclippedVerticesItems[s + 8] = dark.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 9] = dark.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 10] = dark.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 11] = dark.a;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 12] = x2;\n\t\t\t\t\t\tclippedVerticesItems[s + 13] = y2;\n\t\t\t\t\t\tclippedVerticesItems[s + 14] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 15] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 16] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 17] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 18] = u2;\n\t\t\t\t\t\tclippedVerticesItems[s + 19] = v2;\n\t\t\t\t\t\tclippedVerticesItems[s + 20] = dark.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 21] = dark.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 22] = dark.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 23] = dark.a;\n\n\t\t\t\t\t\tclippedVerticesItems[s + 24] = x3;\n\t\t\t\t\t\tclippedVerticesItems[s + 25] = y3;\n\t\t\t\t\t\tclippedVerticesItems[s + 26] = light.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 27] = light.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 28] = light.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 29] = light.a;\n\t\t\t\t\t\tclippedVerticesItems[s + 30] = u3;\n\t\t\t\t\t\tclippedVerticesItems[s + 31] = v3;\n\t\t\t\t\t\tclippedVerticesItems[s + 32] = dark.r;\n\t\t\t\t\t\tclippedVerticesItems[s + 33] = dark.g;\n\t\t\t\t\t\tclippedVerticesItems[s + 34] = dark.b;\n\t\t\t\t\t\tclippedVerticesItems[s + 35] = dark.a;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);\n\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + 1);\n\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + 2);\n\t\t\t\t\tindex += 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic clipTrianglesUnpacked (vertices: NumberArrayLike, triangles: NumberArrayLike, trianglesLength: number, uvs: NumberArrayLike) {\n\t\tlet clipOutput = this.clipOutput, clippedVertices = this.clippedVertices, clippedUVs = this.clippedUVs;\n\t\tlet clippedTriangles = this.clippedTriangles;\n\t\tlet polygons = this.clippingPolygons!;\n\t\tlet polygonsCount = polygons.length;\n\n\t\tlet index = 0;\n\t\tclippedVertices.length = 0;\n\t\tclippedUVs.length = 0;\n\t\tclippedTriangles.length = 0;\n\t\tfor (let i = 0; i < trianglesLength; i += 3) {\n\t\t\tlet vertexOffset = triangles[i] << 1;\n\t\t\tlet x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];\n\t\t\tlet u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 1] << 1;\n\t\t\tlet x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];\n\t\t\tlet u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];\n\n\t\t\tvertexOffset = triangles[i + 2] << 1;\n\t\t\tlet x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];\n\t\t\tlet u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];\n\n\t\t\tfor (let p = 0; p < polygonsCount; p++) {\n\t\t\t\tlet s = clippedVertices.length;\n\t\t\t\tif (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {\n\t\t\t\t\tlet clipOutputLength = clipOutput.length;\n\t\t\t\t\tif (clipOutputLength == 0) continue;\n\t\t\t\t\tlet d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;\n\t\t\t\t\tlet d = 1 / (d0 * d2 + d1 * (y1 - y3));\n\n\t\t\t\t\tlet clipOutputCount = clipOutputLength >> 1;\n\t\t\t\t\tlet clipOutputItems = this.clipOutput;\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * 2);\n\t\t\t\t\tlet clippedUVsItems = Utils.setArraySize(clippedUVs, s + clipOutputCount * 2);\n\t\t\t\t\tfor (let ii = 0; ii < clipOutputLength; ii += 2, s += 2) {\n\t\t\t\t\t\tlet x = clipOutputItems[ii], y = clipOutputItems[ii + 1];\n\t\t\t\t\t\tclippedVerticesItems[s] = x;\n\t\t\t\t\t\tclippedVerticesItems[s + 1] = y;\n\t\t\t\t\t\tlet c0 = x - x3, c1 = y - y3;\n\t\t\t\t\t\tlet a = (d0 * c0 + d1 * c1) * d;\n\t\t\t\t\t\tlet b = (d4 * c0 + d2 * c1) * d;\n\t\t\t\t\t\tlet c = 1 - a - b;\n\t\t\t\t\t\tclippedUVsItems[s] = u1 * a + u2 * b + u3 * c;\n\t\t\t\t\t\tclippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c;\n\t\t\t\t\t}\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));\n\t\t\t\t\tclipOutputCount--;\n\t\t\t\t\tfor (let ii = 1; ii < clipOutputCount; ii++, s += 3) {\n\t\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + ii);\n\t\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + ii + 1);\n\t\t\t\t\t}\n\t\t\t\t\tindex += clipOutputCount + 1;\n\n\t\t\t\t} else {\n\t\t\t\t\tlet clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * 2);\n\t\t\t\t\tclippedVerticesItems[s] = x1;\n\t\t\t\t\tclippedVerticesItems[s + 1] = y1;\n\t\t\t\t\tclippedVerticesItems[s + 2] = x2;\n\t\t\t\t\tclippedVerticesItems[s + 3] = y2;\n\t\t\t\t\tclippedVerticesItems[s + 4] = x3;\n\t\t\t\t\tclippedVerticesItems[s + 5] = y3;\n\n\t\t\t\t\tlet clippedUVSItems = Utils.setArraySize(clippedUVs, s + 3 * 2);\n\t\t\t\t\tclippedUVSItems[s] = u1;\n\t\t\t\t\tclippedUVSItems[s + 1] = v1;\n\t\t\t\t\tclippedUVSItems[s + 2] = u2;\n\t\t\t\t\tclippedUVSItems[s + 3] = v2;\n\t\t\t\t\tclippedUVSItems[s + 4] = u3;\n\t\t\t\t\tclippedUVSItems[s + 5] = v3;\n\n\t\t\t\t\ts = clippedTriangles.length;\n\t\t\t\t\tlet clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);\n\t\t\t\t\tclippedTrianglesItems[s] = index;\n\t\t\t\t\tclippedTrianglesItems[s + 1] = (index + 1);\n\t\t\t\t\tclippedTrianglesItems[s + 2] = (index + 2);\n\t\t\t\t\tindex += 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping\n\t * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */\n\tclip (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array, output: Array) {\n\t\tlet originalOutput = output;\n\t\tlet clipped = false;\n\n\t\t// Avoid copy at the end.\n\t\tlet input: Array;\n\t\tif (clippingArea.length % 4 >= 2) {\n\t\t\tinput = output;\n\t\t\toutput = this.scratch;\n\t\t} else\n\t\t\tinput = this.scratch;\n\n\t\tinput.length = 0;\n\t\tinput.push(x1);\n\t\tinput.push(y1);\n\t\tinput.push(x2);\n\t\tinput.push(y2);\n\t\tinput.push(x3);\n\t\tinput.push(y3);\n\t\tinput.push(x1);\n\t\tinput.push(y1);\n\t\toutput.length = 0;\n\n\t\tlet clippingVerticesLast = clippingArea.length - 4;\n\t\tlet clippingVertices = clippingArea;\n\t\tfor (let i = 0; ; i += 2) {\n\t\t\tlet edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];\n\t\t\tlet ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3];\n\n\t\t\tlet outputStart = output.length;\n\t\t\tlet inputVertices = input;\n\t\t\tfor (let ii = 0, nn = input.length - 2; ii < nn;) {\n\t\t\t\tlet inputX = inputVertices[ii], inputY = inputVertices[ii + 1];\n\t\t\t\tii += 2;\n\t\t\t\tlet inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1];\n\t\t\t\tlet s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2);\n\t\t\t\tlet s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY);\n\t\t\t\tif (s1 > 0) {\n\t\t\t\t\tif (s2) { // v1 inside, v2 inside\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// v1 inside, v2 outside\n\t\t\t\t\tlet ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex);\n\t\t\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\t\t\toutput.push(inputX + ix * t);\n\t\t\t\t\t\toutput.push(inputY + iy * t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} else if (s2) { // v1 outside, v2 inside\n\t\t\t\t\tlet ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex);\n\t\t\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\t\t\toutput.push(inputX + ix * t);\n\t\t\t\t\t\toutput.push(inputY + iy * t);\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput.push(inputX2);\n\t\t\t\t\t\toutput.push(inputY2);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclipped = true;\n\t\t\t}\n\n\t\t\tif (outputStart == output.length) { // All edges outside.\n\t\t\t\toriginalOutput.length = 0;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\toutput.push(output[0]);\n\t\t\toutput.push(output[1]);\n\n\t\t\tif (i == clippingVerticesLast) break;\n\t\t\tlet temp = output;\n\t\t\toutput = input;\n\t\t\toutput.length = 0;\n\t\t\tinput = temp;\n\t\t}\n\n\t\tif (originalOutput != output) {\n\t\t\toriginalOutput.length = 0;\n\t\t\tfor (let i = 0, n = output.length - 2; i < n; i++)\n\t\t\t\toriginalOutput[i] = output[i];\n\t\t} else\n\t\t\toriginalOutput.length = originalOutput.length - 2;\n\n\t\treturn clipped;\n\t}\n\n\tpublic static makeClockwise (polygon: NumberArrayLike) {\n\t\tlet vertices = polygon;\n\t\tlet verticeslength = polygon.length;\n\n\t\tlet area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;\n\t\tfor (let i = 0, n = verticeslength - 3; i < n; i += 2) {\n\t\t\tp1x = vertices[i];\n\t\t\tp1y = vertices[i + 1];\n\t\t\tp2x = vertices[i + 2];\n\t\t\tp2y = vertices[i + 3];\n\t\t\tarea += p1x * p2y - p2x * p1y;\n\t\t}\n\t\tif (area < 0) return;\n\n\t\tfor (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {\n\t\t\tlet x = vertices[i], y = vertices[i + 1];\n\t\t\tlet other = lastX - i;\n\t\t\tvertices[i] = vertices[other];\n\t\t\tvertices[i + 1] = vertices[other + 1];\n\t\t\tvertices[other] = x;\n\t\t\tvertices[other + 1] = y;\n\t\t}\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Animation, Timeline, InheritTimeline, AttachmentTimeline, RGBATimeline, RGBTimeline, AlphaTimeline, RGBA2Timeline, RGB2Timeline, RotateTimeline, TranslateTimeline, TranslateXTimeline, TranslateYTimeline, ScaleTimeline, ScaleXTimeline, ScaleYTimeline, ShearTimeline, ShearXTimeline, ShearYTimeline, IkConstraintTimeline, TransformConstraintTimeline, PathConstraintPositionTimeline, PathConstraintSpacingTimeline, PathConstraintMixTimeline, DeformTimeline, DrawOrderTimeline, EventTimeline, CurveTimeline1, CurveTimeline2, CurveTimeline, PhysicsConstraintResetTimeline, PhysicsConstraintInertiaTimeline, PhysicsConstraintStrengthTimeline, PhysicsConstraintDampingTimeline, PhysicsConstraintMassTimeline, PhysicsConstraintWindTimeline, PhysicsConstraintGravityTimeline, PhysicsConstraintMixTimeline } from \"./Animation.js\";\nimport { VertexAttachment, Attachment } from \"./attachments/Attachment.js\";\nimport { AttachmentLoader } from \"./attachments/AttachmentLoader.js\";\nimport { MeshAttachment } from \"./attachments/MeshAttachment.js\";\nimport { BoneData, Inherit } from \"./BoneData.js\";\nimport { EventData } from \"./EventData.js\";\nimport { Event } from \"./Event.js\";\nimport { IkConstraintData } from \"./IkConstraintData.js\";\nimport { PathConstraintData, PositionMode, SpacingMode, RotateMode } from \"./PathConstraintData.js\";\nimport { SkeletonData } from \"./SkeletonData.js\";\nimport { Skin } from \"./Skin.js\";\nimport { SlotData, BlendMode } from \"./SlotData.js\";\nimport { TransformConstraintData } from \"./TransformConstraintData.js\";\nimport { Utils, Color, NumberArrayLike } from \"./Utils.js\";\nimport { Sequence, SequenceMode } from \"./attachments/Sequence.js\";\nimport { SequenceTimeline } from \"./Animation.js\";\nimport { HasTextureRegion } from \"./attachments/HasTextureRegion.js\";\nimport { PhysicsConstraintData } from \"./PhysicsConstraintData.js\";\n\n/** Loads skeleton data in the Spine JSON format.\n *\n * See [Spine JSON format](http://esotericsoftware.com/spine-json-format) and\n * [JSON and binary data](http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data) in the Spine\n * Runtimes Guide. */\nexport class SkeletonJson {\n\tattachmentLoader: AttachmentLoader;\n\n\t/** Scales bone positions, image sizes, and translations as they are loaded. This allows different size images to be used at\n\t * runtime than were used in Spine.\n\t *\n\t * See [Scaling](http://esotericsoftware.com/spine-loading-skeleton-data#Scaling) in the Spine Runtimes Guide. */\n\tscale = 1;\n\tprivate linkedMeshes = new Array();\n\n\tconstructor (attachmentLoader: AttachmentLoader) {\n\t\tthis.attachmentLoader = attachmentLoader;\n\t}\n\n\treadSkeletonData (json: string | any): SkeletonData {\n\t\tlet scale = this.scale;\n\t\tlet skeletonData = new SkeletonData();\n\t\tlet root = typeof (json) === \"string\" ? JSON.parse(json) : json;\n\n\t\t// Skeleton\n\t\tlet skeletonMap = root.skeleton;\n\t\tif (skeletonMap) {\n\t\t\tskeletonData.hash = skeletonMap.hash;\n\t\t\tskeletonData.version = skeletonMap.spine;\n\t\t\tskeletonData.x = skeletonMap.x;\n\t\t\tskeletonData.y = skeletonMap.y;\n\t\t\tskeletonData.width = skeletonMap.width;\n\t\t\tskeletonData.height = skeletonMap.height;\n\t\t\tskeletonData.referenceScale = getValue(skeletonMap, \"referenceScale\", 100) * scale;\n\t\t\tskeletonData.fps = skeletonMap.fps;\n\t\t\tskeletonData.imagesPath = skeletonMap.images ?? null;\n\t\t\tskeletonData.audioPath = skeletonMap.audio ?? null;\n\t\t}\n\n\t\t// Bones\n\t\tif (root.bones) {\n\t\t\tfor (let i = 0; i < root.bones.length; i++) {\n\t\t\t\tlet boneMap = root.bones[i];\n\n\t\t\t\tlet parent: BoneData | null = null;\n\t\t\t\tlet parentName: string = getValue(boneMap, \"parent\", null);\n\t\t\t\tif (parentName) parent = skeletonData.findBone(parentName);\n\t\t\t\tlet data = new BoneData(skeletonData.bones.length, boneMap.name, parent);\n\t\t\t\tdata.length = getValue(boneMap, \"length\", 0) * scale;\n\t\t\t\tdata.x = getValue(boneMap, \"x\", 0) * scale;\n\t\t\t\tdata.y = getValue(boneMap, \"y\", 0) * scale;\n\t\t\t\tdata.rotation = getValue(boneMap, \"rotation\", 0);\n\t\t\t\tdata.scaleX = getValue(boneMap, \"scaleX\", 1);\n\t\t\t\tdata.scaleY = getValue(boneMap, \"scaleY\", 1);\n\t\t\t\tdata.shearX = getValue(boneMap, \"shearX\", 0);\n\t\t\t\tdata.shearY = getValue(boneMap, \"shearY\", 0);\n\t\t\t\tdata.inherit = Utils.enumValue(Inherit, getValue(boneMap, \"inherit\", \"Normal\"));\n\t\t\t\tdata.skinRequired = getValue(boneMap, \"skin\", false);\n\n\t\t\t\tlet color = getValue(boneMap, \"color\", null);\n\t\t\t\tif (color) data.color.setFromString(color);\n\n\t\t\t\tskeletonData.bones.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Slots.\n\t\tif (root.slots) {\n\t\t\tfor (let i = 0; i < root.slots.length; i++) {\n\t\t\t\tlet slotMap = root.slots[i];\n\t\t\t\tlet slotName = slotMap.name;\n\n\t\t\t\tlet boneData = skeletonData.findBone(slotMap.bone);\n\t\t\t\tif (!boneData) throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotName}`);\n\t\t\t\tlet data = new SlotData(skeletonData.slots.length, slotName, boneData);\n\n\t\t\t\tlet color: string = getValue(slotMap, \"color\", null);\n\t\t\t\tif (color) data.color.setFromString(color);\n\n\t\t\t\tlet dark: string = getValue(slotMap, \"dark\", null);\n\t\t\t\tif (dark) data.darkColor = Color.fromString(dark);\n\n\t\t\t\tdata.attachmentName = getValue(slotMap, \"attachment\", null);\n\t\t\t\tdata.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, \"blend\", \"normal\"));\n\t\t\t\tdata.visible = getValue(slotMap, \"visible\", true);\n\t\t\t\tskeletonData.slots.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// IK constraints\n\t\tif (root.ik) {\n\t\t\tfor (let i = 0; i < root.ik.length; i++) {\n\t\t\t\tlet constraintMap = root.ik[i];\n\t\t\t\tlet data = new IkConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tfor (let ii = 0; ii < constraintMap.bones.length; ii++) {\n\t\t\t\t\tlet bone = skeletonData.findBone(constraintMap.bones[ii]);\n\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`);\n\t\t\t\t\tdata.bones.push(bone);\n\t\t\t\t}\n\n\t\t\t\tlet target = skeletonData.findBone(constraintMap.target);;\n\t\t\t\tif (!target) throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`);\n\t\t\t\tdata.target = target;\n\n\t\t\t\tdata.mix = getValue(constraintMap, \"mix\", 1);\n\t\t\t\tdata.softness = getValue(constraintMap, \"softness\", 0) * scale;\n\t\t\t\tdata.bendDirection = getValue(constraintMap, \"bendPositive\", true) ? 1 : -1;\n\t\t\t\tdata.compress = getValue(constraintMap, \"compress\", false);\n\t\t\t\tdata.stretch = getValue(constraintMap, \"stretch\", false);\n\t\t\t\tdata.uniform = getValue(constraintMap, \"uniform\", false);\n\n\t\t\t\tskeletonData.ikConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Transform constraints.\n\t\tif (root.transform) {\n\t\t\tfor (let i = 0; i < root.transform.length; i++) {\n\t\t\t\tlet constraintMap = root.transform[i];\n\t\t\t\tlet data = new TransformConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tfor (let ii = 0; ii < constraintMap.bones.length; ii++) {\n\t\t\t\t\tlet boneName = constraintMap.bones[ii];\n\t\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`);\n\t\t\t\t\tdata.bones.push(bone);\n\t\t\t\t}\n\n\t\t\t\tlet targetName: string = constraintMap.target;\n\t\t\t\tlet target = skeletonData.findBone(targetName);\n\t\t\t\tif (!target) throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`);\n\t\t\t\tdata.target = target;\n\n\t\t\t\tdata.local = getValue(constraintMap, \"local\", false);\n\t\t\t\tdata.relative = getValue(constraintMap, \"relative\", false);\n\t\t\t\tdata.offsetRotation = getValue(constraintMap, \"rotation\", 0);\n\t\t\t\tdata.offsetX = getValue(constraintMap, \"x\", 0) * scale;\n\t\t\t\tdata.offsetY = getValue(constraintMap, \"y\", 0) * scale;\n\t\t\t\tdata.offsetScaleX = getValue(constraintMap, \"scaleX\", 0);\n\t\t\t\tdata.offsetScaleY = getValue(constraintMap, \"scaleY\", 0);\n\t\t\t\tdata.offsetShearY = getValue(constraintMap, \"shearY\", 0);\n\n\t\t\t\tdata.mixRotate = getValue(constraintMap, \"mixRotate\", 1);\n\t\t\t\tdata.mixX = getValue(constraintMap, \"mixX\", 1);\n\t\t\t\tdata.mixY = getValue(constraintMap, \"mixY\", data.mixX);\n\t\t\t\tdata.mixScaleX = getValue(constraintMap, \"mixScaleX\", 1);\n\t\t\t\tdata.mixScaleY = getValue(constraintMap, \"mixScaleY\", data.mixScaleX);\n\t\t\t\tdata.mixShearY = getValue(constraintMap, \"mixShearY\", 1);\n\n\t\t\t\tskeletonData.transformConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Path constraints.\n\t\tif (root.path) {\n\t\t\tfor (let i = 0; i < root.path.length; i++) {\n\t\t\t\tlet constraintMap = root.path[i];\n\t\t\t\tlet data = new PathConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tfor (let ii = 0; ii < constraintMap.bones.length; ii++) {\n\t\t\t\t\tlet boneName = constraintMap.bones[ii];\n\t\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`);\n\t\t\t\t\tdata.bones.push(bone);\n\t\t\t\t}\n\n\t\t\t\tlet targetName: string = constraintMap.target;\n\t\t\t\tlet target = skeletonData.findSlot(targetName);\n\t\t\t\tif (!target) throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`);\n\t\t\t\tdata.target = target;\n\n\t\t\t\tdata.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, \"positionMode\", \"Percent\"));\n\t\t\t\tdata.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, \"spacingMode\", \"Length\"));\n\t\t\t\tdata.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, \"rotateMode\", \"Tangent\"));\n\t\t\t\tdata.offsetRotation = getValue(constraintMap, \"rotation\", 0);\n\t\t\t\tdata.position = getValue(constraintMap, \"position\", 0);\n\t\t\t\tif (data.positionMode == PositionMode.Fixed) data.position *= scale;\n\t\t\t\tdata.spacing = getValue(constraintMap, \"spacing\", 0);\n\t\t\t\tif (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) data.spacing *= scale;\n\t\t\t\tdata.mixRotate = getValue(constraintMap, \"mixRotate\", 1);\n\t\t\t\tdata.mixX = getValue(constraintMap, \"mixX\", 1);\n\t\t\t\tdata.mixY = getValue(constraintMap, \"mixY\", data.mixX);\n\n\t\t\t\tskeletonData.pathConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Physics constraints.\n\t\tif (root.physics) {\n\t\t\tfor (let i = 0; i < root.physics.length; i++) {\n\t\t\t\tconst constraintMap = root.physics[i];\n\t\t\t\tconst data = new PhysicsConstraintData(constraintMap.name);\n\t\t\t\tdata.order = getValue(constraintMap, \"order\", 0);\n\t\t\t\tdata.skinRequired = getValue(constraintMap, \"skin\", false);\n\n\t\t\t\tconst boneName = constraintMap.bone;\n\t\t\t\tconst bone = skeletonData.findBone(boneName);\n\t\t\t\tif (bone == null) throw new Error(\"Physics bone not found: \" + boneName);\n\t\t\t\tdata.bone = bone;\n\n\t\t\t\tdata.x = getValue(constraintMap, \"x\", 0);\n\t\t\t\tdata.y = getValue(constraintMap, \"y\", 0);\n\t\t\t\tdata.rotate = getValue(constraintMap, \"rotate\", 0);\n\t\t\t\tdata.scaleX = getValue(constraintMap, \"scaleX\", 0);\n\t\t\t\tdata.shearX = getValue(constraintMap, \"shearX\", 0);\n\t\t\t\tdata.limit = getValue(constraintMap, \"limit\", 5000) * scale;\n\t\t\t\tdata.step = 1 / getValue(constraintMap, \"fps\", 60);\n\t\t\t\tdata.inertia = getValue(constraintMap, \"inertia\", 1);\n\t\t\t\tdata.strength = getValue(constraintMap, \"strength\", 100);\n\t\t\t\tdata.damping = getValue(constraintMap, \"damping\", 1);\n\t\t\t\tdata.massInverse = 1 / getValue(constraintMap, \"mass\", 1);\n\t\t\t\tdata.wind = getValue(constraintMap, \"wind\", 0);\n\t\t\t\tdata.gravity = getValue(constraintMap, \"gravity\", 0);\n\t\t\t\tdata.mix = getValue(constraintMap, \"mix\", 1);\n\t\t\t\tdata.inertiaGlobal = getValue(constraintMap, \"inertiaGlobal\", false);\n\t\t\t\tdata.strengthGlobal = getValue(constraintMap, \"strengthGlobal\", false);\n\t\t\t\tdata.dampingGlobal = getValue(constraintMap, \"dampingGlobal\", false);\n\t\t\t\tdata.massGlobal = getValue(constraintMap, \"massGlobal\", false);\n\t\t\t\tdata.windGlobal = getValue(constraintMap, \"windGlobal\", false);\n\t\t\t\tdata.gravityGlobal = getValue(constraintMap, \"gravityGlobal\", false);\n\t\t\t\tdata.mixGlobal = getValue(constraintMap, \"mixGlobal\", false);\n\n\t\t\t\tskeletonData.physicsConstraints.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Skins.\n\t\tif (root.skins) {\n\t\t\tfor (let i = 0; i < root.skins.length; i++) {\n\t\t\t\tlet skinMap = root.skins[i]\n\t\t\t\tlet skin = new Skin(skinMap.name);\n\n\t\t\t\tif (skinMap.bones) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.bones.length; ii++) {\n\t\t\t\t\t\tlet boneName = skinMap.bones[ii];\n\t\t\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\t\t\tif (!bone) throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.bones.push(bone);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.ik) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.ik.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.ik[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findIkConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.transform) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.transform.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.transform[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findTransformConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.path) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.path.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.path[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findPathConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (skinMap.physics) {\n\t\t\t\t\tfor (let ii = 0; ii < skinMap.physics.length; ii++) {\n\t\t\t\t\t\tlet constraintName = skinMap.physics[ii];\n\t\t\t\t\t\tlet constraint = skeletonData.findPhysicsConstraint(constraintName);\n\t\t\t\t\t\tif (!constraint) throw new Error(`Couldn't find physics constraint ${constraintName} for skin ${skinMap.name}.`);\n\t\t\t\t\t\tskin.constraints.push(constraint);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (let slotName in skinMap.attachments) {\n\t\t\t\t\tlet slot = skeletonData.findSlot(slotName);\n\t\t\t\t\tif (!slot) throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`);\n\t\t\t\t\tlet slotMap = skinMap.attachments[slotName];\n\t\t\t\t\tfor (let entryName in slotMap) {\n\t\t\t\t\t\tlet attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData);\n\t\t\t\t\t\tif (attachment) skin.setAttachment(slot.index, entryName, attachment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tskeletonData.skins.push(skin);\n\t\t\t\tif (skin.name == \"default\") skeletonData.defaultSkin = skin;\n\t\t\t}\n\t\t}\n\n\t\t// Linked meshes.\n\t\tfor (let i = 0, n = this.linkedMeshes.length; i < n; i++) {\n\t\t\tlet linkedMesh = this.linkedMeshes[i];\n\t\t\tlet skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);\n\t\t\tif (!skin) throw new Error(`Skin not found: ${linkedMesh.skin}`);\n\t\t\tlet parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);\n\t\t\tif (!parent) throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);\n\t\t\tlinkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh;\n\t\t\tlinkedMesh.mesh.setParentMesh(parent);\n\t\t\tif (linkedMesh.mesh.region != null) linkedMesh.mesh.updateRegion();\n\t\t}\n\t\tthis.linkedMeshes.length = 0;\n\n\t\t// Events.\n\t\tif (root.events) {\n\t\t\tfor (let eventName in root.events) {\n\t\t\t\tlet eventMap = root.events[eventName];\n\t\t\t\tlet data = new EventData(eventName);\n\t\t\t\tdata.intValue = getValue(eventMap, \"int\", 0);\n\t\t\t\tdata.floatValue = getValue(eventMap, \"float\", 0);\n\t\t\t\tdata.stringValue = getValue(eventMap, \"string\", \"\");\n\t\t\t\tdata.audioPath = getValue(eventMap, \"audio\", null);\n\t\t\t\tif (data.audioPath) {\n\t\t\t\t\tdata.volume = getValue(eventMap, \"volume\", 1);\n\t\t\t\t\tdata.balance = getValue(eventMap, \"balance\", 0);\n\t\t\t\t}\n\t\t\t\tskeletonData.events.push(data);\n\t\t\t}\n\t\t}\n\n\t\t// Animations.\n\t\tif (root.animations) {\n\t\t\tfor (let animationName in root.animations) {\n\t\t\t\tlet animationMap = root.animations[animationName];\n\t\t\t\tthis.readAnimation(animationMap, animationName, skeletonData);\n\t\t\t}\n\t\t}\n\n\t\treturn skeletonData;\n\t}\n\n\treadAttachment (map: any, skin: Skin, slotIndex: number, name: string, skeletonData: SkeletonData): Attachment | null {\n\t\tlet scale = this.scale;\n\t\tname = getValue(map, \"name\", name);\n\n\t\tswitch (getValue(map, \"type\", \"region\")) {\n\t\t\tcase \"region\": {\n\t\t\t\tlet path = getValue(map, \"path\", name);\n\t\t\t\tlet sequence = this.readSequence(getValue(map, \"sequence\", null));\n\t\t\t\tlet region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);\n\t\t\t\tif (!region) return null;\n\t\t\t\tregion.path = path;\n\t\t\t\tregion.x = getValue(map, \"x\", 0) * scale;\n\t\t\t\tregion.y = getValue(map, \"y\", 0) * scale;\n\t\t\t\tregion.scaleX = getValue(map, \"scaleX\", 1);\n\t\t\t\tregion.scaleY = getValue(map, \"scaleY\", 1);\n\t\t\t\tregion.rotation = getValue(map, \"rotation\", 0);\n\t\t\t\tregion.width = map.width * scale;\n\t\t\t\tregion.height = map.height * scale;\n\t\t\t\tregion.sequence = sequence;\n\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) region.color.setFromString(color);\n\n\t\t\t\tif (region.region != null) region.updateRegion();\n\t\t\t\treturn region;\n\t\t\t}\n\t\t\tcase \"boundingbox\": {\n\t\t\t\tlet box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);\n\t\t\t\tif (!box) return null;\n\t\t\t\tthis.readVertices(map, box, map.vertexCount << 1);\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) box.color.setFromString(color);\n\t\t\t\treturn box;\n\t\t\t}\n\t\t\tcase \"mesh\":\n\t\t\tcase \"linkedmesh\": {\n\t\t\t\tlet path = getValue(map, \"path\", name);\n\t\t\t\tlet sequence = this.readSequence(getValue(map, \"sequence\", null));\n\t\t\t\tlet mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);\n\t\t\t\tif (!mesh) return null;\n\t\t\t\tmesh.path = path;\n\n\t\t\t\tlet color = getValue(map, \"color\", null);\n\t\t\t\tif (color) mesh.color.setFromString(color);\n\n\t\t\t\tmesh.width = getValue(map, \"width\", 0) * scale;\n\t\t\t\tmesh.height = getValue(map, \"height\", 0) * scale;\n\t\t\t\tmesh.sequence = sequence;\n\n\t\t\t\tlet parent: string = getValue(map, \"parent\", null);\n\t\t\t\tif (parent) {\n\t\t\t\t\tthis.linkedMeshes.push(new LinkedMesh(mesh, getValue(map, \"skin\", null), slotIndex, parent, getValue(map, \"timelines\", true)));\n\t\t\t\t\treturn mesh;\n\t\t\t\t}\n\n\t\t\t\tlet uvs: Array = map.uvs;\n\t\t\t\tthis.readVertices(map, mesh, uvs.length);\n\t\t\t\tmesh.triangles = map.triangles;\n\t\t\t\tmesh.regionUVs = uvs;\n\t\t\t\tif (mesh.region != null) mesh.updateRegion();\n\n\t\t\t\tmesh.edges = getValue(map, \"edges\", null);\n\t\t\t\tmesh.hullLength = getValue(map, \"hull\", 0) * 2;\n\t\t\t\treturn mesh;\n\t\t\t}\n\t\t\tcase \"path\": {\n\t\t\t\tlet path = this.attachmentLoader.newPathAttachment(skin, name);\n\t\t\t\tif (!path) return null;\n\t\t\t\tpath.closed = getValue(map, \"closed\", false);\n\t\t\t\tpath.constantSpeed = getValue(map, \"constantSpeed\", true);\n\n\t\t\t\tlet vertexCount = map.vertexCount;\n\t\t\t\tthis.readVertices(map, path, vertexCount << 1);\n\n\t\t\t\tlet lengths: Array = Utils.newArray(vertexCount / 3, 0);\n\t\t\t\tfor (let i = 0; i < map.lengths.length; i++)\n\t\t\t\t\tlengths[i] = map.lengths[i] * scale;\n\t\t\t\tpath.lengths = lengths;\n\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) path.color.setFromString(color);\n\t\t\t\treturn path;\n\t\t\t}\n\t\t\tcase \"point\": {\n\t\t\t\tlet point = this.attachmentLoader.newPointAttachment(skin, name);\n\t\t\t\tif (!point) return null;\n\t\t\t\tpoint.x = getValue(map, \"x\", 0) * scale;\n\t\t\t\tpoint.y = getValue(map, \"y\", 0) * scale;\n\t\t\t\tpoint.rotation = getValue(map, \"rotation\", 0);\n\n\t\t\t\tlet color = getValue(map, \"color\", null);\n\t\t\t\tif (color) point.color.setFromString(color);\n\t\t\t\treturn point;\n\t\t\t}\n\t\t\tcase \"clipping\": {\n\t\t\t\tlet clip = this.attachmentLoader.newClippingAttachment(skin, name);\n\t\t\t\tif (!clip) return null;\n\n\t\t\t\tlet end = getValue(map, \"end\", null);\n\t\t\t\tif (end) clip.endSlot = skeletonData.findSlot(end);\n\n\t\t\t\tlet vertexCount = map.vertexCount;\n\t\t\t\tthis.readVertices(map, clip, vertexCount << 1);\n\n\t\t\t\tlet color: string = getValue(map, \"color\", null);\n\t\t\t\tif (color) clip.color.setFromString(color);\n\t\t\t\treturn clip;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\treadSequence (map: any) {\n\t\tif (map == null) return null;\n\t\tlet sequence = new Sequence(getValue(map, \"count\", 0));\n\t\tsequence.start = getValue(map, \"start\", 1);\n\t\tsequence.digits = getValue(map, \"digits\", 0);\n\t\tsequence.setupIndex = getValue(map, \"setup\", 0);\n\t\treturn sequence;\n\t}\n\n\treadVertices (map: any, attachment: VertexAttachment, verticesLength: number) {\n\t\tlet scale = this.scale;\n\t\tattachment.worldVerticesLength = verticesLength;\n\t\tlet vertices: Array = map.vertices;\n\t\tif (verticesLength == vertices.length) {\n\t\t\tlet scaledVertices = Utils.toFloatArray(vertices);\n\t\t\tif (scale != 1) {\n\t\t\t\tfor (let i = 0, n = vertices.length; i < n; i++)\n\t\t\t\t\tscaledVertices[i] *= scale;\n\t\t\t}\n\t\t\tattachment.vertices = scaledVertices;\n\t\t\treturn;\n\t\t}\n\t\tlet weights = new Array();\n\t\tlet bones = new Array();\n\t\tfor (let i = 0, n = vertices.length; i < n;) {\n\t\t\tlet boneCount = vertices[i++];\n\t\t\tbones.push(boneCount);\n\t\t\tfor (let nn = i + boneCount * 4; i < nn; i += 4) {\n\t\t\t\tbones.push(vertices[i]);\n\t\t\t\tweights.push(vertices[i + 1] * scale);\n\t\t\t\tweights.push(vertices[i + 2] * scale);\n\t\t\t\tweights.push(vertices[i + 3]);\n\t\t\t}\n\t\t}\n\t\tattachment.bones = bones;\n\t\tattachment.vertices = Utils.toFloatArray(weights);\n\t}\n\n\treadAnimation (map: any, name: string, skeletonData: SkeletonData) {\n\t\tlet scale = this.scale;\n\t\tlet timelines = new Array();\n\n\t\t// Slot timelines.\n\t\tif (map.slots) {\n\t\t\tfor (let slotName in map.slots) {\n\t\t\t\tlet slotMap = map.slots[slotName];\n\t\t\t\tlet slot = skeletonData.findSlot(slotName);\n\t\t\t\tif (!slot) throw new Error(\"Slot not found: \" + slotName);\n\t\t\t\tlet slotIndex = slot.index;\n\t\t\t\tfor (let timelineName in slotMap) {\n\t\t\t\t\tlet timelineMap = slotMap[timelineName];\n\t\t\t\t\tif (!timelineMap) continue;\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (timelineName == \"attachment\") {\n\t\t\t\t\t\tlet timeline = new AttachmentTimeline(frames, slotIndex);\n\t\t\t\t\t\tfor (let frame = 0; frame < frames; frame++) {\n\t\t\t\t\t\t\tlet keyMap = timelineMap[frame];\n\t\t\t\t\t\t\ttimeline.setFrame(frame, getValue(keyMap, \"time\", 0), getValue(keyMap, \"name\", null));\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"rgba\") {\n\t\t\t\t\t\tlet timeline = new RGBATimeline(frames, frames << 2, slotIndex);\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.color);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b, color.a);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.color);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"rgb\") {\n\t\t\t\t\t\tlet timeline = new RGBTimeline(frames, frames * 3, slotIndex);\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.color);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.color);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"alpha\") {\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1));\n\t\t\t\t\t} else if (timelineName == \"rgba2\") {\n\t\t\t\t\t\tlet timeline = new RGBA2Timeline(frames, frames * 7, slotIndex);\n\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.light);\n\t\t\t\t\t\tlet color2 = Color.fromString(keyMap.dark);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.light);\n\t\t\t\t\t\t\tlet newColor2 = Color.fromString(nextMap.dark);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tcolor2 = newColor2;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\n\t\t\t\t\t} else if (timelineName == \"rgb2\") {\n\t\t\t\t\t\tlet timeline = new RGB2Timeline(frames, frames * 6, slotIndex);\n\n\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet color = Color.fromString(keyMap.light);\n\t\t\t\t\t\tlet color2 = Color.fromString(keyMap.dark);\n\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet newColor = Color.fromString(nextMap.light);\n\t\t\t\t\t\t\tlet newColor2 = Color.fromString(nextMap.dark);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tcolor = newColor;\n\t\t\t\t\t\t\tcolor2 = newColor2;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Bone timelines.\n\t\tif (map.bones) {\n\t\t\tfor (let boneName in map.bones) {\n\t\t\t\tlet boneMap = map.bones[boneName];\n\t\t\t\tlet bone = skeletonData.findBone(boneName);\n\t\t\t\tif (!bone) throw new Error(\"Bone not found: \" + boneName);\n\t\t\t\tlet boneIndex = bone.index;\n\t\t\t\tfor (let timelineName in boneMap) {\n\t\t\t\t\tlet timelineMap = boneMap[timelineName];\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (frames == 0) continue;\n\n\t\t\t\t\tif (timelineName === \"rotate\") {\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1));\n\t\t\t\t\t} else if (timelineName === \"translate\") {\n\t\t\t\t\t\tlet timeline = new TranslateTimeline(frames, frames << 1, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline2(timelineMap, timeline, \"x\", \"y\", 0, scale));\n\t\t\t\t\t} else if (timelineName === \"translatex\") {\n\t\t\t\t\t\tlet timeline = new TranslateXTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, scale));\n\t\t\t\t\t} else if (timelineName === \"translatey\") {\n\t\t\t\t\t\tlet timeline = new TranslateYTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, scale));\n\t\t\t\t\t} else if (timelineName === \"scale\") {\n\t\t\t\t\t\tlet timeline = new ScaleTimeline(frames, frames << 1, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline2(timelineMap, timeline, \"x\", \"y\", 1, 1));\n\t\t\t\t\t} else if (timelineName === \"scalex\") {\n\t\t\t\t\t\tlet timeline = new ScaleXTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 1, 1));\n\t\t\t\t\t} else if (timelineName === \"scaley\") {\n\t\t\t\t\t\tlet timeline = new ScaleYTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 1, 1));\n\t\t\t\t\t} else if (timelineName === \"shear\") {\n\t\t\t\t\t\tlet timeline = new ShearTimeline(frames, frames << 1, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline2(timelineMap, timeline, \"x\", \"y\", 0, 1));\n\t\t\t\t\t} else if (timelineName === \"shearx\") {\n\t\t\t\t\t\tlet timeline = new ShearXTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, 1));\n\t\t\t\t\t} else if (timelineName === \"sheary\") {\n\t\t\t\t\t\tlet timeline = new ShearYTimeline(frames, frames, boneIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, 1));\n\t\t\t\t\t} else if (timelineName === \"inherit\") {\n\t\t\t\t\t\tlet timeline = new InheritTimeline(frames, bone.index);\n\t\t\t\t\t\tfor (let frame = 0; frame < timelineMap.length; frame++) {\n\t\t\t\t\t\t\tlet aFrame = timelineMap[frame];\n\t\t\t\t\t\t\ttimeline.setFrame(frame, getValue(aFrame, \"time\", 0), Utils.enumValue(Inherit, getValue(aFrame, \"inherit\", \"Normal\")));\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// IK constraint timelines.\n\t\tif (map.ik) {\n\t\t\tfor (let constraintName in map.ik) {\n\t\t\t\tlet constraintMap = map.ik[constraintName];\n\t\t\t\tlet keyMap = constraintMap[0];\n\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\tlet constraint = skeletonData.findIkConstraint(constraintName);\n\t\t\t\tif (!constraint) throw new Error(\"IK Constraint not found: \" + constraintName);\n\t\t\t\tlet constraintIndex = skeletonData.ikConstraints.indexOf(constraint);\n\t\t\t\tlet timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex);\n\n\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\tlet mix = getValue(keyMap, \"mix\", 1);\n\t\t\t\tlet softness = getValue(keyMap, \"softness\", 0) * scale;\n\n\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\ttimeline.setFrame(frame, time, mix, softness, getValue(keyMap, \"bendPositive\", true) ? 1 : -1, getValue(keyMap, \"compress\", false), getValue(keyMap, \"stretch\", false));\n\t\t\t\t\tlet nextMap = constraintMap[frame + 1];\n\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\tlet mix2 = getValue(nextMap, \"mix\", 1);\n\t\t\t\t\tlet softness2 = getValue(nextMap, \"softness\", 0) * scale;\n\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\tif (curve) {\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale);\n\t\t\t\t\t}\n\n\t\t\t\t\ttime = time2;\n\t\t\t\t\tmix = mix2;\n\t\t\t\t\tsoftness = softness2;\n\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t}\n\t\t\t\ttimelines.push(timeline);\n\t\t\t}\n\t\t}\n\n\t\t// Transform constraint timelines.\n\t\tif (map.transform) {\n\t\t\tfor (let constraintName in map.transform) {\n\t\t\t\tlet timelineMap = map.transform[constraintName];\n\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\tlet constraint = skeletonData.findTransformConstraint(constraintName);\n\t\t\t\tif (!constraint) throw new Error(\"Transform constraint not found: \" + constraintName);\n\t\t\t\tlet constraintIndex = skeletonData.transformConstraints.indexOf(constraint);\n\t\t\t\tlet timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex);\n\n\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\tlet mixRotate = getValue(keyMap, \"mixRotate\", 1);\n\t\t\t\tlet mixX = getValue(keyMap, \"mixX\", 1);\n\t\t\t\tlet mixY = getValue(keyMap, \"mixY\", mixX);\n\t\t\t\tlet mixScaleX = getValue(keyMap, \"mixScaleX\", 1);\n\t\t\t\tlet mixScaleY = getValue(keyMap, \"mixScaleY\", mixScaleX);\n\t\t\t\tlet mixShearY = getValue(keyMap, \"mixShearY\", 1);\n\n\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);\n\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\tlet mixRotate2 = getValue(nextMap, \"mixRotate\", 1);\n\t\t\t\t\tlet mixX2 = getValue(nextMap, \"mixX\", 1);\n\t\t\t\t\tlet mixY2 = getValue(nextMap, \"mixY\", mixX2);\n\t\t\t\t\tlet mixScaleX2 = getValue(nextMap, \"mixScaleX\", 1);\n\t\t\t\t\tlet mixScaleY2 = getValue(nextMap, \"mixScaleY\", mixScaleX2);\n\t\t\t\t\tlet mixShearY2 = getValue(nextMap, \"mixShearY\", 1);\n\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\tif (curve) {\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);\n\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1);\n\t\t\t\t\t}\n\n\t\t\t\t\ttime = time2;\n\t\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\t\tmixX = mixX2;\n\t\t\t\t\tmixY = mixY2;\n\t\t\t\t\tmixScaleX = mixScaleX2;\n\t\t\t\t\tmixScaleY = mixScaleY2;\n\t\t\t\t\tmixScaleX = mixScaleX2;\n\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t}\n\t\t\t\ttimelines.push(timeline);\n\t\t\t}\n\t\t}\n\n\t\t// Path constraint timelines.\n\t\tif (map.path) {\n\t\t\tfor (let constraintName in map.path) {\n\t\t\t\tlet constraintMap = map.path[constraintName];\n\t\t\t\tlet constraint = skeletonData.findPathConstraint(constraintName);\n\t\t\t\tif (!constraint) throw new Error(\"Path constraint not found: \" + constraintName);\n\t\t\t\tlet constraintIndex = skeletonData.pathConstraints.indexOf(constraint);\n\t\t\t\tfor (let timelineName in constraintMap) {\n\t\t\t\t\tlet timelineMap = constraintMap[timelineName];\n\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (timelineName === \"position\") {\n\t\t\t\t\t\tlet timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, constraint.positionMode == PositionMode.Fixed ? scale : 1));\n\t\t\t\t\t} else if (timelineName === \"spacing\") {\n\t\t\t\t\t\tlet timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex);\n\t\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, constraint.spacingMode == SpacingMode.Length || constraint.spacingMode == SpacingMode.Fixed ? scale : 1));\n\t\t\t\t\t} else if (timelineName === \"mix\") {\n\t\t\t\t\t\tlet timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex);\n\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\tlet mixRotate = getValue(keyMap, \"mixRotate\", 1);\n\t\t\t\t\t\tlet mixX = getValue(keyMap, \"mixX\", 1);\n\t\t\t\t\t\tlet mixY = getValue(keyMap, \"mixY\", mixX);\n\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\ttimeline.setFrame(frame, time, mixRotate, mixX, mixY);\n\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\tlet mixRotate2 = getValue(nextMap, \"mixRotate\", 1);\n\t\t\t\t\t\t\tlet mixX2 = getValue(nextMap, \"mixX\", 1);\n\t\t\t\t\t\t\tlet mixY2 = getValue(nextMap, \"mixY\", mixX2);\n\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\tif (curve) {\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);\n\t\t\t\t\t\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\tmixRotate = mixRotate2;\n\t\t\t\t\t\t\tmixX = mixX2;\n\t\t\t\t\t\t\tmixY = mixY2;\n\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Physics constraint timelines.\n\t\tif (map.physics) {\n\t\t\tfor (let constraintName in map.physics) {\n\t\t\t\tlet constraintMap = map.physics[constraintName];\n\t\t\t\tlet constraintIndex = -1;\n\t\t\t\tif (constraintName.length > 0) {\n\t\t\t\t\tlet constraint = skeletonData.findPhysicsConstraint(constraintName);\n\t\t\t\t\tif (!constraint) throw new Error(\"Physics constraint not found: \" + constraintName);\n\t\t\t\t\tconstraintIndex = skeletonData.physicsConstraints.indexOf(constraint);\n\t\t\t\t}\n\t\t\t\tfor (let timelineName in constraintMap) {\n\t\t\t\t\tlet timelineMap = constraintMap[timelineName];\n\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\t\tlet frames = timelineMap.length;\n\t\t\t\t\tif (timelineName == \"reset\") {\n\t\t\t\t\t\tconst timeline = new PhysicsConstraintResetTimeline(frames, constraintIndex);\n\t\t\t\t\t\tfor (let frame = 0; keyMap != null; keyMap = timelineMap[frame + 1], frame++)\n\t\t\t\t\t\t\ttimeline.setFrame(frame, getValue(keyMap, \"time\", 0));\n\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet timeline;\n\t\t\t\t\tif (timelineName == \"inertia\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintInertiaTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"strength\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintStrengthTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"damping\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintDampingTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"mass\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintMassTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"wind\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintWindTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"gravity\")\n\t\t\t\t\t\ttimeline = new PhysicsConstraintGravityTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse if (timelineName == \"mix\") //\n\t\t\t\t\t\ttimeline = new PhysicsConstraintMixTimeline(frames, frames, constraintIndex);\n\t\t\t\t\telse\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\ttimelines.push(readTimeline1(timelineMap, timeline, 0, 1));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attachment timelines.\n\t\tif (map.attachments) {\n\t\t\tfor (let attachmentsName in map.attachments) {\n\t\t\t\tlet attachmentsMap = map.attachments[attachmentsName];\n\t\t\t\tlet skin = skeletonData.findSkin(attachmentsName);\n\t\t\t\tif (!skin) throw new Error(\"Skin not found: \" + attachmentsName);\n\t\t\t\tfor (let slotMapName in attachmentsMap) {\n\t\t\t\t\tlet slotMap = attachmentsMap[slotMapName];\n\t\t\t\t\tlet slot = skeletonData.findSlot(slotMapName);\n\t\t\t\t\tif (!slot) throw new Error(\"Slot not found: \" + slotMapName);\n\t\t\t\t\tlet slotIndex = slot.index;\n\t\t\t\t\tfor (let attachmentMapName in slotMap) {\n\t\t\t\t\t\tlet attachmentMap = slotMap[attachmentMapName];\n\t\t\t\t\t\tlet attachment = skin.getAttachment(slotIndex, attachmentMapName);\n\n\t\t\t\t\t\tfor (let timelineMapName in attachmentMap) {\n\t\t\t\t\t\t\tlet timelineMap = attachmentMap[timelineMapName];\n\t\t\t\t\t\t\tlet keyMap = timelineMap[0];\n\t\t\t\t\t\t\tif (!keyMap) continue;\n\n\t\t\t\t\t\t\tif (timelineMapName == \"deform\") {\n\t\t\t\t\t\t\t\tlet weighted = attachment.bones;\n\t\t\t\t\t\t\t\tlet vertices = attachment.vertices;\n\t\t\t\t\t\t\t\tlet deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;\n\n\t\t\t\t\t\t\t\tlet timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment);\n\t\t\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\t\t\tfor (let frame = 0, bezier = 0; ; frame++) {\n\t\t\t\t\t\t\t\t\tlet deform: NumberArrayLike;\n\t\t\t\t\t\t\t\t\tlet verticesValue: Array = getValue(keyMap, \"vertices\", null);\n\t\t\t\t\t\t\t\t\tif (!verticesValue)\n\t\t\t\t\t\t\t\t\t\tdeform = weighted ? Utils.newFloatArray(deformLength) : vertices;\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tdeform = Utils.newFloatArray(deformLength);\n\t\t\t\t\t\t\t\t\t\tlet start = getValue(keyMap, \"offset\", 0);\n\t\t\t\t\t\t\t\t\t\tUtils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length);\n\t\t\t\t\t\t\t\t\t\tif (scale != 1) {\n\t\t\t\t\t\t\t\t\t\t\tfor (let i = start, n = i + verticesValue.length; i < n; i++)\n\t\t\t\t\t\t\t\t\t\t\t\tdeform[i] *= scale;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (!weighted) {\n\t\t\t\t\t\t\t\t\t\t\tfor (let i = 0; i < deformLength; i++)\n\t\t\t\t\t\t\t\t\t\t\t\tdeform[i] += vertices[i];\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, deform);\n\t\t\t\t\t\t\t\t\tlet nextMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\t\t\tif (!nextMap) {\n\t\t\t\t\t\t\t\t\t\ttimeline.shrink(bezier);\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\t\t\t\t\t\t\t\tlet curve = keyMap.curve;\n\t\t\t\t\t\t\t\t\tif (curve) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);\n\t\t\t\t\t\t\t\t\ttime = time2;\n\t\t\t\t\t\t\t\t\tkeyMap = nextMap;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\t} else if (timelineMapName == \"sequence\") {\n\t\t\t\t\t\t\t\tlet timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment as unknown as HasTextureRegion);\n\t\t\t\t\t\t\t\tlet lastDelay = 0;\n\t\t\t\t\t\t\t\tfor (let frame = 0; frame < timelineMap.length; frame++) {\n\t\t\t\t\t\t\t\t\tlet delay = getValue(keyMap, \"delay\", lastDelay);\n\t\t\t\t\t\t\t\t\tlet time = getValue(keyMap, \"time\", 0);\n\t\t\t\t\t\t\t\t\tlet mode = SequenceMode[getValue(keyMap, \"mode\", \"hold\")] as unknown as number;\n\t\t\t\t\t\t\t\t\tlet index = getValue(keyMap, \"index\", 0);\n\t\t\t\t\t\t\t\t\ttimeline.setFrame(frame, time, mode, index, delay);\n\t\t\t\t\t\t\t\t\tlastDelay = delay;\n\t\t\t\t\t\t\t\t\tkeyMap = timelineMap[frame + 1];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttimelines.push(timeline);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Draw order timelines.\n\t\tif (map.drawOrder) {\n\t\t\tlet timeline = new DrawOrderTimeline(map.drawOrder.length);\n\t\t\tlet slotCount = skeletonData.slots.length;\n\t\t\tlet frame = 0;\n\t\t\tfor (let i = 0; i < map.drawOrder.length; i++, frame++) {\n\t\t\t\tlet drawOrderMap = map.drawOrder[i];\n\t\t\t\tlet drawOrder: Array | null = null;\n\t\t\t\tlet offsets = getValue(drawOrderMap, \"offsets\", null);\n\t\t\t\tif (offsets) {\n\t\t\t\t\tdrawOrder = Utils.newArray(slotCount, -1);\n\t\t\t\t\tlet unchanged = Utils.newArray(slotCount - offsets.length, 0);\n\t\t\t\t\tlet originalIndex = 0, unchangedIndex = 0;\n\t\t\t\t\tfor (let ii = 0; ii < offsets.length; ii++) {\n\t\t\t\t\t\tlet offsetMap = offsets[ii];\n\t\t\t\t\t\tlet slot = skeletonData.findSlot(offsetMap.slot);\n\t\t\t\t\t\tif (!slot) throw new Error(\"Slot not found: \" + slot);\n\t\t\t\t\t\tlet slotIndex = slot.index;\n\t\t\t\t\t\t// Collect unchanged items.\n\t\t\t\t\t\twhile (originalIndex != slotIndex)\n\t\t\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t\t\t// Set changed items.\n\t\t\t\t\t\tdrawOrder[originalIndex + offsetMap.offset] = originalIndex++;\n\t\t\t\t\t}\n\t\t\t\t\t// Collect remaining unchanged items.\n\t\t\t\t\twhile (originalIndex < slotCount)\n\t\t\t\t\t\tunchanged[unchangedIndex++] = originalIndex++;\n\t\t\t\t\t// Fill in unchanged items.\n\t\t\t\t\tfor (let ii = slotCount - 1; ii >= 0; ii--)\n\t\t\t\t\t\tif (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];\n\t\t\t\t}\n\t\t\t\ttimeline.setFrame(frame, getValue(drawOrderMap, \"time\", 0), drawOrder);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\t// Event timelines.\n\t\tif (map.events) {\n\t\t\tlet timeline = new EventTimeline(map.events.length);\n\t\t\tlet frame = 0;\n\t\t\tfor (let i = 0; i < map.events.length; i++, frame++) {\n\t\t\t\tlet eventMap = map.events[i];\n\t\t\t\tlet eventData = skeletonData.findEvent(eventMap.name);\n\t\t\t\tif (!eventData) throw new Error(\"Event not found: \" + eventMap.name);\n\t\t\t\tlet event = new Event(Utils.toSinglePrecision(getValue(eventMap, \"time\", 0)), eventData);\n\t\t\t\tevent.intValue = getValue(eventMap, \"int\", eventData.intValue);\n\t\t\t\tevent.floatValue = getValue(eventMap, \"float\", eventData.floatValue);\n\t\t\t\tevent.stringValue = getValue(eventMap, \"string\", eventData.stringValue);\n\t\t\t\tif (event.data.audioPath) {\n\t\t\t\t\tevent.volume = getValue(eventMap, \"volume\", 1);\n\t\t\t\t\tevent.balance = getValue(eventMap, \"balance\", 0);\n\t\t\t\t}\n\t\t\t\ttimeline.setFrame(frame, event);\n\t\t\t}\n\t\t\ttimelines.push(timeline);\n\t\t}\n\n\t\tlet duration = 0;\n\t\tfor (let i = 0, n = timelines.length; i < n; i++)\n\t\t\tduration = Math.max(duration, timelines[i].getDuration());\n\t\tskeletonData.animations.push(new Animation(name, timelines, duration));\n\t}\n}\n\nclass LinkedMesh {\n\tparent: string; skin: string;\n\tslotIndex: number;\n\tmesh: MeshAttachment;\n\tinheritTimeline: boolean;\n\n\tconstructor (mesh: MeshAttachment, skin: string, slotIndex: number, parent: string, inheritDeform: boolean) {\n\t\tthis.mesh = mesh;\n\t\tthis.skin = skin;\n\t\tthis.slotIndex = slotIndex;\n\t\tthis.parent = parent;\n\t\tthis.inheritTimeline = inheritDeform;\n\t}\n}\n\nfunction readTimeline1 (keys: any[], timeline: CurveTimeline1, defaultValue: number, scale: number) {\n\tlet keyMap = keys[0];\n\tlet time = getValue(keyMap, \"time\", 0);\n\tlet value = getValue(keyMap, \"value\", defaultValue) * scale;\n\tlet bezier = 0;\n\tfor (let frame = 0; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value);\n\t\tlet nextMap = keys[frame + 1];\n\t\tif (!nextMap) {\n\t\t\ttimeline.shrink(bezier);\n\t\t\treturn timeline;\n\t\t}\n\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\tlet value2 = getValue(nextMap, \"value\", defaultValue) * scale;\n\t\tif (keyMap.curve) bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale);\n\t\ttime = time2;\n\t\tvalue = value2;\n\t\tkeyMap = nextMap;\n\t}\n}\n\nfunction readTimeline2 (keys: any[], timeline: CurveTimeline2, name1: string, name2: string, defaultValue: number, scale: number) {\n\tlet keyMap = keys[0];\n\tlet time = getValue(keyMap, \"time\", 0);\n\tlet value1 = getValue(keyMap, name1, defaultValue) * scale;\n\tlet value2 = getValue(keyMap, name2, defaultValue) * scale;\n\tlet bezier = 0;\n\tfor (let frame = 0; ; frame++) {\n\t\ttimeline.setFrame(frame, time, value1, value2);\n\t\tlet nextMap = keys[frame + 1];\n\t\tif (!nextMap) {\n\t\t\ttimeline.shrink(bezier);\n\t\t\treturn timeline;\n\t\t}\n\t\tlet time2 = getValue(nextMap, \"time\", 0);\n\t\tlet nvalue1 = getValue(nextMap, name1, defaultValue) * scale;\n\t\tlet nvalue2 = getValue(nextMap, name2, defaultValue) * scale;\n\t\tlet curve = keyMap.curve;\n\t\tif (curve) {\n\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale);\n\t\t\tbezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale);\n\t\t}\n\t\ttime = time2;\n\t\tvalue1 = nvalue1;\n\t\tvalue2 = nvalue2;\n\t\tkeyMap = nextMap;\n\t}\n}\n\nfunction readCurve (curve: any, timeline: CurveTimeline, bezier: number, frame: number, value: number, time1: number, time2: number,\n\tvalue1: number, value2: number, scale: number) {\n\tif (curve == \"stepped\") {\n\t\ttimeline.setStepped(frame);\n\t\treturn bezier;\n\t}\n\tlet i = value << 2;\n\tlet cx1 = curve[i];\n\tlet cy1 = curve[i + 1] * scale;\n\tlet cx2 = curve[i + 2];\n\tlet cy2 = curve[i + 3] * scale;\n\ttimeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);\n\treturn bezier + 1;\n}\n\nfunction getValue (map: any, property: string, defaultValue: any) {\n\treturn map[property] !== undefined ? map[property] : defaultValue;\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\n(() => {\n\tif (typeof Math.fround === \"undefined\") {\n\t\tMath.fround = (function (array) {\n\t\t\treturn function (x: number) {\n\t\t\t\treturn array[0] = x, array[0];\n\t\t\t};\n\t\t})(new Float32Array(1));\n\t}\n})();\n\nexport { }\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Restorable, BlendMode } from \"@esotericsoftware/spine-core\";\n\nexport class ManagedWebGLRenderingContext {\n\tpublic canvas: HTMLCanvasElement | OffscreenCanvas;\n\tpublic gl: WebGLRenderingContext;\n\tprivate restorables = new Array();\n\n\tconstructor (canvasOrContext: HTMLCanvasElement | WebGLRenderingContext, contextConfig: any = { alpha: \"true\" }) {\n\t\tif (!((canvasOrContext instanceof WebGLRenderingContext) || (typeof WebGL2RenderingContext !== 'undefined' && canvasOrContext instanceof WebGL2RenderingContext))) {\n\t\t\tlet canvas: HTMLCanvasElement = canvasOrContext;\n\t\t\tthis.gl = (canvas.getContext(\"webgl2\", contextConfig) || canvas.getContext(\"webgl\", contextConfig));\n\t\t\tthis.canvas = canvas;\n\t\t\tcanvas.addEventListener(\"webglcontextlost\", (e: any) => {\n\t\t\t\tlet event = e;\n\t\t\t\tif (e) e.preventDefault();\n\t\t\t});\n\t\t\tcanvas.addEventListener(\"webglcontextrestored\", (e: any) => {\n\t\t\t\tfor (let i = 0, n = this.restorables.length; i < n; i++)\n\t\t\t\t\tthis.restorables[i].restore();\n\t\t\t});\n\t\t} else {\n\t\t\tthis.gl = canvasOrContext;\n\t\t\tthis.canvas = this.gl.canvas;\n\t\t}\n\t}\n\n\taddRestorable (restorable: Restorable) {\n\t\tthis.restorables.push(restorable);\n\t}\n\n\tremoveRestorable (restorable: Restorable) {\n\t\tlet index = this.restorables.indexOf(restorable);\n\t\tif (index > -1) this.restorables.splice(index, 1);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture, Disposable, Restorable, TextureFilter, TextureWrap } from \"@esotericsoftware/spine-core\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class GLTexture extends Texture implements Disposable, Restorable {\n\tcontext: ManagedWebGLRenderingContext;\n\tprivate texture: WebGLTexture | null = null;\n\tprivate boundUnit = 0;\n\tprivate useMipMaps = false;\n\n\tpublic static DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false;\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, image: HTMLImageElement | ImageBitmap, useMipMaps: boolean = false) {\n\t\tsuper(image);\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.useMipMaps = useMipMaps;\n\t\tthis.restore();\n\t\tthis.context.addRestorable(this);\n\t}\n\n\tsetFilters (minFilter: TextureFilter, magFilter: TextureFilter) {\n\t\tlet gl = this.context.gl;\n\t\tthis.bind();\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, GLTexture.validateMagFilter(magFilter));\n\t\tthis.useMipMaps = GLTexture.usesMipMaps(minFilter);\n\t\tif (this.useMipMaps) gl.generateMipmap(gl.TEXTURE_2D);\n\t}\n\n\tstatic validateMagFilter (magFilter: TextureFilter) {\n\t\tswitch (magFilter) {\n\t\t\tcase TextureFilter.MipMapLinearLinear:\n\t\t\tcase TextureFilter.MipMapLinearNearest:\n\t\t\tcase TextureFilter.MipMapNearestLinear:\n\t\t\tcase TextureFilter.MipMapNearestNearest:\n\t\t\t\treturn TextureFilter.Linear;\n\t\t\tdefault:\n\t\t\t\treturn magFilter;\n\t\t}\n\t}\n\n\tstatic usesMipMaps (filter: TextureFilter) {\n\t\tswitch (filter) {\n\t\t\tcase TextureFilter.MipMapLinearLinear:\n\t\t\tcase TextureFilter.MipMapLinearNearest:\n\t\t\tcase TextureFilter.MipMapNearestLinear:\n\t\t\tcase TextureFilter.MipMapNearestNearest:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tsetWraps (uWrap: TextureWrap, vWrap: TextureWrap) {\n\t\tlet gl = this.context.gl;\n\t\tthis.bind();\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap);\n\t}\n\n\tupdate (useMipMaps: boolean) {\n\t\tlet gl = this.context.gl;\n\t\tif (!this.texture) this.texture = this.context.gl.createTexture();\n\t\tthis.bind();\n\t\tif (GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL) gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tif (useMipMaps) gl.generateMipmap(gl.TEXTURE_2D);\n\t}\n\n\trestore () {\n\t\tthis.texture = null;\n\t\tthis.update(this.useMipMaps);\n\t}\n\n\tbind (unit: number = 0) {\n\t\tlet gl = this.context.gl;\n\t\tthis.boundUnit = unit;\n\t\tgl.activeTexture(gl.TEXTURE0 + unit);\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.texture);\n\t}\n\n\tunbind () {\n\t\tlet gl = this.context.gl;\n\t\tgl.activeTexture(gl.TEXTURE0 + this.boundUnit);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t}\n\n\tdispose () {\n\t\tthis.context.removeRestorable(this);\n\t\tlet gl = this.context.gl;\n\t\tgl.deleteTexture(this.texture);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { AssetManagerBase, Downloader } from \"@esotericsoftware/spine-core\"\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\nimport { GLTexture } from \"./GLTexture.js\";\n\n\nexport class AssetManager extends AssetManagerBase {\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, pathPrefix: string = \"\", downloader: Downloader = new Downloader()) {\n\t\tsuper((image: HTMLImageElement | ImageBitmap) => {\n\t\t\treturn new GLTexture(context, image);\n\t\t}, pathPrefix, downloader);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Matrix4, M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33 } from \"./Matrix4.js\";\n\nexport class Vector3 {\n\tx = 0;\n\ty = 0;\n\tz = 0;\n\n\tconstructor (x: number = 0, y: number = 0, z: number = 0) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t}\n\n\tsetFrom (v: Vector3): Vector3 {\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\t\tthis.z = v.z;\n\t\treturn this;\n\t}\n\n\tset (x: number, y: number, z: number): Vector3 {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t\treturn this;\n\t}\n\n\tadd (v: Vector3): Vector3 {\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\t\tthis.z += v.z;\n\t\treturn this;\n\t}\n\n\tsub (v: Vector3): Vector3 {\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\t\tthis.z -= v.z;\n\t\treturn this;\n\t}\n\n\tscale (s: number): Vector3 {\n\t\tthis.x *= s;\n\t\tthis.y *= s;\n\t\tthis.z *= s;\n\t\treturn this;\n\t}\n\n\tnormalize (): Vector3 {\n\t\tlet len = this.length();\n\t\tif (len == 0) return this;\n\t\tlen = 1 / len;\n\t\tthis.x *= len;\n\t\tthis.y *= len;\n\t\tthis.z *= len;\n\t\treturn this;\n\t}\n\n\tcross (v: Vector3): Vector3 {\n\t\treturn this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x)\n\t}\n\n\tmultiply (matrix: Matrix4): Vector3 {\n\t\tlet l_mat = matrix.values;\n\t\treturn this.set(this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03],\n\t\t\tthis.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13],\n\t\t\tthis.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]);\n\t}\n\n\tproject (matrix: Matrix4): Vector3 {\n\t\tlet l_mat = matrix.values;\n\t\tlet l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]);\n\t\treturn this.set((this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w,\n\t\t\t(this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w,\n\t\t\t(this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w);\n\t}\n\n\tdot (v: Vector3): number {\n\t\treturn this.x * v.x + this.y * v.y + this.z * v.z;\n\t}\n\n\tlength (): number {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\n\t}\n\n\tdistance (v: Vector3): number {\n\t\tlet a = v.x - this.x;\n\t\tlet b = v.y - this.y;\n\t\tlet c = v.z - this.z;\n\t\treturn Math.sqrt(a * a + b * b + c * c);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Vector3 } from \"./Vector3.js\";\n\nexport const M00 = 0;\nexport const M01 = 4;\nexport const M02 = 8;\nexport const M03 = 12;\nexport const M10 = 1;\nexport const M11 = 5;\nexport const M12 = 9;\nexport const M13 = 13;\nexport const M20 = 2;\nexport const M21 = 6;\nexport const M22 = 10;\nexport const M23 = 14;\nexport const M30 = 3;\nexport const M31 = 7;\nexport const M32 = 11;\nexport const M33 = 15;\n\nexport class Matrix4 {\n\ttemp: Float32Array = new Float32Array(16);\n\tvalues: Float32Array = new Float32Array(16);\n\n\tprivate static xAxis = new Vector3();\n\tprivate static yAxis = new Vector3();\n\tprivate static zAxis = new Vector3();\n\tprivate static tmpMatrix = new Matrix4();\n\n\tconstructor () {\n\t\tlet v = this.values;\n\t\tv[M00] = 1;\n\t\tv[M11] = 1;\n\t\tv[M22] = 1;\n\t\tv[M33] = 1;\n\t}\n\n\tset (values: ArrayLike): Matrix4 {\n\t\tthis.values.set(values);\n\t\treturn this;\n\t}\n\n\ttranspose (): Matrix4 {\n\t\tlet t = this.temp;\n\t\tlet v = this.values;\n\t\tt[M00] = v[M00];\n\t\tt[M01] = v[M10];\n\t\tt[M02] = v[M20];\n\t\tt[M03] = v[M30];\n\t\tt[M10] = v[M01];\n\t\tt[M11] = v[M11];\n\t\tt[M12] = v[M21];\n\t\tt[M13] = v[M31];\n\t\tt[M20] = v[M02];\n\t\tt[M21] = v[M12];\n\t\tt[M22] = v[M22];\n\t\tt[M23] = v[M32];\n\t\tt[M30] = v[M03];\n\t\tt[M31] = v[M13];\n\t\tt[M32] = v[M23];\n\t\tt[M33] = v[M33];\n\t\treturn this.set(t);\n\t}\n\n\tidentity (): Matrix4 {\n\t\tlet v = this.values;\n\t\tv[M00] = 1;\n\t\tv[M01] = 0;\n\t\tv[M02] = 0;\n\t\tv[M03] = 0;\n\t\tv[M10] = 0;\n\t\tv[M11] = 1;\n\t\tv[M12] = 0;\n\t\tv[M13] = 0;\n\t\tv[M20] = 0;\n\t\tv[M21] = 0;\n\t\tv[M22] = 1;\n\t\tv[M23] = 0;\n\t\tv[M30] = 0;\n\t\tv[M31] = 0;\n\t\tv[M32] = 0;\n\t\tv[M33] = 1;\n\t\treturn this;\n\t}\n\n\tinvert (): Matrix4 {\n\t\tlet v = this.values;\n\t\tlet t = this.temp;\n\t\tlet l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03]\n\t\t\t+ v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03]\n\t\t\t- v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13]\n\t\t\t- v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13]\n\t\t\t+ v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23]\n\t\t\t+ v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23]\n\t\t\t- v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33]\n\t\t\t- v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33];\n\t\tif (l_det == 0) throw new Error(\"non-invertible matrix\");\n\t\tlet inv_det = 1.0 / l_det;\n\t\tt[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32]\n\t\t\t- v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33];\n\t\tt[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32]\n\t\t\t+ v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33];\n\t\tt[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32]\n\t\t\t- v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33];\n\t\tt[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22]\n\t\t\t+ v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23];\n\t\tt[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32]\n\t\t\t+ v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33];\n\t\tt[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32]\n\t\t\t- v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33];\n\t\tt[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32]\n\t\t\t+ v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33];\n\t\tt[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22]\n\t\t\t- v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23];\n\t\tt[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31]\n\t\t\t- v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33];\n\t\tt[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31]\n\t\t\t+ v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33];\n\t\tt[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31]\n\t\t\t- v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33];\n\t\tt[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21]\n\t\t\t+ v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23];\n\t\tt[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31]\n\t\t\t+ v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32];\n\t\tt[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31]\n\t\t\t- v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32];\n\t\tt[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31]\n\t\t\t+ v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32];\n\t\tt[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21]\n\t\t\t- v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22];\n\t\tv[M00] = t[M00] * inv_det;\n\t\tv[M01] = t[M01] * inv_det;\n\t\tv[M02] = t[M02] * inv_det;\n\t\tv[M03] = t[M03] * inv_det;\n\t\tv[M10] = t[M10] * inv_det;\n\t\tv[M11] = t[M11] * inv_det;\n\t\tv[M12] = t[M12] * inv_det;\n\t\tv[M13] = t[M13] * inv_det;\n\t\tv[M20] = t[M20] * inv_det;\n\t\tv[M21] = t[M21] * inv_det;\n\t\tv[M22] = t[M22] * inv_det;\n\t\tv[M23] = t[M23] * inv_det;\n\t\tv[M30] = t[M30] * inv_det;\n\t\tv[M31] = t[M31] * inv_det;\n\t\tv[M32] = t[M32] * inv_det;\n\t\tv[M33] = t[M33] * inv_det;\n\t\treturn this;\n\t}\n\n\tdeterminant (): number {\n\t\tlet v = this.values;\n\t\treturn v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03]\n\t\t\t+ v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03]\n\t\t\t- v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13]\n\t\t\t- v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13]\n\t\t\t+ v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23]\n\t\t\t+ v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23]\n\t\t\t- v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33]\n\t\t\t- v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33];\n\t}\n\n\ttranslate (x: number, y: number, z: number): Matrix4 {\n\t\tlet v = this.values;\n\t\tv[M03] += x;\n\t\tv[M13] += y;\n\t\tv[M23] += z;\n\t\treturn this;\n\t}\n\n\tcopy (): Matrix4 {\n\t\treturn new Matrix4().set(this.values);\n\t}\n\n\tprojection (near: number, far: number, fovy: number, aspectRatio: number): Matrix4 {\n\t\tthis.identity();\n\t\tlet l_fd = (1.0 / Math.tan((fovy * (Math.PI / 180)) / 2.0));\n\t\tlet l_a1 = (far + near) / (near - far);\n\t\tlet l_a2 = (2 * far * near) / (near - far);\n\t\tlet v = this.values;\n\t\tv[M00] = l_fd / aspectRatio;\n\t\tv[M10] = 0;\n\t\tv[M20] = 0;\n\t\tv[M30] = 0;\n\t\tv[M01] = 0;\n\t\tv[M11] = l_fd;\n\t\tv[M21] = 0;\n\t\tv[M31] = 0;\n\t\tv[M02] = 0;\n\t\tv[M12] = 0;\n\t\tv[M22] = l_a1;\n\t\tv[M32] = -1;\n\t\tv[M03] = 0;\n\t\tv[M13] = 0;\n\t\tv[M23] = l_a2;\n\t\tv[M33] = 0;\n\t\treturn this;\n\t}\n\n\tortho2d (x: number, y: number, width: number, height: number): Matrix4 {\n\t\treturn this.ortho(x, x + width, y, y + height, 0, 1);\n\t}\n\n\tortho (left: number, right: number, bottom: number, top: number, near: number, far: number): Matrix4 {\n\t\tthis.identity();\n\t\tlet x_orth = 2 / (right - left);\n\t\tlet y_orth = 2 / (top - bottom);\n\t\tlet z_orth = -2 / (far - near);\n\n\t\tlet tx = -(right + left) / (right - left);\n\t\tlet ty = -(top + bottom) / (top - bottom);\n\t\tlet tz = -(far + near) / (far - near);\n\n\t\tlet v = this.values;\n\t\tv[M00] = x_orth;\n\t\tv[M10] = 0;\n\t\tv[M20] = 0;\n\t\tv[M30] = 0;\n\t\tv[M01] = 0;\n\t\tv[M11] = y_orth;\n\t\tv[M21] = 0;\n\t\tv[M31] = 0;\n\t\tv[M02] = 0;\n\t\tv[M12] = 0;\n\t\tv[M22] = z_orth;\n\t\tv[M32] = 0;\n\t\tv[M03] = tx;\n\t\tv[M13] = ty;\n\t\tv[M23] = tz;\n\t\tv[M33] = 1;\n\t\treturn this;\n\t}\n\n\tmultiply (matrix: Matrix4): Matrix4 {\n\t\tlet t = this.temp;\n\t\tlet v = this.values;\n\t\tlet m = matrix.values;\n\t\tt[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30];\n\t\tt[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31];\n\t\tt[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32];\n\t\tt[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33];\n\t\tt[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30];\n\t\tt[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31];\n\t\tt[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32];\n\t\tt[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33];\n\t\tt[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30];\n\t\tt[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31];\n\t\tt[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32];\n\t\tt[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33];\n\t\tt[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30];\n\t\tt[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31];\n\t\tt[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32];\n\t\tt[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33];\n\t\treturn this.set(this.temp);\n\t}\n\n\tmultiplyLeft (matrix: Matrix4): Matrix4 {\n\t\tlet t = this.temp;\n\t\tlet v = this.values;\n\t\tlet m = matrix.values;\n\t\tt[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30];\n\t\tt[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31];\n\t\tt[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32];\n\t\tt[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33];\n\t\tt[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30];\n\t\tt[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31];\n\t\tt[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32];\n\t\tt[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33];\n\t\tt[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30];\n\t\tt[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31];\n\t\tt[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32];\n\t\tt[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33];\n\t\tt[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30];\n\t\tt[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31];\n\t\tt[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32];\n\t\tt[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33];\n\t\treturn this.set(this.temp);\n\t}\n\n\tlookAt (position: Vector3, direction: Vector3, up: Vector3) {\n\t\tlet xAxis = Matrix4.xAxis, yAxis = Matrix4.yAxis, zAxis = Matrix4.zAxis;\n\t\tzAxis.setFrom(direction).normalize();\n\t\txAxis.setFrom(direction).normalize();\n\t\txAxis.cross(up).normalize();\n\t\tyAxis.setFrom(xAxis).cross(zAxis).normalize();\n\t\tthis.identity();\n\t\tlet val = this.values;\n\t\tval[M00] = xAxis.x;\n\t\tval[M01] = xAxis.y;\n\t\tval[M02] = xAxis.z;\n\t\tval[M10] = yAxis.x;\n\t\tval[M11] = yAxis.y;\n\t\tval[M12] = yAxis.z;\n\t\tval[M20] = -zAxis.x;\n\t\tval[M21] = -zAxis.y;\n\t\tval[M22] = -zAxis.z;\n\n\t\tMatrix4.tmpMatrix.identity();\n\t\tMatrix4.tmpMatrix.values[M03] = -position.x;\n\t\tMatrix4.tmpMatrix.values[M13] = -position.y;\n\t\tMatrix4.tmpMatrix.values[M23] = -position.z;\n\t\tthis.multiply(Matrix4.tmpMatrix)\n\n\t\treturn this;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Matrix4 } from \"./Matrix4.js\";\nimport { Vector3 } from \"./Vector3.js\";\n\nexport class OrthoCamera {\n\tposition = new Vector3(0, 0, 0);\n\tdirection = new Vector3(0, 0, -1);\n\tup = new Vector3(0, 1, 0);\n\tnear = 0;\n\tfar = 100;\n\tzoom = 1;\n\tviewportWidth = 0;\n\tviewportHeight = 0;\n\tprojectionView = new Matrix4();\n\tinverseProjectionView = new Matrix4();\n\tprojection = new Matrix4();\n\tview = new Matrix4();\n\n\tconstructor (viewportWidth: number, viewportHeight: number) {\n\t\tthis.viewportWidth = viewportWidth;\n\t\tthis.viewportHeight = viewportHeight;\n\t\tthis.update();\n\t}\n\n\tupdate () {\n\t\tlet projection = this.projection;\n\t\tlet view = this.view;\n\t\tlet projectionView = this.projectionView;\n\t\tlet inverseProjectionView = this.inverseProjectionView;\n\t\tlet zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight;\n\t\tprojection.ortho(zoom * (-viewportWidth / 2), zoom * (viewportWidth / 2),\n\t\t\tzoom * (-viewportHeight / 2), zoom * (viewportHeight / 2),\n\t\t\tthis.near, this.far);\n\t\tview.lookAt(this.position, this.direction, this.up);\n\t\tprojectionView.set(projection.values);\n\t\tprojectionView.multiply(view);\n\t\tinverseProjectionView.set(projectionView.values).invert();\n\t}\n\n\tscreenToWorld (screenCoords: Vector3, screenWidth: number, screenHeight: number) {\n\t\tlet x = screenCoords.x, y = screenHeight - screenCoords.y - 1;\n\t\tscreenCoords.x = (2 * x) / screenWidth - 1;\n\t\tscreenCoords.y = (2 * y) / screenHeight - 1;\n\t\tscreenCoords.z = (2 * screenCoords.z) - 1;\n\t\tscreenCoords.project(this.inverseProjectionView);\n\t\treturn screenCoords;\n\t}\n\n\tworldToScreen (worldCoords: Vector3, screenWidth: number, screenHeight: number) {\n\t\tworldCoords.project(this.projectionView);\n\t\tworldCoords.x = screenWidth * (worldCoords.x + 1) / 2;\n\t\tworldCoords.y = screenHeight * (worldCoords.y + 1) / 2;\n\t\tworldCoords.z = (worldCoords.z + 1) / 2;\n\t\treturn worldCoords;\n\t}\n\n\tsetViewport (viewportWidth: number, viewportHeight: number) {\n\t\tthis.viewportWidth = viewportWidth;\n\t\tthis.viewportHeight = viewportHeight;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nexport class Input {\n\telement: HTMLElement;\n\tmouseX = 0;\n\tmouseY = 0;\n\tbuttonDown = false;\n\ttouch0: Touch | null = null;\n\ttouch1: Touch | null = null;\n\tinitialPinchDistance = 0;\n\tprivate listeners = new Array();\n\tprivate eventListeners: Array<{ target: any, event: any, func: any }> = [];\n\n\tconstructor (element: HTMLElement) {\n\t\tthis.element = element;\n\t\tthis.setupCallbacks(element);\n\t}\n\n\tprivate setupCallbacks (element: HTMLElement) {\n\t\tlet mouseDown = (ev: UIEvent) => {\n\t\t\tif (ev instanceof MouseEvent) {\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tthis.mouseX = ev.clientX - rect.left;;\n\t\t\t\tthis.mouseY = ev.clientY - rect.top;\n\t\t\t\tthis.buttonDown = true;\n\t\t\t\tthis.listeners.map((listener) => { if (listener.down) listener.down(this.mouseX, this.mouseY); });\n\n\t\t\t\tdocument.addEventListener(\"mousemove\", mouseMove);\n\t\t\t\tdocument.addEventListener(\"mouseup\", mouseUp);\n\t\t\t}\n\t\t}\n\n\t\tlet mouseMove = (ev: UIEvent) => {\n\t\t\tif (ev instanceof MouseEvent) {\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tthis.mouseX = ev.clientX - rect.left;;\n\t\t\t\tthis.mouseY = ev.clientY - rect.top;\n\n\t\t\t\tthis.listeners.map((listener) => {\n\t\t\t\t\tif (this.buttonDown) {\n\t\t\t\t\t\tif (listener.dragged) listener.dragged(this.mouseX, this.mouseY);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (listener.moved) listener.moved(this.mouseX, this.mouseY);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tlet mouseUp = (ev: UIEvent) => {\n\t\t\tif (ev instanceof MouseEvent) {\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tthis.mouseX = ev.clientX - rect.left;;\n\t\t\t\tthis.mouseY = ev.clientY - rect.top;\n\t\t\t\tthis.buttonDown = false;\n\t\t\t\tthis.listeners.map((listener) => { if (listener.up) listener.up(this.mouseX, this.mouseY); });\n\n\t\t\t\tdocument.removeEventListener(\"mousemove\", mouseMove);\n\t\t\t\tdocument.removeEventListener(\"mouseup\", mouseUp);\n\t\t\t}\n\t\t}\n\n\t\tlet mouseWheel = (e: WheelEvent) => {\n\t\t\te.preventDefault();\n\t\t\tlet deltaY = e.deltaY;\n\t\t\tif (e.deltaMode == WheelEvent.DOM_DELTA_LINE) deltaY *= 8;\n\t\t\tif (e.deltaMode == WheelEvent.DOM_DELTA_PAGE) deltaY *= 24;\n\t\t\tthis.listeners.map((listener) => { if (listener.wheel) listener.wheel(e.deltaY); });\n\t\t};\n\n\t\telement.addEventListener(\"mousedown\", mouseDown, true);\n\t\telement.addEventListener(\"mousemove\", mouseMove, true);\n\t\telement.addEventListener(\"mouseup\", mouseUp, true);\n\t\telement.addEventListener(\"wheel\", mouseWheel, true);\n\n\n\t\telement.addEventListener(\"touchstart\", (ev: TouchEvent) => {\n\t\t\tif (!this.touch0 || !this.touch1) {\n\t\t\t\tvar touches = ev.changedTouches;\n\t\t\t\tlet nativeTouch = touches.item(0);\n\t\t\t\tif (!nativeTouch) return;\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tlet x = nativeTouch.clientX - rect.left;\n\t\t\t\tlet y = nativeTouch.clientY - rect.top;\n\t\t\t\tlet touch = new Touch(nativeTouch.identifier, x, y);\n\t\t\t\tthis.mouseX = x;\n\t\t\t\tthis.mouseY = y;\n\t\t\t\tthis.buttonDown = true;\n\n\t\t\t\tif (!this.touch0) {\n\t\t\t\t\tthis.touch0 = touch;\n\t\t\t\t\tthis.listeners.map((listener) => { if (listener.down) listener.down(touch.x, touch.y) })\n\t\t\t\t} else if (!this.touch1) {\n\t\t\t\t\tthis.touch1 = touch;\n\t\t\t\t\tlet dx = this.touch1.x - this.touch0.x;\n\t\t\t\t\tlet dy = this.touch1.x - this.touch0.x;\n\t\t\t\t\tthis.initialPinchDistance = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\t\tthis.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, this.initialPinchDistance) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tev.preventDefault();\n\t\t}, false);\n\n\t\telement.addEventListener(\"touchmove\", (ev: TouchEvent) => {\n\t\t\tif (this.touch0) {\n\t\t\t\tvar touches = ev.changedTouches;\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\t\t\t\tfor (var i = 0; i < touches.length; i++) {\n\t\t\t\t\tvar nativeTouch = touches[i];\n\t\t\t\t\tlet x = nativeTouch.clientX - rect.left;\n\t\t\t\t\tlet y = nativeTouch.clientY - rect.top;\n\n\t\t\t\t\tif (this.touch0.identifier === nativeTouch.identifier) {\n\t\t\t\t\t\tthis.touch0.x = this.mouseX = x;\n\t\t\t\t\t\tthis.touch0.y = this.mouseY = y;\n\t\t\t\t\t\tthis.listeners.map((listener) => { if (listener.dragged) listener.dragged(x, y) });\n\t\t\t\t\t}\n\t\t\t\t\tif (this.touch1 && this.touch1.identifier === nativeTouch.identifier) {\n\t\t\t\t\t\tthis.touch1.x = this.mouseX = x;\n\t\t\t\t\t\tthis.touch1.y = this.mouseY = y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.touch0 && this.touch1) {\n\t\t\t\t\tlet dx = this.touch1.x - this.touch0.x;\n\t\t\t\t\tlet dy = this.touch1.x - this.touch0.x;\n\t\t\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\t\tthis.listeners.map((listener) => { if (listener.zoom) listener.zoom(this.initialPinchDistance, distance) });\n\t\t\t\t}\n\t\t\t}\n\t\t\tev.preventDefault();\n\t\t}, false);\n\n\t\tlet touchEnd = (ev: TouchEvent) => {\n\t\t\tif (this.touch0) {\n\t\t\t\tvar touches = ev.changedTouches;\n\t\t\t\tlet rect = element.getBoundingClientRect();\n\n\t\t\t\tfor (var i = 0; i < touches.length; i++) {\n\t\t\t\t\tvar nativeTouch = touches[i];\n\t\t\t\t\tlet x = nativeTouch.clientX - rect.left;\n\t\t\t\t\tlet y = nativeTouch.clientY - rect.top;\n\n\t\t\t\t\tif (this.touch0.identifier === nativeTouch.identifier) {\n\t\t\t\t\t\tthis.touch0 = null;\n\t\t\t\t\t\tthis.mouseX = x;\n\t\t\t\t\t\tthis.mouseY = y;\n\t\t\t\t\t\tthis.listeners.map((listener) => { if (listener.up) listener.up(x, y) });\n\n\t\t\t\t\t\tif (!this.touch1) {\n\t\t\t\t\t\t\tthis.buttonDown = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.touch0 = this.touch1;\n\t\t\t\t\t\t\tthis.touch1 = null;\n\t\t\t\t\t\t\tthis.mouseX = this.touch0.x;\n\t\t\t\t\t\t\tthis.mouseX = this.touch0.x;\n\t\t\t\t\t\t\tthis.buttonDown = true;\n\t\t\t\t\t\t\tthis.listeners.map((listener) => { if (listener.down) listener.down(this.touch0!.x, this.touch0!.y) });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.touch1 && this.touch1.identifier) {\n\t\t\t\t\t\tthis.touch1 = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tev.preventDefault();\n\t\t};\n\t\telement.addEventListener(\"touchend\", touchEnd, false);\n\t\telement.addEventListener(\"touchcancel\", touchEnd);\n\t}\n\n\taddListener (listener: InputListener) {\n\t\tthis.listeners.push(listener);\n\t}\n\n\tremoveListener (listener: InputListener) {\n\t\tlet idx = this.listeners.indexOf(listener);\n\t\tif (idx > -1) {\n\t\t\tthis.listeners.splice(idx, 1);\n\t\t}\n\t}\n}\n\nexport class Touch {\n\tconstructor (public identifier: number, public x: number, public y: number) {\n\t}\n}\n\nexport interface InputListener {\n\tdown?(x: number, y: number): void;\n\tup?(x: number, y: number): void;\n\tmoved?(x: number, y: number): void;\n\tdragged?(x: number, y: number): void;\n\twheel?(delta: number): void;\n\tzoom?(initialDistance: number, distance: number): void;\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Input } from \"./Input.js\";\nimport { OrthoCamera } from \"./Camera.js\";\nimport { Vector3 } from \"./Vector3.js\";\n\nexport class CameraController {\n\tconstructor (public canvas: HTMLElement, public camera: OrthoCamera) {\n\t\tlet cameraX = 0, cameraY = 0, cameraZoom = 0;\n\t\tlet mouseX = 0, mouseY = 0;\n\t\tlet lastX = 0, lastY = 0;\n\t\tlet initialZoom = 0;\n\n\t\tnew Input(canvas).addListener({\n\t\t\tdown: (x: number, y: number) => {\n\t\t\t\tcameraX = camera.position.x;\n\t\t\t\tcameraY = camera.position.y;\n\t\t\t\tmouseX = lastX = x;\n\t\t\t\tmouseY = lastY = y;\n\t\t\t\tinitialZoom = camera.zoom;\n\t\t\t},\n\t\t\tdragged: (x: number, y: number) => {\n\t\t\t\tlet deltaX = x - mouseX;\n\t\t\t\tlet deltaY = y - mouseY;\n\t\t\t\tlet originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight);\n\t\t\t\tlet deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld);\n\t\t\t\tcamera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0);\n\t\t\t\tcamera.update();\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t},\n\t\t\twheel: (delta: number) => {\n\t\t\t\tlet zoomAmount = delta / 200 * camera.zoom;\n\t\t\t\tlet newZoom = camera.zoom + zoomAmount;\n\t\t\t\tif (newZoom > 0) {\n\t\t\t\t\tlet x = 0, y = 0;\n\t\t\t\t\tif (delta < 0) {\n\t\t\t\t\t\tx = lastX; y = lastY;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2);\n\t\t\t\t\t\tlet mouseToCenterX = lastX - viewCenter.x;\n\t\t\t\t\t\tlet mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y;\n\t\t\t\t\t\tx = viewCenter.x - mouseToCenterX;\n\t\t\t\t\t\ty = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY;\n\t\t\t\t\t}\n\t\t\t\t\tlet oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight);\n\t\t\t\t\tcamera.zoom = newZoom;\n\t\t\t\t\tcamera.update();\n\t\t\t\t\tlet newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight);\n\t\t\t\t\tcamera.position.add(oldDistance.sub(newDistance));\n\t\t\t\t\tcamera.update();\n\t\t\t\t}\n\t\t\t},\n\t\t\tzoom: (initialDistance, distance) => {\n\t\t\t\tlet newZoom = initialDistance / distance;\n\t\t\t\tcamera.zoom = initialZoom * newZoom;\n\t\t\t},\n\t\t\tup: (x: number, y: number) => {\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t},\n\t\t\tmoved: (x: number, y: number) => {\n\t\t\t\tlastX = x;\n\t\t\t\tlastY = y;\n\t\t\t},\n\t\t});\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Restorable } from \"@esotericsoftware/spine-core\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class Shader implements Disposable, Restorable {\n\tpublic static MVP_MATRIX = \"u_projTrans\";\n\tpublic static POSITION = \"a_position\";\n\tpublic static COLOR = \"a_color\";\n\tpublic static COLOR2 = \"a_color2\";\n\tpublic static TEXCOORDS = \"a_texCoords\";\n\tpublic static SAMPLER = \"u_texture\";\n\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate vs: WebGLShader | null = null;\n\tprivate vsSource: string;\n\tprivate fs: WebGLShader | null = null;\n\tprivate fsSource: string;\n\tprivate program: WebGLProgram | null = null;\n\tprivate tmp2x2: Float32Array = new Float32Array(2 * 2);\n\tprivate tmp3x3: Float32Array = new Float32Array(3 * 3);\n\tprivate tmp4x4: Float32Array = new Float32Array(4 * 4);\n\n\tpublic getProgram () { return this.program; }\n\tpublic getVertexShader () { return this.vertexShader; }\n\tpublic getFragmentShader () { return this.fragmentShader; }\n\tpublic getVertexShaderSource () { return this.vsSource; }\n\tpublic getFragmentSource () { return this.fsSource; }\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, private vertexShader: string, private fragmentShader: string) {\n\t\tthis.vsSource = vertexShader;\n\t\tthis.fsSource = fragmentShader;\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.context.addRestorable(this);\n\t\tthis.compile();\n\t}\n\n\tprivate compile () {\n\t\tlet gl = this.context.gl;\n\t\ttry {\n\t\t\tthis.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader);\n\t\t\tif (!this.vs) throw new Error(\"Couldn't compile vertex shader.\");\n\t\t\tthis.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader);\n\t\t\tif (!this.fs) throw new Error(\"Couldn#t compile fragment shader.\");\n\t\t\tthis.program = this.compileProgram(this.vs, this.fs);\n\t\t} catch (e) {\n\t\t\tthis.dispose();\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tprivate compileShader (type: number, source: string) {\n\t\tlet gl = this.context.gl;\n\t\tlet shader = gl.createShader(type);\n\t\tif (!shader) throw new Error(\"Couldn't create shader.\");\n\t\tgl.shaderSource(shader, source);\n\t\tgl.compileShader(shader);\n\t\tif (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n\t\t\tlet error = \"Couldn't compile shader: \" + gl.getShaderInfoLog(shader);\n\t\t\tgl.deleteShader(shader);\n\t\t\tif (!gl.isContextLost()) throw new Error(error);\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate compileProgram (vs: WebGLShader, fs: WebGLShader) {\n\t\tlet gl = this.context.gl;\n\t\tlet program = gl.createProgram();\n\t\tif (!program) throw new Error(\"Couldn't compile program.\");\n\t\tgl.attachShader(program, vs);\n\t\tgl.attachShader(program, fs);\n\t\tgl.linkProgram(program);\n\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tlet error = \"Couldn't compile shader program: \" + gl.getProgramInfoLog(program);\n\t\t\tgl.deleteProgram(program);\n\t\t\tif (!gl.isContextLost()) throw new Error(error);\n\t\t}\n\t\treturn program;\n\t}\n\n\trestore () {\n\t\tthis.compile();\n\t}\n\n\tpublic bind () {\n\t\tthis.context.gl.useProgram(this.program);\n\t}\n\n\tpublic unbind () {\n\t\tthis.context.gl.useProgram(null);\n\t}\n\n\tpublic setUniformi (uniform: string, value: number) {\n\t\tthis.context.gl.uniform1i(this.getUniformLocation(uniform), value);\n\t}\n\n\tpublic setUniformf (uniform: string, value: number) {\n\t\tthis.context.gl.uniform1f(this.getUniformLocation(uniform), value);\n\t}\n\n\tpublic setUniform2f (uniform: string, value: number, value2: number) {\n\t\tthis.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2);\n\t}\n\n\tpublic setUniform3f (uniform: string, value: number, value2: number, value3: number) {\n\t\tthis.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3);\n\t}\n\n\tpublic setUniform4f (uniform: string, value: number, value2: number, value3: number, value4: number) {\n\t\tthis.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4);\n\t}\n\n\tpublic setUniform2x2f (uniform: string, value: ArrayLike) {\n\t\tlet gl = this.context.gl;\n\t\tthis.tmp2x2.set(value);\n\t\tgl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2);\n\t}\n\n\tpublic setUniform3x3f (uniform: string, value: ArrayLike) {\n\t\tlet gl = this.context.gl;\n\t\tthis.tmp3x3.set(value);\n\t\tgl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3);\n\t}\n\n\tpublic setUniform4x4f (uniform: string, value: ArrayLike) {\n\t\tlet gl = this.context.gl;\n\t\tthis.tmp4x4.set(value);\n\t\tgl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4);\n\t}\n\n\tpublic getUniformLocation (uniform: string): WebGLUniformLocation | null {\n\t\tlet gl = this.context.gl;\n\t\tif (!this.program) throw new Error(\"Shader not compiled.\");\n\t\tlet location = gl.getUniformLocation(this.program, uniform);\n\t\tif (!location && !gl.isContextLost()) throw new Error(`Couldn't find location for uniform ${uniform}`);\n\t\treturn location;\n\t}\n\n\tpublic getAttributeLocation (attribute: string): number {\n\t\tlet gl = this.context.gl;\n\t\tif (!this.program) throw new Error(\"Shader not compiled.\");\n\t\tlet location = gl.getAttribLocation(this.program, attribute);\n\t\tif (location == -1 && !gl.isContextLost()) throw new Error(`Couldn't find location for attribute ${attribute}`);\n\t\treturn location;\n\t}\n\n\tpublic dispose () {\n\t\tthis.context.removeRestorable(this);\n\n\t\tlet gl = this.context.gl;\n\t\tif (this.vs) {\n\t\t\tgl.deleteShader(this.vs);\n\t\t\tthis.vs = null;\n\t\t}\n\n\t\tif (this.fs) {\n\t\t\tgl.deleteShader(this.fs);\n\t\t\tthis.fs = null;\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tgl.deleteProgram(this.program);\n\t\t\tthis.program = null;\n\t\t}\n\t}\n\n\tpublic static newColoredTextured (context: ManagedWebGLRenderingContext | WebGLRenderingContext): Shader {\n\t\tlet vs = `\nattribute vec4 ${Shader.POSITION};\nattribute vec4 ${Shader.COLOR};\nattribute vec2 ${Shader.TEXCOORDS};\nuniform mat4 ${Shader.MVP_MATRIX};\nvarying vec4 v_color;\nvarying vec2 v_texCoords;\n\nvoid main () {\n\tv_color = ${Shader.COLOR};\n\tv_texCoords = ${Shader.TEXCOORDS};\n\tgl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};\n}\n`;\n\n\t\tlet fs = `\n#ifdef GL_ES\n\t#define LOWP lowp\n\tprecision mediump float;\n#else\n\t#define LOWP\n#endif\nvarying LOWP vec4 v_color;\nvarying vec2 v_texCoords;\nuniform sampler2D u_texture;\n\nvoid main () {\n\tgl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n}\n`;\n\n\t\treturn new Shader(context, vs, fs);\n\t}\n\n\tpublic static newTwoColoredTextured (context: ManagedWebGLRenderingContext | WebGLRenderingContext): Shader {\n\t\tlet vs = `\nattribute vec4 ${Shader.POSITION};\nattribute vec4 ${Shader.COLOR};\nattribute vec4 ${Shader.COLOR2};\nattribute vec2 ${Shader.TEXCOORDS};\nuniform mat4 ${Shader.MVP_MATRIX};\nvarying vec4 v_light;\nvarying vec4 v_dark;\nvarying vec2 v_texCoords;\n\nvoid main () {\n\tv_light = ${Shader.COLOR};\n\tv_dark = ${Shader.COLOR2};\n\tv_texCoords = ${Shader.TEXCOORDS};\n\tgl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};\n}\n`;\n\n\t\tlet fs = `\n#ifdef GL_ES\n\t#define LOWP lowp\n\tprecision mediump float;\n#else\n\t#define LOWP\n#endif\nvarying LOWP vec4 v_light;\nvarying LOWP vec4 v_dark;\nvarying vec2 v_texCoords;\nuniform sampler2D u_texture;\n\nvoid main () {\n\tvec4 texColor = texture2D(u_texture, v_texCoords);\n\tgl_FragColor.a = texColor.a * v_light.a;\n\tgl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n}\n`;\n\n\t\treturn new Shader(context, vs, fs);\n\t}\n\n\tpublic static newColored (context: ManagedWebGLRenderingContext | WebGLRenderingContext): Shader {\n\t\tlet vs = `\nattribute vec4 ${Shader.POSITION};\nattribute vec4 ${Shader.COLOR};\nuniform mat4 ${Shader.MVP_MATRIX};\nvarying vec4 v_color;\n\nvoid main () {\n\tv_color = ${Shader.COLOR};\n\tgl_Position = ${Shader.MVP_MATRIX} * ${Shader.POSITION};\n}\n`;\n\n\t\tlet fs = `\n#ifdef GL_ES\n\t#define LOWP lowp\n\tprecision mediump float;\n#else\n\t#define LOWP\n#endif\nvarying LOWP vec4 v_color;\n\nvoid main () {\n\tgl_FragColor = v_color;\n}\n`;\n\n\t\treturn new Shader(context, vs, fs);\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Restorable } from \"@esotericsoftware/spine-core\";\nimport { Shader } from \"./Shader.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\n\nexport class Mesh implements Disposable, Restorable {\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate vertices: Float32Array;\n\tprivate verticesBuffer: WebGLBuffer | null = null;\n\tprivate verticesLength = 0;\n\tprivate dirtyVertices = false;\n\tprivate indices: Uint16Array;\n\tprivate indicesBuffer: WebGLBuffer | null = null;\n\tprivate indicesLength = 0;\n\tprivate dirtyIndices = false;\n\tprivate elementsPerVertex = 0;\n\n\tgetAttributes (): VertexAttribute[] { return this.attributes; }\n\n\tmaxVertices (): number { return this.vertices.length / this.elementsPerVertex; }\n\tnumVertices (): number { return this.verticesLength / this.elementsPerVertex; }\n\tsetVerticesLength (length: number) {\n\t\tthis.dirtyVertices = true;\n\t\tthis.verticesLength = length;\n\t}\n\tgetVertices (): Float32Array { return this.vertices; }\n\n\tmaxIndices (): number { return this.indices.length; }\n\tnumIndices (): number { return this.indicesLength; }\n\tsetIndicesLength (length: number) {\n\t\tthis.dirtyIndices = true;\n\t\tthis.indicesLength = length;\n\t}\n\tgetIndices (): Uint16Array { return this.indices };\n\n\tgetVertexSizeInFloats (): number {\n\t\tlet size = 0;\n\t\tfor (var i = 0; i < this.attributes.length; i++) {\n\t\t\tlet attribute = this.attributes[i];\n\t\t\tsize += attribute.numElements;\n\t\t}\n\t\treturn size;\n\t}\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, private attributes: VertexAttribute[], maxVertices: number, maxIndices: number) {\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.elementsPerVertex = 0;\n\t\tfor (let i = 0; i < attributes.length; i++) {\n\t\t\tthis.elementsPerVertex += attributes[i].numElements;\n\t\t}\n\t\tthis.vertices = new Float32Array(maxVertices * this.elementsPerVertex);\n\t\tthis.indices = new Uint16Array(maxIndices);\n\t\tthis.context.addRestorable(this);\n\t}\n\n\tsetVertices (vertices: Array) {\n\t\tthis.dirtyVertices = true;\n\t\tif (vertices.length > this.vertices.length) throw Error(\"Mesh can't store more than \" + this.maxVertices() + \" vertices\");\n\t\tthis.vertices.set(vertices, 0);\n\t\tthis.verticesLength = vertices.length;\n\t}\n\n\tsetIndices (indices: Array) {\n\t\tthis.dirtyIndices = true;\n\t\tif (indices.length > this.indices.length) throw Error(\"Mesh can't store more than \" + this.maxIndices() + \" indices\");\n\t\tthis.indices.set(indices, 0);\n\t\tthis.indicesLength = indices.length;\n\t}\n\n\tdraw (shader: Shader, primitiveType: number) {\n\t\tthis.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex);\n\t}\n\n\tdrawWithOffset (shader: Shader, primitiveType: number, offset: number, count: number) {\n\t\tlet gl = this.context.gl;\n\t\tif (this.dirtyVertices || this.dirtyIndices) this.update();\n\t\tthis.bind(shader);\n\t\tif (this.indicesLength > 0) {\n\t\t\tgl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2);\n\t\t} else {\n\t\t\tgl.drawArrays(primitiveType, offset, count);\n\t\t}\n\t\tthis.unbind(shader);\n\t}\n\n\tbind (shader: Shader) {\n\t\tlet gl = this.context.gl;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);\n\t\tlet offset = 0;\n\t\tfor (let i = 0; i < this.attributes.length; i++) {\n\t\t\tlet attrib = this.attributes[i];\n\t\t\tlet location = shader.getAttributeLocation(attrib.name);\n\t\t\tgl.enableVertexAttribArray(location);\n\t\t\tgl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4);\n\t\t\toffset += attrib.numElements;\n\t\t}\n\t\tif (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);\n\t}\n\n\tunbind (shader: Shader) {\n\t\tlet gl = this.context.gl;\n\t\tfor (let i = 0; i < this.attributes.length; i++) {\n\t\t\tlet attrib = this.attributes[i];\n\t\t\tlet location = shader.getAttributeLocation(attrib.name);\n\t\t\tgl.disableVertexAttribArray(location);\n\t\t}\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\tif (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\t}\n\n\tprivate update () {\n\t\tlet gl = this.context.gl;\n\t\tif (this.dirtyVertices) {\n\t\t\tif (!this.verticesBuffer) {\n\t\t\t\tthis.verticesBuffer = gl.createBuffer();\n\t\t\t}\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);\n\t\t\tgl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);\n\t\t\tthis.dirtyVertices = false;\n\t\t}\n\n\t\tif (this.dirtyIndices) {\n\t\t\tif (!this.indicesBuffer) {\n\t\t\t\tthis.indicesBuffer = gl.createBuffer();\n\t\t\t}\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);\n\t\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);\n\t\t\tthis.dirtyIndices = false;\n\t\t}\n\t}\n\n\trestore () {\n\t\tthis.verticesBuffer = null;\n\t\tthis.indicesBuffer = null;\n\t\tthis.update();\n\t}\n\n\tdispose () {\n\t\tthis.context.removeRestorable(this);\n\t\tlet gl = this.context.gl;\n\t\tgl.deleteBuffer(this.verticesBuffer);\n\t\tgl.deleteBuffer(this.indicesBuffer);\n\t}\n}\n\nexport class VertexAttribute {\n\tconstructor (public name: string, public type: VertexAttributeType, public numElements: number) { }\n}\n\nexport class Position2Attribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.POSITION, VertexAttributeType.Float, 2);\n\t}\n}\n\nexport class Position3Attribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.POSITION, VertexAttributeType.Float, 3);\n\t}\n}\n\nexport class TexCoordAttribute extends VertexAttribute {\n\tconstructor (unit: number = 0) {\n\t\tsuper(Shader.TEXCOORDS + (unit == 0 ? \"\" : unit), VertexAttributeType.Float, 2);\n\t}\n}\n\nexport class ColorAttribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.COLOR, VertexAttributeType.Float, 4);\n\t}\n}\n\nexport class Color2Attribute extends VertexAttribute {\n\tconstructor () {\n\t\tsuper(Shader.COLOR2, VertexAttributeType.Float, 4);\n\t}\n}\n\nexport enum VertexAttributeType {\n\tFloat\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BlendMode, Disposable } from \"@esotericsoftware/spine-core\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { Mesh, Position2Attribute, ColorAttribute, TexCoordAttribute, Color2Attribute } from \"./Mesh.js\";\nimport { Shader } from \"./Shader.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nconst GL_ONE = 1;\nconst GL_ONE_MINUS_SRC_COLOR = 0x0301;\nconst GL_SRC_ALPHA = 0x0302;\nconst GL_ONE_MINUS_SRC_ALPHA = 0x0303;\nconst GL_ONE_MINUS_DST_ALPHA = 0x0305;\nconst GL_DST_COLOR = 0x0306;\n\nexport class PolygonBatcher implements Disposable {\n\tpublic static disableCulling = false;\n\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate drawCalls = 0;\n\tprivate static globalDrawCalls = 0;\n\tisDrawing = false;\n\tprivate mesh: Mesh;\n\tprivate shader: Shader | null = null;\n\tprivate lastTexture: GLTexture | null = null;\n\tprivate verticesLength = 0;\n\tprivate indicesLength = 0;\n\tprivate srcColorBlend: number;\n\tprivate srcAlphaBlend: number;\n\tprivate dstBlend: number;\n\tprivate cullWasEnabled = false;\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true, maxVertices: number = 10920) {\n\t\tif (maxVertices > 10920) throw new Error(\"Can't have more than 10920 triangles per batch: \" + maxVertices);\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tlet attributes = twoColorTint ?\n\t\t\t[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] :\n\t\t\t[new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()];\n\t\tthis.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3);\n\t\tlet gl = this.context.gl;\n\t\tthis.srcColorBlend = gl.SRC_ALPHA;\n\t\tthis.srcAlphaBlend = gl.ONE;\n\t\tthis.dstBlend = gl.ONE_MINUS_SRC_ALPHA;\n\t}\n\n\tbegin (shader: Shader) {\n\t\tif (this.isDrawing) throw new Error(\"PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()\");\n\t\tthis.drawCalls = 0;\n\t\tthis.shader = shader;\n\t\tthis.lastTexture = null;\n\t\tthis.isDrawing = true;\n\n\t\tlet gl = this.context.gl;\n\t\tgl.enable(gl.BLEND);\n\t\tgl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);\n\n\t\tif (PolygonBatcher.disableCulling) {\n\t\t\tthis.cullWasEnabled = gl.isEnabled(gl.CULL_FACE);\n\t\t\tif (this.cullWasEnabled) gl.disable(gl.CULL_FACE);\n\t\t}\n\t}\n\n\tprivate static blendModesGL: { srcRgb: number, srcRgbPma: number, dstRgb: number, srcAlpha: number }[] = [\n\t\t{ srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },\n\t\t{ srcRgb: GL_SRC_ALPHA, srcRgbPma: GL_ONE, dstRgb: GL_ONE, srcAlpha: GL_ONE },\n\t\t{ srcRgb: GL_DST_COLOR, srcRgbPma: GL_DST_COLOR, dstRgb: GL_ONE_MINUS_SRC_ALPHA, srcAlpha: GL_ONE },\n\t\t{ srcRgb: GL_ONE, srcRgbPma: GL_ONE, dstRgb: GL_ONE_MINUS_SRC_COLOR, srcAlpha: GL_ONE }\n\t]\n\n\tsetBlendMode (blendMode: BlendMode, premultipliedAlpha: boolean) {\n\t\tconst blendModeGL = PolygonBatcher.blendModesGL[blendMode];\n\t\tconst srcColorBlend = premultipliedAlpha ? blendModeGL.srcRgbPma : blendModeGL.srcRgb;\n\t\tconst srcAlphaBlend = blendModeGL.srcAlpha;\n\t\tconst dstBlend = blendModeGL.dstRgb;\n\n\t\tif (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend) return;\n\t\tthis.srcColorBlend = srcColorBlend;\n\t\tthis.srcAlphaBlend = srcAlphaBlend;\n\t\tthis.dstBlend = dstBlend;\n\t\tif (this.isDrawing) {\n\t\t\tthis.flush();\n\t\t}\n\t\tlet gl = this.context.gl;\n\t\tgl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);\n\t}\n\n\tdraw (texture: GLTexture, vertices: ArrayLike, indices: Array) {\n\t\tif (texture != this.lastTexture) {\n\t\t\tthis.flush();\n\t\t\tthis.lastTexture = texture;\n\t\t} else if (this.verticesLength + vertices.length > this.mesh.getVertices().length ||\n\t\t\tthis.indicesLength + indices.length > this.mesh.getIndices().length) {\n\t\t\tthis.flush();\n\t\t}\n\n\t\tlet indexStart = this.mesh.numVertices();\n\t\tthis.mesh.getVertices().set(vertices, this.verticesLength);\n\t\tthis.verticesLength += vertices.length;\n\t\tthis.mesh.setVerticesLength(this.verticesLength)\n\n\t\tlet indicesArray = this.mesh.getIndices();\n\t\tfor (let i = this.indicesLength, j = 0; j < indices.length; i++, j++)\n\t\t\tindicesArray[i] = indices[j] + indexStart;\n\t\tthis.indicesLength += indices.length;\n\t\tthis.mesh.setIndicesLength(this.indicesLength);\n\t}\n\n\tflush () {\n\t\tif (this.verticesLength == 0) return;\n\t\tif (!this.lastTexture) throw new Error(\"No texture set.\");\n\t\tif (!this.shader) throw new Error(\"No shader set.\");\n\t\tthis.lastTexture.bind();\n\t\tthis.mesh.draw(this.shader, this.context.gl.TRIANGLES);\n\n\t\tthis.verticesLength = 0;\n\t\tthis.indicesLength = 0;\n\t\tthis.mesh.setVerticesLength(0);\n\t\tthis.mesh.setIndicesLength(0);\n\t\tthis.drawCalls++;\n\t\tPolygonBatcher.globalDrawCalls++;\n\t}\n\n\tend () {\n\t\tif (!this.isDrawing) throw new Error(\"PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()\");\n\t\tif (this.verticesLength > 0 || this.indicesLength > 0) this.flush();\n\t\tthis.shader = null;\n\t\tthis.lastTexture = null;\n\t\tthis.isDrawing = false;\n\n\t\tlet gl = this.context.gl;\n\t\tgl.disable(gl.BLEND);\n\t\tif (PolygonBatcher.disableCulling) {\n\t\t\tif (this.cullWasEnabled) gl.enable(gl.CULL_FACE);\n\t\t}\n\t}\n\n\tgetDrawCalls () {\n\t\treturn this.drawCalls;\n\t}\n\n\tstatic getAndResetGlobalDrawCalls () {\n\t\tlet result = PolygonBatcher.globalDrawCalls;\n\t\tPolygonBatcher.globalDrawCalls = 0;\n\t\treturn result;\n\t}\n\n\tdispose () {\n\t\tthis.mesh.dispose();\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Color, Vector2, MathUtils } from \"@esotericsoftware/spine-core\";\nimport { Mesh, Position2Attribute, ColorAttribute } from \"./Mesh.js\";\nimport { Shader } from \"./Shader.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class ShapeRenderer implements Disposable {\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate isDrawing = false;\n\tprivate mesh: Mesh;\n\tprivate shapeType = ShapeType.Filled;\n\tprivate color = new Color(1, 1, 1, 1);\n\tprivate shader: Shader | null = null;\n\tprivate vertexIndex = 0;\n\tprivate tmp = new Vector2();\n\tprivate srcColorBlend: number;\n\tprivate srcAlphaBlend: number;\n\tprivate dstBlend: number;\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext, maxVertices: number = 10920) {\n\t\tif (maxVertices > 10920) throw new Error(\"Can't have more than 10920 triangles per batch: \" + maxVertices);\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0);\n\t\tlet gl = this.context.gl;\n\t\tthis.srcColorBlend = gl.SRC_ALPHA;\n\t\tthis.srcAlphaBlend = gl.ONE;\n\t\tthis.dstBlend = gl.ONE_MINUS_SRC_ALPHA;\n\t}\n\n\tbegin (shader: Shader) {\n\t\tif (this.isDrawing) throw new Error(\"ShapeRenderer.begin() has already been called\");\n\t\tthis.shader = shader;\n\t\tthis.vertexIndex = 0;\n\t\tthis.isDrawing = true;\n\n\t\tlet gl = this.context.gl;\n\t\tgl.enable(gl.BLEND);\n\t\tgl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);\n\t}\n\n\tsetBlendMode (srcColorBlend: number, srcAlphaBlend: number, dstBlend: number) {\n\t\tthis.srcColorBlend = srcColorBlend;\n\t\tthis.srcAlphaBlend = srcAlphaBlend;\n\t\tthis.dstBlend = dstBlend;\n\t\tif (this.isDrawing) {\n\t\t\tthis.flush();\n\t\t\tlet gl = this.context.gl;\n\t\t\tgl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);\n\t\t}\n\t}\n\n\tsetColor (color: Color) {\n\t\tthis.color.setFromColor(color);\n\t}\n\n\tsetColorWith (r: number, g: number, b: number, a: number) {\n\t\tthis.color.set(r, g, b, a);\n\t}\n\n\tpoint (x: number, y: number, color?: Color) {\n\t\tthis.check(ShapeType.Point, 1);\n\t\tif (!color) color = this.color;\n\t\tthis.vertex(x, y, color);\n\t}\n\n\tline (x: number, y: number, x2: number, y2: number, color?: Color) {\n\t\tthis.check(ShapeType.Line, 2);\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\t\tif (!color) color = this.color;\n\t\tthis.vertex(x, y, color);\n\t\tthis.vertex(x2, y2, color);\n\t}\n\n\ttriangle (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, color?: Color, color2?: Color, color3?: Color) {\n\t\tthis.check(filled ? ShapeType.Filled : ShapeType.Line, 3);\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\t\tif (!color) color = this.color;\n\t\tif (!color2) color2 = this.color;\n\t\tif (!color3) color3 = this.color;\n\t\tif (filled) {\n\t\t\tthis.vertex(x, y, color);\n\t\t\tthis.vertex(x2, y2, color2);\n\t\t\tthis.vertex(x3, y3, color3);\n\t\t} else {\n\t\t\tthis.vertex(x, y, color);\n\t\t\tthis.vertex(x2, y2, color2);\n\n\t\t\tthis.vertex(x2, y2, color);\n\t\t\tthis.vertex(x3, y3, color2);\n\n\t\t\tthis.vertex(x3, y3, color);\n\t\t\tthis.vertex(x, y, color2);\n\t\t}\n\t}\n\n\tquad (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, color?: Color, color2?: Color, color3?: Color, color4?: Color) {\n\t\tthis.check(filled ? ShapeType.Filled : ShapeType.Line, 3);\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\t\tif (!color) color = this.color;\n\t\tif (!color2) color2 = this.color;\n\t\tif (!color3) color3 = this.color;\n\t\tif (!color4) color4 = this.color;\n\t\tif (filled) {\n\t\t\tthis.vertex(x, y, color); this.vertex(x2, y2, color2); this.vertex(x3, y3, color3);\n\t\t\tthis.vertex(x3, y3, color3); this.vertex(x4, y4, color4); this.vertex(x, y, color);\n\t\t} else {\n\t\t\tthis.vertex(x, y, color); this.vertex(x2, y2, color2);\n\t\t\tthis.vertex(x2, y2, color2); this.vertex(x3, y3, color3);\n\t\t\tthis.vertex(x3, y3, color3); this.vertex(x4, y4, color4);\n\t\t\tthis.vertex(x4, y4, color4); this.vertex(x, y, color);\n\t\t}\n\t}\n\n\trect (filled: boolean, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color);\n\t}\n\n\trectLine (filled: boolean, x1: number, y1: number, x2: number, y2: number, width: number, color?: Color) {\n\t\tthis.check(filled ? ShapeType.Filled : ShapeType.Line, 8);\n\t\tif (!color) color = this.color;\n\t\tlet t = this.tmp.set(y2 - y1, x1 - x2);\n\t\tt.normalize();\n\t\twidth *= 0.5;\n\t\tlet tx = t.x * width;\n\t\tlet ty = t.y * width;\n\t\tif (!filled) {\n\t\t\tthis.vertex(x1 + tx, y1 + ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\t\t\tthis.vertex(x2 - tx, y2 - ty, color);\n\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\t\t\tthis.vertex(x1 + tx, y1 + ty, color);\n\n\t\t\tthis.vertex(x2 - tx, y2 - ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t} else {\n\t\t\tthis.vertex(x1 + tx, y1 + ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\n\t\t\tthis.vertex(x2 - tx, y2 - ty, color);\n\t\t\tthis.vertex(x2 + tx, y2 + ty, color);\n\t\t\tthis.vertex(x1 - tx, y1 - ty, color);\n\t\t}\n\t}\n\n\tx (x: number, y: number, size: number) {\n\t\tthis.line(x - size, y - size, x + size, y + size);\n\t\tthis.line(x - size, y + size, x + size, y - size);\n\t}\n\n\tpolygon (polygonVertices: ArrayLike, offset: number, count: number, color?: Color) {\n\t\tif (count < 3) throw new Error(\"Polygon must contain at least 3 vertices\");\n\t\tthis.check(ShapeType.Line, count * 2);\n\t\tif (!color) color = this.color;\n\t\tlet vertices = this.mesh.getVertices();\n\t\tlet idx = this.vertexIndex;\n\n\t\toffset <<= 1;\n\t\tcount <<= 1;\n\n\t\tlet firstX = polygonVertices[offset];\n\t\tlet firstY = polygonVertices[offset + 1];\n\t\tlet last = offset + count;\n\n\t\tfor (let i = offset, n = offset + count - 2; i < n; i += 2) {\n\t\t\tlet x1 = polygonVertices[i];\n\t\t\tlet y1 = polygonVertices[i + 1];\n\n\t\t\tlet x2 = 0;\n\t\t\tlet y2 = 0;\n\n\t\t\tif (i + 2 >= last) {\n\t\t\t\tx2 = firstX;\n\t\t\t\ty2 = firstY;\n\t\t\t} else {\n\t\t\t\tx2 = polygonVertices[i + 2];\n\t\t\t\ty2 = polygonVertices[i + 3];\n\t\t\t}\n\n\t\t\tthis.vertex(x1, y1, color!);\n\t\t\tthis.vertex(x2, y2, color!);\n\t\t}\n\t}\n\n\tcircle (filled: boolean, x: number, y: number, radius: number, color?: Color, segments: number = 0) {\n\t\tif (segments == 0) segments = Math.max(1, (6 * MathUtils.cbrt(radius)) | 0);\n\t\tif (segments <= 0) throw new Error(\"segments must be > 0.\");\n\t\tif (!color) color = this.color;\n\t\tlet angle = 2 * MathUtils.PI / segments;\n\t\tlet cos = Math.cos(angle);\n\t\tlet sin = Math.sin(angle);\n\t\tlet cx = radius, cy = 0;\n\t\tif (!filled) {\n\t\t\tthis.check(ShapeType.Line, segments * 2 + 2);\n\t\t\tfor (let i = 0; i < segments; i++) {\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t\tlet temp = cx;\n\t\t\t\tcx = cos * cx - sin * cy;\n\t\t\t\tcy = sin * temp + cos * cy;\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t}\n\t\t\t// Ensure the last segment is identical to the first.\n\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t} else {\n\t\t\tthis.check(ShapeType.Filled, segments * 3 + 3);\n\t\t\tsegments--;\n\t\t\tfor (let i = 0; i < segments; i++) {\n\t\t\t\tthis.vertex(x, y, color);\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t\tlet temp = cx;\n\t\t\t\tcx = cos * cx - sin * cy;\n\t\t\t\tcy = sin * temp + cos * cy;\n\t\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t\t}\n\t\t\t// Ensure the last segment is identical to the first.\n\t\t\tthis.vertex(x, y, color);\n\t\t\tthis.vertex(x + cx, y + cy, color);\n\t\t}\n\n\t\tlet temp = cx;\n\t\tcx = radius;\n\t\tcy = 0;\n\t\tthis.vertex(x + cx, y + cy, color);\n\t}\n\n\tcurve (x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color) {\n\t\tthis.check(ShapeType.Line, segments * 2 + 2);\n\t\tif (!color) color = this.color;\n\n\t\t// Algorithm from: http://www.antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION\n\t\tlet subdiv_step = 1 / segments;\n\t\tlet subdiv_step2 = subdiv_step * subdiv_step;\n\t\tlet subdiv_step3 = subdiv_step * subdiv_step * subdiv_step;\n\n\t\tlet pre1 = 3 * subdiv_step;\n\t\tlet pre2 = 3 * subdiv_step2;\n\t\tlet pre4 = 6 * subdiv_step2;\n\t\tlet pre5 = 6 * subdiv_step3;\n\n\t\tlet tmp1x = x1 - cx1 * 2 + cx2;\n\t\tlet tmp1y = y1 - cy1 * 2 + cy2;\n\n\t\tlet tmp2x = (cx1 - cx2) * 3 - x1 + x2;\n\t\tlet tmp2y = (cy1 - cy2) * 3 - y1 + y2;\n\n\t\tlet fx = x1;\n\t\tlet fy = y1;\n\n\t\tlet dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;\n\t\tlet dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;\n\n\t\tlet ddfx = tmp1x * pre4 + tmp2x * pre5;\n\t\tlet ddfy = tmp1y * pre4 + tmp2y * pre5;\n\n\t\tlet dddfx = tmp2x * pre5;\n\t\tlet dddfy = tmp2y * pre5;\n\n\t\twhile (segments-- > 0) {\n\t\t\tthis.vertex(fx, fy, color!);\n\t\t\tfx += dfx;\n\t\t\tfy += dfy;\n\t\t\tdfx += ddfx;\n\t\t\tdfy += ddfy;\n\t\t\tddfx += dddfx;\n\t\t\tddfy += dddfy;\n\t\t\tthis.vertex(fx, fy, color!);\n\t\t}\n\t\tthis.vertex(fx, fy, color!);\n\t\tthis.vertex(x2, y2, color!);\n\t}\n\n\tprivate vertex (x: number, y: number, color: Color) {\n\t\tlet idx = this.vertexIndex;\n\t\tlet vertices = this.mesh.getVertices();\n\t\tvertices[idx++] = x;\n\t\tvertices[idx++] = y;\n\t\tvertices[idx++] = color.r;\n\t\tvertices[idx++] = color.g;\n\t\tvertices[idx++] = color.b;\n\t\tvertices[idx++] = color.a;\n\t\tthis.vertexIndex = idx;\n\t}\n\n\tend () {\n\t\tif (!this.isDrawing) throw new Error(\"ShapeRenderer.begin() has not been called\");\n\t\tthis.flush();\n\t\tlet gl = this.context.gl;\n\t\tgl.disable(gl.BLEND);\n\t\tthis.isDrawing = false;\n\t}\n\n\tprivate flush () {\n\t\tif (this.vertexIndex == 0) return;\n\t\tif (!this.shader) throw new Error(\"No shader set.\");\n\t\tthis.mesh.setVerticesLength(this.vertexIndex);\n\t\tthis.mesh.draw(this.shader, this.shapeType);\n\t\tthis.vertexIndex = 0;\n\t}\n\n\tprivate check (shapeType: ShapeType, numVertices: number) {\n\t\tif (!this.isDrawing) throw new Error(\"ShapeRenderer.begin() has not been called\");\n\t\tif (this.shapeType == shapeType) {\n\t\t\tif (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices) this.flush();\n\t\t\telse return;\n\t\t} else {\n\t\t\tthis.flush();\n\t\t\tthis.shapeType = shapeType;\n\t\t}\n\t}\n\n\tdispose () {\n\t\tthis.mesh.dispose();\n\t}\n}\n\nexport enum ShapeType {\n\tPoint = 0x0000,\n\tLine = 0x0001,\n\tFilled = 0x0004\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Disposable, Color, SkeletonBounds, Utils, Skeleton, RegionAttachment, MeshAttachment, PathAttachment, ClippingAttachment } from \"@esotericsoftware/spine-core\";\nimport { ShapeRenderer } from \"./ShapeRenderer.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\nexport class SkeletonDebugRenderer implements Disposable {\n\tboneLineColor = new Color(1, 0, 0, 1);\n\tboneOriginColor = new Color(0, 1, 0, 1);\n\tattachmentLineColor = new Color(0, 0, 1, 0.5);\n\ttriangleLineColor = new Color(1, 0.64, 0, 0.5);\n\tpathColor = new Color().setFromString(\"FF7F00\");\n\tclipColor = new Color(0.8, 0, 0, 2);\n\taabbColor = new Color(0, 1, 0, 0.5);\n\tdrawBones = true;\n\tdrawRegionAttachments = true;\n\tdrawBoundingBoxes = true;\n\tdrawMeshHull = true;\n\tdrawMeshTriangles = true;\n\tdrawPaths = true;\n\tdrawSkeletonXY = false;\n\tdrawClipping = true;\n\tpremultipliedAlpha = false;\n\tscale = 1;\n\tboneWidth = 2;\n\n\tprivate context: ManagedWebGLRenderingContext;\n\tprivate bounds = new SkeletonBounds();\n\tprivate temp = new Array();\n\tprivate vertices = Utils.newFloatArray(2 * 1024);\n\tprivate static LIGHT_GRAY = new Color(192 / 255, 192 / 255, 192 / 255, 1);\n\tprivate static GREEN = new Color(0, 1, 0, 1);\n\n\tconstructor (context: ManagedWebGLRenderingContext | WebGLRenderingContext) {\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t}\n\n\tdraw (shapes: ShapeRenderer, skeleton: Skeleton, ignoredBones?: Array) {\n\t\tlet skeletonX = skeleton.x;\n\t\tlet skeletonY = skeleton.y;\n\t\tlet gl = this.context.gl;\n\t\tlet srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA;\n\t\tshapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n\t\tlet bones = skeleton.bones;\n\t\tif (this.drawBones) {\n\t\t\tshapes.setColor(this.boneLineColor);\n\t\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\t\tlet bone = bones[i];\n\t\t\t\tif (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) continue;\n\t\t\t\tif (!bone.parent) continue;\n\t\t\t\tlet x = bone.data.length * bone.a + bone.worldX;\n\t\t\t\tlet y = bone.data.length * bone.c + bone.worldY;\n\t\t\t\tshapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale);\n\t\t\t}\n\t\t\tif (this.drawSkeletonXY) shapes.x(skeletonX, skeletonY, 4 * this.scale);\n\t\t}\n\n\t\tif (this.drawRegionAttachments) {\n\t\t\tshapes.setColor(this.attachmentLineColor);\n\t\t\tlet slots = skeleton.slots;\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\t\tlet regionAttachment = attachment;\n\t\t\t\t\tlet vertices = this.vertices;\n\t\t\t\t\tregionAttachment.computeWorldVertices(slot, vertices, 0, 2);\n\t\t\t\t\tshapes.line(vertices[0], vertices[1], vertices[2], vertices[3]);\n\t\t\t\t\tshapes.line(vertices[2], vertices[3], vertices[4], vertices[5]);\n\t\t\t\t\tshapes.line(vertices[4], vertices[5], vertices[6], vertices[7]);\n\t\t\t\t\tshapes.line(vertices[6], vertices[7], vertices[0], vertices[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawMeshHull || this.drawMeshTriangles) {\n\t\t\tlet slots = skeleton.slots;\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tif (!slot.bone.active) continue;\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (!(attachment instanceof MeshAttachment)) continue;\n\t\t\t\tlet mesh = attachment;\n\t\t\t\tlet vertices = this.vertices;\n\t\t\t\tmesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2);\n\t\t\t\tlet triangles = mesh.triangles;\n\t\t\t\tlet hullLength = mesh.hullLength;\n\t\t\t\tif (this.drawMeshTriangles) {\n\t\t\t\t\tshapes.setColor(this.triangleLineColor);\n\t\t\t\t\tfor (let ii = 0, nn = triangles.length; ii < nn; ii += 3) {\n\t\t\t\t\t\tlet v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2;\n\t\t\t\t\t\tshapes.triangle(false, vertices[v1], vertices[v1 + 1], //\n\t\t\t\t\t\t\tvertices[v2], vertices[v2 + 1], //\n\t\t\t\t\t\t\tvertices[v3], vertices[v3 + 1] //\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.drawMeshHull && hullLength > 0) {\n\t\t\t\t\tshapes.setColor(this.attachmentLineColor);\n\t\t\t\t\thullLength = (hullLength >> 1) * 2;\n\t\t\t\t\tlet lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1];\n\t\t\t\t\tfor (let ii = 0, nn = hullLength; ii < nn; ii += 2) {\n\t\t\t\t\t\tlet x = vertices[ii], y = vertices[ii + 1];\n\t\t\t\t\t\tshapes.line(x, y, lastX, lastY);\n\t\t\t\t\t\tlastX = x;\n\t\t\t\t\t\tlastY = y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawBoundingBoxes) {\n\t\t\tlet bounds = this.bounds;\n\t\t\tbounds.update(skeleton, true);\n\t\t\tshapes.setColor(this.aabbColor);\n\t\t\tshapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight());\n\t\t\tlet polygons = bounds.polygons;\n\t\t\tlet boxes = bounds.boundingBoxes;\n\t\t\tfor (let i = 0, n = polygons.length; i < n; i++) {\n\t\t\t\tlet polygon = polygons[i];\n\t\t\t\tshapes.setColor(boxes[i].color);\n\t\t\t\tshapes.polygon(polygon, 0, polygon.length);\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawPaths) {\n\t\t\tlet slots = skeleton.slots;\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tif (!slot.bone.active) continue;\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (!(attachment instanceof PathAttachment)) continue;\n\t\t\t\tlet path = attachment;\n\t\t\t\tlet nn = path.worldVerticesLength;\n\t\t\t\tlet world = this.temp = Utils.setArraySize(this.temp, nn, 0);\n\t\t\t\tpath.computeWorldVertices(slot, 0, nn, world, 0, 2);\n\t\t\t\tlet color = this.pathColor;\n\t\t\t\tlet x1 = world[2], y1 = world[3], x2 = 0, y2 = 0;\n\t\t\t\tif (path.closed) {\n\t\t\t\t\tshapes.setColor(color);\n\t\t\t\t\tlet cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1];\n\t\t\t\t\tx2 = world[nn - 4];\n\t\t\t\t\ty2 = world[nn - 3];\n\t\t\t\t\tshapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);\n\t\t\t\t\tshapes.setColor(SkeletonDebugRenderer.LIGHT_GRAY);\n\t\t\t\t\tshapes.line(x1, y1, cx1, cy1);\n\t\t\t\t\tshapes.line(x2, y2, cx2, cy2);\n\t\t\t\t}\n\t\t\t\tnn -= 4;\n\t\t\t\tfor (let ii = 4; ii < nn; ii += 6) {\n\t\t\t\t\tlet cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3];\n\t\t\t\t\tx2 = world[ii + 4];\n\t\t\t\t\ty2 = world[ii + 5];\n\t\t\t\t\tshapes.setColor(color);\n\t\t\t\t\tshapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);\n\t\t\t\t\tshapes.setColor(SkeletonDebugRenderer.LIGHT_GRAY);\n\t\t\t\t\tshapes.line(x1, y1, cx1, cy1);\n\t\t\t\t\tshapes.line(x2, y2, cx2, cy2);\n\t\t\t\t\tx1 = x2;\n\t\t\t\t\ty1 = y2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawBones) {\n\t\t\tshapes.setColor(this.boneOriginColor);\n\t\t\tfor (let i = 0, n = bones.length; i < n; i++) {\n\t\t\t\tlet bone = bones[i];\n\t\t\t\tif (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1) continue;\n\t\t\t\tshapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8);\n\t\t\t}\n\t\t}\n\n\t\tif (this.drawClipping) {\n\t\t\tlet slots = skeleton.slots;\n\t\t\tshapes.setColor(this.clipColor)\n\t\t\tfor (let i = 0, n = slots.length; i < n; i++) {\n\t\t\t\tlet slot = slots[i];\n\t\t\t\tif (!slot.bone.active) continue;\n\t\t\t\tlet attachment = slot.getAttachment();\n\t\t\t\tif (!(attachment instanceof ClippingAttachment)) continue;\n\t\t\t\tlet clip = attachment;\n\t\t\t\tlet nn = clip.worldVerticesLength;\n\t\t\t\tlet world = this.temp = Utils.setArraySize(this.temp, nn, 0);\n\t\t\t\tclip.computeWorldVertices(slot, 0, nn, world, 0, 2);\n\t\t\t\tfor (let i = 0, n = world.length; i < n; i += 2) {\n\t\t\t\t\tlet x = world[i];\n\t\t\t\t\tlet y = world[i + 1];\n\t\t\t\t\tlet x2 = world[(i + 2) % world.length];\n\t\t\t\t\tlet y2 = world[(i + 3) % world.length];\n\t\t\t\t\tshapes.line(x, y, x2, y2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdispose () {\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { NumberArrayLike, Color, SkeletonClipping, Vector2, Utils, Skeleton, BlendMode, RegionAttachment, TextureAtlasRegion, MeshAttachment, ClippingAttachment } from \"@esotericsoftware/spine-core\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { PolygonBatcher } from \"./PolygonBatcher.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n\n\nclass Renderable {\n\tconstructor (public vertices: NumberArrayLike, public numVertices: number, public numFloats: number) { }\n};\n\nexport type VertexTransformer = (vertices: NumberArrayLike, numVertices: number, stride: number) => void;\n\nexport class SkeletonRenderer {\n\tstatic QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];\n\n\tpremultipliedAlpha = false;\n\tprivate tempColor = new Color();\n\tprivate tempColor2 = new Color();\n\tprivate vertices: NumberArrayLike;\n\tprivate vertexSize = 2 + 2 + 4;\n\tprivate twoColorTint = false;\n\tprivate renderable: Renderable = new Renderable([], 0, 0);\n\tprivate clipper: SkeletonClipping = new SkeletonClipping();\n\tprivate temp = new Vector2();\n\tprivate temp2 = new Vector2();\n\tprivate temp3 = new Color();\n\tprivate temp4 = new Color();\n\n\tconstructor (context: ManagedWebGLRenderingContext, twoColorTint: boolean = true) {\n\t\tthis.twoColorTint = twoColorTint;\n\t\tif (twoColorTint)\n\t\t\tthis.vertexSize += 4;\n\t\tthis.vertices = Utils.newFloatArray(this.vertexSize * 1024);\n\t}\n\n\tdraw (batcher: PolygonBatcher, skeleton: Skeleton, slotRangeStart: number = -1, slotRangeEnd: number = -1, transformer: VertexTransformer | null = null) {\n\t\tlet clipper = this.clipper;\n\t\tlet premultipliedAlpha = this.premultipliedAlpha;\n\t\tlet twoColorTint = this.twoColorTint;\n\t\tlet blendMode: BlendMode | null = null;\n\n\t\tlet renderable: Renderable = this.renderable;\n\t\tlet uvs: NumberArrayLike;\n\t\tlet triangles: Array;\n\t\tlet drawOrder = skeleton.drawOrder;\n\t\tlet attachmentColor: Color;\n\t\tlet skeletonColor = skeleton.color;\n\t\tlet vertexSize = twoColorTint ? 12 : 8;\n\t\tlet inRange = false;\n\t\tif (slotRangeStart == -1) inRange = true;\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;\n\t\t\tlet slot = drawOrder[i];\n\t\t\tif (!slot.bone.active) {\n\t\t\t\tclipper.clipEndWithSlot(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (slotRangeStart >= 0 && slotRangeStart == slot.data.index) {\n\t\t\t\tinRange = true;\n\t\t\t}\n\n\t\t\tif (!inRange) {\n\t\t\t\tclipper.clipEndWithSlot(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) {\n\t\t\t\tinRange = false;\n\t\t\t}\n\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tlet texture: GLTexture;\n\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\tlet region = attachment;\n\t\t\t\trenderable.vertices = this.vertices;\n\t\t\t\trenderable.numVertices = 4;\n\t\t\t\trenderable.numFloats = clippedVertexSize << 2;\n\t\t\t\tregion.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize);\n\t\t\t\ttriangles = SkeletonRenderer.QUAD_TRIANGLES;\n\t\t\t\tuvs = region.uvs;\n\t\t\t\ttexture = region.region!.texture;\n\t\t\t\tattachmentColor = region.color;\n\t\t\t} else if (attachment instanceof MeshAttachment) {\n\t\t\t\tlet mesh = attachment;\n\t\t\t\trenderable.vertices = this.vertices;\n\t\t\t\trenderable.numVertices = (mesh.worldVerticesLength >> 1);\n\t\t\t\trenderable.numFloats = renderable.numVertices * clippedVertexSize;\n\t\t\t\tif (renderable.numFloats > renderable.vertices.length) {\n\t\t\t\t\trenderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats);\n\t\t\t\t}\n\t\t\t\tmesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);\n\t\t\t\ttriangles = mesh.triangles;\n\t\t\t\ttexture = mesh.region!.texture;\n\t\t\t\tuvs = mesh.uvs;\n\t\t\t\tattachmentColor = mesh.color;\n\t\t\t} else if (attachment instanceof ClippingAttachment) {\n\t\t\t\tlet clip = (attachment);\n\t\t\t\tclipper.clipStart(slot, clip);\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\tclipper.clipEndWithSlot(slot);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (texture) {\n\t\t\t\tlet slotColor = slot.color;\n\t\t\t\tlet finalColor = this.tempColor;\n\t\t\t\tfinalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r;\n\t\t\t\tfinalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g;\n\t\t\t\tfinalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b;\n\t\t\t\tfinalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;\n\t\t\t\tif (premultipliedAlpha) {\n\t\t\t\t\tfinalColor.r *= finalColor.a;\n\t\t\t\t\tfinalColor.g *= finalColor.a;\n\t\t\t\t\tfinalColor.b *= finalColor.a;\n\t\t\t\t}\n\t\t\t\tlet darkColor = this.tempColor2;\n\t\t\t\tif (!slot.darkColor)\n\t\t\t\t\tdarkColor.set(0, 0, 0, 1.0);\n\t\t\t\telse {\n\t\t\t\t\tif (premultipliedAlpha) {\n\t\t\t\t\t\tdarkColor.r = slot.darkColor.r * finalColor.a;\n\t\t\t\t\t\tdarkColor.g = slot.darkColor.g * finalColor.a;\n\t\t\t\t\t\tdarkColor.b = slot.darkColor.b * finalColor.a;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdarkColor.setFromColor(slot.darkColor);\n\t\t\t\t\t}\n\t\t\t\t\tdarkColor.a = premultipliedAlpha ? 1.0 : 0.0;\n\t\t\t\t}\n\n\t\t\t\tlet slotBlendMode = slot.data.blendMode;\n\t\t\t\tif (slotBlendMode != blendMode) {\n\t\t\t\t\tblendMode = slotBlendMode;\n\t\t\t\t\tbatcher.setBlendMode(blendMode, premultipliedAlpha);\n\t\t\t\t}\n\n\t\t\t\tif (clipper.isClipping()) {\n\t\t\t\t\tclipper.clipTriangles(renderable.vertices, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);\n\t\t\t\t\tlet clippedVertices = new Float32Array(clipper.clippedVertices);\n\t\t\t\t\tlet clippedTriangles = clipper.clippedTriangles;\n\t\t\t\t\tif (transformer) transformer(clippedVertices, clippedVertices.length, vertexSize);\n\t\t\t\t\tbatcher.draw(texture, clippedVertices, clippedTriangles);\n\t\t\t\t} else {\n\t\t\t\t\tlet verts = renderable.vertices;\n\t\t\t\t\tif (!twoColorTint) {\n\t\t\t\t\t\tfor (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) {\n\t\t\t\t\t\t\tverts[v] = finalColor.r;\n\t\t\t\t\t\t\tverts[v + 1] = finalColor.g;\n\t\t\t\t\t\t\tverts[v + 2] = finalColor.b;\n\t\t\t\t\t\t\tverts[v + 3] = finalColor.a;\n\t\t\t\t\t\t\tverts[v + 4] = uvs[u];\n\t\t\t\t\t\t\tverts[v + 5] = uvs[u + 1];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (let v = 2, u = 0, n = renderable.numFloats; v < n; v += vertexSize, u += 2) {\n\t\t\t\t\t\t\tverts[v] = finalColor.r;\n\t\t\t\t\t\t\tverts[v + 1] = finalColor.g;\n\t\t\t\t\t\t\tverts[v + 2] = finalColor.b;\n\t\t\t\t\t\t\tverts[v + 3] = finalColor.a;\n\t\t\t\t\t\t\tverts[v + 4] = uvs[u];\n\t\t\t\t\t\t\tverts[v + 5] = uvs[u + 1];\n\t\t\t\t\t\t\tverts[v + 6] = darkColor.r;\n\t\t\t\t\t\t\tverts[v + 7] = darkColor.g;\n\t\t\t\t\t\t\tverts[v + 8] = darkColor.b;\n\t\t\t\t\t\t\tverts[v + 9] = darkColor.a;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tlet view = (renderable.vertices as Float32Array).subarray(0, renderable.numFloats);\n\t\t\t\t\tif (transformer) transformer(renderable.vertices, renderable.numFloats, vertexSize);\n\t\t\t\t\tbatcher.draw(texture, view, triangles);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclipper.clipEndWithSlot(slot);\n\t\t}\n\t\tclipper.clipEnd();\n\t}\n\n\t/** Returns the {@link SkeletonClipping} used by this renderer for use with e.g. {@link Skeleton.getBounds} **/\n\tpublic getSkeletonClipping (): SkeletonClipping {\n\t\treturn this.clipper;\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Color, Disposable, Skeleton, MathUtils, TextureAtlasRegion } from \"@esotericsoftware/spine-core\";\nimport { OrthoCamera } from \"./Camera.js\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { PolygonBatcher } from \"./PolygonBatcher.js\";\nimport { Shader } from \"./Shader.js\";\nimport { ShapeRenderer } from \"./ShapeRenderer.js\";\nimport { SkeletonDebugRenderer } from \"./SkeletonDebugRenderer.js\";\nimport { SkeletonRenderer, VertexTransformer } from \"./SkeletonRenderer.js\";\nimport { ManagedWebGLRenderingContext } from \"./WebGL.js\";\n;\n\nconst quad = [\n\t0, 0, 1, 1, 1, 1, 0, 0,\n\t0, 0, 1, 1, 1, 1, 0, 0,\n\t0, 0, 1, 1, 1, 1, 0, 0,\n\t0, 0, 1, 1, 1, 1, 0, 0,\n];\nconst QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];\nconst WHITE = new Color(1, 1, 1, 1);\n\nexport class SceneRenderer implements Disposable {\n\tcontext: ManagedWebGLRenderingContext;\n\tcanvas: HTMLCanvasElement;\n\tcamera: OrthoCamera;\n\tbatcher: PolygonBatcher;\n\tprivate twoColorTint = false;\n\tprivate batcherShader: Shader;\n\tprivate shapes: ShapeRenderer;\n\tprivate shapesShader: Shader;\n\tprivate activeRenderer: PolygonBatcher | ShapeRenderer | SkeletonDebugRenderer | null = null;\n\tskeletonRenderer: SkeletonRenderer;\n\tskeletonDebugRenderer: SkeletonDebugRenderer;\n\n\tconstructor (canvas: HTMLCanvasElement, context: ManagedWebGLRenderingContext | WebGLRenderingContext, twoColorTint: boolean = true) {\n\t\tthis.canvas = canvas;\n\t\tthis.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);\n\t\tthis.twoColorTint = twoColorTint;\n\t\tthis.camera = new OrthoCamera(canvas.width, canvas.height);\n\t\tthis.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context);\n\t\tthis.batcher = new PolygonBatcher(this.context, twoColorTint);\n\t\tthis.shapesShader = Shader.newColored(this.context);\n\t\tthis.shapes = new ShapeRenderer(this.context);\n\t\tthis.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint);\n\t\tthis.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context);\n\t}\n\n\tdispose () {\n\t\tthis.batcher.dispose();\n\t\tthis.batcherShader.dispose();\n\t\tthis.shapes.dispose();\n\t\tthis.shapesShader.dispose();\n\t\tthis.skeletonDebugRenderer.dispose();\n\t}\n\n\tbegin () {\n\t\tthis.camera.update();\n\t\tthis.enableRenderer(this.batcher);\n\t}\n\n\tdrawSkeleton (skeleton: Skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform: VertexTransformer | null = null) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tthis.skeletonRenderer.premultipliedAlpha = premultipliedAlpha;\n\t\tthis.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform);\n\t}\n\n\tdrawSkeletonDebug (skeleton: Skeleton, premultipliedAlpha = false, ignoredBones?: Array) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha;\n\t\tthis.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones);\n\t}\n\n\tdrawTexture (texture: GLTexture, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\t\tvar i = 0;\n\t\tquad[i++] = x;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tdrawTextureUV (texture: GLTexture, x: number, y: number, width: number, height: number, u: number, v: number, u2: number, v2: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\t\tvar i = 0;\n\t\tquad[i++] = x;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u;\n\t\tquad[i++] = v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u2;\n\t\tquad[i++] = v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u2;\n\t\tquad[i++] = v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = u;\n\t\tquad[i++] = v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tdrawTextureRotated (texture: GLTexture, x: number, y: number, width: number, height: number, pivotX: number, pivotY: number, angle: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\n\t\t// bottom left and top right corner points relative to origin\n\t\tlet worldOriginX = x + pivotX;\n\t\tlet worldOriginY = y + pivotY;\n\t\tlet fx = -pivotX;\n\t\tlet fy = -pivotY;\n\t\tlet fx2 = width - pivotX;\n\t\tlet fy2 = height - pivotY;\n\n\t\t// construct corner points, start from top left and go counter clockwise\n\t\tlet p1x = fx;\n\t\tlet p1y = fy;\n\t\tlet p2x = fx;\n\t\tlet p2y = fy2;\n\t\tlet p3x = fx2;\n\t\tlet p3y = fy2;\n\t\tlet p4x = fx2;\n\t\tlet p4y = fy;\n\n\t\tlet x1 = 0;\n\t\tlet y1 = 0;\n\t\tlet x2 = 0;\n\t\tlet y2 = 0;\n\t\tlet x3 = 0;\n\t\tlet y3 = 0;\n\t\tlet x4 = 0;\n\t\tlet y4 = 0;\n\n\t\t// rotate\n\t\tif (angle != 0) {\n\t\t\tlet cos = MathUtils.cosDeg(angle);\n\t\t\tlet sin = MathUtils.sinDeg(angle);\n\n\t\t\tx1 = cos * p1x - sin * p1y;\n\t\t\ty1 = sin * p1x + cos * p1y;\n\n\t\t\tx4 = cos * p2x - sin * p2y;\n\t\t\ty4 = sin * p2x + cos * p2y;\n\n\t\t\tx3 = cos * p3x - sin * p3y;\n\t\t\ty3 = sin * p3x + cos * p3y;\n\n\t\t\tx2 = x3 + (x1 - x4);\n\t\t\ty2 = y3 + (y1 - y4);\n\t\t} else {\n\t\t\tx1 = p1x;\n\t\t\ty1 = p1y;\n\n\t\t\tx4 = p2x;\n\t\t\ty4 = p2y;\n\n\t\t\tx3 = p3x;\n\t\t\ty3 = p3y;\n\n\t\t\tx2 = p4x;\n\t\t\ty2 = p4y;\n\t\t}\n\n\t\tx1 += worldOriginX;\n\t\ty1 += worldOriginY;\n\t\tx2 += worldOriginX;\n\t\ty2 += worldOriginY;\n\t\tx3 += worldOriginX;\n\t\ty3 += worldOriginY;\n\t\tx4 += worldOriginX;\n\t\ty4 += worldOriginY;\n\n\t\tvar i = 0;\n\t\tquad[i++] = x1;\n\t\tquad[i++] = y1;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x2;\n\t\tquad[i++] = y2;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 1;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x3;\n\t\tquad[i++] = y3;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 1;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x4;\n\t\tquad[i++] = y4;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = 0;\n\t\tquad[i++] = 0;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tdrawRegion (region: TextureAtlasRegion, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.enableRenderer(this.batcher);\n\t\tif (!color) color = WHITE;\n\t\tvar i = 0;\n\t\tquad[i++] = x;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u;\n\t\tquad[i++] = region.v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u2;\n\t\tquad[i++] = region.v2;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x + width;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u2;\n\t\tquad[i++] = region.v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t}\n\t\tquad[i++] = x;\n\t\tquad[i++] = y + height;\n\t\tquad[i++] = color.r;\n\t\tquad[i++] = color.g;\n\t\tquad[i++] = color.b;\n\t\tquad[i++] = color.a;\n\t\tquad[i++] = region.u;\n\t\tquad[i++] = region.v;\n\t\tif (this.twoColorTint) {\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i++] = 0;\n\t\t\tquad[i] = 0;\n\t\t}\n\t\tthis.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES);\n\t}\n\n\tline (x: number, y: number, x2: number, y2: number, color?: Color, color2?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.line(x, y, x2, y2, color);\n\t}\n\n\ttriangle (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, color?: Color, color2?: Color, color3?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3);\n\t}\n\n\tquad (filled: boolean, x: number, y: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, color?: Color, color2?: Color, color3?: Color, color4?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4);\n\t}\n\n\trect (filled: boolean, x: number, y: number, width: number, height: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.rect(filled, x, y, width, height, color);\n\t}\n\n\trectLine (filled: boolean, x1: number, y1: number, x2: number, y2: number, width: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.rectLine(filled, x1, y1, x2, y2, width, color);\n\t}\n\n\tpolygon (polygonVertices: ArrayLike, offset: number, count: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.polygon(polygonVertices, offset, count, color);\n\t}\n\n\tcircle (filled: boolean, x: number, y: number, radius: number, color?: Color, segments: number = 0) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.circle(filled, x, y, radius, color, segments);\n\t}\n\n\tcurve (x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, segments: number, color?: Color) {\n\t\tthis.enableRenderer(this.shapes);\n\t\tthis.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color);\n\t}\n\n\tend () {\n\t\tif (this.activeRenderer === this.batcher) this.batcher.end();\n\t\telse if (this.activeRenderer === this.shapes) this.shapes.end();\n\t\tthis.activeRenderer = null;\n\t}\n\n\tresize (resizeMode: ResizeMode) {\n\t\tlet canvas = this.canvas;\n\t\tvar dpr = window.devicePixelRatio || 1;\n\t\tvar w = Math.round(canvas.clientWidth * dpr);\n\t\tvar h = Math.round(canvas.clientHeight * dpr);\n\n\t\tif (canvas.width != w || canvas.height != h) {\n\t\t\tcanvas.width = w;\n\t\t\tcanvas.height = h;\n\t\t}\n\t\tthis.context.gl.viewport(0, 0, canvas.width, canvas.height);\n\n\t\t// Nothing to do for stretch, we simply apply the viewport size of the camera.\n\t\tif (resizeMode === ResizeMode.Expand)\n\t\t\tthis.camera.setViewport(w, h);\n\t\telse if (resizeMode === ResizeMode.Fit) {\n\t\t\tlet sourceWidth = canvas.width, sourceHeight = canvas.height;\n\t\t\tlet targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight;\n\t\t\tlet targetRatio = targetHeight / targetWidth;\n\t\t\tlet sourceRatio = sourceHeight / sourceWidth;\n\t\t\tlet scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight;\n\t\t\tthis.camera.setViewport(sourceWidth * scale, sourceHeight * scale);\n\t\t}\n\t\tthis.camera.update();\n\t}\n\n\tprivate enableRenderer (renderer: PolygonBatcher | ShapeRenderer | SkeletonDebugRenderer) {\n\t\tif (this.activeRenderer === renderer) return;\n\t\tthis.end();\n\t\tif (renderer instanceof PolygonBatcher) {\n\t\t\tthis.batcherShader.bind();\n\t\t\tthis.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values);\n\t\t\tthis.batcherShader.setUniformi(\"u_texture\", 0);\n\t\t\tthis.batcher.begin(this.batcherShader);\n\t\t\tthis.activeRenderer = this.batcher;\n\t\t} else if (renderer instanceof ShapeRenderer) {\n\t\t\tthis.shapesShader.bind();\n\t\t\tthis.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values);\n\t\t\tthis.shapes.begin(this.shapesShader);\n\t\t\tthis.activeRenderer = this.shapes;\n\t\t} else\n\t\t\tthis.activeRenderer = this.skeletonDebugRenderer;\n\t}\n}\n\nexport enum ResizeMode {\n\tStretch,\n\tExpand,\n\tFit\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { BlendMode, Color, Disposable, TimeKeeper } from \"@esotericsoftware/spine-core\";\nimport { GLTexture } from \"./GLTexture.js\";\nimport { ResizeMode, SceneRenderer } from \"./SceneRenderer.js\";\n\nlet spinnerImage: HTMLImageElement;\nlet logoImage: HTMLImageElement;\nlet loaded = 0;\n\nconst FADE_IN = 1, FADE_OUT = 1;\nconst logoWidth = 165, logoHeight = 108, spinnerSize = 163;\n\nexport class LoadingScreen implements Disposable {\n\tprivate renderer: SceneRenderer;\n\tprivate logo: GLTexture | null = null;\n\tprivate spinner: GLTexture | null = null;\n\tprivate angle = 0;\n\tprivate fadeOut = 0;\n\tprivate fadeIn = 0;\n\tprivate timeKeeper = new TimeKeeper();\n\tbackgroundColor = new Color(0.135, 0.135, 0.135, 1);\n\tprivate tempColor = new Color();\n\n\tconstructor (renderer: SceneRenderer) {\n\t\tthis.renderer = renderer;\n\n\t\tthis.timeKeeper.maxDelta = 9;\n\n\t\tif (!logoImage) {\n\t\t\tlet isSafari = navigator.userAgent.indexOf(\"Safari\") > -1; // Thank you Apple Inc.\n\t\t\tlet onload = () => loaded++;\n\n\t\t\tlogoImage = new Image();\n\t\t\tlogoImage.src = SPINE_LOGO_DATA;\n\t\t\tif (!isSafari) logoImage.crossOrigin = \"anonymous\";\n\t\t\tlogoImage.onload = onload;\n\n\t\t\tspinnerImage = new Image();\n\t\t\tspinnerImage.src = SPINNER_DATA;\n\t\t\tif (!isSafari) spinnerImage.crossOrigin = \"anonymous\";\n\t\t\tspinnerImage.onload = onload;\n\t\t}\n\t}\n\tdispose (): void {\n\t\tthis.logo?.dispose();\n\t\tthis.spinner?.dispose();\n\t}\n\n\tdraw (complete = false) {\n\t\tif (loaded < 2 || (complete && this.fadeOut > FADE_OUT)) return;\n\n\t\tthis.timeKeeper.update();\n\t\tlet a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25));\n\t\tthis.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5));\n\n\t\tlet tempColor = this.tempColor;\n\t\tlet renderer = this.renderer;\n\t\tlet canvas = renderer.canvas;\n\t\tlet gl = renderer.context.gl;\n\n\t\trenderer.resize(ResizeMode.Expand);\n\t\trenderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0);\n\t\trenderer.batcher.setBlendMode(BlendMode.Normal, true);\n\n\t\tif (complete) {\n\t\t\tthis.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1);\n\t\t\tif (this.fadeOut > FADE_OUT) return;\n\t\t\ttempColor.setFromColor(this.backgroundColor);\n\t\t\ta = 1 - this.fadeOut / FADE_OUT;\n\t\t\ta = 1 - (a - 1) * (a - 1);\n\t\t\ttempColor.a *= a;\n\t\t\tif (tempColor.a > 0) {\n\t\t\t\trenderer.camera.zoom = 1;\n\t\t\t\trenderer.begin();\n\t\t\t\trenderer.quad(true, 0, 0, canvas.width, 0, canvas.width, canvas.height, 0, canvas.height,\n\t\t\t\t\ttempColor, tempColor, tempColor, tempColor);\n\t\t\t\trenderer.end();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.fadeIn += this.timeKeeper.delta;\n\t\t\tif (this.backgroundColor.a > 0) {\n\t\t\t\tgl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a);\n\t\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\t}\n\t\t\ta = 1;\n\t\t}\n\t\ta *= Math.min(this.fadeIn / FADE_IN, 1);\n\t\ttempColor.set(a, a, a, a);\n\n\t\tif (!this.logo) {\n\t\t\tthis.logo = new GLTexture(renderer.context, logoImage);\n\t\t\tthis.spinner = new GLTexture(renderer.context, spinnerImage);\n\t\t}\n\t\trenderer.camera.zoom = Math.max(1, spinnerSize / canvas.height);\n\t\trenderer.begin();\n\t\trenderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor);\n\t\tif (this.spinner) renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor);\n\t\trenderer.end();\n\t}\n}\n\nlet SPINNER_DATA = \"data:image/png;base64,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\";\n\nlet SPINE_LOGO_DATA = \"data:image/png;base64,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\";\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { TimeKeeper, AssetManager, ManagedWebGLRenderingContext, SceneRenderer, Input, StringMap } from \"./index.js\";\n\n/** An app running inside a {@link SpineCanvas}. The app life-cycle\n * is as follows:\n *\n * 1. `loadAssets()` is called. The app can queue assets for loading via {@link SpineCanvas.assetManager}.\n * 2. `initialize()` is called when all assets are loaded. The app can setup anything it needs to enter the main application logic.\n * 3. `update()` is called periodically at screen refresh rate. The app can update its state.\n * 4. `render()` is called periodically at screen refresh rate. The app can render its state via {@link SpineCanvas.renderer} or directly via the WebGL context in {@link SpineCanvas.gl}.\n *\n * The `error()` method is called in case the assets could not be loaded. The `dispose()` method is called in case the canvas has been disposed via {@link SpineCanvas.dispose}.\n */\nexport interface SpineCanvasApp {\n\tloadAssets?(canvas: SpineCanvas): void;\n\tinitialize?(canvas: SpineCanvas): void;\n\tupdate?(canvas: SpineCanvas, delta: number): void;\n\trender?(canvas: SpineCanvas): void;\n\terror?(canvas: SpineCanvas, errors: StringMap): void;\n\tdispose?(canvas: SpineCanvas): void;\n}\n\n/** Configuration passed to the {@link SpineCanvas} constructor */\nexport interface SpineCanvasConfig {\n\t/* The {@link SpineCanvasApp} to be run in the canvas. */\n\tapp: SpineCanvasApp;\n\t/* The path prefix to be used by the {@link AssetManager}. */\n\tpathPrefix?: string;\n\t/* The WebGL context configuration */\n\twebglConfig?: any;\n}\n\n/** Manages the life-cycle and WebGL context of a {@link SpineCanvasApp}. The app loads\n * assets and initializes itself, then updates and renders its state at the screen refresh rate. */\nexport class SpineCanvas {\n\treadonly context: ManagedWebGLRenderingContext;\n\n\t/** Tracks the current time, delta, and other time related statistics. */\n\treadonly time = new TimeKeeper();\n\t/** The HTML canvas to render to. */\n\treadonly htmlCanvas: HTMLCanvasElement;\n\t/** The WebGL rendering context. */\n\treadonly gl: WebGLRenderingContext;\n\t/** The scene renderer for easy drawing of skeletons, shapes, and images. */\n\treadonly renderer: SceneRenderer;\n\t/** The asset manager to load assets with. */\n\treadonly assetManager: AssetManager;\n\t/** The input processor used to listen to mouse, touch, and keyboard events. */\n\treadonly input: Input;\n\n\tprivate disposed = false;\n\n\t/** Constructs a new spine canvas, rendering to the provided HTML canvas. */\n\tconstructor (canvas: HTMLCanvasElement, private config: SpineCanvasConfig) {\n\t\tif (!config.pathPrefix) config.pathPrefix = \"\";\n\t\tif (!config.app) config.app = {\n\t\t\tloadAssets: () => { },\n\t\t\tinitialize: () => { },\n\t\t\tupdate: () => { },\n\t\t\trender: () => { },\n\t\t\terror: () => { },\n\t\t\tdispose: () => { },\n\t\t}\n\t\tif (!config.webglConfig) config.webglConfig = { alpha: true };\n\n\t\tthis.htmlCanvas = canvas;\n\t\tthis.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig);\n\t\tthis.renderer = new SceneRenderer(canvas, this.context);\n\t\tthis.gl = this.context.gl;\n\t\tthis.assetManager = new AssetManager(this.context, config.pathPrefix);\n\t\tthis.input = new Input(canvas);\n\n\t\tif (config.app.loadAssets) config.app.loadAssets(this);\n\n\t\tlet loop = () => {\n\t\t\tif (this.disposed) return;\n\t\t\trequestAnimationFrame(loop);\n\t\t\tthis.time.update();\n\t\t\tif (config.app.update) config.app.update(this, this.time.delta);\n\t\t\tif (config.app.render) config.app.render(this);\n\t\t}\n\n\t\tlet waitForAssets = () => {\n\t\t\tif (this.disposed) return;\n\t\t\tif (this.assetManager.isLoadingComplete()) {\n\t\t\t\tif (this.assetManager.hasErrors()) {\n\t\t\t\t\tif (config.app.error) config.app.error(this, this.assetManager.getErrors());\n\t\t\t\t} else {\n\t\t\t\t\tif (config.app.initialize) config.app.initialize(this);\n\t\t\t\t\tloop();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\trequestAnimationFrame(waitForAssets);\n\t\t}\n\t\trequestAnimationFrame(waitForAssets);\n\t}\n\n\t/** Clears the canvas with the given color. The color values are given in the range [0,1]. */\n\tclear (r: number, g: number, b: number, a: number) {\n\t\tthis.gl.clearColor(r, g, b, a);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\t}\n\n\t/** Disposes the app, so the update() and render() functions are no longer called. Calls the dispose() callback.*/\n\tdispose () {\n\t\tif (this.config.app.dispose) this.config.app.dispose(this);\n\t\tthis.disposed = true;\n\t}\n}\n", "/*\nThe MIT License (MIT)\n\nCopyright (c) 2021-present AgogPixel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n// Adapted from https://github.com/agogpixel/phaser3-ts-utils/tree/main\n\nlet components = (Phaser.GameObjects.Components as any);\nexport const ComputedSize = components.ComputedSize;\nexport const Depth = components.Depth;\nexport const Flip = components.Flip;\nexport const ScrollFactor = components.ScrollFactor;\nexport const Transform = components.Transform;\nexport const Visible = components.Visible;\nexport const Origin = components.Origin;\nexport const Alpha = components.Alpha;\n\nexport interface Type<\n\tT,\n\tP extends any[] = any[]\n\t> extends Function {\n\tnew(...args: P): T;\n}\n\nexport type Mixin = <\n\tGameObjectType extends Type\n\t>(\n\tBaseGameObject: GameObjectType\n) => GameObjectType & Type;\n\nexport function createMixin<\n\tGameObjectComponent,\n\tGameObjectConstraint extends Phaser.GameObjects.GameObject = Phaser.GameObjects.GameObject\n> (\n\t...component: GameObjectComponent[]\n): Mixin {\n\treturn (BaseGameObject) => {\n\t\t(Phaser as any).Class.mixin(BaseGameObject, component);\n\t\treturn BaseGameObject as any;\n\t};\n}\n\ntype ComputedSizeMixin = Mixin;\nexport const ComputedSizeMixin: ComputedSizeMixin = createMixin(ComputedSize);\n\ntype DepthMixin = Mixin;\nexport const DepthMixin: DepthMixin = createMixin(Depth);\n\ntype FlipMixin = Mixin;\nexport const FlipMixin: FlipMixin = createMixin(Flip);\n\ntype ScrollFactorMixin = Mixin;\nexport const ScrollFactorMixin: ScrollFactorMixin = createMixin(ScrollFactor);\n\ntype TransformMixin = Mixin;\nexport const TransformMixin: TransformMixin = createMixin(Transform);\n\ntype VisibleMixin = Mixin;\nexport const VisibleMixin: VisibleMixin = createMixin(Visible);\n\ntype OriginMixin = Mixin;\nexport const OriginMixin: OriginMixin = createMixin(Origin);\n\ntype AlphaMixin = Mixin;\nexport const AlphaMixin: AlphaMixin = createMixin(Alpha);", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { SPINE_GAME_OBJECT_TYPE } from \"./keys.js\";\nimport { SpinePlugin } from \"./SpinePlugin.js\";\nimport {\n\tComputedSizeMixin,\n\tDepthMixin,\n\tFlipMixin,\n\tScrollFactorMixin,\n\tTransformMixin,\n\tVisibleMixin,\n\tAlphaMixin,\n\tOriginMixin,\n} from \"./mixins.js\";\nimport {\n\tAnimationState,\n\tAnimationStateData,\n\tBone,\n\tMathUtils,\n\tPhysics,\n\tSkeleton,\n\tSkeletonClipping,\n\tSkin,\n\tVector2,\n} from \"@esotericsoftware/spine-core\";\n\nclass BaseSpineGameObject extends Phaser.GameObjects.GameObject {\n\tconstructor (scene: Phaser.Scene, type: string) {\n\t\tsuper(scene, type);\n\t}\n}\n\n/** A bounds provider calculates the bounding box for a skeleton, which is then assigned as the size of the SpineGameObject. */\nexport interface SpineGameObjectBoundsProvider {\n\t// Returns the bounding box for the skeleton, in skeleton space.\n\tcalculateBounds (gameObject: SpineGameObject): {\n\t\tx: number;\n\t\ty: number;\n\t\twidth: number;\n\t\theight: number;\n\t};\n}\n\n/** A bounds provider that calculates the bounding box from the setup pose. */\nexport class SetupPoseBoundsProvider implements SpineGameObjectBoundsProvider {\n\t/**\n\t * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.\n\t */\n\tconstructor (\n\t\tprivate clipping = false,\n\t) { }\n\n\tcalculateBounds (gameObject: SpineGameObject) {\n\t\tif (!gameObject.skeleton) return { x: 0, y: 0, width: 0, height: 0 };\n\t\t// Make a copy of animation state and skeleton as this might be called while\n\t\t// the skeleton in the GameObject has already been heavily modified. We can not\n\t\t// reconstruct that state.\n\t\tconst skeleton = new Skeleton(gameObject.skeleton.data);\n\t\tskeleton.setToSetupPose();\n\t\tskeleton.updateWorldTransform(Physics.update);\n\t\tconst bounds = skeleton.getBoundsRect(this.clipping ? new SkeletonClipping() : undefined);\n\t\treturn bounds.width == Number.NEGATIVE_INFINITY\n\t\t\t? { x: 0, y: 0, width: 0, height: 0 }\n\t\t\t: bounds;\n\t}\n}\n\n/** A bounds provider that calculates the bounding box by taking the maximumg bounding box for a combination of skins and specific animation. */\nexport class SkinsAndAnimationBoundsProvider\n\timplements SpineGameObjectBoundsProvider {\n\t/**\n\t * @param animation The animation to use for calculating the bounds. If null, the setup pose is used.\n\t * @param skins The skins to use for calculating the bounds. If empty, the default skin is used.\n\t * @param timeStep The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.\n\t * @param clipping If true, clipping attachments are used to compute the bounds. False, by default.\n\t */\n\tconstructor (\n\t\tprivate animation: string | null,\n\t\tprivate skins: string[] = [],\n\t\tprivate timeStep: number = 0.05,\n\t\tprivate clipping = false,\n\t) { }\n\n\tcalculateBounds (gameObject: SpineGameObject): {\n\t\tx: number;\n\t\ty: number;\n\t\twidth: number;\n\t\theight: number;\n\t} {\n\t\tif (!gameObject.skeleton || !gameObject.animationState)\n\t\t\treturn { x: 0, y: 0, width: 0, height: 0 };\n\t\t// Make a copy of animation state and skeleton as this might be called while\n\t\t// the skeleton in the GameObject has already been heavily modified. We can not\n\t\t// reconstruct that state.\n\t\tconst animationState = new AnimationState(gameObject.animationState.data);\n\t\tconst skeleton = new Skeleton(gameObject.skeleton.data);\n\t\tconst clipper = this.clipping ? new SkeletonClipping() : undefined;\n\t\tconst data = skeleton.data;\n\t\tif (this.skins.length > 0) {\n\t\t\tlet customSkin = new Skin(\"custom-skin\");\n\t\t\tfor (const skinName of this.skins) {\n\t\t\t\tconst skin = data.findSkin(skinName);\n\t\t\t\tif (skin == null) continue;\n\t\t\t\tcustomSkin.addSkin(skin);\n\t\t\t}\n\t\t\tskeleton.setSkin(customSkin);\n\t\t}\n\t\tskeleton.setToSetupPose();\n\n\t\tconst animation =\n\t\t\tthis.animation != null ? data.findAnimation(this.animation!) : null;\n\t\tif (animation == null) {\n\t\t\tskeleton.updateWorldTransform(Physics.update);\n\t\t\tconst bounds = skeleton.getBoundsRect(clipper);\n\t\t\treturn bounds.width == Number.NEGATIVE_INFINITY\n\t\t\t\t? { x: 0, y: 0, width: 0, height: 0 }\n\t\t\t\t: bounds;\n\t\t} else {\n\t\t\tlet minX = Number.POSITIVE_INFINITY,\n\t\t\t\tminY = Number.POSITIVE_INFINITY,\n\t\t\t\tmaxX = Number.NEGATIVE_INFINITY,\n\t\t\t\tmaxY = Number.NEGATIVE_INFINITY;\n\t\t\tanimationState.clearTracks();\n\t\t\tanimationState.setAnimationWith(0, animation, false);\n\t\t\tconst steps = Math.max(animation.duration / this.timeStep, 1.0);\n\t\t\tfor (let i = 0; i < steps; i++) {\n\t\t\t\tconst delta = i > 0 ? this.timeStep : 0;\n\t\t\t\tanimationState.update(delta);\n\t\t\t\tanimationState.apply(skeleton);\n\t\t\t\tskeleton.update(delta);\n\t\t\t\tskeleton.updateWorldTransform(Physics.update);\n\n\t\t\t\tconst bounds = skeleton.getBoundsRect(clipper);\n\t\t\t\tminX = Math.min(minX, bounds.x);\n\t\t\t\tminY = Math.min(minY, bounds.y);\n\t\t\t\tmaxX = Math.max(maxX, bounds.x + bounds.width);\n\t\t\t\tmaxY = Math.max(maxY, bounds.y + bounds.height);\n\t\t\t}\n\t\t\tconst bounds = {\n\t\t\t\tx: minX,\n\t\t\t\ty: minY,\n\t\t\t\twidth: maxX - minX,\n\t\t\t\theight: maxY - minY,\n\t\t\t};\n\t\t\treturn bounds.width == Number.NEGATIVE_INFINITY\n\t\t\t\t? { x: 0, y: 0, width: 0, height: 0 }\n\t\t\t\t: bounds;\n\t\t}\n\t}\n}\n\n/**\n * A SpineGameObject is a Phaser {@link GameObject} that can be added to a Phaser Scene and render a Spine skeleton.\n *\n * The Spine GameObject is a thin wrapper around a Spine {@link Skeleton}, {@link AnimationState} and {@link AnimationStateData}. It is responsible for:\n * - updating the animation state\n * - applying the animation state to the skeleton's bones, slots, attachments, and draw order.\n * - updating the skeleton's bone world transforms\n * - rendering the skeleton\n *\n * See the {@link SpinePlugin} class for more information on how to create a `SpineGameObject`.\n *\n * The skeleton, animation state, and animation state data can be accessed via the repsective fields. They can be manually updated via {@link updatePose}.\n *\n * To modify the bone hierarchy before the world transforms are computed, a callback can be set via the {@link beforeUpdateWorldTransforms} field.\n *\n * To modify the bone hierarchy after the world transforms are computed, a callback can be set via the {@link afterUpdateWorldTransforms} field.\n *\n * The class also features methods to convert between the skeleton coordinate system and the Phaser coordinate system.\n *\n * See {@link skeletonToPhaserWorldCoordinates}, {@link phaserWorldCoordinatesToSkeleton}, and {@link phaserWorldCoordinatesToBoneLocal.}\n */\nexport class SpineGameObject extends DepthMixin(\n\tOriginMixin(\n\t\tComputedSizeMixin(\n\t\t\tFlipMixin(\n\t\t\t\tScrollFactorMixin(\n\t\t\t\t\tTransformMixin(VisibleMixin(AlphaMixin(BaseSpineGameObject)))\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t)\n) {\n\tblendMode = -1;\n\tskeleton: Skeleton;\n\tanimationStateData: AnimationStateData;\n\tanimationState: AnimationState;\n\tbeforeUpdateWorldTransforms: (object: SpineGameObject) => void = () => { };\n\tafterUpdateWorldTransforms: (object: SpineGameObject) => void = () => { };\n\tprivate premultipliedAlpha = false;\n\n\tconstructor (\n\t\tscene: Phaser.Scene,\n\t\tprivate plugin: SpinePlugin,\n\t\tx: number,\n\t\ty: number,\n\t\tdataKey: string,\n\t\tatlasKey: string,\n\t\tpublic boundsProvider: SpineGameObjectBoundsProvider = new SetupPoseBoundsProvider()\n\t) {\n\t\tsuper(scene, (window as any).SPINE_GAME_OBJECT_TYPE ? (window as any).SPINE_GAME_OBJECT_TYPE : SPINE_GAME_OBJECT_TYPE);\n\t\tthis.setPosition(x, y);\n\n\t\tthis.premultipliedAlpha = this.plugin.isAtlasPremultiplied(atlasKey);\n\t\tthis.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);\n\t\tthis.animationStateData = new AnimationStateData(this.skeleton.data);\n\t\tthis.animationState = new AnimationState(this.animationStateData);\n\t\tthis.skeleton.updateWorldTransform(Physics.update);\n\t\tthis.updateSize();\n\t}\n\n\tupdateSize () {\n\t\tif (!this.skeleton) return;\n\t\tlet bounds = this.boundsProvider.calculateBounds(this);\n\t\t// For some reason the TS compiler and the ComputedSize mixin don't work well together and we have\n\t\t// to cast to any.\n\t\tlet self = this as any;\n\t\tself.width = bounds.width;\n\t\tself.height = bounds.height;\n\t\tthis.displayOriginX = -bounds.x;\n\t\tthis.displayOriginY = -bounds.y;\n\t}\n\n\t/** Converts a point from the skeleton coordinate system to the Phaser world coordinate system. */\n\tskeletonToPhaserWorldCoordinates (point: { x: number; y: number }) {\n\t\tlet transform = this.getWorldTransformMatrix();\n\t\tlet a = transform.a,\n\t\t\tb = transform.b,\n\t\t\tc = transform.c,\n\t\t\td = transform.d,\n\t\t\ttx = transform.tx,\n\t\t\tty = transform.ty;\n\t\tlet x = point.x;\n\t\tlet y = point.y;\n\t\tpoint.x = x * a + y * c + tx;\n\t\tpoint.y = x * b + y * d + ty;\n\t}\n\n\t/** Converts a point from the Phaser world coordinate system to the skeleton coordinate system. */\n\tphaserWorldCoordinatesToSkeleton (point: { x: number; y: number }) {\n\t\tlet transform = this.getWorldTransformMatrix();\n\t\ttransform = transform.invert();\n\t\tlet a = transform.a,\n\t\t\tb = transform.b,\n\t\t\tc = transform.c,\n\t\t\td = transform.d,\n\t\t\ttx = transform.tx,\n\t\t\tty = transform.ty;\n\t\tlet x = point.x;\n\t\tlet y = point.y;\n\t\tpoint.x = x * a + y * c + tx;\n\t\tpoint.y = x * b + y * d + ty;\n\t}\n\n\t/** Converts a point from the Phaser world coordinate system to the bone's local coordinate system. */\n\tphaserWorldCoordinatesToBone (point: { x: number; y: number }, bone: Bone) {\n\t\tthis.phaserWorldCoordinatesToSkeleton(point);\n\t\tif (bone.parent) {\n\t\t\tbone.parent.worldToLocal(point as Vector2);\n\t\t} else {\n\t\t\tbone.worldToLocal(point as Vector2);\n\t\t}\n\t}\n\n\t/**\n\t * Updates the {@link AnimationState}, applies it to the {@link Skeleton}, then updates the world transforms of all bones.\n\t * @param delta The time delta in milliseconds\n\t */\n\tupdatePose (delta: number) {\n\t\tthis.animationState.update(delta / 1000);\n\t\tthis.animationState.apply(this.skeleton);\n\t\tthis.beforeUpdateWorldTransforms(this);\n\t\tthis.skeleton.update(delta / 1000);\n\t\tthis.skeleton.updateWorldTransform(Physics.update);\n\t\tthis.afterUpdateWorldTransforms(this);\n\t}\n\n\tpreUpdate (time: number, delta: number) {\n\t\tif (!this.skeleton || !this.animationState) return;\n\t\tthis.updatePose(delta);\n\t}\n\n\tpreDestroy () {\n\t\t// FIXME tear down any event emitters\n\t}\n\n\twillRender (camera: Phaser.Cameras.Scene2D.Camera) {\n\t\tvar GameObjectRenderMask = 0xf;\n\t\tvar result = !this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && this.cameraFilter & camera.id));\n\t\tif (!this.visible) result = false;\n\n\t\tif (!result && this.parentContainer && this.plugin.webGLRenderer) {\n\t\t\tvar sceneRenderer = this.plugin.webGLRenderer;\n\n\t\t\tif (this.plugin.gl && this.plugin.phaserRenderer instanceof Phaser.Renderer.WebGL.WebGLRenderer && sceneRenderer.batcher.isDrawing) {\n\t\t\t\tsceneRenderer.end();\n\t\t\t\tthis.plugin.phaserRenderer.pipelines.rebind();\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\trenderWebGL (\n\t\trenderer: Phaser.Renderer.WebGL.WebGLRenderer,\n\t\tsrc: SpineGameObject,\n\t\tcamera: Phaser.Cameras.Scene2D.Camera,\n\t\tparentMatrix: Phaser.GameObjects.Components.TransformMatrix\n\t) {\n\t\tif (!this.skeleton || !this.animationState || !this.plugin.webGLRenderer)\n\t\t\treturn;\n\n\t\tlet sceneRenderer = this.plugin.webGLRenderer;\n\t\tif (renderer.newType) {\n\t\t\trenderer.pipelines.clear();\n\t\t\tsceneRenderer.begin();\n\t\t}\n\n\t\tcamera.addToRenderList(src);\n\t\tlet transform = Phaser.GameObjects.GetCalcMatrix(\n\t\t\tsrc,\n\t\t\tcamera,\n\t\t\tparentMatrix\n\t\t).calc;\n\t\tlet a = transform.a,\n\t\t\tb = transform.b,\n\t\t\tc = transform.c,\n\t\t\td = transform.d,\n\t\t\ttx = transform.tx,\n\t\t\tty = transform.ty;\n\t\tsceneRenderer.drawSkeleton(\n\t\t\tthis.skeleton,\n\t\t\tthis.premultipliedAlpha,\n\t\t\t-1,\n\t\t\t-1,\n\t\t\t(vertices, numVertices, stride) => {\n\t\t\t\tfor (let i = 0; i < numVertices; i += stride) {\n\t\t\t\t\tlet vx = vertices[i];\n\t\t\t\t\tlet vy = vertices[i + 1];\n\t\t\t\t\tvertices[i] = vx * a + vy * c + tx;\n\t\t\t\t\tvertices[i + 1] = vx * b + vy * d + ty;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tif (!renderer.nextTypeMatch) {\n\t\t\tsceneRenderer.end();\n\t\t\trenderer.pipelines.rebind();\n\t\t}\n\t}\n\n\trenderCanvas (\n\t\trenderer: Phaser.Renderer.Canvas.CanvasRenderer,\n\t\tsrc: SpineGameObject,\n\t\tcamera: Phaser.Cameras.Scene2D.Camera,\n\t\tparentMatrix: Phaser.GameObjects.Components.TransformMatrix\n\t) {\n\t\tif (!this.skeleton || !this.animationState || !this.plugin.canvasRenderer)\n\t\t\treturn;\n\n\t\tlet context = renderer.currentContext;\n\t\tlet skeletonRenderer = this.plugin.canvasRenderer;\n\t\t(skeletonRenderer as any).ctx = context;\n\n\t\tcamera.addToRenderList(src);\n\t\tlet transform = Phaser.GameObjects.GetCalcMatrix(\n\t\t\tsrc,\n\t\t\tcamera,\n\t\t\tparentMatrix\n\t\t).calc;\n\t\tlet skeleton = this.skeleton;\n\t\tskeleton.x = transform.tx;\n\t\tskeleton.y = transform.ty;\n\t\tskeleton.scaleX = transform.scaleX;\n\t\tskeleton.scaleY = transform.scaleY;\n\t\tlet root = skeleton.getRootBone()!;\n\t\troot.rotation = -MathUtils.radiansToDegrees * transform.rotationNormalized;\n\t\tthis.skeleton.updateWorldTransform(Physics.update);\n\n\t\tcontext.save();\n\t\tskeletonRenderer.draw(skeleton);\n\t\tcontext.restore();\n\t}\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Texture, TextureFilter, TextureWrap } from \"@esotericsoftware/spine-core\";\n\nexport class CanvasTexture extends Texture {\n\tconstructor (image: HTMLImageElement | ImageBitmap) {\n\t\tsuper(image);\n\t}\n\n\tsetFilters (minFilter: TextureFilter, magFilter: TextureFilter) { }\n\tsetWraps (uWrap: TextureWrap, vWrap: TextureWrap) { }\n\tdispose () { }\n}\n", "/******************************************************************************\n * Spine Runtimes License Agreement\n * Last updated July 28, 2023. Replaces all prior versions.\n *\n * Copyright (c) 2013-2023, Esoteric Software LLC\n *\n * Integration of the Spine Runtimes into software or otherwise creating\n * derivative works of the Spine Runtimes is permitted under the terms and\n * conditions of Section 2 of the Spine Editor License Agreement:\n * http://esotericsoftware.com/spine-editor-license\n *\n * Otherwise, it is permitted to integrate the Spine Runtimes into software or\n * otherwise create derivative works of the Spine Runtimes (collectively,\n * \"Products\"), provided that each user of the Products must obtain their own\n * Spine Editor license and redistribution of the Products in any form must\n * include this license and copyright notice.\n *\n * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,\n * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE\n * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *****************************************************************************/\n\nimport { Utils, Color, Skeleton, RegionAttachment, BlendMode, MeshAttachment, Slot, TextureRegion, TextureAtlasRegion } from \"@esotericsoftware/spine-core\";\nimport { CanvasTexture } from \"./CanvasTexture.js\";\n\nconst worldVertices = Utils.newFloatArray(8);\n\nexport class SkeletonRenderer {\n\tstatic QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];\n\tstatic VERTEX_SIZE = 2 + 2 + 4;\n\n\tprivate ctx: CanvasRenderingContext2D;\n\n\tpublic triangleRendering = false;\n\tpublic debugRendering = false;\n\tprivate vertices = Utils.newFloatArray(8 * 1024);\n\tprivate tempColor = new Color();\n\n\tconstructor (context: CanvasRenderingContext2D) {\n\t\tthis.ctx = context;\n\t}\n\n\tdraw (skeleton: Skeleton) {\n\t\tif (this.triangleRendering) this.drawTriangles(skeleton);\n\t\telse this.drawImages(skeleton);\n\t}\n\n\tprivate drawImages (skeleton: Skeleton) {\n\t\tlet ctx = this.ctx;\n\t\tlet color = this.tempColor;\n\t\tlet skeletonColor = skeleton.color;\n\t\tlet drawOrder = skeleton.drawOrder;\n\n\t\tif (this.debugRendering) ctx.strokeStyle = \"green\";\n\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet slot = drawOrder[i];\n\t\t\tlet bone = slot.bone;\n\t\t\tif (!bone.active) continue;\n\n\t\t\tlet attachment = slot.getAttachment();\n\t\t\tif (!(attachment instanceof RegionAttachment)) continue;\n\t\t\tattachment.computeWorldVertices(slot, worldVertices, 0, 2);\n\t\t\tlet region: TextureRegion = attachment.region;\n\n\t\t\tlet image: HTMLImageElement = (region.texture).getImage() as HTMLImageElement;\n\n\t\t\tlet slotColor = slot.color;\n\t\t\tlet regionColor = attachment.color;\n\t\t\tcolor.set(skeletonColor.r * slotColor.r * regionColor.r,\n\t\t\t\tskeletonColor.g * slotColor.g * regionColor.g,\n\t\t\t\tskeletonColor.b * slotColor.b * regionColor.b,\n\t\t\t\tskeletonColor.a * slotColor.a * regionColor.a);\n\n\t\t\tctx.save();\n\t\t\tctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);\n\t\t\tctx.translate(attachment.offset[0], attachment.offset[1]);\n\t\t\tctx.rotate(attachment.rotation * Math.PI / 180);\n\n\t\t\tlet atlasScale = attachment.width / region.originalWidth;\n\t\t\tctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);\n\n\t\t\tlet w = region.width, h = region.height;\n\t\t\tctx.translate(w / 2, h / 2);\n\t\t\tif (attachment.region!.degrees == 90) {\n\t\t\t\tlet t = w;\n\t\t\t\tw = h;\n\t\t\t\th = t;\n\t\t\t\tctx.rotate(-Math.PI / 2);\n\t\t\t}\n\t\t\tctx.scale(1, -1);\n\t\t\tctx.translate(-w / 2, -h / 2);\n\n\t\t\tctx.globalAlpha = color.a;\n\t\t\tctx.drawImage(image, image.width * region.u, image.height * region.v, w, h, 0, 0, w, h);\n\t\t\tif (this.debugRendering) ctx.strokeRect(0, 0, w, h);\n\t\t\tctx.restore();\n\t\t}\n\t}\n\n\tprivate drawTriangles (skeleton: Skeleton) {\n\t\tlet ctx = this.ctx;\n\t\tlet color = this.tempColor;\n\t\tlet skeletonColor = skeleton.color;\n\t\tlet drawOrder = skeleton.drawOrder;\n\n\t\tlet blendMode: BlendMode | null = null;\n\t\tlet vertices: ArrayLike = this.vertices;\n\t\tlet triangles: Array | null = null;\n\n\t\tfor (let i = 0, n = drawOrder.length; i < n; i++) {\n\t\t\tlet slot = drawOrder[i];\n\t\t\tlet attachment = slot.getAttachment();\n\n\t\t\tlet texture: HTMLImageElement;\n\t\t\tlet region: TextureAtlasRegion;\n\t\t\tif (attachment instanceof RegionAttachment) {\n\t\t\t\tlet regionAttachment = attachment;\n\t\t\t\tvertices = this.computeRegionVertices(slot, regionAttachment, false);\n\t\t\t\ttriangles = SkeletonRenderer.QUAD_TRIANGLES;\n\t\t\t\ttexture = (regionAttachment.region!.texture).getImage() as HTMLImageElement;\n\t\t\t} else if (attachment instanceof MeshAttachment) {\n\t\t\t\tlet mesh = attachment;\n\t\t\t\tvertices = this.computeMeshVertices(slot, mesh, false);\n\t\t\t\ttriangles = mesh.triangles;\n\t\t\t\ttexture = (mesh.region!.texture).getImage() as HTMLImageElement;\n\t\t\t} else\n\t\t\t\tcontinue;\n\n\t\t\tif (texture) {\n\t\t\t\tif (slot.data.blendMode != blendMode) blendMode = slot.data.blendMode;\n\n\t\t\t\tlet slotColor = slot.color;\n\t\t\t\tlet attachmentColor = attachment.color;\n\t\t\t\tcolor.set(skeletonColor.r * slotColor.r * attachmentColor.r,\n\t\t\t\t\tskeletonColor.g * slotColor.g * attachmentColor.g,\n\t\t\t\t\tskeletonColor.b * slotColor.b * attachmentColor.b,\n\t\t\t\t\tskeletonColor.a * slotColor.a * attachmentColor.a);\n\n\t\t\t\tctx.globalAlpha = color.a;\n\n\t\t\t\tfor (var j = 0; j < triangles.length; j += 3) {\n\t\t\t\t\tlet t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8;\n\n\t\t\t\t\tlet x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];\n\t\t\t\t\tlet x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];\n\t\t\t\t\tlet x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];\n\n\t\t\t\t\tthis.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);\n\n\t\t\t\t\tif (this.debugRendering) {\n\t\t\t\t\t\tctx.strokeStyle = \"green\";\n\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\tctx.moveTo(x0, y0);\n\t\t\t\t\t\tctx.lineTo(x1, y1);\n\t\t\t\t\t\tctx.lineTo(x2, y2);\n\t\t\t\t\t\tctx.lineTo(x0, y0);\n\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.ctx.globalAlpha = 1;\n\t}\n\n\t// Adapted from http://extremelysatisfactorytotalitarianism.com/blog/?p=2120\n\t// Apache 2 licensed\n\tprivate drawTriangle (img: HTMLImageElement, x0: number, y0: number, u0: number, v0: number,\n\t\tx1: number, y1: number, u1: number, v1: number,\n\t\tx2: number, y2: number, u2: number, v2: number) {\n\t\tlet ctx = this.ctx;\n\n\t\tconst width = img.width - 1;\n\t\tconst height = img.height - 1;\n\t\tu0 *= width;\n\t\tv0 *= height;\n\t\tu1 *= width;\n\t\tv1 *= height;\n\t\tu2 *= width;\n\t\tv2 *= height;\n\n\t\tctx.beginPath();\n\t\tctx.moveTo(x0, y0);\n\t\tctx.lineTo(x1, y1);\n\t\tctx.lineTo(x2, y2);\n\t\tctx.closePath();\n\n\t\tx1 -= x0;\n\t\ty1 -= y0;\n\t\tx2 -= x0;\n\t\ty2 -= y0;\n\n\t\tu1 -= u0;\n\t\tv1 -= v0;\n\t\tu2 -= u0;\n\t\tv2 -= v0;\n\n\t\tlet det = u1 * v2 - u2 * v1;\n\t\tif (det == 0) return;\n\t\tdet = 1 / det;\n\n\t\t// linear transformation\n\t\tconst a = (v2 * x1 - v1 * x2) * det;\n\t\tconst b = (v2 * y1 - v1 * y2) * det;\n\t\tconst c = (u1 * x2 - u2 * x1) * det;\n\t\tconst d = (u1 * y2 - u2 * y1) * det;\n\n\t\t// translation\n\t\tconst e = x0 - a * u0 - c * v0;\n\t\tconst f = y0 - b * u0 - d * v0;\n\n\t\tctx.save();\n\t\tctx.transform(a, b, c, d, e, f);\n\t\tctx.clip();\n\t\tctx.drawImage(img, 0, 0);\n\t\tctx.restore();\n\t}\n\n\tprivate computeRegionVertices (slot: Slot, region: RegionAttachment, pma: boolean) {\n\t\tlet skeletonColor = slot.bone.skeleton.color;\n\t\tlet slotColor = slot.color;\n\t\tlet regionColor = region.color;\n\t\tlet alpha = skeletonColor.a * slotColor.a * regionColor.a;\n\t\tlet multiplier = pma ? alpha : 1;\n\t\tlet color = this.tempColor;\n\t\tcolor.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,\n\t\t\tskeletonColor.g * slotColor.g * regionColor.g * multiplier,\n\t\t\tskeletonColor.b * slotColor.b * regionColor.b * multiplier,\n\t\t\talpha);\n\n\t\tregion.computeWorldVertices(slot, this.vertices, 0, SkeletonRenderer.VERTEX_SIZE);\n\n\t\tlet vertices = this.vertices;\n\t\tlet uvs = region.uvs;\n\n\t\tvertices[RegionAttachment.C1R] = color.r;\n\t\tvertices[RegionAttachment.C1G] = color.g;\n\t\tvertices[RegionAttachment.C1B] = color.b;\n\t\tvertices[RegionAttachment.C1A] = color.a;\n\t\tvertices[RegionAttachment.U1] = uvs[0];\n\t\tvertices[RegionAttachment.V1] = uvs[1];\n\n\t\tvertices[RegionAttachment.C2R] = color.r;\n\t\tvertices[RegionAttachment.C2G] = color.g;\n\t\tvertices[RegionAttachment.C2B] = color.b;\n\t\tvertices[RegionAttachment.C2A] = color.a;\n\t\tvertices[RegionAttachment.U2] = uvs[2];\n\t\tvertices[RegionAttachment.V2] = uvs[3];\n\n\t\tvertices[RegionAttachment.C3R] = color.r;\n\t\tvertices[RegionAttachment.C3G] = color.g;\n\t\tvertices[RegionAttachment.C3B] = color.b;\n\t\tvertices[RegionAttachment.C3A] = color.a;\n\t\tvertices[RegionAttachment.U3] = uvs[4];\n\t\tvertices[RegionAttachment.V3] = uvs[5];\n\n\t\tvertices[RegionAttachment.C4R] = color.r;\n\t\tvertices[RegionAttachment.C4G] = color.g;\n\t\tvertices[RegionAttachment.C4B] = color.b;\n\t\tvertices[RegionAttachment.C4A] = color.a;\n\t\tvertices[RegionAttachment.U4] = uvs[6];\n\t\tvertices[RegionAttachment.V4] = uvs[7];\n\n\t\treturn vertices;\n\t}\n\n\tprivate computeMeshVertices (slot: Slot, mesh: MeshAttachment, pma: boolean) {\n\t\tlet skeletonColor = slot.bone.skeleton.color;\n\t\tlet slotColor = slot.color;\n\t\tlet regionColor = mesh.color;\n\t\tlet alpha = skeletonColor.a * slotColor.a * regionColor.a;\n\t\tlet multiplier = pma ? alpha : 1;\n\t\tlet color = this.tempColor;\n\t\tcolor.set(skeletonColor.r * slotColor.r * regionColor.r * multiplier,\n\t\t\tskeletonColor.g * slotColor.g * regionColor.g * multiplier,\n\t\t\tskeletonColor.b * slotColor.b * regionColor.b * multiplier,\n\t\t\talpha);\n\n\t\tlet vertexCount = mesh.worldVerticesLength / 2;\n\t\tlet vertices = this.vertices;\n\t\tif (vertices.length < mesh.worldVerticesLength) this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength);\n\t\tmesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, SkeletonRenderer.VERTEX_SIZE);\n\n\t\tlet uvs = mesh.uvs;\n\t\tfor (let i = 0, u = 0, v = 2; i < vertexCount; i++) {\n\t\t\tvertices[v++] = color.r;\n\t\t\tvertices[v++] = color.g;\n\t\t\tvertices[v++] = color.b;\n\t\t\tvertices[v++] = color.a;\n\t\t\tvertices[v++] = uvs[u++];\n\t\t\tvertices[v++] = uvs[u++];\n\t\t\tv += 2;\n\t\t}\n\n\t\treturn vertices;\n\t}\n}\n"], + "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAAA;AAAA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgCA,MAAI,OAAO,WAAW,eAAe,OAAO,QAAQ;AACnD,QAAI,cAAc,OAAO;AACzB,WAAO,UAAU,CAAC,MAAc;AAC/B,UAAI;AAAa,eAAO,YAAY,CAAC;AAAA,eAC5B,MAAM;AAAU,eAAO,OAAO;AAAA,IACxC;AAAA,EACD;;;ACTA,MAAAC,UAAwB;;;ACAjB,MAAM,gCAAgC;AACtC,MAAM,wBAAwB;AAE9B,MAAM,gCAAgC;AACtC,MAAM,wBAAwB;AAC9B,MAAM,yBAAyB;;;ACE/B,MAAM,SAAN,MAAa;AAAA,IACnB,QAAQ,IAAI,MAA0B;AAAA,IAEtC,IAAK,OAAwB;AAC5B,UAAI,WAAW,KAAK,SAAS,KAAK;AAClC,WAAK,MAAM,QAAQ,CAAC,IAAI,QAAQ;AAChC,aAAO,CAAC;AAAA,IACT;AAAA,IAEA,SAAU,OAAe;AACxB,aAAO,KAAK,MAAM,QAAQ,CAAC,KAAK;AAAA,IACjC;AAAA,IAEA,OAAQ,OAAe;AACtB,WAAK,MAAM,QAAQ,CAAC,IAAI;AAAA,IACzB;AAAA,IAEA,QAAS;AACR,WAAK,MAAM,SAAS;AAAA,IACrB;AAAA,EACD;AAEO,MAAM,YAAN,MAAgB;AAAA,IACtB,UAA8B,CAAC;AAAA,IAC/B,OAAO;AAAA,IAEP,IAAK,OAAwB;AAC5B,UAAI,WAAW,KAAK,QAAQ,KAAK;AACjC,WAAK,QAAQ,KAAK,IAAI;AACtB,UAAI,CAAC,UAAU;AACd,aAAK;AACL,eAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR;AAAA,IAEA,OAAQ,QAA2B;AAClC,UAAI,UAAU,KAAK;AACnB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,GAAG;AACzC,aAAK,IAAI,OAAO,CAAC,CAAC;AACnB,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,SAAU,OAAe;AACxB,aAAO,KAAK,QAAQ,KAAK;AAAA,IAC1B;AAAA,IAEA,QAAS;AACR,WAAK,UAAU,CAAC;AAChB,WAAK,OAAO;AAAA,IACb;AAAA,EACD;AAaO,MAAM,SAAN,MAAY;AAAA,IAOlB,YAAoB,IAAY,GAAU,IAAY,GAAU,IAAY,GAAU,IAAY,GAAG;AAAjF;AAAsB;AAAsB;AAAsB;AAAA,IACtF;AAAA,IAEA,IAAK,GAAW,GAAW,GAAW,GAAW;AAChD,WAAK,IAAI;AACT,WAAK,IAAI;AACT,WAAK,IAAI;AACT,WAAK,IAAI;AACT,aAAO,KAAK,MAAM;AAAA,IACnB;AAAA,IAEA,aAAc,GAAU;AACvB,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,EAAE;AACX,aAAO;AAAA,IACR;AAAA,IAEA,cAAe,KAAa;AAC3B,YAAM,IAAI,OAAO,CAAC,KAAK,MAAM,IAAI,OAAO,CAAC,IAAI;AAC7C,WAAK,IAAI,SAAS,IAAI,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI;AAC1C,WAAK,IAAI,SAAS,IAAI,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI;AAC1C,WAAK,IAAI,SAAS,IAAI,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI;AAC1C,WAAK,IAAI,IAAI,UAAU,IAAI,IAAI,SAAS,IAAI,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI;AAChE,aAAO;AAAA,IACR;AAAA,IAEA,IAAK,GAAW,GAAW,GAAW,GAAW;AAChD,WAAK,KAAK;AACV,WAAK,KAAK;AACV,WAAK,KAAK;AACV,WAAK,KAAK;AACV,aAAO,KAAK,MAAM;AAAA,IACnB;AAAA,IAEA,QAAS;AACR,UAAI,KAAK,IAAI;AAAG,aAAK,IAAI;AAAA,eAChB,KAAK,IAAI;AAAG,aAAK,IAAI;AAE9B,UAAI,KAAK,IAAI;AAAG,aAAK,IAAI;AAAA,eAChB,KAAK,IAAI;AAAG,aAAK,IAAI;AAE9B,UAAI,KAAK,IAAI;AAAG,aAAK,IAAI;AAAA,eAChB,KAAK,IAAI;AAAG,aAAK,IAAI;AAE9B,UAAI,KAAK,IAAI;AAAG,aAAK,IAAI;AAAA,eAChB,KAAK,IAAI;AAAG,aAAK,IAAI;AAC9B,aAAO;AAAA,IACR;AAAA,IAEA,OAAO,gBAAiB,OAAc,OAAe;AACpD,YAAM,MAAM,QAAQ,gBAAgB,MAAM;AAC1C,YAAM,MAAM,QAAQ,cAAgB,MAAM;AAC1C,YAAM,MAAM,QAAQ,WAAgB,KAAK;AACzC,YAAM,KAAM,QAAQ,OAAe;AAAA,IACpC;AAAA,IAEA,OAAO,cAAe,OAAc,OAAe;AAClD,YAAM,MAAM,QAAQ,cAAgB,MAAM;AAC1C,YAAM,MAAM,QAAQ,WAAgB,KAAK;AACzC,YAAM,KAAM,QAAQ,OAAe;AAAA,IACpC;AAAA,IAEA,WAAY;AACX,YAAM,MAAM,CAAC,OAAe,OAAO,IAAI,KAAK,SAAS,EAAE,GAAG,MAAM,EAAE;AAClE,aAAO,OAAO,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;AAAA,IAC7D;AAAA,IAEA,OAAO,WAAY,KAAoB;AACtC,aAAO,IAAI,OAAM,EAAE,cAAc,GAAG;AAAA,IACrC;AAAA,EACD;AA/EO,MAAM,QAAN;AACN,gBADY,OACE,SAAQ,IAAI,OAAM,GAAG,GAAG,GAAG,CAAC;AAC1C,gBAFY,OAEE,OAAM,IAAI,OAAM,GAAG,GAAG,GAAG,CAAC;AACxC,gBAHY,OAGE,SAAQ,IAAI,OAAM,GAAG,GAAG,GAAG,CAAC;AAC1C,gBAJY,OAIE,QAAO,IAAI,OAAM,GAAG,GAAG,GAAG,CAAC;AACzC,gBALY,OAKE,WAAU,IAAI,OAAM,GAAG,GAAG,GAAG,CAAC;AA4EtC,MAAM,aAAN,MAAgB;AAAA,IAStB,OAAO,MAAO,OAAe,KAAa,KAAa;AACtD,UAAI,QAAQ;AAAK,eAAO;AACxB,UAAI,QAAQ;AAAK,eAAO;AACxB,aAAO;AAAA,IACR;AAAA,IAEA,OAAO,OAAQ,SAAiB;AAC/B,aAAO,KAAK,IAAI,UAAU,WAAU,MAAM;AAAA,IAC3C;AAAA,IAEA,OAAO,OAAQ,SAAiB;AAC/B,aAAO,KAAK,IAAI,UAAU,WAAU,MAAM;AAAA,IAC3C;AAAA,IAEA,OAAO,SAAU,GAAW,GAAW;AACtC,aAAO,KAAK,MAAM,GAAG,CAAC,IAAI,WAAU;AAAA,IACrC;AAAA,IAEA,OAAO,OAAQ,OAAuB;AACrC,aAAO,QAAQ,IAAI,IAAI,QAAQ,IAAI,KAAK;AAAA,IACzC;AAAA,IAEA,OAAO,MAAO,GAAW;AACxB,aAAO,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC;AAAA,IAC3C;AAAA,IAEA,OAAO,KAAM,GAAW;AACvB,UAAI,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;AACnC,aAAO,IAAI,IAAI,CAAC,IAAI;AAAA,IACrB;AAAA,IAEA,OAAO,iBAAkB,KAAa,KAAqB;AAC1D,aAAO,WAAU,qBAAqB,KAAK,MAAM,MAAM,OAAO,GAAG;AAAA,IAClE;AAAA,IAEA,OAAO,qBAAsB,KAAa,KAAa,MAAsB;AAC5E,UAAI,IAAI,KAAK,OAAO;AACpB,UAAI,IAAI,MAAM;AACd,UAAI,MAAM,OAAO,OAAO;AAAG,eAAO,MAAM,KAAK,KAAK,IAAI,KAAK,OAAO,IAAI;AACtE,aAAO,MAAM,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,KAAK;AAAA,IAClD;AAAA,IAEA,OAAO,aAAc,OAAe;AACnC,aAAO,UAAU,QAAS,QAAQ,OAAQ;AAAA,IAC3C;AAAA,EACD;AAtDO,MAAM,YAAN;AACN,gBADY,WACL,MAAK;AACZ,gBAFY,WAEL,OAAM,WAAU,KAAK;AAC5B,gBAHY,WAGL,UAAS,IAAI,WAAU;AAC9B,gBAJY,WAIL,oBAAmB,MAAM,WAAU;AAC1C,gBALY,WAKL,UAAS,WAAU;AAC1B,gBANY,WAML,oBAAmB,WAAU,KAAK;AACzC,gBAPY,WAOL,UAAS,WAAU;AAiDpB,MAAe,gBAAf,MAA6B;AAAA,IAEnC,MAAO,OAAe,KAAa,GAAmB;AACrD,aAAO,SAAS,MAAM,SAAS,KAAK,cAAc,CAAC;AAAA,IACpD;AAAA,EACD;AAEO,MAAM,MAAN,cAAkB,cAAc;AAAA,IAC5B,QAAQ;AAAA,IAElB,YAAa,OAAe;AAC3B,YAAM;AACN,WAAK,QAAQ;AAAA,IACd;AAAA,IAEA,cAAe,GAAmB;AACjC,UAAI,KAAK;AAAK,eAAO,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,IAAI;AACnD,aAAO,KAAK,KAAK,IAAI,KAAK,GAAG,KAAK,KAAK,KAAK,KAAK,QAAQ,KAAK,IAAI,KAAK,KAAK;AAAA,IAC7E;AAAA,EACD;AAEO,MAAM,SAAN,cAAqB,IAAI;AAAA,IAC/B,YAAa,OAAe;AAC3B,YAAM,KAAK;AAAA,IACZ;AAAA,IAEA,cAAe,GAAmB;AACjC,aAAO,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,KAAK,KAAK,QAAQ,KAAK,IAAI,KAAK,KAAK;AAAA,IACvE;AAAA,EACD;AAEO,MAAM,SAAN,MAAY;AAAA,IAGlB,OAAO,UAAc,QAAsB,aAAqB,MAAoB,WAAmB,aAAqB;AAC3H,eAAS,IAAI,aAAa,IAAI,WAAW,IAAI,cAAc,aAAa,KAAK,KAAK;AACjF,aAAK,CAAC,IAAI,OAAO,CAAC;AAAA,MACnB;AAAA,IACD;AAAA,IAEA,OAAO,UAAc,OAAqB,WAAmB,SAAiB,OAAU;AACvF,eAAS,IAAI,WAAW,IAAI,SAAS;AACpC,cAAM,CAAC,IAAI;AAAA,IACb;AAAA,IAEA,OAAO,aAAiB,OAAiB,MAAc,QAAa,GAAa;AAChF,UAAI,UAAU,MAAM;AACpB,UAAI,WAAW;AAAM,eAAO;AAC5B,YAAM,SAAS;AACf,UAAI,UAAU,MAAM;AACnB,iBAAS,IAAI,SAAS,IAAI,MAAM;AAAK,gBAAM,CAAC,IAAI;AAAA,MACjD;AACA,aAAO;AAAA,IACR;AAAA,IAEA,OAAO,oBAAwB,OAAiB,MAAc,QAAa,GAAa;AACvF,UAAI,MAAM,UAAU;AAAM,eAAO;AACjC,aAAO,OAAM,aAAa,OAAO,MAAM,KAAK;AAAA,IAC7C;AAAA,IAEA,OAAO,SAAa,MAAc,cAA2B;AAC5D,UAAI,QAAQ,IAAI,MAAS,IAAI;AAC7B,eAAS,IAAI,GAAG,IAAI,MAAM;AAAK,cAAM,CAAC,IAAI;AAC1C,aAAO;AAAA,IACR;AAAA,IAEA,OAAO,cAAe,MAA+B;AACpD,UAAI,OAAM;AACT,eAAO,IAAI,aAAa,IAAI;AAAA,WACxB;AACJ,YAAI,QAAQ,IAAI,MAAc,IAAI;AAClC,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ;AAAK,gBAAM,CAAC,IAAI;AAClD,eAAO;AAAA,MACR;AAAA,IACD;AAAA,IAEA,OAAO,cAAe,MAA4B;AACjD,UAAI,OAAM;AACT,eAAO,IAAI,WAAW,IAAI;AAAA,WACtB;AACJ,YAAI,QAAQ,IAAI,MAAc,IAAI;AAClC,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ;AAAK,gBAAM,CAAC,IAAI;AAClD,eAAO;AAAA,MACR;AAAA,IACD;AAAA,IAEA,OAAO,aAAc,OAAsB;AAC1C,aAAO,OAAM,wBAAwB,IAAI,aAAa,KAAK,IAAI;AAAA,IAChE;AAAA,IAEA,OAAO,kBAAmB,OAAe;AACxC,aAAO,OAAM,wBAAwB,KAAK,OAAO,KAAK,IAAI;AAAA,IAC3D;AAAA;AAAA,IAGA,OAAO,sBAAuB,OAAe,OAAiB;AAAA,IAC9D;AAAA,IAEA,OAAO,SAAa,OAAiB,SAAY,WAAW,MAAM;AACjE,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ;AACjC,YAAI,MAAM,CAAC,KAAK;AAAS,iBAAO;AACjC,aAAO;AAAA,IACR;AAAA,IAEA,OAAO,UAAW,MAAW,MAAc;AAC1C,aAAO,KAAK,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC;AAAA,IAClD;AAAA,EACD;AA5EO,MAAM,QAAN;AACN,gBADY,OACL,yBAAwB,OAAQ,iBAAkB;AA6EnD,MAAM,aAAN,MAAiB;AAAA,IACvB,OAAO,SAAU,UAAoB;AACpC,eAAS,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,KAAK;AAC/C,YAAI,OAAO,SAAS,MAAM,CAAC;AAC3B,gBAAQ,IAAI,KAAK,KAAK,OAAO,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,SAAS,OAAO,KAAK,MAAM;AAAA,MACrI;AAAA,IACD;AAAA,EACD;AAEO,MAAM,OAAN,MAAc;AAAA,IACZ,QAAQ,IAAI,MAAS;AAAA,IACrB;AAAA,IAER,YAAa,cAAuB;AACnC,WAAK,eAAe;AAAA,IACrB;AAAA,IAEA,SAAU;AACT,aAAO,KAAK,MAAM,SAAS,IAAI,KAAK,MAAM,IAAI,IAAK,KAAK,aAAa;AAAA,IACtE;AAAA,IAEA,KAAM,MAAS;AACd,UAAK,KAAa;AAAO,QAAC,KAAa,MAAM;AAC7C,WAAK,MAAM,KAAK,IAAI;AAAA,IACrB;AAAA,IAEA,QAAS,OAAqB;AAC7B,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ;AACjC,aAAK,KAAK,MAAM,CAAC,CAAC;AAAA,IACpB;AAAA,IAEA,QAAS;AACR,WAAK,MAAM,SAAS;AAAA,IACrB;AAAA,EACD;AAEO,MAAM,UAAN,MAAc;AAAA,IACpB,YAAoB,IAAI,GAAU,IAAI,GAAG;AAArB;AAAc;AAAA,IAClC;AAAA,IAEA,IAAK,GAAW,GAAoB;AACnC,WAAK,IAAI;AACT,WAAK,IAAI;AACT,aAAO;AAAA,IACR;AAAA,IAEA,SAAU;AACT,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,KAAK;AACb,aAAO,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC;AAAA,IAC/B;AAAA,IAEA,YAAa;AACZ,UAAI,MAAM,KAAK,OAAO;AACtB,UAAI,OAAO,GAAG;AACb,aAAK,KAAK;AACV,aAAK,KAAK;AAAA,MACX;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAEO,MAAM,aAAN,MAAiB;AAAA,IACvB,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,YAAY;AAAA,IAEJ,WAAW,KAAK,IAAI,IAAI;AAAA,IACxB,aAAa;AAAA,IACb,YAAY;AAAA,IAEpB,SAAU;AACT,UAAI,MAAM,KAAK,IAAI,IAAI;AACvB,WAAK,QAAQ,MAAM,KAAK;AACxB,WAAK,aAAa,KAAK;AACvB,WAAK,aAAa,KAAK;AACvB,UAAI,KAAK,QAAQ,KAAK;AAAU,aAAK,QAAQ,KAAK;AAClD,WAAK,WAAW;AAEhB,WAAK;AACL,UAAI,KAAK,YAAY,GAAG;AACvB,aAAK,kBAAkB,KAAK,aAAa,KAAK;AAC9C,aAAK,YAAY;AACjB,aAAK,aAAa;AAAA,MACnB;AAAA,IACD;AAAA,EACD;AAOO,MAAM,eAAN,MAAmB;AAAA,IACzB;AAAA,IACA,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,IAER,YAAa,aAAqB,IAAI;AACrC,WAAK,SAAS,IAAI,MAAc,UAAU;AAAA,IAC3C;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,eAAe,KAAK,OAAO;AAAA,IACxC;AAAA,IAEA,SAAU,OAAe;AACxB,UAAI,KAAK,cAAc,KAAK,OAAO;AAAQ,aAAK;AAChD,WAAK,OAAO,KAAK,WAAW,IAAI;AAChC,UAAI,KAAK,YAAY,KAAK,OAAO,SAAS;AAAG,aAAK,YAAY;AAC9D,WAAK,QAAQ;AAAA,IACd;AAAA,IAEA,UAAW;AACV,UAAI,KAAK,cAAc,GAAG;AACzB,YAAI,KAAK,OAAO;AACf,cAAI,OAAO;AACX,mBAAS,IAAI,GAAG,IAAI,KAAK,OAAO,QAAQ;AACvC,oBAAQ,KAAK,OAAO,CAAC;AACtB,eAAK,OAAO,OAAO,KAAK,OAAO;AAC/B,eAAK,QAAQ;AAAA,QACd;AACA,eAAO,KAAK;AAAA,MACb;AACA,aAAO;AAAA,IACR;AAAA,EACD;;;AC1bO,MAAe,aAAf,MAA0B;AAAA,IAChC;AAAA,IAEA,YAAa,MAAc;AAC1B,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,OAAO;AAAA,IACb;AAAA,EAGD;AAIO,MAAe,oBAAf,cAAwC,WAAW;AAAA;AAAA,IAIzD,KAAK,kBAAiB;AAAA;AAAA;AAAA;AAAA,IAKtB,QAA8B;AAAA;AAAA;AAAA;AAAA,IAK9B,WAA4B,CAAC;AAAA;AAAA;AAAA,IAI7B,sBAAsB;AAAA;AAAA;AAAA,IAItB,qBAAiC;AAAA,IAEjC,YAAa,MAAc;AAC1B,YAAM,IAAI;AAAA,IACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAaA,qBAAsB,MAAY,OAAe,OAAeC,gBAAgC,QAAgB,QAAgB;AAC/H,cAAQ,UAAU,SAAS,KAAK;AAChC,UAAI,WAAW,KAAK,KAAK;AACzB,UAAI,cAAc,KAAK;AACvB,UAAI,WAAW,KAAK;AACpB,UAAI,QAAQ,KAAK;AACjB,UAAI,CAAC,OAAO;AACX,YAAI,YAAY,SAAS;AAAG,qBAAW;AACvC,YAAI,OAAO,KAAK;AAChB,YAAI,IAAI,KAAK;AACb,YAAI,IAAI,KAAK;AACb,YAAI,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK;AACjD,iBAASC,KAAI,OAAO,IAAI,QAAQ,IAAI,OAAOA,MAAK,GAAG,KAAK,QAAQ;AAC/D,cAAI,KAAK,SAASA,EAAC,GAAG,KAAK,SAASA,KAAI,CAAC;AACzC,UAAAD,eAAc,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI;AACrC,UAAAA,eAAc,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,QAC1C;AACA;AAAA,MACD;AACA,UAAI,IAAI,GAAG,OAAO;AAClB,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK,GAAG;AAClC,YAAI,IAAI,MAAM,CAAC;AACf,aAAK,IAAI;AACT,gBAAQ;AAAA,MACT;AACA,UAAI,gBAAgB,SAAS;AAC7B,UAAI,YAAY,UAAU,GAAG;AAC5B,iBAAS,IAAI,QAAQ,IAAI,OAAO,GAAG,IAAI,OAAO,KAAK,QAAQ;AAC1D,cAAI,KAAK,GAAG,KAAK;AACjB,cAAI,IAAI,MAAM,GAAG;AACjB,eAAK;AACL,iBAAO,IAAI,GAAG,KAAK,KAAK,GAAG;AAC1B,gBAAI,OAAO,cAAc,MAAM,CAAC,CAAC;AACjC,gBAAI,KAAK,SAAS,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,SAAS,SAAS,IAAI,CAAC;AACnE,mBAAO,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,UAAU;AAClD,mBAAO,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,UAAU;AAAA,UACnD;AACA,UAAAA,eAAc,CAAC,IAAI;AACnB,UAAAA,eAAc,IAAI,CAAC,IAAI;AAAA,QACxB;AAAA,MACD,OAAO;AACN,YAAI,SAAS;AACb,iBAAS,IAAI,QAAQ,IAAI,OAAO,GAAG,IAAI,QAAQ,GAAG,IAAI,OAAO,KAAK,QAAQ;AACzE,cAAI,KAAK,GAAG,KAAK;AACjB,cAAI,IAAI,MAAM,GAAG;AACjB,eAAK;AACL,iBAAO,IAAI,GAAG,KAAK,KAAK,GAAG,KAAK,GAAG;AAClC,gBAAI,OAAO,cAAc,MAAM,CAAC,CAAC;AACjC,gBAAI,KAAK,SAAS,CAAC,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,GAAG,SAAS,SAAS,IAAI,CAAC;AAC/F,mBAAO,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,UAAU;AAClD,mBAAO,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,UAAU;AAAA,UACnD;AACA,UAAAA,eAAc,CAAC,IAAI;AACnB,UAAAA,eAAc,IAAI,CAAC,IAAI;AAAA,QACxB;AAAA,MACD;AAAA,IACD;AAAA;AAAA,IAGA,OAAQ,YAA8B;AACrC,UAAI,KAAK,OAAO;AACf,mBAAW,QAAQ,IAAI,MAAc,KAAK,MAAM,MAAM;AACtD,cAAM,UAAU,KAAK,OAAO,GAAG,WAAW,OAAO,GAAG,KAAK,MAAM,MAAM;AAAA,MACtE;AACC,mBAAW,QAAQ;AAEpB,UAAI,KAAK,UAAU;AAClB,mBAAW,WAAW,MAAM,cAAc,KAAK,SAAS,MAAM;AAC9D,cAAM,UAAU,KAAK,UAAU,GAAG,WAAW,UAAU,GAAG,KAAK,SAAS,MAAM;AAAA,MAC/E;AAEA,iBAAW,sBAAsB,KAAK;AACtC,iBAAW,qBAAqB,KAAK;AAAA,IACtC;AAAA,EACD;AAjHO,MAAe,mBAAf;AACN,gBADqB,kBACN,UAAS;;;ACZlB,MAAM,YAAN,MAAe;AAAA,IAGrB,KAAK,UAAS,OAAO;AAAA,IACrB;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA;AAAA,IAET,aAAa;AAAA,IAEb,YAAa,OAAe;AAC3B,WAAK,UAAU,IAAI,MAAqB,KAAK;AAAA,IAC9C;AAAA,IAEA,OAAkB;AACjB,UAAI,OAAO,IAAI,UAAS,KAAK,QAAQ,MAAM;AAC3C,YAAM,UAAU,KAAK,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,QAAQ,MAAM;AACrE,WAAK,QAAQ,KAAK;AAClB,WAAK,SAAS,KAAK;AACnB,WAAK,aAAa,KAAK;AACvB,aAAO;AAAA,IACR;AAAA,IAEA,MAAO,MAAY,YAA8B;AAChD,UAAI,QAAQ,KAAK;AACjB,UAAI,SAAS;AAAI,gBAAQ,KAAK;AAC9B,UAAI,SAAS,KAAK,QAAQ;AAAQ,gBAAQ,KAAK,QAAQ,SAAS;AAChE,UAAI,SAAS,KAAK,QAAQ,KAAK;AAC/B,UAAI,WAAW,UAAU,QAAQ;AAChC,mBAAW,SAAS;AACpB,mBAAW,aAAa;AAAA,MACzB;AAAA,IACD;AAAA,IAEA,QAAS,UAAkB,OAAuB;AACjD,UAAI,SAAS;AACb,UAAI,SAAS,KAAK,QAAQ,OAAO,SAAS;AAC1C,eAAS,IAAI,KAAK,SAAS,MAAM,QAAQ,IAAI,GAAG;AAC/C,kBAAU;AACX,gBAAU;AACV,aAAO;AAAA,IACR;AAAA,IAEA,OAAe,SAAkB;AAChC,aAAO,UAAS;AAAA,IACjB;AAAA,EACD;AA9CO,MAAM,WAAN;AACN,gBADY,UACG,WAAU;AA+CnB,MAAK,eAAL,kBAAKE,kBAAL;AACN,IAAAA,4BAAA,UAAO,KAAP;AACA,IAAAA,4BAAA,UAAO,KAAP;AACA,IAAAA,4BAAA,UAAO,KAAP;AACA,IAAAA,4BAAA,cAAW,KAAX;AACA,IAAAA,4BAAA,iBAAc,KAAd;AACA,IAAAA,4BAAA,iBAAc,KAAd;AACA,IAAAA,4BAAA,qBAAkB,KAAlB;AAPW,WAAAA;AAAA,KAAA;AAUL,MAAM,qBAAqB;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;;;ACzDO,MAAM,YAAN,MAAgB;AAAA;AAAA,IAEtB;AAAA,IACA,YAA6B,CAAC;AAAA,IAC9B,cAAyB,IAAI,UAAU;AAAA;AAAA,IAGvC;AAAA,IAEA,YAAa,MAAc,WAA4B,UAAkB;AACxE,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,OAAO;AACZ,WAAK,aAAa,SAAS;AAC3B,WAAK,WAAW;AAAA,IACjB;AAAA,IAEA,aAAc,WAA4B;AACzC,UAAI,CAAC;AAAW,cAAM,IAAI,MAAM,2BAA2B;AAC3D,WAAK,YAAY;AACjB,WAAK,YAAY,MAAM;AACvB,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ;AACrC,aAAK,YAAY,OAAO,UAAU,CAAC,EAAE,eAAe,CAAC;AAAA,IACvD;AAAA,IAEA,YAAa,KAAwB;AACpC,eAAS,IAAI,GAAG,IAAI,IAAI,QAAQ;AAC/B,YAAI,KAAK,YAAY,SAAS,IAAI,CAAC,CAAC;AAAG,iBAAO;AAC/C,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,MAAO,UAAoB,UAAkB,MAAc,MAAe,QAAsB,OAAe,OAAiB,WAAyB;AACxJ,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AAEzD,UAAI,QAAQ,KAAK,YAAY,GAAG;AAC/B,gBAAQ,KAAK;AACb,YAAI,WAAW;AAAG,sBAAY,KAAK;AAAA,MACpC;AAEA,UAAI,YAAY,KAAK;AACrB,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG;AAC5C,kBAAU,CAAC,EAAE,MAAM,UAAU,UAAU,MAAM,QAAQ,OAAO,OAAO,SAAS;AAAA,IAC9E;AAAA,EACD;AAMO,MAAK,WAAL,kBAAKC,cAAL;AAGN,IAAAA,oBAAA;AAMA,IAAAA,oBAAA;AAKA,IAAAA,oBAAA;AAOA,IAAAA,oBAAA;AArBW,WAAAA;AAAA,KAAA;AA4BL,MAAK,eAAL,kBAAKC,kBAAL;AACN,IAAAA,4BAAA;AAAO,IAAAA,4BAAA;AADI,WAAAA;AAAA,KAAA;AAIZ,MAAM,WAAW;AAAA,IAChB,QAAQ;AAAA,IACR,GAAG;AAAA,IACH,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IAET,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IAEN,YAAY;AAAA,IACZ,QAAQ;AAAA,IAER,OAAO;AAAA,IACP,WAAW;AAAA,IAEX,cAAc;AAAA,IACd,qBAAqB;AAAA,IAErB,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,mBAAmB;AAAA,IAEnB,0BAA0B;AAAA,IAC1B,2BAA2B;AAAA,IAC3B,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,sBAAsB;AAAA,IACtB,wBAAwB;AAAA,IAExB,UAAU;AAAA,EACX;AAGO,MAAe,WAAf,MAAwB;AAAA,IAC9B;AAAA,IACA;AAAA,IAEA,YAAa,YAAoB,aAAuB;AACvD,WAAK,cAAc;AACnB,WAAK,SAAS,MAAM,cAAc,aAAa,KAAK,gBAAgB,CAAC;AAAA,IACtE;AAAA,IAEA,iBAAkB;AACjB,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,kBAA2B;AAC1B,aAAO;AAAA,IACR;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,OAAO,SAAS,KAAK,gBAAgB;AAAA,IAClD;AAAA,IAEA,cAAuB;AACtB,aAAO,KAAK,OAAO,KAAK,OAAO,SAAS,KAAK,gBAAgB,CAAC;AAAA,IAC/D;AAAA,IAIA,OAAO,QAAS,QAAyB,MAAc;AACtD,UAAI,IAAI,OAAO;AACf,eAAS,IAAI,GAAG,IAAI,GAAG;AACtB,YAAI,OAAO,CAAC,IAAI;AAAM,iBAAO,IAAI;AAClC,aAAO,IAAI;AAAA,IACZ;AAAA,IAEA,OAAO,OAAQ,QAAyB,MAAc,MAAc;AACnE,UAAI,IAAI,OAAO;AACf,eAAS,IAAI,MAAM,IAAI,GAAG,KAAK;AAC9B,YAAI,OAAO,CAAC,IAAI;AAAM,iBAAO,IAAI;AAClC,aAAO,IAAI;AAAA,IACZ;AAAA,EACD;AAaO,MAAe,gBAAf,cAAqC,SAAS;AAAA,IAC1C;AAAA;AAAA,IAEV,YAAa,YAAoB,aAAqB,aAAuB;AAC5E,YAAM,YAAY,WAAW;AAC7B,WAAK,SAAS,MAAM;AAAA,QAAc,aAAa,cAAc;AAAA;AAAA,MAAiB;AAC9E,WAAK,OAAO,aAAa,CAAC,IAAI;AAAA,IAC/B;AAAA;AAAA,IAGA,UAAW,OAAe;AACzB,WAAK,OAAO,KAAK,IAAI;AAAA,IACtB;AAAA;AAAA,IAGA,WAAY,OAAe;AAC1B,WAAK,OAAO,KAAK,IAAI;AAAA,IACtB;AAAA;AAAA;AAAA,IAIA,OAAQ,aAAqB;AAC5B,UAAI,OAAO,KAAK,cAAc,IAAI,cAAc;AAChD,UAAI,KAAK,OAAO,SAAS,MAAM;AAC9B,YAAI,YAAY,MAAM,cAAc,IAAI;AACxC,cAAM,UAAU,KAAK,QAAQ,GAAG,WAAW,GAAG,IAAI;AAClD,aAAK,SAAS;AAAA,MACf;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBA,UAAW,QAAgB,OAAe,OAAe,OAAe,QAAgB,KAAa,KAAa,KACjH,KAAa,OAAe,QAAgB;AAC5C,UAAI,SAAS,KAAK;AAClB,UAAI,IAAI,KAAK,cAAc,IAAI,SAAS;AACxC,UAAI,SAAS;AAAG,eAAO,KAAK,IAAI,IAAc;AAC9C,UAAI,QAAQ,QAAQ,MAAM,IAAI,OAAO,MAAM,QAAQ,SAAS,MAAM,IAAI,OAAO;AAC7E,UAAI,SAAS,MAAM,OAAO,IAAI,QAAQ,SAAS,MAAO,SAAS,MAAM,OAAO,IAAI,SAAS,UAAU;AACnG,UAAI,MAAM,OAAO,IAAI,MAAM,MAAM,OAAO,IAAI;AAC5C,UAAI,MAAM,MAAM,SAAS,MAAM,OAAO,OAAO,YAAY,MAAM,MAAM,UAAU,MAAM,OAAO,OAAO;AACnG,UAAI,IAAI,QAAQ,IAAI,IAAI,SAAS;AACjC,eAAS,IAAI,IAAI,IAAmB,IAAI,GAAG,KAAK,GAAG;AAClD,eAAO,CAAC,IAAI;AACZ,eAAO,IAAI,CAAC,IAAI;AAChB,cAAM;AACN,cAAM;AACN,eAAO;AACP,eAAO;AACP,aAAK;AACL,aAAK;AAAA,MACN;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,eAAgB,MAAc,YAAoB,aAAqB,GAAW;AACjF,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,CAAC,IAAI,MAAM;AACrB,YAAIC,KAAI,KAAK,OAAO,UAAU,GAAGC,KAAI,KAAK,OAAO,aAAa,WAAW;AACzE,eAAOA,MAAK,OAAOD,OAAM,OAAO,CAAC,IAAIA,OAAM,OAAO,IAAI,CAAC,IAAIC;AAAA,MAC5D;AACA,UAAI,IAAI,IAAI;AACZ,WAAK,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG;AAC3B,YAAI,OAAO,CAAC,KAAK,MAAM;AACtB,cAAID,KAAI,OAAO,IAAI,CAAC,GAAGC,KAAI,OAAO,IAAI,CAAC;AACvC,iBAAOA,MAAK,OAAOD,OAAM,OAAO,CAAC,IAAIA,OAAM,OAAO,IAAI,CAAC,IAAIC;AAAA,QAC5D;AAAA,MACD;AACA,oBAAc,KAAK,gBAAgB;AACnC,UAAI,IAAI,OAAO,IAAI,CAAC,GAAG,IAAI,OAAO,IAAI,CAAC;AACvC,aAAO,KAAK,OAAO,MAAM,KAAK,OAAO,UAAU,IAAI,MAAM,KAAK,OAAO,aAAa,WAAW,IAAI;AAAA,IAClG;AAAA,EACD;AAEO,MAAe,iBAAf,cAAsC,cAAc;AAAA,IAC1D,YAAa,YAAoB,aAAqB,YAAoB;AACzE,YAAM,YAAY,aAAa,CAAC,UAAU,CAAC;AAAA,IAC5C;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,OAAe,MAAc,OAAe;AACrD,gBAAU;AACV,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAU,IAAI;AAAA,IACnC;AAAA;AAAA,IAGA,cAAe,MAAc;AAC5B,UAAI,SAAS,KAAK;AAClB,UAAI,IAAI,OAAO,SAAS;AACxB,eAAS,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG;AAClC,YAAI,OAAO,EAAE,IAAI,MAAM;AACtB,cAAI,KAAK;AACT;AAAA,QACD;AAAA,MACD;AAEA,UAAI,YAAY,KAAK,OAAO,KAAK,CAAC;AAClC,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC,GAAG,QAAQ;AAAA,YAAO,IAAI;AAAA;AAAA,UAAU;AACrD,iBAAO,SAAS,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI,WAAW;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAU,IAAI;AAAA,QACjH,KAAK;AACJ,iBAAO;AAAA,YAAO,IAAI;AAAA;AAAA,UAAU;AAAA,MAC9B;AACA,aAAO,KAAK;AAAA,QAAe;AAAA,QAAM;AAAA,QAAG;AAAA,QAAY,YAAY;AAAA;AAAA,MAAW;AAAA,IACxE;AAAA,IAEA,iBAAkB,MAAc,OAAe,OAAiB,SAAiB,OAAe;AAC/F,UAAI,OAAO,KAAK,OAAO,CAAC,GAAG;AAC1B,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,mBAAO;AAAA,UACR,KAAK;AACJ,mBAAO,WAAW,QAAQ,WAAW;AAAA,QACvC;AACA,eAAO;AAAA,MACR;AACA,UAAI,QAAQ,KAAK,cAAc,IAAI;AACnC,cAAQ,OAAO;AAAA,QACd,KAAK;AACJ,iBAAO,QAAQ,QAAQ;AAAA,QACxB,KAAK;AAAA,QACL,KAAK;AACJ,mBAAS,QAAQ;AAAA,MACnB;AACA,aAAO,UAAU,QAAQ;AAAA,IAC1B;AAAA,IAEA,iBAAkB,MAAc,OAAe,OAAiB,SAAiB,OAAe;AAC/F,UAAI,OAAO,KAAK,OAAO,CAAC,GAAG;AAC1B,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,mBAAO;AAAA,UACR,KAAK;AACJ,mBAAO,WAAW,QAAQ,WAAW;AAAA,QACvC;AACA,eAAO;AAAA,MACR;AACA,UAAI,QAAQ,KAAK,cAAc,IAAI;AACnC,UAAI,SAAS;AAAgB,eAAO,SAAS,QAAQ,SAAS;AAC9D,aAAO,WAAW,QAAQ,WAAW;AAAA,IACtC;AAAA,IAEA,kBAAmB,MAAc,OAAe,OAAiB,SAAiB,OAAe,OAAe;AAC/G,UAAI,OAAO,KAAK,OAAO,CAAC,GAAG;AAC1B,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,mBAAO;AAAA,UACR,KAAK;AACJ,mBAAO,WAAW,QAAQ,WAAW;AAAA,QACvC;AACA,eAAO;AAAA,MACR;AACA,UAAI,SAAS;AAAgB,eAAO,SAAS,QAAQ,SAAS;AAC9D,aAAO,WAAW,QAAQ,WAAW;AAAA,IACtC;AAAA,IAEA,cAAe,MAAc,OAAe,OAAiB,WAAyB,SAAiB,OAAe;AACrH,YAAM,SAAS,KAAK;AACpB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,mBAAO;AAAA,UACR,KAAK;AACJ,mBAAO,WAAW,QAAQ,WAAW;AAAA,QACvC;AACA,eAAO;AAAA,MACR;AACA,UAAI,QAAQ,KAAK,cAAc,IAAI,IAAI;AACvC,UAAI,SAAS,GAAG;AACf,YAAI,SAAS;AAAc,iBAAO,UAAU,QAAQ;AACpD,eAAO;AAAA,MACR;AAEA,UAAI,aAAa,gBAAqB;AACrC,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,mBAAO,SAAS,KAAK,IAAI,KAAK,IAAI,UAAU,OAAO,KAAK,IAAI,SAAS;AAAA,UACtE,KAAK;AAAA,UACL,KAAK;AACJ,mBAAO,WAAW,KAAK,IAAI,KAAK,IAAI,UAAU,OAAO,OAAO,IAAI,WAAW;AAAA,QAC7E;AAAA,MACD,OAAO;AACN,YAAI,IAAI;AACR,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,gBAAI,KAAK,IAAI,KAAK,IAAI,UAAU,OAAO,KAAK;AAC5C,mBAAO,KAAK,QAAQ,KAAK;AAAA,UAC1B,KAAK;AAAA,UACL,KAAK;AACJ,gBAAI,KAAK,IAAI,OAAO,IAAI,UAAU,OAAO,KAAK;AAC9C,mBAAO,KAAK,QAAQ,KAAK;AAAA,QAC3B;AAAA,MACD;AACA,aAAO,WAAW,QAAQ,SAAS;AAAA,IACpC;AAAA,EACD;AAGO,MAAe,iBAAf,cAAsC,cAAc;AAAA;AAAA;AAAA,IAG1D,YAAa,YAAoB,aAAqB,aAAqB,aAAqB;AAC/F,YAAM,YAAY,aAAa,CAAC,aAAa,WAAW,CAAC;AAAA,IAC1D;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,OAAe,MAAc,QAAgB,QAAgB;AACtE,eAAS;AACT,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AACnC,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AAAA,IACpC;AAAA,EACD;AAGO,MAAM,iBAAN,cAA6B,eAAuC;AAAA,IAC1E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,SAAS,MAAM,SAAS;AAChE,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAA6B,OAAe,OAAiB,WAAyB;AAChJ,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,WAAW,KAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK,UAAU,KAAK,KAAK,QAAQ;AAAA,IAC7G;AAAA,EACD;AAGO,MAAM,oBAAN,cAAgC,eAAuC;AAAA,IAC7E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE;AAAA,QAAM;AAAA,QAAY;AAAA,QACjB,SAAS,IAAI,MAAM;AAAA,QACnB,SAAS,IAAI,MAAM;AAAA,MACpB;AACA,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK;AAAQ;AAElB,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,iBAAK,IAAI,KAAK,KAAK;AACnB,iBAAK,IAAI,KAAK,KAAK;AACnB;AAAA,UACD,KAAK;AACJ,iBAAK,MAAM,KAAK,KAAK,IAAI,KAAK,KAAK;AACnC,iBAAK,MAAM,KAAK,KAAK,IAAI,KAAK,KAAK;AAAA,QACrC;AACA;AAAA,MACD;AAEA,UAAI,IAAI,GAAG,IAAI;AACf,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,KAAK;AACpD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,KAAK;AACpD;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY;AAAA;AAAA,UAAW;AACrE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY,KAAoB;AAAA;AAAA,UAAW;AAAA,MAC3F;AAEA,cAAQ,OAAO;AAAA,QACd,KAAK;AACJ,eAAK,IAAI,KAAK,KAAK,IAAI,IAAI;AAC3B,eAAK,IAAI,KAAK,KAAK,IAAI,IAAI;AAC3B;AAAA,QACD,KAAK;AAAA,QACL,KAAK;AACJ,eAAK,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK;AACvC,eAAK,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK;AACvC;AAAA,QACD,KAAK;AACJ,eAAK,KAAK,IAAI;AACd,eAAK,KAAK,IAAI;AAAA,MAChB;AAAA,IACD;AAAA,EACD;AAGO,MAAM,qBAAN,cAAiC,eAAuC;AAAA,IAC9E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,IAAI,MAAM,SAAS;AAC3D,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,IAAI,KAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK,GAAG,KAAK,KAAK,CAAC;AAAA,IACxF;AAAA,EACD;AAGO,MAAM,qBAAN,cAAiC,eAAuC;AAAA,IAC9E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,IAAI,MAAM,SAAS;AAC3D,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,IAAI,KAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK,GAAG,KAAK,KAAK,CAAC;AAAA,IACxF;AAAA,EACD;AAGO,MAAM,gBAAN,cAA4B,eAAuC;AAAA,IACzE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE;AAAA,QAAM;AAAA,QAAY;AAAA,QACjB,SAAS,SAAS,MAAM;AAAA,QACxB,SAAS,SAAS,MAAM;AAAA,MACzB;AACA,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK;AAAQ;AAElB,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,iBAAK,SAAS,KAAK,KAAK;AACxB,iBAAK,SAAS,KAAK,KAAK;AACxB;AAAA,UACD,KAAK;AACJ,iBAAK,WAAW,KAAK,KAAK,SAAS,KAAK,UAAU;AAClD,iBAAK,WAAW,KAAK,KAAK,SAAS,KAAK,UAAU;AAAA,QACpD;AACA;AAAA,MACD;AAEA,UAAI,GAAG;AACP,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,KAAK;AACpD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,KAAK;AACpD;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY;AAAA;AAAA,UAAW;AACrE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY,KAAoB;AAAA;AAAA,UAAW;AAAA,MAC3F;AACA,WAAK,KAAK,KAAK;AACf,WAAK,KAAK,KAAK;AAEf,UAAI,SAAS,GAAG;AACf,YAAI,SAAS,aAAc;AAC1B,eAAK,UAAU,IAAI,KAAK,KAAK;AAC7B,eAAK,UAAU,IAAI,KAAK,KAAK;AAAA,QAC9B,OAAO;AACN,eAAK,SAAS;AACd,eAAK,SAAS;AAAA,QACf;AAAA,MACD,OAAO;AACN,YAAI,KAAK,GAAG,KAAK;AACjB,YAAI,aAAa,gBAAqB;AACrC,kBAAQ,OAAO;AAAA,YACd,KAAK;AACJ,mBAAK,KAAK,KAAK;AACf,mBAAK,KAAK,KAAK;AACf,mBAAK,SAAS,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,OAAO,EAAE,IAAI,MAAM;AAC/D,mBAAK,SAAS,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,OAAO,EAAE,IAAI,MAAM;AAC/D;AAAA,YACD,KAAK;AAAA,YACL,KAAK;AACJ,mBAAK,KAAK;AACV,mBAAK,KAAK;AACV,mBAAK,SAAS,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,OAAO,EAAE,IAAI,MAAM;AAC/D,mBAAK,SAAS,MAAM,KAAK,IAAI,CAAC,IAAI,UAAU,OAAO,EAAE,IAAI,MAAM;AAC/D;AAAA,YACD,KAAK;AACJ,mBAAK,WAAW,IAAI,KAAK,KAAK,UAAU;AACxC,mBAAK,WAAW,IAAI,KAAK,KAAK,UAAU;AAAA,UAC1C;AAAA,QACD,OAAO;AACN,kBAAQ,OAAO;AAAA,YACd,KAAK;AACJ,mBAAK,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,UAAU,OAAO,CAAC;AACpD,mBAAK,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,UAAU,OAAO,CAAC;AACpD,mBAAK,SAAS,MAAM,IAAI,MAAM;AAC9B,mBAAK,SAAS,MAAM,IAAI,MAAM;AAC9B;AAAA,YACD,KAAK;AAAA,YACL,KAAK;AACJ,mBAAK,KAAK,IAAI,KAAK,MAAM,IAAI,UAAU,OAAO,CAAC;AAC/C,mBAAK,KAAK,IAAI,KAAK,MAAM,IAAI,UAAU,OAAO,CAAC;AAC/C,mBAAK,SAAS,MAAM,IAAI,MAAM;AAC9B,mBAAK,SAAS,MAAM,IAAI,MAAM;AAC9B;AAAA,YACD,KAAK;AACJ,mBAAK,WAAW,IAAI,KAAK,KAAK,UAAU;AACxC,mBAAK,WAAW,IAAI,KAAK,KAAK,UAAU;AAAA,UAC1C;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGO,MAAM,iBAAN,cAA6B,eAAuC;AAAA,IAC1E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,SAAS,MAAM,SAAS;AAChE,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,SAAS,KAAK,cAAc,MAAM,OAAO,OAAO,WAAW,KAAK,QAAQ,KAAK,KAAK,MAAM;AAAA,IAC/G;AAAA,EACD;AAGO,MAAM,iBAAN,cAA6B,eAAuC;AAAA,IAC1E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,SAAS,MAAM,SAAS;AAChE,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,SAAS,KAAK,cAAc,MAAM,OAAO,OAAO,WAAW,KAAK,QAAQ,KAAK,KAAK,MAAM;AAAA,IAC/G;AAAA,EACD;AAGO,MAAM,gBAAN,cAA4B,eAAuC;AAAA,IACzE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE;AAAA,QAAM;AAAA,QAAY;AAAA,QACjB,SAAS,SAAS,MAAM;AAAA,QACxB,SAAS,SAAS,MAAM;AAAA,MACzB;AACA,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK;AAAQ;AAElB,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,iBAAK,SAAS,KAAK,KAAK;AACxB,iBAAK,SAAS,KAAK,KAAK;AACxB;AAAA,UACD,KAAK;AACJ,iBAAK,WAAW,KAAK,KAAK,SAAS,KAAK,UAAU;AAClD,iBAAK,WAAW,KAAK,KAAK,SAAS,KAAK,UAAU;AAAA,QACpD;AACA;AAAA,MACD;AAEA,UAAI,IAAI,GAAG,IAAI;AACf,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,KAAK;AACpD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,KAAK;AACpD;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC1B;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY;AAAA;AAAA,UAAW;AACrE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY,KAAoB;AAAA;AAAA,UAAW;AAAA,MAC3F;AAEA,cAAQ,OAAO;AAAA,QACd,KAAK;AACJ,eAAK,SAAS,KAAK,KAAK,SAAS,IAAI;AACrC,eAAK,SAAS,KAAK,KAAK,SAAS,IAAI;AACrC;AAAA,QACD,KAAK;AAAA,QACL,KAAK;AACJ,eAAK,WAAW,KAAK,KAAK,SAAS,IAAI,KAAK,UAAU;AACtD,eAAK,WAAW,KAAK,KAAK,SAAS,IAAI,KAAK,UAAU;AACtD;AAAA,QACD,KAAK;AACJ,eAAK,UAAU,IAAI;AACnB,eAAK,UAAU,IAAI;AAAA,MACrB;AAAA,IACD;AAAA,EACD;AAGO,MAAM,iBAAN,cAA6B,eAAuC;AAAA,IAC1E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,SAAS,MAAM,SAAS;AAChE,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,SAAS,KAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,KAAK,MAAM;AAAA,IACvG;AAAA,EACD;AAGO,MAAM,iBAAN,cAA6B,eAAuC;AAAA,IAC1E,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,SAAS,MAAM,SAAS;AAChE,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,KAAK;AAAQ,aAAK,SAAS,KAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,KAAK,MAAM;AAAA,IACvG;AAAA,EACD;AAEO,MAAM,kBAAN,cAA8B,SAAiC;AAAA,IACrE,YAAY;AAAA,IAEZ,YAAa,YAAoB,WAAmB;AACnD,YAAM,YAAY,CAAC,SAAS,UAAU,MAAM,SAAS,CAAC;AACtD,WAAK,YAAY;AAAA,IAClB;AAAA,IAEO,kBAAmB;AACzB,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKO,SAAU,OAAe,MAAc,SAAkB;AAC/D,eAAS;AACT,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAY,IAAI;AAAA,IACrC;AAAA,IAEO,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AAChJ,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK;AAAQ;AAElB,UAAI,aAAa,gBAAqB;AACrC,YAAI,SAAS;AAAgB,eAAK,UAAU,KAAK,KAAK;AACtD;AAAA,MACD;AAEA,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,SAAS,iBAAkB,SAAS;AAAgB,eAAK,UAAU,KAAK,KAAK;AACjF;AAAA,MACD;AACA,WAAK,UAAU,KAAK;AAAA,QAAO,SAAS;AAAA,UAAO;AAAA,UAAQ;AAAA,UAAM;AAAA;AAAA,QAAY,IAAI;AAAA;AAAA,MAAY;AAAA,IACtF;AAAA,EACD;AAGO,MAAM,eAAN,cAA2B,cAAsC;AAAA,IACvE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,MAAM,MAAM;AAAA,QACrB,SAAS,QAAQ,MAAM;AAAA,MACxB,CAAC;AACD,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,GAAW,GAAW,GAAW,GAAW;AAClF,eAAS;AACT,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAAA,IAC/B;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,SAAS,KAAK;AAClB,UAAI,QAAQ,KAAK;AACjB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,QAAQ,KAAK,KAAK;AACtB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,kBAAM,aAAa,KAAK;AACxB;AAAA,UACD,KAAK;AACJ,kBAAM;AAAA,eAAK,MAAM,IAAI,MAAM,KAAK;AAAA,eAAQ,MAAM,IAAI,MAAM,KAAK;AAAA,eAAQ,MAAM,IAAI,MAAM,KAAK;AAAA,eACxF,MAAM,IAAI,MAAM,KAAK;AAAA,YAAK;AAAA,QAC9B;AACA;AAAA,MACD;AAEA,UAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;AAC7B,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY;AAAA;AAAA,UAAW;AAChE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB;AAAA;AAAA,UAAW;AACpF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AACxF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAAA,MAC1F;AACA,UAAI,SAAS;AACZ,cAAM,IAAI,GAAG,GAAG,GAAG,CAAC;AAAA,WAChB;AACJ,YAAI,SAAS;AAAgB,gBAAM,aAAa,KAAK,KAAK,KAAK;AAC/D,cAAM,KAAK,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,KAAK;AAAA,MACrG;AAAA,IACD;AAAA,EACD;AAGO,MAAM,cAAN,cAA0B,cAAsC;AAAA,IACtE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,MAAM,MAAM;AAAA,MACtB,CAAC;AACD,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,GAAW,GAAW,GAAW;AACvE,gBAAU;AACV,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAAA,IAC/B;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,SAAS,KAAK;AAClB,UAAI,QAAQ,KAAK;AACjB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,QAAQ,KAAK,KAAK;AACtB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,kBAAM,IAAI,MAAM;AAChB,kBAAM,IAAI,MAAM;AAChB,kBAAM,IAAI,MAAM;AAChB;AAAA,UACD,KAAK;AACJ,kBAAM,MAAM,MAAM,IAAI,MAAM,KAAK;AACjC,kBAAM,MAAM,MAAM,IAAI,MAAM,KAAK;AACjC,kBAAM,MAAM,MAAM,IAAI,MAAM,KAAK;AAAA,QACnC;AACA;AAAA,MACD;AAEA,UAAI,IAAI,GAAG,IAAI,GAAG,IAAI;AACtB,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK,OAAO,KAAK,CAAC;AAClC,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY;AAAA;AAAA,UAAW;AAChE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB;AAAA;AAAA,UAAW;AACpF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAAA,MAC1F;AACA,UAAI,SAAS,GAAG;AACf,cAAM,IAAI;AACV,cAAM,IAAI;AACV,cAAM,IAAI;AAAA,MACX,OAAO;AACN,YAAI,SAAS,eAAgB;AAC5B,cAAI,QAAQ,KAAK,KAAK;AACtB,gBAAM,IAAI,MAAM;AAChB,gBAAM,IAAI,MAAM;AAChB,gBAAM,IAAI,MAAM;AAAA,QACjB;AACA,cAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,cAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,cAAM,MAAM,IAAI,MAAM,KAAK;AAAA,MAC5B;AAAA,IACD;AAAA,EACD;AAGO,MAAM,gBAAN,cAA4B,eAAuC;AAAA,IACzE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa,SAAS,QAAQ,MAAM,SAAS;AAC/D,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,QAAQ,KAAK;AACjB,UAAI,OAAO,KAAK,OAAO,CAAC,GAAG;AAC1B,YAAI,QAAQ,KAAK,KAAK;AACtB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,kBAAM,IAAI,MAAM;AAChB;AAAA,UACD,KAAK;AACJ,kBAAM,MAAM,MAAM,IAAI,MAAM,KAAK;AAAA,QACnC;AACA;AAAA,MACD;AAEA,UAAI,IAAI,KAAK,cAAc,IAAI;AAC/B,UAAI,SAAS;AACZ,cAAM,IAAI;AAAA,WACN;AACJ,YAAI,SAAS;AAAgB,gBAAM,IAAI,KAAK,KAAK,MAAM;AACvD,cAAM,MAAM,IAAI,MAAM,KAAK;AAAA,MAC5B;AAAA,IACD;AAAA,EACD;AAGO,MAAM,gBAAN,cAA4B,cAAsC;AAAA,IACxE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,MAAM,MAAM;AAAA,QACrB,SAAS,QAAQ,MAAM;AAAA,QACvB,SAAS,OAAO,MAAM;AAAA,MACvB,CAAC;AACD,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,GAAW,GAAW,GAAW,GAAW,IAAY,IAAY,IAAY;AACtH,gBAAU;AACV,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAO,IAAI;AAC/B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAO,IAAI;AAC/B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAO,IAAI;AAAA,IAChC;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,SAAS,KAAK;AAClB,UAAI,QAAQ,KAAK,OAAO,OAAO,KAAK;AACpC,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,aAAa,KAAK,KAAK,OAAO,YAAY,KAAK,KAAK;AACxD,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,kBAAM,aAAa,UAAU;AAC7B,iBAAK,IAAI,UAAU;AACnB,iBAAK,IAAI,UAAU;AACnB,iBAAK,IAAI,UAAU;AACnB;AAAA,UACD,KAAK;AACJ,kBAAM;AAAA,eAAK,WAAW,IAAI,MAAM,KAAK;AAAA,eAAQ,WAAW,IAAI,MAAM,KAAK;AAAA,eAAQ,WAAW,IAAI,MAAM,KAAK;AAAA,eACvG,WAAW,IAAI,MAAM,KAAK;AAAA,YAAK;AACjC,iBAAK,MAAM,UAAU,IAAI,KAAK,KAAK;AACnC,iBAAK,MAAM,UAAU,IAAI,KAAK,KAAK;AACnC,iBAAK,MAAM,UAAU,IAAI,KAAK,KAAK;AAAA,QACrC;AACA;AAAA,MACD;AAEA,UAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK;AACrD,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK,OAAO,KAAK,CAAC;AAClC,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,iBAAO;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAO,IAAI,MAAM;AAClD,iBAAO;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAO,IAAI,MAAM;AAClD,iBAAO;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAO,IAAI,MAAM;AAClD;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY;AAAA;AAAA,UAAW;AAChE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB;AAAA;AAAA,UAAW;AACpF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AACxF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AACxF,eAAK,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAS,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAC1F,eAAK,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAS,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAC1F,eAAK,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAS,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAAA,MAC5F;AAEA,UAAI,SAAS,GAAG;AACf,cAAM,IAAI,GAAG,GAAG,GAAG,CAAC;AACpB,aAAK,IAAI;AACT,aAAK,IAAI;AACT,aAAK,IAAI;AAAA,MACV,OAAO;AACN,YAAI,SAAS,eAAgB;AAC5B,gBAAM,aAAa,KAAK,KAAK,KAAK;AAClC,cAAI,YAAY,KAAK,KAAK;AAC1B,eAAK,IAAI,UAAU;AACnB,eAAK,IAAI,UAAU;AACnB,eAAK,IAAI,UAAU;AAAA,QACpB;AACA,cAAM,KAAK,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,KAAK;AACpG,aAAK,MAAM,KAAK,KAAK,KAAK;AAC1B,aAAK,MAAM,KAAK,KAAK,KAAK;AAC1B,aAAK,MAAM,KAAK,KAAK,KAAK;AAAA,MAC3B;AAAA,IACD;AAAA,EACD;AAGO,MAAM,eAAN,cAA2B,cAAsC;AAAA,IACvE,YAAY;AAAA,IAEZ,YAAa,YAAoB,aAAqB,WAAmB;AACxE,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,MAAM,MAAM;AAAA,QACrB,SAAS,OAAO,MAAM;AAAA,MACvB,CAAC;AACD,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,GAAW,GAAW,GAAW,IAAY,IAAY,IAAY;AAC3G,eAAS;AACT,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAC9B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAO,IAAI;AAC/B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAO,IAAI;AAC/B,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAO,IAAI;AAAA,IAChC;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,SAAS,KAAK;AAClB,UAAI,QAAQ,KAAK,OAAO,OAAO,KAAK;AACpC,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,aAAa,KAAK,KAAK,OAAO,YAAY,KAAK,KAAK;AACxD,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,kBAAM,IAAI,WAAW;AACrB,kBAAM,IAAI,WAAW;AACrB,kBAAM,IAAI,WAAW;AACrB,iBAAK,IAAI,UAAU;AACnB,iBAAK,IAAI,UAAU;AACnB,iBAAK,IAAI,UAAU;AACnB;AAAA,UACD,KAAK;AACJ,kBAAM,MAAM,WAAW,IAAI,MAAM,KAAK;AACtC,kBAAM,MAAM,WAAW,IAAI,MAAM,KAAK;AACtC,kBAAM,MAAM,WAAW,IAAI,MAAM,KAAK;AACtC,iBAAK,MAAM,UAAU,IAAI,KAAK,KAAK;AACnC,iBAAK,MAAM,UAAU,IAAI,KAAK,KAAK;AACnC,iBAAK,MAAM,UAAU,IAAI,KAAK,KAAK;AAAA,QACrC;AACA;AAAA,MACD;AAEA,UAAI,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK;AACrD,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,iBAAO;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAO,IAAI,MAAM;AAClD,iBAAO;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAO,IAAI,MAAM;AAClD,iBAAO;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAO,IAAI,MAAM;AAClD;AAAA,QACD,KAAK;AACJ,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB,eAAK;AAAA,YAAO,IAAI;AAAA;AAAA,UAAO;AACvB;AAAA,QACD;AACC,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY;AAAA;AAAA,UAAW;AAChE,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB;AAAA;AAAA,UAAW;AACpF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AACxF,eAAK,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAS,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAC1F,eAAK,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAS,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAC1F,eAAK,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAS,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAAA,MAC5F;AAEA,UAAI,SAAS,GAAG;AACf,cAAM,IAAI;AACV,cAAM,IAAI;AACV,cAAM,IAAI;AACV,aAAK,IAAI;AACT,aAAK,IAAI;AACT,aAAK,IAAI;AAAA,MACV,OAAO;AACN,YAAI,SAAS,eAAgB;AAC5B,cAAI,aAAa,KAAK,KAAK,OAAO,YAAY,KAAK,KAAK;AACxD,gBAAM,IAAI,WAAW;AACrB,gBAAM,IAAI,WAAW;AACrB,gBAAM,IAAI,WAAW;AACrB,eAAK,IAAI,UAAU;AACnB,eAAK,IAAI,UAAU;AACnB,eAAK,IAAI,UAAU;AAAA,QACpB;AACA,cAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,cAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,cAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,aAAK,MAAM,KAAK,KAAK,KAAK;AAC1B,aAAK,MAAM,KAAK,KAAK,KAAK;AAC1B,aAAK,MAAM,KAAK,KAAK,KAAK;AAAA,MAC3B;AAAA,IACD;AAAA,EACD;AAGO,MAAM,qBAAN,cAAiC,SAAiC;AAAA,IACxE,YAAY;AAAA;AAAA,IAGZ;AAAA,IAEA,YAAa,YAAoB,WAAmB;AACnD,YAAM,YAAY;AAAA,QACjB,SAAS,aAAa,MAAM;AAAA,MAC7B,CAAC;AACD,WAAK,YAAY;AACjB,WAAK,kBAAkB,IAAI,MAAc,UAAU;AAAA,IACpD;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,OAAO;AAAA,IACpB;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,gBAA+B;AACrE,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK,gBAAgB,KAAK,IAAI;AAAA,IAC/B;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,aAAa,gBAAqB;AACrC,YAAI,SAAS;AAAgB,eAAK,cAAc,UAAU,MAAM,KAAK,KAAK,cAAc;AACxF;AAAA,MACD;AAEA,UAAI,OAAO,KAAK,OAAO,CAAC,GAAG;AAC1B,YAAI,SAAS,iBAAkB,SAAS;AAAgB,eAAK,cAAc,UAAU,MAAM,KAAK,KAAK,cAAc;AACnH;AAAA,MACD;AAEA,WAAK,cAAc,UAAU,MAAM,KAAK,gBAAgB,SAAS,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC;AAAA,IAC7F;AAAA,IAEA,cAAe,UAAoB,MAAY,gBAA+B;AAC7E,WAAK,cAAc,CAAC,iBAAiB,OAAO,SAAS,cAAc,KAAK,WAAW,cAAc,CAAC;AAAA,IACnG;AAAA,EACD;AAGO,MAAM,iBAAN,cAA6B,cAAsC;AAAA,IACzE,YAAY;AAAA;AAAA,IAGZ;AAAA;AAAA,IAGA;AAAA,IAEA,YAAa,YAAoB,aAAqB,WAAmB,YAA8B;AACtG,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,SAAS,MAAM,YAAY,MAAM,WAAW;AAAA,MACtD,CAAC;AACD,WAAK,YAAY;AACjB,WAAK,aAAa;AAClB,WAAK,WAAW,IAAI,MAAuB,UAAU;AAAA,IACtD;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,OAAO;AAAA,IACpB;AAAA;AAAA;AAAA,IAIA,SAAU,OAAe,MAAc,UAA2B;AACjE,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK,SAAS,KAAK,IAAI;AAAA,IACxB;AAAA;AAAA;AAAA,IAIA,UAAW,QAAgB,OAAe,OAAe,OAAe,QAAgB,KAAa,KAAa,KACjH,KAAa,OAAe,QAAgB;AAC5C,UAAI,SAAS,KAAK;AAClB,UAAI,IAAI,KAAK,cAAc,IAAI,SAAS;AACxC,UAAI,SAAS;AAAG,eAAO,KAAK,IAAI,IAAc;AAC9C,UAAI,QAAQ,QAAQ,MAAM,IAAI,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM;AACrE,UAAI,SAAS,MAAM,OAAO,IAAI,QAAQ,SAAS,MAAO,QAAQ,MAAM,MAAM,cAAc;AACxF,UAAI,MAAM,OAAO,IAAI,MAAM,MAAM,OAAO,IAAI;AAC5C,UAAI,MAAM,MAAM,SAAS,MAAM,OAAO,OAAO,YAAY,KAAK,MAAM,MAAM,OAAO,OAAO;AACxF,UAAI,IAAI,QAAQ,IAAI,IAAI;AACxB,eAAS,IAAI,IAAI,IAAmB,IAAI,GAAG,KAAK,GAAG;AAClD,eAAO,CAAC,IAAI;AACZ,eAAO,IAAI,CAAC,IAAI;AAChB,cAAM;AACN,cAAM;AACN,eAAO;AACP,eAAO;AACP,aAAK;AACL,aAAK;AAAA,MACN;AAAA,IACD;AAAA,IAEA,gBAAiB,MAAc,OAAe;AAC7C,UAAI,SAAS,KAAK;AAClB,UAAI,IAAI,OAAO,KAAK;AACpB,cAAQ,GAAG;AAAA,QACV,KAAK;AACJ,cAAID,KAAI,KAAK,OAAO,KAAK;AACzB,kBAAQ,OAAOA,OAAM,KAAK,OAAO,QAAQ,KAAK,gBAAgB,CAAC,IAAIA;AAAA,QACpE,KAAK;AACJ,iBAAO;AAAA,MACT;AACA,WAAK;AACL,UAAI,OAAO,CAAC,IAAI,MAAM;AACrB,YAAIA,KAAI,KAAK,OAAO,KAAK;AACzB,eAAO,OAAO,IAAI,CAAC,KAAK,OAAOA,OAAM,OAAO,CAAC,IAAIA;AAAA,MAClD;AACA,UAAI,IAAI,IAAI;AACZ,WAAK,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG;AAC3B,YAAI,OAAO,CAAC,KAAK,MAAM;AACtB,cAAIA,KAAI,OAAO,IAAI,CAAC,GAAGC,KAAI,OAAO,IAAI,CAAC;AACvC,iBAAOA,MAAK,OAAOD,OAAM,OAAO,CAAC,IAAIA,OAAM,OAAO,IAAI,CAAC,IAAIC;AAAA,QAC5D;AAAA,MACD;AACA,UAAI,IAAI,OAAO,IAAI,CAAC,GAAG,IAAI,OAAO,IAAI,CAAC;AACvC,aAAO,KAAK,IAAI,MAAM,OAAO,MAAM,KAAK,OAAO,QAAQ,KAAK,gBAAgB,CAAC,IAAI;AAAA,IAClF;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,OAAa,SAAS,MAAM,KAAK,SAAS;AAC9C,UAAI,CAAC,KAAK,KAAK;AAAQ;AACvB,UAAI,iBAAoC,KAAK,cAAc;AAC3D,UAAI,CAAC;AAAgB;AACrB,UAAI,EAAE,0BAA0B,qBAAwC,eAAgB,sBAAsB,KAAK;AAAY;AAE/H,UAAI,SAAwB,KAAK;AACjC,UAAI,OAAO,UAAU;AAAG,gBAAQ;AAEhC,UAAI,WAAW,KAAK;AACpB,UAAI,cAAc,SAAS,CAAC,EAAE;AAE9B,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,mBAAO,SAAS;AAChB;AAAA,UACD,KAAK;AACJ,gBAAI,SAAS,GAAG;AACf,qBAAO,SAAS;AAChB;AAAA,YACD;AACA,mBAAO,SAAS;AAChB,gBAAI,mBAAqC;AACzC,gBAAI,CAAC,iBAAiB,OAAO;AAE5B,kBAAI,gBAAgB,iBAAiB;AACrC,uBAAS,IAAI,GAAG,IAAI,aAAa;AAChC,uBAAO,CAAC,MAAM,cAAc,CAAC,IAAI,OAAO,CAAC,KAAK;AAAA,YAChD,OAAO;AAEN,sBAAQ,IAAI;AACZ,uBAAS,IAAI,GAAG,IAAI,aAAa;AAChC,uBAAO,CAAC,KAAK;AAAA,YACf;AAAA,QACF;AACA;AAAA,MACD;AAEA,aAAO,SAAS;AAChB,UAAI,QAAQ,OAAO,OAAO,SAAS,CAAC,GAAG;AACtC,YAAI,eAAe,SAAS,OAAO,SAAS,CAAC;AAC7C,YAAI,SAAS,GAAG;AACf,cAAI,SAAS,aAAc;AAC1B,gBAAI,mBAAmB;AACvB,gBAAI,CAAC,iBAAiB,OAAO;AAE5B,kBAAI,gBAAgB,iBAAiB;AACrC,uBAASC,KAAI,GAAGA,KAAI,aAAaA;AAChC,uBAAOA,EAAC,KAAK,aAAaA,EAAC,IAAI,cAAcA,EAAC;AAAA,YAChD,OAAO;AAEN,uBAASA,KAAI,GAAGA,KAAI,aAAaA;AAChC,uBAAOA,EAAC,KAAK,aAAaA,EAAC;AAAA,YAC7B;AAAA,UACD;AACC,kBAAM,UAAU,cAAc,GAAG,QAAQ,GAAG,WAAW;AAAA,QACzD,OAAO;AACN,kBAAQ,OAAO;AAAA,YACd,KAAK,eAAgB;AACpB,kBAAIC,oBAAmB;AACvB,kBAAI,CAACA,kBAAiB,OAAO;AAE5B,oBAAI,gBAAgBA,kBAAiB;AACrC,yBAASD,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,sBAAI,QAAQ,cAAcA,EAAC;AAC3B,yBAAOA,EAAC,IAAI,SAAS,aAAaA,EAAC,IAAI,SAAS;AAAA,gBACjD;AAAA,cACD,OAAO;AAEN,yBAASA,KAAI,GAAGA,KAAI,aAAaA;AAChC,yBAAOA,EAAC,IAAI,aAAaA,EAAC,IAAI;AAAA,cAChC;AACA;AAAA,YACD;AAAA,YACA,KAAK;AAAA,YACL,KAAK;AACJ,uBAASA,KAAI,GAAGA,KAAI,aAAaA;AAChC,uBAAOA,EAAC,MAAM,aAAaA,EAAC,IAAI,OAAOA,EAAC,KAAK;AAC9C;AAAA,YACD,KAAK;AACJ,kBAAI,mBAAmB;AACvB,kBAAI,CAAC,iBAAiB,OAAO;AAE5B,oBAAI,gBAAgB,iBAAiB;AACrC,yBAASA,KAAI,GAAGA,KAAI,aAAaA;AAChC,yBAAOA,EAAC,MAAM,aAAaA,EAAC,IAAI,cAAcA,EAAC,KAAK;AAAA,cACtD,OAAO;AAEN,yBAASA,KAAI,GAAGA,KAAI,aAAaA;AAChC,yBAAOA,EAAC,KAAK,aAAaA,EAAC,IAAI;AAAA,cACjC;AAAA,UACF;AAAA,QACD;AACA;AAAA,MACD;AAGA,UAAI,QAAQ,SAAS,QAAQ,QAAQ,IAAI;AACzC,UAAI,UAAU,KAAK,gBAAgB,MAAM,KAAK;AAC9C,UAAI,eAAe,SAAS,KAAK;AACjC,UAAI,eAAe,SAAS,QAAQ,CAAC;AAErC,UAAI,SAAS,GAAG;AACf,YAAI,SAAS,aAAc;AAC1B,cAAI,mBAAmB;AACvB,cAAI,CAAC,iBAAiB,OAAO;AAE5B,gBAAI,gBAAgB,iBAAiB;AACrC,qBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,kBAAI,OAAO,aAAaA,EAAC;AACzB,qBAAOA,EAAC,KAAK,QAAQ,aAAaA,EAAC,IAAI,QAAQ,UAAU,cAAcA,EAAC;AAAA,YACzE;AAAA,UACD,OAAO;AAEN,qBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,kBAAI,OAAO,aAAaA,EAAC;AACzB,qBAAOA,EAAC,KAAK,QAAQ,aAAaA,EAAC,IAAI,QAAQ;AAAA,YAChD;AAAA,UACD;AAAA,QACD,OAAO;AACN,mBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,gBAAI,OAAO,aAAaA,EAAC;AACzB,mBAAOA,EAAC,IAAI,QAAQ,aAAaA,EAAC,IAAI,QAAQ;AAAA,UAC/C;AAAA,QACD;AAAA,MACD,OAAO;AACN,gBAAQ,OAAO;AAAA,UACd,KAAK,eAAgB;AACpB,gBAAIC,oBAAmB;AACvB,gBAAI,CAACA,kBAAiB,OAAO;AAE5B,kBAAI,gBAAgBA,kBAAiB;AACrC,uBAASD,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,oBAAI,OAAO,aAAaA,EAAC,GAAG,QAAQ,cAAcA,EAAC;AACnD,uBAAOA,EAAC,IAAI,SAAS,QAAQ,aAAaA,EAAC,IAAI,QAAQ,UAAU,SAAS;AAAA,cAC3E;AAAA,YACD,OAAO;AAEN,uBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,oBAAI,OAAO,aAAaA,EAAC;AACzB,uBAAOA,EAAC,KAAK,QAAQ,aAAaA,EAAC,IAAI,QAAQ,WAAW;AAAA,cAC3D;AAAA,YACD;AACA;AAAA,UACD;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AACJ,qBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,kBAAI,OAAO,aAAaA,EAAC;AACzB,qBAAOA,EAAC,MAAM,QAAQ,aAAaA,EAAC,IAAI,QAAQ,UAAU,OAAOA,EAAC,KAAK;AAAA,YACxE;AACA;AAAA,UACD,KAAK;AACJ,gBAAI,mBAAmB;AACvB,gBAAI,CAAC,iBAAiB,OAAO;AAE5B,kBAAI,gBAAgB,iBAAiB;AACrC,uBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,oBAAI,OAAO,aAAaA,EAAC;AACzB,uBAAOA,EAAC,MAAM,QAAQ,aAAaA,EAAC,IAAI,QAAQ,UAAU,cAAcA,EAAC,KAAK;AAAA,cAC/E;AAAA,YACD,OAAO;AAEN,uBAASA,KAAI,GAAGA,KAAI,aAAaA,MAAK;AACrC,oBAAI,OAAO,aAAaA,EAAC;AACzB,uBAAOA,EAAC,MAAM,QAAQ,aAAaA,EAAC,IAAI,QAAQ,WAAW;AAAA,cAC5D;AAAA,YACD;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGO,MAAM,iBAAN,cAA4B,SAAS;AAAA;AAAA,IAI3C;AAAA,IAEA,YAAa,YAAoB;AAChC,YAAM,YAAY,eAAc,WAAW;AAE3C,WAAK,SAAS,IAAI,MAAa,UAAU;AAAA,IAC1C;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,OAAO;AAAA,IACpB;AAAA;AAAA,IAGA,SAAU,OAAe,OAAc;AACtC,WAAK,OAAO,KAAK,IAAI,MAAM;AAC3B,WAAK,OAAO,KAAK,IAAI;AAAA,IACtB;AAAA;AAAA,IAGA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,CAAC;AAAa;AAElB,UAAI,SAAS,KAAK;AAClB,UAAI,aAAa,KAAK,OAAO;AAE7B,UAAI,WAAW,MAAM;AACpB,aAAK,MAAM,UAAU,UAAU,OAAO,WAAW,aAAa,OAAO,OAAO,SAAS;AACrF,mBAAW;AAAA,MACZ,WAAW,YAAY,OAAO,aAAa,CAAC;AAC3C;AACD,UAAI,OAAO,OAAO,CAAC;AAAG;AAEtB,UAAI,IAAI;AACR,UAAI,WAAW,OAAO,CAAC;AACtB,YAAI;AAAA,WACA;AACJ,YAAI,SAAS,QAAQ,QAAQ,QAAQ,IAAI;AACzC,YAAI,YAAY,OAAO,CAAC;AACxB,eAAO,IAAI,GAAG;AACb,cAAI,OAAO,IAAI,CAAC,KAAK;AAAW;AAChC;AAAA,QACD;AAAA,MACD;AACA,aAAO,IAAI,cAAc,QAAQ,OAAO,CAAC,GAAG;AAC3C,oBAAY,KAAK,KAAK,OAAO,CAAC,CAAC;AAAA,IACjC;AAAA,EACD;AAlDO,MAAM,gBAAN;AACN,gBADY,eACL,eAAc,CAAC,KAAK,SAAS,KAAK;AAoDnC,MAAM,qBAAN,cAAgC,SAAS;AAAA;AAAA,IAI/C;AAAA,IAEA,YAAa,YAAoB;AAChC,YAAM,YAAY,mBAAkB,WAAW;AAC/C,WAAK,aAAa,IAAI,MAA4B,UAAU;AAAA,IAC7D;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,OAAO;AAAA,IACpB;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,OAAe,MAAc,WAAiC;AACvE,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK,WAAW,KAAK,IAAI;AAAA,IAC1B;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,aAAa,gBAAqB;AACrC,YAAI,SAAS;AAAgB,gBAAM,UAAU,SAAS,OAAO,GAAG,SAAS,WAAW,GAAG,SAAS,MAAM,MAAM;AAC5G;AAAA,MACD;AAEA,UAAI,OAAO,KAAK,OAAO,CAAC,GAAG;AAC1B,YAAI,SAAS,iBAAkB,SAAS;AAAgB,gBAAM,UAAU,SAAS,OAAO,GAAG,SAAS,WAAW,GAAG,SAAS,MAAM,MAAM;AACvI;AAAA,MACD;AAEA,UAAI,MAAM,SAAS,QAAQ,KAAK,QAAQ,IAAI;AAC5C,UAAI,wBAAwB,KAAK,WAAW,GAAG;AAC/C,UAAI,CAAC;AACJ,cAAM,UAAU,SAAS,OAAO,GAAG,SAAS,WAAW,GAAG,SAAS,MAAM,MAAM;AAAA,WAC3E;AACJ,YAAI,YAAyB,SAAS;AACtC,YAAI,QAAqB,SAAS;AAClC,iBAAS,IAAI,GAAG,IAAI,sBAAsB,QAAQ,IAAI,GAAG;AACxD,oBAAU,CAAC,IAAI,MAAM,sBAAsB,CAAC,CAAC;AAAA,MAC/C;AAAA,IACD;AAAA,EACD;AA7CO,MAAM,oBAAN;AACN,gBADY,mBACL,eAAc,CAAC,KAAK,SAAS,SAAS;AAgDvC,MAAM,uBAAN,cAAmC,cAAc;AAAA;AAAA,IAEvD,kBAA0B;AAAA,IAE1B,YAAa,YAAoB,aAAqB,mBAA2B;AAChF,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,eAAe,MAAM;AAAA,MAC/B,CAAC;AACD,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,KAAa,UAAkB,eAAuB,UAAmB,SAAkB;AACjI,eAAS;AACT,WAAK,OAAO,KAAK,IAAI;AACrB,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAQ,IAAI;AAChC,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAa,IAAI;AACrC,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAmB,IAAI;AAC3C,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAa,IAAI,WAAW,IAAI;AACpD,WAAK;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAY,IAAI,UAAU,IAAI;AAAA,IACnD;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,aAA2B,SAAS,cAAc,KAAK,eAAe;AAC1E,UAAI,CAAC,WAAW;AAAQ;AAExB,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,uBAAW,MAAM,WAAW,KAAK;AACjC,uBAAW,WAAW,WAAW,KAAK;AACtC,uBAAW,gBAAgB,WAAW,KAAK;AAC3C,uBAAW,WAAW,WAAW,KAAK;AACtC,uBAAW,UAAU,WAAW,KAAK;AACrC;AAAA,UACD,KAAK;AACJ,uBAAW,QAAQ,WAAW,KAAK,MAAM,WAAW,OAAO;AAC3D,uBAAW,aAAa,WAAW,KAAK,WAAW,WAAW,YAAY;AAC1E,uBAAW,gBAAgB,WAAW,KAAK;AAC3C,uBAAW,WAAW,WAAW,KAAK;AACtC,uBAAW,UAAU,WAAW,KAAK;AAAA,QACvC;AACA;AAAA,MACD;AAEA,UAAI,MAAM,GAAG,WAAW;AACxB,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,gBAAM;AAAA,YAAO,IAAI;AAAA;AAAA,UAAQ;AACzB,qBAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAa;AACnC,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,kBAAQ;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAQ,IAAI,OAAO;AACrD,uBAAa;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAa,IAAI,YAAY;AACpE;AAAA,QACD,KAAK;AACJ,gBAAM;AAAA,YAAO,IAAI;AAAA;AAAA,UAAQ;AACzB,qBAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAa;AACnC;AAAA,QACD;AACC,gBAAM,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAU,YAAY;AAAA;AAAA,UAAW;AACpE,qBAAW,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAe,YAAY,KAAoB;AAAA;AAAA,UAAW;AAAA,MACpG;AAEA,UAAI,SAAS,eAAgB;AAC5B,mBAAW,MAAM,WAAW,KAAK,OAAO,MAAM,WAAW,KAAK,OAAO;AACrE,mBAAW,WAAW,WAAW,KAAK,YAAY,WAAW,WAAW,KAAK,YAAY;AAEzF,YAAI,aAAa,gBAAqB;AACrC,qBAAW,gBAAgB,WAAW,KAAK;AAC3C,qBAAW,WAAW,WAAW,KAAK;AACtC,qBAAW,UAAU,WAAW,KAAK;AAAA,QACtC,OAAO;AACN,qBAAW,gBAAgB;AAAA,YAAO,IAAI;AAAA;AAAA,UAAmB;AACzD,qBAAW,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAa,KAAK;AACnD,qBAAW,UAAU;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,KAAK;AAAA,QAClD;AAAA,MACD,OAAO;AACN,mBAAW,QAAQ,MAAM,WAAW,OAAO;AAC3C,mBAAW,aAAa,WAAW,WAAW,YAAY;AAC1D,YAAI,aAAa,eAAoB;AACpC,qBAAW,gBAAgB;AAAA,YAAO,IAAI;AAAA;AAAA,UAAmB;AACzD,qBAAW,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAa,KAAK;AACnD,qBAAW,UAAU;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,KAAK;AAAA,QAClD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAIO,MAAM,8BAAN,cAA0C,cAAc;AAAA;AAAA,IAE9D,kBAA0B;AAAA,IAE1B,YAAa,YAAoB,aAAqB,0BAAkC;AACvF,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,sBAAsB,MAAM;AAAA,MACtC,CAAC;AACD,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,SAAU,OAAe,MAAc,WAAmB,MAAc,MAAc,WAAmB,WACxG,WAAmB;AACnB,UAAI,SAAS,KAAK;AAClB,eAAS;AACT,aAAO,KAAK,IAAI;AAChB;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AAC9B;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AACzB;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AACzB;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AAC9B;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AAC9B;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AAAA,IAC/B;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,aAAkC,SAAS,qBAAqB,KAAK,eAAe;AACxF,UAAI,CAAC,WAAW;AAAQ;AAExB,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,OAAO,WAAW;AACtB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,uBAAW,YAAY,KAAK;AAC5B,uBAAW,OAAO,KAAK;AACvB,uBAAW,OAAO,KAAK;AACvB,uBAAW,YAAY,KAAK;AAC5B,uBAAW,YAAY,KAAK;AAC5B,uBAAW,YAAY,KAAK;AAC5B;AAAA,UACD,KAAK;AACJ,uBAAW,cAAc,KAAK,YAAY,WAAW,aAAa;AAClE,uBAAW,SAAS,KAAK,OAAO,WAAW,QAAQ;AACnD,uBAAW,SAAS,KAAK,OAAO,WAAW,QAAQ;AACnD,uBAAW,cAAc,KAAK,YAAY,WAAW,aAAa;AAClE,uBAAW,cAAc,KAAK,YAAY,WAAW,aAAa;AAClE,uBAAW,cAAc,KAAK,YAAY,WAAW,aAAa;AAAA,QACpE;AACA;AAAA,MACD;AAEA,UAAI,QAAQ,GAAG,GAAG,QAAQ,QAAQ;AAClC,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK;AAAA,QAAO,IAAI;AAAA;AAAA,MAAY;AAC5C,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,qBAAW;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,UAAU;AAC9D,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,qBAAW;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,UAAU;AAC9D,qBAAW;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,UAAU;AAC9D,qBAAW;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,UAAU;AAC9D;AAAA,QACD,KAAK;AACJ,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B;AAAA,QACD;AACC,mBAAS,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY;AAAA;AAAA,UAAW;AAC1E,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB;AAAA;AAAA,UAAW;AACpF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AACxF,mBAAS,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAClG,mBAAS,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAClG,mBAAS,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAAA,MACpG;AAEA,UAAI,SAAS,eAAgB;AAC5B,YAAI,OAAO,WAAW;AACtB,mBAAW,YAAY,KAAK,aAAa,SAAS,KAAK,aAAa;AACpE,mBAAW,OAAO,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAChD,mBAAW,OAAO,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAChD,mBAAW,YAAY,KAAK,aAAa,SAAS,KAAK,aAAa;AACpE,mBAAW,YAAY,KAAK,aAAa,SAAS,KAAK,aAAa;AACpE,mBAAW,YAAY,KAAK,aAAa,SAAS,KAAK,aAAa;AAAA,MACrE,OAAO;AACN,mBAAW,cAAc,SAAS,WAAW,aAAa;AAC1D,mBAAW,SAAS,IAAI,WAAW,QAAQ;AAC3C,mBAAW,SAAS,IAAI,WAAW,QAAQ;AAC3C,mBAAW,cAAc,SAAS,WAAW,aAAa;AAC1D,mBAAW,cAAc,SAAS,WAAW,aAAa;AAC1D,mBAAW,cAAc,SAAS,WAAW,aAAa;AAAA,MAC3D;AAAA,IACD;AAAA,EACD;AAGO,MAAM,iCAAN,cAA6C,eAAe;AAAA;AAAA;AAAA,IAGlE,kBAA0B;AAAA,IAE1B,YAAa,YAAoB,aAAqB,qBAA6B;AAClF,YAAM,YAAY,aAAa,SAAS,yBAAyB,MAAM,mBAAmB;AAC1F,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,aAA6B,SAAS,gBAAgB,KAAK,eAAe;AAC9E,UAAI,WAAW;AACd,mBAAW,WAAW,KAAK,iBAAiB,MAAM,OAAO,OAAO,WAAW,UAAU,WAAW,KAAK,QAAQ;AAAA,IAC/G;AAAA,EACD;AAGO,MAAM,gCAAN,cAA4C,eAAe;AAAA;AAAA;AAAA,IAGjE,kBAAkB;AAAA,IAElB,YAAa,YAAoB,aAAqB,qBAA6B;AAClF,YAAM,YAAY,aAAa,SAAS,wBAAwB,MAAM,mBAAmB;AACzF,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,aAA6B,SAAS,gBAAgB,KAAK,eAAe;AAC9E,UAAI,WAAW;AACd,mBAAW,UAAU,KAAK,iBAAiB,MAAM,OAAO,OAAO,WAAW,SAAS,WAAW,KAAK,OAAO;AAAA,IAC5G;AAAA,EACD;AAIO,MAAM,4BAAN,cAAwC,cAAc;AAAA;AAAA;AAAA,IAG5D,kBAAkB;AAAA,IAElB,YAAa,YAAoB,aAAqB,qBAA6B;AAClF,YAAM,YAAY,aAAa;AAAA,QAC9B,SAAS,oBAAoB,MAAM;AAAA,MACpC,CAAC;AACD,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,kBAAmB;AAClB,aAAO;AAAA,IACR;AAAA,IAEA,SAAU,OAAe,MAAc,WAAmB,MAAc,MAAc;AACrF,UAAI,SAAS,KAAK;AAClB,gBAAU;AACV,aAAO,KAAK,IAAI;AAChB;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAW,IAAI;AAC9B;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AACzB;AAAA,QAAO,QAAQ;AAAA;AAAA,MAAM,IAAI;AAAA,IAC1B;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI,aAA6B,SAAS,gBAAgB,KAAK,eAAe;AAC9E,UAAI,CAAC,WAAW;AAAQ;AAExB,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd,KAAK;AACJ,uBAAW,YAAY,WAAW,KAAK;AACvC,uBAAW,OAAO,WAAW,KAAK;AAClC,uBAAW,OAAO,WAAW,KAAK;AAClC;AAAA,UACD,KAAK;AACJ,uBAAW,cAAc,WAAW,KAAK,YAAY,WAAW,aAAa;AAC7E,uBAAW,SAAS,WAAW,KAAK,OAAO,WAAW,QAAQ;AAC9D,uBAAW,SAAS,WAAW,KAAK,OAAO,WAAW,QAAQ;AAAA,QAChE;AACA;AAAA,MACD;AAEA,UAAI,QAAQ,GAAG;AACf,UAAI,IAAI,SAAS;AAAA,QAAO;AAAA,QAAQ;AAAA,QAAM;AAAA;AAAA,MAAY;AAClD,UAAI,YAAY,KAAK,OAAO,KAAK,CAAC;AAClC,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,cAAI,SAAS,OAAO,CAAC;AACrB,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI,KAAK,OAAO,WAAW;AAAA,YAAO,IAAI;AAAA;AAAA,UAAY,IAAI;AACtD,qBAAW;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAW,IAAI,UAAU;AAC9D,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C,gBAAM;AAAA,YAAO,IAAI,IAAe;AAAA;AAAA,UAAM,IAAI,KAAK;AAC/C;AAAA,QACD,KAAK;AACJ,mBAAS;AAAA,YAAO,IAAI;AAAA;AAAA,UAAW;AAC/B,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB,cAAI;AAAA,YAAO,IAAI;AAAA;AAAA,UAAM;AACrB;AAAA,QACD;AACC,mBAAS,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAa,YAAY;AAAA;AAAA,UAAW;AAC1E,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB;AAAA;AAAA,UAAW;AACpF,cAAI,KAAK;AAAA,YAAe;AAAA,YAAM;AAAA,YAAG;AAAA,YAAQ,YAAY,KAAoB,IAAI;AAAA;AAAA,UAAW;AAAA,MAC1F;AAEA,UAAI,SAAS,eAAgB;AAC5B,YAAI,OAAO,WAAW;AACtB,mBAAW,YAAY,KAAK,aAAa,SAAS,KAAK,aAAa;AACpE,mBAAW,OAAO,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAChD,mBAAW,OAAO,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAAA,MACjD,OAAO;AACN,mBAAW,cAAc,SAAS,WAAW,aAAa;AAC1D,mBAAW,SAAS,IAAI,WAAW,QAAQ;AAC3C,mBAAW,SAAS,IAAI,WAAW,QAAQ;AAAA,MAC5C;AAAA,IACD;AAAA,EACD;AAGO,MAAe,4BAAf,cAAiD,eAAe;AAAA;AAAA;AAAA,IAGtE,kBAAkB;AAAA;AAAA,IAGlB,YAAa,YAAoB,aAAqB,wBAAgC,UAAkB;AACvG,YAAM,YAAY,aAAa,WAAW,MAAM,sBAAsB;AACtE,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAC9I,UAAI;AACJ,UAAI,KAAK,mBAAmB,IAAI;AAC/B,cAAM,QAAQ,QAAQ,KAAK,OAAO,CAAC,IAAI,KAAK,cAAc,IAAI,IAAI;AAElE,mBAAWE,eAAc,SAAS,oBAAoB;AACrD,cAAIA,YAAW,UAAU,KAAK,OAAOA,YAAW,IAAI;AACnD,iBAAK,IAAIA,aAAY,KAAK,kBAAkB,MAAM,OAAO,OAAO,KAAK,IAAIA,WAAU,GAAG,KAAK,MAAMA,WAAU,GAAG,KAAK,CAAC;AAAA,QACtH;AAAA,MACD,OAAO;AACN,qBAAa,SAAS,mBAAmB,KAAK,eAAe;AAC7D,YAAI,WAAW;AAAQ,eAAK,IAAI,YAAY,KAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK,IAAI,UAAU,GAAG,KAAK,MAAM,UAAU,CAAC,CAAC;AAAA,MACpI;AAAA,IACD;AAAA,EASD;AAGO,MAAM,mCAAN,cAA+C,0BAA0B;AAAA,IAC/E,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,wBAAwB;AAAA,IACzF;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,UAAU;AAAA,IACtB;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,oCAAN,cAAgD,0BAA0B;AAAA,IAChF,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,yBAAyB;AAAA,IAC1F;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,WAAW;AAAA,IACvB;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,mCAAN,cAA+C,0BAA0B;AAAA,IAC/E,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,wBAAwB;AAAA,IACzF;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,UAAU;AAAA,IACtB;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,gCAAN,cAA4C,0BAA0B;AAAA,IAC5E,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,qBAAqB;AAAA,IACtF;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,IAAI,WAAW,KAAK;AAAA,IAC5B;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,IAAI,WAAW;AAAA,IACvB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,cAAc,IAAI;AAAA,IAC9B;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,gCAAN,cAA4C,0BAA0B;AAAA,IAC5E,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,qBAAqB;AAAA,IACtF;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,OAAO;AAAA,IACnB;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,mCAAN,cAA+C,0BAA0B;AAAA,IAC/E,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,wBAAwB;AAAA,IACzF;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,UAAU;AAAA,IACtB;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,+BAAN,cAA2C,0BAA0B;AAAA,IAC3E,YAAa,YAAoB,aAAqB,wBAAgC;AACrF,YAAM,YAAY,aAAa,wBAAwB,SAAS,oBAAoB;AAAA,IACrF;AAAA,IAEA,MAAO,YAAuC;AAC7C,aAAO,WAAW,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,YAAuC;AAC3C,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,IAAK,YAA+B,OAAqB;AACxD,iBAAW,MAAM;AAAA,IAClB;AAAA,IAEA,OAAQ,YAA4C;AACnD,aAAO,WAAW;AAAA,IACnB;AAAA,EACD;AAGO,MAAM,kCAAN,cAA6C,SAAS;AAAA;AAAA;AAAA,IAK5D;AAAA;AAAA,IAGA,YAAa,YAAoB,wBAAgC;AAChE,YAAM,YAAY,gCAA+B,WAAW;AAC5D,WAAK,kBAAkB;AAAA,IACxB;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK,OAAO;AAAA,IACpB;AAAA;AAAA;AAAA,IAIA,SAAU,OAAe,MAAc;AACtC,WAAK,OAAO,KAAK,IAAI;AAAA,IACtB;AAAA;AAAA,IAGA,MAAO,UAAoB,UAAkB,MAAc,aAA2B,OAAe,OAAiB,WAAyB;AAE9I,UAAI;AACJ,UAAI,KAAK,mBAAmB,IAAI;AAC/B,qBAAa,SAAS,mBAAmB,KAAK,eAAe;AAC7D,YAAI,CAAC,WAAW;AAAQ;AAAA,MACzB;AAEA,YAAM,SAAS,KAAK;AAEpB,UAAI,WAAW,MAAM;AACpB,aAAK,MAAM,UAAU,UAAU,OAAO,WAAW,CAAC,GAAG,OAAO,OAAO,SAAS;AAC5E,mBAAW;AAAA,MACZ,WAAW,YAAY,OAAO,OAAO,SAAS,CAAC;AAC9C;AACD,UAAI,OAAO,OAAO,CAAC;AAAG;AAEtB,UAAI,WAAW,OAAO,CAAC,KAAK,QAAQ,OAAO,SAAS,QAAQ,QAAQ,QAAQ,IAAI,CAAC,GAAG;AACnF,YAAI,cAAc;AACjB,qBAAW,MAAM;AAAA,aACb;AACJ,qBAAWA,eAAc,SAAS,oBAAoB;AACrD,gBAAIA,YAAW;AAAQ,cAAAA,YAAW,MAAM;AAAA,UACzC;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAnDO,MAAM,iCAAN;AACN,gBADY,gCACG,eAAwB,CAAC,SAAS,uBAAuB,SAAS,CAAC;AAqD5E,MAAM,oBAAN,cAA+B,SAAiC;AAAA,IAKtE;AAAA,IACA;AAAA,IAEA,YAAa,YAAoB,WAAmB,YAA8B;AACjF,YAAM,YAAY;AAAA,QACjB,SAAS,WAAW,MAAM,YAAY,MAAM,WAAW,SAAU;AAAA,MAClE,CAAC;AACD,WAAK,YAAY;AACjB,WAAK,aAAa;AAAA,IACnB;AAAA,IAEA,kBAAmB;AAClB,aAAO,kBAAiB;AAAA,IACzB;AAAA,IAEA,eAAgB;AACf,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,gBAAiB;AAChB,aAAO,KAAK;AAAA,IACb;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,OAAe,MAAc,MAAoB,OAAe,OAAe;AACxF,UAAI,SAAS,KAAK;AAClB,eAAS,kBAAiB;AAC1B,aAAO,KAAK,IAAI;AAChB,aAAO,QAAQ,kBAAiB,IAAI,IAAI,OAAQ,SAAS;AACzD,aAAO,QAAQ,kBAAiB,KAAK,IAAI;AAAA,IAC1C;AAAA,IAEA,MAAO,UAAoB,UAAkB,MAAc,QAAsB,OAAe,OAAiB,WAAyB;AACzI,UAAI,OAAO,SAAS,MAAM,KAAK,SAAS;AACxC,UAAI,CAAC,KAAK,KAAK;AAAQ;AACvB,UAAI,iBAAiB,KAAK;AAC1B,UAAI,aAAa,KAAK;AACtB,UAAI,kBAAkB,YAAY;AACjC,YAAI,EAAE,0BAA0B,qBAC3B,eAAoC,sBAAsB;AAAY;AAAA,MAC5E;AAEA,UAAI,aAAa,gBAAqB;AACrC,YAAI,SAAS;AAAgB,eAAK,gBAAgB;AAClD;AAAA,MACD;AAEA,UAAI,SAAS,KAAK;AAClB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,YAAI,SAAS,iBAAkB,SAAS;AAAgB,eAAK,gBAAgB;AAC7E;AAAA,MACD;AAEA,UAAI,IAAI,SAAS,OAAO,QAAQ,MAAM,kBAAiB,OAAO;AAC9D,UAAI,SAAS,OAAO,CAAC;AACrB,UAAI,eAAe,OAAO,IAAI,kBAAiB,IAAI;AACnD,UAAI,QAAQ,OAAO,IAAI,kBAAiB,KAAK;AAE7C,UAAI,CAAC,KAAK,WAAW;AAAU;AAC/B,UAAI,QAAQ,gBAAgB,GAAG,QAAQ,KAAK,WAAW,SAAU,QAAQ;AACzE,UAAI,OAAO,mBAAmB,eAAe,EAAG;AAChD,UAAI,sBAA2B;AAC9B,kBAAY,OAAO,UAAU,QAAQ,OAAW;AAChD,gBAAQ,MAAM;AAAA,UACb;AACC,oBAAQ,KAAK,IAAI,QAAQ,GAAG,KAAK;AACjC;AAAA,UACD;AACC,qBAAS;AACT;AAAA,UACD,uBAA4B;AAC3B,gBAAI,KAAK,SAAS,KAAK;AACvB,oBAAQ,KAAK,IAAI,IAAI,QAAQ;AAC7B,gBAAI,SAAS;AAAO,sBAAQ,IAAI;AAChC;AAAA,UACD;AAAA,UACA;AACC,oBAAQ,KAAK,IAAI,QAAQ,IAAI,OAAO,CAAC;AACrC;AAAA,UACD;AACC,oBAAQ,QAAQ,IAAK,QAAQ;AAC7B;AAAA,UACD,8BAAmC;AAClC,gBAAI,KAAK,SAAS,KAAK;AACvB,oBAAQ,KAAK,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC3C,gBAAI,SAAS;AAAO,sBAAQ,IAAI;AAAA,UACjC;AAAA,QACD;AAAA,MACD;AACA,WAAK,gBAAgB;AAAA,IACtB;AAAA,EACD;AAlGO,MAAM,mBAAN;AACN,gBADY,kBACL,WAAU;AACjB,gBAFY,kBAEL,QAAO;AACd,gBAHY,kBAGL,SAAQ;;;ACrsET,MAAM,kBAAN,MAAqB;AAAA,IAE3B,OAAe,iBAA6B;AAC3C,aAAO,gBAAe;AAAA,IACvB;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA,SAAS,IAAI,MAAyB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMtC,YAAY;AAAA,IACZ,eAAe;AAAA,IAEf,SAAS,IAAI,MAAa;AAAA,IAC1B,YAAY,IAAI,MAA8B;AAAA,IAC9C,QAAQ,IAAI,WAAW,IAAI;AAAA,IAC3B,cAAc,IAAI,UAAU;AAAA,IAC5B,oBAAoB;AAAA,IAEpB,iBAAiB,IAAI,KAAiB,MAAM,IAAI,WAAW,CAAC;AAAA,IAE5D,YAAa,MAA0B;AACtC,WAAK,OAAO;AAAA,IACb;AAAA;AAAA,IAGA,OAAQ,OAAe;AACtB,eAAS,KAAK;AACd,UAAI,SAAS,KAAK;AAClB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,GAAG,KAAK;AAC9C,YAAI,UAAU,OAAO,CAAC;AACtB,YAAI,CAAC;AAAS;AAEd,gBAAQ,gBAAgB,QAAQ;AAChC,gBAAQ,YAAY,QAAQ;AAE5B,YAAI,eAAe,QAAQ,QAAQ;AAEnC,YAAI,QAAQ,QAAQ,GAAG;AACtB,kBAAQ,SAAS;AACjB,cAAI,QAAQ,QAAQ;AAAG;AACvB,yBAAe,CAAC,QAAQ;AACxB,kBAAQ,QAAQ;AAAA,QACjB;AAEA,YAAI,OAAO,QAAQ;AACnB,YAAI,MAAM;AAET,cAAI,WAAW,QAAQ,YAAY,KAAK;AACxC,cAAI,YAAY,GAAG;AAClB,iBAAK,QAAQ;AACb,iBAAK,aAAa,QAAQ,aAAa,IAAI,KAAK,WAAW,QAAQ,YAAY,SAAS,KAAK;AAC7F,oBAAQ,aAAa;AACrB,iBAAK,WAAW,GAAG,MAAM,IAAI;AAC7B,mBAAO,KAAK,YAAY;AACvB,mBAAK,WAAW;AAChB,qBAAO,KAAK;AAAA,YACb;AACA;AAAA,UACD;AAAA,QACD,WAAW,QAAQ,aAAa,QAAQ,YAAY,CAAC,QAAQ,YAAY;AACxE,iBAAO,CAAC,IAAI;AACZ,eAAK,MAAM,IAAI,OAAO;AACtB,eAAK,UAAU,OAAO;AACtB;AAAA,QACD;AACA,YAAI,QAAQ,cAAc,KAAK,iBAAiB,SAAS,KAAK,GAAG;AAEhE,cAAI,OAA0B,QAAQ;AACtC,kBAAQ,aAAa;AACrB,cAAI;AAAM,iBAAK,WAAW;AAC1B,iBAAO,MAAM;AACZ,iBAAK,MAAM,IAAI,IAAI;AACnB,mBAAO,KAAK;AAAA,UACb;AAAA,QACD;AAEA,gBAAQ,aAAa;AAAA,MACtB;AAEA,WAAK,MAAM,MAAM;AAAA,IAClB;AAAA;AAAA,IAGA,iBAAkB,IAAgB,OAAwB;AACzD,UAAI,OAAO,GAAG;AACd,UAAI,CAAC;AAAM,eAAO;AAElB,UAAI,WAAW,KAAK,iBAAiB,MAAM,KAAK;AAEhD,WAAK,gBAAgB,KAAK;AAC1B,WAAK,YAAY,KAAK;AAGtB,UAAI,GAAG,iBAAiB,MAAM,GAAG,WAAW,GAAG,aAAa;AAE3D,YAAI,KAAK,cAAc,KAAK,GAAG,eAAe,GAAG;AAChD,aAAG,aAAa,KAAK;AACrB,cAAI,KAAK,cAAc;AAAM,iBAAK,WAAW,WAAW;AACxD,aAAG,iBAAiB,KAAK;AACzB,eAAK,MAAM,IAAI,IAAI;AAAA,QACpB;AACA,eAAO;AAAA,MACR;AAEA,WAAK,aAAa,QAAQ,KAAK;AAC/B,SAAG,WAAW;AACd,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,MAAO,UAA6B;AACnC,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,KAAK;AAAmB,aAAK,mBAAmB;AAEpD,UAAI,SAAS,KAAK;AAClB,UAAI,SAAS,KAAK;AAClB,UAAI,UAAU;AAEd,eAASC,KAAI,GAAGC,KAAI,OAAO,QAAQD,KAAIC,IAAGD,MAAK;AAC9C,YAAI,UAAU,OAAOA,EAAC;AACtB,YAAI,CAAC,WAAW,QAAQ,QAAQ;AAAG;AACnC,kBAAU;AACV,YAAI,QAAkBA,MAAK,oBAAqB,QAAQ;AAGxD,YAAI,QAAQ,QAAQ;AACpB,YAAI,QAAQ;AACX,mBAAS,KAAK,gBAAgB,SAAS,UAAU,KAAK;AAAA,iBAC9C,QAAQ,aAAa,QAAQ,YAAY,CAAC,QAAQ;AAC1D,kBAAQ;AACT,YAAI,cAAc,SAAS,QAAQ;AAInC,YAAI,gBAAgB,QAAQ,eAAe,gBAAgB,QAAQ,iBAAiB,GAAG,YAAY;AACnG,YAAI,cAA8B;AAClC,YAAI,QAAQ,SAAS;AACpB,sBAAY,QAAQ,UAAW,WAAW;AAC1C,wBAAc;AAAA,QACf;AACA,YAAI,YAAY,QAAQ,UAAW;AACnC,YAAI,gBAAgB,UAAU;AAC9B,YAAKA,MAAK,KAAK,SAAS,KAAM,sBAAuB;AACpD,cAAIA,MAAK;AAAG,0BAAc;AAC1B,mBAAS,KAAK,GAAG,KAAK,eAAe,MAAM;AAI1C,kBAAM,sBAAsB,OAAO,KAAK;AACxC,gBAAI,WAAW,UAAU,EAAE;AAC3B,gBAAI,oBAAoB;AACvB,mBAAK,wBAAwB,UAAU,UAAU,WAAW,OAAO,WAAW;AAAA;AAE9E,uBAAS,MAAM,UAAU,eAAe,WAAW,aAAa,OAAO,oBAAyB;AAAA,UAClG;AAAA,QACD,OAAO;AACN,cAAI,eAAe,QAAQ;AAE3B,cAAI,mBAAmB,QAAQ;AAC/B,cAAI,aAAa,CAAC,oBAAoB,QAAQ,kBAAkB,UAAU,iBAAiB;AAC3F,cAAI;AAAY,oBAAQ,kBAAkB,SAAS,iBAAiB;AAEpE,mBAAS,KAAK,GAAG,KAAK,eAAe,MAAM;AAC1C,gBAAIE,YAAW,UAAU,EAAE;AAC3B,gBAAI,gBAAgB,aAAa,EAAE,KAAK,aAAa;AACrD,gBAAI,CAAC,oBAAoBA,qBAAoB,gBAAgB;AAC5D,mBAAK,oBAAoBA,WAAU,UAAU,WAAW,OAAO,eAAe,QAAQ,mBAAmB,MAAM,GAAG,UAAU;AAAA,YAC7H,WAAWA,qBAAoB,oBAAoB;AAClD,mBAAK,wBAAwBA,WAAU,UAAU,WAAW,OAAO,WAAW;AAAA,YAC/E,OAAO;AAEN,oBAAM,sBAAsB,OAAO,KAAK;AACxC,cAAAA,UAAS,MAAM,UAAU,eAAe,WAAW,aAAa,OAAO,4BAAiC;AAAA,YACzG;AAAA,UACD;AAAA,QACD;AACA,aAAK,YAAY,SAAS,aAAa;AACvC,eAAO,SAAS;AAChB,gBAAQ,oBAAoB;AAC5B,gBAAQ,gBAAgB,QAAQ;AAAA,MACjC;AAKA,UAAI,aAAa,KAAK,eAAe;AACrC,UAAI,QAAQ,SAAS;AACrB,eAAS,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,IAAI,GAAG,KAAK;AACtD,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,mBAAmB,YAAY;AACvC,cAAI,iBAAiB,KAAK,KAAK;AAC/B,eAAK,cAAc,CAAC,iBAAiB,OAAO,SAAS,cAAc,KAAK,KAAK,OAAO,cAAc,CAAC;AAAA,QACpG;AAAA,MACD;AACA,WAAK,gBAAgB;AAErB,WAAK,MAAM,MAAM;AACjB,aAAO;AAAA,IACR;AAAA,IAEA,gBAAiB,IAAgB,UAAoB,OAAiB;AACrE,UAAI,OAAO,GAAG;AACd,UAAI,KAAK;AAAY,aAAK,gBAAgB,MAAM,UAAU,KAAK;AAE/D,UAAI,MAAM;AACV,UAAI,GAAG,eAAe,GAAG;AACxB,cAAM;AACN,YAAI;AAAyB;AAAA,MAC9B,OAAO;AACN,cAAM,GAAG,UAAU,GAAG;AACtB,YAAI,MAAM;AAAG,gBAAM;AACnB,YAAI;AAAyB,kBAAQ,KAAK;AAAA,MAC3C;AAEA,UAAI,cAAc,MAAM,KAAK,wBAAwB,YAAY,MAAM,KAAK;AAC5E,UAAI,YAAY,KAAK,UAAW;AAChC,UAAI,gBAAgB,UAAU;AAC9B,UAAI,YAAY,KAAK,QAAQ,GAAG,gBAAgB,WAAW,aAAa,IAAI;AAC5E,UAAI,gBAAgB,KAAK,eAAe,gBAAgB,KAAK,iBAAiB,GAAG,YAAY;AAC7F,UAAI,SAAS;AACb,UAAI,KAAK;AACR,oBAAY,KAAK,UAAW,WAAW;AAAA,eAC/B,MAAM,KAAK;AACnB,iBAAS,KAAK;AAEf,UAAI,sBAAuB;AAC1B,iBAAS,IAAI,GAAG,IAAI,eAAe;AAClC,oBAAU,CAAC,EAAE,MAAM,UAAU,eAAe,WAAW,QAAQ,UAAU,qBAA0B;AAAA,MACrG,OAAO;AACN,YAAI,eAAe,KAAK;AACxB,YAAI,kBAAkB,KAAK;AAE3B,YAAI,mBAAmB,KAAK;AAC5B,YAAI,aAAa,CAAC,oBAAoB,KAAK,kBAAkB,UAAU,iBAAiB;AACxF,YAAI;AAAY,eAAK,kBAAkB,SAAS,iBAAiB;AAEjE,aAAK,aAAa;AAClB,iBAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACvC,cAAI,WAAW,UAAU,CAAC;AAC1B,cAAI;AACJ,cAAI;AACJ,cAAI,QAAQ;AACZ,kBAAQ,aAAa,CAAC,GAAG;AAAA,YACxB,KAAK;AACJ,kBAAI,CAAC,aAAa,oBAAoB;AAAmB;AACzD,8BAAgB;AAChB,sBAAQ;AACR;AAAA,YACD,KAAK;AACJ;AACA,sBAAQ;AACR;AAAA,YACD,KAAK;AACJ,8BAAgB;AAChB,sBAAQ;AACR;AAAA,YACD,KAAK;AACJ;AACA,sBAAQ;AACR;AAAA,YACD;AACC;AACA,kBAAI,UAAU,gBAAgB,CAAC;AAC/B,sBAAQ,YAAY,KAAK,IAAI,GAAG,IAAI,QAAQ,UAAU,QAAQ,WAAW;AACzE;AAAA,UACF;AACA,eAAK,cAAc;AAEnB,cAAI,CAAC,oBAAoB,oBAAoB;AAC5C,iBAAK,oBAAoB,UAAU,UAAU,WAAW,OAAO,eAAe,KAAK,mBAAmB,KAAK,GAAG,UAAU;AAAA,mBAChH,oBAAoB;AAC5B,iBAAK,wBAAwB,UAAU,UAAU,WAAW,eAAe,eAAe,SAAS,KAAK,wBAAwB;AAAA,eAC5H;AAEJ,kBAAM,sBAAsB,OAAO,KAAK;AACxC,gBAAI,aAAa,oBAAoB,qBAAqB;AACzD;AACD,qBAAS,MAAM,UAAU,eAAe,WAAW,QAAQ,OAAO,eAAe,SAAS;AAAA,UAC3F;AAAA,QACD;AAAA,MACD;AAEA,UAAI,GAAG,cAAc;AAAG,aAAK,YAAY,MAAM,aAAa;AAC5D,WAAK,OAAO,SAAS;AACrB,WAAK,oBAAoB;AACzB,WAAK,gBAAgB,KAAK;AAE1B,aAAO;AAAA,IACR;AAAA,IAEA,wBAAyB,UAA8B,UAAoB,MAAc,OAAiB,aAAsB;AAC/H,UAAI,OAAO,SAAS,MAAM,SAAS,SAAS;AAC5C,UAAI,CAAC,KAAK,KAAK;AAAQ;AAEvB,UAAI,OAAO,SAAS,OAAO,CAAC,GAAG;AAC9B,YAAI,0BAA2B;AAC9B,eAAK,cAAc,UAAU,MAAM,KAAK,KAAK,gBAAgB,WAAW;AAAA,MAC1E;AACC,aAAK,cAAc,UAAU,MAAM,SAAS,gBAAgB,SAAS,QAAQ,SAAS,QAAQ,IAAI,CAAC,GAAG,WAAW;AAGlH,UAAI,KAAK,mBAAmB,KAAK;AAAc,aAAK,kBAAkB,KAAK,eAAe;AAAA,IAC3F;AAAA,IAEA,cAAe,UAAoB,MAAY,gBAA+B,aAAsB;AACnG,WAAK,cAAc,CAAC,iBAAiB,OAAO,SAAS,cAAc,KAAK,KAAK,OAAO,cAAc,CAAC;AACnG,UAAI;AAAa,aAAK,kBAAkB,KAAK,eAAe;AAAA,IAC7D;AAAA,IAEA,oBAAqB,UAA0B,UAAoB,MAAc,OAAe,OAC/F,mBAAkC,GAAW,YAAqB;AAElE,UAAI;AAAY,0BAAkB,CAAC,IAAI;AAEvC,UAAI,SAAS,GAAG;AACf,iBAAS,MAAM,UAAU,GAAG,MAAM,MAAM,GAAG,oBAAyB;AACpE;AAAA,MACD;AAEA,UAAI,OAAO,SAAS,MAAM,SAAS,SAAS;AAC5C,UAAI,CAAC,KAAK;AAAQ;AAClB,UAAI,SAAS,SAAS;AACtB,UAAI,KAAK,GAAG,KAAK;AACjB,UAAI,OAAO,OAAO,CAAC,GAAG;AACrB,gBAAQ,OAAO;AAAA,UACd;AACC,iBAAK,WAAW,KAAK,KAAK;AAAA,UAC3B;AACC;AAAA,UACD;AACC,iBAAK,KAAK;AACV,iBAAK,KAAK,KAAK;AAAA,QACjB;AAAA,MACD,OAAO;AACN,aAAK,yBAA0B,KAAK,KAAK,WAAW,KAAK;AACzD,aAAK,KAAK,KAAK,WAAW,SAAS,cAAc,IAAI;AAAA,MACtD;AAGA,UAAI,QAAQ,GAAG,OAAO,KAAK;AAC3B,cAAQ,KAAK,KAAK,OAAO,MAAM,GAAG,IAAI;AACtC,UAAI,QAAQ,GAAG;AACd,gBAAQ,kBAAkB,CAAC;AAAA,MAC5B,OAAO;AACN,YAAI,YAAY,GAAG,WAAW;AAC9B,YAAI,YAAY;AACf,sBAAY;AACZ,qBAAW;AAAA,QACZ,OAAO;AACN,sBAAY,kBAAkB,CAAC;AAC/B,qBAAW,kBAAkB,IAAI,CAAC;AAAA,QACnC;AACA,YAAI,QAAQ,YAAY,YAAY;AACpC,gBAAQ,OAAO;AACf,YAAI,UAAU,QAAQ,GAAG,MAAM,aAAa;AAC5C,YAAI,KAAK,IAAI,QAAQ,KAAK,MAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,OAAO,IAAI,GAAG;AACrF,cAAI,KAAK,IAAI,YAAY,KAAK,IAAI,KAAK;AACtC,qBAAS,MAAM,UAAU,OAAO,SAAS;AACzC,kBAAM;AAAA,UACP,WAAW,SAAS;AACnB,qBAAS,MAAM,UAAU,OAAO,SAAS;AAAA;AAEzC,kBAAM;AAAA,QACR;AACA,YAAI,OAAO;AAAS,mBAAS,MAAM,UAAU,OAAO,SAAS;AAC7D,0BAAkB,CAAC,IAAI;AAAA,MACxB;AACA,wBAAkB,IAAI,CAAC,IAAI;AAC3B,WAAK,WAAW,KAAK,QAAQ;AAAA,IAC9B;AAAA,IAEA,YAAa,OAAmB,eAAuB;AACtD,UAAI,iBAAiB,MAAM,gBAAgB,eAAe,MAAM;AAChE,UAAI,WAAW,eAAe;AAC9B,UAAI,mBAAmB,MAAM,YAAY;AAGzC,UAAI,SAAS,KAAK;AAClB,UAAI,IAAI,GAAG,IAAI,OAAO;AACtB,aAAO,IAAI,GAAG,KAAK;AAClB,YAAI,QAAQ,OAAO,CAAC;AACpB,YAAI,MAAM,OAAO;AAAkB;AACnC,YAAI,MAAM,OAAO;AAAc;AAC/B,aAAK,MAAM,MAAM,OAAO,KAAK;AAAA,MAC9B;AAGA,UAAI,WAAW;AACf,UAAI,MAAM,MAAM;AACf,YAAI,YAAY;AACf,qBAAW;AAAA,aACP;AACJ,gBAAM,SAAS,KAAK,MAAM,MAAM,YAAY,QAAQ;AACpD,qBAAW,SAAS,KAAK,SAAS,KAAK,MAAM,MAAM,YAAY,QAAQ;AAAA,QACxE;AAAA,MACD;AACC,mBAAW,iBAAiB,gBAAgB,MAAM,gBAAgB;AACnE,UAAI;AAAU,aAAK,MAAM,SAAS,KAAK;AAGvC,aAAO,IAAI,GAAG,KAAK;AAClB,YAAI,QAAQ,OAAO,CAAC;AACpB,YAAI,MAAM,OAAO;AAAgB;AACjC,aAAK,MAAM,MAAM,OAAO,KAAK;AAAA,MAC9B;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,cAAe;AACd,UAAI,mBAAmB,KAAK,MAAM;AAClC,WAAK,MAAM,gBAAgB;AAC3B,eAAS,IAAI,GAAG,IAAI,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC9C,aAAK,WAAW,CAAC;AAClB,WAAK,OAAO,SAAS;AACrB,WAAK,MAAM,gBAAgB;AAC3B,WAAK,MAAM,MAAM;AAAA,IAClB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,WAAY,YAAoB;AAC/B,UAAI,cAAc,KAAK,OAAO;AAAQ;AACtC,UAAI,UAAU,KAAK,OAAO,UAAU;AACpC,UAAI,CAAC;AAAS;AAEd,WAAK,MAAM,IAAI,OAAO;AAEtB,WAAK,UAAU,OAAO;AAEtB,UAAI,QAAQ;AACZ,aAAO,MAAM;AACZ,YAAI,OAAO,MAAM;AACjB,YAAI,CAAC;AAAM;AACX,aAAK,MAAM,IAAI,IAAI;AACnB,cAAM,aAAa;AACnB,cAAM,WAAW;AACjB,gBAAQ;AAAA,MACT;AAEA,WAAK,OAAO,QAAQ,UAAU,IAAI;AAElC,WAAK,MAAM,MAAM;AAAA,IAClB;AAAA,IAEA,WAAY,OAAe,SAAqB,WAAoB;AACnE,UAAI,OAAO,KAAK,cAAc,KAAK;AACnC,WAAK,OAAO,KAAK,IAAI;AACrB,cAAQ,WAAW;AAEnB,UAAI,MAAM;AACT,YAAI;AAAW,eAAK,MAAM,UAAU,IAAI;AACxC,gBAAQ,aAAa;AACrB,aAAK,WAAW;AAChB,gBAAQ,UAAU;AAGlB,YAAI,KAAK,cAAc,KAAK,cAAc;AACzC,kBAAQ,kBAAkB,KAAK,IAAI,GAAG,KAAK,UAAU,KAAK,WAAW;AAEtE,aAAK,kBAAkB,SAAS;AAAA,MACjC;AAEA,WAAK,MAAM,MAAM,OAAO;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA,IAKA,aAAc,YAAoB,eAAuB,OAAgB,OAAO;AAC/E,UAAI,YAAY,KAAK,KAAK,aAAa,cAAc,aAAa;AAClE,UAAI,CAAC;AAAW,cAAM,IAAI,MAAM,0BAA0B,aAAa;AACvE,aAAO,KAAK,iBAAiB,YAAY,WAAW,IAAI;AAAA,IACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,iBAAkB,YAAoB,WAAsB,OAAgB,OAAO;AAClF,UAAI,CAAC;AAAW,cAAM,IAAI,MAAM,2BAA2B;AAC3D,UAAI,YAAY;AAChB,UAAI,UAAU,KAAK,cAAc,UAAU;AAC3C,UAAI,SAAS;AACZ,YAAI,QAAQ,iBAAiB,IAAI;AAEhC,eAAK,OAAO,UAAU,IAAI,QAAQ;AAClC,eAAK,MAAM,UAAU,OAAO;AAC5B,eAAK,MAAM,IAAI,OAAO;AACtB,eAAK,UAAU,OAAO;AACtB,oBAAU,QAAQ;AAClB,sBAAY;AAAA,QACb;AACC,eAAK,UAAU,OAAO;AAAA,MACxB;AACA,UAAI,QAAQ,KAAK,WAAW,YAAY,WAAW,MAAM,OAAO;AAChE,WAAK,WAAW,YAAY,OAAO,SAAS;AAC5C,WAAK,MAAM,MAAM;AACjB,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,aAAc,YAAoB,eAAuB,OAAgB,OAAO,QAAgB,GAAG;AAClG,UAAI,YAAY,KAAK,KAAK,aAAa,cAAc,aAAa;AAClE,UAAI,CAAC;AAAW,cAAM,IAAI,MAAM,0BAA0B,aAAa;AACvE,aAAO,KAAK,iBAAiB,YAAY,WAAW,MAAM,KAAK;AAAA,IAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,iBAAkB,YAAoB,WAAsB,OAAgB,OAAO,QAAgB,GAAG;AACrG,UAAI,CAAC;AAAW,cAAM,IAAI,MAAM,2BAA2B;AAE3D,UAAI,OAAO,KAAK,cAAc,UAAU;AACxC,UAAI,MAAM;AACT,eAAO,KAAK;AACX,iBAAO,KAAK;AAAA,MACd;AAEA,UAAI,QAAQ,KAAK,WAAW,YAAY,WAAW,MAAM,IAAI;AAE7D,UAAI,CAAC,MAAM;AACV,aAAK,WAAW,YAAY,OAAO,IAAI;AACvC,aAAK,MAAM,MAAM;AAAA,MAClB,OAAO;AACN,aAAK,OAAO;AACZ,cAAM,WAAW;AACjB,YAAI,SAAS;AAAG,mBAAS,KAAK,iBAAiB,IAAI,MAAM;AAAA,MAC1D;AAEA,YAAM,QAAQ;AACd,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBA,kBAAmB,YAAoB,cAAsB,GAAG;AAC/D,UAAI,QAAQ,KAAK,iBAAiB,YAAY,gBAAe,eAAe,GAAG,KAAK;AACpF,YAAM,cAAc;AACpB,YAAM,WAAW;AACjB,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAaA,kBAAmB,YAAoB,cAAsB,GAAG,QAAgB,GAAG;AAClF,UAAI,QAAQ,KAAK,iBAAiB,YAAY,gBAAe,eAAe,GAAG,OAAO,KAAK;AAC3F,UAAI,SAAS;AAAG,cAAM,SAAS,MAAM,cAAc;AACnD,YAAM,cAAc;AACpB,YAAM,WAAW;AACjB,aAAO;AAAA,IACR;AAAA;AAAA;AAAA,IAIA,mBAAoB,cAAsB,GAAG;AAC5C,UAAI,mBAAmB,KAAK,MAAM;AAClC,WAAK,MAAM,gBAAgB;AAC3B,eAAS,IAAI,GAAG,IAAI,KAAK,OAAO,QAAQ,IAAI,GAAG,KAAK;AACnD,YAAI,UAAU,KAAK,OAAO,CAAC;AAC3B,YAAI;AAAS,eAAK,kBAAkB,QAAQ,YAAY,WAAW;AAAA,MACpE;AACA,WAAK,MAAM,gBAAgB;AAC3B,WAAK,MAAM,MAAM;AAAA,IAClB;AAAA,IAEA,cAAe,OAAe;AAC7B,UAAI,QAAQ,KAAK,OAAO;AAAQ,eAAO,KAAK,OAAO,KAAK;AACxD,YAAM,oBAAoB,KAAK,QAAQ,QAAQ,GAAG,IAAI;AACtD,WAAK,OAAO,SAAS,QAAQ;AAC7B,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,WAAY,YAAoB,WAAsB,MAAe,MAAyB;AAC7F,UAAI,QAAQ,KAAK,eAAe,OAAO;AACvC,YAAM,MAAM;AACZ,YAAM,aAAa;AACnB,YAAM,YAAY;AAClB,YAAM,OAAO;AACb,YAAM,eAAe;AAErB,YAAM,UAAU;AAChB,YAAM,mBAAmB;AAEzB,YAAM,iBAAiB;AACvB,YAAM,2BAA2B;AACjC,YAAM,yBAAyB;AAC/B,YAAM,wBAAwB;AAE9B,YAAM,iBAAiB;AACvB,YAAM,eAAe,UAAU;AAC/B,YAAM,gBAAgB;AACtB,YAAM,oBAAoB;AAE1B,YAAM,QAAQ;AACd,YAAM,YAAY;AAClB,YAAM,YAAY;AAClB,YAAM,gBAAgB;AACtB,YAAM,WAAW,OAAO;AACxB,YAAM,YAAY;AAElB,YAAM,QAAQ;AACd,YAAM,UAAU;AAChB,YAAM,cAAc,CAAC,OAAO,IAAI,KAAK,KAAK,OAAO,KAAK,WAAY,SAAS;AAC3E,YAAM,iBAAiB;AACvB,YAAM,aAAa;AACnB,YAAM;AACN,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,UAAW,OAAmB;AAC7B,UAAI,OAAO,MAAM;AACjB,aAAO,MAAM;AACZ,aAAK,MAAM,QAAQ,IAAI;AACvB,eAAO,KAAK;AAAA,MACb;AACA,YAAM,OAAO;AAAA,IACd;AAAA,IAEA,qBAAsB;AACrB,WAAK,oBAAoB;AAEzB,WAAK,YAAY,MAAM;AACvB,UAAI,SAAS,KAAK;AAClB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,GAAG,KAAK;AAC9C,YAAI,QAAQ,OAAO,CAAC;AACpB,YAAI,CAAC;AAAO;AACZ,eAAO,MAAM;AACZ,kBAAQ,MAAM;AACf,WAAG;AACF,cAAI,CAAC,MAAM,YAAY,MAAM;AAA0B,iBAAK,YAAY,KAAK;AAC7E,kBAAQ,MAAM;AAAA,QACf,SAAS;AAAA,MACV;AAAA,IACD;AAAA,IAEA,YAAa,OAAmB;AAC/B,UAAI,KAAK,MAAM;AACf,UAAI,YAAY,MAAM,UAAW;AACjC,UAAI,iBAAiB,MAAM,UAAW,UAAU;AAChD,UAAI,eAAe,MAAM;AACzB,mBAAa,SAAS;AACtB,UAAI,kBAAkB,MAAM;AAC5B,sBAAgB,SAAS;AACzB,UAAI,cAAc,KAAK;AAEvB,UAAI,MAAM,GAAG,cAAc;AAC1B,iBAAS,IAAI,GAAG,IAAI,gBAAgB;AACnC,uBAAa,CAAC,IAAI,YAAY,OAAO,UAAU,CAAC,EAAE,eAAe,CAAC,IAAI,aAAa;AACpF;AAAA,MACD;AAEA;AACA,iBAAS,IAAI,GAAG,IAAI,gBAAgB,KAAK;AACxC,cAAI,WAAW,UAAU,CAAC;AAC1B,cAAI,MAAM,SAAS,eAAe;AAClC,cAAI,CAAC,YAAY,OAAO,GAAG;AAC1B,yBAAa,CAAC,IAAI;AAAA,mBACV,CAAC,MAAM,oBAAoB,sBAAsB,oBAAoB,qBAC1E,oBAAoB,iBAAiB,CAAC,GAAG,UAAW,YAAY,GAAG,GAAG;AACzE,yBAAa,CAAC,IAAI;AAAA,UACnB,OAAO;AACN,qBAAS,OAAO,GAAG,UAAU,MAAM,OAAO,KAAM,UAAU;AACzD,kBAAI,KAAK,UAAW,YAAY,GAAG;AAAG;AACtC,kBAAI,MAAM,cAAc,GAAG;AAC1B,6BAAa,CAAC,IAAI;AAClB,gCAAgB,CAAC,IAAI;AACrB,yBAAS;AAAA,cACV;AACA;AAAA,YACD;AACA,yBAAa,CAAC,IAAI;AAAA,UACnB;AAAA,QACD;AAAA,IACD;AAAA;AAAA,IAGA,WAAY,YAAoB;AAC/B,UAAI,cAAc,KAAK,OAAO;AAAQ,eAAO;AAC7C,aAAO,KAAK,OAAO,UAAU;AAAA,IAC9B;AAAA;AAAA,IAGA,YAAa,UAAkC;AAC9C,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,WAAK,UAAU,KAAK,QAAQ;AAAA,IAC7B;AAAA;AAAA,IAGA,eAAgB,UAAkC;AACjD,UAAI,QAAQ,KAAK,UAAU,QAAQ,QAAQ;AAC3C,UAAI,SAAS;AAAG,aAAK,UAAU,OAAO,OAAO,CAAC;AAAA,IAC/C;AAAA;AAAA,IAGA,iBAAkB;AACjB,WAAK,UAAU,SAAS;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA,IAKA,6BAA8B;AAC7B,WAAK,MAAM,MAAM;AAAA,IAClB;AAAA,EACD;AA/uBO,MAAM,iBAAN;AACN,gBADY,gBACL,mBAAkB,IAAI,UAAU,WAAW,CAAC,GAAG,CAAC;AAmvBjD,MAAM,aAAN,MAAiB;AAAA;AAAA,IAEvB,YAA8B;AAAA,IAE9B,WAA8B;AAAA;AAAA,IAG9B,OAA0B;AAAA;AAAA;AAAA,IAI1B,aAAgC;AAAA;AAAA;AAAA,IAIhC,WAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,IAM9B,WAA0C;AAAA;AAAA;AAAA;AAAA,IAK1C,aAAqB;AAAA;AAAA;AAAA,IAIrB,OAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAahB,eAAwB;AAAA,IAExB,UAAmB;AAAA,IAEnB,mBAA4B;AAAA;AAAA;AAAA;AAAA,IAK5B,iBAAyB;AAAA;AAAA;AAAA;AAAA,IAKzB,yBAAiC;AAAA;AAAA;AAAA,IAIjC,2BAAmC;AAAA;AAAA;AAAA;AAAA,IAKnC,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMhC,iBAAyB;AAAA;AAAA;AAAA,IAIzB,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,IAOvB,gBAAwB;AAAA,IAExB,oBAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ5B,QAAgB;AAAA;AAAA;AAAA;AAAA,IAKhB,YAAoB;AAAA,IAEpB,YAAoB;AAAA,IAAG,gBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAS/C,WAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAanB,YAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOpB,QAAgB;AAAA;AAAA;AAAA,IAIhB,UAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAelB,eAAuB;AAAA,IAAG,iBAAyB;AAAA,IAAG,aAAqB;AAAA,IAE3E,IAAI,cAAe;AAClB,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,IAAI,YAAa,aAAqB;AACrC,WAAK,eAAe;AAAA,IACrB;AAAA,IAEA,wBAAyB,aAAqB,OAAe;AAC5D,WAAK,eAAe;AACpB,UAAI,KAAK,YAAY,QAAQ,SAAS;AAAG,iBAAS,KAAK,SAAS,iBAAiB,IAAI;AACrF,WAAK,QAAQ;AAAA,IACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA;AAAA,IACA,eAAe,IAAI,MAAc;AAAA,IACjC,kBAAkB,IAAI,MAAkB;AAAA,IACxC,oBAAoB,IAAI,MAAc;AAAA,IAEtC,QAAS;AACR,WAAK,OAAO;AACZ,WAAK,WAAW;AAChB,WAAK,aAAa;AAClB,WAAK,WAAW;AAChB,WAAK,YAAY;AACjB,WAAK,WAAW;AAChB,WAAK,aAAa,SAAS;AAC3B,WAAK,gBAAgB,SAAS;AAC9B,WAAK,kBAAkB,SAAS;AAAA,IACjC;AAAA;AAAA;AAAA;AAAA,IAKA,mBAAoB;AACnB,UAAI,KAAK,MAAM;AACd,YAAI,WAAW,KAAK,eAAe,KAAK;AACxC,YAAI,YAAY;AAAG,iBAAO,KAAK;AAC/B,eAAQ,KAAK,YAAY,WAAY,KAAK;AAAA,MAC3C;AACA,aAAO,KAAK,IAAI,KAAK,YAAY,KAAK,gBAAgB,KAAK,YAAY;AAAA,IACxE;AAAA,IAEA,iBAAkB,eAAuB;AACxC,WAAK,gBAAgB;AACrB,WAAK,oBAAoB;AAAA,IAC1B;AAAA;AAAA;AAAA;AAAA,IAKA,aAAc;AACb,aAAO,KAAK,aAAa,KAAK,eAAe,KAAK;AAAA,IACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,0BAA2B;AAC1B,WAAK,kBAAkB,SAAS;AAAA,IACjC;AAAA,IAEA,mBAAoB;AACnB,UAAI,WAAW,KAAK,eAAe,KAAK;AACxC,UAAI,YAAY,GAAG;AAClB,YAAI,KAAK;AAAM,iBAAO,YAAY,KAAM,KAAK,YAAY,WAAY;AACrE,YAAI,KAAK,YAAY;AAAU,iBAAO;AAAA,MACvC;AACA,aAAO,KAAK;AAAA,IACb;AAAA;AAAA;AAAA;AAAA,IAKA,aAAc;AACb,aAAO,KAAK,iBAAiB;AAAA,IAC9B;AAAA;AAAA;AAAA,IAIA,cAAe;AACd,aAAO,KAAK,QAAQ,QAAQ,KAAK,gBAAgB,KAAK,KAAK,SAAS;AAAA,IACrE;AAAA,EACD;AAEO,MAAM,aAAN,MAAiB;AAAA,IACvB,UAAsB,CAAC;AAAA,IACvB,gBAAgB;AAAA,IAChB;AAAA,IAEA,YAAa,WAA2B;AACvC,WAAK,YAAY;AAAA,IAClB;AAAA,IAEA,MAAO,OAAmB;AACzB,WAAK,QAAQ,KAAK,UAAU,KAAK;AACjC,WAAK,QAAQ,KAAK,KAAK;AACvB,WAAK,UAAU,oBAAoB;AAAA,IACpC;AAAA,IAEA,UAAW,OAAmB;AAC7B,WAAK,QAAQ,KAAK,UAAU,SAAS;AACrC,WAAK,QAAQ,KAAK,KAAK;AAAA,IACxB;AAAA,IAEA,IAAK,OAAmB;AACvB,WAAK,QAAQ,KAAK,UAAU,GAAG;AAC/B,WAAK,QAAQ,KAAK,KAAK;AACvB,WAAK,UAAU,oBAAoB;AAAA,IACpC;AAAA,IAEA,QAAS,OAAmB;AAC3B,WAAK,QAAQ,KAAK,UAAU,OAAO;AACnC,WAAK,QAAQ,KAAK,KAAK;AAAA,IACxB;AAAA,IAEA,SAAU,OAAmB;AAC5B,WAAK,QAAQ,KAAK,UAAU,QAAQ;AACpC,WAAK,QAAQ,KAAK,KAAK;AAAA,IACxB;AAAA,IAEA,MAAO,OAAmB,OAAc;AACvC,WAAK,QAAQ,KAAK,UAAU,KAAK;AACjC,WAAK,QAAQ,KAAK,KAAK;AACvB,WAAK,QAAQ,KAAK,KAAK;AAAA,IACxB;AAAA,IAEA,QAAS;AACR,UAAI,KAAK;AAAe;AACxB,WAAK,gBAAgB;AAErB,UAAI,UAAU,KAAK;AACnB,UAAI,YAAY,KAAK,UAAU;AAE/B,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,GAAG;AAC3C,YAAI,OAAO,QAAQ,CAAC;AACpB,YAAI,QAAQ,QAAQ,IAAI,CAAC;AACzB,gBAAQ,MAAM;AAAA,UACb,KAAK,UAAU;AACd,gBAAI,MAAM,YAAY,MAAM,SAAS;AAAO,oBAAM,SAAS,MAAM,KAAK;AACtE,qBAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;AAC7C,kBAAI,WAAW,UAAU,EAAE;AAC3B,kBAAI,SAAS;AAAO,yBAAS,MAAM,KAAK;AAAA,YACzC;AACA;AAAA,UACD,KAAK,UAAU;AACd,gBAAI,MAAM,YAAY,MAAM,SAAS;AAAW,oBAAM,SAAS,UAAU,KAAK;AAC9E,qBAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;AAC7C,kBAAI,WAAW,UAAU,EAAE;AAC3B,kBAAI,SAAS;AAAW,yBAAS,UAAU,KAAK;AAAA,YACjD;AACA;AAAA,UACD,KAAK,UAAU;AACd,gBAAI,MAAM,YAAY,MAAM,SAAS;AAAK,oBAAM,SAAS,IAAI,KAAK;AAClE,qBAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;AAC7C,kBAAI,WAAW,UAAU,EAAE;AAC3B,kBAAI,SAAS;AAAK,yBAAS,IAAI,KAAK;AAAA,YACrC;AAAA,UAED,KAAK,UAAU;AACd,gBAAI,MAAM,YAAY,MAAM,SAAS;AAAS,oBAAM,SAAS,QAAQ,KAAK;AAC1E,qBAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;AAC7C,kBAAI,WAAW,UAAU,EAAE;AAC3B,kBAAI,SAAS;AAAS,yBAAS,QAAQ,KAAK;AAAA,YAC7C;AACA,iBAAK,UAAU,eAAe,KAAK,KAAK;AACxC;AAAA,UACD,KAAK,UAAU;AACd,gBAAI,MAAM,YAAY,MAAM,SAAS;AAAU,oBAAM,SAAS,SAAS,KAAK;AAC5E,qBAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;AAC7C,kBAAI,WAAW,UAAU,EAAE;AAC3B,kBAAI,SAAS;AAAU,yBAAS,SAAS,KAAK;AAAA,YAC/C;AACA;AAAA,UACD,KAAK,UAAU;AACd,gBAAI,QAAQ,QAAQ,MAAM,CAAC;AAC3B,gBAAI,MAAM,YAAY,MAAM,SAAS;AAAO,oBAAM,SAAS,MAAM,OAAO,KAAK;AAC7E,qBAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,MAAM;AAC7C,kBAAI,WAAW,UAAU,EAAE;AAC3B,kBAAI,SAAS;AAAO,yBAAS,MAAM,OAAO,KAAK;AAAA,YAChD;AACA;AAAA,QACF;AAAA,MACD;AACA,WAAK,MAAM;AAEX,WAAK,gBAAgB;AAAA,IACtB;AAAA,IAEA,QAAS;AACR,WAAK,QAAQ,SAAS;AAAA,IACvB;AAAA,EACD;AAEO,MAAK,YAAL,kBAAKC,eAAL;AACN,IAAAA,sBAAA;AAAO,IAAAA,sBAAA;AAAW,IAAAA,sBAAA;AAAK,IAAAA,sBAAA;AAAS,IAAAA,sBAAA;AAAU,IAAAA,sBAAA;AAD/B,WAAAA;AAAA,KAAA;AA+BL,MAAe,wBAAf,MAAuE;AAAA,IAC7E,MAAO,OAAmB;AAAA,IAC1B;AAAA,IAEA,UAAW,OAAmB;AAAA,IAC9B;AAAA,IAEA,IAAK,OAAmB;AAAA,IACxB;AAAA,IAEA,QAAS,OAAmB;AAAA,IAC5B;AAAA,IAEA,SAAU,OAAmB;AAAA,IAC7B;AAAA,IAEA,MAAO,OAAmB,OAAc;AAAA,IACxC;AAAA,EACD;AAKO,MAAM,aAAa;AAKnB,MAAM,QAAQ;AAMd,MAAM,kBAAkB;AAMxB,MAAM,aAAa;AAanB,MAAM,WAAW;AAEjB,MAAM,QAAQ;AACd,MAAM,UAAU;;;ACnrChB,MAAM,qBAAN,MAAyB;AAAA;AAAA,IAE/B;AAAA,IAEA,qBAAwC,CAAC;AAAA;AAAA,IAGzC,aAAa;AAAA,IAEb,YAAa,cAA4B;AACxC,UAAI,CAAC;AAAc,cAAM,IAAI,MAAM,8BAA8B;AACjE,WAAK,eAAe;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA,IAKA,OAAQ,UAAkB,QAAgB,UAAkB;AAC3D,UAAI,OAAO,KAAK,aAAa,cAAc,QAAQ;AACnD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,0BAA0B,QAAQ;AAC7D,UAAI,KAAK,KAAK,aAAa,cAAc,MAAM;AAC/C,UAAI,CAAC;AAAI,cAAM,IAAI,MAAM,0BAA0B,MAAM;AACzD,WAAK,WAAW,MAAM,IAAI,QAAQ;AAAA,IACnC;AAAA;AAAA;AAAA;AAAA,IAKA,WAAY,MAAiB,IAAe,UAAkB;AAC7D,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAI,cAAM,IAAI,MAAM,oBAAoB;AAC7C,UAAI,MAAM,KAAK,OAAO,MAAM,GAAG;AAC/B,WAAK,mBAAmB,GAAG,IAAI;AAAA,IAChC;AAAA;AAAA;AAAA,IAIA,OAAQ,MAAiB,IAAe;AACvC,UAAI,MAAM,KAAK,OAAO,MAAM,GAAG;AAC/B,UAAI,QAAQ,KAAK,mBAAmB,GAAG;AACvC,aAAO,UAAU,SAAY,KAAK,aAAa;AAAA,IAChD;AAAA,EACD;;;ACxCO,MAAM,wBAAN,cAAoC,iBAAiB;AAAA,IAC3D,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,IAE5B,YAAa,MAAc;AAC1B,YAAM,IAAI;AAAA,IACX;AAAA,IAEA,OAAoB;AACnB,UAAI,OAAO,IAAI,sBAAsB,KAAK,IAAI;AAC9C,WAAK,OAAO,IAAI;AAChB,WAAK,MAAM,aAAa,KAAK,KAAK;AAClC,aAAO;AAAA,IACR;AAAA,EACD;;;AChBO,MAAM,qBAAN,cAAiC,iBAAiB;AAAA;AAAA;AAAA,IAGxD,UAA2B;AAAA;AAAA;AAAA;AAAA,IAK3B,QAAQ,IAAI,MAAM,QAAQ,QAAQ,QAAQ,CAAC;AAAA;AAAA,IAE3C,YAAa,MAAc;AAC1B,YAAM,IAAI;AAAA,IACX;AAAA,IAEA,OAAoB;AACnB,UAAI,OAAO,IAAI,mBAAmB,KAAK,IAAI;AAC3C,WAAK,OAAO,IAAI;AAChB,WAAK,UAAU,KAAK;AACpB,WAAK,MAAM,aAAa,KAAK,KAAK;AAClC,aAAO;AAAA,IACR;AAAA,EACD;;;AC1BO,MAAe,UAAf,MAAuB;AAAA,IACnB;AAAA,IAEV,YAAa,OAA6C;AACzD,WAAK,SAAS;AAAA,IACf;AAAA,IAEA,WAAkD;AACjD,aAAO,KAAK;AAAA,IACb;AAAA,EAKD;AAEO,MAAK,gBAAL,kBAAKC,mBAAL;AACN,IAAAA,8BAAA,aAAU,QAAV;AACA,IAAAA,8BAAA,YAAS,QAAT;AACA,IAAAA,8BAAA,YAAS,QAAT;AACA,IAAAA,8BAAA,0BAAuB,QAAvB;AACA,IAAAA,8BAAA,yBAAsB,QAAtB;AACA,IAAAA,8BAAA,yBAAsB,QAAtB;AACA,IAAAA,8BAAA,wBAAqB,QAArB;AAPW,WAAAA;AAAA,KAAA;AAUL,MAAK,cAAL,kBAAKC,iBAAL;AACN,IAAAA,0BAAA,oBAAiB,SAAjB;AACA,IAAAA,0BAAA,iBAAc,SAAd;AACA,IAAAA,0BAAA,YAAS,SAAT;AAHW,WAAAA;AAAA,KAAA;AAML,MAAM,gBAAN,MAAoB;AAAA,IAC1B;AAAA,IACA,IAAI;AAAA,IAAG,IAAI;AAAA,IACX,KAAK;AAAA,IAAG,KAAK;AAAA,IACb,QAAQ;AAAA,IAAG,SAAS;AAAA,IACpB,UAAU;AAAA,IACV,UAAU;AAAA,IAAG,UAAU;AAAA,IACvB,gBAAgB;AAAA,IAAG,iBAAiB;AAAA,EACrC;AAEO,MAAM,cAAN,cAA0B,QAAQ;AAAA,IACxC,WAAY,WAA0B,WAA0B;AAAA,IAAE;AAAA,IAClE,SAAU,OAAoB,OAAoB;AAAA,IAAE;AAAA,IACpD,UAAW;AAAA,IAAE;AAAA,EACd;;;AC1CO,MAAM,eAAN,MAAyC;AAAA,IAC/C,QAAQ,IAAI,MAAwB;AAAA,IACpC,UAAU,IAAI,MAA0B;AAAA,IAExC,YAAa,WAAmB;AAC/B,UAAI,SAAS,IAAI,mBAAmB,SAAS;AAC7C,UAAI,QAAQ,IAAI,MAAc,CAAC;AAE/B,UAAI,aAA0D,CAAC;AAC/D,iBAAW,MAAM,IAAI,CAACC,UAA2B;AAChD,QAAAA,MAAM,QAAQ,SAAS,MAAM,CAAC,CAAC;AAC/B,QAAAA,MAAM,SAAS,SAAS,MAAM,CAAC,CAAC;AAAA,MACjC;AACA,iBAAW,QAAQ,IAAI,MAAM;AAAA,MAE7B;AACA,iBAAW,QAAQ,IAAI,CAACA,UAA2B;AAClD,QAAAA,MAAM,YAAY,MAAM,UAAU,eAAe,MAAM,CAAC,CAAC;AACzD,QAAAA,MAAM,YAAY,MAAM,UAAU,eAAe,MAAM,CAAC,CAAC;AAAA,MAC1D;AACA,iBAAW,QAAQ,IAAI,CAACA,UAA2B;AAClD,YAAI,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK;AAAI,UAAAA,MAAM;AACvC,YAAI,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK;AAAI,UAAAA,MAAM;AAAA,MACxC;AACA,iBAAW,KAAK,IAAI,CAACA,UAA2B;AAC/C,QAAAA,MAAM,MAAM,MAAM,CAAC,KAAK;AAAA,MACzB;AAEA,UAAI,eAAgE,CAAC;AACrE,mBAAa,IAAI,IAAI,CAAC,WAA+B;AACpD,eAAO,IAAI,SAAS,MAAM,CAAC,CAAC;AAC5B,eAAO,IAAI,SAAS,MAAM,CAAC,CAAC;AAAA,MAC7B;AACA,mBAAa,MAAM,IAAI,CAAC,WAA+B;AACtD,eAAO,QAAQ,SAAS,MAAM,CAAC,CAAC;AAChC,eAAO,SAAS,SAAS,MAAM,CAAC,CAAC;AAAA,MAClC;AACA,mBAAa,QAAQ,IAAI,CAAC,WAA+B;AACxD,eAAO,IAAI,SAAS,MAAM,CAAC,CAAC;AAC5B,eAAO,IAAI,SAAS,MAAM,CAAC,CAAC;AAC5B,eAAO,QAAQ,SAAS,MAAM,CAAC,CAAC;AAChC,eAAO,SAAS,SAAS,MAAM,CAAC,CAAC;AAAA,MAClC;AACA,mBAAa,QAAQ,IAAI,CAAC,WAA+B;AACxD,eAAO,UAAU,SAAS,MAAM,CAAC,CAAC;AAClC,eAAO,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,MACnC;AACA,mBAAa,MAAM,IAAI,CAAC,WAA+B;AACtD,eAAO,gBAAgB,SAAS,MAAM,CAAC,CAAC;AACxC,eAAO,iBAAiB,SAAS,MAAM,CAAC,CAAC;AAAA,MAC1C;AACA,mBAAa,SAAS,IAAI,CAAC,WAA+B;AACzD,eAAO,UAAU,SAAS,MAAM,CAAC,CAAC;AAClC,eAAO,UAAU,SAAS,MAAM,CAAC,CAAC;AAClC,eAAO,gBAAgB,SAAS,MAAM,CAAC,CAAC;AACxC,eAAO,iBAAiB,SAAS,MAAM,CAAC,CAAC;AAAA,MAC1C;AACA,mBAAa,QAAQ,IAAI,CAAC,WAA+B;AACxD,YAAI,QAAQ,MAAM,CAAC;AACnB,YAAI,SAAS;AACZ,iBAAO,UAAU;AAAA,iBACT,SAAS;AACjB,iBAAO,UAAU,SAAS,KAAK;AAAA,MACjC;AACA,mBAAa,OAAO,IAAI,CAAC,WAA+B;AACvD,eAAO,QAAQ,SAAS,MAAM,CAAC,CAAC;AAAA,MACjC;AAEA,UAAI,OAAO,OAAO,SAAS;AAE3B,aAAO,QAAQ,KAAK,KAAK,EAAE,UAAU;AACpC,eAAO,OAAO,SAAS;AAExB,aAAO,MAAM;AACZ,YAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,UAAU;AAAG;AACtC,YAAI,OAAO,UAAU,OAAO,IAAI,KAAK;AAAG;AACxC,eAAO,OAAO,SAAS;AAAA,MACxB;AAGA,UAAI,OAAgC;AACpC,UAAI,QAAyB;AAC7B,UAAI,SAA4B;AAChC,aAAO,MAAM;AACZ,YAAI,SAAS;AAAM;AACnB,YAAI,KAAK,KAAK,EAAE,UAAU,GAAG;AAC5B,iBAAO;AACP,iBAAO,OAAO,SAAS;AAAA,QACxB,WAAW,CAAC,MAAM;AACjB,iBAAO,IAAI,iBAAiB,KAAK,KAAK,CAAC;AACvC,iBAAO,MAAM;AACZ,gBAAI,OAAO,UAAU,OAAO,OAAO,OAAO,SAAS,CAAC,KAAK;AAAG;AAC5D,gBAAI,QAAQ,WAAW,MAAM,CAAC,CAAC;AAC/B,gBAAI;AAAO,oBAAM,IAAI;AAAA,UACtB;AACA,eAAK,MAAM,KAAK,IAAI;AAAA,QACrB,OAAO;AACN,cAAI,SAAS,IAAI,mBAAmB,MAAM,IAAI;AAE9C,iBAAO,MAAM;AACZ,gBAAI,QAAQ,OAAO,UAAU,OAAO,OAAO,OAAO,SAAS,CAAC;AAC5D,gBAAI,SAAS;AAAG;AAChB,gBAAI,QAAQ,aAAa,MAAM,CAAC,CAAC;AACjC,gBAAI;AACH,oBAAM,MAAM;AAAA,iBACR;AACJ,kBAAI,CAAC;AAAO,wBAAQ,CAAC;AACrB,kBAAI,CAAC;AAAQ,yBAAS,CAAC;AACvB,oBAAM,KAAK,MAAM,CAAC,CAAC;AACnB,kBAAI,cAAwB,CAAC;AAC7B,uBAAS,IAAI,GAAG,IAAI,OAAO;AAC1B,4BAAY,KAAK,SAAS,MAAM,IAAI,CAAC,CAAC,CAAC;AACxC,qBAAO,KAAK,WAAW;AAAA,YACxB;AAAA,UACD;AACA,cAAI,OAAO,iBAAiB,KAAK,OAAO,kBAAkB,GAAG;AAC5D,mBAAO,gBAAgB,OAAO;AAC9B,mBAAO,iBAAiB,OAAO;AAAA,UAChC;AACA,cAAI,SAAS,MAAM,SAAS,KAAK,UAAU,OAAO,SAAS,GAAG;AAC7D,mBAAO,QAAQ;AACf,mBAAO,SAAS;AAChB,oBAAQ;AACR,qBAAS;AAAA,UACV;AACA,iBAAO,IAAI,OAAO,IAAI,KAAK;AAC3B,iBAAO,IAAI,OAAO,IAAI,KAAK;AAC3B,cAAI,OAAO,WAAW,IAAI;AACzB,mBAAO,MAAM,OAAO,IAAI,OAAO,UAAU,KAAK;AAC9C,mBAAO,MAAM,OAAO,IAAI,OAAO,SAAS,KAAK;AAAA,UAC9C,OAAO;AACN,mBAAO,MAAM,OAAO,IAAI,OAAO,SAAS,KAAK;AAC7C,mBAAO,MAAM,OAAO,IAAI,OAAO,UAAU,KAAK;AAAA,UAC/C;AACA,eAAK,QAAQ,KAAK,MAAM;AAAA,QACzB;AAAA,MACD;AAAA,IACD;AAAA,IAEA,WAAY,MAAyC;AACpD,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC7C,YAAI,KAAK,QAAQ,CAAC,EAAE,QAAQ,MAAM;AACjC,iBAAO,KAAK,QAAQ,CAAC;AAAA,QACtB;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,IAEA,YAAa,cAAgC,aAAqB,IAAI;AACrE,eAAS,QAAQ,KAAK;AACrB,aAAK,WAAW,aAAa,IAAI,aAAa,KAAK,IAAI,CAAC;AAAA,IAC1D;AAAA,IAEA,UAAW;AACV,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,aAAK,MAAM,CAAC,EAAE,SAAS,QAAQ;AAAA,MAChC;AAAA,IACD;AAAA,EACD;AAEA,MAAM,qBAAN,MAAyB;AAAA,IACxB;AAAA,IACA,QAAgB;AAAA,IAEhB,YAAa,MAAc;AAC1B,WAAK,QAAQ,KAAK,MAAM,YAAY;AAAA,IACrC;AAAA,IAEA,WAA2B;AAC1B,UAAI,KAAK,SAAS,KAAK,MAAM;AAC5B,eAAO;AACR,aAAO,KAAK,MAAM,KAAK,OAAO;AAAA,IAC/B;AAAA,IAEA,UAAW,OAAiB,MAA6B;AACxD,UAAI,CAAC;AAAM,eAAO;AAClB,aAAO,KAAK,KAAK;AACjB,UAAI,KAAK,UAAU;AAAG,eAAO;AAE7B,UAAI,QAAQ,KAAK,QAAQ,GAAG;AAC5B,UAAI,SAAS;AAAI,eAAO;AACxB,YAAM,CAAC,IAAI,KAAK,OAAO,GAAG,KAAK,EAAE,KAAK;AACtC,eAAS,IAAI,GAAG,YAAY,QAAQ,KAAK,KAAK;AAC7C,YAAI,QAAQ,KAAK,QAAQ,KAAK,SAAS;AACvC,YAAI,SAAS,IAAI;AAChB,gBAAM,CAAC,IAAI,KAAK,OAAO,SAAS,EAAE,KAAK;AACvC,iBAAO;AAAA,QACR;AACA,cAAM,CAAC,IAAI,KAAK,OAAO,WAAW,QAAQ,SAAS,EAAE,KAAK;AAC1D,oBAAY,QAAQ;AACpB,YAAI,KAAK;AAAG,iBAAO;AAAA,MACpB;AAAA,IACD;AAAA,EACD;AAEO,MAAM,mBAAN,MAAuB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAA0B;AAAA,IAC1B,QAAgB;AAAA,IAChB,SAAiB;AAAA,IACjB,MAAe;AAAA,IACf,UAAU,IAAI,MAA0B;AAAA,IAExC,YAAa,MAAc;AAC1B,WAAK,OAAO;AAAA,IACb;AAAA,IAEA,WAAY,SAAkB;AAC7B,WAAK,UAAU;AACf,cAAQ,WAAW,KAAK,WAAW,KAAK,SAAS;AACjD,cAAQ,SAAS,KAAK,OAAO,KAAK,KAAK;AACvC,eAAS,UAAU,KAAK;AACvB,eAAO,UAAU;AAAA,IACnB;AAAA,EACD;AAEO,MAAM,qBAAN,cAAiC,cAAc;AAAA,IACrD;AAAA,IACA;AAAA,IACA,IAAY;AAAA,IACZ,IAAY;AAAA,IACZ,UAAkB;AAAA,IAClB,UAAkB;AAAA,IAClB,gBAAwB;AAAA,IACxB,iBAAyB;AAAA,IACzB,QAAgB;AAAA,IAChB,UAAkB;AAAA,IAClB,QAAyB;AAAA,IACzB,SAA4B;AAAA,IAE5B,YAAa,MAAwB,MAAc;AAClD,YAAM;AACN,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,QAAQ,KAAK,IAAI;AAAA,IACvB;AAAA,EACD;;;ACxOO,MAAM,iBAAN,cAA6B,iBAA6C;AAAA,IAChF,SAA+B;AAAA;AAAA,IAG/B;AAAA;AAAA,IAGA,YAA6B,CAAC;AAAA;AAAA;AAAA;AAAA,IAK9B,MAAuB,CAAC;AAAA;AAAA,IAGxB,YAA2B,CAAC;AAAA;AAAA,IAG5B,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA;AAAA,IAG5B,QAAgB;AAAA;AAAA,IAGhB,SAAiB;AAAA;AAAA,IAGjB,aAAqB;AAAA;AAAA;AAAA,IAIrB,QAAuB,CAAC;AAAA,IAEhB,aAAoC;AAAA,IAE5C,WAA4B;AAAA,IAE5B,YAAY,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,IAEhC,YAAa,MAAc,MAAc;AACxC,YAAM,IAAI;AACV,WAAK,OAAO;AAAA,IACb;AAAA;AAAA;AAAA,IAIA,eAAgB;AACf,UAAI,CAAC,KAAK;AAAQ,cAAM,IAAI,MAAM,iBAAiB;AACnD,UAAI,YAAY,KAAK;AACrB,UAAI,CAAC,KAAK,OAAO,KAAK,IAAI,UAAU,UAAU;AAAQ,aAAK,MAAM,MAAM,cAAc,UAAU,MAAM;AACrG,UAAI,MAAM,KAAK;AACf,UAAI,IAAI,KAAK,IAAI;AACjB,UAAI,IAAI,KAAK,OAAO,GAAG,IAAI,KAAK,OAAO,GAAG,QAAQ,GAAG,SAAS;AAC9D,UAAI,KAAK,kBAAkB,oBAAoB;AAC9C,YAAI,SAAS,KAAK,QAAQ,OAAO,OAAO;AACxC,YAAI,eAAe,KAAK,OAAO,gBAAgB,KAAK;AACpD,gBAAQ,OAAO,SAAS;AAAA,UACvB,KAAK;AACJ,kBAAM,OAAO,iBAAiB,OAAO,UAAU,OAAO,UAAU;AAChE,kBAAM,OAAO,gBAAgB,OAAO,UAAU,OAAO,SAAS;AAC9D,oBAAQ,OAAO,iBAAiB;AAChC,qBAAS,OAAO,gBAAgB;AAChC,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC9B,kBAAI,CAAC,IAAI,IAAI,UAAU,IAAI,CAAC,IAAI;AAChC,kBAAI,IAAI,CAAC,IAAI,KAAK,IAAI,UAAU,CAAC,KAAK;AAAA,YACvC;AACA;AAAA,UACD,KAAK;AACJ,kBAAM,OAAO,gBAAgB,OAAO,UAAU,OAAO,SAAS;AAC9D,iBAAK,OAAO,UAAU;AACtB,oBAAQ,OAAO,gBAAgB;AAC/B,qBAAS,OAAO,iBAAiB;AACjC,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC9B,kBAAI,CAAC,IAAI,KAAK,IAAI,UAAU,CAAC,KAAK;AAClC,kBAAI,IAAI,CAAC,IAAI,KAAK,IAAI,UAAU,IAAI,CAAC,KAAK;AAAA,YAC3C;AACA;AAAA,UACD,KAAK;AACJ,iBAAK,OAAO,UAAU;AACtB,iBAAK,OAAO,UAAU;AACtB,oBAAQ,OAAO,iBAAiB;AAChC,qBAAS,OAAO,gBAAgB;AAChC,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC9B,kBAAI,CAAC,IAAI,KAAK,IAAI,UAAU,IAAI,CAAC,KAAK;AACtC,kBAAI,IAAI,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI;AAAA,YACjC;AACA;AAAA,QACF;AACA,aAAK,OAAO,UAAU;AACtB,cAAM,OAAO,iBAAiB,OAAO,UAAU,OAAO,UAAU;AAChE,gBAAQ,OAAO,gBAAgB;AAC/B,iBAAS,OAAO,iBAAiB;AAAA,MAClC,WAAW,CAAC,KAAK,QAAQ;AACxB,YAAI,IAAI;AACR,gBAAQ,SAAS;AAAA,MAClB,OAAO;AACN,gBAAQ,KAAK,OAAO,KAAK;AACzB,iBAAS,KAAK,OAAO,KAAK;AAAA,MAC3B;AAEA,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC9B,YAAI,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI;AAC5B,YAAI,IAAI,CAAC,IAAI,IAAI,UAAU,IAAI,CAAC,IAAI;AAAA,MACrC;AAAA,IACD;AAAA;AAAA;AAAA;AAAA,IAKA,gBAAiB;AAChB,aAAO,KAAK;AAAA,IACb;AAAA;AAAA,IAGA,cAAe,YAA4B;AAC1C,WAAK,aAAa;AAClB,UAAI,YAAY;AACf,aAAK,QAAQ,WAAW;AACxB,aAAK,WAAW,WAAW;AAC3B,aAAK,sBAAsB,WAAW;AACtC,aAAK,YAAY,WAAW;AAC5B,aAAK,YAAY,WAAW;AAC5B,aAAK,aAAa,WAAW;AAC7B,aAAK,sBAAsB,WAAW;AAAA,MACvC;AAAA,IACD;AAAA,IAEA,OAAoB;AACnB,UAAI,KAAK;AAAY,eAAO,KAAK,cAAc;AAE/C,UAAI,OAAO,IAAI,eAAe,KAAK,MAAM,KAAK,IAAI;AAClD,WAAK,SAAS,KAAK;AACnB,WAAK,MAAM,aAAa,KAAK,KAAK;AAElC,WAAK,OAAO,IAAI;AAChB,WAAK,YAAY,IAAI,MAAc,KAAK,UAAU,MAAM;AACxD,YAAM,UAAU,KAAK,WAAW,GAAG,KAAK,WAAW,GAAG,KAAK,UAAU,MAAM;AAC3E,WAAK,MAAM,IAAI,MAAc,KAAK,IAAI,MAAM;AAC5C,YAAM,UAAU,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,IAAI,MAAM;AACzD,WAAK,YAAY,IAAI,MAAc,KAAK,UAAU,MAAM;AACxD,YAAM,UAAU,KAAK,WAAW,GAAG,KAAK,WAAW,GAAG,KAAK,UAAU,MAAM;AAC3E,WAAK,aAAa,KAAK;AAEvB,WAAK,WAAW,KAAK,YAAY,OAAO,KAAK,SAAS,KAAK,IAAI;AAG/D,UAAI,KAAK,OAAO;AACf,aAAK,QAAQ,IAAI,MAAc,KAAK,MAAM,MAAM;AAChD,cAAM,UAAU,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,MAAM,MAAM;AAAA,MAChE;AACA,WAAK,QAAQ,KAAK;AAClB,WAAK,SAAS,KAAK;AAEnB,aAAO;AAAA,IACR;AAAA,IAEA,qBAAsB,MAAY,OAAe,OAAeC,gBAAgC,QAAgB,QAAgB;AAC/H,UAAI,KAAK,YAAY;AAAM,aAAK,SAAS,MAAM,MAAM,IAAI;AACzD,YAAM,qBAAqB,MAAM,OAAO,OAAOA,gBAAe,QAAQ,MAAM;AAAA,IAC7E;AAAA;AAAA,IAGA,gBAAiC;AAChC,UAAI,OAAO,IAAI,eAAe,KAAK,MAAM,KAAK,IAAI;AAClD,WAAK,SAAS,KAAK;AACnB,WAAK,MAAM,aAAa,KAAK,KAAK;AAClC,WAAK,qBAAqB,KAAK;AAC/B,WAAK,cAAc,KAAK,aAAa,KAAK,aAAa,IAAI;AAC3D,UAAI,KAAK,UAAU;AAAM,aAAK,aAAa;AAC3C,aAAO;AAAA,IACR;AAAA,EACD;;;ACjLO,MAAM,iBAAN,cAA6B,iBAAiB;AAAA;AAAA,IAGpD,UAAyB,CAAC;AAAA;AAAA,IAG1B,SAAS;AAAA;AAAA;AAAA,IAIT,gBAAgB;AAAA;AAAA;AAAA,IAIhB,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,IAE5B,YAAa,MAAc;AAC1B,YAAM,IAAI;AAAA,IACX;AAAA,IAEA,OAAoB;AACnB,UAAI,OAAO,IAAI,eAAe,KAAK,IAAI;AACvC,WAAK,OAAO,IAAI;AAChB,WAAK,UAAU,IAAI,MAAc,KAAK,QAAQ,MAAM;AACpD,YAAM,UAAU,KAAK,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,QAAQ,MAAM;AACrE,WAAK,SAAS;AACd,WAAK,gBAAgB,KAAK;AAC1B,WAAK,MAAM,aAAa,KAAK,KAAK;AAClC,aAAO;AAAA,IACR;AAAA,EACD;;;AC3BO,MAAM,kBAAN,cAA8B,iBAAiB;AAAA,IACrD,IAAY;AAAA,IACZ,IAAY;AAAA,IACZ,WAAmB;AAAA;AAAA;AAAA,IAInB,QAAQ,IAAI,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA,IAElC,YAAa,MAAc;AAC1B,YAAM,IAAI;AAAA,IACX;AAAA,IAEA,qBAAsB,MAAY,OAAgB;AACjD,YAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AACnD,YAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AACnD,aAAO;AAAA,IACR;AAAA,IAEA,qBAAsB,MAAY;AACjC,YAAM,IAAI,KAAK,WAAW,UAAU,QAAQ,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;AAC/E,YAAM,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK;AACpC,YAAM,IAAI,MAAM,KAAK,IAAI,MAAM,KAAK;AACpC,aAAO,UAAU,SAAS,GAAG,CAAC;AAAA,IAC/B;AAAA,IAEA,OAAoB;AACnB,UAAI,OAAO,IAAI,gBAAgB,KAAK,IAAI;AACxC,WAAK,IAAI,KAAK;AACd,WAAK,IAAI,KAAK;AACd,WAAK,WAAW,KAAK;AACrB,WAAK,MAAM,aAAa,KAAK,KAAK;AAClC,aAAO;AAAA,IACR;AAAA,EACD;;;AChCO,MAAM,oBAAN,cAA+B,WAAuC;AAAA;AAAA,IAE5E,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,WAAW;AAAA;AAAA,IAGX,QAAQ;AAAA;AAAA,IAGR,SAAS;AAAA;AAAA,IAGT,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA;AAAA,IAG5B;AAAA,IAEA,SAA+B;AAAA,IAC/B,WAA4B;AAAA;AAAA;AAAA;AAAA,IAK5B,SAAS,MAAM,cAAc,CAAC;AAAA,IAE9B,MAAM,MAAM,cAAc,CAAC;AAAA,IAE3B,YAAY,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,IAEhC,YAAa,MAAc,MAAc;AACxC,YAAM,IAAI;AACV,WAAK,OAAO;AAAA,IACb;AAAA;AAAA,IAGA,eAAsB;AACrB,UAAI,CAAC,KAAK;AAAQ,cAAM,IAAI,MAAM,iBAAiB;AACnD,UAAI,SAAS,KAAK;AAClB,UAAI,MAAM,KAAK;AAEf,UAAI,UAAU,MAAM;AACnB,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT,YAAI,CAAC,IAAI;AACT;AAAA,MACD;AAEA,UAAI,eAAe,KAAK,QAAQ,KAAK,OAAO,gBAAgB,KAAK;AACjE,UAAI,eAAe,KAAK,SAAS,KAAK,OAAO,iBAAiB,KAAK;AACnE,UAAI,SAAS,CAAC,KAAK,QAAQ,IAAI,KAAK,SAAS,KAAK,OAAO,UAAU;AACnE,UAAI,SAAS,CAAC,KAAK,SAAS,IAAI,KAAK,SAAS,KAAK,OAAO,UAAU;AACpE,UAAI,UAAU,SAAS,KAAK,OAAO,QAAQ;AAC3C,UAAI,UAAU,SAAS,KAAK,OAAO,SAAS;AAC5C,UAAI,UAAU,KAAK,WAAW,UAAU;AACxC,UAAI,MAAM,KAAK,IAAI,OAAO;AAC1B,UAAI,MAAM,KAAK,IAAI,OAAO;AAC1B,UAAI,IAAI,KAAK,GAAG,IAAI,KAAK;AACzB,UAAI,YAAY,SAAS,MAAM;AAC/B,UAAI,YAAY,SAAS;AACzB,UAAI,YAAY,SAAS,MAAM;AAC/B,UAAI,YAAY,SAAS;AACzB,UAAI,aAAa,UAAU,MAAM;AACjC,UAAI,aAAa,UAAU;AAC3B,UAAI,aAAa,UAAU,MAAM;AACjC,UAAI,aAAa,UAAU;AAC3B,UAAI,SAAS,KAAK;AAClB,aAAO,CAAC,IAAI,YAAY;AACxB,aAAO,CAAC,IAAI,YAAY;AACxB,aAAO,CAAC,IAAI,YAAY;AACxB,aAAO,CAAC,IAAI,aAAa;AACzB,aAAO,CAAC,IAAI,aAAa;AACzB,aAAO,CAAC,IAAI,aAAa;AACzB,aAAO,CAAC,IAAI,aAAa;AACzB,aAAO,CAAC,IAAI,YAAY;AAExB,UAAI,OAAO,WAAW,IAAI;AACzB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAAA,MACjB,OAAO;AACN,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,CAAC,IAAI,OAAO;AAAA,MACjB;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,qBAAsB,MAAYC,gBAAgC,QAAgB,QAAgB;AACjG,UAAI,KAAK,YAAY;AACpB,aAAK,SAAS,MAAM,MAAM,IAAI;AAE/B,UAAI,OAAO,KAAK;AAChB,UAAI,eAAe,KAAK;AACxB,UAAI,IAAI,KAAK,QAAQ,IAAI,KAAK;AAC9B,UAAI,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK;AACjD,UAAI,UAAU,GAAG,UAAU;AAE3B,gBAAU,aAAa,CAAC;AACxB,gBAAU,aAAa,CAAC;AACxB,MAAAA,eAAc,MAAM,IAAI,UAAU,IAAI,UAAU,IAAI;AACpD,MAAAA,eAAc,SAAS,CAAC,IAAI,UAAU,IAAI,UAAU,IAAI;AACxD,gBAAU;AAEV,gBAAU,aAAa,CAAC;AACxB,gBAAU,aAAa,CAAC;AACxB,MAAAA,eAAc,MAAM,IAAI,UAAU,IAAI,UAAU,IAAI;AACpD,MAAAA,eAAc,SAAS,CAAC,IAAI,UAAU,IAAI,UAAU,IAAI;AACxD,gBAAU;AAEV,gBAAU,aAAa,CAAC;AACxB,gBAAU,aAAa,CAAC;AACxB,MAAAA,eAAc,MAAM,IAAI,UAAU,IAAI,UAAU,IAAI;AACpD,MAAAA,eAAc,SAAS,CAAC,IAAI,UAAU,IAAI,UAAU,IAAI;AACxD,gBAAU;AAEV,gBAAU,aAAa,CAAC;AACxB,gBAAU,aAAa,CAAC;AACxB,MAAAA,eAAc,MAAM,IAAI,UAAU,IAAI,UAAU,IAAI;AACpD,MAAAA,eAAc,SAAS,CAAC,IAAI,UAAU,IAAI,UAAU,IAAI;AAAA,IACzD;AAAA,IAEA,OAAoB;AACnB,UAAI,OAAO,IAAI,kBAAiB,KAAK,MAAM,KAAK,IAAI;AACpD,WAAK,SAAS,KAAK;AACnB,WAAK,IAAI,KAAK;AACd,WAAK,IAAI,KAAK;AACd,WAAK,SAAS,KAAK;AACnB,WAAK,SAAS,KAAK;AACnB,WAAK,WAAW,KAAK;AACrB,WAAK,QAAQ,KAAK;AAClB,WAAK,SAAS,KAAK;AACnB,YAAM,UAAU,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,CAAC;AAC3C,YAAM,UAAU,KAAK,QAAQ,GAAG,KAAK,QAAQ,GAAG,CAAC;AACjD,WAAK,MAAM,aAAa,KAAK,KAAK;AAClC,WAAK,WAAW,KAAK,YAAY,OAAO,KAAK,SAAS,KAAK,IAAI;AAC/D,aAAO;AAAA,IACR;AAAA,EAqCD;AA9MO,MAAM,mBAAN;AA2KN,gBA3KY,kBA2KL,MAAK;AACZ,gBA5KY,kBA4KL,MAAK;AACZ,gBA7KY,kBA6KL,OAAM;AACb,gBA9KY,kBA8KL,OAAM;AACb,gBA/KY,kBA+KL,OAAM;AACb,gBAhLY,kBAgLL,OAAM;AACb,gBAjLY,kBAiLL,MAAK;AACZ,gBAlLY,kBAkLL,MAAK;AAEZ,gBApLY,kBAoLL,MAAK;AACZ,gBArLY,kBAqLL,MAAK;AACZ,gBAtLY,kBAsLL,OAAM;AACb,gBAvLY,kBAuLL,OAAM;AACb,gBAxLY,kBAwLL,OAAM;AACb,gBAzLY,kBAyLL,OAAM;AACb,gBA1LY,kBA0LL,MAAK;AACZ,gBA3LY,kBA2LL,MAAK;AAEZ,gBA7LY,kBA6LL,MAAK;AACZ,gBA9LY,kBA8LL,MAAK;AACZ,gBA/LY,kBA+LL,OAAM;AACb,gBAhMY,kBAgML,OAAM;AACb,gBAjMY,kBAiML,OAAM;AACb,gBAlMY,kBAkML,OAAM;AACb,gBAnMY,kBAmML,MAAK;AACZ,gBApMY,kBAoML,MAAK;AAEZ,gBAtMY,kBAsML,MAAK;AACZ,gBAvMY,kBAuML,MAAK;AACZ,gBAxMY,kBAwML,OAAM;AACb,gBAzMY,kBAyML,OAAM;AACb,gBA1MY,kBA0ML,OAAM;AACb,gBA3MY,kBA2ML,OAAM;AACb,gBA5MY,kBA4ML,MAAK;AACZ,gBA7MY,kBA6ML,MAAK;;;ACzMN,MAAM,wBAAN,MAAwD;AAAA,IAC9D;AAAA,IAEA,YAAa,OAAqB;AACjC,WAAK,QAAQ;AAAA,IACd;AAAA,IAEA,aAAc,MAAc,UAAkB,UAAoB;AACjE,UAAI,UAAU,SAAS;AACvB,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAAI,GAAG,KAAK;AAC/C,YAAI,OAAO,SAAS,QAAQ,UAAU,CAAC;AACvC,YAAI,SAAS,KAAK,MAAM,WAAW,IAAI;AACvC,YAAI,UAAU;AAAM,gBAAM,IAAI,MAAM,gCAAgC,OAAO,iBAAiB,OAAO,GAAG;AACtG,gBAAQ,CAAC,IAAI;AAAA,MACd;AAAA,IACD;AAAA,IAEA,oBAAqB,MAAY,MAAc,MAAc,UAAsC;AAClG,UAAI,aAAa,IAAI,iBAAiB,MAAM,IAAI;AAChD,UAAI,YAAY,MAAM;AACrB,aAAK,aAAa,MAAM,MAAM,QAAQ;AAAA,MACvC,OAAO;AACN,YAAI,SAAS,KAAK,MAAM,WAAW,IAAI;AACvC,YAAI,CAAC;AAAQ,gBAAM,IAAI,MAAM,gCAAgC,OAAO,0BAA0B,OAAO,GAAG;AACxG,mBAAW,SAAS;AAAA,MACrB;AACA,aAAO;AAAA,IACR;AAAA,IAEA,kBAAmB,MAAY,MAAc,MAAc,UAAoC;AAC9F,UAAI,aAAa,IAAI,eAAe,MAAM,IAAI;AAC9C,UAAI,YAAY,MAAM;AACrB,aAAK,aAAa,MAAM,MAAM,QAAQ;AAAA,MACvC,OAAO;AACN,YAAI,SAAS,KAAK,MAAM,WAAW,IAAI;AACvC,YAAI,CAAC;AAAQ,gBAAM,IAAI,MAAM,gCAAgC,OAAO,wBAAwB,OAAO,GAAG;AACtG,mBAAW,SAAS;AAAA,MACrB;AACA,aAAO;AAAA,IACR;AAAA,IAEA,yBAA0B,MAAY,MAAqC;AAC1E,aAAO,IAAI,sBAAsB,IAAI;AAAA,IACtC;AAAA,IAEA,kBAAmB,MAAY,MAA8B;AAC5D,aAAO,IAAI,eAAe,IAAI;AAAA,IAC/B;AAAA,IAEA,mBAAoB,MAAY,MAA+B;AAC9D,aAAO,IAAI,gBAAgB,IAAI;AAAA,IAChC;AAAA,IAEA,sBAAuB,MAAY,MAAkC;AACpE,aAAO,IAAI,mBAAmB,IAAI;AAAA,IACnC;AAAA,EACD;;;ACpEO,MAAM,WAAN,MAAe;AAAA;AAAA,IAErB,QAAgB;AAAA;AAAA,IAGhB;AAAA;AAAA,IAGA,SAA0B;AAAA;AAAA,IAG1B,SAAiB;AAAA;AAAA,IAGjB,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,WAAW;AAAA;AAAA,IAGX,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,UAAU,QAAQ;AAAA;AAAA;AAAA;AAAA,IAKlB,eAAe;AAAA;AAAA;AAAA,IAIf,QAAQ,IAAI,MAAM;AAAA;AAAA,IAGlB;AAAA;AAAA,IAGA,UAAU;AAAA,IAEV,YAAa,OAAe,MAAc,QAAyB;AAClE,UAAI,QAAQ;AAAG,cAAM,IAAI,MAAM,qBAAqB;AACpD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,QAAQ;AACb,WAAK,OAAO;AACZ,WAAK,SAAS;AAAA,IACf;AAAA,EACD;AAGO,MAAK,UAAL,kBAAKC,aAAL;AAAe,IAAAA,kBAAA;AAAQ,IAAAA,kBAAA;AAAiB,IAAAA,kBAAA;AAAwB,IAAAA,kBAAA;AAAS,IAAAA,kBAAA;AAApE,WAAAA;AAAA,KAAA;;;ACvDL,MAAM,OAAN,MAAgC;AAAA;AAAA,IAEtC;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA,SAAsB;AAAA;AAAA,IAGtB,WAAW,IAAI,MAAY;AAAA;AAAA,IAG3B,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,WAAW;AAAA;AAAA,IAGX,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA;AAAA,IAGT,KAAK;AAAA;AAAA,IAGL,KAAK;AAAA;AAAA,IAGL,YAAY;AAAA;AAAA,IAGZ,UAAU;AAAA;AAAA,IAGV,UAAU;AAAA;AAAA,IAGV,UAAU;AAAA;AAAA,IAGV,UAAU;AAAA;AAAA,IAGV,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA,IAGJ,SAAS;AAAA;AAAA,IAGT,SAAS;AAAA,IAET;AAAA,IAEA,SAAS;AAAA,IACT,SAAS;AAAA;AAAA,IAGT,YAAa,MAAgB,UAAoB,QAAqB;AACrE,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,WAAK,OAAO;AACZ,WAAK,WAAW;AAChB,WAAK,SAAS;AACd,WAAK,eAAe;AAAA,IACrB;AAAA;AAAA;AAAA,IAIA,WAAY;AACX,aAAO,KAAK;AAAA,IACb;AAAA;AAAA,IAGA,OAAQ,SAAkB;AACzB,WAAK,yBAAyB,KAAK,IAAI,KAAK,IAAI,KAAK,WAAW,KAAK,SAAS,KAAK,SAAS,KAAK,SAAS,KAAK,OAAO;AAAA,IACvH;AAAA;AAAA;AAAA;AAAA,IAKA,uBAAwB;AACvB,WAAK,yBAAyB,KAAK,GAAG,KAAK,GAAG,KAAK,UAAU,KAAK,QAAQ,KAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM;AAAA,IAChH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,yBAA0B,GAAW,GAAW,UAAkB,QAAgB,QAAgB,QAAgB,QAAgB;AACjI,WAAK,KAAK;AACV,WAAK,KAAK;AACV,WAAK,YAAY;AACjB,WAAK,UAAU;AACf,WAAK,UAAU;AACf,WAAK,UAAU;AACf,WAAK,UAAU;AAEf,UAAI,SAAS,KAAK;AAClB,UAAI,CAAC,QAAQ;AACZ,YAAI,WAAW,KAAK;AACpB,cAAM,KAAK,SAAS,QAAQ,KAAK,SAAS;AAC1C,cAAM,MAAM,WAAW,UAAU,UAAU;AAC3C,cAAM,MAAM,WAAW,KAAK,UAAU,UAAU;AAChD,aAAK,IAAI,KAAK,IAAI,EAAE,IAAI,SAAS;AACjC,aAAK,IAAI,KAAK,IAAI,EAAE,IAAI,SAAS;AACjC,aAAK,IAAI,KAAK,IAAI,EAAE,IAAI,SAAS;AACjC,aAAK,IAAI,KAAK,IAAI,EAAE,IAAI,SAAS;AACjC,aAAK,SAAS,IAAI,KAAK,SAAS;AAChC,aAAK,SAAS,IAAI,KAAK,SAAS;AAChC;AAAA,MACD;AAEA,UAAI,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO;AAC7D,WAAK,SAAS,KAAK,IAAI,KAAK,IAAI,OAAO;AACvC,WAAK,SAAS,KAAK,IAAI,KAAK,IAAI,OAAO;AAEvC,cAAQ,KAAK,SAAS;AAAA,QACrB,qBAAqB;AACpB,gBAAM,MAAM,WAAW,UAAU,UAAU;AAC3C,gBAAM,MAAM,WAAW,KAAK,UAAU,UAAU;AAChD,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB;AAAA,QACD;AAAA,QACA,8BAA8B;AAC7B,gBAAM,MAAM,WAAW,UAAU,UAAU;AAC3C,gBAAM,MAAM,WAAW,KAAK,UAAU,UAAU;AAChD,eAAK,IAAI,KAAK,IAAI,EAAE,IAAI;AACxB,eAAK,IAAI,KAAK,IAAI,EAAE,IAAI;AACxB,eAAK,IAAI,KAAK,IAAI,EAAE,IAAI;AACxB,eAAK,IAAI,KAAK,IAAI,EAAE,IAAI;AACxB;AAAA,QACD;AAAA,QACA,qCAAqC;AACpC,cAAI,KAAK,IAAI,KAAK,SAAS,QAAQ,KAAK,IAAI,KAAK,SAAS;AAC1D,gBAAM;AACN,gBAAM;AACN,cAAI,IAAI,KAAK,KAAK,KAAK;AACvB,cAAI,MAAM;AACV,cAAI,IAAI,MAAQ;AACf,gBAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI;AAC5C,iBAAK,KAAK;AACV,iBAAK,KAAK;AACV,kBAAM,KAAK,MAAM,IAAI,EAAE,IAAI,UAAU;AAAA,UACtC,OAAO;AACN,iBAAK;AACL,iBAAK;AACL,kBAAM,KAAK,KAAK,MAAM,IAAI,EAAE,IAAI,UAAU;AAAA,UAC3C;AACA,gBAAM,MAAM,WAAW,SAAS,OAAO,UAAU;AACjD,gBAAM,MAAM,WAAW,SAAS,MAAM,MAAM,UAAU;AACtD,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,gBAAM,KAAK,KAAK,IAAI,EAAE,IAAI;AAC1B,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB;AAAA,QACD;AAAA,QACA;AAAA,QACA,kCAAkC;AACjC,sBAAY,UAAU;AACtB,gBAAM,MAAM,KAAK,IAAI,QAAQ,GAAG,MAAM,KAAK,IAAI,QAAQ;AACvD,cAAI,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,SAAS;AAC/C,cAAI,MAAM,KAAK,MAAM,KAAK,OAAO,KAAK,SAAS;AAC/C,cAAI,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACnC,cAAI,IAAI;AAAS,gBAAI,IAAI;AACzB,gBAAM;AACN,gBAAM;AACN,cAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAC/B,cAAI,KAAK,8BACJ,KAAK,KAAK,KAAK,KAAK,MAAO,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,SAAS;AAAI,gBAAI,CAAC;AAC5F,qBAAW,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,EAAE;AAC1C,gBAAM,KAAK,KAAK,IAAI,QAAQ,IAAI;AAChC,gBAAM,KAAK,KAAK,IAAI,QAAQ,IAAI;AAChC,oBAAU,UAAU;AACpB,oBAAU,KAAK,UAAU,UAAU;AACnC,gBAAM,KAAK,KAAK,IAAI,MAAM,IAAI;AAC9B,gBAAM,KAAK,KAAK,IAAI,MAAM,IAAI;AAC9B,gBAAM,KAAK,KAAK,IAAI,MAAM,IAAI;AAC9B,gBAAM,KAAK,KAAK,IAAI,MAAM,IAAI;AAC9B,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB,eAAK,IAAI,KAAK,KAAK,KAAK;AACxB;AAAA,QACD;AAAA,MACD;AACA,WAAK,KAAK,KAAK,SAAS;AACxB,WAAK,KAAK,KAAK,SAAS;AACxB,WAAK,KAAK,KAAK,SAAS;AACxB,WAAK,KAAK,KAAK,SAAS;AAAA,IACzB;AAAA;AAAA,IAGA,iBAAkB;AACjB,UAAI,OAAO,KAAK;AAChB,WAAK,IAAI,KAAK;AACd,WAAK,IAAI,KAAK;AACd,WAAK,WAAW,KAAK;AACrB,WAAK,SAAS,KAAK;AACnB,WAAK,SAAS,KAAK;AACnB,WAAK,SAAS,KAAK;AACnB,WAAK,SAAS,KAAK;AACnB,WAAK,UAAU,KAAK;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,yBAA0B;AACzB,UAAI,SAAS,KAAK;AAClB,UAAI,CAAC,QAAQ;AACZ,aAAK,KAAK,KAAK,SAAS,KAAK,SAAS;AACtC,aAAK,KAAK,KAAK,SAAS,KAAK,SAAS;AACtC,aAAK,YAAY,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,UAAU;AACxD,aAAK,UAAU,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAC1D,aAAK,UAAU,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAC1D,aAAK,UAAU;AACf,aAAK,UAAU,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,UAAU;AAC5G;AAAA,MACD;AACA,UAAI,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO;AAC7D,UAAI,MAAM,KAAK,KAAK,KAAK,KAAK;AAC9B,UAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAC3D,UAAI,KAAK,KAAK,SAAS,OAAO,QAAQ,KAAK,KAAK,SAAS,OAAO;AAChE,WAAK,KAAM,KAAK,KAAK,KAAK;AAC1B,WAAK,KAAM,KAAK,KAAK,KAAK;AAE1B,UAAI,IAAI,IAAI,IAAI;AAChB,UAAI,KAAK,oCAAoC;AAC5C,aAAK,KAAK;AACV,aAAK,KAAK;AACV,aAAK,KAAK;AACV,aAAK,KAAK;AAAA,MACX,OAAO;AACN,gBAAQ,KAAK,SAAS;AAAA,UACrB,qCAAqC;AACpC,gBAAIC,KAAI,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,KAAK,KAAK,KAAK,KAAK;AACtD,iBAAK,CAAC,KAAK,KAAK,SAAS,SAASA,KAAI,KAAK,SAAS;AACpD,iBAAK,KAAK,KAAK,SAAS,SAASA,KAAI,KAAK,SAAS;AACnD,kBAAM,KAAK,KAAK,KAAK,KAAK;AAC1B,iBAAK,KAAK;AACV,iBAAK,KAAK;AACV;AAAA,UACD;AAAA,UACA;AAAA,UACA;AACC,gBAAI,MAAM,UAAU,OAAO,KAAK,QAAQ,GAAG,MAAM,UAAU,OAAO,KAAK,QAAQ;AAC/E,kBAAM,KAAK,MAAM,KAAK,OAAO,KAAK,SAAS;AAC3C,kBAAM,KAAK,MAAM,KAAK,OAAO,KAAK,SAAS;AAC3C,gBAAI,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACnC,gBAAI,IAAI;AAAS,kBAAI,IAAI;AACzB,kBAAM;AACN,kBAAM;AACN,gBAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAC/B,gBAAI,KAAK,8BAA8B,MAAM,MAAM,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,SAAS;AAAI,kBAAI,CAAC;AAC/G,gBAAI,IAAI,UAAU,KAAK,IAAI,KAAK,MAAM,IAAI,EAAE;AAC5C,iBAAK,KAAK,IAAI,CAAC,IAAI;AACnB,iBAAK,KAAK,IAAI,CAAC,IAAI;AACnB,kBAAM,KAAK,KAAK,KAAK,KAAK;AAC1B,iBAAK,KAAK;AACV,iBAAK,KAAK;AACV,iBAAK,KAAK;AACV,iBAAK,KAAK;AAAA,QACZ;AACA,aAAK,KAAK,KAAK,IAAI,KAAK,KAAK;AAC7B,aAAK,KAAK,KAAK,IAAI,KAAK,KAAK;AAC7B,aAAK,KAAK,KAAK,IAAI,KAAK,KAAK;AAC7B,aAAK,KAAK,KAAK,IAAI,KAAK,KAAK;AAAA,MAC9B;AAEA,WAAK,UAAU;AACf,WAAK,UAAU,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAC1C,UAAI,KAAK,UAAU,MAAQ;AAC1B,YAAI,MAAM,KAAK,KAAK,KAAK;AACzB,aAAK,UAAU,MAAM,KAAK;AAC1B,aAAK,UAAU,CAAC,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,IAAI,UAAU;AAC/D,aAAK,YAAY,KAAK,MAAM,IAAI,EAAE,IAAI,UAAU;AAAA,MACjD,OAAO;AACN,aAAK,UAAU;AACf,aAAK,UAAU,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAC1C,aAAK,UAAU;AACf,aAAK,YAAY,KAAK,KAAK,MAAM,IAAI,EAAE,IAAI,UAAU;AAAA,MACtD;AAAA,IACD;AAAA;AAAA,IAIA,oBAAqB;AACpB,aAAO,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,UAAU;AAAA,IAC/C;AAAA;AAAA,IAGA,oBAAqB;AACpB,aAAO,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,UAAU;AAAA,IAC/C;AAAA;AAAA,IAGA,iBAAkB;AACjB,aAAO,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IACnD;AAAA;AAAA,IAGA,iBAAkB;AACjB,aAAO,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IACnD;AAAA;AAAA,IAGA,aAAc,OAAgB;AAC7B,UAAI,SAAS,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AAClD,UAAI,IAAI,MAAM,IAAI,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK;AAClD,YAAM,IAAI,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI;AAC7C,YAAM,IAAI,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI;AAC7C,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,aAAc,OAAgB;AAC7B,UAAI,IAAI,MAAM,GAAG,IAAI,MAAM;AAC3B,YAAM,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK;AACzC,YAAM,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK;AACzC,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,cAAe,OAAgB;AAC9B,UAAI,SAAS;AAAM,cAAM,IAAI,MAAM,uBAAuB;AAC1D,aAAO,KAAK,UAAU,OAAO,QAAQ,KAAK,OAAO,aAAa,KAAK;AAAA,IACpE;AAAA;AAAA,IAGA,cAAe,OAAgB;AAC9B,UAAI,SAAS;AAAM,cAAM,IAAI,MAAM,uBAAuB;AAC1D,aAAO,KAAK,UAAU,OAAO,QAAQ,KAAK,OAAO,aAAa,KAAK;AAAA,IACpE;AAAA;AAAA,IAGA,qBAAsB,eAAuB;AAC5C,UAAI,MAAM,UAAU,OAAO,aAAa,GAAG,MAAM,UAAU,OAAO,aAAa;AAC/E,aAAO,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI,GAAG,IAAI,UAAU,SAAS,KAAK,WAAW,KAAK;AAAA,IACvH;AAAA;AAAA,IAGA,qBAAsB,eAAuB;AAC5C,uBAAiB,KAAK,WAAW,KAAK;AACtC,UAAI,MAAM,UAAU,OAAO,aAAa,GAAG,MAAM,UAAU,OAAO,aAAa;AAC/E,aAAO,KAAK,MAAM,MAAM,KAAK,IAAI,MAAM,KAAK,GAAG,MAAM,KAAK,IAAI,MAAM,KAAK,CAAC,IAAI,UAAU;AAAA,IACzF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,YAAa,SAAiB;AAC7B,iBAAW,UAAU;AACrB,YAAM,MAAM,KAAK,IAAI,OAAO,GAAG,MAAM,KAAK,IAAI,OAAO;AACrD,YAAM,KAAK,KAAK,GAAG,KAAK,KAAK;AAC7B,WAAK,IAAI,MAAM,KAAK,MAAM,KAAK;AAC/B,WAAK,IAAI,MAAM,KAAK,MAAM,KAAK;AAC/B,WAAK,IAAI,MAAM,KAAK,MAAM,KAAK;AAC/B,WAAK,IAAI,MAAM,KAAK,MAAM,KAAK;AAAA,IAChC;AAAA,EACD;;;ACxZO,MAAe,iBAAf,MAA8B;AAAA,IACpC,YAAoB,MAAqB,OAAsB,cAAuB;AAAlE;AAAqB;AAAsB;AAAA,IAAyB;AAAA,EACzF;;;ACCO,MAAM,mBAAN,MAA6C;AAAA,IAC3C,aAAqB;AAAA,IACrB;AAAA,IACA;AAAA,IACA,SAAyB,CAAC;AAAA,IAC1B,SAA4B,CAAC;AAAA,IAC7B,SAAS;AAAA,IACT,SAAS;AAAA,IAEjB,YAAa,eAAmE,aAAqB,IAAI,aAAyB,IAAI,WAAW,GAAG;AACnJ,WAAK,gBAAgB;AACrB,WAAK,aAAa;AAClB,WAAK,aAAa;AAAA,IACnB;AAAA,IAEQ,MAAO,MAAsB;AACpC,WAAK;AACL,aAAO,KAAK,aAAa;AAAA,IAC1B;AAAA,IAEQ,QAAS,UAA6C,MAAc,OAAY;AACvF,WAAK;AACL,WAAK;AACL,WAAK,OAAO,IAAI,IAAI;AACpB,UAAI;AAAU,iBAAS,MAAM,KAAK;AAAA,IACnC;AAAA,IAEQ,MAAO,UAAmD,MAAc,SAAiB;AAChG,WAAK;AACL,WAAK;AACL,WAAK,OAAO,IAAI,IAAI;AACpB,UAAI;AAAU,iBAAS,MAAM,OAAO;AAAA,IACrC;AAAA,IAEA,UAAW;AACV,UAAI,UAAU,IAAI,QAAQ,CAAC,SAAmD,WAAgD;AAC7H,YAAI,QAAQ,MAAM;AACjB,cAAI,KAAK,kBAAkB,GAAG;AAC7B,gBAAI,KAAK,UAAU;AAAG,qBAAO,KAAK,MAAM;AAAA;AACnC,sBAAQ,IAAI;AACjB;AAAA,UACD;AACA,gCAAsB,KAAK;AAAA,QAC5B;AACA,8BAAsB,KAAK;AAAA,MAC5B,CAAC;AACD,aAAO;AAAA,IACR;AAAA,IAEA,cAAe,MAAc,MAAc;AAC1C,WAAK,WAAW,YAAY,KAAK,aAAa,IAAI,IAAI;AAAA,IACvD;AAAA,IAEA,WAAY,MACX,UAAsD,MAAM;AAAA,IAAE,GAC9D,QAAiD,MAAM;AAAA,IAAE,GAAG;AAC5D,aAAO,KAAK,MAAM,IAAI;AAEtB,WAAK,WAAW,eAAe,MAAM,CAAC,SAA2B;AAChE,aAAK,QAAQ,SAAS,MAAM,IAAI;AAAA,MACjC,GAAG,CAAC,QAAgB,iBAA+B;AAClD,aAAK,MAAM,OAAO,MAAM,wBAAwB,gBAAgB,WAAW,cAAc;AAAA,MAC1F,CAAC;AAAA,IACF;AAAA,IAEA,SAAU,MACT,UAAgD,MAAM;AAAA,IAAE,GACxD,QAAiD,MAAM;AAAA,IAAE,GAAG;AAC5D,aAAO,KAAK,MAAM,IAAI;AAEtB,WAAK,WAAW,aAAa,MAAM,CAAC,SAAuB;AAC1D,aAAK,QAAQ,SAAS,MAAM,IAAI;AAAA,MACjC,GAAG,CAAC,QAAgB,iBAA+B;AAClD,aAAK,MAAM,OAAO,MAAM,sBAAsB,gBAAgB,WAAW,cAAc;AAAA,MACxF,CAAC;AAAA,IACF;AAAA,IAEA,SAAU,MACT,UAAkD,MAAM;AAAA,IAAE,GAC1D,QAAiD,MAAM;AAAA,IAAE,GAAG;AAC5D,aAAO,KAAK,MAAM,IAAI;AAEtB,WAAK,WAAW,aAAa,MAAM,CAAC,SAAuB;AAC1D,aAAK,QAAQ,SAAS,MAAM,IAAI;AAAA,MACjC,GAAG,CAAC,QAAgB,iBAA+B;AAClD,aAAK,MAAM,OAAO,MAAM,sBAAsB,gBAAgB,WAAW,cAAc;AAAA,MACxF,CAAC;AAAA,IACF;AAAA,IAEA,YAAa,MACZ,UAAoD,MAAM;AAAA,IAAE,GAC5D,QAAiD,MAAM;AAAA,IAAE,GAAG;AAC5D,aAAO,KAAK,MAAM,IAAI;AAEtB,UAAI,YAAY,CAAC,EAAE,OAAO,WAAW,eAAe,OAAO,cAAc,eAAe,OAAO;AAC/F,UAAI,cAAc,CAAC;AACnB,UAAI,aAAa;AAChB,cAAM,MAAM,EAAE,MAAmB,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa;AAC7D,cAAI,SAAS;AAAI,mBAAO,SAAS,KAAK;AACtC,eAAK,MAAM,OAAO,MAAM,wBAAwB,MAAM;AACtD,iBAAO;AAAA,QACR,CAAC,EAAE,KAAK,CAAC,SAAS;AACjB,iBAAO,OAAO,kBAAkB,MAAM,EAAE,kBAAkB,QAAQ,sBAAsB,OAAO,CAAC,IAAI;AAAA,QACrG,CAAC,EAAE,KAAK,CAAC,WAAW;AACnB,cAAI;AAAQ,iBAAK,QAAQ,SAAS,MAAM,KAAK,cAAc,MAAM,CAAC;AAAA,QACnE,CAAC;AAAA,MACF,OAAO;AACN,YAAI,QAAQ,IAAI,MAAM;AACtB,cAAM,cAAc;AACpB,cAAM,SAAS,MAAM;AACpB,eAAK,QAAQ,SAAS,MAAM,KAAK,cAAc,KAAK,CAAC;AAAA,QACtD;AACA,cAAM,UAAU,MAAM;AACrB,eAAK,MAAM,OAAO,MAAM,wBAAwB,MAAM;AAAA,QACvD;AACA,YAAI,KAAK,WAAW,YAAY,IAAI;AAAG,iBAAO,KAAK,WAAW,YAAY,IAAI;AAC9E,cAAM,MAAM;AAAA,MACb;AAAA,IACD;AAAA,IAEA,iBAAkB,MACjB,UAAuD,MAAM;AAAA,IAAE,GAC/D,QAAiD,MAAM;AAAA,IAAE,GACzD,WACC;AACD,UAAI,QAAQ,KAAK,YAAY,GAAG;AAChC,UAAI,SAAS,SAAS,IAAI,KAAK,UAAU,GAAG,QAAQ,CAAC,IAAI;AACzD,aAAO,KAAK,MAAM,IAAI;AAEtB,WAAK,WAAW,aAAa,MAAM,CAAC,cAA4B;AAC/D,YAAI;AACH,cAAI,QAAQ,IAAI,aAAa,SAAS;AACtC,cAAI,SAAS,MAAM,MAAM,QAAQ,QAAQ;AACzC,mBAAS,QAAQ,MAAM,OAAO;AAC7B,iBAAK;AAAA,cAAY,CAAC,YAAY,SAAS,KAAK,OAAO,UAAU,KAAK,IAAK;AAAA,cACtE,CAAC,WAAmB,YAAqB;AACxC,oBAAI,CAAC,OAAO;AACX,uBAAK,WAAW,OAAO;AACvB,sBAAI,EAAE,UAAU;AAAG,yBAAK,QAAQ,SAAS,MAAM,KAAK;AAAA,gBACrD;AAAA,cACD;AAAA,cACA,CAAC,WAAmB,YAAoB;AACvC,oBAAI,CAAC;AAAO,uBAAK,MAAM,OAAO,MAAM,+BAA+B,oBAAoB,WAAW;AAClG,wBAAQ;AAAA,cACT;AAAA,YACD;AAAA,UACD;AAAA,QACD,SAAS,GAAP;AACD,eAAK,MAAM,OAAO,MAAM,gCAAgC,SAAU,EAAU,SAAS;AAAA,QACtF;AAAA,MACD,GAAG,CAAC,QAAgB,iBAA+B;AAClD,aAAK,MAAM,OAAO,MAAM,+BAA+B,gBAAgB,WAAW,cAAc;AAAA,MACjG,CAAC;AAAA,IACF;AAAA,IAEA,IAAK,MAAc;AAClB,aAAO,KAAK,OAAO,KAAK,aAAa,IAAI;AAAA,IAC1C;AAAA,IAEA,QAAS,MAAc;AACtB,aAAO,KAAK,aAAa;AACzB,UAAI,QAAQ,KAAK,OAAO,IAAI;AAC5B,UAAI;AAAO,eAAO;AAClB,UAAI,QAAQ,KAAK,OAAO,IAAI;AAC5B,YAAM,MAAM,sBAAsB,QAAQ,QAAQ,OAAO,QAAQ,GAAG;AAAA,IACrE;AAAA,IAEA,OAAQ,MAAc;AACrB,aAAO,KAAK,aAAa;AACzB,UAAI,QAAQ,KAAK,OAAO,IAAI;AAC5B,UAAU,MAAO;AAAS,QAAM,MAAO,QAAQ;AAC/C,aAAO,KAAK,OAAO,IAAI;AACvB,aAAO;AAAA,IACR;AAAA,IAEA,YAAa;AACZ,eAAS,OAAO,KAAK,QAAQ;AAC5B,YAAI,QAAQ,KAAK,OAAO,GAAG;AAC3B,YAAU,MAAO;AAAS,UAAM,MAAO,QAAQ;AAAA,MAChD;AACA,WAAK,SAAS,CAAC;AAAA,IAChB;AAAA,IAEA,oBAA8B;AAC7B,aAAO,KAAK,UAAU;AAAA,IACvB;AAAA,IAEA,YAAqB;AACpB,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,YAAqB;AACpB,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,UAAW;AACV,WAAK,UAAU;AAAA,IAChB;AAAA,IAEA,YAAa;AACZ,aAAO,OAAO,KAAK,KAAK,MAAM,EAAE,SAAS;AAAA,IAC1C;AAAA,IAEA,YAAa;AACZ,aAAO,KAAK;AAAA,IACb;AAAA,EACD;AAEO,MAAM,aAAN,MAAiB;AAAA,IACf,YAAwC,CAAC;AAAA,IACjD,cAAiC,CAAC;AAAA,IAElC,gBAAiB,SAAiB;AACjC,UAAI,CAAC,QAAQ,WAAW,OAAO,GAAG;AACjC,cAAM,IAAI,MAAM,iBAAiB;AAAA,MAClC;AAEA,UAAI,YAAY,QAAQ,QAAQ,SAAS;AACzC,UAAI,aAAa,IAAI;AACpB,qBAAa,UAAU;AACvB,eAAO,KAAK,QAAQ,OAAO,SAAS,CAAC;AAAA,MACtC,OAAO;AACN,eAAO,QAAQ,OAAO,QAAQ,QAAQ,GAAG,IAAI,CAAC;AAAA,MAC/C;AAAA,IACD;AAAA,IAEA,mBAAoB,QAAgB;AACnC,UAAI,gBAAgB,OAAO,KAAK,MAAM;AACtC,UAAI,MAAM,cAAc;AACxB,UAAI,QAAQ,IAAI,WAAW,GAAG;AAC9B,eAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC7B,cAAM,CAAC,IAAI,cAAc,WAAW,CAAC;AAAA,MACtC;AACA,aAAO;AAAA,IACR;AAAA,IAEA,oBAAqB,SAAiB;AACrC,UAAI,CAAC,QAAQ,WAAW,OAAO,GAAG;AACjC,cAAM,IAAI,MAAM,iBAAiB;AAAA,MAClC;AAEA,UAAI,YAAY,QAAQ,QAAQ,SAAS;AACzC,UAAI,aAAa;AAAI,cAAM,IAAI,MAAM,wBAAwB;AAC7D,mBAAa,UAAU;AACvB,aAAO,KAAK,mBAAmB,QAAQ,OAAO,SAAS,CAAC;AAAA,IACzD;AAAA,IAEA,aAAc,KAAa,SAAiC,OAAuD;AAClH,UAAI,KAAK,MAAM,KAAK,SAAS,KAAK;AAAG;AACrC,UAAI,KAAK,YAAY,GAAG,GAAG;AAC1B,YAAI;AACH,cAAI,UAAU,KAAK,YAAY,GAAG;AAClC,eAAK,OAAO,KAAK,KAAK,KAAK,gBAAgB,OAAO,CAAC;AAAA,QACpD,SAAS,GAAP;AACD,eAAK,OAAO,KAAK,KAAK,KAAK,UAAU,CAAC,CAAC;AAAA,QACxC;AACA;AAAA,MACD;AACA,UAAI,UAAU,IAAI,eAAe;AACjC,cAAQ,iBAAiB,WAAW;AACpC,cAAQ,KAAK,OAAO,KAAK,IAAI;AAC7B,UAAI,OAAO,MAAM;AAChB,aAAK,OAAO,KAAK,QAAQ,QAAQ,QAAQ,YAAY;AAAA,MACtD;AACA,cAAQ,SAAS;AACjB,cAAQ,UAAU;AAClB,cAAQ,KAAK;AAAA,IACd;AAAA,IAEA,aAAc,KAAa,SAAiC,OAAuD;AAClH,WAAK,aAAa,KAAK,CAAC,SAAuB;AAC9C,gBAAQ,KAAK,MAAM,IAAI,CAAC;AAAA,MACzB,GAAG,KAAK;AAAA,IACT;AAAA,IAEA,eAAgB,KAAa,SAAqC,OAAuD;AACxH,UAAI,KAAK,MAAM,KAAK,SAAS,KAAK;AAAG;AACrC,UAAI,KAAK,YAAY,GAAG,GAAG;AAC1B,YAAI;AACH,cAAI,UAAU,KAAK,YAAY,GAAG;AAClC,eAAK,OAAO,KAAK,KAAK,KAAK,oBAAoB,OAAO,CAAC;AAAA,QACxD,SAAS,GAAP;AACD,eAAK,OAAO,KAAK,KAAK,KAAK,UAAU,CAAC,CAAC;AAAA,QACxC;AACA;AAAA,MACD;AACA,UAAI,UAAU,IAAI,eAAe;AACjC,cAAQ,KAAK,OAAO,KAAK,IAAI;AAC7B,cAAQ,eAAe;AACvB,UAAI,UAAU,MAAM;AACnB,aAAK,OAAO,KAAK,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,MAClD;AACA,cAAQ,SAAS,MAAM;AACtB,YAAI,QAAQ,UAAU,OAAO,QAAQ,UAAU;AAC9C,eAAK,OAAO,KAAK,KAAK,IAAI,WAAW,QAAQ,QAAuB,CAAC;AAAA;AAErE,kBAAQ;AAAA,MACV;AACA,cAAQ,UAAU;AAClB,cAAQ,KAAK;AAAA,IACd;AAAA,IAEQ,MAAO,KAAa,SAAc,OAAY;AACrD,UAAI,YAAY,KAAK,UAAU,GAAG;AAClC,UAAI;AACH,YAAI;AAAW,iBAAO;AACtB,aAAK,UAAU,GAAG,IAAI,YAAY,CAAC;AAAA,MACpC,UAAE;AACD,kBAAU,KAAK,SAAS,KAAK;AAAA,MAC9B;AAAA,IACD;AAAA,IAEQ,OAAQ,KAAa,QAAgB,MAAW;AACvD,UAAI,YAAY,KAAK,UAAU,GAAG;AAClC,aAAO,KAAK,UAAU,GAAG;AACzB,UAAI,OAAO,UAAU,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI;AAChE,eAAS,IAAI,KAAK,SAAS,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG,KAAK;AAC/D,kBAAU,CAAC,EAAE,MAAM,MAAM,IAAI;AAAA,IAC/B;AAAA,EACD;;;AC5TO,MAAM,QAAN,MAAY;AAAA,IAClB;AAAA,IACA,WAAmB;AAAA,IACnB,aAAqB;AAAA,IACrB,cAA6B;AAAA,IAC7B,OAAe;AAAA,IACf,SAAiB;AAAA,IACjB,UAAkB;AAAA,IAElB,YAAa,MAAc,MAAiB;AAC3C,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,OAAO;AACZ,WAAK,OAAO;AAAA,IACb;AAAA,EACD;;;AClBO,MAAM,YAAN,MAAgB;AAAA,IACtB;AAAA,IACA,WAAmB;AAAA,IACnB,aAAqB;AAAA,IACrB,cAA6B;AAAA,IAC7B,YAA2B;AAAA,IAC3B,SAAiB;AAAA,IACjB,UAAkB;AAAA,IAElB,YAAa,MAAc;AAC1B,WAAK,OAAO;AAAA,IACb;AAAA,EACD;;;ACJO,MAAM,eAAN,MAAwC;AAAA;AAAA,IAE9C;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA,gBAAgB;AAAA;AAAA,IAGhB,WAAW;AAAA;AAAA;AAAA,IAIX,UAAU;AAAA;AAAA,IAGV,MAAM;AAAA;AAAA,IAGN,WAAW;AAAA,IACX,SAAS;AAAA,IAET,YAAa,MAAwB,UAAoB;AACxD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,WAAK,OAAO;AAEZ,WAAK,QAAQ,IAAI,MAAY;AAC7B,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,YAAI,OAAO,SAAS,SAAS,KAAK,MAAM,CAAC,EAAE,IAAI;AAC/C,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,sBAAsB,KAAK,MAAM,CAAC,EAAE,MAAM;AACrE,aAAK,MAAM,KAAK,IAAI;AAAA,MACrB;AACA,UAAI,SAAS,SAAS,SAAS,KAAK,OAAO,IAAI;AAC/C,UAAI,CAAC;AAAQ,cAAM,IAAI,MAAM,sBAAsB,KAAK,OAAO,MAAM;AAErE,WAAK,SAAS;AACd,WAAK,MAAM,KAAK;AAChB,WAAK,WAAW,KAAK;AACrB,WAAK,gBAAgB,KAAK;AAC1B,WAAK,WAAW,KAAK;AACrB,WAAK,UAAU,KAAK;AAAA,IACrB;AAAA,IAEA,WAAY;AACX,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,iBAAkB;AACjB,YAAM,OAAO,KAAK;AAClB,WAAK,MAAM,KAAK;AAChB,WAAK,WAAW,KAAK;AACrB,WAAK,gBAAgB,KAAK;AAC1B,WAAK,WAAW,KAAK;AACrB,WAAK,UAAU,KAAK;AAAA,IACrB;AAAA,IAEA,OAAQ,SAAkB;AACzB,UAAI,KAAK,OAAO;AAAG;AACnB,UAAI,SAAS,KAAK;AAClB,UAAI,QAAQ,KAAK;AACjB,cAAQ,MAAM,QAAQ;AAAA,QACrB,KAAK;AACJ,eAAK,OAAO,MAAM,CAAC,GAAG,OAAO,QAAQ,OAAO,QAAQ,KAAK,UAAU,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK,GAAG;AAC5G;AAAA,QACD,KAAK;AACJ,eAAK,OAAO,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,QAAQ,OAAO,QAAQ,KAAK,eAAe,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK,UAAU,KAAK,GAAG;AAC1I;AAAA,MACF;AAAA,IACD;AAAA;AAAA,IAGA,OAAQ,MAAY,SAAiB,SAAiB,UAAmB,SAAkB,SAAkB,OAAe;AAC3H,UAAI,IAAI,KAAK;AACb,UAAI,CAAC;AAAG,cAAM,IAAI,MAAM,2BAA2B;AACnD,UAAI,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE;AACzC,UAAI,aAAa,CAAC,KAAK,UAAU,KAAK,WAAW,KAAK,GAAG,KAAK;AAE9D,cAAQ,KAAK,SAAS;AAAA,QACrB;AACC,gBAAM,UAAU,KAAK,UAAU,UAAU,OAAO,KAAK,SAAS,MAAM;AACpE,gBAAM,UAAU,KAAK,UAAU,UAAU,OAAO,KAAK,SAAS,MAAM;AACpE;AAAA,QACD;AACC,cAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,IAAI,KAAK,IAAI,MAAQ,KAAK,KAAK,KAAK,EAAE;AACxE,cAAI,KAAK,KAAK,KAAK,SAAS;AAC5B,cAAI,KAAK,KAAK,KAAK,SAAS;AAC5B,eAAK,CAAC,KAAK,IAAI,KAAK,SAAS;AAC7B,eAAK,KAAK,IAAI,KAAK,SAAS;AAC5B,wBAAc,KAAK,MAAM,IAAI,EAAE,IAAI,UAAU;AAAA,QAE9C;AACC,cAAI,IAAI,UAAU,EAAE,QAAQ,IAAI,UAAU,EAAE;AAC5C,cAAI,IAAI,KAAK,KAAK,KAAK;AACvB,cAAI,KAAK,IAAI,CAAC,KAAK,MAAQ;AAC1B,iBAAK;AACL,iBAAK;AAAA,UACN,OAAO;AACN,kBAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK;AAClC,kBAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK;AAAA,UACnC;AAAA,MACF;AACA,oBAAc,KAAK,MAAM,IAAI,EAAE,IAAI,UAAU;AAC7C,UAAI,KAAK,UAAU;AAAG,sBAAc;AACpC,UAAI,aAAa;AAChB,sBAAc;AAAA,eACN,aAAa;AACrB,sBAAc;AACf,UAAI,KAAK,KAAK,SAAS,KAAK,KAAK;AACjC,UAAI,YAAY,SAAS;AACxB,gBAAQ,KAAK,SAAS;AAAA,UACrB;AAAA,UACA;AACC,iBAAK,UAAU,KAAK;AACpB,iBAAK,UAAU,KAAK;AAAA,QACtB;AACA,cAAM,IAAI,KAAK,KAAK,SAAS;AAC7B,YAAI,IAAI,MAAQ;AACf,gBAAM,KAAK,KAAK,KAAK,KAAK;AAC1B,cAAK,YAAY,KAAK,IAAI,KAAO,WAAW,KAAK,IAAI,GAAI;AACxD,kBAAM,KAAK,KAAK,KAAK,EAAE,IAAI,IAAI,KAAK,QAAQ;AAC5C,kBAAM;AACN,gBAAI;AAAS,oBAAM;AAAA,UACpB;AAAA,QACD;AAAA,MACD;AACA,WAAK;AAAA,QAAyB,KAAK;AAAA,QAAI,KAAK;AAAA,QAAI,KAAK,YAAY,aAAa;AAAA,QAAO;AAAA,QAAI;AAAA,QAAI,KAAK;AAAA,QACjG,KAAK;AAAA,MAAO;AAAA,IACd;AAAA;AAAA;AAAA,IAIA,OAAQ,QAAc,OAAa,SAAiB,SAAiB,SAAiB,SAAkB,SAAkB,UAAkB,OAAe;AAC1J,UAAI,OAAO,6BAA6B,MAAM;AAA2B;AACzE,UAAI,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI,MAAM,OAAO,SAAS,MAAM,OAAO,SAAS,KAAK,KAAK,KAAK,KAAK,MAAM,MAAM;AAChH,UAAI,MAAM,GAAG,MAAM,GAAG,KAAK;AAC3B,UAAI,MAAM,GAAG;AACZ,cAAM,CAAC;AACP,cAAM;AACN,aAAK;AAAA,MACN,OAAO;AACN,cAAM;AACN,aAAK;AAAA,MACN;AACA,UAAI,MAAM,GAAG;AACZ,cAAM,CAAC;AACP,aAAK,CAAC;AAAA,MACP;AACA,UAAI,MAAM,GAAG;AACZ,cAAM,CAAC;AACP,cAAM;AAAA,MACP;AACC,cAAM;AACP,UAAI,KAAK,MAAM,IAAI,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,OAAO,GAAG,IAAI,OAAO,GAAG,IAAI,OAAO,GAAG,IAAI,OAAO;AAClG,UAAI,IAAI,KAAK,IAAI,MAAM,GAAG,KAAK;AAC/B,UAAI,CAAC,KAAK,SAAS;AAClB,aAAK;AACL,cAAM,IAAI,KAAK,OAAO;AACtB,cAAM,IAAI,KAAK,OAAO;AAAA,MACvB,OAAO;AACN,aAAK,MAAM;AACX,cAAM,IAAI,KAAK,IAAI,KAAK,OAAO;AAC/B,cAAM,IAAI,KAAK,IAAI,KAAK,OAAO;AAAA,MAChC;AACA,UAAI,KAAK,OAAO;AAChB,UAAI,CAAC;AAAI,cAAM,IAAI,MAAM,sCAAsC;AAC/D,UAAI,GAAG;AACP,UAAI,GAAG;AACP,UAAI,GAAG;AACP,UAAI,GAAG;AACP,UAAI,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,MAAM,GAAG,QAAQ,IAAI,MAAM,GAAG;AAC1D,WAAK,KAAK,IAAI,EAAE,KAAK,OAAS,IAAI,IAAI;AACtC,UAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK;AAChE,UAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,GAAG,KAAK,MAAM,KAAK,SAAS,KAAK,IAAI;AACzE,UAAI,KAAK,MAAQ;AAChB,aAAK,OAAO,QAAQ,SAAS,SAAS,OAAO,SAAS,OAAO,KAAK;AAClE,cAAM,yBAAyB,IAAI,IAAI,GAAG,MAAM,SAAS,MAAM,SAAS,MAAM,SAAS,MAAM,OAAO;AACpG;AAAA,MACD;AACA,UAAI,UAAU,GAAG;AACjB,UAAI,UAAU,GAAG;AACjB,UAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK;AAChE,UAAI,KAAK,KAAK,KAAK,KAAK;AACxB,UAAI,YAAY,GAAG;AAClB,oBAAY,OAAO,MAAM,KAAK;AAC9B,YAAI,KAAK,KAAK,KAAK,EAAE,GAAG,KAAK,KAAK,KAAK,KAAK,MAAM;AAClD,YAAI,KAAK,GAAG;AACX,cAAI,IAAI,KAAK,IAAI,GAAG,MAAM,WAAW,EAAE,IAAI;AAC3C,eAAK,KAAK,YAAY,IAAI,IAAI,MAAM;AACpC,gBAAM,IAAI;AACV,gBAAM,IAAI;AACV,eAAK,KAAK,KAAK,KAAK;AAAA,QACrB;AAAA,MACD;AACA;AACA,YAAI,GAAG;AACN,gBAAM;AACN,cAAI,OAAO,KAAK,KAAK,KAAK,KAAK,OAAO,IAAI,KAAK;AAC/C,cAAI,MAAM,IAAI;AACb,kBAAM;AACN,iBAAK,KAAK,KAAK;AAAA,UAChB,WAAW,MAAM,GAAG;AACnB,kBAAM;AACN,iBAAK;AACL,gBAAI,SAAS;AACZ,mBAAK,KAAK,KAAK,EAAE,KAAK,KAAK,MAAM,KAAK,QAAQ;AAC9C,oBAAM;AACN,kBAAI;AAAS,sBAAM;AAAA,YACpB;AAAA,UACD;AACC,iBAAK,KAAK,KAAK,GAAG,IAAI;AACvB,cAAI,KAAK,KAAK;AACd,cAAI,KAAK,KAAK,IAAI,EAAE;AACpB,eAAK,KAAK,MAAM,KAAK,IAAI,KAAK,GAAG,KAAK,IAAI,KAAK,CAAC;AAAA,QACjD,OAAO;AACN,cAAI,MAAM;AACV,cAAI,MAAM;AACV,cAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,IAAI,EAAE;AAClD,cAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK;AAClC,cAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK;AACjC,cAAI,KAAK,KAAK,IAAI,KAAK;AACvB,cAAI,KAAK,GAAG;AACX,gBAAI,IAAI,KAAK,KAAK,CAAC;AACnB,gBAAI,KAAK;AAAG,kBAAI,CAAC;AACjB,gBAAI,EAAE,KAAK,KAAK;AAChB,gBAAI,KAAK,IAAI,IAAI,KAAK,IAAI;AAC1B,gBAAI,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK;AAC3C,iBAAK,KAAK,IAAI;AACd,gBAAI,MAAM,GAAG;AACZ,kBAAI,KAAK,KAAK,EAAE,IAAI;AACpB,mBAAK,KAAK,KAAK,MAAM,GAAG,CAAC;AACzB,mBAAK,KAAK,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG;AACvC,oBAAM;AAAA,YACP;AAAA,UACD;AACA,cAAI,WAAW,UAAU,IAAI,OAAO,KAAK,GAAG,UAAU,OAAO,MAAM,OAAO;AAC1E,cAAI,WAAW,GAAG,OAAO,KAAK,GAAG,UAAU,OAAO,MAAM,OAAO;AAC/D,cAAI,CAAC,IAAI,MAAM,KAAK;AACpB,cAAI,KAAK,MAAM,KAAK,GAAG;AACtB,gBAAI,KAAK,KAAK,CAAC;AACf,gBAAI,IAAI,KAAK,IAAI,CAAC,IAAI;AACtB,gBAAI,IAAI,KAAK,IAAI,CAAC;AAClB,gBAAI,IAAI,IAAI,IAAI;AAChB,gBAAI,IAAI,SAAS;AAChB,yBAAW;AACX,wBAAU;AACV,qBAAO;AACP,qBAAO;AAAA,YACR;AACA,gBAAI,IAAI,SAAS;AAChB,yBAAW;AACX,wBAAU;AACV,qBAAO;AACP,qBAAO;AAAA,YACR;AAAA,UACD;AACA,cAAI,OAAO,UAAU,WAAW,KAAK;AACpC,iBAAK,KAAK,KAAK,MAAM,OAAO,SAAS,IAAI;AACzC,iBAAK,WAAW;AAAA,UACjB,OAAO;AACN,iBAAK,KAAK,KAAK,MAAM,OAAO,SAAS,IAAI;AACzC,iBAAK,WAAW;AAAA,UACjB;AAAA,QACD;AACA,UAAI,KAAK,KAAK,MAAM,IAAI,EAAE,IAAI;AAC9B,UAAI,WAAW,OAAO;AACtB,YAAM,KAAK,MAAM,UAAU,SAAS,MAAM;AAC1C,UAAI,KAAK;AACR,cAAM;AAAA,eACE,KAAK;AACb,cAAM;AACP,aAAO,yBAAyB,IAAI,IAAI,WAAW,KAAK,OAAO,IAAI,IAAI,GAAG,CAAC;AAC3E,iBAAW,MAAM;AACjB,aAAO,KAAK,MAAM,UAAU,SAAS,MAAM,WAAW,KAAK,MAAM;AACjE,UAAI,KAAK;AACR,cAAM;AAAA,eACE,KAAK;AACb,cAAM;AACP,YAAM,yBAAyB,IAAI,IAAI,WAAW,KAAK,OAAO,MAAM,SAAS,MAAM,SAAS,MAAM,SAAS,MAAM,OAAO;AAAA,IACzH;AAAA,EACD;;;ACjSO,MAAM,mBAAN,cAA+B,eAAe;AAAA;AAAA,IAEpD,QAAQ,IAAI,MAAgB;AAAA;AAAA,IAGpB,UAA2B;AAAA,IACnC,IAAW,OAAQ,UAAoB;AAAE,WAAK,UAAU;AAAA,IAAU;AAAA,IAClE,IAAW,SAAU;AACpB,UAAI,CAAC,KAAK;AAAS,cAAM,IAAI,MAAM,mBAAmB;AAAA;AACjD,eAAO,KAAK;AAAA,IAClB;AAAA;AAAA,IAGA,gBAAgB;AAAA;AAAA,IAGhB,WAAW;AAAA;AAAA;AAAA,IAIX,UAAU;AAAA;AAAA;AAAA,IAIV,UAAU;AAAA;AAAA,IAGV,MAAM;AAAA;AAAA,IAGN,WAAW;AAAA,IAEX,YAAa,MAAc;AAC1B,YAAM,MAAM,GAAG,KAAK;AAAA,IACrB;AAAA,EACD;;;AClCO,MAAM,qBAAN,cAAiC,eAAe;AAAA;AAAA,IAGtD,QAAQ,IAAI,MAAgB;AAAA;AAAA,IAGpB,UAA2B;AAAA,IACnC,IAAW,OAAQ,UAAoB;AAAE,WAAK,UAAU;AAAA,IAAU;AAAA,IAClE,IAAW,SAAU;AACpB,UAAI,CAAC,KAAK;AAAS,cAAM,IAAI,MAAM,mBAAmB;AAAA;AACjD,eAAO,KAAK;AAAA,IAClB;AAAA;AAAA,IAGA,eAA6B,aAAa;AAAA;AAAA,IAG1C,cAA2B,YAAY;AAAA;AAAA,IAGvC,aAAyB,WAAW;AAAA;AAAA,IAGpC,iBAAyB;AAAA;AAAA,IAGzB,WAAmB;AAAA;AAAA,IAGnB,UAAkB;AAAA,IAElB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,OAAO;AAAA,IAEP,YAAa,MAAc;AAC1B,YAAM,MAAM,GAAG,KAAK;AAAA,IACrB;AAAA,EACD;AAKO,MAAK,eAAL,kBAAKC,kBAAL;AAAoB,IAAAA,4BAAA;AAAO,IAAAA,4BAAA;AAAtB,WAAAA;AAAA,KAAA;AAKL,MAAK,cAAL,kBAAKC,iBAAL;AAAmB,IAAAA,0BAAA;AAAQ,IAAAA,0BAAA;AAAO,IAAAA,0BAAA;AAAS,IAAAA,0BAAA;AAAtC,WAAAA;AAAA,KAAA;AAKL,MAAK,aAAL,kBAAKC,gBAAL;AAAkB,IAAAA,wBAAA;AAAS,IAAAA,wBAAA;AAAO,IAAAA,wBAAA;AAA7B,WAAAA;AAAA,KAAA;;;AChDL,MAAM,kBAAN,MAA0C;AAAA;AAAA,IAKhD;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA,WAAW;AAAA;AAAA,IAGX,UAAU;AAAA,IAEV,YAAY;AAAA,IAEZ,OAAO;AAAA,IAEP,OAAO;AAAA,IAEP,SAAS,IAAI,MAAc;AAAA,IAAG,YAAY,IAAI,MAAc;AAAA,IAC5D,QAAQ,IAAI,MAAc;AAAA,IAAG,SAAS,IAAI,MAAc;AAAA,IAAG,UAAU,IAAI,MAAc;AAAA,IACvF,WAAW,IAAI,MAAc;AAAA,IAE7B,SAAS;AAAA,IAET,YAAa,MAA0B,UAAoB;AAC1D,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,WAAK,OAAO;AAEZ,WAAK,QAAQ,IAAI,MAAY;AAC7B,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK;AAClD,YAAI,OAAO,SAAS,SAAS,KAAK,MAAM,CAAC,EAAE,IAAI;AAC/C,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,sBAAsB,KAAK,MAAM,CAAC,EAAE,OAAO;AACtE,aAAK,MAAM,KAAK,IAAI;AAAA,MACrB;AACA,UAAI,SAAS,SAAS,SAAS,KAAK,OAAO,IAAI;AAC/C,UAAI,CAAC;AAAQ,cAAM,IAAI,MAAM,6BAA6B,KAAK,OAAO,MAAM;AAC5E,WAAK,SAAS;AAEd,WAAK,WAAW,KAAK;AACrB,WAAK,UAAU,KAAK;AACpB,WAAK,YAAY,KAAK;AACtB,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO,KAAK;AAAA,IAClB;AAAA,IAEA,WAAY;AACX,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,iBAAkB;AACjB,YAAM,OAAO,KAAK;AAClB,WAAK,WAAW,KAAK;AACrB,WAAK,UAAU,KAAK;AACpB,WAAK,YAAY,KAAK;AACtB,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO,KAAK;AAAA,IAClB;AAAA,IAEA,OAAQ,SAAkB;AACzB,UAAI,aAAa,KAAK,OAAO,cAAc;AAC3C,UAAI,EAAE,sBAAsB;AAAiB;AAE7C,UAAI,YAAY,KAAK,WAAW,OAAO,KAAK,MAAM,OAAO,KAAK;AAC9D,UAAI,aAAa,KAAK,QAAQ,KAAK,QAAQ;AAAG;AAE9C,UAAI,OAAO,KAAK;AAChB,UAAI,WAAW,KAAK,+BAAkC,QAAQ,KAAK;AAEnE,UAAI,QAAQ,KAAK;AACjB,UAAI,YAAY,MAAM,QAAQ,cAAc,WAAW,YAAY,YAAY;AAC/E,UAAI,SAAS,MAAM,aAAa,KAAK,QAAQ,WAAW,GAAG,UAAyB,QAAQ,KAAK,UAAU,MAAM,aAAa,KAAK,SAAS,SAAS,IAAI,CAAC;AAC1J,UAAI,UAAU,KAAK;AAEnB,cAAQ,KAAK,aAAa;AAAA,QACzB;AACC,cAAI,OAAO;AACV,qBAAS,IAAI,GAAG,IAAI,cAAc,GAAG,IAAI,GAAG,KAAK;AAChD,kBAAI,OAAO,MAAM,CAAC;AAClB,kBAAI,cAAc,KAAK,KAAK;AAC5B,kBAAI,IAAI,cAAc,KAAK,GAAG,IAAI,cAAc,KAAK;AACrD,sBAAQ,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC;AAAA,YACrC;AAAA,UACD;AACA,gBAAM,UAAU,QAAQ,GAAG,aAAa,OAAO;AAC/C;AAAA,QACD;AACC,cAAI,MAAM;AACV,mBAAS,IAAI,GAAG,IAAI,cAAc,GAAG,IAAI,KAAI;AAC5C,gBAAI,OAAO,MAAM,CAAC;AAClB,gBAAI,cAAc,KAAK,KAAK;AAC5B,gBAAI,cAAc,gBAAe,SAAS;AACzC,kBAAI;AAAO,wBAAQ,CAAC,IAAI;AACxB,qBAAO,EAAE,CAAC,IAAI;AAAA,YACf,OAAO;AACN,kBAAI,IAAI,cAAc,KAAK,GAAG,IAAI,cAAc,KAAK;AACrD,kBAAI,SAAS,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC;AACpC,kBAAI;AAAO,wBAAQ,CAAC,IAAI;AACxB,qBAAO,EAAE,CAAC,IAAI;AACd,qBAAO;AAAA,YACR;AAAA,UACD;AACA,cAAI,MAAM,GAAG;AACZ,kBAAM,cAAc,MAAM;AAC1B,qBAAS,IAAI,GAAG,IAAI,aAAa;AAChC,qBAAO,CAAC,KAAK;AAAA,UACf;AACA;AAAA,QACD;AACC,cAAI,gBAAgB,KAAK;AACzB,mBAAS,IAAI,GAAG,IAAI,cAAc,GAAG,IAAI,KAAI;AAC5C,gBAAI,OAAO,MAAM,CAAC;AAClB,gBAAI,cAAc,KAAK,KAAK;AAC5B,gBAAI,cAAc,gBAAe,SAAS;AACzC,kBAAI;AAAO,wBAAQ,CAAC,IAAI;AACxB,qBAAO,EAAE,CAAC,IAAI;AAAA,YACf,OAAO;AACN,kBAAI,IAAI,cAAc,KAAK,GAAG,IAAI,cAAc,KAAK;AACrD,kBAAI,SAAS,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC;AACpC,kBAAI;AAAO,wBAAQ,CAAC,IAAI;AACxB,qBAAO,EAAE,CAAC,KAAK,gBAAgB,cAAc,UAAU,WAAW,SAAS;AAAA,YAC5E;AAAA,UACD;AAAA,MACF;AAEA,UAAI,YAAY,KAAK,sBAAsC,YAAY,aAAa,QAAQ;AAC5F,UAAI,QAAQ,UAAU,CAAC,GAAG,QAAQ,UAAU,CAAC,GAAG,iBAAiB,KAAK;AACtE,UAAI,MAAM;AACV,UAAI,kBAAkB;AACrB,cAAM,KAAK;AAAA,WACP;AACJ,cAAM;AACN,YAAI,IAAI,KAAK,OAAO;AACpB,0BAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,UAAU,SAAS,CAAC,UAAU;AAAA,MAC7E;AACA,eAAS,IAAI,GAAG,IAAI,GAAG,IAAI,WAAW,KAAK,KAAK,GAAG;AAClD,YAAI,OAAO,MAAM,CAAC;AAClB,aAAK,WAAW,QAAQ,KAAK,UAAU;AACvC,aAAK,WAAW,QAAQ,KAAK,UAAU;AACvC,YAAI,IAAI,UAAU,CAAC,GAAG,IAAI,UAAU,IAAI,CAAC,GAAG,KAAK,IAAI,OAAO,KAAK,IAAI;AACrE,YAAI,OAAO;AACV,cAAI,SAAS,QAAQ,CAAC;AACtB,cAAI,UAAU,GAAG;AAChB,gBAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI,SAAS,KAAK,YAAY;AAClE,iBAAK,KAAK;AACV,iBAAK,KAAK;AAAA,UACX;AAAA,QACD;AACA,gBAAQ;AACR,gBAAQ;AACR,YAAI,YAAY,GAAG;AAClB,cAAI,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM;AAC1E,cAAI;AACH,gBAAI,UAAU,IAAI,CAAC;AAAA,mBACX,OAAO,IAAI,CAAC,KAAK;AACzB,gBAAI,UAAU,IAAI,CAAC;AAAA;AAEnB,gBAAI,KAAK,MAAM,IAAI,EAAE;AACtB,eAAK,KAAK,MAAM,GAAG,CAAC;AACpB,cAAI,KAAK;AACR,kBAAM,KAAK,IAAI,CAAC;AAChB,kBAAM,KAAK,IAAI,CAAC;AAChB,gBAAI,SAAS,KAAK,KAAK;AACvB,sBAAU,UAAU,MAAM,IAAI,MAAM,KAAK,MAAM;AAC/C,sBAAU,UAAU,MAAM,IAAI,MAAM,KAAK,MAAM;AAAA,UAChD,OAAO;AACN,iBAAK;AAAA,UACN;AACA,cAAI,IAAI,UAAU;AACjB,iBAAK,UAAU;AAAA,mBACP,IAAI,CAAC,UAAU;AACvB,iBAAK,UAAU;AAChB,eAAK;AACL,gBAAM,KAAK,IAAI,CAAC;AAChB,gBAAM,KAAK,IAAI,CAAC;AAChB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AAAA,QAC1B;AACA,aAAK,uBAAuB;AAAA,MAC7B;AAAA,IACD;AAAA,IAEA,sBAAuB,MAAsB,aAAqB,UAAmB;AACpF,UAAI,SAAS,KAAK;AAClB,UAAI,WAAW,KAAK;AACpB,UAAI,SAAS,KAAK,QAAQ,MAAM,MAAM,aAAa,KAAK,WAAW,cAAc,IAAI,CAAC,GAAG,QAAuB,KAAK;AACrH,UAAIC,UAAS,KAAK;AAClB,UAAI,iBAAiB,KAAK,qBAAqB,aAAa,iBAAiB,GAAG,YAAY,gBAAe;AAE3G,UAAI,CAAC,KAAK,eAAe;AACxB,YAAI,UAAU,KAAK;AACnB,sBAAcA,UAAS,IAAI;AAC3B,YAAIC,cAAa,QAAQ,UAAU;AACnC,YAAI,KAAK,KAAK;AAAsC,sBAAYA;AAEhE,YAAIC;AACJ,gBAAQ,KAAK,KAAK,aAAa;AAAA,UAC9B;AACC,YAAAA,cAAaD;AACb;AAAA,UACD;AACC,YAAAC,cAAaD,cAAa;AAC1B;AAAA,UACD;AACC,YAAAC,cAAa;AAAA,QACf;AACA,gBAAQ,MAAM,aAAa,KAAK,OAAO,CAAC;AACxC,iBAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,aAAa,KAAK,KAAK,GAAG;AAC/D,cAAI,QAAQ,OAAO,CAAC,IAAIA;AACxB,sBAAY;AACZ,cAAI,IAAI;AAER,cAAIF,SAAQ;AACX,iBAAKC;AACL,gBAAI,IAAI;AAAG,mBAAKA;AAChB,oBAAQ;AAAA,UACT,WAAW,IAAI,GAAG;AACjB,gBAAI,aAAa,gBAAe,QAAQ;AACvC,0BAAY,gBAAe;AAC3B,mBAAK,qBAAqB,QAAQ,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,YACpD;AACA,iBAAK,kBAAkB,GAAG,OAAO,GAAG,KAAK,CAAC;AAC1C;AAAA,UACD,WAAW,IAAIA,aAAY;AAC1B,gBAAI,aAAa,gBAAe,OAAO;AACtC,0BAAY,gBAAe;AAC3B,mBAAK,qBAAqB,QAAQ,iBAAiB,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,YACrE;AACA,iBAAK,iBAAiB,IAAIA,aAAY,OAAO,GAAG,KAAK,CAAC;AACtD;AAAA,UACD;AAGA,mBAAS,SAAS;AACjB,gBAAI,SAAS,QAAQ,KAAK;AAC1B,gBAAI,IAAI;AAAQ;AAChB,gBAAI,SAAS;AACZ,mBAAK;AAAA,iBACD;AACJ,kBAAI,OAAO,QAAQ,QAAQ,CAAC;AAC5B,mBAAK,IAAI,SAAS,SAAS;AAAA,YAC5B;AACA;AAAA,UACD;AACA,cAAI,SAAS,WAAW;AACvB,wBAAY;AACZ,gBAAID,WAAU,SAAS,YAAY;AAClC,mBAAK,qBAAqB,QAAQ,iBAAiB,GAAG,GAAG,OAAO,GAAG,CAAC;AACpE,mBAAK,qBAAqB,QAAQ,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,YACpD;AACC,mBAAK,qBAAqB,QAAQ,QAAQ,IAAI,GAAG,GAAG,OAAO,GAAG,CAAC;AAAA,UACjE;AACA,eAAK;AAAA,YAAiB;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG,MAAM,CAAC;AAAA,YAAG;AAAA,YAAK;AAAA,YAC7G,YAAa,IAAI,KAAK,SAAS;AAAA,UAAE;AAAA,QACnC;AACA,eAAO;AAAA,MACR;AAGA,UAAIA,SAAQ;AACX,0BAAkB;AAClB,gBAAQ,MAAM,aAAa,KAAK,OAAO,cAAc;AACrD,aAAK,qBAAqB,QAAQ,GAAG,iBAAiB,GAAG,OAAO,GAAG,CAAC;AACpE,aAAK,qBAAqB,QAAQ,GAAG,GAAG,OAAO,iBAAiB,GAAG,CAAC;AACpE,cAAM,iBAAiB,CAAC,IAAI,MAAM,CAAC;AACnC,cAAM,iBAAiB,CAAC,IAAI,MAAM,CAAC;AAAA,MACpC,OAAO;AACN;AACA,0BAAkB;AAClB,gBAAQ,MAAM,aAAa,KAAK,OAAO,cAAc;AACrD,aAAK,qBAAqB,QAAQ,GAAG,gBAAgB,OAAO,GAAG,CAAC;AAAA,MACjE;AAGA,UAAI,SAAS,MAAM,aAAa,KAAK,QAAQ,UAAU;AACvD,UAAI,aAAa;AACjB,UAAI,KAAK,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK;AACnF,UAAI,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM;AACjF,eAAS,IAAI,GAAG,IAAI,GAAG,IAAI,YAAY,KAAK,KAAK,GAAG;AACnD,cAAM,MAAM,CAAC;AACb,cAAM,MAAM,IAAI,CAAC;AACjB,cAAM,MAAM,IAAI,CAAC;AACjB,cAAM,MAAM,IAAI,CAAC;AACjB,aAAK,MAAM,IAAI,CAAC;AAChB,aAAK,MAAM,IAAI,CAAC;AAChB,gBAAQ,KAAK,MAAM,IAAI,OAAO;AAC9B,gBAAQ,KAAK,MAAM,IAAI,OAAO;AAC9B,kBAAU,MAAM,OAAO,IAAI,KAAK,MAAM;AACtC,kBAAU,MAAM,OAAO,IAAI,KAAK,MAAM;AACtC,eAAO,OAAO,IAAI;AAClB,eAAO,OAAO,IAAI;AAClB,eAAO,MAAM,MAAM,OAAO,OAAO,QAAQ;AACzC,eAAO,MAAM,MAAM,OAAO,OAAO,QAAQ;AACzC,sBAAc,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC7C,eAAO;AACP,eAAO;AACP,gBAAQ;AACR,gBAAQ;AACR,sBAAc,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC7C,eAAO;AACP,eAAO;AACP,sBAAc,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC7C,eAAO,OAAO;AACd,eAAO,OAAO;AACd,sBAAc,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC7C,eAAO,CAAC,IAAI;AACZ,aAAK;AACL,aAAK;AAAA,MACN;AAEA,UAAI,KAAK,KAAK;AAAsC,oBAAY;AAEhE,UAAI;AACJ,cAAQ,KAAK,KAAK,aAAa;AAAA,QAC9B;AACC,uBAAa;AACb;AAAA,QACD;AACC,uBAAa,aAAa;AAC1B;AAAA,QACD;AACC,uBAAa;AAAA,MACf;AAEA,UAAI,WAAW,KAAK;AACpB,UAAI,cAAc;AAClB,eAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,aAAa,KAAK,KAAK,GAAG;AAC5E,YAAI,QAAQ,OAAO,CAAC,IAAI;AACxB,oBAAY;AACZ,YAAI,IAAI;AAER,YAAIA,SAAQ;AACX,eAAK;AACL,cAAI,IAAI;AAAG,iBAAK;AAChB,kBAAQ;AAAA,QACT,WAAW,IAAI,GAAG;AACjB,eAAK,kBAAkB,GAAG,OAAO,GAAG,KAAK,CAAC;AAC1C;AAAA,QACD,WAAW,IAAI,YAAY;AAC1B,eAAK,iBAAiB,IAAI,YAAY,OAAO,iBAAiB,GAAG,KAAK,CAAC;AACvE;AAAA,QACD;AAGA,iBAAS,SAAS;AACjB,cAAI,SAAS,OAAO,KAAK;AACzB,cAAI,IAAI;AAAQ;AAChB,cAAI,SAAS;AACZ,iBAAK;AAAA,eACD;AACJ,gBAAI,OAAO,OAAO,QAAQ,CAAC;AAC3B,iBAAK,IAAI,SAAS,SAAS;AAAA,UAC5B;AACA;AAAA,QACD;AAGA,YAAI,SAAS,WAAW;AACvB,sBAAY;AACZ,cAAI,KAAK,QAAQ;AACjB,eAAK,MAAM,EAAE;AACb,eAAK,MAAM,KAAK,CAAC;AACjB,gBAAM,MAAM,KAAK,CAAC;AAClB,gBAAM,MAAM,KAAK,CAAC;AAClB,gBAAM,MAAM,KAAK,CAAC;AAClB,gBAAM,MAAM,KAAK,CAAC;AAClB,eAAK,MAAM,KAAK,CAAC;AACjB,eAAK,MAAM,KAAK,CAAC;AACjB,kBAAQ,KAAK,MAAM,IAAI,OAAO;AAC9B,kBAAQ,KAAK,MAAM,IAAI,OAAO;AAC9B,oBAAU,MAAM,OAAO,IAAI,KAAK,MAAM;AACtC,oBAAU,MAAM,OAAO,IAAI,KAAK,MAAM;AACtC,iBAAO,OAAO,IAAI;AAClB,iBAAO,OAAO,IAAI;AAClB,iBAAO,MAAM,MAAM,MAAM,OAAO,QAAQ;AACxC,iBAAO,MAAM,MAAM,MAAM,OAAO,QAAQ;AACxC,wBAAc,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC7C,mBAAS,CAAC,IAAI;AACd,eAAK,KAAK,GAAG,KAAK,GAAG,MAAM;AAC1B,mBAAO;AACP,mBAAO;AACP,oBAAQ;AACR,oBAAQ;AACR,2BAAe,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC9C,qBAAS,EAAE,IAAI;AAAA,UAChB;AACA,iBAAO;AACP,iBAAO;AACP,yBAAe,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC9C,mBAAS,CAAC,IAAI;AACd,iBAAO,OAAO;AACd,iBAAO,OAAO;AACd,yBAAe,KAAK,KAAK,MAAM,MAAM,MAAM,GAAG;AAC9C,mBAAS,CAAC,IAAI;AACd,oBAAU;AAAA,QACX;AAGA,aAAK;AACL,iBAAS,WAAW;AACnB,cAAI,SAAS,SAAS,OAAO;AAC7B,cAAI,IAAI;AAAQ;AAChB,cAAI,WAAW;AACd,iBAAK;AAAA,eACD;AACJ,gBAAI,OAAO,SAAS,UAAU,CAAC;AAC/B,gBAAI,WAAW,IAAI,SAAS,SAAS;AAAA,UACtC;AACA;AAAA,QACD;AACA,aAAK,iBAAiB,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,KAAK,GAAG,YAAa,IAAI,KAAK,SAAS,CAAE;AAAA,MAC7G;AACA,aAAO;AAAA,IACR;AAAA,IAEA,kBAAmB,GAAW,MAAqB,GAAW,KAAoB,GAAW;AAC5F,UAAI,KAAK,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,EAAE;AACvG,UAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;AAC5B,UAAI,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;AAChC,UAAI,IAAI,CAAC,IAAI;AAAA,IACd;AAAA,IAEA,iBAAkB,GAAW,MAAqB,GAAW,KAAoB,GAAW;AAC3F,UAAI,KAAK,KAAK,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,GAAG,KAAK,KAAK,KAAK,CAAC,GAAG,KAAK,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,KAAK,MAAM,IAAI,EAAE;AACvG,UAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;AAC5B,UAAI,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;AAChC,UAAI,IAAI,CAAC,IAAI;AAAA,IACd;AAAA,IAEA,iBAAkB,GAAW,IAAY,IAAY,KAAa,KAAa,KAAa,KAAa,IAAY,IACpH,KAAoB,GAAW,UAAmB;AAClD,UAAI,KAAK,KAAK,MAAM,CAAC,GAAG;AACvB,YAAI,CAAC,IAAI;AACT,YAAI,IAAI,CAAC,IAAI;AACb,YAAI,IAAI,CAAC,IAAI,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE;AAC1C;AAAA,MACD;AACA,UAAI,KAAK,IAAI,GAAG,MAAM,KAAK,GAAG,IAAI,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,KAAK;AAChE,UAAI,KAAK,IAAI,GAAG,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,OAAO,MAAM;AAC3D,UAAI,IAAI,KAAK,MAAM,MAAM,OAAO,MAAM,OAAO,KAAK,KAAK,IAAI,KAAK,MAAM,MAAM,OAAO,MAAM,OAAO,KAAK;AACrG,UAAI,CAAC,IAAI;AACT,UAAI,IAAI,CAAC,IAAI;AACb,UAAI,UAAU;AACb,YAAI,IAAI;AACP,cAAI,IAAI,CAAC,IAAI,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE;AAAA;AAE1C,cAAI,IAAI,CAAC,IAAI,KAAK,MAAM,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,MAAM,GAAG;AAAA,MAC1G;AAAA,IACD;AAAA,EACD;AA1cO,MAAM,iBAAN;AACN,gBADY,gBACL,QAAO;AAAI,gBADN,gBACa,UAAS;AAAI,gBAD1B,gBACiC,SAAQ;AACrD,gBAFY,gBAEL,WAAU;;;ACLX,MAAM,oBAAN,MAA6C;AAAA,IAC1C;AAAA,IACD,QAAqB;AAAA;AAAA,IAE7B,IAAW,KAAM,MAAY;AAAE,WAAK,QAAQ;AAAA,IAAM;AAAA,IAClD,IAAW,OAAQ;AAClB,UAAI,CAAC,KAAK;AAAO,cAAM,IAAI,MAAM,eAAe;AAAA;AAC3C,eAAO,KAAK;AAAA,IAClB;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IAEN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,gBAAgB;AAAA,IAEhB,SAAS;AAAA,IAEA;AAAA,IACT,YAAY;AAAA,IACZ,WAAW;AAAA,IAEX,YAAa,MAA6B,UAAoB;AAC7D,WAAK,OAAO;AACZ,WAAK,WAAW;AAEhB,WAAK,OAAO,SAAS,MAAM,KAAK,KAAK,KAAK;AAE1C,WAAK,UAAU,KAAK;AACpB,WAAK,WAAW,KAAK;AACrB,WAAK,UAAU,KAAK;AACpB,WAAK,cAAc,KAAK;AACxB,WAAK,OAAO,KAAK;AACjB,WAAK,UAAU,KAAK;AACpB,WAAK,MAAM,KAAK;AAAA,IACjB;AAAA,IAEA,QAAS;AACR,WAAK,YAAY;AACjB,WAAK,WAAW,KAAK,SAAS;AAC9B,WAAK,SAAS;AACd,WAAK,UAAU;AACf,WAAK,YAAY;AACjB,WAAK,UAAU;AACf,WAAK,YAAY;AACjB,WAAK,eAAe;AACpB,WAAK,iBAAiB;AACtB,WAAK,cAAc;AACnB,WAAK,gBAAgB;AAAA,IACtB;AAAA,IAEA,iBAAkB;AACjB,YAAM,OAAO,KAAK;AAClB,WAAK,UAAU,KAAK;AACpB,WAAK,WAAW,KAAK;AACrB,WAAK,UAAU,KAAK;AACpB,WAAK,cAAc,KAAK;AACxB,WAAK,OAAO,KAAK;AACjB,WAAK,UAAU,KAAK;AACpB,WAAK,MAAM,KAAK;AAAA,IACjB;AAAA,IAEA,WAAY;AACX,aAAO,KAAK;AAAA,IACb;AAAA;AAAA,IAGA,OAAQ,SAAkB;AACzB,YAAM,MAAM,KAAK;AACjB,UAAI,OAAO;AAAG;AAEd,YAAM,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,KAAK,KAAK,IAAI,GAAG,iBAAiB,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,GAAG,SAAS,KAAK,KAAK,SAAS;AAC3I,YAAM,OAAO,KAAK;AAClB,YAAM,IAAI,KAAK,KAAK;AAEpB,cAAQ,SAAS;AAAA,QAChB;AACC;AAAA,QACD;AACC,eAAK,MAAM;AAAA,QAEZ;AACC,gBAAM,WAAW,KAAK;AACtB,gBAAM,QAAQ,KAAK,IAAI,KAAK,SAAS,OAAO,KAAK,UAAU,CAAC;AAC5D,eAAK,aAAa;AAClB,eAAK,WAAW,SAAS;AAEzB,gBAAM,KAAK,KAAK,QAAQ,KAAK,KAAK;AAClC,cAAI,KAAK,QAAQ;AAChB,iBAAK,SAAS;AACd,iBAAK,KAAK;AACV,iBAAK,KAAK;AAAA,UACX,OAAO;AACN,gBAAI,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,SAAS,KAAK,gBAAgB,IAAI;AACzG,gBAAI,KAAK,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,KAAK,IAAI,SAAS,MAAM;AACpE,kBAAM,KAAK,IAAI,SAAS,MAAM;AAC9B,gBAAI,KAAK,GAAG;AACX,kBAAI,GAAG;AACN,sBAAM,KAAK,KAAK,KAAK,MAAM;AAC3B,qBAAK,WAAW,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK;AAC9C,qBAAK,KAAK;AAAA,cACX;AACA,kBAAI,GAAG;AACN,sBAAM,KAAK,KAAK,KAAK,MAAM;AAC3B,qBAAK,WAAW,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK;AAC9C,qBAAK,KAAK;AAAA,cACX;AACA,kBAAI,KAAK,GAAG;AACX,oBAAI,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC;AACjC,sBAAM,IAAI,KAAK,cAAc,GAAG,IAAI,KAAK,UAAU,IAAI,KAAK,OAAO,IAAI,SAAS,QAAQ,IAAI,KAAK,UAAU,IAAI,SAAS;AACxH,mBAAG;AACF,sBAAI,GAAG;AACN,yBAAK,cAAc,IAAI,KAAK,UAAU,KAAK;AAC3C,yBAAK,WAAW,KAAK,YAAY;AACjC,yBAAK,aAAa;AAAA,kBACnB;AACA,sBAAI,GAAG;AACN,yBAAK,cAAc,IAAI,KAAK,UAAU,KAAK;AAC3C,yBAAK,WAAW,KAAK,YAAY;AACjC,yBAAK,aAAa;AAAA,kBACnB;AACA,uBAAK;AAAA,gBACN,SAAS,KAAK;AAAA,cACf;AACA,kBAAI;AAAG,qBAAK,UAAU,KAAK,UAAU,MAAM,KAAK,KAAK;AACrD,kBAAI;AAAG,qBAAK,UAAU,KAAK,UAAU,MAAM,KAAK,KAAK;AAAA,YACtD;AACA,gBAAI,kBAAkB,QAAQ;AAC7B,kBAAI,KAAK,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK;AACxD,kBAAI,KAAK,KAAK,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK;AACpD,kBAAI,KAAK;AACR,qBAAK;AAAA,uBACG,KAAK,CAAC;AACd,qBAAK,CAAC;AACP,kBAAI,KAAK;AACR,qBAAK;AAAA,uBACG,KAAK,CAAC;AACd,qBAAK,CAAC;AACP,kBAAI,gBAAgB;AACnB,sBAAM,KAAK,KAAK,SAAS,KAAK,KAAK,UAAU;AAC7C,oBAAI,IAAI,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,eAAe;AAC1E,qBAAK,iBAAiB,IAAI,KAAK,KAAK,IAAI,UAAU,SAAS,GAAG,IAAI,UAAU,OAAO;AACnF,oBAAI,KAAK,eAAe,KAAK;AAC7B,oBAAI,KAAK,IAAI,CAAC;AACd,oBAAI,KAAK,IAAI,CAAC;AACd,oBAAI,QAAQ;AACX,sBAAI,IAAI,KAAK,eAAe;AAC5B,sBAAI,IAAI;AAAG,yBAAK,gBAAgB,KAAK,IAAI,KAAK,KAAK,IAAI;AAAA,gBACxD;AAAA,cACD,OAAO;AACN,oBAAI,KAAK,IAAI,EAAE;AACf,oBAAI,KAAK,IAAI,EAAE;AACf,sBAAM,IAAI,IAAI,KAAK,eAAe;AAClC,oBAAI,IAAI;AAAG,uBAAK,gBAAgB,KAAK,IAAI,KAAK,KAAK,IAAI;AAAA,cACxD;AACA,kBAAI,KAAK;AACT,kBAAI,KAAK,GAAG;AACX,oBAAI,KAAK;AAAI,sBAAI,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC;AAC9C,sBAAM,IAAI,KAAK,cAAc,GAAG,IAAI,KAAK,UAAU,IAAI,KAAK,MAAM,IAAK,SAAS,QAAQ,CAAC,KAAK,UAAU,KAAK,SAAU,IAAI,IAAI;AAC/H,uBAAO,MAAM;AACZ,uBAAK;AACL,sBAAI,QAAQ;AACX,yBAAK,kBAAkB,IAAI,IAAI,IAAI,IAAI,KAAK,cAAc,KAAK;AAC/D,yBAAK,eAAe,KAAK,gBAAgB;AACzC,yBAAK,iBAAiB;AAAA,kBACvB;AACA,sBAAI,gBAAgB;AACnB,yBAAK,oBAAoB,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,eAAe,KAAK;AACvE,yBAAK,gBAAgB,KAAK,iBAAiB;AAC3C,yBAAK,kBAAkB;AACvB,wBAAI,IAAI;AAAG;AACX,0BAAM,IAAI,KAAK,eAAe,KAAK;AACnC,wBAAI,KAAK,IAAI,CAAC;AACd,wBAAI,KAAK,IAAI,CAAC;AAAA,kBACf,WAAW,IAAI;AACd;AAAA,gBACF;AAAA,cACD;AAAA,YACD;AACA,iBAAK,YAAY;AAAA,UAClB;AACA,eAAK,KAAK,KAAK;AACf,eAAK,KAAK,KAAK;AACf;AAAA,QACD;AACC,cAAI;AAAG,iBAAK,UAAU,KAAK,UAAU,MAAM,KAAK,KAAK;AACrD,cAAI;AAAG,iBAAK,UAAU,KAAK,UAAU,MAAM,KAAK,KAAK;AAAA,MACvD;AAEA,UAAI,gBAAgB;AACnB,YAAI,IAAI,KAAK,eAAe,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;AACnD,YAAI,KAAK,KAAK,SAAS,GAAG;AACzB,cAAI,IAAI;AACR,cAAI,KAAK,KAAK,SAAS,GAAG;AACzB,gBAAI,IAAI,KAAK,KAAK;AAClB,gBAAI,KAAK,IAAI,CAAC;AACd,gBAAI,KAAK,IAAI,CAAC;AACd,gBAAI,KAAK;AACT,iBAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAC1B,iBAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAAA,UAC3B;AACA,eAAK,IAAI,KAAK,KAAK;AACnB,cAAI,KAAK,IAAI,CAAC;AACd,cAAI,KAAK,IAAI,CAAC;AACd,cAAI,KAAK;AACT,eAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAC1B,eAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAAA,QAC3B,OAAO;AACN,eAAK,KAAK,KAAK;AACf,cAAI,KAAK,IAAI,CAAC;AACd,cAAI,KAAK,IAAI,CAAC;AACd,cAAI,KAAK;AACT,eAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAC1B,eAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAC1B,cAAI,KAAK;AACT,eAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAC1B,eAAK,IAAI,IAAI,IAAI,IAAI,KAAK;AAAA,QAC3B;AAAA,MACD;AACA,UAAI,QAAQ;AACX,cAAM,IAAI,IAAI,KAAK,cAAc,MAAM,KAAK,KAAK;AACjD,aAAK,KAAK;AACV,aAAK,KAAK;AAAA,MACX;AACA,UAAI,yBAAyB;AAC5B,aAAK,KAAK,IAAI,KAAK;AACnB,aAAK,KAAK,IAAI,KAAK;AAAA,MACpB;AACA,WAAK,uBAAuB;AAAA,IAC7B;AAAA;AAAA;AAAA,IAIA,UAAW,GAAW,GAAW;AAChC,WAAK,MAAM;AACX,WAAK,MAAM;AACX,WAAK,MAAM;AACX,WAAK,MAAM;AAAA,IACZ;AAAA;AAAA;AAAA,IAIA,OAAQ,GAAW,GAAW,SAAiB;AAC9C,YAAM,IAAI,UAAU,UAAU,QAAQ,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;AACzE,YAAM,KAAK,KAAK,KAAK,GAAG,KAAK,KAAK,KAAK;AACvC,WAAK,UAAU,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,MAAM,EAAE;AAAA,IAClE;AAAA,EACD;;;ACzQO,MAAM,OAAN,MAAW;AAAA;AAAA,IAEjB;AAAA;AAAA,IAGA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA,IAIA,YAA0B;AAAA,IAE1B,aAAgC;AAAA,IAEhC,kBAA0B;AAAA;AAAA;AAAA,IAI1B,gBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMxB,SAAS,IAAI,MAAc;AAAA,IAE3B,YAAa,MAAgB,MAAY;AACxC,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,QAAQ,IAAI,MAAM;AACvB,WAAK,YAAY,CAAC,KAAK,YAAY,OAAO,IAAI,MAAM;AACpD,WAAK,eAAe;AAAA,IACrB;AAAA;AAAA,IAGA,cAAyB;AACxB,aAAO,KAAK,KAAK;AAAA,IAClB;AAAA;AAAA,IAGA,gBAAoC;AACnC,aAAO,KAAK;AAAA,IACb;AAAA;AAAA;AAAA;AAAA,IAKA,cAAe,YAA+B;AAC7C,UAAI,KAAK,cAAc;AAAY;AACnC,UAAI,EAAE,sBAAsB,qBAAqB,EAAE,KAAK,sBAAsB,qBACvD,WAAY,sBAAyC,KAAK,WAAY,oBAAoB;AAChH,aAAK,OAAO,SAAS;AAAA,MACtB;AACA,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACtB;AAAA;AAAA,IAGA,iBAAkB;AACjB,WAAK,MAAM,aAAa,KAAK,KAAK,KAAK;AACvC,UAAI,KAAK;AAAW,aAAK,UAAU,aAAa,KAAK,KAAK,SAAU;AACpE,UAAI,CAAC,KAAK,KAAK;AACd,aAAK,aAAa;AAAA,WACd;AACJ,aAAK,aAAa;AAClB,aAAK,cAAc,KAAK,KAAK,SAAS,cAAc,KAAK,KAAK,OAAO,KAAK,KAAK,cAAc,CAAC;AAAA,MAC/F;AAAA,IACD;AAAA,EACD;;;ACvEO,MAAM,sBAAN,MAA+C;AAAA;AAAA,IAGrD;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA,IAEA,YAAY;AAAA,IAAG,OAAO;AAAA,IAAG,OAAO;AAAA,IAAG,YAAY;AAAA,IAAG,YAAY;AAAA,IAAG,YAAY;AAAA,IAE7E,OAAO,IAAI,QAAQ;AAAA,IACnB,SAAS;AAAA,IAET,YAAa,MAA+B,UAAoB;AAC/D,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,WAAK,OAAO;AAEZ,WAAK,QAAQ,IAAI,MAAY;AAC7B,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,YAAI,OAAO,SAAS,SAAS,KAAK,MAAM,CAAC,EAAE,IAAI;AAC/C,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,sBAAsB,KAAK,MAAM,CAAC,EAAE,OAAO;AACtE,aAAK,MAAM,KAAK,IAAI;AAAA,MACrB;AACA,UAAI,SAAS,SAAS,SAAS,KAAK,OAAO,IAAI;AAC/C,UAAI,CAAC;AAAQ,cAAM,IAAI,MAAM,6BAA6B,KAAK,OAAO,OAAO;AAC7E,WAAK,SAAS;AAEd,WAAK,YAAY,KAAK;AACtB,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO,KAAK;AACjB,WAAK,YAAY,KAAK;AACtB,WAAK,YAAY,KAAK;AACtB,WAAK,YAAY,KAAK;AAAA,IACvB;AAAA,IAEA,WAAY;AACX,aAAO,KAAK;AAAA,IACb;AAAA,IAEA,iBAAkB;AACjB,YAAM,OAAO,KAAK;AAClB,WAAK,YAAY,KAAK;AACtB,WAAK,OAAO,KAAK;AACjB,WAAK,OAAO,KAAK;AACjB,WAAK,YAAY,KAAK;AACtB,WAAK,YAAY,KAAK;AACtB,WAAK,YAAY,KAAK;AAAA,IACvB;AAAA,IAEA,OAAQ,SAAkB;AACzB,UAAI,KAAK,aAAa,KAAK,KAAK,QAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK,aAAa,KAAK,KAAK,aAAa,KAAK,KAAK,aAAa;AAAG;AAElI,UAAI,KAAK,KAAK,OAAO;AACpB,YAAI,KAAK,KAAK;AACb,eAAK,mBAAmB;AAAA;AAExB,eAAK,mBAAmB;AAAA,MAC1B,OAAO;AACN,YAAI,KAAK,KAAK;AACb,eAAK,mBAAmB;AAAA;AAExB,eAAK,mBAAmB;AAAA,MAC1B;AAAA,IACD;AAAA,IAEA,qBAAsB;AACrB,UAAI,YAAY,KAAK,WAAW,OAAO,KAAK,MAAM,OAAO,KAAK,MAAM,YAAY,KAAK,WACpF,YAAY,KAAK,WAAW,YAAY,KAAK;AAC9C,UAAI,YAAY,QAAQ,KAAK,QAAQ;AAErC,UAAI,SAAS,KAAK;AAClB,UAAI,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO;AAC7D,UAAI,gBAAgB,KAAK,KAAK,KAAK,KAAK,IAAI,UAAU,SAAS,CAAC,UAAU;AAC1E,UAAI,iBAAiB,KAAK,KAAK,iBAAiB;AAChD,UAAI,eAAe,KAAK,KAAK,eAAe;AAE5C,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAElB,YAAI,aAAa,GAAG;AACnB,cAAI,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK;AACjD,cAAI,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI,KAAK,MAAM,GAAG,CAAC,IAAI;AAChD,cAAI,IAAI,UAAU;AACjB,iBAAK,UAAU;AAAA,mBACP,IAAI,CAAC,UAAU;AACvB,iBAAK,UAAU;AAChB,eAAK;AACL,cAAI,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;AACvC,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AAAA,QAC1B;AAEA,YAAI,WAAW;AACd,cAAI,OAAO,KAAK;AAChB,iBAAO,aAAa,KAAK,IAAI,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO,CAAC;AAClE,eAAK,WAAW,KAAK,IAAI,KAAK,UAAU;AACxC,eAAK,WAAW,KAAK,IAAI,KAAK,UAAU;AAAA,QACzC;AAEA,YAAI,aAAa,GAAG;AACnB,cAAI,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AACnD,cAAI,KAAK;AAAG,iBAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI,IAAI,KAAK,KAAK,gBAAgB,aAAa;AAChG,eAAK,KAAK;AACV,eAAK,KAAK;AAAA,QACX;AACA,YAAI,aAAa,GAAG;AACnB,cAAI,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AACnD,cAAI,KAAK;AAAG,iBAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI,IAAI,KAAK,KAAK,gBAAgB,aAAa;AAChG,eAAK,KAAK;AACV,eAAK,KAAK;AAAA,QACX;AAEA,YAAI,YAAY,GAAG;AAClB,cAAI,IAAI,KAAK,GAAG,IAAI,KAAK;AACzB,cAAI,KAAK,KAAK,MAAM,GAAG,CAAC;AACxB,cAAI,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC;AACjF,cAAI,IAAI,UAAU;AACjB,iBAAK,UAAU;AAAA,mBACP,IAAI,CAAC,UAAU;AACvB,iBAAK,UAAU;AAChB,cAAI,MAAM,IAAI,gBAAgB;AAC9B,cAAI,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC;AAC/B,eAAK,IAAI,KAAK,IAAI,CAAC,IAAI;AACvB,eAAK,IAAI,KAAK,IAAI,CAAC,IAAI;AAAA,QACxB;AAEA,aAAK,uBAAuB;AAAA,MAC7B;AAAA,IACD;AAAA,IAEA,qBAAsB;AACrB,UAAI,YAAY,KAAK,WAAW,OAAO,KAAK,MAAM,OAAO,KAAK,MAAM,YAAY,KAAK,WACpF,YAAY,KAAK,WAAW,YAAY,KAAK;AAC9C,UAAI,YAAY,QAAQ,KAAK,QAAQ;AAErC,UAAI,SAAS,KAAK;AAClB,UAAI,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO;AAC7D,UAAI,gBAAgB,KAAK,KAAK,KAAK,KAAK,IAAI,UAAU,SAAS,CAAC,UAAU;AAC1E,UAAI,iBAAiB,KAAK,KAAK,iBAAiB,eAAe,eAAe,KAAK,KAAK,eAAe;AAEvG,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAElB,YAAI,aAAa,GAAG;AACnB,cAAI,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,KAAK;AACjD,cAAI,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI;AAC7B,cAAI,IAAI,UAAU;AACjB,iBAAK,UAAU;AAAA,mBACP,IAAI,CAAC,UAAU;AACvB,iBAAK,UAAU;AAChB,eAAK;AACL,cAAI,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;AACvC,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AACzB,eAAK,IAAI,MAAM,IAAI,MAAM;AAAA,QAC1B;AAEA,YAAI,WAAW;AACd,cAAI,OAAO,KAAK;AAChB,iBAAO,aAAa,KAAK,IAAI,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO,CAAC;AAClE,eAAK,UAAU,KAAK,IAAI;AACxB,eAAK,UAAU,KAAK,IAAI;AAAA,QACzB;AAEA,YAAI,aAAa,GAAG;AACnB,cAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI,IAAI,KAAK,KAAK,gBAAgB,YAAY;AAClF,eAAK,KAAK;AACV,eAAK,KAAK;AAAA,QACX;AACA,YAAI,aAAa,GAAG;AACnB,cAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI,IAAI,KAAK,KAAK,gBAAgB,YAAY;AAClF,eAAK,KAAK;AACV,eAAK,KAAK;AAAA,QACX;AAEA,YAAI,YAAY,GAAG;AAClB,cAAI,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,EAAE;AAC9C,cAAI,IAAI,UAAU;AACjB,iBAAK,UAAU;AAAA,mBACP,IAAI,CAAC,UAAU;AACvB,iBAAK,UAAU;AAChB,cAAI,IAAI,KAAK,GAAG,IAAI,KAAK;AACzB,cAAI,KAAK,MAAM,GAAG,CAAC,KAAK,IAAI,UAAU,KAAK,IAAI,gBAAgB;AAC/D,cAAI,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC;AAC/B,eAAK,IAAI,KAAK,IAAI,CAAC,IAAI;AACvB,eAAK,IAAI,KAAK,IAAI,CAAC,IAAI;AAAA,QACxB;AAEA,aAAK,uBAAuB;AAAA,MAC7B;AAAA,IACD;AAAA,IAEA,qBAAsB;AACrB,UAAI,YAAY,KAAK,WAAW,OAAO,KAAK,MAAM,OAAO,KAAK,MAAM,YAAY,KAAK,WACpF,YAAY,KAAK,WAAW,YAAY,KAAK;AAE9C,UAAI,SAAS,KAAK;AAElB,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAElB,YAAI,WAAW,KAAK;AACpB,YAAI,aAAa;AAAG,uBAAa,OAAO,YAAY,WAAW,KAAK,KAAK,kBAAkB;AAE3F,YAAI,IAAI,KAAK,IAAI,IAAI,KAAK;AAC1B,cAAM,OAAO,KAAK,IAAI,KAAK,KAAK,WAAW;AAC3C,cAAM,OAAO,KAAK,IAAI,KAAK,KAAK,WAAW;AAE3C,YAAI,SAAS,KAAK,SAAS,SAAS,KAAK;AACzC,YAAI,aAAa,KAAK,UAAU;AAC/B,oBAAU,UAAU,OAAO,UAAU,SAAS,KAAK,KAAK,gBAAgB,aAAa;AACtF,YAAI,aAAa,KAAK,UAAU;AAC/B,oBAAU,UAAU,OAAO,UAAU,SAAS,KAAK,KAAK,gBAAgB,aAAa;AAEtF,YAAI,SAAS,KAAK;AAClB,YAAI,aAAa;AAAG,qBAAW,OAAO,UAAU,SAAS,KAAK,KAAK,gBAAgB;AAEnF,aAAK,yBAAyB,GAAG,GAAG,UAAU,QAAQ,QAAQ,KAAK,SAAS,MAAM;AAAA,MACnF;AAAA,IACD;AAAA,IAEA,qBAAsB;AACrB,UAAI,YAAY,KAAK,WAAW,OAAO,KAAK,MAAM,OAAO,KAAK,MAAM,YAAY,KAAK,WACpF,YAAY,KAAK,WAAW,YAAY,KAAK;AAE9C,UAAI,SAAS,KAAK;AAElB,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAElB,YAAI,WAAW,KAAK,aAAa,OAAO,YAAY,KAAK,KAAK,kBAAkB;AAChF,YAAI,IAAI,KAAK,MAAM,OAAO,KAAK,KAAK,KAAK,WAAW;AACpD,YAAI,IAAI,KAAK,MAAM,OAAO,KAAK,KAAK,KAAK,WAAW;AACpD,YAAI,SAAS,KAAK,YAAa,OAAO,UAAU,IAAI,KAAK,KAAK,gBAAgB,YAAa;AAC3F,YAAI,SAAS,KAAK,YAAa,OAAO,UAAU,IAAI,KAAK,KAAK,gBAAgB,YAAa;AAC3F,YAAI,SAAS,KAAK,WAAW,OAAO,UAAU,KAAK,KAAK,gBAAgB;AAExE,aAAK,yBAAyB,GAAG,GAAG,UAAU,QAAQ,QAAQ,KAAK,SAAS,MAAM;AAAA,MACnF;AAAA,IACD;AAAA,EACD;;;AClPO,MAAM,YAAN,MAAe;AAAA;AAAA,IAKrB;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAGA;AAAA;AAAA,IAIA;AAAA;AAAA,IAGA,eAAe,IAAI,MAAiB;AAAA;AAAA,IAGpC,OAAoB;AAAA;AAAA,IAGpB;AAAA;AAAA;AAAA,IAIA,SAAS;AAAA;AAAA;AAAA,IAID,UAAU;AAAA,IAElB,IAAW,SAAU;AACpB,aAAO,UAAS,QAAQ,CAAC,KAAK,UAAU,KAAK;AAAA,IAC9C;AAAA,IAEA,IAAW,OAAQ,QAAgB;AAClC,WAAK,UAAU;AAAA,IAChB;AAAA;AAAA,IAGA,IAAI;AAAA;AAAA,IAGJ,IAAI;AAAA;AAAA;AAAA;AAAA,IAKJ,OAAO;AAAA,IAEP,YAAa,MAAoB;AAChC,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,OAAO;AAEZ,WAAK,QAAQ,IAAI,MAAY;AAC7B,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,YAAI,WAAW,KAAK,MAAM,CAAC;AAC3B,YAAI;AACJ,YAAI,CAAC,SAAS;AACb,iBAAO,IAAI,KAAK,UAAU,MAAM,IAAI;AAAA,aAChC;AACJ,cAAI,SAAS,KAAK,MAAM,SAAS,OAAO,KAAK;AAC7C,iBAAO,IAAI,KAAK,UAAU,MAAM,MAAM;AACtC,iBAAO,SAAS,KAAK,IAAI;AAAA,QAC1B;AACA,aAAK,MAAM,KAAK,IAAI;AAAA,MACrB;AAEA,WAAK,QAAQ,IAAI,MAAY;AAC7B,WAAK,YAAY,IAAI,MAAY;AACjC,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,YAAI,WAAW,KAAK,MAAM,CAAC;AAC3B,YAAI,OAAO,KAAK,MAAM,SAAS,SAAS,KAAK;AAC7C,YAAI,OAAO,IAAI,KAAK,UAAU,IAAI;AAClC,aAAK,MAAM,KAAK,IAAI;AACpB,aAAK,UAAU,KAAK,IAAI;AAAA,MACzB;AAEA,WAAK,gBAAgB,IAAI,MAAoB;AAC7C,eAAS,IAAI,GAAG,IAAI,KAAK,cAAc,QAAQ,KAAK;AACnD,YAAI,mBAAmB,KAAK,cAAc,CAAC;AAC3C,aAAK,cAAc,KAAK,IAAI,aAAa,kBAAkB,IAAI,CAAC;AAAA,MACjE;AAEA,WAAK,uBAAuB,IAAI,MAA2B;AAC3D,eAAS,IAAI,GAAG,IAAI,KAAK,qBAAqB,QAAQ,KAAK;AAC1D,YAAI,0BAA0B,KAAK,qBAAqB,CAAC;AACzD,aAAK,qBAAqB,KAAK,IAAI,oBAAoB,yBAAyB,IAAI,CAAC;AAAA,MACtF;AAEA,WAAK,kBAAkB,IAAI,MAAsB;AACjD,eAAS,IAAI,GAAG,IAAI,KAAK,gBAAgB,QAAQ,KAAK;AACrD,YAAI,qBAAqB,KAAK,gBAAgB,CAAC;AAC/C,aAAK,gBAAgB,KAAK,IAAI,eAAe,oBAAoB,IAAI,CAAC;AAAA,MACvE;AAEA,WAAK,qBAAqB,IAAI,MAAyB;AACvD,eAAS,IAAI,GAAG,IAAI,KAAK,mBAAmB,QAAQ,KAAK;AACxD,YAAI,wBAAwB,KAAK,mBAAmB,CAAC;AACrD,aAAK,mBAAmB,KAAK,IAAI,kBAAkB,uBAAuB,IAAI,CAAC;AAAA,MAChF;AAEA,WAAK,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AACjC,WAAK,YAAY;AAAA,IAClB;AAAA;AAAA;AAAA,IAIA,cAAe;AACd,UAAI,cAAc,KAAK;AACvB,kBAAY,SAAS;AAErB,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,aAAK,SAAS,KAAK,KAAK;AACxB,aAAK,SAAS,CAAC,KAAK;AAAA,MACrB;AAEA,UAAI,KAAK,MAAM;AACd,YAAI,YAAY,KAAK,KAAK;AAC1B,iBAAS,IAAI,GAAG,IAAI,KAAK,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK;AACvD,cAAI,OAAoB,KAAK,MAAM,UAAU,CAAC,EAAE,KAAK;AACrD,aAAG;AACF,iBAAK,SAAS;AACd,iBAAK,SAAS;AACd,mBAAO,KAAK;AAAA,UACb,SAAS;AAAA,QACV;AAAA,MACD;AAGA,UAAI,gBAAgB,KAAK;AACzB,UAAI,uBAAuB,KAAK;AAChC,UAAI,kBAAkB,KAAK;AAC3B,UAAI,qBAAqB,KAAK;AAC9B,UAAI,UAAU,cAAc,QAAQ,iBAAiB,qBAAqB,QAAQ,YAAY,gBAAgB,QAAQ,eAAe,KAAK,mBAAmB;AAC7J,UAAI,kBAAkB,UAAU,iBAAiB,YAAY;AAE7D;AACA,iBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACzC,mBAAS,KAAK,GAAG,KAAK,SAAS,MAAM;AACpC,gBAAI,aAAa,cAAc,EAAE;AACjC,gBAAI,WAAW,KAAK,SAAS,GAAG;AAC/B,mBAAK,iBAAiB,UAAU;AAChC,uBAAS;AAAA,YACV;AAAA,UACD;AACA,mBAAS,KAAK,GAAG,KAAK,gBAAgB,MAAM;AAC3C,gBAAI,aAAa,qBAAqB,EAAE;AACxC,gBAAI,WAAW,KAAK,SAAS,GAAG;AAC/B,mBAAK,wBAAwB,UAAU;AACvC,uBAAS;AAAA,YACV;AAAA,UACD;AACA,mBAAS,KAAK,GAAG,KAAK,WAAW,MAAM;AACtC,gBAAI,aAAa,gBAAgB,EAAE;AACnC,gBAAI,WAAW,KAAK,SAAS,GAAG;AAC/B,mBAAK,mBAAmB,UAAU;AAClC,uBAAS;AAAA,YACV;AAAA,UACD;AACA,mBAAS,KAAK,GAAG,KAAK,cAAc,MAAM;AACzC,kBAAM,aAAa,mBAAmB,EAAE;AACxC,gBAAI,WAAW,KAAK,SAAS,GAAG;AAC/B,mBAAK,sBAAsB,UAAU;AACrC,uBAAS;AAAA,YACV;AAAA,UACD;AAAA,QACD;AAEA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG;AACxC,aAAK,SAAS,MAAM,CAAC,CAAC;AAAA,IACxB;AAAA,IAEA,iBAAkB,YAA0B;AAC3C,iBAAW,SAAS,WAAW,OAAO,SAAS,MAAM,CAAC,WAAW,KAAK,gBAAiB,KAAK,QAAQ,MAAM,SAAS,KAAK,KAAK,aAAa,WAAW,MAAM,IAAI;AAC/J,UAAI,CAAC,WAAW;AAAQ;AAExB,UAAI,SAAS,WAAW;AACxB,WAAK,SAAS,MAAM;AAEpB,UAAI,cAAc,WAAW;AAC7B,UAAI,SAAS,YAAY,CAAC;AAC1B,WAAK,SAAS,MAAM;AAEpB,UAAI,YAAY,UAAU,GAAG;AAC5B,aAAK,aAAa,KAAK,UAAU;AACjC,aAAK,UAAU,OAAO,QAAQ;AAAA,MAC/B,OAAO;AACN,YAAI,QAAQ,YAAY,YAAY,SAAS,CAAC;AAC9C,aAAK,SAAS,KAAK;AAEnB,aAAK,aAAa,KAAK,UAAU;AAEjC,aAAK,UAAU,OAAO,QAAQ;AAC9B,cAAM,SAAS;AAAA,MAChB;AAAA,IACD;AAAA,IAEA,mBAAoB,YAA4B;AAC/C,iBAAW,SAAS,WAAW,OAAO,KAAK,SAAS,MAAM,CAAC,WAAW,KAAK,gBAAiB,KAAK,QAAQ,MAAM,SAAS,KAAK,KAAK,aAAa,WAAW,MAAM,IAAI;AACpK,UAAI,CAAC,WAAW;AAAQ;AAExB,UAAI,OAAO,WAAW;AACtB,UAAI,YAAY,KAAK,KAAK;AAC1B,UAAI,WAAW,KAAK;AACpB,UAAI,KAAK;AAAM,aAAK,6BAA6B,KAAK,MAAM,WAAW,QAAQ;AAC/E,UAAI,KAAK,KAAK,eAAe,KAAK,KAAK,eAAe,KAAK;AAC1D,aAAK,6BAA6B,KAAK,KAAK,aAAa,WAAW,QAAQ;AAC7E,eAAS,IAAI,GAAG,IAAI,KAAK,KAAK,MAAM,QAAQ,IAAI,GAAG;AAClD,aAAK,6BAA6B,KAAK,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ;AAE1E,UAAI,aAAa,KAAK,cAAc;AACpC,UAAI,sBAAsB;AAAgB,aAAK,iCAAiC,YAAY,QAAQ;AAEpG,UAAI,cAAc,WAAW;AAC7B,UAAI,YAAY,YAAY;AAC5B,eAAS,IAAI,GAAG,IAAI,WAAW;AAC9B,aAAK,SAAS,YAAY,CAAC,CAAC;AAE7B,WAAK,aAAa,KAAK,UAAU;AAEjC,eAAS,IAAI,GAAG,IAAI,WAAW;AAC9B,aAAK,UAAU,YAAY,CAAC,EAAE,QAAQ;AACvC,eAAS,IAAI,GAAG,IAAI,WAAW;AAC9B,oBAAY,CAAC,EAAE,SAAS;AAAA,IAC1B;AAAA,IAEA,wBAAyB,YAAiC;AACzD,iBAAW,SAAS,WAAW,OAAO,SAAS,MAAM,CAAC,WAAW,KAAK,gBAAiB,KAAK,QAAQ,MAAM,SAAS,KAAK,KAAK,aAAa,WAAW,MAAM,IAAI;AAC/J,UAAI,CAAC,WAAW;AAAQ;AAExB,WAAK,SAAS,WAAW,MAAM;AAE/B,UAAI,cAAc,WAAW;AAC7B,UAAI,YAAY,YAAY;AAC5B,UAAI,WAAW,KAAK,OAAO;AAC1B,iBAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AACnC,cAAI,QAAQ,YAAY,CAAC;AACzB,eAAK,SAAS,MAAM,MAAO;AAC3B,eAAK,SAAS,KAAK;AAAA,QACpB;AAAA,MACD,OAAO;AACN,iBAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AACnC,eAAK,SAAS,YAAY,CAAC,CAAC;AAAA,QAC7B;AAAA,MACD;AAEA,WAAK,aAAa,KAAK,UAAU;AAEjC,eAAS,IAAI,GAAG,IAAI,WAAW;AAC9B,aAAK,UAAU,YAAY,CAAC,EAAE,QAAQ;AACvC,eAAS,IAAI,GAAG,IAAI,WAAW;AAC9B,oBAAY,CAAC,EAAE,SAAS;AAAA,IAC1B;AAAA,IAEA,6BAA8B,MAAY,WAAmB,UAAgB;AAC5E,UAAI,cAAc,KAAK,YAAY,SAAS;AAC5C,UAAI,CAAC;AAAa;AAClB,eAAS,OAAO,aAAa;AAC5B,aAAK,iCAAiC,YAAY,GAAG,GAAG,QAAQ;AAAA,MACjE;AAAA,IACD;AAAA,IAEA,iCAAkC,YAAwB,UAAgB;AACzE,UAAI,EAAE,sBAAsB;AAAiB;AAC7C,UAAI,YAA6B,WAAY;AAC7C,UAAI,CAAC;AACJ,aAAK,SAAS,QAAQ;AAAA,WAClB;AACJ,YAAI,QAAQ,KAAK;AACjB,iBAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,KAAI;AAC7C,cAAI,KAAK,UAAU,GAAG;AACtB,gBAAM;AACN,iBAAO,IAAI;AACV,iBAAK,SAAS,MAAM,UAAU,GAAG,CAAC,CAAC;AAAA,QACrC;AAAA,MACD;AAAA,IACD;AAAA,IAEA,sBAAuB,YAA+B;AACrD,YAAM,OAAO,WAAW;AACxB,iBAAW,SAAS,KAAK,WAAW,CAAC,WAAW,KAAK,gBAAiB,KAAK,QAAQ,QAAQ,MAAM,SAAS,KAAK,KAAK,aAAa,WAAW,MAAM,IAAI;AACtJ,UAAI,CAAC,WAAW;AAAQ;AAExB,WAAK,SAAS,IAAI;AAElB,WAAK,aAAa,KAAK,UAAU;AAEjC,WAAK,UAAU,KAAK,QAAQ;AAC5B,WAAK,SAAS;AAAA,IACf;AAAA,IAEA,SAAU,MAAY;AACrB,UAAI,CAAC;AAAM;AACX,UAAI,KAAK;AAAQ;AACjB,UAAI,SAAS,KAAK;AAClB,UAAI;AAAQ,aAAK,SAAS,MAAM;AAChC,WAAK,SAAS;AACd,WAAK,aAAa,KAAK,IAAI;AAAA,IAC5B;AAAA,IAEA,UAAW,OAAoB;AAC9B,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,CAAC,KAAK;AAAQ;AAClB,YAAI,KAAK;AAAQ,eAAK,UAAU,KAAK,QAAQ;AAC7C,aAAK,SAAS;AAAA,MACf;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,qBAAsB,SAAkB;AACvC,UAAI,YAAY,UAAa,YAAY;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACrF,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,aAAK,KAAK,KAAK;AACf,aAAK,KAAK,KAAK;AACf,aAAK,YAAY,KAAK;AACtB,aAAK,UAAU,KAAK;AACpB,aAAK,UAAU,KAAK;AACpB,aAAK,UAAU,KAAK;AACpB,aAAK,UAAU,KAAK;AAAA,MACrB;AAEA,UAAI,cAAc,KAAK;AACvB,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,IAAI,GAAG;AAC9C,oBAAY,CAAC,EAAE,OAAO,OAAO;AAAA,IAC/B;AAAA,IAEA,yBAA0B,SAAkB,QAAc;AACzD,UAAI,CAAC;AAAQ,cAAM,IAAI,MAAM,wBAAwB;AAErD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,aAAK,KAAK,KAAK;AACf,aAAK,KAAK,KAAK;AACf,aAAK,YAAY,KAAK;AACtB,aAAK,UAAU,KAAK;AACpB,aAAK,UAAU,KAAK;AACpB,aAAK,UAAU,KAAK;AACpB,aAAK,UAAU,KAAK;AAAA,MACrB;AAGA,UAAI,WAAW,KAAK,YAAY;AAChC,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,6BAA6B;AAC5D,UAAI,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,OAAO;AAC7D,eAAS,SAAS,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,OAAO;AACrD,eAAS,SAAS,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,OAAO;AAErD,YAAM,MAAM,SAAS,WAAW,SAAS,UAAU,UAAU;AAC7D,YAAM,MAAM,SAAS,WAAW,KAAK,SAAS,UAAU,UAAU;AAClE,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,SAAS;AACnC,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,SAAS;AACnC,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,SAAS;AACnC,YAAM,KAAK,KAAK,IAAI,EAAE,IAAI,SAAS;AACnC,eAAS,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK;AACxC,eAAS,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK;AACxC,eAAS,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK;AACxC,eAAS,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK;AAGxC,UAAI,cAAc,KAAK;AACvB,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,IAAI,GAAG,KAAK;AACnD,YAAI,YAAY,YAAY,CAAC;AAC7B,YAAI,aAAa;AAAU,oBAAU,OAAO,OAAO;AAAA,MACpD;AAAA,IACD;AAAA;AAAA,IAGA,iBAAkB;AACjB,WAAK,oBAAoB;AACzB,WAAK,oBAAoB;AAAA,IAC1B;AAAA;AAAA,IAGA,sBAAuB;AACtB,iBAAW,QAAQ,KAAK;AAAO,aAAK,eAAe;AACnD,iBAAW,cAAc,KAAK;AAAe,mBAAW,eAAe;AACvE,iBAAW,cAAc,KAAK;AAAsB,mBAAW,eAAe;AAC9E,iBAAW,cAAc,KAAK;AAAiB,mBAAW,eAAe;AACzE,iBAAW,cAAc,KAAK;AAAoB,mBAAW,eAAe;AAAA,IAC7E;AAAA;AAAA,IAGA,sBAAuB;AACtB,UAAI,QAAQ,KAAK;AACjB,YAAM,UAAU,OAAO,GAAG,KAAK,WAAW,GAAG,MAAM,MAAM;AACzD,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG;AACxC,cAAM,CAAC,EAAE,eAAe;AAAA,IAC1B;AAAA;AAAA,IAGA,cAAe;AACd,UAAI,KAAK,MAAM,UAAU;AAAG,eAAO;AACnC,aAAO,KAAK,MAAM,CAAC;AAAA,IACpB;AAAA;AAAA,IAGA,SAAU,UAAkB;AAC3B,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,KAAK,QAAQ;AAAU,iBAAO;AAAA,MACxC;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,UAAkB;AAC3B,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,KAAK,QAAQ;AAAU,iBAAO;AAAA,MACxC;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,cAAe,UAAkB;AAChC,UAAI,OAAO,KAAK,KAAK,SAAS,QAAQ;AACtC,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,qBAAqB,QAAQ;AACxD,WAAK,QAAQ,IAAI;AAAA,IAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,QAAS,SAAe;AACvB,UAAI,WAAW,KAAK;AAAM;AAC1B,UAAI,SAAS;AACZ,YAAI,KAAK;AACR,kBAAQ,UAAU,MAAM,KAAK,IAAI;AAAA,aAC7B;AACJ,cAAI,QAAQ,KAAK;AACjB,mBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,gBAAI,OAAO,MAAM,CAAC;AAClB,gBAAI,OAAO,KAAK,KAAK;AACrB,gBAAI,MAAM;AACT,kBAAI,aAAa,QAAQ,cAAc,GAAG,IAAI;AAC9C,kBAAI;AAAY,qBAAK,cAAc,UAAU;AAAA,YAC9C;AAAA,UACD;AAAA,QACD;AAAA,MACD;AACA,WAAK,OAAO;AACZ,WAAK,YAAY;AAAA,IAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,oBAAqB,UAAkB,gBAA2C;AACjF,UAAI,OAAO,KAAK,KAAK,SAAS,QAAQ;AACtC,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,6BAA6B,UAAU;AAClE,aAAO,KAAK,cAAc,KAAK,OAAO,cAAc;AAAA,IACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,cAAe,WAAmB,gBAA2C;AAC5E,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,UAAI,KAAK,MAAM;AACd,YAAI,aAAa,KAAK,KAAK,cAAc,WAAW,cAAc;AAClE,YAAI;AAAY,iBAAO;AAAA,MACxB;AACA,UAAI,KAAK,KAAK;AAAa,eAAO,KAAK,KAAK,YAAY,cAAc,WAAW,cAAc;AAC/F,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,cAAe,UAAkB,gBAAwB;AACxD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,KAAK,QAAQ,UAAU;AAC/B,cAAI,aAAgC;AACpC,cAAI,gBAAgB;AACnB,yBAAa,KAAK,cAAc,GAAG,cAAc;AACjD,gBAAI,CAAC;AAAY,oBAAM,IAAI,MAAM,2BAA2B,iBAAiB,iBAAiB,QAAQ;AAAA,UACvG;AACA,eAAK,cAAc,UAAU;AAC7B;AAAA,QACD;AAAA,MACD;AACA,YAAM,IAAI,MAAM,qBAAqB,QAAQ;AAAA,IAC9C;AAAA;AAAA;AAAA;AAAA,IAMA,iBAAkB,gBAAwB;AACzC,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,aAAO,KAAK,cAAc,KAAK,CAAC,eAAe,WAAW,KAAK,QAAQ,cAAc,KAAK;AAAA,IAC3F;AAAA;AAAA;AAAA;AAAA,IAKA,wBAAyB,gBAAwB;AAChD,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,aAAO,KAAK,qBAAqB,KAAK,CAAC,eAAe,WAAW,KAAK,QAAQ,cAAc,KAAK;AAAA,IAClG;AAAA;AAAA;AAAA;AAAA,IAKA,mBAAoB,gBAAwB;AAC3C,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,aAAO,KAAK,gBAAgB,KAAK,CAAC,eAAe,WAAW,KAAK,QAAQ,cAAc,KAAK;AAAA,IAC7F;AAAA;AAAA;AAAA,IAIA,sBAAuB,gBAAwB;AAC9C,UAAI,kBAAkB;AAAM,cAAM,IAAI,MAAM,gCAAgC;AAC5E,aAAO,KAAK,mBAAmB,KAAK,CAAC,eAAe,WAAW,KAAK,QAAQ,cAAc,KAAK;AAAA,IAChG;AAAA;AAAA;AAAA,IAIA,cAAe,SAA4B;AAC1C,UAAI,SAAS,IAAI,QAAQ;AACzB,UAAI,OAAO,IAAI,QAAQ;AACvB,WAAK,UAAU,QAAQ,MAAM,QAAW,OAAO;AAC/C,aAAO,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,GAAG,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE;AAAA,IAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,UAAW,QAAiB,MAAe,OAAsB,IAAI,MAAc,CAAC,GAAG,UAAmC,MAAM;AAC/H,UAAI,CAAC;AAAQ,cAAM,IAAI,MAAM,wBAAwB;AACrD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,YAAY,KAAK;AACrB,UAAI,OAAO,OAAO,mBAAmB,OAAO,OAAO,mBAAmB,OAAO,OAAO,mBAAmB,OAAO,OAAO;AACrH,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG,KAAK;AACjD,YAAI,OAAO,UAAU,CAAC;AACtB,YAAI,CAAC,KAAK,KAAK;AAAQ;AACvB,YAAI,iBAAiB;AACrB,YAAI,WAAmC;AACvC,YAAI,YAAoC;AACxC,YAAI,aAAa,KAAK,cAAc;AACpC,YAAI,sBAAsB,kBAAkB;AAC3C,2BAAiB;AACjB,qBAAW,MAAM,aAAa,MAAM,gBAAgB,CAAC;AACrD,qBAAW,qBAAqB,MAAM,UAAU,GAAG,CAAC;AACpD,sBAAY,UAAS;AAAA,QACtB,WAAW,sBAAsB,gBAAgB;AAChD,cAAI,OAAwB;AAC5B,2BAAiB,KAAK;AACtB,qBAAW,MAAM,aAAa,MAAM,gBAAgB,CAAC;AACrD,eAAK,qBAAqB,MAAM,GAAG,gBAAgB,UAAU,GAAG,CAAC;AACjE,sBAAY,KAAK;AAAA,QAClB,WAAW,sBAAsB,sBAAsB,WAAW,MAAM;AACvE,kBAAQ,UAAU,MAAM,UAAU;AAClC;AAAA,QACD;AACA,YAAI,YAAY,WAAW;AAC1B,cAAI,WAAW,QAAQ,QAAQ,WAAW,GAAG;AAC5C,oBAAQ,cAAc,UAAU,WAAW,UAAU,MAAM;AAC3D,uBAAW,QAAQ;AACnB,6BAAiB,QAAQ,gBAAgB;AAAA,UAC1C;AACA,mBAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,KAAK,IAAI,MAAM,GAAG;AACxD,gBAAI,IAAI,SAAS,EAAE,GAAG,IAAI,SAAS,KAAK,CAAC;AACzC,mBAAO,KAAK,IAAI,MAAM,CAAC;AACvB,mBAAO,KAAK,IAAI,MAAM,CAAC;AACvB,mBAAO,KAAK,IAAI,MAAM,CAAC;AACvB,mBAAO,KAAK,IAAI,MAAM,CAAC;AAAA,UACxB;AAAA,QACD;AACA,YAAI,WAAW;AAAM,kBAAQ,gBAAgB,IAAI;AAAA,MAClD;AACA,UAAI,WAAW;AAAM,gBAAQ,QAAQ;AACrC,aAAO,IAAI,MAAM,IAAI;AACrB,WAAK,IAAI,OAAO,MAAM,OAAO,IAAI;AAAA,IAClC;AAAA;AAAA,IAGA,OAAQ,OAAe;AACtB,WAAK,QAAQ;AAAA,IACd;AAAA,IAEA,iBAAkB,GAAW,GAAW;AACvC,YAAM,qBAAqB,KAAK;AAChC,eAAS,IAAI,GAAG,IAAI,mBAAmB,QAAQ,IAAI,GAAG;AACrD,2BAAmB,CAAC,EAAE,UAAU,GAAG,CAAC;AAAA,IACtC;AAAA;AAAA,IAGA,cAAe,GAAW,GAAW,SAAiB;AACrD,YAAM,qBAAqB,KAAK;AAChC,eAAS,IAAI,GAAG,IAAI,mBAAmB,QAAQ,IAAI,GAAG;AACrD,2BAAmB,CAAC,EAAE,OAAO,GAAG,GAAG,OAAO;AAAA,IAC5C;AAAA,EACD;AAnoBO,MAAM,WAAN;AACN,gBADY,UACG,iBAAgB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAChD,gBAFY,UAEL,SAAQ;AAooBT,MAAK,UAAL,kBAAKG,aAAL;AAEN,IAAAA,kBAAA;AAGA,IAAAA,kBAAA;AAGA,IAAAA,kBAAA;AAGA,IAAAA,kBAAA;AAXW,WAAAA;AAAA,KAAA;;;ACnpBL,MAAM,wBAAN,cAAoC,eAAe;AAAA,IACjD,QAAyB;AAAA;AAAA,IAEjC,IAAW,KAAM,UAAoB;AAAE,WAAK,QAAQ;AAAA,IAAU;AAAA,IAC9D,IAAW,OAAQ;AAClB,UAAI,CAAC,KAAK;AAAO,cAAM,IAAI,MAAM,mBAAmB;AAAA;AAC/C,eAAO,KAAK;AAAA,IAClB;AAAA,IAEA,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA;AAAA,IAEV,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,YAAY;AAAA,IAEZ,YAAa,MAAc;AAC1B,YAAM,MAAM,GAAG,KAAK;AAAA,IACrB;AAAA,EACD;;;AC5BO,MAAM,eAAN,MAAmB;AAAA;AAAA,IAGzB,OAAsB;AAAA;AAAA,IAGtB,QAAQ,IAAI,MAAgB;AAAA;AAAA;AAAA,IAG5B,QAAQ,IAAI,MAAgB;AAAA;AAAA,IAE5B,QAAQ,IAAI,MAAY;AAAA;AAAA;AAAA;AAAA;AAAA,IAMxB,cAA2B;AAAA;AAAA,IAG3B,SAAS,IAAI,MAAiB;AAAA;AAAA,IAG9B,aAAa,IAAI,MAAiB;AAAA;AAAA,IAGlC,gBAAgB,IAAI,MAAwB;AAAA;AAAA,IAG5C,uBAAuB,IAAI,MAA+B;AAAA;AAAA,IAG1D,kBAAkB,IAAI,MAA0B;AAAA;AAAA,IAGhD,qBAAqB,IAAI,MAA6B;AAAA;AAAA,IAGtD,IAAY;AAAA;AAAA,IAGZ,IAAY;AAAA;AAAA,IAGZ,QAAgB;AAAA;AAAA,IAGhB,SAAiB;AAAA;AAAA;AAAA,IAIjB,iBAAiB;AAAA;AAAA,IAGjB,UAAyB;AAAA;AAAA,IAGzB,OAAsB;AAAA;AAAA;AAAA,IAItB,MAAM;AAAA;AAAA,IAGN,aAA4B;AAAA;AAAA,IAG5B,YAA2B;AAAA;AAAA;AAAA;AAAA,IAK3B,SAAU,UAAkB;AAC3B,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,QAAQ;AAAU,iBAAO;AAAA,MACnC;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,UAAkB;AAC3B,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,QAAQ;AAAU,iBAAO;AAAA,MACnC;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,SAAU,UAAkB;AAC3B,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,QAAQ,KAAK;AACjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC7C,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,KAAK,QAAQ;AAAU,iBAAO;AAAA,MACnC;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,UAAW,eAAuB;AACjC,UAAI,CAAC;AAAe,cAAM,IAAI,MAAM,+BAA+B;AACnE,UAAI,SAAS,KAAK;AAClB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,GAAG,KAAK;AAC9C,YAAI,QAAQ,OAAO,CAAC;AACpB,YAAI,MAAM,QAAQ;AAAe,iBAAO;AAAA,MACzC;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,cAAe,eAAuB;AACrC,UAAI,CAAC;AAAe,cAAM,IAAI,MAAM,+BAA+B;AACnE,UAAI,aAAa,KAAK;AACtB,eAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,IAAI,GAAG,KAAK;AAClD,YAAI,YAAY,WAAW,CAAC;AAC5B,YAAI,UAAU,QAAQ;AAAe,iBAAO;AAAA,MAC7C;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,iBAAkB,gBAAwB;AACzC,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,YAAM,gBAAgB,KAAK;AAC3B,eAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,IAAI,GAAG,KAAK;AACrD,cAAM,aAAa,cAAc,CAAC;AAClC,YAAI,WAAW,QAAQ;AAAgB,iBAAO;AAAA,MAC/C;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,wBAAyB,gBAAwB;AAChD,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,YAAM,uBAAuB,KAAK;AAClC,eAAS,IAAI,GAAG,IAAI,qBAAqB,QAAQ,IAAI,GAAG,KAAK;AAC5D,cAAM,aAAa,qBAAqB,CAAC;AACzC,YAAI,WAAW,QAAQ;AAAgB,iBAAO;AAAA,MAC/C;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,mBAAoB,gBAAwB;AAC3C,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,YAAM,kBAAkB,KAAK;AAC7B,eAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,IAAI,GAAG,KAAK;AACvD,cAAM,aAAa,gBAAgB,CAAC;AACpC,YAAI,WAAW,QAAQ;AAAgB,iBAAO;AAAA,MAC/C;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,sBAAuB,gBAAwB;AAC9C,UAAI,CAAC;AAAgB,cAAM,IAAI,MAAM,gCAAgC;AACrE,YAAM,qBAAqB,KAAK;AAChC,eAAS,IAAI,GAAG,IAAI,mBAAmB,QAAQ,IAAI,GAAG,KAAK;AAC1D,cAAM,aAAa,mBAAmB,CAAC;AACvC,YAAI,WAAW,QAAQ;AAAgB,iBAAO;AAAA,MAC/C;AACA,aAAO;AAAA,IACR;AAAA,EACD;;;AC/LO,MAAM,YAAN,MAAgB;AAAA,IACtB,YAAoB,YAAoB,GAAU,MAAqB,YAAwB;AAA3E;AAA8B;AAAqB;AAAA,IAA0B;AAAA,EAClG;AAMO,MAAM,OAAN,MAAW;AAAA;AAAA,IAEjB;AAAA,IAEA,cAAc,IAAI,MAA6B;AAAA,IAC/C,QAAQ,MAAgB;AAAA,IACxB,cAAc,IAAI,MAAsB;AAAA;AAAA,IAGxC,QAAQ,IAAI,MAAM,YAAY,YAAY,YAAY,CAAC;AAAA;AAAA,IAEvD,YAAa,MAAc;AAC1B,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,WAAK,OAAO;AAAA,IACb;AAAA;AAAA,IAGA,cAAe,WAAmB,MAAc,YAAwB;AACvE,UAAI,CAAC;AAAY,cAAM,IAAI,MAAM,4BAA4B;AAC7D,UAAI,cAAc,KAAK;AACvB,UAAI,aAAa,YAAY;AAAQ,oBAAY,SAAS,YAAY;AACtE,UAAI,CAAC,YAAY,SAAS;AAAG,oBAAY,SAAS,IAAI,CAAC;AACvD,kBAAY,SAAS,EAAE,IAAI,IAAI;AAAA,IAChC;AAAA;AAAA,IAGA,QAAS,MAAY;AACpB,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,YAAI,OAAO,KAAK,MAAM,CAAC;AACvB,YAAI,YAAY;AAChB,iBAAS,KAAK,GAAG,KAAK,KAAK,MAAM,QAAQ,MAAM;AAC9C,cAAI,KAAK,MAAM,EAAE,KAAK,MAAM;AAC3B,wBAAY;AACZ;AAAA,UACD;AAAA,QACD;AACA,YAAI,CAAC;AAAW,eAAK,MAAM,KAAK,IAAI;AAAA,MACrC;AAEA,eAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;AACjD,YAAI,aAAa,KAAK,YAAY,CAAC;AACnC,YAAI,YAAY;AAChB,iBAAS,KAAK,GAAG,KAAK,KAAK,YAAY,QAAQ,MAAM;AACpD,cAAI,KAAK,YAAY,EAAE,KAAK,YAAY;AACvC,wBAAY;AACZ;AAAA,UACD;AAAA,QACD;AACA,YAAI,CAAC;AAAW,eAAK,YAAY,KAAK,UAAU;AAAA,MACjD;AAEA,UAAI,cAAc,KAAK,eAAe;AACtC,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC5C,YAAI,aAAa,YAAY,CAAC;AAC9B,aAAK,cAAc,WAAW,WAAW,WAAW,MAAM,WAAW,UAAU;AAAA,MAChF;AAAA,IACD;AAAA;AAAA;AAAA,IAIA,SAAU,MAAY;AACrB,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,YAAI,OAAO,KAAK,MAAM,CAAC;AACvB,YAAI,YAAY;AAChB,iBAAS,KAAK,GAAG,KAAK,KAAK,MAAM,QAAQ,MAAM;AAC9C,cAAI,KAAK,MAAM,EAAE,KAAK,MAAM;AAC3B,wBAAY;AACZ;AAAA,UACD;AAAA,QACD;AACA,YAAI,CAAC;AAAW,eAAK,MAAM,KAAK,IAAI;AAAA,MACrC;AAEA,eAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;AACjD,YAAI,aAAa,KAAK,YAAY,CAAC;AACnC,YAAI,YAAY;AAChB,iBAAS,KAAK,GAAG,KAAK,KAAK,YAAY,QAAQ,MAAM;AACpD,cAAI,KAAK,YAAY,EAAE,KAAK,YAAY;AACvC,wBAAY;AACZ;AAAA,UACD;AAAA,QACD;AACA,YAAI,CAAC;AAAW,eAAK,YAAY,KAAK,UAAU;AAAA,MACjD;AAEA,UAAI,cAAc,KAAK,eAAe;AACtC,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC5C,YAAI,aAAa,YAAY,CAAC;AAC9B,YAAI,CAAC,WAAW;AAAY;AAC5B,YAAI,WAAW,sBAAsB,gBAAgB;AACpD,qBAAW,aAAa,WAAW,WAAW,cAAc;AAC5D,eAAK,cAAc,WAAW,WAAW,WAAW,MAAM,WAAW,UAAU;AAAA,QAChF,OAAO;AACN,qBAAW,aAAa,WAAW,WAAW,KAAK;AACnD,eAAK,cAAc,WAAW,WAAW,WAAW,MAAM,WAAW,UAAU;AAAA,QAChF;AAAA,MACD;AAAA,IACD;AAAA;AAAA,IAGA,cAAe,WAAmB,MAAiC;AAClE,UAAI,aAAa,KAAK,YAAY,SAAS;AAC3C,aAAO,aAAa,WAAW,IAAI,IAAI;AAAA,IACxC;AAAA;AAAA,IAGA,iBAAkB,WAAmB,MAAc;AAClD,UAAI,aAAa,KAAK,YAAY,SAAS;AAC3C,UAAI;AAAY,eAAO,WAAW,IAAI;AAAA,IACvC;AAAA;AAAA,IAGA,iBAAoC;AACnC,UAAI,UAAU,IAAI,MAAiB;AACnC,eAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;AACjD,YAAI,kBAAkB,KAAK,YAAY,CAAC;AACxC,YAAI,iBAAiB;AACpB,mBAAS,QAAQ,iBAAiB;AACjC,gBAAI,aAAa,gBAAgB,IAAI;AACrC,gBAAI;AAAY,sBAAQ,KAAK,IAAI,UAAU,GAAG,MAAM,UAAU,CAAC;AAAA,UAChE;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,sBAAuB,WAAmB,aAA+B;AACxE,UAAI,kBAAkB,KAAK,YAAY,SAAS;AAChD,UAAI,iBAAiB;AACpB,iBAAS,QAAQ,iBAAiB;AACjC,cAAI,aAAa,gBAAgB,IAAI;AACrC,cAAI;AAAY,wBAAY,KAAK,IAAI,UAAU,WAAW,MAAM,UAAU,CAAC;AAAA,QAC5E;AAAA,MACD;AAAA,IACD;AAAA;AAAA,IAGA,QAAS;AACR,WAAK,YAAY,SAAS;AAC1B,WAAK,MAAM,SAAS;AACpB,WAAK,YAAY,SAAS;AAAA,IAC3B;AAAA;AAAA,IAGA,UAAW,UAAoB,SAAe;AAC7C,UAAI,YAAY;AAChB,eAAS,IAAI,GAAG,IAAI,SAAS,MAAM,QAAQ,KAAK;AAC/C,YAAI,OAAO,SAAS,MAAM,CAAC;AAC3B,YAAI,iBAAiB,KAAK,cAAc;AACxC,YAAI,kBAAkB,YAAY,QAAQ,YAAY,QAAQ;AAC7D,cAAI,aAAa,QAAQ,YAAY,SAAS;AAC9C,mBAAS,OAAO,YAAY;AAC3B,gBAAI,iBAA6B,WAAW,GAAG;AAC/C,gBAAI,kBAAkB,gBAAgB;AACrC,kBAAI,aAAa,KAAK,cAAc,WAAW,GAAG;AAClD,kBAAI;AAAY,qBAAK,cAAc,UAAU;AAC7C;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;;;AChLO,MAAM,WAAN,MAAe;AAAA;AAAA,IAErB,QAAgB;AAAA;AAAA,IAGhB;AAAA;AAAA,IAGA;AAAA;AAAA;AAAA,IAIA,QAAQ,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA;AAAA;AAAA,IAI5B,YAA0B;AAAA;AAAA,IAG1B,iBAAgC;AAAA;AAAA,IAGhC,YAAuB,UAAU;AAAA;AAAA,IAGjC,UAAU;AAAA,IAEV,YAAa,OAAe,MAAc,UAAoB;AAC7D,UAAI,QAAQ;AAAG,cAAM,IAAI,MAAM,qBAAqB;AACpD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,sBAAsB;AACjD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,WAAK,QAAQ;AACb,WAAK,OAAO;AACZ,WAAK,WAAW;AAAA,IACjB;AAAA,EACD;AAGO,MAAK,YAAL,kBAAKC,eAAL;AAAiB,IAAAA,sBAAA;AAAQ,IAAAA,sBAAA;AAAU,IAAAA,sBAAA;AAAU,IAAAA,sBAAA;AAAxC,WAAAA;AAAA,KAAA;;;ACpCL,MAAM,0BAAN,cAAsC,eAAe;AAAA;AAAA,IAG3D,QAAQ,IAAI,MAAgB;AAAA;AAAA,IAGpB,UAA2B;AAAA,IACnC,IAAW,OAAQ,UAAoB;AAAE,WAAK,UAAU;AAAA,IAAU;AAAA,IAClE,IAAW,SAAU;AACpB,UAAI,CAAC,KAAK;AAAS,cAAM,IAAI,MAAM,mBAAmB;AAAA;AACjD,eAAO,KAAK;AAAA,IAClB;AAAA,IAEA,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA;AAAA,IAGZ,iBAAiB;AAAA;AAAA,IAGjB,UAAU;AAAA;AAAA,IAGV,UAAU;AAAA;AAAA,IAGV,eAAe;AAAA;AAAA,IAGf,eAAe;AAAA;AAAA,IAGf,eAAe;AAAA,IAEf,WAAW;AAAA,IACX,QAAQ;AAAA,IAER,YAAa,MAAc;AAC1B,YAAM,MAAM,GAAG,KAAK;AAAA,IACrB;AAAA,EACD;;;AC3BO,MAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,IAK3B,QAAQ;AAAA,IAER;AAAA,IACQ,eAAe,IAAI,MAAkB;AAAA,IAE7C,YAAa,kBAAoC;AAChD,WAAK,mBAAmB;AAAA,IACzB;AAAA,IAEA,iBAAkB,QAAgD;AACjE,UAAI,QAAQ,KAAK;AAEjB,UAAI,eAAe,IAAI,aAAa;AACpC,mBAAa,OAAO;AAEpB,UAAI,QAAQ,IAAI,YAAY,MAAM;AAElC,UAAI,UAAU,MAAM,UAAU;AAC9B,UAAI,WAAW,MAAM,UAAU;AAC/B,mBAAa,OAAO,YAAY,KAAK,WAAW,IAAI,OAAO,SAAS,SAAS,EAAE,IAAI,QAAQ,SAAS,EAAE;AACtG,mBAAa,UAAU,MAAM,WAAW;AACxC,mBAAa,IAAI,MAAM,UAAU;AACjC,mBAAa,IAAI,MAAM,UAAU;AACjC,mBAAa,QAAQ,MAAM,UAAU;AACrC,mBAAa,SAAS,MAAM,UAAU;AACtC,mBAAa,iBAAiB,MAAM,UAAU,IAAI;AAElD,UAAI,eAAe,MAAM,YAAY;AACrC,UAAI,cAAc;AACjB,qBAAa,MAAM,MAAM,UAAU;AACnC,qBAAa,aAAa,MAAM,WAAW;AAC3C,qBAAa,YAAY,MAAM,WAAW;AAAA,MAC3C;AAEA,UAAI,IAAI;AAER,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAI,MAAM,MAAM,WAAW;AAC3B,YAAI,CAAC;AAAK,gBAAM,IAAI,MAAM,0CAA0C;AACpE,cAAM,QAAQ,KAAK,GAAG;AAAA,MACvB;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAI,OAAO,MAAM,WAAW;AAC5B,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,6BAA6B;AACxD,YAAI,SAAS,KAAK,IAAI,OAAO,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AACnE,YAAI,OAAO,IAAI,SAAS,GAAG,MAAM,MAAM;AACvC,aAAK,WAAW,MAAM,UAAU;AAChC,aAAK,IAAI,MAAM,UAAU,IAAI;AAC7B,aAAK,IAAI,MAAM,UAAU,IAAI;AAC7B,aAAK,SAAS,MAAM,UAAU;AAC9B,aAAK,SAAS,MAAM,UAAU;AAC9B,aAAK,SAAS,MAAM,UAAU;AAC9B,aAAK,SAAS,MAAM,UAAU;AAC9B,aAAK,SAAS,MAAM,UAAU,IAAI;AAClC,aAAK,UAAU,MAAM,SAAS;AAC9B,aAAK,eAAe,MAAM,YAAY;AACtC,YAAI,cAAc;AACjB,gBAAM,gBAAgB,KAAK,OAAO,MAAM,UAAU,CAAC;AACnD,eAAK,OAAO,MAAM,WAAW,KAAK;AAClC,eAAK,UAAU,MAAM,YAAY;AAAA,QAClC;AACA,qBAAa,MAAM,KAAK,IAAI;AAAA,MAC7B;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAI,WAAW,MAAM,WAAW;AAChC,YAAI,CAAC;AAAU,gBAAM,IAAI,MAAM,6BAA6B;AAC5D,YAAI,WAAW,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AACrD,YAAI,OAAO,IAAI,SAAS,GAAG,UAAU,QAAQ;AAC7C,cAAM,gBAAgB,KAAK,OAAO,MAAM,UAAU,CAAC;AAEnD,YAAI,YAAY,MAAM,UAAU;AAChC,YAAI,aAAa;AAAI,gBAAM,cAAc,KAAK,YAAY,IAAI,MAAM,GAAG,SAAS;AAEhF,aAAK,iBAAiB,MAAM,cAAc;AAC1C,aAAK,YAAY,MAAM,QAAQ,IAAI;AACnC,YAAI;AAAc,eAAK,UAAU,MAAM,YAAY;AACnD,qBAAa,MAAM,KAAK,IAAI;AAAA,MAC7B;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC/B,YAAI,OAAO,MAAM,WAAW;AAC5B,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,2CAA2C;AACtE,YAAI,OAAO,IAAI,iBAAiB,IAAI;AACpC,aAAK,QAAQ,MAAM,QAAQ,IAAI;AAC/B,aAAK,MAAM,QAAQ,IAAI;AACvB,iBAAS,KAAK,GAAG,KAAK,IAAI;AACzB,eAAK,MAAM,KAAK,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC,CAAC;AACxD,aAAK,SAAS,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AACpD,YAAI,QAAQ,MAAM,SAAS;AAC3B,aAAK,gBAAgB,QAAQ,MAAM;AACnC,aAAK,iBAAiB,QAAQ,MAAM,IAAI,IAAI;AAC5C,aAAK,YAAY,QAAQ,MAAM;AAC/B,aAAK,WAAW,QAAQ,MAAM;AAC9B,aAAK,WAAW,QAAQ,OAAO;AAC/B,aAAK,QAAQ,OAAO;AAAG,eAAK,OAAO,QAAQ,OAAO,IAAI,MAAM,UAAU,IAAI;AAC1E,aAAK,QAAQ,QAAQ;AAAG,eAAK,WAAW,MAAM,UAAU,IAAI;AAC5D,qBAAa,cAAc,KAAK,IAAI;AAAA,MACrC;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC/B,YAAI,OAAO,MAAM,WAAW;AAC5B,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,kDAAkD;AAC7E,YAAI,OAAO,IAAI,wBAAwB,IAAI;AAC3C,aAAK,QAAQ,MAAM,QAAQ,IAAI;AAC/B,aAAK,MAAM,QAAQ,IAAI;AACvB,iBAAS,KAAK,GAAG,KAAK,IAAI;AACzB,eAAK,MAAM,KAAK,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC,CAAC;AACxD,aAAK,SAAS,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AACpD,YAAI,QAAQ,MAAM,SAAS;AAC3B,aAAK,gBAAgB,QAAQ,MAAM;AACnC,aAAK,SAAS,QAAQ,MAAM;AAC5B,aAAK,YAAY,QAAQ,MAAM;AAC/B,aAAK,QAAQ,MAAM;AAAG,eAAK,iBAAiB,MAAM,UAAU;AAC5D,aAAK,QAAQ,OAAO;AAAG,eAAK,UAAU,MAAM,UAAU,IAAI;AAC1D,aAAK,QAAQ,OAAO;AAAG,eAAK,UAAU,MAAM,UAAU,IAAI;AAC1D,aAAK,QAAQ,OAAO;AAAG,eAAK,eAAe,MAAM,UAAU;AAC3D,aAAK,QAAQ,QAAQ;AAAG,eAAK,eAAe,MAAM,UAAU;AAC5D,gBAAQ,MAAM,SAAS;AACvB,aAAK,QAAQ,MAAM;AAAG,eAAK,eAAe,MAAM,UAAU;AAC1D,aAAK,QAAQ,MAAM;AAAG,eAAK,YAAY,MAAM,UAAU;AACvD,aAAK,QAAQ,MAAM;AAAG,eAAK,OAAO,MAAM,UAAU;AAClD,aAAK,QAAQ,MAAM;AAAG,eAAK,OAAO,MAAM,UAAU;AAClD,aAAK,QAAQ,OAAO;AAAG,eAAK,YAAY,MAAM,UAAU;AACxD,aAAK,QAAQ,OAAO;AAAG,eAAK,YAAY,MAAM,UAAU;AACxD,aAAK,QAAQ,OAAO;AAAG,eAAK,YAAY,MAAM,UAAU;AACxD,qBAAa,qBAAqB,KAAK,IAAI;AAAA,MAC5C;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC/B,YAAI,OAAO,MAAM,WAAW;AAC5B,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,6CAA6C;AACxE,YAAI,OAAO,IAAI,mBAAmB,IAAI;AACtC,aAAK,QAAQ,MAAM,QAAQ,IAAI;AAC/B,aAAK,eAAe,MAAM,YAAY;AACtC,aAAK,MAAM,QAAQ,IAAI;AACvB,iBAAS,KAAK,GAAG,KAAK,IAAI;AACzB,eAAK,MAAM,KAAK,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC,CAAC;AACxD,aAAK,SAAS,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AACpD,cAAM,QAAQ,MAAM,SAAS;AAC7B,aAAK,eAAe,QAAQ;AAC5B,aAAK,cAAe,SAAS,IAAK;AAClC,aAAK,aAAc,SAAS,IAAK;AACjC,aAAK,QAAQ,QAAQ;AAAG,eAAK,iBAAiB,MAAM,UAAU;AAC9D,aAAK,WAAW,MAAM,UAAU;AAChC,YAAI,KAAK;AAAoC,eAAK,YAAY;AAC9D,aAAK,UAAU,MAAM,UAAU;AAC/B,YAAI,KAAK,iCAAqC,KAAK;AAAkC,eAAK,WAAW;AACrG,aAAK,YAAY,MAAM,UAAU;AACjC,aAAK,OAAO,MAAM,UAAU;AAC5B,aAAK,OAAO,MAAM,UAAU;AAC5B,qBAAa,gBAAgB,KAAK,IAAI;AAAA,MACvC;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC/B,cAAM,OAAO,MAAM,WAAW;AAC9B,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,gDAAgD;AAC3E,cAAM,OAAO,IAAI,sBAAsB,IAAI;AAC3C,aAAK,QAAQ,MAAM,QAAQ,IAAI;AAC/B,aAAK,OAAO,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AAClD,YAAI,QAAQ,MAAM,SAAS;AAC3B,aAAK,gBAAgB,QAAQ,MAAM;AACnC,aAAK,QAAQ,MAAM;AAAG,eAAK,IAAI,MAAM,UAAU;AAC/C,aAAK,QAAQ,MAAM;AAAG,eAAK,IAAI,MAAM,UAAU;AAC/C,aAAK,QAAQ,MAAM;AAAG,eAAK,SAAS,MAAM,UAAU;AACpD,aAAK,QAAQ,OAAO;AAAG,eAAK,SAAS,MAAM,UAAU;AACrD,aAAK,QAAQ,OAAO;AAAG,eAAK,SAAS,MAAM,UAAU;AACrD,aAAK,UAAU,QAAQ,OAAO,IAAI,MAAM,UAAU,IAAI,OAAQ;AAC9D,aAAK,OAAO,IAAI,MAAM,iBAAiB;AACvC,aAAK,UAAU,MAAM,UAAU;AAC/B,aAAK,WAAW,MAAM,UAAU;AAChC,aAAK,UAAU,MAAM,UAAU;AAC/B,aAAK,eAAe,QAAQ,QAAQ,IAAI,MAAM,UAAU,IAAI;AAC5D,aAAK,OAAO,MAAM,UAAU;AAC5B,aAAK,UAAU,MAAM,UAAU;AAC/B,gBAAQ,MAAM,SAAS;AACvB,aAAK,QAAQ,MAAM;AAAG,eAAK,gBAAgB;AAC3C,aAAK,QAAQ,MAAM;AAAG,eAAK,iBAAiB;AAC5C,aAAK,QAAQ,MAAM;AAAG,eAAK,gBAAgB;AAC3C,aAAK,QAAQ,MAAM;AAAG,eAAK,aAAa;AACxC,aAAK,QAAQ,OAAO;AAAG,eAAK,aAAa;AACzC,aAAK,QAAQ,OAAO;AAAG,eAAK,gBAAgB;AAC5C,aAAK,QAAQ,OAAO;AAAG,eAAK,YAAY;AACxC,aAAK,OAAO,QAAQ,QAAQ,IAAI,MAAM,UAAU,IAAI;AACpD,qBAAa,mBAAmB,KAAK,IAAI;AAAA,MAC1C;AAGA,UAAI,cAAc,KAAK,SAAS,OAAO,cAAc,MAAM,YAAY;AACvE,UAAI,aAAa;AAChB,qBAAa,cAAc;AAC3B,qBAAa,MAAM,KAAK,WAAW;AAAA,MACpC;AAGA;AACC,YAAI,IAAI,aAAa,MAAM;AAC3B,cAAM,aAAa,aAAa,OAAO,IAAI,IAAI,MAAM,QAAQ,IAAI,CAAC;AAClE,eAAO,IAAI,GAAG,KAAK;AAClB,cAAI,OAAO,KAAK,SAAS,OAAO,cAAc,OAAO,YAAY;AACjE,cAAI,CAAC;AAAM,kBAAM,IAAI,MAAM,2CAA2C;AACtE,uBAAa,MAAM,CAAC,IAAI;AAAA,QACzB;AAAA,MACD;AAGA,UAAI,KAAK,aAAa;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAI,aAAa,KAAK,aAAa,CAAC;AACpC,cAAM,OAAO,aAAa,MAAM,WAAW,SAAS;AACpD,YAAI,CAAC,WAAW;AAAQ,gBAAM,IAAI,MAAM,qCAAqC;AAC7E,YAAI,SAAS,KAAK,cAAc,WAAW,WAAW,WAAW,MAAM;AACvE,YAAI,CAAC;AAAQ,gBAAM,IAAI,MAAM,0BAA0B,WAAW,QAAQ;AAC1E,mBAAW,KAAK,qBAAqB,WAAW,kBAAkB,SAA6B,WAAW;AAC1G,mBAAW,KAAK,cAAc,MAAwB;AACtD,YAAI,WAAW,KAAK,UAAU;AAAM,qBAAW,KAAK,aAAa;AAAA,MAClE;AACA,WAAK,aAAa,SAAS;AAG3B,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAI,YAAY,MAAM,WAAW;AACjC,YAAI,CAAC;AAAW,gBAAM,IAAI,MAAM,kCAAkC;AAClE,YAAI,OAAO,IAAI,UAAU,SAAS;AAClC,aAAK,WAAW,MAAM,QAAQ,KAAK;AACnC,aAAK,aAAa,MAAM,UAAU;AAClC,aAAK,cAAc,MAAM,WAAW;AACpC,aAAK,YAAY,MAAM,WAAW;AAClC,YAAI,KAAK,WAAW;AACnB,eAAK,SAAS,MAAM,UAAU;AAC9B,eAAK,UAAU,MAAM,UAAU;AAAA,QAChC;AACA,qBAAa,OAAO,KAAK,IAAI;AAAA,MAC9B;AAGA,UAAI,MAAM,QAAQ,IAAI;AACtB,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAI,gBAAgB,MAAM,WAAW;AACrC,YAAI,CAAC;AAAe,gBAAM,IAAI,MAAM,iCAAiC;AACrE,qBAAa,WAAW,KAAK,KAAK,cAAc,OAAO,eAAe,YAAY,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACR;AAAA,IAEQ,SAAU,OAAoB,cAA4B,aAAsB,cAAoC;AAC3H,UAAI,OAAO;AACX,UAAI,YAAY;AAEhB,UAAI,aAAa;AAChB,oBAAY,MAAM,QAAQ,IAAI;AAC9B,YAAI,aAAa;AAAG,iBAAO;AAC3B,eAAO,IAAI,KAAK,SAAS;AAAA,MAC1B,OAAO;AACN,YAAI,WAAW,MAAM,WAAW;AAChC,YAAI,CAAC;AAAU,gBAAM,IAAI,MAAM,6BAA6B;AAC5D,eAAO,IAAI,KAAK,QAAQ;AACxB,YAAI;AAAc,gBAAM,gBAAgB,KAAK,OAAO,MAAM,UAAU,CAAC;AACrE,aAAK,MAAM,SAAS,MAAM,QAAQ,IAAI;AACtC,iBAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,IAAI,GAAG;AAC7C,eAAK,MAAM,CAAC,IAAI,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AAEvD,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG;AAC/C,eAAK,YAAY,KAAK,aAAa,cAAc,MAAM,QAAQ,IAAI,CAAC,CAAC;AACtE,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG;AAC/C,eAAK,YAAY,KAAK,aAAa,qBAAqB,MAAM,QAAQ,IAAI,CAAC,CAAC;AAC7E,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG;AAC/C,eAAK,YAAY,KAAK,aAAa,gBAAgB,MAAM,QAAQ,IAAI,CAAC,CAAC;AACxE,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG;AAC/C,eAAK,YAAY,KAAK,aAAa,mBAAmB,MAAM,QAAQ,IAAI,CAAC,CAAC;AAE3E,oBAAY,MAAM,QAAQ,IAAI;AAAA,MAC/B;AAEA,eAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AACnC,YAAI,YAAY,MAAM,QAAQ,IAAI;AAClC,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,MAAM;AACzD,cAAI,OAAO,MAAM,cAAc;AAC/B,cAAI,CAAC;AACJ,kBAAM,IAAI,MAAM,kCAAkC;AACnD,cAAI,aAAa,KAAK,eAAe,OAAO,cAAc,MAAM,WAAW,MAAM,YAAY;AAC7F,cAAI;AAAY,iBAAK,cAAc,WAAW,MAAM,UAAU;AAAA,QAC/D;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,IAEQ,eAAgB,OAAoB,cAA4B,MAAY,WAAmB,gBAA2C,cAA0C;AAC3L,UAAI,QAAQ,KAAK;AAEjB,UAAI,QAAQ,MAAM,SAAS;AAC3B,YAAM,QAAQ,QAAQ,MAAM,IAAI,MAAM,cAAc,IAAI;AACxD,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,kCAAkC;AAC7D,cAAS,QAAQ,GAA0B;AAAA,QAC1C,KAAK,eAAe,QAAQ;AAC3B,cAAI,QAAQ,QAAQ,OAAO,IAAI,MAAM,cAAc,IAAI;AACvD,gBAAM,SAAS,QAAQ,OAAO,IAAI,MAAM,UAAU,IAAI;AACtD,gBAAM,YAAY,QAAQ,OAAO,IAAI,KAAK,aAAa,KAAK,IAAI;AAChE,cAAI,YAAY,QAAQ,QAAQ,IAAI,MAAM,UAAU,IAAI;AACxD,cAAI,IAAI,MAAM,UAAU;AACxB,cAAI,IAAI,MAAM,UAAU;AACxB,cAAI,SAAS,MAAM,UAAU;AAC7B,cAAI,SAAS,MAAM,UAAU;AAC7B,cAAI,QAAQ,MAAM,UAAU;AAC5B,cAAI,SAAS,MAAM,UAAU;AAE7B,cAAI,CAAC;AAAM,mBAAO;AAClB,cAAI,SAAS,KAAK,iBAAiB,oBAAoB,MAAM,MAAM,MAAM,QAAQ;AACjF,cAAI,CAAC;AAAQ,mBAAO;AACpB,iBAAO,OAAO;AACd,iBAAO,IAAI,IAAI;AACf,iBAAO,IAAI,IAAI;AACf,iBAAO,SAAS;AAChB,iBAAO,SAAS;AAChB,iBAAO,WAAW;AAClB,iBAAO,QAAQ,QAAQ;AACvB,iBAAO,SAAS,SAAS;AACzB,gBAAM,gBAAgB,OAAO,OAAO,KAAK;AACzC,iBAAO,WAAW;AAClB,cAAI,YAAY;AAAM,mBAAO,aAAa;AAC1C,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe,aAAa;AAChC,cAAI,WAAW,KAAK,aAAa,QAAQ,QAAQ,OAAO,CAAC;AACzD,cAAI,QAAQ,eAAe,MAAM,UAAU,IAAI;AAE/C,cAAI,MAAM,KAAK,iBAAiB,yBAAyB,MAAM,IAAI;AACnE,cAAI,CAAC;AAAK,mBAAO;AACjB,cAAI,sBAAsB,SAAS;AACnC,cAAI,WAAW,SAAS;AACxB,cAAI,QAAQ,SAAS;AACrB,cAAI;AAAc,kBAAM,gBAAgB,IAAI,OAAO,KAAK;AACxD,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe,MAAM;AACzB,cAAI,QAAQ,QAAQ,OAAO,IAAI,MAAM,cAAc,IAAI;AACvD,gBAAM,SAAS,QAAQ,OAAO,IAAI,MAAM,UAAU,IAAI;AACtD,gBAAM,YAAY,QAAQ,OAAO,IAAI,KAAK,aAAa,KAAK,IAAI;AAChE,gBAAM,aAAa,MAAM,QAAQ,IAAI;AACrC,gBAAM,WAAW,KAAK,aAAa,QAAQ,QAAQ,QAAQ,CAAC;AAC5D,gBAAM,MAAM,KAAK,eAAe,OAAO,SAAS,QAAQ,CAAC;AACzD,gBAAM,YAAY,KAAK,eAAe,QAAQ,SAAS,SAAS,aAAa,KAAK,CAAC;AACnF,cAAI,QAAkB,CAAC;AACvB,cAAI,QAAQ,GAAG,SAAS;AACxB,cAAI,cAAc;AACjB,oBAAQ,KAAK,eAAe,OAAO,MAAM,QAAQ,IAAI,CAAC;AACtD,oBAAQ,MAAM,UAAU;AACxB,qBAAS,MAAM,UAAU;AAAA,UAC1B;AAEA,cAAI,CAAC;AAAM,mBAAO;AAClB,cAAI,OAAO,KAAK,iBAAiB,kBAAkB,MAAM,MAAM,MAAM,QAAQ;AAC7E,cAAI,CAAC;AAAM,mBAAO;AAClB,eAAK,OAAO;AACZ,gBAAM,gBAAgB,KAAK,OAAO,KAAK;AACvC,eAAK,QAAQ,SAAS;AACtB,eAAK,WAAW,SAAS;AACzB,eAAK,sBAAsB,SAAS;AACpC,eAAK,YAAY;AACjB,eAAK,YAAY;AACjB,cAAI,YAAY;AAAM,iBAAK,aAAa;AACxC,eAAK,aAAa,cAAc;AAChC,eAAK,WAAW;AAChB,cAAI,cAAc;AACjB,iBAAK,QAAQ;AACb,iBAAK,QAAQ,QAAQ;AACrB,iBAAK,SAAS,SAAS;AAAA,UACxB;AACA,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe,YAAY;AAC/B,gBAAM,QAAQ,QAAQ,OAAO,IAAI,MAAM,cAAc,IAAI;AACzD,cAAI,QAAQ;AAAM,kBAAM,IAAI,MAAM,sCAAsC;AACxE,gBAAM,SAAS,QAAQ,OAAO,IAAI,MAAM,UAAU,IAAI;AACtD,gBAAM,YAAY,QAAQ,OAAO,IAAI,KAAK,aAAa,KAAK,IAAI;AAChE,gBAAM,oBAAoB,QAAQ,QAAQ;AAC1C,gBAAM,YAAY,MAAM,QAAQ,IAAI;AACpC,gBAAM,SAAS,MAAM,cAAc;AACnC,cAAI,QAAQ,GAAG,SAAS;AACxB,cAAI,cAAc;AACjB,oBAAQ,MAAM,UAAU;AACxB,qBAAS,MAAM,UAAU;AAAA,UAC1B;AAEA,cAAI,OAAO,KAAK,iBAAiB,kBAAkB,MAAM,MAAM,MAAM,QAAQ;AAC7E,cAAI,CAAC;AAAM,mBAAO;AAClB,eAAK,OAAO;AACZ,gBAAM,gBAAgB,KAAK,OAAO,KAAK;AACvC,eAAK,WAAW;AAChB,cAAI,cAAc;AACjB,iBAAK,QAAQ,QAAQ;AACrB,iBAAK,SAAS,SAAS;AAAA,UACxB;AACA,eAAK,aAAa,KAAK,IAAI,WAAW,MAAM,WAAW,WAAW,QAAQ,gBAAgB,CAAC;AAC3F,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe,MAAM;AACzB,gBAAMC,WAAU,QAAQ,OAAO;AAC/B,gBAAM,iBAAiB,QAAQ,OAAO;AACtC,gBAAM,WAAW,KAAK,aAAa,QAAQ,QAAQ,OAAO,CAAC;AAE3D,gBAAM,UAAU,MAAM,SAAS,SAAS,SAAS,GAAG,CAAC;AACrD,mBAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAAI,GAAG;AAC1C,oBAAQ,CAAC,IAAI,MAAM,UAAU,IAAI;AAClC,gBAAM,QAAQ,eAAe,MAAM,UAAU,IAAI;AAEjD,gBAAM,OAAO,KAAK,iBAAiB,kBAAkB,MAAM,IAAI;AAC/D,cAAI,CAAC;AAAM,mBAAO;AAClB,eAAK,SAASA;AACd,eAAK,gBAAgB;AACrB,eAAK,sBAAsB,SAAS;AACpC,eAAK,WAAW,SAAS;AACzB,eAAK,QAAQ,SAAS;AACtB,eAAK,UAAU;AACf,cAAI;AAAc,kBAAM,gBAAgB,KAAK,OAAO,KAAK;AACzD,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe,OAAO;AAC1B,gBAAM,WAAW,MAAM,UAAU;AACjC,gBAAM,IAAI,MAAM,UAAU;AAC1B,gBAAM,IAAI,MAAM,UAAU;AAC1B,gBAAM,QAAQ,eAAe,MAAM,UAAU,IAAI;AAEjD,gBAAM,QAAQ,KAAK,iBAAiB,mBAAmB,MAAM,IAAI;AACjE,cAAI,CAAC;AAAO,mBAAO;AACnB,gBAAM,IAAI,IAAI;AACd,gBAAM,IAAI,IAAI;AACd,gBAAM,WAAW;AACjB,cAAI;AAAc,kBAAM,gBAAgB,MAAM,OAAO,KAAK;AAC1D,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe,UAAU;AAC7B,gBAAM,eAAe,MAAM,QAAQ,IAAI;AACvC,gBAAM,WAAW,KAAK,aAAa,QAAQ,QAAQ,OAAO,CAAC;AAC3D,cAAI,QAAQ,eAAe,MAAM,UAAU,IAAI;AAE/C,cAAI,OAAO,KAAK,iBAAiB,sBAAsB,MAAM,IAAI;AACjE,cAAI,CAAC;AAAM,mBAAO;AAClB,eAAK,UAAU,aAAa,MAAM,YAAY;AAC9C,eAAK,sBAAsB,SAAS;AACpC,eAAK,WAAW,SAAS;AACzB,eAAK,QAAQ,SAAS;AACtB,cAAI;AAAc,kBAAM,gBAAgB,KAAK,OAAO,KAAK;AACzD,iBAAO;AAAA,QACR;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,IAEQ,aAAc,OAAoB;AACzC,UAAI,WAAW,IAAI,SAAS,MAAM,QAAQ,IAAI,CAAC;AAC/C,eAAS,QAAQ,MAAM,QAAQ,IAAI;AACnC,eAAS,SAAS,MAAM,QAAQ,IAAI;AACpC,eAAS,aAAa,MAAM,QAAQ,IAAI;AACxC,aAAO;AAAA,IACR;AAAA,IAEQ,aAAc,OAAoB,UAA6B;AACtE,YAAM,QAAQ,KAAK;AACnB,YAAM,cAAc,MAAM,QAAQ,IAAI;AACtC,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,SAAS,eAAe;AACjC,UAAI,CAAC,UAAU;AACd,iBAAS,WAAW,KAAK,eAAe,OAAO,SAAS,QAAQ,KAAK;AACrE,eAAO;AAAA,MACR;AACA,UAAI,UAAU,IAAI,MAAc;AAChC,UAAI,aAAa,IAAI,MAAc;AACnC,eAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACrC,YAAI,YAAY,MAAM,QAAQ,IAAI;AAClC,mBAAW,KAAK,SAAS;AACzB,iBAAS,KAAK,GAAG,KAAK,WAAW,MAAM;AACtC,qBAAW,KAAK,MAAM,QAAQ,IAAI,CAAC;AACnC,kBAAQ,KAAK,MAAM,UAAU,IAAI,KAAK;AACtC,kBAAQ,KAAK,MAAM,UAAU,IAAI,KAAK;AACtC,kBAAQ,KAAK,MAAM,UAAU,CAAC;AAAA,QAC/B;AAAA,MACD;AACA,eAAS,WAAW,MAAM,aAAa,OAAO;AAC9C,eAAS,QAAQ;AACjB,aAAO;AAAA,IACR;AAAA,IAEQ,eAAgB,OAAoB,GAAW,OAAyB;AAC/E,UAAI,QAAQ,IAAI,MAAc,CAAC;AAC/B,UAAI,SAAS,GAAG;AACf,iBAAS,IAAI,GAAG,IAAI,GAAG;AACtB,gBAAM,CAAC,IAAI,MAAM,UAAU;AAAA,MAC7B,OAAO;AACN,iBAAS,IAAI,GAAG,IAAI,GAAG;AACtB,gBAAM,CAAC,IAAI,MAAM,UAAU,IAAI;AAAA,MACjC;AACA,aAAO;AAAA,IACR;AAAA,IAEQ,eAAgB,OAAoB,GAAqB;AAChE,UAAI,QAAQ,IAAI,MAAc,CAAC;AAC/B,eAAS,IAAI,GAAG,IAAI,GAAG;AACtB,cAAM,CAAC,IAAI,MAAM,QAAQ,IAAI;AAC9B,aAAO;AAAA,IACR;AAAA,IAEQ,cAAe,OAAoB,MAAc,cAAuC;AAC/F,YAAM,QAAQ,IAAI;AAClB,UAAI,YAAY,IAAI,MAAgB;AACpC,UAAI,QAAQ,KAAK;AAGjB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,YAAI,YAAY,MAAM,QAAQ,IAAI;AAClC,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,MAAM;AACzD,cAAI,eAAe,MAAM,SAAS;AAClC,cAAI,aAAa,MAAM,QAAQ,IAAI;AACnC,cAAI,YAAY,aAAa;AAC7B,kBAAQ,cAAc;AAAA,YACrB,KAAK,iBAAiB;AACrB,kBAAI,WAAW,IAAI,mBAAmB,YAAY,SAAS;AAC3D,uBAAS,QAAQ,GAAG,QAAQ,YAAY;AACvC,yBAAS,SAAS,OAAO,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC;AAClE,wBAAU,KAAK,QAAQ;AACvB;AAAA,YACD;AAAA,YACA,KAAK,WAAW;AACf,kBAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,kBAAI,WAAW,IAAI,aAAa,YAAY,aAAa,SAAS;AAElE,kBAAI,OAAO,MAAM,UAAU;AAC3B,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AAEnC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,GAAG,GAAG,GAAG,CAAC;AACzC,oBAAI,SAAS;AAAW;AAExB,oBAAI,QAAQ,MAAM,UAAU;AAC5B,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AAEpC,wBAAQ,MAAM,SAAS,GAAG;AAAA,kBACzB,KAAK;AACJ,6BAAS,WAAW,KAAK;AACzB;AAAA,kBACD,KAAK;AACJ,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AAAA,gBACtE;AACA,uBAAO;AACP,oBAAI;AACJ,oBAAI;AACJ,oBAAI;AACJ,oBAAI;AAAA,cACL;AACA,wBAAU,KAAK,QAAQ;AACvB;AAAA,YACD;AAAA,YACA,KAAK,UAAU;AACd,kBAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,kBAAI,WAAW,IAAI,YAAY,YAAY,aAAa,SAAS;AAEjE,kBAAI,OAAO,MAAM,UAAU;AAC3B,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AAEnC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,GAAG,GAAG,CAAC;AACtC,oBAAI,SAAS;AAAW;AAExB,oBAAI,QAAQ,MAAM,UAAU;AAC5B,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AAEpC,wBAAQ,MAAM,SAAS,GAAG;AAAA,kBACzB,KAAK;AACJ,6BAAS,WAAW,KAAK;AACzB;AAAA,kBACD,KAAK;AACJ,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AAAA,gBACtE;AACA,uBAAO;AACP,oBAAI;AACJ,oBAAI;AACJ,oBAAI;AAAA,cACL;AACA,wBAAU,KAAK,QAAQ;AACvB;AAAA,YACD;AAAA,YACA,KAAK,YAAY;AAChB,kBAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,kBAAI,WAAW,IAAI,cAAc,YAAY,aAAa,SAAS;AAEnE,kBAAI,OAAO,MAAM,UAAU;AAC3B,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,kBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,kBAAI,KAAK,MAAM,iBAAiB,IAAI;AAEpC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE;AACrD,oBAAI,SAAS;AAAW;AACxB,oBAAI,QAAQ,MAAM,UAAU;AAC5B,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,MAAM,MAAM,iBAAiB,IAAI;AACrC,oBAAI,MAAM,MAAM,iBAAiB,IAAI;AACrC,oBAAI,MAAM,MAAM,iBAAiB,IAAI;AAErC,wBAAQ,MAAM,SAAS,GAAG;AAAA,kBACzB,KAAK;AACJ,6BAAS,WAAW,KAAK;AACzB;AAAA,kBACD,KAAK;AACJ,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,IAAI,KAAK,CAAC;AACtE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,IAAI,KAAK,CAAC;AACtE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,IAAI,KAAK,CAAC;AAAA,gBACxE;AACA,uBAAO;AACP,oBAAI;AACJ,oBAAI;AACJ,oBAAI;AACJ,oBAAI;AACJ,qBAAK;AACL,qBAAK;AACL,qBAAK;AAAA,cACN;AACA,wBAAU,KAAK,QAAQ;AACvB;AAAA,YACD;AAAA,YACA,KAAK,WAAW;AACf,kBAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,kBAAI,WAAW,IAAI,aAAa,YAAY,aAAa,SAAS;AAElE,kBAAI,OAAO,MAAM,UAAU;AAC3B,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,IAAI,MAAM,iBAAiB,IAAI;AACnC,kBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,kBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,kBAAI,KAAK,MAAM,iBAAiB,IAAI;AAEpC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE;AAClD,oBAAI,SAAS;AAAW;AACxB,oBAAI,QAAQ,MAAM,UAAU;AAC5B,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,oBAAI,MAAM,MAAM,iBAAiB,IAAI;AACrC,oBAAI,MAAM,MAAM,iBAAiB,IAAI;AACrC,oBAAI,MAAM,MAAM,iBAAiB,IAAI;AAErC,wBAAQ,MAAM,SAAS,GAAG;AAAA,kBACzB,KAAK;AACJ,6BAAS,WAAW,KAAK;AACzB;AAAA,kBACD,KAAK;AACJ,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AACpE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,IAAI,KAAK,CAAC;AACtE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,IAAI,KAAK,CAAC;AACtE,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,IAAI,KAAK,CAAC;AAAA,gBACxE;AACA,uBAAO;AACP,oBAAI;AACJ,oBAAI;AACJ,oBAAI;AACJ,qBAAK;AACL,qBAAK;AACL,qBAAK;AAAA,cACN;AACA,wBAAU,KAAK,QAAQ;AACvB;AAAA,YACD;AAAA,YACA,KAAK,YAAY;AAChB,kBAAI,WAAW,IAAI,cAAc,YAAY,MAAM,QAAQ,IAAI,GAAG,SAAS;AAC3E,kBAAI,OAAO,MAAM,UAAU,GAAG,IAAI,MAAM,iBAAiB,IAAI;AAC7D,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,CAAC;AAChC,oBAAI,SAAS;AAAW;AACxB,oBAAI,QAAQ,MAAM,UAAU;AAC5B,oBAAI,KAAK,MAAM,iBAAiB,IAAI;AACpC,wBAAQ,MAAM,SAAS,GAAG;AAAA,kBACzB,KAAK;AACJ,6BAAS,WAAW,KAAK;AACzB;AAAA,kBACD,KAAK;AACJ,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,IAAI,CAAC;AAAA,gBACtE;AACA,uBAAO;AACP,oBAAI;AAAA,cACL;AACA,wBAAU,KAAK,QAAQ;AAAA,YACxB;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,YAAI,YAAY,MAAM,QAAQ,IAAI;AAClC,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,MAAM;AACzD,cAAI,OAAO,MAAM,SAAS,GAAG,aAAa,MAAM,QAAQ,IAAI;AAC5D,cAAI,QAAQ,cAAc;AACzB,gBAAI,WAAW,IAAI,gBAAgB,YAAY,SAAS;AACxD,qBAAS,QAAQ,GAAG,QAAQ,YAAY,SAAS;AAChD,uBAAS,SAAS,OAAO,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC;AAAA,YAC7D;AACA,sBAAU,KAAK,QAAQ;AACvB;AAAA,UACD;AACA,cAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,kBAAQ,MAAM;AAAA,YACb,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,eAAe,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAC9F;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,kBAAkB,YAAY,aAAa,SAAS,GAAG,KAAK,CAAC;AACrG;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,mBAAmB,YAAY,aAAa,SAAS,GAAG,KAAK,CAAC;AACtG;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,mBAAmB,YAAY,aAAa,SAAS,GAAG,KAAK,CAAC;AACtG;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,cAAc,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAC7F;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,eAAe,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAC9F;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,eAAe,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAC9F;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,cAAc,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAC7F;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,eAAe,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAC9F;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,eAAe,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC;AAAA,UAChG;AAAA,QACD;AAAA,MACD;AAGA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,YAAI,QAAQ,MAAM,QAAQ,IAAI,GAAG,aAAa,MAAM,QAAQ,IAAI,GAAG,YAAY,aAAa;AAC5F,YAAI,WAAW,IAAI,qBAAqB,YAAY,MAAM,QAAQ,IAAI,GAAG,KAAK;AAC9E,YAAI,QAAQ,MAAM,SAAS;AAC3B,YAAI,OAAO,MAAM,UAAU,GAAG,OAAO,QAAQ,MAAM,KAAM,QAAQ,MAAM,IAAI,MAAM,UAAU,IAAI,IAAK;AACpG,YAAI,YAAY,QAAQ,MAAM,IAAI,MAAM,UAAU,IAAI,QAAQ;AAC9D,iBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,mBAAS,SAAS,OAAO,MAAM,KAAK,WAAW,QAAQ,MAAM,IAAI,IAAI,KAAK,QAAQ,OAAO,IAAI,QAAQ,OAAO,CAAC;AAC7G,cAAI,SAAS;AAAW;AACxB,kBAAQ,MAAM,SAAS;AACvB,gBAAM,QAAQ,MAAM,UAAU,GAAG,QAAQ,QAAQ,MAAM,KAAM,QAAQ,MAAM,IAAI,MAAM,UAAU,IAAI,IAAK;AACxG,gBAAM,aAAa,QAAQ,MAAM,IAAI,MAAM,UAAU,IAAI,QAAQ;AACjE,eAAK,QAAQ,OAAO,GAAG;AACtB,qBAAS,WAAW,KAAK;AAAA,UAC1B,YAAY,QAAQ,QAAQ,GAAG;AAC9B,sBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,KAAK,MAAM,CAAC;AACxE,sBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,UAAU,WAAW,KAAK;AAAA,UACvF;AACA,iBAAO;AACP,gBAAM;AACN,qBAAW;AAAA,QACZ;AACA,kBAAU,KAAK,QAAQ;AAAA,MACxB;AAGA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,YAAI,QAAQ,MAAM,QAAQ,IAAI,GAAG,aAAa,MAAM,QAAQ,IAAI,GAAG,YAAY,aAAa;AAC5F,YAAI,WAAW,IAAI,4BAA4B,YAAY,MAAM,QAAQ,IAAI,GAAG,KAAK;AACrF,YAAI,OAAO,MAAM,UAAU,GAAG,YAAY,MAAM,UAAU,GAAG,OAAO,MAAM,UAAU,GAAG,OAAO,MAAM,UAAU,GAC7G,YAAY,MAAM,UAAU,GAAG,YAAY,MAAM,UAAU,GAAG,YAAY,MAAM,UAAU;AAC3F,iBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,mBAAS,SAAS,OAAO,MAAM,WAAW,MAAM,MAAM,WAAW,WAAW,SAAS;AACrF,cAAI,SAAS;AAAW;AACxB,cAAI,QAAQ,MAAM,UAAU,GAAG,aAAa,MAAM,UAAU,GAAG,QAAQ,MAAM,UAAU,GAAG,QAAQ,MAAM,UAAU,GACjH,aAAa,MAAM,UAAU,GAAG,aAAa,MAAM,UAAU,GAAG,aAAa,MAAM,UAAU;AAC9F,kBAAQ,MAAM,SAAS,GAAG;AAAA,YACzB,KAAK;AACJ,uBAAS,WAAW,KAAK;AACzB;AAAA,YACD,KAAK;AACJ,wBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AACpF,wBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AAC1E,wBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AAC1E,wBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AACpF,wBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AACpF,wBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AAAA,UACtF;AACA,iBAAO;AACP,sBAAY;AACZ,iBAAO;AACP,iBAAO;AACP,sBAAY;AACZ,sBAAY;AACZ,sBAAY;AAAA,QACb;AACA,kBAAU,KAAK,QAAQ;AAAA,MACxB;AAGA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,YAAI,QAAQ,MAAM,QAAQ,IAAI;AAC9B,YAAI,OAAO,aAAa,gBAAgB,KAAK;AAC7C,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,MAAM;AACzD,gBAAM,OAAO,MAAM,SAAS,GAAG,aAAa,MAAM,QAAQ,IAAI,GAAG,cAAc,MAAM,QAAQ,IAAI;AACjG,kBAAQ,MAAM;AAAA,YACb,KAAK;AACJ,wBACE,KAAK;AAAA,gBAAc;AAAA,gBAAO,IAAI,+BAA+B,YAAY,aAAa,KAAK;AAAA,gBAC3F,KAAK,gCAAqC,QAAQ;AAAA,cAAC,CAAC;AACtD;AAAA,YACD,KAAK;AACJ,wBACE,KAAK;AAAA,gBAAc;AAAA,gBAAO,IAAI,8BAA8B,YAAY,aAAa,KAAK;AAAA,gBAC1F,KAAK,iCAAqC,KAAK,+BAAmC,QAAQ;AAAA,cAAC,CAAC;AAC9F;AAAA,YACD,KAAK;AACJ,kBAAI,WAAW,IAAI,0BAA0B,YAAY,aAAa,KAAK;AAC3E,kBAAI,OAAO,MAAM,UAAU,GAAG,YAAY,MAAM,UAAU,GAAG,OAAO,MAAM,UAAU,GAAG,OAAO,MAAM,UAAU;AAC9G,uBAAS,QAAQ,GAAG,SAAS,GAAG,YAAY,SAAS,cAAc,IAAI,KAAK,SAAS;AACpF,yBAAS,SAAS,OAAO,MAAM,WAAW,MAAM,IAAI;AACpD,oBAAI,SAAS;AAAW;AACxB,oBAAI,QAAQ,MAAM,UAAU,GAAG,aAAa,MAAM,UAAU,GAAG,QAAQ,MAAM,UAAU,GACtF,QAAQ,MAAM,UAAU;AACzB,wBAAQ,MAAM,SAAS,GAAG;AAAA,kBACzB,KAAK;AACJ,6BAAS,WAAW,KAAK;AACzB;AAAA,kBACD,KAAK;AACJ,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AACpF,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AAC1E,8BAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AAAA,gBAC5E;AACA,uBAAO;AACP,4BAAY;AACZ,uBAAO;AACP,uBAAO;AAAA,cACR;AACA,wBAAU,KAAK,QAAQ;AAAA,UACzB;AAAA,QACD;AAAA,MACD;AAGA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,cAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI;AACpC,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,MAAM;AACzD,gBAAM,OAAO,MAAM,SAAS,GAAG,aAAa,MAAM,QAAQ,IAAI;AAC9D,cAAI,QAAQ,eAAe;AAC1B,kBAAM,WAAW,IAAI,+BAA+B,YAAY,KAAK;AACrE,qBAAS,QAAQ,GAAG,QAAQ,YAAY;AACvC,uBAAS,SAAS,OAAO,MAAM,UAAU,CAAC;AAC3C,sBAAU,KAAK,QAAQ;AACvB;AAAA,UACD;AACA,gBAAM,cAAc,MAAM,QAAQ,IAAI;AACtC,kBAAQ,MAAM;AAAA,YACb,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,iCAAiC,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AAC5G;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,kCAAkC,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AAC7G;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,iCAAiC,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AAC5G;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,8BAA8B,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AACzG;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,8BAA8B,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AACzG;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,iCAAiC,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AAC5G;AAAA,YACD,KAAK;AACJ,wBAAU,KAAK,cAAc,OAAO,IAAI,6BAA6B,YAAY,aAAa,KAAK,GAAG,CAAC,CAAC;AAAA,UAC1G;AAAA,QACD;AAAA,MACD;AAGA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI,GAAG,IAAI,GAAG,KAAK;AACpD,YAAI,OAAO,aAAa,MAAM,MAAM,QAAQ,IAAI,CAAC;AACjD,iBAAS,KAAK,GAAG,KAAK,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,MAAM;AACzD,cAAI,YAAY,MAAM,QAAQ,IAAI;AAClC,mBAAS,MAAM,GAAG,MAAM,MAAM,QAAQ,IAAI,GAAG,MAAM,KAAK,OAAO;AAC9D,gBAAI,iBAAiB,MAAM,cAAc;AACzC,gBAAI,CAAC;AAAgB,oBAAM,IAAI,MAAM,kCAAkC;AACvE,gBAAI,aAAa,KAAK,cAAc,WAAW,cAAc;AAC7D,gBAAI,eAAe,MAAM,SAAS;AAClC,gBAAI,aAAa,MAAM,QAAQ,IAAI;AACnC,gBAAI,YAAY,aAAa;AAE7B,oBAAQ,cAAc;AAAA,cACrB,KAAK,mBAAmB;AACvB,oBAAI,mBAAmB;AACvB,oBAAI,WAAW,iBAAiB;AAChC,oBAAI,WAAW,iBAAiB;AAChC,oBAAI,eAAe,WAAW,SAAS,SAAS,IAAI,IAAI,SAAS;AAGjE,oBAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,oBAAI,WAAW,IAAI,eAAe,YAAY,aAAa,WAAW,gBAAgB;AAEtF,oBAAI,OAAO,MAAM,UAAU;AAC3B,yBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,sBAAI;AACJ,sBAAI,MAAM,MAAM,QAAQ,IAAI;AAC5B,sBAAI,OAAO;AACV,6BAAS,WAAW,MAAM,cAAc,YAAY,IAAI;AAAA,uBACpD;AACJ,6BAAS,MAAM,cAAc,YAAY;AACzC,wBAAI,QAAQ,MAAM,QAAQ,IAAI;AAC9B,2BAAO;AACP,wBAAI,SAAS,GAAG;AACf,+BAAS,IAAI,OAAO,IAAI,KAAK;AAC5B,+BAAO,CAAC,IAAI,MAAM,UAAU;AAAA,oBAC9B,OAAO;AACN,+BAAS,IAAI,OAAO,IAAI,KAAK;AAC5B,+BAAO,CAAC,IAAI,MAAM,UAAU,IAAI;AAAA,oBAClC;AACA,wBAAI,CAAC,UAAU;AACd,+BAAS,IAAI,GAAG,KAAK,OAAO,QAAQ,IAAI,IAAI;AAC3C,+BAAO,CAAC,KAAK,SAAS,CAAC;AAAA,oBACzB;AAAA,kBACD;AAEA,2BAAS,SAAS,OAAO,MAAM,MAAM;AACrC,sBAAI,SAAS;AAAW;AACxB,sBAAI,QAAQ,MAAM,UAAU;AAC5B,0BAAQ,MAAM,SAAS,GAAG;AAAA,oBACzB,KAAK;AACJ,+BAAS,WAAW,KAAK;AACzB;AAAA,oBACD,KAAK;AACJ,gCAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,GAAG,GAAG,CAAC;AAAA,kBACrE;AACA,yBAAO;AAAA,gBACR;AACA,0BAAU,KAAK,QAAQ;AACvB;AAAA,cACD;AAAA,cACA,KAAK,qBAAqB;AACzB,oBAAI,WAAW,IAAI,iBAAiB,YAAY,WAAW,UAAyC;AACpG,yBAAS,QAAQ,GAAG,QAAQ,YAAY,SAAS;AAChD,sBAAI,OAAO,MAAM,UAAU;AAC3B,sBAAI,eAAe,MAAM,UAAU;AACnC,2BAAS;AAAA,oBAAS;AAAA,oBAAO;AAAA,oBAAM,mBAAmB,eAAe,EAAG;AAAA,oBAAG,gBAAgB;AAAA,oBACtF,MAAM,UAAU;AAAA,kBAAC;AAAA,gBACnB;AACA,0BAAU,KAAK,QAAQ;AACvB;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,UAAI,iBAAiB,MAAM,QAAQ,IAAI;AACvC,UAAI,iBAAiB,GAAG;AACvB,YAAI,WAAW,IAAI,kBAAkB,cAAc;AACnD,YAAI,YAAY,aAAa,MAAM;AACnC,iBAAS,IAAI,GAAG,IAAI,gBAAgB,KAAK;AACxC,cAAI,OAAO,MAAM,UAAU;AAC3B,cAAI,cAAc,MAAM,QAAQ,IAAI;AACpC,cAAI,YAAY,MAAM,SAAS,WAAW,CAAC;AAC3C,mBAAS,KAAK,YAAY,GAAG,MAAM,GAAG;AACrC,sBAAU,EAAE,IAAI;AACjB,cAAI,YAAY,MAAM,SAAS,YAAY,aAAa,CAAC;AACzD,cAAI,gBAAgB,GAAG,iBAAiB;AACxC,mBAAS,KAAK,GAAG,KAAK,aAAa,MAAM;AACxC,gBAAI,YAAY,MAAM,QAAQ,IAAI;AAElC,mBAAO,iBAAiB;AACvB,wBAAU,gBAAgB,IAAI;AAE/B,sBAAU,gBAAgB,MAAM,QAAQ,IAAI,CAAC,IAAI;AAAA,UAClD;AAEA,iBAAO,gBAAgB;AACtB,sBAAU,gBAAgB,IAAI;AAE/B,mBAAS,KAAK,YAAY,GAAG,MAAM,GAAG;AACrC,gBAAI,UAAU,EAAE,KAAK;AAAI,wBAAU,EAAE,IAAI,UAAU,EAAE,cAAc;AACpE,mBAAS,SAAS,GAAG,MAAM,SAAS;AAAA,QACrC;AACA,kBAAU,KAAK,QAAQ;AAAA,MACxB;AAGA,UAAI,aAAa,MAAM,QAAQ,IAAI;AACnC,UAAI,aAAa,GAAG;AACnB,YAAI,WAAW,IAAI,cAAc,UAAU;AAC3C,iBAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACpC,cAAI,OAAO,MAAM,UAAU;AAC3B,cAAI,YAAY,aAAa,OAAO,MAAM,QAAQ,IAAI,CAAC;AACvD,cAAI,QAAQ,IAAI,MAAM,MAAM,SAAS;AACrC,gBAAM,WAAW,MAAM,QAAQ,KAAK;AACpC,gBAAM,aAAa,MAAM,UAAU;AACnC,gBAAM,cAAc,MAAM,WAAW;AACrC,cAAI,MAAM,eAAe;AAAM,kBAAM,cAAc,UAAU;AAC7D,cAAI,MAAM,KAAK,WAAW;AACzB,kBAAM,SAAS,MAAM,UAAU;AAC/B,kBAAM,UAAU,MAAM,UAAU;AAAA,UACjC;AACA,mBAAS,SAAS,GAAG,KAAK;AAAA,QAC3B;AACA,kBAAU,KAAK,QAAQ;AAAA,MACxB;AAEA,UAAI,WAAW;AACf,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG;AAC5C,mBAAW,KAAK,IAAI,UAAU,UAAU,CAAC,EAAE,YAAY,CAAC;AACzD,aAAO,IAAI,UAAU,MAAM,WAAW,QAAQ;AAAA,IAC/C;AAAA,EACD;AAEO,MAAM,cAAN,MAAkB;AAAA,IACxB,YAAa,MAAuC,UAAU,IAAI,MAAc,GAAW,QAAgB,GAAW,SAAS,IAAI,SAAS,gBAAgB,cAAc,OAAO,KAAK,MAAM,GAAG;AAA3I;AAAuC;AAA2B;AAAA,IACtH;AAAA,IAEA,WAAoB;AACnB,aAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,IACxC;AAAA,IAEA,mBAA4B;AAC3B,aAAO,KAAK,OAAO,SAAS,KAAK,OAAO;AAAA,IACzC;AAAA,IAEA,YAAqB;AACpB,UAAI,QAAQ,KAAK,OAAO,SAAS,KAAK,KAAK;AAC3C,WAAK,SAAS;AACd,aAAO;AAAA,IACR;AAAA,IAEA,YAAqB;AACpB,UAAI,QAAQ,KAAK,OAAO,SAAS,KAAK,KAAK;AAC3C,WAAK,SAAS;AACd,aAAO;AAAA,IACR;AAAA,IAEA,QAAS,kBAA2B;AACnC,UAAI,IAAI,KAAK,SAAS;AACtB,UAAI,SAAS,IAAI;AACjB,WAAK,IAAI,QAAS,GAAG;AACpB,YAAI,KAAK,SAAS;AAClB,mBAAW,IAAI,QAAS;AACxB,aAAK,IAAI,QAAS,GAAG;AACpB,cAAI,KAAK,SAAS;AAClB,qBAAW,IAAI,QAAS;AACxB,eAAK,IAAI,QAAS,GAAG;AACpB,gBAAI,KAAK,SAAS;AAClB,uBAAW,IAAI,QAAS;AACxB,iBAAK,IAAI,QAAS,GAAG;AACpB,kBAAI,KAAK,SAAS;AAClB,yBAAW,IAAI,QAAS;AAAA,YACzB;AAAA,UACD;AAAA,QACD;AAAA,MACD;AACA,aAAO,mBAAmB,SAAW,WAAW,IAAK,EAAE,SAAS;AAAA,IACjE;AAAA,IAEA,gBAAgC;AAC/B,UAAI,QAAQ,KAAK,QAAQ,IAAI;AAC7B,aAAO,SAAS,IAAI,OAAO,KAAK,QAAQ,QAAQ,CAAC;AAAA,IAClD;AAAA,IAEA,aAA6B;AAC5B,UAAI,YAAY,KAAK,QAAQ,IAAI;AACjC,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,iBAAO;AAAA,QACR,KAAK;AACJ,iBAAO;AAAA,MACT;AACA;AACA,UAAI,QAAQ;AACZ,UAAI,YAAY;AAChB,eAAS,IAAI,GAAG,IAAI,aAAY;AAC/B,YAAI,IAAI,KAAK,iBAAiB;AAC9B,gBAAQ,KAAK,GAAG;AAAA,UACf,KAAK;AAAA,UACL,KAAK;AACJ,qBAAS,OAAO,cAAe,IAAI,OAAS,IAAI,KAAK,SAAS,IAAI,EAAK;AACvE,iBAAK;AACL;AAAA,UACD,KAAK;AACJ,qBAAS,OAAO,cAAe,IAAI,OAAS,MAAM,KAAK,SAAS,IAAI,OAAS,IAAI,KAAK,SAAS,IAAI,EAAK;AACxG,iBAAK;AACL;AAAA,UACD;AACC,qBAAS,OAAO,aAAa,CAAC;AAC9B;AAAA,QACF;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,IAEA,YAAqB;AACpB,UAAI,QAAQ,KAAK,OAAO,WAAW,KAAK,KAAK;AAC7C,WAAK,SAAS;AACd,aAAO;AAAA,IACR;AAAA,IAEA,cAAwB;AACvB,aAAO,KAAK,SAAS,KAAK;AAAA,IAC3B;AAAA,EACD;AAEA,MAAM,aAAN,MAAiB;AAAA,IAChB;AAAA,IAAuB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IAEA,YAAa,MAAsB,WAAmB,WAAmB,QAAuB,eAAwB;AACvH,WAAK,OAAO;AACZ,WAAK,YAAY;AACjB,WAAK,YAAY;AACjB,WAAK,SAAS;AACd,WAAK,kBAAkB;AAAA,IACxB;AAAA,EACD;AAEA,MAAM,WAAN,MAAe;AAAA,IACd,YAAoB,QAA8B,MAAa,WAAgD,MAAa,SAAiB,GAAG;AAA5H;AAA2C;AAA6D;AAAA,IAAsB;AAAA,EACnJ;AAEA,MAAK,iBAAL,kBAAKC,oBAAL;AAAsB,IAAAA,gCAAA;AAAQ,IAAAA,gCAAA;AAAa,IAAAA,gCAAA;AAAM,IAAAA,gCAAA;AAAY,IAAAA,gCAAA;AAAM,IAAAA,gCAAA;AAAO,IAAAA,gCAAA;AAArE,WAAAA;AAAA,KAAA;AAEL,WAAS,cAAe,OAAoB,UAA0B,OAA+B;AACpG,QAAI,OAAO,MAAM,UAAU,GAAG,QAAQ,MAAM,UAAU,IAAI;AAC1D,aAAS,QAAQ,GAAG,SAAS,GAAG,YAAY,SAAS,cAAc,IAAI,KAAK,SAAS;AACpF,eAAS,SAAS,OAAO,MAAM,KAAK;AACpC,UAAI,SAAS;AAAW;AACxB,UAAI,QAAQ,MAAM,UAAU,GAAG,SAAS,MAAM,UAAU,IAAI;AAC5D,cAAQ,MAAM,SAAS,GAAG;AAAA,QACzB,KAAK;AACJ,mBAAS,WAAW,KAAK;AACzB;AAAA,QACD,KAAK;AACJ,oBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,OAAO,QAAQ,KAAK;AAAA,MAClF;AACA,aAAO;AACP,cAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAEA,WAAS,cAAe,OAAoB,UAA0B,OAA+B;AACpG,QAAI,OAAO,MAAM,UAAU,GAAG,SAAS,MAAM,UAAU,IAAI,OAAO,SAAS,MAAM,UAAU,IAAI;AAC/F,aAAS,QAAQ,GAAG,SAAS,GAAG,YAAY,SAAS,cAAc,IAAI,KAAK,SAAS;AACpF,eAAS,SAAS,OAAO,MAAM,QAAQ,MAAM;AAC7C,UAAI,SAAS;AAAW;AACxB,UAAI,QAAQ,MAAM,UAAU,GAAG,UAAU,MAAM,UAAU,IAAI,OAAO,UAAU,MAAM,UAAU,IAAI;AAClG,cAAQ,MAAM,SAAS,GAAG;AAAA,QACzB,KAAK;AACJ,mBAAS,WAAW,KAAK;AACzB;AAAA,QACD,KAAK;AACJ,oBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,QAAQ,SAAS,KAAK;AAClF,oBAAU,OAAO,UAAU,UAAU,OAAO,GAAG,MAAM,OAAO,QAAQ,SAAS,KAAK;AAAA,MACpF;AACA,aAAO;AACP,eAAS;AACT,eAAS;AAAA,IACV;AACA,WAAO;AAAA,EACR;AAEA,WAAS,UAAW,OAAoB,UAAyB,QAAgB,OAAe,OAC/F,OAAe,OAAe,QAAgB,QAAgB,OAAe;AAC7E,aAAS,UAAU,QAAQ,OAAO,OAAO,OAAO,QAAQ,MAAM,UAAU,GAAG,MAAM,UAAU,IAAI,OAAO,MAAM,UAAU,GAAG,MAAM,UAAU,IAAI,OAAO,OAAO,MAAM;AAAA,EAClK;AAEA,MAAM,cAAc;AACpB,MAAM,iBAAiB;AACvB,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,cAAc;AACpB,MAAM,eAAe;AAErB,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,WAAW;AACjB,MAAM,aAAa;AACnB,MAAM,YAAY;AAClB,MAAM,aAAa;AAEnB,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;AAE5B,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,WAAW;AAEjB,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AACxB,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,kBAAkB;AACxB,MAAM,cAAc;AACpB,MAAM,gBAAgB;AAGtB,MAAM,gBAAgB;AACtB,MAAM,eAAe;;;AC7vCd,MAAM,iBAAN,MAAqB;AAAA;AAAA,IAG3B,OAAO;AAAA;AAAA,IAGP,OAAO;AAAA;AAAA,IAGP,OAAO;AAAA;AAAA,IAGP,OAAO;AAAA;AAAA,IAGP,gBAAgB,IAAI,MAA6B;AAAA;AAAA,IAGjD,WAAW,IAAI,MAAuB;AAAA,IAE9B,cAAc,IAAI,KAAsB,MAAM;AACrD,aAAO,MAAM,cAAc,EAAE;AAAA,IAC9B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMD,OAAQ,UAAoB,YAAqB;AAChD,UAAI,CAAC;AAAU,cAAM,IAAI,MAAM,0BAA0B;AACzD,UAAI,gBAAgB,KAAK;AACzB,UAAI,WAAW,KAAK;AACpB,UAAI,cAAc,KAAK;AACvB,UAAI,QAAQ,SAAS;AACrB,UAAI,YAAY,MAAM;AAEtB,oBAAc,SAAS;AACvB,kBAAY,QAAQ,QAAQ;AAC5B,eAAS,SAAS;AAElB,eAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AACnC,YAAI,OAAO,MAAM,CAAC;AAClB,YAAI,CAAC,KAAK,KAAK;AAAQ;AACvB,YAAI,aAAa,KAAK,cAAc;AACpC,YAAI,sBAAsB,uBAAuB;AAChD,cAAI,cAAc;AAClB,wBAAc,KAAK,WAAW;AAE9B,cAAI,UAAU,YAAY,OAAO;AACjC,cAAI,QAAQ,UAAU,YAAY,qBAAqB;AACtD,sBAAU,MAAM,cAAc,YAAY,mBAAmB;AAAA,UAC9D;AACA,mBAAS,KAAK,OAAO;AACrB,sBAAY,qBAAqB,MAAM,GAAG,YAAY,qBAAqB,SAAS,GAAG,CAAC;AAAA,QACzF;AAAA,MACD;AAEA,UAAI,YAAY;AACf,aAAK,YAAY;AAAA,MAClB,OAAO;AACN,aAAK,OAAO,OAAO;AACnB,aAAK,OAAO,OAAO;AACnB,aAAK,OAAO,OAAO;AACnB,aAAK,OAAO,OAAO;AAAA,MACpB;AAAA,IACD;AAAA,IAEA,cAAe;AACd,UAAI,OAAO,OAAO,mBAAmB,OAAO,OAAO,mBAAmB,OAAO,OAAO,mBAAmB,OAAO,OAAO;AACrH,UAAI,WAAW,KAAK;AACpB,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AAChD,YAAI,UAAU,SAAS,CAAC;AACxB,YAAI,WAAW;AACf,iBAAS,KAAK,GAAG,KAAK,QAAQ,QAAQ,KAAK,IAAI,MAAM,GAAG;AACvD,cAAI,IAAI,SAAS,EAAE;AACnB,cAAI,IAAI,SAAS,KAAK,CAAC;AACvB,iBAAO,KAAK,IAAI,MAAM,CAAC;AACvB,iBAAO,KAAK,IAAI,MAAM,CAAC;AACvB,iBAAO,KAAK,IAAI,MAAM,CAAC;AACvB,iBAAO,KAAK,IAAI,MAAM,CAAC;AAAA,QACxB;AAAA,MACD;AACA,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,OAAO;AAAA,IACb;AAAA;AAAA,IAGA,kBAAmB,GAAW,GAAW;AACxC,aAAO,KAAK,KAAK,QAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK;AAAA,IACxE;AAAA;AAAA,IAGA,sBAAuB,IAAY,IAAY,IAAY,IAAY;AACtE,UAAI,OAAO,KAAK;AAChB,UAAI,OAAO,KAAK;AAChB,UAAI,OAAO,KAAK;AAChB,UAAI,OAAO,KAAK;AAChB,UAAK,MAAM,QAAQ,MAAM,QAAU,MAAM,QAAQ,MAAM,QAAU,MAAM,QAAQ,MAAM,QAAU,MAAM,QAAQ,MAAM;AAClH,eAAO;AACR,UAAI,KAAK,KAAK,OAAO,KAAK;AAC1B,UAAI,IAAI,KAAK,OAAO,MAAM;AAC1B,UAAI,IAAI,QAAQ,IAAI;AAAM,eAAO;AACjC,UAAI,KAAK,OAAO,MAAM;AACtB,UAAI,IAAI,QAAQ,IAAI;AAAM,eAAO;AACjC,UAAI,KAAK,OAAO,MAAM,IAAI;AAC1B,UAAI,IAAI,QAAQ,IAAI;AAAM,eAAO;AACjC,WAAK,OAAO,MAAM,IAAI;AACtB,UAAI,IAAI,QAAQ,IAAI;AAAM,eAAO;AACjC,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,uBAAwB,QAAwB;AAC/C,aAAO,KAAK,OAAO,OAAO,QAAQ,KAAK,OAAO,OAAO,QAAQ,KAAK,OAAO,OAAO,QAAQ,KAAK,OAAO,OAAO;AAAA,IAC5G;AAAA;AAAA;AAAA,IAIA,cAAe,GAAW,GAAyC;AAClE,UAAI,WAAW,KAAK;AACpB,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG;AAC3C,YAAI,KAAK,qBAAqB,SAAS,CAAC,GAAG,GAAG,CAAC;AAAG,iBAAO,KAAK,cAAc,CAAC;AAC9E,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,qBAAsB,SAA0B,GAAW,GAAW;AACrE,UAAI,WAAW;AACf,UAAI,KAAK,QAAQ;AAEjB,UAAI,YAAY,KAAK;AACrB,UAAI,SAAS;AACb,eAAS,KAAK,GAAG,KAAK,IAAI,MAAM,GAAG;AAClC,YAAI,UAAU,SAAS,KAAK,CAAC;AAC7B,YAAI,QAAQ,SAAS,YAAY,CAAC;AAClC,YAAK,UAAU,KAAK,SAAS,KAAO,QAAQ,KAAK,WAAW,GAAI;AAC/D,cAAI,UAAU,SAAS,EAAE;AACzB,cAAI,WAAW,IAAI,YAAY,QAAQ,YAAY,SAAS,SAAS,IAAI,WAAW;AAAG,qBAAS,CAAC;AAAA,QAClG;AACA,oBAAY;AAAA,MACb;AACA,aAAO;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,kBAAmB,IAAY,IAAY,IAAY,IAAY;AAClE,UAAI,WAAW,KAAK;AACpB,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG;AAC3C,YAAI,KAAK,yBAAyB,SAAS,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE;AAAG,iBAAO,KAAK,cAAc,CAAC;AAC5F,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,yBAA0B,SAA0B,IAAY,IAAY,IAAY,IAAY;AACnG,UAAI,WAAW;AACf,UAAI,KAAK,QAAQ;AAEjB,UAAI,UAAU,KAAK,IAAI,WAAW,KAAK;AACvC,UAAI,OAAO,KAAK,KAAK,KAAK;AAC1B,UAAI,KAAK,SAAS,KAAK,CAAC,GAAG,KAAK,SAAS,KAAK,CAAC;AAC/C,eAAS,KAAK,GAAG,KAAK,IAAI,MAAM,GAAG;AAClC,YAAI,KAAK,SAAS,EAAE,GAAG,KAAK,SAAS,KAAK,CAAC;AAC3C,YAAI,OAAO,KAAK,KAAK,KAAK;AAC1B,YAAI,UAAU,KAAK,IAAI,WAAW,KAAK;AACvC,YAAI,OAAO,UAAU,WAAW,WAAW;AAC3C,YAAI,KAAK,OAAO,UAAU,UAAU,QAAQ;AAC5C,aAAM,KAAK,MAAM,KAAK,MAAQ,KAAK,MAAM,KAAK,QAAU,KAAK,MAAM,KAAK,MAAQ,KAAK,MAAM,KAAK,KAAM;AACrG,cAAI,KAAK,OAAO,WAAW,WAAW,QAAQ;AAC9C,eAAM,KAAK,MAAM,KAAK,MAAQ,KAAK,MAAM,KAAK,QAAU,KAAK,MAAM,KAAK,MAAQ,KAAK,MAAM,KAAK;AAAM,mBAAO;AAAA,QAC9G;AACA,aAAK;AACL,aAAK;AAAA,MACN;AACA,aAAO;AAAA,IACR;AAAA;AAAA,IAGA,WAAY,aAAoC;AAC/C,UAAI,CAAC;AAAa,cAAM,IAAI,MAAM,6BAA6B;AAC/D,UAAI,QAAQ,KAAK,cAAc,QAAQ,WAAW;AAClD,aAAO,SAAS,KAAK,OAAO,KAAK,SAAS,KAAK;AAAA,IAChD;AAAA;AAAA,IAGA,WAAY;AACX,aAAO,KAAK,OAAO,KAAK;AAAA,IACzB;AAAA;AAAA,IAGA,YAAa;AACZ,aAAO,KAAK,OAAO,KAAK;AAAA,IACzB;AAAA,EACD;;;ACxMO,MAAM,eAAN,MAAmB;AAAA,IACjB,iBAAiB,IAAI,MAAqB;AAAA,IAC1C,wBAAwB,IAAI,MAAqB;AAAA,IAEjD,eAAe,IAAI,MAAc;AAAA,IACjC,iBAAiB,IAAI,MAAe;AAAA,IACpC,YAAY,IAAI,MAAc;AAAA,IAE9B,cAAc,IAAI,KAAoB,MAAM;AACnD,aAAO,IAAI,MAAc;AAAA,IAC1B,CAAC;AAAA,IAEO,qBAAqB,IAAI,KAAoB,MAAM;AAC1D,aAAO,IAAI,MAAc;AAAA,IAC1B,CAAC;AAAA,IAEM,YAAa,eAA+C;AAClE,UAAI,WAAW;AACf,UAAI,cAAc,cAAc,UAAU;AAE1C,UAAI,UAAU,KAAK;AACnB,cAAQ,SAAS;AACjB,eAAS,IAAI,GAAG,IAAI,aAAa;AAChC,gBAAQ,CAAC,IAAI;AAEd,UAAI,YAAY,KAAK;AACrB,gBAAU,SAAS;AACnB,eAAS,IAAI,GAAG,IAAI,aAAa,IAAI,GAAG,EAAE;AACzC,kBAAU,CAAC,IAAI,aAAa,UAAU,GAAG,aAAa,UAAU,OAAO;AAExE,UAAI,YAAY,KAAK;AACrB,gBAAU,SAAS;AAEnB,aAAO,cAAc,GAAG;AAEvB,YAAI,WAAW,cAAc,GAAG,IAAI,GAAG,OAAO;AAC9C,eAAO,MAAM;AACZ;AACA,gBAAI,CAAC,UAAU,CAAC,GAAG;AAClB,kBAAI,KAAK,QAAQ,QAAQ,KAAK,GAAG,KAAK,QAAQ,CAAC,KAAK,GAAG,KAAK,QAAQ,IAAI,KAAK;AAC7E,kBAAI,MAAM,SAAS,EAAE,GAAG,MAAM,SAAS,KAAK,CAAC;AAC7C,kBAAI,MAAM,SAAS,EAAE,GAAG,MAAM,SAAS,KAAK,CAAC;AAC7C,kBAAI,MAAM,SAAS,EAAE,GAAG,MAAM,SAAS,KAAK,CAAC;AAC7C,uBAAS,MAAM,OAAO,KAAK,aAAa,MAAM,UAAU,MAAM,KAAK,KAAK,aAAa;AACpF,oBAAI,CAAC,UAAU,EAAE;AAAG;AACpB,oBAAI,IAAI,QAAQ,EAAE,KAAK;AACvB,oBAAI,KAAK,SAAS,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC;AACzC,oBAAI,aAAa,aAAa,KAAK,KAAK,KAAK,KAAK,IAAI,EAAE,GAAG;AAC1D,sBAAI,aAAa,aAAa,KAAK,KAAK,KAAK,KAAK,IAAI,EAAE,GAAG;AAC1D,wBAAI,aAAa,aAAa,KAAK,KAAK,KAAK,KAAK,IAAI,EAAE;AAAG,4BAAM;AAAA,kBAClE;AAAA,gBACD;AAAA,cACD;AACA;AAAA,YACD;AAEA,cAAI,QAAQ,GAAG;AACd,eAAG;AACF,kBAAI,CAAC,UAAU,CAAC;AAAG;AACnB;AAAA,YACD,SAAS,IAAI;AACb;AAAA,UACD;AAEA,qBAAW;AACX,cAAI;AACJ,kBAAQ,OAAO,KAAK;AAAA,QACrB;AAGA,kBAAU,KAAK,SAAS,cAAc,IAAI,KAAK,WAAW,CAAC;AAC3D,kBAAU,KAAK,QAAQ,CAAC,CAAC;AACzB,kBAAU,KAAK,SAAS,IAAI,KAAK,WAAW,CAAC;AAC7C,gBAAQ,OAAO,GAAG,CAAC;AACnB,kBAAU,OAAO,GAAG,CAAC;AACrB;AAEA,YAAI,iBAAiB,cAAc,IAAI,KAAK;AAC5C,YAAI,YAAY,KAAK,cAAc,IAAI;AACvC,kBAAU,aAAa,IAAI,aAAa,UAAU,eAAe,aAAa,UAAU,OAAO;AAC/F,kBAAU,SAAS,IAAI,aAAa,UAAU,WAAW,aAAa,UAAU,OAAO;AAAA,MACxF;AAEA,UAAI,eAAe,GAAG;AACrB,kBAAU,KAAK,QAAQ,CAAC,CAAC;AACzB,kBAAU,KAAK,QAAQ,CAAC,CAAC;AACzB,kBAAU,KAAK,QAAQ,CAAC,CAAC;AAAA,MAC1B;AAEA,aAAO;AAAA,IACR;AAAA,IAEA,UAAW,eAA8B,WAAgD;AACxF,UAAI,WAAW;AACf,UAAI,iBAAiB,KAAK;AAC1B,WAAK,YAAY,QAAQ,cAAc;AACvC,qBAAe,SAAS;AAExB,UAAI,wBAAwB,KAAK;AACjC,WAAK,mBAAmB,QAAQ,qBAAqB;AACrD,4BAAsB,SAAS;AAE/B,UAAI,iBAAiB,KAAK,mBAAmB,OAAO;AACpD,qBAAe,SAAS;AAExB,UAAI,UAAU,KAAK,YAAY,OAAO;AACtC,cAAQ,SAAS;AAGjB,UAAI,eAAe,IAAI,cAAc;AACrC,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG,KAAK,GAAG;AACpD,YAAI,KAAK,UAAU,CAAC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,KAAK,GAAG,KAAK,UAAU,IAAI,CAAC,KAAK;AACjF,YAAI,KAAK,SAAS,EAAE,GAAG,KAAK,SAAS,KAAK,CAAC;AAC3C,YAAI,KAAK,SAAS,EAAE,GAAG,KAAK,SAAS,KAAK,CAAC;AAC3C,YAAI,KAAK,SAAS,EAAE,GAAG,KAAK,SAAS,KAAK,CAAC;AAG3C,YAAI,SAAS;AACb,YAAI,gBAAgB,IAAI;AACvB,cAAI,IAAI,QAAQ,SAAS;AACzB,cAAI,WAAW,aAAa,QAAQ,QAAQ,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,IAAI,EAAE;AACtG,cAAI,WAAW,aAAa,QAAQ,IAAI,IAAI,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;AAC1F,cAAI,YAAY,eAAe,YAAY,aAAa;AACvD,oBAAQ,KAAK,EAAE;AACf,oBAAQ,KAAK,EAAE;AACf,2BAAe,KAAK,EAAE;AACtB,qBAAS;AAAA,UACV;AAAA,QACD;AAGA,YAAI,CAAC,QAAQ;AACZ,cAAI,QAAQ,SAAS,GAAG;AACvB,2BAAe,KAAK,OAAO;AAC3B,kCAAsB,KAAK,cAAc;AAAA,UAC1C,OAAO;AACN,iBAAK,YAAY,KAAK,OAAO;AAC7B,iBAAK,mBAAmB,KAAK,cAAc;AAAA,UAC5C;AACA,oBAAU,KAAK,YAAY,OAAO;AAClC,kBAAQ,SAAS;AACjB,kBAAQ,KAAK,EAAE;AACf,kBAAQ,KAAK,EAAE;AACf,kBAAQ,KAAK,EAAE;AACf,kBAAQ,KAAK,EAAE;AACf,kBAAQ,KAAK,EAAE;AACf,kBAAQ,KAAK,EAAE;AACf,2BAAiB,KAAK,mBAAmB,OAAO;AAChD,yBAAe,SAAS;AACxB,yBAAe,KAAK,EAAE;AACtB,yBAAe,KAAK,EAAE;AACtB,yBAAe,KAAK,EAAE;AACtB,wBAAc,aAAa,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AACzD,yBAAe;AAAA,QAChB;AAAA,MACD;AAEA,UAAI,QAAQ,SAAS,GAAG;AACvB,uBAAe,KAAK,OAAO;AAC3B,8BAAsB,KAAK,cAAc;AAAA,MAC1C;AAGA,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,IAAI,GAAG,KAAK;AACtD,yBAAiB,sBAAsB,CAAC;AACxC,YAAI,eAAe,UAAU;AAAG;AAChC,YAAI,aAAa,eAAe,CAAC;AACjC,YAAI,YAAY,eAAe,eAAe,SAAS,CAAC;AAExD,kBAAU,eAAe,CAAC;AAC1B,YAAI,IAAI,QAAQ,SAAS;AACzB,YAAI,YAAY,QAAQ,CAAC,GAAG,YAAY,QAAQ,IAAI,CAAC;AACrD,YAAI,QAAQ,QAAQ,IAAI,CAAC,GAAG,QAAQ,QAAQ,IAAI,CAAC;AACjD,YAAI,SAAS,QAAQ,CAAC,GAAG,SAAS,QAAQ,CAAC;AAC3C,YAAI,UAAU,QAAQ,CAAC,GAAG,UAAU,QAAQ,CAAC;AAC7C,YAAI,UAAU,aAAa,QAAQ,WAAW,WAAW,OAAO,OAAO,QAAQ,MAAM;AAErF,iBAAS,KAAK,GAAG,KAAK,GAAG,MAAM;AAC9B,cAAI,MAAM;AAAG;AACb,cAAI,eAAe,sBAAsB,EAAE;AAC3C,cAAI,aAAa,UAAU;AAAG;AAC9B,cAAI,kBAAkB,aAAa,CAAC;AACpC,cAAI,mBAAmB,aAAa,CAAC;AACrC,cAAI,iBAAiB,aAAa,CAAC;AAEnC,cAAI,YAAY,eAAe,EAAE;AACjC,cAAI,KAAK,UAAU,UAAU,SAAS,CAAC,GAAG,KAAK,UAAU,UAAU,SAAS,CAAC;AAE7E,cAAI,mBAAmB,cAAc,oBAAoB;AAAW;AACpE,cAAI,WAAW,aAAa,QAAQ,WAAW,WAAW,OAAO,OAAO,IAAI,EAAE;AAC9E,cAAI,WAAW,aAAa,QAAQ,IAAI,IAAI,QAAQ,QAAQ,SAAS,OAAO;AAC5E,cAAI,YAAY,WAAW,YAAY,SAAS;AAC/C,sBAAU,SAAS;AACnB,yBAAa,SAAS;AACtB,oBAAQ,KAAK,EAAE;AACf,oBAAQ,KAAK,EAAE;AACf,2BAAe,KAAK,cAAc;AAClC,wBAAY;AACZ,wBAAY;AACZ,oBAAQ;AACR,oBAAQ;AACR,iBAAK;AAAA,UACN;AAAA,QACD;AAAA,MACD;AAGA,eAAS,IAAI,eAAe,SAAS,GAAG,KAAK,GAAG,KAAK;AACpD,kBAAU,eAAe,CAAC;AAC1B,YAAI,QAAQ,UAAU,GAAG;AACxB,yBAAe,OAAO,GAAG,CAAC;AAC1B,eAAK,YAAY,KAAK,OAAO;AAC7B,2BAAiB,sBAAsB,CAAC;AACxC,gCAAsB,OAAO,GAAG,CAAC;AACjC,eAAK,mBAAmB,KAAK,cAAc;AAAA,QAC5C;AAAA,MACD;AAEA,aAAO;AAAA,IACR;AAAA,IAEA,OAAe,UAAW,OAAe,aAAqB,UAA2B,SAAmC;AAC3H,UAAI,WAAW,SAAS,cAAc,QAAQ,KAAK,WAAW,KAAK;AACnE,UAAI,UAAU,QAAQ,KAAK,KAAK;AAChC,UAAI,OAAO,SAAS,QAAQ,KAAK,WAAW,KAAK;AACjD,aAAO,CAAC,KAAK;AAAA,QAAa,SAAS,QAAQ;AAAA,QAAG,SAAS,WAAW,CAAC;AAAA,QAAG,SAAS,OAAO;AAAA,QAAG,SAAS,UAAU,CAAC;AAAA,QAAG,SAAS,IAAI;AAAA,QAC5H,SAAS,OAAO,CAAC;AAAA,MAAC;AAAA,IACpB;AAAA,IAEA,OAAe,aAAc,KAAa,KAAa,KAAa,KAAa,KAAa,KAAsB;AACnH,aAAO,OAAO,MAAM,OAAO,OAAO,MAAM,OAAO,OAAO,MAAM,QAAQ;AAAA,IACrE;AAAA,IAEA,OAAe,QAAS,KAAa,KAAa,KAAa,KAAa,KAAa,KAAqB;AAC7G,UAAI,KAAK,MAAM,KAAK,KAAK,MAAM;AAC/B,aAAO,MAAM,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,IAAI,IAAI;AAAA,IAC7D;AAAA,EACD;;;AC1OO,MAAM,mBAAN,MAAuB;AAAA,IACrB,eAAe,IAAI,aAAa;AAAA,IAChC,kBAAkB,IAAI,MAAc;AAAA,IACpC,aAAa,IAAI,MAAc;AAAA,IACvC,kBAAkB,IAAI,MAAc;AAAA,IACpC,aAAa,IAAI,MAAc;AAAA,IAC/B,mBAAmB,IAAI,MAAc;AAAA,IAC7B,UAAU,IAAI,MAAc;AAAA,IAE5B,iBAA4C;AAAA,IAC5C,mBAAgD;AAAA,IAExD,UAAW,MAAY,MAAkC;AACxD,UAAI,KAAK;AAAgB,eAAO;AAChC,WAAK,iBAAiB;AAEtB,UAAI,IAAI,KAAK;AACb,UAAI,WAAW,MAAM,aAAa,KAAK,iBAAiB,CAAC;AACzD,WAAK,qBAAqB,MAAM,GAAG,GAAG,UAAU,GAAG,CAAC;AACpD,UAAI,kBAAkB,KAAK;AAC3B,uBAAiB,cAAc,eAAe;AAC9C,UAAI,mBAAmB,KAAK,mBAAmB,KAAK,aAAa,UAAU,iBAAiB,KAAK,aAAa,YAAY,eAAe,CAAC;AAC1I,eAAS,IAAI,GAAGC,KAAI,iBAAiB,QAAQ,IAAIA,IAAG,KAAK;AACxD,YAAI,UAAU,iBAAiB,CAAC;AAChC,yBAAiB,cAAc,OAAO;AACtC,gBAAQ,KAAK,QAAQ,CAAC,CAAC;AACvB,gBAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA,MACxB;AAEA,aAAO,iBAAiB;AAAA,IACzB;AAAA,IAEA,gBAAiB,MAAY;AAC5B,UAAI,KAAK,kBAAkB,KAAK,eAAe,WAAW,KAAK;AAAM,aAAK,QAAQ;AAAA,IACnF;AAAA,IAEA,UAAW;AACV,UAAI,CAAC,KAAK;AAAgB;AAC1B,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AACxB,WAAK,gBAAgB,SAAS;AAC9B,WAAK,iBAAiB,SAAS;AAC/B,WAAK,gBAAgB,SAAS;AAAA,IAC/B;AAAA,IAEA,aAAuB;AACtB,aAAO,KAAK,kBAAkB;AAAA,IAC/B;AAAA,IAcA,cACC,UACA,2BACA,4BACA,sBACA,YACA,aACA,gBACA,eACO;AAEP,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI;AAEJ,UAAI,OAAO,8BAA8B,UAAU;AAClD,oBAAY;AACZ,0BAAkB;AAClB,cAAM;AACN,gBAAQ;AACR,eAAO;AACP,mBAAW;AAAA,MACZ,OAAO;AACN,oBAAY;AACZ,0BAAkB;AAClB,cAAM;AACN,gBAAQ;AACR,eAAO;AACP,mBAAW;AAAA,MACZ;AAEA,UAAI,OAAO,SAAS,QAAQ,OAAO,aAAa;AAC/C,aAAK,oBAAoB,UAAU,WAAW,iBAAiB,KAAK,OAAO,MAAM,QAAQ;AAAA;AAEzF,aAAK,sBAAsB,UAAU,WAAW,eAAe;AAAA,IACjE;AAAA,IAEQ,sBAAuB,UAA2B,WAA4B,iBAAyB;AAE9G,UAAI,aAAa,KAAK,YAAY,kBAAkB,KAAK;AACzD,UAAI,mBAAmB,KAAK;AAC5B,UAAI,WAAW,KAAK;AACpB,UAAI,gBAAgB,SAAS;AAE7B,UAAI,QAAQ;AACZ,sBAAgB,SAAS;AACzB,uBAAiB,SAAS;AAC1B,eAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK,GAAG;AAC5C,YAAI,eAAe,UAAU,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAE/D,uBAAe,UAAU,IAAI,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAE/D,uBAAe,UAAU,IAAI,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAE/D,iBAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACvC,cAAI,IAAI,gBAAgB;AACxB,cAAI,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC,GAAG,UAAU,GAAG;AAC/D,gBAAI,mBAAmB,WAAW;AAClC,gBAAI,oBAAoB;AAAG;AAE3B,gBAAI,kBAAkB,oBAAoB;AAC1C,gBAAI,kBAAkB,KAAK;AAC3B,gBAAI,uBAAuB,MAAM,aAAa,iBAAiB,IAAI,kBAAkB,CAAC;AACtF,qBAAS,KAAK,GAAG,KAAK,kBAAkB,MAAM,GAAG,KAAK,GAAG;AACxD,kBAAI,IAAI,gBAAgB,EAAE,GAAG,IAAI,gBAAgB,KAAK,CAAC;AACvD,mCAAqB,CAAC,IAAI;AAC1B,mCAAqB,IAAI,CAAC,IAAI;AAAA,YAC/B;AAEA,gBAAI,iBAAiB;AACrB,gBAAI,wBAAwB,MAAM,aAAa,kBAAkB,IAAI,KAAK,kBAAkB,EAAE;AAC9F;AACA,qBAAS,KAAK,GAAG,KAAK,iBAAiB,MAAM,KAAK,GAAG;AACpD,oCAAsB,CAAC,IAAI;AAC3B,oCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,oCAAsB,IAAI,CAAC,IAAK,QAAQ,KAAK;AAAA,YAC9C;AACA,qBAAS,kBAAkB;AAAA,UAE5B,OAAO;AACN,gBAAI,uBAAuB,MAAM,aAAa,iBAAiB,IAAI,IAAI,CAAC;AACxE,iCAAqB,CAAC,IAAI;AAC1B,iCAAqB,IAAI,CAAC,IAAI;AAE9B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI;AAE9B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI;AAE9B,gBAAI,iBAAiB;AACrB,gBAAI,wBAAwB,MAAM,aAAa,kBAAkB,IAAI,CAAC;AACtE,kCAAsB,CAAC,IAAI;AAC3B,kCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,kCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,qBAAS;AACT;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IAEQ,oBAAqB,UAA2B,WAA4B,iBAAyB,KAC5G,OAAc,MAAa,UAAmB;AAE9C,UAAI,aAAa,KAAK,YAAY,kBAAkB,KAAK;AACzD,UAAI,mBAAmB,KAAK;AAC5B,UAAI,WAAW,KAAK;AACpB,UAAI,gBAAgB,SAAS;AAC7B,UAAI,aAAa,WAAW,KAAK;AAEjC,UAAI,QAAQ;AACZ,sBAAgB,SAAS;AACzB,uBAAiB,SAAS;AAC1B,eAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK,GAAG;AAC5C,YAAI,eAAe,UAAU,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAC/D,YAAI,KAAK,IAAI,YAAY,GAAG,KAAK,IAAI,eAAe,CAAC;AAErD,uBAAe,UAAU,IAAI,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAC/D,YAAI,KAAK,IAAI,YAAY,GAAG,KAAK,IAAI,eAAe,CAAC;AAErD,uBAAe,UAAU,IAAI,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAC/D,YAAI,KAAK,IAAI,YAAY,GAAG,KAAK,IAAI,eAAe,CAAC;AAErD,iBAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACvC,cAAI,IAAI,gBAAgB;AACxB,cAAI,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC,GAAG,UAAU,GAAG;AAC/D,gBAAI,mBAAmB,WAAW;AAClC,gBAAI,oBAAoB;AAAG;AAC3B,gBAAI,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK;AACxD,gBAAI,IAAI,KAAK,KAAK,KAAK,MAAM,KAAK;AAElC,gBAAI,kBAAkB,oBAAoB;AAC1C,gBAAI,kBAAkB,KAAK;AAC3B,gBAAI,uBAAuB,MAAM,aAAa,iBAAiB,IAAI,kBAAkB,UAAU;AAC/F,qBAAS,KAAK,GAAG,KAAK,kBAAkB,MAAM,GAAG,KAAK,YAAY;AACjE,kBAAI,IAAI,gBAAgB,EAAE,GAAG,IAAI,gBAAgB,KAAK,CAAC;AACvD,mCAAqB,CAAC,IAAI;AAC1B,mCAAqB,IAAI,CAAC,IAAI;AAC9B,mCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,mCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,mCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,mCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,kBAAI,KAAK,IAAI,IAAI,KAAK,IAAI;AAC1B,kBAAI,KAAK,KAAK,KAAK,KAAK,MAAM;AAC9B,kBAAI,KAAK,KAAK,KAAK,KAAK,MAAM;AAC9B,kBAAI,IAAI,IAAI,IAAI;AAChB,mCAAqB,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AACrD,mCAAqB,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AACrD,kBAAI,UAAU;AACb,qCAAqB,IAAI,CAAC,IAAI,KAAK;AACnC,qCAAqB,IAAI,CAAC,IAAI,KAAK;AACnC,qCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,qCAAqB,IAAI,EAAE,IAAI,KAAK;AAAA,cACrC;AAAA,YACD;AAEA,gBAAI,iBAAiB;AACrB,gBAAI,wBAAwB,MAAM,aAAa,kBAAkB,IAAI,KAAK,kBAAkB,EAAE;AAC9F;AACA,qBAAS,KAAK,GAAG,KAAK,iBAAiB,MAAM,KAAK,GAAG;AACpD,oCAAsB,CAAC,IAAI;AAC3B,oCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,oCAAsB,IAAI,CAAC,IAAK,QAAQ,KAAK;AAAA,YAC9C;AACA,qBAAS,kBAAkB;AAAA,UAE5B,OAAO;AACN,gBAAI,uBAAuB,MAAM,aAAa,iBAAiB,IAAI,IAAI,UAAU;AACjF,iCAAqB,CAAC,IAAI;AAC1B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,iCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,iCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,iCAAqB,IAAI,CAAC,IAAI,MAAM;AACpC,gBAAI,CAAC,UAAU;AACd,mCAAqB,IAAI,CAAC,IAAI;AAC9B,mCAAqB,IAAI,CAAC,IAAI;AAE9B,mCAAqB,IAAI,CAAC,IAAI;AAC9B,mCAAqB,IAAI,CAAC,IAAI;AAC9B,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAE/B,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAAA,YAChC,OAAO;AACN,mCAAqB,IAAI,CAAC,IAAI;AAC9B,mCAAqB,IAAI,CAAC,IAAI;AAC9B,mCAAqB,IAAI,CAAC,IAAI,KAAK;AACnC,mCAAqB,IAAI,CAAC,IAAI,KAAK;AACnC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AAEpC,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AAEpC,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI,MAAM;AACrC,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI;AAC/B,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AACpC,mCAAqB,IAAI,EAAE,IAAI,KAAK;AAAA,YACrC;AAEA,gBAAI,iBAAiB;AACrB,gBAAI,wBAAwB,MAAM,aAAa,kBAAkB,IAAI,CAAC;AACtE,kCAAsB,CAAC,IAAI;AAC3B,kCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,kCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,qBAAS;AACT;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IAEO,sBAAuB,UAA2B,WAA4B,iBAAyB,KAAsB;AACnI,UAAI,aAAa,KAAK,YAAY,kBAAkB,KAAK,iBAAiB,aAAa,KAAK;AAC5F,UAAI,mBAAmB,KAAK;AAC5B,UAAI,WAAW,KAAK;AACpB,UAAI,gBAAgB,SAAS;AAE7B,UAAI,QAAQ;AACZ,sBAAgB,SAAS;AACzB,iBAAW,SAAS;AACpB,uBAAiB,SAAS;AAC1B,eAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK,GAAG;AAC5C,YAAI,eAAe,UAAU,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAC/D,YAAI,KAAK,IAAI,YAAY,GAAG,KAAK,IAAI,eAAe,CAAC;AAErD,uBAAe,UAAU,IAAI,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAC/D,YAAI,KAAK,IAAI,YAAY,GAAG,KAAK,IAAI,eAAe,CAAC;AAErD,uBAAe,UAAU,IAAI,CAAC,KAAK;AACnC,YAAI,KAAK,SAAS,YAAY,GAAG,KAAK,SAAS,eAAe,CAAC;AAC/D,YAAI,KAAK,IAAI,YAAY,GAAG,KAAK,IAAI,eAAe,CAAC;AAErD,iBAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACvC,cAAI,IAAI,gBAAgB;AACxB,cAAI,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC,GAAG,UAAU,GAAG;AAC/D,gBAAI,mBAAmB,WAAW;AAClC,gBAAI,oBAAoB;AAAG;AAC3B,gBAAI,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK;AACxD,gBAAI,IAAI,KAAK,KAAK,KAAK,MAAM,KAAK;AAElC,gBAAI,kBAAkB,oBAAoB;AAC1C,gBAAI,kBAAkB,KAAK;AAC3B,gBAAI,uBAAuB,MAAM,aAAa,iBAAiB,IAAI,kBAAkB,CAAC;AACtF,gBAAI,kBAAkB,MAAM,aAAa,YAAY,IAAI,kBAAkB,CAAC;AAC5E,qBAAS,KAAK,GAAG,KAAK,kBAAkB,MAAM,GAAG,KAAK,GAAG;AACxD,kBAAI,IAAI,gBAAgB,EAAE,GAAG,IAAI,gBAAgB,KAAK,CAAC;AACvD,mCAAqB,CAAC,IAAI;AAC1B,mCAAqB,IAAI,CAAC,IAAI;AAC9B,kBAAI,KAAK,IAAI,IAAI,KAAK,IAAI;AAC1B,kBAAI,KAAK,KAAK,KAAK,KAAK,MAAM;AAC9B,kBAAI,KAAK,KAAK,KAAK,KAAK,MAAM;AAC9B,kBAAI,IAAI,IAAI,IAAI;AAChB,8BAAgB,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AAC5C,8BAAgB,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK;AAAA,YACjD;AAEA,gBAAI,iBAAiB;AACrB,gBAAI,wBAAwB,MAAM,aAAa,kBAAkB,IAAI,KAAK,kBAAkB,EAAE;AAC9F;AACA,qBAAS,KAAK,GAAG,KAAK,iBAAiB,MAAM,KAAK,GAAG;AACpD,oCAAsB,CAAC,IAAI;AAC3B,oCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,oCAAsB,IAAI,CAAC,IAAK,QAAQ,KAAK;AAAA,YAC9C;AACA,qBAAS,kBAAkB;AAAA,UAE5B,OAAO;AACN,gBAAI,uBAAuB,MAAM,aAAa,iBAAiB,IAAI,IAAI,CAAC;AACxE,iCAAqB,CAAC,IAAI;AAC1B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI;AAC9B,iCAAqB,IAAI,CAAC,IAAI;AAE9B,gBAAI,kBAAkB,MAAM,aAAa,YAAY,IAAI,IAAI,CAAC;AAC9D,4BAAgB,CAAC,IAAI;AACrB,4BAAgB,IAAI,CAAC,IAAI;AACzB,4BAAgB,IAAI,CAAC,IAAI;AACzB,4BAAgB,IAAI,CAAC,IAAI;AACzB,4BAAgB,IAAI,CAAC,IAAI;AACzB,4BAAgB,IAAI,CAAC,IAAI;AAEzB,gBAAI,iBAAiB;AACrB,gBAAI,wBAAwB,MAAM,aAAa,kBAAkB,IAAI,CAAC;AACtE,kCAAsB,CAAC,IAAI;AAC3B,kCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,kCAAsB,IAAI,CAAC,IAAK,QAAQ;AACxC,qBAAS;AACT;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA;AAAA;AAAA,IAIA,KAAM,IAAY,IAAY,IAAY,IAAY,IAAY,IAAY,cAA6B,QAAuB;AACjI,UAAI,iBAAiB;AACrB,UAAI,UAAU;AAGd,UAAI;AACJ,UAAI,aAAa,SAAS,KAAK,GAAG;AACjC,gBAAQ;AACR,iBAAS,KAAK;AAAA,MACf;AACC,gBAAQ,KAAK;AAEd,YAAM,SAAS;AACf,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE;AACb,aAAO,SAAS;AAEhB,UAAI,uBAAuB,aAAa,SAAS;AACjD,UAAI,mBAAmB;AACvB,eAAS,IAAI,KAAK,KAAK,GAAG;AACzB,YAAI,QAAQ,iBAAiB,CAAC,GAAG,QAAQ,iBAAiB,IAAI,CAAC;AAC/D,YAAI,KAAK,QAAQ,iBAAiB,IAAI,CAAC,GAAG,KAAK,QAAQ,iBAAiB,IAAI,CAAC;AAE7E,YAAI,cAAc,OAAO;AACzB,YAAI,gBAAgB;AACpB,iBAAS,KAAK,GAAG,KAAK,MAAM,SAAS,GAAG,KAAK,MAAK;AACjD,cAAI,SAAS,cAAc,EAAE,GAAG,SAAS,cAAc,KAAK,CAAC;AAC7D,gBAAM;AACN,cAAI,UAAU,cAAc,EAAE,GAAG,UAAU,cAAc,KAAK,CAAC;AAC/D,cAAI,KAAK,MAAM,QAAQ,WAAW,MAAM,QAAQ;AAChD,cAAI,KAAK,MAAM,QAAQ,UAAU,MAAM,QAAQ;AAC/C,cAAI,KAAK,GAAG;AACX,gBAAI,IAAI;AACP,qBAAO,KAAK,OAAO;AACnB,qBAAO,KAAK,OAAO;AACnB;AAAA,YACD;AAEA,gBAAI,KAAK,UAAU,QAAQ,KAAK,UAAU,QAAQ,IAAI,MAAM,KAAK,KAAK,KAAK;AAC3E,gBAAI,KAAK,KAAK,KAAK,GAAG;AACrB,qBAAO,KAAK,SAAS,KAAK,CAAC;AAC3B,qBAAO,KAAK,SAAS,KAAK,CAAC;AAAA,YAC5B,OAAO;AACN,qBAAO,KAAK,OAAO;AACnB,qBAAO,KAAK,OAAO;AACnB;AAAA,YACD;AAAA,UACD,WAAW,IAAI;AACd,gBAAI,KAAK,UAAU,QAAQ,KAAK,UAAU,QAAQ,IAAI,MAAM,KAAK,KAAK,KAAK;AAC3E,gBAAI,KAAK,KAAK,KAAK,GAAG;AACrB,qBAAO,KAAK,SAAS,KAAK,CAAC;AAC3B,qBAAO,KAAK,SAAS,KAAK,CAAC;AAC3B,qBAAO,KAAK,OAAO;AACnB,qBAAO,KAAK,OAAO;AAAA,YACpB,OAAO;AACN,qBAAO,KAAK,OAAO;AACnB,qBAAO,KAAK,OAAO;AACnB;AAAA,YACD;AAAA,UACD;AACA,oBAAU;AAAA,QACX;AAEA,YAAI,eAAe,OAAO,QAAQ;AACjC,yBAAe,SAAS;AACxB,iBAAO;AAAA,QACR;AAEA,eAAO,KAAK,OAAO,CAAC,CAAC;AACrB,eAAO,KAAK,OAAO,CAAC,CAAC;AAErB,YAAI,KAAK;AAAsB;AAC/B,YAAI,OAAO;AACX,iBAAS;AACT,eAAO,SAAS;AAChB,gBAAQ;AAAA,MACT;AAEA,UAAI,kBAAkB,QAAQ;AAC7B,uBAAe,SAAS;AACxB,iBAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG;AAC7C,yBAAe,CAAC,IAAI,OAAO,CAAC;AAAA,MAC9B;AACC,uBAAe,SAAS,eAAe,SAAS;AAEjD,aAAO;AAAA,IACR;AAAA,IAEA,OAAc,cAAe,SAA0B;AACtD,UAAI,WAAW;AACf,UAAI,iBAAiB,QAAQ;AAE7B,UAAI,OAAO,SAAS,iBAAiB,CAAC,IAAI,SAAS,CAAC,IAAI,SAAS,CAAC,IAAI,SAAS,iBAAiB,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;AACrI,eAAS,IAAI,GAAG,IAAI,iBAAiB,GAAG,IAAI,GAAG,KAAK,GAAG;AACtD,cAAM,SAAS,CAAC;AAChB,cAAM,SAAS,IAAI,CAAC;AACpB,cAAM,SAAS,IAAI,CAAC;AACpB,cAAM,SAAS,IAAI,CAAC;AACpB,gBAAQ,MAAM,MAAM,MAAM;AAAA,MAC3B;AACA,UAAI,OAAO;AAAG;AAEd,eAAS,IAAI,GAAG,QAAQ,iBAAiB,GAAG,IAAI,kBAAkB,GAAG,IAAI,GAAG,KAAK,GAAG;AACnF,YAAI,IAAI,SAAS,CAAC,GAAG,IAAI,SAAS,IAAI,CAAC;AACvC,YAAI,QAAQ,QAAQ;AACpB,iBAAS,CAAC,IAAI,SAAS,KAAK;AAC5B,iBAAS,IAAI,CAAC,IAAI,SAAS,QAAQ,CAAC;AACpC,iBAAS,KAAK,IAAI;AAClB,iBAAS,QAAQ,CAAC,IAAI;AAAA,MACvB;AAAA,IACD;AAAA,EACD;;;ACnfO,MAAM,eAAN,MAAmB;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,QAAQ;AAAA,IACA,eAAe,IAAI,MAAkB;AAAA,IAE7C,YAAa,kBAAoC;AAChD,WAAK,mBAAmB;AAAA,IACzB;AAAA,IAEA,iBAAkB,MAAkC;AACnD,UAAI,QAAQ,KAAK;AACjB,UAAI,eAAe,IAAI,aAAa;AACpC,UAAI,OAAO,OAAQ,SAAU,WAAW,KAAK,MAAM,IAAI,IAAI;AAG3D,UAAI,cAAc,KAAK;AACvB,UAAI,aAAa;AAChB,qBAAa,OAAO,YAAY;AAChC,qBAAa,UAAU,YAAY;AACnC,qBAAa,IAAI,YAAY;AAC7B,qBAAa,IAAI,YAAY;AAC7B,qBAAa,QAAQ,YAAY;AACjC,qBAAa,SAAS,YAAY;AAClC,qBAAa,iBAAiB,SAAS,aAAa,kBAAkB,GAAG,IAAI;AAC7E,qBAAa,MAAM,YAAY;AAC/B,qBAAa,aAAa,YAAY,UAAU;AAChD,qBAAa,YAAY,YAAY,SAAS;AAAA,MAC/C;AAGA,UAAI,KAAK,OAAO;AACf,iBAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,cAAI,UAAU,KAAK,MAAM,CAAC;AAE1B,cAAI,SAA0B;AAC9B,cAAI,aAAqB,SAAS,SAAS,UAAU,IAAI;AACzD,cAAI;AAAY,qBAAS,aAAa,SAAS,UAAU;AACzD,cAAI,OAAO,IAAI,SAAS,aAAa,MAAM,QAAQ,QAAQ,MAAM,MAAM;AACvE,eAAK,SAAS,SAAS,SAAS,UAAU,CAAC,IAAI;AAC/C,eAAK,IAAI,SAAS,SAAS,KAAK,CAAC,IAAI;AACrC,eAAK,IAAI,SAAS,SAAS,KAAK,CAAC,IAAI;AACrC,eAAK,WAAW,SAAS,SAAS,YAAY,CAAC;AAC/C,eAAK,SAAS,SAAS,SAAS,UAAU,CAAC;AAC3C,eAAK,SAAS,SAAS,SAAS,UAAU,CAAC;AAC3C,eAAK,SAAS,SAAS,SAAS,UAAU,CAAC;AAC3C,eAAK,SAAS,SAAS,SAAS,UAAU,CAAC;AAC3C,eAAK,UAAU,MAAM,UAAU,SAAS,SAAS,SAAS,WAAW,QAAQ,CAAC;AAC9E,eAAK,eAAe,SAAS,SAAS,QAAQ,KAAK;AAEnD,cAAI,QAAQ,SAAS,SAAS,SAAS,IAAI;AAC3C,cAAI;AAAO,iBAAK,MAAM,cAAc,KAAK;AAEzC,uBAAa,MAAM,KAAK,IAAI;AAAA,QAC7B;AAAA,MACD;AAGA,UAAI,KAAK,OAAO;AACf,iBAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,cAAI,UAAU,KAAK,MAAM,CAAC;AAC1B,cAAI,WAAW,QAAQ;AAEvB,cAAI,WAAW,aAAa,SAAS,QAAQ,IAAI;AACjD,cAAI,CAAC;AAAU,kBAAM,IAAI,MAAM,sBAAsB,QAAQ,iBAAiB,UAAU;AACxF,cAAI,OAAO,IAAI,SAAS,aAAa,MAAM,QAAQ,UAAU,QAAQ;AAErE,cAAI,QAAgB,SAAS,SAAS,SAAS,IAAI;AACnD,cAAI;AAAO,iBAAK,MAAM,cAAc,KAAK;AAEzC,cAAI,OAAe,SAAS,SAAS,QAAQ,IAAI;AACjD,cAAI;AAAM,iBAAK,YAAY,MAAM,WAAW,IAAI;AAEhD,eAAK,iBAAiB,SAAS,SAAS,cAAc,IAAI;AAC1D,eAAK,YAAY,MAAM,UAAU,WAAW,SAAS,SAAS,SAAS,QAAQ,CAAC;AAChF,eAAK,UAAU,SAAS,SAAS,WAAW,IAAI;AAChD,uBAAa,MAAM,KAAK,IAAI;AAAA,QAC7B;AAAA,MACD;AAGA,UAAI,KAAK,IAAI;AACZ,iBAAS,IAAI,GAAG,IAAI,KAAK,GAAG,QAAQ,KAAK;AACxC,cAAI,gBAAgB,KAAK,GAAG,CAAC;AAC7B,cAAI,OAAO,IAAI,iBAAiB,cAAc,IAAI;AAClD,eAAK,QAAQ,SAAS,eAAe,SAAS,CAAC;AAC/C,eAAK,eAAe,SAAS,eAAe,QAAQ,KAAK;AAEzD,mBAAS,KAAK,GAAG,KAAK,cAAc,MAAM,QAAQ,MAAM;AACvD,gBAAI,OAAO,aAAa,SAAS,cAAc,MAAM,EAAE,CAAC;AACxD,gBAAI,CAAC;AAAM,oBAAM,IAAI,MAAM,sBAAsB,cAAc,MAAM,EAAE,uBAAuB,cAAc,OAAO;AACnH,iBAAK,MAAM,KAAK,IAAI;AAAA,UACrB;AAEA,cAAI,SAAS,aAAa,SAAS,cAAc,MAAM;AAAE;AACzD,cAAI,CAAC;AAAQ,kBAAM,IAAI,MAAM,6BAA6B,cAAc,4BAA4B,cAAc,OAAO;AACzH,eAAK,SAAS;AAEd,eAAK,MAAM,SAAS,eAAe,OAAO,CAAC;AAC3C,eAAK,WAAW,SAAS,eAAe,YAAY,CAAC,IAAI;AACzD,eAAK,gBAAgB,SAAS,eAAe,gBAAgB,IAAI,IAAI,IAAI;AACzE,eAAK,WAAW,SAAS,eAAe,YAAY,KAAK;AACzD,eAAK,UAAU,SAAS,eAAe,WAAW,KAAK;AACvD,eAAK,UAAU,SAAS,eAAe,WAAW,KAAK;AAEvD,uBAAa,cAAc,KAAK,IAAI;AAAA,QACrC;AAAA,MACD;AAGA,UAAI,KAAK,WAAW;AACnB,iBAAS,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;AAC/C,cAAI,gBAAgB,KAAK,UAAU,CAAC;AACpC,cAAI,OAAO,IAAI,wBAAwB,cAAc,IAAI;AACzD,eAAK,QAAQ,SAAS,eAAe,SAAS,CAAC;AAC/C,eAAK,eAAe,SAAS,eAAe,QAAQ,KAAK;AAEzD,mBAAS,KAAK,GAAG,KAAK,cAAc,MAAM,QAAQ,MAAM;AACvD,gBAAI,WAAW,cAAc,MAAM,EAAE;AACrC,gBAAI,OAAO,aAAa,SAAS,QAAQ;AACzC,gBAAI,CAAC;AAAM,oBAAM,IAAI,MAAM,sBAAsB,qCAAqC,cAAc,OAAO;AAC3G,iBAAK,MAAM,KAAK,IAAI;AAAA,UACrB;AAEA,cAAI,aAAqB,cAAc;AACvC,cAAI,SAAS,aAAa,SAAS,UAAU;AAC7C,cAAI,CAAC;AAAQ,kBAAM,IAAI,MAAM,6BAA6B,uCAAuC,cAAc,OAAO;AACtH,eAAK,SAAS;AAEd,eAAK,QAAQ,SAAS,eAAe,SAAS,KAAK;AACnD,eAAK,WAAW,SAAS,eAAe,YAAY,KAAK;AACzD,eAAK,iBAAiB,SAAS,eAAe,YAAY,CAAC;AAC3D,eAAK,UAAU,SAAS,eAAe,KAAK,CAAC,IAAI;AACjD,eAAK,UAAU,SAAS,eAAe,KAAK,CAAC,IAAI;AACjD,eAAK,eAAe,SAAS,eAAe,UAAU,CAAC;AACvD,eAAK,eAAe,SAAS,eAAe,UAAU,CAAC;AACvD,eAAK,eAAe,SAAS,eAAe,UAAU,CAAC;AAEvD,eAAK,YAAY,SAAS,eAAe,aAAa,CAAC;AACvD,eAAK,OAAO,SAAS,eAAe,QAAQ,CAAC;AAC7C,eAAK,OAAO,SAAS,eAAe,QAAQ,KAAK,IAAI;AACrD,eAAK,YAAY,SAAS,eAAe,aAAa,CAAC;AACvD,eAAK,YAAY,SAAS,eAAe,aAAa,KAAK,SAAS;AACpE,eAAK,YAAY,SAAS,eAAe,aAAa,CAAC;AAEvD,uBAAa,qBAAqB,KAAK,IAAI;AAAA,QAC5C;AAAA,MACD;AAGA,UAAI,KAAK,MAAM;AACd,iBAAS,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK;AAC1C,cAAI,gBAAgB,KAAK,KAAK,CAAC;AAC/B,cAAI,OAAO,IAAI,mBAAmB,cAAc,IAAI;AACpD,eAAK,QAAQ,SAAS,eAAe,SAAS,CAAC;AAC/C,eAAK,eAAe,SAAS,eAAe,QAAQ,KAAK;AAEzD,mBAAS,KAAK,GAAG,KAAK,cAAc,MAAM,QAAQ,MAAM;AACvD,gBAAI,WAAW,cAAc,MAAM,EAAE;AACrC,gBAAI,OAAO,aAAa,SAAS,QAAQ;AACzC,gBAAI,CAAC;AAAM,oBAAM,IAAI,MAAM,sBAAsB,gCAAgC,cAAc,OAAO;AACtG,iBAAK,MAAM,KAAK,IAAI;AAAA,UACrB;AAEA,cAAI,aAAqB,cAAc;AACvC,cAAI,SAAS,aAAa,SAAS,UAAU;AAC7C,cAAI,CAAC;AAAQ,kBAAM,IAAI,MAAM,6BAA6B,kCAAkC,cAAc,OAAO;AACjH,eAAK,SAAS;AAEd,eAAK,eAAe,MAAM,UAAU,cAAc,SAAS,eAAe,gBAAgB,SAAS,CAAC;AACpG,eAAK,cAAc,MAAM,UAAU,aAAa,SAAS,eAAe,eAAe,QAAQ,CAAC;AAChG,eAAK,aAAa,MAAM,UAAU,YAAY,SAAS,eAAe,cAAc,SAAS,CAAC;AAC9F,eAAK,iBAAiB,SAAS,eAAe,YAAY,CAAC;AAC3D,eAAK,WAAW,SAAS,eAAe,YAAY,CAAC;AACrD,cAAI,KAAK;AAAoC,iBAAK,YAAY;AAC9D,eAAK,UAAU,SAAS,eAAe,WAAW,CAAC;AACnD,cAAI,KAAK,iCAAqC,KAAK;AAAkC,iBAAK,WAAW;AACrG,eAAK,YAAY,SAAS,eAAe,aAAa,CAAC;AACvD,eAAK,OAAO,SAAS,eAAe,QAAQ,CAAC;AAC7C,eAAK,OAAO,SAAS,eAAe,QAAQ,KAAK,IAAI;AAErD,uBAAa,gBAAgB,KAAK,IAAI;AAAA,QACvC;AAAA,MACD;AAGA,UAAI,KAAK,SAAS;AACjB,iBAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC7C,gBAAM,gBAAgB,KAAK,QAAQ,CAAC;AACpC,gBAAM,OAAO,IAAI,sBAAsB,cAAc,IAAI;AACzD,eAAK,QAAQ,SAAS,eAAe,SAAS,CAAC;AAC/C,eAAK,eAAe,SAAS,eAAe,QAAQ,KAAK;AAEzD,gBAAM,WAAW,cAAc;AAC/B,gBAAM,OAAO,aAAa,SAAS,QAAQ;AAC3C,cAAI,QAAQ;AAAM,kBAAM,IAAI,MAAM,6BAA6B,QAAQ;AACvE,eAAK,OAAO;AAEZ,eAAK,IAAI,SAAS,eAAe,KAAK,CAAC;AACvC,eAAK,IAAI,SAAS,eAAe,KAAK,CAAC;AACvC,eAAK,SAAS,SAAS,eAAe,UAAU,CAAC;AACjD,eAAK,SAAS,SAAS,eAAe,UAAU,CAAC;AACjD,eAAK,SAAS,SAAS,eAAe,UAAU,CAAC;AACjD,eAAK,QAAQ,SAAS,eAAe,SAAS,GAAI,IAAI;AACtD,eAAK,OAAO,IAAI,SAAS,eAAe,OAAO,EAAE;AACjD,eAAK,UAAU,SAAS,eAAe,WAAW,CAAC;AACnD,eAAK,WAAW,SAAS,eAAe,YAAY,GAAG;AACvD,eAAK,UAAU,SAAS,eAAe,WAAW,CAAC;AACnD,eAAK,cAAc,IAAI,SAAS,eAAe,QAAQ,CAAC;AACxD,eAAK,OAAO,SAAS,eAAe,QAAQ,CAAC;AAC7C,eAAK,UAAU,SAAS,eAAe,WAAW,CAAC;AACnD,eAAK,MAAM,SAAS,eAAe,OAAO,CAAC;AAC3C,eAAK,gBAAgB,SAAS,eAAe,iBAAiB,KAAK;AACnE,eAAK,iBAAiB,SAAS,eAAe,kBAAkB,KAAK;AACrE,eAAK,gBAAgB,SAAS,eAAe,iBAAiB,KAAK;AACnE,eAAK,aAAa,SAAS,eAAe,cAAc,KAAK;AAC7D,eAAK,aAAa,SAAS,eAAe,cAAc,KAAK;AAC7D,eAAK,gBAAgB,SAAS,eAAe,iBAAiB,KAAK;AACnE,eAAK,YAAY,SAAS,eAAe,aAAa,KAAK;AAE3D,uBAAa,mBAAmB,KAAK,IAAI;AAAA,QAC1C;AAAA,MACD;AAGA,UAAI,KAAK,OAAO;AACf,iBAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC3C,cAAI,UAAU,KAAK,MAAM,CAAC;AAC1B,cAAI,OAAO,IAAI,KAAK,QAAQ,IAAI;AAEhC,cAAI,QAAQ,OAAO;AAClB,qBAAS,KAAK,GAAG,KAAK,QAAQ,MAAM,QAAQ,MAAM;AACjD,kBAAI,WAAW,QAAQ,MAAM,EAAE;AAC/B,kBAAI,OAAO,aAAa,SAAS,QAAQ;AACzC,kBAAI,CAAC;AAAM,sBAAM,IAAI,MAAM,sBAAsB,qBAAqB,QAAQ,OAAO;AACrF,mBAAK,MAAM,KAAK,IAAI;AAAA,YACrB;AAAA,UACD;AAEA,cAAI,QAAQ,IAAI;AACf,qBAAS,KAAK,GAAG,KAAK,QAAQ,GAAG,QAAQ,MAAM;AAC9C,kBAAI,iBAAiB,QAAQ,GAAG,EAAE;AAClC,kBAAI,aAAa,aAAa,iBAAiB,cAAc;AAC7D,kBAAI,CAAC;AAAY,sBAAM,IAAI,MAAM,+BAA+B,2BAA2B,QAAQ,OAAO;AAC1G,mBAAK,YAAY,KAAK,UAAU;AAAA,YACjC;AAAA,UACD;AAEA,cAAI,QAAQ,WAAW;AACtB,qBAAS,KAAK,GAAG,KAAK,QAAQ,UAAU,QAAQ,MAAM;AACrD,kBAAI,iBAAiB,QAAQ,UAAU,EAAE;AACzC,kBAAI,aAAa,aAAa,wBAAwB,cAAc;AACpE,kBAAI,CAAC;AAAY,sBAAM,IAAI,MAAM,sCAAsC,2BAA2B,QAAQ,OAAO;AACjH,mBAAK,YAAY,KAAK,UAAU;AAAA,YACjC;AAAA,UACD;AAEA,cAAI,QAAQ,MAAM;AACjB,qBAAS,KAAK,GAAG,KAAK,QAAQ,KAAK,QAAQ,MAAM;AAChD,kBAAI,iBAAiB,QAAQ,KAAK,EAAE;AACpC,kBAAI,aAAa,aAAa,mBAAmB,cAAc;AAC/D,kBAAI,CAAC;AAAY,sBAAM,IAAI,MAAM,iCAAiC,2BAA2B,QAAQ,OAAO;AAC5G,mBAAK,YAAY,KAAK,UAAU;AAAA,YACjC;AAAA,UACD;AAEA,cAAI,QAAQ,SAAS;AACpB,qBAAS,KAAK,GAAG,KAAK,QAAQ,QAAQ,QAAQ,MAAM;AACnD,kBAAI,iBAAiB,QAAQ,QAAQ,EAAE;AACvC,kBAAI,aAAa,aAAa,sBAAsB,cAAc;AAClE,kBAAI,CAAC;AAAY,sBAAM,IAAI,MAAM,oCAAoC,2BAA2B,QAAQ,OAAO;AAC/G,mBAAK,YAAY,KAAK,UAAU;AAAA,YACjC;AAAA,UACD;AAEA,mBAAS,YAAY,QAAQ,aAAa;AACzC,gBAAI,OAAO,aAAa,SAAS,QAAQ;AACzC,gBAAI,CAAC;AAAM,oBAAM,IAAI,MAAM,sBAAsB,qBAAqB,QAAQ,OAAO;AACrF,gBAAI,UAAU,QAAQ,YAAY,QAAQ;AAC1C,qBAAS,aAAa,SAAS;AAC9B,kBAAI,aAAa,KAAK,eAAe,QAAQ,SAAS,GAAG,MAAM,KAAK,OAAO,WAAW,YAAY;AAClG,kBAAI;AAAY,qBAAK,cAAc,KAAK,OAAO,WAAW,UAAU;AAAA,YACrE;AAAA,UACD;AACA,uBAAa,MAAM,KAAK,IAAI;AAC5B,cAAI,KAAK,QAAQ;AAAW,yBAAa,cAAc;AAAA,QACxD;AAAA,MACD;AAGA,eAAS,IAAI,GAAG,IAAI,KAAK,aAAa,QAAQ,IAAI,GAAG,KAAK;AACzD,YAAI,aAAa,KAAK,aAAa,CAAC;AACpC,YAAI,OAAO,CAAC,WAAW,OAAO,aAAa,cAAc,aAAa,SAAS,WAAW,IAAI;AAC9F,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,mBAAmB,WAAW,MAAM;AAC/D,YAAI,SAAS,KAAK,cAAc,WAAW,WAAW,WAAW,MAAM;AACvE,YAAI,CAAC;AAAQ,gBAAM,IAAI,MAAM,0BAA0B,WAAW,QAAQ;AAC1E,mBAAW,KAAK,qBAAqB,WAAW,kBAAoC,SAA2B,WAAW;AAC1H,mBAAW,KAAK,cAA8B,MAAM;AACpD,YAAI,WAAW,KAAK,UAAU;AAAM,qBAAW,KAAK,aAAa;AAAA,MAClE;AACA,WAAK,aAAa,SAAS;AAG3B,UAAI,KAAK,QAAQ;AAChB,iBAAS,aAAa,KAAK,QAAQ;AAClC,cAAI,WAAW,KAAK,OAAO,SAAS;AACpC,cAAI,OAAO,IAAI,UAAU,SAAS;AAClC,eAAK,WAAW,SAAS,UAAU,OAAO,CAAC;AAC3C,eAAK,aAAa,SAAS,UAAU,SAAS,CAAC;AAC/C,eAAK,cAAc,SAAS,UAAU,UAAU,EAAE;AAClD,eAAK,YAAY,SAAS,UAAU,SAAS,IAAI;AACjD,cAAI,KAAK,WAAW;AACnB,iBAAK,SAAS,SAAS,UAAU,UAAU,CAAC;AAC5C,iBAAK,UAAU,SAAS,UAAU,WAAW,CAAC;AAAA,UAC/C;AACA,uBAAa,OAAO,KAAK,IAAI;AAAA,QAC9B;AAAA,MACD;AAGA,UAAI,KAAK,YAAY;AACpB,iBAAS,iBAAiB,KAAK,YAAY;AAC1C,cAAI,eAAe,KAAK,WAAW,aAAa;AAChD,eAAK,cAAc,cAAc,eAAe,YAAY;AAAA,QAC7D;AAAA,MACD;AAEA,aAAO;AAAA,IACR;AAAA,IAEA,eAAgB,KAAU,MAAY,WAAmB,MAAc,cAA+C;AACrH,UAAI,QAAQ,KAAK;AACjB,aAAO,SAAS,KAAK,QAAQ,IAAI;AAEjC,cAAQ,SAAS,KAAK,QAAQ,QAAQ,GAAG;AAAA,QACxC,KAAK,UAAU;AACd,cAAI,OAAO,SAAS,KAAK,QAAQ,IAAI;AACrC,cAAI,WAAW,KAAK,aAAa,SAAS,KAAK,YAAY,IAAI,CAAC;AAChE,cAAI,SAAS,KAAK,iBAAiB,oBAAoB,MAAM,MAAM,MAAM,QAAQ;AACjF,cAAI,CAAC;AAAQ,mBAAO;AACpB,iBAAO,OAAO;AACd,iBAAO,IAAI,SAAS,KAAK,KAAK,CAAC,IAAI;AACnC,iBAAO,IAAI,SAAS,KAAK,KAAK,CAAC,IAAI;AACnC,iBAAO,SAAS,SAAS,KAAK,UAAU,CAAC;AACzC,iBAAO,SAAS,SAAS,KAAK,UAAU,CAAC;AACzC,iBAAO,WAAW,SAAS,KAAK,YAAY,CAAC;AAC7C,iBAAO,QAAQ,IAAI,QAAQ;AAC3B,iBAAO,SAAS,IAAI,SAAS;AAC7B,iBAAO,WAAW;AAElB,cAAI,QAAgB,SAAS,KAAK,SAAS,IAAI;AAC/C,cAAI;AAAO,mBAAO,MAAM,cAAc,KAAK;AAE3C,cAAI,OAAO,UAAU;AAAM,mBAAO,aAAa;AAC/C,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,eAAe;AACnB,cAAI,MAAM,KAAK,iBAAiB,yBAAyB,MAAM,IAAI;AACnE,cAAI,CAAC;AAAK,mBAAO;AACjB,eAAK,aAAa,KAAK,KAAK,IAAI,eAAe,CAAC;AAChD,cAAI,QAAgB,SAAS,KAAK,SAAS,IAAI;AAC/C,cAAI;AAAO,gBAAI,MAAM,cAAc,KAAK;AACxC,iBAAO;AAAA,QACR;AAAA,QACA,KAAK;AAAA,QACL,KAAK,cAAc;AAClB,cAAI,OAAO,SAAS,KAAK,QAAQ,IAAI;AACrC,cAAI,WAAW,KAAK,aAAa,SAAS,KAAK,YAAY,IAAI,CAAC;AAChE,cAAI,OAAO,KAAK,iBAAiB,kBAAkB,MAAM,MAAM,MAAM,QAAQ;AAC7E,cAAI,CAAC;AAAM,mBAAO;AAClB,eAAK,OAAO;AAEZ,cAAI,QAAQ,SAAS,KAAK,SAAS,IAAI;AACvC,cAAI;AAAO,iBAAK,MAAM,cAAc,KAAK;AAEzC,eAAK,QAAQ,SAAS,KAAK,SAAS,CAAC,IAAI;AACzC,eAAK,SAAS,SAAS,KAAK,UAAU,CAAC,IAAI;AAC3C,eAAK,WAAW;AAEhB,cAAI,SAAiB,SAAS,KAAK,UAAU,IAAI;AACjD,cAAI,QAAQ;AACX,iBAAK,aAAa,KAAK,IAAIC,YAAW,MAAc,SAAS,KAAK,QAAQ,IAAI,GAAG,WAAW,QAAQ,SAAS,KAAK,aAAa,IAAI,CAAC,CAAC;AACrI,mBAAO;AAAA,UACR;AAEA,cAAI,MAAqB,IAAI;AAC7B,eAAK,aAAa,KAAK,MAAM,IAAI,MAAM;AACvC,eAAK,YAAY,IAAI;AACrB,eAAK,YAAY;AACjB,cAAI,KAAK,UAAU;AAAM,iBAAK,aAAa;AAE3C,eAAK,QAAQ,SAAS,KAAK,SAAS,IAAI;AACxC,eAAK,aAAa,SAAS,KAAK,QAAQ,CAAC,IAAI;AAC7C,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,QAAQ;AACZ,cAAI,OAAO,KAAK,iBAAiB,kBAAkB,MAAM,IAAI;AAC7D,cAAI,CAAC;AAAM,mBAAO;AAClB,eAAK,SAAS,SAAS,KAAK,UAAU,KAAK;AAC3C,eAAK,gBAAgB,SAAS,KAAK,iBAAiB,IAAI;AAExD,cAAI,cAAc,IAAI;AACtB,eAAK,aAAa,KAAK,MAAM,eAAe,CAAC;AAE7C,cAAI,UAAyB,MAAM,SAAS,cAAc,GAAG,CAAC;AAC9D,mBAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,QAAQ;AACvC,oBAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI;AAC/B,eAAK,UAAU;AAEf,cAAI,QAAgB,SAAS,KAAK,SAAS,IAAI;AAC/C,cAAI;AAAO,iBAAK,MAAM,cAAc,KAAK;AACzC,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,SAAS;AACb,cAAI,QAAQ,KAAK,iBAAiB,mBAAmB,MAAM,IAAI;AAC/D,cAAI,CAAC;AAAO,mBAAO;AACnB,gBAAM,IAAI,SAAS,KAAK,KAAK,CAAC,IAAI;AAClC,gBAAM,IAAI,SAAS,KAAK,KAAK,CAAC,IAAI;AAClC,gBAAM,WAAW,SAAS,KAAK,YAAY,CAAC;AAE5C,cAAI,QAAQ,SAAS,KAAK,SAAS,IAAI;AACvC,cAAI;AAAO,kBAAM,MAAM,cAAc,KAAK;AAC1C,iBAAO;AAAA,QACR;AAAA,QACA,KAAK,YAAY;AAChB,cAAI,OAAO,KAAK,iBAAiB,sBAAsB,MAAM,IAAI;AACjE,cAAI,CAAC;AAAM,mBAAO;AAElB,cAAI,MAAM,SAAS,KAAK,OAAO,IAAI;AACnC,cAAI;AAAK,iBAAK,UAAU,aAAa,SAAS,GAAG;AAEjD,cAAI,cAAc,IAAI;AACtB,eAAK,aAAa,KAAK,MAAM,eAAe,CAAC;AAE7C,cAAI,QAAgB,SAAS,KAAK,SAAS,IAAI;AAC/C,cAAI;AAAO,iBAAK,MAAM,cAAc,KAAK;AACzC,iBAAO;AAAA,QACR;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,IAEA,aAAc,KAAU;AACvB,UAAI,OAAO;AAAM,eAAO;AACxB,UAAI,WAAW,IAAI,SAAS,SAAS,KAAK,SAAS,CAAC,CAAC;AACrD,eAAS,QAAQ,SAAS,KAAK,SAAS,CAAC;AACzC,eAAS,SAAS,SAAS,KAAK,UAAU,CAAC;AAC3C,eAAS,aAAa,SAAS,KAAK,SAAS,CAAC;AAC9C,aAAO;AAAA,IACR;AAAA,IAEA,aAAc,KAAU,YAA8B,gBAAwB;AAC7E,UAAI,QAAQ,KAAK;AACjB,iBAAW,sBAAsB;AACjC,UAAI,WAA0B,IAAI;AAClC,UAAI,kBAAkB,SAAS,QAAQ;AACtC,YAAI,iBAAiB,MAAM,aAAa,QAAQ;AAChD,YAAI,SAAS,GAAG;AACf,mBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG;AAC3C,2BAAe,CAAC,KAAK;AAAA,QACvB;AACA,mBAAW,WAAW;AACtB;AAAA,MACD;AACA,UAAI,UAAU,IAAI,MAAc;AAChC,UAAI,QAAQ,IAAI,MAAc;AAC9B,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,KAAI;AAC5C,YAAI,YAAY,SAAS,GAAG;AAC5B,cAAM,KAAK,SAAS;AACpB,iBAAS,KAAK,IAAI,YAAY,GAAG,IAAI,IAAI,KAAK,GAAG;AAChD,gBAAM,KAAK,SAAS,CAAC,CAAC;AACtB,kBAAQ,KAAK,SAAS,IAAI,CAAC,IAAI,KAAK;AACpC,kBAAQ,KAAK,SAAS,IAAI,CAAC,IAAI,KAAK;AACpC,kBAAQ,KAAK,SAAS,IAAI,CAAC,CAAC;AAAA,QAC7B;AAAA,MACD;AACA,iBAAW,QAAQ;AACnB,iBAAW,WAAW,MAAM,aAAa,OAAO;AAAA,IACjD;AAAA,IAEA,cAAe,KAAU,MAAc,cAA4B;AAClE,UAAI,QAAQ,KAAK;AACjB,UAAI,YAAY,IAAI,MAAgB;AAGpC,UAAI,IAAI,OAAO;AACd,iBAAS,YAAY,IAAI,OAAO;AAC/B,cAAI,UAAU,IAAI,MAAM,QAAQ;AAChC,cAAI,OAAO,aAAa,SAAS,QAAQ;AACzC,cAAI,CAAC;AAAM,kBAAM,IAAI,MAAM,qBAAqB,QAAQ;AACxD,cAAI,YAAY,KAAK;AACrB,mBAAS,gBAAgB,SAAS;AACjC,gBAAI,cAAc,QAAQ,YAAY;AACtC,gBAAI,CAAC;AAAa;AAClB,gBAAI,SAAS,YAAY;AACzB,gBAAI,gBAAgB,cAAc;AACjC,kBAAI,WAAW,IAAI,mBAAmB,QAAQ,SAAS;AACvD,uBAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS;AAC5C,oBAAI,SAAS,YAAY,KAAK;AAC9B,yBAAS,SAAS,OAAO,SAAS,QAAQ,QAAQ,CAAC,GAAG,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,cACrF;AACA,wBAAU,KAAK,QAAQ;AAAA,YAExB,WAAW,gBAAgB,QAAQ;AAClC,kBAAI,WAAW,IAAI,aAAa,QAAQ,UAAU,GAAG,SAAS;AAC9D,kBAAI,SAAS,YAAY,CAAC;AAC1B,kBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,kBAAI,QAAQ,MAAM,WAAW,OAAO,KAAK;AAEzC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACjE,oBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,oBAAI,CAAC,SAAS;AACb,2BAAS,OAAO,MAAM;AACtB;AAAA,gBACD;AACA,oBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,oBAAI,WAAW,MAAM,WAAW,QAAQ,KAAK;AAC7C,oBAAI,QAAQ,OAAO;AACnB,oBAAI,OAAO;AACV,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AAAA,gBAC1F;AACA,uBAAO;AACP,wBAAQ;AACR,yBAAS;AAAA,cACV;AAEA,wBAAU,KAAK,QAAQ;AAAA,YAExB,WAAW,gBAAgB,OAAO;AACjC,kBAAI,WAAW,IAAI,YAAY,QAAQ,SAAS,GAAG,SAAS;AAC5D,kBAAI,SAAS,YAAY,CAAC;AAC1B,kBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,kBAAI,QAAQ,MAAM,WAAW,OAAO,KAAK;AAEzC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACxD,oBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,oBAAI,CAAC,SAAS;AACb,2BAAS,OAAO,MAAM;AACtB;AAAA,gBACD;AACA,oBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,oBAAI,WAAW,MAAM,WAAW,QAAQ,KAAK;AAC7C,oBAAI,QAAQ,OAAO;AACnB,oBAAI,OAAO;AACV,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AAAA,gBAC1F;AACA,uBAAO;AACP,wBAAQ;AACR,yBAAS;AAAA,cACV;AAEA,wBAAU,KAAK,QAAQ;AAAA,YAExB,WAAW,gBAAgB,SAAS;AACnC,wBAAU,KAAKC,eAAc,aAAa,IAAI,cAAc,QAAQ,QAAQ,SAAS,GAAG,GAAG,CAAC,CAAC;AAAA,YAC9F,WAAW,gBAAgB,SAAS;AACnC,kBAAI,WAAW,IAAI,cAAc,QAAQ,SAAS,GAAG,SAAS;AAE9D,kBAAI,SAAS,YAAY,CAAC;AAC1B,kBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,kBAAI,QAAQ,MAAM,WAAW,OAAO,KAAK;AACzC,kBAAI,SAAS,MAAM,WAAW,OAAO,IAAI;AAEzC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAC/F,oBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,oBAAI,CAAC,SAAS;AACb,2BAAS,OAAO,MAAM;AACtB;AAAA,gBACD;AACA,oBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,oBAAI,WAAW,MAAM,WAAW,QAAQ,KAAK;AAC7C,oBAAI,YAAY,MAAM,WAAW,QAAQ,IAAI;AAC7C,oBAAI,QAAQ,OAAO;AACnB,oBAAI,OAAO;AACV,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,UAAU,GAAG,CAAC;AAC3F,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,UAAU,GAAG,CAAC;AAC3F,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,UAAU,GAAG,CAAC;AAAA,gBAC5F;AACA,uBAAO;AACP,wBAAQ;AACR,yBAAS;AACT,yBAAS;AAAA,cACV;AAEA,wBAAU,KAAK,QAAQ;AAAA,YAExB,WAAW,gBAAgB,QAAQ;AAClC,kBAAI,WAAW,IAAI,aAAa,QAAQ,SAAS,GAAG,SAAS;AAE7D,kBAAI,SAAS,YAAY,CAAC;AAC1B,kBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,kBAAI,QAAQ,MAAM,WAAW,OAAO,KAAK;AACzC,kBAAI,SAAS,MAAM,WAAW,OAAO,IAAI;AAEzC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AACtF,oBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,oBAAI,CAAC,SAAS;AACb,2BAAS,OAAO,MAAM;AACtB;AAAA,gBACD;AACA,oBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,oBAAI,WAAW,MAAM,WAAW,QAAQ,KAAK;AAC7C,oBAAI,YAAY,MAAM,WAAW,QAAQ,IAAI;AAC7C,oBAAI,QAAQ,OAAO;AACnB,oBAAI,OAAO;AACV,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,GAAG,SAAS,GAAG,CAAC;AACzF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,UAAU,GAAG,CAAC;AAC3F,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,UAAU,GAAG,CAAC;AAC3F,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,GAAG,UAAU,GAAG,CAAC;AAAA,gBAC5F;AACA,uBAAO;AACP,wBAAQ;AACR,yBAAS;AACT,yBAAS;AAAA,cACV;AAEA,wBAAU,KAAK,QAAQ;AAAA,YACxB;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,UAAI,IAAI,OAAO;AACd,iBAAS,YAAY,IAAI,OAAO;AAC/B,cAAI,UAAU,IAAI,MAAM,QAAQ;AAChC,cAAI,OAAO,aAAa,SAAS,QAAQ;AACzC,cAAI,CAAC;AAAM,kBAAM,IAAI,MAAM,qBAAqB,QAAQ;AACxD,cAAI,YAAY,KAAK;AACrB,mBAAS,gBAAgB,SAAS;AACjC,gBAAI,cAAc,QAAQ,YAAY;AACtC,gBAAI,SAAS,YAAY;AACzB,gBAAI,UAAU;AAAG;AAEjB,gBAAI,iBAAiB,UAAU;AAC9B,wBAAU,KAAKA,eAAc,aAAa,IAAI,eAAe,QAAQ,QAAQ,SAAS,GAAG,GAAG,CAAC,CAAC;AAAA,YAC/F,WAAW,iBAAiB,aAAa;AACxC,kBAAI,WAAW,IAAI,kBAAkB,QAAQ,UAAU,GAAG,SAAS;AACnE,wBAAU,KAAKC,eAAc,aAAa,UAAU,KAAK,KAAK,GAAG,KAAK,CAAC;AAAA,YACxE,WAAW,iBAAiB,cAAc;AACzC,kBAAI,WAAW,IAAI,mBAAmB,QAAQ,QAAQ,SAAS;AAC/D,wBAAU,KAAKD,eAAc,aAAa,UAAU,GAAG,KAAK,CAAC;AAAA,YAC9D,WAAW,iBAAiB,cAAc;AACzC,kBAAI,WAAW,IAAI,mBAAmB,QAAQ,QAAQ,SAAS;AAC/D,wBAAU,KAAKA,eAAc,aAAa,UAAU,GAAG,KAAK,CAAC;AAAA,YAC9D,WAAW,iBAAiB,SAAS;AACpC,kBAAI,WAAW,IAAI,cAAc,QAAQ,UAAU,GAAG,SAAS;AAC/D,wBAAU,KAAKC,eAAc,aAAa,UAAU,KAAK,KAAK,GAAG,CAAC,CAAC;AAAA,YACpE,WAAW,iBAAiB,UAAU;AACrC,kBAAI,WAAW,IAAI,eAAe,QAAQ,QAAQ,SAAS;AAC3D,wBAAU,KAAKD,eAAc,aAAa,UAAU,GAAG,CAAC,CAAC;AAAA,YAC1D,WAAW,iBAAiB,UAAU;AACrC,kBAAI,WAAW,IAAI,eAAe,QAAQ,QAAQ,SAAS;AAC3D,wBAAU,KAAKA,eAAc,aAAa,UAAU,GAAG,CAAC,CAAC;AAAA,YAC1D,WAAW,iBAAiB,SAAS;AACpC,kBAAI,WAAW,IAAI,cAAc,QAAQ,UAAU,GAAG,SAAS;AAC/D,wBAAU,KAAKC,eAAc,aAAa,UAAU,KAAK,KAAK,GAAG,CAAC,CAAC;AAAA,YACpE,WAAW,iBAAiB,UAAU;AACrC,kBAAI,WAAW,IAAI,eAAe,QAAQ,QAAQ,SAAS;AAC3D,wBAAU,KAAKD,eAAc,aAAa,UAAU,GAAG,CAAC,CAAC;AAAA,YAC1D,WAAW,iBAAiB,UAAU;AACrC,kBAAI,WAAW,IAAI,eAAe,QAAQ,QAAQ,SAAS;AAC3D,wBAAU,KAAKA,eAAc,aAAa,UAAU,GAAG,CAAC,CAAC;AAAA,YAC1D,WAAW,iBAAiB,WAAW;AACtC,kBAAI,WAAW,IAAI,gBAAgB,QAAQ,KAAK,KAAK;AACrD,uBAAS,QAAQ,GAAG,QAAQ,YAAY,QAAQ,SAAS;AACxD,oBAAI,SAAS,YAAY,KAAK;AAC9B,yBAAS,SAAS,OAAO,SAAS,QAAQ,QAAQ,CAAC,GAAG,MAAM,UAAU,SAAS,SAAS,QAAQ,WAAW,QAAQ,CAAC,CAAC;AAAA,cACtH;AACA,wBAAU,KAAK,QAAQ;AAAA,YACxB;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,UAAI,IAAI,IAAI;AACX,iBAAS,kBAAkB,IAAI,IAAI;AAClC,cAAI,gBAAgB,IAAI,GAAG,cAAc;AACzC,cAAI,SAAS,cAAc,CAAC;AAC5B,cAAI,CAAC;AAAQ;AAEb,cAAI,aAAa,aAAa,iBAAiB,cAAc;AAC7D,cAAI,CAAC;AAAY,kBAAM,IAAI,MAAM,8BAA8B,cAAc;AAC7E,cAAI,kBAAkB,aAAa,cAAc,QAAQ,UAAU;AACnE,cAAI,WAAW,IAAI,qBAAqB,cAAc,QAAQ,cAAc,UAAU,GAAG,eAAe;AAExG,cAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,cAAI,MAAM,SAAS,QAAQ,OAAO,CAAC;AACnC,cAAI,WAAW,SAAS,QAAQ,YAAY,CAAC,IAAI;AAEjD,mBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,qBAAS,SAAS,OAAO,MAAM,KAAK,UAAU,SAAS,QAAQ,gBAAgB,IAAI,IAAI,IAAI,IAAI,SAAS,QAAQ,YAAY,KAAK,GAAG,SAAS,QAAQ,WAAW,KAAK,CAAC;AACtK,gBAAI,UAAU,cAAc,QAAQ,CAAC;AACrC,gBAAI,CAAC,SAAS;AACb,uBAAS,OAAO,MAAM;AACtB;AAAA,YACD;AAEA,gBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,gBAAI,OAAO,SAAS,SAAS,OAAO,CAAC;AACrC,gBAAI,YAAY,SAAS,SAAS,YAAY,CAAC,IAAI;AACnD,gBAAI,QAAQ,OAAO;AACnB,gBAAI,OAAO;AACV,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,KAAK,MAAM,CAAC;AAC/E,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,UAAU,WAAW,KAAK;AAAA,YAC9F;AAEA,mBAAO;AACP,kBAAM;AACN,uBAAW;AACX,qBAAS;AAAA,UACV;AACA,oBAAU,KAAK,QAAQ;AAAA,QACxB;AAAA,MACD;AAGA,UAAI,IAAI,WAAW;AAClB,iBAAS,kBAAkB,IAAI,WAAW;AACzC,cAAI,cAAc,IAAI,UAAU,cAAc;AAC9C,cAAI,SAAS,YAAY,CAAC;AAC1B,cAAI,CAAC;AAAQ;AAEb,cAAI,aAAa,aAAa,wBAAwB,cAAc;AACpE,cAAI,CAAC;AAAY,kBAAM,IAAI,MAAM,qCAAqC,cAAc;AACpF,cAAI,kBAAkB,aAAa,qBAAqB,QAAQ,UAAU;AAC1E,cAAI,WAAW,IAAI,4BAA4B,YAAY,QAAQ,YAAY,SAAS,GAAG,eAAe;AAE1G,cAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,cAAI,YAAY,SAAS,QAAQ,aAAa,CAAC;AAC/C,cAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,cAAI,OAAO,SAAS,QAAQ,QAAQ,IAAI;AACxC,cAAI,YAAY,SAAS,QAAQ,aAAa,CAAC;AAC/C,cAAI,YAAY,SAAS,QAAQ,aAAa,SAAS;AACvD,cAAI,YAAY,SAAS,QAAQ,aAAa,CAAC;AAE/C,mBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,qBAAS,SAAS,OAAO,MAAM,WAAW,MAAM,MAAM,WAAW,WAAW,SAAS;AACrF,gBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,gBAAI,CAAC,SAAS;AACb,uBAAS,OAAO,MAAM;AACtB;AAAA,YACD;AAEA,gBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,gBAAI,aAAa,SAAS,SAAS,aAAa,CAAC;AACjD,gBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,gBAAI,QAAQ,SAAS,SAAS,QAAQ,KAAK;AAC3C,gBAAI,aAAa,SAAS,SAAS,aAAa,CAAC;AACjD,gBAAI,aAAa,SAAS,SAAS,aAAa,UAAU;AAC1D,gBAAI,aAAa,SAAS,SAAS,aAAa,CAAC;AACjD,gBAAI,QAAQ,OAAO;AACnB,gBAAI,OAAO;AACV,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AAC3F,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AACjF,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AACjF,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AAC3F,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AAC3F,uBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AAAA,YAC5F;AAEA,mBAAO;AACP,wBAAY;AACZ,mBAAO;AACP,mBAAO;AACP,wBAAY;AACZ,wBAAY;AACZ,wBAAY;AACZ,qBAAS;AAAA,UACV;AACA,oBAAU,KAAK,QAAQ;AAAA,QACxB;AAAA,MACD;AAGA,UAAI,IAAI,MAAM;AACb,iBAAS,kBAAkB,IAAI,MAAM;AACpC,cAAI,gBAAgB,IAAI,KAAK,cAAc;AAC3C,cAAI,aAAa,aAAa,mBAAmB,cAAc;AAC/D,cAAI,CAAC;AAAY,kBAAM,IAAI,MAAM,gCAAgC,cAAc;AAC/E,cAAI,kBAAkB,aAAa,gBAAgB,QAAQ,UAAU;AACrE,mBAAS,gBAAgB,eAAe;AACvC,gBAAI,cAAc,cAAc,YAAY;AAC5C,gBAAI,SAAS,YAAY,CAAC;AAC1B,gBAAI,CAAC;AAAQ;AAEb,gBAAI,SAAS,YAAY;AACzB,gBAAI,iBAAiB,YAAY;AAChC,kBAAI,WAAW,IAAI,+BAA+B,QAAQ,QAAQ,eAAe;AACjF,wBAAU,KAAKA,eAAc,aAAa,UAAU,GAAG,WAAW,gCAAqC,QAAQ,CAAC,CAAC;AAAA,YAClH,WAAW,iBAAiB,WAAW;AACtC,kBAAI,WAAW,IAAI,8BAA8B,QAAQ,QAAQ,eAAe;AAChF,wBAAU,KAAKA,eAAc,aAAa,UAAU,GAAG,WAAW,iCAAqC,WAAW,+BAAmC,QAAQ,CAAC,CAAC;AAAA,YAChK,WAAW,iBAAiB,OAAO;AAClC,kBAAI,WAAW,IAAI,0BAA0B,QAAQ,SAAS,GAAG,eAAe;AAChF,kBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,kBAAI,YAAY,SAAS,QAAQ,aAAa,CAAC;AAC/C,kBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,kBAAI,OAAO,SAAS,QAAQ,QAAQ,IAAI;AACxC,uBAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,yBAAS,SAAS,OAAO,MAAM,WAAW,MAAM,IAAI;AACpD,oBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,oBAAI,CAAC,SAAS;AACb,2BAAS,OAAO,MAAM;AACtB;AAAA,gBACD;AACA,oBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,oBAAI,aAAa,SAAS,SAAS,aAAa,CAAC;AACjD,oBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,oBAAI,QAAQ,SAAS,SAAS,QAAQ,KAAK;AAC3C,oBAAI,QAAQ,OAAO;AACnB,oBAAI,OAAO;AACV,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,WAAW,YAAY,CAAC;AAC3F,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AACjF,2BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,MAAM,OAAO,CAAC;AAAA,gBAClF;AACA,uBAAO;AACP,4BAAY;AACZ,uBAAO;AACP,uBAAO;AACP,yBAAS;AAAA,cACV;AACA,wBAAU,KAAK,QAAQ;AAAA,YACxB;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,UAAI,IAAI,SAAS;AAChB,iBAAS,kBAAkB,IAAI,SAAS;AACvC,cAAI,gBAAgB,IAAI,QAAQ,cAAc;AAC9C,cAAI,kBAAkB;AACtB,cAAI,eAAe,SAAS,GAAG;AAC9B,gBAAI,aAAa,aAAa,sBAAsB,cAAc;AAClE,gBAAI,CAAC;AAAY,oBAAM,IAAI,MAAM,mCAAmC,cAAc;AAClF,8BAAkB,aAAa,mBAAmB,QAAQ,UAAU;AAAA,UACrE;AACA,mBAAS,gBAAgB,eAAe;AACvC,gBAAI,cAAc,cAAc,YAAY;AAC5C,gBAAI,SAAS,YAAY,CAAC;AAC1B,gBAAI,CAAC;AAAQ;AAEb,gBAAI,SAAS,YAAY;AACzB,gBAAI,gBAAgB,SAAS;AAC5B,oBAAME,YAAW,IAAI,+BAA+B,QAAQ,eAAe;AAC3E,uBAAS,QAAQ,GAAG,UAAU,MAAM,SAAS,YAAY,QAAQ,CAAC,GAAG;AACpE,gBAAAA,UAAS,SAAS,OAAO,SAAS,QAAQ,QAAQ,CAAC,CAAC;AACrD,wBAAU,KAAKA,SAAQ;AACvB;AAAA,YACD;AAEA,gBAAI;AACJ,gBAAI,gBAAgB;AACnB,yBAAW,IAAI,iCAAiC,QAAQ,QAAQ,eAAe;AAAA,qBACvE,gBAAgB;AACxB,yBAAW,IAAI,kCAAkC,QAAQ,QAAQ,eAAe;AAAA,qBACxE,gBAAgB;AACxB,yBAAW,IAAI,iCAAiC,QAAQ,QAAQ,eAAe;AAAA,qBACvE,gBAAgB;AACxB,yBAAW,IAAI,8BAA8B,QAAQ,QAAQ,eAAe;AAAA,qBACpE,gBAAgB;AACxB,yBAAW,IAAI,8BAA8B,QAAQ,QAAQ,eAAe;AAAA,qBACpE,gBAAgB;AACxB,yBAAW,IAAI,iCAAiC,QAAQ,QAAQ,eAAe;AAAA,qBACvE,gBAAgB;AACxB,yBAAW,IAAI,6BAA6B,QAAQ,QAAQ,eAAe;AAAA;AAE3E;AACD,sBAAU,KAAKF,eAAc,aAAa,UAAU,GAAG,CAAC,CAAC;AAAA,UAC1D;AAAA,QACD;AAAA,MACD;AAGA,UAAI,IAAI,aAAa;AACpB,iBAAS,mBAAmB,IAAI,aAAa;AAC5C,cAAI,iBAAiB,IAAI,YAAY,eAAe;AACpD,cAAI,OAAO,aAAa,SAAS,eAAe;AAChD,cAAI,CAAC;AAAM,kBAAM,IAAI,MAAM,qBAAqB,eAAe;AAC/D,mBAAS,eAAe,gBAAgB;AACvC,gBAAI,UAAU,eAAe,WAAW;AACxC,gBAAI,OAAO,aAAa,SAAS,WAAW;AAC5C,gBAAI,CAAC;AAAM,oBAAM,IAAI,MAAM,qBAAqB,WAAW;AAC3D,gBAAI,YAAY,KAAK;AACrB,qBAAS,qBAAqB,SAAS;AACtC,kBAAI,gBAAgB,QAAQ,iBAAiB;AAC7C,kBAAI,aAA+B,KAAK,cAAc,WAAW,iBAAiB;AAElF,uBAAS,mBAAmB,eAAe;AAC1C,oBAAI,cAAc,cAAc,eAAe;AAC/C,oBAAI,SAAS,YAAY,CAAC;AAC1B,oBAAI,CAAC;AAAQ;AAEb,oBAAI,mBAAmB,UAAU;AAChC,sBAAI,WAAW,WAAW;AAC1B,sBAAI,WAAW,WAAW;AAC1B,sBAAI,eAAe,WAAW,SAAS,SAAS,IAAI,IAAI,SAAS;AAEjE,sBAAI,WAAW,IAAI,eAAe,YAAY,QAAQ,YAAY,QAAQ,WAAW,UAAU;AAC/F,sBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,2BAAS,QAAQ,GAAG,SAAS,KAAK,SAAS;AAC1C,wBAAI;AACJ,wBAAI,gBAA+B,SAAS,QAAQ,YAAY,IAAI;AACpE,wBAAI,CAAC;AACJ,+BAAS,WAAW,MAAM,cAAc,YAAY,IAAI;AAAA,yBACpD;AACJ,+BAAS,MAAM,cAAc,YAAY;AACzC,0BAAI,QAAgB,SAAS,QAAQ,UAAU,CAAC;AAChD,4BAAM,UAAU,eAAe,GAAG,QAAQ,OAAO,cAAc,MAAM;AACrE,0BAAI,SAAS,GAAG;AACf,iCAAS,IAAI,OAAO,IAAI,IAAI,cAAc,QAAQ,IAAI,GAAG;AACxD,iCAAO,CAAC,KAAK;AAAA,sBACf;AACA,0BAAI,CAAC,UAAU;AACd,iCAAS,IAAI,GAAG,IAAI,cAAc;AACjC,iCAAO,CAAC,KAAK,SAAS,CAAC;AAAA,sBACzB;AAAA,oBACD;AAEA,6BAAS,SAAS,OAAO,MAAM,MAAM;AACrC,wBAAI,UAAU,YAAY,QAAQ,CAAC;AACnC,wBAAI,CAAC,SAAS;AACb,+BAAS,OAAO,MAAM;AACtB;AAAA,oBACD;AACA,wBAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,wBAAI,QAAQ,OAAO;AACnB,wBAAI;AAAO,+BAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,GAAG,GAAG,CAAC;AACrF,2BAAO;AACP,6BAAS;AAAA,kBACV;AACA,4BAAU,KAAK,QAAQ;AAAA,gBACxB,WAAW,mBAAmB,YAAY;AACzC,sBAAI,WAAW,IAAI,iBAAiB,YAAY,QAAQ,WAAW,UAAyC;AAC5G,sBAAI,YAAY;AAChB,2BAAS,QAAQ,GAAG,QAAQ,YAAY,QAAQ,SAAS;AACxD,wBAAI,QAAQ,SAAS,QAAQ,SAAS,SAAS;AAC/C,wBAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,wBAAI,OAAO,aAAa,SAAS,QAAQ,QAAQ,MAAM,CAAC;AACxD,wBAAI,QAAQ,SAAS,QAAQ,SAAS,CAAC;AACvC,6BAAS,SAAS,OAAO,MAAM,MAAM,OAAO,KAAK;AACjD,gCAAY;AACZ,6BAAS,YAAY,QAAQ,CAAC;AAAA,kBAC/B;AACA,4BAAU,KAAK,QAAQ;AAAA,gBACxB;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,UAAI,IAAI,WAAW;AAClB,YAAI,WAAW,IAAI,kBAAkB,IAAI,UAAU,MAAM;AACzD,YAAI,YAAY,aAAa,MAAM;AACnC,YAAI,QAAQ;AACZ,iBAAS,IAAI,GAAG,IAAI,IAAI,UAAU,QAAQ,KAAK,SAAS;AACvD,cAAI,eAAe,IAAI,UAAU,CAAC;AAClC,cAAI,YAAkC;AACtC,cAAI,UAAU,SAAS,cAAc,WAAW,IAAI;AACpD,cAAI,SAAS;AACZ,wBAAY,MAAM,SAAiB,WAAW,EAAE;AAChD,gBAAI,YAAY,MAAM,SAAiB,YAAY,QAAQ,QAAQ,CAAC;AACpE,gBAAI,gBAAgB,GAAG,iBAAiB;AACxC,qBAAS,KAAK,GAAG,KAAK,QAAQ,QAAQ,MAAM;AAC3C,kBAAI,YAAY,QAAQ,EAAE;AAC1B,kBAAI,OAAO,aAAa,SAAS,UAAU,IAAI;AAC/C,kBAAI,CAAC;AAAM,sBAAM,IAAI,MAAM,qBAAqB,IAAI;AACpD,kBAAI,YAAY,KAAK;AAErB,qBAAO,iBAAiB;AACvB,0BAAU,gBAAgB,IAAI;AAE/B,wBAAU,gBAAgB,UAAU,MAAM,IAAI;AAAA,YAC/C;AAEA,mBAAO,gBAAgB;AACtB,wBAAU,gBAAgB,IAAI;AAE/B,qBAAS,KAAK,YAAY,GAAG,MAAM,GAAG;AACrC,kBAAI,UAAU,EAAE,KAAK;AAAI,0BAAU,EAAE,IAAI,UAAU,EAAE,cAAc;AAAA,UACrE;AACA,mBAAS,SAAS,OAAO,SAAS,cAAc,QAAQ,CAAC,GAAG,SAAS;AAAA,QACtE;AACA,kBAAU,KAAK,QAAQ;AAAA,MACxB;AAGA,UAAI,IAAI,QAAQ;AACf,YAAI,WAAW,IAAI,cAAc,IAAI,OAAO,MAAM;AAClD,YAAI,QAAQ;AACZ,iBAAS,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,SAAS;AACpD,cAAI,WAAW,IAAI,OAAO,CAAC;AAC3B,cAAI,YAAY,aAAa,UAAU,SAAS,IAAI;AACpD,cAAI,CAAC;AAAW,kBAAM,IAAI,MAAM,sBAAsB,SAAS,IAAI;AACnE,cAAI,QAAQ,IAAI,MAAM,MAAM,kBAAkB,SAAS,UAAU,QAAQ,CAAC,CAAC,GAAG,SAAS;AACvF,gBAAM,WAAW,SAAS,UAAU,OAAO,UAAU,QAAQ;AAC7D,gBAAM,aAAa,SAAS,UAAU,SAAS,UAAU,UAAU;AACnE,gBAAM,cAAc,SAAS,UAAU,UAAU,UAAU,WAAW;AACtE,cAAI,MAAM,KAAK,WAAW;AACzB,kBAAM,SAAS,SAAS,UAAU,UAAU,CAAC;AAC7C,kBAAM,UAAU,SAAS,UAAU,WAAW,CAAC;AAAA,UAChD;AACA,mBAAS,SAAS,OAAO,KAAK;AAAA,QAC/B;AACA,kBAAU,KAAK,QAAQ;AAAA,MACxB;AAEA,UAAI,WAAW;AACf,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG;AAC5C,mBAAW,KAAK,IAAI,UAAU,UAAU,CAAC,EAAE,YAAY,CAAC;AACzD,mBAAa,WAAW,KAAK,IAAI,UAAU,MAAM,WAAW,QAAQ,CAAC;AAAA,IACtE;AAAA,EACD;AAEA,MAAMD,cAAN,MAAiB;AAAA,IAChB;AAAA,IAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IAEA,YAAa,MAAsB,MAAc,WAAmB,QAAgB,eAAwB;AAC3G,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,YAAY;AACjB,WAAK,SAAS;AACd,WAAK,kBAAkB;AAAA,IACxB;AAAA,EACD;AAEA,WAASC,eAAe,MAAa,UAA0B,cAAsB,OAAe;AACnG,QAAI,SAAS,KAAK,CAAC;AACnB,QAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,QAAI,QAAQ,SAAS,QAAQ,SAAS,YAAY,IAAI;AACtD,QAAI,SAAS;AACb,aAAS,QAAQ,KAAK,SAAS;AAC9B,eAAS,SAAS,OAAO,MAAM,KAAK;AACpC,UAAI,UAAU,KAAK,QAAQ,CAAC;AAC5B,UAAI,CAAC,SAAS;AACb,iBAAS,OAAO,MAAM;AACtB,eAAO;AAAA,MACR;AACA,UAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,UAAI,SAAS,SAAS,SAAS,SAAS,YAAY,IAAI;AACxD,UAAI,OAAO;AAAO,iBAAS,UAAU,OAAO,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,OAAO,QAAQ,KAAK;AAChH,aAAO;AACP,cAAQ;AACR,eAAS;AAAA,IACV;AAAA,EACD;AAEA,WAASC,eAAe,MAAa,UAA0B,OAAe,OAAe,cAAsB,OAAe;AACjI,QAAI,SAAS,KAAK,CAAC;AACnB,QAAI,OAAO,SAAS,QAAQ,QAAQ,CAAC;AACrC,QAAI,SAAS,SAAS,QAAQ,OAAO,YAAY,IAAI;AACrD,QAAI,SAAS,SAAS,QAAQ,OAAO,YAAY,IAAI;AACrD,QAAI,SAAS;AACb,aAAS,QAAQ,KAAK,SAAS;AAC9B,eAAS,SAAS,OAAO,MAAM,QAAQ,MAAM;AAC7C,UAAI,UAAU,KAAK,QAAQ,CAAC;AAC5B,UAAI,CAAC,SAAS;AACb,iBAAS,OAAO,MAAM;AACtB,eAAO;AAAA,MACR;AACA,UAAI,QAAQ,SAAS,SAAS,QAAQ,CAAC;AACvC,UAAI,UAAU,SAAS,SAAS,OAAO,YAAY,IAAI;AACvD,UAAI,UAAU,SAAS,SAAS,OAAO,YAAY,IAAI;AACvD,UAAI,QAAQ,OAAO;AACnB,UAAI,OAAO;AACV,iBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,QAAQ,SAAS,KAAK;AACzF,iBAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,GAAG,MAAM,OAAO,QAAQ,SAAS,KAAK;AAAA,MAC1F;AACA,aAAO;AACP,eAAS;AACT,eAAS;AACT,eAAS;AAAA,IACV;AAAA,EACD;AAEA,WAAS,UAAW,OAAY,UAAyB,QAAgB,OAAe,OAAe,OAAe,OACrH,QAAgB,QAAgB,OAAe;AAC/C,QAAI,SAAS,WAAW;AACvB,eAAS,WAAW,KAAK;AACzB,aAAO;AAAA,IACR;AACA,QAAI,IAAI,SAAS;AACjB,QAAI,MAAM,MAAM,CAAC;AACjB,QAAI,MAAM,MAAM,IAAI,CAAC,IAAI;AACzB,QAAI,MAAM,MAAM,IAAI,CAAC;AACrB,QAAI,MAAM,MAAM,IAAI,CAAC,IAAI;AACzB,aAAS,UAAU,QAAQ,OAAO,OAAO,OAAO,QAAQ,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM;AACzF,WAAO,SAAS;AAAA,EACjB;AAEA,WAAS,SAAU,KAAU,UAAkB,cAAmB;AACjE,WAAO,IAAI,QAAQ,MAAM,SAAY,IAAI,QAAQ,IAAI;AAAA,EACtD;;;ACtnCA,GAAC,MAAM;AACN,QAAI,OAAO,KAAK,WAAW,aAAa;AACvC,WAAK,SAAU,SAAU,OAAO;AAC/B,eAAO,SAAU,GAAW;AAC3B,iBAAO,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC;AAAA,QAC7B;AAAA,MACD,EAAG,IAAI,aAAa,CAAC,CAAC;AAAA,IACvB;AAAA,EACD,GAAG;;;ACNI,MAAM,+BAAN,MAAmC;AAAA,IAClC;AAAA,IACA;AAAA,IACC,cAAc,IAAI,MAAkB;AAAA,IAE5C,YAAa,iBAA4D,gBAAqB,EAAE,OAAO,OAAO,GAAG;AAChH,UAAI,EAAG,2BAA2B,yBAA2B,OAAO,2BAA2B,eAAe,2BAA2B,yBAA0B;AAClK,YAAI,SAA4B;AAChC,aAAK,KAA6B,OAAO,WAAW,UAAU,aAAa,KAAK,OAAO,WAAW,SAAS,aAAa;AACxH,aAAK,SAAS;AACd,eAAO,iBAAiB,oBAAoB,CAAC,MAAW;AACvD,cAAI,QAA2B;AAC/B,cAAI;AAAG,cAAE,eAAe;AAAA,QACzB,CAAC;AACD,eAAO,iBAAiB,wBAAwB,CAAC,MAAW;AAC3D,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,IAAI,GAAG;AACnD,iBAAK,YAAY,CAAC,EAAE,QAAQ;AAAA,QAC9B,CAAC;AAAA,MACF,OAAO;AACN,aAAK,KAAK;AACV,aAAK,SAAS,KAAK,GAAG;AAAA,MACvB;AAAA,IACD;AAAA,IAEA,cAAe,YAAwB;AACtC,WAAK,YAAY,KAAK,UAAU;AAAA,IACjC;AAAA,IAEA,iBAAkB,YAAwB;AACzC,UAAI,QAAQ,KAAK,YAAY,QAAQ,UAAU;AAC/C,UAAI,QAAQ;AAAI,aAAK,YAAY,OAAO,OAAO,CAAC;AAAA,IACjD;AAAA,EACD;;;AC/BO,MAAM,aAAN,cAAwB,QAA0C;AAAA,IACxE;AAAA,IACQ,UAA+B;AAAA,IAC/B,YAAY;AAAA,IACZ,aAAa;AAAA,IAIrB,YAAa,SAA+D,OAAuC,aAAsB,OAAO;AAC/I,YAAM,KAAK;AACX,WAAK,UAAU,mBAAmB,+BAA+B,UAAU,IAAI,6BAA6B,OAAO;AACnH,WAAK,aAAa;AAClB,WAAK,QAAQ;AACb,WAAK,QAAQ,cAAc,IAAI;AAAA,IAChC;AAAA,IAEA,WAAY,WAA0B,WAA0B;AAC/D,UAAI,KAAK,KAAK,QAAQ;AACtB,WAAK,KAAK;AACV,SAAG,cAAc,GAAG,YAAY,GAAG,oBAAoB,SAAS;AAChE,SAAG,cAAc,GAAG,YAAY,GAAG,oBAAoB,WAAU,kBAAkB,SAAS,CAAC;AAC7F,WAAK,aAAa,WAAU,YAAY,SAAS;AACjD,UAAI,KAAK;AAAY,WAAG,eAAe,GAAG,UAAU;AAAA,IACrD;AAAA,IAEA,OAAO,kBAAmB,WAA0B;AACnD,cAAQ,WAAW;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AACC;AAAA,QACD;AACC,iBAAO;AAAA,MACT;AAAA,IACD;AAAA,IAEA,OAAO,YAAa,QAAuB;AAC1C,cAAQ,QAAQ;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AACC,iBAAO;AAAA,QACR;AACC,iBAAO;AAAA,MACT;AAAA,IACD;AAAA,IAEA,SAAU,OAAoB,OAAoB;AACjD,UAAI,KAAK,KAAK,QAAQ;AACtB,WAAK,KAAK;AACV,SAAG,cAAc,GAAG,YAAY,GAAG,gBAAgB,KAAK;AACxD,SAAG,cAAc,GAAG,YAAY,GAAG,gBAAgB,KAAK;AAAA,IACzD;AAAA,IAEA,OAAQ,YAAqB;AAC5B,UAAI,KAAK,KAAK,QAAQ;AACtB,UAAI,CAAC,KAAK;AAAS,aAAK,UAAU,KAAK,QAAQ,GAAG,cAAc;AAChE,WAAK,KAAK;AACV,UAAI,WAAU;AAA0C,WAAG,YAAY,GAAG,gCAAgC,KAAK;AAC/G,SAAG,WAAW,GAAG,YAAY,GAAG,GAAG,MAAM,GAAG,MAAM,GAAG,eAAe,KAAK,MAAM;AAC/E,SAAG,cAAc,GAAG,YAAY,GAAG,oBAAoB,GAAG,MAAM;AAChE,SAAG,cAAc,GAAG,YAAY,GAAG,oBAAoB,aAAa,GAAG,uBAAuB,GAAG,MAAM;AACvG,SAAG,cAAc,GAAG,YAAY,GAAG,gBAAgB,GAAG,aAAa;AACnE,SAAG,cAAc,GAAG,YAAY,GAAG,gBAAgB,GAAG,aAAa;AACnE,UAAI;AAAY,WAAG,eAAe,GAAG,UAAU;AAAA,IAChD;AAAA,IAEA,UAAW;AACV,WAAK,UAAU;AACf,WAAK,OAAO,KAAK,UAAU;AAAA,IAC5B;AAAA,IAEA,KAAM,OAAe,GAAG;AACvB,UAAI,KAAK,KAAK,QAAQ;AACtB,WAAK,YAAY;AACjB,SAAG,cAAc,GAAG,WAAW,IAAI;AACnC,SAAG,YAAY,GAAG,YAAY,KAAK,OAAO;AAAA,IAC3C;AAAA,IAEA,SAAU;AACT,UAAI,KAAK,KAAK,QAAQ;AACtB,SAAG,cAAc,GAAG,WAAW,KAAK,SAAS;AAC7C,SAAG,YAAY,GAAG,YAAY,IAAI;AAAA,IACnC;AAAA,IAEA,UAAW;AACV,WAAK,QAAQ,iBAAiB,IAAI;AAClC,UAAI,KAAK,KAAK,QAAQ;AACtB,SAAG,cAAc,KAAK,OAAO;AAAA,IAC9B;AAAA,EACD;AA5FO,MAAM,YAAN;AAMN,gBANY,WAME,4CAA2C;;;ACJnD,MAAM,eAAN,cAA2B,iBAAiB;AAAA,IAClD,YAAa,SAA+D,aAAqB,IAAI,aAAyB,IAAI,WAAW,GAAG;AAC/I,YAAM,CAAC,UAA0C;AAChD,eAAO,IAAI,UAAU,SAAS,KAAK;AAAA,MACpC,GAAG,YAAY,UAAU;AAAA,IAC1B;AAAA,EACD;;;ACTO,MAAM,UAAN,MAAc;AAAA,IACpB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IAEJ,YAAa,IAAY,GAAG,IAAY,GAAG,IAAY,GAAG;AACzD,WAAK,IAAI;AACT,WAAK,IAAI;AACT,WAAK,IAAI;AAAA,IACV;AAAA,IAEA,QAAS,GAAqB;AAC7B,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,EAAE;AACX,aAAO;AAAA,IACR;AAAA,IAEA,IAAK,GAAW,GAAW,GAAoB;AAC9C,WAAK,IAAI;AACT,WAAK,IAAI;AACT,WAAK,IAAI;AACT,aAAO;AAAA,IACR;AAAA,IAEA,IAAK,GAAqB;AACzB,WAAK,KAAK,EAAE;AACZ,WAAK,KAAK,EAAE;AACZ,WAAK,KAAK,EAAE;AACZ,aAAO;AAAA,IACR;AAAA,IAEA,IAAK,GAAqB;AACzB,WAAK,KAAK,EAAE;AACZ,WAAK,KAAK,EAAE;AACZ,WAAK,KAAK,EAAE;AACZ,aAAO;AAAA,IACR;AAAA,IAEA,MAAO,GAAoB;AAC1B,WAAK,KAAK;AACV,WAAK,KAAK;AACV,WAAK,KAAK;AACV,aAAO;AAAA,IACR;AAAA,IAEA,YAAsB;AACrB,UAAI,MAAM,KAAK,OAAO;AACtB,UAAI,OAAO;AAAG,eAAO;AACrB,YAAM,IAAI;AACV,WAAK,KAAK;AACV,WAAK,KAAK;AACV,WAAK,KAAK;AACV,aAAO;AAAA,IACR;AAAA,IAEA,MAAO,GAAqB;AAC3B,aAAO,KAAK,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,IACtG;AAAA,IAEA,SAAU,QAA0B;AACnC,UAAI,QAAQ,OAAO;AACnB,aAAO,KAAK;AAAA,QAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG;AAAA,QAC1F,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG;AAAA,QAC3E,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG;AAAA,MAAC;AAAA,IAC9E;AAAA,IAEA,QAAS,QAA0B;AAClC,UAAI,QAAQ,OAAO;AACnB,UAAI,MAAM,KAAK,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG;AAC1F,aAAO,KAAK;AAAA,SAAK,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,KAAK;AAAA,SAC/F,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,KAAK;AAAA,SAChF,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,KAAK;AAAA,MAAG;AAAA,IACtF;AAAA,IAEA,IAAK,GAAoB;AACxB,aAAO,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE;AAAA,IACjD;AAAA,IAEA,SAAkB;AACjB,aAAO,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IACrE;AAAA,IAEA,SAAU,GAAoB;AAC7B,UAAI,IAAI,EAAE,IAAI,KAAK;AACnB,UAAI,IAAI,EAAE,IAAI,KAAK;AACnB,UAAI,IAAI,EAAE,IAAI,KAAK;AACnB,aAAO,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;AAAA,IACvC;AAAA,EACD;;;ACzFO,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AAEZ,MAAM,WAAN,MAAc;AAAA,IACpB,OAAqB,IAAI,aAAa,EAAE;AAAA,IACxC,SAAuB,IAAI,aAAa,EAAE;AAAA,IAO1C,cAAe;AACd,UAAI,IAAI,KAAK;AACb,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AAAA,IACV;AAAA,IAEA,IAAK,QAAoC;AACxC,WAAK,OAAO,IAAI,MAAM;AACtB,aAAO;AAAA,IACR;AAAA,IAEA,YAAsB;AACrB,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,KAAK;AACb,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,QAAE,GAAG,IAAI,EAAE,GAAG;AACd,aAAO,KAAK,IAAI,CAAC;AAAA,IAClB;AAAA,IAEA,WAAqB;AACpB,UAAI,IAAI,KAAK;AACb,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,aAAO;AAAA,IACR;AAAA,IAEA,SAAmB;AAClB,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,KAAK;AACb,UAAI,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACjH,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC3G,UAAI,SAAS;AAAG,cAAM,IAAI,MAAM,uBAAuB;AACvD,UAAI,UAAU,IAAM;AACpB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACnF,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAChF,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI;AAClB,aAAO;AAAA,IACR;AAAA,IAEA,cAAuB;AACtB,UAAI,IAAI,KAAK;AACb,aAAO,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAC5G,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IACxG,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAAA,IAC5G;AAAA,IAEA,UAAW,GAAW,GAAW,GAAoB;AACpD,UAAI,IAAI,KAAK;AACb,QAAE,GAAG,KAAK;AACV,QAAE,GAAG,KAAK;AACV,QAAE,GAAG,KAAK;AACV,aAAO;AAAA,IACR;AAAA,IAEA,OAAiB;AAChB,aAAO,IAAI,SAAQ,EAAE,IAAI,KAAK,MAAM;AAAA,IACrC;AAAA,IAEA,WAAY,MAAc,KAAa,MAAc,aAA8B;AAClF,WAAK,SAAS;AACd,UAAI,OAAQ,IAAM,KAAK,IAAK,QAAQ,KAAK,KAAK,OAAQ,CAAG;AACzD,UAAI,QAAQ,MAAM,SAAS,OAAO;AAClC,UAAI,OAAQ,IAAI,MAAM,QAAS,OAAO;AACtC,UAAI,IAAI,KAAK;AACb,QAAE,GAAG,IAAI,OAAO;AAChB,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,aAAO;AAAA,IACR;AAAA,IAEA,QAAS,GAAW,GAAW,OAAe,QAAyB;AACtE,aAAO,KAAK,MAAM,GAAG,IAAI,OAAO,GAAG,IAAI,QAAQ,GAAG,CAAC;AAAA,IACpD;AAAA,IAEA,MAAO,MAAc,OAAe,QAAgB,KAAa,MAAc,KAAsB;AACpG,WAAK,SAAS;AACd,UAAI,SAAS,KAAK,QAAQ;AAC1B,UAAI,SAAS,KAAK,MAAM;AACxB,UAAI,SAAS,MAAM,MAAM;AAEzB,UAAI,KAAK,EAAE,QAAQ,SAAS,QAAQ;AACpC,UAAI,KAAK,EAAE,MAAM,WAAW,MAAM;AAClC,UAAI,KAAK,EAAE,MAAM,SAAS,MAAM;AAEhC,UAAI,IAAI,KAAK;AACb,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,QAAE,GAAG,IAAI;AACT,aAAO;AAAA,IACR;AAAA,IAEA,SAAU,QAA0B;AACnC,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,OAAO;AACf,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,aAAO,KAAK,IAAI,KAAK,IAAI;AAAA,IAC1B;AAAA,IAEA,aAAc,QAA0B;AACvC,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,KAAK;AACb,UAAI,IAAI,OAAO;AACf,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG;AAC7E,QAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAA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", + "names": ["Matrix4", "Phaser", "worldVertices", "v", "SequenceMode", "MixBlend", "MixDirection", "x", "y", "i", "vertexAttachment", "constraint", "i", "n", "timeline", "EventType", "TextureFilter", "TextureWrap", "page", "worldVertices", "worldVertices", "Inherit", "s", "PositionMode", "SpacingMode", "RotateMode", "closed", "pathLength", "multiplier", "Physics", "BlendMode", "closed", "AttachmentType", "n", "LinkedMesh", "readTimeline1", "readTimeline2", "timeline", "Matrix4", "Matrix4", "VertexAttributeType", "temp", "ShapeType", "i", "n", "n", "ResizeMode", "bounds", "_SkeletonRenderer", "SkeletonRenderer", "SkeletonRenderer", "SpineSkeletonDataFileType"] +} diff --git a/spine-ts/spine-phaser-v3/dist/index.d.ts b/spine-ts/spine-phaser-v3/dist/index.d.ts new file mode 100644 index 000000000..f4f58dede --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/index.d.ts @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +export * from "./require-shim.js"; +export * from "./SpinePlugin.js"; +export * from "./SpineGameObject.js"; +export * from "./mixins.js"; +export * from "@esotericsoftware/spine-core"; +export * from "@esotericsoftware/spine-webgl"; +import { SpineGameObjectConfig, SpinePlugin } from "./SpinePlugin.js"; +import { SpineGameObject, SpineGameObjectBoundsProvider } from "./SpineGameObject.js"; +declare global { + namespace Phaser.Loader { + interface LoaderPlugin { + spineJson(key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin; + spineBinary(key: string, url: string, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin; + spineAtlas(key: string, url: string, premultipliedAlpha?: boolean, xhrSettings?: Phaser.Types.Loader.XHRSettingsObject): LoaderPlugin; + } + } + namespace Phaser.GameObjects { + interface GameObjectFactory { + spine(x: number, y: number, dataKey: string, atlasKey: string, boundsProvider?: SpineGameObjectBoundsProvider): SpineGameObject; + } + interface GameObjectCreator { + spine(config: SpineGameObjectConfig, addToScene?: boolean): SpineGameObject; + } + } + namespace Phaser { + interface Scene { + spine: SpinePlugin; + } + } +} diff --git a/spine-ts/spine-phaser-v3/dist/index.js b/spine-ts/spine-phaser-v3/dist/index.js new file mode 100644 index 000000000..e82948b73 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/index.js @@ -0,0 +1,38 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +export * from "./require-shim.js"; +export * from "./SpinePlugin.js"; +export * from "./SpineGameObject.js"; +export * from "./mixins.js"; +export * from "@esotericsoftware/spine-core"; +export * from "@esotericsoftware/spine-webgl"; +import { SpinePlugin } from "./SpinePlugin.js"; +window.spine = { SpinePlugin: SpinePlugin }; +window["spine.SpinePlugin"] = SpinePlugin; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRS9FLGNBQWMsbUJBQW1CLENBQUE7QUFDakMsY0FBYyxrQkFBa0IsQ0FBQTtBQUNoQyxjQUFjLHNCQUFzQixDQUFBO0FBQ3BDLGNBQWMsYUFBYSxDQUFBO0FBQzNCLGNBQWMsOEJBQThCLENBQUM7QUFDN0MsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxPQUFPLEVBQXlCLFdBQVcsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3JFLE1BQWMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQUM7QUFDcEQsTUFBYyxDQUFDLG1CQUFtQixDQUFDLEdBQUcsV0FBVyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBKdWx5IDI4LCAyMDIzLiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjMsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3JcbiAqIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSEVcbiAqIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5leHBvcnQgKiBmcm9tIFwiLi9yZXF1aXJlLXNoaW0uanNcIlxuZXhwb3J0ICogZnJvbSBcIi4vU3BpbmVQbHVnaW4uanNcIlxuZXhwb3J0ICogZnJvbSBcIi4vU3BpbmVHYW1lT2JqZWN0LmpzXCJcbmV4cG9ydCAqIGZyb20gXCIuL21peGlucy5qc1wiXG5leHBvcnQgKiBmcm9tIFwiQGVzb3Rlcmljc29mdHdhcmUvc3BpbmUtY29yZVwiO1xuZXhwb3J0ICogZnJvbSBcIkBlc290ZXJpY3NvZnR3YXJlL3NwaW5lLXdlYmdsXCI7XG5pbXBvcnQgeyBTcGluZUdhbWVPYmplY3RDb25maWcsIFNwaW5lUGx1Z2luIH0gZnJvbSBcIi4vU3BpbmVQbHVnaW4uanNcIjtcbih3aW5kb3cgYXMgYW55KS5zcGluZSA9IHsgU3BpbmVQbHVnaW46IFNwaW5lUGx1Z2luIH07XG4od2luZG93IGFzIGFueSlbXCJzcGluZS5TcGluZVBsdWdpblwiXSA9IFNwaW5lUGx1Z2luO1xuXG5pbXBvcnQgeyBTcGluZUdhbWVPYmplY3QsIFNwaW5lR2FtZU9iamVjdEJvdW5kc1Byb3ZpZGVyIH0gZnJvbSBcIi4vU3BpbmVHYW1lT2JqZWN0LmpzXCI7XG5cbmRlY2xhcmUgZ2xvYmFsIHtcblx0bmFtZXNwYWNlIFBoYXNlci5Mb2FkZXIge1xuXHRcdGV4cG9ydCBpbnRlcmZhY2UgTG9hZGVyUGx1Z2luIHtcblx0XHRcdHNwaW5lSnNvbiAoa2V5OiBzdHJpbmcsIHVybDogc3RyaW5nLCB4aHJTZXR0aW5ncz86IFBoYXNlci5UeXBlcy5Mb2FkZXIuWEhSU2V0dGluZ3NPYmplY3QpOiBMb2FkZXJQbHVnaW47XG5cdFx0XHRzcGluZUJpbmFyeSAoa2V5OiBzdHJpbmcsIHVybDogc3RyaW5nLCB4aHJTZXR0aW5ncz86IFBoYXNlci5UeXBlcy5Mb2FkZXIuWEhSU2V0dGluZ3NPYmplY3QpOiBMb2FkZXJQbHVnaW47XG5cdFx0XHRzcGluZUF0bGFzIChrZXk6IHN0cmluZywgdXJsOiBzdHJpbmcsIHByZW11bHRpcGxpZWRBbHBoYT86IGJvb2xlYW4sIHhoclNldHRpbmdzPzogUGhhc2VyLlR5cGVzLkxvYWRlci5YSFJTZXR0aW5nc09iamVjdCk6IExvYWRlclBsdWdpbjtcblx0XHR9XG5cdH1cblxuXHRuYW1lc3BhY2UgUGhhc2VyLkdhbWVPYmplY3RzIHtcblx0XHRleHBvcnQgaW50ZXJmYWNlIEdhbWVPYmplY3RGYWN0b3J5IHtcblx0XHRcdHNwaW5lICh4OiBudW1iZXIsIHk6IG51bWJlciwgZGF0YUtleTogc3RyaW5nLCBhdGxhc0tleTogc3RyaW5nLCBib3VuZHNQcm92aWRlcj86IFNwaW5lR2FtZU9iamVjdEJvdW5kc1Byb3ZpZGVyKTogU3BpbmVHYW1lT2JqZWN0O1xuXHRcdH1cblxuXHRcdGV4cG9ydCBpbnRlcmZhY2UgR2FtZU9iamVjdENyZWF0b3Ige1xuXHRcdFx0c3BpbmUgKGNvbmZpZzogU3BpbmVHYW1lT2JqZWN0Q29uZmlnLCBhZGRUb1NjZW5lPzogYm9vbGVhbik6IFNwaW5lR2FtZU9iamVjdDtcblx0XHR9XG5cdH1cblxuXHRuYW1lc3BhY2UgUGhhc2VyIHtcblx0XHRleHBvcnQgaW50ZXJmYWNlIFNjZW5lIHtcblx0XHRcdHNwaW5lOiBTcGluZVBsdWdpbjtcblx0XHR9XG5cdH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/spine-ts/spine-phaser-v3/dist/keys.d.ts b/spine-ts/spine-phaser-v3/dist/keys.d.ts new file mode 100644 index 000000000..d5ad39375 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/keys.d.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +export declare const SPINE_SKELETON_FILE_CACHE_KEY = "esotericsoftware.spine.skeletonFile.cache"; +export declare const SPINE_ATLAS_CACHE_KEY = "esotericsoftware.spine.atlas.cache"; +export declare const SPINE_LOADER_TYPE = "spine"; +export declare const SPINE_SKELETON_DATA_FILE_TYPE = "spineSkeletonData"; +export declare const SPINE_ATLAS_FILE_TYPE = "spineAtlasData"; +export declare const SPINE_GAME_OBJECT_TYPE = "spine"; diff --git a/spine-ts/spine-phaser-v3/dist/keys.js b/spine-ts/spine-phaser-v3/dist/keys.js new file mode 100644 index 000000000..2744dfb34 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/keys.js @@ -0,0 +1,35 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +export const SPINE_SKELETON_FILE_CACHE_KEY = "esotericsoftware.spine.skeletonFile.cache"; +export const SPINE_ATLAS_CACHE_KEY = "esotericsoftware.spine.atlas.cache"; +export const SPINE_LOADER_TYPE = "spine"; +export const SPINE_SKELETON_DATA_FILE_TYPE = "spineSkeletonData"; +export const SPINE_ATLAS_FILE_TYPE = "spineAtlasData"; +export const SPINE_GAME_OBJECT_TYPE = "spine"; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9rZXlzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0VBMkIrRTtBQUUvRSxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRywyQ0FBMkMsQ0FBQztBQUN6RixNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxvQ0FBb0MsQ0FBQztBQUMxRSxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUM7QUFDekMsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQUcsbUJBQW1CLENBQUM7QUFDakUsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsZ0JBQWdCLENBQUM7QUFDdEQsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsT0FBTyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBKdWx5IDI4LCAyMDIzLiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjMsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3JcbiAqIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSEVcbiAqIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5leHBvcnQgY29uc3QgU1BJTkVfU0tFTEVUT05fRklMRV9DQUNIRV9LRVkgPSBcImVzb3Rlcmljc29mdHdhcmUuc3BpbmUuc2tlbGV0b25GaWxlLmNhY2hlXCI7XG5leHBvcnQgY29uc3QgU1BJTkVfQVRMQVNfQ0FDSEVfS0VZID0gXCJlc290ZXJpY3NvZnR3YXJlLnNwaW5lLmF0bGFzLmNhY2hlXCI7XG5leHBvcnQgY29uc3QgU1BJTkVfTE9BREVSX1RZUEUgPSBcInNwaW5lXCI7XG5leHBvcnQgY29uc3QgU1BJTkVfU0tFTEVUT05fREFUQV9GSUxFX1RZUEUgPSBcInNwaW5lU2tlbGV0b25EYXRhXCI7XG5leHBvcnQgY29uc3QgU1BJTkVfQVRMQVNfRklMRV9UWVBFID0gXCJzcGluZUF0bGFzRGF0YVwiO1xuZXhwb3J0IGNvbnN0IFNQSU5FX0dBTUVfT0JKRUNUX1RZUEUgPSBcInNwaW5lXCI7XG4iXX0= \ No newline at end of file diff --git a/spine-ts/spine-phaser-v3/dist/mixins.d.ts b/spine-ts/spine-phaser-v3/dist/mixins.d.ts new file mode 100644 index 000000000..a845fb3ab --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/mixins.d.ts @@ -0,0 +1,30 @@ +export declare const ComputedSize: any; +export declare const Depth: any; +export declare const Flip: any; +export declare const ScrollFactor: any; +export declare const Transform: any; +export declare const Visible: any; +export declare const Origin: any; +export declare const Alpha: any; +export interface Type extends Function { + new (...args: P): T; +} +export type Mixin = >(BaseGameObject: GameObjectType) => GameObjectType & Type; +export declare function createMixin(...component: GameObjectComponent[]): Mixin; +type ComputedSizeMixin = Mixin; +export declare const ComputedSizeMixin: ComputedSizeMixin; +type DepthMixin = Mixin; +export declare const DepthMixin: DepthMixin; +type FlipMixin = Mixin; +export declare const FlipMixin: FlipMixin; +type ScrollFactorMixin = Mixin; +export declare const ScrollFactorMixin: ScrollFactorMixin; +type TransformMixin = Mixin; +export declare const TransformMixin: TransformMixin; +type VisibleMixin = Mixin; +export declare const VisibleMixin: VisibleMixin; +type OriginMixin = Mixin; +export declare const OriginMixin: OriginMixin; +type AlphaMixin = Mixin; +export declare const AlphaMixin: AlphaMixin; +export {}; diff --git a/spine-ts/spine-phaser-v3/dist/mixins.js b/spine-ts/spine-phaser-v3/dist/mixins.js new file mode 100644 index 000000000..2a8bce6c4 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/mixins.js @@ -0,0 +1,48 @@ +/* +The MIT License (MIT) + +Copyright (c) 2021-present AgogPixel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +// Adapted from https://github.com/agogpixel/phaser3-ts-utils/tree/main +let components = Phaser.GameObjects.Components; +export const ComputedSize = components.ComputedSize; +export const Depth = components.Depth; +export const Flip = components.Flip; +export const ScrollFactor = components.ScrollFactor; +export const Transform = components.Transform; +export const Visible = components.Visible; +export const Origin = components.Origin; +export const Alpha = components.Alpha; +export function createMixin(...component) { + return (BaseGameObject) => { + Phaser.Class.mixin(BaseGameObject, component); + return BaseGameObject; + }; +} +export const ComputedSizeMixin = createMixin(ComputedSize); +export const DepthMixin = createMixin(Depth); +export const FlipMixin = createMixin(Flip); +export const ScrollFactorMixin = createMixin(ScrollFactor); +export const TransformMixin = createMixin(Transform); +export const VisibleMixin = createMixin(Visible); +export const OriginMixin = createMixin(Origin); +export const AlphaMixin = createMixin(Alpha); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWl4aW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21peGlucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQXNCRTtBQUVGLHVFQUF1RTtBQUV2RSxJQUFJLFVBQVUsR0FBSSxNQUFNLENBQUMsV0FBVyxDQUFDLFVBQWtCLENBQUM7QUFDeEQsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUM7QUFDcEQsTUFBTSxDQUFDLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUM7QUFDdEMsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUM7QUFDcEMsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUM7QUFDcEQsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUM7QUFDOUMsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUM7QUFDMUMsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7QUFDeEMsTUFBTSxDQUFDLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUM7QUFldEMsTUFBTSxVQUFVLFdBQVcsQ0FJMUIsR0FBRyxTQUFnQztJQUVuQyxPQUFPLENBQUMsY0FBYyxFQUFFLEVBQUU7UUFDeEIsTUFBYyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZELE9BQU8sY0FBcUIsQ0FBQztJQUM5QixDQUFDLENBQUM7QUFDSCxDQUFDO0FBR0QsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQXNCLFdBQVcsQ0FBNkMsWUFBWSxDQUFDLENBQUM7QUFHMUgsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFlLFdBQVcsQ0FBc0MsS0FBSyxDQUFDLENBQUM7QUFHOUYsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFjLFdBQVcsQ0FBcUMsSUFBSSxDQUFDLENBQUM7QUFHMUYsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQXNCLFdBQVcsQ0FBNkMsWUFBWSxDQUFDLENBQUM7QUFHMUgsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFtQixXQUFXLENBQTBDLFNBQVMsQ0FBQyxDQUFDO0FBRzlHLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBaUIsV0FBVyxDQUF3QyxPQUFPLENBQUMsQ0FBQztBQUd0RyxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQWdCLFdBQVcsQ0FBdUMsTUFBTSxDQUFDLENBQUM7QUFHbEcsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFlLFdBQVcsQ0FBc0MsS0FBSyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuVGhlIE1JVCBMaWNlbnNlIChNSVQpXG5cbkNvcHlyaWdodCAoYykgMjAyMS1wcmVzZW50IEFnb2dQaXhlbFxuXG5QZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG5vZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG5pbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG50byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG5jb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbmZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG5GSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbkxJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG5PVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRVxuU09GVFdBUkUuXG4qL1xuXG4vLyBBZGFwdGVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2Fnb2dwaXhlbC9waGFzZXIzLXRzLXV0aWxzL3RyZWUvbWFpblxuXG5sZXQgY29tcG9uZW50cyA9IChQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cyBhcyBhbnkpO1xuZXhwb3J0IGNvbnN0IENvbXB1dGVkU2l6ZSA9IGNvbXBvbmVudHMuQ29tcHV0ZWRTaXplO1xuZXhwb3J0IGNvbnN0IERlcHRoID0gY29tcG9uZW50cy5EZXB0aDtcbmV4cG9ydCBjb25zdCBGbGlwID0gY29tcG9uZW50cy5GbGlwO1xuZXhwb3J0IGNvbnN0IFNjcm9sbEZhY3RvciA9IGNvbXBvbmVudHMuU2Nyb2xsRmFjdG9yO1xuZXhwb3J0IGNvbnN0IFRyYW5zZm9ybSA9IGNvbXBvbmVudHMuVHJhbnNmb3JtO1xuZXhwb3J0IGNvbnN0IFZpc2libGUgPSBjb21wb25lbnRzLlZpc2libGU7XG5leHBvcnQgY29uc3QgT3JpZ2luID0gY29tcG9uZW50cy5PcmlnaW47XG5leHBvcnQgY29uc3QgQWxwaGEgPSBjb21wb25lbnRzLkFscGhhO1xuXG5leHBvcnQgaW50ZXJmYWNlIFR5cGU8XG5cdFQsXG5cdFAgZXh0ZW5kcyBhbnlbXSA9IGFueVtdXG5cdD4gZXh0ZW5kcyBGdW5jdGlvbiB7XG5cdG5ldyguLi5hcmdzOiBQKTogVDtcbn1cblxuZXhwb3J0IHR5cGUgTWl4aW48R2FtZU9iamVjdENvbXBvbmVudCwgR2FtZU9iamVjdENvbnN0cmFpbnQgZXh0ZW5kcyBQaGFzZXIuR2FtZU9iamVjdHMuR2FtZU9iamVjdD4gPSA8XG5cdEdhbWVPYmplY3RUeXBlIGV4dGVuZHMgVHlwZTxHYW1lT2JqZWN0Q29uc3RyYWludD5cblx0Pihcblx0QmFzZUdhbWVPYmplY3Q6IEdhbWVPYmplY3RUeXBlXG4pID0+IEdhbWVPYmplY3RUeXBlICYgVHlwZTxHYW1lT2JqZWN0Q29tcG9uZW50PjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1peGluPFxuXHRHYW1lT2JqZWN0Q29tcG9uZW50LFxuXHRHYW1lT2JqZWN0Q29uc3RyYWludCBleHRlbmRzIFBoYXNlci5HYW1lT2JqZWN0cy5HYW1lT2JqZWN0ID0gUGhhc2VyLkdhbWVPYmplY3RzLkdhbWVPYmplY3Rcbj4gKFxuXHQuLi5jb21wb25lbnQ6IEdhbWVPYmplY3RDb21wb25lbnRbXVxuKTogTWl4aW48R2FtZU9iamVjdENvbXBvbmVudCwgR2FtZU9iamVjdENvbnN0cmFpbnQ+IHtcblx0cmV0dXJuIChCYXNlR2FtZU9iamVjdCkgPT4ge1xuXHRcdChQaGFzZXIgYXMgYW55KS5DbGFzcy5taXhpbihCYXNlR2FtZU9iamVjdCwgY29tcG9uZW50KTtcblx0XHRyZXR1cm4gQmFzZUdhbWVPYmplY3QgYXMgYW55O1xuXHR9O1xufVxuXG50eXBlIENvbXB1dGVkU2l6ZU1peGluID0gTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuQ29tcHV0ZWRTaXplLCBQaGFzZXIuR2FtZU9iamVjdHMuR2FtZU9iamVjdD47XG5leHBvcnQgY29uc3QgQ29tcHV0ZWRTaXplTWl4aW46IENvbXB1dGVkU2l6ZU1peGluID0gY3JlYXRlTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuQ29tcHV0ZWRTaXplPihDb21wdXRlZFNpemUpO1xuXG50eXBlIERlcHRoTWl4aW4gPSBNaXhpbjxQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cy5EZXB0aCwgUGhhc2VyLkdhbWVPYmplY3RzLkdhbWVPYmplY3Q+O1xuZXhwb3J0IGNvbnN0IERlcHRoTWl4aW46IERlcHRoTWl4aW4gPSBjcmVhdGVNaXhpbjxQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cy5EZXB0aD4oRGVwdGgpO1xuXG50eXBlIEZsaXBNaXhpbiA9IE1peGluPFBoYXNlci5HYW1lT2JqZWN0cy5Db21wb25lbnRzLkZsaXAsIFBoYXNlci5HYW1lT2JqZWN0cy5HYW1lT2JqZWN0PjtcbmV4cG9ydCBjb25zdCBGbGlwTWl4aW46IEZsaXBNaXhpbiA9IGNyZWF0ZU1peGluPFBoYXNlci5HYW1lT2JqZWN0cy5Db21wb25lbnRzLkZsaXA+KEZsaXApO1xuXG50eXBlIFNjcm9sbEZhY3Rvck1peGluID0gTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuU2Nyb2xsRmFjdG9yLCBQaGFzZXIuR2FtZU9iamVjdHMuR2FtZU9iamVjdD47XG5leHBvcnQgY29uc3QgU2Nyb2xsRmFjdG9yTWl4aW46IFNjcm9sbEZhY3Rvck1peGluID0gY3JlYXRlTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuU2Nyb2xsRmFjdG9yPihTY3JvbGxGYWN0b3IpO1xuXG50eXBlIFRyYW5zZm9ybU1peGluID0gTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuVHJhbnNmb3JtLCBQaGFzZXIuR2FtZU9iamVjdHMuR2FtZU9iamVjdD47XG5leHBvcnQgY29uc3QgVHJhbnNmb3JtTWl4aW46IFRyYW5zZm9ybU1peGluID0gY3JlYXRlTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuVHJhbnNmb3JtPihUcmFuc2Zvcm0pO1xuXG50eXBlIFZpc2libGVNaXhpbiA9IE1peGluPFBoYXNlci5HYW1lT2JqZWN0cy5Db21wb25lbnRzLlZpc2libGUsIFBoYXNlci5HYW1lT2JqZWN0cy5HYW1lT2JqZWN0PjtcbmV4cG9ydCBjb25zdCBWaXNpYmxlTWl4aW46IFZpc2libGVNaXhpbiA9IGNyZWF0ZU1peGluPFBoYXNlci5HYW1lT2JqZWN0cy5Db21wb25lbnRzLlZpc2libGU+KFZpc2libGUpO1xuXG50eXBlIE9yaWdpbk1peGluID0gTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuT3JpZ2luLCBQaGFzZXIuR2FtZU9iamVjdHMuR2FtZU9iamVjdD47XG5leHBvcnQgY29uc3QgT3JpZ2luTWl4aW46IE9yaWdpbk1peGluID0gY3JlYXRlTWl4aW48UGhhc2VyLkdhbWVPYmplY3RzLkNvbXBvbmVudHMuT3JpZ2luPihPcmlnaW4pO1xuXG50eXBlIEFscGhhTWl4aW4gPSBNaXhpbjxQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cy5BbHBoYSwgUGhhc2VyLkdhbWVPYmplY3RzLkdhbWVPYmplY3Q+O1xuZXhwb3J0IGNvbnN0IEFscGhhTWl4aW46IEFscGhhTWl4aW4gPSBjcmVhdGVNaXhpbjxQaGFzZXIuR2FtZU9iamVjdHMuQ29tcG9uZW50cy5BbHBoYT4oQWxwaGEpOyJdfQ== \ No newline at end of file diff --git a/spine-ts/spine-phaser-v3/dist/require-shim.d.ts b/spine-ts/spine-phaser-v3/dist/require-shim.d.ts new file mode 100644 index 000000000..f0e80f395 --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/require-shim.d.ts @@ -0,0 +1,32 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +declare global { + var require: any; +} +export {}; diff --git a/spine-ts/spine-phaser-v3/dist/require-shim.js b/spine-ts/spine-phaser-v3/dist/require-shim.js new file mode 100644 index 000000000..1b9d3dfda --- /dev/null +++ b/spine-ts/spine-phaser-v3/dist/require-shim.js @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated July 28, 2023. Replaces all prior versions. + * + * Copyright (c) 2013-2023, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software or + * otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * 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. + *****************************************************************************/ +if (typeof window !== 'undefined' && window.Phaser) { + let prevRequire = window.require; + window.require = (x) => { + if (prevRequire) + return prevRequire(x); + else if (x === "Phaser") + return window.Phaser; + }; +} +export {}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWlyZS1zaGltLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JlcXVpcmUtc2hpbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFLL0UsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3BELElBQUksV0FBVyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7SUFDakMsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQVMsRUFBRSxFQUFFO1FBQzlCLElBQUksV0FBVztZQUFFLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ2xDLElBQUksQ0FBQyxLQUFLLFFBQVE7WUFBRSxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDL0MsQ0FBQyxDQUFBO0FBQ0YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIFNwaW5lIFJ1bnRpbWVzIExpY2Vuc2UgQWdyZWVtZW50XG4gKiBMYXN0IHVwZGF0ZWQgSnVseSAyOCwgMjAyMy4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDIzLCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yXG4gKiBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRIRSBTUElORSBSVU5USU1FUyBBUkUgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTllcbiAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsXG4gKiBCVVNJTkVTUyBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkRcbiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhFXG4gKiBTUElORSBSVU5USU1FUywgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuZGVjbGFyZSBnbG9iYWwge1xuXHR2YXIgcmVxdWlyZTogYW55O1xufVxuaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5QaGFzZXIpIHtcblx0bGV0IHByZXZSZXF1aXJlID0gd2luZG93LnJlcXVpcmU7XG5cdHdpbmRvdy5yZXF1aXJlID0gKHg6IHN0cmluZykgPT4ge1xuXHRcdGlmIChwcmV2UmVxdWlyZSkgcmV0dXJuIHByZXZSZXF1aXJlKHgpO1xuXHRcdGVsc2UgaWYgKHggPT09IFwiUGhhc2VyXCIpIHJldHVybiB3aW5kb3cuUGhhc2VyO1xuXHR9XG59XG5leHBvcnQgeyB9XG4iXX0= \ No newline at end of file diff --git a/spine-ts/spine-phaser/example/add-existing.html b/spine-ts/spine-phaser-v3/example/add-existing.html similarity index 96% rename from spine-ts/spine-phaser/example/add-existing.html rename to spine-ts/spine-phaser-v3/example/add-existing.html index 7e7f2abca..b1222709d 100644 --- a/spine-ts/spine-phaser/example/add-existing.html +++ b/spine-ts/spine-phaser-v3/example/add-existing.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/arcade-physics-example.html b/spine-ts/spine-phaser-v3/example/arcade-physics-example.html similarity index 96% rename from spine-ts/spine-phaser/example/arcade-physics-example.html rename to spine-ts/spine-phaser-v3/example/arcade-physics-example.html index 7f737c735..6c0f0f141 100644 --- a/spine-ts/spine-phaser/example/arcade-physics-example.html +++ b/spine-ts/spine-phaser-v3/example/arcade-physics-example.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/assets/celestial-circus-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/celestial-circus-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/celestial-circus-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/celestial-circus-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/celestial-circus-pma.png b/spine-ts/spine-phaser-v3/example/assets/celestial-circus-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/celestial-circus-pma.png rename to spine-ts/spine-phaser-v3/example/assets/celestial-circus-pma.png diff --git a/spine-ts/spine-phaser/example/assets/celestial-circus-pro.json b/spine-ts/spine-phaser-v3/example/assets/celestial-circus-pro.json similarity index 100% rename from spine-ts/spine-phaser/example/assets/celestial-circus-pro.json rename to spine-ts/spine-phaser-v3/example/assets/celestial-circus-pro.json diff --git a/spine-ts/spine-phaser/example/assets/celestial-circus-pro.skel b/spine-ts/spine-phaser-v3/example/assets/celestial-circus-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/celestial-circus-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/celestial-circus-pro.skel diff --git a/spine-ts/spine-phaser/example/assets/celestial-circus.atlas b/spine-ts/spine-phaser-v3/example/assets/celestial-circus.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/celestial-circus.atlas rename to spine-ts/spine-phaser-v3/example/assets/celestial-circus.atlas diff --git a/spine-ts/spine-phaser/example/assets/celestial-circus.png b/spine-ts/spine-phaser-v3/example/assets/celestial-circus.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/celestial-circus.png rename to spine-ts/spine-phaser-v3/example/assets/celestial-circus.png diff --git a/spine-ts/spine-phaser/example/assets/cloud-pot.atlas b/spine-ts/spine-phaser-v3/example/assets/cloud-pot.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/cloud-pot.atlas rename to spine-ts/spine-phaser-v3/example/assets/cloud-pot.atlas diff --git a/spine-ts/spine-phaser/example/assets/cloud-pot.json b/spine-ts/spine-phaser-v3/example/assets/cloud-pot.json similarity index 100% rename from spine-ts/spine-phaser/example/assets/cloud-pot.json rename to spine-ts/spine-phaser-v3/example/assets/cloud-pot.json diff --git a/spine-ts/spine-phaser/example/assets/cloud-pot.png b/spine-ts/spine-phaser-v3/example/assets/cloud-pot.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/cloud-pot.png rename to spine-ts/spine-phaser-v3/example/assets/cloud-pot.png diff --git a/spine-ts/spine-phaser/example/assets/cloud-pot.skel b/spine-ts/spine-phaser-v3/example/assets/cloud-pot.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/cloud-pot.skel rename to spine-ts/spine-phaser-v3/example/assets/cloud-pot.skel diff --git a/spine-ts/spine-phaser/example/assets/coin-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/coin-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/coin-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/coin-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/coin-pma.png b/spine-ts/spine-phaser-v3/example/assets/coin-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/coin-pma.png rename to spine-ts/spine-phaser-v3/example/assets/coin-pma.png diff --git a/spine-ts/spine-phaser/example/assets/coin-pro.skel b/spine-ts/spine-phaser-v3/example/assets/coin-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/coin-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/coin-pro.skel diff --git a/spine-ts/spine-phaser/example/assets/mix-and-match-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/mix-and-match-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/mix-and-match-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/mix-and-match-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/mix-and-match-pma.png b/spine-ts/spine-phaser-v3/example/assets/mix-and-match-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/mix-and-match-pma.png rename to spine-ts/spine-phaser-v3/example/assets/mix-and-match-pma.png diff --git a/spine-ts/spine-phaser/example/assets/mix-and-match-pro.skel b/spine-ts/spine-phaser-v3/example/assets/mix-and-match-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/mix-and-match-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/mix-and-match-pro.skel diff --git a/spine-ts/spine-phaser/example/assets/raptor-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/raptor-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/raptor-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/raptor-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/raptor-pma.png b/spine-ts/spine-phaser-v3/example/assets/raptor-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/raptor-pma.png rename to spine-ts/spine-phaser-v3/example/assets/raptor-pma.png diff --git a/spine-ts/spine-phaser/example/assets/raptor-pro.json b/spine-ts/spine-phaser-v3/example/assets/raptor-pro.json similarity index 100% rename from spine-ts/spine-phaser/example/assets/raptor-pro.json rename to spine-ts/spine-phaser-v3/example/assets/raptor-pro.json diff --git a/spine-ts/spine-phaser/example/assets/sack-pro.json b/spine-ts/spine-phaser-v3/example/assets/sack-pro.json similarity index 100% rename from spine-ts/spine-phaser/example/assets/sack-pro.json rename to spine-ts/spine-phaser-v3/example/assets/sack-pro.json diff --git a/spine-ts/spine-phaser/example/assets/sack-pro.skel b/spine-ts/spine-phaser-v3/example/assets/sack-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/sack-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/sack-pro.skel diff --git a/spine-ts/spine-phaser/example/assets/sack.atlas b/spine-ts/spine-phaser-v3/example/assets/sack.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/sack.atlas rename to spine-ts/spine-phaser-v3/example/assets/sack.atlas diff --git a/spine-ts/spine-phaser/example/assets/sack.png b/spine-ts/spine-phaser-v3/example/assets/sack.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/sack.png rename to spine-ts/spine-phaser-v3/example/assets/sack.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pma.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pma.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pma.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pma_2.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_2.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pma_2.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_2.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pma_3.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_3.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pma_3.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_3.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pma_4.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_4.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pma_4.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_4.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pma_5.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_5.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pma_5.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pma_5.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pro.json b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pro.json similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pro.json rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pro.json diff --git a/spine-ts/spine-phaser/example/assets/snowglobe-pro.skel b/spine-ts/spine-phaser-v3/example/assets/snowglobe-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/snowglobe-pro.skel diff --git a/spine-ts/spine-phaser/example/assets/snowglobe.atlas b/spine-ts/spine-phaser-v3/example/assets/snowglobe.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe.atlas rename to spine-ts/spine-phaser-v3/example/assets/snowglobe.atlas diff --git a/spine-ts/spine-phaser/example/assets/snowglobe.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe_2.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe_2.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe_2.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe_2.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe_3.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe_3.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe_3.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe_3.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe_4.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe_4.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe_4.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe_4.png diff --git a/spine-ts/spine-phaser/example/assets/snowglobe_5.png b/spine-ts/spine-phaser-v3/example/assets/snowglobe_5.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/snowglobe_5.png rename to spine-ts/spine-phaser-v3/example/assets/snowglobe_5.png diff --git a/spine-ts/spine-phaser/example/assets/spineboy-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/spineboy-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/spineboy-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/spineboy-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/spineboy-pma.png b/spine-ts/spine-phaser-v3/example/assets/spineboy-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/spineboy-pma.png rename to spine-ts/spine-phaser-v3/example/assets/spineboy-pma.png diff --git a/spine-ts/spine-phaser/example/assets/spineboy-pro.skel b/spine-ts/spine-phaser-v3/example/assets/spineboy-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/spineboy-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/spineboy-pro.skel diff --git a/spine-ts/spine-phaser/example/assets/stretchyman-pma.atlas b/spine-ts/spine-phaser-v3/example/assets/stretchyman-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/assets/stretchyman-pma.atlas rename to spine-ts/spine-phaser-v3/example/assets/stretchyman-pma.atlas diff --git a/spine-ts/spine-phaser/example/assets/stretchyman-pma.png b/spine-ts/spine-phaser-v3/example/assets/stretchyman-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/assets/stretchyman-pma.png rename to spine-ts/spine-phaser-v3/example/assets/stretchyman-pma.png diff --git a/spine-ts/spine-phaser/example/assets/stretchyman-pro.skel b/spine-ts/spine-phaser-v3/example/assets/stretchyman-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/assets/stretchyman-pro.skel rename to spine-ts/spine-phaser-v3/example/assets/stretchyman-pro.skel diff --git a/spine-ts/spine-phaser/example/basic-example.html b/spine-ts/spine-phaser-v3/example/basic-example.html similarity index 96% rename from spine-ts/spine-phaser/example/basic-example.html rename to spine-ts/spine-phaser-v3/example/basic-example.html index 2528858af..347584cd1 100644 --- a/spine-ts/spine-phaser/example/basic-example.html +++ b/spine-ts/spine-phaser-v3/example/basic-example.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/basic-vanilla-js-example.html b/spine-ts/spine-phaser-v3/example/basic-vanilla-js-example.html similarity index 100% rename from spine-ts/spine-phaser/example/basic-vanilla-js-example.html rename to spine-ts/spine-phaser-v3/example/basic-vanilla-js-example.html diff --git a/spine-ts/spine-phaser/example/batching-test.html b/spine-ts/spine-phaser-v3/example/batching-test.html similarity index 97% rename from spine-ts/spine-phaser/example/batching-test.html rename to spine-ts/spine-phaser-v3/example/batching-test.html index 439fa2942..dc8e5c9aa 100644 --- a/spine-ts/spine-phaser/example/batching-test.html +++ b/spine-ts/spine-phaser-v3/example/batching-test.html @@ -28,7 +28,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/blend-test.html b/spine-ts/spine-phaser-v3/example/blend-test.html similarity index 97% rename from spine-ts/spine-phaser/example/blend-test.html rename to spine-ts/spine-phaser-v3/example/blend-test.html index 6e511bc22..eeaf7c7a3 100644 --- a/spine-ts/spine-phaser/example/blend-test.html +++ b/spine-ts/spine-phaser-v3/example/blend-test.html @@ -28,7 +28,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/bounds-test.html b/spine-ts/spine-phaser-v3/example/bounds-test.html similarity index 97% rename from spine-ts/spine-phaser/example/bounds-test.html rename to spine-ts/spine-phaser-v3/example/bounds-test.html index c5c553274..f89c8b472 100644 --- a/spine-ts/spine-phaser/example/bounds-test.html +++ b/spine-ts/spine-phaser-v3/example/bounds-test.html @@ -27,7 +27,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/camera-pipeline-test.html b/spine-ts/spine-phaser-v3/example/camera-pipeline-test.html similarity index 98% rename from spine-ts/spine-phaser/example/camera-pipeline-test.html rename to spine-ts/spine-phaser-v3/example/camera-pipeline-test.html index e0d3e7b3a..158ad4b73 100644 --- a/spine-ts/spine-phaser/example/camera-pipeline-test.html +++ b/spine-ts/spine-phaser-v3/example/camera-pipeline-test.html @@ -26,7 +26,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/canvas-test.html b/spine-ts/spine-phaser-v3/example/canvas-test.html similarity index 96% rename from spine-ts/spine-phaser/example/canvas-test.html rename to spine-ts/spine-phaser-v3/example/canvas-test.html index 4a93b5850..759881157 100644 --- a/spine-ts/spine-phaser/example/canvas-test.html +++ b/spine-ts/spine-phaser-v3/example/canvas-test.html @@ -26,7 +26,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/control-bones-example.html b/spine-ts/spine-phaser-v3/example/control-bones-example.html similarity index 97% rename from spine-ts/spine-phaser/example/control-bones-example.html rename to spine-ts/spine-phaser-v3/example/control-bones-example.html index 97e9005de..8c30084b2 100644 --- a/spine-ts/spine-phaser/example/control-bones-example.html +++ b/spine-ts/spine-phaser-v3/example/control-bones-example.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/custom-spine-object-type.html b/spine-ts/spine-phaser-v3/example/custom-spine-object-type.html similarity index 96% rename from spine-ts/spine-phaser/example/custom-spine-object-type.html rename to spine-ts/spine-phaser-v3/example/custom-spine-object-type.html index 7e269a527..533418014 100644 --- a/spine-ts/spine-phaser/example/custom-spine-object-type.html +++ b/spine-ts/spine-phaser-v3/example/custom-spine-object-type.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/depth-test.html b/spine-ts/spine-phaser-v3/example/depth-test.html similarity index 96% rename from spine-ts/spine-phaser/example/depth-test.html rename to spine-ts/spine-phaser-v3/example/depth-test.html index 4b3956fc2..c716d9986 100644 --- a/spine-ts/spine-phaser/example/depth-test.html +++ b/spine-ts/spine-phaser-v3/example/depth-test.html @@ -26,7 +26,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/events-example.html b/spine-ts/spine-phaser-v3/example/events-example.html similarity index 97% rename from spine-ts/spine-phaser/example/events-example.html rename to spine-ts/spine-phaser-v3/example/events-example.html index 2298e2490..b629c7dd9 100644 --- a/spine-ts/spine-phaser/example/events-example.html +++ b/spine-ts/spine-phaser-v3/example/events-example.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/extended-class-test.html b/spine-ts/spine-phaser-v3/example/extended-class-test.html similarity index 98% rename from spine-ts/spine-phaser/example/extended-class-test.html rename to spine-ts/spine-phaser-v3/example/extended-class-test.html index d03ddf408..2b9b0d23e 100644 --- a/spine-ts/spine-phaser/example/extended-class-test.html +++ b/spine-ts/spine-phaser-v3/example/extended-class-test.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/inline-loading.html b/spine-ts/spine-phaser-v3/example/inline-loading.html similarity index 98% rename from spine-ts/spine-phaser/example/inline-loading.html rename to spine-ts/spine-phaser-v3/example/inline-loading.html index 88f7c9958..1e3c7fa17 100644 --- a/spine-ts/spine-phaser/example/inline-loading.html +++ b/spine-ts/spine-phaser-v3/example/inline-loading.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/mix-and-match-example.html b/spine-ts/spine-phaser-v3/example/mix-and-match-example.html similarity index 97% rename from spine-ts/spine-phaser/example/mix-and-match-example.html rename to spine-ts/spine-phaser-v3/example/mix-and-match-example.html index 3afe2e9e5..0f36a6e10 100644 --- a/spine-ts/spine-phaser/example/mix-and-match-example.html +++ b/spine-ts/spine-phaser-v3/example/mix-and-match-example.html @@ -26,7 +26,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/multi-scene-test.html b/spine-ts/spine-phaser-v3/example/multi-scene-test.html similarity index 97% rename from spine-ts/spine-phaser/example/multi-scene-test.html rename to spine-ts/spine-phaser-v3/example/multi-scene-test.html index 8a074e927..0ff589fb6 100644 --- a/spine-ts/spine-phaser/example/multi-scene-test.html +++ b/spine-ts/spine-phaser-v3/example/multi-scene-test.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/phaser.png b/spine-ts/spine-phaser-v3/example/phaser.png similarity index 100% rename from spine-ts/spine-phaser/example/phaser.png rename to spine-ts/spine-phaser-v3/example/phaser.png diff --git a/spine-ts/spine-phaser/example/physics.html b/spine-ts/spine-phaser-v3/example/physics.html similarity index 95% rename from spine-ts/spine-phaser/example/physics.html rename to spine-ts/spine-phaser-v3/example/physics.html index f8cb8defe..0eb540816 100644 --- a/spine-ts/spine-phaser/example/physics.html +++ b/spine-ts/spine-phaser-v3/example/physics.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/physics2.html b/spine-ts/spine-phaser-v3/example/physics2.html similarity index 97% rename from spine-ts/spine-phaser/example/physics2.html rename to spine-ts/spine-phaser-v3/example/physics2.html index 55b4aac56..92978ecae 100644 --- a/spine-ts/spine-phaser/example/physics2.html +++ b/spine-ts/spine-phaser-v3/example/physics2.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/physics3.html b/spine-ts/spine-phaser-v3/example/physics3.html similarity index 95% rename from spine-ts/spine-phaser/example/physics3.html rename to spine-ts/spine-phaser-v3/example/physics3.html index 7037af24c..acd141e33 100644 --- a/spine-ts/spine-phaser/example/physics3.html +++ b/spine-ts/spine-phaser-v3/example/physics3.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/physics4.html b/spine-ts/spine-phaser-v3/example/physics4.html similarity index 95% rename from spine-ts/spine-phaser/example/physics4.html rename to spine-ts/spine-phaser-v3/example/physics4.html index 18480f3aa..9b30dd018 100644 --- a/spine-ts/spine-phaser/example/physics4.html +++ b/spine-ts/spine-phaser-v3/example/physics4.html @@ -5,7 +5,7 @@ - + Spine Phaser Example diff --git a/spine-ts/spine-phaser/example/render-to-texture-test.html b/spine-ts/spine-phaser-v3/example/render-to-texture-test.html similarity index 94% rename from spine-ts/spine-phaser/example/render-to-texture-test.html rename to spine-ts/spine-phaser-v3/example/render-to-texture-test.html index d19f11a8f..be2099f22 100644 --- a/spine-ts/spine-phaser/example/render-to-texture-test.html +++ b/spine-ts/spine-phaser-v3/example/render-to-texture-test.html @@ -26,7 +26,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], @@ -43,6 +43,7 @@ function create() { const renderTexture = this.add.renderTexture(400, 300, 800, 600); + console.log(renderTexture.renderMode); const spineboy = this.add.spine( 400, 300, diff --git a/spine-ts/spine-phaser/example/typescript/README.md b/spine-ts/spine-phaser-v3/example/typescript/README.md similarity index 100% rename from spine-ts/spine-phaser/example/typescript/README.md rename to spine-ts/spine-phaser-v3/example/typescript/README.md diff --git a/spine-ts/spine-phaser/example/typescript/assets/spineboy-pma.atlas b/spine-ts/spine-phaser-v3/example/typescript/assets/spineboy-pma.atlas similarity index 100% rename from spine-ts/spine-phaser/example/typescript/assets/spineboy-pma.atlas rename to spine-ts/spine-phaser-v3/example/typescript/assets/spineboy-pma.atlas diff --git a/spine-ts/spine-phaser/example/typescript/assets/spineboy-pma.png b/spine-ts/spine-phaser-v3/example/typescript/assets/spineboy-pma.png similarity index 100% rename from spine-ts/spine-phaser/example/typescript/assets/spineboy-pma.png rename to spine-ts/spine-phaser-v3/example/typescript/assets/spineboy-pma.png diff --git a/spine-ts/spine-phaser/example/typescript/assets/spineboy-pro.skel b/spine-ts/spine-phaser-v3/example/typescript/assets/spineboy-pro.skel similarity index 100% rename from spine-ts/spine-phaser/example/typescript/assets/spineboy-pro.skel rename to spine-ts/spine-phaser-v3/example/typescript/assets/spineboy-pro.skel diff --git a/spine-ts/spine-phaser/example/typescript/index.html b/spine-ts/spine-phaser-v3/example/typescript/index.html similarity index 100% rename from spine-ts/spine-phaser/example/typescript/index.html rename to spine-ts/spine-phaser-v3/example/typescript/index.html diff --git a/spine-ts/spine-phaser/example/typescript/index.ts b/spine-ts/spine-phaser-v3/example/typescript/index.ts similarity index 100% rename from spine-ts/spine-phaser/example/typescript/index.ts rename to spine-ts/spine-phaser-v3/example/typescript/index.ts diff --git a/spine-ts/spine-phaser/example/typescript/package-lock.json b/spine-ts/spine-phaser-v3/example/typescript/package-lock.json similarity index 100% rename from spine-ts/spine-phaser/example/typescript/package-lock.json rename to spine-ts/spine-phaser-v3/example/typescript/package-lock.json diff --git a/spine-ts/spine-phaser/example/typescript/package.json b/spine-ts/spine-phaser-v3/example/typescript/package.json similarity index 100% rename from spine-ts/spine-phaser/example/typescript/package.json rename to spine-ts/spine-phaser-v3/example/typescript/package.json diff --git a/spine-ts/spine-phaser/example/visibility-test-container.html b/spine-ts/spine-phaser-v3/example/visibility-test-container.html similarity index 95% rename from spine-ts/spine-phaser/example/visibility-test-container.html rename to spine-ts/spine-phaser-v3/example/visibility-test-container.html index 4ed5d8a9d..7fd320b1a 100644 --- a/spine-ts/spine-phaser/example/visibility-test-container.html +++ b/spine-ts/spine-phaser-v3/example/visibility-test-container.html @@ -5,7 +5,7 @@ - + Spine Phaser Example @@ -27,7 +27,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/example/visibility-test.html b/spine-ts/spine-phaser-v3/example/visibility-test.html similarity index 93% rename from spine-ts/spine-phaser/example/visibility-test.html rename to spine-ts/spine-phaser-v3/example/visibility-test.html index f70377bb5..09efb6f1d 100644 --- a/spine-ts/spine-phaser/example/visibility-test.html +++ b/spine-ts/spine-phaser-v3/example/visibility-test.html @@ -5,7 +5,7 @@ - + Spine Phaser Example @@ -27,7 +27,7 @@ { type: "scenePlugin", key: "spine.SpinePlugin", - url: "../dist/iife/spine-phaser.js", + url: "../dist/iife/spine-phaser-v3.js", sceneKey: "spine", }, ], diff --git a/spine-ts/spine-phaser/package.json b/spine-ts/spine-phaser-v3/package.json similarity index 74% rename from spine-ts/spine-phaser/package.json rename to spine-ts/spine-phaser-v3/package.json index ebf943c3d..45b7f2f0f 100644 --- a/spine-ts/spine-phaser/package.json +++ b/spine-ts/spine-phaser-v3/package.json @@ -1,7 +1,7 @@ { - "name": "@esotericsoftware/spine-phaser", + "name": "@esotericsoftware/spine-phaser-v3", "version": "4.2.76", - "description": "The official Spine Runtimes for the Phaser.", + "description": "The official Spine Runtimes for the Phaser v3.", "main": "dist/index.js", "types": "dist/index.d.ts", "type": "module", @@ -31,11 +31,14 @@ }, "homepage": "https://github.com/esotericsoftware/spine-runtimes#readme", "dependencies": { + "@esotericsoftware/spine-canvas": "4.2.76", "@esotericsoftware/spine-core": "4.2.76", - "@esotericsoftware/spine-webgl": "4.2.76", - "@esotericsoftware/spine-canvas": "4.2.76" + "@esotericsoftware/spine-webgl": "4.2.76" + }, + "devDependencies": { + "phaser": "^3.60.0" }, "peerDependencies": { "phaser": "^3.60.0" } -} \ No newline at end of file +} diff --git a/spine-ts/spine-phaser/src/SpineGameObject.ts b/spine-ts/spine-phaser-v3/src/SpineGameObject.ts similarity index 100% rename from spine-ts/spine-phaser/src/SpineGameObject.ts rename to spine-ts/spine-phaser-v3/src/SpineGameObject.ts diff --git a/spine-ts/spine-phaser/src/SpinePlugin.ts b/spine-ts/spine-phaser-v3/src/SpinePlugin.ts similarity index 100% rename from spine-ts/spine-phaser/src/SpinePlugin.ts rename to spine-ts/spine-phaser-v3/src/SpinePlugin.ts diff --git a/spine-ts/spine-phaser/src/index.ts b/spine-ts/spine-phaser-v3/src/index.ts similarity index 100% rename from spine-ts/spine-phaser/src/index.ts rename to spine-ts/spine-phaser-v3/src/index.ts diff --git a/spine-ts/spine-phaser/src/keys.ts b/spine-ts/spine-phaser-v3/src/keys.ts similarity index 100% rename from spine-ts/spine-phaser/src/keys.ts rename to spine-ts/spine-phaser-v3/src/keys.ts diff --git a/spine-ts/spine-phaser/src/mixins.ts b/spine-ts/spine-phaser-v3/src/mixins.ts similarity index 100% rename from spine-ts/spine-phaser/src/mixins.ts rename to spine-ts/spine-phaser-v3/src/mixins.ts diff --git a/spine-ts/spine-phaser/src/require-shim.ts b/spine-ts/spine-phaser-v3/src/require-shim.ts similarity index 100% rename from spine-ts/spine-phaser/src/require-shim.ts rename to spine-ts/spine-phaser-v3/src/require-shim.ts diff --git a/spine-ts/spine-phaser/tsconfig.json b/spine-ts/spine-phaser-v3/tsconfig.json similarity index 100% rename from spine-ts/spine-phaser/tsconfig.json rename to spine-ts/spine-phaser-v3/tsconfig.json diff --git a/spine-ts/spine-phaser-v4/LICENSE b/spine-ts/spine-phaser-v4/LICENSE new file mode 100644 index 000000000..4501a611f --- /dev/null +++ b/spine-ts/spine-phaser-v4/LICENSE @@ -0,0 +1,26 @@ +Spine Runtimes License Agreement +Last updated May 1, 2019. Replaces all prior versions. + +Copyright (c) 2013-2019, Esoteric Software LLC + +Integration of the Spine Runtimes into software or otherwise creating +derivative works of the Spine Runtimes is permitted under the terms and +conditions of Section 2 of the Spine Editor License Agreement: +http://esotericsoftware.com/spine-editor-license + +Otherwise, it is permitted to integrate the Spine Runtimes into software +or otherwise create derivative works of the Spine Runtimes (collectively, +"Products"), provided that each user of the Products must obtain their own +Spine Editor license and redistribution of the Products in any form must +include this license and copyright notice. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS +INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND 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 THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/spine-ts/spine-phaser-v4/README.md b/spine-ts/spine-phaser-v4/README.md new file mode 100644 index 000000000..15b1d0813 --- /dev/null +++ b/spine-ts/spine-phaser-v4/README.md @@ -0,0 +1,3 @@ +# spine-ts Phaser v3 + +Please see the top-level [README.md](../README.md) for more information. \ No newline at end of file diff --git a/spine-ts/spine-phaser-v4/example/add-existing.html b/spine-ts/spine-phaser-v4/example/add-existing.html new file mode 100644 index 000000000..f42ee87f6 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/add-existing.html @@ -0,0 +1,60 @@ + + + + + + + + + + Spine Phaser Example + + + +

    Add existing object

    + + + diff --git a/spine-ts/spine-phaser-v4/example/arcade-physics-example.html b/spine-ts/spine-phaser-v4/example/arcade-physics-example.html new file mode 100644 index 000000000..e8bf54224 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/arcade-physics-example.html @@ -0,0 +1,64 @@ + + + + + + + + + + Spine Phaser Example + + + +

    Arcade Physics example

    + + + diff --git a/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.atlas b/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.atlas new file mode 100644 index 000000000..614022925 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.atlas @@ -0,0 +1,174 @@ +celestial-circus-pma.png + size: 1024, 1024 + filter: Linear, Linear + pma: true + scale: 0.4 +arm-back-down + bounds: 324, 401, 38, 82 + rotate: 90 +arm-back-up + bounds: 290, 44, 83, 116 + rotate: 90 +arm-front-down + bounds: 706, 2, 36, 78 + rotate: 90 +arm-front-up + bounds: 860, 138, 77, 116 +bench + bounds: 725, 256, 189, 48 +body-bottom + bounds: 879, 868, 154, 124 + rotate: 90 +body-top + bounds: 725, 128, 126, 133 + rotate: 90 +chest + bounds: 408, 26, 104, 93 +cloud-back + bounds: 752, 378, 202, 165 +cloud-front + bounds: 2, 2, 325, 196 + rotate: 90 +collar + bounds: 786, 13, 47, 26 +ear + bounds: 1002, 643, 20, 28 +eye-back-shadow + bounds: 428, 395, 14, 10 +eye-front-shadow + bounds: 704, 529, 24, 14 +eye-reflex-back + bounds: 860, 128, 8, 7 + rotate: 90 +eye-reflex-front + bounds: 726, 386, 10, 7 +eye-white-back + bounds: 835, 23, 13, 16 +eye-white-front + bounds: 1005, 1000, 22, 17 + rotate: 90 +eyelashes-down-back + bounds: 232, 329, 11, 6 + rotate: 90 +eyelashes-down-front + bounds: 913, 851, 15, 6 + rotate: 90 +eyelashes-top-back + bounds: 408, 395, 18, 10 +eyelashes-top-front + bounds: 702, 179, 30, 16 + rotate: 90 +face + bounds: 514, 26, 93, 102 + rotate: 90 +feathers-back + bounds: 954, 625, 46, 46 +feathers-front + bounds: 706, 40, 72, 86 +fringe-middle-back + bounds: 200, 6, 33, 52 + rotate: 90 +fringe-middle-front + bounds: 878, 76, 60, 50 + rotate: 90 +fringe-side-back + bounds: 780, 41, 27, 94 + rotate: 90 +fringe-side-front + bounds: 939, 161, 26, 93 +glove-bottom-back + bounds: 954, 572, 51, 41 + rotate: 90 +glove-bottom-front + bounds: 916, 256, 47, 48 +hair-back-1 + bounds: 444, 395, 132, 306 + rotate: 90 +hair-back-2 + bounds: 438, 211, 80, 285 + rotate: 90 +hair-back-3 + bounds: 719, 306, 70, 268 + rotate: 90 +hair-back-4 + bounds: 438, 121, 88, 262 + rotate: 90 +hair-back-5 + bounds: 438, 293, 88, 279 + rotate: 90 +hair-back-6 + bounds: 200, 41, 88, 286 +hair-hat-shadow + bounds: 232, 398, 90, 41 +hand-back + bounds: 954, 673, 60, 47 + rotate: 90 +hand-front + bounds: 967, 172, 53, 60 +hat-back + bounds: 954, 802, 64, 45 + rotate: 90 +hat-front + bounds: 780, 70, 96, 56 +head-back + bounds: 618, 17, 102, 86 + rotate: 90 +jabot + bounds: 967, 234, 70, 55 + rotate: 90 +leg-back + bounds: 232, 441, 210, 333 +leg-front + bounds: 444, 529, 258, 320 +logo-brooch + bounds: 954, 545, 16, 25 +mouth + bounds: 408, 121, 22, 6 +neck + bounds: 232, 342, 39, 56 + rotate: 90 +nose + bounds: 742, 529, 6, 7 + rotate: 90 +nose-highlight + bounds: 719, 300, 4, 4 +nose-shadow + bounds: 869, 128, 7, 8 +pupil-back + bounds: 730, 529, 10, 14 +pupil-front + bounds: 254, 21, 12, 18 +rope-back + bounds: 232, 383, 10, 492 + rotate: 90 +rope-front + bounds: 232, 383, 10, 492 + rotate: 90 +rope-front-bottom + bounds: 954, 735, 42, 65 +skirt + bounds: 2, 776, 440, 246 +sock-bow + bounds: 408, 407, 33, 32 +spine-logo-body + bounds: 879, 853, 13, 32 + rotate: 90 +star-big + bounds: 939, 141, 18, 24 + rotate: 90 +star-medium + bounds: 742, 537, 6, 8 + rotate: 90 +star-small + bounds: 719, 378, 3, 4 + rotate: 90 +underskirt + bounds: 2, 329, 445, 228 + rotate: 90 +underskirt-back + bounds: 444, 851, 433, 171 +wing-back + bounds: 290, 129, 146, 252 +wing-front + bounds: 704, 545, 304, 248 + rotate: 90 diff --git a/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.png b/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pma.png new file mode 100644 index 0000000000000000000000000000000000000000..da9f980835c1d9f9f688169e5c544a02c0571153 GIT binary patch literal 818183 zcmZ_#RX|)_6D^8%L*o#f;1*mG+@-M~!5xAHcXxLU4vl;8;O_1oLU4C?mp**^-}j!U zQ!i^it+}SG8dal4MJUQkq9GF^0{{RtX(@4K008tp1OX7?-yeP?j6ncYuSscf5moo4 zlMaMt9W$5D?VYRl*=q{tlKUmZYUNtBR38cMW7^R0xAFOrfV~rP8}OnVdwZe@85al% zUf2oXKv)OF51;*`y;7J*j{Yd|cPQitww*&CJ3H<(c^!K&h{mpbZx7OVXU(R@?<;OA z-8xXZ!_diuydN$$`~E)%mv0DH=so=Q7?_G25;dU~7I}c2-V{z#td3A5na}#EY-nOB zR6^?U4NOx?J>Jp;W^|Ei90faMg8%P}yU73j;)UQ@q;HvvD}`Ddp^ex#QC)4;9KLMS zW*5ofi2gJ^(C*aCk{t*x3yG|=Cjd1I{$X()$fdwZNunK>3-_R-S1?L^Kwq@Y&679975 zDF7ZG;5Ib1E$yVM>Y0~Us*BE_7(ch|Y{Pt$;Gu_aGzqN43BU~WzYtERNTCo9vLP@? z;@sTUn$JvbU2Q}&kQH}6oUZyK|%b}KY!RC z0}f&mn9tCy$g$9f)@tEjWMzO~^!R73Z%Sc&JSmjM6kYJCx941T5;vA0v@jh~@hrI> zhMohsP(lbTdazfNy?5cZ?!2mvI&0KHKBsblt@S>03(~TVp9V^}kyluWZ~b(hY|wH>GIe5hVjL6K<}V&?&#f z^=IdsD|gcd2uRE=z>3dOHG*bg##jKXsHqS*wL+L$odCxMm;pzi^%z@hX6DN4(q>{+ zjJ#PGnU@8$YhrI_+xK$h|Ev)RIGwnhYtr+3Oj*(#3ujRNlZJbL7k1^n{K9LAVtgk1E!kP{_leAgyLpsd|CS}O-U3R znmFRFgX4}FXb5nZ2V`$c_bM1H%O@yoLU9&~;KGZDVY(ZoG-L4zyK9GCsHTU4{Y`-Q zGz+0hUYUz8OsYF<=4Hq@R+hHg)G8?V>4V0kM0WIWWOlJdzcS(s z$;4%HhQ_@OvL6%;$;*#aiZ}CQVAeTq;`M0$iO01_V5IdG8Kqv zXi72`5*-AqJcq#jSOu3bjJ9uc&!y)civ(2tn5@mU(E7n3eR6w|YXLFdRaJ%Cz|oU< zG=zA3?<(Y()a!5=UAXH$$J8k~k>~BA3-jF{gSru5PA5i^86mgUU9Wq`ol?t|0F4`7 z3e=gwLUQ;m|3sE^jQl3PboXf8xVKMN+>Q}C=X}exJ-tz^t|qK<(@9tsxQdK*F=74{ zVidwE-d8OeUC%*ef_HP?O4%2}h3p6%Aq(QFN4a$3OfAh7=xU=aIj2~Y036kdr8vWHpJkL-n6Vj>1(M2=M;H2shx4|>?$5{sp0=F$V|_o~ zW2+n6OrD=#|If9qeMMbJ!hbj_wtZ?^T+z`|I$2@oM}MKyPcZvVls^^|J$`axE&ZjB zR3ToGoQBb|P*Z*H-v?)X44jr=orr_UKzTMLRI;H1x z+M?Ts?NoJ2lIWb8dhawaAVPgxWn~KchhKD4O+fyR`M#M|)t|1QZhaCk$@&a6U zpC6KnR-sI2I5e>Mgc#poiQ+PkggnD~T`5Hx!U?+vS>Zm=F`+O?z;-b7S=-_zS>n=M zYwa$h3%%~Idt3~Bd6WQ=2~84Dzfou+2AGNJ+Mt!&c5IFc{}ji@G+xG#sTaw&00bK( zFiqpgzpU<%&Cvsn61`RLp)P)HR_=lU;9r`ROep#>Iek`)-HEXMim+1gc#1OH&Wiry zf7WPLzTl;$kC1%PNaBSidieqU`kBO#1WBUHtGb@@71r!eO>&wyUYvyMU7lTZqbF=? zvL};u!a-;W1q3}lzEr2hQeNR=ge^9-;go{@T&{1_O$8JfGP%x0y5=&)5Yw%hwZoQ~ z6P-$LtZ&$_1?T^R-gZ(e$c^n&ah3PkNT|30!C6KzJv@%w0E2A23BEkL@e+KH5ncKg zK|mf|B&Jq8o(B@j^++}eMj!c=h?F=RMyx40;ZNA1%WfkqfW{NS+Q@E}t8XqrDAm@E z9XDxz4Q&MWh=;xG>&0#JIy8$M7*|f7YkrkF>>8+f!VIos0=Xl_S%^r}vkNk#`54tL zUgkxd0NtE(|HDm~jd2k^%rotO>n*2i{B{rODk@eeLkQ%VCxPZ-WYz6E301?=8^>jD zcI}P%+`M6X(m{M9!j&)B!v3CtJ)E8t(J=2=M~-m}5Q+oIWfy)|`BOH>i12yZMM6VO zjb8090aQic)d`y0U&yyil;X41$k_F=xc=6!(P+Eqt;d!X;r3R+&ZZjp>NI{o0VD za46>gjZ2F`{Wt?Jo2yMwzYgXJSRe%|%tsJpGr-K z=r20)KnFx*R*XdeXaJ)c6@hq+pGxrao)PTvyT=qiO*3) z`T8-tZF5q=ck50#Ry<$H`sAaPjtmu4fUJai_x9Mt=gKbUj{>XTH?JOERjXyk9cXAJ zf3n}QD=u)j1tGoo!>~!ClUL@-=4F7pCx8(|pPis`{O@;j=Dzq@!>c6O^-xo0XLkj4 zsrav5ZXw6roR_Alm1|*c+m-glnhFIe&fDC*O5ARgp2u@^$QvA0u9!%!IFK%zHb-!v zrU4o70V&)KWQ$I|PC*_3G(C5i$~DE0q?4BAm;nWnN1zM8?YKFGjHW`R|L-oN1e8PX zb=)4w{)8LSr^AGrhQs)OMPmiJ!ggF}rnop_S! zq>4!+Zq3<>rX06~@=u(u>_*l64B5evcaai}?1rs)ZhXv0h{9Z+2yO1GmjP5~{g)s| zWKlHMg$Y2y~&|cejB<6fvVLM5Tl3 zvDlJ{QF~+8ZeHy&k7m~qU%Sl}z0I{vB^nTc?td!v)*%fjS!1a_WAmn$b2h{|d>kYN z9ZoVgllTjSS(H@!P9&6vef|1D;H7`E>q2;D_9E=-?8+T8qmb)1=f~H7T0~Q)TRicW zN5lX<)Yo1)0$S*UaI_aduun=Z=;{C@{bI#T_s|xm253g>HoR~d7LCyWm;H!0(UhHp zQvEN9idAXS7GL$a9mv7uk*}{7$u6#i-Erqkt29e2AMOYBc)OzivLn-%f7|vZ)5^7i zzku0)x-+PKM?q0zs+?1q=lyahSn5sNAp*y{I}d@$NdzZ?4#ipmj_Tr^2MN$j62J;@ z&Y;5#sG*bW>jDnKcmC`fu0eu2-qn%AY?um!bQMp}2?o zxqm9LLQW+^aX)fuW@8;K^uH8V5BJBhfjjveH6B_2tLi#aO3Ip#hv((D@Z0GPkn8^W zj~_Jpe8q9Q!L7;VjwUD`r}V+8{buZRf`=zJ)7S4eC>M_OCK9#CG%gqR=<7Gg7;g!V z8370<>6;c0uebL@&k*TT=lRF~o1SIXDsUIIy&bH@`eJ9WcrmAD6JwuOJvi$4JKSlj zCSESz_M~G20@1F&PNmY3qnq$*OyiW{M%i;5xL)x#ISB&VpZ|L23kUHKzGw}Vs1 zSHz!w%r+RnZg9hNDq z+Rxo7G;nY?(y(R4nIFO9-Gh|7VD3Yg!K!Ge5)?hbpEXGA5Vz0_L@9*fLS8sj%c-R} zoCCBg{PQvl7K$!63WPh?+0b%a?*F&r@)2j1LUz{`F-;$K)elHUglPUch@PpwtoE-~ z{528<4E<;>vpWhk+8F1t0dTaiJ4QcO|IVSQ$vIWO%Ubib>|`1sz5e-pUV!;e6A!R#;IlhHbuep#0}r)ki+v|Eowengb zsqQ^$Xr*KK)mycdFVlul&gp1Z4>h&`88C7$0OePYVwC@HM{0wr7V$kCrt3a z`4ud-27!I7b_`& z&n?*zPzU0te+UE@!b{SiqskfI&##+|9fcBAF8sCkqRIbLVS(E#5^8F$t@Ag2$^LGy zB86FhrBmxKIs(Xxkg8Q`;FGicY3Oxhw1TXu#^>+#yC^wr&)+rlT?Sm$VSIhMDk^+i=IEEAnTGHdd?}Uc1tEX~S=%gebqtHlbIss?8VN+(u z-k&eNZ*_iYGQrETVqyQXImzKEyB;P(fsIA+Q1u36JQ{#NJ|Y5jBV18gqTGV3K!_AL zu&acLR+MT9j7lj<8#<)72A$o{@iti(&cPRQpwjsL^O>3A|3vcJT?u&b)Sn}!RB;8@ zQ<0goC)HytTD3g7x@uzfLf0U&Wvdy3JHr=;+J<(mgTBpEIT)Z&X>IX{v>dAq>%}|o z9N|;7QIK!@c(ty2$Oo-q?LPAz%*VTivyAfd+C8LA}6 zu%t5m4-#t5gleEJ!Ymhrt+AOKr`1+_o}c9v`}SKg z!K_z=l>iAr8C4GH(a^*5vj)MH-yb2N>BmuoD>;?$(?fG@w@bK;GfSxfeh@3_j5FDV z;f@Q6`D?Q<=)k2y{f>SG+(Gf(2MST?XzF&9Te40igEeofWg9#Fa*b+;_;Dj^D59%P zi|1NYCMg9Ivj3M@lQjF<(mwrOUr2N4`-n$-M*F*X*uU)9pI(!(BVnp(9K{MQ4*l*tD zYSj*3{PGah3uWI1N4ieoNwSG&k|AKZjPUa_b@FN=2cGl*MJhN*p3HOX$+~`pd|n@| zY4%`GI`r`Wgln<-czJ*ny_tD?4+gx0BO3*4y|(t#K9Y$D&Q1Tg%v5^PKWKGNZ?pim zRc<}UGszBv7)R>22lV`f`u0F{p4rqD*^aN%%eSW)C6M~Wp*-R(fET=b1&CvJ_+?}r zM~xll#v4%LSw*iA;osp`jYHP5?Jw8>{9CT*V719V4vd2!_K_FYGQfVe>=!d!&Mx>= zWgK;t`f-$NP-&j}`_gBrdQ?El8oc$BPA&l^T{%oE1FV&-C zZDwjJF&RmYkR>L!Et!yz`vaH(aDo2z!fYk%`Y*k%QQ05>Uj{a8bz%LdprFahdg&+V zh6~>>53Q~tRD&j0ofc}O95RxiR4!;2W2Kvp9utbUr)Z1pg;---X;f`(bAmVT9hX@^?pxSA=rM9%EPeL|7J#* zQAG3gYaoy{P2MCuHbSRT1Qm8 z^NT;J9F*XjB$sHizR+(!$H)uNFfI|WYK0cjEgk>qA8CQZ!*7)cWLYAK4vU+IQB=9& zSMjtQ99Pu%eTn5vxlRQFK%TZ$cGAHr^7{U5eg)dgv@K-$EAatmRCF(d_5%Jef?D$;Tv~HXoke0R4q4F%yv1&27rfj zC}v4{c>(B4d06LuTH`dw7Sk9PbwJdb>*|31db926TppPG_i^ZtG{|HvIjeVg>O^W0 za%uQN^rC)xyut3(0WT!4`;>e2DomTx4z_wP-l*@(=~~yhgWPOc5bakz0cYz;|33(vfE5kJ+QO`HdCVUiduk=*#u*)T785H{N`TR+K^Chz5xPp$a6R>snL}M{ zJl2g|TkpO^KAb^FSAC%u2S(%G@f6hx_6dPF9L4L_Q~{&ZM>T)f9Y?%$N*oxV@;O3k zDM{O+7&I_av0ZBO$A@Jfy0cg|sPBdeh&CdTPeS0}g4Z5ybP>~gvcdc>B4=*;9u&UGhnIz4arvja<-v^*L5pB;=Ol6plSSp3HB}!l#HIx^u?f{I4 zedzN1kD3Pp$EJIWq8aVNi;0ZfZPv_8(>QR?=K@$ zU&!z_oAUVT2}gDKD0Q_d@8lxJFu5)>YgB7G*R4yFE!zziYHW%t2~YcZNM6mN z?w1q3o2oKX$doZ#X(8*P+eG1a-{Ys_%FYV2!zF{V(t9+yw~Kv42&2Id1iyqEY*WM) zEZDS;Z&;q$ureD!Bp4)8d^XU6#h32l{BBsH4?r52ByUV>2`8!u4mn#X)Ie*Z{8GH| z{o>wLX0+pCQxr+`tW=+uj~!&z_1MT47HaIHYHDB7iz*(!{rZns%UsN*i?p;Dy~(We zUF6)iUA3pKO|t*2Pnu|=HC+FhRrHePb{Tr1fPS*zvO%CWH^n1NAWk7Z{t!oG7XR`c zVYZvb2PdM!-mYuAK{CLCpA?{{eAaK|YO|F%Um=P0y7V9VfYi0m*fEp=?zZMH42cD({Dcy$TW+V)7gE7773zi-B7$0^t z*UChYM-)q)f*Ft)c2V_aM?GIg3egGqzP9eUc9cB!Phko-tZgad+=oQsiU7PklARMHIiPfLbL43YZym+!?}vQ%za6>kAT1wt82 z+2ugh<0Hay%eklKxTc?9WcL)}@4UW#wp+kb%s@C!Z~76@lyMP%%;e>Z?7t7|pLxmH zV9It5M{!>xP~;!D6e>2p$#VUZ#L^|}CHi?d7|dUiEM0;Zqk>9%`6|f#9ddJ zWVdNgH96f#4k8@h8oy%A)%sx0hZvfd*pJgToH)c4t*t=xqwbQ%;HZHHl$-`sNfa6U z^Eoo8v1qvLEGA0B#A()Pm4w+!0Tu1s_s9Lr^JKk{b7tJVv+=)GmoaL;R)=dygYK(U zzp>HOaiZTcyjW$R5<}az*9y32^@cthPI(g@4p?(Sq$G8q`Y!;}!$2Gu?2d|Dux&7j zOKe2BA{3bEAj&i$R+fhn7*KLk`05E3W(kyZS|H;Wc|0v&39iv;Elu1zGR$_(LMy*;Yir1Fg$8bo_y6{}CV z;iWmt+X`4-+=JKJ(3J|JcV;p@P2p)Z^2K|Otm7B~k&H}2EjM572SZMB@m?ft$8kDa zjjf(cNdG&nV(dTXWRRf-mc?MQ`Cx5>*L)WnnC64YQ~+bE+via}%A;tA0vG@qZeLFg zeGQ1M3YPWwve1gCTCyHJYmquiQIdpge;8u6zPQ)~u{qI1yV#*Y)?ZyEh9LUwrhvD@WDwnWa`=6st8v zgXmGitho!^B9yZ-rN8~__)N1CuJ*S_LN^g^ke1O{H6GuaSL`^X}V7@3jvzcB6_ugQw&Q~J4z+qNm=b=B~Ym4gq1d+ea8c*5@ z%1TftdwzHOWw$|igfXPg1iRyrOC6C}WfKZPD$@ZG-Y-!gBQGMcprJ7gXc=gd%Bmnh zaCmzbPO7R{}A^g9!j%^l9k2-`_Ep3nxf_^|VM2 zkjh6|dj8jQ@KA5SMvFE3ZgZ9mt-h~MxBRXr3jt7}*_a>`Et&yEaY*d7@2Io!D~A#G zM?W!c>08nvDft01Ol;psN6P-kF+l_})n_87H>Q1jsE6s)+OY7@c&y_xphG)W;%Al> z9?V7=OgsK83f}6Gun;vXXs9#l2Jx<#EmO%~vj@?iXAmtLXyDA|=I;HlAr%~HoG^kR z6<-IO$;U>()pLq*a6z?Jp{SwR$`sEj0shqjTZ8ColH-6J{8gjH!SMU6kqG|MnP>*3 zaTx>w2EPd~n8A`z_{s(|&WLDKUFy&=M;fc#^-XP^3t?H=fon1uoNFW%X63&2fscP>|ip_FoO2WI2!oACX|GZ42Fr2E*64d>@(x>>Myx|uy-ktGW6T4`kFaka3PE?O%fCgLV6!5~AkI zQ7a+8N4W1oJ_iT!DcPQn-A($d{0}*0rb%nX`t(VW2>f>KZ>`Id&}q1GwuuhJj8|qv z8q`Fpx1zEDo776>e%{dfVOZu!ume;4sZo++qT;xm2zf%Vqc7pkA7b+K1~b~Q22or2 z%A{-f0V&6t)GtPG-y|SoxC80G=pt+6vWzVF4N{9Hs{<`c7&InJ9b2^N&&Y@$7sV7h zADD?(+8=2UZni4_J}y5oG!2YLNH}8Bt>n%Re_ZafnK?6Tu-Lmyk@psxm0Q&R{GXg? zdmJD)J099F_NCqZnYW2azs50Mdqi|OzX2nHJKmDL&p2)7-5?MMUM4{BvL9Q)Jl*wc zV@S08#D{&E-85sS1jsLWu!7i~B}{9;loT*^nF=l@V<8tZZ(n1#c=1 zk6pdwA1K}$gaPDIuczS(sQ3tQumL#3|Ln!r)W+x^|H`swN{){lm8ROh{cv$Jsj}|K zK^X13$DZ>zKBuAYlK zALfz0pY_^|a`p=+vBSRB*f2AD>48V8+EwafRo51mczx+C%X(5+?zgYnumN6@y`WFU zjm_^Fz3+>jGz?M4WjeagQR{JKM`eo>@7BO{ z;4zv6T!W(H(|vV(^w`xbG3-xrz^8~@BEqC=mE2)C#d4EWeBS)2iHV(Br^mw<9oxI< zo}e&B+!h`_UN;_nx~YTKJbAORp^NP>SRGTxM(^N!3=)(mX7|V-ojFI6iJFGRc7eZt z@TrUZHUT+nUdC6OO)_t+t=e11O`jX>uo$p?+{xr6G97w%832Vl1!LMO`(5oR&-2!K zM^oefiQ8h?0nM!*hmYmwExVy(!Y$6yP)e1=(wMjCUr*;0q_IN?@bK`XyN(_Mk+_U^ z=j&a<@lsS*k1qt=>aNa?rVnAlUQf^5`klMneLeV!Tx#5qMfi=(Hy^c`a7qAyyg+C) ztel%p)x0R!kftdbJI73ucKpte8tYU`zKt{nQ&tWE{v)Wm^^cm~WFoNY7~sqZP5M}k z3C(pw)5DKk{?-#(rVSUcOQDfaY$Cxp?gVP|F>baucpV%QrsAvsX4rsqXQUn?1xuUv zth$v4{SA%$n}0cxjgd!6ZeaPR0!puDH%+dmY#0o1J_J@6Aq^N-qY?Z*BCb|WD53I@ z4<0?hkFdI|VL?UPi^&2A5d%Ke!(&kUEAhhP$-q>@m_IUsE%1}_;pYy6;<%O7)s*x# z!Y%FW?7Gf7pU;+?9k#!o*EYV}7w=6J{pRPhwsS6>hw||M?lxMDY3}ot!uoSf7fL8) zo&nEi%5*p}`hcGRSvPM%+5xc26^1|Lapxmm0uWJv_Dw}&18&D$S2R`!tGkl51H!*F z)eG+fNyJEaS#fO#c7H`7wF(%>HM`krBqE<;>|O;6;4Qj7BXPVCbJ_vgn;8t~JaSVJ z{VPPt8$mquVwtvCjX+g10~I?_1^9WaV)gtFCG32`o-Y2}m_4fpiasd8{A;268U7|% zxkOHi%;*9AGCfg^ww)ilIy=I`NCn-kw~(HF*urp$R)2qQIQX+HbQPa5I}wFP1%2pX z7+^avNmIScicW_oyuU{wuFeOfGxXg&kdMn{10+fYS!FrozI)2Jgs7ebc|1 z0y55VWk$vGe#sw%mTo}L+=7S;4tYyhrw3~J4ztK|KA-j#+YOyeiE&VI*lEYNGEbo1 zBJ}zPzP#LHe8l~Y1@7iZcvqEPApyw9sH#z!w;XDi}FE@-w4T(tjAfH z(fB8f^4SUTGWM>nFz#rT)Cz)!X64Knhd5T_-ZfmoLEffZv^m{0UGMsjRQw7CPv8{d zM;@ARY#eW`_o;EmMt|iKQn%M_B7I);cEQ&-!!L@Am}6gT{@2%%G4K7recpOo4wOc9 zY)4G{H-HgYWCdqB=9oS`d+5BxA;+FFwrfw+opuED?=o9|nCyZMJQ6*h)iZx1*W*V; zA?^#ZAnN}TX`-dfql63RUm*1zU>pC-0wiV7!-0mi9A6VKEPYo)=uaUCoumVclE%>s z$7p?loNW(vQvnPQ(=o|4Z`BA&)Swa9Ebt;xbq1P{&UZ~- zar*)Y7OH+Z4~t$fDvv&M2q`q6Yuyg`Wl0XA&JFUpMz>1;rI??BTRq0_zt;wK* z1XQ9hxxh2|Aj{tARG0EjpU?=frEy(^HIok(99H?9TIrW7yb0=foi@zh-QM2fMh$GG zbiM3;5r)28PdzgO|I?vxh;lG->iP^wfVxdP2c_ktakALY1UdXi65BJ3gtA?g@`a{b;RD{IN60gTVIl7OkC z`xT40+4;~2l;F&Gu15YmgY2a0h=L9?0jX3AqWFQ;YjF1tO5X;nE9K!UTRkOWJ67{i zFN#o;?{0s?`dg2}*&;X3Q{C)aSg)e!JL%sl^kw-tak^2F-r-fzUI@62_X&WjHB za~K%K_~wcG75y}{bVkI;+S=Orywk_at-TexA7YqyG1?jbe7SeXcUGWp78oBca~egI zJa-sQNjXuoTSKB3fl4Da0Q_nO91u0U#@NxnO!-E34(A?&lnyb$4=wc6RXqPZBk7Rh zXWmDfg3k1vo&`gLL$1d9*URxMI`npACT;%3HPuaM5k2eyUX621B;p%YfwGyEigjt3 zwpL6&?CWW%6AUpC+!#jB*YxNEM>Z_$TBbOH^s28gI@p@<`tiw*RG64Bhee;L^tmIC(@S>mTBXoBhH#$RRZE z=6bf$qJjYe(t?|rH)LN(V-)s7JDDKx zPwQ=c--mv(3au8y**&=$r$L325a(^mD?W#Bzmy>&i13*_e;P%y$AXm9da$Yh-xUIF zqG9_A1CVb#(GeR7fMXEA&UOqfE@^>HqrcQQjBkzIHxZw5zcEZ_ZVXoAn3utaq*>5S z$iXJivrHR;7taIasI%?^t%ohYfs0K8)XSYYu;iH@Y^;|X(Z=4^58^;UJsY8DL|hx! zg75ad$#&JV=nd~b?dUUdssYJ?oiMcV`14C*z?_u^p-jNfhbZHxfZZ&a3jD#2bF6An zd>(laYihPas}=i`UQW;)BW$~zBgHwlzDSi?cSp!fy@&>93ah=`kM>}K6=}e)spF*L z20_Q3iP3hwYLC(M;Y((=*ngD88}cA>E;fj~DggZBju*tVzN5Z-8Up9@lCG%xnA2`* zcE{|?l)3V6Eowe-uM?cPV-zG-%-*kZ?7NZiTuvVfly|mqb~;GgjX|O+TWxZM9_Py$RHID7ZtTsVTco^^ z1qQB1_`IL%W=$BeL*;SvuY5VW*ahdhPW<^*l zFu>=I0g@^GfA9;$(7}Kt0G)_ZSc|D$s!#4;{@pYd^}n;@Iya97biHH*0-oYnj~Cyn zPM{-`ue4-bsNWuw$%rjL_n82!MLXJ$LB3 zosYs~5BHLt&_2n|(z4Ls$E^_N;ZJY0w|C?hviSRK3Bv;g6nU(8@q|PPmp4}u(fh6q zTun4ao1m#H9ZLLh^3^?FZSh@0Qq9mX19HS#9hmIxh!a8$BNsUeuwg* zdZr_wR(W$jM|R5^Y@`l6WE+t{w<5_}0y5%H+M?Wu3YN)>tCQ`Apk-v`iG0H=e*y*3 zm6g#ATDw+SE=i4~FnDNjq7#M6;(+JzZ=n-aWVadLnO_5oa+PWF$|s#CtLqLV%+UUS(I zH@hz{G1AZs8ko9b$rMrsi?J$CI~PIbnqv&%>$Iag?+3YP(c#F?-(yeLa6>Z2ONPh^_I=y-&!fYTH5a z>BuU#Q3+AZ$EHjZQue5n@WFvqu7BrwKRFmna7h0AK25Y^kc}<8I{~OZUVYU+KR9Rp zt9RVVE;^N2^->Vh32eR}A;N{#+w6Q3i7S@8NCI3Z!nL<8UK6FvT7t_SoA-U;|Bi+y zUTnwvS_dnx`x*uWdl$J^or6O=YJyeOhM+IO6g(9H_J%%}+KZ4Al#Z zr1y0mbrvJolL}2g9$2PPKkpbUe#gXOExJu?(uH#SJ%53^o};wIthn(_W)FS3N>|RK zUj4=`Cg#)xsNB(K9y9**se+J00@bnEAD~8!E{5RReeze+0~#Ra<$HC&zAnrw;CgUy zv4Zm6|KgBa((A>@J|N;w1ui!9rYDSr1*HQ%ob?66Z(5RL!RC7WaWfoMTg^#6-ky(C z1WV~R`kd0*bzVNja&Q*$d$1xdN7iwvf712tSzx|jg%0ZrzO7`RkB{Sq)c}(%I(AzF zs{ek+dX$n-cN+WXW^FSr{_)n0JEx*V{jHNs@Nq89dW6U#1YY6ic_zI|6*IrpqG>2L z`D*)cT4zthsfM2CS=O-zbEoFa-_h}#@s;~C=!pIaAInR)5^dNmD|$>}p}V+sAC=*I z0D;FtLmugE;Nmw_WMfvPzqAx*&dn*2%S4J#l~7}D+@F3r9NZT`_wRSSxDcTOj+ds) zY1*$%f>Za?0sf>ShF_kevsk~{ma5sCPfrV|mbsn96B+UXIV32sM=uXnL@CA`CK3Oc z+u9aUUU2p?2YoGXLqsFekY^=)If{CQvu3(Y1ZPFoC_(4sYy z2^%bmdOl(-D8@FNQQW)BsC-pr0=tE5qfP(w!UN&qfsYB;c5ZpM`^hw*l3%}mMGg_& zl!XY6sTDd7oxfGZu6j;*xY_A89jI5!(PuF3ED;{kNX#+9NJ^^B`FmT8$_`*}YTS`7 z32M+Opx!VarH||(ixq5t+RRNwh3hv5V--r~c%8IC3NOc=ml|EUic<`P!L#-Gl(f@K zG)Oxz;;@()T0rx8KpalU^h=U|I#O=Rjh74{-IIF}qnZ=Vy6N7Jk6$i4<}&T%;jGUn zwnM1~rfFH={wf>6w)5^vpdW${caK9knShjB30A){*dfh(QsOM%z3(3$od; z*kKP3gpJbP71=(w!*1V_EhmOq@S+Cnm7!b&#`TtSWokmejd%I*+BHbd{N=%B-n*ir zuyiWEi5T-`5|y_XU-Eyyn*y2&2Y3T(m5g9n&nrA}$91nmgjgmBEmq@+2Y; zuSvjO4I(9Ua^n30^DpEhJMQx2H;8UDT2($GO9+C6?~i)?gjS^hN(P@oYWY~J9Z%uU zo7KMIQhw{psE@|a)kNl~06j)fq^9Ak>-jvE7AOcm_ij&}@!V8>!hT$B{h_8%d>72$UnpXI#9pz|UePa5F zMAR6}J#SbxtIk@E3v${Xda>up1i9+Z$0IRS*mUJ17qff-@+_LuH zVHv8x7nb8Dot4T%KGiGiYK!BLG27PHY?K&ug%jVV@7QbHB5-n-`Q74pZiQ2^!NG&? zvZ+W3?7Ju2Z|dkbjTI;7`dAIJi440@;vT=uBNK-c?^vV8zteiQ@Xcfxm5TDR&#n6W zqbRsEnG79a7bwkitYO(Wa(#tF-@8R_N+l=v&1pc~bpFYq*!P}G#mMm!$mKn{3KZiK zF>YOa8lGcY+b%7mM4$`+kfzOh&9tiR|D3@6>WW6n-~2p0U5UND_!b}0``LQQlMfRp zFa#2EUK`Aq)b6+uNEeB-IP{v`>4HqB6-D@wHQ(#cyO7)qZO^i+0XHbV)0se@_@R%t zehvT z_3wg*su^n5MuCNuZlCPk7kS25unDHbMQPM)@|hjF4$=Bd4lflVK=>2O1Pp2_Zmspp z{EbEGzn!^*PxhoQcHWgom;2s^Cc}I6jUlP5Mfmwl!OzUz{Arh)I?ZsVS$jgp37eJz zLl&$uq^t~rZPLY6=+9rh-*_N*-^SJ*DE;BDR~F}v1wFG5m}FtTzr(SREYyU^o?~5r zzK93K7^ydz;5Jz%MXG?E%y>aaG^+19YvS{^9hn*qG~7Z(L2tvC$EW$V>FH^I!7poP z6uqBdUgy@{OHA!eBU%rCPKku(Qe$p51tflQh~#_h645}5jpwdg8Z!=N8;&~bnzR}! z{Z$5^=LkTbho`de{H~e~*V3rQv)!^ksxBz9pV#%2C$!Ocx_r9B!#}1dPLR(YqdXCl zvz7M-$Y!-OV3&_x_N6kgh{E&amAd*_^BqtQpyY>adP^C~+%0E4>p)u{Ut1k0dZnWumKEF#Va)!8- zcPSb6Xr#fs?5?1%v1fshvt;9c&i4s&7~dKKEC_PTeONqC8V)4wI(NS5Ki2uR?)nHU z-H-tFXlEn9b{tGx+*G1b+C+vOR**a9#af5gKWCMdzo_6a*W79oc}pP1aZyL@qm%F& z4xze#FQmQ~)5gRN4YMybSc!8giEgVi63z_++Q}Si=&IwVGtQsPeG!^;MYAw~@+c%Q zlzoi?+&WiF)eOLOA>zn{U`oPoqDDqUY3&7;$a8BZ^=^$E^;Jis*1Q6IZO{?jAYmas zwk9L!OleLg4H?=}r^&$3dGqb)7euB{jrUby?nT=!+`S`$W3>(4NVJcdAEJkHfArOj zyc@eNkVV0FLAx|xKA9nA|A*E;Q~8bwYdxXOtSauE0dXpM4+YLdrlceX@23M4gtrfg zA&2hOW|oyawVu-ZywMT%Zu(|cRl1EBF=-s{T{+I-p@!seLFA!goPEMKww(?{Qc*$b z^nD8l7)cD&)6Qs-5++;gWL}TwZYN}Kml^eX@%Aq7iiq8yc&s4=(ZfB`{NX&hoftV| zDHMMjo*L?qxkQ)HMV{Qjzc~>`O24z`)K#N z3~7!ax$gi}2P3L%_5LqJRoEPGt?D7xu81^syQ_)pg`ZHQ*s}N6V_v$l$*k7uIsF2#Kbmti+b8PHP@s~&2xyOh=DPek=-Dj zO?rV|8%FQww;(Cxpu9+8a3Zc#TFprt*j^K~b16HWq{K!KgihE?SECY`f0p}cJ4|`f z$+OcS;XVpPvAjNGj^!xfvjP1kk0Xy7US`_A^%{!$m|(C>s2WL2ffvEC=5);I2R&i* zI)5JW^Sj|z2s_tQo4Nj!7&6ZjV}?PlPR~2^5t}QM94y3-x>$;B|I&Z4IplZOon4&0 z?gKqA_MQ4`{TM!mkOd)E^I5(S62hPYjHg|~fQ?Xm*8z{n8YB~chQ@07j=v-e`DP98 zeZyWnv98I?phV(!q|L@L9SSGz(n*EULlnK=o1nw7;wkU)yX+gNWlOfuuha&Q8NHii zEHVChIG){>M}S_1DuCGOIiRwbvj6oF(@H{yhF^@H~Lh&&TP2vJSx@KT1M_?c|w z81WQoj<0HKYDjNhx#)s(w{GoCrJE>BnpO%G*#FugC#lEg4h&7^t9wd2oFw3iAn}uN z$EcA+p-zbgu30U)o}$Pcc6>_q7P9A2z=YqTD2JRRz&7jJ{w&AcoS50-c;2!X?(UxN zjq5%MxSHt7v2hzA?ghs$78Ajta8zn(o?g3pN%yj6UOV#C15fM@96mAgY^ADYu{`>{ z`mExyNam``wtuvtu_cZPwP>p4jY;8Cl7Cs2WjqfZlVUhI!d?Kl`tQ#||1aj)u2N_^ zTRwXK&tCnLho0W^t$@gfS{q_ZGl@{=wHL0xYoModiDetybbcCyfJ9U(k#GzvkRTd~ zzw_~cWkIo&huN7aC>3+Ww6I($LB3cj?;9L@{-1yR{Qo?7eDX!ZwBB?IgupSO6DNm` zytMPskJt3K-b{R{Tp|ru?>WIO2(dO%0bl}8EtSE*CWF{R3A{A`2nk@>?#~ZV4k>_~ zG0V7rUoI7(QpiCjwhS0fbZT}KkWqk~BmgUjjz1MPu*OOQ>_5QqkS~k?CoHUNVA~X^@;Kh);{DyN=fopoJ9cA!ug7kAo3*N{=Ce;f^TP7QOV{F!iwp2D zHGBXj$B)YoKltEJfArv^|9E_OW>>yc9e3|@T31Q%N2MC5f?Eo4(JLGQ=;?F6+6dtA zAi!`Te!NmOvVIGIk6$;j+uz&1CLRqoS1SduECXnog;HS}CPxkdF9ktUtI*K41X_Al zgQ;t%tABOS(A6L|dBe&5S!bPfmT6uBJAVFMGIkS7OGB{+ShD6Kz}0;+!V@8oOIeUh zF^D&G)}9|%ow323rc_ApIVJ&uku+3_bB>gprlF~G1z9&mF$}s|#SZcm9vyh5j|#+} zO>;WDY)N-|J5KyH&8)OHMc0G^Vz{lTh26Sg?W*3M-Z;Z@h-En_&J{_;U#Y0>)`pxh zY2c~j9D>}LbcRU#9#NCIYBe-(bmNdU-~{^atU7lBjZBxq6~2+2${oIH6*+`g9k(2}06&VPL1 zsc-H*GW^oec>dM*!X%Jm8S$2DxBuSiHR}fg;RM2_f4}e;xdcEmnM`V$rr}B_Hb}!g z(#MV+JLa!Y?<{bU0so)Nm&fooYv+OCpPs*Q@hygF8XH&jULKVA=stt`JpvX6f^I_~keZKzaAFg-H?)v8RA|EZbWm}S}e_a1uw zuO55hz<0`c_TF2sYj#yN3i!;|{_^jBciZN*&#v33^j>yp#kXHEIT{Y7u{1N9?tfd!|2zp`-T!9r_mJ z|FF=I-|77~%-UE!$K@Z@5@x4};AB@$HOqFZ7p`-^+Xq#%{6na|Nuf@1@4Z;NCaZVI z2Nkrcqe4TJ4V>5jh+*&629T^H?lcrVOS& z4Gh}=2v}EcNf8-8sfu8A0Is0SvmNC98M+P(evNLG1se>qVvV`LH3tCNQ8I8`g1jZU zd=ffaTbFU?V`>S6<9c!NkyhNHla25@GD*9@u*J%IlXe`_s)wj}PyE>6N`deRjuz|CpGV z8nGP|K_wemO-smdzkr;1R@ zSI8`I)Afz_s4zv!}yw%r~KMHoEM;_W2=UV@`2ih^Y^ z*aH9)0aH^`Q`ivDU#Z?5)F}gw-}lgtKjt|)`0!JE{}zuOU9+_P(%=5rTz7CY5K{LsiTj-xbK0VJiGtzRaLKG@1tM#edLSs#E%|+>RS&y@-+I>uYdiI z)~;Q<_TwM__{Xoh>Z+@-nPlx}NYg-bOs$pGa${#s5`p1aFpVJSl`2#UC1QF=id3eP z=#x?tGDr-H2>}i#`Phg#s6%ch3)n_V2*iQG_pgwR+0?%dN>y)!=Qw5xAKK3lO+*SZ*KSuMD z0$j3yLi6`=9>g;yv}=Khw;+;W1}hA0g-iipg(T2SaK5#G7zR4`#jdHgH>$w(8gL#1 zD;7ckT9yzMG}{ae-vO363$~?!X%xt4L6&U=To1;kDwOS3Tr6)~p-uWXy#T4Ec)%ow z>%2^xF@=;DFU^>DJ(ip8Ii2*B7l z!0a5r?vcccFYGJa{|2K9efW6C@&B{;CSY=1<(cqz_qw%j-Bn$^?`lb{eV1(6mSkjO z8{-v2%m4xM1e}n`Gnq+XhJVOEkT3?4NeJX;!ZJfJHo*{sF&Ja;zR8lUU1~|K-uLRR zeYxxZeCM8ft6G+A*_Lb>)!{K}wQB3?TjzY=`@Kt3Q&ZFDKmYm9-+IeUcZ>}@>*08w zY3VAxtIl)+YiA=Ba{kR zwy87F)ZWq6bj9Ucul^GS{$gah`1IXh`MWRe-@kvqVP&(vOFo$3u3z4KJAR!n zD9MFPam+N?!iLqWIzI5eYnCtVZc89F91~IICg&kDpR){OjVjGPYti;?DFeb`hVJTd*tw+jS_MFZ_0 z`Or;&-qG714%f9nIM(_Gno;YAMK29(+UDlw=8yrfXV0EJwcYCNSqQwBsgLBIgF`?2 zZ(sYtC>jk)q9EU}W7S=a4e?MUD0ei)WA*vMSRh^>CjcBy@`0p2L|`G6B%moWR0@SW z%*;+1WzEQYJs#o6@xjv!Ct#MLarpSq!J~uYd!Kr7;HSBwGJig$>SeOeH1t^4_RLrTTpm9NA`ih>1ZHMtW}bca*=N80^{;<@`1J9l$0Y`j3=BPg zHZ}uZ>kmBezyrH>?b^jKubr>>kT{p>ZTj7xr<{N z4pBaDxa}NF|6UIaID4H?J?uAMVb>2;ascb_Cpvf3Gf|45X=QQm0go4r`@jrAx)vKtKEH4AY`GMuUi*`5*2r!*(kD;c3b}|6I zPC;w}mT`fp7lGlzz_D)fcU2iCAcCQ#K{MUJvJq<9WLUQG_Rmh44K`I1H*-XF?G2rP z4Vv!c!s45*l@&6vK`@3;xO|;ZWJf_MCz)%n+VQEfsudo2>ZNa7435gWVdy{l{y#kj zrunR@8Rf~j?9q$WMnrpuDm9Kmykw_$vW{*XlFBo&0f3oijBANK-vq{U8uWQXBxmGcs zg8Ato@CE8$v5D6ux=2HMY~Le94&V#LtXR27BQ$lchS5{|U}1J_5deUD8m14NI{YL= zV(s8^TL5#pn1lM3J_0%@U}n>@EX`|Ptf+;h)8Klsv@ zzVxNR!NI|I84$prrhjE`{5oXYA?Q9in>~u|=Z846vzh+A>N!Wv&1@C`eopbvKp+qhanxE{??CNg zs;5Shj{E-KefN=%;GbT%7_E=^Iy`RKRTuKMuIOuDKQuNu(j1F)oEn`zy1b`pi^uKq zPE0MFXimgqv-8RPu~Us)1aeIT1OpZXQl!g#r@wD(; zX)*BJbI-l-ulIfS@1A?^x#zG^KUc%PpZ)A-Kl_`%`J2DNbLrJ?gKU^@eB&G6uwyc7 ztF~$Yz}vLeuIRq*`s=Rym?TLYBAfoY*Ejt;#|?@&_X`{cj=z0X_wTp_&~Gx;0Yi+{ zKtt6u!!#>C0ZyGks|be;z%6$9x1IMF6)99(@0j%w=AvmiqZ$=Wzpkc1DbA9~KWg_u zYM}IgwgMPXPrB;JL(@qHuwE=D);X@q*5W`An?WfJfoT@OfE;ja2w2Q&CK^cI0Vs&? z0Wol*%mo{~ppRwP;D^9D;0JlHsHDK6T(IDBH-e_*Ancb~wya)t^GkAiL54;gJ?q+)Hn5lBzqyzu@VLkKLy!^DQN8x z#E*XTqaWS9d-v{#9(w4ZuYK)nUpspA=+TSaMIAx*&Zh9Dp7!V!A-~*&``q+gcHqGA zsRyx9u=#O=Ba^3RCX-4zTb7lQQgyaapBK|I>?0C1mT^#a-2Vvxu3P69SkCF>oUqIQ z8Ot0O!2*tTH2zkjT{%z*kiaq(qdwgL9n)uGuOs2Lwf`6&W}EXe%wl)nDqkS`Aa^hV zJlCjifpb5mQXde}A6H=n#2Q*a5@r6qs(NiISDt$D(COxvj!yjaLbAr%+uPgkxb^x! zmL!>vw=8=@_eCiVHcTd6*tn%qsT9Tl)|}5Tu7xp!xkA!0>3wSNiTe%1)NQlAr}v)x zv1yumwosnK2t&g#v}&m$evSSEZ!4Ig>-xaJz`)&i-+lL2zxvg$BEv+Y3!_@MY}v8} z&j^&Ch@vR@WlwDN@|9b)vdWrY-TMAy6mHv!-T2U?r!pvYhv+ zD?gDH*ng*4$~x6%a+Rjs`Z1`}68Sk%UnPN|r@_=yVDjkP&y%0i0v8O2zDWQDr~nUG zl%c7MmEnr!fGYJ{u$q3n4*@iaW#A-%umKQMARvI2fhC>s?H{~;``!Qi!(V;mot6R= z%W8W6@yVaR-8#+-xn`2N0sQZ1*wcl%#l@1EMt^`>^Iu!%dtpI!+ikbq_UTW5`qQgc zty*=q+n{bAK!(|ggCz1VRNqoLtOOU-H+DmMeiEj~j)E^3CrvsU1mYxqX6!f=vPlvJ zb+(1gKF10md40q{&;|;EkpvX8^RO^GN~ZocV+oskZ0wKjeHbQ34nuS28Ug~KKL92L z6f*PR!b#NBX-f_eZL;pu*h5~US}u~?H#9Ufpa%Bln{U4PGoSg)XYRZAhd(YWYVl$; z3*%`mA{+IyX))e2YmakDY2XXPI&iA|u2*K}2XvkM#eo8I@Hk9M{-uD~+b8nIJ3h zyigaZi+eqCnBjSCE}5J_j|#j-eID0O6jgiEeoWu`*0;WeQkSc*zWVBTJRZl-1vdUi zjvP6HlCF`Fk&$<^tgE(a>s<)|Y~Ql#L#z6`uU1QG@Yi)iFxGb#O8#3!Ck<g%mwYZ0wNcnW{2nlKnz>(Yh5F@0Ys9ZX(TBC?=89lASxj!7n87lMc)m- zdv5=>1II^y`A%Mcm<{~sv{T-`J`B;F1TSxn~_jVr?W6(CrUHHa!dea01RI;Y6A~YW~Mh?dY4#oywCTxLVq=`tFbOL6waPr{epebdiNfcdfDC8Dk z@W|89+Pi^x37|g#Myh@J%U}L-v5?gt`o%9ELUMbdsLo$3za#A38|r*ZBSCk2wxG=B zi|YJ|;khSL*^-@X;;gCZK2oXwE$$>ywBFz+h+`6uGz<+VNy_- zb((O70_o0i%T~@7)@F+tXHfrHEAERCxU)C7*!(MMMX%53&cxm%5w~`eUp4oy&H{#N znSj;g69xi49$SGS$n>9GeEp&1B;MEtf+)FDsf8^^2gi2`0xKUsJ@>ow4FW9b?Owk7 zinSj{UyBu+ZzR|Kxhz#x)oO}AHeA@~ppF|E02u%GMsm_?tG3S5B1{xr*9{#DMk|%6 zn9JugXS;DWUwTWi#rQdRfv(zHUt7P=i+i`cP`676U31mOPjz;5E#-I@gc8d^l!F(x z8nRuBs}B7$3rq8iU;rx?2pngB`}S;AYs^$L2kC9>lEb70h)K1QtgS6HE3yE5Y*o>q znn{Wid9^eThF&H>02=Diq5s(jO;s!aJLkBPEoeFn2m5&qqYS2z$8cugg&=U8?63=f zzE4b*e$rf2#8n>Gnbe%Yh^W9IND&pt)CAEGGz4T>o-LLN*<*vFPiflupP1BEZPnI= zTd47T@WBTkM0aJDeSI5poXn$9-|YARU<_bpeu^~f*o@=9VKar(enPo#T~59)$sQ8H zihB;3^z*{2Z0oEw?VlMXrfBy5tSUt)=2GN2@j0rc0QgwA*P#>uv!s2&db+pqBq3nr z#2%2nA)-IUb?Wd_Fgtz{G_?fT)C|$2;(ms&7hTl1Y~FB%R+z3&%}t~d!d^yT4o!HPVvE*EhPKcj^JK%j!2 zSBt)H(({Nk@+?iwv6^@r&|nw_oF9UvMrHW?_&oG$WCbv2YRhr2a_uqT_V}P7-slQ= z_(Uq5bft2o$yBB^e!hN>NR9rFpZd_>#{#esSrl!38wo?^+)5s60iDd^G!-ZR`1L*a z+;b0pc5(WN4br8)r?D)*+qnrcda#7)km*?+u6liVLR&D)$talBXTOSQ{ zE?e5SSt+F(`?k8)mcd0GevuzAhK8}=ML`O|~PhkkuAU6)ue$+9e?W({Lxuwc5_ zHNLe~TW{Aw=Vzo;Vy5^Txt}Pxp<~%LICc1GSV#>M<34Qcaq5ngdo(peeZEA^`LJP& zHgv-AmwyAi=pr=yvo=VgM3@5Q*-^-6W}Vc4P+bf06-dpEk%&Nio@x*Q>HRIe8wmRV zEr)A7||svCWK4>hSDPBkb_&o}f6u)qN8{4^QUnf{aWlBCX99hZ|Rz`Y8_ zgix-G<0KB5PEoExR}QEvJzh^C`#F2*!+vd^iL&$cNY~ccX%%KNU5x4 zZP`q1oyVFBfc3b=Fv=ZNO)p6z?=>xrD{~%Y4vgC+1S3Irn`S_O&`vX`z?wTvI`h` zBggI7v^4(C)ZHn7mj`wzu&DoxZK}jL@&HZ{L3D*cSMy*P3Y2rF zz~x;AhRIgtCeuN`X8Qq9?Z0U(dO0l5Tem}vCLP0=dLB5=1E#3}#|It804e%N9e0qdt#3q{~0k?4U%DGZvL2EUg}v^T}p9z8Yk z#5<|M$ASp8kx1voV(5k&Zny#Uy{Pj=o!ApkJn;mY(V$5T7EQG+rnWBSwQ}XkRm+xi zY{F()5M6I<|J5`o7t(&w<|y*S7&C8%&KJfmCvg$QjV1prN_Pb^8bZ;3ieq%m47r?|*i7K0EYI z{+`g(w7n^`0d?sohLcaeULjp7D}@&h9DjUOZ|9cY*5*|Vo%A!*u-0aV+0nNQ75bxx zob8KapF!67XIip>Dpndf7bt6twVQjIGDG?*(>hmevs+3ru%_^5DI(B|hMZ^US3nSb zj+psb<}{Sac1F^Vb#zvJ&!+n0^9lT76F`nVr}r9PZ=|k)-M((w6^8}}k1grQUv+G7 z_P1{p1PJ)t(OYl4`cuI`Ac!6ncr79baL%7MUDwe+0I1VBx|}1JjT3(a^3cE%&%a9v z;Ks&3>XSQm)Ybpla^1CE*7Y_~WdxDsK{It=R0br*11^q-)uQW0QUi*NG29qDIPPQi zKRP=3PnnW3lPQ#EE`}tdcU!M-mAVYivJB_y4BVd#xC*a4p_5sP@c-Le?mw7UDI_SVL}uHKdPKDVbX z=#RVRr$<;(@PJy(1IO~FW~iltrq8^v|D`8>@#vHP_w?w@e%U1id~Pw?+u3m0j;pr6 z2Oq=d54wx_V(#GK!-r0sIC*4fWc=iOx-f#E!Ps=>z=ci)sjb?2*8%_@Sq!aNy<#WJ z3ykcEfy)zlTc6+3&f60P%kkftXe@HnH;Mk=pzHz0gvGi+3IqV1Vwi@xi2iQ7;ydp7 zjGazkfQpGDrb$intlVMyRano!0Vf5(%$x?66VWFXSb+gX=PJg540T(kvICr^F!X1u z#29i8m|;&n3~e4!0qS=Y0gm^PX5Dh`uPTrj)&W24_Y0@|j6EG8MuSF`^Dl@xLe@W8Sz;6*=dUbEt+7xo|h$<$ot_&ahPdOV)H?z-!)kAM8*ACJXi zF`V{eVPqFg9UUDV+qP}nh6NM4e*f8@{n?+5jtq}eFiEX#H??)Ct#oQWKYHq5p}Aw3 zTM*-K=)P(>PmKQ}@peM<2RiBZh2q5Ve{$pqwDzob%=}R6jFWtH>c?gqzdmbGFS@|( z3&Pa!5g0jo5Zacbxt~NM1G|Zye`@3~czh9%8Y%z)z6SIlK)C>d2Z2Ze5*;fb-ntA* z#T-nJ9409P-eA4M9>Dz&Spnfv3k(nJAq)fbD8QcqeFAQH@9taGQi1vUxBu-g=2Q8x zck1_qPXC7nrhi#hwfwnE(F&zm_Nnm*1y0>oW{~5wgV=Yra z{GQ`0z?|W2V~5nR6$8L3oxk-s=k7;@OqAuzR|a-%8F|mld}ivzaPleL(BJeKfyoWm z?b`6E{^h;vgW-B|9f#xXZ|E`Xa|~!Ex-A1Ze*E}xGy}x*?^0v8wTJy1Z%-x?V0L~~M8KC9W!#&M zd@fg<96eFg3@$r1K0Z1)aCl~5aCG0Pp^5!N;|nk53gtOC%fww0d7s-Q1maQOlC}M9 z?_ITO<=VE^=8lGVys?nWLm{07iA#V>2!r2e0CI-hkv7ov5~FD)nd6w&wzk$gcU-ac z#>by{(8HRv*oPllw;^T6EB;yRuWjuy#ZefXPxU0WA6=8uc-p z1g4>ZX%xWJvj9xE0#ulEqG7*s`c#CXZ&nH)oaU3Jocvt{Rha_QC;`LDAP6z?Iys(o zCitXi;yIGF%}{f}${RzY{_MCxs4yE4MX)2Cfoe#JY`|oRQ6Ptt923ChY5+wMptH4k z?NyuCe(b(qJoaDT?uHtRBaHO=!WX{q1*Aga_mBy2*5XbOgzK)m?z*9&p`kDQKcBrj zn=d7y1_0F7MZ83T^WaA_8uqm?3~Rb1!7sZ6|JdaG5w|P_rsql&HdEKQPMD@ECBZjWCI`r05$u=C-y-k)@!?;uLuObxu^^nF|}FLUsYvQW+*r3_#1$rIv=AWkJ_fvK?kp)8LOJ7BLsF0jzKA zB@%&LYKDLUC_V7{BOvu`AclY_6A0BcS9hKS6z~P=oF>s?9Q5MP!SCL^>jnUW``S0} z`;=Xzz7uP9A%E&zZ>t-It{H|BkA@SnOB5`VSD=pm_Bm;@!6=)oiuL7~$l7{-dVZ4I zu?(I512xCBb#|tc9D{%{Y|N6{8!USMh2LzxA*}p8tA(2+FiE^JnO=16Fn?A z?#-2V*z}{LI!jk`b8|B`|8sM5bC=SdSQqwmUE>S?tzY3fo10reGFXT%?FC~Y4Xhx5 zGM@r zXEY-mD+PV7L^SMa_xrqojT<*^+J4#Q-QB%Q+uD0p`gFC-;C0ROA~nF?LThOpjB%{0 zlss)cD?O%RM$4sKdvfZuIX^db&E(YV*q#?(dg|xDdhGk76LW|2MRmcJW+1zG`}+1j z3I_vq8#iy-w08BXwV`O-gLSB`Fd*^_1iZ)uae><%0k1nu_8CDGPzGgNfVrW}OauQ24E)$?fle{K64Z ziRoGaSk40sE8&QOJi6n?Og#q-qv8tyj?W+q)^J~ka$(4NRXBwg>If5ntvDiDQy8Z5 zv)Ro(PHL>_4D}VT%Nol}!THjzrHEM|eLsk-RMQEdfV5r)1kiPq9_q~MrCrxN_}gc{ zmdTf<-_GAXYM4Ly$xnXLZvM{&FhF_0-CzFVKQ5#THN?NRUZ)`d78~twKyKkVo}Zpe z4;D)5!i9J)mSu!k#Mjl`-mq#Rou6jF6t`_ydVNDInpm;4XM^kw8O1`bTvt~got~ap z&~+$2`TWa|O0q|ah69O_k&&^9sriAQ{_2_k^?J0{x%u?u^Lt);Y{iQHRk`#m^F{yw zyeFf$Bu6DJ8J9}Ue=gP&;YhoNK7fuR;*i_)AFpQqq11&up90meVv$;fjKOEir zYe*%>!5gR}(gQ(|2sn`@Q~tPRf=8P$1Q8Ix-~?CI?}3Bnt~E$sb>DK!ZSM~Rg5Ga_ z``-UPF_St`C@KpV^Yx0F+gK#nP}Z~pX1dz?adM7O_Ls#xGbm-B0_Jq@w^LvUD~&Yb z6g#N0ld*wxmZd&2^z5a&G^h9{w0&weiw1z_^m!xf1HNK<%g{63w9;x!-K>c3Y^{G4 z#hW_cgY=HUs`FV_HE0@dVODzI0Ur>^4lw%UTy-ZvGD$p}I5WF4`8XKTEJ_U(w z>!C0{4QeV4<%wx14GsfVD=7ICSq?*d`fw9yUA@_>5{MUcL=eAQ}e$} z7l_H`rF`xY6UCN9c;&Jso$FRC@7dDT(Y9pS%1wUF+8_zjF23jZ5p|O&+g5 z3h|a@044{sr)NMF$`&(~v64dYe|G(?X(|*lbFi>53bV6Z~Ngr_x#|o=MHP>Y-s|cm}}kuwROn@0A9B%+!PNl z!$Qg*?EvWv^FP~&4vP#YHmJ&d--)$5i-Z5`pNLR31z;Sjf5UlB1JttWOfIa+H$5ylAH*=>`EC?3e<)pD0Jc z(7T|NJq>C(3B2g0#p^3`jh#jxiy*zypIcM`9hAap(6uCRoEHQ!41yR1hUJ|bS~3EL zP&BQ?0jj~oX$eE1k;;1q6$V4KiIZ(SXlT}LIo@JQ7F_CC&X=!PBBligg{E>KlxP5$b_Ec@Fsjb&qeO*o4?zs7yKke`DTO+bs zbbMlZ`0u`X@28KP9Df3fBv}&t#j=`tvpUkoSg+$lk>;|vL51DKVFcHkh1_Lfxh810jzNu+6z>`7gZ-nu=(#c~dhxZ;k zHSzRo=@)U*@{5O`_~E+M{g?Ygv9*ymNK0<&SVaoJg}E^(@lp(6wSaxZDBY1q-;qy>WKp zBmo2vpg`cDt#<>AoY==-``+uW>1b4Zvgswu{waxQaORXIA+kkInOz!f9GRiD!__mOWRhR7+&|%(TT=40{|@P zsJm*z+WsAqB=gaRjyKi()B1?P#vcIym&@fsi5s%n(C;Rj&1TUT;8NO?Lw>o*t$;u1 z^1}4*o<>S0=%q5b##qyY%!xtpB;w$1X(YGz^>x9*-UFZ&ieRR*x24px03vTdo zB4l-i71UzSEvD}qYudfPePDX}^9%XXSf;2A!H>~Nu>SquB;wSTSQ-$lU z-Fa)@vQ=$vZ-_x}mUzn&U|9jCPK|+5RxEImvXX3%l42k_5Rjv zO{i%9O*+Y7DU(uDlA!BZGWo}1m*c&p7;~5pwyx7*L=aCx3RYC6Bz7}z0|wQ9C*A|r z|2Z*&hQV5n&J=M43Z`(J4>V;2L{9UsUfO>Bo`Zuwc{`o6*Q{By*6;QD-{3K4loc(H zkwG<+m)bhp>T0du)ZUs{^2v|f{<)6Mu69w9ICSk!G^dw;T7xfsaquZx5Y!(ba4 znjoLgf!E^$mrG``@pVZq^4Y74#>jrz*w9KQ9i>tcylxNqj84x?L36}x|I|m`_c!0Z z=bak%#q>{0RU$| zF?5K;+aS@tg4_ouEA4%oVP^CgObi}?cOJ0`{u_o92WXn$?D2S=S>7+UCxDf-!&1oriTcCu@hpuNghh`{9#l7+cv;I3 z*8&2}d=Z$S@6EI%)E_{jY&F(7o1BPTYCyKoCR-MPjhAzjytUdrxc{pUxb7 z1Lqo37xHxU^>nQ1>g|u=b&Md>TUprr+eUu~1|TC~U|?WiVPRq6Qq%v3IKIWLF_HA) z0T3C^i8*GForpdd)3Z>Vo(1;hLm>FQASdGB?e4HX-{~x5jtqcOE|Y7U$KediLxknQ z&$~cUaxN~LzxrdLMAOkw@u^?W%zSx1T^#v+e@|tJ4}=1q#Lg==-F(@ml{a3w`<6aK z&AICuyCE29I_rIKpFmKB@NJQxqNogE-xvmH`Jz=Pf>kG~iehk*$Oy8GIgKEA+{92C z0as*O;b#PZX%yMwpA?IQa(zRa)U)y`vftZ=nYsB4Xl2#fPc(z&nq@puSGX$Tw~JN%S3 zFmPn((EdF`W22+v4DV9b^mkspY)Sj(t=q0x_x%1-OTPd8d)$XkO#Y^pBvD(JEC3)1 zyh}IvlA%|$HS(z?a`g(iX zuQ-oS;)z&nj4fKD9T{ZW&9Mm%Z4n^~Q9`FujW`e+)GNS_@x#|c9*?{}#%lg;xq+3k z?EDr&OV=KP{!(uBS3m~5xgsp4W-Lmh<>7Tu5fdChLaU93LXXnn{plOWlZjHs_ z>rcpZLs8VCVbnJ8+Iru5t4gzB1L?_>AE>J>}2{qxs8 z_d9GnQP;k1{ko02uGoC@0}uW7|2*^Jkq4$`v&UY!Uvlm>%iDLa?eE&QZT<3XjrD=f zklz>fxIM&7G||uulIQ~4?<*Rvf7RD#>$gQwBLDgQRuk>>1>yL>A#Urc?#+Y4t8N|` zoOtoICYK0Sy!g_gCuS#ylyD^GZth-tmK(i#Plb&#YVmOoad`rOQ_iX$h`9En_P;vC z3_%o6pboMlM__8?2(*p$ z+XT&BYsqV{7fy|G=_Fwa%uSpk&xSd0Z7uMZMI$W>EZ1phy5#}GI@*86s5+Nz(4S{%^dDO>1Eh^VDc14a%;f=sZ@vj8 zAOM2&wz$_cDt-VuHRffg>EC%;{y-SI+FIiq`a7=NdwA?8xq>ox?q?IruU)%#4Nm>> z+_cj&-tyk$cDpgf2F(Cb-r@KA{g>MQ9P+qYT_wg}!T}0r#YM8rEB7s|iPTIEw9HA! zoj47=EP=1H4T5V|K>DSFU=&NBqMVUo2@rr@0ddI(9!}(aYJNr3kXH1?TQ9%IJ$=_u zGPAd==)ZUALFlK@P#5UkwrS-JTen`eaYIHC*;Uxi>yj9WSo~0DB=JDgt&h9(-;CvA1w$_bFVxd`KAyVxn*>AwQwLoyfL5LZ zT}_i>6&MXz&I`N{t4#5sLg_ahb0!PKu$uhJdu=f_z!_+mRk8sGL@*co4>+cRY*l&! z{Te5Iq7(&QEP4cvmEW#wP?lx6yS=^J#P`XGcVq~a>ooxYO;_Er6tt}pYTM04y%uGW z*3!Vr1;fyTWS?Np&`#U2r)G6LTxBIE2Z84$2u2zgMVsNigAI4Nkb$|W(-0*R1BN!| z3BdTlxyh4|UYLB<2@`q&B&Ua=TuMTE-UYLhCqVKtFgoxeVC<~N7bTAUXhw)`|4Y|h z;N6v4KPX29xnxzqaM%7tI_F&cm+6{V5;W?ygmNDO( z1_3xQ73xlFo?-P%zy{X(LC%v50OcW(x;VS0uX9C5^P$ZLj!*skT<^PjdHdBZP4&xi z=~-B@<^69t9+{yZJf!{eJkKNTADjP6%>WSB@!8ZPxu`eEmP-lL@!L_BPUum^)0tLc z46x_}l`lf-;8AczA|SUkL1}CP^n8JMHDQm)Q6DFgD8TYCrDVZf)|dTZpy9hucs$>K zY+~jg-v|hFQ8ySID@8({)@yfc{KFe=`oNWa-EC`mL1d9#btWrIDV8ChOk4GFxlC$& ziv>ytMbvl0piCU7N|Z9_P>G>FQV!^d`-`GMDVqmPS7BsqFBp<$MjP6hMC)phBoE}~ z7BD@;6lE79NFvBSOE!S}N+F$tp(&(F&=Qpj4X6sO_GAFF+kw{@?8kK^HWhzMs zRX-cK4|*vu26@kkyu$_q34l>{uRGk?8ebJpG)D(d4%V=s$v~i-l zq~tQ3TaK1ShYy#N3%SwRWO90NWbF9k&maDwqN?R0HnwkKUAJrFAAk6RH~)$32{LHf zb*5WAHi6gzVb*=Td8za7m_ctEhPdyEz+_&olewuV0Zd7|Mu zsIO}Pm&^6aM*BQ0+yess5Na2pSjf9S@uBPgb5m2i_v_#J`CY}5de$hTOg6tTF*P;P z+}fP5%sm&sF1z_RsiCPI4`&0fvNr^Qa3ct!7t~^zB!mznIbMKBtQ{st4#UjYaVTWw z!56Fp!Q}=~lp$Q-0{QeTkpf^UK((2ly-;4(v2+WZIPe%8Kll(ZrWYi)h&wbXQkSgR z1%rp5BGi7Q?yF@qSM@vKrD-q_jdeqMZU!b#ABCpQHP*3Y&`r+ZKrNL>y~=U2<#)mW z_yP?OjdxqLR6BN+NY5P9yb4g}=w3`m zv<&+eI&<8tHGNSkj&sV`AO-dMIbR3>p7FBV2W^RP@3PMLWyep?J@$H0j2y>^JjY4f zH}&5RdfA06A(lJ8+K+zvzwh6-|D~sgCl>a_>LV@J@4WgW0dJigjdhS- zgw*UD#${_@ly$;{#i_rpTXEQ=eANwj>B!!}@BZZ8AC67Uoxs>n3i6OE34hmy$(GSC ziW6M%rluZ|J5tiGq$BX zDLO0zIh!58+JGQbqI_`Mzz;8;o5ZjPWA{|WYItp0ew7QcNsBa1DL^qZN$BzALXvzx zs}w*jX9?|-;Y3i2Rvj$5L!@XVdU->G+`NZ?1)@6uvKQm5@=k5x1OU+Kzd@U4NBd}2 z==)Gr5HYst674iudbqHh4}8&nDCK9Mm>mPt5W&z2pq3^;Qw2iZH}nGeQ&Z-N$sZOY ztP}*%)eJ1}CC`P_HEXkVWS3x|R?^NzhKeMCuo6f_6H9>uaL`l&u%IrAr3?qttfU6e zX&y@r1a101i323YP7H8@+lo2Vix3Wl;$F8H%@vf{3w;f)Ua?{|Mj_c+Q1X&-$|RYu z=_k>UXpHT+V%vLPI(YIouQeU5tqWU-;3OX>?)6cB+l|*<{o$>f*X)khM-wLN%H>nj zJjeq;Vu!@vIw)nFTNu1y=R+L8+KoF9K>Vf^%d@;MbG5484ffVzfm7(Dh2jGsP0bf9N*l}2Cy>8PV8_JOXJAf8wU zsniLOyf9if)V5 z1p-K}0Aa5wr4lJ#Z5f&5@Opqowrw=I_g(>z1|RcXSVGr>0YF-=D< z<}lz)#&PO*2!PaN>rMCncJpuh3NX$qS$so-9E|4=V0Ot63`V%+-EF;3yg1l4K0~|! zUJIu%`g`K<>0Z*`_MwJf zV7RJ1se%vLmF1c20Gwhw@y}J43(B!LrUGn*c-cyG(o2C`#PFAW?R@O+%Vdp1ryy5zr+k4l@$g;w{vYanNDOVs(f4NYyYDGHiLWZY7lC*RZ z5lxt?ba00aJbvFw1+g^s$lxV4C6VkHRo+sR5kTu^WDI1pDHt9+3WZ!5B61v9@PMM~ z_@0voW$|m=t8)b?WO7j7+5je_8V~>K$4?(WarpR&;kl>hGo_)A-f_!+t*cLj>JvT0 z43vNt*n{Bf)UEU{;%Va4^bC1jM~>~u{Num=%lD>|sWAlj&P@1;1l?_ovB1(qqM?cB zc{Jh#rI-gpD~SQ0D^ZIFtgTB906_D!?)H`qf*9aY=Z+IIPa4@Xv@vs)Nyj2g<^J^OrAA04~5hiu)IW=1?07G0_a*9 z3>}N0BDShv>I!)pwUhzT9f4A2f;i~w3=cX!MtTgg!XR*h4DLV+04G-x4an=YCK32| zqzE#0Jn^E9&7d9urp2Z=plXuDSn0H)8)U8-Sk?=r+yoe$2TZ+8ocj%4Ncy6O|zV*Ujw{q zX=!aVfvxGc-tN7FVR(*Xge~ir-uS-VTRz><(bgM_waC6;$U~;9z7T}#+kDu3<8_J6 z7EaK}zJd`y*(?~j0*GFo{GQ2wzIyU`3J zedfDE4Vj<%S_jBB%c}|94s2S49Y2wmsnKng8bB=|e%N2s= z&h=0(=3sW>1W5(Z6b;I`5{QBy0^w%JXQqjy0vl`w7VkL-0HC2C`Y+@%3n0oebi}R# z(Zhf@7$ebuskw3TxO0=k5Q?-}%|9}h=%mW)k3&N<52ug60J9T=5Q%jF%kq#}n1gb$ z2-73S33DM5YXjNi1D+Q^DV1Sib{rzH7Vrcj#Iwd?fAK`ZAiB20(9vf+AH41TpIp_y zY{TDw^ZS2!cwp>z7sF@FG)yBJ@W(5DFXrNDc@>%P;qYnRWiXlr_D z-S|xA&}#ub9$Acpg26~*W1`t5yNLni`DOs9s;cJm`Fu}LPY=f64h{|uUMlBDYuLAb zZ8&)QN^oB#Ic?H`k*+GlkA$RLks+4> zrCibS$Ot7MT-OezTnQwOL$g2h6d)<4c;4u`2^zz|?C1m>A9!Z`(EdHAPYlmJIX0a> zaKqJ`{$$nC?yK=NNwUXE{?aT@E0eQQ0{QS&@|YEB*K!A=w~oX6ql{Vgi0MjG|` ziI=Ha9)bfBnGli9NN^KfDn7O-dO=r;;PS;ulWP?;0;r`FnfwRhD?llwNfV18fv)7C zTug#s_@Iy;20`+JQp|$jss~O80J;^}=>`U)SyK(0Vo!ck{4 z9f&kR<~qr1$EiO{C`$$MID%XcEa!3#u?mHsQaV9**bfzC)uMA+8Ope!^AxSM5pLB< zHE^W8l(}JvM6K8W(X9`HDqFBt>%m;>QsPNDQp1js@z}Mt;%i(Fb@Plmc2pn z2BI{UO?-6vpA-5hBrMq7`H?yPRQQdh8gK3ptn^K1`OI;82IKQZ!~SjaZO*HJ7MSdr&hoK|3t@!5Va0iP$Tl~SH^ zA$!J1%xV-hJ5m(^81#BktbKt@e{=%^fhJJ$C77K!4Vi^;2u7QsXT_D|-$?|j5CDPq z!U8uA99x3c?)4ywK2QoO$gU{boWR`V5Y#2QK@f#k$Rluy8meo7LOu;MlLtU4bwhJc zKiRX~avj85mcz;YkHOHfBjES7L!hpn0-hESizcs<9Drar0Sj~EexG(6`jc!(r!@YY3 z@s@aK$v}9nb9O#|@>Opu@&29L*M9(yVUNG=RiiH7Tq9@wu;_h*NdW0|Iz2HlF>y&8 z9t^OXJK`U?fs6d7HeKw)0!5Yuay`nd2nscz##%?ix{*2q*a;Vlt`hs2gjasQ;-h3b zX;9>RU^s{hZct3ky`A&jm29aWIg(62x{xW3Ud->CC~%(jD_U=U-*wmAe(ig&-__Q; zP7nk)6jKE#<%^&et)`q8dGh(T*b%xlbi@6f{HIw%Jf`BuWtbJpKVj*TJwOANRe?tt zm|gGc1_c2*GL&H{%M<~H`Kd{C-6v;A)Ey?0FV02f91O#n)SMI>cT66^+IMK+Ie6ru zA03*T&yI~xXAYq+(C({uUSA*Y;Npqp#Gnude)znMS!pyd7Yq9h>?3frSjf)9voAe! z=)l0Cqseq(q)=4nUpXjZCATcQ8{7Ka;rb>H-veZ`%_rwF2acS0KAkO1)ylfsy5s-= zT+_1)rwZ9w#p{pBh^g5~A2A4_%_ulMq)9duRyQmcPon?lNFQr8r;B-5wyV9VQH2)O z_@VJrX686(N``8U1TahmSY8HR@`2=ukmuqA7r2A1AV>ixJ-}SlKr1kj3iMFPervLMkU*3IU zc;>k?-Fu@UU(4!cojY7EU&X;(H=s~V6P-F{ASc?ElSu+b#^p0}aOC-)feRFf*C!z8 z^+B|)lQ{Wb6z@65K_pyH3<0m(vEh#K+5E|SA9(yrXPI7_(=*8tli^e%0n#mok2ASZ zRBO*LtH)>HXuWYS;8+nNbzM*zK0v7RIQ_SiMHtFbLb+9Deg-7j3oe(ROkk|v9S0mE z!^rXdFf%+1OV(Wuvd`y$$o7O9B?G#y!sv;;kWS7KCWh<|LpGU(bb16d#Rr;Jg8ffF z0&BNl4{pE5F`Xj&EXP8$p`9=hRFqq(MZ#3TYY~$kaNkSL3_)sclEez4`!%vWiupA8 zVGG$jfX+i}?^^H#{2+N`B5&}EaVQtFuzW?K?<-&K`aWQ+$)g^KtY{!Wdk9i#dU-OwOu|Wbu9Bs`dL$tf14HIdV9f zB}@OExT;wIIZgzHx5@xuEE7OoU*s8d#*M7==zN1|E;rQI$6YOn`esEv_F8~3lc*0Y zX>0FjK`;}qtqZYmEb8<5d|h2#T@1r8m%Q|@7=3kha%^p2#$zhnfN9OB&{*VxiHj!A_ndymz`|tnp z&mVo}*f(bv@~3LmU2R>G062O)?Y!XtK$gm$FtZG)o&wH zF>A5e2sXu&snU3wG|d3)tZ0h`08oiwbo>nH?~yfWF=GupeOw}u zXnciEm9jG`+LBkU;o;%oYjaW%I%zrMc^K#7-F-)84UQnQE6y04qnT3;kuyT69%{Bv##?}k!Z^~K_awo%tW@=kr#hS4B=cp z84`&WkVNSsoSHGv($oQ^;$i7MJGS2b!oEX~42~vWIP-S1^Vy*%o_y|+P{4Obw4sBw z-25wvD-2`1CYv^Z=Ik{F^%%ijFf~6;_WfwIix>hj9P1cDp~jwQ(Se6zAq(i)U^n=p z%Lnxhy)ZF!7zPjTgWffpffJ~tjB0x^;;&=rRw4-)J#_%ahYkYA`aoB4!mkhtDbI^! znm>N(ICQRDMT$nYD#nWO1|ibW1~X$PVP<>)qOmSAb&@16*{A)1dPvTk2BlPlKsW{+ zOSh4I9d)d8<0CL~{2(mMjDo2(k!wuySYS^biHK~5h1oHI=lJzrkLT{`>A#;kH8QjJ zod5w!Wu+hpJZ~F1TI?;JO!=xY9Fu}(gf?wjj0xMUm!+|OEY;H!*&9yc=$#3uO=EWL zqzK#32OQ}DM?Qy)ELmW{Tfd+!F9AArTx9b`&N%LZF#_uvJ(kN7+O? zIUlF~#6OC#f2^2j+?TQGC(VDcY)$q}!%5>ZDWJT#W;Sf6 zX>u;G0@0dUX9Vp7a2Uwq^YEMnESi+z%UX{)Gj$5)=7#YbMnmH=wp=WMR8}3&6}#?~ zaQ|S?Yvv>f9x@P3E>2fALU)=lbuT%H^=>8w<-GA&iGxPac-B??fE&wn+ zml>F!PfmwJkp?9{2P`XF6C+I{2fxW0i{|>4!zd6srfuNIiL66muXL^q)gM}PKSM78 z!w4`xz85qlN1A^iz5oRX#rwe%YIY{n6*E4H?Gkf40~nlwKvlDAg8-)8PqR)lVLcQF zjEEB+86-Ij7#EK~Kp{0k3R9&pM%V$OTu*fR2F*Ig0*gL%m8AhaWX_!0hQiWu=eL`1qiXWWunuql4(+XCQ0OQK=pkoRMm!Z@fE=4fCGrcZ6B_Jy&(hY} z<~h!D5`>i};EU|iJS+R!-uvh?2mkp(ABvrA?VXFgBPzMp#0NkWUvZ!L`T2RIQ2N_? zL)$Og{GOK&oqVje-JJg=iM)5?>fZPM=^uUYf7V6)EvPNWW~;SlJ^AyEE%*DUK__qk8W|M0#0AN<R!=`>rTw5b7$K{-(1Yj^7_M2E*31uXf$9ZlO==DH&J$l)YH`b z1ZmjgO-spcB1mph@c9CDAbWj~nw^C4lP93QxeYM-$z&=tBuVx|G~NaIObW{RlfW7Q za0R`jVXupKfu@xqo1TS{ll!5ey&b~wxb@nIR6!@jpVwCpd0(1%0qE*+V(2KjWOBXW zL?3Tc$fn5aK|@19Z~-rg;0r1sd&i(u$blI$hXx!%wI`G5G% z=l}NGw~tTFAAP%j=X6&lzj!Ax@%A<<>_!hG2q94hnSJx` zD^mrIvQ=Oa>%>T#ivvCzSp=7!+P4}akL zzqsR$58d3*xdzQK+rjx|9Kc7hXPj|IW)d z{b7B5OM_BQf*feIC^szU!~-$a?(9_?DpEsLRV5pZ71?H1ZcBCa7LA<+rI3O`c>(lt zj%xim;5ZLNn^uF%Tff+mnxQm!rb3A)2qpyrY*qo$ts4}wch~@I)!|UlegQS@a|fEi z<&8lpHw}f<5TTY8v!_AS${@-yYab*OC;Q>pMc{`8MB9fBb*cpxlcDmSDm3RsKmo%#h&KC*>BnMfJOK*8G66JMY7%G~Rjdf6s`2Nlq8$H!_TB^9vg<4p z{P&4B=a*B}tDK~gN~LI7$+nDxFvd1E3=P=e9t;C?dm1-0YkCbctX|X8*fb487#7`h z55YhiyM-}e%a)TI6ib!!%kk!XPu#QqefB=*+^4Eis(O-(ch-8U(yRAwI_K>D|KI-w z67mC}0o9Uyh>EB6B{K7YklY@d+Nr7>!F=``INg*onRF0X+XtRdwh3LSEyD<*KRN;NOez3P2|zkGiYAc&RE6ex z7qW#(2GXFDKT@>^hPH$0RN(ya@4_vKhar|o2d1pt6CjftW1zw6!g=OBp-0Bq<6}|* zGCoiefDK%Ba2#wlU?q^uMh#9zMw;FXRW-0;8Tybg@Q
      9DiO)&(y@thtuwpvXOeMkaB^Z~ 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%0D9rY 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%0D0dT{|Jhpmb5fLzIOp{1A9ts_yB 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�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%0Dl}g=x=WTDg^L1DL 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%0DPaeY15`n82SIVaQ>eQ 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 z

      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
      K!8TQz03M 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 SvV! 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 z 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�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
      T^hPN(~r~ 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
      %k0tdfU+E6{HK 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

      lLc*VW&hH-Pz(lHbyxat z2>`}7ZC$sWR)3p;{;gC4;IxfQ$p)c*ws{$DV3r1JoU!c%0A5AAJyQus6#!PlL5Fgp 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 Uxxx))r~m)}07*qoM6N<$g3`$CmH+?% literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.json b/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.json new file mode 100644 index 000000000..1a7eebab0 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.json @@ -0,0 +1,3758 @@ +{ +"skeleton": { + "hash": "FsTlpSGjt5g", + "spine": "4.2.22", + "x": -755, + "y": -556.02, + "width": 1332, + "height": 2365.02, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root" }, + { "name": "cloud", "parent": "root", "y": 1580, "color": "91aaebff", "icon": "circle" }, + { "name": "swing-top", "parent": "cloud", "length": 1040.94, "rotation": -90, "y": 4.09, "color": "afc1eeff" }, + { "name": "swing-bottom", "parent": "swing-top", "length": 520.47, "x": 1040.94, "color": "afc1eeff" }, + { + "name": "bench-front", + "parent": "swing-bottom", + "rotation": 90, + "x": 528.6, + "y": -170.65, + "color": "afc1eeff", + "icon": "diamond" + }, + { "name": "bench-back", "parent": "bench-front", "x": 314.34, "y": 66.88, "color": "34497dff", "icon": "diamond" }, + { + "name": "rope-front", + "parent": "swing-top", + "rotation": 90, + "x": 215.22, + "y": -172.32, + "color": "afc1eeff", + "icon": "diamond" + }, + { + "name": "rope-back", + "parent": "swing-top", + "rotation": 90, + "x": 153.36, + "y": 157.07, + "color": "34497dff", + "icon": "diamond" + }, + { "name": "body-bottom", "parent": "bench-front", "x": 172.22, "y": 170.54, "color": "ff9b1aff", "icon": "diamondB" }, + { + "name": "body-down", + "parent": "body-bottom", + "length": 144.53, + "rotation": 90, + "x": 1.67, + "y": 3.34, + "color": "ff9b1aff" + }, + { "name": "body-up", "parent": "body-down", "length": 222.38, "x": 142.12, "y": -0.84, "color": "ff9b1aff" }, + { + "name": "leg-back", + "parent": "body-bottom", + "length": 337.6, + "rotation": -43.22, + "x": 81.18, + "y": 17, + "color": "1540beff" + }, + { "name": "leg-back-down", "parent": "leg-back", "length": 393.2, "rotation": -28.55, "x": 337.6, "color": "1540beff" }, + { "name": "foot-back", "parent": "leg-back-down", "length": 136.87, "rotation": 1.38, "x": 393.2, "color": "1540beff" }, + { + "name": "leg-front", + "parent": "body-bottom", + "length": 325.03, + "rotation": -28.9, + "x": -50.72, + "y": -36.36, + "color": "d10606ff" + }, + { "name": "leg-front-down", "parent": "leg-front", "length": 407.97, "rotation": -44.64, "x": 325.03, "color": "d10606ff" }, + { "name": "foot-front", "parent": "leg-front-down", "length": 174.76, "rotation": 23.03, "x": 407.97, "color": "d10606ff" }, + { + "name": "chest-control", + "parent": "body-up", + "rotation": -0.22, + "x": 135.95, + "y": -81.51, + "color": "ff9b1aff", + "icon": "arrows" + }, + { "name": "neck", "parent": "body-up", "length": 98.45, "x": 296.95, "y": 23.58, "color": "ff9b1aff" }, + { + "name": "jabot", + "parent": "body-up", + "length": 86.81, + "rotation": -167.47, + "x": 284.11, + "y": -5.52, + "color": "ff9b1aff" + }, + { "name": "face", "parent": "neck", "length": 254.23, "x": 95.02, "y": 10.27, "color": "ff9b1aff" }, + { "name": "face-control", "parent": "face", "x": 25.68, "y": -99.3, "color": "ff9b1aff", "icon": "arrowsB" }, + { "name": "face-inverse", "parent": "face", "x": 135.25, "y": 152.37, "color": "ff9b1aff", "icon": "warning" }, + { + "name": "hat-front", + "parent": "face", + "length": 88.84, + "rotation": 25.08, + "x": 216.57, + "y": 39.38, + "color": "ffe719ff" + }, + { + "name": "feathers-front", + "parent": "hat-front", + "length": 125.88, + "rotation": -23.52, + "x": 19.98, + "y": -76.45, + "color": "ffe719ff" + }, + { "name": "feathers-front-top", "parent": "feathers-front", "length": 120.64, "rotation": 46.61, "x": 125.88, "color": "ffe719ff" }, + { + "name": "hair-back", + "parent": "face-inverse", + "length": 468.65, + "rotation": 180, + "x": -6.39, + "y": -102.85, + "color": "561d8ea9" + }, + { "name": "hair-back-down", "parent": "hair-back", "length": 234.32, "x": 468.65, "color": "561d8ea9" }, + { "name": "face-holder", "parent": "face", "x": 59.16, "y": -82.67, "color": "ff9b1aff", "icon": "square" }, + { + "name": "fringe-side-front", + "parent": "face-holder", + "length": 214.4, + "rotation": 180, + "x": 111.88, + "y": 110.79, + "color": "c181e8ff" + }, + { + "name": "fringe-side-back", + "parent": "face-holder", + "length": 221.68, + "rotation": 180, + "x": 106.6, + "y": -43.08, + "color": "9f19ffff" + }, + { "name": "arm-front-up-holder", "parent": "body-up", "x": 237.74, "y": 145.38, "color": "ff1919ff", "icon": "arrowsB" }, + { "name": "arm-front-up", "parent": "arm-front-up-holder", "length": 223.61, "rotation": 155.09, "x": 0.6, "color": "ff1919ff" }, + { "name": "arm-back-up-holder", "parent": "body-up", "x": 263.54, "y": -112.02, "color": "19b2ffff", "icon": "warning" }, + { "name": "arm-back-up", "parent": "arm-back-up-holder", "length": 231.75, "rotation": -155.69, "color": "19b2ffff" }, + { + "name": "wing-front", + "parent": "body-down", + "length": 441.84, + "rotation": 51.84, + "x": 184.85, + "y": 60.03, + "color": "19ffb2ff" + }, + { "name": "wing-front-tip", "parent": "wing-front", "length": 401.17, "rotation": 10.15, "x": 441.84, "color": "19ffb2ff" }, + { + "name": "wing-back", + "parent": "body-down", + "length": 187.48, + "rotation": -37.42, + "x": 188.23, + "y": -9.9, + "color": "0fab73ff" + }, + { "name": "wing-back-tip", "parent": "wing-back", "length": 414.74, "rotation": 15.88, "x": 187.48, "color": "0fab73ff" }, + { + "name": "sock-bow", + "parent": "leg-front-down", + "length": 48.74, + "rotation": -14.1, + "x": 258.61, + "y": -45.08, + "color": "d10606ff" + }, + { + "name": "skirt-back", + "parent": "bench-front", + "length": 282.06, + "rotation": -105.78, + "x": -169.75, + "y": 31.39, + "color": "abe323ff" + }, + { + "name": "skirt-front", + "parent": "bench-back", + "length": 243.95, + "rotation": -62.03, + "x": 191.48, + "y": 67.98, + "color": "00842eff" + }, + { "name": "underskirt-back", "parent": "skirt-back", "x": 294.81, "y": 0.61, "color": "abe323ff" }, + { "name": "underskirt-front", "parent": "skirt-front", "x": 249.28, "y": -0.54, "color": "00842eff" }, + { "name": "mouth", "parent": "face-holder", "x": -71.7, "y": 11.81, "color": "ff9b1aff", "icon": "mouth" }, + { "name": "eye-white-front", "parent": "face-holder", "x": 2, "y": 55.83, "color": "fff019ff", "icon": "eye" }, + { "name": "pupil-front", "parent": "eye-white-front", "x": 2.39, "y": -1.65, "color": "fff019ff", "icon": "star" }, + { + "name": "eyelashes-top-front", + "parent": "eye-white-front", + "rotation": -5.82, + "x": 23.09, + "y": -5.15, + "color": "fff019ff", + "icon": "arrowLeftRight" + }, + { "name": "eyelashes-down-front", "parent": "eye-white-front", "x": -19.83, "y": 8.85, "color": "fff019ff", "icon": "arrowLeftRight" }, + { "name": "eye-white-back", "parent": "face-holder", "x": -0.34, "y": -36.94, "color": "c99d19ff", "icon": "eye" }, + { "name": "pupil-back", "parent": "eye-white-back", "x": 2.17, "y": -1.08, "color": "c99d19ff", "icon": "star" }, + { "name": "eyelashes-top-back", "parent": "eye-white-back", "x": 17.02, "y": -2.38, "color": "c99d19ff", "icon": "arrowLeftRight" }, + { "name": "eyelashes-down-back", "parent": "eye-white-back", "x": -17.56, "y": -0.43, "color": "c99d19ff", "icon": "arrowLeftRight" }, + { "name": "star1", "parent": "cloud", "x": -244.61, "y": 44.37, "color": "ffe12fff", "icon": "star" }, + { "name": "star2", "parent": "cloud", "x": 161.71, "y": 44.37, "color": "ffe12fff", "icon": "star" }, + { "name": "star3", "parent": "cloud", "x": -120.79, "y": -83.12, "color": "ffe12fff", "icon": "star" }, + { "name": "star4", "parent": "cloud", "x": 19.54, "y": 117.75, "color": "ffe12fff", "icon": "star" }, + { "name": "star5", "parent": "cloud", "x": -216.18, "y": -117.05, "color": "ffe12fff", "icon": "star" }, + { "name": "star6", "parent": "cloud", "x": 204.82, "y": -110.63, "color": "ffe12fff", "icon": "star" }, + { "name": "cloud-perspective", "parent": "cloud", "y": 25.92, "color": "d9e2faff", "icon": "arrowsB" } +], +"slots": [ + { "name": "underskirt-back", "bone": "body-bottom", "attachment": "underskirt-back" }, + { "name": "wing-back", "bone": "wing-back", "attachment": "wing-back" }, + { "name": "wing-front", "bone": "wing-front", "attachment": "wing-front" }, + { "name": "hat/feathers-back", "bone": "feathers-front", "attachment": "feathers-back" }, + { "name": "hat/feathers-front", "bone": "feathers-front", "attachment": "feathers-front" }, + { "name": "hat/hat-back", "bone": "hat-front", "attachment": "hat-back" }, + { "name": "hat/hat-front", "bone": "hat-front", "attachment": "hat-front" }, + { "name": "bench", "bone": "bench-front", "attachment": "bench" }, + { "name": "head-back", "bone": "face", "attachment": "head-back" }, + { "name": "hair-back/hair-back-6", "bone": "hair-back", "attachment": "hair-back-6" }, + { "name": "hair-back/hair-back-5", "bone": "hair-back", "attachment": "hair-back-5" }, + { "name": "hair-back/hair-back-4", "bone": "hair-back", "attachment": "hair-back-4" }, + { "name": "hair-back/hair-back-3", "bone": "hair-back", "attachment": "hair-back-3" }, + { "name": "hair-back/hair-back-2", "bone": "hair-back", "attachment": "hair-back-2" }, + { "name": "hair-back/hair-back-1", "bone": "hair-back", "attachment": "hair-back-1" }, + { "name": "arm-back-up", "bone": "arm-back-up-holder", "attachment": "arm-back-up" }, + { "name": "arm-back-down", "bone": "arm-back-up", "attachment": "arm-back-down" }, + { "name": "cloud-back", "bone": "cloud", "attachment": "cloud-back" }, + { "name": "rope-back", "bone": "rope-back", "attachment": "rope-back" }, + { "name": "body-bottom", "bone": "body-down", "attachment": "body-bottom" }, + { "name": "leg-back", "bone": "leg-back", "attachment": "leg-back" }, + { "name": "leg-front", "bone": "leg-front", "attachment": "leg-front" }, + { "name": "sock-bow", "bone": "sock-bow", "attachment": "sock-bow" }, + { "name": "body-top", "bone": "body-up", "attachment": "body-top" }, + { "name": "chest", "bone": "body-up", "attachment": "chest" }, + { "name": "arm-front-up", "bone": "arm-front-up", "attachment": "arm-front-up" }, + { "name": "neck", "bone": "neck", "attachment": "neck" }, + { "name": "collar", "bone": "body-up", "attachment": "collar" }, + { "name": "jabot", "bone": "jabot", "attachment": "jabot" }, + { "name": "logo-brooch", "bone": "body-up", "attachment": "logo-brooch" }, + { "name": "face/fringe-side-back", "bone": "fringe-side-back", "attachment": "fringe-side-back" }, + { "name": "face/face", "bone": "face", "attachment": "face" }, + { "name": "face/ear", "bone": "face", "attachment": "ear" }, + { "name": "face/eye-white-back", "bone": "eye-white-back", "attachment": "eye-white-back" }, + { "name": "face/eye-white-front", "bone": "eye-white-front", "attachment": "eye-white-front" }, + { "name": "face/nose", "bone": "face-holder", "attachment": "nose", "blend": "multiply" }, + { "name": "face/mouth", "bone": "mouth", "attachment": "mouth", "blend": "multiply" }, + { "name": "face/eyelashes-down-back", "bone": "eyelashes-down-back", "attachment": "eyelashes-down-back", "blend": "multiply" }, + { "name": "face/eyelashes-down-front", "bone": "eyelashes-down-front", "attachment": "eyelashes-down-front" }, + { "name": "face/pupil-back", "bone": "pupil-back", "attachment": "pupil-back" }, + { "name": "face/eye-reflex-back", "bone": "pupil-back", "attachment": "eye-reflex-back" }, + { "name": "face/pupil-front", "bone": "pupil-front", "attachment": "pupil-front" }, + { "name": "face/eye-reflex-front", "bone": "pupil-front", "attachment": "eye-reflex-front" }, + { "name": "face/eyelashes-top-back", "bone": "eyelashes-top-back", "attachment": "eyelashes-top-back", "blend": "multiply" }, + { "name": "face/eyelashes-top-front", "bone": "eyelashes-top-front", "attachment": "eyelashes-top-front" }, + { "name": "face/eye-front-shadow", "bone": "eye-white-front", "attachment": "eye-front-shadow", "blend": "multiply" }, + { "name": "face/eye-back-shadow", "bone": "eye-white-back", "attachment": "eye-back-shadow", "blend": "multiply" }, + { "name": "face/nose-shadow", "bone": "face-holder", "attachment": "nose-shadow", "blend": "multiply" }, + { "name": "face/nose-highlight", "bone": "face-holder", "attachment": "nose-highlight" }, + { "name": "face/fringe-front/fringe-middle-back", "bone": "face", "attachment": "fringe-middle-back" }, + { "name": "face/fringe-front/fringe-middle-front", "bone": "face", "attachment": "fringe-middle-front" }, + { "name": "face/fringe-front/fringe-side-front", "bone": "fringe-side-front", "attachment": "fringe-side-front" }, + { "name": "face/hair-hat-shadow", "bone": "face", "attachment": "hair-hat-shadow", "blend": "multiply" }, + { "name": "underskirt", "bone": "underskirt-back", "attachment": "underskirt" }, + { "name": "skirt", "bone": "skirt-front", "attachment": "skirt" }, + { "name": "spine-logo-body", "bone": "body-up", "attachment": "spine-logo-body" }, + { "name": "arm-front-down", "bone": "arm-front-up", "attachment": "arm-front-down" }, + { "name": "rope-front", "bone": "rope-front", "attachment": "rope-front" }, + { "name": "rope-front-bottom", "bone": "bench-front", "attachment": "rope-front-bottom" }, + { "name": "glove-bottom-back", "bone": "bench-back", "attachment": "glove-bottom-back" }, + { "name": "hand-back", "bone": "bench-back", "attachment": "hand-back" }, + { "name": "glove-bottom-front", "bone": "bench-front", "attachment": "glove-bottom-front" }, + { "name": "hand-front", "bone": "bench-front", "attachment": "hand-front" }, + { "name": "cloud-front", "bone": "cloud", "attachment": "cloud-front" }, + { "name": "stars/star1", "bone": "star1" }, + { "name": "stars/star2", "bone": "star2" }, + { "name": "stars/star3", "bone": "star3" }, + { "name": "stars/star4", "bone": "star4" }, + { "name": "stars/star5", "bone": "star5" }, + { "name": "stars/star6", "bone": "star6" } +], +"transform": [ + { + "name": "girl/face-control", + "order": 9, + "bones": [ "face-holder" ], + "target": "face-control", + "x": 33.48, + "y": 16.63, + "mixRotate": 0, + "mixX": 0.8, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "girl/head-control", + "order": 8, + "bones": [ "face-inverse" ], + "target": "face-control", + "x": 109.57, + "y": 251.66, + "mixRotate": 0, + "mixX": -0.5, + "mixScaleX": 0, + "mixShearY": 0 + }, + { + "name": "girl/shoulders-perspective", + "order": 6, + "bones": [ "arm-back-up-holder" ], + "target": "arm-front-up-holder", + "x": 25.8, + "y": -257.4, + "mixRotate": 0, + "mixX": -1, + "mixScaleX": 0, + "mixShearY": 0 + } +], +"physics": [ + { + "name": "bench-back", + "order": 31, + "bone": "bench-back", + "x": 0.4949, + "y": 0.4579, + "limit": 1500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "bench-front", + "order": 2, + "bone": "bench-front", + "x": 0.1279, + "y": 0.2256, + "inertia": 0.4071, + "strength": 81.4, + "damping": 0.792 + }, + { + "name": "cloud-perspective", + "order": 32, + "bone": "cloud-perspective", + "x": 1, + "y": 1, + "limit": 500, + "inertia": 0.25, + "damping": 0.85, + "windGlobal": true + }, + { "name": "swing-bottom", "order": 1, "bone": "swing-bottom", "rotate": 1, "inertia": 0.5, "damping": 0.85 }, + { "name": "swing-top", "bone": "swing-top", "rotate": 1, "limit": 7000, "inertia": 0.5, "damping": 0.85 }, + { + "name": "girl/hair/fringe-side-back", + "order": 26, + "bone": "fringe-side-back", + "rotate": 1, + "scaleX": 0.6033, + "limit": 1500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "girl/hair/fringe-side-front", + "order": 25, + "bone": "fringe-side-front", + "rotate": 1, + "scaleX": 0.6033, + "limit": 1500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "girl/hair/hair-back", + "order": 23, + "bone": "hair-back", + "rotate": 1, + "limit": 1500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "girl/hair/hair-back-down", + "order": 24, + "bone": "hair-back-down", + "x": 1, + "y": 1, + "rotate": 1, + "scaleX": 0.3641, + "limit": 1500, + "inertia": 0.7345, + "damping": 0.8142, + "windGlobal": true + }, + { + "name": "girl/legs/foot-back", + "order": 22, + "bone": "foot-back", + "rotate": 1, + "limit": 1500, + "inertia": 0.1593, + "damping": 0.85 + }, + { + "name": "girl/legs/foot-front", + "order": 20, + "bone": "foot-front", + "rotate": 1, + "limit": 1500, + "inertia": 0.1593, + "damping": 0.85 + }, + { + "name": "girl/legs/leg-back-down", + "order": 21, + "bone": "leg-back-down", + "rotate": 1, + "limit": 1500, + "inertia": 0.8496, + "damping": 0.85 + }, + { + "name": "girl/legs/leg-front-down", + "order": 18, + "bone": "leg-front-down", + "rotate": 1, + "limit": 1500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "girl/legs/sock-bow", + "order": 19, + "bone": "sock-bow", + "rotate": 1, + "limit": 1500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "girl/skirt/skirt-back", + "order": 27, + "bone": "skirt-back", + "rotate": 1, + "limit": 1500, + "inertia": 0.3805, + "strength": 113.3, + "damping": 0.8982, + "mass": 2.27 + }, + { + "name": "girl/skirt/skirt-front", + "order": 29, + "bone": "skirt-front", + "rotate": 1, + "limit": 1500, + "inertia": 0.3805, + "strength": 113.3, + "damping": 0.8982, + "mass": 2.27 + }, + { + "name": "girl/skirt/underskirt-back", + "order": 28, + "bone": "underskirt-back", + "x": 0.3737, + "y": 0.3737, + "limit": 100, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.85, + "windGlobal": true + }, + { + "name": "girl/skirt/underskirt-front", + "order": 30, + "bone": "underskirt-front", + "x": 0.3737, + "y": 0.3737, + "limit": 100, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.85, + "windGlobal": true + }, + { + "name": "girl/wings/wing-back", + "order": 16, + "bone": "wing-back", + "rotate": 0.4105, + "shearX": 0.1602, + "limit": 1600, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.85 + }, + { + "name": "girl/wings/wing-back-tip", + "order": 17, + "bone": "wing-back-tip", + "rotate": 1, + "limit": 1600, + "inertia": 0.5, + "damping": 0.85, + "windGlobal": true + }, + { + "name": "girl/wings/wing-front", + "order": 14, + "bone": "wing-front", + "rotate": 0.4105, + "shearX": 0.1602, + "limit": 1600, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.85 + }, + { + "name": "girl/wings/wing-front-tip", + "order": 15, + "bone": "wing-front-tip", + "rotate": 1, + "limit": 1600, + "inertia": 0.5, + "damping": 0.85, + "windGlobal": true + }, + { + "name": "girl/arm-front-up-holder", + "order": 5, + "bone": "arm-front-up-holder", + "x": 0.6522, + "y": 0.1359, + "limit": 500, + "inertia": 0.5, + "damping": 0.85 + }, + { + "name": "girl/body-down", + "order": 3, + "bone": "body-down", + "rotate": 1, + "limit": 1500, + "inertia": 0.1195, + "damping": 0.85 + }, + { + "name": "girl/body-up", + "order": 4, + "bone": "body-up", + "rotate": 0.3098, + "limit": 1500, + "inertia": 0.2257, + "damping": 0.85 + }, + { + "name": "girl/chest-control", + "order": 11, + "bone": "chest-control", + "x": 1, + "y": 1, + "limit": 500, + "inertia": 0.354, + "strength": 146.9, + "damping": 0.8938, + "mass": 2 + }, + { + "name": "girl/face-control", + "order": 7, + "bone": "face-control", + "x": 0.5, + "y": 0.5, + "limit": 1500, + "inertia": 0.1372, + "strength": 138.9, + "damping": 0.6372 + }, + { + "name": "girl/feathers-front", + "order": 10, + "bone": "feathers-front", + "rotate": 1, + "limit": 1500, + "inertia": 0.5, + "strength": 48.8, + "damping": 0.85 + }, + { + "name": "girl/feathers-front-top", + "order": 13, + "bone": "feathers-front-top", + "rotate": 1, + "limit": 1500, + "inertia": 0.5, + "strength": 48.8, + "damping": 0.85 + }, + { + "name": "girl/jabot", + "order": 12, + "bone": "jabot", + "rotate": 1, + "scaleX": 0.7011, + "limit": 1500, + "inertia": 0.2566, + "damping": 0.7965, + "mass": 1.36, + "windGlobal": true + } +], +"skins": [ + { + "name": "default", + "attachments": { + "arm-back-down": { + "arm-back-down": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 0.62552, 0, 1, 0, 0.30019, 0.75582, 0.67336, 0.80436 ], + "triangles": [ 5, 2, 3, 6, 3, 4, 0, 6, 4, 5, 1, 2, 1, 5, 6, 0, 1, 6, 5, 3, 6 ], + "vertices": [ 1, 34, 266.05, 30.04, 1, 1, 34, 226.94, -56.53, 1, 2, 5, 14.31, 488.57, 0.7907, 7, 0.93, -860.73, 0.2093, 2, 5, 73.73, 488.57, 0.7907, 7, 60.36, -860.73, 0.2093, 2, 5, 109.31, 488.57, 0.7907, 7, 95.93, -860.73, 0.2093, 2, 34, 192.84, -9.84, 0.7879, 5, 42.83, 332.87, 0.2121, 2, 34, 216.55, 18.35, 0.7879, 5, 78.28, 322.87, 0.2121 ], + "hull": 5, + "edges": [ 0, 2, 2, 4, 0, 8, 4, 6, 6, 8 ], + "width": 95, + "height": 206 + } + }, + "arm-back-up": { + "arm-back-up": { "x": -86.1, "y": -20.9, "rotation": -90, "width": 208, "height": 290 } + }, + "arm-front-down": { + "arm-front-down": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 0.43452, 0, 0.67692, 0, 1, 0, 0.31332, 0.74613, 0.71731, 0.75077 ], + "triangles": [ 1, 6, 0, 6, 7, 0, 6, 3, 7, 6, 1, 2, 0, 7, 5, 3, 4, 7, 7, 4, 5, 6, 2, 3 ], + "vertices": [ 1, 32, 227.27, 54.07, 1, 1, 32, 265.18, -27.55, 1, 2, 4, -107.35, 521.45, 0.6047, 6, -105.68, -832.87, 0.3953, 2, 4, -68.25, 521.45, 0.6047, 6, -66.58, -832.87, 0.3953, 2, 4, -46.43, 521.45, 0.6047, 6, -44.76, -832.87, 0.3953, 2, 4, -17.35, 521.45, 0.6047, 6, -15.68, -832.87, 0.3953, 3, 4, -79.16, 375.21, 0.15283, 32, 208.17, -22.94, 0.81603, 6, -77.48, -979.11, 0.03115, 3, 4, -42.8, 374.3, 0.2334, 32, 193.68, 10.42, 0.71976, 6, -41.12, -980.02, 0.04684 ], + "hull": 6, + "edges": [ 0, 2, 4, 6, 6, 8, 8, 10, 2, 4, 10, 0 ], + "width": 90, + "height": 196 + } + }, + "arm-front-up": { + "arm-front-up": { "x": 83.58, "y": 4.97, "rotation": 114.91, "width": 192, "height": 290 } + }, + "bench": { + "bench": { "x": 149.15, "y": 26.95, "width": 473, "height": 119 } + }, + "body-bottom": { + "body-bottom": { "x": 0.06, "y": -1.26, "rotation": -90, "width": 385, "height": 311 } + }, + "body-top": { + "body-top": { + "type": "mesh", + "uvs": [ 0.68503, 0.0173, 0.77124, 0.03199, 0.91531, 0.05656, 1, 0.43324, 1, 0.67192, 0.92419, 1, 0.7759, 1, 0.42918, 0.97744, 0.26456, 0.96673, 0.14336, 0.62093, 0, 0.2119, 0, 0.18595, 0.14242, 0.01727, 0.31495, 0.00606, 0.38463, 0.55715, 0.30121, 0.21217, 0.9283, 0.59001, 0.92255, 0.42573 ], + "triangles": [ 17, 1, 2, 3, 17, 2, 6, 16, 4, 16, 6, 14, 16, 14, 17, 16, 3, 4, 1, 17, 0, 0, 17, 15, 16, 17, 3, 0, 15, 13, 5, 6, 4, 8, 14, 7, 14, 6, 7, 8, 9, 14, 9, 15, 14, 9, 10, 15, 17, 14, 15, 15, 11, 12, 15, 12, 13, 15, 10, 11 ], + "vertices": [ 2, 10, 305.7, -37.39, 0.67811, 33, 42.16, 74.63, 0.32189, 2, 10, 300.82, -64.63, 0.4046, 33, 37.28, 47.39, 0.5954, 1, 33, 29.13, 1.86, 1, 2, 10, 167.61, -136.92, 0.7252, 33, -95.93, -24.9, 0.2748, 2, 10, 88.36, -136.92, 0.7252, 33, -175.17, -24.9, 0.2748, 1, 9, 121.56, -113.8, 1, 2, 31, -258.3, -211.49, 0.2636, 9, 121.56, -66.94, 0.7364, 2, 31, -250.81, -101.92, 0.3876, 9, 129.05, 42.62, 0.6124, 1, 9, 132.61, 94.64, 1, 2, 31, -132.44, -11.6, 0.458, 10, 105.29, 133.78, 0.542, 1, 31, 3.35, 33.7, 1, 1, 31, 11.97, 33.7, 1, 2, 31, 67.97, -11.31, 0.68, 10, 305.71, 134.07, 0.32, 1, 10, 309.43, 79.55, 1, 2, 31, -111.27, -87.84, 0.8168, 10, 126.47, 57.54, 0.1832, 1, 31, 3.26, -61.48, 1, 2, 10, 115.56, -114.26, 0.9535, 33, -147.98, -2.25, 0.0465, 2, 10, 170.1, -112.45, 0.7252, 33, -93.44, -0.43, 0.2748 ], + "hull": 14, + "edges": [ 4, 6, 6, 8, 8, 10, 10, 12, 20, 22, 22, 24, 16, 18, 18, 20, 12, 14, 14, 16, 2, 4, 24, 26, 0, 2, 26, 0 ], + "width": 316, + "height": 332 + } + }, + "chest": { + "chest": { + "type": "mesh", + "uvs": [ 0.45001, 0, 0.57525, 0.0237, 0.76703, 0.22276, 0.97238, 0.4359, 1, 0.66542, 1, 0.81592, 0.7799, 0.99414, 0.13228, 0.99919, 0, 0.20603, 0, 0.12601, 0.18781, 0, 0.34662, 0.79353, 0.63746, 0.78251, 0.85889, 0.71271, 0.61432, 0.54004, 0.49204, 0.35267, 0.31357, 0.55841, 0.81262, 0.47023, 0.23094, 0.33063, 0.3334, 0.8964, 0.65398, 0.89272, 0.87211, 0.81925, 0.17806, 0.67229 ], + "triangles": [ 20, 19, 11, 7, 19, 6, 16, 18, 15, 19, 22, 11, 8, 10, 18, 8, 9, 10, 7, 8, 22, 22, 8, 18, 7, 22, 19, 22, 18, 16, 22, 16, 11, 11, 16, 14, 20, 11, 12, 16, 15, 14, 11, 14, 12, 13, 17, 4, 18, 10, 0, 15, 0, 1, 15, 1, 2, 18, 0, 15, 17, 2, 3, 14, 15, 2, 17, 14, 2, 13, 4, 5, 21, 13, 5, 6, 20, 21, 6, 21, 5, 19, 20, 6, 17, 3, 4, 12, 14, 13, 12, 13, 21, 20, 12, 21, 14, 17, 13 ], + "vertices": [ 1, 10, 306.44, -25.48, 1, 2, 33, 37.38, 54.11, 0.1756, 10, 300.92, -57.91, 0.8244, 2, 33, -9, 4.44, 0.1756, 10, 254.54, -107.58, 0.8244, 3, 17, 69.23, -79, 0.20371, 33, -58.66, -48.75, 0.4198, 10, 204.88, -160.77, 0.37649, 3, 17, 15.78, -86.35, 0.14356, 33, -112.14, -55.9, 0.3282, 10, 151.4, -167.92, 0.52824, 2, 33, -147.21, -55.9, 0.3282, 10, 116.33, -167.92, 0.6718, 1, 10, 74.81, -110.91, 1, 2, 10, 73.63, 56.82, 0.1679, 31, -164.11, -88.56, 0.8321, 2, 10, 258.44, 91.08, 0.1679, 31, 20.7, -54.3, 0.8321, 2, 10, 277.08, 91.08, 0.1679, 31, 39.34, -54.3, 0.8321, 2, 10, 306.44, 42.44, 0.313, 31, 68.7, -102.94, 0.687, 3, 17, -14.71, 82.76, 0.21816, 10, 121.55, 1.3, 0.09484, 31, -116.19, -144.08, 0.687, 3, 17, -11.86, 7.45, 0.41027, 10, 124.12, -74.02, 0.26153, 31, -113.62, -219.4, 0.3282, 3, 17, 4.62, -49.85, 0.49165, 33, -123.16, -19.36, 0.1527, 10, 140.38, -131.38, 0.35565, 3, 17, 44.61, 13.65, 0.41027, 10, 180.61, -68.03, 0.26153, 31, -57.12, -213.41, 0.3282, 3, 17, 88.15, 45.49, 0.30258, 10, 224.27, -36.36, 0.36922, 31, -13.47, -181.74, 0.3282, 3, 17, 40.04, 91.53, 0.21816, 10, 176.33, 9.86, 0.09484, 31, -61.4, -135.52, 0.687, 3, 17, 61.07, -37.65, 0.486, 33, -66.66, -7.37, 0.1527, 10, 196.88, -119.39, 0.3613, 3, 17, 93.03, 113.13, 0.14098, 10, 229.41, 31.26, 0.17202, 31, -8.33, -114.12, 0.687, 3, 17, -38.69, 86.1, 0.18636, 10, 97.58, 4.73, 0.12664, 31, -140.16, -140.65, 0.687, 3, 17, -37.52, 3.07, 0.34873, 10, 98.44, -78.3, 0.32307, 31, -139.3, -223.68, 0.3282, 3, 17, -20.19, -53.36, 0.42304, 33, -147.98, -22.78, 0.1603, 10, 115.56, -134.8, 0.41666, 3, 17, 13.37, 126.52, 0.17681, 10, 149.8, 44.96, 0.13619, 31, -87.94, -100.42, 0.687 ], + "hull": 11, + "edges": [ 0, 20, 0, 2, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 2, 4, 4, 6 ], + "width": 259, + "height": 233 + } + }, + "cloud-back": { + "cloud-back": { "x": 34, "y": -35, "width": 504, "height": 412 } + }, + "cloud-front": { + "cloud-front": { + "type": "mesh", + "uvs": [ 0.31327, 1, 0, 0.6177, 0, 0.42025, 0.19412, 0.14966, 0.35888, 0, 0.74282, 0, 1, 0.29836, 1, 0.56651, 0.88846, 0.97605, 0.41478, 0.80054, 0.21765, 0.47631, 0.33975, 0.22279, 0.54864, 0.12772, 0.6678, 0.17403, 0.81785, 0.30323, 0.77666, 0.58114, 0.62747, 0.67312, 0.44331, 0.66744, 0.36329, 0.40562, 0.50892, 0.29396, 0.70487, 0.40205, 0.82079, 0.74203, 0.8914, 0.43487 ], + "triangles": [ 8, 16, 21, 21, 16, 15, 9, 16, 8, 9, 17, 16, 9, 10, 17, 17, 10, 18, 21, 15, 22, 17, 19, 16, 16, 19, 20, 16, 20, 15, 13, 19, 12, 19, 13, 20, 17, 18, 19, 15, 14, 22, 15, 20, 14, 10, 11, 18, 18, 11, 19, 20, 13, 14, 19, 11, 12, 8, 0, 9, 1, 10, 0, 0, 10, 9, 8, 21, 7, 21, 22, 7, 1, 2, 10, 22, 6, 7, 2, 3, 10, 10, 3, 11, 22, 14, 6, 13, 5, 14, 14, 5, 6, 11, 4, 12, 11, 3, 4, 13, 12, 5, 12, 4, 5 ], + "vertices": [ 1, 1, -190.62, -261, 1, 1, 1, -445, -73.68, 1, 1, 1, -445, 23.08, 1, 1, 1, -287.38, 155.67, 1, 1, 1, -153.59, 229, 1, 1, 1, 158.17, 229, 1, 1, 1, 367, 82.8, 1, 1, 1, 367, -48.59, 1, 1, 1, 276.43, -249.27, 1, 2, 1, -108.2, -163.26, 0.2626, 59, -108.2, -189.18, 0.7374, 2, 1, -268.27, -4.39, 0.2626, 59, -268.27, -30.31, 0.7374, 2, 1, -169.12, 119.83, 0.2626, 59, -169.12, 93.92, 0.7374, 2, 1, 0.5, 166.42, 0.2626, 59, 0.5, 140.5, 0.7374, 2, 1, 97.25, 143.72, 0.2626, 59, 97.25, 117.81, 0.7374, 2, 1, 219.09, 80.42, 0.2626, 59, 219.09, 54.5, 0.7374, 1, 59, 185.64, -81.67, 1, 1, 59, 64.51, -126.75, 1, 1, 59, -85.03, -123.96, 1, 1, 59, -150.01, 4.33, 1, 1, 59, -31.75, 59.04, 1, 1, 59, 127.35, 6.08, 1, 2, 1, 221.48, -134.59, 0.2626, 59, 221.48, -160.51, 0.7374, 2, 1, 278.82, 15.91, 0.2626, 59, 278.82, -10, 0.7374 ], + "hull": 9, + "edges": [ 2, 4, 6, 8, 8, 10, 12, 14, 14, 16, 4, 6, 0, 2, 16, 0, 10, 12 ], + "width": 812, + "height": 490 + } + }, + "collar": { + "collar": { "x": 318.94, "y": 22.08, "rotation": -90, "width": 118, "height": 65 } + }, + "glove-bottom-back": { + "glove-bottom-back": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 7, 127.93, -931.73, 0.1628, 5, 141.31, 417.57, 0.8372, 2, 7, -0.07, -931.73, 0.1628, 5, 13.31, 417.57, 0.8372, 2, 7, -0.07, -829.73, 0.1628, 5, 13.31, 519.57, 0.8372, 2, 7, 127.93, -829.73, 0.1628, 5, 141.31, 519.57, 0.8372 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 128, + "height": 102 + } + }, + "glove-bottom-front": { + "glove-bottom-front": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 6, 9.32, -909.87, 0.3023, 4, 7.65, 444.45, 0.6977, 2, 6, -108.68, -909.87, 0.3023, 4, -110.35, 444.45, 0.6977, 2, 6, -108.68, -788.87, 0.3023, 4, -110.35, 565.45, 0.6977, 2, 6, 9.32, -788.87, 0.3023, 4, 7.65, 565.45, 0.6977 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 118, + "height": 121 + } + }, + "hand-back": { + "hand-back": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 7, 101.93, -888.73, 0.1628, 5, 115.31, 460.57, 0.8372, 2, 7, -47.07, -888.73, 0.1628, 5, -33.69, 460.57, 0.8372, 2, 7, -47.07, -771.73, 0.1628, 5, -33.69, 577.57, 0.8372, 2, 7, 101.93, -771.73, 0.1628, 5, 115.31, 577.57, 0.8372 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 149, + "height": 117 + } + }, + "hand-front": { + "hand-front": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 6, 43.32, -868.87, 0.3023, 4, 41.65, 485.45, 0.6977, 2, 6, -89.68, -868.87, 0.3023, 4, -91.35, 485.45, 0.6977, 2, 6, -89.68, -718.87, 0.3023, 4, -91.35, 635.45, 0.6977, 2, 6, 43.32, -718.87, 0.3023, 4, 41.65, 635.45, 0.6977 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 133, + "height": 150 + } + }, + "head-back": { + "head-back": { "x": 143.48, "y": -6.28, "rotation": -90, "width": 255, "height": 216 } + }, + "jabot": { + "jabot": { + "type": "mesh", + "uvs": [ 0, 0.00242, 0.68427, 0.0674, 0.78113, 0.19093, 0.92461, 0.37391, 1, 0.47007, 1, 0.77668, 0.68139, 0.9938, 0.25297, 0.99999, 0, 0.59156, 0.10822, 0.43911, 0.20325, 0.30524, 1.0E-5, 0.15397, 0.29926, 0.57598, 0.67862, 0.52015, 0.47435, 0.25963 ], + "triangles": [ 12, 13, 6, 7, 8, 12, 7, 12, 6, 13, 3, 4, 5, 13, 4, 6, 13, 5, 12, 8, 9, 12, 14, 13, 13, 2, 3, 9, 10, 12, 0, 10, 11, 1, 14, 0, 14, 10, 0, 2, 14, 1, 2, 13, 14, 12, 10, 14 ], + "vertices": [ 1, 10, 323.11, 83.08, 1, 1, 10, 314.14, -37.35, 1, 1, 10, 297.09, -54.4, 1, 2, 10, 271.84, -79.65, 0.3511, 19, 28.05, 69.71, 0.6489, 3, 10, 258.57, -92.92, 0.22821, 19, 43.89, 79.78, 0.57989, 17, 122.67, -10.95, 0.1919, 3, 10, 216.26, -92.92, 0.14314, 19, 85.19, 70.6, 0.50336, 17, 80.35, -11.11, 0.3535, 3, 19, 102.27, 9.36, 0.37012, 17, 50.18, 44.86, 0.20238, 31, -51.44, -182.23, 0.4275, 3, 19, 86.75, -64.43, 0.3751, 17, 49.04, 120.25, 0.2051, 31, -52.29, -106.82, 0.4198, 4, 10, 241.81, 83.08, 0.10381, 19, 22.07, -95.66, 0.36505, 17, 105.24, 164.99, 0.11134, 31, 4.07, -62.3, 0.4198, 2, 10, 262.84, 64.03, 0.3511, 19, 5.67, -72.51, 0.6489, 1, 10, 281.32, 47.31, 1, 1, 10, 302.19, 83.08, 1, 4, 10, 243.96, 30.41, 0.03577, 19, 31.4, -43.78, 0.43309, 17, 107.59, 112.33, 0.11134, 31, 6.22, -114.97, 0.4198, 4, 10, 251.66, -36.36, 0.0353, 19, 38.36, 23.07, 0.42734, 17, 115.54, 45.59, 0.10986, 31, 13.92, -181.74, 0.4275, 1, 10, 287.61, -0.41, 1 ], + "hull": 12, + "edges": [ 0, 22, 0, 2, 8, 10, 10, 12, 12, 14, 14, 16, 20, 22, 2, 4, 4, 6, 6, 8, 16, 18, 18, 20 ], + "width": 176, + "height": 138 + } + }, + "leg-back": { + "leg-back": { + "type": "mesh", + "uvs": [ 0.32178, 1.0E-5, 0.65435, 0.2781, 0.68868, 0.31943, 0.70599, 0.34212, 0.72097, 0.37811, 0.74825, 0.44366, 0.81512, 0.57229, 0.88933, 0.74052, 0.91935, 0.79172, 0.93814, 0.82344, 1, 0.92792, 1, 0.99738, 0.92956, 1, 0.89693, 1, 0.74794, 0.8868, 0.75056, 0.80978, 0.74352, 0.76967, 0.58619, 0.589, 0.53314, 0.47715, 0.51888, 0.42426, 0.49157, 0.38949, 0.38189, 0.33429, 0.00221, 0.25355, 0, 0, 0.61105, 0.38965, 0.82789, 0.78577, 0.84871, 0.8316, 0.67341, 0.63766 ], + "triangles": [ 10, 26, 9, 26, 10, 14, 10, 12, 13, 13, 14, 10, 11, 12, 10, 18, 19, 24, 5, 17, 18, 24, 4, 5, 5, 18, 24, 17, 5, 6, 27, 17, 6, 27, 6, 7, 16, 27, 7, 17, 27, 16, 25, 16, 7, 25, 7, 8, 15, 16, 25, 26, 25, 8, 26, 8, 9, 15, 25, 26, 14, 15, 26, 4, 24, 3, 3, 24, 2, 22, 23, 0, 21, 22, 0, 1, 21, 0, 20, 21, 1, 24, 20, 1, 2, 24, 1, 19, 20, 24 ], + "vertices": [ 1, 11, 6.11, 129.11, 1, 2, 11, 291.73, 79.64, 0.99946, 12, -78.35, 48.04, 5.4E-4, 2, 11, 328.42, 66.88, 0.80865, 12, -40.02, 54.36, 0.19135, 2, 11, 347.98, 59.31, 0.57491, 12, -19.23, 57.06, 0.42509, 2, 11, 374.22, 42.84, 0.29825, 12, 11.7, 55.13, 0.70175, 1, 12, 68.04, 51.63, 1, 1, 12, 180.76, 51.39, 1, 1, 12, 326.03, 44.49, 1, 2, 12, 371.46, 46.09, 0.83005, 13, -20.62, 46.6, 0.16995, 2, 12, 399.64, 47.17, 0.63671, 13, 7.58, 47, 0.36329, 1, 13, 100.44, 48.33, 1, 1, 13, 154.94, 28.9, 1, 1, 13, 144.61, -6.6, 1, 1, 13, 138.87, -22.71, 1, 2, 12, 418.59, -64, 0.15021, 13, 23.84, -64.6, 0.84979, 2, 12, 358.08, -42.62, 0.88261, 13, -36.14, -41.76, 0.11739, 1, 12, 325.19, -35.68, 1, 1, 12, 156.46, -66.9, 1, 2, 11, 359, -84.68, 0.05891, 12, 59.27, -64.15, 0.94109, 2, 11, 323.39, -57.69, 0.38892, 12, 15.09, -57.47, 0.61108, 2, 11, 293.12, -46.39, 0.86698, 12, -16.9, -62, 0.13302, 1, 11, 219.75, -52.23, 1, 1, 11, 28.71, -139.47, 1, 1, 11, -116.77, 13.65, 1, 1, 11, 338.83, -3.61, 1, 1, 12, 351.76, 2.12, 1, 2, 12, 391.43, 0.53, 0.59072, 13, -1.75, 0.58, 0.40928, 1, 12, 209.26, -36.17, 1 ], + "hull": 24, + "edges": [ 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 40, 42, 42, 44, 44, 46, 38, 40, 0, 2, 2, 4, 34, 36, 36, 38, 8, 10, 14, 16, 10, 12, 12, 14, 46, 0, 16, 18, 18, 20, 4, 6, 6, 8 ], + "width": 524, + "height": 833 + } + }, + "leg-front": { + "leg-front": { + "type": "mesh", + "uvs": [ 0.2969, 2.9E-4, 0.42768, 0.05548, 0.59878, 0.15796, 0.6729, 0.22265, 0.68354, 0.26066, 0.69232, 0.29199, 0.6999, 0.31906, 0.70297, 0.35118, 0.7066, 0.38928, 0.71781, 0.50659, 0.74604, 0.58144, 0.79461, 0.71079, 0.82243, 0.74694, 0.84954, 0.78219, 0.87827, 0.81953, 0.93986, 0.89147, 0.96913, 0.90818, 1, 0.95735, 1, 1, 0.95733, 1, 0.84902, 0.98418, 0.74245, 0.97522, 0.69287, 0.89751, 0.70858, 0.8364, 0.71574, 0.80857, 0.70333, 0.77999, 0.54961, 0.5917, 0.50703, 0.39889, 0.46896, 0.33342, 0.29427, 0.28929, 0.2526, 0.31853, 1.0E-5, 0.27849, 0, 0, 0.60991, 0.31513, 0.78952, 0.80682, 0.79263, 0.83757, 0.84003, 0.80682 ], + "triangles": [ 13, 36, 34, 36, 13, 14, 35, 34, 36, 24, 34, 35, 23, 24, 35, 35, 22, 23, 21, 22, 35, 14, 35, 36, 15, 35, 14, 15, 20, 35, 21, 35, 20, 16, 20, 15, 19, 16, 17, 19, 20, 16, 18, 19, 17, 13, 34, 12, 33, 4, 5, 33, 5, 6, 26, 27, 8, 33, 7, 27, 6, 7, 33, 7, 8, 27, 9, 26, 8, 10, 26, 9, 25, 10, 11, 25, 11, 12, 26, 10, 25, 34, 25, 12, 24, 25, 34, 31, 32, 0, 29, 31, 0, 29, 0, 1, 28, 29, 1, 33, 2, 3, 33, 3, 4, 2, 28, 1, 30, 31, 29, 33, 28, 2, 27, 28, 33 ], + "vertices": [ 1, 14, 26.69, 123.29, 1, 1, 14, 121.98, 125.47, 1, 1, 14, 258.37, 107.11, 1, 2, 14, 325.3, 84.95, 0.7863, 15, -59.49, 60.64, 0.2137, 2, 14, 346.02, 61.65, 0.62278, 15, -28.38, 58.62, 0.37722, 2, 14, 363.09, 42.45, 0.37112, 15, -2.74, 56.95, 0.62888, 2, 14, 377.85, 25.86, 0.15366, 15, 19.42, 55.51, 0.84634, 2, 14, 392, 4.32, 0.08338, 15, 44.62, 50.13, 0.91662, 1, 15, 74.52, 43.75, 1, 1, 15, 166.57, 24.1, 1, 1, 15, 229.17, 24.62, 1, 1, 15, 337.29, 25.39, 1, 2, 15, 370.13, 34.43, 0.6412, 16, -21.35, 46.49, 0.3588, 2, 15, 402.13, 43.24, 0.49447, 16, 11.55, 42.08, 0.50553, 2, 15, 436.04, 52.57, 0.04576, 16, 46.4, 37.4, 0.95424, 2, 15, 502.5, 74.42, 0, 16, 116.12, 31.5, 1, 2, 15, 520.68, 88.77, 0, 16, 138.46, 37.59, 1, 2, 15, 564.06, 96.75, 0, 16, 181.5, 27.96, 1, 2, 15, 596.79, 87.08, 0, 16, 207.84, 6.25, 1, 1, 16, 190.3, -15.01, 1, 1, 16, 136.03, -60.96, 1, 2, 15, 530.63, -66.86, 0, 16, 86.72, -109.53, 1, 2, 15, 461.92, -79.96, 0.03259, 16, 18.37, -94.7, 0.96741, 2, 15, 417.92, -56.38, 0.32661, 16, -12.9, -55.78, 0.67339, 2, 15, 397.88, -45.63, 0.7066, 16, -27.14, -38.05, 0.2934, 2, 15, 373.68, -46.84, 0.97283, 16, -49.88, -29.69, 0.02717, 1, 15, 201.08, -99.4, 1, 2, 14, 299.64, -90.27, 0.24722, 15, 45.36, -82.07, 0.75278, 2, 14, 252.8, -56.31, 0.90138, 15, -11.83, -90.82, 0.09862, 1, 14, 136.94, -79.94, 1, 1, 14, 124.68, -113.43, 1, 1, 14, -33.65, -164.25, 1, 1, 14, -141.33, 30.79, 1, 2, 14, 325.44, 0.51, 0.49238, 15, -0.07, 0.65, 0.50762, 2, 15, 410.04, 0.47, 0.39999, 16, 2.09, -0.38, 0.60001, 1, 16, 22.35, -14.47, 1, 2, 15, 419.29, 31.76, 0.19906, 16, 22.85, 24.8, 0.80094 ], + "hull": 33, + "edges": [ 2, 4, 4, 6, 18, 20, 30, 32, 32, 34, 34, 36, 38, 40, 42, 44, 48, 50, 50, 52, 58, 60, 62, 64, 64, 0, 60, 62, 0, 2, 56, 58, 52, 54, 16, 18, 26, 28, 44, 46, 46, 48, 22, 24, 24, 26, 20, 22, 28, 30, 36, 38, 40, 42, 54, 56, 10, 12, 6, 8, 8, 10, 12, 14, 14, 16 ], + "width": 646, + "height": 800 + } + }, + "logo-brooch": { + "logo-brooch": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 10, 246.44, -26.92, 0.7273, 17, 110.29, 55.01, 0.2727, 2, 10, 246.44, 13.08, 0.7273, 17, 110.14, 95.01, 0.2727, 1, 10, 308.44, 13.08, 1, 1, 10, 308.44, -26.92, 1 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 40, + "height": 62 + } + }, + "neck": { + "neck": { "x": 64, "y": -0.01, "rotation": -90, "width": 97, "height": 141 } + }, + "rope-back": { + "rope-back": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0.95833, 0, 0.91667, 0, 0.875, 0, 0.83333, 0, 0.79167, 0, 0.75, 0, 0.70833, 0, 0.66667, 0, 0.625, 0, 0.58333, 0, 0.54167, 0, 0.5, 0, 0.45833, 0, 0.41667, 0, 0.375, 0, 0.33333, 0, 0.29167, 0, 0.25, 0, 0.20833, 0, 0.16667, 0, 0.125, 0, 0.08333, 0, 0.04167, 0, 0, 1, 0, 1, 0.04167, 1, 0.08333, 1, 0.125, 1, 0.16667, 1, 0.20833, 1, 0.25, 1, 0.29167, 1, 0.33333, 1, 0.375, 1, 0.41667, 1, 0.45833, 1, 0.5, 1, 0.54167, 1, 0.58333, 1, 0.625, 1, 0.66667, 1, 0.70833, 1, 0.75, 1, 0.79167, 1, 0.83333, 1, 0.875, 1, 0.91667, 1, 0.95833 ], + "triangles": [ 38, 13, 37, 12, 13, 38, 39, 12, 38, 11, 12, 39, 40, 11, 39, 10, 11, 40, 41, 10, 40, 9, 10, 41, 42, 9, 41, 8, 9, 42, 43, 8, 42, 7, 8, 43, 44, 7, 43, 6, 7, 44, 45, 6, 44, 5, 6, 45, 46, 5, 45, 4, 5, 46, 47, 4, 46, 3, 4, 47, 48, 3, 47, 2, 3, 48, 49, 2, 48, 1, 2, 49, 0, 1, 49, 24, 25, 26, 27, 24, 26, 23, 24, 27, 28, 23, 27, 22, 23, 28, 29, 22, 28, 21, 22, 29, 30, 21, 29, 20, 21, 30, 31, 20, 30, 19, 20, 31, 32, 19, 31, 18, 19, 32, 33, 18, 32, 17, 18, 33, 34, 17, 33, 16, 17, 34, 35, 16, 34, 15, 16, 35, 36, 15, 35, 14, 15, 36, 37, 14, 36, 13, 14, 37 ], + "vertices": [ 2, 7, 15.93, -1218.87, 0.06239, 5, 29.31, 130.43, 0.93761, 2, 7, -9.07, -1218.87, 0.06239, 5, 4.31, 130.43, 0.93761, 2, 7, -9.07, -1167.62, 0.06783, 5, 4.31, 181.68, 0.93217, 2, 7, -9.07, -1116.37, 0.07874, 5, 4.31, 232.93, 0.92126, 2, 7, -9.07, -1065.12, 0.0952, 5, 4.31, 284.18, 0.9048, 2, 7, -9.07, -1013.87, 0.11728, 5, 4.31, 335.43, 0.88272, 2, 7, -9.07, -962.62, 0.14499, 5, 4.31, 386.68, 0.85501, 2, 7, -9.07, -911.37, 0.17827, 5, 4.31, 437.93, 0.82173, 2, 7, -9.07, -860.12, 0.21693, 5, 4.31, 489.18, 0.78307, 2, 7, -9.07, -808.87, 0.2606, 5, 4.31, 540.43, 0.73939, 2, 7, -9.07, -757.62, 0.30875, 5, 4.31, 591.68, 0.69125, 2, 7, -9.07, -706.37, 0.36064, 5, 4.31, 642.93, 0.63936, 2, 7, -9.07, -655.12, 0.41536, 5, 4.31, 694.18, 0.58464, 2, 7, -9.07, -603.87, 0.4719, 5, 4.31, 745.43, 0.5281, 2, 7, -9.07, -552.62, 0.52914, 5, 4.31, 796.68, 0.47086, 2, 7, -9.07, -501.37, 0.58596, 5, 4.31, 847.93, 0.41404, 2, 7, -9.07, -450.12, 0.64132, 5, 4.31, 899.18, 0.35868, 2, 7, -9.07, -398.87, 0.69428, 5, 4.31, 950.43, 0.30572, 2, 7, -9.07, -347.62, 0.74413, 5, 4.31, 1001.68, 0.25586, 2, 7, -9.07, -296.37, 0.7904, 5, 4.31, 1052.93, 0.2096, 2, 7, -9.07, -245.12, 0.83286, 5, 4.31, 1104.18, 0.16714, 2, 7, -9.07, -193.87, 0.87161, 5, 4.31, 1155.43, 0.12839, 2, 7, -9.07, -142.62, 0.90701, 5, 4.31, 1206.68, 0.09299, 2, 7, -9.07, -91.37, 0.93965, 5, 4.31, 1257.93, 0.06036, 2, 7, -9.07, -40.12, 0.97033, 5, 4.31, 1309.18, 0.02967, 1, 7, -9.07, 11.13, 1, 1, 7, 15.93, 11.13, 1, 2, 7, 15.93, -40.12, 0.97033, 5, 29.31, 1309.18, 0.02967, 2, 7, 15.93, -91.37, 0.93965, 5, 29.31, 1257.93, 0.06036, 2, 7, 15.93, -142.62, 0.90701, 5, 29.31, 1206.68, 0.09299, 2, 7, 15.93, -193.87, 0.87161, 5, 29.31, 1155.43, 0.12839, 2, 7, 15.93, -245.12, 0.83286, 5, 29.31, 1104.18, 0.16714, 2, 7, 15.93, -296.37, 0.7904, 5, 29.31, 1052.93, 0.2096, 2, 7, 15.93, -347.62, 0.74413, 5, 29.31, 1001.68, 0.25586, 2, 7, 15.93, -398.87, 0.69428, 5, 29.31, 950.43, 0.30572, 2, 7, 15.93, -450.12, 0.64132, 5, 29.31, 899.18, 0.35868, 2, 7, 15.93, -501.37, 0.58596, 5, 29.31, 847.93, 0.41404, 2, 7, 15.93, -552.62, 0.52914, 5, 29.31, 796.68, 0.47086, 2, 7, 15.93, -603.87, 0.4719, 5, 29.31, 745.43, 0.5281, 2, 7, 15.93, -655.12, 0.41536, 5, 29.31, 694.18, 0.58464, 2, 7, 15.93, -706.37, 0.36064, 5, 29.31, 642.93, 0.63936, 2, 7, 15.93, -757.62, 0.30875, 5, 29.31, 591.68, 0.69125, 2, 7, 15.93, -808.87, 0.2606, 5, 29.31, 540.43, 0.73939, 2, 7, 15.93, -860.12, 0.21693, 5, 29.31, 489.18, 0.78307, 2, 7, 15.93, -911.37, 0.17827, 5, 29.31, 437.93, 0.82173, 2, 7, 15.93, -962.62, 0.14499, 5, 29.31, 386.68, 0.85501, 2, 7, 15.93, -1013.87, 0.11728, 5, 29.31, 335.43, 0.88272, 2, 7, 15.93, -1065.12, 0.0952, 5, 29.31, 284.18, 0.9048, 2, 7, 15.93, -1116.37, 0.07874, 5, 29.31, 232.93, 0.92126, 2, 7, 15.93, -1167.62, 0.06783, 5, 29.31, 181.68, 0.93217 ], + "hull": 50, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 84, 84, 86, 86, 88, 88, 90, 90, 92, 92, 94, 94, 96, 96, 98, 98, 0 ], + "width": 25, + "height": 1230 + } + }, + "rope-front": { + "rope-front": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0.95833, 0, 0.91667, 0, 0.875, 0, 0.83333, 0, 0.79167, 0, 0.75, 0, 0.70833, 0, 0.66667, 0, 0.625, 0, 0.58333, 0, 0.54167, 0, 0.5, 0, 0.45833, 0, 0.41667, 0, 0.375, 0, 0.33333, 0, 0.29167, 0, 0.25, 0, 0.20833, 0, 0.16667, 0, 0.125, 0, 0.08333, 0, 0.04167, 0, 0, 1, 0, 1, 0.04167, 1, 0.08333, 1, 0.125, 1, 0.16667, 1, 0.20833, 1, 0.25, 1, 0.29167, 1, 0.33333, 1, 0.375, 1, 0.41667, 1, 0.45833, 1, 0.5, 1, 0.54167, 1, 0.58333, 1, 0.625, 1, 0.66667, 1, 0.70833, 1, 0.75, 1, 0.79167, 1, 0.83333, 1, 0.875, 1, 0.91667, 1, 0.95833 ], + "triangles": [ 0, 1, 49, 1, 2, 49, 49, 2, 48, 2, 3, 48, 48, 3, 47, 3, 4, 47, 47, 4, 46, 4, 5, 46, 46, 5, 45, 5, 6, 45, 45, 6, 44, 6, 7, 44, 44, 7, 43, 7, 8, 43, 43, 8, 42, 8, 9, 42, 42, 9, 41, 9, 10, 41, 41, 10, 40, 10, 11, 40, 40, 11, 39, 11, 12, 39, 39, 12, 38, 12, 13, 38, 38, 13, 37, 13, 14, 37, 37, 14, 36, 14, 15, 36, 36, 15, 35, 15, 16, 35, 35, 16, 34, 16, 17, 34, 34, 17, 33, 17, 18, 33, 33, 18, 32, 18, 19, 32, 32, 19, 31, 19, 20, 31, 31, 20, 30, 20, 21, 30, 30, 21, 29, 21, 22, 29, 29, 22, 28, 22, 23, 28, 28, 23, 27, 23, 24, 27, 27, 24, 26, 24, 25, 26 ], + "vertices": [ 2, 6, 15.32, -1218.87, 0.01425, 4, 13.65, 135.45, 0.98575, 2, 6, -9.68, -1218.87, 0.01425, 4, -11.35, 135.45, 0.98575, 2, 6, -9.68, -1167.62, 0.03549, 4, -11.35, 186.7, 0.96451, 2, 6, -9.68, -1116.37, 0.05791, 4, -11.35, 237.95, 0.94209, 2, 6, -9.68, -1065.12, 0.08257, 4, -11.35, 289.2, 0.91743, 2, 6, -9.68, -1013.87, 0.11037, 4, -11.35, 340.45, 0.88963, 2, 6, -9.68, -962.62, 0.142, 4, -11.35, 391.7, 0.858, 2, 6, -9.68, -911.37, 0.17784, 4, -11.35, 442.95, 0.82216, 2, 6, -9.68, -860.12, 0.21806, 4, -11.35, 494.2, 0.78194, 2, 6, -9.68, -808.87, 0.26251, 4, -11.35, 545.45, 0.73749, 2, 6, -9.68, -757.62, 0.31083, 4, -11.35, 596.7, 0.68917, 2, 6, -9.68, -706.37, 0.36243, 4, -11.35, 647.95, 0.63757, 2, 6, -9.68, -655.12, 0.41654, 4, -11.35, 699.2, 0.58346, 2, 6, -9.68, -603.87, 0.47225, 4, -11.35, 750.45, 0.52776, 2, 6, -9.68, -552.62, 0.52855, 4, -11.35, 801.7, 0.47145, 2, 6, -9.68, -501.37, 0.58444, 4, -11.35, 852.95, 0.41556, 2, 6, -9.68, -450.12, 0.63896, 4, -11.35, 904.2, 0.36104, 2, 6, -9.68, -398.87, 0.69127, 4, -11.35, 955.45, 0.30873, 2, 6, -9.68, -347.62, 0.74069, 4, -11.35, 1006.7, 0.25931, 2, 6, -9.68, -296.37, 0.78679, 4, -11.35, 1057.95, 0.21321, 2, 6, -9.68, -245.12, 0.82936, 4, -11.35, 1109.2, 0.17064, 2, 6, -9.68, -193.87, 0.86847, 4, -11.35, 1160.45, 0.13153, 2, 6, -9.68, -142.62, 0.90445, 4, -11.35, 1211.7, 0.09555, 2, 6, -9.68, -91.37, 0.93784, 4, -11.35, 1262.95, 0.06216, 2, 6, -9.68, -40.12, 0.9694, 4, -11.35, 1314.2, 0.0306, 1, 6, -9.68, 11.13, 1, 1, 6, 15.32, 11.13, 1, 2, 6, 15.32, -40.12, 0.9694, 4, 13.65, 1314.2, 0.0306, 2, 6, 15.32, -91.37, 0.93784, 4, 13.65, 1262.95, 0.06216, 2, 6, 15.32, -142.62, 0.90445, 4, 13.65, 1211.7, 0.09555, 2, 6, 15.32, -193.87, 0.86847, 4, 13.65, 1160.45, 0.13153, 2, 6, 15.32, -245.12, 0.82936, 4, 13.65, 1109.2, 0.17064, 2, 6, 15.32, -296.37, 0.78679, 4, 13.65, 1057.95, 0.21321, 2, 6, 15.32, -347.62, 0.74069, 4, 13.65, 1006.7, 0.25931, 2, 6, 15.32, -398.87, 0.69127, 4, 13.65, 955.45, 0.30873, 2, 6, 15.32, -450.12, 0.63896, 4, 13.65, 904.2, 0.36104, 2, 6, 15.32, -501.37, 0.58444, 4, 13.65, 852.95, 0.41556, 2, 6, 15.32, -552.62, 0.52855, 4, 13.65, 801.7, 0.47145, 2, 6, 15.32, -603.87, 0.47225, 4, 13.65, 750.45, 0.52776, 2, 6, 15.32, -655.12, 0.41654, 4, 13.65, 699.2, 0.58346, 2, 6, 15.32, -706.37, 0.36243, 4, 13.65, 647.95, 0.63757, 2, 6, 15.32, -757.62, 0.31083, 4, 13.65, 596.7, 0.68917, 2, 6, 15.32, -808.87, 0.26251, 4, 13.65, 545.45, 0.73749, 2, 6, 15.32, -860.12, 0.21806, 4, 13.65, 494.2, 0.78194, 2, 6, 15.32, -911.37, 0.17784, 4, 13.65, 442.95, 0.82216, 2, 6, 15.32, -962.62, 0.142, 4, 13.65, 391.7, 0.858, 2, 6, 15.32, -1013.87, 0.11037, 4, 13.65, 340.45, 0.88963, 2, 6, 15.32, -1065.12, 0.08257, 4, 13.65, 289.2, 0.91743, 2, 6, 15.32, -1116.37, 0.05791, 4, 13.65, 237.95, 0.94209, 2, 6, 15.32, -1167.62, 0.03549, 4, 13.65, 186.7, 0.96451 ], + "hull": 50, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 64, 66, 66, 68, 68, 70, 70, 72, 72, 74, 74, 76, 76, 78, 78, 80, 80, 82, 82, 84, 84, 86, 86, 88, 88, 90, 90, 92, 92, 94, 94, 96, 96, 98, 98, 0 ], + "width": 25, + "height": 1230 + } + }, + "rope-front-bottom": { + "rope-front-bottom": { "x": 6.65, "y": 90.45, "width": 106, "height": 162 } + }, + "skirt": { + "skirt": { + "type": "mesh", + "uvs": [ 0.46879, 0.00497, 0.6193, 0.00865, 0.73168, 0.0729, 0.79086, 0.14366, 0.84028, 0.20275, 0.88824, 0.26009, 0.94354, 0.36305, 0.99934, 0.46693, 0.99902, 0.53745, 0.95967, 0.62431, 0.73749, 0.83501, 0.67118, 0.86255, 0.64669, 0.83712, 0.63777, 0.79457, 0.54456, 0.88007, 0.41826, 0.85692, 0.33176, 0.67054, 0.38298, 0.45193, 0.32025, 0.393, 0.25971, 0.50948, 0.25592, 0.54358, 0.29136, 0.69557, 0.26023, 0.76971, 0.23714, 0.78393, 0.24583, 0.96708, 0.21631, 1, 0.18626, 1, 0.13297, 0.98375, 0.0482, 0.9579, 0, 0.74426, 0, 0.71238, 0.02405, 0.63249, 0.05524, 0.52888, 0.08731, 0.42235, 0.14673, 0.31698, 0.23977, 0.15198, 0.37537, 0.00268, 0.78833, 0.34934, 0.65072, 0.38132, 0.57259, 0.40578, 0.43328, 0.39355, 0.25324, 0.41895, 0.07649, 0.66731, 0.10759, 0.5469, 0.14767, 0.71528, 0.16981, 0.55631, 0.17312, 0.35376, 0.82186, 0.47041, 0.69302, 0.54288, 0.59275, 0.58024 ], + "triangles": [ 21, 23, 20, 17, 40, 15, 16, 17, 15, 23, 45, 20, 20, 45, 19, 45, 46, 41, 19, 45, 41, 19, 41, 18, 17, 18, 40, 18, 41, 35, 18, 36, 40, 41, 46, 35, 11, 12, 13, 10, 47, 9, 10, 48, 47, 47, 6, 9, 8, 9, 7, 48, 37, 47, 7, 9, 6, 47, 5, 6, 47, 37, 5, 37, 4, 5, 37, 3, 4, 10, 11, 13, 25, 26, 24, 24, 26, 23, 26, 27, 23, 27, 44, 23, 27, 28, 44, 28, 29, 42, 28, 42, 44, 31, 42, 30, 23, 21, 22, 23, 44, 45, 42, 29, 30, 42, 43, 44, 44, 43, 45, 31, 32, 42, 42, 32, 43, 45, 43, 46, 32, 33, 43, 46, 33, 34, 46, 43, 33, 46, 34, 35, 13, 48, 10, 37, 38, 3, 14, 15, 49, 49, 40, 39, 39, 1, 38, 1, 39, 0, 39, 40, 0, 40, 36, 0, 18, 35, 36, 38, 1, 2, 3, 38, 2, 49, 39, 38, 49, 38, 48, 48, 38, 37, 14, 49, 13, 13, 49, 48, 40, 49, 15 ], + "vertices": [ 2, 9, 138.5, 15.05, 0.4884, 31, -241.35, -129.5, 0.5116, 1, 9, 136.23, -150.36, 1, 3, 9, 96.66, -273.87, 0.814, 40, -398.02, 529.23, 0, 41, -147.06, 12.37, 0.186, 3, 9, 53.07, -338.91, 0.59714, 40, -373.76, 603.67, 0, 41, -78.06, 49.37, 0.40286, 3, 9, 16.67, -393.22, 0.41605, 40, -353.5, 665.83, 0, 41, -20.44, 80.26, 0.58395, 2, 9, -18.65, -445.93, 0.2403, 41, 35.48, 110.24, 0.7597, 2, 9, -82.08, -506.71, 0.2093, 41, 120, 134.17, 0.7907, 1, 41, 205.28, 158.32, 1, 2, 9, -189.51, -567.68, 0.04571, 41, 243.48, 137.63, 0.95429, 2, 9, -243.01, -524.44, 0.18, 41, 270.45, 74.34, 0.82, 2, 9, -372.8, -280.26, 0.54183, 41, 270.54, -202.19, 0.45817, 2, 9, -389.77, -207.39, 0.4651, 41, 251.35, -274.5, 0.5349, 2, 9, -374.1, -180.47, 0.4651, 41, 224.88, -290.93, 0.5349, 2, 9, -347.89, -170.66, 0.4651, 41, 197.14, -287.3, 0.5349, 3, 9, -400.56, -68.23, 0.46933, 41, 195.61, -402.46, 0.25937, 4, 242.12, -226.67, 0.2713, 4, 9, -386.3, 70.57, 0.56245, 40, 160.39, 329.06, 3.0E-5, 41, 117.91, -518.37, 0.16622, 4, 103.31, -212.42, 0.2713, 3, 40, 75.75, 206.36, 0.00607, 41, -28.08, -548.47, 0.12573, 4, 8.25, -97.6, 0.8682, 1, 4, 64.54, 37.06, 1, 1, 4, -4.4, 73.36, 1, 2, 40, 1.8, 103.19, 0.1318, 4, -70.93, 1.61, 0.8682, 1, 4, -75.1, -19.39, 1, 2, 40, 102.65, 167.82, 0.4651, 4, -36.15, -113.02, 0.5349, 2, 40, 155.91, 147.31, 0.64377, 4, -70.37, -158.69, 0.35623, 2, 40, 171.24, 125.28, 0.51563, 4, -95.74, -167.45, 0.48437, 2, 40, 277.21, 165.15, 0.77714, 4, -86.18, -280.27, 0.22286, 2, 40, 305.54, 139.44, 0.88571, 4, -118.63, -300.55, 0.11429, 2, 40, 314.52, 107.65, 0.80857, 4, -151.66, -300.55, 0.19143, 2, 40, 320.81, 48.57, 0.78571, 4, -210.22, -290.54, 0.21429, 1, 40, 330.82, -45.4, 1, 1, 40, 218.57, -132.16, 1, 1, 40, 199.67, -137.5, 1, 3, 9, -248.05, 503.81, 0.02228, 40, 145.13, -125.45, 0.95682, 4, -329.92, -74.16, 0.0209, 3, 9, -184.23, 469.54, 0.08011, 40, 74.39, -109.81, 0.86977, 4, -295.65, -10.34, 0.05012, 3, 9, -118.6, 434.29, 0.20512, 40, 1.66, -93.74, 0.70568, 4, -260.41, 55.28, 0.0892, 3, 9, -53.7, 368.99, 0.40948, 40, -78.56, -48.54, 0.4572, 4, -195.1, 120.19, 0.13332, 3, 9, 47.94, 266.73, 0.66886, 40, -204.17, 22.23, 0.15284, 4, -92.84, 221.83, 0.1783, 1, 9, 139.91, 117.71, 1, 2, 9, -73.63, -336.14, 0.3798, 41, 32.53, -12.51, 0.6202, 4, 9, -93.33, -184.9, 0.7038, 40, -191, 495.26, 0, 41, -21, -155.32, 0.24191, 31, -473.19, -329.44, 0.05429, 4, 9, -108.4, -99.03, 0.70715, 40, -153.16, 416.72, 1.1E-4, 41, -47.98, -238.22, 0.17845, 31, -488.26, -243.58, 0.11429, 2, 4, 119.82, 73.02, 0.8217, 31, -480.72, -90.48, 0.1783, 1, 4, -78.04, 57.38, 1, 2, 40, 150.1, -64.16, 0.7752, 4, -272.3, -95.61, 0.2248, 2, 40, 69.43, -51.42, 0.6899, 4, -238.11, -21.44, 0.3101, 2, 40, 157.27, 19.15, 0.7752, 4, -194.07, -125.16, 0.2248, 3, 9, -201.12, 343.62, 4.5E-4, 40, 56.42, 15.95, 0.68945, 4, -169.73, -27.24, 0.3101, 3, 9, -76.35, 339.99, 0.06162, 40, -64.64, -14.47, 0.64378, 4, -166.1, 97.53, 0.2946, 2, 9, -148.21, -372.98, 0.2403, 41, 115.68, -14.95, 0.7597, 2, 9, -192.85, -231.39, 0.5891, 41, 88.69, -160.94, 0.4109, 3, 9, -215.87, -121.19, 0.5659, 40, -55.76, 467.26, 1.0E-5, 41, 57.33, -269.06, 0.43409 ], + "hull": 37, + "edges": [ 2, 4, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 48, 48, 50, 50, 52, 56, 58, 58, 60, 70, 72, 64, 66, 60, 62, 62, 64, 52, 54, 54, 56, 66, 68, 68, 70, 86, 92, 10, 12, 12, 14, 30, 80, 2, 0, 0, 72, 4, 6, 6, 8, 8, 10 ], + "width": 1099, + "height": 616 + } + }, + "sock-bow": { + "sock-bow": { + "type": "mesh", + "uvs": [ 0.99999, 0.72, 0.75258, 0.92781, 0.22969, 1, 1.0E-5, 0.92563, 1.0E-5, 0.78642, 0.06114, 0.10062, 0.48481, 0.07, 0.87771, 1.0E-5, 0.21914, 0.65955, 0.54384, 0.47361, 0.92125, 0.55017, 0.11372, 0.57861, 0.42577, 0.77111, 0.57969, 0.72736, 0.45951, 0.1958, 0.54595, 0.17611 ], + "triangles": [ 15, 6, 7, 14, 5, 6, 9, 15, 10, 11, 14, 9, 14, 6, 15, 9, 14, 15, 15, 7, 10, 11, 5, 14, 8, 11, 9, 13, 9, 10, 12, 8, 9, 13, 12, 9, 0, 10, 7, 1, 13, 10, 11, 4, 5, 4, 11, 8, 2, 3, 4, 0, 1, 10, 2, 8, 12, 2, 4, 8, 1, 2, 12, 1, 12, 13 ], + "vertices": [ 1, 39, 34.06, 38.19, 1, 1, 39, 49.83, 16.99, 1, 1, 39, 53.81, -26.61, 1, 1, 39, 47.08, -45.41, 1, 1, 39, 35.95, -44.96, 1, 2, 39, -18.66, -37.63, 0.5344, 15, 231.35, -77.03, 0.4656, 1, 15, 238.97, -42.61, 1, 2, 39, -23.91, 30.42, 0.5344, 15, 242.84, -9.75, 0.4656, 2, 39, 26.56, -26.36, 0.5344, 15, 277.95, -77.12, 0.4656, 1, 15, 271.32, -47.06, 1, 2, 39, 20.22, 32.22, 0.5344, 15, 286.07, -18.76, 0.4656, 2, 39, 19.73, -34.84, 0.5344, 15, 269.26, -83.68, 0.4656, 2, 39, 36.18, -9.6, 0.5344, 15, 291.37, -63.2, 0.4656, 2, 39, 33.21, 3.31, 0.5344, 15, 291.63, -49.96, 0.4656, 1, 15, 248.02, -47.48, 1, 1, 15, 248.54, -40.15, 1 ], + "hull": 8, + "edges": [ 0, 14, 6, 8, 8, 10, 4, 6, 0, 2, 2, 4, 10, 12, 12, 14 ], + "width": 83, + "height": 80 + } + }, + "spine-logo-body": { + "spine-logo-body": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 0, 1, 3 ], + "vertices": [ 2, 31, -248.3, -203.3, 0.6279, 33, -274.1, 54.1, 0.3721, 2, 31, -248.3, -171.3, 0.6977, 33, -274.1, 86.1, 0.3023, 2, 31, -169.3, -171.3, 0.6977, 33, -195.1, 86.1, 0.3023, 2, 31, -169.3, -203.3, 0.6279, 33, -195.1, 54.1, 0.3721 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 32, + "height": 79 + } + }, + "underskirt": { + "underskirt": { + "type": "mesh", + "uvs": [ 0.61384, 0.00326, 0.86014, 0.1566, 1, 0.41744, 0.99999, 0.63264, 0.91366, 0.67712, 0.71449, 0.81522, 0.48265, 0.87782, 0.37222, 0.75816, 0.31568, 0.69151, 0.33041, 0.38409, 0.3203, 0.38107, 0.28115, 0.91727, 0.22206, 1, 0.13682, 0.99971, 0.05161, 0.92594, 0, 0.71479, 0, 0.68836, 0.09431, 0.39249, 0.29714, 0.10495, 0.42184, 0.00353 ], + "triangles": [ 5, 1, 4, 5, 0, 1, 3, 4, 2, 2, 4, 1, 12, 13, 11, 17, 11, 13, 16, 13, 14, 16, 14, 15, 17, 13, 16, 10, 11, 17, 6, 7, 0, 6, 0, 5, 19, 0, 9, 8, 9, 7, 0, 7, 9, 17, 18, 10, 19, 9, 18, 9, 10, 18 ], + "vertices": [ 3, 9, 59.71, -144.35, 0.82348, 42, -622.06, 414.02, 1.0E-5, 43, -424.46, -118.81, 0.17652, 2, 9, -27.7, -418.23, 0.20974, 43, -218.8, 82.08, 0.79026, 2, 9, -176.38, -573.76, 0.00244, 43, -14.54, 149.69, 0.99756, 1, 43, 93.78, 92.15, 1, 2, 9, -324.39, -477.75, 0.00233, 43, 71.15, -4.52, 0.99767, 2, 9, -403.12, -256.27, 0.35855, 43, 36.78, -237.06, 0.64145, 3, 9, -438.79, 1.54, 0.73381, 42, -102.67, 409.16, 0.0028, 43, -52.63, -481.48, 0.26339, 3, 9, -370.59, 124.33, 0.82181, 42, -134.93, 272.44, 0.02156, 43, -170.47, -557.93, 0.15663, 3, 9, -332.6, 187.21, 0.83983, 42, -154.39, 201.61, 0.03404, 43, -233.51, -595.65, 0.12614, 3, 9, -157.37, 170.82, 0.72848, 42, -327.47, 169.74, 0.2419, 43, -380.58, -498.98, 0.02962, 3, 9, -155.65, 182.06, 0.65493, 42, -326.07, 158.45, 0.32779, 43, -387.37, -508.1, 0.01728, 2, 9, -461.28, 225.6, 0.0394, 42, -20.11, 199.65, 0.9606, 2, 9, -508.44, 291.31, 0.01441, 42, 43.13, 149.23, 0.98559, 2, 9, -508.27, 386.1, 5.6E-4, 42, 68.74, 57.97, 0.99944, 1, 42, 54.04, -44.65, 1, 2, 9, -345.87, 538.24, 0.02475, 42, -46.18, -132.6, 0.97525, 2, 9, -330.8, 538.24, 0.02806, 42, -60.68, -136.69, 0.97194, 2, 9, -162.16, 433.37, 0.22852, 42, -251.48, -81.62, 0.77148, 2, 9, 1.74, 207.82, 0.78318, 42, -470.53, 90.88, 0.21682, 3, 9, 59.55, 69.15, 0.97304, 42, -563.86, 208.61, 0.02695, 43, -524.47, -307.44, 1.0E-5 ], + "hull": 20, + "edges": [ 0, 38, 0, 2, 2, 4, 4, 6, 8, 10, 10, 12, 12, 14, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 14, 16, 16, 18, 18, 20, 6, 8 ], + "width": 1112, + "height": 570 + } + }, + "underskirt-back": { + "underskirt-back": { + "type": "mesh", + "uvs": [ 0.8116, 0, 1, 0.3776, 1, 0.45388, 0.98647, 0.56624, 0.92179, 0.61762, 0.8759, 0.61039, 0.87506, 0.61851, 0.72906, 0.8252, 0.48046, 0.90197, 0.37375, 0.98138, 0.17375, 1, 0.14891, 1, 0, 0.76838, 0, 0.7307, 0.01937, 0.5828, 0.09779, 0.29851, 0.26066, 0.09077, 0.63845, 0 ], + "triangles": [ 8, 17, 7, 6, 7, 5, 7, 17, 0, 5, 7, 0, 3, 4, 2, 4, 1, 2, 5, 1, 4, 1, 5, 0, 16, 9, 10, 10, 14, 15, 14, 11, 13, 10, 11, 14, 10, 15, 16, 9, 16, 8, 11, 12, 13, 8, 16, 17 ], + "vertices": [ 2, 9, -29.44, -358.72, 0.4574, 43, -245.18, 28.7, 0.5426, 1, 43, -6.75, 133.1, 1, 1, 43, 22.09, 117.78, 1, 1, 43, 57.69, 82.29, 1, 2, 42, -372.61, 831.26, 1.1E-4, 43, 44.25, 10.1, 0.99989, 2, 42, -362.08, 782.6, 0.00633, 43, 18.21, -32.33, 0.99367, 2, 42, -358.49, 782.66, 0.00746, 43, 20.85, -34.77, 0.99254, 2, 42, -230.37, 654.55, 0.14266, 43, 24.81, -215.91, 0.85734, 2, 42, -125.55, 404.39, 0.58607, 43, -72.45, -469.09, 0.41393, 2, 42, -61.42, 302.42, 0.78309, 43, -96.64, -587.1, 0.21691, 2, 42, 5.13, 96.14, 0.98087, 43, -191.2, -782.14, 0.01913, 2, 42, 12.44, 70.26, 0.9887, 43, -203.82, -805.89, 0.0113, 1, 42, -39.11, -111.89, 1, 1, 42, -54.63, -116.28, 1, 1, 42, -121.25, -113.3, 1, 2, 9, -157.2, 414.33, 0.6279, 42, -261.43, -64.65, 0.3721, 3, 9, -68.29, 237.94, 0.6279, 42, -394.95, 80.92, 0.33514, 43, -490.74, -516.48, 0.03696, 3, 9, -29.44, -171.2, 0.6279, 42, -543.57, 464.1, 0.0647, 43, -333.14, -136.91, 0.3074 ], + "hull": 18, + "edges": [ 0, 34, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 14, 16 ], + "width": 1083, + "height": 428 + } + }, + "wing-back": { + "wing-back": { + "type": "mesh", + "uvs": [ 0.27992, 1, 0.41993, 0.8511, 0.63506, 0.69103, 0.71019, 0.49935, 0.7819, 0.3709, 1, 0.06855, 1, 0, 0.83312, 0, 0.50871, 0.27604, 0.42334, 0.38473, 0.29016, 0.46773, 0.23894, 0.57049, 0, 0.70289, 0, 1 ], + "triangles": [ 3, 10, 9, 3, 9, 4, 9, 8, 4, 4, 8, 5, 8, 7, 5, 7, 6, 5, 0, 13, 1, 13, 12, 1, 12, 11, 1, 1, 11, 2, 2, 11, 3, 3, 11, 10 ], + "vertices": [ 1, 37, -58.79, -72.37, 1, 1, 37, 46.56, -55.93, 1, 2, 37, 174.1, -56.94, 0.68025, 38, -28.45, -51.1, 0.31975, 2, 37, 286.48, -5.39, 0.4003, 38, 93.74, -32.27, 0.5997, 2, 37, 366.51, 22.98, 0.17872, 38, 178.48, -26.89, 0.82128, 1, 38, 384.52, -30.9, 1, 1, 38, 424.63, -15.07, 1, 1, 38, 402.32, 41.43, 1, 2, 37, 353.46, 138.21, 0.10957, 38, 197.47, 87.52, 0.89043, 2, 37, 280.29, 121.34, 0.25682, 38, 122.47, 91.32, 0.74318, 2, 37, 209.37, 128.12, 0.46071, 38, 56.11, 117.24, 0.53929, 2, 37, 146.7, 103.65, 0.71584, 38, -10.86, 110.85, 0.28416, 2, 37, 27.71, 122.12, 0.99997, 38, -120.26, 161.17, 3.0E-5, 1, 37, -120.71, 8.55, 1 ], + "hull": 14, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 0, 26 ], + "width": 364, + "height": 629 + } + }, + "wing-front": { + "wing-front": { + "type": "mesh", + "uvs": [ 0, 0, 0.02331, 0, 0.22961, 0.21519, 0.35084, 0.26796, 0.43003, 0.30243, 0.488, 0.32767, 0.53152, 0.4064, 0.57005, 0.47608, 0.62939, 0.54328, 1, 0.68105, 0.99999, 0.99998, 0.617, 0.99221, 0.44034, 0.85621, 0.38946, 0.74627, 0.35759, 0.67741, 0.3699, 0.6309, 0.30589, 0.58118, 0.22551, 0.51873, 0.16197, 0.39023, 0.08039, 0.22526, 0.00685, 0.07654 ], + "triangles": [ 5, 15, 4, 16, 4, 15, 16, 3, 4, 16, 17, 3, 3, 18, 2, 3, 17, 18, 18, 19, 2, 2, 19, 1, 19, 20, 1, 20, 0, 1, 10, 11, 9, 11, 8, 9, 11, 12, 8, 12, 13, 8, 14, 15, 13, 7, 13, 15, 7, 8, 13, 15, 6, 7, 15, 5, 6 ], + "vertices": [ 1, 36, 423.69, -49.6, 1, 1, 36, 408.05, -57.92, 1, 1, 36, 206.97, -13.75, 1, 2, 35, 555.33, -8.25, 0.10655, 36, 110.26, -28.12, 0.89345, 2, 35, 494.8, -28.62, 0.21311, 36, 47.09, -37.51, 0.78689, 2, 35, 450.49, -43.54, 0.49546, 36, 0.85, -44.38, 0.50454, 2, 35, 394.32, -25.6, 0.76147, 36, -51.28, -16.82, 0.23853, 2, 35, 344.61, -9.71, 0.92422, 36, -97.42, 7.57, 0.07578, 2, 35, 283.41, -4.82, 0.9928, 36, -156.8, 23.18, 0.0072, 1, 35, 9.16, -111.67, 1, 1, 35, -113, 43.82, 1, 1, 35, 118.85, 219.86, 1, 2, 35, 276.52, 236.51, 0.96534, 36, -121.05, 261.95, 0.03466, 2, 35, 349.03, 206.81, 0.92167, 36, -54.9, 219.92, 0.07833, 2, 35, 394.46, 188.2, 0.916, 36, -13.47, 193.6, 0.084, 2, 35, 404.91, 159.74, 0.7786, 36, -8.19, 163.75, 0.2214, 2, 35, 462.21, 165.55, 0.4504, 36, 49.24, 159.37, 0.5496, 2, 35, 534.17, 172.86, 0.29838, 36, 121.35, 153.88, 0.70162, 2, 35, 621.37, 140.04, 0.14825, 36, 201.4, 106.21, 0.85175, 1, 36, 304.17, 45.02, 1, 1, 36, 396.81, -10.14, 1 ], + "hull": 21, + "edges": [ 0, 2, 14, 16, 22, 24, 28, 30, 40, 0, 34, 36, 36, 38, 4, 6, 30, 32, 32, 34, 6, 8, 8, 10, 10, 12, 12, 14, 30, 10, 24, 26, 26, 28, 26, 14, 18, 20, 16, 18, 20, 22, 38, 40, 2, 4 ], + "width": 760, + "height": 620 + } + }, + "face/fringe-front/fringe-middle-back": { + "fringe-middle-back": { + "type": "mesh", + "uvs": [ 0.32752, 0, 0.86964, 0.29818, 1, 0.59486, 1, 1, 0.28701, 1, 0.30763, 0.65487, 0, 0.25321, 0, 0 ], + "triangles": [ 4, 5, 3, 5, 2, 3, 5, 1, 2, 5, 6, 1, 6, 0, 1, 6, 7, 0 ], + "vertices": [ 1, 20, 208.48, -106.96, 1, 2, 20, 169.72, -151.96, 0.6589, 28, 110.56, -69.29, 0.3411, 2, 20, 131.15, -162.78, 0.3535, 30, 34.61, 37.03, 0.6465, 2, 20, 78.48, -162.78, 0.3535, 30, 87.28, 37.03, 0.6465, 3, 20, 78.48, -103.6, 0.1164, 30, 87.28, -22.15, 0.6465, 28, 19.32, -20.93, 0.2371, 3, 20, 123.35, -105.31, 0.1164, 30, 42.41, -20.44, 0.6465, 28, 64.19, -22.64, 0.2371, 2, 20, 175.56, -79.78, 0.6589, 28, 116.4, 2.89, 0.3411, 1, 20, 208.48, -79.78, 1 ], + "hull": 8, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 0, 14 ], + "width": 83, + "height": 130 + } + }, + "face/fringe-front/fringe-middle-front": { + "fringe-middle-front": { + "type": "mesh", + "uvs": [ 1, 1, 0.75, 1, 0.5, 1, 0.25, 1, 0, 1, 0, 0.66667, 0, 0.33333, 0, 0, 0.5, 0, 1, 0, 1, 0.33333, 1, 0.66667, 0.58576, 0.6538, 0.52144, 0.32047 ], + "triangles": [ 1, 11, 0, 2, 12, 1, 1, 12, 11, 2, 3, 12, 12, 3, 5, 3, 4, 5, 12, 10, 11, 5, 13, 12, 5, 6, 13, 12, 13, 10, 6, 8, 13, 10, 8, 9, 6, 7, 8, 10, 13, 8 ], + "vertices": [ 3, 20, 80.48, -129.78, 0.0853, 30, 85.28, 4.03, 0.303, 28, 21.32, -47.11, 0.6117, 2, 30, 85.28, -33.47, 0.303, 28, 21.32, -9.61, 0.697, 2, 29, 90.56, 82.9, 0.3636, 28, 21.32, 27.89, 0.6364, 2, 29, 90.56, 45.4, 0.3636, 28, 21.32, 65.39, 0.6364, 2, 29, 90.56, 7.9, 0.3636, 28, 21.32, 102.89, 0.6364, 2, 29, 48.89, 7.9, 0.3636, 28, 62.99, 102.89, 0.6364, 2, 20, 163.81, 20.22, 0.3566, 28, 104.66, 102.89, 0.6434, 1, 20, 205.48, 20.22, 1, 1, 20, 205.48, -54.78, 1, 1, 20, 205.48, -129.78, 1, 2, 20, 163.81, -129.78, 0.3178, 28, 104.66, -47.11, 0.6822, 3, 20, 122.15, -129.78, 0.0853, 30, 43.61, 4.03, 0.303, 28, 62.99, -47.11, 0.6117, 2, 29, 47.28, 95.77, 0.3636, 28, 64.6, 15.03, 0.6364, 2, 20, 165.42, -57.99, 0.3566, 28, 106.26, 24.67, 0.6434 ], + "hull": 12, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 18, 20, 20, 22, 22, 0, 14, 16, 16, 18, 20, 16 ], + "width": 150, + "height": 125 + } + }, + "face/fringe-front/fringe-side-front": { + "fringe-side-front": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0.8, 0, 0.6, 0, 0.4, 0, 0.2, 0, 0, 1, 0, 1, 0.2, 1, 0.4, 1, 0.6, 1, 0.8 ], + "triangles": [ 3, 4, 9, 8, 5, 7, 5, 6, 7, 4, 5, 8, 9, 4, 8, 0, 1, 11, 1, 2, 11, 11, 2, 10, 2, 3, 10, 10, 3, 9 ], + "vertices": [ 1, 29, 217.56, 17.9, 1, 1, 29, 217.56, -48.1, 1, 2, 29, 171.16, -48.1, 0.82503, 28, -59.28, 158.89, 0.17497, 2, 29, 124.76, -48.1, 0.60616, 28, -12.88, 158.89, 0.39384, 3, 29, 78.36, -48.1, 0.3251, 20, 92.68, 76.22, 0.1478, 28, 33.52, 158.89, 0.5271, 2, 20, 139.08, 76.22, 0.1705, 28, 79.92, 158.89, 0.8295, 2, 20, 185.48, 76.22, 0.4031, 28, 126.32, 158.89, 0.5969, 2, 20, 185.48, 10.22, 0.4031, 28, 126.32, 92.89, 0.5969, 2, 20, 139.08, 10.22, 0.1705, 28, 79.92, 92.89, 0.8295, 3, 29, 78.36, 17.9, 0.3251, 20, 92.68, 10.22, 0.1478, 28, 33.52, 92.89, 0.5271, 2, 29, 124.76, 17.9, 0.60616, 28, -12.88, 92.89, 0.39384, 2, 29, 171.16, 17.9, 0.82503, 28, -59.28, 92.89, 0.17497 ], + "hull": 12, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 0 ], + "width": 66, + "height": 232 + } + }, + "face/ear": { + "ear": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 20, 20.48, 52.22, 0.3101, 28, -38.68, 134.89, 0.6899, 2, 28, -38.68, 184.89, 0.7287, 22, -114.77, -50.15, 0.2713, 2, 28, 31.32, 184.89, 0.7287, 22, -44.77, -50.15, 0.2713, 2, 20, 90.48, 52.22, 0.3101, 28, 31.32, 134.89, 0.6899 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 50, + "height": 70 + } + }, + "face/eye-back-shadow": { + "eye-back-shadow": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 51, -20.35, -15.78, 0.2749, 49, -3.33, -18.17, 0.7251, 2, 51, -20.35, 19.22, 0.1085, 49, -3.33, 16.83, 0.8915, 2, 51, 3.65, 19.22, 0.69582, 49, 20.67, 16.83, 0.30418, 2, 51, 3.65, -15.78, 0.91085, 49, 20.67, -18.17, 0.08915 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 35, + "height": 24 + } + }, + "face/eye-front-shadow": { + "eye-front-shadow": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 47, -34.76, -19.78, 0.1604, 45, -11.68, -24.94, 0.8396, 2, 47, -34.76, 39.22, 0.03854, 45, -11.68, 34.06, 0.96146, 2, 47, 1.24, 39.22, 0.96, 45, 24.32, 34.06, 0.04, 2, 47, 1.24, -19.78, 0.92478, 45, 24.32, -24.94, 0.07522 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 59, + "height": 36 + } + }, + "face/eye-reflex-back": { + "eye-reflex-back": { "x": -1, "y": 6.42, "rotation": -90, "width": 19, "height": 17 } + }, + "face/eye-reflex-front": { + "eye-reflex-front": { "x": -2.07, "y": 7.22, "rotation": -90, "width": 25, "height": 18 } + }, + "face/eye-white-back": { + "eye-white-back": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 1, 52, -1.77, -14.73, 1, 1, 52, -1.77, 17.27, 1, 1, 51, 3.65, 19.22, 1, 2, 49, 20.67, -15.17, 0.03731, 51, 3.65, -12.78, 0.96269 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 32, + "height": 40 + } + }, + "face/eye-white-front": { + "eye-white-front": { + "type": "mesh", + "uvs": [ 0.98492, 0.7288, 0.74399, 0.97841, 0.09394, 0.97675, 0, 0.61321, 0.44029, 0.01082, 0.98133, 0.03613 ], + "triangles": [ 0, 1, 4, 1, 3, 4, 1, 2, 3, 0, 4, 5 ], + "vertices": [ 2, 45, -10.01, -24.09, 0.90792, 48, 9.81, -32.94, 0.09208, 1, 48, -0.92, -19.45, 1, 1, 48, -0.85, 16.95, 1, 3, 45, -5.04, 31.06, 0.13374, 47, -28.13, 36.22, 0.27714, 48, 14.78, 22.22, 0.58912, 1, 47, -2.23, 11.56, 1, 1, 47, -3.31, -18.74, 1 ], + "hull": 6, + "edges": [ 0, 10, 0, 2, 2, 4, 4, 6, 8, 10, 6, 8 ], + "width": 56, + "height": 43 + } + }, + "face/eyelashes-down-back": { + "eyelashes-down-back": { "x": -0.77, "y": -0.73, "rotation": -90, "width": 28, "height": 14 } + }, + "face/eyelashes-down-front": { + "eyelashes-down-front": { "x": -2.35, "y": 0.72, "rotation": -90, "width": 37, "height": 15 } + }, + "face/eyelashes-top-back": { + "eyelashes-top-back": { + "type": "mesh", + "uvs": [ 0.53449, 0.0112, 0.80224, 0.23436, 1, 0.50028, 0.89272, 0.90854, 0.67501, 0.92236, 0.35422, 0.73425, 0.24884, 0.95236, 0.02061, 0.96391, 0.02196, 0.59454, 0.24865, 0.01679 ], + "triangles": [ 7, 8, 6, 3, 1, 2, 5, 0, 4, 4, 1, 3, 4, 0, 1, 8, 9, 5, 5, 9, 0, 6, 8, 5 ], + "vertices": [ 1, 51, 9.38, -2.84, 1, 2, 51, 4.02, -14.88, 0.86286, 49, 21.04, -17.27, 0.13714, 2, 51, -2.36, -23.78, 0.5814, 49, 14.66, -26.17, 0.4186, 2, 51, -12.16, -18.96, 0.5814, 49, 4.86, -21.34, 0.4186, 2, 51, -12.49, -9.16, 0.6434, 49, 4.53, -11.54, 0.3566, 1, 51, -7.98, 5.28, 1, 2, 51, -13.21, 10.02, 0.6047, 49, 3.81, 7.63, 0.3953, 2, 51, -13.49, 20.29, 0.5814, 49, 3.53, 17.9, 0.4186, 2, 51, -4.62, 20.23, 0.5814, 49, 12.4, 17.84, 0.4186, 1, 51, 9.24, 10.03, 1 ], + "hull": 10, + "edges": [ 0, 18, 0, 2, 4, 6, 14, 16, 16, 18, 12, 14, 6, 8, 8, 10, 10, 12, 2, 4 ], + "width": 45, + "height": 24 + } + }, + "face/eyelashes-top-front": { + "eyelashes-top-front": { + "type": "mesh", + "uvs": [ 0, 0.74724, 0.51172, 0, 0.61319, 0, 0.99001, 0.18532, 0.99016, 0.28688, 0.83893, 0.5606, 0.6312, 0.2977, 0.48808, 0.44992, 0.18971, 1, 0.09689, 1, 0, 0.86051 ], + "triangles": [ 4, 5, 3, 7, 0, 1, 7, 1, 6, 1, 2, 6, 5, 6, 3, 6, 2, 3, 0, 8, 9, 9, 10, 0, 7, 8, 0 ], + "vertices": [ 1, 45, -1.31, 42.06, 1, 1, 47, 6.24, 9.35, 1, 1, 47, 6.24, 1.84, 1, 2, 45, 21.73, -31.2, 0.2713, 47, -1.36, -26.05, 0.7287, 2, 45, 17.56, -31.21, 0.2713, 47, -5.52, -26.06, 0.7287, 2, 45, 6.34, -20.02, 0.34, 47, -16.75, -14.87, 0.66, 1, 47, -5.97, 0.51, 1, 2, 45, 10.88, 5.94, 0.23429, 47, -12.21, 11.1, 0.76571, 1, 45, -11.68, 28.02, 1, 1, 45, -11.68, 34.89, 1, 1, 45, -5.96, 42.06, 1 ], + "hull": 11, + "edges": [ 0, 20, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20 ], + "width": 74, + "height": 41 + } + }, + "face/face": { + "face": { + "type": "mesh", + "uvs": [ 0.84841, 0, 0.99605, 0.18591, 0.99597, 0.82505, 0.75638, 1, 0.56116, 1, 0.28151, 0.91236, 0.02486, 0.65319, 0.25928, 0.18329, 0.83782, 0, 0.31251, 0.58794, 0.2902, 0.34407, 0.75589, 0.2771, 0.94411, 0.34407, 0.92878, 0.62458, 0.66107, 0.87982, 0.7811, 0.68326 ], + "triangles": [ 4, 14, 3, 3, 14, 2, 4, 5, 14, 5, 9, 14, 5, 6, 9, 14, 15, 2, 14, 9, 15, 15, 13, 2, 13, 12, 2, 2, 12, 1, 15, 9, 13, 6, 10, 9, 6, 7, 10, 9, 11, 13, 13, 11, 12, 9, 10, 11, 12, 11, 1, 10, 7, 11, 11, 8, 1, 8, 0, 1, 11, 7, 8 ], + "vertices": [ 1, 20, 201.48, -112.61, 1, 1, 20, 153.89, -146.86, 1, 2, 20, -9.73, -146.84, 0.2016, 28, -68.89, -64.18, 0.7984, 1, 28, -113.68, -8.59, 1, 1, 28, -113.68, 36.7, 1, 2, 20, -32.08, 18.91, 0.2481, 28, -91.24, 101.58, 0.7519, 2, 20, 34.26, 78.46, 0.3488, 28, -24.89, 161.12, 0.6512, 1, 20, 154.56, 24.07, 1, 1, 20, 201.48, -110.15, 1, 1, 28, -8.19, 94.39, 1, 1, 28, 54.24, 99.56, 1, 1, 28, 71.38, -8.48, 1, 2, 20, 113.4, -134.81, 0.2403, 28, 54.24, -52.14, 0.7597, 2, 20, 41.59, -131.25, 0.2403, 28, -17.57, -48.59, 0.7597, 1, 28, -82.91, 13.52, 1, 1, 21, 0.89, 2.3, 1 ], + "hull": 9, + "edges": [ 0, 16, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 18, 26 ], + "width": 232, + "height": 256 + } + }, + "face/fringe-side-back": { + "fringe-side-back": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0.8, 0, 0.6, 0, 0.4, 0, 0.2, 0, 0, 1, 0, 1, 0.2, 1, 0.4, 1, 0.6, 1, 0.8 ], + "triangles": [ 10, 3, 9, 3, 4, 9, 9, 4, 8, 8, 5, 7, 5, 6, 7, 4, 5, 8, 0, 1, 11, 1, 2, 11, 11, 2, 10, 2, 3, 10 ], + "vertices": [ 1, 30, 219.28, 49.03, 1, 1, 30, 219.28, -18.97, 1, 2, 30, 172.48, -18.97, 0.78148, 20, -6.72, -106.78, 0.21852, 2, 30, 125.68, -18.97, 0.54452, 20, 40.08, -106.78, 0.45548, 2, 30, 78.88, -18.97, 0.28148, 20, 86.88, -106.78, 0.71852, 1, 20, 133.68, -106.78, 1, 1, 20, 180.48, -106.78, 1, 1, 20, 180.48, -174.78, 1, 1, 20, 133.68, -174.78, 1, 2, 30, 78.88, 49.03, 0.28148, 20, 86.88, -174.78, 0.71852, 2, 30, 125.68, 49.03, 0.54452, 20, 40.08, -174.78, 0.45548, 2, 30, 172.48, 49.03, 0.78148, 20, -6.72, -174.78, 0.21852 ], + "hull": 12, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 0 ], + "width": 68, + "height": 234 + } + }, + "face/hair-hat-shadow": { + "hair-hat-shadow": { "x": 198.48, "y": 40.22, "rotation": -90, "width": 224, "height": 102 } + }, + "face/mouth": { + "mouth": { "x": 4.02, "y": -0.92, "rotation": -90, "width": 56, "height": 16 } + }, + "face/nose": { + "nose": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 1, 21, -13.2, -1.48, 1, 2, 28, -46.68, -3.11, 0.4, 21, -13.2, 13.52, 0.6, 2, 28, -29.68, -3.11, 0.4, 21, 3.8, 13.52, 0.6, 1, 21, 3.8, -1.48, 1 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 15, + "height": 17 + } + }, + "face/nose-highlight": { + "nose-highlight": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 2, 28, -33.68, -11.11, 0.124, 21, -0.2, 5.52, 0.876, 2, 28, -33.68, -1.11, 0.124, 21, -0.2, 15.52, 0.876, 2, 28, -22.68, -1.11, 0.124, 21, 10.8, 15.52, 0.876, 2, 28, -22.68, -11.11, 0.124, 21, 10.8, 5.52, 0.876 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 10, + "height": 11 + } + }, + "face/nose-shadow": { + "nose-shadow": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 1, 21, -15.2, -5.48, 1, 2, 28, -48.68, -4.11, 0.6047, 21, -15.2, 12.52, 0.3953, 2, 28, -28.68, -4.11, 0.6047, 21, 4.8, 12.52, 0.3953, 1, 21, 4.8, -5.48, 1 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 18, + "height": 20 + } + }, + "face/pupil-back": { + "pupil-back": { "x": -2.5, "y": 1.42, "rotation": -90, "width": 25, "height": 36 } + }, + "face/pupil-front": { + "pupil-front": { "x": -0.07, "y": 1.72, "rotation": -90, "width": 30, "height": 44 } + }, + "hair-back/hair-back-1": { + "hair-back-1": { + "type": "mesh", + "uvs": [ 1, 0.05206, 0.78167, 0.17387, 0.70445, 0.29745, 0.65078, 0.39485, 0.49669, 0.47826, 0.30981, 0.57942, 0.46147, 0.61966, 0.65876, 0.71313, 0.30967, 0.78419, 0.48938, 0.84645, 0.47689, 0.91323, 0.30103, 1, 0.21344, 1, 0.10045, 0.96739, 0.0798, 0.89237, 0.04833, 0.77797, 0, 0.60231, 0, 0.55114, 0.36021, 0.41385, 0.44814, 0.36733, 0.56438, 0.25145, 0.68422, 0.13617, 0.82577, 0, 1, 1.0E-5 ], + "triangles": [ 10, 11, 14, 14, 11, 12, 12, 13, 14, 5, 17, 18, 4, 19, 3, 3, 19, 2, 19, 20, 2, 18, 19, 4, 5, 18, 4, 14, 8, 10, 10, 8, 9, 14, 15, 8, 8, 15, 6, 15, 5, 6, 15, 16, 5, 16, 17, 5, 8, 6, 7, 0, 22, 23, 22, 0, 21, 0, 1, 21, 2, 20, 1, 20, 21, 1 ], + "vertices": [ 1, 20, 193.6, 53.22, 1, 1, 20, 100.3, 125.49, 1, 2, 20, 5.63, 151.05, 0.5115, 26, 123.22, -101.53, 0.4885, 2, 20, -68.98, 168.82, 0.3588, 26, 197.83, -119.3, 0.6412, 2, 20, -132.86, 219.82, 0.3053, 26, 261.72, -170.3, 0.6947, 3, 20, -210.35, 281.68, 0.26425, 26, 339.21, -232.16, 0.61722, 27, -129.44, -232.16, 0.11853, 3, 20, -241.18, 231.47, 0.22919, 26, 370.03, -181.96, 0.54443, 27, -98.61, -181.96, 0.22638, 3, 20, -312.77, 166.17, 0.2009, 26, 441.63, -116.65, 0.50653, 27, -27.02, -116.65, 0.29257, 3, 20, -367.21, 281.72, 0.18235, 26, 496.06, -232.2, 0.47614, 27, 27.42, -232.2, 0.3415, 3, 20, -414.9, 222.24, 0.21741, 26, 543.75, -172.72, 0.57649, 27, 75.11, -172.72, 0.2061, 3, 20, -466.05, 226.37, 0.23495, 26, 594.91, -176.85, 0.4504, 27, 126.26, -176.85, 0.31465, 3, 20, -532.52, 284.58, 0.23495, 26, 661.38, -235.06, 0.4504, 27, 192.73, -235.06, 0.31465, 3, 20, -532.52, 313.57, 0.23495, 26, 661.38, -264.05, 0.4504, 27, 192.73, -264.05, 0.31465, 3, 20, -507.54, 350.97, 0.23495, 26, 636.39, -301.46, 0.4504, 27, 167.75, -301.46, 0.31465, 3, 20, -450.07, 357.81, 0.23495, 26, 578.93, -308.29, 0.4504, 27, 110.28, -308.29, 0.31465, 3, 20, -362.45, 368.22, 0.23506, 26, 491.3, -318.71, 0.51948, 27, 22.66, -318.71, 0.24546, 3, 20, -227.89, 384.22, 0.25098, 26, 356.75, -334.7, 0.57166, 27, -111.9, -334.7, 0.17736, 3, 20, -188.7, 384.22, 0.27537, 26, 317.55, -334.7, 0.63085, 27, -151.1, -334.7, 0.09378, 2, 20, -83.53, 264.99, 0.3053, 26, 212.38, -215.47, 0.6947, 2, 20, -47.89, 235.89, 0.3588, 26, 176.75, -186.37, 0.6412, 2, 20, 40.87, 197.41, 0.49123, 26, 87.99, -147.89, 0.50877, 2, 20, 129.18, 157.75, 0.68581, 26, -0.32, -108.23, 0.31419, 1, 20, 233.48, 110.89, 1, 1, 20, 233.47, 53.22, 1 ], + "hull": 24, + "edges": [ 0, 2, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 32, 34, 34, 36, 36, 38, 44, 46, 30, 32, 30, 12, 26, 28, 28, 30, 6, 8, 8, 10, 4, 6, 38, 40, 2, 4, 46, 0, 40, 42, 42, 44 ], + "width": 331, + "height": 766 + } + }, + "hair-back/hair-back-2": { + "hair-back-2": { + "type": "mesh", + "uvs": [ 0.89086, 0, 0.99848, 0, 0.96651, 0.15477, 0.94381, 0.26466, 0.92222, 0.36914, 0.89845, 0.48424, 0.57735, 0.62302, 0.73413, 0.63077, 0.9883, 0.70379, 0.86085, 0.84916, 0.74336, 0.98316, 0.59619, 1, 0.37348, 1, 0.10983, 0.83684, 1.0E-5, 0.76887, 0, 0.66185, 0.06689, 0.57957, 0.28324, 0.47594, 0.49583, 0.37411, 0.59097, 0.27636, 0.69109, 0.15073, 0.80033, 0.01367, 0.54528, 0.76481 ], + "triangles": [ 22, 7, 8, 14, 15, 22, 13, 14, 22, 9, 22, 8, 9, 13, 22, 9, 12, 13, 9, 11, 12, 10, 11, 9, 4, 19, 3, 18, 19, 4, 5, 18, 4, 17, 18, 5, 6, 17, 5, 16, 17, 6, 15, 16, 6, 22, 15, 6, 22, 6, 7, 19, 20, 3, 3, 20, 2, 1, 21, 0, 2, 21, 1, 20, 21, 2 ], + "vertices": [ 1, 20, 157.48, 123.05, 1, 1, 20, 157.48, 101.53, 1, 2, 20, 47.29, 107.92, 0.70089, 26, 81.57, -58.4, 0.29911, 2, 20, -30.96, 112.46, 0.4885, 26, 159.82, -62.94, 0.5115, 2, 20, -105.35, 116.78, 0.33608, 26, 234.21, -67.26, 0.66392, 2, 20, -187.3, 121.53, 0.1832, 26, 316.15, -72.01, 0.8168, 3, 20, -286.11, 185.75, 0.1756, 26, 414.96, -136.23, 0.74597, 27, -53.68, -136.23, 0.07843, 3, 20, -291.63, 154.4, 0.1756, 26, 420.49, -104.88, 0.63052, 27, -48.16, -104.88, 0.19388, 3, 20, -343.62, 103.56, 0.1756, 26, 472.48, -54.04, 0.45922, 27, 3.83, -54.04, 0.36518, 3, 20, -447.12, 129.05, 0.1756, 26, 575.98, -79.53, 0.24092, 27, 107.33, -79.53, 0.58348, 2, 20, -542.53, 152.55, 0.1756, 27, 202.74, -103.03, 0.8244, 2, 20, -554.52, 181.98, 0.1756, 27, 214.73, -132.46, 0.8244, 2, 20, -554.52, 226.52, 0.1756, 27, 214.73, -177.01, 0.8244, 3, 20, -438.35, 279.26, 0.1756, 26, 567.2, -229.74, 0.24092, 27, 98.56, -229.74, 0.58348, 3, 20, -389.96, 301.22, 0.1756, 26, 518.81, -251.7, 0.45922, 27, 50.17, -251.7, 0.36518, 3, 20, -313.75, 301.22, 0.1756, 26, 442.61, -251.7, 0.63052, 27, -26.04, -251.7, 0.19388, 3, 20, -255.17, 287.84, 0.1756, 26, 384.03, -238.32, 0.74597, 27, -84.62, -238.32, 0.07843, 2, 20, -181.39, 244.57, 0.1832, 26, 310.24, -195.05, 0.8168, 2, 20, -108.88, 202.06, 0.33608, 26, 237.74, -152.54, 0.66392, 2, 20, -39.29, 183.03, 0.4885, 26, 168.15, -133.51, 0.5115, 2, 20, 50.16, 163, 0.6489, 26, 78.7, -113.48, 0.3511, 1, 20, 147.75, 141.16, 1, 2, 20, -387.07, 192.17, 0.1756, 27, 47.28, -142.65, 0.8244 ], + "hull": 22, + "edges": [ 0, 42, 0, 2, 10, 12, 12, 14, 14, 16, 20, 22, 22, 24, 28, 30, 30, 32, 36, 38, 6, 8, 8, 10, 32, 34, 34, 36, 24, 26, 26, 28, 16, 18, 18, 20, 38, 40, 40, 42, 2, 4, 4, 6 ], + "width": 200, + "height": 712 + } + }, + "hair-back/hair-back-3": { + "hair-back-3": { + "type": "mesh", + "uvs": [ 0.84591, 0.08889, 0.82372, 0.26566, 0.80438, 0.41975, 0.94221, 0.62567, 1, 0.81672, 0.70929, 0.99918, 0.46458, 0.99803, 0.23662, 0.83671, 0, 0.66926, 0, 0.51704, 0.21223, 0.38901, 0.3832, 0.26202, 0.39154, 0.00106, 0.78531, 0.00114 ], + "triangles": [ 4, 5, 7, 5, 6, 7, 4, 7, 3, 7, 8, 3, 8, 2, 3, 2, 8, 9, 2, 9, 10, 10, 11, 2, 2, 11, 1, 1, 11, 0, 0, 12, 13, 0, 11, 12 ], + "vertices": [ 1, 20, 43.92, 49.03, 1, 3, 20, -74.51, 52.89, 0.49873, 26, 203.37, -3.37, 0.44236, 27, -265.28, -3.37, 0.05891, 3, 20, -177.75, 56.26, 0.3969, 26, 306.6, -6.74, 0.30443, 27, -162.04, -6.74, 0.29867, 3, 20, -315.72, 32.28, 0.1145, 26, 444.58, 17.24, 0.16959, 27, -24.07, 17.24, 0.71591, 2, 20, -443.72, 22.22, 0.1145, 27, 103.93, 27.3, 0.8855, 2, 20, -565.97, 72.8, 0.1145, 27, 226.18, -23.29, 0.8855, 2, 20, -565.2, 115.38, 0.1145, 27, 225.41, -65.87, 0.8855, 3, 20, -457.12, 155.05, 0.1145, 26, 585.97, -105.53, 0.04756, 27, 117.32, -105.53, 0.83794, 3, 20, -344.93, 196.22, 0.1145, 26, 473.78, -146.7, 0.53505, 27, 5.13, -146.7, 0.35045, 3, 20, -242.93, 196.22, 0.1145, 26, 371.79, -146.7, 0.63528, 27, -96.86, -146.7, 0.25022, 3, 20, -157.16, 159.29, 0.30166, 26, 286.01, -109.77, 0.5576, 27, -182.63, -109.77, 0.14074, 3, 20, -72.07, 129.55, 0.49024, 26, 200.93, -80.03, 0.47767, 27, -267.72, -80.03, 0.03208, 1, 20, 102.77, 128.09, 1, 1, 20, 102.72, 59.58, 1 ], + "hull": 14, + "edges": [ 0, 26, 6, 8, 8, 10, 10, 12, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 12, 14, 14, 16, 14, 6, 16, 4, 6, 4, 0, 2, 2, 4 ], + "width": 174, + "height": 670 + } + }, + "hair-back/hair-back-4": { + "hair-back-4": { + "type": "mesh", + "uvs": [ 0.84401, 0.30705, 0.95315, 0.49123, 0.9783, 0.6272, 1, 0.74452, 0.91116, 0.87667, 0.91728, 1, 0.62869, 1, 0.56926, 1, 0.32887, 0.88007, 0.04472, 0.7649, 0, 0.61844, 0.14237, 0.48206, 0.16865, 0.34839, 0.03769, 0.00116, 0.67304, 0.01853 ], + "triangles": [ 11, 2, 10, 2, 9, 10, 3, 9, 2, 5, 6, 4, 3, 8, 9, 4, 8, 3, 6, 7, 8, 8, 4, 6, 2, 11, 1, 11, 12, 1, 12, 0, 1, 12, 13, 14, 12, 14, 0 ], + "vertices": [ 2, 20, -118.94, -74.62, 0.3588, 26, 247.8, 124.13, 0.6412, 3, 20, -239.77, -98.52, 0.2672, 26, 368.62, 148.04, 0.3511, 27, -100.02, 148.04, 0.3817, 3, 20, -328.96, -104.03, 0.19285, 26, 457.82, 153.54, 0.32625, 27, -10.83, 153.54, 0.4809, 3, 20, -405.92, -108.78, 0.12293, 26, 534.78, 158.3, 0.37135, 27, 66.13, 158.3, 0.50573, 3, 20, -492.62, -89.32, 0.05925, 26, 621.47, 138.84, 0.1867, 27, 152.83, 138.84, 0.75405, 2, 26, 702.38, 140.18, 0, 27, 233.73, 140.18, 1, 3, 20, -573.52, -27.46, 0.0224, 26, 702.38, 76.98, 0.06577, 27, 233.73, 76.98, 0.91183, 3, 20, -573.52, -14.45, 0.05056, 26, 702.38, 63.96, 0.14653, 27, 233.73, 63.96, 0.80292, 3, 20, -494.85, 38.2, 0.08885, 26, 623.7, 11.32, 0.25335, 27, 155.06, 11.32, 0.65779, 3, 20, -419.29, 100.43, 0.19057, 26, 548.15, -50.91, 0.36714, 27, 79.5, -50.91, 0.44229, 3, 20, -323.21, 110.22, 0.2672, 26, 452.07, -60.7, 0.2519, 27, -16.58, -60.7, 0.4809, 3, 20, -233.75, 79.04, 0.2672, 26, 362.61, -29.52, 0.3511, 27, -106.04, -29.52, 0.3817, 2, 20, -146.06, 73.29, 0.3588, 26, 274.92, -23.77, 0.6412, 1, 20, 81.72, 101.97, 1, 2, 20, 70.32, -37.17, 0.99873, 26, 58.53, 86.69, 0.00127 ], + "hull": 15, + "edges": [ 12, 14, 20, 22, 22, 24, 24, 26, 26, 28, 2, 4, 4, 6, 2, 0, 0, 28, 18, 20, 14, 16, 16, 18, 8, 10, 6, 8, 10, 12 ], + "width": 219, + "height": 656 + } + }, + "hair-back/hair-back-5": { + "hair-back-5": { + "type": "mesh", + "uvs": [ 0.52681, 0.0022, 0.53701, 0.13188, 0.57788, 0.19975, 0.74688, 0.40516, 0.89266, 0.58235, 1, 0.80234, 0.94757, 0.86532, 0.87274, 0.99806, 0.65652, 1, 0.49768, 0.91169, 0.26202, 0.78067, 0.35593, 0.58238, 0.25008, 0.42396, 0, 0.16031, 0, 0.12266, 0.22195, 0.00216 ], + "triangles": [ 8, 9, 7, 7, 9, 6, 6, 9, 5, 5, 9, 4, 9, 10, 4, 11, 4, 10, 11, 3, 4, 11, 12, 3, 12, 13, 2, 12, 2, 3, 15, 1, 14, 1, 15, 0, 2, 13, 1, 1, 13, 14 ], + "vertices": [ 1, 20, 168.95, -85.68, 1, 2, 20, 78.56, -87.92, 0.84015, 26, 50.29, 137.44, 0.15985, 2, 20, 31.25, -96.91, 0.67545, 26, 97.6, 146.43, 0.32455, 2, 20, -111.92, -134.09, 0.50775, 26, 240.77, 183.61, 0.49225, 2, 20, -235.42, -166.16, 0.34305, 26, 364.28, 215.68, 0.65695, 3, 20, -387.13, -190.07, 0.10437, 26, 515.98, 239.59, 0.36512, 27, 47.26, 237.59, 0.53051, 3, 20, -432.65, -178.24, 0.03859, 26, 561.5, 227.76, 0.18918, 27, 92.85, 227.76, 0.77223, 2, 26, 654.02, 211.3, 0.2137, 27, 185.38, 211.3, 0.7863, 2, 26, 655.38, 163.73, 0.2137, 27, 186.73, 163.73, 0.7863, 3, 20, -464.97, -79.27, 0.09122, 26, 593.83, 128.79, 0.40749, 27, 125.18, 128.79, 0.50129, 2, 20, -373.65, -27.42, 0.1832, 26, 502.5, 76.94, 0.8168, 2, 20, -235.44, -48.08, 0.38703, 26, 364.29, 97.6, 0.61297, 2, 20, -125.02, -24.8, 0.59141, 26, 253.87, 74.32, 0.40859, 1, 20, 58.74, 30.22, 1, 1, 20, 84.98, 30.22, 1, 1, 20, 168.97, -18.61, 1 ], + "hull": 16, + "edges": [ 0, 30, 0, 2, 2, 4, 14, 16, 20, 22, 26, 28, 28, 30, 10, 12, 12, 14, 16, 18, 18, 20, 4, 6, 6, 8, 24, 26, 22, 24, 18, 8, 8, 10 ], + "width": 220, + "height": 697 + } + }, + "hair-back/hair-back-6": { + "hair-back-6": { + "type": "mesh", + "uvs": [ 0, 0.00316, 0.19789, 0.00238, 0.24097, 0.10462, 0.42784, 0.26537, 0.57522, 0.34678, 0.68888, 0.40956, 0.80549, 0.47398, 0.94785, 0.55261, 0.89923, 0.64182, 0.84246, 0.74598, 1, 0.78199, 1, 0.82207, 0.92109, 0.94159, 0.77855, 1, 0.5892, 1, 0.4989, 0.90847, 0.38858, 0.79465, 0.39143, 0.71034, 0.43093, 0.64588, 0.41659, 0.56993, 0.34767, 0.47025, 0.25898, 0.39956, 0.12664, 0.29408, 0.0176, 0.20717, 0, 0.0579, 0.6061, 0.79944 ], + "triangles": [ 12, 13, 15, 13, 14, 15, 12, 15, 11, 11, 15, 9, 15, 16, 25, 15, 25, 9, 9, 10, 11, 25, 8, 9, 25, 16, 17, 8, 25, 17, 18, 8, 17, 18, 19, 8, 8, 19, 7, 19, 6, 7, 19, 20, 6, 20, 5, 6, 5, 21, 4, 5, 20, 21, 21, 3, 4, 21, 22, 3, 22, 23, 3, 23, 2, 3, 23, 24, 2, 24, 1, 2, 24, 0, 1 ], + "vertices": [ 1, 20, 167.22, -45.78, 1, 1, 20, 167.78, -89.31, 1, 3, 20, 94.68, -98.79, 0.86501, 26, 34.18, 148.31, 0.12237, 27, -434.47, 148.31, 0.01262, 3, 20, -20.26, -139.9, 0.73484, 26, 149.11, 189.42, 0.23236, 27, -319.53, 189.42, 0.03279, 3, 20, -78.47, -172.33, 0.6136, 26, 207.32, 221.85, 0.31854, 27, -261.32, 221.85, 0.06786, 3, 20, -123.36, -197.33, 0.50408, 26, 252.21, 246.85, 0.37201, 27, -216.43, 246.85, 0.12392, 3, 20, -169.41, -222.99, 0.40753, 26, 298.27, 272.51, 0.38856, 27, -170.38, 272.51, 0.20391, 3, 20, -225.64, -254.3, 0.32386, 26, 354.49, 303.82, 0.37034, 27, -114.15, 303.82, 0.3058, 3, 20, -289.42, -243.61, 0.25215, 26, 418.27, 293.13, 0.32576, 27, -50.37, 293.13, 0.42209, 3, 20, -363.9, -231.12, 0.20172, 26, 492.75, 280.64, 0.2532, 27, 24.1, 280.64, 0.54508, 3, 20, -389.64, -265.78, 0.16128, 26, 518.5, 315.3, 0.17872, 27, 49.85, 315.3, 0.65999, 3, 20, -418.3, -265.78, 0.10469, 26, 547.16, 315.3, 0.2824, 27, 78.51, 315.3, 0.61291, 3, 20, -503.76, -248.42, 0.07948, 26, 632.61, 297.94, 0.2824, 27, 163.97, 297.94, 0.63812, 3, 20, -545.52, -217.06, 0.06028, 26, 674.38, 266.58, 0.2824, 27, 205.73, 266.58, 0.65732, 3, 20, -545.52, -175.4, 0.06028, 26, 674.38, 224.92, 0.2824, 27, 205.73, 224.92, 0.65732, 3, 20, -480.08, -155.54, 0.15387, 26, 608.93, 205.05, 0.2824, 27, 140.29, 205.05, 0.56373, 3, 20, -398.7, -131.27, 0.25129, 26, 527.55, 180.79, 0.44103, 27, 58.91, 180.79, 0.30769, 3, 20, -338.41, -131.89, 0.2923, 26, 467.27, 181.41, 0.5779, 27, -1.38, 181.41, 0.1298, 3, 20, -292.32, -140.58, 0.37144, 26, 421.18, 190.1, 0.53386, 27, -47.47, 190.1, 0.0947, 3, 20, -238.02, -137.43, 0.45068, 26, 366.88, 186.95, 0.48817, 27, -101.77, 186.95, 0.06116, 3, 20, -166.75, -122.27, 0.53005, 26, 295.6, 171.78, 0.44014, 27, -173.04, 171.78, 0.0298, 2, 20, -116.21, -102.75, 0.60953, 26, 245.06, 152.27, 0.39047, 2, 20, -40.79, -73.64, 0.72471, 26, 169.64, 123.16, 0.27529, 2, 20, 21.35, -49.65, 0.8574, 26, 107.5, 99.17, 0.1426, 1, 20, 128.08, -45.78, 1, 3, 20, -402.12, -179.12, 0.19676, 26, 530.97, 228.64, 0.26884, 27, 62.33, 228.64, 0.5344 ], + "hull": 25, + "edges": [ 0, 48, 0, 2, 2, 4, 4, 6, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 38, 40, 46, 48, 12, 14, 10, 12, 44, 46, 40, 42, 42, 44, 6, 8, 8, 10, 36, 38, 14, 16, 16, 18, 32, 34, 34, 36, 28, 30, 30, 32, 50, 16, 18, 30 ], + "width": 220, + "height": 715 + } + }, + "hat/feathers-back": { + "feathers-back": { + "type": "mesh", + "uvs": [ 0.99999, 0, 1, 0.33648, 0.94897, 0.50948, 0.82521, 0.929, 0.47931, 1, 0.33408, 0.78083, 0.14308, 0.49259, 0, 0.27667, 0, 0.08318, 0.4705, 0.03304, 0.78052, 0, 0.66524, 0.5216, 0.59356, 0.18309, 0.6294, 0.3623 ], + "triangles": [ 1, 10, 0, 12, 10, 1, 6, 9, 12, 6, 7, 9, 6, 12, 13, 1, 13, 12, 3, 11, 2, 5, 6, 11, 3, 4, 11, 4, 5, 11, 6, 13, 11, 11, 13, 2, 2, 13, 1, 7, 8, 9, 12, 9, 10 ], + "vertices": [ 2, 24, 96.3, -42.01, 0.6031, 23, 91.5, -153.41, 0.3969, 2, 24, 57.96, -40.97, 0.2748, 23, 56.76, -137.15, 0.7252, 2, 24, 38.4, -34.62, 0.2748, 23, 41.37, -123.52, 0.7252, 1, 23, 4.03, -90.47, 1, 1, 23, 13.42, -51.32, 1, 1, 23, 43.07, -46.92, 1, 2, 24, 42.82, 57.17, 0.2748, 23, 82.06, -41.13, 0.7252, 2, 24, 67.87, 72.8, 0.6031, 23, 111.27, -36.79, 0.3969, 2, 24, 89.92, 72.2, 0.6031, 23, 131.24, -46.15, 0.3969, 2, 24, 94.18, 18.43, 0.6031, 23, 113.68, -97.15, 0.3969, 2, 24, 96.98, -17, 0.6031, 23, 102.11, -130.75, 0.3969, 2, 24, 37.9, -2.25, 0.2748, 23, 53.83, -93.64, 0.7252, 2, 24, 76.7, 4.87, 0.6031, 23, 92.24, -102.6, 0.3969, 2, 24, 56.16, 1.34, 0.2748, 23, 72.01, -97.64, 0.7252 ], + "hull": 11, + "edges": [ 0, 2, 14, 16, 8, 10, 10, 12, 12, 14, 16, 18, 18, 20, 20, 0, 2, 4, 4, 6, 24, 26, 24, 18, 26, 22, 6, 8 ], + "width": 114, + "height": 114 + } + }, + "hat/feathers-front": { + "feathers-front": { + "type": "mesh", + "uvs": [ 0.3388, 0, 0.54158, 0.14344, 0.74297, 0.2859, 0.85306, 0.36378, 1, 0.46773, 1, 0.60515, 0.95944, 0.81123, 0.66438, 1, 0.58726, 1, 0.56097, 0.78724, 0.54426, 0.65203, 0.40317, 0.57511, 0.19125, 0.45957, 0, 0.3553, 0, 1.0E-5, 0.75902, 0.42138, 0.75203, 0.58249, 0.74507, 0.72959, 0.79778, 0.42193, 0.78067, 0.58361 ], + "triangles": [ 19, 4, 5, 5, 17, 19, 7, 8, 9, 7, 17, 6, 17, 7, 9, 6, 17, 5, 0, 13, 14, 12, 0, 1, 12, 13, 0, 11, 12, 1, 11, 1, 2, 17, 10, 16, 17, 16, 19, 19, 18, 4, 15, 2, 3, 11, 2, 15, 15, 10, 11, 19, 15, 18, 16, 15, 19, 16, 10, 15, 9, 10, 17, 18, 15, 3, 18, 3, 4 ], + "vertices": [ 1, 25, 92.8, -22.38, 1, 2, 24, 174.08, 16.41, 0.21011, 25, 45.04, -23.75, 0.78989, 2, 24, 142.48, -18.99, 0.41348, 25, -2.4, -25.11, 0.58652, 2, 24, 125.2, -38.35, 0.5954, 23, 119.46, -161.59, 0.4046, 2, 24, 102.14, -64.18, 0.5954, 23, 88.01, -176.07, 0.4046, 2, 24, 72.6, -63.38, 0.3969, 23, 61.25, -163.54, 0.6031, 2, 24, 28.51, -54.87, 0.1298, 23, 24.22, -138.15, 0.8702, 1, 23, 9.97, -72.84, 1, 1, 23, 15.86, -60.27, 1, 2, 24, 35.62, 16.68, 0.458, 23, 59.29, -75.37, 0.542, 3, 24, 64.76, 18.9, 0.51591, 25, -28.26, 57.4, 0.2824, 23, 86.9, -84.97, 0.20169, 2, 24, 81.98, 43.84, 0.5618, 25, 1.7, 62.01, 0.4382, 2, 24, 107.85, 81.29, 0.37966, 25, 46.68, 68.95, 0.62034, 2, 24, 131.2, 115.1, 0.19036, 25, 87.29, 75.21, 0.80964, 1, 25, 138.24, 18.29, 1, 2, 24, 113.28, -21.09, 0.76701, 25, -23.98, -5.33, 0.23299, 3, 24, 78.69, -18.89, 0.55872, 25, -46.15, 21.31, 0.2824, 23, 84.58, -125.18, 0.15888, 3, 24, 47.11, -16.78, 0.28286, 25, -66.31, 45.71, 0.3824, 23, 56.47, -110.64, 0.33474, 2, 24, 112.97, -28.06, 0.5954, 23, 112.36, -147.28, 0.4046, 2, 24, 78.31, -24.04, 0.3969, 23, 82.18, -129.75, 0.6031 ], + "hull": 15, + "edges": [ 8, 10, 10, 12, 12, 14, 14, 16, 28, 0, 26, 28, 24, 26, 0, 2, 2, 4, 20, 22, 22, 24, 16, 18, 18, 20, 4, 6, 6, 8 ], + "width": 180, + "height": 215 + } + }, + "hat/hat-back": { + "hat-back": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 3, 0, 1, 2, 3 ], + "vertices": [ 1, 23, -51.19, -50.19, 1, 2, 22, 56.23, -21.15, 0.2791, 23, 16.22, 93.82, 0.7209, 2, 22, 168.23, -21.15, 0.2791, 23, 117.65, 46.34, 0.7209, 1, 23, 50.25, -97.67, 1 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 159, + "height": 112 + } + }, + "hat/hat-front": { + "hat-front": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0, 1, 0 ], + "triangles": [ 1, 2, 3, 1, 3, 0 ], + "vertices": [ 2, 28, 83.32, -0.11, 0.1628, 23, -118.89, -79.23, 0.8372, 2, 22, 7.23, 5.85, 0.2636, 23, -16.72, 139.05, 0.7364, 2, 22, 147.23, 5.85, 0.2636, 23, 110.08, 79.69, 0.7364, 2, 28, 223.32, -0.11, 0.1628, 23, 7.91, -138.58, 0.8372 ], + "hull": 4, + "edges": [ 0, 2, 2, 4, 4, 6, 0, 6 ], + "width": 241, + "height": 140 + } + }, + "stars/star1": { + "star-big": { "width": 44, "height": 60 }, + "star-medium": { "width": 14, "height": 20 }, + "star-small": { "width": 8, "height": 11 } + }, + "stars/star2": { + "star-big": { "width": 44, "height": 60 }, + "star-medium": { "width": 14, "height": 20 }, + "star-small": { "width": 8, "height": 11 } + }, + "stars/star3": { + "star-big": { "width": 44, "height": 60 }, + "star-medium": { "width": 14, "height": 20 }, + "star-small": { "width": 8, "height": 11 } + }, + "stars/star4": { + "star-big": { "width": 44, "height": 60 }, + "star-medium": { "width": 14, "height": 20 }, + "star-small": { "width": 8, "height": 11 } + }, + "stars/star5": { + "star-big": { "width": 44, "height": 60 }, + "star-medium": { "width": 14, "height": 20 }, + "star-small": { "width": 8, "height": 11 } + }, + "stars/star6": { + "star-big": { "width": 44, "height": 60 }, + "star-medium": { "width": 14, "height": 20 }, + "star-small": { "width": 8, "height": 11 } + } + } + } +], +"animations": { + "eyeblink": { + "bones": { + "eyelashes-top-front": { + "translate": [ + { + "curve": [ 0.061, 0, 0.071, -26.84, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -26.84, + "curve": [ 0.282, -26.84, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-top-back": { + "translate": [ + { + "curve": [ 0.061, 0, 0.071, -22.55, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -22.55, + "curve": [ 0.282, -22.55, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-down-front": { + "translate": [ + { + "curve": [ 0.061, 0, 0.071, 12.12, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": 12.12, + "curve": [ 0.282, 12.12, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-down-back": { + "translate": [ + { + "curve": [ 0.061, 0, 0.071, 10.12, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": 10.12, + "curve": [ 0.282, 10.12, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ] + }, + "pupil-front": { + "translate": [ + { + "curve": [ 0.061, 0, 0.071, -6.11, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -6.11, + "curve": [ 0.282, -6.11, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ], + "scale": [ + { + "curve": [ 0.061, 1, 0.071, 0.152, 0.029, 1, 0.071, 1 ] + }, + { + "time": 0.1, + "x": 0.152, + "curve": [ 0.282, 0.152, 0.244, 1, 0.183, 1, 0.25, 1 ] + }, + { "time": 0.3333 } + ] + }, + "pupil-back": { + "translate": [ + { + "curve": [ 0.061, 0, 0.071, -6.11, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -6.11, + "curve": [ 0.282, -6.11, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ], + "scale": [ + { + "curve": [ 0.061, 1, 0.071, 0.152, 0.029, 1, 0.071, 1 ] + }, + { + "time": 0.1, + "x": 0.152, + "curve": [ 0.282, 0.152, 0.244, 1, 0.183, 1, 0.25, 1 ] + }, + { "time": 0.3333 } + ] + } + } + }, + "eyeblink-long": { + "bones": { + "eyelashes-top-front": { + "translate": [ + { + "curve": [ 0.06, 0, 0.071, -26.84, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -26.84, + "curve": [ 0.278, -26.84, 0.246, 0, 0.182, 0, 0.252, 0 ] + }, + { "time": 0.3333, "curve": "stepped" }, + { "time": 4.7 } + ] + }, + "eyelashes-top-back": { + "translate": [ + { + "curve": [ 0.06, 0, 0.071, -22.55, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -22.55, + "curve": [ 0.278, -22.55, 0.246, 0, 0.182, 0, 0.252, 0 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-down-front": { + "translate": [ + { + "curve": [ 0.06, 0, 0.071, 12.12, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": 12.12, + "curve": [ 0.278, 12.12, 0.246, 0, 0.182, 0, 0.252, 0 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-down-back": { + "translate": [ + { + "curve": [ 0.06, 0, 0.071, 10.12, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": 10.12, + "curve": [ 0.278, 10.12, 0.246, 0, 0.182, 0, 0.252, 0 ] + }, + { "time": 0.3333 } + ] + }, + "pupil-front": { + "translate": [ + { + "curve": [ 0.06, 0, 0.071, -6.11, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -6.11, + "curve": [ 0.278, -6.11, 0.246, 0, 0.182, 0, 0.252, 0 ] + }, + { "time": 0.3333 } + ], + "scale": [ + { + "curve": [ 0.06, 1, 0.071, 0.152, 0.029, 1, 0.071, 1 ] + }, + { + "time": 0.1, + "x": 0.152, + "curve": [ 0.278, 0.152, 0.246, 1, 0.182, 1, 0.252, 1 ] + }, + { "time": 0.3333 } + ] + }, + "pupil-back": { + "translate": [ + { + "curve": [ 0.06, 0, 0.071, -6.11, 0.029, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": -6.11, + "curve": [ 0.278, -6.11, 0.246, 0, 0.182, 0, 0.252, 0 ] + }, + { "time": 0.3333 } + ], + "scale": [ + { + "curve": [ 0.06, 1, 0.071, 0.152, 0.029, 1, 0.071, 1 ] + }, + { + "time": 0.1, + "x": 0.152, + "curve": [ 0.278, 0.152, 0.246, 1, 0.182, 1, 0.252, 1 ] + }, + { "time": 0.3333 } + ] + } + } + }, + "stars": { + "slots": { + "stars/star1": { + "attachment": [ + { "time": 0.0667, "name": "star-small" }, + { "time": 0.1333, "name": "star-medium" }, + { "time": 0.2, "name": "star-big" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4 } + ] + }, + "stars/star2": { + "attachment": [ + { "time": 0.0667, "name": "star-small" }, + { "time": 0.1333, "name": "star-medium" }, + { "time": 0.2, "name": "star-big" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4 } + ] + }, + "stars/star3": { + "attachment": [ + { "time": 0.0667, "name": "star-small" }, + { "time": 0.1333, "name": "star-medium" }, + { "time": 0.2, "name": "star-big" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4 } + ] + }, + "stars/star4": { + "attachment": [ + { "time": 0.4, "name": "star-small" }, + { "time": 0.4667, "name": "star-medium" }, + { "time": 0.5333, "name": "star-big" }, + { "time": 0.6, "name": "star-medium" }, + { "time": 0.6667, "name": "star-small" }, + { "time": 0.7333 } + ] + }, + "stars/star5": { + "attachment": [ + { "time": 0.1667, "name": "star-small" }, + { "time": 0.2333, "name": "star-medium" }, + { "time": 0.3, "name": "star-big" }, + { "time": 0.3667, "name": "star-medium" }, + { "time": 0.4333, "name": "star-small" }, + { "time": 0.5 } + ] + }, + "stars/star6": { + "attachment": [ + { "time": 0.4, "name": "star-small" }, + { "time": 0.4667, "name": "star-medium" }, + { "time": 0.5333, "name": "star-big" }, + { "time": 0.6, "name": "star-medium" }, + { "time": 0.6667, "name": "star-small" }, + { "time": 0.7333 } + ] + } + } + }, + "swing": { + "slots": { + "stars/star1": { + "attachment": [ + { "time": 0.0667, "name": "star-small" }, + { "time": 0.1333, "name": "star-medium" }, + { "time": 0.2, "name": "star-big" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4 }, + { "time": 0.8, "name": "star-small" }, + { "time": 0.8667, "name": "star-medium" }, + { "time": 0.9333, "name": "star-big" }, + { "time": 1, "name": "star-medium" }, + { "time": 1.0667, "name": "star-small" }, + { "time": 1.1333 }, + { "time": 1.5333, "name": "star-small" }, + { "time": 1.6, "name": "star-medium" }, + { "time": 1.6667, "name": "star-big" }, + { "time": 1.7333, "name": "star-medium" }, + { "time": 1.8, "name": "star-small" }, + { "time": 1.8667 } + ] + }, + "stars/star2": { + "attachment": [ + { "time": 0.0667, "name": "star-small" }, + { "time": 0.1333, "name": "star-medium" }, + { "time": 0.2, "name": "star-big" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4 }, + { "time": 0.8, "name": "star-small" }, + { "time": 0.8667, "name": "star-medium" }, + { "time": 0.9333, "name": "star-big" }, + { "time": 1, "name": "star-medium" }, + { "time": 1.0667, "name": "star-small" }, + { "time": 1.1333 }, + { "time": 1.5333, "name": "star-small" }, + { "time": 1.6, "name": "star-medium" }, + { "time": 1.6667, "name": "star-big" }, + { "time": 1.7333, "name": "star-medium" }, + { "time": 1.8, "name": "star-small" }, + { "time": 1.8667 } + ] + }, + "stars/star3": { + "attachment": [ + { "time": 0.0667, "name": "star-small" }, + { "time": 0.1333, "name": "star-medium" }, + { "time": 0.2, "name": "star-big" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4 }, + { "time": 0.8, "name": "star-small" }, + { "time": 0.8667, "name": "star-medium" }, + { "time": 0.9333, "name": "star-big" }, + { "time": 1, "name": "star-medium" }, + { "time": 1.0667, "name": "star-small" }, + { "time": 1.1333 }, + { "time": 1.5333, "name": "star-small" }, + { "time": 1.6, "name": "star-medium" }, + { "time": 1.6667, "name": "star-big" }, + { "time": 1.7333, "name": "star-medium" }, + { "time": 1.8, "name": "star-small" }, + { "time": 1.8667 } + ] + }, + "stars/star4": { + "attachment": [ + { "time": 0.4, "name": "star-small" }, + { "time": 0.4667, "name": "star-medium" }, + { "time": 0.5333, "name": "star-big" }, + { "time": 0.6, "name": "star-medium" }, + { "time": 0.6667, "name": "star-small" }, + { "time": 0.7333 }, + { "time": 1.1333, "name": "star-small" }, + { "time": 1.2, "name": "star-medium" }, + { "time": 1.2667, "name": "star-big" }, + { "time": 1.3333, "name": "star-medium" }, + { "time": 1.4, "name": "star-small" }, + { "time": 1.4667 }, + { "time": 1.8667, "name": "star-small" }, + { "time": 1.9333, "name": "star-medium" }, + { "time": 2, "name": "star-big" }, + { "time": 2.0667, "name": "star-medium" }, + { "time": 2.1333, "name": "star-small" }, + { "time": 2.2 } + ] + }, + "stars/star5": { + "attachment": [ + { "time": 0.1667, "name": "star-small" }, + { "time": 0.2333, "name": "star-medium" }, + { "time": 0.3, "name": "star-big" }, + { "time": 0.3667, "name": "star-medium" }, + { "time": 0.4333, "name": "star-small" }, + { "time": 0.5 }, + { "time": 0.9, "name": "star-small" }, + { "time": 0.9667, "name": "star-medium" }, + { "time": 1.0333, "name": "star-big" }, + { "time": 1.1, "name": "star-medium" }, + { "time": 1.1667, "name": "star-small" }, + { "time": 1.2333 }, + { "time": 1.6333, "name": "star-small" }, + { "time": 1.7, "name": "star-medium" }, + { "time": 1.7667, "name": "star-big" }, + { "time": 1.8333, "name": "star-medium" }, + { "time": 1.9, "name": "star-small" }, + { "time": 1.9667 } + ] + }, + "stars/star6": { + "attachment": [ + { "time": 0.4, "name": "star-small" }, + { "time": 0.4667, "name": "star-medium" }, + { "time": 0.5333, "name": "star-big" }, + { "time": 0.6, "name": "star-medium" }, + { "time": 0.6667, "name": "star-small" }, + { "time": 0.7333 }, + { "time": 1.1333, "name": "star-small" }, + { "time": 1.2, "name": "star-medium" }, + { "time": 1.2667, "name": "star-big" }, + { "time": 1.3333, "name": "star-medium" }, + { "time": 1.4, "name": "star-small" }, + { "time": 1.4667 }, + { "time": 1.8667, "name": "star-small" }, + { "time": 1.9333, "name": "star-medium" }, + { "time": 2, "name": "star-big" }, + { "time": 2.0667, "name": "star-medium" }, + { "time": 2.1333, "name": "star-small" }, + { "time": 2.2 } + ] + } + }, + "bones": { + "swing-top": { + "rotate": [ + { + "value": -13.18, + "curve": [ 0.607, -13.18, 0.733, 15.86 ] + }, + { + "time": 1.1, + "value": 15.86, + "curve": [ 1.707, 15.86, 1.833, -13.18 ] + }, + { "time": 2.2, "value": -13.18 } + ] + }, + "swing-bottom": { + "rotate": [ + { + "value": 0.37, + "curve": [ 0.145, -6.53, 0.258, -13.18 ] + }, + { + "time": 0.4333, + "value": -13.18, + "curve": [ 1.04, -13.18, 1.166, 15.86 ] + }, + { + "time": 1.5333, + "value": 15.86, + "curve": [ 1.851, 15.86, 2.043, 7.96 ] + }, + { "time": 2.2, "value": 0.37 } + ] + }, + "body-up": { + "rotate": [ + { + "value": 11.88, + "curve": [ 0.368, 11.88, 0.732, -7.09 ] + }, + { + "time": 1.1, + "value": -7.09, + "curve": [ 1.468, -7.09, 1.832, 11.88 ] + }, + { "time": 2.2, "value": 11.88 } + ] + }, + "neck": { + "rotate": [ + { + "value": -14.54, + "curve": [ 0.357, -14.54, 0.709, 16.44 ] + }, + { + "time": 1.0667, + "value": 16.44, + "curve": [ 1.445, 16.44, 1.822, -14.54 ] + }, + { "time": 2.2, "value": -14.54 } + ] + }, + "face-control": { + "translate": [ + { "y": 14.53 }, + { "time": 1.0333, "x": -1.18, "y": -10.95 }, + { "time": 2.2, "y": 14.53 } + ] + }, + "pupil-front": { + "translate": [ + {}, + { "time": 1.1, "x": -7.23, "y": -2.49 }, + { "time": 2.2 } + ] + }, + "pupil-back": { + "translate": [ + {}, + { "time": 1.1, "x": -7.23, "y": -2.49 }, + { "time": 2.2 } + ] + }, + "eyelashes-top-front": { + "translate": [ + {}, + { "time": 1, "x": -7.38 }, + { "time": 2.2 } + ] + }, + "eyelashes-top-back": { + "translate": [ + {}, + { "time": 1, "x": -7.38 }, + { "time": 2.2 } + ] + }, + "mouth": { + "scale": [ + {}, + { "time": 0.9333, "x": 0.848, "y": 1.067 }, + { "time": 2.2 } + ] + }, + "face": { + "translate": [ + {}, + { "time": 0.6667, "x": -13.93, "y": -16.25 }, + { "time": 1.6, "x": 5.02, "y": -6.3 }, + { "time": 2.2 } + ] + }, + "wing-front-tip": { + "rotate": [ + { + "value": -5.65, + "curve": [ 0.148, -14.43, 0.293, -30.34 ] + }, + { + "time": 0.4667, + "value": -30.34, + "curve": [ 0.661, -30.34, 0.822, -11.79 ] + }, + { "time": 1 }, + { + "time": 1.5, + "value": 33.17, + "curve": [ 1.691, 33.17, 1.864, 0 ] + }, + { + "time": 2.0333, + "curve": [ 2.091, 0, 2.146, -2.29 ] + }, + { "time": 2.2, "value": -5.65 } + ] + }, + "wing-front": { + "rotate": [ + { "value": -28.71 }, + { "time": 1, "value": 12.5 }, + { "time": 2.2, "value": -28.71 } + ], + "scale": [ + { "y": 0.497 }, + { "time": 1 }, + { "time": 2.2, "y": 0.497 } + ] + }, + "wing-back": { + "rotate": [ + { + "value": 31.82, + "curve": [ 0.359, 31.82, 0.667, 15.27 ] + }, + { + "time": 1, + "value": 15.27, + "curve": [ 1.37, 15.27, 1.83, 31.82 ] + }, + { "time": 2.2, "value": 31.82 } + ], + "scale": [ + { + "x": 1.248, + "y": 0.376, + "curve": [ 0.359, 1.248, 0.667, 1, 0.359, 0.376, 0.667, 1 ] + }, + { + "time": 1, + "curve": [ 1.37, 1, 1.83, 1.248, 1.37, 1, 1.83, 0.376 ] + }, + { "time": 2.2, "x": 1.248, "y": 0.376 } + ] + }, + "wing-back-tip": { + "rotate": [ + { + "value": 3.37, + "curve": [ 0.148, 8.61, 0.293, 18.1 ] + }, + { + "time": 0.4667, + "value": 18.1, + "curve": [ 0.661, 18.1, 0.822, 10.98 ] + }, + { "time": 1 }, + { "time": 1.5667, "value": 11.59 }, + { "time": 2.2, "value": 3.37 } + ], + "scale": [ + { + "x": 1.122, + "curve": [ 0.157, 1.173, 0.295, 1.246, 0.157, 1, 0.295, 1 ] + }, + { + "time": 0.4667, + "x": 1.222, + "curve": [ 0.647, 1.198, 0.822, 0.499, 0.647, 1, 0.822, 1 ] + }, + { + "time": 1, + "x": 0.499, + "curve": [ 1.175, 0.499, 2.151, 1.105, 1.175, 1, 2.151, 1 ] + }, + { "time": 2.2, "x": 1.122 } + ] + }, + "cloud": { + "rotate": [ + { + "value": -0.49, + "curve": [ 0.135, -1.47, 0.268, -2.39 ] + }, + { + "time": 0.4, + "value": -2.78, + "curve": [ 0.445, -2.91, 0.489, -3 ] + }, + { + "time": 0.5333, + "value": -3, + "curve": [ 0.867, -3, 1.2, 3 ] + }, + { + "time": 1.5333, + "value": 3, + "curve": [ 1.756, 3, 1.98, 1.16 ] + }, + { "time": 2.2, "value": -0.49 } + ], + "translate": [ + { + "x": -150, + "curve": [ 0.557, -150, 0.55, 146.39, 0.333, 0, 0.667, 0 ] + }, + { + "time": 1, + "x": 150, + "curve": [ 1.668, 155.35, 1.8, -150, 1.4, 0, 1.8, 0 ] + }, + { "time": 2.2, "x": -150 } + ] + }, + "rope-back": { + "translate": [ + {}, + { "time": 1, "y": -1.11 }, + { "time": 2.2 } + ] + }, + "bench-front": { + "translate": [ + {}, + { "time": 1, "y": 120.63 }, + { "time": 2.2 } + ] + }, + "bench-back": { + "translate": [ + {}, + { "time": 1, "x": -11.37 }, + { "time": 2.2 } + ] + }, + "rope-front": { + "translate": [ + {}, + { "time": 1, "y": 91.13 }, + { "time": 2.2 } + ] + } + } + }, + "wind-idle": { + "slots": { + "stars/star1": { + "attachment": [ + { "time": 0.1333, "name": "star-small" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.4, "name": "star-big" }, + { "time": 0.5, "name": "star-medium" }, + { "time": 0.6333, "name": "star-small" }, + { "time": 0.7667 }, + { "time": 1.6667, "name": "star-small" }, + { "time": 1.7333, "name": "star-medium" }, + { "time": 1.8, "name": "star-big" }, + { "time": 1.8667, "name": "star-medium" }, + { "time": 1.9333, "name": "star-small" }, + { "time": 2 }, + { "time": 2.4667, "name": "star-small" }, + { "time": 2.5333, "name": "star-medium" }, + { "time": 2.5667, "name": "star-big" }, + { "time": 2.6333, "name": "star-medium" }, + { "time": 2.7, "name": "star-small" }, + { "time": 2.7667 }, + { "time": 3.4, "name": "star-small" }, + { "time": 3.5333, "name": "star-medium" }, + { "time": 3.6333, "name": "star-big" }, + { "time": 3.7667, "name": "star-medium" }, + { "time": 3.9, "name": "star-small" }, + { "time": 4.0333 }, + { "time": 4.9333, "name": "star-small" }, + { "time": 5, "name": "star-medium" }, + { "time": 5.0667, "name": "star-big" }, + { "time": 5.1333, "name": "star-medium" }, + { "time": 5.2, "name": "star-small" }, + { "time": 5.2667 }, + { "time": 5.7, "name": "star-small" }, + { "time": 5.7667, "name": "star-medium" }, + { "time": 5.8333, "name": "star-big" }, + { "time": 5.9, "name": "star-medium" }, + { "time": 5.9667, "name": "star-small" }, + { "time": 6.0333 }, + { "time": 6.6333, "name": "star-small" }, + { "time": 6.7333, "name": "star-medium" }, + { "time": 6.8667, "name": "star-big" }, + { "time": 7, "name": "star-medium" }, + { "time": 7.1333, "name": "star-small" }, + { "time": 7.2667 }, + { "time": 8.1667, "name": "star-small" }, + { "time": 8.2333, "name": "star-medium" }, + { "time": 8.3, "name": "star-big" }, + { "time": 8.3667, "name": "star-medium" }, + { "time": 8.4333, "name": "star-small" }, + { "time": 8.5 }, + { "time": 8.9333, "name": "star-small" }, + { "time": 9, "name": "star-medium" }, + { "time": 9.0667, "name": "star-big" }, + { "time": 9.1333, "name": "star-medium" }, + { "time": 9.2, "name": "star-small" }, + { "time": 9.2667 } + ] + }, + "stars/star2": { + "attachment": [ + { "time": 0.1333, "name": "star-small" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.4, "name": "star-big" }, + { "time": 0.5, "name": "star-medium" }, + { "time": 0.6333, "name": "star-small" }, + { "time": 0.7667 }, + { "time": 1.6667, "name": "star-small" }, + { "time": 1.7333, "name": "star-medium" }, + { "time": 1.8, "name": "star-big" }, + { "time": 1.8667, "name": "star-medium" }, + { "time": 1.9333, "name": "star-small" }, + { "time": 2 }, + { "time": 2.4667, "name": "star-small" }, + { "time": 2.5333, "name": "star-medium" }, + { "time": 2.5667, "name": "star-big" }, + { "time": 2.6333, "name": "star-medium" }, + { "time": 2.7, "name": "star-small" }, + { "time": 2.7667 }, + { "time": 3.4, "name": "star-small" }, + { "time": 3.5333, "name": "star-medium" }, + { "time": 3.6333, "name": "star-big" }, + { "time": 3.7667, "name": "star-medium" }, + { "time": 3.9, "name": "star-small" }, + { "time": 4.0333 }, + { "time": 4.9333, "name": "star-small" }, + { "time": 5, "name": "star-medium" }, + { "time": 5.0667, "name": "star-big" }, + { "time": 5.1333, "name": "star-medium" }, + { "time": 5.2, "name": "star-small" }, + { "time": 5.2667 }, + { "time": 5.7, "name": "star-small" }, + { "time": 5.7667, "name": "star-medium" }, + { "time": 5.8333, "name": "star-big" }, + { "time": 5.9, "name": "star-medium" }, + { "time": 5.9667, "name": "star-small" }, + { "time": 6.0333 }, + { "time": 6.6333, "name": "star-small" }, + { "time": 6.7333, "name": "star-medium" }, + { "time": 6.8667, "name": "star-big" }, + { "time": 7, "name": "star-medium" }, + { "time": 7.1333, "name": "star-small" }, + { "time": 7.2667 }, + { "time": 8.1667, "name": "star-small" }, + { "time": 8.2333, "name": "star-medium" }, + { "time": 8.3, "name": "star-big" }, + { "time": 8.3667, "name": "star-medium" }, + { "time": 8.4333, "name": "star-small" }, + { "time": 8.5 }, + { "time": 8.9333, "name": "star-small" }, + { "time": 9, "name": "star-medium" }, + { "time": 9.0667, "name": "star-big" }, + { "time": 9.1333, "name": "star-medium" }, + { "time": 9.2, "name": "star-small" }, + { "time": 9.2667 } + ] + }, + "stars/star3": { + "attachment": [ + { "time": 0.1333, "name": "star-small" }, + { "time": 0.2667, "name": "star-medium" }, + { "time": 0.4, "name": "star-big" }, + { "time": 0.5, "name": "star-medium" }, + { "time": 0.6333, "name": "star-small" }, + { "time": 0.7667 }, + { "time": 1.6667, "name": "star-small" }, + { "time": 1.7333, "name": "star-medium" }, + { "time": 1.8, "name": "star-big" }, + { "time": 1.8667, "name": "star-medium" }, + { "time": 1.9333, "name": "star-small" }, + { "time": 2 }, + { "time": 2.4667, "name": "star-small" }, + { "time": 2.5333, "name": "star-medium" }, + { "time": 2.5667, "name": "star-big" }, + { "time": 2.6333, "name": "star-medium" }, + { "time": 2.7, "name": "star-small" }, + { "time": 2.7667 }, + { "time": 3.4, "name": "star-small" }, + { "time": 3.5333, "name": "star-medium" }, + { "time": 3.6333, "name": "star-big" }, + { "time": 3.7667, "name": "star-medium" }, + { "time": 3.9, "name": "star-small" }, + { "time": 4.0333 }, + { "time": 4.9333, "name": "star-small" }, + { "time": 5, "name": "star-medium" }, + { "time": 5.0667, "name": "star-big" }, + { "time": 5.1333, "name": "star-medium" }, + { "time": 5.2, "name": "star-small" }, + { "time": 5.2667 }, + { "time": 5.7, "name": "star-small" }, + { "time": 5.7667, "name": "star-medium" }, + { "time": 5.8333, "name": "star-big" }, + { "time": 5.9, "name": "star-medium" }, + { "time": 5.9667, "name": "star-small" }, + { "time": 6.0333 }, + { "time": 6.6333, "name": "star-small" }, + { "time": 6.7333, "name": "star-medium" }, + { "time": 6.8667, "name": "star-big" }, + { "time": 7, "name": "star-medium" }, + { "time": 7.1333, "name": "star-small" }, + { "time": 7.2667 }, + { "time": 8.1667, "name": "star-small" }, + { "time": 8.2333, "name": "star-medium" }, + { "time": 8.3, "name": "star-big" }, + { "time": 8.3667, "name": "star-medium" }, + { "time": 8.4333, "name": "star-small" }, + { "time": 8.5 }, + { "time": 8.9333, "name": "star-small" }, + { "time": 9, "name": "star-medium" }, + { "time": 9.0667, "name": "star-big" }, + { "time": 9.1333, "name": "star-medium" }, + { "time": 9.2, "name": "star-small" }, + { "time": 9.2667 } + ] + }, + "stars/star4": { + "attachment": [ + { "time": 0.7667, "name": "star-small" }, + { "time": 0.9, "name": "star-medium" }, + { "time": 1.0333, "name": "star-big" }, + { "time": 1.1667, "name": "star-medium" }, + { "time": 1.2667, "name": "star-small" }, + { "time": 1.4 }, + { "time": 2, "name": "star-small" }, + { "time": 2.0667, "name": "star-medium" }, + { "time": 2.1333, "name": "star-big" }, + { "time": 2.2, "name": "star-medium" }, + { "time": 2.2667, "name": "star-small" }, + { "time": 2.3333 }, + { "time": 2.7667, "name": "star-small" }, + { "time": 2.8333, "name": "star-medium" }, + { "time": 2.9, "name": "star-big" }, + { "time": 2.9667, "name": "star-medium" }, + { "time": 3.0333, "name": "star-small" }, + { "time": 3.1 }, + { "time": 4.0333, "name": "star-small" }, + { "time": 4.1667, "name": "star-medium" }, + { "time": 4.3, "name": "star-big" }, + { "time": 4.4333, "name": "star-medium" }, + { "time": 4.5333, "name": "star-small" }, + { "time": 4.6333 }, + { "time": 5.2667, "name": "star-small" }, + { "time": 5.3333, "name": "star-medium" }, + { "time": 5.4, "name": "star-big" }, + { "time": 5.4667, "name": "star-medium" }, + { "time": 5.5333, "name": "star-small" }, + { "time": 5.6 }, + { "time": 6.0333, "name": "star-small" }, + { "time": 6.1, "name": "star-medium" }, + { "time": 6.1667, "name": "star-big" }, + { "time": 6.2333, "name": "star-medium" }, + { "time": 6.3, "name": "star-small" }, + { "time": 6.3667 }, + { "time": 7.2667, "name": "star-small" }, + { "time": 7.4, "name": "star-medium" }, + { "time": 7.5333, "name": "star-big" }, + { "time": 7.6667, "name": "star-medium" }, + { "time": 7.7333, "name": "star-small" }, + { "time": 7.8667 }, + { "time": 8.5, "name": "star-small" }, + { "time": 8.5667, "name": "star-medium" }, + { "time": 8.6333, "name": "star-big" }, + { "time": 8.7, "name": "star-medium" }, + { "time": 8.7333, "name": "star-small" }, + { "time": 8.8 }, + { "time": 9.2667, "name": "star-small" }, + { "time": 9.3333, "name": "star-medium" }, + { "time": 9.4, "name": "star-big" }, + { "time": 9.4667, "name": "star-medium" }, + { "time": 9.5333, "name": "star-small" }, + { "time": 9.6 } + ] + }, + "stars/star5": { + "attachment": [ + { "time": 0.3333, "name": "star-small" }, + { "time": 0.4667, "name": "star-medium" }, + { "time": 0.5667, "name": "star-big" }, + { "time": 0.7, "name": "star-medium" }, + { "time": 0.8333, "name": "star-small" }, + { "time": 0.9667 }, + { "time": 1.7667, "name": "star-small" }, + { "time": 1.8333, "name": "star-medium" }, + { "time": 1.9, "name": "star-big" }, + { "time": 1.9667, "name": "star-medium" }, + { "time": 2.0333, "name": "star-small" }, + { "time": 2.1 }, + { "time": 2.5667, "name": "star-small" }, + { "time": 2.6, "name": "star-medium" }, + { "time": 2.6667, "name": "star-big" }, + { "time": 2.7333, "name": "star-medium" }, + { "time": 2.8, "name": "star-small" }, + { "time": 2.8667 }, + { "time": 3.6, "name": "star-small" }, + { "time": 3.7, "name": "star-medium" }, + { "time": 3.8333, "name": "star-big" }, + { "time": 3.9667, "name": "star-medium" }, + { "time": 4.1, "name": "star-small" }, + { "time": 4.2333 }, + { "time": 5.0333, "name": "star-small" }, + { "time": 5.1, "name": "star-medium" }, + { "time": 5.1667, "name": "star-big" }, + { "time": 5.2333, "name": "star-medium" }, + { "time": 5.3, "name": "star-small" }, + { "time": 5.3667 }, + { "time": 5.8, "name": "star-small" }, + { "time": 5.8667, "name": "star-medium" }, + { "time": 5.9333, "name": "star-big" }, + { "time": 6, "name": "star-medium" }, + { "time": 6.0667, "name": "star-small" }, + { "time": 6.1333 }, + { "time": 6.8, "name": "star-small" }, + { "time": 6.9333, "name": "star-medium" }, + { "time": 7.0667, "name": "star-big" }, + { "time": 7.2, "name": "star-medium" }, + { "time": 7.3333, "name": "star-small" }, + { "time": 7.4667 }, + { "time": 8.2667, "name": "star-small" }, + { "time": 8.3333, "name": "star-medium" }, + { "time": 8.4, "name": "star-big" }, + { "time": 8.4667, "name": "star-medium" }, + { "time": 8.5333, "name": "star-small" }, + { "time": 8.6 }, + { "time": 9.0333, "name": "star-small" }, + { "time": 9.1, "name": "star-medium" }, + { "time": 9.1667, "name": "star-big" }, + { "time": 9.2333, "name": "star-medium" }, + { "time": 9.3, "name": "star-small" }, + { "time": 9.3667 } + ] + }, + "stars/star6": { + "attachment": [ + { "time": 0.7667, "name": "star-small" }, + { "time": 0.9, "name": "star-medium" }, + { "time": 1.0333, "name": "star-big" }, + { "time": 1.1667, "name": "star-medium" }, + { "time": 1.2667, "name": "star-small" }, + { "time": 1.4 }, + { "time": 2, "name": "star-small" }, + { "time": 2.0667, "name": "star-medium" }, + { "time": 2.1333, "name": "star-big" }, + { "time": 2.2, "name": "star-medium" }, + { "time": 2.2667, "name": "star-small" }, + { "time": 2.3333 }, + { "time": 2.7667, "name": "star-small" }, + { "time": 2.8333, "name": "star-medium" }, + { "time": 2.9, "name": "star-big" }, + { "time": 2.9667, "name": "star-medium" }, + { "time": 3.0333, "name": "star-small" }, + { "time": 3.1 }, + { "time": 4.0333, "name": "star-small" }, + { "time": 4.1667, "name": "star-medium" }, + { "time": 4.3, "name": "star-big" }, + { "time": 4.4333, "name": "star-medium" }, + { "time": 4.5333, "name": "star-small" }, + { "time": 4.6333 }, + { "time": 5.2667, "name": "star-small" }, + { "time": 5.3333, "name": "star-medium" }, + { "time": 5.4, "name": "star-big" }, + { "time": 5.4667, "name": "star-medium" }, + { "time": 5.5333, "name": "star-small" }, + { "time": 5.6 }, + { "time": 6.0333, "name": "star-small" }, + { "time": 6.1, "name": "star-medium" }, + { "time": 6.1667, "name": "star-big" }, + { "time": 6.2333, "name": "star-medium" }, + { "time": 6.3, "name": "star-small" }, + { "time": 6.3667 }, + { "time": 7.2667, "name": "star-small" }, + { "time": 7.4, "name": "star-medium" }, + { "time": 7.5333, "name": "star-big" }, + { "time": 7.6667, "name": "star-medium" }, + { "time": 7.7333, "name": "star-small" }, + { "time": 7.8667 }, + { "time": 8.5, "name": "star-small" }, + { "time": 8.5667, "name": "star-medium" }, + { "time": 8.6333, "name": "star-big" }, + { "time": 8.7, "name": "star-medium" }, + { "time": 8.7333, "name": "star-small" }, + { "time": 8.8 }, + { "time": 9.2667, "name": "star-small" }, + { "time": 9.3333, "name": "star-medium" }, + { "time": 9.4, "name": "star-big" }, + { "time": 9.4667, "name": "star-medium" }, + { "time": 9.5333, "name": "star-small" }, + { "time": 9.6 } + ] + } + }, + "bones": { + "body-up": { + "rotate": [ + { + "time": 2.6333, + "curve": [ 2.822, 1.06, 3.011, 3.17 ] + }, + { "time": 3.2, "value": 3.17, "curve": "stepped" }, + { + "time": 9, + "value": 3.17, + "curve": [ 9.2, 3.17, 9.4, 1.06 ] + }, + { + "time": 9.6, + "curve": [ 9.611, -0.06, 9.622, 0 ] + }, + { "time": 9.6333 } + ], + "translate": [ + { + "curve": [ 0.311, -1.37, 0.624, 10, 0.311, 0, 0.624, 0 ] + }, + { + "time": 0.9333, + "x": 10, + "curve": [ 1.691, 10, 2.444, 0, 1.691, 0, 2.444, 0 ] + }, + { + "time": 3.2, + "curve": [ 3.509, 0, 3.824, 10, 3.509, 0, 3.824, 0 ] + }, + { + "time": 4.1333, + "x": 10, + "curve": [ 4.891, 10, 5.642, 3.33, 4.891, 0, 5.642, 0 ] + }, + { "time": 6.4, "curve": "stepped" }, + { + "time": 6.4333, + "curve": [ 6.743, 0, 7.057, 10, 6.743, 0, 7.057, 0 ] + }, + { + "time": 7.3667, + "x": 10, + "curve": [ 8.124, 10, 8.876, 3.33, 8.124, 0, 8.876, 0 ] + }, + { "time": 9.6333 } + ] + }, + "wing-front": { + "rotate": [ + { "time": 0.8333 }, + { "time": 1.7333, "value": -4.1 }, + { "time": 2.6667 }, + { "time": 3.0333, "value": -28.71 }, + { "time": 3.3667, "curve": "stepped" }, + { "time": 3.4667 }, + { "time": 4.0333, "value": -28.71 }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 5.8667, + "curve": [ 6.256, -1.37, 6.644, -4.1 ] + }, + { + "time": 7.0333, + "value": -4.1, + "curve": [ 7.478, -4.1, 7.922, -1.37 ] + }, + { "time": 8.3667 }, + { "time": 8.9333, "value": -28.71 }, + { "time": 9.6 } + ], + "scale": [ + { "time": 0.8333 }, + { "time": 1.7333, "y": 0.928 }, + { "time": 2.6667 }, + { "time": 3.0333, "y": 0.497 }, + { "time": 3.3667, "curve": "stepped" }, + { "time": 3.4667 }, + { "time": 4.0333, "y": 0.497 }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 5.8667, + "curve": [ 6.256, 1, 6.644, 1, 6.256, 0.976, 6.644, 0.928 ] + }, + { + "time": 7.0333, + "y": 0.928, + "curve": [ 7.478, 1, 7.922, 1, 7.478, 0.928, 7.922, 0.976 ] + }, + { "time": 8.3667 }, + { "time": 8.9333, "y": 0.497 }, + { "time": 9.6 } + ] + }, + "wing-front-tip": { + "rotate": [ + { "time": 0.9667 }, + { + "time": 2.0667, + "value": -7.42, + "curve": [ 2.097, -3.69, 2.451, -6.54 ] + }, + { "time": 2.6667 }, + { + "time": 2.8333, + "value": 33.17, + "curve": [ 2.891, 33.17, 2.916, 0 ] + }, + { + "time": 2.9667, + "curve": [ 3.029, 0, 3.128, -30.34 ] + }, + { + "time": 3.2, + "value": -30.34, + "curve": [ 3.258, -30.34, 3.317, 0 ] + }, + { "time": 3.3667, "curve": "stepped" }, + { "time": 3.4667 }, + { + "time": 3.6667, + "value": 33.17, + "curve": [ 3.755, 33.17, 3.824, 0 ] + }, + { + "time": 3.9333, + "curve": [ 4.067, 0, 4.245, -30.34 ] + }, + { + "time": 4.4, + "value": -30.34, + "curve": [ 4.525, -30.34, 4.631, 0 ] + }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 6.1333, + "curve": [ 6.522, -2.47, 7.24, -14.83 ] + }, + { + "time": 7.3, + "value": -7.42, + "curve": [ 7.331, -3.63, 7.969, -6.64 ] + }, + { "time": 8.3667 }, + { + "time": 8.6333, + "value": 33.17, + "curve": [ 8.731, 33.17, 8.78, 0 ] + }, + { + "time": 8.8667, + "curve": [ 8.973, 0, 9.144, -30.34 ] + }, + { + "time": 9.2667, + "value": -30.34, + "curve": [ 9.366, -30.34, 9.485, 0 ] + }, + { "time": 9.6 } + ] + }, + "wing-back-tip": { + "rotate": [ + { "time": 0.9667 }, + { + "time": 2.0667, + "value": 4.42, + "curve": [ 2.097, 2.2, 2.451, 3.9 ] + }, + { "time": 2.6667 }, + { + "time": 2.8667, + "value": -11.49, + "curve": [ 2.87, -11.49, 2.922, 0 ] + }, + { + "time": 2.9667, + "curve": [ 3.029, 0, 3.128, 18.1 ] + }, + { + "time": 3.2, + "value": 18.1, + "curve": [ 3.258, 18.1, 3.317, 0 ] + }, + { "time": 3.3667, "curve": "stepped" }, + { "time": 3.4667 }, + { + "time": 3.7, + "value": -11.49, + "curve": [ 3.705, -11.49, 3.837, 0 ] + }, + { + "time": 3.9333, + "curve": [ 4.067, 0, 4.245, 18.1 ] + }, + { + "time": 4.4, + "value": 18.1, + "curve": [ 4.525, 18.1, 4.631, 0 ] + }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 6.1333, + "curve": [ 6.522, 1.47, 7.24, 8.85 ] + }, + { + "time": 7.3, + "value": 4.42, + "curve": [ 7.331, 2.17, 7.969, 3.96 ] + }, + { "time": 8.3667 }, + { + "time": 8.6333, + "value": -11.49, + "curve": [ 8.639, -11.49, 8.79, 0 ] + }, + { + "time": 8.8667, + "curve": [ 8.973, 0, 9.144, 18.1 ] + }, + { + "time": 9.2667, + "value": 18.1, + "curve": [ 9.366, 18.1, 9.485, 0 ] + }, + { "time": 9.6 } + ], + "scale": [ + { "time": 0.9667 }, + { + "time": 2.0667, + "x": 1.043, + "curve": [ 2.096, 1.021, 2.451, 1, 2.096, 1, 2.451, 1 ] + }, + { + "time": 2.6667, + "curve": [ 2.718, 1, 2.816, 0.807, 2.718, 1, 2.816, 1 ] + }, + { + "time": 2.8667, + "x": 0.807, + "curve": [ 2.912, 0.807, 2.923, 1.061, 2.912, 1, 2.923, 1 ] + }, + { + "time": 2.9667, + "x": 1.081, + "curve": [ 3.037, 1.112, 3.131, 1.254, 3.037, 1, 3.131, 1 ] + }, + { + "time": 3.2, + "x": 1.222, + "curve": [ 3.254, 1.198, 3.317, 1, 3.254, 1, 3.317, 1 ] + }, + { "time": 3.3667, "curve": "stepped" }, + { + "time": 3.4667, + "curve": [ 3.545, 1, 3.623, 0.807, 3.545, 1, 3.623, 1 ] + }, + { + "time": 3.7, + "x": 0.807, + "curve": [ 3.769, 0.807, 3.84, 1.061, 3.769, 1, 3.84, 1 ] + }, + { + "time": 3.9333, + "x": 1.081, + "curve": [ 4.085, 1.112, 4.252, 1.254, 4.085, 1, 4.252, 1 ] + }, + { + "time": 4.4, + "x": 1.222, + "curve": [ 4.517, 1.198, 4.618, 1, 4.517, 1, 4.618, 1 ] + }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 6.1333, + "curve": [ 6.522, 1.014, 7.244, 1.085, 6.522, 1, 6.911, 1 ] + }, + { + "time": 7.3, + "x": 1.043, + "curve": [ 7.329, 1.02, 7.969, 1, 7.329, 1, 7.969, 1 ] + }, + { + "time": 8.3667, + "curve": [ 8.454, 1, 8.548, 0.807, 8.454, 1, 8.548, 1 ] + }, + { + "time": 8.6333, + "x": 0.807, + "curve": [ 8.71, 0.807, 8.793, 1.061, 8.71, 1, 8.793, 1 ] + }, + { + "time": 8.8667, + "x": 1.081, + "curve": [ 8.987, 1.112, 9.149, 1.254, 8.987, 1, 9.149, 1 ] + }, + { + "time": 9.2667, + "x": 1.222, + "curve": [ 9.359, 1.198, 9.47, 1, 9.359, 1, 9.47, 1 ] + }, + { "time": 9.6 } + ] + }, + "wing-back": { + "rotate": [ + { "time": 0.8333 }, + { + "time": 1.9333, + "value": 1.94, + "curve": [ 1.967, 0.82, 2.422, 0 ] + }, + { + "time": 2.6667, + "curve": [ 2.778, 0, 2.922, 31.82 ] + }, + { + "time": 3.0333, + "value": 31.82, + "curve": [ 3.141, 31.82, 3.254, 0 ] + }, + { "time": 3.3667, "curve": "stepped" }, + { + "time": 3.4667, + "curve": [ 3.637, 0, 3.795, 31.82 ] + }, + { + "time": 4.0333, + "value": 31.82, + "curve": [ 4.265, 31.82, 4.502, 0 ] + }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 5.8667, + "curve": [ 6.256, 0.65, 6.975, 3.88 ] + }, + { + "time": 7.0333, + "value": 1.94, + "curve": [ 7.067, 0.82, 7.922, 0 ] + }, + { + "time": 8.3667, + "curve": [ 8.556, 0, 8.744, 31.82 ] + }, + { + "time": 8.9333, + "value": 31.82, + "curve": [ 9.117, 31.82, 9.34, 0 ] + }, + { "time": 9.6 } + ], + "scale": [ + { "time": 0.8333 }, + { + "time": 1.9333, + "x": 1.015, + "y": 0.962, + "curve": [ 1.967, 1.006, 2.422, 1, 1.967, 0.984, 2.422, 1 ] + }, + { + "time": 2.6667, + "curve": [ 2.778, 1, 2.922, 1.248, 2.778, 1, 2.922, 0.376 ] + }, + { + "time": 3.0333, + "x": 1.248, + "y": 0.376, + "curve": [ 3.141, 1.248, 3.254, 1, 3.141, 0.376, 3.254, 1 ] + }, + { "time": 3.3667, "curve": "stepped" }, + { + "time": 3.4667, + "curve": [ 3.637, 1, 3.795, 1.248, 3.637, 1, 3.795, 0.376 ] + }, + { + "time": 4.0333, + "x": 1.248, + "y": 0.376, + "curve": [ 4.265, 1.248, 4.502, 1, 4.265, 0.376, 4.502, 1 ] + }, + { "time": 4.7333, "curve": "stepped" }, + { + "time": 5.8667, + "curve": [ 6.256, 1.005, 6.975, 1.03, 6.256, 0.987, 6.975, 0.924 ] + }, + { + "time": 7.0333, + "x": 1.015, + "y": 0.962, + "curve": [ 7.067, 1.006, 7.922, 1, 7.067, 0.984, 7.922, 1 ] + }, + { + "time": 8.3667, + "curve": [ 8.556, 1, 8.744, 1.248, 8.556, 1, 8.744, 0.376 ] + }, + { + "time": 8.9333, + "x": 1.248, + "y": 0.376, + "curve": [ 9.117, 1.248, 9.34, 1, 9.117, 0.376, 9.34, 1 ] + }, + { "time": 9.6 } + ] + }, + "pupil-front": { + "translate": [ + { + "x": -9.97, + "curve": [ 0.033, -9.97, 0.067, -6.11, 0.033, 0, 0.067, 0 ] + }, + { + "time": 0.1, + "x": -6.11, + "curve": [ 0.282, -6.11, 0.256, -9.97, 0.183, 0, 0.256, 0 ] + }, + { "time": 0.3333, "x": -9.97, "curve": "stepped" }, + { "time": 1.4333, "x": -9.97 }, + { "time": 1.6333, "x": -9.97, "y": 5.36, "curve": "stepped" }, + { "time": 6.4667, "x": -9.97, "y": 5.36 }, + { "time": 6.7667, "x": -9.97 } + ], + "scale": [ + { + "curve": [ 0.033, 1, 0.071, 0.152, 0.033, 1, 0.071, 1 ] + }, + { + "time": 0.1, + "x": 0.152, + "curve": [ 0.282, 0.152, 0.244, 1, 0.183, 1, 0.25, 1 ] + }, + { "time": 0.3333 } + ] + }, + "pupil-back": { + "translate": [ + { + "x": -8.93, + "curve": [ 0.033, -8.93, 0.067, -6.11, 0.033, 0, 0.067, 0 ] + }, + { + "time": 0.1, + "x": -6.11, + "curve": [ 0.282, -6.11, 0.256, -8.93, 0.183, 0, 0.256, 0 ] + }, + { "time": 0.3333, "x": -8.93, "curve": "stepped" }, + { "time": 1.4333, "x": -8.93 }, + { "time": 1.6333, "x": -8.93, "y": 3.83, "curve": "stepped" }, + { "time": 6.4667, "x": -8.93, "y": 3.83 }, + { "time": 6.7667, "x": -8.93 } + ], + "scale": [ + { + "curve": [ 0.033, 1, 0.071, 0.152, 0.033, 1, 0.071, 1 ] + }, + { + "time": 0.1, + "x": 0.152, + "curve": [ 0.282, 0.152, 0.244, 1, 0.183, 1, 0.25, 1 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-top-front": { + "translate": [ + { + "x": -15.36, + "y": 1.57, + "curve": [ 0.033, -15.36, 0.067, -26.84, 0.033, 1.57, 0.067, 0 ] + }, + { + "time": 0.1, + "x": -26.84, + "curve": [ 0.282, -26.84, 0.256, -10.38, 0.183, 0, 0.256, 1.06 ] + }, + { "time": 0.3333, "x": -10.38, "y": 1.06, "curve": "stepped" }, + { "time": 8.3667, "x": -10.38, "y": 1.06 }, + { "time": 8.8667, "x": -15.36, "y": 1.57 } + ] + }, + "eyelashes-top-back": { + "translate": [ + { + "x": -14.46, + "y": -3.29, + "curve": [ 0.033, -14.46, 0.067, -22.55, 0.033, -3.29, 0.067, 0 ] + }, + { + "time": 0.1, + "x": -22.55, + "curve": [ 0.282, -22.55, 0.256, -9.45, 0.183, 0, 0.256, -3.29 ] + }, + { "time": 0.3333, "x": -9.45, "y": -3.29, "curve": "stepped" }, + { "time": 8.3667, "x": -9.45, "y": -3.29 }, + { "time": 8.8667, "x": -14.46, "y": -3.29 } + ] + }, + "face-control": { + "translate": [ + { "x": -2.21, "curve": "stepped" }, + { "time": 1.4, "x": -2.21 }, + { "time": 1.8333, "x": -2.21, "y": 11.22 }, + { "time": 2.6, "x": -2.21, "y": 12.66 }, + { "time": 2.8667, "x": -6.06, "y": 13.01 }, + { "time": 3.3, "x": -2.21, "y": 13.4 }, + { "time": 6.6333, "x": -2.21, "y": 11.22 }, + { "time": 6.8, "x": -5.12, "y": 4.99 }, + { "time": 6.9333, "x": -2.21 } + ] + }, + "face": { + "rotate": [ + { "value": -15.25, "curve": "stepped" }, + { + "time": 2.5, + "value": -15.25, + "curve": [ 2.744, -13.13, 2.989, -8.89 ] + }, + { "time": 3.2333, "value": -8.89, "curve": "stepped" }, + { + "time": 8.2, + "value": -8.89, + "curve": [ 8.544, -8.89, 8.889, -15.25 ] + }, + { "time": 9.2333, "value": -15.25 } + ] + }, + "hair-back": { + "rotate": [ + { "value": 12.31, "curve": "stepped" }, + { "time": 2.5, "value": 12.31 }, + { "time": 3.2, "value": 7.32, "curve": "stepped" }, + { "time": 8.5333, "value": 7.32 }, + { "time": 9.5667, "value": 12.31 } + ] + }, + "fringe-side-front": { + "rotate": [ + { "value": 6.43, "curve": "stepped" }, + { "time": 2.5, "value": 6.43 }, + { "time": 3.2, "value": 6.92, "curve": "stepped" }, + { "time": 8.5333, "value": 6.92 }, + { "time": 9.5667, "value": 6.43 } + ] + }, + "fringe-side-back": { + "rotate": [ + { "value": 6.43, "curve": "stepped" }, + { "time": 2.5, "value": 6.43 }, + { "time": 3.2, "value": 6.92, "curve": "stepped" }, + { "time": 8.5333, "value": 6.92 }, + { "time": 9.5667, "value": 6.43 } + ] + }, + "leg-front-down": { + "rotate": [ + { "value": -25.69, "curve": "stepped" }, + { + "time": 2.6333, + "value": -25.69, + "curve": [ 2.967, -22.72, 3.3, -16.78 ] + }, + { "time": 3.6333, "value": -16.78, "curve": "stepped" }, + { + "time": 7.3667, + "value": -16.78, + "curve": [ 7.689, -16.78, 8.011, -22.72 ] + }, + { + "time": 8.3333, + "value": -25.69, + "curve": [ 8.767, -29.68, 9.2, -25.69 ] + }, + { "time": 9.6333, "value": -25.69 } + ] + }, + "leg-back-down": { + "rotate": [ + { "value": -31.75 } + ] + }, + "eyelashes-down-front": { + "translate": [ + { + "curve": [ 0.033, 0, 0.071, 12.12, 0.033, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": 12.12, + "curve": [ 0.282, 12.12, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ] + }, + "eyelashes-down-back": { + "translate": [ + { + "curve": [ 0.033, 0, 0.071, 10.12, 0.033, 0, 0.071, 0 ] + }, + { + "time": 0.1, + "x": 10.12, + "curve": [ 0.282, 10.12, 0.244, 0, 0.183, 0, 0.25, 0 ] + }, + { "time": 0.3333 } + ] + }, + "swing-top": { + "rotate": [ + { + "curve": [ 0.244, 0, 0.489, 0 ] + }, + { + "time": 0.7333, + "value": -0.11, + "curve": [ 0.989, -0.23, 1.244, -1.74 ] + }, + { + "time": 1.5, + "value": -1.74, + "curve": [ 1.744, -1.74, 1.989, 0.52 ] + }, + { + "time": 2.2333, + "value": 0.52, + "curve": [ 2.389, 0.52, 2.544, -0.61 ] + }, + { + "time": 2.7, + "value": -0.61, + "curve": [ 2.9, -0.61, 3.1, 1.19 ] + }, + { + "time": 3.3, + "value": 1.19, + "curve": [ 3.522, 1.19, 3.744, 1.19 ] + }, + { + "time": 3.9667, + "value": 0.66, + "curve": [ 4.344, -0.24, 4.722, -3.51 ] + }, + { + "time": 5.1, + "value": -3.51, + "curve": [ 5.211, -3.51, 5.322, -3.39 ] + }, + { + "time": 5.4333, + "value": -3.26, + "curve": [ 5.644, -3, 5.856, -2.71 ] + }, + { + "time": 6.0667, + "value": -2.32, + "curve": [ 6.356, -1.77, 6.644, -0.44 ] + }, + { + "time": 6.9333, + "value": -0.44, + "curve": [ 7.111, -0.44, 7.289, -0.82 ] + }, + { + "time": 7.4667, + "value": -0.82, + "curve": [ 7.811, -0.82, 8.156, 4.18 ] + }, + { + "time": 8.5, + "value": 4.18, + "curve": [ 8.867, 4.18, 9.233, 1.39 ] + }, + { + "time": 9.6, + "curve": [ 9.611, -0.04, 9.622, 0 ] + }, + { "time": 9.6333 } + ] + }, + "cloud": { + "translate": [ + { + "curve": [ 0.356, 0, 0.711, -11.64, 0.356, 0, 0.711, 0 ] + }, + { + "time": 1.0667, + "x": -11.64, + "curve": [ 1.5, -11.64, 1.933, 17.3, 1.5, 0, 1.933, 0 ] + }, + { + "time": 2.3667, + "x": 17.3, + "curve": [ 2.944, 17.3, 3.522, 17.3, 2.944, 0, 3.522, 0 ] + }, + { + "time": 4.1, + "x": 13.15, + "curve": [ 4.444, 10.68, 4.789, -11.93, 4.444, 0, 4.789, 0 ] + }, + { + "time": 5.1333, + "x": -12.61, + "curve": [ 5.878, -14.07, 6.622, -14.07, 5.878, 0, 6.622, 0 ] + }, + { + "time": 7.3667, + "x": -14.07, + "curve": [ 7.689, -14.07, 8.011, 19.19, 7.689, 0, 8.011, 0 ] + }, + { + "time": 8.3333, + "x": 19.19, + "curve": [ 8.756, 19.19, 9.178, 6.4, 8.756, 0, 9.178, 0 ] + }, + { + "time": 9.6, + "curve": [ 9.611, -0.17, 9.622, 0, 9.611, 0, 9.622, 0 ] + }, + { "time": 9.6333 } + ] + }, + "arm-front-up-holder": { + "translate": [ + { "time": 2 }, + { "time": 3.6667, "x": -1.79, "y": -23.94, "curve": "stepped" }, + { "time": 7.8667, "x": -1.79, "y": -23.94 }, + { "time": 9.0667 } + ] + }, + "bench-back": { + "translate": [ + { + "x": 8.04, + "curve": [ 0.156, 8.04, 0.311, 0, 0.156, 0, 0.311, 0 ] + }, + { + "time": 0.4667, + "curve": [ 0.822, 0, 1.178, -11.64, 0.822, 0, 1.178, 0 ] + }, + { + "time": 1.5333, + "x": -11.64, + "curve": [ 1.967, -11.64, 2.4, 17.3, 1.967, 0, 2.4, 0 ] + }, + { + "time": 2.8333, + "x": 17.3, + "curve": [ 3.411, 17.3, 3.989, 17.3, 3.411, 0, 3.989, 0 ] + }, + { + "time": 4.5667, + "x": 13.15, + "curve": [ 4.911, 10.68, 5.256, -11.93, 4.911, 0, 5.256, 0 ] + }, + { + "time": 5.6, + "x": -12.61, + "curve": [ 6.344, -14.07, 7.089, -14.07, 6.344, 0, 7.089, 0 ] + }, + { + "time": 7.8333, + "x": -14.07, + "curve": [ 8.156, -14.07, 8.478, 19.19, 8.156, 0, 8.478, 0 ] + }, + { + "time": 8.8, + "x": 19.19, + "curve": [ 9.079, 19.19, 9.267, 8.04, 9.079, 0, 9.357, 0 ] + }, + { "time": 9.6333, "x": 8.04 } + ] + } + }, + "physics": { + "girl/feathers-front": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "girl/feathers-front-top": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "girl/hair/fringe-side-back": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "girl/hair/fringe-side-front": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "girl/hair/hair-back": { + "wind": [ + { + "value": -4.3, + "curve": [ 0.189, -4.3, 0.378, -14.3 ] + }, + { + "time": 0.5667, + "value": -14.3, + "curve": [ 0.911, -14.3, 1.256, -6.3803 ] + }, + { + "time": 1.6, + "value": -4.3, + "curve": [ 2.1, -1.2803, 2.6, 1 ] + }, + { + "time": 3.1, + "value": 1, + "curve": [ 3.578, 1, 4.056, 1 ] + }, + { + "time": 4.5333, + "curve": [ 4.822, -0.6047, 5.111, -10 ] + }, + { + "time": 5.4, + "value": -10, + "curve": [ 5.667, -10, 5.933, -5 ] + }, + { + "time": 6.2, + "value": -5, + "curve": [ 6.389, -5, 6.578, -7 ] + }, + { + "time": 6.7667, + "value": -7, + "curve": [ 7.178, -7, 7.589, -2.9126 ] + }, + { + "time": 8, + "value": 1, + "curve": [ 8.233, 3.2207, 8.467, 11.4 ] + }, + { + "time": 8.7, + "value": 11.4, + "curve": [ 8.967, 11.4, 9.233, -4.3 ] + }, + { "time": 9.5, "value": -4.3 } + ] + }, + "girl/legs/sock-bow": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "girl/skirt/skirt-back": { + "wind": [ + {}, + { "time": 0.6, "value": -8.6 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.4 }, + { "time": 5, "value": -7.1, "curve": "stepped" }, + { "time": 6.6333, "value": -7.1 }, + { "time": 8.4333, "value": 7.1 }, + { "time": 9.6 } + ] + }, + "girl/skirt/skirt-front": { + "wind": [ + {}, + { "time": 0.7333, "value": -8.6 }, + { "time": 1.6667, "curve": "stepped" }, + { "time": 4.5333 }, + { "time": 5.1333, "value": -7.1, "curve": "stepped" }, + { "time": 6.8667, "value": -7.1 }, + { "time": 8.2333, "value": 7.1 }, + { "time": 9.6 } + ] + }, + "girl/wings/wing-back": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "girl/wings/wing-front": { + "wind": [ + { "value": -15.8 }, + { "time": 0.7667, "value": -33.3 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 4.9 }, + { "time": 5.5, "value": -19.3 }, + { "time": 5.9667, "value": -5.7 }, + { "time": 6.8, "value": -15.7 }, + { "time": 7.9333 }, + { "time": 8.7667, "value": 8.6 }, + { "time": 9.6333, "value": -15.8 } + ] + }, + "": { + "wind": [ + { + "value": -15.8, + "curve": [ 0.256, -15.8, 0.511, -33.3 ] + }, + { + "time": 0.7667, + "value": -33.3, + "curve": [ 1.044, -33.3, 1.322, 0 ] + }, + { + "time": 1.6, + "curve": [ 1.8, 0, 2, -8.6 ] + }, + { + "time": 2.2, + "value": -8.6, + "curve": [ 2.5, -8.6, 2.8, 1 ] + }, + { + "time": 3.1, + "value": 1, + "curve": [ 3.578, 1, 4.056, 0 ] + }, + { "time": 4.5333, "curve": "stepped" }, + { + "time": 4.9, + "curve": [ 5.1, 0, 5.3, -19.3 ] + }, + { + "time": 5.5, + "value": -19.3, + "curve": [ 5.656, -19.3, 5.811, -7.1 ] + }, + { + "time": 5.9667, + "value": -5.7, + "curve": [ 6.044, -5, 6.122, -5 ] + }, + { + "time": 6.2, + "value": -5, + "curve": [ 6.389, -5, 6.578, -7 ] + }, + { + "time": 6.7667, + "value": -7, + "curve": [ 7.156, -7, 7.544, -3.7011 ] + }, + { + "time": 7.9333, + "curve": [ 8.189, 2.4322, 8.444, 11.4 ] + }, + { + "time": 8.7, + "value": 11.4, + "curve": [ 9.011, 11.4, 9.322, -15.8 ] + }, + { "time": 9.6333, "value": -15.8 } + ] + } + } + }, + "wing-flap": { + "bones": { + "body-up": { + "translate": [ + { + "curve": [ 0.222, 0, 0.444, 10, 0.222, 0, 0.444, 0 ] + }, + { + "time": 0.6667, + "x": 10, + "curve": [ 1.211, 10, 1.756, 3.33, 1.211, 0, 1.756, 0 ] + }, + { "time": 2.3 } + ] + }, + "wing-front": { + "rotate": [ + {}, + { "time": 0.6, "value": -28.71 }, + { "time": 1.1333 }, + { "time": 1.7, "value": -28.71 }, + { "time": 2.2667 } + ], + "scale": [ + {}, + { "time": 0.6, "y": 0.497 }, + { "time": 1.1333 }, + { "time": 1.7, "y": 0.497 }, + { "time": 2.2667 } + ] + }, + "wing-front-tip": { + "rotate": [ + {}, + { + "time": 0.2333, + "value": 33.17, + "curve": [ 0.333, 33.17, 0.412, 0 ] + }, + { + "time": 0.5, + "curve": [ 0.608, 0, 0.742, -30.34 ] + }, + { + "time": 0.8667, + "value": -30.34, + "curve": [ 0.968, -30.34, 1.042, -12.9 ] + }, + { "time": 1.1333 }, + { + "time": 1.3667, + "value": 33.17, + "curve": [ 1.466, 33.17, 1.545, 0 ] + }, + { + "time": 1.6333, + "curve": [ 1.741, 0, 1.875, -30.34 ] + }, + { + "time": 2, + "value": -30.34, + "curve": [ 2.101, -30.34, 2.184, 0 ] + }, + { "time": 2.2667 } + ] + }, + "wing-back-tip": { + "rotate": [ + {}, + { + "time": 0.2667, + "value": -11.49, + "curve": [ 0.272, -11.49, 0.422, 0 ] + }, + { + "time": 0.5, + "curve": [ 0.608, 0, 0.742, 18.1 ] + }, + { + "time": 0.8667, + "value": 18.1, + "curve": [ 0.968, 18.1, 1.042, 3.83 ] + }, + { "time": 1.1333 }, + { + "time": 1.4, + "value": -11.49, + "curve": [ 1.406, -11.49, 1.555, 0 ] + }, + { + "time": 1.6333, + "curve": [ 1.741, 0, 1.875, 18.1 ] + }, + { + "time": 2, + "value": 18.1, + "curve": [ 2.101, 18.1, 2.184, 0 ] + }, + { "time": 2.2667 } + ], + "scale": [ + { + "curve": [ 0.089, 1, 0.18, 0.807, 0.089, 1, 0.18, 1 ] + }, + { + "time": 0.2667, + "x": 0.807, + "curve": [ 0.345, 0.807, 0.425, 1.061, 0.345, 1, 0.425, 1 ] + }, + { + "time": 0.5, + "x": 1.081, + "curve": [ 0.622, 1.112, 0.747, 1.254, 0.622, 1, 0.747, 1 ] + }, + { + "time": 0.8667, + "x": 1.222, + "curve": [ 0.961, 1.198, 1.042, 1, 0.961, 1, 1.042, 1 ] + }, + { + "time": 1.1333, + "curve": [ 1.222, 1, 1.313, 0.807, 1.222, 1, 1.313, 1 ] + }, + { + "time": 1.4, + "x": 0.807, + "curve": [ 1.478, 0.807, 1.558, 1.061, 1.478, 1, 1.558, 1 ] + }, + { + "time": 1.6333, + "x": 1.081, + "curve": [ 1.755, 1.112, 1.88, 1.254, 1.755, 1, 1.88, 1 ] + }, + { + "time": 2, + "x": 1.222, + "curve": [ 2.094, 1.198, 2.173, 1, 2.094, 1, 2.173, 1 ] + }, + { "time": 2.2667 } + ] + }, + "wing-back": { + "rotate": [ + { + "curve": [ 0.193, 0, 0.407, 31.82 ] + }, + { + "time": 0.6, + "value": 31.82, + "curve": [ 0.787, 31.82, 0.951, 0 ] + }, + { + "time": 1.1333, + "curve": [ 1.326, 0, 1.507, 31.82 ] + }, + { + "time": 1.7, + "value": 31.82, + "curve": [ 1.887, 31.82, 2.08, 0 ] + }, + { "time": 2.2667 } + ], + "scale": [ + { + "curve": [ 0.193, 1, 0.407, 1.248, 0.193, 1, 0.407, 0.376 ] + }, + { + "time": 0.6, + "x": 1.248, + "y": 0.376, + "curve": [ 0.787, 1.248, 0.951, 1, 0.787, 0.376, 0.951, 1 ] + }, + { + "time": 1.1333, + "curve": [ 1.326, 1, 1.507, 1.248, 1.326, 1, 1.507, 0.376 ] + }, + { + "time": 1.7, + "x": 1.248, + "y": 0.376, + "curve": [ 1.887, 1.248, 2.08, 1, 1.887, 0.376, 2.08, 1 ] + }, + { "time": 2.2667 } + ] + } + } + }, + "wings-and-feet": { + "bones": { + "body-up": { + "translate": [ + { + "curve": [ 0.222, 0, 0.444, 10, 0.222, 0, 0.444, 0 ] + }, + { + "time": 0.6667, + "x": 10, + "curve": [ 1.211, 10, 1.756, 3.33, 1.211, 0, 1.756, 0 ] + }, + { "time": 2.3 } + ] + }, + "wing-front": { + "rotate": [ + {}, + { "time": 0.6, "value": -28.71 }, + { "time": 1.1333 }, + { "time": 1.7, "value": -28.71 }, + { "time": 2.2667 } + ], + "scale": [ + {}, + { "time": 0.6, "y": 0.497 }, + { "time": 1.1333 }, + { "time": 1.7, "y": 0.497 }, + { "time": 2.2667 } + ] + }, + "wing-front-tip": { + "rotate": [ + {}, + { + "time": 0.2333, + "value": 33.17, + "curve": [ 0.333, 33.17, 0.412, 0 ] + }, + { + "time": 0.5, + "curve": [ 0.608, 0, 0.742, -30.34 ] + }, + { + "time": 0.8667, + "value": -30.34, + "curve": [ 0.968, -30.34, 1.042, -12.9 ] + }, + { "time": 1.1333 }, + { + "time": 1.3667, + "value": 33.17, + "curve": [ 1.466, 33.17, 1.545, 0 ] + }, + { + "time": 1.6333, + "curve": [ 1.741, 0, 1.875, -30.34 ] + }, + { + "time": 2, + "value": -30.34, + "curve": [ 2.101, -30.34, 2.184, 0 ] + }, + { "time": 2.2667 } + ] + }, + "wing-back-tip": { + "rotate": [ + {}, + { + "time": 0.2667, + "value": -11.49, + "curve": [ 0.272, -11.49, 0.422, 0 ] + }, + { + "time": 0.5, + "curve": [ 0.608, 0, 0.742, 18.1 ] + }, + { + "time": 0.8667, + "value": 18.1, + "curve": [ 0.968, 18.1, 1.042, 3.83 ] + }, + { "time": 1.1333 }, + { + "time": 1.4, + "value": -11.49, + "curve": [ 1.406, -11.49, 1.555, 0 ] + }, + { + "time": 1.6333, + "curve": [ 1.741, 0, 1.875, 18.1 ] + }, + { + "time": 2, + "value": 18.1, + "curve": [ 2.101, 18.1, 2.184, 0 ] + }, + { "time": 2.2667 } + ], + "scale": [ + { + "curve": [ 0.089, 1, 0.18, 0.807, 0.089, 1, 0.18, 1 ] + }, + { + "time": 0.2667, + "x": 0.807, + "curve": [ 0.345, 0.807, 0.425, 1.061, 0.345, 1, 0.425, 1 ] + }, + { + "time": 0.5, + "x": 1.081, + "curve": [ 0.622, 1.112, 0.747, 1.254, 0.622, 1, 0.747, 1 ] + }, + { + "time": 0.8667, + "x": 1.222, + "curve": [ 0.961, 1.198, 1.042, 1, 0.961, 1, 1.042, 1 ] + }, + { + "time": 1.1333, + "curve": [ 1.222, 1, 1.313, 0.807, 1.222, 1, 1.313, 1 ] + }, + { + "time": 1.4, + "x": 0.807, + "curve": [ 1.478, 0.807, 1.558, 1.061, 1.478, 1, 1.558, 1 ] + }, + { + "time": 1.6333, + "x": 1.081, + "curve": [ 1.755, 1.112, 1.88, 1.254, 1.755, 1, 1.88, 1 ] + }, + { + "time": 2, + "x": 1.222, + "curve": [ 2.094, 1.198, 2.173, 1, 2.094, 1, 2.173, 1 ] + }, + { "time": 2.2667 } + ] + }, + "wing-back": { + "rotate": [ + { + "curve": [ 0.193, 0, 0.407, 31.82 ] + }, + { + "time": 0.6, + "value": 31.82, + "curve": [ 0.787, 31.82, 0.951, 0 ] + }, + { + "time": 1.1333, + "curve": [ 1.326, 0, 1.507, 31.82 ] + }, + { + "time": 1.7, + "value": 31.82, + "curve": [ 1.887, 31.82, 2.08, 0 ] + }, + { "time": 2.2667 } + ], + "scale": [ + { + "curve": [ 0.193, 1, 0.407, 1.248, 0.193, 1, 0.407, 0.376 ] + }, + { + "time": 0.6, + "x": 1.248, + "y": 0.376, + "curve": [ 0.787, 1.248, 0.951, 1, 0.787, 0.376, 0.951, 1 ] + }, + { + "time": 1.1333, + "curve": [ 1.326, 1, 1.507, 1.248, 1.326, 1, 1.507, 0.376 ] + }, + { + "time": 1.7, + "x": 1.248, + "y": 0.376, + "curve": [ 1.887, 1.248, 2.08, 1, 1.887, 0.376, 2.08, 1 ] + }, + { "time": 2.2667 } + ] + }, + "leg-back-down": { + "rotate": [ + { + "value": -15.56, + "curve": [ 0.122, -7.02, 0.244, 8.91 ] + }, + { + "time": 0.3667, + "value": 8.91, + "curve": [ 0.556, 8.91, 0.744, -26.59 ] + }, + { + "time": 0.9333, + "value": -26.59, + "curve": [ 1.133, -26.59, 1.333, 8.91 ] + }, + { + "time": 1.5333, + "value": 8.91, + "curve": [ 1.744, 8.91, 1.956, -20.89 ] + }, + { + "time": 2.1667, + "value": -20.89, + "curve": [ 2.211, -20.89, 2.256, -18.67 ] + }, + { "time": 2.3, "value": -15.56 } + ] + }, + "leg-front-down": { + "rotate": [ + { + "value": 8.91, + "curve": [ 0.189, 8.91, 0.378, -26.59 ] + }, + { + "time": 0.5667, + "value": -26.59, + "curve": [ 0.767, -26.59, 0.967, 8.91 ] + }, + { + "time": 1.1667, + "value": 8.91, + "curve": [ 1.378, 8.91, 1.589, -20.89 ] + }, + { + "time": 1.8, + "value": -20.89, + "curve": [ 1.967, -20.89, 2.133, 8.91 ] + }, + { "time": 2.3, "value": 8.91 } + ] + } + } + } +} +} \ No newline at end of file diff --git a/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.skel b/spine-ts/spine-phaser-v4/example/assets/celestial-circus-pro.skel new file mode 100644 index 0000000000000000000000000000000000000000..cf834001b8e5a711f52e4597799f976d473db9c1 GIT binary patch literal 52572 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 AW&i*H literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/celestial-circus.atlas b/spine-ts/spine-phaser-v4/example/assets/celestial-circus.atlas new file mode 100644 index 000000000..17f32b2a3 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/celestial-circus.atlas @@ -0,0 +1,173 @@ +celestial-circus.png + size: 1024, 1024 + filter: Linear, Linear + scale: 0.4 +arm-back-down + bounds: 324, 401, 38, 82 + rotate: 90 +arm-back-up + bounds: 290, 44, 83, 116 + rotate: 90 +arm-front-down + bounds: 706, 2, 36, 78 + rotate: 90 +arm-front-up + bounds: 860, 138, 77, 116 +bench + bounds: 725, 256, 189, 48 +body-bottom + bounds: 879, 868, 154, 124 + rotate: 90 +body-top + bounds: 725, 128, 126, 133 + rotate: 90 +chest + bounds: 408, 26, 104, 93 +cloud-back + bounds: 752, 378, 202, 165 +cloud-front + bounds: 2, 2, 325, 196 + rotate: 90 +collar + bounds: 786, 13, 47, 26 +ear + bounds: 1002, 643, 20, 28 +eye-back-shadow + bounds: 428, 395, 14, 10 +eye-front-shadow + bounds: 704, 529, 24, 14 +eye-reflex-back + bounds: 860, 128, 8, 7 + rotate: 90 +eye-reflex-front + bounds: 726, 386, 10, 7 +eye-white-back + bounds: 835, 23, 13, 16 +eye-white-front + bounds: 1005, 1000, 22, 17 + rotate: 90 +eyelashes-down-back + bounds: 232, 329, 11, 6 + rotate: 90 +eyelashes-down-front + bounds: 913, 851, 15, 6 + rotate: 90 +eyelashes-top-back + bounds: 408, 395, 18, 10 +eyelashes-top-front + bounds: 702, 179, 30, 16 + rotate: 90 +face + bounds: 514, 26, 93, 102 + rotate: 90 +feathers-back + bounds: 954, 625, 46, 46 +feathers-front + bounds: 706, 40, 72, 86 +fringe-middle-back + bounds: 200, 6, 33, 52 + rotate: 90 +fringe-middle-front + bounds: 878, 76, 60, 50 + rotate: 90 +fringe-side-back + bounds: 780, 41, 27, 94 + rotate: 90 +fringe-side-front + bounds: 939, 161, 26, 93 +glove-bottom-back + bounds: 954, 572, 51, 41 + rotate: 90 +glove-bottom-front + bounds: 916, 256, 47, 48 +hair-back-1 + bounds: 444, 395, 132, 306 + rotate: 90 +hair-back-2 + bounds: 438, 211, 80, 285 + rotate: 90 +hair-back-3 + bounds: 719, 306, 70, 268 + rotate: 90 +hair-back-4 + bounds: 438, 121, 88, 262 + rotate: 90 +hair-back-5 + bounds: 438, 293, 88, 279 + rotate: 90 +hair-back-6 + bounds: 200, 41, 88, 286 +hair-hat-shadow + bounds: 232, 398, 90, 41 +hand-back + bounds: 954, 673, 60, 47 + rotate: 90 +hand-front + bounds: 967, 172, 53, 60 +hat-back + bounds: 954, 802, 64, 45 + rotate: 90 +hat-front + bounds: 780, 70, 96, 56 +head-back + bounds: 618, 17, 102, 86 + rotate: 90 +jabot + bounds: 967, 234, 70, 55 + rotate: 90 +leg-back + bounds: 232, 441, 210, 333 +leg-front + bounds: 444, 529, 258, 320 +logo-brooch + bounds: 954, 545, 16, 25 +mouth + bounds: 408, 121, 22, 6 +neck + bounds: 232, 342, 39, 56 + rotate: 90 +nose + bounds: 742, 529, 6, 7 + rotate: 90 +nose-highlight + bounds: 719, 300, 4, 4 +nose-shadow + bounds: 869, 128, 7, 8 +pupil-back + bounds: 730, 529, 10, 14 +pupil-front + bounds: 254, 21, 12, 18 +rope-back + bounds: 232, 383, 10, 492 + rotate: 90 +rope-front + bounds: 232, 383, 10, 492 + rotate: 90 +rope-front-bottom + bounds: 954, 735, 42, 65 +skirt + bounds: 2, 776, 440, 246 +sock-bow + bounds: 408, 407, 33, 32 +spine-logo-body + bounds: 879, 853, 13, 32 + rotate: 90 +star-big + bounds: 939, 141, 18, 24 + rotate: 90 +star-medium + bounds: 742, 537, 6, 8 + rotate: 90 +star-small + bounds: 719, 378, 3, 4 + rotate: 90 +underskirt + bounds: 2, 329, 445, 228 + rotate: 90 +underskirt-back + bounds: 444, 851, 433, 171 +wing-back + bounds: 290, 129, 146, 252 +wing-front + bounds: 704, 545, 304, 248 + rotate: 90 diff --git a/spine-ts/spine-phaser-v4/example/assets/celestial-circus.png b/spine-ts/spine-phaser-v4/example/assets/celestial-circus.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c26ccf2f7cd9fe789f23ffc18df2913000bc00 GIT binary patch literal 808981 zcmaI7Wmr`2_r|-2p>rq!si8qYQaXl^4nYu7K*) z_dnBFCzJqW;e1FGlOj#LU%O2&0hc8Kt z`=RVzr*Tj;Pet@Nwh3b^Jo>w8t!gz-nsFjyQo*pO*AJHhpV8ykpGUjzBaHP>thBRt zzJAhlyKr?={Ug5OGI9k_{QpO+KdUGz(x<#}52d5DOpXt;BssvuLatn_zGnpQdN{eO z#>Dhxf?C^);5rib6rAq8BIn5Il9l^hIrnqk|1bQ=X+8VCuzM|DQzLLE{w2niR?@*g&DNIy`pFf%hlK_CO$=g&ST zdtlTz7L2=THmVa#zuXi0ELAQdtb(Ylb^clR%Rc~1T4^Bway4f!d^GjxvbjfNvUrrE zK83)K6s4j4mY_m1oq9a#{|i5R@8gk+$bP%3~i+cBlU?rIeV4s< zgWdyUh?C%$i<<)Jxrhx+S=7;s)jR56^o6E`8!%>!PpQ0z1v!W)m zb2_I+lZh@_^JP*ZMm!K4tV13;PMAjFG!}fQ4dujenhi)S`7Ys4`#lF_zJm}6b^bDD zqD*NzFM@v*eed1XJ-!okxxRwD-Cyz0aX){0Q~wJ!6$#fr6;YM~?h-m;ra8QxBQUSO z6Wr%>^_kAggQ)`{yy2KJTL>3@Ryw+1R7AhDVYsWdI+U$L1idyO!Zc2EtT$()Va&c^ z?4b6I!!#67&2eZDEkhmzKXzbPT>9&?`K_)?HgPITm_KC@tT$}sVy}kXl;xN%p^%)~ zZbWB>4m;t}*L*9kLPd%dN39&&YRlLab+Er;E-Xd{(+UKvSK`r;D6j@+k^;EYVU{nC z<;V1;srXH{Ui3N)Et$IBhisodw#SID6CAZ1q`bSd7yCEs(Q~6sRQa_Elp~BjgQbPa zjc1I7AO{nIUIEy_7#;@hgVOGs|MvoD7^EH-xZYHmr~@(kByv&XqB0YvfXE%@@!idoN4YqncEI$vi_Oz(Qo zm=q-=kU>$z0H6&U9At=V^=ez|1a(T zZPYj%hZJ-SjKOJZDTmbnK0$Bw44SH90=IK`LB;T z8QBa*T$)rpyhhP;+O&&J97#YQSnf>Gi97z1i$wD9d5{dx^WGyWIP0uuXbiI+Dg)-) z&+G*MRP)g@Fc1S-kk9A76_S(A%A+pId8zW5-pkIXl}kh~HVQij2@ut-%XIm)?)((1 zuht|3CKEW1?x-n4P0;zeEThL9a-Pmk;I#BQ9fI(Cjt0i{?esu=L;L#0v1m%GG7J99 zf%pnaH@bzwpwp;hOXr+$1+M{Tbh3U4w|LdRbLr;ylnzrnc1-#Tx|Vg;#$eAz?Ame5 zx_1zlMeO_A+;={YK8Kh0{@qPpzNIq#9M8Cxd|jqjQvdJuGF*4B+#l^0=x=RYOe;;M z963YW?W5glb5uX4$6WX~+8^{FG#QH--%`8$Gie}Ci0F+IbZ?O5}O!l)<}K&YzmHuCJtRy?PJ z2M$98Devw-k5lcWFaZXg=V(}H^zd8W$KXw$E&_+5fd`Cl&FL?@(is1KvLH9jF~uvp zNPj>rdtIx8pKBnAk{85%P`Zeg=6lh2CsDnBs+Usjaqw?A?D1N9hFm|19p8>NefIPG z->G`MF^k%qNUzbC(BpTA4_)M;7GPo<0A&a+fF4H#1u-MY5C2bMXor@ve{Cnp@LjbJR=JF_0HqYYC%oW#+S)R;SzIPIbr&kV zfq(#Jw)`Z`epY;Ac8p$21uMF!&stw(9PJ3ow>n^5^|qew_@%EnnCK=?ec4d+RU|pE z=$L{Npvs*CI|&C8;?jfea+-8GuY{%}SdDR`XzBNAt14T7_Q?+C=A#PN=l*_<|5mdy z9hzS$)BjIMBl_L^-JQn!39`3H!z6!{E(+~q7Ubd;McIdKktFPM6?tqDVZmomZ$2*u zY;E9Qrn|%Kw^zvj3WbjUn0aoD8^pGhMd38tdjK{HUP%jy2nvt5-2Lru)atf*G}C%m zZ<{o@5q@LJo zgDpYhgpg9#w;Ya!)U9KJZ8p2+PMN?vZ8o@f$m2uo;o!Xu9`$}V0Sq%-3xKZkm)IEN z$|#YUe)Ffv?9~{ey^bWUf5vrz-6dJbvC~THy~B=t_%68OD1Z4WWR zK8an+Natr%+w4DVrmoQGOjm)(#7X3 z*&>t!eJqoL{t_Vo1tf@u&vsXG;KXde-eaR;q2wf?Vg+hNc+v7mL71f4Ra;dE0}#E8 zHp&)=d{V!qSKrGJ;gj{_5avj_Q+v&uD+QPpQAhPekL?6KEJeCezX#odLm*W?jom?{ zn*WR%SQ#Ekii+x!yn&3_Y@pA!t0Z~Q&?dh?J-tQnJz zB&jlCs4WS?Xso&83(q-V?2|)9FggjO(G{pr-3tE;BHAU9l!{P*2E*g}z2gx5;k(OC zd{&B3J#ptlK$n_UA*Y)$4ikbp<4zbthkF(d;u1UFrEK@!-#Pw0{gr|u)}{JsBJubA zQ}JPI{4g~>jtm>#qK{Uv#`!y0j?TN_T`hC_=+a4sFxE7MIGRV@X131)wF7EecxeQ& zjRz5ML5Y6(fNQKk55u-Jg-M&3ZH#t0P@x6nZU93T^5y)uzQA$+@^~Lj_RZgg!!ZZ_ zBrg1ik?tRS0&H915z&QR{~{$%e{fJ?bUH!L8aJo7afw4MX(Z6|F05^^_=M~j=<*P< zQ+AZ(-^6-Il)!@s+x# zKsh8iAE6)PwBR3;T$n8LG+fV8QA1AnfVR^hcc%+dF87}dl=^{V?WgnYx_rWG4?gY? zpv8TZ^ZlT;T(A09mKF@eD~I+mPA$R5BSg2A4tm*ZZPw@xPF!Qh)2O=g65r^18-1kL zq2R;FBkG>Pq7H4=ZxlJoZjB5x`#Vn|Vkx!PA%=s1i^G92Rh>q5JLPcCT}SDH2)4x3 zPwLyeFUzh5+q1XiYlGR>2=_s!l@i-4;TWAa1$*SZh3X;I8OT3=c@{X)GV+A{^NKi% z31$G_*xuCmE`J;sZqAYwTw&2|r8Qdwx#i$_yfi18@V{)V8VJg6G^v^1ZetCf(DnSY zE*$ew)&w=v;t&*QUXm3?3@9)q-VPrrSW3kuta_?dqpPrklZX^Q_LD;>6{PyZNOD{w zjXaE&2Hr~33&kZt3t&pj$?%lqNFes4gBzVH*jQ4f4WEI7V`%+x4m_^Z{MZ|EyME_) zRz^ER@Ls)rW2;AXVZ^u0d?$+t?a+ayY3ExupVST|*bRG=h>&@R@W<46ZcDVv-?f2P8~q2Pi<+Jv~PJ&a9gWf2(^JbeBk$XzRrHwZzkCi z`$usc*wOKA-}8bT!CL}cVw>&{EWSnt1Sya20t_WVL0_9*Abu7BjICCopz3%ob%q0u zyt-ORmZUr03ZX|~puw#0NkJU$f& z{iScEiR>Z1kR1-lYU-VZhTd11!b!yHEHi56vvmb9ic^WWk7=G06^~J zO_yHwrMs5_N6*`~Y)uuuq!M<#vbj7IM-mTdMyX|<;~2KBbBrFhi(9_hZ~wQA6#SO? zR9e0QCq*Y~lC6IgZ}!f=t>?UF#VdbmFt~-ho`=h(JE`wgHu> z1eDZmyI>!#`vV*Im8lW6f7$pA{)e;;hwb|%I{Y?gT1oh4qO zGcKTD(7}TB+u&;xkY~@8cht0c{jd-#SCaW0+kVRt^9xFgKgKme-f2~*KA(?qac$ID zGBhPtLBm-|_9}^vBxMtQXSy$FkEE2^vvV)keVK$_!J#eRbJBfV;O=|#*N!&h^XOu{ zkNtez-L&IM)|m_A@2|_3Nk$CcEoyj>TXT6=hyMp&4u*gKMuj7v&D{UP-%6G@LWrbS z+Y!X*NLg8KqywCdkjbu;`>Wf_=3aQ~BeJd+UP5qaL#V)YxpWFr%k#B>&z--(x*Y%` zmYn$o`UMnlO>xOT^g+yW#k`q2N3a7eAI}F?71hyC3Jyq+{ihN8FKd1XWc@=~;A{~* z*W0JA2zO)21alcZjuXU~I+6!=L4HgIVC9){n7z0s7Z{TY7K-xTdi+2M$4oiQ)u#xm zcKPdSE&pNI)aV~}kl@ge??V>1zC_bmwO;kA(Z7H38-u$}cx4 z+my;73i5AhJ$ICMUpYJqfe~#bBRW4@{>@P>s>=M~MWxV^Yk(g6(aQY!xD|6}!7eP? zeS5)Bq@@f$f?5u(BJO=RWD@lx6pSymz9@Z^yk9L>BrfUSjn+f{5UGA-LOLGSm)JF2 zALRav-qEwn-V3v(;_^^DX2bNzWpjDa7TCnjd*Oe+T*!3Y z=6}kLak<%9CYStBh7TjU{x+2#J&7ag@fy4>t17VgiE*}2Xl!pt>f`xOj3yV9C?3d* z*v_$j#P^}yBCpA?&7#%V%&^Z&qquu#2E`BJ<)Nf=B`CE|GZcYPgv`+I0c9pkJ2iq{YurG%C$tdbD>$J^D0GREM@`nf@3jb!MV@;}R#?GI=3J zRZ1)!>S>nr(~$c0gKtvU z0C`p#;$YlIxvF`~T#Ww$<+T%jokIjvSFRDdX}h#wykJVE-|Eqa@p8#`FkNYep#7}p zr-=7n$=OSTkD{k48}l>0U2l)SO6(>zU^idi3&j|)m2Hi#+~*5QoMdt>*Plf$RBtN$ zmn|BY{Sy=YMw{E{Sxm;Or1Hi-J+!4+G=fL5w7uf-v`5VnuMw8fLQx6uie@xQMl580 zY*e)32XG86^=z3ebR6flnG{VHR|=MK$>Dj!=DNohe*fVKFH6!Q2uOi)|IuUbQc+18 zub^*kQy|a+y@Lgcx z&HbM=Y{+9g_;`2%Y9EcU5pTo0S+Rc3s?mtx7w~Ks39PllOm0xU`l}ZT*h1g|QdAUh z;A>1T1MirX@u;prMg%|fn8|0BaWY$WhV=!{b)pipoWH`+pFj!-Z>xVHX+HDe6-#^! zt_q8k;@8>$>qJb{7ZeN%#c#%m!8BHUFnUBi6iAC9=yQfaJ?jU{a(pYB-%|-or!+WR z6o+~*_5Jic*xowGn{XrG{O(UPt=o8v-ZHS+q2 z@OYv)USyrUF0MTKyufMr*ON(MD~J0RNcuw`-tB&K$`3N#NwTS{FTj1=ST?lChfjeQ zDH53oRQRa>wLq$RcX9W-XT*F3(Or;0{w_P=7XApZ%G7Q60Q54B680H)IXat$izp{_ z_3qnyj_wzdZ?j8n{FZk=QseEoE1xy#zKCcGl`z`MgtAgU1;$goYtzK~|rPV46sbGl)PH@kjq^v1q6REtO&^85V4 zn`ojRDDKjFK1)m@5+S!TvfWhZz1rduQlkD;jy$#K3k%8thZ)FHu;^3zDJ z2A8cDh~LS5-UUd5yi|KOvW;s(zmg7ruGvpV2A;IuH>v|oQHGpi~Ld+=6>sIN*KyBj1tw_;)qoaZ=)i3LuOH98R;@xu$Y71yF6rza)7 zKh)W9)os0W^CYLAH_Zk9^L3;uJa)3)VrRKmG2NWmj7&kK|WiVkj<7&PR5BRjYdWZ}O2}v2Y%{og~KlX{-+QcUs??012 z_Nj{LDo&6m_nxm3D;OByp(K)Yz)DA&X?jxY_QKgdWAx-;( zXvj32CwHH;5Y`#ErA5a{srd}jM~FbzZ0v7yYuOWr5}7ajEt(026nXuvjCS7uVVcPF zmDMcXZ@$-<)jwC#%f4TeT)H@9)qngu(y;W)Igm5$?+=3eqejN=>?Dl7Y_a-B5(mrs z{4jLnQ1}9MceI5_8;b#JzM$_DbpAerP7VIksZLG@IhwHktd`XaY_+{e%(#`fH zyZK7g$diWh;bnp|FSbadv={kX%4{?A-X9JgE?XCXJ;o|y2Qnh;O`u7_R;m`SRiWve z-W3I>vFwKemI)=G%;fwh9X~7EF-!RQC&f2h6WAm9zHsA(pEGh$)~_OQ*C2@ZT#o&| zQImkVDK!5B-tA=6z4df9&4sBf^g1B+-K-Sk`p|uBdF5g0O)gTdF&o-aR5C9-CGkvzy?f#eo&0X@FAtl*F71vTcJSm0hocA&CT?shNq*m>&yEzaJDwLKkcjgV8 z=E2;Rmd6XuMALl7ZQ=!XJR^SNPNU|BD?JZYviFt-6B%9A2zAlB!jG9m(=Y}rX&r=TBW-QOR@g)x3TvX>eNKq8lPFO4-{O=YRreA)AGEq#vIrAbQ( z&tn1~&L^FB641C;7WV!7by38-x`V$j|X+N|~8qCtl4b*9`} zOojhxLweoK3V*L{)gjeD5OLbF`^!cBezYe~6(5Fyc$;=ZDa-Hiof?BJ-=YKBWsHTH znRKDtGgc)>Wu@@7H2#S+N^wI`uT;`}l7ZdZ%DYw*L^WDIM7-vcv?eut3X|Ike6a0} zi|bMW<+r-pXGcAF`E2q)GFV|6Qh&kvQx?6{l(iVr#{)3SI_#BVp}-9Ci9GnNYr zjr^UQjh|pxjsMe^<^6(d47`qj9;-SLw!(jmhJgbu!Cfm0`WGwxp+x(plUn&w11T}J zItd~+_IiY1|51!{tuncLd-yb4>1)h)VQ-ysvEC% z=LjZR)JgGeFUNgnk$|ul6Gj8a$N@of>?0KZTNMzyoO?36(HexR$2oCZrCC4mUsAS@ zrTORBVg;Oz{m24NWGa07c1v1wsBC(8tfO9d-1(bfq69`LlZ9(3zd#1I=hw%%Ed}Q@-8o0d(C1CYte=}w znXdmxtr+62!4^>!#TNAf;`d42nhhI*Lal6wr^PF-)miL(kM4{d`)T)R&%GrocbF1> zi_O^h?`S{X=avmK<0zxl*YFM-y3~;SZr{Js(Z6oXOno9;FH`?l7SS<|ZbF-$3gbPR z>ADWCdPZ$s74Me|z3iw{1ZuF>(#4tyqZ}L$FajK<>qD^E@B_ICjMMPCFax<2nT_5P zNn;25p;GT^cNr-EV7NzJ=T_?lcqbnH$6fAH1C52Jf7bYWJec7|f%0w2(r?^Y!1>E+ ztqDl}{T0101NJBC&_0xW@AF6?ts`D-UbP@l3mZ2pLdbB>e!}VxgU`m-FH6DT-j68822o{8Z`Y|hgqkvnCj}<@MZgGVSx|N!5`$=hxnXtE61-OuJR3pOa*hH zCKE$99~z`S*r9PRvM`r6LEa!~t;w0I7!Qhv<{6J_8D%T9;R*;&ds(V-*gQ>erLkAn zNhGDzL_mxyZ`O~|0VvkxWPFH-m*M#E8$N`b%(>hqBP$5|?1qI=PAVzFl2f zdIdeH#+O=^b-SM=B?u?Ub!-~}qB{hb0 z@m<|Cw-Yz^m^g0AkQiDh3;AH^i5Ut$w<9y?3WXeWR+#1APkBLLaEu*nPs)psz4)Ebk)~MCZ;S2!)lh(&&v!3$sa>4E{-&;HZ+2R(gjvAW z|M^oLefWk42vNg`5sAQJ{5#ar49mVCRBC=Xq(RB#wPb-bY2a%I4n9isgM5F<6Pdrd zK_8Vuz=6}d-Z-@)r(AX$jP$I^1*28g2dP@t%uL89glmh#h?()uusjk(unVa0A-^{p zgQxO-MIFDC$-~5ba)l9fRQ&6f<;1SmOT&R`(V`+qUx&ZK?P=eHFl?h4PG#W0R#azJ z3(zZxVxlc|`KH>2xQiTbHVB#=R_;$*?K;2bVnge6sOH!WcjFbZ?{a-+vK0!c-FLJl zDC?4k2BSgfVq`d$kRHg!bW^(oZ!!e!;+YLcd0GT(Ebibzy2xp(+EH=`0F2){>H(RQXwb=e&>mmqu3#=1 zJSk401biEXKW;=lmKh$m{I{qbjh@5LtB-n75+AVN-k??OJ^ zR=HmtyWba5RJ+r2d2*dXreY^?HWS8DUyAiOM}B?5{M~|*(cC*PC9WQCcfL}L%w(*0 zaond$=nPsL(-mTRH4MI9oLKB&aQch1@%3UR$iZJt17fVY+JMi%ufLoP?y(x}DB_b> z7l*q$qsU(sJL#=E>Pq%4FAUrK?~LP%S4*?PV$jmijXS5~9Jw>F019=+a^Jhb)>)$Y zm|&U6h=M4EF66MFL3T3y5%rhFF`70cL>ggPRtTg+Pe9C?sMg$PNhVDzD0Q!Pd0~0n zo)DCmK?ZQK39TSm)EtE3N;<|ED&Z(F1+}pFPESe2*g^9|UuqV;P$*~IZ}vV(Tu+=L zrWQ6>Iamif{{G<8_!)CaChA@mArJg@ja0!vVC{n5i0{1KmUMVbym~UR5~H1@PzyL_ z2LiUq)A2Y4Q4}!(j=}XXDl2k3C{utw&WAqZ#2CDM##u6H*xZZa$3%KUg7Ab_C@dTI zQEIY4wb>{p`I#dJeMj9DB2DBwgRtJhScNyUbMbnk-(l5 zLa9~zvi_?na}^>&Mu{7>`0i#525Nu5ii%s!vrJ89w*jot!v^)^tAO1iJcv^TAZllku? zw|m%4RlPWLHo*MRb&MV0vu}X_O(VwxV}P1!1pSaZ~uu>k0!hr@@o76`PljH zU2_JPN8s;lOz;X%mHqb5*B+kUtrcz@(c{z${{rU+K9($5$#+(NS8JX-30hSkN6l2* zv?)^^jI(0y@hZiw{N->Q6J!-#t$6%f8$AYV`byvVMzWUXxbJQs>AV!Ec7f<-Nv4#We6 z{J3Y;64N$DdX52d!)fpuR659=0iGvd%+mS*_QuW{$`#=cX~Z~|O2UEK2^w@^2TO&| z-%~yR;*wJjQ(*~8kwAGS({Dr9tLceNUj^*dnzeCrdoHpg8*2}cYpj5$_3ecskmdIM zk?X$|>5WKV9Rt=cV9IQpxkis!!>ysX)OhyTT(KtVlteS@)(O_6%%H6l;{}?Q&fj~j z<$`&!G!u|9BZ{%ZeIrpP^H)L3gK&>zjp6V>Zf#u6w`ul>C|4rD<+(4l2ME1z?xD@F zQoESQmOskG(#}|gDC3)!BR4b3H*yHJ>}%Z-+4SU{IxJsE+U*1qh*Gmyd2X7M=Xp`* z>N7DR85eH+F|i&^K{pG$Ui*U1PF*4NIRwhsaxY@p95TlBeNseLbN*ZMtG44N59Fnu zXl7pa=cn~=2@CmZNJL@d&HAXl_ z89Wf97UfOio8gzq6p~ht$9gZ5z@|Zk1hEc&Hs!ib)?fIpjEPev9(9mAe9^ayg)jXE zSMHE`F36uamX@y6!$U_pP?$Bv@w{&h2)_Tgsnb1s{Gpncl~8j^h5Zu02)cvGy@^b69b4L3R?So0FxR1}h6{QlYZF^rl3N|Bt;6w$ZX zTC%La&}zG$&9Y+Bk73~-z9k5{Y4tCD2Wad6UBqKA%g&0wFR2P7q%&6s^Tr8dMi}Za!YD(nOUl8_i z{~~^J`Rgq3!Yl|FrU}zCw_8JpW#(aNwbNBMGg~)vg%uneip0uV=*%GQe9bsb=|+L? zYH-$Y$Q?+9JfO4&@Ol=k7mRO!iNURbN=>+$fzx_gVN4v*!ze@_t_JU&;OHy@n+j3* z593yoq(?Jhn&h@>$@{rtn&_j9yN6#xW`)U0e;SWV+v0Z4cedlHmm?SV64KG&E7v?5 z-=l#M@QKG46s3-U8>`$8itIcD>qUN%@eoXP!^qa!EHc;>1a1b6O`nBjbTraYc~VrOd2nlfO#crV?e zF46B7<0=NGZNdaM5h}G@co2}X0h@nUQ3u6()G1tGEkrFAkP(UkDG(ABxV0CtC3p4vMhZ!da-W$JIdr+{cK4566z%;8xjuG8wKy}8qf3F#tl=7$!)N5N zzRovs_pxiLL+>3`$&;q4;{odYBm>tLY2nDgt=#zN(MY#nZl6EiO(r|*+)tk_fDSN# zXCR(&|7bg*2hl8@&!N=@Q7ZN!(}WfTORrR=kEk-|F9&5UZw`CcS6VAhvc8(1?Ft^W z&5thEg*Cey#(_=5jei<1b4Yphxt;xy-fB72Qy0~Ss5X4V(;>%*6vHHni$OieSNWAx z0fW=!%NAs49Vj+hCom@iiXada_p<`i+HWd3fwD03=Ec@nUUCs^Md_!<*uL3}3V&Ip z%j(V4)$LK>1E=fvQ`-@$#>NIzA(pwJ0TDzWhDBZwcVVt0EU7(GQpjS^hsjcwNh3i84UAHQM}0}WJt#oT-!GDAmvdNj-0&h5}? z*+~b#;qIo>))Iioi8SAFnD38PF8-#t5XK3SF(e^0&9b|Imk-cVcOK-hMFeGAJ_=@MXo@ z^!$c0+wI%NGye(=z27%w=&p(^Sj7r?=C~P%*HozDv23OZ0$5<_DJ%(gJzeY89F&H^Zn@5747^Y_rgajB49{>zWELcK6U3`LEawsN!^v%CDTpn2jL z6YOgW3ZEF~vr7+3itoZ`yG2uMk zDy%?ZYdjvnv7dFD8;*TNn4_XeMVUT(KXv4^&;NnDDingsjAnurYyxKQ!_R5s-x#HB z+i7cLxbkazpN%9(_4k?4bMR8Z%SdMYNH~)jLx@%UC<$E+hEOAf?M9~YjqUBereFS z(cJv9d5ex>Rk;3Nhj z?~d>H`p?3S(vP0^mM=I9V8Tdh>5>bW1+#dl+e;X@>A$qMG3Ghw)fXx zHkYM+Upqt;L@HSPEWDbNjd}*L65C_Nkj9$*L&VXi=Q79)NviIs3bkvlC>T!>#s@0W|a`I?>|iTz50 zM_)sJ{FPD5PH*3k+u5y$QBs5L&P>{ku;zR6r@GS>hww)QnDZ%!$*hBd??(iovCCy?ACPso4 z<92NnK0}%|h$kZ_h2*9z1M=bH{bnJ$-&}n_^dOV>aRUJ*RB*=ctVeaFw|*GWw;cHo zd=W5uR9*5)l2tAJV!>_5?mL$0iwdf%o!EjbGRc=W2iE^txstE#uLoz6Z41xQsWBFQ z(|c}V;i_fbRCXX`&|3To{X-ATuM&N}?Yf~+2`*QRLLF5! zSxlj2q4i%_Qq}{5s`@?5`tu%JH`z;Wb7ip+@S8n$4_pM)I%shUcaI#k13gX9Jc z)V-EezjpRNnmO+~V9{}*tO9YS`|7#3r?^o(X_C$a_$ybOPYj57z`61!>Ff=)A%WdT z*$x3JuhnK!E~CXfg*JNXY{y%Rs~4^%Qmsa z^6Dp|;J1=~*)qC(H{`O7+C>f_v8nrGU7|o1>!H4F#I6+kU)T;Y>{bn0nK%(m5RBxr`0sp3$ zpw%>)<=zyFSR_Bwd9SQAoXYsIFeSSy|bO{26b?UR*Vf za<%;q>Z;1QH+JaXGu%ui&6s(*1rmqCh#Jg-;#ESE7N2A+5Vp&>$~d_iiq{n_75U^& zBjWn6q@A$HiB_p1F*VUO7FThz^m-N-HM$f2g>5slT#B!m&#Kq3SmVik_=5r%7BxNm zP|ooDdFQ~%a`6%knqn*8REZr*Dj71}E^J0H-kp_h`6#Pyf9oWj3P%ru=d9kLwC(R% zirH;XY@Vo(S@^sm`~r2n&{6lck3+{i50;!|-}QV>&DMn%V_kq=A%I8s;*C<^KcRzb z$8*oli#KFMq2|(TSQSU;ns9FSH!oP3R;OcRJk42)jdjr!+EMJ?;3PONJ8xH6lU@f8 zfg)Is4MTIJUd0in#ejb!Jm2)MUUyv$x?{f?c5o#)M%}>rM=L)fyF+kC zl7bS+Cpo&{Fij_-`o!)59V3NZ{i`3kymzFNk*ZA>*5Verq(GiS^Jzuj(cOI6F+c8? z?6Y|fIHdsoVJlhB9FHqOD@tM?O;7^1^mV9Cg`7<;sWN?+kI5Vs=1R{{H=Wq!s$iVm zahQ4ET9dY}JC#_LRGSal)6x7H_IK;m{fbvt4~1qFThSyiiz-r-Bk&>A?VXX1gM4Sq z!|l(y!io{HrnD2ZfgWCb@pIj=DdGT1s?dIhAJnD+d`$@`Dt$$4MlVgjOMUypOaBCT zRPlRtE9+UYdMTpLM=1t0#!y+u8SikIkpW-JAoEcTR&E5o4y=wcXo+vqV}>bY#8Obn z1DwFct^yK*f^PP?hF(3N3(lAPZ}vSH_bzS;F!?=t>YH20_G+H%`>K6vedp&P7C+21 zfo8UFr{+G%B7h_X-UIrA@?NbER_3`#l#8rG4+Y>lh`{d%fD^2EZ*2ST4O|r{)f7yI zb7!c2YVgi#&OMqgEe>H5iV#ZZ=jYuOn5_@8Wxgt4ja)!uFn&}4~+aI_o%jc2eesfdGA;}7{L`(5>tD&GsqJaO)UKsF$24B7b+UhIKm@sKh9n1M0@t-sFLTURp_WO= z@cqzo0bhU-gY<=oz5vo0VAWdv)h6Ka{ea6m4=KUsT1a=Rp4aB`rpukqfeq(KA$qIj zBBb=exrwFX6ef;620NaFTd$&PU<3MAoekl+)HSdn>3j9$!t^o35*Yy4l*)FXt-U{p z-SmB=+PbjeoHt={egbwZ1rVXKG>6Jk8**L44bYEqcy0}DtqjIFgzqAm=|FjL76bz0 z96iHlfQS%_rQuaevMrrww}1FuG2gA#wqAGFFYSc%mg_He81M?E=nV?W22ciYj%AwZ zRYR-I-k!m;+BRBc4d2(AkS4M;?n2vES$@bPi9<&3t@x;@E$E;`+-Tc+YiTc-~C{zxD4Qj=A;9 zUuFya8{?@Q4Xu6UQ@=-zZAt-vtFQk|Yorghu29eN9^;x_3jh{w{^&bKO|MRMxBB%; zvhq7p3EwcSw=PwevQo-bm1@N-l^4<5Jpi{}Lpq&>Y1)Cgo?#-DOh2t=pNQaj9+Xlj zmzOX#J&tO%0!|E4_@j)NSF6|lp;(&#bg5dN+j8BmlU~=}`@uUDfFicth0lF#>!0_o z-1LLKl^a$Yru7zX@D+w-aAGXl<8sDeCu3lo!FRnN5kLqq!vGl^TyZEN!DBYOqKjIk z7RhCqWums=p<49drF>XP6H-br&XH)#24j5gKuQMFu>i{gGZ`$~1o0Y((F02h)Bn8X z+9zG7=K;)WpzBo5kB3{|-d42$fES=lVwqT`V+WM#FiacSj&-Nh{5Q^C1)%_vVdJk| z>znZZaN4aM`j++oSZ>H4X#af?#qtF%{}eUM!4M(nu7YWn($fp=+^=;|k>wvzvq+(d zavvV7ifHu#_)v#i4OnQz6s%Ymh?&}nUpM(8cuu!kgYSo)0KtNwgg~uyB+xr56H2-I zu}nx&f$*kam|Y;4nr_KJh7n9f6od4AO>$^33VhFlK>+C~i*S9Iu?V>c1`a%6GFVm~ zq<~842pF?ZPi5ENRjG`>1Hk?l&BQCpOQKUNB#+IrnDe=c^bUieZ< z@$%x#SqFB1?|t=Z>0OCT-cGf3K?wn&6plXrV@N5`+jTk$ox{ks_X7axejT%uhtV^% zaoL5LF#|*EF2GW83ip5eGgx!x>(M)W2GY51)GCV@JG>joOgk(q_9R-Z?IbWUvIp%w ztKrtl=;&Po(~eN*7B!{ zMq|PH8%+N7)L*K`+7$xy+S`YonDVPx0t6PUg$9d&Bg-_gX5CqE>ouC5n^+r*#cv|0 zyGAER@7cLy^H;W3{nbD32|VdJb%wj zarQRP^U7Pd?HYf&uj3tmddoO)%Rec#g#cU+;9LM#0JvD2Ne1T&=irtRNm-@dJ6rJ> z4BLe8lkmz_l#5Fs(+GxCB53phf+Qbg7+{tO%d)^Y15bLGpPqwIE}TRThG{@5z_d(A zRYg4Aw&285e>=VZ!ADMT=w)pNyXF*L<}`puTHo4MwE%$Udoyywe`(_)gPK zA(8EWTFrligsR4(&l!Q~COe$Y2gdm7$;%>^H~&p@a6qZZWj{>JQ&FlwFwJLRdSI@! z!9F#T0yJ2_sBxd*K|*6f6>Uty3!;(=P#&OaP|}0x6u^ySLs|e9-M3z;YV*T}*Ff+X z0>o2*I|m{KZuY{khaklalyo8dBBb|(nUBR$SZEVP4IR$v`0=)V>h$qi7{puyRUcdR{S6;X4MWL;=W6nMGdin2WCyt%D z@1buWKD_sbKdRTN-v{B)))$cC`All-^> zxM3ll%z+ywl9`5w6A__nU>&$&VDAIpz+(@519KBc;3P6S>Qth=cQt&kj>Y*2JprI8rgg=YLz7xPiFc`#hE_ebKmIID}Q0w z_Pt7}4*~cY(Mwk!uygyx78soY&~F3E(i5`d$wabp!FjJ+(c3fl3d1mZ0FYPrFf%@f z#ko>o7%Q7J`z)aChf)p&3XIKJLs&;Tp$1Yxs33lpQ2-Dy7C8OuP?=D{A2jjMAObPS zauq!8JQe)eqyubPyPj~9V2NzN@D$!A90EuM2njG5xwMDBvTO(K9la1zCI@>4ep`56 zYJ7H5-Ez~#U)_53-OmdM@TE_Ea5&d7^xyN{!?|4h0CJs!PwSM_fBU*=o6!t_`&(D5 z=clf`?#>8!zx~F`zgYKb#|&Pg#QfcvUJf5gZDdl2uez)t^9vGh*-{t%M+}7)U zaiB_jMHB&iODXjq0CE}xxCFo}0p!DUDq=y5G~*2xk6|%z!+@Pi0-Qs5BDijYVA&bO z5i`LAlsP-fGGg?0r)>Z{Mu({YvqOPkw<>?Uss$U#ej%> zrPMtD-f#+53*XnN7_Dkm3jlb&>ed@CciIOx{T1W(`vJwBL=MT^&?%VyJrx*m;(bE% zuwOmNt{+WufMD?_#)3?EO%YTo*w`o~8&U%zaIW?Dq`(agvQF9*FiZweieOrOVB|oFDv0O6SsaWUc5m4BFu$_RPgIAxM@JDAnGZRT8Sz< z2Dd&-w$u4O5LIry{^E~cdEMPF_%w|e6FYZo{t4=(t z05D7o+4g>vmu3S~zEx*0lWSGW3z(Zcf>fsCNf+_h=S;IRk4iP?$6NVRnav2yud z^sPJ##|}P-`RU`!000mnmdN7Zqu)oqa~MuM0GR955;_LfgBupydIgDe9&68hJ-A_^ zUM*pIbRSjA3*F;KAH8gF&3P9Q(Z6aS;LuA62)J$gMI;&D2;eOMGJrAx>?NRTnaFA`pccK(y@U&HDjT8U&y~m!OCuc7q*@V__KL2KZs+L8!NE+X?cCY9=@G|rR!mGD z-)mX+s|>?TmP(8J^SSoU*}3Vm=X>`v#*U9p9Q_VSZYw3z#OXKyy7HR4o|Ao+1_NdR z+@_TJB!HCw-bRf5o?%%VPrm0On8`R45!`AG$_12=h$pj{ogG1~Rz#c8@U%z=X)&nR z%0CA1zXALRz%imzPBQu;fDh|+>15>s_&5>yt#4+lS^&WFSgFFwx5P8O@Ac~?E~P-a z{i#j=PI1A6kP0T}i2UuFy8p-}K>v`M1BNJQpwTqVP^#e*5bZPcE+S$B@Z~Q5q4WN- zO^VjmM`nErkWvNCsIsBy7hVx=bsF4ALU@aS-L2{WtN|E6hDY4=x@E)64+L(tN3P02 zahO&=+}aT+RfR+eoV9@w4>n)ShyV)V2fzmlnF}F!p&v_z;D^a0@B^SoQV>us7@T-7 ze76M8TNp5n%%xte{mYsb_riitJ1%WkkWfS;4D8V>w|$}fQa<^w+P3TXE!S_pdW>HC zt8M+slv-$F$JzFP~U-e6iW#FK3(6=xuX55|orb$p%u>yXS8FmY^e05GHr$hP;x ziKo%G@+?dr--pW5+%nK1nQcdB-&%|x*^S;6XTWk2n4ccO?8M=q*Hi+GaTK~&p`&jt z>{t>#E6%{7M}L5&`3VFQb9xVeHv#yHQtIyj?0vDjsPEiyv7;2752#-Ss1HPCQfePa z{XZ^n{P*7Vhx%hwhl{g|?!xq9%&oaiYm4@IQGsC}F>Qpa*D!AK000-k`UM1Q8l==_ zfE1YHLg~pqHKy%Noj7AmKduJXg@h5muR`WZ<8-jxR6H}0TGn; zEr{+%js1Z_V0sn;iIGAo90ddsnkmv8q4Y=dE-zz7N1hl~RAJ878*=(+=QO0O9})rIZbYP6fPLO2vd! zTq!WqNt(Hi{;o=SKBdWE;{fgxzWeo~kNx=9%S+QcdWSbY@(hmcxKiqa06ugA5I_PL z18@_7@3g*st$L{!y_632Q-Ay36>XgxKE}=1TL6VbTR-x>XP#gx|ICZCfP!!EpmAmq zEnh8b`U5RugCd}$g7AI#o)0Lcn{?S|;FWCX45Lv3g_!_4+E_LyiA_@fkV+Z;ky1iI z!F7Gzd=ttG`>;5(8%he8b^%WEOpTy2otG@NXMp~{QqiO)8pPgXf@!Y;qZF8ak5u>=N*g5+Yfw9d1T%QFk(0g;ZkiD|!59nTZG;53%|O4Y0JpY) z(&Ao7QG@VncU3DR@4oWdJ6}*K!0p>FwgfZSmTh0C{jyyMcJA1`3W^*>s;Gd4tG4Z0 zYF!>%^(;63X#j5r@W%koJlXB0j_=3#(cKtWy$Nj{15fzf<0#IJBbG=bmF+?@+YZi6 zOpWft;XOaZy0hPaOuqMok1Ko^$M!!6!*b9w^ok~+Kw1P0MRgj{ZQD$4C~%2uKxF^`STC_=Ue8d zicJk6?0qq;hop*mtMrX8sxsKiYEbuKIIup7G-cf4Y5X ze)1Zn6xN>gYtYe{PkC1~`x*x^c1%w^cW40M3q;gf8(Q_e)zsnRo^4 zxC1A#K|c*?x8BX2p}B=SJtrL-I%G%GY6J9=MBi;tsTorM%N-*e|L`u+cT%U4^cY^z%J zl5GB8r>82Lo{D+qdv#2V?17RJZ5;zhW(v_#<-0W;-g_TrCy&61rO>}-6Y`xyD9(;y z| zqi^L|kV1eP288c{h~dEQ?;_thj6%-}0EAklh@<;{0wo0o*PaKLCbEena2DP8*gaD@3M5gaYN(BG_ z=>!3TgF80NjvUB-a>J|YE|lvv);1vk&kxo-A+_HRMJ$76KcEP~(6nT54sag)+c0#q zuK@vr2S0oAIe^*eaqNBM{^H2g_&-)_wR@Gqx3_M8c0qut(S2u(9p3%5T4k~8^b0OV zESWvkyShyjf2kwUq-FqIujBvr5Yc?=iq@)DwW?Jw?Rv>b0B--#Z?}QiCc|(n7%?RC zL(fU`k0)yV)$&w;h9)18@gFrA{RIxh0y5ObhmQYXP6W1 zsbG5gpqT~%y`)lw+Owu?K^4(&Rg*`6rUV3r zOyNXd$wp!U1!1fqOM!?$hBhG7><7~Cnvww<04(^M7za}X-}PWR4u}Z0-2tz*05Hce z%+y7n{K)VA@ZBHyOtE#^wyISxspfwpfY0k#v8P^?OdB12YjJqby>Q(sX2uVpYhXQ` zcp8S~pwP1tQ=|Jpj3Jo{=-%mE7xEp$02Dm83d=sREX;Beu^O3rgE+GHKEx6kwD+uzj;B`6u_H>Vb_LlJPW~gxJT=yV)%mLuaYj?Gz z60K@gt6BiSvr*hit~Bk`1#Yc~Ovf5HiNbUCT%nu4BEXk{3?Ojk*V(_#x5ILcKY;

      0!x4t@ajbn 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
      E)H?hO98V6#Qm7_HB-DJa4diGB0A#d#sc^vL zzEY|KI+x=UB}(*EP8CfU1<9JsO}&H=*+h;pMdOb-1eaL@p2*E<1_Y$fNsgO*rl5j; z+(g!pMAyYpG&U(?21`K(W-tW+#972}{y?3A0gNh|v2O6Pn8O&yAN*{`A9X!SsA;=p z)a&~|B?FIzmPe^Xgwb#dT=db}JOjcQ_U->3RBF?phM^=FT2htC6~_;m$#bR&AfONJ z*&$zMUI3|H9~r;{1rD^gmT~6P-53npD3zu$RlgVzK(DuiVX%hA%mQ}pc}D6+j=W>I z{)Eq*z6YJo8j96vY^|L|;P(-P!v_aZ|4qZ7clT9q|L9|qQA#Nb01gWt|I*6Y`wN6p zn3f02@gSu{=nvqP>IgTN0Pmx?RMl)}X zBwm;3H6vxpVuci`943j3OCzh3hBbM9nt794{NgA?5DZ}19)ySyiwNEJDr~nX2fY?4 zmKvhHwT!^;Q_4)qn29JH4MxL`9fp4BxW%ol^)vlat@$O!>|z-9?zV03pIhxyM|m8` zFz9tb;7b74UVmr&I0hyjWA1Fh+i?v6o940c6SiHNjd_IWxxJX$whsog(k7J}OjGqq zx>u#3BUBV9LBJQ zLw|Y<%D~TL9V<|fYPJBz3{&%Gr!hvB_URy+^^~RpTj`}`cL}3^}67Z$xLlx zV-_IdNHf%87-ku9)JN#I!Ke+vLr6&2Zc|2K@9+Hnxxa{`&fl7pt^WMGZi^@H?xemc z5a7s_N8W@4q$r60SF$$ativO!Ex@ySFp8m8vdw@*81X|Kk@1t zu6$CP|MwiU!?^sKl}+b&4YOFB-hK&6{vcOCelrhBs&b@(}odSdb?^+Y+2lwMxx(n;=c zja-zj%np=^>pzHU_H!EcJR=~Pys7liSo`#-rk!CocUo?{uxr zwNg@S4qO1BfrVT=Av+vEn|84A@qA&sFr6@EiRxxT7^J}>ABsQncJJ04T@|c zDFF=nZJasvRm40(p;W(rFl-&$*gF5k^J~X$yZZXuA9_6BeJSNn0{BA!3*RvdQc8$0 zg53rb22SR{8L7P`h@LPDZD1`DW6gx&qQNm}U`=^i zsAg44k$y*o$fnvU*e8Yl&KeoBCt)iH#l-PPJy4wU}6>o=9zP^um?*A%Dc3P4GNWcE2iNQB`C%ZvBH_xq5XqqVt+Qe_&Y(lku70NXA> z$PjTfgztA?nI_^mM5Q{7=JWzA+sP*S8UP?UzYmg2Um+y>j1$l=*)x)MGzAmJn*U51 ziM-E1o@FI?3I^nT0+Rpwoedm&;Qye#wG7WIqgJ0q#H005(EIbH%`<!Y(MaK&W+p z6toRyI3Ef8^}qi4w|?-R$-6nJZ$*9Z$RTHT$AKSl3)KU&3zt5-T$}wF+x9>W6NBz1 zq~K_8oX4o&La{o1eq-sxksp2Kuix~fO%s3fr9^V;+SYLXm0+bGuGDtG@oHeqfMJ>t zajYn+$w5_X=@N%+MX@#1#gVII0CjjKsfiYdqJ}1usC2?c70S#ELruagTT$u^16H}5 zKE~rQ|ND9%0Rh2i(8AfH|ANt=9ow$^|7@Q8=XdbHA6#?z_Q~{rQr{7E%aKD&Ko*-b zyRL}Bz^FI&{3jX9E26;PO$j^8m~|14;{_1(o7217%rMK2S1A%nM6uK~iKeEfje*I= zritm4pUYf&hfHJm@=;OA^qj{WBIddY7g~F(55yNV|1!~`>S-i$O+QGcbxnRJ3A8p| z0|olIq#ApDd*u}%GyouTale`W0LFCh1Tq%t@mWq^i^TOG0M|`;@;Lf-l&OS(Jn)%B z0H!qVyy0FlNt78VkTiYNVBk?8PCWRzt>K_ujl;m0n!Xt2%AA%UBDaqLLD)jSe;%V@ z7nbGXz-8ZuLZLF2R76rk!|a%uc&!j^#+XuibGqU*0#)Xw)~UCE`V7?DA~5oMIQ7t% z5c)$@N;|-)1!{ySSEkUMSx8L~^N-zbt>B@fp9eEczSUW|V<`H++v%>}DQcs89ddkr$ULGuK#-_rmu2qAXMzrdz0u7-M!6`d>P6-)G;_ zZ7f2p69eD|J-P%-bdf|I*yZEEU;?$))5|?y0R;c4t zsvsnmLa^!CeS`Mak`V-hc;~LCTaH_HOw&=#t~S#njDi}u19Xl8pRz%vRFn2tjGb8W zKtUQer*-mi5M>|%a?_|piK{32%46#S{U||hTF~`VQu9k;y8$UVf&X4{>mSI(_pry|NjGkO8^wUooDJ~!p}#33hW?fES-P= zQX3&AU`;ylPa601^FkU!J(fNtvxrS-hKdwIuhV>{ZH{e|(BE^7dJ-3ztdGP`0IAWO zZcMobtqiJ-v1KkD3+dj$;}|01Da#;PNIZ@qAP|Q>!oWwjy^3CE4a0s5wp#)LfnnOM zC?4K59B$qhNBt9=htjcU-^7@G1z`r7Qwyj~Er1e3CyvmJ-md{bMww=%%T&v+ru~UI zX$HV0?+?}K7E=3%fI`VSq|n|bB%S&vYY2d59T^Xk22d?u1Vsuwq-#e5L8(80Zl;OB z(#AQCd;q}7W1q)p*nwrcFqj2OOq7b-V45zZ;1~`!F!Ec7qaiA_DKN^=oY@82_F!4= zxY2TsZKVLboKF%&PU=H4W587JPcueE0;Z-QaIX2+U=hiA2Y@Cr0d-asf@5p_EY?;| z!w&|q%nEANoe(_2M(c#!XrKG5?r7^Hox#T6U32}N;ln}imosKN<#MI@J&srDODXqO z8rxsuc*TQJF!BR`5K_jtKkVHT47;CLI{(mzUVq&uzoXgN69C{lq<;TbUqMQ>xM*6{ zDhO{&Aq$-MeLEK2t2Ej)sYyN2^`Unkw8}H{jc_>lQ4q3ZJB3-pvR6&hnGQz1&u*-p zUb*(VJDxOT^QIdQ6(lFGTJO#Lmspt7^{L%xOz+W#U>t^}nh27+fFwEGc}hQ{4Ae4I zA0YXd)3(ynv6KZcHciXXcbTc1f5u?g7R*9HH3DCU{(m7D@by4~DD<)T(C6U~+AM{df*s@Fm>olrdm>{q$Yi+%}4i*HM%+1 ze38(W$6Wc9=ABU0j7v!HFb0o#+92i)v+{Y-`KhN6+0+dQuplIeLDMOI;-;VK)Ki84 zwEOOn05eYb8DiX{v!vAkfkV zp%45dkv8Q($E4|?Of_~q3=u~GR+b*pHiSufoi-GeLU}%n2IzG+K?y^*vxZ)0Rk(#(90mg!_(Quf zy&I)U1J&Ag7?zu!8*g0;@k+N?k^T0XWjRGN9Q8?|+(5s(0VyRIGr;4hzp;Aqmsig{ z^zm!2|IP&gCIG;sCN-(=*t+@1l|RxMmVT|(wSK}YPGQ^p(_va}8so$aBQ-Wk5pb4G z5SYnQ_x{A>Pf7`zGyxJRV<5dmidd%xuvAw^+5gYpn@3xA-Q|Jb-uq1V-1)xwy_!^2 zDveCG#R42?1IA=%4`pKr!C@J&><|cx$sq}mEK3e7n)K=pAqm(fHn_9g32w`nCLu}F z?Jxuk1k09e%{AAX$2*>T&e?nSAA3BnB-;s=EXnVzWv%C`_v+ny&pG?--#0R_D6&C- zQLBX@if)wqAM)@$qs-q=AcWdR%51;dvp7afT?W zXPwz&K@vBb5R!#q&4!Vg0oWfn)G$qKXdiT@hV7BIGmp^wIhQJJQpk@1b@YBvdK}n_x|Ks2;qaK*Iv+ zAxhdXJYsDFDxU*zyr8pWjYyP_3C3740dqk;=^dQXTf=i<&|?N ziyTQ($L7W*)EjLKM|+pR$o-er9{E4tcJKdq$Gnu10{AHa@A3Ya0ia*h-um#6uLpTq za>%mOiZt%A^1gz^8GkOT2MrIA%`G` zfH_kdXXNix0dS(=D5kk?1`!wy_t4+pz|Qt%KmxUT3qlCAI}4B?2%{QW?F9ruY=6J0 z7xiD81qi(RnKG)IE~E=E)%Pu>6f__!9*%L`mePuUEu<9)b0C+)v4oL;54nfok82jeE#tTqp*T2#D02ePl zgd(4!UY|uPUD0c0iD}WtaI!wyA8dZ;>c$iQbUGPc3X}9)x3l=>Gq--@KjL8!r_CpETXt(HzRICPrN!U%`9s6-VXQHfA3`fgiytRK-%CK z#V*K-U+wUNo)Dt^m2p(v<&kIE^^r=FO=b9p-gu9PyNKcx86^)Dlg)R$^_}m(baeKQ zjxW{m-uJvdB7!c}TeGL6DB~07?)smjq<)K(a#slc4WcX`qDrq~s8~~LCA}R^kc1VG@siaa5A`0O1eb2sn2$r??r1)kdP6@yrlP=(S_bZH- z_SxzhFjoTz-Se$et<5Ib$aN(^i2CrPR27JZIh6o}&@3vWV1cU>vp|UXw~2dykWzb; zRi*(AnDx}Eic@8my6M)tg4HXZ-I)ycI|uuljIt1|<_QErtQ%3(XA}e>8jX1*wHkPt zV}0#OB>U@FI(Cba0uyp$y0cvzGf_-KnQ{;w18ijBxrXR(4JYu&emlJ&N0nK*xk8?BF_-VO-!>9>dh`1 ztvOJ_ASF;1T;GGRAf}YA5kw1E?CVq&fNiM_qch~h0QEZ>em)~sSO ziMrZCP#~M`VteZf_I6h>J9ivuy^S<&Reey>vx|5ZAY0u`sh9Tx2L@;Wwz9?202+i) z-hV$Izym};32JEz?ba;TSDylF67>65(MXp-C_@r=AtbMdQR9aw4enasx%ifDXZasA z>YX=*K^)I4oEWFT!m3M?vTi__LzR6rV94`vzP)}yY;Rl;VN|O@Qc_E1(5NqHa8(T( zWm#Z2Tmu(l3R#*8@YP<5o~W>L6MKKxp(;i5(K}yv%flSrMSY?2d^jAI(QEeVDL%yjKv^9l# zco%{zbqw*8FZx%~Kt1byK+q^=gb;QOv8oacLLVFjTdM_-Y_i z0SFM=AYw=m0|J?>BdRS$79h~-6T7YmjOc9a>!XO0;LVelYu!u)p;mw%4D2%Ugcp1G_J@J;RX#;DyZEJn+V^i{kXPb4zD#@6H|n zS}A1_)tcQ=e_QY}zmiYKf4=(kLmztoyWjAcx4r9Q&zfBMf%{%Xe&D`O9DxKc!sGq- zzdjMbH$&p<0Ldie1pqI30N~dicq1tVx>*^%9z@bGs;P$zywEUWq;OO}G+i3DLi)W8 zr3ZBiDL{k^Br*sttqdyq;bI@CF8C;jBLua?`Te{{O!ccn=reAtHrrW$66=>ggD6T5 zvTXnD=fCf0_&++n*tOw}wf5}tS2w$h=OpI`N!t3(g%h_&#f-4}Xx7 z@RIwvm#z*-sfHpZ7-*n}0^8H==1uDuj+Rz#Llo8~JDZpL z0%dzL*+wmHgOU(LH>I#3M5}!aMKJ_qfFP9ESbYkE{Y}iypTf-CaSgJ{DjN;rrGN|1 ztLs3a%7W}ygGrb3qW)R{0$5r;i+a6{Cm;J0lx2~9&rkl!e|-*b!B{8%lV>2+B!H0= zq9M!DdFth}&~To9z}+tn?5TVW$ABLO0nD?ia^35jPx^I}CL6;Jl->pFRae@9+FH=7 zxf&Ks(rbhPEQnU|5YrrB&Z_}#G~+J0tHx7*uWc)YSrdYve_?Vv)IcmOi%+TN`4{ea zZ*n*+i!6v$MG!_DB1qvv{e-NXm?*Aee(7dNaEwR$00gdHcnD>gV`u9!`n#KG_m=6;si4rFTe2vPNpszF7OB5FNw z$^7>7CR!~50pW!MO07^a>joi8?Xz_3R@56^>}*`Z!QL7I8lqmGMOvE!qoHdq0mIzP zEtpOR*xS2+;cy3!efIY;zjzw$&O928u6?HHh0#+=>Jvir^~SlE58$IxdZ4ESIz3Up zKjGy6#CwK#giIJEXf(Un+gU}F#29D0Xf_wE^(3MV5Xxw;GkJZ%$0SZ$s3lETH%RFh zTpSjT--f}#7Nq3gw7+%rHk}o61OOZzdcc48>l>7?+oaOOaZp5pi^nLV!&<#_`|RSG z2NqA<`d3@sC8p5&5Vb}JEQqkPe)0JJ_SILmx{I$L9&A1IfBdiAUwF$;ec(?%_=|sQ zu3n$HGm6tYM}wVLw7QF*9v*Bjec*yR&79lk+RLB8pS6Fi`SVDZy+RI$HfO zB;F>&1!qAT#i`HOc)mM$&!cDA+W|KOBZClv;r==fwy%QGU`il;sjX)3BxP#&q6#;sy7abp?>p^YIgE_pPQ*P{*?AwTD6w0jXc7@mu@WBpYsMT1%Me z?^Z8~3vGRn&PqUSE`YQFXKp_C`dqDof_0Iq|Sm#&^Flsiggtw z2MExcIabTF(PU%o$x$4qwf^7=Z8eXB%0ycb7^EPG<2D$JF&b`ykO?N^0d_X8ATK89 zbQhHb*aKsY^!bKC->U`Fw4f&ycLRZh#*e)Ggn$M}!W!bJCR^stPCwa$V}ArRb|QL4M3FNWI?F(e%#a53p3<9wT%y!TRHAG^-!o3Eg+RYs5Tf=KOe)ZUk`S%VJP4uS zCrS(kTaZGazq^Km{WY{YbC{XC331Z2>HUO4-`i9X4`!(MFMAUJ3RBtV((sLXp>n}_ zVhZ8`HTE-<5>nbU0WVxtXG&O#LR7ODd;kal(M<=Y>KFtF!U(_l1T{1oi)51T;EB)v zA#VS=Z%3NUebE3wQg5Nrp2c{$7lcXLcp>gHjsSo!)A7Fh-*`H0c3!=B;*M{jgdXoL zoLVf)ye>ug7o+~pr}Au^b{9^52c-d9IsLT=<65Odw9%eJqdkX%o$II4dgoM9YwiEu zNACFQwAuY07DO*Erdeb8)Sa|DfATHk;oh{&vp0?gyANG_^p8IK-uusgAgMJjfB!o_ zbkr{J0zU{LpM#WC>2u_9TV)II_vFzvI5&ERU}EuTVDsf%8ieXb4HNTCM)Ai^p%fISAuL z%7Ry>&6zY#>Wl?pi?X1|MhDFxO2)0;avX$lIe+XNC}RktG^n>{V-++d>Wl?9Tz8`6 z$aeR@v#Cm|&kI|PY3sF2s2%kKt%$3oGXntkWdB4D)n3+ylKcCTUc>efC-<}r9KCVS z(8IGR1!$lLY({Mjp6cd1)WBhe9nG*yj*7I@NT3ZUp?v((_L>t28`5WG{Y1-x3nx=o zst4hif4xcNqI8m9!&;g2a#G!76VJyhy&i8Nh*K3Ag%fvyeuPpl=Sp~k0kHt6O&}LS z?Wvjhdv8VZLJ&e=+UiozO# z&M~yb5{APy3wofsmNiJRT{R?`EVg5 z_V+hHDML0LTzw9Q|1Sgp08-K$H157YfIxvaM0@SMWO;M#`|25&d`_y*7k&MJNR@3N z)cqul@thKSZ-VK}2O%M)^HNJIrVwsm^pP5))X=ZcRMh!Cerw|q21F+gTsM_$T2VyI zwQHW^eg$Tr!t#7@PNn2)mRG-b1CklpyX3qgvXBOBG7c9?m0zBldz^ykwM1&)yv-+( z#M%M~A$qAYdk2P@g_CG^7m-Z{2%{QyHZNiQ`eWGJzK&xzy$p;6Xm;n-{l~n$g4bbh z(*DhdZ$2wgaxeq(>GeuU;XUa*CD0-X_x_}S6iy9k*J7h)D%E>8Y9<%B@4_IRT0sC@ zhqW3Y(WrJH(e5mw*_^@tjtU4AqQJr63J56X=WeS2lu?u-ic-W;9eLSDQH*fu;zKxl z?k?2p9ru|S#@<&W5kFW_e`(fua;OPFNPw5l24Jo?Nh=_sxkA#kg-&+?JKNW=zrTto zX=0{(*4Yw-K&{q8&L^NE$7r~RwAniZ(0#tWJ4HSjfe@Oejoz^%0O07r`|o=lMG)R~ z;_NHl*_}V}*C}PS-r^}R79!6^DDr$|Zu#76x2``0$t9LgeH|oMivkT8cu{~dh9Hcw zc;Ys+drNro;ZGn4qql}}?XC6JEYf-#Gs|ZX#VKm_HYui)S~eM+&PE5PJF~}L{q!Th zA8f5Y^of`{J_MG4ZzybV4g zRP|uH#AtvCUvAcPpQ@eeM@gca%tDXXp_P!zhNH6?vmM*c`Dmeo?DJHmYzoT^UH3p8F)~%`WPVP9v?ix36CMbXZJB(a!dxB&xMB z)4N$I5A^F}l!34S&8A8W-`%@}@o*n&*B?i{-a$j}QKC52Z^=~wO0NPE(&#J9`}Eob zyeriQ21-$2Z+8uY(cY88(e5Xnhg(~Io(aGLTXy*KYUxm6$%PTqxIsnBwuywzks#*Z z@Pqg$K&0_Xd)I_C3I1L$fn`;t8_KbPGYiofJ;w*3Q4_L6kIb;^w<>;j@2;xYoqdsXNf@EUNGweMCteQBp^vJ%`C?zqNAu zYk!O~w)Sfeod4ht-Sgn!=%lR=z;jt) ztIE+x1rjES-AM7_P;|;0{VzD{XY^``gz#QIaCAwSqWF z%Oq{}qU393tGCo5MAc4}#S}ppS05v~c28A>sR|>*1`5COOGxl6Q^URv^n;Lx05H#c z>49Cg^IN*kYAF<}Pdx7|(X6Dw9IO{vdrN(mh7bbD9Cb?k5HmBJGh(a9C}2aNRKk7f z7&PNKHXC)}z&ztc^?SyJs0Q8HS2l}JOD)`H*qmeA1%5*^yH+Wf*C~V|gQ=7Jnj8h_fJ4(k zZp{^fyZ5Cn49)Js>_Tx%wsHOOkr2F5mP3q3Td2idwb2(|eVhcMsD*`vJ29E;DBIIu z55vI@7!AefsXqORItt)7(pKq#$~DlO?aTRrtPkKk47L z+(<82&}MHi$FS<4KU<}%6)DmW{xkz7V=62Zrl;P?@zwRpY-lJ&)q;wis_V*AolPMK+O1;%p~$iwY;9e^Xt2js+_VZPP>N3P zChYBA!1}evfiy)kS^k0<`el(J8x24Sn{r-k9svMf;m7;l{l?kTcf9f~GYhBAM{%8; zyyfdb5a}Dz^p>hCeRkojvXOBK2#)DE120MhQHVnO^UAVBl*9<58hZ05(d;guH-GY3 ze?O%RC(eC6dh@61aoT)0Wl;h=_=`tp=Ea}{_}Jz5J#hX2M2tA+FIlPhzrOEHluPm2 zLZmMPB#}fR&6H^=KVx?0miD2dAJjTPi|VvslNPI3N#m8Jb`UbDw~$^Zu1z@ScKD$> zWRMUb?+*|p34&SzLMgJ{JrsjJ(uD;Cag1_2Mz*mILMWnk3p5Nt!%zVLlprHhOecNR zTQfzgGxxLK`kk-)e~+&2=kEC6FZ|6jr@#KSY_RvscM!^!!Z^8b^@%_K)F(dn&qt85 z$l6){qd)%dZ(#A>f8U!)2@pyJrGj#TDHtd%DXBpsOgpo(-spby!PeE!gh{&8oxkaU zByDC%y|ovH$(e(l>nG~1xm_W}Nl4Lbb(aL8w7Ix&+nr^R2a=azZ{ZYMIsG+p+Uz<8 z$5z1wd|BD5 z&Ybc-BO{GA!;F=_>O2v_b=rQQWcgMhU2QV&B$g&^!#RUyhYf=(9q?(?2Kw{#?E}PP)XcCXiDsQ8Dsp_u zIT&G>UpSovESPMrKeam<_v;zkj*DV|W@AP5qf0M+US}Mn>8u)-NQlvJ4TT(|*u0AI za36700|>CNa9V{5YH(|N>net$T`aHMqDYZ!2to+bMi=A3F1RSMzq5v-n1T?3gM-Z> zW%R;M|N5_N9bEeG3jnoOLxg7YiJ#;z)$n8|9YUTxNaoO}!8DghqYxr5D))peOGp-2 zMF$aXP`3b-R33c`OmVI%=%l*Ob>gIL)=-{o1;m-5UPw>XWBTn)`viea#8>x+yB4G# z{+<0rRM#6Dn<;GzhYk5C7SI@kFfdJ6Py?puwMP0%mr4tOtj0=szIiDGMCrmCrIg@>3N$5L=o}3J1{0R- zHFS8YsVWCgyeJC?+D1u=Q)ga=jkPCn{pzDAi#?2MTOfoWW~o}o;WA4)?GqS<3Hk@u za4_A#TzJiZ`ao?M1Z}IrIMRD!N`g@!4>Dyij#u60MLJcfMY5RLAqX>e~UF3SOky0R^ zWG12nL;}S$2O%NmmTp6oBwxfci6D$?XtZX#C(qsWqrdZ^dp=rDvlTAH$-T`hnGod& z1dkGlt+(C#()O9ZSdRDJ|Av5o+$JR{0XEMl{_LgN1R$u4g=7oU0;d>dm|Hpr#+VM( z(GO$J6=Ow--awn=XiuuIcl<)LSZcs>C^$8NT#zo9Ob;3)U|>;bgLr(FO-yrSqY;8Q zRvY+i3XxASUR^~H#o*(i_OSue%}pycBp}FnhV|9QQ0vXeu%3K)xb@VBj;`+K_W14} z`BxF8!M_>}cD_k)9`^UvCzOScoc*eA`MtE+i|U=Zi=X;~AH?qFWp=QAZQPwdnf7;A z_gmeiK!Tj0l%5TO@X`M6+IpNedyV$oxgyUN8tvJXvhd8Pzw@cI(LE7_@d|+Y?9yo( z#wjU_oF!?K?yO%RjrKfm&n!nl7(+@iWBTR4*h2~dnHOpRHiNv7@T0(Nm7Y)mbdqz; zRKt^s-nij5Ab@4e^*tek=c_a|UzK5mxJ?>&)k~_zj+h^-NQ4c@X6407A5eKcu+~lP zseTN@2dDUftR$pU9d1T7t7+Riv@%DS;l=YeTv(SSMF`Ita;8OTfekm)1jSv!yN*&rQwB6e< z_spsn2wY;j1umonWlm!3*S}fTRHuczphaMI{#32gTZ*q;et3U4+!^KhuvZirW@c^% zBSA%$uZCT<1}AYFNz{N41tcjUWQM_D7nAV;q~KsIM5ECG0IaP(fufio&&Eh6 zQuJ?=Fa!&NDqkwy01cg)!?R4M?h^$Nlw7xDsP)8F;0fteBg|x7Xs&@0Yx$8x`N$@Y0A86=j?&x*LHP1hsxq zQ|sp`C9J&PgFjr5o|ak&b?%sH4LD>qa>@zf!u#}f9>fWjPuz~~>@n=^T*v!tM8M!&Mvs}O{zKr^-{ zqik`^XLXG)4LPLMWl~~!WD;bn>?EXm^)>0if+# zy@NREARA?hRh&wc)7*KhG)yUNEsjnnwtFP18Bya0R1&_)Z~`fTs1|?T*OR0zbY@r3 z-(5S=nLYmR%VN5a*1PSSZvRG6=Go4uzw=0cckTKIf8qQ78T|4d5?CgX zFDF0(peZ4*0J!*4e6K{5A`^4-(`i;qk`Aaw*LhJOj3P)%byyE~6?=YCF&Ap{!c^C` z?^ia13}ei0h+HbQ^kmP%deDsb(fU%ge2nM0_T&L9QWgbKa{dI&!>Omw=YT(cp(H7UhiC(hmVRb`PSyv#8k z9q_s3vjre&SrpTJIx5meHvkX`&UxDGyl&Lrl~VGsJ+qP!LQt!BpoBQ`Bx4~sFHoy@ zZg>q%l`_oSK8by?FJ1@Wl@LW)T@B2J+!$^RBP@hU*fv0c@OTIy1|6xslngK)^)v?=fAe=6ZNtT zh?cc;qLTWF>rFR9zuy@yjf|K3K!P_A!37E`MU$2hgH%HSxllO{heP#rS2>aHnj@b7 zns`i_^G>Tj3!<2wJoB>N_SVJG=GxQKvK)uku6>f$(;0NyClLlU`}4%hn4l~`5Jego zXd@20NWuf~5(vWp7oYkI?CxAgS?0Xn>`cbl;PD`gc1v0O{_bEk5oNg%MsaUv@A@Sn z_|ucT{{)8|z5SjCN6+&TGXiiGz?mky9&)Q=it5mB_v?@psq$X!aR=V!h_X%#YL%0XZ zc_Eh8+C%K~S$e7{lUG1PrN-d;UKH9=WYkv%QV@bGMT6c?sBU<5Pf<{}PuBym3GY)1 z9}WSzH&5F*i?JC0gy77Pu55cCf&BOC4G+VIne;u<==B}7pT ztJ`1i@7{#ALLO?bWAce|PQIE|8{t= z_3^v!eQ@>YY<_tTO6WeM{9^)~l)$aJd-x@J2*$dgv**&3qn6Gf3==QwMK}hF1v(GF zd1-AgvXn~ZMvU~=Bo%8`PAE20rE05(2c^yvDT`96kb}T(b|KY(Zx}_zpp~u?Nh9aP zN1auFlr{fAI9q|JPEdzp~J5W(;FXYn0rDhK6e{FSC%GZ zy&A1$((}Dacg5&YYZ(xpAJu=h8A|{p1@jmj8ipPapxL?r&cCdmZ^jKRIS1EloWD7g zTqw{20^BI-0_G|}Ei(x#!8eK^>D4)3&1ejkuTW2&VSFe0-w=AZ;EIXhBb{&m$5$YbJ2&fKfH5F$%S4Bt(A}QjijiMN1 z_3EQoyZ$&zULa2EkB<4^-XI7*dFA>e2ZE72Eo-G<6S`9m#81BSH|3XkeaQhl3gA^Q zI-ot!4G%$pu-T{#eX4@91kZEuY-(*fvM3c8r3Y)u7-$q~I}TTE8q#BDO?{sQ(czj# zgajmaEf%(=!vzc)<(&{p`C>pa)#yX)bu1x4iDH^*pw}U;GJJ@~09z)U5^&wB;Q|NM zIv|9$!RXf|ga8p#6U@>E@fll^+c#*Jp=RL)=SrCqMre1J(CRLrf3S+-U;|N90}X(D zvX3b4pgVIKQVNv$1Vu4He{Tbv=g6`FSP)@x>1G{dOx$N+b|zBUipHqEG?adlme6K2%~I(?afCK(HNcjBIIZXwAVvYZ(w(Ggss&lk!NE-N;w|v zl4&-A6dd)|oXJvnXzj`)|Jys>_0bosTK5P5c#e-oYwoW3W9NPtpzSbD(df*h*;>Hp zU|3-xOggDyDHZBTRHv!+^+3ai;1wlK5GDWkC=lsWs7CJcVX^ z9+bIDp*wd1{oOSp1bLRgE^}I`+_}CR6J#BjzCoVAS8nc(^OWDE!se z-u=%1a&%QcFUK7K>i^xF<1eD)_c@j>xNHl1nO8fJ&8Agyp@0J6QlU*qn6U~}`jb6N zfV8RH)NQmp8-eh`!_@Weo>%Z{%T%heHrN|5&iAC64WAClGs7$@5>DqmRmuCMRUTN+ zu+PR*s{Fv_eM%RYW&5!~tP05Y_L}AaV<)B5qt5jD;W7rKs~j_GJaaC%21<030MP@j zpDEzd!aK%?!(IbO^$)EAdnuysoUVHesa(6EDiVq8-i%0z^0pAGAG?N zA%ljkrT*p|daXOu$8D?$MrunyFgt%!&}htb5BApb&Go0JgZ^4F%?`qPV}=S*APDLx z@*(1=0Tx7vqXvp%0!AVTUH~8%46b4I+GChbM@VXof}{My-Gi;)e)~WE$YG@ve<3U` zgpfi?`JVy&@JnXJG7Q)S(qVN}(jJ3V=`o z3TF4*QmT9r7s@BAp^BicCRD#4Q(dZTiWDS@ASKY7JB75~!Oqqd^bd9*MTs=c&}=S) zQi>>UAP5qKVG1D%j0S6+>$2vK5p=Q`q~jTrMSH>TNS^M!o79{~W*;qfnj{%^3(-0|;EYOMuPN;GEYuyo=MjP?dD)RI!iYUscg z!(0$bK)91anjv2yljKkdsH;Jvlp>!@0SQFuGv@+yW>?Vc%z*_r`d8|$8Pr=d=+2+O zlb`(|}Hs89QuH^c9 z)fcqM2av7?%MRT>lcH%N;`Ojw@48kJCPtq=5vauwRft#6rnO$g?D2_>GA11$EKPcP;X1jS=xhU738E9OL4bOlP7!O3uP4$bx{)?Cd^)D5^u0C5mE#dZUZccn5irA*$6L3L44B^K$&p zpJDiap&eIm$Vqz%9)wZ^Nuo@M@UB07jc{Evs)7kiRk>G`08wfGLUItoAcY$6t?kZQ zPpUP#f=l%?lzQHCXD1Hzq00E03S&T;g zII{5`1mDNyr~Vw{h0|#DmQZhWHIT|R!2unbs)1bTsTZ7_$gT6l*^{JHSrJl$B*dyQ zWEJG~6KABdf;rKXvy%~znUNYWo}D{^VmiUj_El`}Jce%jG@`I>TVM?6&`g&x$#*au zY+!Ta61d>#^_Ff70yOKA4f4~^A^SWcR$7pqz4n~9BpWD3l#P4q5@jw!!GYh9~9qesh$+F=Flajyv zzK_44_v%Lgz;krG|J~zvG^d$)mG-bUbGpji7!EDC>k!L{S1323qDXn3C^lNvwWA+XjGuIq9r)9X|vF zq9`DU@;ed&Fs3%~Ff5(*s7hPaMD+s|LP_~F|7PvSW}|G?WkNzq?PoOAK3ZbkKUl|b zuvG?8@Q=2(K6&lvEI%(t2;duDgvfB9oU5E4AkRgjloMP=qfQ~l)+`O^Kn z(wFDzVb5%62}}qbH@jz*3=V(zgdG%pK*3!5cC%}SYtu9CsTkaF>D3B)>^iKs-6(jx zw0-@%c%cH!SQx5dAaFr{>TRg1D$W4Mr*BWts6>y-oIaS4C0e&9v42oxRE0kKFweAH4b^xntQ&efWRYXSFw! z1xbt`iPfc&N;^=CJV(|aLX0!rO-~`Gg#w>6U~d!wPLA(&^ubj<8pfJ31{zQZ?yOFP zF;%f>LgqBFMhLOrW3mFQLde`JdQGA>13-8-1nSy^C{>^W=eAXaNTL8(N|a9=y23G_ z3Xl^T5Vb%oP;brRcwEEkl}9k@Zy^X{ltqp>?jj0P)pR5T7>$tDXH^~nDY3t|1|c}g ze1cAIN$-2KRm*SkkXrSw*Dj{57?6H7qN`vedR-xefdtGoH|S@AzXrHQ663-5))4sJ zs$OmgC{|9~jv~*{KiI_X?gh-x-F`#Rc@QL^d59pWVKVMxYyBb`jV_`jbwPf<(m=1< zu$7mVR@KbD`#uW_plTtgf(hpDloEgvinC{54#7FLcdj9u43Xy(q|Gj_u0DxizPUB* z?`+!+sqvMOa58hZ??k>!}=9T9Oq2yIk;*}b_DkbnU(aTey6ko5zy$fwxbzJ?$Oek)0vA9?$ae3Tzu8PCg+ z09blay<#E2Cz%f6(hRtflMA7x<=kyxOu(Nv{JVN2sTi|L*|@g5NPqJVKyXOHK>Ug& zGl1J{4O2GY@5Y^96n-rr@q+mbSfDk$QYVDFS~@R#KugkLDy&R1fyYD<^Rq%*Z;ZcH zvwXU>N&8t{{(zC{8|ktTCdf+zEQKBpxb!SUZfKykliPW4)oXJ|i|R24gas6dmiJ2+ zUPio%GU==dMopmX0@MR?h_xwMw%szPE}6Tc2E;Rj!$C8d#u6>mFt2LST`d+db^#$( zsG$XMr2BJvXyWyH$t!hrK?oW!EFQZhf)J5bn*@z!FMuAhI4@8XQ~AWCzgLLt{}x>S zoxA`3$JSm%cWqWp6#Gg?@a=y<83C;&Xe6<+wd$(Q;l{RoHd~-hSKS2xQ-RpVo_8qF z&sbUn*GhmuHv@TH_bd#-0tU`Ggy4Gkl@Ow|HKe@cp5lOdYk^Y^nz~NEj*s}rssIEu zS)f5UBDiJaDHRYPw(gM_Pdg;yq>htk?!w;oRcvovkX($gySqVVdgnlC%YmUZM58ee z8Zx9s7ybRK$cqv3e1w_V6DlJqVAk?v)>W(CF_t!y6=3HDIP%b|UKE_$fIvSJfEX*# z;b(+l)o&mqiDlb~X4;pJ--@JG$M)tG>>gaeO!qVb7FDcb_4)#Wu#SWNB@73<_}s&v zz{<%xFu!!#4eLf>W|Us`*`)uR9tsO|NHr=|HXcB2!3?8>@~oVc1(;vB34p}3nBvOi zM^H?L$W}+&yc}=5m~Yo30N_h}{OWzLB}vkhC(eESI|MIJjt=(F?wv%DNt9&b*c1W1 zKq-V@lmgs@k`Yuk8HdxHiIppvz#lc_ltpPh&_V*GEWn}=*=T||ttp>U$-%XpQ3`=D z4pn{NvtR+WdK=x@V;CN6y(Ve2Z~N8zUi+DM-1pn!=uE%3j`zR&^(iP5kRp(TjPAbY z!RJiL@#{bLJumOZ%~$hm`i(Uae8c|Uw(QQ#Evg+a0E&kRA=xwTAA;FULUvGZ%>t5u zmnA5RZ7T*fY@pOtTGZ`4tTm2vhfGslZDSrBT7s+Ws{(`t>V7IqS5qbcKY42KOEY-Vs@GgP=GG?ZdzDdy80o)z_Egz?$3$Cs zCG$4Ae#o5}KsAU#OdEnH|5V-csuJ6>% zf&_Gqa-)nR}NEHwi$^T0n7u;KDIV8Ak24OcbfoU$1*C%f0LuQRiPD6WyMji;u9 z7jiJTnt&Wb9JgEurw;dHG(|mK#w6RqXt0ZHJV3j%i0;e^Xuu#!VLww}!6U4~>rfpl zysxztK;^Zd3U&~u{<5E=sYZm!eR0+=^BDtGb4(P~u()yyvTTU`oi&WJO$0PWE$KRi z83CfGj#@l}(eNn@cDB$T>_A9?#l_QAfRhqH5KpCmiv80{`yuT1&wLL7)fK09F|!sk zhhVZw?X2Je>(`$Er3|gk+<0^6%BMHhpIAQv0FDlOge*RN;+DJaPaD14#=|}I7EU3K zyZU-!Hhr8IWu^aAB~zoCqN*RZymWH|HC@YQQ^C1nFTIOb>U1F?C`hR@1xn?oDvQE? zO&LR36e#in^>*_a-w$O0;#vb?R6D-7a_e_rc;ZhU*HV|G;{|&B%6)&6P&#dN>fKkQ zajjF28^=fegKy5W$(bZc$0fukKk~o4^}m)7j|m}JGp%1-JJ`yo6tN^2-+j-60swyF z7hglZ|DFFy{?ae~HS%LW_8%kwy!YL2=n+D4O6f>Q5i?Lu2t6Kv@NT2`*V~QuHVQLd; zlB^9IT9$=l3d+(;t|gX1R0y~3@s>tm;J`F#R0CQPW;i}O;!tYa1gK?0Rfr(bz2Jj` zO=QCZImy-@%<{cYA6=Qx>%p`Q;Q1Tutpr|6w>gK<>pbx!B9f~vZd12q{Ou-uPRZiA z>w4FNv%5Tr_4ccciw7uB=t0`6+A=kGgxOHQN{cpia&{NYN7XQHI>Ld9uir}JiP=LD zC;2pkvBw;{s(b2%EIMB;k;E!DO~|befLk%T4cv4aI+Ii2;&99+UU+~8u^ z>h+Ws1hLO~qt5U?XIG6X-D{{Yw9;N%zRHkPzzbp7S05O#CrNsnZJQzC&c97{x9o0J zb}I$P_V(rJ-p+L~8txUFyBB_SnoU0QB3x&-0Q^S)-}RMh1^6EU1g!XnF@z~|mnMM5 z!Yon)egYV6?Lk7?aBBl-iLyixN2>k8s>7WuU6ewF2NQr7rDd^2!ELoKq11+*3hjkA z%_1~lAcEKsJX0xZ_Tf@z6_}yd?Ae{g0N~uIdCeLlIJf?MLMa-}StPY)eEI1=pN{-^9_`}f*_VNY`d;Ql-_pcMHyv z^2~whX5Etn2M3!N4)>5v$N6a5|G7)6kN)p(f7eH|7xk@pv>JWsjt{)&d~NZjm;KZB z%+e2+MNZO256j12fgnslDYJkSFH4lu!lmwdsG4CUObC$0GrfQ#n>4Be1Emn4LEvly zCX|Re=7KT`76d4!Im)5{p#*`cUXl`VEkSFpdxI@t)ZfM^;0_D-@NwAyPFrD z80>BS&fD&NaQ*14zi^KC-TwwkfTh{`+?(og{d^K7OL0^?+3n4<_0>z^-tHzE^)}+T zCeuc<$n$(V3?lSL`yU=>!}(fTU%S40{XZ?tu8b%7cxy5l&c$I8h-~`iII4}JB-tpY z)7zW1W@~@6|HRFw@3`se)u+*EbYC$V^|Nkg_E&tlL4YP$~GiS$V$GB2?13sqWh?X4*4?g$^1Lg zs}6I|VQm$V0=yImScsCV=V@8yWs#2sApwFQ4nd@h;*=7?z>5MxmMVA003nA$wJB2` zV`y-}UPs1cWYWHkGDA2yuel}(01{Bu#ZI&gTQieJVMyS$6ZoE5xD@s322tA2*bZ-| z+Ko7X#rU%;K@>)PW$Gezcv*jMqr7_g;XzSk`+EngKfOA*@LPZPo{#ev=~{CNz%K*% z4gk^f^?S=Q2V!Z1;G zIL(*}p|0Pu%+{+$3)>JN0Txi*XyPhA?dPu7At3}9 zV>ZjE$fwv^e_CvBT%c*aizsX&t(D9~8zR@@bAd@1uWk8PmxD7LMJF`Ngw{ z=B9l<3w>v(DIc$PZIA>Iq8i8ce7oVytK0&j|4vR*07aKN zc>J?}fI)v3jpi)oX3ipx8wi3Jgi_?wAy!vEjp1Nx+U_hAjIu_jw}g|YzXr?;KR0qG z2SmdLAv$1#+;D|T!9C#HYmM--0eD#;n~rep^5@Xs--3YX=O}*msmq`Gw?A~xN48$< z`=lcUz?bOw<$rjdHfN5%w$YmVUVxBRX9?Zj&437W7c+O8JL%ARUUC;4B>hB9bz?Ez z?W+=kg{@UlssLh>ld0agaLz3Q0!~!E03nc5q5m!OTo#xXnN3_SvK+iD(de~ReV{(Z zgFV#JmQKM;((e56pPoNe2oMUn66l!S$3-iaZySst3)|Z|Ax#n@6#0*cG%~#!srr^Dq!GMH^FvYJ0{2t4c_~QCy_UsC>#Ph{2)R&i;VEu zXRqGVsvmqtN~mBwlTT>Vtc@?8QGH(%fN+=iZzS=$^IO`~X;f;;B;+AL#5^P=IL|Q} z?h4A-aM0h(^XWJslrSMgSxhrPl9W&~N*le}u)kT3$NiwySrA1&8AA#Zgt45NKb=k| zgM856nj}f9ndf5}Ck+|JsqD?3tW#}6I@E4zKRbUT?mj|yy^)Gaz_gke+k>%M@CpOy z#|A)WpIEDg@98DpCi+mnHf1i*(W1KDn(y%1VN0l$S@i8HGwl$ z3~)At1TgOJVlvuC+MH3rWsG4m+($OA4I)1cG_gl_JTNV5_+tHWX*I-Qdk^jbJQ zx(C(zBC7R8*tV-hQH-UY{)DeGmfn$L1du#GMw(NbaXh6>p4=WtFs>dL=Yp7hi?DGY ze$FycDox?s^InL1zVQE{*V#aO`!uGemqED$#yK`uA3_w4z-;^B&GxC^E!gEZaLak# zBgekPie4ErGdnTzdnlA@;FRmcC&Prv?`hd{E!Q7cXQ#r*EXLNP-Gt!?XHFhLuh#(O z9H9u>!?5@Nu53U2j;n9@z_&#t`lJEy1gzU`xuQ0`u=f?!=^g(!ZDFC|R_ z4Ls5}ZSwsSIiHAyp`8=NQH*}OhhP+dQVO?J03ihZb_n-Ge5W)W8nnSlw(gB{1;{WC=tmWw)uP$)!Y6$s45k+KnVG%p`9Do#3 z$HfQ*q8Mgpc8tY})vB|QQowaR2pNMhMp~^+!nrkDC{$*LgD#4N3T*CT*X{#QQWDQA zfpZ&>f=H9w%guy8mH*P5ELSMxZFA60m9IMKabmw4lIFh*1NEaKiilgRfZJ|baHUdI z1q~H4MFS;7$7c)Ok!Q9wK6y$f^rka!tN}`z*J&C7#K`%QiKR;I)mdB^NR|dbNZ$9V zU(0aNK)1DySakn)9IyTT)z=@M+#65*iU9P!q0ca~eH9BRqXt{=C?Iq6ekI4^>{34_)Hv{n<|o#94>!sEU9Mk2az6Wn zF_?Pj0U~AM92jphoCRGXNpeP#&XJFfGUU0$u10dQ^yHpWX6miR4reMQa#KdfYyrpy zP3G$+@G<>yio|Jif+YT1ndEbuM4fz0q9PC~f`}s#j0P$SBie4B4hMrK<(5+!4cY*R za@=A>D6``zWKt@jWQ@S?HwmT0aY}P>;LBcT)3F?P=m4d)m3svND{{*%bvqkTzt^yA z+k@@6+oz6w!LHQiV?s$RL}(XF(}UTC{WTDPQAQlML=t9$Gyur4DVu4Ys2uE&j@dbk zHALloz2<$;pa)|y5!rj3NO4IP_oc60lIcNI_HRdw0!8L*C1b?_kVdVww^s(Ms}J^r zaL{NC*M6-(Y<}$9;bB7v>AmOoe(FP0Q+vK};Ibe7L#I$VSSVI6bqke^wUhT16tI^N zI$NqtyQ4uz0bq<7M! zDJ7iHANg*f+zI@FU#iXyx~(GLpA#U#aiPK`r} zwiHNHY?DM~VCeiwydahNSXX`LFq7Cdv#<}H<|>+7rx5rZ_@geSrw^nsK_w-GOw>Re z)!J@EaSy}6CYsx)(AqkQQ9(qLpR z5g^y#B4h1LG6sjtr$IfzE%G)^478zaA~*#`9mM4=DMav&+bverKR{v!AO zUO~R2E~A$W`^{>rxyGdu2u6KO&+SGOj=;GEB_)=3oe#$?Ji6G=HDiV0$Nf;Pk>|sD3e*| zT?wJdrLoYSf0MgPOp%nAZc#?F1DDiF0741kFaozNSXLdBIB*JOc-}0kwH=@q!}jV? zvbB2j`xbXyaQFJ@BcGaZ0iN3Rr-xonZEh77>pOn3$i15=A&bnhap3&t!M5GB*v$dB zQ$SAsA;=g-3ITL)H8ei6I(zYvyP%)G_PR4Z}A8V=K#~kjZPxDFqVgKQ*5GT&{BpfyzyoRhsjhy=LU$m^90#Pe0cjl64A)ZWttd zn|!34l1YSTP8LhExGk9+RMSGAWRZJF5jQel8?UJs1^$ndW6#o)A(X z81if;@6+4OsZ6P8$?6;^C$}5&AGH-1^z(Rr+4sTX$l}jI(DfDLWozWkg=?80x(9POzJ|imn*6O zNi$%YO1!`sOfdlq>*8O>tC2isAg4efOsBFaDbl10N(hL>07!E_$r>#QB`gemw6;%o z*UvoUx`ncg<6yHrT>r&Uzw_y94&Cu>0~CJEul}`o&)cq8`NW+^nln4k`+VGQP1WZ1 zh+(hc`NMAHm8ZO^*`4K5WwzUEuN7>!>@&+INALY-d)K+o9jqL?+bh-P0^2EwN^L$6 zGREnLKIeV^<-gKwZJxyD>QVZf?|nr8Kz{W0w>pknjxKr8&xa3v<&#)nKc-&zAAbe_ z@Hc<(dKL})jCi)V@|XWCR!WgOZ~Gr;HNI4cW$f?Tcd>ftp5ye&U;m3303Lks!{l=x zyxqR?|9nsI-v8@LHw5BZZBY$2PFYvJ@qNLc{mxI6lu&%f{)>CtXO6m1#37V0C1k-a z6kW$D%`k2~+p@hKjN1c3$YP;fpAjOSvz@|)wo{yEmPG=;kJjc%5JJ&utfEq1fMvUw zp5FtvSbc&zF&IwP95YJB6mVVR^h8IgI7ogO9yS28z*WIT6un*TOK`M!T=U#?5@R3AHr(7B( zO-*J}A_#>)>SNGvV{7vSdff&Xx0D}^27WaByT0G~NVB{Cx7WV;PXF8OkThWc{JSRq z2TR4u%*^sRm%T5Ff)|v^Q`mR@_kxlllmaZ3#Lr|vL>5o|(2VJ*6Jb;UNdu1CRywJn3Dn3;PUA?VoqB+P zaR$a{8mmGmh3z@8TpOHIJo3P2vAuTuTkm=6Po6VZnSWE& ztG$vaRdNeO?A>=E7~@&2mdM#n$XAJdOsKUm@RporE!nsdcys#sLS=c_jHLe5M{T|& zpAnt+LF4!Mr9bp*U+rhR^_GJRVeI`vFPQ!%e>5yE?|m*RwPjeAlSzM*$RD1uHL?k1 zl5LK3T2H7}*HFe%DV$~is5Is#u?Wa0%I*yzOl@U~3Da01oEa~yOg9t)f?>aj6G!h- zQg;7B(e*c6d&3>W$<_MQFQpU#@M{3x_BcLR7c^lA#BpA=|EP~c4r-M83{?hC8*2#Q zEU!Lt@VeyVlI-;qC?|8cfbkfk#1XC=Q%EWL+WNvW7*d*Cp~j$8d9a;Ir&yU}GL7Mr zYMf@DOy+S`gCaTbCRy8w<-ib`=81l&X!aO{;4$7<)teMz) zllnl)2>t#Vqzch%ufr>rvAA>|rsj8>IAxKZbErAbTXNq2^kXyo zPuh@FS>gv7I|HgT;U)cek|n5+w09|S^nuS}YvZJfqS1W=(R*d1yMFrG>pw6^Ypp@?eW~Q2G1zz?Ku*ONHLiWrhrTUUoRbE?H@V(@ z%N3qgsQlRC?h9Y%6{;^;-v1ot6>BJ$7cuM&L3wiXsPWDk!5HW-=_V!sKcy7nFf!78 zsXhG3VU5rGvVE647Rk9^@D{@(dvLfisRG9bQJM_EDxXVNKyz zhT=_WHu)!Mj1WnQ|Agp>K+3o-D1o*0p#-Sb)jse<&2s13zbg0 z(rJ?^r1O4O!dNPC)sphuK9`W?bFVESS!ZgQ47wzZYAuBn=9>+9xS)Y}<&_zEqIVkK z2cq{!B~99muNqsYq!jU>(^_K$6us^?Y^N~rhua_bgVtY4DHkZ^=PM=d79w~cjylJc z#E4K5U323Ho^U|jyKcII1CW9$P6)L*E7Z!Br5%HAbGKy|>QL^hl~jADX7@P#-j)Oq zQOavk;5$;rR7oiuw+P0q7$C&;N=(Gzus*e1kSdHkuj<%#kwo!GR;vqKd&D*1l;)IF zDrv$bsz7Sg6p5un8Ng~{FG#Fb0HhL#Vohfc{h?f6eQ?m;UiGGCm;HXP!Gh7iu1_sS zmgC&LvGwpxYnu<-osQ#`041@s_YzP_;g#x7`s)&LjK~k+_lJl^0fM0q5yfD(l|Gvi`z)c_G8+Y9 zj(>twDJf(E9L+2;GTB#himkM9U{s0<1e6gl^DGl_3?&s#Kk`LHkq^uAK%@hkSJOtS zT61={ZZ)es1&F7Nr?MF$)|&0*tRY2rJdgP$G5v{ z?YdcH+<;ZzCk&$0DLpk*SB3s+(PAbd(Qiw-?D6XE(`{sgrPRQ6T{8` z(s=6?Q7P>+kqRYQrsJ8*Mh>L%@k&{CX!hJN5hO;+FY^;Ar682dTW!*~A!$1N%(5~P zr_p*cM$>#&X=tV*L`qLh4{J(6NC6tf5OEAy&lwuQ;AuT3EgiPNAqbDo79t zNhziJpieW!g3=QHWb%l#kV=46>`~ES1j<;zq={BT77s`WXcBar0&=9z%uXO}DVIQh zVL#|$FlfZK9sjXJXCnQ7`qwsqA%ODNIhAI-h*Wt`9^EEaxe0!nADoZKQ@MtLnR(=k z@-&Xm9EuXql1k!+NKS@I0EqEMTh0QL@9L4Wgmo%)jNHj$<#|4m{86#XQOgQ@1i} zX^tPDgcxgZ3Ql}! z=x?o4!m6WTdzpY#I?Z+IdIgVhE4D0;D#*e5=_9sfyZ+4lKBrW!Ta4S5#cd4xEy4xy>xwL9eqWEZc$O7TK`V4jE%Cjsg+KVbt6@rTkGRj^ohfmJ`@c!HL6> zk`SFR95D%bT#(?Cs~bm7#wz%`SN+O69+*6mzOxt6guK%LaND7SrwPMn6`{)Y3T}0J z=QYEAo0MyFucee-&~B`XLa9b6<#J*7g|twfvN*R0<4=6h0^=O4#Nn0-hW@UHVco4J zq>v^?FdKqs<)Nboc2Nw*s9}+4Mi=8eg=8kr;v{_l2GX4r-&sReK}iZQlKJQfuk8QGMUkLmGDwP?mY&`g$ zMtA*lkN4m3;LrcT8i4${>+hk}0$)H&DFRBR0`u(BKElY#Fz5|c4DPsvcOeqN&)o1g z-*HXJNdw>;oxZ;1ih}D^Ua{|j7yUOv=o|sT{)=9M>humoK?J`)f)qke%?S_%5u{WQ zQG{?5Xc@j`!FFv>&Oy`rfEeh8&JC52=}nY$-V&%EHPqu2P@K!n*#6>03XW#Y=7_z|A|Dx`mT|vzrI{9EzKEVb2!n5e-N z2uQO{-XC?rZT_WB_kllo-J1`0Cs*q;q5*IQzE=82}%pAVdP-spOg%dzOB_Kgvd9vfFd=p5%Eg4YVQ`lZV{C zklf?>;+e?ofsjmblDH^o(lwM)DT5}d7L`h-?=VR<3e-eO$y`*QO5zBSMcbuK?zH$< zsp^2_C;udg7R)7bsHFHei3UDoEH#cZS{I9wp8K$kn9qR z)qjUlXP#MBncD>xg(C~f2ce`2r4R%I#~*d0La8p}$nScE3i{nG!nwnxhzTK7Ditfs za)y8^dW9;9;!y;k;CiLzXwZp5f9O%pTtbM|?`&J#a!9dQh41(7?e#a0aL(`Yqu%F6 zjdn2>;Yx3?c`9OI^mD)Uk;!0Svd+534=df}1ONDdFnOWLbp!7*9Ux;p2GK*to*P=Ne2#7GopxuMtA3`Lm zDVm#_n*m8;$6^*w&+kf^pq5uwX5Cu5PS%#yQyb!q{lVH^GKHb#REESn*g z6)@%Mnt@8=3d;hoEHTs_Snb{JXESH{Y3DW73SI zj^zGY00_QQ@4-m};2T(f{MMI}f?NCErM=I7Qyhm2oY|P$b3Upw%lh19JoMbLKsW=W z(oh|t5Dc`$$SoBhg+Obq0cJ6jr)#hr%h&;E?ioZuSTZFtu^dJrAk7U*41qZXpDCCK zGp45|Qp5i&%YsPrk@ZxcSvtC;xpfqA>|@Ytz$?~KEX~64s-VmPVhJJQEUz@Bhb9jL zVELTqpx@b+E648MebpOp|MKK2dGgku-SRS4;H95%x%;2vIK=(~m!_K#vl4iX*<6x` zF&UThCmGwRH!G=Qr2bsW^O?1V+K)`qn>{vFqUK5!C}a!-Fg`sc`Qk;N+OLl9{^;NH z=loFWr}gHX=>RN2)4ox>^VQs$Ij1(W2b6Hck@oyD zV=OOEM(XEJRXRxSt&9RsqygWU!k==U`nWr-6|Aq^A4bvYt=GNzFB_Aq^%=2z0RQ}T z8vsNX|3s3plnj_+bbQ)ju63m{LrW^-r26aRq>gD(9mSdFKaNv*e3AjpI5VKS*c9VP zC*V57JyRoU*}qZ0Bzs0WK}rM)I?jlIj^F>u>o(r)1imMuI4ihwO|8^oVEnCV(?EF6N|#xf1Vr!yC#48&?)EyJjpKxod!gS@x6mx(Lw|ea1O#&p{MKnkCX7V$>ag7(0N52%BbRe(%VAog|$r9V`%z z*l@lQbubL5FO48Hf3~>ueArF_t*z7O_qNgNokr2y0oyKsa0?J3vtA|2NJ3FAFQHtS z$NK75FdVdT`ouk$o!^IYbw)R3iAoz2iS;p!KsGkv6snpu$MaBIC=iJ;;A;k%9fwY5 zQKoqtDovFYaTLNI^$|wC-|DS>dU97x8UW9jWl3kMKD+DYI0_F`s>`U(EMs-^TL(OAvMXu$>|-+gqW)mnK)plegY^^DB7St-Y?~RDQlvsq-Dn=fJky z)DKIN7(14c`^SpoCoE%K4rkqOWo-bKM%dO9uAKQT-{){B@CrW|Gu)ZJ=O;f^wSU517q{nFfLB za3nkoFtZUQNgC;k*F^|nBn9Z`NH$@}xB~rd6C!SH0NsyHuGVM9B7`WV)aL+P^))#F zCZ9QpRfSP`fY3DV3}igMD9yc3C7v`Vk$jBhWK00zkF>86M*5#xRsaePaC7jIxnQ;A zKxyDq6d6HZXEqB!F%V*!6G`)cB@urBp_)QXj09DU#Q++RpHiTNgK(xN`XZk?Kp)dy zkbnqb)H8XI*4VQpA180%a!P71D-zBIa=^qqaM36eg3$njUJJd>7C@BRTzlB4OhpeM z5utR{@16NV82A1l3VIJmV${9v#>3wcY?|wCJiKjGFAoF2I}ZIAkzini6bT{HbEZne z{>HN<`uhNR+_5WH+FoJP54PpriOEO@L8sH&CrLqg%?nw;$C(+tEjdRa`5sIZcDC1g5nH1+D7k!(g zyClkm9P5CPe5_vFoI=U zU^X{UFP?j!w#nA_h4!FMc7_HhA`*?MB&)|A4jP?i>dho=(jg88a5F{BQVRxu(yrj zU{j|8I0bZ?XDmtL^~qK8BLw-6r#CY+9@ge{O1t?sRGywkemdne2 zP`Si*DuspRi_%R`ry6KlIU`0wMo9|cgHljb7c`7%$sI!mongrz@7 zgZvT+osDjorI5M-Y^MAgGMJI6Q+TXU+KR@QiHOY(qf}CW=fHrJWtKBDEy~Z0R2pYR(}F!! z6VaTyBAGZDRhv{I%yE5DtQVZ@qcdo8EtVa@hl~JM`h?f=X--LjWH$zi`{3SAHVj`n~4Rqxe0a&;5QC zz$Yf}>SR6D%fQ%@d-}e2{q|41KlF!JC=tJ)KEL}?LfIupzx;{N@yY`b5-y+foN{$) ziE+z*av|qLL;IY9j$NKvoZi5ydS2fu7&`jcafC;KtytVN(q&j znx4`V0x$+86a-NwA}Wz%>%$!*GNm625u1q$)n0I=vw&$D9SD@_71#wA>u2spw{;qo z=|vQ)bxberMzJ;p_f!#`<_5a0b%cH&Qb}}MYbccJfReB+2SZ5sqaH%Pk1!YpaTI?1 z+8aI`O|FzDZ_SkF_u7_QcANsrmFY3UcM@?0Y0|-Hj`?+#oGbPJt29(BQHrJX?7TD} z$=gn0fHIqgDv|@bB!zyOJFdo9F=y97W~IOu22v)Bzt}C*wT&f-qq10*zfLr)Cz09d z_durP>V)vGpuo&jF|o?%slD0f2u&>sB-dP%ImsR6Ss_S_504O%Sr7~qFbqc6+BgbD zy2mM(e{t=NADr9=&#ZOQ$ffI#t3dxo|L&VSI3`o?e6#lK@4`H!%9nh~hL-DRG<+2c z2;bLAm}HV4M*3@Vp0kT(QI`ofCiCbU#}8*I1PW9`KGWzXN+6Z7!6g3Aq&boUDeC56 z5*?^=k#jN!zRh?w(&S5L7PlBt>_aJu#?~p>*my)LNf>wd8OE#<;o{@n-l@+ih|hO> z$G^layV2h`#jbhtge?D!tZNS4F2^PblQmi23Jrlb{!J6WZMWTW@Gn5HCklqYFdB58 zSE|llD5a<#_Xor3)KY)v{^u+_6$t|QXSh>vp`?WEX+R)j6q_ej(Q9qpS*ZeeDAH)iJcpgOgfS=USfPZ%9fqsgfel#(DK*Z4*5T&YNA zQ6o8kbne`lvH_$9|8<%h5F%PVdgcqi?}z>bqC9B;JpJp|o3B_{*m=P2;nGzQ*<%vjSz=gjx53m(iB77;-**!2<&u{uTs*c?vyb~;P;0J z`a{&0X5f{J8FY-~D9>lfbdu?8Ivpi62OBX{mbADbh~qv81L|VIS)!k6>%{VQ|ZJ2qC-Pe(06t z4TmNP08hrc?dF3d7UBY>Fy%N!*tTaBRGJ_@?!QeRuMi^3?;eZpOX%6j^^+z^Kzp{v zBDPF1pZ!UeBc8~jsqO}kr>Bwey6LQd0X=TSy}7?9lrmq)5SsF9^3YQftpcS~5sQFO zJ*O9OY~nO&1_UESNA_?Nb!7^C0xj{U>4Z0-h7%}BG=R-?-;>6i&K_48RFLUd%;fV3 zW!PAI5S`8`-?F>^D1mz>SL-uwbpZSefJ?q5Uwxvu$t`NEV)@Wdt6Ut5FifuFc;rKd zk(Tyb2{bmxG%zfe6fA3T!y*u4k%S5VLpQ>79ADCeOb&xdq?|HvPy&d=W;yHb$c!nj4Rx+dG2_5f}}(;T7s2kZ{}zxb1*(1{rf$kqe~++N~`_ z(FmQ^8m4A;VqwR#;5sE^+a%clC5`?gDSL^ee~%muK>wbSJkulB9lRQw(?*7?Bcgo2XK4}0vt?SQjdAT#aeBj{1?(=^`#4(>+IuFxJdtti; z3_E=U{Skx^h=UNp(APJ$YiE8)rXK<#j^6V8`Bz z@s-bh7)nYwg*p~@T?TGj@cTZzQWbm7dp;bufTQ<*22tc+S1LH40Pw#iSIv{KD63FO zE|IY;R4Vn?Dp?HARLr(|8G`6w#ZAOhGpU zIyaYcEw4-9W-OtWoAiq0`cEgVM5Xa$)S^hRG)fAi5J)n036MmS{HSR$n#;Uvs#JZ6kHHW(Q9@vyK52s zb`Q}gNY59Hv+TTPurxa2)TpVDS*!>puxtmGZ$wD+&+yRJ1;=7JcUYi*6?ZcccwIxdZw{~ z$q$;u;U+&fCF8#r#BiWYvY8MXhAS0i@Y zMzT#yCM5CvSYHu)Lj1WCQAh@@(8(mhP+?B%Vk6Z5s{ zo$!iNpoYLJg+O!b1T5PDWdxeF{f<-DwW6S z0x0LXBLoyctfaQn2muL|HnH2y6%Z=>oCSYKsrcgLN`1zze+BSi0RQDXwui`B%0Xms zV3kYRUn)RJf!Ghs!B`>e4-pMV;EtWC)l#UHgrXD@aYlodNoq)TFeGM@l>tEYgDMDy z81$NId-HhAxJ`pmuP;@+9z}i=ME-rdwK52U)`vqTj=kYL&h@m*)yZ&qSVAB>r|CeZ3cS_FMyN+LIhNb*lMgF zZ@ON|-QGG*2%&DbwN9iIic%)MV%2JFog`c9$51R!jmouIzu8zR`=cI@!V$t?h{YWT z(r9Vq>kq@8N`SeLSq+nhMwxR{(g*>iKpbaZhbT0gYuMgAg_)V1i^|52+h|NrG<7{+?!laLI{Kq z+2>Mb)Bzf+PSR7DnMx80ZgEH{(OTO^b$$w#V~=HXl0>>pGukqNG5~9t#WP6>B?x+* zHMF)*Vt&s)?A(7DDC2Ow%2)mQrxtdiKD&%zw~Z+DA>sg(*l81kafVWL7Uw_jM{x3i zyAXw=%iKbx3Set;^*nLw)>{q|LTKc=h3R6k0^8B@egyX@$Gs)51QGl2I~}weD-dx2+x9@Y1Wex`Oe)A&D}X7b#=A^2 zufKVZ(hVzt*d)+Qsh}V;jzF@JDUua0M5WEP1Z381oC0Ox|E5&_%b0ycgi-ESXc__()YcOz8Htq3q0B>raLwL` z!Vy~AD{&l$qSIU-4hJpek9yR0oliv3=&pW${X>B4aAtRY`q$qvnEazm)?`iAH?xdN zXaL|CfMd7aa>f0%*`50qcVGAx$1Og41;Y7Blh1dYB_40nTm87)7yI zpOsReKD$$m1}*H_|2z`Mfq+uc>ErhdhW%EZl`X{``bX=VU-`R&TfZm_7k+Ux>g9B!W>Nj~x3VEXR}W?#8D& z{mm}|uuX*TWK9|XPwo2Cn-9`TW%lKBOZ$JDGB#T%)livQM4?pEP!6TRevOq)M1BaT z;F{Pmq=h)m6iX76F>uZhhY`A)EtF?!uwC20 z*GT#`vUsPo?lZAa8BtpJ0b1LSU}|wUrskF(S4;}y7B2X%m*T#E{Rp__KtvIUZ5tbd z!l*w2Wm>LeIUb_OKff}yc+rFu`~)vb>}sL*{X)c~(`jICVRx3*Y6|&;hA*X-iV>=d zdCJYl#R^iG#4%3N22y^LN~OOvqrHADG?eC0l9ceTlIef?0l5zxFUGQGj~b6=yY|LA z;#+UN;;)9maXXat*RGxVQh{*`1PuMoCgRvfxiW{MJqxcmm3sCQzjDGgNV07~31nh} zG341)!YpJ4`6HP{LdpE*s^Oi5(dc`WH=l7yEyZnT24QChskJS($lz`hD<>?x1&qvT7YTGcOCKW}0ob5S? z6SkO85JDJs3o#&M4MAp{XYqq(6we3+w`}4T%0?Y5+1A=I^m|)wu`(4Asy?%|b^qJ1 zy8drZ-gf9^pYr|A5!b6-R;w+){N(X3oTr4G9t}Gv6so9AFM?49O1K`Z$PDZXDNTJs z3|N|uO_7vTP$CATgb*=W%{6$1D#Ccw+SopN{eOMa`|h1wv6BYC)3V;QeVKXbDsyx@zR?)^h0#ET8M(s`11io!uYPuLCHXylE^gzX!w}PdnP0y zr9%_`W05uuvdO&y7^3x9zaL`bb7pqc!d7zm(@C6tnAH&236 zj$&yR#memCem~-92-|hREemd`3K>hS0FV+<5MtCHAc}m%QGkADtKzuDSKoHakDpd? z@W{0{eRy)Hdm`$8iG2|2%2153ylZz#z$eLMUz!-OwAqwv&gQ&X`H6j+K$8IORHoiV zE<=`>Kg^!rxy?%{0|?Be0pzR!>9w5C5g*_8Jb;w*NdWo-)jdVKeUr;dr^C4W(}Az{ zQ({|TFrbcGltM&&X5kz#X6eEoNjjlU0$`kFu{F63INNkpN-WP4$&-YQB=tbXv57X* zG~Pt^PtC`#p1u!CcK!_r@4D(ucTBwh&-7xJkU%N*HUQ5D@S@2(^6z>x!E6iOR4r>B z0$|M!loS{aTXOB>{VEQ^9w^*iYs2TB-R$+Y|JPu+{=3cQv6(RLf91Lx4^J9rlQmhB z^^~li{^eV@0c_v;mMiYHZ12x@?0NPz0J(g6Vc!M4_7-+Y0oyIWE7lB%_(|D^a@_!o z4+;$CwgKBNGA?45@$|KxD6`Ci*Dop15t zFEzGLT+k-=j`fuX3$>|5xLygaTSDj$QLfIwa$GRV)2Tla1*K6~!lb=KqXD)yPN3J_ zM&J+O2mLKy4&NrD;lq=wbkYELTGp*M9kiU{)Ejp0f9`KG&gaXudF7-wncPMXY2N;Tvx z781Qi2c_vs`hAtiV$0I#CF9Le0HSb!&9(bL2r$3n0yu63y+#{_N(oNE%br4CMgBw? zgAf94!7<4KGL4l}QX=vrblRH;gApj@j9boY&%N~fFYUE9kN?&0&E7Taw?4=TJ^tDo zJ}_wpe3MHl)rrEOKrI)J;~IIr_TwvMK!55i9zdGPB{PDniCq@F(Lu43fkd8aldE3Pg7>vduXKAQ+Ol zftIC{e-owF?>FFjUPH;?V+8W#hf8Y%V+X5gT?X@;P9)`o-=E{SgVN|YMb^QkgfHRYKZn7q8vYw80?e%wr03LbQ z%~#yW9q&C}srGiqEk1AM_&ue5dxPyh@O&)pxyTG#o!l>KV zKxC?80hu|U>ocCN37ExDo~eU-js_%K44u_2NGj4qrG9riT3b2NisP_E8QwkgH{TsS zM)7^!p*sbD^>^O#ip@%C`oZ>@Q&zdM@MA=h|D=d|K5db@WqC9Vhft@ry?JhaFF=5W z9p_>=XdC6UfW>VnA<)`Bjpp_l4ErtA>hmqa*&}PMqyMwjU;X`S4oxDIpYr{C@)iK^ zxcTz>{L;Bs7c0|;>a)9wrRps9UHBqcwwG2w!6-m?vjx9D)Hk1H85zHTFfcytqo&&X zFHMnQ3K1DggubSIYM_$TS>?vVpF+x#=p>azsYxLqVm&Oe91DeN34{>C6fpmgOv6B= ziPsqPHnF|&Afj-9`t%;mFJA<^;KH&jfKgbE1xhHG&A~0p6iDOi_wg34j zRhAG1A>uHGlp-xUH&(xdZtD~Z<*KQj1cFf?l=1amYyF?rPu=%s2!0}$IXqe4!20Xo zx$@GP!rTX3r?_w5{)=JTu8GYuRu8GA|M`MFiCzWGuzxv62nf|_6PiG2Hk_Q5;ISSM zgpl!vh0543dD4H{jZV@9@*i(_1G(pW24@NZDMfDjudNG6N!JywpFzmr~N{FISt5Tg?TU&o{+m8k}wEF8uBP!M>u-B(&ea9;R zZoT=6=~8v(hC;di2Deb2KFWsKtp5!EaM#(8=ijzb>+L49^7xb3DSb`3bx zuUAL`B?w$^282kI>vK>_!XI=Hg~38`*M&blHNR)yi6fu=RRDKQZntlI#c|XSGC~yj zrtv}`3}o`GTHVCrWm0@4ktOO>yPdBB`>I5Vzma``MikNsB zj3)pjjjb&Dk02YTqX&=&zix+;h}{z2xnX4gaIsbxQzg(zmVfAEjXZ$rbvowFn^!zynID9|!QO z0Ima2oxC$&eMP|tLPW4^7p=`x=(g4og+Zv4><_w)m2PwOlg-VO9|--?s5(90eCcc6 za%}RhP1a;h*0;iXfKRmUtXJc+@|8I2~YYT)>+G}sZ@yeK<-vh@h zJ*}_PEfrw74rCl74r35PFzOA!D1j9E>{FwObzSD9>(_iBioIQM{LI{ zS4A8?B&GkW!(nUv8+{$uz41dKfP3EYmdo!Wf^e#+C|0I+i6~m;)S8hbd_^3Eol)3n zD210ej`z{Qpm{;3x89S854T6FU+#9d)T{s7dnZb;Ndw^NTYr4$rB<;r{aUYBeU*qK zzGLsj*mdB$z?h|r|0ssv9~#ge0kbT~SmY0rTFOsJZVF0_C!dZJ)B#YI6#1HtoYo$O zte?dEQKd7Ig%Ac_rke>$>Y_dJ11P0n*_H+fDnKd;DFxciQ;5PIEZ4)_^aZHYmr_r+ zR02^L>FKB`Z78DU+?EvAO%UM&bQr?Q>`zj{0xNzylMPqNpv3+C}*Hd zCv7A^Lm?taDbq%Yw(SUze3Qat-Dcc?oE1V!fD&|DtLS%6tui+Hv?6LkEC1GQ1gtBi z-UQ$u0bCE@#l|S}9lr+M2Ds&*-`PUHvxV)oqo9;yYGDt$%?&jgv{wCL@6)#B{?o~a zKYv$0>OK??0{QwICswb?nyktC)?3#dIxGS70sPTN-~ZN6OfR1EvgYQ=R}Z?4eT8z} z9rhZkQePzX*_~jPt!emA!(yC)aR%;WjDk_G52xUO*_Huwr<Z}+okeg z(6*SxKhkNR`tMtfQ)@qW=$i+yzV7-vV*tr{{+Rg%03XPI+@HSrpi4Q#bvGQINc<-a zfM?FC)fWG2ZFD`^OdEM z9-B#PngXD7EML+rV4NWe!!#mEnXL81yA72UR?3jsq>`YZP*hL)brGYBwQv-`@@!D! zRUY)V&~BW7<#<@yeHj>aQcHjo(iC|~^FYh>nc}8XsHH@~$Ojh|2$c|Vh(T|Jm7`yT zTbRbw>^{sa9MBV1k-QEGN-Rjh;17IAAz>F>%FYLTvd-LRx8*&ef z$$C83XmNTf3`5Dd1({qUCTlyN{HGMjAbp9fosmr1pBCk23NA5L&X$F^1;`q*GJy6+c%`y-Qrf3hZPvc9d>554NQ?)%H%`Kcqk zSbblmHur)kTzoDFdCj2PoLf15H|CcQpfba)c!H)#Mov({hz z-c>(bEKeO$O4=Ya@i|e8SfaTeUf;I>4&aT1;8DR9ff z?ELv4un>n)Rv=2LV?vYyiDDDsroSn(j9)0$u_AF8!E!7t?S2kUJoqmt)#hMX1@zjh zP*TG6rr@|WFv3!9fszWr$cHj10dA>)a(y0B#yGKhl*}yc|E|XRBNxB(=F9KB?#4TN zlUwict)br^dc-TcRv|6;NiMoB@%ker`4bSLr|}7(Tbjv!c3lFDk<`PlbHL5@Wg;XA z2&7d1KYQ;PZP|5|iGFj19ZtIWR#H_-Dg{fj9Az70LN{Py(^xV#@Sq!Pt7P237|jbr zt1QX1X&wX2qv>vtY&VZ#lZ0F{&=?0C;Ms0t8|CCu<#g-jlXhBRz8`C!b8iXgmW*s1 z&K#r0t-5v2K4W6QbM{?}KF`g?VYK;Up{$jMH#uWDI}x00Dhw{!IWM0`Ri{UIQThYCrE`ZxupnK7aBN+uyuk%B-)P zGpnX5J|cvCU~}#4((;)n9$#NM`Is@5WMG-uTMoT*{{6&A_qkuWn!7*h7OAcJy!T*-Z9;vcr^R-qe;!xyFLD6zp_3qV z*N<8bXk6)M1kiwp#yNCNq`x@f=8HaW9pK|n?+J&EB#!f}zZUHHP*?21+d2@&euxkx zw)xKn8qcT=hj<%kL0bSEfFKU&IgH;e(SUJRL3iUEmd`x_rOjs@4<{VwuRajK0eG01 ze+*vpGuAI)xVsJc8+r9M*C;rshs$cZZf52Eu zZa(zhY%($?F^Nfht;Xwr;cf@Oz2mLo?K)|_t24dx@@%mF9aD3AUIp;={f%W#n^WTG zBY%Ttdk)j{m!LJhfcEqbC>;X`xr2~j{8X#V`u3M?mRs*#o!rq$d`$xYGxK|1y!+DUzFkQ5oE>|w!H&Jxj6K0oC&J^NIWZFIbxaH07tA6*Fe&D~g(&-0)XDc*0Oiw4 z%os<6FrRC6cD{t!lJ^c$Y;(-0i}!&VKta5(2IQQz@WwKTDO?{>>l_3(fIMS-2Q&X5fL8+ec>pi|O4kR-hnrYi zIx*;NEXiSSwNE5I+}l|CM2m4=iWt?9*Q zy+fcXhR6n+<*>J6&YybB#!0i|y>ATrYez1eed1u&+j!`fw;bM_+`&nFO#=XT-hN}F zH8uZ={a3&A*V0Dkxr=+BgN0oO>ZE6E^gY%oW6$t))w9fUxXRX*(4g!OA2{^R)t=#F zFLkliiacuNAN#R~q(#)~|K5AB<+=hdKsr<#14s})OGRod&c?>TRTdzIa~1l%RSf#) zprZyBcU=#yYkzdYm=Df%tFxfmH@@z2U}i{?fl}auOM&;HN;;w=NCba4TN%Wy6g&1@ ziLAeg)pN(t-8hA$IXkvc<89gn*4UsrFD0TRM%tKylnT>xyKgwjyaT|A$<%xLVSV-F zAnSh0l+}0j2kS_iEqLCtnFIju7((!v4&ZILk)wkBsOlZ49z0gK=h~jHX1+s=b9&x- zn`iJyC~zAGfWTuFemvDNV3hdRNjkPk3(zy@0AZpH$*UhMs>TmrIP+*{YW5P$%D(xj+eU1SqaMWt@k1Zfpk_1O);14tchLvg|=? z`V9Nx?J(}ViL~`47lyE190lD+rRIwgKv4CyX%e{e{X)*f#+X--78)umHw$X zZSU!>o~6?pOTIn5!;uhr;i_92Q>=qTMPI6j@d5HrfW52a(QoO`l2 z*jyGHE2o?_Rn(c?nR;i6e6X=nmDvZnYiIvcQ4Rl&V>M~_pTqbjSH&(CMQ zwdclZ8}qvk1l};VbDU`m284Ee0eFTjO-Ptn2DNi+DWDOBBzctlGXj@Bv|lS<#qHc8_xdQ}hKu|T8AYoCJL*)4?vTPY?a~4xGdlAL$;9nkv zHt11xIEV&@WKgM~3*eovtDak+#7F~x1l2iY_-;}G)_aITAW9QV&F(;N?JNiaW!{BS zt#M1b_pY`F4Cn5Qg*6uWa1&BRu%?_5QeQW*1bl|c2+(K3eNw9LD2rV9y4@XhVZq!sO=TZ;IXjtsxkjxNTGxjTbdfy!xRfgvu-GEM}Ows<>byzViJ>> z#1|e1-|{{O00$2p-URS*=3o8m6OVuT?#DfvuMPksz6>?ZyPvHh~1Gwp#o#YSH#v z;(%iyK@cQ`3Z=0=c$e4wY41H;5k&Ka3|$1CEjBieqN@5J5T>RsgHrLhyy_|o9qF2z z?Z>V8Bx>pawnPQN;WL63fU7;;1(-Nk&B-mX!m6ksmBQ5AZmgU;g3aagn3}r`Qp#|i zqOL60$Fz0w@2th_j!SX+$-jel7K?kXyzu7 zx@kDLZv|Dh~uI|z_7aHo9XE1xzp%`A?>oc&9I!LFj}eB0V`nGhI_ z_6%B63m_3RIfM}K&cRgWxXKTfAOKZ4M0evnOqFA9VIShS6#z2lASG?JNz`3H>^-b0 zu(I?ds$vK!#K&0l{@|9k{n-Rj|Jnlq7{FO({=WhIK7cm?cs+o{FBiuE_8wK4xiiP^ zUmtc?&#y0^MAlooyDW!i^FjBCAO7Fp`N_$hoWvw1F^MngbK*FFUp{i=2%UZW!}!L7 zzsB!;+YkKp?84r;1-kM-N~t9?_7A$N&vmxa&KWJF;$d$Mn`>u%vpqLhJ@;hfyz}j; z1?#;_hrLx|W=a~J$dp+@B-VPH=LTgl{FF1*`;5uYZmym^W%9wwYku-SO$1seF#!PT z#9uU8GvB(f`^tZ-qjX`%-fPgF*)g{I+m>NGr6jsl$}~k8s_@(XYn=CRZLtOffjxvu zJ>-a2?Z=dXkfhbZVzsV7sJ07u&+x|9s_j9rZR8*@(s=W=xZdXGaWETbonn6RItZc0 zmCq5lFskq~Z_ye?#~#_oQGLu&R_1+pkMIo7!AecC3|$eDA&F3AIU1cNrswx!{laPF z**em>nZUK)26WJvQ4ubfDGNxY0cI$jEC}$V0`&~Tdi&6NZ}|i5WcoSh&OV9#mt703 zBlvo(Y#&!6KwyiQvBk+}0L}(l3M5@@`v-!v24$6_Ds#kf1cpZvHBjV(FdwQCN@;XD zGZ0cB&j#Z;&}mNtEb7mtnm*vSk3$dOXF>RjXL9auyzQRqowwikr$n1sBX*}tTYl&2 z@)P@`&4y_87eNF}&Fn(bn89Fk6=`Dz-r4Yn4T`Lb_2pBrCWkRO8jTK;xP`hWf=Gy< z{?9dtL0fc|?#6k5xm?(>|MqjspPSg8O*VL^nfX=#e^k=~e(0aeF@TwI?!-goU~}0e zX=l(~KYMKL!ii4|HdpTIcb9qCUq5lnp@~)HBqlM5Nqi~e$}6uN7Yg3+3xBixtd<)>mIWx47?ByDq){ zO*&5ZP0jA6{a4)p9X~~bZW}k6>KZ6BBkvD`lD`}Irq@Xp6P&fdVy_m}8?{^qg?%0; zRKDi(J8MJrz2;W?8XOq?Kk5ojtpPZ;(!(|-|Ed_GyLl3xb4<@(ibiX3q<#jWL~sZo zu4w`SGE$JD7WS(h2}T_WK}o%~iK{^hA*g=u79~I`38@s6R#1@!2uRxvJo1@8M|X7z zyZ65cotb^Gm4&MX)JEC^LJGu<1g+@~2K{q5`taY>6aoJ;pTF-zzxnz%-!lOLo?-m) zuipG)E#3J!N%HDuYZ|ljyD&4oFs80}7sj7d0#b?^uwqzKKOe}~`g{`3S%4k#YzXfi zHa9Pz)0st)4UlC6SW`kr8fl}6Y|w?Z2G$yYJzA}4u=j=5IvEbT;eGiK)>Vj9gl4mY z`NcgDL}<095k(OIasYmrfVapOz48lwVBLAgO_vk+d7hK&WwP+CmEkLh;*M19hEl0a zk`_FB6j>MS8N>c6q?C213w(QOLG0LlEs~@&#`}~CJUnmh_;d1n1B2c&R+o-3q4+~3 zyKi{It-qH~M&Ts3CEyakw*vS@0I&FB>jRYez=24tocVmwT|Y-sMN4Z-$4+IvwLd4R zE?qr;?7#PWD<8P!*7r_;s!2>@5|j9H-p}3k8tMV0lc;08jlDJf_SC{2YfC0USvJ_T z030(ju@Fq&-g4;PiJ;#kp0)U@>;Smy_8WKayyWWFPR;N6`J~ZKckI0e3%jqVZ8^s1Zs_Z?pQKx3;weu@>_aIlQcwG&{r&^m=yEx>QJEC*Y`Ab`dkC<>@7DAprszWTU+L_7$t zY2dLUeEq610D+qJ;H<0F z8|zCbijdg1+p`!Bdl>XKP?iPQJG5FIw<#%c1uk190rFJ6`oME>E4(pc|MXL8f^nW41NycjuLAsQ%{ZT|&klY;pjb zk*a!9^7{PFmwi*xn9^dTbcwnnM$p*uugrVsuAhZ<1*T_qJU-|>`gZSo6ToT`7X=YH zX8sU>`vLqP0Db~M^Vv9dcl|u#q=|g6QT4kkdD@)D@|h<}Qx)C*=7qK1V!W!=slxa1^iTR0^V#Susl)>ogz z%K0OhUAPR3d#;78EKFI#R(5=B9ckz!MrVE+rW)dNAOC|IOc75WdFbOWecjLf!Nz3j zePMC;ufMS&fNw}u%;;4!avt$zG$`8TN+jpG%v~kE{)rKQ%wKbJzLxlgGToN}`%^X|fWQ z+f3;FLv6)({nAY-*vDYmCUCKL?vj_!B%NP5bNa}08jX&Toz~C2^2gu)>(4&e_o`VC zJ)fD+5MdgiS%6*+##ts@MxZr-R|)>}Ok!VS`s;6PxA$Dv>MX*V0#TI0dk2t*GbOqk zODKk2#Ay>nvHp0R;I-Z5&mK8=+r7nP^iAR)i*4NizXjlmr~7O*RSqFFs(euOyDK{D ztqrU#%RzUwXR7>|_wEye?&?Mqr>je+9zEGzKUXsN(OYi4cVb03iAhXi5|fz3BqjjB zJ-_|aFKN&0__a7~e&fu-e(b*Nddw~Ee_Fnq-uYT3oRJT5l*2r{t$y#w>Wn?ZnUGA4 zlKxTE{UWLWLL0o)3cj`&W6!Y0gx74-9dOQ#)&9rHxpf%yFJL%W2D3%0vl~;hmyC9s z+mia)U7&9H#x@Q!5uhTyMNz25+CbraoiX8kLXLG0WKAI$!3#uNzVU;>64q9ZB2E)r zdi5(HMGR{!Oj(8QhPsj}m4c2n;zo)KXCK7s`6toaSVFTsU#y;c@?R{SdE$Xv-g0=7 zP?f6Ekb2u9udrOv`eDqDX9i9mPP2%Z*00iJUwNt`i!Za#gWrIsu6Vrp9wXQ$zTkVIH0mVrCCWN$_S5EF0brPdG>2H{CIz zR!w380DRfSJMOqCo!@=n<~;{q@Y6}7bJ^_Te$4MYfGBA^{mq*X-8jxV^PAgCG(^9ckgQMz7P;fLP!x_Uuz6FW9mvg#@z!WaA0&dymKgvE;iRs zBG1+_J-Z*X^9MrZf17RJ=yOAre+w9(Z6an;2M+&O*v$Ja^>+@M0aD4jqrq(n3f5Ex zsTG8jFlLDLHJ+6O5Vnw_1HGD5Sx1LZJ-PFfH(Jwk{8eq1>75C;A8kV+vR zc41BR$)gYb^^d>)7ytO7$@F`6;+=23X}%NBzixJB$L?X)Ed=Pr>%GFg2b>)VKyv-wZD1 zK&_leGW*Rs`{I6r{V>3#=l;V4tQ^(twv{N2Rbvm(3)QSf{y2`LzxvYdDw@M6ys#sSq}ok zIX@QqV_ysQ)pGq@)7uFI$l52p1_qcpw940&{!!9BQu-G}u+E^jej0=R5=ba?ruL%M zUIfCn7R)7tVl1EiJbLR( z#mOf=^Ar8Gm3QBK+uaj|>Srl_=eF-9DOCz4$Ka`hhYl~_b;nJSmhsiz+ojjvdiTnI zz3oQvrrQpGNt5sDz7I+O_<#TOzr-L~0C4)?p~L^I8W8{Wwi`tfwIULYuP;hJrIcI% z(}`wh*XM*38$a+9Z=PsWOyb!B17z(IFhY`f+jExz6ht(sEKOn(Utw|lzky~uXj+04 zfSI`o+2pExx$K8tO@dfMh+RbK)kK{eAflIo?Ou?2F0+nCD=@PKAV4%K!bK3$)E%=P zfChU5l8FW93?zo#S`XyjFVs}YY)-Kq+|ArQbMV%CCY`O5m;eA@ig@QQ-88-D@)!R8 z?9R)+J#9?M1JC_Nq|MG3ep=hA@>Nly%7X>q7zFU!#q{bz`nG?M0D)1GJ!;7xTl9Gk zTiH74=P@+^2+6W%gSF)&=x&?_v%`*EFF>=kxb5?3T*0SpV8E#2PLjsrexptRsT86{ z3?W4jCv;o6%@%NhT0~Hc=>el-ORWO;f8{93q6ZzNSh(a;WP@c$sj+t9G={xZNEv~I zgp?6>?70@r&LRK-DJ7(qNZTn+J^5Ljc>#3Uv$ ziAhZ2pBnGD?KQ#+EC?}uolpyJ@;?7=BB_K>5wii{!K}ev12obGs{o{ch#`c7AR7{Y zcJQtT5={UG>;?eEU_S&24Jl(Vq;t0Wx5V}o;2v>q5LBdLN&_|yLXI5OYlKjU;BsE`_(_PZPZhQO zA9HOX=%IuP$+;j1=U^+pB@&2GeK#gYk!_$VdzhZx2dx`uv=)MDKM`b|ob!kRP}>Mn zoxBGHe;PNK3L(b){gDemUH2bX{)27+1t6k!2%sAE9DTnLFw*Yqf>JSN7WY9%2^O!p z0^V8dy7YQ<*Un>Y={VMwj>Fm#%jX`$ymy$Iy<}{w$R3zk*o)28Gl-IAXXV_HNtJaH zlbFOLCNYUgOkxuMw8a1R8)KF`uLYU!m2&nbB6%4=9U+n+=q(6D(*R45oP%>7&Z@fb zMdN)jsqj1Reb`643_{AWr7~d%&=Bm`;9UlWltlXFB$JneJ+x~78^FEm9dCQ%N1b2( z>>J;Fcmf1WVgdj>TfxkW-n;kpHkMunfI2ffA;hy|!CX6oK}Z1|Yk2FnYyuH}k1>}% zRMp2F05xx32m$9DgrtyC%Uama1nxfsf$G<>08F0Y-09E2xeC*B`!F@V4+0TJZh1r$ zx)8!qz>c?7>_Z|y`a5CE(k#3g@YX|WQS1B>KwSI5ht~>{fW=tEPY40$eRyr%$slBm zc4rTS&~Vm5kbuw;pd&2oIe@ucm!i9R6;3?@W7vA6dt)IV9=!AqIo)SQh1pyvS4>qx=q-T73&cidDASMRkjc>Wv-1*j5N927BfE2lgf#`ECu`&R&lom1Nox-+Rk>?u;hB!ali1(ni9x~(@<-*g(9to0zxUT=D^A^}ChXK*6&OiY5A90?GFvhmRB zBD(p|;o|rH!*?}3Wc*{l_~+~IdE0kfn%lI?Ac{p9RU8i@QM3vZZwLtimX2YmHrt#5 zFa&!6A`MVMOs*5J&-csevmVqY>CDY<{?h>f{K2n$*IZFWO6xLVFVey$OCZ*>Nw-)l zrYb2grO5V6BNznDEUKBtaEEoeYnh_T=!(F3yV0NT=Y ztGt)%>@g6M`Q}>>5AM3-#x_7Pz*EG0o&{23;XQfN*7=UYsv=fA%&Isd@)Zlf8)O3P zVr?(UU9?W2pOV0w5L3or1|ju8Uoc__7-DMQeCWL^0C3kGH(d?lO*pY4B@63GLwGUY z?C#&pTC3BIVd0ssR?;4`R_XPu)no4p1u5p*y+x%=JT#5Gmo)?k>)w0cN%KqcGFn^c z^hCdCCc`or5I{_rC*~DT)Fe;|1~0bP=NPo(LT~y(L1-*?)*9_JuZ~{WJB)OtrqaRn zE4`VA0d|0Jttg)=tn3+%D)PR~LYSt`)2wW)g1AWnJ!S?mwLBOCFaTP$PmGVFBKA%e zt)$q&>@)Awa9E}7ozrWV_lB(#gDSnifNJO>s=Tr-h0XO!s=0J?Co`=G@-x}Y+jsmjK{q=LXjBg%HpHa6YraIWP&iBxC((j~IA=~}Gvxx8we1u-R5Xv=Ck)kPku za;{g-tT`_S4c*@{w2kwM><%f+pma?F!+}xFrfXM%M75F6Y|b>+u3;7z*o#f$RW>xu zoI#R^1$)*rY4`F$)n4huy#;{E^?Z5>#GJdvS|anEU~Ce=T2_f5j$3hwK^c{$ONPwQ zAQJF?4n%!`i*{V>P|{VijoxL0Dw$dC&3+6Z3-+m$Y#LEE*DG56h}3v~@QsUFs|)s~W?ZROdSi(^wj%xs)`E2F|D=jU4Mdzr~sHX2Cb8jfkG zrQJU$nx~Xxl&oG-x#<4V zMoW>Z=8Q{+-m`%K6G(fY5DcBlA%hs1iLFqH7d-4Zj^UXzAq27K7=)A=Ag1+-y-frQ zM-<(1>%G};-}Zg-$8USzB*FV<-y7Yu8#MCc&a5aR8#!OKm zMqK)l(?Gp2jehbdL6_q@Dr#4N?Sh0ljR6h-#0c3O*%tB$&_K`w2=oL8=X@>dR}1?o z8NQ42nBB98D2<&_x-j6cRF*CmpmmIhud_N(f6OG63`%4UaYy8OH{>4uT zhu?YqZTHy8H2h!3yMOuHuiDXE`Dr2X;#lN~v3ezz1uthiJ}AjQF`aDu+rmcYN|#&_ zQR$R0dT5&Kg4{XhWgEcB(x;*!2d^e}xfHfb#C^|lqw;a;y;xFYx$wzUTldzKa69^@ z)7P9|-%$Oviqoj#B=#&aKokrN+p7Dd;pj@|viqZ+=$LU)CzZo?;hJ3fWEDgl zi(g{Cs%j> zSsE8gfM1kG#lrwD$*N?!5tW^8-unD}d*i4g|IJI?xks6?Jk=P!pmORO0e{@HkW$!B z=T-c5tvEXntMU&ktFJz>y7xWvt<{?T2ttyZ zGL&i1VAWGI5Q#c#@f3M8xL?MWfkDvd7nl?e%6< z{3{~#nTfQtvsxL|h>8aZd_`fBLXfA@sRBUXI{mU{oIP2X*f3M!y=YWU4Q87CHD)~5 zdbQS!Gqcj0J*lO=zF#yS0{IIIt?o-pt8FiD9%;q-wTd{_v-bD_QQgmF4v>duy0R!X6|q_WYmRy>>{;yD21nVK8f%ma}u z=Oy_amgU)4mHV1{IJKE~qDWM$o~ejsxlq{nEQ9tHHvK4oRV7T5z~82Xy%5XtK(Ffj zVP;ybX4IcAY+B7GYcD3k$wAebZASfmVUrCh+|>Ya<)XByhYjO2Di__~jE1rG`lKKi zS1xiyd{wNf-KC8wQAJF|OSwro)rA?F=AX9W!Pi@-y8y9cnp46Jg%V{iZ$B{I=+7Ik zE>*(E#>tgdl3l(z?BvZPyPUww&Z(;^r<4@#0Rk@pyzZHB&wOxH$IZN)>2D# zUu3-+q$-O%iz*Qr_sq-%CG4djtZAyIl&G3RH+6q1hF3Y3*AemGX;D4Da>;#4SYaWx zb&*Wf@LvpU=V&5|3k<}T)vmVgM~34Q09o(p1+lI&$LhY)C0R4dzpiuy>Ckg;?p$%n0GNacVWuWddLWO!=TpMH-cfmiFOcncR>@aVjfVT|qEI^$Y|6zn+ZXm|B zc{t}nHNO`56GDuUOz&L%9e}8jK#02C-}$k{A&=VsYs~yX-xV)%P<5N)w@>he%=rV9gkynN2pCA= zYVeDpMFl~O%E!=3!mC9%mT0LpbcbP`h;<3a5=wfAdVc063D-wfkP3*kg=2+wGK2@A zsA3qW;aOn1(ZirA6{hw%!nD8pvfLM#hN;p+_& zuvyGQsu;p=z&e72gY^>aWQfv6h?Id6z8)(c&P#NQHrjC?o&|^ml=4X9a=cCr%LH?+ zE_!(rg^kgUhe)FmMHQiR5h|I`EIM%ytJxgdaUb1s3aQE=gh#9loR^4I ziOi&kWQATag}HVQQN$ROO*j_N(xNnBjEu%$R>hElk?L@-6J3T)w{$Uu^XWeox&w++Oy1PDlEj?yLJ+N&Wl+YI;FClKV(i8s-&rVy(ttgDidsse%- zg^9onM6rjGK%_mS@KDmB85h{d+K}W>IgL&_L{Y^cDUsPZB(jTs7NMQ=k?Io0DG)K3 z38jrtm=L12KL!!dE zNX+3`AbkB?C8R2Y@ex?GAg8|tB7X?3I0obNy-)V9`x(ovv)(y>^Pzhu`%YjKQ!D;EuyrtHg(@#W6h!uf5Ov}|;@k6B_-`cgXDb5+!<#Mo z0M(UzXB}*1Fzhd*yLk#EfZ6%W(daBdkPKD(QCa^fqJrVyu5SOAwb)FT zEnJ3XT@c+ML7=j*Ys>k0q_9YdM0jtL&l5uBH>Uc!3@ad4WjUc#|NL^%o**9nJ%V}(Q(sC*1X z29^~F4C@sl%8~n!7{(%pccBZUauJvrkqXIy_XOjkkn{)x4*>~>$|top2BV}sNHxQ| z3f@@=3?LEqNEJ5_iyZ7cjF)h%po9yXU9SN!VqGCOjd6lc2E>41eEkp!lJaHTSmg5ayo2+eT+z!(9*$s z0m~XmRH1Sj-V*=;K{g~m?9ew;XzLz?;E+6mVd@Qj+_?s5zXFxq2gz#?gHMA7e+@=B zZYRm1Q~+B_n*bohs)Ta{sQ^zJQ_U;@c7ib|8+GCkHtT6rB32>!E=(LY*c>V&6c|9k zErb|E9%UJT4eJzGwBQ#1Jy`F6E7lyIeL_$JJkJ3aajmAu~KkBQ3s6Sszi_&Vu zs)BI}d6l4*WC8TD8cI5(x&RSSn5YJ;0-yvYNa1S07O-B1wMj8p%|WOZ3fn=X3W#(+ zD&s-vrEvNHDqMmz>cdnOrqnSMHijr31NA=xZ`L4DA~P{!WdeZ30>*~1r=&w^HJAlr zT|!F>K@968w6ZWZBv77%zKmx9=LMv6a84ptrnY)@==Q@r99_rJTHu@vV;O*=0E&5* z>clrB?^1Yp2v`^9q4gT6 zE})e|Uc~{NBVXUa08%Oul3B+Jk*pxdfdE(^k~1(PjveAeK&gV#CWa)3(rKvCTqPcl2T2~ossSl%xb|dWy+SMv z3LAmE2_Po`>jQ9=iecy$bODqP;E#v(0)ic!m-Q}-;SfVmcxFp7FdRdY1(AT371#p~ zDy+wd;k zESL$_$@-Z%qCL7Wzu@3K!vFa&|6ToBK`wA}ya@XpFgz(pvJeu15#>sF(Ew(D0FVu! z`%xg?`z{RbyZOM6E%QIJpCkaY02Tqv0JxusCT;=$#CXRYubG3Ky$jU(K0t|(Xzzgc zZ3vk_MH=iq+(=}*E}8`ZAPIYQThFVSx(ftbY^8PR;&oeM-`?}s+8RE9hX7!zx`Uvm z=_;kc@E`_ATCmRm-T+X6AlN%|+?myX=gjh79Xxb+()~J#2>|dkEB_w?aOIci^FXyF zV3pTy0Cn5EkYam&9w-Aow9ETCx%bx9)o?$)%tD6uR(XM?GY=up)T<`aZH7bhRcytwm5HlTrzQ#6{m}wBU^Z4I+Y!)VSMW)Xgwz|L2mg&E|pOe z%J!e*F(9@~$$87ka%*v*(Zg>9K5dysjPS3~=WlnXBms;iC}zG5V(OdVoq?-*px#Fz ziU;d1mvGFwNoD-KM&}i%EnDX|(%tm+d!)ShvqrBGqSn4}Tjwz1B>?I3K%Ex@`4fQeL%5Z&QTG=h zg&%*X@qMTnJD$V$(J>$uAV;sGZMW{3tm^eKovrULDY*I91I-)4wH`bQtlkY&XD>R5 z(Rt9ezi+Ld;g3>46ou>Y6&>-VfJlLOHxTay(rW>;3bbwrk^ucr0c-bMe2u+1N~SkM06O0Q=y{;~@vSl6d_Ld?fa?WN zmMvhr^$mLV^BnJisshU5Dfi3&{jooKzIh+U|MusZ=f6LHM*mL)P~$nk^eX|o3G_b+ z&W{1JS^&2IwRR8ib^!O#2uYg6GmdxO{;GuH z=lx&a_us+}k|~AMix6sNtWPDigf;&^d+#1@*;Unv{>GehJ@)Io>r|yGFGB(t1cHhR zirSze3M5q!ZChG}R8^X`o3AhTe)l3Il}c4W)VA?*TQpC!5$z@<6{H&!MIN6D3IR2c zgpg;YD)l&Z-utoEnsbhE|Cn>_y$>QpX|#YnzRxdM=e5o{d(Az@Z~PuU()V@zdxr;D z89io<9jviY%LBBAGA77=MIbclqlpMw8-Ng^vpvIEJCx)G7D4!0MG87I@da3c-7$z? zhfogj^kHwG_)?qbxuv!1M6)RirSH9#Q-u0*>hd7^0mVj8JIn5F(JF zAA+y|8YsJcq>XGOj{uNmElkht!l`5Tqq}|@#b6cF&7BbTDEb>H`WwesWI!UTlSl9? zSKWv;n!unpYHWs0CU2cgDJ-MI-_egXtY6aDVyy9`u_ju0G{lcLLc{CPTaqKg$9QZ2 z9~+JV0GodeQEgDR0}38e9UC^q^`(&t*TC{6-&>8Ea*Q=~L}NoiY~Y61GS<+KU$-`+ zYpjO>(qq?68kl}D*ciZ`0&V;qfI(=mX)C~hkw?&$0cISCiD{kT-q6zk?JH zfKY+*^B}G71$CYcpa&j&9i>Eln)D=%f3I)UDjyC19o!dRtXYVUQVpQ} z9H8|aAip5IhU^l+gRkRz6JRtTX#@dy43LqrVUWY$s2)mVlI?I9RWcgdr5*z7=cxWe ze+j4)enibJ8x64IuYqv@C_EoD+~%@ueQjiZOa_bs4C{d?>1bH>5XvKU=gl8*hnEt7X2 zSo=^!8RFkSHGr8P0~${QC=9fyC~2z8zg^j`&m1~oy{f%grNs=ci+T#k+UmY@?v++S4p5Xa-VZ}fQF!=$ zqzu(b0O8%1eHg@T)x#5yeg>VX9hjOs58Jjs6+}85Mnqut@R3TSNDYVhz$|cMXe9;5 z(ji1Yiu+SKzQbz@QH3f@P$S6##SO&h`YEOfc=1tgfZ^e&bf5@^MkFAf?1CXmji}nn zqUa9L=rqSRzzWmzJF#;5F?d%YZ+5V9>QS6}{65%ffU4-72INC~ue)n<@O_o~&;#G; zFFWV4BLx4f^~!|%uYlb210~w$&=hFvMg_XOQ4S5$8&cU5s<2wlfxs}zLXm}H4mx(Y zNUtZ9E`ufuMIMD~A)x{gf<=y82MuI~G7bR@&jtn+gb0ojIImIp3{CXly#YWl3~G)K>4oq>&mA%PA76V7&rMkOw4G!b*xnRbbIbsSg$n zhb+)rl}Cay(q93FMowK=Z^C992Hq=pCNy*p*5%0HV6+2E15{Y3qzT3)U|vEl$Kkz( zioIIlb0n&QK%wV4L4V5)w303cu7O#RS&7DkZ6y@1nRViLObiCTWDCx(9A0IT?<*_K?*~< zbm1~gH@esuv{88jMS(Wl%nGdaJ77_m%DeEa(M$*MtgzN=qqGKw&cHu*V!C-QewF~jXbf)Oa&H#(Sh1N z-RxpeRq!kKf~MN&%zQVB{3YNqWqla!hkEMNR1hIpAG|PX-vsXol~ph(z@kvP1WF0C3Y735hcH8`els1Q za4Ax%z!J3M8`TsbfQEzh8m%N~+gr&d2DXV*SFjQcX>&b5-?cy_@KIJ|RPe@0v_~uL zfhExKooFxK|gcLk$SRa0;q|Z^p7M`Vk znL}%j`Sv=530g6FRSxS65^YgA16u*P?xA!!5^dppkT6VT8*pC1d4q1%LNn=Mqnt+N z5;V;Qm^CCyZhBQ4UIH4Cn<6}~5cH}>^gjvue~#~)mNT@>X7DVDzrSM*c!iER1C}KE zFNEKZNRaAqrZF2dl0FLCK&E?OXq4PQ!xZTI4l*@>f(I#qbqOqIut+gwR^ee#`bK>A z0{uAnurP8xK%yP2q$pi@uSm2*!40I!!Wc&7vk*0m3fxs_Ha(gR2csF4PmvmjW?GGg}7D@{=-Q8hpDh%i6(9ZiPZHki{^O$aQK_u81 zv~kY#8LSUlu->4P_0cOEXl4aA2CX2~(k{p-0BoOH4tShP(64f&rh*d2YQKTfrpS{b zK1&JCn>mKcr6^nq1wm#8ur9DH!~10tXxa!e66+IKpCHqNAVUG6Z(B%x2`!H!bqW|f z1hGNZ;+H-E?LA6we*N2D{*EuV&7TF(25>)sCV-CuxSfbT^{v*!+nI0_Cf2Aw4jzJaL2?@j8I z!PC!q><*B8m$e%37Q_`270vf3=;uqD4bA2(r_d^BhXstL?qQ{vhbE6y713--helN} zG_f-X#(BX=$spAO2o$UYlPN_EFB-WTK#_w2!?7NC)=rc6Aj&FE8%9|$>!>@W*ih9Q zs0fT9xb12<7*!#mFktn42e~QW#c zR8>K@3PPevR1t`=oFLO>Fe7wra=K}>pIRGCAyHNx|nU<1d4oX}jMgffAkh^xdGx9rova5Nwfng#f&pCB zz;wQWGrf5<(g74PtWRN-i`z4`o|NBxBpUkVm~M8F8H;Y&IJq%s z?Erv0sRGdC63n;P&?_2ntRbSHRnRDxHo<&n9o88*uc4G+V6$MjR%K}C{a}u!JO)+T z6;Z04_nQK&RIZ^Ko%xxP&I6^3#mY+2H?%po&_08Wm18i7kS8VjWscNXG}98jGMNAMixidB5hzeWSxs_G z5qF$7Gr=IQK(}ZkH6;dBJ|J-3%6e2A-Wg?K$fEEKcs5aE&1fY(Y*y3J0L_3U45=H% zbnuMe1nr~?4~16Jhm{1mF0kC6M{26Dc?F?i2I$!qYw|wP6%!$Y07g3$E;~uUB9SN} z2D5%5(Qev{ZaFr?`{%`=-K;=Lp;tAKnF^Vy(98k=GN`hOASHlKX_G+rcIYu^FyCBV zSnW>(1Wf0fa9&|!&_E6ns+{3AAz{r3e~|JdAR|lLZu>LmkXWEvFDDG|T`_ zOrOORjy0O5w_&uq&{1PGO?;N8&h*RXrZH~bdV}dkcWtw1w&q$JNi_8U;wAspRYh$i-$*?Ka z%Af9*jnuQDMp8^?#v)BDoYS!097|2r?w8rjMn7L?QH?;vVAIZeP{h5>qP>)v^1@7) z@T{>}w%4Y!RSi(bu_{ZKJ<3cw34A=3tn^%LEnin&oKRF+V2Xm zgP`xN^tn$g7Yo0!zUdxy!YfxF*xJvCND80>AO)~WM8%gd1Pl><)5IbF=CA#vN{gu( zQ2SB{{Sc&l6sqwOAo)(9krVkg!D}JYfyi;d|FKAM5x~bG#cu@tNacv8mB`?fOM2C7 z-*6WLzk7P;-Iap#Vi;0N=uJB^sJvBeHw7F+)Rcsg1H@ ze_gx%*Znpr72W;?zH(rxeF8>HFdEnR0C2W~cpl0HYNmnG8r~LQzYO6sAZUoVyV)Udr_zL8_|` z9GS3DCIG-$2>^T?zzfc%Yhur+`UQ&K0N%Pt?;nZuXpC#;T#5eX8LX{5hN9TO?81eZ zoqtM16~j>Nt&1Av2qM%Q_aT*S?0cft1_s`DFy_-i<22?0fM_}>EJFZ5CmKnb42S)3 zV?m|WkXu-%1Pl>^2z7Fu1fVobYKGsZW+Ke&m`9Rl@yi&;AO2fB{@`a&6+O%>>_TsI z6-km|^~~`X9Dn$4{_Ztz{2!A{)F)AY@YWY^+ckIk&3RH@ywaQcq$05*X!_Efs3bq( zMW>ov4}u?<$=8y;ZT-)Z)0d>$KBi%RqHvAh7oomU)z77>>S<+Z;Mxx;_yq!|io6>5 zme+8s$u_*`SwsHhTD9<-nHgMQ$ez^7zqoBSW;X2XpLo$N7Tsu@^``>nIBQyOA6XhE$G~4sj z|1(k5OO3W)=vC9lX7lA|v#3W1?s))p*UGtf5#iEY_rG(~PCw8|*3VbOElqw(!53ZE zd8G9D`a*vCg%u~Koli~?Nj{q`DXn;C&vqJp*SRy(#da@h(U2RYx|luPKj;3bZ0)I9 z@l(8*KiMp&*Yjj>()r|v8@jg$qRo;U-Q4sy0J^Mn`8@^af0>)&DI$7my0LzN2x-UW zM6YVDF*G;R@=w#mKEIh1^DDiX%Q}rNM5s_CCk9noI5snhaevKB-#gdZxOZuD_JVdc zSX=G4RigcQ^R2bnrS8nJRN2)*m30#1EVJ6QUb{vzkTbpc&vmlyC3#Zr>{pEoXBz9- z>F%~Wno0j<03A(Dwc0J)pP$M%f5iI4IM$zSrh{g;Y@KT~A8%zvbGbY7i99Ku2BMb| zK>VbjZqaDOu$9DU@>u6q{RYu~1csc`AG z$|X-Ul5)HC2FwIyp zv-Sd`U6pEgo?~;=vwl`5@2z%=e0gzd_52fS+rF5ZD&OpP?(Q_Z&rMC$DQxz4O8Mt` zulq#Um~E`S0OEP2KX<<(PFMOf|Gk~|zT0uKGu2g+XnVZ!$x5cn9Ru6kB=VQ0x*E)6 zYYR*Lg(tdI=l+>|d9`rOpD^TRS?KcwxsXMjC^_Gjs_ML^>8%2&danIZ5iBa=S?g0b zldnFd?^-n1SjiomZebgr_d>Z=e6FzmUrzL{!sS&bTYv6qG567_Y`vw)FQmH42d;Ih z@A5|t*k`(UAs|WN8h>K6dy!|oHl45i@W3@cQ@UJ;_%SDjryKnrFI;xgC|;dzc7G^O ziccyMSGnZ8`%heW(|L2Jo>SPglPEVeu-Pf^=_5q)uYxjQ?z!pDrqrKGRF(ByyPr_?GerCmfWEKd`~$h}O|{L&Wgc2pKL1qL z&NPgwO2_G%BL8iPDxcmmo0~n~d7|XT@#$oBL&LqI#!TWxFFUVWTJdGAbZ}3<$~XIE{>3zLYH4$3 zaL)9ZpKE4Cn^`^3EgRMH=Imc=n_5|%X>NYk>5cghtoGU)il8%7&NcHwWv05sdZSs? zV-QMO*+BBN#KxfgJpdk9>v!&Nq(z4W&*(JzM8rD>RrX-%lKTj_AklWgGnRT~`(!8U zo~y{G(~Y%V$JfvOLPGXvJKy|X7PXqFs=wNwJ2BT>rj2TIIC(d4%R3DE$m!w+rG+P}&U3q9%YrkcS|t-4+0;0Av8sapA#ZAlXjf z6+rF>@L}fDe@vnkk@*opb02{32Q`Uk20A-G`fLc4iRRoapxDobzBV#-;}T7&u&}C4 z0PBy{!%!WkU3-8*1!sQ|iM=|(q)F_XO^ntKeX&vm?;Lzwlo2GF2U1M$QjtZ_2Y4Cm z*FcoA`0nlH;E~ttKXB(i*&Oo5gO^Wb&23YpJ3pM}b1x{nM?a~vxmRg34fg#W#63+! z&$HWjH|g|QO1Dmm@2`ls$JqD97N`GU-+{Z1O*-xg0C2Vp{|dmT0X*j{x+pM*gJ7`H zgR>6a+9-vSA>vpA1)FP6V0HOXm?Xu*_DhhYO%M#2eK;_T4o;=ck0ME24Fby0%uj1Q z(h-lP0w_J^*dGx{8WUp*kF-t7gu$Ii4Z(&Q5e-x)9>)FE-=|Is;P`!r6i5LkNx)La z35IlltPv6cND<1xChq<8A7Rj4L)K_R*hj6mf+Bt5@7g%pwa^=8E?g@8Sz+kU^0qY zAlO{@8-3U45o2qn-1;H6vzvM z2Xg~?-RnLmw;jAvv$Czd2kzRq>H6JMjik)_Rbz#ev<&;MPZjNZ;}L)J;XPAEeE-!4 z-sb?|mczTXXK8xTU8A9hxVi6|BbzrLydn{zoJgDivj4zc#cgl7Qu)f|)}S)1QVNKf zotB>ese^wkHyzr&jf995uU~!bU1hk|JxwNYN|Z}j3E=6~2k+!}9=hDT`oR0#O$T?I z{RfY@TMz9v9txTiGh6}|ugSneXy1W5>}|jPVse{l3TV6k;9Y#{;VZSE(jp=ZQdb{% zU-|C0{MZgf&MmdF<;F^bkg^hw284*nY-$Zkt5gQ6XfSyqO~w8<9`U!{@bV6OZTDSw zq`2|m%SdT$Ak+|p!TvV}jo>ZU?{4nB?#Qr7xcSiK2?$LvSs@Cco@rvQe#7lPzHTxC zJ5f-~S`ob8ci=8}>%o_+s}BAl-}u%mNtZ6!EC()aW|BhX16LGH%5y7HC8RYISZCIw zpXjTuzr)>pcz3JR82pDf9^o6`dL@~n1S_3`P?1p63yQ0+yVC-|ufP7M>HqvM|3d)a z_kQIkl(#MED@&@<$Ws>Uka|t_>NnlV?>u+~c`YG~O{gIRt30fQcmS|-C0_Ts56Ufv z_aw}WrYN7}MY>^g3BW6~5Gu`zUUT4%c)u>sL@BrL+OXlc?cnA5H3#44-*NCK$xxCI zpqpv4_}O3jeYyGI9umz7e8T$=-tKNXe5Hbv$^HX>Sl)DK_x%0?N0x6nw0nN#Xt4>+hr?dc6XkVDJ%9(PIdq4H-wMhc;kN3E2~Nzz`o$C557M>i+fsO_obNy z>|Mpbc=-Jc0JpvAN<~RaoL*M@u6_UTnr}M1yG3FOZ6J<)vj3VpZ`hNIf@4RCt$dl81Re#n(Q5BCcl|y0x0?@L zk%1JE!0$Z}UMDvne1#D$4Pvn>_obA&wfDf0?#+jGcbu}lh7+tzHRbiMzg=!Vw5PT2 zz@5GD`o5wq&_%F5@YAls>c6|;E`Qq%mn()&NT9E}_Rju04_|IxeeL_)&4({fL5j$W z_TmcwqLoVa9(Z4M)AhRzAX+Cz*fWVR?LTl=ar2?w?R^K1bVrT$%akTFC4`a$PHAE1 z$&m4O-<$sM%Wm*~>+mbgYp=b--E#fz*52!m^lmwHMRV_gyZX0WcX_h+`uExRtR{O8 z+-cwO%RfoFY$~l>d+&iG>!bU&C*5}-WX#`q@MY@igYVz+v)=ypm(c58_rd!0kTa8G zYnc*_+AEa--hc3jzv{|Puj@h9l!jO^zVP^ ze@Xb-J&701S0A|Df5~e)*>~+%);ibM_2oWx>%o_+%4B%$HMjFO`ullg1~dS4i0B)3 z=z8bDE6AJ0%Y>%?ozmG)iSJE=6cMEmb`Z1y^r3VIpbX*>Q#ASz>BRBlR5Y^S$PO$4 z3VkXdB7Wm;BHI+no(8d6$bzT|GM7M`*(Uk~si0v&+>SK0V6f>H)ao`!^^ z(uQq)?6ZO3y(Iv2G{>-2HS+6-;DR;=s%GlOep|<%Tb0$&2cY&L2mk>EmhMox>)^{T zf_)z%SoUt?-&FqOpS<>(Cm#=Z}0LA5hN5{-z$ z{q@xXCg1-nBmIz$XB}zr-P_BLHyO zS#wP+5D5djEh|*L0-@uIG@|H0Qw+LTUpb16wc}_{En<4^d^DOfLwym(vPD4@27eoo z!>A{eXj2?0{$|VtT(cA~7~cQ3{b1EK?v2 zXq5q^;A|D*a@8n-icm)|^dRCPQb5>3(K-YQ;B^4DZomO32%Q6yUI>*m;i?f{L==qq zlp^@J;8H|z)((@iC~okzHt^oV79ruQ?#FBSKrrDBsa^GwO}qzU47f>5jK_}KeT3ea zIWTT(8G%rc;VP|=r0EtzU|*dCyQR47vmbHA@qJgl>0J+fRp8~V`xij;T&1%g(57)2 zsn!pO=qaTXyxRb&0B|JPE|5wAVi2WZUj`NiDF}PGVhP^&L6iebon=&1@Avj+h5?4| zM!H+1B?cH$TIrUQR=S6fM!HiPq)Q|R>6GpUNhPHFKi}VaUOey5i?i0*XUBbC`*RgQ zhov*xPyWK&sT|m*Z(p5JIe)v0TPa;6t`YSbU}|;&0UjEFfN26i%MDj+$!TEjCP#R; zHSZIZte?w0@7BL#>`8Xb){AMOlV>%1sT^d<_ zn^AY)cP0tYo(#Fh9bu(KT7o>g!joV7KLo{9a!WiJSYHpOISH@`{(s-hV}@J!&!bbp z1%NFCA&&Q+42m|)6HR5n7LZrU1ME z)V(Au#F_Bc7!uW30*CxzGc9HdsY3r}uzXTQt8D#p*HAEOHkG@7K};#X5&4H2N+00| z{>`B>Oe9F2nk2^mxS>{PL#D7^UAu8Uj=PPDVpw(D!@ZCP`U;LVtZI#WxUgUI8p(T* zy?)xI3aCh8YLF^Q91r9lnz0(*dAsI8bcLFn8>Ck9)s0B(gWP&B7x_ztE|3j30B_Sw z=4e?v2i^UZZEHf~Vcw|gK>y;WYC`APetSK1AEb54&0GYA>rRcdZ;jv` zKi2QcBXP0QK@5SjRO?uPb)Xpy;v>M6t|0Q|LD7GK5Q~==9jaP^<#CY)jnsF;K-!R3K6~}Zay9Ye!<}8!w$P} zIn%ywyoATSOsz882@zBqP|u2`>$(is&m7}n`dI8O^!|r@-naM&!RCBM%;>s(9J81p zB_gk17FbOLoB%G3Ni&yd)$f%(Byquu+`hiM$|pKfBWq4EyuD7HPbBOamcE%MURgqK zd5J$Zh#f##9ldlJhIXYZFtlP9dXCs`Rb?rGZ?K(WJJBxNH;f|qDhshb(`$kF;hbr~ zO7!Brcno~C0q;U-E4p$00EtnDAy-|o7;xHV7{0eDoK^O!u>0a zi#g2;;o4R=>TjjA-CNZ*?>#nyU2JE5_)Ic2N?IQ7cP^Ew7Zln~P)y=WRK}_#Yti#- z6bvcl;Npin5(Ist1_Y^%4vxaUY3}$s?voMx@(D40jXM`!6ty16hSbqC!YE)k?;z;s zB*nyT@AG4&B~uFaYYHVg;7pDWA>UnZcNo2H*1DjckE5m%ZodYew>yu%_}TpvQM1!p zZ@@1o`5(IiuKfxn&SS{hFPd0+y$)UR05?Nr1FPUuAYdNFD>PWo z{eNk_)9PqW)|XHdOBZwOVI4NxkUR|0FkhHi-mJvS+BN5;WT>JS_=9uQy<$j}*uaE6 z`^TF+q^gn9>G)`dwiwXNO81mdX5kz%%9HLk;G(HRhDWCNQpZq49#~=ilSB^FaSRZj zzQODs$PK^dQM7LQLUpcrV)QI-jr&2iAI^MZ!TbT!N}#=|C+|Q49RLRNF*@$NRI+b` zonH|nvdp@0Bcx=N0|)P)PTsiR#c?@gX7-U~INWzJuliBmr`UXWaV&+f9Wz1OB$ll| z(eokq4U63U?7m(z%><|axT(iWE4u{5QN>p!RK@!yS-A>W*7o|2t6K#jMIgD_dCx7w}^hMF|(`;|6Fusk|+ar?=Y$Z%iWu z>~ZiU&VT?7S>;EzDC9f)k?&{pm@^>Bxx{jr36wH|?hmFBn8|dJ6~>Q+G#HRw|4V6Q zLUQ2d5vUBhhOVU}F4Z*o5pkWcs$tqd$q-5y9x%Ai$0T^S{xfEv^F|4pl5Q-Hhtzm< zZ9Qfii_>Cpvc?z1MyqD#dX9Y6U1_*Ryy)9W$et`GD!z=rWMY#iVV zKB=D%+nZW!=@j4%GJ5|zy~)aNqClrWhHg3{FhanhhE)JkYtqI z=7rd;12m(dAZe_n(IB_iu=31}NNwIC5g*-z0;qc&N~CGb1)SXs>pR26P7cviM{V4B}}0>k9OR?`vCV_?_)_j$Pna zvM&P1w8%64<|~&5(MmpUOB3k>C#hlp`@INDARS~waX%|$<}2_d7tkgc@5E)fI38%R zkr-4nE->|Do-OG_hhw!L#B?AOPiPtI3N68KTtfC7HqkzkXXB_LpZ0>Up{aeAp)TBo z_7M%S*BTsf8g~PrAyyeNi!orzyVfv7ZFh5+8Lo&ia?SSYav8t#X}8BWAe@X$r>66+ z1jAMmnP_%5*Z;e5PR!A8K4-V|&lS5vt;`JojcY45uta}dp1KrkiqgAL#)Z#ci{jhH*M)OyfHEk~35JxBi zECgbtOIK#U@oJF?uEUt6WCP5RAo=q6!`*0M&RNL-S!kDeboB&)01?dc-hji^*ps4r(qD7m6fiTS9=)6vxmK83C5!_0c&Mh z%pVxQ;FA+Y8=IRQSRwPhy(lSWZkr0FGLti>kaj^=zd=*!?Uqi2Im~Pk(8M|6ZYAr=-761{G zERJZe7nJ-PW|ss0&hIC_H~Ae)Lql^>+uYw`){5fDzQ^?g4j0v12HP62+Yxnx2Ae>T z!;AaC->J$$YJ^I8!~_^iFh%JLFh1SFb8k| zEC9{WLNSBSVJ?*UY5dZwezw=E;CTGJAHPpYhSuy)4A23Ei66{!QOnR1!=)S1K5sKv z0v6eW^+EbT4n8etCY_jp>6@-LKcgM?wCWu1_8;31Z=S!tQ3E`P!1qvEG+_Zmh{;GU zv;QJb*mu>>MICo^1tJg#vb2U!A9q^c?WJV=ms+){piudAd4c;SGmUR8`-${}h(DV-Sh?swH44H;jZV1QUog8+ z6w<%%k=OvzF(;F=%_>3`g^DJBWIO@Utl_QF1e-bqS>bM0?~K@IYWRuf{i zxOTfAxzFV+=|ag*S{~#2SJ%*7dlCH+u~Jy%lC@H0IM%4esB2dxi=JKRiEGN~k}e~L zCRazk>o-prX2`_#bjHj8-k=27{1v)ckj?8GJ{XAK<^I#ML1EiWiZVuP(bL9&uVDE_ zp2|Iv%1uLcUK+O8&nC|wrZZQ^GMUgQsR6_`eh%5SQB(my6t#$?O2Voi1*}QQaXSZD z$O~E^^33ia0C4Rk0=tawG>dIi%OEI6w(EP;^uURnzT0HR+Lu0Kbp;y_;An8&n@99- z5)Bdk8QZqadpyevBF3u7)b$|tk5iaM*=kr6D?WsnE?Q=hWA&x_;>-gzDTP<7?T}y@ zUa&6kmI1X`8XuJpqKazpE=rsrR~lv#~S|8aKvOAoR50(5wl=$1R#!rIH&h|2}dUfV5~D} z$l6%a>%$8Mz@PYGS>g1iaBp~Mgj&QP3xp|DAEb?3z<=_&vdf7$zFL#`<(p-f<5xVA z2RiiuNMUZ|NBG4@us|f@;%l7!{<{-;d^L>>Cg5x3q5|dSCpr zw3nB8A#M9UkIMFkvZmr}l%dZHiq@Xb)Nysh5g;=JzojsCMjZowBp_@KC=em>;B`p4 zbqOc-`$3ApfU?Rk9v_4xveY8~_Xx&P?82!r08K`j9at-4)wjJDEFA6x66Ts*j?IH}+o$!eqY zc3tyUSo^`MmLq!m17>@Acy#>Giqo_+6BFMK$frhdz+VIWh!JX_CJd1=IQ<|yJoiNx zSM(n^Cc;(j{`w2_J%m7qUJq{elCq&1x&wwN19|BKrSLY1z>GFSYfw;DvsCvZhq z+b8O~uG-{^gOY8-eKEosp`RgqiXRmJuto9}oceajwHhdx#9bHnjFGIk43U!R5Erz# zk>7<-!@D(lfa2shJ~Jy?=4e>4q>fGO`BP@FAqRn8S#BGR?%p{3fYK#s+uGK={F0!1 zr^k%K#jWxbF|07|pcnfQ6@b3W6H#C;%nTonZ{qpP?=DqDMQ zepY6yUujUJ{fWuXiRr4$x{lT&1SbXJe7$+X)&fluKX6mfk<~FXFsOrTWb|q@Lt|hJ zE$T3sm|t~zzH9VJEt5(<6Ay|wv}zyHg*!27`V`pZ3qok-q#dodIX}))q>V1AusnF;)YYKXBS6QxR4j@n+q?QP$i)>WM0hJKG?H;lpJF`caT z^D3Qh{%W~`9y-m#>5md05}SQHj;{np_^U2su1%UU|2Dafi(X@eNI!3%_zu`VdmM}o zp`#8$9}fKIJ5K`FvxGK55Y-?JaG~T~I^p;B>kZmmiswe;@Uw=y5dwbTL;W(N1d;@9 zNZhXrw9;rbGI5nEBDm^#VpJK*VH+uCIo$&>gPE+4t1{_i30ChH&hnak{!I?}lJV43 zW=k#|j5;`r53Mr+PmyDBmnzIDD;xwwB>vNsT{HW-3O<2;7W<&Um;Ip@u8_9M;#h6jCFo|X)H{FF#h4e&{bzG^4o-;ey)zZ$c04hqZB~rxx)`~LlW`}9VGo7 z<%BEOXAx`CcFbX{rS#NH)I$DafS?>ZWxOp4pM89d@CoA&xDJQY$}GMhaca7%*wi6i zYf*5)E-Q^o)28ALH4Pw*4G{~2@hB38d#9OkC|9`FUXhJ`M9j@0Ys zDUMF*RpaaE^kt8i_3bZk4_hoP2=K8SG-aq_ncj3^FZ769P1u-^09&bSK2;@+tUoq) znEr9(%3BCrO=udj@b;KT5BOWsUYV^%;-0^Mz%)poUdopv3{(OuDzY_$%1rlD7~V4| zOKT`=5OgOMkblCEi<&}!^MM%N3_}qJ%vuN(UIM+WRtivhxBu~?R3+4w#f^ubHQ2Rf zuj&ndNrR zz={;Lc28Q?;%ZXTz4k|E0HMuaiYgpY4>djIU)6hkN~r?PzBan&@{)2zxqA{Ji-8QY z2YtnysfkQTB)Hx2JymSKCtDTMudMdE<~tkx!ZXT3)kLdXG^}6z4H+4^uk zr`U_XRpmd*Sr0_t0C*x;f_z~+V*p7Rn8zm$mH&P{`KopQ5vK}r)nHND3A!eL2H|uu zJOY4?Cw;P-%4VM+vW+uc<7G*y%^M~jV)1M^VDdJ{qz|-LQTs!f!%HhR@G(6N@Fu@? zp73-_-dygvMb|8BrEjo%5iu8!Vogd1U|2ZhyWw7Pnl#X;DW7yDS#4 zcspVD4N*n{SVMi=x$$6%0>mu(-E0g4Co@Sk1Ac3kfa&)JZ=EIHr$g`TM#;DyUlq3 zv$q_59amwBAf3ghpgugv2ubaa8>8i@mOo;pVN^}_1P1l$U9pA9hZZ__OHzw)Ohw7x zu~EunR@__~*bgr3NX_UaU@DgF*=i7$$;*<>d5L%kry;#*`0iGj9i*<8UkbWP5+5KH zmP;JPf^HQdorAAb-cMxa-1%OQE`qKD?&3BbBQH}}`2^c~O7!gy>d+-G6i&PKgv+%_9UBkvZ3#kiz(#DL*`dS`77+t*Dm4>`HPSceK0DD z0>(w3pPk2TMvYIoU&^K_%8fhV-a=A*ZceAR-4E@}n^Fy86!ILnM4{9^X>4N(ht)WC z)EY>dz3MV5f{oCps1{{%DSNxa7ZOh#AEW3bx-_JHR%Xps24+?z_iZ*nEAUqZ$JeH?CK3*N z%~TWzCnvLpHp$abe)0<%YV13OFF9U+Rv)!!?)qM`J_V|*dOaSK5;PN-N0MCD1Wf0c zo;|I*_2f1~Qglsy2j&IdJ$E-DH(H(lx6vB?)Sqr&)p32Gewp%)!(RrXDl@^x7F-5l zV3L+2kVyl4)ujDpA0DR6*lgr?y_oP0@Ht#}NwM^2xDk)h?&z3 zT*uFz(k;fD)F8Tw6^e>i51r@Q%zHDEzBL_tMivkKHH$e`f7FT1%-FJg$E(vS?>kQX zrr&(ebK6C2Qxm=a$?7Dw8Pm{e@%GmLMlc$%hPLrbo+YSI(4g@0vDL%We~4*x@g%fT zf~XxM*)it3lvT5xUz6IQv7`CFez|qupzk=-f-BcOE+ab>y`myVjUv#I4%#6vG1%Qp z6{o~ynkK6nhAKKvREs7!X!vXNAjG&!u4FfDMBhYb)^+y#0{~EHIuDb>LORcH>{aVR6Ca1OK$> z#u6Ec|Bc4-E98f{mVoX0R}~z4`-OV>(s>+NiA(FUaM_(4kiKT9`PXwc^d6T-=qaHV z;d@&AnkrY^P7gRRW(W!xHm5+#^gbmyz2YCyZJ4B?)16E7%nrzPLBAC_%&Y@=f#%scE0K!U+4ax2_1v=AO~zT z`#1YFJU1z~AE^EcL%+yK+@=)9r!sU6M!$ zcUWXuj}W5K;;+&vv%+4Yd0WR@QN&<;hPKoVkXwPsyaDU~uxHp2s|>2<$2}jy>bWLQ zYBo1EJM@eU_FqkYO_@yzT=O*hMRl}f5b@{7!zCV$z;n*?$%y*v+lzrNi|H$*g!nQ+ zs-2nF=lX8}a2@P|1E-3#b#$|fnX`?ZyB=xXT#9D-?D0@*wuJ*QhFYT!3M3+dAS{65 z{uzDu?D-OHgE7GfGnH3@d#T6bb_>O*AQ)yq(RT$YuB43QY!bo!wflYqZ!jJY<#jnv zfU%_qry!Q1yLakm>69vauag84IRHwdkOvPOsGo3@Z@O4VpmExn@W_EBj18*F{6j&! z>J|Yx-!>!0; z^BNc-53X)53+p*0$E5Q*(ZoeNaPK=ZTL@in?g(4+U8oNp3h4p@-t`b_>kHOx103A3 zjGAb-!s*C0=CW9ao!#7@L&mEDax|(jQ_y(>SJCD3Z&6xkTrl7fd~nXrK!RlO+n;Wj zE;K9GC|d_vvdNCiuwd`B3!#c1QBNd#(Han~20bg?&j^>=2(A;ePlsR?wG+h{Cqo^x9(+=K zaS`EeS2!q&jRSQ*CeYrz!)jo0!S81V0I+8l0dac1E2S_A_!pW)+u$^fucd_KH#0+75aQw`XCia`9As!5XM^#<+?AH5sK-2bOk`^PX*8g zMwua4Si~nxe%V6npCm!qPwl#gfpmQYqEKZ}J)9XqNKZ7C5E5^j?LseO0gr$v153n1 zJKa`a$3grsPO?Y(AGUe#Qz6}BfPOlJOI7byw!vGkuqNC;4N&j5lqRevsQEGOnF*JC za~WDmj5SG^c_r9j8DT1{3rSoelBA3cwaR{lem?A1dVq3}ON3FZ_ssW@0#ijCMRC>& zN`9{HB#V6UF7;CV(rLNU>Asl@?1~EN<-m>Vx1}XQ4^yKTf8?UyV0qS5R<%$jNV`Wcz%p+_KnsX#@+i3t5cK^wA4l85NR#X@uB67zKi}d)Lxb2t zf@bM{`Iero`KYr5n-@MAvnU2*9F5k7tk4;)pS})u4!-W@qXz34hJed?BkGN#0?>)W zqkyBQbKO-Iue}zQ=yiJ}-=nf}U?E+7enNKei5#?9=3Zv8{1ad6?G=r{#mqV9%cwlJ zhp=M--j*m~QJIarPFg`3cY@A&e@u10^%i=o0Psv|u+Lj~yyq2zzRN~A3&f(NN&ZS@ z;&Hhio9NML^LT`U2gt6vc#b?-Cu)32fe{|59v*3b3xZu}=6utZ{TylyA{^BsR>g^1 z6!UruQ-&&|yoe0BS@d0~zzl~J2(c<+v|m%p34@vwvKE87fV3LG^+SjzpbFKMi`f?Vs;u$t!tyRxUmV z`Z#J|KHra2KZI}EW(D9;Jxi_TbiXBIkm}8U8~O5ce50(&%;$VM8Kuxfs0tYO!ebb! zC2K3EdfN&!r&Nc1!4Q1QMinv0PyaTmOBV`{G*{B#G&92>r&D=;4c_VI)!+&erwfCk zfxkh)Z_=M^@ZFeNzV9*c6Pu|)!{sddqV+IxVNGOR9BW+MT$Mla{EYc9k|px|(BODA z+?RDOUKkFL>Z`+%um7m6{=wqDK#Ka1W^ZJgT1kybb?K+EbMg2Wp8a51jVTEWx5I7? z4LC~Eubqr3K8$RHTrsgc7yqk`vzHUk-J$2NjkUGkn}48reB#(8`(h?SP4kC1M|k~V ztmer|V*gi%*L*A0^dIo`Xx)xx`#z*ZcYVF3$3wNU!+@u`G4*%O6Pd4yE~A zuR{wVr=@^9^3^VT4+tU;<>n1TCT$Me|5_b0<9XwASJCM|O)|(`l$pP^i{P&rW*V}KUKCIX|Wuvd_(_h8cZ9B@gUqKP*0&t$Ggh2NnL zcZJoamrtMK$~#i~2cxK=>0!%DEKBWBN=!+xO3efql3=puXiksgH|_eopm}&1be=ux&lG{ zZX5c#GWj6Bhg>H^)~mXo{GC-~Yo$THLWve;jhTwquRdQsD$5+B;!d6-Y^K70d<$i0 zp6^>8W>0VFQDo47;d-*i(v~DpbcSlek74mAMDx!TWY-_h6xKi9o;;ZnGRdIM>5elQ$k59w^^bn#jel!RwRd!i)8r^=Ir2#D9@b`7CVY z99kzQ9smz|F`7&;F+Jp4to9(I!VE^~nBRd70{Fp}04pD|tL~*RyZ0688Wm~P^d*8U zm1xma^{`q@d_DXyrUeC+R17pab!ay|Mhoc#!>iw52L>5nx7T2R0%5*SUD zhK~yE6N*hwCp-;aX>ZQBA)tye4R_fNB`dxQCxeaBe`VC+8JEr%zAuv^wo{P>A`EV3 z1>>7GB0nNd{hy48<VdsPX=!B7cdg%eyw^ueo;y$2 zA*Z|Fcqm8qDyFS$eHX_#)vv(w z(69X-BViZk{W~28s;pXWDxG-toN!}6E(^mv=q4>eY2$wdf$fd%%h%>UzgR6_XrRkX zHYja$gfNK+u4sy8Jbifa4W+b~%(#|FPB=`7a59Xt- z>bKmOm9JQ0ra(@04i;mS6yG&{X|Xaz!5=9n6(W=H zkLNjn5lPSZ+uFy(*=_sIYDE#N39>96tEm3-8-@7hoTU~tn??d zwZB(SwSZ>$u_)x|HbiDT8x9yYj@{yDHo6|4ggU14{U|4Vw~p7lE*u%IUS%Bo>bm)^ zzz)K*0&JAh5~6>IexF>XoJoj}_mWMP&aNOr@Cud*k$Mlr=&3_tB){$pV|c_ZCXut8 z^^MzH!e0|3UWHRewYn-7h};Uq#>A1}u?Hb#)}ga0jBN9%6SUNF--SP`8jeGq{e;9N zaBWKvl@{Wm5W-0>k~s4~_zLM@8*06H5hJ!PI(gR9IA5;nvf998h$kJd&mNJ>90VXT z9{Wt&zN*LJiMdJ4kS&cMCYW)QTJZ&uBTE4vota)#tZ<)@0Q^kp1n>A;eJJ)BrOb3! ze|!(Dak%%*+>fR+lX-8OgX}cPlh+bE;ecbofWPD4+rxWjB7fJjhX>)U06vHoN( zY`Df8PIeIGI;2yU4VuCbK0#D7QUKsqGLI5LG7%y{?Xy3S9IQ_3o;%zn&$_lc!yOmVZ4TSns*jKu8s~ z7W`%EGpFk#>+jO+Cv3oP&+~NN8{R3WW%%Onb!TYevSrA`;;uKfYiK<$XFv?d9MknU4ZN#(4V5pdZ+7@Pl9>cch#( zV392MFaQHVbp)vAjG^5)n9-jQ#=%4XlVJ@zWNe9JEUR7ClKPUUv(|7fpYF!;$AEO z7C?jJ3=%xKH9G}K6TYFhBJj1$A(GApp5i-iu862e#XTW?a4`sKDI~R-j zZZI@61Ua5L-dXEG(vNVaBs}MYf9h@967D?A2r+Ekdpj|<3g;;nnGeR7wK8L&T(8Rh zQsN%pGaTB%4;J6neLQF66RHDxuStutq5Mt9&c4Q(sxYt`$_(LE5tGd=YtWf|*MIoH zA7z4`O)>ky-#3bzDr6{wTQ66tB`Dpd`Z>qODy?f1#iLO>?yt{$Q=m3+cFtirwZ-5f zn37RLSDQUdTEE?fjlJ))QU{drh8k*>e~O+8o!Lg&q0nRe887Y6a3`jCOxnG)UEOlA z);Kv}8SFRwCO{2vad~7o=jeRz`<`?rg)d1McaHr1a#ogF9`DHx;@^XE7thg4hWuA^ z(k46R)*7!xieD4HilKafz4#h|XyZGGo0OHe@D7Fphh~MNKBilIBxKOe!bQ^f|LMZ^Se^Fl@Q)?xJA&uZp|RsZ#_yzK#)w z;k~1Er#KKXw*L1>?335}nD@05kJ#pp>vLWqx^p0A14UN)nqMIAJUM&>h!kB2M-2K# z*t)yj{ci?F=}_t1R53e$jo5WKlZeO)rkjbPwkZBF8KR)haq>>~xY+&M$2y3~JhZ>R zjUv9uwsJTfCCgdxNcP-i&D+a~93_$f3SgDujw?$fsdRSfV5ld6;gzFcEAR+5hP{fn zKi<~QEq8+^I;R3R7;f@q;R~U!k2Z4NqDU#L7&>2imd&RzQn6gl(IYwdziOCpE)v6o z5ASgLte4TuzzN#lLP8cskIWcmS=edXKUdnis%>?1Sd`hf;U-7&TY;}jnEpmA0Sazh zH(e)EAxzCd!N5_}f5%F9G;jIvM)_T=gB^NR5a|fLKcsshW}APhdvSbpsNq|Su#0zZ zvt2H6<|Us|=Bie2|IK#=g2B`yxtBo!AclX!03QD`qX{>7Wd6b7*Xlb-2kKSCnc2mX z9{O;ce5zg=Ah^{*{H2kjx#KB1Uq4$9oG?-M3jNeX;|g7jnQ38I#t(pA&w!WYO>m(b zS5SSYXVCs4=a{%e_!x21+lfHowdsUfc9^@wy;)6d)44hV( zu^_ZA;3~RIFjpLxt}!LlG%dfQ08&5%(cgCRz@zA7;dihyayKv&IxsV228*m6$!Zf$ z`qfnPXyN?)H@r*ZYQ$B=dg6e@jOZdh2+byI2d5ZPvTM31Lg1)QL;JFiQ4P}agX--k zQ5~E2yG4I(WKIDSH_TdbfG=?b<;iEhl0X?O zuJ$wXn&*4xKku%mFTbCsyB7Ut<&2jae60Piha1KaQn?(zjK{5LLb&A;PWl}7ICq1& zo!cLVuLH5*=X3LtZPCkQyuX}{+k75YULlo>$4JX{`R8T{q*TvL{YP!Gg!S}DZs0cS zn!Bm#yj1(;_dMUJgS}@tlMA8Tr!rb;=ZEF3>3|nx|D;Sw5d+#Zr=JtJ%o>qpfTpa; zcfJqpwpkZw;f$HH&El1T@y@aFa-}l)>C)h|{cY$_WB+eC)`$HG+TV_KJUgRBn*;_k zZkplu>GHp`QIuXS#=Uj+V&Y@yCuCWq`ue+J*5@JB5|4Q0@@+jd>IGOOHzY$dO}nBg z+6gE`(cZxR#7lF@{wYfod!`*R>t5!s9Y;%8hgn6&71Mh9`q5d4Wu`}RhB)I6e6wK- z*^~H$O5c86h9+B!F$7}hW{i17q}2vt$3X0qoN4L}!1KWyz3a5oLq9J!pqq_{hC9rP zF)8L7{->{^D>uC)7|b@ZvHrzhA!K3`fl4%TnmiO!gP?B+c~kWFFWhi7adCUvBq7WZ zeg}Uxu;TwQ!Y*H%JQ&WOQ2gDnXrR$RgR=mPPUB_X5vqPS4q`mG?BI{;nDUoVF=boO zFa10vo_+@gxa-%TpkZg#e&~R=6n8TO50QIo=JR~p!2Lpp9+3d2!?VBF)9*BFdNLk$ z5<|%uxAgI2a1V%{LOtmj6;^xMV~n(y(>sz;p%BcdBVa=Mcn{fCj`J42T9aL4m$7Wu zDmZqGRd)ozSnAu`ZjIXlas$lg+Y~hEuU#Lvo!hg9RYy98=hV^6e}YMt!9WQXH<9!Q zrIz9Z`e0U#K9yXITxozsw(JE>`XE6W(;y&}Q082v1uK6Uwcf9rBrPCsDre}6>Xi{- ziTbcYev;cw*-Yz`!o-S_On=9@nWlQooNDb?Ne02^{$2C`On{eZ`vW^D{>|s9){|M>GQ0f2xFK!+{*B}un+>x`LGl2;DfI!#BpPIB{`27kWP11acfT6_+y2%BoGCqXzV@7!Lb2Zb zx9@Y~_*w3@X~bD|cd*;lqLKTzLs=STwgt>rvpjZdE1t7Y$Y|z%)W?;?+lbdUN`Ru2g33qHy90tg0Wyr57S~A zzzPW_xjyzg^!*s_%;%SHTUOb3UH;qZ zX783RCODilJEC-`7hqGYH+~<1g%;XPE>6xHWwLP*Aa{a}iU#r`3X7WLn)02LgePM6 zijpzKPLh?+vL1{$?ofqoWTU&HXFCELJ~w#E^m;5@}1HtYE#X)G`)R6lqktoP`kn}8TpRhhI{x4&|HC3kzniGlUG)n*VdQF+g+n!d#6|O zsnizkK0nnUg&1w~c_!imhR;1J3%#LL;Klw>C6+@zO*LvgkI_MyY^*^(eOY|jcONIf z#4Ig9F&6$X4gP6K*$3ya(E%FIzT)Sn7EY7eo5$q`lpK?w^2Lusuf3sX(bW1*T1gaT zLD>RvsusVFu3TS{IWarK;Ofpk@)Uw~DRE&Lk=liwFA8`D@blVbv@W+h*5sJ|OaUV3 zTEtSSP#Ao(&gvJ1MXmob?&zokTeH*3-OuvKgVK|y$LJH1*|tshUzzUfdMywX-|=P~ z!-GmJ-d_DZ{iUwy%vWcwE|0tB zf9|X~=Yw^Quhqg{3*dd9Q>gohmh;yT0FZUAGr$$Q?cC%wdG`JFXKjA|qJF-kO}z2B znJQw8^~f$l;=A9IUSMxCsD%(QfOL$6wH6ZD{Z|M&(>RIpP<9D=MG4|$SN*3RSwRzP zw=-pTB9>D!b&)@cEkj?Fo{sxE7BCBjOnDUAA51XzzSu$&71?(^Z>jv~VSB$}+e7=| z@oOE6)ltUoFH6Y<@>A*UKU(M*J!RDiF)U$8OY6o!cy2JB|G^y>_D{YR=6%Y$l`c6k!;=tc7DcU}P-+5yg`(3B zud-XH*MZ907r6Utl*Os&z|U#^tsU_73E^J@6r~q$XsuUY=o)#Bxw6Q&-H>Oa;GLdy z?bCZ}qYi;#OX+5Af9FK_bkRQ&7Guy9$5OJ~V{hRHz5h0`-+&=nSSE2;ftv_$KX#id zLE(83bNGp4-2C`75U~UV#GMUQrDux)JBIWvy=hpUm4Ag}uzkoEW0b4wMKOhGjVjJW zqV{OisQQo0L$h-1^yqm%LCI(NCMq4YE&QzcUwrvk#Z8Oaz`nTS8P~k;Z%Vs%DJ;NM zF$T|8jsL4M!`QzIZ%Qm?lSZc|3XLR=U@qBxvO|$1aeGGMc+3zmPP$t{uxIvl)Si^( z{^;l*sCb%_JbuekRUs`QNc-2aZ6|Aai=vnu?~ybpR`|=iVXtYc*d=<}1tHv^E7})i zvUNotl{SOudocuTkM6g&(ct-!y2?Jm;!;=hBjgU*t1+!o`?2mmammgok1nyTBA`6Vu&<*6mqfO8k{!<3Hx@)WH1p)?@;TK`7jOi6 zgV7~eF;?`gPkVBFPbKbkEQSeRl|2+UEGPo&-5nEE{HYj4c_a>(MAe@EQ77jnP5S;- zRZvEQ&SL8docg6?I>wgF6v$gSKNOlodO_Lnv}`8!htQC(BUfj8jYg>GP73Q8SIKVh zpd;es`}Dr_m-6?+?f82e9SD6kK!Pxa;>%m;x~YjUTXIo=5O;h&@O6<@Ze@KRqAN**KkNhy^KVq2CnkE5c)%o9bfsLu7zH7-6!ay zzM(|K@04YF$lJ%Y1yYq?*}-c!*y&kgWUT2dc#FlFH9hjrGegz_oaNtqR=>V*mC13h zO~Ltx;)I*ky#$qxanV~?dfy_XHvq2Hj{Mx?X@0Q(gaoT@%uSMZI3I-s`h}GLI}~Rz zvL%0=Zp%sJ$V}e@{uUdkruifXX89L3_^O+NDal+S#WrAYKFRh{fVlZW+|}-);dFn}p!_p`+Hy&Qv%2O3xZ|3hf$vVSJY3Ds zuPl;I0U^<^MAXBS`l4n&%f9DL?@$BBZ0&Fb$(hUKW@ifB#>@&|`klOxG0LBTJbM5* zj}Vv`lcpH%vgtc#kU}J~&>Cz@h);oHQD34qUzA6VuF^~Q)%^*H&NVd&3Ld;;7U;zO z*m~UYCf3hv+M2$bbM6+VJc5*s`A-Lr0wW(sF!N!ifRpSy;EhhUw~Ecfh=jYuF#iu-%or>X+GbEN&}fWg`N)Fbxo%z{_da1 z0ssgKz__2S$L&jO_}qP#Fd~gcPnwY!8!AF_&CQ3`TwfMW;-K9v8s~$g1>uE^1R#AK z;i>mFpFqq%U0Nc37q`_my1YhS+iG@pYU7Tieb^b0(HEHQ)mel&kt7Jc_YDWPOK ziped-F*D8bQwa?)UPsa)f{vmZcjHiu{_Ct+#M74YjjJQj*ZG-n_i8=r_vaAWz+?NT z!&GFX!Yj0qAVkf_OMZBIkO*Uxi!wWXm)l}lTiCG3+M2Mx`KWO4`VBa%`J!&x`X`xqJ zoe_;fQE2&+`N%Vq7R3*X;zoN!E)UGplCE&O= z>3lCPL=>1wQA~UA>93)p)LX}!Al!Fv(rfPdI;z!zA=qI=c%#TRB~R++BJS7+xZ0H_ zS1%TLy3|VT=YNc-dOGbi{6Yo+09a9OUI9)>5@-n${M@3DK^;4HrhjX_yQapAW@0T1 z&Z*Zf|9wHjeyREPgnp^_jwMBT@tfv)4g*NPxKh7lNd4&SgL9L$L))EwPDW?8^DTh} zf2x{8&~BxZoer_@3gu6m&#s!MpRHi3Lv+iD!95s5*zbPF1Hs^m)t=eP-> zG_$oZW1TzS;6SKDBT9#dxMns|$Zaydv<1 z003`Q21(fakfSCE0)mySKCSRE6db2-ZctR?BuYnJD`V*-$6|9%>n45;kJI0td(S6A z$?_b1&(~ni>a(52C)A0$cE?0fHbOZ{ibU`B1ZFGurzdzRCehip8c@DuvLv(v2fM*V z>;-F9zP*f|E)R@t#Z&@My7aydx6|0FHk69qG$X+8R#@UFSEX#`$RbF(18O_(-Xlwi2vp<&EI8&% zfGp@Hd!4au8D*0Ij;{L&FHTPA-GNQre^@*`c<%P8X^8Wvj?AMT3}CAgT-Wg8(P4v5 zr+}dXJ;&IX^)U1`2!zsG2!N@KkNOYbJnIMkd~W|OKYi%#n{f7dPepHH_PA8#0G_JSfEz^QO#lvzOae!1 zv_|V#tvBzw#1PNC6hx;m9ALVDH}DV`HtBv5&HZAkO}fD-T|1>)-6N(J?Pg!iaeZon z!vsIFNWJ%}a%=8miHUG8iCWPSpV34Mrl`UQEO-a!gMnX0S+F!#Bf=c)Zsp^KcDFI zjr1TO5nzHH zLVO!+kp%XLHt|N~%gIm?DG^=GA~luRx4joUoQtf7CJvbp6ASFRsL60$H-NJeaEAbq z4srJtS+?P30G}A`?(cp*kPLvIddOeh82yFD1SRF) z1+KOUAqX_4Frl|LM2UFcM3BY9vMQIcw0I}hRt~^qIc7JUirI~4V|;vTIAl1WYn@&v z!~w>rm)60>s>w>z{#fLz-pE^*CX5Ne)hT5}_`FxA)r8nKnjt%^5>+TTvW5ey)0x5e z)MlJ;+G8<3wfUS4TTgwrI|t@aAhS8coIill9?0zJW5K)0pX0!?e*bO=aK? zGeIf+836?oat`#mnwh*#`JEw%3C(}ajDt+{c_#ep!>RcP06O`{2F93AjZclC=;p|a z9G$TO#aI#kyA%Fj$jNP@ZKB)-O7nLLmL*02M^6CN*`YC23VWwDwQt1+62fEyzM)vA z?w(l_H8{lmF>8Jxw>$tC)awF8ah&cVjL!H(05Ksa&WulOx#y3(Y}fmppUD14X87M% zT#3cy1=Nd6sH+lpFC4_JgCjUlE@8nAkeLiScb!chA1tzw}#&_ul-DwUvd1rK9_?p4N5D z*DQe70{94k=ZHvebh3@sXpPn}TApATA_O#Xwj6z8^xhPk)Ktf6lOCm^%q<36Y%rsy zA90}NlRiA^;A8V2*`(BBlcokUy3gzP+rWb85GonjMX#wA01@E;9}RS!19WH>%(b(1 z%(z&qMyZ|ENWZqZVHmJ^)yHdOouNSGXOmp_+lfDs)*owlW=^#HcAXq2|B*2qKmrF> z*MXtyESz`x{MFb{hX7G_D{;DSZEDJ6%@G+Dwyxo7o&GD0pA%!3Qka9uGp+vvgTt6C z^cprqAUo^Q9WcwYV4SE70`I)`CoT;n8+k`eYcR-)LLb{C0L9jgv@#43TgHt_ruGn+ zd(* z&`C@%T(J>1jh`+LZi*pl(G%N6N}E9w88%+g^ms#$ zjk_fIBsHgXDl}SDe?vf)fik1A06lj?oI{BJqvLn6j0k!~2LzlbkRQ3%n@#1nx+BA9 z^9N9#4r)vLI3I1fXFf&*=Gxc?A{3B4WL z0RSD&FrD>~SJ><-J9aEy*JW3}-(GzAfBo{oyT0*%WqEOXS@to1=(xuaGl0hecn5&D zh{$;wnLApeHCm%}-wzgpOi)xnEg%oba6NF1R(@MEC z+OcrSAWxfVuaoh}W+QIWq?%vRBZ%G+fcpBQ;b46IPQeYQj~O)kp#cxQL3l3l`BMZjG+TbV-?fo)}?i4m`J{z6x6uM*6AO!7Cq)5eSK8wJL)y&iQJ&o#U z>97OZug7pF;k`8{cgsjuWiKm^9 z?)WtAzw@i-ob&jnU31Hq|Hs6ecRlB?U%uBw0X_>^__=Z9tgih*5u@}WZqGh4aL)-~na zMNS0_hiOQW^&sL==oulw`hoy#-G~e{;4Pmg%Krl5hQSc!l*;3 z{Tjl|-0Jlym;fHnC83Dv79BWS?<3-G-s{gT)|u+U$|(Yg-+sKwz>wGz%HB6JR{VdK&=;5@8^ufD55vlIWu8?t@J@+GeI zmzECRb<>|R^XnIn?0v-Q@)2x5`CR11aUDE#06Z7K69BwPME-_|7Diihv_@;R?$e^_ zEdV_Q=n#-YFb+y&)hJnGFuc}n0yfk#{EKV=06t8#{XNXxl6jp*0YUk@y_qv;y@IIr`ZO03%WnD=m_kMY<^XHI}PX*B(+txNs_9Av4XAvS4pZ?u_@ z1G7*I>uciBxC^P!&uHuqdt{s?1%=nR!a&0hbv7vo0H77^M}Tm|`H>ez0uxxDYijJ( zB$1c^C&6P&d?OQB=PRc2L1Xm$P&t50v3~L0^5Vl|*EYoqrsoUMx`vu`2vEAtqyvly z(ya4C@C{=*f(3yQVl;isww_Ppi_{)^3S}^6D@;CsNSTSJOH5vV5Wr_foBTlz0EozG zApq~;v&07kvFr~~_J=7l42rfA6ND(3j);JLpaI!BIC2W9MhSt2<;7!pVK0V*MXasP zq0^hhrmbhA)166iCgCuQ4xOskiPL=Dp8<(fgAnT)1UHF}L$U3nOh9AEqj6aidE)dC z4$Vp+0!VTsjnW~}$!R^T0&1BVu;+BhN3B;qDB-Nb#x1AAWCafF`PvCP&N%hKQ>w7~4{rXc^R#&=R(>vQbx0G@D3)b1KhO$!$)brx<@nRae=^)Q@ zbn+fZOcV8|F2vLvfXzKw_abX*07;1ai&GhDWgUmNQxAjo)P+==nZScq^q(<6cASs- zx`GUbIJ$5IEB#fovbKD$&9@=$mEMgLfEq(DzL)l+`oU;`+Z95&4vs;hrM-jkIh`bTNCF1=x06s~~BM@}7 zMr*Xb%QgNqQ1^U64dQKTJrbSV8!sw~bam(9AVL2w9$xA1sljd?Qod!ZM=9nHjpq%8 z_*}GQZwiWgZ3Gjm&Jc)AODZY}NEdE3{yHW0(R439mq>F*BNK?!`!xA?E@9AnGL$q!P7vU?vpZZfMw}T-XbUl?kC{iEKE<8Ahf+Tej?6W6nsL zFknp94D|w zGdjH!5oAT6(+>wF=I3t1($Tx%oW=BplQA)|9Yryjv{hasrF}~e6lqy$@*f>fi@e#0 zY+y`?42y@3XoDi6Q6#O{zi0}Qv|w$A)u^qa#^p0=r6cNSRB8|omt`UBI_a30wv1~Os29JW57nEc+~VJx&y;2t>3Gp#tTFU z!cEcDAm;=k(eE|W|CoUcqhHx^#9BolgAz=HJTEZO9p5lBIs2%4+n;XIERUJI8lntE z+OPs;8BDi;>Gfb&R#AzA^$yE!i2da)6}Q@S<~0lr}Vyw4;}lL`ifmQ%3H2|_D5Hi4t;I=&PQDhqD%YB z3)yMsJ`uf%nPYZ6o7TVOcI_O)xgQnh-bEsB_bbbP0_MFuJ~0C9Mr*W2>pMgf%O#=- z3$RXTRp(9~WC-5+)KD@re5CWUc4l6}l)D97`!Oy3{x<8~^h5H1ByfPym`_83c^#z11kf1jlyKmYCf!b(c=I>ibAhfV~`kY_Q)n+Vt5JHkHN66PT@PT9%iBdn8aAVmaHNqZmB7rwEPq#$_O0D zQvz*5J&kqdj4^tTm;natFzD+8r9W$;gIMnmeAe@-ttxJY|B8_JQ zv4OWXTw7zpXQkCE7{kguP#_4DK1&3^`DVbGBpNMGha`cBtVjSr7myyTJ(`Q_|D@!b z9t+@KM?3w&4FFv5aJj$@+C?zALE$^75I_Kv8IA1FND=FliqxXgs~%WHP?c*~Tbje6 zeK#S?y4bYskuau%PG<@Nq-c-mD4GsAYvFD9{o*~Gtf%j|%7#h22^y{w2hgW4eAT4~MpyAWTQA=A zw(vm(mH~VPz*qkK4HxtB{QO79I@9NNvhJBo=6TN7rylJeoXSn!8ShSmgpived}Vpi z))`8k0dbN*5^l((dq|u>n8Ltci;*}vNiNJ344K4-iiuM5Z-PFtbDX_12SdO))Xt$l z=!1!tz1Z8o4HCN2H?D6Gzz=Z__51>4Y7%4&1cEhJ;+y?BWMK5V-MM1x^j|oll}@*~ zwVUB7dAAE+R-lz3&N=lQ6i4>pj{SFG%~hBp)n29^M7*e~jacX4nFOF(wVJgWN#CS#vD_f-$W)?3RZ@i~$z`$Z(VL1%X!s@X)9? za)*!xww^*?4azk53-W}Z`zH?ZxDoKkI7JLHyKr@bi=wXAn>Qub00%J4l2FJ{55X@KVGGvIl z+BL>vL?F1v1kl%5T|SJt{og<}>|=U%Cnl!1BhSYZ9Z8g~6wtY_sSKIMeKa0CN`or8 zMbh-t!%Cw*C}@$C5+wjK!%f^D0puyYu4wv#s6j%c@<>4O)X+nGGx={!(E^(wn4(15 z6jJtTY;uSR)v!c?4tAV=0lx5wx1W%Ax-SCoe?Qze@0YK8yYb$iX_y|vBC{ei6^?0H z7NS~ndKiQ}^psSBP!VthL?8cwD_$@^Is)(CdiC$T-vihKV9#}b_;b8GIQn$QcG4%2th>9=)Zy5!0lmbvF10VqBCKV!WP*D_(j|N24 zE?SbKGlB%*crE83RShu1I*ZI0)KzISGWXh$vXu@Ps~Hi7zQ%;Ja@~kG}HyE1vf6 z#m=eQUijPZu8-&Y{-WRf`=z(M0dF|<5f_#d)0ne>+D?%%Oe8uBLTV&z(sy>@r?jJ&oeXSXh)9LXpPprt?RD3WJWOdZ1I&EJa<}? zX#uIHmvaB?-Ww!gKpotG%Smb_z_6S z@;ubdQ6j($=k2<4JxM4vn*jfF;oCoew|btwlyf@+)W} zxCOSVLroDK_bJGAqrP9fhp#QH1Tcd#lMD~xWgQKlO&B10HDZjnBW8jKYYGI`fhQ2( z{0!EcFGk;qD3e4?NCHCgKulurf@lwcmUluNK;}gcRyM$vcZ0LZXJ_O;4&c3`9seK% z005i|;E@lP3!E4Lu?Z#yn}E<&gV6lPs1w6RwNoM9&sHVYR_8G6FQOc-qUcOv`;NyW z%R7pYxpoK0xzA;S_pqLP5z!AC#_0lV@PYyYD}YyJIYU4aP!$nii3o=Qxy^d{(uJ?Qbkr;y zLU;C`MR0iyc4rqc4A_B^L+yXA_$ODWEw-I=HdeY zIuKk8ktc)bM!&eQI{*Q*BY%L=8m-Z~=b>$h>P-9+h{h3ZW!Yo^LZfQPG=_4mqoz5M zw7zqp%!qd>QvLdRXLxEFL2CE*8m%V+-=0TDojn@-GbK?mr9l$MgqwIDgjWat=CL77 z#B^I?&@`tyT!RA%H^Z#RXwdpKG?)d504pKhE;Z(vHq)BiL&V66Jn7uMy7VXTBAN(# zpQ!RN89VNbKaLErK;@rk?cn=kb zLE9IAqr@37#RjT|pZ*e39_85;VAelMy=s>?d) zyNpNP&C~BR8ZpvlB6#N#?Vn9RLLN zfWh#ZHXy38A^{j3Fc})3+)yvh?HvQ~umu2a+WpQ6ft&%tj2Cp6NJPY{&!Q256+#eI zkqCtL3FPx$%$^Hh^~-*A^d0~8{NMh&@`gWp){SfBMs)4cxR;sFj&&wpnCHbwwXJqq zS7A`EAvZa4lVjuL7UYz{aITaUi-60B%_5vJ={8b;>obfE8*Bzy`7q^}C$jfIppY)vN`2&-yONVJ@(@8kt zlt(9))OQU6FasLXM9I`jskfwlETNE^h4>c%c(#cA(_sHy*LAw%pXCi3N78`N8m-X^ z^_#dM5q|}gJqk1qP=Ubimo(j_%)qpgpu!MIYe>XsKwcNC2MDqlY1cZxSiPPQO$5D! z={HF-xTBV_o)aHrYg)v{Ce-MFEcjX_-D#sG*F-8vczjm9ya%@f0h;DAB^LPPClHwh zvDS^u)W~Q}%mIU>pGO21$TYNjA{4z2h*)#&Z8Fx2K6qZ4vGJacWX#7%WxFO7c<}&P zz&6HsP_Tk^5+4m4y~d1tWs8|435dQ90gMpm;p#fb3Do02#Dkp+1tW7x0}B9l_vO``SyNJ!JCqQW213e0#Ap#SLfJIO%@Lh{Y zDWJVV^snc=?D?ysBky~=UizCKh&Q0s8-C+iyO+inKG-Qb)04f~U&~GY1ZLV?d&~^& zpf{`s81If_YJ3LcopIzQYch5ttv^KsY2g&I`{ex}%;KJOi~pNj03mANC2s7^Try;F9;R~BL|+-e`WCu~Fql#gR>ZFOhk(-V?2yo^51;D>uzw76|IJx20x19dyAH8CB(~e8_-uA`ru)l=v*fh4E z@~H2g4G_~Em;vWN(GwujH#u>0!%W4w4J%7Wo;QDZ&$F4$CvN}DKfV3tn?C*Nxw$(J zUHTjEaHHKgTBG%FMgX$yBK~$D3r)BmhNMyUiFz%q$uz5xn{UOoMTh+aXj02vC>>kW zOrxVjwXIukIp@cFn^$VL@th3#lBV7JL~r-f)TB;z@pKQP=?GGAD=rWkuPqui8x0GE zk!bmbGHpclxfxDPHj9UI(d2m~hbj z|Lnbayk%8+=ly%uT6>@A&bMxjOcu@}CTcKhoZ1bT6^CD6%|3Lv;6Qus_s4a z+ zfxG?Glo*VLm}*a=+wb1I++BXxo6oz*9@Y@uW^Y|Ng?h!t`MFKBZQHScXRO?M8?*pH zRZTDCa@yxNwZ3@zS(l~988xzAvDI9kUBCQ`gWdZuvv~`KckhL7HZZ*P4!Ge6V8(3L z1_3zG?`@v?X7}_9e)C2DYv*77{T&a)>$~%ui-rKc__u#v-gVURPq^FJ@|4B>cTTn^ z=Qj4&4q@X_kH+-;)*rkHPJOiA-Nwxi|In^GzF}5Y_8sc3E#Aoh?>O_K@xCx#<8=fqCR!nOIZ#+I47dwY zjVdC~c}a-!>o@>Zi<|W+Evh=RRg!y71%Kd031vP){=g~5R>l2{IYsu>qux?+t<*Xw zpF+hSh{bKP4k#5AbCCrQwE{7g&pSEuvYb_Y`rVj0G+D(y>x2mqm8;BQh(__+)B%WG zYdDC1UkOJmK2JvA34|!-AkmNh`|7M5hGY?#7n2Q=Lc#@}mUkZ9sGdg_&*M}T@L=)( zYYmmj=L4#w0-a?j%M$P&rjZ3DVQMDFWC9X@f7M_KzjLrVq~bwp2BmZw`i0a2iW+}- zMK!yyyl$RhZ4thYWGG0S;vJPyfS2TfXh~26=WMVoCq{)RQm6r-0U`_16EF5YfA_cn z@DtPk0PyPorXR8!ELSpqt#$IOkWwg%5sJYGwkSh~POId_an51o&|O$t*@LN>t!Phf z1RO-ZQ`rKNFSG{Vh?|5b4_~^J9*{QAICW3{AeLB`kQktqM%K(lZWAOzzVMPhfOIpa zZkse5Odh}_u+oi_B1IF|JVR38GbPwb@LR=>G$$(qgzg$iEwLM#zRp<;`>W_oZa`V| zXFXYaq~5f5f8cMZ05LNhh#fH*2E1Z+OvKDEAY{yZ11q}r(c|L(CvKg7)}_k;mI3Sr z@C^VTeeb!awLJNUZ`*Lp`JLv(i}x8eXP16O6B3F%)0mNj&nZ2fAhu{T<&h_zUhuVw{L80UVvNc zp*Xmh8V7N5QLux7QoX&aFQkVx-~T|rwy*my7v6s1+fO-5>Fj@PKIX9}H{1JPw&|G1 zy!4Kn{|y_rJ_1v7o6+n{|6q!Mx*9+!kP7JlX-}6pCL%)CY-1*GV#aSV))up~8@9c0 za&p59wKl)gZcnXsR}QQ>XFp%s(G8!v@ZtZmXYaRfP)v(&I`g727i7G~>mj;!o_X== z1?TU!7@Y&a9GX3mHHz#oy6urK3*G@UgPkZ zWFVD;-7=Vq6Ns8m0r2VZo&OWi0AS{M0B?QB7XO~pMx>2iH(e)@>e!-`JkgMQABmRi zJWSTc?1t@VPt1Wm!^zeVHW!)x*W$s52;>>i;b*(j0p6$SV9XGW{(nS@t4N!OB@ zxYFILRhT`(<4Wh&ORS4F!AHeTI(-Noy3`R(p>v!%$w49&peY=g0@7U!#MeqhRtFNs z4Z)T}tSs%pXt=u8TRr$;K~(_8V#uI$FQwC2fwlwr2owD1ngTmh_!wftGzXh%F!ivAKLr>?fB!1*8%9v z-oXiUNB2|>mCfaC_@z~Jm)DTb%|f?Z$QsiC5zIsfhrWFy3U4iKZeOMr+Fv;QDcHIE zJ7#0+Q^lU{uO7JJTWUV*gr~+H2g~3(&`{{Q0@iRZd(`y#bWHok2jjKean_{+0J|?Z z_msbGPt0DMHQEbGn95{an9B$JnL zL^W9stut)e`iQ8mnj8(flg^c|>8>8)qmF*uVDaExi=N%}|NalB{ZntSbj_~YuUlN} z9^BK&+xe)wxbMy9Tru`hj@NiSBv#o6cb6FXHuye3Jt#d156OS&B?Or zW8o$2rle4dvDFewtF%fg(mE*6OOctR=cq;4ic}u8;y=*$tBC8^kggBKqI_RTbY7ie zpCE=&aZnqOL5TexRU%cEWfcb@{;0@ANU8uIeC#Sq*GX$576%VRGJY&pJtzM@L4o1I zS-Ph3QYI9_!6qEe%(k@Q=gBqGN~hOJDFtPMb)j@4C}?DP4geUH>k|l+3g>X8HEaYPBrv<`!{UXt}VX9M8FRS|g;QyW5NrgiYv1-J=U=dQF7sr3zq`pvDfT#`3@%|qov zv}XKT;jU(l96B?haJM#ia0KpAfjT$=MO11icz6qxgF-w~T6i7;WQp=10Bk)}ZlI~^ z1S?fVT-7_9fqt%Hvnc&rNtWtpu!`R5eiTKw)0tZM-AA0b>BP(5_sFXc?!Ngd4}Eaw znMVffLm57b8QVb^FsRLpHbI)Y1noUWAhpcEH;(_cUtS$=aX)?QHUG~C_5=9T`_FmB zrzy*~&rZz!=~R3Ak^O$}af>TW9@!DiOwD3$dJZ$wbI_TAZZ=Z(G1UDC{wqrO)h|a}i_uiGR{PMo#gMab5Klt#zd(^7~e{kf=K6!^tDu-ha4TW-P8G51v z$_#X~iPg0g94OX2ZJ&BSKXLXQJI=nBgb%F_4UTGDTkKwXec2zVGFQnu;NdZF7CO^Q zuBBI+8#{k#pE&i2H=l7?`Cz`5JI}tfyx{FG|K{?+U2h>$C*{q~liL%szmhlF?ftuN z#)d7&!+DEFvje4mfRE#-2#BwFj0zO*B_Jsfo2ggXx|?z(j_Si9{lXI*w^e20$Lc>T1l zVlOcKT|)MLhTcM01$%;06M$DTAfj~xBcHMY<4B9e3r^|pxK^xJv2L{Pj2gY+EKPzK z4X0`eCt>1VQU4JKMOuj@pDW+D6wT4Y4-StNY^HMlB_N{pm}9y@klWiLd^7~6Rg9^w zQncb3G&C+;QbUjm5Wg6YsM4hph_w{%&UtutVPdV7_~|{2G9km>`vlah)Vf9)2hPK@hCE&e~vi z@ErI;Qsgr;Tv>w2C+U7rZ)8;urdG^HTX7`!>nxLLKc^ZgLjF+u+L$~RKilK~SIS6p zNMaqu(h=<(%FM#MgJ9&uex)(K-@nf>;(@D?`8tUJd}yv%*P@b9MT!5gHxNILf-M3c zz!qhq-bd&P#6M(h@VGEnzJD)qeD%Ccq7WUXWGb(W0jJoJaML;$B1ftS7p^5tsjzW+ z4`p-$hs0?<18{MZRI2iXQFspCI_W5?>fIEf9sx;7vnZ#F6)bMz01 z6(DTHjAGQo(!txXym$xNlXEDGE}KT)-FwG%mmIkJmiO;C^ODa$)Nj`PANlw!K#ySN zX(r5pvB1Ez4=>h$Lk!?v27i;8Z#wo3uNhD79s=tlfBJ@FJNd*ToG+i)Zgx&?H(Of) zdPLT2U}|ax4}auiVVy;z(X675ew2NT8QklG`vY)c)8=NqLwC@_-HUs%+*?I6Z`j^w z@S$A?cK@mM?)EpGanU{ecJDs-E?du@jzLQ`efm`@<1pdxB)UVxhD;I^A@ zz>4kfrzb7^+K!K2^>^Rx>0R(!FMgD{_RwDr_pCl=f^yZ?IT(z^vX5-rA+5nxYA{s5tf1|c!^M-d$x-{kZuhPmoe6 zB2b%ZgNzgVs6+^qe=~4`0*2tUD|wf(T%$DZ4- zbG@}gU%30W>&|5GKkq#A;)kT<{m{oQY5{yS19M=sJ!1oajSOyaDE@m4tTOW#w*AVh z_m8)>hu-@1J6}w@mYWNkrZ;T_`RC0|%)N@4pE^A;O_nVtrf1Nan83o^Mi`xiE`Jtc zAXoID>$7{Xd+Z5>_oC8a9E;ch)`m0zObg|T3hSu6!=T>$v?)}ta zZ~3?1e8$BGzGu<5>I`o=^wq5f&N~ddEAa4G+`kKJ%ljR)Dtp7#PeakauCDCM4&HssUynxJ-i|Xa zT^Zl0<27DC+3Ujd-*__V=|2E99}g~Pf{b$>py`n1>@}D}ah)c;r~q$~3q?v~*BmDG zhx^h)W8g5ZlSuVL5)`F|WCX*-A~bdiQd7I8FsPINIWe&mbe1LCtkybkt>m1UlBO8) z=RQ3a2r`|P=P5tOSr2U#RF*+SJHlak^-3E#+qy8ZC&1)6oVDq9cFu#H3&i~xg)PTBS+g1-)!>z!o+=P`xF%kP zgFZd~P_vXF4S*_8p|jz4R`GG9kpM8tqJ%9=Df|I#O!)sb^#)0E$4aBb7?W(#p%GA} zj4Y;t=fUZh&3S`-5-b^1x?yoONk$eAnM|Jx~^ammN`8wJzO{ zv}Ts+H>%vyD2Iyv7n7MFr^%!jP(~mNBu}(Dtg)AflIW4Q7UW!@iAtzTx;eB0CodGi zK z?B?h9`@Lg^#qhC%UT>RqcEi%-9uP6|EXT~uJTlT~c!JRy@wRo{o=hB29l#2kB9lld zjJ!pEG=Oss%Y#+)iy;bIt_=s>46Hu5J>`OO&+0QV zprf@&KK-b`UAKK3D|P_g$#1pCbuRdR#XkW2#s#1K&ijAkMQTm3!NcgMKJ!3lc% z#0T_r^TwZs*Ky}Lmkj}2b-{V3eqnNU(+6fZ9Q77g7LPSqbGzy;Ei50r3(fX4W;Yy# znT4a#Y)ync^u8{E1=2c2fD;Ip4tuwc=`p@4|0~~GcpsD{P+DlM(V3hBl)}X1Jj!CI z2mMvObl|R+XN}g&2GiR{bJN>iQxyHB&wcbMS1umh^%>o0jz)v-(%SO=#naEabgT{- zukrdxI->fO&oB@EmDGk8gR*xKm6L4m42?lO1?EYBHiZg5f}=%-PD;Z|u@#l3fvS&S z_pHTHC;5LZAs_+WNY0p1bw-tiHV(eXs0#3x&eq{MaP;9*Wj6=~y%Ll_HT{ogQV1v( z^`Vx0{>88LrK{rqw48sP14|>qSyvU@ExT(&njvE72`YpL23XnGXZ$v5w*F>jqOSc zTa>A@A@yYJ|zZFC8rVv=N5pL+!VVab(`Zc_;a*;kl830i*9HCVj?}X2mlg>Dn6U zzRL4+NKFYSlAY>;GP)f}L)B>o@#4Rv2 z2yhJUX}~hks`t2Q;We-N&Ui~Za@K2p|AU_c@VN`lKc%HfP0Tc>PiW+g=gzdJU%onA zJ9eryHF?+WJ1{7Qm~6B|1HdyjPR*k?3~K#OqlMgLSR3_Wl*XVOBGVZ>7~N4HBU_+5 z?CsBV_RnjB-rx3%L3wcH;HP(-^MiTob*B1_O%q?D1LezmzQ80mP zFPWa(a;!omjHmMAzBD!r-ip`OQ)YXwx@m9W5NT_ z0GJc`|M5pe@h=;rElc#4yC_FR0+x934tepwOL3Q^^>Jg3o_}jY-m_8)!`?t9?J7xP zVh1ltra%)&dV!}XQ=|F&AmQ=OiIgjC!P3d3G(mKwts?)# zjzE%g3J~&Eo}yWt^P!m`O$3u^zW|c;`@#%5@-+c&Ig*L6+yxxq-NGdr(vHk^;rXZPzz9_|*O~np08f~1Prj`5?lIHt$%l=K(f)?XW<2}OWTS&a-6ag| z2s71SVdM90wm^*dgtv{p?AXXfXRd*#IR!c#`0-gDa% zv)fzkDe}yCe61UEg!&W*vG`=T)DQgfA8MCw|-$bTs@d)Z7i+szPLYH`?_N8 zz4`3R#{1TIjn@OTE;#QM6N=^+pr(EU;I}cC4e**wwR3=SKy3un7I-IYs8~?ewv$BH zuT5^XF-fkT&b_W`E=F}g0s#sKz&n@hqCP^bMJ20hjI4MzuE2tTHWfe*l9UzCi_vxp zFqAe@G`b2jE%vDBjgLPgCS6qx0Gp=JQCSd&Z}p^v=wGkfYqimEMVMsgc@AY%vInzB z+)bWIlZ8|B0UW;H0m_7GiCTq#uMArz|ZLQDSg0BTV?MLs=A|K+jC@ z<{On>Gh5m)tp}h;2Y8`eld>oR8$gr^L;*So04C3pGZUxW-aqk~(x%ZUQ&%ShV zeCIzn4S;t6c*_F`9DJ~s_a3ga=&$x*M`aZ|B7g6kkp4yPu2iIiMvswCH&HC22i+cA z5pFipRTN*0(n}tm*sYVsf)cn%d`@v=M56rHJXNw;#^>TnCmprmbBZ@*gtw$TQ}KVr zzY7`VDiBbi(k7%N8pK-*5?`6l4e~~wfGRH9BCHGkBI{DFEJ=)s&UA_rnOc|ydyiXh z_$TbW^M>vXU-`_hoqpD(7eAEVPu+_z-UP-b0Brz@34H`if?`G&j60`)>9k_JosCz0 zz3;!hN-0*ybQ-Ovmd^g$M5FyU=iQd6*2K>jWs#NavZ>a@m%GEB?=)J^vDSXJnYW(3 zdwJgnGHv#(_E+~>=hV)#FTLe{D{|lZk}bG)|6ka}!7uo^{966!xeNK>lb^XSR)QmK zz31(xH1e#qecSdE-!VPE^>OW~`K=RE8=43Ad&Mk7KJSzc)TTctHThH`y`A9O%oYp} z_FX772dGIvZ3>NmRIFE1>w0mH2)Oee#9SrOM0!5b*uP52;>58I({vl`t;&S6V;D$@ zyxzGaOo)sC@4cu4NF?hr?HA~us##krz+U(oYi&&>AjNygz)Hn`l^Ix_qa#NpMk4|O z`jaBwSsNM{GWbeT_!=+EmL;^(FnNY@R3s^Wh~o?UDJB1Yb)86J{z5~+!Q>4|+ltfk zP=F_|yqu$r6#2DUEP(=zF`%Zl zi4k`*drEYkEpHe1S30p`#shzSIt_*WHQB0|@l6U(uJ z8|?y77wr2N`tpwdvg6E4yW_k60d4>=^CJL!3xGb7E^3^zkNQIlR(l~*BX+CgjnCru zu~OhFty66duHA6r!yk4BD2Jmeszh!arM1L^Ac0eef=VEHag2r+qA6mgtBRz4k<$1o zlap#URotZ4!(EWzfSlqv)VhwTlCCU!M&4>vc7(Wrt3Y2h%?3M0Vir@gn_=>%WHaA~Mu7L=q6mtBm=qw>f0p=HL>3HJ7BJ>o2Dezm zq8Al4N_aXn`*2A1WdU1`;G9LjzlH;QZ)H;YP_MgKC}ZsE+QF+6E_rRRPTMyC`3B2ZA zIIqRYH)Q%goelA_;dc&ne{UV~W+TL#_xdRbAr2gglti5ezM07kOqQi& z0c~_rNT3EEbiyEu*Ij89RLI^1ivdEz!AP^gS)1$z+GyCage@%cMh;u-0(c4DuHEVV z%JX-g@wYdRcYz1K0q|D`k75J;T;=x z{%thcQxnKq4LDoi`Y(M7d+xm96T5Ey%75K?_NCt#-`?XjUgPypS|5GqTQ-jdYYUSz zTOPLY=tu4(qG!x+JZ@^xUm@=uwrzg`W*3e|-ss%d53G>-P?iA}7}WsYCmObNi4TJX z^7_A53J};U6s>!V)GYQ6T-x+Fo;`+xE>@QIqSsr2wIeWt4;{GkZtF*1E^Pn*9Sqkn zDwe&op3?vC%-UVO1 zm;OmeGoYj@E=Qx(IPp%D%FcyEp;|n*ElZ3BVofFjiG?G6A5rx6GfbAH5WhF)}Cu!xlLm|KTL4m=SB>7q5kRF7PnI0KV=`IuY5#_GU@)}K(3zY? zt1}(sr{1BrwnXjD^tPqNJzKRgPxjua{$S;*%m2^AKf1Vh>%X|tc6S`%tcdX%uODPx zc>b%82hE%THSr9hRvQ>Wo6R7-0ZM0~kd?DqJdat4h$ZhUm5&wZ8&r~ddsnGM1C%dj z16EOQ?4&>x@LPlh5?6Bh7)j?NG)~UJsc;qVe=G!9&WcPv*at+CzD`9@BiIwO{Osr( zCqO|4UzNgDDFs%c;0+)-q~?eBA*mpqcPT=yb;zstQjA8%07;?iB+)9Wbv?T@fD2aF zP>^dKnOZ?H70CE5H821cuYYCtHF2Mop(AMz_{z2sJ^C^3Pmuy(LW9SLYZ7Vvrjb`s zicuA;G!%t8p#JCHyVT?ez2Bfph_yvX{sOd|*Iil408atKbuvC>{J0Lb(`%JiLc6?HYqj#y;t>LXt8(;i;Aly_z;;+OL1+aCs zE+vxmK0HqWvv37W(L&)&4TqRWAe*g~E@$X$%H!+MU$BG;6H|$};(Hi4~Z{*D8@$@lahUy5vBPT5}*4{3?8= z5Xpou4|Hj+c{YhO6f#WDZbqv!jj7o!H0-Tx>krldsMpRd9P`q-nWJxBJaorrKl$2VBcfoj#*LPnRocEedpozzmo_Q_U<=(GBXA4l-Mku9`HyVi=AM@Pv zMg#05-H8Ya)l{5)^!AHl6A)5=7!tY281Vvyjx_f;i56y5f{St(Cc!gICMr@ni$X}p z+Eg}DtRg?Q`aTiGV0k?RQoq+9Wo3U@WfRVb+X}#{nm$~HJ(LdBO}EY#(j?& zX*|Z2SDs~9MyR0O&N*1?U@{#n2`&J+qnF8F$K=k-$S=d;0<)cXult^k8 zx+bix?WRcGR7y7!!^5RcMuhS)17yXkBvPV!j7n4%n}2cW<=QsAqq?FC4&{}KRC z1Mmzf`14u=pasBF&*{PH>Oa2kxX1n8n{L1UhVd00ukrff){ZkSUIDQ3o^xOEk+r2g zmzZYf=&i?`a8hS_{;kERKfAiL_jmxRGqnL*jy(Yr(;Hy2#=Sq7QlLBsvMe+KiXub+ z5`h(g9D&JIxmMnbl}zHVqGwkoR&km`T8B6;=+s$A8xs4ki{zT{9>z9`9?)}4ue*Rzg@4NZTL4S4kjx#SBb5O=>ylU&+=bYM9 zX5rUCt+x>&530*!q0ELfh#`S_M!23UZIvf)gRRs`K_7r~0;o%ccPPd@6UaINv#C_r zDHUS;l9xY7T*KK;(yNH6q5_KbAPlC86meIlXxIO{DvqP|6=}L0_nD}ET^G$4|4gE+ z*R5K*7L*FHdD6&?sRsdC$m?SBLh~Vj5DgK$3Wc~aHT$a~z%p!60LX%BAY2S#FHnLD zu2V2*1(Fmm2xoygzz3`3FB0_?q^7Xacu=C)^(kpgQQ&krXF~*do`b<~-ov>vf&Oak z6nReJKfS0LbY`Gs02mt?>3tzA7?bBfOfORkIyQkKhsH&11$!I-F}+PLkS>>tBopj zy(pDZ(d(bQLZBeGinRWc)AZdt2gR!L$#5mlC#B%6U2hMN1DAImATRzMRY{tp$Y+T# zVXsm*GiJC(Pgk-nh);-7vmi(#*LdlG3b9lvouDBcfghy6(kXG0<;@i){_6PFzJJ%>ZhwMd@Z$)03Ii_&@FW07|9}s(G1VC$IQWw_ z=(zWv__I%cn_dH^1lYFTdTW#%HJIH!mE2!ZXfY+<)gu zMAW$R+h5+$Xmv0>w-t@nB-#_R$nqwXHuwDe%JWdT7X`R1K~P{_n}GR{!5kxK)3*v6 zCLP+Nzf)@|4yx07T_%iLEEgx~FCot|Faz5k{S>UN9MFpg?>ee1N0^-6xSd$du66fc z{J}qY{nuar`yc%G@w;HW#!Eh9&BS)1{6CP=b3v^+2W2)&Vn`*MS8~r~9mXtAkm=i0l+Q<`V6BB=hRRF;D6)sMUhEUWcHo?Y_c^?`P^!$pt})&X z9>4~Gc>m22dsUNUC2Vq8GXu~D zl@_cO7&^gBm~Fbz;(i;unhH9AOI(oScm;6j6HtRx80(VOiC$Wl**NE*nBYLrMgr+$ z=QZZ4N@upwZlc*~q0wm}Yh)GmR4b7Uh0RK5I*>zsy_?7Bze!Ods>a5sG8#r?PQ8@_ z@XnU2OZ(pG8DnYa{agGW4d8ze@KTxR|LFZO023<5nkyci4T=}O@66YK{7vV5a7_Fj zukpG+ngM5BUI5s8!8xbxyP^2ZZ`#2i8*F~q&yb=MHXik;(?|X8WTQ1PGa7ak0Bqd$ zNKDUfL*DG9LtWUIHK^GHvJ6~|KrT$`gU8i@9f2a5TMlX*W&e>809s#IC?%shPU!&@ z57z9Fk_Y48h!W1|46}3FFtcGBx+{mUc;K$Akxjg8V$+6`m(0|mD=$3b%we&7UBA2f zwO{@H4~(IK<8{QY_x`tEnIygNR-)|bAO)4pL7UBBs6=58jXX+_J4)a^v2JPu)&Q4f z^1bU=D8}f$$b}N6YCNk&<_LSA6s?R1y>n@As1gC>%;*6SCqKPP@H!9WRf?=mNhcfz zSRj=elS%e2O^1XiIqYm1ED6=uE27|akC3@!XYk4U9|v~6&aJA&YCGov#6*Ay@AJ?I zwp9|ZJiy`lGQ*-wQ+(%aip_JSL~x63H>M!OBm>mA1tGTE!j%?TvjGzCJrP4^S`@>O zxI!f$LXEuHkO;kK-3qU}GY%+iP(N@j9YMa%2veZ`e7y@z4U^{p%2c?=e=7>M2!aw8 z0cvV7!1>B@taMO=vGp|uf-o9Ty?3-R0Eg#6^7!nd#YDIe%8VNT4{!tErAPEtB_!Ag z1lX4~au6vD*1EN>qr9oL4&;0376Q7GDy@^*i~NPfD^!$$Od307&L@9Pv;eR~5(XuK z2Ro`FMugg*NX~>5N5Uzql@f3xb_l^9f&D^Ne4wJVNd>?QkhPnbUYJE|dP1^BRic^( z#ZnbLlJZyMWfPigik_(@9E6R`fm8`+G}t?=9J(7T2k&-^`|r5^*U!3aeE9nj*N3*B zNCZ3*pdA2q23tkFh5w`8A_Pr@wlb<~-FwPQzSjTPV@~@2U;V8wjR9ZdHD34A+Ih~! z3}6ocTyWkgyNL1GV%Yz8Ys&-kn~(dCS>Ae1mN&QT+jXNkwD&eNT9asXrmTt03pj@J>jF8HID zX;Ra_XUycUFi0~iXtNR8WHLYrM15mS@@7Y=HIotKwP&6 zPy+SGg0LRB7nKD*+FNV6^~z{K24lXoL6u4*yeR@SrC97b7^gSIf3^YGS+0yaQa zwb3b#yUxf;94}GSQUvFTygpbH0Nv2y(XR??A_#S#Kujsh(PSopxk)J~CV03isl~aF zR6qom)WU_F|LchiRm?XTLMG9MDOS8@MJ7^W_o&&8wIq%y0G?9aqQr9H5x&o}TQ?L` zlD^=a4Na8H1pb+Ksfpp;5QH*(Ho0Oie0gZRE8P3i_xA%ba}MB-0c;vyUZi4|85j+Q zD2q}$qK73g5~mw10!QK|8aIPPK$UJDi&7vK|FM&oI)pVDee?)<>)^}E5)g}gQdDbP z#5_-d?Kvlmf(SPe`+^P|4iQ01ZfCR(WX%SqHqN3wJpm(R+0b>2KZ|PnHNzHGXru&J zI-!h8IzsHm${{drZZVm_x<2l@<*QJ}?7rj1Yd`#p&w141l~><527ml;g@1PH?54*9 zIFo??3DENnhbsOk*`Wl~NW6d{1@_z+j*3$OZ2PtCkGbk&d+sR5uf%wb*ZsS$y!u95 zarKSm$FBUBn_u+v$K1WR@3zl5Z$CF0tX|jZ%&5_@KRX(%HkJT^A6>xkG#}y@>K>V;&6f6U%V6fFeu+kChEJw3BfzISS ziedm*OuN$lOlNxTC6gPr;`t|SUVhm#k6*m}>Kn&zfblva)+&V)_AXjq<9RVE zOqE3X`6vai`T3LWD8*6NY_7HBDb)P^VPda>x>jWRRI@Dvn{6m4IkK)~sKw4F3oX~u z2#6>(HGD0%zPd)Ch}Y2~8=EWw0%y;#qq5pJl_(B~(?q+1d&_?6xrz!Tg!C>{U_g@_ zXp=!3ladr-lT~RAFLnhYg2^*vc>^ZTpk#`l?7$4M7x;=9;2GB11PPA}i1=D3HGvLI z3~!x)%x&Nkuy7IL0I~)+j7bsfg=HWtfTZpacw$r^#Mdvf4^lI$ZgW-&>@C16P|Cr( z{wLuVKXk>_-x@PwzRP+1{%!y~9>A9c{54(?)=^pvy91P?QFwzZ3ZzwAWr)TOS%}TB z>%B~IW2?!p*fU&NCQx6L$yePnB_1eOWw|;h(I;_gUn8j2j#o^$?5!T8;G-_{2ocA_TWnE>7e!lUB$aL)~* z^850APy-xp`@84khDO(t9l$_=TjmdN@=<@IW}63go_XoGi8Ef~^G}S z-M1|-?taICUElsP2zz#(b?M^xRUfa1?*07orqT;9&}Q!ADxYrT&4-~JK?=nz`Tk?^ z%r#J__a1NzGL@X(dtTQdh!gHq(8(k}7RiYdrIeft1GPQG(bZC$gdK&H`;O#Iub_GY z1r#Mv{fz5k6r4okrRJgcDef~npBDy61@%M9t&iWRj7gRU?;Px? zfO8He&yxZo+La)~HDwIEwXoJfONy2)ZLs%h1tVVkAlHwOK}K2F@G#Oeh_VVLiil{1 zb=E^?8d;vzz}%H;A|`cZSq>#bGm~X0vX2D79XSoIEW>jYm4dSlwk(qOKc2he_XahD zO57Lcf(;?QuCX?VstS@cf*6UeveXggJ8gUfdi7Ncn!`$8x!8sN{RZ} z%J1&riroM&f_?Y3xm*0$>(Bi7xB+l4>wZ@NoO8}OPX+M0@ujVb|40rA-LfE8AyU;w zS2IDzDSrI(Kvj(gs{kU2@p(!G-w)C>U!qKERhN$ufS}5oRZ}HErt9o#F)C42V5&1Dudl3`V`k$VCT6E$@(MI^Z^b{DVM~iqf0TZ;+T_#oTTjUH*7j$eICb+CSAXlk_+9vYi~kJ({)~YC4#JjuE7R|- zZ%FBXsQtVC58dOd4u916o@goq&%l9E_nEEE>a+hCqefQ&^x^~aAo-lRQ>Y=@#?yVlU$z+Yju)Dm$d#Co^dA%-2ePme^rqK%f zu~MQ2&{Y&*1c9Z`8Cuu;qxhjCe%lmTEB-UV(5A+3`Z}2$a-4kCK!gbxNCc$}W*3e| zt22##yKXj_X)m-pGcQ><>i9QKZ`d~R3n#R`c;(eMjul4Z^^jZdJm4 zvxyDbOv2>z)p;pRu6_EDj_|n=4H4{{2>7=MA z6~JB`>Lev(;U|h?h=D6+AW+E-Ie+_G%?ayQIxTp1`*QtrvaxlCgS;DOH(JtkjK|G+KZJUXjQVYx7{Zn|eaHlmiCedUCl8o(HguN3G=k(QZ#IxMGUUw;rsg)GGdYh@e=TG1 z2}J5~&-vN;J74nbN8b6#Yi=5QLDv=ikDokscGJ^No!xvsfd38P7YNAf7yjNG0N?A+ z4sQY6%U7nqrmBmKK=d`i8>sj1+OsiRv-7X|)u;dSW!GG{I)1grYrGzqb>-DJ^5vhq zuJ`dzUi;Obf0X%*G1*l_>RZ$ETm8!7o~g1Jbo$*TtS;?E)@UJXw8DW@Ymhbxz7=d< zH859f0!F)lst$FP))$EyO-c&?xR3Zs#tKr^XM^x*pj7w?CLI1V)5P@bRy3LuC`YAk zG&{Lx`#7!4hL=A3(QB7{=Bsy(U+wXFD6P|;d%~p77Ty7<6P0NqZ!LgSD-EB*WHrLx zxK`+@Dvcv~>?xfMop53AJDHgP`z)v6jzEZV%hQrJ#k?-%pbjuh%}HTr5vgi8#+AJw$<|%d@A0P9ijHxglN2K7-ox7EU*U5PVBg$31RXqNdIF)rp8!_ zX$xUmUb9jK$wA_3MUDeW#GlEsq!#hs%ivKbb%!$5b!L|L4pl=xL={3!6%wwu7Uo0X z5=8%hRF(iWTe371w9yqW!3B0gQWwi(hu_R|SC%#NAQ~gx9 zGn6y}xF*L;n-K%Vvf(4d7jo@z74tk3l-W6WS4F*q?=x`D!w9|GPBRaF=U5(iVaIxtwkBUGs!Y8~cyr8`seIQo%K#>(Puee5GoI;p$7 z|7X^g_kRt*IA#vO2OjqLjDXhw_(K541IX^Jtf%|m9aO_U(7F}@B_4prhP(q;czy8Z z-M_eLrhWI{y#1HY`_;2Px^Mi-jn{ZRu?a8 z9K5MjlOPu0HIpGHzq_i6d5*QNlH#0Fj9rwE*W>1*^2j?6g{nznGF{2+RZu$wKt5OL z1X`zS8?T>ILAoEQ{X{w_E({5X+rgC%wzSA($X65&wk#7|kktB=gZiKA%mjOZ_bF|` z7Gflw9&vScfWX=Ez#9$ehB<%~}?8$|pf zihw`o!|$$iuxk({bwpH|gl3Kc86?$mY}&Aj*CRG|RBGUOXW`vyY&`5@?tU169q$hJ zzV25A05cPS3jnl^=-U4!z_aS$>qr2kB2W;g3Z# z*JJx)r&54Qb!n3lOF-Iaxe|BB4ruxih;n?Y6>YMyj$6yxb|22-KEcZXRm9tCZ+%!vw!zZ35b<9J5YHe6bw<)FNa@>Q#MJ)Ne4So z4OASOC>PZ!1t9oMm7ISm9qbbyr^*hjMSO`ZfD~Ho8O&}t8ek?So^rN)(Wavw^-Ry) zfBus+C7hBDJH0O@Cu&d_Kd2W=)mDoESwFlW?#@Ei)jFy;1% zLzTeN;<1l%^av8H9TpQTj)+3hS-baw1U@i263nyKz*Abm7$fj!yUr4j?sMl;b3xVY zq?IKB>(1KuW;b0oeO`C2R@E7rD!F@@aMQZUv(B<~hEduiOM`bVoW;TGSX$otwC6<| zt*V0rV*xEd!#HeHTEkllSC&CZps9ibN(7>_77$K>l4eCv5h#FEVl%|w(PRchDm*4A zMD+t-uA(M5rBfTYhQfxAHM54a`YDa{PC_(nZ<9V({nxswEuS33(3PjPo)j-zBp|plEVZ(?UKx8}FQGvl)4})$W zqy7LUGjPtK92P0&#M!Wky28qbNz9F|*&iZMM0W5`1mKUz3bUOJNu=gzxL&RcWI^7nVCDZ z@3z_HL%Y@L;vNk9YtY)D(U}Sp{&+}_g@H7qBc!Uz?E+ZTUx+~4cu3}Ik76J-jbrhF z1n;VW29pFYd=6%L3)8dP01z6D2@RrSv#j}?tl9d;bDuna@QSN%97m9j*H7ho`SYK$ zNt?;HDcw4bC`Z=V2JgZ&Jjlphjl@q$x{m~Wt_suo&_`(ntxYQYLNlO>wu_(iv8a#! z{#bNJf_p5a<$#&akch)4X+S8k2Sxr>iWSrJ9cDIx|qlBxp9(rsRmK3$6fy3{L3=@wG^nt@?yLLLr?4L=9|5g@7dU z)Z_`zrnkZUTR7^8i z0(ced`itJJopHtIzH;+;cX;3$0Ivk_lJR9-U;WoJ?^&|#huwaVztpB8k>>B^A6M8U z<#)~}LMTCC7&;uDST^GnkrHp@7}HcM(&}-3Q7I7NCXkyfL=W=1M1gbwiysU|BWvbq z!;Mp&;L+jgCaxs_Xd!+M*ZSx#t)du=LidsxY{RBdjtY1y76*9>@dHE&{6&$1GNBtu zVkd}^C+oVtT4Vq2n{}f-z3|jWXa9QT5eNkQz{4KD5x`#nI3wC~4sQU^VU;``_7(Kq z3Vp&o;w)*Mz`q6yBw8o@Cjbgn$37PS;qMfTQfTWOgL0$>`&LfkQCXh$#*;pO#Z@!4kFJNZjXpx+voi`?) zJHKiB3!Zn<=C8fzsYe~U@|v5*e$nyzsamJL@EN~t8XI0mD$^!kfHIS*u@;+TEN8p` zXVaWCs4dbHXDFV0y(2uI=xIE7Y0*_F~ zcs+Gys=7k1j@CNuf3evBLb8UW28pVa!m(KsR0ToNpoBF5k^M(We{2ZF1_P3^BB%_A zLIa0A!2XjL(_yr5XM#GIz-|fb`vBWzaR09^|J>Kc z_R;UL?r#RbbH|tT@FGbz#u~x67>ok=j#MpngoCdtN_UcENII6z!E>$SiOOQ2v<79; z9h7clg#9HdvmCslyr}LYVpKAmimoc)zN~ zg;Hz)%q4o>A>7M^yxD+va;PID)k50nIZ&j72dIiXv_%Q;J(@t+oMbgylh}OBV=?Hi zJeq)oBe3}20N^43&$yR2=J)*1@AK7%y~XMKe*HZg3Dv=YYAuIk1pv@i8IEhs;m+am zI*>&Ohr@nv38J85}jb*&X>%m_;&bY(^xaNKT{ngjHvK)3-4!m%BZp+Sz z>4oPHd#e+R`|qGuXByLUTQR%gD6n&IqfzaETBYBFArz&(At}%hNZs*sk(~>GT&+Q= z*&V8nG?P>WAJuafDK?8dp&X8&tijy;abW9F40~HhH@0j$?q@GPwEsKrefQa?{MlR1 zy>z_C+=q3+xu@hi&%U&{@VwJ9=UHn)8w!>^3K@pF7B|a2jkXZcn)kMQ`dOEa8!Y$Z zy70VHCzP4mPLyYWfzB3Ev5&f>9ZJajp`g|#lVK53lMG3z8izI-StC#MbpSw#R78dX znBcgA)rH7CpDa4sX!$x(lEy(-is(}*-kO<{B0t!q#^?_r3g_P}+j z03WCH2HuzJz=29@uu@fIxUGK2#N%SFov+lo#Dn-=s3H{u?-8~}1j@)e~z@%Ofc4N`t%Kujn{7S09Ve>p5*8d*{(WR!)?P$>W&y0(#d z>*2@(l!Z9N!lGZUp)t`$qum66Fnv-Qz14#=ovDSV|6lgrG|H~4JQIHQaL&17-MTfZ zG?ZprvMmo7LyTuL#@GhgBq4-^(INTL>7=u|d*w?vM%X~0J7JM8-75i`A!H5>#*#@V z1h7NE1OqYPdBT>gS*23Vx9&Y>@BRJQ``vrrl59Lk203@Hkj9hv(NiJ?=t|n zte*hi<0VxDlm;3QV>qu?k zfrB?xYsrzDZoKxE>)!kMUX)jF_0~_xdgt%{Z3_TC{h@3B>Bxbd-xwHMd;aj)hPNt} zUuLvkIW@7H0oHt~S{neAUIGcKF860+0JwtCnr3Os9Hv;Rq5#>L5jE7O4$zQH2+I##`w*&)!Sz|C{vTyp{@!1GZ0OFn{PswXMkerRU;pxpTXR#Fm8y*&8m;>Be4&-3rDl=0 z4>UM7*ZK!{9yz%4j{)4%yJC)GX({@)8f|{A$Y&vvA?u%H6tvOcj6)=Ls!MUu@X1Qn zO&+chF7h0@P;N@hA!HJw@qDCp(2IMDe&kVAFC_3z)yC)wgo5xA}SLJnWae5)bG|ZO?+N76ZWPir1YjVEXs+l zHtI-9DF9&K&igQV;0YW)xbucbe(;qKzWcww_$ND`UAyHX0DlKy*;8Ne&y4~uGwV6waJ&*qYhxR{;BrVU(%^dpD zp}i0NfAdoZ?t1sOe_s>pPi}jo)IzL~X}R4TSpV~RJ3p^fZq(AOeo<@T2ukI8bzyF* zNV9Az&8mZ17p1gZF-elKg}EcFRIMXT%UGD7G@LV5t~Ft_!eVO*d1vkihYvjd?)mA7 zyWf5N7kcRn$6?)kuj&ZBuyQg z(ge!5laMk7c$)Y_T%DdpYtjT<)EV`rSthy^q_u^nhK?+g_gBhx+= zP40zf5oqVZV6?W!lYoPGBJN^TJtNn%p=|w5lz%R`OV7$}-75uTlAy>7v=fUf4B9c== z-8Q!7jNjh-_z&+bRT}5--+BM0y^r6Mjg4jQi zf`dC9DuAF}Eebfa+TI5l^G%4+P72Y!w-US9=d{l+jbRu69epqMs&nsoZM4!1Jigk-0hd<86RpC;{^1wb-pO~CnL z`6R9=f>A7CUNG(?yd;qn_V{zbVcO19fLn0Fs)=(zSr(K`Q=0<7IT-AaP!R7t%GKPKH23N^Xxo znTcBjhlTT&JYKYcRym5+!!Y_V3>Kjw!5IEh>%|ZBn*SFb02u2X&SNan{=2^|rQNvALQHx2T(Lz(=pU{uXo7jn{4%U3tp;OO?jzO09YR%#j1U-I~Mb%1vlCSJ>iP zx=EcqZ1M4D@P6C%;WW^~+4wW%K{e9H? zM^|%x_M1QRk?QuMvoP`Q_kQ6;8%0`gtX*3w4_uQks^2bG2UcjU&=?qBqw)^=`p2O1 z4z$)79$N=6g{)LVl9V8l1WB3&=krAPsV?VMPi)P5HI!=O@cze{(HIv=xzYmwj>FPw z1R{Gsn1(S0jA{GntYnvYl+GV0X znexQ!)ZypM(bWwz-VcCrH>7eJZtk?<9@O)u*TMfI%KYtcr>71Z4A$B9k&#KZQHi}X8`B+4(U^ONl|EDh_Z+` zFh^szd8G(is3qnmp3dcvOPMAS;;9`~NTJ9JKPlIRau*jof=F>5MjNl?hc3&KJj!$oXT!&_Z&)3wahn}AAS4O!lTFtom23SNT(%Z4rlOR(xUaeV zRkixi$VF%O-+9~Z54@;o>mR@24eU*?effn#^!?XLZS*&^Rs&h7hQX0F7+bXogQIKE z*S`#v>HvmDSEE#^qg-u3iWEXvcX;MU1}-O_k@lK}9B;-kvF|a=P94O+@ahs5?BJzm zHSgVV#{<26`+2OZFF(DHvFgh?&(7eo4w;U^K*B)VrknHNh99#g9TnSXbPagCwmS0D z;I26ik{c5;*%ADE5G7BAdJSE=ba+Vu^9)xm1O%lxvA_}lgE#-|s`sMUx>(NYSqre< zSDXvWnnf@pG$HHHM+pY+Ejot@z+!%z$QRpQ+G^jIHK&t_9q6e}?&}%hBoowBGZv0v zEbk30Tw=6p*FXouzasBgx_egyqIKK12L~uzW1nW3?JXSeAQA~7?E6r;V-X9gyLI>b za}p3MA?DCVqi~Vj+VuxkQl-Q98Z$bhNk4OdM*K5l3{)qFDzvBYbIx6ofbL2J@bzL8 zV{VTPu}yO5VlPx@544&BLjlH8FrMa2B;R`1fB(z7dppAm4*-0;Cjoeh#>;DuC>oDL z$bkBJsuZDJ#8Imk@2x!=d$&g7at9^p|JVf!g{|+x@K)k6@JRwCvF$9g4&sjwj z^%NiDC`8Up9keod^099tD_1eG=aFwLwq`%KA4ZNx!p; zBrCR^;fBycvdwW;Jb6;0owyDi! z^L)nBpAn)0nT>{23|AwD!BL=}lfMR4i^4T+LRuqe=FB#ko8W4yCEa&V&7#r9*PqO~ zqG@7H|K`1XAn$v7PAfOBrI7dqyGyELpQK9E2c7KUqn z^6kJ43qaTkh(Hsn!AajAJRAgs44@5xZls&H&i$78%l%`xXX291KaLV7cR%eC0lb-{ z(%yq09#Dde%3TC&(J4^0JKkr&9wT>N3GU=4?(?{qNWV9C`8QZu1;scTJqx2|Ve~Yt z&cT61qIN)c4&Au@_WKX_c7_)a05Hb%0r+6=a6U62z|&)d@Cc%brt=^JBe%KQ&6r1e zeVaK-NUd$+b3Xy;&R>l+))q-qg>qVd6X^dg!!wQwp`wa&Znb0_5Q&785;9F)><7Fn zzt$S6lRG(q?s`7s00BlcA04?d(|cQTthl59>q3D`t9Rn$OJJfK3=72@8P6E4u(&vb z1H13X+|+?5CiXx6ws-xvzkAV9gIx3fYXJVokGr0qD*&+c=W*Wd(noZ$23Ys2bv5+t z=;!j2e#Vyo2jQ{sasY|CC}DPCzTBFa+AI?B-K&1?tX;R={*dYIG`-bZCkq(x;KF6+ z4uA9TzDK_#lk~}==v%`;t38_kX`Lf3hF@t*<`sOwJph)C!wd ztT_W~HoOdtf#pbW`42gIUDAvFhn((km~U3HGrCsTwkO`?mUjk)Ow$RzETNoFoO zv+<8RZtnrN&vm`wvNQUH9QjQ^trfBkp7i_Xzl$*%Ff{9_LD}>)U5|{Exo{Di%uZ-6 zYg2m$0A;_cqUe(Gk(`v8II7d)0atXA1jAoy=H0LhoOQ?g=@63*SMPNVfZX3X)x$=6 zvpTjUVvi>Kh_v*|O})tv0GcN3@bX$~YAD_3zydPc)5^XF3o-3m{K1N`g{Ta zw=t3SwXHN+Na?5cMjH>>cvgU;Qh5MJJCi}8@H=*cb_o>JzmPuxu~TBu%FBY?@wR)o zbfs?D(*MzRe-{s%V(R7{cRaMv+ZmqO;>YQE-r75q&mIim&dolnWY*>0(HVslZbRU< z*(W4j3TJL7o!h6|M0h~#e50hTX&&jetb1tTBLV$H#37NPk+)8;MaOD(9GDMHMUfB? zsq_p6zwtUFL(*Omvw<$&B6n0D*VIw-?;W3&?xJ*g%8}bV7Uvf|jfsE@L&h|Y!bzyD zDhf>Oe-uwX_Fd;Wuy}V-v?pJrr_$vBKJ?5b{?FD4fIZ{Kbu$7Yz+mYl|Cs-UoAR;# z{aA0KE;FnyH&I@|NO9lcKjd@zoIicv8oG90 z5|zFNWFnyy4F$9xQg9(4gbXHVt}&qrDm4YXYpRKEXIB_hYXjh%Bk#0@F?xhC)7!6~ z&l2^s0CqMLB`{I(I{BC-sg#Xz)7mz2#v3nd=LryicLOT{RZhzuDE*<~qX{`(BiiZI zDH)1%=Q2qmIy<)p)nqIP_+gG#_I+5ZkKpw|?130KAR7SEg8PA*n<#MD1cCTDi1}k8 zX{$9ofM*&irMzh%69P#o_3xK_0f?fnwMLP5f~=Ng48ooJE-sK*5=9}>2@7MaYI3@>A z!FU5qjDgD)-~bRo@4jLL;0*w5l&2%-+_deDS#M)_X6t#I02*Ub0PpG@%I5xokp(TvLDZ zCLNd4^?-9oiWzZi0$tb}3N`0~XjcC9dALE4ORHAiRE45Q{6_AaWj*anYZ&*r+Y5_6 z1%NZ*QEpWf*5OqMXl^&W$wN<|)1Ctt5~Xrue_pg-bcREpUAyHh0DlRf@!U_q=l*#1 zluyEr`MgIxiaiB8;2FLx4u+a2L8P4RpPD^e-}?A%*wXyNn{If+$F95n)}FSsw|eU& zTJPERdHsnSul--`#o6uk{*m9$O0{(}GyBgjR3ZBNmt$aP9GnR|?bjMMAUukma%nQg z$BqTfuW`&ZyO;Re4{fG8KXLRkUFT>dQsi^i1IAb?k7Zgf4!!K*#=hM|p z$WphlZpKY);k^L5GGR<))5aM3n#)k{AI0M0G%EG_sinP*R|DAo69+_Y*jhEf8bCkJ zn5YU_TF<~UrCN6}#gyWDB?DT_umkV9{_{UI-?uUOBgV8QV6vvsi{5CDAa$a#!{yrh zivfm+0M5t3HH)N2N6`3dM>D7Yw~SB*&AJ;-8%3?G1k<_aCuxd;<(|%OB{}vEuiU`M z$NBM)Sm0{}iY|;31)RJ`Ywo=Qe9cMkn@qC_;GmdjZ>+~%LP%hcDw}5Eqv(vAkSe9@ zq%>lkddk1cyeDQ6BhzXpZ{4Bgp~y2uPn~CWL(tLVy|G<@*3{ zB<}Wt2n-ZLx^t{MK}6FTL9bzpwv5@&wVMS(3)BBjWjj-#x?O48KVu|*r*X>eeLsh2a9tp zkH7*9MZ1H%-SJvSfQ&%2H-JGLJyH;o$=#+Ryq?n2_!vW}RtA@n;teeAKern>XRIqx z0Em%d+o;p)5G62NtU`K1JZF?@E}POdrb0K%+DRf zkwcF|o6eI9b4Px2=R^Pc_3N(x;*l3g^S=hb{{^t=*Qh7fKR9YXAH-f@*fQV zcv_%;Btzt%8yN$JXW;bnCH8}!KKB%_%K$9u0u%W>_L$jr|9Pw5Up{BqUm2Jq@A$pH zo$2i^z13SM-}>`EeA`fSc>F_s&Cy>dl^cDkQ=r*gfuUs^kS1j)RlrcBtS=}P0B&`w z?s>f4Rs;uaZ@OhDQY;j&%mMPma3ix_#yRr5h54C-m^`?`gXfL@o_*fArsSHIK1b&_kD5d zCk9-6@a?NaI`TK1m0lrBtFpOZJ`1j#^R zFDB#Ss4Z)Nb7AW>A|sH znLAev)wryCV!;{r11Cx-Fs?SGNi*jhDlbrUa?5Ph27+^lG$bETgDwPzOw-_@WdhsC zvj^OJ@O7+f{uvnZP8&rYyt-s+Js6aW>{faH6b(2v)gpXf5tw2P0K*jB${Z}am;p8k z!1)qzXRhk~4LFBVg$Dr0D-4W7O71-zEV!Y)M}gM53q&x+AYbf+Xh|u$q{(DfZjYUE zeF?h2pRAk(pEPZdw-;@_FGWZ$1EAC-j5-9)IxVf{KJu>L`;+(g?w~(@J#P5HQ{d2fN}X6_x8O%$aP z8T=5P$m)XZCPMLsDpx+Xg%D!pm;!;kVgSex8vq^~IAF2+|55t?@Mr=6;NAZb%xRVa0PLv%ioh6fA;)Z zr}E~p^Uu5X=icx$_rBqkr&Zs4)hpEBed(^n-cHk7y>)V|TfY2*h09(t@J|fv?oNBY zRjK!n=Xs|xeRwabeZxr8ay03S5@8s?Wbh5(JQTrRYDV{)$oR?^y2fFoW$O>V@ztk`Tfch$3(5|->XNmb@y1)YXpCz$ z4TFZCpc-SFGeq7Q=2#|ufMa&rc7PcJ!{B9>9!!YpR3H0D^zP_7vby%57gt4ysnc4! z=;vTeNMM3@)rWW1@Bn&fxe1HZ}()ov2%Dsls z&iF5`dkA!JM%q-j=%R4X2T!MGjwwq~e^i4LL)L>FQ4|T)z4TdZvs-wu#@6g67=>$N zJ+gSv_7mHQu02Zm;x741YYiz9f2jTNkB(2&7sLkU^nH`zBbgP7MB3k_@0QXgU5XeT z3)&}W&(Pk?l>;skFaRmq%N2@F4z0+GLPJFU1{Q!U0ce49oiHxdl@|@&y8ZTt+P%Bz zi3b4Q1>hyULwOv&3@Pk}skGC?#9BJq6Nw$5k+(Z&&$mLo;f;24wnm;pdRe(}HY$N(@H13nu7;ArE)vPe;vB`|Fg zJ~7`wUv>HTD=s*{F}UJwjI-sJo;~orD=uE&y6ujKdYese_0~zScHI78@wYp^^~h__ zPj3^l*{IYTYYbFvV*le@$P{T>wv7vmviu^tu#R%c1F$T-mUpRHS)7_f-T?F%y3KMS zospKp-1OvmNm_rkHfqlm7p!=2`|S_@)Pl>O`S3f=Z1k`DK%=>G%i!>8B(mhDXN3oC zK|@nd<#hyMA6abg@63cD0(X&dTw1msmo|coM^k@dQUHJyDY)dAo!XCbwIQWU_guWC z{`DPqJb1zlTtD^uzj#Xj;QBupT6Wqt#**_nmszzoD91Ov6#auM&>UQWRqM_{b7&Qs zL#r?}x)uYYYf$eSL33~g`udmgqSJ0>%cg;9P)1X%rIZ)S*L&DnzYD6$$>kJ3nvpbzR@Bu%)|!P zRC|$u9}5k(kK1!T9Y#@Xo9W7#XWq3vOs^vi37vpP=?&=;7M_6s-w4ukYi+u_#0Yo8_LLZOV{Tg}4vU0hU;dr@voEm#d9wBKiF?{{-DvJLm zzXjo*4`41{kcWMXhp0x*xno4R@0xQDe#XbdI1@*D-}F9=*5NB~$5Ja5d;(kyVv=PL ziGV7I?Taq6M>;<&vmqF^lBWcLB+T~w9)L8?3xdVQl#IbB;MQTuFv^&hEBn3 zDS!|(J#aaNAqLSQwDfsongnE9FOdC4U;IQaTYPwm`xM=vp;w|eVjShxJsW9HIxns>GqX1?5B zoGSp6iXH|o!vMpY9C_=4sw(igH8ux`;7g@0;2;KEy6yZUSa? z!U_5YMv!DB(QeIG6Is0ojPHHj`OEKr{iU1qjyrz3B&dJ!2k+Tbt&V@Z(Hy^|TyCJ= zHxjJ>omdiwTKCRL7epe+)|;rqaG7ukl2HMV(WfaNQt?bL+C8dGsXp9 zn4jGKg@64136%kS=EJ|VxjC|CJ5ai~-WXyl)}D#su?^@OScY=BA4yt8rPhQ@Qb?Hr z#(wuwNTj72%9TEps|_@oV`wzTQ0p6lDmvU4tYa)$D@EyLsxTLnN|k+Azj90e6_>2u zv*T+g_B^=i^39sF(z%TBm)S2g1>+f@jc=xy2f}Qsls2L1<6dkYoG2w4ICmM zz{_S35+LXr;|}3xZn#6yo54gbFf}zrSI5sE*B^8qMS~qgpb}?6PfjcZoh$1PN=X3z zyrbWt#=bjsODpXF4wpa`)fP%A7eVI+a7uaidRxmXC$Y6jSt2^;!?ClM6mxO_FLQ`Y z!MS^1Nt!?i>89tx8!FP2o&j#^&x7>W7~6D%AxYEloK9EIC=$>$?bO(lK_o>UdTFiO z2MOe}b-H!{llweMd*3fgDj*h-j?xuKoKM3BD$fx9|L z39LN2ZBqe^${0^(ue@m4ojdM$u+zJHo*)2V+qP|Q0`ObC!+87_cV;EZQEx(g%2M~W zXlmimL~_^klMLt9s#M_{ZPF%rV?M@@2||Qe6xK!Kv(BT^Q*kW)-}neZx}YP+6zlFv z(|+yrXCBp!41;*cYz5;k2Nj|D*Tx&$2q7aHB2mMrAhG$UREQ)=1}=e_BL`S}alSos z9q9mkl)V@X`!u>b%T0RSEpI0gXlbo&3N z0ssI&xEtg`-p2IKy{IlQY!k>ttHGYGmap=l1oF3|w~Zzdx% zdDGPw)#}UtOLK4>ea&T1$_^QXGX)E=Y;-uNQ5Rv_8%=q+YZQn%AkzdQNxEqN+}94l zrJZQgl|~b-`6F1En?$AFKeRA6^_9Qf@vSFL)aU=y4O@9yshv}A4E=hVmE_2Z(_OMd z2|}iR!fR>I+8gEhDX$3=-y}^S(+r8s&}c5hz{nZ^23e^tIG1B-)^}xdX#90EQ+vMg z`pecG+3~f9PS~*F4VP~&F+O~ufw{n#4!Gd$A}6S(Au{LF)CS~*!keBP0vpqH>BVjQ@kSTtq!pcI|I#sVB9 zXCO^JrG=2uAPvd5kBzqPMLK^g?|tFpsf{0s5m-hVcJe;YD;#rx`#~Qg?*jTxly)YJp_-%kLJL5^_7(&x@xWZ6p`|L6SAE%i zo&#zUKmjnrplAMW`|S_3dUwtf000#qZ#?xE9b#koF{loW) zD=yhEKQpoK+gY_P)2zI4W_oW`rX^M?_W{gB($druESf60NvF&CHa@z_P!?5Gly`ds za2L-T3QGm)jZV1A< z?p-mxn_SPC8%i)|nC2r98AH8q2-W%k(zJ}$!gRX0Fw{!%I~tY`Z^e^dfLBbd`X~5`6^2vf;pG7`EU2%2rj``Y{s4j$;G{m)YJVn+jL==+yKDqv(5%vqm#*K6AnQvSzm?WhHII~)J=ec2xx&t`lqp@AI zCe{C{P)-gIYz=H|xb(v``})?z)cbJ|t=AaO1R=&QeJ^C%$b~@B$z8l5Jop6`Ji~&w z0uLS$F8UD0zHeeS(D$s3jg0gO3dXqTM;9yU<-a^gE}Z|DkoNrb=MoEm6R|P^kh5%QMr7z={02ydA+hG4;!U*b z)@KEOf*?%v)I?$;Br-ITJZcRI&6F;0H4!M+>XZ&k|3NfF&sa3`=YRpBVtK^mSV*$DZ~y7FCXt zNKg|Q+C`27cYX(zN)0P6x)@wY%ueo4%k_a%k~AB+=Cxq{xnzFk(7(O@()EXTeC@%X7|ZD94{R0H z>dODr99;X$S*e=t-~9j{d*BJuPAtiW{K&t|+`6ZjDm>sG%M$Y1#uejoZHFtgStM|+w_v_$m59q5eKX-`n%9UVAA7c`XS6vex zrq)Y1G98E$eH)q5>g^b5(l!`>n=%C z%Sdq5k@sVWQc^mLZFJflD5aeFV~BC=uDzooize}IiXU^5>3C2rPUi>7hm5hGRcjOW zWKhC{@_>YIabjauMv;-llB$$>GjU=DSZ|g(m{|nOf&lQyRhO*z#`fELGJvOA{CWKD zulEk$iCK&@BqfXB#ct{`)dmqIN~Y49XqsT8N3ZdNqAaZ3}Enio>?d2Y<+4F>uG<+j{1jZQuP@C zxh|le;?W70sEQOC274B#(9s1NvIOKgzWLFQ;hvj6je27QTh4zYhR4i`Lv1~aBZqd|0*Bn_smakXFdmv3 z)d>#MMJM;ZIa(=~pktlEi*^U9-GRz;=%Rq?YqfZvnT>&}l2yob%~{ z!8LFD)Q8`a{^TYJQVfi&{n;eVYO~Y(v3utO=(H2ePUqOY^GQ7R!1qETK@>j)qc!Q9YB(n-(0QrpT=VYnd7w5N_}-> zVEM1l%}gZUyZu%?`h&Z%IA_plb#P$UZrt;)|BQXR?nkFHW#b5Krjd5^DhmIz` zB21pS;7HR9Yfd>2qbp8DmR9TK%Fvs$O5a7F*tRt}5nr*^haUp;V_*ri?!f5Wzh^&T zk4)bX#WQ4v12VhgT`WY3tETuq z=AR?3CEfJeCmJA%)#JVqhI8Sk?0?f-5M3Qt5nB3%? zBDTqKpCbA~b8F+f^G>I0Ku0utO8Fw~y)Nu~p~yivoxO2v0&2LeA+|LL)LKJP6u0}c z$P2%p+4pK04K}4g`P2i;=*>M4K*vILauj*t{Tc{(VVwD>K>#q0F#!ZKMnwGqBZF3N ze#rd*(CYYu1jWZEGUg*)1E^?a0y2?SmJk^O3c+D?8$b#$agk=a+`CI2X8^z$vkt(S zy~B5c000*BI7H<#VW;$_C?U@{P^WxckJHU_M_nRq9v9rvgQUO6gwsJ$6Ho4}o;nr# z4LCXvZ5$@jF!`GbLl>%OjE>@!;5T_P4W!ql_Zf-~)>XKL$RXx6o}2}VfRH@=4m&!= zNy-eB+JFMsfs^pGc-3*J27mJB_S5_WdzyDle-=hzUuPDF^97h=e4>PL)I|NbQQ?YtL8E7bZ&P!w&}93H>6F}QqHZ|CW)-a7f#uU)@Gz3JCJ z_O0oIyWaQU-Cw?D=E$BW4^KXZCmy*AN-KXKB0V(oMq=nP5A(6Kq-S?Uxh{ytY+#g) zz14++&Mg2?wA*OUEdbh}-amv@8_z+hQiE1%HiGktO*m&Cc7+Zcic0ch1e)PcI{@8f)VQyu9h|K&rEu`1*%eqEzWaUvsp7c;zX-Y8X4NP4Z_x@|OOyUa|H1tXx}T zG>6J1%9SQopK>lvJ@XQ*IrSX0=I3zlUEjbX_xvjiIw)7mkcpKJ3MU~XhjwB__*%=k ztb4hGt3Nmx##U`cU;i>>S*2;o@`oLLzNkK_@C~$bjcZ_Ta{upy60s=q&qoVJasZwr zj+V}Y%e*^h5NXHb$+69p57BpUvK7S9bCJ&hSg5t*nNb{BX*~c!Wg?QqCS5o~J)+rn z`D75=AOg^=0iM<7tGoyv3(l<3?Jl;`k9@CSEcIU(%7TxDvNRk=xi2~$zaJHO4wV;B zc@CB57Hr6K_%JLl@5E(19hfoYylL9P2}C z1*26c>LDICR#N0BVX>lA&G01S+BTAjQ=XR(dElY6&M zXx-JMaba)xVZyK6e>&*-wJnHvlpShd>HoA@1iHU{hzAbh#HHA9MThKBif0OLpQ6kB zMQd$A19FsgW-mlLq|YvdfRG7_qK!^_UNC0HPo^{Bvun370LxC6^Y+I!`%eo`JpFG? z7mHX>9USb;VsCpIg*iHQxlficl-5w<2@0dIw>^W7QRtUtOwZ5a$e~?${K0P_NlWN! zE<=$oZZyEldwWiA_14L|e&M%1J~wq_&v$2z?El>C%)TFJzNj95_}iGDoeU;r2r+lm z*pq%8?jC8UR4SOJk?vU;UkuZP%}&`06zw+h#YGrxnE)HlyacN^z7(ZWeRObS-T&Hn z+QonK=@0$Fh8OynGzOQSnpM-XND8#(7O`UW2Ap}`t8mI0KZ8@xybxn6Hek==kKxF~ z?qK#yuHw;D+pE8b%IyulPo!@oX$_67$KbNHZt`rHV99X>02%|! zU(Oi2`oNQq@`*hMAVi9>Ri~k^e;KOvCYG;06`Rk#7`6H!Cifq}6Ayn6+O$z0XdrcI zN7VFkN8b+h3VgOa=iC+3ri+q1FtiG_z9H1=BWoJX@n65`hOOebf5}GdXQsW&4u(2l zD0~AeoXHqG>b9Lq!zFXKQHg>sT?uTjA_(zd+bp10L!8vn1 zZ?^4CLY-%Zj6fA%=i1s;W{DrnF-od(APUvg96Wqa#-^3XG`0Q%Ea>>d&(>Ccv zUPPCmYpOwpixwPFMFB3PHL{dRI8K~-gTcb}1vEeeBMC`hPFNX(Lf-B`<%KihrrO-5 z7LcsM7(`55kMZkkE0re3kijf2$k|sD4;H)~r!B_U~ zjK?1UxT1IHPH-FL9aqdTdn|9v!>ru4H_yOfU#kN*~o6G6a?Zq0lC}$(T5YSqGii(v5}oNA6HoziCFg zGMSbjWU^ok_MK#>LxPj0L4D>dgTiR+Zck&XXg&QinYg(xfiZ?Q6k00BfzIqvasURP zDJ$p`B}gW~YZ%Deda*I=$6fC--{Kdv9I* z(fxP6Z}*S>?TY=o@B7D@slAvu@B~_|X{VDF{yxSN36Nozaqj*wZbGNLz?kT%hN$0K zgCS(88%O(HoSj3_ZUY8r3@pQn^=G2q9EHj|84O;%a{Wu*|Jgryd-a7n7B_wHS|O8c zoG~ss?Hu*S2-a*o4{2Hf=K}Rc6RS6z38g!@?|XOR;FC{w)BJ%hdNRlykDSb7eKt+~ zXtGLka$|=C&TbKg9WDLpEY4$ob`rJvz-yPS*?e53rCJqdPwac5Gg}$LCN|llyPH@4zW4i4JU68ra0Vtuy+i9iK zQUxPp>(N@6$||+NUzD=6>3Dz7*IoaA78%!HU`);$7^r-o|9;TrlF$8zjwj$T0uT%W z;V0Id3oyaJ+@zc4)znlP9TF6b3wHM|_s03xM<#^eESNmAm{Kmn@39aq9XI%)IL4Cq z8~sd2hSX#<=*;F2B?oA&;M^TO^_@%UJ{^4~<-SjeG)+C2C6feFO79mUq(oLOAxTpU z5_oEQXsng8wXsYR$Rx3^4OqE@F<_G0*XOLOrX_$xCKjk9I=pZ-JLe)|*XpC96=h-@ zee0p1{UDEOYmrE#rII%|4W0rb7=be0eY_n2V-O_1o_*|070E0-NmC?Q>W#d+%|Tt# z7ez+u;QQshS`gAhNJ`8&w^CtM`0GwymyE7gq0KgcN0vPWd zx)a|f1I{E?|ii0pBVxL`hOl{RfjdA!c)*f-H0kY%w%-s+WH><6&~Xi^_{V3hl- zm4bGgf0*{W*g=N^lhY}oe*Ui8?Q9Zgn3{ePu^oI)YwWx%yc2Jc7m*f>J4aOJ%$ppt zECljS3)2&OFnMt2!RH%)`4d=80HxyqD;-~u>c{-_$3X#8#Uk2TVWKmSxuWxo-d(~3 z`ecR_0xg}RrE*Mk=Fu?<%5(!vD@y$+af#;HtFZFzFT)wX@miemYnLKzO~On*i9-*4 z3y*yNt6+>hx-ftEaBtV?t=>BM*LCmx{MQf(j z^YY{I@&Ejz?_9-Y>Gc!)4oSumEMI*(hQ~I5GvU8atBX$292~>46{jN2Dmb)v7w-Sg zS1l;f-#}U}fpdZ@t)U(Ph6aFPHYPhw(=N6u`Bv$|)+k&E z$W$V$lPKn=UpIoP?I77DS~-EXno9jhGA4Q|Gk0X5`r;Pw5CfivNUm8u~9zqY-BJNQys1}?E_5E*P*zX8+b+hsu{cp!sw z?$2GH<{&76g5(2nij?zWFd~H!)f}za-d*uH0RR9t0yw32=uYhNG=I*$l+JjaeKZLd zRw9sODMTtmE+>mNQs0-Ei0VWXdy45W-l&CWRH{%8xzyhM)zZF#W=A?L85x1Zn{;fX z1RZV=6bIt1M3=A}7!UchCPFsj{xVP!!v;?O<`H1dQL2=k=}Cf0eGpm|KZG$)o@A%P zStrQB?|DH4<~cl9{5u0l85}^zDC}xap<~pKeKiJPSz5n4dbiU;M7x3M+S|ob;L~Ue&|b!bJO?rcAehp ztrySwrQiAFzwCMR`#)Ri%f7-=UF?1GKFrTe1|wQ01Mti&0zEp=d*NjP!HgJzN=^6eNHxuq1WC1G z>CsQ&?>8{I2DQepdv0<0vhhv-`KBATJ}=|Mzxac9uIO*B{%xp%b5z06Xs$$GW7N}{ ziP~%;6Sn@rF*N#@q0??-*CUVN(R=Sgk#|t4mXTx`gb*mzDn9nm)00VuoTj!OVyvtA zlQPBdvUMnxYe>^d6YTiwlC?g3pVkNeRO`HL450D}XjLp}w1R_rn1XBHWYPIxQvjs* z3Lv94ktC2=iX_Y2XH9%eB%=7}I0lbQ{Ooi{hm&r5`%R#(IC-2Z8MF5Nk44E$$|-R%(_J1cKc9xN<6R&TGJ0ks7^Tti*hpU2I) zF%;QneKeGd_#^r~9DrtJy|OEXf${J=UUH$W&xDrW+h9Ckf8^rB~u*|79yS z{ioMp?K>_+cHuZCS4!;aOyNLh7W?yA^qsQ`jdPZxQmrG+N*Eehj+LuV!Pttmc-cj- zLn%wya3y`q@|7F6_BNf~>a7>o`qlS;Ve-j`zw_&cb^b`3V&TBvhcP|5Czx$9qSIPA z0OzdBfXaLA&>YfRliT}ZhzK-R3JgH!1+*%l+8xghShfBo7#`aI0R3rN8DBPj`e#1# z;kRu1#D{+Vgt5_zcAK>prtg@aIfB_KYlccxSz`7vZcX88^#N3BHQe)^JFsu(qu$w^ z^47U)3N5|a$qij2|`Ds(Aw6ovA+Wl7_KBqumdjR z4fBdl#~WsQZvi(Q*IGg4$~XDcuu_@`HQYsRpDXWlETEtQ0I8J;^>{Sx^3qur&NUMz zXTDD6&a;6W{!R2fi9}kdf{@-Il?G{)ija45do1H=Jpr7~tzS7{fphMS!M!P=mq%GY zFblMjG$2kIGf^XNx=a&IG?XMJ1MNp7@u1)3JTfZh3AkvuLsGt)Cj%Gu?u5r)&-&)G zZQHj02f(?#L-&GU0D)dbZkx_c)Ei;=m|f-_K8?@gv6Lc;-ypQp7XT*wuBAFM7^h{k z$gMegj2lJ$5vV{BBHG8bbUzL-kpXN#-&q_lLj@PP`isbkm<8>jaJi+Ni*R#ud9?0{ zkd`y&AZu@2#%N3)cmhv8@|~|A+WYALzV7;4_MS}V!Pe&JWzRPSfGughS@&O~TTAz& z;;)~vqo0W#^~^Y$=DGBDqVGKA5(WnIMF#~8S}I3LNMv04-#zO005rCYqjvdv^fd=D zIIqRz-h`p$D=<2?8cEVURLZh4s|=_124HeeUnSGkMWz$=6Hu`b&*wtEUd{lZ;7JYE3sWWZimp za|~yD1hAc^jMUuG6spu$v-;pH1!D|FyKMmgW5BsU-@r1YX$eMaY7)d^{Ry#^{V;l1uPreh`#=1p6>0vfwX~06I3cq zEX*Il{@p*q=!$VvYIWb(GZ(Q%pn#7Ibie=?A+~!DXG&(H#S+LQ zMc!V--1Ic^b_-cKLt|jX4;zv!bH$ADv1(M;@I=@_2SO4O;|xl5FgJS`3})x_QU~aIQcAf=KldI0M_qFa5S;s((~uKB{md9JF04X;u`ZoBmKXtsD#ke9 z1NyuoVwS=+=-NwAnc&{Xz#4=yXJ+T(0^QV_^AN8si1`|Vs6&&l1B0MTdJ(56a^@o? zDc0LKS%dK3m6P@g9_n+)zBLB^y^<#Y)#>nNmEF;v;XUXs%|AteTj_3K7IZO>?WW<3 z3qxJ+frcplTPq#Xz-YLqtYla4;Fm$gCFjD&K^c-BARISu1jvPF1bY^Xf#1umtauL4 zivT(YjGq6q?O*%B-rk+?==EF}0I%sCwijkmbOwt|_F@-aZ`?;nG-D8{L|V#hES^Jd z$r;~9Xt3ad>Te2xCdGo;Z5-&{ib$=oP{J^kx3Hk|V>tZVbEZ?~NG=_R%n}TZEJuHH z80$8kflX(ehjpi&g^_dCVau<)3M(!+9Yd>DVeQ7#QLY@@d#gD(it)9lfJ2|!XBPf+ z^~w!@c+(BnRC>ElZ}rxTXT9tCTNn55e&9c9%zdcZ*Hlx7cY#Yg{bt^AH@=TWnp_yq z4B#;>o>5wWf>BmWE7KIldEk&o02#%>0DaA6Sia^A42`Zutub=$igjoG*}BcI`0LTp z<*)eUjo0$y{kfA;HD8!pM5)|Bb7(cRwo^7@?a}m%0jSg(SU$c93ky@Y`(JLiF}sfX z&82Jf6X~b^L{kn7J!cfh8AO&rWY3(%<zR$ZC`;eW>;gtgiKszM4t?tYiQ;-LQ3h zWYyWf*IDF$#91lpA6$uYwa-)1Ng8Oh>7ESxC_4MSXXOf3t~~?wMiUFOv$*d&ci`~B zUDixZN{A#uwb_p(%Ys3mGfL#l#VjX@lRembT)EP~(6V(XihOhb(5j11%sGCG2E?}+ zuiVdg8NdP0OABLTbGlk1f_?O#5V>x zV#ZJ5yu?T%;ElUUHq0W!M_5qJ4gxKUL4)F3U2{*&B^xi{;{jO|V{WA)E}a2s28biQ zJK(X`vtj@kW7Yw9U+=KJFpH>Cq|Kq5mPiCtr|8N~CvBBh+ESE?Jknb+zqwLm3*E2? zktJAEM+PoL8S-x?p5nSqi_HJXvw&{0gcy2VSM+?wz$3zOSI9(^qw92fv4bn!xMU(B z(!~8~C&lGj6^TnjkZFRnoPi60sfpc~ncSa0`olXuK6zm0A6<9-EpsQ+Iq=!FTR4FC zK40U_7n}jWthT?UaxCfsRgpokU=kIZws6LfaDk-1f)y8>hOAk}tZHL^b^$5lP{v?E z=V%*+)=+}JYd52|dIT$0Z$!1$2LLwGMo9EGhcP_568(cCXbz2HXk-jRK7F!Onw2mx zI0}{LGAoq_J3O0u^*Mt-*#6HCncgncTfOz-Shs%Vo~hSdu=2i2t+}P>s5SF5lfs}t zt#8oZOS>mdj{eJq&qk;HigD(cb@pD$jDbi}$SiYOV-B6?E+*GKv#=BMBq^aeyb2;o zF>_>pB4j$AWZ7jh$ri4-c*Cw+zWn`#3iGpvp*jYg_7nz}jU!1j7*JvaJdKiS73s9sL}&K8cquSHI|-e4 z*uw1O*DihO@V~v`vQw*9UA}o_>nqQ!U;V1nmR)(tsrstRH_08hKiGM$-}#jnpLUpY z&KXlLXP7TDmLn|>dtEtqdh(D5FOVb&xa59XPDXs3@h;{7r9CU9kas$cCSLg3lqS=} zobjm{ES?0p`i}7~CZLEl?;=dt;aD~_bvGtB^T+2g7raXv0I-lxZ;WqLi%uR*n4Jcn zaW8XaAm%EiK7{%k-e9j=ryi$iF)&D(06gp^29Y;G#8@Ej4DRKva7}keWC-#L;gb`( z--nd~Gr=Jk53c!O-i#7Xf~%aKpMiNPFE#Ww)=`D@gy{1UP-KC$us2#6h;(M)4p^ge z#eG4xcGrHg&ln)M2wo!Y*em~?GXMGM`=A)h_?UUX!1XW`W$q;{OhFfi0I(`d=g#e4 z`?sFQ(=pbw)mgp0cgS8y1i)S-NtXDAJt;(@YnUj)#(_By8s!f+R~ap?g%+?1nCQLi(KjD}Erag_(w1x^lb~7$G$A)Xp!|DsRAkRCPpP5E}a2^wP z?*uO=;5DFc)iC;(k3ysp14GMDuOC}V$%Q~F1b}B|w9UCdwbnqTTF1cy53U=jRer0w z>AdMr-@v~3j_Ysj$pLz+w_YUcmw)Ha4*$hRli#gWM(2{WbnV>qgd7-N2_X_For8(! zzNVu*UYb04@RT8~*Pz;qFonJEs>Ma9L_$`|wqa%*s_2B|9qpQD2b2$vtbt5Rm^|^>PNkwd)24+PAr~$1k3Y_IC=OXY`IXS z@k+rF#4%XFkaT-6JVa&e#=!N|QZ!ifXl5mJh6o43C3BP<9nEtbZ%=gT8Y zs|&}75E)-u*#EUp|Jg5nBTd@(b~?>d@A=TJ;%tuLdv<*){mibP`ERYpw#g*Zvn0a-A{rpm!AaH0(Aj-kAI8$+O_XUM|9TN$KP$llElk=lYvW z>%mQvZkk~`QC>%(Hx0LWp@gd87SVOB(5Y0Q1VIp}Mpu7d0v2c>i~(9Ms~9}e4$73% zznU<+3BR;b0s+_>)|5a3<{?TWZzk@95-=Tas6ePeZ!7D`1@#)8;UR(427*K?ph8J{ zxjPozu_-7~;GzX3Jn+LvGZuXUz*;c#8VkIzw_A1PG)Y7*bkhv1MXuAcyD(RxX^mqf}uX zL;C;Y?YU37%$KqX;LicnhKKFB#sM_?MW~9J(b{*)C`6ihW_}VhPz|xjGEI|l)P0i? z$~A?D+K4^jVg&Wg(KP&S>gzRn5}wwN=xM(=Ek79pxuIl$O+fuDP#7-*&p;+%o&gKB zH!7p|H;8JvR>8>hIO2THYW|ac8{fTa50ZXo<@mw-e*4t%M?dw8zxk=7yYJlly!-5L z9G%Jm_+WV;5||#I}vdl?#~Oa2`f#lNg_vamf?U&?=UzV3Z+b zbSjrCzA7k`jNe&~Odcxv_5f%C{GO>XjGW8|Mo7EKRTMcIsqwVipi^ zZt2oZo`}?xanpPd0&ot(2%=(9H3K>kK%@y+7`bUE0I3UYo9g3f(evd|RL1520KHB< zH#)xYh9Jsq10jcA`MS#%zVxMg&ieiR-JkyQdAWG*FL}z|R;|s3Th6}&UmZt9Y}j%s;#|>FWjh`9Y4<(b zhz+tDAl0Nh&XoWuv2^MXdfjD=&u&7#Sapqurf9=7m)a*m>Pai5N-6;<(OO$VW9<}+ ze*Q(InEDv#|Lsm+d8M`kzWa^+3kcKy7mnG0T?%a2@NDA!(?FP3q`72^l?+X;kbJ`{FOOI_dLv|#XF-f08X1_dTj@r?24bb zeAf(P3JEWc*+2Je=!df}R0!*H;Tpr)`}KZbRq3&BihI z-8n=kxX@kzrq9sKC#x;iKQBG`fbCzHj_8B|=%_uWs+SWhhHJ2Uqc-x-bI;dC8^T9o4V6d2LoKCs zJC!!i7;Yo8@p<0Qc-kuC)TuTn;m|v(T=#jJ4g8Ekd-dz`3k(w*WT=#$j>%}e2&10a z2OZdqS?IJ?=4YdP4*60ZfniAyf-s6v9+`&VS$Jsgzx~f|61m)@|SP-DGbUa_k z)cqM|MESnH@@QHlu-KOEK5g|eutDR<6ws8toW<8 z5iy{qVgX32--R~)V?m(wyh1=G37}oo)noXeiJAcTKnK62Dog8WQyQ7T>e4YV7UW09 zH(U}$xyzHq`F*c`$;O4By#7MD=Z?Kk$OgFi!#A?G-T10&k`DVAW2G05jBN;~W-mY( z#_m2VVKvLf8Qo4`Gey@Wlpt3q1CUr*IEJMY#}OBD7@3&%sJxEaZWDUQ(=QF9ToG|x z#NvrZh?KI{Zms^qEnm6!$0W){RwtxZn4 zsY8qg-AowGAj1w4bvYErCA1m~Xs#`T1;EtC?FhrjPB@LLIk8Dg)J96OAOO=o6RV5I z&{#f!+SGa2wB>S)j%`4(IEo;MP%Mt3Hogg!ktwA8UO7oRI|}8|msQ8-wp@SZ_}6d! z>H}vL9r*g|FJXiRR{~-iz`?=_D9zd73S&C1kT_boFUvDB7AKd`k(oj`1}W#@JX3~` zfr<|#l&HiE?NLSjbHkH?QsZT1>p&B%A$<~pl`ELXnVQwIQ>6p5gf+BN*QyXg)t=0A z_t&2btiOkninA!R4Xy<|v|GPBt)*wEXI%DSO$4#d7t7Ax1iS`WMgCFEIuYFMErfW| zNXtAho(Bq~FtQAo{YL_U1{?*~8hR}wFxq(ax|kiDF&60Ks2XM|g^K;uAV3g>E~-!( z({XBLG@Nrgl(U0FYEl%SfFbUhdtzRPHxwk!qyd>uOE7zrkWPlcO)sPOOaGi8IvD~m z2@$$4U=)(~Aowx}2_k|1*LUCc?e7fldQT4k_%#4886L9dxcB!rj`gUc-t?$P*^-(@ z6@;OsX(?X}Y27?ApkvY(8=;m0XtXxMx*!t|9QUGr47k9#-5>`{1HXqmyxFJ?rQfHd z5zm;AYWGtWT@r$YOga2VA;LI95CtxOm-_lIhLevyK%=;Dd42Kd-M8NM;L+zP08j$( zO8}}r7y!WF*U1^4lX&J7LQ1rFf}L-_8s}eoB{p4lA#$}mM(3sxO%}27WtX6K=^V` z;iTXAdTo5uGNr*w(yYrWV>4Q}Z1x{*Z0k)Yty_1N*(RPa3Km9cI+tZ2x{;Rs#2MS# z2`sZZXT8yZQijR79mtnQk@Q-WXUWE5W#YxP=`A;Qnk${xT)p}Do;&yU&h$P$_Te`a ze)=`nTwN?}{k60w-&h;pdF|xPj&OWxGZ+mW{hAUl*+4f{#%R}?W;s23sXC5AaRl|1 zQxH7C)TS-UCI0jxo~ z;}BdR45MPMT)iv|qX$3v*?)fEY!2s7Uc0SMX#N|N#pj1n`FuhcD9eM;0L+V8Gse&6 zJveZOSfe}BghI11qc~Q_P!F3ZQ)Y9PRYIxKV+%O_wuyz)-Uvo6K|H5ut4H@J^43F& zYEZ&wjuP|xZ24%-@$95ogAmYDZaZDq{{;b4&iXp_z#n|6!IeMsP|s@^veGxO9$>q= z3AHuDmY%z|RP=pVW{MxlNSyzHS2Ig31286vRLgMO2R-~G@ngyFma!{@i)_Yu7NcFTr!`rOM}2bY>`wQgT2B%|y(GA`ETE5Cqnx1P~p2LIdjMg9>}W8`*&Lnty}d`5VDN zEJ?r=JxOc%S*UJMEDW4Ej4qJET!eh7h`5kbAONEX;~2S80W6@W0Suki8nU!o?6lVQ zz50b4?%DmnpMO)_8%L++0Q{eT4)=YA0068r0z6YAza9j5JODs~pf55o;)V8kOo4PV z#(CFWjPtf%fa#e{s7=hGIy#P#(FugP7_*zUU~F;*BejWVWQz1mfNq6i8G>i%w$?V* zM#j!h5q#@^ed(@+;YKuE!*y<~J$F7VZvE>0Ctq{*hDUhDC*xfC($R?-62^IDZf5Dj zE;p<6&FPfBX-Aw)~dYU-ObmdFOj5Mt-|cntDwT6t|C#&7oSG z0VT}3cw6S5ot#Q*#3sGGaerbpipjd}$hfAqR&O)EU*O<|{;}wT8ypBAWH%nA&(gf-u&)`aylVH2Qx6&@j{! zS0L%NaqQ6jAdpx%{wR`O7fG)TLMWm*@5w|M$|I8~6l>`9>oixYoPWa=h76;LTAls|Dqy%Bj;hX^+WlRl?gfFR3 z$1JsO`ksH3m3ey2ErGoTq}I-xCR`mu7isN#5?Gditu?hoR!^IyH)Jxv1^lQz`&ql^ z^C#{u#cB}TQj>9R*$j@YAgy`3s5Ur^fR^!hsE0)?A zK4~Kk5(esIu1rSdgWj0w=$|#wD zjmptC2xc}C>45^2xr-kfX*bBEx4GLXKlNu09;<cxjuo=*o5sH4dg?_h1JI&QQjvrqB+E>2$(DUwNzj1V`4B(vriqA-m^(2x2 z&K3YjCC8C|9X*jDksJ-)M@uB=@Dznw8DrON$LN-6%x&7HVrg`AOBlr{mMVzi9KtaA z0lVA?3WYM_T!D03_48`A$%|j{vJ2)v^QCVd7;Z+xHC*S;`utb!X}tRCnSG_w)K5q$ zMyED!2c;BQudiu#63CRyjTp}}FT$2csHy)zM4)2|3{d91=GslrJZYTH!!A^6poF5^ zX@Iey5Cq}*<1^bfzv`-)#%r(Lk$dZn*Irf`nfz!JO}uw)vGI~(X>wv}ZYQQ@cPNdz zzu)WoyvnR++SFGysafibz=+M=b~OYc6ouj_R+o?B_@TXkpm=_^v zK0{OUo9|O?fM_)NRDaISIM4Gb$W+3I@=Ab}$YiNvHyK|5LYbBl3(eBdTch?+a51Wm zjX?(XJ)%`rQkx4(E3uM7Ir>wdEuf8|2T~GDjV~1VA%xJzj)9XK=tD1f8-gzZvUNc6 z-e2v${oa+~o$e_D0K0bWdL4kb3=h|Hzoh51Z)N^EUz3}RO?~4NCK^NE+_EIqx+vA8 z3uEY^pV!?WF=({n;hI!uf|{rgLX~ESYt+sf!boQ@WS+}zY&!dMApT7^{XwXTk{}N4 z^gjp#y-_m+0YeyvhzohJ(8Q4_l)qf7BFg8SnTmHq;ylID$pdIN7I|akIEjbZxQ9jNY@L3CafJKk~)CN9{7 zv59Gnj!ix9K(`SUuH z-=qXVU?-JA2-RFLYO}p6M9h=w`j7@Dp6y;ToBP4jrJ^HY;dTXN{H}q#I zg(qDk11t@bOKt%G{WgOzMyI`sc4HOo<|<~++m1L_bPb;tI!n%N-9*C>gc0zhkHr)F zktJPJM`utd*N~JRt00VGWNa2h4_9DJ@<;%dix9@SOIZ+huD&R~f6pCzpR^yq z?%N*d{KPfW4~O~bHwfOXN(h9}CM(YNs4bJ$DcUs^Jdl|9|_~7Sxuh;tO+REX-J^JW)oD!4?nE5raeV(HIK21% z0nPI>c!SaaMu3s=jToKSh#<_N-CW5h{q)Czpm^bV+pY>GXLq1nomK@u8_bj^gxaa0 zkwlu|gwgt&y2rf*-MH%bGG}h+H6(;$cEd%;7phoYSipDh`iiFmhn-T=Fi-%Geh$ec zc$%o#HA>NHE}_?6!|})NM}6faq~v<2(^tlBURnbH6!T*!RVRu;kb7$o=FZv+=%x>T z;Ss@;zo0>>BSngS_b7PMuo6xiA#HTtLh2@*Sd&V^nCBnm^!HLoD~U13k!r){APV%P z+fl_c16WKaigr3LGNH}f@P^hnl$1*SH2W`p{3Br38_ zHLCt}UmNpf(#B$X4tJ^^_F@oi>>pFi3S)w2{f(rAy4aEKn?g zKzjm606`caS5%I+Oali#P}1)wxq#@&wNC^)n;^#56!e8ERLahv}VLv2n{zjEqiTa%v7? z6c6apo^LA*BaGB0u{eK(#JS=XqjNj&d+EjH!+Y*{XlM#JT*GyatlhUiDBt+1%W{lG z^Q)(hzA%al;mG8iqN)m^w6Ge`HuPIXM}=*i6*?~zdmu}#{?|_ai30~Ks;Ww0Tk#XJBxSV#Ea^#T@gd8wXQ$T{26!uyO!W@Dq z#@g~xPzH>QPohvBbszw7QEI+XT9)*1{LpvM@3kRB`j~`#I8C~F7RH5keF?p83)R{T za)qiIyf9`DS`dV2wic1}JJqz;IduJ16Zd@SNu)yf>nC5n`7uJmZG@1EMb?Cb1PjU_ zIx5c4s-4!_0VymDAcaJhrcUPRHT*Eteh<)sW}%p&jhzMycgvL8SHOG*LbwSrfnox{ zyIyRAPU&gjlXAHyu7P&ttc$OMW2O#7&>4m*aZ!54^bYGxt<8C3CAC&!GsxgE=^Cz| zCDwbx7#o@-0QZ~%vj4yTqGBejX9VKPwS+zzEMrh&qyjtDLsL)lA(Fy{iKIK38?p5%aFfRSVT zR*cjJHr)&mybj0~2#xQ8Y=7a4x82tr-r=4)0PtP_v%|yneOd$5oeXJ`Sv1b4So!zd zq}xZ*>kpXgfD&sgLR@r!)pi*JKw)DxoF>j713rRkHy=YqlHTUGP6uT+2uppWE=tAd zl?+?KdID%uKm!`EFhH)DM_kCEP%R;hV@PD^wd)9i2y4s7Fn{<#oI17-OD7MaxjK(9 z$|098kIikp{6e1gU*2i2mR^6uh5L8kvG;jl2&e&opZ`Gz004rBGL$w>ptxlm#ZnoC zV&&<(L;rxRAPgZmN2j@35JHp_p56VqFW)oNl?~T$okQz$U%vbBD_%UYFP|S3X}9;1 ze5pb!lQRwk&^me+1_feU-#ylOXq5eBQ zie9$~N+`l8K)2IInsC&{H>$`#>KYh7p3F9P=3dL#fG*oFAPA#_dTKpckD?-S`7%}) zkD}LYf<+X?YE2p4t#ACv8E-yM>JFtq7KSKS#KO^i$dW$VjUHwY#h8OObM&}81Ru=U#SqU zu{Mkr3-Wk*@n*WNWG?RanS?B&jpVH3zm~}u*@HC65E>*fDIbO{18bfw9P`Jkd5zv( z9SG?)uLJ5@FXx^NfMxD_!|8u&*3n>mHmsKjh11%*8eR^h8~73#HIerQ@07U7yp^I5 z%M3Be5DElxpopp24R|AXrp*xbXQRO#=XW3nUnAr|4`KZjq%)(mQUmH9Z{q*VXR6L) z4#}GU$v}X;K<6L6c-y`0;oa>i002_T2*9rZm>M3g@8i-)W!g`b_FtT?wJ{fMmZV7g ziH#0aF0N7={RxZy3GMD`Ha&~9>8qMJR}f|FqH|z{7({`s*`G-auoo^|qtB>z;bj&X zRyP=xDiB1WXBtR7=>m`?DS{|Ob$k@XkrIL^MAGl#=>Biv=%e4l{E>$-fAk@&oH~q7 zYZaa53gSWun0Dzx+ zHUI!TO(Q_8kNyKtKe~j8muyD{j*-#vbLtX|b9odBCCIF|jRfKNYp&UP*XO@--_Q?W zxQ6Q-TCe%B?akKespC;l_?h~t6Qz8qit^Z$a>Xv>wGRyi%jFP_jDp26XcXG!-%-e! zjmIK}HtU;NnR~Y`oSz5)FsoP@Lv8Xrl&TY8p_+s@mKz9y7;(O!a>1#iOIs5y)3{hS zZQZmPr+m2SA2CclkadlVa>Q>pSJ3ZtaQxt2RL93r9i8-a@ZQbhY(W4sMK){-0G;Lv zgcRsBJIEJms7-9NIripQan3Cb-@j{_40CuCaZ|(i0}caln4trt#NqvSqp^Ad&9!;7 zn=5@nE&E#~nf6AEhRmd`AI&I30BVMB32n ztq~rib*UdPWi-=y(}?N_LfceIC!;Y#D#IFuiMuwYh9=6Ib7Wa&r_CnG%ImkCgqAY> zyjmurDe|U%RgJ0sJ;d`E@IG(p$$*s`!UvpbrIoYTbDB7B0b_<} zj~msp0il^5%o;NSK)?b>BGr%S=T~wd;u$Q$W68Md(vNMlrjK?QC@ttI{UM@v3`~B5 zV`>oRE2UWr#E<*)Vg@N=c0Ur_0h^YIV1d#QB5UX*mWAIH+1j^u-|?^<-r1f40I+M< zuFU}6`*dT-hU>}p`O=wtz-g0&ln|LvdK@lXjExt6A-F)=?<46Y3hiVj?!`p4=!=XC zyCF+1Aq01HeWQgEjy6QJgQ)N7N`1o)tHq+A)I%ewYx<$7Lj$@kswNRpF4h`GX$uge zMKYUnREUvf86=kq1mOve?!OzY`Vz9N55ZFeVT?Fe1Pfx+CN^U0Mc1HM8AEww3URTF zQgwoaQGRxGV&lb~=IU~<)oAXyWAEzo004N~a}5Bjf7BBh0h)hhSq3>8qcB@VZDQJ? zx97kL!U(xS5skGa77@9Vu(*7~i|79N)~|k-4|lHN8m@C={ry+>;`Oh%ut^DhFwRwO zXe^y5jm>OETr4Srw=e_=L)CO-naY9>BSqcTrfI}C?P5$#`#mY0ZEPq7(f7wE3jhEB z3qlmiHAulxs*Itv) z@Be0D_EnJXT|#ueTOOGR(tdB_on~Hyo_;Svpt*Ds%L|9GymCx0QhHK?PETBmwrB*#Lg zr@m_1o@GjU>Wt|WKqEb=hLx1P8Clv{Pw)oiKeK+tdO5JGp)>LYqBG zA(U5vmUgJfYp$3%UKF44Ij~fHUk+kft>E~-sP=)BB+&Hn75z+9d|6LiDWd!<^~M%r3HE)6I|Fm%6y)tUr|wubwDN%y!8#i z+xP6bbMLT5JHvW1)%i4lk>R0wZWdWbcQR2MBF&VU2Nz0bZ%hGf?xvcQcbgrh)v}1F zp3Dd9;`uBR>X1Mw<-lX8M#HW9vA!`FU6)+1kAn1mr!sC~j9L)FzGCSzhow}B25CRh z@rIc;AyEb(Nx!cOCoOB}G+OAk+7KyFu5JJUL$}pLoGW8wYz`B%=VR-|SL3{$FF{-= z+v8fUPGWk~McAN9||Sqxv&9)%5khPjO?Wlwo%BCD`_Yt8wic-;CPKG`igt ztSz6w()=OJAA1OCzXP5owqB52*kT>pop#w zVMrXPOv5nDRjOk%;37dkX)E@K=K%mh5JWM;CjN09c8LSzkOY1h)+mFyE5z%r~(H{=l+*NIdv7S8!inQ5(n z1P5dtLaaiHM6))CmDCW=Dn|ygh{W$gqqO!0iPd$R-EQd*?kswcM5x>I_BgrQqo8{&3G>4pK+x zWfmM*f5Do`xS8g&kRb>|!-WA0LL2eN%@ELB>x{Z?kPwfCZ~6jv{XhtNyp_j*O1)r~ zG3509QaAaAJ>pC?z2prunAAX@xpvj@f@WP1Js_kOEEU?+(Ptv421Ed24N@{l*`I&+ zu3P)VJKE#avrqJZUAuO@8^Ftlhw9mE@w^Lp9c|8RhFPjMF5j%gBE%rd-M8IQ4*8VY zX}Y<{Oyq{NR47faPcsixbjY3mvxE=@252O4U_%8mv4^Ypo*K7m|AYhhi zXbKV&Ey&Z%$^jIJ!0m?5Gmb)W9Ig6-$|^2RV&nD~VtjTpa)rtO70`j{1Ywv1=PBwd zCu+Uc+P+s@J$K*V-?8rp79D&h831_7J^*K!_CJmfKnEOi*Itb3)Ho{D+PMkRQ3^&G znyZVs(Q0)&m+Z0YubO^z&mDV*d)aUe*EzEG+_5*g_C>WX2Q=(3gg=@uRHDMj7#Is6 zdR;&p?#eWQOcKaMySNiC>Q9^Ok$?eIYh?Ab86bd;BZJjnle6|sA(SFlC}L*I7EEv0 zgtg-*&}-L`CVecQI*hc}hSU!9oO3Xu(tV_%Z^L-G5j&-0dfMk2AXtZXswe4;g^2SN zB>gse-7eOaP9RN|QK?NM2;$RGW532RW?=9pim7rQmoAIY#+|Vs0_Ppbj3P~X5F$gN zShFld>em}msuTp_nggPn3PUG1bx2@Mgk1yIYA#`E{vfz${`1=Mfp@&+S3mmTt+zec zQ|H7!x%-a2e9s+wvp2o!iVda8#E+**my{|K$mL6x0x!8xuK)V;KD_VWk#yTj?bg!G zKlk4Mei#5gy6bgxYUaZCRYqps9Y*=6Hn9ogv)e#fXzAug-%cpS;{1NJ8%wmla$@(V zcYl4~(>b@lc-y`G*S>V_Ue24l31mz1q5(oefD~2Ka};^{dt-Ply=XbtX#3~9Iak%s zn5I*@NNXL}>H7tmDYj*`5LaWH8qsIf(m zz3-bEjCf246OU*Ux{1ARDP`I>!E2;Vq$6WGUJ^i2AQ$3!+j z9bqnB)b=8VZKIv)ESR>M!64}#V76R3z%N^H8B=_iB%3n4AD*d_;Li;$uT zDUuX2{ii*5+_@Ayi2C9ZC<#%jRlaAj6z57P zRmUsE%J@s0s|%k2F#m%L4?Xw4j-2*20f4#S7fTECe=4N{`7378XFaeWIHxb!k=g|E z#WD^(`rS)sCTD&<5n>*|w}zY9a1GbFv)=uITbh6KM{oNx%GlUr58d?}8Beis$K{|= zgsj<8`yh3B@iI+Svl)h#9!w|&4E^g1o< zz5knN*ZZiioj|9#0>&b6$uTjz1I6;_fH9z&+!8z86+$XnJ*8HAZJIJEq)Isu0#TI5 z#?6=G@WH!r#4@v|0QxyVd7FQ^Zq8`N&&ytyE;@rOJL$~w+9Q^o4Zv3+# zn)$Mn>6I*q-YsQzS(eqo+f5J}tHDbagQq!ARsf|r6u)S?T6wXk0Z`38Mb*NRF$>e8rq%9ZrgV zU?4p&0ON2kJ%d2~2qnekV$dVYm;?HQJa}ps^PJqV0Zg;?ZT8d!+3iEX$B^afS)hh)+ zm>mL273DApsz?b)E!B`};75rU?`P^t&zpei-(h+NB`E-C7^vPT<6w+hUk}b(03r~I zc`2H=5AR}65de@ns& za}+D%+n=Ni=KBf{J(umiJOe|sp7qe;DatHDkwsvHtOEmpzThC|jbQ6*F2&rIZ5W$4 z_d`Ph#xOQ9jRX7czkaM(`isx}`7izE^77KZ{PM2P4Gm|8Yq-vl_4eQVpWXlQ$8Y~s zAzyvnsRQ5LnadS1v+V^4N`UBf)dXK~UDU&BY@w%H(DY(E{TpZ!yri9{5S1!B9mq6= z%(%_wu8d5gT%AB=bOOz_MI_xG_CI(RTJ;uI78cQ|*Ae9N7@e3!u~I`2#)zV#YB(er zXtcO)Y=m$?z7PU|&UaT0JVk9{6B=u$zLf(w4+Ivjl9UK~HL7yBRl7i_=yWylvQik$!@2@siadna}> z%{7f3lz~XqVA*Lk)4K7D$M4>UUby z)FL*=-SbY65a_nn(5f$H{a)*vjpY-&&2!`n)op3NS1DD-F*&yb`O=7&x@275l~)oC z10+cs-S(OY!uT1DpMBQ{zOV}5n;+fvy1M|;Wl?D-rO{i2;IjeC6VAJoXFWo*HXs%N z8bQhckb&+9QxKL1AvuVYgJ(VPv|_apIz~{b)Wz$0v_BmN5p3@ENww z$kH~*Sl4NLrh2}NTVI8XR*4L5GDiFjmeiZmc0Tx(Ruo?QP zUVvIgr-|%dpASBeKHxDxiJ8zFzXwXy9)dw{0BQc$_61)5VNn%85~;RU%?1LXyv?A7 zfyS>)Z~?+77zIQoAti?tJx;)vhIg>12mktgYQOcA482i!8xWXxq*7DFp>pLLE;(LMTmM&jK)}9Is%@i znBH(X1Q%#5uOiAt%FXu-i)SgywHa{ED-!YrpZLh@Prma5yMIudHu+3H899q@NJ!MP zKKddrT|S1! z$~+(m3Y8ivBjYHKPNGyDLqK9X{g(oodFS-sYO=2feo~^}?PBrxK_vYa#y4yP0YTDj z;ju^V!seYQaUL7-|2Bjx2fp-2iy6GO)Z3dI`6W~Q;Wd<@N%1{O~q z!1UaO%E_M4f%};CFCYMw&M}+|;hHEdTTIgwQVJyfF7l;3q5}I)YgK%Ym{$?-G@U9G zMRv={uEUbVaJS=!?KcP_s;6e~KPH71= zC_$#0^~o3@oQ|7wZa+qoUZp-KRey$2G?+YK*dJU|^Yu`S=?Fq0buCL&T7b>4hi|f| z*{cKtURY)-?O&eCi$Dw-0_yWwTCWYCt&2fWM|w{8#>kRD0U`Ed7fxzHT)j^0|2T6_ zN|}Kk6mx+1$sNRQHQX>90;WwG4MkrYgc9WgKs3{Ud6EF7Y$A@Oa0bbQBSc86;rCex zrtgrt@mKo^(|;#kN{KTP&o6(9O_P{;$u^9?U=B2(n3_HBhobrS z*ZDgy$BAQyK-uzzrLoz!{?+fk_21s{p}!Tw-EO#s>)cpB_gkM603P|$Cw}L1t>)s7 zt=@NZG|ClF9iIh>VnA@Uo0`VLM*ZpBYC=zM@(J-CcNQRkln~7Zka1TVc>me^rjhi4 zVq#)5q>vaL-GC^J(d)I5_ER+Kt5{xG#^T9UEF3?GfaMV8@&J_x!WgB>IO2RB#Yzo; zKoErp;{te=A`D`z)fdrPTfyqmF(g?Nko~&~)$z~tTC49%vt;VX{(CTc-X$s~&vi(u z0ijGu7_~8*8D5w_RSJ-_=4crbgoI*zYO9I{%nqShUjP9^sXB#1v8uD@Rm`x7RWlMp z#ZV-+QDKZ}lR(uNwVNwgUO0$27dPumhd=YKU7vm2J)BUP5=xF`X&<>_1>JUCW!}Tf zx7W!EjkN`cOt3WRX6EO^pfEF1o4bb65Vi45U^H|SXRoPL!x)aN)kbS=0m}=I{cCG& z@!y}#bN%{VcS-;U035ja!#D0B5(!C*Ik31wK`sK3Re+sGXyI1@oPf-oPiRzvY%u^_ zitefuoxc+qUlhFYZ-RI4hfD(+jD4EY__`o>fd-b8;j`+Q#lZWu&7qz)8y^5lm0yOT z>`OgNGVB29HN1pT<4Zp19z(`iCkHWe{06(tDjo%gPg>(CFNhF9g&p#+ZU}3P%*w206o!7*Ah#}Cl zdaBL%gtUyBfvLTgH4)1+CIh;D1B%+u(c=IRi*UI3Lb7h^KgyZkpwL2N!y`DM%aQ*NQJq!KT8E*9E!Zex|u5a$t(wT&F)wC|1${5e0m{2Gp z*VBAs@u^Y-bd(E`PIqT^JRv} zSInP&^Crp>HHr&8NZ_WAeDMdl`6tiisd=V<=V^$IaRv3Pk9yWal5z+}Ft&XTm%R0* zs7%%{J~@l(=s5C)(&K_#=j?QlQcTZoQhD5s`cIC}PTlwM58wEA@A}{uTEmTRxQ6T8 zStpJ^{KbB^IbJSLzVD&C|8dL3FZyv*MkXOS1u;zwr2~cUY5IOc&7~?H(1HL@viXD@RiXaRjL}vRQ2W|i&<4C(b&@jN% z+=bv7uyE`c>MJMFX|G}P`B&NaIN#ylOnr&Gq*-#`6YTmy z5X40Srgh2;tBc1mIzFeLU)3wUZVQ~J;5@m#-CVRTu`CFAzu(EmC$}J1sOYAjcsP!5 zS@wdX(^*EE^gBtf_5ZcoYt85Ce80)v!x8`u0LK8}=HGo|1mG4K<`!ZSZs)zDBS5%O zq-&2!r1QBTJNWazwa1z(fBg4<;RTdcE(CIli7Kf}s4|m(9s4{mA=mMBCSA&C1#G0C zF^OZ+Wy@30Pp9l#_rN!E$XLd*lwZl3|q}BghS1029 z37}aAl<40jh5NnIlQc+a6HP4ZK(m2OB%fgzm^epaQ^1(@P9Rq9q4qFJsEQ>O5`q9h z6oF^PfYG!B1cIv`ga!3BU2ej-a!^t*i>?dMUHAVC;IFrZCS&A(w9KpS>Y4GwTk@fYjk zSbR+sJO^H?srv!5^nZWjF*jam3 zW|TaDW=MMg$;ar_TW16SlB5g4Gw?JyObFUP%vjWueFP%}qhSssVGdoMVm0eQuC@^5 zLrhG~VRB~UIT`!+gojDr^cf2f1R;9u#-_R2#D5_qSo-)!-gN7`KJfXWAHZ-8*EzD@ z{lQz(kAC>ZzYd~YHafB4&ksKIjogk)uS20U0tjU=XS+B%`NyEv7XV>_H3mE@`akDD zl4#Ig0|3T3UkFGOqb3EAWor5T9P!R7DRKl#wQVqzOmA*G92i#@yCR5$8g5dv$jFvHQYzy#JQulYd;e zBk6VCpD&NTqC7JBru)CS8&_QOGsxvDt`^ADw4NA>f0iK?s#XCRj6>#WrW*?angxiW z5;ktV3}F;w-?#rAEC{i(cm$P^350P$xubi{2W8AUzC(Ko!PXYa@VL`%fU*GN)0-Qe z{fpmoIF`>>NAksy4Plf=uhm4a(?qY+fW#a`#zA#Mx^(g&vNS=fwel(6XW1l)w1 zh=KTP%jh>lDh)bFsoAPTH^$cDT3Wrnt*Z$@h@r8sFaL?9@|)Kqp|tMA4*~I+AU;^& zTm=W>0ZsCRDchKq1o(7YGnfN~mF}8pI=o0eD~-^vf!g2i;`g8>3W5*%F&HL;`PGyV zfDr^V0#8%T))h7(zyKen=TJXNT$DJaHWe&OQtJ<3<0idm1Om+tPU|3~48c!6EJf?^ z@Q(Eq0RRA-^nb(ki~<3toBf&C8lGm#h=jVLKnmY{!vO`-)6DZML%-8QrepJrjt1TY z-_Ujp;-)r0SOY&pnNt_G@*nUKcwy=IQcDd2hqgkYs7yz?P~GSo7Mt1hgj5U!|2Pc9 zyin?NQbO3r2*J_st)kspKy`F8l70j2<|%OAL#Mrjd~pnf1U9GG=)sb1PZ^TZ04M&?l)pF$Mpf9M*2e@#ry zApvNDDFJ8G{0jluZrkU!_i?8aRA1LF{bL_~(?{dw_zt=0!cuu;>godzeyv=a+Kicv7wO|bA+tri-&8ntpt}Wo?(FakiRCRWo=zh<8VGwnKF#kZYH2%`HrISed9cCrF^3|bXjDbtTLKZ*}sNtap%9#WN7l^>D;kUCh zQ}0Pim0Cg>buo}4)t_A(0DTNZ=71l*0pBwP0F?B9!}V$dgmxAlXw+ex{i&`u z+(xD{T?3o*X@0-ixG1Qj85y+F#3LE4q}`y*<|5GV*0Hp3zk-ol^Pq$x;|U;vTwxTY z%ADPxtz?07uz;b{XrnSdVvlRPxq?&2_CgAdc4O%w`Ge0^m(SHNA<~zbNvm=@6HGus zQ0M|D{`aF8+dPYY(m(eB0Qo&W4*k7Ssftp$3fgI%pD=u?P^$hMfV+mf-Ea-pxwGE= z{x2;4%^$w?=0bJ+s@nACH=a1T57QejLZLXS?yh;8}u+neB*kB?wAE zSpdQ^NSWDm0It)Eq$h_|TdeX0$jnrqQjAY-K@=Bo^5~=BX@X9xiK7SZ#mM+9CT6yQ zvPd=6hAu87MCKYh!85EZ9!0)T0SVe^b9MgiyexdrDSOgs=i>uYJ`2`JaF9CtEjvsg%h_uU#}M$R)3NOqho}Xm1DiGRSiRh!0Es#RTTP6@PQ`M zNHYrC!v)KrwBn^2AR#pcE3qHoRt7XTSz$zzwi41f>)iPj&yG*~1}mQOu_1Csaj* zQ|g%?GV8Me%PQsyP|z|I2ove;rF2mOVI4c67)gdbpusOw(<{la#};<_1W4-49Hovj zFmeFNby|m%mMx+_N+k_8QfC?{FA*-5_3xnvrA)p9DTfAtPXhoT&xQW@hq(J!=6qQO zk@0mAqJy!0?iw@n7w+_I`v1ZxfDlrf>3C707C9tV|8Fihg{R|YXjuZPCUNn}}y#S@PrO}e0zq1W#$tt}n@ z7a0YQ{7{~LPx<0@&;TO@jmH+y>$Fi{T|%i?8KCr?YuD?O0Rk(! z`>h~ej1Ts_RyAWK{ex=)*JX2k@L7R9&B~74=DH|UfPHPSIl@pjh z`Y@{F6UY@xRLFkt)4TrcdjjuqTo4j8iE<_I<$0t@6a8)*rK)l$?{!;PUO0kQV`Z&T zKY243S#SMwq$spN$Ybs1%1e$Nx}OS}AqZl0nyU~(W|UFBwtVEvozBXCZPk~)_MQ*j z^8A&PNihb|V<0Wips4ignPR<~2{om})|irLfXX(N=4qUN1gs0a0|JPNqvq0+s+x12 zShsxJ^h;?~I!=F2-SY~k(U)9;NU9mSn&NJx3$C5F)vKM@d!~@^`+p%cM&Ky@CMip5 z7OeVNq2D)mk{Q9B6hIqrQ{x3->S+@JE~Qcsf$UY?@U;$Mzdd7@TGlu|S zy&8yjoK1frq#Tf32q_fCX@CWz^`|Z>P-?J1!bFm*W6Qa4APQw}7%I4B8VhZHsN^;b zQg%UP7gCBAWc|0^^?|?s>hKQr^Zd>p-Q6Q#;Hgb<%=)lYrxJsIg&>M-Jwzx4sFoT)y=N(% z@tLhl^!pcD1563S==f&DSC-LSUBvv+16W;HMB}lCaPsgWNFgycJqyZ|fpDi?N3YWW z093~(vHg-4VrB7AzqxvR@rgc?PPdUI-4@B^stDse3dIpsSEL!zw1*Q%9z@b_qu*rN`;@O6qi$cA zdFY-r={)d;cmM4j$MQAuu}fab7$EFGsNwdjg&RE?a?La={GyoGfZG^9Lnctpx!{FS zpJNaBBmh<#$rq0)?O@#W*}Lo;r=4e|20A>{dkUb40|dxj7e0H-y_QP@@Xyc7bp90* z0<56sTgig+LMRzka%K~}{C?iRHqeI%`eS(C+F(3etqvfL<1L!CD?y;PBVc_V%1SWXN2;3SAmYE0s@C(L3 zjyYhI@}7iF)?hyi1uqEuJX$S+p$EoH#TYX@xHCO*0AMive^Q$W1k}qq=j(706*siN zO>&GHN250@e;eE(Y$~%+ImQ@hr5&TdP6n88lzNRY72wX$#6zG$3W!JsO}|kZGLBXl zNP7pE1^W$T##v#x3Y9FrZ`{S))LgG#a8qv?=y4ZjpgESBopC zVib+$DxfX`70e@)9_3_?;s+E)FUsW5%Ans}gor8-c?x6ny>kb4d;s9RW8m!B4PXwy z1)fr-eSJi#|4*2{;2bU_DK zbvrdYu;(7+S?|8N>3jcp^Ls!2hyW)89@_Wd4=-DP@;RptjjsBIeLH^8oZWXHTfN~7 ztUvK=RBAP(NfH_a250EzJ_jpDg)x9LQM5T;icJj7;Z>+NCNR17R4g2L2)iG+16mQZ zGH5R!Kx1eWQ5<7vWDFw{V_3ERWUM*iOb{8g7N_G%ZD{?YZk(eU;CVd(HuiO z-UNd{n)Wff?>_9?c?Y-WHQ{bAB;{Q_}}42`TgcV^$+U(zbu zuF{Tr<3-mU7ZGNPVI(r?0vA&txRjp&Ti`}^GbfgUgIm+kvP zh}jmLt%&qvB`Jgn3uRM|&_?+)%vPaFUkpeRrH-d#j+_-I#8g((&=wjx3#WcYfsKWEZc z#OB$kz&y>6XE{`sLdqCgs}RXY#;S8XYVQF9?Ewcrg_j~k*4V{wd@KD{Wy|R#4*-H6B5-mDByiD6p|Qp8e_BjT|M@{&iIL+ z|G6D^e|>cQNoQkh)d^3W73I0XT8Fsa;M83j7?9=UJ0?Jh#&7&|PFV9TPrxm8K*l-j za~au~G}k~>&iz}@H2njBMrmt6ge-oof2Ua#;RaL)d&=O_>OVBmn2!pqqABZV)3aYlTORm6Dk zSm3T{XN-q`_fd+>UZ#Mt3<}E@U?3QP1h`-z6XF@{5VDlizy*U=GcdFafZAkQ|6QPe z_u#Jd!~uYx862J`dhcc{(K5GKShSD;?Jp)~kvV66V@)}jo$9-ZIv63(dSDFbciLz# zErJZ8)81#b@hnCZ*CC?{RF)yG4k3ygRyV^W2oyB`Ve;=AXwHK6Daa2T(7<`2Me+-r zcP>@Vom0fpnYa`SO(EQ|pV>Hik}<~Vn2P=>01##L&>0P?TtVe2xQLMSmk>oGMLIz# z3syKEgRn?CMg^Awaixx-v9mBbxdBVFd$7DXjb3~4g|bpT8^BXqEA;vux2M-`diEaz zxEa7va@ku+_16v|@8}GDQeb(4hKLb!ff|>{jYd8k;e=m#23DVTBGzs=36*O7>C^ll zJn=sS0|0KTJv20ijVGOs9rxcUBTcVdv--r(0QmdC>Nu!D9bYvw^WZnw?c&18H7EbY z?DYK`WnAII<7=OcNrFSO0`b(XMk({sUj-*5TQzDZ-pm-A6PKAAJE1WtOvF-FP*?ptq!|s zE&;@mXE}s)MsY;QlO8%tvog=Jjm$bF9u@%TbY_!kWxUE+8(at@T66u@(*Az0Gk;&M zx?k>gX1_%`yKVE<>$Aa?0dP^<$wh76==KIKC!uxGNZKiM;esEUY1bSIh$4I5{mzX$ z58wt)%=v8)`G(x4Ujz`0IrG4R^X~kxe8in)p?XP-jsG(NV_=+t!|LS?sY0S)iU~LK z)cS)#0G~j?IbiH*Rc1PPZ9A=qbtKv~SxTd(tl6+bujUQZaxg!3zLxvd^JO zA-DrLX_7Vame%#(dp~%SO&>ij40P58V*+Hd4{JU1u?sG~DH&XGPaFW)G&np@#=X19 z11-!*+=YSS0)%txw^MflDRQxZ2K~+gI;{gplOD9{yByvWLd3|kE`*H1m_U}c(eE#! z5)VVorw}}XQVE2pAc`6gvWCXcDu`$p;PxUSCr4oLu^@JV5JG}tatj`X*b?EIY~v!1 zIOiZu&R&3pi9Q$uxja-q?PrWZ=enR8`2~)%LeJ$~LW9X61JYyxNq-rmW2de_iOYsZ zI=9D8L=rqupO}kS%uzuV)%q~TR-J&|_kRaUrK^RIuX?Hj0IqIz@AKD>UhBWIajkKQ zWtAX?L?k54nkJg-CP17ZNMqHr*5l-#J{zMGQ)mtyC)58!Hvf+R1{|vKKg9QjnxhyS zpMsv5t~a5t_{_)N-TBow{n<@})p1aRI(}-)dp?x__~bubyOlRbrvCem?cdmN`Z+H{ zt?>lcM<4I!HN4IMEF|;@=^A`DP4o9ptu39_0rr0C<{1HGtO+sW9K@~38H~M`b78+H zr3kB;F&1p^_m^?k_dX9W^~r_V``-KJi$1ydxQ^Gh>-K))FQ=}k)`mCtyUV{}jFvm^ z`!*ukz}gd@84S;?=b@Y43SmtGLz-|g8MTv5J3Ih$CSe}%C>geS?Xb?R|B?^_OfU!; zgNq22+EB#UBTHcGjnT>a(D*tj>$_Wvdp^IkxOhvRr@b_7)pWZ2`8RL9Y2ZM<;uKaB zI&U|?;-Kj!XGSNa4E|MqM-ujT#z{L_iLVb>zY1*t!3u_m_oSjC11%Z)aoT0c7P7>jwLk$J*2BQ;zVt{y$ zXz|}ipAq*5SKE^V0Q`r+;d!FXMB#41I14d+7R@%H+1Jhwz$gus=Fr;3;e^IHM!mio zoV7s2kn~!p#2S_QFc=8^-l7BLltsb_puB5Sf=DAzmeB9bqgoq9x3dS0;nk=&$K7*B zU`!&a)KIB4VO;bI7aUSbunG@p1yY5%aV zI!jOFSiSabfAi1R{P}Y9yby=Lu6&%B`9ng6Lsq-^K?-@)1w&O#Jb!AZEOq9|+) zT+}aV$AU0L1RLq10rbg2+BaWrUl70pLm+05^x9aQ*^5fGiGDA=$2`LH9{~E@F4%UH9$W=0%jo3$jH~Z5Uio>W+aT2K^xUyseaaO# z0OQ8dzMYH|+V1O0)P3zTr3s=FF}GyS4;4NGWX^hmZ0Lrr^$KkBl7-3b^UFeIo0s@4z@00d8Ch zR{#zSf_|QJ7C;6vMQk`@3@XnZ%fZQQ9POSlSm}*7He?Ktb}jHs2M>674+HKHM<4qg z*hwI}-uSdrCpBP*%Q{zGdodevM0@~*+kIjBJ$KegrJ z8`@W1&fe8%j*oE}|Mo-od=saf^&&J!S3UkG_4~e9tLO80g4juu) zBv-pgKthN+<5GqWiVMpSP|i3^#1WEy8@qRWAItN5QEfDr7Uy?;{l8rDnJ2vAe&Zj1 zymj@Z=Uvn5EZ$zLkG!HWwECTSn$~rmVtmz!7#dq^J&hc-nRF3>2wqU38M8WKqfD4| z8b8T&^k!a~N_vSzo~7ut7SQi50i2fetbhNZqhCtD0^I zH2;UX#j52+!)w=aHu=mvn_I)hI-7CNn9X=+%>HglI(pmi8XFVG3kP}2Qnla@FBw)c zW}I%{HlUVTZzVCDTOX{jzbr-Ot-MdOVA$sk^@7Qr8*F**zA?7ZCcP3XGN7=h^>ls; zDOxr@+a?kCX}1ODOs+$8c95=k#;Z>TDD5kluqNN$Ln|;6y!$>G_qI)uBEsMXVg)Og zGj4$mr_tA07LJSGyL(@S0FF4hFc$?wC?qEc$12boq#c{c(LRW*Hv#7!1o59)z!)8T z1$>$p4=DlUViPU1M+gCx?*dTJgG;|kbL44m9sKh=+`#?MF!{VoQEQB2Xk;C#^-+vYoQN##A+9u?sYV9IB|5EXq)7{%r9J4h_ga_tY#B+i;9PgP zdtMn9F*+#!oCgyYM zZ@cFyuhTnsZ1w3!la<2``pW-ZaE?Z$hP5v|6C{AiRqG&x3=YyyzvlnZfB^(a&%v(~ zMG-g`*t_fA%1~qE8HlR#XU`t_*IT}@T@6;xK@IBosatNlTm9nm*FF$e>YZ9+(MInHfzkWCG6G-l4NftO>~ z>0E&cXKW?}AO!NPi~H~X3i{oJ7U#Grs>-dc*8cDQ<84pQ+I906?xKIVOl&Mn!NdMh*o=1} zg!OfDa!$Xu40LsGhUq5Vf$9%Hxl}9!y?C+b3>13D8V#m>f&5t5`gwUNm1HBvc?1N# zy&H0sr{BI&XXT_S6#HVU(=X0ZE=2I+@(e>RgiSOkMRjs#gy?@R4B5y<1NtGDYpy-J zf!t)>M}k{VvEuUtr+&u*@J+n`EZ#f79xER9{Fd3k!h5z+j65VK_*4QeC0Hp6+_?S+ z?s0HZV7qJyh$w=HA_w4@6~_gvI0l9mVe|n2au(Ek*ZJ?g`dQO94p)e`~{|*Pk@MIpuYJ<1x~jI zLx`$X$fyD)I99KJ4vf~|YdHGd1*p7_nSHkdjH6l~h01cY+dIIRfQ+gjGYujGDQl?K z#vw!%)#@5>chPdmLmEJtKD7dAcc}ox?J-$i*oj_y1}f`f9}za3^wWqcRe%FVXGr=j zq-h&QYsjdAvB{IcxD0fokSFRRK|ld);L_ggnXqXEGL|bEv82~Rp7dI2+WF4rZ8x=# zkyGghk6_&Yr1Zh;5PxR?L^ntGo;k>&3Kr(}V`6IU@o{k;@uZ&~@o^7R5gZ~$aCB?} zC!BaXI-ONu+3e&@%2@Hdyf>W-*VKdU)B`Kxz)^Ph0Wb6$?d z@Z$({iDK~aF_=yl==JP$Un$$@`{99eG&dzJv~e3~;~l=;%5Ic$$v&3)FDemCZYOYD zija7w@)X_f5*B72!t&z2PL?fQk@RQ&@8-8&e^io8UjNRI&HerR&wtD6jc5LTRB61$ z^i+Le|3gUo9jsb^I%>5MyQgxEmoWrwbm)luu!Wb?7g*t7?zQJ$Lb$ZB2g?i7XfGas zh~$@-X1Blp{7bGIn1~&f%J+lv{X~2NGqYf9%1xoISu^L{QRJOO!vk5y`A{i1Dmn!q zC?o}tfi@cC8cZ$(cq9voyK9Qc5SXy0fh^?RQvd|Y$rt3AH17H#Pt!k0TaS|07nP*H zfdNq3Tdio^9cX7$yBG{-CGTts9+bSyj&(-faGHKFXY8jmG-HrV1|JarUW|*_Ln(O+ zRFX}ENxL69>J@Q){`iO3P;Ed4!K1@Z_lu}TOaCXOtl^;$U?>Na$b|#sjP)^5 zPHJEqm%u9UYgR#aT81%m00}UzZzHxm@Kbu6bvOpVD*(J~aCn|zf3YHamqBGY(rzEx z>HYJ53PMSj<|s+V8G~5EJnl?65X@_c3RZ!ie6teWUPytcT7irr+Z0P_r{t`N9pqd< zNC_!xh^r$Q8eNCx&^ko%Fl1b_+B;DJ1B2Enl!|!Bv`T;D>??s;VzCE|^{`cK-+xBAu062GS^#K6C z1Yq6KdJT5CuNcr?UdF^vY{K}|D%9%Dkb$6(Vrs6icP^^ae;n_ha(=(k2DH>^qf?Xx<|vn-0Ms5eHB%oD(E z`dJiN`hT7k8h;dy;pC=wzCjKYXWLO(RzNA{jL4d-g=8HdIHzZ64|{gpj{Up0!2*MIJNt(TlL@}*j1=ngQns`a7Cq}Lg3FYZUXH4Bv`h$?l< zrtp#oBA1oU0=;`Bu+756R_7U#q=lvVJ(%8g7n0r*xL{vP`ZMoIdW(15bnBf19r019 zn{T_T`x`GmJ7J>!3yjN(h=u@W_lr>+LkMo8sh!aqFHN&8?ceIbt4Lsp4AWGSa~zVJhRn4A9vRdb58mNg`EYH?D9lCOxBGK zX#)(7iGw1>kcIBOkU98hL?(*qyV2U30G1N8NE^r6r2-suvWWmpxP6LI$~D(T@_{u1 zv~mES&=uYr6^sZAURYC7FLR(0@Zmi;g!_H^J$i^Wbf5_r!b$=HgSTLzGAEz(5(lCl zjNS_%C8FeegzjIx`90VEaBy`!xd6b$gA{-#qoFEYXzl{clME(TRtMzb?mXS!8i?2% zx5`vNt*J!!XAWjG?jrXup|d>DXrgKa8OLD~P(~}Q2GG%wjIp{XBE*#%q^y9m3hK=X z42`Zwy)gyBt1w0(itE-xAgTc%^tv<1Rm(N;8e|k02ZXG;d{4Gw?}A|9Lg@AOBk3)m z+8D#g*hb`e7g^RpduboCw1YhDf^mr`YG8coOhi#5EEqs}0b(n4=nR4C7gb_#&d?km zg^VP+tvPg-=dg48*TEQ93kM$hM5n#*ty^xp`97-jI<$(^xlT74Ls*=j;r(v=)Tl8cU;2Wn+itn_ zp25a*P=h+o>ZX6YbK&QIV&cx`=+yJMh}Ls1P;HDLdOYhW=YS9}y?)3?_rO2-e`h>2 zGb^!6R>W{cGWZVp+-@S{_7xgQuZ`K62hmzOfTZ7=US4|WExq>c51+sFM>8G2`PRGi z-(7#(-7kOc_!m{yd$3Y({3H>tciVHk-&9|i!( zNV-Olhy5vMykG#he0meu9xGX7JK4)n8Eky0l-+b#pit}Ux0B=8gB16!*l>p>PW)U&&@9Cn@4dvIeYFKo1y!(o(-_pmWN3_{8h z9p5f2UOVrp`k{Gth@OxlYz~B!kdcItG2*z1N_7m4q19+MS0Szp0mMNjvu?qv4?{VU z{wzA}X$VoVh8{Y1i3Ai7P@_|HyZh1a%_6SUv1;A3(HvQ8(+g0nQ=CT_oj3_2V;d1g zjgV_fF8|YOusAFH1$@j47XncnA+0s}3_fkD)9hxVPVZ#ZhK?r$#HUEcl_dgsXAbg8f zCVf2C=MVdMd#-j{i-O5orCJ~P@=KpTHFwLc_YBs}K@I9St51LSyK}$%qLV(`>nz?| ztu=o}?Sp+^giKTklMN{&}nJ?zZP{=yhhk6~%Q* zlio8q7i@Ol{pfWTk)=JPNe4;Nfl>*KQBW!aV;qaKJJIVbVrKeY?Av(<7Uy?E<$aLJ zma=5|Oa1PF5A-_I?^Ahydds$(2LS9*uHSg+sVy)(kIS*M0nQB70dObX6oK)|r3iX& zA1!T+E<7zzn8kUsZR-(1D>UnVdd^D`g2DMe_zv(8qi36Z=b8_0jrPDoszfL_FkDQZUFPCtm;+J_OD?FiiWc<{to~ z@H6(u3n0QTKi=ps$QD=ue3V%b1n+HNEYl*2EZf$BH7E`Jxa&m%6UiM1Ke#K)bvWaW z-GFfHg4s9vP--U_1VA})QTw7&(;wV2F#dZ&B_F;wrYeBy;Lto7jRr~=E<)oSB0+?- z&AQ|u&7gAyaXyP#Qe5qw<@GC+-6q8XQufAz&?I}Oag?#<~-FI^t zS24Bj)FTIK;~1>b0QD0a2S`q1>((c7jS{(`0(19x8|N!5^Urw%F>h4NG!E>$7fTD% zh@u8sO9$q2HTS_Jnf>CHtvCGGj7l%Kpe zIv}#N3n3%-x$Rv{iU^(MIT$jC;wrSt(HxmH{m#PIx}Dj-Px}l1+UYLLZF%pfmIi0% zkES@M)R@**n2FQC#fyLzz(=8t2G`n30KA_A2&9VruipzYVi3|vVaeFWkujSY4|1$p z;f6`20TDUJdR8>ub`M=7VR#0BF$Tm4!o_NH&O^kW-*5X#xF5v94f8nXj)Kn$l@Aro zdzqC>4pd++IUs1>okriD)27&a7zV?1cs_DNKQg?Cz=V}c7~jZq3P}qf15z$MgE1?m z5H2M_=~6VGE?7hEvxMFO%*Oi}=f}l3jLu=WaQy^aS^^79gCI%bC8>fjp+B)Ek2b}@ zg9M({0i8jqodD$kM9x@zvoW1NC8GA=ih5$j4gmn11K`__U=TQ{Bk4DSlfOdNPtkAn zkaYV1D7bcd#4OyjjVUDt6twq%*t^A0Yws~YE|$cy0-|b+=J*hV5XiIK8UeaR4UUR~ z5~ZFw_toHz>*!C$ExcM8s5A>2A94}|5eWbqL>fyA524pS0IhS#xCS8v(xeS3Yv3$` z);W~wfnd-aT7}6qXQ5gfacF1}PsBI}bDu?f6w~Rxm@{ed$HB+2c-lXgcKXjaVPWoG zEH6G}QB)#y+jAX&e{SDHw|^i@d*8ZX+YQ;Vcs^ab>DdgxO8|Ttz{HdFyowB#Rf?Dk zG`NIdj(*jwKt68`e&W2BV&lnYpk5z3#+(1g;P6jJ+Wgbu&HoMy1lZcU=Rqva&!E-q zEY9>g@0wqpxo*q08x{vE=b#34{MD70pUWEcp|u-Md;Z6U$JhK~p7dC4XbfkZ^Ye%* zwIhB$-D<&Px!tfkW8n~$M%KhkyNE9Wpt8(u#;tdd*4B|*sSNw~-HX=ZEIRE47)rj; z>F#<*u6zG};kFx}QWV>(E1Dd-+(zHoCH8* zX?GU`%~b2dyBB76KA2~nkF*zd?b~w6%>&<+A5(qgedoU#V)z=yqNWhz5Yak_N)1sQ zhe4T*#MUA9PvyC5vbi#KBad!GSk z{Sk(T{x!YCn2a5qA*5?rxd8Y3eb*E4IIVFiu2ZNw9+TVF+Lf#8PC*PMd0Z-$v4L4D#S4+=fT;3*k$e#%pV9@ylW`KP?BIBZSfIPK{1=>-HymnAV_TQDt zVRVixTLQ?SpDZCuS^#mVJVA4KEwoNt6yYXBQEV9srL5G0Uq7UrIOo%qo(Ohf6wWo4 zORF#9kw9apiRM@Xa|a&8zK3pyRv9|Wb6>jut}p-Qg8^Y%0|1Zq^&>U^hn@OA5*y&qK!7m@ z`=@u}!1Qh?&L7;pIQOdae*elJ3|7rS4eI!bM%HKf@_~`zb>lJ~e(l1{{kIN{u9ZT>8yI+Hac;+Vnj@2W zXL)9pjA2_YzOg?z1An~r;Y-h}%V=t=h(>;wi|QyB!-%TuA)=}q0y7tXojV3g5zWUX z5A^Un%~v$;!pR3XV<2Qu$qsN{1B=#yOt6E5F*aH|Q0xg-1`}NOd5EI(dw3y57($h) z?tx(w=J~MF04Hm(%v&!lz>1-l-%qiS0N^9@tbw&10%|bE?Xk#J*vtE9Yc50>ig71R zu)P5R&g09yQTzUlbLMxf3G1C@8+6j%wZ9lfdM5D0*pnp{1LvYh*N_6rtwTZxh&ZzB zWu;-X3K9lZVrN*BKj%-z8M0&nTFt>w&zT7(2`K+_P3iyHe9<)vgDdFh0RUG3c<6ujS8MHXiXvA>5*4ss60^yw33z%t{sj`#!m_?`d+~D#SH=BiZ}l z4=^|VAiAx&*3#Ub*Ztb-FTeS?*+g!7_9_4$1n}!mRJKC^dOF9xtb@!bZ2HMlamvq~ zg{f0FqB%N-lTUkQSh$b*<{ytV@jnz0@F>myV~7YmED+#o@17l4T%5~O;-9!{*Y-bp z!@ECzV6bWqYEZ{-edLPQ)P$7JJ^5KLzOpeiex{5nyg4$3lg|9IBo1z+HhX}?X%leq!dmok-r@hwr`wR0AT$!o%jyzrd{N`=PrWxLqmz~Q1 z;DT*84D|d@;kx>gbGZTPmFB6Jh-ml?M3`g{i0dbUi8?qJ(0Oi~UTv(SzhHLa&j2YS zfB`CVLn+4$utPP1P9K2Qiy)JN^E#sH=>TgMjVD-lu^1$UJXy$C%a50}fyit|?~$^dO_bgs=vCF815M7v?-cd_scV z$6Kwx)}}D(^Xo+EXMI0lJWId;L>kOF^$Q`L9D&?^-wqRn;6Wy^BFTgtxFH0zVS123OCMR}Z_(Tyn`JuLbav zgF|yvP=GK|_YJ&Xc!Z0rW8j6WuOZ}VW)lIZxF1_ulqoruno`Cl0-c_;n~?L;b5g+) zD4PWN1c6|>L4|2Z(&<6vc4HADLRcwt*SQY!;M@slWx$z4Ty3J(m_W5Q0wH8@6fNRX z5W;%=qUqg?nO_7;=&lD1e8gW=i6Ny33v^?22ywL%3{~Q|hW6qC)S6>azq7dNXP?#h z+$~?&-aQ^pryG`Ly629qz6rp;Ib*;R5v(PT90?Q-^&UTCJ)ZZbmt*y&6R_dLQ?Y9G z2DeE(rZ2w3H2-*l&HoXC0Eh1X5yutux@`fiPUlgz^Rnl!{rXJbR|&Z@o*s z;>D-!0qCA2X}1NJXC%E=HO~?V8KF{p>~X7%bBJoChzI6H9H8Gb01Ro`!@fP+v48Kq z$kHCNte40*{^tDLJ%7;7XKp?S+MVeVdY@18v@KoLE^F0Jh?LC?#=uC;xI( z9xv^M%dUW7Fjz9>^ZRTer5$)N9#Rjal!cKXXSSI)I_#5!<9{$2l;9`~3Ty*TVL!v& znqqww+&;$`7?Zl6@$s7oNdP{fEc7An->vSSKm2&P$VLxR7}JMRGtg=Y#v~xph9UZ% zF-uoyJ^Q~mZ~f$e_WvZ;p%?()9smGGqxW|W1rd}|NIHFVm)htpcdT=Lr7+*~CK)Qv z(QkJxRmpwd7-RK5WwR1T)A8AxVNoMOb*PT060L~G@r(fD7X{~L>UBXx6kY>h$dV-J zlT>a|Q6UA4GH&Xw0kZKU+?lTgeHCMNvBpa3Q)uK5qLg#agZDuB*fGu^r3`V2oQo9; zw$2rXCPvX58!mEAVc7#aw|^7+9=ZcWCcFDPpMMhrZrHr-`s0cQc%|9KY>8C?t6LWL>v446O zW|o&`7qjlKEHBT0ck{(J4klTH8q{%KAN|wU4y`@mtj%LnC%jkdd~|eTy;ytFvoJKe z3NkvfHCXlf$a_8L)J6_xX#%4ZruW=~h1tCX#_~>k9+hgdo9D}KotwY^R-*pwo8EK1 z9{eT-_2a0I{K@NoRYc=|z{SYRNhh3%CK#$W0Re zBM>CRK0yQEfy`P4EPRT9jrA)exIk&BCRV!rb16&GgAyaw7;q_zNKmcq1YRjOa4Ze< z+~AN45qbyfa%j`R{NKG)Af$MKK$IiPc7nhW^No&0V9iC1Hi1d(hl|1N(0y){;}IEy z%2V4v=p5QCLL1B20E`A>3&wOlNYwkA^SA!P%-{++I(4YA-cJk;%TYjDSV6s)OrqMX zLqrlP&5) zguwr#_7o?$<{m|qVU`yLB1C}}1OS2rSXAVxmK!MU^hzEG3Farky2O@o^ry0v!E2(J zC`?nl1FK!T1gecX8Y9gW%|Be8=(>~7!P5Lb^t+33RH>brC;cjb;|c(H{f^sn0RMdL zrf2^Fo%{8m1~sVTxZeEVKGDANvR8d*?!bdz8K2zv{7SX)Umv>r>nBgFIT?&| z)EXlgnOKJ?esrTiS+7Cs97(r@*5U!|d+07SniH7W{{Ygo{as`7Yx>FZWUA)B*j=9f z<{K~i|2@}!=A(al!Cnx*2#_y>?vE3Cj3EUj%V4|?E+<@^odM$p43V3% zcR-Xur74W*SuHzC(|yW7Muokl;M@-J$@ykcVWw>um2T12HQ#7$Qw97EspMi$hV0-= z@(@?;bL%NQmcl-pPz?CWdxKzzSKb#8Sra{GibSl^-h&Ha%@5sR(Sryic-TV=A*^Ir z<>7gmlN_Mr?r&ZHg_9yn=q$I#$FUR)5tLeXntTp}4j2uGQ~>Vw?t-~wksxyrVQ|U3 z_ZZ6ou0d!a&s#90!Jt8ufN{|$V{X!>^?o4VIcWZWga7~$t$(}};z1n&7{ED%1URo^ zbj>7|_Rj|mkk=*|r~j9cw7P%i>gnD3$#^$V7FFJd1r308)b;9KSU3aC&>$&y%9k3zGn*6Npg&7o%v0DwUa>giDzY`Z=M@b4eK^wr-tMn_ZYPJ7di z?O#7}Y;t2I9U7}H&+o;=>XVVBR>3whu|Cjfy;fL874$ocSeo01nTPH}ueAuBt9GX| z|1X`++}P66u6JpZeuoA+`9VG9K(H%+aP^a{FyK9k2&=W-tZlu>ifW4r>v^eUCi zGLQ!8G30#(trGw-jOx2dbp^(Bi1BKRfqfY~K7$OM#$^>E8n(A#Z9rjy@1h0`0&U$G zXN1QYv`Zjhj29YpqgG7enJCz-jB^;$D`M8S)7OkZ`X}!Pmg{4XR|oN8!CfD`*9X*!2U7Lc)UG#3UeOAWD$w zE(DDs!a9H$xQM}-aG(PVLqVG&)`vk41Pwri#1cXdLLXp~$Y7RC@&%3lzZuiLX3H^} z(sfJ&004e*a7cbsD1iMxu2nERHG<`trGNzLTtj79(6MW6699r!rh;<^HD&Ool;g?3 z!QDkq&P12Q{dtM_qXFb@?@a^4h=ZwHH1E@Krj`o;z+%JWuD@&nCS#>$T^t z8Lx~`tqq|*G=}B*eLm+NM1;=r91Qegp7+1Dw7C14*7Cl8Ho2++Y-!8IgT{YQPtDr= z$Jc8BKfL<#SMSgy8pKpZ$cfX9ZoPqv<}WcGH&wpS6QVJu^9~rRkHQ6m$Mp1$EsR4MvttTc))K8hdHqZTHyL z-9N-x6ISfExu?^kV7}TdC=0QDK6QW*3+C71IRppyvRHEaa~}uj*|voO7+~bs0me>q zeN>=Q!GMs$9)$(@u+`(609;Txo(~Ed^Dt<+J|zR06oecMHE;+>(S$JyAPGhlXx)KP zJ%BkjF{J=001}K<3}aCWU@w^dq*9&F8d~_?=55z?23Nt44*(b$9FiYRamHb|)zDWO zbwt%3@+1T2R%dS;ci-qcZI3Z-dR`a`T8Ce=!feCG05KQ+qcaT|dD;*U3zKkEp)f&k zlz%P+@?0V5_QHE%1Q<^rBE4dPTiMSzP{23$oP#uha}6$K&`ud+ARGXJvYyEU5W%a! zf&yA=G)C%R+@Q6%7rZ6WZOx)m9me?T6ToXC=(-NB#_$B1Ba>K|*#)DOa**b6U22uS zsCLriH5`9&09IsRxYq*f#z3+}&Kalh~4{hFhosYg9tRaIsHh_Sw*R=t(-CuWJ zdD*MKEcoJyOg6_rG^+XXPZ^y&ASK&i^7-o+RA1@DXvP+Pck6W-0DSn8*IZYxtp61* zYOhn-e#nRc7=zXZjF)fX-KK{9s_h?wN@lWaj55>x_#1Y#3~rK!qn= z+FPJ7z_#-_9Sr=6L0uuC4QW}9MPP?~2(sevUY%y25fzq#PV-;(4C6w;XrDAtq=_-c zV3YzE0y2sMonPrW7}It887krmAwevGHYtdDU|fPofwMX^oB<;jDItwH6Mb#e4~Wz^ zLH)0iNtTpZ+N%xS^Lv-vI50f^G1Q8ViHL3i@QT4*@dAkOU6NQ<)0R{YGo(TnE~+(Wao)yVt8UYlx~bqR3@(y3Ei55u_rMj${O2S7?BTw5Fc3hGYD>^=FJt@m??FWI{Emg0Uwh3v zKlaVR!a1lxJ$>t{%U=~Uq8JK&l4y=iZEUD49cnMn>@)5L97%wnwE}0w`v6$jpIgv^!OqJFNq!e{Jqs`b11CV<#lSwzc=c2U`Evkk z2v#34=uLxTRG`t&)Z1%J|2js|ZiB92OzhNo>+77-{aH1_h422YX*np zN74UNK-}PvIwm-xN`$1-cMZ2GCg2VXu%0Bw>hYdARMeD$fyn=N2OlF#Ol*9 zGQJL+NACR)$mHlOwoq-#xw1{$sTeE<<^jp4c0{NB$zozAuY^oLj7bLA!H zzDK-Z)vb*OhyHf{o}Cj63=?q;BeH@9MdDa`eJQb;=v5`;o;?p$1ZQY3 zFQCyJ#;P?Nk1-&C9{%;AO#5&s&%VR301ib1c*N%aQTzZ7Q$s@|c*ZlHi~H`svtAR? zYp%Kg_dp20Ij&C&04rXf8}1~$Ecktes6l7Yr%PU3j+@}#GY_(0ovRT0%{c>z zK|lt1gE1xy?u=3(QqabNA&fIfF$zOn7|IS1k`Efw{&OE@dgj7Qt{dq2pQ6P|O{oO%Z2;#C4$ILktGTy}jdA+^q}@Z( z?IUUTkfmwRA8F&K`v{tMt#px#3bMu`+=B(SS@({hM%m{Vu|!mjAtK?-@``4JaSoj; zaKRxWiL9R@OHv3aT{BHkdF~!-7a-%K2T_2bx#~fwHl(Z|&%4O8E`+Q={r|L5y!)qMDEJ8%BhyZbw5#_AB5 ziW^oNMuY=-7m5KRXKd`8^tzvYdt9kcuHJCQd3kGQs4CeRy1T$@wFaW7f}xQy)ap$% zn!``=-oM=7KbGl#DfaJ(r~ij&{tp!)h{H<{4z4`UaNm7*pr0n+zHfH-@12+H!z9E04WBz}ycnyEUMV}hb`i~(1V1okyRu2x#QSMC)xyGGfw3PuQ?H>B= z9{TMLvVLYW?m36i8p`_skb%l|&=q;QvR|mIqiLb#VS)!!K^aTL^=h$*IJZ-eY-*)l zT%ctDs4Rz&!h!>C!L!+<%t;gMdkW@&oMC4F_h2Xkk%lojseA6EmQwF5{HkRgh zqP4gW%L}^zX3+00Lr96ysg2MozwN<0zw#Rd*1ure(=YS*qnG?gF7G3)^WNIueCD}qgx}g6p4wEck2ELOp7OqIao>1_<5`S!BbE}4 z<}fy#a0(jDk>E`Glm!4*e0_KmKk|+G69xee#T;1qKIk#D@k9noOY@kU-H-Y1@~7@U zuZVH^VS<4C_m<^%g!Am zfEdvk#Q0vpap3%muFnTY{qfb+m;Tl`k0)t1)HE~2ZJ;L48(KfY8J+HU?{yc zQ@hUFyzPd?!5MY@0RYc&0Du@AmZRL8P|+wDhq!f@I_S51XwNU%_`g_!O9`DTs5}oE zAe|`~BA3@`9XxG=ZVv8#LSv?L1s(}h>NN-{z+Fs-_5gs7*kdd_m(4z9A;zQ}`Nx=# z`LK%_mzDz6TH1*`YgzL+#!#(}BZ}(I55S;4GzuaO#wDbT0dmfy;Z&qRzv5g#NP+rL z10t3y8Z@(rBd{|^XT{HA%sMpw~;1oOszW&-S#}R%5Q$~?ytV%jqm#S zj;G_fch%+RRt<53j^ATtWHT+u17dExt#;r1n4w%(-w=91rF zf{A8*WTG)PvHlftrS`tb)hCXn)Az`U@d-v`P^~qve&Z>Cr>8wNF0zMzeJJ`r9ZvgS z#A^CX-XjA84*ed8R$ilzSo~tg{c4InNMUU&o|3m=4+cRoy zt8QXGRh!kz*;&fyIvA*uu`G)zMl2E@iQU!7#uubvC(%fBHyL9p&zSr+80&7?dj0I+ zXbx&nPfmUOq7QKbO#s*gU;{wI3~Z7ZX%J?>&49IO z**o5z^wQI!n0MvahOg4-Gqx%w?!9p9jRXK!U-qgY0yY8k-<(wU`vm&S3%1=jkas-J z`pEm<_yR7*|CY#{W^bzt1=itOG&L~Uqu1(S z>A)g73ripa$XJ32OU*aBaL6|$$A7Euft&KHgPL>eD*(q3V4NeaRUj*oV+~PA5@3Qu zD+S@)PtzoUQI^_7ei3r)0_F_-3djD!M9|Xv0V!o@acr2NeQa1j-E(NAp|!G6ETzQ^ zV2Eomgp`P@u`@|w&WO-8Yo^FQwZ@0m^n^KcK`sDoa!4sLGBp9E`nc!&{|YXo-hJP9 z{$_UH16OR>cK!aR`Ef-@IzgNw1)!1(vojF=_2XWE5l7nvJMbYd`J_Y-Q7r z$7ufdc&Go5784l0b+}l`WWZW|BnxCgDI_stH>Yxm6V+`0Lp8wWSxOY7|mqeOv_NkYM19BPSd2BpF8r4FL{Agh+@SRWU0zHm{MR)jhl_ zr{gonzi6iW6R63>3*Y}w^Mj*3s6jpU`rEhuAI`_bIuQK~fD?&f%&Mqa9SpJCg7q0_ zk-+8w>>{Es{>~L|eHdHoqg!9{cD?7D?`kh6>mv@->VP6dVi4ArXGxv2qoF&l}S3zwqLl)!?`C`0DESz3FTz*ZsLM*~@`A1_=Pe;9>+KiU0%0 z1}OCLe(=PY+goymEJ+IKKsgFK?9W{cw=o6Do?FenH`LZ<8d@KKj8-9zH-dA^xaC~9 zy?e38U@nr+J}(c>{oHvBl&AcF_39!w%p+s>&B9Uqjnbi42zzP&JX$;Hu!1rR$jvN> zauC!vm0tMI=WqRg4-U?v2rHgwPec`Y#=}=Apr;SOLzp^GB%Kx(2QjRd5{a0m&Z1Z=8pEZef`m2~UeX{YSHe}C+9&fFr&wu;O7`Xk>qbLPyMGiUZ% z-}PNfN(q%{lM>7RfdB?$3S!*;mAOEvG*vXcD4F{S!}?KX9LZiVboQu@3DF>1A_-$H zAtKW8A?TgES7ZQ^ zRLzF!=WdUS1#LnIot7XIpb&tVhoDda5uw|RP#qY+y7OOx$pgE1|M03yjvUzaueaQI z*&SDJzWo^|tGi~)&beE*ZoH%ZQ)4sYjGcR!D_PAd%7!I#}6xaQZz^;Du6fxc&Vjj}#Oe zMcKRmqpx}KJ;C!vZsQXBRk;{mef@3uNJ(CKE%)Ah??=ap(@OxX1)~uF!vq>6q7o58 zQt%X%M?^7zSyEsioGqnfpS|uA|M>b3yv>p5+qYdd6ik2piplxzs^L1&Uk6%U;K-a} zqOtcv8d$v^fFl4D6W>q?nS1GoUdDkA9ij-vzO^5W!b! z0!k(zj6o6gTxYE#z8e!10zy%b%1^JiQ(#XXrTw^)!!#{z`Z&xMhW<`X6^++YF)<X86q=AvW(zn8fD#+`Cu^P}4U=gu zWP1Locl-9DD}^*tC!3Uz03diihe#5%8ckHnqezCkm^rd{b)`0VUaK+nrDdFypZ0b2 z)}0E#SGRAy{F`MK6q%wA1t5T_?i=3oSI0aizw(>gfBf-nGq0%*jf~Frk6$`8w!S~| z_{Dy`@>1gDPtDDs-RZ#hIOc2p=pP&g;~s*bU`!}a1KYO9!GAeIU{NH%(x6=(W7`h= zFR{I)e(w2}EPDnbU~pg*&E{OS<`q5^u)@6nevp5BJ@x9=^%oL=Du8nVoJYVF0DeXT zi{4@`eu`($2=l?sP~u+C$c>Fu$yB$TV7ZoDc|5?+IygG24tbnlyaH~ND| zsju*@n_mC&{RsHK;GFt@F)pJ`*WH;bOY(Zg*I!)shkl*P7ZTLV0IVd!N`OX*Ac)uu zF}8<*rs<&;0TiTCWhhht40w!}l-I2Tn04>j?%o%N^OG+D0PX>$qBer>uLDKi^ddqr zyAPYLyHf(VfBTIaZ-l~?0A3EDl)pNUzplCN_5{FBK6c|9e+ztM8YsOHkZYBiLJ|uw zHULn;fMo5pm3GaI0#@-X7%_=m=r!1b^%5}d|4OgdZBkbv4nl}2Fcu(=LwMd4g5o%& zl3>O!z$$&o`3D-gtCHy&oG}-jZP)t%nekuKx?`jpW_E#LeGWioZEc%)44?$va00QI z0!YSEMqgJd`rWr)f6KS?vnMA2PAljKGLduE*)mBojW^{$rOxZLF&hjb)?kq_0{1;| z-(+rPK<=p_F35$3>N$J?DJ7y#s5|5yPcJGKC=oK|cj%ETyICPihGZVgnUok(#5(;; z%0!BA9dTlf`~)Mwj23{DG5Rwmgpg2@WpYdbDHCH#NMPK9gaU(f27UJVYB|4&kV|xQ zih^=8Rza!gBucQO4oJrrI2dHC9LbC{_BY zKD6?ct>(-Z0Nndbz5s06x}yuA`*`kq)t1k-0qnkM>uW!<@8Ns-=&Ez?f>O^}x&Ffc zFHzo0LoZknh7C5eXBR)P_aTg}Sc`i95X#j$d_OqZX#Z#kf9YQ@!thJQ_AS@-U$~8> z!2dD|fQ64i+1u)iQ?*({t=dnWPJ6|QzTy9Q^NpAP_BES#9@E#QAHfcKb%{92%Q z!M~_z$!`~ZTv;;QBXXaARUUx2zWyc<2xWp;O0;FfDNzI6!|efnr2Aaj-HhS@@2KzZ z{Bvi-`_G#%I^F%nCh^;5W5D~@1*nI?= zBO(C>ZaBIGKnH|*u81j#8UaE9oP?@a0^nmGcui29`Rb*!LVEo*V7MO;0;pAi>HyG) zAPsr2_%nL*&c-dK>jK{@p}8_Pd9Jgws8w*L;nn_{|S+Ip_G$QvI);$ z3nJg7bjwtsDm8ev>s{OXl8KI-wv8*5S>ppNZ3IXKCAtuD4pL5=b-VzP2Px-4v?4?3 z>L_g}a?Lez9s1N1&|w^dcgQ{@XMoUSzyyNKti`p2R_e%b&vV9xQgx7s8AReB7z$7- z{^M94`G}HH?j@5G0H+Q4>&}LA=2Q?-Y{0*8Oqe4FgfxKD$Zr%tB%O?1#HRb4Q3G(F z>-=~-hklaCi|p!6gJ+5P={dA!=FypN=|3|)%W0phR1%OWAdpgJNC8U%08$Aj<#9xz z9Tl)3I`H*)fe>0|?|IJrgFFr;^s!B%Ow^!~kW#p;Qz7XtVd0IvoRERFGxkArRuRMN9PnqXLqzv6BBhk-8i}+A(yKBFO92low_jIp*)gAA?@w%9vt?)aS2tXG zH}^X4;C%4E6M~HZR*K{iNLd82GNkB&(HMw)5aTW;P|xbKRQ69<_k88L?MewK5dnxH zRTEOSAY})PmEi~DGg5TxfZ|flK_m@$ybMA?uidp2*sX2#^*mjzkc}TyhBmO{wTUo3 zSX{3`WV%L%72O&ouikHgC_aoRnE+!&Fvhz|h5xK%_sdsb|LL4?$_aqef%}z0521P;UqIAOVhGrRvu$lOtxFDgmj=*JMa78f$xm!PSo?rZp%jJDJjvK zX<+8S5iQL(^Y2RPI1s7QeFf5ae_AvuOiRoe8>UaCk|595AY3FGAPYfYhSAg)G95=4 zcDjhVk?H8`S$@v_%={5EjHLdLahArL*!@#_9!W7x4hSLONoCAM1mZ9TV+{3?0r-Ug zPzrGrBZ(3)rlqX*wQ)p<&?JTw!W|2phpJq3N{=(D9fL62Qc{9*jlgP+{?Yr(+kHUCy0TJhV#VE;?wqf_fKd9r|Ko-5LV?B;qhAdFWK_sYU6abkyL(=bI&N%!aK)qBMnd!DR-1>nx zJo4u2K9k44J$V4X2jG28XrMUz&g*jr=)9hO z^*8VRvkLS0^8od7Msz+g7BgZKL};2JQ=f>M3NnW71q-E(as&|`0@x!2S%kt`5QLJL zCdC|JkK2uNhU;?8Kp#-{fPK3G9sq0B0SAu&Li8VIM7g=&DXw?C?+yvz>o>n|<2MLJUdDYW1y`K#H925a!Oxw zTN}?!1PGDAAO;g@6}5nnA%vVqB4(kKR7pH@P$Il7N~Yg`&6b^$`5BTE0H+xF8*pg| zfFz6&hY^&Jh(qR1a&2hA3|N-V6`qVKoi)L;AY7SPyM;zumK#veW_(GUz$^IheE)>_ z1@wY{9la-oL=r{lHrs|tRPL2F&Qa)$_Fq zzz39M4k$CGM*yUma}tJFAtUiuQkjdFRWy;4Ju%L}IZrc2rG#Q+R0;}AX-89@F&K=) z2*e1r!F~jVz?qi7Ncg2xP;s0l4VYPf_nMo1*88bR3g)q%&X~%`uZ2h*PrJz+_CInD zx}8~Y&Q*P2Md5G%=&dU|t=Xwfd9>O|skdzT+vpP?y6k&L_TT@`q4BexSFR0SCaZmy zvastln+I2RI!#_KS5c|

      JRqoO>tqT5>{fcU1ZRg6@CMwwH(q#8I3F?QOF}04Z?p zVdcto2&1q%8i#+dd#-yQfIazHc3MF{0XQ4Lo6Ns6p6E7d5xiH6fPa=J%9>VDhA`>{ z|EVq@V;8FxZ~y|2qs)CsrO-&a=*YMrk91yKU`%$txch~&&)Zk3mA`V+ue{=GY^d}d zIqdB*%AdUQdP>))Zus+lCDp|Qbrvx;#)u{vV-0ih6$F|mqJ~uJuvCDA>L{Q?3R03f z&=TQ+Yq$QU_`B;rLcU+z3#n>C$>}$2yS8l~W2`nc(ryTUco3)-0Y3n0HK0@hk_nP+ zTJb%lxs8HJd+o z2*B6=`a|!SCFcDPK&@nqQP|xF&mRC|4BV@Oh?~c-hFmI>0>GebhuSDVP`)6^$e&dRScjt@6%u&Na6%h zJ9H)&7PMNaf3{0)dn5~EIkZurgc8c+lxG%A*13Zg1AXpstq3qO`6ucVprk?)$7s#Y zyC}c*Todg^6Ecx5n$LpVBu~XV(k9H1%I0NS%;&>hh_WT!`a|Zze zYW?FP4CnXP`iJhD*mK|aj~v+bF;M*Arpk zneQ9(v)I3Xck6I#?$i5b55N1(zyEjb{LDH%^~v=YzL0?10jzvHAHKcdyvKL7Cply3 zZocjOQwIDmg!$<>fCK(SU_Ar_GKvBHyTl|90KmbpfsTw(G_>!ql5?c-L`t?H~MW_S*gX3=-KB3lZSvx4S3)oV5T#;cc1#X%Sg!YUA^^A zm+msP14TxtDT%89OaS;IfHsqe`maO|&`wf)Z0jY&y#f=;8|VJOFG?xa1L_>k>gN&# zqf)lJj18_AVoCv?gdz?S+L)VFKoA`%yYq|+N}}^!nauq;F~3g%N1&n~U3J~9J+k_b zf8f{F0$AmF1Fz>^?OH~Kl7a+~fQZBMYVf=PFy?`IB{1^bx|}g`%}~lX5!&Q1nIsTN z1QBAOCew@s`xDXFE=1>3Z{PB%JSH|L08V{LspIFucE`C`iYSJZ zX>^?J3fq568Tb*UW_U!@yRPoZ!E?{s%&(_^vod!A!7F&+zOPdRh#emhkR3TNB@%&d ztBuZl+o>AjFhbmkki@YbWyo~WQ`b(U&i8~&Bp_vs5tYmHv}Az>&zc$Jfd{`>fM4*< zT#!s%^ra>ggwVH-x=|0{CZrw$X;)r9j?P5osd1q+>H%Wlfd|j`!F>;&iS_fW@gfll zrGk!0G2q>TeQEpwM4TXw6GLz)C<$l2q8y+iXNYKt5lw0^M0 zs=v&S=3j@nU9VRvD3vN07#>5dK5$|QfQ3NZ%y?OSvA_ETNAuD@^)z&8PGc)TCJ%Mk!J zT2(DF0PMAivbUq2(}ut@x1!9wm|Yw$&=fd@>5}>bg_elWkqPD!of_zu3;QCOlnX=U z|CH-$x6yh1pV@T7&Tf8IglzrFr1e2=r|bB~=1Lcaovq#yyBR8Ze1(1XlV^RN4Z zYuxqqb07XByW)4=@|YS02R`RN@6kt-uW_a-7d^`mYZJhM!#v*8e%`GuTD$e?%{%tl z+t2R6Dyi@aD4Y+%YXR(*3LhrILsDUS z1G{j`lN1ozc^J14H&GnUBu=UxgEilLcrtZH6fI$ zWvyf|&q12;2qClzAcFh6@}W@7J;f2-M;{D*6{+>twsPf=vCm5x^#jrN zIG+9S+qZlsZ+PVd!090Xk|;*l?rOj19|mUrve4W*FjP-mKUN@d0bG712s zIrQ#+2AJ!vcE&+oWeEXGJftH9e!(}h^vCZFU>{RTg}57`IX#D{(?!@0-CTbXCrF~W z=lR-E2x*fIpwcc5Pn8fN7H-bRMju-6?-hKfl3<*{3p_B!5l3-4PjAKpvIKxg5*OiT zkEcy7ARBjL%=zpXhLt1PNI`py90_1j2Xy?Rmhcx!1q7v{j&u|f%5?sPk@pMZNuV83 z;Svov=T71;4e*!7C&3yxIx@ok;|vOV^dTq|5tNExoWlz|@Ic|g?|%g{NkEL<_r0(0 z_?;w)zPxF3J_mJb$$-npE_(4LTOq=qm+hG|i=O9&^OG1ETZO*ZvTP3e2ZQZu@FRP02R}iT)07L*iM2vmoitDaE;bT?b zxcTf2&6%0MQAz6z-=}6HS$)sp_}o8N#2?(W<@STi-EaEyc##4;A@I%7*CRIyduhU2XD4^SFquXq!5?s>r+t%{PMs8@wN|jl^D>p}< z1=`Ln(*Q&6c}||L*X+tgoERaeYj!8KK=z z0#GOy!8{Mj$p1x>KnXogprmqM07@!DWN-(b>@ko+_C`Y5aS2QQnDGTmo^aoTUkKp& znvkdt)Dg#R?0@(k%pBP#5AD70Q-}86_rXnDZoeo2TS^(@%6akR^DOLj0 zaT^4nEn+B+ZlPMdCtO#)tuS7_D;f`)Z{K#uM1JPv^<=BhecE&g5i*eU6yasbc*eQOTK%y>ZB0p>j}n8aDyRnNw0n72VH^*2C~r?c+13y+Ke zp%fC#<0#e2@I24mzX$kd%3L{9NjA=Oo zo&QS-xnt7}JDd4s;xv8W-MF!`di_POuJ(_=iFF&VDfx`6u!&lI0R00asPzq^SSl}M z-WHPqCz=3QZuWm!0${1G|1zThgx;y|qYwa6Dt!O@-@v{DkIwMEzH9c+9sYct*M8E$ zKLfB8z~&S2;k!@)kWP9~576$N=wF@ypd}>!w8V(O(geVA5rYc|gav=k{;n%yOvP;^ zN&*~VyH0xw%%5cE^}k1+S^GW;ynFTaJ94Adyz3**==6^j4`JSY3 zhzlVEy7L`$nr%Z|NW@`mNC}u|Kn-|BV%+V` zF;G%vy7baS^GTx$(9wC8DbXGR%7AST%+oUyPU)ah*MI9Coq}YZMgtN#0ImRI-j^CG z+VKc72>^CKx!F&BOjtTb;LHnCPXZnJmu}CFF9;zVS!4gDBOBz#2drWt`#ojxlzVN{ zM1brIt@nq4alOq#xrkDwj;V=yNWakFUSU;pevY^1XQ|nkMzN>~0MGMJ6LorwQp?@G7fSWCaC>gHJOMz&P_6Z$ z({2_^h0?Pd-PV_P{>zVY7vGau8wbXo58$H!iYJ2rSZ)M>miwNtCgRj-H&FCc*D#jSA253!o2!k5PT8qfEO{-H}>_3YU@{^NnXo0(T$dF7Q? zUZ<%}xdK2*h4$RMGn!LYYHoq8HF}fje7BXj+itguhReonA>#vJKxQ_^&i>tYtQjp_ zOs8FI%Ki-*lQ{#9m6_WwR?8?>%V0b+`%Yxs>~-8-5+~?3+X!17bekOqmcw=zB1xQt zU5RWIU>aFykB79$2FAQkn%mpOoK**C`M-AI&#D61KvW< z;P;pWCb|<(oH@mW^#V{*!3(rMf}Qzyri7HL0l06x06Y$v2zT6rVi8J7*YTGo!q7ff zXZlE)bHn)~AY%lXzFuyuB%?ymaj9lMd=Eh(fL{pEH$DW$7!L0KA@)4@ZOlzi{L`MF zeEat|ZP|Hmewlc3)GhD3thV~>=l@cnRDCszIzJnT&ITEGP^}H%?DL-s&-dYbg_B?c zxYQi~=`{gNL<}J%f}n^f3h~gcAF3nG*$+Q7x$nK3w%neRRwtouU4LN_z`p``(TV!- zJr)6QGz9=HIRcQn{U0v@;7Hw`+h^`ii^2YK1OR0TE%Uk65+OP=#^I<5-d~)i690+6 zw!S@CSG|p@mDaUeZ_5<{dF7Q?UZ=VK;zO??l?3ET#ynEK1fCD57@$cgtOipxD9jVU z%<84Bpr&;876lS=0>IogTW){S8^L~J>nlj`fnupKUk&T^nX5MMc*d=pPALH(g>W%= zWM=(gy4rTeUnvDrz0U4ZDKKIV@F^uT#(ll=S>?L_%J~Rn4dEO(WXyD|$$1Z?909rg zv1EfK1(=bNhwUz;5D1C|6sjdd1aKr#lqL-*1(E3I+?r`1iIa4G--2xew5@@ijl#1E z25AlXi1iQ=>HnxF-B2nC?s0g905IKq7;w)$4lnSXVW3E~Q$FV`HCHrB1Ca>CVdQ4| ztx2Dh$|w!&D1iRn?z8m)uz#b>NC4*=_%n}#^VF#yq&x61ueEaKf7&}iip=p8!W>`e z{0XweNj9d?`X+EQ7Gg&sTuOn*;THn?qH-18+6u}ALxkI((OC)AhT zwlxP-PnO!g?NU-;<+v^sNzB#sg(Vx@@jQmNYI+~=M4Jd!9xBI0Hw zJD;1J-+LDkeede)cRZ=$DsOrJGo?tYo+MYEV3!nL9n1sNgEZHc7pBgoc!Cw{Ml8D z1@+F}AL%xUU~=f~&8^$La(79h*zB(d9(YjJs1KR|K#IXps#gF2aVLUb3ecVJxUm5# z1Vj{TaBBd*B^9)HfdVnT4;t{M3I_`wtS5q!a`AGD$N^&8vDZM?&cB<41IFM7+Jw(a z>D@w<2}ZJjB^tYs7C~ZNX#OZbVMQ9 z*h8I2V9g4x2_%ea!R|*7v13gUGxC3%3c(D4V$}(HKRkFIhgb072LbxW2f=+GVW){* zKlm!(uA$+TFPH6U?n7X3 zXcVL4YfvbZGUGW5fqJiEBn9uwC;@tA`IqSaFSwst^8P6t>NNn&5EEF~`Cm)~NF}g$ z?<0uf5cT>1#>ZD9ib6c{@co$S%zybOhxWYlt?&KpuKX-Hq2PZdfNud>iHBCs%l;IR+@1VBQenP`8trijoM5t0gjl#P|YM#IG~abhjmj$c?f7`;q( zqO%eq=L@ycu2w|}K2rLcx?td=o3`EF&dJes$u)XMgCLXF!6Dcd8z!Gv9)U6VpLA&iHZCJMV70XIZm8W8fzY=(C{SO5hpi zuG=q_?hM1k;z5z=#3?6PcMEe$JN`;aX#B6iIvCR?c~I~RzFu?-fw&vF`zK+laIsx! z4UDx%fF%wrpa+nGe@hIw+(B*Xr&N+I@v$9!6lUZP#LVK(09^&$xhI)+ zlyrArIr+ZzEU;aDVI=pS??EI2NfbjVWhDLfbxLLZI;mi>DWE>?){g#Y53c;%3tKvG;G> z`u6L0#`)=(S6+GL_4w-MZ5xXqdd`M*FWl(y!Y^?iJf~1BgL4lfV`st-is&C)p;Nr1 zg2z1c^^ch*Tnxqx?lNnudTj`e#t|r`&}z*>B;j)^<$>EqN6z~D?Kk53O`CT-d^(?R z&}#PA4jq2m(A4Bv3V=sItq?#Jib#SolvHJpGmJDEuV~H8zIgK7bM6B0otyx8!fOQW z9-oAfTN6tIw4DSzv)mzuOrOJoTx%L9VSenH{kK{58t7WnJ_W|~FC5Oc;FOe;ms_{{ zpj1Q>#puqrQK*){IY%5tNTdMcT3L`pF%siQZzcRtdMrTNd3lfP$M(39^J`K<2ot@R zS+ZGELq~p?Za5eKX%AnflW4*ELKU&`4B(t=w|fh+m2`9Onl;g{g*EW=JUs_*Jq3ABQ9V77XGP+4_JZ(z!C%mE%;^us^gxIVzG>7a}J$O3;h@d0T>=x zfw{(PnWFd&pZ}Aq?tR^FeLRn`JOOp<`U?jDyz6v4wmJ%^f4qM?{#)4(+b7N}s3j5v z2E8)M+(%gin2K5jP7EW33i`ZK&s(A2E8%e198!-o-`yQAe#!VSX!Fy z464<^UmWaP{mM$I@2znh_I11SShfDysMd!tw(6Y4is>Wizxj ziX~uRRO5}weIOBI;;@Iq&2}UT!TdAfd^o8DfR>TRS}sqdJF*7+3zzM#rTQA!Nl0Pf zv0aB-9{{OOG-Uv{o$r>WBit*SH;)4X^Oynb09Q&Y1`M$vq8K94N&@}8&>8W8@1*F7 ziM|twaQXEjF-isr7d=SEaE~~HGBf=mk=i)V`U+&wfbQfgJ>L%1GxMoU?_~Nuq|`3~ z8Q_}6-m6~cdj%-NAn5xux0-T_2c-}t3DAw4ES@p#K>!7#xF8b`NX~eVF>-U!%8)J+ zsoA1P1jzT&QR_rPsKmt(Y7;)@T+H=IgEBM!=!r8VkReK>OC)gV43zetdN7-Lk}509 zHs=^KBN52>7QiSml-c3-{4^TV2QfD@aS#fR=HUOSQSW~D7Zrg0+qYeQV7^d3$ktzQ z$3b4PBGdel+ zL2u`Nxvxjt$`ju|9n)K;0A&`S&I|Au2U`$D2ml4S6+GLb-dtz+oj`Yt$pE@9`kM}6e~l8QVm0+XCNq*(APf>=KBtBS(R}LHnNf7 zDjkV}(kd29L;aN^ShopG?gjS! z1XL&i^D{safw~F_6%PS4_e?k^P96bZ&JAhZ(p=1=ZE# zG(o8d#^DSarL>+53Q~z4cYh1^vnc>%NdRSuk*pD7hUgF}i%HHW!J15}MVN~*LJ~(f zd|(%fR67e(BC!%(gM8$t+vaNoli9b1D^ zxw6c?m+AWVNcoS0H6U`MFKS`;ANKnUhSt0}gI5AX%QYRj$-SL(j{O6TdUU?l?-Soe&q&}~H;o23? z{=Wpgf(HRsufGU`!)w4jKV7p(lST#wB>Jl|%4RTT*7N`*1Ceb;rpDn0%z?PR$`1~& z!tCUJOwSy|+Laf*3E26)({&8y>;0WprLwownqMpTKV*E>%;!;S4v_>}0yrE&B;)n} z0-=)=08fYj&?iRJ4PAFyWxCxKI9q_n7`gZ(rF8ckN&%d?e0ynJ=$$-V%9Kbz1~98s zSzrz6M3O)W1tA4wVx;jU4cLQX0nFn_q8Ktx&~3GmM0z}cNUI1K=ML1vy3M=!eA68_ zMuJ3o%)uELsx;b3?|*ujq>`y?xKkl#zy_grgn^NJzhHJ%%y+I&7BNKL; z_V@@rq7chS&+~Hzk1?0RV7E&dl{CSS4OZP?1P(6#FG~bLzs7MGfqS0r#G5EVn3zMy z^GFF{NdR+xSi?wr;G9Rqf}WK%c2rUVLVFNc6TqxC+xaNCxJZflxx<*6co?n5B+9kH zeS04K&W)9zG@XBZJT>du>vkw$$G1N9$8WnY?6&rY_5NSph1SHS8CF{vMpap!>fpnULM~Qu6`m9RPJ9@C#@(X3*`nQLfa?dz)ck za2So&+%J@a;w=Ck$*F81k`0wtT|Q79+1y_nxd@D~cEj@!cm*I%pyEWYVK~lC(lho^lFI3=A>IN5 zK9MAdx)Gvoh_KT|x79_|=^~C|?VfMq>TJ}TRuv>j;snB|288L>%S4;lNi$;LI{LAh z!Iyf3fVejLi@W-MaW_KL2@!QebQ*0}SH;(^`Ql)?cy~Yc{n*3>!#f(i@)qzZ72OUu$ zO^4rH2yB`_mhpp8OXx^O_1N$Dq-0aj6())$)z0A)`0r4J8P7A(f ze_YVTM@pFW{BGg47e2mqd?%n#EJ0X8lBnl)_4)uj#$GU3s=e)|8!z$mv*7X7t?Msj z0N!}|_CTHDd#fk3vEE<{wd5bw<9K`pV1IWO6VZI3Ffw}8ZGZkh&b;OQmlyLhG_Sn! z%4_M`zU_7OzS8jT4pc@y>3gM%xbNf4vtNLK`%rPLJN{BYi3CUzYo4ZozSP}(Se&Ab zy>#ColuVln0aj_v?3r5HJD6{p`T3_uulATo?d6adoGur8Ao~%$7s*D z(3qS>Yj!^M+Os1BCJrwSqty7%tn8gk-x(2V>A6f2O*#mf>Ds5+^e(>1kpYGn02a-z z6HJ_8ChATfyWTgZH3qa^1j@|u+hgxi5|Anaq_oC_)pejW}$h-IxY|xhQJi1sUfu)2C6ree-Qc4jkOQ?QpZTrO|B8 z9XzlbyB_#HrY0vAgZX9nfb1N8uS5UQzoujqEe-k!i~qU5^^y;E(?TQ=LYscdIU;W2jV*oCF>OlU-vTd~(s4wxYS`yqJ-~K*65}>yv6yntt z)UP-n&wAU>;MuQz$xp2u8veo=tIzqiEMsIsO#RJ@65Mo+MK!o`K z3PJV0<}?mZJOl!vF?;CSO3{x__c3|v2mb!RBQJi*8>dIdKGjwntTuqchKo>o$*a-- zv%ie7^DaV#AsA_QH;+#ozGVB>%h}WYJUMA208$9}L4eo~Arc8@I?u`iP6p?upTwqf zZ@?{Fw!CtHR3)*=k2i~I+s(GK@HQ%r!59t7G$-Cjz{z9qOr)Qb3Q{D9!x&+!<2(Tr z5fl*^$<%aCsh&LXRM@K=@K3_Xy&qDb4;{~>;J~(93n`V(@n<6R7*cn9w~SJ@S!s?5 zEyyo3oPkv;IFRmC#}@31)VZHgkDGqhqcHn??KbUxTHv3(KV@>BA@x`T<2<8)c9Z&= z1Tbu)NCZ6N%x?EXN@0u$dp#1;2T>U?We5PPP{@!D483{k+3^X7tr(#;uo6;r;RgZ6 z)}DvCsRRAh`pAu3v0VUuoPU%&ed?h}`a9^=fsiRmd zxpODO0`^WKAHyP`Cq-bZg^`RSf^c>#;6+loZ!sG0W zBJr!Xzwfg5Y`Wq0+za5b*RKO8pKQQSkNb9u1^LJ6>;L#>2Oi6;z;gS2j9>w2%xi^` z=y(!z_8`W7`6BeM8pGi5IGXcw!Q4!Eezj0LS0*c7_V=Io{cD=@v%B8#?!P*mpRRf3 zmDe-5{_uA;QePeQ^(&wIH+_}iiy0ACt+@dGgDb3tICCvF9ed6|N~VojGhS_GnVp{( zpa5UT0$Qc8zK}CB4j>^!jKha_quH23r`|T62&%c zxji}6$47X)ghunFgVh536)Q1V;VAT%Kpsc2xf}fKb(oPpynXx6qq8=60HT}#c#Ng9 zLwUtAtqK>7W*YF_Rvl7Ct^p z*O@k=knFxw#?e&2j>S?RMlX5=O7$w*&1vj;;M=S0eGwl33fZOs{|M=_H^%vGp zb@#sqBxk)MkKxOoNr*iPNpSSgK(&PX{?WE@{5}LrYdNP$ zx^@KpE5@*D?FN)9H4KfcfRtxr-=19zz_SXKzMW06`h)-PkFVPKtMB>vp8U+sE3dqs zsWs4t7oD^Er{7U5R4xvRC9Gb3K1!8(3NGAwT&3oI8UTQV2K5SAHEkw_Tq&J$2BQcd z(%pa4nuN!Zbi3%Z=h1G?AW0(lK@n0V7#d#l?RtH*+3C(d(&;pQQmqb8-0^1{b|0SE z^;IZ@n{K#$;#3@;N~hA)W=^0Pz3CKNIw_J5$)N9vR4=YBmQ(hUrsmy zAcaJ?*@03DaW_o6@uu4?k_2%_&-nD}c^ZuO>+~;7-H!*aohd2PVYQZ9)->^ALEiX2$)U4jYMIoI<$3IOBjFmX@!-WUx!Grf#s zzI`H$F)-3^cuv$4vzT3dN;7lMjbB3c_)*V7R*xYdF@}ypf*CfEd1gezdIA_yCgXT$ z=J?4(p&2EE1@zV--Hs|q7_&iccGKKfnPX?j12V}3M1*p65bMu>2_Crj%P5qpXLaJq z5`dflc)F1Qe{g#O;Njc<^4(XFl0P%n*LT(AkpnMkHRot-d@YKl@`6~u|@-J?>en&HZ^^dz= z1>o7I7WE&02me^E`%8pRE~XEb=*IV`-Im(CT7pl`Y~eUE2$tmmBotaALPy4^jE!L6 z+%;H#_Ono{55N!7_)f++M#om8uYVZRlLtq=*4&?-v;N$7-Fee*{_nZD=`X+O_io*r zpT2qJmDe++KK_9#f-_e?cXib1{05YIW1(2a$mlv$>O;nGJq7<{)rZ8~+&`IhzV**? zc*~A$69-vUfF%vc0Dq;R6a!!)0Q<+_b00|(qZ_us$U~`I85LrBv|1TFvr_1PCHH*< zUJ)J@Q0W`|#+`q0&Y#Y=roPka%p4+8(WcEi!;^8Gx}{>=@e2p0=i3*pyWj$-p_QNq zzY9zq07ljzI`}A>tq@VgUk{)JJiXHZPB;M&bwh;hj+x^Zh`N#MX6YGl-TAk%bTT7@ zCzC@Thr*cZ5j=u%;Me98QV2IQuOQt_J@Z(`s7^YtX*lIGb@ZM z=Q=Nx&_J1#iyl-^fKU#+>*Rtoc8(Eq2?o~OP$}6nvH+2SZcADyDWOOKVkw1jN`k=1 z>n)H6v+4u5Iey#WwuD1==G`g++)O+H;2ex`cf644qGz9*6tcIEW99#um;z0*F!$Vv zNK1=AJ=-VJ-UOEPkV1fQLfGn}|8`&09s94c8pGkv%&% zU4MHwKb!N)E3c<(ZQr(WH383GJ9PeQhU=?dt?F3a>CEGdGoOocxo#S1wmHfySV@7r zRU?y1zt4`}+GuZ;8963^JWrbeI#YMubo2`)42-Ns|KJK^9UxpYG7=%$?FPbj6LHwV z%+!9=`$ho9UR*1We!AdQC)cce&Mq+g%l7xtt%;Hky>sh{9bHu1Yq5Ie>(lMd&y@

      A|O#bGWoPOP<9fBty{OQ1aQq0*_Z{_Nf;ySh6tNo z?cy&4k}yWpjgdr=bLUq=rXBN)gxqz^jR7B&(%{ud+Fg=>ArKhn;J#;k12S?I^R4bS z>u!7!CkQ)Th**H2B`t7L{lyD#Vhk+f>1E>pNukHlpII0C1q*g3Ntd!mVL;3%0y6pb z$Qb)sknSEsWn}S$-Zv@r`jJtO0iKreXTiU9#JB1I{dex-2kp;xoFc_7cYA4e%^L=)N|P$^|n9nze1&bgKrNt0)ui3Ci6Q)WcLjv1H{5zbTP0cDL9Gh+;7 zMmvb5X#^ z`Tt%lmd)%#aFzD3j%B0-C8o!LfDXa!|X+uqwP+Si3a89n!2{I{iVu{ij`CyoO1kkmZ% z|I|8^%4HOb%iAz`o{w^+ripx+1Q6YIKG81)LG|pPd%^fuF8TTMmOgy#A_}j32r5;`7^g-hKZGS-0GI_xHX7MkR)KD-BaI?!jWs((a3V`dV3z>=2gN`}$IEa8K zY+&lhk1%=o2N0s`R2goD-gNmHXYc|aUJxKC77&yQ@O)2q)Q!?YB#Dbwj7>zNNHh^7 zgoH?BYW!y|Izk8txtQ>y43VM1J_q-?8#!Q{f%`tV=Ye}(kNdwpW|q|8mI$%0k(ZA7 zh&VzVb^#(0b=yY($~#EUfV%pIJHx{dG`{=rzK7p3+3wt!u%I(NIicP4)iF{4mP`de zulGg$*@$oen8(y)oR<5kcU+v?n zD^Aq|siXZ)EwXJ|_P#y0QH%Zlmv;46i?*naYcH2puBat*1{UAqXwOFh;KV>jx;V0X z4<32&hdt4=%T@p22v)7#fR(GyL@_8-2C9|UpSAj|+sDV&|L#Zs_%$p)rSr-wucu29 zu{9T7aPfx+hF1O0RckLOu2_98R;=8B@fByGT<%L%vO)l12qcjpi=bZmCoN?xJ zF+8>&^}bO|AK7<)IT-lBs?y_NfC7iez3dfwFJ9Pt-N*1^rL+YY#$)29s3 zu;hV50EWdQVvx$bNzKTD1<$rG!#$3}2kwD_gy$8(c>!J!81PSE#(g{}2HK#}s2{ii z(N@_ZgpT@?LTIBuAt2%yB1s^GgiM5sFJz4C5e}%MI{)#VMx30g? z1Moorrz{7UdVBASlORDoz4PpM)YG-k^y-Ngow7@*02cbS98Cp43-;NKs4aRvOYQ5T zdoFhaU6DYmrZ9B&8jOvv0qEEx48$0MLJ{@8L6B0ME3uA==;9)(&-!mKKlh#;U;6%Z zeun3jS6)xmy7|V9{E~~$Kl9u(U-Ewj2Ufm*Y{DdHD}XqP zTqob^xrx$=2W7RkMrR&%A|z1+B^6|pAc=Hdy-o-q$Zn$L3W{80pGp$QSUN4g1&{VU z`)4_nq2+V)<*-1NxzB11{nBE9eI2FznRLCB8rX3m;QOBLwtGB{H{{$<;dPhZzOOJ0 z2_Zb=h;I@EluD`oJk{I_FGPJ}9{`3MZrBU9 zh``Nj80YYe{=d0?4yTWP6JwJLtLw|B?tJGh_Z-e|H_yNEu3PU>r_Vg`>nF}F{?tYk zJ-T%6w0!7+`w%B_dQI7^2+;pr2FWq5Y5R;ZES@=mPN%&M20(`Qos|Zd^>QKL2f83P zz#X@dfI)~-u@Z#B|G}~1_@((#-gN8(aP>3)wlw57`}bCzb$2V-bcrE-d<-_%(|2?C zr6F74o}p3OOCz>~%o4QehamudB2Xxm(dnF@3aeNwWB0zxuxsz7n3>(d$4lk!+p}~3 zAAJ13ylp-|z4MWed^}f&Aez7Ss{j3GCntA(-}KzY7;DU#`8{*AeMZn=J<lV4ldj!lvwD6OnEU1uiO(Y1Tjwu2H(licDG=`Nsz==gEe{kA@z>@QD-0U#5J_IeW==T;yMJwJ&ObelQ_Km*m(g&mpLIaqDJ zIU#hX*t-2gQ{*#~4rWXP(~iDADZRim%j-@vB)Jn*DQPA+OuPI`YtTnd*Fw(6E^{&( zt+|pWWq@%9UI*-yGZPqBVRHom)$;{HpO#+h;QKn)=%o$Y=Ulhm$PR4$pY3E@Uj)~^ z5q(C0HZ6f?bo^Grz?n1OD^;ct7Ahc$k;H8*pM4lXp^UItbrJ|`HmIa>sRX37wm+3m zWV{^gXW+tZpQiE~0H5(30Fdz`V9tYpb8Xn?2Ofm)r(j-a2?ICPN?~FiQ*Q$9iWIge z!#UTck&L0z7(>+Az=_AdijCE?w0QiXyH6ax|BidV@XgiycJurkcYp4y$t$m4c(5IJ zze>OpKIhl1uPz6*`nWR<-Mk1egbiSxtB*}$V`Cjb5I}eyg0PVKUi5?g9zOs!SO{R+ z5uFPkm1-TFd*~B{yKb=O2Vg+4)oGr5#r5<5kn5s{j~mBleiXos&*Xa!^8rAg?L@y8 zzh7-XK>PrD?g!~KtAAar_Z010AM0Zh^l}w?-;@pcOamSNQTw2;!>>p|%@t9-bQaUI zJ9U9;TQ!vQhFmC?G2WO)5_OsEHh0d=?|Iz~-*bIn4fonran_g0p!VFdsR3H&D_zr)2``l)QorFbff8+suHl$&MzTz@7-gHN=Ji2P#KhzdRBDr0 zJn@KEt~6d)DotGTiWk=Zzk9#%z*9~%dj0=#-GimmXTC?SH+OO(oQr@H9bmBwoQ;5> z5ImBM)&JY8-+2AXpML(E-}VK7Ia2^&+j(Ks?xMZAfo`*nBu<<`UuUBQl1l$=&Fc-Y zw~_!yzs~?;C8g2vTL*Y$T<+73crR$?t~|g6bJZj=J^0oKa9htg>s{TB^R(Z#1=Ur7lmwMij3+?UMm54)eZ;M#%T8G#s$zYqw*DvIR>S{tXKRE#)o!t+D; zK{=Id7~@3unGColBG-wx+iSJ^c7HjEg((VH@Xv+NueTb03)T&|w>|@Y7{CvGa1$A6 zB_Lez-lB=ycg#sfvg_oY2PHS~z?c6DQKyO4`qEb(yZ>*0>ZbR6>hb(`^ZXw7e&L(= z)L(q%@M~Xo$=^#-R4tYEEH5pNSF2;X05z-#(Er$wLI7h7rE&#ptIJqkK7&G7M4?#5 zUo2}?E!?^$d{4+`a z$0kOAtnZg?$pCuNAO>XsLx}zv=|KOsJozHPC=mb~xet1uITyE3e%WqR<{Ox3%tCnH zwt;_tVWCnTL#bRv)Lfe>6~dRxPV<0QtX%S%mn?kg-Y?`ufPCa59~b`kcW?c^@0ppo z=s$DM4;JF zEwb!oN{s<^^tnk3$Rr6UnYdyAdYY65iwI#@3V1;qLHCrxCY`pTi`hE9) z;en^roxk_<-&AjU`Nc~hOpisaiNj4479+j87z0$4%nG7fG*SP%PyO9v-?3IRjxS^+2Lk##3Xt|$4yWLc0 zme2mt-JkpF>HO&S4&(m+p=bJi*$`OGMy3G_2h*&tXv8u_^Zo+B01JQ(G7AQZ4UCO0 z5M;N4Vd&%AEdmgLgcOzv5$4`-1!foaV7xK?q`<#@UI>9=sSM%yAQ=a7r+FY0xMpH< z;l*!x!;AO6^19it-TQ@a=7z8N$VWad$Z_ZGH_Yx_IQT)v_@x(L{+;l>5FiESdD?W3 z@t!zhW_;Ju`2sopzFyWmXBhxld3KxtNer^{4*MK8ueZ`;bM0k@aqOP!q4w)0t79A( zU$xY0K$v?_ukROeo?$C+6iYQ!$ELBmbW+5f&a1%1)c1Vn!ax1#Q)B|X_WQo`k@fkx zPsSS^$(Gh$S@#*+vtu4(0Z>B((Q5B&maF&w@t05C|Lu5QWjz2+nx9Qax7ESgnPpAa zhwk=zo(EEdZmXT%$ZhN$*U@t1GVId|6r(in-FAGEN|q z1dKsz-fef88A`Zd4vYqc5XD*<)kYoF#uzFSH5995BUMPjxRg55kfd@zUZ)N8IvLw& zKx<&=wCj#?j-FUUd$PNZe#ZPz>+Cf>J?nCB3lv#;j4goJjy%kJ3*UqAMGA&9lP;o^ z5fB@bMw`Om^3E+4$e41>EL@4P#y)sK87oVVqt!ZtM0Rw+#K;Gjsq`_GQJb2;#QZcWV>P!PYgXd+IqPK{xQIi}&~7cG-PAvi zKkz@XzIp;gQc5NN=Ewv8`0jIOpZNIAhwi2Pc9W0nc*lGHR4$%+;0^>Vb6*^DO9% zEuc+O4u(HYXsHODxdL|Fa4m%IV{Bq-lO0D}g8%IEW8;(9z3*~darH|u)tIf-Jn{Ou zTJ94naeP4QU!znGHG3;bdy*qsfz}E<>4?aW8bAOL9txN)YSePe82qK zr@CKndhb2S+itseLsiS`rBJkXlm!+l9(IQklOf>Aq>fhS+cpUx%d1;4Kcm5avyHVg zE1GKUy8GHRFYZQ2x{;yTYsY^ZxhADH^8;rfNj(z|+qt$b6pU$&iOOi@wN78l0hH8! z0a;BqI3bA=Fvj79+?|_RQjpcWYt5|H&2!F?#2l;}K?tGU>XXDxE(i?mwI)hqRlq~q zfwz+nYkXlO05ID2Eal!x5S${w(OuFkdb=&)On-rl4j#rwfRTS_CKE4xSp^j6>zJir=k0J#IwDarD7|`l)WWd+O#x_sINK zlaFEJt?#)j0`S|P{m8$6peDQz9X;~!#qCzpo0;8_cHiv@ZLU`itve|YA$8jUN~MaE zy$rQe@4f$}zp%b1dRoD3@OSfnwKk5)sX5O5;Ja75?LP*P8(o_5vAtIoo=OVN(^m>$ z+kS>N>89(u7we&7V#M!IGBk@-LSZ{K?iecy~ZZsyswq>HBP;#}OqLRd#x1lkY^ zK*ANGE5|Yax`U`rPGD}wUX&~KErI=cJx@TXT*IXYUx-$79S=Y7mHEk{e_QS1gD?HW zuatj(y}5SZ&9{Cgmj&b_ANjZ-#+|p{Si1NHuY7S(s8lB}y$T{IruTIsov;?iDO=jk zLo&^KZD6iaX#m&Y8$=+Bd6)$z2A7cnBmqq5%c<4;8$UMZQ)U~!ChDD(0@>(rXb&)$ z=ywLDyZaX3NU4+JNI^xhZf0^VCug2;28LwJ%L~OS_Fn!HJpRy^8gn~d@T-6L%ig(e zwDRXSz306m}iemVq_5Zn8+S#sCMm7 z+^+RypihXv*Pz5udu-A|7}hYi;~E@0{6)0eONinYroGEiEKa5diYhJa=z<}47YBEo z1b0RyWFO_}G}FfSX){0lT0itr9;+ES0COG$wvgcFb}mgJlhnXc$wm;Au=Aqpv2ykZ zn$5F_qt^fXz`y+EdpPH(Za#ERZi<$VEyt-7N4^kG&i+tXu6_9Uu}8ln2t!Ow&G+1p zUB};5zc2)T5oYIiqtk9eD!GZqc_^oPbKs953;?rDrE(2xYb)1PEA@kU0ib8>0Wf!A zY|1cb-3!%wL3`#}+6UYL=<6+GgBZC7(hsh2U<-z??q+T6lxO_n3$YHsa!d4aNl2Y*zCDdxr&P~xeA?5>*6Tt?rg6u zy|Us3|Ks=G|CV3=@%MZ(|8C?XANjZd?gsd-LZ$wWN^J_l3wp1?O6e{-V@3)9fO!U7 zQ_2Wn0ECz7?d^PBN`0NT(S8~Kvh;ELdXdhzsjn2QlzyEMVBE{F!AzskuHU7Q8Hsqe zi=^2!ONlS1Tt-z&Ut;6+ z&#o>ny=iGZDHJ)-glHw>^*=ked(YQ_hrhiG0A~D8052an0f~@AamK8TL&nm8f89}L zg2OL_+E}hA5Vbpq+TFCe;56Iu zAQQFpfK&|<8o0h!1`mk_`hl&J!85{^;>q=^ew zilC&@#SRPDg+Q@dN~?-Y7i}0%^+A46!R*3ySU&p*hzRS;CjkZcK@E(Fv=G6WarxKX zP1}u6iKnUdlxKB600d|7eBZ_MNdSHrAS@MJp+xlJiHR`y*vaFEFDsR*VYyuEl>}r9 z0a@UZDF$#MP$-sldI{T(_bMAK1hD=h!7v6ux{M!&XtmbMLMCtc#0TI0*FXFpem~bf z>v0u;XPpK<(2XZ&q-<(R!%G7LucjUZo`Jr-ukXR=Y;f%ZPfbThDKM0Zftyz~l)9r`zJ+tg#rm3~r4nGk{q*#C{Bgr<@ecj~C zU?Qmt0%W!QEMtzY2o%Rink}d(28?+(v6MLJ?p0EOWTNE)j2T}7U}oVGY^*P#D92tA z6iff=jzjFj?>zM6=kaGIXOR|Qe&lN^ZJ!`vjQM50O;|$3#jAML$;?L50@4+*m_Wbw@3w;)XydR?O6%`stjxo@6KijtoLhRfJ`aLoh(e|0wB5q9Irhesjip*} zuuPu4N;}i`X_ZJMQKAj&B&DE_GIYaCry2yrod_yPJKR<)58j)L=>*qf{&RNH4UuKLt42>@Q^?Fox9p&qXJ4$6%?9*HEg~QK?VY%igbuMon69~1@`U<~j)APjV*U#$jKs{ug(CZ*025WTH(U zIMeR`NfbLuchZfVxt^t2E0r2ZAmbGv6X}ctb)*|h&GEnu0MvgwLqKiE?~(*Gpe6tc z!~s&wX;qMM-lxngBaR~YEC3WBgqJb~42a~$iIM@3QS3DNN=n30?7I7wouFk9TAxl* zW@7Y&t5`8^4explI9PTb!=S;x1;e)BVNCP_2CdKMsqX=qDx9V1XnMVoNtgnROw#&| zGKL-2BY>O9l~UH_pQjr8z)!skNOye{rG*Q3Opz8kIOpJD35}WkSUUR%;_f=u*PcKz zX`ob^1`)IzLkJzUC?ymlmplN#>`Tw>BhDE-Q}AHs`LIxMasW6fgGwW;xb9JrA~4BJ z+@moZB!Xfbo=Jhwaf$*#A;9YLIy%i&C?$C&X)+)AIIr=BpZL&ypZ)N=Z!Ikqt|^wv zla0n~58&>lCiffo(crH`{Q?H=`h!nz3jBLtQ>{%v#&NMwEL;cRAM>M#9|SOUVQfma z^S`+hz-H!s$S42?y#Pi~{SEt*jp*t3te<+)XnWr`Qx>p7y?*vWSp;Z4dhT!0}PP}Fvc)GF^#LQc^QBB!LNJ=KXd9(tvc2P@VWe}l8=1kyN~U?k^y+>g|=NiXNLpk$hi8C(DDzI4*JfsJ}Cf(K>b0lfZ?Tv zUQoYzCIK?uFLnz%=QhB=Q7n|7I{4p;BrvMrw#nmRp@;)lUXR)nkGyc{+~V(j_BY<~ z@JhG+?q+NKAppoDWAl-Ze0;0M9q+qwZ&0XAa^WHFwookBhlBs@Ma#tdL3m&j4GsF^ zSo@G!xBu*%fE#l?Yw+S4wP|sHl+w%DH#J>;@;xBx!s(n%GnTl}g#o)BMNqA_)A>7Z zH0uvwUTY-^WVeT)3kaM6k`Omr@W8+V-}&NrUWj684C`yB{5x*Dq43UIKmD{y8h_`| z8~MzEE5Ex?s{K+DcWcu-F0HrLm#f0_JU=Kldv%pft(ilc?*QHjZbQGNdsv_`pv>s#Nlwr{s5N)aNP!_;*5FWUA%21&yJ8Usn511WHmy zfqqZT6tD~gORa}#qI1#(8<8>hE6|@<9M6pT~!<2;lk)ck_k->t5%+9#D-D zu)U{K@9s6j&HK<-1jtzWjVvq-U#73fkogWM0@_Hx7|`u@P_EXW2JnBrk7xd%;cvz{ z$IjjRQ6HP!Av}K)PdxJ3pjf-B(wO@waPK4e)h{3U$j7(n+J8EZ+Fr3-M-Y~VfdApw zNFo4X2o?movmb`~(%bFmB5WM>G*yYRQbZ1N;DGnWjl;&HYY8zELch<-3S_HeyaotR zS~hIy{VGYIqOOVe>jy8UFl>#z88WhFD-*CyONF@EgrE`x(gA$3n4O-x(GwJJ*&@eRX;9$YTIot~F-g7=-1IFfJy7unbZX(+d}a zh)}GImpiSs7p|N=cFpXr1Mx?1f77oM*!oSkeCjz<8163sd=Z9bt-HzERo}Y(TM9Lx zWACg{8;BsKf>dc&UU#^)PF*F;83rQb*zYv$hMF#wDF|eo-H{DAVwz?`$h!J7w{2{g zLlUJ$0G=_!uyJ#`vrjG-FNqS!Sb}qopcq2N5=5G|&Y0deOqi%X4lu>iB8Ao3gVI

      #0&qi`x=teXM_2+JempsbMqY3XLfc+>Su_`d5_ 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%0D;f2y-k{ibf3<7+F2ezRB_cQV<61|gZ< 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 literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/cloud-pot.atlas b/spine-ts/spine-phaser-v4/example/assets/cloud-pot.atlas new file mode 100644 index 000000000..d7e313052 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/cloud-pot.atlas @@ -0,0 +1,85 @@ +cloud-pot.png + size: 1024, 512 + filter: Linear, Linear + scale: 0.5 +cloud-base-1 + bounds: 2, 300, 233, 210 +cloud-base-10 + bounds: 214, 113, 97, 101 +cloud-base-2 + bounds: 2, 90, 210, 208 +cloud-base-3 + bounds: 237, 346, 175, 164 +cloud-base-4 + bounds: 414, 347, 176, 163 +cloud-base-5 + bounds: 313, 89, 145, 125 +cloud-base-6 + bounds: 744, 374, 161, 136 +cloud-base-7 + bounds: 592, 361, 150, 149 +cloud-base-8 + bounds: 237, 216, 154, 128 +cloud-base-9 + bounds: 907, 402, 107, 108 +cloud-cheeks + bounds: 2, 9, 218, 79 +cloud-eyes-closed + bounds: 744, 350, 132, 22 +cloud-eyes-open + bounds: 592, 333, 133, 26 +cloud-eyes-reflex + bounds: 393, 224, 120, 17 + rotate: 90 +cloud-mouth-closed + bounds: 907, 374, 49, 16 +cloud-mouth-open + bounds: 222, 15, 59, 35 +leaf-big + bounds: 214, 218, 20, 49 +leaf-small + bounds: 958, 373, 17, 30 + rotate: 90 +petal-1 + bounds: 283, 2, 26, 18 +petal-2 + bounds: 283, 22, 28, 17 + rotate: 90 +petal-3 + bounds: 214, 269, 29, 21 + rotate: 90 +pot-base + bounds: 222, 52, 76, 59 +pot-eyes-closed + bounds: 878, 363, 46, 9 +pot-eyes-open + bounds: 222, 2, 40, 11 +pot-mouth-open + bounds: 990, 374, 14, 16 +pot-mouth-pouty + bounds: 300, 93, 18, 10 + rotate: 90 +pot-mouth-smile + bounds: 300, 77, 14, 10 + rotate: 90 +pot-mouth-smile-big + bounds: 878, 352, 20, 9 +rain-blue + bounds: 926, 360, 12, 18 + rotate: 90 +rain-color + bounds: 264, 4, 9, 17 + rotate: 90 +rain-green + bounds: 900, 349, 12, 18 + rotate: 90 +rain-white + bounds: 727, 337, 12, 22 +rain-white-reflex + bounds: 2, 2, 5, 10 + rotate: 90 +stem + bounds: 907, 392, 8, 105 + rotate: 90 +stem-end + bounds: 300, 62, 13, 13 diff --git a/spine-ts/spine-phaser-v4/example/assets/cloud-pot.json b/spine-ts/spine-phaser-v4/example/assets/cloud-pot.json new file mode 100644 index 000000000..75fc72a21 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/cloud-pot.json @@ -0,0 +1,842 @@ +{ +"skeleton": { + "hash": "CKnF82un6n8", + "spine": "4.2.22", + "x": -345, + "y": -272846.84, + "width": 756, + "height": 273927.84, + "images": "./images/", + "audio": "" +}, +"bones": [ + { "name": "root" }, + { "name": "pot-control", "parent": "root", "x": 5, "y": 42, "color": "8828ffff", "icon": "arrowsB" }, + { "name": "cloud", "parent": "pot-control", "x": 26.5, "y": 772, "color": "1ee8c0ff", "icon": "circle" }, + { "name": "cloud-base-1", "parent": "cloud", "x": -4, "y": 57, "color": "b0d5eaff" }, + { "name": "cloud-base-2", "parent": "cloud-base-1", "x": 148.5, "y": -18.5, "color": "b0d5eaff" }, + { "name": "cloud-base-3", "parent": "cloud-base-1", "x": -182, "y": -87.5, "color": "b0d5eaff" }, + { "name": "cloud-base-4", "parent": "cloud", "x": -31.5, "y": -77, "color": "b0d5eaff" }, + { "name": "cloud-base-5", "parent": "cloud-base-4", "x": 177.5, "y": 8, "color": "b0d5eaff" }, + { "name": "cloud-base-6", "parent": "cloud-base-1", "x": -150.5, "y": 40, "color": "b0d5eaff" }, + { "name": "cloud-base-7", "parent": "cloud-base-1", "x": 8.5, "y": 36.5, "color": "b0d5eaff" }, + { "name": "cloud-base-8", "parent": "cloud-base-2", "x": 3.5, "y": 68.5, "color": "b0d5eaff" }, + { "name": "cloud-base-9", "parent": "cloud-base-3", "x": -83.5, "y": 30.5, "color": "b0d5eaff" }, + { "name": "cloud-base-10", "parent": "cloud-base-5", "x": 137, "y": 54.5, "color": "b0d5eaff" }, + { "name": "rain-blue", "parent": "cloud", "x": 102.49, "y": -26, "color": "2360e3ff", "icon": "diamond" }, + { "name": "rain-color", "parent": "cloud", "x": -39.42, "y": -26, "color": "2360e3ff", "icon": "diamond" }, + { "name": "rain-green", "parent": "cloud", "x": 35.08, "y": -26, "color": "2360e3ff", "icon": "diamond" }, + { "name": "rain-white", "parent": "cloud", "x": -103.92, "y": -26, "color": "2360e3ff", "icon": "diamond" }, + { "name": "pot", "parent": "pot-control", "x": -5, "y": -42, "color": "8828ffff" }, + { "name": "pot-face", "parent": "pot", "x": -1.06, "y": 28.16, "color": "f38383ff", "icon": "gear" }, + { + "name": "leaf-big", + "parent": "pot", + "length": 46.73, + "rotation": 119.24, + "x": 4.04, + "y": 95.05, + "color": "abe323ff" + }, + { "name": "leaf-big-tip", "parent": "leaf-big", "length": 46.73, "x": 46.73, "color": "abe323ff" }, + { + "name": "leaf-small", + "parent": "pot", + "length": 51.32, + "rotation": 50.93, + "x": 10.16, + "y": 96.81, + "color": "abe323ff" + }, + { + "name": "stem", + "parent": "pot", + "length": 104.76, + "rotation": 90, + "x": 7.24, + "y": 92.61, + "color": "abe323ff" + }, + { "name": "stem2", "parent": "stem", "length": 69.84, "x": 104.76, "color": "abe323ff" }, + { "name": "stem3", "parent": "stem2", "length": 34.92, "x": 69.84, "color": "abe323ff" }, + { + "name": "petal-3", + "parent": "stem3", + "length": 37.74, + "rotation": 1.03, + "x": 30.73, + "y": 0.64, + "color": "2381e3ff" + }, + { + "name": "petal-1", + "parent": "stem3", + "length": 40.11, + "rotation": 70.18, + "x": 34.13, + "y": 3.02, + "color": "2381e3ff" + }, + { + "name": "petal-2", + "parent": "stem3", + "length": 48.62, + "rotation": -80.34, + "x": 32.09, + "y": -4.46, + "color": "2381e3ff" + }, + { "name": "cloud-face", "parent": "cloud", "y": 14.93, "color": "9e82ffff", "icon": "arrowsB" } +], +"slots": [ + { "name": "rain/rain-green", "bone": "rain-green", "attachment": "rain-green" }, + { "name": "rain/rain-blue", "bone": "rain-blue", "attachment": "rain-blue" }, + { "name": "rain/rain-color", "bone": "rain-color", "attachment": "rain-color" }, + { "name": "rain/rain-white", "bone": "rain-white", "attachment": "rain-white" }, + { "name": "rain/rain-white-reflex", "bone": "rain-white", "attachment": "rain-white-reflex" }, + { "name": "flower/petal-1", "bone": "petal-1", "attachment": "petal-1" }, + { "name": "flower/petal-2", "bone": "petal-2", "attachment": "petal-2" }, + { "name": "flower/petal-3", "bone": "petal-3", "attachment": "petal-3" }, + { "name": "flower/stem", "bone": "stem", "attachment": "stem" }, + { "name": "flower/leaf-big", "bone": "leaf-big", "attachment": "leaf-big" }, + { "name": "flower/leaf-small", "bone": "leaf-small", "attachment": "leaf-small" }, + { "name": "flower/stem-end", "bone": "stem3", "attachment": "stem-end" }, + { "name": "pot/pot-base", "bone": "pot", "attachment": "pot-base" }, + { "name": "pot/pot-mouth", "bone": "pot-face", "attachment": "pot-mouth-smile-big" }, + { "name": "pot/pot-eyes", "bone": "pot-face", "attachment": "pot-eyes-open" }, + { "name": "cloud/cloud-base/cloud-base-1", "bone": "cloud-base-1", "attachment": "cloud-base-1" }, + { "name": "cloud/cloud-base/cloud-base-2", "bone": "cloud-base-2", "attachment": "cloud-base-2" }, + { "name": "cloud/cloud-base/cloud-base-3", "bone": "cloud-base-3", "attachment": "cloud-base-3" }, + { "name": "cloud/cloud-base/cloud-base-4", "bone": "cloud-base-4", "attachment": "cloud-base-4" }, + { "name": "cloud/cloud-base/cloud-base-5", "bone": "cloud-base-5", "attachment": "cloud-base-5" }, + { "name": "cloud/cloud-base/cloud-base-6", "bone": "cloud-base-6", "attachment": "cloud-base-6" }, + { "name": "cloud/cloud-base/cloud-base-7", "bone": "cloud-base-7", "attachment": "cloud-base-7" }, + { "name": "cloud/cloud-base/cloud-base-8", "bone": "cloud-base-8", "attachment": "cloud-base-8" }, + { "name": "cloud/cloud-base/cloud-base-9", "bone": "cloud-base-9", "attachment": "cloud-base-9" }, + { "name": "cloud/cloud-base/cloud-base-10", "bone": "cloud-base-10", "attachment": "cloud-base-10" }, + { "name": "cloud/cloud-cheeks", "bone": "cloud-face", "attachment": "cloud-cheeks" }, + { "name": "cloud/cloud-eyes", "bone": "cloud-face", "attachment": "cloud-eyes-open" }, + { "name": "cloud/cloud-eyes-reflex", "bone": "cloud-face", "attachment": "cloud-eyes-reflex" }, + { "name": "cloud/cloud-mouth", "bone": "cloud-face", "attachment": "cloud-mouth-closed" } +], +"physics": [ + { + "name": "cloud", + "order": 25, + "bone": "cloud", + "x": 1, + "y": 1, + "inertia": 0.5, + "strength": 172.8, + "damping": 0.8571, + "mass": 3 + }, + { + "name": "cloud-face", + "order": 24, + "bone": "cloud-face", + "x": 0.1923, + "y": 0.141, + "limit": 500, + "inertia": 0.5, + "damping": 0.15 + }, + { + "name": "pot-face", + "order": 23, + "bone": "pot-face", + "x": 0.1667, + "y": 0.1026, + "limit": 500, + "inertia": 0.5, + "strength": 137.3, + "damping": 0.6078 + }, + { + "name": "cloud-base/cloud-base-1", + "order": 4, + "bone": "cloud-base-1", + "x": 1, + "y": 1, + "limit": 500, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-2", + "order": 5, + "bone": "cloud-base-2", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-3", + "order": 6, + "bone": "cloud-base-3", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-4", + "order": 7, + "bone": "cloud-base-4", + "x": 1, + "y": 1, + "limit": 500, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-5", + "order": 8, + "bone": "cloud-base-5", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-6", + "order": 9, + "bone": "cloud-base-6", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-7", + "order": 10, + "bone": "cloud-base-7", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-8", + "order": 11, + "bone": "cloud-base-8", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-9", + "order": 12, + "bone": "cloud-base-9", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "cloud-base/cloud-base-10", + "order": 13, + "bone": "cloud-base-10", + "x": 1, + "y": 1, + "limit": 300, + "inertia": 0.3741, + "strength": 134.7, + "damping": 0.8163, + "mass": 2.8 + }, + { + "name": "plant/leaf-big", + "order": 14, + "bone": "leaf-big", + "rotate": 0.7532, + "shearX": 0.2468, + "limit": 500, + "inertia": 0.5, + "strength": 160.5, + "damping": 0.8367, + "mass": 4 + }, + { + "name": "plant/leaf-big-tip", + "order": 22, + "bone": "leaf-big-tip", + "rotate": 1, + "limit": 500, + "inertia": 0.5, + "strength": 160.5, + "damping": 0.8367, + "mass": 4 + }, + { + "name": "plant/leaf-small", + "order": 15, + "bone": "leaf-small", + "rotate": 0.6026, + "limit": 500, + "inertia": 0.5, + "strength": 160.5, + "damping": 0.8367, + "mass": 4 + }, + { + "name": "plant/petal-1", + "order": 19, + "bone": "petal-1", + "rotate": 1, + "limit": 500, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.6531, + "mass": 2.6 + }, + { + "name": "plant/petal-2", + "order": 21, + "bone": "petal-2", + "rotate": 1, + "limit": 500, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.6531, + "mass": 2.6 + }, + { + "name": "plant/petal-3", + "order": 20, + "bone": "petal-3", + "rotate": 1, + "limit": 500, + "inertia": 0.5, + "strength": 164.6, + "damping": 0.7823, + "mass": 3.83 + }, + { + "name": "plant/stem", + "order": 16, + "bone": "stem", + "rotate": 0.8205, + "limit": 700, + "inertia": 0.5, + "strength": 152.4, + "damping": 0.9388, + "mass": 2.6 + }, + { + "name": "plant/stem2", + "order": 17, + "bone": "stem2", + "rotate": 0.8205, + "limit": 700, + "inertia": 0.5, + "strength": 152.4, + "damping": 0.9388, + "mass": 2.6 + }, + { + "name": "plant/stem3", + "order": 18, + "bone": "stem3", + "rotate": 0.8205, + "limit": 700, + "inertia": 0.5, + "strength": 152.4, + "damping": 0.9388, + "mass": 2.6 + }, + { + "name": "rain/rain-blue", + "order": 3, + "bone": "rain-blue", + "x": 1, + "y": 1, + "strength": 0, + "gravity": 70 + }, + { + "name": "rain/rain-color", + "order": 2, + "bone": "rain-color", + "x": 1, + "y": 1, + "strength": 0, + "gravity": 70 + }, + { + "name": "rain/rain-green", + "order": 1, + "bone": "rain-green", + "x": 1, + "y": 1, + "strength": 0, + "gravity": 70 + }, + { "name": "rain/rain-white", "bone": "rain-white", "x": 1, "y": 1, "strength": 0, "gravity": 70 } +], +"skins": [ + { + "name": "default", + "attachments": { + "cloud/cloud-base/cloud-base-1": { + "cloud-base-1": { "width": 465, "height": 420 } + }, + "cloud/cloud-base/cloud-base-2": { + "cloud-base-2": { "width": 420, "height": 415 } + }, + "cloud/cloud-base/cloud-base-3": { + "cloud-base-3": { "width": 349, "height": 327 } + }, + "cloud/cloud-base/cloud-base-4": { + "cloud-base-4": { "width": 352, "height": 326 } + }, + "cloud/cloud-base/cloud-base-5": { + "cloud-base-5": { "width": 289, "height": 250 } + }, + "cloud/cloud-base/cloud-base-6": { + "cloud-base-6": { "width": 322, "height": 272 } + }, + "cloud/cloud-base/cloud-base-7": { + "cloud-base-7": { "width": 300, "height": 297 } + }, + "cloud/cloud-base/cloud-base-8": { + "cloud-base-8": { "width": 307, "height": 256 } + }, + "cloud/cloud-base/cloud-base-9": { + "cloud-base-9": { "width": 214, "height": 216 } + }, + "cloud/cloud-base/cloud-base-10": { + "cloud-base-10": { "width": 193, "height": 201 } + }, + "cloud/cloud-cheeks": { + "cloud-cheeks": { "x": -19, "y": -53.93, "width": 435, "height": 158 } + }, + "cloud/cloud-eyes": { + "cloud-eyes-closed": { "x": -10, "y": -5.43, "width": 263, "height": 43 }, + "cloud-eyes-open": { "x": -8, "y": -4.43, "width": 265, "height": 51 } + }, + "cloud/cloud-eyes-reflex": { + "cloud-eyes-reflex": { "x": -10, "y": 2.07, "width": 239, "height": 34 } + }, + "cloud/cloud-mouth": { + "cloud-mouth-closed": { "y": -14.93, "width": 97, "height": 32 }, + "cloud-mouth-open": { "x": -0.5, "y": -27.93, "width": 118, "height": 70 } + }, + "flower/leaf-big": { + "leaf-big": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0.75, 0, 0.5, 0, 0.25, 0, 0, 1, 0, 1, 0.25, 1, 0.5, 1, 0.75 ], + "triangles": [ 8, 3, 7, 3, 4, 7, 7, 4, 6, 4, 5, 6, 0, 1, 9, 1, 2, 9, 9, 2, 8, 2, 3, 8 ], + "vertices": [ 1, 19, -5.05, -21.72, 1, 1, 19, -5.05, 18.28, 1, 2, 19, 19.45, 18.28, 0.75483, 20, -27.28, 18.28, 0.24517, 2, 19, 43.95, 18.28, 0.50538, 20, -2.78, 18.28, 0.49462, 2, 19, 68.45, 18.28, 0.25278, 20, 21.72, 18.28, 0.74722, 1, 20, 46.22, 18.28, 1, 1, 20, 46.22, -21.72, 1, 2, 19, 68.45, -21.72, 0.24458, 20, 21.72, -21.72, 0.75542, 2, 19, 43.95, -21.72, 0.4937, 20, -2.78, -21.72, 0.5063, 2, 19, 19.45, -21.72, 0.74651, 20, -27.28, -21.72, 0.25349 ], + "hull": 10, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 0 ], + "width": 40, + "height": 98 + } + }, + "flower/leaf-small": { + "leaf-small": { "x": 25.02, "y": 0.4, "rotation": -91.36, "width": 34, "height": 59 } + }, + "flower/petal-1": { + "petal-1": { "x": 18.88, "y": -4.54, "rotation": -160.18, "width": 52, "height": 36 } + }, + "flower/petal-2": { + "petal-2": { "x": 21.96, "y": 2.06, "rotation": -9.66, "width": 56, "height": 34 } + }, + "flower/petal-3": { + "petal-3": { "x": 16.97, "y": -5.71, "rotation": -91.03, "width": 58, "height": 42 } + }, + "flower/stem": { + "stem": { + "type": "mesh", + "uvs": [ 1, 1, 0, 1, 0, 0.90909, 0, 0.81818, 0, 0.72727, 0, 0.63636, 0, 0.54545, 0, 0.45455, 0, 0.36364, 0, 0.27273, 0, 0.18182, 0, 0.09091, 0, 0, 1, 0, 1, 0.09091, 1, 0.18182, 1, 0.27273, 1, 0.36364, 1, 0.45455, 1, 0.54545, 1, 0.63636, 1, 0.72727, 1, 0.81818, 1, 0.90909 ], + "triangles": [ 15, 10, 14, 10, 11, 14, 14, 11, 13, 11, 12, 13, 18, 7, 17, 7, 8, 17, 17, 8, 16, 8, 9, 16, 16, 9, 15, 9, 10, 15, 0, 1, 23, 1, 2, 23, 23, 2, 22, 2, 3, 22, 22, 3, 21, 3, 4, 21, 21, 4, 20, 4, 5, 20, 20, 5, 19, 5, 6, 19, 19, 6, 18, 6, 7, 18 ], + "vertices": [ 1, 22, -3.61, -6.76, 1, 1, 22, -3.61, 9.24, 1, 3, 22, 15.49, 9.24, 0.97258, 23, -89.27, 9.24, 0.02734, 24, -159.11, 9.24, 8.0E-5, 3, 22, 34.58, 9.24, 0.92758, 23, -70.18, 9.24, 0.07175, 24, -140.02, 9.24, 6.7E-4, 3, 22, 53.67, 9.24, 0.851, 23, -51.09, 9.24, 0.14565, 24, -120.93, 9.24, 0.00335, 3, 22, 72.76, 9.24, 0.73702, 23, -32, 9.24, 0.25075, 24, -101.84, 9.24, 0.01223, 3, 22, 91.85, 9.24, 0.59184, 23, -12.91, 9.24, 0.37282, 24, -82.74, 9.24, 0.03534, 3, 22, 110.94, 9.24, 0.43333, 23, 6.18, 9.24, 0.482, 24, -63.65, 9.24, 0.08467, 3, 22, 130.03, 9.24, 0.28467, 23, 25.27, 9.24, 0.54153, 24, -44.56, 9.24, 0.1738, 3, 22, 149.12, 9.24, 0.16502, 23, 44.37, 9.24, 0.52188, 24, -25.47, 9.24, 0.3131, 3, 22, 168.21, 9.24, 0.08234, 23, 63.46, 9.24, 0.4129, 24, -6.38, 9.24, 0.50477, 3, 22, 187.3, 9.24, 0.03198, 23, 82.55, 9.24, 0.228, 24, 12.71, 9.24, 0.74001, 1, 24, 31.8, 9.24, 1, 1, 24, 31.8, -6.76, 1, 3, 22, 187.3, -6.76, 0.02989, 23, 82.55, -6.76, 0.23389, 24, 12.71, -6.76, 0.73622, 3, 22, 168.21, -6.76, 0.07799, 23, 63.46, -6.76, 0.42357, 24, -6.38, -6.76, 0.49844, 3, 22, 149.12, -6.76, 0.1584, 23, 44.37, -6.76, 0.53549, 24, -25.47, -6.76, 0.30611, 3, 22, 130.03, -6.76, 0.27629, 23, 25.27, -6.76, 0.55594, 24, -44.56, -6.76, 0.16777, 3, 22, 110.94, -6.76, 0.42428, 23, 6.18, -6.76, 0.49529, 24, -63.65, -6.76, 0.08044, 3, 22, 91.85, -6.76, 0.58346, 23, -12.91, -6.76, 0.38366, 24, -82.74, -6.76, 0.03289, 3, 22, 72.76, -6.76, 0.73038, 23, -32, -6.76, 0.25856, 24, -101.84, -6.76, 0.01107, 3, 22, 53.67, -6.76, 0.84652, 23, -51.09, -6.76, 0.15057, 24, -120.93, -6.76, 0.00291, 3, 22, 34.58, -6.76, 0.92506, 23, -70.18, -6.76, 0.0744, 24, -140.02, -6.76, 5.4E-4, 3, 22, 15.49, -6.76, 0.97151, 23, -89.27, -6.76, 0.02843, 24, -159.11, -6.76, 6.0E-5 ], + "hull": 24, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46, 0 ], + "width": 16, + "height": 210 + } + }, + "flower/stem-end": { + "stem-end": { "x": 25.8, "y": -0.26, "rotation": -90, "width": 25, "height": 26 } + }, + "pot/pot-base": { + "pot-base": { "x": 5, "y": 42, "width": 152, "height": 118 } + }, + "pot/pot-eyes": { + "pot-eyes-closed": { "x": -0.94, "y": 2.34, "width": 92, "height": 17 }, + "pot-eyes-open": { "x": 0.06, "y": 3.84, "width": 80, "height": 22 } + }, + "pot/pot-mouth": { + "pot-mouth-open": { "x": -1.44, "y": -13.66, "width": 27, "height": 31 }, + "pot-mouth-pouty": { "x": 0.56, "y": -12.66, "width": 35, "height": 19 }, + "pot-mouth-smile": { "x": 0.56, "y": -12.16, "width": 27, "height": 20 }, + "pot-mouth-smile-big": { "x": 1.56, "y": -9.16, "width": 39, "height": 18 } + }, + "rain/rain-blue": { + "rain-blue": { "width": 23, "height": 36 } + }, + "rain/rain-color": { + "rain-color": { "width": 18, "height": 34 } + }, + "rain/rain-green": { + "rain-green": { "width": 23, "height": 36 } + }, + "rain/rain-white": { + "rain-white": { "width": 23, "height": 44 } + }, + "rain/rain-white-reflex": { + "rain-white-reflex": { "x": -0.5, "y": 3.5, "width": 10, "height": 19 } + } + } + } +], +"animations": { + "playing-in-the-rain": { + "slots": { + "cloud/cloud-eyes": { + "attachment": [ + { "time": 0.2, "name": "cloud-eyes-closed" }, + { "time": 0.9, "name": "cloud-eyes-open" }, + { "time": 1.7667, "name": "cloud-eyes-closed" }, + { "time": 1.9333, "name": "cloud-eyes-open" }, + { "time": 2.4333, "name": "cloud-eyes-closed" }, + { "time": 2.6, "name": "cloud-eyes-open" }, + { "time": 3.9333, "name": "cloud-eyes-closed" }, + { "time": 4.1, "name": "cloud-eyes-open" } + ] + }, + "cloud/cloud-mouth": { + "attachment": [ + { "time": 0.2, "name": "cloud-mouth-open" }, + { "time": 0.9, "name": "cloud-mouth-closed" } + ] + }, + "pot/pot-eyes": { + "attachment": [ + { "time": 0.1333, "name": "pot-eyes-closed" }, + { "time": 0.3, "name": "pot-eyes-open" }, + { "time": 1.0667, "name": "pot-eyes-closed" }, + { "time": 1.5, "name": "pot-eyes-open" }, + { "time": 3.0333, "name": "pot-eyes-closed" }, + { "time": 3.2333, "name": "pot-eyes-open" }, + { "time": 3.4667, "name": "pot-eyes-closed" }, + { "time": 3.6667, "name": "pot-eyes-open" } + ] + }, + "pot/pot-mouth": { + "attachment": [ + { "time": 0.1333, "name": "pot-mouth-open" }, + { "time": 0.3, "name": "pot-mouth-smile-big" }, + { "time": 1.0667, "name": "pot-mouth-pouty" }, + { "time": 2.4, "name": "pot-mouth-smile" }, + { "time": 3.0333, "name": "pot-mouth-smile-big" } + ] + } + }, + "bones": { + "pot": { + "rotate": [ + { "time": 1.1 }, + { "time": 1.2, "value": -12.76 }, + { "time": 1.5333, "curve": "stepped" }, + { "time": 3.7667 }, + { "time": 3.9, "value": 8.28 }, + { "time": 4.2333, "value": -4.34 }, + { "time": 4.4333 } + ], + "scale": [ + {}, + { "time": 0.2, "y": 0.752 }, + { "time": 0.4, "x": 0.845, "y": 1.068 }, + { "time": 0.6333 } + ] + }, + "pot-control": { + "translatex": [ + { + "time": 1.0667, + "curve": [ 1.222, -203.48, 1.378, -610.44 ] + }, + { "time": 1.5333, "value": -610.44, "curve": "stepped" }, + { + "time": 2.2333, + "value": -610.44, + "curve": [ 2.389, -610.44, 2.544, -478.45 ] + }, + { "time": 2.7, "value": -478.45, "curve": "stepped" }, + { + "time": 3.8333, + "value": -478.45, + "curve": [ 3.971, -478.45, 4.095, -135.56 ] + }, + { "time": 4.2333 } + ], + "translatey": [ + { + "time": 1.0333, + "curve": [ 1.089, 10.56, 1.144, 44.34 ] + }, + { + "time": 1.2, + "value": 44.34, + "curve": [ 1.256, 44.34, 1.311, 0 ] + }, + { "time": 1.3667, "curve": "stepped" }, + { + "time": 2.2333, + "curve": [ 2.408, 0, 2.392, 44.34 ] + }, + { + "time": 2.4333, + "value": 44.34, + "curve": [ 2.455, 44.34, 2.51, 0 ] + }, + { "time": 2.6, "curve": "stepped" }, + { + "time": 3.8, + "curve": [ 3.841, 14.78, 3.893, 44.34 ] + }, + { + "time": 3.9333, + "value": 44.34, + "curve": [ 4.023, 44.34, 4.111, 14.78 ] + }, + { "time": 4.2 } + ] + }, + "cloud-base-1": { + "rotate": [ + { + "curve": [ 0.144, -9.36, 0.289, -17.29 ] + }, + { + "time": 0.4333, + "value": -17.29, + "curve": [ 0.5, -17.29, 0.567, -4.32 ] + }, + { "time": 0.6333 } + ], + "scale": [ + { + "curve": [ 0.089, 1, 0.178, 1.064, 0.089, 1, 0.178, 1.064 ] + }, + { + "time": 0.2667, + "x": 1.064, + "y": 1.064, + "curve": [ 0.411, 1.064, 0.556, 1.021, 0.411, 1.064, 0.556, 1.021 ] + }, + { "time": 0.7 } + ] + }, + "cloud-base-4": { + "rotate": [ + { + "curve": [ 0.1, 5.55, 0.2, 14.81 ] + }, + { + "time": 0.3, + "value": 14.81, + "curve": [ 0.467, 14.81, 0.633, 9.25 ] + }, + { "time": 0.8 } + ], + "scale": [ + { + "curve": [ 0.089, 1, 0.178, 1.064, 0.089, 1, 0.178, 1.064 ] + }, + { + "time": 0.2667, + "x": 1.064, + "y": 1.064, + "curve": [ 0.411, 1.064, 0.556, 1.021, 0.411, 1.064, 0.556, 1.021 ] + }, + { "time": 0.7 } + ] + }, + "cloud": { + "translate": [ + { "time": 0.2333 }, + { "time": 0.3333, "y": 30.43 }, + { "time": 0.4667 }, + { "time": 0.5667, "y": 30.43 }, + { "time": 0.6667 }, + { "time": 0.7667, "y": 30.43 }, + { "time": 0.9333 } + ] + } + }, + "physics": { + "rain/rain-blue": { + "reset": [ + { "time": 0.4667 }, + { "time": 0.9333 }, + { "time": 1.4 }, + { "time": 1.8667 }, + { "time": 2.3333 }, + { "time": 2.8 }, + { "time": 3.2667 }, + { "time": 3.7333 }, + { "time": 4.2 }, + { "time": 4.6667 } + ] + }, + "rain/rain-color": { + "reset": [ + { "time": 0.3 }, + { "time": 0.7667 }, + { "time": 1.2333 }, + { "time": 1.7 }, + { "time": 2.1667 }, + { "time": 2.6333 }, + { "time": 3.1 }, + { "time": 3.5667 }, + { "time": 4.0333 }, + { "time": 4.5 } + ] + }, + "rain/rain-green": { + "reset": [ + { "time": 0.1333 }, + { "time": 0.6 }, + { "time": 1.0667 }, + { "time": 1.5333 }, + { "time": 2 }, + { "time": 2.4667 }, + { "time": 2.9333 }, + { "time": 3.4 }, + { "time": 3.8667 }, + { "time": 4.3333 } + ] + }, + "rain/rain-white": { + "reset": [ + {}, + { "time": 0.4667 }, + { "time": 0.9333 }, + { "time": 1.4 }, + { "time": 1.8667 }, + { "time": 2.3333 }, + { "time": 2.8 }, + { "time": 3.2667 }, + { "time": 3.7333 }, + { "time": 4.2 } + ] + } + } + }, + "pot-moving-followed-by-rain": { + "bones": { + "pot-control": { + "translate": [ + {}, + { "time": 0.5667, "x": -389.34, "curve": "stepped" }, + { "time": 1.1667, "x": -389.34 }, + { "time": 2.2, "x": 463.88, "curve": "stepped" }, + { "time": 2.4667, "x": 463.88 }, + { "time": 3 } + ] + } + }, + "physics": { + "rain/rain-blue": { + "reset": [ + { "time": 0.4667 }, + { "time": 0.9333 }, + { "time": 1.4 }, + { "time": 1.8667 }, + { "time": 2.3333 }, + { "time": 2.8 }, + { "time": 3.2667 } + ] + }, + "rain/rain-color": { + "reset": [ + { "time": 0.3 }, + { "time": 0.7667 }, + { "time": 1.2333 }, + { "time": 1.7 }, + { "time": 2.1667 }, + { "time": 2.6333 }, + { "time": 3.1 } + ] + }, + "rain/rain-green": { + "reset": [ + { "time": 0.1333 }, + { "time": 0.6 }, + { "time": 1.0667 }, + { "time": 1.5333 }, + { "time": 2 }, + { "time": 2.4667 }, + { "time": 2.9333 } + ] + }, + "rain/rain-white": { + "reset": [ + {}, + { "time": 0.4667 }, + { "time": 0.9333 }, + { "time": 1.4 }, + { "time": 1.8667 }, + { "time": 2.3333 }, + { "time": 2.8 } + ] + } + } + }, + "rain": { + "physics": { + "rain/rain-blue": { + "reset": [ + { "time": 0.4667 } + ] + }, + "rain/rain-color": { + "reset": [ + { "time": 0.3 } + ] + }, + "rain/rain-green": { + "reset": [ + { "time": 0.1333 } + ] + }, + "rain/rain-white": { + "reset": [ + {} + ] + } + } + } +} +} \ No newline at end of file diff --git a/spine-ts/spine-phaser-v4/example/assets/cloud-pot.png b/spine-ts/spine-phaser-v4/example/assets/cloud-pot.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5ef99a1a148e04e1d149287f33e45ba6689da7 GIT binary patch literal 336346 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

      8qK^}SksnciARe;$MUFr=WXl8r1t}G84IhN# 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 literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/cloud-pot.skel b/spine-ts/spine-phaser-v4/example/assets/cloud-pot.skel new file mode 100644 index 0000000000000000000000000000000000000000..d25759ceaeb1fafec0c8baacb87d589d5156fc36 GIT binary patch literal 8397 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

      i8`0max$yc^&nxUBl?kzyCJTjFWg0 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ΠF)L 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 X!!3&mVyCl`K~{OX`njxgN@xNASB>?& literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/coin-pro.skel b/spine-ts/spine-phaser-v4/example/assets/coin-pro.skel new file mode 100644 index 0000000000000000000000000000000000000000..b43113b01d9b16c2c049b13a97e1cf606cd3c8f1 GIT binary patch literal 2790 zcma)63s96*6u$TF3l=aP@e!DkS_%jlP^rM)fBzpdbjHUxFy$1!SYRF8W!Oat<&g^E zgBdC@^O0pXLzpGn3~0Iw|5lo!Ax-L#|I;iThtXfIYk#A9UC1R>l$5(U84|^wwGe*1BAqr2w~%Gg!Iud=9NpcOtu*8=f6D1 zoSSR5WQ|;IHCv)G^Q;zolr7tAF-7HAv#cQxo!S`Lw9NX}aBi`gGfYu7d)`uWRQGp57mM|AUveU%pSOpXhuCdkfw>g`|Q^DzS$K@m9 zKHC`CZA4;0+V3vE(8c1Iv7fpEga0+|E^KuLWk)*1Eyn>j)t~>vr9C-Ceo5_?yVqQm zH(ZUAukD>9*DOEA;#JD0J6@4L?j-Wfz#2J!-6Xm9M422~^PfxGlHT<0u|2MU8 zR*Bv9>*ZDL>5>+Q$>H6%Aa$Kii%*M3>6g{nQ#{u7b6

      dg=Ygx8Bz(1M+m_I zYNnvFvNE@U1%gRMG%}kXAi8>W0h|yz{opP-YF`P>u# z!L+^oGK5Cd{aqtBLG9cm43CTFCa9X5l#+DD6j~fvmm+gn)xuTUdjK7fWhF!tPpP)D8?HG>HsERY8}5>&xQBh5FY?ym^}Jb zFc|*1{ZZ1<=qg{#9awP*rs%_<^Wr>F2u%rzG&~d31I6$|hPm`$R-DI^(1ywhw5WRt z{qxktq#tI^=a_{A3{FtIhm4_kZyG^&<+>rH@{SPZAHtaobJ>U0kLqpXg&U0s7W7uQ z8hjq~hkGkHPtuqjB)Ilh^b4Zj_lXQ=DQp~K?Dr2Eq@0R{tLF4>nHyP0whblz`g=pE$>>Gaq) z9O%q4`exch$2ZsS0_GkJbIB&z36a<)w7g-Fb5?jR{Vcq}SrXq3n3EV*$o;*?w2`G+ zH1&JMvo0=^mW=bG4GD8;?zXuUFoXpRvLiFg@X3%=g?w`SEK1Ao(>BdLN|Luxz(4{F zk`0IV)9GJdjyGtqiT2L9o@fca0+^E+1_|Bwe!38N^H;~wAJ>C{2&6di_oX1VAIGik?C+f2>lPg7Dt8v literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.atlas b/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.atlas new file mode 100644 index 000000000..b4cc35fa9 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.atlas @@ -0,0 +1,359 @@ +mix-and-match-pma.png + size: 1024, 512 + filter: Linear, Linear + pma: true + scale: 0.5 +base-head + bounds: 118, 70, 95, 73 +boy/arm-front + bounds: 831, 311, 36, 115 + rotate: 90 +boy/backpack + bounds: 249, 357, 119, 153 +boy/backpack-pocket + bounds: 628, 193, 34, 62 + rotate: 90 +boy/backpack-strap-front + bounds: 330, 263, 38, 88 + rotate: 90 +boy/backpack-up + bounds: 482, 171, 21, 70 +boy/body + bounds: 845, 413, 97, 132 + rotate: 90 +boy/boot-ribbon-front + bounds: 234, 304, 9, 11 +boy/collar + bounds: 471, 243, 73, 29 + rotate: 90 +boy/ear + bounds: 991, 352, 19, 23 + rotate: 90 +boy/eye-back-low-eyelid + bounds: 66, 72, 17, 6 +boy/eye-back-pupil + bounds: 694, 279, 8, 9 + rotate: 90 +boy/eye-back-up-eyelid + bounds: 460, 101, 23, 5 + rotate: 90 +boy/eye-back-up-eyelid-back + bounds: 979, 414, 19, 10 + rotate: 90 +boy/eye-front-low-eyelid + bounds: 1015, 203, 22, 7 + rotate: 90 +boy/eye-front-pupil + bounds: 309, 50, 9, 9 +boy/eye-front-up-eyelid + bounds: 991, 373, 31, 6 +boy/eye-front-up-eyelid-back + bounds: 107, 76, 26, 9 + rotate: 90 +boy/eye-iris-back + bounds: 810, 260, 17, 17 +boy/eye-iris-front + bounds: 902, 230, 18, 18 +boy/eye-white-back + bounds: 599, 179, 20, 12 +boy/eye-white-front + bounds: 544, 183, 27, 13 +boy/eyebrow-back + bounds: 1002, 225, 20, 11 + rotate: 90 +boy/eyebrow-front + bounds: 975, 234, 25, 11 +boy/hair-back + bounds: 629, 289, 122, 81 + rotate: 90 +boy/hair-bangs + bounds: 505, 180, 70, 37 + rotate: 90 +boy/hair-side + bounds: 979, 435, 25, 43 + rotate: 90 +boy/hand-backfingers + bounds: 858, 183, 19, 21 +boy/hand-front-fingers + bounds: 879, 183, 19, 21 +boy/hat + bounds: 218, 121, 93, 56 +boy/leg-front + bounds: 85, 104, 31, 158 +boy/mouth-close + bounds: 467, 100, 21, 5 +girl-blue-cape/mouth-close + bounds: 467, 100, 21, 5 +girl-spring-dress/mouth-close + bounds: 467, 100, 21, 5 +girl/mouth-close + bounds: 467, 100, 21, 5 +boy/mouth-smile + bounds: 1015, 258, 29, 7 + rotate: 90 +boy/nose + bounds: 323, 79, 17, 10 +boy/pompom + bounds: 979, 462, 48, 43 + rotate: 90 +boy/zip + bounds: 922, 231, 14, 23 + rotate: 90 +girl-blue-cape/back-eyebrow + bounds: 527, 106, 18, 12 + rotate: 90 +girl-blue-cape/body-dress + bounds: 2, 264, 109, 246 +girl-blue-cape/body-ribbon + bounds: 576, 193, 50, 38 +girl-blue-cape/cape-back + bounds: 113, 317, 134, 193 +girl-blue-cape/cape-back-up + bounds: 504, 305, 123, 106 +girl-blue-cape/cape-ribbon + bounds: 396, 118, 50, 18 + rotate: 90 +girl-blue-cape/cape-shoulder-back + bounds: 420, 243, 49, 59 +girl-blue-cape/cape-shoulder-front + bounds: 2, 2, 62, 76 +girl-blue-cape/cape-up-front + bounds: 118, 145, 98, 117 +girl-blue-cape/ear + bounds: 837, 181, 19, 23 +girl-spring-dress/ear + bounds: 837, 181, 19, 23 +girl/ear + bounds: 837, 181, 19, 23 +girl-blue-cape/eye-back-low-eyelid + bounds: 810, 252, 17, 6 +girl-spring-dress/eye-back-low-eyelid + bounds: 810, 252, 17, 6 +girl/eye-back-low-eyelid + bounds: 810, 252, 17, 6 +girl-blue-cape/eye-back-pupil + bounds: 309, 40, 8, 9 + rotate: 90 +girl-spring-dress/eye-back-pupil + bounds: 309, 40, 8, 9 + rotate: 90 +girl/eye-back-pupil + bounds: 309, 40, 8, 9 + rotate: 90 +girl-blue-cape/eye-back-up-eyelid + bounds: 573, 179, 24, 12 +girl-spring-dress/eye-back-up-eyelid + bounds: 573, 179, 24, 12 +girl/eye-back-up-eyelid + bounds: 573, 179, 24, 12 +girl-blue-cape/eye-back-up-eyelid-back + bounds: 380, 105, 17, 11 + rotate: 90 +girl-spring-dress/eye-back-up-eyelid-back + bounds: 380, 105, 17, 11 + rotate: 90 +girl/eye-back-up-eyelid-back + bounds: 380, 105, 17, 11 + rotate: 90 +girl-blue-cape/eye-front-low-eyelid + bounds: 1016, 353, 18, 6 + rotate: 90 +girl-spring-dress/eye-front-low-eyelid + bounds: 1016, 353, 18, 6 + rotate: 90 +girl/eye-front-low-eyelid + bounds: 1016, 353, 18, 6 + rotate: 90 +girl-blue-cape/eye-front-pupil + bounds: 363, 94, 9, 9 +girl-spring-dress/eye-front-pupil + bounds: 363, 94, 9, 9 +girl/eye-front-pupil + bounds: 363, 94, 9, 9 +girl-blue-cape/eye-front-up-eyelid + bounds: 679, 413, 30, 14 + rotate: 90 +girl-spring-dress/eye-front-up-eyelid + bounds: 679, 413, 30, 14 + rotate: 90 +girl/eye-front-up-eyelid + bounds: 679, 413, 30, 14 + rotate: 90 +girl-blue-cape/eye-front-up-eyelid-back + bounds: 947, 234, 26, 11 +girl-spring-dress/eye-front-up-eyelid-back + bounds: 947, 234, 26, 11 +girl/eye-front-up-eyelid-back + bounds: 947, 234, 26, 11 +girl-blue-cape/eye-iris-back + bounds: 323, 105, 17, 17 +girl-blue-cape/eye-iris-front + bounds: 467, 107, 18, 18 +girl-blue-cape/eye-white-back + bounds: 621, 175, 20, 16 +girl-spring-dress/eye-white-back + bounds: 621, 175, 20, 16 +girl-blue-cape/eye-white-front + bounds: 643, 175, 20, 16 +girl-spring-dress/eye-white-front + bounds: 643, 175, 20, 16 +girl/eye-white-front + bounds: 643, 175, 20, 16 +girl-blue-cape/front-eyebrow + bounds: 309, 101, 18, 12 + rotate: 90 +girl-blue-cape/hair-back + bounds: 712, 317, 117, 98 +girl-blue-cape/hair-bangs + bounds: 313, 170, 91, 40 + rotate: 90 +girl-blue-cape/hair-head-side-back + bounds: 544, 198, 30, 52 +girl-blue-cape/hair-head-side-front + bounds: 466, 127, 41, 42 +girl-blue-cape/hair-side + bounds: 175, 2, 36, 71 + rotate: 90 +girl-blue-cape/hand-front-fingers + bounds: 902, 207, 19, 21 +girl-spring-dress/hand-front-fingers + bounds: 902, 207, 19, 21 +girl-blue-cape/leg-front + bounds: 519, 413, 30, 158 + rotate: 90 +girl-blue-cape/mouth-smile + bounds: 1015, 227, 29, 7 + rotate: 90 +girl-spring-dress/mouth-smile + bounds: 1015, 227, 29, 7 + rotate: 90 +girl/mouth-smile + bounds: 1015, 227, 29, 7 + rotate: 90 +girl-blue-cape/nose + bounds: 342, 82, 11, 7 +girl-spring-dress/nose + bounds: 342, 82, 11, 7 +girl/nose + bounds: 342, 82, 11, 7 +girl-blue-cape/sleeve-back + bounds: 416, 95, 42, 29 +girl-blue-cape/sleeve-front + bounds: 249, 303, 52, 119 + rotate: 90 +girl-spring-dress/arm-front + bounds: 829, 292, 17, 111 + rotate: 90 +girl-spring-dress/back-eyebrow + bounds: 309, 81, 18, 12 + rotate: 90 +girl-spring-dress/body-up + bounds: 66, 2, 64, 66 +girl-spring-dress/cloak-down + bounds: 758, 227, 50, 50 +girl-spring-dress/cloak-up + bounds: 628, 229, 64, 58 +girl-spring-dress/eye-iris-back + bounds: 342, 105, 17, 17 +girl-spring-dress/eye-iris-front + bounds: 487, 107, 18, 18 +girl-spring-dress/front-eyebrow + bounds: 323, 91, 18, 12 +girl-spring-dress/hair-back + bounds: 370, 417, 147, 93 +girl-spring-dress/hair-bangs + bounds: 829, 250, 91, 40 +girl-spring-dress/hair-head-side-back + bounds: 509, 126, 30, 52 +girl-spring-dress/hair-head-side-front + bounds: 816, 206, 41, 42 +girl-spring-dress/hair-side + bounds: 248, 2, 36, 71 + rotate: 90 +girl-spring-dress/leg-front + bounds: 831, 381, 30, 158 + rotate: 90 +girl-spring-dress/neck + bounds: 85, 70, 20, 32 +girl-spring-dress/shoulder-ribbon + bounds: 175, 44, 36, 24 +girl-spring-dress/skirt + bounds: 2, 80, 182, 81 + rotate: 90 +girl-spring-dress/underskirt + bounds: 519, 445, 175, 65 +girl/arm-front + bounds: 712, 279, 36, 115 + rotate: 90 +girl/back-eyebrow + bounds: 309, 61, 18, 12 + rotate: 90 +girl/bag-base + bounds: 694, 219, 62, 58 +girl/bag-strap-front + bounds: 370, 304, 12, 96 + rotate: 90 +girl/bag-top + bounds: 765, 175, 49, 50 +girl/body + bounds: 370, 318, 97, 132 + rotate: 90 +girl/boot-ribbon-front + bounds: 323, 64, 13, 13 +girl/eye-iris-back + bounds: 361, 105, 17, 17 +girl/eye-iris-front + bounds: 507, 106, 18, 18 +girl/eye-white-back + bounds: 665, 175, 20, 16 +girl/front-eyebrow + bounds: 343, 91, 18, 12 +girl/hair-back + bounds: 696, 417, 147, 93 +girl/hair-bangs + bounds: 922, 247, 91, 40 +girl/hair-flap-down-front + bounds: 415, 171, 70, 65 + rotate: 90 +girl/hair-head-side-back + bounds: 991, 381, 30, 52 +girl/hair-head-side-front + bounds: 859, 206, 41, 42 +girl/hair-patch + bounds: 132, 2, 66, 41 + rotate: 90 +girl/hair-side + bounds: 692, 181, 36, 71 + rotate: 90 +girl/hair-strand-back-1 + bounds: 948, 289, 58, 74 + rotate: 90 +girl/hair-strand-back-2 + bounds: 355, 170, 91, 58 + rotate: 90 +girl/hair-strand-back-3 + bounds: 215, 40, 92, 79 +girl/hair-strand-front-1 + bounds: 234, 263, 38, 94 + rotate: 90 +girl/hair-strand-front-2 + bounds: 576, 233, 70, 50 + rotate: 90 +girl/hair-strand-front-3 + bounds: 313, 124, 44, 81 + rotate: 90 +girl/hand-front-fingers + bounds: 923, 208, 19, 21 +girl/hat + bounds: 218, 179, 93, 82 +girl/leg-front + bounds: 831, 349, 30, 158 + rotate: 90 +girl/pompom + bounds: 416, 126, 48, 43 +girl/scarf + bounds: 113, 264, 119, 51 +girl/scarf-back + bounds: 502, 252, 72, 51 +girl/zip + bounds: 816, 179, 19, 25 diff --git a/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.png b/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pma.png new file mode 100644 index 0000000000000000000000000000000000000000..0f60ebf9a36e3bfe34d6e32db17296caaa6ee747 GIT binary patch literal 377480 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%0Df67kLY~VdjJzqE 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

      f9qQ_K(4bd!}#KT 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%0AUEAJ6cXy{CAR*l&f^-Q;NVjx%4AR}*pmcYq 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 literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pro.skel b/spine-ts/spine-phaser-v4/example/assets/mix-and-match-pro.skel new file mode 100644 index 0000000000000000000000000000000000000000..afe6d4738131a62223089f0004bbc0bad83606f1 GIT binary patch literal 259912 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 literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/phaser.js b/spine-ts/spine-phaser-v4/example/assets/phaser.js new file mode 100644 index 000000000..ac91fc044 --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/phaser.js @@ -0,0 +1,246192 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define("Phaser", [], factory); + else if(typeof exports === 'object') + exports["Phaser"] = factory(); + else + root["Phaser"] = factory(); +})(this, () => { +return /******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 50792: +/***/ ((module) => { + +"use strict"; + + +var has = Object.prototype.hasOwnProperty + , prefix = '~'; + +/** + * Constructor to create a storage for our `EE` objects. + * An `Events` instance is a plain object whose properties are event names. + * + * @constructor + * @private + */ +function Events() {} + +// +// We try to not inherit from `Object.prototype`. In some engines creating an +// instance in this way is faster than calling `Object.create(null)` directly. +// If `Object.create(null)` is not supported we prefix the event names with a +// character to make sure that the built-in object properties are not +// overridden or used as an attack vector. +// +if (Object.create) { + Events.prototype = Object.create(null); + + // + // This hack is needed because the `__proto__` property is still inherited in + // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. + // + if (!new Events().__proto__) prefix = false; +} + +/** + * Representation of a single event listener. + * + * @param {Function} fn The listener function. + * @param {*} context The context to invoke the listener with. + * @param {Boolean} [once=false] Specify if the listener is a one-time listener. + * @constructor + * @private + */ +function EE(fn, context, once) { + this.fn = fn; + this.context = context; + this.once = once || false; +} + +/** + * Add a listener for a given event. + * + * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. + * @param {(String|Symbol)} event The event name. + * @param {Function} fn The listener function. + * @param {*} context The context to invoke the listener with. + * @param {Boolean} once Specify if the listener is a one-time listener. + * @returns {EventEmitter} + * @private + */ +function addListener(emitter, event, fn, context, once) { + if (typeof fn !== 'function') { + throw new TypeError('The listener must be a function'); + } + + var listener = new EE(fn, context || emitter, once) + , evt = prefix ? prefix + event : event; + + if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; + else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); + else emitter._events[evt] = [emitter._events[evt], listener]; + + return emitter; +} + +/** + * Clear event by name. + * + * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. + * @param {(String|Symbol)} evt The Event name. + * @private + */ +function clearEvent(emitter, evt) { + if (--emitter._eventsCount === 0) emitter._events = new Events(); + else delete emitter._events[evt]; +} + +/** + * Minimal `EventEmitter` interface that is molded against the Node.js + * `EventEmitter` interface. + * + * @constructor + * @public + */ +function EventEmitter() { + this._events = new Events(); + this._eventsCount = 0; +} + +/** + * Return an array listing the events for which the emitter has registered + * listeners. + * + * @returns {Array} + * @public + */ +EventEmitter.prototype.eventNames = function eventNames() { + var names = [] + , events + , name; + + if (this._eventsCount === 0) return names; + + for (name in (events = this._events)) { + if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); + } + + if (Object.getOwnPropertySymbols) { + return names.concat(Object.getOwnPropertySymbols(events)); + } + + return names; +}; + +/** + * Return the listeners registered for a given event. + * + * @param {(String|Symbol)} event The event name. + * @returns {Array} The registered listeners. + * @public + */ +EventEmitter.prototype.listeners = function listeners(event) { + var evt = prefix ? prefix + event : event + , handlers = this._events[evt]; + + if (!handlers) return []; + if (handlers.fn) return [handlers.fn]; + + for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { + ee[i] = handlers[i].fn; + } + + return ee; +}; + +/** + * Return the number of listeners listening to a given event. + * + * @param {(String|Symbol)} event The event name. + * @returns {Number} The number of listeners. + * @public + */ +EventEmitter.prototype.listenerCount = function listenerCount(event) { + var evt = prefix ? prefix + event : event + , listeners = this._events[evt]; + + if (!listeners) return 0; + if (listeners.fn) return 1; + return listeners.length; +}; + +/** + * Calls each of the listeners registered for a given event. + * + * @param {(String|Symbol)} event The event name. + * @returns {Boolean} `true` if the event had listeners, else `false`. + * @public + */ +EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { + var evt = prefix ? prefix + event : event; + + if (!this._events[evt]) return false; + + var listeners = this._events[evt] + , len = arguments.length + , args + , i; + + if (listeners.fn) { + if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); + + switch (len) { + case 1: return listeners.fn.call(listeners.context), true; + case 2: return listeners.fn.call(listeners.context, a1), true; + case 3: return listeners.fn.call(listeners.context, a1, a2), true; + case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; + case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; + case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; + } + + for (i = 1, args = new Array(len -1); i < len; i++) { + args[i - 1] = arguments[i]; + } + + listeners.fn.apply(listeners.context, args); + } else { + var length = listeners.length + , j; + + for (i = 0; i < length; i++) { + if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); + + switch (len) { + case 1: listeners[i].fn.call(listeners[i].context); break; + case 2: listeners[i].fn.call(listeners[i].context, a1); break; + case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; + case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; + default: + if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { + args[j - 1] = arguments[j]; + } + + listeners[i].fn.apply(listeners[i].context, args); + } + } + } + + return true; +}; + +/** + * Add a listener for a given event. + * + * @param {(String|Symbol)} event The event name. + * @param {Function} fn The listener function. + * @param {*} [context=this] The context to invoke the listener with. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.on = function on(event, fn, context) { + return addListener(this, event, fn, context, false); +}; + +/** + * Add a one-time listener for a given event. + * + * @param {(String|Symbol)} event The event name. + * @param {Function} fn The listener function. + * @param {*} [context=this] The context to invoke the listener with. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.once = function once(event, fn, context) { + return addListener(this, event, fn, context, true); +}; + +/** + * Remove the listeners of a given event. + * + * @param {(String|Symbol)} event The event name. + * @param {Function} fn Only remove the listeners that match this function. + * @param {*} context Only remove the listeners that have this context. + * @param {Boolean} once Only remove one-time listeners. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { + var evt = prefix ? prefix + event : event; + + if (!this._events[evt]) return this; + if (!fn) { + clearEvent(this, evt); + return this; + } + + var listeners = this._events[evt]; + + if (listeners.fn) { + if ( + listeners.fn === fn && + (!once || listeners.once) && + (!context || listeners.context === context) + ) { + clearEvent(this, evt); + } + } else { + for (var i = 0, events = [], length = listeners.length; i < length; i++) { + if ( + listeners[i].fn !== fn || + (once && !listeners[i].once) || + (context && listeners[i].context !== context) + ) { + events.push(listeners[i]); + } + } + + // + // Reset the array, or remove it completely if we have no more listeners. + // + if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; + else clearEvent(this, evt); + } + + return this; +}; + +/** + * Remove all listeners, or those of the specified event. + * + * @param {(String|Symbol)} [event] The event name. + * @returns {EventEmitter} `this`. + * @public + */ +EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { + var evt; + + if (event) { + evt = prefix ? prefix + event : event; + if (this._events[evt]) clearEvent(this, evt); + } else { + this._events = new Events(); + this._eventsCount = 0; + } + + return this; +}; + +// +// Alias methods names because people roll like that. +// +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +// +// Expose the prefix. +// +EventEmitter.prefixed = prefix; + +// +// Allow `EventEmitter` to be imported as module namespace. +// +EventEmitter.EventEmitter = EventEmitter; + +// +// Expose the module. +// +if (true) { + module.exports = EventEmitter; +} + + +/***/ }), + +/***/ 11517: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var QuickSet = __webpack_require__(38829); + +/** + * Takes an array of Game Objects and aligns them next to each other. + * + * The alignment position is controlled by the `position` parameter, which should be one + * of the Phaser.Display.Align constants, such as `Phaser.Display.Align.TOP_LEFT`, + * `Phaser.Display.Align.TOP_CENTER`, etc. + * + * The first item isn't moved. The second item is aligned next to the first, + * then the third next to the second, and so on. + * + * @function Phaser.Actions.AlignTo + * @since 3.22.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} position - The position to align the items with. This is an align constant, such as `Phaser.Display.Align.LEFT_CENTER`. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var AlignTo = function (items, position, offsetX, offsetY) +{ + var target = items[0]; + + for (var i = 1; i < items.length; i++) + { + var item = items[i]; + + QuickSet(item, target, position, offsetX, offsetY); + + target = item; + } + + return items; +}; + +module.exports = AlignTo; + + +/***/ }), + +/***/ 80318: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `angle` property, + * and then adds the given value to each of their `angle` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `Angle(group.getChildren(), value, step)` + * + * @function Phaser.Actions.Angle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `angle` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var Angle = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'angle', value, step, index, direction); +}; + +module.exports = Angle; + + +/***/ }), + +/***/ 60757: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of objects and passes each of them to the given callback. + * + * @function Phaser.Actions.Call + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {Phaser.Types.Actions.CallCallback} callback - The callback to be invoked. It will be passed just one argument: the item from the array. + * @param {*} context - The scope in which the callback will be invoked. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that was passed to this Action. + */ +var Call = function (items, callback, context) +{ + for (var i = 0; i < items.length; i++) + { + var item = items[i]; + + callback.call(context, item); + } + + return items; +}; + +module.exports = Call; + + +/***/ }), + +/***/ 69927: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of objects and returns the first element in the array that has properties which match + * all of those specified in the `compare` object. For example, if the compare object was: `{ scaleX: 0.5, alpha: 1 }` + * then it would return the first item which had the property `scaleX` set to 0.5 and `alpha` set to 1. + * + * To use this with a Group: `GetFirst(group.getChildren(), compare, index)` + * + * @function Phaser.Actions.GetFirst + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be searched by this action. + * @param {object} compare - The comparison object. Each property in this object will be checked against the items of the array. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * + * @return {?(object|Phaser.GameObjects.GameObject)} The first object in the array that matches the comparison object, or `null` if no match was found. + */ +var GetFirst = function (items, compare, index) +{ + if (index === undefined) { index = 0; } + + for (var i = index; i < items.length; i++) + { + var item = items[i]; + + var match = true; + + for (var property in compare) + { + if (item[property] !== compare[property]) + { + match = false; + } + } + + if (match) + { + return item; + } + } + + return null; +}; + +module.exports = GetFirst; + + +/***/ }), + +/***/ 32265: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of objects and returns the last element in the array that has properties which match + * all of those specified in the `compare` object. For example, if the compare object was: `{ scaleX: 0.5, alpha: 1 }` + * then it would return the last item which had the property `scaleX` set to 0.5 and `alpha` set to 1. + * + * To use this with a Group: `GetLast(group.getChildren(), compare, index)` + * + * @function Phaser.Actions.GetLast + * @since 3.3.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be searched by this action. + * @param {object} compare - The comparison object. Each property in this object will be checked against the items of the array. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * + * @return {?(object|Phaser.GameObjects.GameObject)} The last object in the array that matches the comparison object, or `null` if no match was found. + */ +var GetLast = function (items, compare, index) +{ + if (index === undefined) { index = 0; } + + for (var i = items.length - 1; i >= index; i--) + { + var item = items[i]; + + var match = true; + + for (var property in compare) + { + if (item[property] !== compare[property]) + { + match = false; + } + } + + if (match) + { + return item; + } + } + + return null; +}; + +module.exports = GetLast; + + +/***/ }), + +/***/ 94420: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AlignIn = __webpack_require__(11879); +var CONST = __webpack_require__(60461); +var GetFastValue = __webpack_require__(95540); +var NOOP = __webpack_require__(29747); +var Zone = __webpack_require__(41481); + +var tempZone = new Zone({ sys: { queueDepthSort: NOOP, events: { once: NOOP } } }, 0, 0, 1, 1).setOrigin(0, 0); + +/** + * Takes an array of Game Objects, or any objects that have public `x` and `y` properties, + * and then aligns them based on the grid configuration given to this action. + * + * @function Phaser.Actions.GridAlign + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {Phaser.Types.Actions.GridAlignConfig} options - The GridAlign Configuration object. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var GridAlign = function (items, options) +{ + if (options === undefined) { options = {}; } + + var widthSet = options.hasOwnProperty('width'); + var heightSet = options.hasOwnProperty('height'); + + var width = GetFastValue(options, 'width', -1); + var height = GetFastValue(options, 'height', -1); + + var cellWidth = GetFastValue(options, 'cellWidth', 1); + var cellHeight = GetFastValue(options, 'cellHeight', cellWidth); + + var position = GetFastValue(options, 'position', CONST.TOP_LEFT); + var x = GetFastValue(options, 'x', 0); + var y = GetFastValue(options, 'y', 0); + + var cx = 0; + var cy = 0; + var w = (width * cellWidth); + var h = (height * cellHeight); + + tempZone.setPosition(x, y); + tempZone.setSize(cellWidth, cellHeight); + + for (var i = 0; i < items.length; i++) + { + AlignIn(items[i], tempZone, position); + + if (widthSet && width === -1) + { + // We keep laying them out horizontally until we've done them all + tempZone.x += cellWidth; + } + else if (heightSet && height === -1) + { + // We keep laying them out vertically until we've done them all + tempZone.y += cellHeight; + } + else if (heightSet && !widthSet) + { + // We keep laying them out until we hit the column limit + cy += cellHeight; + tempZone.y += cellHeight; + + if (cy === h) + { + cy = 0; + cx += cellWidth; + tempZone.y = y; + tempZone.x += cellWidth; + + if (cx === w) + { + // We've hit the column limit, so return, even if there are items left + break; + } + } + } + else + { + // We keep laying them out until we hit the column limit + cx += cellWidth; + tempZone.x += cellWidth; + + if (cx === w) + { + cx = 0; + cy += cellHeight; + tempZone.x = x; + tempZone.y += cellHeight; + + if (cy === h) + { + // We've hit the column limit, so return, even if there are items left + break; + } + } + } + } + + return items; +}; + +module.exports = GridAlign; + + +/***/ }), + +/***/ 41721: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `alpha` property, + * and then adds the given value to each of their `alpha` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `IncAlpha(group.getChildren(), value, step)` + * + * @function Phaser.Actions.IncAlpha + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `alpha` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var IncAlpha = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'alpha', value, step, index, direction); +}; + +module.exports = IncAlpha; + + +/***/ }), + +/***/ 67285: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `x` property, + * and then adds the given value to each of their `x` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `IncX(group.getChildren(), value, step)` + * + * @function Phaser.Actions.IncX + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `x` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var IncX = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'x', value, step, index, direction); +}; + +module.exports = IncX; + + +/***/ }), + +/***/ 9074: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have public `x` and `y` properties, + * and then adds the given value to each of them. + * + * The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `IncXY(group.getChildren(), x, y, stepX, stepY)` + * + * @function Phaser.Actions.IncXY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} x - The amount to be added to the `x` property. + * @param {number} [y=x] - The amount to be added to the `y` property. If `undefined` or `null` it uses the `x` value. + * @param {number} [stepX=0] - This is added to the `x` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `y` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var IncXY = function (items, x, y, stepX, stepY, index, direction) +{ + if (y === undefined || y === null) { y = x; } + + PropertyValueInc(items, 'x', x, stepX, index, direction); + + return PropertyValueInc(items, 'y', y, stepY, index, direction); +}; + +module.exports = IncXY; + + +/***/ }), + +/***/ 75222: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `y` property, + * and then adds the given value to each of their `y` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `IncY(group.getChildren(), value, step)` + * + * @function Phaser.Actions.IncY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `y` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var IncY = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'y', value, step, index, direction); +}; + +module.exports = IncY; + + +/***/ }), + +/***/ 22983: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects and positions them on evenly spaced points around the perimeter of a Circle. + * + * If you wish to pass a `Phaser.GameObjects.Circle` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.PlaceOnCircle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Circle} circle - The Circle to position the Game Objects on. + * @param {number} [startAngle=0] - Optional angle to start position from, in radians. + * @param {number} [endAngle=6.28] - Optional angle to stop position at, in radians. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var PlaceOnCircle = function (items, circle, startAngle, endAngle) +{ + if (startAngle === undefined) { startAngle = 0; } + if (endAngle === undefined) { endAngle = 6.28; } + + var angle = startAngle; + var angleStep = (endAngle - startAngle) / items.length; + + var cx = circle.x; + var cy = circle.y; + var radius = circle.radius; + + for (var i = 0; i < items.length; i++) + { + items[i].x = cx + (radius * Math.cos(angle)); + items[i].y = cy + (radius * Math.sin(angle)); + + angle += angleStep; + } + + return items; +}; + +module.exports = PlaceOnCircle; + + +/***/ }), + +/***/ 95253: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects and positions them on evenly spaced points around the perimeter of an Ellipse. + * + * If you wish to pass a `Phaser.GameObjects.Ellipse` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.PlaceOnEllipse + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to position the Game Objects on. + * @param {number} [startAngle=0] - Optional angle to start position from, in radians. + * @param {number} [endAngle=6.28] - Optional angle to stop position at, in radians. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var PlaceOnEllipse = function (items, ellipse, startAngle, endAngle) +{ + if (startAngle === undefined) { startAngle = 0; } + if (endAngle === undefined) { endAngle = 6.28; } + + var angle = startAngle; + var angleStep = (endAngle - startAngle) / items.length; + + var a = ellipse.width / 2; + var b = ellipse.height / 2; + + for (var i = 0; i < items.length; i++) + { + items[i].x = ellipse.x + a * Math.cos(angle); + items[i].y = ellipse.y + b * Math.sin(angle); + + angle += angleStep; + } + + return items; +}; + +module.exports = PlaceOnEllipse; + + +/***/ }), + +/***/ 88505: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetPoints = __webpack_require__(15258); +var GetEasedPoints = __webpack_require__(26708); + +/** + * Positions an array of Game Objects on evenly spaced points of a Line. + * If the ease parameter is supplied, it will space the points based on that easing function along the line. + * + * @function Phaser.Actions.PlaceOnLine + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Line} line - The Line to position the Game Objects on. + * @param {(string|function)} [ease] - An optional ease to use. This can be either a string from the EaseMap, or a custom function. + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var PlaceOnLine = function (items, line, ease) +{ + var points; + + if (ease) + { + points = GetEasedPoints(line, ease, items.length); + } + else + { + points = GetPoints(line, items.length); + } + + for (var i = 0; i < items.length; i++) + { + var item = items[i]; + var point = points[i]; + + item.x = point.x; + item.y = point.y; + } + + return items; +}; + +module.exports = PlaceOnLine; + + +/***/ }), + +/***/ 41346: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MarchingAnts = __webpack_require__(14649); +var RotateLeft = __webpack_require__(86003); +var RotateRight = __webpack_require__(49498); + +/** + * Takes an array of Game Objects and positions them on evenly spaced points around the perimeter of a Rectangle. + * + * Placement starts from the top-left of the rectangle, and proceeds in a clockwise direction. + * If the `shift` parameter is given you can offset where placement begins. + * + * @function Phaser.Actions.PlaceOnRectangle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to position the Game Objects on. + * @param {number} [shift=0] - An optional positional offset. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var PlaceOnRectangle = function (items, rect, shift) +{ + if (shift === undefined) { shift = 0; } + + var points = MarchingAnts(rect, false, items.length); + + if (shift > 0) + { + RotateLeft(points, shift); + } + else if (shift < 0) + { + RotateRight(points, Math.abs(shift)); + } + + for (var i = 0; i < items.length; i++) + { + items[i].x = points[i].x; + items[i].y = points[i].y; + } + + return items; +}; + +module.exports = PlaceOnRectangle; + + +/***/ }), + +/***/ 11575: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BresenhamPoints = __webpack_require__(84993); + +/** + * Takes an array of Game Objects and positions them on evenly spaced points around the edges of a Triangle. + * + * If you wish to pass a `Phaser.GameObjects.Triangle` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.PlaceOnTriangle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Triangle} triangle - The Triangle to position the Game Objects on. + * @param {number} [stepRate=1] - An optional step rate, to increase or decrease the packing of the Game Objects on the lines. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var PlaceOnTriangle = function (items, triangle, stepRate) +{ + var p1 = BresenhamPoints({ x1: triangle.x1, y1: triangle.y1, x2: triangle.x2, y2: triangle.y2 }, stepRate); + var p2 = BresenhamPoints({ x1: triangle.x2, y1: triangle.y2, x2: triangle.x3, y2: triangle.y3 }, stepRate); + var p3 = BresenhamPoints({ x1: triangle.x3, y1: triangle.y3, x2: triangle.x1, y2: triangle.y1 }, stepRate); + + // Remove overlaps + p1.pop(); + p2.pop(); + p3.pop(); + + p1 = p1.concat(p2, p3); + + var step = p1.length / items.length; + var p = 0; + + for (var i = 0; i < items.length; i++) + { + var item = items[i]; + var point = p1[Math.floor(p)]; + + item.x = point.x; + item.y = point.y; + + p += step; + } + + return items; +}; + +module.exports = PlaceOnTriangle; + + +/***/ }), + +/***/ 29953: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Play an animation on all Game Objects in the array that have an Animation component. + * + * You can pass either an animation key, or an animation configuration object for more control over the playback. + * + * @function Phaser.Actions.PlayAnimation + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {boolean} [ignoreIfPlaying=false] - If this animation is already playing then ignore this call. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var PlayAnimation = function (items, key, ignoreIfPlaying) +{ + for (var i = 0; i < items.length; i++) + { + var gameObject = items[i]; + + if (gameObject.anims) + { + gameObject.anims.play(key, ignoreIfPlaying); + } + } + + return items; +}; + +module.exports = PlayAnimation; + + +/***/ }), + +/***/ 66979: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects, or any objects that have a public property as defined in `key`, + * and then adds the given value to it. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `PropertyValueInc(group.getChildren(), key, value, step)` + * + * @function Phaser.Actions.PropertyValueInc + * @since 3.3.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {string} key - The property to be updated. + * @param {number} value - The amount to be added to the property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var PropertyValueInc = function (items, key, value, step, index, direction) +{ + if (step === undefined) { step = 0; } + if (index === undefined) { index = 0; } + if (direction === undefined) { direction = 1; } + + var i; + var t = 0; + var end = items.length; + + if (direction === 1) + { + // Start to End + for (i = index; i < end; i++) + { + items[i][key] += value + (t * step); + t++; + } + } + else + { + // End to Start + for (i = index; i >= 0; i--) + { + items[i][key] += value + (t * step); + t++; + } + } + + return items; +}; + +module.exports = PropertyValueInc; + + +/***/ }), + +/***/ 43967: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects, or any objects that have a public property as defined in `key`, + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `PropertyValueSet(group.getChildren(), key, value, step)` + * + * @function Phaser.Actions.PropertyValueSet + * @since 3.3.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {string} key - The property to be updated. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var PropertyValueSet = function (items, key, value, step, index, direction) +{ + if (step === undefined) { step = 0; } + if (index === undefined) { index = 0; } + if (direction === undefined) { direction = 1; } + + var i; + var t = 0; + var end = items.length; + + if (direction === 1) + { + // Start to End + for (i = index; i < end; i++) + { + items[i][key] = value + (t * step); + t++; + } + } + else + { + // End to Start + for (i = index; i >= 0; i--) + { + items[i][key] = value + (t * step); + t++; + } + } + + return items; +}; + +module.exports = PropertyValueSet; + + +/***/ }), + +/***/ 88926: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Random = __webpack_require__(28176); + +/** + * Takes an array of Game Objects and positions them at random locations within the Circle. + * + * If you wish to pass a `Phaser.GameObjects.Circle` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.RandomCircle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Circle} circle - The Circle to position the Game Objects within. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RandomCircle = function (items, circle) +{ + for (var i = 0; i < items.length; i++) + { + Random(circle, items[i]); + } + + return items; +}; + +module.exports = RandomCircle; + + +/***/ }), + +/***/ 33286: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Random = __webpack_require__(24820); + +/** + * Takes an array of Game Objects and positions them at random locations within the Ellipse. + * + * If you wish to pass a `Phaser.GameObjects.Ellipse` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.RandomEllipse + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to position the Game Objects within. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RandomEllipse = function (items, ellipse) +{ + for (var i = 0; i < items.length; i++) + { + Random(ellipse, items[i]); + } + + return items; +}; + +module.exports = RandomEllipse; + + +/***/ }), + +/***/ 96000: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Random = __webpack_require__(65822); + +/** + * Takes an array of Game Objects and positions them at random locations on the Line. + * + * If you wish to pass a `Phaser.GameObjects.Line` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.RandomLine + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Line} line - The Line to position the Game Objects randomly on. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RandomLine = function (items, line) +{ + for (var i = 0; i < items.length; i++) + { + Random(line, items[i]); + } + + return items; +}; + +module.exports = RandomLine; + + +/***/ }), + +/***/ 28789: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Random = __webpack_require__(26597); + +/** + * Takes an array of Game Objects and positions them at random locations within the Rectangle. + * + * @function Phaser.Actions.RandomRectangle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to position the Game Objects within. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RandomRectangle = function (items, rect) +{ + for (var i = 0; i < items.length; i++) + { + Random(rect, items[i]); + } + + return items; +}; + +module.exports = RandomRectangle; + + +/***/ }), + +/***/ 97154: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Random = __webpack_require__(90260); + +/** + * Takes an array of Game Objects and positions them at random locations within the Triangle. + * + * If you wish to pass a `Phaser.GameObjects.Triangle` Shape to this function, you should pass its `geom` property. + * + * @function Phaser.Actions.RandomTriangle + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Triangle} triangle - The Triangle to position the Game Objects within. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RandomTriangle = function (items, triangle) +{ + for (var i = 0; i < items.length; i++) + { + Random(triangle, items[i]); + } + + return items; +}; + +module.exports = RandomTriangle; + + +/***/ }), + +/***/ 20510: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `rotation` property, + * and then adds the given value to each of their `rotation` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `Rotate(group.getChildren(), value, step)` + * + * @function Phaser.Actions.Rotate + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `rotation` property (in radians). + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var Rotate = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'rotation', value, step, index, direction); +}; + +module.exports = Rotate; + + +/***/ }), + +/***/ 91051: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateAroundDistance = __webpack_require__(1163); +var DistanceBetween = __webpack_require__(20339); + +/** + * Rotates each item around the given point by the given angle. + * + * @function Phaser.Actions.RotateAround + * @since 3.0.0 + * @see Phaser.Math.RotateAroundDistance + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {object} point - Any object with public `x` and `y` properties. + * @param {number} angle - The angle to rotate by, in radians. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RotateAround = function (items, point, angle) +{ + var x = point.x; + var y = point.y; + + for (var i = 0; i < items.length; i++) + { + var item = items[i]; + + RotateAroundDistance(item, x, y, angle, Math.max(1, DistanceBetween(item.x, item.y, x, y))); + } + + return items; +}; + +module.exports = RotateAround; + + +/***/ }), + +/***/ 76332: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MathRotateAroundDistance = __webpack_require__(1163); + +/** + * Rotates an array of Game Objects around a point by the given angle and distance. + * + * @function Phaser.Actions.RotateAroundDistance + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {object} point - Any object with public `x` and `y` properties. + * @param {number} angle - The angle to rotate by, in radians. + * @param {number} distance - The distance from the point of rotation in pixels. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var RotateAroundDistance = function (items, point, angle, distance) +{ + var x = point.x; + var y = point.y; + + // There's nothing to do + if (distance === 0) + { + return items; + } + + for (var i = 0; i < items.length; i++) + { + MathRotateAroundDistance(items[i], x, y, angle, distance); + } + + return items; +}; + +module.exports = RotateAroundDistance; + + +/***/ }), + +/***/ 61619: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `scaleX` property, + * and then adds the given value to each of their `scaleX` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `ScaleX(group.getChildren(), value, step)` + * + * @function Phaser.Actions.ScaleX + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `scaleX` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var ScaleX = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'scaleX', value, step, index, direction); +}; + +module.exports = ScaleX; + + +/***/ }), + +/***/ 94868: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have public `scaleX` and `scaleY` properties, + * and then adds the given value to each of them. + * + * The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `ScaleXY(group.getChildren(), scaleX, scaleY, stepX, stepY)` + * + * @function Phaser.Actions.ScaleXY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} scaleX - The amount to be added to the `scaleX` property. + * @param {number} [scaleY] - The amount to be added to the `scaleY` property. If `undefined` or `null` it uses the `scaleX` value. + * @param {number} [stepX=0] - This is added to the `scaleX` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `scaleY` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var ScaleXY = function (items, scaleX, scaleY, stepX, stepY, index, direction) +{ + if (scaleY === undefined || scaleY === null) { scaleY = scaleX; } + + PropertyValueInc(items, 'scaleX', scaleX, stepX, index, direction); + + return PropertyValueInc(items, 'scaleY', scaleY, stepY, index, direction); +}; + +module.exports = ScaleXY; + + +/***/ }), + +/***/ 95532: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueInc = __webpack_require__(66979); + +/** + * Takes an array of Game Objects, or any objects that have a public `scaleY` property, + * and then adds the given value to each of their `scaleY` properties. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `ScaleY(group.getChildren(), value, step)` + * + * @function Phaser.Actions.ScaleY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to be added to the `scaleY` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var ScaleY = function (items, value, step, index, direction) +{ + return PropertyValueInc(items, 'scaleY', value, step, index, direction); +}; + +module.exports = ScaleY; + + +/***/ }), + +/***/ 8689: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `alpha` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetAlpha(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetAlpha + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetAlpha = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'alpha', value, step, index, direction); +}; + +module.exports = SetAlpha; + + +/***/ }), + +/***/ 2645: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `blendMode` + * and then sets it to the given value. + * + * To use this with a Group: `SetBlendMode(group.getChildren(), value)` + * + * @function Phaser.Actions.SetBlendMode + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {(Phaser.BlendModes|string|number)} value - The Blend Mode to be set. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetBlendMode = function (items, value, index, direction) +{ + return PropertyValueSet(items, 'blendMode', value, 0, index, direction); +}; + +module.exports = SetBlendMode; + + +/***/ }), + +/***/ 32372: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `depth` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetDepth(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetDepth + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetDepth = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'depth', value, step, index, direction); +}; + +module.exports = SetDepth; + + +/***/ }), + +/***/ 85373: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Passes all provided Game Objects to the Input Manager to enable them for input with identical areas and callbacks. + * + * @see {@link Phaser.GameObjects.GameObject#setInteractive} + * + * @function Phaser.Actions.SetHitArea + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {(Phaser.Types.Input.InputConfiguration|any)} [hitArea] - Either an input configuration object, or a geometric shape that defines the hit area for the Game Object. If not given it will try to create a Rectangle based on the texture frame. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The callback that determines if the pointer is within the Hit Area shape or not. If you provide a shape you must also provide a callback. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var SetHitArea = function (items, hitArea, hitAreaCallback) +{ + for (var i = 0; i < items.length; i++) + { + items[i].setInteractive(hitArea, hitAreaCallback); + } + + return items; +}; + +module.exports = SetHitArea; + + +/***/ }), + +/***/ 81583: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public properties `originX` and `originY` + * and then sets them to the given values. + * + * The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetOrigin(group.getChildren(), originX, originY, stepX, stepY)` + * + * @function Phaser.Actions.SetOrigin + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} originX - The amount to set the `originX` property to. + * @param {number} [originY] - The amount to set the `originY` property to. If `undefined` or `null` it uses the `originX` value. + * @param {number} [stepX=0] - This is added to the `originX` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `originY` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetOrigin = function (items, originX, originY, stepX, stepY, index, direction) +{ + if (originY === undefined || originY === null) { originY = originX; } + + PropertyValueSet(items, 'originX', originX, stepX, index, direction); + PropertyValueSet(items, 'originY', originY, stepY, index, direction); + + items.forEach(function (item) + { + item.updateDisplayOrigin(); + }); + + return items; +}; + +module.exports = SetOrigin; + + +/***/ }), + +/***/ 79939: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `rotation` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetRotation(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetRotation + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetRotation = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'rotation', value, step, index, direction); +}; + +module.exports = SetRotation; + + +/***/ }), + +/***/ 2699: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public properties `scaleX` and `scaleY` + * and then sets them to the given values. + * + * The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetScale(group.getChildren(), scaleX, scaleY, stepX, stepY)` + * + * @function Phaser.Actions.SetScale + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} scaleX - The amount to set the `scaleX` property to. + * @param {number} [scaleY] - The amount to set the `scaleY` property to. If `undefined` or `null` it uses the `scaleX` value. + * @param {number} [stepX=0] - This is added to the `scaleX` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `scaleY` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetScale = function (items, scaleX, scaleY, stepX, stepY, index, direction) +{ + if (scaleY === undefined || scaleY === null) { scaleY = scaleX; } + + PropertyValueSet(items, 'scaleX', scaleX, stepX, index, direction); + + return PropertyValueSet(items, 'scaleY', scaleY, stepY, index, direction); +}; + +module.exports = SetScale; + + +/***/ }), + +/***/ 98739: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `scaleX` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetScaleX(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetScaleX + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetScaleX = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'scaleX', value, step, index, direction); +}; + +module.exports = SetScaleX; + + +/***/ }), + +/***/ 98476: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `scaleY` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetScaleY(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetScaleY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetScaleY = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'scaleY', value, step, index, direction); +}; + +module.exports = SetScaleY; + + +/***/ }), + +/***/ 6207: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public properties `scrollFactorX` and `scrollFactorY` + * and then sets them to the given values. + * + * The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetScrollFactor(group.getChildren(), scrollFactorX, scrollFactorY, stepX, stepY)` + * + * @function Phaser.Actions.SetScrollFactor + * @since 3.21.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} scrollFactorX - The amount to set the `scrollFactorX` property to. + * @param {number} [scrollFactorY] - The amount to set the `scrollFactorY` property to. If `undefined` or `null` it uses the `scrollFactorX` value. + * @param {number} [stepX=0] - This is added to the `scrollFactorX` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `scrollFactorY` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetScrollFactor = function (items, scrollFactorX, scrollFactorY, stepX, stepY, index, direction) +{ + if (scrollFactorY === undefined || scrollFactorY === null) { scrollFactorY = scrollFactorX; } + + PropertyValueSet(items, 'scrollFactorX', scrollFactorX, stepX, index, direction); + + return PropertyValueSet(items, 'scrollFactorY', scrollFactorY, stepY, index, direction); +}; + +module.exports = SetScrollFactor; + + +/***/ }), + +/***/ 6607: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `scrollFactorX` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetScrollFactorX(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetScrollFactorX + * @since 3.21.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetScrollFactorX = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'scrollFactorX', value, step, index, direction); +}; + +module.exports = SetScrollFactorX; + + +/***/ }), + +/***/ 72248: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `scrollFactorY` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetScrollFactorY(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetScrollFactorY + * @since 3.21.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetScrollFactorY = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'scrollFactorY', value, step, index, direction); +}; + +module.exports = SetScrollFactorY; + + +/***/ }), + +/***/ 14036: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects, or any objects that have the public method setTint() and then updates it to the given value(s). You can specify tint color per corner or provide only one color value for `topLeft` parameter, in which case whole item will be tinted with that color. + * + * @function Phaser.Actions.SetTint + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {number} topLeft - The tint being applied to top-left corner of item. If other parameters are given no value, this tint will be applied to whole item. + * @param {number} [topRight] - The tint to be applied to top-right corner of item. + * @param {number} [bottomLeft] - The tint to be applied to the bottom-left corner of item. + * @param {number} [bottomRight] - The tint to be applied to the bottom-right corner of item. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var SetTint = function (items, topLeft, topRight, bottomLeft, bottomRight) +{ + for (var i = 0; i < items.length; i++) + { + items[i].setTint(topLeft, topRight, bottomLeft, bottomRight); + } + + return items; +}; + +module.exports = SetTint; + + +/***/ }), + +/***/ 50159: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `visible` + * and then sets it to the given value. + * + * To use this with a Group: `SetVisible(group.getChildren(), value)` + * + * @function Phaser.Actions.SetVisible + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {boolean} value - The value to set the property to. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetVisible = function (items, value, index, direction) +{ + return PropertyValueSet(items, 'visible', value, 0, index, direction); +}; + +module.exports = SetVisible; + + +/***/ }), + +/***/ 77597: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `x` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetX(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetX + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetX = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'x', value, step, index, direction); +}; + +module.exports = SetX; + + +/***/ }), + +/***/ 83194: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public properties `x` and `y` + * and then sets them to the given values. + * + * The optional `stepX` and `stepY` properties are applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetXY(group.getChildren(), x, y, stepX, stepY)` + * + * @function Phaser.Actions.SetXY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} x - The amount to set the `x` property to. + * @param {number} [y=x] - The amount to set the `y` property to. If `undefined` or `null` it uses the `x` value. + * @param {number} [stepX=0] - This is added to the `x` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `y` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetXY = function (items, x, y, stepX, stepY, index, direction) +{ + if (y === undefined || y === null) { y = x; } + + PropertyValueSet(items, 'x', x, stepX, index, direction); + + return PropertyValueSet(items, 'y', y, stepY, index, direction); +}; + +module.exports = SetXY; + + +/***/ }), + +/***/ 67678: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PropertyValueSet = __webpack_require__(43967); + +/** + * Takes an array of Game Objects, or any objects that have the public property `y` + * and then sets it to the given value. + * + * The optional `step` property is applied incrementally, multiplied by each item in the array. + * + * To use this with a Group: `SetY(group.getChildren(), value, step)` + * + * @function Phaser.Actions.SetY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action. + */ +var SetY = function (items, value, step, index, direction) +{ + return PropertyValueSet(items, 'y', value, step, index, direction); +}; + +module.exports = SetY; + + +/***/ }), + +/***/ 35850: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Takes an array of items, such as Game Objects, or any objects with public `x` and + * `y` properties and then iterates through them. As this function iterates, it moves + * the position of the current element to be that of the previous entry in the array. + * This repeats until all items have been moved. + * + * The direction controls the order of iteration. A value of 0 (the default) assumes + * that the final item in the array is the 'head' item. + * + * A direction value of 1 assumes that the first item in the array is the 'head' item. + * + * The position of the 'head' item is set to the x/y values given to this function. + * Every other item in the array is then updated, in sequence, to be that of the + * previous (or next) entry in the array. + * + * The final x/y coords are returned, or set in the 'output' Vector2. + * + * Think of it as being like the game Snake, where the 'head' is moved and then + * each body piece is moved into the space of the previous piece. + * + * @function Phaser.Actions.ShiftPosition + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items] + * @generic {Phaser.Math.Vector2} O - [output,$return] + * + * @param {(Phaser.Types.Math.Vector2Like[]|Phaser.GameObjects.GameObject[])} items - An array of Game Objects, or objects with public x and y positions. The contents of this array are updated by this Action. + * @param {number} x - The x coordinate to place the head item at. + * @param {number} y - The y coordinate to place the head item at. + * @param {number} [direction=0] - The iteration direction. 0 = first to last and 1 = last to first. + * @param {Phaser.Types.Math.Vector2Like} [output] - An optional Vec2Like object to store the final position in. + * + * @return {Phaser.Types.Math.Vector2Like} The output vector. + */ +var ShiftPosition = function (items, x, y, direction, output) +{ + if (direction === undefined) { direction = 0; } + if (output === undefined) { output = new Vector2(); } + + var px; + var py; + var len = items.length; + + if (len === 1) + { + px = items[0].x; + py = items[0].y; + + items[0].x = x; + items[0].y = y; + } + else + { + var i = 1; + var pos = 0; + + if (direction === 0) + { + pos = len - 1; + i = len - 2; + } + + px = items[pos].x; + py = items[pos].y; + + // Update the head item to the new x/y coordinates + items[pos].x = x; + items[pos].y = y; + + for (var c = 0; c < len; c++) + { + if (i >= len || i === -1) + { + continue; + } + + // Current item + var cur = items[i]; + + // Get current item x/y, to be passed to the next item in the list + var cx = cur.x; + var cy = cur.y; + + // Set current item to the previous items x/y + cur.x = px; + cur.y = py; + + // Set current as previous + px = cx; + py = cy; + + if (direction === 0) + { + i--; + } + else + { + i++; + } + } + } + + // Return the final set of coordinates as they're effectively lost from the shift and may be needed + + output.x = px; + output.y = py; + + return output; +}; + +module.exports = ShiftPosition; + + +/***/ }), + +/***/ 8628: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayShuffle = __webpack_require__(33680); + +/** + * Shuffles the array in place. The shuffled array is both modified and returned. + * + * @function Phaser.Actions.Shuffle + * @since 3.0.0 + * @see Phaser.Utils.Array.Shuffle + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var Shuffle = function (items) +{ + return ArrayShuffle(items); +}; + +module.exports = Shuffle; + + +/***/ }), + +/***/ 21837: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MathSmoothStep = __webpack_require__(7602); + +/** + * Smoothstep is a sigmoid-like interpolation and clamping function. + * + * The function depends on three parameters, the input x, the "left edge" + * and the "right edge", with the left edge being assumed smaller than the right edge. + * + * The function receives a real number x as an argument and returns 0 if x is less than + * or equal to the left edge, 1 if x is greater than or equal to the right edge, and smoothly + * interpolates, using a Hermite polynomial, between 0 and 1 otherwise. The slope of the + * smoothstep function is zero at both edges. + * + * This is convenient for creating a sequence of transitions using smoothstep to interpolate + * each segment as an alternative to using more sophisticated or expensive interpolation techniques. + * + * @function Phaser.Actions.SmoothStep + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {string} property - The property of the Game Object to interpolate. + * @param {number} min - The minimum interpolation value. + * @param {number} max - The maximum interpolation value. + * @param {boolean} [inc=false] - Should the property value be incremented (`true`) or set (`false`)? + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var SmoothStep = function (items, property, min, max, inc) +{ + if (inc === undefined) { inc = false; } + + var step = Math.abs(max - min) / items.length; + var i; + + if (inc) + { + for (i = 0; i < items.length; i++) + { + items[i][property] += MathSmoothStep(i * step, min, max); + } + } + else + { + for (i = 0; i < items.length; i++) + { + items[i][property] = MathSmoothStep(i * step, min, max); + } + } + + return items; +}; + +module.exports = SmoothStep; + + +/***/ }), + +/***/ 21910: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MathSmootherStep = __webpack_require__(54261); + +/** + * Smootherstep is a sigmoid-like interpolation and clamping function. + * + * The function depends on three parameters, the input x, the "left edge" and the "right edge", with the left edge being assumed smaller than the right edge. The function receives a real number x as an argument and returns 0 if x is less than or equal to the left edge, 1 if x is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial, between 0 and 1 otherwise. The slope of the smoothstep function is zero at both edges. This is convenient for creating a sequence of transitions using smoothstep to interpolate each segment as an alternative to using more sophisticated or expensive interpolation techniques. + * + * @function Phaser.Actions.SmootherStep + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {string} property - The property of the Game Object to interpolate. + * @param {number} min - The minimum interpolation value. + * @param {number} max - The maximum interpolation value. + * @param {boolean} [inc=false] - Should the values be incremented? `true` or set (`false`) + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var SmootherStep = function (items, property, min, max, inc) +{ + if (inc === undefined) { inc = false; } + + var step = Math.abs(max - min) / items.length; + var i; + + if (inc) + { + for (i = 0; i < items.length; i++) + { + items[i][property] += MathSmootherStep(i * step, min, max); + } + } + else + { + for (i = 0; i < items.length; i++) + { + items[i][property] = MathSmootherStep(i * step, min, max); + } + } + + return items; +}; + +module.exports = SmootherStep; + + +/***/ }), + +/***/ 62054: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects and then modifies their `property` so the value equals, or is incremented, by the + * calculated spread value. + * + * The spread value is derived from the given `min` and `max` values and the total number of items in the array. + * + * For example, to cause an array of Sprites to change in alpha from 0 to 1 you could call: + * + * ```javascript + * Phaser.Actions.Spread(itemsArray, 'alpha', 0, 1); + * ``` + * + * @function Phaser.Actions.Spread + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {string} property - The property of the Game Object to spread. + * @param {number} min - The minimum value. + * @param {number} max - The maximum value. + * @param {boolean} [inc=false] - Should the values be incremented? `true` or set (`false`) + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that were passed to this Action. + */ +var Spread = function (items, property, min, max, inc) +{ + if (inc === undefined) { inc = false; } + if (items.length === 0) { return items; } + if (items.length === 1) // if only one item put it at the center + { + if (inc) + { + items[0][property] += (max + min) / 2; + } + else + { + items[0][property] = (max + min) / 2; + } + + return items; + } + + var step = Math.abs(max - min) / (items.length - 1); + var i; + + if (inc) + { + for (i = 0; i < items.length; i++) + { + items[i][property] += i * step + min; + } + } + else + { + for (i = 0; i < items.length; i++) + { + items[i][property] = i * step + min; + } + } + + return items; +}; + +module.exports = Spread; + + +/***/ }), + +/***/ 79815: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array of Game Objects and toggles the visibility of each one. + * Those previously `visible = false` will become `visible = true`, and vice versa. + * + * @function Phaser.Actions.ToggleVisible + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var ToggleVisible = function (items) +{ + for (var i = 0; i < items.length; i++) + { + items[i].visible = !items[i].visible; + } + + return items; +}; + +module.exports = ToggleVisible; + + +/***/ }), + +/***/ 39665: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Wrap = __webpack_require__(15994); + +/** + * Iterates through the given array and makes sure that each objects x and y + * properties are wrapped to keep them contained within the given Rectangles + * area. + * + * @function Phaser.Actions.WrapInRectangle + * @since 3.0.0 + * @see Phaser.Math.Wrap + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(array|Phaser.GameObjects.GameObject[])} items - An array of Game Objects. The contents of this array are updated by this Action. + * @param {Phaser.Geom.Rectangle} rect - The rectangle which the objects will be wrapped to remain within. + * @param {number} [padding=0] - An amount added to each side of the rectangle during the operation. + * + * @return {(array|Phaser.GameObjects.GameObject[])} The array of Game Objects that was passed to this Action. + */ +var WrapInRectangle = function (items, rect, padding) +{ + if (padding === undefined) + { + padding = 0; + } + + for (var i = 0; i < items.length; i++) + { + var item = items[i]; + + item.x = Wrap(item.x, rect.left - padding, rect.right + padding); + item.y = Wrap(item.y, rect.top - padding, rect.bottom + padding); + } + + return items; +}; + +module.exports = WrapInRectangle; + + +/***/ }), + +/***/ 61061: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Actions + */ + +module.exports = { + + AlignTo: __webpack_require__(11517), + Angle: __webpack_require__(80318), + Call: __webpack_require__(60757), + GetFirst: __webpack_require__(69927), + GetLast: __webpack_require__(32265), + GridAlign: __webpack_require__(94420), + IncAlpha: __webpack_require__(41721), + IncX: __webpack_require__(67285), + IncXY: __webpack_require__(9074), + IncY: __webpack_require__(75222), + PlaceOnCircle: __webpack_require__(22983), + PlaceOnEllipse: __webpack_require__(95253), + PlaceOnLine: __webpack_require__(88505), + PlaceOnRectangle: __webpack_require__(41346), + PlaceOnTriangle: __webpack_require__(11575), + PlayAnimation: __webpack_require__(29953), + PropertyValueInc: __webpack_require__(66979), + PropertyValueSet: __webpack_require__(43967), + RandomCircle: __webpack_require__(88926), + RandomEllipse: __webpack_require__(33286), + RandomLine: __webpack_require__(96000), + RandomRectangle: __webpack_require__(28789), + RandomTriangle: __webpack_require__(97154), + Rotate: __webpack_require__(20510), + RotateAround: __webpack_require__(91051), + RotateAroundDistance: __webpack_require__(76332), + ScaleX: __webpack_require__(61619), + ScaleXY: __webpack_require__(94868), + ScaleY: __webpack_require__(95532), + SetAlpha: __webpack_require__(8689), + SetBlendMode: __webpack_require__(2645), + SetDepth: __webpack_require__(32372), + SetHitArea: __webpack_require__(85373), + SetOrigin: __webpack_require__(81583), + SetRotation: __webpack_require__(79939), + SetScale: __webpack_require__(2699), + SetScaleX: __webpack_require__(98739), + SetScaleY: __webpack_require__(98476), + SetScrollFactor: __webpack_require__(6207), + SetScrollFactorX: __webpack_require__(6607), + SetScrollFactorY: __webpack_require__(72248), + SetTint: __webpack_require__(14036), + SetVisible: __webpack_require__(50159), + SetX: __webpack_require__(77597), + SetXY: __webpack_require__(83194), + SetY: __webpack_require__(67678), + ShiftPosition: __webpack_require__(35850), + Shuffle: __webpack_require__(8628), + SmootherStep: __webpack_require__(21910), + SmoothStep: __webpack_require__(21837), + Spread: __webpack_require__(62054), + ToggleVisible: __webpack_require__(79815), + WrapInRectangle: __webpack_require__(39665) + +}; + + +/***/ }), + +/***/ 42099: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(74943); +var FindClosestInSorted = __webpack_require__(81957); +var Frame = __webpack_require__(41138); +var GetValue = __webpack_require__(35154); +var SortByDigits = __webpack_require__(90126); + +/** + * @classdesc + * A Frame based Animation. + * + * Animations in Phaser consist of a sequence of `AnimationFrame` objects, which are managed by + * this class, along with properties that impact playback, such as the animations frame rate + * or delay. + * + * This class contains all of the properties and methods needed to handle playback of the animation + * directly to an `AnimationState` instance, which is owned by a Sprite, or similar Game Object. + * + * You don't typically create an instance of this class directly, but instead go via + * either the `AnimationManager` or the `AnimationState` and use their `create` methods, + * depending on if you need a global animation, or local to a specific Sprite. + * + * @class Animation + * @memberof Phaser.Animations + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationManager} manager - A reference to the global Animation Manager + * @param {string} key - The unique identifying string for this animation. + * @param {Phaser.Types.Animations.Animation} config - The Animation configuration. + */ +var Animation = new Class({ + + initialize: + + function Animation (manager, key, config) + { + /** + * A reference to the global Animation Manager. + * + * @name Phaser.Animations.Animation#manager + * @type {Phaser.Animations.AnimationManager} + * @since 3.0.0 + */ + this.manager = manager; + + /** + * The unique identifying string for this animation. + * + * @name Phaser.Animations.Animation#key + * @type {string} + * @since 3.0.0 + */ + this.key = key; + + /** + * A frame based animation (as opposed to a bone based animation) + * + * @name Phaser.Animations.Animation#type + * @type {string} + * @default frame + * @since 3.0.0 + */ + this.type = 'frame'; + + /** + * Extract all the frame data into the frames array. + * + * @name Phaser.Animations.Animation#frames + * @type {Phaser.Animations.AnimationFrame[]} + * @since 3.0.0 + */ + this.frames = this.getFrames( + manager.textureManager, + GetValue(config, 'frames', []), + GetValue(config, 'defaultTextureKey', null), + GetValue(config, 'sortFrames', true) + ); + + /** + * The frame rate of playback in frames per second (default 24 if duration is null) + * + * @name Phaser.Animations.Animation#frameRate + * @type {number} + * @default 24 + * @since 3.0.0 + */ + this.frameRate = GetValue(config, 'frameRate', null); + + /** + * How long the animation should play for, in milliseconds. + * If the `frameRate` property has been set then it overrides this value, + * otherwise the `frameRate` is derived from `duration`. + * + * @name Phaser.Animations.Animation#duration + * @type {number} + * @since 3.0.0 + */ + this.duration = GetValue(config, 'duration', null); + + /** + * How many ms per frame, not including frame specific modifiers. + * + * @name Phaser.Animations.Animation#msPerFrame + * @type {number} + * @since 3.0.0 + */ + this.msPerFrame; + + /** + * Skip frames if the time lags, or always advanced anyway? + * + * @name Phaser.Animations.Animation#skipMissedFrames + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.skipMissedFrames = GetValue(config, 'skipMissedFrames', true); + + /** + * The delay in ms before the playback will begin. + * + * @name Phaser.Animations.Animation#delay + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.delay = GetValue(config, 'delay', 0); + + /** + * Number of times to repeat the animation. Set to -1 to repeat forever. + * + * @name Phaser.Animations.Animation#repeat + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.repeat = GetValue(config, 'repeat', 0); + + /** + * The delay in ms before the a repeat play starts. + * + * @name Phaser.Animations.Animation#repeatDelay + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.repeatDelay = GetValue(config, 'repeatDelay', 0); + + /** + * Should the animation yoyo (reverse back down to the start) before repeating? + * + * @name Phaser.Animations.Animation#yoyo + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.yoyo = GetValue(config, 'yoyo', false); + + /** + * If the animation has a delay set, before playback will begin, this + * controls when the first frame is set on the Sprite. If this property + * is 'false' then the frame is set only after the delay has expired. + * This is the default behavior. + * + * @name Phaser.Animations.Animation#showBeforeDelay + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.showBeforeDelay = GetValue(config, 'showBeforeDelay', false); + + /** + * Should the GameObject's `visible` property be set to `true` when the animation starts to play? + * + * @name Phaser.Animations.Animation#showOnStart + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.showOnStart = GetValue(config, 'showOnStart', false); + + /** + * Should the GameObject's `visible` property be set to `false` when the animation finishes? + * + * @name Phaser.Animations.Animation#hideOnComplete + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.hideOnComplete = GetValue(config, 'hideOnComplete', false); + + /** + * Start playback of this animation from a random frame? + * + * @name Phaser.Animations.Animation#randomFrame + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.randomFrame = GetValue(config, 'randomFrame', false); + + /** + * Global pause. All Game Objects using this Animation instance are impacted by this property. + * + * @name Phaser.Animations.Animation#paused + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.paused = false; + + this.calculateDuration(this, this.getTotalFrames(), this.duration, this.frameRate); + + if (this.manager.on) + { + this.manager.on(Events.PAUSE_ALL, this.pause, this); + this.manager.on(Events.RESUME_ALL, this.resume, this); + } + }, + + /** + * Gets the total number of frames in this animation. + * + * @method Phaser.Animations.Animation#getTotalFrames + * @since 3.50.0 + * + * @return {number} The total number of frames in this animation. + */ + getTotalFrames: function () + { + return this.frames.length; + }, + + /** + * Calculates the duration, frame rate and msPerFrame values. + * + * @method Phaser.Animations.Animation#calculateDuration + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} target - The target to set the values on. + * @param {number} totalFrames - The total number of frames in the animation. + * @param {?number} [duration] - The duration to calculate the frame rate from. Pass `null` if you wish to set the `frameRate` instead. + * @param {?number} [frameRate] - The frame rate to calculate the duration from. + */ + calculateDuration: function (target, totalFrames, duration, frameRate) + { + if (duration === null && frameRate === null) + { + // No duration or frameRate given, use default frameRate of 24fps + target.frameRate = 24; + target.duration = (24 / totalFrames) * 1000; + } + else if (duration && frameRate === null) + { + // Duration given but no frameRate, so set the frameRate based on duration + // I.e. 12 frames in the animation, duration = 4000 ms + // So frameRate is 12 / (4000 / 1000) = 3 fps + target.duration = duration; + target.frameRate = totalFrames / (duration / 1000); + } + else + { + // frameRate given, derive duration from it (even if duration also specified) + // I.e. 15 frames in the animation, frameRate = 30 fps + // So duration is 15 / 30 = 0.5 * 1000 (half a second, or 500ms) + target.frameRate = frameRate; + target.duration = (totalFrames / frameRate) * 1000; + } + + target.msPerFrame = 1000 / target.frameRate; + }, + + /** + * Add frames to the end of the animation. + * + * @method Phaser.Animations.Animation#addFrame + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Animations.AnimationFrame[])} config - Either a string, in which case it will use all frames from a texture with the matching key, or an array of Animation Frame configuration objects. + * + * @return {this} This Animation object. + */ + addFrame: function (config) + { + return this.addFrameAt(this.frames.length, config); + }, + + /** + * Add frame/s into the animation. + * + * @method Phaser.Animations.Animation#addFrameAt + * @since 3.0.0 + * + * @param {number} index - The index to insert the frame at within the animation. + * @param {(string|Phaser.Types.Animations.AnimationFrame[])} config - Either a string, in which case it will use all frames from a texture with the matching key, or an array of Animation Frame configuration objects. + * + * @return {this} This Animation object. + */ + addFrameAt: function (index, config) + { + var newFrames = this.getFrames(this.manager.textureManager, config); + + if (newFrames.length > 0) + { + if (index === 0) + { + this.frames = newFrames.concat(this.frames); + } + else if (index === this.frames.length) + { + this.frames = this.frames.concat(newFrames); + } + else + { + var pre = this.frames.slice(0, index); + var post = this.frames.slice(index); + + this.frames = pre.concat(newFrames, post); + } + + this.updateFrameSequence(); + } + + return this; + }, + + /** + * Check if the given frame index is valid. + * + * @method Phaser.Animations.Animation#checkFrame + * @since 3.0.0 + * + * @param {number} index - The index to be checked. + * + * @return {boolean} `true` if the index is valid, otherwise `false`. + */ + checkFrame: function (index) + { + return (index >= 0 && index < this.frames.length); + }, + + /** + * Called internally when this Animation first starts to play. + * Sets the accumulator and nextTick properties. + * + * @method Phaser.Animations.Animation#getFirstTick + * @protected + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State belonging to the Game Object invoking this call. + */ + getFirstTick: function (state) + { + // When is the first update due? + state.accumulator = 0; + + state.nextTick = state.frameRate === state.currentAnim.frameRate ? state.currentFrame.duration || state.msPerFrame : state.msPerFrame; + }, + + /** + * Returns the AnimationFrame at the provided index + * + * @method Phaser.Animations.Animation#getFrameAt + * @since 3.0.0 + * + * @param {number} index - The index in the AnimationFrame array + * + * @return {Phaser.Animations.AnimationFrame} The frame at the index provided from the animation sequence + */ + getFrameAt: function (index) + { + return this.frames[index]; + }, + + /** + * Creates AnimationFrame instances based on the given frame data. + * + * @method Phaser.Animations.Animation#getFrames + * @since 3.0.0 + * + * @param {Phaser.Textures.TextureManager} textureManager - A reference to the global Texture Manager. + * @param {(string|Phaser.Types.Animations.AnimationFrame[])} frames - Either a string, in which case it will use all frames from a texture with the matching key, or an array of Animation Frame configuration objects. + * @param {string} [defaultTextureKey] - The key to use if no key is set in the frame configuration object. + * + * @return {Phaser.Animations.AnimationFrame[]} An array of newly created AnimationFrame instances. + */ + getFrames: function (textureManager, frames, defaultTextureKey, sortFrames) + { + if (sortFrames === undefined) { sortFrames = true; } + + var out = []; + var prev; + var animationFrame; + var index = 1; + var i; + var textureKey; + + // if frames is a string, we'll get all the frames from the texture manager as if it's a sprite sheet + if (typeof frames === 'string') + { + textureKey = frames; + + if (!textureManager.exists(textureKey)) + { + console.warn('Texture "%s" not found', textureKey); + + return out; + } + + var texture = textureManager.get(textureKey); + var frameKeys = texture.getFrameNames(); + + if (sortFrames) + { + SortByDigits(frameKeys); + } + + frames = []; + + frameKeys.forEach(function (value) + { + frames.push({ key: textureKey, frame: value }); + }); + } + + if (!Array.isArray(frames) || frames.length === 0) + { + return out; + } + + for (i = 0; i < frames.length; i++) + { + var item = frames[i]; + + var key = GetValue(item, 'key', defaultTextureKey); + + if (!key) + { + continue; + } + + // Could be an integer or a string + var frame = GetValue(item, 'frame', 0); + + // The actual texture frame + var textureFrame = textureManager.getFrame(key, frame); + + if (!textureFrame) + { + console.warn('Texture "%s" not found', key); + + continue; + } + + animationFrame = new Frame(key, frame, index, textureFrame); + + animationFrame.duration = GetValue(item, 'duration', 0); + + animationFrame.isFirst = (!prev); + + // The previously created animationFrame + if (prev) + { + prev.nextFrame = animationFrame; + + animationFrame.prevFrame = prev; + } + + out.push(animationFrame); + + prev = animationFrame; + + index++; + } + + if (out.length > 0) + { + animationFrame.isLast = true; + + // Link them end-to-end, so they loop + animationFrame.nextFrame = out[0]; + + out[0].prevFrame = animationFrame; + + // Generate the progress data + + var slice = 1 / (out.length - 1); + + for (i = 0; i < out.length; i++) + { + out[i].progress = i * slice; + } + } + + return out; + }, + + /** + * Called internally. Sets the accumulator and nextTick values of the current Animation. + * + * @method Phaser.Animations.Animation#getNextTick + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State belonging to the Game Object invoking this call. + */ + getNextTick: function (state) + { + state.accumulator -= state.nextTick; + + state.nextTick = state.frameRate === state.currentAnim.frameRate ? state.currentFrame.duration || state.msPerFrame : state.msPerFrame; + }, + + /** + * Returns the frame closest to the given progress value between 0 and 1. + * + * @method Phaser.Animations.Animation#getFrameByProgress + * @since 3.4.0 + * + * @param {number} value - A value between 0 and 1. + * + * @return {Phaser.Animations.AnimationFrame} The frame closest to the given progress value. + */ + getFrameByProgress: function (value) + { + value = Clamp(value, 0, 1); + + return FindClosestInSorted(value, this.frames, 'progress'); + }, + + /** + * Advance the animation frame. + * + * @method Phaser.Animations.Animation#nextFrame + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State to advance. + */ + nextFrame: function (state) + { + var frame = state.currentFrame; + + if (frame.isLast) + { + // We're at the end of the animation + + // Yoyo? (happens before repeat) + if (state.yoyo) + { + this.handleYoyoFrame(state, false); + } + else if (state.repeatCounter > 0) + { + // Repeat (happens before complete) + + if (state.inReverse && state.forward) + { + state.forward = false; + } + else + { + this.repeatAnimation(state); + } + } + else + { + state.complete(); + } + } + else + { + this.updateAndGetNextTick(state, frame.nextFrame); + } + }, + + /** + * Handle the yoyo functionality in nextFrame and previousFrame methods. + * + * @method Phaser.Animations.Animation#handleYoyoFrame + * @private + * @since 3.12.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State to advance. + * @param {boolean} isReverse - Is animation in reverse mode? (Default: false) + */ + handleYoyoFrame: function (state, isReverse) + { + if (!isReverse) { isReverse = false; } + + if (state.inReverse === !isReverse && state.repeatCounter > 0) + { + if (state.repeatDelay === 0 || state.pendingRepeat) + { + state.forward = isReverse; + } + + this.repeatAnimation(state); + + return; + } + + if (state.inReverse !== isReverse && state.repeatCounter === 0) + { + state.complete(); + + return; + } + + state.forward = isReverse; + + var frame = (isReverse) ? state.currentFrame.nextFrame : state.currentFrame.prevFrame; + + this.updateAndGetNextTick(state, frame); + }, + + /** + * Returns the animation last frame. + * + * @method Phaser.Animations.Animation#getLastFrame + * @since 3.12.0 + * + * @return {Phaser.Animations.AnimationFrame} The last Animation Frame. + */ + getLastFrame: function () + { + return this.frames[this.frames.length - 1]; + }, + + /** + * Called internally when the Animation is playing backwards. + * Sets the previous frame, causing a yoyo, repeat, complete or update, accordingly. + * + * @method Phaser.Animations.Animation#previousFrame + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State belonging to the Game Object invoking this call. + */ + previousFrame: function (state) + { + var frame = state.currentFrame; + + if (frame.isFirst) + { + // We're at the start of the animation + if (state.yoyo) + { + this.handleYoyoFrame(state, true); + } + else if (state.repeatCounter > 0) + { + if (state.inReverse && !state.forward) + { + this.repeatAnimation(state); + } + else + { + // Repeat (happens before complete) + state.forward = true; + + this.repeatAnimation(state); + } + } + else + { + state.complete(); + } + } + else + { + this.updateAndGetNextTick(state, frame.prevFrame); + } + }, + + /** + * Update Frame and Wait next tick. + * + * @method Phaser.Animations.Animation#updateAndGetNextTick + * @private + * @since 3.12.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State. + * @param {Phaser.Animations.AnimationFrame} frame - An Animation frame. + */ + updateAndGetNextTick: function (state, frame) + { + state.setCurrentFrame(frame); + + this.getNextTick(state); + }, + + /** + * Removes the given AnimationFrame from this Animation instance. + * This is a global action. Any Game Object using this Animation will be impacted by this change. + * + * @method Phaser.Animations.Animation#removeFrame + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationFrame} frame - The AnimationFrame to be removed. + * + * @return {this} This Animation object. + */ + removeFrame: function (frame) + { + var index = this.frames.indexOf(frame); + + if (index !== -1) + { + this.removeFrameAt(index); + } + + return this; + }, + + /** + * Removes a frame from the AnimationFrame array at the provided index + * and updates the animation accordingly. + * + * @method Phaser.Animations.Animation#removeFrameAt + * @since 3.0.0 + * + * @param {number} index - The index in the AnimationFrame array + * + * @return {this} This Animation object. + */ + removeFrameAt: function (index) + { + this.frames.splice(index, 1); + + this.updateFrameSequence(); + + return this; + }, + + /** + * Called internally during playback. Forces the animation to repeat, providing there are enough counts left + * in the repeat counter. + * + * @method Phaser.Animations.Animation#repeatAnimation + * @fires Phaser.Animations.Events#ANIMATION_REPEAT + * @fires Phaser.Animations.Events#SPRITE_ANIMATION_REPEAT + * @fires Phaser.Animations.Events#SPRITE_ANIMATION_KEY_REPEAT + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationState} state - The Animation State belonging to the Game Object invoking this call. + */ + repeatAnimation: function (state) + { + if (state._pendingStop === 2) + { + if (state._pendingStopValue === 0) + { + return state.stop(); + } + else + { + state._pendingStopValue--; + } + } + + if (state.repeatDelay > 0 && !state.pendingRepeat) + { + state.pendingRepeat = true; + state.accumulator -= state.nextTick; + state.nextTick += state.repeatDelay; + } + else + { + state.repeatCounter--; + + if (state.forward) + { + state.setCurrentFrame(state.currentFrame.nextFrame); + } + else + { + state.setCurrentFrame(state.currentFrame.prevFrame); + } + + if (state.isPlaying) + { + this.getNextTick(state); + + state.handleRepeat(); + } + } + }, + + /** + * Converts the animation data to JSON. + * + * @method Phaser.Animations.Animation#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Animations.JSONAnimation} The resulting JSONAnimation formatted object. + */ + toJSON: function () + { + var output = { + key: this.key, + type: this.type, + frames: [], + frameRate: this.frameRate, + duration: this.duration, + skipMissedFrames: this.skipMissedFrames, + delay: this.delay, + repeat: this.repeat, + repeatDelay: this.repeatDelay, + yoyo: this.yoyo, + showBeforeDelay: this.showBeforeDelay, + showOnStart: this.showOnStart, + randomFrame: this.randomFrame, + hideOnComplete: this.hideOnComplete + }; + + this.frames.forEach(function (frame) + { + output.frames.push(frame.toJSON()); + }); + + return output; + }, + + /** + * Called internally whenever frames are added to, or removed from, this Animation. + * + * @method Phaser.Animations.Animation#updateFrameSequence + * @since 3.0.0 + * + * @return {this} This Animation object. + */ + updateFrameSequence: function () + { + var len = this.frames.length; + var slice = 1 / (len - 1); + + var frame; + + for (var i = 0; i < len; i++) + { + frame = this.frames[i]; + + frame.index = i + 1; + frame.isFirst = false; + frame.isLast = false; + frame.progress = i * slice; + + if (i === 0) + { + frame.isFirst = true; + + if (len === 1) + { + frame.isLast = true; + frame.nextFrame = frame; + frame.prevFrame = frame; + } + else + { + frame.isLast = false; + frame.prevFrame = this.frames[len - 1]; + frame.nextFrame = this.frames[i + 1]; + } + } + else if (i === len - 1 && len > 1) + { + frame.isLast = true; + frame.prevFrame = this.frames[len - 2]; + frame.nextFrame = this.frames[0]; + } + else if (len > 1) + { + frame.prevFrame = this.frames[i - 1]; + frame.nextFrame = this.frames[i + 1]; + } + } + + return this; + }, + + /** + * Pauses playback of this Animation. The paused state is set immediately. + * + * @method Phaser.Animations.Animation#pause + * @since 3.0.0 + * + * @return {this} This Animation object. + */ + pause: function () + { + this.paused = true; + + return this; + }, + + /** + * Resumes playback of this Animation. The paused state is reset immediately. + * + * @method Phaser.Animations.Animation#resume + * @since 3.0.0 + * + * @return {this} This Animation object. + */ + resume: function () + { + this.paused = false; + + return this; + }, + + /** + * Destroys this Animation instance. It will remove all event listeners, + * remove this animation and its key from the global Animation Manager, + * and then destroy all Animation Frames in turn. + * + * @method Phaser.Animations.Animation#destroy + * @since 3.0.0 + */ + destroy: function () + { + if (this.manager.off) + { + this.manager.off(Events.PAUSE_ALL, this.pause, this); + this.manager.off(Events.RESUME_ALL, this.resume, this); + } + + this.manager.remove(this.key); + + for (var i = 0; i < this.frames.length; i++) + { + this.frames[i].destroy(); + } + + this.frames = []; + + this.manager = null; + } + +}); + +module.exports = Animation; + + +/***/ }), + +/***/ 41138: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A single frame in an Animation sequence. + * + * An AnimationFrame consists of a reference to the Texture it uses for rendering, references to other + * frames in the animation, and index data. It also has the ability to modify the animation timing. + * + * AnimationFrames are generated automatically by the Animation class. + * + * @class AnimationFrame + * @memberof Phaser.Animations + * @constructor + * @since 3.0.0 + * + * @param {string} textureKey - The key of the Texture this AnimationFrame uses. + * @param {(string|number)} textureFrame - The key of the Frame within the Texture that this AnimationFrame uses. + * @param {number} index - The index of this AnimationFrame within the Animation sequence. + * @param {Phaser.Textures.Frame} frame - A reference to the Texture Frame this AnimationFrame uses for rendering. + * @param {boolean} [isKeyFrame=false] - Is this Frame a Keyframe within the Animation? + */ +var AnimationFrame = new Class({ + + initialize: + + function AnimationFrame (textureKey, textureFrame, index, frame, isKeyFrame) + { + if (isKeyFrame === undefined) { isKeyFrame = false; } + + /** + * The key of the Texture this AnimationFrame uses. + * + * @name Phaser.Animations.AnimationFrame#textureKey + * @type {string} + * @since 3.0.0 + */ + this.textureKey = textureKey; + + /** + * The key of the Frame within the Texture that this AnimationFrame uses. + * + * @name Phaser.Animations.AnimationFrame#textureFrame + * @type {(string|number)} + * @since 3.0.0 + */ + this.textureFrame = textureFrame; + + /** + * The index of this AnimationFrame within the Animation sequence. + * + * @name Phaser.Animations.AnimationFrame#index + * @type {number} + * @since 3.0.0 + */ + this.index = index; + + /** + * A reference to the Texture Frame this AnimationFrame uses for rendering. + * + * @name Phaser.Animations.AnimationFrame#frame + * @type {Phaser.Textures.Frame} + * @since 3.0.0 + */ + this.frame = frame; + + /** + * Is this the first frame in an animation sequence? + * + * @name Phaser.Animations.AnimationFrame#isFirst + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isFirst = false; + + /** + * Is this the last frame in an animation sequence? + * + * @name Phaser.Animations.AnimationFrame#isLast + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isLast = false; + + /** + * A reference to the AnimationFrame that comes before this one in the animation, if any. + * + * @name Phaser.Animations.AnimationFrame#prevFrame + * @type {?Phaser.Animations.AnimationFrame} + * @default null + * @readonly + * @since 3.0.0 + */ + this.prevFrame = null; + + /** + * A reference to the AnimationFrame that comes after this one in the animation, if any. + * + * @name Phaser.Animations.AnimationFrame#nextFrame + * @type {?Phaser.Animations.AnimationFrame} + * @default null + * @readonly + * @since 3.0.0 + */ + this.nextFrame = null; + + /** + * The duration, in ms, of this frame of the animation. + * + * @name Phaser.Animations.AnimationFrame#duration + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.duration = 0; + + /** + * What % through the animation does this frame come? + * This value is generated when the animation is created and cached here. + * + * @name Phaser.Animations.AnimationFrame#progress + * @type {number} + * @default 0 + * @readonly + * @since 3.0.0 + */ + this.progress = 0; + + /** + * Is this Frame a KeyFrame within the Animation? + * + * @name Phaser.Animations.AnimationFrame#isKeyFrame + * @type {boolean} + * @since 3.50.0 + */ + this.isKeyFrame = isKeyFrame; + }, + + /** + * Generates a JavaScript object suitable for converting to JSON. + * + * @method Phaser.Animations.AnimationFrame#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Animations.JSONAnimationFrame} The AnimationFrame data. + */ + toJSON: function () + { + return { + key: this.textureKey, + frame: this.textureFrame, + duration: this.duration, + keyframe: this.isKeyFrame + }; + }, + + /** + * Destroys this object by removing references to external resources and callbacks. + * + * @method Phaser.Animations.AnimationFrame#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.frame = undefined; + } + +}); + +module.exports = AnimationFrame; + + +/***/ }), + +/***/ 60848: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Animation = __webpack_require__(42099); +var Class = __webpack_require__(83419); +var CustomMap = __webpack_require__(90330); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(74943); +var GameEvents = __webpack_require__(8443); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var MATH_CONST = __webpack_require__(36383); +var NumberArray = __webpack_require__(20283); +var Pad = __webpack_require__(41836); + +/** + * @classdesc + * The Animation Manager. + * + * Animations are managed by the global Animation Manager. This is a singleton class that is + * responsible for creating and delivering animations and their corresponding data to all Game Objects. + * Unlike plugins it is owned by the Game instance, not the Scene. + * + * Sprites and other Game Objects get the data they need from the AnimationManager. + * + * @class AnimationManager + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Animations + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - A reference to the Phaser.Game instance. + */ +var AnimationManager = new Class({ + + Extends: EventEmitter, + + initialize: + + function AnimationManager (game) + { + EventEmitter.call(this); + + /** + * A reference to the Phaser.Game instance. + * + * @name Phaser.Animations.AnimationManager#game + * @type {Phaser.Game} + * @protected + * @since 3.0.0 + */ + this.game = game; + + /** + * A reference to the Texture Manager. + * + * @name Phaser.Animations.AnimationManager#textureManager + * @type {Phaser.Textures.TextureManager} + * @protected + * @since 3.0.0 + */ + this.textureManager = null; + + /** + * The global time scale of the Animation Manager. + * + * This scales the time delta between two frames, thus influencing the speed of time for the Animation Manager. + * + * @name Phaser.Animations.AnimationManager#globalTimeScale + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.globalTimeScale = 1; + + /** + * The Animations registered in the Animation Manager. + * + * This map should be modified with the {@link #add} and {@link #create} methods of the Animation Manager. + * + * @name Phaser.Animations.AnimationManager#anims + * @type {Phaser.Structs.Map.} + * @protected + * @since 3.0.0 + */ + this.anims = new CustomMap(); + + /** + * A list of animation mix times. + * + * See the {@link #setMix} method for more details. + * + * @name Phaser.Animations.AnimationManager#mixes + * @type {Phaser.Structs.Map.} + * @since 3.50.0 + */ + this.mixes = new CustomMap(); + + /** + * Whether the Animation Manager is paused along with all of its Animations. + * + * @name Phaser.Animations.AnimationManager#paused + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.paused = false; + + /** + * The name of this Animation Manager. + * + * @name Phaser.Animations.AnimationManager#name + * @type {string} + * @since 3.0.0 + */ + this.name = 'AnimationManager'; + + game.events.once(GameEvents.BOOT, this.boot, this); + }, + + /** + * Registers event listeners after the Game boots. + * + * @method Phaser.Animations.AnimationManager#boot + * @listens Phaser.Core.Events#DESTROY + * @since 3.0.0 + */ + boot: function () + { + this.textureManager = this.game.textures; + + this.game.events.once(GameEvents.DESTROY, this.destroy, this); + }, + + /** + * Adds a mix between two animations. + * + * Mixing allows you to specify a unique delay between a pairing of animations. + * + * When playing Animation A on a Game Object, if you then play Animation B, and a + * mix exists, it will wait for the specified delay to be over before playing Animation B. + * + * This allows you to customise smoothing between different types of animation, such + * as blending between an idle and a walk state, or a running and a firing state. + * + * Note that mixing is only applied if you use the `Sprite.play` method. If you opt to use + * `playAfterRepeat` or `playAfterDelay` instead, those will take priority and the mix + * delay will not be used. + * + * To update an existing mix, just call this method with the new delay. + * + * To remove a mix pairing, see the `removeMix` method. + * + * @method Phaser.Animations.AnimationManager#addMix + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A. + * @param {(string|Phaser.Animations.Animation)} animB - The string-based key, or instance of, Animation B. + * @param {number} delay - The delay, in milliseconds, to wait when transitioning from Animation A to B. + * + * @return {this} This Animation Manager. + */ + addMix: function (animA, animB, delay) + { + var anims = this.anims; + var mixes = this.mixes; + + var keyA = (typeof(animA) === 'string') ? animA : animA.key; + var keyB = (typeof(animB) === 'string') ? animB : animB.key; + + if (anims.has(keyA) && anims.has(keyB)) + { + var mixObj = mixes.get(keyA); + + if (!mixObj) + { + mixObj = {}; + } + + mixObj[keyB] = delay; + + mixes.set(keyA, mixObj); + } + + return this; + }, + + /** + * Removes a mix between two animations. + * + * Mixing allows you to specify a unique delay between a pairing of animations. + * + * Calling this method lets you remove those pairings. You can either remove + * it between `animA` and `animB`, or if you do not provide the `animB` parameter, + * it will remove all `animA` mixes. + * + * If you wish to update an existing mix instead, call the `addMix` method with the + * new delay. + * + * @method Phaser.Animations.AnimationManager#removeMix + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A. + * @param {(string|Phaser.Animations.Animation)} [animB] - The string-based key, or instance of, Animation B. If not given, all mixes for Animation A will be removed. + * + * @return {this} This Animation Manager. + */ + removeMix: function (animA, animB) + { + var mixes = this.mixes; + + var keyA = (typeof(animA) === 'string') ? animA : animA.key; + + var mixObj = mixes.get(keyA); + + if (mixObj) + { + if (animB) + { + var keyB = (typeof(animB) === 'string') ? animB : animB.key; + + if (mixObj.hasOwnProperty(keyB)) + { + // Remove just this pairing + delete mixObj[keyB]; + } + } + else if (!animB) + { + // Remove everything for animA + mixes.delete(keyA); + } + } + + return this; + }, + + /** + * Returns the mix delay between two animations. + * + * If no mix has been set-up, this method will return zero. + * + * If you wish to create, or update, a new mix, call the `addMix` method. + * If you wish to remove a mix, call the `removeMix` method. + * + * @method Phaser.Animations.AnimationManager#getMix + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation)} animA - The string-based key, or instance of, Animation A. + * @param {(string|Phaser.Animations.Animation)} animB - The string-based key, or instance of, Animation B. + * + * @return {number} The mix duration, or zero if no mix exists. + */ + getMix: function (animA, animB) + { + var mixes = this.mixes; + + var keyA = (typeof(animA) === 'string') ? animA : animA.key; + var keyB = (typeof(animB) === 'string') ? animB : animB.key; + + var mixObj = mixes.get(keyA); + + if (mixObj && mixObj.hasOwnProperty(keyB)) + { + return mixObj[keyB]; + } + else + { + return 0; + } + }, + + /** + * Adds an existing Animation to the Animation Manager. + * + * @method Phaser.Animations.AnimationManager#add + * @fires Phaser.Animations.Events#ADD_ANIMATION + * @since 3.0.0 + * + * @param {string} key - The key under which the Animation should be added. The Animation will be updated with it. Must be unique. + * @param {Phaser.Animations.Animation} animation - The Animation which should be added to the Animation Manager. + * + * @return {this} This Animation Manager. + */ + add: function (key, animation) + { + if (this.anims.has(key)) + { + console.warn('Animation key exists: ' + key); + + return this; + } + + animation.key = key; + + this.anims.set(key, animation); + + this.emit(Events.ADD_ANIMATION, key, animation); + + return this; + }, + + /** + * Checks to see if the given key is already in use within the Animation Manager or not. + * + * Animations are global. Keys created in one scene can be used from any other Scene in your game. They are not Scene specific. + * + * @method Phaser.Animations.AnimationManager#exists + * @since 3.16.0 + * + * @param {string} key - The key of the Animation to check. + * + * @return {boolean} `true` if the Animation already exists in the Animation Manager, or `false` if the key is available. + */ + exists: function (key) + { + return this.anims.has(key); + }, + + /** + * Create one, or more animations from a loaded Aseprite JSON file. + * + * Aseprite is a powerful animated sprite editor and pixel art tool. + * + * You can find more details at https://www.aseprite.org/ + * + * To export a compatible JSON file in Aseprite, please do the following: + * + * 1. Go to "File - Export Sprite Sheet" + * + * 2. On the **Layout** tab: + * 2a. Set the "Sheet type" to "Packed" + * 2b. Set the "Constraints" to "None" + * 2c. Check the "Merge Duplicates" checkbox + * + * 3. On the **Sprite** tab: + * 3a. Set "Layers" to "Visible layers" + * 3b. Set "Frames" to "All frames", unless you only wish to export a sub-set of tags + * + * 4. On the **Borders** tab: + * 4a. Check the "Trim Sprite" and "Trim Cells" options + * 4b. Ensure "Border Padding", "Spacing" and "Inner Padding" are all > 0 (1 is usually enough) + * + * 5. On the **Output** tab: + * 5a. Check "Output File", give your image a name and make sure you choose "png files" as the file type + * 5b. Check "JSON Data" and give your json file a name + * 5c. The JSON Data type can be either a Hash or Array, Phaser doesn't mind. + * 5d. Make sure "Tags" is checked in the Meta options + * 5e. In the "Item Filename" input box, make sure it says just "{frame}" and nothing more. + * + * 6. Click export + * + * This was tested with Aseprite 1.2.25. + * + * This will export a png and json file which you can load using the Aseprite Loader, i.e.: + * + * ```javascript + * function preload () + * { + * this.load.path = 'assets/animations/aseprite/'; + * this.load.aseprite('paladin', 'paladin.png', 'paladin.json'); + * } + * ``` + * + * Once loaded, you can call this method from within a Scene with the 'atlas' key: + * + * ```javascript + * this.anims.createFromAseprite('paladin'); + * ``` + * + * Any animations defined in the JSON will now be available to use in Phaser and you play them + * via their Tag name. For example, if you have an animation called 'War Cry' on your Aseprite timeline, + * you can play it in Phaser using that Tag name: + * + * ```javascript + * this.add.sprite(400, 300).play('War Cry'); + * ``` + * + * When calling this method you can optionally provide an array of tag names, and only those animations + * will be created. For example: + * + * ```javascript + * this.anims.createFromAseprite('paladin', [ 'step', 'War Cry', 'Magnum Break' ]); + * ``` + * + * This will only create the 3 animations defined. Note that the tag names are case-sensitive. + * + * @method Phaser.Animations.AnimationManager#createFromAseprite + * @since 3.50.0 + * + * @param {string} key - The key of the loaded Aseprite atlas. It must have been loaded prior to calling this method. + * @param {string[]} [tags] - An array of Tag names. If provided, only animations found in this array will be created. + * @param {(Phaser.Animations.AnimationManager|Phaser.GameObjects.GameObject)} [target] - Create the animations on this target Sprite. If not given, they will be created globally in this Animation Manager. + * + * @return {Phaser.Animations.Animation[]} An array of Animation instances that were successfully created. + */ + createFromAseprite: function (key, tags, target) + { + var output = []; + + var data = this.game.cache.json.get(key); + + if (!data) + { + console.warn('No Aseprite data found for: ' + key); + + return output; + } + + var _this = this; + + var meta = GetValue(data, 'meta', null); + var frames = GetValue(data, 'frames', null); + + if (meta && frames) + { + var frameTags = GetValue(meta, 'frameTags', []); + + frameTags.forEach(function (tag) + { + var animFrames = []; + + var name = GetFastValue(tag, 'name', null); + var from = GetFastValue(tag, 'from', 0); + var to = GetFastValue(tag, 'to', 0); + var direction = GetFastValue(tag, 'direction', 'forward'); + + if (!name) + { + // Skip if no name + return; + } + + if (!tags || (tags && tags.indexOf(name) > -1)) + { + // Get all the frames for this tag and calculate the total duration in milliseconds. + var totalDuration = 0; + for (var i = from; i <= to; i++) + { + var frameKey = i.toString(); + var frame = frames[frameKey]; + + if (frame) + { + var frameDuration = GetFastValue(frame, 'duration', MATH_CONST.MAX_SAFE_INTEGER); + animFrames.push({ key: key, frame: frameKey, duration: frameDuration }); + totalDuration += frameDuration; + } + } + + if (direction === 'reverse') + { + animFrames = animFrames.reverse(); + } + + // Create the animation + var createConfig = { + key: name, + frames: animFrames, + duration: totalDuration, + yoyo: (direction === 'pingpong') + }; + + var result; + + if (target) + { + if (target.anims) + { + result = target.anims.create(createConfig); + } + } + else + { + result = _this.create(createConfig); + } + + if (result) + { + output.push(result); + } + } + }); + } + + return output; + }, + + /** + * Creates a new Animation and adds it to the Animation Manager. + * + * Animations are global. Once created, you can use them in any Scene in your game. They are not Scene specific. + * + * If an invalid key is given this method will return `false`. + * + * If you pass the key of an animation that already exists in the Animation Manager, that animation will be returned. + * + * A brand new animation is only created if the key is valid and not already in use. + * + * If you wish to re-use an existing key, call `AnimationManager.remove` first, then this method. + * + * @method Phaser.Animations.AnimationManager#create + * @fires Phaser.Animations.Events#ADD_ANIMATION + * @since 3.0.0 + * + * @param {Phaser.Types.Animations.Animation} config - The configuration settings for the Animation. + * + * @return {(Phaser.Animations.Animation|false)} The Animation that was created, or `false` if the key is already in use. + */ + create: function (config) + { + var key = config.key; + + var anim = false; + + if (key) + { + anim = this.get(key); + + if (!anim) + { + anim = new Animation(this, key, config); + + this.anims.set(key, anim); + + this.emit(Events.ADD_ANIMATION, key, anim); + } + else + { + console.warn('AnimationManager key already exists: ' + key); + } + } + + return anim; + }, + + /** + * Loads this Animation Manager's Animations and settings from a JSON object. + * + * @method Phaser.Animations.AnimationManager#fromJSON + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Animations.JSONAnimations|Phaser.Types.Animations.JSONAnimation)} data - The JSON object to parse. + * @param {boolean} [clearCurrentAnimations=false] - If set to `true`, the current animations will be removed (`anims.clear()`). If set to `false` (default), the animations in `data` will be added. + * + * @return {Phaser.Animations.Animation[]} An array containing all of the Animation objects that were created as a result of this call. + */ + fromJSON: function (data, clearCurrentAnimations) + { + if (clearCurrentAnimations === undefined) { clearCurrentAnimations = false; } + + if (clearCurrentAnimations) + { + this.anims.clear(); + } + + // Do we have a String (i.e. from JSON, or an Object?) + if (typeof data === 'string') + { + data = JSON.parse(data); + } + + var output = []; + + // Array of animations, or a single animation? + if (data.hasOwnProperty('anims') && Array.isArray(data.anims)) + { + for (var i = 0; i < data.anims.length; i++) + { + output.push(this.create(data.anims[i])); + } + + if (data.hasOwnProperty('globalTimeScale')) + { + this.globalTimeScale = data.globalTimeScale; + } + } + else if (data.hasOwnProperty('key') && data.type === 'frame') + { + output.push(this.create(data)); + } + + return output; + }, + + /** + * Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object. + * + * Generates objects with string based frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNames}. + * + * It's a helper method, designed to make it easier for you to extract all of the frame names from texture atlases. + * + * If you're working with a sprite sheet, see the `generateFrameNumbers` method instead. + * + * Example: + * + * If you have a texture atlases loaded called `gems` and it contains 6 frames called `ruby_0001`, `ruby_0002`, and so on, + * then you can call this method using: `this.anims.generateFrameNames('gems', { prefix: 'ruby_', start: 1, end: 6, zeroPad: 4 })`. + * + * The `end` value tells it to select frames 1 through 6, incrementally numbered, all starting with the prefix `ruby_`. The `zeroPad` + * value tells it how many zeroes pad out the numbers. To create an animation using this method, you can do: + * + * ```javascript + * this.anims.create({ + * key: 'ruby', + * repeat: -1, + * frames: this.anims.generateFrameNames('gems', { + * prefix: 'ruby_', + * end: 6, + * zeroPad: 4 + * }) + * }); + * ``` + * + * Please see the animation examples for further details. + * + * @method Phaser.Animations.AnimationManager#generateFrameNames + * @since 3.0.0 + * + * @param {string} key - The key for the texture containing the animation frames. + * @param {Phaser.Types.Animations.GenerateFrameNames} [config] - The configuration object for the animation frame names. + * + * @return {Phaser.Types.Animations.AnimationFrame[]} The array of {@link Phaser.Types.Animations.AnimationFrame} objects. + */ + generateFrameNames: function (key, config) + { + var prefix = GetValue(config, 'prefix', ''); + var start = GetValue(config, 'start', 0); + var end = GetValue(config, 'end', 0); + var suffix = GetValue(config, 'suffix', ''); + var zeroPad = GetValue(config, 'zeroPad', 0); + var out = GetValue(config, 'outputArray', []); + var frames = GetValue(config, 'frames', false); + + if (!this.textureManager.exists(key)) + { + console.warn('Texture "%s" not found', key); + + return out; + } + + var texture = this.textureManager.get(key); + + if (!texture) + { + return out; + } + + var i; + + if (!config) + { + // Use every frame in the atlas + frames = texture.getFrameNames(); + + for (i = 0; i < frames.length; i++) + { + out.push({ key: key, frame: frames[i] }); + } + } + else + { + if (!frames) + { + frames = NumberArray(start, end); + } + + for (i = 0; i < frames.length; i++) + { + var frame = prefix + Pad(frames[i], zeroPad, '0', 1) + suffix; + + if (texture.has(frame)) + { + out.push({ key: key, frame: frame }); + } + else + { + console.warn('Frame "%s" not found in texture "%s"', frame, key); + } + } + } + + return out; + }, + + /** + * Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object. + * + * Generates objects with numbered frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNumbers}. + * + * If you're working with a texture atlas, see the `generateFrameNames` method instead. + * + * It's a helper method, designed to make it easier for you to extract frames from sprite sheets. + * + * Example: + * + * If you have a sprite sheet loaded called `explosion` and it contains 12 frames, then you can call this method using: + * + * `this.anims.generateFrameNumbers('explosion', { start: 0, end: 11 })`. + * + * The `end` value of 11 tells it to stop after the 12th frame has been added, because it started at zero. + * + * To create an animation using this method, you can do: + * + * ```javascript + * this.anims.create({ + * key: 'boom', + * frames: this.anims.generateFrameNumbers('explosion', { + * start: 0, + * end: 11 + * }) + * }); + * ``` + * + * Note that `start` is optional and you don't need to include it if the animation starts from frame 0. + * + * To specify an animation in reverse, swap the `start` and `end` values. + * + * If the frames are not sequential, you may pass an array of frame numbers instead, for example: + * + * `this.anims.generateFrameNumbers('explosion', { frames: [ 0, 1, 2, 1, 2, 3, 4, 0, 1, 2 ] })` + * + * Please see the animation examples and `GenerateFrameNumbers` config docs for further details. + * + * @method Phaser.Animations.AnimationManager#generateFrameNumbers + * @since 3.0.0 + * + * @param {string} key - The key for the texture containing the animation frames. + * @param {Phaser.Types.Animations.GenerateFrameNumbers} [config] - The configuration object for the animation frames. + * + * @return {Phaser.Types.Animations.AnimationFrame[]} The array of {@link Phaser.Types.Animations.AnimationFrame} objects. + */ + generateFrameNumbers: function (key, config) + { + var start = GetValue(config, 'start', 0); + var end = GetValue(config, 'end', -1); + var first = GetValue(config, 'first', false); + var out = GetValue(config, 'outputArray', []); + var frames = GetValue(config, 'frames', false); + + if (!this.textureManager.exists(key)) + { + console.warn('Texture "%s" not found', key); + + return out; + } + + var texture = this.textureManager.get(key); + + if (!texture) + { + return out; + } + + if (first && texture.has(first)) + { + out.push({ key: key, frame: first }); + } + + // No 'frames' array? Then generate one automatically + if (!frames) + { + if (end === -1) + { + // -1 because of __BASE, which we don't want in our results + // and -1 because frames are zero based + end = texture.frameTotal - 2; + } + + frames = NumberArray(start, end); + } + + for (var i = 0; i < frames.length; i++) + { + var frameName = frames[i]; + + if (texture.has(frameName)) + { + out.push({ key: key, frame: frameName }); + } + else + { + console.warn('Frame "%s" not found in texture "%s"', frameName, key); + } + } + + return out; + }, + + /** + * Get an Animation. + * + * @method Phaser.Animations.AnimationManager#get + * @since 3.0.0 + * + * @param {string} key - The key of the Animation to retrieve. + * + * @return {Phaser.Animations.Animation} The Animation. + */ + get: function (key) + { + return this.anims.get(key); + }, + + /** + * Returns an array of all Animation keys that are using the given + * Texture. Only Animations that have at least one AnimationFrame + * entry using this texture will be included in the result. + * + * @method Phaser.Animations.AnimationManager#getAnimsFromTexture + * @since 3.60.0 + * + * @param {(string|Phaser.Textures.Texture|Phaser.Textures.Frame)} key - The unique string-based key of the Texture, or a Texture, or Frame instance. + * + * @return {string[]} An array of Animation keys that feature the given Texture. + */ + getAnimsFromTexture: function (key) + { + var texture = this.textureManager.get(key); + + var match = texture.key; + var anims = this.anims.getArray(); + + var out = []; + + for (var i = 0; i < anims.length; i++) + { + var anim = anims[i]; + var frames = anim.frames; + + for (var c = 0; c < frames.length; c++) + { + if (frames[c].textureKey === match) + { + out.push(anim.key); + + break; + } + } + } + + return out; + }, + + /** + * Pause all animations. + * + * @method Phaser.Animations.AnimationManager#pauseAll + * @fires Phaser.Animations.Events#PAUSE_ALL + * @since 3.0.0 + * + * @return {this} This Animation Manager. + */ + pauseAll: function () + { + if (!this.paused) + { + this.paused = true; + + this.emit(Events.PAUSE_ALL); + } + + return this; + }, + + /** + * Play an animation on the given Game Objects that have an Animation Component. + * + * @method Phaser.Animations.AnimationManager#play + * @since 3.0.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component. + * + * @return {this} This Animation Manager. + */ + play: function (key, children) + { + if (!Array.isArray(children)) + { + children = [ children ]; + } + + for (var i = 0; i < children.length; i++) + { + children[i].anims.play(key); + } + + return this; + }, + + /** + * Takes an array of Game Objects that have an Animation Component and then + * starts the given animation playing on them. The start time of each Game Object + * is offset, incrementally, by the `stagger` amount. + * + * For example, if you pass an array with 4 children and a stagger time of 1000, + * the delays will be: + * + * child 1: 1000ms delay + * child 2: 2000ms delay + * child 3: 3000ms delay + * child 4: 4000ms delay + * + * If you set the `staggerFirst` parameter to `false` they would be: + * + * child 1: 0ms delay + * child 2: 1000ms delay + * child 3: 2000ms delay + * child 4: 3000ms delay + * + * You can also set `stagger` to be a negative value. If it was -1000, the above would be: + * + * child 1: 3000ms delay + * child 2: 2000ms delay + * child 3: 1000ms delay + * child 4: 0ms delay + * + * @method Phaser.Animations.AnimationManager#staggerPlay + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} children - An array of Game Objects to play the animation on. They must have an Animation Component. + * @param {number} stagger - The amount of time, in milliseconds, to offset each play time by. If a negative value is given, it's applied to the children in reverse order. + * @param {boolean} [staggerFirst=true] -Should the first child be staggered as well? + * + * @return {this} This Animation Manager. + */ + staggerPlay: function (key, children, stagger, staggerFirst) + { + if (stagger === undefined) { stagger = 0; } + if (staggerFirst === undefined) { staggerFirst = true; } + + if (!Array.isArray(children)) + { + children = [ children ]; + } + + var len = children.length; + + if (!staggerFirst) + { + len--; + } + + for (var i = 0; i < children.length; i++) + { + var time = (stagger < 0) ? Math.abs(stagger) * (len - i) : stagger * i; + + children[i].anims.playAfterDelay(key, time); + } + + return this; + }, + + /** + * Removes an Animation from this Animation Manager, based on the given key. + * + * This is a global action. Once an Animation has been removed, no Game Objects + * can carry on using it. + * + * @method Phaser.Animations.AnimationManager#remove + * @fires Phaser.Animations.Events#REMOVE_ANIMATION + * @since 3.0.0 + * + * @param {string} key - The key of the animation to remove. + * + * @return {Phaser.Animations.Animation} The Animation instance that was removed from the Animation Manager. + */ + remove: function (key) + { + var anim = this.get(key); + + if (anim) + { + this.emit(Events.REMOVE_ANIMATION, key, anim); + + this.anims.delete(key); + + this.removeMix(key); + } + + return anim; + }, + + /** + * Resume all paused animations. + * + * @method Phaser.Animations.AnimationManager#resumeAll + * @fires Phaser.Animations.Events#RESUME_ALL + * @since 3.0.0 + * + * @return {this} This Animation Manager. + */ + resumeAll: function () + { + if (this.paused) + { + this.paused = false; + + this.emit(Events.RESUME_ALL); + } + + return this; + }, + + /** + * Returns the Animation data as JavaScript object based on the given key. + * Or, if not key is defined, it will return the data of all animations as array of objects. + * + * @method Phaser.Animations.AnimationManager#toJSON + * @since 3.0.0 + * + * @param {string} [key] - The animation to get the JSONAnimation data from. If not provided, all animations are returned as an array. + * + * @return {Phaser.Types.Animations.JSONAnimations} The resulting JSONAnimations formatted object. + */ + toJSON: function (key) + { + var output = { + anims: [], + globalTimeScale: this.globalTimeScale + }; + + if (key !== undefined && key !== '') + { + output.anims.push(this.anims.get(key).toJSON()); + } + else + { + this.anims.each(function (animationKey, animation) + { + output.anims.push(animation.toJSON()); + }); + } + + return output; + }, + + /** + * Destroy this Animation Manager and clean up animation definitions and references to other objects. + * This method should not be called directly. It will be called automatically as a response to a `destroy` event from the Phaser.Game instance. + * + * @method Phaser.Animations.AnimationManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.anims.clear(); + this.mixes.clear(); + + this.textureManager = null; + + this.game = null; + } + +}); + +module.exports = AnimationManager; + + +/***/ }), + +/***/ 9674: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Animation = __webpack_require__(42099); +var Between = __webpack_require__(30976); +var Class = __webpack_require__(83419); +var CustomMap = __webpack_require__(90330); +var Events = __webpack_require__(74943); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * The Animation State Component. + * + * This component provides features to apply animations to Game Objects. It is responsible for + * loading, queuing animations for later playback, mixing between animations and setting + * the current animation frame to the Game Object that owns this component. + * + * This component lives as an instance within any Game Object that has it defined, such as Sprites. + * + * You can access its properties and methods via the `anims` property, i.e. `Sprite.anims`. + * + * As well as playing animations stored in the global Animation Manager, this component + * can also create animations that are stored locally within it. See the `create` method + * for more details. + * + * Prior to Phaser 3.50 this component was called just `Animation` and lived in the + * `Phaser.GameObjects.Components` namespace. It was renamed to `AnimationState` + * in 3.50 to help better identify its true purpose when browsing the documentation. + * + * @class AnimationState + * @memberof Phaser.Animations + * @constructor + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} parent - The Game Object to which this animation component belongs. + */ +var AnimationState = new Class({ + + initialize: + + function AnimationState (parent) + { + /** + * The Game Object to which this animation component belongs. + * + * You can typically access this component from the Game Object + * via the `this.anims` property. + * + * @name Phaser.Animations.AnimationState#parent + * @type {Phaser.GameObjects.GameObject} + * @since 3.0.0 + */ + this.parent = parent; + + /** + * A reference to the global Animation Manager. + * + * @name Phaser.Animations.AnimationState#animationManager + * @type {Phaser.Animations.AnimationManager} + * @since 3.0.0 + */ + this.animationManager = parent.scene.sys.anims; + + this.animationManager.on(Events.REMOVE_ANIMATION, this.globalRemove, this); + + /** + * A reference to the Texture Manager. + * + * @name Phaser.Animations.AnimationState#textureManager + * @type {Phaser.Textures.TextureManager} + * @protected + * @since 3.50.0 + */ + this.textureManager = this.animationManager.textureManager; + + /** + * The Animations stored locally in this Animation component. + * + * Do not modify the contents of this Map directly, instead use the + * `add`, `create` and `remove` methods of this class instead. + * + * @name Phaser.Animations.AnimationState#anims + * @type {Phaser.Structs.Map.} + * @protected + * @since 3.50.0 + */ + this.anims = null; + + /** + * Is an animation currently playing or not? + * + * @name Phaser.Animations.AnimationState#isPlaying + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isPlaying = false; + + /** + * Has the current animation started playing, or is it waiting for a delay to expire? + * + * @name Phaser.Animations.AnimationState#hasStarted + * @type {boolean} + * @default false + * @since 3.50.0 + */ + this.hasStarted = false; + + /** + * The current Animation loaded into this Animation component. + * + * Will be `null` if no animation is yet loaded. + * + * @name Phaser.Animations.AnimationState#currentAnim + * @type {?Phaser.Animations.Animation} + * @default null + * @since 3.0.0 + */ + this.currentAnim = null; + + /** + * The current AnimationFrame being displayed by this Animation component. + * + * Will be `null` if no animation is yet loaded. + * + * @name Phaser.Animations.AnimationState#currentFrame + * @type {?Phaser.Animations.AnimationFrame} + * @default null + * @since 3.0.0 + */ + this.currentFrame = null; + + /** + * The key, instance, or config of the next Animation to be loaded into this Animation component + * when the current animation completes. + * + * Will be `null` if no animation has been queued. + * + * @name Phaser.Animations.AnimationState#nextAnim + * @type {?(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} + * @default null + * @since 3.16.0 + */ + this.nextAnim = null; + + /** + * A queue of Animations to be loaded into this Animation component when the current animation completes. + * + * Populate this queue via the `chain` method. + * + * @name Phaser.Animations.AnimationState#nextAnimsQueue + * @type {array} + * @since 3.24.0 + */ + this.nextAnimsQueue = []; + + /** + * The Time Scale factor. + * + * You can adjust this value to modify the passage of time for the animation that is currently + * playing. For example, setting it to 2 will make the animation play twice as fast. Or setting + * it to 0.5 will slow the animation down. + * + * You can change this value at run-time, or set it via the `PlayAnimationConfig`. + * + * Prior to Phaser 3.50 this property was private and called `_timeScale`. + * + * @name Phaser.Animations.AnimationState#timeScale + * @type {number} + * @default 1 + * @since 3.50.0 + */ + this.timeScale = 1; + + /** + * The frame rate of playback, of the current animation, in frames per second. + * + * This value is set when a new animation is loaded into this component and should + * be treated as read-only, as changing it once playback has started will not alter + * the animation. To change the frame rate, provide a new value in the `PlayAnimationConfig` object. + * + * @name Phaser.Animations.AnimationState#frameRate + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.frameRate = 0; + + /** + * The duration of the current animation, in milliseconds. + * + * This value is set when a new animation is loaded into this component and should + * be treated as read-only, as changing it once playback has started will not alter + * the animation. To change the duration, provide a new value in the `PlayAnimationConfig` object. + * + * @name Phaser.Animations.AnimationState#duration + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.duration = 0; + + /** + * The number of milliseconds per frame, not including frame specific modifiers that may be present in the + * Animation data. + * + * This value is calculated when a new animation is loaded into this component and should + * be treated as read-only. Changing it will not alter playback speed. + * + * @name Phaser.Animations.AnimationState#msPerFrame + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.msPerFrame = 0; + + /** + * Skip frames if the time lags, or always advanced anyway? + * + * @name Phaser.Animations.AnimationState#skipMissedFrames + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.skipMissedFrames = true; + + /** + * Start playback of this animation from a random frame? + * + * @name Phaser.Animations.AnimationState#randomFrame + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.randomFrame = false; + + /** + * The delay before starting playback of the current animation, in milliseconds. + * + * This value is set when a new animation is loaded into this component and should + * be treated as read-only, as changing it once playback has started will not alter + * the animation. To change the delay, provide a new value in the `PlayAnimationConfig` object. + * + * Prior to Phaser 3.50 this property was private and called `_delay`. + * + * @name Phaser.Animations.AnimationState#delay + * @type {number} + * @default 0 + * @since 3.50.0 + */ + this.delay = 0; + + /** + * The number of times to repeat playback of the current animation. + * + * If -1, it means the animation will repeat forever. + * + * This value is set when a new animation is loaded into this component and should + * be treated as read-only, as changing it once playback has started will not alter + * the animation. To change the number of repeats, provide a new value in the `PlayAnimationConfig` object. + * + * Prior to Phaser 3.50 this property was private and called `_repeat`. + * + * @name Phaser.Animations.AnimationState#repeat + * @type {number} + * @default 0 + * @since 3.50.0 + */ + this.repeat = 0; + + /** + * The number of milliseconds to wait before starting the repeat playback of the current animation. + * + * This value is set when a new animation is loaded into this component, but can also be modified + * at run-time. + * + * You can change the repeat delay by providing a new value in the `PlayAnimationConfig` object. + * + * Prior to Phaser 3.50 this property was private and called `_repeatDelay`. + * + * @name Phaser.Animations.AnimationState#repeatDelay + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.repeatDelay = 0; + + /** + * Should the current animation yoyo? An animation that yoyos will play in reverse, from the end + * to the start, before then repeating or completing. An animation that does not yoyo will just + * play from the start to the end. + * + * This value is set when a new animation is loaded into this component, but can also be modified + * at run-time. + * + * You can change the yoyo by providing a new value in the `PlayAnimationConfig` object. + * + * Prior to Phaser 3.50 this property was private and called `_yoyo`. + * + * @name Phaser.Animations.AnimationState#yoyo + * @type {boolean} + * @default false + * @since 3.50.0 + */ + this.yoyo = false; + + /** + * If the animation has a delay set, before playback will begin, this + * controls when the first frame is set on the Sprite. If this property + * is 'false' then the frame is set only after the delay has expired. + * This is the default behavior. + * + * If this property is 'true' then the first frame of this animation + * is set immediately, and then when the delay expires, playback starts. + * + * @name Phaser.Animations.AnimationState#showBeforeDelay + * @type {boolean} + * @since 3.60.0 + */ + this.showBeforeDelay = false; + + /** + * Should the GameObject's `visible` property be set to `true` when the animation starts to play? + * + * This will happen _after_ any delay that may have been set. + * + * This value is set when a new animation is loaded into this component, but can also be modified + * at run-time, assuming the animation is currently delayed. + * + * @name Phaser.Animations.AnimationState#showOnStart + * @type {boolean} + * @since 3.50.0 + */ + this.showOnStart = false; + + /** + * Should the GameObject's `visible` property be set to `false` when the animation completes? + * + * This value is set when a new animation is loaded into this component, but can also be modified + * at run-time, assuming the animation is still actively playing. + * + * @name Phaser.Animations.AnimationState#hideOnComplete + * @type {boolean} + * @since 3.50.0 + */ + this.hideOnComplete = false; + + /** + * Is the playhead moving forwards (`true`) or in reverse (`false`) ? + * + * @name Phaser.Animations.AnimationState#forward + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.forward = true; + + /** + * An internal trigger that tells the component if it should plays the animation + * in reverse mode ('true') or not ('false'). This is used because `forward` can + * be changed by the `yoyo` feature. + * + * Prior to Phaser 3.50 this property was private and called `_reverse`. + * + * @name Phaser.Animations.AnimationState#inReverse + * @type {boolean} + * @default false + * @since 3.50.0 + */ + this.inReverse = false; + + /** + * Internal time overflow accumulator. + * + * This has the `delta` time added to it as part of the `update` step. + * + * @name Phaser.Animations.AnimationState#accumulator + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.accumulator = 0; + + /** + * The time point at which the next animation frame will change. + * + * This value is compared against the `accumulator` as part of the `update` step. + * + * @name Phaser.Animations.AnimationState#nextTick + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.nextTick = 0; + + /** + * A counter keeping track of how much delay time, in milliseconds, is left before playback begins. + * + * This is set via the `playAfterDelay` method, although it can be modified at run-time + * if required, as long as the animation has not already started playing. + * + * @name Phaser.Animations.AnimationState#delayCounter + * @type {number} + * @default 0 + * @since 3.50.0 + */ + this.delayCounter = 0; + + /** + * A counter that keeps track of how many repeats are left to run. + * + * This value is set when a new animation is loaded into this component, but can also be modified + * at run-time. + * + * @name Phaser.Animations.AnimationState#repeatCounter + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.repeatCounter = 0; + + /** + * An internal flag keeping track of pending repeats. + * + * @name Phaser.Animations.AnimationState#pendingRepeat + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.pendingRepeat = false; + + /** + * Is the Animation paused? + * + * @name Phaser.Animations.AnimationState#_paused + * @type {boolean} + * @private + * @default false + * @since 3.0.0 + */ + this._paused = false; + + /** + * Was the animation previously playing before being paused? + * + * @name Phaser.Animations.AnimationState#_wasPlaying + * @type {boolean} + * @private + * @default false + * @since 3.0.0 + */ + this._wasPlaying = false; + + /** + * Internal property tracking if this Animation is waiting to stop. + * + * 0 = No + * 1 = Waiting for ms to pass + * 2 = Waiting for repeat + * 3 = Waiting for specific frame + * + * @name Phaser.Animations.AnimationState#_pendingStop + * @type {number} + * @private + * @since 3.4.0 + */ + this._pendingStop = 0; + + /** + * Internal property used by _pendingStop. + * + * @name Phaser.Animations.AnimationState#_pendingStopValue + * @type {any} + * @private + * @since 3.4.0 + */ + this._pendingStopValue; + }, + + /** + * Sets an animation, or an array of animations, to be played in the future, after the current one completes or stops. + * + * The current animation must enter a 'completed' state for this to happen, i.e. finish all of its repeats, delays, etc, + * or have one of the `stop` methods called. + * + * An animation set to repeat forever will never enter a completed state unless stopped. + * + * You can chain a new animation at any point, including before the current one starts playing, during it, or when it ends (via its `animationcomplete` event). + * + * Chained animations are specific to a Game Object, meaning different Game Objects can have different chained animations without impacting the global animation they're playing. + * + * Call this method with no arguments to reset all currently chained animations. + * + * @method Phaser.Animations.AnimationState#chain + * @since 3.16.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig|string[]|Phaser.Animations.Animation[]|Phaser.Types.Animations.PlayAnimationConfig[])} [key] - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object, or an array of them. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + chain: function (key) + { + var parent = this.parent; + + if (key === undefined) + { + this.nextAnimsQueue.length = 0; + this.nextAnim = null; + + return parent; + } + + if (!Array.isArray(key)) + { + key = [ key ]; + } + + for (var i = 0; i < key.length; i++) + { + var anim = key[i]; + + if (!this.nextAnim) + { + this.nextAnim = anim; + } + else + { + this.nextAnimsQueue.push(anim); + } + } + + return this.parent; + }, + + /** + * Returns the key of the animation currently loaded into this component. + * + * Prior to Phaser 3.50 this method was called `getCurrentKey`. + * + * @method Phaser.Animations.AnimationState#getName + * @since 3.50.0 + * + * @return {string} The key of the Animation currently loaded into this component, or an empty string if none loaded. + */ + getName: function () + { + return (this.currentAnim) ? this.currentAnim.key : ''; + }, + + /** + * Returns the key of the animation frame currently displayed by this component. + * + * @method Phaser.Animations.AnimationState#getFrameName + * @since 3.50.0 + * + * @return {string} The key of the Animation Frame currently displayed by this component, or an empty string if no animation has been loaded. + */ + getFrameName: function () + { + return (this.currentFrame) ? this.currentFrame.textureFrame : ''; + }, + + /** + * Internal method used to load an animation into this component. + * + * @method Phaser.Animations.AnimationState#load + * @protected + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or a `PlayAnimationConfig` object. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + load: function (key) + { + if (this.isPlaying) + { + this.stop(); + } + + var manager = this.animationManager; + var animKey = (typeof key === 'string') ? key : GetFastValue(key, 'key', null); + + // Get the animation, first from the local map and, if not found, from the Animation Manager + var anim = (this.exists(animKey)) ? this.get(animKey) : manager.get(animKey); + + if (!anim) + { + console.warn('Missing animation: ' + animKey); + } + else + { + this.currentAnim = anim; + + // And now override the animation values, if set in the config. + + var totalFrames = anim.getTotalFrames(); + var frameRate = GetFastValue(key, 'frameRate', anim.frameRate); + var duration = GetFastValue(key, 'duration', anim.duration); + + anim.calculateDuration(this, totalFrames, duration, frameRate); + + this.delay = GetFastValue(key, 'delay', anim.delay); + this.repeat = GetFastValue(key, 'repeat', anim.repeat); + this.repeatDelay = GetFastValue(key, 'repeatDelay', anim.repeatDelay); + this.yoyo = GetFastValue(key, 'yoyo', anim.yoyo); + this.showBeforeDelay = GetFastValue(key, 'showBeforeDelay', anim.showBeforeDelay); + this.showOnStart = GetFastValue(key, 'showOnStart', anim.showOnStart); + this.hideOnComplete = GetFastValue(key, 'hideOnComplete', anim.hideOnComplete); + this.skipMissedFrames = GetFastValue(key, 'skipMissedFrames', anim.skipMissedFrames); + this.randomFrame = GetFastValue(key, 'randomFrame', anim.randomFrame); + + this.timeScale = GetFastValue(key, 'timeScale', this.timeScale); + + var startFrame = GetFastValue(key, 'startFrame', 0); + + if (startFrame > totalFrames) + { + startFrame = 0; + } + + if (this.randomFrame) + { + startFrame = Between(0, totalFrames - 1); + } + + var frame = anim.frames[startFrame]; + + if (startFrame === 0 && !this.forward) + { + frame = anim.getLastFrame(); + } + + this.currentFrame = frame; + } + + return this.parent; + }, + + /** + * Pause the current animation and set the `isPlaying` property to `false`. + * You can optionally pause it at a specific frame. + * + * @method Phaser.Animations.AnimationState#pause + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationFrame} [atFrame] - An optional frame to set after pausing the animation. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + pause: function (atFrame) + { + if (!this._paused) + { + this._paused = true; + this._wasPlaying = this.isPlaying; + this.isPlaying = false; + } + + if (atFrame !== undefined) + { + this.setCurrentFrame(atFrame); + } + + return this.parent; + }, + + /** + * Resumes playback of a paused animation and sets the `isPlaying` property to `true`. + * You can optionally tell it to start playback from a specific frame. + * + * @method Phaser.Animations.AnimationState#resume + * @since 3.0.0 + * + * @param {Phaser.Animations.AnimationFrame} [fromFrame] - An optional frame to set before restarting playback. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + resume: function (fromFrame) + { + if (this._paused) + { + this._paused = false; + this.isPlaying = this._wasPlaying; + } + + if (fromFrame !== undefined) + { + this.setCurrentFrame(fromFrame); + } + + return this.parent; + }, + + /** + * Waits for the specified delay, in milliseconds, then starts playback of the given animation. + * + * If the animation _also_ has a delay value set in its config, it will be **added** to the delay given here. + * + * If an animation is already running and a new animation is given to this method, it will wait for + * the given delay before starting the new animation. + * + * If no animation is currently running, the given one begins after the delay. + * + * Prior to Phaser 3.50 this method was called 'delayedPlay' and the parameters were in the reverse order. + * + * @method Phaser.Animations.AnimationState#playAfterDelay + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {number} delay - The delay, in milliseconds, to wait before starting the animation playing. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + playAfterDelay: function (key, delay) + { + if (!this.isPlaying) + { + this.delayCounter = delay; + + this.play(key, true); + } + else + { + // If we've got a nextAnim, move it to the queue + var nextAnim = this.nextAnim; + var queue = this.nextAnimsQueue; + + if (nextAnim) + { + queue.unshift(nextAnim); + } + + this.nextAnim = key; + + this._pendingStop = 1; + this._pendingStopValue = delay; + } + + return this.parent; + }, + + /** + * Waits for the current animation to complete the `repeatCount` number of repeat cycles, then starts playback + * of the given animation. + * + * You can use this to ensure there are no harsh jumps between two sets of animations, i.e. going from an + * idle animation to a walking animation, by making them blend smoothly into each other. + * + * If no animation is currently running, the given one will start immediately. + * + * @method Phaser.Animations.AnimationState#playAfterRepeat + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {number} [repeatCount=1] - How many times should the animation repeat before the next one starts? + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + playAfterRepeat: function (key, repeatCount) + { + if (repeatCount === undefined) { repeatCount = 1; } + + if (!this.isPlaying) + { + this.play(key); + } + else + { + // If we've got a nextAnim, move it to the queue + var nextAnim = this.nextAnim; + var queue = this.nextAnimsQueue; + + if (nextAnim) + { + queue.unshift(nextAnim); + } + + if (this.repeatCounter !== -1 && repeatCount > this.repeatCounter) + { + repeatCount = this.repeatCounter; + } + + this.nextAnim = key; + + this._pendingStop = 2; + this._pendingStopValue = repeatCount; + } + + return this.parent; + }, + + /** + * Start playing the given animation on this Sprite. + * + * Animations in Phaser can either belong to the global Animation Manager, or specifically to this Sprite. + * + * The benefit of a global animation is that multiple Sprites can all play the same animation, without + * having to duplicate the data. You can just create it once and then play it on any Sprite. + * + * The following code shows how to create a global repeating animation. The animation will be created + * from all of the frames within the sprite sheet that was loaded with the key 'muybridge': + * + * ```javascript + * var config = { + * key: 'run', + * frames: 'muybridge', + * frameRate: 15, + * repeat: -1 + * }; + * + * // This code should be run from within a Scene: + * this.anims.create(config); + * ``` + * + * However, if you wish to create an animation that is unique to this Sprite, and this Sprite alone, + * you can call the `Animation.create` method instead. It accepts the exact same parameters as when + * creating a global animation, however the resulting data is kept locally in this Sprite. + * + * With the animation created, either globally or locally, you can now play it on this Sprite: + * + * ```javascript + * this.add.sprite(x, y).play('run'); + * ``` + * + * Alternatively, if you wish to run it at a different frame rate, for example, you can pass a config + * object instead: + * + * ```javascript + * this.add.sprite(x, y).play({ key: 'run', frameRate: 24 }); + * ``` + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * If you need a Sprite to be able to play both local and global animations, make sure they don't + * have conflicting keys. + * + * See the documentation for the `PlayAnimationConfig` config object for more details about this. + * + * Also, see the documentation in the Animation Manager for further details on creating animations. + * + * @method Phaser.Animations.AnimationState#play + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.0.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {boolean} [ignoreIfPlaying=false] - If this animation is already playing then ignore this call. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + play: function (key, ignoreIfPlaying) + { + if (ignoreIfPlaying === undefined) { ignoreIfPlaying = false; } + + var currentAnim = this.currentAnim; + var parent = this.parent; + + // Must be either an Animation instance, or a PlayAnimationConfig object + var animKey = (typeof key === 'string') ? key : key.key; + + if (ignoreIfPlaying && this.isPlaying && currentAnim.key === animKey) + { + return parent; + } + + // Are we mixing? + if (currentAnim && this.isPlaying) + { + var mix = this.animationManager.getMix(currentAnim.key, key); + + if (mix > 0) + { + return this.playAfterDelay(key, mix); + } + } + + this.forward = true; + this.inReverse = false; + + this._paused = false; + this._wasPlaying = true; + + return this.startAnimation(key); + }, + + /** + * Start playing the given animation on this Sprite, in reverse. + * + * Animations in Phaser can either belong to the global Animation Manager, or specifically to this Sprite. + * + * The benefit of a global animation is that multiple Sprites can all play the same animation, without + * having to duplicate the data. You can just create it once and then play it on any Sprite. + * + * The following code shows how to create a global repeating animation. The animation will be created + * from all of the frames within the sprite sheet that was loaded with the key 'muybridge': + * + * ```javascript + * var config = { + * key: 'run', + * frames: 'muybridge', + * frameRate: 15, + * repeat: -1 + * }; + * + * // This code should be run from within a Scene: + * this.anims.create(config); + * ``` + * + * However, if you wish to create an animation that is unique to this Sprite, and this Sprite alone, + * you can call the `Animation.create` method instead. It accepts the exact same parameters as when + * creating a global animation, however the resulting data is kept locally in this Sprite. + * + * With the animation created, either globally or locally, you can now play it on this Sprite: + * + * ```javascript + * this.add.sprite(x, y).playReverse('run'); + * ``` + * + * Alternatively, if you wish to run it at a different frame rate, for example, you can pass a config + * object instead: + * + * ```javascript + * this.add.sprite(x, y).playReverse({ key: 'run', frameRate: 24 }); + * ``` + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * If you need a Sprite to be able to play both local and global animations, make sure they don't + * have conflicting keys. + * + * See the documentation for the `PlayAnimationConfig` config object for more details about this. + * + * Also, see the documentation in the Animation Manager for further details on creating animations. + * + * @method Phaser.Animations.AnimationState#playReverse + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.12.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {boolean} [ignoreIfPlaying=false] - If an animation is already playing then ignore this call. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + playReverse: function (key, ignoreIfPlaying) + { + if (ignoreIfPlaying === undefined) { ignoreIfPlaying = false; } + + // Must be either an Animation instance, or a PlayAnimationConfig object + var animKey = (typeof key === 'string') ? key : key.key; + + if (ignoreIfPlaying && this.isPlaying && this.currentAnim.key === animKey) + { + return this.parent; + } + + this.forward = false; + this.inReverse = true; + + this._paused = false; + this._wasPlaying = true; + + return this.startAnimation(key); + }, + + /** + * Load the animation based on the key and set-up all of the internal values + * needed for playback to start. If there is no delay, it will also fire the start events. + * + * @method Phaser.Animations.AnimationState#startAnimation + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.50.0 + * + * @param {(string|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or a `PlayAnimationConfig` object. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + startAnimation: function (key) + { + this.load(key); + + var anim = this.currentAnim; + var gameObject = this.parent; + + if (!anim) + { + return gameObject; + } + + // Should give us 9,007,199,254,740,991 safe repeats + this.repeatCounter = (this.repeat === -1) ? Number.MAX_VALUE : this.repeat; + + anim.getFirstTick(this); + + this.isPlaying = true; + this.pendingRepeat = false; + this.hasStarted = false; + + this._pendingStop = 0; + this._pendingStopValue = 0; + this._paused = false; + + // Add any delay the animation itself may have had as well + this.delayCounter += this.delay; + + if (this.delayCounter === 0) + { + this.handleStart(); + } + else if (this.showBeforeDelay) + { + // We have a delay, but still need to set the frame + this.setCurrentFrame(this.currentFrame); + } + + return gameObject; + }, + + /** + * Handles the start of an animation playback. + * + * @method Phaser.Animations.AnimationState#handleStart + * @private + * @since 3.50.0 + */ + handleStart: function () + { + if (this.showOnStart) + { + this.parent.setVisible(true); + } + + this.setCurrentFrame(this.currentFrame); + + this.hasStarted = true; + + this.emitEvents(Events.ANIMATION_START); + }, + + /** + * Handles the repeat of an animation. + * + * @method Phaser.Animations.AnimationState#handleRepeat + * @private + * @since 3.50.0 + */ + handleRepeat: function () + { + this.pendingRepeat = false; + + this.emitEvents(Events.ANIMATION_REPEAT); + }, + + /** + * Handles the stop of an animation playback. + * + * @method Phaser.Animations.AnimationState#handleStop + * @private + * @since 3.50.0 + */ + handleStop: function () + { + this._pendingStop = 0; + + this.isPlaying = false; + + this.emitEvents(Events.ANIMATION_STOP); + }, + + /** + * Handles the completion of an animation playback. + * + * @method Phaser.Animations.AnimationState#handleComplete + * @private + * @since 3.50.0 + */ + handleComplete: function () + { + this._pendingStop = 0; + + this.isPlaying = false; + + if (this.hideOnComplete) + { + this.parent.setVisible(false); + } + + this.emitEvents(Events.ANIMATION_COMPLETE, Events.ANIMATION_COMPLETE_KEY); + }, + + /** + * Fires the given animation event. + * + * @method Phaser.Animations.AnimationState#emitEvents + * @private + * @since 3.50.0 + * + * @param {string} event - The Animation Event to dispatch. + */ + emitEvents: function (event, keyEvent) + { + var anim = this.currentAnim; + + if (anim) + { + var frame = this.currentFrame; + + var gameObject = this.parent; + + var frameKey = frame.textureFrame; + + gameObject.emit(event, anim, frame, gameObject, frameKey); + + if (keyEvent) + { + gameObject.emit(keyEvent + anim.key, anim, frame, gameObject, frameKey); + } + } + }, + + /** + * Reverse the Animation that is already playing on the Game Object. + * + * @method Phaser.Animations.AnimationState#reverse + * @since 3.12.0 + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + reverse: function () + { + if (this.isPlaying) + { + this.inReverse = !this.inReverse; + + this.forward = !this.forward; + } + + return this.parent; + }, + + /** + * Returns a value between 0 and 1 indicating how far this animation is through, ignoring repeats and yoyos. + * + * The value is based on the current frame and how far that is in the animation, it is not based on + * the duration of the animation. + * + * @method Phaser.Animations.AnimationState#getProgress + * @since 3.4.0 + * + * @return {number} The progress of the current animation in frames, between 0 and 1. + */ + getProgress: function () + { + var frame = this.currentFrame; + + if (!frame) + { + return 0; + } + + var p = frame.progress; + + if (this.inReverse) + { + p *= -1; + } + + return p; + }, + + /** + * Takes a value between 0 and 1 and uses it to set how far this animation is through playback. + * + * Does not factor in repeats or yoyos, but does handle playing forwards or backwards. + * + * The value is based on the current frame and how far that is in the animation, it is not based on + * the duration of the animation. + * + * @method Phaser.Animations.AnimationState#setProgress + * @since 3.4.0 + * + * @param {number} [value=0] - The progress value, between 0 and 1. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + setProgress: function (value) + { + if (!this.forward) + { + value = 1 - value; + } + + this.setCurrentFrame(this.currentAnim.getFrameByProgress(value)); + + return this.parent; + }, + + /** + * Sets the number of times that the animation should repeat after its first play through. + * For example, if repeat is 1, the animation will play a total of twice: the initial play plus 1 repeat. + * + * To repeat indefinitely, use -1. + * The value should always be an integer. + * + * Calling this method only works if the animation is already running. Otherwise, any + * value specified here will be overwritten when the next animation loads in. To avoid this, + * use the `repeat` property of the `PlayAnimationConfig` object instead. + * + * @method Phaser.Animations.AnimationState#setRepeat + * @since 3.4.0 + * + * @param {number} value - The number of times that the animation should repeat. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + setRepeat: function (value) + { + this.repeatCounter = (value === -1) ? Number.MAX_VALUE : value; + + return this.parent; + }, + + /** + * Handle the removal of an animation from the Animation Manager. + * + * @method Phaser.Animations.AnimationState#globalRemove + * @since 3.50.0 + * + * @param {string} [key] - The key of the removed Animation. + * @param {Phaser.Animations.Animation} [animation] - The removed Animation. + */ + globalRemove: function (key, animation) + { + if (animation === undefined) { animation = this.currentAnim; } + + if (this.isPlaying && animation.key === this.currentAnim.key) + { + this.stop(); + + this.setCurrentFrame(this.currentAnim.frames[0]); + } + }, + + /** + * Restarts the current animation from its beginning. + * + * You can optionally reset the delay and repeat counters as well. + * + * Calling this will fire the `ANIMATION_RESTART` event immediately. + * + * If you `includeDelay` then it will also fire the `ANIMATION_START` event once + * the delay has expired, otherwise, playback will just begin immediately. + * + * @method Phaser.Animations.AnimationState#restart + * @fires Phaser.Animations.Events#ANIMATION_RESTART + * @since 3.0.0 + * + * @param {boolean} [includeDelay=false] - Whether to include the delay value of the animation when restarting. + * @param {boolean} [resetRepeats=false] - Whether to reset the repeat counter or not? + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + restart: function (includeDelay, resetRepeats) + { + if (includeDelay === undefined) { includeDelay = false; } + if (resetRepeats === undefined) { resetRepeats = false; } + + var anim = this.currentAnim; + var gameObject = this.parent; + + if (!anim) + { + return gameObject; + } + + if (resetRepeats) + { + this.repeatCounter = (this.repeat === -1) ? Number.MAX_VALUE : this.repeat; + } + + anim.getFirstTick(this); + + this.emitEvents(Events.ANIMATION_RESTART); + + this.isPlaying = true; + this.pendingRepeat = false; + + // Set this to `true` if there is no delay to include, so it skips the `hasStarted` check in `update`. + this.hasStarted = !includeDelay; + + this._pendingStop = 0; + this._pendingStopValue = 0; + this._paused = false; + + this.setCurrentFrame(anim.frames[0]); + + return this.parent; + }, + + /** + * The current animation has completed. This dispatches the `ANIMATION_COMPLETE` event. + * + * This method is called by the Animation instance and should not usually be invoked directly. + * + * If no animation is loaded, no events will be dispatched. + * + * If another animation has been queued for playback, it will be started after the events fire. + * + * @method Phaser.Animations.AnimationState#complete + * @fires Phaser.Animations.Events#ANIMATION_COMPLETE + * @since 3.50.0 + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + complete: function () + { + this._pendingStop = 0; + + this.isPlaying = false; + + if (this.currentAnim) + { + this.handleComplete(); + } + + if (this.nextAnim) + { + var key = this.nextAnim; + + this.nextAnim = (this.nextAnimsQueue.length > 0) ? this.nextAnimsQueue.shift() : null; + + this.play(key); + } + + return this.parent; + }, + + /** + * Immediately stops the current animation from playing and dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing. + * + * @method Phaser.Animations.AnimationState#stop + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.0.0 + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stop: function () + { + this._pendingStop = 0; + + this.isPlaying = false; + + this.delayCounter = 0; + + if (this.currentAnim) + { + this.handleStop(); + } + + if (this.nextAnim) + { + var key = this.nextAnim; + + this.nextAnim = this.nextAnimsQueue.shift(); + + this.play(key); + } + + return this.parent; + }, + + /** + * Stops the current animation from playing after the specified time delay, given in milliseconds. + * + * It then dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing, + * when the current one stops. + * + * @method Phaser.Animations.AnimationState#stopAfterDelay + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.4.0 + * + * @param {number} delay - The number of milliseconds to wait before stopping this animation. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stopAfterDelay: function (delay) + { + this._pendingStop = 1; + this._pendingStopValue = delay; + + return this.parent; + }, + + /** + * Stops the current animation from playing when it next repeats. + * + * It then dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing, + * when the current one stops. + * + * Prior to Phaser 3.50 this method was called `stopOnRepeat` and had no parameters. + * + * @method Phaser.Animations.AnimationState#stopAfterRepeat + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.50.0 + * + * @param {number} [repeatCount=1] - How many times should the animation repeat before stopping? + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stopAfterRepeat: function (repeatCount) + { + if (repeatCount === undefined) { repeatCount = 1; } + + if (this.repeatCounter !== -1 && repeatCount > this.repeatCounter) + { + repeatCount = this.repeatCounter; + } + + this._pendingStop = 2; + this._pendingStopValue = repeatCount; + + return this.parent; + }, + + /** + * Stops the current animation from playing when it next sets the given frame. + * If this frame doesn't exist within the animation it will not stop it from playing. + * + * It then dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing, + * when the current one stops. + * + * @method Phaser.Animations.AnimationState#stopOnFrame + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.4.0 + * + * @param {Phaser.Animations.AnimationFrame} frame - The frame to check before stopping this animation. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stopOnFrame: function (frame) + { + this._pendingStop = 3; + this._pendingStopValue = frame; + + return this.parent; + }, + + /** + * Returns the total number of frames in this animation, or returns zero if no + * animation has been loaded. + * + * @method Phaser.Animations.AnimationState#getTotalFrames + * @since 3.4.0 + * + * @return {number} The total number of frames in the current animation, or zero if no animation has been loaded. + */ + getTotalFrames: function () + { + return (this.currentAnim) ? this.currentAnim.getTotalFrames() : 0; + }, + + /** + * The internal update loop for the AnimationState Component. + * + * This is called automatically by the `Sprite.preUpdate` method. + * + * @method Phaser.Animations.AnimationState#update + * @since 3.0.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + var anim = this.currentAnim; + + if (!this.isPlaying || !anim || anim.paused) + { + return; + } + + this.accumulator += delta * this.timeScale * this.animationManager.globalTimeScale; + + if (this._pendingStop === 1) + { + this._pendingStopValue -= delta; + + if (this._pendingStopValue <= 0) + { + return this.stop(); + } + } + + if (!this.hasStarted) + { + if (this.accumulator >= this.delayCounter) + { + this.accumulator -= this.delayCounter; + + this.handleStart(); + } + } + else if (this.accumulator >= this.nextTick) + { + // Process one frame advance as standard + + if (this.forward) + { + anim.nextFrame(this); + } + else + { + anim.previousFrame(this); + } + + // And only do more if we're skipping frames and have time left + if (this.isPlaying && this._pendingStop === 0 && this.skipMissedFrames && this.accumulator > this.nextTick) + { + var safetyNet = 0; + + do + { + if (this.forward) + { + anim.nextFrame(this); + } + else + { + anim.previousFrame(this); + } + + safetyNet++; + + } while (this.isPlaying && this.accumulator > this.nextTick && safetyNet < 60); + } + } + }, + + /** + * Sets the given Animation Frame as being the current frame + * and applies it to the parent Game Object, adjusting size and origin as needed. + * + * @method Phaser.Animations.AnimationState#setCurrentFrame + * @fires Phaser.Animations.Events#ANIMATION_UPDATE + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.4.0 + * + * @param {Phaser.Animations.AnimationFrame} animationFrame - The animation frame to change to. + * + * @return {Phaser.GameObjects.GameObject} The Game Object this Animation Component belongs to. + */ + setCurrentFrame: function (animationFrame) + { + var gameObject = this.parent; + + this.currentFrame = animationFrame; + + gameObject.texture = animationFrame.frame.texture; + gameObject.frame = animationFrame.frame; + + if (gameObject.isCropped) + { + gameObject.frame.updateCropUVs(gameObject._crop, gameObject.flipX, gameObject.flipY); + } + + if (animationFrame.setAlpha) + { + gameObject.alpha = animationFrame.alpha; + } + + gameObject.setSizeToFrame(); + + if (gameObject._originComponent) + { + if (animationFrame.frame.customPivot) + { + gameObject.setOrigin(animationFrame.frame.pivotX, animationFrame.frame.pivotY); + } + else + { + gameObject.updateDisplayOrigin(); + } + } + + if (this.isPlaying && this.hasStarted) + { + this.emitEvents(Events.ANIMATION_UPDATE); + + if (this._pendingStop === 3 && this._pendingStopValue === animationFrame) + { + this.stop(); + } + } + + return gameObject; + }, + + /** + * Advances the animation to the next frame, regardless of the time or animation state. + * If the animation is set to repeat, or yoyo, this will still take effect. + * + * Calling this does not change the direction of the animation. I.e. if it was currently + * playing in reverse, calling this method doesn't then change the direction to forwards. + * + * @method Phaser.Animations.AnimationState#nextFrame + * @since 3.16.0 + * + * @return {Phaser.GameObjects.GameObject} The Game Object this Animation Component belongs to. + */ + nextFrame: function () + { + if (this.currentAnim) + { + this.currentAnim.nextFrame(this); + } + + return this.parent; + }, + + /** + * Advances the animation to the previous frame, regardless of the time or animation state. + * If the animation is set to repeat, or yoyo, this will still take effect. + * + * Calling this does not change the direction of the animation. I.e. if it was currently + * playing in forwards, calling this method doesn't then change the direction to backwards. + * + * @method Phaser.Animations.AnimationState#previousFrame + * @since 3.16.0 + * + * @return {Phaser.GameObjects.GameObject} The Game Object this Animation Component belongs to. + */ + previousFrame: function () + { + if (this.currentAnim) + { + this.currentAnim.previousFrame(this); + } + + return this.parent; + }, + + /** + * Get an Animation instance that has been created locally on this Sprite. + * + * See the `create` method for more details. + * + * @method Phaser.Animations.AnimationState#get + * @since 3.50.0 + * + * @param {string} key - The key of the Animation to retrieve. + * + * @return {Phaser.Animations.Animation} The Animation, or `null` if the key is invalid. + */ + get: function (key) + { + return (this.anims) ? this.anims.get(key) : null; + }, + + /** + * Checks to see if the given key is already used locally within the animations stored on this Sprite. + * + * @method Phaser.Animations.AnimationState#exists + * @since 3.50.0 + * + * @param {string} key - The key of the Animation to check. + * + * @return {boolean} `true` if the Animation exists locally, or `false` if the key is available, or there are no local animations. + */ + exists: function (key) + { + return (this.anims) ? this.anims.has(key) : false; + }, + + /** + * Creates a new Animation that is local specifically to this Sprite. + * + * When a Sprite owns an animation, it is kept out of the global Animation Manager, which means + * you're free to use keys that may be already defined there. Unless you specifically need a Sprite + * to have a unique animation, you should favor using global animations instead, as they allow for + * the same animation to be used across multiple Sprites, saving on memory. However, if this Sprite + * is the only one to use this animation, it's sensible to create it here. + * + * If an invalid key is given this method will return `false`. + * + * If you pass the key of an animation that already exists locally, that animation will be returned. + * + * A brand new animation is only created if the key is valid and not already in use by this Sprite. + * + * If you wish to re-use an existing key, call the `remove` method first, then this method. + * + * @method Phaser.Animations.AnimationState#create + * @since 3.50.0 + * + * @param {Phaser.Types.Animations.Animation} config - The configuration settings for the Animation. + * + * @return {(Phaser.Animations.Animation|false)} The Animation that was created, or `false` if the key is already in use. + */ + create: function (config) + { + var key = config.key; + + var anim = false; + + if (key) + { + anim = this.get(key); + + if (!anim) + { + anim = new Animation(this, key, config); + + if (!this.anims) + { + this.anims = new CustomMap(); + } + + this.anims.set(key, anim); + } + else + { + console.warn('Animation key already exists: ' + key); + } + } + + return anim; + }, + + /** + * Create one, or more animations from a loaded Aseprite JSON file. + * + * Aseprite is a powerful animated sprite editor and pixel art tool. + * + * You can find more details at https://www.aseprite.org/ + * + * To export a compatible JSON file in Aseprite, please do the following: + * + * 1. Go to "File - Export Sprite Sheet" + * + * 2. On the **Layout** tab: + * 2a. Set the "Sheet type" to "Packed" + * 2b. Set the "Constraints" to "None" + * 2c. Check the "Merge Duplicates" checkbox + * + * 3. On the **Sprite** tab: + * 3a. Set "Layers" to "Visible layers" + * 3b. Set "Frames" to "All frames", unless you only wish to export a sub-set of tags + * + * 4. On the **Borders** tab: + * 4a. Check the "Trim Sprite" and "Trim Cells" options + * 4b. Ensure "Border Padding", "Spacing" and "Inner Padding" are all > 0 (1 is usually enough) + * + * 5. On the **Output** tab: + * 5a. Check "Output File", give your image a name and make sure you choose "png files" as the file type + * 5b. Check "JSON Data" and give your json file a name + * 5c. The JSON Data type can be either a Hash or Array, Phaser doesn't mind. + * 5d. Make sure "Tags" is checked in the Meta options + * 5e. In the "Item Filename" input box, make sure it says just "{frame}" and nothing more. + * + * 6. Click export + * + * This was tested with Aseprite 1.2.25. + * + * This will export a png and json file which you can load using the Aseprite Loader, i.e.: + * + * ```javascript + * function preload () + * { + * this.load.path = 'assets/animations/aseprite/'; + * this.load.aseprite('paladin', 'paladin.png', 'paladin.json'); + * } + * ``` + * + * Once loaded, you can call this method on a Sprite with the 'atlas' key: + * + * ```javascript + * const sprite = this.add.sprite(400, 300); + * + * sprite.anims.createFromAseprite('paladin'); + * ``` + * + * Any animations defined in the JSON will now be available to use on this Sprite and you play them + * via their Tag name. For example, if you have an animation called 'War Cry' on your Aseprite timeline, + * you can play it on the Sprite using that Tag name: + * + * ```javascript + * const sprite = this.add.sprite(400, 300); + * + * sprite.anims.createFromAseprite('paladin'); + * + * sprite.play('War Cry'); + * ``` + * + * When calling this method you can optionally provide an array of tag names, and only those animations + * will be created. For example: + * + * ```javascript + * sprite.anims.createFromAseprite('paladin', [ 'step', 'War Cry', 'Magnum Break' ]); + * ``` + * + * This will only create the 3 animations defined. Note that the tag names are case-sensitive. + * + * @method Phaser.Animations.AnimationState#createFromAseprite + * @since 3.60.0 + * + * @param {string} key - The key of the loaded Aseprite atlas. It must have been loaded prior to calling this method. + * @param {string[]} [tags] - An array of Tag names. If provided, only animations found in this array will be created. + * + * @return {Phaser.Animations.Animation[]} An array of Animation instances that were successfully created. + */ + createFromAseprite: function (key, tags) + { + return this.animationManager.createFromAseprite(key, tags, this.parent); + }, + + /** + * Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object. + * + * Generates objects with string based frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNames}. + * + * It's a helper method, designed to make it easier for you to extract all of the frame names from texture atlases. + * If you're working with a sprite sheet, see the `generateFrameNumbers` method instead. + * + * Example: + * + * If you have a texture atlases loaded called `gems` and it contains 6 frames called `ruby_0001`, `ruby_0002`, and so on, + * then you can call this method using: `this.anims.generateFrameNames('gems', { prefix: 'ruby_', end: 6, zeroPad: 4 })`. + * + * The `end` value tells it to look for 6 frames, incrementally numbered, all starting with the prefix `ruby_`. The `zeroPad` + * value tells it how many zeroes pad out the numbers. To create an animation using this method, you can do: + * + * ```javascript + * this.anims.create({ + * key: 'ruby', + * repeat: -1, + * frames: this.anims.generateFrameNames('gems', { + * prefix: 'ruby_', + * end: 6, + * zeroPad: 4 + * }) + * }); + * ``` + * + * Please see the animation examples for further details. + * + * @method Phaser.Animations.AnimationState#generateFrameNames + * @since 3.50.0 + * + * @param {string} key - The key for the texture containing the animation frames. + * @param {Phaser.Types.Animations.GenerateFrameNames} [config] - The configuration object for the animation frame names. + * + * @return {Phaser.Types.Animations.AnimationFrame[]} The array of {@link Phaser.Types.Animations.AnimationFrame} objects. + */ + generateFrameNames: function (key, config) + { + return this.animationManager.generateFrameNames(key, config); + }, + + /** + * Generate an array of {@link Phaser.Types.Animations.AnimationFrame} objects from a texture key and configuration object. + * + * Generates objects with numbered frame names, as configured by the given {@link Phaser.Types.Animations.GenerateFrameNumbers}. + * + * If you're working with a texture atlas, see the `generateFrameNames` method instead. + * + * It's a helper method, designed to make it easier for you to extract frames from sprite sheets. + * If you're working with a texture atlas, see the `generateFrameNames` method instead. + * + * Example: + * + * If you have a sprite sheet loaded called `explosion` and it contains 12 frames, then you can call this method using: + * `this.anims.generateFrameNumbers('explosion', { start: 0, end: 11 })`. + * + * The `end` value tells it to stop after 12 frames. To create an animation using this method, you can do: + * + * ```javascript + * this.anims.create({ + * key: 'boom', + * frames: this.anims.generateFrameNumbers('explosion', { + * start: 0, + * end: 11 + * }) + * }); + * ``` + * + * Note that `start` is optional and you don't need to include it if the animation starts from frame 0. + * + * To specify an animation in reverse, swap the `start` and `end` values. + * + * If the frames are not sequential, you may pass an array of frame numbers instead, for example: + * + * `this.anims.generateFrameNumbers('explosion', { frames: [ 0, 1, 2, 1, 2, 3, 4, 0, 1, 2 ] })` + * + * Please see the animation examples and `GenerateFrameNumbers` config docs for further details. + * + * @method Phaser.Animations.AnimationState#generateFrameNumbers + * @since 3.50.0 + * + * @param {string} key - The key for the texture containing the animation frames. + * @param {Phaser.Types.Animations.GenerateFrameNumbers} [config] - The configuration object for the animation frames. + * + * @return {Phaser.Types.Animations.AnimationFrame[]} The array of {@link Phaser.Types.Animations.AnimationFrame} objects. + */ + generateFrameNumbers: function (key, config) + { + return this.animationManager.generateFrameNumbers(key, config); + }, + + /** + * Removes a locally created Animation from this Sprite, based on the given key. + * + * Once an Animation has been removed, this Sprite cannot play it again without re-creating it. + * + * @method Phaser.Animations.AnimationState#remove + * @since 3.50.0 + * + * @param {string} key - The key of the animation to remove. + * + * @return {Phaser.Animations.Animation} The Animation instance that was removed from this Sprite, if the key was valid. + */ + remove: function (key) + { + var anim = this.get(key); + + if (anim) + { + if (this.currentAnim === anim) + { + this.stop(); + } + + this.anims.delete(key); + } + + return anim; + }, + + /** + * Destroy this Animation component. + * + * Unregisters event listeners and cleans up its references. + * + * @method Phaser.Animations.AnimationState#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.animationManager.off(Events.REMOVE_ANIMATION, this.globalRemove, this); + + if (this.anims) + { + this.anims.clear(); + } + + this.animationManager = null; + this.parent = null; + this.nextAnim = null; + this.nextAnimsQueue.length = 0; + + this.currentAnim = null; + this.currentFrame = null; + }, + + /** + * `true` if the current animation is paused, otherwise `false`. + * + * @name Phaser.Animations.AnimationState#isPaused + * @readonly + * @type {boolean} + * @since 3.4.0 + */ + isPaused: { + + get: function () + { + return this._paused; + } + + } + +}); + +module.exports = AnimationState; + + +/***/ }), + +/***/ 57090: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Add Animation Event. + * + * This event is dispatched when a new animation is added to the global Animation Manager. + * + * This can happen either as a result of an animation instance being added to the Animation Manager, + * or the Animation Manager creating a new animation directly. + * + * @event Phaser.Animations.Events#ADD_ANIMATION + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the Animation that was added to the global Animation Manager. + * @param {Phaser.Animations.Animation} animation - An instance of the newly created Animation. + */ +module.exports = 'add'; + + +/***/ }), + +/***/ 25312: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Complete Event. + * + * This event is dispatched by a Sprite when an animation playing on it completes playback. + * This happens when the animation gets to the end of its sequence, factoring in any delays + * or repeats it may have to process. + * + * An animation that is set to loop, or repeat forever, will never fire this event, because + * it never actually completes. If you need to handle this, listen for the `ANIMATION_STOP` + * event instead, as this is emitted when the animation is stopped directly. + * + * Listen for it on the Sprite using `sprite.on('animationcomplete', listener)` + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_COMPLETE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationcomplete'; + + +/***/ }), + +/***/ 89580: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Complete Dynamic Key Event. + * + * This event is dispatched by a Sprite when an animation playing on it completes playback. + * This happens when the animation gets to the end of its sequence, factoring in any delays + * or repeats it may have to process. + * + * An animation that is set to loop, or repeat forever, will never fire this event, because + * it never actually completes. If you need to handle this, listen for the `ANIMATION_STOP` + * event instead, as this is emitted when the animation is stopped directly. + * + * The difference between this and the `ANIMATION_COMPLETE` event is that this one has a + * dynamic event name that contains the name of the animation within it. For example, + * if you had an animation called `explode` you could listen for the completion of that + * specific animation by using: `sprite.on('animationcomplete-explode', listener)`. Or, if you + * wish to use types: `sprite.on(Phaser.Animations.Events.ANIMATION_COMPLETE_KEY + 'explode', listener)`. + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_COMPLETE_KEY + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that completed. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationcomplete-'; + + +/***/ }), + +/***/ 52860: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Repeat Event. + * + * This event is dispatched by a Sprite when an animation repeats playing on it. + * This happens if the animation was created, or played, with a `repeat` value specified. + * + * An animation will repeat when it reaches the end of its sequence. + * + * Listen for it on the Sprite using `sprite.on('animationrepeat', listener)` + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_REPEAT + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that has repeated. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation repeated. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationrepeat'; + + +/***/ }), + +/***/ 63850: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Restart Event. + * + * This event is dispatched by a Sprite when an animation restarts playing on it. + * This only happens when the `Sprite.anims.restart` method is called. + * + * Listen for it on the Sprite using `sprite.on('animationrestart', listener)` + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_RESTART + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that has restarted. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation restarted. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationrestart'; + + +/***/ }), + +/***/ 99085: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Start Event. + * + * This event is dispatched by a Sprite when an animation starts playing on it. + * This happens when the animation is played, factoring in any delay that may have been specified. + * This event happens after the delay has expired and prior to the first update event. + * + * Listen for it on the Sprite using `sprite.on('animationstart', listener)` + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_START + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that has started. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation started. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationstart'; + + +/***/ }), + +/***/ 28087: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Stop Event. + * + * This event is dispatched by a Sprite when an animation is stopped on it. An animation + * will only be stopeed if a method such as `Sprite.stop` or `Sprite.anims.stopAfterDelay` + * is called. It can also be emitted if a new animation is started before the current one completes. + * + * Listen for it on the Sprite using `sprite.on('animationstop', listener)` + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_STOP + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that has stopped. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation stopped. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationstop'; + + +/***/ }), + +/***/ 1794: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Animation Update Event. + * + * This event is dispatched by a Sprite when an animation playing on it updates. This happens when the animation changes frame. + * An animation will change frame based on the frame rate and other factors like `timeScale` and `delay`. It can also change + * frame when stopped or restarted. + * + * Listen for it on the Sprite using `sprite.on('animationupdate', listener)` + * + * If an animation is playing faster than the game frame-rate can handle, it's entirely possible for it to emit several + * update events in a single game frame, so please be aware of this in your code. The **final** event received that frame + * is the one that is rendered to the game. + * + * The animation event flow is as follows: + * + * 1. `ANIMATION_START` + * 2. `ANIMATION_UPDATE` (repeated for however many frames the animation has) + * 3. `ANIMATION_REPEAT` (only if the animation is set to repeat, it then emits more update events after this) + * 4. `ANIMATION_COMPLETE` (only if there is a finite, or zero, repeat count) + * 5. `ANIMATION_COMPLETE_KEY` (only if there is a finite, or zero, repeat count) + * + * If the animation is stopped directly, the `ANIMATION_STOP` event is dispatched instead of `ANIMATION_COMPLETE`. + * + * If the animation is restarted while it is already playing, `ANIMATION_RESTART` is emitted. + * + * @event Phaser.Animations.Events#ANIMATION_UPDATE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Animations.Animation} animation - A reference to the Animation that has updated. + * @param {Phaser.Animations.AnimationFrame} frame - The current Animation Frame of the Animation. + * @param {Phaser.GameObjects.Sprite} gameObject - A reference to the Game Object on which the animation updated. + * @param {string} frameKey - The unique key of the Animation Frame within the Animation. + */ +module.exports = 'animationupdate'; + + +/***/ }), + +/***/ 52562: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pause All Animations Event. + * + * This event is dispatched when the global Animation Manager is told to pause. + * + * When this happens all current animations will stop updating, although it doesn't necessarily mean + * that the game has paused as well. + * + * @event Phaser.Animations.Events#PAUSE_ALL + * @type {string} + * @since 3.0.0 + */ +module.exports = 'pauseall'; + + +/***/ }), + +/***/ 57953: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Remove Animation Event. + * + * This event is dispatched when an animation is removed from the global Animation Manager. + * + * @event Phaser.Animations.Events#REMOVE_ANIMATION + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the Animation that was removed from the global Animation Manager. + * @param {Phaser.Animations.Animation} animation - An instance of the removed Animation. + */ +module.exports = 'remove'; + + +/***/ }), + +/***/ 68339: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Resume All Animations Event. + * + * This event is dispatched when the global Animation Manager resumes, having been previously paused. + * + * When this happens all current animations will continue updating again. + * + * @event Phaser.Animations.Events#RESUME_ALL + * @type {string} + * @since 3.0.0 + */ +module.exports = 'resumeall'; + + +/***/ }), + +/***/ 74943: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Animations.Events + */ + +module.exports = { + + ADD_ANIMATION: __webpack_require__(57090), + ANIMATION_COMPLETE: __webpack_require__(25312), + ANIMATION_COMPLETE_KEY: __webpack_require__(89580), + ANIMATION_REPEAT: __webpack_require__(52860), + ANIMATION_RESTART: __webpack_require__(63850), + ANIMATION_START: __webpack_require__(99085), + ANIMATION_STOP: __webpack_require__(28087), + ANIMATION_UPDATE: __webpack_require__(1794), + PAUSE_ALL: __webpack_require__(52562), + REMOVE_ANIMATION: __webpack_require__(57953), + RESUME_ALL: __webpack_require__(68339) + +}; + + +/***/ }), + +/***/ 60421: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Animations + */ + +module.exports = { + + Animation: __webpack_require__(42099), + AnimationFrame: __webpack_require__(41138), + AnimationManager: __webpack_require__(60848), + AnimationState: __webpack_require__(9674), + Events: __webpack_require__(74943) + +}; + + +/***/ }), + +/***/ 2161: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CustomMap = __webpack_require__(90330); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(24736); + +/** + * @classdesc + * The BaseCache is a base Cache class that can be used for storing references to any kind of data. + * + * Data can be added, retrieved and removed based on the given keys. + * + * Keys are string-based. + * + * @class BaseCache + * @memberof Phaser.Cache + * @constructor + * @since 3.0.0 + */ +var BaseCache = new Class({ + + initialize: + + function BaseCache () + { + /** + * The Map in which the cache objects are stored. + * + * You can query the Map directly or use the BaseCache methods. + * + * @name Phaser.Cache.BaseCache#entries + * @type {Phaser.Structs.Map.} + * @since 3.0.0 + */ + this.entries = new CustomMap(); + + /** + * An instance of EventEmitter used by the cache to emit related events. + * + * @name Phaser.Cache.BaseCache#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events = new EventEmitter(); + }, + + /** + * Adds an item to this cache. The item is referenced by a unique string, which you are responsible + * for setting and keeping track of. The item can only be retrieved by using this string. + * + * @method Phaser.Cache.BaseCache#add + * @fires Phaser.Cache.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique key by which the data added to the cache will be referenced. + * @param {*} data - The data to be stored in the cache. + * + * @return {this} This BaseCache object. + */ + add: function (key, data) + { + this.entries.set(key, data); + + this.events.emit(Events.ADD, this, key, data); + + return this; + }, + + /** + * Checks if this cache contains an item matching the given key. + * This performs the same action as `BaseCache.exists`. + * + * @method Phaser.Cache.BaseCache#has + * @since 3.0.0 + * + * @param {string} key - The unique key of the item to be checked in this cache. + * + * @return {boolean} Returns `true` if the cache contains an item matching the given key, otherwise `false`. + */ + has: function (key) + { + return this.entries.has(key); + }, + + /** + * Checks if this cache contains an item matching the given key. + * This performs the same action as `BaseCache.has` and is called directly by the Loader. + * + * @method Phaser.Cache.BaseCache#exists + * @since 3.7.0 + * + * @param {string} key - The unique key of the item to be checked in this cache. + * + * @return {boolean} Returns `true` if the cache contains an item matching the given key, otherwise `false`. + */ + exists: function (key) + { + return this.entries.has(key); + }, + + /** + * Gets an item from this cache based on the given key. + * + * @method Phaser.Cache.BaseCache#get + * @since 3.0.0 + * + * @param {string} key - The unique key of the item to be retrieved from this cache. + * + * @return {*} The item in the cache, or `null` if no item matching the given key was found. + */ + get: function (key) + { + return this.entries.get(key); + }, + + /** + * Removes and item from this cache based on the given key. + * + * If an entry matching the key is found it is removed from the cache and a `remove` event emitted. + * No additional checks are done on the item removed. If other systems or parts of your game code + * are relying on this item, it is up to you to sever those relationships prior to removing the item. + * + * @method Phaser.Cache.BaseCache#remove + * @fires Phaser.Cache.Events#REMOVE + * @since 3.0.0 + * + * @param {string} key - The unique key of the item to remove from the cache. + * + * @return {this} This BaseCache object. + */ + remove: function (key) + { + var entry = this.get(key); + + if (entry) + { + this.entries.delete(key); + + this.events.emit(Events.REMOVE, this, key, entry.data); + } + + return this; + }, + + /** + * Returns all keys in use in this cache. + * + * @method Phaser.Cache.BaseCache#getKeys + * @since 3.17.0 + * + * @return {string[]} Array containing all the keys. + */ + getKeys: function () + { + return this.entries.keys(); + }, + + /** + * Destroys this cache and all items within it. + * + * @method Phaser.Cache.BaseCache#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.entries.clear(); + this.events.removeAllListeners(); + + this.entries = null; + this.events = null; + } + +}); + +module.exports = BaseCache; + + +/***/ }), + +/***/ 24047: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseCache = __webpack_require__(2161); +var Class = __webpack_require__(83419); +var GameEvents = __webpack_require__(8443); + +/** + * @classdesc + * The Cache Manager is the global cache owned and maintained by the Game instance. + * + * Various systems, such as the file Loader, rely on this cache in order to store the files + * it has loaded. The manager itself doesn't store any files, but instead owns multiple BaseCache + * instances, one per type of file. You can also add your own custom caches. + * + * @class CacheManager + * @memberof Phaser.Cache + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - A reference to the Phaser.Game instance that owns this CacheManager. + */ +var CacheManager = new Class({ + + initialize: + + function CacheManager (game) + { + /** + * A reference to the Phaser.Game instance that owns this CacheManager. + * + * @name Phaser.Cache.CacheManager#game + * @type {Phaser.Game} + * @protected + * @since 3.0.0 + */ + this.game = game; + + /** + * A Cache storing all binary files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#binary + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.binary = new BaseCache(); + + /** + * A Cache storing all bitmap font data files, typically added via the Loader. + * Only the font data is stored in this cache, the textures are part of the Texture Manager. + * + * @name Phaser.Cache.CacheManager#bitmapFont + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.bitmapFont = new BaseCache(); + + /** + * A Cache storing all JSON data files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#json + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.json = new BaseCache(); + + /** + * A Cache storing all physics data files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#physics + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.physics = new BaseCache(); + + /** + * A Cache storing all shader source files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#shader + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.shader = new BaseCache(); + + /** + * A Cache storing all non-streaming audio files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#audio + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.audio = new BaseCache(); + + /** + * A Cache storing all non-streaming video files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#video + * @type {Phaser.Cache.BaseCache} + * @since 3.20.0 + */ + this.video = new BaseCache(); + + /** + * A Cache storing all text files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#text + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.text = new BaseCache(); + + /** + * A Cache storing all html files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#html + * @type {Phaser.Cache.BaseCache} + * @since 3.12.0 + */ + this.html = new BaseCache(); + + /** + * A Cache storing all WaveFront OBJ files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#obj + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.obj = new BaseCache(); + + /** + * A Cache storing all tilemap data files, typically added via the Loader. + * Only the data is stored in this cache, the textures are part of the Texture Manager. + * + * @name Phaser.Cache.CacheManager#tilemap + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.tilemap = new BaseCache(); + + /** + * A Cache storing all xml data files, typically added via the Loader. + * + * @name Phaser.Cache.CacheManager#xml + * @type {Phaser.Cache.BaseCache} + * @since 3.0.0 + */ + this.xml = new BaseCache(); + + /** + * An object that contains your own custom BaseCache entries. + * Add to this via the `addCustom` method. + * + * @name Phaser.Cache.CacheManager#custom + * @type {Object.} + * @since 3.0.0 + */ + this.custom = {}; + + this.game.events.once(GameEvents.DESTROY, this.destroy, this); + }, + + /** + * Add your own custom Cache for storing your own files. + * The cache will be available under `Cache.custom.key`. + * The cache will only be created if the key is not already in use. + * + * @method Phaser.Cache.CacheManager#addCustom + * @since 3.0.0 + * + * @param {string} key - The unique key of your custom cache. + * + * @return {Phaser.Cache.BaseCache} A reference to the BaseCache that was created. If the key was already in use, a reference to the existing cache is returned instead. + */ + addCustom: function (key) + { + if (!this.custom.hasOwnProperty(key)) + { + this.custom[key] = new BaseCache(); + } + + return this.custom[key]; + }, + + /** + * Removes all entries from all BaseCaches and destroys all custom caches. + * + * @method Phaser.Cache.CacheManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + var keys = [ + 'binary', + 'bitmapFont', + 'json', + 'physics', + 'shader', + 'audio', + 'video', + 'text', + 'html', + 'obj', + 'tilemap', + 'xml' + ]; + + for (var i = 0; i < keys.length; i++) + { + this[keys[i]].destroy(); + this[keys[i]] = null; + } + + for (var key in this.custom) + { + this.custom[key].destroy(); + } + + this.custom = null; + + this.game = null; + } + +}); + +module.exports = CacheManager; + + +/***/ }), + +/***/ 51464: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Cache Add Event. + * + * This event is dispatched by any Cache that extends the BaseCache each time a new object is added to it. + * + * @event Phaser.Cache.Events#ADD + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Cache.BaseCache} cache - The cache to which the object was added. + * @param {string} key - The key of the object added to the cache. + * @param {*} object - A reference to the object that was added to the cache. + */ +module.exports = 'add'; + + +/***/ }), + +/***/ 59261: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Cache Remove Event. + * + * This event is dispatched by any Cache that extends the BaseCache each time an object is removed from it. + * + * @event Phaser.Cache.Events#REMOVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Cache.BaseCache} cache - The cache from which the object was removed. + * @param {string} key - The key of the object removed from the cache. + * @param {*} object - A reference to the object that was removed from the cache. + */ +module.exports = 'remove'; + + +/***/ }), + +/***/ 24736: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cache.Events + */ + +module.exports = { + + ADD: __webpack_require__(51464), + REMOVE: __webpack_require__(59261) + +}; + + +/***/ }), + +/***/ 83388: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cache + */ + +module.exports = { + + BaseCache: __webpack_require__(2161), + CacheManager: __webpack_require__(24047), + Events: __webpack_require__(24736) + +}; + + +/***/ }), + +/***/ 71911: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var DegToRad = __webpack_require__(39506); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(19715); +var Rectangle = __webpack_require__(87841); +var TransformMatrix = __webpack_require__(61340); +var ValueToColor = __webpack_require__(80333); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Base Camera class. + * + * The Camera is the way in which all games are rendered in Phaser. They provide a view into your game world, + * and can be positioned, rotated, zoomed and scrolled accordingly. + * + * A Camera consists of two elements: The viewport and the scroll values. + * + * The viewport is the physical position and size of the Camera within your game. Cameras, by default, are + * created the same size as your game, but their position and size can be set to anything. This means if you + * wanted to create a camera that was 320x200 in size, positioned in the bottom-right corner of your game, + * you'd adjust the viewport to do that (using methods like `setViewport` and `setSize`). + * + * If you wish to change where the Camera is looking in your game, then you scroll it. You can do this + * via the properties `scrollX` and `scrollY` or the method `setScroll`. Scrolling has no impact on the + * viewport, and changing the viewport has no impact on the scrolling. + * + * By default a Camera will render all Game Objects it can see. You can change this using the `ignore` method, + * allowing you to filter Game Objects out on a per-Camera basis. + * + * The Base Camera is extended by the Camera class, which adds in special effects including Fade, + * Flash and Camera Shake, as well as the ability to follow Game Objects. + * + * The Base Camera was introduced in Phaser 3.12. It was split off from the Camera class, to allow + * you to isolate special effects as needed. Therefore the 'since' values for properties of this class relate + * to when they were added to the Camera class. + * + * @class BaseCamera + * @memberof Phaser.Cameras.Scene2D + * @constructor + * @since 3.12.0 + * + * @extends Phaser.Events.EventEmitter + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.Visible + * + * @param {number} x - The x position of the Camera, relative to the top-left of the game canvas. + * @param {number} y - The y position of the Camera, relative to the top-left of the game canvas. + * @param {number} width - The width of the Camera, in pixels. + * @param {number} height - The height of the Camera, in pixels. + */ +var BaseCamera = new Class({ + + Extends: EventEmitter, + + Mixins: [ + Components.AlphaSingle, + Components.Visible + ], + + initialize: + + function BaseCamera (x, y, width, height) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 0; } + if (height === undefined) { height = 0; } + + EventEmitter.call(this); + + /** + * A reference to the Scene this camera belongs to. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene; + + /** + * A reference to the Game Scene Manager. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#sceneManager + * @type {Phaser.Scenes.SceneManager} + * @since 3.12.0 + */ + this.sceneManager; + + /** + * A reference to the Game Scale Manager. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#scaleManager + * @type {Phaser.Scale.ScaleManager} + * @since 3.16.0 + */ + this.scaleManager; + + /** + * A reference to the Scene's Camera Manager to which this Camera belongs. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#cameraManager + * @type {Phaser.Cameras.Scene2D.CameraManager} + * @since 3.17.0 + */ + this.cameraManager; + + /** + * The Camera ID. Assigned by the Camera Manager and used to handle camera exclusion. + * This value is a bitmask. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#id + * @type {number} + * @readonly + * @since 3.11.0 + */ + this.id = 0; + + /** + * The name of the Camera. This is left empty for your own use. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#name + * @type {string} + * @default '' + * @since 3.0.0 + */ + this.name = ''; + + /** + * Should this camera round its pixel values to integers? + * + * @name Phaser.Cameras.Scene2D.BaseCamera#roundPixels + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.roundPixels = false; + + /** + * Is this Camera visible or not? + * + * A visible camera will render and perform input tests. + * An invisible camera will not render anything and will skip input tests. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#visible + * @type {boolean} + * @default true + * @since 3.10.0 + */ + + /** + * Is this Camera using a bounds to restrict scrolling movement? + * + * Set this property along with the bounds via `Camera.setBounds`. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#useBounds + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.useBounds = false; + + /** + * The World View is a Rectangle that defines the area of the 'world' the Camera is currently looking at. + * This factors in the Camera viewport size, zoom and scroll position and is updated in the Camera preRender step. + * If you have enabled Camera bounds the worldview will be clamped to those bounds accordingly. + * You can use it for culling or intersection checks. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#worldView + * @type {Phaser.Geom.Rectangle} + * @readonly + * @since 3.11.0 + */ + this.worldView = new Rectangle(); + + /** + * Is this Camera dirty? + * + * A dirty Camera has had either its viewport size, bounds, scroll, rotation or zoom levels changed since the last frame. + * + * This flag is cleared during rendering with the new values. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#dirty + * @type {boolean} + * @default true + * @since 3.11.0 + */ + this.dirty = true; + + /** + * The x position of the Camera viewport, relative to the top-left of the game canvas. + * The viewport is the area into which the camera renders. + * To adjust the position the camera is looking at in the game world, see the `scrollX` value. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_x + * @type {number} + * @private + * @since 3.0.0 + */ + this._x = x; + + /** + * The y position of the Camera, relative to the top-left of the game canvas. + * The viewport is the area into which the camera renders. + * To adjust the position the camera is looking at in the game world, see the `scrollY` value. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_y + * @type {number} + * @private + * @since 3.0.0 + */ + this._y = y; + + /** + * The width of the Camera viewport, in pixels. + * + * The viewport is the area into which the Camera renders. Setting the viewport does + * not restrict where the Camera can scroll to. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_width + * @type {number} + * @private + * @since 3.11.0 + */ + this._width = width; + + /** + * The height of the Camera viewport, in pixels. + * + * The viewport is the area into which the Camera renders. Setting the viewport does + * not restrict where the Camera can scroll to. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_height + * @type {number} + * @private + * @since 3.11.0 + */ + this._height = height; + + /** + * The bounds the camera is restrained to during scrolling. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_bounds + * @type {Phaser.Geom.Rectangle} + * @private + * @since 3.0.0 + */ + this._bounds = new Rectangle(); + + /** + * The horizontal scroll position of this Camera. + * + * Change this value to cause the Camera to scroll around your Scene. + * + * Alternatively, setting the Camera to follow a Game Object, via the `startFollow` method, + * will automatically adjust the Camera scroll values accordingly. + * + * You can set the bounds within which the Camera can scroll via the `setBounds` method. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_scrollX + * @type {number} + * @private + * @default 0 + * @since 3.11.0 + */ + this._scrollX = 0; + + /** + * The vertical scroll position of this Camera. + * + * Change this value to cause the Camera to scroll around your Scene. + * + * Alternatively, setting the Camera to follow a Game Object, via the `startFollow` method, + * will automatically adjust the Camera scroll values accordingly. + * + * You can set the bounds within which the Camera can scroll via the `setBounds` method. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_scrollY + * @type {number} + * @private + * @default 0 + * @since 3.11.0 + */ + this._scrollY = 0; + + /** + * The Camera horizontal zoom value. Change this value to zoom in, or out of, a Scene. + * + * A value of 0.5 would zoom the Camera out, so you can now see twice as much + * of the Scene as before. A value of 2 would zoom the Camera in, so every pixel + * now takes up 2 pixels when rendered. + * + * Set to 1 to return to the default zoom level. + * + * Be careful to never set this value to zero. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_zoomX + * @type {number} + * @private + * @default 1 + * @since 3.50.0 + */ + this._zoomX = 1; + + /** + * The Camera vertical zoom value. Change this value to zoom in, or out of, a Scene. + * + * A value of 0.5 would zoom the Camera out, so you can now see twice as much + * of the Scene as before. A value of 2 would zoom the Camera in, so every pixel + * now takes up 2 pixels when rendered. + * + * Set to 1 to return to the default zoom level. + * + * Be careful to never set this value to zero. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_zoomY + * @type {number} + * @private + * @default 1 + * @since 3.50.0 + */ + this._zoomY = 1; + + /** + * The rotation of the Camera in radians. + * + * Camera rotation always takes place based on the Camera viewport. By default, rotation happens + * in the center of the viewport. You can adjust this with the `originX` and `originY` properties. + * + * Rotation influences the rendering of _all_ Game Objects visible by this Camera. However, it does not + * rotate the Camera viewport itself, which always remains an axis-aligned rectangle. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_rotation + * @type {number} + * @private + * @default 0 + * @since 3.11.0 + */ + this._rotation = 0; + + /** + * A local transform matrix used to compute the camera view. + * + * In v3, this contained a combination of the external camera position, + * and the internal rotation and zoom. + * In v4, it instead contains the internal camera scroll, rotation, and zoom. + * Note that these are applied in the order of rotation, scale, then scroll. + * This makes it easier to apply scaleFactor to the scroll values. + * + * See also `matrixExternal` and `matrixCombined`. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#matrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 3.0.0 + */ + this.matrix = new TransformMatrix(); + + /** + * A local transform matrix combining `matrix` and `matrixExternal`. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#matrixCombined + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + */ + this.matrixCombined = new TransformMatrix(); + + /** + * A local transform matrix used to compute the camera location. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#matrixExternal + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + */ + this.matrixExternal = new TransformMatrix(); + + /** + * Does this Camera have a transparent background? + * + * @name Phaser.Cameras.Scene2D.BaseCamera#transparent + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.transparent = true; + + /** + * The background color of this Camera. Only used if `transparent` is `false`. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#backgroundColor + * @type {Phaser.Display.Color} + * @since 3.0.0 + */ + this.backgroundColor = ValueToColor('rgba(0,0,0,0)'); + + /** + * The Camera alpha value. Setting this property impacts every single object that this Camera + * renders. You can either set the property directly, i.e. via a Tween, to fade a Camera in or out, + * or via the chainable `setAlpha` method instead. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#alpha + * @type {number} + * @default 1 + * @since 3.11.0 + */ + + /** + * Should the camera cull Game Objects before checking them for input hit tests? + * In some special cases it may be beneficial to disable this. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#disableCull + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.disableCull = false; + + /** + * A temporary array of culled objects. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#culledObjects + * @type {Phaser.GameObjects.GameObject[]} + * @default [] + * @private + * @since 3.0.0 + */ + this.culledObjects = []; + + /** + * The mid-point of the Camera in 'world' coordinates. + * + * Use it to obtain exactly where in the world the center of the camera is currently looking. + * + * This value is updated in the preRender method, after the scroll values and follower + * have been processed. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#midPoint + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.11.0 + */ + this.midPoint = new Vector2(width / 2, height / 2); + + /** + * The horizontal origin of rotation for this Camera. + * + * By default the camera rotates around the center of the viewport. + * + * Changing the origin allows you to adjust the point in the viewport from which rotation happens. + * A value of 0 would rotate from the top-left of the viewport. A value of 1 from the bottom right. + * + * See `setOrigin` to set both origins in a single, chainable call. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#originX + * @type {number} + * @default 0.5 + * @since 3.11.0 + */ + this.originX = 0.5; + + /** + * The vertical origin of rotation for this Camera. + * + * By default the camera rotates around the center of the viewport. + * + * Changing the origin allows you to adjust the point in the viewport from which rotation happens. + * A value of 0 would rotate from the top-left of the viewport. A value of 1 from the bottom right. + * + * See `setOrigin` to set both origins in a single, chainable call. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#originY + * @type {number} + * @default 0.5 + * @since 3.11.0 + */ + this.originY = 0.5; + + /** + * Does this Camera have a custom viewport? + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_customViewport + * @type {boolean} + * @private + * @default false + * @since 3.12.0 + */ + this._customViewport = false; + + /** + * The Mask this Camera is using during render. + * Set the mask using the `setMask` method. Remove the mask using the `clearMask` method. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#mask + * @type {?Phaser.Display.Masks.GeometryMask} + * @since 3.17.0 + */ + this.mask = null; + + /** + * The Camera that this Camera uses for translation during masking. + * + * If the mask is fixed in position this will be a reference to + * the CameraManager.default instance. Otherwise, it'll be a reference + * to itself. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#_maskCamera + * @type {?Phaser.Cameras.Scene2D.BaseCamera} + * @private + * @since 3.17.0 + */ + this._maskCamera = null; + + /** + * This array is populated with all of the Game Objects that this Camera has rendered + * in the previous (or current, depending on when you inspect it) frame. + * + * It is cleared at the start of `Camera.preUpdate`, or if the Camera is destroyed. + * + * You should not modify this array as it is used internally by the input system, + * however you can read it as required. Note that Game Objects may appear in this + * list multiple times if they belong to multiple non-exclusive Containers. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#renderList + * @type {Phaser.GameObjects.GameObject[]} + * @since 3.52.0 + */ + this.renderList = []; + + /** + * Is this Camera a Scene Camera? (which is the default), or a Camera + * belonging to a Texture? + * + * @name Phaser.Cameras.Scene2D.BaseCamera#isSceneCamera + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.isSceneCamera = true; + + /** + * Whether to force the camera to render via a framebuffer. + * This only applies when using the WebGL renderer. + * This makes the camera contents available to other WebGL processes, + * such as `CaptureFrame`. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#forceComposite + * @type {boolean} + * @default false + * @since 4.0.0 + * @webglOnly + */ + this.forceComposite = false; + + /** + * Can this Camera render rounded pixel values? + * + * This property is updated during the `preRender` method and should not be + * set directly. It is set based on the `roundPixels` property of the Camera + * combined with the zoom level. If the zoom is an integer then the WebGL + * Renderer can apply rounding during rendering. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#renderRoundPixels + * @type {boolean} + * @readonly + * @default true + * @since 3.86.0 + */ + this.renderRoundPixels = true; + }, + + /** + * Adds the given Game Object to this cameras render list. + * + * This is invoked during the rendering stage. Only objects that are actually rendered + * will appear in the render list. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#addToRenderList + * @since 3.52.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to add to the render list. + */ + addToRenderList: function (child) + { + this.renderList.push(child); + }, + + /** + * Set the Alpha level of this Camera. The alpha controls the opacity of the Camera as it renders. + * Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setAlpha + * @since 3.11.0 + * + * @param {number} [value=1] - The Camera alpha value. + * + * @return {this} This Camera instance. + */ + + /** + * Sets the rotation origin of this Camera. + * + * The values are given in the range 0 to 1 and are only used when calculating Camera rotation. + * + * By default the camera rotates around the center of the viewport. + * + * Changing the origin allows you to adjust the point in the viewport from which rotation happens. + * A value of 0 would rotate from the top-left of the viewport. A value of 1 from the bottom right. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setOrigin + * @since 3.11.0 + * + * @param {number} [x=0.5] - The horizontal origin value. + * @param {number} [y=x] - The vertical origin value. If not defined it will be set to the value of `x`. + * + * @return {this} This Camera instance. + */ + setOrigin: function (x, y) + { + if (x === undefined) { x = 0.5; } + if (y === undefined) { y = x; } + + this.originX = x; + this.originY = y; + + return this; + }, + + /** + * Calculates what the Camera.scrollX and scrollY values would need to be in order to move + * the Camera so it is centered on the given x and y coordinates, without actually moving + * the Camera there. The results are clamped based on the Camera bounds, if set. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#getScroll + * @since 3.11.0 + * + * @param {number} x - The horizontal coordinate to center on. + * @param {number} y - The vertical coordinate to center on. + * @param {Phaser.Math.Vector2} [out] - A Vector2 to store the values in. If not given a new Vector2 is created. + * + * @return {Phaser.Math.Vector2} The scroll coordinates stored in the `x` and `y` properties. + */ + getScroll: function (x, y, out) + { + if (out === undefined) { out = new Vector2(); } + + var originX = this.width * 0.5; + var originY = this.height * 0.5; + + out.x = x - originX; + out.y = y - originY; + + if (this.useBounds) + { + out.x = this.clampX(out.x); + out.y = this.clampY(out.y); + } + + return out; + }, + + /** + * Moves the Camera horizontally so that it is centered on the given x coordinate, bounds allowing. + * Calling this does not change the scrollY value. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#centerOnX + * @since 3.16.0 + * + * @param {number} x - The horizontal coordinate to center on. + * + * @return {this} This Camera instance. + */ + centerOnX: function (x) + { + var originX = this.width * 0.5; + + this.midPoint.x = x; + + this.scrollX = x - originX; + + if (this.useBounds) + { + this.scrollX = this.clampX(this.scrollX); + } + + return this; + }, + + /** + * Moves the Camera vertically so that it is centered on the given y coordinate, bounds allowing. + * Calling this does not change the scrollX value. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#centerOnY + * @since 3.16.0 + * + * @param {number} y - The vertical coordinate to center on. + * + * @return {this} This Camera instance. + */ + centerOnY: function (y) + { + var originY = this.height * 0.5; + + this.midPoint.y = y; + + this.scrollY = y - originY; + + if (this.useBounds) + { + this.scrollY = this.clampY(this.scrollY); + } + + return this; + }, + + /** + * Moves the Camera so that it is centered on the given coordinates, bounds allowing. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#centerOn + * @since 3.11.0 + * + * @param {number} x - The horizontal coordinate to center on. + * @param {number} y - The vertical coordinate to center on. + * + * @return {this} This Camera instance. + */ + centerOn: function (x, y) + { + this.centerOnX(x); + this.centerOnY(y); + + return this; + }, + + /** + * Moves the Camera so that it is looking at the center of the Camera Bounds, if enabled. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#centerToBounds + * @since 3.0.0 + * + * @return {this} This Camera instance. + */ + centerToBounds: function () + { + if (this.useBounds) + { + var bounds = this._bounds; + var originX = this.width * 0.5; + var originY = this.height * 0.5; + + this.midPoint.set(bounds.centerX, bounds.centerY); + + this.scrollX = bounds.centerX - originX; + this.scrollY = bounds.centerY - originY; + } + + return this; + }, + + /** + * Moves the Camera so that it is re-centered based on its viewport size. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#centerToSize + * @since 3.0.0 + * + * @return {this} This Camera instance. + */ + centerToSize: function () + { + this.scrollX = this.width * 0.5; + this.scrollY = this.height * 0.5; + + return this; + }, + + /** + * Takes an array of Game Objects and returns a new array featuring only those objects + * visible by this camera. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#cull + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject[]} G - [renderableObjects,$return] + * + * @param {Phaser.GameObjects.GameObject[]} renderableObjects - An array of Game Objects to cull. + * + * @return {Phaser.GameObjects.GameObject[]} An array of Game Objects visible to this Camera. + */ + cull: function (renderableObjects) + { + if (this.disableCull) + { + return renderableObjects; + } + + var cameraMatrix = this.matrix.matrix; + + var mva = cameraMatrix[0]; + var mvb = cameraMatrix[1]; + var mvc = cameraMatrix[2]; + var mvd = cameraMatrix[3]; + + /* First Invert Matrix */ + var determinant = (mva * mvd) - (mvb * mvc); + + if (!determinant) + { + return renderableObjects; + } + + var scrollX = this.scrollX; + var scrollY = this.scrollY; + var cameraW = this.width; + var cameraH = this.height; + var cullTop = this.y; + var cullBottom = cullTop + cameraH; + var cullLeft = this.x; + var cullRight = cullLeft + cameraW; + var culledObjects = this.culledObjects; + var length = renderableObjects.length; + + determinant = 1 / determinant; + + culledObjects.length = 0; + + for (var index = 0; index < length; ++index) + { + var object = renderableObjects[index]; + + if (!object.hasOwnProperty('width') || object.parentContainer) + { + culledObjects.push(object); + continue; + } + + var objectW = object.width; + var objectH = object.height; + var objectX = (object.x - (scrollX * object.scrollFactorX)) - (objectW * object.originX); + var objectY = (object.y - (scrollY * object.scrollFactorY)) - (objectH * object.originY); + var tx = (objectX * mva + objectY * mvc); + var ty = (objectX * mvb + objectY * mvd); + var tw = ((objectX + objectW) * mva + (objectY + objectH) * mvc); + var th = ((objectX + objectW) * mvb + (objectY + objectH) * mvd); + + if ((tw > cullLeft && tx < cullRight) && (th > cullTop && ty < cullBottom)) + { + culledObjects.push(object); + } + } + + return culledObjects; + }, + + /** + * Converts the given `x` and `y` coordinates into World space, based on this Cameras transform. + * You can optionally provide a Vector2, or similar object, to store the results in. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#getWorldPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [output,$return] + * + * @param {number} x - The x position to convert to world space. + * @param {number} y - The y position to convert to world space. + * @param {(object|Phaser.Math.Vector2)} [output] - An optional object to store the results in. If not provided a new Vector2 will be created. + * + * @return {Phaser.Math.Vector2} An object holding the converted values in its `x` and `y` properties. + */ + getWorldPoint: function (x, y, output) + { + if (output === undefined) { output = new Vector2(); } + + var cameraMatrix = this.matrixCombined.matrix; + + var mva = cameraMatrix[0]; + var mvb = cameraMatrix[1]; + var mvc = cameraMatrix[2]; + var mvd = cameraMatrix[3]; + var mve = cameraMatrix[4]; + var mvf = cameraMatrix[5]; + + // Invert Matrix + var determinant = (mva * mvd) - (mvb * mvc); + + if (!determinant) + { + output.x = x; + output.y = y; + + return output; + } + + determinant = 1 / determinant; + + var ima = mvd * determinant; + var imb = -mvb * determinant; + var imc = -mvc * determinant; + var imd = mva * determinant; + var ime = (mvc * mvf - mvd * mve) * determinant; + var imf = (mvb * mve - mva * mvf) * determinant; + + // Apply transform to point + output.x = (x * ima + y * imc) + ime; + output.y = (x * imb + y * imd) + imf; + + return output; + }, + + /** + * Given a Game Object, or an array of Game Objects, it will update all of their camera filter settings + * so that they are ignored by this Camera. This means they will not be rendered by this Camera. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#ignore + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]|Phaser.GameObjects.Group|Phaser.GameObjects.Layer|Phaser.GameObjects.Layer[])} entries - The Game Object, or array of Game Objects, to be ignored by this Camera. + * + * @return {this} This Camera instance. + */ + ignore: function (entries) + { + var id = this.id; + + if (!Array.isArray(entries)) + { + entries = [ entries ]; + } + + for (var i = 0; i < entries.length; i++) + { + var entry = entries[i]; + + if (Array.isArray(entry)) + { + this.ignore(entry); + } + else if (entry.isParent) + { + this.ignore(entry.getChildren()); + } + else + { + entry.cameraFilter |= id; + } + } + + return this; + }, + + /** + * Takes an x value and checks it's within the range of the Camera bounds, adjusting if required. + * Do not call this method if you are not using camera bounds. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#clampX + * @since 3.11.0 + * + * @param {number} x - The value to horizontally scroll clamp. + * + * @return {number} The adjusted value to use as scrollX. + */ + clampX: function (x) + { + var bounds = this._bounds; + + var dw = this.displayWidth; + + var bx = bounds.x + ((dw - this.width) / 2); + var bw = Math.max(bx, bx + bounds.width - dw); + + if (x < bx) + { + x = bx; + } + else if (x > bw) + { + x = bw; + } + + return x; + }, + + /** + * Takes a y value and checks it's within the range of the Camera bounds, adjusting if required. + * Do not call this method if you are not using camera bounds. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#clampY + * @since 3.11.0 + * + * @param {number} y - The value to vertically scroll clamp. + * + * @return {number} The adjusted value to use as scrollY. + */ + clampY: function (y) + { + var bounds = this._bounds; + + var dh = this.displayHeight; + + var by = bounds.y + ((dh - this.height) / 2); + var bh = Math.max(by, by + bounds.height - dh); + + if (y < by) + { + y = by; + } + else if (y > bh) + { + y = bh; + } + + return y; + }, + + /* + var gap = this._zoomInversed; + return gap * Math.round((src.x - this.scrollX * src.scrollFactorX) / gap); + */ + + /** + * If this Camera has previously had movement bounds set on it, this will remove them. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#removeBounds + * @since 3.0.0 + * + * @return {this} This Camera instance. + */ + removeBounds: function () + { + this.useBounds = false; + + this.dirty = true; + + this._bounds.setEmpty(); + + return this; + }, + + /** + * Set the rotation of this Camera. This causes everything it renders to appear rotated. + * + * Rotating a camera does not rotate the viewport itself, it is applied during rendering. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setAngle + * @since 3.0.0 + * + * @param {number} [value=0] - The cameras angle of rotation, given in degrees. + * + * @return {this} This Camera instance. + */ + setAngle: function (value) + { + if (value === undefined) { value = 0; } + + this.rotation = DegToRad(value); + + return this; + }, + + /** + * Sets the background color for this Camera. + * + * By default a Camera has a transparent background but it can be given a solid color, with any level + * of transparency, via this method. + * + * The color value can be specified using CSS color notation, hex or numbers. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setBackgroundColor + * @since 3.0.0 + * + * @param {(string|number|Phaser.Types.Display.InputColorObject)} [color='rgba(0,0,0,0)'] - The color value. In CSS, hex or numeric color notation. + * + * @return {this} This Camera instance. + */ + setBackgroundColor: function (color) + { + if (color === undefined) { color = 'rgba(0,0,0,0)'; } + + this.backgroundColor = ValueToColor(color); + + this.transparent = (this.backgroundColor.alpha === 0); + + return this; + }, + + /** + * Set the bounds of the Camera. The bounds are an axis-aligned rectangle. + * + * The Camera bounds controls where the Camera can scroll to, stopping it from scrolling off the + * edges and into blank space. It does not limit the placement of Game Objects, or where + * the Camera viewport can be positioned. + * + * Temporarily disable the bounds by changing the boolean `Camera.useBounds`. + * + * Clear the bounds entirely by calling `Camera.removeBounds`. + * + * If you set bounds that are smaller than the viewport it will stop the Camera from being + * able to scroll. The bounds can be positioned where-ever you wish. By default they are from + * 0x0 to the canvas width x height. This means that the coordinate 0x0 is the top left of + * the Camera bounds. However, you can position them anywhere. So if you wanted a game world + * that was 2048x2048 in size, with 0x0 being the center of it, you can set the bounds x/y + * to be -1024, -1024, with a width and height of 2048. Depending on your game you may find + * it easier for 0x0 to be the top-left of the bounds, or you may wish 0x0 to be the middle. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setBounds + * @since 3.0.0 + * + * @param {number} x - The top-left x coordinate of the bounds. + * @param {number} y - The top-left y coordinate of the bounds. + * @param {number} width - The width of the bounds, in pixels. + * @param {number} height - The height of the bounds, in pixels. + * @param {boolean} [centerOn=false] - If `true` the Camera will automatically be centered on the new bounds. + * + * @return {this} This Camera instance. + */ + setBounds: function (x, y, width, height, centerOn) + { + if (centerOn === undefined) { centerOn = false; } + + this._bounds.setTo(x, y, width, height); + + this.dirty = true; + this.useBounds = true; + + if (centerOn) + { + this.centerToBounds(); + } + else + { + this.scrollX = this.clampX(this.scrollX); + this.scrollY = this.clampY(this.scrollY); + } + + return this; + }, + + /** + * Sets the `forceComposite` property of this Camera. + * This property is only used by the WebGL Renderer. + * If `true` the camera will render via a framebuffer, + * making it available to other WebGL systems. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setForceComposite + * @since 4.0.0 + * @webglOnly + * + * @param {boolean} value - The value to set the property to. + * + * @returns {this} This Camera instance. + */ + setForceComposite: function (value) + { + this.forceComposite = value; + + return this; + }, + + /** + * Returns a rectangle containing the bounds of the Camera. + * + * If the Camera does not have any bounds the rectangle will be empty. + * + * The rectangle is a copy of the bounds, so is safe to modify. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#getBounds + * @since 3.16.0 + * + * @param {Phaser.Geom.Rectangle} [out] - An optional Rectangle to store the bounds in. If not given, a new Rectangle will be created. + * + * @return {Phaser.Geom.Rectangle} A rectangle containing the bounds of this Camera. + */ + getBounds: function (out) + { + if (out === undefined) { out = new Rectangle(); } + + var source = this._bounds; + + out.setTo(source.x, source.y, source.width, source.height); + + return out; + }, + + /** + * Sets the name of this Camera. + * This value is for your own use and isn't used internally. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setName + * @since 3.0.0 + * + * @param {string} [value=''] - The name of the Camera. + * + * @return {this} This Camera instance. + */ + setName: function (value) + { + if (value === undefined) { value = ''; } + + this.name = value; + + return this; + }, + + /** + * Set the position of the Camera viewport within the game. + * + * This does not change where the camera is 'looking'. See `setScroll` to control that. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setPosition + * @since 3.0.0 + * + * @param {number} x - The top-left x coordinate of the Camera viewport. + * @param {number} [y=x] - The top-left y coordinate of the Camera viewport. + * + * @return {this} This Camera instance. + */ + setPosition: function (x, y) + { + if (y === undefined) { y = x; } + + this.x = x; + this.y = y; + + return this; + }, + + /** + * Set the rotation of this Camera. This causes everything it renders to appear rotated. + * + * Rotating a camera does not rotate the viewport itself, it is applied during rendering. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setRotation + * @since 3.0.0 + * + * @param {number} [value=0] - The rotation of the Camera, in radians. + * + * @return {this} This Camera instance. + */ + setRotation: function (value) + { + if (value === undefined) { value = 0; } + + this.rotation = value; + + return this; + }, + + /** + * Should the Camera round pixel values to whole integers when rendering Game Objects? + * + * In some types of game, especially with pixel art, this is required to prevent sub-pixel aliasing. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setRoundPixels + * @since 3.0.0 + * + * @param {boolean} value - `true` to round Camera pixels, `false` to not. + * + * @return {this} This Camera instance. + */ + setRoundPixels: function (value) + { + this.roundPixels = value; + + return this; + }, + + /** + * Sets the Scene the Camera is bound to. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setScene + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene the camera is bound to. + * @param {boolean} [isSceneCamera=true] - Is this Camera being used for a Scene (true) or a Texture? (false) + * + * @return {this} This Camera instance. + */ + setScene: function (scene, isSceneCamera) + { + if (isSceneCamera === undefined) { isSceneCamera = true; } + + if (this.scene && this._customViewport) + { + this.sceneManager.customViewports--; + } + + this.scene = scene; + this.isSceneCamera = isSceneCamera; + + var sys = scene.sys; + + this.sceneManager = sys.game.scene; + this.scaleManager = sys.scale; + this.cameraManager = sys.cameras; + + this.updateSystem(); + + return this; + }, + + /** + * Set the position of where the Camera is looking within the game. + * You can also modify the properties `Camera.scrollX` and `Camera.scrollY` directly. + * Use this method, or the scroll properties, to move your camera around the game world. + * + * This does not change where the camera viewport is placed. See `setPosition` to control that. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setScroll + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the Camera in the game world. + * @param {number} [y=x] - The y coordinate of the Camera in the game world. + * + * @return {this} This Camera instance. + */ + setScroll: function (x, y) + { + if (y === undefined) { y = x; } + + this.scrollX = x; + this.scrollY = y; + + return this; + }, + + /** + * Set the size of the Camera viewport. + * + * By default a Camera is the same size as the game, but can be made smaller via this method, + * allowing you to create mini-cam style effects by creating and positioning a smaller Camera + * viewport within your game. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setSize + * @since 3.0.0 + * + * @param {number} width - The width of the Camera viewport. + * @param {number} [height=width] - The height of the Camera viewport. + * + * @return {this} This Camera instance. + */ + setSize: function (width, height) + { + if (height === undefined) { height = width; } + + this.width = width; + this.height = height; + + return this; + }, + + /** + * This method sets the position and size of the Camera viewport in a single call. + * + * If you're trying to change where the Camera is looking at in your game, then see + * the method `Camera.setScroll` instead. This method is for changing the viewport + * itself, not what the camera can see. + * + * By default a Camera is the same size as the game, but can be made smaller via this method, + * allowing you to create mini-cam style effects by creating and positioning a smaller Camera + * viewport within your game. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setViewport + * @since 3.0.0 + * + * @param {number} x - The top-left x coordinate of the Camera viewport. + * @param {number} y - The top-left y coordinate of the Camera viewport. + * @param {number} width - The width of the Camera viewport. + * @param {number} [height=width] - The height of the Camera viewport. + * + * @return {this} This Camera instance. + */ + setViewport: function (x, y, width, height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + + return this; + }, + + /** + * Set the zoom value of the Camera. + * + * Changing to a smaller value, such as 0.5, will cause the camera to 'zoom out'. + * Changing to a larger value, such as 2, will cause the camera to 'zoom in'. + * + * A value of 1 means 'no zoom' and is the default. + * + * Changing the zoom does not impact the Camera viewport in any way, it is only applied during rendering. + * + * As of Phaser 3.50 you can now set the horizontal and vertical zoom values independently. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setZoom + * @since 3.0.0 + * + * @param {number} [x=1] - The horizontal zoom value of the Camera. The minimum it can be is 0.001. + * @param {number} [y=x] - The vertical zoom value of the Camera. The minimum it can be is 0.001. + * + * @return {this} This Camera instance. + */ + setZoom: function (x, y) + { + if (x === undefined) { x = 1; } + if (y === undefined) { y = x; } + + if (x === 0) + { + x = 0.001; + } + + if (y === 0) + { + y = 0.001; + } + + this.zoomX = x; + this.zoomY = y; + + return this; + }, + + /** + * Sets the mask to be applied to this Camera during rendering. + * + * The mask must have been previously created and must be a GeometryMask. + * This only works in the Canvas Renderer. + * In WebGL, use a Mask filter instead (see {@link Phaser.GameObjects.Components.FilterList#addMask}). + * + * If a mask is already set on this Camera it will be immediately replaced. + * + * Masks have no impact on physics or input detection. They are purely a rendering component + * that allows you to limit what is visible during the render pass. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setMask + * @since 3.17.0 + * + * @param {Phaser.Display.Masks.GeometryMask} mask - The mask this Camera will use when rendering. + * @param {boolean} [fixedPosition=true] - Should the mask translate along with the Camera, or be fixed in place and not impacted by the Cameras transform? + * + * @return {this} This Camera instance. + */ + setMask: function (mask, fixedPosition) + { + if (fixedPosition === undefined) { fixedPosition = true; } + + this.mask = mask; + + this._maskCamera = (fixedPosition) ? this.cameraManager.default : this; + + return this; + }, + + /** + * Clears the mask that this Camera was using. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#clearMask + * @since 3.17.0 + * + * @param {boolean} [destroyMask=false] - Destroy the mask before clearing it? + * + * @return {this} This Camera instance. + */ + clearMask: function (destroyMask) + { + if (destroyMask === undefined) { destroyMask = false; } + + if (destroyMask && this.mask) + { + this.mask.destroy(); + } + + this.mask = null; + + return this; + }, + + /** + * Sets the visibility of this Camera. + * + * An invisible Camera will skip rendering and input tests of everything it can see. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setVisible + * @since 3.10.0 + * + * @param {boolean} value - The visible state of the Camera. + * + * @return {this} This Camera instance. + */ + + /** + * Returns an Object suitable for JSON storage containing all of the Camera viewport and rendering properties. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Cameras.Scene2D.JSONCamera} A well-formed object suitable for conversion to JSON. + */ + toJSON: function () + { + var output = { + name: this.name, + x: this.x, + y: this.y, + width: this.width, + height: this.height, + zoom: this.zoom, + rotation: this.rotation, + roundPixels: this.roundPixels, + scrollX: this.scrollX, + scrollY: this.scrollY, + backgroundColor: this.backgroundColor.rgba + }; + + if (this.useBounds) + { + output['bounds'] = { + x: this._bounds.x, + y: this._bounds.y, + width: this._bounds.width, + height: this._bounds.height + }; + } + + return output; + }, + + /** + * Internal method called automatically by the Camera Manager. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#update + * @protected + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function () + { + // NOOP + }, + + /** + * Set if this Camera is being used as a Scene Camera, or a Texture + * Camera. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#setIsSceneCamera + * @since 3.60.0 + * + * @param {boolean} value - Is this being used as a Scene Camera, or a Texture camera? + */ + setIsSceneCamera: function (value) + { + this.isSceneCamera = value; + + return this; + }, + + /** + * Internal method called automatically when the viewport changes. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#updateSystem + * @private + * @since 3.12.0 + */ + updateSystem: function () + { + if (!this.scaleManager || !this.isSceneCamera) + { + return; + } + + var custom = (this._x !== 0 || this._y !== 0 || this.scaleManager.width !== this._width || this.scaleManager.height !== this._height); + + var sceneManager = this.sceneManager; + + if (custom && !this._customViewport) + { + // We need a custom viewport for this Camera + sceneManager.customViewports++; + } + else if (!custom && this._customViewport) + { + // We're turning off a custom viewport for this Camera + sceneManager.customViewports--; + } + + this.dirty = true; + this._customViewport = custom; + }, + + /** + * Destroys this Camera instance and its internal properties and references. + * Once destroyed you cannot use this Camera again, even if re-added to a Camera Manager. + * + * This method is called automatically by `CameraManager.remove` if that methods `runDestroy` argument is `true`, which is the default. + * + * Unless you have a specific reason otherwise, always use `CameraManager.remove` and allow it to handle the camera destruction, + * rather than calling this method directly. + * + * @method Phaser.Cameras.Scene2D.BaseCamera#destroy + * @fires Phaser.Cameras.Scene2D.Events#DESTROY + * @since 3.0.0 + */ + destroy: function () + { + this.emit(Events.DESTROY, this); + + this.removeAllListeners(); + + this.matrix.destroy(); + this.matrixCombined.destroy(); + this.matrixExternal.destroy(); + + this.culledObjects = []; + + if (this._customViewport) + { + // We're turning off a custom viewport for this Camera + this.sceneManager.customViewports--; + } + + this.renderList = []; + + this._bounds = null; + + this.scene = null; + this.scaleManager = null; + this.sceneManager = null; + this.cameraManager = null; + }, + + /** + * The x position of the Camera viewport, relative to the top-left of the game canvas. + * The viewport is the area into which the camera renders. + * To adjust the position the camera is looking at in the game world, see the `scrollX` value. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#x + * @type {number} + * @since 3.0.0 + */ + x: { + + get: function () + { + return this._x; + }, + + set: function (value) + { + this._x = value; + this.updateSystem(); + } + + }, + + /** + * The y position of the Camera viewport, relative to the top-left of the game canvas. + * The viewport is the area into which the camera renders. + * To adjust the position the camera is looking at in the game world, see the `scrollY` value. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#y + * @type {number} + * @since 3.0.0 + */ + y: { + + get: function () + { + return this._y; + }, + + set: function (value) + { + this._y = value; + this.updateSystem(); + } + + }, + + /** + * The width of the Camera viewport, in pixels. + * + * The viewport is the area into which the Camera renders. Setting the viewport does + * not restrict where the Camera can scroll to. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#width + * @type {number} + * @since 3.0.0 + */ + width: { + + get: function () + { + return this._width; + }, + + set: function (value) + { + this._width = value; + this.updateSystem(); + } + + }, + + /** + * The height of the Camera viewport, in pixels. + * + * The viewport is the area into which the Camera renders. Setting the viewport does + * not restrict where the Camera can scroll to. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#height + * @type {number} + * @since 3.0.0 + */ + height: { + + get: function () + { + return this._height; + }, + + set: function (value) + { + this._height = value; + this.updateSystem(); + } + + }, + + /** + * The horizontal scroll position of this Camera. + * + * Change this value to cause the Camera to scroll around your Scene. + * + * Alternatively, setting the Camera to follow a Game Object, via the `startFollow` method, + * will automatically adjust the Camera scroll values accordingly. + * + * You can set the bounds within which the Camera can scroll via the `setBounds` method. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#scrollX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + scrollX: { + + get: function () + { + return this._scrollX; + }, + + set: function (value) + { + if (value !== this._scrollX) + { + this._scrollX = value; + this.dirty = true; + } + } + + }, + + /** + * The vertical scroll position of this Camera. + * + * Change this value to cause the Camera to scroll around your Scene. + * + * Alternatively, setting the Camera to follow a Game Object, via the `startFollow` method, + * will automatically adjust the Camera scroll values accordingly. + * + * You can set the bounds within which the Camera can scroll via the `setBounds` method. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#scrollY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + scrollY: { + + get: function () + { + return this._scrollY; + }, + + set: function (value) + { + if (value !== this._scrollY) + { + this._scrollY = value; + this.dirty = true; + } + } + + }, + + /** + * The Camera zoom value. Change this value to zoom in, or out of, a Scene. + * + * A value of 0.5 would zoom the Camera out, so you can now see twice as much + * of the Scene as before. A value of 2 would zoom the Camera in, so every pixel + * now takes up 2 pixels when rendered. + * + * Set to 1 to return to the default zoom level. + * + * Be careful to never set this value to zero. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#zoom + * @type {number} + * @default 1 + * @since 3.0.0 + */ + zoom: { + + get: function () + { + return (this._zoomX + this._zoomY) / 2; + }, + + set: function (value) + { + this._zoomX = value; + this._zoomY = value; + + this.dirty = true; + } + + }, + + /** + * The Camera horizontal zoom value. Change this value to zoom in, or out of, a Scene. + * + * A value of 0.5 would zoom the Camera out, so you can now see twice as much + * of the Scene as before. A value of 2 would zoom the Camera in, so every pixel + * now takes up 2 pixels when rendered. + * + * Set to 1 to return to the default zoom level. + * + * Be careful to never set this value to zero. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#zoomX + * @type {number} + * @default 1 + * @since 3.50.0 + */ + zoomX: { + + get: function () + { + return this._zoomX; + }, + + set: function (value) + { + this._zoomX = value; + this.dirty = true; + } + + }, + + /** + * The Camera vertical zoom value. Change this value to zoom in, or out of, a Scene. + * + * A value of 0.5 would zoom the Camera out, so you can now see twice as much + * of the Scene as before. A value of 2 would zoom the Camera in, so every pixel + * now takes up 2 pixels when rendered. + * + * Set to 1 to return to the default zoom level. + * + * Be careful to never set this value to zero. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#zoomY + * @type {number} + * @default 1 + * @since 3.50.0 + */ + zoomY: { + + get: function () + { + return this._zoomY; + }, + + set: function (value) + { + this._zoomY = value; + this.dirty = true; + } + + }, + + /** + * The rotation of the Camera in radians. + * + * Camera rotation always takes place based on the Camera viewport. By default, rotation happens + * in the center of the viewport. You can adjust this with the `originX` and `originY` properties. + * + * Rotation influences the rendering of _all_ Game Objects visible by this Camera. However, it does not + * rotate the Camera viewport itself, which always remains an axis-aligned rectangle. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#rotation + * @type {number} + * @private + * @default 0 + * @since 3.11.0 + */ + rotation: { + + get: function () + { + return this._rotation; + }, + + set: function (value) + { + this._rotation = value; + this.dirty = true; + } + + }, + + /** + * The horizontal position of the center of the Camera's viewport, relative to the left of the game canvas. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#centerX + * @type {number} + * @readonly + * @since 3.10.0 + */ + centerX: { + + get: function () + { + return this.x + (0.5 * this.width); + } + + }, + + /** + * The vertical position of the center of the Camera's viewport, relative to the top of the game canvas. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#centerY + * @type {number} + * @readonly + * @since 3.10.0 + */ + centerY: { + + get: function () + { + return this.y + (0.5 * this.height); + } + + }, + + /** + * The displayed width of the camera viewport, factoring in the camera zoom level. + * + * If a camera has a viewport width of 800 and a zoom of 0.5 then its display width + * would be 1600, as it's displaying twice as many pixels as zoom level 1. + * + * Equally, a camera with a width of 800 and zoom of 2 would have a display width + * of 400 pixels. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#displayWidth + * @type {number} + * @readonly + * @since 3.11.0 + */ + displayWidth: { + + get: function () + { + return this.width / this.zoomX; + } + + }, + + /** + * The displayed height of the camera viewport, factoring in the camera zoom level. + * + * If a camera has a viewport height of 600 and a zoom of 0.5 then its display height + * would be 1200, as it's displaying twice as many pixels as zoom level 1. + * + * Equally, a camera with a height of 600 and zoom of 2 would have a display height + * of 300 pixels. + * + * @name Phaser.Cameras.Scene2D.BaseCamera#displayHeight + * @type {number} + * @readonly + * @since 3.11.0 + */ + displayHeight: { + + get: function () + { + return this.height / this.zoomY; + } + + } + +}); + +module.exports = BaseCamera; + + +/***/ }), + +/***/ 38058: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseCamera = __webpack_require__(71911); +var CenterOn = __webpack_require__(67502); +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var Effects = __webpack_require__(20052); +var Events = __webpack_require__(19715); +var Linear = __webpack_require__(28915); +var Rectangle = __webpack_require__(87841); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Camera. + * + * The Camera is the way in which all games are rendered in Phaser. They provide a view into your game world, + * and can be positioned, rotated, zoomed and scrolled accordingly. + * + * A Camera consists of two elements: The viewport and the scroll values. + * + * The viewport is the physical position and size of the Camera within your game. Cameras, by default, are + * created the same size as your game, but their position and size can be set to anything. This means if you + * wanted to create a camera that was 320x200 in size, positioned in the bottom-right corner of your game, + * you'd adjust the viewport to do that (using methods like `setViewport` and `setSize`). + * + * If you wish to change where the Camera is looking in your game, then you scroll it. You can do this + * via the properties `scrollX` and `scrollY` or the method `setScroll`. Scrolling has no impact on the + * viewport, and changing the viewport has no impact on the scrolling. + * + * By default a Camera will render all Game Objects it can see. You can change this using the `ignore` method, + * allowing you to filter Game Objects out on a per-Camera basis. + * + * A Camera also has built-in special effects including Fade, Flash and Camera Shake. + * + * @class Camera + * @memberof Phaser.Cameras.Scene2D + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Cameras.Scene2D.BaseCamera + * + * @param {number} x - The x position of the Camera, relative to the top-left of the game canvas. + * @param {number} y - The y position of the Camera, relative to the top-left of the game canvas. + * @param {number} width - The width of the Camera, in pixels. + * @param {number} height - The height of the Camera, in pixels. + */ +var Camera = new Class({ + + Extends: BaseCamera, + + initialize: + + function Camera (x, y, width, height) + { + BaseCamera.call(this, x, y, width, height); + + /** + * The filters for this camera. + * Filters control special effects and masks. + * + * This object contains two lists of filters: `internal` and `external`. + * See {@link Phaser.GameObjects.Components.FilterList} for more information. + * + * @name Phaser.Cameras.Scene2D.Camera#filters + * @type {{ internal: Phaser.GameObjects.Components.FilterList, external: Phaser.GameObjects.Components.FilterList }} + * @since 4.0.0 + */ + this.filters = { + internal: new Components.FilterList(this), + external: new Components.FilterList(this) + }; + + /** + * Does this Camera allow the Game Objects it renders to receive input events? + * + * @name Phaser.Cameras.Scene2D.Camera#inputEnabled + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.inputEnabled = true; + + /** + * The Camera Fade effect handler. + * To fade this camera see the `Camera.fade` methods. + * + * @name Phaser.Cameras.Scene2D.Camera#fadeEffect + * @type {Phaser.Cameras.Scene2D.Effects.Fade} + * @since 3.5.0 + */ + this.fadeEffect = new Effects.Fade(this); + + /** + * The Camera Flash effect handler. + * To flash this camera see the `Camera.flash` method. + * + * @name Phaser.Cameras.Scene2D.Camera#flashEffect + * @type {Phaser.Cameras.Scene2D.Effects.Flash} + * @since 3.5.0 + */ + this.flashEffect = new Effects.Flash(this); + + /** + * The Camera Shake effect handler. + * To shake this camera see the `Camera.shake` method. + * + * @name Phaser.Cameras.Scene2D.Camera#shakeEffect + * @type {Phaser.Cameras.Scene2D.Effects.Shake} + * @since 3.5.0 + */ + this.shakeEffect = new Effects.Shake(this); + + /** + * The Camera Pan effect handler. + * To pan this camera see the `Camera.pan` method. + * + * @name Phaser.Cameras.Scene2D.Camera#panEffect + * @type {Phaser.Cameras.Scene2D.Effects.Pan} + * @since 3.11.0 + */ + this.panEffect = new Effects.Pan(this); + + /** + * The Camera Rotate To effect handler. + * To rotate this camera see the `Camera.rotateTo` method. + * + * @name Phaser.Cameras.Scene2D.Camera#rotateToEffect + * @type {Phaser.Cameras.Scene2D.Effects.RotateTo} + * @since 3.23.0 + */ + this.rotateToEffect = new Effects.RotateTo(this); + + /** + * The Camera Zoom effect handler. + * To zoom this camera see the `Camera.zoom` method. + * + * @name Phaser.Cameras.Scene2D.Camera#zoomEffect + * @type {Phaser.Cameras.Scene2D.Effects.Zoom} + * @since 3.11.0 + */ + this.zoomEffect = new Effects.Zoom(this); + + /** + * The linear interpolation value to use when following a target. + * + * Can also be set via `setLerp` or as part of the `startFollow` call. + * + * The default values of 1 means the camera will instantly snap to the target coordinates. + * A lower value, such as 0.1 means the camera will more slowly track the target, giving + * a smooth transition. You can set the horizontal and vertical values independently, and also + * adjust this value in real-time during your game. + * + * Be sure to keep the value between 0 and 1. A value of zero will disable tracking on that axis. + * + * @name Phaser.Cameras.Scene2D.Camera#lerp + * @type {Phaser.Math.Vector2} + * @since 3.9.0 + */ + this.lerp = new Vector2(1, 1); + + /** + * The values stored in this property are subtracted from the Camera targets position, allowing you to + * offset the camera from the actual target x/y coordinates by this amount. + * Can also be set via `setFollowOffset` or as part of the `startFollow` call. + * + * @name Phaser.Cameras.Scene2D.Camera#followOffset + * @type {Phaser.Math.Vector2} + * @since 3.9.0 + */ + this.followOffset = new Vector2(); + + /** + * The Camera dead zone. + * + * The deadzone is only used when the camera is following a target. + * + * It defines a rectangular region within which if the target is present, the camera will not scroll. + * If the target moves outside of this area, the camera will begin scrolling in order to follow it. + * + * The `lerp` values that you can set for a follower target also apply when using a deadzone. + * + * You can directly set this property to be an instance of a Rectangle. Or, you can use the + * `setDeadzone` method for a chainable approach. + * + * The rectangle you provide can have its dimensions adjusted dynamically, however, please + * note that its position is updated every frame, as it is constantly re-centered on the cameras mid point. + * + * Calling `setDeadzone` with no arguments will reset an active deadzone, as will setting this property + * to `null`. + * + * @name Phaser.Cameras.Scene2D.Camera#deadzone + * @type {?Phaser.Geom.Rectangle} + * @since 3.11.0 + */ + this.deadzone = null; + + /** + * Internal follow target reference. + * + * @name Phaser.Cameras.Scene2D.Camera#_follow + * @type {?any} + * @private + * @default null + * @since 3.0.0 + */ + this._follow = null; + }, + + /** + * Sets the Camera dead zone. + * + * The deadzone is only used when the camera is following a target. + * + * It defines a rectangular region within which if the target is present, the camera will not scroll. + * If the target moves outside of this area, the camera will begin scrolling in order to follow it. + * + * The deadzone rectangle is re-positioned every frame so that it is centered on the mid-point + * of the camera. This allows you to use the object for additional game related checks, such as + * testing if an object is within it or not via a Rectangle.contains call. + * + * The `lerp` values that you can set for a follower target also apply when using a deadzone. + * + * Calling this method with no arguments will reset an active deadzone. + * + * @method Phaser.Cameras.Scene2D.Camera#setDeadzone + * @since 3.11.0 + * + * @param {number} [width] - The width of the deadzone rectangle in pixels. If not specified the deadzone is removed. + * @param {number} [height] - The height of the deadzone rectangle in pixels. + * + * @return {this} This Camera instance. + */ + setDeadzone: function (width, height) + { + if (width === undefined) + { + this.deadzone = null; + } + else + { + if (this.deadzone) + { + this.deadzone.width = width; + this.deadzone.height = height; + } + else + { + this.deadzone = new Rectangle(0, 0, width, height); + } + + if (this._follow) + { + var originX = this.width / 2; + var originY = this.height / 2; + + var fx = this._follow.x - this.followOffset.x; + var fy = this._follow.y - this.followOffset.y; + + this.midPoint.set(fx, fy); + + this.scrollX = fx - originX; + this.scrollY = fy - originY; + } + + CenterOn(this.deadzone, this.midPoint.x, this.midPoint.y); + } + + return this; + }, + + /** + * Fades the Camera in from the given color over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Camera#fadeIn + * @fires Phaser.Cameras.Scene2D.Events#FADE_IN_START + * @fires Phaser.Cameras.Scene2D.Events#FADE_IN_COMPLETE + * @since 3.3.0 + * + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {number} [red=0] - The amount to fade the red channel towards. A value between 0 and 255. + * @param {number} [green=0] - The amount to fade the green channel towards. A value between 0 and 255. + * @param {number} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255. + * @param {function} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + fadeIn: function (duration, red, green, blue, callback, context) + { + return this.fadeEffect.start(false, duration, red, green, blue, true, callback, context); + }, + + /** + * Fades the Camera out to the given color over the duration specified. + * This is an alias for Camera.fade that forces the fade to start, regardless of existing fades. + * + * @method Phaser.Cameras.Scene2D.Camera#fadeOut + * @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_START + * @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_COMPLETE + * @since 3.3.0 + * + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {number} [red=0] - The amount to fade the red channel towards. A value between 0 and 255. + * @param {number} [green=0] - The amount to fade the green channel towards. A value between 0 and 255. + * @param {number} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255. + * @param {function} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + fadeOut: function (duration, red, green, blue, callback, context) + { + return this.fadeEffect.start(true, duration, red, green, blue, true, callback, context); + }, + + /** + * Fades the Camera from the given color to transparent over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Camera#fadeFrom + * @fires Phaser.Cameras.Scene2D.Events#FADE_IN_START + * @fires Phaser.Cameras.Scene2D.Events#FADE_IN_COMPLETE + * @since 3.5.0 + * + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {number} [red=0] - The amount to fade the red channel towards. A value between 0 and 255. + * @param {number} [green=0] - The amount to fade the green channel towards. A value between 0 and 255. + * @param {number} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255. + * @param {boolean} [force=false] - Force the effect to start immediately, even if already running. + * @param {function} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + fadeFrom: function (duration, red, green, blue, force, callback, context) + { + return this.fadeEffect.start(false, duration, red, green, blue, force, callback, context); + }, + + /** + * Fades the Camera from transparent to the given color over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Camera#fade + * @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_START + * @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_COMPLETE + * @since 3.0.0 + * + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {number} [red=0] - The amount to fade the red channel towards. A value between 0 and 255. + * @param {number} [green=0] - The amount to fade the green channel towards. A value between 0 and 255. + * @param {number} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255. + * @param {boolean} [force=false] - Force the effect to start immediately, even if already running. + * @param {function} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + fade: function (duration, red, green, blue, force, callback, context) + { + return this.fadeEffect.start(true, duration, red, green, blue, force, callback, context); + }, + + /** + * Flashes the Camera by setting it to the given color immediately and then fading it away again quickly over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Camera#flash + * @fires Phaser.Cameras.Scene2D.Events#FLASH_START + * @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE + * @since 3.0.0 + * + * @param {number} [duration=250] - The duration of the effect in milliseconds. + * @param {number} [red=255] - The amount to fade the red channel towards. A value between 0 and 255. + * @param {number} [green=255] - The amount to fade the green channel towards. A value between 0 and 255. + * @param {number} [blue=255] - The amount to fade the blue channel towards. A value between 0 and 255. + * @param {boolean} [force=false] - Force the effect to start immediately, even if already running. + * @param {function} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + flash: function (duration, red, green, blue, force, callback, context) + { + return this.flashEffect.start(duration, red, green, blue, force, callback, context); + }, + + /** + * Shakes the Camera by the given intensity over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Camera#shake + * @fires Phaser.Cameras.Scene2D.Events#SHAKE_START + * @fires Phaser.Cameras.Scene2D.Events#SHAKE_COMPLETE + * @since 3.0.0 + * + * @param {number} [duration=100] - The duration of the effect in milliseconds. + * @param {(number|Phaser.Math.Vector2)} [intensity=0.05] - The intensity of the shake. + * @param {boolean} [force=false] - Force the shake effect to start immediately, even if already running. + * @param {function} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + shake: function (duration, intensity, force, callback, context) + { + return this.shakeEffect.start(duration, intensity, force, callback, context); + }, + + /** + * This effect will scroll the Camera so that the center of its viewport finishes at the given destination, + * over the duration and with the ease specified. + * + * @method Phaser.Cameras.Scene2D.Camera#pan + * @fires Phaser.Cameras.Scene2D.Events#PAN_START + * @fires Phaser.Cameras.Scene2D.Events#PAN_COMPLETE + * @since 3.11.0 + * + * @param {number} x - The destination x coordinate to scroll the center of the Camera viewport to. + * @param {number} y - The destination y coordinate to scroll the center of the Camera viewport to. + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {(string|function)} [ease='Linear'] - The ease to use for the pan. Can be any of the Phaser Easing constants or a custom function. + * @param {boolean} [force=false] - Force the pan effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraPanCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is, + * the current camera scroll x coordinate and the current camera scroll y coordinate. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + pan: function (x, y, duration, ease, force, callback, context) + { + return this.panEffect.start(x, y, duration, ease, force, callback, context); + }, + + /** + * This effect will rotate the Camera so that the viewport finishes at the given angle in radians, + * over the duration and with the ease specified. + * + * @method Phaser.Cameras.Scene2D.Camera#rotateTo + * @since 3.23.0 + * + * @param {number} radians - The destination angle in radians to rotate the Camera viewport to. If the angle is positive then the rotation is clockwise else anticlockwise + * @param {boolean} [shortestPath=false] - If shortest path is set to true the camera will rotate in the quickest direction clockwise or anti-clockwise. + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {(string|function)} [ease='Linear'] - The ease to use for the rotation. Can be any of the Phaser Easing constants or a custom function. + * @param {boolean} [force=false] - Force the rotation effect to start immediately, even if already running. + * @param {CameraRotateCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is, + * the current camera rotation angle in radians. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} This Camera instance. + */ + rotateTo: function (radians, shortestPath, duration, ease, force, callback, context) + { + return this.rotateToEffect.start(radians, shortestPath, duration, ease, force, callback, context); + }, + + /** + * This effect will zoom the Camera to the given scale, over the duration and with the ease specified. + * + * @method Phaser.Cameras.Scene2D.Camera#zoomTo + * @fires Phaser.Cameras.Scene2D.Events#ZOOM_START + * @fires Phaser.Cameras.Scene2D.Events#ZOOM_COMPLETE + * @since 3.11.0 + * + * @param {number} zoom - The target Camera zoom value. + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {(string|function)} [ease='Linear'] - The ease to use for the pan. Can be any of the Phaser Easing constants or a custom function. + * @param {boolean} [force=false] - Force the pan effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraPanCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is, + * the current camera scroll x coordinate and the current camera scroll y coordinate. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {this} This Camera instance. + */ + zoomTo: function (zoom, duration, ease, force, callback, context) + { + return this.zoomEffect.start(zoom, duration, ease, force, callback, context); + }, + + /** + * Internal preRender step. + * + * @method Phaser.Cameras.Scene2D.Camera#preRender + * @protected + * @since 3.0.0 + */ + preRender: function () + { + this.renderList.length = 0; + + var width = this.width; + var height = this.height; + + var halfWidth = width * 0.5; + var halfHeight = height * 0.5; + + var zoomX = this.zoomX; + var zoomY = this.zoomY; + + this.renderRoundPixels = (this.roundPixels && Number.isInteger(zoomX) && Number.isInteger(zoomY)); + + var originX = width * this.originX; + var originY = height * this.originY; + + var follow = this._follow; + var deadzone = this.deadzone; + + var sx = this.scrollX; + var sy = this.scrollY; + + if (deadzone) + { + CenterOn(deadzone, this.midPoint.x, this.midPoint.y); + } + + var emitFollowEvent = false; + + if (follow && !this.panEffect.isRunning) + { + var lerp = this.lerp; + + var fx = follow.x - this.followOffset.x; + var fy = follow.y - this.followOffset.y; + + if (deadzone) + { + if (fx < deadzone.x) + { + sx = Linear(sx, sx - (deadzone.x - fx), lerp.x); + } + else if (fx > deadzone.right) + { + sx = Linear(sx, sx + (fx - deadzone.right), lerp.x); + } + + if (fy < deadzone.y) + { + sy = Linear(sy, sy - (deadzone.y - fy), lerp.y); + } + else if (fy > deadzone.bottom) + { + sy = Linear(sy, sy + (fy - deadzone.bottom), lerp.y); + } + } + else + { + sx = Linear(sx, fx - originX, lerp.x); + sy = Linear(sy, fy - originY, lerp.y); + } + + emitFollowEvent = true; + } + + if (this.useBounds) + { + sx = this.clampX(sx); + sy = this.clampY(sy); + } + + // Values are in pixels and not impacted by zooming the Camera + this.scrollX = sx; + this.scrollY = sy; + + var midX = sx + halfWidth; + var midY = sy + halfHeight; + + // The center of the camera, in world space, so taking zoom into account + // Basically the pixel value of what it's looking at in the middle of the cam + this.midPoint.set(midX, midY); + + var displayWidth = width / zoomX; + var displayHeight = height / zoomY; + + var vwx = midX - (displayWidth / 2); + var vwy = midY - (displayHeight / 2); + + this.worldView.setTo(vwx, vwy, displayWidth, displayHeight); + + var matrix = this.matrix; + var matrixExternal = this.matrixExternal; + + // Apply view transforms in order IRST. + matrix.applyITRS(originX, originY, this.rotation, zoomX, zoomY); + matrix.translate(-sx - originX, -sy - originY); + + matrixExternal.applyITRS(this.x, this.y, 0, 1, 1); + + matrixExternal.multiply(matrix, this.matrixCombined); + + this.shakeEffect.preRender(); + + if (emitFollowEvent) + { + this.emit(Events.FOLLOW_UPDATE, this, follow); + } + }, + + /** + * Returns the view matrix of the camera. This is used internally. + * + * This is `matrix` if the camera is intended to render to a framebuffer, + * and `matrixCombined` otherwise. + * + * @method Phaser.Cameras.Scene2D.Camera#getViewMatrix + * @webglonly + * @since 4.0.0 + * @param {boolean} [forceComposite=false] - If `true`, the view matrix will always be `matrix`. This is typically used when rendering to a framebuffer, so the external matrix is irrelevant. + * @returns {Phaser.GameObjects.Components.TransformMatrix} The view matrix of the camera. + */ + getViewMatrix: function (forceComposite) + { + if ( + forceComposite || this.forceComposite || + this.filters.external.length > 0 || + this.filters.internal.length > 0 + ) + { + return this.matrix; + } + else + { + return this.matrixCombined; + } + }, + + /** + * Sets the linear interpolation value to use when following a target. + * + * The default values of 1 means the camera will instantly snap to the target coordinates. + * A lower value, such as 0.1 means the camera will more slowly track the target, giving + * a smooth transition. You can set the horizontal and vertical values independently, and also + * adjust this value in real-time during your game. + * + * Be sure to keep the value between 0 and 1. A value of zero will disable tracking on that axis. + * + * @method Phaser.Cameras.Scene2D.Camera#setLerp + * @since 3.9.0 + * + * @param {number} [x=1] - The amount added to the horizontal linear interpolation of the follow target. + * @param {number} [y=1] - The amount added to the vertical linear interpolation of the follow target. + * + * @return {this} This Camera instance. + */ + setLerp: function (x, y) + { + if (x === undefined) { x = 1; } + if (y === undefined) { y = x; } + + this.lerp.set(x, y); + + return this; + }, + + /** + * Sets the horizontal and vertical offset of the camera from its follow target. + * The values are subtracted from the targets position during the Cameras update step. + * + * @method Phaser.Cameras.Scene2D.Camera#setFollowOffset + * @since 3.9.0 + * + * @param {number} [x=0] - The horizontal offset from the camera follow target.x position. + * @param {number} [y=0] - The vertical offset from the camera follow target.y position. + * + * @return {this} This Camera instance. + */ + setFollowOffset: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + this.followOffset.set(x, y); + + return this; + }, + + /** + * Sets the Camera to follow a Game Object. + * + * When enabled the Camera will automatically adjust its scroll position to keep the target Game Object + * in its center. + * + * You can set the linear interpolation value used in the follow code. + * Use low lerp values (such as 0.1) to automatically smooth the camera motion. + * + * If you find you're getting a slight "jitter" effect when following an object it's probably to do with sub-pixel + * rendering of the targets position. This can be rounded by setting the `roundPixels` argument to `true` to + * force full pixel rounding rendering. Note that this can still be broken if you have specified a non-integer zoom + * value on the camera. So be sure to keep the camera zoom to integers. + * + * @method Phaser.Cameras.Scene2D.Camera#startFollow + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|object)} target - The target for the Camera to follow. + * @param {boolean} [roundPixels=false] - Round the camera position to whole integers to avoid sub-pixel rendering? + * @param {number} [lerpX=1] - A value between 0 and 1. This value specifies the amount of linear interpolation to use when horizontally tracking the target. The closer the value to 1, the faster the camera will track. + * @param {number} [lerpY=1] - A value between 0 and 1. This value specifies the amount of linear interpolation to use when vertically tracking the target. The closer the value to 1, the faster the camera will track. + * @param {number} [offsetX=0] - The horizontal offset from the camera follow target.x position. + * @param {number} [offsetY=0] - The vertical offset from the camera follow target.y position. + * + * @return {this} This Camera instance. + */ + startFollow: function (target, roundPixels, lerpX, lerpY, offsetX, offsetY) + { + if (roundPixels === undefined) { roundPixels = false; } + if (lerpX === undefined) { lerpX = 1; } + if (lerpY === undefined) { lerpY = lerpX; } + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = offsetX; } + + this._follow = target; + + this.roundPixels = roundPixels; + + lerpX = Clamp(lerpX, 0, 1); + lerpY = Clamp(lerpY, 0, 1); + + this.lerp.set(lerpX, lerpY); + + this.followOffset.set(offsetX, offsetY); + + var originX = this.width / 2; + var originY = this.height / 2; + + var fx = target.x - offsetX; + var fy = target.y - offsetY; + + this.midPoint.set(fx, fy); + + this.scrollX = fx - originX; + this.scrollY = fy - originY; + + if (this.useBounds) + { + this.scrollX = this.clampX(this.scrollX); + this.scrollY = this.clampY(this.scrollY); + } + + return this; + }, + + /** + * Stops a Camera from following a Game Object, if previously set via `Camera.startFollow`. + * + * @method Phaser.Cameras.Scene2D.Camera#stopFollow + * @since 3.0.0 + * + * @return {this} This Camera instance. + */ + stopFollow: function () + { + this._follow = null; + + return this; + }, + + /** + * Resets any active FX, such as a fade, flash or shake. Useful to call after a fade in order to + * remove the fade. + * + * @method Phaser.Cameras.Scene2D.Camera#resetFX + * @since 3.0.0 + * + * @return {this} This Camera instance. + */ + resetFX: function () + { + this.rotateToEffect.reset(); + this.panEffect.reset(); + this.shakeEffect.reset(); + this.flashEffect.reset(); + this.fadeEffect.reset(); + + return this; + }, + + /** + * Internal method called automatically by the Camera Manager. + * + * @method Phaser.Cameras.Scene2D.Camera#update + * @protected + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (this.visible) + { + this.rotateToEffect.update(time, delta); + this.panEffect.update(time, delta); + this.zoomEffect.update(time, delta); + this.shakeEffect.update(time, delta); + this.flashEffect.update(time, delta); + this.fadeEffect.update(time, delta); + } + }, + + /** + * Destroys this Camera instance. You rarely need to call this directly. + * + * Called by the Camera Manager. If you wish to destroy a Camera please use `CameraManager.remove` as + * cameras are stored in a pool, ready for recycling later, and calling this directly will prevent that. + * + * @method Phaser.Cameras.Scene2D.Camera#destroy + * @fires Phaser.Cameras.Scene2D.Events#DESTROY + * @since 3.0.0 + */ + destroy: function () + { + this.resetFX(); + + this.filters.internal.destroy(); + this.filters.external.destroy(); + + BaseCamera.prototype.destroy.call(this); + + this._follow = null; + + this.deadzone = null; + } + +}); + +module.exports = Camera; + + +/***/ }), + +/***/ 32743: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Camera = __webpack_require__(38058); +var Class = __webpack_require__(83419); +var GetFastValue = __webpack_require__(95540); +var PluginCache = __webpack_require__(37277); +var RectangleContains = __webpack_require__(37303); +var ScaleEvents = __webpack_require__(97480); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * The Camera Manager is a plugin that belongs to a Scene and is responsible for managing all of the Scene Cameras. + * + * By default you can access the Camera Manager from within a Scene using `this.cameras`, although this can be changed + * in your game config. + * + * Create new Cameras using the `add` method. Or extend the Camera class with your own addition code and then add + * the new Camera in using the `addExisting` method. + * + * Cameras provide a view into your game world, and can be positioned, rotated, zoomed and scrolled accordingly. + * + * A Camera consists of two elements: The viewport and the scroll values. + * + * The viewport is the physical position and size of the Camera within your game. Cameras, by default, are + * created the same size as your game, but their position and size can be set to anything. This means if you + * wanted to create a camera that was 320x200 in size, positioned in the bottom-right corner of your game, + * you'd adjust the viewport to do that (using methods like `setViewport` and `setSize`). + * + * If you wish to change where the Camera is looking in your game, then you scroll it. You can do this + * via the properties `scrollX` and `scrollY` or the method `setScroll`. Scrolling has no impact on the + * viewport, and changing the viewport has no impact on the scrolling. + * + * By default a Camera will render all Game Objects it can see. You can change this using the `ignore` method, + * allowing you to filter Game Objects out on a per-Camera basis. The Camera Manager can manage up to 31 unique + * 'Game Object ignore capable' Cameras. Any Cameras beyond 31 that you create will all be given a Camera ID of + * zero, meaning that they cannot be used for Game Object exclusion. This means if you need your Camera to ignore + * Game Objects, make sure it's one of the first 31 created. + * + * A Camera also has built-in special effects including Fade, Flash, Camera Shake, Pan and Zoom. + * + * @class CameraManager + * @memberof Phaser.Cameras.Scene2D + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that owns the Camera Manager plugin. + */ +var CameraManager = new Class({ + + initialize: + + function CameraManager (scene) + { + /** + * The Scene that owns the Camera Manager plugin. + * + * @name Phaser.Cameras.Scene2D.CameraManager#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene.Systems handler for the Scene that owns the Camera Manager. + * + * @name Phaser.Cameras.Scene2D.CameraManager#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * All Cameras created by, or added to, this Camera Manager, will have their `roundPixels` + * property set to match this value. By default it is set to match the value set in the + * game configuration, but can be changed at any point. Equally, individual cameras can + * also be changed as needed. + * + * @name Phaser.Cameras.Scene2D.CameraManager#roundPixels + * @type {boolean} + * @since 3.11.0 + */ + this.roundPixels = scene.sys.game.config.roundPixels; + + /** + * An Array of the Camera objects being managed by this Camera Manager. + * The Cameras are updated and rendered in the same order in which they appear in this array. + * Do not directly add or remove entries to this array. However, you can move the contents + * around the array should you wish to adjust the display order. + * + * @name Phaser.Cameras.Scene2D.CameraManager#cameras + * @type {Phaser.Cameras.Scene2D.Camera[]} + * @since 3.0.0 + */ + this.cameras = []; + + /** + * A handy reference to the 'main' camera. By default this is the first Camera the + * Camera Manager creates. You can also set it directly, or use the `makeMain` argument + * in the `add` and `addExisting` methods. It allows you to access it from your game: + * + * ```javascript + * var cam = this.cameras.main; + * ``` + * + * Also see the properties `camera1`, `camera2` and so on. + * + * @name Phaser.Cameras.Scene2D.CameraManager#main + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 3.0.0 + */ + this.main; + + /** + * A default un-transformed Camera that doesn't exist on the camera list and doesn't + * count towards the total number of cameras being managed. It exists for other + * systems, as well as your own code, should they require a basic un-transformed + * camera instance from which to calculate a view matrix. + * + * @name Phaser.Cameras.Scene2D.CameraManager#default + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 3.17.0 + */ + this.default; + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Cameras.Scene2D.CameraManager#boot + * @private + * @listens Phaser.Scenes.Events#DESTROY + * @since 3.5.1 + */ + boot: function () + { + var sys = this.systems; + + if (sys.settings.cameras) + { + // We have cameras to create + this.fromJSON(sys.settings.cameras); + } + else + { + // Make one + this.add(); + } + + this.main = this.cameras[0]; + + // Create a default camera + this.default = new Camera(0, 0, sys.scale.width, sys.scale.height).setScene(this.scene); + + sys.game.scale.on(ScaleEvents.RESIZE, this.onResize, this); + + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Cameras.Scene2D.CameraManager#start + * @private + * @listens Phaser.Scenes.Events#UPDATE + * @listens Phaser.Scenes.Events#SHUTDOWN + * @since 3.5.0 + */ + start: function () + { + if (!this.main) + { + var sys = this.systems; + + if (sys.settings.cameras) + { + // We have cameras to create + this.fromJSON(sys.settings.cameras); + } + else + { + // Make one + this.add(); + } + + this.main = this.cameras[0]; + } + + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.UPDATE, this.update, this); + eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Adds a new Camera into the Camera Manager. The Camera Manager can support up to 31 different Cameras. + * + * Each Camera has its own viewport, which controls the size of the Camera and its position within the canvas. + * + * Use the `Camera.scrollX` and `Camera.scrollY` properties to change where the Camera is looking, or the + * Camera methods such as `centerOn`. Cameras also have built in special effects, such as fade, flash, shake, + * pan and zoom. + * + * By default Cameras are transparent and will render anything that they can see based on their `scrollX` + * and `scrollY` values. Game Objects can be set to be ignored by a Camera by using the `Camera.ignore` method. + * + * The Camera will have its `roundPixels` property set to whatever `CameraManager.roundPixels` is. You can change + * it after creation if required. + * + * See the Camera class documentation for more details. + * + * @method Phaser.Cameras.Scene2D.CameraManager#add + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal position of the Camera viewport. + * @param {number} [y=0] - The vertical position of the Camera viewport. + * @param {number} [width] - The width of the Camera viewport. If not given it'll be the game config size. + * @param {number} [height] - The height of the Camera viewport. If not given it'll be the game config size. + * @param {boolean} [makeMain=false] - Set this Camera as being the 'main' camera. This just makes the property `main` a reference to it. + * @param {string} [name=''] - The name of the Camera. + * + * @return {Phaser.Cameras.Scene2D.Camera} The newly created Camera. + */ + add: function (x, y, width, height, makeMain, name) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.scene.sys.scale.width; } + if (height === undefined) { height = this.scene.sys.scale.height; } + if (makeMain === undefined) { makeMain = false; } + if (name === undefined) { name = ''; } + + var camera = new Camera(x, y, width, height); + + camera.setName(name); + camera.setScene(this.scene); + camera.setRoundPixels(this.roundPixels); + + camera.id = this.getNextID(); + + this.cameras.push(camera); + + if (makeMain) + { + this.main = camera; + } + + return camera; + }, + + /** + * Adds an existing Camera into the Camera Manager. + * + * The Camera should either be a `Phaser.Cameras.Scene2D.Camera` instance, or a class that extends from it. + * + * The Camera will have its `roundPixels` property set to whatever `CameraManager.roundPixels` is. You can change + * it after addition if required. + * + * The Camera will be assigned an ID, which is used for Game Object exclusion and then added to the + * manager. As long as it doesn't already exist in the manager it will be added then returned. + * + * If this method returns `null` then the Camera already exists in this Camera Manager. + * + * @method Phaser.Cameras.Scene2D.CameraManager#addExisting + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to be added to the Camera Manager. + * @param {boolean} [makeMain=false] - Set this Camera as being the 'main' camera. This just makes the property `main` a reference to it. + * + * @return {?Phaser.Cameras.Scene2D.Camera} The Camera that was added to the Camera Manager, or `null` if it couldn't be added. + */ + addExisting: function (camera, makeMain) + { + if (makeMain === undefined) { makeMain = false; } + + var index = this.cameras.indexOf(camera); + + if (index === -1) + { + camera.id = this.getNextID(); + + camera.setRoundPixels(this.roundPixels); + + this.cameras.push(camera); + + if (makeMain) + { + this.main = camera; + } + + return camera; + } + + return null; + }, + + /** + * Gets the next available Camera ID number. + * + * The Camera Manager supports up to 31 unique cameras, after which the ID returned will always be zero. + * You can create additional cameras beyond 31, but they cannot be used for Game Object exclusion. + * + * @method Phaser.Cameras.Scene2D.CameraManager#getNextID + * @private + * @since 3.11.0 + * + * @return {number} The next available Camera ID, or 0 if they're all already in use. + */ + getNextID: function () + { + var cameras = this.cameras; + + var testID = 1; + + // Find the first free camera ID we can use + + for (var t = 0; t < 32; t++) + { + var found = false; + + for (var i = 0; i < cameras.length; i++) + { + var camera = cameras[i]; + + if (camera && camera.id === testID) + { + found = true; + continue; + } + } + + if (found) + { + testID = testID << 1; + } + else + { + return testID; + } + } + + return 0; + }, + + /** + * Gets the total number of Cameras in this Camera Manager. + * + * If the optional `isVisible` argument is set it will only count Cameras that are currently visible. + * + * @method Phaser.Cameras.Scene2D.CameraManager#getTotal + * @since 3.11.0 + * + * @param {boolean} [isVisible=false] - Set the `true` to only include visible Cameras in the total. + * + * @return {number} The total number of Cameras in this Camera Manager. + */ + getTotal: function (isVisible) + { + if (isVisible === undefined) { isVisible = false; } + + var total = 0; + + var cameras = this.cameras; + + for (var i = 0; i < cameras.length; i++) + { + var camera = cameras[i]; + + if (!isVisible || (isVisible && camera.visible)) + { + total++; + } + } + + return total; + }, + + /** + * Populates this Camera Manager based on the given configuration object, or an array of config objects. + * + * See the `Phaser.Types.Cameras.Scene2D.CameraConfig` documentation for details of the object structure. + * + * @method Phaser.Cameras.Scene2D.CameraManager#fromJSON + * @since 3.0.0 + * + * @param {(Phaser.Types.Cameras.Scene2D.CameraConfig|Phaser.Types.Cameras.Scene2D.CameraConfig[])} config - A Camera configuration object, or an array of them, to be added to this Camera Manager. + * + * @return {this} This Camera Manager instance. + */ + fromJSON: function (config) + { + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var gameWidth = this.scene.sys.scale.width; + var gameHeight = this.scene.sys.scale.height; + + for (var i = 0; i < config.length; i++) + { + var cameraConfig = config[i]; + + var x = GetFastValue(cameraConfig, 'x', 0); + var y = GetFastValue(cameraConfig, 'y', 0); + var width = GetFastValue(cameraConfig, 'width', gameWidth); + var height = GetFastValue(cameraConfig, 'height', gameHeight); + + var camera = this.add(x, y, width, height); + + // Direct properties + camera.name = GetFastValue(cameraConfig, 'name', ''); + camera.zoom = GetFastValue(cameraConfig, 'zoom', 1); + camera.rotation = GetFastValue(cameraConfig, 'rotation', 0); + camera.scrollX = GetFastValue(cameraConfig, 'scrollX', 0); + camera.scrollY = GetFastValue(cameraConfig, 'scrollY', 0); + camera.roundPixels = GetFastValue(cameraConfig, 'roundPixels', false); + camera.visible = GetFastValue(cameraConfig, 'visible', true); + + // Background Color + + var backgroundColor = GetFastValue(cameraConfig, 'backgroundColor', false); + + if (backgroundColor) + { + camera.setBackgroundColor(backgroundColor); + } + + // Bounds + + var boundsConfig = GetFastValue(cameraConfig, 'bounds', null); + + if (boundsConfig) + { + var bx = GetFastValue(boundsConfig, 'x', 0); + var by = GetFastValue(boundsConfig, 'y', 0); + var bwidth = GetFastValue(boundsConfig, 'width', gameWidth); + var bheight = GetFastValue(boundsConfig, 'height', gameHeight); + + camera.setBounds(bx, by, bwidth, bheight); + } + } + + return this; + }, + + /** + * Gets a Camera based on its name. + * + * Camera names are optional and don't have to be set, so this method is only of any use if you + * have given your Cameras unique names. + * + * @method Phaser.Cameras.Scene2D.CameraManager#getCamera + * @since 3.0.0 + * + * @param {string} name - The name of the Camera. + * + * @return {?Phaser.Cameras.Scene2D.Camera} The first Camera with a name matching the given string, otherwise `null`. + */ + getCamera: function (name) + { + var cameras = this.cameras; + + for (var i = 0; i < cameras.length; i++) + { + if (cameras[i].name === name) + { + return cameras[i]; + } + } + + return null; + }, + + /** + * Returns an array of all cameras below the given Pointer. + * + * The first camera in the array is the top-most camera in the camera list. + * + * @method Phaser.Cameras.Scene2D.CameraManager#getCamerasBelowPointer + * @since 3.10.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to check against. + * + * @return {Phaser.Cameras.Scene2D.Camera[]} An array of cameras below the Pointer. + */ + getCamerasBelowPointer: function (pointer) + { + var cameras = this.cameras; + + var x = pointer.x; + var y = pointer.y; + + var output = []; + + for (var i = 0; i < cameras.length; i++) + { + var camera = cameras[i]; + + if (camera.visible && camera.inputEnabled && RectangleContains(camera, x, y)) + { + // So the top-most camera is at the top of the search array + output.unshift(camera); + } + } + + return output; + }, + + /** + * Removes the given Camera, or an array of Cameras, from this Camera Manager. + * + * If found in the Camera Manager it will be immediately removed from the local cameras array. + * If also currently the 'main' camera, 'main' will be reset to be camera 0. + * + * The removed Cameras are automatically destroyed if the `runDestroy` argument is `true`, which is the default. + * If you wish to re-use the cameras then set this to `false`, but know that they will retain their references + * and internal data until destroyed or re-added to a Camera Manager. + * + * @method Phaser.Cameras.Scene2D.CameraManager#remove + * @since 3.0.0 + * + * @param {(Phaser.Cameras.Scene2D.Camera|Phaser.Cameras.Scene2D.Camera[])} camera - The Camera, or an array of Cameras, to be removed from this Camera Manager. + * @param {boolean} [runDestroy=true] - Automatically call `Camera.destroy` on each Camera removed from this Camera Manager. + * + * @return {number} The total number of Cameras removed. + */ + remove: function (camera, runDestroy) + { + if (runDestroy === undefined) { runDestroy = true; } + + if (!Array.isArray(camera)) + { + camera = [ camera ]; + } + + var total = 0; + var cameras = this.cameras; + + for (var i = 0; i < camera.length; i++) + { + var index = cameras.indexOf(camera[i]); + + if (index !== -1) + { + if (runDestroy) + { + cameras[index].destroy(); + } + else + { + cameras[index].renderList = []; + } + + cameras.splice(index, 1); + + total++; + } + } + + if (!this.main && cameras[0]) + { + this.main = cameras[0]; + } + + return total; + }, + + /** + * The internal render method. This is called automatically by the Scene and should not be invoked directly. + * + * It will iterate through all local cameras and render them in turn, as long as they're visible and have + * an alpha level > 0. + * + * @method Phaser.Cameras.Scene2D.CameraManager#render + * @protected + * @since 3.0.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The Renderer that will render the children to this camera. + * @param {Phaser.GameObjects.DisplayList} displayList - The Display List for the Scene. + */ + render: function (renderer, displayList) + { + var scene = this.scene; + var cameras = this.cameras; + + for (var i = 0; i < cameras.length; i++) + { + var camera = cameras[i]; + + if (camera.visible && camera.alpha > 0) + { + camera.preRender(); + + var visibleChildren = this.getVisibleChildren(displayList.getChildren(), camera); + + renderer.render(scene, visibleChildren, camera); + } + } + }, + + /** + * Takes an array of Game Objects and a Camera and returns a new array + * containing only those Game Objects that pass the `willRender` test + * against the given Camera. + * + * @method Phaser.Cameras.Scene2D.CameraManager#getVisibleChildren + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject[]} children - An array of Game Objects to be checked against the camera. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to filter the Game Objects against. + * + * @return {Phaser.GameObjects.GameObject[]} A filtered list of only Game Objects within the Scene that will render against the given Camera. + */ + getVisibleChildren: function (children, camera) + { + return children.filter(function (child) + { + return child.willRender(camera); + }); + }, + + /** + * Resets this Camera Manager. + * + * This will iterate through all current Cameras, destroying them all, then it will reset the + * cameras array, reset the ID counter and create 1 new single camera using the default values. + * + * @method Phaser.Cameras.Scene2D.CameraManager#resetAll + * @since 3.0.0 + * + * @return {Phaser.Cameras.Scene2D.Camera} The freshly created main Camera. + */ + resetAll: function () + { + for (var i = 0; i < this.cameras.length; i++) + { + this.cameras[i].destroy(); + } + + this.cameras = []; + + this.main = this.add(); + + return this.main; + }, + + /** + * The main update loop. Called automatically when the Scene steps. + * + * @method Phaser.Cameras.Scene2D.CameraManager#update + * @protected + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + for (var i = 0; i < this.cameras.length; i++) + { + this.cameras[i].update(time, delta); + } + }, + + /** + * The event handler that manages the `resize` event dispatched by the Scale Manager. + * + * @method Phaser.Cameras.Scene2D.CameraManager#onResize + * @since 3.18.0 + * + * @param {Phaser.Structs.Size} gameSize - The default Game Size object. This is the un-modified game dimensions. + * @param {Phaser.Structs.Size} baseSize - The base Size object. The game dimensions. The canvas width / height values match this. + */ + onResize: function (gameSize, baseSize, displaySize, previousWidth, previousHeight) + { + for (var i = 0; i < this.cameras.length; i++) + { + var cam = this.cameras[i]; + + // if camera is at 0x0 and was the size of the previous game size, then we can safely assume it + // should be updated to match the new game size too + + if (cam._x === 0 && cam._y === 0 && cam._width === previousWidth && cam._height === previousHeight) + { + cam.setSize(baseSize.width, baseSize.height); + } + } + }, + + /** + * Resizes all cameras to the given dimensions. + * + * @method Phaser.Cameras.Scene2D.CameraManager#resize + * @since 3.2.0 + * + * @param {number} width - The new width of the camera. + * @param {number} height - The new height of the camera. + */ + resize: function (width, height) + { + for (var i = 0; i < this.cameras.length; i++) + { + this.cameras[i].setSize(width, height); + } + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Cameras.Scene2D.CameraManager#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + this.main = undefined; + + for (var i = 0; i < this.cameras.length; i++) + { + this.cameras[i].destroy(); + } + + this.cameras = []; + + var eventEmitter = this.systems.events; + + eventEmitter.off(SceneEvents.UPDATE, this.update, this); + eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Cameras.Scene2D.CameraManager#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.default.destroy(); + + this.systems.events.off(SceneEvents.START, this.start, this); + this.systems.events.off(SceneEvents.DESTROY, this.destroy, this); + this.systems.game.scale.off(ScaleEvents.RESIZE, this.onResize, this); + + this.scene = null; + this.systems = null; + } + +}); + +PluginCache.register('CameraManager', CameraManager, 'cameras'); + +module.exports = CameraManager; + + +/***/ }), + +/***/ 5020: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(19715); + +/** + * @classdesc + * A Camera Fade effect. + * + * This effect will fade the camera viewport to the given color, over the duration specified. + * + * Only the camera viewport is faded. None of the objects it is displaying are impacted, i.e. their colors do + * not change. + * + * The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback, + * which is invoked each frame for the duration of the effect, if required. + * + * @class Fade + * @memberof Phaser.Cameras.Scene2D.Effects + * @constructor + * @since 3.5.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon. + */ +var Fade = new Class({ + + initialize: + + function Fade (camera) + { + /** + * The Camera this effect belongs to. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @readonly + * @since 3.5.0 + */ + this.camera = camera; + + /** + * Is this effect actively running? + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#isRunning + * @type {boolean} + * @readonly + * @default false + * @since 3.5.0 + */ + this.isRunning = false; + + /** + * Has this effect finished running? + * + * This is different from `isRunning` because it remains set to `true` when the effect is over, + * until the effect is either reset or started again. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#isComplete + * @type {boolean} + * @readonly + * @default false + * @since 3.5.0 + */ + this.isComplete = false; + + /** + * The direction of the fade. + * `true` = fade out (transparent to color), `false` = fade in (color to transparent) + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#direction + * @type {boolean} + * @readonly + * @since 3.5.0 + */ + this.direction = true; + + /** + * The duration of the effect, in milliseconds. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#duration + * @type {number} + * @readonly + * @default 0 + * @since 3.5.0 + */ + this.duration = 0; + + /** + * The value of the red color channel the camera will use for the fade effect. + * A value between 0 and 255. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#red + * @type {number} + * @private + * @since 3.5.0 + */ + this.red = 0; + + /** + * The value of the green color channel the camera will use for the fade effect. + * A value between 0 and 255. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#green + * @type {number} + * @private + * @since 3.5.0 + */ + this.green = 0; + + /** + * The value of the blue color channel the camera will use for the fade effect. + * A value between 0 and 255. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#blue + * @type {number} + * @private + * @since 3.5.0 + */ + this.blue = 0; + + /** + * The value of the alpha channel used during the fade effect. + * A value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#alpha + * @type {number} + * @private + * @since 3.5.0 + */ + this.alpha = 0; + + /** + * If this effect is running this holds the current percentage of the progress, a value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#progress + * @type {number} + * @since 3.5.0 + */ + this.progress = 0; + + /** + * Effect elapsed timer. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#_elapsed + * @type {number} + * @private + * @since 3.5.0 + */ + this._elapsed = 0; + + /** + * This callback is invoked every frame for the duration of the effect. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#_onUpdate + * @type {?Phaser.Types.Cameras.Scene2D.CameraFadeCallback} + * @private + * @default null + * @since 3.5.0 + */ + this._onUpdate; + + /** + * On Complete callback scope. + * + * @name Phaser.Cameras.Scene2D.Effects.Fade#_onUpdateScope + * @type {any} + * @private + * @since 3.5.0 + */ + this._onUpdateScope; + }, + + /** + * Fades the Camera to or from the given color over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#start + * @fires Phaser.Cameras.Scene2D.Events#FADE_IN_START + * @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_START + * @since 3.5.0 + * + * @param {boolean} [direction=true] - The direction of the fade. `true` = fade out (transparent to color), `false` = fade in (color to transparent) + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {number} [red=0] - The amount to fade the red channel towards. A value between 0 and 255. + * @param {number} [green=0] - The amount to fade the green channel towards. A value between 0 and 255. + * @param {number} [blue=0] - The amount to fade the blue channel towards. A value between 0 and 255. + * @param {boolean} [force=false] - Force the effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraFadeCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started. + */ + start: function (direction, duration, red, green, blue, force, callback, context) + { + if (direction === undefined) { direction = true; } + if (duration === undefined) { duration = 1000; } + if (red === undefined) { red = 0; } + if (green === undefined) { green = 0; } + if (blue === undefined) { blue = 0; } + if (force === undefined) { force = false; } + if (callback === undefined) { callback = null; } + if (context === undefined) { context = this.camera.scene; } + + if (!force && this.isRunning) + { + return this.camera; + } + + this.isRunning = true; + this.isComplete = false; + this.duration = duration; + this.direction = direction; + this.progress = 0; + + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = (direction) ? Number.MIN_VALUE : 1; + + this._elapsed = 0; + + this._onUpdate = callback; + this._onUpdateScope = context; + + var eventName = (direction) ? Events.FADE_OUT_START : Events.FADE_IN_START; + + this.camera.emit(eventName, this.camera, this, duration, red, green, blue); + + return this.camera; + }, + + /** + * The main update loop for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#update + * @since 3.5.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (!this.isRunning) + { + return; + } + + this._elapsed += delta; + + this.progress = Clamp(this._elapsed / this.duration, 0, 1); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, this.camera, this.progress); + } + + if (this._elapsed < this.duration) + { + this.alpha = (this.direction) ? this.progress : 1 - this.progress; + } + else + { + this.alpha = (this.direction) ? 1 : 0; + this.effectComplete(); + } + }, + + /** + * Called internally by the Canvas Renderer. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderCanvas + * @since 3.5.0 + * + * @param {CanvasRenderingContext2D} ctx - The Canvas context to render to. + * + * @return {boolean} `true` if the effect drew to the renderer, otherwise `false`. + */ + postRenderCanvas: function (ctx) + { + if (!this.isRunning && !this.isComplete) + { + return false; + } + + var camera = this.camera; + + ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')'; + ctx.fillRect(camera.x, camera.y, camera.width, camera.height); + + return true; + }, + + /** + * Called internally by the WebGL Renderer. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#postRenderWebGL + * @since 3.5.0 + * + * @return {boolean} `true` if the effect should draw to the renderer, otherwise `false`. + */ + postRenderWebGL: function () + { + return this.isRunning || this.isComplete; + }, + + /** + * Called internally when the effect completes. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#effectComplete + * @fires Phaser.Cameras.Scene2D.Events#FADE_IN_COMPLETE + * @fires Phaser.Cameras.Scene2D.Events#FADE_OUT_COMPLETE + * @since 3.5.0 + */ + effectComplete: function () + { + this._onUpdate = null; + this._onUpdateScope = null; + + this.isRunning = false; + this.isComplete = true; + + var eventName = (this.direction) ? Events.FADE_OUT_COMPLETE : Events.FADE_IN_COMPLETE; + + this.camera.emit(eventName, this.camera, this); + }, + + /** + * Resets this camera effect. + * If it was previously running, it stops instantly without calling its onComplete callback or emitting an event. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#reset + * @since 3.5.0 + */ + reset: function () + { + this.isRunning = false; + this.isComplete = false; + + this._onUpdate = null; + this._onUpdateScope = null; + }, + + /** + * Destroys this effect, releasing it from the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Fade#destroy + * @since 3.5.0 + */ + destroy: function () + { + this.reset(); + + this.camera = null; + } + +}); + +module.exports = Fade; + + +/***/ }), + +/***/ 10662: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(19715); + +/** + * @classdesc + * A Camera Flash effect. + * + * This effect will flash the camera viewport to the given color, over the duration specified. + * + * Only the camera viewport is flashed. None of the objects it is displaying are impacted, i.e. their colors do + * not change. + * + * The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback, + * which is invoked each frame for the duration of the effect, if required. + * + * @class Flash + * @memberof Phaser.Cameras.Scene2D.Effects + * @constructor + * @since 3.5.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon. + */ +var Flash = new Class({ + + initialize: + + function Flash (camera) + { + /** + * The Camera this effect belongs to. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @readonly + * @since 3.5.0 + */ + this.camera = camera; + + /** + * Is this effect actively running? + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#isRunning + * @type {boolean} + * @readonly + * @default false + * @since 3.5.0 + */ + this.isRunning = false; + + /** + * The duration of the effect, in milliseconds. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#duration + * @type {number} + * @readonly + * @default 0 + * @since 3.5.0 + */ + this.duration = 0; + + /** + * The value of the red color channel the camera will use for the flash effect. + * A value between 0 and 255. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#red + * @type {number} + * @private + * @since 3.5.0 + */ + this.red = 0; + + /** + * The value of the green color channel the camera will use for the flash effect. + * A value between 0 and 255. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#green + * @type {number} + * @private + * @since 3.5.0 + */ + this.green = 0; + + /** + * The value of the blue color channel the camera will use for the flash effect. + * A value between 0 and 255. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#blue + * @type {number} + * @private + * @since 3.5.0 + */ + this.blue = 0; + + /** + * The value of the alpha channel used during the flash effect. + * A value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#alpha + * @type {number} + * @since 3.5.0 + */ + this.alpha = 1; + + /** + * If this effect is running this holds the current percentage of the progress, a value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#progress + * @type {number} + * @since 3.5.0 + */ + this.progress = 0; + + /** + * Effect elapsed timer. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#_elapsed + * @type {number} + * @private + * @since 3.5.0 + */ + this._elapsed = 0; + + /** + * This is an internal copy of the initial value of `this.alpha`, used to calculate the current alpha value of the fade effect. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#_alpha + * @type {number} + * @private + * @readonly + * @since 3.60.0 + */ + this._alpha; + + /** + * This callback is invoked every frame for the duration of the effect. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#_onUpdate + * @type {?Phaser.Types.Cameras.Scene2D.CameraFlashCallback} + * @private + * @default null + * @since 3.5.0 + */ + this._onUpdate; + + /** + * On Complete callback scope. + * + * @name Phaser.Cameras.Scene2D.Effects.Flash#_onUpdateScope + * @type {any} + * @private + * @since 3.5.0 + */ + this._onUpdateScope; + }, + + /** + * Flashes the Camera to or from the given color over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#start + * @fires Phaser.Cameras.Scene2D.Events#FLASH_START + * @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE + * @since 3.5.0 + * + * @param {number} [duration=250] - The duration of the effect in milliseconds. + * @param {number} [red=255] - The amount to flash the red channel towards. A value between 0 and 255. + * @param {number} [green=255] - The amount to flash the green channel towards. A value between 0 and 255. + * @param {number} [blue=255] - The amount to flash the blue channel towards. A value between 0 and 255. + * @param {boolean} [force=false] - Force the effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraFlashCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started. + */ + start: function (duration, red, green, blue, force, callback, context) + { + if (duration === undefined) { duration = 250; } + if (red === undefined) { red = 255; } + if (green === undefined) { green = 255; } + if (blue === undefined) { blue = 255; } + if (force === undefined) { force = false; } + if (callback === undefined) { callback = null; } + if (context === undefined) { context = this.camera.scene; } + + if (!force && this.isRunning) + { + return this.camera; + } + + this.isRunning = true; + this.duration = duration; + this.progress = 0; + + this.red = red; + this.green = green; + this.blue = blue; + + this._alpha = this.alpha; + this._elapsed = 0; + + this._onUpdate = callback; + this._onUpdateScope = context; + + this.camera.emit(Events.FLASH_START, this.camera, this, duration, red, green, blue); + + return this.camera; + }, + + /** + * The main update loop for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#update + * @since 3.5.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (!this.isRunning) + { + return; + } + + this._elapsed += delta; + + this.progress = Clamp(this._elapsed / this.duration, 0, 1); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, this.camera, this.progress); + } + + if (this._elapsed < this.duration) + { + this.alpha = this._alpha * (1 - this.progress); + } + else + { + this.effectComplete(); + } + }, + + /** + * Called internally by the Canvas Renderer. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderCanvas + * @since 3.5.0 + * + * @param {CanvasRenderingContext2D} ctx - The Canvas context to render to. + * + * @return {boolean} `true` if the effect drew to the renderer, otherwise `false`. + */ + postRenderCanvas: function (ctx) + { + if (!this.isRunning) + { + return false; + } + + var camera = this.camera; + + ctx.fillStyle = 'rgba(' + this.red + ',' + this.green + ',' + this.blue + ',' + this.alpha + ')'; + ctx.fillRect(camera.x, camera.y, camera.width, camera.height); + + return true; + }, + + /** + * Called internally by the WebGL Renderer. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#postRenderWebGL + * @since 3.5.0 + * + * @return {boolean} `true` if the effect should draw to the renderer, otherwise `false`. + */ + postRenderWebGL: function () + { + return this.isRunning; + }, + + /** + * Called internally when the effect completes. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#effectComplete + * @fires Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE + * @since 3.5.0 + */ + effectComplete: function () + { + this.alpha = this._alpha; + this._onUpdate = null; + this._onUpdateScope = null; + + this.isRunning = false; + + this.camera.emit(Events.FLASH_COMPLETE, this.camera, this); + }, + + /** + * Resets this camera effect. + * If it was previously running, it stops instantly without calling its onComplete callback or emitting an event. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#reset + * @since 3.5.0 + */ + reset: function () + { + this.isRunning = false; + + this._onUpdate = null; + this._onUpdateScope = null; + }, + + /** + * Destroys this effect, releasing it from the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Flash#destroy + * @since 3.5.0 + */ + destroy: function () + { + this.reset(); + + this.camera = null; + } + +}); + +module.exports = Flash; + + +/***/ }), + +/***/ 20359: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var EaseMap = __webpack_require__(62640); +var Events = __webpack_require__(19715); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Camera Pan effect. + * + * This effect will scroll the Camera so that the center of its viewport finishes at the given destination, + * over the duration and with the ease specified. + * + * Only the camera scroll is moved. None of the objects it is displaying are impacted, i.e. their positions do + * not change. + * + * The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback, + * which is invoked each frame for the duration of the effect if required. + * + * @class Pan + * @memberof Phaser.Cameras.Scene2D.Effects + * @constructor + * @since 3.11.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon. + */ +var Pan = new Class({ + + initialize: + + function Pan (camera) + { + /** + * The Camera this effect belongs to. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @readonly + * @since 3.11.0 + */ + this.camera = camera; + + /** + * Is this effect actively running? + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#isRunning + * @type {boolean} + * @readonly + * @default false + * @since 3.11.0 + */ + this.isRunning = false; + + /** + * The duration of the effect, in milliseconds. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#duration + * @type {number} + * @readonly + * @default 0 + * @since 3.11.0 + */ + this.duration = 0; + + /** + * The starting scroll coordinates to pan the camera from. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#source + * @type {Phaser.Math.Vector2} + * @since 3.11.0 + */ + this.source = new Vector2(); + + /** + * The constantly updated value based on zoom. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#current + * @type {Phaser.Math.Vector2} + * @since 3.11.0 + */ + this.current = new Vector2(); + + /** + * The destination scroll coordinates to pan the camera to. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#destination + * @type {Phaser.Math.Vector2} + * @since 3.11.0 + */ + this.destination = new Vector2(); + + /** + * The ease function to use during the pan. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#ease + * @type {function} + * @since 3.11.0 + */ + this.ease; + + /** + * If this effect is running this holds the current percentage of the progress, a value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#progress + * @type {number} + * @since 3.11.0 + */ + this.progress = 0; + + /** + * Effect elapsed timer. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#_elapsed + * @type {number} + * @private + * @since 3.11.0 + */ + this._elapsed = 0; + + /** + * This callback is invoked every frame for the duration of the effect. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#_onUpdate + * @type {?Phaser.Types.Cameras.Scene2D.CameraPanCallback} + * @private + * @default null + * @since 3.11.0 + */ + this._onUpdate; + + /** + * On Complete callback scope. + * + * @name Phaser.Cameras.Scene2D.Effects.Pan#_onUpdateScope + * @type {any} + * @private + * @since 3.11.0 + */ + this._onUpdateScope; + }, + + /** + * This effect will scroll the Camera so that the center of its viewport finishes at the given destination, + * over the duration and with the ease specified. + * + * @method Phaser.Cameras.Scene2D.Effects.Pan#start + * @fires Phaser.Cameras.Scene2D.Events#PAN_START + * @fires Phaser.Cameras.Scene2D.Events#PAN_COMPLETE + * @since 3.11.0 + * + * @param {number} x - The destination x coordinate to scroll the center of the Camera viewport to. + * @param {number} y - The destination y coordinate to scroll the center of the Camera viewport to. + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {(string|function)} [ease='Linear'] - The ease to use for the pan. Can be any of the Phaser Easing constants or a custom function. + * @param {boolean} [force=false] - Force the pan effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraPanCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is, + * the current camera scroll x coordinate and the current camera scroll y coordinate. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started. + */ + start: function (x, y, duration, ease, force, callback, context) + { + if (duration === undefined) { duration = 1000; } + if (ease === undefined) { ease = EaseMap.Linear; } + if (force === undefined) { force = false; } + if (callback === undefined) { callback = null; } + if (context === undefined) { context = this.camera.scene; } + + var cam = this.camera; + + if (!force && this.isRunning) + { + return cam; + } + + this.isRunning = true; + this.duration = duration; + this.progress = 0; + + // Starting from + this.source.set(cam.scrollX, cam.scrollY); + + // Destination + this.destination.set(x, y); + + // Zoom factored version + cam.getScroll(x, y, this.current); + + // Using this ease + if (typeof ease === 'string' && EaseMap.hasOwnProperty(ease)) + { + this.ease = EaseMap[ease]; + } + else if (typeof ease === 'function') + { + this.ease = ease; + } + + this._elapsed = 0; + + this._onUpdate = callback; + this._onUpdateScope = context; + + this.camera.emit(Events.PAN_START, this.camera, this, duration, x, y); + + return cam; + }, + + /** + * The main update loop for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Pan#update + * @since 3.11.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (!this.isRunning) + { + return; + } + + this._elapsed += delta; + + var progress = Clamp(this._elapsed / this.duration, 0, 1); + + this.progress = progress; + + var cam = this.camera; + + if (this._elapsed < this.duration) + { + var v = this.ease(progress); + + cam.getScroll(this.destination.x, this.destination.y, this.current); + + var x = this.source.x + ((this.current.x - this.source.x) * v); + var y = this.source.y + ((this.current.y - this.source.y) * v); + + cam.setScroll(x, y); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, cam, progress, x, y); + } + } + else + { + cam.centerOn(this.destination.x, this.destination.y); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, cam, progress, cam.scrollX, cam.scrollY); + } + + this.effectComplete(); + } + }, + + /** + * Called internally when the effect completes. + * + * @method Phaser.Cameras.Scene2D.Effects.Pan#effectComplete + * @fires Phaser.Cameras.Scene2D.Events#PAN_COMPLETE + * @since 3.11.0 + */ + effectComplete: function () + { + this._onUpdate = null; + this._onUpdateScope = null; + + this.isRunning = false; + + this.camera.emit(Events.PAN_COMPLETE, this.camera, this); + }, + + /** + * Resets this camera effect. + * If it was previously running, it stops instantly without calling its onComplete callback or emitting an event. + * + * @method Phaser.Cameras.Scene2D.Effects.Pan#reset + * @since 3.11.0 + */ + reset: function () + { + this.isRunning = false; + + this._onUpdate = null; + this._onUpdateScope = null; + }, + + /** + * Destroys this effect, releasing it from the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Pan#destroy + * @since 3.11.0 + */ + destroy: function () + { + this.reset(); + + this.camera = null; + this.source = null; + this.destination = null; + } + +}); + +module.exports = Pan; + + +/***/ }), + +/***/ 34208: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Jason Nicholls + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(19715); +var EaseMap = __webpack_require__(62640); + +/** + * @classdesc + * A Camera Rotate effect. + * + * This effect will rotate the Camera so that the its viewport finishes at the given angle in radians, + * over the duration and with the ease specified. + * + * Camera rotation always takes place based on the Camera viewport. By default, rotation happens + * in the center of the viewport. You can adjust this with the `originX` and `originY` properties. + * + * Rotation influences the rendering of _all_ Game Objects visible by this Camera. However, it does not + * rotate the Camera viewport itself, which always remains an axis-aligned rectangle. + * + * Only the camera is rotates. None of the objects it is displaying are impacted, i.e. their positions do + * not change. + * + * The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback, + * which is invoked each frame for the duration of the effect if required. + * + * @class RotateTo + * @memberof Phaser.Cameras.Scene2D.Effects + * @constructor + * @since 3.23.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon. + */ +var RotateTo = new Class({ + + initialize: + + function RotateTo (camera) + { + /** + * The Camera this effect belongs to. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @readonly + * @since 3.23.0 + */ + this.camera = camera; + + /** + * Is this effect actively running? + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#isRunning + * @type {boolean} + * @readonly + * @default false + * @since 3.23.0 + */ + this.isRunning = false; + + /** + * The duration of the effect, in milliseconds. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#duration + * @type {number} + * @readonly + * @default 0 + * @since 3.23.0 + */ + this.duration = 0; + + /** + * The starting angle to rotate the camera from. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#source + * @type {number} + * @since 3.23.0 + */ + this.source = 0; + + /** + * The constantly updated value based on the force. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#current + * @type {number} + * @since 3.23.0 + */ + this.current = 0; + + /** + * The destination angle in radians to rotate the camera to. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#destination + * @type {number} + * @since 3.23.0 + */ + this.destination = 0; + + /** + * The ease function to use during the Rotate. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#ease + * @type {function} + * @since 3.23.0 + */ + this.ease; + + /** + * If this effect is running this holds the current percentage of the progress, a value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#progress + * @type {number} + * @since 3.23.0 + */ + this.progress = 0; + + /** + * Effect elapsed timer. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#_elapsed + * @type {number} + * @private + * @since 3.23.0 + */ + this._elapsed = 0; + + /** + * @callback CameraRotateCallback + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera on which the effect is running. + * @param {number} progress - The progress of the effect. A value between 0 and 1. + * @param {number} angle - The Camera's new angle in radians. + */ + + /** + * This callback is invoked every frame for the duration of the effect. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdate + * @type {?CameraRotateCallback} + * @private + * @default null + * @since 3.23.0 + */ + this._onUpdate; + + /** + * On Complete callback scope. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#_onUpdateScope + * @type {any} + * @private + * @since 3.23.0 + */ + this._onUpdateScope; + + /** + * The direction of the rotation. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#clockwise + * @type {boolean} + * @since 3.23.0 + */ + this.clockwise = true; + + /** + * The shortest direction to the target rotation. + * + * @name Phaser.Cameras.Scene2D.Effects.RotateTo#shortestPath + * @type {boolean} + * @since 3.23.0 + */ + this.shortestPath = false; + }, + + /** + * This effect will scroll the Camera so that the center of its viewport finishes at the given angle, + * over the duration and with the ease specified. + * + * @method Phaser.Cameras.Scene2D.Effects.RotateTo#start + * @fires Phaser.Cameras.Scene2D.Events#ROTATE_START + * @fires Phaser.Cameras.Scene2D.Events#ROTATE_COMPLETE + * @since 3.23.0 + * + * @param {number} radians - The destination angle in radians to rotate the Camera viewport to. If the angle is positive then the rotation is clockwise else anticlockwise + * @param {boolean} [shortestPath=false] - If shortest path is set to true the camera will rotate in the quickest direction clockwise or anti-clockwise. + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {(string|function)} [ease='Linear'] - The ease to use for the Rotate. Can be any of the Phaser Easing constants or a custom function. + * @param {boolean} [force=false] - Force the rotation effect to start immediately, even if already running. + * @param {CameraRotateCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent four arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is, + * the current camera scroll x coordinate and the current camera scroll y coordinate. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started. + */ + start: function (radians, shortestPath, duration, ease, force, callback, context) + { + if (duration === undefined) { duration = 1000; } + if (ease === undefined) { ease = EaseMap.Linear; } + if (force === undefined) { force = false; } + if (callback === undefined) { callback = null; } + if (context === undefined) { context = this.camera.scene; } + if (shortestPath === undefined) { shortestPath = false; } + + this.shortestPath = shortestPath; + + var tmpDestination = radians; + + if (radians < 0) + { + tmpDestination = -1 * radians; + this.clockwise = false; + } + else + { + this.clockwise = true; + } + + var maxRad = (360 * Math.PI) / 180; + + tmpDestination = tmpDestination - (Math.floor(tmpDestination / maxRad) * maxRad); + + var cam = this.camera; + + if (!force && this.isRunning) + { + return cam; + } + + this.isRunning = true; + this.duration = duration; + this.progress = 0; + + // Starting from + this.source = cam.rotation; + + // Destination + this.destination = tmpDestination; + + // Using this ease + if (typeof ease === 'string' && EaseMap.hasOwnProperty(ease)) + { + this.ease = EaseMap[ease]; + } + else if (typeof ease === 'function') + { + this.ease = ease; + } + + this._elapsed = 0; + + this._onUpdate = callback; + this._onUpdateScope = context; + + + if (this.shortestPath) + { + // The shortest path is true so calculate the quickest direction + var cwDist = 0; + var acwDist = 0; + + if (this.destination > this.source) + { + cwDist = Math.abs(this.destination - this.source); + } + else + { + cwDist = (Math.abs(this.destination + maxRad) - this.source); + } + + if (this.source > this.destination) + { + acwDist = Math.abs(this.source - this.destination); + } + else + { + acwDist = (Math.abs(this.source + maxRad) - this.destination); + } + + if (cwDist < acwDist) + { + this.clockwise = true; + } + else if (cwDist > acwDist) + { + this.clockwise = false; + } + } + + this.camera.emit(Events.ROTATE_START, this.camera, this, duration, tmpDestination); + + return cam; + }, + + /** + * The main update loop for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.RotateTo#update + * @since 3.23.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (!this.isRunning) + { + return; + } + + this._elapsed += delta; + + var progress = Clamp(this._elapsed / this.duration, 0, 1); + + this.progress = progress; + + var cam = this.camera; + + if (this._elapsed < this.duration) + { + var v = this.ease(progress); + + this.current = cam.rotation; + var distance = 0; + var maxRad = (360 * Math.PI) / 180; + var target = this.destination; + var current = this.current; + + if (this.clockwise === false) + { + target = this.current; + current = this.destination; + } + + if (target >= current) + { + distance = Math.abs(target - current); + } + else + { + distance = (Math.abs(target + maxRad) - current); + } + + var r = 0; + + if (this.clockwise) + { + r = (cam.rotation + (distance * v)); + } + else + { + r = (cam.rotation - (distance * v)); + } + + cam.rotation = r; + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, cam, progress, r); + } + } + else + { + cam.rotation = this.destination; + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, cam, progress, this.destination); + } + + this.effectComplete(); + } + }, + + /** + * Called internally when the effect completes. + * + * @method Phaser.Cameras.Scene2D.Effects.RotateTo#effectComplete + * @since 3.23.0 + */ + effectComplete: function () + { + this._onUpdate = null; + this._onUpdateScope = null; + + this.isRunning = false; + + this.camera.emit(Events.ROTATE_COMPLETE, this.camera, this); + }, + + /** + * Resets this camera effect. + * If it was previously running, it stops instantly without calling its onComplete callback or emitting an event. + * + * @method Phaser.Cameras.Scene2D.Effects.RotateTo#reset + * @since 3.23.0 + */ + reset: function () + { + this.isRunning = false; + + this._onUpdate = null; + this._onUpdateScope = null; + }, + + /** + * Destroys this effect, releasing it from the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.RotateTo#destroy + * @since 3.23.0 + */ + destroy: function () + { + this.reset(); + + this.camera = null; + this.source = null; + this.destination = null; + } + +}); + +module.exports = RotateTo; + + +/***/ }), + +/***/ 30330: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(19715); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Camera Shake effect. + * + * This effect will shake the camera viewport by a random amount, bounded by the specified intensity, each frame. + * + * Only the camera viewport is moved. None of the objects it is displaying are impacted, i.e. their positions do + * not change. + * + * The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback, + * which is invoked each frame for the duration of the effect if required. + * + * @class Shake + * @memberof Phaser.Cameras.Scene2D.Effects + * @constructor + * @since 3.5.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon. + */ +var Shake = new Class({ + + initialize: + + function Shake (camera) + { + /** + * The Camera this effect belongs to. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @readonly + * @since 3.5.0 + */ + this.camera = camera; + + /** + * Is this effect actively running? + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#isRunning + * @type {boolean} + * @readonly + * @default false + * @since 3.5.0 + */ + this.isRunning = false; + + /** + * The duration of the effect, in milliseconds. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#duration + * @type {number} + * @readonly + * @default 0 + * @since 3.5.0 + */ + this.duration = 0; + + /** + * The intensity of the effect. Use small float values. The default when the effect starts is 0.05. + * This is a Vector2 object, allowing you to control the shake intensity independently across x and y. + * You can modify this value while the effect is active to create more varied shake effects. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#intensity + * @type {Phaser.Math.Vector2} + * @since 3.5.0 + */ + this.intensity = new Vector2(); + + /** + * If this effect is running this holds the current percentage of the progress, a value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#progress + * @type {number} + * @since 3.5.0 + */ + this.progress = 0; + + /** + * Effect elapsed timer. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#_elapsed + * @type {number} + * @private + * @since 3.5.0 + */ + this._elapsed = 0; + + /** + * How much to offset the camera by horizontally. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#_offsetX + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._offsetX = 0; + + /** + * How much to offset the camera by vertically. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#_offsetY + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._offsetY = 0; + + /** + * This callback is invoked every frame for the duration of the effect. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#_onUpdate + * @type {?Phaser.Types.Cameras.Scene2D.CameraShakeCallback} + * @private + * @default null + * @since 3.5.0 + */ + this._onUpdate; + + /** + * On Complete callback scope. + * + * @name Phaser.Cameras.Scene2D.Effects.Shake#_onUpdateScope + * @type {any} + * @private + * @since 3.5.0 + */ + this._onUpdateScope; + }, + + /** + * Shakes the Camera by the given intensity over the duration specified. + * + * @method Phaser.Cameras.Scene2D.Effects.Shake#start + * @fires Phaser.Cameras.Scene2D.Events#SHAKE_START + * @fires Phaser.Cameras.Scene2D.Events#SHAKE_COMPLETE + * @since 3.5.0 + * + * @param {number} [duration=100] - The duration of the effect in milliseconds. + * @param {(number|Phaser.Math.Vector2)} [intensity=0.05] - The intensity of the shake. + * @param {boolean} [force=false] - Force the shake effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraShakeCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent two arguments: A reference to the camera and a progress amount between 0 and 1 indicating how complete the effect is. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started. + */ + start: function (duration, intensity, force, callback, context) + { + if (duration === undefined) { duration = 100; } + if (intensity === undefined) { intensity = 0.05; } + if (force === undefined) { force = false; } + if (callback === undefined) { callback = null; } + if (context === undefined) { context = this.camera.scene; } + + if (!force && this.isRunning) + { + return this.camera; + } + + this.isRunning = true; + this.duration = duration; + this.progress = 0; + + if (typeof intensity === 'number') + { + this.intensity.set(intensity); + } + else + { + this.intensity.set(intensity.x, intensity.y); + } + + this._elapsed = 0; + this._offsetX = 0; + this._offsetY = 0; + + this._onUpdate = callback; + this._onUpdateScope = context; + + this.camera.emit(Events.SHAKE_START, this.camera, this, duration, intensity); + + return this.camera; + }, + + /** + * The pre-render step for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Shake#preRender + * @since 3.5.0 + */ + preRender: function () + { + if (this.isRunning) + { + this.camera.matrix.translate(this._offsetX, this._offsetY); + } + }, + + /** + * The main update loop for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Shake#update + * @since 3.5.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (!this.isRunning) + { + return; + } + + this._elapsed += delta; + + this.progress = Clamp(this._elapsed / this.duration, 0, 1); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, this.camera, this.progress); + } + + if (this._elapsed < this.duration) + { + var intensity = this.intensity; + var width = this.camera.width; + var height = this.camera.height; + var zoom = this.camera.zoom; + + this._offsetX = (Math.random() * intensity.x * width * 2 - intensity.x * width) * zoom; + this._offsetY = (Math.random() * intensity.y * height * 2 - intensity.y * height) * zoom; + + if (this.camera.roundPixels) + { + this._offsetX = Math.round(this._offsetX); + this._offsetY = Math.round(this._offsetY); + } + } + else + { + this.effectComplete(); + } + }, + + /** + * Called internally when the effect completes. + * + * @method Phaser.Cameras.Scene2D.Effects.Shake#effectComplete + * @fires Phaser.Cameras.Scene2D.Events#SHAKE_COMPLETE + * @since 3.5.0 + */ + effectComplete: function () + { + this._offsetX = 0; + this._offsetY = 0; + + this._onUpdate = null; + this._onUpdateScope = null; + + this.isRunning = false; + + this.camera.emit(Events.SHAKE_COMPLETE, this.camera, this); + }, + + /** + * Resets this camera effect. + * If it was previously running, it stops instantly without calling its onComplete callback or emitting an event. + * + * @method Phaser.Cameras.Scene2D.Effects.Shake#reset + * @since 3.5.0 + */ + reset: function () + { + this.isRunning = false; + + this._offsetX = 0; + this._offsetY = 0; + + this._onUpdate = null; + this._onUpdateScope = null; + }, + + /** + * Destroys this effect, releasing it from the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Shake#destroy + * @since 3.5.0 + */ + destroy: function () + { + this.reset(); + + this.camera = null; + this.intensity = null; + } + +}); + +module.exports = Shake; + + +/***/ }), + +/***/ 45641: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var EaseMap = __webpack_require__(62640); +var Events = __webpack_require__(19715); + +/** + * @classdesc + * A Camera Zoom effect. + * + * This effect will zoom the Camera to the given scale, over the duration and with the ease specified. + * + * The effect will dispatch several events on the Camera itself and you can also specify an `onUpdate` callback, + * which is invoked each frame for the duration of the effect if required. + * + * @class Zoom + * @memberof Phaser.Cameras.Scene2D.Effects + * @constructor + * @since 3.11.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera this effect is acting upon. + */ +var Zoom = new Class({ + + initialize: + + function Zoom (camera) + { + /** + * The Camera this effect belongs to. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @readonly + * @since 3.11.0 + */ + this.camera = camera; + + /** + * Is this effect actively running? + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#isRunning + * @type {boolean} + * @readonly + * @default false + * @since 3.11.0 + */ + this.isRunning = false; + + /** + * The duration of the effect, in milliseconds. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#duration + * @type {number} + * @readonly + * @default 0 + * @since 3.11.0 + */ + this.duration = 0; + + /** + * The starting zoom value; + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#source + * @type {number} + * @since 3.11.0 + */ + this.source = 1; + + /** + * The destination zoom value. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#destination + * @type {number} + * @since 3.11.0 + */ + this.destination = 1; + + /** + * The ease function to use during the zoom. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#ease + * @type {function} + * @since 3.11.0 + */ + this.ease; + + /** + * If this effect is running this holds the current percentage of the progress, a value between 0 and 1. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#progress + * @type {number} + * @since 3.11.0 + */ + this.progress = 0; + + /** + * Effect elapsed timer. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#_elapsed + * @type {number} + * @private + * @since 3.11.0 + */ + this._elapsed = 0; + + /** + * This callback is invoked every frame for the duration of the effect. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#_onUpdate + * @type {?Phaser.Types.Cameras.Scene2D.CameraZoomCallback} + * @private + * @default null + * @since 3.11.0 + */ + this._onUpdate; + + /** + * On Complete callback scope. + * + * @name Phaser.Cameras.Scene2D.Effects.Zoom#_onUpdateScope + * @type {any} + * @private + * @since 3.11.0 + */ + this._onUpdateScope; + }, + + /** + * This effect will zoom the Camera to the given scale, over the duration and with the ease specified. + * + * @method Phaser.Cameras.Scene2D.Effects.Zoom#start + * @fires Phaser.Cameras.Scene2D.Events#ZOOM_START + * @fires Phaser.Cameras.Scene2D.Events#ZOOM_COMPLETE + * @since 3.11.0 + * + * @param {number} zoom - The target Camera zoom value. + * @param {number} [duration=1000] - The duration of the effect in milliseconds. + * @param {(string|function)} [ease='Linear'] - The ease to use for the Zoom. Can be any of the Phaser Easing constants or a custom function. + * @param {boolean} [force=false] - Force the zoom effect to start immediately, even if already running. + * @param {Phaser.Types.Cameras.Scene2D.CameraZoomCallback} [callback] - This callback will be invoked every frame for the duration of the effect. + * It is sent three arguments: A reference to the camera, a progress amount between 0 and 1 indicating how complete the effect is, + * and the current camera zoom value. + * @param {any} [context] - The context in which the callback is invoked. Defaults to the Scene to which the Camera belongs. + * + * @return {Phaser.Cameras.Scene2D.Camera} The Camera on which the effect was started. + */ + start: function (zoom, duration, ease, force, callback, context) + { + if (duration === undefined) { duration = 1000; } + if (ease === undefined) { ease = EaseMap.Linear; } + if (force === undefined) { force = false; } + if (callback === undefined) { callback = null; } + if (context === undefined) { context = this.camera.scene; } + + var cam = this.camera; + + if (!force && this.isRunning) + { + return cam; + } + + this.isRunning = true; + this.duration = duration; + this.progress = 0; + + // Starting from + this.source = cam.zoom; + + // Zooming to + this.destination = zoom; + + // Using this ease + if (typeof ease === 'string' && EaseMap.hasOwnProperty(ease)) + { + this.ease = EaseMap[ease]; + } + else if (typeof ease === 'function') + { + this.ease = ease; + } + + this._elapsed = 0; + + this._onUpdate = callback; + this._onUpdateScope = context; + + this.camera.emit(Events.ZOOM_START, this.camera, this, duration, zoom); + + return cam; + }, + + /** + * The main update loop for this effect. Called automatically by the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Zoom#update + * @since 3.11.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (!this.isRunning) + { + return; + } + + this._elapsed += delta; + + this.progress = Clamp(this._elapsed / this.duration, 0, 1); + + if (this._elapsed < this.duration) + { + this.camera.zoom = this.source + ((this.destination - this.source) * this.ease(this.progress)); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, this.camera, this.progress, this.camera.zoom); + } + } + else + { + this.camera.zoom = this.destination; + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, this.camera, this.progress, this.destination); + } + + this.effectComplete(); + } + }, + + /** + * Called internally when the effect completes. + * + * @method Phaser.Cameras.Scene2D.Effects.Zoom#effectComplete + * @fires Phaser.Cameras.Scene2D.Events#ZOOM_COMPLETE + * @since 3.11.0 + */ + effectComplete: function () + { + this._onUpdate = null; + this._onUpdateScope = null; + + this.isRunning = false; + + this.camera.emit(Events.ZOOM_COMPLETE, this.camera, this); + }, + + /** + * Resets this camera effect. + * If it was previously running, it stops instantly without calling its onComplete callback or emitting an event. + * + * @method Phaser.Cameras.Scene2D.Effects.Zoom#reset + * @since 3.11.0 + */ + reset: function () + { + this.isRunning = false; + + this._onUpdate = null; + this._onUpdateScope = null; + }, + + /** + * Destroys this effect, releasing it from the Camera. + * + * @method Phaser.Cameras.Scene2D.Effects.Zoom#destroy + * @since 3.11.0 + */ + destroy: function () + { + this.reset(); + + this.camera = null; + } + +}); + +module.exports = Zoom; + + +/***/ }), + +/***/ 20052: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cameras.Scene2D.Effects + */ + +module.exports = { + + Fade: __webpack_require__(5020), + Flash: __webpack_require__(10662), + Pan: __webpack_require__(20359), + Shake: __webpack_require__(30330), + RotateTo: __webpack_require__(34208), + Zoom: __webpack_require__(45641) + +}; + + +/***/ }), + +/***/ 16438: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Destroy Camera Event. + * + * This event is dispatched by a Camera instance when it is destroyed by the Camera Manager. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('cameradestroy', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.DESTROY, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#DESTROY + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.BaseCamera} camera - The camera that was destroyed. + */ +module.exports = 'cameradestroy'; + + +/***/ }), + +/***/ 32726: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Fade In Complete Event. + * + * This event is dispatched by a Camera instance when the Fade In Effect completes. + * + * Listen to it from a Camera instance using `Camera.on('camerafadeincomplete', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#FADE_IN_COMPLETE + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Fade} effect - A reference to the effect instance. + */ +module.exports = 'camerafadeincomplete'; + + +/***/ }), + +/***/ 87807: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Fade In Start Event. + * + * This event is dispatched by a Camera instance when the Fade In Effect starts. + * + * Listen to it from a Camera instance using `Camera.on('camerafadeinstart', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#FADE_IN_START + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Fade} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} red - The red color channel value. + * @param {number} green - The green color channel value. + * @param {number} blue - The blue color channel value. + */ +module.exports = 'camerafadeinstart'; + + +/***/ }), + +/***/ 45917: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Fade Out Complete Event. + * + * This event is dispatched by a Camera instance when the Fade Out Effect completes. + * + * Listen to it from a Camera instance using `Camera.on('camerafadeoutcomplete', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#FADE_OUT_COMPLETE + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Fade} effect - A reference to the effect instance. + */ +module.exports = 'camerafadeoutcomplete'; + + +/***/ }), + +/***/ 95666: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Fade Out Start Event. + * + * This event is dispatched by a Camera instance when the Fade Out Effect starts. + * + * Listen to it from a Camera instance using `Camera.on('camerafadeoutstart', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#FADE_OUT_START + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Fade} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} red - The red color channel value. + * @param {number} green - The green color channel value. + * @param {number} blue - The blue color channel value. + */ +module.exports = 'camerafadeoutstart'; + + +/***/ }), + +/***/ 47056: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Flash Complete Event. + * + * This event is dispatched by a Camera instance when the Flash Effect completes. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('cameraflashcomplete', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.FLASH_COMPLETE, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#FLASH_COMPLETE + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Flash} effect - A reference to the effect instance. + */ +module.exports = 'cameraflashcomplete'; + + +/***/ }), + +/***/ 91261: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Flash Start Event. + * + * This event is dispatched by a Camera instance when the Flash Effect starts. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('cameraflashstart', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.FLASH_START, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#FLASH_START + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Flash} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} red - The red color channel value. + * @param {number} green - The green color channel value. + * @param {number} blue - The blue color channel value. + */ +module.exports = 'cameraflashstart'; + + +/***/ }), + +/***/ 45047: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Follower Update Event. + * + * This event is dispatched by a Camera instance when it is following a + * Game Object and the Camera position has been updated as a result of + * that following. + * + * Listen to it from a Camera instance using: `camera.on('followupdate', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#FOLLOW_UPDATE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Cameras.Scene2D.BaseCamera} camera - The camera that emitted the event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the camera is following. + */ +module.exports = 'followupdate'; + + +/***/ }), + +/***/ 81927: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Pan Complete Event. + * + * This event is dispatched by a Camera instance when the Pan Effect completes. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerapancomplete', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.PAN_COMPLETE, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#PAN_COMPLETE + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Pan} effect - A reference to the effect instance. + */ +module.exports = 'camerapancomplete'; + + +/***/ }), + +/***/ 74264: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Pan Start Event. + * + * This event is dispatched by a Camera instance when the Pan Effect starts. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerapanstart', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.PAN_START, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#PAN_START + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Pan} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} x - The destination scroll x coordinate. + * @param {number} y - The destination scroll y coordinate. + */ +module.exports = 'camerapanstart'; + + +/***/ }), + +/***/ 54419: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Post-Render Event. + * + * This event is dispatched by a Camera instance after is has finished rendering. + * It is dispatched whether the Camera is rendering to a texture or to the main canvas. + * + * Listen to it from a Camera instance using: `camera.on('postrender', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#POST_RENDER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.BaseCamera} camera - The camera that has finished rendering to a texture. + */ +module.exports = 'postrender'; + + +/***/ }), + +/***/ 79330: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Pre-Render Event. + * + * This event is dispatched by a Camera instance when it is about to render. + * It is only dispatched if the Camera is rendering to a texture. + * + * Listen to it from a Camera instance using: `camera.on('prerender', listener)`. + * + * @event Phaser.Cameras.Scene2D.Events#PRE_RENDER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.BaseCamera} camera - The camera that is about to render to a texture. + */ +module.exports = 'prerender'; + + +/***/ }), + +/***/ 93183: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Rotate Complete Event. + * + * This event is dispatched by a Camera instance when the Rotate Effect completes. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerarotatecomplete', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.ROTATE_COMPLETE, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#ROTATE_COMPLETE + * @type {string} + * @since 3.23.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance. + */ +module.exports = 'camerarotatecomplete'; + + +/***/ }), + +/***/ 80112: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Rotate Start Event. + * + * This event is dispatched by a Camera instance when the Rotate Effect starts. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerarotatestart', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.ROTATE_START, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#ROTATE_START + * @type {string} + * @since 3.23.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.RotateTo} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} destination - The destination value. + */ +module.exports = 'camerarotatestart'; + + +/***/ }), + +/***/ 62252: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Shake Complete Event. + * + * This event is dispatched by a Camera instance when the Shake Effect completes. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerashakecomplete', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.SHAKE_COMPLETE, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#SHAKE_COMPLETE + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Shake} effect - A reference to the effect instance. + */ +module.exports = 'camerashakecomplete'; + + +/***/ }), + +/***/ 86017: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Shake Start Event. + * + * This event is dispatched by a Camera instance when the Shake Effect starts. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerashakestart', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.SHAKE_START, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#SHAKE_START + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Shake} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} intensity - The intensity of the effect. + */ +module.exports = 'camerashakestart'; + + +/***/ }), + +/***/ 539: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Zoom Complete Event. + * + * This event is dispatched by a Camera instance when the Zoom Effect completes. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerazoomcomplete', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.ZOOM_COMPLETE, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#ZOOM_COMPLETE + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Zoom} effect - A reference to the effect instance. + */ +module.exports = 'camerazoomcomplete'; + + +/***/ }), + +/***/ 51892: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Camera Zoom Start Event. + * + * This event is dispatched by a Camera instance when the Zoom Effect starts. + * + * Listen for it via either of the following: + * + * ```js + * this.cameras.main.on('camerazoomstart', () => {}); + * ``` + * + * or use the constant, to avoid having to remember the correct event string: + * + * ```js + * this.cameras.main.on(Phaser.Cameras.Scene2D.Events.ZOOM_START, () => {}); + * ``` + * + * @event Phaser.Cameras.Scene2D.Events#ZOOM_START + * @type {string} + * @since 3.3.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that the effect began on. + * @param {Phaser.Cameras.Scene2D.Effects.Zoom} effect - A reference to the effect instance. + * @param {number} duration - The duration of the effect. + * @param {number} zoom - The destination zoom value. + */ +module.exports = 'camerazoomstart'; + + +/***/ }), + +/***/ 19715: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cameras.Scene2D.Events + */ + +module.exports = { + + DESTROY: __webpack_require__(16438), + FADE_IN_COMPLETE: __webpack_require__(32726), + FADE_IN_START: __webpack_require__(87807), + FADE_OUT_COMPLETE: __webpack_require__(45917), + FADE_OUT_START: __webpack_require__(95666), + FLASH_COMPLETE: __webpack_require__(47056), + FLASH_START: __webpack_require__(91261), + FOLLOW_UPDATE: __webpack_require__(45047), + PAN_COMPLETE: __webpack_require__(81927), + PAN_START: __webpack_require__(74264), + POST_RENDER: __webpack_require__(54419), + PRE_RENDER: __webpack_require__(79330), + ROTATE_COMPLETE: __webpack_require__(93183), + ROTATE_START: __webpack_require__(80112), + SHAKE_COMPLETE: __webpack_require__(62252), + SHAKE_START: __webpack_require__(86017), + ZOOM_COMPLETE: __webpack_require__(539), + ZOOM_START: __webpack_require__(51892) + +}; + + +/***/ }), + +/***/ 87969: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cameras.Scene2D + */ + +module.exports = { + + Camera: __webpack_require__(38058), + BaseCamera: __webpack_require__(71911), + CameraManager: __webpack_require__(32743), + Effects: __webpack_require__(20052), + Events: __webpack_require__(19715) + +}; + + +/***/ }), + +/***/ 63091: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetValue = __webpack_require__(35154); + +/** + * @classdesc + * A Fixed Key Camera Control. + * + * This allows you to control the movement and zoom of a camera using the defined keys. + * + * ```javascript + * var camControl = new FixedKeyControl({ + * camera: this.cameras.main, + * left: cursors.left, + * right: cursors.right, + * speed: float OR { x: 0, y: 0 } + * }); + * ``` + * + * Movement is precise and has no 'smoothing' applied to it. + * + * You must call the `update` method of this controller every frame. + * + * @class FixedKeyControl + * @memberof Phaser.Cameras.Controls + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Cameras.Controls.FixedKeyControlConfig} config - The Fixed Key Control configuration object. + */ +var FixedKeyControl = new Class({ + + initialize: + + function FixedKeyControl (config) + { + /** + * The Camera that this Control will update. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#camera + * @type {?Phaser.Cameras.Scene2D.Camera} + * @default null + * @since 3.0.0 + */ + this.camera = GetValue(config, 'camera', null); + + /** + * The Key to be pressed that will move the Camera left. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#left + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.left = GetValue(config, 'left', null); + + /** + * The Key to be pressed that will move the Camera right. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#right + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.right = GetValue(config, 'right', null); + + /** + * The Key to be pressed that will move the Camera up. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#up + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.up = GetValue(config, 'up', null); + + /** + * The Key to be pressed that will move the Camera down. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#down + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.down = GetValue(config, 'down', null); + + /** + * The Key to be pressed that will zoom the Camera in. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#zoomIn + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.zoomIn = GetValue(config, 'zoomIn', null); + + /** + * The Key to be pressed that will zoom the Camera out. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#zoomOut + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.zoomOut = GetValue(config, 'zoomOut', null); + + /** + * The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#zoomSpeed + * @type {number} + * @default 0.01 + * @since 3.0.0 + */ + this.zoomSpeed = GetValue(config, 'zoomSpeed', 0.01); + + /** + * The smallest zoom value the camera will reach when zoomed out. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#minZoom + * @type {number} + * @default 0.001 + * @since 3.53.0 + */ + this.minZoom = GetValue(config, 'minZoom', 0.001); + + /** + * The largest zoom value the camera will reach when zoomed in. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#maxZoom + * @type {number} + * @default 1000 + * @since 3.53.0 + */ + this.maxZoom = GetValue(config, 'maxZoom', 1000); + + /** + * The horizontal speed the camera will move. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#speedX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.speedX = 0; + + /** + * The vertical speed the camera will move. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#speedY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.speedY = 0; + + var speed = GetValue(config, 'speed', null); + + if (typeof speed === 'number') + { + this.speedX = speed; + this.speedY = speed; + } + else + { + this.speedX = GetValue(config, 'speed.x', 0); + this.speedY = GetValue(config, 'speed.y', 0); + } + + /** + * Internal property to track the current zoom level. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#_zoom + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._zoom = 0; + + /** + * A flag controlling if the Controls will update the Camera or not. + * + * @name Phaser.Cameras.Controls.FixedKeyControl#active + * @type {boolean} + * @since 3.0.0 + */ + this.active = (this.camera !== null); + }, + + /** + * Starts the Key Control running, providing it has been linked to a camera. + * + * @method Phaser.Cameras.Controls.FixedKeyControl#start + * @since 3.0.0 + * + * @return {this} This Key Control instance. + */ + start: function () + { + this.active = (this.camera !== null); + + return this; + }, + + /** + * Stops this Key Control from running. Call `start` to start it again. + * + * @method Phaser.Cameras.Controls.FixedKeyControl#stop + * @since 3.0.0 + * + * @return {this} This Key Control instance. + */ + stop: function () + { + this.active = false; + + return this; + }, + + /** + * Binds this Key Control to a camera. + * + * @method Phaser.Cameras.Controls.FixedKeyControl#setCamera + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to bind this Key Control to. + * + * @return {this} This Key Control instance. + */ + setCamera: function (camera) + { + this.camera = camera; + + return this; + }, + + /** + * Applies the results of pressing the control keys to the Camera. + * + * You must call this every step, it is not called automatically. + * + * @method Phaser.Cameras.Controls.FixedKeyControl#update + * @since 3.0.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + update: function (delta) + { + if (!this.active) + { + return; + } + + if (delta === undefined) { delta = 1; } + + var cam = this.camera; + + if (this.up && this.up.isDown) + { + cam.scrollY -= ((this.speedY * delta) | 0); + } + else if (this.down && this.down.isDown) + { + cam.scrollY += ((this.speedY * delta) | 0); + } + + if (this.left && this.left.isDown) + { + cam.scrollX -= ((this.speedX * delta) | 0); + } + else if (this.right && this.right.isDown) + { + cam.scrollX += ((this.speedX * delta) | 0); + } + + // Camera zoom + + if (this.zoomIn && this.zoomIn.isDown) + { + cam.zoom -= this.zoomSpeed; + + if (cam.zoom < this.minZoom) + { + cam.zoom = this.minZoom; + } + } + else if (this.zoomOut && this.zoomOut.isDown) + { + cam.zoom += this.zoomSpeed; + + if (cam.zoom > this.maxZoom) + { + cam.zoom = this.maxZoom; + } + } + }, + + /** + * Destroys this Key Control. + * + * @method Phaser.Cameras.Controls.FixedKeyControl#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.camera = null; + + this.left = null; + this.right = null; + this.up = null; + this.down = null; + + this.zoomIn = null; + this.zoomOut = null; + } + +}); + +module.exports = FixedKeyControl; + + +/***/ }), + +/***/ 58818: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetValue = __webpack_require__(35154); + +/** + * @classdesc + * A Smoothed Key Camera Control. + * + * This allows you to control the movement and zoom of a camera using the defined keys. + * Unlike the Fixed Camera Control you can also provide physics values for acceleration, drag and maxSpeed for smoothing effects. + * + * ```javascript + * var controlConfig = { + * camera: this.cameras.main, + * left: cursors.left, + * right: cursors.right, + * up: cursors.up, + * down: cursors.down, + * zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q), + * zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E), + * zoomSpeed: 0.02, + * acceleration: 0.06, + * drag: 0.0005, + * maxSpeed: 1.0 + * }; + * ``` + * + * You must call the `update` method of this controller every frame. + * + * @class SmoothedKeyControl + * @memberof Phaser.Cameras.Controls + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Cameras.Controls.SmoothedKeyControlConfig} config - The Smoothed Key Control configuration object. + */ +var SmoothedKeyControl = new Class({ + + initialize: + + function SmoothedKeyControl (config) + { + /** + * The Camera that this Control will update. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#camera + * @type {?Phaser.Cameras.Scene2D.Camera} + * @default null + * @since 3.0.0 + */ + this.camera = GetValue(config, 'camera', null); + + /** + * The Key to be pressed that will move the Camera left. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#left + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.left = GetValue(config, 'left', null); + + /** + * The Key to be pressed that will move the Camera right. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#right + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.right = GetValue(config, 'right', null); + + /** + * The Key to be pressed that will move the Camera up. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#up + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.up = GetValue(config, 'up', null); + + /** + * The Key to be pressed that will move the Camera down. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#down + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.down = GetValue(config, 'down', null); + + /** + * The Key to be pressed that will zoom the Camera in. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomIn + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.zoomIn = GetValue(config, 'zoomIn', null); + + /** + * The Key to be pressed that will zoom the Camera out. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomOut + * @type {?Phaser.Input.Keyboard.Key} + * @default null + * @since 3.0.0 + */ + this.zoomOut = GetValue(config, 'zoomOut', null); + + /** + * The speed at which the camera will zoom if the `zoomIn` or `zoomOut` keys are pressed. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#zoomSpeed + * @type {number} + * @default 0.01 + * @since 3.0.0 + */ + this.zoomSpeed = GetValue(config, 'zoomSpeed', 0.01); + + /** + * The smallest zoom value the camera will reach when zoomed out. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#minZoom + * @type {number} + * @default 0.001 + * @since 3.53.0 + */ + this.minZoom = GetValue(config, 'minZoom', 0.001); + + /** + * The largest zoom value the camera will reach when zoomed in. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#maxZoom + * @type {number} + * @default 1000 + * @since 3.53.0 + */ + this.maxZoom = GetValue(config, 'maxZoom', 1000); + + /** + * The horizontal acceleration the camera will move. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#accelX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.accelX = 0; + + /** + * The vertical acceleration the camera will move. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#accelY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.accelY = 0; + + var accel = GetValue(config, 'acceleration', null); + + if (typeof accel === 'number') + { + this.accelX = accel; + this.accelY = accel; + } + else + { + this.accelX = GetValue(config, 'acceleration.x', 0); + this.accelY = GetValue(config, 'acceleration.y', 0); + } + + /** + * The horizontal drag applied to the camera when it is moving. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#dragX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.dragX = 0; + + /** + * The vertical drag applied to the camera when it is moving. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#dragY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.dragY = 0; + + var drag = GetValue(config, 'drag', null); + + if (typeof drag === 'number') + { + this.dragX = drag; + this.dragY = drag; + } + else + { + this.dragX = GetValue(config, 'drag.x', 0); + this.dragY = GetValue(config, 'drag.y', 0); + } + + /** + * The maximum horizontal speed the camera will move. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#maxSpeedX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.maxSpeedX = 0; + + /** + * The maximum vertical speed the camera will move. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#maxSpeedY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.maxSpeedY = 0; + + var maxSpeed = GetValue(config, 'maxSpeed', null); + + if (typeof maxSpeed === 'number') + { + this.maxSpeedX = maxSpeed; + this.maxSpeedY = maxSpeed; + } + else + { + this.maxSpeedX = GetValue(config, 'maxSpeed.x', 0); + this.maxSpeedY = GetValue(config, 'maxSpeed.y', 0); + } + + /** + * Internal property to track the speed of the control. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#_speedX + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._speedX = 0; + + /** + * Internal property to track the speed of the control. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#_speedY + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._speedY = 0; + + /** + * Internal property to track the zoom of the control. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#_zoom + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._zoom = 0; + + /** + * A flag controlling if the Controls will update the Camera or not. + * + * @name Phaser.Cameras.Controls.SmoothedKeyControl#active + * @type {boolean} + * @since 3.0.0 + */ + this.active = (this.camera !== null); + }, + + /** + * Starts the Key Control running, providing it has been linked to a camera. + * + * @method Phaser.Cameras.Controls.SmoothedKeyControl#start + * @since 3.0.0 + * + * @return {this} This Key Control instance. + */ + start: function () + { + this.active = (this.camera !== null); + + return this; + }, + + /** + * Stops this Key Control from running. Call `start` to start it again. + * + * @method Phaser.Cameras.Controls.SmoothedKeyControl#stop + * @since 3.0.0 + * + * @return {this} This Key Control instance. + */ + stop: function () + { + this.active = false; + + return this; + }, + + /** + * Binds this Key Control to a camera. + * + * @method Phaser.Cameras.Controls.SmoothedKeyControl#setCamera + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to bind this Key Control to. + * + * @return {this} This Key Control instance. + */ + setCamera: function (camera) + { + this.camera = camera; + + return this; + }, + + /** + * Applies the results of pressing the control keys to the Camera. + * + * You must call this every step, it is not called automatically. + * + * @method Phaser.Cameras.Controls.SmoothedKeyControl#update + * @since 3.0.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + update: function (delta) + { + if (!this.active) + { + return; + } + + if (delta === undefined) { delta = 1; } + + var cam = this.camera; + + // Apply Deceleration + + if (this._speedX > 0) + { + this._speedX -= this.dragX * delta; + + if (this._speedX < 0) + { + this._speedX = 0; + } + } + else if (this._speedX < 0) + { + this._speedX += this.dragX * delta; + + if (this._speedX > 0) + { + this._speedX = 0; + } + } + + if (this._speedY > 0) + { + this._speedY -= this.dragY * delta; + + if (this._speedY < 0) + { + this._speedY = 0; + } + } + else if (this._speedY < 0) + { + this._speedY += this.dragY * delta; + + if (this._speedY > 0) + { + this._speedY = 0; + } + } + + // Check for keys + + if (this.up && this.up.isDown) + { + this._speedY += this.accelY; + + if (this._speedY > this.maxSpeedY) + { + this._speedY = this.maxSpeedY; + } + } + else if (this.down && this.down.isDown) + { + this._speedY -= this.accelY; + + if (this._speedY < -this.maxSpeedY) + { + this._speedY = -this.maxSpeedY; + } + } + + if (this.left && this.left.isDown) + { + this._speedX += this.accelX; + + if (this._speedX > this.maxSpeedX) + { + this._speedX = this.maxSpeedX; + } + } + else if (this.right && this.right.isDown) + { + this._speedX -= this.accelX; + + if (this._speedX < -this.maxSpeedX) + { + this._speedX = -this.maxSpeedX; + } + } + + // Camera zoom + + if (this.zoomIn && this.zoomIn.isDown) + { + this._zoom = -this.zoomSpeed; + } + else if (this.zoomOut && this.zoomOut.isDown) + { + this._zoom = this.zoomSpeed; + } + else + { + this._zoom = 0; + } + + // Apply to Camera + + if (this._speedX !== 0) + { + cam.scrollX -= ((this._speedX * delta) | 0); + } + + if (this._speedY !== 0) + { + cam.scrollY -= ((this._speedY * delta) | 0); + } + + if (this._zoom !== 0) + { + cam.zoom += this._zoom; + + if (cam.zoom < this.minZoom) + { + cam.zoom = this.minZoom; + } + else if (cam.zoom > this.maxZoom) + { + cam.zoom = this.maxZoom; + } + } + }, + + /** + * Destroys this Key Control. + * + * @method Phaser.Cameras.Controls.SmoothedKeyControl#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.camera = null; + + this.left = null; + this.right = null; + this.up = null; + this.down = null; + + this.zoomIn = null; + this.zoomOut = null; + } + +}); + +module.exports = SmoothedKeyControl; + + +/***/ }), + +/***/ 38865: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cameras.Controls + */ + +module.exports = { + + FixedKeyControl: __webpack_require__(63091), + SmoothedKeyControl: __webpack_require__(58818) + +}; + + +/***/ }), + +/***/ 26638: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Cameras + */ + +/** + * @namespace Phaser.Types.Cameras + */ + +module.exports = { + + Controls: __webpack_require__(38865), + Scene2D: __webpack_require__(87969) + +}; + + +/***/ }), + +/***/ 8054: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Global constants. + * + * @ignore + */ + +var CONST = { + + /** + * Phaser Release Version + * + * @name Phaser.VERSION + * @const + * @type {string} + * @since 3.0.0 + */ + VERSION: '4.0.0 RC1', + + /** + * Phaser Release Version as displayed in the console.log header URL. + * + * @name Phaser.LOG_VERSION + * @const + * @type {string} + * @since 3.87.0 + */ + LOG_VERSION: 'v400', + + BlendModes: __webpack_require__(10312), + + ScaleModes: __webpack_require__(29795), + + /** + * This setting will auto-detect if the browser is capable of suppporting WebGL. + * If it is, it will use the WebGL Renderer. If not, it will fall back to the Canvas Renderer. + * + * @name Phaser.AUTO + * @const + * @type {number} + * @since 3.0.0 + */ + AUTO: 0, + + /** + * Forces Phaser to only use the Canvas Renderer, regardless if the browser supports + * WebGL or not. + * + * @name Phaser.CANVAS + * @const + * @type {number} + * @since 3.0.0 + */ + CANVAS: 1, + + /** + * Forces Phaser to use the WebGL Renderer. If the browser does not support it, there is + * no fallback to Canvas with this setting, so you should trap it and display a suitable + * message to the user. + * + * @name Phaser.WEBGL + * @const + * @type {number} + * @since 3.0.0 + */ + WEBGL: 2, + + /** + * A Headless Renderer doesn't create either a Canvas or WebGL Renderer. However, it still + * absolutely relies on the DOM being present and available. This mode is meant for unit testing, + * not for running Phaser on the server, which is something you really shouldn't do. + * + * @name Phaser.HEADLESS + * @const + * @type {number} + * @since 3.0.0 + */ + HEADLESS: 3, + + /** + * In Phaser the value -1 means 'forever' in lots of cases, this const allows you to use it instead + * to help you remember what the value is doing in your code. + * + * @name Phaser.FOREVER + * @const + * @type {number} + * @since 3.0.0 + */ + FOREVER: -1, + + /** + * Direction constant. + * + * @name Phaser.NONE + * @const + * @type {number} + * @since 3.0.0 + */ + NONE: 4, + + /** + * Direction constant. + * + * @name Phaser.UP + * @const + * @type {number} + * @since 3.0.0 + */ + UP: 5, + + /** + * Direction constant. + * + * @name Phaser.DOWN + * @const + * @type {number} + * @since 3.0.0 + */ + DOWN: 6, + + /** + * Direction constant. + * + * @name Phaser.LEFT + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT: 7, + + /** + * Direction constant. + * + * @name Phaser.RIGHT + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT: 8 + +}; + +module.exports = CONST; + + +/***/ }), + +/***/ 69547: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(8054); +var DefaultPlugins = __webpack_require__(42363); +var Device = __webpack_require__(82264); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var IsPlainObject = __webpack_require__(41212); +var NOOP = __webpack_require__(29747); +var PhaserMath = __webpack_require__(75508); +var ValueToColor = __webpack_require__(80333); + +/** + * @classdesc + * The active game configuration settings, parsed from a {@link Phaser.Types.Core.GameConfig} object. + * + * @class Config + * @memberof Phaser.Core + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Core.GameConfig} [GameConfig] - The configuration object for your Phaser Game instance. + * + * @see Phaser.Game#config + */ +var Config = new Class({ + + initialize: + + function Config (config) + { + if (config === undefined) { config = {}; } + + var defaultBannerColor = [ + '#ff0000', + '#ffff00', + '#00ff00', + '#00ffff', + '#000000' + ]; + + var defaultBannerTextColor = '#ffffff'; + + // Scale Manager - Anything set in here over-rides anything set in the core game config + + var scaleConfig = GetValue(config, 'scale', null); + + /** + * @const {(number|string)} Phaser.Core.Config#width - The width of the underlying canvas, in pixels. + */ + this.width = GetValue(scaleConfig, 'width', 1024, config); + + /** + * @const {(number|string)} Phaser.Core.Config#height - The height of the underlying canvas, in pixels. + */ + this.height = GetValue(scaleConfig, 'height', 768, config); + + /** + * @const {(Phaser.Scale.ZoomType|number)} Phaser.Core.Config#zoom - The zoom factor, as used by the Scale Manager. + */ + this.zoom = GetValue(scaleConfig, 'zoom', 1, config); + + /** + * @const {?*} Phaser.Core.Config#parent - A parent DOM element into which the canvas created by the renderer will be injected. + */ + this.parent = GetValue(scaleConfig, 'parent', undefined, config); + + /** + * @const {Phaser.Scale.ScaleModeType} Phaser.Core.Config#scaleMode - The scale mode as used by the Scale Manager. The default is zero, which is no scaling. + */ + this.scaleMode = GetValue(scaleConfig, (scaleConfig) ? 'mode' : 'scaleMode', 0, config); + + /** + * @const {boolean} Phaser.Core.Config#expandParent - Is the Scale Manager allowed to adjust the CSS height property of the parent to be 100%? + */ + this.expandParent = GetValue(scaleConfig, 'expandParent', true, config); + + /** + * @const {boolean} Phaser.Core.Config#autoRound - Automatically round the display and style sizes of the canvas. This can help with performance in lower-powered devices. + */ + this.autoRound = GetValue(scaleConfig, 'autoRound', false, config); + + /** + * @const {Phaser.Scale.CenterType} Phaser.Core.Config#autoCenter - Automatically center the canvas within the parent? + */ + this.autoCenter = GetValue(scaleConfig, 'autoCenter', 0, config); + + /** + * @const {number} Phaser.Core.Config#resizeInterval - How many ms should elapse before checking if the browser size has changed? + */ + this.resizeInterval = GetValue(scaleConfig, 'resizeInterval', 500, config); + + /** + * @const {?(HTMLElement|string)} Phaser.Core.Config#fullscreenTarget - The DOM element that will be sent into full screen mode, or its `id`. If undefined Phaser will create its own div and insert the canvas into it when entering fullscreen mode. + */ + this.fullscreenTarget = GetValue(scaleConfig, 'fullscreenTarget', null, config); + + /** + * @const {number} Phaser.Core.Config#minWidth - The minimum width, in pixels, the canvas will scale down to. A value of zero means no minimum. + */ + this.minWidth = GetValue(scaleConfig, 'min.width', 0, config); + + /** + * @const {number} Phaser.Core.Config#maxWidth - The maximum width, in pixels, the canvas will scale up to. A value of zero means no maximum. + */ + this.maxWidth = GetValue(scaleConfig, 'max.width', 0, config); + + /** + * @const {number} Phaser.Core.Config#minHeight - The minimum height, in pixels, the canvas will scale down to. A value of zero means no minimum. + */ + this.minHeight = GetValue(scaleConfig, 'min.height', 0, config); + + /** + * @const {number} Phaser.Core.Config#maxHeight - The maximum height, in pixels, the canvas will scale up to. A value of zero means no maximum. + */ + this.maxHeight = GetValue(scaleConfig, 'max.height', 0, config); + + /** + * @const {number} Phaser.Core.Config#snapWidth - The horizontal amount to snap the canvas by when the Scale Manager is resizing. A value of zero means no snapping. + */ + this.snapWidth = GetValue(scaleConfig, 'snap.width', 0, config); + + /** + * @const {number} Phaser.Core.Config#snapHeight - The vertical amount to snap the canvas by when the Scale Manager is resizing. A value of zero means no snapping. + */ + this.snapHeight = GetValue(scaleConfig, 'snap.height', 0, config); + + /** + * @const {number} Phaser.Core.Config#renderType - Force Phaser to use a specific renderer. Can be `CONST.CANVAS`, `CONST.WEBGL`, `CONST.HEADLESS` or `CONST.AUTO` (default) + */ + this.renderType = GetValue(config, 'type', CONST.AUTO); + + /** + * @const {?HTMLCanvasElement} Phaser.Core.Config#canvas - Force Phaser to use your own Canvas element instead of creating one. + */ + this.canvas = GetValue(config, 'canvas', null); + + /** + * @const {?(CanvasRenderingContext2D|WebGLRenderingContext)} Phaser.Core.Config#context - Force Phaser to use your own Canvas context instead of creating one. + */ + this.context = GetValue(config, 'context', null); + + /** + * @const {?string} Phaser.Core.Config#canvasStyle - Optional CSS attributes to be set on the canvas object created by the renderer. + */ + this.canvasStyle = GetValue(config, 'canvasStyle', null); + + /** + * @const {boolean} Phaser.Core.Config#customEnvironment - Is Phaser running under a custom (non-native web) environment? If so, set this to `true` to skip internal Feature detection. If `true` the `renderType` cannot be left as `AUTO`. + */ + this.customEnvironment = GetValue(config, 'customEnvironment', false); + + /** + * @const {?object} Phaser.Core.Config#sceneConfig - The default Scene configuration object. + */ + this.sceneConfig = GetValue(config, 'scene', null); + + /** + * @const {string[]} Phaser.Core.Config#seed - A seed which the Random Data Generator will use. If not given, a dynamic seed based on the time is used. + */ + this.seed = GetValue(config, 'seed', [ (Date.now() * Math.random()).toString() ]); + + PhaserMath.RND = new PhaserMath.RandomDataGenerator(this.seed); + + /** + * @const {string} Phaser.Core.Config#gameTitle - The title of the game. + */ + this.gameTitle = GetValue(config, 'title', ''); + + /** + * @const {string} Phaser.Core.Config#gameURL - The URL of the game. + */ + this.gameURL = GetValue(config, 'url', 'https://phaser.io/' + CONST.LOG_VERSION); + + /** + * @const {string} Phaser.Core.Config#gameVersion - The version of the game. + */ + this.gameVersion = GetValue(config, 'version', ''); + + /** + * @const {boolean} Phaser.Core.Config#autoFocus - If `true` the window will automatically be given focus immediately and on any future mousedown event. + */ + this.autoFocus = GetValue(config, 'autoFocus', true); + + /** + * @const {(number|boolean)} Phaser.Core.Config#stableSort - `false` or `0` = Use the built-in StableSort (needed for older browsers), `true` or `1` = Rely on ES2019 Array.sort being stable (modern browsers only), or `-1` = Try and determine this automatically based on browser inspection (not guaranteed to work, errs on side of caution). + */ + this.stableSort = GetValue(config, 'stableSort', -1); + + if (this.stableSort === -1) + { + this.stableSort = (Device.browser.es2019) ? 1 : 0; + } + + Device.features.stableSort = this.stableSort; + + // DOM Element Container + + /** + * @const {?boolean} Phaser.Core.Config#domCreateContainer - Should the game create a div element to act as a DOM Container? Only enable if you're using DOM Element objects. You must provide a parent object if you use this feature. + */ + this.domCreateContainer = GetValue(config, 'dom.createContainer', false); + + /** + * @const {?string} Phaser.Core.Config#domPointerEvents - The default `pointerEvents` attribute set on the DOM Container. + */ + this.domPointerEvents = GetValue(config, 'dom.pointerEvents', 'none'); + + // Input + + /** + * @const {boolean} Phaser.Core.Config#inputKeyboard - Enable the Keyboard Plugin. This can be disabled in games that don't need keyboard input. + */ + this.inputKeyboard = GetValue(config, 'input.keyboard', true); + + /** + * @const {*} Phaser.Core.Config#inputKeyboardEventTarget - The DOM Target to listen for keyboard events on. Defaults to `window` if not specified. + */ + this.inputKeyboardEventTarget = GetValue(config, 'input.keyboard.target', window); + + /** + * @const {?number[]} Phaser.Core.Config#inputKeyboardCapture - `preventDefault` will be called on every non-modified key which has a key code in this array. By default, it is empty. + */ + this.inputKeyboardCapture = GetValue(config, 'input.keyboard.capture', []); + + /** + * @const {(boolean|object)} Phaser.Core.Config#inputMouse - Enable the Mouse Plugin. This can be disabled in games that don't need mouse input. + */ + this.inputMouse = GetValue(config, 'input.mouse', true); + + /** + * @const {?*} Phaser.Core.Config#inputMouseEventTarget - The DOM Target to listen for mouse events on. Defaults to the game canvas if not specified. + */ + this.inputMouseEventTarget = GetValue(config, 'input.mouse.target', null); + + /** + * @const {boolean} Phaser.Core.Config#inputMousePreventDefaultDown - Should `mousedown` DOM events have `preventDefault` called on them? + */ + this.inputMousePreventDefaultDown = GetValue(config, 'input.mouse.preventDefaultDown', true); + + /** + * @const {boolean} Phaser.Core.Config#inputMousePreventDefaultUp - Should `mouseup` DOM events have `preventDefault` called on them? + */ + this.inputMousePreventDefaultUp = GetValue(config, 'input.mouse.preventDefaultUp', true); + + /** + * @const {boolean} Phaser.Core.Config#inputMousePreventDefaultMove - Should `mousemove` DOM events have `preventDefault` called on them? + */ + this.inputMousePreventDefaultMove = GetValue(config, 'input.mouse.preventDefaultMove', true); + + /** + * @const {boolean} Phaser.Core.Config#inputMousePreventDefaultWheel - Should `wheel` DOM events have `preventDefault` called on them? + */ + this.inputMousePreventDefaultWheel = GetValue(config, 'input.mouse.preventDefaultWheel', true); + + /** + * @const {boolean} Phaser.Core.Config#inputTouch - Enable the Touch Plugin. This can be disabled in games that don't need touch input. + */ + this.inputTouch = GetValue(config, 'input.touch', Device.input.touch); + + /** + * @const {?*} Phaser.Core.Config#inputTouchEventTarget - The DOM Target to listen for touch events on. Defaults to the game canvas if not specified. + */ + this.inputTouchEventTarget = GetValue(config, 'input.touch.target', null); + + /** + * @const {boolean} Phaser.Core.Config#inputTouchCapture - Should touch events be captured? I.e. have prevent default called on them. + */ + this.inputTouchCapture = GetValue(config, 'input.touch.capture', true); + + /** + * @const {number} Phaser.Core.Config#inputActivePointers - The number of Pointer objects created by default. In a mouse-only, or non-multi touch game, you can leave this as 1. + */ + this.inputActivePointers = GetValue(config, 'input.activePointers', 1); + + /** + * @const {number} Phaser.Core.Config#inputSmoothFactor - The smoothing factor to apply during Pointer movement. See {@link Phaser.Input.Pointer#smoothFactor}. + */ + this.inputSmoothFactor = GetValue(config, 'input.smoothFactor', 0); + + /** + * @const {boolean} Phaser.Core.Config#inputWindowEvents - Should Phaser listen for input events on the Window? If you disable this, events like 'POINTER_UP_OUTSIDE' will no longer fire. + */ + this.inputWindowEvents = GetValue(config, 'input.windowEvents', true); + + /** + * @const {boolean} Phaser.Core.Config#inputGamepad - Enable the Gamepad Plugin. This can be disabled in games that don't need gamepad input. + */ + this.inputGamepad = GetValue(config, 'input.gamepad', false); + + /** + * @const {*} Phaser.Core.Config#inputGamepadEventTarget - The DOM Target to listen for gamepad events on. Defaults to `window` if not specified. + */ + this.inputGamepadEventTarget = GetValue(config, 'input.gamepad.target', window); + + /** + * @const {boolean} Phaser.Core.Config#disableContextMenu - Set to `true` to disable the right-click context menu. + */ + this.disableContextMenu = GetValue(config, 'disableContextMenu', false); + + /** + * @const {Phaser.Types.Core.AudioConfig} Phaser.Core.Config#audio - The Audio Configuration object. + */ + this.audio = GetValue(config, 'audio', {}); + + // If you do: { banner: false } it won't display any banner at all + + /** + * @const {boolean} Phaser.Core.Config#hideBanner - Don't write the banner line to the console.log. See `Phaser.Types.Core.BannerConfig` for details of this object. + */ + this.hideBanner = (GetValue(config, 'banner', null) === false); + + /** + * @const {boolean} Phaser.Core.Config#hidePhaser - Omit Phaser's name and version from the banner. + */ + this.hidePhaser = GetValue(config, 'banner.hidePhaser', false); + + /** + * @const {string} Phaser.Core.Config#bannerTextColor - The color of the banner text. + */ + this.bannerTextColor = GetValue(config, 'banner.text', defaultBannerTextColor); + + /** + * @const {string[]} Phaser.Core.Config#bannerBackgroundColor - The background colors of the banner. + */ + this.bannerBackgroundColor = GetValue(config, 'banner.background', defaultBannerColor); + + if (this.gameTitle === '' && this.hidePhaser) + { + this.hideBanner = true; + } + + /** + * @const {Phaser.Types.Core.FPSConfig} Phaser.Core.Config#fps - The Frame Rate Configuration object, as parsed by the Timestep class. + */ + this.fps = GetValue(config, 'fps', null); + + // Render Settings - Anything set in here over-rides anything set in the core game config + + var renderConfig = GetValue(config, 'render', null); + + /** + * @const {boolean} Phaser.Core.Config#autoMobileTextures - If iOS or Android detected, automatically restrict WebGL to use 1 texture per batch. This can help performance on some devices. + */ + this.autoMobileTextures = GetValue(renderConfig, 'autoMobileTextures', true, config); + + /** + * @const {boolean} Phaser.Core.Config#antialias - When set to `true`, WebGL uses linear interpolation to draw scaled or rotated textures, giving a smooth appearance. When set to `false`, WebGL uses nearest-neighbor interpolation, giving a crisper appearance. `false` also disables antialiasing of the game canvas itself, if the browser supports it, when the game canvas is scaled. + */ + this.antialias = GetValue(renderConfig, 'antialias', true, config); + + /** + * @const {boolean} Phaser.Core.Config#antialiasGL - Sets the `antialias` property when the WebGL context is created. Setting this value does not impact any subsequent textures that are created, or the canvas style attributes. + */ + this.antialiasGL = GetValue(renderConfig, 'antialiasGL', true, config); + + /** + * @const {string} Phaser.Core.Config#mipmapFilter - Sets the mipmap magFilter to be used when creating WebGL textures. Don't set unless you wish to create mipmaps. Set to one of the following: 'NEAREST', 'LINEAR', 'NEAREST_MIPMAP_NEAREST', 'LINEAR_MIPMAP_NEAREST', 'NEAREST_MIPMAP_LINEAR' or 'LINEAR_MIPMAP_LINEAR'. + */ + this.mipmapFilter = GetValue(renderConfig, 'mipmapFilter', '', config); + + /** + * @const {boolean} Phaser.Core.Config#desynchronized - When set to `true` it will create a desynchronized context for both 2D and WebGL. See https://developers.google.com/web/updates/2019/05/desynchronized for details. + */ + this.desynchronized = GetValue(renderConfig, 'desynchronized', false, config); + + /** + * @const {boolean} Phaser.Core.Config#roundPixels - Draw texture-based Game Objects at only whole-integer positions. Game Objects without textures, like Graphics, ignore this property. + */ + this.roundPixels = GetValue(renderConfig, 'roundPixels', false, config); + + /** + * @const {boolean} Phaser.Core.Config#selfShadow - On textured objects with lighting, this enables self-shadowing based on the diffuse map. + */ + this.selfShadow = GetValue(renderConfig, 'selfShadow', false, config); + + /** + * @const {number} Phaser.Core.Config#pathDetailThreshold - Threshold for combining points into a single path in the WebGL renderer for Graphics objects. This can be overridden at the Graphics object level. + */ + this.pathDetailThreshold = GetValue(renderConfig, 'pathDetailThreshold', 1, config); + + /** + * @const {boolean} Phaser.Core.Config#pixelArt - Prevent pixel art from becoming blurred when scaled. It will remain crisp (tells the WebGL renderer to automatically create textures using a linear filter mode). + */ + this.pixelArt = GetValue(renderConfig, 'pixelArt', this.zoom !== 1, config); + + if (this.pixelArt) + { + this.antialias = false; + this.antialiasGL = false; + this.roundPixels = true; + } + + /** + * @const {boolean} Phaser.Core.Config#smoothPixelArt - WebGL only. Sets `antialias` to true and `pixelArt` to false. Texture-based Game Objects use special shader setting that preserve blocky pixels, but smooth the edges between the pixels. This is only visible when objects are scaled up; otherwise, `antialias` is simpler. + */ + this.smoothPixelArt = GetValue(renderConfig, 'smoothPixelArt', false, config); + + if (this.smoothPixelArt) + { + this.antialias = true; + this.antialiasGL = true; + this.pixelArt = false; + } + + /** + * @const {boolean} Phaser.Core.Config#transparent - Whether the game canvas will have a transparent background. + */ + this.transparent = GetValue(renderConfig, 'transparent', false, config); + + /** + * @const {boolean} Phaser.Core.Config#clearBeforeRender - Whether the game canvas will be cleared between each rendering frame. You can disable this if you have a full-screen background image or game object. + */ + this.clearBeforeRender = GetValue(renderConfig, 'clearBeforeRender', true, config); + + /** + * @const {boolean} Phaser.Core.Config#preserveDrawingBuffer - If the value is true the WebGL buffers will not be cleared and will preserve their values until cleared or overwritten by the author. + */ + this.preserveDrawingBuffer = GetValue(renderConfig, 'preserveDrawingBuffer', false, config); + + /** + * @const {boolean} Phaser.Core.Config#premultipliedAlpha - In WebGL mode, sets the drawing buffer to contain colors with pre-multiplied alpha. + */ + this.premultipliedAlpha = GetValue(renderConfig, 'premultipliedAlpha', true, config); + + /** + * @const {boolean} Phaser.Core.Config#skipUnreadyShaders - Avert stuttering during shader compilation, by enabling parallel shader compilation, where supported. Objects which request a shader that is not yet ready will not be drawn. This prevents stutter, but may cause "pop-in" of objects unless you use a pre-touch strategy. + */ + this.skipUnreadyShaders = GetValue(renderConfig, 'skipUnreadyShaders', false, config); + + /** + * @const {boolean} Phaser.Core.Config#failIfMajorPerformanceCaveat - Let the browser abort creating a WebGL context if it judges performance would be unacceptable. + */ + this.failIfMajorPerformanceCaveat = GetValue(renderConfig, 'failIfMajorPerformanceCaveat', false, config); + + /** + * @const {string} Phaser.Core.Config#powerPreference - "high-performance", "low-power" or "default". A hint to the browser on how much device power the game might use. + */ + this.powerPreference = GetValue(renderConfig, 'powerPreference', 'default', config); + + /** + * @const {number} Phaser.Core.Config#batchSize - The default WebGL Batch size. Represents the number of _quads_ that can be added to a single batch. + */ + this.batchSize = GetValue(renderConfig, 'batchSize', 16384, config); + + /** + * @const {number} Phaser.Core.Config#maxTextures - When in WebGL mode, this sets the maximum number of GPU Textures to use. The default, -1, will use all available units. The WebGL1 spec says all browsers should provide a minimum of 8. + */ + this.maxTextures = GetValue(renderConfig, 'maxTextures', -1, config); + + /** + * @const {number} Phaser.Core.Config#maxLights - The maximum number of lights allowed to be visible within range of a single Camera in the LightManager. + */ + this.maxLights = GetValue(renderConfig, 'maxLights', 10, config); + + var bgc = GetValue(config, 'backgroundColor', 0); + + /** + * @const {Phaser.Display.Color} Phaser.Core.Config#backgroundColor - The background color of the game canvas. The default is black. This value is ignored if `transparent` is set to `true`. + */ + this.backgroundColor = ValueToColor(bgc); + + if (this.transparent) + { + this.backgroundColor = ValueToColor(0x000000); + this.backgroundColor.alpha = 0; + } + + /** + * @const {Phaser.Types.Core.BootCallback} Phaser.Core.Config#preBoot - Called before Phaser boots. Useful for initializing anything not related to Phaser that Phaser may require while booting. + */ + this.preBoot = GetValue(config, 'callbacks.preBoot', NOOP); + + /** + * @const {Phaser.Types.Core.BootCallback} Phaser.Core.Config#postBoot - A function to run at the end of the boot sequence. At this point, all the game systems have started and plugins have been loaded. + */ + this.postBoot = GetValue(config, 'callbacks.postBoot', NOOP); + + /** + * @const {Phaser.Types.Core.PhysicsConfig} Phaser.Core.Config#physics - The Physics Configuration object. + */ + this.physics = GetValue(config, 'physics', {}); + + /** + * @const {(boolean|string)} Phaser.Core.Config#defaultPhysicsSystem - The default physics system. It will be started for each scene. Either 'arcade', 'impact' or 'matter'. + */ + this.defaultPhysicsSystem = GetValue(this.physics, 'default', false); + + /** + * @const {string} Phaser.Core.Config#loaderBaseURL - A URL used to resolve paths given to the loader. Example: 'http://labs.phaser.io/assets/'. + */ + this.loaderBaseURL = GetValue(config, 'loader.baseURL', ''); + + /** + * @const {string} Phaser.Core.Config#loaderPath - A URL path used to resolve relative paths given to the loader. Example: 'images/sprites/'. + */ + this.loaderPath = GetValue(config, 'loader.path', ''); + + /** + * @const {number} Phaser.Core.Config#loaderMaxParallelDownloads - Maximum parallel downloads allowed for resources (Default to 32). + */ + this.loaderMaxParallelDownloads = GetValue(config, 'loader.maxParallelDownloads', (Device.os.android) ? 6 : 32); + + /** + * @const {(string|undefined)} Phaser.Core.Config#loaderCrossOrigin - 'anonymous', 'use-credentials', or `undefined`. If you're not making cross-origin requests, leave this as `undefined`. See {@link https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes}. + */ + this.loaderCrossOrigin = GetValue(config, 'loader.crossOrigin', undefined); + + /** + * @const {string} Phaser.Core.Config#loaderResponseType - The response type of the XHR request, e.g. `blob`, `text`, etc. + */ + this.loaderResponseType = GetValue(config, 'loader.responseType', ''); + + /** + * @const {boolean} Phaser.Core.Config#loaderAsync - Should the XHR request use async or not? + */ + this.loaderAsync = GetValue(config, 'loader.async', true); + + /** + * @const {string} Phaser.Core.Config#loaderUser - Optional username for all XHR requests. + */ + this.loaderUser = GetValue(config, 'loader.user', ''); + + /** + * @const {string} Phaser.Core.Config#loaderPassword - Optional password for all XHR requests. + */ + this.loaderPassword = GetValue(config, 'loader.password', ''); + + /** + * @const {number} Phaser.Core.Config#loaderTimeout - Optional XHR timeout value, in ms. + */ + this.loaderTimeout = GetValue(config, 'loader.timeout', 0); + + /** + * @const {number} Phaser.Core.Config#loaderMaxRetries - The number of times to retry a file load if it fails. + */ + this.loaderMaxRetries = GetValue(config, 'loader.maxRetries', 2); + + /** + * @const {boolean} Phaser.Core.Config#loaderWithCredentials - Optional XHR withCredentials value. + */ + this.loaderWithCredentials = GetValue(config, 'loader.withCredentials', false); + + /** + * @const {string} Phaser.Core.Config#loaderImageLoadType - Optional load type for image, `XHR` is default, or `HTMLImageElement` for a lightweight way. + */ + this.loaderImageLoadType = GetValue(config, 'loader.imageLoadType', 'XHR'); + + // On iOS, Capacitor often runs on a capacitor:// protocol, meaning local files are served from capacitor:// rather than file:// + // See: https://github.com/photonstorm/phaser/issues/5685 + + /** + * @const {string[]} Phaser.Core.Config#loaderLocalScheme - An array of schemes that the Loader considers as being 'local' files. Defaults to: `[ 'file://', 'capacitor://' ]`. + */ + this.loaderLocalScheme = GetValue(config, 'loader.localScheme', [ 'file://', 'capacitor://' ]); + + /** + * @const {number} Phaser.Core.Config#glowQuality - The quality of the Glow filter (defaults to 10) + */ + this.glowQuality = GetValue(config, 'filters.glow.quality', 10); + + /** + * @const {number} Phaser.Core.Config#glowDistance - The distance of the Glow filter (defaults to 10) + */ + this.glowDistance = GetValue(config, 'filters.glow.distance', 10); + + /* + * Allows `plugins` property to either be an array, in which case it just replaces + * the default plugins like previously, or a config object. + * + * plugins: { + * global: [ + * { key: 'TestPlugin', plugin: TestPlugin, start: true, data: { msg: 'The plugin is alive' } }, + * ], + * scene: [ + * { key: 'WireFramePlugin', plugin: WireFramePlugin, systemKey: 'wireFramePlugin', sceneKey: 'wireframe' } + * ], + * default: [], OR + * defaultMerge: [ + * 'ModPlayer' + * ] + * } + */ + + /** + * @const {any} Phaser.Core.Config#installGlobalPlugins - An array of global plugins to be installed. + */ + this.installGlobalPlugins = []; + + /** + * @const {any} Phaser.Core.Config#installScenePlugins - An array of Scene level plugins to be installed. + */ + this.installScenePlugins = []; + + var plugins = GetValue(config, 'plugins', null); + var defaultPlugins = DefaultPlugins.DefaultScene; + + if (plugins) + { + // Old 3.7 array format? + if (Array.isArray(plugins)) + { + this.defaultPlugins = plugins; + } + else if (IsPlainObject(plugins)) + { + this.installGlobalPlugins = GetFastValue(plugins, 'global', []); + this.installScenePlugins = GetFastValue(plugins, 'scene', []); + + if (Array.isArray(plugins.default)) + { + defaultPlugins = plugins.default; + } + else if (Array.isArray(plugins.defaultMerge)) + { + defaultPlugins = defaultPlugins.concat(plugins.defaultMerge); + } + } + } + + /** + * @const {any} Phaser.Core.Config#defaultPlugins - The plugins installed into every Scene (in addition to CoreScene and Global). + */ + this.defaultPlugins = defaultPlugins; + + // Default / Missing Images + var pngPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAg'; + + /** + * @const {string} Phaser.Core.Config#defaultImage - A base64 encoded PNG that will be used as the default blank texture. + */ + this.defaultImage = GetValue(config, 'images.default', pngPrefix + 'AQMAAABJtOi3AAAAA1BMVEX///+nxBvIAAAAAXRSTlMAQObYZgAAABVJREFUeF7NwIEAAAAAgKD9qdeocAMAoAABm3DkcAAAAABJRU5ErkJggg=='); + + /** + * @const {string} Phaser.Core.Config#missingImage - A base64 encoded PNG that will be used as the default texture when a texture is assigned that is missing or not loaded. + */ + this.missingImage = GetValue(config, 'images.missing', pngPrefix + 'CAIAAAD8GO2jAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJ9JREFUeNq01ssOwyAMRFG46v//Mt1ESmgh+DFmE2GPOBARKb2NVjo+17PXLD8a1+pl5+A+wSgFygymWYHBb0FtsKhJDdZlncG2IzJ4ayoMDv20wTmSMzClEgbWYNTAkQ0Z+OJ+A/eWnAaR9+oxCF4Os0H8htsMUp+pwcgBBiMNnAwF8GqIgL2hAzaGFFgZauDPKABmowZ4GL369/0rwACp2yA/ttmvsQAAAABJRU5ErkJggg=='); + + /** + * @const {string} Phaser.Core.Config#whiteImage - A base64 encoded PNG that will be used as the default texture when a texture is assigned that is white or not loaded. + */ + this.whiteImage = GetValue(config, 'images.white', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpi/P//PwMMMDEgAdwcgAADAJZuAwXJYZOzAAAAAElFTkSuQmCC'); + + if (window) + { + if (window.FORCE_WEBGL) + { + this.renderType = CONST.WEBGL; + } + else if (window.FORCE_CANVAS) + { + this.renderType = CONST.CANVAS; + } + } + } + +}); + +module.exports = Config; + + +/***/ }), + +/***/ 86054: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasInterpolation = __webpack_require__(20623); +var CanvasPool = __webpack_require__(27919); +var CONST = __webpack_require__(8054); +var Features = __webpack_require__(89357); + +/** + * Called automatically by Phaser.Game and responsible for creating the renderer it will use. + * + * Relies upon two webpack global flags to be defined: `WEBGL_RENDERER` and `CANVAS_RENDERER` during build time, but not at run-time. + * + * @function Phaser.Core.CreateRenderer + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Phaser.Game instance on which the renderer will be set. + */ +var CreateRenderer = function (game) +{ + var config = game.config; + + if ((config.customEnvironment || config.canvas) && config.renderType === CONST.AUTO) + { + throw new Error('Must set explicit renderType in custom environment'); + } + + // Not a custom environment, didn't provide their own canvas and not headless, so determine the renderer: + if (!config.customEnvironment && !config.canvas && config.renderType !== CONST.HEADLESS) + { + if (config.renderType === CONST.AUTO) + { + config.renderType = Features.webGL ? CONST.WEBGL : CONST.CANVAS; + } + + if (config.renderType === CONST.WEBGL) + { + if (!Features.webGL) { throw new Error('Cannot create WebGL context, aborting.'); } + } + else if (config.renderType === CONST.CANVAS) + { + if (!Features.canvas) { throw new Error('Cannot create Canvas context, aborting.'); } + } + else + { + throw new Error('Unknown value for renderer type: ' + config.renderType); + } + } + + // Pixel Art mode? + if (!config.antialias) + { + CanvasPool.disableSmoothing(); + } + + var baseSize = game.scale.baseSize; + + var width = baseSize.width; + var height = baseSize.height; + + // Does the game config provide its own canvas element to use? + if (config.canvas) + { + game.canvas = config.canvas; + + game.canvas.width = width; + game.canvas.height = height; + } + else + { + game.canvas = CanvasPool.create(game, width, height, config.renderType); + } + + // Does the game config provide some canvas css styles to use? + if (config.canvasStyle) + { + game.canvas.style = config.canvasStyle; + } + + // Pixel Art mode? + if (!config.antialias) + { + CanvasInterpolation.setCrisp(game.canvas); + } + + if (config.renderType === CONST.HEADLESS) + { + // Nothing more to do here + return; + } + + var CanvasRenderer; + var WebGLRenderer; + + if (true) + { + CanvasRenderer = __webpack_require__(68627); + WebGLRenderer = __webpack_require__(74797); + + // Let the config pick the renderer type, as both are included + if (config.renderType === CONST.WEBGL) + { + game.renderer = new WebGLRenderer(game); + } + else + { + game.renderer = new CanvasRenderer(game); + game.context = game.renderer.gameContext; + } + } + + if (false) + {} + + if (false) + {} +}; + +module.exports = CreateRenderer; + + +/***/ }), + +/***/ 96391: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(8054); + +/** + * Called automatically by Phaser.Game and responsible for creating the console.log debug header. + * + * You can customize or disable the header via the Game Config object. + * + * @function Phaser.Core.DebugHeader + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Phaser.Game instance which will output this debug header. + */ +var DebugHeader = function (game) +{ + var config = game.config; + + if (config.hideBanner) + { + return; + } + + var renderType = 'WebGL'; + + if (config.renderType === CONST.CANVAS) + { + renderType = 'Canvas'; + } + else if (config.renderType === CONST.HEADLESS) + { + renderType = 'Headless'; + } + + var audioConfig = config.audio; + var deviceAudio = game.device.audio; + + var audioType; + + if (deviceAudio.webAudio && !audioConfig.disableWebAudio) + { + audioType = 'Web Audio'; + } + else if (audioConfig.noAudio || (!deviceAudio.webAudio && !deviceAudio.audioData)) + { + audioType = 'No Audio'; + } + else + { + audioType = 'HTML5 Audio'; + } + + if (!game.device.browser.ie) + { + var c = ''; + var args = [ c ]; + + if (Array.isArray(config.bannerBackgroundColor)) + { + var lastColor; + + config.bannerBackgroundColor.forEach(function (color) + { + c = c.concat('%c '); + + args.push('background: ' + color); + + lastColor = color; + }); + + // inject the text color + args[args.length - 1] = 'color: ' + config.bannerTextColor + '; background: ' + lastColor; + } + else + { + c = c.concat('%c '); + + args.push('color: ' + config.bannerTextColor + '; background: ' + config.bannerBackgroundColor); + } + + // URL link background color (always transparent to support different browser themes) + args.push('background: transparent'); + + if (config.gameTitle) + { + c = c.concat(config.gameTitle); + + if (config.gameVersion) + { + c = c.concat(' v' + config.gameVersion); + } + + if (!config.hidePhaser) + { + c = c.concat(' / '); + } + } + + if (!config.hidePhaser) + { + c = c.concat('Phaser v' + CONST.VERSION + ' (' + renderType + ' | ' + audioType + ')'); + } + + c = c.concat(' %c ' + config.gameURL); + + // Inject the new string back into the args array + args[0] = c; + + console.log.apply(console, args); + } + else if (window['console']) + { + console.log('Phaser v' + CONST.VERSION + ' / https://phaser.io'); + } +}; + +module.exports = DebugHeader; + + +/***/ }), + +/***/ 50127: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AddToDOM = __webpack_require__(40366); +var AnimationManager = __webpack_require__(60848); +var CacheManager = __webpack_require__(24047); +var CanvasPool = __webpack_require__(27919); +var Class = __webpack_require__(83419); +var Config = __webpack_require__(69547); +var CreateDOMContainer = __webpack_require__(83719); +var CreateRenderer = __webpack_require__(86054); +var DataManager = __webpack_require__(45893); +var DebugHeader = __webpack_require__(96391); +var Device = __webpack_require__(82264); +var DOMContentLoaded = __webpack_require__(57264); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(8443); +var InputManager = __webpack_require__(7003); +var PluginCache = __webpack_require__(37277); +var PluginManager = __webpack_require__(77332); +var ScaleManager = __webpack_require__(76531); +var SceneManager = __webpack_require__(60903); +var TextureEvents = __webpack_require__(69442); +var TextureManager = __webpack_require__(17130); +var TimeStep = __webpack_require__(65898); +var VisibilityHandler = __webpack_require__(51085); + +if (true) +{ + var SoundManagerCreator = __webpack_require__(14747); +} + +/** + * @classdesc + * The Phaser.Game instance is the main controller for the entire Phaser game. It is responsible + * for handling the boot process, parsing the configuration values, creating the renderer, + * and setting-up all of the global Phaser systems, such as sound and input. + * Once that is complete it will start the Scene Manager and then begin the main game loop. + * + * You should generally avoid accessing any of the systems created by Game, and instead use those + * made available to you via the Phaser.Scene Systems class instead. + * + * @class Game + * @memberof Phaser + * @constructor + * @fires Phaser.Core.Events#BLUR + * @fires Phaser.Core.Events#FOCUS + * @fires Phaser.Core.Events#HIDDEN + * @fires Phaser.Core.Events#VISIBLE + * @since 3.0.0 + * + * @param {Phaser.Types.Core.GameConfig} [GameConfig] - The configuration object for your Phaser Game instance. + */ +var Game = new Class({ + + initialize: + + function Game (config) + { + /** + * The parsed Game Configuration object. + * + * The values stored within this object are read-only and should not be changed at run-time. + * + * @name Phaser.Game#config + * @type {Phaser.Core.Config} + * @readonly + * @since 3.0.0 + */ + this.config = new Config(config); + + /** + * A reference to either the Canvas or WebGL Renderer that this Game is using. + * + * @name Phaser.Game#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.0.0 + */ + this.renderer = null; + + /** + * A reference to an HTML Div Element used as the DOM Element Container. + * + * Only set if `createDOMContainer` is `true` in the game config (by default it is `false`) and + * if you provide a parent element to insert the Phaser Game inside. + * + * See the DOM Element Game Object for more details. + * + * @name Phaser.Game#domContainer + * @type {HTMLDivElement} + * @since 3.17.0 + */ + this.domContainer = null; + + /** + * A reference to the HTML Canvas Element that Phaser uses to render the game. + * This is created automatically by Phaser unless you provide a `canvas` property + * in your Game Config. + * + * @name Phaser.Game#canvas + * @type {HTMLCanvasElement} + * @since 3.0.0 + */ + this.canvas = null; + + /** + * A reference to the Rendering Context belonging to the Canvas Element this game is rendering to. + * If the game is running under Canvas it will be a 2d Canvas Rendering Context. + * If the game is running under WebGL it will be a WebGL Rendering Context. + * This context is created automatically by Phaser unless you provide a `context` property + * in your Game Config. + * + * @name Phaser.Game#context + * @type {(CanvasRenderingContext2D|WebGLRenderingContext)} + * @since 3.0.0 + */ + this.context = null; + + /** + * A flag indicating when this Game instance has finished its boot process. + * + * @name Phaser.Game#isBooted + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + this.isBooted = false; + + /** + * A flag indicating if this Game is currently running its game step or not. + * + * @name Phaser.Game#isRunning + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + this.isRunning = false; + + /** + * An Event Emitter which is used to broadcast game-level events from the global systems. + * + * @name Phaser.Game#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events = new EventEmitter(); + + /** + * An instance of the Animation Manager. + * + * The Animation Manager is a global system responsible for managing all animations used within your game. + * + * @name Phaser.Game#anims + * @type {Phaser.Animations.AnimationManager} + * @since 3.0.0 + */ + this.anims = new AnimationManager(this); + + /** + * An instance of the Texture Manager. + * + * The Texture Manager is a global system responsible for managing all textures being used by your game. + * + * @name Phaser.Game#textures + * @type {Phaser.Textures.TextureManager} + * @since 3.0.0 + */ + this.textures = new TextureManager(this); + + /** + * An instance of the Cache Manager. + * + * The Cache Manager is a global system responsible for caching, accessing and releasing external game assets. + * + * @name Phaser.Game#cache + * @type {Phaser.Cache.CacheManager} + * @since 3.0.0 + */ + this.cache = new CacheManager(this); + + /** + * An instance of the Data Manager. This is a global manager, available from any Scene + * and allows you to share and exchange your own game-level data or events without having + * to use an internal event system. + * + * @name Phaser.Game#registry + * @type {Phaser.Data.DataManager} + * @since 3.0.0 + */ + this.registry = new DataManager(this, new EventEmitter()); + + /** + * An instance of the Input Manager. + * + * The Input Manager is a global system responsible for the capture of browser-level input events. + * + * @name Phaser.Game#input + * @type {Phaser.Input.InputManager} + * @since 3.0.0 + */ + this.input = new InputManager(this, this.config); + + /** + * An instance of the Scene Manager. + * + * The Scene Manager is a global system responsible for creating, modifying and updating the Scenes in your game. + * + * @name Phaser.Game#scene + * @type {Phaser.Scenes.SceneManager} + * @since 3.0.0 + */ + this.scene = new SceneManager(this, this.config.sceneConfig); + + /** + * A reference to the Device inspector. + * + * Contains information about the device running this game, such as OS, browser vendor and feature support. + * Used by various systems to determine capabilities and code paths. + * + * @name Phaser.Game#device + * @type {Phaser.DeviceConf} + * @since 3.0.0 + */ + this.device = Device; + + /** + * An instance of the Scale Manager. + * + * The Scale Manager is a global system responsible for handling scaling of the game canvas. + * + * @name Phaser.Game#scale + * @type {Phaser.Scale.ScaleManager} + * @since 3.16.0 + */ + this.scale = new ScaleManager(this, this.config); + + /** + * An instance of the base Sound Manager. + * + * The Sound Manager is a global system responsible for the playback and updating of all audio in your game. + * + * You can disable the inclusion of the Sound Manager in your build by toggling the webpack `FEATURE_SOUND` flag. + * + * @name Phaser.Game#sound + * @type {(Phaser.Sound.NoAudioSoundManager|Phaser.Sound.HTML5AudioSoundManager|Phaser.Sound.WebAudioSoundManager)} + * @since 3.0.0 + */ + this.sound = null; + + if (true) + { + this.sound = SoundManagerCreator.create(this); + } + + /** + * An instance of the Time Step. + * + * The Time Step is a global system responsible for setting-up and responding to the browser frame events, processing + * them and calculating delta values. It then automatically calls the game step. + * + * @name Phaser.Game#loop + * @type {Phaser.Core.TimeStep} + * @since 3.0.0 + */ + this.loop = new TimeStep(this, this.config.fps); + + /** + * An instance of the Plugin Manager. + * + * The Plugin Manager is a global system that allows plugins to register themselves with it, and can then install + * those plugins into Scenes as required. + * + * @name Phaser.Game#plugins + * @type {Phaser.Plugins.PluginManager} + * @since 3.0.0 + */ + this.plugins = new PluginManager(this, this.config); + + /** + * Is this Game pending destruction at the start of the next frame? + * + * @name Phaser.Game#pendingDestroy + * @type {boolean} + * @private + * @since 3.5.0 + */ + this.pendingDestroy = false; + + /** + * Remove the Canvas once the destroy is over? + * + * @name Phaser.Game#removeCanvas + * @type {boolean} + * @private + * @since 3.5.0 + */ + this.removeCanvas = false; + + /** + * Remove everything when the game is destroyed. + * You cannot create a new Phaser instance on the same web page after doing this. + * + * @name Phaser.Game#noReturn + * @type {boolean} + * @private + * @since 3.12.0 + */ + this.noReturn = false; + + /** + * Does the window the game is running in currently have focus or not? + * This is modified by the VisibilityHandler. + * + * @name Phaser.Game#hasFocus + * @type {boolean} + * @readonly + * @since 3.9.0 + */ + this.hasFocus = false; + + /** + * Is the Game currently paused? This will stop everything from updating, + * except the `TimeStep` and related RequestAnimationFrame or setTimeout. + * Those will continue stepping, but the core Game step will be skipped. + * + * @name Phaser.Game#isPaused + * @type {boolean} + * @since 3.60.0 + */ + this.isPaused = false; + + // Wait for the DOM Ready event, then call boot. + DOMContentLoaded(this.boot.bind(this)); + }, + + /** + * This method is called automatically when the DOM is ready. It is responsible for creating the renderer, + * displaying the Debug Header, adding the game canvas to the DOM and emitting the 'boot' event. + * It listens for a 'ready' event from the base systems and once received it will call `Game.start`. + * + * @method Phaser.Game#boot + * @protected + * @fires Phaser.Core.Events#BOOT + * @listens Phaser.Textures.Events#READY + * @since 3.0.0 + */ + boot: function () + { + if (!PluginCache.hasCore('EventEmitter')) + { + console.warn('Aborting. Core Plugins missing.'); + return; + } + + this.isBooted = true; + + this.config.preBoot(this); + + this.scale.preBoot(); + + CreateRenderer(this); + + CreateDOMContainer(this); + + DebugHeader(this); + + AddToDOM(this.canvas, this.config.parent); + + // The Texture Manager has to wait on a couple of non-blocking events before it's fully ready. + // So it will emit this internal event when done: + this.textures.once(TextureEvents.READY, this.texturesReady, this); + + this.events.emit(Events.BOOT); + + if (false) + {} + }, + + /** + * Called automatically when the Texture Manager has finished setting up and preparing the + * default textures. + * + * @method Phaser.Game#texturesReady + * @private + * @fires Phaser.Game#READY + * @since 3.12.0 + */ + texturesReady: function () + { + // Start all the other systems + this.events.emit(Events.READY); + + this.start(); + }, + + /** + * Called automatically by Game.boot once all of the global systems have finished setting themselves up. + * By this point the Game is now ready to start the main loop running. + * It will also enable the Visibility Handler. + * + * @method Phaser.Game#start + * @protected + * @since 3.0.0 + */ + start: function () + { + this.isRunning = true; + + this.config.postBoot(this); + + if (this.renderer) + { + this.loop.start(this.step.bind(this)); + } + else + { + this.loop.start(this.headlessStep.bind(this)); + } + + VisibilityHandler(this); + + var eventEmitter = this.events; + + eventEmitter.on(Events.HIDDEN, this.onHidden, this); + eventEmitter.on(Events.VISIBLE, this.onVisible, this); + eventEmitter.on(Events.BLUR, this.onBlur, this); + eventEmitter.on(Events.FOCUS, this.onFocus, this); + }, + + /** + * The main Game Step. Called automatically by the Time Step, once per browser frame (typically as a result of + * Request Animation Frame, or Set Timeout on very old browsers.) + * + * The step will update the global managers first, then proceed to update each Scene in turn, via the Scene Manager. + * + * It will then render each Scene in turn, via the Renderer. This process emits `prerender` and `postrender` events. + * + * @method Phaser.Game#step + * @fires Phaser.Core.Events#PRE_STEP + * @fires Phaser.Core.Events#STEP + * @fires Phaser.Core.Events#POST_STEP + * @fires Phaser.Core.Events#PRE_RENDER + * @fires Phaser.Core.Events#POST_RENDER + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + step: function (time, delta) + { + if (this.pendingDestroy) + { + return this.runDestroy(); + } + + if (this.isPaused) + { + return; + } + + var eventEmitter = this.events; + + // Global Managers like Input and Sound update in the prestep + + eventEmitter.emit(Events.PRE_STEP, time, delta); + + // This is mostly meant for user-land code and plugins + + eventEmitter.emit(Events.STEP, time, delta); + + // Update the Scene Manager and all active Scenes + + this.scene.update(time, delta); + + // Our final event before rendering starts + + eventEmitter.emit(Events.POST_STEP, time, delta); + + var renderer = this.renderer; + + // Run the Pre-render (clearing the canvas, setting background colors, etc) + + renderer.preRender(); + + eventEmitter.emit(Events.PRE_RENDER, renderer, time, delta); + + // The main render loop. Iterates all Scenes and all Cameras in those scenes, rendering to the renderer instance. + + this.scene.render(renderer); + + // The Post-Render call. Tidies up loose end, takes snapshots, etc. + + renderer.postRender(); + + // The final event before the step repeats. Your last chance to do anything to the canvas before it all starts again. + + eventEmitter.emit(Events.POST_RENDER, renderer, time, delta); + }, + + /** + * A special version of the Game Step for the HEADLESS renderer only. + * + * The main Game Step. Called automatically by the Time Step, once per browser frame (typically as a result of + * Request Animation Frame, or Set Timeout on very old browsers.) + * + * The step will update the global managers first, then proceed to update each Scene in turn, via the Scene Manager. + * + * This process emits `prerender` and `postrender` events, even though nothing actually displays. + * + * @method Phaser.Game#headlessStep + * @fires Phaser.Game#PRE_RENDER + * @fires Phaser.Game#POST_RENDER + * @since 3.2.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + headlessStep: function (time, delta) + { + if (this.pendingDestroy) + { + return this.runDestroy(); + } + + if (this.isPaused) + { + return; + } + + var eventEmitter = this.events; + + // Global Managers like Input and Sound update in the prestep + + eventEmitter.emit(Events.PRE_STEP, time, delta); + + // This is mostly meant for user-land code and plugins + + eventEmitter.emit(Events.STEP, time, delta); + + // Update the Scene Manager and all active Scenes + + this.scene.update(time, delta); + + // Our final event before rendering starts + + eventEmitter.emit(Events.POST_STEP, time, delta); + + // Render + this.scene.isProcessing = false; + + eventEmitter.emit(Events.PRE_RENDER, null, time, delta); + + eventEmitter.emit(Events.POST_RENDER, null, time, delta); + }, + + /** + * Called automatically by the Visibility Handler. + * This will pause the main loop and then emit a pause event. + * + * @method Phaser.Game#onHidden + * @protected + * @fires Phaser.Core.Events#PAUSE + * @since 3.0.0 + */ + onHidden: function () + { + this.loop.pause(); + + this.events.emit(Events.PAUSE); + }, + + /** + * This will pause the entire game and emit a `PAUSE` event. + * + * All of Phaser's internal systems will be paused and the game will not re-render. + * + * Note that it does not pause any Loader requests that are currently in-flight. + * + * @method Phaser.Game#pause + * @fires Phaser.Core.Events#PAUSE + * @since 3.60.0 + */ + pause: function () + { + var wasPaused = this.isPaused; + + this.isPaused = true; + + if (!wasPaused) + { + this.events.emit(Events.PAUSE); + } + }, + + /** + * Called automatically by the Visibility Handler. + * This will resume the main loop and then emit a resume event. + * + * @method Phaser.Game#onVisible + * @protected + * @fires Phaser.Core.Events#RESUME + * @since 3.0.0 + */ + onVisible: function () + { + this.loop.resume(); + + this.events.emit(Events.RESUME, this.loop.pauseDuration); + }, + + /** + * This will resume the entire game and emit a `RESUME` event. + * + * All of Phaser's internal systems will be resumed and the game will start rendering again. + * + * @method Phaser.Game#resume + * @fires Phaser.Core.Events#RESUME + * @since 3.60.0 + */ + resume: function () + { + var wasPaused = this.isPaused; + + this.isPaused = false; + + if (wasPaused) + { + this.events.emit(Events.RESUME, 0); + } + }, + + /** + * Called automatically by the Visibility Handler. + * This will set the main loop into a 'blurred' state, which pauses it. + * + * @method Phaser.Game#onBlur + * @protected + * @since 3.0.0 + */ + onBlur: function () + { + this.hasFocus = false; + + this.loop.blur(); + }, + + /** + * Called automatically by the Visibility Handler. + * This will set the main loop into a 'focused' state, which resumes it. + * + * @method Phaser.Game#onFocus + * @protected + * @since 3.0.0 + */ + onFocus: function () + { + this.hasFocus = true; + + this.loop.focus(); + }, + + /** + * Returns the current game frame. + * + * When the game starts running, the frame is incremented every time Request Animation Frame, or Set Timeout, fires. + * + * @method Phaser.Game#getFrame + * @since 3.16.0 + * + * @return {number} The current game frame. + */ + getFrame: function () + { + return this.loop.frame; + }, + + /** + * Returns the time that the current game step started at, as based on `performance.now`. + * + * @method Phaser.Game#getTime + * @since 3.16.0 + * + * @return {number} The current game timestamp. + */ + getTime: function () + { + return this.loop.now; + }, + + /** + * Flags this Game instance as needing to be destroyed on the _next frame_, making this an asynchronous operation. + * + * It will wait until the current frame has completed and then call `runDestroy` internally. + * + * If you need to react to the games eventual destruction, listen for the `DESTROY` event. + * + * If you **do not** need to run Phaser again on the same web page you can set the `noReturn` argument to `true` and it will free-up + * memory being held by the core Phaser plugins. If you do need to create another game instance on the same page, leave this as `false`. + * + * @method Phaser.Game#destroy + * @fires Phaser.Core.Events#DESTROY + * @since 3.0.0 + * + * @param {boolean} removeCanvas - Set to `true` if you would like the parent canvas element removed from the DOM, or `false` to leave it in place. + * @param {boolean} [noReturn=false] - If `true` all the core Phaser plugins are destroyed. You cannot create another instance of Phaser on the same web page if you do this. + */ + destroy: function (removeCanvas, noReturn) + { + if (noReturn === undefined) { noReturn = false; } + + this.pendingDestroy = true; + + this.removeCanvas = removeCanvas; + this.noReturn = noReturn; + }, + + /** + * Destroys this Phaser.Game instance, all global systems, all sub-systems and all Scenes. + * + * @method Phaser.Game#runDestroy + * @private + * @since 3.5.0 + */ + runDestroy: function () + { + this.scene.destroy(); + + this.events.emit(Events.DESTROY); + + this.events.removeAllListeners(); + + if (this.renderer) + { + this.renderer.destroy(); + } + + if (this.removeCanvas && this.canvas) + { + CanvasPool.remove(this.canvas); + + if (this.canvas.parentNode) + { + this.canvas.parentNode.removeChild(this.canvas); + } + } + + if (this.domContainer && this.domContainer.parentNode) + { + this.domContainer.parentNode.removeChild(this.domContainer); + } + + this.loop.destroy(); + + this.pendingDestroy = false; + } + +}); + +module.exports = Game; + +/** + * "Computers are good at following instructions, but not at reading your mind." - Donald Knuth + */ + + +/***/ }), + +/***/ 65898: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetValue = __webpack_require__(35154); +var NOOP = __webpack_require__(29747); +var RequestAnimationFrame = __webpack_require__(43092); + +// http://www.testufo.com/#test=animation-time-graph + +/** + * @classdesc + * The core runner class that Phaser uses to handle the game loop. It can use either Request Animation Frame, + * or SetTimeout, based on browser support and config settings, to create a continuous loop within the browser. + * + * Each time the loop fires, `TimeStep.step` is called and this is then passed onto the core Game update loop, + * it is the core heartbeat of your game. It will fire as often as Request Animation Frame is capable of handling + * on the target device. + * + * Note that there are lots of situations where a browser will stop updating your game. Such as if the player + * switches tabs, or covers up the browser window with another application. In these cases, the 'heartbeat' + * of your game will pause, and only resume when focus is returned to it by the player. There is no way to avoid + * this situation, all you can do is use the visibility events the browser, and Phaser, provide to detect when + * it has happened and then gracefully recover. + * + * @class TimeStep + * @memberof Phaser.Core + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - A reference to the Phaser.Game instance that owns this Time Step. + * @param {Phaser.Types.Core.FPSConfig} config + */ +var TimeStep = new Class({ + + initialize: + + function TimeStep (game, config) + { + /** + * A reference to the Phaser.Game instance. + * + * @name Phaser.Core.TimeStep#game + * @type {Phaser.Game} + * @readonly + * @since 3.0.0 + */ + this.game = game; + + /** + * The Request Animation Frame DOM Event handler. + * + * @name Phaser.Core.TimeStep#raf + * @type {Phaser.DOM.RequestAnimationFrame} + * @readonly + * @since 3.0.0 + */ + this.raf = new RequestAnimationFrame(); + + /** + * A flag that is set once the TimeStep has started running and toggled when it stops. + * + * @name Phaser.Core.TimeStep#started + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.started = false; + + /** + * A flag that is set once the TimeStep has started running and toggled when it stops. + * The difference between this value and `started` is that `running` is toggled when + * the TimeStep is sent to sleep, where-as `started` remains `true`, only changing if + * the TimeStep is actually stopped, not just paused. + * + * @name Phaser.Core.TimeStep#running + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.running = false; + + /** + * The minimum fps rate you want the Time Step to run at. + * + * Setting this cannot guarantee the browser runs at this rate, it merely influences + * the internal timing values to help the Timestep know when it has gone out of sync. + * + * @name Phaser.Core.TimeStep#minFps + * @type {number} + * @default 5 + * @since 3.0.0 + */ + this.minFps = GetValue(config, 'min', 5); + + /** + * The target fps rate for the Time Step to run at. + * + * Setting this value will not actually change the speed at which the browser runs, that is beyond + * the control of Phaser. Instead, it allows you to determine performance issues and if the Time Step + * is spiraling out of control. + * + * @name Phaser.Core.TimeStep#targetFps + * @type {number} + * @default 60 + * @since 3.0.0 + */ + this.targetFps = GetValue(config, 'target', 60); + + /** + * Enforce a frame rate limit. This forces how often the Game step will run. By default it is zero, + * which means it will run at whatever limit the browser (via RequestAnimationFrame) can handle, which + * is the optimum rate for fast-action or responsive games. + * + * However, if you are building a non-game app, like a graphics generator, or low-intensity game that doesn't + * require 60fps, then you can lower the step rate via this Game Config value: + * + * ```js + * fps: { + * limit: 30 + * } + * ``` + * + * Setting this _beyond_ the rate of RequestAnimationFrame will make no difference at all. + * + * Use it purely to _restrict_ updates in low-intensity situations only. + * + * @name Phaser.Core.TimeStep#fpsLimit + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.fpsLimit = GetValue(config, 'limit', 0); + + /** + * Is the FPS rate limited? + * + * This is set by setting the Game Config `limit` value to a value above zero. + * + * Consider this property as read-only. + * + * @name Phaser.Core.TimeStep#hasFpsLimit + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.hasFpsLimit = (this.fpsLimit > 0); + + /** + * Internal value holding the fps rate limit in ms. + * + * @name Phaser.Core.TimeStep#_limitRate + * @type {number} + * @private + * @since 3.60.0 + */ + this._limitRate = (this.hasFpsLimit) ? (1000 / this.fpsLimit) : 0; + + /** + * The minimum fps value in ms. + * + * Defaults to 200ms between frames (i.e. super slow!) + * + * @name Phaser.Core.TimeStep#_min + * @type {number} + * @private + * @since 3.0.0 + */ + this._min = 1000 / this.minFps; + + /** + * The target fps value in ms. + * + * Defaults to 16.66ms between frames (i.e. normal) + * + * @name Phaser.Core.TimeStep#_target + * @type {number} + * @private + * @since 3.0.0 + */ + this._target = 1000 / this.targetFps; + + /** + * An exponential moving average of the frames per second. + * + * @name Phaser.Core.TimeStep#actualFps + * @type {number} + * @readonly + * @default 60 + * @since 3.0.0 + */ + this.actualFps = this.targetFps; + + /** + * The time at which the next fps rate update will take place. + * + * When an fps update happens, the `framesThisSecond` value is reset. + * + * @name Phaser.Core.TimeStep#nextFpsUpdate + * @type {number} + * @readonly + * @default 0 + * @since 3.0.0 + */ + this.nextFpsUpdate = 0; + + /** + * The number of frames processed this second. + * + * @name Phaser.Core.TimeStep#framesThisSecond + * @type {number} + * @readonly + * @default 0 + * @since 3.0.0 + */ + this.framesThisSecond = 0; + + /** + * A callback to be invoked each time the TimeStep steps. + * + * @name Phaser.Core.TimeStep#callback + * @type {Phaser.Types.Core.TimeStepCallback} + * @default NOOP + * @since 3.0.0 + */ + this.callback = NOOP; + + /** + * You can force the TimeStep to use SetTimeOut instead of Request Animation Frame by setting + * the `forceSetTimeOut` property to `true` in the Game Configuration object. It cannot be changed at run-time. + * + * @name Phaser.Core.TimeStep#forceSetTimeOut + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.forceSetTimeOut = GetValue(config, 'forceSetTimeOut', false); + + /** + * The time, updated each step by adding the elapsed delta time to the previous value. + * + * This differs from the `TimeStep.now` value, which is the high resolution time value + * as provided by Request Animation Frame. + * + * @name Phaser.Core.TimeStep#time + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.time = 0; + + /** + * The time at which the game started running. + * + * This value is adjusted if the game is then paused and resumes. + * + * @name Phaser.Core.TimeStep#startTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.startTime = 0; + + /** + * The time of the previous step. + * + * This is typically a high resolution timer value, as provided by Request Animation Frame. + * + * @name Phaser.Core.TimeStep#lastTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.lastTime = 0; + + /** + * The current frame the game is on. This counter is incremented once every game step, regardless of how much + * time has passed and is unaffected by delta smoothing. + * + * @name Phaser.Core.TimeStep#frame + * @type {number} + * @readonly + * @default 0 + * @since 3.0.0 + */ + this.frame = 0; + + /** + * Is the browser currently considered in focus by the Page Visibility API? + * + * This value is set in the `blur` method, which is called automatically by the Game instance. + * + * @name Phaser.Core.TimeStep#inFocus + * @type {boolean} + * @readonly + * @default true + * @since 3.0.0 + */ + this.inFocus = true; + + /** + * The duration of the most recent game pause, if any, in ms. + * + * @name Phaser.Core.TimeStep#pauseDuration + * @type {number} + * @readonly + * @default 0 + * @since 3.85.0 + */ + this.pauseDuration = 0; + + /** + * The timestamp at which the game became paused, as determined by the Page Visibility API. + * + * @name Phaser.Core.TimeStep#_pauseTime + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._pauseTime = 0; + + /** + * An internal counter to allow for the browser 'cooling down' after coming back into focus. + * + * @name Phaser.Core.TimeStep#_coolDown + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._coolDown = 0; + + /** + * The delta time, in ms, since the last game step. This is a clamped and smoothed average value. + * + * @name Phaser.Core.TimeStep#delta + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.delta = 0; + + /** + * Internal index of the delta history position. + * + * @name Phaser.Core.TimeStep#deltaIndex + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.deltaIndex = 0; + + /** + * Internal array holding the previous delta values, used for delta smoothing. + * + * @name Phaser.Core.TimeStep#deltaHistory + * @type {number[]} + * @since 3.0.0 + */ + this.deltaHistory = []; + + /** + * The maximum number of delta values that are retained in order to calculate a smoothed moving average. + * + * This can be changed in the Game Config via the `fps.deltaHistory` property. The default is 10. + * + * @name Phaser.Core.TimeStep#deltaSmoothingMax + * @type {number} + * @default 10 + * @since 3.0.0 + */ + this.deltaSmoothingMax = GetValue(config, 'deltaHistory', 10); + + /** + * The number of frames that the cooldown is set to after the browser panics over the FPS rate, usually + * as a result of switching tabs and regaining focus. + * + * This can be changed in the Game Config via the `fps.panicMax` property. The default is 120. + * + * @name Phaser.Core.TimeStep#panicMax + * @type {number} + * @default 120 + * @since 3.0.0 + */ + this.panicMax = GetValue(config, 'panicMax', 120); + + /** + * The actual elapsed time in ms between one update and the next. + * + * Unlike with `delta`, no smoothing, capping, or averaging is applied to this value. + * So please be careful when using this value in math calculations. + * + * @name Phaser.Core.TimeStep#rawDelta + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.rawDelta = 0; + + /** + * The time, set at the start of the current step. + * + * This is typically a high resolution timer value, as provided by Request Animation Frame. + * + * This can differ from the `time` value in that it isn't calculated based on the delta value. + * + * @name Phaser.Core.TimeStep#now + * @type {number} + * @default 0 + * @since 3.18.0 + */ + this.now = 0; + + /** + * Apply smoothing to the delta value used within Phasers internal calculations? + * + * This can be changed in the Game Config via the `fps.smoothStep` property. The default is `true`. + * + * Smoothing helps settle down the delta values after browser tab switches, or other situations + * which could cause significant delta spikes or dips. By default it has been enabled in Phaser 3 + * since the first version, but is now exposed under this property (and the corresponding game config + * `smoothStep` value), to allow you to easily disable it, should you require. + * + * @name Phaser.Core.TimeStep#smoothStep + * @type {boolean} + * @since 3.22.0 + */ + this.smoothStep = GetValue(config, 'smoothStep', true); + }, + + /** + * Called by the Game instance when the DOM window.onBlur event triggers. + * + * @method Phaser.Core.TimeStep#blur + * @since 3.0.0 + */ + blur: function () + { + this.inFocus = false; + }, + + /** + * Called by the Game instance when the DOM window.onFocus event triggers. + * + * @method Phaser.Core.TimeStep#focus + * @since 3.0.0 + */ + focus: function () + { + this.inFocus = true; + + this.resetDelta(); + }, + + /** + * Called when the visibility API says the game is 'hidden' (tab switch out of view, etc) + * + * @method Phaser.Core.TimeStep#pause + * @since 3.0.0 + */ + pause: function () + { + this._pauseTime = window.performance.now(); + }, + + /** + * Called when the visibility API says the game is 'visible' again (tab switch back into view, etc) + * + * @method Phaser.Core.TimeStep#resume + * @since 3.0.0 + */ + resume: function () + { + this.resetDelta(); + + this.pauseDuration = this.time - this._pauseTime; + this.startTime += this.pauseDuration; + }, + + /** + * Resets the time, lastTime, fps averages and delta history. + * Called automatically when a browser sleeps them resumes. + * + * @method Phaser.Core.TimeStep#resetDelta + * @since 3.0.0 + */ + resetDelta: function () + { + var now = window.performance.now(); + + this.time = now; + this.lastTime = now; + this.nextFpsUpdate = now + 1000; + this.framesThisSecond = 0; + + // Pre-populate smoothing array + + for (var i = 0; i < this.deltaSmoothingMax; i++) + { + this.deltaHistory[i] = Math.min(this._target, this.deltaHistory[i]); + } + + this.delta = 0; + this.deltaIndex = 0; + + this._coolDown = this.panicMax; + }, + + /** + * Starts the Time Step running, if it is not already doing so. + * Called automatically by the Game Boot process. + * + * @method Phaser.Core.TimeStep#start + * @since 3.0.0 + * + * @param {Phaser.Types.Core.TimeStepCallback} callback - The callback to be invoked each time the Time Step steps. + */ + start: function (callback) + { + if (this.started) + { + return this; + } + + this.started = true; + this.running = true; + + for (var i = 0; i < this.deltaSmoothingMax; i++) + { + this.deltaHistory[i] = this._target; + } + + this.resetDelta(); + + this.startTime = window.performance.now(); + + this.callback = callback; + + var step = (this.hasFpsLimit) ? this.stepLimitFPS.bind(this) : this.step.bind(this); + + this.raf.start(step, this.forceSetTimeOut, this._target); + }, + + /** + * Takes the delta value and smooths it based on the previous frames. + * + * Called automatically as part of the step. + * + * @method Phaser.Core.TimeStep#smoothDelta + * @since 3.60.0 + * + * @param {number} delta - The delta value for this step. + * + * @return {number} The smoothed delta value. + */ + smoothDelta: function (delta) + { + var idx = this.deltaIndex; + var history = this.deltaHistory; + var max = this.deltaSmoothingMax; + + if (this._coolDown > 0 || !this.inFocus) + { + this._coolDown--; + + delta = Math.min(delta, this._target); + } + + if (delta > this._min) + { + // Probably super bad start time or browser tab context loss, + // so use the last 'sane' delta value + + delta = history[idx]; + + // Clamp delta to min (in case history has become corrupted somehow) + delta = Math.min(delta, this._min); + } + + // Smooth out the delta over the previous X frames + + // add the delta to the smoothing array + history[idx] = delta; + + // adjusts the delta history array index based on the smoothing count + // this stops the array growing beyond the size of deltaSmoothingMax + this.deltaIndex++; + + if (this.deltaIndex >= max) + { + this.deltaIndex = 0; + } + + // Loop the history array, adding the delta values together + var avg = 0; + + for (var i = 0; i < max; i++) + { + avg += history[i]; + } + + // Then divide by the array length to get the average delta + avg /= max; + + return avg; + }, + + /** + * Update the estimate of the frame rate, `fps`. Every second, the number + * of frames that occurred in that second are included in an exponential + * moving average of all frames per second, with an alpha of 0.25. This + * means that more recent seconds affect the estimated frame rate more than + * older seconds. + * + * When a browser window is NOT minimized, but is covered up (i.e. you're using + * another app which has spawned a window over the top of the browser), then it + * will start to throttle the raf callback time. It waits for a while, and then + * starts to drop the frame rate at 1 frame per second until it's down to just over 1fps. + * So if the game was running at 60fps, and the player opens a new window, then + * after 60 seconds (+ the 'buffer time') it'll be down to 1fps, so rafin'g at 1Hz. + * + * When they make the game visible again, the frame rate is increased at a rate of + * approx. 8fps, back up to 60fps (or the max it can obtain) + * + * There is no easy way to determine if this drop in frame rate is because the + * browser is throttling raf, or because the game is struggling with performance + * because you're asking it to do too much on the device. + * + * Compute the new exponential moving average with an alpha of 0.25. + * + * @method Phaser.Core.TimeStep#updateFPS + * @since 3.60.0 + * + * @param {number} time - The timestamp passed in from RequestAnimationFrame or setTimeout. + */ + updateFPS: function (time) + { + this.actualFps = 0.25 * this.framesThisSecond + 0.75 * this.actualFps; + this.nextFpsUpdate = time + 1000; + this.framesThisSecond = 0; + }, + + /** + * The main step method with an fps limiter. This is called each time the browser updates, either by Request Animation Frame, + * or by Set Timeout. It is responsible for calculating the delta values, frame totals, cool down history and more. + * You generally should never call this method directly. + * + * @method Phaser.Core.TimeStep#stepLimitFPS + * @since 3.60.0 + * + * @param {number} time - The timestamp passed in from RequestAnimationFrame or setTimeout. + */ + stepLimitFPS: function (time) + { + this.now = time; + + // delta time (time is in ms) + // Math.max because Chrome will sometimes give negative deltas + var delta = Math.max(0, time - this.lastTime); + + this.rawDelta = delta; + + // Real-world timer advance + this.time += this.rawDelta; + + if (this.smoothStep) + { + delta = this.smoothDelta(delta); + } + + // Set as the world delta value (after smoothing, if applied) + this.delta += delta; + + if (time >= this.nextFpsUpdate) + { + this.updateFPS(time); + } + + this.framesThisSecond++; + + if (this.delta >= this._limitRate) + { + this.callback(time, this.delta); + + this.delta = 0; + } + + // Shift time value over + this.lastTime = time; + + this.frame++; + }, + + /** + * The main step method. This is called each time the browser updates, either by Request Animation Frame, + * or by Set Timeout. It is responsible for calculating the delta values, frame totals, cool down history and more. + * You generally should never call this method directly. + * + * @method Phaser.Core.TimeStep#step + * @since 3.0.0 + * + * @param {number} time - The timestamp passed in from RequestAnimationFrame or setTimeout. + */ + step: function (time) + { + this.now = time; + + // delta time (time is in ms) + // Math.max because Chrome will sometimes give negative deltas + var delta = Math.max(0, time - this.lastTime); + + this.rawDelta = delta; + + // Real-world timer advance + this.time += this.rawDelta; + + if (this.smoothStep) + { + delta = this.smoothDelta(delta); + } + + // Set as the world delta value (after smoothing, if applied) + this.delta = delta; + + if (time >= this.nextFpsUpdate) + { + this.updateFPS(time); + } + + this.framesThisSecond++; + + this.callback(time, delta); + + // Shift time value over + this.lastTime = time; + + this.frame++; + }, + + /** + * Manually calls `TimeStep.step`. + * + * @method Phaser.Core.TimeStep#tick + * @since 3.0.0 + */ + tick: function () + { + var now = window.performance.now(); + + if (this.hasFpsLimit) + { + this.stepLimitFPS(now); + } + else + { + this.step(now); + } + }, + + /** + * Sends the TimeStep to sleep, stopping Request Animation Frame (or SetTimeout) and toggling the `running` flag to false. + * + * @method Phaser.Core.TimeStep#sleep + * @since 3.0.0 + */ + sleep: function () + { + if (this.running) + { + this.raf.stop(); + + this.running = false; + } + }, + + /** + * Wakes-up the TimeStep, restarting Request Animation Frame (or SetTimeout) and toggling the `running` flag to true. + * The `seamless` argument controls if the wake-up should adjust the start time or not. + * + * @method Phaser.Core.TimeStep#wake + * @since 3.0.0 + * + * @param {boolean} [seamless=false] - Adjust the startTime based on the lastTime values. + */ + wake: function (seamless) + { + if (seamless === undefined) { seamless = false; } + + var now = window.performance.now(); + + if (this.running) + { + return; + } + else if (seamless) + { + this.startTime += -this.lastTime + (this.lastTime + now); + } + + var step = (this.hasFpsLimit) ? this.stepLimitFPS.bind(this) : this.step.bind(this); + + this.raf.start(step, this.forceSetTimeOut, this._target); + + this.running = true; + + this.nextFpsUpdate = now + 1000; + this.framesThisSecond = 0; + this.fpsLimitTriggered = false; + + this.tick(); + }, + + /** + * Gets the duration which the game has been running, in seconds. + * + * @method Phaser.Core.TimeStep#getDuration + * @since 3.17.0 + * + * @return {number} The duration in seconds. + */ + getDuration: function () + { + return Math.round(this.lastTime - this.startTime) / 1000; + }, + + /** + * Gets the duration which the game has been running, in ms. + * + * @method Phaser.Core.TimeStep#getDurationMS + * @since 3.17.0 + * + * @return {number} The duration in ms. + */ + getDurationMS: function () + { + return Math.round(this.lastTime - this.startTime); + }, + + /** + * Stops the TimeStep running. + * + * @method Phaser.Core.TimeStep#stop + * @since 3.0.0 + * + * @return {this} The TimeStep object. + */ + stop: function () + { + this.running = false; + this.started = false; + + this.raf.stop(); + + return this; + }, + + /** + * Destroys the TimeStep. This will stop Request Animation Frame, stop the step, clear the callbacks and null + * any objects. + * + * @method Phaser.Core.TimeStep#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.stop(); + + this.raf.destroy(); + + this.raf = null; + this.game = null; + this.callback = null; + } + +}); + +module.exports = TimeStep; + + +/***/ }), + +/***/ 51085: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Events = __webpack_require__(8443); + +/** + * The Visibility Handler is responsible for listening out for document level visibility change events. + * This includes `visibilitychange` if the browser supports it, and blur and focus events. It then uses + * the provided Event Emitter and fires the related events. + * + * @function Phaser.Core.VisibilityHandler + * @fires Phaser.Core.Events#BLUR + * @fires Phaser.Core.Events#FOCUS + * @fires Phaser.Core.Events#HIDDEN + * @fires Phaser.Core.Events#VISIBLE + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Game instance this Visibility Handler is working on. + */ +var VisibilityHandler = function (game) +{ + var hiddenVar; + var eventEmitter = game.events; + + if (document.hidden !== undefined) + { + hiddenVar = 'visibilitychange'; + } + else + { + var vendors = [ 'webkit', 'moz', 'ms' ]; + + vendors.forEach(function (prefix) + { + if (document[prefix + 'Hidden'] !== undefined) + { + document.hidden = function () + { + return document[prefix + 'Hidden']; + }; + + hiddenVar = prefix + 'visibilitychange'; + } + + }); + } + + var onChange = function (event) + { + if (document.hidden || event.type === 'pause') + { + eventEmitter.emit(Events.HIDDEN); + } + else + { + eventEmitter.emit(Events.VISIBLE); + } + }; + + if (hiddenVar) + { + document.addEventListener(hiddenVar, onChange, false); + } + + window.onblur = function () + { + eventEmitter.emit(Events.BLUR); + }; + + window.onfocus = function () + { + eventEmitter.emit(Events.FOCUS); + }; + + // Automatically give the window focus unless config says otherwise + if (window.focus && game.config.autoFocus) + { + window.focus(); + } +}; + +module.exports = VisibilityHandler; + + +/***/ }), + +/***/ 97217: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Blur Event. + * + * This event is dispatched by the Game Visibility Handler when the window in which the Game instance is embedded + * enters a blurred state. The blur event is raised when the window loses focus. This can happen if a user swaps + * tab, or if they simply remove focus from the browser to another app. + * + * @event Phaser.Core.Events#BLUR + * @type {string} + * @since 3.0.0 + */ +module.exports = 'blur'; + + +/***/ }), + +/***/ 47548: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Boot Event. + * + * This event is dispatched when the Phaser Game instance has finished booting, but before it is ready to start running. + * The global systems use this event to know when to set themselves up, dispatching their own `ready` events as required. + * + * @event Phaser.Core.Events#BOOT + * @type {string} + * @since 3.0.0 + */ +module.exports = 'boot'; + + +/***/ }), + +/***/ 19814: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Context Lost Event. + * + * This event is dispatched by the Game if the WebGL Renderer it is using encounters a WebGL Context Lost event from the browser. + * + * The renderer halts all rendering and cannot resume after this happens. + * + * @event Phaser.Core.Events#CONTEXT_LOST + * @type {string} + * @since 3.19.0 + */ +module.exports = 'contextlost'; + + +/***/ }), + +/***/ 68446: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Destroy Event. + * + * This event is dispatched when the game instance has been told to destroy itself. + * Lots of internal systems listen to this event in order to clear themselves out. + * Custom plugins and game code should also do the same. + * + * @event Phaser.Core.Events#DESTROY + * @type {string} + * @since 3.0.0 + */ +module.exports = 'destroy'; + + +/***/ }), + +/***/ 41700: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Focus Event. + * + * This event is dispatched by the Game Visibility Handler when the window in which the Game instance is embedded + * enters a focused state. The focus event is raised when the window re-gains focus, having previously lost it. + * + * @event Phaser.Core.Events#FOCUS + * @type {string} + * @since 3.0.0 + */ +module.exports = 'focus'; + + +/***/ }), + +/***/ 25432: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Hidden Event. + * + * This event is dispatched by the Game Visibility Handler when the document in which the Game instance is embedded + * enters a hidden state. Only browsers that support the Visibility API will cause this event to be emitted. + * + * In most modern browsers, when the document enters a hidden state, the Request Animation Frame and setTimeout, which + * control the main game loop, will automatically pause. There is no way to stop this from happening. It is something + * your game should account for in its own code, should the pause be an issue (i.e. for multiplayer games) + * + * @event Phaser.Core.Events#HIDDEN + * @type {string} + * @since 3.0.0 + */ +module.exports = 'hidden'; + + +/***/ }), + +/***/ 65942: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Pause Event. + * + * This event is dispatched when the Game loop enters a paused state, usually as a result of the Visibility Handler. + * + * @event Phaser.Core.Events#PAUSE + * @type {string} + * @since 3.0.0 + */ +module.exports = 'pause'; + + +/***/ }), + +/***/ 59211: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Post-Render Event. + * + * This event is dispatched right at the end of the render process. + * + * Every Scene will have rendered and been drawn to the canvas by the time this event is fired. + * Use it for any last minute post-processing before the next game step begins. + * + * @event Phaser.Core.Events#POST_RENDER + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - A reference to the current renderer being used by the Game instance. + */ +module.exports = 'postrender'; + + +/***/ }), + +/***/ 47789: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Post-Step Event. + * + * This event is dispatched after the Scene Manager has updated. + * Hook into it from plugins or systems that need to do things before the render starts. + * + * @event Phaser.Core.Events#POST_STEP + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'poststep'; + + +/***/ }), + +/***/ 39066: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Pre-Render Event. + * + * This event is dispatched immediately before any of the Scenes have started to render. + * + * The renderer will already have been initialized this frame, clearing itself and preparing to receive the Scenes for rendering, but it won't have actually drawn anything yet. + * + * @event Phaser.Core.Events#PRE_RENDER + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - A reference to the current renderer being used by the Game instance. + */ +module.exports = 'prerender'; + + +/***/ }), + +/***/ 460: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Pre-Step Event. + * + * This event is dispatched before the main Game Step starts. By this point in the game cycle none of the Scene updates have yet happened. + * Hook into it from plugins or systems that need to update before the Scene Manager does. + * + * @event Phaser.Core.Events#PRE_STEP + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'prestep'; + + +/***/ }), + +/***/ 16175: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Ready Event. + * + * This event is dispatched when the Phaser Game instance has finished booting, the Texture Manager is fully ready, + * and all local systems are now able to start. + * + * @event Phaser.Core.Events#READY + * @type {string} + * @since 3.0.0 + */ +module.exports = 'ready'; + + +/***/ }), + +/***/ 42331: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Resume Event. + * + * This event is dispatched when the game loop leaves a paused state and resumes running. + * + * @event Phaser.Core.Events#RESUME + * @type {string} + * @since 3.0.0 + * + * @param {number} pauseDuration - The duration, in ms, that the game was paused for, or 0 if {@link Phaser.Game#resume} was called. + */ +module.exports = 'resume'; + + +/***/ }), + +/***/ 11966: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Step Event. + * + * This event is dispatched after the Game Pre-Step and before the Scene Manager steps. + * Hook into it from plugins or systems that need to update before the Scene Manager does, but after the core Systems have. + * + * @event Phaser.Core.Events#STEP + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'step'; + + +/***/ }), + +/***/ 32969: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * This event is dispatched when the Scene Manager has created the System Scene, + * which other plugins and systems may use to initialize themselves. + * + * This event is dispatched just once by the Game instance. + * + * @event Phaser.Core.Events#SYSTEM_READY + * @type {string} + * @since 3.70.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + */ +module.exports = 'systemready'; + + +/***/ }), + +/***/ 94830: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Visible Event. + * + * This event is dispatched by the Game Visibility Handler when the document in which the Game instance is embedded + * enters a visible state, previously having been hidden. + * + * Only browsers that support the Visibility API will cause this event to be emitted. + * + * @event Phaser.Core.Events#VISIBLE + * @type {string} + * @since 3.0.0 + */ +module.exports = 'visible'; + + +/***/ }), + +/***/ 8443: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Core.Events + */ + +module.exports = { + + BLUR: __webpack_require__(97217), + BOOT: __webpack_require__(47548), + CONTEXT_LOST: __webpack_require__(19814), + DESTROY: __webpack_require__(68446), + FOCUS: __webpack_require__(41700), + HIDDEN: __webpack_require__(25432), + PAUSE: __webpack_require__(65942), + POST_RENDER: __webpack_require__(59211), + POST_STEP: __webpack_require__(47789), + PRE_RENDER: __webpack_require__(39066), + PRE_STEP: __webpack_require__(460), + READY: __webpack_require__(16175), + RESUME: __webpack_require__(42331), + STEP: __webpack_require__(11966), + SYSTEM_READY: __webpack_require__(32969), + VISIBLE: __webpack_require__(94830) + +}; + + +/***/ }), + +/***/ 42857: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Core + */ + +module.exports = { + + Config: __webpack_require__(69547), + CreateRenderer: __webpack_require__(86054), + DebugHeader: __webpack_require__(96391), + Events: __webpack_require__(8443), + TimeStep: __webpack_require__(65898), + VisibilityHandler: __webpack_require__(51085) + +}; + + +/***/ }), + +/***/ 46728: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog) + +var Class = __webpack_require__(83419); +var CubicBezier = __webpack_require__(36316); +var Curve = __webpack_require__(80021); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A higher-order Bézier curve constructed of four points. + * + * @class CubicBezier + * @extends Phaser.Curves.Curve + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector2[])} p0 - Start point, or an array of point pairs. + * @param {Phaser.Math.Vector2} p1 - Control Point 1. + * @param {Phaser.Math.Vector2} p2 - Control Point 2. + * @param {Phaser.Math.Vector2} p3 - End Point. + */ +var CubicBezierCurve = new Class({ + + Extends: Curve, + + initialize: + + function CubicBezierCurve (p0, p1, p2, p3) + { + Curve.call(this, 'CubicBezierCurve'); + + if (Array.isArray(p0)) + { + p3 = new Vector2(p0[6], p0[7]); + p2 = new Vector2(p0[4], p0[5]); + p1 = new Vector2(p0[2], p0[3]); + p0 = new Vector2(p0[0], p0[1]); + } + + /** + * The start point of this curve. + * + * @name Phaser.Curves.CubicBezier#p0 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p0 = p0; + + /** + * The first control point of this curve. + * + * @name Phaser.Curves.CubicBezier#p1 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p1 = p1; + + /** + * The second control point of this curve. + * + * @name Phaser.Curves.CubicBezier#p2 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p2 = p2; + + /** + * The end point of this curve. + * + * @name Phaser.Curves.CubicBezier#p3 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p3 = p3; + }, + + /** + * Gets the starting point on the curve. + * + * @method Phaser.Curves.CubicBezier#getStartPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return out.copy(this.p0); + }, + + /** + * Returns the resolution of this curve. + * + * @method Phaser.Curves.CubicBezier#getResolution + * @since 3.0.0 + * + * @param {number} divisions - The amount of divisions used by this curve. + * + * @return {number} The resolution of the curve. + */ + getResolution: function (divisions) + { + return divisions; + }, + + /** + * Get point at relative position in curve according to length. + * + * @method Phaser.Curves.CubicBezier#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var p0 = this.p0; + var p1 = this.p1; + var p2 = this.p2; + var p3 = this.p3; + + return out.set(CubicBezier(t, p0.x, p1.x, p2.x, p3.x), CubicBezier(t, p0.y, p1.y, p2.y, p3.y)); + }, + + /** + * Draws this curve to the specified graphics object. + * + * @method Phaser.Curves.CubicBezier#draw + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.Graphics} G - [graphics,$return] + * + * @param {Phaser.GameObjects.Graphics} graphics - The graphics object this curve should be drawn to. + * @param {number} [pointsTotal=32] - The number of intermediary points that make up this curve. A higher number of points will result in a smoother curve. + * + * @return {Phaser.GameObjects.Graphics} The graphics object this curve was drawn to. Useful for method chaining. + */ + draw: function (graphics, pointsTotal) + { + if (pointsTotal === undefined) { pointsTotal = 32; } + + var points = this.getPoints(pointsTotal); + + graphics.beginPath(); + graphics.moveTo(this.p0.x, this.p0.y); + + for (var i = 1; i < points.length; i++) + { + graphics.lineTo(points[i].x, points[i].y); + } + + graphics.strokePath(); + + // So you can chain graphics calls + return graphics; + }, + + /** + * Returns a JSON object that describes this curve. + * + * @method Phaser.Curves.CubicBezier#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Curves.JSONCurve} The JSON object containing this curve data. + */ + toJSON: function () + { + return { + type: this.type, + points: [ + this.p0.x, this.p0.y, + this.p1.x, this.p1.y, + this.p2.x, this.p2.y, + this.p3.x, this.p3.y + ] + }; + } + +}); + +/** + * Generates a curve from a JSON object. + * + * @function Phaser.Curves.CubicBezier.fromJSON + * @since 3.0.0 + * + * @param {Phaser.Types.Curves.JSONCurve} data - The JSON object containing this curve data. + * + * @return {Phaser.Curves.CubicBezier} The curve generated from the JSON object. + */ +CubicBezierCurve.fromJSON = function (data) +{ + var points = data.points; + + var p0 = new Vector2(points[0], points[1]); + var p1 = new Vector2(points[2], points[3]); + var p2 = new Vector2(points[4], points[5]); + var p3 = new Vector2(points[6], points[7]); + + return new CubicBezierCurve(p0, p1, p2, p3); +}; + +module.exports = CubicBezierCurve; + + +/***/ }), + +/***/ 80021: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FromPoints = __webpack_require__(19217); +var Rectangle = __webpack_require__(87841); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Base Curve class, which all other curve types extend. + * + * Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog) + * + * @class Curve + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {string} type - The curve type. + */ +var Curve = new Class({ + + initialize: + + function Curve (type) + { + /** + * String based identifier for the type of curve. + * + * @name Phaser.Curves.Curve#type + * @type {string} + * @since 3.0.0 + */ + this.type = type; + + /** + * The default number of divisions within the curve. + * + * @name Phaser.Curves.Curve#defaultDivisions + * @type {number} + * @default 5 + * @since 3.0.0 + */ + this.defaultDivisions = 5; + + /** + * The quantity of arc length divisions within the curve. + * + * @name Phaser.Curves.Curve#arcLengthDivisions + * @type {number} + * @default 100 + * @since 3.0.0 + */ + this.arcLengthDivisions = 100; + + /** + * An array of cached arc length values. + * + * @name Phaser.Curves.Curve#cacheArcLengths + * @type {number[]} + * @default [] + * @since 3.0.0 + */ + this.cacheArcLengths = []; + + /** + * Does the data of this curve need updating? + * + * @name Phaser.Curves.Curve#needsUpdate + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.needsUpdate = true; + + /** + * For a curve on a Path, `false` means the Path will ignore this curve. + * + * @name Phaser.Curves.Curve#active + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.active = true; + + /** + * A temporary calculation Vector. + * + * @name Phaser.Curves.Curve#_tmpVec2A + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tmpVec2A = new Vector2(); + + /** + * A temporary calculation Vector. + * + * @name Phaser.Curves.Curve#_tmpVec2B + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tmpVec2B = new Vector2(); + }, + + /** + * Draws this curve on the given Graphics object. + * + * The curve is drawn using `Graphics.strokePoints` so will be drawn at whatever the present Graphics stroke color is. + * The Graphics object is not cleared before the draw, so the curve will appear on-top of anything else already rendered to it. + * + * @method Phaser.Curves.Curve#draw + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.Graphics} G - [graphics,$return] + * + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics instance onto which this curve will be drawn. + * @param {number} [pointsTotal=32] - The resolution of the curve. The higher the value the smoother it will render, at the cost of rendering performance. + * + * @return {Phaser.GameObjects.Graphics} The Graphics object to which the curve was drawn. + */ + draw: function (graphics, pointsTotal) + { + if (pointsTotal === undefined) { pointsTotal = 32; } + + // So you can chain graphics calls + return graphics.strokePoints(this.getPoints(pointsTotal)); + }, + + /** + * Returns a Rectangle where the position and dimensions match the bounds of this Curve. + * + * You can control the accuracy of the bounds. The value given is used to work out how many points + * to plot across the curve. Higher values are more accurate at the cost of calculation speed. + * + * @method Phaser.Curves.Curve#getBounds + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} [out] - The Rectangle to store the bounds in. If falsey a new object will be created. + * @param {number} [accuracy=16] - The accuracy of the bounds calculations. + * + * @return {Phaser.Geom.Rectangle} A Rectangle object holding the bounds of this curve. If `out` was given it will be this object. + */ + getBounds: function (out, accuracy) + { + if (!out) { out = new Rectangle(); } + if (accuracy === undefined) { accuracy = 16; } + + var len = this.getLength(); + + if (accuracy > len) + { + accuracy = len / 2; + } + + // The length of the curve in pixels + // So we'll have 1 spaced point per 'accuracy' pixels + + var spaced = Math.max(1, Math.round(len / accuracy)); + + return FromPoints(this.getSpacedPoints(spaced), out); + }, + + /** + * Returns an array of points, spaced out X distance pixels apart. + * The smaller the distance, the larger the array will be. + * + * @method Phaser.Curves.Curve#getDistancePoints + * @since 3.0.0 + * + * @param {number} distance - The distance, in pixels, between each point along the curve. + * + * @return {Phaser.Math.Vector2[]} An Array of Vector2 objects. + */ + getDistancePoints: function (distance) + { + var len = this.getLength(); + + var spaced = Math.max(1, len / distance); + + return this.getSpacedPoints(spaced); + }, + + /** + * Get a point at the end of the curve. + * + * @method Phaser.Curves.Curve#getEndPoint + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2} [out] - Optional Vector object to store the result in. + * + * @return {Phaser.Math.Vector2} Vector2 containing the coordinates of the curves end point. + */ + getEndPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return this.getPointAt(1, out); + }, + + /** + * Get total curve arc length + * + * @method Phaser.Curves.Curve#getLength + * @since 3.0.0 + * + * @return {number} The total length of the curve. + */ + getLength: function () + { + var lengths = this.getLengths(); + + return lengths[lengths.length - 1]; + }, + + + /** + * Get a list of cumulative segment lengths. + * + * These lengths are + * + * - [0] 0 + * - [1] The first segment + * - [2] The first and second segment + * - ... + * - [divisions] All segments + * + * @method Phaser.Curves.Curve#getLengths + * @since 3.0.0 + * + * @param {number} [divisions] - The number of divisions or segments. + * + * @return {number[]} An array of cumulative lengths. + */ + getLengths: function (divisions) + { + if (divisions === undefined) { divisions = this.arcLengthDivisions; } + + if ((this.cacheArcLengths.length === divisions + 1) && !this.needsUpdate) + { + return this.cacheArcLengths; + } + + this.needsUpdate = false; + + var cache = []; + var current; + var last = this.getPoint(0, this._tmpVec2A); + var sum = 0; + + cache.push(0); + + for (var p = 1; p <= divisions; p++) + { + current = this.getPoint(p / divisions, this._tmpVec2B); + + sum += current.distance(last); + + cache.push(sum); + + last.copy(current); + } + + this.cacheArcLengths = cache; + + return cache; // { sums: cache, sum:sum }; Sum is in the last element. + }, + + // Get point at relative position in curve according to arc length + + // - u [0 .. 1] + + /** + * Get a point at a relative position on the curve, by arc length. + * + * @method Phaser.Curves.Curve#getPointAt + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} u - The relative position, [0..1]. + * @param {Phaser.Math.Vector2} [out] - A point to store the result in. + * + * @return {Phaser.Math.Vector2} The point. + */ + getPointAt: function (u, out) + { + var t = this.getUtoTmapping(u); + + return this.getPoint(t, out); + }, + + // Get sequence of points using getPoint( t ) + + /** + * Get a sequence of evenly spaced points from the curve. + * + * You can pass `divisions`, `stepRate`, or neither. + * + * The number of divisions will be + * + * 1. `divisions`, if `divisions` > 0; or + * 2. `this.getLength / stepRate`, if `stepRate` > 0; or + * 3. `this.defaultDivisions` + * + * `1 + divisions` points will be returned. + * + * @method Phaser.Curves.Curve#getPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [out,$return] + * + * @param {number} [divisions] - The number of divisions to make. + * @param {number} [stepRate] - The curve distance between points, implying `divisions`. + * @param {Phaser.Math.Vector2[]} [out] - An optional array to store the points in. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 points from the curve. + */ + getPoints: function (divisions, stepRate, out) + { + if (out === undefined) { out = []; } + + // If divisions is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!divisions) + { + if (!stepRate) + { + divisions = this.defaultDivisions; + } + else + { + divisions = this.getLength() / stepRate; + } + } + + for (var d = 0; d <= divisions; d++) + { + out.push(this.getPoint(d / divisions)); + } + + return out; + }, + + /** + * Get a random point from the curve. + * + * @method Phaser.Curves.Curve#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A point object to store the result in. + * + * @return {Phaser.Math.Vector2} The point. + */ + getRandomPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return this.getPoint(Math.random(), out); + }, + + // Get sequence of points using getPointAt( u ) + + /** + * Get a sequence of equally spaced points (by arc distance) from the curve. + * + * `1 + divisions` points will be returned. + * + * @method Phaser.Curves.Curve#getSpacedPoints + * @since 3.0.0 + * + * @param {number} [divisions=this.defaultDivisions] - The number of divisions to make. + * @param {number} [stepRate] - Step between points. Used to calculate the number of points to return when divisions is falsy. Ignored if divisions is positive. + * @param {Phaser.Math.Vector2[]} [out] - An optional array to store the points in. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 points. + */ + getSpacedPoints: function (divisions, stepRate, out) + { + if (out === undefined) { out = []; } + + // If divisions is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!divisions) + { + if (!stepRate) + { + divisions = this.defaultDivisions; + } + else + { + divisions = this.getLength() / stepRate; + } + } + + for (var d = 0; d <= divisions; d++) + { + var t = this.getUtoTmapping(d / divisions, null, divisions); + + out.push(this.getPoint(t)); + } + + return out; + }, + + /** + * Get a point at the start of the curve. + * + * @method Phaser.Curves.Curve#getStartPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A point to store the result in. + * + * @return {Phaser.Math.Vector2} The point. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return this.getPointAt(0, out); + }, + + /** + * Get a unit vector tangent at a relative position on the curve. + * In case any sub curve does not implement its tangent derivation, + * 2 points a small delta apart will be used to find its gradient + * which seems to give a reasonable approximation + * + * @method Phaser.Curves.Curve#getTangent + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The relative position on the curve, [0..1]. + * @param {Phaser.Math.Vector2} [out] - A vector to store the result in. + * + * @return {Phaser.Math.Vector2} Vector approximating the tangent line at the point t (delta +/- 0.0001) + */ + getTangent: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var delta = 0.0001; + var t1 = t - delta; + var t2 = t + delta; + + // Capping in case of danger + + if (t1 < 0) + { + t1 = 0; + } + + if (t2 > 1) + { + t2 = 1; + } + + this.getPoint(t1, this._tmpVec2A); + this.getPoint(t2, out); + + return out.subtract(this._tmpVec2A).normalize(); + }, + + /** + * Get a unit vector tangent at a relative position on the curve, by arc length. + * + * @method Phaser.Curves.Curve#getTangentAt + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} u - The relative position on the curve, [0..1]. + * @param {Phaser.Math.Vector2} [out] - A vector to store the result in. + * + * @return {Phaser.Math.Vector2} The tangent vector. + */ + getTangentAt: function (u, out) + { + var t = this.getUtoTmapping(u); + + return this.getTangent(t, out); + }, + + /** + * Given a distance in pixels, get a t to find p. + * + * @method Phaser.Curves.Curve#getTFromDistance + * @since 3.0.0 + * + * @param {number} distance - The distance, in pixels. + * @param {number} [divisions] - Optional amount of divisions. + * + * @return {number} The distance. + */ + getTFromDistance: function (distance, divisions) + { + if (distance <= 0) + { + return 0; + } + + return this.getUtoTmapping(0, distance, divisions); + }, + + /** + * Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant. + * + * @method Phaser.Curves.Curve#getUtoTmapping + * @since 3.0.0 + * + * @param {number} u - A float between 0 and 1. + * @param {number} distance - The distance, in pixels. + * @param {number} [divisions] - Optional amount of divisions. + * + * @return {number} The equidistant value. + */ + getUtoTmapping: function (u, distance, divisions) + { + var arcLengths = this.getLengths(divisions); + + var i = 0; + var il = arcLengths.length; + + var targetArcLength; // The targeted u distance value to get + + if (distance) + { + // Cannot overshoot the curve + targetArcLength = Math.min(distance, arcLengths[il - 1]); + } + else + { + targetArcLength = u * arcLengths[il - 1]; + } + + // binary search for the index with largest value smaller than target u distance + + var low = 0; + var high = il - 1; + var comparison; + + while (low <= high) + { + i = Math.floor(low + (high - low) / 2); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats + + comparison = arcLengths[i] - targetArcLength; + + if (comparison < 0) + { + low = i + 1; + } + else if (comparison > 0) + { + high = i - 1; + } + else + { + high = i; + break; + } + } + + i = high; + + if (arcLengths[i] === targetArcLength) + { + return i / (il - 1); + } + + // we could get finer grain at lengths, or use simple interpolation between two points + + var lengthBefore = arcLengths[i]; + var lengthAfter = arcLengths[i + 1]; + + var segmentLength = lengthAfter - lengthBefore; + + // determine where we are between the 'before' and 'after' points + + var segmentFraction = (targetArcLength - lengthBefore) / segmentLength; + + // add that fractional amount to t + + return (i + segmentFraction) / (il - 1); + }, + + /** + * Calculate and cache the arc lengths. + * + * @method Phaser.Curves.Curve#updateArcLengths + * @since 3.0.0 + * + * @see Phaser.Curves.Curve#getLengths() + */ + updateArcLengths: function () + { + this.needsUpdate = true; + + this.getLengths(); + } + +}); + +module.exports = Curve; + + +/***/ }), + +/***/ 73825: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog) + +var Class = __webpack_require__(83419); +var Curve = __webpack_require__(80021); +var DegToRad = __webpack_require__(39506); +var GetValue = __webpack_require__(35154); +var RadToDeg = __webpack_require__(43396); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * An Elliptical Curve derived from the Base Curve class. + * + * See https://en.wikipedia.org/wiki/Elliptic_curve for more details. + * + * @class Ellipse + * @extends Phaser.Curves.Curve + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {(number|Phaser.Types.Curves.EllipseCurveConfig)} [x=0] - The x coordinate of the ellipse, or an Ellipse Curve configuration object. + * @param {number} [y=0] - The y coordinate of the ellipse. + * @param {number} [xRadius=0] - The horizontal radius of ellipse. + * @param {number} [yRadius=0] - The vertical radius of ellipse. + * @param {number} [startAngle=0] - The start angle of the ellipse, in degrees. + * @param {number} [endAngle=360] - The end angle of the ellipse, in degrees. + * @param {boolean} [clockwise=false] - Whether the ellipse angles are given as clockwise (`true`) or counter-clockwise (`false`). + * @param {number} [rotation=0] - The rotation of the ellipse, in degrees. + */ +var EllipseCurve = new Class({ + + Extends: Curve, + + initialize: + + function EllipseCurve (x, y, xRadius, yRadius, startAngle, endAngle, clockwise, rotation) + { + if (typeof x === 'object') + { + var config = x; + + x = GetValue(config, 'x', 0); + y = GetValue(config, 'y', 0); + xRadius = GetValue(config, 'xRadius', 0); + yRadius = GetValue(config, 'yRadius', xRadius); + startAngle = GetValue(config, 'startAngle', 0); + endAngle = GetValue(config, 'endAngle', 360); + clockwise = GetValue(config, 'clockwise', false); + rotation = GetValue(config, 'rotation', 0); + } + else + { + if (yRadius === undefined) { yRadius = xRadius; } + if (startAngle === undefined) { startAngle = 0; } + if (endAngle === undefined) { endAngle = 360; } + if (clockwise === undefined) { clockwise = false; } + if (rotation === undefined) { rotation = 0; } + } + + Curve.call(this, 'EllipseCurve'); + + // Center point + + /** + * The center point of the ellipse. Used for calculating rotation. + * + * @name Phaser.Curves.Ellipse#p0 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p0 = new Vector2(x, y); + + /** + * The horizontal radius of the ellipse. + * + * @name Phaser.Curves.Ellipse#_xRadius + * @type {number} + * @private + * @since 3.0.0 + */ + this._xRadius = xRadius; + + /** + * The vertical radius of the ellipse. + * + * @name Phaser.Curves.Ellipse#_yRadius + * @type {number} + * @private + * @since 3.0.0 + */ + this._yRadius = yRadius; + + // Radians + + /** + * The starting angle of the ellipse in radians. + * + * @name Phaser.Curves.Ellipse#_startAngle + * @type {number} + * @private + * @since 3.0.0 + */ + this._startAngle = DegToRad(startAngle); + + /** + * The end angle of the ellipse in radians. + * + * @name Phaser.Curves.Ellipse#_endAngle + * @type {number} + * @private + * @since 3.0.0 + */ + this._endAngle = DegToRad(endAngle); + + /** + * Anti-clockwise direction. + * + * @name Phaser.Curves.Ellipse#_clockwise + * @type {boolean} + * @private + * @since 3.0.0 + */ + this._clockwise = clockwise; + + /** + * The rotation of the arc. + * + * @name Phaser.Curves.Ellipse#_rotation + * @type {number} + * @private + * @since 3.0.0 + */ + this._rotation = DegToRad(rotation); + }, + + /** + * Gets the starting point on the curve. + * + * @method Phaser.Curves.Ellipse#getStartPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return this.getPoint(0, out); + }, + + /** + * Get the resolution of the curve. + * + * @method Phaser.Curves.Ellipse#getResolution + * @since 3.0.0 + * + * @param {number} divisions - Optional divisions value. + * + * @return {number} The curve resolution. + */ + getResolution: function (divisions) + { + return divisions * 2; + }, + + /** + * Get point at relative position in curve according to length. + * + * @method Phaser.Curves.Ellipse#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var twoPi = Math.PI * 2; + var deltaAngle = this._endAngle - this._startAngle; + var samePoints = Math.abs(deltaAngle) < Number.EPSILON; + + // ensures that deltaAngle is 0 .. 2 PI + while (deltaAngle < 0) + { + deltaAngle += twoPi; + } + + while (deltaAngle > twoPi) + { + deltaAngle -= twoPi; + } + + if (deltaAngle < Number.EPSILON) + { + if (samePoints) + { + deltaAngle = 0; + } + else + { + deltaAngle = twoPi; + } + } + + if (this._clockwise && !samePoints) + { + if (deltaAngle === twoPi) + { + deltaAngle = - twoPi; + } + else + { + deltaAngle = deltaAngle - twoPi; + } + } + + var angle = this._startAngle + t * deltaAngle; + var x = this.p0.x + this._xRadius * Math.cos(angle); + var y = this.p0.y + this._yRadius * Math.sin(angle); + + if (this._rotation !== 0) + { + var cos = Math.cos(this._rotation); + var sin = Math.sin(this._rotation); + + var tx = x - this.p0.x; + var ty = y - this.p0.y; + + // Rotate the point about the center of the ellipse. + x = tx * cos - ty * sin + this.p0.x; + y = tx * sin + ty * cos + this.p0.y; + } + + return out.set(x, y); + }, + + /** + * Sets the horizontal radius of this curve. + * + * @method Phaser.Curves.Ellipse#setXRadius + * @since 3.0.0 + * + * @param {number} value - The horizontal radius of this curve. + * + * @return {this} This curve object. + */ + setXRadius: function (value) + { + this.xRadius = value; + + return this; + }, + + /** + * Sets the vertical radius of this curve. + * + * @method Phaser.Curves.Ellipse#setYRadius + * @since 3.0.0 + * + * @param {number} value - The vertical radius of this curve. + * + * @return {this} This curve object. + */ + setYRadius: function (value) + { + this.yRadius = value; + + return this; + }, + + /** + * Sets the width of this curve. + * + * @method Phaser.Curves.Ellipse#setWidth + * @since 3.0.0 + * + * @param {number} value - The width of this curve. + * + * @return {this} This curve object. + */ + setWidth: function (value) + { + this.xRadius = value / 2; + + return this; + }, + + /** + * Sets the height of this curve. + * + * @method Phaser.Curves.Ellipse#setHeight + * @since 3.0.0 + * + * @param {number} value - The height of this curve. + * + * @return {this} This curve object. + */ + setHeight: function (value) + { + this.yRadius = value / 2; + + return this; + }, + + /** + * Sets the start angle of this curve. + * + * @method Phaser.Curves.Ellipse#setStartAngle + * @since 3.0.0 + * + * @param {number} value - The start angle of this curve, in radians. + * + * @return {this} This curve object. + */ + setStartAngle: function (value) + { + this.startAngle = value; + + return this; + }, + + /** + * Sets the end angle of this curve. + * + * @method Phaser.Curves.Ellipse#setEndAngle + * @since 3.0.0 + * + * @param {number} value - The end angle of this curve, in radians. + * + * @return {this} This curve object. + */ + setEndAngle: function (value) + { + this.endAngle = value; + + return this; + }, + + /** + * Sets if this curve extends clockwise or anti-clockwise. + * + * @method Phaser.Curves.Ellipse#setClockwise + * @since 3.0.0 + * + * @param {boolean} value - The clockwise state of this curve. + * + * @return {this} This curve object. + */ + setClockwise: function (value) + { + this.clockwise = value; + + return this; + }, + + /** + * Sets the rotation of this curve. + * + * @method Phaser.Curves.Ellipse#setRotation + * @since 3.0.0 + * + * @param {number} value - The rotation of this curve, in radians. + * + * @return {this} This curve object. + */ + setRotation: function (value) + { + this.rotation = value; + + return this; + }, + + /** + * The x coordinate of the center of the ellipse. + * + * @name Phaser.Curves.Ellipse#x + * @type {number} + * @since 3.0.0 + */ + x: { + + get: function () + { + return this.p0.x; + }, + + set: function (value) + { + this.p0.x = value; + } + + }, + + /** + * The y coordinate of the center of the ellipse. + * + * @name Phaser.Curves.Ellipse#y + * @type {number} + * @since 3.0.0 + */ + y: { + + get: function () + { + return this.p0.y; + }, + + set: function (value) + { + this.p0.y = value; + } + + }, + + /** + * The horizontal radius of the ellipse. + * + * @name Phaser.Curves.Ellipse#xRadius + * @type {number} + * @since 3.0.0 + */ + xRadius: { + + get: function () + { + return this._xRadius; + }, + + set: function (value) + { + this._xRadius = value; + } + + }, + + /** + * The vertical radius of the ellipse. + * + * @name Phaser.Curves.Ellipse#yRadius + * @type {number} + * @since 3.0.0 + */ + yRadius: { + + get: function () + { + return this._yRadius; + }, + + set: function (value) + { + this._yRadius = value; + } + + }, + + /** + * The start angle of the ellipse in degrees. + * + * @name Phaser.Curves.Ellipse#startAngle + * @type {number} + * @since 3.0.0 + */ + startAngle: { + + get: function () + { + return RadToDeg(this._startAngle); + }, + + set: function (value) + { + this._startAngle = DegToRad(value); + } + + }, + + /** + * The end angle of the ellipse in degrees. + * + * @name Phaser.Curves.Ellipse#endAngle + * @type {number} + * @since 3.0.0 + */ + endAngle: { + + get: function () + { + return RadToDeg(this._endAngle); + }, + + set: function (value) + { + this._endAngle = DegToRad(value); + } + + }, + + /** + * `true` if the ellipse rotation is clockwise or `false` if anti-clockwise. + * + * @name Phaser.Curves.Ellipse#clockwise + * @type {boolean} + * @since 3.0.0 + */ + clockwise: { + + get: function () + { + return this._clockwise; + }, + + set: function (value) + { + this._clockwise = value; + } + + }, + + /** + * The rotation of the ellipse, relative to the center, in degrees. + * + * @name Phaser.Curves.Ellipse#angle + * @type {number} + * @since 3.14.0 + */ + angle: { + + get: function () + { + return RadToDeg(this._rotation); + }, + + set: function (value) + { + this._rotation = DegToRad(value); + } + + }, + + /** + * The rotation of the ellipse, relative to the center, in radians. + * + * @name Phaser.Curves.Ellipse#rotation + * @type {number} + * @since 3.0.0 + */ + rotation: { + + get: function () + { + return this._rotation; + }, + + set: function (value) + { + this._rotation = value; + } + + }, + + /** + * JSON serialization of the curve. + * + * @method Phaser.Curves.Ellipse#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Curves.JSONEllipseCurve} The JSON object containing this curve data. + */ + toJSON: function () + { + return { + type: this.type, + x: this.p0.x, + y: this.p0.y, + xRadius: this._xRadius, + yRadius: this._yRadius, + startAngle: RadToDeg(this._startAngle), + endAngle: RadToDeg(this._endAngle), + clockwise: this._clockwise, + rotation: RadToDeg(this._rotation) + }; + } + +}); + +/** + * Creates a curve from the provided Ellipse Curve Configuration object. + * + * @function Phaser.Curves.Ellipse.fromJSON + * @since 3.0.0 + * + * @param {Phaser.Types.Curves.JSONEllipseCurve} data - The JSON object containing this curve data. + * + * @return {Phaser.Curves.Ellipse} The ellipse curve constructed from the configuration object. + */ +EllipseCurve.fromJSON = function (data) +{ + return new EllipseCurve(data); +}; + +module.exports = EllipseCurve; + + +/***/ }), + +/***/ 33951: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog) + +var Class = __webpack_require__(83419); +var Curve = __webpack_require__(80021); +var FromPoints = __webpack_require__(19217); +var Rectangle = __webpack_require__(87841); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A LineCurve is a "curve" comprising exactly two points (a line segment). + * + * @class Line + * @extends Phaser.Curves.Curve + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|number[])} p0 - The first endpoint. + * @param {Phaser.Math.Vector2} [p1] - The second endpoint. + */ +var LineCurve = new Class({ + + Extends: Curve, + + initialize: + + // vec2s or array + function LineCurve (p0, p1) + { + Curve.call(this, 'LineCurve'); + + if (Array.isArray(p0)) + { + p1 = new Vector2(p0[2], p0[3]); + p0 = new Vector2(p0[0], p0[1]); + } + + /** + * The first endpoint. + * + * @name Phaser.Curves.Line#p0 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p0 = p0; + + /** + * The second endpoint. + * + * @name Phaser.Curves.Line#p1 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p1 = p1; + + // Override default Curve.arcLengthDivisions + + /** + * The quantity of arc length divisions within the curve. + * + * @name Phaser.Curves.Line#arcLengthDivisions + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.arcLengthDivisions = 1; + }, + + /** + * Returns a Rectangle where the position and dimensions match the bounds of this Curve. + * + * @method Phaser.Curves.Line#getBounds + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} [out] - A Rectangle object to store the bounds in. If not given a new Rectangle will be created. + * + * @return {Phaser.Geom.Rectangle} A Rectangle object holding the bounds of this curve. If `out` was given it will be this object. + */ + getBounds: function (out) + { + if (out === undefined) { out = new Rectangle(); } + + return FromPoints([ this.p0, this.p1 ], out); + }, + + /** + * Gets the starting point on the curve. + * + * @method Phaser.Curves.Line#getStartPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return out.copy(this.p0); + }, + + /** + * Gets the resolution of the line. + * + * @method Phaser.Curves.Line#getResolution + * @since 3.0.0 + * + * @param {number} [divisions=1] - The number of divisions to consider. + * + * @return {number} The resolution. Equal to the number of divisions. + */ + getResolution: function (divisions) + { + if (divisions === undefined) { divisions = 1; } + + return divisions; + }, + + /** + * Get point at relative position in curve according to length. + * + * @method Phaser.Curves.Line#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + if (t === 1) + { + return out.copy(this.p1); + } + + out.copy(this.p1).subtract(this.p0).scale(t).add(this.p0); + + return out; + }, + + // Line curve is linear, so we can overwrite default getPointAt + + /** + * Gets a point at a given position on the line. + * + * @method Phaser.Curves.Line#getPointAt + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} u - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPointAt: function (u, out) + { + return this.getPoint(u, out); + }, + + /** + * Gets the slope of the line as a unit vector. + * + * @method Phaser.Curves.Line#getTangent + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} [t] - The relative position on the line, [0..1]. + * @param {Phaser.Math.Vector2} [out] - A vector to store the result in. + * + * @return {Phaser.Math.Vector2} The tangent vector. + */ + getTangent: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + out.copy(this.p1).subtract(this.p0).normalize(); + + return out; + }, + + /** + * Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant. + * + * @method Phaser.Curves.Line#getUtoTmapping + * @since 3.0.0 + * + * @param {number} u - A float between 0 and 1. + * @param {number} distance - The distance, in pixels. + * @param {number} [divisions] - Optional amount of divisions. + * + * @return {number} The equidistant value. + */ + getUtoTmapping: function (u, distance, divisions) + { + var t; + + if (distance) + { + var arcLengths = this.getLengths(divisions); + var lineLength = arcLengths[arcLengths.length - 1]; + + // Cannot overshoot the curve + var targetLineLength = Math.min(distance, lineLength); + + t = targetLineLength / lineLength; + } + else + { + t = u; + } + + return t; + }, + + // Override default Curve.draw because this is better than calling getPoints on a line! + + /** + * Draws this curve on the given Graphics object. + * + * The curve is drawn using `Graphics.lineBetween` so will be drawn at whatever the present Graphics line color is. + * The Graphics object is not cleared before the draw, so the curve will appear on-top of anything else already rendered to it. + * + * @method Phaser.Curves.Line#draw + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.Graphics} G - [graphics,$return] + * + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics instance onto which this curve will be drawn. + * + * @return {Phaser.GameObjects.Graphics} The Graphics object to which the curve was drawn. + */ + draw: function (graphics) + { + graphics.lineBetween(this.p0.x, this.p0.y, this.p1.x, this.p1.y); + + // So you can chain graphics calls + return graphics; + }, + + /** + * Gets a JSON representation of the line. + * + * @method Phaser.Curves.Line#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Curves.JSONCurve} The JSON object containing this curve data. + */ + toJSON: function () + { + return { + type: this.type, + points: [ + this.p0.x, this.p0.y, + this.p1.x, this.p1.y + ] + }; + } + +}); + +/** + * Configures this line from a JSON representation. + * + * @function Phaser.Curves.Line.fromJSON + * @since 3.0.0 + * + * @param {Phaser.Types.Curves.JSONCurve} data - The JSON object containing this curve data. + * + * @return {Phaser.Curves.Line} A new LineCurve object. + */ +LineCurve.fromJSON = function (data) +{ + var points = data.points; + + var p0 = new Vector2(points[0], points[1]); + var p1 = new Vector2(points[2], points[3]); + + return new LineCurve(p0, p1); +}; + +module.exports = LineCurve; + + +/***/ }), + +/***/ 14744: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Curve = __webpack_require__(80021); +var QuadraticBezierInterpolation = __webpack_require__(32112); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A quadratic Bézier curve constructed from two control points. + * + * @class QuadraticBezier + * @extends Phaser.Curves.Curve + * @memberof Phaser.Curves + * @constructor + * @since 3.2.0 + * + * @param {(Phaser.Math.Vector2|number[])} p0 - Start point, or an array of point pairs. + * @param {Phaser.Math.Vector2} p1 - Control Point 1. + * @param {Phaser.Math.Vector2} p2 - Control Point 2. + */ +var QuadraticBezier = new Class({ + + Extends: Curve, + + initialize: + + function QuadraticBezier (p0, p1, p2) + { + Curve.call(this, 'QuadraticBezierCurve'); + + if (Array.isArray(p0)) + { + p2 = new Vector2(p0[4], p0[5]); + p1 = new Vector2(p0[2], p0[3]); + p0 = new Vector2(p0[0], p0[1]); + } + + /** + * The start point. + * + * @name Phaser.Curves.QuadraticBezier#p0 + * @type {Phaser.Math.Vector2} + * @since 3.2.0 + */ + this.p0 = p0; + + /** + * The first control point. + * + * @name Phaser.Curves.QuadraticBezier#p1 + * @type {Phaser.Math.Vector2} + * @since 3.2.0 + */ + this.p1 = p1; + + /** + * The second control point. + * + * @name Phaser.Curves.QuadraticBezier#p2 + * @type {Phaser.Math.Vector2} + * @since 3.2.0 + */ + this.p2 = p2; + }, + + /** + * Gets the starting point on the curve. + * + * @method Phaser.Curves.QuadraticBezier#getStartPoint + * @since 3.2.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return out.copy(this.p0); + }, + + /** + * Get the resolution of the curve. + * + * @method Phaser.Curves.QuadraticBezier#getResolution + * @since 3.2.0 + * + * @param {number} divisions - Optional divisions value. + * + * @return {number} The curve resolution. + */ + getResolution: function (divisions) + { + return divisions; + }, + + /** + * Get point at relative position in curve according to length. + * + * @method Phaser.Curves.QuadraticBezier#getPoint + * @since 3.2.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var p0 = this.p0; + var p1 = this.p1; + var p2 = this.p2; + + return out.set( + QuadraticBezierInterpolation(t, p0.x, p1.x, p2.x), + QuadraticBezierInterpolation(t, p0.y, p1.y, p2.y) + ); + }, + + /** + * Draws this curve on the given Graphics object. + * + * The curve is drawn using `Graphics.strokePoints` so will be drawn at whatever the present Graphics stroke color is. + * The Graphics object is not cleared before the draw, so the curve will appear on-top of anything else already rendered to it. + * + * @method Phaser.Curves.QuadraticBezier#draw + * @since 3.2.0 + * + * @generic {Phaser.GameObjects.Graphics} G - [graphics,$return] + * + * @param {Phaser.GameObjects.Graphics} graphics - `Graphics` object to draw onto. + * @param {number} [pointsTotal=32] - Number of points to be used for drawing the curve. Higher numbers result in smoother curve but require more processing. + * + * @return {Phaser.GameObjects.Graphics} `Graphics` object that was drawn to. + */ + draw: function (graphics, pointsTotal) + { + if (pointsTotal === undefined) { pointsTotal = 32; } + + var points = this.getPoints(pointsTotal); + + graphics.beginPath(); + graphics.moveTo(this.p0.x, this.p0.y); + + for (var i = 1; i < points.length; i++) + { + graphics.lineTo(points[i].x, points[i].y); + } + + graphics.strokePath(); + + // So you can chain graphics calls + return graphics; + }, + + /** + * Converts the curve into a JSON compatible object. + * + * @method Phaser.Curves.QuadraticBezier#toJSON + * @since 3.2.0 + * + * @return {Phaser.Types.Curves.JSONCurve} The JSON object containing this curve data. + */ + toJSON: function () + { + return { + type: this.type, + points: [ + this.p0.x, this.p0.y, + this.p1.x, this.p1.y, + this.p2.x, this.p2.y + ] + }; + } + +}); + +/** + * Creates a curve from a JSON object, e. g. created by `toJSON`. + * + * @function Phaser.Curves.QuadraticBezier.fromJSON + * @since 3.2.0 + * + * @param {Phaser.Types.Curves.JSONCurve} data - The JSON object containing this curve data. + * + * @return {Phaser.Curves.QuadraticBezier} The created curve instance. + */ +QuadraticBezier.fromJSON = function (data) +{ + var points = data.points; + + var p0 = new Vector2(points[0], points[1]); + var p1 = new Vector2(points[2], points[3]); + var p2 = new Vector2(points[4], points[5]); + + return new QuadraticBezier(p0, p1, p2); +}; + +module.exports = QuadraticBezier; + + +/***/ }), + +/***/ 42534: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog) + +var CatmullRom = __webpack_require__(87842); +var Class = __webpack_require__(83419); +var Curve = __webpack_require__(80021); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * Create a smooth 2d spline curve from a series of points. + * + * @class Spline + * @extends Phaser.Curves.Curve + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2[]|number[]|number[][])} [points] - The points that configure the curve. + */ +var SplineCurve = new Class({ + + Extends: Curve, + + initialize: + + function SplineCurve (points) + { + if (points === undefined) { points = []; } + + Curve.call(this, 'SplineCurve'); + + /** + * The Vector2 points that configure the curve. + * + * @name Phaser.Curves.Spline#points + * @type {Phaser.Math.Vector2[]} + * @default [] + * @since 3.0.0 + */ + this.points = []; + + this.addPoints(points); + }, + + /** + * Add a list of points to the current list of Vector2 points of the curve. + * + * @method Phaser.Curves.Spline#addPoints + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2[]|number[]|number[][])} points - The points that configure the curve. + * + * @return {this} This curve object. + */ + addPoints: function (points) + { + for (var i = 0; i < points.length; i++) + { + var p = new Vector2(); + + if (typeof points[i] === 'number') + { + p.x = points[i]; + p.y = points[i + 1]; + i++; + } + else if (Array.isArray(points[i])) + { + // An array of arrays? + p.x = points[i][0]; + p.y = points[i][1]; + } + else + { + p.x = points[i].x; + p.y = points[i].y; + } + + this.points.push(p); + } + + return this; + }, + + /** + * Add a point to the current list of Vector2 points of the curve. + * + * @method Phaser.Curves.Spline#addPoint + * @since 3.0.0 + * + * @param {number} x - The x coordinate of this curve + * @param {number} y - The y coordinate of this curve + * + * @return {Phaser.Math.Vector2} The new Vector2 added to the curve + */ + addPoint: function (x, y) + { + var vec = new Vector2(x, y); + + this.points.push(vec); + + return vec; + }, + + /** + * Gets the starting point on the curve. + * + * @method Phaser.Curves.Spline#getStartPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return out.copy(this.points[0]); + }, + + /** + * Get the resolution of the curve. + * + * @method Phaser.Curves.Spline#getResolution + * @since 3.0.0 + * + * @param {number} divisions - Optional divisions value. + * + * @return {number} The curve resolution. + */ + getResolution: function (divisions) + { + return divisions * this.points.length; + }, + + /** + * Get point at relative position in curve according to length. + * + * @method Phaser.Curves.Spline#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var points = this.points; + + var point = (points.length - 1) * t; + + var intPoint = Math.floor(point); + + var weight = point - intPoint; + + var p0 = points[(intPoint === 0) ? intPoint : intPoint - 1]; + var p1 = points[intPoint]; + var p2 = points[(intPoint > points.length - 2) ? points.length - 1 : intPoint + 1]; + var p3 = points[(intPoint > points.length - 3) ? points.length - 1 : intPoint + 2]; + + return out.set(CatmullRom(weight, p0.x, p1.x, p2.x, p3.x), CatmullRom(weight, p0.y, p1.y, p2.y, p3.y)); + }, + + /** + * Exports a JSON object containing this curve data. + * + * @method Phaser.Curves.Spline#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Curves.JSONCurve} The JSON object containing this curve data. + */ + toJSON: function () + { + var points = []; + + for (var i = 0; i < this.points.length; i++) + { + points.push(this.points[i].x); + points.push(this.points[i].y); + } + + return { + type: this.type, + points: points + }; + } + +}); + +/** + * Imports a JSON object containing this curve data. + * + * @function Phaser.Curves.Spline.fromJSON + * @since 3.0.0 + * + * @param {Phaser.Types.Curves.JSONCurve} data - The JSON object containing this curve data. + * + * @return {Phaser.Curves.Spline} The spline curve created. + */ +SplineCurve.fromJSON = function (data) +{ + return new SplineCurve(data.points); +}; + +module.exports = SplineCurve; + + +/***/ }), + +/***/ 25410: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Curves + */ + +module.exports = { + Path: __webpack_require__(46669), + MoveTo: __webpack_require__(68618), + + CubicBezier: __webpack_require__(46728), + Curve: __webpack_require__(80021), + Ellipse: __webpack_require__(73825), + Line: __webpack_require__(33951), + QuadraticBezier: __webpack_require__(14744), + Spline: __webpack_require__(42534) +}; + + +/***/ }), + +/***/ 68618: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A MoveTo Curve is a very simple curve consisting of only a single point. + * Its intended use is to move the ending point in a Path. + * + * @class MoveTo + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {number} [x=0] - `x` pixel coordinate. + * @param {number} [y=0] - `y` pixel coordinate. + */ +var MoveTo = new Class({ + + initialize: + + function MoveTo (x, y) + { + /** + * Denotes that this Curve does not influence the bounds, points, and drawing of its parent Path. Must be `false` or some methods in the parent Path will throw errors. + * + * @name Phaser.Curves.MoveTo#active + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.active = false; + + /** + * The lone point which this curve consists of. + * + * @name Phaser.Curves.MoveTo#p0 + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.p0 = new Vector2(x, y); + }, + + /** + * Get point at relative position in curve according to length. + * + * @method Phaser.Curves.MoveTo#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The position along the curve to return. Where 0 is the start and 1 is the end. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not given will be created. + * + * @return {Phaser.Math.Vector2} The coordinates of the point on the curve. If an `out` object was given this will be returned. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + return out.copy(this.p0); + }, + + /** + * Retrieves the point at given position in the curve. This will always return this curve's only point. + * + * @method Phaser.Curves.MoveTo#getPointAt + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} u - The position in the path to retrieve, between 0 and 1. Not used. + * @param {Phaser.Math.Vector2} [out] - An optional vector in which to store the point. + * + * @return {Phaser.Math.Vector2} The modified `out` vector, or a new `Vector2` if none was provided. + */ + getPointAt: function (u, out) + { + return this.getPoint(u, out); + }, + + /** + * Gets the resolution of this curve. + * + * @method Phaser.Curves.MoveTo#getResolution + * @since 3.0.0 + * + * @return {number} The resolution of this curve. For a MoveTo the value is always 1. + */ + getResolution: function () + { + return 1; + }, + + /** + * Gets the length of this curve. + * + * @method Phaser.Curves.MoveTo#getLength + * @since 3.0.0 + * + * @return {number} The length of this curve. For a MoveTo the value is always 0. + */ + getLength: function () + { + return 0; + }, + + /** + * Converts this curve into a JSON-serializable object. + * + * @method Phaser.Curves.MoveTo#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Curves.JSONCurve} A primitive object with the curve's type and only point. + */ + toJSON: function () + { + return { + type: 'MoveTo', + points: [ + this.p0.x, this.p0.y + ] + }; + } + +}); + +module.exports = MoveTo; + + +/***/ }), + +/***/ 46669: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Based on the three.js Curve classes created by [zz85](http://www.lab4games.net/zz85/blog) + +var Class = __webpack_require__(83419); +var CubicBezierCurve = __webpack_require__(46728); +var EllipseCurve = __webpack_require__(73825); +var GameObjectFactory = __webpack_require__(39429); +var LineCurve = __webpack_require__(33951); +var MovePathTo = __webpack_require__(68618); +var QuadraticBezierCurve = __webpack_require__(14744); +var Rectangle = __webpack_require__(87841); +var SplineCurve = __webpack_require__(42534); +var Vector2 = __webpack_require__(26099); +var MATH_CONST = __webpack_require__(36383); + +/** + * @classdesc + * A Path combines multiple Curves into one continuous compound curve. + * It does not matter how many Curves are in the Path or what type they are. + * + * A Curve in a Path does not have to start where the previous Curve ends - that is to say, a Path does not + * have to be an uninterrupted curve. Only the order of the Curves influences the actual points on the Path. + * + * @class Path + * @memberof Phaser.Curves + * @constructor + * @since 3.0.0 + * + * @param {number} [x=0] - The X coordinate of the Path's starting point or a {@link Phaser.Types.Curves.JSONPath}. + * @param {number} [y=0] - The Y coordinate of the Path's starting point. + */ +var Path = new Class({ + + initialize: + + function Path (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + /** + * The name of this Path. + * Empty by default and never populated by Phaser, this is left for developers to use. + * + * @name Phaser.Curves.Path#name + * @type {string} + * @default '' + * @since 3.0.0 + */ + this.name = ''; + + /** + * The default number of divisions within a curve. + * + * @name Phaser.Curves.Path#defaultDivisions + * @type {number} + * @default 12 + * @since 3.70.0 + */ + this.defaultDivisions = 12; + + /** + * The list of Curves which make up this Path. + * + * @name Phaser.Curves.Path#curves + * @type {Phaser.Curves.Curve[]} + * @default [] + * @since 3.0.0 + */ + this.curves = []; + + /** + * The cached length of each Curve in the Path. + * + * Used internally by {@link #getCurveLengths}. + * + * @name Phaser.Curves.Path#cacheLengths + * @type {number[]} + * @default [] + * @since 3.0.0 + */ + this.cacheLengths = []; + + /** + * Automatically closes the path. + * + * @name Phaser.Curves.Path#autoClose + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.autoClose = false; + + /** + * The starting point of the Path. + * + * This is not necessarily equivalent to the starting point of the first Curve in the Path. In an empty Path, it's also treated as the ending point. + * + * @name Phaser.Curves.Path#startPoint + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.startPoint = new Vector2(); + + /** + * A temporary vector used to avoid object creation when adding a Curve to the Path. + * + * @name Phaser.Curves.Path#_tmpVec2A + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tmpVec2A = new Vector2(); + + /** + * A temporary vector used to avoid object creation when adding a Curve to the Path. + * + * @name Phaser.Curves.Path#_tmpVec2B + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tmpVec2B = new Vector2(); + + if (typeof x === 'object') + { + this.fromJSON(x); + } + else + { + this.startPoint.set(x, y); + } + }, + + /** + * Appends a Curve to the end of the Path. + * + * The Curve does not have to start where the Path ends or, for an empty Path, at its defined starting point. + * + * @method Phaser.Curves.Path#add + * @since 3.0.0 + * + * @param {Phaser.Curves.Curve} curve - The Curve to append. + * + * @return {this} This Path object. + */ + add: function (curve) + { + this.curves.push(curve); + + return this; + }, + + /** + * Creates a circular Ellipse Curve positioned at the end of the Path. + * + * @method Phaser.Curves.Path#circleTo + * @since 3.0.0 + * + * @param {number} radius - The radius of the circle. + * @param {boolean} [clockwise=false] - `true` to create a clockwise circle as opposed to a counter-clockwise circle. + * @param {number} [rotation=0] - The rotation of the circle in degrees. + * + * @return {this} This Path object. + */ + circleTo: function (radius, clockwise, rotation) + { + if (clockwise === undefined) { clockwise = false; } + + return this.ellipseTo(radius, radius, 0, 360, clockwise, rotation); + }, + + /** + * Ensures that the Path is closed. + * + * A closed Path starts and ends at the same point. If the Path is not closed, a straight Line Curve will be created from the ending point directly to the starting point. During the check, the actual starting point of the Path, i.e. the starting point of the first Curve, will be used as opposed to the Path's defined {@link startPoint}, which could differ. + * + * Calling this method on an empty Path will result in an error. + * + * @method Phaser.Curves.Path#closePath + * @since 3.0.0 + * + * @return {this} This Path object. + */ + closePath: function () + { + // Add a line curve if start and end of lines are not connected + var startPoint = this.curves[0].getPoint(0); + var endPoint = this.curves[this.curves.length - 1].getPoint(1); + + if (!startPoint.equals(endPoint)) + { + // This will copy a reference to the vectors, which probably isn't sensible + this.curves.push(new LineCurve(endPoint, startPoint)); + } + + return this; + }, + + /** + * Creates a cubic bezier curve starting at the previous end point and ending at p3, using p1 and p2 as control points. + * + * @method Phaser.Curves.Path#cubicBezierTo + * @since 3.0.0 + * + * @param {(number|Phaser.Math.Vector2)} x - The x coordinate of the end point. Or, if a Vector2, the p1 value. + * @param {(number|Phaser.Math.Vector2)} y - The y coordinate of the end point. Or, if a Vector2, the p2 value. + * @param {(number|Phaser.Math.Vector2)} control1X - The x coordinate of the first control point. Or, if a Vector2, the p3 value. + * @param {number} [control1Y] - The y coordinate of the first control point. Not used if Vector2s are provided as the first 3 arguments. + * @param {number} [control2X] - The x coordinate of the second control point. Not used if Vector2s are provided as the first 3 arguments. + * @param {number} [control2Y] - The y coordinate of the second control point. Not used if Vector2s are provided as the first 3 arguments. + * + * @return {this} This Path object. + */ + cubicBezierTo: function (x, y, control1X, control1Y, control2X, control2Y) + { + var p0 = this.getEndPoint(); + var p1; + var p2; + var p3; + + // Assume they're all Vector2s + if (x instanceof Vector2) + { + p1 = x; + p2 = y; + p3 = control1X; + } + else + { + p1 = new Vector2(control1X, control1Y); + p2 = new Vector2(control2X, control2Y); + p3 = new Vector2(x, y); + } + + return this.add(new CubicBezierCurve(p0, p1, p2, p3)); + }, + + // Creates a quadratic bezier curve starting at the previous end point and ending at p2, using p1 as a control point + + /** + * Creates a Quadratic Bezier Curve starting at the ending point of the Path. + * + * @method Phaser.Curves.Path#quadraticBezierTo + * @since 3.2.0 + * + * @param {(number|Phaser.Math.Vector2[])} x - The X coordinate of the second control point or, if it's a `Vector2`, the first control point. + * @param {number} [y] - The Y coordinate of the second control point or, if `x` is a `Vector2`, the second control point. + * @param {number} [controlX] - If `x` is not a `Vector2`, the X coordinate of the first control point. + * @param {number} [controlY] - If `x` is not a `Vector2`, the Y coordinate of the first control point. + * + * @return {this} This Path object. + */ + quadraticBezierTo: function (x, y, controlX, controlY) + { + var p0 = this.getEndPoint(); + var p1; + var p2; + + // Assume they're all Vector2s + if (x instanceof Vector2) + { + p1 = x; + p2 = y; + } + else + { + p1 = new Vector2(controlX, controlY); + p2 = new Vector2(x, y); + } + + return this.add(new QuadraticBezierCurve(p0, p1, p2)); + }, + + /** + * Draws all Curves in the Path to a Graphics Game Object. + * + * @method Phaser.Curves.Path#draw + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.Graphics} G - [out,$return] + * + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics Game Object to draw to. + * @param {number} [pointsTotal=32] - The number of points to draw for each Curve. Higher numbers result in a smoother curve but require more processing. + * + * @return {Phaser.GameObjects.Graphics} The Graphics object which was drawn to. + */ + draw: function (graphics, pointsTotal) + { + for (var i = 0; i < this.curves.length; i++) + { + var curve = this.curves[i]; + + if (!curve.active) + { + continue; + } + + curve.draw(graphics, pointsTotal); + } + + return graphics; + }, + + /** + * Creates an ellipse curve positioned at the previous end point, using the given parameters. + * + * @method Phaser.Curves.Path#ellipseTo + * @since 3.0.0 + * + * @param {number} [xRadius=0] - The horizontal radius of ellipse. + * @param {number} [yRadius=0] - The vertical radius of ellipse. + * @param {number} [startAngle=0] - The start angle of the ellipse, in degrees. + * @param {number} [endAngle=360] - The end angle of the ellipse, in degrees. + * @param {boolean} [clockwise=false] - Whether the ellipse angles are given as clockwise (`true`) or counter-clockwise (`false`). + * @param {number} [rotation=0] - The rotation of the ellipse, in degrees. + * + * @return {this} This Path object. + */ + ellipseTo: function (xRadius, yRadius, startAngle, endAngle, clockwise, rotation) + { + var ellipse = new EllipseCurve(0, 0, xRadius, yRadius, startAngle, endAngle, clockwise, rotation); + + var end = this.getEndPoint(this._tmpVec2A); + + // Calculate where to center the ellipse + var start = ellipse.getStartPoint(this._tmpVec2B); + + end.subtract(start); + + ellipse.x = end.x; + ellipse.y = end.y; + + return this.add(ellipse); + }, + + /** + * Creates a Path from a Path Configuration object. + * + * The provided object should be a {@link Phaser.Types.Curves.JSONPath}, as returned by {@link #toJSON}. Providing a malformed object may cause errors. + * + * @method Phaser.Curves.Path#fromJSON + * @since 3.0.0 + * + * @param {Phaser.Types.Curves.JSONPath} data - The JSON object containing the Path data. + * + * @return {this} This Path object. + */ + fromJSON: function (data) + { + // data should be an object matching the Path.toJSON object structure. + + this.curves = []; + this.cacheLengths = []; + + this.startPoint.set(data.x, data.y); + + this.autoClose = data.autoClose; + + for (var i = 0; i < data.curves.length; i++) + { + var curve = data.curves[i]; + + switch (curve.type) + { + case 'LineCurve': + this.add(LineCurve.fromJSON(curve)); + break; + + case 'EllipseCurve': + this.add(EllipseCurve.fromJSON(curve)); + break; + + case 'SplineCurve': + this.add(SplineCurve.fromJSON(curve)); + break; + + case 'CubicBezierCurve': + this.add(CubicBezierCurve.fromJSON(curve)); + break; + + case 'QuadraticBezierCurve': + this.add(QuadraticBezierCurve.fromJSON(curve)); + break; + } + } + + return this; + }, + + /** + * Returns a Rectangle with a position and size matching the bounds of this Path. + * + * @method Phaser.Curves.Path#getBounds + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} [out] - The Rectangle to store the bounds in. + * @param {number} [accuracy=16] - The accuracy of the bounds calculations. Higher values are more accurate at the cost of calculation speed. + * + * @return {Phaser.Geom.Rectangle} The modified `out` Rectangle, or a new Rectangle if none was provided. + */ + getBounds: function (out, accuracy) + { + if (out === undefined) { out = new Rectangle(); } + if (accuracy === undefined) { accuracy = 16; } + + out.x = Number.MAX_VALUE; + out.y = Number.MAX_VALUE; + + var bounds = new Rectangle(); + var maxRight = MATH_CONST.MIN_SAFE_INTEGER; + var maxBottom = MATH_CONST.MIN_SAFE_INTEGER; + + for (var i = 0; i < this.curves.length; i++) + { + var curve = this.curves[i]; + + if (!curve.active) + { + continue; + } + + curve.getBounds(bounds, accuracy); + + out.x = Math.min(out.x, bounds.x); + out.y = Math.min(out.y, bounds.y); + + maxRight = Math.max(maxRight, bounds.right); + maxBottom = Math.max(maxBottom, bounds.bottom); + } + + out.right = maxRight; + out.bottom = maxBottom; + + return out; + }, + + /** + * Returns an array containing the length of the Path at the end of each Curve. + * + * The result of this method will be cached to avoid recalculating it in subsequent calls. The cache is only invalidated when the {@link #curves} array changes in length, leading to potential inaccuracies if a Curve in the Path is changed, or if a Curve is removed and another is added in its place. + * + * @method Phaser.Curves.Path#getCurveLengths + * @since 3.0.0 + * + * @return {number[]} An array containing the length of the Path at the end of each one of its Curves. + */ + getCurveLengths: function () + { + // We use cache values if curves and cache array are same length + + if (this.cacheLengths.length === this.curves.length) + { + return this.cacheLengths; + } + + // Get length of sub-curve + // Push sums into cached array + + var lengths = []; + var sums = 0; + + for (var i = 0; i < this.curves.length; i++) + { + sums += this.curves[i].getLength(); + + lengths.push(sums); + } + + this.cacheLengths = lengths; + + return lengths; + }, + + /** + * Returns the Curve that forms the Path at the given normalized location (between 0 and 1). + * + * @method Phaser.Curves.Path#getCurveAt + * @since 3.60.0 + * + * @param {number} t - The normalized location on the Path, between 0 and 1. + * + * @return {?Phaser.Curves.Curve} The Curve that is part of this Path at a given location, or `null` if no curve was found. + */ + getCurveAt: function (t) + { + var d = t * this.getLength(); + var curveLengths = this.getCurveLengths(); + var i = 0; + + while (i < curveLengths.length) + { + if (curveLengths[i] >= d) + { + return this.curves[i]; + } + + i++; + } + + return null; + }, + + /** + * Returns the ending point of the Path. + * + * A Path's ending point is equivalent to the ending point of the last Curve in the Path. For an empty Path, the ending point is at the Path's defined {@link #startPoint}. + * + * @method Phaser.Curves.Path#getEndPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - The object to store the point in. + * + * @return {Phaser.Math.Vector2} The modified `out` object, or a new Vector2 if none was provided. + */ + getEndPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + if (this.curves.length > 0) + { + this.curves[this.curves.length - 1].getPoint(1, out); + } + else + { + out.copy(this.startPoint); + } + + return out; + }, + + /** + * Returns the total length of the Path. + * + * @see {@link #getCurveLengths} + * + * @method Phaser.Curves.Path#getLength + * @since 3.0.0 + * + * @return {number} The total length of the Path. + */ + getLength: function () + { + var lens = this.getCurveLengths(); + + return lens[lens.length - 1]; + }, + + // To get accurate point with reference to + // entire path distance at time t, + // following has to be done: + + // 1. Length of each sub path have to be known + // 2. Locate and identify type of curve + // 3. Get t for the curve + // 4. Return curve.getPointAt(t') + + /** + * Calculates the coordinates of the point at the given normalized location (between 0 and 1) on the Path. + * + * The location is relative to the entire Path, not to an individual Curve. A location of 0.5 is always in the middle of the Path and is thus an equal distance away from both its starting and ending points. In a Path with one Curve, it would be in the middle of the Curve; in a Path with two Curves, it could be anywhere on either one of them depending on their lengths. + * + * @method Phaser.Curves.Path#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The location of the point to return, between 0 and 1. + * @param {Phaser.Math.Vector2} [out] - The object in which to store the calculated point. + * + * @return {?Phaser.Math.Vector2} The modified `out` object, or a new `Vector2` if none was provided. + */ + getPoint: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var d = t * this.getLength(); + var curveLengths = this.getCurveLengths(); + var i = 0; + + while (i < curveLengths.length) + { + if (curveLengths[i] >= d) + { + var diff = curveLengths[i] - d; + var curve = this.curves[i]; + + var segmentLength = curve.getLength(); + var u = (segmentLength === 0) ? 0 : 1 - diff / segmentLength; + + return curve.getPointAt(u, out); + } + + i++; + } + + // loop where sum != 0, sum > d , sum+1 1 && !points[points.length - 1].equals(points[0])) + { + points.push(points[0]); + } + + return points; + }, + + /** + * Returns a randomly chosen point anywhere on the path. This follows the same rules as `getPoint` in that it may return a point on any Curve inside this path. + * + * When calling this method multiple times, the points are not guaranteed to be equally spaced spatially. + * + * @method Phaser.Curves.Path#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - `Vector2` instance that should be used for storing the result. If `undefined` a new `Vector2` will be created. + * + * @return {Phaser.Math.Vector2} The modified `out` object, or a new `Vector2` if none was provided. + */ + getRandomPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return this.getPoint(Math.random(), out); + }, + + /** + * Divides this Path into a set of equally spaced points, + * + * The resulting points are equally spaced with respect to the points' position on the path, but not necessarily equally spaced spatially. + * + * @method Phaser.Curves.Path#getSpacedPoints + * @since 3.0.0 + * + * @param {number} [divisions=40] - The amount of points to divide this Path into. + * + * @return {Phaser.Math.Vector2[]} A list of the points this path was subdivided into. + */ + getSpacedPoints: function (divisions) + { + if (divisions === undefined) { divisions = 40; } + + var points = []; + + for (var i = 0; i <= divisions; i++) + { + points.push(this.getPoint(i / divisions)); + } + + if (this.autoClose) + { + points.push(points[0]); + } + + return points; + }, + + /** + * Returns the starting point of the Path. + * + * @method Phaser.Curves.Path#getStartPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Math.Vector2} [out] - `Vector2` instance that should be used for storing the result. If `undefined` a new `Vector2` will be created. + * + * @return {Phaser.Math.Vector2} The modified `out` object, or a new Vector2 if none was provided. + */ + getStartPoint: function (out) + { + if (out === undefined) { out = new Vector2(); } + + return out.copy(this.startPoint); + }, + + /** + * Gets a unit vector tangent at a relative position on the path. + * + * @method Phaser.Curves.Path#getTangent + * @since 3.23.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} t - The relative position on the path, [0..1]. + * @param {Phaser.Math.Vector2} [out] - A vector to store the result in. + * + * @return {Phaser.Math.Vector2} Vector approximating the tangent line at the point t (delta +/- 0.0001) + */ + getTangent: function (t, out) + { + if (out === undefined) { out = new Vector2(); } + + var d = t * this.getLength(); + var curveLengths = this.getCurveLengths(); + var i = 0; + + while (i < curveLengths.length) + { + if (curveLengths[i] >= d) + { + var diff = curveLengths[i] - d; + var curve = this.curves[i]; + + var segmentLength = curve.getLength(); + var u = (segmentLength === 0) ? 0 : 1 - diff / segmentLength; + + return curve.getTangentAt(u, out); + } + + i++; + } + + return null; + }, + + /** + * Creates a line curve from the previous end point to x/y. + * + * @method Phaser.Curves.Path#lineTo + * @since 3.0.0 + * + * @param {(number|Phaser.Math.Vector2|Phaser.Types.Math.Vector2Like)} x - The X coordinate of the line's end point, or a `Vector2` / `Vector2Like` containing the entire end point. + * @param {number} [y] - The Y coordinate of the line's end point, if a number was passed as the X parameter. + * + * @return {this} This Path object. + */ + lineTo: function (x, y) + { + if (x instanceof Vector2) + { + this._tmpVec2B.copy(x); + } + else if (typeof x === 'object') + { + this._tmpVec2B.setFromObject(x); + } + else + { + this._tmpVec2B.set(x, y); + } + + var end = this.getEndPoint(this._tmpVec2A); + + return this.add(new LineCurve([ end.x, end.y, this._tmpVec2B.x, this._tmpVec2B.y ])); + }, + + /** + * Creates a spline curve starting at the previous end point, using the given points on the curve. + * + * @method Phaser.Curves.Path#splineTo + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2[]} points - The points the newly created spline curve should consist of. + * + * @return {this} This Path object. + */ + splineTo: function (points) + { + points.unshift(this.getEndPoint()); + + return this.add(new SplineCurve(points)); + }, + + /** + * Creates a "gap" in this path from the path's current end point to the given coordinates. + * + * After calling this function, this Path's end point will be equal to the given coordinates + * + * @method Phaser.Curves.Path#moveTo + * @since 3.0.0 + * + * @param {(number|Phaser.Math.Vector2|Phaser.Types.Math.Vector2Like)} x - The X coordinate of the position to move the path's end point to, or a `Vector2` / `Vector2Like` containing the entire new end point. + * @param {number} [y] - The Y coordinate of the position to move the path's end point to, if a number was passed as the X coordinate. + * + * @return {this} This Path object. + */ + moveTo: function (x, y) + { + if (x instanceof Vector2) + { + return this.add(new MovePathTo(x.x, x.y)); + } + else + { + return this.add(new MovePathTo(x, y)); + } + }, + + /** + * Converts this Path to a JSON object containing the path information and its constituent curves. + * + * @method Phaser.Curves.Path#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.Curves.JSONPath} The JSON object containing this path's data. + */ + toJSON: function () + { + var out = []; + + for (var i = 0; i < this.curves.length; i++) + { + out.push(this.curves[i].toJSON()); + } + + return { + type: 'Path', + x: this.startPoint.x, + y: this.startPoint.y, + autoClose: this.autoClose, + curves: out + }; + }, + + /** + * cacheLengths must be recalculated. + * + * @method Phaser.Curves.Path#updateArcLengths + * @since 3.0.0 + */ + updateArcLengths: function () + { + this.cacheLengths = []; + + this.getCurveLengths(); + }, + + /** + * Disposes of this Path, clearing its internal references to objects so they can be garbage-collected. + * + * @method Phaser.Curves.Path#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.curves.length = 0; + this.cacheLengths.length = 0; + this.startPoint = undefined; + } + +}); + +/** + * Creates a new Path Object. + * + * @method Phaser.GameObjects.GameObjectFactory#path + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Path. + * @param {number} y - The vertical position of this Path. + * + * @return {Phaser.Curves.Path} The Path Object that was created. + */ +GameObjectFactory.register('path', function (x, y) +{ + return new Path(x, y); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + +module.exports = Path; + + +/***/ }), + +/***/ 45893: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Events = __webpack_require__(24882); + +/** + * @callback DataEachCallback + * + * @param {*} parent - The parent object of the DataManager. + * @param {string} key - The key of the value. + * @param {*} value - The value. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the game object, key, and data. + */ + +/** + * @classdesc + * The Data Manager Component features a means to store pieces of data specific to a Game Object, System or Plugin. + * You can then search, query it, and retrieve the data. The parent must either extend EventEmitter, + * or have a property called `events` that is an instance of it. + * + * @class DataManager + * @memberof Phaser.Data + * @constructor + * @since 3.0.0 + * + * @param {object} parent - The object that this DataManager belongs to. + * @param {Phaser.Events.EventEmitter} [eventEmitter] - The DataManager's event emitter. + */ +var DataManager = new Class({ + + initialize: + + function DataManager (parent, eventEmitter) + { + /** + * The object that this DataManager belongs to. + * + * @name Phaser.Data.DataManager#parent + * @type {*} + * @since 3.0.0 + */ + this.parent = parent; + + /** + * The DataManager's event emitter. + * + * @name Phaser.Data.DataManager#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events = eventEmitter; + + if (!eventEmitter) + { + this.events = (parent.events) ? parent.events : parent; + } + + /** + * The data list. + * + * @name Phaser.Data.DataManager#list + * @type {Object.} + * @default {} + * @since 3.0.0 + */ + this.list = {}; + + /** + * The public values list. You can use this to access anything you have stored + * in this Data Manager. For example, if you set a value called `gold` you can + * access it via: + * + * ```javascript + * this.data.values.gold; + * ``` + * + * You can also modify it directly: + * + * ```javascript + * this.data.values.gold += 1000; + * ``` + * + * Doing so will emit a `setdata` event from the parent of this Data Manager. + * + * Do not modify this object directly. Adding properties directly to this object will not + * emit any events. Always use `DataManager.set` to create new items the first time around. + * + * @name Phaser.Data.DataManager#values + * @type {Object.} + * @default {} + * @since 3.10.0 + */ + this.values = {}; + + /** + * Whether setting data is frozen for this DataManager. + * + * @name Phaser.Data.DataManager#_frozen + * @type {boolean} + * @private + * @default false + * @since 3.0.0 + */ + this._frozen = false; + + if (!parent.hasOwnProperty('sys') && this.events) + { + this.events.once(Events.DESTROY, this.destroy, this); + } + }, + + /** + * Retrieves the value for the given key, or undefined if it doesn't exist. + * + * You can also access values via the `values` object. For example, if you had a key called `gold` you can do either: + * + * ```javascript + * this.data.get('gold'); + * ``` + * + * Or access the value directly: + * + * ```javascript + * this.data.values.gold; + * ``` + * + * You can also pass in an array of keys, in which case an array of values will be returned: + * + * ```javascript + * this.data.get([ 'gold', 'armor', 'health' ]); + * ``` + * + * This approach is useful for destructuring arrays in ES6. + * + * @method Phaser.Data.DataManager#get + * @since 3.0.0 + * + * @param {(string|string[])} key - The key of the value to retrieve, or an array of keys. + * + * @return {*} The value belonging to the given key, or an array of values, the order of which will match the input array. + */ + get: function (key) + { + var list = this.list; + + if (Array.isArray(key)) + { + var output = []; + + for (var i = 0; i < key.length; i++) + { + output.push(list[key[i]]); + } + + return output; + } + else + { + return list[key]; + } + }, + + /** + * Retrieves all data values in a new object. + * + * @method Phaser.Data.DataManager#getAll + * @since 3.0.0 + * + * @return {Object.} All data values. + */ + getAll: function () + { + var results = {}; + + for (var key in this.list) + { + if (this.list.hasOwnProperty(key)) + { + results[key] = this.list[key]; + } + } + + return results; + }, + + /** + * Queries the DataManager for the values of keys matching the given regular expression. + * + * @method Phaser.Data.DataManager#query + * @since 3.0.0 + * + * @param {RegExp} search - A regular expression object. If a non-RegExp object obj is passed, it is implicitly converted to a RegExp by using new RegExp(obj). + * + * @return {Object.} The values of the keys matching the search string. + */ + query: function (search) + { + var results = {}; + + for (var key in this.list) + { + if (this.list.hasOwnProperty(key) && key.match(search)) + { + results[key] = this.list[key]; + } + } + + return results; + }, + + /** + * Sets a value for the given key. If the key doesn't already exist in the Data Manager then it is created. + * + * ```javascript + * data.set('name', 'Red Gem Stone'); + * ``` + * + * You can also pass in an object of key value pairs as the first argument: + * + * ```javascript + * data.set({ name: 'Red Gem Stone', level: 2, owner: 'Link', gold: 50 }); + * ``` + * + * To get a value back again you can call `get`: + * + * ```javascript + * data.get('gold'); + * ``` + * + * Or you can access the value directly via the `values` property, where it works like any other variable: + * + * ```javascript + * data.values.gold += 50; + * ``` + * + * When the value is first set, a `setdata` event is emitted. + * + * If the key already exists, a `changedata` event is emitted instead, along an event named after the key. + * For example, if you updated an existing key called `PlayerLives` then it would emit the event `changedata-PlayerLives`. + * These events will be emitted regardless if you use this method to set the value, or the direct `values` setter. + * + * Please note that the data keys are case-sensitive and must be valid JavaScript Object property strings. + * This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager. + * + * @method Phaser.Data.DataManager#set + * @fires Phaser.Data.Events#SET_DATA + * @fires Phaser.Data.Events#CHANGE_DATA + * @fires Phaser.Data.Events#CHANGE_DATA_KEY + * @since 3.0.0 + * + * @generic {any} T + * @genericUse {(string|T)} - [key] + * + * @param {(string|object)} key - The key to set the value for. Or an object of key value pairs. If an object the `data` argument is ignored. + * @param {*} [data] - The value to set for the given key. If an object is provided as the key this argument is ignored. + * + * @return {this} This Data Manager instance. + */ + set: function (key, data) + { + if (this._frozen) + { + return this; + } + + if (typeof key === 'string') + { + return this.setValue(key, data); + } + else + { + for (var entry in key) + { + this.setValue(entry, key[entry]); + } + } + + return this; + }, + + /** + * Increase a value for the given key. If the key doesn't already exist in the Data Manager then it is increased from 0. + * + * When the value is first set, a `setdata` event is emitted. + * + * @method Phaser.Data.DataManager#inc + * @fires Phaser.Data.Events#SET_DATA + * @fires Phaser.Data.Events#CHANGE_DATA + * @fires Phaser.Data.Events#CHANGE_DATA_KEY + * @since 3.23.0 + * + * @param {string} key - The key to change the value for. + * @param {number} [amount=1] - The amount to increase the given key by. Pass a negative value to decrease the key. + * + * @return {this} This Data Manager instance. + */ + inc: function (key, amount) + { + if (this._frozen) + { + return this; + } + + if (amount === undefined) + { + amount = 1; + } + + var value = this.get(key); + + if (value === undefined) + { + value = 0; + } + + this.set(key, (value + amount)); + + return this; + }, + + /** + * Toggle a boolean value for the given key. If the key doesn't already exist in the Data Manager then it is toggled from false. + * + * When the value is first set, a `setdata` event is emitted. + * + * @method Phaser.Data.DataManager#toggle + * @fires Phaser.Data.Events#SET_DATA + * @fires Phaser.Data.Events#CHANGE_DATA + * @fires Phaser.Data.Events#CHANGE_DATA_KEY + * @since 3.23.0 + * + * @param {string} key - The key to toggle the value for. + * + * @return {this} This Data Manager instance. + */ + toggle: function (key) + { + if (this._frozen) + { + return this; + } + + this.set(key, !this.get(key)); + + return this; + }, + + /** + * Internal value setter, called automatically by the `set` method. + * + * @method Phaser.Data.DataManager#setValue + * @fires Phaser.Data.Events#SET_DATA + * @fires Phaser.Data.Events#CHANGE_DATA + * @fires Phaser.Data.Events#CHANGE_DATA_KEY + * @private + * @since 3.10.0 + * + * @param {string} key - The key to set the value for. + * @param {*} data - The value to set. + * + * @return {this} This Data Manager instance. + */ + setValue: function (key, data) + { + if (this._frozen) + { + return this; + } + + if (this.has(key)) + { + // Hit the key getter, which will in turn emit the events. + this.values[key] = data; + } + else + { + var _this = this; + var list = this.list; + var events = this.events; + var parent = this.parent; + + Object.defineProperty(this.values, key, { + + enumerable: true, + + configurable: true, + + get: function () + { + return list[key]; + }, + + set: function (value) + { + if (!_this._frozen) + { + var previousValue = list[key]; + list[key] = value; + + events.emit(Events.CHANGE_DATA, parent, key, value, previousValue); + events.emit(Events.CHANGE_DATA_KEY + key, parent, value, previousValue); + } + } + + }); + + list[key] = data; + + events.emit(Events.SET_DATA, parent, key, data); + } + + return this; + }, + + /** + * Passes all data entries to the given callback. + * + * @method Phaser.Data.DataManager#each + * @since 3.0.0 + * + * @param {DataEachCallback} callback - The function to call. + * @param {*} [context] - Value to use as `this` when executing callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the game object, key, and data. + * + * @return {this} This Data Manager instance. + */ + each: function (callback, context) + { + var args = [ this.parent, null, undefined ]; + + for (var i = 1; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (var key in this.list) + { + args[1] = key; + args[2] = this.list[key]; + + callback.apply(context, args); + } + + return this; + }, + + /** + * Merge the given object of key value pairs into this DataManager. + * + * Any newly created values will emit a `setdata` event. Any updated values (see the `overwrite` argument) + * will emit a `changedata` event. + * + * @method Phaser.Data.DataManager#merge + * @fires Phaser.Data.Events#SET_DATA + * @fires Phaser.Data.Events#CHANGE_DATA + * @fires Phaser.Data.Events#CHANGE_DATA_KEY + * @since 3.0.0 + * + * @param {Object.} data - The data to merge. + * @param {boolean} [overwrite=true] - Whether to overwrite existing data. Defaults to true. + * + * @return {this} This Data Manager instance. + */ + merge: function (data, overwrite) + { + if (overwrite === undefined) { overwrite = true; } + + // Merge data from another component into this one + for (var key in data) + { + if (data.hasOwnProperty(key) && (overwrite || (!overwrite && !this.has(key)))) + { + this.setValue(key, data[key]); + } + } + + return this; + }, + + /** + * Remove the value for the given key. + * + * If the key is found in this Data Manager it is removed from the internal lists and a + * `removedata` event is emitted. + * + * You can also pass in an array of keys, in which case all keys in the array will be removed: + * + * ```javascript + * this.data.remove([ 'gold', 'armor', 'health' ]); + * ``` + * + * @method Phaser.Data.DataManager#remove + * @fires Phaser.Data.Events#REMOVE_DATA + * @since 3.0.0 + * + * @param {(string|string[])} key - The key to remove, or an array of keys to remove. + * + * @return {this} This Data Manager instance. + */ + remove: function (key) + { + if (this._frozen) + { + return this; + } + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + this.removeValue(key[i]); + } + } + else + { + return this.removeValue(key); + } + + return this; + }, + + /** + * Internal value remover, called automatically by the `remove` method. + * + * @method Phaser.Data.DataManager#removeValue + * @private + * @fires Phaser.Data.Events#REMOVE_DATA + * @since 3.10.0 + * + * @param {string} key - The key to set the value for. + * + * @return {this} This Data Manager instance. + */ + removeValue: function (key) + { + if (this.has(key)) + { + var data = this.list[key]; + + delete this.list[key]; + delete this.values[key]; + + this.events.emit(Events.REMOVE_DATA, this.parent, key, data); + } + + return this; + }, + + /** + * Retrieves the data associated with the given 'key', deletes it from this Data Manager, then returns it. + * + * @method Phaser.Data.DataManager#pop + * @fires Phaser.Data.Events#REMOVE_DATA + * @since 3.0.0 + * + * @param {string} key - The key of the value to retrieve and delete. + * + * @return {*} The value of the given key. + */ + pop: function (key) + { + var data = undefined; + + if (!this._frozen && this.has(key)) + { + data = this.list[key]; + + delete this.list[key]; + delete this.values[key]; + + this.events.emit(Events.REMOVE_DATA, this.parent, key, data); + } + + return data; + }, + + /** + * Determines whether the given key is set in this Data Manager. + * + * Please note that the keys are case-sensitive and must be valid JavaScript Object property strings. + * This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager. + * + * @method Phaser.Data.DataManager#has + * @since 3.0.0 + * + * @param {string} key - The key to check. + * + * @return {boolean} Returns `true` if the key exists, otherwise `false`. + */ + has: function (key) + { + return this.list.hasOwnProperty(key); + }, + + /** + * Freeze or unfreeze this Data Manager. A frozen Data Manager will block all attempts + * to create new values or update existing ones. + * + * @method Phaser.Data.DataManager#setFreeze + * @since 3.0.0 + * + * @param {boolean} value - Whether to freeze or unfreeze the Data Manager. + * + * @return {this} This Data Manager instance. + */ + setFreeze: function (value) + { + this._frozen = value; + + return this; + }, + + /** + * Delete all data in this Data Manager and unfreeze it. + * + * @method Phaser.Data.DataManager#reset + * @since 3.0.0 + * + * @return {this} This Data Manager instance. + */ + reset: function () + { + for (var key in this.list) + { + delete this.list[key]; + delete this.values[key]; + } + + this._frozen = false; + + return this; + }, + + /** + * Destroy this data manager. + * + * @method Phaser.Data.DataManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.reset(); + + this.events.off(Events.CHANGE_DATA); + this.events.off(Events.SET_DATA); + this.events.off(Events.REMOVE_DATA); + + this.parent = null; + }, + + /** + * Gets or sets the frozen state of this Data Manager. + * A frozen Data Manager will block all attempts to create new values or update existing ones. + * + * @name Phaser.Data.DataManager#freeze + * @type {boolean} + * @since 3.0.0 + */ + freeze: { + + get: function () + { + return this._frozen; + }, + + set: function (value) + { + this._frozen = (value) ? true : false; + } + + }, + + /** + * Return the total number of entries in this Data Manager. + * + * @name Phaser.Data.DataManager#count + * @type {number} + * @since 3.0.0 + */ + count: { + + get: function () + { + var i = 0; + + for (var key in this.list) + { + if (this.list[key] !== undefined) + { + i++; + } + } + + return i; + } + + } + +}); + +module.exports = DataManager; + + +/***/ }), + +/***/ 63646: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var DataManager = __webpack_require__(45893); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * The Data Component features a means to store pieces of data specific to a Game Object, System or Plugin. + * You can then search, query it, and retrieve the data. The parent must either extend EventEmitter, + * or have a property called `events` that is an instance of it. + * + * @class DataManagerPlugin + * @extends Phaser.Data.DataManager + * @memberof Phaser.Data + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - A reference to the Scene that this DataManager belongs to. + */ +var DataManagerPlugin = new Class({ + + Extends: DataManager, + + initialize: + + function DataManagerPlugin (scene) + { + DataManager.call(this, scene, scene.sys.events); + + /** + * A reference to the Scene that this DataManager belongs to. + * + * @name Phaser.Data.DataManagerPlugin#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene's Systems. + * + * @name Phaser.Data.DataManagerPlugin#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Data.DataManagerPlugin#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.events = this.systems.events; + + this.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Data.DataManagerPlugin#start + * @private + * @since 3.5.0 + */ + start: function () + { + this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Data.DataManagerPlugin#shutdown + * @private + * @since 3.5.0 + */ + shutdown: function () + { + this.systems.events.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Data.DataManagerPlugin#destroy + * @since 3.5.0 + */ + destroy: function () + { + DataManager.prototype.destroy.call(this); + + this.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + } + +}); + +PluginCache.register('DataManagerPlugin', DataManagerPlugin, 'data'); + +module.exports = DataManagerPlugin; + + +/***/ }), + +/***/ 10700: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Change Data Event. + * + * This event is dispatched by a Data Manager when an item in the data store is changed. + * + * Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for + * a change data event from a Game Object you would use: `sprite.on('changedata', listener)`. + * + * This event is dispatched for all items that change in the Data Manager. + * To listen for the change of a specific item, use the `CHANGE_DATA_KEY_EVENT` event. + * + * @event Phaser.Data.Events#CHANGE_DATA + * @type {string} + * @since 3.0.0 + * + * @param {any} parent - A reference to the object that the Data Manager responsible for this event belongs to. + * @param {string} key - The unique key of the data item within the Data Manager. + * @param {any} value - The new value of the item in the Data Manager. + * @param {any} previousValue - The previous value of the item in the Data Manager. + */ +module.exports = 'changedata'; + + +/***/ }), + +/***/ 93608: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Change Data Key Event. + * + * This event is dispatched by a Data Manager when an item in the data store is changed. + * + * Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for + * the change of a specific data item from a Game Object you would use: `sprite.on('changedata-key', listener)`, + * where `key` is the unique string key of the data item. For example, if you have a data item stored called `gold` + * then you can listen for `sprite.on('changedata-gold')`. + * + * @event Phaser.Data.Events#CHANGE_DATA_KEY + * @type {string} + * @since 3.16.1 + * + * @param {any} parent - A reference to the object that owns the instance of the Data Manager responsible for this event. + * @param {any} value - The item that was updated in the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance. + * @param {any} previousValue - The previous item that was updated in the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance. + */ +module.exports = 'changedata-'; + + +/***/ }), + +/***/ 60883: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Data Manager Destroy Event. + * + * The Data Manager will listen for the destroy event from its parent, and then close itself down. + * + * @event Phaser.Data.Events#DESTROY + * @type {string} + * @since 3.50.0 + */ +module.exports = 'destroy'; + + +/***/ }), + +/***/ 69780: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Remove Data Event. + * + * This event is dispatched by a Data Manager when an item is removed from it. + * + * Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for + * the removal of a data item on a Game Object you would use: `sprite.on('removedata', listener)`. + * + * @event Phaser.Data.Events#REMOVE_DATA + * @type {string} + * @since 3.0.0 + * + * @param {any} parent - A reference to the object that owns the instance of the Data Manager responsible for this event. + * @param {string} key - The unique key of the data item within the Data Manager. + * @param {any} data - The item that was removed from the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance. + */ +module.exports = 'removedata'; + + +/***/ }), + +/***/ 22166: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Set Data Event. + * + * This event is dispatched by a Data Manager when a new item is added to the data store. + * + * Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for + * the addition of a new data item on a Game Object you would use: `sprite.on('setdata', listener)`. + * + * @event Phaser.Data.Events#SET_DATA + * @type {string} + * @since 3.0.0 + * + * @param {any} parent - A reference to the object that owns the instance of the Data Manager responsible for this event. + * @param {string} key - The unique key of the data item within the Data Manager. + * @param {any} data - The item that was added to the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance. + */ +module.exports = 'setdata'; + + +/***/ }), + +/***/ 24882: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Data.Events + */ + +module.exports = { + + CHANGE_DATA: __webpack_require__(10700), + CHANGE_DATA_KEY: __webpack_require__(93608), + DESTROY: __webpack_require__(60883), + REMOVE_DATA: __webpack_require__(69780), + SET_DATA: __webpack_require__(22166) + +}; + + +/***/ }), + +/***/ 44965: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Data + */ + +module.exports = { + + DataManager: __webpack_require__(45893), + DataManagerPlugin: __webpack_require__(63646), + Events: __webpack_require__(24882) + +}; + + +/***/ }), + +/***/ 7098: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Browser = __webpack_require__(84148); + +/** + * Determines the audio playback capabilities of the device running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.audio` from within any Scene. + * + * @typedef {object} Phaser.Device.Audio + * @since 3.0.0 + * + * @property {boolean} audioData - Can this device play HTML Audio tags? + * @property {boolean} dolby - Can this device play EC-3 Dolby Digital Plus files? + * @property {boolean} m4a - Can this device can play m4a files. + * @property {boolean} aac - Can this device can play aac files. + * @property {boolean} flac - Can this device can play flac files. + * @property {boolean} mp3 - Can this device play mp3 files? + * @property {boolean} ogg - Can this device play ogg files? + * @property {boolean} opus - Can this device play opus files? + * @property {boolean} wav - Can this device play wav files? + * @property {boolean} webAudio - Does this device have the Web Audio API? + * @property {boolean} webm - Can this device play webm files? + */ +var Audio = { + + flac: false, + aac: false, + audioData: false, + dolby: false, + m4a: false, + mp3: false, + ogg: false, + opus: false, + wav: false, + webAudio: false, + webm: false + +}; + +function init () +{ + if (typeof importScripts === 'function') + { + return Audio; + } + + Audio.audioData = !!(window['Audio']); + + Audio.webAudio = !!(window['AudioContext'] || window['webkitAudioContext']); + + var audioElement = document.createElement('audio'); + var result = !!audioElement.canPlayType; + + try + { + if (result) + { + var CanPlay = function (type1, type2) + { + var canPlayType1 = audioElement.canPlayType('audio/' + type1).replace(/^no$/, ''); + + if (type2) + { + return Boolean(canPlayType1 || audioElement.canPlayType('audio/' + type2).replace(/^no$/, '')); + } + else + { + return Boolean(canPlayType1); + } + }; + + // wav Mimetypes accepted: + // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements + + Audio.ogg = CanPlay('ogg; codecs="vorbis"'); + Audio.opus = CanPlay('ogg; codecs="opus"', 'opus'); + Audio.mp3 = CanPlay('mpeg'); + Audio.wav = CanPlay('wav'); + Audio.m4a = CanPlay('x-m4a'); + Audio.aac = CanPlay('aac'); + Audio.flac = CanPlay('flac', 'x-flac'); + Audio.webm = CanPlay('webm; codecs="vorbis"'); + + if (audioElement.canPlayType('audio/mp4; codecs="ec-3"') !== '') + { + if (Browser.edge) + { + Audio.dolby = true; + } + else if (Browser.safari && Browser.safariVersion >= 9) + { + if ((/Mac OS X (\d+)_(\d+)/).test(navigator.userAgent)) + { + var major = parseInt(RegExp.$1, 10); + var minor = parseInt(RegExp.$2, 10); + + if ((major === 10 && minor >= 11) || major > 10) + { + Audio.dolby = true; + } + } + } + } + } + } + catch (e) + { + // Nothing to do here + } + + return Audio; +} + +module.exports = init(); + + +/***/ }), + +/***/ 84148: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var OS = __webpack_require__(25892); + +/** + * Determines the browser type and version running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.browser` from within any Scene. + * + * @typedef {object} Phaser.Device.Browser + * @since 3.0.0 + * + * @property {boolean} chrome - Set to true if running in Chrome. + * @property {boolean} edge - Set to true if running in Microsoft Edge browser. + * @property {boolean} firefox - Set to true if running in Firefox. + * @property {boolean} ie - Set to true if running in Internet Explorer 11 or less (not Edge). + * @property {boolean} mobileSafari - Set to true if running in Mobile Safari. + * @property {boolean} opera - Set to true if running in Opera. + * @property {boolean} safari - Set to true if running in Safari. + * @property {boolean} silk - Set to true if running in the Silk browser (as used on the Amazon Kindle) + * @property {boolean} trident - Set to true if running a Trident version of Internet Explorer (IE11+) + * @property {number} chromeVersion - If running in Chrome this will contain the major version number. + * @property {number} firefoxVersion - If running in Firefox this will contain the major version number. + * @property {number} ieVersion - If running in Internet Explorer this will contain the major version number. Beyond IE10 you should use Browser.trident and Browser.tridentVersion. + * @property {number} safariVersion - If running in Safari this will contain the major version number. + * @property {number} tridentVersion - If running in Internet Explorer 11 this will contain the major version number. See {@link http://msdn.microsoft.com/en-us/library/ie/ms537503(v=vs.85).aspx} + */ +var Browser = { + + chrome: false, + chromeVersion: 0, + edge: false, + firefox: false, + firefoxVersion: 0, + ie: false, + ieVersion: 0, + mobileSafari: false, + opera: false, + safari: false, + safariVersion: 0, + silk: false, + trident: false, + tridentVersion: 0, + es2019: false + +}; + +function init () +{ + var ua = navigator.userAgent; + + if ((/Edg\/\d+/).test(ua)) + { + Browser.edge = true; + Browser.es2019 = true; + } + else if ((/OPR/).test(ua)) + { + Browser.opera = true; + Browser.es2019 = true; + } + else if ((/Chrome\/(\d+)/).test(ua) && !OS.windowsPhone) + { + Browser.chrome = true; + Browser.chromeVersion = parseInt(RegExp.$1, 10); + Browser.es2019 = (Browser.chromeVersion > 69); + } + else if ((/Firefox\D+(\d+)/).test(ua)) + { + Browser.firefox = true; + Browser.firefoxVersion = parseInt(RegExp.$1, 10); + Browser.es2019 = (Browser.firefoxVersion > 10); + } + else if ((/AppleWebKit\/(?!.*CriOS)/).test(ua) && OS.iOS) + { + Browser.mobileSafari = true; + Browser.es2019 = true; + } + else if ((/MSIE (\d+\.\d+);/).test(ua)) + { + Browser.ie = true; + Browser.ieVersion = parseInt(RegExp.$1, 10); + } + else if ((/Version\/(\d+\.\d+(\.\d+)?) Safari/).test(ua) && !OS.windowsPhone) + { + Browser.safari = true; + Browser.safariVersion = parseInt(RegExp.$1, 10); + Browser.es2019 = (Browser.safariVersion > 10); + } + else if ((/Trident\/(\d+\.\d+)(.*)rv:(\d+\.\d+)/).test(ua)) + { + Browser.ie = true; + Browser.trident = true; + Browser.tridentVersion = parseInt(RegExp.$1, 10); + Browser.ieVersion = parseInt(RegExp.$3, 10); + } + + // Silk gets its own if clause because its ua also contains 'Safari' + if ((/Silk/).test(ua)) + { + Browser.silk = true; + } + + return Browser; +} + +module.exports = init(); + + +/***/ }), + +/***/ 89289: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasPool = __webpack_require__(27919); + +/** + * Determines the canvas features of the browser running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.canvasFeatures` from within any Scene. + * + * @typedef {object} Phaser.Device.CanvasFeatures + * @since 3.0.0 + * + * @property {boolean} supportInverseAlpha - Set to true if the browser supports inversed alpha. + * @property {boolean} supportNewBlendModes - Set to true if the browser supports new canvas blend modes. + */ +var CanvasFeatures = { + + supportInverseAlpha: false, + supportNewBlendModes: false + +}; + +function checkBlendMode () +{ + var pngHead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABAQMAAADD8p2OAAAAA1BMVEX/'; + var pngEnd = 'AAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg=='; + + var magenta = new Image(); + + magenta.onload = function () + { + var yellow = new Image(); + + yellow.onload = function () + { + var canvas = CanvasPool.create2D(yellow, 6); + var context = canvas.getContext('2d', { willReadFrequently: true }); + + context.globalCompositeOperation = 'multiply'; + + context.drawImage(magenta, 0, 0); + context.drawImage(yellow, 2, 0); + + if (!context.getImageData(2, 0, 1, 1)) + { + return false; + } + + var data = context.getImageData(2, 0, 1, 1).data; + + CanvasPool.remove(yellow); + + CanvasFeatures.supportNewBlendModes = (data[0] === 255 && data[1] === 0 && data[2] === 0); + }; + + yellow.src = pngHead + '/wCKxvRF' + pngEnd; + }; + + magenta.src = pngHead + 'AP804Oa6' + pngEnd; + + return false; +} + +function checkInverseAlpha () +{ + var canvas = CanvasPool.create2D(this, 2); + var context = canvas.getContext('2d', { willReadFrequently: true }); + + context.fillStyle = 'rgba(10, 20, 30, 0.5)'; + + // Draw a single pixel + context.fillRect(0, 0, 1, 1); + + // Get the color values + var s1 = context.getImageData(0, 0, 1, 1); + + if (s1 === null) + { + return false; + } + + // Plot them to x2 + context.putImageData(s1, 1, 0); + + // Get those values + var s2 = context.getImageData(1, 0, 1, 1); + + var result = (s2.data[0] === s1.data[0] && s2.data[1] === s1.data[1] && s2.data[2] === s1.data[2] && s2.data[3] === s1.data[3]); + + CanvasPool.remove(this); + + // Compare and return + return result; +} + +function init () +{ + if (typeof importScripts !== 'function' && document !== undefined) + { + CanvasFeatures.supportNewBlendModes = checkBlendMode(); + CanvasFeatures.supportInverseAlpha = checkInverseAlpha(); + } + + return CanvasFeatures; +} + +module.exports = init(); + + +/***/ }), + +/***/ 89357: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var OS = __webpack_require__(25892); +var Browser = __webpack_require__(84148); +var CanvasPool = __webpack_require__(27919); + +/** + * Determines the features of the browser running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.features` from within any Scene. + * + * @typedef {object} Phaser.Device.Features + * @since 3.0.0 + * + * @property {boolean} canvas - Is canvas available? + * @property {?boolean} canvasBitBltShift - True if canvas supports a 'copy' bitblt onto itself when the source and destination regions overlap. + * @property {boolean} file - Is file available? + * @property {boolean} fileSystem - Is fileSystem available? + * @property {boolean} getUserMedia - Does the device support the getUserMedia API? + * @property {boolean} littleEndian - Is the device big or little endian? (only detected if the browser supports TypedArrays) + * @property {boolean} localStorage - Is localStorage available? + * @property {boolean} pointerLock - Is Pointer Lock available? + * @property {boolean} stableSort - Is Array.sort stable? + * @property {boolean} support32bit - Does the device context support 32bit pixel manipulation using array buffer views? + * @property {boolean} vibration - Does the device support the Vibration API? + * @property {boolean} webGL - Is webGL available? + * @property {boolean} worker - Is worker available? + */ +var Features = { + + canvas: false, + canvasBitBltShift: null, + file: false, + fileSystem: false, + getUserMedia: true, + littleEndian: false, + localStorage: false, + pointerLock: false, + stableSort: false, + support32bit: false, + vibration: false, + webGL: false, + worker: false + +}; + +// Check Little or Big Endian system. +// @author Matt DesLauriers (@mattdesl) +function checkIsLittleEndian () +{ + var a = new ArrayBuffer(4); + var b = new Uint8Array(a); + var c = new Uint32Array(a); + + b[0] = 0xa1; + b[1] = 0xb2; + b[2] = 0xc3; + b[3] = 0xd4; + + if (c[0] === 0xd4c3b2a1) + { + return true; + } + + if (c[0] === 0xa1b2c3d4) + { + return false; + } + else + { + // Could not determine endianness + return null; + } +} + +function init () +{ + if (typeof importScripts === 'function') + { + return Features; + } + + Features.canvas = !!window['CanvasRenderingContext2D']; + + try + { + Features.localStorage = !!localStorage.getItem; + } + catch (error) + { + Features.localStorage = false; + } + + Features.file = !!window['File'] && !!window['FileReader'] && !!window['FileList'] && !!window['Blob']; + Features.fileSystem = !!window['requestFileSystem']; + + var isUint8 = false; + + var testWebGL = function () + { + if (window['WebGLRenderingContext']) + { + try + { + var canvas = CanvasPool.createWebGL(this); + + var ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + + var canvas2D = CanvasPool.create2D(this); + + var ctx2D = canvas2D.getContext('2d', { willReadFrequently: true }); + + // Can't be done on a webgl context + var image = ctx2D.createImageData(1, 1); + + // Test to see if ImageData uses CanvasPixelArray or Uint8ClampedArray. + // @author Matt DesLauriers (@mattdesl) + isUint8 = image.data instanceof Uint8ClampedArray; + + CanvasPool.remove(canvas); + CanvasPool.remove(canvas2D); + + return !!ctx; + } + catch (e) + { + return false; + } + } + + return false; + }; + + Features.webGL = testWebGL(); + + Features.worker = !!window['Worker']; + + Features.pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document; + + navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia; + + window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; + + Features.getUserMedia = Features.getUserMedia && !!navigator.getUserMedia && !!window.URL; + + // Older versions of firefox (< 21) apparently claim support but user media does not actually work + if (Browser.firefox && Browser.firefoxVersion < 21) + { + Features.getUserMedia = false; + } + + // Excludes iOS versions as they generally wrap UIWebView (eg. Safari WebKit) and it + // is safer to not try and use the fast copy-over method. + if (!OS.iOS && (Browser.ie || Browser.firefox || Browser.chrome)) + { + Features.canvasBitBltShift = true; + } + + // Known not to work + if (Browser.safari || Browser.mobileSafari) + { + Features.canvasBitBltShift = false; + } + + navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate; + + if (navigator.vibrate) + { + Features.vibration = true; + } + + if (typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined' && typeof Uint32Array !== 'undefined') + { + Features.littleEndian = checkIsLittleEndian(); + } + + Features.support32bit = ( + typeof ArrayBuffer !== 'undefined' && + typeof Uint8ClampedArray !== 'undefined' && + typeof Int32Array !== 'undefined' && + Features.littleEndian !== null && + isUint8 + ); + + return Features; +} + +module.exports = init(); + + +/***/ }), + +/***/ 91639: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Determines the full screen support of the browser running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.fullscreen` from within any Scene. + * + * @typedef {object} Phaser.Device.Fullscreen + * @since 3.0.0 + * + * @property {boolean} available - Does the browser support the Full Screen API? + * @property {boolean} keyboard - Does the browser support access to the Keyboard during Full Screen mode? + * @property {string} cancel - If the browser supports the Full Screen API this holds the call you need to use to cancel it. + * @property {string} request - If the browser supports the Full Screen API this holds the call you need to use to activate it. + */ +var Fullscreen = { + + available: false, + cancel: '', + keyboard: false, + request: '' + +}; + +/** +* Checks for support of the Full Screen API. +* +* @ignore +*/ +function init () +{ + if (typeof importScripts === 'function') + { + return Fullscreen; + } + + var i; + + var suffix1 = 'Fullscreen'; + var suffix2 = 'FullScreen'; + + var fs = [ + 'request' + suffix1, + 'request' + suffix2, + 'webkitRequest' + suffix1, + 'webkitRequest' + suffix2, + 'msRequest' + suffix1, + 'msRequest' + suffix2, + 'mozRequest' + suffix2, + 'mozRequest' + suffix1 + ]; + + for (i = 0; i < fs.length; i++) + { + if (document.documentElement[fs[i]]) + { + Fullscreen.available = true; + Fullscreen.request = fs[i]; + break; + } + } + + var cfs = [ + 'cancel' + suffix2, + 'exit' + suffix1, + 'webkitCancel' + suffix2, + 'webkitExit' + suffix1, + 'msCancel' + suffix2, + 'msExit' + suffix1, + 'mozCancel' + suffix2, + 'mozExit' + suffix1 + ]; + + if (Fullscreen.available) + { + for (i = 0; i < cfs.length; i++) + { + if (document[cfs[i]]) + { + Fullscreen.cancel = cfs[i]; + break; + } + } + } + + // Keyboard Input? + // Safari 5.1 says it supports fullscreen keyboard, but is lying. + if (window['Element'] && Element['ALLOW_KEYBOARD_INPUT'] && !(/ Version\/5\.1(?:\.\d+)? Safari\//).test(navigator.userAgent)) + { + Fullscreen.keyboard = true; + } + + Object.defineProperty(Fullscreen, 'active', { get: function () { return !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement); } }); + + return Fullscreen; +} + +module.exports = init(); + + +/***/ }), + +/***/ 31784: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Browser = __webpack_require__(84148); + +/** + * Determines the input support of the browser running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.input` from within any Scene. + * + * @typedef {object} Phaser.Device.Input + * @since 3.0.0 + * + * @property {?string} wheelType - The newest type of Wheel/Scroll event supported: 'wheel', 'mousewheel', 'DOMMouseScroll' + * @property {boolean} gamepads - Is navigator.getGamepads available? + * @property {boolean} mspointer - Is mspointer available? + * @property {boolean} touch - Is touch available? + */ +var Input = { + + gamepads: false, + mspointer: false, + touch: false, + wheelEvent: null + +}; + +function init () +{ + if (typeof importScripts === 'function') + { + return Input; + } + + if ('ontouchstart' in document.documentElement || (navigator.maxTouchPoints && navigator.maxTouchPoints >= 1)) + { + Input.touch = true; + } + + if (navigator.msPointerEnabled || navigator.pointerEnabled) + { + Input.mspointer = true; + } + + if (navigator.getGamepads) + { + Input.gamepads = true; + } + + // See https://developer.mozilla.org/en-US/docs/Web/Events/wheel + if ('onwheel' in window || (Browser.ie && 'WheelEvent' in window)) + { + // DOM3 Wheel Event: FF 17+, IE 9+, Chrome 31+, Safari 7+ + Input.wheelEvent = 'wheel'; + } + else if ('onmousewheel' in window) + { + // Non-FF legacy: IE 6-9, Chrome 1-31, Safari 5-7. + Input.wheelEvent = 'mousewheel'; + } + else if (Browser.firefox && 'MouseScrollEvent' in window) + { + // FF prior to 17. This should probably be scrubbed. + Input.wheelEvent = 'DOMMouseScroll'; + } + + return Input; +} + +module.exports = init(); + + +/***/ }), + +/***/ 25892: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Determines the operating system of the device running this Phaser Game instance. + * These values are read-only and populated during the boot sequence of the game. + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.os` from within any Scene. + * + * @typedef {object} Phaser.Device.OS + * @since 3.0.0 + * + * @property {boolean} android - Is running on android? + * @property {boolean} chromeOS - Is running on chromeOS? + * @property {boolean} cordova - Is the game running under Apache Cordova? + * @property {boolean} crosswalk - Is the game running under the Intel Crosswalk XDK? + * @property {boolean} desktop - Is running on a desktop? + * @property {boolean} ejecta - Is the game running under Ejecta? + * @property {boolean} electron - Is the game running under GitHub Electron? + * @property {boolean} iOS - Is running on iOS? + * @property {boolean} iPad - Is running on iPad? + * @property {boolean} iPhone - Is running on iPhone? + * @property {boolean} kindle - Is running on an Amazon Kindle? + * @property {boolean} linux - Is running on linux? + * @property {boolean} macOS - Is running on macOS? + * @property {boolean} node - Is the game running under Node.js? + * @property {boolean} nodeWebkit - Is the game running under Node-Webkit? + * @property {boolean} webApp - Set to true if running as a WebApp, i.e. within a WebView + * @property {boolean} windows - Is running on windows? + * @property {boolean} windowsPhone - Is running on a Windows Phone? + * @property {number} iOSVersion - If running in iOS this will contain the major version number. + * @property {number} pixelRatio - PixelRatio of the host device? + */ +var OS = { + + android: false, + chromeOS: false, + cordova: false, + crosswalk: false, + desktop: false, + ejecta: false, + electron: false, + iOS: false, + iOSVersion: 0, + iPad: false, + iPhone: false, + kindle: false, + linux: false, + macOS: false, + node: false, + nodeWebkit: false, + pixelRatio: 1, + webApp: false, + windows: false, + windowsPhone: false + +}; + +function init () +{ + if (typeof importScripts === 'function') + { + return OS; + } + + var ua = navigator.userAgent; + + if ((/Windows/).test(ua)) + { + OS.windows = true; + } + else if ((/Mac OS/).test(ua) && !((/like Mac OS/).test(ua))) + { + // Because iOS 13 identifies as Mac OS: + if (navigator.maxTouchPoints && navigator.maxTouchPoints > 2) + { + OS.iOS = true; + OS.iPad = true; + + (navigator.appVersion).match(/Version\/(\d+)/); + + OS.iOSVersion = parseInt(RegExp.$1, 10); + } + else + { + OS.macOS = true; + } + } + else if ((/Android/).test(ua)) + { + OS.android = true; + } + else if ((/Linux/).test(ua)) + { + OS.linux = true; + } + else if ((/iP[ao]d|iPhone/i).test(ua)) + { + OS.iOS = true; + + (navigator.appVersion).match(/OS (\d+)/); + + OS.iOSVersion = parseInt(RegExp.$1, 10); + + OS.iPhone = ua.toLowerCase().indexOf('iphone') !== -1; + OS.iPad = ua.toLowerCase().indexOf('ipad') !== -1; + } + else if ((/Kindle/).test(ua) || (/\bKF[A-Z][A-Z]+/).test(ua) || (/Silk.*Mobile Safari/).test(ua)) + { + OS.kindle = true; + + // This will NOT detect early generations of Kindle Fire, I think there is no reliable way... + // E.g. "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-80) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true" + } + else if ((/CrOS/).test(ua)) + { + OS.chromeOS = true; + } + + if ((/Windows Phone/i).test(ua) || (/IEMobile/i).test(ua)) + { + OS.android = false; + OS.iOS = false; + OS.macOS = false; + OS.windows = true; + OS.windowsPhone = true; + } + + var silk = (/Silk/).test(ua); + + if (OS.windows || OS.macOS || (OS.linux && !silk) || OS.chromeOS) + { + OS.desktop = true; + } + + // Windows Phone / Table reset + if (OS.windowsPhone || (((/Windows NT/i).test(ua)) && ((/Touch/i).test(ua)))) + { + OS.desktop = false; + } + + // WebApp mode in iOS + if (navigator.standalone) + { + OS.webApp = true; + } + + if (typeof importScripts !== 'function') + { + if (window.cordova !== undefined) + { + OS.cordova = true; + } + + if (window.ejecta !== undefined) + { + OS.ejecta = true; + } + } + + if (typeof process !== 'undefined' && process.versions && process.versions.node) + { + OS.node = true; + } + + if (OS.node && typeof process.versions === 'object') + { + OS.nodeWebkit = !!process.versions['node-webkit']; + + OS.electron = !!process.versions.electron; + } + + if ((/Crosswalk/).test(ua)) + { + OS.crosswalk = true; + } + + OS.pixelRatio = window['devicePixelRatio'] || 1; + + return OS; +} + +module.exports = init(); + + +/***/ }), + +/***/ 43267: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); + +/** + * Determines the video support of the browser running this Phaser Game instance. + * + * These values are read-only and populated during the boot sequence of the game. + * + * They are then referenced by internal game systems and are available for you to access + * via `this.sys.game.device.video` from within any Scene. + * + * In Phaser 3.20 the properties were renamed to drop the 'Video' suffix. + * + * @typedef {object} Phaser.Device.Video + * @since 3.0.0 + * + * @property {boolean} h264 - Can this device play h264 mp4 video files? + * @property {boolean} hls - Can this device play hls video files? + * @property {boolean} mov - Can this device play mov video files? + * @property {boolean} mp4 - Can this device play h264 mp4 video files? + * @property {boolean} m4v - Can this device play m4v (typically mp4) video files? + * @property {boolean} ogg - Can this device play ogg video files? + * @property {boolean} vp9 - Can this device play vp9 video files? + * @property {boolean} webm - Can this device play webm video files? + * @property {function} getVideoURL - Returns the first video URL that can be played by this browser. + */ +var Video = { + + h264: false, + hls: false, + mov: false, + mp4: false, + m4v: false, + ogg: false, + vp9: false, + webm: false, + hasRequestVideoFrame: false + +}; + +function init () +{ + if (typeof importScripts === 'function') + { + return Video; + } + + var videoElement = document.createElement('video'); + var result = !!videoElement.canPlayType; + var no = /^no$/; + + try + { + if (result) + { + if (videoElement.canPlayType('video/ogg; codecs="theora"').replace(no, '')) + { + Video.ogg = true; + } + + if (videoElement.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(no, '')) + { + // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 + Video.h264 = true; + Video.mp4 = true; + } + + if (videoElement.canPlayType('video/quicktime4; codecs="avc1.42E01E"').replace(no, '')) + { + Video.mov = true; + } + + if (videoElement.canPlayType('video/x-m4v').replace(no, '')) + { + Video.m4v = true; + } + + if (videoElement.canPlayType('video/webm; codecs="vp8, vorbis"').replace(no, '')) + { + Video.webm = true; + } + + if (videoElement.canPlayType('video/webm; codecs="vp9"').replace(no, '')) + { + Video.vp9 = true; + } + + if (videoElement.canPlayType('application/x-mpegURL; codecs="avc1.42E01E"').replace(no, '')) + { + Video.hls = true; + } + } + } + catch (e) + { + // Nothing to do + } + + if (videoElement.parentNode) + { + videoElement.parentNode.removeChild(videoElement); + } + + Video.getVideoURL = function (urls) + { + if (!Array.isArray(urls)) + { + urls = [ urls ]; + } + + for (var i = 0; i < urls.length; i++) + { + var url = GetFastValue(urls[i], 'url', urls[i]); + + if (url.indexOf('blob:') === 0) + { + return { + url: url, + type: '' + }; + } + + var videoType; + + if (url.indexOf('data:') === 0) + { + videoType = url.split(',')[0].match(/\/(.*?);/); + } + else + { + videoType = url.match(/\.([a-zA-Z0-9]+)($|\?)/); + } + + videoType = GetFastValue(urls[i], 'type', (videoType) ? videoType[1] : '').toLowerCase(); + + if (Video[videoType]) + { + return { + url: url, + type: videoType + }; + } + } + + return null; + }; + + return Video; +} + +module.exports = init(); + + +/***/ }), + +/***/ 82264: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// This singleton is instantiated as soon as Phaser loads, +// before a Phaser.Game instance has even been created. +// Which means all instances of Phaser Games can share it, +// without having to re-poll the device all over again + +/** + * @namespace Phaser.Device + * @since 3.0.0 + */ + +/** + * @typedef {object} Phaser.DeviceConf + * + * @property {Phaser.Device.OS} os - The OS Device functions. + * @property {Phaser.Device.Browser} browser - The Browser Device functions. + * @property {Phaser.Device.Features} features - The Features Device functions. + * @property {Phaser.Device.Input} input - The Input Device functions. + * @property {Phaser.Device.Audio} audio - The Audio Device functions. + * @property {Phaser.Device.Video} video - The Video Device functions. + * @property {Phaser.Device.Fullscreen} fullscreen - The Fullscreen Device functions. + * @property {Phaser.Device.CanvasFeatures} canvasFeatures - The Canvas Device functions. + */ + +module.exports = { + + os: __webpack_require__(25892), + browser: __webpack_require__(84148), + features: __webpack_require__(89357), + input: __webpack_require__(31784), + audio: __webpack_require__(7098), + video: __webpack_require__(43267), + fullscreen: __webpack_require__(91639), + canvasFeatures: __webpack_require__(89289) + +}; + + +/***/ }), + +/***/ 89422: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +var tempMatrix = new Float32Array(20); + +/** + * @classdesc + * The ColorMatrix class creates a 5x4 matrix that can be used in shaders and graphics + * operations. It provides methods required to modify the color values, such as adjusting + * the brightness, setting a sepia tone, hue rotation and more. + * + * Use the method `getData` to return a Float32Array containing the current color values. + * + * @class ColorMatrix + * @memberof Phaser.Display + * @constructor + * @since 3.50.0 + */ +var ColorMatrix = new Class({ + + initialize: + + function ColorMatrix () + { + /** + * Internal ColorMatrix array. + * + * @name Phaser.Display.ColorMatrix#_matrix + * @type {Float32Array} + * @private + * @since 3.50.0 + */ + this._matrix = new Float32Array(20); + + /** + * The value that determines how much of the original color is used + * when mixing the colors. A value between 0 (all original) and 1 (all final) + * + * @name Phaser.Display.ColorMatrix#alpha + * @type {number} + * @since 3.50.0 + */ + this.alpha = 1; + + /** + * Is the ColorMatrix array dirty? + * + * @name Phaser.Display.ColorMatrix#_dirty + * @type {boolean} + * @private + * @since 3.50.0 + */ + this._dirty = true; + + /** + * The matrix data as a Float32Array. + * + * Returned by the `getData` method. + * + * @name Phaser.Display.ColorMatrix#data + * @type {Float32Array} + * @private + * @since 3.50.0 + */ + this._data = new Float32Array(20); + + this.reset(); + }, + + /** + * Sets this ColorMatrix from the given array of color values. + * + * @method Phaser.Display.ColorMatrix#set + * @since 3.50.0 + * + * @param {(number[]|Float32Array)} value - The ColorMatrix values to set. Must have 20 elements. + * + * @return {this} This ColorMatrix instance. + */ + set: function (value) + { + this._matrix.set(value); + + this._dirty = true; + + return this; + }, + + /** + * Resets the ColorMatrix to default values and also resets + * the `alpha` property back to 1. + * + * @method Phaser.Display.ColorMatrix#reset + * @since 3.50.0 + * + * @return {this} This ColorMatrix instance. + */ + reset: function () + { + var m = this._matrix; + + m.fill(0); + + m[0] = 1; + m[6] = 1; + m[12] = 1; + m[18] = 1; + + this.alpha = 1; + + this._dirty = true; + + return this; + }, + + /** + * Gets the ColorMatrix as a Float32Array. + * + * Can be used directly as a 1fv shader uniform value. + * + * @method Phaser.Display.ColorMatrix#getData + * @since 3.50.0 + * + * @return {Float32Array} The ColorMatrix as a Float32Array. + */ + getData: function () + { + var data = this._data; + + if (this._dirty) + { + data.set(this._matrix); + + data[4] /= 255; + data[9] /= 255; + data[14] /= 255; + data[19] /= 255; + + this._dirty = false; + } + + return data; + }, + + /** + * Changes the brightness of this ColorMatrix by the given amount. + * + * @method Phaser.Display.ColorMatrix#brightness + * @since 3.50.0 + * + * @param {number} [value=0] - The amount of brightness to apply to this ColorMatrix. Between 0 (black) and 1. + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + brightness: function (value, multiply) + { + if (value === undefined) { value = 0; } + if (multiply === undefined) { multiply = false; } + + var b = value; + + return this.multiply([ + b, 0, 0, 0, 0, + 0, b, 0, 0, 0, + 0, 0, b, 0, 0, + 0, 0, 0, 1, 0 + ], multiply); + }, + + /** + * Changes the saturation of this ColorMatrix by the given amount. + * + * @method Phaser.Display.ColorMatrix#saturate + * @since 3.50.0 + * + * @param {number} [value=0] - The amount of saturation to apply to this ColorMatrix. + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + saturate: function (value, multiply) + { + if (value === undefined) { value = 0; } + if (multiply === undefined) { multiply = false; } + + var x = (value * 2 / 3) + 1; + var y = ((x - 1) * -0.5); + + return this.multiply([ + x, y, y, 0, 0, + y, x, y, 0, 0, + y, y, x, 0, 0, + 0, 0, 0, 1, 0 + ], multiply); + }, + + /** + * Desaturates this ColorMatrix (removes color from it). + * + * @method Phaser.Display.ColorMatrix#saturation + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + desaturate: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.saturate(-1, multiply); + }, + + /** + * Rotates the hues of this ColorMatrix by the value given. + * + * @method Phaser.Display.ColorMatrix#hue + * @since 3.50.0 + * + * @param {number} [rotation=0] - The amount of hue rotation to apply to this ColorMatrix, in degrees. + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + hue: function (rotation, multiply) + { + if (rotation === undefined) { rotation = 0; } + if (multiply === undefined) { multiply = false; } + + rotation = rotation / 180 * Math.PI; + + var cos = Math.cos(rotation); + var sin = Math.sin(rotation); + var lumR = 0.213; + var lumG = 0.715; + var lumB = 0.072; + + return this.multiply([ + lumR + cos * (1 - lumR) + sin * (-lumR),lumG + cos * (-lumG) + sin * (-lumG),lumB + cos * (-lumB) + sin * (1 - lumB), 0, 0, + lumR + cos * (-lumR) + sin * (0.143),lumG + cos * (1 - lumG) + sin * (0.140),lumB + cos * (-lumB) + sin * (-0.283), 0, 0, + lumR + cos * (-lumR) + sin * (-(1 - lumR)),lumG + cos * (-lumG) + sin * (lumG),lumB + cos * (1 - lumB) + sin * (lumB), 0, 0, + 0, 0, 0, 1, 0 + ], multiply); + }, + + /** + * Sets this ColorMatrix to be grayscale. + * + * @method Phaser.Display.ColorMatrix#grayscale + * @since 3.50.0 + * + * @param {number} [value=1] - The grayscale scale (0 is black). + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + grayscale: function (value, multiply) + { + if (value === undefined) { value = 1; } + if (multiply === undefined) { multiply = false; } + + return this.saturate(-value, multiply); + }, + + /** + * Sets this ColorMatrix to be black and white. + * + * @method Phaser.Display.ColorMatrix#blackWhite + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + blackWhite: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.BLACK_WHITE, multiply); + }, + + /** + * Change the contrast of this ColorMatrix by the amount given. + * + * @method Phaser.Display.ColorMatrix#contrast + * @since 3.50.0 + * + * @param {number} [value=0] - The amount of contrast to apply to this ColorMatrix. + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + contrast: function (value, multiply) + { + if (value === undefined) { value = 0; } + if (multiply === undefined) { multiply = false; } + + var v = value + 1; + var o = -0.5 * (v - 1); + + return this.multiply([ + v, 0, 0, 0, o, + 0, v, 0, 0, o, + 0, 0, v, 0, o, + 0, 0, 0, 1, 0 + ], multiply); + }, + + /** + * Converts this ColorMatrix to have negative values. + * + * @method Phaser.Display.ColorMatrix#negative + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + negative: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.NEGATIVE, multiply); + }, + + /** + * Apply a desaturated luminance to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#desaturateLuminance + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + desaturateLuminance: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.DESATURATE_LUMINANCE, multiply); + }, + + /** + * Applies a sepia tone to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#sepia + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + sepia: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.SEPIA, multiply); + }, + + /** + * Applies a night vision tone to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#night + * @since 3.50.0 + * + * @param {number} [intensity=0.1] - The intensity of this effect. + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + night: function (intensity, multiply) + { + if (intensity === undefined) { intensity = 0.1; } + if (multiply === undefined) { multiply = false; } + + return this.multiply([ + intensity * (-2.0), -intensity, 0, 0, 0, + -intensity, 0, intensity, 0, 0, + 0, intensity, intensity * 2.0, 0, 0, + 0, 0, 0, 1, 0 + ], multiply); + }, + + /** + * Applies a trippy color tone to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#lsd + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + lsd: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.LSD, multiply); + }, + + /** + * Applies a brown tone to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#brown + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + brown: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.BROWN, multiply); + }, + + /** + * Applies a vintage pinhole color effect to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#vintagePinhole + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + vintagePinhole: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.VINTAGE, multiply); + }, + + /** + * Applies a kodachrome color effect to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#kodachrome + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + kodachrome: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.KODACHROME, multiply); + }, + + /** + * Applies a technicolor color effect to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#technicolor + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + technicolor: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.TECHNICOLOR, multiply); + }, + + /** + * Applies a polaroid color effect to this ColorMatrix. + * + * @method Phaser.Display.ColorMatrix#polaroid + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + polaroid: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.POLAROID, multiply); + }, + + /** + * Shifts the values of this ColorMatrix into BGR order. + * + * @method Phaser.Display.ColorMatrix#shiftToBGR + * @since 3.50.0 + * + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + shiftToBGR: function (multiply) + { + if (multiply === undefined) { multiply = false; } + + return this.multiply(ColorMatrix.SHIFT_BGR, multiply); + }, + + /** + * Multiplies the two given matrices. + * + * @method Phaser.Display.ColorMatrix#multiply + * @since 3.50.0 + * + * @param {number[]} a - The 5x4 array to multiply with ColorMatrix._matrix. + * @param {boolean} [multiply=false] - Multiply the resulting ColorMatrix (`true`), or set it (`false`) ? + * + * @return {this} This ColorMatrix instance. + */ + multiply: function (a, multiply) + { + if (multiply === undefined) { multiply = false; } + + // Duplicate _matrix into c + + if (!multiply) + { + this.reset(); + } + + var m = this._matrix; + var c = tempMatrix; + + // copy _matrix to tempMatrox + c.set(m); + + m.set([ + // R + (c[0] * a[0]) + (c[1] * a[5]) + (c[2] * a[10]) + (c[3] * a[15]), + (c[0] * a[1]) + (c[1] * a[6]) + (c[2] * a[11]) + (c[3] * a[16]), + (c[0] * a[2]) + (c[1] * a[7]) + (c[2] * a[12]) + (c[3] * a[17]), + (c[0] * a[3]) + (c[1] * a[8]) + (c[2] * a[13]) + (c[3] * a[18]), + (c[0] * a[4]) + (c[1] * a[9]) + (c[2] * a[14]) + (c[3] * a[19]) + c[4], + + // G + (c[5] * a[0]) + (c[6] * a[5]) + (c[7] * a[10]) + (c[8] * a[15]), + (c[5] * a[1]) + (c[6] * a[6]) + (c[7] * a[11]) + (c[8] * a[16]), + (c[5] * a[2]) + (c[6] * a[7]) + (c[7] * a[12]) + (c[8] * a[17]), + (c[5] * a[3]) + (c[6] * a[8]) + (c[7] * a[13]) + (c[8] * a[18]), + (c[5] * a[4]) + (c[6] * a[9]) + (c[7] * a[14]) + (c[8] * a[19]) + c[9], + + // B + (c[10] * a[0]) + (c[11] * a[5]) + (c[12] * a[10]) + (c[13] * a[15]), + (c[10] * a[1]) + (c[11] * a[6]) + (c[12] * a[11]) + (c[13] * a[16]), + (c[10] * a[2]) + (c[11] * a[7]) + (c[12] * a[12]) + (c[13] * a[17]), + (c[10] * a[3]) + (c[11] * a[8]) + (c[12] * a[13]) + (c[13] * a[18]), + (c[10] * a[4]) + (c[11] * a[9]) + (c[12] * a[14]) + (c[13] * a[19]) + c[14], + + // A + (c[15] * a[0]) + (c[16] * a[5]) + (c[17] * a[10]) + (c[18] * a[15]), + (c[15] * a[1]) + (c[16] * a[6]) + (c[17] * a[11]) + (c[18] * a[16]), + (c[15] * a[2]) + (c[16] * a[7]) + (c[17] * a[12]) + (c[18] * a[17]), + (c[15] * a[3]) + (c[16] * a[8]) + (c[17] * a[13]) + (c[18] * a[18]), + (c[15] * a[4]) + (c[16] * a[9]) + (c[17] * a[14]) + (c[18] * a[19]) + c[19] + + ]); + + this._dirty = true; + + return this; + } + +}); + +/** + * A constant array used by the ColorMatrix class for black_white operations. + * + * @name Phaser.Display.ColorMatrix.BLACK_WHITE + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.BLACK_WHITE = [ 0.3, 0.6, 0.1, 0, 0, 0.3, 0.6, 0.1, 0, 0, 0.3, 0.6, 0.1, 0, 0, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for negative operations. + * + * @name Phaser.Display.ColorMatrix.NEGATIVE + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.NEGATIVE = [ -1, 0, 0, 1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for desatured luminance operations. + * + * @name Phaser.Display.ColorMatrix.DESATURATE_LUMINANCE + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.DESATURATE_LUMINANCE = [ 0.2764723, 0.9297080, 0.0938197, 0, -37.1, 0.2764723, 0.9297080, 0.0938197, 0, -37.1, 0.2764723, 0.9297080, 0.0938197, 0, -37.1, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for sepia operations. + * + * @name Phaser.Display.ColorMatrix.SEPIA + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.SEPIA = [ 0.393, 0.7689999, 0.18899999, 0, 0, 0.349, 0.6859999, 0.16799999, 0, 0, 0.272, 0.5339999, 0.13099999, 0, 0, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for lsd operations. + * + * @name Phaser.Display.ColorMatrix.LSD + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.LSD = [ 2, -0.4, 0.5, 0, 0, -0.5, 2, -0.4, 0, 0, -0.4, -0.5, 3, 0, 0, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for brown operations. + * + * @name Phaser.Display.ColorMatrix.BROWN + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.BROWN = [ 0.5997023498159715, 0.34553243048391263, -0.2708298674538042, 0, 47.43192855600873, -0.037703249837783157, 0.8609577587992641, 0.15059552388459913, 0, -36.96841498319127, 0.24113635128153335, -0.07441037908422492, 0.44972182064877153, 0, -7.562075277591283, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for vintage pinhole operations. + * + * @name Phaser.Display.ColorMatrix.VINTAGE + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.VINTAGE = [ 0.6279345635605994, 0.3202183420819367, -0.03965408211312453, 0, 9.651285835294123, 0.02578397704808868, 0.6441188644374771, 0.03259127616149294, 0, 7.462829176470591, 0.0466055556782719, -0.0851232987247891, 0.5241648018700465, 0, 5.159190588235296, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for kodachrome operations. + * + * @name Phaser.Display.ColorMatrix.KODACHROME + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.KODACHROME = [ 1.1285582396593525, -0.3967382283601348, -0.03992559172921793, 0, 63.72958762196502, -0.16404339962244616, 1.0835251566291304, -0.05498805115633132, 0, 24.732407896706203, -0.16786010706155763, -0.5603416277695248, 1.6014850761964943, 0, 35.62982807460946, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for technicolor operations. + * + * @name Phaser.Display.ColorMatrix.TECHNICOLOR + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.TECHNICOLOR = [ 1.9125277891456083, -0.8545344976951645, -0.09155508482755585, 0, 11.793603434377337, -0.3087833385928097, 1.7658908555458428, -0.10601743074722245, 0, -70.35205161461398, -0.231103377548616, -0.7501899197440212, 1.847597816108189, 0, 30.950940869491138, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for polaroid shift operations. + * + * @name Phaser.Display.ColorMatrix.POLAROID + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.POLAROID = [ 1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016, 1.483, 0, 0, 0, 0, 0, 1, 0 ]; + +/** + * A constant array used by the ColorMatrix class for shift BGR operations. + * + * @name Phaser.Display.ColorMatrix.SHIFT_BGR + * @const + * @type {number[]} + * @since 3.60.0 + */ +ColorMatrix.SHIFT_BGR = [ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0 ]; + +module.exports = ColorMatrix; + + +/***/ }), + +/***/ 51767: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var NOOP = __webpack_require__(29747); + +/** + * @classdesc + * The RGB class holds a single color value and allows for easy modification and reading of it, + * with optional on-change callback notification and a dirty flag. + * + * @class RGB + * @memberof Phaser.Display + * @constructor + * @since 3.50.0 + * + * @param {number} [red=0] - The red color value. A number between 0 and 1. + * @param {number} [green=0] - The green color value. A number between 0 and 1. + * @param {number} [blue=0] - The blue color value. A number between 0 and 1. + */ +var RGB = new Class({ + + initialize: + + function RGB (red, green, blue) + { + /** + * Cached RGB values. + * + * @name Phaser.Display.RGB#_rgb + * @type {number[]} + * @private + * @since 3.50.0 + */ + this._rgb = [ 0, 0, 0 ]; + + /** + * This callback will be invoked each time one of the RGB color values change. + * + * The callback is sent the new color values as the parameters. + * + * @name Phaser.Display.RGB#onChangeCallback + * @type {function} + * @since 3.50.0 + */ + this.onChangeCallback = NOOP; + + /** + * Is this color dirty? + * + * @name Phaser.Display.RGB#dirty + * @type {boolean} + * @since 3.50.0 + */ + this.dirty = false; + + this.set(red, green, blue); + }, + + /** + * Sets the red, green and blue values of this RGB object, flags it as being + * dirty and then invokes the `onChangeCallback`, if set. + * + * @method Phaser.Display.RGB#set + * @since 3.50.0 + * + * @param {number} [red=0] - The red color value. A number between 0 and 1. + * @param {number} [green=0] - The green color value. A number between 0 and 1. + * @param {number} [blue=0] - The blue color value. A number between 0 and 1. + * + * @return {this} This RGB instance. + */ + set: function (red, green, blue) + { + if (red === undefined) { red = 0; } + if (green === undefined) { green = 0; } + if (blue === undefined) { blue = 0; } + + this._rgb = [ red, green, blue ]; + + this.onChange(); + + return this; + }, + + /** + * Compares the given rgb parameters with those in this object and returns + * a boolean `true` value if they are equal, otherwise it returns `false`. + * + * @method Phaser.Display.RGB#equals + * @since 3.50.0 + * + * @param {number} red - The red value to compare with this object. + * @param {number} green - The green value to compare with this object. + * @param {number} blue - The blue value to compare with this object. + * + * @return {boolean} `true` if the given values match those in this object, otherwise `false`. + */ + equals: function (red, green, blue) + { + var rgb = this._rgb; + + return (rgb[0] === red && rgb[1] === green && rgb[2] === blue); + }, + + /** + * Internal on change handler. Sets this object as being dirty and + * then invokes the `onChangeCallback`, if set, passing in the + * new RGB values. + * + * @method Phaser.Display.RGB#onChange + * @since 3.50.0 + */ + onChange: function () + { + this.dirty = true; + + var rgb = this._rgb; + + this.onChangeCallback.call(this, rgb[0], rgb[1], rgb[2]); + }, + + /** + * The red color value. Between 0 and 1. + * + * Changing this property will flag this RGB object as being dirty + * and invoke the `onChangeCallback` , if set. + * + * @name Phaser.Display.RGB#r + * @type {number} + * @since 3.50.0 + */ + r: { + + get: function () + { + return this._rgb[0]; + }, + + set: function (value) + { + this._rgb[0] = value; + this.onChange(); + } + + }, + + /** + * The green color value. Between 0 and 1. + * + * Changing this property will flag this RGB object as being dirty + * and invoke the `onChangeCallback` , if set. + * + * @name Phaser.Display.RGB#g + * @type {number} + * @since 3.50.0 + */ + g: { + + get: function () + { + return this._rgb[1]; + }, + + set: function (value) + { + this._rgb[1] = value; + this.onChange(); + } + + }, + + /** + * The blue color value. Between 0 and 1. + * + * Changing this property will flag this RGB object as being dirty + * and invoke the `onChangeCallback` , if set. + * + * @name Phaser.Display.RGB#b + * @type {number} + * @since 3.50.0 + */ + b: { + + get: function () + { + return this._rgb[2]; + }, + + set: function (value) + { + this._rgb[2] = value; + this.onChange(); + } + + }, + + /** + * Nulls any external references this object contains. + * + * @method Phaser.Display.RGB#destroy + * @since 3.50.0 + */ + destroy: function () + { + this.onChangeCallback = null; + } + +}); + +module.exports = RGB; + + +/***/ }), + +/***/ 60461: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ALIGN_CONST = { + + /** + * A constant representing a top-left alignment or position. + * @constant + * @name Phaser.Display.Align.TOP_LEFT + * @since 3.0.0 + * @type {number} + */ + TOP_LEFT: 0, + + /** + * A constant representing a top-center alignment or position. + * @constant + * @name Phaser.Display.Align.TOP_CENTER + * @since 3.0.0 + * @type {number} + */ + TOP_CENTER: 1, + + /** + * A constant representing a top-right alignment or position. + * @constant + * @name Phaser.Display.Align.TOP_RIGHT + * @since 3.0.0 + * @type {number} + */ + TOP_RIGHT: 2, + + /** + * A constant representing a left-top alignment or position. + * @constant + * @name Phaser.Display.Align.LEFT_TOP + * @since 3.0.0 + * @type {number} + */ + LEFT_TOP: 3, + + /** + * A constant representing a left-center alignment or position. + * @constant + * @name Phaser.Display.Align.LEFT_CENTER + * @since 3.0.0 + * @type {number} + */ + LEFT_CENTER: 4, + + /** + * A constant representing a left-bottom alignment or position. + * @constant + * @name Phaser.Display.Align.LEFT_BOTTOM + * @since 3.0.0 + * @type {number} + */ + LEFT_BOTTOM: 5, + + /** + * A constant representing a center alignment or position. + * @constant + * @name Phaser.Display.Align.CENTER + * @since 3.0.0 + * @type {number} + */ + CENTER: 6, + + /** + * A constant representing a right-top alignment or position. + * @constant + * @name Phaser.Display.Align.RIGHT_TOP + * @since 3.0.0 + * @type {number} + */ + RIGHT_TOP: 7, + + /** + * A constant representing a right-center alignment or position. + * @constant + * @name Phaser.Display.Align.RIGHT_CENTER + * @since 3.0.0 + * @type {number} + */ + RIGHT_CENTER: 8, + + /** + * A constant representing a right-bottom alignment or position. + * @constant + * @name Phaser.Display.Align.RIGHT_BOTTOM + * @since 3.0.0 + * @type {number} + */ + RIGHT_BOTTOM: 9, + + /** + * A constant representing a bottom-left alignment or position. + * @constant + * @name Phaser.Display.Align.BOTTOM_LEFT + * @since 3.0.0 + * @type {number} + */ + BOTTOM_LEFT: 10, + + /** + * A constant representing a bottom-center alignment or position. + * @constant + * @name Phaser.Display.Align.BOTTOM_CENTER + * @since 3.0.0 + * @type {number} + */ + BOTTOM_CENTER: 11, + + /** + * A constant representing a bottom-right alignment or position. + * @constant + * @name Phaser.Display.Align.BOTTOM_RIGHT + * @since 3.0.0 + * @type {number} + */ + BOTTOM_RIGHT: 12 + +}; + +module.exports = ALIGN_CONST; + + +/***/ }), + +/***/ 54312: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetCenterX = __webpack_require__(35893); +var SetBottom = __webpack_require__(86327); +var SetCenterX = __webpack_require__(88417); + +/** + * Takes given Game Object and aligns it so that it is positioned in the bottom center of the other. + * + * @function Phaser.Display.Align.In.BottomCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var BottomCenter = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetCenterX(gameObject, GetCenterX(alignIn) + offsetX); + SetBottom(gameObject, GetBottom(alignIn) + offsetY); + + return gameObject; +}; + +module.exports = BottomCenter; + + +/***/ }), + +/***/ 46768: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetLeft = __webpack_require__(26541); +var SetBottom = __webpack_require__(86327); +var SetLeft = __webpack_require__(385); + +/** + * Takes given Game Object and aligns it so that it is positioned in the bottom left of the other. + * + * @function Phaser.Display.Align.In.BottomLeft + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var BottomLeft = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetLeft(alignIn) - offsetX); + SetBottom(gameObject, GetBottom(alignIn) + offsetY); + + return gameObject; +}; + +module.exports = BottomLeft; + + +/***/ }), + +/***/ 35827: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetRight = __webpack_require__(54380); +var SetBottom = __webpack_require__(86327); +var SetRight = __webpack_require__(40136); + +/** + * Takes given Game Object and aligns it so that it is positioned in the bottom right of the other. + * + * @function Phaser.Display.Align.In.BottomRight + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var BottomRight = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetRight(alignIn) + offsetX); + SetBottom(gameObject, GetBottom(alignIn) + offsetY); + + return gameObject; +}; + +module.exports = BottomRight; + + +/***/ }), + +/***/ 46871: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CenterOn = __webpack_require__(66786); +var GetCenterX = __webpack_require__(35893); +var GetCenterY = __webpack_require__(7702); + +/** + * Takes given Game Object and aligns it so that it is positioned in the center of the other. + * + * @function Phaser.Display.Align.In.Center + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var Center = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + CenterOn(gameObject, GetCenterX(alignIn) + offsetX, GetCenterY(alignIn) + offsetY); + + return gameObject; +}; + +module.exports = Center; + + +/***/ }), + +/***/ 5198: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCenterY = __webpack_require__(7702); +var GetLeft = __webpack_require__(26541); +var SetCenterY = __webpack_require__(20786); +var SetLeft = __webpack_require__(385); + +/** + * Takes given Game Object and aligns it so that it is positioned in the left center of the other. + * + * @function Phaser.Display.Align.In.LeftCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var LeftCenter = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetLeft(alignIn) - offsetX); + SetCenterY(gameObject, GetCenterY(alignIn) + offsetY); + + return gameObject; +}; + +module.exports = LeftCenter; + + +/***/ }), + +/***/ 11879: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ALIGN_CONST = __webpack_require__(60461); + +var AlignInMap = []; + +AlignInMap[ALIGN_CONST.BOTTOM_CENTER] = __webpack_require__(54312); +AlignInMap[ALIGN_CONST.BOTTOM_LEFT] = __webpack_require__(46768); +AlignInMap[ALIGN_CONST.BOTTOM_RIGHT] = __webpack_require__(35827); +AlignInMap[ALIGN_CONST.CENTER] = __webpack_require__(46871); +AlignInMap[ALIGN_CONST.LEFT_CENTER] = __webpack_require__(5198); +AlignInMap[ALIGN_CONST.RIGHT_CENTER] = __webpack_require__(80503); +AlignInMap[ALIGN_CONST.TOP_CENTER] = __webpack_require__(89698); +AlignInMap[ALIGN_CONST.TOP_LEFT] = __webpack_require__(922); +AlignInMap[ALIGN_CONST.TOP_RIGHT] = __webpack_require__(21373); +AlignInMap[ALIGN_CONST.LEFT_BOTTOM] = AlignInMap[ALIGN_CONST.BOTTOM_LEFT]; +AlignInMap[ALIGN_CONST.LEFT_TOP] = AlignInMap[ALIGN_CONST.TOP_LEFT]; +AlignInMap[ALIGN_CONST.RIGHT_BOTTOM] = AlignInMap[ALIGN_CONST.BOTTOM_RIGHT]; +AlignInMap[ALIGN_CONST.RIGHT_TOP] = AlignInMap[ALIGN_CONST.TOP_RIGHT]; + +/** + * Takes given Game Object and aligns it so that it is positioned relative to the other. + * The alignment used is based on the `position` argument, which is an `ALIGN_CONST` value, such as `LEFT_CENTER` or `TOP_RIGHT`. + * + * @function Phaser.Display.Align.In.QuickSet + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} position - The position to align the Game Object with. This is an align constant, such as `ALIGN_CONST.LEFT_CENTER`. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var QuickSet = function (child, alignIn, position, offsetX, offsetY) +{ + return AlignInMap[position](child, alignIn, offsetX, offsetY); +}; + +module.exports = QuickSet; + + +/***/ }), + +/***/ 80503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCenterY = __webpack_require__(7702); +var GetRight = __webpack_require__(54380); +var SetCenterY = __webpack_require__(20786); +var SetRight = __webpack_require__(40136); + +/** + * Takes given Game Object and aligns it so that it is positioned in the right center of the other. + * + * @function Phaser.Display.Align.In.RightCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var RightCenter = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetRight(alignIn) + offsetX); + SetCenterY(gameObject, GetCenterY(alignIn) + offsetY); + + return gameObject; +}; + +module.exports = RightCenter; + + +/***/ }), + +/***/ 89698: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCenterX = __webpack_require__(35893); +var GetTop = __webpack_require__(17717); +var SetCenterX = __webpack_require__(88417); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned in the top center of the other. + * + * @function Phaser.Display.Align.In.TopCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var TopCenter = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetCenterX(gameObject, GetCenterX(alignIn) + offsetX); + SetTop(gameObject, GetTop(alignIn) - offsetY); + + return gameObject; +}; + +module.exports = TopCenter; + + +/***/ }), + +/***/ 922: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLeft = __webpack_require__(26541); +var GetTop = __webpack_require__(17717); +var SetLeft = __webpack_require__(385); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned in the top left of the other. + * + * @function Phaser.Display.Align.In.TopLeft + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var TopLeft = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetLeft(alignIn) - offsetX); + SetTop(gameObject, GetTop(alignIn) - offsetY); + + return gameObject; +}; + +module.exports = TopLeft; + + +/***/ }), + +/***/ 21373: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetRight = __webpack_require__(54380); +var GetTop = __webpack_require__(17717); +var SetRight = __webpack_require__(40136); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned in the top right of the other. + * + * @function Phaser.Display.Align.In.TopRight + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignIn - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var TopRight = function (gameObject, alignIn, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetRight(alignIn) + offsetX); + SetTop(gameObject, GetTop(alignIn) - offsetY); + + return gameObject; +}; + +module.exports = TopRight; + + +/***/ }), + +/***/ 91660: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display.Align.In + */ + +module.exports = { + + BottomCenter: __webpack_require__(54312), + BottomLeft: __webpack_require__(46768), + BottomRight: __webpack_require__(35827), + Center: __webpack_require__(46871), + LeftCenter: __webpack_require__(5198), + QuickSet: __webpack_require__(11879), + RightCenter: __webpack_require__(80503), + TopCenter: __webpack_require__(89698), + TopLeft: __webpack_require__(922), + TopRight: __webpack_require__(21373) + +}; + + +/***/ }), + +/***/ 71926: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(60461); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Display.Align + */ + +var Align = { + + In: __webpack_require__(91660), + To: __webpack_require__(16694) + +}; + +// Merge in the consts +Align = Extend(false, Align, CONST); + +module.exports = Align; + + +/***/ }), + +/***/ 21578: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetCenterX = __webpack_require__(35893); +var SetCenterX = __webpack_require__(88417); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the bottom center position of the other. + * + * @function Phaser.Display.Align.To.BottomCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var BottomCenter = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetCenterX(gameObject, GetCenterX(alignTo) + offsetX); + SetTop(gameObject, GetBottom(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = BottomCenter; + + +/***/ }), + +/***/ 10210: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetLeft = __webpack_require__(26541); +var SetLeft = __webpack_require__(385); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the bottom left position of the other. + * + * @function Phaser.Display.Align.To.BottomLeft + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var BottomLeft = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetLeft(alignTo) - offsetX); + SetTop(gameObject, GetBottom(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = BottomLeft; + + +/***/ }), + +/***/ 82341: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetRight = __webpack_require__(54380); +var SetRight = __webpack_require__(40136); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the bottom right position of the other. + * + * @function Phaser.Display.Align.To.BottomRight + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var BottomRight = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetRight(alignTo) + offsetX); + SetTop(gameObject, GetBottom(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = BottomRight; + + +/***/ }), + +/***/ 87958: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetLeft = __webpack_require__(26541); +var SetBottom = __webpack_require__(86327); +var SetRight = __webpack_require__(40136); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the left bottom position of the other. + * + * @function Phaser.Display.Align.To.LeftBottom + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var LeftBottom = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetLeft(alignTo) - offsetX); + SetBottom(gameObject, GetBottom(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = LeftBottom; + + +/***/ }), + +/***/ 40080: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCenterY = __webpack_require__(7702); +var GetLeft = __webpack_require__(26541); +var SetCenterY = __webpack_require__(20786); +var SetRight = __webpack_require__(40136); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the left center position of the other. + * + * @function Phaser.Display.Align.To.LeftCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var LeftCenter = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetLeft(alignTo) - offsetX); + SetCenterY(gameObject, GetCenterY(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = LeftCenter; + + +/***/ }), + +/***/ 88466: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLeft = __webpack_require__(26541); +var GetTop = __webpack_require__(17717); +var SetRight = __webpack_require__(40136); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the left top position of the other. + * + * @function Phaser.Display.Align.To.LeftTop + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var LeftTop = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetLeft(alignTo) - offsetX); + SetTop(gameObject, GetTop(alignTo) - offsetY); + + return gameObject; +}; + +module.exports = LeftTop; + + +/***/ }), + +/***/ 38829: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ALIGN_CONST = __webpack_require__(60461); + +var AlignToMap = []; + +AlignToMap[ALIGN_CONST.BOTTOM_CENTER] = __webpack_require__(21578); +AlignToMap[ALIGN_CONST.BOTTOM_LEFT] = __webpack_require__(10210); +AlignToMap[ALIGN_CONST.BOTTOM_RIGHT] = __webpack_require__(82341); +AlignToMap[ALIGN_CONST.LEFT_BOTTOM] = __webpack_require__(87958); +AlignToMap[ALIGN_CONST.LEFT_CENTER] = __webpack_require__(40080); +AlignToMap[ALIGN_CONST.LEFT_TOP] = __webpack_require__(88466); +AlignToMap[ALIGN_CONST.RIGHT_BOTTOM] = __webpack_require__(19211); +AlignToMap[ALIGN_CONST.RIGHT_CENTER] = __webpack_require__(34609); +AlignToMap[ALIGN_CONST.RIGHT_TOP] = __webpack_require__(48741); +AlignToMap[ALIGN_CONST.TOP_CENTER] = __webpack_require__(49440); +AlignToMap[ALIGN_CONST.TOP_LEFT] = __webpack_require__(81288); +AlignToMap[ALIGN_CONST.TOP_RIGHT] = __webpack_require__(61323); + +/** + * Takes a Game Object and aligns it next to another, at the given position. + * The alignment used is based on the `position` argument, which is a `Phaser.Display.Align` property such as `LEFT_CENTER` or `TOP_RIGHT`. + * + * @function Phaser.Display.Align.To.QuickSet + * @since 3.22.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} position - The position to align the Game Object with. This is an align constant, such as `Phaser.Display.Align.LEFT_CENTER`. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var QuickSet = function (child, alignTo, position, offsetX, offsetY) +{ + return AlignToMap[position](child, alignTo, offsetX, offsetY); +}; + +module.exports = QuickSet; + + +/***/ }), + +/***/ 19211: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetRight = __webpack_require__(54380); +var SetBottom = __webpack_require__(86327); +var SetLeft = __webpack_require__(385); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the right bottom position of the other. + * + * @function Phaser.Display.Align.To.RightBottom + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var RightBottom = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetRight(alignTo) + offsetX); + SetBottom(gameObject, GetBottom(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = RightBottom; + + +/***/ }), + +/***/ 34609: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCenterY = __webpack_require__(7702); +var GetRight = __webpack_require__(54380); +var SetCenterY = __webpack_require__(20786); +var SetLeft = __webpack_require__(385); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the right center position of the other. + * + * @function Phaser.Display.Align.To.RightCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var RightCenter = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetRight(alignTo) + offsetX); + SetCenterY(gameObject, GetCenterY(alignTo) + offsetY); + + return gameObject; +}; + +module.exports = RightCenter; + + +/***/ }), + +/***/ 48741: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetRight = __webpack_require__(54380); +var GetTop = __webpack_require__(17717); +var SetLeft = __webpack_require__(385); +var SetTop = __webpack_require__(66737); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the right top position of the other. + * + * @function Phaser.Display.Align.To.RightTop + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var RightTop = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetRight(alignTo) + offsetX); + SetTop(gameObject, GetTop(alignTo) - offsetY); + + return gameObject; +}; + +module.exports = RightTop; + + +/***/ }), + +/***/ 49440: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCenterX = __webpack_require__(35893); +var GetTop = __webpack_require__(17717); +var SetBottom = __webpack_require__(86327); +var SetCenterX = __webpack_require__(88417); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the top center position of the other. + * + * @function Phaser.Display.Align.To.TopCenter + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var TopCenter = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetCenterX(gameObject, GetCenterX(alignTo) + offsetX); + SetBottom(gameObject, GetTop(alignTo) - offsetY); + + return gameObject; +}; + +module.exports = TopCenter; + + +/***/ }), + +/***/ 81288: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLeft = __webpack_require__(26541); +var GetTop = __webpack_require__(17717); +var SetBottom = __webpack_require__(86327); +var SetLeft = __webpack_require__(385); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the top left position of the other. + * + * @function Phaser.Display.Align.To.TopLeft + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var TopLeft = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetLeft(gameObject, GetLeft(alignTo) - offsetX); + SetBottom(gameObject, GetTop(alignTo) - offsetY); + + return gameObject; +}; + +module.exports = TopLeft; + + +/***/ }), + +/***/ 61323: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetRight = __webpack_require__(54380); +var GetTop = __webpack_require__(17717); +var SetBottom = __webpack_require__(86327); +var SetRight = __webpack_require__(40136); + +/** + * Takes given Game Object and aligns it so that it is positioned next to the top right position of the other. + * + * @function Phaser.Display.Align.To.TopRight + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be positioned. + * @param {Phaser.GameObjects.GameObject} alignTo - The Game Object to base the alignment position on. + * @param {number} [offsetX=0] - Optional horizontal offset from the position. + * @param {number} [offsetY=0] - Optional vertical offset from the position. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was aligned. + */ +var TopRight = function (gameObject, alignTo, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + SetRight(gameObject, GetRight(alignTo) + offsetX); + SetBottom(gameObject, GetTop(alignTo) - offsetY); + + return gameObject; +}; + +module.exports = TopRight; + + +/***/ }), + +/***/ 16694: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display.Align.To + */ + +module.exports = { + + BottomCenter: __webpack_require__(21578), + BottomLeft: __webpack_require__(10210), + BottomRight: __webpack_require__(82341), + LeftBottom: __webpack_require__(87958), + LeftCenter: __webpack_require__(40080), + LeftTop: __webpack_require__(88466), + QuickSet: __webpack_require__(38829), + RightBottom: __webpack_require__(19211), + RightCenter: __webpack_require__(34609), + RightTop: __webpack_require__(48741), + TopCenter: __webpack_require__(49440), + TopLeft: __webpack_require__(81288), + TopRight: __webpack_require__(61323) + +}; + + +/***/ }), + +/***/ 66786: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetCenterX = __webpack_require__(88417); +var SetCenterY = __webpack_require__(20786); + +/** + * Positions the Game Object so that it is centered on the given coordinates. + * + * @function Phaser.Display.Bounds.CenterOn + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} x - The horizontal coordinate to position the Game Object on. + * @param {number} y - The vertical coordinate to position the Game Object on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var CenterOn = function (gameObject, x, y) +{ + SetCenterX(gameObject, x); + + return SetCenterY(gameObject, y); +}; + +module.exports = CenterOn; + + +/***/ }), + +/***/ 62235: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the bottom coordinate from the bounds of the Game Object. + * + * @function Phaser.Display.Bounds.GetBottom + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The bottom coordinate of the bounds of the Game Object. + */ +var GetBottom = function (gameObject) +{ + return (gameObject.y + gameObject.height) - (gameObject.height * gameObject.originY); +}; + +module.exports = GetBottom; + + +/***/ }), + +/***/ 72873: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetBottom = __webpack_require__(62235); +var GetLeft = __webpack_require__(26541); +var GetRight = __webpack_require__(54380); +var GetTop = __webpack_require__(17717); +var Rectangle = __webpack_require__(87841); + +/** + * Returns the unrotated bounds of the Game Object as a rectangle. + * + * @function Phaser.Display.Bounds.GetBounds + * @since 3.24.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * @param {(Phaser.Geom.Rectangle|object)} [output] - An object to store the values in. If not provided a new Rectangle will be created. + * + * @return {(Phaser.Geom.Rectangle|object)} - The bounds of the Game Object. + */ +var GetBounds = function (gameObject, output) +{ + if (output === undefined) { output = new Rectangle(); } + + var left = GetLeft(gameObject); + var top = GetTop(gameObject); + + output.x = left; + output.y = top; + output.width = GetRight(gameObject) - left; + output.height = GetBottom(gameObject) - top; + + return output; +}; + +module.exports = GetBounds; + + +/***/ }), + +/***/ 35893: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the center x coordinate from the bounds of the Game Object. + * + * @function Phaser.Display.Bounds.GetCenterX + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The center x coordinate of the bounds of the Game Object. + */ +var GetCenterX = function (gameObject) +{ + return gameObject.x - (gameObject.width * gameObject.originX) + (gameObject.width * 0.5); +}; + +module.exports = GetCenterX; + + +/***/ }), + +/***/ 7702: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the center y coordinate from the bounds of the Game Object. + * + * @function Phaser.Display.Bounds.GetCenterY + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The center y coordinate of the bounds of the Game Object. + */ +var GetCenterY = function (gameObject) +{ + return gameObject.y - (gameObject.height * gameObject.originY) + (gameObject.height * 0.5); +}; + +module.exports = GetCenterY; + + +/***/ }), + +/***/ 26541: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the left coordinate from the bounds of the Game Object. + * + * @function Phaser.Display.Bounds.GetLeft + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The left coordinate of the bounds of the Game Object. + */ +var GetLeft = function (gameObject) +{ + return gameObject.x - (gameObject.width * gameObject.originX); +}; + +module.exports = GetLeft; + + +/***/ }), + +/***/ 87431: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the amount the Game Object is visually offset from its x coordinate. + * This is the same as `width * origin.x`. + * This value will only be > 0 if `origin.x` is not equal to zero. + * + * @function Phaser.Display.Bounds.GetOffsetX + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The horizontal offset of the Game Object. + */ +var GetOffsetX = function (gameObject) +{ + return gameObject.width * gameObject.originX; +}; + +module.exports = GetOffsetX; + + +/***/ }), + +/***/ 46928: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the amount the Game Object is visually offset from its y coordinate. + * This is the same as `width * origin.y`. + * This value will only be > 0 if `origin.y` is not equal to zero. + * + * @function Phaser.Display.Bounds.GetOffsetY + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The vertical offset of the Game Object. + */ +var GetOffsetY = function (gameObject) +{ + return gameObject.height * gameObject.originY; +}; + +module.exports = GetOffsetY; + + +/***/ }), + +/***/ 54380: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the right coordinate from the bounds of the Game Object. + * + * @function Phaser.Display.Bounds.GetRight + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The right coordinate of the bounds of the Game Object. + */ +var GetRight = function (gameObject) +{ + return (gameObject.x + gameObject.width) - (gameObject.width * gameObject.originX); +}; + +module.exports = GetRight; + + +/***/ }), + +/***/ 17717: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the top coordinate from the bounds of the Game Object. + * + * @function Phaser.Display.Bounds.GetTop + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to get the bounds value from. + * + * @return {number} The top coordinate of the bounds of the Game Object. + */ +var GetTop = function (gameObject) +{ + return gameObject.y - (gameObject.height * gameObject.originY); +}; + +module.exports = GetTop; + + +/***/ }), + +/***/ 86327: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Positions the Game Object so that the bottom of its bounds aligns with the given coordinate. + * + * @function Phaser.Display.Bounds.SetBottom + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} value - The coordinate to position the Game Object bounds on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var SetBottom = function (gameObject, value) +{ + gameObject.y = (value - gameObject.height) + (gameObject.height * gameObject.originY); + + return gameObject; +}; + +module.exports = SetBottom; + + +/***/ }), + +/***/ 88417: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Positions the Game Object so that the center top of its bounds aligns with the given coordinate. + * + * @function Phaser.Display.Bounds.SetCenterX + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} x - The coordinate to position the Game Object bounds on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var SetCenterX = function (gameObject, x) +{ + var offsetX = gameObject.width * gameObject.originX; + + gameObject.x = (x + offsetX) - (gameObject.width * 0.5); + + return gameObject; +}; + +module.exports = SetCenterX; + + +/***/ }), + +/***/ 20786: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Positions the Game Object so that the center top of its bounds aligns with the given coordinate. + * + * @function Phaser.Display.Bounds.SetCenterY + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} y - The coordinate to position the Game Object bounds on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var SetCenterY = function (gameObject, y) +{ + var offsetY = gameObject.height * gameObject.originY; + + gameObject.y = (y + offsetY) - (gameObject.height * 0.5); + + return gameObject; +}; + +module.exports = SetCenterY; + + +/***/ }), + +/***/ 385: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Positions the Game Object so that the left of its bounds aligns with the given coordinate. + * + * @function Phaser.Display.Bounds.SetLeft + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} value - The coordinate to position the Game Object bounds on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var SetLeft = function (gameObject, value) +{ + gameObject.x = value + (gameObject.width * gameObject.originX); + + return gameObject; +}; + +module.exports = SetLeft; + + +/***/ }), + +/***/ 40136: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Positions the Game Object so that the left of its bounds aligns with the given coordinate. + * + * @function Phaser.Display.Bounds.SetRight + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} value - The coordinate to position the Game Object bounds on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var SetRight = function (gameObject, value) +{ + gameObject.x = (value - gameObject.width) + (gameObject.width * gameObject.originX); + + return gameObject; +}; + +module.exports = SetRight; + + +/***/ }), + +/***/ 66737: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Positions the Game Object so that the top of its bounds aligns with the given coordinate. + * + * @function Phaser.Display.Bounds.SetTop + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will be re-positioned. + * @param {number} value - The coordinate to position the Game Object bounds on. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was positioned. + */ +var SetTop = function (gameObject, value) +{ + gameObject.y = value + (gameObject.height * gameObject.originY); + + return gameObject; +}; + +module.exports = SetTop; + + +/***/ }), + +/***/ 58724: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display.Bounds + */ + +module.exports = { + + CenterOn: __webpack_require__(66786), + GetBottom: __webpack_require__(62235), + GetBounds: __webpack_require__(72873), + GetCenterX: __webpack_require__(35893), + GetCenterY: __webpack_require__(7702), + GetLeft: __webpack_require__(26541), + GetOffsetX: __webpack_require__(87431), + GetOffsetY: __webpack_require__(46928), + GetRight: __webpack_require__(54380), + GetTop: __webpack_require__(17717), + SetBottom: __webpack_require__(86327), + SetCenterX: __webpack_require__(88417), + SetCenterY: __webpack_require__(20786), + SetLeft: __webpack_require__(385), + SetRight: __webpack_require__(40136), + SetTop: __webpack_require__(66737) + +}; + + +/***/ }), + +/***/ 20623: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display.Canvas.CanvasInterpolation + * @since 3.0.0 + */ +var CanvasInterpolation = { + + /** + * Sets the CSS image-rendering property on the given canvas to be 'crisp' (aka 'optimize contrast' on webkit). + * + * @function Phaser.Display.Canvas.CanvasInterpolation.setCrisp + * @since 3.0.0 + * + * @param {HTMLCanvasElement} canvas - The canvas object to have the style set on. + * + * @return {HTMLCanvasElement} The canvas. + */ + setCrisp: function (canvas) + { + var types = [ 'optimizeSpeed', '-moz-crisp-edges', '-o-crisp-edges', '-webkit-optimize-contrast', 'optimize-contrast', 'crisp-edges', 'pixelated' ]; + + types.forEach(function (type) + { + canvas.style['image-rendering'] = type; + }); + + canvas.style.msInterpolationMode = 'nearest-neighbor'; + + return canvas; + }, + + /** + * Sets the CSS image-rendering property on the given canvas to be 'bicubic' (aka 'auto'). + * + * @function Phaser.Display.Canvas.CanvasInterpolation.setBicubic + * @since 3.0.0 + * + * @param {HTMLCanvasElement} canvas - The canvas object to have the style set on. + * + * @return {HTMLCanvasElement} The canvas. + */ + setBicubic: function (canvas) + { + canvas.style['image-rendering'] = 'auto'; + canvas.style.msInterpolationMode = 'bicubic'; + + return canvas; + } + +}; + +module.exports = CanvasInterpolation; + + +/***/ }), + +/***/ 27919: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(8054); +var Smoothing = __webpack_require__(68703); + +// The pool into which the canvas elements are placed. +var pool = []; + +// Automatically apply smoothing(false) to created Canvas elements +var _disableContextSmoothing = false; + +/** + * The CanvasPool is a global static object, that allows Phaser to recycle and pool 2D Context Canvas DOM elements. + * It does not pool WebGL Contexts, because once the context options are set they cannot be modified again, + * which is useless for the Phaser renderer. + * + * This singleton is instantiated as soon as Phaser loads, before a Phaser.Game instance has even been created. + * Which means all instances of Phaser Games on the same page can share the one single pool. + * + * @namespace Phaser.Display.Canvas.CanvasPool + * @since 3.0.0 + */ +var CanvasPool = function () +{ + /** + * Creates a new Canvas DOM element, or pulls one from the pool if free. + * + * @function Phaser.Display.Canvas.CanvasPool.create + * @since 3.0.0 + * + * @param {*} parent - The parent of the Canvas object. + * @param {number} [width=1] - The width of the Canvas. + * @param {number} [height=1] - The height of the Canvas. + * @param {number} [canvasType=Phaser.CANVAS] - The type of the Canvas. Either `Phaser.CANVAS` or `Phaser.WEBGL`. + * @param {boolean} [selfParent=false] - Use the generated Canvas element as the parent? + * + * @return {HTMLCanvasElement} The canvas element that was created or pulled from the pool + */ + var create = function (parent, width, height, canvasType, selfParent) + { + if (width === undefined) { width = 1; } + if (height === undefined) { height = 1; } + if (canvasType === undefined) { canvasType = CONST.CANVAS; } + if (selfParent === undefined) { selfParent = false; } + + var canvas; + var container = first(canvasType); + + if (container === null) + { + container = { + parent: parent, + canvas: document.createElement('canvas'), + type: canvasType + }; + + if (canvasType === CONST.CANVAS) + { + pool.push(container); + } + + canvas = container.canvas; + } + else + { + container.parent = parent; + + canvas = container.canvas; + } + + if (selfParent) + { + container.parent = canvas; + } + + canvas.width = width; + canvas.height = height; + + if (_disableContextSmoothing && canvasType === CONST.CANVAS) + { + Smoothing.disable(canvas.getContext('2d', { willReadFrequently: false })); + } + + return canvas; + }; + + /** + * Creates a new Canvas DOM element, or pulls one from the pool if free. + * + * @function Phaser.Display.Canvas.CanvasPool.create2D + * @since 3.0.0 + * + * @param {*} parent - The parent of the Canvas object. + * @param {number} [width=1] - The width of the Canvas. + * @param {number} [height=1] - The height of the Canvas. + * + * @return {HTMLCanvasElement} The created canvas. + */ + var create2D = function (parent, width, height) + { + return create(parent, width, height, CONST.CANVAS); + }; + + /** + * Creates a new Canvas DOM element, or pulls one from the pool if free. + * + * @function Phaser.Display.Canvas.CanvasPool.createWebGL + * @since 3.0.0 + * + * @param {*} parent - The parent of the Canvas object. + * @param {number} [width=1] - The width of the Canvas. + * @param {number} [height=1] - The height of the Canvas. + * + * @return {HTMLCanvasElement} The created WebGL canvas. + */ + var createWebGL = function (parent, width, height) + { + return create(parent, width, height, CONST.WEBGL); + }; + + /** + * Gets the first free canvas index from the pool. + * + * @function Phaser.Display.Canvas.CanvasPool.first + * @since 3.0.0 + * + * @param {number} [canvasType=Phaser.CANVAS] - The type of the Canvas. Either `Phaser.CANVAS` or `Phaser.WEBGL`. + * + * @return {HTMLCanvasElement} The first free canvas, or `null` if a WebGL canvas was requested or if the pool doesn't have free canvases. + */ + var first = function (canvasType) + { + if (canvasType === undefined) { canvasType = CONST.CANVAS; } + + if (canvasType === CONST.WEBGL) + { + return null; + } + + for (var i = 0; i < pool.length; i++) + { + var container = pool[i]; + + if (!container.parent && container.type === canvasType) + { + return container; + } + } + + return null; + }; + + /** + * Looks up a canvas based on its parent, and if found puts it back in the pool, freeing it up for re-use. + * The canvas has its width and height set to 1, and its parent attribute nulled. + * + * @function Phaser.Display.Canvas.CanvasPool.remove + * @since 3.0.0 + * + * @param {*} parent - The canvas or the parent of the canvas to free. + */ + var remove = function (parent) + { + // Check to see if the parent is a canvas object + var isCanvas = parent instanceof HTMLCanvasElement; + + pool.forEach(function (container) + { + if ((isCanvas && container.canvas === parent) || (!isCanvas && container.parent === parent)) + { + container.parent = null; + container.canvas.width = 1; + container.canvas.height = 1; + } + }); + }; + + /** + * Gets the total number of used canvas elements in the pool. + * + * @function Phaser.Display.Canvas.CanvasPool.total + * @since 3.0.0 + * + * @return {number} The number of used canvases. + */ + var total = function () + { + var c = 0; + + pool.forEach(function (container) + { + if (container.parent) + { + c++; + } + }); + + return c; + }; + + /** + * Gets the total number of free canvas elements in the pool. + * + * @function Phaser.Display.Canvas.CanvasPool.free + * @since 3.0.0 + * + * @return {number} The number of free canvases. + */ + var free = function () + { + return pool.length - total(); + }; + + /** + * Disable context smoothing on any new Canvas element created. + * + * @function Phaser.Display.Canvas.CanvasPool.disableSmoothing + * @since 3.0.0 + */ + var disableSmoothing = function () + { + _disableContextSmoothing = true; + }; + + /** + * Enable context smoothing on any new Canvas element created. + * + * @function Phaser.Display.Canvas.CanvasPool.enableSmoothing + * @since 3.0.0 + */ + var enableSmoothing = function () + { + _disableContextSmoothing = false; + }; + + return { + create2D: create2D, + create: create, + createWebGL: createWebGL, + disableSmoothing: disableSmoothing, + enableSmoothing: enableSmoothing, + first: first, + free: free, + pool: pool, + remove: remove, + total: total + }; +}; + +// If we export the called function here, it'll only be invoked once (not every time it's required). +module.exports = CanvasPool(); + + +/***/ }), + +/***/ 68703: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Browser specific prefix, so not going to change between contexts, only between browsers +var prefix = ''; + +/** + * @namespace Phaser.Display.Canvas.Smoothing + * @since 3.0.0 + */ +var Smoothing = function () +{ + /** + * Gets the Smoothing Enabled vendor prefix being used on the given context, or null if not set. + * + * @function Phaser.Display.Canvas.Smoothing.getPrefix + * @since 3.0.0 + * + * @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The canvas context to check. + * + * @return {string} The name of the property on the context which controls image smoothing (either `imageSmoothingEnabled` or a vendor-prefixed version thereof), or `null` if not supported. + */ + var getPrefix = function (context) + { + var vendors = [ 'i', 'webkitI', 'msI', 'mozI', 'oI' ]; + + for (var i = 0; i < vendors.length; i++) + { + var s = vendors[i] + 'mageSmoothingEnabled'; + + if (s in context) + { + return s; + } + } + + return null; + }; + + /** + * Sets the Image Smoothing property on the given context. Set to false to disable image smoothing. + * By default browsers have image smoothing enabled, which isn't always what you visually want, especially + * when using pixel art in a game. Note that this sets the property on the context itself, so that any image + * drawn to the context will be affected. This sets the property across all current browsers but support is + * patchy on earlier browsers, especially on mobile. + * + * @function Phaser.Display.Canvas.Smoothing.enable + * @since 3.0.0 + * + * @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The context on which to enable smoothing. + * + * @return {(CanvasRenderingContext2D|WebGLRenderingContext)} The provided context. + */ + var enable = function (context) + { + if (prefix === '') + { + prefix = getPrefix(context); + } + + if (prefix) + { + context[prefix] = true; + } + + return context; + }; + + /** + * Sets the Image Smoothing property on the given context. Set to false to disable image smoothing. + * By default browsers have image smoothing enabled, which isn't always what you visually want, especially + * when using pixel art in a game. Note that this sets the property on the context itself, so that any image + * drawn to the context will be affected. This sets the property across all current browsers but support is + * patchy on earlier browsers, especially on mobile. + * + * @function Phaser.Display.Canvas.Smoothing.disable + * @since 3.0.0 + * + * @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The context on which to disable smoothing. + * + * @return {(CanvasRenderingContext2D|WebGLRenderingContext)} The provided context. + */ + var disable = function (context) + { + if (prefix === '') + { + prefix = getPrefix(context); + } + + if (prefix) + { + context[prefix] = false; + } + + return context; + }; + + /** + * Returns `true` if the given context has image smoothing enabled, otherwise returns `false`. + * Returns null if no smoothing prefix is available. + * + * @function Phaser.Display.Canvas.Smoothing.isEnabled + * @since 3.0.0 + * + * @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The context to check. + * + * @return {?boolean} `true` if smoothing is enabled on the context, otherwise `false`. `null` if not supported. + */ + var isEnabled = function (context) + { + return (prefix !== null) ? context[prefix] : null; + }; + + return { + disable: disable, + enable: enable, + getPrefix: getPrefix, + isEnabled: isEnabled + }; + +}; + +module.exports = Smoothing(); + + +/***/ }), + +/***/ 65208: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sets the touch-action property on the canvas style. Can be used to disable default browser touch actions. + * + * @function Phaser.Display.Canvas.TouchAction + * @since 3.0.0 + * + * @param {HTMLCanvasElement} canvas - The canvas element to have the style applied to. + * @param {string} [value='none'] - The touch action value to set on the canvas. Set to `none` to disable touch actions. + * + * @return {HTMLCanvasElement} The canvas element. + */ +var TouchAction = function (canvas, value) +{ + if (value === undefined) { value = 'none'; } + + canvas.style['msTouchAction'] = value; + canvas.style['ms-touch-action'] = value; + canvas.style['touch-action'] = value; + + return canvas; +}; + +module.exports = TouchAction; + + +/***/ }), + +/***/ 91610: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sets the user-select property on the canvas style. Can be used to disable default browser selection actions. + * + * @function Phaser.Display.Canvas.UserSelect + * @since 3.0.0 + * + * @param {HTMLCanvasElement} canvas - The canvas element to have the style applied to. + * @param {string} [value='none'] - The touch callout value to set on the canvas. Set to `none` to disable touch callouts. + * + * @return {HTMLCanvasElement} The canvas element. + */ +var UserSelect = function (canvas, value) +{ + if (value === undefined) { value = 'none'; } + + var vendors = [ + '-webkit-', + '-khtml-', + '-moz-', + '-ms-', + '' + ]; + + vendors.forEach(function (vendor) + { + canvas.style[vendor + 'user-select'] = value; + }); + + canvas.style['-webkit-touch-callout'] = value; + canvas.style['-webkit-tap-highlight-color'] = 'rgba(0, 0, 0, 0)'; + + return canvas; +}; + +module.exports = UserSelect; + + +/***/ }), + +/***/ 26253: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display.Canvas + */ + +module.exports = { + + CanvasInterpolation: __webpack_require__(20623), + CanvasPool: __webpack_require__(27919), + Smoothing: __webpack_require__(68703), + TouchAction: __webpack_require__(65208), + UserSelect: __webpack_require__(91610) + +}; + + +/***/ }), + +/***/ 40987: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetColor = __webpack_require__(37589); +var GetColor32 = __webpack_require__(1000); +var HSVToRGB = __webpack_require__(7537); +var RGBToHSV = __webpack_require__(87837); + +/** + * @namespace Phaser.Display.Color + */ + +/** + * @classdesc + * The Color class holds a single color value and allows for easy modification and reading of it. + * + * @class Color + * @memberof Phaser.Display + * @constructor + * @since 3.0.0 + * + * @param {number} [red=0] - The red color value. A number between 0 and 255. + * @param {number} [green=0] - The green color value. A number between 0 and 255. + * @param {number} [blue=0] - The blue color value. A number between 0 and 255. + * @param {number} [alpha=255] - The alpha value. A number between 0 and 255. + */ +var Color = new Class({ + + initialize: + + function Color (red, green, blue, alpha) + { + if (red === undefined) { red = 0; } + if (green === undefined) { green = 0; } + if (blue === undefined) { blue = 0; } + if (alpha === undefined) { alpha = 255; } + + /** + * The internal red color value. + * + * @name Phaser.Display.Color#r + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this.r = 0; + + /** + * The internal green color value. + * + * @name Phaser.Display.Color#g + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this.g = 0; + + /** + * The internal blue color value. + * + * @name Phaser.Display.Color#b + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this.b = 0; + + /** + * The internal alpha color value. + * + * @name Phaser.Display.Color#a + * @type {number} + * @private + * @default 255 + * @since 3.0.0 + */ + this.a = 255; + + /** + * The hue color value. A number between 0 and 1. + * This is the base color. + * + * @name Phaser.Display.Color#_h + * @type {number} + * @default 0 + * @private + * @since 3.13.0 + */ + this._h = 0; + + /** + * The saturation color value. A number between 0 and 1. + * This controls how much of the hue will be in the final color, where 1 is fully saturated and 0 will give you white. + * + * @name Phaser.Display.Color#_s + * @type {number} + * @default 0 + * @private + * @since 3.13.0 + */ + this._s = 0; + + /** + * The lightness color value. A number between 0 and 1. + * This controls how dark the color is. Where 1 is as bright as possible and 0 is black. + * + * @name Phaser.Display.Color#_v + * @type {number} + * @default 0 + * @private + * @since 3.13.0 + */ + this._v = 0; + + /** + * Is this color update locked? + * + * @name Phaser.Display.Color#_locked + * @type {boolean} + * @private + * @since 3.13.0 + */ + this._locked = false; + + /** + * An array containing the calculated color values for WebGL use. + * + * @name Phaser.Display.Color#gl + * @type {number[]} + * @since 3.0.0 + */ + this.gl = [ 0, 0, 0, 1 ]; + + /** + * Pre-calculated internal color value. + * + * @name Phaser.Display.Color#_color + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._color = 0; + + /** + * Pre-calculated internal color32 value. + * + * @name Phaser.Display.Color#_color32 + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._color32 = 0; + + /** + * Pre-calculated internal color rgb string value. + * + * @name Phaser.Display.Color#_rgba + * @type {string} + * @private + * @default '' + * @since 3.0.0 + */ + this._rgba = ''; + + this.setTo(red, green, blue, alpha); + }, + + /** + * Sets this color to be transparent. Sets all values to zero. + * + * @method Phaser.Display.Color#transparent + * @since 3.0.0 + * + * @return {Phaser.Display.Color} This Color object. + */ + transparent: function () + { + this._locked = true; + + this.red = 0; + this.green = 0; + this.blue = 0; + this.alpha = 0; + + this._locked = false; + + return this.update(true); + }, + + /** + * Sets the color of this Color component. + * + * @method Phaser.Display.Color#setTo + * @since 3.0.0 + * + * @param {number} red - The red color value. A number between 0 and 255. + * @param {number} green - The green color value. A number between 0 and 255. + * @param {number} blue - The blue color value. A number between 0 and 255. + * @param {number} [alpha=255] - The alpha value. A number between 0 and 255. + * @param {boolean} [updateHSV=true] - Update the HSV values after setting the RGB values? + * + * @return {Phaser.Display.Color} This Color object. + */ + setTo: function (red, green, blue, alpha, updateHSV) + { + if (alpha === undefined) { alpha = 255; } + if (updateHSV === undefined) { updateHSV = true; } + + this._locked = true; + + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + + this._locked = false; + + return this.update(updateHSV); + }, + + /** + * Sets the red, green, blue and alpha GL values of this Color component. + * + * @method Phaser.Display.Color#setGLTo + * @since 3.0.0 + * + * @param {number} red - The red color value. A number between 0 and 1. + * @param {number} green - The green color value. A number between 0 and 1. + * @param {number} blue - The blue color value. A number between 0 and 1. + * @param {number} [alpha=1] - The alpha value. A number between 0 and 1. + * + * @return {Phaser.Display.Color} This Color object. + */ + setGLTo: function (red, green, blue, alpha) + { + if (alpha === undefined) { alpha = 1; } + + this._locked = true; + + this.redGL = red; + this.greenGL = green; + this.blueGL = blue; + this.alphaGL = alpha; + + this._locked = false; + + return this.update(true); + }, + + /** + * Sets the color based on the color object given. + * + * @method Phaser.Display.Color#setFromRGB + * @since 3.0.0 + * + * @param {Phaser.Types.Display.InputColorObject} color - An object containing `r`, `g`, `b` and optionally `a` values in the range 0 to 255. + * + * @return {Phaser.Display.Color} This Color object. + */ + setFromRGB: function (color) + { + this._locked = true; + + this.red = color.r; + this.green = color.g; + this.blue = color.b; + + if (color.hasOwnProperty('a')) + { + this.alpha = color.a; + } + + this._locked = false; + + return this.update(true); + }, + + /** + * Sets the color based on the hue, saturation and lightness values given. + * + * @method Phaser.Display.Color#setFromHSV + * @since 3.13.0 + * + * @param {number} h - The hue, in the range 0 - 1. This is the base color. + * @param {number} s - The saturation, in the range 0 - 1. This controls how much of the hue will be in the final color, where 1 is fully saturated and 0 will give you white. + * @param {number} v - The value, in the range 0 - 1. This controls how dark the color is. Where 1 is as bright as possible and 0 is black. + * + * @return {Phaser.Display.Color} This Color object. + */ + setFromHSV: function (h, s, v) + { + return HSVToRGB(h, s, v, this); + }, + + /** + * Updates the internal cache values. + * + * @method Phaser.Display.Color#update + * @private + * @since 3.0.0 + * + * @return {Phaser.Display.Color} This Color object. + */ + update: function (updateHSV) + { + if (updateHSV === undefined) { updateHSV = false; } + + if (this._locked) + { + return this; + } + + var r = this.r; + var g = this.g; + var b = this.b; + var a = this.a; + + this._color = GetColor(r, g, b); + this._color32 = GetColor32(r, g, b, a); + this._rgba = 'rgba(' + r + ',' + g + ',' + b + ',' + (a / 255) + ')'; + + if (updateHSV) + { + RGBToHSV(r, g, b, this); + } + + return this; + }, + + /** + * Updates the internal hsv cache values. + * + * @method Phaser.Display.Color#updateHSV + * @private + * @since 3.13.0 + * + * @return {Phaser.Display.Color} This Color object. + */ + updateHSV: function () + { + var r = this.r; + var g = this.g; + var b = this.b; + + RGBToHSV(r, g, b, this); + + return this; + }, + + /** + * Returns a new Color component using the values from this one. + * + * @method Phaser.Display.Color#clone + * @since 3.0.0 + * + * @return {Phaser.Display.Color} A new Color object. + */ + clone: function () + { + return new Color(this.r, this.g, this.b, this.a); + }, + + /** + * Sets this Color object to be grayscaled based on the shade value given. + * + * @method Phaser.Display.Color#gray + * @since 3.13.0 + * + * @param {number} shade - A value between 0 and 255. + * + * @return {Phaser.Display.Color} This Color object. + */ + gray: function (shade) + { + return this.setTo(shade, shade, shade); + }, + + /** + * Sets this Color object to be a random color between the `min` and `max` values given. + * + * @method Phaser.Display.Color#random + * @since 3.13.0 + * + * @param {number} [min=0] - The minimum random color value. Between 0 and 255. + * @param {number} [max=255] - The maximum random color value. Between 0 and 255. + * + * @return {Phaser.Display.Color} This Color object. + */ + random: function (min, max) + { + if (min === undefined) { min = 0; } + if (max === undefined) { max = 255; } + + var r = Math.floor(min + Math.random() * (max - min)); + var g = Math.floor(min + Math.random() * (max - min)); + var b = Math.floor(min + Math.random() * (max - min)); + + return this.setTo(r, g, b); + }, + + /** + * Sets this Color object to be a random grayscale color between the `min` and `max` values given. + * + * @method Phaser.Display.Color#randomGray + * @since 3.13.0 + * + * @param {number} [min=0] - The minimum random color value. Between 0 and 255. + * @param {number} [max=255] - The maximum random color value. Between 0 and 255. + * + * @return {Phaser.Display.Color} This Color object. + */ + randomGray: function (min, max) + { + if (min === undefined) { min = 0; } + if (max === undefined) { max = 255; } + + var s = Math.floor(min + Math.random() * (max - min)); + + return this.setTo(s, s, s); + }, + + /** + * Increase the saturation of this Color by the percentage amount given. + * The saturation is the amount of the base color in the hue. + * + * @method Phaser.Display.Color#saturate + * @since 3.13.0 + * + * @param {number} amount - The percentage amount to change this color by. A value between 0 and 100. + * + * @return {Phaser.Display.Color} This Color object. + */ + saturate: function (amount) + { + this.s += amount / 100; + + return this; + }, + + /** + * Decrease the saturation of this Color by the percentage amount given. + * The saturation is the amount of the base color in the hue. + * + * @method Phaser.Display.Color#desaturate + * @since 3.13.0 + * + * @param {number} amount - The percentage amount to change this color by. A value between 0 and 100. + * + * @return {Phaser.Display.Color} This Color object. + */ + desaturate: function (amount) + { + this.s -= amount / 100; + + return this; + }, + + /** + * Increase the lightness of this Color by the percentage amount given. + * + * @method Phaser.Display.Color#lighten + * @since 3.13.0 + * + * @param {number} amount - The percentage amount to change this color by. A value between 0 and 100. + * + * @return {Phaser.Display.Color} This Color object. + */ + lighten: function (amount) + { + this.v += amount / 100; + + return this; + }, + + /** + * Decrease the lightness of this Color by the percentage amount given. + * + * @method Phaser.Display.Color#darken + * @since 3.13.0 + * + * @param {number} amount - The percentage amount to change this color by. A value between 0 and 100. + * + * @return {Phaser.Display.Color} This Color object. + */ + darken: function (amount) + { + this.v -= amount / 100; + + return this; + }, + + /** + * Brighten this Color by the percentage amount given. + * + * @method Phaser.Display.Color#brighten + * @since 3.13.0 + * + * @param {number} amount - The percentage amount to change this color by. A value between 0 and 100. + * + * @return {Phaser.Display.Color} This Color object. + */ + brighten: function (amount) + { + var r = this.r; + var g = this.g; + var b = this.b; + + r = Math.max(0, Math.min(255, r - Math.round(255 * - (amount / 100)))); + g = Math.max(0, Math.min(255, g - Math.round(255 * - (amount / 100)))); + b = Math.max(0, Math.min(255, b - Math.round(255 * - (amount / 100)))); + + return this.setTo(r, g, b); + }, + + /** + * The color of this Color component, not including the alpha channel. + * + * @name Phaser.Display.Color#color + * @type {number} + * @readonly + * @since 3.0.0 + */ + color: { + + get: function () + { + return this._color; + } + + }, + + /** + * The color of this Color component, including the alpha channel. + * + * @name Phaser.Display.Color#color32 + * @type {number} + * @readonly + * @since 3.0.0 + */ + color32: { + + get: function () + { + return this._color32; + } + + }, + + /** + * The color of this Color component as a string which can be used in CSS color values. + * + * @name Phaser.Display.Color#rgba + * @type {string} + * @readonly + * @since 3.0.0 + */ + rgba: { + + get: function () + { + return this._rgba; + } + + }, + + /** + * The red color value, normalized to the range 0 to 1. + * + * @name Phaser.Display.Color#redGL + * @type {number} + * @since 3.0.0 + */ + redGL: { + + get: function () + { + return this.gl[0]; + }, + + set: function (value) + { + this.gl[0] = Math.min(Math.abs(value), 1); + + this.r = Math.floor(this.gl[0] * 255); + + this.update(true); + } + + }, + + /** + * The green color value, normalized to the range 0 to 1. + * + * @name Phaser.Display.Color#greenGL + * @type {number} + * @since 3.0.0 + */ + greenGL: { + + get: function () + { + return this.gl[1]; + }, + + set: function (value) + { + this.gl[1] = Math.min(Math.abs(value), 1); + + this.g = Math.floor(this.gl[1] * 255); + + this.update(true); + } + + }, + + /** + * The blue color value, normalized to the range 0 to 1. + * + * @name Phaser.Display.Color#blueGL + * @type {number} + * @since 3.0.0 + */ + blueGL: { + + get: function () + { + return this.gl[2]; + }, + + set: function (value) + { + this.gl[2] = Math.min(Math.abs(value), 1); + + this.b = Math.floor(this.gl[2] * 255); + + this.update(true); + } + + }, + + /** + * The alpha color value, normalized to the range 0 to 1. + * + * @name Phaser.Display.Color#alphaGL + * @type {number} + * @since 3.0.0 + */ + alphaGL: { + + get: function () + { + return this.gl[3]; + }, + + set: function (value) + { + this.gl[3] = Math.min(Math.abs(value), 1); + + this.a = Math.floor(this.gl[3] * 255); + + this.update(); + } + + }, + + /** + * The red color value, normalized to the range 0 to 255. + * + * @name Phaser.Display.Color#red + * @type {number} + * @since 3.0.0 + */ + red: { + + get: function () + { + return this.r; + }, + + set: function (value) + { + value = Math.floor(Math.abs(value)); + + this.r = Math.min(value, 255); + + this.gl[0] = value / 255; + + this.update(true); + } + + }, + + /** + * The green color value, normalized to the range 0 to 255. + * + * @name Phaser.Display.Color#green + * @type {number} + * @since 3.0.0 + */ + green: { + + get: function () + { + return this.g; + }, + + set: function (value) + { + value = Math.floor(Math.abs(value)); + + this.g = Math.min(value, 255); + + this.gl[1] = value / 255; + + this.update(true); + } + + }, + + /** + * The blue color value, normalized to the range 0 to 255. + * + * @name Phaser.Display.Color#blue + * @type {number} + * @since 3.0.0 + */ + blue: { + + get: function () + { + return this.b; + }, + + set: function (value) + { + value = Math.floor(Math.abs(value)); + + this.b = Math.min(value, 255); + + this.gl[2] = value / 255; + + this.update(true); + } + + }, + + /** + * The alpha color value, normalized to the range 0 to 255. + * + * @name Phaser.Display.Color#alpha + * @type {number} + * @since 3.0.0 + */ + alpha: { + + get: function () + { + return this.a; + }, + + set: function (value) + { + value = Math.floor(Math.abs(value)); + + this.a = Math.min(value, 255); + + this.gl[3] = value / 255; + + this.update(); + } + + }, + + /** + * The hue color value. A number between 0 and 1. + * This is the base color. + * + * @name Phaser.Display.Color#h + * @type {number} + * @since 3.13.0 + */ + h: { + + get: function () + { + return this._h; + }, + + set: function (value) + { + this._h = value; + + HSVToRGB(value, this._s, this._v, this); + } + + }, + + /** + * The saturation color value. A number between 0 and 1. + * This controls how much of the hue will be in the final color, where 1 is fully saturated and 0 will give you white. + * + * @name Phaser.Display.Color#s + * @type {number} + * @since 3.13.0 + */ + s: { + + get: function () + { + return this._s; + }, + + set: function (value) + { + this._s = value; + + HSVToRGB(this._h, value, this._v, this); + } + + }, + + /** + * The lightness color value. A number between 0 and 1. + * This controls how dark the color is. Where 1 is as bright as possible and 0 is black. + * + * @name Phaser.Display.Color#v + * @type {number} + * @since 3.13.0 + */ + v: { + + get: function () + { + return this._v; + }, + + set: function (value) + { + this._v = value; + + HSVToRGB(this._h, this._s, value, this); + } + + } + +}); + +module.exports = Color; + + +/***/ }), + +/***/ 92728: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetColor = __webpack_require__(37589); + +/** + * Return an array of Colors in a Color Spectrum. + * + * The spectrum colors flow in the order: red, yellow, green, blue. + * + * By default this function will return an array with 1024 elements in. + * + * However, you can reduce this to a smaller quantity if needed, by specitying the `limit` parameter. + * + * @function Phaser.Display.Color.ColorSpectrum + * @since 3.50.0 + * + * @param {number} [limit=1024] - How many colors should be returned? The maximum is 1024 but you can set a smaller quantity if required. + * + * @return {Phaser.Types.Display.ColorObject[]} An array containing `limit` parameter number of elements, where each contains a Color Object. + */ +var ColorSpectrum = function (limit) +{ + if (limit === undefined) { limit = 1024; } + + var colors = []; + + var range = 255; + + var i; + var r = 255; + var g = 0; + var b = 0; + + // Red to Yellow + for (i = 0; i <= range; i++) + { + colors.push({ r: r, g: i, b: b, color: GetColor(r, i, b) }); + } + + g = 255; + + // Yellow to Green + for (i = range; i >= 0; i--) + { + colors.push({ r: i, g: g, b: b, color: GetColor(i, g, b) }); + } + + r = 0; + + // Green to Blue + for (i = 0; i <= range; i++, g--) + { + colors.push({ r: r, g: g, b: i, color: GetColor(r, g, i) }); + } + + g = 0; + b = 255; + + // Blue to Red + for (i = 0; i <= range; i++, b--, r++) + { + colors.push({ r: r, g: g, b: b, color: GetColor(r, g, b) }); + } + + if (limit === 1024) + { + return colors; + } + else + { + var out = []; + + var t = 0; + var inc = 1024 / limit; + + for (i = 0; i < limit; i++) + { + out.push(colors[Math.floor(t)]); + + t += inc; + } + + return out; + } +}; + +module.exports = ColorSpectrum; + + +/***/ }), + +/***/ 91588: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts the given color value into an Object containing r,g,b and a properties. + * + * @function Phaser.Display.Color.ColorToRGBA + * @since 3.0.0 + * + * @param {number} color - A color value, optionally including the alpha value. + * + * @return {Phaser.Types.Display.ColorObject} An object containing the parsed color values. + */ +var ColorToRGBA = function (color) +{ + var output = { + r: color >> 16 & 0xFF, + g: color >> 8 & 0xFF, + b: color & 0xFF, + a: 255 + }; + + if (color > 16777215) + { + output.a = color >>> 24; + } + + return output; +}; + +module.exports = ColorToRGBA; + + +/***/ }), + +/***/ 62957: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns a string containing a hex representation of the given color component. + * + * @function Phaser.Display.Color.ComponentToHex + * @since 3.0.0 + * + * @param {number} color - The color channel to get the hex value for, must be a value between 0 and 255. + * + * @return {string} A string of length 2 characters, i.e. 255 = ff, 100 = 64. + */ +var ComponentToHex = function (color) +{ + var hex = color.toString(16); + + return (hex.length === 1) ? '0' + hex : hex; +}; + +module.exports = ComponentToHex; + + +/***/ }), + +/***/ 37589: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Given 3 separate color values this will return an integer representation of it. + * + * @function Phaser.Display.Color.GetColor + * @since 3.0.0 + * + * @param {number} red - The red color value. A number between 0 and 255. + * @param {number} green - The green color value. A number between 0 and 255. + * @param {number} blue - The blue color value. A number between 0 and 255. + * + * @return {number} The combined color value. + */ +var GetColor = function (red, green, blue) +{ + return red << 16 | green << 8 | blue; +}; + +module.exports = GetColor; + + +/***/ }), + +/***/ 1000: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Given an alpha and 3 color values this will return an integer representation of it. + * + * @function Phaser.Display.Color.GetColor32 + * @since 3.0.0 + * + * @param {number} red - The red color value. A number between 0 and 255. + * @param {number} green - The green color value. A number between 0 and 255. + * @param {number} blue - The blue color value. A number between 0 and 255. + * @param {number} alpha - The alpha color value. A number between 0 and 255. + * + * @return {number} The combined color value. + */ +var GetColor32 = function (red, green, blue, alpha) +{ + return alpha << 24 | red << 16 | green << 8 | blue; +}; + +module.exports = GetColor32; + + +/***/ }), + +/***/ 62183: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Color = __webpack_require__(40987); +var HueToComponent = __webpack_require__(89528); + +/** + * Converts HSL (hue, saturation and lightness) values to a Phaser Color object. + * + * @function Phaser.Display.Color.HSLToColor + * @since 3.0.0 + * + * @param {number} h - The hue value in the range 0 to 1. + * @param {number} s - The saturation value in the range 0 to 1. + * @param {number} l - The lightness value in the range 0 to 1. + * + * @return {Phaser.Display.Color} A Color object created from the results of the h, s and l values. + */ +var HSLToColor = function (h, s, l) +{ + // achromatic by default + var r = l; + var g = l; + var b = l; + + if (s !== 0) + { + var q = (l < 0.5) ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + + r = HueToComponent(p, q, h + 1 / 3); + g = HueToComponent(p, q, h); + b = HueToComponent(p, q, h - 1 / 3); + } + + var color = new Color(); + + return color.setGLTo(r, g, b, 1); +}; + +module.exports = HSLToColor; + + +/***/ }), + +/***/ 27939: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var HSVToRGB = __webpack_require__(7537); + +/** + * Generates an HSV color wheel which is an array of 360 Color objects, for each step of the wheel. + * + * @function Phaser.Display.Color.HSVColorWheel + * @since 3.0.0 + * + * @param {number} [s=1] - The saturation, in the range 0 - 1. + * @param {number} [v=1] - The value, in the range 0 - 1. + * + * @return {Phaser.Types.Display.ColorObject[]} An array containing 360 ColorObject elements, where each element contains a Color object corresponding to the color at that point in the HSV color wheel. + */ +var HSVColorWheel = function (s, v) +{ + if (s === undefined) { s = 1; } + if (v === undefined) { v = 1; } + + var colors = []; + + for (var c = 0; c <= 359; c++) + { + colors.push(HSVToRGB(c / 359, s, v)); + } + + return colors; +}; + +module.exports = HSVColorWheel; + + +/***/ }), + +/***/ 7537: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetColor = __webpack_require__(37589); + +/** + * RGB space conversion. + * + * @ignore + * + * @param {number} n - The value to convert. + * @param {number} h - The h value. + * @param {number} s - The s value. + * @param {number} v - The v value. + * + * @return {number} The converted value. + */ +function ConvertValue (n, h, s, v) +{ + var k = (n + h * 6) % 6; + + var min = Math.min(k, 4 - k, 1); + + return Math.round(255 * (v - v * s * Math.max(0, min))); +} + +/** + * Converts a HSV (hue, saturation and value) color set to RGB. + * + * Conversion formula from https://en.wikipedia.org/wiki/HSL_and_HSV + * + * Assumes HSV values are contained in the set [0, 1]. + * + * @function Phaser.Display.Color.HSVToRGB + * @since 3.0.0 + * + * @param {number} h - The hue, in the range 0 - 1. This is the base color. + * @param {number} s - The saturation, in the range 0 - 1. This controls how much of the hue will be in the final color, where 1 is fully saturated and 0 will give you white. + * @param {number} v - The value, in the range 0 - 1. This controls how dark the color is. Where 1 is as bright as possible and 0 is black. + * @param {(Phaser.Types.Display.ColorObject|Phaser.Display.Color)} [out] - A Color object to store the results in. If not given a new ColorObject will be created. + * + * @return {(Phaser.Types.Display.ColorObject|Phaser.Display.Color)} An object with the red, green and blue values set in the r, g and b properties. + */ +var HSVToRGB = function (h, s, v, out) +{ + if (s === undefined) { s = 1; } + if (v === undefined) { v = 1; } + + var r = ConvertValue(5, h, s, v); + var g = ConvertValue(3, h, s, v); + var b = ConvertValue(1, h, s, v); + + if (!out) + { + return { r: r, g: g, b: b, color: GetColor(r, g, b) }; + } + else if (out.setTo) + { + return out.setTo(r, g, b, out.alpha, true); + } + else + { + out.r = r; + out.g = g; + out.b = b; + out.color = GetColor(r, g, b); + + return out; + } +}; + +module.exports = HSVToRGB; + + +/***/ }), + +/***/ 70238: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Color = __webpack_require__(40987); + +/** + * Converts a hex string into a Phaser Color object. + * + * The hex string can supplied as `'#0033ff'` or the short-hand format of `'#03f'`; it can begin with an optional "#" or "0x", or be unprefixed. + * + * An alpha channel is _not_ supported. + * + * @function Phaser.Display.Color.HexStringToColor + * @since 3.0.0 + * + * @param {string} hex - The hex color value to convert, such as `#0033ff` or the short-hand format: `#03f`. + * + * @return {Phaser.Display.Color} A Color object populated by the values of the given string. + */ +var HexStringToColor = function (hex) +{ + var color = new Color(); + + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + hex = hex.replace(/^(?:#|0x)?([a-f\d])([a-f\d])([a-f\d])$/i, function (m, r, g, b) + { + return r + r + g + g + b + b; + }); + + var result = (/^(?:#|0x)?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i).exec(hex); + + if (result) + { + var r = parseInt(result[1], 16); + var g = parseInt(result[2], 16); + var b = parseInt(result[3], 16); + + color.setTo(r, g, b); + } + + return color; +}; + +module.exports = HexStringToColor; + + +/***/ }), + +/***/ 89528: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts a hue to an RGB color. + * Based on code by Michael Jackson (https://github.com/mjijackson) + * + * @function Phaser.Display.Color.HueToComponent + * @since 3.0.0 + * + * @param {number} p + * @param {number} q + * @param {number} t + * + * @return {number} The combined color value. + */ +var HueToComponent = function (p, q, t) +{ + if (t < 0) + { + t += 1; + } + + if (t > 1) + { + t -= 1; + } + + if (t < 1 / 6) + { + return p + (q - p) * 6 * t; + } + + if (t < 1 / 2) + { + return q; + } + + if (t < 2 / 3) + { + return p + (q - p) * (2 / 3 - t) * 6; + } + + return p; +}; + +module.exports = HueToComponent; + + +/***/ }), + +/***/ 30100: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Color = __webpack_require__(40987); +var IntegerToRGB = __webpack_require__(90664); + +/** + * Converts the given color value into an instance of a Color object. + * + * @function Phaser.Display.Color.IntegerToColor + * @since 3.0.0 + * + * @param {number} input - The color value to convert into a Color object. + * + * @return {Phaser.Display.Color} A Color object. + */ +var IntegerToColor = function (input) +{ + var rgb = IntegerToRGB(input); + + return new Color(rgb.r, rgb.g, rgb.b, rgb.a); +}; + +module.exports = IntegerToColor; + + +/***/ }), + +/***/ 90664: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Return the component parts of a color as an Object with the properties alpha, red, green, blue. + * + * Alpha will only be set if it exists in the given color (0xAARRGGBB) + * + * @function Phaser.Display.Color.IntegerToRGB + * @since 3.0.0 + * + * @param {number} input - The color value to convert into a Color object. + * + * @return {Phaser.Types.Display.ColorObject} An object with the red, green and blue values set in the r, g and b properties. + */ +var IntegerToRGB = function (color) +{ + if (color > 16777215) + { + // The color value has an alpha component + return { + a: color >>> 24, + r: color >> 16 & 0xFF, + g: color >> 8 & 0xFF, + b: color & 0xFF + }; + } + else + { + return { + a: 255, + r: color >> 16 & 0xFF, + g: color >> 8 & 0xFF, + b: color & 0xFF + }; + } +}; + +module.exports = IntegerToRGB; + + +/***/ }), + +/***/ 13699: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Linear = __webpack_require__(28915); +var GetColor = __webpack_require__(37589); + +/** + * @namespace Phaser.Display.Color.Interpolate + * @memberof Phaser.Display.Color + * @since 3.0.0 + */ + +/** + * Interpolates between the two given color ranges over the length supplied. + * + * @function Phaser.Display.Color.Interpolate.RGBWithRGB + * @memberof Phaser.Display.Color.Interpolate + * @static + * @since 3.0.0 + * + * @param {number} r1 - Red value. + * @param {number} g1 - Blue value. + * @param {number} b1 - Green value. + * @param {number} r2 - Red value. + * @param {number} g2 - Blue value. + * @param {number} b2 - Green value. + * @param {number} [length=100] - Distance to interpolate over. + * @param {number} [index=0] - Index to start from. + * + * @return {Phaser.Types.Display.ColorObject} An object containing the interpolated color values. + */ +var RGBWithRGB = function (r1, g1, b1, r2, g2, b2, length, index) +{ + if (length === undefined) { length = 100; } + if (index === undefined) { index = 0; } + + var t = index / length; + var r = Linear(r1, r2, t); + var g = Linear(g1, g2, t); + var b = Linear(b1, b2, t); + + return { + r: r, + g: g, + b: b, + a: 255, + color: GetColor(r, g, b) + }; +}; + +/** + * Interpolates between the two given color objects over the length supplied. + * + * @function Phaser.Display.Color.Interpolate.ColorWithColor + * @memberof Phaser.Display.Color.Interpolate + * @static + * @since 3.0.0 + * + * @param {Phaser.Display.Color} color1 - The first Color object. + * @param {Phaser.Display.Color} color2 - The second Color object. + * @param {number} [length=100] - Distance to interpolate over. + * @param {number} [index=0] - Index to start from. + * + * @return {Phaser.Types.Display.ColorObject} An object containing the interpolated color values. + */ +var ColorWithColor = function (color1, color2, length, index) +{ + if (length === undefined) { length = 100; } + if (index === undefined) { index = 0; } + + return RGBWithRGB(color1.r, color1.g, color1.b, color2.r, color2.g, color2.b, length, index); +}; + +/** + * Interpolates between the Color object and color values over the length supplied. + * + * @function Phaser.Display.Color.Interpolate.ColorWithRGB + * @memberof Phaser.Display.Color.Interpolate + * @static + * @since 3.0.0 + * + * @param {Phaser.Display.Color} color1 - The first Color object. + * @param {number} r - Red value. + * @param {number} g - Blue value. + * @param {number} b - Green value. + * @param {number} [length=100] - Distance to interpolate over. + * @param {number} [index=0] - Index to start from. + * + * @return {Phaser.Types.Display.ColorObject} An object containing the interpolated color values. + */ +var ColorWithRGB = function (color, r, g, b, length, index) +{ + if (length === undefined) { length = 100; } + if (index === undefined) { index = 0; } + + return RGBWithRGB(color.r, color.g, color.b, r, g, b, length, index); +}; + +module.exports = { + + RGBWithRGB: RGBWithRGB, + ColorWithRGB: ColorWithRGB, + ColorWithColor: ColorWithColor + +}; + + +/***/ }), + +/***/ 68957: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Color = __webpack_require__(40987); + +/** + * Converts an object containing `r`, `g`, `b` and `a` properties into a Color class instance. + * + * @function Phaser.Display.Color.ObjectToColor + * @since 3.0.0 + * + * @param {Phaser.Types.Display.InputColorObject} input - An object containing `r`, `g`, `b` and `a` properties in the range 0 to 255. + * + * @return {Phaser.Display.Color} A Color object. + */ +var ObjectToColor = function (input) +{ + return new Color(input.r, input.g, input.b, input.a); +}; + +module.exports = ObjectToColor; + + +/***/ }), + +/***/ 87388: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Color = __webpack_require__(40987); + +/** + * Converts a CSS 'web' string into a Phaser Color object. + * + * The web string can be in the format `'rgb(r,g,b)'` or `'rgba(r,g,b,a)'` where r/g/b are in the range [0..255] and a is in the range [0..1]. + * + * @function Phaser.Display.Color.RGBStringToColor + * @since 3.0.0 + * + * @param {string} rgb - The CSS format color string, using the `rgb` or `rgba` format. + * + * @return {Phaser.Display.Color} A Color object. + */ +var RGBStringToColor = function (rgb) +{ + var color = new Color(); + + var result = (/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d+(?:\.\d+)?))?\s*\)$/).exec(rgb.toLowerCase()); + + if (result) + { + var r = parseInt(result[1], 10); + var g = parseInt(result[2], 10); + var b = parseInt(result[3], 10); + var a = (result[4] !== undefined) ? parseFloat(result[4]) : 1; + + color.setTo(r, g, b, a * 255); + } + + return color; +}; + +module.exports = RGBStringToColor; + + +/***/ }), + +/***/ 87837: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts an RGB color value to HSV (hue, saturation and value). + * Conversion formula from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes RGB values are contained in the set [0, 255] and returns h, s and v in the set [0, 1]. + * Based on code by Michael Jackson (https://github.com/mjijackson) + * + * @function Phaser.Display.Color.RGBToHSV + * @since 3.0.0 + * + * @param {number} r - The red color value. A number between 0 and 255. + * @param {number} g - The green color value. A number between 0 and 255. + * @param {number} b - The blue color value. A number between 0 and 255. + * @param {(Phaser.Types.Display.HSVColorObject|Phaser.Display.Color)} [out] - An object to store the color values in. If not given an HSV Color Object will be created. + * + * @return {(Phaser.Types.Display.HSVColorObject|Phaser.Display.Color)} An object with the properties `h`, `s` and `v` set. + */ +var RGBToHSV = function (r, g, b, out) +{ + if (out === undefined) { out = { h: 0, s: 0, v: 0 }; } + + r /= 255; + g /= 255; + b /= 255; + + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var d = max - min; + + // achromatic by default + var h = 0; + var s = (max === 0) ? 0 : d / max; + var v = max; + + if (max !== min) + { + if (max === r) + { + h = (g - b) / d + ((g < b) ? 6 : 0); + } + else if (max === g) + { + h = (b - r) / d + 2; + } + else if (max === b) + { + h = (r - g) / d + 4; + } + + h /= 6; + } + + if (out.hasOwnProperty('_h')) + { + out._h = h; + out._s = s; + out._v = v; + } + else + { + out.h = h; + out.s = s; + out.v = v; + } + + return out; +}; + +module.exports = RGBToHSV; + + +/***/ }), + +/***/ 75723: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ComponentToHex = __webpack_require__(62957); + +/** + * Converts the color values into an HTML compatible color string, prefixed with either `#` or `0x`. + * + * @function Phaser.Display.Color.RGBToString + * @since 3.0.0 + * + * @param {number} r - The red color value. A number between 0 and 255. + * @param {number} g - The green color value. A number between 0 and 255. + * @param {number} b - The blue color value. A number between 0 and 255. + * @param {number} [a=255] - The alpha value. A number between 0 and 255. + * @param {string} [prefix=#] - The prefix of the string. Either `#` or `0x`. + * + * @return {string} A string-based representation of the color values. + */ +var RGBToString = function (r, g, b, a, prefix) +{ + if (a === undefined) { a = 255; } + if (prefix === undefined) { prefix = '#'; } + + if (prefix === '#') + { + return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1, 7); + } + else + { + return '0x' + ComponentToHex(a) + ComponentToHex(r) + ComponentToHex(g) + ComponentToHex(b); + } +}; + +module.exports = RGBToString; + + +/***/ }), + +/***/ 85386: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Between = __webpack_require__(30976); +var Color = __webpack_require__(40987); + +/** + * Creates a new Color object where the r, g, and b values have been set to random values + * based on the given min max values. + * + * @function Phaser.Display.Color.RandomRGB + * @since 3.0.0 + * + * @param {number} [min=0] - The minimum value to set the random range from (between 0 and 255) + * @param {number} [max=255] - The maximum value to set the random range from (between 0 and 255) + * + * @return {Phaser.Display.Color} A Color object. + */ +var RandomRGB = function (min, max) +{ + if (min === undefined) { min = 0; } + if (max === undefined) { max = 255; } + + return new Color(Between(min, max), Between(min, max), Between(min, max)); +}; + +module.exports = RandomRGB; + + +/***/ }), + +/***/ 80333: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var HexStringToColor = __webpack_require__(70238); +var IntegerToColor = __webpack_require__(30100); +var ObjectToColor = __webpack_require__(68957); +var RGBStringToColor = __webpack_require__(87388); + +/** + * Converts the given source color value into an instance of a Color class. + * The value can be either a string, prefixed with `rgb` or a hex string, a number or an Object. + * + * @function Phaser.Display.Color.ValueToColor + * @since 3.0.0 + * + * @param {(string|number|Phaser.Types.Display.InputColorObject)} input - The source color value to convert. + * + * @return {Phaser.Display.Color} A Color object. + */ +var ValueToColor = function (input) +{ + var t = typeof input; + + switch (t) + { + case 'string': + + if (input.substr(0, 3).toLowerCase() === 'rgb') + { + return RGBStringToColor(input); + } + else + { + return HexStringToColor(input); + } + + case 'number': + + return IntegerToColor(input); + + case 'object': + + return ObjectToColor(input); + } +}; + +module.exports = ValueToColor; + + +/***/ }), + +/***/ 3956: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Color = __webpack_require__(40987); + +Color.ColorSpectrum = __webpack_require__(92728); +Color.ColorToRGBA = __webpack_require__(91588); +Color.ComponentToHex = __webpack_require__(62957); +Color.GetColor = __webpack_require__(37589); +Color.GetColor32 = __webpack_require__(1000); +Color.HexStringToColor = __webpack_require__(70238); +Color.HSLToColor = __webpack_require__(62183); +Color.HSVColorWheel = __webpack_require__(27939); +Color.HSVToRGB = __webpack_require__(7537); +Color.HueToComponent = __webpack_require__(89528); +Color.IntegerToColor = __webpack_require__(30100); +Color.IntegerToRGB = __webpack_require__(90664); +Color.Interpolate = __webpack_require__(13699); +Color.ObjectToColor = __webpack_require__(68957); +Color.RandomRGB = __webpack_require__(85386); +Color.RGBStringToColor = __webpack_require__(87388); +Color.RGBToHSV = __webpack_require__(87837); +Color.RGBToString = __webpack_require__(75723); +Color.ValueToColor = __webpack_require__(80333); + +module.exports = Color; + + +/***/ }), + +/***/ 27460: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display + */ + +module.exports = { + + Align: __webpack_require__(71926), + BaseShader: __webpack_require__(73894), + Bounds: __webpack_require__(58724), + Canvas: __webpack_require__(26253), + Color: __webpack_require__(3956), + ColorMatrix: __webpack_require__(89422), + Masks: __webpack_require__(69781), + RGB: __webpack_require__(51767) + +}; + + +/***/ }), + +/***/ 80661: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A Geometry Mask can be applied to a Game Object to hide any pixels of it which don't intersect + * a visible pixel from the geometry mask. The mask is essentially a clipping path which can only + * make a masked pixel fully visible or fully invisible without changing its alpha (opacity). + * + * A Geometry Mask uses a Graphics Game Object to determine which pixels of the masked Game Object(s) + * should be clipped. For any given point of a masked Game Object's texture, the pixel will only be displayed + * if the Graphics Game Object of the Geometry Mask has a visible pixel at the same position. The color and + * alpha of the pixel from the Geometry Mask do not matter. + * + * The Geometry Mask's location matches the location of its Graphics object, not the location of the masked objects. + * Moving or transforming the underlying Graphics object will change the mask (and affect the visibility + * of any masked objects), whereas moving or transforming a masked object will not affect the mask. + * You can think of the Geometry Mask (or rather, of its Graphics object) as an invisible curtain placed + * in front of all masked objects which has its own visual properties and, naturally, respects the camera's + * visual properties, but isn't affected by and doesn't follow the masked objects by itself. + * + * GeometryMask is only supported in the Canvas Renderer. + * If you want to use geometry to mask objects in WebGL, + * see {@link Phaser.GameObjects.Components.FilterList#addMask}. + * + * @class GeometryMask + * @memberof Phaser.Display.Masks + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - This parameter is not used. + * @param {Phaser.GameObjects.Graphics} graphicsGeometry - The Graphics Game Object to use for the Geometry Mask. Doesn't have to be in the Display List. + */ +var GeometryMask = new Class({ + + initialize: + + function GeometryMask (scene, graphicsGeometry) + { + /** + * The Graphics object which describes the Geometry Mask. + * + * @name Phaser.Display.Masks.GeometryMask#geometryMask + * @type {Phaser.GameObjects.Graphics} + * @since 3.0.0 + */ + this.geometryMask = graphicsGeometry; + }, + + /** + * Sets a new Graphics object for the Geometry Mask. + * + * @method Phaser.Display.Masks.GeometryMask#setShape + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Graphics} graphicsGeometry - The Graphics object which will be used for the Geometry Mask. + * + * @return {this} This Geometry Mask + */ + setShape: function (graphicsGeometry) + { + this.geometryMask = graphicsGeometry; + + return this; + }, + + /** + * Sets the clipping path of a 2D canvas context to the Geometry Mask's underlying Graphics object. + * + * @method Phaser.Display.Masks.GeometryMask#preRenderCanvas + * @since 3.0.0 + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - The Canvas Renderer instance to set the clipping path on. + * @param {Phaser.GameObjects.GameObject} mask - The Game Object being rendered. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera the Game Object is being rendered through. + */ + preRenderCanvas: function (renderer, mask, camera) + { + var geometryMask = this.geometryMask; + + renderer.currentContext.save(); + + geometryMask.renderCanvas(renderer, geometryMask, camera, null, null, true); + + renderer.currentContext.clip(); + }, + + /** + * Restore the canvas context's previous clipping path, thus turning off the mask for it. + * + * @method Phaser.Display.Masks.GeometryMask#postRenderCanvas + * @since 3.0.0 + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - The Canvas Renderer instance being restored. + */ + postRenderCanvas: function (renderer) + { + renderer.currentContext.restore(); + }, + + /** + * Destroys this GeometryMask and nulls any references it holds. + * + * Note that if a Game Object is currently using this mask it will _not_ automatically detect you have destroyed it, + * so be sure to call `clearMask` on any Game Object using it, before destroying it. + * + * @method Phaser.Display.Masks.GeometryMask#destroy + * @since 3.7.0 + */ + destroy: function () + { + this.geometryMask = null; + } + +}); + +module.exports = GeometryMask; + + +/***/ }), + +/***/ 69781: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Display.Masks + */ + +module.exports = { + + GeometryMask: __webpack_require__(80661) + +}; + + +/***/ }), + +/***/ 73894: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A BaseShader is a small resource class that contains GLSL code for a shader. + * + * It contains the key of the shader, the source code, and optional metadata. + * The source code is not of a specific type, such as fragment or vertex, + * or even an incomplete snippet of GLSL. + * It's just the raw source code as a string. + * It may be retrieved and compiled as you wish. + * These keys can be used by `Phaser.GameObjects.Shader` and + * `Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader`. + * + * BaseShaders are stored in the Shader Cache, available in a Scene via `this.cache.shaders` and are referenced + * by a unique key-based string. Retrieve them via `this.cache.shaders.get(key)`. + * + * BaseShaders are created automatically by the GLSL File Loader when loading an external shader resource. + * They can also be created at runtime, allowing you to use dynamically generated shader source code. + * + * @class BaseShader + * @memberof Phaser.Display + * @constructor + * @since 4.0.0 + * + * @param {string} key - The key of this shader. Must be unique within the shader cache. + * @param {string} glsl - The GLSL source code for the shader. + * @param {object} [metadata] - Additional metadata for this shader code. + */ +var BaseShader = new Class({ + initialize: function BaseShader (key, glsl, metadata) + { + if (metadata === undefined) { metadata = {}; } + + /** + * The key of this shader code, + * unique within the shader cache of this Phaser game instance. + * + * @name Phaser.Display.BaseShader#key + * @type {string} + * @since 3.17.0 + */ + this.key = key; + + /** + * GLSL source code for a shader. + * The use of this code is not specified by Phaser. + * You can add metadata to further describe its purpose. + * + * @name Phaser.Display.BaseShader#glsl + * @type {string} + * @since 4.0.0 + */ + this.glsl = glsl; + + /** + * Additional metadata for this shader. This is not used by Phaser, + * but it may be used by your game code or external tools. + * For example, you could add properties that describe + * the shader's purpose, author, version, etc. + * + * @name Phaser.Display.BaseShader#metadata + * @type {object} + * @since 4.0.0 + */ + this.metadata = metadata; + } +}); + +module.exports = BaseShader; + + +/***/ }), + +/***/ 40366: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Adds the given element to the DOM. If a parent is provided the element is added as a child of the parent, providing it was able to access it. + * If no parent was given it falls back to using `document.body`. + * + * @function Phaser.DOM.AddToDOM + * @since 3.0.0 + * + * @param {HTMLElement} element - The element to be added to the DOM. Usually a Canvas object. + * @param {(string|HTMLElement)} [parent] - The parent in which to add the element. Can be a string which is passed to `getElementById` or an actual DOM object. + * + * @return {HTMLElement} The element that was added to the DOM. + */ +var AddToDOM = function (element, parent) +{ + var target; + + if (parent) + { + if (typeof parent === 'string') + { + // Hopefully an element ID + target = document.getElementById(parent); + } + else if (typeof parent === 'object' && parent.nodeType === 1) + { + // Quick test for a HTMLElement + target = parent; + } + } + else if (element.parentElement || parent === null) + { + return element; + } + + // Fallback, covers an invalid ID and a non HTMLElement object + if (!target) + { + target = document.body; + } + + target.appendChild(element); + + return element; +}; + +module.exports = AddToDOM; + + +/***/ }), + +/***/ 83719: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AddToDOM = __webpack_require__(40366); + +var CreateDOMContainer = function (game) +{ + var config = game.config; + + if (!config.parent || !config.domCreateContainer) + { + return; + } + + // DOM Element Container + var div = document.createElement('div'); + + div.style.cssText = [ + 'display: block;', + 'width: ' + game.scale.width + 'px;', + 'height: ' + game.scale.height + 'px;', + 'padding: 0; margin: 0;', + 'position: absolute;', + 'overflow: hidden;', + 'pointer-events: ' + config.domPointerEvents + ';', + 'transform: scale(1);', + 'transform-origin: left top;' + ].join(' '); + + game.domContainer = div; + + AddToDOM(div, config.parent); +}; + +module.exports = CreateDOMContainer; + + +/***/ }), + +/***/ 57264: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var OS = __webpack_require__(25892); + +/** + * @callback ContentLoadedCallback + */ + +/** + * Inspects the readyState of the document. If the document is already complete then it invokes the given callback. + * If not complete it sets up several event listeners such as `deviceready`, and once those fire, it invokes the callback. + * Called automatically by the Phaser.Game instance. Should not usually be accessed directly. + * + * @function Phaser.DOM.DOMContentLoaded + * @since 3.0.0 + * + * @param {ContentLoadedCallback} callback - The callback to be invoked when the device is ready and the DOM content is loaded. + */ +var DOMContentLoaded = function (callback) +{ + if (document.readyState === 'complete' || document.readyState === 'interactive') + { + callback(); + + return; + } + + var check = function () + { + document.removeEventListener('deviceready', check, true); + document.removeEventListener('DOMContentLoaded', check, true); + window.removeEventListener('load', check, true); + + callback(); + }; + + if (!document.body) + { + window.setTimeout(check, 20); + } + else if (OS.cordova) + { + // Ref. http://docs.phonegap.com/en/3.5.0/cordova_events_events.md.html#deviceready + document.addEventListener('deviceready', check, false); + } + else + { + document.addEventListener('DOMContentLoaded', check, true); + window.addEventListener('load', check, true); + } +}; + +module.exports = DOMContentLoaded; + + +/***/ }), + +/***/ 57811: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Attempts to determine the document inner height across iOS and standard devices. + * Based on code by @tylerjpeterson + * + * @function Phaser.DOM.GetInnerHeight + * @since 3.16.0 + * + * @param {boolean} iOS - Is this running on iOS? + * + * @return {number} The inner height value. + */ +var GetInnerHeight = function (iOS) +{ + + if (!iOS) + { + return window.innerHeight; + } + + var axis = Math.abs(window.orientation); + + var size = { w: 0, h: 0 }; + + var ruler = document.createElement('div'); + + ruler.setAttribute('style', 'position: fixed; height: 100vh; width: 0; top: 0'); + + document.documentElement.appendChild(ruler); + + size.w = (axis === 90) ? ruler.offsetHeight : window.innerWidth; + size.h = (axis === 90) ? window.innerWidth : ruler.offsetHeight; + + document.documentElement.removeChild(ruler); + + ruler = null; + + if (Math.abs(window.orientation) !== 90) + { + return size.h; + } + else + { + return size.w; + } +}; + +module.exports = GetInnerHeight; + + +/***/ }), + +/***/ 45818: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(13560); + +/** + * Attempts to determine the screen orientation using the Orientation API. + * + * @function Phaser.DOM.GetScreenOrientation + * @since 3.16.0 + * + * @param {number} width - The width of the viewport. + * @param {number} height - The height of the viewport. + * + * @return {string} The orientation. + */ +var GetScreenOrientation = function (width, height) +{ + var screen = window.screen; + var orientation = (screen) ? screen.orientation || screen.mozOrientation || screen.msOrientation : false; + + if (orientation && typeof orientation.type === 'string') + { + // Screen Orientation API specification + return orientation.type; + } + else if (typeof orientation === 'string') + { + // moz / ms-orientation are strings + return orientation; + } + + if (typeof window.orientation === 'number') + { + // Do this check first, as iOS supports this, but also has an incomplete window.screen implementation + // This may change by device based on "natural" orientation. + return (window.orientation === 0 || window.orientation === 180) ? CONST.ORIENTATION.PORTRAIT : CONST.ORIENTATION.LANDSCAPE; + } + else if (window.matchMedia) + { + if (window.matchMedia('(orientation: portrait)').matches) + { + return CONST.ORIENTATION.PORTRAIT; + } + else if (window.matchMedia('(orientation: landscape)').matches) + { + return CONST.ORIENTATION.LANDSCAPE; + } + } + else + { + return (height > width) ? CONST.ORIENTATION.PORTRAIT : CONST.ORIENTATION.LANDSCAPE; + } +}; + +module.exports = GetScreenOrientation; + + +/***/ }), + +/***/ 74403: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Attempts to get the target DOM element based on the given value, which can be either + * a string, in which case it will be looked-up by ID, or an element node. If nothing + * can be found it will return a reference to the document.body. + * + * @function Phaser.DOM.GetTarget + * @since 3.16.0 + * + * @param {HTMLElement} element - The DOM element to look-up. + */ +var GetTarget = function (element) +{ + var target; + + if (element !== '') + { + if (typeof element === 'string') + { + // Hopefully an element ID + target = document.getElementById(element); + } + else if (element && element.nodeType === 1) + { + // Quick test for a HTMLElement + target = element; + } + } + + // Fallback to the document body. Covers an invalid ID and a non HTMLElement object. + if (!target) + { + // Use the full window + target = document.body; + } + + return target; +}; + +module.exports = GetTarget; + + +/***/ }), + +/***/ 56836: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes the given data string and parses it as XML. + * First tries to use the window.DOMParser and reverts to the Microsoft.XMLDOM if that fails. + * The parsed XML object is returned, or `null` if there was an error while parsing the data. + * + * @function Phaser.DOM.ParseXML + * @since 3.0.0 + * + * @param {string} data - The XML source stored in a string. + * + * @return {?(DOMParser|ActiveXObject)} The parsed XML data, or `null` if the data could not be parsed. + */ +var ParseXML = function (data) +{ + var xml = ''; + + try + { + if (window['DOMParser']) + { + var domparser = new DOMParser(); + xml = domparser.parseFromString(data, 'text/xml'); + } + else + { + xml = new ActiveXObject('Microsoft.XMLDOM'); + xml.loadXML(data); + } + } + catch (e) + { + xml = null; + } + + if (!xml || !xml.documentElement || xml.getElementsByTagName('parsererror').length) + { + return null; + } + else + { + return xml; + } +}; + +module.exports = ParseXML; + + +/***/ }), + +/***/ 35846: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Attempts to remove the element from its parentNode in the DOM. + * + * @function Phaser.DOM.RemoveFromDOM + * @since 3.0.0 + * + * @param {HTMLElement} element - The DOM element to remove from its parent node. + */ +var RemoveFromDOM = function (element) +{ + if (element.parentNode) + { + element.parentNode.removeChild(element); + } +}; + +module.exports = RemoveFromDOM; + + +/***/ }), + +/***/ 43092: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var NOOP = __webpack_require__(29747); + +/** + * @classdesc + * Abstracts away the use of RAF or setTimeOut for the core game update loop. + * + * This is invoked automatically by the Phaser.Game instance. + * + * @class RequestAnimationFrame + * @memberof Phaser.DOM + * @constructor + * @since 3.0.0 + */ +var RequestAnimationFrame = new Class({ + + initialize: + + function RequestAnimationFrame () + { + /** + * True if RequestAnimationFrame is running, otherwise false. + * + * @name Phaser.DOM.RequestAnimationFrame#isRunning + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isRunning = false; + + /** + * The callback to be invoked each step. + * + * @name Phaser.DOM.RequestAnimationFrame#callback + * @type {FrameRequestCallback} + * @since 3.0.0 + */ + this.callback = NOOP; + + /** + * True if the step is using setTimeout instead of RAF. + * + * @name Phaser.DOM.RequestAnimationFrame#isSetTimeOut + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isSetTimeOut = false; + + /** + * The setTimeout or RAF callback ID used when canceling them. + * + * @name Phaser.DOM.RequestAnimationFrame#timeOutID + * @type {?number} + * @default null + * @since 3.0.0 + */ + this.timeOutID = null; + + /** + * The delay rate in ms for setTimeOut. + * + * @name Phaser.DOM.RequestAnimationFrame#delay + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.delay = 0; + + var _this = this; + + /** + * The RAF step function. + * + * Invokes the callback and schedules another call to requestAnimationFrame. + * + * @name Phaser.DOM.RequestAnimationFrame#step + * @type {FrameRequestCallback} + * @since 3.0.0 + * + * @param {number} time - The timestamp passed in from RequestAnimationFrame. + */ + this.step = function step (time) + { + _this.callback(time); + + if (_this.isRunning) + { + _this.timeOutID = window.requestAnimationFrame(step); + } + }; + + /** + * The SetTimeout step function. + * + * Invokes the callback and schedules another call to setTimeout. + * + * @name Phaser.DOM.RequestAnimationFrame#stepTimeout + * @type {function} + * @since 3.0.0 + */ + this.stepTimeout = function stepTimeout () + { + if (_this.isRunning) + { + // Make the next request before the callback, so that timing is maintained + _this.timeOutID = window.setTimeout(stepTimeout, _this.delay); + } + + _this.callback(window.performance.now()); + }; + }, + + /** + * Starts the requestAnimationFrame or setTimeout process running. + * + * @method Phaser.DOM.RequestAnimationFrame#start + * @since 3.0.0 + * + * @param {FrameRequestCallback} callback - The callback to invoke each step. + * @param {boolean} forceSetTimeOut - Should it use SetTimeout, even if RAF is available? + * @param {number} delay - The setTimeout delay rate in ms. + */ + start: function (callback, forceSetTimeOut, delay) + { + if (this.isRunning) + { + return; + } + + this.callback = callback; + + this.isSetTimeOut = forceSetTimeOut; + + this.delay = delay; + + this.isRunning = true; + + this.timeOutID = (forceSetTimeOut) ? window.setTimeout(this.stepTimeout, 0) : window.requestAnimationFrame(this.step); + }, + + /** + * Stops the requestAnimationFrame or setTimeout from running. + * + * @method Phaser.DOM.RequestAnimationFrame#stop + * @since 3.0.0 + */ + stop: function () + { + this.isRunning = false; + + if (this.isSetTimeOut) + { + clearTimeout(this.timeOutID); + } + else + { + window.cancelAnimationFrame(this.timeOutID); + } + }, + + /** + * Stops the step from running and clears the callback reference. + * + * @method Phaser.DOM.RequestAnimationFrame#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.stop(); + + this.callback = NOOP; + } + +}); + +module.exports = RequestAnimationFrame; + + +/***/ }), + +/***/ 84902: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.DOM + */ + +var Dom = { + + AddToDOM: __webpack_require__(40366), + DOMContentLoaded: __webpack_require__(57264), + GetInnerHeight: __webpack_require__(57811), + GetScreenOrientation: __webpack_require__(45818), + GetTarget: __webpack_require__(74403), + ParseXML: __webpack_require__(56836), + RemoveFromDOM: __webpack_require__(35846), + RequestAnimationFrame: __webpack_require__(43092) + +}; + +module.exports = Dom; + + +/***/ }), + +/***/ 47565: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EE = __webpack_require__(50792); +var PluginCache = __webpack_require__(37277); + +/** + * @classdesc + * EventEmitter is a Scene Systems plugin compatible version of eventemitter3. + * + * @class EventEmitter + * @memberof Phaser.Events + * @constructor + * @since 3.0.0 + */ +var EventEmitter = new Class({ + + Extends: EE, + + initialize: + + function EventEmitter () + { + EE.call(this); + }, + + /** + * Removes all listeners. + * + * @method Phaser.Events.EventEmitter#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + this.removeAllListeners(); + }, + + /** + * Removes all listeners. + * + * @method Phaser.Events.EventEmitter#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.removeAllListeners(); + } + +}); + +/** + * Return an array listing the events for which the emitter has registered listeners. + * + * @method Phaser.Events.EventEmitter#eventNames + * @since 3.0.0 + * + * @return {Array.} + */ + +/** + * Return the listeners registered for a given event. + * + * @method Phaser.Events.EventEmitter#listeners + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * + * @return {Function[]} The registered listeners. + */ + +/** + * Return the number of listeners listening to a given event. + * + * @method Phaser.Events.EventEmitter#listenerCount + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * + * @return {number} The number of listeners. + */ + +/** + * Calls each of the listeners registered for a given event. + * + * @method Phaser.Events.EventEmitter#emit + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * @param {...*} [args] - Additional arguments that will be passed to the event handler. + * + * @return {boolean} `true` if the event had listeners, else `false`. + */ + +/** + * Add a listener for a given event. + * + * @method Phaser.Events.EventEmitter#on + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} fn - The listener function. + * @param {*} [context=this] - The context to invoke the listener with. + * + * @return {this} `this`. + */ + +/** + * Add a listener for a given event. + * + * @method Phaser.Events.EventEmitter#addListener + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} fn - The listener function. + * @param {*} [context=this] - The context to invoke the listener with. + * + * @return {this} `this`. + */ + +/** + * Add a one-time listener for a given event. + * + * @method Phaser.Events.EventEmitter#once + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} fn - The listener function. + * @param {*} [context=this] - The context to invoke the listener with. + * + * @return {this} `this`. + */ + +/** + * Remove the listeners of a given event. + * + * @method Phaser.Events.EventEmitter#removeListener + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} [fn] - Only remove the listeners that match this function. + * @param {*} [context] - Only remove the listeners that have this context. + * @param {boolean} [once] - Only remove one-time listeners. + * + * @return {this} `this`. + */ + +/** + * Remove the listeners of a given event. + * + * @method Phaser.Events.EventEmitter#off + * @since 3.0.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} [fn] - Only remove the listeners that match this function. + * @param {*} [context] - Only remove the listeners that have this context. + * @param {boolean} [once] - Only remove one-time listeners. + * + * @return {this} `this`. + */ + +/** + * Remove all listeners, or those of the specified event. + * + * @method Phaser.Events.EventEmitter#removeAllListeners + * @since 3.0.0 + * + * @param {(string|symbol)} [event] - The event name. + * + * @return {this} `this`. + */ + +PluginCache.register('EventEmitter', EventEmitter, 'events'); + +module.exports = EventEmitter; + + +/***/ }), + +/***/ 93055: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Events + */ + +module.exports = { EventEmitter: __webpack_require__(47565) }; + + +/***/ }), + +/***/ 10189: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Barrel Filter Controller. + * + * This filter controller manages the barrel distortion effect for a Camera. + * A barrel effect allows you to apply either a 'pinch' or 'expand' distortion to + * the view. The amount of the effect can be modified in real-time. + * + * A Barrel effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addBarrel(); + * camera.filters.external.addBarrel(); + * ``` + * + * @class Barrel + * @extends Phaser.Filters.Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that owns this filter. + * @param {number} [amount=1] - The amount of distortion applied to the barrel effect. A value of 1 is no distortion. Typically keep this within +- 1. + */ +var Barrel = new Class({ + Extends: Controller, + + initialize: function Barrel (camera, amount) + { + if (amount === undefined) { amount = 1; } + + Controller.call(this, camera, 'FilterBarrel'); + + /** + * The amount of distortion applied to the barrel effect. + * + * Typically keep this within the range 1 (no distortion) to +- 1. + * + * @name Phaser.Filters.Barrel#amount + * @type {number} + * @since 4.0.0 + */ + this.amount = amount; + } +}); + +module.exports = Barrel; + + +/***/ }), + +/***/ 16762: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Blend Filter Controller. + * + * This filter controller manages the blend effect for a Camera. + * A blend effect allows you to apply another texture to the view + * using a specific blend mode. + * This supports blend modes not otherwise available in WebGL. + * + * A Blend effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * camera.filters.internal.addBlend(); + * camera.filters.external.addBlend(); + * ``` + * + * @class Blend + * @extends Phaser.Filters.Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that owns this filter. + * @param {Phaser.Textures.Texture} [texture='__WHITE'] - The texture to apply to the view. + * @param {Phaser.BlendModes} [blendMode=Phaser.BlendModes.NORMAL] - The blend mode to apply to the view. + * @param {number} [amount=1] - The amount of the blend effect to apply to the view. At 0, the original image is preserved. At 1, the blend texture is fully applied. The expected range is 0 to 1, but you can go outside that range for different effects. + * @param {number[]} [color=[1, 1, 1, 1]] - The color to apply to the blend texture. Each value corresponds to a color channel in RGBA. The expected range is 0 to 1, but you can go outside that range for different effects. + */ +var Blend = new Class({ + Extends: Controller, + + initialize: function Blend (camera, texture, blendMode, amount, color) + { + if (texture === undefined) { texture = '__WHITE'; } + if (blendMode === undefined) { blendMode = 0; } + if (amount === undefined) { amount = 1; } + if (color === undefined) { color = [ 1, 1, 1, 1 ]; } + + Controller.call(this, camera, 'FilterBlend'); + + /** + * The underlying texture used for the mask. + * + * @name Phaser.Filters.Blend#glTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @since 4.0.0 + */ + this.glTexture; + + /** + * The blend mode to apply to the view. + * This supports blend modes not otherwise available in WebGL. + * + * @name Phaser.Filters.Blend#blendMode + * @type {Phaser.BlendModes} + * @since 4.0.0 + * @default Phaser.BlendModes.NORMAL + */ + this.blendMode = blendMode; + + /** + * The amount of the blend effect to apply to the view. + * At 0, the original image is preserved. At 1, the blend texture is fully applied. + * + * @name Phaser.Filters.Blend#amount + * @type {number} + * @since 4.0.0 + * @default 1 + */ + this.amount = amount; + + /** + * The color to apply to the blend texture. + * Each value corresponds to a color channel in RGBA. + * The expected range is 0 to 1, but you can go outside that range for different effects. + * + * @name Phaser.Filters.Blend#color + * @type {number[]} + * @since 4.0.0 + * @default [1, 1, 1, 1] + */ + this.color = color; + + this.setTexture(texture); + }, + + /** + * Sets the texture used for the blend. + * + * @method Phaser.Filters.Blend#setTexture + * @since 4.0.0 + * @param {string} [texture='__WHITE'] - The unique string-based key of the texture to use for displacement, which must exist in the Texture Manager. + * @returns {this} This Filter Controller. + */ + setTexture: function (texture) + { + var phaserTexture = this.camera.scene.sys.textures.getFrame(texture); + + if (phaserTexture) + { + this.glTexture = phaserTexture.glTexture; + } + + return this; + } +}); + +module.exports = Blend; + + +/***/ }), + +/***/ 88344: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Blur Filter Controller. + * + * This filter controller manages a blur effect. + * + * A Gaussian blur is the result of blurring an image by a Gaussian function. It is a widely used effect, + * typically to reduce image noise and reduce detail. The visual effect of this blurring technique is a + * smooth blur resembling that of viewing the image through a translucent screen, distinctly different + * from the bokeh effect produced by an out-of-focus lens or the shadow of an object under usual illumination. + * + * A Blur effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addBlur(); + * camera.filters.external.addBlur(); + * ``` + * + * @class Blur + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @extends Phaser.Filters.Controller + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {number} [quality=0] - The quality of the blur effect. Can be either 0 for Low Quality, 1 for Medium Quality or 2 for High Quality. + * @param {number} [x=2] - The horizontal offset of the blur effect. + * @param {number} [y=2] - The vertical offset of the blur effect. + * @param {number} [strength=1] - The strength of the blur effect. + * @param {number} [color=0xffffff] - The color of the blur, as a hex value. + * @param {number} [steps=4] - The number of steps to run the blur effect for. This value should always be an integer. + */ +var Blur = new Class({ + Extends: Controller, + + initialize: function Blur (camera, quality, x, y, strength, color, steps) + { + if (quality === undefined) { quality = 0; } + if (x === undefined) { x = 2; } + if (y === undefined) { y = 2; } + if (strength === undefined) { strength = 1; } + if (steps === undefined) { steps = 4; } + + Controller.call(this, camera, 'FilterBlur'); + + /** + * The quality of the blur effect. + * + * This can be: + * + * 0 for Low Quality + * 1 for Medium Quality + * 2 for High Quality + * + * The higher the quality, the more complex shader is used + * and the more processing time is spent on the GPU calculating + * the final blur. This value is used in conjunction with the + * `steps` value, as one has a direct impact on the other. + * + * Keep this value as low as you can, while still achieving the + * desired effect you need for your game. + * + * @name Phaser.Filters.Blur#quality + * @type {number} + * @default 0 + * @since 4.0.0 + */ + this.quality = quality; + + /** + * The horizontal offset of the blur effect. + * + * @name Phaser.Filters.Blur#x + * @type {number} + * @default 2 + * @since 4.0.0 + */ + this.x = x; + + /** + * The vertical offset of the blur effect. + * + * @name Phaser.Filters.Blur#y + * @type {number} + * @default 2 + * @since 4.0.0 + */ + this.y = y; + + /** + * The strength of the blur effect. + * + * @name Phaser.Filters.Blur#strength + * @type {number} + * @default 1 + * @since 4.0.0 + */ + this.strength = strength; + + /** + * The internal gl color array. + * + * @name Phaser.Filters.Blur#glcolor + * @type {number[]} + * @since 4.0.0 + */ + this.glcolor = [ 1, 1, 1 ]; + + if (color !== undefined && color !== null) + { + this.color = color; + } + + /** + * The number of steps to run the Blur effect for. + * + * This value should always be an integer. + * + * The higher the value, the smoother the blur, + * but at the cost of exponentially more gl operations. + * + * Keep this to the lowest possible number you can have it, while + * still looking correct for your game. + * + * @name Phaser.Filters.Blur#steps + * @type {number} + * @default 4 + * @since 4.0.0 + */ + this.steps = steps; + }, + + /** + * The color of the blur as a number value. + * + * @name Phaser.Filters.Blur#color + * @type {number} + * @since 4.0.0 + */ + color: { + + get: function () + { + var color = this.glcolor; + + return (((color[0] * 255) << 16) + ((color[1] * 255) << 8) + (color[2] * 255 | 0)); + }, + + set: function (value) + { + var color = this.glcolor; + + color[0] = ((value >> 16) & 0xFF) / 255; + color[1] = ((value >> 8) & 0xFF) / 255; + color[2] = (value & 0xFF) / 255; + } + + }, + + getPadding: function () + { + var override = this.paddingOverride; + if (override) + { + this.currentPadding.setTo(override.x, override.y, override.width, override.height); + return override; + } + + var quality = this.quality; + var offsetConstant = quality === 0 ? 1.333 + : quality === 1 ? 3.2307692308 + : 5.176470588235294; + var offset = this.steps * this.strength * offsetConstant; + var x = Math.ceil(this.x * offset); + var y = Math.ceil(this.y * offset); + + this.currentPadding.setTo(-x, -y, x * 2, y * 2); + + return this.currentPadding; + } +}); + +module.exports = Blur; + + +/***/ }), + +/***/ 47564: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Bokeh Filter Controller. + * + * This filter controller manages the bokeh effect for a Camera. + * + * Bokeh refers to a visual effect that mimics the photographic technique of creating a shallow depth of field. + * This effect is used to emphasize the game's main subject or action, by blurring the background or foreground + * elements, resulting in a more immersive and visually appealing experience. It is achieved through rendering + * techniques that simulate the out-of-focus areas, giving a sense of depth and realism to the game's graphics. + * + * This effect can also be used to generate a Tilt Shift effect, which is a technique used to create a miniature + * effect by blurring everything except a small area of the image. This effect is achieved by blurring the + * top and bottom elements, while keeping the center area in focus. + * + * A Bokeh effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addBokeh(); + * camera.filters.external.addBokeh(); + * ``` + * + * @class Bokeh + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @extends Phaser.Filters.Controller + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {number} [radius=0.5] - The radius of the bokeh effect. + * @param {number} [amount=1] - The amount of the bokeh effect. + * @param {number} [contrast=0.2] - The color contrast of the bokeh effect. + * @param {boolean} [isTiltShift=false] - Is this a bokeh or Tile Shift effect? + * @param {number} [blurX=1] - If Tilt Shift, the amount of horizontal blur. + * @param {number} [blurY=1] - If Tilt Shift, the amount of vertical blur. + * @param {number} [strength=1] - If Tilt Shift, the strength of the blur. + * */ +var Bokeh = new Class({ + + Extends: Controller, + + initialize: function Bokeh (camera, radius, amount, contrast, isTiltShift, blurX, blurY, strength) + { + if (radius === undefined) { radius = 0.5; } + if (amount === undefined) { amount = 1; } + if (contrast === undefined) { contrast = 0.2; } + if (isTiltShift === undefined) { isTiltShift = false; } + if (blurX === undefined) { blurX = 1; } + if (blurY === undefined) { blurY = 1; } + if (strength === undefined) { strength = 1; } + + Controller.call(this, camera, 'FilterBokeh'); + + /** + * The radius of the bokeh effect. + * + * This is a float value, where a radius of 0 will result in no effect being applied, + * and a radius of 1 will result in a strong bokeh. However, you can exceed this value + * for even stronger effects. + * + * @name Phaser.Filters.Bokeh#radius + * @type {number} + * @default 0.5 + * @since 4.0.0 + */ + this.radius = radius; + + /** + * The amount, or strength, of the bokeh effect. + * + * @name Phaser.Filters.Bokeh#amount + * @type {number} + * @default 1 + * @since 4.0.0 + */ + this.amount = amount; + + /** + * The color contrast, or brightness, of the bokeh effect. + * + * @name Phaser.Filters.Bokeh#contrast + * @type {number} + * @default 0.2 + * @since 4.0.0 + */ + this.contrast = contrast; + + /** + * Is this a Tilt Shift effect or a standard bokeh effect? + * + * @name Phaser.Filters.Bokeh#isTiltShift + * @type {boolean} + * @since 4.0.0 + */ + this.isTiltShift = isTiltShift; + + /** + * If a Tilt Shift effect this controls the amount of horizontal blur. + * + * Setting this value on a non-Tilt Shift effect will have no effect. + * + * @name Phaser.Filters.Bokeh#blurX + * @type {number} + * @default 1 + * @since 4.0.0 + */ + this.blurX = blurX; + + /** + * If a Tilt Shift effect this controls the amount of vertical blur. + * + * Setting this value on a non-Tilt Shift effect will have no effect. + * + * @name Phaser.Filters.Bokeh#blurY + * @type {number} + * @default 1 + * @since 4.0.0 + */ + this.blurY = blurY; + + /** + * If a Tilt Shift effect this controls the strength of the blur. + * + * Setting this value on a non-Tilt Shift effect will have no effect. + * + * @name Phaser.Filters.Bokeh#strength + * @type {number} + * @default 1 + * @since 4.0.0 + */ + this.strength = strength; + }, + + getPadding: function () + { + var override = this.paddingOverride; + if (override) + { + this.currentPadding.setTo(override.x, override.y, override.width, override.height); + return override; + } + + /* + The padding is calculated based on the camera height and the radius of the bokeh effect. + The constant value is derived from the shader. + The shader samples based on a complicated formula, + but it is based on camera height and radius, + multiplied by various constants including 0.025 and 0.06, + and an iteration which sums to 14.284061040284603 after 100 iterations. + Together, these multiply to the constant 0.021426096060426905. + This is the maximum padding required for the bokeh effect. + */ + + var padding = Math.ceil(this.camera.height * this.radius * 0.021426096060426905); + + this.currentPadding.setTo(-padding, -padding, padding * 2, padding * 2); + + return this.currentPadding; + } +}); + +module.exports = Bokeh; + + +/***/ }), + +/***/ 77011: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); +var DisplayColorMatrix = __webpack_require__(89422); + +/** + * @classdesc + * The ColorMatrix Filter Controller. + * + * This filter controller manages the color matrix effect for a Camera. + * + * The color matrix effect is a visual technique that involves manipulating the colors of an image + * or scene using a mathematical matrix. This process can adjust hue, saturation, brightness, and contrast, + * allowing developers to create various stylistic appearances or mood settings within the game. + * Common applications include simulating different lighting conditions, applying color filters, + * or achieving a specific visual style. + * + * A ColorMatrix effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * const cmFilter = camera.filters.internal.addColorMatrix(); + * camera.filters.external.addColorMatrix(); + * + * // To set the matrix values: + * cmFilter.colorMatrix.sepia(); + * ``` + * + * @class ColorMatrix + * @extends Phaser.Filters.Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that owns this filter. + */ +var ColorMatrix = new Class({ + Extends: Controller, + + initialize: function ColorMatrix (camera) + { + Controller.call(this, camera, 'FilterColorMatrix'); + + /** + * The color matrix for this effect. + * This is where the color values are managed and set. + * + * @name Phaser.Filters.ColorMatrix#colorMatrix + * @type {Phaser.Display.ColorMatrix} + * @since 4.0.0 + */ + this.colorMatrix = new DisplayColorMatrix(); + }, + + destroy: function () + { + this.colorMatrix = null; + + Controller.prototype.destroy.call(this); + } +}); + +module.exports = ColorMatrix; + + +/***/ }), + +/***/ 13045: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Rectangle = __webpack_require__(87841); + +/** + * @classdesc + * The Controller for a filter effect. + * + * You should not normally create an instance of this class directly, but instead use one of the built-in filters that extend it. + * + * You should not use a Controller for more than one Camera. + * Create a new instance for each Camera that you wish to apply the filter to. + * If you share Controllers, and destroy one owner, the Controller will be destroyed. + * + * @class Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {string} renderNode - The ID of the RenderNode that this filter uses. + */ +var Controller = new Class({ + initialize: function Controller (camera, renderNode) + { + /** + * Toggle this boolean to enable or disable this filter, + * without removing and adding it from the Game Object. + * + * @name Phaser.Filters.Controller#active + * @type {boolean} + * @since 4.0.0 + */ + this.active = true; + + /** + * A reference to the Camera that owns this filter. + * + * @name Phaser.Filters.Controller#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 4.0.0 + */ + this.camera = camera; + + /** + * The ID of the RenderNode that this filter uses. + * + * @name Phaser.Filters.Controller#renderNode + * @type {string} + * @since 4.0.0 + */ + this.renderNode = renderNode; + + /** + * Padding override. This is on by default. If this is set, + * the filter will use this padding instead of calculating it. + * Prefer using `setPaddingOverride` instead of modifying this directly. + * + * @name Phaser.Filters.Controller#paddingOverride + * @type {Phaser.Geom.Rectangle} + * @since 4.0.0 + */ + this.paddingOverride = new Rectangle(); + + /** + * The padding currently being used by this filter. + * This is set and used during rendering using `getPadding`. + * It is necessary for filters being used in an external list. + * You should not modify this value directly. + * + * @name Phaser.Filters.Controller#currentPadding + * @type {Phaser.Geom.Rectangle} + * @since 4.0.0 + */ + this.currentPadding = new Rectangle(); + + /** + * If `true`, this filter will be permitted to draw to the base texture. + * This can be unwanted if, for example, the filter doesn't actually + * draw anything. + * + * This is an internal flag used by the renderer. + * You should not modify this value directly. + * + * @name Phaser.Filters.Controller#allowBaseDraw + * @type {boolean} + * @since 4.0.0 + * @default true + * @readonly + */ + this.allowBaseDraw = true; + + /** + * Whether this filter controller will be destroyed when the FilterList + * that owns it is destroyed. If you enable this, you must ensure that + * you clean up the filter controller at an appropriate time. + * This allows you to reuse a controller for multiple objects; + * this is not recommended unless you know what you're doing. + * It tends to work best with external filters. + * + * @name Phaser.Filters.Controller#ignoreDestroy + * @type {boolean} + * @since 4.0.0 + * @default false + */ + this.ignoreDestroy = false; + }, + + /** + * Returns the padding required for this filter, + * and sets `currentPadding` to the result. + * Most filters don't need extra padding, + * but some might sample beyond the texture size, such as a blur. + * + * The bounds are encoded as a Rectangle. + * To enlarge the bounds, the top and left values should be negative, + * and the bottom and right values should be positive. + * + * @method Phaser.Filters.Controller#getPadding + * @since 4.0.0 + * @returns {Phaser.Geom.Rectangle} The padding required by this filter. + */ + getPadding: function () + { + return this.paddingOverride || this.currentPadding; + }, + + /** + * Sets the padding override. + * If this is set, the filter will use this padding instead of calculating them. + *it Call `setPaddingOverride(null)` to clear the override. + * Call `setPaddingOverride()` to set the padding to 0. + * + * @method Phaser.Filters.Controller#setPaddingOverride + * @since 4.0.0 + * @param {number|null} [left=0] - The top padding. + * @param {number} [top=0] - The top padding. + * @param {number} [right=0] - The right padding. + * @param {number} [bottom=0] - The bottom padding. + */ + setPaddingOverride: function (left, top, right, bottom) + { + if (left === null) + { + this.paddingOverride = null; + return this; + } + + if (left === undefined) { left = 0; } + if (top === undefined) { top = 0; } + if (right === undefined) { right = 0; } + if (bottom === undefined) { bottom = 0; } + + this.paddingOverride = new Rectangle(left, top, right - left, bottom - top); + + return this; + }, + + /** + * Sets the active state of this filter. + * + * A disabled filter will not be used. + * + * @method Phaser.Filters.Controller#setActive + * @since 4.0.0 + * @param {boolean} value - `true` to enable this filter, or `false` to disable it. + * @returns {this} This filter instance. + */ + setActive: function (value) + { + this.active = value; + + return this; + }, + + /** + * Destroys this Controller and nulls any references it holds. + * + * @method Phaser.Filters.Controller#destroy + * @since 4.0.0 + */ + destroy: function () + { + this.active = false; + this.renderNode = null; + this.camera = null; + } +}); + +module.exports = Controller; + + +/***/ }), + +/***/ 16898: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Displacement Filter Controller. + * + * This Filter controller manages the displacement effect. + * + * The displacement effect is a visual technique that alters the position of pixels in an image + * or texture based on the values of a displacement map. This effect is used to create the illusion + * of depth, surface irregularities, or distortion in otherwise flat elements. It can be applied to + * characters, objects, or backgrounds to enhance realism, convey movement, or achieve various + * stylistic appearances. + * + * A Displacement effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addDisplacement(); + * camera.filters.external.addDisplacement(); + * ``` + * + * @class Displacement + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @extends Phaser.Filters.Controller + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {string} [texture='__WHITE'] - The unique string-based key of the texture to use for displacement, which must exist in the Texture Manager. + * @param {number} [x=0.005] - The amount of horizontal displacement to apply. A very small float number, such as 0.005. + * @param {number} [y=0.005] - The amount of vertical displacement to apply. A very small float number, such as 0.005. + */ +var Displacement = new Class({ + Extends: Controller, + + initialize: function Displacement (camera, texture, x, y) + { + if (texture === undefined) { texture = '__WHITE'; } + if (x === undefined) { x = 0.005; } + if (y === undefined) { y = 0.005; } + + Controller.call(this, camera, 'FilterDisplacement'); + + /** + * The amount of horizontal displacement to apply. + * The maximum horizontal displacement in pixels is `x` + * multiplied by 0.5 times the width of the camera rendering the filter. + * + * @name Phaser.Filters.Displacement#x + * @type {number} + * @since 4.0.0 + * @default 0.005 + */ + this.x = x; + + /** + * The amount of vertical displacement to apply. + * The maximum vertical displacement in pixels is `y` + * multiplied by 0.5 times the height of the camera rendering the filter. + * + * @name Phaser.Filters.Displacement#y + * @type {number} + * @since 4.0.0 + * @default 0.005 + */ + this.y = y; + + /** + * The underlying texture used for displacement. + * + * @name Phaser.Filters.Displacement#texture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @since 4.0.0 + */ + this.glTexture; + + this.setTexture(texture); + }, + + /** + * Sets the Texture to be used for the displacement effect. + * + * You can only use a whole texture, not a frame from a texture atlas or sprite sheet. + * + * @method Phaser.Filters.Displacement#setTexture + * @since 4.0.0 + * @param {string} [texture='__WHITE'] - The unique string-based key of the texture to use for displacement, which must exist in the Texture Manager. + * @returns {this} This Filter Controller. + */ + setTexture: function (texture) + { + var phaserTexture = this.camera.scene.sys.textures.getFrame(texture); + + if (phaserTexture) + { + this.glTexture = phaserTexture.glTexture; + } + + return this; + }, + + getPadding: function () + { + var override = this.paddingOverride; + if (override) + { + this.currentPadding.setTo(override.x, override.y, override.width, override.height); + return override; + } + + var camera = this.camera; + var x = Math.ceil(camera.width * this.x * 0.5); + var y = Math.ceil(camera.height * this.y * 0.5); + + this.currentPadding.setTo(-x, -y, x * 2, y * 2); + + return this.currentPadding; + } +}); + +module.exports = Displacement; + + +/***/ }), + +/***/ 42652: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Glow Filter controller. + * + * This filter controller manages the glow effect for a Camera. + * + * The glow effect is a visual technique that creates a soft, luminous halo around game objects, + * characters, or UI elements. This effect is used to emphasize importance, enhance visual appeal, + * or convey a sense of energy, magic, or otherworldly presence. The effect can also be set on + * the inside of edges. The color and strength of the glow can be modified. + * + * A Glow effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addGlow(); + * camera.filters.external.addGlow(); + * ``` + * + * Conversion note from Phaser 3: + * - The shader now uses stochastic sampling instead of sampling along straight lines. This improves quality, especially around corners. + * - `scale` has been added to the parameter list, before `knockout`. + * - `quality` is no longer a fraction, but an integer value. The default has changed from 0.1 to 10. This is not a linear conversion, because of the quality improvement. Judge the quality by eye and adjust the value accordingly. + * + * @class Glow + * @extends Phaser.Filters.Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that owns this filter. + * @param {number} [color=0xffffff] - The color of the glow effect as a number value. + * @param {number} [outerStrength=4] - The strength of the glow outward from the edge of textures. + * @param {number} [innerStrength=0] - The strength of the glow inward from the edge of textures. + * @param {number} [scale=1] - The scale of the glow effect. This multiplies the fixed distance. + * @param {boolean} [knockout=false] - If `true` only the glow is drawn, not the texture itself. + * @param {number} [quality=10] - The quality of the glow effect. This cannot be changed after the filter has been created. + * @param {number} [distance=10] - The distance of the glow effect. This cannot be changed after the filter has been created. + */ +var Glow = new Class({ + Extends: Controller, + + initialize: function Glow (camera, color, outerStrength, innerStrength, scale, knockout, quality, distance) + { + if (outerStrength === undefined) { outerStrength = 4; } + if (innerStrength === undefined) { innerStrength = 0; } + if (scale === undefined) { scale = 1; } + if (knockout === undefined) { knockout = false; } + if (quality === undefined) { quality = camera.scene.sys.game.config.glowQuality; } + if (distance === undefined) { distance = camera.scene.sys.game.config.glowDistance; } + + Controller.call(this, camera, 'FilterGlow'); + + /** + * The strength of the glow outward from the edge of textures. + * + * @name Phaser.Filters.Glow#outerStrength + * @type {number} + * @since 4.0.0 + * @default 4 + */ + this.outerStrength = outerStrength; + + /** + * The strength of the glow inward from the edge of textures. + * + * @name Phaser.Filters.Glow#innerStrength + * @type {number} + * @since 4.0.0 + * @default 0 + */ + this.innerStrength = innerStrength; + + /** + * The scale of the glow effect. This multiplies the fixed distance. + * + * @name Phaser.Filters.Glow#scale + * @type {number} + * @since 4.0.0 + * @default 1 + */ + this.scale = scale; + + /** + * If `true` only the glow is drawn, not the texture itself. + * + * @name Phaser.Filters.Glow#knockout + * @type {number} + * @since 4.0.0 + * @default false + */ + this.knockout = knockout; + + /** + * The quality of the glow effect. + * This cannot be changed after the filter has been created. + * This controls the number of samples that the glow effect will run for. + * A higher number is higher quality, but slower to process. + * Integer values only. + * + * @name Phaser.Filters.Glow#quality + * @type {number} + * @since 4.0.0 + * @default 10 + * @private + * @readonly + */ + this._quality = Math.max(Math.round(quality), 1); + + /** + * The distance of the glow effect. + * This cannot be changed after the filter has been created. + * This controls the distance of the glow effect, in pixels. + * Integer values only. + * + * @name Phaser.Filters.Glow#distance + * @type {number} + * @since 4.0.0 + * @default 10 + * @private + * @readonly + */ + this._distance = Math.max(Math.round(distance), 1); + + /** + * A 4 element array of gl color values. + * + * @name Phaser.Filters.Glow#glcolor + * @type {number[]} + * @since 4.0.0 + */ + this.glcolor = [ 1, 1, 1, 1 ]; + + if (color !== undefined) + { + this.color = color; + } + }, + + /** + * The color of the glow as a number value. + * + * @name Phaser.Filters.Glow#color + * @type {number} + * @since 4.0.0 + */ + color: { + + get: function () + { + var color = this.glcolor; + + return (((color[0] * 255) << 16) + ((color[1] * 255) << 8) + (color[2] * 255 | 0)); + }, + + set: function (value) + { + var color = this.glcolor; + + color[0] = ((value >> 16) & 0xFF) / 255; + color[1] = ((value >> 8) & 0xFF) / 255; + color[2] = (value & 0xFF) / 255; + } + + }, + + /** + * The distance of the glow effect. + * This cannot be changed after the filter has been created. + * This controls the distance of the glow effect, in pixels. + * Integer values only. + * + * @name Phaser.Filters.Glow#distance + * @type {number} + * @since 4.0.0 + * @readonly + */ + distance: { + + get: function () + { + return this._distance; + } + + }, + + /** + * The quality of the glow effect. + * This cannot be changed after the filter has been created. + * This controls the number of samples that the glow effect will run for. + * A higher number is higher quality, but slower to process. + * Integer values only. + * + * @name Phaser.Filters.Glow#quality + * @type {number} + * @since 4.0.0 + * @readonly + */ + quality: { + + get: function () + { + return this._quality; + } + }, + + getPadding: function () + { + var override = this.paddingOverride; + if (override) + { + this.currentPadding.setTo(override.x, override.y, override.width, override.height); + return override; + } + + var padding = this.currentPadding; + var distance = Math.ceil(this.distance * this.scale); + + padding.left = -distance; + padding.top = -distance; + padding.right = distance; + padding.bottom = distance; + + return padding; + } +}); + +module.exports = Glow; + + +/***/ }), + +/***/ 97797: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var UUID = __webpack_require__(45650); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Mask Filter Controller. + * + * This filter controller manages a mask effect. + * + * A mask uses a texture to hide parts of an input. + * It multiplies the color and alpha of the input + * by the alpha of the mask in the corresponding texel. + * + * Masks can be inverted, which switches what they hide and what they show. + * + * Masks can use either a texture or a GameObject. + * If a GameObject is used, the mask will render the GameObject + * to a DynamicTexture and use that. + * The mask will automatically update when the GameObject changes, + * unless the `autoUpdate` flag is set to `false`. + * + * When the mask filter is used as an internal filter, + * the mask will match the object/view being filtered. + * This is useful for creating effects that follow the object, + * such as effects intended to match an animated sprite. + * + * When the mask filter is used as an external filter, + * the mask will match the context of the camera. + * This is useful for creating effects that cover the entire view. + * + * An optional `viewCamera` can be specified when creating the mask. + * If not used, mask objects will be viewed through the current camera, + * or through a default camera if no other option is set. + * For example, when rendering to a DynamicTexture outside the normal rendering + * flow. + * + * A Mask effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * const texture = 'MyMask'; + * + * camera.filters.internal.addMask(texture); + * camera.filters.external.addMask(texture, true, myCamera); + * ``` + * + * @class Mask + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @extends Phaser.Filters.Controller + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {string|Phaser.GameObjects.GameObject} [mask='__WHITE'] - The source of the mask. This can be a unique string-based key of the texture to use for the mask, which must exist in the Texture Manager. Or it can be a GameObject, in which case the mask will render the GameObject to a DynamicTexture and use that. + * @param {boolean} [invert=false] - Whether to invert the mask. + * @param {Phaser.Cameras.Scene2D.Camera} [viewCamera] - The Camera to use when rendering the mask with a GameObject. If not specified, uses the scene's `main` camera. + * @param {'local'|'world'} [viewTransform='world'] - The transform to use when rendering the mask with a GameObject. 'local' uses the GameObject's own properties. 'world' uses the GameObject's `parentContainer` value to compute a world position. + */ +var Mask = new Class({ + Extends: Controller, + + initialize: function Mask (camera, mask, invert, viewCamera, viewTransform) + { + if (mask === undefined) { mask = '__WHITE'; } + if (invert === undefined) { invert = false; } + + Controller.call(this, camera, 'FilterMask'); + + /** + * The underlying texture used for the mask. + * + * @name Phaser.Filters.Mask#glTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @since 4.0.0 + */ + this.glTexture; + + /** + * The dynamic texture used for the mask. + * This is only set if the mask is a GameObject. + * + * @name Phaser.Filters.Mask#_dynamicTexture + * @type {Phaser.Textures.DynamicTexture} + * @private + * @since 4.0.0 + * @default null + */ + this._dynamicTexture = null; + + /** + * The GameObject used for the mask. + * This is only set if the mask is a GameObject. + * + * @name Phaser.Filters.Mask#maskGameObject + * @type {Phaser.GameObjects.GameObject} + * @since 4.0.0 + * @default null + */ + this.maskGameObject = null; + + /** + * Whether to invert the mask. + * An inverted mask switches what it hides and what it shows. + * + * @name Phaser.Filters.Mask#invert + * @type {boolean} + * @since 4.0.0 + * @default false + */ + this.invert = invert; + + /** + * Whether the mask should automatically update. + * This only applies when the mask is a GameObject. + * If `false`, the mask will not change even if the GameObject changes. + * + * @name Phaser.Filters.Mask#autoUpdate + * @type {boolean} + * @since 4.0.0 + * @default true + */ + this.autoUpdate = true; + + /** + * Whether the mask needs updating, once. + * This only applies when the mask is a GameObject. + * If `true`, the mask will be updated before the next render. + * This is automatically set to `true` when the mask is a GameObject, + * but it turns off after the mask is updated. + * + * @name Phaser.Filters.Mask#needsUpdate + * @type {boolean} + * @since 4.0.0 + * @default false + */ + this.needsUpdate = false; + + /** + * The transform type to use when rendering the mask with a GameObject. + * 'local' uses the GameObject's own properties. + * 'world' uses the GameObject's `parentContainer` value to compute a world position. + * This only applies when the mask is a GameObject. + * + * @name Phaser.Filters.Mask#viewTransform + * @type {'local'|'world'} + * @since 4.0.0 + * @default 'world' + */ + this.viewTransform = viewTransform || 'world'; + + /** + * The Camera to use when rendering the mask. + * If not specified, uses the currently rendering camera, + * or failing that, an internal Camera. + * + * @name Phaser.Filters.Mask#viewCamera + * @type {?Phaser.Cameras.Scene2D.Camera} + * @since 4.0.0 + */ + this.viewCamera = viewCamera; + + if (typeof mask === 'string') + { + this.setTexture(mask); + } + else + { + this.setGameObject(mask); + } + }, + + /** + * Updates the DynamicTexture for the mask. + * The DynamicTexture is created or resized if necessary. + * This is called automatically during rendering + * when the mask is a GameObject + * and the `needsUpdate` or `autoUpdate` flags are set. + * It should not be called directly. + * + * @method Phaser.Filters.Mask#updateDynamicTexture + * @since 4.0.0 + * @param {number} width - The width of the DynamicTexture. + * @param {number} height - The height of the DynamicTexture + */ + updateDynamicTexture: function (width, height) + { + var gameObject = this.maskGameObject; + + if (!gameObject) + { + return; + } + + if (!this._dynamicTexture) + { + var textureManager = this.camera.scene.sys.textures; + this._dynamicTexture = textureManager.addDynamicTexture(UUID(), width, height); + } + else if (this._dynamicTexture.width !== width || this._dynamicTexture.height !== height) + { + this._dynamicTexture.setSize(width, height); + } + else + { + this._dynamicTexture.clear(); + } + + this.glTexture = this._dynamicTexture.get().glTexture; + + var camera = this.viewCamera || gameObject.scene.renderer.currentViewCamera; + + // Draw the GameObject to the DynamicTexture. + this._dynamicTexture.capture(gameObject, { transform: this.viewTransform, camera: camera }); + this._dynamicTexture.render(); + + this.needsUpdate = false; + }, + + /** + * Sets the GameObject used for the mask. + * + * @method Phaser.Filters.Mask#setGameObject + * @since 4.0.0 + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject to use for the mask. + * @returns {this} This Filter Controller. + */ + setGameObject: function (gameObject) + { + this.maskGameObject = gameObject; + this.needsUpdate = true; + + // `_dynamicTexture` will be generated at render time, + // using the camera of the current context. + // The camera which owns this filter is only the correct camera + // if this filter is being used as an internal filter. + + return this; + }, + + /** + * Sets the texture used for the mask. + * + * @method Phaser.Filters.Mask#setTexture + * @since 4.0.0 + * @param {string} [texture='__WHITE'] - The unique string-based key of the texture to use for displacement, which must exist in the Texture Manager. + * @returns {this} This Filter Controller. + */ + setTexture: function (texture) + { + var phaserTexture = this.camera.scene.sys.textures.getFrame(texture); + + if (phaserTexture) + { + this.maskGameObject = null; + this.glTexture = phaserTexture.glTexture; + } + + return this; + }, + + destroy: function () + { + if (this._dynamicTexture) + { + this._dynamicTexture.destroy(); + } + + this.maskGameObject = null; + this._dynamicTexture = null; + + Controller.prototype.destroy.call(this); + } +}); + +module.exports = Mask; + + +/***/ }), + +/***/ 2195: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FilterList = __webpack_require__(53427); +var Controller = __webpack_require__(13045); +var Blend = __webpack_require__(16762); + +/** + * @classdesc + * The Parallel Filters Controller. + * + * This filter controller splits the input into two lists of filters, + * runs each list separately, and then blends the results together. + * + * The Parallel Filters effect is useful for reusing an input. + * Ordinarily, a filter modifies the input and passes it to the next filter. + * This effect allows you to split the input and re-use it elsewhere. + * It does not gain performance benefits from parallel processing; + * it is a convenience for reusing the input. + * + * The Parallel Filters effect is not a filter itself. + * It is a controller that manages two FilterLists, + * and the final Blend filter that combines the results. + * The FilterLists are named 'top' and 'bottom'. + * The 'top' output is applied as a blend texture to the 'bottom' output. + * + * You do not have to populate both lists. If only one is populated, + * it will be blended with the original input at the end. + * This is useful when you want to retain image data that would be lost + * in the filter process. + * + * A Parallel Filters effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * camera.filters.internal.addParallelFilters(); + * camera.filters.external.addParallelFilters(); + * ``` + * + * @example + * // Create a customizable Bloom effect. + * const camera = this.cameras.main; + * const parallelFilters = camera.filters.internal.addParallelFilters(); + * parallelFilters.top.addThreshold(0.5, 1); + * parallelFilters.top.addBlur(); + * parallelFilters.blend.blendMode = Phaser.BlendModes.ADD; + * parallelFilters.blend.amount = 0.5; + * + * @class ParallelFilters + * @extends Phaser.Filters.Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that owns this filter. + */ +var ParallelFilters = new Class({ + Extends: Controller, + + initialize: function ParallelFilters (camera) + { + Controller.call(this, camera, 'FilterParallelFilters'); + + /** + * The top FilterList. + * + * @name Phaser.Filters.ParallelFilters#top + * @type {Phaser.GameObjects.Components.FilterList} + * @since 4.0.0 + */ + this.top = new FilterList(camera); + + /** + * The bottom FilterList. + * + * @name Phaser.Filters.ParallelFilters#bottom + * @type {Phaser.GameObjects.Components.FilterList} + * @since 4.0.0 + */ + this.bottom = new FilterList(camera); + + /** + * The Blend filter controller that combines the top and bottom FilterLists. + * This is just another filter controller. + * See {@link Phaser.Filters.Blend} for more information. + * + * The `texture` property of the Blend controller will be + * overwritten during rendering. + * + * @name Phaser.Filters.ParallelFilters#blend + * @type {Phaser.Filters.Blend} + * @since 4.0.0 + */ + this.blend = new Blend(camera); + } +}); + +module.exports = ParallelFilters; + + +/***/ }), + +/***/ 29861: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Pixelate Filter Controller. + * + * This filter controller manages the pixelate effect for a Camera. + * The pixelate effect is a visual technique that deliberately reduces the resolution or detail of an image, + * creating a blocky or mosaic appearance composed of large, visible pixels. This effect can be used for stylistic + * purposes, as a homage to retro gaming, or as a means to obscure certain elements within the game, such as + * during a transition or to censor specific content. + * + * A Pixelate effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * camera.filters.internal.addPixelate(); + * ``` + * + * @class Pixelate + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @extends Phaser.Filters.Controller + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {number} [amount=1] - The amount of pixelation to apply. + */ +var Pixelate = new Class({ + Extends: Controller, + + initialize: function Pixelate (camera, amount) + { + if (amount === undefined) { amount = 1; } + + Controller.call(this, camera, 'FilterPixelate'); + + /** + * The amount of pixelation to apply. + * + * The size of the pixels is equal to 2 + the amount. + * + * @name Phaser.Filters.Pixelate#amount + * @type {number} + * @default 1 + * @since 4.0.0 + */ + this.amount = amount; + } +}); + +module.exports = Pixelate; + + +/***/ }), + +/***/ 63785: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Sampler Filter Controller. + * + * This controller manages a sampler. + * It doesn't actually render anything, and leaves the image unaltered. + * It is used to sample a region of the camera view, and pass the results to a callback. + * This is useful for extracting data from the camera view. + * + * This operation is expensive, so use sparingly. + * + * A Sampler is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addSampler(callback, region); + * camera.filters.external.addSampler(callback, region); + * ``` + * + * @class Sampler + * @memberof Phaser.Filters + * @extends Phaser.Filters.Controller + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The callback to call with the results of the sampler. + * @param {null|Phaser.Types.Math.Vector2Like|Phaser.Geom.Rectangle} [region=null] - The region to sample. If `null`, the entire camera view is sampled. If a `Phaser.Types.Math.Vector2Like`, a point is sampled. If a `Phaser.Geom.Rectangle`, the region is sampled. + */ +var Sampler = new Class({ + Extends: Controller, + + initialize: function Sampler (camera, callback, region) + { + if (region === undefined) { region = null; } + + Controller.call(this, camera, 'FilterSampler'); + + this.allowBaseDraw = false; + + /** + * The callback to call with the results of the sampler. + * + * @name Phaser.Filters.Sampler#callback + * @type {Phaser.Types.Renderer.Snapshot.SnapshotCallback} + * @since 4.0.0 + */ + this.callback = callback; + + /** + * The region to sample. If `null`, the entire camera view is sampled. + * If a `Phaser.Types.Math.Vector2Like`, a point is sampled. + * If a `Phaser.Geom.Rectangle`, the region is sampled. + * + * @name Phaser.Filters.Sampler#region + * @type {null|Phaser.Types.Math.Vector2Like|Phaser.Geom.Rectangle} + */ + this.region = region; + } +}); + +module.exports = Sampler; + + +/***/ }), + +/***/ 62229: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Shadow Filter. + * + * This filter controller manages the shadow effect for a Camera. + * + * The shadow effect is a visual technique used to create the illusion of depth and realism by adding darker, + * offset silhouettes or shapes beneath game objects, characters, or environments. These simulated shadows + * help to enhance the visual appeal and immersion, making the 2D game world appear more dynamic and three-dimensional. + * + * A Shadow effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addShadow(); + * camera.filters.external.addShadow(); + * ``` + * + * @class Shadow + * @extends Phaser.Filters.Controller + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera that owns this filter. + * @param {number} [x=0] - The horizontal offset of the shadow effect. + * @param {number} [y=0] - The vertical offset of the shadow effect. + * @param {number} [decay=0.1] - The amount of decay for the shadow effect. + * @param {number} [power=1] - The power of the shadow effect. + * @param {number} [color=0x000000] - The color of the shadow, as a hex value. + * @param {number} [samples=6] - The number of samples that the shadow effect will run for. + * @param {number} [intensity=1] - The intensity of the shadow effect. + */ +var Shadow = new Class({ + + Extends: Controller, + + initialize: function Shadow (camera, x, y, decay, power, color, samples, intensity) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (decay === undefined) { decay = 0.1; } + if (power === undefined) { power = 1; } + if (samples === undefined) { samples = 6; } + if (intensity === undefined) { intensity = 1; } + + Controller.call(this, camera, 'FilterShadow'); + + /** + * The horizontal offset of the shadow effect. + * + * @name Phaser.Filters.Shadow#x + * @type {number} + * @since 4.0.0 + */ + this.x = x; + + /** + * The vertical offset of the shadow effect. + * + * @name Phaser.Filters.Shadow#y + * @type {number} + * @since 4.0.0 + */ + this.y = y; + + /** + * The amount of decay for the shadow effect. + * + * @name Phaser.Filters.Shadow#decay + * @type {number} + * @since 4.0.0 + */ + this.decay = decay; + + /** + * The power of the shadow effect. + * + * @name Phaser.Filters.Shadow#power + * @type {number} + * @since 4.0.0 + */ + this.power = power; + + /** + * The internal gl color array. + * + * @name Phaser.Filters.Shadow#glcolor + * @type {number[]} + * @since 4.0.0 + */ + this.glcolor = [ 0, 0, 0, 1 ]; + + /** + * The number of samples that the shadow effect will run for. + * + * This should be an integer with a minimum value of 1 and a maximum of 12. + * + * @name Phaser.Filters.Shadow#samples + * @type {number} + * @since 4.0.0 + */ + this.samples = samples; + + /** + * The intensity of the shadow effect. + * + * @name Phaser.Filters.Shadow#intensity + * @type {number} + * @since 4.0.0 + */ + this.intensity = intensity; + + if (color !== undefined) + { + this.color = color; + } + }, + + /** + * The color of the shadow. + * + * @name Phaser.Filters.Shadow#color + * @type {number} + * @since 4.0.0 + */ + color: { + + get: function () + { + var color = this.glcolor; + + return (((color[0] * 255) << 16) + ((color[1] * 255) << 8) + (color[2] * 255 | 0)); + }, + + set: function (value) + { + var color = this.glcolor; + + color[0] = ((value >> 16) & 0xFF) / 255; + color[1] = ((value >> 8) & 0xFF) / 255; + color[2] = (value & 0xFF) / 255; + } + + }, + + getPadding: function () + { + var override = this.paddingOverride; + if (override) + { + this.currentPadding.setTo(override.x, override.y, override.width, override.height); + return override; + } + + var camera = this.camera; + var factor = this.decay * this.intensity; + var x = Math.ceil(Math.abs(this.x) * camera.width * factor); + var y = Math.ceil(Math.abs(this.y) * camera.height * factor); + + // Never get smaller, only larger. + this.currentPadding.setTo(-x, -y, x * 2, y * 2); + + return this.currentPadding; + } +}); + +module.exports = Shadow; + + +/***/ }), + +/***/ 99534: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Controller = __webpack_require__(13045); + +/** + * @classdesc + * The Threshold Filter Controller. + * + * This controller manages a threshold filter. + * Input values are compared to a threshold value or range. + * Values below the threshold are set to 0, and values above the threshold are set to 1. + * Values within the range are linearly interpolated between 0 and 1. + * + * This is useful for creating effects such as sharp edges from gradients, + * or for creating binary effects. + * + * The threshold is stored as a range, with two edges. + * Each edge has a value for each channel, between 0 and 1. + * If the two edges are the same, the threshold has no interpolation, + * and will output either 0 or 1. + * Each channel can also be inverted. + * + * A Threshold effect is added to a Camera via the FilterList component: + * + * ```js + * const camera = this.cameras.main; + * + * camera.filters.internal.addThreshold(); + * camera.filters.external.addThreshold(); + * ``` + * + * @class Threshold + * @memberof Phaser.Filters + * @constructor + * @since 4.0.0 + * @extends Phaser.Filters.Controller + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this filter. + * @param {number|number[]} [edge1=0.5] - The first edge of the threshold. This may be an array of the RGBA channels, or a single number to apply to all 4 channels. + * @param {number|number[]} [edge2=0.5] - The second edge of the threshold. This may be an array of the RGBA channels, or a single number to apply to all 4 channels. + * @param {boolean|boolean[]} [invert=false] - Whether each channel is inverted. This may be an array of the RGBA channels, or a single boolean to apply to all 4 channels. + */ +var Threshold = new Class({ + Extends: Controller, + + initialize: function Threshold (camera, edge1, edge2, invert) + { + Controller.call(this, camera, 'FilterThreshold'); + + /** + * The first edge of the threshold. + * This contains the lowest value for each channel. + * + * @name Phaser.Filters.Threshold#edge1 + * @type {number[]} + * @default [ 0.5, 0.5, 0.5, 0.5 ] + * @since 4.0.0 + */ + this.edge1 = [ 0.5, 0.5, 0.5, 0.5 ]; + + /** + * The second edge of the threshold. + * This contains the highest value for each channel. + * If it is the same as the first edge, the threshold is a single value. + * + * @name Phaser.Filters.Threshold#edge2 + * @type {number[]} + * @default [ 0.5, 0.5, 0.5, 0.5 ] + * @since 4.0.0 + */ + this.edge2 = [ 0.5, 0.5, 0.5, 0.5 ]; + + /** + * Whether each channel is inverted. + * + * @name Phaser.Filters.Threshold#invert + * @type {boolean[]} + * @default [ false, false, false, false ] + * @since 4.0.0 + */ + this.invert = [ false, false, false, false ]; + + this.setEdge(edge1, edge2); + this.setInvert(invert); + }, + + /** + * Set the edges of the threshold. + * If the second edge is not provided, it will be set to the first edge. + * + * This ensures that the first edge is not greater than the second edge. + * It may swap channels between edges to ensure this. + * + * @method Phaser.Filters.Threshold#setEdge + * @since 4.0.0 + * @param {number|number[]} [edge1=0.5] - The first edge of the threshold. This may be an array of the RGBA channels, or a single number to apply to all 4 channels. + * @param {number|number[]} [edge2=0.5] - The second edge of the threshold. This may be an array of the RGBA channels, or a single number to apply to all 4 channels. + * @return {Phaser.Filters.Threshold} This Threshold instance. + */ + setEdge: function (edge1, edge2) + { + if (edge1 === undefined) + { + edge1 = 0.5; + } + if (typeof edge1 === 'number') + { + edge1 = [ edge1, edge1, edge1, edge1 ]; + } + + this.edge1[0] = edge1[0]; + this.edge1[1] = edge1[1]; + this.edge1[2] = edge1[2]; + this.edge1[3] = edge1[3]; + + if (edge2 === undefined) + { + edge2 = edge1; + } + if (typeof edge2 === 'number') + { + edge2 = [ edge2, edge2, edge2, edge2 ]; + } + + this.edge2[0] = edge2[0]; + this.edge2[1] = edge2[1]; + this.edge2[2] = edge2[2]; + this.edge2[3] = edge2[3]; + + for (var i = 0; i < 4; i++) + { + if (this.edge1[i] > this.edge2[i]) + { + var temp = this.edge1[i]; + this.edge1[i] = this.edge2[i]; + this.edge2[i] = temp; + } + } + + return this; + }, + + /** + * Set the invert state of the threshold. + * If invert is not provided, it will be set to false. + * + * @method Phaser.Filters.Threshold#setInvert + * @since 4.0.0 + * @param {boolean|boolean[]} [invert=false] - Whether each channel is inverted. This may be an array of the RGBA channels, or a single boolean to apply to all 4 channels. + * @return {Phaser.Filters.Threshold} This Threshold instance. + */ + setInvert: function (invert) + { + if (invert === undefined) + { + invert = false; + } + if (typeof invert === 'boolean') + { + invert = [ invert, invert, invert, invert ]; + } + + this.invert[0] = invert[0]; + this.invert[1] = invert[1]; + this.invert[2] = invert[2]; + this.invert[3] = invert[3]; + + return this; + } +}); + +module.exports = Threshold; + + +/***/ }), + +/***/ 11889: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Filters + */ + +var Filters = { + Controller: __webpack_require__(13045), + + Barrel: __webpack_require__(10189), + Blend: __webpack_require__(16762), + Blur: __webpack_require__(88344), + Bokeh: __webpack_require__(47564), + ColorMatrix: __webpack_require__(77011), + Displacement: __webpack_require__(16898), + Glow: __webpack_require__(42652), + Mask: __webpack_require__(97797), + ParallelFilters: __webpack_require__(2195), + Pixelate: __webpack_require__(29861), + Sampler: __webpack_require__(63785), + Shadow: __webpack_require__(62229), + Threshold: __webpack_require__(99534) +}; + +module.exports = Filters; + + +/***/ }), + +/***/ 25305: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlendModes = __webpack_require__(10312); +var GetAdvancedValue = __webpack_require__(23568); + +/** + * Builds a Game Object using the provided configuration object. + * + * @function Phaser.GameObjects.BuildGameObject + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - A reference to the Scene. + * @param {Phaser.GameObjects.GameObject} gameObject - The initial GameObject. + * @param {Phaser.Types.GameObjects.GameObjectConfig} config - The config to build the GameObject with. + * + * @return {Phaser.GameObjects.GameObject} The built Game Object. + */ +var BuildGameObject = function (scene, gameObject, config) +{ + // Position + + gameObject.x = GetAdvancedValue(config, 'x', 0); + gameObject.y = GetAdvancedValue(config, 'y', 0); + gameObject.depth = GetAdvancedValue(config, 'depth', 0); + + // Flip + + gameObject.flipX = GetAdvancedValue(config, 'flipX', false); + gameObject.flipY = GetAdvancedValue(config, 'flipY', false); + + // Scale + // Either: { scale: 2 } or { scale: { x: 2, y: 2 }} + + var scale = GetAdvancedValue(config, 'scale', null); + + if (typeof scale === 'number') + { + gameObject.setScale(scale); + } + else if (scale !== null) + { + gameObject.scaleX = GetAdvancedValue(scale, 'x', 1); + gameObject.scaleY = GetAdvancedValue(scale, 'y', 1); + } + + // ScrollFactor + // Either: { scrollFactor: 2 } or { scrollFactor: { x: 2, y: 2 }} + + var scrollFactor = GetAdvancedValue(config, 'scrollFactor', null); + + if (typeof scrollFactor === 'number') + { + gameObject.setScrollFactor(scrollFactor); + } + else if (scrollFactor !== null) + { + gameObject.scrollFactorX = GetAdvancedValue(scrollFactor, 'x', 1); + gameObject.scrollFactorY = GetAdvancedValue(scrollFactor, 'y', 1); + } + + // Rotation + + gameObject.rotation = GetAdvancedValue(config, 'rotation', 0); + + var angle = GetAdvancedValue(config, 'angle', null); + + if (angle !== null) + { + gameObject.angle = angle; + } + + // Alpha + + gameObject.alpha = GetAdvancedValue(config, 'alpha', 1); + + // Origin + // Either: { origin: 0.5 } or { origin: { x: 0.5, y: 0.5 }} + + var origin = GetAdvancedValue(config, 'origin', null); + + if (typeof origin === 'number') + { + gameObject.setOrigin(origin); + } + else if (origin !== null) + { + var ox = GetAdvancedValue(origin, 'x', 0.5); + var oy = GetAdvancedValue(origin, 'y', 0.5); + + gameObject.setOrigin(ox, oy); + } + + // BlendMode + + gameObject.blendMode = GetAdvancedValue(config, 'blendMode', BlendModes.NORMAL); + + // Visible + + gameObject.visible = GetAdvancedValue(config, 'visible', true); + + // Add to Scene + + var add = GetAdvancedValue(config, 'add', true); + + if (add) + { + scene.sys.displayList.add(gameObject); + } + + if (gameObject.preUpdate) + { + scene.sys.updateList.add(gameObject); + } + + return gameObject; +}; + +module.exports = BuildGameObject; + + +/***/ }), + +/***/ 13059: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetAdvancedValue = __webpack_require__(23568); + +/** + * Adds an Animation component to a Sprite and populates it based on the given config. + * + * @function Phaser.GameObjects.BuildGameObjectAnimation + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Sprite} sprite - The sprite to add an Animation component to. + * @param {object} config - The animation config. + * + * @return {Phaser.GameObjects.Sprite} The updated Sprite. + */ +var BuildGameObjectAnimation = function (sprite, config) +{ + var animConfig = GetAdvancedValue(config, 'anims', null); + + if (animConfig === null) + { + return sprite; + } + + if (typeof animConfig === 'string') + { + // { anims: 'key' } + sprite.anims.play(animConfig); + } + else if (typeof animConfig === 'object') + { + // { anims: { + // key: string + // startFrame: [string|number] + // delay: [float] + // repeat: [integer] + // repeatDelay: [float] + // yoyo: [boolean] + // play: [boolean] + // delayedPlay: [boolean] + // } + // } + + var anims = sprite.anims; + + var key = GetAdvancedValue(animConfig, 'key', undefined); + + if (key) + { + var startFrame = GetAdvancedValue(animConfig, 'startFrame', undefined); + + var delay = GetAdvancedValue(animConfig, 'delay', 0); + var repeat = GetAdvancedValue(animConfig, 'repeat', 0); + var repeatDelay = GetAdvancedValue(animConfig, 'repeatDelay', 0); + var yoyo = GetAdvancedValue(animConfig, 'yoyo', false); + + var play = GetAdvancedValue(animConfig, 'play', false); + var delayedPlay = GetAdvancedValue(animConfig, 'delayedPlay', 0); + + var playConfig = { + key: key, + delay: delay, + repeat: repeat, + repeatDelay: repeatDelay, + yoyo: yoyo, + startFrame: startFrame + }; + + if (play) + { + anims.play(playConfig); + } + else if (delayedPlay > 0) + { + anims.playAfterDelay(playConfig, delayedPlay); + } + else + { + anims.load(playConfig); + } + } + } + + return sprite; +}; + +module.exports = BuildGameObjectAnimation; + + +/***/ }), + +/***/ 8050: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var List = __webpack_require__(73162); +var PluginCache = __webpack_require__(37277); +var GameObjectEvents = __webpack_require__(51708); +var SceneEvents = __webpack_require__(44594); +var StableSort = __webpack_require__(19186); + +/** + * @classdesc + * The Display List plugin. + * + * Display Lists belong to a Scene and maintain the list of Game Objects to render every frame. + * + * Some of these Game Objects may also be part of the Scene's [Update List]{@link Phaser.GameObjects.UpdateList}, for updating. + * + * @class DisplayList + * @extends Phaser.Structs.List. + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that this Display List belongs to. + */ +var DisplayList = new Class({ + + Extends: List, + + initialize: + + function DisplayList (scene) + { + List.call(this, scene); + + /** + * The flag the determines whether Game Objects should be sorted when `depthSort()` is called. + * + * @name Phaser.GameObjects.DisplayList#sortChildrenFlag + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.sortChildrenFlag = false; + + /** + * The Scene that this Display List belongs to. + * + * @name Phaser.GameObjects.DisplayList#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The Scene's Systems. + * + * @name Phaser.GameObjects.DisplayList#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * The Scene's Event Emitter. + * + * @name Phaser.GameObjects.DisplayList#events + * @type {Phaser.Events.EventEmitter} + * @since 3.50.0 + */ + this.events = scene.sys.events; + + // Set the List callbacks + this.addCallback = this.addChildCallback; + this.removeCallback = this.removeChildCallback; + + this.events.once(SceneEvents.BOOT, this.boot, this); + this.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.DisplayList#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * Internal method called from `List.addCallback`. + * + * @method Phaser.GameObjects.DisplayList#addChildCallback + * @private + * @fires Phaser.Scenes.Events#ADDED_TO_SCENE + * @fires Phaser.GameObjects.Events#ADDED_TO_SCENE + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the list. + */ + addChildCallback: function (gameObject) + { + if (gameObject.displayList && gameObject.displayList !== this) + { + gameObject.removeFromDisplayList(); + } + + if (gameObject.parentContainer) + { + gameObject.parentContainer.remove(gameObject); + } + + if (!gameObject.displayList) + { + this.queueDepthSort(); + + gameObject.displayList = this; + + gameObject.emit(GameObjectEvents.ADDED_TO_SCENE, gameObject, this.scene); + + this.events.emit(SceneEvents.ADDED_TO_SCENE, gameObject, this.scene); + } + }, + + /** + * Internal method called from `List.removeCallback`. + * + * @method Phaser.GameObjects.DisplayList#removeChildCallback + * @private + * @fires Phaser.Scenes.Events#REMOVED_FROM_SCENE + * @fires Phaser.GameObjects.Events#REMOVED_FROM_SCENE + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the list. + */ + removeChildCallback: function (gameObject) + { + this.queueDepthSort(); + + gameObject.displayList = null; + + gameObject.emit(GameObjectEvents.REMOVED_FROM_SCENE, gameObject, this.scene); + + this.events.emit(SceneEvents.REMOVED_FROM_SCENE, gameObject, this.scene); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.DisplayList#start + * @private + * @since 3.5.0 + */ + start: function () + { + this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Force a sort of the display list on the next call to depthSort. + * + * @method Phaser.GameObjects.DisplayList#queueDepthSort + * @since 3.0.0 + */ + queueDepthSort: function () + { + this.sortChildrenFlag = true; + }, + + /** + * Immediately sorts the display list if the flag is set. + * + * @method Phaser.GameObjects.DisplayList#depthSort + * @since 3.0.0 + */ + depthSort: function () + { + if (this.sortChildrenFlag) + { + StableSort(this.list, this.sortByDepth); + + this.sortChildrenFlag = false; + } + }, + + /** + * Compare the depth of two Game Objects. + * + * @method Phaser.GameObjects.DisplayList#sortByDepth + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} childA - The first Game Object. + * @param {Phaser.GameObjects.GameObject} childB - The second Game Object. + * + * @return {number} The difference between the depths of each Game Object. + */ + sortByDepth: function (childA, childB) + { + return childA._depth - childB._depth; + }, + + /** + * Returns an array which contains all objects currently on the Display List. + * This is a reference to the main list array, not a copy of it, so be careful not to modify it. + * + * @method Phaser.GameObjects.DisplayList#getChildren + * @since 3.12.0 + * + * @return {Phaser.GameObjects.GameObject[]} The group members. + */ + getChildren: function () + { + return this.list; + }, + + /** + * The Scene that owns this plugin is shutting down. + * + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.GameObjects.DisplayList#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + var list = this.list; + var i = list.length; + + while (i--) + { + if (list[i]) + { + list[i].destroy(true); + } + } + + list.length = 0; + + this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.GameObjects.DisplayList#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + this.events = null; + } + +}); + +PluginCache.register('DisplayList', DisplayList, 'displayList'); + +module.exports = DisplayList; + + +/***/ }), + +/***/ 95643: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var ComponentsToJSON = __webpack_require__(53774); +var DataManager = __webpack_require__(45893); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(51708); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * The base class that all Game Objects extend. + * You don't create GameObjects directly and they cannot be added to the display list. + * Instead, use them as the base for your own custom classes. + * + * @class GameObject + * @memberof Phaser.GameObjects + * @extends Phaser.Events.EventEmitter + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Filters + * @extends Phaser.GameObjects.Components.RenderSteps + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. + * @param {string} type - A textual representation of the type of Game Object, i.e. `sprite`. + */ +var GameObject = new Class({ + + Extends: EventEmitter, + + Mixins: [ + Components.Filters, + Components.RenderSteps + ], + + initialize: + + function GameObject (scene, type) + { + EventEmitter.call(this); + + /** + * A reference to the Scene to which this Game Object belongs. + * + * Game Objects can only belong to one Scene. + * + * You should consider this property as being read-only. You cannot move a + * Game Object to another Scene by simply changing it. + * + * @name Phaser.GameObjects.GameObject#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * Holds a reference to the Display List that contains this Game Object. + * + * This is set automatically when this Game Object is added to a Scene or Layer. + * + * You should treat this property as being read-only. + * + * @name Phaser.GameObjects.GameObject#displayList + * @type {(Phaser.GameObjects.DisplayList|Phaser.GameObjects.Layer)} + * @default null + * @since 3.50.0 + */ + this.displayList = null; + + /** + * A textual representation of this Game Object, i.e. `sprite`. + * Used internally by Phaser but is available for your own custom classes to populate. + * + * @name Phaser.GameObjects.GameObject#type + * @type {string} + * @since 3.0.0 + */ + this.type = type; + + /** + * The current state of this Game Object. + * + * Phaser itself will never modify this value, although plugins may do so. + * + * Use this property to track the state of a Game Object during its lifetime. For example, it could change from + * a state of 'moving', to 'attacking', to 'dead'. The state value should be an integer (ideally mapped to a constant + * in your game code), or a string. These are recommended to keep it light and simple, with fast comparisons. + * If you need to store complex data about your Game Object, look at using the Data Component instead. + * + * @name Phaser.GameObjects.GameObject#state + * @type {(number|string)} + * @since 3.16.0 + */ + this.state = 0; + + /** + * The parent Container of this Game Object, if it has one. + * + * @name Phaser.GameObjects.GameObject#parentContainer + * @type {Phaser.GameObjects.Container} + * @since 3.4.0 + */ + this.parentContainer = null; + + /** + * The name of this Game Object. + * Empty by default and never populated by Phaser, this is left for developers to use. + * + * @name Phaser.GameObjects.GameObject#name + * @type {string} + * @default '' + * @since 3.0.0 + */ + this.name = ''; + + /** + * The active state of this Game Object. + * A Game Object with an active state of `true` is processed by the Scenes UpdateList, if added to it. + * An active object is one which is having its logic and internal systems updated. + * + * @name Phaser.GameObjects.GameObject#active + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.active = true; + + /** + * The Tab Index of the Game Object. + * Reserved for future use by plugins and the Input Manager. + * + * @name Phaser.GameObjects.GameObject#tabIndex + * @type {number} + * @default -1 + * @since 3.0.0 + */ + this.tabIndex = -1; + + /** + * A Data Manager. + * It allows you to store, query and get key/value paired information specific to this Game Object. + * `null` by default. Automatically created if you use `getData` or `setData` or `setDataEnabled`. + * + * @name Phaser.GameObjects.GameObject#data + * @type {Phaser.Data.DataManager} + * @default null + * @since 3.0.0 + */ + this.data = null; + + /** + * The flags that are compared against `RENDER_MASK` to determine if this Game Object will render or not. + * The bits are 0001 | 0010 | 0100 | 1000 set by the components Visible, Alpha, Transform and Texture respectively. + * If those components are not used by your custom class then you can use this bitmask as you wish. + * + * @name Phaser.GameObjects.GameObject#renderFlags + * @type {number} + * @default 15 + * @since 3.0.0 + */ + this.renderFlags = 15; + + /** + * A bitmask that controls if this Game Object is drawn by a Camera or not. + * Not usually set directly, instead call `Camera.ignore`, however you can + * set this property directly using the Camera.id property: + * + * @example + * this.cameraFilter |= camera.id + * + * @name Phaser.GameObjects.GameObject#cameraFilter + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.cameraFilter = 0; + + /** + * If this Game Object is enabled for input then this property will contain an InteractiveObject instance. + * Not usually set directly. Instead call `GameObject.setInteractive()`. + * + * @name Phaser.GameObjects.GameObject#input + * @type {?Phaser.Types.Input.InteractiveObject} + * @default null + * @since 3.0.0 + */ + this.input = null; + + /** + * If this Game Object is enabled for Arcade or Matter Physics then this property will contain a reference to a Physics Body. + * + * @name Phaser.GameObjects.GameObject#body + * @type {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|MatterJS.BodyType)} + * @default null + * @since 3.0.0 + */ + this.body = null; + + /** + * This Game Object will ignore all calls made to its destroy method if this flag is set to `true`. + * This includes calls that may come from a Group, Container or the Scene itself. + * While it allows you to persist a Game Object across Scenes, please understand you are entirely + * responsible for managing references to and from this Game Object. + * + * @name Phaser.GameObjects.GameObject#ignoreDestroy + * @type {boolean} + * @default false + * @since 3.5.0 + */ + this.ignoreDestroy = false; + + // Initialize RenderSteps mixin. + if (this.addRenderStep) + { + this.addRenderStep(this.renderWebGL); + } + + this.on(Events.ADDED_TO_SCENE, this.addedToScene, this); + this.on(Events.REMOVED_FROM_SCENE, this.removedFromScene, this); + + // Tell the Scene to re-sort the children + scene.sys.queueDepthSort(); + }, + + /** + * Sets the `active` property of this Game Object and returns this Game Object for further chaining. + * A Game Object with its `active` property set to `true` will be updated by the Scenes UpdateList. + * + * @method Phaser.GameObjects.GameObject#setActive + * @since 3.0.0 + * + * @param {boolean} value - True if this Game Object should be set as active, false if not. + * + * @return {this} This GameObject. + */ + setActive: function (value) + { + this.active = value; + + return this; + }, + + /** + * Sets the `name` property of this Game Object and returns this Game Object for further chaining. + * The `name` property is not populated by Phaser and is presented for your own use. + * + * @method Phaser.GameObjects.GameObject#setName + * @since 3.0.0 + * + * @param {string} value - The name to be given to this Game Object. + * + * @return {this} This GameObject. + */ + setName: function (value) + { + this.name = value; + + return this; + }, + + /** + * Sets the current state of this Game Object. + * + * Phaser itself will never modify the State of a Game Object, although plugins may do so. + * + * For example, a Game Object could change from a state of 'moving', to 'attacking', to 'dead'. + * The state value should typically be an integer (ideally mapped to a constant + * in your game code), but could also be a string. It is recommended to keep it light and simple. + * If you need to store complex data about your Game Object, look at using the Data Component instead. + * + * @method Phaser.GameObjects.GameObject#setState + * @since 3.16.0 + * + * @param {(number|string)} value - The state of the Game Object. + * + * @return {this} This GameObject. + */ + setState: function (value) + { + this.state = value; + + return this; + }, + + /** + * Adds a Data Manager component to this Game Object. + * + * @method Phaser.GameObjects.GameObject#setDataEnabled + * @since 3.0.0 + * @see Phaser.Data.DataManager + * + * @return {this} This GameObject. + */ + setDataEnabled: function () + { + if (!this.data) + { + this.data = new DataManager(this); + } + + return this; + }, + + /** + * Allows you to store a key value pair within this Game Objects Data Manager. + * + * If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled + * before setting the value. + * + * If the key doesn't already exist in the Data Manager then it is created. + * + * ```javascript + * sprite.setData('name', 'Red Gem Stone'); + * ``` + * + * You can also pass in an object of key value pairs as the first argument: + * + * ```javascript + * sprite.setData({ name: 'Red Gem Stone', level: 2, owner: 'Link', gold: 50 }); + * ``` + * + * To get a value back again you can call `getData`: + * + * ```javascript + * sprite.getData('gold'); + * ``` + * + * Or you can access the value directly via the `values` property, where it works like any other variable: + * + * ```javascript + * sprite.data.values.gold += 50; + * ``` + * + * When the value is first set, a `setdata` event is emitted from this Game Object. + * + * If the key already exists, a `changedata` event is emitted instead, along an event named after the key. + * For example, if you updated an existing key called `PlayerLives` then it would emit the event `changedata-PlayerLives`. + * These events will be emitted regardless if you use this method to set the value, or the direct `values` setter. + * + * Please note that the data keys are case-sensitive and must be valid JavaScript Object property strings. + * This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager. + * + * @method Phaser.GameObjects.GameObject#setData + * @since 3.0.0 + * + * @generic {any} T + * @genericUse {(string|T)} - [key] + * + * @param {(string|object)} key - The key to set the value for. Or an object of key value pairs. If an object the `data` argument is ignored. + * @param {*} [data] - The value to set for the given key. If an object is provided as the key this argument is ignored. + * + * @return {this} This GameObject. + */ + setData: function (key, value) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + this.data.set(key, value); + + return this; + }, + + /** + * Increase a value for the given key within this Game Objects Data Manager. If the key doesn't already exist in the Data Manager then it is increased from 0. + * + * If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled + * before setting the value. + * + * If the key doesn't already exist in the Data Manager then it is created. + * + * When the value is first set, a `setdata` event is emitted from this Game Object. + * + * @method Phaser.GameObjects.GameObject#incData + * @since 3.23.0 + * + * @param {string} key - The key to change the value for. + * @param {number} [amount=1] - The amount to increase the given key by. Pass a negative value to decrease the key. + * + * @return {this} This GameObject. + */ + incData: function (key, amount) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + this.data.inc(key, amount); + + return this; + }, + + /** + * Toggle a boolean value for the given key within this Game Objects Data Manager. If the key doesn't already exist in the Data Manager then it is toggled from false. + * + * If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled + * before setting the value. + * + * If the key doesn't already exist in the Data Manager then it is created. + * + * When the value is first set, a `setdata` event is emitted from this Game Object. + * + * @method Phaser.GameObjects.GameObject#toggleData + * @since 3.23.0 + * + * @param {string} key - The key to toggle the value for. + * + * @return {this} This GameObject. + */ + toggleData: function (key) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + this.data.toggle(key); + + return this; + }, + + /** + * Retrieves the value for the given key in this Game Objects Data Manager, or undefined if it doesn't exist. + * + * You can also access values via the `values` object. For example, if you had a key called `gold` you can do either: + * + * ```javascript + * sprite.getData('gold'); + * ``` + * + * Or access the value directly: + * + * ```javascript + * sprite.data.values.gold; + * ``` + * + * You can also pass in an array of keys, in which case an array of values will be returned: + * + * ```javascript + * sprite.getData([ 'gold', 'armor', 'health' ]); + * ``` + * + * This approach is useful for destructuring arrays in ES6. + * + * @method Phaser.GameObjects.GameObject#getData + * @since 3.0.0 + * + * @param {(string|string[])} key - The key of the value to retrieve, or an array of keys. + * + * @return {*} The value belonging to the given key, or an array of values, the order of which will match the input array. + */ + getData: function (key) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + return this.data.get(key); + }, + + /** + * Pass this Game Object to the Input Manager to enable it for Input. + * + * Input works by using hit areas, these are nearly always geometric shapes, such as rectangles or circles, that act as the hit area + * for the Game Object. However, you can provide your own hit area shape and callback, should you wish to handle some more advanced + * input detection. + * + * If no arguments are provided it will try and create a rectangle hit area based on the texture frame the Game Object is using. If + * this isn't a texture-bound object, such as a Graphics or BitmapText object, this will fail, and you'll need to provide a specific + * shape for it to use. + * + * You can also provide an Input Configuration Object as the only argument to this method. + * + * @example + * sprite.setInteractive(); + * + * @example + * sprite.setInteractive(new Phaser.Geom.Circle(45, 46, 45), Phaser.Geom.Circle.Contains); + * + * @example + * graphics.setInteractive(new Phaser.Geom.Rectangle(0, 0, 128, 128), Phaser.Geom.Rectangle.Contains); + * + * @method Phaser.GameObjects.GameObject#setInteractive + * @since 3.0.0 + * + * @param {(Phaser.Types.Input.InputConfiguration|any)} [hitArea] - Either an input configuration object, or a geometric shape that defines the hit area for the Game Object. If not given it will try to create a Rectangle based on the texture frame. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The callback that determines if the pointer is within the Hit Area shape or not. If you provide a shape you must also provide a callback. + * @param {boolean} [dropZone=false] - Should this Game Object be treated as a drop zone target? + * + * @return {this} This GameObject. + */ + setInteractive: function (hitArea, hitAreaCallback, dropZone) + { + this.scene.sys.input.enable(this, hitArea, hitAreaCallback, dropZone); + + return this; + }, + + /** + * If this Game Object has previously been enabled for input, this will disable it. + * + * An object that is disabled for input stops processing or being considered for + * input events, but can be turned back on again at any time by simply calling + * `setInteractive()` with no arguments provided. + * + * If want to completely remove interaction from this Game Object then use `removeInteractive` instead. + * + * @method Phaser.GameObjects.GameObject#disableInteractive + * @since 3.7.0 + * + * @param {boolean} [resetCursor=false] - Should the currently active Input cursor, if any, be reset to the default cursor? + * + * @return {this} This GameObject. + */ + disableInteractive: function (resetCursor) + { + if (resetCursor === undefined) { resetCursor = false; } + + this.scene.sys.input.disable(this, resetCursor); + + return this; + }, + + /** + * If this Game Object has previously been enabled for input, this will queue it + * for removal, causing it to no longer be interactive. The removal happens on + * the next game step, it is not immediate. + * + * The Interactive Object that was assigned to this Game Object will be destroyed, + * removed from the Input Manager and cleared from this Game Object. + * + * If you wish to re-enable this Game Object at a later date you will need to + * re-create its InteractiveObject by calling `setInteractive` again. + * + * If you wish to only temporarily stop an object from receiving input then use + * `disableInteractive` instead, as that toggles the interactive state, where-as + * this erases it completely. + * + * If you wish to resize a hit area, don't remove and then set it as being + * interactive. Instead, access the hitarea object directly and resize the shape + * being used. I.e.: `sprite.input.hitArea.setSize(width, height)` (assuming the + * shape is a Rectangle, which it is by default.) + * + * @method Phaser.GameObjects.GameObject#removeInteractive + * @since 3.7.0 + * + * @param {boolean} [resetCursor=false] - Should the currently active Input cursor, if any, be reset to the default cursor? + * + * @return {this} This GameObject. + */ + removeInteractive: function (resetCursor) + { + if (resetCursor === undefined) { resetCursor = false; } + + this.scene.sys.input.clear(this); + + if (resetCursor) + { + this.scene.sys.input.resetCursor(); + } + + this.input = undefined; + + return this; + }, + + /** + * This callback is invoked when this Game Object is added to a Scene. + * + * Can be overriden by custom Game Objects, but be aware of some Game Objects that + * will use this, such as Sprites, to add themselves into the Update List. + * + * You can also listen for the `ADDED_TO_SCENE` event from this Game Object. + * + * @method Phaser.GameObjects.GameObject#addedToScene + * @since 3.50.0 + */ + addedToScene: function () + { + }, + + /** + * This callback is invoked when this Game Object is removed from a Scene. + * + * Can be overriden by custom Game Objects, but be aware of some Game Objects that + * will use this, such as Sprites, to removed themselves from the Update List. + * + * You can also listen for the `REMOVED_FROM_SCENE` event from this Game Object. + * + * @method Phaser.GameObjects.GameObject#removedFromScene + * @since 3.50.0 + */ + removedFromScene: function () + { + }, + + /** + * To be overridden by custom GameObjects. Allows base objects to be used in a Pool. + * + * @method Phaser.GameObjects.GameObject#update + * @since 3.0.0 + * + * @param {...*} [args] - args + */ + update: function () + { + }, + + /** + * Returns a JSON representation of the Game Object. + * + * @method Phaser.GameObjects.GameObject#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object. + */ + toJSON: function () + { + return ComponentsToJSON(this); + }, + + /** + * Compares the renderMask with the renderFlags to see if this Game Object will render or not. + * Also checks the Game Object against the given Cameras exclusion list. + * + * @method Phaser.GameObjects.GameObject#willRender + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to check against this Game Object. + * + * @return {boolean} True if the Game Object should be rendered, otherwise false. + */ + willRender: function (camera) + { + var listWillRender = (this.displayList && this.displayList.active) ? this.displayList.willRender(camera) : true; + + return !(!listWillRender || GameObject.RENDER_MASK !== this.renderFlags || (this.cameraFilter !== 0 && (this.cameraFilter & camera.id))); + }, + + /** + * Returns an array containing the display list index of either this Game Object, or if it has one, + * its parent Container. It then iterates up through all of the parent containers until it hits the + * root of the display list (which is index 0 in the returned array). + * + * Used internally by the InputPlugin but also useful if you wish to find out the display depth of + * this Game Object and all of its ancestors. + * + * @method Phaser.GameObjects.GameObject#getIndexList + * @since 3.4.0 + * + * @return {number[]} An array of display list position indexes. + */ + getIndexList: function () + { + // eslint-disable-next-line consistent-this + var child = this; + var parent = this.parentContainer; + + var indexes = []; + + while (parent) + { + indexes.unshift(parent.getIndex(child)); + + child = parent; + + if (!parent.parentContainer) + { + break; + } + else + { + parent = parent.parentContainer; + } + } + + if (this.displayList) + { + indexes.unshift(this.displayList.getIndex(child)); + } + else + { + indexes.unshift(this.scene.sys.displayList.getIndex(child)); + } + + return indexes; + }, + + /** + * Adds this Game Object to the given Display List. + * + * If no Display List is specified, it will default to the Display List owned by the Scene to which + * this Game Object belongs. + * + * A Game Object can only exist on one Display List at any given time, but may move freely between them. + * + * If this Game Object is already on another Display List when this method is called, it will first + * be removed from it, before being added to the new list. + * + * You can query which list it is on by looking at the `Phaser.GameObjects.GameObject#displayList` property. + * + * If a Game Object isn't on any display list, it will not be rendered. If you just wish to temporarly + * disable it from rendering, consider using the `setVisible` method, instead. + * + * @method Phaser.GameObjects.GameObject#addToDisplayList + * @fires Phaser.Scenes.Events#ADDED_TO_SCENE + * @fires Phaser.GameObjects.Events#ADDED_TO_SCENE + * @since 3.53.0 + * + * @param {(Phaser.GameObjects.DisplayList|Phaser.GameObjects.Layer)} [displayList] - The Display List to add to. Defaults to the Scene Display List. + * + * @return {this} This Game Object. + */ + addToDisplayList: function (displayList) + { + if (displayList === undefined) { displayList = this.scene.sys.displayList; } + + if (this.displayList && this.displayList !== displayList) + { + this.removeFromDisplayList(); + } + + // Don't repeat if it's already on this list + if (!displayList.exists(this)) + { + this.displayList = displayList; + + displayList.add(this, true); + + displayList.queueDepthSort(); + + this.emit(Events.ADDED_TO_SCENE, this, this.scene); + + displayList.events.emit(SceneEvents.ADDED_TO_SCENE, this, this.scene); + } + + return this; + }, + + /** + * Adds this Game Object to the Update List belonging to the Scene. + * + * When a Game Object is added to the Update List it will have its `preUpdate` method called + * every game frame. This method is passed two parameters: `delta` and `time`. + * + * If you wish to run your own logic within `preUpdate` then you should always call + * `super.preUpdate(time, delta)` within it, or it may fail to process required operations, + * such as Sprite animations. + * + * @method Phaser.GameObjects.GameObject#addToUpdateList + * @since 3.53.0 + * + * @return {this} This Game Object. + */ + addToUpdateList: function () + { + if (this.scene && this.preUpdate) + { + this.scene.sys.updateList.add(this); + } + + return this; + }, + + /** + * Removes this Game Object from the Display List it is currently on. + * + * A Game Object can only exist on one Display List at any given time, but may move freely removed + * and added back at a later stage. + * + * You can query which list it is on by looking at the `Phaser.GameObjects.GameObject#displayList` property. + * + * If a Game Object isn't on any Display List, it will not be rendered. If you just wish to temporarly + * disable it from rendering, consider using the `setVisible` method, instead. + * + * @method Phaser.GameObjects.GameObject#removeFromDisplayList + * @fires Phaser.Scenes.Events#REMOVED_FROM_SCENE + * @fires Phaser.GameObjects.Events#REMOVED_FROM_SCENE + * @since 3.53.0 + * + * @return {this} This Game Object. + */ + removeFromDisplayList: function () + { + var displayList = this.displayList || this.scene.sys.displayList; + + if (displayList && displayList.exists(this)) + { + displayList.remove(this, true); + + displayList.queueDepthSort(); + + this.displayList = null; + + this.emit(Events.REMOVED_FROM_SCENE, this, this.scene); + + displayList.events.emit(SceneEvents.REMOVED_FROM_SCENE, this, this.scene); + } + + return this; + }, + + /** + * Removes this Game Object from the Scene's Update List. + * + * When a Game Object is on the Update List, it will have its `preUpdate` method called + * every game frame. Calling this method will remove it from the list, preventing this. + * + * Removing a Game Object from the Update List will stop most internal functions working. + * For example, removing a Sprite from the Update List will prevent it from being able to + * run animations. + * + * @method Phaser.GameObjects.GameObject#removeFromUpdateList + * @since 3.53.0 + * + * @return {this} This Game Object. + */ + removeFromUpdateList: function () + { + if (this.scene && this.preUpdate) + { + this.scene.sys.updateList.remove(this); + } + + return this; + }, + + /** + * Returns a reference to the underlying display list _array_ that contains this Game Object, + * which will be either the Scene's Display List or the internal list belonging + * to its parent Container, if it has one. + * + * If this Game Object is not on a display list or in a container, it will return `null`. + * + * You should be very careful with this method, and understand that it returns a direct reference to the + * internal array used by the Display List. Mutating this array directly can cause all kinds of subtle + * and difficult to debug issues in your game. + * + * @method Phaser.GameObjects.GameObject#getDisplayList + * @since 3.85.0 + * + * @return {?Phaser.GameObjects.GameObject[]} The internal Display List array of Game Objects, or `null`. + */ + getDisplayList: function () + { + var list = null; + + if (this.parentContainer) + { + list = this.parentContainer.list; + } + else if (this.displayList) + { + list = this.displayList.list; + } + + return list; + }, + + /** + * Destroys this Game Object removing it from the Display List and Update List and + * severing all ties to parent resources. + * + * Also removes itself from the Input Manager and Physics Manager if previously enabled. + * + * Use this to remove a Game Object from your game if you don't ever plan to use it again. + * As long as no reference to it exists within your own code it should become free for + * garbage collection by the browser. + * + * If you just want to temporarily disable an object then look at using the + * Game Object Pool instead of destroying it, as destroyed objects cannot be resurrected. + * + * @method Phaser.GameObjects.GameObject#destroy + * @fires Phaser.GameObjects.Events#DESTROY + * @since 3.0.0 + * + * @param {boolean} [fromScene=false] - `True` if this Game Object is being destroyed by the Scene, `false` if not. + */ + destroy: function (fromScene) + { + // This Game Object has already been destroyed + if (!this.scene || this.ignoreDestroy) + { + return; + } + + if (fromScene === undefined) { fromScene = false; } + + if (this.preDestroy) + { + this.preDestroy.call(this); + } + + this.emit(Events.DESTROY, this, fromScene); + + this.removeAllListeners(); + this.removeFromDisplayList(); + this.removeFromUpdateList(); + + if (this.input) + { + this.scene.sys.input.clear(this); + + this.input = undefined; + } + + if (this.data) + { + this.data.destroy(); + + this.data = undefined; + } + + if (this.body) + { + this.body.destroy(); + + this.body = undefined; + } + + if (this.filterCamera) + { + this.filterCamera.destroy(); + + this.filterCamera = undefined; + } + + this.active = false; + this.visible = false; + + this.scene = undefined; + this.parentContainer = undefined; + } + +}); + +/** + * The bitmask that `GameObject.renderFlags` is compared against to determine if the Game Object will render or not. + * + * @constant {number} RENDER_MASK + * @memberof Phaser.GameObjects.GameObject + * @default + */ +GameObject.RENDER_MASK = 15; + +module.exports = GameObject; + + +/***/ }), + +/***/ 44603: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * The Game Object Creator is a Scene plugin that allows you to quickly create many common + * types of Game Objects and return them using a configuration object, rather than + * having to specify a limited set of parameters such as with the GameObjectFactory. + * + * Game Objects made via this class are automatically added to the Scene and Update List + * unless you explicitly set the `add` property in the configuration object to `false`. + * + * @class GameObjectCreator + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object Factory belongs. + */ +var GameObjectCreator = new Class({ + + initialize: + + function GameObjectCreator (scene) + { + /** + * The Scene to which this Game Object Creator belongs. + * + * @name Phaser.GameObjects.GameObjectCreator#scene + * @type {Phaser.Scene} + * @protected + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene.Systems. + * + * @name Phaser.GameObjects.GameObjectCreator#systems + * @type {Phaser.Scenes.Systems} + * @protected + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * A reference to the Scene Event Emitter. + * + * @name Phaser.GameObjects.GameObjectCreator#events + * @type {Phaser.Events.EventEmitter} + * @protected + * @since 3.50.0 + */ + this.events = scene.sys.events; + + /** + * A reference to the Scene Display List. + * + * @name Phaser.GameObjects.GameObjectCreator#displayList + * @type {Phaser.GameObjects.DisplayList} + * @protected + * @since 3.0.0 + */ + this.displayList; + + /** + * A reference to the Scene Update List. + * + * @name Phaser.GameObjects.GameObjectCreator#updateList + * @type {Phaser.GameObjects.UpdateList} + * @protected + * @since 3.0.0 + */ + this.updateList; + + this.events.once(SceneEvents.BOOT, this.boot, this); + this.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.GameObjectCreator#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.displayList = this.systems.displayList; + this.updateList = this.systems.updateList; + + this.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.GameObjectCreator#start + * @private + * @since 3.5.0 + */ + start: function () + { + this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.GameObjects.GameObjectCreator#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.GameObjects.GameObjectCreator#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + this.events = null; + + this.displayList = null; + this.updateList = null; + } + +}); + +/** + * Static method called directly by the Game Object creator functions. + * With this method you can register a custom GameObject factory in the GameObjectCreator, + * providing a name (`factoryType`) and the constructor (`factoryFunction`) in order + * to be called when you invoke Phaser.Scene.make[ factoryType ] method. + * + * @method Phaser.GameObjects.GameObjectCreator.register + * @static + * @since 3.0.0 + * + * @param {string} factoryType - The key of the factory that you will use to call to Phaser.Scene.make[ factoryType ] method. + * @param {function} factoryFunction - The constructor function to be called when you invoke to the Phaser.Scene.make method. + */ +GameObjectCreator.register = function (factoryType, factoryFunction) +{ + if (!GameObjectCreator.prototype.hasOwnProperty(factoryType)) + { + GameObjectCreator.prototype[factoryType] = factoryFunction; + } +}; + +/** + * Static method called directly by the Game Object Creator functions. + * + * With this method you can remove a custom Game Object Creator that has been previously + * registered in the Game Object Creator. Pass in its `factoryType` in order to remove it. + * + * @method Phaser.GameObjects.GameObjectCreator.remove + * @static + * @since 3.0.0 + * + * @param {string} factoryType - The key of the factory that you want to remove from the GameObjectCreator. + */ +GameObjectCreator.remove = function (factoryType) +{ + if (GameObjectCreator.prototype.hasOwnProperty(factoryType)) + { + delete GameObjectCreator.prototype[factoryType]; + } +}; + +PluginCache.register('GameObjectCreator', GameObjectCreator, 'make'); + +module.exports = GameObjectCreator; + + +/***/ }), + +/***/ 39429: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * The Game Object Factory is a Scene plugin that allows you to quickly create many common + * types of Game Objects and have them automatically registered with the Scene. + * + * Game Objects directly register themselves with the Factory and inject their own creation + * methods into the class. + * + * @class GameObjectFactory + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object Factory belongs. + */ +var GameObjectFactory = new Class({ + + initialize: + + function GameObjectFactory (scene) + { + /** + * The Scene to which this Game Object Factory belongs. + * + * @name Phaser.GameObjects.GameObjectFactory#scene + * @type {Phaser.Scene} + * @protected + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene.Systems. + * + * @name Phaser.GameObjects.GameObjectFactory#systems + * @type {Phaser.Scenes.Systems} + * @protected + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * A reference to the Scene Event Emitter. + * + * @name Phaser.GameObjects.GameObjectFactory#events + * @type {Phaser.Events.EventEmitter} + * @protected + * @since 3.50.0 + */ + this.events = scene.sys.events; + + /** + * A reference to the Scene Display List. + * + * @name Phaser.GameObjects.GameObjectFactory#displayList + * @type {Phaser.GameObjects.DisplayList} + * @protected + * @since 3.0.0 + */ + this.displayList; + + /** + * A reference to the Scene Update List. + * + * @name Phaser.GameObjects.GameObjectFactory#updateList + * @type {Phaser.GameObjects.UpdateList} + * @protected + * @since 3.0.0 + */ + this.updateList; + + this.events.once(SceneEvents.BOOT, this.boot, this); + this.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.GameObjectFactory#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.displayList = this.systems.displayList; + this.updateList = this.systems.updateList; + + this.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.GameObjectFactory#start + * @private + * @since 3.5.0 + */ + start: function () + { + this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Adds an existing Game Object to this Scene. + * + * If the Game Object renders, it will be added to the Display List. + * If it has a `preUpdate` method, it will be added to the Update List. + * + * @method Phaser.GameObjects.GameObjectFactory#existing + * @since 3.0.0 + * + * @generic {(Phaser.GameObjects.GameObject|Phaser.GameObjects.Group|Phaser.GameObjects.Layer)} G - [child,$return] + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.Group|Phaser.GameObjects.Layer)} child - The child to be added to this Scene. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was added. + */ + existing: function (child) + { + if (child.renderCanvas || child.renderWebGL) + { + this.displayList.add(child); + } + + // For when custom objects have overridden `preUpdate` but don't hook into the ADDED_TO_SCENE event: + // Adding to the list multiple times is safe, as it won't add duplicates into the list anyway. + if (child.preUpdate) + { + this.updateList.add(child); + } + + return child; + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.GameObjects.GameObjectFactory#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.GameObjects.GameObjectFactory#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + this.events = null; + + this.displayList = null; + this.updateList = null; + } + +}); + +/** + * Static method called directly by the Game Object factory functions. + * With this method you can register a custom GameObject factory in the GameObjectFactory, + * providing a name (`factoryType`) and the constructor (`factoryFunction`) in order + * to be called when you call to Phaser.Scene.add[ factoryType ] method. + * + * @method Phaser.GameObjects.GameObjectFactory.register + * @static + * @since 3.0.0 + * + * @param {string} factoryType - The key of the factory that you will use to call to Phaser.Scene.add[ factoryType ] method. + * @param {function} factoryFunction - The constructor function to be called when you invoke to the Phaser.Scene.add method. + */ +GameObjectFactory.register = function (factoryType, factoryFunction) +{ + if (!GameObjectFactory.prototype.hasOwnProperty(factoryType)) + { + GameObjectFactory.prototype[factoryType] = factoryFunction; + } +}; + +/** + * Static method called directly by the Game Object factory functions. + * With this method you can remove a custom GameObject factory registered in the GameObjectFactory, + * providing a its `factoryType`. + * + * @method Phaser.GameObjects.GameObjectFactory.remove + * @static + * @since 3.0.0 + * + * @param {string} factoryType - The key of the factory that you want to remove from the GameObjectFactory. + */ +GameObjectFactory.remove = function (factoryType) +{ + if (GameObjectFactory.prototype.hasOwnProperty(factoryType)) + { + delete GameObjectFactory.prototype[factoryType]; + } +}; + +PluginCache.register('GameObjectFactory', GameObjectFactory, 'add'); + +module.exports = GameObjectFactory; + + +/***/ }), + +/***/ 91296: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); + +var camMatrix = new TransformMatrix(); +var spriteMatrix = new TransformMatrix(); +var calcMatrix = new TransformMatrix(); +var camExternalMatrix = new TransformMatrix(); + +var result = { + camera: camMatrix, + sprite: spriteMatrix, + calc: calcMatrix, + cameraExternal: camExternalMatrix +}; + +/** + * Calculates the Transform Matrix of the given Game Object and Camera, factoring in + * the parent matrix if provided. + * + * Note that the object this results contains _references_ to the Transform Matrices, + * not new instances of them. Therefore, you should use their values immediately, or + * copy them to your own matrix, as they will be replaced as soon as another Game + * Object is rendered. + * + * @function Phaser.GameObjects.GetCalcMatrix + * @memberof Phaser.GameObjects + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} src - The Game Object to calculate the transform matrix for. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera being used to render the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - The transform matrix of the parent container, if any. + * @param {boolean} [ignoreCameraPosition=false] - Should the camera's translation be ignored? This is what moves a camera around on the screen, but it should be ignored when the camera is being rendered to a framebuffer. + * + * @return {Phaser.Types.GameObjects.GetCalcMatrixResults} The results object containing the updated transform matrices. + */ +var GetCalcMatrix = function (src, camera, parentMatrix, ignoreCameraPosition) +{ + if (ignoreCameraPosition) + { + camExternalMatrix.loadIdentity(); + } + else + { + camExternalMatrix.copyFrom(camera.matrixExternal); + } + + camMatrix.copyWithScrollFactorFrom( + ignoreCameraPosition ? camera.matrix : camera.matrixCombined, + camera.scrollX, camera.scrollY, + src.scrollFactorX, src.scrollFactorY + ); + + calcMatrix.copyFrom(camMatrix); + + if (parentMatrix) + { + calcMatrix.multiply(parentMatrix); + } + + spriteMatrix.applyITRS(src.x, src.y, src.rotation, src.scaleX, src.scaleY); + + calcMatrix.multiply(spriteMatrix); + + return result; +}; + +module.exports = GetCalcMatrix; + + +/***/ }), + +/***/ 45027: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var ProcessQueue = __webpack_require__(25774); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * The Update List plugin. + * + * Update Lists belong to a Scene and maintain the list Game Objects to be updated every frame. + * + * Some or all of these Game Objects may also be part of the Scene's [Display List]{@link Phaser.GameObjects.DisplayList}, for Rendering. + * + * @class UpdateList + * @extends Phaser.Structs.ProcessQueue. + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that the Update List belongs to. + */ +var UpdateList = new Class({ + + Extends: ProcessQueue, + + initialize: + + function UpdateList (scene) + { + ProcessQueue.call(this); + + // No duplicates in this list + this.checkQueue = true; + + /** + * The Scene that the Update List belongs to. + * + * @name Phaser.GameObjects.UpdateList#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The Scene's Systems. + * + * @name Phaser.GameObjects.UpdateList#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * The `pending` list is a selection of items which are due to be made 'active' in the next update. + * + * @name Phaser.GameObjects.UpdateList#_pending + * @type {Array.<*>} + * @private + * @default [] + * @since 3.20.0 + */ + + /** + * The `active` list is a selection of items which are considered active and should be updated. + * + * @name Phaser.GameObjects.UpdateList#_active + * @type {Array.<*>} + * @private + * @default [] + * @since 3.20.0 + */ + + /** + * The `destroy` list is a selection of items that were active and are awaiting being destroyed in the next update. + * + * @name Phaser.GameObjects.UpdateList#_destroy + * @type {Array.<*>} + * @private + * @default [] + * @since 3.20.0 + */ + + /** + * The total number of items awaiting processing. + * + * @name Phaser.GameObjects.UpdateList#_toProcess + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.UpdateList#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.GameObjects.UpdateList#start + * @private + * @since 3.5.0 + */ + start: function () + { + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.PRE_UPDATE, this.update, this); + eventEmitter.on(SceneEvents.UPDATE, this.sceneUpdate, this); + eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The update step. + * + * Pre-updates every active Game Object in the list. + * + * @method Phaser.GameObjects.UpdateList#sceneUpdate + * @since 3.20.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time elapsed since the last frame. + */ + sceneUpdate: function (time, delta) + { + var list = this._active; + var length = list.length; + + for (var i = 0; i < length; i++) + { + var gameObject = list[i]; + + if (gameObject.active) + { + gameObject.preUpdate.call(gameObject, time, delta); + } + } + }, + + /** + * The Scene that owns this plugin is shutting down. + * + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.GameObjects.UpdateList#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + var i = this._active.length; + + while (i--) + { + this._active[i].destroy(true); + } + + i = this._pending.length; + + while (i--) + { + this._pending[i].destroy(true); + } + + i = this._destroy.length; + + while (i--) + { + this._destroy[i].destroy(true); + } + + this._toProcess = 0; + + this._pending = []; + this._active = []; + this._destroy = []; + + this.removeAllListeners(); + + var eventEmitter = this.systems.events; + + eventEmitter.off(SceneEvents.PRE_UPDATE, this.update, this); + eventEmitter.off(SceneEvents.UPDATE, this.sceneUpdate, this); + eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * + * We need to shutdown and then kill off all external references. + * + * @method Phaser.GameObjects.UpdateList#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.systems.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + } + + /** + * Adds a new item to the Update List. + * + * The item is added to the pending list and made active in the next update. + * + * @method Phaser.GameObjects.UpdateList#add + * @since 3.0.0 + * + * @param {*} item - The item to add to the queue. + * + * @return {*} The item that was added. + */ + + /** + * Removes an item from the Update List. + * + * The item is added to the pending destroy and fully removed in the next update. + * + * @method Phaser.GameObjects.UpdateList#remove + * @since 3.0.0 + * + * @param {*} item - The item to be removed from the queue. + * + * @return {*} The item that was removed. + */ + + /** + * Removes all active items from this Update List. + * + * All the items are marked as 'pending destroy' and fully removed in the next update. + * + * @method Phaser.GameObjects.UpdateList#removeAll + * @since 3.20.0 + * + * @return {this} This Update List object. + */ + + /** + * Update this queue. First it will process any items awaiting destruction, and remove them. + * + * Then it will check to see if there are any items pending insertion, and move them to an + * active state. Finally, it will return a list of active items for further processing. + * + * @method Phaser.GameObjects.UpdateList#update + * @since 3.0.0 + * + * @return {Array.<*>} A list of active items. + */ + + /** + * Returns the current list of active items. + * + * This method returns a reference to the active list array, not a copy of it. + * Therefore, be careful to not modify this array outside of the ProcessQueue. + * + * @method Phaser.GameObjects.UpdateList#getActive + * @since 3.0.0 + * + * @return {Array.<*>} A list of active items. + */ + + /** + * The number of entries in the active list. + * + * @name Phaser.GameObjects.UpdateList#length + * @type {number} + * @readonly + * @since 3.20.0 + */ +}); + +PluginCache.register('UpdateList', UpdateList, 'updateList'); + +module.exports = UpdateList; + + +/***/ }), + +/***/ 3217: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var tempTextureData = { + frame: null, + uvSource: null +}; + +var tempTransformData = { + quad: new Float32Array(8) +}; + +/** + * Renders one character of the Bitmap Text to WebGL. + * + * @function BatchChar + * @since 3.50.0 + * @private + * + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad} submitterNode - The Submitter Node which handles rendering the character as a quad. + * @param {Phaser.GameObjects.BitmapText} src - The BitmapText Game Object. + * @param {Phaser.Types.GameObjects.BitmapText.BitmapTextCharacter} char - The character to render. + * @param {Phaser.Types.GameObjects.BitmapText.BitmapFontCharacterData} glyph - The character glyph. + * @param {number} offsetX - The x offset. + * @param {number} offsetY - The y offset. + * @param {Phaser.GameObjects.Components.TransformMatrix} calcMatrix - The transform matrix. + * @param {object} tintData - The tint data to pass to the submitter node. + * @param {number} tintData.tintFill - The tint effect mode. + * @param {number} tintData.tintTopLeft - The top-left tint value. + * @param {number} tintData.tintTopRight - The top-right tint value. + * @param {number} tintData.tintBottomLeft - The bottom-left tint value. + * @param {number} tintData.tintBottomRight - The bottom-right tint value. + */ +var BatchChar = function (drawingContext, submitterNode, src, char, glyph, offsetX, offsetY, calcMatrix, tintData) +{ + tempTextureData.frame = src.frame; + tempTextureData.uvSource = glyph; + + var x = (char.x - src.displayOriginX) + offsetX; + var y = (char.y - src.displayOriginY) + offsetY; + + var xw = x + char.w; + var yh = y + char.h; + + var a = calcMatrix.a; + var b = calcMatrix.b; + var c = calcMatrix.c; + var d = calcMatrix.d; + var e = calcMatrix.e; + var f = calcMatrix.f; + + var tx0 = x * a + y * c + e; + var ty0 = x * b + y * d + f; + + var tx1 = x * a + yh * c + e; + var ty1 = x * b + yh * d + f; + + var tx2 = xw * a + yh * c + e; + var ty2 = xw * b + yh * d + f; + + var tx3 = xw * a + y * c + e; + var ty3 = xw * b + y * d + f; + + tempTransformData.quad[0] = tx0; + tempTransformData.quad[1] = ty0; + + tempTransformData.quad[2] = tx1; + tempTransformData.quad[3] = ty1; + + tempTransformData.quad[4] = tx2; + tempTransformData.quad[5] = ty2; + + tempTransformData.quad[6] = tx3; + tempTransformData.quad[7] = ty3; + + submitterNode.run( + drawingContext, + src, + undefined, + 0, + tempTextureData, + tempTransformData, + tintData + ); +}; + +module.exports = BatchChar; + + +/***/ }), + +/***/ 53048: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the full bounds, in local and world space, of a BitmapText Game Object. + * + * Returns a BitmapTextSize object that contains global and local variants of the Game Objects x and y coordinates and + * its width and height. Also includes an array of the line lengths and all word positions. + * + * The global position and size take into account the Game Object's position and scale. + * + * The local position and size just takes into account the font data. + * + * @function GetBitmapTextSize + * @since 3.0.0 + * @private + * + * @param {(Phaser.GameObjects.DynamicBitmapText|Phaser.GameObjects.BitmapText)} src - The BitmapText to calculate the bounds values for. + * @param {boolean} [round=false] - Whether to round the positions to the nearest integer. + * @param {boolean} [updateOrigin=false] - Whether to update the origin of the BitmapText after bounds calculations? + * @param {object} [out] - Object to store the results in, to save constant object creation. If not provided an empty object is returned. + * + * @return {Phaser.Types.GameObjects.BitmapText.BitmapTextSize} The calculated bounds values of the BitmapText. + */ +var GetBitmapTextSize = function (src, round, updateOrigin, out) +{ + if (updateOrigin === undefined) { updateOrigin = false; } + + if (out === undefined) + { + out = { + local: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + global: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + lines: { + shortest: 0, + longest: 0, + lengths: null, + height: 0 + }, + wrappedText: '', + words: [], + characters: [], + scaleX: 0, + scaleY: 0 + }; + + return out; + } + + var text = src.text; + var textLength = text.length; + var maxWidth = src.maxWidth; + var wordWrapCharCode = src.wordWrapCharCode; + + var bx = Number.MAX_VALUE; + var by = Number.MAX_VALUE; + var bw = 0; + var bh = 0; + + var chars = src.fontData.chars; + var lineHeight = src.fontData.lineHeight; + var letterSpacing = src.letterSpacing; + var lineSpacing = src.lineSpacing; + + var xAdvance = 0; + var yAdvance = 0; + + var charCode = 0; + + var glyph = null; + + var align = src._align; + + var x = 0; + var y = 0; + + var scale = (src.fontSize / src.fontData.size); + var sx = scale * src.scaleX; + var sy = scale * src.scaleY; + + var lastGlyph = null; + var lastCharCode = 0; + var lineWidths = []; + var shortestLine = Number.MAX_VALUE; + var longestLine = 0; + var currentLine = 0; + var currentLineWidth = 0; + + var i; + var j; + var lines; + var words = []; + var characters = []; + var current = null; + + // Measure the width of the text + var measureTextWidth = function (text, fontData) + { + var width = 0; + + for (var i = 0; i < text.length; i++) + { + var charCode = text.charCodeAt(i); + var glyph = fontData.chars[charCode]; + + if (glyph) + { + width += glyph.xAdvance; + } + } + + return width * sx; + }; + + // Scan for breach of maxWidth and insert carriage-returns + if (maxWidth > 0) + { + // Split the text into lines + lines = text.split('\n'); + var wrappedLines = []; + + // Loop through each line + for (i = 0; i < lines.length; i++) + { + var line = lines[i]; + var word = ''; + var wrappedLine = ''; + var lineToCheck = ''; + var lineWithWord = ''; + + // Loop through each character in a line + for (j = 0; j < line.length; j++) + { + charCode = line.charCodeAt(j); + + word += line[j]; + + // White space or end of line? + if (charCode === wordWrapCharCode || j === line.length - 1) + { + lineWithWord = lineToCheck + word; + + var textWidth = measureTextWidth(lineWithWord, src.fontData); + + if (textWidth <= maxWidth) + { + lineToCheck = lineWithWord; + } + else + { + // If the current word is too long to fit on a line, wrap it + // Remove trailing word wrap char to keep text length the same + wrappedLine = wrappedLine.slice(0, -1); + wrappedLine += (wrappedLine ? '\n' : '') + lineToCheck; + lineToCheck = word; + } + + word = ''; + } + } + + wrappedLine = wrappedLine.slice(0, -1); + wrappedLine += (wrappedLine ? '\n' : '') + lineToCheck; + wrappedLines.push(wrappedLine); + } + + text = wrappedLines.join('\n'); + + out.wrappedText = text; + + textLength = text.length; + } + + var charIndex = 0; + + for (i = 0; i < textLength; i++) + { + charCode = text.charCodeAt(i); + + if (charCode === 10) + { + if (current !== null) + { + words.push({ + word: current.word, + i: current.i, + x: current.x * sx, + y: current.y * sy, + w: current.w * sx, + h: current.h * sy + }); + + current = null; + } + + lastGlyph = null; + + lineWidths[currentLine] = currentLineWidth; + + if (currentLineWidth > longestLine) + { + longestLine = currentLineWidth; + } + + if (currentLineWidth < shortestLine) + { + shortestLine = currentLineWidth; + } + + currentLine++; + currentLineWidth = 0; + + xAdvance = 0; + yAdvance = (lineHeight + lineSpacing) * currentLine; + + continue; + } + + glyph = chars[charCode]; + + if (!glyph) + { + continue; + } + + x = xAdvance; + y = yAdvance; + + if (lastGlyph !== null) + { + var kerningOffset = glyph.kerning[lastCharCode]; + + x += (kerningOffset !== undefined) ? kerningOffset : 0; + } + + if (bx > x) + { + bx = x; + } + + if (by > y) + { + by = y; + } + + var gw = x + glyph.xAdvance; + var gh = y + lineHeight; + + if (bw < gw) + { + bw = gw; + } + + if (bh < gh) + { + bh = gh; + } + + var charWidth = glyph.xOffset + glyph.xAdvance + ((kerningOffset !== undefined) ? kerningOffset : 0); + + if (charCode === wordWrapCharCode) + { + if (current !== null) + { + words.push({ + word: current.word, + i: current.i, + x: current.x * sx, + y: current.y * sy, + w: current.w * sx, + h: current.h * sy + }); + + current = null; + } + } + else + { + if (current === null) + { + // We're starting a new word, recording the starting index, etc + current = { word: '', i: charIndex, x: xAdvance, y: yAdvance, w: 0, h: lineHeight }; + } + + current.word = current.word.concat(text[i]); + current.w += charWidth; + } + + characters.push({ + i: charIndex, + idx: i, + char: text[i], + code: charCode, + x: (glyph.xOffset + x) * scale, + y: (glyph.yOffset + yAdvance) * scale, + w: glyph.width * scale, + h: glyph.height * scale, + t: yAdvance * scale, + r: gw * scale, + b: lineHeight * scale, + line: currentLine, + glyph: glyph + }); + + xAdvance += glyph.xAdvance + letterSpacing + ((kerningOffset !== undefined) ? kerningOffset : 0); + lastGlyph = glyph; + lastCharCode = charCode; + currentLineWidth = gw * scale; + charIndex++; + } + + // Last word + if (current !== null) + { + words.push({ + word: current.word, + i: current.i, + x: current.x * sx, + y: current.y * sy, + w: current.w * sx, + h: current.h * sy + }); + } + + lineWidths[currentLine] = currentLineWidth; + + if (currentLineWidth > longestLine) + { + longestLine = currentLineWidth; + } + + if (currentLineWidth < shortestLine) + { + shortestLine = currentLineWidth; + } + + // Adjust all of the character positions based on alignment + if (align > 0) + { + for (var c = 0; c < characters.length; c++) + { + var currentChar = characters[c]; + + if (align === 1) + { + var ax1 = ((longestLine - lineWidths[currentChar.line]) / 2); + + currentChar.x += ax1; + currentChar.r += ax1; + } + else if (align === 2) + { + var ax2 = (longestLine - lineWidths[currentChar.line]); + + currentChar.x += ax2; + currentChar.r += ax2; + } + } + } + + var local = out.local; + var global = out.global; + + lines = out.lines; + + local.x = bx * scale; + local.y = by * scale; + local.width = bw * scale; + local.height = bh * scale; + + global.x = (src.x - src._displayOriginX) + (bx * sx); + global.y = (src.y - src._displayOriginY) + (by * sy); + + global.width = bw * sx; + global.height = bh * sy; + + lines.shortest = shortestLine; + lines.longest = longestLine; + lines.lengths = lineWidths; + + if (round) + { + local.x = Math.ceil(local.x); + local.y = Math.ceil(local.y); + local.width = Math.ceil(local.width); + local.height = Math.ceil(local.height); + + global.x = Math.ceil(global.x); + global.y = Math.ceil(global.y); + global.width = Math.ceil(global.width); + global.height = Math.ceil(global.height); + + lines.shortest = Math.ceil(shortestLine); + lines.longest = Math.ceil(longestLine); + } + + if (updateOrigin) + { + src._displayOriginX = (src.originX * local.width); + src._displayOriginY = (src.originY * local.height); + + global.x = src.x - (src._displayOriginX * src.scaleX); + global.y = src.y - (src._displayOriginY * src.scaleY); + + if (round) + { + global.x = Math.ceil(global.x); + global.y = Math.ceil(global.y); + } + } + + out.words = words; + out.characters = characters; + out.lines.height = lineHeight; + out.scale = scale; + out.scaleX = src.scaleX; + out.scaleY = src.scaleY; + + return out; +}; + +module.exports = GetBitmapTextSize; + + +/***/ }), + +/***/ 61327: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ParseXMLBitmapFont = __webpack_require__(21859); + +/** + * Parse an XML Bitmap Font from an Atlas. + * + * Adds the parsed Bitmap Font data to the cache with the `fontName` key. + * + * @function ParseFromAtlas + * @since 3.0.0 + * @private + * + * @param {Phaser.Scene} scene - The Scene to parse the Bitmap Font for. + * @param {string} fontName - The key of the font to add to the Bitmap Font cache. + * @param {string} textureKey - The key of the BitmapFont's texture. + * @param {string} frameKey - The key of the BitmapFont texture's frame. + * @param {string} xmlKey - The key of the XML data of the font to parse. + * @param {number} [xSpacing] - The x-axis spacing to add between each letter. + * @param {number} [ySpacing] - The y-axis spacing to add to the line height. + * + * @return {boolean} Whether the parsing was successful or not. + */ +var ParseFromAtlas = function (scene, fontName, textureKey, frameKey, xmlKey, xSpacing, ySpacing) +{ + var texture = scene.sys.textures.get(textureKey); + var frame = texture.get(frameKey); + var xml = scene.sys.cache.xml.get(xmlKey); + + if (frame && xml) + { + var data = ParseXMLBitmapFont(xml, frame, xSpacing, ySpacing, texture); + + scene.sys.cache.bitmapFont.add(fontName, { data: data, texture: textureKey, frame: frameKey, fromAtlas: true }); + + return true; + } + else + { + return false; + } +}; + +module.exports = ParseFromAtlas; + + +/***/ }), + +/***/ 6925: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetValue = __webpack_require__(35154); + +/** + * Parses a Retro Font configuration object so you can pass it to the BitmapText constructor + * and create a BitmapText object using a fixed-width retro font. + * + * @function Phaser.GameObjects.RetroFont.Parse + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - A reference to the Phaser Scene. + * @param {Phaser.Types.GameObjects.BitmapText.RetroFontConfig} config - The font configuration object. + * + * @return {Phaser.Types.GameObjects.BitmapText.BitmapFontData} A parsed Bitmap Font data entry for the Bitmap Font cache. + */ +var ParseRetroFont = function (scene, config) +{ + var w = config.width; + var h = config.height; + + var cx = Math.floor(w / 2); + var cy = Math.floor(h / 2); + + var letters = GetValue(config, 'chars', ''); + + if (letters === '') + { + return; + } + + var key = GetValue(config, 'image', ''); + + var frame = scene.sys.textures.getFrame(key); + var textureX = frame.cutX; + var textureY = frame.cutY; + var textureWidth = frame.source.width; + var textureHeight = frame.source.height; + + var offsetX = GetValue(config, 'offset.x', 0); + var offsetY = GetValue(config, 'offset.y', 0); + var spacingX = GetValue(config, 'spacing.x', 0); + var spacingY = GetValue(config, 'spacing.y', 0); + var lineSpacing = GetValue(config, 'lineSpacing', 0); + + var charsPerRow = GetValue(config, 'charsPerRow', null); + + if (charsPerRow === null) + { + charsPerRow = textureWidth / w; + + if (charsPerRow > letters.length) + { + charsPerRow = letters.length; + } + } + + var x = offsetX; + var y = offsetY; + + var data = { + retroFont: true, + font: key, + size: w, + lineHeight: h + lineSpacing, + chars: {} + }; + + var r = 0; + + for (var i = 0; i < letters.length; i++) + { + var charCode = letters.charCodeAt(i); + + var u0 = (textureX + x) / textureWidth; + var v0 = 1 - (textureY + y) / textureHeight; + var u1 = (textureX + x + w) / textureWidth; + var v1 = 1 - (textureY + y + h) / textureHeight; + + data.chars[charCode] = + { + x: x, + y: y, + width: w, + height: h, + centerX: cx, + centerY: cy, + xOffset: 0, + yOffset: 0, + xAdvance: w, + data: {}, + kerning: {}, + u0: u0, + v0: v0, + u1: u1, + v1: v1 + }; + + r++; + + if (r === charsPerRow) + { + r = 0; + x = offsetX; + y += h + spacingY; + } + else + { + x += w + spacingX; + } + } + + var entry = { + data: data, + frame: null, + texture: key + }; + + return entry; +}; + +module.exports = ParseRetroFont; + + +/***/ }), + +/***/ 21859: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Read an integer value from an XML Node. + * + * @function getValue + * @since 3.0.0 + * @private + * + * @param {Node} node - The XML Node. + * @param {string} attribute - The attribute to read. + * + * @return {number} The parsed value. + */ +function getValue (node, attribute) +{ + return parseInt(node.getAttribute(attribute), 10); +} + +/** + * Parse an XML font to Bitmap Font data for the Bitmap Font cache. + * + * @function ParseXMLBitmapFont + * @since 3.0.0 + * @private + * + * @param {XMLDocument} xml - The XML Document to parse the font from. + * @param {Phaser.Textures.Frame} frame - The texture frame to take into account when creating the uv data. + * @param {number} [xSpacing=0] - The x-axis spacing to add between each letter. + * @param {number} [ySpacing=0] - The y-axis spacing to add to the line height. + * @param {Phaser.Textures.Texture} [texture] - If provided, each glyph in the Bitmap Font will be added to this texture as a frame. + * + * @return {Phaser.Types.GameObjects.BitmapText.BitmapFontData} The parsed Bitmap Font data. + */ +var ParseXMLBitmapFont = function (xml, frame, xSpacing, ySpacing, texture) +{ + if (xSpacing === undefined) { xSpacing = 0; } + if (ySpacing === undefined) { ySpacing = 0; } + + var textureX = frame.cutX; + var textureY = frame.cutY; + var textureWidth = frame.source.width; + var textureHeight = frame.source.height; + var sourceIndex = frame.sourceIndex; + + var data = {}; + var info = xml.getElementsByTagName('info')[0]; + var common = xml.getElementsByTagName('common')[0]; + + data.font = info.getAttribute('face'); + data.size = getValue(info, 'size'); + data.lineHeight = getValue(common, 'lineHeight') + ySpacing; + data.chars = {}; + + var letters = xml.getElementsByTagName('char'); + + var adjustForTrim = (frame !== undefined && frame.trimmed); + + if (adjustForTrim) + { + var top = frame.height; + var left = frame.width; + } + + for (var i = 0; i < letters.length; i++) + { + var node = letters[i]; + + var charCode = getValue(node, 'id'); + var letter = String.fromCharCode(charCode); + var gx = getValue(node, 'x'); + var gy = getValue(node, 'y'); + var gw = getValue(node, 'width'); + var gh = getValue(node, 'height'); + + // Handle frame trim issues + + if (adjustForTrim) + { + if (gx < left) + { + left = gx; + } + + if (gy < top) + { + top = gy; + } + } + + if (adjustForTrim && top !== 0 && left !== 0) + { + // Now we know the top and left coordinates of the glyphs in the original data + // so we can work out how much to adjust the glyphs by + + gx -= frame.x; + gy -= frame.y; + } + + var u0 = (textureX + gx) / textureWidth; + var v0 = 1 - (textureY + gy) / textureHeight; + var u1 = (textureX + gx + gw) / textureWidth; + var v1 = 1 - (textureY + gy + gh) / textureHeight; + + data.chars[charCode] = + { + x: gx, + y: gy, + width: gw, + height: gh, + centerX: Math.floor(gw / 2), + centerY: Math.floor(gh / 2), + xOffset: getValue(node, 'xoffset'), + yOffset: getValue(node, 'yoffset'), + xAdvance: getValue(node, 'xadvance') + xSpacing, + data: {}, + kerning: {}, + u0: u0, + v0: v0, + u1: u1, + v1: v1 + }; + + if (texture && gw !== 0 && gh !== 0) + { + var charFrame = texture.add(letter, sourceIndex, gx, gy, gw, gh); + + if (charFrame) + { + charFrame.setUVs(gw, gh, u0, v0, u1, v1); + } + } + } + + var kernings = xml.getElementsByTagName('kerning'); + + for (i = 0; i < kernings.length; i++) + { + var kern = kernings[i]; + + var first = getValue(kern, 'first'); + var second = getValue(kern, 'second'); + var amount = getValue(kern, 'amount'); + + data.chars[second].kerning[first] = amount; + } + + return data; +}; + +module.exports = ParseXMLBitmapFont; + + +/***/ }), + +/***/ 196: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RETRO_FONT_CONST = __webpack_require__(87662); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.GameObjects.RetroFont + * @since 3.6.0 + */ + +var RetroFont = { Parse: __webpack_require__(6925) }; + +// Merge in the consts +RetroFont = Extend(false, RetroFont, RETRO_FONT_CONST); + +module.exports = RetroFont; + + +/***/ }), + +/***/ 87662: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RETRO_FONT_CONST = { + + /** + * Text Set 1 = !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET1 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET1: ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~', + + /** + * Text Set 2 = !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET2 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET2: ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ', + + /** + * Text Set 3 = ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET3 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET3: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ', + + /** + * Text Set 4 = ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET4 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET4: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789', + + /** + * Text Set 5 = ABCDEFGHIJKLMNOPQRSTUVWXYZ.,/() '!?-*:0123456789 + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET5 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET5: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.,/() \'!?-*:0123456789', + + /** + * Text Set 6 = ABCDEFGHIJKLMNOPQRSTUVWXYZ!?:;0123456789"(),-.' + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET6 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET6: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ!?:;0123456789"(),-.\' ', + + /** + * Text Set 7 = AGMSY+:4BHNTZ!;5CIOU.?06DJPV,(17EKQW")28FLRX-'39 + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET7 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET7: 'AGMSY+:4BHNTZ!;5CIOU.?06DJPV,(17EKQW")28FLRX-\'39', + + /** + * Text Set 8 = 0123456789 .ABCDEFGHIJKLMNOPQRSTUVWXYZ + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET8 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET8: '0123456789 .ABCDEFGHIJKLMNOPQRSTUVWXYZ', + + /** + * Text Set 9 = ABCDEFGHIJKLMNOPQRSTUVWXYZ()-0123456789.:,'"?! + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET9 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET9: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ()-0123456789.:,\'"?!', + + /** + * Text Set 10 = ABCDEFGHIJKLMNOPQRSTUVWXYZ + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET10 + * @type {string} + * @since 3.6.0 + */ + TEXT_SET10: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + + /** + * Text Set 11 = ABCDEFGHIJKLMNOPQRSTUVWXYZ.,"-+!?()':;0123456789 + * + * @name Phaser.GameObjects.RetroFont.TEXT_SET11 + * @since 3.6.0 + * @type {string} + */ + TEXT_SET11: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.,"-+!?()\':;0123456789' + +}; + +module.exports = RETRO_FONT_CONST; + + +/***/ }), + +/***/ 2638: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BitmapText = __webpack_require__(22186); +var Class = __webpack_require__(83419); +var Render = __webpack_require__(12310); + +/** + * @classdesc + * BitmapText objects work by taking a texture file and an XML or JSON file that describes the font structure. + * + * During rendering for each letter of the text is rendered to the display, proportionally spaced out and aligned to + * match the font structure. + * + * Dynamic Bitmap Text objects are different from Static Bitmap Text in that they invoke a callback for each + * letter being rendered during the render pass. This callback allows you to manipulate the properties of + * each letter being rendered, such as its position, scale or tint, allowing you to create interesting effects + * like jiggling text, which can't be done with Static text. This means that Dynamic Text takes more processing + * time, so only use them if you require the callback ability they have. + * + * BitmapText objects are less flexible than Text objects, in that they have less features such as shadows, fills and the ability + * to use Web Fonts, however you trade this flexibility for rendering speed. You can also create visually compelling BitmapTexts by + * processing the font texture in an image editor, applying fills and any other effects required. + * + * To create multi-line text insert \r, \n or \r\n escape codes into the text string. + * + * To create a BitmapText data files you need a 3rd party app such as: + * + * BMFont (Windows, free): {@link http://www.angelcode.com/products/bmfont/|http://www.angelcode.com/products/bmfont/} + * Glyph Designer (OS X, commercial): {@link http://www.71squared.com/en/glyphdesigner|http://www.71squared.com/en/glyphdesigner} + * Snow BMF (Web-based, free): {@link https://snowb.org//|https://snowb.org/} + * Littera (Flash-based, free): {@link http://kvazars.com/littera/|http://kvazars.com/littera/} + * + * For most use cases it is recommended to use XML. If you wish to use JSON, the formatting should be equal to the result of + * converting a valid XML file through the popular X2JS library. An online tool for conversion can be found here: {@link http://codebeautify.org/xmltojson|http://codebeautify.org/xmltojson} + * + * @class DynamicBitmapText + * @extends Phaser.GameObjects.BitmapText + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. It can only belong to one Scene at any given time. + * @param {number} x - The x coordinate of this Game Object in world space. + * @param {number} y - The y coordinate of this Game Object in world space. + * @param {string} font - The key of the font to use from the Bitmap Font cache. + * @param {(string|string[])} [text] - The string, or array of strings, to be set as the content of this Bitmap Text. + * @param {number} [size] - The font size of this Bitmap Text. + * @param {number} [align=0] - The alignment of the text in a multi-line BitmapText object. + */ +var DynamicBitmapText = new Class({ + + Extends: BitmapText, + + Mixins: [ + Render + ], + + initialize: + + function DynamicBitmapText (scene, x, y, font, text, size, align) + { + BitmapText.call(this, scene, x, y, font, text, size, align); + + this.type = 'DynamicBitmapText'; + + /** + * The horizontal scroll position of the Bitmap Text. + * + * @name Phaser.GameObjects.DynamicBitmapText#scrollX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.scrollX = 0; + + /** + * The vertical scroll position of the Bitmap Text. + * + * @name Phaser.GameObjects.DynamicBitmapText#scrollY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.scrollY = 0; + + /** + * The crop width of the Bitmap Text. + * + * @name Phaser.GameObjects.DynamicBitmapText#cropWidth + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.cropWidth = 0; + + /** + * The crop height of the Bitmap Text. + * + * @name Phaser.GameObjects.DynamicBitmapText#cropHeight + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.cropHeight = 0; + + /** + * A callback that alters how each character of the Bitmap Text is rendered. + * + * @name Phaser.GameObjects.DynamicBitmapText#displayCallback + * @type {Phaser.Types.GameObjects.BitmapText.DisplayCallback} + * @since 3.0.0 + */ + this.displayCallback; + + /** + * The data object that is populated during rendering, then passed to the displayCallback. + * You should modify this object then return it back from the callback. It's updated values + * will be used to render the specific glyph. + * + * Please note that if you need a reference to this object locally in your game code then you + * should shallow copy it, as it's updated and re-used for every glyph in the text. + * + * @name Phaser.GameObjects.DynamicBitmapText#callbackData + * @type {Phaser.Types.GameObjects.BitmapText.DisplayCallbackConfig} + * @since 3.11.0 + */ + this.callbackData = { + parent: this, + color: 0, + tint: { + topLeft: 0, + topRight: 0, + bottomLeft: 0, + bottomRight: 0 + }, + index: 0, + charCode: 0, + x: 0, + y: 0, + scale: 0, + rotation: 0, + data: 0 + }; + }, + + /** + * Set the crop size of this Bitmap Text. + * + * @method Phaser.GameObjects.DynamicBitmapText#setSize + * @since 3.0.0 + * + * @param {number} width - The width of the crop. + * @param {number} height - The height of the crop. + * + * @return {this} This Game Object. + */ + setSize: function (width, height) + { + this.cropWidth = width; + this.cropHeight = height; + + return this; + }, + + /** + * Set a callback that alters how each character of the Bitmap Text is rendered. + * + * The callback receives a {@link Phaser.Types.GameObjects.BitmapText.DisplayCallbackConfig} object that contains information about the character that's + * about to be rendered. + * + * It should return an object with `x`, `y`, `scale` and `rotation` properties that will be used instead of the + * usual values when rendering. + * + * @method Phaser.GameObjects.DynamicBitmapText#setDisplayCallback + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.BitmapText.DisplayCallback} callback - The display callback to set. + * + * @return {this} This Game Object. + */ + setDisplayCallback: function (callback) + { + this.displayCallback = callback; + + return this; + }, + + /** + * Set the horizontal scroll position of this Bitmap Text. + * + * @method Phaser.GameObjects.DynamicBitmapText#setScrollX + * @since 3.0.0 + * + * @param {number} value - The horizontal scroll position to set. + * + * @return {this} This Game Object. + */ + setScrollX: function (value) + { + this.scrollX = value; + + return this; + }, + + /** + * Set the vertical scroll position of this Bitmap Text. + * + * @method Phaser.GameObjects.DynamicBitmapText#setScrollY + * @since 3.0.0 + * + * @param {number} value - The vertical scroll position to set. + * + * @return {this} This Game Object. + */ + setScrollY: function (value) + { + this.scrollY = value; + + return this; + } + +}); + +module.exports = DynamicBitmapText; + + +/***/ }), + +/***/ 86741: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.DynamicBitmapText#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.DynamicBitmapText} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var DynamicBitmapTextCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + var text = src._text; + var textLength = text.length; + + var ctx = renderer.currentContext; + + if (textLength === 0 || !SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + return; + } + + camera.addToRenderList(src); + + var textureFrame = src.fromAtlas + ? src.frame + : src.texture.frames['__BASE']; + + var displayCallback = src.displayCallback; + var callbackData = src.callbackData; + + var chars = src.fontData.chars; + var lineHeight = src.fontData.lineHeight; + var letterSpacing = src._letterSpacing; + + var xAdvance = 0; + var yAdvance = 0; + + var charCode = 0; + + var glyph = null; + var glyphX = 0; + var glyphY = 0; + var glyphW = 0; + var glyphH = 0; + + var x = 0; + var y = 0; + + var lastGlyph = null; + var lastCharCode = 0; + + var image = src.frame.source.image; + + var textureX = textureFrame.cutX; + var textureY = textureFrame.cutY; + + var rotation = 0; + var scale = 0; + var baseScale = (src._fontSize / src.fontData.size); + + var align = src._align; + var currentLine = 0; + var lineOffsetX = 0; + + // Update the bounds - skipped internally if not dirty + src.getTextBounds(false); + + var lineData = src._bounds.lines; + + if (align === 1) + { + lineOffsetX = (lineData.longest - lineData.lengths[0]) / 2; + } + else if (align === 2) + { + lineOffsetX = (lineData.longest - lineData.lengths[0]); + } + + ctx.translate(-src.displayOriginX, -src.displayOriginY); + + var roundPixels = camera.roundPixels; + + if (src.cropWidth > 0 && src.cropHeight > 0) + { + ctx.beginPath(); + ctx.rect(0, 0, src.cropWidth, src.cropHeight); + ctx.clip(); + } + + for (var i = 0; i < textLength; i++) + { + // Reset the scale (in case the callback changed it) + scale = baseScale; + rotation = 0; + + charCode = text.charCodeAt(i); + + if (charCode === 10) + { + currentLine++; + + if (align === 1) + { + lineOffsetX = (lineData.longest - lineData.lengths[currentLine]) / 2; + } + else if (align === 2) + { + lineOffsetX = (lineData.longest - lineData.lengths[currentLine]); + } + + xAdvance = 0; + yAdvance += lineHeight; + lastGlyph = null; + + continue; + } + + glyph = chars[charCode]; + + if (!glyph) + { + continue; + } + + glyphX = textureX + glyph.x; + glyphY = textureY + glyph.y; + + glyphW = glyph.width; + glyphH = glyph.height; + + x = (glyph.xOffset + xAdvance) - src.scrollX; + y = (glyph.yOffset + yAdvance) - src.scrollY; + + if (lastGlyph !== null) + { + var kerningOffset = glyph.kerning[lastCharCode]; + x += (kerningOffset !== undefined) ? kerningOffset : 0; + } + + if (displayCallback) + { + callbackData.index = i; + callbackData.charCode = charCode; + callbackData.x = x; + callbackData.y = y; + callbackData.scale = scale; + callbackData.rotation = rotation; + callbackData.data = glyph.data; + + var output = displayCallback(callbackData); + + x = output.x; + y = output.y; + scale = output.scale; + rotation = output.rotation; + } + + x *= scale; + y *= scale; + + x += lineOffsetX; + + xAdvance += glyph.xAdvance + letterSpacing + ((kerningOffset !== undefined) ? kerningOffset : 0); + lastGlyph = glyph; + lastCharCode = charCode; + + // Nothing to render or a space? Then skip to the next glyph + if (glyphW === 0 || glyphH === 0 || charCode === 32) + { + continue; + } + + if (roundPixels) + { + x = Math.round(x); + y = Math.round(y); + } + + ctx.save(); + + ctx.translate(x, y); + + ctx.rotate(rotation); + + ctx.scale(scale, scale); + + ctx.drawImage(image, glyphX, glyphY, glyphW, glyphH, 0, 0, glyphW, glyphH); + + ctx.restore(); + } + + ctx.restore(); +}; + +module.exports = DynamicBitmapTextCanvasRenderer; + + +/***/ }), + +/***/ 11164: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BitmapText = __webpack_require__(2638); +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); + +/** + * Creates a new Dynamic Bitmap Text Game Object and returns it. + * + * Note: This method will only be available if the Dynamic Bitmap Text Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#dynamicBitmapText + * @since 3.0.0 + *² + * @param {Phaser.Types.GameObjects.BitmapText.BitmapTextConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.DynamicBitmapText} The Game Object that was created. + */ +GameObjectCreator.register('dynamicBitmapText', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var font = GetAdvancedValue(config, 'font', ''); + var text = GetAdvancedValue(config, 'text', ''); + var size = GetAdvancedValue(config, 'size', false); + + var bitmapText = new BitmapText(this.scene, 0, 0, font, text, size); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, bitmapText, config); + + return bitmapText; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 72566: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DynamicBitmapText = __webpack_require__(2638); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Dynamic Bitmap Text Game Object and adds it to the Scene. + * + * BitmapText objects work by taking a texture file and an XML or JSON file that describes the font structure. + * + * During rendering for each letter of the text is rendered to the display, proportionally spaced out and aligned to + * match the font structure. + * + * Dynamic Bitmap Text objects are different from Static Bitmap Text in that they invoke a callback for each + * letter being rendered during the render pass. This callback allows you to manipulate the properties of + * each letter being rendered, such as its position, scale or tint, allowing you to create interesting effects + * like jiggling text, which can't be done with Static text. This means that Dynamic Text takes more processing + * time, so only use them if you require the callback ability they have. + * + * BitmapText objects are less flexible than Text objects, in that they have less features such as shadows, fills and the ability + * to use Web Fonts, however you trade this flexibility for rendering speed. You can also create visually compelling BitmapTexts by + * processing the font texture in an image editor, applying fills and any other effects required. + * + * To create multi-line text insert \r, \n or \r\n escape codes into the text string. + * + * To create a BitmapText data files you need a 3rd party app such as: + * + * BMFont (Windows, free): http://www.angelcode.com/products/bmfont/ + * Glyph Designer (OS X, commercial): http://www.71squared.com/en/glyphdesigner + * Littera (Web-based, free): http://kvazars.com/littera/ + * + * For most use cases it is recommended to use XML. If you wish to use JSON, the formatting should be equal to the result of + * converting a valid XML file through the popular X2JS library. An online tool for conversion can be found here: http://codebeautify.org/xmltojson + * + * Note: This method will only be available if the Dynamic Bitmap Text Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#dynamicBitmapText + * @since 3.0.0 + * + * @param {number} x - The x position of the Game Object. + * @param {number} y - The y position of the Game Object. + * @param {string} font - The key of the font to use from the BitmapFont cache. + * @param {(string|string[])} [text] - The string, or array of strings, to be set as the content of this Bitmap Text. + * @param {number} [size] - The font size to set. + * + * @return {Phaser.GameObjects.DynamicBitmapText} The Game Object that was created. + */ +GameObjectFactory.register('dynamicBitmapText', function (x, y, font, text, size) +{ + return this.displayList.add(new DynamicBitmapText(this.scene, x, y, font, text, size)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 12310: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(73482); +} + +if (true) +{ + renderCanvas = __webpack_require__(86741); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 73482: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var TransformMatrix = __webpack_require__(61340); +var Utils = __webpack_require__(70554); + +var tempMatrix = new TransformMatrix(); + +var tempTextureData = { + frame: null, + uvSource: null +}; + +var tempTintData1 = { + tintEffect: 0, + tintTopLeft: 0, + tintTopRight: 0, + tintBottomLeft: 0, + tintBottomRight: 0 +}; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.DynamicBitmapText#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.DynamicBitmapText} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var DynamicBitmapTextWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var text = src.text; + var textLength = text.length; + + if (textLength === 0) + { + return; + } + + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var currentContext = drawingContext; + + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + var result = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas); + + var spriteMatrix = result.sprite; + var calcMatrix = result.calc; + + var fontMatrix = tempMatrix; + + var crop = (src.cropWidth > 0 || src.cropHeight > 0); + + if (crop) + { + currentContext = drawingContext.getClone(); + currentContext.setScissorEnable(true); + currentContext.setScissorBox( + calcMatrix.tx, + calcMatrix.ty, + src.cropWidth * calcMatrix.scaleX, + src.cropHeight * calcMatrix.scaleY + ); + currentContext.use(); + } + + tempTextureData.frame = src.frame; + + var tintEffect = src.tintFill; + var tintTL = Utils.getTintAppendFloatAlpha(src.tintTopLeft, src._alphaTL); + var tintTR = Utils.getTintAppendFloatAlpha(src.tintTopRight, src._alphaTR); + var tintBL = Utils.getTintAppendFloatAlpha(src.tintBottomLeft, src._alphaBL); + var tintBR = Utils.getTintAppendFloatAlpha(src.tintBottomRight, src._alphaBR); + + var xAdvance = 0; + var yAdvance = 0; + var charCode = 0; + var lastCharCode = 0; + var letterSpacing = src.letterSpacing; + var glyph; + var glyphW = 0; + var glyphH = 0; + var lastGlyph; + var scrollX = src.scrollX; + var scrollY = src.scrollY; + + var fontData = src.fontData; + var chars = fontData.chars; + var lineHeight = fontData.lineHeight; + var scale = (src.fontSize / fontData.size); + var rotation = 0; + + var align = src._align; + var currentLine = 0; + var lineOffsetX = 0; + + // Update the bounds - skipped internally if not dirty + var bounds = src.getTextBounds(false); + + // In case the method above changed it (word wrapping) + if (src.maxWidth > 0) + { + text = bounds.wrappedText; + textLength = text.length; + } + + var lineData = src._bounds.lines; + + if (align === 1) + { + lineOffsetX = (lineData.longest - lineData.lengths[0]) / 2; + } + else if (align === 2) + { + lineOffsetX = (lineData.longest - lineData.lengths[0]); + } + + var displayCallback = src.displayCallback; + var callbackData = src.callbackData; + + for (var i = 0; i < textLength; i++) + { + charCode = text.charCodeAt(i); + + // Carriage-return + if (charCode === 10) + { + currentLine++; + + if (align === 1) + { + lineOffsetX = (lineData.longest - lineData.lengths[currentLine]) / 2; + } + else if (align === 2) + { + lineOffsetX = (lineData.longest - lineData.lengths[currentLine]); + } + + xAdvance = 0; + yAdvance += lineHeight; + lastGlyph = null; + + continue; + } + + glyph = chars[charCode]; + + if (!glyph) + { + continue; + } + + tempTextureData.uvSource = glyph; + + glyphW = glyph.width; + glyphH = glyph.height; + + var x = (glyph.xOffset + xAdvance) - scrollX; + var y = (glyph.yOffset + yAdvance) - scrollY; + + if (lastGlyph !== null) + { + var kerningOffset = glyph.kerning[lastCharCode] || 0; + x += kerningOffset; + xAdvance += kerningOffset; + } + + xAdvance += glyph.xAdvance + letterSpacing; + lastGlyph = glyph; + lastCharCode = charCode; + + // Nothing to render or a space? Then skip to the next glyph + if (glyphW === 0 || glyphH === 0 || charCode === 32) + { + continue; + } + + scale = (src.fontSize / src.fontData.size); + rotation = 0; + + if (displayCallback) + { + callbackData.color = 0; + callbackData.tint.topLeft = tintTL; + callbackData.tint.topRight = tintTR; + callbackData.tint.bottomLeft = tintBL; + callbackData.tint.bottomRight = tintBR; + callbackData.index = i; + callbackData.charCode = charCode; + callbackData.x = x; + callbackData.y = y; + callbackData.scale = scale; + callbackData.rotation = rotation; + callbackData.data = glyph.data; + + var output = displayCallback(callbackData); + + x = output.x; + y = output.y; + scale = output.scale; + rotation = output.rotation; + + if (output.color) + { + tintTL = output.color; + tintTR = output.color; + tintBL = output.color; + tintBR = output.color; + } + else + { + tintTL = output.tint.topLeft; + tintTR = output.tint.topRight; + tintBL = output.tint.bottomLeft; + tintBR = output.tint.bottomRight; + } + + tintTL = Utils.getTintAppendFloatAlpha(tintTL, src._alphaTL); + tintTR = Utils.getTintAppendFloatAlpha(tintTR, src._alphaTR); + tintBL = Utils.getTintAppendFloatAlpha(tintBL, src._alphaBL); + tintBR = Utils.getTintAppendFloatAlpha(tintBR, src._alphaBR); + } + + tempTintData1.tintFill = tintEffect; + tempTintData1.tintTopLeft = tintTL; + tempTintData1.tintTopRight = tintTR; + tempTintData1.tintBottomLeft = tintBL; + tempTintData1.tintBottomRight = tintBR; + + x *= scale; + y *= scale; + + x -= src.displayOriginX; + y -= src.displayOriginY; + + x += lineOffsetX; + + fontMatrix.applyITRS(x, y, rotation, scale, scale); + + calcMatrix.multiply(fontMatrix, spriteMatrix); + + var xw = glyphW; + var yh = glyphH; + + var tx0 = spriteMatrix.e; + var ty0 = spriteMatrix.f; + + var tx1 = yh * spriteMatrix.c + spriteMatrix.e; + var ty1 = yh * spriteMatrix.d + spriteMatrix.f; + + var tx2 = xw * spriteMatrix.a + yh * spriteMatrix.c + spriteMatrix.e; + var ty2 = xw * spriteMatrix.b + yh * spriteMatrix.d + spriteMatrix.f; + + var tx3 = xw * spriteMatrix.a + spriteMatrix.e; + var ty3 = xw * spriteMatrix.b + spriteMatrix.f; + + submitterNode.run( + currentContext, + src, + undefined, + 0, + tempTextureData, + { + quad: [ tx0, ty0, tx1, ty1, tx2, ty2, tx3, ty3 ] + }, + tempTintData1 + ); + } + + if (crop) + { + drawingContext.use(); + } +}; + +module.exports = DynamicBitmapTextWebGLRenderer; + + +/***/ }), + +/***/ 22186: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultBitmapTextNodes = __webpack_require__(70972); +var Class = __webpack_require__(83419); +var Clamp = __webpack_require__(45319); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var GetBitmapTextSize = __webpack_require__(53048); +var ParseFromAtlas = __webpack_require__(61327); +var ParseXMLBitmapFont = __webpack_require__(21859); +var Rectangle = __webpack_require__(87841); +var Render = __webpack_require__(18658); + +/** + * @classdesc + * BitmapText objects work by taking a texture file and an XML or JSON file that describes the font structure. + * + * During rendering for each letter of the text is rendered to the display, proportionally spaced out and aligned to + * match the font structure. + * + * BitmapText objects are less flexible than Text objects, in that they have less features such as shadows, fills and the ability + * to use Web Fonts, however you trade this flexibility for rendering speed. You can also create visually compelling BitmapTexts by + * processing the font texture in an image editor, applying fills and any other effects required. + * + * To create multi-line text insert \r, \n or \r\n escape codes into the text string. + * + * To create a BitmapText data files you need a 3rd party app such as: + * + * BMFont (Windows, free): {@link http://www.angelcode.com/products/bmfont/|http://www.angelcode.com/products/bmfont/} + * Glyph Designer (OS X, commercial): {@link http://www.71squared.com/en/glyphdesigner|http://www.71squared.com/en/glyphdesigner} + * Snow BMF (Web-based, free): {@link https://snowb.org//|https://snowb.org/} + * Littera (Flash-based, free): {@link http://kvazars.com/littera/|http://kvazars.com/littera/} + * + * For most use cases it is recommended to use XML. If you wish to use JSON, the formatting should be equal to the result of + * converting a valid XML file through the popular X2JS library. An online tool for conversion can be found here: {@link http://codebeautify.org/xmltojson|http://codebeautify.org/xmltojson} + * + * @class BitmapText + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. It can only belong to one Scene at any given time. + * @param {number} x - The x coordinate of this Game Object in world space. + * @param {number} y - The y coordinate of this Game Object in world space. + * @param {string} font - The key of the font to use from the Bitmap Font cache. + * @param {(string|string[])} [text] - The string, or array of strings, to be set as the content of this Bitmap Text. + * @param {number} [size] - The font size of this Bitmap Text. + * @param {number} [align=0] - The alignment of the text in a multi-line BitmapText object. + */ +var BitmapText = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.Depth, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.Texture, + Components.Tint, + Components.Transform, + Components.Visible, + Render + ], + + initialize: + + function BitmapText (scene, x, y, font, text, size, align) + { + if (text === undefined) { text = ''; } + if (align === undefined) { align = 0; } + + GameObject.call(this, scene, 'BitmapText'); + + /** + * The key of the Bitmap Font used by this Bitmap Text. + * To change the font after creation please use `setFont`. + * + * @name Phaser.GameObjects.BitmapText#font + * @type {string} + * @readonly + * @since 3.0.0 + */ + this.font = font; + + var entry = this.scene.sys.cache.bitmapFont.get(font); + + if (!entry) + { + console.warn('Invalid BitmapText key: ' + font); + } + + /** + * The data of the Bitmap Font used by this Bitmap Text. + * + * @name Phaser.GameObjects.BitmapText#fontData + * @type {Phaser.Types.GameObjects.BitmapText.BitmapFontData} + * @readonly + * @since 3.0.0 + */ + this.fontData = entry.data; + + /** + * The text that this Bitmap Text object displays. + * + * @name Phaser.GameObjects.BitmapText#_text + * @type {string} + * @private + * @since 3.0.0 + */ + this._text = ''; + + /** + * The font size of this Bitmap Text. + * + * @name Phaser.GameObjects.BitmapText#_fontSize + * @type {number} + * @private + * @since 3.0.0 + */ + this._fontSize = size || this.fontData.size; + + /** + * Adds / Removes spacing between characters. + * + * Can be a negative or positive number. + * + * @name Phaser.GameObjects.BitmapText#_letterSpacing + * @type {number} + * @private + * @since 3.4.0 + */ + this._letterSpacing = 0; + + /** + * Adds / Removes line spacing in a multiline BitmapText object. + * + * Can be a negative or positive number. + * + * @name Phaser.GameObjects.BitmapText#_lineSpacing + * @type {number} + * @private + * @since 3.60.0 + */ + this._lineSpacing = 0; + + /** + * Controls the alignment of each line of text in this BitmapText object. + * Only has any effect when this BitmapText contains multiple lines of text, split with carriage-returns. + * Has no effect with single-lines of text. + * + * See the methods `setLeftAlign`, `setCenterAlign` and `setRightAlign`. + * + * 0 = Left aligned (default) + * 1 = Middle aligned + * 2 = Right aligned + * + * The alignment position is based on the longest line of text. + * + * @name Phaser.GameObjects.BitmapText#_align + * @type {number} + * @private + * @since 3.11.0 + */ + this._align = align; + + /** + * An object that describes the size of this Bitmap Text. + * + * @name Phaser.GameObjects.BitmapText#_bounds + * @type {Phaser.Types.GameObjects.BitmapText.BitmapTextSize} + * @private + * @since 3.0.0 + */ + this._bounds = GetBitmapTextSize(); + + /** + * An internal dirty flag for bounds calculation. + * + * @name Phaser.GameObjects.BitmapText#_dirty + * @type {boolean} + * @private + * @since 3.11.0 + */ + this._dirty = true; + + /** + * Internal cache var holding the maxWidth. + * + * @name Phaser.GameObjects.BitmapText#_maxWidth + * @type {number} + * @private + * @since 3.21.0 + */ + this._maxWidth = 0; + + /** + * The character code used to detect for word wrapping. + * Defaults to 32 (a space character). + * + * @name Phaser.GameObjects.BitmapText#wordWrapCharCode + * @type {number} + * @since 3.21.0 + */ + this.wordWrapCharCode = 32; + + /** + * Internal array holding the character tint color data. + * + * @name Phaser.GameObjects.BitmapText#charColors + * @type {array} + * @private + * @since 3.50.0 + */ + this.charColors = []; + + /** + * The horizontal offset of the drop shadow. + * + * You can set this directly, or use `Phaser.GameObjects.BitmapText#setDropShadow`. + * + * @name Phaser.GameObjects.BitmapText#dropShadowX + * @type {number} + * @since 3.50.0 + */ + this.dropShadowX = 0; + + /** + * The vertical offset of the drop shadow. + * + * You can set this directly, or use `Phaser.GameObjects.BitmapText#setDropShadow`. + * + * @name Phaser.GameObjects.BitmapText#dropShadowY + * @type {number} + * @since 3.50.0 + */ + this.dropShadowY = 0; + + /** + * The color of the drop shadow. + * + * You can set this directly, or use `Phaser.GameObjects.BitmapText#setDropShadow`. + * + * @name Phaser.GameObjects.BitmapText#dropShadowColor + * @type {number} + * @since 3.50.0 + */ + this.dropShadowColor = 0x000000; + + /** + * The alpha value of the drop shadow. + * + * You can set this directly, or use `Phaser.GameObjects.BitmapText#setDropShadow`. + * + * @name Phaser.GameObjects.BitmapText#dropShadowAlpha + * @type {number} + * @since 3.50.0 + */ + this.dropShadowAlpha = 0.5; + + /** + * Indicates whether the font texture is from an atlas or not. + * + * @name Phaser.GameObjects.BitmapText#fromAtlas + * @type {boolean} + * @since 3.54.0 + * @readonly + */ + this.fromAtlas = entry.fromAtlas; + + this.setTexture(entry.texture, entry.frame); + this.setPosition(x, y); + this.setOrigin(0, 0); + this.initRenderNodes(this._defaultRenderNodesMap); + + this.setText(text); + }, + + /** + * The default render nodes to initialize. + * + * @name Phaser.GameObjects.BitmapText#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultBitmapTextNodes; + } + }, + + /** + * Set the lines of text in this BitmapText to be left-aligned. + * This only has any effect if this BitmapText contains more than one line of text. + * + * @method Phaser.GameObjects.BitmapText#setLeftAlign + * @since 3.11.0 + * + * @return {this} This BitmapText Object. + */ + setLeftAlign: function () + { + this._align = BitmapText.ALIGN_LEFT; + + this._dirty = true; + + return this; + }, + + /** + * Set the lines of text in this BitmapText to be center-aligned. + * This only has any effect if this BitmapText contains more than one line of text. + * + * @method Phaser.GameObjects.BitmapText#setCenterAlign + * @since 3.11.0 + * + * @return {this} This BitmapText Object. + */ + setCenterAlign: function () + { + this._align = BitmapText.ALIGN_CENTER; + + this._dirty = true; + + return this; + }, + + /** + * Set the lines of text in this BitmapText to be right-aligned. + * This only has any effect if this BitmapText contains more than one line of text. + * + * @method Phaser.GameObjects.BitmapText#setRightAlign + * @since 3.11.0 + * + * @return {this} This BitmapText Object. + */ + setRightAlign: function () + { + this._align = BitmapText.ALIGN_RIGHT; + + this._dirty = true; + + return this; + }, + + /** + * Set the font size of this Bitmap Text. + * + * @method Phaser.GameObjects.BitmapText#setFontSize + * @since 3.0.0 + * + * @param {number} size - The font size to set. + * + * @return {this} This BitmapText Object. + */ + setFontSize: function (size) + { + this._fontSize = size; + + this._dirty = true; + + return this; + }, + + /** + * Sets the letter spacing between each character of this Bitmap Text. + * Can be a positive value to increase the space, or negative to reduce it. + * Spacing is applied after the kerning values have been set. + * + * @method Phaser.GameObjects.BitmapText#setLetterSpacing + * @since 3.4.0 + * + * @param {number} [spacing=0] - The amount of horizontal space to add between each character. + * + * @return {this} This BitmapText Object. + */ + setLetterSpacing: function (spacing) + { + if (spacing === undefined) { spacing = 0; } + + this._letterSpacing = spacing; + + this._dirty = true; + + return this; + }, + + /** + * Sets the line spacing value. This value is added to the font height to + * calculate the overall line height. + * + * Spacing can be a negative or positive number. + * + * Only has an effect if this BitmapText object contains multiple lines of text. + * + * @method Phaser.GameObjects.BitmapText#setLineSpacing + * @since 3.60.0 + * + * @param {number} [spacing=0] - The amount of space to add between each line in multi-line text. + * + * @return {this} This BitmapText Object. + */ + setLineSpacing: function (spacing) + { + if (spacing === undefined) { spacing = 0; } + + this.lineSpacing = spacing; + + return this; + }, + + /** + * Set the textual content of this BitmapText. + * + * An array of strings will be converted into multi-line text. Use the align methods to change multi-line alignment. + * + * @method Phaser.GameObjects.BitmapText#setText + * @since 3.0.0 + * + * @param {(string|string[])} value - The string, or array of strings, to be set as the content of this BitmapText. + * + * @return {this} This BitmapText Object. + */ + setText: function (value) + { + if (!value && value !== 0) + { + value = ''; + } + + if (Array.isArray(value)) + { + value = value.join('\n'); + } + + if (value !== this.text) + { + this._text = value.toString(); + + this._dirty = true; + + this.updateDisplayOrigin(); + } + + return this; + }, + + /** + * Sets a drop shadow effect on this Bitmap Text. + * + * This is a WebGL only feature and only works with Static Bitmap Text, not Dynamic. + * + * You can set the vertical and horizontal offset of the shadow, as well as the color and alpha. + * + * Once a shadow has been enabled you can modify the `dropShadowX` and `dropShadowY` properties of this + * Bitmap Text directly to adjust the position of the shadow in real-time. + * + * If you wish to clear the shadow, call this method with no parameters specified. + * + * @method Phaser.GameObjects.BitmapText#setDropShadow + * @webglOnly + * @since 3.50.0 + * + * @param {number} [x=0] - The horizontal offset of the drop shadow. + * @param {number} [y=0] - The vertical offset of the drop shadow. + * @param {number} [color=0x000000] - The color of the drop shadow, given as a hex value, i.e. `0x000000` for black. + * @param {number} [alpha=0.5] - The alpha of the drop shadow, given as a float between 0 and 1. This is combined with the Bitmap Text alpha as well. + * + * @return {this} This BitmapText Object. + */ + setDropShadow: function (x, y, color, alpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (color === undefined) { color = 0x000000; } + if (alpha === undefined) { alpha = 0.5; } + + this.dropShadowX = x; + this.dropShadowY = y; + this.dropShadowColor = color; + this.dropShadowAlpha = alpha; + + return this; + }, + + /** + * Sets a tint on a range of characters in this Bitmap Text, starting from the `start` parameter index + * and running for `length` quantity of characters. + * + * The `start` parameter can be negative. In this case, it starts at the end of the text and counts + * backwards `start` places. + * + * You can also pass in -1 as the `length` and it will tint all characters from `start` + * up until the end of the string. + + * Remember that spaces and punctuation count as characters. + * + * This is a WebGL only feature and only works with Static Bitmap Text, not Dynamic. + * + * The tint works by taking the pixel color values from the Bitmap Text texture, and then + * multiplying it by the color value of the tint. You can provide either one color value, + * in which case the whole character will be tinted in that color. Or you can provide a color + * per corner. The colors are blended together across the extent of the character range. + * + * To swap this from being an additive tint to a fill based tint, set the `tintFill` parameter to `true`. + * + * To modify the tint color once set, call this method again with new color values. + * + * Using `setWordTint` can override tints set by this function, and vice versa. + * + * To remove a tint call this method with just the `start`, and optionally, the `length` parameters defined. + * + * @method Phaser.GameObjects.BitmapText#setCharacterTint + * @webglOnly + * @since 3.50.0 + * + * @param {number} [start=0] - The starting character to begin the tint at. If negative, it counts back from the end of the text. + * @param {number} [length=1] - The number of characters to tint. Remember that spaces count as a character too. Pass -1 to tint all characters from `start` onwards. + * @param {boolean} [tintFill=false] - Use a fill-based tint (true), or an additive tint (false) + * @param {number} [topLeft=0xffffff] - The tint being applied to the top-left of the character. If not other values are given this value is applied evenly, tinting the whole character. + * @param {number} [topRight] - The tint being applied to the top-right of the character. + * @param {number} [bottomLeft] - The tint being applied to the bottom-left of the character. + * @param {number} [bottomRight] - The tint being applied to the bottom-right of the character. + * + * @return {this} This BitmapText Object. + */ + setCharacterTint: function (start, length, tintFill, topLeft, topRight, bottomLeft, bottomRight) + { + if (start === undefined) { start = 0; } + if (length === undefined) { length = 1; } + if (tintFill === undefined) { tintFill = false; } + if (topLeft === undefined) { topLeft = -1; } + + if (topRight === undefined) + { + topRight = topLeft; + bottomLeft = topLeft; + bottomRight = topLeft; + } + + var len = this.text.length; + + if (length === -1) + { + length = len; + } + + if (start < 0) + { + start = len + start; + } + + start = Clamp(start, 0, len - 1); + + var end = Clamp(start + length, start, len); + + var charColors = this.charColors; + + for (var i = start; i < end; i++) + { + var color = charColors[i]; + + if (topLeft === -1) + { + charColors[i] = null; + } + else + { + var tintEffect = (tintFill) ? 1 : 0; + + if (color) + { + color.tintEffect = tintEffect; + color.tintTL = topLeft; + color.tintTR = topRight; + color.tintBL = bottomLeft; + color.tintBR = bottomRight; + } + else + { + charColors[i] = { + tintEffect: tintEffect, + tintTL: topLeft, + tintTR: topRight, + tintBL: bottomLeft, + tintBR: bottomRight + }; + } + } + } + + return this; + }, + + /** + * Sets a tint on a matching word within this Bitmap Text. + * + * The `word` parameter can be either a string or a number. + * + * If a string, it will run a string comparison against the text contents, and if matching, + * it will tint the whole word. + * + * If a number, if till that word, based on its offset within the text contents. + * + * The `count` parameter controls how many words are replaced. Pass in -1 to replace them all. + * + * This parameter is ignored if you pass a number as the `word` to be searched for. + * + * This is a WebGL only feature and only works with Static Bitmap Text, not Dynamic. + * + * The tint works by taking the pixel color values from the Bitmap Text texture, and then + * multiplying it by the color value of the tint. You can provide either one color value, + * in which case the whole character will be tinted in that color. Or you can provide a color + * per corner. The colors are blended together across the extent of the character range. + * + * To swap this from being an additive tint to a fill based tint, set the `tintFill` parameter to `true`. + * + * To modify the tint color once set, call this method again with new color values. + * + * Using `setCharacterTint` can override tints set by this function, and vice versa. + * + * @method Phaser.GameObjects.BitmapText#setWordTint + * @webglOnly + * @since 3.50.0 + * + * @param {(string|number)} word - The word to search for. Either a string, or an index of the word in the words array. + * @param {number} [count=1] - The number of matching words to tint. Pass -1 to tint all matching words. + * @param {boolean} [tintFill=false] - Use a fill-based tint (true), or an additive tint (false) + * @param {number} [topLeft=0xffffff] - The tint being applied to the top-left of the word. If not other values are given this value is applied evenly, tinting the whole word. + * @param {number} [topRight] - The tint being applied to the top-right of the word. + * @param {number} [bottomLeft] - The tint being applied to the bottom-left of the word. + * @param {number} [bottomRight] - The tint being applied to the bottom-right of the word. + * + * @return {this} This BitmapText Object. + */ + setWordTint: function (word, count, tintFill, topLeft, topRight, bottomLeft, bottomRight) + { + if (count === undefined) { count = 1; } + + var bounds = this.getTextBounds(); + + var words = bounds.words; + + var wordIsNumber = (typeof(word) === 'number'); + + var total = 0; + + for (var i = 0; i < words.length; i++) + { + var lineword = words[i]; + + if ((wordIsNumber && i === word) || (!wordIsNumber && lineword.word === word)) + { + this.setCharacterTint(lineword.i, lineword.word.length, tintFill, topLeft, topRight, bottomLeft, bottomRight); + + total++; + + if (total === count) + { + return this; + } + } + } + + return this; + }, + + /** + * Calculate the bounds of this Bitmap Text. + * + * An object is returned that contains the position, width and height of the Bitmap Text in local and global + * contexts. + * + * Local size is based on just the font size and a [0, 0] position. + * + * Global size takes into account the Game Object's scale, world position and display origin. + * + * Also in the object is data regarding the length of each line, should this be a multi-line BitmapText. + * + * @method Phaser.GameObjects.BitmapText#getTextBounds + * @since 3.0.0 + * + * @param {boolean} [round=false] - Whether to round the results up to the nearest integer. + * + * @return {Phaser.Types.GameObjects.BitmapText.BitmapTextSize} An object that describes the size of this Bitmap Text. + */ + getTextBounds: function (round) + { + // local = The BitmapText based on fontSize and 0x0 coords + // global = The BitmapText, taking into account scale and world position + // lines = The BitmapText line data + + var bounds = this._bounds; + + if (this._dirty || round || this.scaleX !== bounds.scaleX || this.scaleY !== bounds.scaleY) + { + GetBitmapTextSize(this, round, true, bounds); + + this._dirty = false; + } + + return bounds; + }, + + /** + * Gets the character located at the given x/y coordinate within this Bitmap Text. + * + * The coordinates you pass in are translated into the local space of the + * Bitmap Text, however, it is up to you to first translate the input coordinates to world space. + * + * If you wish to use this in combination with an input event, be sure + * to pass in `Pointer.worldX` and `worldY` so they are in world space. + * + * In some cases, based on kerning, characters can overlap. When this happens, + * the first character in the word is returned. + * + * Note that this does not work for DynamicBitmapText if you have changed the + * character positions during render. It will only scan characters in their un-translated state. + * + * @method Phaser.GameObjects.BitmapText#getCharacterAt + * @since 3.50.0 + * + * @param {number} x - The x position to check. + * @param {number} y - The y position to check. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera which is being tested against. If not given will use the Scene default camera. + * + * @return {Phaser.Types.GameObjects.BitmapText.BitmapTextCharacter} The character object at the given position, or `null`. + */ + getCharacterAt: function (x, y, camera) + { + var point = this.getLocalPoint(x, y, null, camera); + + var bounds = this.getTextBounds(); + + var chars = bounds.characters; + + var tempRect = new Rectangle(); + + for (var i = 0; i < chars.length; i++) + { + var char = chars[i]; + + tempRect.setTo(char.x, char.t, char.r - char.x, char.b); + + if (tempRect.contains(point.x, point.y)) + { + return char; + } + } + + return null; + }, + + /** + * Updates the Display Origin cached values internally stored on this Game Object. + * You don't usually call this directly, but it is exposed for edge-cases where you may. + * + * @method Phaser.GameObjects.BitmapText#updateDisplayOrigin + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + updateDisplayOrigin: function () + { + this._dirty = true; + + this.getTextBounds(false); + + return this; + }, + + /** + * Changes the font this BitmapText is using to render. + * + * The new texture is loaded and applied to the BitmapText. The existing text, size and alignment are preserved, + * unless overridden via the arguments. + * + * @method Phaser.GameObjects.BitmapText#setFont + * @since 3.11.0 + * + * @param {string} font - The key of the font to use from the Bitmap Font cache. + * @param {number} [size] - The font size of this Bitmap Text. If not specified the current size will be used. + * @param {number} [align=0] - The alignment of the text in a multi-line BitmapText object. If not specified the current alignment will be used. + * + * @return {this} This BitmapText Object. + */ + setFont: function (key, size, align) + { + if (size === undefined) { size = this._fontSize; } + if (align === undefined) { align = this._align; } + + var entry = this.scene.sys.cache.bitmapFont.get(key); + + if (entry) + { + this.font = key; + this.fontData = entry.data; + this._fontSize = size; + this._align = align; + this.fromAtlas = entry.fromAtlas === true; + + this.setTexture(entry.texture, entry.frame); + + GetBitmapTextSize(this, false, true, this._bounds); + } + + return this; + }, + + /** + * Sets the maximum display width of this BitmapText in pixels. + * + * If `BitmapText.text` is longer than `maxWidth` then the lines will be automatically wrapped + * based on the previous whitespace character found in the line. + * + * If no whitespace was found then no wrapping will take place and consequently the `maxWidth` value will not be honored. + * + * Disable maxWidth by setting the value to 0. + * + * You can set the whitespace character to be searched for by setting the `wordWrapCharCode` parameter or property. + * + * @method Phaser.GameObjects.BitmapText#setMaxWidth + * @since 3.21.0 + * + * @param {number} value - The maximum display width of this BitmapText in pixels. Set to zero to disable. + * @param {number} [wordWrapCharCode] - The character code to check for when word wrapping. Defaults to 32 (the space character). + * + * @return {this} This BitmapText Object. + */ + setMaxWidth: function (value, wordWrapCharCode) + { + this._maxWidth = value; + + this._dirty = true; + + if (wordWrapCharCode !== undefined) + { + this.wordWrapCharCode = wordWrapCharCode; + } + + return this; + }, + + /** + * Controls the alignment of each line of text in this BitmapText object. + * + * Only has any effect when this BitmapText contains multiple lines of text, split with carriage-returns. + * Has no effect with single-lines of text. + * + * See the methods `setLeftAlign`, `setCenterAlign` and `setRightAlign`. + * + * 0 = Left aligned (default) + * 1 = Middle aligned + * 2 = Right aligned + * + * The alignment position is based on the longest line of text. + * + * @name Phaser.GameObjects.BitmapText#align + * @type {number} + * @since 3.11.0 + */ + align: { + + set: function (value) + { + this._align = value; + this._dirty = true; + }, + + get: function () + { + return this._align; + } + + }, + + /** + * The text that this Bitmap Text object displays. + * + * You can also use the method `setText` if you want a chainable way to change the text content. + * + * @name Phaser.GameObjects.BitmapText#text + * @type {string} + * @since 3.0.0 + */ + text: { + + set: function (value) + { + this.setText(value); + }, + + get: function () + { + return this._text; + } + + }, + + /** + * The font size of this Bitmap Text. + * + * You can also use the method `setFontSize` if you want a chainable way to change the font size. + * + * @name Phaser.GameObjects.BitmapText#fontSize + * @type {number} + * @since 3.0.0 + */ + fontSize: { + + set: function (value) + { + this._fontSize = value; + this._dirty = true; + }, + + get: function () + { + return this._fontSize; + } + + }, + + /** + * Adds / Removes spacing between characters. + * + * Can be a negative or positive number. + * + * You can also use the method `setLetterSpacing` if you want a chainable way to change the letter spacing. + * + * @name Phaser.GameObjects.BitmapText#letterSpacing + * @type {number} + * @since 3.0.0 + */ + letterSpacing: { + + set: function (value) + { + this._letterSpacing = value; + this._dirty = true; + }, + + get: function () + { + return this._letterSpacing; + } + + }, + + /** + * Adds / Removes spacing between lines. + * + * Can be a negative or positive number. + * + * You can also use the method `setLineSpacing` if you want a chainable way to change the line spacing. + * + * @name Phaser.GameObjects.BitmapText#lineSpacing + * @type {number} + * @since 3.60.0 + */ + lineSpacing: { + + set: function (value) + { + this._lineSpacing = value; + this._dirty = true; + }, + + get: function () + { + return this._lineSpacing; + } + + }, + + /** + * The maximum display width of this BitmapText in pixels. + * + * If BitmapText.text is longer than maxWidth then the lines will be automatically wrapped + * based on the last whitespace character found in the line. + * + * If no whitespace was found then no wrapping will take place and consequently the maxWidth value will not be honored. + * + * Disable maxWidth by setting the value to 0. + * + * @name Phaser.GameObjects.BitmapText#maxWidth + * @type {number} + * @since 3.21.0 + */ + maxWidth: { + + set: function (value) + { + this._maxWidth = value; + this._dirty = true; + }, + + get: function () + { + return this._maxWidth; + } + + }, + + /** + * The width of this Bitmap Text. + * + * This property is read-only. + * + * @name Phaser.GameObjects.BitmapText#width + * @type {number} + * @readonly + * @since 3.0.0 + */ + width: { + + get: function () + { + this.getTextBounds(false); + + return this._bounds.global.width; + } + + }, + + /** + * The height of this Bitmap text. + * + * This property is read-only. + * + * @name Phaser.GameObjects.BitmapText#height + * @type {number} + * @readonly + * @since 3.0.0 + */ + height: { + + get: function () + { + this.getTextBounds(false); + + return this._bounds.global.height; + } + + }, + + /** + * The displayed width of this Bitmap Text. + * + * This value takes into account the scale factor. + * + * This property is read-only. + * + * @name Phaser.GameObjects.BitmapText#displayWidth + * @type {number} + * @readonly + * @since 3.60.0 + */ + displayWidth: { + + get: function () + { + return this.width; + } + + }, + + /** + * The displayed height of this Bitmap Text. + * + * This value takes into account the scale factor. + * + * This property is read-only. + * + * @name Phaser.GameObjects.BitmapText#displayHeight + * @type {number} + * @readonly + * @since 3.60.0 + */ + displayHeight: { + + get: function () + { + return this.height; + } + + }, + + /** + * Build a JSON representation of this Bitmap Text. + * + * @method Phaser.GameObjects.BitmapText#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.BitmapText.JSONBitmapText} A JSON representation of this Bitmap Text. + */ + toJSON: function () + { + var out = Components.ToJSON(this); + + // Extra data is added here + + var data = { + font: this.font, + text: this.text, + fontSize: this.fontSize, + letterSpacing: this.letterSpacing, + lineSpacing: this.lineSpacing, + align: this.align + }; + + out.data = data; + + return out; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.BitmapText#preDestroy + * @protected + * @since 3.50.0 + */ + preDestroy: function () + { + this.charColors.length = 0; + this._bounds = null; + this.fontData = null; + } + +}); + +/** + * Left align the text characters in a multi-line BitmapText object. + * + * @name Phaser.GameObjects.BitmapText.ALIGN_LEFT + * @type {number} + * @since 3.11.0 + */ +BitmapText.ALIGN_LEFT = 0; + +/** + * Center align the text characters in a multi-line BitmapText object. + * + * @name Phaser.GameObjects.BitmapText.ALIGN_CENTER + * @type {number} + * @since 3.11.0 + */ +BitmapText.ALIGN_CENTER = 1; + +/** + * Right align the text characters in a multi-line BitmapText object. + * + * @name Phaser.GameObjects.BitmapText.ALIGN_RIGHT + * @type {number} + * @since 3.11.0 + */ +BitmapText.ALIGN_RIGHT = 2; + +/** + * Parse an XML Bitmap Font from an Atlas. + * + * Adds the parsed Bitmap Font data to the cache with the `fontName` key. + * + * @method Phaser.GameObjects.BitmapText.ParseFromAtlas + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to parse the Bitmap Font for. + * @param {string} fontName - The key of the font to add to the Bitmap Font cache. + * @param {string} textureKey - The key of the BitmapFont's texture. + * @param {string} frameKey - The key of the BitmapFont texture's frame. + * @param {string} xmlKey - The key of the XML data of the font to parse. + * @param {number} [xSpacing] - The x-axis spacing to add between each letter. + * @param {number} [ySpacing] - The y-axis spacing to add to the line height. + * + * @return {boolean} Whether the parsing was successful or not. + */ +BitmapText.ParseFromAtlas = ParseFromAtlas; + +/** + * Parse an XML font to Bitmap Font data for the Bitmap Font cache. + * + * @method Phaser.GameObjects.BitmapText.ParseXMLBitmapFont + * @since 3.17.0 + * + * @param {XMLDocument} xml - The XML Document to parse the font from. + * @param {Phaser.Textures.Frame} frame - The texture frame to take into account when creating the uv data. + * @param {number} [xSpacing=0] - The x-axis spacing to add between each letter. + * @param {number} [ySpacing=0] - The y-axis spacing to add to the line height. + * + * @return {Phaser.Types.GameObjects.BitmapText.BitmapFontData} The parsed Bitmap Font data. + */ +BitmapText.ParseXMLBitmapFont = ParseXMLBitmapFont; + +module.exports = BitmapText; + + +/***/ }), + +/***/ 37289: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.BitmapText#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.BitmapText} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var BitmapTextCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + var text = src._text; + var textLength = text.length; + + var ctx = renderer.currentContext; + + if (textLength === 0 || !SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + return; + } + + camera.addToRenderList(src); + + var textureFrame = src.fromAtlas + ? src.frame + : src.texture.frames['__BASE']; + + var chars = src.fontData.chars; + var lineHeight = src.fontData.lineHeight; + var letterSpacing = src._letterSpacing; + var lineSpacing = src._lineSpacing; + + var xAdvance = 0; + var yAdvance = 0; + + var charCode = 0; + + var glyph = null; + var glyphX = 0; + var glyphY = 0; + var glyphW = 0; + var glyphH = 0; + + var x = 0; + var y = 0; + + var lastGlyph = null; + var lastCharCode = 0; + + var image = textureFrame.source.image; + + var textureX = textureFrame.cutX; + var textureY = textureFrame.cutY; + + var scale = (src._fontSize / src.fontData.size); + + var align = src._align; + var currentLine = 0; + var lineOffsetX = 0; + + // Update the bounds - skipped internally if not dirty + var bounds = src.getTextBounds(false); + + // In case the method above changed it (word wrapping) + if (src.maxWidth > 0) + { + text = bounds.wrappedText; + textLength = text.length; + } + + var lineData = src._bounds.lines; + + if (align === 1) + { + lineOffsetX = (lineData.longest - lineData.lengths[0]) / 2; + } + else if (align === 2) + { + lineOffsetX = (lineData.longest - lineData.lengths[0]); + } + + ctx.translate(-src.displayOriginX, -src.displayOriginY); + + var roundPixels = camera.roundPixels; + + for (var i = 0; i < textLength; i++) + { + charCode = text.charCodeAt(i); + + if (charCode === 10) + { + currentLine++; + + if (align === 1) + { + lineOffsetX = (lineData.longest - lineData.lengths[currentLine]) / 2; + } + else if (align === 2) + { + lineOffsetX = (lineData.longest - lineData.lengths[currentLine]); + } + + xAdvance = 0; + yAdvance += lineHeight + lineSpacing; + + lastGlyph = null; + + continue; + } + + glyph = chars[charCode]; + + if (!glyph) + { + continue; + } + + glyphX = textureX + glyph.x; + glyphY = textureY + glyph.y; + + glyphW = glyph.width; + glyphH = glyph.height; + + x = glyph.xOffset + xAdvance; + y = glyph.yOffset + yAdvance; + + if (lastGlyph !== null) + { + var kerningOffset = glyph.kerning[lastCharCode]; + x += (kerningOffset !== undefined) ? kerningOffset : 0; + } + + x *= scale; + y *= scale; + + x += lineOffsetX; + + xAdvance += glyph.xAdvance + letterSpacing + ((kerningOffset !== undefined) ? kerningOffset : 0); + lastGlyph = glyph; + lastCharCode = charCode; + + // Nothing to render or a space? Then skip to the next glyph + if (glyphW === 0 || glyphH === 0 || charCode === 32) + { + continue; + } + + if (roundPixels) + { + x = Math.round(x); + y = Math.round(y); + } + + ctx.save(); + + ctx.translate(x, y); + + ctx.scale(scale, scale); + + ctx.drawImage(image, glyphX, glyphY, glyphW, glyphH, 0, 0, glyphW, glyphH); + + ctx.restore(); + } + + ctx.restore(); +}; + +module.exports = BitmapTextCanvasRenderer; + + +/***/ }), + +/***/ 57336: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BitmapText = __webpack_require__(22186); +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var GetValue = __webpack_require__(35154); + +/** + * Creates a new Bitmap Text Game Object and returns it. + * + * Note: This method will only be available if the Bitmap Text Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#bitmapText + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.BitmapText.BitmapTextConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.BitmapText} The Game Object that was created. + */ +GameObjectCreator.register('bitmapText', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var font = GetValue(config, 'font', ''); + var text = GetAdvancedValue(config, 'text', ''); + var size = GetAdvancedValue(config, 'size', false); + var align = GetValue(config, 'align', 0); + + var bitmapText = new BitmapText(this.scene, 0, 0, font, text, size, align); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, bitmapText, config); + + return bitmapText; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 34914: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BitmapText = __webpack_require__(22186); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Bitmap Text Game Object and adds it to the Scene. + * + * BitmapText objects work by taking a texture file and an XML or JSON file that describes the font structure. + * + * During rendering for each letter of the text is rendered to the display, proportionally spaced out and aligned to + * match the font structure. + * + * BitmapText objects are less flexible than Text objects, in that they have less features such as shadows, fills and the ability + * to use Web Fonts, however you trade this flexibility for rendering speed. You can also create visually compelling BitmapTexts by + * processing the font texture in an image editor, applying fills and any other effects required. + * + * To create multi-line text insert \r, \n or \r\n escape codes into the text string. + * + * To create a BitmapText data files you need a 3rd party app such as: + * + * BMFont (Windows, free): http://www.angelcode.com/products/bmfont/ + * Glyph Designer (OS X, commercial): http://www.71squared.com/en/glyphdesigner + * Littera (Web-based, free): http://kvazars.com/littera/ + * + * For most use cases it is recommended to use XML. If you wish to use JSON, the formatting should be equal to the result of + * converting a valid XML file through the popular X2JS library. An online tool for conversion can be found here: http://codebeautify.org/xmltojson + * + * Note: This method will only be available if the Bitmap Text Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#bitmapText + * @since 3.0.0 + * + * @param {number} x - The x position of the Game Object. + * @param {number} y - The y position of the Game Object. + * @param {string} font - The key of the font to use from the BitmapFont cache. + * @param {(string|string[])} [text] - The string, or array of strings, to be set as the content of this Bitmap Text. + * @param {number} [size] - The font size to set. + * @param {number} [align=0] - The alignment of the text in a multi-line BitmapText object. + * + * @return {Phaser.GameObjects.BitmapText} The Game Object that was created. + */ +GameObjectFactory.register('bitmapText', function (x, y, font, text, size, align) +{ + return this.displayList.add(new BitmapText(this.scene, x, y, font, text, size, align)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 18658: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(33590); +} + +if (true) +{ + renderCanvas = __webpack_require__(37289); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 33590: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BatchChar = __webpack_require__(3217); +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); + +var tempTintData1 = { + tintEffect: 0, + tintTopLeft: 0, + tintTopRight: 0, + tintBottomLeft: 0, + tintBottomRight: 0 +}; + +var tempTintData2 = { + tintEffect: 0, + tintTopLeft: 0, + tintTopRight: 0, + tintBottomLeft: 0, + tintBottomRight: 0 +}; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.BitmapText#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.BitmapText} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var BitmapTextWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var text = src._text; + var textLength = text.length; + + if (textLength === 0) + { + return; + } + + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var charColors = src.charColors; + + var getTint = Utils.getTintAppendFloatAlpha; + + tempTintData1.tintFill = src.tintFill; + tempTintData1.tintTopLeft = getTint(src.tintTopLeft, src._alphaTL); + tempTintData1.tintTopRight = getTint(src.tintTopRight, src._alphaTR); + tempTintData1.tintBottomLeft = getTint(src.tintBottomLeft, src._alphaBL); + tempTintData1.tintBottomRight = getTint(src.tintBottomRight, src._alphaBR); + + // Update the bounds - skipped internally if not dirty + var bounds = src.getTextBounds(false); + + var i; + var char; + var glyph; + + var characters = bounds.characters; + + var dropShadowX = src.dropShadowX; + var dropShadowY = src.dropShadowY; + + var dropShadow = (dropShadowX !== 0 || dropShadowY !== 0); + + if (dropShadow) + { + var srcShadowColor = src.dropShadowColor; + var srcShadowAlpha = src.dropShadowAlpha; + + tempTintData2.tintFill = 1; + tempTintData2.tintTopLeft = getTint(srcShadowColor, srcShadowAlpha * src._alphaTL); + tempTintData2.tintTopRight = getTint(srcShadowColor, srcShadowAlpha * src._alphaTR); + tempTintData2.tintBottomLeft = getTint(srcShadowColor, srcShadowAlpha * src._alphaBL); + tempTintData2.tintBottomRight = getTint(srcShadowColor, srcShadowAlpha * src._alphaBR); + + for (i = 0; i < characters.length; i++) + { + char = characters[i]; + glyph = char.glyph; + + if (char.code === 32 || glyph.width === 0 || glyph.height === 0) + { + continue; + } + + BatchChar(drawingContext, submitterNode, src, char, glyph, dropShadowX, dropShadowY, calcMatrix, tempTintData2); + } + } + + for (i = 0; i < characters.length; i++) + { + char = characters[i]; + glyph = char.glyph; + + if (char.code === 32 || glyph.width === 0 || glyph.height === 0) + { + continue; + } + + if (charColors[char.i]) + { + var color = charColors[char.i]; + + tempTintData2.tintFill = color.tintEffect; + tempTintData2.tintTopLeft = getTint(color.tintTL, src._alphaTL); + tempTintData2.tintTopRight = getTint(color.tintTR, src._alphaTR); + tempTintData2.tintBottomLeft = getTint(color.tintBL, src._alphaBL); + tempTintData2.tintBottomRight = getTint(color.tintBR, src._alphaBR); + + BatchChar(drawingContext, submitterNode, src, char, glyph, 0, 0, calcMatrix, tempTintData2); + } + else + { + BatchChar(drawingContext, submitterNode, src, char, glyph, 0, 0, calcMatrix, tempTintData1); + } + } +}; + +module.exports = BitmapTextWebGLRenderer; + + +/***/ }), + +/***/ 6107: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlitterRender = __webpack_require__(48011); +var Bob = __webpack_require__(46590); +var DefaultBlitterNodes = __webpack_require__(98682); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var Frame = __webpack_require__(4327); +var GameObject = __webpack_require__(95643); +var List = __webpack_require__(73162); + +/** + * @callback CreateCallback + * + * @param {Phaser.GameObjects.Bob} bob - The Bob that was created by the Blitter. + * @param {number} index - The position of the Bob within the Blitter display list. + */ + +/** + * @classdesc + * A Blitter Game Object. + * + * The Blitter Game Object is a special kind of container that creates, updates and manages Bob objects. + * Bobs are designed for rendering speed rather than flexibility. They consist of a texture, or frame from a texture, + * a position and an alpha value. You cannot scale or rotate them. They use a batched drawing method for speed + * during rendering. + * + * A Blitter Game Object has one texture bound to it. Bobs created by the Blitter can use any Frame from this + * Texture to render with, but they cannot use any other Texture. It is this single texture-bind that allows + * them their speed. + * + * If you have a need to blast a large volume of frames around the screen then Blitter objects are well worth + * investigating. They are especially useful for using as a base for your own special effects systems. + * + * @class Blitter + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. It can only belong to one Scene at any given time. + * @param {number} [x=0] - The x coordinate of this Game Object in world space. + * @param {number} [y=0] - The y coordinate of this Game Object in world space. + * @param {string} [texture='__DEFAULT'] - The key of the texture this Game Object will use for rendering. The Texture must already exist in the Texture Manager. + * @param {(string|number)} [frame=0] - The Frame of the Texture that this Game Object will use. Only set if the Texture has multiple frames, such as a Texture Atlas or Sprite Sheet. + */ +var Blitter = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.Depth, + Components.Lighting, + Components.Mask, + Components.RenderNodes, + Components.ScrollFactor, + Components.Size, + Components.Texture, + Components.Transform, + Components.Visible, + BlitterRender + ], + + initialize: + + function Blitter (scene, x, y, texture, frame) + { + GameObject.call(this, scene, 'Blitter'); + + this.setTexture(texture, frame); + this.setPosition(x, y); + this.initRenderNodes(this._defaultRenderNodesMap); + + /** + * The children of this Blitter. + * This List contains all of the Bob objects created by the Blitter. + * + * @name Phaser.GameObjects.Blitter#children + * @type {Phaser.Structs.List.} + * @since 3.0.0 + */ + this.children = new List(); + + /** + * A transient array that holds all of the Bobs that will be rendered this frame. + * The array is re-populated whenever the dirty flag is set. + * + * @name Phaser.GameObjects.Blitter#renderList + * @type {Phaser.GameObjects.Bob[]} + * @default [] + * @private + * @since 3.0.0 + */ + this.renderList = []; + + /** + * Is the Blitter considered dirty? + * A 'dirty' Blitter has had its child count changed since the last frame. + * + * @name Phaser.GameObjects.Blitter#dirty + * @type {boolean} + * @since 3.0.0 + */ + this.dirty = false; + }, + + /** + * The default render nodes to use for this Game Object. + * + * @name Phaser.GameObjects.Blitter#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultBlitterNodes; + } + }, + + /** + * Creates a new Bob in this Blitter. + * + * The Bob is created at the given coordinates, relative to the Blitter and uses the given frame. + * A Bob can use any frame belonging to the texture bound to the Blitter. + * + * @method Phaser.GameObjects.Blitter#create + * @since 3.0.0 + * + * @param {number} x - The x position of the Bob. Bob coordinate are relative to the position of the Blitter object. + * @param {number} y - The y position of the Bob. Bob coordinate are relative to the position of the Blitter object. + * @param {(string|number|Phaser.Textures.Frame)} [frame] - The Frame the Bob will use. It _must_ be part of the Texture the parent Blitter object is using. + * @param {boolean} [visible=true] - Should the created Bob render or not? + * @param {number} [index] - The position in the Blitters Display List to add the new Bob at. Defaults to the top of the list. + * + * @return {Phaser.GameObjects.Bob} The newly created Bob object. + */ + create: function (x, y, frame, visible, index) + { + if (visible === undefined) { visible = true; } + if (index === undefined) { index = this.children.length; } + + if (frame === undefined) + { + frame = this.frame; + } + else if (!(frame instanceof Frame)) + { + frame = this.texture.get(frame); + } + + var bob = new Bob(this, x, y, frame, visible); + + this.children.addAt(bob, index, false); + + this.dirty = true; + + return bob; + }, + + /** + * Creates multiple Bob objects within this Blitter and then passes each of them to the specified callback. + * + * @method Phaser.GameObjects.Blitter#createFromCallback + * @since 3.0.0 + * + * @param {CreateCallback} callback - The callback to invoke after creating a bob. It will be sent two arguments: The Bob and the index of the Bob. + * @param {number} quantity - The quantity of Bob objects to create. + * @param {(string|number|Phaser.Textures.Frame|string[]|number[]|Phaser.Textures.Frame[])} [frame] - The Frame the Bobs will use. It must be part of the Blitter Texture. + * @param {boolean} [visible=true] - Should the created Bob render or not? + * + * @return {Phaser.GameObjects.Bob[]} An array of Bob objects that were created. + */ + createFromCallback: function (callback, quantity, frame, visible) + { + var bobs = this.createMultiple(quantity, frame, visible); + + for (var i = 0; i < bobs.length; i++) + { + var bob = bobs[i]; + + callback.call(this, bob, i); + } + + return bobs; + }, + + /** + * Creates multiple Bobs in one call. + * + * The amount created is controlled by a combination of the `quantity` argument and the number of frames provided. + * + * If the quantity is set to 10 and you provide 2 frames, then 20 Bobs will be created. 10 with the first + * frame and 10 with the second. + * + * @method Phaser.GameObjects.Blitter#createMultiple + * @since 3.0.0 + * + * @param {number} quantity - The quantity of Bob objects to create. + * @param {(string|number|Phaser.Textures.Frame|string[]|number[]|Phaser.Textures.Frame[])} [frame] - The Frame the Bobs will use. It must be part of the Blitter Texture. + * @param {boolean} [visible=true] - Should the created Bob render or not? + * + * @return {Phaser.GameObjects.Bob[]} An array of Bob objects that were created. + */ + createMultiple: function (quantity, frame, visible) + { + if (frame === undefined) { frame = this.frame.name; } + if (visible === undefined) { visible = true; } + + if (!Array.isArray(frame)) + { + frame = [ frame ]; + } + + var bobs = []; + var _this = this; + + frame.forEach(function (singleFrame) + { + for (var i = 0; i < quantity; i++) + { + bobs.push(_this.create(0, 0, singleFrame, visible)); + } + }); + + return bobs; + }, + + /** + * Checks if the given child can render or not, by checking its `visible` and `alpha` values. + * + * @method Phaser.GameObjects.Blitter#childCanRender + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Bob} child - The Bob to check for rendering. + * + * @return {boolean} Returns `true` if the given child can render, otherwise `false`. + */ + childCanRender: function (child) + { + return (child.visible && child.alpha > 0); + }, + + /** + * Returns an array of Bobs to be rendered. + * If the Blitter is dirty then a new list is generated and stored in `renderList`. + * + * @method Phaser.GameObjects.Blitter#getRenderList + * @since 3.0.0 + * + * @return {Phaser.GameObjects.Bob[]} An array of Bob objects that will be rendered this frame. + */ + getRenderList: function () + { + if (this.dirty) + { + this.renderList = this.children.list.filter(this.childCanRender, this); + this.dirty = false; + } + + return this.renderList; + }, + + /** + * Removes all Bobs from the children List and clears the dirty flag. + * + * @method Phaser.GameObjects.Blitter#clear + * @since 3.0.0 + */ + clear: function () + { + this.children.removeAll(); + this.dirty = true; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.Blitter#preDestroy + * @protected + * @since 3.9.0 + */ + preDestroy: function () + { + this.children.destroy(); + + this.renderList = []; + } + +}); + +module.exports = Blitter; + + +/***/ }), + +/***/ 72396: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Blitter#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Blitter} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var BlitterCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + var list = src.getRenderList(); + + if (list.length === 0) + { + return; + } + + var ctx = renderer.currentContext; + + var alpha = camera.alpha * src.alpha; + + if (alpha === 0) + { + // Nothing to see, so abort early + return; + } + + camera.addToRenderList(src); + + // Blend Mode + Scale Mode + ctx.globalCompositeOperation = renderer.blendModes[src.blendMode]; + + ctx.imageSmoothingEnabled = !src.frame.source.scaleMode; + + var cameraScrollX = src.x - camera.scrollX * src.scrollFactorX; + var cameraScrollY = src.y - camera.scrollY * src.scrollFactorY; + + ctx.save(); + + if (parentMatrix) + { + parentMatrix.copyToContext(ctx); + } + + var roundPixels = camera.roundPixels; + + // Render bobs + for (var i = 0; i < list.length; i++) + { + var bob = list[i]; + var flip = (bob.flipX || bob.flipY); + var frame = bob.frame; + var cd = frame.canvasData; + var dx = frame.x; + var dy = frame.y; + var fx = 1; + var fy = 1; + + var bobAlpha = bob.alpha * alpha; + + if (bobAlpha === 0) + { + continue; + } + + ctx.globalAlpha = bobAlpha; + + if (!flip) + { + if (roundPixels) + { + dx = Math.round(dx); + dy = Math.round(dy); + } + + if (cd.width > 0 && cd.height > 0) + { + ctx.drawImage( + frame.source.image, + cd.x, + cd.y, + cd.width, + cd.height, + dx + bob.x + cameraScrollX, + dy + bob.y + cameraScrollY, + cd.width, + cd.height + ); + } + } + else + { + if (bob.flipX) + { + fx = -1; + dx -= cd.width; + } + + if (bob.flipY) + { + fy = -1; + dy -= cd.height; + } + + if (cd.width > 0 && cd.height > 0) + { + ctx.save(); + ctx.translate(bob.x + cameraScrollX, bob.y + cameraScrollY); + ctx.scale(fx, fy); + ctx.drawImage(frame.source.image, cd.x, cd.y, cd.width, cd.height, dx, dy, cd.width, cd.height); + ctx.restore(); + } + } + } + + ctx.restore(); +}; + +module.exports = BlitterCanvasRenderer; + + +/***/ }), + +/***/ 9403: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Blitter = __webpack_require__(6107); +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); + +/** + * Creates a new Blitter Game Object and returns it. + * + * Note: This method will only be available if the Blitter Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#blitter + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Blitter} The Game Object that was created. + */ +GameObjectCreator.register('blitter', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var frame = GetAdvancedValue(config, 'frame', null); + + var blitter = new Blitter(this.scene, 0, 0, key, frame); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, blitter, config); + + return blitter; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 12709: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Blitter = __webpack_require__(6107); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Blitter Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Blitter Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#blitter + * @since 3.0.0 + * + * @param {number} x - The x position of the Game Object. + * @param {number} y - The y position of the Game Object. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - The default Frame children of the Blitter will use. + * + * @return {Phaser.GameObjects.Blitter} The Game Object that was created. + */ +GameObjectFactory.register('blitter', function (x, y, texture, frame) +{ + return this.displayList.add(new Blitter(this.scene, x, y, texture, frame)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 48011: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(99485); +} + +if (true) +{ + renderCanvas = __webpack_require__(72396); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 99485: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); +var Utils = __webpack_require__(70554); + +var tempMatrix = new TransformMatrix(); +var tempTransformer = { + quad: new Float32Array(8) +}; +var tempTexturer = {}; +var tempTinter = {}; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Blitter#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Blitter} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var BlitterWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var list = src.getRenderList(); + var camera = drawingContext.camera; + var alpha = src.alpha; + + if (list.length === 0 || alpha === 0) + { + // Nothing to see, so abort early + return; + } + + camera.addToRenderList(src); + + var calcMatrix = tempMatrix.copyWithScrollFactorFrom( + camera.getViewMatrix(!drawingContext.useCanvas), + camera.scrollX, camera.scrollY, + src.scrollFactorX, src.scrollFactorY + ); + + if (parentMatrix) + { + calcMatrix.multiply(parentMatrix); + } + + var blitterX = src.x; + var blitterY = src.y; + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + for (var i = 0; i < list.length; i++) + { + var bob = list[i]; + var frame = bob.frame; + var bobAlpha = bob.alpha * alpha; + + if (bobAlpha === 0) + { + continue; + } + + var width = frame.width; + var height = frame.height; + + var x = blitterX + bob.x + frame.x; + var y = blitterY + bob.y + frame.y; + + if (bob.flipX) + { + width *= -1; + x += frame.width; + } + + if (bob.flipY) + { + height *= -1; + y += frame.height; + } + + calcMatrix.setQuad(x, y, x + width, y + height, tempTransformer.quad); + + tempTexturer.frame = frame; + tempTexturer.uvSource = frame; + + var tint = Utils.getTintAppendFloatAlpha(bob.tint, bobAlpha); + + tempTinter.tintTopLeft = tint; + tempTinter.tintBottomLeft = tint; + tempTinter.tintTopRight = tint; + tempTinter.tintBottomRight = tint; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + src, + parentMatrix, + 0, + tempTexturer, + tempTransformer, + tempTinter, + + // Optional normal map parameters. + undefined, + 0 + ); + } +}; + +module.exports = BlitterWebGLRenderer; + + +/***/ }), + +/***/ 46590: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Frame = __webpack_require__(4327); + +/** + * @classdesc + * A Bob Game Object. + * + * A Bob belongs to a Blitter Game Object. The Blitter is responsible for managing and rendering this object. + * + * A Bob has a position, alpha value and a frame from a texture that it uses to render with. You can also toggle + * the flipped and visible state of the Bob. The Frame the Bob uses to render can be changed dynamically, but it + * must be a Frame within the Texture used by the parent Blitter. + * + * Bob positions are relative to the Blitter parent. So if you move the Blitter parent, all Bob children will + * have their positions impacted by this change as well. + * + * You can manipulate Bob objects directly from your game code, but the creation and destruction of them should be + * handled via the Blitter parent. + * + * @class Bob + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Blitter} blitter - The parent Blitter object is responsible for updating this Bob. + * @param {number} x - The horizontal position of this Game Object in the world, relative to the parent Blitter position. + * @param {number} y - The vertical position of this Game Object in the world, relative to the parent Blitter position. + * @param {(string|number)} frame - The Frame this Bob will render with, as defined in the Texture the parent Blitter is using. + * @param {boolean} visible - Should the Bob render visible or not to start with? + */ +var Bob = new Class({ + + initialize: + + function Bob (blitter, x, y, frame, visible) + { + /** + * The Blitter object that this Bob belongs to. + * + * @name Phaser.GameObjects.Bob#parent + * @type {Phaser.GameObjects.Blitter} + * @since 3.0.0 + */ + this.parent = blitter; + + /** + * The x position of this Bob, relative to the x position of the Blitter. + * + * @name Phaser.GameObjects.Bob#x + * @type {number} + * @since 3.0.0 + */ + this.x = x; + + /** + * The y position of this Bob, relative to the y position of the Blitter. + * + * @name Phaser.GameObjects.Bob#y + * @type {number} + * @since 3.0.0 + */ + this.y = y; + + /** + * The frame that the Bob uses to render with. + * To change the frame use the `Bob.setFrame` method. + * + * @name Phaser.GameObjects.Bob#frame + * @type {Phaser.Textures.Frame} + * @protected + * @since 3.0.0 + */ + this.frame = frame; + + /** + * A blank object which can be used to store data related to this Bob in. + * + * @name Phaser.GameObjects.Bob#data + * @type {object} + * @default {} + * @since 3.0.0 + */ + this.data = {}; + + /** + * The tint value of this Bob. + * + * @name Phaser.GameObjects.Bob#tint + * @type {number} + * @default 0xffffff + * @since 3.20.0 + */ + this.tint = 0xffffff; + + /** + * The visible state of this Bob. + * + * @name Phaser.GameObjects.Bob#_visible + * @type {boolean} + * @private + * @since 3.0.0 + */ + this._visible = visible; + + /** + * The alpha value of this Bob. + * + * @name Phaser.GameObjects.Bob#_alpha + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + this._alpha = 1; + + /** + * The horizontally flipped state of the Bob. + * A Bob that is flipped horizontally will render inversed on the horizontal axis. + * Flipping always takes place from the middle of the texture. + * + * @name Phaser.GameObjects.Bob#flipX + * @type {boolean} + * @since 3.0.0 + */ + this.flipX = false; + + /** + * The vertically flipped state of the Bob. + * A Bob that is flipped vertically will render inversed on the vertical axis (i.e. upside down) + * Flipping always takes place from the middle of the texture. + * + * @name Phaser.GameObjects.Bob#flipY + * @type {boolean} + * @since 3.0.0 + */ + this.flipY = false; + + /** + * Private read-only property used to allow Bobs to have physics bodies. + * + * @name Phaser.GameObjects.Bob#hasTransformComponent + * @type {boolean} + * @private + * @readonly + * @since 3.60.0 + */ + this.hasTransformComponent = true; + }, + + /** + * Changes the Texture Frame being used by this Bob. + * The frame must be part of the Texture the parent Blitter is using. + * If no value is given it will use the default frame of the Blitter parent. + * + * @method Phaser.GameObjects.Bob#setFrame + * @since 3.0.0 + * + * @param {(string|number|Phaser.Textures.Frame)} [frame] - The frame to be used during rendering. + * + * @return {this} This Bob Game Object. + */ + setFrame: function (frame) + { + if (frame === undefined) + { + this.frame = this.parent.frame; + } + else if (frame instanceof Frame && frame.texture === this.parent.texture) + { + this.frame = frame; + } + else + { + this.frame = this.parent.texture.get(frame); + } + + return this; + }, + + /** + * Resets the horizontal and vertical flipped state of this Bob back to their default un-flipped state. + * + * @method Phaser.GameObjects.Bob#resetFlip + * @since 3.0.0 + * + * @return {this} This Bob Game Object. + */ + resetFlip: function () + { + this.flipX = false; + this.flipY = false; + + return this; + }, + + /** + * Resets this Bob. + * + * Changes the position to the values given, and optionally changes the frame. + * + * Also resets the flipX and flipY values, sets alpha back to 1 and visible to true. + * + * @method Phaser.GameObjects.Bob#reset + * @since 3.0.0 + * + * @param {number} x - The x position of the Bob. Bob coordinate are relative to the position of the Blitter object. + * @param {number} y - The y position of the Bob. Bob coordinate are relative to the position of the Blitter object. + * @param {(string|number|Phaser.Textures.Frame)} [frame] - The Frame the Bob will use. It _must_ be part of the Texture the parent Blitter object is using. + * + * @return {this} This Bob Game Object. + */ + reset: function (x, y, frame) + { + this.x = x; + this.y = y; + + this.flipX = false; + this.flipY = false; + + this._alpha = 1; + this._visible = true; + + this.parent.dirty = true; + + if (frame) + { + this.setFrame(frame); + } + + return this; + }, + + /** + * Changes the position of this Bob to the values given. + * + * @method Phaser.GameObjects.Bob#setPosition + * @since 3.20.0 + * + * @param {number} x - The x position of the Bob. Bob coordinate are relative to the position of the Blitter object. + * @param {number} y - The y position of the Bob. Bob coordinate are relative to the position of the Blitter object. + * + * @return {this} This Bob Game Object. + */ + setPosition: function (x, y) + { + this.x = x; + this.y = y; + + return this; + }, + + /** + * Sets the horizontal flipped state of this Bob. + * + * @method Phaser.GameObjects.Bob#setFlipX + * @since 3.0.0 + * + * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped. + * + * @return {this} This Bob Game Object. + */ + setFlipX: function (value) + { + this.flipX = value; + + return this; + }, + + /** + * Sets the vertical flipped state of this Bob. + * + * @method Phaser.GameObjects.Bob#setFlipY + * @since 3.0.0 + * + * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped. + * + * @return {this} This Bob Game Object. + */ + setFlipY: function (value) + { + this.flipY = value; + + return this; + }, + + /** + * Sets the horizontal and vertical flipped state of this Bob. + * + * @method Phaser.GameObjects.Bob#setFlip + * @since 3.0.0 + * + * @param {boolean} x - The horizontal flipped state. `false` for no flip, or `true` to be flipped. + * @param {boolean} y - The horizontal flipped state. `false` for no flip, or `true` to be flipped. + * + * @return {this} This Bob Game Object. + */ + setFlip: function (x, y) + { + this.flipX = x; + this.flipY = y; + + return this; + }, + + /** + * Sets the visibility of this Bob. + * + * An invisible Bob will skip rendering. + * + * @method Phaser.GameObjects.Bob#setVisible + * @since 3.0.0 + * + * @param {boolean} value - The visible state of the Game Object. + * + * @return {this} This Bob Game Object. + */ + setVisible: function (value) + { + this.visible = value; + + return this; + }, + + /** + * Set the Alpha level of this Bob. The alpha controls the opacity of the Game Object as it renders. + * Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque. + * + * A Bob with alpha 0 will skip rendering. + * + * @method Phaser.GameObjects.Bob#setAlpha + * @since 3.0.0 + * + * @param {number} value - The alpha value used for this Bob. Between 0 and 1. + * + * @return {this} This Bob Game Object. + */ + setAlpha: function (value) + { + this.alpha = value; + + return this; + }, + + /** + * Sets the tint of this Bob. + * + * @method Phaser.GameObjects.Bob#setTint + * @since 3.20.0 + * + * @param {number} value - The tint value used for this Bob. Between 0 and 0xffffff. + * + * @return {this} This Bob Game Object. + */ + setTint: function (value) + { + this.tint = value; + + return this; + }, + + /** + * Destroys this Bob instance. + * Removes itself from the Blitter and clears the parent, frame and data properties. + * + * @method Phaser.GameObjects.Bob#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.parent.dirty = true; + + this.parent.children.remove(this); + + this.parent = undefined; + this.frame = undefined; + this.data = undefined; + }, + + /** + * The visible state of the Bob. + * + * An invisible Bob will skip rendering. + * + * @name Phaser.GameObjects.Bob#visible + * @type {boolean} + * @since 3.0.0 + */ + visible: { + + get: function () + { + return this._visible; + }, + + set: function (value) + { + this.parent.dirty |= (this._visible !== value); + this._visible = value; + } + + }, + + /** + * The alpha value of the Bob, between 0 and 1. + * + * A Bob with alpha 0 will skip rendering. + * + * @name Phaser.GameObjects.Bob#alpha + * @type {number} + * @since 3.0.0 + */ + alpha: { + + get: function () + { + return this._alpha; + }, + + set: function (value) + { + this.parent.dirty |= ((this._alpha > 0) !== (value > 0)); + this._alpha = value; + } + + } + +}); + +module.exports = Bob; + + +/***/ }), + +/***/ 43451: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DrawingContext = __webpack_require__(87774); +var DefaultQuadNodes = __webpack_require__(30529); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var CaptureFrameRender = __webpack_require__(36683); + +/** + * @classdesc + * A CaptureFrame is a special type of GameObject that allows you to + * capture the current state of the render. + * For example, if you place a CaptureFrame between two other objects, + * it will capture the first object to a texture, but not the second. + * This is useful for full-scene post-processing prior to render completion, + * such as a layer of water. + * + * This is a WebGL only feature and is not available in Canvas mode. + * + * You must activate the `forceComposite` property of the Camera, + * or otherwise use this object within a framebuffer, to use this feature. + * Examples of framebuffer situations include Filters, DynamicTexture, + * and a camera with alpha between 0 and 1. + * + * This object does not render anything. It simply captures a texture + * from the current framebuffer at the moment it 'renders'. + * If you add filters to this object, it will capture the clear, temporary + * framebuffer used for the filter, not the main framebuffer. + * If you add filters to a Container that contains this object, + * it will capture only objects within that Container. + * If you set `visible` to `false`, it will just stop capturing. + * + * @example + * // Within a Scene's `create` method: + * + * // This image will be captured: + * var image1 = this.add.image(0, 0, 'image1'); + * + * // Enable framebuffer usage: + * this.cameras.main.setForceComposite(true); + * + * // Set up a CaptureFrame: + * var captureFrame = this.add.captureFrame('myCaptureFrame'); + * + * // This image will not be captured, and can display the captured image: + * var image2 = this.add.image(0, 0, 'myCaptureFrame'); + * // Add filters to image2 to distort the captured image. + * + * @class CaptureFrame + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 4.0.0 + * @webglOnly + * + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this CaptureFrame belongs. + * @param {string} key - The key of the texture to create from this CaptureFrame. + */ +var CaptureFrame = new Class({ + Extends: GameObject, + + Mixins: [ + Components.BlendMode, + Components.Depth, + Components.RenderNodes, + Components.Visible, + CaptureFrameRender + ], + + initialize: function CaptureFrame (scene, key) + { + GameObject.call(this, scene, 'CaptureFrame'); + + var renderer = scene.renderer; + + /** + * The drawing context of this CaptureFrame. + * This contains the WebGL framebuffer and texture data. + * + * @name Phaser.GameObjects.CaptureFrame#drawingContext + * @type {Phaser.Renderer.WebGL.DrawingContext} + * @webglOnly + * @since 4.0.0 + */ + this.drawingContext = new DrawingContext(renderer, { + width: renderer.width, + height: renderer.height + }); + + /** + * A texture containing the captured frame. + * This is updated when the GameObject renders. + * + * @name Phaser.GameObjects.CaptureFrame#captureTexture + * @type {Phaser.Textures.Texture} + * @webglOnly + * @since 4.0.0 + */ + this.captureTexture = scene.sys.textures.addGLTexture(key, this.drawingContext.texture); + + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.CaptureFrame#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultQuadNodes; + } + }, + + /** + * Set the alpha value of this CaptureFrame. + * This has no effect and is only present for compatibility with other Game Objects. + * + * @method Phaser.GameObjects.CaptureFrame#setAlpha + * @since 4.0.0 + * @webglOnly + * @param {number} alpha - The alpha value (not used). + * @returns {this} + */ + setAlpha: function (alpha) + { + return this; + }, + + /** + * Set the scroll factor of this CaptureFrame. + * This has no effect and is only present for compatibility with other Game Objects. + * + * @method Phaser.GameObjects.CaptureFrame#setScrollFactor + * @since 4.0.0 + * @webglOnly + * @param {number} x - The horizontal scroll factor (not used). + * @param {number} y - The vertical scroll factor (not used). + * @returns {this} + */ + setScrollFactor: function (x, y) + { + return this; + } +}); + +module.exports = CaptureFrame; + + +/***/ }), + +/***/ 23675: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var CaptureFrame = __webpack_require__(43451); + +/** + * Creates a new CaptureFrame Game Object and returns it. + * + * Note: This method will only be available if the CaptureFrame Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#captureFrame + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} config - The configuration object this Game Object will use to create itself. CaptureFrame only uses the `key`, `visible`, `depth`, and `add` properties. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.CaptureFrame} The Game Object that was created. + */ +GameObjectCreator.register('captureFrame', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var depth = GetAdvancedValue(config, 'depth', 0); + var key = GetAdvancedValue(config, 'key', null); + var visible = GetAdvancedValue(config, 'visible', true); + + var captureFrame = new CaptureFrame(this.scene, key); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + // This method does not use BuildGameObject, because most of the properties + // are not settable on a CaptureFrame, and it doesn't render. + captureFrame + .setDepth(depth) + .setVisible(visible); + if (config.add) + { + this.scene.sys.displayList.add(captureFrame); + } + + return captureFrame; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 20421: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CaptureFrame = __webpack_require__(43451); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new CaptureFrame Game Object and adds it to the Scene. + * + * Note: This method will only be available if the CaptureFrame Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#captureFrame + * @since 3.0.0 + * + * @param {string} key - The key of the texture to create from this CaptureFrame. + * + * @return {Phaser.GameObjects.CaptureFrame} The Game Object that was created. + */ +GameObjectFactory.register('captureFrame', function (key) +{ + return this.displayList.add(new CaptureFrame(this.scene, key)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 36683: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(82237); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 82237: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var _warned = false; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.CaptureFrame#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.CaptureFrame} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ +var CaptureFrameWebGLRenderer = function (renderer, src, drawingContext) +{ + if (drawingContext.useCanvas) + { + // We can't derive a texture from the canvas. + + if (!_warned) + { + _warned = true; + console.warn('CaptureFrame: Cannot capture from main canvas. Activate `forceComposite` on the camera to use this feature. This warning will now mute.'); + } + + return; + } + + drawingContext.camera.addToRenderList(src); + + var width = drawingContext.width; + var height = drawingContext.height; + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + // Ensure capture drawing context is the same size as the current drawing context. + src.drawingContext.resize(width, height); + + src.drawingContext.use(); + + // Draw current FBO to capture frame. + (customRenderNodes.BatchHandler || defaultRenderNodes.BatchHandler).batch( + src.drawingContext, + + // Texture. + drawingContext.texture, + + // Transformed quad in order TL, BL, TR, BR. + 0, height, + 0, 0, + width, height, + width, 0, + + // Texture coordinates in X, Y, Width, Height. + 0, 0, + 1, 1, + + // Tint color: + false, + + // Tint colors in order TL, BL, TR, BR. + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + + // Render options: + {} + ); + + src.drawingContext.release(); +}; + +module.exports = CaptureFrameWebGLRenderer; + + +/***/ }), + +/***/ 16005: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); + +// bitmask flag for GameObject.renderMask +var _FLAG = 2; // 0010 + +/** + * Provides methods used for setting the alpha properties of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.Alpha + * @since 3.0.0 + */ + +var Alpha = { + + /** + * Private internal value. Holds the global alpha value. + * + * @name Phaser.GameObjects.Components.Alpha#_alpha + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _alpha: 1, + + /** + * Private internal value. Holds the top-left alpha value. + * + * @name Phaser.GameObjects.Components.Alpha#_alphaTL + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _alphaTL: 1, + + /** + * Private internal value. Holds the top-right alpha value. + * + * @name Phaser.GameObjects.Components.Alpha#_alphaTR + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _alphaTR: 1, + + /** + * Private internal value. Holds the bottom-left alpha value. + * + * @name Phaser.GameObjects.Components.Alpha#_alphaBL + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _alphaBL: 1, + + /** + * Private internal value. Holds the bottom-right alpha value. + * + * @name Phaser.GameObjects.Components.Alpha#_alphaBR + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _alphaBR: 1, + + /** + * Clears all alpha values associated with this Game Object. + * + * Immediately sets the alpha levels back to 1 (fully opaque). + * + * @method Phaser.GameObjects.Components.Alpha#clearAlpha + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + clearAlpha: function () + { + return this.setAlpha(1); + }, + + /** + * Set the Alpha level of this Game Object. The alpha controls the opacity of the Game Object as it renders. + * Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque. + * + * If your game is running under WebGL you can optionally specify four different alpha values, each of which + * correspond to the four corners of the Game Object. Under Canvas only the `topLeft` value given is used. + * + * @method Phaser.GameObjects.Components.Alpha#setAlpha + * @since 3.0.0 + * + * @param {number} [topLeft=1] - The alpha value used for the top-left of the Game Object. If this is the only value given it's applied across the whole Game Object. + * @param {number} [topRight] - The alpha value used for the top-right of the Game Object. WebGL only. + * @param {number} [bottomLeft] - The alpha value used for the bottom-left of the Game Object. WebGL only. + * @param {number} [bottomRight] - The alpha value used for the bottom-right of the Game Object. WebGL only. + * + * @return {this} This Game Object instance. + */ + setAlpha: function (topLeft, topRight, bottomLeft, bottomRight) + { + if (topLeft === undefined) { topLeft = 1; } + + // Treat as if there is only one alpha value for the whole Game Object + if (topRight === undefined) + { + this.alpha = topLeft; + } + else + { + this._alphaTL = Clamp(topLeft, 0, 1); + this._alphaTR = Clamp(topRight, 0, 1); + this._alphaBL = Clamp(bottomLeft, 0, 1); + this._alphaBR = Clamp(bottomRight, 0, 1); + } + + return this; + }, + + /** + * The alpha value of the Game Object. + * + * This is a global value, impacting the entire Game Object, not just a region of it. + * + * @name Phaser.GameObjects.Components.Alpha#alpha + * @type {number} + * @since 3.0.0 + */ + alpha: { + + get: function () + { + return this._alpha; + }, + + set: function (value) + { + var v = Clamp(value, 0, 1); + + this._alpha = v; + this._alphaTL = v; + this._alphaTR = v; + this._alphaBL = v; + this._alphaBR = v; + + if (v === 0) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The alpha value starting from the top-left of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * + * @name Phaser.GameObjects.Components.Alpha#alphaTopLeft + * @type {number} + * @webglOnly + * @since 3.0.0 + */ + alphaTopLeft: { + + get: function () + { + return this._alphaTL; + }, + + set: function (value) + { + var v = Clamp(value, 0, 1); + + this._alphaTL = v; + + if (v !== 0) + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The alpha value starting from the top-right of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * + * @name Phaser.GameObjects.Components.Alpha#alphaTopRight + * @type {number} + * @webglOnly + * @since 3.0.0 + */ + alphaTopRight: { + + get: function () + { + return this._alphaTR; + }, + + set: function (value) + { + var v = Clamp(value, 0, 1); + + this._alphaTR = v; + + if (v !== 0) + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The alpha value starting from the bottom-left of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * + * @name Phaser.GameObjects.Components.Alpha#alphaBottomLeft + * @type {number} + * @webglOnly + * @since 3.0.0 + */ + alphaBottomLeft: { + + get: function () + { + return this._alphaBL; + }, + + set: function (value) + { + var v = Clamp(value, 0, 1); + + this._alphaBL = v; + + if (v !== 0) + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The alpha value starting from the bottom-right of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * + * @name Phaser.GameObjects.Components.Alpha#alphaBottomRight + * @type {number} + * @webglOnly + * @since 3.0.0 + */ + alphaBottomRight: { + + get: function () + { + return this._alphaBR; + }, + + set: function (value) + { + var v = Clamp(value, 0, 1); + + this._alphaBR = v; + + if (v !== 0) + { + this.renderFlags |= _FLAG; + } + } + + } + +}; + +module.exports = Alpha; + + +/***/ }), + +/***/ 88509: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); + +// bitmask flag for GameObject.renderMask +var _FLAG = 2; // 0010 + +/** + * Provides methods used for setting the alpha property of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.AlphaSingle + * @since 3.22.0 + */ + +var AlphaSingle = { + + /** + * Private internal value. Holds the global alpha value. + * + * @name Phaser.GameObjects.Components.AlphaSingle#_alpha + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _alpha: 1, + + /** + * Clears all alpha values associated with this Game Object. + * + * Immediately sets the alpha levels back to 1 (fully opaque). + * + * @method Phaser.GameObjects.Components.AlphaSingle#clearAlpha + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + clearAlpha: function () + { + return this.setAlpha(1); + }, + + /** + * Set the Alpha level of this Game Object. The alpha controls the opacity of the Game Object as it renders. + * Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque. + * + * @method Phaser.GameObjects.Components.AlphaSingle#setAlpha + * @since 3.0.0 + * + * @param {number} [value=1] - The alpha value applied across the whole Game Object. + * + * @return {this} This Game Object instance. + */ + setAlpha: function (value) + { + if (value === undefined) { value = 1; } + + this.alpha = value; + + return this; + }, + + /** + * The alpha value of the Game Object. + * + * This is a global value, impacting the entire Game Object, not just a region of it. + * + * @name Phaser.GameObjects.Components.AlphaSingle#alpha + * @type {number} + * @since 3.0.0 + */ + alpha: { + + get: function () + { + return this._alpha; + }, + + set: function (value) + { + var v = Clamp(value, 0, 1); + + this._alpha = v; + + if (v === 0) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + } + + } + +}; + +module.exports = AlphaSingle; + + +/***/ }), + +/***/ 90065: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlendModes = __webpack_require__(10312); + +/** + * Provides methods used for setting the blend mode of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.BlendMode + * @since 3.0.0 + */ + +var BlendMode = { + + /** + * Private internal value. Holds the current blend mode. + * + * @name Phaser.GameObjects.Components.BlendMode#_blendMode + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + _blendMode: BlendModes.NORMAL, + + /** + * Sets the Blend Mode being used by this Game Object. + * + * This can be a const, such as `Phaser.BlendModes.SCREEN`, or an integer, such as 4 (for Overlay) + * + * Under WebGL only the following Blend Modes are available: + * + * * NORMAL + * * ADD + * * MULTIPLY + * * SCREEN + * * ERASE + * + * Canvas has more available depending on browser support. + * + * You can also create your own custom Blend Modes in WebGL. + * + * Blend modes have different effects under Canvas and WebGL, and from browser to browser, depending + * on support. Blend Modes also cause a WebGL batch flush should it encounter a new blend mode. For these + * reasons try to be careful about the construction of your Scene and the frequency of which blend modes + * are used. + * + * @name Phaser.GameObjects.Components.BlendMode#blendMode + * @type {(Phaser.BlendModes|string|number)} + * @since 3.0.0 + */ + blendMode: { + + get: function () + { + return this._blendMode; + }, + + set: function (value) + { + if (typeof value === 'string') + { + value = BlendModes[value]; + } + + value |= 0; + + if (value >= -1) + { + this._blendMode = value; + } + } + + }, + + /** + * Sets the Blend Mode being used by this Game Object. + * + * This can be a const, such as `Phaser.BlendModes.SCREEN`, or an integer, such as 4 (for Overlay) + * + * Under WebGL only the following Blend Modes are available: + * + * * NORMAL + * * ADD + * * MULTIPLY + * * SCREEN + * * ERASE (only works when rendering to a framebuffer, like a Render Texture) + * + * Canvas has more available depending on browser support. + * + * You can also create your own custom Blend Modes in WebGL. + * + * Blend modes have different effects under Canvas and WebGL, and from browser to browser, depending + * on support. Blend Modes also cause a WebGL batch flush should it encounter a new blend mode. For these + * reasons try to be careful about the construction of your Scene and the frequency in which blend modes + * are used. + * + * @method Phaser.GameObjects.Components.BlendMode#setBlendMode + * @since 3.0.0 + * + * @param {(string|Phaser.BlendModes|number)} value - The BlendMode value. Either a string, a CONST or a number. + * + * @return {this} This Game Object instance. + */ + setBlendMode: function (value) + { + this.blendMode = value; + + return this; + } + +}; + +module.exports = BlendMode; + + +/***/ }), + +/***/ 94215: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for calculating and setting the size of a non-Frame based Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.ComputedSize + * @since 3.0.0 + */ + +var ComputedSize = { + + /** + * The native (un-scaled) width of this Game Object. + * + * Changing this value will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or use + * the `displayWidth` property. + * + * @name Phaser.GameObjects.Components.ComputedSize#width + * @type {number} + * @since 3.0.0 + */ + width: 0, + + /** + * The native (un-scaled) height of this Game Object. + * + * Changing this value will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or use + * the `displayHeight` property. + * + * @name Phaser.GameObjects.Components.ComputedSize#height + * @type {number} + * @since 3.0.0 + */ + height: 0, + + /** + * The displayed width of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.Components.ComputedSize#displayWidth + * @type {number} + * @since 3.0.0 + */ + displayWidth: { + + get: function () + { + return this.scaleX * this.width; + }, + + set: function (value) + { + this.scaleX = value / this.width; + } + + }, + + /** + * The displayed height of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.Components.ComputedSize#displayHeight + * @type {number} + * @since 3.0.0 + */ + displayHeight: { + + get: function () + { + return this.scaleY * this.height; + }, + + set: function (value) + { + this.scaleY = value / this.height; + } + + }, + + /** + * Sets the internal size of this Game Object, as used for frame or physics body creation. + * + * This will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or call the + * `setDisplaySize` method, which is the same thing as changing the scale but allows you + * to do so by giving pixel values. + * + * If you have enabled this Game Object for input, changing the size will _not_ change the + * size of the hit area. To do this you should adjust the `input.hitArea` object directly. + * + * @method Phaser.GameObjects.Components.ComputedSize#setSize + * @since 3.4.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + + return this; + }, + + /** + * Sets the display size of this Game Object. + * + * Calling this will adjust the scale. + * + * @method Phaser.GameObjects.Components.ComputedSize#setDisplaySize + * @since 3.4.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setDisplaySize: function (width, height) + { + this.displayWidth = width; + this.displayHeight = height; + + return this; + } + +}; + +module.exports = ComputedSize; + + +/***/ }), + +/***/ 61683: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for getting and setting the texture of a Game Object. + * + * @namespace Phaser.GameObjects.Components.Crop + * @since 3.12.0 + */ + +var Crop = { + + /** + * The Texture this Game Object is using to render with. + * + * @name Phaser.GameObjects.Components.Crop#texture + * @type {Phaser.Textures.Texture|Phaser.Textures.CanvasTexture} + * @since 3.0.0 + */ + texture: null, + + /** + * The Texture Frame this Game Object is using to render with. + * + * @name Phaser.GameObjects.Components.Crop#frame + * @type {Phaser.Textures.Frame} + * @since 3.0.0 + */ + frame: null, + + /** + * A boolean flag indicating if this Game Object is being cropped or not. + * You can toggle this at any time after `setCrop` has been called, to turn cropping on or off. + * Equally, calling `setCrop` with no arguments will reset the crop and disable it. + * + * @name Phaser.GameObjects.Components.Crop#isCropped + * @type {boolean} + * @since 3.11.0 + */ + isCropped: false, + + /** + * Applies a crop to a texture based Game Object, such as a Sprite or Image. + * + * The crop is a rectangle that limits the area of the texture frame that is visible during rendering. + * + * Cropping a Game Object does not change its size, dimensions, physics body or hit area, it just + * changes what is shown when rendered. + * + * The crop size as well as coordinates can not exceed the the size of the texture frame. + * + * The crop coordinates are relative to the texture frame, not the Game Object, meaning 0 x 0 is the top-left. + * + * Therefore, if you had a Game Object that had an 800x600 sized texture, and you wanted to show only the left + * half of it, you could call `setCrop(0, 0, 400, 600)`. + * + * It is also scaled to match the Game Object scale automatically. Therefore a crop rectangle of 100x50 would crop + * an area of 200x100 when applied to a Game Object that had a scale factor of 2. + * + * You can either pass in numeric values directly, or you can provide a single Rectangle object as the first argument. + * + * Call this method with no arguments at all to reset the crop, or toggle the property `isCropped` to `false`. + * + * You should do this if the crop rectangle becomes the same size as the frame itself, as it will allow + * the renderer to skip several internal calculations. + * + * @method Phaser.GameObjects.Components.Crop#setCrop + * @since 3.11.0 + * + * @param {(number|Phaser.Geom.Rectangle)} [x] - The x coordinate to start the crop from. Cannot be negative or exceed the Frame width. Or a Phaser.Geom.Rectangle object, in which case the rest of the arguments are ignored. + * @param {number} [y] - The y coordinate to start the crop from. Cannot be negative or exceed the Frame height. + * @param {number} [width] - The width of the crop rectangle in pixels. Cannot exceed the Frame width. + * @param {number} [height] - The height of the crop rectangle in pixels. Cannot exceed the Frame height. + * + * @return {this} This Game Object instance. + */ + setCrop: function (x, y, width, height) + { + if (x === undefined) + { + this.isCropped = false; + } + else if (this.frame) + { + if (typeof x === 'number') + { + this.frame.setCropUVs(this._crop, x, y, width, height, this.flipX, this.flipY); + } + else + { + var rect = x; + + this.frame.setCropUVs(this._crop, rect.x, rect.y, rect.width, rect.height, this.flipX, this.flipY); + } + + this.isCropped = true; + } + + return this; + }, + + /** + * Internal method that returns a blank, well-formed crop object for use by a Game Object. + * + * @method Phaser.GameObjects.Components.Crop#resetCropObject + * @private + * @since 3.12.0 + * + * @return {object} The crop object. + */ + resetCropObject: function () + { + return { u0: 0, v0: 0, u1: 0, v1: 0, width: 0, height: 0, x: 0, y: 0, flipX: false, flipY: false, cx: 0, cy: 0, cw: 0, ch: 0 }; + } + +}; + +module.exports = Crop; + + +/***/ }), + +/***/ 89272: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the depth of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.Depth + * @since 3.0.0 + */ + +var ArrayUtils = __webpack_require__(37105); + +var Depth = { + + /** + * Private internal value. Holds the depth of the Game Object. + * + * @name Phaser.GameObjects.Components.Depth#_depth + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + _depth: 0, + + /** + * The depth of this Game Object within the Scene. Ensure this value is only ever set to a number data-type. + * + * The depth is also known as the 'z-index' in some environments, and allows you to change the rendering order + * of Game Objects, without actually moving their position in the display list. + * + * The default depth is zero. A Game Object with a higher depth + * value will always render in front of one with a lower value. + * + * Setting the depth will queue a depth sort event within the Scene. + * + * @name Phaser.GameObjects.Components.Depth#depth + * @type {number} + * @since 3.0.0 + */ + depth: { + + get: function () + { + return this._depth; + }, + + set: function (value) + { + if (this.displayList) + { + this.displayList.queueDepthSort(); + } + + this._depth = value; + } + + }, + + /** + * The depth of this Game Object within the Scene. + * + * The depth is also known as the 'z-index' in some environments, and allows you to change the rendering order + * of Game Objects, without actually moving their position in the display list. + * + * The default depth is zero. A Game Object with a higher depth + * value will always render in front of one with a lower value. + * + * Setting the depth will queue a depth sort event within the Scene. + * + * @method Phaser.GameObjects.Components.Depth#setDepth + * @since 3.0.0 + * + * @param {number} value - The depth of this Game Object. Ensure this value is only ever a number data-type. + * + * @return {this} This Game Object instance. + */ + setDepth: function (value) + { + if (value === undefined) { value = 0; } + + this.depth = value; + + return this; + }, + + /** + * Sets this Game Object to be at the top of the display list, or the top of its parent container. + * + * Being at the top means it will render on-top of everything else. + * + * This method does not change this Game Objects `depth` value, it simply alters its list position. + * + * @method Phaser.GameObjects.Components.Depth#setToTop + * @since 3.85.0 + * + * @return {this} This Game Object instance. + */ + setToTop: function () + { + var list = this.getDisplayList(); + + if (list) + { + ArrayUtils.BringToTop(list, this); + } + + return this; + }, + + /** + * Sets this Game Object to the back of the display list, or the back of its parent container. + * + * Being at the back means it will render below everything else. + * + * This method does not change this Game Objects `depth` value, it simply alters its list position. + * + * @method Phaser.GameObjects.Components.Depth#setToBack + * @since 3.85.0 + * + * @return {this} This Game Object instance. + */ + setToBack: function () + { + var list = this.getDisplayList(); + + if (list) + { + ArrayUtils.SendToBack(list, this); + } + + return this; + }, + + /** + * Move this Game Object so that it appears above the given Game Object. + * + * This means it will render immediately after the other object in the display list. + * + * Both objects must belong to the same display list, or parent container. + * + * This method does not change this Game Objects `depth` value, it simply alters its list position. + * + * @method Phaser.GameObjects.Components.Depth#setAbove + * @since 3.85.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that this Game Object will be moved to be above. + * + * @return {this} This Game Object instance. + */ + setAbove: function (gameObject) + { + var list = this.getDisplayList(); + + if (list && gameObject) + { + ArrayUtils.MoveAbove(list, this, gameObject); + } + + return this; + }, + + /** + * Move this Game Object so that it appears below the given Game Object. + * + * This means it will render immediately under the other object in the display list. + * + * Both objects must belong to the same display list, or parent container. + * + * This method does not change this Game Objects `depth` value, it simply alters its list position. + * + * @method Phaser.GameObjects.Components.Depth#setBelow + * @since 3.85.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that this Game Object will be moved to be below. + * + * @return {this} This Game Object instance. + */ + setBelow: function (gameObject) + { + var list = this.getDisplayList(); + + if (list && gameObject) + { + ArrayUtils.MoveBelow(list, this, gameObject); + } + + return this; + } + +}; + +module.exports = Depth; + + +/***/ }), + +/***/ 3248: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods for managing an elapse timer on a Game Object. + * The timer is used to drive animations and other time-based effects. + * + * This is not necessary for normal animations. + * It is intended to drive shader effects that require a time value. + * + * If you are adding this component to a Game Object, + * ensure that you register a preUpdate method on the Game Object, e.g.: + * + * ```javascript + * // Overrides Game Object method + * addedToScene: function () + * { + * this.scene.sys.updateList.add(this); + * }, + * + * // Overrides Game Object method + * removedFromScene: function () + * { + * this.scene.sys.updateList.remove(this); + * }, + * + * preUpdate: function (time, delta) + * { + * this.updateTimer(time, delta); + * } + * ``` + * + * @namespace Phaser.GameObjects.Components.ElapseTimer + * @since 4.0.0 + */ +var ElapseTimer = { + + /** + * The time elapsed since timer initialization, in milliseconds. + * + * @name Phaser.GameObjects.Components.ElapseTimer#timeElapsed + * @type {number} + * @since 4.0.0 + */ + timeElapsed: 0, + + /** + * The time after which `timeElapsed` will reset, in milliseconds. + * By default, this is 1 hour. + * If you use the timer for animations, you can set this to a period + * that matches the animation durations. + * + * This is necessary for the timer to avoid floating-point precision issues + * in shaders. + * A float32 can represent a few hours of milliseconds accurately, + * but the precision decreases as the value increases. + * + * @name Phaser.GameObjects.Components.ElapseTimer#timeElapsedResetPeriod + * @type {number} + * @since 4.0.0 + * @default 3600000 + */ + timeElapsedResetPeriod: 60 * 60 * 1000, + + /** + * Whether the elapse timer is paused. + * + * @name Phaser.GameObjects.Components.ElapseTimer#timePaused + * @type {boolean} + * @since 4.0.0 + * @default false + */ + timePaused: false, + + /** + * Set the reset period for the elapse timer for this game object. + * + * @method Phaser.GameObjects.Components.ElapseTimer#setTimerResetPeriod + * @since 4.0.0 + * @param {number} period - The time after which `timeElapsed` will reset, in milliseconds. + * @return {this} This game object. + */ + setTimerResetPeriod: function (period) + { + this.timeElapsedResetPeriod = period; + + return this; + }, + + /** + * Pauses or resumes the elapse timer for this game object. + * + * @method Phaser.GameObjects.Components.ElapseTimer#setTimerPaused + * @since 4.0.0 + * @param {boolean} [paused] - Pause state (`true` to pause, `false` to unpause). If not specified, the timer will unpause. + * @return {this} This game object. + */ + setTimerPaused: function (paused) + { + this.timePaused = !!paused; + + return this; + }, + + /** + * Reset the elapse timer for this game object. + * + * @method Phaser.GameObjects.Components.ElapseTimer#resetTimer + * @since 4.0.0 + * @param {number} [ms=0] - The time to reset the timer to. + * @return {this} This game object. + */ + resetTimer: function (ms) + { + if (ms === undefined) { ms = 0; } + this.timeElapsed = ms; + + return this; + }, + + /** + * Update the elapse timer for this game object. + * This should be called automatically by the preUpdate method. + * + * Override this method to create more advanced time management, + * or set it to a NOOP function to disable the timer update. + * If you want to control animations with a tween or input system, + * disabling the timer update could be useful. + * + * @method Phaser.GameObjects.Components.ElapseTimer#updateTimer + * @since 4.0.0 + * @param {number} time - The current time in milliseconds. + * @param {number} delta - The time since the last update, in milliseconds. + * @return {this} This game object. + */ + updateTimer: function (time, delta) + { + if (!this.timePaused) + { + this.timeElapsed += delta; + + if (this.timeElapsed >= this.timeElapsedResetPeriod) + { + this.timeElapsed -= this.timeElapsedResetPeriod; + } + } + + return this; + } +}; + +module.exports = ElapseTimer; + + +/***/ }), + +/***/ 53427: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Barrel = __webpack_require__(10189); +var Blend = __webpack_require__(16762); +var Blur = __webpack_require__(88344); +var Bokeh = __webpack_require__(47564); +var ColorMatrix = __webpack_require__(77011); +var Displacement = __webpack_require__(16898); +var Glow = __webpack_require__(42652); +var Mask = __webpack_require__(97797); +var ParallelFilters = null; +var Pixelate = __webpack_require__(29861); +var Sampler = __webpack_require__(63785); +var Shadow = __webpack_require__(62229); +var Threshold = __webpack_require__(99534); + +/** + * @classdesc + * A list of filters being applied to a {@link Phaser.Cameras.Scene2D.Camera}. + * + * Filters can apply special effects and masks. + * They are only available in WebGL. + * Use `gameObject.enableFilters()` to apply them to Game Objects. + * + * Filters include the following: + * + * * Barrel Distortion + * * Blur + * * Blend + * * Bokeh / Tilt Shift + * * Color Matrix + * * Displacement + * * Glow + * * Mask + * * Parallel Filters + * * Pixelate + * * Sampler + * * Shadow + * * Threshold + * + * This list is either 'internal' or 'external'. + * Internal filters apply to things within the camera. + * External filters apply to the camera itself, in its rendering context. + * A complete list of rendering steps for a Camera goes: + * + * 1. Objects render to a texture the size of the camera. + * 2. Internal filters draw that texture to new textures, applying effects. + * These are usually the same size, but may expand to accommodate blur. + * 3. The texture is drawn to a texture the size of the context where the camera + * will be drawn, accounting for transformation of the camera itself. + * 4. External filters draw that texture to new textures, + * again applying effects and expanding where necessary. + * 5. The final texture draws the filtered camera contents to the context. + * + * For example, consider a game object which is rotated 45 degrees. + * Apply a horizontal blur filter. + * If the filter is internal, the blur will appear at 45 degrees, + * because it is applied before the object is rotated. + * If the filter is external, the blur will appear horizontal, + * because it is applied after the object is rotated. + * + * You should use internal filters wherever possible, + * because they apply only to the region of the camera/game object. + * External filters are full-screen and can be more expensive. + * + * Filters can be stacked. The order of the list is the order of application. + * + * As you can appreciate, some effects are more expensive than others. For example, a bloom effect is going to be more + * expensive than a simple color matrix effect, so please consider using them wisely and performance test your target + * platforms early on in production. + * + * This FilterList is created internally and does not need to be instantiated directly. + * + * In Phaser 3, Filters were known as FX. + * + * @class FilterList + * @memberof Phaser.GameObjects.Components + * @constructor + * @since 4.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that owns this list. + */ +var FilterList = new Class({ + initialize: function FilterList (camera) + { + /** + * The Camera that owns this list. + * + * @name Phaser.GameObjects.Components.FilterList#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 4.0.0 + */ + this.camera = camera; + + /** + * The list of filters. + * + * This list can be manipulated directly. + * If you want to add or remove filters, + * please use the appropriate methods to ensure they are handled correctly. + * Moving filters around in the list is safe. + * + * @name Phaser.GameObjects.Components.FilterList#list + * @type {Phaser.Filters.Controller[]} + * @default [] + * @since 4.0.0 + */ + this.list = []; + }, + + /** + * Destroys and removes all filters in this list. + * + * @method Phaser.GameObjects.Components.FilterList#clear + * @since 4.0.0 + * @returns {this} This FilterList instance. + */ + clear: function () + { + for (var i = 0; i < this.list.length; i++) + { + var filter = this.list[i]; + if (!filter.ignoreDestroy) + { + filter.destroy(); + } + } + + this.list.length = 0; + + return this; + }, + + /** + * Adds a filter to this list. + * + * @method Phaser.GameObjects.Components.FilterList#add + * @since 4.0.0 + * + * @param {Phaser.Filters.Controller} filter - The filter to add. + * @param {number} [index] - The index to insert the filter at. If not given, the filter is added to the end of the list. If negative, it is inserted from the end. + * + * @return {Phaser.Filters.Controller} The filter that was added. + */ + add: function (filter, index) + { + if (index === undefined) + { + this.list.push(filter); + } + else + { + this.list.splice(index, 0, filter); + } + + return filter; + }, + + /** + * Removes a filter from this list, then destroys it. + * + * @method Phaser.GameObjects.Components.FilterList#remove + * @since 4.0.0 + * + * @param {Phaser.Filters.Controller} filter - The filter to remove. + * @param {boolean} [forceDestroy=false] - If `true`, the filter will be destroyed even if it has the `ignoreDestroy` flag set. + * + * @return {this} This FilterList instance. + */ + remove: function (filter, forceDestroy) + { + var index = this.list.indexOf(filter); + + if (index !== -1) + { + this.list.splice(index, 1); + if (!filter.ignoreDestroy || forceDestroy) + { + filter.destroy(); + } + } + + return this; + }, + + /** + * Returns all active filters in this list. + * + * @method Phaser.GameObjects.Components.FilterList#getActive + * @since 4.0.0 + * @return {Phaser.Filters.Controller[]} The active filters in this list. + */ + getActive: function () + { + return this.list.filter(isActive); + }, + + /** + * Adds a Barrel effect. + * + * A barrel effect allows you to apply either a 'pinch' or 'expand' distortion to + * a Game Object. The amount of the effect can be modified in real-time. + * + * @method Phaser.GameObjects.Components.FilterList#addBarrel + * @since 4.0.0 + * @param {number} [amount=1] - The amount of distortion applied to the barrel effect. A value of 1 is no distortion. Typically keep this within +- 1. + * @return {Phaser.Filters.Barrel} The new Barrel filter controller. + */ + addBarrel: function (amount) + { + return this.add(new Barrel(this.camera, amount)); + }, + + /** + * Adds a Blend effect. + * + * A blend effect allows you to apply another texture to the view + * using a specific blend mode. + * This supports blend modes not otherwise available in WebGL. + * + * @method Phaser.GameObjects.Components.FilterList#addBlend + * @since 4.0.0 + * @param {Phaser.Textures.Texture} [texture='__WHITE'] - The texture to apply to the view. + * @param {Phaser.BlendModes} [blendMode=Phaser.BlendModes.NORMAL] - The blend mode to apply to the view. + * @param {number} [amount=1] - The amount of the blend effect to apply to the view. At 0, the original image is preserved. At 1, the blend texture is fully applied. The expected range is 0 to 1, but you can go outside that range for different effects. + * @param {number[]} [color=[1, 1, 1, 1]] - The color to apply to the blend texture. Each value corresponds to a color channel in RGBA. The expected range is 0 to 1, but you can go outside that range for different effects. + * @return {Phaser.Filters.Blend} The new Blend filter controller. + */ + addBlend: function (texture, blendMode, amount, color) + { + return this.add(new Blend( + this.camera, + texture, + blendMode, + amount, + color + )); + }, + + /** + * Adds a Blur effect. + * + * A Gaussian blur is the result of blurring an image by a Gaussian function. It is a widely used effect, + * typically to reduce image noise and reduce detail. The visual effect of this blurring technique is a + * smooth blur resembling that of viewing the image through a translucent screen, distinctly different + * from the bokeh effect produced by an out-of-focus lens or the shadow of an object under usual illumination. + * + * @method Phaser.GameObjects.Components.FilterList#addBlur + * @since 4.0.0 + * + * @param {number} [quality=0] - The quality of the blur effect. Can be either 0 for Low Quality, 1 for Medium Quality or 2 for High Quality. + * @param {number} [x=2] - The horizontal offset of the blur effect. + * @param {number} [y=2] - The vertical offset of the blur effect. + * @param {number} [strength=1] - The strength of the blur effect. + * @param {number} [color=0xffffff] - The color of the blur, as a hex value. + * @param {number} [steps=4] - The number of steps to run the blur effect for. This value should always be an integer. + * + * @return {Phaser.Filters.Blur} The new Blur filter controller. + */ + addBlur: function (quality, x, y, strength, color, steps) + { + return this.add(new Blur( + this.camera, + quality, + x, + y, + strength, + color, + steps + )); + }, + + /** + * Adds a Bokeh effect. + * + * Bokeh refers to a visual effect that mimics the photographic technique of creating a shallow depth of field. + * This effect is used to emphasize the game's main subject or action, by blurring the background or foreground + * elements, resulting in a more immersive and visually appealing experience. It is achieved through rendering + * techniques that simulate the out-of-focus areas, giving a sense of depth and realism to the game's graphics. + * + * See also Tilt Shift. + * + * @method Phaser.GameObjects.Components.FilterList#addBokeh + * @since 4.0.0 + * + * @param {number} [radius=0.5] - The radius of the bokeh effect. + * @param {number} [amount=1] - The amount of the bokeh effect. + * @param {number} [contrast=0.2] - The color contrast of the bokeh effect. + * + * @return {Phaser.Filters.Bokeh} The new Bokeh filter controller. + */ + addBokeh: function (radius, amount, contrast) + { + return this.add(new Bokeh( + this.camera, + radius, + amount, + contrast + )); + }, + + /** + * Adds a Color Matrix effect. + * + * The color matrix effect is a visual technique that involves manipulating the colors of an image + * or scene using a mathematical matrix. This process can adjust hue, saturation, brightness, and contrast, + * allowing developers to create various stylistic appearances or mood settings within the game. + * Common applications include simulating different lighting conditions, applying color filters, + * or achieving a specific visual style. + * + * @method Phaser.GameObjects.Components.FilterList#addColorMatrix + * @since 4.0.0 + * @return {Phaser.Filters.ColorMatrix} The new ColorMatrix filter controller. + */ + addColorMatrix: function () + { + return this.add(new ColorMatrix(this.camera)); + }, + + /** + * Adds a Displacement effect. + * + * The displacement effect is a visual technique that alters the position of pixels in an image + * or texture based on the values of a displacement map. This effect is used to create the illusion + * of depth, surface irregularities, or distortion in otherwise flat elements. It can be applied to + * characters, objects, or backgrounds to enhance realism, convey movement, or achieve various + * stylistic appearances. + * + * @method Phaser.GameObjects.Components.FilterList#addDisplacement + * @since 4.0.0 + * + * @param {string} [texture='__WHITE'] - The unique string-based key of the texture to use for displacement, which must exist in the Texture Manager. + * @param {number} [x=0.005] - The amount of horizontal displacement to apply. A very small float number, such as 0.005. + * @param {number} [y=0.005] - The amount of vertical displacement to apply. A very small float number, such as 0.005. + * + * @return {Phaser.Filters.Displacement} The new Displacement filter controller. + */ + addDisplacement: function (texture, x, y) + { + return this.add(new Displacement( + this.camera, + texture, + x, + y + )); + }, + + /** + * Adds a Glow effect. + * + * The glow effect is a visual technique that creates a soft, luminous halo around game objects, + * characters, or UI elements. This effect is used to emphasize importance, enhance visual appeal, + * or convey a sense of energy, magic, or otherworldly presence. The effect can also be set on + * the inside of the edge. The color and strength of the glow can be modified. + * + * @method Phaser.GameObjects.Components.FilterList#addGlow + * @since 4.0.0 + * + * @param {number} [color=0xffffff] - The color of the glow effect as a number value. + * @param {number} [outerStrength=4] - The strength of the glow outward from the edge of textures. + * @param {number} [innerStrength=0] - The strength of the glow inward from the edge of textures. + * @param {number} [scale=1] - The scale of the glow effect. This multiplies the fixed distance. + * @param {boolean} [knockout=false] - If `true` only the glow is drawn, not the texture itself. + * @param {number} [quality=0.1] - The quality of the glow effect. This cannot be changed after the filter has been created. + * @param {number} [distance=10] - The distance of the glow effect. This cannot be changed after the filter has been created. + * + * @return {Phaser.Filters.Glow} The new Glow filter controller. + */ + addGlow: function (color, outerStrength, innerStrength, scale, knockout, quality, distance) + { + return this.add(new Glow( + this.camera, + color, + outerStrength, + innerStrength, + scale, + knockout, + quality, + distance + )); + }, + + /** + * Adds a Mask effect. + * + * A mask uses a texture to hide parts of an input. + * It multiplies the color and alpha of the input + * by the alpha of the mask in the corresponding texel. + * + * Masks can be inverted, which switches what they hide and what they show. + * + * Masks can use either a texture or a GameObject. + * If a GameObject is used, the mask will render the GameObject + * to a DynamicTexture and use that. + * The mask will automatically update when the GameObject changes, + * unless the `autoUpdate` flag is set to `false`. + * + * When the mask filter is used as an internal filter, + * the mask will match the object/view being filtered. + * This is useful for creating effects that follow the object, + * such as effects intended to match an animated sprite. + * + * When the mask filter is used as an external filter, + * the mask will match the context of the camera. + * This is useful for creating effects that cover the entire view. + * + * An optional `viewCamera` can be specified when creating the mask. + * If not used, mask objects will be viewed through a default camera. + * Set the `viewCamera` to the scene's main camera (`this.cameras.main`) + * to view the mask through the main camera. + * + * @method Phaser.GameObjects.Components.FilterList#addMask + * @since 4.0.0 + * + * @param {string} [texture='__WHITE'] - The unique string-based key of the texture to use for the mask, which must exist in the Texture Manager. + * @param {boolean} [invert=false] - Whether to invert the mask. + * @param {Phaser.Cameras.Scene2D.Camera} [viewCamera] - The Camera to use when rendering the mask. If not specified, uses an internal Camera. + * + * @return {Phaser.Filters.Mask} The new Mask filter controller. + */ + addMask: function (texture, invert, viewCamera) + { + return this.add(new Mask( + this.camera, + texture, + invert, + viewCamera + )); + }, + + /** + * Adds a Parallel Filters effect. + * + * This filter controller splits the input into two lists of filters, + * runs each list separately, and then blends the results together. + * + * The Parallel Filters effect is useful for reusing an input. + * Ordinarily, a filter modifies the input and passes it to the next filter. + * This effect allows you to split the input and re-use it elsewhere. + * It does not gain performance benefits from parallel processing; + * it is a convenience for reusing the input. + * + * The Parallel Filters effect is not a filter itself. + * It is a controller that manages two FilterLists, + * and the final Blend filter that combines the results. + * The FilterLists are named 'top' and 'bottom'. + * The 'top' output is applied as a blend texture to the 'bottom' output. + * + * You do not have to populate both lists. If only one is populated, + * it will be blended with the original input at the end. + * This is useful when you want to retain image data that would be lost + * in the filter process. + * + * @example + * // Create a customizable Bloom effect. + * const camera = this.cameras.main; + * const parallelFilters = camera.filters.internal.addParallelFilters(); + * parallelFilters.top.addThreshold(0.5, 1); + * parallelFilters.top.addBlur(); + * parallelFilters.blend.blendMode = Phaser.BlendModes.ADD; + * parallelFilters.blend.amount = 0.5; + * + * @method Phaser.GameObjects.Components.FilterList#addParallelFilters + * @since 4.0.0 + * @return {Phaser.Filters.ParallelFilters} The new Parallel Filters filter controller. + */ + addParallelFilters: function () + { + // This import avoids a circular dependency. + if (!ParallelFilters) + { + ParallelFilters = __webpack_require__(2195); + } + return this.add(new ParallelFilters(this.camera)); + }, + + /** + * Adds a Pixelate effect. + * + * The pixelate effect is a visual technique that deliberately reduces the resolution or detail of an image, + * creating a blocky or mosaic appearance composed of large, visible pixels. This effect can be used for stylistic + * purposes, as a homage to retro gaming, or as a means to obscure certain elements within the game, such as + * during a transition or to censor specific content. + * + * @method Phaser.GameObjects.Components.FilterList#addPixelate + * @since 4.0.0 + * + * @param {number} [amount] - The amount of pixelation. A higher value creates a more pronounced effect. + * + * @return {Phaser.Filters.Pixelate} The new Pixelate filter controller. + */ + addPixelate: function (amount) + { + return this.add(new Pixelate( + this.camera, + amount + )); + }, + + /** + * Adds a Sampler effect. + * + * This controller manages a sampler. + * It doesn't actually render anything, and leaves the image unaltered. + * It is used to sample a region of the camera view, and pass the results to a callback. + * This is useful for extracting data from the camera view. + * + * This operation is expensive, so use sparingly. + * + * @method Phaser.GameObjects.Components.FilterList#addSampler + * @since 4.0.0 + * + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The callback to call with the results of the sampler. + * @param {null|Phaser.Types.Math.Vector2Like|Phaser.Geom.Rectangle} [region=null] - The region to sample. If `null`, the entire camera view is sampled. If a `Phaser.Types.Math.Vector2Like`, a point is sampled. If a `Phaser.Geom.Rectangle`, the region is sampled. + * + * @return {Phaser.Filters.Sampler} The new Sampler filter controller. + */ + addSampler: function (callback, region) + { + return this.add(new Sampler( + this.camera, + callback, + region + )); + }, + + /** + * Adds a Shadow effect. + * + * The shadow effect is a visual technique used to create the illusion of depth and realism by adding darker, + * offset silhouettes or shapes beneath game objects, characters, or environments. These simulated shadows + * help to enhance the visual appeal and immersion, making the 2D game world appear more dynamic and three-dimensional. + * + * @method Phaser.GameObjects.Components.FilterList#addShadow + * @since 4.0.0 + * + * @param {number} [x=0] - The horizontal offset of the shadow effect. + * @param {number} [y=0] - The vertical offset of the shadow effect. + * @param {number} [decay=0.1] - The amount of decay for the shadow effect. + * @param {number} [power=1] - The power of the shadow effect. + * @param {number} [color=0x000000] - The color of the shadow, as a hex value. + * @param {number} [samples=6] - The number of samples that the shadow effect will run for. + * @param {number} [intensity=1] - The intensity of the shadow effect. + * + * @return {Phaser.Filters.Shadow} The new Shadow filter controller. + */ + addShadow: function (x, y, decay, power, color, samples, intensity) + { + return this.add(new Shadow( + this.camera, + x, + y, + decay, + power, + color, + samples, + intensity + )); + }, + + /** + * Adds a Threshold effect. + * + * Input values are compared to a threshold value or range. + * Values below the threshold are set to 0, and values above the threshold are set to 1. + * Values within the range are linearly interpolated between 0 and 1. + * + * This is useful for creating effects such as sharp edges from gradients, + * or for creating binary effects. + * + * The threshold is stored as a range, with two edges. + * Each edge has a value for each channel, between 0 and 1. + * If the two edges are the same, the threshold has no interpolation, + * and will output either 0 or 1. + * Each channel can also be inverted. + * + * @method Phaser.GameObjects.Components.FilterList#addThreshold + * @since 4.0.0 + * + * @param {number|number[]} [edge1=0.5] - The first edge of the threshold. This may be an array of the RGBA channels, or a single number for all 4 channels. + * @param {number|number[]} [edge2=0.5] - The second edge of the threshold. This may be an array of the RGBA channels, or a single number for all 4 channels. + * @param {boolean|boolean[]} [invert=false] - Whether each channel is inverted. This may be an array of the RGBA channels, or a single boolean for all 4 channels. + * + * @return {Phaser.Filters.Threshold} The new Threshold filter controller. + */ + addThreshold: function (edge1, edge2, invert) + { + return this.add(new Threshold( + this.camera, + edge1, + edge2, + invert + )); + }, + + /** + * Adds a Tilt Shift effect. + * + * This Bokeh effect can also be used to generate a Tilt Shift effect, which is a technique used to create a miniature + * effect by blurring everything except a small area of the image. This effect is achieved by blurring the + * top and bottom elements, while keeping the center area in focus. + * + * See also Bokeh. + * + * @method Phaser.GameObjects.Components.FilterList#addTiltShift + * @since 4.0.0 + * + * @param {number} [radius] - The radius of the bokeh effect. + * @param {number} [amount] - The amount of the bokeh effect. + * @param {number} [contrast] - The color contrast of the bokeh effect. + * @param {number} [blurX] - The amount of horizontal blur. + * @param {number} [blurY] - The amount of vertical blur. + * @param {number} [strength] - The strength of the blur. + * + * @return {Phaser.Filters.Bokeh} The new Bokeh filter controller. + */ + addTiltShift: function (radius, amount, contrast, blurX, blurY, strength) + { + return this.add(new Bokeh( + this.camera, + radius, + amount, + contrast, + true, + blurX, + blurY, + strength + )); + }, + + /** + * Destroys this FilterList. + * + * @method Phaser.GameObjects.Components.FilterList#destroy + * @since 4.0.0 + */ + destroy: function () + { + this.clear(); + + this.camera = null; + } +}); + +function isActive (filter) +{ + return filter.active; +} + +module.exports = FilterList; + + +/***/ }), + +/***/ 43102: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Camera = null; // Lazy loaded. +var Vector2 = __webpack_require__(26099); +var TransformMatrix = __webpack_require__(61340); + +/** + * Provides methods used for setting the filters properties of a Game Object. + * These apply special effects, post-processing and masks to the object. + * Should be applied as a mixin and not used directly. + * + * Filters work by rendering the object to a texture. + * The texture is then rendered again for each filter, using a shader. + * See {@link Phaser.GameObjects.Components.FilterList} for more information. + * + * Enable filters with `enableFilters()`. + * Each object with filters enabled, and any filters active, + * makes a new draw call, plus one or more per active filter. + * This can be expensive. Use sparingly. + * + * --- + * + * ## Camera + * + * Filters has a `filterCamera` property, which is a Camera. + * The Camera does most of the hard work, including the filters. + * + * The Camera automatically focuses on the Game Object, + * so you should not need to adjust it manually. + * If you do want to adjust it, you can use `focusFiltersOverride`. + * + * --- + * + * ## Framebuffer Coverage + * + * Filters are rendered to a framebuffer, which is a texture. + * Anything outside the bounds of the framebuffer is not rendered. + * Think of it as a window into another world. + * + * To ensure that the game object fits into the framebuffer, + * the internal camera is transformed to match the object. + * The object can transform normally, and the camera will follow + * while `filtersAutoFocus` is enabled. + * + * @namespace Phaser.GameObjects.Components.Filters + * @since 4.0.0 + */ +var Filters = {}; + +if (true) +{ + Filters = + { + /** + * The Camera used for filters. + * You can use this to alter the perspective of filters. + * It is not necessary to use this camera for ordinary rendering. + * + * This is only available if you use the `enableFilters` method. + * + * @name Phaser.GameObjects.Components.Filters#filterCamera + * @type {Phaser.Cameras.Scene2D.Camera} + * @default null + * @since 4.0.0 + * @webglOnly + */ + filterCamera: null, + + /** + * Get the filters lists. + * This is an object with `internal` and `external` properties. + * Each list is a {@see Phaser.GameObjects.Components.FilterList} object. + * + * This is only available if you use the `enableFilters` method. + * + * @name Phaser.GameObjects.Components.Filters#filters + * @type {{internal: Phaser.GameObjects.Components.FilterList, external: Phaser.GameObjects.Components.FilterList}|null} + * @readonly + * @since 4.0.0 + * @webglOnly + */ + filters: { + get: function () + { + if (this.filterCamera) + { + return this.filterCamera.filters; + } + return null; + } + }, + + /** + * Whether any filters should be rendered on this Game Object. + * This is `true` by default, even if there are no filters yet. + * Disable this to skip filter rendering. + * + * Use `willRenderFilters()` to see if there are any active filters. + * + * @name Phaser.GameObjects.Components.Filters#renderFilters + * @type {boolean} + * @default true + * @since 4.0.0 + * @webglOnly + */ + renderFilters: true, + + /** + * The maximum size of the base filter texture. + * Filters may use a larger texture after the base texture is rendered. + * The maximum texture size is 4096 in WebGL. + * You may set this lower to save memory or prevent resizing. + * + * @name Phaser.GameObjects.Components.Filters#maxFilterSize + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + * @webglOnly + */ + maxFilterSize: null, + + /** + * Whether `filterCamera` should update every frame + * to focus on the Game Object. + * Disable this if you want to manually control the camera. + * + * @name Phaser.GameObjects.Components.Filters#filtersAutoFocus + * @type {boolean} + * @default true + * @since 4.0.0 + * @webglOnly + */ + filtersAutoFocus: true, + + /** + * Whether the filters should focus on the context, + * rather than attempt to focus on the Game Object. + * This is enabled automatically when enabling filters on objects + * which don't have well-defined bounds. + * + * This effectively sets the internal filters to render the same way + * as the external filters. + * + * This is only used if `filtersAutoFocus` is enabled. + * + * The "context" is the framebuffer to which the Game Object is rendered. + * This is usually the main framebuffer, but might be another framebuffer. + * It can even be several different framebuffers if the Game Object is + * rendered multiple times. + * + * @name Phaser.GameObjects.Components.Filters#filtersFocusContext + * @type {boolean} + * @default false + * @since 4.0.0 + * @webglOnly + */ + filtersFocusContext: false, + + /** + * Whether the Filters component should always draw to a framebuffer, + * even if there are no active filters. + * + * @name Phaser.GameObjects.Components.Filters#filtersForceComposite + * @type {boolean} + * @default false + * @since 4.0.0 + * @webglOnly + */ + filtersForceComposite: false, + + /** + * A transform matrix used to render the filters. + * It holds the transform of the Game Object. + * + * This is only available if you use the `enableFilters` method. + * + * @name Phaser.GameObjects.Components.Filters#_filtersMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 4.0.0 + * @webglOnly + */ + _filtersMatrix: null, + + /** + * A transform matrix used to render the filters. + * It holds the view matrix for the filter camera, adjusted for the Game Object. + * + * This is only available if you use the `enableFilters` method. + * + * @name Phaser.GameObjects.Components.Filters#_filtersViewMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 4.0.0 + * @webglOnly + */ + _filtersViewMatrix: null, + + /** + * Whether this Game Object will render filters. + * This is true if it has active filters, + * and if the `renderFilters` property is also true. + * + * @method Phaser.GameObjects.Components.Filters#willRenderFilters + * @since 4.0.0 + * @webglOnly + * @return {boolean} Whether the Game Object will render filters. + */ + willRenderFilters: function () + { + return this.renderFilters && + this.filters && + ( + this.filters.internal.getActive().length > 0 || + this.filters.external.getActive().length > 0 || + this.filtersForceComposite + ); + }, + + /** + * Enable this Game Object to have filters. + * + * You need to call this method if you want to use the `filterCamera` + * and `filters` properties. It sets up the necessary data structures. + * You may disable filter rendering with the `renderFilters` property. + * + * This is a WebGL only feature. It will return early if not available. + * + * @method Phaser.GameObjects.Components.Filters#enableFilters + * @since 4.0.0 + * @webglOnly + * @returns {this} + */ + enableFilters: function () + { + if (this.filterCamera || !this.scene.renderer.gl) + { + return this; + } + + var scene = this.scene; + + if (!Camera) + { + // Lazy load the camera class to avoid circular dependencies. + Camera = __webpack_require__(38058); + } + + this.filterCamera = new Camera(0, 0, 1, 1).setScene(scene, false); + + if (scene.game.config.roundPixels) + { + this.filterCamera.roundPixels = true; + } + + if (!this.maxFilterSize) + { + this.maxFilterSize = new Vector2(4096, 4096); + } + + this._filtersMatrix = new TransformMatrix(); + this._filtersViewMatrix = new TransformMatrix(); + + // Check whether the object is poorly bounded, and needs to focus on the context. + if ( + !this.getBounds || + this.width === undefined || + this.height === undefined || + this.width === 0 || + this.height === 0 + ) + { + this.filtersFocusContext = true; + } + + // Add filters as a render step. + this.addRenderStep(this.renderWebGLFilters, 0); + + return this; + }, + + /** + * Render this object using filters. + * + * This function's scope is not guaranteed, so it doesn't refer to `this`. + * + * @method Phaser.GameObjects.Components.Filters#renderWebGLFilters + * @webglOnly + * @since 4.0.0 + * @type {Phaser.Types.GameObjects.RenderWebGLStep} + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer instance to render with. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object being rendered. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - The parent matrix of the Game Object, if it has one. + * @param {number} [renderStep=0] - The index of this function in the Game Object's list of render processes. Used to support multiple rendering functions. + */ + renderWebGLFilters: function ( + renderer, + gameObject, + drawingContext, + parentMatrix, + renderStep + ) + { + if (!gameObject.willRenderFilters()) + { + gameObject.renderWebGLStep( + renderer, + gameObject, + drawingContext, + parentMatrix, + renderStep + 1 + ); + return; + } + + var camera = drawingContext.camera; + + // Add this Game Object to the camera's render list, + // because other calls to `addToRenderList` will happen in another camera. + camera.addToRenderList(gameObject); + + var filtersFocusContext = gameObject.filtersFocusContext; + + if (gameObject.filtersAutoFocus) + { + var contextCamera = null; + if (filtersFocusContext) + { + contextCamera = camera; + } + gameObject.focusFilters(contextCamera); + } + + var filterCamera = gameObject.filterCamera; + filterCamera.preRender(); + + // Get transform. + var transformMatrix = gameObject._filtersMatrix; + var cameraMatrix = gameObject._filtersViewMatrix.copyWithScrollFactorFrom( + camera.getViewMatrix(!drawingContext.useCanvas), + camera.scrollX, camera.scrollY, + gameObject.scrollFactorX, gameObject.scrollFactorY + ); + + if (parentMatrix) + { + cameraMatrix.multiply(parentMatrix); + } + + if (filtersFocusContext) + { + transformMatrix.loadIdentity(); + } + else + { + if (gameObject.type === 'Layer') + { + transformMatrix.loadIdentity(); + } + else + { + var flipX = gameObject.flipX ? -1 : 1; + var flipY = gameObject.flipY ? -1 : 1; + transformMatrix.applyITRS( + gameObject.x, + gameObject.y, + gameObject.rotation, + gameObject.scaleX * flipX, + gameObject.scaleY * flipY + ); + } + + // Offset origin. + var width = filterCamera.width; + var height = filterCamera.height; + transformMatrix.translate( + -width * filterCamera.originX, + -height * filterCamera.originY + ); + + cameraMatrix.multiply(transformMatrix, transformMatrix); + } + + // Set object scrollFactor to default. + // We can't accurately focus the camera on the object if it has a scrollFactor, + // because the camera needs to be set further away, + // going to infinity at scrollFactor 0. + // The scroll factor is baked into the transformMatrix, above. + var scrollX = gameObject.scrollFactorX; + var scrollY = gameObject.scrollFactorY; + gameObject.scrollFactorX = 1; + gameObject.scrollFactorY = 1; + + // Now we have the transform for the game object. + // Render game object to framebuffer. + renderer.cameraRenderNode.run( + drawingContext, + [ gameObject ], + filterCamera, + transformMatrix, + true, + renderStep + 1 + ); + + // Restore scrollFactor. + gameObject.scrollFactorX = scrollX; + gameObject.scrollFactorY = scrollY; + }, + + /** + * Focus the filter camera. + * This sets the size and position of the filter camera to match the GameObject. + * This is called automatically on render if `filtersAutoFocus` is enabled. + * + * If a camera is provided, this will focus on the camera. + * Otherwise, this will focus on the GameObject's raw dimensions + * if available. + * If the GameObject has no dimensions, this will focus on the context: + * the camera belonging to the DrawingContext used to render the GameObject. + * Context focus occurs during rendering, + * as the context is not known until then. + * + * @method Phaser.GameObjects.Components.Filters#focusFilters + * @webglOnly + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The camera to focus on. Optional; if provided, this will focus on the camera. + * @returns {this} + */ + focusFilters: function (camera) + { + var filterCamera = this.filterCamera; + + // Attempt to create bounds from basic object properties. + if (!camera) + { + var posX = this.x; + var posY = this.y; + var originX = this.originX; + var originY = this.originY; + var width = this.width; + var height = this.height; + + if ( + this.type === 'Layer' || + isNaN(posX) || isNaN(posY) || + isNaN(width) || isNaN(height) || + isNaN(originX) || isNaN(originY) || + width === 0 || height === 0 + ) + { + this.filtersFocusContext = true; + return this; + } + + var rotation = this.rotation; + var scaleX = this.scaleX; + var scaleY = this.scaleY; + + var centerX = posX + width * (0.5 - originX); + var centerY = posY + height * (0.5 - originY); + + // Handle flip. + if (this.flipX) + { + scaleX *= -1; + } + if (this.flipY) + { + scaleY *= -1; + } + + // Set the filter camera size to match the object. + this.setFilterSize(width, height); + + // Set the filter camera to match the object. + this.filterCamera + .centerOn(centerX, centerY) + .setRotation(-rotation) + .setOrigin(originX, originY) + .setZoom(1 / scaleX, 1 / scaleY); + } + else + { + // Focus on the camera. + width = camera.width; + height = camera.height; + + // Set the filter camera size to match the object. + this.setFilterSize(width, height); + + filterCamera.setScroll(camera.scrollX, camera.scrollY); + filterCamera.setRotation(camera.rotation); + filterCamera.setZoom(camera.zoomX, camera.zoomY); + } + + return this; + }, + + /** + * Manually override the focus of the filter camera. + * This allows you to set the size and position of the filter camera manually. + * It deactivates `filtersAutoFocus` when called. + * + * The camera will set scroll to place the game object at the + * given position within a rectangle of the given width and height. + * For example, calling `focusFiltersOverride(400, 200, 800, 600)` + * will focus the camera to place the object's center + * 100 pixels above the center of the camera (which is at 400x300). + * + * @method Phaser.GameObjects.Components.Filters#focusFiltersOverride + * @webglOnly + * @since 4.0.0 + * @param {number} [x] - The x-coordinate of the focus point, relative to the filter size. Default is the center. + * @param {number} [y] - The y-coordinate of the focus point, relative to the filter size. Default is the center. + * @param {number} [width] - The width of the focus area. Default is the filter width. + * @param {number} [height] - The height of the focus area. Default is the filter height. + * @returns {this} + */ + focusFiltersOverride: function (x, y, width, height) + { + var filterCamera = this.filterCamera; + + // Maintain size. + if (width === undefined) + { + width = filterCamera.width; + } + if (height === undefined) + { + height = filterCamera.height; + } + + // Default to center. + if (x === undefined) + { + x = width / 2; + } + if (y === undefined) + { + y = height / 2; + } + + var objectX = this.x; + var objectY = this.y; + + this.setFilterSize(width, height); + filterCamera.setScroll(objectX - x, objectY - y); + + var originX = x / width; + var originY = y / height; + + filterCamera.setOrigin(originX, originY); + + // Stop automatic focus. + this.filtersAutoFocus = false; + + return this; + }, + + /** + * Set the base size of the filter camera. + * This is the size of the texture that internal filters will be drawn to. + * External filters are drawn to the size of the context (usually the game canvas). + * + * This is typically the size of the GameObject. + * It is set automatically when the Game Object is rendered + * and `filtersAutoFocus` is enabled. + * Turn off auto focus to set it manually. + * + * Technically, larger framebuffers may be used to provide padding. + * This is the size of the final framebuffer used for "internal" rendering. + * + * @method Phaser.GameObjects.Components.Filters#setFilterSize + * @webglOnly + * @since 4.0.0 + * @param {number} width - Base width of the filter texture. + * @param {number} height - Base height of the filter texture. + * @returns {this} + */ + setFilterSize: function (width, height) + { + // Sanitize inputs. + width = Math.max(1, Math.min(Math.ceil(width), this.maxFilterSize.x)); + height = Math.max(1, Math.min(Math.ceil(height), this.maxFilterSize.y)); + + var filterCamera = this.filterCamera; + if (!filterCamera) + { + return this; + } + filterCamera.setSize(width, height); + + return this; + }, + + /** + * Set whether filters should be updated every frame. + * Sets the `filtersAutoFocus` property. + * + * @method Phaser.GameObjects.Components.Filters#setFiltersAutoFocus + * @webglOnly + * @since 4.0.0 + * @param {boolean} value - Whether filters should be updated every frame. + * @returns {this} + */ + setFiltersAutoFocus: function (value) + { + this.filtersAutoFocus = value; + + return this; + }, + + /** + * Set whether the filters should focus on the context. + * Sets the `filtersFocusContext` property. + * + * @method Phaser.GameObjects.Components.Filters#setFiltersFocusContext + * @webglOnly + * @since 4.0.0 + * @param {boolean} value - Whether the filters should focus on the context. + * @returns {this} + */ + setFiltersFocusContext: function (value) + { + this.filtersFocusContext = value; + + return this; + }, + + /** + * Set whether the filters should always draw to a framebuffer. + * Sets the `filtersForceComposite` property. + * + * @method Phaser.GameObjects.Components.Filters#setFiltersForceComposite + * @webglOnly + * @since 4.0.0 + * @param {boolean} value - Whether the object should always draw to a framebuffer, even if there are no active filters. + * @returns {this} + */ + setFiltersForceComposite: function (value) + { + this.filtersForceComposite = value; + + return this; + }, + + /** + * Set whether the filters should be rendered. + * Sets the `renderFilters` property. + * + * @method Phaser.GameObjects.Components.Filters#setRenderFilters + * @webglOnly + * @since 4.0.0 + * @param {boolean} value - Whether the filters should be rendered. + * @returns {this} + */ + setRenderFilters: function (value) + { + this.renderFilters = value; + + return this; + } + }; +} + +module.exports = Filters; + + +/***/ }), + +/***/ 54434: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for visually flipping a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.Flip + * @since 3.0.0 + */ + +var Flip = { + + /** + * The horizontally flipped state of the Game Object. + * + * A Game Object that is flipped horizontally will render inversed on the horizontal axis. + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @name Phaser.GameObjects.Components.Flip#flipX + * @type {boolean} + * @default false + * @since 3.0.0 + */ + flipX: false, + + /** + * The vertically flipped state of the Game Object. + * + * A Game Object that is flipped vertically will render inversed on the vertical axis (i.e. upside down) + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @name Phaser.GameObjects.Components.Flip#flipY + * @type {boolean} + * @default false + * @since 3.0.0 + */ + flipY: false, + + /** + * Toggles the horizontal flipped state of this Game Object. + * + * A Game Object that is flipped horizontally will render inversed on the horizontal axis. + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @method Phaser.GameObjects.Components.Flip#toggleFlipX + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + toggleFlipX: function () + { + this.flipX = !this.flipX; + + return this; + }, + + /** + * Toggles the vertical flipped state of this Game Object. + * + * @method Phaser.GameObjects.Components.Flip#toggleFlipY + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + toggleFlipY: function () + { + this.flipY = !this.flipY; + + return this; + }, + + /** + * Sets the horizontal flipped state of this Game Object. + * + * A Game Object that is flipped horizontally will render inversed on the horizontal axis. + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @method Phaser.GameObjects.Components.Flip#setFlipX + * @since 3.0.0 + * + * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped. + * + * @return {this} This Game Object instance. + */ + setFlipX: function (value) + { + this.flipX = value; + + return this; + }, + + /** + * Sets the vertical flipped state of this Game Object. + * + * @method Phaser.GameObjects.Components.Flip#setFlipY + * @since 3.0.0 + * + * @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped. + * + * @return {this} This Game Object instance. + */ + setFlipY: function (value) + { + this.flipY = value; + + return this; + }, + + /** + * Sets the horizontal and vertical flipped state of this Game Object. + * + * A Game Object that is flipped will render inversed on the flipped axis. + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @method Phaser.GameObjects.Components.Flip#setFlip + * @since 3.0.0 + * + * @param {boolean} x - The horizontal flipped state. `false` for no flip, or `true` to be flipped. + * @param {boolean} y - The horizontal flipped state. `false` for no flip, or `true` to be flipped. + * + * @return {this} This Game Object instance. + */ + setFlip: function (x, y) + { + this.flipX = x; + this.flipY = y; + + return this; + }, + + /** + * Resets the horizontal and vertical flipped state of this Game Object back to their default un-flipped state. + * + * @method Phaser.GameObjects.Components.Flip#resetFlip + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + resetFlip: function () + { + this.flipX = false; + this.flipY = false; + + return this; + } + +}; + +module.exports = Flip; + + +/***/ }), + +/***/ 8004: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var RotateAround = __webpack_require__(11520); +var Vector2 = __webpack_require__(26099); + +/** + * Provides methods used for obtaining the bounds of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.GetBounds + * @since 3.0.0 + */ + +var GetBounds = { + + /** + * Processes the bounds output vector before returning it. + * + * @method Phaser.GameObjects.Components.GetBounds#prepareBoundsOutput + * @private + * @since 3.18.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} output - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + prepareBoundsOutput: function (output, includeParent) + { + if (includeParent === undefined) { includeParent = false; } + + if (this.rotation !== 0) + { + RotateAround(output, this.x, this.y, this.rotation); + } + + if (includeParent && this.parentContainer) + { + var parentMatrix = this.parentContainer.getBoundsTransformMatrix(); + + parentMatrix.transformPoint(output.x, output.y, output); + } + + return output; + }, + + /** + * Gets the center coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getCenter + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getCenter: function (output, includeParent) + { + if (output === undefined) { output = new Vector2(); } + + output.x = this.x - (this.displayWidth * this.originX) + (this.displayWidth / 2); + output.y = this.y - (this.displayHeight * this.originY) + (this.displayHeight / 2); + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the top-left corner coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getTopLeft + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getTopLeft: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = this.x - (this.displayWidth * this.originX); + output.y = this.y - (this.displayHeight * this.originY); + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the top-center coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getTopCenter + * @since 3.18.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getTopCenter: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = (this.x - (this.displayWidth * this.originX)) + (this.displayWidth / 2); + output.y = this.y - (this.displayHeight * this.originY); + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the top-right corner coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getTopRight + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getTopRight: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = (this.x - (this.displayWidth * this.originX)) + this.displayWidth; + output.y = this.y - (this.displayHeight * this.originY); + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the left-center coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getLeftCenter + * @since 3.18.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getLeftCenter: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = this.x - (this.displayWidth * this.originX); + output.y = (this.y - (this.displayHeight * this.originY)) + (this.displayHeight / 2); + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the right-center coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getRightCenter + * @since 3.18.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getRightCenter: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = (this.x - (this.displayWidth * this.originX)) + this.displayWidth; + output.y = (this.y - (this.displayHeight * this.originY)) + (this.displayHeight / 2); + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the bottom-left corner coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getBottomLeft + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getBottomLeft: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = this.x - (this.displayWidth * this.originX); + output.y = (this.y - (this.displayHeight * this.originY)) + this.displayHeight; + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the bottom-center coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getBottomCenter + * @since 3.18.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getBottomCenter: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = (this.x - (this.displayWidth * this.originX)) + (this.displayWidth / 2); + output.y = (this.y - (this.displayHeight * this.originY)) + this.displayHeight; + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the bottom-right corner coordinate of this Game Object, regardless of origin. + * + * The returned point is calculated in local space and does not factor in any parent Containers, + * unless the `includeParent` argument is set to `true`. + * + * @method Phaser.GameObjects.Components.GetBounds#getBottomRight + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} O - [output,$return] + * + * @param {Phaser.Types.Math.Vector2Like} [output] - An object to store the values in. If not provided a new Vector2 will be created. + * @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector? + * + * @return {Phaser.Types.Math.Vector2Like} The values stored in the output object. + */ + getBottomRight: function (output, includeParent) + { + if (!output) { output = new Vector2(); } + + output.x = (this.x - (this.displayWidth * this.originX)) + this.displayWidth; + output.y = (this.y - (this.displayHeight * this.originY)) + this.displayHeight; + + return this.prepareBoundsOutput(output, includeParent); + }, + + /** + * Gets the bounds of this Game Object, regardless of origin. + * + * The values are stored and returned in a Rectangle, or Rectangle-like, object. + * + * @method Phaser.GameObjects.Components.GetBounds#getBounds + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [output,$return] + * + * @param {(Phaser.Geom.Rectangle|object)} [output] - An object to store the values in. If not provided a new Rectangle will be created. + * + * @return {(Phaser.Geom.Rectangle|object)} The values stored in the output object. + */ + getBounds: function (output) + { + if (output === undefined) { output = new Rectangle(); } + + // We can use the output object to temporarily store the x/y coords in: + + var TLx, TLy, TRx, TRy, BLx, BLy, BRx, BRy; + + // Instead of doing a check if parent container is + // defined per corner we only do it once. + if (this.parentContainer) + { + var parentMatrix = this.parentContainer.getBoundsTransformMatrix(); + + this.getTopLeft(output); + parentMatrix.transformPoint(output.x, output.y, output); + + TLx = output.x; + TLy = output.y; + + this.getTopRight(output); + parentMatrix.transformPoint(output.x, output.y, output); + + TRx = output.x; + TRy = output.y; + + this.getBottomLeft(output); + parentMatrix.transformPoint(output.x, output.y, output); + + BLx = output.x; + BLy = output.y; + + this.getBottomRight(output); + parentMatrix.transformPoint(output.x, output.y, output); + + BRx = output.x; + BRy = output.y; + } + else + { + this.getTopLeft(output); + + TLx = output.x; + TLy = output.y; + + this.getTopRight(output); + + TRx = output.x; + TRy = output.y; + + this.getBottomLeft(output); + + BLx = output.x; + BLy = output.y; + + this.getBottomRight(output); + + BRx = output.x; + BRy = output.y; + } + + output.x = Math.min(TLx, TRx, BLx, BRx); + output.y = Math.min(TLy, TRy, BLy, BRy); + output.width = Math.max(TLx, TRx, BLx, BRx) - output.x; + output.height = Math.max(TLy, TRy, BLy, BRy) - output.y; + + return output; + } + +}; + +module.exports = GetBounds; + + +/***/ }), + +/***/ 73629: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods for enabling lighting effects on a Game Object. + * + * This should only be applied to GameObjects that have RenderNodes. + * + * @namespace Phaser.GameObjects.Components.Lighting + * @webglOnly + * @since 4.0.0 + */ +var Lighting = { + + /** + * Should this GameObject use lighting? + * + * This flag is used to set up WebGL shaders for rendering. + * + * @name Phaser.GameObjects.Components.Lighting#lighting + * @type {boolean} + * @webglOnly + * @since 4.0.0 + * @default false + * @readonly + */ + lighting: false, + + /** + * Should this GameObject use self-shadowing? + * Self-shadowing is only enabled if `lighting` is enabled. + * + * The game config option `render.selfShadow` is used if this is not a boolean. + * + * This flag is used to set up WebGL shaders for rendering. + * + * @name Phaser.GameObjects.Components.Lighting#selfShadow + * @type {{ enabled: boolean, penumbra: number, diffuseFlatThreshold: number }} + * @webglOnly + * @since 4.0.0 + */ + selfShadow: { + enabled: null, + penumbra: 0.5, + diffuseFlatThreshold: 1 / 3 + }, + + /** + * Sets whether this GameObject should use lighting. + * + * @method Phaser.GameObjects.Components.Lighting#setLighting + * @webglOnly + * @since 4.0.0 + * @param {boolean} enable - `true` to use lighting, or `false` to disable it. + * @return {this} This GameObject instance. + */ + setLighting: function (enable) + { + this.lighting = enable; + + return this; + }, + + /** + * Sets whether this GameObject should use self-shadowing. + * Self-shadowing is only enabled if `lighting` is also enabled. + * + * @method Phaser.GameObjects.Components.Lighting#setSelfShadow + * @webglOnly + * @since 4.0.0 + * @param {?boolean} [enabled] - `true` to use self-shadowing, `false` to disable it, `null` to use the game default from `config.render.selfShadow`, or `undefined` to keep the setting. + * @param {number} [penumbra] - The penumbra value for the shadow. Lower is sharper but more jagged. Default is 0.5. + * @param {number} [diffuseFlatThreshold] - The texture brightness threshold at which the diffuse lighting will be considered flat. Range is 0-1. Default is 1/3. + * @return {this} This GameObject instance. + */ + setSelfShadow: function (enabled, penumbra, diffuseFlatThreshold) + { + if (enabled !== undefined) + { + if (enabled === null) + { + this.selfShadow.enabled = this.scene.sys.game.config.selfShadow; + } + else + { + this.selfShadow.enabled = enabled; + } + } + + if (penumbra !== undefined) + { + this.selfShadow.penumbra = penumbra; + } + + if (diffuseFlatThreshold !== undefined) + { + this.selfShadow.diffuseFlatThreshold = diffuseFlatThreshold; + } + + return this; + } +}; + +module.exports = Lighting; + + +/***/ }), + +/***/ 8573: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(8054); +var GeometryMask = __webpack_require__(80661); + +/** + * Provides methods used for getting and setting the mask of a Game Object. + * + * This only works under the Canvas Renderer. + * For WebGL, see {@link Phaser.GameObjects.Components.FilterList#addMask}. + * + * @namespace Phaser.GameObjects.Components.Mask + * @since 3.0.0 + */ + +var Mask = { + + /** + * The Mask this Game Object is using during render. + * + * @name Phaser.GameObjects.Components.Mask#mask + * @type {Phaser.Display.Masks.GeometryMask} + * @since 3.0.0 + */ + mask: null, + + /** + * Sets the mask that this Game Object will use to render with. + * + * The mask must have been previously created and must be a GeometryMask. + * This only works in the Canvas Renderer. + * In WebGL, use a Mask filter instead (see {@link Phaser.GameObjects.Components.FilterList#addMask}). + * + * If a mask is already set on this Game Object it will be immediately replaced. + * + * Masks are positioned in global space and are not relative to the Game Object to which they + * are applied. The reason for this is that multiple Game Objects can all share the same mask. + * + * Masks have no impact on physics or input detection. They are purely a rendering component + * that allows you to limit what is visible during the render pass. + * + * @method Phaser.GameObjects.Components.Mask#setMask + * @since 3.6.2 + * + * @param {Phaser.Display.Masks.GeometryMask} mask - The mask this Game Object will use when rendering. + * + * @return {this} This Game Object instance. + */ + setMask: function (mask) + { + if (this.scene.renderer.type === CONST.WEBGL) + { + console.warn('Phaser.GameObjects.Components.Mask.setMask: This method is not supported in WebGL. Create a Mask filter instead.'); + return this; + } + + this.mask = mask; + + return this; + }, + + /** + * Clears the mask that this Game Object was using. + * + * This only works in the Canvas Renderer. + * In WebGL, use a Mask filter instead (see {@link Phaser.GameObjects.Components.FilterList#addMask}). + * + * @method Phaser.GameObjects.Components.Mask#clearMask + * @since 3.6.2 + * + * @param {boolean} [destroyMask=false] - Destroy the mask before clearing it? + * + * @return {this} This Game Object instance. + */ + clearMask: function (destroyMask) + { + if (destroyMask === undefined) { destroyMask = false; } + + if (destroyMask && this.mask) + { + this.mask.destroy(); + } + + this.mask = null; + + return this; + }, + + /** + * Creates and returns a Geometry Mask. This mask can be used by any Game Object, + * including this one. + * + * To create the mask you need to pass in a reference to a Graphics Game Object. + * + * If you do not provide a graphics object, and this Game Object is an instance + * of a Graphics object, then it will use itself to create the mask. + * + * This means you can call this method to create a Geometry Mask from any Graphics Game Object. + * + * This only works in the Canvas Renderer. + * In WebGL, use a Mask filter instead (see {@link Phaser.GameObjects.Components.FilterList#addMask}). + * + * @method Phaser.GameObjects.Components.Mask#createGeometryMask + * @since 3.6.2 + * + * @generic {Phaser.GameObjects.Graphics} G + * @generic {Phaser.GameObjects.Shape} S + * @genericUse {(G|S)} [graphics] + * + * @param {Phaser.GameObjects.Graphics|Phaser.GameObjects.Shape} [graphics] - A Graphics Game Object, or any kind of Shape Game Object. The geometry within it will be used as the mask. + * + * @return {Phaser.Display.Masks.GeometryMask} This Geometry Mask that was created. + */ + createGeometryMask: function (graphics) + { + if (graphics === undefined && (this.type === 'Graphics' || this.geom)) + { + // eslint-disable-next-line consistent-this + graphics = this; + } + + return new GeometryMask(this.scene, graphics); + } + +}; + +module.exports = Mask; + + +/***/ }), + +/***/ 27387: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for getting and setting the origin of a Game Object. + * Values are normalized, given in the range 0 to 1. + * Display values contain the calculated pixel values. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.Origin + * @since 3.0.0 + */ + +var Origin = { + + /** + * A property indicating that a Game Object has this component. + * + * @name Phaser.GameObjects.Components.Origin#_originComponent + * @type {boolean} + * @private + * @default true + * @since 3.2.0 + */ + _originComponent: true, + + /** + * The horizontal origin of this Game Object. + * The origin maps the relationship between the size and position of the Game Object. + * The default value is 0.5, meaning all Game Objects are positioned based on their center. + * Setting the value to 0 means the position now relates to the left of the Game Object. + * Set this value with `setOrigin()`. + * + * @name Phaser.GameObjects.Components.Origin#originX + * @type {number} + * @readonly + * @default 0.5 + * @since 3.0.0 + */ + originX: 0.5, + + /** + * The vertical origin of this Game Object. + * The origin maps the relationship between the size and position of the Game Object. + * The default value is 0.5, meaning all Game Objects are positioned based on their center. + * Setting the value to 0 means the position now relates to the top of the Game Object. + * Set this value with `setOrigin()`. + * + * @name Phaser.GameObjects.Components.Origin#originY + * @type {number} + * @readonly + * @default 0.5 + * @since 3.0.0 + */ + originY: 0.5, + + // private + read only + _displayOriginX: 0, + _displayOriginY: 0, + + /** + * The horizontal display origin of this Game Object. + * The origin is a normalized value between 0 and 1. + * The displayOrigin is a pixel value, based on the size of the Game Object combined with the origin. + * + * @name Phaser.GameObjects.Components.Origin#displayOriginX + * @type {number} + * @since 3.0.0 + */ + displayOriginX: { + + get: function () + { + return this._displayOriginX; + }, + + set: function (value) + { + this._displayOriginX = value; + this.originX = value / this.width; + } + + }, + + /** + * The vertical display origin of this Game Object. + * The origin is a normalized value between 0 and 1. + * The displayOrigin is a pixel value, based on the size of the Game Object combined with the origin. + * + * @name Phaser.GameObjects.Components.Origin#displayOriginY + * @type {number} + * @since 3.0.0 + */ + displayOriginY: { + + get: function () + { + return this._displayOriginY; + }, + + set: function (value) + { + this._displayOriginY = value; + this.originY = value / this.height; + } + + }, + + /** + * Sets the origin of this Game Object. + * + * The values are given in the range 0 to 1. + * + * @method Phaser.GameObjects.Components.Origin#setOrigin + * @since 3.0.0 + * + * @param {number} [x=0.5] - The horizontal origin value. + * @param {number} [y=x] - The vertical origin value. If not defined it will be set to the value of `x`. + * + * @return {this} This Game Object instance. + */ + setOrigin: function (x, y) + { + if (x === undefined) { x = 0.5; } + if (y === undefined) { y = x; } + + this.originX = x; + this.originY = y; + + return this.updateDisplayOrigin(); + }, + + /** + * Sets the origin of this Game Object based on the Pivot values in its Frame. + * + * @method Phaser.GameObjects.Components.Origin#setOriginFromFrame + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + setOriginFromFrame: function () + { + if (!this.frame || !this.frame.customPivot) + { + return this.setOrigin(); + } + else + { + this.originX = this.frame.pivotX; + this.originY = this.frame.pivotY; + } + + return this.updateDisplayOrigin(); + }, + + /** + * Sets the display origin of this Game Object. + * The difference between this and setting the origin is that you can use pixel values for setting the display origin. + * + * @method Phaser.GameObjects.Components.Origin#setDisplayOrigin + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal display origin value. + * @param {number} [y=x] - The vertical display origin value. If not defined it will be set to the value of `x`. + * + * @return {this} This Game Object instance. + */ + setDisplayOrigin: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = x; } + + this.displayOriginX = x; + this.displayOriginY = y; + + return this; + }, + + /** + * Updates the Display Origin cached values internally stored on this Game Object. + * You don't usually call this directly, but it is exposed for edge-cases where you may. + * + * @method Phaser.GameObjects.Components.Origin#updateDisplayOrigin + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + updateDisplayOrigin: function () + { + this._displayOriginX = this.originX * this.width; + this._displayOriginY = this.originY * this.height; + + return this; + } + +}; + +module.exports = Origin; + + +/***/ }), + +/***/ 37640: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DegToRad = __webpack_require__(39506); +var GetBoolean = __webpack_require__(57355); +var GetValue = __webpack_require__(35154); +var TWEEN_CONST = __webpack_require__(86353); +var Vector2 = __webpack_require__(26099); + +/** + * Provides methods used for managing a Game Object following a Path. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.PathFollower + * @since 3.17.0 + */ + +var PathFollower = { + + /** + * The Path this PathFollower is following. It can only follow one Path at a time. + * + * @name Phaser.GameObjects.Components.PathFollower#path + * @type {Phaser.Curves.Path} + * @since 3.0.0 + */ + path: null, + + /** + * Should the PathFollower automatically rotate to point in the direction of the Path? + * + * @name Phaser.GameObjects.Components.PathFollower#rotateToPath + * @type {boolean} + * @default false + * @since 3.0.0 + */ + rotateToPath: false, + + /** + * If the PathFollower is rotating to match the Path (@see Phaser.GameObjects.PathFollower#rotateToPath) + * this value is added to the rotation value. This allows you to rotate objects to a path but control + * the angle of the rotation as well. + * + * @name Phaser.GameObjects.PathFollower#pathRotationOffset + * @type {number} + * @default 0 + * @since 3.0.0 + */ + pathRotationOffset: 0, + + /** + * An additional vector to add to the PathFollowers position, allowing you to offset it from the + * Path coordinates. + * + * @name Phaser.GameObjects.PathFollower#pathOffset + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + pathOffset: null, + + /** + * A Vector2 that stores the current point of the path the follower is on. + * + * @name Phaser.GameObjects.PathFollower#pathVector + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + pathVector: null, + + /** + * The distance the follower has traveled from the previous point to the current one, at the last update. + * + * @name Phaser.GameObjects.PathFollower#pathDelta + * @type {Phaser.Math.Vector2} + * @since 3.23.0 + */ + pathDelta: null, + + /** + * The Tween used for following the Path. + * + * @name Phaser.GameObjects.PathFollower#pathTween + * @type {Phaser.Tweens.Tween} + * @since 3.0.0 + */ + pathTween: null, + + /** + * Settings for the PathFollower. + * + * @name Phaser.GameObjects.PathFollower#pathConfig + * @type {?Phaser.Types.GameObjects.PathFollower.PathConfig} + * @default null + * @since 3.0.0 + */ + pathConfig: null, + + /** + * Records the direction of the follower so it can change direction. + * + * @name Phaser.GameObjects.PathFollower#_prevDirection + * @type {number} + * @private + * @since 3.0.0 + */ + _prevDirection: TWEEN_CONST.PLAYING_FORWARD, + + /** + * Set the Path that this PathFollower should follow. + * + * Optionally accepts {@link Phaser.Types.GameObjects.PathFollower.PathConfig} settings. + * + * @method Phaser.GameObjects.Components.PathFollower#setPath + * @since 3.0.0 + * + * @param {Phaser.Curves.Path} path - The Path this PathFollower is following. It can only follow one Path at a time. + * @param {(number|Phaser.Types.GameObjects.PathFollower.PathConfig|Phaser.Types.Tweens.NumberTweenBuilderConfig)} [config] - Settings for the PathFollower. + * + * @return {this} This Game Object. + */ + setPath: function (path, config) + { + if (config === undefined) { config = this.pathConfig; } + + var tween = this.pathTween; + + if (tween && tween.isPlaying()) + { + tween.stop(); + } + + this.path = path; + + if (config) + { + this.startFollow(config); + } + + return this; + }, + + /** + * Set whether the PathFollower should automatically rotate to point in the direction of the Path. + * + * @method Phaser.GameObjects.Components.PathFollower#setRotateToPath + * @since 3.0.0 + * + * @param {boolean} value - Whether the PathFollower should automatically rotate to point in the direction of the Path. + * @param {number} [offset=0] - Rotation offset in degrees. + * + * @return {this} This Game Object. + */ + setRotateToPath: function (value, offset) + { + if (offset === undefined) { offset = 0; } + + this.rotateToPath = value; + + this.pathRotationOffset = offset; + + return this; + }, + + /** + * Is this PathFollower actively following a Path or not? + * + * To be considered as `isFollowing` it must be currently moving on a Path, and not paused. + * + * @method Phaser.GameObjects.Components.PathFollower#isFollowing + * @since 3.0.0 + * + * @return {boolean} `true` is this PathFollower is actively following a Path, otherwise `false`. + */ + isFollowing: function () + { + var tween = this.pathTween; + + return (tween && tween.isPlaying()); + }, + + /** + * Starts this PathFollower following its given Path. + * + * @method Phaser.GameObjects.Components.PathFollower#startFollow + * @since 3.3.0 + * + * @param {(number|Phaser.Types.GameObjects.PathFollower.PathConfig|Phaser.Types.Tweens.NumberTweenBuilderConfig)} [config={}] - The duration of the follow, or a PathFollower config object. + * @param {number} [startAt=0] - Optional start position of the follow, between 0 and 1. + * + * @return {this} This Game Object. + */ + startFollow: function (config, startAt) + { + if (config === undefined) { config = {}; } + if (startAt === undefined) { startAt = 0; } + + var tween = this.pathTween; + + if (tween && tween.isPlaying()) + { + tween.stop(); + } + + if (typeof config === 'number') + { + config = { duration: config }; + } + + // Override in case they've been specified in the config + config.from = GetValue(config, 'from', 0); + config.to = GetValue(config, 'to', 1); + + var positionOnPath = GetBoolean(config, 'positionOnPath', false); + + this.rotateToPath = GetBoolean(config, 'rotateToPath', false); + this.pathRotationOffset = GetValue(config, 'rotationOffset', 0); + + // This works, but it's not an ideal way of doing it as the follower jumps position + var seek = GetValue(config, 'startAt', startAt); + + if (seek) + { + config.onStart = function (tween) + { + var tweenData = tween.data[0]; + tweenData.progress = seek; + tweenData.elapsed = tweenData.duration * seek; + var v = tweenData.ease(tweenData.progress); + tweenData.current = tweenData.start + ((tweenData.end - tweenData.start) * v); + tweenData.setTargetValue(); + }; + } + + if (!this.pathOffset) + { + this.pathOffset = new Vector2(this.x, this.y); + } + + if (!this.pathVector) + { + this.pathVector = new Vector2(); + } + + if (!this.pathDelta) + { + this.pathDelta = new Vector2(); + } + + this.pathDelta.reset(); + + config.persist = true; + + this.pathTween = this.scene.sys.tweens.addCounter(config); + + // The starting point of the path, relative to this follower + this.path.getStartPoint(this.pathOffset); + + if (positionOnPath) + { + this.x = this.pathOffset.x; + this.y = this.pathOffset.y; + } + + this.pathOffset.x = this.x - this.pathOffset.x; + this.pathOffset.y = this.y - this.pathOffset.y; + + this._prevDirection = TWEEN_CONST.PLAYING_FORWARD; + + if (this.rotateToPath) + { + // Set the rotation now (in case the tween has a delay on it, etc) + var nextPoint = this.path.getPoint(0.1); + + this.rotation = Math.atan2(nextPoint.y - this.y, nextPoint.x - this.x) + DegToRad(this.pathRotationOffset); + } + + this.pathConfig = config; + + return this; + }, + + /** + * Pauses this PathFollower. It will still continue to render, but it will remain motionless at the + * point on the Path at which you paused it. + * + * @method Phaser.GameObjects.Components.PathFollower#pauseFollow + * @since 3.3.0 + * + * @return {this} This Game Object. + */ + pauseFollow: function () + { + var tween = this.pathTween; + + if (tween && tween.isPlaying()) + { + tween.pause(); + } + + return this; + }, + + /** + * Resumes a previously paused PathFollower. + * + * If the PathFollower was not paused this has no effect. + * + * @method Phaser.GameObjects.Components.PathFollower#resumeFollow + * @since 3.3.0 + * + * @return {this} This Game Object. + */ + resumeFollow: function () + { + var tween = this.pathTween; + + if (tween && tween.isPaused()) + { + tween.resume(); + } + + return this; + }, + + /** + * Stops this PathFollower from following the path any longer. + * + * This will invoke any 'stop' conditions that may exist on the Path, or for the follower. + * + * @method Phaser.GameObjects.Components.PathFollower#stopFollow + * @since 3.3.0 + * + * @return {this} This Game Object. + */ + stopFollow: function () + { + var tween = this.pathTween; + + if (tween && tween.isPlaying()) + { + tween.stop(); + } + + return this; + }, + + /** + * Internal update handler that advances this PathFollower along the path. + * + * Called automatically by the Scene step, should not typically be called directly. + * + * @method Phaser.GameObjects.Components.PathFollower#pathUpdate + * @since 3.17.0 + */ + pathUpdate: function () + { + var tween = this.pathTween; + + if (tween && tween.data) + { + var tweenData = tween.data[0]; + var pathDelta = this.pathDelta; + var pathVector = this.pathVector; + + pathDelta.copy(pathVector).negate(); + + if (tweenData.state === TWEEN_CONST.COMPLETE) + { + this.path.getPoint(tweenData.end, pathVector); + + pathDelta.add(pathVector); + pathVector.add(this.pathOffset); + + this.setPosition(pathVector.x, pathVector.y); + + return; + } + else if (tweenData.state !== TWEEN_CONST.PLAYING_FORWARD && tweenData.state !== TWEEN_CONST.PLAYING_BACKWARD) + { + // If delayed, etc then bail out + return; + } + + this.path.getPoint(tween.getValue(), pathVector); + + pathDelta.add(pathVector); + pathVector.add(this.pathOffset); + + var oldX = this.x; + var oldY = this.y; + + this.setPosition(pathVector.x, pathVector.y); + + var speedX = this.x - oldX; + var speedY = this.y - oldY; + + if (speedX === 0 && speedY === 0) + { + // Bail out early + return; + } + + if (tweenData.state !== this._prevDirection) + { + // We've changed direction, so don't do a rotate this frame + this._prevDirection = tweenData.state; + + return; + } + + if (this.rotateToPath) + { + this.rotation = Math.atan2(speedY, speedX) + DegToRad(this.pathRotationOffset); + } + } + } + +}; + +module.exports = PathFollower; + + +/***/ }), + +/***/ 68680: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DeepCopy = __webpack_require__(62644); + +/** + * Provides methods for setting the WebGL render nodes of a Game Object. + * + * @namespace Phaser.GameObjects.Components.RenderNodes + * @webglOnly + * @since 4.0.0 + */ +var RenderNodes = { + /** + * Customized WebGL render nodes of this Game Object. + * RenderNodes are responsible for managing the rendering process of this Game Object. + * A default set of RenderNodes are coded into the engine, + * but they will check here first to see if a custom one exists. + * + * @name Phaser.GameObjects.Components.RenderNodes#customRenderNodes + * @type {object} + * @webglOnly + * @since 4.0.0 + */ + customRenderNodes: null, + + /** + * The default RenderNodes for this Game Object. + * RenderNodes are responsible for managing the rendering process of this Game Object. + * These are the nodes that are used if no custom ones are set. + * + * RenderNodes are identified by a unique key for their role. + * + * Common role keys include: + * + * - 'Submitter': responsible for running other node roles for each element. + * - 'Transformer': responsible for providing vertex coordinates for an element. + * - 'Texturer': responsible for handling textures for an element. + * + * @name Phaser.GameObjects.Components.RenderNodes#defaultRenderNodes + * @type {object} + * @webglOnly + * @since 4.0.0 + */ + defaultRenderNodes: null, + + /** + * An object to store render node specific data in, to be read by the render nodes this Game Object uses. + * + * Render nodes store their data under their own name, not their role. + * + * @name Phaser.GameObjects.Components.RenderNodes#renderNodeData + * @type {object} + * @webglOnly + * @since 4.0.0 + */ + renderNodeData: null, + + /** + * Initializes the render nodes for this Game Object. + * + * This method is called when the Game Object is added to the Scene. + * It is responsible for setting up the default render nodes + * this Game Object will use. + * + * @method Phaser.GameObjects.Components.RenderNodes#initRenderNodes + * @webglOnly + * @since 4.0.0 + * @param {Map} defaultNodes - The default render nodes to set for this Game Object. + */ + initRenderNodes: function (defaultNodes) + { + this.customRenderNodes = {}; + this.defaultRenderNodes = {}; + this.renderNodeData = {}; + + var renderer = this.scene.sys.renderer; + + if (!renderer) + { + return; + } + + var manager = renderer.renderNodes; + + if (!(manager && defaultNodes)) + { + return; + } + + var defaultRenderNodes = this.defaultRenderNodes; + defaultNodes.each(function (role, node) + { + defaultRenderNodes[role] = manager.getNode(node); + }); + }, + + /** + * Sets the RenderNode for a given role. + * + * Also sets the relevant render node data object, if specified. + * + * If the node cannot be set, no changes are made. + * + * @method Phaser.GameObjects.Components.RenderNodes#setRenderNodeRole + * @webglOnly + * @since 4.0.0 + * @param {string} key - The key of the role to set the render node for. + * @param {string|Phaser.Renderer.WebGL.RenderNodes.RenderNode|null} renderNode - The render node to set on this Game Object. Either a string, or a RenderNode instance. If `null`, the render node is removed, along with its data. + * @param {object} [renderNodeData] - An object to store render node specific data in, to be read by the render nodes this Game Object uses. + * @param {boolean} [copyData=false] - Should the data be copied from the `renderNodeData` object? + * @return {this} This Game Object instance. + */ + setRenderNodeRole: function (key, renderNode, renderNodeData, copyData) + { + var renderer = this.scene.sys.renderer; + + if (!renderer) + { + return this; + } + + var manager = renderer.renderNodes; + + if (!manager) + { + return this; + } + + if (renderNode !== null) + { + if (typeof renderNode === 'string') + { + renderNode = manager.getNode(renderNode); + } + if (!renderNode) + { + return this; + } + this.customRenderNodes[key] = renderNode; + + if (renderNodeData) + { + this.renderNodeData[renderNode.name] = copyData ? DeepCopy(renderNodeData) : renderNodeData; + } + else + { + this.renderNodeData[renderNode.name] = {}; + } + } + else + { + var node = this.customRenderNodes[key]; + if (node) + { + delete this.renderNodeData[node.name]; + delete this.customRenderNodes[key]; + } + } + + return this; + }, + + /** + * Adds an entry to the `renderNodeData` object of this game object. + * + * If `key` is not set, it is created. If it is set, it is updated. + * + * If `value` is undefined and `key` exists, the key is removed. + * + * @method Phaser.GameObjects.Components.RenderNodes#setRenderNodeData + * @webglOnly + * @since 4.0.0 + * @param {string|Phaser.Renderer.WebGL.RenderNodes.RenderNode} renderNode - The render node to set the data for. If a string, it should be the name of the render node. + * @param {string} key - The key of the property to set. + * @param {*} value - The value to set the property to. + * @return {this} This Game Object instance. + */ + setRenderNodeData: function (renderNode, key, value) + { + var name = renderNode; + if (typeof renderNode !== 'string') + { + name = renderNode.name; + } + var data = this.renderNodeData[name]; + + if (value === undefined) + { + delete data[key]; + } + else + { + data[key] = value; + } + + return this; + } +}; + +module.exports = RenderNodes; + + +/***/ }), + +/***/ 86038: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Handles render steps for a Game Object. + * The render step is a point in the render process that allows you to inject your own logic. + * + * @namespace Phaser.GameObjects.Components.RenderSteps + * @webglOnly + * @since 4.0.0 + */ +var RenderSteps = {}; + +if (true) +{ + RenderSteps = { + /** + * The list of steps to run when this Game Object is rendered. + * This is used by `renderWebGLStep` to kick off rendering. + * The functions in this list are responsible for invoking any + * subsequent functions. + * + * @name Phaser.GameObjects.Components.RenderSteps#_renderSteps + * @private + * @webglOnly + * @since 4.0.0 + * @type {Phaser.Types.GameObjects.RenderWebGLStep[]} + */ + _renderSteps: null, + + /** + * Run a step in the render process. + * This is called automatically by the Render module. + * + * In most cases, it just runs the `renderWebGL` function. + * + * When `_renderSteps` has more than one entry, + * such as when Filters are enabled for this object, + * it allows those processes to defer `renderWebGL` + * and otherwise manage the flow of rendering. + * + * @method Phaser.GameObjects.Components.RenderSteps#renderWebGLStep + * @webglOnly + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer instance to render with. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object being rendered. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - The parent matrix of the Game Object, if it has one. + * @param {number} [renderStep=0] - Which step of the rendering process should be run? + * @param {Phaser.GameObjects.GameObject[]} [displayList] - The display list which is currently being rendered. If not provided, it will be created with the Game Object. + * @param {number} [displayListIndex=0] - The index of the Game Object within the display list. + */ + renderWebGLStep: function ( + renderer, + gameObject, + drawingContext, + parentMatrix, + renderStep, + displayList, + displayListIndex + ) + { + if (renderStep === undefined) + { + renderStep = 0; + } + + var fn = gameObject._renderSteps[renderStep]; + + if (!fn) + { + return; + } + + if (!displayList) + { + displayList = [ gameObject ]; + displayListIndex = 0; + } + else if (displayListIndex === undefined) + { + displayListIndex = 0; + } + + fn(renderer, gameObject, drawingContext, parentMatrix, renderStep, displayList, displayListIndex); + }, + + /** + * Add a render step. + * + * The first render step in `_renderSteps` is run first. + * It should call the next render step in the list. + * This allows render steps to control the rendering flow. + * + * @method Phaser.GameObjects.Components.RenderSteps#addRenderStep + * @param {Phaser.Types.GameObjects.RenderWebGLStep} fn - The render step function to add. + * @param {number} [index] - The index in the render list to add the step to. Omit to add to the end. + * + * @return {this} This Game Object instance. + */ + addRenderStep: function (fn, index) + { + if (!this._renderSteps) + { + this._renderSteps = []; + } + + if (index === undefined) + { + this._renderSteps.push(fn); + return this; + } + + this._renderSteps.splice(index, 0, fn); + + return this; + } + }; +} + +module.exports = RenderSteps; + + +/***/ }), + +/***/ 80227: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for getting and setting the Scroll Factor of a Game Object. + * + * @namespace Phaser.GameObjects.Components.ScrollFactor + * @since 3.0.0 + */ + +var ScrollFactor = { + + /** + * The horizontal scroll factor of this Game Object. + * + * The scroll factor controls the influence of the movement of a Camera upon this Game Object. + * + * When a camera scrolls it will change the location at which this Game Object is rendered on-screen. + * It does not change the Game Objects actual position values. + * + * A value of 1 means it will move exactly in sync with a camera. + * A value of 0 means it will not move at all, even if the camera moves. + * Other values control the degree to which the camera movement is mapped to this Game Object. + * + * Please be aware that scroll factor values other than 1 are not taken in to consideration when + * calculating physics collisions. Bodies always collide based on their world position, but changing + * the scroll factor is a visual adjustment to where the textures are rendered, which can offset + * them from physics bodies if not accounted for in your code. + * + * @name Phaser.GameObjects.Components.ScrollFactor#scrollFactorX + * @type {number} + * @default 1 + * @since 3.0.0 + */ + scrollFactorX: 1, + + /** + * The vertical scroll factor of this Game Object. + * + * The scroll factor controls the influence of the movement of a Camera upon this Game Object. + * + * When a camera scrolls it will change the location at which this Game Object is rendered on-screen. + * It does not change the Game Objects actual position values. + * + * A value of 1 means it will move exactly in sync with a camera. + * A value of 0 means it will not move at all, even if the camera moves. + * Other values control the degree to which the camera movement is mapped to this Game Object. + * + * Please be aware that scroll factor values other than 1 are not taken in to consideration when + * calculating physics collisions. Bodies always collide based on their world position, but changing + * the scroll factor is a visual adjustment to where the textures are rendered, which can offset + * them from physics bodies if not accounted for in your code. + * + * @name Phaser.GameObjects.Components.ScrollFactor#scrollFactorY + * @type {number} + * @default 1 + * @since 3.0.0 + */ + scrollFactorY: 1, + + /** + * Sets the scroll factor of this Game Object. + * + * The scroll factor controls the influence of the movement of a Camera upon this Game Object. + * + * When a camera scrolls it will change the location at which this Game Object is rendered on-screen. + * It does not change the Game Objects actual position values. + * + * A value of 1 means it will move exactly in sync with a camera. + * A value of 0 means it will not move at all, even if the camera moves. + * Other values control the degree to which the camera movement is mapped to this Game Object. + * + * Please be aware that scroll factor values other than 1 are not taken in to consideration when + * calculating physics collisions. Bodies always collide based on their world position, but changing + * the scroll factor is a visual adjustment to where the textures are rendered, which can offset + * them from physics bodies if not accounted for in your code. + * + * @method Phaser.GameObjects.Components.ScrollFactor#setScrollFactor + * @since 3.0.0 + * + * @param {number} x - The horizontal scroll factor of this Game Object. + * @param {number} [y=x] - The vertical scroll factor of this Game Object. If not set it will use the `x` value. + * + * @return {this} This Game Object instance. + */ + setScrollFactor: function (x, y) + { + if (y === undefined) { y = x; } + + this.scrollFactorX = x; + this.scrollFactorY = y; + + return this; + } + +}; + +module.exports = ScrollFactor; + + +/***/ }), + +/***/ 16736: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for getting and setting the size of a Game Object. + * + * @namespace Phaser.GameObjects.Components.Size + * @since 3.0.0 + */ + +var Size = { + + /** + * A property indicating that a Game Object has this component. + * + * @name Phaser.GameObjects.Components.Size#_sizeComponent + * @type {boolean} + * @private + * @default true + * @since 3.2.0 + */ + _sizeComponent: true, + + /** + * The native (un-scaled) width of this Game Object. + * + * Changing this value will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or use + * the `displayWidth` property. + * + * @name Phaser.GameObjects.Components.Size#width + * @type {number} + * @since 3.0.0 + */ + width: 0, + + /** + * The native (un-scaled) height of this Game Object. + * + * Changing this value will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or use + * the `displayHeight` property. + * + * @name Phaser.GameObjects.Components.Size#height + * @type {number} + * @since 3.0.0 + */ + height: 0, + + /** + * The displayed width of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.Components.Size#displayWidth + * @type {number} + * @since 3.0.0 + */ + displayWidth: { + + get: function () + { + return Math.abs(this.scaleX * this.frame.realWidth); + }, + + set: function (value) + { + this.scaleX = value / this.frame.realWidth; + } + + }, + + /** + * The displayed height of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.Components.Size#displayHeight + * @type {number} + * @since 3.0.0 + */ + displayHeight: { + + get: function () + { + return Math.abs(this.scaleY * this.frame.realHeight); + }, + + set: function (value) + { + this.scaleY = value / this.frame.realHeight; + } + + }, + + /** + * Sets the size of this Game Object to be that of the given Frame. + * + * This will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or call the + * `setDisplaySize` method, which is the same thing as changing the scale but allows you + * to do so by giving pixel values. + * + * If you have enabled this Game Object for input, changing the size will _not_ change the + * size of the hit area. To do this you should adjust the `input.hitArea` object directly. + * + * @method Phaser.GameObjects.Components.Size#setSizeToFrame + * @since 3.0.0 + * + * @param {Phaser.Textures.Frame|boolean} [frame] - The frame to base the size of this Game Object on. + * + * @return {this} This Game Object instance. + */ + setSizeToFrame: function (frame) + { + if (!frame) { frame = this.frame; } + + this.width = frame.realWidth; + this.height = frame.realHeight; + + var input = this.input; + + if (input && !input.customHitArea) + { + input.hitArea.width = this.width; + input.hitArea.height = this.height; + } + + return this; + }, + + /** + * Sets the internal size of this Game Object, as used for frame or physics body creation. + * + * This will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or call the + * `setDisplaySize` method, which is the same thing as changing the scale but allows you + * to do so by giving pixel values. + * + * If you have enabled this Game Object for input, changing the size will _not_ change the + * size of the hit area. To do this you should adjust the `input.hitArea` object directly. + * + * @method Phaser.GameObjects.Components.Size#setSize + * @since 3.0.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + + return this; + }, + + /** + * Sets the display size of this Game Object. + * + * Calling this will adjust the scale. + * + * @method Phaser.GameObjects.Components.Size#setDisplaySize + * @since 3.0.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setDisplaySize: function (width, height) + { + this.displayWidth = width; + this.displayHeight = height; + + return this; + } + +}; + +module.exports = Size; + + +/***/ }), + +/***/ 37726: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Frame = __webpack_require__(4327); + +// bitmask flag for GameObject.renderMask +var _FLAG = 8; // 1000 + +/** + * Provides methods used for getting and setting the texture of a Game Object. + * + * @namespace Phaser.GameObjects.Components.Texture + * @since 3.0.0 + */ + +var Texture = { + + /** + * The Texture this Game Object is using to render with. + * + * @name Phaser.GameObjects.Components.Texture#texture + * @type {Phaser.Textures.Texture|Phaser.Textures.CanvasTexture} + * @since 3.0.0 + */ + texture: null, + + /** + * The Texture Frame this Game Object is using to render with. + * + * @name Phaser.GameObjects.Components.Texture#frame + * @type {Phaser.Textures.Frame} + * @since 3.0.0 + */ + frame: null, + + /** + * Internal flag. Not to be set by this Game Object. + * + * @name Phaser.GameObjects.Components.Texture#isCropped + * @type {boolean} + * @private + * @since 3.11.0 + */ + isCropped: false, + + /** + * Sets the texture and frame this Game Object will use to render with. + * + * Textures are referenced by their string-based keys, as stored in the Texture Manager. + * + * Calling this method will modify the `width` and `height` properties of your Game Object. + * + * It will also change the `origin` if the Frame has a custom pivot point, as exported from packages like Texture Packer. + * + * @method Phaser.GameObjects.Components.Texture#setTexture + * @since 3.0.0 + * + * @param {(string|Phaser.Textures.Texture)} key - The key of the texture to be used, as stored in the Texture Manager, or a Texture instance. + * @param {(string|number)} [frame] - The name or index of the frame within the Texture. + * @param {boolean} [updateSize=true] - Should this call adjust the size of the Game Object? + * @param {boolean} [updateOrigin=true] - Should this call change the origin of the Game Object? + * + * @return {this} This Game Object instance. + */ + setTexture: function (key, frame, updateSize, updateOrigin) + { + this.texture = this.scene.sys.textures.get(key); + + return this.setFrame(frame, updateSize, updateOrigin); + }, + + /** + * Sets the frame this Game Object will use to render with. + * + * If you pass a string or index then the Frame has to belong to the current Texture being used + * by this Game Object. + * + * If you pass a Frame instance, then the Texture being used by this Game Object will also be updated. + * + * Calling `setFrame` will modify the `width` and `height` properties of your Game Object. + * + * It will also change the `origin` if the Frame has a custom pivot point, as exported from packages like Texture Packer. + * + * @method Phaser.GameObjects.Components.Texture#setFrame + * @since 3.0.0 + * + * @param {(string|number|Phaser.Textures.Frame)} frame - The name or index of the frame within the Texture, or a Frame instance. + * @param {boolean} [updateSize=true] - Should this call adjust the size of the Game Object? + * @param {boolean} [updateOrigin=true] - Should this call adjust the origin of the Game Object? + * + * @return {this} This Game Object instance. + */ + setFrame: function (frame, updateSize, updateOrigin) + { + if (updateSize === undefined) { updateSize = true; } + if (updateOrigin === undefined) { updateOrigin = true; } + + if (frame instanceof Frame) + { + this.texture = this.scene.sys.textures.get(frame.texture.key); + + this.frame = frame; + } + else + { + this.frame = this.texture.get(frame); + } + + if (!this.frame.cutWidth || !this.frame.cutHeight) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + + if (this._sizeComponent && updateSize) + { + this.setSizeToFrame(); + } + + if (this._originComponent && updateOrigin) + { + if (this.frame.customPivot) + { + this.setOrigin(this.frame.pivotX, this.frame.pivotY); + } + else + { + this.updateDisplayOrigin(); + } + } + + return this; + } + +}; + +module.exports = Texture; + + +/***/ }), + +/***/ 79812: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Frame = __webpack_require__(4327); + +// bitmask flag for GameObject.renderMask +var _FLAG = 8; // 1000 + +/** + * Provides methods used for getting and setting the texture of a Game Object. + * + * @namespace Phaser.GameObjects.Components.TextureCrop + * @since 3.0.0 + */ + +var TextureCrop = { + + /** + * The Texture this Game Object is using to render with. + * + * @name Phaser.GameObjects.Components.TextureCrop#texture + * @type {Phaser.Textures.Texture|Phaser.Textures.CanvasTexture} + * @since 3.0.0 + */ + texture: null, + + /** + * The Texture Frame this Game Object is using to render with. + * + * @name Phaser.GameObjects.Components.TextureCrop#frame + * @type {Phaser.Textures.Frame} + * @since 3.0.0 + */ + frame: null, + + /** + * A boolean flag indicating if this Game Object is being cropped or not. + * You can toggle this at any time after `setCrop` has been called, to turn cropping on or off. + * Equally, calling `setCrop` with no arguments will reset the crop and disable it. + * + * @name Phaser.GameObjects.Components.TextureCrop#isCropped + * @type {boolean} + * @since 3.11.0 + */ + isCropped: false, + + /** + * Applies a crop to a texture based Game Object, such as a Sprite or Image. + * + * The crop is a rectangle that limits the area of the texture frame that is visible during rendering. + * + * Cropping a Game Object does not change its size, dimensions, physics body or hit area, it just + * changes what is shown when rendered. + * + * The crop size as well as coordinates can not exceed the the size of the texture frame. + * + * The crop coordinates are relative to the texture frame, not the Game Object, meaning 0 x 0 is the top-left. + * + * Therefore, if you had a Game Object that had an 800x600 sized texture, and you wanted to show only the left + * half of it, you could call `setCrop(0, 0, 400, 600)`. + * + * It is also scaled to match the Game Object scale automatically. Therefore a crop rectangle of 100x50 would crop + * an area of 200x100 when applied to a Game Object that had a scale factor of 2. + * + * You can either pass in numeric values directly, or you can provide a single Rectangle object as the first argument. + * + * Call this method with no arguments at all to reset the crop, or toggle the property `isCropped` to `false`. + * + * You should do this if the crop rectangle becomes the same size as the frame itself, as it will allow + * the renderer to skip several internal calculations. + * + * @method Phaser.GameObjects.Components.TextureCrop#setCrop + * @since 3.11.0 + * + * @param {(number|Phaser.Geom.Rectangle)} [x] - The x coordinate to start the crop from. Cannot be negative or exceed the Frame width. Or a Phaser.Geom.Rectangle object, in which case the rest of the arguments are ignored. + * @param {number} [y] - The y coordinate to start the crop from. Cannot be negative or exceed the Frame height. + * @param {number} [width] - The width of the crop rectangle in pixels. Cannot exceed the Frame width. + * @param {number} [height] - The height of the crop rectangle in pixels. Cannot exceed the Frame height. + * + * @return {this} This Game Object instance. + */ + setCrop: function (x, y, width, height) + { + if (x === undefined) + { + this.isCropped = false; + } + else if (this.frame) + { + if (typeof x === 'number') + { + this.frame.setCropUVs(this._crop, x, y, width, height, this.flipX, this.flipY); + } + else + { + var rect = x; + + this.frame.setCropUVs(this._crop, rect.x, rect.y, rect.width, rect.height, this.flipX, this.flipY); + } + + this.isCropped = true; + } + + return this; + }, + + /** + * Sets the texture and frame this Game Object will use to render with. + * + * Textures are referenced by their string-based keys, as stored in the Texture Manager. + * + * @method Phaser.GameObjects.Components.TextureCrop#setTexture + * @since 3.0.0 + * + * @param {string} key - The key of the texture to be used, as stored in the Texture Manager. + * @param {(string|number)} [frame] - The name or index of the frame within the Texture. + * + * @return {this} This Game Object instance. + */ + setTexture: function (key, frame) + { + this.texture = this.scene.sys.textures.get(key); + + return this.setFrame(frame); + }, + + /** + * Sets the frame this Game Object will use to render with. + * + * If you pass a string or index then the Frame has to belong to the current Texture being used + * by this Game Object. + * + * If you pass a Frame instance, then the Texture being used by this Game Object will also be updated. + * + * Calling `setFrame` will modify the `width` and `height` properties of your Game Object. + * + * It will also change the `origin` if the Frame has a custom pivot point, as exported from packages like Texture Packer. + * + * @method Phaser.GameObjects.Components.TextureCrop#setFrame + * @since 3.0.0 + * + * @param {(string|number|Phaser.Textures.Frame)} frame - The name or index of the frame within the Texture, or a Frame instance. + * @param {boolean} [updateSize=true] - Should this call adjust the size of the Game Object? + * @param {boolean} [updateOrigin=true] - Should this call adjust the origin of the Game Object? + * + * @return {this} This Game Object instance. + */ + setFrame: function (frame, updateSize, updateOrigin) + { + if (updateSize === undefined) { updateSize = true; } + if (updateOrigin === undefined) { updateOrigin = true; } + + if (frame instanceof Frame) + { + this.texture = this.scene.sys.textures.get(frame.texture.key); + + this.frame = frame; + } + else + { + this.frame = this.texture.get(frame); + } + + if (!this.frame.cutWidth || !this.frame.cutHeight) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + + if (this._sizeComponent && updateSize) + { + this.setSizeToFrame(); + } + + if (this._originComponent && updateOrigin) + { + if (this.frame.customPivot) + { + this.setOrigin(this.frame.pivotX, this.frame.pivotY); + } + else + { + this.updateDisplayOrigin(); + } + } + + if (this.isCropped) + { + this.frame.updateCropUVs(this._crop, this.flipX, this.flipY); + } + + return this; + }, + + /** + * Internal method that returns a blank, well-formed crop object for use by a Game Object. + * + * @method Phaser.GameObjects.Components.TextureCrop#resetCropObject + * @private + * @since 3.12.0 + * + * @return {object} The crop object. + */ + resetCropObject: function () + { + return { u0: 0, v0: 0, u1: 0, v1: 0, width: 0, height: 0, x: 0, y: 0, flipX: false, flipY: false, cx: 0, cy: 0, cw: 0, ch: 0 }; + } + +}; + +module.exports = TextureCrop; + + +/***/ }), + +/***/ 27472: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the tint of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.Tint + * @webglOnly + * @since 3.0.0 + */ + +var Tint = { + + /** + * The tint value being applied to the top-left vertice of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple. + * + * @name Phaser.GameObjects.Components.Tint#tintTopLeft + * @type {number} + * @default 0xffffff + * @since 3.0.0 + */ + tintTopLeft: 0xffffff, + + /** + * The tint value being applied to the top-right vertice of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple. + * + * @name Phaser.GameObjects.Components.Tint#tintTopRight + * @type {number} + * @default 0xffffff + * @since 3.0.0 + */ + tintTopRight: 0xffffff, + + /** + * The tint value being applied to the bottom-left vertice of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple. + * + * @name Phaser.GameObjects.Components.Tint#tintBottomLeft + * @type {number} + * @default 0xffffff + * @since 3.0.0 + */ + tintBottomLeft: 0xffffff, + + /** + * The tint value being applied to the bottom-right vertice of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple. + * + * @name Phaser.GameObjects.Components.Tint#tintBottomRight + * @type {number} + * @default 0xffffff + * @since 3.0.0 + */ + tintBottomRight: 0xffffff, + + /** + * The tint fill mode. + * + * `false` = An additive tint (the default), where vertices colors are blended with the texture. + * `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha. + * + * @name Phaser.GameObjects.Components.Tint#tintFill + * @type {boolean} + * @default false + * @since 3.11.0 + */ + tintFill: false, + + /** + * Clears all tint values associated with this Game Object. + * + * Immediately sets the color values back to 0xffffff and the tint type to 'additive', + * which results in no visible change to the texture. + * + * @method Phaser.GameObjects.Components.Tint#clearTint + * @webglOnly + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + clearTint: function () + { + this.setTint(0xffffff); + + return this; + }, + + /** + * Sets an additive tint on this Game Object. + * + * The tint works by taking the pixel color values from the Game Objects texture, and then + * multiplying it by the color value of the tint. You can provide either one color value, + * in which case the whole Game Object will be tinted in that color. Or you can provide a color + * per corner. The colors are blended together across the extent of the Game Object. + * + * To modify the tint color once set, either call this method again with new values or use the + * `tint` property to set all colors at once. Or, use the properties `tintTopLeft`, `tintTopRight, + * `tintBottomLeft` and `tintBottomRight` to set the corner color values independently. + * + * To remove a tint call `clearTint`. + * + * To swap this from being an additive tint to a fill based tint set the property `tintFill` to `true`. + * + * @method Phaser.GameObjects.Components.Tint#setTint + * @webglOnly + * @since 3.0.0 + * + * @param {number} [topLeft=0xffffff] - The tint being applied to the top-left of the Game Object. If no other values are given this value is applied evenly, tinting the whole Game Object. + * @param {number} [topRight] - The tint being applied to the top-right of the Game Object. + * @param {number} [bottomLeft] - The tint being applied to the bottom-left of the Game Object. + * @param {number} [bottomRight] - The tint being applied to the bottom-right of the Game Object. + * + * @return {this} This Game Object instance. + */ + setTint: function (topLeft, topRight, bottomLeft, bottomRight) + { + if (topLeft === undefined) { topLeft = 0xffffff; } + + if (topRight === undefined) + { + topRight = topLeft; + bottomLeft = topLeft; + bottomRight = topLeft; + } + + this.tintTopLeft = topLeft; + this.tintTopRight = topRight; + this.tintBottomLeft = bottomLeft; + this.tintBottomRight = bottomRight; + + this.tintFill = false; + + return this; + }, + + /** + * Sets a fill-based tint on this Game Object. + * + * Unlike an additive tint, a fill-tint literally replaces the pixel colors from the texture + * with those in the tint. You can use this for effects such as making a player flash 'white' + * if hit by something. You can provide either one color value, in which case the whole + * Game Object will be rendered in that color. Or you can provide a color per corner. The colors + * are blended together across the extent of the Game Object. + * + * To modify the tint color once set, either call this method again with new values or use the + * `tint` property to set all colors at once. Or, use the properties `tintTopLeft`, `tintTopRight, + * `tintBottomLeft` and `tintBottomRight` to set the corner color values independently. + * + * To remove a tint call `clearTint`. + * + * To swap this from being a fill-tint to an additive tint set the property `tintFill` to `false`. + * + * @method Phaser.GameObjects.Components.Tint#setTintFill + * @webglOnly + * @since 3.11.0 + * + * @param {number} [topLeft=0xffffff] - The tint being applied to the top-left of the Game Object. If not other values are given this value is applied evenly, tinting the whole Game Object. + * @param {number} [topRight] - The tint being applied to the top-right of the Game Object. + * @param {number} [bottomLeft] - The tint being applied to the bottom-left of the Game Object. + * @param {number} [bottomRight] - The tint being applied to the bottom-right of the Game Object. + * + * @return {this} This Game Object instance. + */ + setTintFill: function (topLeft, topRight, bottomLeft, bottomRight) + { + this.setTint(topLeft, topRight, bottomLeft, bottomRight); + + this.tintFill = true; + + return this; + }, + + /** + * The tint value being applied to the whole of the Game Object. + * Return `tintTopLeft` when read this tint property. + * + * @name Phaser.GameObjects.Components.Tint#tint + * @type {number} + * @webglOnly + * @since 3.0.0 + */ + tint: { + + get: function () + { + return this.tintTopLeft; + }, + + set: function (value) + { + this.setTint(value, value, value, value); + } + }, + + /** + * Does this Game Object have a tint applied? + * + * It checks to see if the 4 tint properties are set to the value 0xffffff + * and that the `tintFill` property is `false`. This indicates that a Game Object isn't tinted. + * + * @name Phaser.GameObjects.Components.Tint#isTinted + * @type {boolean} + * @webglOnly + * @readonly + * @since 3.11.0 + */ + isTinted: { + + get: function () + { + var white = 0xffffff; + + return ( + this.tintFill || + this.tintTopLeft !== white || + this.tintTopRight !== white || + this.tintBottomLeft !== white || + this.tintBottomRight !== white + ); + } + + } + +}; + +module.exports = Tint; + + +/***/ }), + +/***/ 53774: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Build a JSON representation of the given Game Object. + * + * This is typically extended further by Game Object specific implementations. + * + * @method Phaser.GameObjects.Components.ToJSON + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to export as JSON. + * + * @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object. + */ +var ToJSON = function (gameObject) +{ + var out = { + name: gameObject.name, + type: gameObject.type, + x: gameObject.x, + y: gameObject.y, + depth: gameObject.depth, + scale: { + x: gameObject.scaleX, + y: gameObject.scaleY + }, + origin: { + x: gameObject.originX, + y: gameObject.originY + }, + flipX: gameObject.flipX, + flipY: gameObject.flipY, + rotation: gameObject.rotation, + alpha: gameObject.alpha, + visible: gameObject.visible, + blendMode: gameObject.blendMode, + textureKey: '', + frameKey: '', + data: {} + }; + + if (gameObject.texture) + { + out.textureKey = gameObject.texture.key; + out.frameKey = gameObject.frame.name; + } + + return out; +}; + +module.exports = ToJSON; + + +/***/ }), + +/***/ 16901: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = __webpack_require__(36383); +var TransformMatrix = __webpack_require__(61340); +var TransformXY = __webpack_require__(85955); +var WrapAngle = __webpack_require__(86554); +var WrapAngleDegrees = __webpack_require__(30954); +var Vector2 = __webpack_require__(26099); + +// global bitmask flag for GameObject.renderMask (used by Scale) +var _FLAG = 4; // 0100 + +/** + * Provides methods used for getting and setting the position, scale and rotation of a Game Object. + * + * @namespace Phaser.GameObjects.Components.Transform + * @since 3.0.0 + */ + +var Transform = { + + /** + * A property indicating that a Game Object has this component. + * + * @name Phaser.GameObjects.Components.Transform#hasTransformComponent + * @type {boolean} + * @readonly + * @default true + * @since 3.60.0 + */ + hasTransformComponent: true, + + /** + * Private internal value. Holds the horizontal scale value. + * + * @name Phaser.GameObjects.Components.Transform#_scaleX + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _scaleX: 1, + + /** + * Private internal value. Holds the vertical scale value. + * + * @name Phaser.GameObjects.Components.Transform#_scaleY + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + _scaleY: 1, + + /** + * Private internal value. Holds the rotation value in radians. + * + * @name Phaser.GameObjects.Components.Transform#_rotation + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + _rotation: 0, + + /** + * The x position of this Game Object. + * + * @name Phaser.GameObjects.Components.Transform#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + x: 0, + + /** + * The y position of this Game Object. + * + * @name Phaser.GameObjects.Components.Transform#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + y: 0, + + /** + * The z position of this Game Object. + * + * Note: The z position does not control the rendering order of 2D Game Objects. Use + * {@link Phaser.GameObjects.Components.Depth#depth} instead. + * + * @name Phaser.GameObjects.Components.Transform#z + * @type {number} + * @default 0 + * @since 3.0.0 + */ + z: 0, + + /** + * The w position of this Game Object. + * + * @name Phaser.GameObjects.Components.Transform#w + * @type {number} + * @default 0 + * @since 3.0.0 + */ + w: 0, + + /** + * This is a special setter that allows you to set both the horizontal and vertical scale of this Game Object + * to the same value, at the same time. When reading this value the result returned is `(scaleX + scaleY) / 2`. + * + * Use of this property implies you wish the horizontal and vertical scales to be equal to each other. If this + * isn't the case, use the `scaleX` or `scaleY` properties instead. + * + * @name Phaser.GameObjects.Components.Transform#scale + * @type {number} + * @default 1 + * @since 3.18.0 + */ + scale: { + + get: function () + { + return (this._scaleX + this._scaleY) / 2; + }, + + set: function (value) + { + this._scaleX = value; + this._scaleY = value; + + if (value === 0) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The horizontal scale of this Game Object. + * + * @name Phaser.GameObjects.Components.Transform#scaleX + * @type {number} + * @default 1 + * @since 3.0.0 + */ + scaleX: { + + get: function () + { + return this._scaleX; + }, + + set: function (value) + { + this._scaleX = value; + + if (value === 0) + { + this.renderFlags &= ~_FLAG; + } + else if (this._scaleY !== 0) + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The vertical scale of this Game Object. + * + * @name Phaser.GameObjects.Components.Transform#scaleY + * @type {number} + * @default 1 + * @since 3.0.0 + */ + scaleY: { + + get: function () + { + return this._scaleY; + }, + + set: function (value) + { + this._scaleY = value; + + if (value === 0) + { + this.renderFlags &= ~_FLAG; + } + else if (this._scaleX !== 0) + { + this.renderFlags |= _FLAG; + } + } + + }, + + /** + * The angle of this Game Object as expressed in degrees. + * + * Phaser uses a right-hand clockwise rotation system, where 0 is right, 90 is down, 180/-180 is left + * and -90 is up. + * + * If you prefer to work in radians, see the `rotation` property instead. + * + * @name Phaser.GameObjects.Components.Transform#angle + * @type {number} + * @default 0 + * @since 3.0.0 + */ + angle: { + + get: function () + { + return WrapAngleDegrees(this._rotation * MATH_CONST.RAD_TO_DEG); + }, + + set: function (value) + { + // value is in degrees + this.rotation = WrapAngleDegrees(value) * MATH_CONST.DEG_TO_RAD; + } + }, + + /** + * The angle of this Game Object in radians. + * + * Phaser uses a right-hand clockwise rotation system, where 0 is right, PI/2 is down, +-PI is left + * and -PI/2 is up. + * + * If you prefer to work in degrees, see the `angle` property instead. + * + * @name Phaser.GameObjects.Components.Transform#rotation + * @type {number} + * @default 1 + * @since 3.0.0 + */ + rotation: { + + get: function () + { + return this._rotation; + }, + + set: function (value) + { + // value is in radians + this._rotation = WrapAngle(value); + } + }, + + /** + * Sets the position of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setPosition + * @since 3.0.0 + * + * @param {number} [x=0] - The x position of this Game Object. + * @param {number} [y=x] - The y position of this Game Object. If not set it will use the `x` value. + * @param {number} [z=0] - The z position of this Game Object. + * @param {number} [w=0] - The w position of this Game Object. + * + * @return {this} This Game Object instance. + */ + setPosition: function (x, y, z, w) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = x; } + if (z === undefined) { z = 0; } + if (w === undefined) { w = 0; } + + this.x = x; + this.y = y; + this.z = z; + this.w = w; + + return this; + }, + + /** + * Copies an object's coordinates to this Game Object's position. + * + * @method Phaser.GameObjects.Components.Transform#copyPosition + * @since 3.50.0 + * + * @param {(Phaser.Types.Math.Vector2Like|Phaser.Types.Math.Vector3Like|Phaser.Types.Math.Vector4Like)} source - An object with numeric 'x', 'y', 'z', or 'w' properties. Undefined values are not copied. + * + * @return {this} This Game Object instance. + */ + copyPosition: function (source) + { + if (source.x !== undefined) { this.x = source.x; } + if (source.y !== undefined) { this.y = source.y; } + if (source.z !== undefined) { this.z = source.z; } + if (source.w !== undefined) { this.w = source.w; } + + return this; + }, + + /** + * Sets the position of this Game Object to be a random position within the confines of + * the given area. + * + * If no area is specified a random position between 0 x 0 and the game width x height is used instead. + * + * The position does not factor in the size of this Game Object, meaning that only the origin is + * guaranteed to be within the area. + * + * @method Phaser.GameObjects.Components.Transform#setRandomPosition + * @since 3.8.0 + * + * @param {number} [x=0] - The x position of the top-left of the random area. + * @param {number} [y=0] - The y position of the top-left of the random area. + * @param {number} [width] - The width of the random area. + * @param {number} [height] - The height of the random area. + * + * @return {this} This Game Object instance. + */ + setRandomPosition: function (x, y, width, height) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.scene.sys.scale.width; } + if (height === undefined) { height = this.scene.sys.scale.height; } + + this.x = x + (Math.random() * width); + this.y = y + (Math.random() * height); + + return this; + }, + + /** + * Sets the rotation of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setRotation + * @since 3.0.0 + * + * @param {number} [radians=0] - The rotation of this Game Object, in radians. + * + * @return {this} This Game Object instance. + */ + setRotation: function (radians) + { + if (radians === undefined) { radians = 0; } + + this.rotation = radians; + + return this; + }, + + /** + * Sets the angle of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setAngle + * @since 3.0.0 + * + * @param {number} [degrees=0] - The rotation of this Game Object, in degrees. + * + * @return {this} This Game Object instance. + */ + setAngle: function (degrees) + { + if (degrees === undefined) { degrees = 0; } + + this.angle = degrees; + + return this; + }, + + /** + * Sets the scale of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setScale + * @since 3.0.0 + * + * @param {number} [x=1] - The horizontal scale of this Game Object. + * @param {number} [y=x] - The vertical scale of this Game Object. If not set it will use the `x` value. + * + * @return {this} This Game Object instance. + */ + setScale: function (x, y) + { + if (x === undefined) { x = 1; } + if (y === undefined) { y = x; } + + this.scaleX = x; + this.scaleY = y; + + return this; + }, + + /** + * Sets the x position of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setX + * @since 3.0.0 + * + * @param {number} [value=0] - The x position of this Game Object. + * + * @return {this} This Game Object instance. + */ + setX: function (value) + { + if (value === undefined) { value = 0; } + + this.x = value; + + return this; + }, + + /** + * Sets the y position of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setY + * @since 3.0.0 + * + * @param {number} [value=0] - The y position of this Game Object. + * + * @return {this} This Game Object instance. + */ + setY: function (value) + { + if (value === undefined) { value = 0; } + + this.y = value; + + return this; + }, + + /** + * Sets the z position of this Game Object. + * + * Note: The z position does not control the rendering order of 2D Game Objects. Use + * {@link Phaser.GameObjects.Components.Depth#setDepth} instead. + * + * @method Phaser.GameObjects.Components.Transform#setZ + * @since 3.0.0 + * + * @param {number} [value=0] - The z position of this Game Object. + * + * @return {this} This Game Object instance. + */ + setZ: function (value) + { + if (value === undefined) { value = 0; } + + this.z = value; + + return this; + }, + + /** + * Sets the w position of this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#setW + * @since 3.0.0 + * + * @param {number} [value=0] - The w position of this Game Object. + * + * @return {this} This Game Object instance. + */ + setW: function (value) + { + if (value === undefined) { value = 0; } + + this.w = value; + + return this; + }, + + /** + * Gets the local transform matrix for this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#getLocalTransformMatrix + * @since 3.4.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object. + * + * @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix. + */ + getLocalTransformMatrix: function (tempMatrix) + { + if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); } + + return tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY); + }, + + /** + * Gets the world transform matrix for this Game Object, factoring in any parent Containers. + * + * @method Phaser.GameObjects.Components.Transform#getWorldTransformMatrix + * @since 3.4.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - A temporary matrix to hold parent values during the calculations. + * + * @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix. + */ + getWorldTransformMatrix: function (tempMatrix, parentMatrix) + { + if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); } + + var parent = this.parentContainer; + + if (!parent) + { + return this.getLocalTransformMatrix(tempMatrix); + } + + var destroyParentMatrix = false; + + if (!parentMatrix) + { + parentMatrix = new TransformMatrix(); + + destroyParentMatrix = true; + } + + tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY); + + while (parent) + { + parentMatrix.applyITRS(parent.x, parent.y, parent._rotation, parent._scaleX, parent._scaleY); + + parentMatrix.multiply(tempMatrix, tempMatrix); + + parent = parent.parentContainer; + } + + if (destroyParentMatrix) + { + parentMatrix.destroy(); + } + + return tempMatrix; + }, + + /** + * Takes the given `x` and `y` coordinates and converts them into local space for this + * Game Object, taking into account parent and local transforms, and the Display Origin. + * + * The returned Vector2 contains the translated point in its properties. + * + * A Camera needs to be provided in order to handle modified scroll factors. If no + * camera is specified, it will use the `main` camera from the Scene to which this + * Game Object belongs. + * + * @method Phaser.GameObjects.Components.Transform#getLocalPoint + * @since 3.50.0 + * + * @param {number} x - The x position to translate. + * @param {number} y - The y position to translate. + * @param {Phaser.Math.Vector2} [point] - A Vector2, or point-like object, to store the results in. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera which is being tested against. If not given will use the Scene default camera. + * + * @return {Phaser.Math.Vector2} The translated point. + */ + getLocalPoint: function (x, y, point, camera) + { + if (!point) { point = new Vector2(); } + if (!camera) { camera = this.scene.sys.cameras.main; } + + var csx = camera.scrollX; + var csy = camera.scrollY; + + var px = x + (csx * this.scrollFactorX) - csx; + var py = y + (csy * this.scrollFactorY) - csy; + + if (this.parentContainer) + { + this.getWorldTransformMatrix().applyInverse(px, py, point); + } + else + { + TransformXY(px, py, this.x, this.y, this.rotation, this.scaleX, this.scaleY, point); + } + + // Normalize origin + if (this._originComponent) + { + point.x += this._displayOriginX; + point.y += this._displayOriginY; + } + + return point; + }, + + /** + * Gets the world position of this Game Object, factoring in any parent Containers. + * + * @method Phaser.GameObjects.Components.Transform#getWorldPoint + * @since 3.88.0 + * + * @param {Phaser.Math.Vector2} [point] - A Vector2, or point-like object, to store the result in. + * @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - A temporary matrix to hold the Game Object's values. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - A temporary matrix to hold parent values. + * + * @return {Phaser.Math.Vector2} The world position of this Game Object. + */ + getWorldPoint: function (point, tempMatrix, parentMatrix) + { + if (point === undefined) { point = new Vector2(); } + + var parent = this.parentContainer; + + if (!parent) + { + point.x = this.x; + point.y = this.y; + + return point; + } + + var worldTransform = this.getWorldTransformMatrix(tempMatrix, parentMatrix); + + point.x = worldTransform.tx; + point.y = worldTransform.ty; + + return point; + }, + + /** + * Gets the sum total rotation of all of this Game Objects parent Containers. + * + * The returned value is in radians and will be zero if this Game Object has no parent container. + * + * @method Phaser.GameObjects.Components.Transform#getParentRotation + * @since 3.18.0 + * + * @return {number} The sum total rotation, in radians, of all parent containers of this Game Object. + */ + getParentRotation: function () + { + var rotation = 0; + + var parent = this.parentContainer; + + while (parent) + { + rotation += parent.rotation; + + parent = parent.parentContainer; + } + + return rotation; + } + +}; + +module.exports = Transform; + + +/***/ }), + +/***/ 61340: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var MATH_CONST = __webpack_require__(36383); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Matrix used for display transformations for rendering. + * + * It is represented like so: + * + * ``` + * | a | c | tx | + * | b | d | ty | + * | 0 | 0 | 1 | + * ``` + * + * @class TransformMatrix + * @memberof Phaser.GameObjects.Components + * @constructor + * @since 3.0.0 + * + * @param {number} [a=1] - The Scale X value. + * @param {number} [b=0] - The Skew Y value. + * @param {number} [c=0] - The Skew X value. + * @param {number} [d=1] - The Scale Y value. + * @param {number} [tx=0] - The Translate X value. + * @param {number} [ty=0] - The Translate Y value. + */ +var TransformMatrix = new Class({ + + initialize: + + function TransformMatrix (a, b, c, d, tx, ty) + { + if (a === undefined) { a = 1; } + if (b === undefined) { b = 0; } + if (c === undefined) { c = 0; } + if (d === undefined) { d = 1; } + if (tx === undefined) { tx = 0; } + if (ty === undefined) { ty = 0; } + + /** + * The matrix values. + * + * @name Phaser.GameObjects.Components.TransformMatrix#matrix + * @type {Float32Array} + * @since 3.0.0 + */ + this.matrix = new Float32Array([ a, b, c, d, tx, ty, 0, 0, 1 ]); + + /** + * The decomposed matrix. + * + * @name Phaser.GameObjects.Components.TransformMatrix#decomposedMatrix + * @type {object} + * @since 3.0.0 + */ + this.decomposedMatrix = { + translateX: 0, + translateY: 0, + scaleX: 1, + scaleY: 1, + rotation: 0 + }; + + /** + * The temporary quad value cache. + * + * @name Phaser.GameObjects.Components.TransformMatrix#quad + * @type {Float32Array} + * @since 3.60.0 + */ + this.quad = new Float32Array(8); + }, + + /** + * The Scale X value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#a + * @type {number} + * @since 3.4.0 + */ + a: { + + get: function () + { + return this.matrix[0]; + }, + + set: function (value) + { + this.matrix[0] = value; + } + + }, + + /** + * The Skew Y value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#b + * @type {number} + * @since 3.4.0 + */ + b: { + + get: function () + { + return this.matrix[1]; + }, + + set: function (value) + { + this.matrix[1] = value; + } + + }, + + /** + * The Skew X value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#c + * @type {number} + * @since 3.4.0 + */ + c: { + + get: function () + { + return this.matrix[2]; + }, + + set: function (value) + { + this.matrix[2] = value; + } + + }, + + /** + * The Scale Y value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#d + * @type {number} + * @since 3.4.0 + */ + d: { + + get: function () + { + return this.matrix[3]; + }, + + set: function (value) + { + this.matrix[3] = value; + } + + }, + + /** + * The Translate X value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#e + * @type {number} + * @since 3.11.0 + */ + e: { + + get: function () + { + return this.matrix[4]; + }, + + set: function (value) + { + this.matrix[4] = value; + } + + }, + + /** + * The Translate Y value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#f + * @type {number} + * @since 3.11.0 + */ + f: { + + get: function () + { + return this.matrix[5]; + }, + + set: function (value) + { + this.matrix[5] = value; + } + + }, + + /** + * The Translate X value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#tx + * @type {number} + * @since 3.4.0 + */ + tx: { + + get: function () + { + return this.matrix[4]; + }, + + set: function (value) + { + this.matrix[4] = value; + } + + }, + + /** + * The Translate Y value. + * + * @name Phaser.GameObjects.Components.TransformMatrix#ty + * @type {number} + * @since 3.4.0 + */ + ty: { + + get: function () + { + return this.matrix[5]; + }, + + set: function (value) + { + this.matrix[5] = value; + } + + }, + + /** + * The rotation of the Matrix. Value is in radians. + * + * @name Phaser.GameObjects.Components.TransformMatrix#rotation + * @type {number} + * @readonly + * @since 3.4.0 + */ + rotation: { + + get: function () + { + return Math.acos(this.a / this.scaleX) * ((Math.atan(-this.c / this.a) < 0) ? -1 : 1); + } + + }, + + /** + * The rotation of the Matrix, normalized to be within the Phaser right-handed + * clockwise rotation space. Value is in radians. + * + * @name Phaser.GameObjects.Components.TransformMatrix#rotationNormalized + * @type {number} + * @readonly + * @since 3.19.0 + */ + rotationNormalized: { + + get: function () + { + var matrix = this.matrix; + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + + if (a || b) + { + // var r = Math.sqrt(a * a + b * b); + + return (b > 0) ? Math.acos(a / this.scaleX) : -Math.acos(a / this.scaleX); + } + else if (c || d) + { + // var s = Math.sqrt(c * c + d * d); + + return MATH_CONST.PI_OVER_2 - ((d > 0) ? Math.acos(-c / this.scaleY) : -Math.acos(c / this.scaleY)); + } + else + { + return 0; + } + } + + }, + + /** + * The decomposed horizontal scale of the Matrix. This value is always positive. + * + * @name Phaser.GameObjects.Components.TransformMatrix#scaleX + * @type {number} + * @readonly + * @since 3.4.0 + */ + scaleX: { + + get: function () + { + return Math.sqrt((this.a * this.a) + (this.b * this.b)); + } + + }, + + /** + * The decomposed vertical scale of the Matrix. This value is always positive. + * + * @name Phaser.GameObjects.Components.TransformMatrix#scaleY + * @type {number} + * @readonly + * @since 3.4.0 + */ + scaleY: { + + get: function () + { + return Math.sqrt((this.c * this.c) + (this.d * this.d)); + } + + }, + + /** + * Reset the Matrix to an identity matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#loadIdentity + * @since 3.0.0 + * + * @return {this} This TransformMatrix. + */ + loadIdentity: function () + { + var matrix = this.matrix; + + matrix[0] = 1; + matrix[1] = 0; + matrix[2] = 0; + matrix[3] = 1; + matrix[4] = 0; + matrix[5] = 0; + + return this; + }, + + /** + * Translate the Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#translate + * @since 3.0.0 + * + * @param {number} x - The horizontal translation value. + * @param {number} y - The vertical translation value. + * + * @return {this} This TransformMatrix. + */ + translate: function (x, y) + { + var matrix = this.matrix; + + matrix[4] = matrix[0] * x + matrix[2] * y + matrix[4]; + matrix[5] = matrix[1] * x + matrix[3] * y + matrix[5]; + + return this; + }, + + /** + * Scale the Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#scale + * @since 3.0.0 + * + * @param {number} x - The horizontal scale value. + * @param {number} y - The vertical scale value. + * + * @return {this} This TransformMatrix. + */ + scale: function (x, y) + { + var matrix = this.matrix; + + matrix[0] *= x; + matrix[1] *= x; + matrix[2] *= y; + matrix[3] *= y; + + return this; + }, + + /** + * Rotate the Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#rotate + * @since 3.0.0 + * + * @param {number} angle - The angle of rotation in radians. + * + * @return {this} This TransformMatrix. + */ + rotate: function (angle) + { + var sin = Math.sin(angle); + var cos = Math.cos(angle); + + var matrix = this.matrix; + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + + matrix[0] = a * cos + c * sin; + matrix[1] = b * cos + d * sin; + matrix[2] = a * -sin + c * cos; + matrix[3] = b * -sin + d * cos; + + return this; + }, + + /** + * Multiply this Matrix by the given Matrix. + * + * If an `out` Matrix is given then the results will be stored in it. + * If it is not given, this matrix will be updated in place instead. + * Use an `out` Matrix if you do not wish to mutate this matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#multiply + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} rhs - The Matrix to multiply by. + * @param {Phaser.GameObjects.Components.TransformMatrix} [out] - An optional Matrix to store the results in. + * + * @return {(this|Phaser.GameObjects.Components.TransformMatrix)} Either this TransformMatrix, or the `out` Matrix, if given in the arguments. + */ + multiply: function (rhs, out) + { + var matrix = this.matrix; + var source = rhs.matrix; + + var localA = matrix[0]; + var localB = matrix[1]; + var localC = matrix[2]; + var localD = matrix[3]; + var localE = matrix[4]; + var localF = matrix[5]; + + var sourceA = source[0]; + var sourceB = source[1]; + var sourceC = source[2]; + var sourceD = source[3]; + var sourceE = source[4]; + var sourceF = source[5]; + + var destinationMatrix = (out === undefined) ? matrix : out.matrix; + + destinationMatrix[0] = (sourceA * localA) + (sourceB * localC); + destinationMatrix[1] = (sourceA * localB) + (sourceB * localD); + destinationMatrix[2] = (sourceC * localA) + (sourceD * localC); + destinationMatrix[3] = (sourceC * localB) + (sourceD * localD); + destinationMatrix[4] = (sourceE * localA) + (sourceF * localC) + localE; + destinationMatrix[5] = (sourceE * localB) + (sourceF * localD) + localF; + + return destinationMatrix; + }, + + /** + * Multiply this Matrix by the matrix given, including the offset. + * + * The offsetX is added to the tx value: `offsetX * a + offsetY * c + tx`. + * The offsetY is added to the ty value: `offsetY * b + offsetY * d + ty`. + * + * @method Phaser.GameObjects.Components.TransformMatrix#multiplyWithOffset + * @since 3.11.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} src - The source Matrix to copy from. + * @param {number} offsetX - Horizontal offset to factor in to the multiplication. + * @param {number} offsetY - Vertical offset to factor in to the multiplication. + * + * @return {this} This TransformMatrix. + */ + multiplyWithOffset: function (src, offsetX, offsetY) + { + var matrix = this.matrix; + var otherMatrix = src.matrix; + + var a0 = matrix[0]; + var b0 = matrix[1]; + var c0 = matrix[2]; + var d0 = matrix[3]; + var tx0 = matrix[4]; + var ty0 = matrix[5]; + + var pse = offsetX * a0 + offsetY * c0 + tx0; + var psf = offsetX * b0 + offsetY * d0 + ty0; + + var a1 = otherMatrix[0]; + var b1 = otherMatrix[1]; + var c1 = otherMatrix[2]; + var d1 = otherMatrix[3]; + var tx1 = otherMatrix[4]; + var ty1 = otherMatrix[5]; + + matrix[0] = a1 * a0 + b1 * c0; + matrix[1] = a1 * b0 + b1 * d0; + matrix[2] = c1 * a0 + d1 * c0; + matrix[3] = c1 * b0 + d1 * d0; + matrix[4] = tx1 * a0 + ty1 * c0 + pse; + matrix[5] = tx1 * b0 + ty1 * d0 + psf; + + return this; + }, + + /** + * Transform the Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#transform + * @since 3.0.0 + * + * @param {number} a - The Scale X value. + * @param {number} b - The Shear Y value. + * @param {number} c - The Shear X value. + * @param {number} d - The Scale Y value. + * @param {number} tx - The Translate X value. + * @param {number} ty - The Translate Y value. + * + * @return {this} This TransformMatrix. + */ + transform: function (a, b, c, d, tx, ty) + { + var matrix = this.matrix; + + var a0 = matrix[0]; + var b0 = matrix[1]; + var c0 = matrix[2]; + var d0 = matrix[3]; + var tx0 = matrix[4]; + var ty0 = matrix[5]; + + matrix[0] = a * a0 + b * c0; + matrix[1] = a * b0 + b * d0; + matrix[2] = c * a0 + d * c0; + matrix[3] = c * b0 + d * d0; + matrix[4] = tx * a0 + ty * c0 + tx0; + matrix[5] = tx * b0 + ty * d0 + ty0; + + return this; + }, + + /** + * Transform a point in to the local space of this Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#transformPoint + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the point to transform. + * @param {number} y - The y coordinate of the point to transform. + * @param {Phaser.Types.Math.Vector2Like} [point] - Optional Point object to store the transformed coordinates in. + * + * @return {Phaser.Types.Math.Vector2Like} The Point containing the transformed coordinates. + */ + transformPoint: function (x, y, point) + { + if (point === undefined) { point = { x: 0, y: 0 }; } + + var matrix = this.matrix; + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + var tx = matrix[4]; + var ty = matrix[5]; + + point.x = x * a + y * c + tx; + point.y = x * b + y * d + ty; + + return point; + }, + + /** + * Invert the Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#invert + * @since 3.0.0 + * + * @return {this} This TransformMatrix. + */ + invert: function () + { + var matrix = this.matrix; + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + var tx = matrix[4]; + var ty = matrix[5]; + + var n = a * d - b * c; + + matrix[0] = d / n; + matrix[1] = -b / n; + matrix[2] = -c / n; + matrix[3] = a / n; + matrix[4] = (c * ty - d * tx) / n; + matrix[5] = -(a * ty - b * tx) / n; + + return this; + }, + + /** + * Set the values of this Matrix to copy those of the matrix given. + * + * @method Phaser.GameObjects.Components.TransformMatrix#copyFrom + * @since 3.11.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} src - The source Matrix to copy from. + * + * @return {this} This TransformMatrix. + */ + copyFrom: function (src) + { + var matrix = this.matrix; + + matrix[0] = src.a; + matrix[1] = src.b; + matrix[2] = src.c; + matrix[3] = src.d; + matrix[4] = src.e; + matrix[5] = src.f; + + return this; + }, + + /** + * Set the values of this Matrix to copy those of the array given. + * Where array indexes 0, 1, 2, 3, 4 and 5 are mapped to a, b, c, d, e and f. + * + * @method Phaser.GameObjects.Components.TransformMatrix#copyFromArray + * @since 3.11.0 + * + * @param {array} src - The array of values to set into this matrix. + * + * @return {this} This TransformMatrix. + */ + copyFromArray: function (src) + { + var matrix = this.matrix; + + matrix[0] = src[0]; + matrix[1] = src[1]; + matrix[2] = src[2]; + matrix[3] = src[3]; + matrix[4] = src[4]; + matrix[5] = src[5]; + + return this; + }, + + /** + * Set the values of this Matrix to copy those of the matrix given, + * combined with a camera scroll factor. + * + * This is used in many render functions. + * + * @method Phaser.GameObjects.Components.TransformMatrix#copyWithScrollFactorFrom + * @since 4.0.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} src - The source Matrix to copy from. + * @param {number} scrollX - The horizontal scroll value to factor in. + * @param {number} scrollY - The vertical scroll value to factor in. + * @param {number} scrollFactorX - The horizontal scroll factor to apply. + * @param {number} scrollFactorY - The vertical scroll factor to apply. + * + * @returns {this} This TransformMatrix. + */ + copyWithScrollFactorFrom: function (src, scrollX, scrollY, scrollFactorX, scrollFactorY) + { + var matrix = this.matrix; + + matrix[0] = src.a; + matrix[1] = src.b; + matrix[2] = src.c; + matrix[3] = src.d; + + var sx = scrollX * (1.0 - scrollFactorX); + var sy = scrollY * (1.0 - scrollFactorY); + + matrix[4] = src.a * sx + src.c * sy + src.e; + matrix[5] = src.b * sx + src.d * sy + src.f; + + return this; + }, + + /** + * Copy the values from this Matrix to the given Canvas Rendering Context. + * This will use the Context.transform method. + * + * @method Phaser.GameObjects.Components.TransformMatrix#copyToContext + * @since 3.12.0 + * + * @param {CanvasRenderingContext2D} ctx - The Canvas Rendering Context to copy the matrix values to. + * + * @return {CanvasRenderingContext2D} The Canvas Rendering Context. + */ + copyToContext: function (ctx) + { + var matrix = this.matrix; + + ctx.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + + return ctx; + }, + + /** + * Copy the values from this Matrix to the given Canvas Rendering Context. + * This will use the Context.setTransform method. + * + * @method Phaser.GameObjects.Components.TransformMatrix#setToContext + * @since 3.12.0 + * + * @param {CanvasRenderingContext2D} ctx - The Canvas Rendering Context to copy the matrix values to. + * + * @return {CanvasRenderingContext2D} The Canvas Rendering Context. + */ + setToContext: function (ctx) + { + // using old way for old browser compatibility #6965 + ctx.setTransform(this.a, this.b, this.c, this.d, this.e, this.f); + + return ctx; + }, + + /** + * Copy the values in this Matrix to the array given. + * + * Where array indexes 0, 1, 2, 3, 4 and 5 are mapped to a, b, c, d, e and f. + * + * @method Phaser.GameObjects.Components.TransformMatrix#copyToArray + * @since 3.12.0 + * + * @param {array} [out] - The array to copy the matrix values in to. + * + * @return {array} An array where elements 0 to 5 contain the values from this matrix. + */ + copyToArray: function (out) + { + var matrix = this.matrix; + + if (out === undefined) + { + out = [ matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5] ]; + } + else + { + out[0] = matrix[0]; + out[1] = matrix[1]; + out[2] = matrix[2]; + out[3] = matrix[3]; + out[4] = matrix[4]; + out[5] = matrix[5]; + } + + return out; + }, + + /** + * Set the values of this Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#setTransform + * @since 3.0.0 + * + * @param {number} a - The Scale X value. + * @param {number} b - The Shear Y value. + * @param {number} c - The Shear X value. + * @param {number} d - The Scale Y value. + * @param {number} tx - The Translate X value. + * @param {number} ty - The Translate Y value. + * + * @return {this} This TransformMatrix. + */ + setTransform: function (a, b, c, d, tx, ty) + { + var matrix = this.matrix; + + matrix[0] = a; + matrix[1] = b; + matrix[2] = c; + matrix[3] = d; + matrix[4] = tx; + matrix[5] = ty; + + return this; + }, + + /** + * Decompose this Matrix into its translation, scale and rotation values using QR decomposition. + * + * The result must be applied in the following order to reproduce the current matrix: + * + * translate -> rotate -> scale + * + * @method Phaser.GameObjects.Components.TransformMatrix#decomposeMatrix + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.DecomposeMatrixResults} The decomposed Matrix. + */ + decomposeMatrix: function () + { + var decomposedMatrix = this.decomposedMatrix; + + var matrix = this.matrix; + + // a = scale X (1) + // b = shear Y (0) + // c = shear X (0) + // d = scale Y (1) + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + + var determ = a * d - b * c; + + decomposedMatrix.translateX = matrix[4]; + decomposedMatrix.translateY = matrix[5]; + + if (a || b) + { + var r = Math.sqrt(a * a + b * b); + + decomposedMatrix.rotation = (b > 0) ? Math.acos(a / r) : -Math.acos(a / r); + decomposedMatrix.scaleX = r; + decomposedMatrix.scaleY = determ / r; + } + else if (c || d) + { + var s = Math.sqrt(c * c + d * d); + + decomposedMatrix.rotation = Math.PI * 0.5 - (d > 0 ? Math.acos(-c / s) : -Math.acos(c / s)); + decomposedMatrix.scaleX = determ / s; + decomposedMatrix.scaleY = s; + } + else + { + decomposedMatrix.rotation = 0; + decomposedMatrix.scaleX = 0; + decomposedMatrix.scaleY = 0; + } + + return decomposedMatrix; + }, + + /** + * Apply the identity, translate, rotate and scale operations on the Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#applyITRS + * @since 3.0.0 + * + * @param {number} x - The horizontal translation. + * @param {number} y - The vertical translation. + * @param {number} rotation - The angle of rotation in radians. + * @param {number} scaleX - The horizontal scale. + * @param {number} scaleY - The vertical scale. + * + * @return {this} This TransformMatrix. + */ + applyITRS: function (x, y, rotation, scaleX, scaleY) + { + var matrix = this.matrix; + + var radianSin = Math.sin(rotation); + var radianCos = Math.cos(rotation); + + // Translate + matrix[4] = x; + matrix[5] = y; + + // Rotate and Scale + matrix[0] = radianCos * scaleX; + matrix[1] = radianSin * scaleX; + matrix[2] = -radianSin * scaleY; + matrix[3] = radianCos * scaleY; + + return this; + }, + + /** + * Takes the `x` and `y` values and returns a new position in the `output` vector that is the inverse of + * the current matrix with its transformation applied. + * + * Can be used to translate points from world to local space. + * + * @method Phaser.GameObjects.Components.TransformMatrix#applyInverse + * @since 3.12.0 + * + * @param {number} x - The x position to translate. + * @param {number} y - The y position to translate. + * @param {Phaser.Math.Vector2} [output] - A Vector2, or point-like object, to store the results in. + * + * @return {Phaser.Math.Vector2} The coordinates, inverse-transformed through this matrix. + */ + applyInverse: function (x, y, output) + { + if (output === undefined) { output = new Vector2(); } + + var matrix = this.matrix; + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + var tx = matrix[4]; + var ty = matrix[5]; + + var id = 1 / ((a * d) + (c * -b)); + + output.x = (d * id * x) + (-c * id * y) + (((ty * c) - (tx * d)) * id); + output.y = (a * id * y) + (-b * id * x) + (((-ty * a) + (tx * b)) * id); + + return output; + }, + + /** + * Performs the 8 calculations required to create the vertices of + * a quad based on this matrix and the given vertex coordinates. + * + * The result is stored in `TransformMatrix.quad`, which is returned + * from this method. + * + * @method Phaser.GameObjects.Components.TransformMatrix#setQuad + * @since 3.60.0 + * + * @param {number} x - The x value of the top-left vertex of the quad. + * @param {number} y - The y value of the top-left vertex of the quad. + * @param {number} xw - The x value of the bottom-right vertex of the quad. This is the x + width. + * @param {number} yh - The y value of the bottom-right vertex of the quad. This is the y + height. + * @param {Float32Array} [quad] - Optional Float32Array to store the results in. Otherwises uses the local quad array. + * + * @return {Float32Array} The quad Float32Array. + */ + setQuad: function (x, y, xw, yh, quad) + { + if (quad === undefined) { quad = this.quad; } + + var matrix = this.matrix; + + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + var e = matrix[4]; + var f = matrix[5]; + + quad[0] = x * a + y * c + e; + quad[1] = x * b + y * d + f; + + quad[2] = x * a + yh * c + e; + quad[3] = x * b + yh * d + f; + + quad[4] = xw * a + yh * c + e; + quad[5] = xw * b + yh * d + f; + + quad[6] = xw * a + y * c + e; + quad[7] = xw * b + y * d + f; + + return quad; + }, + + /** + * Returns the X component of this matrix multiplied by the given values. + * This is the same as `x * a + y * c + e`. + * + * @method Phaser.GameObjects.Components.TransformMatrix#getX + * @since 3.12.0 + * + * @param {number} x - The x value. + * @param {number} y - The y value. + * + * @return {number} The calculated x value. + */ + getX: function (x, y) + { + return x * this.a + y * this.c + this.e; + }, + + /** + * Returns the Y component of this matrix multiplied by the given values. + * This is the same as `x * b + y * d + f`. + * + * @method Phaser.GameObjects.Components.TransformMatrix#getY + * @since 3.12.0 + * + * @param {number} x - The x value. + * @param {number} y - The y value. + * + * @return {number} The calculated y value. + */ + getY: function (x, y) + { + return x * this.b + y * this.d + this.f; + }, + + /** + * Returns the X component of this matrix multiplied by the given values. + * + * This is the same as `x * a + y * c + e`, optionally passing via `Math.round`. + * + * @method Phaser.GameObjects.Components.TransformMatrix#getXRound + * @since 3.50.0 + * + * @param {number} x - The x value. + * @param {number} y - The y value. + * @param {boolean} [round=false] - Math.round the resulting value? + * + * @return {number} The calculated x value. + */ + getXRound: function (x, y, round) + { + var v = this.getX(x, y); + + if (round) + { + v = Math.floor(v + 0.5); + } + + return v; + }, + + /** + * Returns the Y component of this matrix multiplied by the given values. + * + * This is the same as `x * b + y * d + f`, optionally passing via `Math.round`. + * + * @method Phaser.GameObjects.Components.TransformMatrix#getYRound + * @since 3.50.0 + * + * @param {number} x - The x value. + * @param {number} y - The y value. + * @param {boolean} [round=false] - Math.round the resulting value? + * + * @return {number} The calculated y value. + */ + getYRound: function (x, y, round) + { + var v = this.getY(x, y); + + if (round) + { + v = Math.floor(v + 0.5); + } + + return v; + }, + + /** + * Returns a string that can be used in a CSS Transform call as a `matrix` property. + * + * @method Phaser.GameObjects.Components.TransformMatrix#getCSSMatrix + * @since 3.12.0 + * + * @return {string} A string containing the CSS Transform matrix values. + */ + getCSSMatrix: function () + { + var m = this.matrix; + + return 'matrix(' + m[0] + ',' + m[1] + ',' + m[2] + ',' + m[3] + ',' + m[4] + ',' + m[5] + ')'; + }, + + /** + * Destroys this Transform Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#destroy + * @since 3.4.0 + */ + destroy: function () + { + this.matrix = null; + this.quad = null; + this.decomposedMatrix = null; + } + +}); + +module.exports = TransformMatrix; + + +/***/ }), + +/***/ 59715: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// bitmask flag for GameObject.renderMask +var _FLAG = 1; // 0001 + +/** + * Provides methods used for setting the visibility of a Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.GameObjects.Components.Visible + * @since 3.0.0 + */ + +var Visible = { + + /** + * Private internal value. Holds the visible value. + * + * @name Phaser.GameObjects.Components.Visible#_visible + * @type {boolean} + * @private + * @default true + * @since 3.0.0 + */ + _visible: true, + + /** + * The visible state of the Game Object. + * + * An invisible Game Object will skip rendering, but will still process update logic. + * + * @name Phaser.GameObjects.Components.Visible#visible + * @type {boolean} + * @since 3.0.0 + */ + visible: { + + get: function () + { + return this._visible; + }, + + set: function (value) + { + if (value) + { + this._visible = true; + this.renderFlags |= _FLAG; + } + else + { + this._visible = false; + this.renderFlags &= ~_FLAG; + } + } + + }, + + /** + * Sets the visibility of this Game Object. + * + * An invisible Game Object will skip rendering, but will still process update logic. + * + * @method Phaser.GameObjects.Components.Visible#setVisible + * @since 3.0.0 + * + * @param {boolean} value - The visible state of the Game Object. + * + * @return {this} This Game Object instance. + */ + setVisible: function (value) + { + this.visible = value; + + return this; + } +}; + +module.exports = Visible; + + +/***/ }), + +/***/ 31401: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.GameObjects.Components + */ + +module.exports = { + + Alpha: __webpack_require__(16005), + AlphaSingle: __webpack_require__(88509), + BlendMode: __webpack_require__(90065), + ComputedSize: __webpack_require__(94215), + Crop: __webpack_require__(61683), + Depth: __webpack_require__(89272), + ElapseTimer: __webpack_require__(3248), + FilterList: __webpack_require__(53427), + Filters: __webpack_require__(43102), + Flip: __webpack_require__(54434), + GetBounds: __webpack_require__(8004), + Lighting: __webpack_require__(73629), + Mask: __webpack_require__(8573), + Origin: __webpack_require__(27387), + PathFollower: __webpack_require__(37640), + RenderNodes: __webpack_require__(68680), + RenderSteps: __webpack_require__(86038), + ScrollFactor: __webpack_require__(80227), + Size: __webpack_require__(16736), + Texture: __webpack_require__(37726), + TextureCrop: __webpack_require__(79812), + Tint: __webpack_require__(27472), + ToJSON: __webpack_require__(53774), + Transform: __webpack_require__(16901), + TransformMatrix: __webpack_require__(61340), + Visible: __webpack_require__(59715) + +}; + + +/***/ }), + +/***/ 31559: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayUtils = __webpack_require__(37105); +var BlendModes = __webpack_require__(10312); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var Events = __webpack_require__(51708); +var GameObject = __webpack_require__(95643); +var Rectangle = __webpack_require__(87841); +var Render = __webpack_require__(29959); +var Union = __webpack_require__(36899); +var Vector2 = __webpack_require__(26099); + +var tempTransformMatrix = new Components.TransformMatrix(); + +/** + * @classdesc + * A Container Game Object. + * + * A Container, as the name implies, can 'contain' other types of Game Object. + * When a Game Object is added to a Container, the Container becomes responsible for the rendering of it. + * By default it will be removed from the Display List and instead added to the Containers own internal list. + * + * The position of the Game Object automatically becomes relative to the position of the Container. + * + * The transform point of a Container is 0x0 (in local space) and that cannot be changed. The children you add to the + * Container should be positioned with this value in mind. I.e. you should treat 0x0 as being the center of + * the Container, and position children positively and negative around it as required. + * + * When the Container is rendered, all of its children are rendered as well, in the order in which they exist + * within the Container. Container children can be repositioned using methods such as `MoveUp`, `MoveDown` and `SendToBack`. + * + * If you modify a transform property of the Container, such as `Container.x` or `Container.rotation` then it will + * automatically influence all children as well. + * + * Containers can include other Containers for deeply nested transforms. + * + * Containers can have masks set on them and can be used as a mask too. However, Container children cannot be masked. + * The masks do not 'stack up'. Only a Container on the root of the display list will use its mask. + * + * Containers can be enabled for input. Because they do not have a texture you need to provide a shape for them + * to use as their hit area. Container children can also be enabled for input, independent of the Container. + * + * If input enabling a _child_ you should not set both the `origin` and a **negative** scale factor on the child, + * or the input area will become misaligned. + * + * Containers can be given a physics body for either Arcade Physics, Impact Physics or Matter Physics. However, + * if Container _children_ are enabled for physics you may get unexpected results, such as offset bodies, + * if the Container itself, or any of its ancestors, is positioned anywhere other than at 0 x 0. Container children + * with physics do not factor in the Container due to the excessive extra calculations needed. Please structure + * your game to work around this. + * + * It's important to understand the impact of using Containers. They add additional processing overhead into + * every one of their children. The deeper you nest them, the more the cost escalates. This is especially true + * for input events. You also lose the ability to set the display depth of Container children in the same + * flexible manner as those not within them. In short, don't use them for the sake of it. You pay a small cost + * every time you create one, try to structure your game around avoiding that where possible. + * + * @class Container + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.4.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {Phaser.GameObjects.GameObject[]} [children] - An optional array of Game Objects to add to this Container. + */ +var Container = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.ComputedSize, + Components.Depth, + Components.Mask, + Components.Transform, + Components.Visible, + Render + ], + + initialize: + + function Container (scene, x, y, children) + { + GameObject.call(this, scene, 'Container'); + + /** + * An array holding the children of this Container. + * + * @name Phaser.GameObjects.Container#list + * @type {Phaser.GameObjects.GameObject[]} + * @since 3.4.0 + */ + this.list = []; + + /** + * Does this Container exclusively manage its children? + * + * The default is `true` which means a child added to this Container cannot + * belong in another Container, which includes the Scene display list. + * + * If you disable this then this Container will no longer exclusively manage its children. + * This allows you to create all kinds of interesting graphical effects, such as replicating + * Game Objects without reparenting them all over the Scene. + * However, doing so will prevent children from receiving any kind of input event or have + * their physics bodies work by default, as they're no longer a single entity on the + * display list, but are being replicated where-ever this Container is. + * + * @name Phaser.GameObjects.Container#exclusive + * @type {boolean} + * @default true + * @since 3.4.0 + */ + this.exclusive = true; + + /** + * Containers can have an optional maximum size. If set to anything above 0 it + * will constrict the addition of new Game Objects into the Container, capping off + * the maximum limit the Container can grow in size to. + * + * @name Phaser.GameObjects.Container#maxSize + * @type {number} + * @default -1 + * @since 3.4.0 + */ + this.maxSize = -1; + + /** + * The cursor position. + * + * @name Phaser.GameObjects.Container#position + * @type {number} + * @since 3.4.0 + */ + this.position = 0; + + /** + * Internal Transform Matrix used for local space conversion. + * + * @name Phaser.GameObjects.Container#localTransform + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 3.4.0 + */ + this.localTransform = new Components.TransformMatrix(); + + /** + * The property key to sort by. + * + * @name Phaser.GameObjects.Container#_sortKey + * @type {string} + * @private + * @since 3.4.0 + */ + this._sortKey = ''; + + /** + * A reference to the Scene Systems Event Emitter. + * + * @name Phaser.GameObjects.Container#_sysEvents + * @type {Phaser.Events.EventEmitter} + * @private + * @since 3.9.0 + */ + this._sysEvents = scene.sys.events; + + /** + * The horizontal scroll factor of this Container. + * + * The scroll factor controls the influence of the movement of a Camera upon this Container. + * + * When a camera scrolls it will change the location at which this Container is rendered on-screen. + * It does not change the Containers actual position values. + * + * For a Container, setting this value will only update the Container itself, not its children. + * If you wish to change the scrollFactor of the children as well, use the `setScrollFactor` method. + * + * A value of 1 means it will move exactly in sync with a camera. + * A value of 0 means it will not move at all, even if the camera moves. + * Other values control the degree to which the camera movement is mapped to this Container. + * + * Please be aware that scroll factor values other than 1 are not taken in to consideration when + * calculating physics collisions. Bodies always collide based on their world position, but changing + * the scroll factor is a visual adjustment to where the textures are rendered, which can offset + * them from physics bodies if not accounted for in your code. + * + * @name Phaser.GameObjects.Container#scrollFactorX + * @type {number} + * @default 1 + * @since 3.4.0 + */ + this.scrollFactorX = 1; + + /** + * The vertical scroll factor of this Container. + * + * The scroll factor controls the influence of the movement of a Camera upon this Container. + * + * When a camera scrolls it will change the location at which this Container is rendered on-screen. + * It does not change the Containers actual position values. + * + * For a Container, setting this value will only update the Container itself, not its children. + * If you wish to change the scrollFactor of the children as well, use the `setScrollFactor` method. + * + * A value of 1 means it will move exactly in sync with a camera. + * A value of 0 means it will not move at all, even if the camera moves. + * Other values control the degree to which the camera movement is mapped to this Container. + * + * Please be aware that scroll factor values other than 1 are not taken in to consideration when + * calculating physics collisions. Bodies always collide based on their world position, but changing + * the scroll factor is a visual adjustment to where the textures are rendered, which can offset + * them from physics bodies if not accounted for in your code. + * + * @name Phaser.GameObjects.Container#scrollFactorY + * @type {number} + * @default 1 + * @since 3.4.0 + */ + this.scrollFactorY = 1; + + this.setPosition(x, y); + + this.setBlendMode(BlendModes.SKIP_CHECK); + + if (children) + { + this.add(children); + } + }, + + /** + * Internal value to allow Containers to be used for input and physics. + * Do not change this value. It has no effect other than to break things. + * + * @name Phaser.GameObjects.Container#originX + * @type {number} + * @readonly + * @override + * @since 3.4.0 + */ + originX: { + + get: function () + { + return 0.5; + } + + }, + + /** + * Internal value to allow Containers to be used for input and physics. + * Do not change this value. It has no effect other than to break things. + * + * @name Phaser.GameObjects.Container#originY + * @type {number} + * @readonly + * @override + * @since 3.4.0 + */ + originY: { + + get: function () + { + return 0.5; + } + + }, + + /** + * Internal value to allow Containers to be used for input and physics. + * Do not change this value. It has no effect other than to break things. + * + * @name Phaser.GameObjects.Container#displayOriginX + * @type {number} + * @readonly + * @override + * @since 3.4.0 + */ + displayOriginX: { + + get: function () + { + return this.width * 0.5; + } + + }, + + /** + * Internal value to allow Containers to be used for input and physics. + * Do not change this value. It has no effect other than to break things. + * + * @name Phaser.GameObjects.Container#displayOriginY + * @type {number} + * @readonly + * @override + * @since 3.4.0 + */ + displayOriginY: { + + get: function () + { + return this.height * 0.5; + } + + }, + + /** + * Does this Container exclusively manage its children? + * + * The default is `true` which means a child added to this Container cannot + * belong in another Container, which includes the Scene display list. + * + * If you disable this then this Container will no longer exclusively manage its children. + * This allows you to create all kinds of interesting graphical effects, such as replicating + * Game Objects without reparenting them all over the Scene. + * However, doing so will prevent children from receiving any kind of input event or have + * their physics bodies work by default, as they're no longer a single entity on the + * display list, but are being replicated where-ever this Container is. + * + * @method Phaser.GameObjects.Container#setExclusive + * @since 3.4.0 + * + * @param {boolean} [value=true] - The exclusive state of this Container. + * + * @return {this} This Container. + */ + setExclusive: function (value) + { + if (value === undefined) { value = true; } + + this.exclusive = value; + + return this; + }, + + /** + * Gets the bounds of this Container. It works by iterating all children of the Container, + * getting their respective bounds, and then working out a min-max rectangle from that. + * It does not factor in if the children render or not, all are included. + * + * Some children are unable to return their bounds, such as Graphics objects, in which case + * they are skipped. + * + * Depending on the quantity of children in this Container it could be a really expensive call, + * so cache it and only poll it as needed. + * + * The values are stored and returned in a Rectangle object. + * + * @method Phaser.GameObjects.Container#getBounds + * @since 3.4.0 + * + * @param {Phaser.Geom.Rectangle} [output] - A Geom.Rectangle object to store the values in. If not provided a new Rectangle will be created. + * + * @return {Phaser.Geom.Rectangle} The values stored in the output object. + */ + getBounds: function (output) + { + if (output === undefined) { output = new Rectangle(); } + + output.setTo(this.x, this.y, 0, 0); + + if (this.parentContainer) + { + var parentMatrix = this.parentContainer.getBoundsTransformMatrix(); + var transformedPosition = parentMatrix.transformPoint(this.x, this.y); + + output.setTo(transformedPosition.x, transformedPosition.y, 0, 0); + } + + if (this.list.length > 0) + { + var children = this.list; + var tempRect = new Rectangle(); + var hasSetFirst = false; + + output.setEmpty(); + + for (var i = 0; i < children.length; i++) + { + var entry = children[i]; + + if (entry.getBounds) + { + entry.getBounds(tempRect); + + if (!hasSetFirst) + { + output.setTo(tempRect.x, tempRect.y, tempRect.width, tempRect.height); + hasSetFirst = true; + } + else + { + Union(tempRect, output, output); + } + } + } + } + + return output; + }, + + /** + * Internal add handler. + * + * @method Phaser.GameObjects.Container#addHandler + * @private + * @since 3.4.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just added to this Container. + */ + addHandler: function (gameObject) + { + gameObject.once(Events.DESTROY, this.onChildDestroyed, this); + + if (this.exclusive) + { + if (gameObject.parentContainer) + { + gameObject.parentContainer.remove(gameObject); + } + + gameObject.parentContainer = this; + + gameObject.removeFromDisplayList(); + + gameObject.addedToScene(); + } + }, + + /** + * Internal remove handler. + * + * @method Phaser.GameObjects.Container#removeHandler + * @private + * @since 3.4.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just removed from this Container. + */ + removeHandler: function (gameObject) + { + gameObject.off(Events.DESTROY, this.remove, this); + + if (this.exclusive) + { + gameObject.parentContainer = null; + + gameObject.removedFromScene(); + + gameObject.addToDisplayList(); + } + }, + + /** + * Takes a Point-like object, such as a Vector2, or object with public x and y properties, + * and transforms it into the space of this Container, then returns it in the output object. + * + * @method Phaser.GameObjects.Container#pointToContainer + * @since 3.4.0 + * + * @param {Phaser.Types.Math.Vector2Like} source - The Source Point to be transformed. + * @param {Phaser.Types.Math.Vector2Like} [output] - A destination object to store the transformed point in. If none given a Vector2 will be created and returned. + * + * @return {Phaser.Types.Math.Vector2Like} The transformed point. + */ + pointToContainer: function (source, output) + { + if (output === undefined) { output = new Vector2(); } + + if (this.parentContainer) + { + this.parentContainer.pointToContainer(source, output); + } + else + { + output.x = source.x; + output.y = source.y; + } + + var tempMatrix = tempTransformMatrix; + + // No need to loadIdentity because applyITRS overwrites every value anyway + tempMatrix.applyITRS(this.x, this.y, this.rotation, this.scaleX, this.scaleY); + + tempMatrix.invert(); + + tempMatrix.transformPoint(source.x, source.y, output); + + return output; + }, + + /** + * Returns the world transform matrix as used for Bounds checks. + * + * The returned matrix is temporal and shouldn't be stored. + * + * @method Phaser.GameObjects.Container#getBoundsTransformMatrix + * @since 3.4.0 + * + * @return {Phaser.GameObjects.Components.TransformMatrix} The world transform matrix. + */ + getBoundsTransformMatrix: function () + { + return this.getWorldTransformMatrix(tempTransformMatrix, this.localTransform); + }, + + /** + * Adds the given Game Object, or array of Game Objects, to this Container. + * + * Each Game Object must be unique within the Container. + * + * @method Phaser.GameObjects.Container#add + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {(T|T[])} - [child] + * + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to add to the Container. + * + * @return {this} This Container instance. + */ + add: function (child) + { + ArrayUtils.Add(this.list, child, this.maxSize, this.addHandler, this); + + return this; + }, + + /** + * Adds the given Game Object, or array of Game Objects, to this Container at the specified position. + * + * Existing Game Objects in the Container are shifted up. + * + * Each Game Object must be unique within the Container. + * + * @method Phaser.GameObjects.Container#addAt + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {(T|T[])} - [child] + * + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to add to the Container. + * @param {number} [index=0] - The position to insert the Game Object/s at. + * + * @return {this} This Container instance. + */ + addAt: function (child, index) + { + ArrayUtils.AddAt(this.list, child, index, this.maxSize, this.addHandler, this); + + return this; + }, + + /** + * Returns the Game Object at the given position in this Container. + * + * @method Phaser.GameObjects.Container#getAt + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [$return] + * + * @param {number} index - The position to get the Game Object from. + * + * @return {?Phaser.GameObjects.GameObject} The Game Object at the specified index, or `null` if none found. + */ + getAt: function (index) + { + return this.list[index]; + }, + + /** + * Returns the index of the given Game Object in this Container. + * + * @method Phaser.GameObjects.Container#getIndex + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to search for in this Container. + * + * @return {number} The index of the Game Object in this Container, or -1 if not found. + */ + getIndex: function (child) + { + return this.list.indexOf(child); + }, + + /** + * Sort the contents of this Container so the items are in order based on the given property. + * For example: `sort('alpha')` would sort the elements based on the value of their `alpha` property. + * + * @method Phaser.GameObjects.Container#sort + * @since 3.4.0 + * + * @param {string} property - The property to lexically sort by. + * @param {function} [handler] - Provide your own custom handler function. Will receive 2 children which it should compare and return a boolean. + * + * @return {this} This Container instance. + */ + sort: function (property, handler) + { + if (!property) + { + return this; + } + + if (handler === undefined) + { + handler = function (childA, childB) + { + return childA[property] - childB[property]; + }; + } + + ArrayUtils.StableSort(this.list, handler); + + return this; + }, + + /** + * Searches for the first instance of a child with its `name` property matching the given argument. + * Should more than one child have the same name only the first is returned. + * + * @method Phaser.GameObjects.Container#getByName + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [$return] + * + * @param {string} name - The name to search for. + * + * @return {?Phaser.GameObjects.GameObject} The first child with a matching name, or `null` if none were found. + */ + getByName: function (name) + { + return ArrayUtils.GetFirst(this.list, 'name', name); + }, + + /** + * Returns a random Game Object from this Container. + * + * @method Phaser.GameObjects.Container#getRandom + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [$return] + * + * @param {number} [startIndex=0] - An optional start index. + * @param {number} [length] - An optional length, the total number of elements (from the startIndex) to choose from. + * + * @return {?Phaser.GameObjects.GameObject} A random child from the Container, or `null` if the Container is empty. + */ + getRandom: function (startIndex, length) + { + return ArrayUtils.GetRandom(this.list, startIndex, length); + }, + + /** + * Gets the first Game Object in this Container. + * + * You can also specify a property and value to search for, in which case it will return the first + * Game Object in this Container with a matching property and / or value. + * + * For example: `getFirst('visible', true)` would return the first Game Object that had its `visible` property set. + * + * You can limit the search to the `startIndex` - `endIndex` range. + * + * @method Phaser.GameObjects.Container#getFirst + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [$return] + * + * @param {string} property - The property to test on each Game Object in the Container. + * @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {number} [startIndex=0] - An optional start index to search from. + * @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {?Phaser.GameObjects.GameObject} The first matching Game Object, or `null` if none was found. + */ + getFirst: function (property, value, startIndex, endIndex) + { + return ArrayUtils.GetFirst(this.list, property, value, startIndex, endIndex); + }, + + /** + * Returns all Game Objects in this Container. + * + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('body')` would return only Game Objects that have a body property. + * + * You can also specify a value to compare the property to: + * + * `getAll('visible', true)` would return only Game Objects that have their visible property set to `true`. + * + * Optionally you can specify a start and end index. For example if this Container had 100 Game Objects, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 Game Objects. + * + * @method Phaser.GameObjects.Container#getAll + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T[]} - [$return] + * + * @param {string} [property] - The property to test on each Game Object in the Container. + * @param {any} [value] - If property is set then the `property` must strictly equal this value to be included in the results. + * @param {number} [startIndex=0] - An optional start index to search from. + * @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {Phaser.GameObjects.GameObject[]} An array of matching Game Objects from this Container. + */ + getAll: function (property, value, startIndex, endIndex) + { + return ArrayUtils.GetAll(this.list, property, value, startIndex, endIndex); + }, + + /** + * Returns the total number of Game Objects in this Container that have a property + * matching the given value. + * + * For example: `count('visible', true)` would count all the elements that have their visible property set. + * + * You can optionally limit the operation to the `startIndex` - `endIndex` range. + * + * @method Phaser.GameObjects.Container#count + * @since 3.4.0 + * + * @param {string} property - The property to check. + * @param {any} value - The value to check. + * @param {number} [startIndex=0] - An optional start index to search from. + * @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {number} The total number of Game Objects in this Container with a property matching the given value. + */ + count: function (property, value, startIndex, endIndex) + { + return ArrayUtils.CountAllMatching(this.list, property, value, startIndex, endIndex); + }, + + /** + * Swaps the position of two Game Objects in this Container. + * Both Game Objects must belong to this Container. + * + * @method Phaser.GameObjects.Container#swap + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child1,child2] + * + * @param {Phaser.GameObjects.GameObject} child1 - The first Game Object to swap. + * @param {Phaser.GameObjects.GameObject} child2 - The second Game Object to swap. + * + * @return {this} This Container instance. + */ + swap: function (child1, child2) + { + ArrayUtils.Swap(this.list, child1, child2); + + return this; + }, + + /** + * Moves a Game Object to a new position within this Container. + * + * The Game Object must already be a child of this Container. + * + * The Game Object is removed from its old position and inserted into the new one. + * Therefore the Container size does not change. Other children will change position accordingly. + * + * @method Phaser.GameObjects.Container#moveTo + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to move. + * @param {number} index - The new position of the Game Object in this Container. + * + * @return {this} This Container instance. + */ + moveTo: function (child, index) + { + ArrayUtils.MoveTo(this.list, child, index); + + return this; + }, + + /** + * Moves a Game Object above another one within this Container. + * If the Game Object is already above the other, it isn't moved. + * + * These 2 Game Objects must already be children of this Container. + * + * @method Phaser.GameObjects.Container#moveAbove + * @since 3.55.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child1,child2] + * + * @param {Phaser.GameObjects.GameObject} child1 - The Game Object to move above base Game Object. + * @param {Phaser.GameObjects.GameObject} child2 - The base Game Object. + * + * @return {this} This Container instance. + */ + moveAbove: function (child1, child2) + { + ArrayUtils.MoveAbove(this.list, child1, child2); + + return this; + }, + + /** + * Moves a Game Object below another one within this Container. + * If the Game Object is already below the other, it isn't moved. + * + * These 2 Game Objects must already be children of this Container. + * + * @method Phaser.GameObjects.Container#moveBelow + * @since 3.55.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child1,child2] + * + * @param {Phaser.GameObjects.GameObject} child1 - The Game Object to move below base Game Object. + * @param {Phaser.GameObjects.GameObject} child2 - The base Game Object. + * + * @return {this} This Container instance. + */ + moveBelow: function (child1, child2) + { + ArrayUtils.MoveBelow(this.list, child1, child2); + + return this; + }, + + /** + * Removes the given Game Object, or array of Game Objects, from this Container. + * + * The Game Objects must already be children of this Container. + * + * You can also optionally call `destroy` on each Game Object that is removed from the Container. + * + * @method Phaser.GameObjects.Container#remove + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {(T|T[])} - [child] + * + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to be removed from the Container. + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each child successfully removed from this Container. + * + * @return {this} This Container instance. + */ + remove: function (child, destroyChild) + { + var removed = ArrayUtils.Remove(this.list, child, this.removeHandler, this); + + if (destroyChild && removed) + { + if (!Array.isArray(removed)) + { + removed = [ removed ]; + } + + for (var i = 0; i < removed.length; i++) + { + removed[i].destroy(); + } + } + + return this; + }, + + /** + * Removes the Game Object at the given position in this Container. + * + * You can also optionally call `destroy` on the Game Object, if one is found. + * + * @method Phaser.GameObjects.Container#removeAt + * @since 3.4.0 + * + * @param {number} index - The index of the Game Object to be removed. + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container. + * + * @return {this} This Container instance. + */ + removeAt: function (index, destroyChild) + { + var removed = ArrayUtils.RemoveAt(this.list, index, this.removeHandler, this); + + if (destroyChild && removed) + { + removed.destroy(); + } + + return this; + }, + + /** + * Removes the Game Objects between the given positions in this Container. + * + * You can also optionally call `destroy` on each Game Object that is removed from the Container. + * + * @method Phaser.GameObjects.Container#removeBetween + * @since 3.4.0 + * + * @param {number} [startIndex=0] - An optional start index to search from. + * @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included) + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container. + * + * @return {this} This Container instance. + */ + removeBetween: function (startIndex, endIndex, destroyChild) + { + var removed = ArrayUtils.RemoveBetween(this.list, startIndex, endIndex, this.removeHandler, this); + + if (destroyChild) + { + for (var i = 0; i < removed.length; i++) + { + removed[i].destroy(); + } + } + + return this; + }, + + /** + * Removes all Game Objects from this Container. + * + * You can also optionally call `destroy` on each Game Object that is removed from the Container. + * + * @method Phaser.GameObjects.Container#removeAll + * @since 3.4.0 + * + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container. + * + * @return {this} This Container instance. + */ + removeAll: function (destroyChild) + { + var list = this.list; + + if (destroyChild) + { + for (var i = 0; i < list.length; i++) + { + if (list[i] && list[i].scene) + { + list[i].off(Events.DESTROY, this.onChildDestroyed, this); + + list[i].destroy(); + } + } + + this.list = []; + } + else + { + ArrayUtils.RemoveBetween(list, 0, list.length, this.removeHandler, this); + } + + return this; + }, + + /** + * Brings the given Game Object to the top of this Container. + * This will cause it to render on-top of any other objects in the Container. + * + * @method Phaser.GameObjects.Container#bringToTop + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to bring to the top of the Container. + * + * @return {this} This Container instance. + */ + bringToTop: function (child) + { + ArrayUtils.BringToTop(this.list, child); + + return this; + }, + + /** + * Sends the given Game Object to the bottom of this Container. + * This will cause it to render below any other objects in the Container. + * + * @method Phaser.GameObjects.Container#sendToBack + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to send to the bottom of the Container. + * + * @return {this} This Container instance. + */ + sendToBack: function (child) + { + ArrayUtils.SendToBack(this.list, child); + + return this; + }, + + /** + * Moves the given Game Object up one place in this Container, unless it's already at the top. + * + * @method Phaser.GameObjects.Container#moveUp + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container. + * + * @return {this} This Container instance. + */ + moveUp: function (child) + { + ArrayUtils.MoveUp(this.list, child); + + return this; + }, + + /** + * Moves the given Game Object down one place in this Container, unless it's already at the bottom. + * + * @method Phaser.GameObjects.Container#moveDown + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container. + * + * @return {this} This Container instance. + */ + moveDown: function (child) + { + ArrayUtils.MoveDown(this.list, child); + + return this; + }, + + /** + * Reverses the order of all Game Objects in this Container. + * + * @method Phaser.GameObjects.Container#reverse + * @since 3.4.0 + * + * @return {this} This Container instance. + */ + reverse: function () + { + this.list.reverse(); + + return this; + }, + + /** + * Shuffles the all Game Objects in this Container using the Fisher-Yates implementation. + * + * @method Phaser.GameObjects.Container#shuffle + * @since 3.4.0 + * + * @return {this} This Container instance. + */ + shuffle: function () + { + ArrayUtils.Shuffle(this.list); + + return this; + }, + + /** + * Replaces a Game Object in this Container with the new Game Object. + * The new Game Object cannot already be a child of this Container. + * + * @method Phaser.GameObjects.Container#replace + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [oldChild,newChild] + * + * @param {Phaser.GameObjects.GameObject} oldChild - The Game Object in this Container that will be replaced. + * @param {Phaser.GameObjects.GameObject} newChild - The Game Object to be added to this Container. + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container. + * + * @return {this} This Container instance. + */ + replace: function (oldChild, newChild, destroyChild) + { + var moved = ArrayUtils.Replace(this.list, oldChild, newChild); + + if (moved) + { + this.addHandler(newChild); + this.removeHandler(oldChild); + + if (destroyChild) + { + oldChild.destroy(); + } + } + + return this; + }, + + /** + * Returns `true` if the given Game Object is a direct child of this Container. + * + * This check does not scan nested Containers. + * + * @method Phaser.GameObjects.Container#exists + * @since 3.4.0 + * + * @generic {Phaser.GameObjects.GameObject} T + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to check for within this Container. + * + * @return {boolean} True if the Game Object is an immediate child of this Container, otherwise false. + */ + exists: function (child) + { + return (this.list.indexOf(child) > -1); + }, + + /** + * Sets the property to the given value on all Game Objects in this Container. + * + * Optionally you can specify a start and end index. For example if this Container had 100 Game Objects, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 Game Objects. + * + * @method Phaser.GameObjects.Container#setAll + * @since 3.4.0 + * + * @param {string} property - The property that must exist on the Game Object. + * @param {any} value - The value to get the property to. + * @param {number} [startIndex=0] - An optional start index to search from. + * @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {this} This Container instance. + */ + setAll: function (property, value, startIndex, endIndex) + { + ArrayUtils.SetAll(this.list, property, value, startIndex, endIndex); + + return this; + }, + + /** + * @callback EachContainerCallback + * @generic I - [item] + * + * @param {*} item - The child Game Object of the Container. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + */ + + /** + * Passes all Game Objects in this Container to the given callback. + * + * A copy of the Container is made before passing each entry to your callback. + * This protects against the callback itself modifying the Container. + * + * If you know for sure that the callback will not change the size of this Container + * then you can use the more performant `Container.iterate` method instead. + * + * @method Phaser.GameObjects.Container#each + * @since 3.4.0 + * + * @param {function} callback - The function to call. + * @param {object} [context] - Value to use as `this` when executing callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {this} This Container instance. + */ + each: function (callback, context) + { + var args = [ null ]; + var i; + var temp = this.list.slice(); + var len = temp.length; + + for (i = 2; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < len; i++) + { + args[0] = temp[i]; + + callback.apply(context, args); + } + + return this; + }, + + /** + * Passes all Game Objects in this Container to the given callback. + * + * Only use this method when you absolutely know that the Container will not be modified during + * the iteration, i.e. by removing or adding to its contents. + * + * @method Phaser.GameObjects.Container#iterate + * @since 3.4.0 + * + * @param {function} callback - The function to call. + * @param {object} [context] - Value to use as `this` when executing callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {this} This Container instance. + */ + iterate: function (callback, context) + { + var args = [ null ]; + var i; + + for (i = 2; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < this.list.length; i++) + { + args[0] = this.list[i]; + + callback.apply(context, args); + } + + return this; + }, + + /** + * Sets the scroll factor of this Container and optionally all of its children. + * + * The scroll factor controls the influence of the movement of a Camera upon this Game Object. + * + * When a camera scrolls it will change the location at which this Game Object is rendered on-screen. + * It does not change the Game Objects actual position values. + * + * A value of 1 means it will move exactly in sync with a camera. + * A value of 0 means it will not move at all, even if the camera moves. + * Other values control the degree to which the camera movement is mapped to this Game Object. + * + * Please be aware that scroll factor values other than 1 are not taken in to consideration when + * calculating physics collisions. Bodies always collide based on their world position, but changing + * the scroll factor is a visual adjustment to where the textures are rendered, which can offset + * them from physics bodies if not accounted for in your code. + * + * @method Phaser.GameObjects.Container#setScrollFactor + * @since 3.4.0 + * + * @param {number} x - The horizontal scroll factor of this Game Object. + * @param {number} [y=x] - The vertical scroll factor of this Game Object. If not set it will use the `x` value. + * @param {boolean} [updateChildren=false] - Apply this scrollFactor to all Container children as well? + * + * @return {this} This Game Object instance. + */ + setScrollFactor: function (x, y, updateChildren) + { + if (y === undefined) { y = x; } + if (updateChildren === undefined) { updateChildren = false; } + + this.scrollFactorX = x; + this.scrollFactorY = y; + + if (updateChildren) + { + ArrayUtils.SetAll(this.list, 'scrollFactorX', x); + ArrayUtils.SetAll(this.list, 'scrollFactorY', y); + } + + return this; + }, + + /** + * The number of Game Objects inside this Container. + * + * @name Phaser.GameObjects.Container#length + * @type {number} + * @readonly + * @since 3.4.0 + */ + length: { + + get: function () + { + return this.list.length; + } + + }, + + /** + * Returns the first Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#first + * @type {?Phaser.GameObjects.GameObject} + * @readonly + * @since 3.4.0 + */ + first: { + + get: function () + { + this.position = 0; + + if (this.list.length > 0) + { + return this.list[0]; + } + else + { + return null; + } + } + + }, + + /** + * Returns the last Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#last + * @type {?Phaser.GameObjects.GameObject} + * @readonly + * @since 3.4.0 + */ + last: { + + get: function () + { + if (this.list.length > 0) + { + this.position = this.list.length - 1; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * Returns the next Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#next + * @type {?Phaser.GameObjects.GameObject} + * @readonly + * @since 3.4.0 + */ + next: { + + get: function () + { + if (this.position < this.list.length) + { + this.position++; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * Returns the previous Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#previous + * @type {?Phaser.GameObjects.GameObject} + * @readonly + * @since 3.4.0 + */ + previous: { + + get: function () + { + if (this.position > 0) + { + this.position--; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.Container#preDestroy + * @protected + * @since 3.9.0 + */ + preDestroy: function () + { + this.removeAll(!!this.exclusive); + + this.localTransform.destroy(); + + this.list = []; + }, + + /** + * Internal handler, called when a child is destroyed. + * + * @method Phaser.GameObjects.Container#onChildDestroyed + * @protected + * @since 3.80.0 + */ + onChildDestroyed: function (gameObject) + { + ArrayUtils.Remove(this.list, gameObject); + + if (this.exclusive) + { + gameObject.parentContainer = null; + + gameObject.removedFromScene(); + } + } + +}); + +module.exports = Container; + + +/***/ }), + +/***/ 53584: +/***/ ((module) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Container#renderCanvas + * @since 3.4.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ContainerCanvasRenderer = function (renderer, container, camera, parentMatrix) +{ + camera.addToRenderList(container); + + var children = container.list; + + if (children.length === 0) + { + return; + } + + var transformMatrix = container.localTransform; + + if (parentMatrix) + { + transformMatrix.loadIdentity(); + transformMatrix.multiply(parentMatrix); + transformMatrix.translate(container.x, container.y); + transformMatrix.rotate(container.rotation); + transformMatrix.scale(container.scaleX, container.scaleY); + } + else + { + transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY); + } + + var containerHasBlendMode = (container.blendMode !== -1); + + if (!containerHasBlendMode) + { + // If Container is SKIP_TEST then set blend mode to be Normal + renderer.setBlendMode(0); + } + + var alpha = container._alpha; + var scrollFactorX = container.scrollFactorX; + var scrollFactorY = container.scrollFactorY; + + if (container.mask) + { + container.mask.preRenderCanvas(renderer, null, camera); + } + + for (var i = 0; i < children.length; i++) + { + var child = children[i]; + + if (!child.willRender(camera)) + { + continue; + } + + var childAlpha = child.alpha; + var childScrollFactorX = child.scrollFactorX; + var childScrollFactorY = child.scrollFactorY; + + if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode) + { + // If Container doesn't have its own blend mode, then a child can have one + renderer.setBlendMode(child.blendMode); + } + + // Set parent values + child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY); + child.setAlpha(childAlpha * alpha); + + // Render + child.renderCanvas(renderer, child, camera, transformMatrix); + + // Restore original values + child.setAlpha(childAlpha); + child.setScrollFactor(childScrollFactorX, childScrollFactorY); + } + + if (container.mask) + { + container.mask.postRenderCanvas(renderer); + } +}; + +module.exports = ContainerCanvasRenderer; + + +/***/ }), + +/***/ 77143: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var Container = __webpack_require__(31559); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var GetFastValue = __webpack_require__(95540); + +/** + * Creates a new Container Game Object and returns it. + * + * Note: This method will only be available if the Container Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#container + * @since 3.4.0 + * + * @param {Phaser.Types.GameObjects.Container.ContainerConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Container} The Game Object that was created. + */ +GameObjectCreator.register('container', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var x = GetAdvancedValue(config, 'x', 0); + var y = GetAdvancedValue(config, 'y', 0); + var children = GetFastValue(config, 'children', null); + + var container = new Container(this.scene, x, y, children); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, container, config); + + return container; +}); + + +/***/ }), + +/***/ 24961: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Container = __webpack_require__(31559); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Container Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Container Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#container + * @since 3.4.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} [children] - An optional array of Game Objects to add to this Container. + * + * @return {Phaser.GameObjects.Container} The Game Object that was created. + */ +GameObjectFactory.register('container', function (x, y, children) +{ + return this.displayList.add(new Container(this.scene, x, y, children)); +}); + + +/***/ }), + +/***/ 29959: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(72249); +} + +if (true) +{ + renderCanvas = __webpack_require__(53584); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 72249: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(8054); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Container#renderWebGL + * @since 3.4.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + * @param {number} renderStep - The index of this function in the Game Object's list of render processes. Used to support multiple rendering functions. + * @param {Phaser.GameObjects.GameObject[]} displayList - The display list which is currently being rendered. + * @param {number} displayListIndex - The index of the Game Object within the display list. + */ +var ContainerWebGLRenderer = function (renderer, container, drawingContext, parentMatrix, renderStep, displayList, displayListIndex) +{ + var camera = drawingContext.camera; + camera.addToRenderList(container); + + var children = container.list; + var childCount = children.length; + + if (childCount === 0) + { + return; + } + + var currentContext = drawingContext; + + var transformMatrix = container.localTransform; + + if (parentMatrix) + { + transformMatrix.loadIdentity(); + transformMatrix.multiply(parentMatrix); + transformMatrix.translate(container.x, container.y); + transformMatrix.rotate(container.rotation); + transformMatrix.scale(container.scaleX, container.scaleY); + } + else + { + transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY); + } + + var containerHasBlendMode = (container.blendMode !== -1); + + if (!containerHasBlendMode && currentContext.blendMode !== 0) + { + // If Container is SKIP_TEST then set blend mode to be Normal + currentContext = currentContext.getClone(); + currentContext.setBlendMode(0); + currentContext.use(); + } + + var alpha = container.alpha; + + var scrollFactorX = container.scrollFactorX; + var scrollFactorY = container.scrollFactorY; + + for (var i = 0; i < childCount; i++) + { + var child = children[i]; + + if (!child.willRender(camera)) + { + continue; + } + + var childAlphaTopLeft; + var childAlphaTopRight; + var childAlphaBottomLeft; + var childAlphaBottomRight; + + if (child.alphaTopLeft !== undefined) + { + childAlphaTopLeft = child.alphaTopLeft; + childAlphaTopRight = child.alphaTopRight; + childAlphaBottomLeft = child.alphaBottomLeft; + childAlphaBottomRight = child.alphaBottomRight; + } + else + { + var childAlpha = child.alpha; + + childAlphaTopLeft = childAlpha; + childAlphaTopRight = childAlpha; + childAlphaBottomLeft = childAlpha; + childAlphaBottomRight = childAlpha; + } + + var childScrollFactorX = child.scrollFactorX; + var childScrollFactorY = child.scrollFactorY; + + if ( + !containerHasBlendMode && + child.blendMode !== currentContext.blendMode && + child.blendMode !== CONST.BlendModes.SKIP_CHECK + ) + { + // If Container doesn't have its own blend mode, then a child can have one + currentContext = currentContext.getClone(); + currentContext.setBlendMode(child.blendMode); + currentContext.use(); + } + + // Set parent values + child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY); + + child.setAlpha(childAlphaTopLeft * alpha, childAlphaTopRight * alpha, childAlphaBottomLeft * alpha, childAlphaBottomRight * alpha); + + // Render + child.renderWebGLStep(renderer, child, currentContext, transformMatrix, undefined, displayList, displayListIndex); + + // Restore original values + + child.setAlpha(childAlphaTopLeft, childAlphaTopRight, childAlphaBottomLeft, childAlphaBottomRight); + + child.setScrollFactor(childScrollFactorX, childScrollFactorY); + } + + // Release any remaining context. + if (currentContext !== drawingContext) + { + currentContext.release(); + } +}; + +module.exports = ContainerWebGLRenderer; + + +/***/ }), + +/***/ 47407: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Blend Modes to CSS Blend Modes Map. + * + * @name Phaser.CSSBlendModes + * @ignore + * @enum {string} + * @memberof Phaser + * @readonly + * @since 3.12.0 + */ + +module.exports = [ + 'normal', + 'multiply', + 'multiply', + 'screen', + 'overlay', + 'darken', + 'lighten', + 'color-dodge', + 'color-burn', + 'hard-light', + 'soft-light', + 'difference', + 'exclusion', + 'hue', + 'saturation', + 'color', + 'luminosity' +]; + + +/***/ }), + +/***/ 3069: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var DOMElementRender = __webpack_require__(441); +var GameObject = __webpack_require__(95643); +var IsPlainObject = __webpack_require__(41212); +var RemoveFromDOM = __webpack_require__(35846); +var SCENE_EVENTS = __webpack_require__(44594); +var Vector4 = __webpack_require__(61369); + +/** + * @classdesc + * DOM Element Game Objects are a way to control and manipulate HTML Elements over the top of your game. + * + * In order for DOM Elements to display you have to enable them by adding the following to your game + * configuration object: + * + * ```javascript + * dom { + * createContainer: true + * } + * ``` + * + * You must also have a parent container for Phaser. This is specified by the `parent` property in the + * game config. + * + * When these two things are added, Phaser will automatically create a DOM Container div that is positioned + * over the top of the game canvas. This div is sized to match the canvas, and if the canvas size changes, + * as a result of settings within the Scale Manager, the dom container is resized accordingly. + * + * If you have not already done so, you have to provide a `parent` in the Game Configuration, or the DOM + * Container will fail to be created. + * + * You can create a DOM Element by either passing in DOMStrings, or by passing in a reference to an existing + * Element that you wish to be placed under the control of Phaser. For example: + * + * ```javascript + * this.add.dom(x, y, 'div', 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser'); + * ``` + * + * The above code will insert a div element into the DOM Container at the given x/y coordinate. The DOMString in + * the 4th argument sets the initial CSS style of the div and the final argument is the inner text. In this case, + * it will create a lime colored div that is 220px by 100px in size with the text Phaser in it, in an Arial font. + * + * You should nearly always, without exception, use explicitly sized HTML Elements, in order to fully control + * alignment and positioning of the elements next to regular game content. + * + * Rather than specify the CSS and HTML directly you can use the `load.html` File Loader to load it into the + * cache and then use the `createFromCache` method instead. You can also use `createFromHTML` and various other + * methods available in this class to help construct your elements. + * + * Once the element has been created you can then control it like you would any other Game Object. You can set its + * position, scale, rotation, alpha and other properties. It will move as the main Scene Camera moves and be clipped + * at the edge of the canvas. It's important to remember some limitations of DOM Elements: The obvious one is that + * they appear above or below your game canvas. You cannot blend them into the display list, meaning you cannot have + * a DOM Element, then a Sprite, then another DOM Element behind it. + * + * They also cannot be enabled for input. To do that, you have to use the `addListener` method to add native event + * listeners directly. The final limitation is to do with cameras. The DOM Container is sized to match the game canvas + * entirely and clipped accordingly. DOM Elements respect camera scrolling and scrollFactor settings, but if you + * change the size of the camera so it no longer matches the size of the canvas, they won't be clipped accordingly. + * + * DOM Game Objects can be added to a Phaser Container, however you should only nest them **one level deep**. + * Any further down the chain and they will ignore all root container properties. + * + * Also, all DOM Elements are inserted into the same DOM Container, regardless of which Scene they are created in. + * + * Note that you should only have DOM Elements in a Scene with a _single_ Camera. If you require multiple cameras, + * use parallel scenes to achieve this. + * + * DOM Elements are a powerful way to align native HTML with your Phaser Game Objects. For example, you can insert + * a login form for a multiplayer game directly into your title screen. Or a text input box for a highscore table. + * Or a banner ad from a 3rd party service. Or perhaps you'd like to use them for high resolution text display and + * UI. The choice is up to you, just remember that you're dealing with standard HTML and CSS floating over the top + * of your game, and should treat it accordingly. + * + * @class DOMElement + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.17.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this DOM Element in the world. + * @param {number} [y=0] - The vertical position of this DOM Element in the world. + * @param {(Element|string)} [element] - An existing DOM element, or a string. If a string starting with a # it will do a `getElementById` look-up on the string (minus the hash). Without a hash, it represents the type of element to create, i.e. 'div'. + * @param {(string|any)} [style] - If a string, will be set directly as the elements `style` property value. If a plain object, will be iterated and the values transferred. In both cases the values replacing whatever CSS styles may have been previously set. + * @param {string} [innerText] - If given, will be set directly as the elements `innerText` property value, replacing whatever was there before. + */ +var DOMElement = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.Origin, + Components.ScrollFactor, + Components.Transform, + Components.Visible, + DOMElementRender + ], + + initialize: + + function DOMElement (scene, x, y, element, style, innerText) + { + GameObject.call(this, scene, 'DOMElement'); + + /** + * A reference to the parent DOM Container that the Game instance created when it started. + * + * @name Phaser.GameObjects.DOMElement#parent + * @type {Element} + * @since 3.17.0 + */ + this.parent = scene.sys.game.domContainer; + + if (!this.parent) + { + throw new Error('No DOM Container set in game config'); + } + + /** + * A reference to the HTML Cache. + * + * @name Phaser.GameObjects.DOMElement#cache + * @type {Phaser.Cache.BaseCache} + * @since 3.17.0 + */ + this.cache = scene.sys.cache.html; + + /** + * The actual DOM Element that this Game Object is bound to. For example, if you've created a `

      ` + * then this property is a direct reference to that element within the dom. + * + * @name Phaser.GameObjects.DOMElement#node + * @type {Element} + * @since 3.17.0 + */ + this.node; + + /** + * By default a DOM Element will have its transform, display, opacity, zIndex and blend mode properties + * updated when its rendered. If, for some reason, you don't want any of these changed other than the + * CSS transform, then set this flag to `true`. When `true` only the CSS Transform is applied and it's + * up to you to keep track of and set the other properties as required. + * + * This can be handy if, for example, you've a nested DOM Element and you don't want the opacity to be + * picked-up by any of its children. + * + * @name Phaser.GameObjects.DOMElement#transformOnly + * @type {boolean} + * @since 3.17.0 + */ + this.transformOnly = false; + + /** + * The angle, in radians, by which to skew the DOM Element on the horizontal axis. + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/transform + * + * @name Phaser.GameObjects.DOMElement#skewX + * @type {number} + * @since 3.17.0 + */ + this.skewX = 0; + + /** + * The angle, in radians, by which to skew the DOM Element on the vertical axis. + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/transform + * + * @name Phaser.GameObjects.DOMElement#skewY + * @type {number} + * @since 3.17.0 + */ + this.skewY = 0; + + /** + * A Vector4 that contains the 3D rotation of this DOM Element around a fixed axis in 3D space. + * + * All values in the Vector4 are treated as degrees, unless the `rotate3dAngle` property is changed. + * + * For more details see the following MDN page: + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d + * + * @name Phaser.GameObjects.DOMElement#rotate3d + * @type {Phaser.Math.Vector4} + * @since 3.17.0 + */ + this.rotate3d = new Vector4(); + + /** + * The unit that represents the 3D rotation values. By default this is `deg` for degrees, but can + * be changed to any supported unit. See this page for further details: + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d + * + * @name Phaser.GameObjects.DOMElement#rotate3dAngle + * @type {string} + * @since 3.17.0 + */ + this.rotate3dAngle = 'deg'; + + /** + * Sets the CSS `pointerEvents` attribute on the DOM Element during rendering. + * + * This is 'auto' by default. Changing it may have unintended side-effects with + * internal Phaser input handling, such as dragging, so only change this if you + * understand the implications. + * + * @name Phaser.GameObjects.DOMElement#pointerEvents + * @type {string} + * @since 3.55.0 + */ + this.pointerEvents = 'auto'; + + /** + * The native (un-scaled) width of this Game Object. + * + * For a DOM Element this property is read-only. + * + * The property `displayWidth` holds the computed bounds of this DOM Element, factoring in scaling. + * + * @name Phaser.GameObjects.DOMElement#width + * @type {number} + * @readonly + * @since 3.17.0 + */ + this.width = 0; + + /** + * The native (un-scaled) height of this Game Object. + * + * For a DOM Element this property is read-only. + * + * The property `displayHeight` holds the computed bounds of this DOM Element, factoring in scaling. + * + * @name Phaser.GameObjects.DOMElement#height + * @type {number} + * @readonly + * @since 3.17.0 + */ + this.height = 0; + + /** + * The computed display width of this Game Object, based on the `getBoundingClientRect` DOM call. + * + * The property `width` holds the un-scaled width of this DOM Element. + * + * @name Phaser.GameObjects.DOMElement#displayWidth + * @type {number} + * @readonly + * @since 3.17.0 + */ + this.displayWidth = 0; + + /** + * The computed display height of this Game Object, based on the `getBoundingClientRect` DOM call. + * + * The property `height` holds the un-scaled height of this DOM Element. + * + * @name Phaser.GameObjects.DOMElement#displayHeight + * @type {number} + * @readonly + * @since 3.17.0 + */ + this.displayHeight = 0; + + /** + * Internal native event handler. + * + * @name Phaser.GameObjects.DOMElement#handler + * @type {number} + * @private + * @since 3.17.0 + */ + this.handler = this.dispatchNativeEvent.bind(this); + + this.setPosition(x, y); + + if (typeof element === 'string') + { + // hash? + if (element[0] === '#') + { + this.setElement(element.substr(1), style, innerText); + } + else + { + this.createElement(element, style, innerText); + } + } + else if (element) + { + this.setElement(element, style, innerText); + } + + scene.sys.events.on(SCENE_EVENTS.SLEEP, this.handleSceneEvent, this); + scene.sys.events.on(SCENE_EVENTS.WAKE, this.handleSceneEvent, this); + scene.sys.events.on(SCENE_EVENTS.PRE_RENDER, this.preRender, this); + }, + + /** + * Handles a Scene Sleep and Wake event. + * + * @method Phaser.GameObjects.DOMElement#handleSceneEvent + * @private + * @since 3.22.0 + * + * @param {Phaser.Scenes.Systems} sys - The Scene Systems. + */ + handleSceneEvent: function (sys) + { + var node = this.node; + var style = node.style; + + if (node) + { + style.display = (sys.settings.visible) ? 'block' : 'none'; + } + }, + + /** + * Sets the horizontal and vertical skew values of this DOM Element. + * + * For more information see: https://developer.mozilla.org/en-US/docs/Web/CSS/transform + * + * @method Phaser.GameObjects.DOMElement#setSkew + * @since 3.17.0 + * + * @param {number} [x=0] - The angle, in radians, by which to skew the DOM Element on the horizontal axis. + * @param {number} [y=x] - The angle, in radians, by which to skew the DOM Element on the vertical axis. + * + * @return {this} This DOM Element instance. + */ + setSkew: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = x; } + + this.skewX = x; + this.skewY = y; + + return this; + }, + + /** + * Sets the perspective CSS property of the _parent DOM Container_. This determines the distance between the z=0 + * plane and the user in order to give a 3D-positioned element some perspective. Each 3D element with + * z > 0 becomes larger; each 3D-element with z < 0 becomes smaller. The strength of the effect is determined + * by the value of this property. + * + * For more information see: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective + * + * **Changing this value changes it globally for all DOM Elements, as they all share the same parent container.** + * + * @method Phaser.GameObjects.DOMElement#setPerspective + * @since 3.17.0 + * + * @param {number} value - The perspective value, in pixels, that determines the distance between the z plane and the user. + * + * @return {this} This DOM Element instance. + */ + setPerspective: function (value) + { + this.parent.style.perspective = value + 'px'; + + return this; + }, + + /** + * The perspective CSS property value of the _parent DOM Container_. This determines the distance between the z=0 + * plane and the user in order to give a 3D-positioned element some perspective. Each 3D element with + * z > 0 becomes larger; each 3D-element with z < 0 becomes smaller. The strength of the effect is determined + * by the value of this property. + * + * For more information see: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective + * + * **Changing this value changes it globally for all DOM Elements, as they all share the same parent container.** + * + * @name Phaser.GameObjects.DOMElement#perspective + * @type {number} + * @since 3.17.0 + */ + perspective: { + + get: function () + { + return parseFloat(this.parent.style.perspective); + }, + + set: function (value) + { + this.parent.style.perspective = value + 'px'; + } + + }, + + /** + * Adds one or more native DOM event listeners onto the underlying Element of this Game Object. + * The event is then dispatched via this Game Objects standard event emitter. + * + * For example: + * + * ```javascript + * var div = this.add.dom(x, y, element); + * + * div.addListener('click'); + * + * div.on('click', handler); + * ``` + * + * @method Phaser.GameObjects.DOMElement#addListener + * @since 3.17.0 + * + * @param {string} events - The DOM event/s to listen for. You can specify multiple events by separating them with spaces. + * + * @return {this} This DOM Element instance. + */ + addListener: function (events) + { + if (this.node) + { + events = events.split(' '); + + for (var i = 0; i < events.length; i++) + { + this.node.addEventListener(events[i], this.handler, false); + } + } + + return this; + }, + + /** + * Removes one or more native DOM event listeners from the underlying Element of this Game Object. + * + * @method Phaser.GameObjects.DOMElement#removeListener + * @since 3.17.0 + * + * @param {string} events - The DOM event/s to stop listening for. You can specify multiple events by separating them with spaces. + * + * @return {this} This DOM Element instance. + */ + removeListener: function (events) + { + if (this.node) + { + events = events.split(' '); + + for (var i = 0; i < events.length; i++) + { + this.node.removeEventListener(events[i], this.handler); + } + } + + return this; + }, + + /** + * Internal event proxy to dispatch native DOM Events via this Game Object. + * + * @method Phaser.GameObjects.DOMElement#dispatchNativeEvent + * @private + * @since 3.17.0 + * + * @param {any} event - The native DOM event. + */ + dispatchNativeEvent: function (event) + { + this.emit(event.type, event); + }, + + /** + * Creates a native DOM Element, adds it to the parent DOM Container and then binds it to this Game Object, + * so you can control it. The `tagName` should be a string and is passed to `document.createElement`: + * + * ```javascript + * this.add.dom().createElement('div'); + * ``` + * + * For more details on acceptable tag names see: https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement + * + * You can also pass in a DOMString or style object to set the CSS on the created element, and an optional `innerText` + * value as well. Here is an example of a DOMString: + * + * ```javascript + * this.add.dom().createElement('div', 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser'); + * ``` + * + * And using a style object: + * + * ```javascript + * var style = { + * 'background-color': 'lime'; + * 'width': '200px'; + * 'height': '100px'; + * 'font': '48px Arial'; + * }; + * + * this.add.dom().createElement('div', style, 'Phaser'); + * ``` + * + * If this Game Object already has an Element, it is removed from the DOM entirely first. + * Any event listeners you may have previously created will need to be re-created after this call. + * + * @method Phaser.GameObjects.DOMElement#createElement + * @since 3.17.0 + * + * @param {string} tagName - A string that specifies the type of element to be created. The nodeName of the created element is initialized with the value of tagName. Don't use qualified names (like "html:a") with this method. + * @param {(string|any)} [style] - Either a DOMString that holds the CSS styles to be applied to the created element, or an object the styles will be ready from. + * @param {string} [innerText] - A DOMString that holds the text that will be set as the innerText of the created element. + * + * @return {this} This DOM Element instance. + */ + createElement: function (tagName, style, innerText) + { + return this.setElement(document.createElement(tagName), style, innerText); + }, + + /** + * Binds a new DOM Element to this Game Object. If this Game Object already has an Element it is removed from the DOM + * entirely first. Any event listeners you may have previously created will need to be re-created on the new element. + * + * The `element` argument you pass to this method can be either a string tagName: + * + * ```javascript + *

      Phaser

      + * + * this.add.dom().setElement('heading'); + * ``` + * + * Or a reference to an Element instance: + * + * ```javascript + *

      Phaser

      + * + * var h1 = document.getElementById('heading'); + * + * this.add.dom().setElement(h1); + * ``` + * + * You can also pass in a DOMString or style object to set the CSS on the created element, and an optional `innerText` + * value as well. Here is an example of a DOMString: + * + * ```javascript + * this.add.dom().setElement(h1, 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser'); + * ``` + * + * And using a style object: + * + * ```javascript + * var style = { + * 'background-color': 'lime'; + * 'width': '200px'; + * 'height': '100px'; + * 'font': '48px Arial'; + * }; + * + * this.add.dom().setElement(h1, style, 'Phaser'); + * ``` + * + * @method Phaser.GameObjects.DOMElement#setElement + * @since 3.17.0 + * + * @param {(string|Element)} element - If a string it is passed to `getElementById()`, or it should be a reference to an existing Element. + * @param {(string|any)} [style] - Either a DOMString that holds the CSS styles to be applied to the created element, or an object the styles will be ready from. + * @param {string} [innerText] - A DOMString that holds the text that will be set as the innerText of the created element. + * + * @return {this} This DOM Element instance. + */ + setElement: function (element, style, innerText) + { + // Already got an element? Remove it first + this.removeElement(); + + var target; + + if (typeof element === 'string') + { + // hash? + if (element[0] === '#') + { + element = element.substr(1); + } + + target = document.getElementById(element); + } + else if (typeof element === 'object' && element.nodeType === 1) + { + target = element; + } + + if (!target) + { + return this; + } + + this.node = target; + + // style can be empty, a string or a plain object + if (style && IsPlainObject(style)) + { + for (var key in style) + { + target.style[key] = style[key]; + } + } + else if (typeof style === 'string') + { + target.style = style; + } + + // Add / Override the values we need + + target.style.zIndex = '0'; + target.style.display = 'inline'; + target.style.position = 'absolute'; + + // Node handler + + target.phaser = this; + + this.parent.appendChild(target); + + // InnerText + + if (innerText) + { + target.innerText = innerText; + } + + return this.updateSize(); + }, + + /** + * Takes a block of html from the HTML Cache, that has previously been preloaded into the game, and then + * creates a DOM Element from it. The loaded HTML is set as the `innerHTML` property of the created + * element. + * + * Assume the following html is stored in a file called `loginform.html`: + * + * ```html + * + * + * ``` + * + * Which is loaded into your game using the cache key 'login': + * + * ```javascript + * this.load.html('login', 'assets/loginform.html'); + * ``` + * + * You can create a DOM Element from it using the cache key: + * + * ```javascript + * this.add.dom().createFromCache('login'); + * ``` + * + * The optional `elementType` argument controls the container that is created, into which the loaded html is inserted. + * The default is a plain `div` object, but any valid tagName can be given. + * + * If this Game Object already has an Element, it is removed from the DOM entirely first. + * Any event listeners you may have previously created will need to be re-created after this call. + * + * @method Phaser.GameObjects.DOMElement#createFromCache + * @since 3.17.0 + * + * @param {string} The key of the html cache entry to use for this DOM Element. + * @param {string} [tagName='div'] - The tag name of the element into which all of the loaded html will be inserted. Defaults to a plain div tag. + * + * @return {this} This DOM Element instance. + */ + createFromCache: function (key, tagName) + { + var html = this.cache.get(key); + + if (html) + { + this.createFromHTML(html, tagName); + } + + return this; + }, + + /** + * Takes a string of html and then creates a DOM Element from it. The HTML is set as the `innerHTML` + * property of the created element. + * + * ```javascript + * let form = ` + * + * + * `; + * ``` + * + * You can create a DOM Element from it using the string: + * + * ```javascript + * this.add.dom().createFromHTML(form); + * ``` + * + * The optional `elementType` argument controls the type of container that is created, into which the html is inserted. + * The default is a plain `div` object, but any valid tagName can be given. + * + * If this Game Object already has an Element, it is removed from the DOM entirely first. + * Any event listeners you may have previously created will need to be re-created after this call. + * + * @method Phaser.GameObjects.DOMElement#createFromHTML + * @since 3.17.0 + * + * @param {string} html - A string of html to be set as the `innerHTML` property of the created element. + * @param {string} [tagName='div'] - The tag name of the element into which all of the html will be inserted. Defaults to a plain div tag. + * + * @return {this} This DOM Element instance. + */ + createFromHTML: function (html, tagName) + { + if (tagName === undefined) { tagName = 'div'; } + + // Already got an element? Remove it first + this.removeElement(); + + var element = document.createElement(tagName); + + this.node = element; + + element.style.zIndex = '0'; + element.style.display = 'inline'; + element.style.position = 'absolute'; + + // Node handler + + element.phaser = this; + + this.parent.appendChild(element); + + element.innerHTML = html; + + return this.updateSize(); + }, + + /** + * Removes the current DOM Element bound to this Game Object from the DOM entirely and resets the + * `node` property of this Game Object to be `null`. + * + * @method Phaser.GameObjects.DOMElement#removeElement + * @since 3.17.0 + * + * @return {this} This DOM Element instance. + */ + removeElement: function () + { + if (this.node) + { + RemoveFromDOM(this.node); + + this.node = null; + } + + return this; + }, + + /** + * Internal method that sets the `displayWidth` and `displayHeight` properties, and the `clientWidth` + * and `clientHeight` values into the `width` and `height` properties respectively. + * + * This is called automatically whenever a new element is created or set. + * + * @method Phaser.GameObjects.DOMElement#updateSize + * @since 3.17.0 + * + * @return {this} This DOM Element instance. + */ + updateSize: function () + { + var node = this.node; + + this.width = node.clientWidth; + this.height = node.clientHeight; + + this.displayWidth = this.width * this.scaleX; + this.displayHeight = this.height * this.scaleY; + + return this; + }, + + /** + * Gets all children from this DOM Elements node, using `querySelectorAll('*')` and then iterates through + * them, looking for the first one that has a property matching the given key and value. It then returns this child + * if found, or `null` if not. + * + * @method Phaser.GameObjects.DOMElement#getChildByProperty + * @since 3.17.0 + * + * @param {string} property - The property to search the children for. + * @param {string} value - The value the property must strictly equal. + * + * @return {?Element} The first matching child DOM Element, or `null` if not found. + */ + getChildByProperty: function (property, value) + { + if (this.node) + { + var children = this.node.querySelectorAll('*'); + + for (var i = 0; i < children.length; i++) + { + if (children[i][property] === value) + { + return children[i]; + } + } + } + + return null; + }, + + /** + * Gets all children from this DOM Elements node, using `querySelectorAll('*')` and then iterates through + * them, looking for the first one that has a matching id. It then returns this child if found, or `null` if not. + * + * Be aware that class and id names are case-sensitive. + * + * @method Phaser.GameObjects.DOMElement#getChildByID + * @since 3.17.0 + * + * @param {string} id - The id to search the children for. + * + * @return {?Element} The first matching child DOM Element, or `null` if not found. + */ + getChildByID: function (id) + { + return this.getChildByProperty('id', id); + }, + + /** + * Gets all children from this DOM Elements node, using `querySelectorAll('*')` and then iterates through + * them, looking for the first one that has a matching name. It then returns this child if found, or `null` if not. + * + * Be aware that class and id names are case-sensitive. + * + * @method Phaser.GameObjects.DOMElement#getChildByName + * @since 3.17.0 + * + * @param {string} name - The name to search the children for. + * + * @return {?Element} The first matching child DOM Element, or `null` if not found. + */ + getChildByName: function (name) + { + return this.getChildByProperty('name', name); + }, + + /** + * Sets the `className` property of the DOM Element node and updates the internal sizes. + * + * @method Phaser.GameObjects.DOMElement#setClassName + * @since 3.17.0 + * + * @param {string} className - A string representing the class or space-separated classes of the element. + * + * @return {this} This DOM Element instance. + */ + setClassName: function (className) + { + if (this.node) + { + this.node.className = className; + + this.updateSize(); + } + + return this; + }, + + /** + * Sets the `innerText` property of the DOM Element node and updates the internal sizes. + * + * Note that only certain types of Elements can have `innerText` set on them. + * + * @method Phaser.GameObjects.DOMElement#setText + * @since 3.17.0 + * + * @param {string} text - A DOMString representing the rendered text content of the element. + * + * @return {this} This DOM Element instance. + */ + setText: function (text) + { + if (this.node) + { + this.node.innerText = text; + + this.updateSize(); + } + + return this; + }, + + /** + * Sets the `innerHTML` property of the DOM Element node and updates the internal sizes. + * + * @method Phaser.GameObjects.DOMElement#setHTML + * @since 3.17.0 + * + * @param {string} html - A DOMString of html to be set as the `innerHTML` property of the element. + * + * @return {this} This DOM Element instance. + */ + setHTML: function (html) + { + if (this.node) + { + this.node.innerHTML = html; + + this.updateSize(); + } + + return this; + }, + + /** + * Runs internal update tasks. + * + * @method Phaser.GameObjects.DOMElement#preRender + * @private + * @since 3.60.0 + */ + preRender: function () + { + var parent = this.parentContainer; + var node = this.node; + + if (node && parent && !parent.willRender()) + { + node.style.display = 'none'; + } + }, + + /** + * Compares the renderMask with the renderFlags to see if this Game Object will render or not. + * + * DOMElements always return `true` as they need to still set values during the render pass, even if not visible. + * + * @method Phaser.GameObjects.DOMElement#willRender + * @since 3.17.0 + * + * @return {boolean} `true` if the Game Object should be rendered, otherwise `false`. + */ + willRender: function () + { + return true; + }, + + /** + * Handles the pre-destroy step for the DOM Element, which removes the underlying node from the DOM. + * + * @method Phaser.GameObjects.DOMElement#preDestroy + * @private + * @since 3.17.0 + */ + preDestroy: function () + { + this.removeElement(); + + this.scene.sys.events.off(SCENE_EVENTS.SLEEP, this.handleSceneEvent, this); + this.scene.sys.events.off(SCENE_EVENTS.WAKE, this.handleSceneEvent, this); + this.scene.sys.events.off(SCENE_EVENTS.PRE_RENDER, this.preRender, this); + } + +}); + +module.exports = DOMElement; + + +/***/ }), + +/***/ 49381: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CSSBlendModes = __webpack_require__(47407); +var GameObject = __webpack_require__(95643); +var TransformMatrix = __webpack_require__(61340); + +var tempMatrix1 = new TransformMatrix(); +var tempMatrix2 = new TransformMatrix(); +var tempMatrix3 = new TransformMatrix(); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.DOMElement#renderWebGL + * @since 3.17.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active renderer. + * @param {Phaser.GameObjects.DOMElement} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var DOMElementCSSRenderer = function (renderer, src, camera, parentMatrix) +{ + if (!src.node) + { + return; + } + + if (camera.camera) + { + // `camera` is really a DrawingContext object, used in WebGL rendering. + camera = camera.camera; + } + + var style = src.node.style; + var settings = src.scene.sys.settings; + + if (!style || !settings.visible || GameObject.RENDER_MASK !== src.renderFlags || (src.cameraFilter !== 0 && (src.cameraFilter & camera.id)) || (src.parentContainer && !src.parentContainer.willRender())) + { + style.display = 'none'; + + return; + } + + var parent = src.parentContainer; + var alpha = camera.alpha * src.alpha; + + if (parent) + { + alpha *= parent.alpha; + } + + var camMatrix = tempMatrix1; + var srcMatrix = tempMatrix2; + var calcMatrix = tempMatrix3; + + var dx = src.width * src.originX; + var dy = src.height * src.originY; + + var tx = '0%'; + var ty = '0%'; + + camMatrix.copyWithScrollFactorFrom( + camera.matrix, + camera.scrollX, camera.scrollY, + src.scrollFactorX, src.scrollFactorY + ); + + if (parentMatrix) + { + camMatrix.multiply(parentMatrix); + dx *= src.scaleX; + dy *= src.scaleY; + } + else + { + tx = (100 * src.originX) + '%'; + ty = (100 * src.originY) + '%'; + } + + camMatrix.translate(-dx, -dy); + + srcMatrix.applyITRS( + src.x, src.y, + src.rotation, + src.scaleX, src.scaleY + ); + + camMatrix.multiply(srcMatrix, calcMatrix); + + if (!src.transformOnly) + { + style.display = 'block'; + style.opacity = alpha; + style.zIndex = src._depth; + style.pointerEvents = src.pointerEvents; + style.mixBlendMode = CSSBlendModes[src._blendMode]; + } + + // https://developer.mozilla.org/en-US/docs/Web/CSS/transform + + style.transform = + calcMatrix.getCSSMatrix() + + ' skew(' + src.skewX + 'rad, ' + src.skewY + 'rad)' + + ' rotate3d(' + src.rotate3d.x + ',' + src.rotate3d.y + ',' + src.rotate3d.z + ',' + src.rotate3d.w + src.rotate3dAngle + ')'; + + style.transformOrigin = tx + ' ' + ty; +}; + +module.exports = DOMElementCSSRenderer; + + +/***/ }), + +/***/ 2611: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DOMElement = __webpack_require__(3069); +var GameObjectFactory = __webpack_require__(39429); + +/** + * DOM Element Game Objects are a way to control and manipulate HTML Elements over the top of your game. + * + * In order for DOM Elements to display you have to enable them by adding the following to your game + * configuration object: + * + * ```javascript + * dom { + * createContainer: true + * } + * ``` + * + * When this is added, Phaser will automatically create a DOM Container div that is positioned over the top + * of the game canvas. This div is sized to match the canvas, and if the canvas size changes, as a result of + * settings within the Scale Manager, the dom container is resized accordingly. + * + * You can create a DOM Element by either passing in DOMStrings, or by passing in a reference to an existing + * Element that you wish to be placed under the control of Phaser. For example: + * + * ```javascript + * this.add.dom(x, y, 'div', 'background-color: lime; width: 220px; height: 100px; font: 48px Arial', 'Phaser'); + * ``` + * + * The above code will insert a div element into the DOM Container at the given x/y coordinate. The DOMString in + * the 4th argument sets the initial CSS style of the div and the final argument is the inner text. In this case, + * it will create a lime colored div that is 220px by 100px in size with the text Phaser in it, in an Arial font. + * + * You should nearly always, without exception, use explicitly sized HTML Elements, in order to fully control + * alignment and positioning of the elements next to regular game content. + * + * Rather than specify the CSS and HTML directly you can use the `load.html` File Loader to load it into the + * cache and then use the `createFromCache` method instead. You can also use `createFromHTML` and various other + * methods available in this class to help construct your elements. + * + * Once the element has been created you can then control it like you would any other Game Object. You can set its + * position, scale, rotation, alpha and other properties. It will move as the main Scene Camera moves and be clipped + * at the edge of the canvas. It's important to remember some limitations of DOM Elements: The obvious one is that + * they appear above or below your game canvas. You cannot blend them into the display list, meaning you cannot have + * a DOM Element, then a Sprite, then another DOM Element behind it. + * + * They also cannot be enabled for input. To do that, you have to use the `addListener` method to add native event + * listeners directly. The final limitation is to do with cameras. The DOM Container is sized to match the game canvas + * entirely and clipped accordingly. DOM Elements respect camera scrolling and scrollFactor settings, but if you + * change the size of the camera so it no longer matches the size of the canvas, they won't be clipped accordingly. + * + * Also, all DOM Elements are inserted into the same DOM Container, regardless of which Scene they are created in. + * + * DOM Elements are a powerful way to align native HTML with your Phaser Game Objects. For example, you can insert + * a login form for a multiplayer game directly into your title screen. Or a text input box for a highscore table. + * Or a banner ad from a 3rd party service. Or perhaps you'd like to use them for high resolution text display and + * UI. The choice is up to you, just remember that you're dealing with standard HTML and CSS floating over the top + * of your game, and should treat it accordingly. + * + * Note: This method will only be available if the DOM Element Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#dom + * @since 3.17.0 + * + * @param {number} x - The horizontal position of this DOM Element in the world. + * @param {number} y - The vertical position of this DOM Element in the world. + * @param {(HTMLElement|string)} [element] - An existing DOM element, or a string. If a string starting with a # it will do a `getElementById` look-up on the string (minus the hash). Without a hash, it represents the type of element to create, i.e. 'div'. + * @param {(string|any)} [style] - If a string, will be set directly as the elements `style` property value. If a plain object, will be iterated and the values transferred. In both cases the values replacing whatever CSS styles may have been previously set. + * @param {string} [innerText] - If given, will be set directly as the elements `innerText` property value, replacing whatever was there before. + * + * @return {Phaser.GameObjects.DOMElement} The Game Object that was created. + */ +GameObjectFactory.register('dom', function (x, y, element, style, innerText) +{ + var gameObject = new DOMElement(this.scene, x, y, element, style, innerText); + + this.displayList.add(gameObject); + + return gameObject; +}); + + +/***/ }), + +/***/ 441: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(49381); +} + +if (true) +{ + renderCanvas = __webpack_require__(49381); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 62980: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Added to Scene Event. + * + * This event is dispatched when a Game Object is added to a Scene. + * + * Listen for it on a Game Object instance using `GameObject.on('addedtoscene', listener)`. + * + * @event Phaser.GameObjects.Events#ADDED_TO_SCENE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the Scene. + * @param {Phaser.Scene} scene - The Scene to which the Game Object was added. + */ +module.exports = 'addedtoscene'; + + +/***/ }), + +/***/ 41337: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Destroy Event. + * + * This event is dispatched when a Game Object instance is being destroyed. + * + * Listen for it on a Game Object instance using `GameObject.on('destroy', listener)`. + * + * @event Phaser.GameObjects.Events#DESTROY + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object which is being destroyed. + * @param {boolean} fromScene - `True` if this Game Object is being destroyed by the Scene, `false` if not. + */ +module.exports = 'destroy'; + + +/***/ }), + +/***/ 44947: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Removed from Scene Event. + * + * This event is dispatched when a Game Object is removed from a Scene. + * + * Listen for it on a Game Object instance using `GameObject.on('removedfromscene', listener)`. + * + * @event Phaser.GameObjects.Events#REMOVED_FROM_SCENE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the Scene. + * @param {Phaser.Scene} scene - The Scene from which the Game Object was removed. + */ +module.exports = 'removedfromscene'; + + +/***/ }), + +/***/ 49358: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Complete Event. + * + * This event is dispatched when a Video finishes playback by reaching the end of its duration. It + * is also dispatched if a video marker sequence is being played and reaches the end. + * + * Note that not all videos can fire this event. Live streams, for example, have no fixed duration, + * so never technically 'complete'. + * + * If a video is stopped from playback, via the `Video.stop` method, it will emit the + * `VIDEO_STOP` event instead of this one. + * + * Listen for it from a Video Game Object instance using `Video.on('complete', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_COMPLETE + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which completed playback. + */ +module.exports = 'complete'; + + +/***/ }), + +/***/ 35163: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Created Event. + * + * This event is dispatched when the texture for a Video has been created. This happens + * when enough of the video source has been loaded that the browser is able to render a + * frame from it. + * + * Listen for it from a Video Game Object instance using `Video.on('created', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_CREATED + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which raised the event. + * @param {number} width - The width of the video. + * @param {number} height - The height of the video. + */ +module.exports = 'created'; + + +/***/ }), + +/***/ 97249: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Error Event. + * + * This event is dispatched when a Video tries to play a source that does not exist, or is the wrong file type. + * + * Listen for it from a Video Game Object instance using `Video.on('error', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_ERROR + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which threw the error. + * @param {DOMException|string} event - The native DOM event the browser raised during playback. + */ +module.exports = 'error'; + + +/***/ }), + +/***/ 19483: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Locked Event. + * + * This event is dispatched when a Video was attempted to be played, but the browser prevented it + * from doing so due to the Media Engagement Interaction policy. + * + * If you get this event you will need to wait for the user to interact with the browser before + * the video will play. This is a browser security measure to prevent autoplaying videos with + * audio. An interaction includes a mouse click, a touch, or a key press. + * + * Listen for it from a Video Game Object instance using `Video.on('locked', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_LOCKED + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which raised the event. + */ +module.exports = 'locked'; + + +/***/ }), + +/***/ 56059: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Loop Event. + * + * This event is dispatched when a Video that is currently playing has looped. This only + * happens if the `loop` parameter was specified, or the `setLoop` method was called, + * and if the video has a fixed duration. Video streams, for example, cannot loop, as + * they have no duration. + * + * Looping is based on the result of the Video `timeupdate` event. This event is not + * frame-accurate, due to the way browsers work, so please do not rely on this loop + * event to be time or frame precise. + * + * Listen for it from a Video Game Object instance using `Video.on('loop', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_LOOP + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which has looped. + */ +module.exports = 'loop'; + + +/***/ }), + +/***/ 26772: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Metadata Event. + * + * This event is dispatched when a Video has access to the metadata. + * + * Listen for it from a Video Game Object instance using `Video.on('metadata', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_METADATA + * @type {string} + * @since 3.80.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which fired the event. + * @param {DOMException|string} event - The native DOM event the browser raised during playback. + */ +module.exports = 'metadata'; + + +/***/ }), + +/***/ 64437: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Playing Event. + * + * The playing event is fired after playback is first started, + * and whenever it is restarted. For example it is fired when playback + * resumes after having been paused or delayed due to lack of data. + * + * Listen for it from a Video Game Object instance using `Video.on('playing', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_PLAYING + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which started playback. + */ +module.exports = 'playing'; + + +/***/ }), + +/***/ 83411: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Play Event. + * + * This event is dispatched when a Video begins playback. For videos that do not require + * interaction unlocking, this is usually as soon as the `Video.play` method is called. + * However, for videos that require unlocking, it is fired once playback begins after + * they've been unlocked. + * + * Listen for it from a Video Game Object instance using `Video.on('play', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_PLAY + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which started playback. + */ +module.exports = 'play'; + + +/***/ }), + +/***/ 75780: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Seeked Event. + * + * This event is dispatched when a Video completes seeking to a new point in its timeline. + * + * Listen for it from a Video Game Object instance using `Video.on('seeked', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_SEEKED + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which completed seeking. + */ +module.exports = 'seeked'; + + +/***/ }), + +/***/ 67799: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Seeking Event. + * + * This event is dispatched when a Video _begins_ seeking to a new point in its timeline. + * When the seek is complete, it will dispatch the `VIDEO_SEEKED` event to conclude. + * + * Listen for it from a Video Game Object instance using `Video.on('seeking', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_SEEKING + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which started seeking. + */ +module.exports = 'seeking'; + + +/***/ }), + +/***/ 63500: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Stalled Event. + * + * This event is dispatched by a Video Game Object when the video playback stalls. + * + * This can happen if the video is buffering. + * + * If will fire for any of the following native DOM events: + * + * `stalled` + * `suspend` + * `waiting` + * + * Listen for it from a Video Game Object instance using `Video.on('stalled', listener)`. + * + * Note that being stalled isn't always a negative thing. A video can be stalled if it + * has downloaded enough data in to its buffer to not need to download any more until + * the current batch of frames have rendered. + * + * @event Phaser.GameObjects.Events#VIDEO_STALLED + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which threw the error. + * @param {Event} event - The native DOM event the browser raised during playback. + */ +module.exports = 'stalled'; + + +/***/ }), + +/***/ 55541: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Stopped Event. + * + * This event is dispatched when a Video is stopped from playback via a call to the `Video.stop` method, + * either directly via game code, or indirectly as the result of changing a video source or destroying it. + * + * Listen for it from a Video Game Object instance using `Video.on('stop', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_STOP + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which stopped playback. + */ +module.exports = 'stop'; + + +/***/ }), + +/***/ 53208: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Texture Ready Event. + * + * This event is dispatched by a Video Game Object when it has finished creating its texture. + * + * This happens when the video has finished loading enough data for its first frame. + * + * If you wish to use the Video texture elsewhere in your game, such as as a Sprite texture, + * then you should listen for this event first, before creating the Sprites that use it. + * + * Listen for it from a Video Game Object instance using `Video.on('textureready', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_TEXTURE + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object that emitted the event. + * @param {Phaser.Textures.Texture} texture - The Texture that was created. + */ +module.exports = 'textureready'; + + +/***/ }), + +/***/ 4992: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Unlocked Event. + * + * This event is dispatched when a Video that was prevented from playback due to the browsers + * Media Engagement Interaction policy, is unlocked by a user gesture. + * + * Listen for it from a Video Game Object instance using `Video.on('unlocked', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_UNLOCKED + * @type {string} + * @since 3.20.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which raised the event. + */ +module.exports = 'unlocked'; + + +/***/ }), + +/***/ 12: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Video Game Object Unsupported Event. + * + * This event is dispatched by a Video Game Object if the media source + * (which may be specified as a MediaStream, MediaSource, Blob, or File, + * for example) doesn't represent a supported media format. + * + * Listen for it from a Video Game Object instance using `Video.on('unsupported', listener)`. + * + * @event Phaser.GameObjects.Events#VIDEO_UNSUPPORTED + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Video} video - The Video Game Object which started playback. + * @param {DOMException|string} event - The native DOM event the browser raised during playback. + */ +module.exports = 'unsupported'; + + +/***/ }), + +/***/ 51708: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.GameObjects.Events + */ + +module.exports = { + + ADDED_TO_SCENE: __webpack_require__(62980), + DESTROY: __webpack_require__(41337), + REMOVED_FROM_SCENE: __webpack_require__(44947), + VIDEO_COMPLETE: __webpack_require__(49358), + VIDEO_CREATED: __webpack_require__(35163), + VIDEO_ERROR: __webpack_require__(97249), + VIDEO_LOCKED: __webpack_require__(19483), + VIDEO_LOOP: __webpack_require__(56059), + VIDEO_METADATA: __webpack_require__(26772), + VIDEO_PLAY: __webpack_require__(83411), + VIDEO_PLAYING: __webpack_require__(64437), + VIDEO_SEEKED: __webpack_require__(75780), + VIDEO_SEEKING: __webpack_require__(67799), + VIDEO_STALLED: __webpack_require__(63500), + VIDEO_STOP: __webpack_require__(55541), + VIDEO_TEXTURE: __webpack_require__(53208), + VIDEO_UNLOCKED: __webpack_require__(4992), + VIDEO_UNSUPPORTED: __webpack_require__(12) + +}; + + +/***/ }), + +/***/ 42421: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var ExternRender = __webpack_require__(64993); + +/** + * @classdesc + * An Extern Game Object is a special type of Game Object that allows you to pass + * rendering off to a 3rd party. + * + * When you create an Extern and place it in the display list of a Scene, the renderer will + * process the list as usual. When it finds an Extern it will flush the current batch + * and prepare a transform matrix which your render function can + * take advantage of, if required. + * + * The WebGL context is then left in a 'clean' state, ready for you to bind your own shaders, + * or draw to it, whatever you wish to do. This should all take place in the `render` method. + * The correct way to deploy an Extern object is to create a class that extends it, then + * override the `render` (and optionally `preUpdate`) methods and pass off control to your + * 3rd party libraries or custom WebGL code there. + * + * The `render` method is called with this signature: + * `render(renderer: Phaser.Renderer.WebGL.WebGLRenderer, drawingContext: Phaser.Renderer.WebGL.DrawingContext, calcMatrix: Phaser.GameObjects.Components.TransformMatrix, displayList: Phaser.GameObjects.GameObject[], displayListIndex: number): void`. + * + * The `displayList` and `displayListIndex` parameters allow you to check + * other objects in the display list. This might be convenient for optimizing + * operations such as resource management. + * + * Once you've finished, you should free-up any of your resources. + * The Extern will then return Phaser state and carry on rendering the display list. + * + * Although this object has lots of properties such as Alpha, Blend Mode and Tint, none of + * them are used during rendering unless you take advantage of them in your own render code. + * + * @example + * extern.render = (webGLRenderer, drawingContext, calcMatrix) => { + * // You may want to initialize the external renderer here. + * // ... + * + * // Ensure the DrawingContext framebuffer is bound. + * // This allows you to use Filters on the external render. + * webGLRenderer.glWrapper.updateBindingsFramebuffer({ + * bindings: { + * framebuffer: drawingContext.framebuffer + * } + * }, true); + * + * // Run the external render method. + * // ... + * }; + * + * @class Extern + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.16.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + */ +var Extern = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.Depth, + Components.Flip, + Components.Origin, + Components.ScrollFactor, + Components.Size, + Components.Texture, + Components.Tint, + Components.Transform, + Components.Visible, + ExternRender + ], + + initialize: + + function Extern (scene) + { + GameObject.call(this, scene, 'Extern'); + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + preUpdate: function () + { + // override this! + // Arguments: time, delta + }, + + render: function () + { + // override this! + // Arguments: renderer, drawingContext, calcMatrix, displayList, displayListIndex + } + +}); + +module.exports = Extern; + + +/***/ }), + +/***/ 70217: +/***/ (() => { + + + +/***/ }), + +/***/ 56315: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Extern = __webpack_require__(42421); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Extern Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Extern Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#extern + * @since 3.16.0 + * + * @return {Phaser.GameObjects.Extern} The Game Object that was created. + */ +GameObjectFactory.register('extern', function () +{ + var extern = new Extern(this.scene); + + this.displayList.add(extern); + + return extern; +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 64993: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(80287); +} + +if (true) +{ + renderCanvas = __webpack_require__(70217); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 80287: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Extern#renderWebGL + * @since 3.16.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Extern} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + * @param {number} renderStep - The render step index. + * @param {Phaser.GameObjects.GameObject[]} displayList - The display list which is currently being rendered. + * @param {number} displayListIndex - The index of the Game Object within the display list. + */ +var ExternWebGLRenderer = function (renderer, src, drawingContext, parentMatrix, renderStep, displayList, displayListIndex) +{ + renderer.renderNodes.getNode('YieldContext').run(drawingContext); + + var calcMatrix = GetCalcMatrix(src, drawingContext.camera, parentMatrix, !drawingContext.useCanvas).calc; + + src.render.call(src, renderer, drawingContext, calcMatrix, displayList, displayListIndex); + + renderer.renderNodes.getNode('RebindContext').run(drawingContext); +}; + +module.exports = ExternWebGLRenderer; + + +/***/ }), + +/***/ 85592: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +module.exports = { + + ARC: 0, + BEGIN_PATH: 1, + CLOSE_PATH: 2, + FILL_RECT: 3, + LINE_TO: 4, + MOVE_TO: 5, + LINE_STYLE: 6, + FILL_STYLE: 7, + FILL_PATH: 8, + STROKE_PATH: 9, + FILL_TRIANGLE: 10, + STROKE_TRIANGLE: 11, + SAVE: 14, + RESTORE: 15, + TRANSLATE: 16, + SCALE: 17, + ROTATE: 18, + GRADIENT_FILL_STYLE: 21, + GRADIENT_LINE_STYLE: 22 + +}; + + +/***/ }), + +/***/ 43831: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseCamera = __webpack_require__(71911); +var Class = __webpack_require__(83419); +var Commands = __webpack_require__(85592); +var Components = __webpack_require__(31401); +var Ellipse = __webpack_require__(8497); +var GameObject = __webpack_require__(95643); +var DefaultGraphicsNodes = __webpack_require__(87891); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var MATH_CONST = __webpack_require__(36383); +var Render = __webpack_require__(84503); + +/** + * @classdesc + * A Graphics object is a way to draw primitive shapes to your game. Primitives include forms of geometry, such as + * Rectangles, Circles, and Polygons. They also include lines, arcs and curves. When you initially create a Graphics + * object it will be empty. + * + * To draw to it you must first specify a line style or fill style (or both), draw shapes using paths, and finally + * fill or stroke them. For example: + * + * ```javascript + * graphics.lineStyle(5, 0xFF00FF, 1.0); + * graphics.beginPath(); + * graphics.moveTo(100, 100); + * graphics.lineTo(200, 200); + * graphics.closePath(); + * graphics.strokePath(); + * ``` + * + * There are also many helpful methods that draw and fill/stroke common shapes for you. + * + * ```javascript + * graphics.lineStyle(5, 0xFF00FF, 1.0); + * graphics.fillStyle(0xFFFFFF, 1.0); + * graphics.fillRect(50, 50, 400, 200); + * graphics.strokeRect(50, 50, 400, 200); + * ``` + * + * When a Graphics object is rendered it will render differently based on if the game is running under Canvas or WebGL. + * Under Canvas it will use the HTML Canvas context drawing operations to draw the path. + * Under WebGL the graphics data is decomposed into polygons. Both of these are expensive processes, especially with + * complex shapes. + * + * If your Graphics object doesn't change much (or at all) once you've drawn your shape to it, then you will help + * performance by calling {@link Phaser.GameObjects.Graphics#generateTexture}. This will 'bake' the Graphics object into + * a Texture, and return it. You can then use this Texture for Sprites or other display objects. If your Graphics object + * updates frequently then you should avoid doing this, as it will constantly generate new textures, which will consume + * memory. + * + * Under WebGL, Graphics uses its own shader which will batch drawing operations. + * Try to keep Graphics objects grouped together so they can be batched together. + * Avoid mixing object types where possible, as each batch will be flushed, + * costing performance. + * + * As you can tell, Graphics objects are a bit of a trade-off. While they are extremely useful, you need to be careful + * in their complexity and quantity of them in your game. + * + * @class Graphics + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * @extends Phaser.GameObjects.Components.ScrollFactor + * + * @param {Phaser.Scene} scene - The Scene to which this Graphics object belongs. + * @param {Phaser.Types.GameObjects.Graphics.Options} [options] - Options that set the position and default style of this Graphics object. + */ +var Graphics = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.Lighting, + Components.Mask, + Components.RenderNodes, + Components.Transform, + Components.Visible, + Components.ScrollFactor, + Render + ], + + initialize: + + function Graphics (scene, options) + { + var x = GetValue(options, 'x', 0); + var y = GetValue(options, 'y', 0); + + GameObject.call(this, scene, 'Graphics'); + + this.setPosition(x, y); + this.initRenderNodes(this._defaultRenderNodesMap); + + /** + * The horizontal display origin of the Graphics. + * + * @name Phaser.GameObjects.Graphics#displayOriginX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.displayOriginX = 0; + + /** + * The vertical display origin of the Graphics. + * + * @name Phaser.GameObjects.Graphics#displayOriginY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.displayOriginY = 0; + + /** + * The array of commands used to render the Graphics. + * + * @name Phaser.GameObjects.Graphics#commandBuffer + * @type {array} + * @default [] + * @since 3.0.0 + */ + this.commandBuffer = []; + + /** + * The default fill color for shapes rendered by this Graphics object. + * Set this value with `setDefaultStyles()`. + * + * @name Phaser.GameObjects.Graphics#defaultFillColor + * @type {number} + * @readonly + * @default -1 + * @since 3.0.0 + */ + this.defaultFillColor = -1; + + /** + * The default fill alpha for shapes rendered by this Graphics object. + * Set this value with `setDefaultStyles()`. + * + * @name Phaser.GameObjects.Graphics#defaultFillAlpha + * @type {number} + * @readonly + * @default 1 + * @since 3.0.0 + */ + this.defaultFillAlpha = 1; + + /** + * The default stroke width for shapes rendered by this Graphics object. + * Set this value with `setDefaultStyles()`. + * + * @name Phaser.GameObjects.Graphics#defaultStrokeWidth + * @type {number} + * @readonly + * @default 1 + * @since 3.0.0 + */ + this.defaultStrokeWidth = 1; + + /** + * The default stroke color for shapes rendered by this Graphics object. + * Set this value with `setDefaultStyles()`. + * + * @name Phaser.GameObjects.Graphics#defaultStrokeColor + * @type {number} + * @readonly + * @default -1 + * @since 3.0.0 + */ + this.defaultStrokeColor = -1; + + /** + * The default stroke alpha for shapes rendered by this Graphics object. + * Set this value with `setDefaultStyles()`. + * + * @name Phaser.GameObjects.Graphics#defaultStrokeAlpha + * @type {number} + * @readonly + * @default 1 + * @since 3.0.0 + */ + this.defaultStrokeAlpha = 1; + + /** + * Internal property that keeps track of the line width style setting. + * + * @name Phaser.GameObjects.Graphics#_lineWidth + * @type {number} + * @private + * @since 3.0.0 + */ + this._lineWidth = 1; + + /** + * Path detail threshold for the WebGL renderer, in pixels. + * Path segments will be combined until the path is complete + * or the segment length is above the threshold. + * + * If the value is negative, the threshold will be taken from the + * game config `render.pathDetailThreshold` property. + * + * This threshold can greatly improve performance on complex shapes. + * It is calculated at render time and does not affect the original + * path data. + * The threshold is evaluated in screen pixels, so if the object is + * scaled up, fine detail will emerge. + * + * @name Phaser.GameObjects.Graphics#pathDetailThreshold + * @type {number} + * @default -1 + * @since 4.0.0 + */ + this.pathDetailThreshold = -1; + + this.lineStyle(1, 0, 0); + this.fillStyle(0, 0); + + this.setDefaultStyles(options); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Graphics#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultGraphicsNodes; + } + }, + + /** + * Set the default style settings for this Graphics object. + * + * @method Phaser.GameObjects.Graphics#setDefaultStyles + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Graphics.Styles} options - The styles to set as defaults. + * + * @return {this} This Game Object. + */ + setDefaultStyles: function (options) + { + if (GetValue(options, 'lineStyle', null)) + { + this.defaultStrokeWidth = GetValue(options, 'lineStyle.width', 1); + this.defaultStrokeColor = GetValue(options, 'lineStyle.color', 0xffffff); + this.defaultStrokeAlpha = GetValue(options, 'lineStyle.alpha', 1); + + this.lineStyle(this.defaultStrokeWidth, this.defaultStrokeColor, this.defaultStrokeAlpha); + } + + if (GetValue(options, 'fillStyle', null)) + { + this.defaultFillColor = GetValue(options, 'fillStyle.color', 0xffffff); + this.defaultFillAlpha = GetValue(options, 'fillStyle.alpha', 1); + + this.fillStyle(this.defaultFillColor, this.defaultFillAlpha); + } + + return this; + }, + + /** + * Set the current line style. Used for all 'stroke' related functions. + * + * @method Phaser.GameObjects.Graphics#lineStyle + * @since 3.0.0 + * + * @param {number} lineWidth - The stroke width. + * @param {number} color - The stroke color. + * @param {number} [alpha=1] - The stroke alpha. + * + * @return {this} This Game Object. + */ + lineStyle: function (lineWidth, color, alpha) + { + if (alpha === undefined) { alpha = 1; } + + this.commandBuffer.push( + Commands.LINE_STYLE, + lineWidth, color, alpha + ); + + this._lineWidth = lineWidth; + + return this; + }, + + /** + * Set the current fill style. Used for all 'fill' related functions. + * + * @method Phaser.GameObjects.Graphics#fillStyle + * @since 3.0.0 + * + * @param {number} color - The fill color. + * @param {number} [alpha=1] - The fill alpha. + * + * @return {this} This Game Object. + */ + fillStyle: function (color, alpha) + { + if (alpha === undefined) { alpha = 1; } + + this.commandBuffer.push( + Commands.FILL_STYLE, + color, alpha + ); + + return this; + }, + + /** + * Sets a gradient fill style. This is a WebGL only feature. + * + * The gradient color values represent the 4 corners of an untransformed rectangle. + * The gradient is used to color all filled shapes and paths drawn after calling this method. + * If you wish to turn a gradient off, call `fillStyle` and provide a new single fill color. + * + * When filling a triangle only the first 3 color values provided are used for the 3 points of a triangle. + * + * This feature is best used only on rectangles and triangles. All other shapes will give strange results. + * + * Note that for objects such as arcs or ellipses, or anything which is made out of triangles, each triangle used + * will be filled with a gradient on its own. There is no ability to gradient fill a shape or path as a single + * entity at this time. + * + * @method Phaser.GameObjects.Graphics#fillGradientStyle + * @webglOnly + * @since 3.12.0 + * + * @param {number} topLeft - The top left fill color. + * @param {number} topRight - The top right fill color. + * @param {number} bottomLeft - The bottom left fill color. + * @param {number} bottomRight - The bottom right fill color. Not used when filling triangles. + * @param {number} [alphaTopLeft=1] - The top left alpha value. If you give only this value, it's used for all corners. + * @param {number} [alphaTopRight=1] - The top right alpha value. + * @param {number} [alphaBottomLeft=1] - The bottom left alpha value. + * @param {number} [alphaBottomRight=1] - The bottom right alpha value. + * + * @return {this} This Game Object. + */ + fillGradientStyle: function (topLeft, topRight, bottomLeft, bottomRight, alphaTopLeft, alphaTopRight, alphaBottomLeft, alphaBottomRight) + { + if (alphaTopLeft === undefined) { alphaTopLeft = 1; } + if (alphaTopRight === undefined) { alphaTopRight = alphaTopLeft; } + if (alphaBottomLeft === undefined) { alphaBottomLeft = alphaTopLeft; } + if (alphaBottomRight === undefined) { alphaBottomRight = alphaTopLeft; } + + this.commandBuffer.push( + Commands.GRADIENT_FILL_STYLE, + alphaTopLeft, alphaTopRight, alphaBottomLeft, alphaBottomRight, + topLeft, topRight, bottomLeft, bottomRight + ); + + return this; + }, + + /** + * Sets a gradient line style. This is a WebGL only feature. + * + * The gradient color values represent the 4 corners of an untransformed rectangle. + * The gradient is used to color all stroked shapes and paths drawn after calling this method. + * If you wish to turn a gradient off, call `lineStyle` and provide a new single line color. + * + * This feature is best used only on single lines. All other shapes will give strange results. + * + * Note that for objects such as arcs or ellipses, or anything which is made out of triangles, each triangle used + * will be filled with a gradient on its own. There is no ability to gradient stroke a shape or path as a single + * entity at this time. + * + * @method Phaser.GameObjects.Graphics#lineGradientStyle + * @webglOnly + * @since 3.12.0 + * + * @param {number} lineWidth - The stroke width. + * @param {number} topLeft - The tint being applied to the top-left of the Game Object. + * @param {number} topRight - The tint being applied to the top-right of the Game Object. + * @param {number} bottomLeft - The tint being applied to the bottom-left of the Game Object. + * @param {number} bottomRight - The tint being applied to the bottom-right of the Game Object. + * @param {number} [alpha=1] - The fill alpha. + * + * @return {this} This Game Object. + */ + lineGradientStyle: function (lineWidth, topLeft, topRight, bottomLeft, bottomRight, alpha) + { + if (alpha === undefined) { alpha = 1; } + + this.commandBuffer.push( + Commands.GRADIENT_LINE_STYLE, + lineWidth, alpha, topLeft, topRight, bottomLeft, bottomRight + ); + + return this; + }, + + /** + * Start a new shape path. + * + * @method Phaser.GameObjects.Graphics#beginPath + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + beginPath: function () + { + this.commandBuffer.push( + Commands.BEGIN_PATH + ); + + return this; + }, + + /** + * Close the current path. + * + * @method Phaser.GameObjects.Graphics#closePath + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + closePath: function () + { + this.commandBuffer.push( + Commands.CLOSE_PATH + ); + + return this; + }, + + /** + * Fill the current path. + * + * @method Phaser.GameObjects.Graphics#fillPath + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + fillPath: function () + { + this.commandBuffer.push( + Commands.FILL_PATH + ); + + return this; + }, + + /** + * Fill the current path. + * + * This is an alias for `Graphics.fillPath` and does the same thing. + * It was added to match the CanvasRenderingContext 2D API. + * + * @method Phaser.GameObjects.Graphics#fill + * @since 3.16.0 + * + * @return {this} This Game Object. + */ + fill: function () + { + this.commandBuffer.push( + Commands.FILL_PATH + ); + + return this; + }, + + /** + * Stroke the current path. + * + * @method Phaser.GameObjects.Graphics#strokePath + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + strokePath: function () + { + this.commandBuffer.push( + Commands.STROKE_PATH + ); + + return this; + }, + + /** + * Stroke the current path. + * + * This is an alias for `Graphics.strokePath` and does the same thing. + * It was added to match the CanvasRenderingContext 2D API. + * + * @method Phaser.GameObjects.Graphics#stroke + * @since 3.16.0 + * + * @return {this} This Game Object. + */ + stroke: function () + { + this.commandBuffer.push( + Commands.STROKE_PATH + ); + + return this; + }, + + /** + * Fill the given circle. + * + * @method Phaser.GameObjects.Graphics#fillCircleShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The circle to fill. + * + * @return {this} This Game Object. + */ + fillCircleShape: function (circle) + { + return this.fillCircle(circle.x, circle.y, circle.radius); + }, + + /** + * Stroke the given circle. + * + * @method Phaser.GameObjects.Graphics#strokeCircleShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The circle to stroke. + * + * @return {this} This Game Object. + */ + strokeCircleShape: function (circle) + { + return this.strokeCircle(circle.x, circle.y, circle.radius); + }, + + /** + * Fill a circle with the given position and radius. + * + * @method Phaser.GameObjects.Graphics#fillCircle + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the center of the circle. + * @param {number} y - The y coordinate of the center of the circle. + * @param {number} radius - The radius of the circle. + * + * @return {this} This Game Object. + */ + fillCircle: function (x, y, radius) + { + this.beginPath(); + this.arc(x, y, radius, 0, MATH_CONST.TAU); + this.fillPath(); + + return this; + }, + + /** + * Stroke a circle with the given position and radius. + * + * @method Phaser.GameObjects.Graphics#strokeCircle + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the center of the circle. + * @param {number} y - The y coordinate of the center of the circle. + * @param {number} radius - The radius of the circle. + * + * @return {this} This Game Object. + */ + strokeCircle: function (x, y, radius) + { + this.beginPath(); + this.arc(x, y, radius, 0, MATH_CONST.TAU); + this.strokePath(); + + return this; + }, + + /** + * Fill the given rectangle. + * + * @method Phaser.GameObjects.Graphics#fillRectShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The rectangle to fill. + * + * @return {this} This Game Object. + */ + fillRectShape: function (rect) + { + return this.fillRect(rect.x, rect.y, rect.width, rect.height); + }, + + /** + * Stroke the given rectangle. + * + * @method Phaser.GameObjects.Graphics#strokeRectShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The rectangle to stroke. + * + * @return {this} This Game Object. + */ + strokeRectShape: function (rect) + { + return this.strokeRect(rect.x, rect.y, rect.width, rect.height); + }, + + /** + * Fill a rectangle with the given position and size. + * + * @method Phaser.GameObjects.Graphics#fillRect + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the top-left of the rectangle. + * @param {number} y - The y coordinate of the top-left of the rectangle. + * @param {number} width - The width of the rectangle. + * @param {number} height - The height of the rectangle. + * + * @return {this} This Game Object. + */ + fillRect: function (x, y, width, height) + { + this.commandBuffer.push( + Commands.FILL_RECT, + x, y, width, height + ); + + return this; + }, + + /** + * Stroke a rectangle with the given position and size. + * + * @method Phaser.GameObjects.Graphics#strokeRect + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the top-left of the rectangle. + * @param {number} y - The y coordinate of the top-left of the rectangle. + * @param {number} width - The width of the rectangle. + * @param {number} height - The height of the rectangle. + * + * @return {this} This Game Object. + */ + strokeRect: function (x, y, width, height) + { + var lineWidthHalf = this._lineWidth / 2; + var minx = x - lineWidthHalf; + var maxx = x + lineWidthHalf; + + this.beginPath(); + this.moveTo(x, y); + this.lineTo(x, y + height); + this.strokePath(); + + this.beginPath(); + this.moveTo(x + width, y); + this.lineTo(x + width, y + height); + this.strokePath(); + + this.beginPath(); + this.moveTo(minx, y); + this.lineTo(maxx + width, y); + this.strokePath(); + + this.beginPath(); + this.moveTo(minx, y + height); + this.lineTo(maxx + width, y + height); + this.strokePath(); + + return this; + }, + + /** + * Fill a rounded rectangle with the given position, size and radius. + * + * @method Phaser.GameObjects.Graphics#fillRoundedRect + * @since 3.11.0 + * + * @param {number} x - The x coordinate of the top-left of the rectangle. + * @param {number} y - The y coordinate of the top-left of the rectangle. + * @param {number} width - The width of the rectangle. + * @param {number} height - The height of the rectangle. + * @param {(Phaser.Types.GameObjects.Graphics.RoundedRectRadius|number)} [radius=20] - The corner radius; It can also be an object to specify different radius for corners. + * + * @return {this} This Game Object. + */ + fillRoundedRect: function (x, y, width, height, radius) + { + if (radius === undefined) { radius = 20; } + + var tl = radius; + var tr = radius; + var bl = radius; + var br = radius; + + if (typeof radius !== 'number') + { + tl = GetFastValue(radius, 'tl', 20); + tr = GetFastValue(radius, 'tr', 20); + bl = GetFastValue(radius, 'bl', 20); + br = GetFastValue(radius, 'br', 20); + } + + var convexTL = (tl >= 0); + var convexTR = (tr >= 0); + var convexBL = (bl >= 0); + var convexBR = (br >= 0); + + tl = Math.abs(tl); + tr = Math.abs(tr); + bl = Math.abs(bl); + br = Math.abs(br); + + this.beginPath(); + this.moveTo(x + tl, y); + this.lineTo(x + width - tr, y); + + if (convexTR) + { + this.arc(x + width - tr, y + tr, tr, -MATH_CONST.PI_OVER_2, 0); + } + else + { + this.arc(x + width, y, tr, Math.PI, MATH_CONST.PI_OVER_2, true); + } + + this.lineTo(x + width, y + height - br); + + if (convexBR) + { + this.arc(x + width - br, y + height - br, br, 0, MATH_CONST.PI_OVER_2); + } + else + { + this.arc(x + width, y + height, br, -MATH_CONST.PI_OVER_2, Math.PI, true); + } + + this.lineTo(x + bl, y + height); + + if (convexBL) + { + this.arc(x + bl, y + height - bl, bl, MATH_CONST.PI_OVER_2, Math.PI); + } + else + { + this.arc(x, y + height, bl, 0, -MATH_CONST.PI_OVER_2, true); + } + + this.lineTo(x, y + tl); + + if (convexTL) + { + this.arc(x + tl, y + tl, tl, -Math.PI, -MATH_CONST.PI_OVER_2); + } + else + { + this.arc(x, y, tl, MATH_CONST.PI_OVER_2, 0, true); + } + + this.fillPath(); + + return this; + }, + + /** + * Stroke a rounded rectangle with the given position, size and radius. + * + * @method Phaser.GameObjects.Graphics#strokeRoundedRect + * @since 3.11.0 + * + * @param {number} x - The x coordinate of the top-left of the rectangle. + * @param {number} y - The y coordinate of the top-left of the rectangle. + * @param {number} width - The width of the rectangle. + * @param {number} height - The height of the rectangle. + * @param {(Phaser.Types.GameObjects.Graphics.RoundedRectRadius|number)} [radius=20] - The corner radius; It can also be an object to specify different radii for corners. + * + * @return {this} This Game Object. + */ + strokeRoundedRect: function (x, y, width, height, radius) + { + if (radius === undefined) { radius = 20; } + + var tl = radius; + var tr = radius; + var bl = radius; + var br = radius; + + var maxRadius = Math.min(width, height) / 2; + + if (typeof radius !== 'number') + { + tl = GetFastValue(radius, 'tl', 20); + tr = GetFastValue(radius, 'tr', 20); + bl = GetFastValue(radius, 'bl', 20); + br = GetFastValue(radius, 'br', 20); + } + + var convexTL = (tl >= 0); + var convexTR = (tr >= 0); + var convexBL = (bl >= 0); + var convexBR = (br >= 0); + + tl = Math.min(Math.abs(tl), maxRadius); + tr = Math.min(Math.abs(tr), maxRadius); + bl = Math.min(Math.abs(bl), maxRadius); + br = Math.min(Math.abs(br), maxRadius); + + this.beginPath(); + this.moveTo(x + tl, y); + this.lineTo(x + width - tr, y); + this.moveTo(x + width - tr, y); + + if (convexTR) + { + this.arc(x + width - tr, y + tr, tr, -MATH_CONST.PI_OVER_2, 0); + } + else + { + this.arc(x + width, y, tr, Math.PI, MATH_CONST.PI_OVER_2, true); + } + + this.lineTo(x + width, y + height - br); + this.moveTo(x + width, y + height - br); + + if (convexBR) + { + this.arc(x + width - br, y + height - br, br, 0, MATH_CONST.PI_OVER_2); + } + else + { + this.arc(x + width, y + height, br, -MATH_CONST.PI_OVER_2, Math.PI, true); + } + + this.lineTo(x + bl, y + height); + this.moveTo(x + bl, y + height); + + if (convexBL) + { + this.arc(x + bl, y + height - bl, bl, MATH_CONST.PI_OVER_2, Math.PI); + } + else + { + this.arc(x, y + height, bl, 0, -MATH_CONST.PI_OVER_2, true); + } + + this.lineTo(x, y + tl); + this.moveTo(x, y + tl); + + if (convexTL) + { + this.arc(x + tl, y + tl, tl, -Math.PI, -MATH_CONST.PI_OVER_2); + } + else + { + this.arc(x, y, tl, MATH_CONST.PI_OVER_2, 0, true); + } + + this.strokePath(); + + return this; + }, + + /** + * Fill the given point. + * + * Draws a square at the given position, 1 pixel in size by default. + * + * @method Phaser.GameObjects.Graphics#fillPointShape + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2} point - The point to fill. + * @param {number} [size=1] - The size of the square to draw. + * + * @return {this} This Game Object. + */ + fillPointShape: function (point, size) + { + return this.fillPoint(point.x, point.y, size); + }, + + /** + * Fill a point at the given position. + * + * Draws a square at the given position, 1 pixel in size by default. + * + * @method Phaser.GameObjects.Graphics#fillPoint + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the point. + * @param {number} y - The y coordinate of the point. + * @param {number} [size=1] - The size of the square to draw. + * + * @return {this} This Game Object. + */ + fillPoint: function (x, y, size) + { + if (!size || size < 1) + { + size = 1; + } + else + { + x -= (size / 2); + y -= (size / 2); + } + + this.commandBuffer.push( + Commands.FILL_RECT, + x, y, size, size + ); + + return this; + }, + + /** + * Fill the given triangle. + * + * @method Phaser.GameObjects.Graphics#fillTriangleShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The triangle to fill. + * + * @return {this} This Game Object. + */ + fillTriangleShape: function (triangle) + { + return this.fillTriangle(triangle.x1, triangle.y1, triangle.x2, triangle.y2, triangle.x3, triangle.y3); + }, + + /** + * Stroke the given triangle. + * + * @method Phaser.GameObjects.Graphics#strokeTriangleShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The triangle to stroke. + * + * @return {this} This Game Object. + */ + strokeTriangleShape: function (triangle) + { + return this.strokeTriangle(triangle.x1, triangle.y1, triangle.x2, triangle.y2, triangle.x3, triangle.y3); + }, + + /** + * Fill a triangle with the given points. + * + * @method Phaser.GameObjects.Graphics#fillTriangle + * @since 3.0.0 + * + * @param {number} x0 - The x coordinate of the first point. + * @param {number} y0 - The y coordinate of the first point. + * @param {number} x1 - The x coordinate of the second point. + * @param {number} y1 - The y coordinate of the second point. + * @param {number} x2 - The x coordinate of the third point. + * @param {number} y2 - The y coordinate of the third point. + * + * @return {this} This Game Object. + */ + fillTriangle: function (x0, y0, x1, y1, x2, y2) + { + this.commandBuffer.push( + Commands.FILL_TRIANGLE, + x0, y0, x1, y1, x2, y2 + ); + + return this; + }, + + /** + * Stroke a triangle with the given points. + * + * @method Phaser.GameObjects.Graphics#strokeTriangle + * @since 3.0.0 + * + * @param {number} x0 - The x coordinate of the first point. + * @param {number} y0 - The y coordinate of the first point. + * @param {number} x1 - The x coordinate of the second point. + * @param {number} y1 - The y coordinate of the second point. + * @param {number} x2 - The x coordinate of the third point. + * @param {number} y2 - The y coordinate of the third point. + * + * @return {this} This Game Object. + */ + strokeTriangle: function (x0, y0, x1, y1, x2, y2) + { + this.commandBuffer.push( + Commands.STROKE_TRIANGLE, + x0, y0, x1, y1, x2, y2 + ); + + return this; + }, + + /** + * Draw the given line. + * + * @method Phaser.GameObjects.Graphics#strokeLineShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to stroke. + * + * @return {this} This Game Object. + */ + strokeLineShape: function (line) + { + return this.lineBetween(line.x1, line.y1, line.x2, line.y2); + }, + + /** + * Draw a line between the given points. + * + * @method Phaser.GameObjects.Graphics#lineBetween + * @since 3.0.0 + * + * @param {number} x1 - The x coordinate of the start point of the line. + * @param {number} y1 - The y coordinate of the start point of the line. + * @param {number} x2 - The x coordinate of the end point of the line. + * @param {number} y2 - The y coordinate of the end point of the line. + * + * @return {this} This Game Object. + */ + lineBetween: function (x1, y1, x2, y2) + { + this.beginPath(); + this.moveTo(x1, y1); + this.lineTo(x2, y2); + this.strokePath(); + + return this; + }, + + /** + * Draw a line from the current drawing position to the given position. + * + * Moves the current drawing position to the given position. + * + * @method Phaser.GameObjects.Graphics#lineTo + * @since 3.0.0 + * + * @param {number} x - The x coordinate to draw the line to. + * @param {number} y - The y coordinate to draw the line to. + * + * @return {this} This Game Object. + */ + lineTo: function (x, y) + { + this.commandBuffer.push( + Commands.LINE_TO, + x, y + ); + + return this; + }, + + /** + * Move the current drawing position to the given position. + * + * @method Phaser.GameObjects.Graphics#moveTo + * @since 3.0.0 + * + * @param {number} x - The x coordinate to move to. + * @param {number} y - The y coordinate to move to. + * + * @return {this} This Game Object. + */ + moveTo: function (x, y) + { + this.commandBuffer.push( + Commands.MOVE_TO, + x, y + ); + + return this; + }, + + /** + * Stroke the shape represented by the given array of points. + * + * Pass `closeShape` to automatically close the shape by joining the last to the first point. + * + * Pass `closePath` to automatically close the path before it is stroked. + * + * @method Phaser.GameObjects.Graphics#strokePoints + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2[]} points - The points to stroke. + * @param {boolean} [closeShape=false] - When `true`, the shape is closed by joining the last point to the first point. + * @param {boolean} [closePath=false] - When `true`, the path is closed before being stroked. + * @param {number} [endIndex] - The index of `points` to stop drawing at. Defaults to `points.length`. + * + * @return {this} This Game Object. + */ + strokePoints: function (points, closeShape, closePath, endIndex) + { + if (closeShape === undefined) { closeShape = false; } + if (closePath === undefined) { closePath = false; } + if (endIndex === undefined) { endIndex = points.length; } + + this.beginPath(); + + this.moveTo(points[0].x, points[0].y); + + for (var i = 1; i < endIndex; i++) + { + this.lineTo(points[i].x, points[i].y); + } + + if (closeShape) + { + this.lineTo(points[0].x, points[0].y); + } + + if (closePath) + { + this.closePath(); + } + + this.strokePath(); + + return this; + }, + + /** + * Fill the shape represented by the given array of points. + * + * Pass `closeShape` to automatically close the shape by joining the last to the first point. + * + * Pass `closePath` to automatically close the path before it is filled. + * + * @method Phaser.GameObjects.Graphics#fillPoints + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2[]} points - The points to fill. + * @param {boolean} [closeShape=false] - When `true`, the shape is closed by joining the last point to the first point. + * @param {boolean} [closePath=false] - When `true`, the path is closed before being stroked. + * @param {number} [endIndex] - The index of `points` to stop at. Defaults to `points.length`. + * + * @return {this} This Game Object. + */ + fillPoints: function (points, closeShape, closePath, endIndex) + { + if (closeShape === undefined) { closeShape = false; } + if (closePath === undefined) { closePath = false; } + if (endIndex === undefined) { endIndex = points.length; } + + this.beginPath(); + + this.moveTo(points[0].x, points[0].y); + + for (var i = 1; i < endIndex; i++) + { + this.lineTo(points[i].x, points[i].y); + } + + if (closeShape) + { + this.lineTo(points[0].x, points[0].y); + } + + if (closePath) + { + this.closePath(); + } + + this.fillPath(); + + return this; + }, + + /** + * Stroke the given ellipse. + * + * @method Phaser.GameObjects.Graphics#strokeEllipseShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The ellipse to stroke. + * @param {number} [smoothness=32] - The number of points to draw the ellipse with. + * + * @return {this} This Game Object. + */ + strokeEllipseShape: function (ellipse, smoothness) + { + if (smoothness === undefined) { smoothness = 32; } + + var points = ellipse.getPoints(smoothness); + + return this.strokePoints(points, true); + }, + + /** + * Stroke an ellipse with the given position and size. + * + * @method Phaser.GameObjects.Graphics#strokeEllipse + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the center of the ellipse. + * @param {number} y - The y coordinate of the center of the ellipse. + * @param {number} width - The width of the ellipse. + * @param {number} height - The height of the ellipse. + * @param {number} [smoothness=32] - The number of points to draw the ellipse with. + * + * @return {this} This Game Object. + */ + strokeEllipse: function (x, y, width, height, smoothness) + { + if (smoothness === undefined) { smoothness = 32; } + + var ellipse = new Ellipse(x, y, width, height); + + var points = ellipse.getPoints(smoothness); + + return this.strokePoints(points, true); + }, + + /** + * Fill the given ellipse. + * + * @method Phaser.GameObjects.Graphics#fillEllipseShape + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The ellipse to fill. + * @param {number} [smoothness=32] - The number of points to draw the ellipse with. + * + * @return {this} This Game Object. + */ + fillEllipseShape: function (ellipse, smoothness) + { + if (smoothness === undefined) { smoothness = 32; } + + var points = ellipse.getPoints(smoothness); + + return this.fillPoints(points, true); + }, + + /** + * Fill an ellipse with the given position and size. + * + * @method Phaser.GameObjects.Graphics#fillEllipse + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the center of the ellipse. + * @param {number} y - The y coordinate of the center of the ellipse. + * @param {number} width - The width of the ellipse. + * @param {number} height - The height of the ellipse. + * @param {number} [smoothness=32] - The number of points to draw the ellipse with. + * + * @return {this} This Game Object. + */ + fillEllipse: function (x, y, width, height, smoothness) + { + if (smoothness === undefined) { smoothness = 32; } + + var ellipse = new Ellipse(x, y, width, height); + + var points = ellipse.getPoints(smoothness); + + return this.fillPoints(points, true); + }, + + /** + * Draw an arc. + * + * This method can be used to create circles, or parts of circles. + * + * Make sure you call `beginPath` before starting the arc unless you wish for the arc to automatically + * close when filled or stroked. + * + * Use the optional `overshoot` argument increase the number of iterations that take place when + * the arc is rendered in WebGL. This is useful if you're drawing an arc with an especially thick line, + * as it will allow the arc to fully join-up. Try small values at first, i.e. 0.01. + * + * Call {@link Phaser.GameObjects.Graphics#fillPath} or {@link Phaser.GameObjects.Graphics#strokePath} after calling + * this method to draw the arc. + * + * @method Phaser.GameObjects.Graphics#arc + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the center of the circle. + * @param {number} y - The y coordinate of the center of the circle. + * @param {number} radius - The radius of the circle. + * @param {number} startAngle - The starting angle, in radians. + * @param {number} endAngle - The ending angle, in radians. + * @param {boolean} [anticlockwise=false] - Whether the drawing should be anticlockwise or clockwise. + * @param {number} [overshoot=0] - This value allows you to increase the segment iterations in WebGL rendering. Useful if the arc has a thick stroke and needs to overshoot to join-up cleanly. Use small numbers such as 0.01 to start with and increase as needed. + * + * @return {this} This Game Object. + */ + arc: function (x, y, radius, startAngle, endAngle, anticlockwise, overshoot) + { + if (anticlockwise === undefined) { anticlockwise = false; } + if (overshoot === undefined) { overshoot = 0; } + + this.commandBuffer.push( + Commands.ARC, + x, y, radius, startAngle, endAngle, anticlockwise, overshoot + ); + + return this; + }, + + /** + * Creates a pie-chart slice shape centered at `x`, `y` with the given radius. + * You must define the start and end angle of the slice. + * + * Setting the `anticlockwise` argument to `true` creates a shape similar to Pacman. + * Setting it to `false` creates a shape like a slice of pie. + * + * This method will begin a new path and close the path at the end of it. + * To display the actual slice you need to call either `strokePath` or `fillPath` after it. + * + * @method Phaser.GameObjects.Graphics#slice + * @since 3.4.0 + * + * @param {number} x - The horizontal center of the slice. + * @param {number} y - The vertical center of the slice. + * @param {number} radius - The radius of the slice. + * @param {number} startAngle - The start angle of the slice, given in radians. + * @param {number} endAngle - The end angle of the slice, given in radians. + * @param {boolean} [anticlockwise=false] - Whether the drawing should be anticlockwise or clockwise. + * @param {number} [overshoot=0] - This value allows you to overshoot the endAngle by this amount. Useful if the arc has a thick stroke and needs to overshoot to join-up cleanly. + * + * @return {this} This Game Object. + */ + slice: function (x, y, radius, startAngle, endAngle, anticlockwise, overshoot) + { + if (anticlockwise === undefined) { anticlockwise = false; } + if (overshoot === undefined) { overshoot = 0; } + + this.commandBuffer.push(Commands.BEGIN_PATH); + + this.commandBuffer.push(Commands.MOVE_TO, x, y); + + this.commandBuffer.push(Commands.ARC, x, y, radius, startAngle, endAngle, anticlockwise, overshoot); + + this.commandBuffer.push(Commands.CLOSE_PATH); + + return this; + }, + + /** + * Saves the state of the Graphics by pushing the current state onto a stack. + * + * The most recently saved state can then be restored with {@link Phaser.GameObjects.Graphics#restore}. + * + * @method Phaser.GameObjects.Graphics#save + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + save: function () + { + this.commandBuffer.push( + Commands.SAVE + ); + + return this; + }, + + /** + * Restores the most recently saved state of the Graphics by popping from the state stack. + * + * Use {@link Phaser.GameObjects.Graphics#save} to save the current state, and call this afterwards to restore that state. + * + * If there is no saved state, this command does nothing. + * + * @method Phaser.GameObjects.Graphics#restore + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + restore: function () + { + this.commandBuffer.push( + Commands.RESTORE + ); + + return this; + }, + + /** + * Inserts a translation command into this Graphics objects command buffer. + * + * All objects drawn _after_ calling this method will be translated + * by the given amount. + * + * This does not change the position of the Graphics object itself, + * only of the objects drawn by it after calling this method. + * + * @method Phaser.GameObjects.Graphics#translateCanvas + * @since 3.0.0 + * + * @param {number} x - The horizontal translation to apply. + * @param {number} y - The vertical translation to apply. + * + * @return {this} This Game Object. + */ + translateCanvas: function (x, y) + { + this.commandBuffer.push( + Commands.TRANSLATE, + x, y + ); + + return this; + }, + + /** + * Inserts a scale command into this Graphics objects command buffer. + * + * All objects drawn _after_ calling this method will be scaled + * by the given amount. + * + * This does not change the scale of the Graphics object itself, + * only of the objects drawn by it after calling this method. + * + * @method Phaser.GameObjects.Graphics#scaleCanvas + * @since 3.0.0 + * + * @param {number} x - The horizontal scale to apply. + * @param {number} y - The vertical scale to apply. + * + * @return {this} This Game Object. + */ + scaleCanvas: function (x, y) + { + this.commandBuffer.push( + Commands.SCALE, + x, y + ); + + return this; + }, + + /** + * Inserts a rotation command into this Graphics objects command buffer. + * + * All objects drawn _after_ calling this method will be rotated + * by the given amount. + * + * This does not change the rotation of the Graphics object itself, + * only of the objects drawn by it after calling this method. + * + * @method Phaser.GameObjects.Graphics#rotateCanvas + * @since 3.0.0 + * + * @param {number} radians - The rotation angle, in radians. + * + * @return {this} This Game Object. + */ + rotateCanvas: function (radians) + { + this.commandBuffer.push( + Commands.ROTATE, + radians + ); + + return this; + }, + + /** + * Clear the command buffer and reset the fill style and line style to their defaults. + * + * @method Phaser.GameObjects.Graphics#clear + * @since 3.0.0 + * + * @return {this} This Game Object. + */ + clear: function () + { + this.commandBuffer.length = 0; + + if (this.defaultFillColor > -1) + { + this.fillStyle(this.defaultFillColor, this.defaultFillAlpha); + } + + if (this.defaultStrokeColor > -1) + { + this.lineStyle(this.defaultStrokeWidth, this.defaultStrokeColor, this.defaultStrokeAlpha); + } + + return this; + }, + + /** + * Generate a texture from this Graphics object. + * + * If `key` is a string it'll generate a new texture using it and add it into the + * Texture Manager (assuming no key conflict happens). + * + * If `key` is a Canvas it will draw the texture to that canvas context. Note that it will NOT + * automatically upload it to the GPU in WebGL mode. + * + * Please understand that the texture is created via the Canvas API of the browser, therefore some + * Graphics features, such as `fillGradientStyle`, will not appear on the resulting texture, + * as they're unsupported by the Canvas API. + * + * @method Phaser.GameObjects.Graphics#generateTexture + * @since 3.0.0 + * + * @param {(string|HTMLCanvasElement)} key - The key to store the texture with in the Texture Manager, or a Canvas to draw to. + * @param {number} [width] - The width of the graphics to generate. + * @param {number} [height] - The height of the graphics to generate. + * + * @return {this} This Game Object. + */ + generateTexture: function (key, width, height) + { + var sys = this.scene.sys; + var renderer = sys.game.renderer; + + if (width === undefined) { width = sys.scale.width; } + if (height === undefined) { height = sys.scale.height; } + + Graphics.TargetCamera.setScene(this.scene); + Graphics.TargetCamera.setViewport(0, 0, width, height); + Graphics.TargetCamera.scrollX = this.x; + Graphics.TargetCamera.scrollY = this.y; + + var texture; + var ctx; + var willRead = { willReadFrequently: true }; + + if (typeof key === 'string') + { + if (sys.textures.exists(key)) + { + // Key is a string, it DOES exist in the Texture Manager AND is a canvas, so draw to it + + texture = sys.textures.get(key); + + var src = texture.getSourceImage(); + + if (src instanceof HTMLCanvasElement) + { + ctx = src.getContext('2d', willRead); + } + } + else + { + // Key is a string and doesn't exist in the Texture Manager, so generate and save it + + texture = sys.textures.createCanvas(key, width, height); + + ctx = texture.getSourceImage().getContext('2d', willRead); + } + } + else if (key instanceof HTMLCanvasElement) + { + // Key is a Canvas, so draw to it + + ctx = key.getContext('2d', willRead); + } + + if (ctx) + { + // var GraphicsCanvasRenderer = function (renderer, src, camera, parentMatrix, renderTargetCtx, allowClip) + this.renderCanvas(renderer, this, Graphics.TargetCamera, null, ctx, false); + + if (texture) + { + texture.refresh(); + } + } + + return this; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.Graphics#preDestroy + * @protected + * @since 3.9.0 + */ + preDestroy: function () + { + this.commandBuffer = []; + } + +}); + +/** + * A Camera used specifically by the Graphics system for rendering to textures. + * + * @name Phaser.GameObjects.Graphics.TargetCamera + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 3.1.0 + */ +Graphics.TargetCamera = new BaseCamera(); + +module.exports = Graphics; + + +/***/ }), + +/***/ 32768: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Commands = __webpack_require__(85592); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Graphics#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Graphics} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + * @param {CanvasRenderingContext2D} [renderTargetCtx] - The target rendering context. + * @param {boolean} allowClip - If `true` then path operations will be used instead of fill operations. + */ +var GraphicsCanvasRenderer = function (renderer, src, camera, parentMatrix, renderTargetCtx, allowClip) +{ + var commandBuffer = src.commandBuffer; + var commandBufferLength = commandBuffer.length; + + var ctx = renderTargetCtx || renderer.currentContext; + + if (commandBufferLength === 0 || !SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + return; + } + + camera.addToRenderList(src); + + var lineAlpha = 1; + var fillAlpha = 1; + var lineColor = 0; + var fillColor = 0; + var lineWidth = 1; + var red = 0; + var green = 0; + var blue = 0; + + // Reset any currently active paths + ctx.beginPath(); + + for (var index = 0; index < commandBufferLength; ++index) + { + var commandID = commandBuffer[index]; + + switch (commandID) + { + case Commands.ARC: + ctx.arc( + commandBuffer[index + 1], + commandBuffer[index + 2], + commandBuffer[index + 3], + commandBuffer[index + 4], + commandBuffer[index + 5], + commandBuffer[index + 6] + ); + + // +7 because overshoot is the 7th value, not used in Canvas + index += 7; + break; + + case Commands.LINE_STYLE: + lineWidth = commandBuffer[index + 1]; + lineColor = commandBuffer[index + 2]; + lineAlpha = commandBuffer[index + 3]; + red = ((lineColor & 0xFF0000) >>> 16); + green = ((lineColor & 0xFF00) >>> 8); + blue = (lineColor & 0xFF); + ctx.strokeStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + lineAlpha + ')'; + ctx.lineWidth = lineWidth; + index += 3; + break; + + case Commands.FILL_STYLE: + fillColor = commandBuffer[index + 1]; + fillAlpha = commandBuffer[index + 2]; + red = ((fillColor & 0xFF0000) >>> 16); + green = ((fillColor & 0xFF00) >>> 8); + blue = (fillColor & 0xFF); + ctx.fillStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + fillAlpha + ')'; + index += 2; + break; + + case Commands.BEGIN_PATH: + ctx.beginPath(); + break; + + case Commands.CLOSE_PATH: + ctx.closePath(); + break; + + case Commands.FILL_PATH: + if (!allowClip) + { + ctx.fill(); + } + break; + + case Commands.STROKE_PATH: + if (!allowClip) + { + ctx.stroke(); + } + break; + + case Commands.FILL_RECT: + if (!allowClip) + { + ctx.fillRect( + commandBuffer[index + 1], + commandBuffer[index + 2], + commandBuffer[index + 3], + commandBuffer[index + 4] + ); + } + else + { + ctx.rect( + commandBuffer[index + 1], + commandBuffer[index + 2], + commandBuffer[index + 3], + commandBuffer[index + 4] + ); + } + index += 4; + break; + + case Commands.FILL_TRIANGLE: + ctx.beginPath(); + ctx.moveTo(commandBuffer[index + 1], commandBuffer[index + 2]); + ctx.lineTo(commandBuffer[index + 3], commandBuffer[index + 4]); + ctx.lineTo(commandBuffer[index + 5], commandBuffer[index + 6]); + ctx.closePath(); + if (!allowClip) + { + ctx.fill(); + } + index += 6; + break; + + case Commands.STROKE_TRIANGLE: + ctx.beginPath(); + ctx.moveTo(commandBuffer[index + 1], commandBuffer[index + 2]); + ctx.lineTo(commandBuffer[index + 3], commandBuffer[index + 4]); + ctx.lineTo(commandBuffer[index + 5], commandBuffer[index + 6]); + ctx.closePath(); + if (!allowClip) + { + ctx.stroke(); + } + index += 6; + break; + + case Commands.LINE_TO: + ctx.lineTo( + commandBuffer[index + 1], + commandBuffer[index + 2] + ); + index += 2; + break; + + case Commands.MOVE_TO: + ctx.moveTo( + commandBuffer[index + 1], + commandBuffer[index + 2] + ); + index += 2; + break; + + case Commands.LINE_FX_TO: + ctx.lineTo( + commandBuffer[index + 1], + commandBuffer[index + 2] + ); + index += 5; + break; + + case Commands.MOVE_FX_TO: + ctx.moveTo( + commandBuffer[index + 1], + commandBuffer[index + 2] + ); + index += 5; + break; + + case Commands.SAVE: + ctx.save(); + break; + + case Commands.RESTORE: + ctx.restore(); + break; + + case Commands.TRANSLATE: + ctx.translate( + commandBuffer[index + 1], + commandBuffer[index + 2] + ); + index += 2; + break; + + case Commands.SCALE: + ctx.scale( + commandBuffer[index + 1], + commandBuffer[index + 2] + ); + index += 2; + break; + + case Commands.ROTATE: + ctx.rotate( + commandBuffer[index + 1] + ); + index += 1; + break; + + case Commands.GRADIENT_FILL_STYLE: + index += 5; + break; + + case Commands.GRADIENT_LINE_STYLE: + index += 6; + break; + } + } + + // Restore the context saved in SetTransform + ctx.restore(); +}; + +module.exports = GraphicsCanvasRenderer; + + +/***/ }), + +/***/ 87079: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectCreator = __webpack_require__(44603); +var Graphics = __webpack_require__(43831); + +/** + * Creates a new Graphics Game Object and returns it. + * + * Note: This method will only be available if the Graphics Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#graphics + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Graphics.Options} [config] - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Graphics} The Game Object that was created. + */ +GameObjectCreator.register('graphics', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + var graphics = new Graphics(this.scene, config); + + if (config.add) + { + this.scene.sys.displayList.add(graphics); + } + + return graphics; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 1201: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Graphics = __webpack_require__(43831); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Graphics Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Graphics Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#graphics + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Graphics.Options} [config] - The Graphics configuration. + * + * @return {Phaser.GameObjects.Graphics} The Game Object that was created. + */ +GameObjectFactory.register('graphics', function (config) +{ + return this.displayList.add(new Graphics(this.scene, config)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 84503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(77545); + + // Needed for Graphics.generateTexture + renderCanvas = __webpack_require__(32768); +} + +if (true) +{ + renderCanvas = __webpack_require__(32768); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 77545: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Commands = __webpack_require__(85592); +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); +var TransformMatrix = __webpack_require__(61340); + +var Point = function (x, y, width) +{ + this.x = x; + this.y = y; + this.width = width; +}; + +var Path = function (x, y, width) +{ + this.points = []; + this.points[0] = new Point(x, y, width); + + this.addPoint = function (x, y, width) + { + var point = this.points[this.points.length - 1]; + + if (point.x === x && point.y === y) + { + return; + } + + this.points.push(new Point(x, y, width)); + }; +}; + +var matrixStack = []; +var tempMatrix = new TransformMatrix(); +var renderMatrix = new TransformMatrix(); +var fillTint = { TL: 0, TR: 0, BL: 0, BR: 0 }; +var strokeTint = { TL: 0, TR: 0, BL: 0, BR: 0 }; +var trianglePath = [ + { x: 0, y: 0, width: 0 }, + { x: 0, y: 0, width: 0 }, + { x: 0, y: 0, width: 0 }, + { x: 0, y: 0, width: 0 } +]; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Graphics#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Graphics} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var GraphicsWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + if (src.commandBuffer.length === 0) + { + return; + } + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + var submitterNode = customRenderNodes.Submitter || defaultRenderNodes.Submitter; + var lighting = src.lighting; + + var currentContext = drawingContext; + + var camera = currentContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var currentMatrix = tempMatrix.loadIdentity(); + + var commands = src.commandBuffer; + var alpha = src.alpha; + + var pathDetailThreshold = Math.max( + src.pathDetailThreshold, + renderer.config.pathDetailThreshold, + 0 + ); + + var lineWidth = 1; + + var tx = 0; + var ty = 0; + var ta = 0; + var iterStep = 0.01; + var PI2 = Math.PI * 2; + + var cmd; + + var path = []; + var pathIndex = 0; + var pathOpen = true; + var lastPath = null; + + var getTint = Utils.getTintAppendFloatAlpha; + + for (var cmdIndex = 0; cmdIndex < commands.length; cmdIndex++) + { + cmd = commands[cmdIndex]; + + switch (cmd) + { + case Commands.BEGIN_PATH: + { + path.length = 0; + lastPath = null; + pathOpen = true; + break; + } + + case Commands.CLOSE_PATH: + { + pathOpen = false; + + if (lastPath && lastPath.points.length) + { + lastPath.points.push(lastPath.points[0]); + } + break; + } + + case Commands.FILL_PATH: + { + calcMatrix.multiply(currentMatrix, renderMatrix); + + for (pathIndex = 0; pathIndex < path.length; pathIndex++) + { + (customRenderNodes.FillPath || defaultRenderNodes.FillPath).run( + currentContext, + renderMatrix, + submitterNode, + path[pathIndex].points, + fillTint.TL, + fillTint.TR, + fillTint.BL, + pathDetailThreshold, + lighting + ); + } + break; + } + + case Commands.STROKE_PATH: + { + calcMatrix.multiply(currentMatrix, renderMatrix); + + for (pathIndex = 0; pathIndex < path.length; pathIndex++) + { + (customRenderNodes.StrokePath || defaultRenderNodes.StrokePath).run( + currentContext, + submitterNode, + path[pathIndex].points, + lineWidth, + pathOpen, + renderMatrix, + strokeTint.TL, + strokeTint.TR, + strokeTint.BL, + strokeTint.BR, + pathDetailThreshold, + lighting + ); + } + break; + } + + case Commands.LINE_STYLE: + { + lineWidth = commands[++cmdIndex]; + var strokeColor = commands[++cmdIndex]; + var strokeAlpha = commands[++cmdIndex] * alpha; + var strokeTintColor = getTint(strokeColor, strokeAlpha); + strokeTint.TL = strokeTintColor; + strokeTint.TR = strokeTintColor; + strokeTint.BL = strokeTintColor; + strokeTint.BR = strokeTintColor; + break; + } + + case Commands.FILL_STYLE: + { + var fillColor = commands[++cmdIndex]; + var fillAlpha = commands[++cmdIndex] * alpha; + var fillTintColor = getTint(fillColor, fillAlpha); + fillTint.TL = fillTintColor; + fillTint.TR = fillTintColor; + fillTint.BL = fillTintColor; + fillTint.BR = fillTintColor; + break; + } + + case Commands.GRADIENT_FILL_STYLE: + { + var alphaTL = commands[++cmdIndex] * alpha; + var alphaTR = commands[++cmdIndex] * alpha; + var alphaBL = commands[++cmdIndex] * alpha; + var alphaBR = commands[++cmdIndex] * alpha; + + fillTint.TL = getTint(commands[++cmdIndex], alphaTL); + fillTint.TR = getTint(commands[++cmdIndex], alphaTR); + fillTint.BL = getTint(commands[++cmdIndex], alphaBL); + fillTint.BR = getTint(commands[++cmdIndex], alphaBR); + break; + } + + case Commands.GRADIENT_LINE_STYLE: + { + lineWidth = commands[++cmdIndex]; + var gradientLineAlpha = commands[++cmdIndex] * alpha; + strokeTint.TL = getTint(commands[++cmdIndex], gradientLineAlpha); + strokeTint.TR = getTint(commands[++cmdIndex], gradientLineAlpha); + strokeTint.BL = getTint(commands[++cmdIndex], gradientLineAlpha); + strokeTint.BR = getTint(commands[++cmdIndex], gradientLineAlpha); + break; + } + + case Commands.ARC: + { + var iteration = 0; + var x = commands[++cmdIndex]; + var y = commands[++cmdIndex]; + var radius = commands[++cmdIndex]; + var startAngle = commands[++cmdIndex]; + var endAngle = commands[++cmdIndex]; + var anticlockwise = commands[++cmdIndex]; + var overshoot = commands[++cmdIndex]; + + endAngle -= startAngle; + + if (anticlockwise) + { + if (endAngle < -PI2) + { + endAngle = -PI2; + } + else if (endAngle > 0) + { + endAngle = -PI2 + endAngle % PI2; + } + } + else if (endAngle > PI2) + { + endAngle = PI2; + } + else if (endAngle < 0) + { + endAngle = PI2 + endAngle % PI2; + } + + if (lastPath === null) + { + lastPath = new Path(x + Math.cos(startAngle) * radius, y + Math.sin(startAngle) * radius, lineWidth); + path.push(lastPath); + iteration += iterStep; + } + + while (iteration < 1 + overshoot) + { + ta = endAngle * iteration + startAngle; + tx = x + Math.cos(ta) * radius; + ty = y + Math.sin(ta) * radius; + + lastPath.addPoint(tx, ty, lineWidth); + + iteration += iterStep; + } + + ta = endAngle + startAngle; + tx = x + Math.cos(ta) * radius; + ty = y + Math.sin(ta) * radius; + + lastPath.addPoint(tx, ty, lineWidth); + + break; + } + + case Commands.FILL_RECT: + { + calcMatrix.multiply(currentMatrix, renderMatrix); + + (customRenderNodes.FillRect || defaultRenderNodes.FillRect).run( + currentContext, + renderMatrix, + submitterNode, + commands[++cmdIndex], + commands[++cmdIndex], + commands[++cmdIndex], + commands[++cmdIndex], + fillTint.TL, + fillTint.TR, + fillTint.BL, + fillTint.BR, + lighting + ); + + break; + } + + case Commands.FILL_TRIANGLE: + { + calcMatrix.multiply(currentMatrix, renderMatrix); + + (customRenderNodes.FillTri || defaultRenderNodes.FillTri).run( + currentContext, + renderMatrix, + submitterNode, + commands[++cmdIndex], + commands[++cmdIndex], + commands[++cmdIndex], + commands[++cmdIndex], + commands[++cmdIndex], + commands[++cmdIndex], + fillTint.TL, + fillTint.TR, + fillTint.BL, + lighting + ); + + break; + } + + case Commands.STROKE_TRIANGLE: + { + calcMatrix.multiply(currentMatrix, renderMatrix); + + trianglePath[0].x = commands[++cmdIndex]; + trianglePath[0].y = commands[++cmdIndex]; + trianglePath[0].width = lineWidth; + + trianglePath[1].x = commands[++cmdIndex]; + trianglePath[1].y = commands[++cmdIndex]; + trianglePath[1].width = lineWidth; + + trianglePath[2].x = commands[++cmdIndex]; + trianglePath[2].y = commands[++cmdIndex]; + trianglePath[2].width = lineWidth; + + trianglePath[3].x = trianglePath[0].x; + trianglePath[3].y = trianglePath[0].y; + trianglePath[3].width = lineWidth; + + (customRenderNodes.StrokePath || defaultRenderNodes.StrokePath).run( + currentContext, + submitterNode, + trianglePath, + lineWidth, + false, + renderMatrix, + strokeTint.TL, + strokeTint.TR, + strokeTint.BL, + strokeTint.BR, + lighting + ); + break; + } + + case Commands.LINE_TO: + { + x = commands[++cmdIndex]; + y = commands[++cmdIndex]; + + if (lastPath !== null) + { + lastPath.addPoint(x, y, lineWidth); + } + else + { + lastPath = new Path(x, y, lineWidth); + path.push(lastPath); + } + break; + } + + case Commands.MOVE_TO: + { + lastPath = new Path(commands[++cmdIndex], commands[++cmdIndex], lineWidth); + path.push(lastPath); + break; + } + + case Commands.SAVE: + { + matrixStack.push(currentMatrix.copyToArray()); + break; + } + + case Commands.RESTORE: + { + currentMatrix.copyFromArray(matrixStack.pop()); + break; + } + + case Commands.TRANSLATE: + { + x = commands[++cmdIndex]; + y = commands[++cmdIndex]; + currentMatrix.translate(x, y); + break; + } + + case Commands.SCALE: + { + x = commands[++cmdIndex]; + y = commands[++cmdIndex]; + currentMatrix.scale(x, y); + break; + } + + case Commands.ROTATE: + { + currentMatrix.rotate(commands[++cmdIndex]); + break; + } + } + } +}; + +module.exports = GraphicsWebGLRenderer; + + +/***/ }), + +/***/ 26479: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Actions = __webpack_require__(61061); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(51708); +var EventEmitter = __webpack_require__(50792); +var GetAll = __webpack_require__(46710); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var HasValue = __webpack_require__(97022); +var IsPlainObject = __webpack_require__(41212); +var Range = __webpack_require__(88492); +var Sprite = __webpack_require__(68287); + +/** + * @classdesc + * A Group is a way for you to create, manipulate, or recycle similar Game Objects. + * + * Group membership is non-exclusive. A Game Object can belong to several groups, one group, or none. + * + * Groups themselves aren't displayable, and can't be positioned, rotated, scaled, or hidden. + * + * @class Group + * @memberof Phaser.GameObjects + * @extends Phaser.Events.EventEmitter + * @constructor + * @since 3.0.0 + * @param {Phaser.Scene} scene - The scene this group belongs to. + * @param {(Phaser.GameObjects.GameObject[]|Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig)} [children] - Game Objects to add to this group; or the `config` argument. + * @param {Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} [config] - Settings for this group. If `key` is set, Phaser.GameObjects.Group#createMultiple is also called with these settings. + * + * @see Phaser.Physics.Arcade.Group + * @see Phaser.Physics.Arcade.StaticGroup + */ +var Group = new Class({ + + Extends: EventEmitter, + + initialize: + + function Group (scene, children, config) + { + EventEmitter.call(this); + + // They can pass in any of the following as the first argument: + + // 1) A single child + // 2) An array of children + // 3) A config object + // 4) An array of config objects + + // Or they can pass in a child, or array of children AND a config object + + if (config) + { + // config has been set, are the children an array? + + if (children && !Array.isArray(children)) + { + children = [ children ]; + } + } + else if (Array.isArray(children)) + { + // No config, so let's check the children argument + + if (IsPlainObject(children[0])) + { + // It's an array of plain config objects + config = children; + children = null; + } + } + else if (IsPlainObject(children)) + { + // Children isn't an array. Is it a config object though? + config = children; + children = null; + } + + /** + * This scene this group belongs to. + * + * @name Phaser.GameObjects.Group#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * Members of this group. + * + * @name Phaser.GameObjects.Group#children + * @type {Set.} + * @since 3.0.0 + */ + this.children = new Set(); + + /** + * A flag identifying this object as a group. + * + * @name Phaser.GameObjects.Group#isParent + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.isParent = true; + + /** + * A textual representation of this Game Object. + * Used internally by Phaser but is available for your own custom classes to populate. + * + * @name Phaser.GameObjects.Group#type + * @type {string} + * @default 'Group' + * @since 3.21.0 + */ + this.type = 'Group'; + + /** + * The class to create new group members from. + * + * @name Phaser.GameObjects.Group#classType + * @type {function} + * @since 3.0.0 + * @default Phaser.GameObjects.Sprite + * @see Phaser.Types.GameObjects.Group.GroupClassTypeConstructor + */ + this.classType = GetFastValue(config, 'classType', Sprite); + + /** + * The name of this group. + * Empty by default and never populated by Phaser, this is left for developers to use. + * + * @name Phaser.GameObjects.Group#name + * @type {string} + * @default '' + * @since 3.18.0 + */ + this.name = GetFastValue(config, 'name', ''); + + /** + * Whether this group runs its {@link Phaser.GameObjects.Group#preUpdate} method (which may update any members). + * + * @name Phaser.GameObjects.Group#active + * @type {boolean} + * @since 3.0.0 + */ + this.active = GetFastValue(config, 'active', true); + + /** + * The maximum size of this group, if used as a pool. -1 is no limit. + * + * @name Phaser.GameObjects.Group#maxSize + * @type {number} + * @since 3.0.0 + * @default -1 + */ + this.maxSize = GetFastValue(config, 'maxSize', -1); + + /** + * A default texture key to use when creating new group members. + * + * This is used in {@link Phaser.GameObjects.Group#create} + * but not in {@link Phaser.GameObjects.Group#createMultiple}. + * + * @name Phaser.GameObjects.Group#defaultKey + * @type {string} + * @since 3.0.0 + */ + this.defaultKey = GetFastValue(config, 'defaultKey', null); + + /** + * A default texture frame to use when creating new group members. + * + * @name Phaser.GameObjects.Group#defaultFrame + * @type {(string|number)} + * @since 3.0.0 + */ + this.defaultFrame = GetFastValue(config, 'defaultFrame', null); + + /** + * Whether to call the update method of any members. + * + * @name Phaser.GameObjects.Group#runChildUpdate + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.GameObjects.Group#preUpdate + */ + this.runChildUpdate = GetFastValue(config, 'runChildUpdate', false); + + /** + * A function to be called when adding or creating group members. + * + * @name Phaser.GameObjects.Group#createCallback + * @type {?Phaser.Types.GameObjects.Group.GroupCallback} + * @since 3.0.0 + */ + this.createCallback = GetFastValue(config, 'createCallback', null); + + /** + * A function to be called when removing group members. + * + * @name Phaser.GameObjects.Group#removeCallback + * @type {?Phaser.Types.GameObjects.Group.GroupCallback} + * @since 3.0.0 + */ + this.removeCallback = GetFastValue(config, 'removeCallback', null); + + /** + * A function to be called when creating several group members at once. + * + * @name Phaser.GameObjects.Group#createMultipleCallback + * @type {?Phaser.Types.GameObjects.Group.GroupMultipleCreateCallback} + * @since 3.0.0 + */ + this.createMultipleCallback = GetFastValue(config, 'createMultipleCallback', null); + + /** + * A function to be called when adding or creating group members. + * For internal use only by a Group, or any class that extends it. + * + * @name Phaser.GameObjects.Group#internalCreateCallback + * @type {?Phaser.Types.GameObjects.Group.GroupCallback} + * @private + * @since 3.22.0 + */ + this.internalCreateCallback = GetFastValue(config, 'internalCreateCallback', null); + + /** + * A function to be called when removing group members. + * For internal use only by a Group, or any class that extends it. + * + * @name Phaser.GameObjects.Group#internalRemoveCallback + * @type {?Phaser.Types.GameObjects.Group.GroupCallback} + * @private + * @since 3.22.0 + */ + this.internalRemoveCallback = GetFastValue(config, 'internalRemoveCallback', null); + + if (children) + { + this.addMultiple(children); + } + + if (config) + { + this.createMultiple(config); + } + + this.on(Events.ADDED_TO_SCENE, this.addedToScene, this); + this.on(Events.REMOVED_FROM_SCENE, this.removedFromScene, this); + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + /** + * Creates a new Game Object and adds it to this group, unless the group {@link Phaser.GameObjects.Group#isFull is full}. + * + * Calls {@link Phaser.GameObjects.Group#createCallback}. + * + * @method Phaser.GameObjects.Group#create + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal position of the new Game Object in the world. + * @param {number} [y=0] - The vertical position of the new Game Object in the world. + * @param {string} [key=defaultKey] - The texture key of the new Game Object. + * @param {(string|number)} [frame=defaultFrame] - The texture frame of the new Game Object. + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of the new Game Object. + * @param {boolean} [active=true] - The {@link Phaser.GameObjects.GameObject#active} state of the new Game Object. + * + * @return {any} The new Game Object (usually a Sprite, etc.). + */ + create: function (x, y, key, frame, visible, active) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (key === undefined) { key = this.defaultKey; } + if (frame === undefined) { frame = this.defaultFrame; } + if (visible === undefined) { visible = true; } + if (active === undefined) { active = true; } + + // Pool? + if (this.isFull()) + { + return null; + } + + var child = new this.classType(this.scene, x, y, key, frame); + + child.addToDisplayList(this.scene.sys.displayList); + child.addToUpdateList(); + + child.visible = visible; + child.setActive(active); + + this.add(child); + + return child; + }, + + /** + * Creates several Game Objects and adds them to this group. + * + * If the group becomes {@link Phaser.GameObjects.Group#isFull}, no further Game Objects are created. + * + * Calls {@link Phaser.GameObjects.Group#createMultipleCallback} and {@link Phaser.GameObjects.Group#createCallback}. + * + * @method Phaser.GameObjects.Group#createMultiple + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Group.GroupCreateConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig[]} config - Creation settings. This can be a single configuration object or an array of such objects, which will be applied in turn. + * + * @return {any[]} The newly created Game Objects. + */ + createMultiple: function (config) + { + if (this.isFull()) + { + return []; + } + + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var output = []; + + if (config[0].key) + { + for (var i = 0; i < config.length; i++) + { + var entries = this.createFromConfig(config[i]); + + output = output.concat(entries); + } + } + + return output; + }, + + /** + * A helper for {@link Phaser.GameObjects.Group#createMultiple}. + * + * @method Phaser.GameObjects.Group#createFromConfig + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Group.GroupCreateConfig} options - Creation settings. + * + * @return {any[]} The newly created Game Objects. + */ + createFromConfig: function (options) + { + if (this.isFull()) + { + return []; + } + + this.classType = GetFastValue(options, 'classType', this.classType); + + var key = GetFastValue(options, 'key', undefined); + var frame = GetFastValue(options, 'frame', null); + var visible = GetFastValue(options, 'visible', true); + var active = GetFastValue(options, 'active', true); + + var entries = []; + + // Can't do anything without at least a key + if (key === undefined) + { + return entries; + } + else + { + if (!Array.isArray(key)) + { + key = [ key ]; + } + + if (!Array.isArray(frame)) + { + frame = [ frame ]; + } + } + + // Build an array of key frame pairs to loop through + + var repeat = GetFastValue(options, 'repeat', 0); + var randomKey = GetFastValue(options, 'randomKey', false); + var randomFrame = GetFastValue(options, 'randomFrame', false); + var yoyo = GetFastValue(options, 'yoyo', false); + var quantity = GetFastValue(options, 'quantity', false); + var frameQuantity = GetFastValue(options, 'frameQuantity', 1); + var max = GetFastValue(options, 'max', 0); + + // If a quantity value is set we use that to override the frameQuantity + + var range = Range(key, frame, { + max: max, + qty: (quantity) ? quantity : frameQuantity, + random: randomKey, + randomB: randomFrame, + repeat: repeat, + yoyo: yoyo + }); + + if (options.createCallback) + { + this.createCallback = options.createCallback; + } + + if (options.removeCallback) + { + this.removeCallback = options.removeCallback; + } + + if (options.internalCreateCallback) + { + this.internalCreateCallback = options.internalCreateCallback; + } + + if (options.internalRemoveCallback) + { + this.internalRemoveCallback = options.internalRemoveCallback; + } + + for (var c = 0; c < range.length; c++) + { + var created = this.create(0, 0, range[c].a, range[c].b, visible, active); + + if (!created) + { + break; + } + + entries.push(created); + } + + // Post-creation options (applied only to those items created in this call): + + if (HasValue(options, 'setXY')) + { + var x = GetValue(options, 'setXY.x', 0); + var y = GetValue(options, 'setXY.y', 0); + var stepX = GetValue(options, 'setXY.stepX', 0); + var stepY = GetValue(options, 'setXY.stepY', 0); + + Actions.SetXY(entries, x, y, stepX, stepY); + } + + if (HasValue(options, 'setRotation')) + { + var rotation = GetValue(options, 'setRotation.value', 0); + var stepRotation = GetValue(options, 'setRotation.step', 0); + + Actions.SetRotation(entries, rotation, stepRotation); + } + + if (HasValue(options, 'setScale')) + { + var scaleX = GetValue(options, 'setScale.x', 1); + var scaleY = GetValue(options, 'setScale.y', scaleX); + var stepScaleX = GetValue(options, 'setScale.stepX', 0); + var stepScaleY = GetValue(options, 'setScale.stepY', 0); + + Actions.SetScale(entries, scaleX, scaleY, stepScaleX, stepScaleY); + } + + if (HasValue(options, 'setOrigin')) + { + var originX = GetValue(options, 'setOrigin.x', 0.5); + var originY = GetValue(options, 'setOrigin.y', originX); + var stepOriginX = GetValue(options, 'setOrigin.stepX', 0); + var stepOriginY = GetValue(options, 'setOrigin.stepY', 0); + + Actions.SetOrigin(entries, originX, originY, stepOriginX, stepOriginY); + } + + if (HasValue(options, 'setAlpha')) + { + var alpha = GetValue(options, 'setAlpha.value', 1); + var stepAlpha = GetValue(options, 'setAlpha.step', 0); + + Actions.SetAlpha(entries, alpha, stepAlpha); + } + + if (HasValue(options, 'setDepth')) + { + var depth = GetValue(options, 'setDepth.value', 0); + var stepDepth = GetValue(options, 'setDepth.step', 0); + + Actions.SetDepth(entries, depth, stepDepth); + } + + if (HasValue(options, 'setScrollFactor')) + { + var scrollFactorX = GetValue(options, 'setScrollFactor.x', 1); + var scrollFactorY = GetValue(options, 'setScrollFactor.y', scrollFactorX); + var stepScrollFactorX = GetValue(options, 'setScrollFactor.stepX', 0); + var stepScrollFactorY = GetValue(options, 'setScrollFactor.stepY', 0); + + Actions.SetScrollFactor(entries, scrollFactorX, scrollFactorY, stepScrollFactorX, stepScrollFactorY); + } + + var hitArea = GetFastValue(options, 'hitArea', null); + var hitAreaCallback = GetFastValue(options, 'hitAreaCallback', null); + + if (hitArea) + { + Actions.SetHitArea(entries, hitArea, hitAreaCallback); + } + + var grid = GetFastValue(options, 'gridAlign', false); + + if (grid) + { + Actions.GridAlign(entries, grid); + } + + if (this.createMultipleCallback) + { + this.createMultipleCallback.call(this, entries); + } + + return entries; + }, + + /** + * Updates any group members, if {@link Phaser.GameObjects.Group#runChildUpdate} is enabled. + * + * @method Phaser.GameObjects.Group#preUpdate + * @since 3.0.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time elapsed since the last frame. + */ + preUpdate: function (time, delta) + { + if (!this.runChildUpdate || this.children.size === 0) + { + return; + } + + this.children.forEach(function (child) + { + if (child.active) + { + child.update(time, delta); + } + }); + }, + + /** + * Adds a Game Object to this group. + * + * Calls {@link Phaser.GameObjects.Group#createCallback}. + * + * @method Phaser.GameObjects.Group#add + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to add. + * @param {boolean} [addToScene=false] - Also add the Game Object to the scene. + * + * @return {this} This Group object. + */ + add: function (child, addToScene) + { + if (addToScene === undefined) { addToScene = false; } + + if (this.isFull()) + { + return this; + } + + this.children.add(child); + + if (this.internalCreateCallback) + { + this.internalCreateCallback.call(this, child); + } + + if (this.createCallback) + { + this.createCallback.call(this, child); + } + + if (addToScene) + { + child.addToDisplayList(this.scene.sys.displayList); + child.addToUpdateList(); + } + + child.on(Events.DESTROY, this.remove, this); + + return this; + }, + + /** + * Adds several Game Objects to this group. + * + * Calls {@link Phaser.GameObjects.Group#createCallback}. + * + * @method Phaser.GameObjects.Group#addMultiple + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject[]} children - The Game Objects to add. + * @param {boolean} [addToScene=false] - Also add the Game Objects to the scene. + * + * @return {this} This group. + */ + addMultiple: function (children, addToScene) + { + if (addToScene === undefined) { addToScene = false; } + + if (Array.isArray(children)) + { + for (var i = 0; i < children.length; i++) + { + this.add(children[i], addToScene); + } + } + + return this; + }, + + /** + * Removes a member of this Group and optionally removes it from the Scene and / or destroys it. + * + * Calls {@link Phaser.GameObjects.Group#removeCallback}. + * + * @method Phaser.GameObjects.Group#remove + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to remove. + * @param {boolean} [removeFromScene=false] - Optionally remove the Group member from the Scene it belongs to. + * @param {boolean} [destroyChild=false] - Optionally call destroy on the removed Group member. + * + * @return {this} This Group object. + */ + remove: function (child, removeFromScene, destroyChild) + { + if (removeFromScene === undefined) { removeFromScene = false; } + if (destroyChild === undefined) { destroyChild = false; } + + if (!this.children.has(child)) + { + return this; + } + + this.children.delete(child); + + if (this.internalRemoveCallback) + { + this.internalRemoveCallback.call(this, child); + } + + if (this.removeCallback) + { + this.removeCallback.call(this, child); + } + + child.off(Events.DESTROY, this.remove, this); + + if (destroyChild) + { + child.destroy(); + } + else if (removeFromScene) + { + child.removeFromDisplayList(); + child.removeFromUpdateList(); + } + + return this; + }, + + /** + * Removes all members of this Group and optionally removes them from the Scene and / or destroys them. + * + * Does not call {@link Phaser.GameObjects.Group#removeCallback}. + * + * @method Phaser.GameObjects.Group#clear + * @since 3.0.0 + * + * @param {boolean} [removeFromScene=false] - Optionally remove each Group member from the Scene. + * @param {boolean} [destroyChild=false] - Optionally call destroy on the removed Group members. + * + * @return {this} This group. + */ + clear: function (removeFromScene, destroyChild) + { + if (removeFromScene === undefined) { removeFromScene = false; } + if (destroyChild === undefined) { destroyChild = false; } + + var children = this.children; + + children.forEach(function (gameObject) + { + gameObject.off(Events.DESTROY, this.remove, this); + + if (destroyChild) + { + gameObject.destroy(); + } + else if (removeFromScene) + { + gameObject.removeFromDisplayList(); + gameObject.removeFromUpdateList(); + } + }); + + children.clear(); + + return this; + }, + + /** + * Tests if a Game Object is a member of this group. + * + * @method Phaser.GameObjects.Group#contains + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - A Game Object. + * + * @return {boolean} True if the Game Object is a member of this group. + */ + contains: function (child) + { + return this.children.has(child); + }, + + /** + * All members of the group. + * + * @method Phaser.GameObjects.Group#getChildren + * @since 3.0.0 + * + * @return {Phaser.GameObjects.GameObject[]} The group members. + */ + getChildren: function () + { + return Array.from(this.children); + }, + + /** + * The number of members of the group. + * + * @method Phaser.GameObjects.Group#getLength + * @since 3.0.0 + * + * @return {number} + */ + getLength: function () + { + return this.children.size; + }, + + /** + * Returns all children in this Group that match the given criteria based on the `property` and `value` arguments. + * + * For example: `getMatching('visible', true)` would return only children that have their `visible` property set. + * + * Optionally, you can specify a start and end index. For example if the Group has 100 elements, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50. + * + * @method Phaser.GameObjects.Group#getMatching + * @since 3.50.0 + * + * @param {string} [property] - The property to test on each array element. + * @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {number} [startIndex] - An optional start index to search from. + * @param {number} [endIndex] - An optional end index to search to. + * + * @return {any[]} An array of matching Group members. The array will be empty if nothing matched. + */ + getMatching: function (property, value, startIndex, endIndex) + { + return GetAll(Array.from(this.children), property, value, startIndex, endIndex); + }, + + /** + * Scans the Group, from top to bottom, for the first member that has an {@link Phaser.GameObjects.GameObject#active} state matching the argument, + * assigns `x` and `y`, and returns the member. + * + * If no matching member is found and `createIfNull` is true and the group isn't full then it will create a new Game Object using `x`, `y`, `key`, `frame`, and `visible`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getFirst + * @since 3.0.0 + * + * @param {boolean} [state=false] - The {@link Phaser.GameObjects.GameObject#active} value to match. + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {?any} The first matching group member, or a newly created member, or null. + */ + getFirst: function (state, createIfNull, x, y, key, frame, visible) + { + return this.getHandler(true, 1, state, createIfNull, x, y, key, frame, visible); + }, + + /** + * Scans the Group, from top to bottom, for the nth member that has an {@link Phaser.GameObjects.GameObject#active} state matching the argument, + * assigns `x` and `y`, and returns the member. + * + * If no matching member is found and `createIfNull` is true and the group isn't full then it will create a new Game Object using `x`, `y`, `key`, `frame`, and `visible`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getFirstNth + * @since 3.6.0 + * + * @param {number} nth - The nth matching Group member to search for. + * @param {boolean} [state=false] - The {@link Phaser.GameObjects.GameObject#active} value to match. + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {?any} The first matching group member, or a newly created member, or null. + */ + getFirstNth: function (nth, state, createIfNull, x, y, key, frame, visible) + { + return this.getHandler(true, nth, state, createIfNull, x, y, key, frame, visible); + }, + + /** + * Scans the Group for the last member that has an {@link Phaser.GameObjects.GameObject#active} state matching the argument, + * assigns `x` and `y`, and returns the member. + * + * If no matching member is found and `createIfNull` is true and the group isn't full then it will create a new Game Object using `x`, `y`, `key`, `frame`, and `visible`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getLast + * @since 3.6.0 + * + * @param {boolean} [state=false] - The {@link Phaser.GameObjects.GameObject#active} value to match. + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {?any} The first matching group member, or a newly created member, or null. + */ + getLast: function (state, createIfNull, x, y, key, frame, visible) + { + return this.getHandler(false, 1, state, createIfNull, x, y, key, frame, visible); + }, + + /** + * Scans the Group for the last nth member that has an {@link Phaser.GameObjects.GameObject#active} state matching the argument, + * assigns `x` and `y`, and returns the member. + * + * If no matching member is found and `createIfNull` is true and the group isn't full then it will create a new Game Object using `x`, `y`, `key`, `frame`, and `visible`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getLastNth + * @since 3.6.0 + * + * @param {number} nth - The nth matching Group member to search for. + * @param {boolean} [state=false] - The {@link Phaser.GameObjects.GameObject#active} value to match. + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {?any} The first matching group member, or a newly created member, or null. + */ + getLastNth: function (nth, state, createIfNull, x, y, key, frame, visible) + { + return this.getHandler(false, nth, state, createIfNull, x, y, key, frame, visible); + }, + + /** + * Scans the group for the last member that has an {@link Phaser.GameObjects.GameObject#active} state matching the argument, + * assigns `x` and `y`, and returns the member. + * + * If no matching member is found and `createIfNull` is true and the group isn't full then it will create a new Game Object using `x`, `y`, `key`, `frame`, and `visible`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getHandler + * @private + * @since 3.6.0 + * + * @param {boolean} forwards - Search front to back or back to front? + * @param {number} nth - Stop matching after nth successful matches. + * @param {boolean} [state=false] - The {@link Phaser.GameObjects.GameObject#active} value to match. + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {?any} The first matching group member, or a newly created member, or null. + */ + getHandler: function (forwards, nth, state, createIfNull, x, y, key, frame, visible) + { + if (state === undefined) { state = false; } + if (createIfNull === undefined) { createIfNull = false; } + + var gameObject; + + var i; + var total = 0; + var children = Array.from(this.children); + + if (forwards) + { + for (i = 0; i < children.length; i++) + { + gameObject = children[i]; + + if (gameObject.active === state) + { + total++; + + if (total === nth) + { + break; + } + } + else + { + gameObject = null; + } + } + } + else + { + for (i = children.length - 1; i >= 0; i--) + { + gameObject = children[i]; + + if (gameObject.active === state) + { + total++; + + if (total === nth) + { + break; + } + } + else + { + gameObject = null; + } + } + } + + if (gameObject) + { + if (typeof(x) === 'number') + { + gameObject.x = x; + } + + if (typeof(y) === 'number') + { + gameObject.y = y; + } + + return gameObject; + } + + // Got this far? We need to create or bail + if (createIfNull) + { + return this.create(x, y, key, frame, visible); + } + else + { + return null; + } + }, + + /** + * Scans the group for the first member that has an {@link Phaser.GameObjects.GameObject#active} state set to `false`, + * assigns `x` and `y`, and returns the member. + * + * If no inactive member is found and the group isn't full then it will create a new Game Object using `x`, `y`, `key`, `frame`, and `visible`. + * The new Game Object will have its active state set to `true`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#get + * @since 3.0.0 + * + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {?any} The first inactive group member, or a newly created member, or null. + */ + get: function (x, y, key, frame, visible) + { + return this.getFirst(false, true, x, y, key, frame, visible); + }, + + /** + * Scans the group for the first member that has an {@link Phaser.GameObjects.GameObject#active} state set to `true`, + * assigns `x` and `y`, and returns the member. + * + * If no active member is found and `createIfNull` is `true` and the group isn't full then it will create a new one using `x`, `y`, `key`, `frame`, and `visible`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getFirstAlive + * @since 3.0.0 + * + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {any} The first active group member, or a newly created member, or null. + */ + getFirstAlive: function (createIfNull, x, y, key, frame, visible) + { + return this.getFirst(true, createIfNull, x, y, key, frame, visible); + }, + + /** + * Scans the group for the first member that has an {@link Phaser.GameObjects.GameObject#active} state set to `false`, + * assigns `x` and `y`, and returns the member. + * + * If no inactive member is found and `createIfNull` is `true` and the group isn't full then it will create a new one using `x`, `y`, `key`, `frame`, and `visible`. + * The new Game Object will have an active state set to `true`. + * Unless a new member is created, `key`, `frame`, and `visible` are ignored. + * + * @method Phaser.GameObjects.Group#getFirstDead + * @since 3.0.0 + * + * @param {boolean} [createIfNull=false] - Create a new Game Object if no matching members are found, using the following arguments. + * @param {number} [x] - The horizontal position of the Game Object in the world. + * @param {number} [y] - The vertical position of the Game Object in the world. + * @param {string} [key=defaultKey] - The texture key assigned to a new Game Object (if one is created). + * @param {(string|number)} [frame=defaultFrame] - A texture frame assigned to a new Game Object (if one is created). + * @param {boolean} [visible=true] - The {@link Phaser.GameObjects.Components.Visible#visible} state of a new Game Object (if one is created). + * + * @return {any} The first inactive group member, or a newly created member, or null. + */ + getFirstDead: function (createIfNull, x, y, key, frame, visible) + { + return this.getFirst(false, createIfNull, x, y, key, frame, visible); + }, + + /** + * {@link Phaser.Animations.AnimationState#play Plays} an animation for all members of this group. + * + * @method Phaser.GameObjects.Group#playAnimation + * @since 3.0.0 + * + * @param {string} key - The string-based key of the animation to play. + * @param {string} [startFrame=0] - Optionally start the animation playing from this frame index. + * + * @return {this} This Group object. + */ + playAnimation: function (key, startFrame) + { + Actions.PlayAnimation(Array.from(this.children), key, startFrame); + + return this; + }, + + /** + * Whether this group's size at its {@link Phaser.GameObjects.Group#maxSize maximum}. + * + * @method Phaser.GameObjects.Group#isFull + * @since 3.0.0 + * + * @return {boolean} True if the number of members equals {@link Phaser.GameObjects.Group#maxSize}. + */ + isFull: function () + { + if (this.maxSize === -1) + { + return false; + } + else + { + return (this.children.size >= this.maxSize); + } + }, + + /** + * Counts the number of active (or inactive) group members. + * + * @method Phaser.GameObjects.Group#countActive + * @since 3.0.0 + * + * @param {boolean} [value=true] - Count active (true) or inactive (false) group members. + * + * @return {number} The number of group members with an active state matching the `active` argument. + */ + countActive: function (value) + { + if (value === undefined) { value = true; } + + var total = 0; + + this.children.forEach(function (child) + { + if (child.active === value) + { + total++; + } + }); + + return total; + }, + + /** + * Counts the number of in-use (active) group members. + * + * @method Phaser.GameObjects.Group#getTotalUsed + * @since 3.0.0 + * + * @return {number} The number of group members with an active state of true. + */ + getTotalUsed: function () + { + return this.countActive(); + }, + + /** + * The difference of {@link Phaser.GameObjects.Group#maxSize} and the number of active group members. + * + * This represents the number of group members that could be created or reactivated before reaching the size limit. + * + * @method Phaser.GameObjects.Group#getTotalFree + * @since 3.0.0 + * + * @return {number} maxSize minus the number of active group numbers; or a large number (if maxSize is -1). + */ + getTotalFree: function () + { + var used = this.getTotalUsed(); + var capacity = (this.maxSize === -1) ? 999999999999 : this.maxSize; + + return (capacity - used); + }, + + /** + * Sets the `active` property of this Group. + * When active, this Group runs its `preUpdate` method. + * + * @method Phaser.GameObjects.Group#setActive + * @since 3.24.0 + * + * @param {boolean} value - True if this Group should be set as active, false if not. + * + * @return {this} This Group object. + */ + setActive: function (value) + { + this.active = value; + + return this; + }, + + /** + * Sets the `name` property of this Group. + * The `name` property is not populated by Phaser and is presented for your own use. + * + * @method Phaser.GameObjects.Group#setName + * @since 3.24.0 + * + * @param {string} value - The name to be given to this Group. + * + * @return {this} This Group object. + */ + setName: function (value) + { + this.name = value; + + return this; + }, + + /** + * Sets the property as defined in `key` of each group member to the given value. + * + * @method Phaser.GameObjects.Group#propertyValueSet + * @since 3.21.0 + * + * @param {string} key - The property to be updated. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {this} This Group object. + */ + propertyValueSet: function (key, value, step, index, direction) + { + Actions.PropertyValueSet(Array.from(this.children), key, value, step, index, direction); + + return this; + }, + + /** + * Adds the given value to the property as defined in `key` of each group member. + * + * @method Phaser.GameObjects.Group#propertyValueInc + * @since 3.21.0 + * + * @param {string} key - The property to be updated. + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {this} This Group object. + */ + propertyValueInc: function (key, value, step, index, direction) + { + Actions.PropertyValueInc(Array.from(this.children), key, value, step, index, direction); + + return this; + }, + + /** + * Sets the x of each group member. + * + * @method Phaser.GameObjects.Group#setX + * @since 3.21.0 + * + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + setX: function (value, step) + { + Actions.SetX(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the y of each group member. + * + * @method Phaser.GameObjects.Group#setY + * @since 3.21.0 + * + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + setY: function (value, step) + { + Actions.SetY(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the x, y of each group member. + * + * @method Phaser.GameObjects.Group#setXY + * @since 3.21.0 + * + * @param {number} x - The amount to set the `x` property to. + * @param {number} [y=x] - The amount to set the `y` property to. If `undefined` or `null` it uses the `x` value. + * @param {number} [stepX=0] - This is added to the `x` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `y` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + setXY: function (x, y, stepX, stepY) + { + Actions.SetXY(Array.from(this.children), x, y, stepX, stepY); + + return this; + }, + + /** + * Adds the given value to the x of each group member. + * + * @method Phaser.GameObjects.Group#incX + * @since 3.21.0 + * + * @param {number} value - The amount to be added to the `x` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + incX: function (value, step) + { + Actions.IncX(Array.from(this.children), value, step); + + return this; + }, + + /** + * Adds the given value to the y of each group member. + * + * @method Phaser.GameObjects.Group#incY + * @since 3.21.0 + * + * @param {number} value - The amount to be added to the `y` property. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + incY: function (value, step) + { + Actions.IncY(Array.from(this.children), value, step); + + return this; + }, + + /** + * Adds the given value to the x, y of each group member. + * + * @method Phaser.GameObjects.Group#incXY + * @since 3.21.0 + * + * @param {number} x - The amount to be added to the `x` property. + * @param {number} [y=x] - The amount to be added to the `y` property. If `undefined` or `null` it uses the `x` value. + * @param {number} [stepX=0] - This is added to the `x` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `y` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + incXY: function (x, y, stepX, stepY) + { + Actions.IncXY(Array.from(this.children), x, y, stepX, stepY); + + return this; + }, + + /** + * Iterate through the group members changing the position of each element to be that of the element that came before + * it in the array (or after it if direction = 1) + * + * The first group member position is set to x/y. + * + * @method Phaser.GameObjects.Group#shiftPosition + * @since 3.21.0 + * + * @param {number} x - The x coordinate to place the first item in the array at. + * @param {number} y - The y coordinate to place the first item in the array at. + * @param {number} [direction=0] - The iteration direction. 0 = first to last and 1 = last to first. + * + * @return {this} This Group object. + */ + shiftPosition: function (x, y, direction) + { + Actions.ShiftPosition(Array.from(this.children), x, y, direction); + + return this; + }, + + /** + * Sets the angle of each group member. + * + * @method Phaser.GameObjects.Group#angle + * @since 3.21.0 + * + * @param {number} value - The amount to set the angle to, in degrees. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + angle: function (value, step) + { + Actions.Angle(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the rotation of each group member. + * + * @method Phaser.GameObjects.Group#rotate + * @since 3.21.0 + * + * @param {number} value - The amount to set the rotation to, in radians. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + rotate: function (value, step) + { + Actions.Rotate(Array.from(this.children), value, step); + + return this; + }, + + /** + * Rotates each group member around the given point by the given angle. + * + * @method Phaser.GameObjects.Group#rotateAround + * @since 3.21.0 + * + * @param {Phaser.Types.Math.Vector2Like} point - Any object with public `x` and `y` properties. + * @param {number} angle - The angle to rotate by, in radians. + * + * @return {this} This Group object. + */ + rotateAround: function (point, angle) + { + Actions.RotateAround(Array.from(this.children), point, angle); + + return this; + }, + + /** + * Rotates each group member around the given point by the given angle and distance. + * + * @method Phaser.GameObjects.Group#rotateAroundDistance + * @since 3.21.0 + * + * @param {Phaser.Types.Math.Vector2Like} point - Any object with public `x` and `y` properties. + * @param {number} angle - The angle to rotate by, in radians. + * @param {number} distance - The distance from the point of rotation in pixels. + * + * @return {this} This Group object. + */ + rotateAroundDistance: function (point, angle, distance) + { + Actions.RotateAroundDistance(Array.from(this.children), point, angle, distance); + + return this; + }, + + /** + * Sets the alpha of each group member. + * + * @method Phaser.GameObjects.Group#setAlpha + * @since 3.21.0 + * + * @param {number} value - The amount to set the alpha to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + setAlpha: function (value, step) + { + Actions.SetAlpha(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the tint of each group member. + * + * @method Phaser.GameObjects.Group#setTint + * @since 3.21.0 + * + * @param {number} topLeft - The tint being applied to top-left corner of item. If other parameters are given no value, this tint will be applied to whole item. + * @param {number} [topRight] - The tint to be applied to top-right corner of item. + * @param {number} [bottomLeft] - The tint to be applied to the bottom-left corner of item. + * @param {number} [bottomRight] - The tint to be applied to the bottom-right corner of item. + * + * @return {this} This Group object. + */ + setTint: function (topLeft, topRight, bottomLeft, bottomRight) + { + Actions.SetTint(Array.from(this.children), topLeft, topRight, bottomLeft, bottomRight); + + return this; + }, + + /** + * Sets the originX, originY of each group member. + * + * @method Phaser.GameObjects.Group#setOrigin + * @since 3.21.0 + * + * @param {number} originX - The amount to set the `originX` property to. + * @param {number} [originY] - The amount to set the `originY` property to. If `undefined` or `null` it uses the `originX` value. + * @param {number} [stepX=0] - This is added to the `originX` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `originY` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + setOrigin: function (originX, originY, stepX, stepY) + { + Actions.SetOrigin(Array.from(this.children), originX, originY, stepX, stepY); + + return this; + }, + + /** + * Sets the scaleX of each group member. + * + * @method Phaser.GameObjects.Group#scaleX + * @since 3.21.0 + * + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + scaleX: function (value, step) + { + Actions.ScaleX(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the scaleY of each group member. + * + * @method Phaser.GameObjects.Group#scaleY + * @since 3.21.0 + * + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + scaleY: function (value, step) + { + Actions.ScaleY(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the scaleX, scaleY of each group member. + * + * @method Phaser.GameObjects.Group#scaleXY + * @since 3.21.0 + * + * @param {number} scaleX - The amount to be added to the `scaleX` property. + * @param {number} [scaleY] - The amount to be added to the `scaleY` property. If `undefined` or `null` it uses the `scaleX` value. + * @param {number} [stepX=0] - This is added to the `scaleX` amount, multiplied by the iteration counter. + * @param {number} [stepY=0] - This is added to the `scaleY` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + scaleXY: function (scaleX, scaleY, stepX, stepY) + { + Actions.ScaleXY(Array.from(this.children), scaleX, scaleY, stepX, stepY); + + return this; + }, + + /** + * Sets the depth of each group member. + * + * @method Phaser.GameObjects.Group#setDepth + * @since 3.0.0 + * + * @param {number} value - The amount to set the property to. + * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter. + * + * @return {this} This Group object. + */ + setDepth: function (value, step) + { + Actions.SetDepth(Array.from(this.children), value, step); + + return this; + }, + + /** + * Sets the blendMode of each group member. + * + * @method Phaser.GameObjects.Group#setBlendMode + * @since 3.21.0 + * + * @param {number} value - The amount to set the property to. + * + * @return {this} This Group object. + */ + setBlendMode: function (value) + { + Actions.SetBlendMode(Array.from(this.children), value); + + return this; + }, + + /** + * Passes all group members to the Input Manager to enable them for input with identical areas and callbacks. + * + * @method Phaser.GameObjects.Group#setHitArea + * @since 3.21.0 + * + * @param {*} hitArea - Either an input configuration object, or a geometric shape that defines the hit area for the Game Object. If not specified a Rectangle will be used. + * @param {Phaser.Types.Input.HitAreaCallback} hitAreaCallback - A callback to be invoked when the Game Object is interacted with. If you provide a shape you must also provide a callback. + * + * @return {this} This Group object. + */ + setHitArea: function (hitArea, hitAreaCallback) + { + Actions.SetHitArea(Array.from(this.children), hitArea, hitAreaCallback); + + return this; + }, + + /** + * Shuffles the group members in place. + * + * @method Phaser.GameObjects.Group#shuffle + * @since 3.21.0 + * + * @return {this} This Group object. + */ + shuffle: function () + { + Actions.Shuffle(Array.from(this.children)); + + return this; + }, + + /** + * Deactivates a member of this group. + * + * @method Phaser.GameObjects.Group#kill + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - A member of this group. + */ + kill: function (gameObject) + { + if (this.children.has(gameObject)) + { + gameObject.setActive(false); + } + }, + + /** + * Deactivates and hides a member of this group. + * + * @method Phaser.GameObjects.Group#killAndHide + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - A member of this group. + */ + killAndHide: function (gameObject) + { + if (this.children.has(gameObject)) + { + gameObject.setActive(false); + gameObject.setVisible(false); + } + }, + + /** + * Sets the visible of each group member. + * + * @method Phaser.GameObjects.Group#setVisible + * @since 3.21.0 + * + * @param {boolean} value - The value to set the property to. + * @param {number} [index=0] - An optional offset to start searching from within the items array. + * @param {number} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning. + * + * @return {this} This Group object. + */ + setVisible: function (value, index, direction) + { + Actions.SetVisible(Array.from(this.children), value, index, direction); + + return this; + }, + + /** + * Toggles (flips) the visible state of each member of this group. + * + * @method Phaser.GameObjects.Group#toggleVisible + * @since 3.0.0 + * + * @return {this} This Group object. + */ + toggleVisible: function () + { + Actions.ToggleVisible(Array.from(this.children)); + + return this; + }, + + /** + * Empties this Group of all children and removes it from the Scene. + * + * Does not call {@link Phaser.GameObjects.Group#removeCallback}. + * + * Children of this Group will _not_ be removed from the Scene by calling this method + * unless you specify the `removeFromScene` parameter. + * + * Children of this Group will also _not_ be destroyed by calling this method + * unless you specify the `destroyChildren` parameter. + * + * @method Phaser.GameObjects.Group#destroy + * @since 3.0.0 + * + * @param {boolean} [destroyChildren=false] - Also {@link Phaser.GameObjects.GameObject#destroy} each Group member. + * @param {boolean} [removeFromScene=false] - Optionally remove each Group member from the Scene. + */ + destroy: function (destroyChildren, removeFromScene) + { + if (destroyChildren === undefined) { destroyChildren = false; } + if (removeFromScene === undefined) { removeFromScene = false; } + + // This Game Object had already been destroyed + if (!this.scene || this.ignoreDestroy) + { + return; + } + + this.emit(Events.DESTROY, this); + + this.removeAllListeners(); + + this.scene.sys.updateList.remove(this); + + this.clear(removeFromScene, destroyChildren); + + this.scene = undefined; + this.children = undefined; + } + +}); + +module.exports = Group; + + +/***/ }), + +/***/ 94975: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectCreator = __webpack_require__(44603); +var Group = __webpack_require__(26479); + +/** + * Creates a new Group Game Object and returns it. + * + * Note: This method will only be available if the Group Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#group + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} config - The configuration object this Game Object will use to create itself. + * + * @return {Phaser.GameObjects.Group} The Game Object that was created. + */ +GameObjectCreator.register('group', function (config) +{ + return new Group(this.scene, null, config); +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 3385: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Group = __webpack_require__(26479); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Group Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Group Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#group + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject[]|Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupConfig[]|Phaser.Types.GameObjects.Group.GroupCreateConfig)} [children] - Game Objects to add to this Group; or the `config` argument. + * @param {Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} [config] - A Group Configuration object. + * + * @return {Phaser.GameObjects.Group} The Game Object that was created. + */ +GameObjectFactory.register('group', function (children, config) +{ + return this.updateList.add(new Group(this.scene, children, config)); +}); + + +/***/ }), + +/***/ 88571: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultImageNodes = __webpack_require__(40939); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var ImageRender = __webpack_require__(59819); + +/** + * @classdesc + * An Image Game Object. + * + * An Image is a light-weight Game Object useful for the display of static images in your game, + * such as logos, backgrounds, scenery or other non-animated elements. Images can have input + * events and physics bodies, or be tweened, tinted or scrolled. The main difference between an + * Image and a Sprite is that you cannot animate an Image as they do not have the Animation component. + * + * @class Image + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.TextureCrop + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + */ +var Image = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.Depth, + Components.Flip, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.Size, + Components.TextureCrop, + Components.Tint, + Components.Transform, + Components.Visible, + ImageRender + ], + + initialize: + + function Image (scene, x, y, texture, frame) + { + GameObject.call(this, scene, 'Image'); + + /** + * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method. + * + * @name Phaser.GameObjects.Image#_crop + * @type {object} + * @private + * @since 3.11.0 + */ + this._crop = this.resetCropObject(); + + this.setTexture(texture, frame); + this.setPosition(x, y); + this.setSizeToFrame(); + this.setOriginFromFrame(); + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Image#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultImageNodes; + } + } + +}); + +module.exports = Image; + + +/***/ }), + +/***/ 40652: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Image#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ImageCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + renderer.batchSprite(src, src.frame, camera, parentMatrix); +}; + +module.exports = ImageCanvasRenderer; + + +/***/ }), + +/***/ 82459: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Image = __webpack_require__(88571); + +/** + * Creates a new Image Game Object and returns it. + * + * Note: This method will only be available if the Image Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#image + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Image} The Game Object that was created. + */ +GameObjectCreator.register('image', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var frame = GetAdvancedValue(config, 'frame', null); + + var image = new Image(this.scene, 0, 0, key, frame); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, image, config); + + return image; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 2117: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Image = __webpack_require__(88571); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Image Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Image Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#image + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.GameObjects.Image} The Game Object that was created. + */ +GameObjectFactory.register('image', function (x, y, texture, frame) +{ + return this.displayList.add(new Image(this.scene, x, y, texture, frame)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 59819: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(99517); +} + +if (true) +{ + renderCanvas = __webpack_require__(40652); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 99517: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Image#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ImageWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + drawingContext.camera.addToRenderList(src); + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + src, + parentMatrix, + 0, + customRenderNodes.Texturer || defaultRenderNodes.Texturer, + customRenderNodes.Transformer || defaultRenderNodes.Transformer + ); +}; + +module.exports = ImageWebGLRenderer; + + +/***/ }), + +/***/ 77856: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.GameObjects + */ + +var GameObjects = { + + Events: __webpack_require__(51708), + + DisplayList: __webpack_require__(8050), + GameObjectCreator: __webpack_require__(44603), + GameObjectFactory: __webpack_require__(39429), + UpdateList: __webpack_require__(45027), + + Components: __webpack_require__(31401), + GetCalcMatrix: __webpack_require__(91296), + + BuildGameObject: __webpack_require__(25305), + BuildGameObjectAnimation: __webpack_require__(13059), + GameObject: __webpack_require__(95643), + BitmapText: __webpack_require__(22186), + Blitter: __webpack_require__(6107), + Bob: __webpack_require__(46590), + Container: __webpack_require__(31559), + DOMElement: __webpack_require__(3069), + DynamicBitmapText: __webpack_require__(2638), + Extern: __webpack_require__(42421), + Graphics: __webpack_require__(43831), + Group: __webpack_require__(26479), + Image: __webpack_require__(88571), + Layer: __webpack_require__(93595), + Particles: __webpack_require__(18404), + PathFollower: __webpack_require__(1159), + RenderTexture: __webpack_require__(591), + RetroFont: __webpack_require__(196), + Rope: __webpack_require__(77757), + Sprite: __webpack_require__(68287), + Stamp: __webpack_require__(14727), + + Text: __webpack_require__(50171), + GetTextSize: __webpack_require__(14220), + MeasureText: __webpack_require__(79557), + TextStyle: __webpack_require__(35762), + + TileSprite: __webpack_require__(20839), + Zone: __webpack_require__(41481), + Video: __webpack_require__(18471), + + // Shapes + + Shape: __webpack_require__(17803), + Arc: __webpack_require__(23629), + Curve: __webpack_require__(89), + Ellipse: __webpack_require__(19921), + Grid: __webpack_require__(30479), + IsoBox: __webpack_require__(61475), + IsoTriangle: __webpack_require__(16933), + Line: __webpack_require__(57847), + Polygon: __webpack_require__(24949), + Rectangle: __webpack_require__(74561), + Star: __webpack_require__(55911), + Triangle: __webpack_require__(36931), + + // Game Object Factories + + Factories: { + Blitter: __webpack_require__(12709), + Container: __webpack_require__(24961), + DOMElement: __webpack_require__(2611), + DynamicBitmapText: __webpack_require__(72566), + Extern: __webpack_require__(56315), + Graphics: __webpack_require__(1201), + Group: __webpack_require__(3385), + Image: __webpack_require__(2117), + Layer: __webpack_require__(20005), + Particles: __webpack_require__(676), + PathFollower: __webpack_require__(90145), + RenderTexture: __webpack_require__(60505), + Rope: __webpack_require__(96819), + Sprite: __webpack_require__(46409), + Stamp: __webpack_require__(85326), + StaticBitmapText: __webpack_require__(34914), + Text: __webpack_require__(68005), + TileSprite: __webpack_require__(91681), + Zone: __webpack_require__(84175), + Video: __webpack_require__(89025), + + // Shapes + Arc: __webpack_require__(42563), + Curve: __webpack_require__(40511), + Ellipse: __webpack_require__(1543), + Grid: __webpack_require__(34137), + IsoBox: __webpack_require__(3933), + IsoTriangle: __webpack_require__(49803), + Line: __webpack_require__(2481), + Polygon: __webpack_require__(64827), + Rectangle: __webpack_require__(87959), + Star: __webpack_require__(93697), + Triangle: __webpack_require__(45245) + }, + + Creators: { + Blitter: __webpack_require__(9403), + Container: __webpack_require__(77143), + DynamicBitmapText: __webpack_require__(11164), + Graphics: __webpack_require__(87079), + Group: __webpack_require__(94975), + Image: __webpack_require__(82459), + Layer: __webpack_require__(25179), + Particles: __webpack_require__(92730), + RenderTexture: __webpack_require__(34495), + Rope: __webpack_require__(26209), + Sprite: __webpack_require__(15567), + Stamp: __webpack_require__(31479), + StaticBitmapText: __webpack_require__(57336), + Text: __webpack_require__(71259), + TileSprite: __webpack_require__(14167), + Zone: __webpack_require__(95261), + Video: __webpack_require__(11511) + } + +}; + +// WebGL only Game Objects +if (true) +{ + GameObjects.CaptureFrame = __webpack_require__(43451); + GameObjects.Shader = __webpack_require__(20071); + GameObjects.NineSlice = __webpack_require__(28103); + GameObjects.PointLight = __webpack_require__(80321); + GameObjects.SpriteGPULayer = __webpack_require__(76573); + + GameObjects.Factories.CaptureFrame = __webpack_require__(20421); + GameObjects.Factories.Shader = __webpack_require__(74177); + GameObjects.Factories.NineSlice = __webpack_require__(47521); + GameObjects.Factories.PointLight = __webpack_require__(71255); + GameObjects.Factories.SpriteGPULayer = __webpack_require__(96019); + + GameObjects.Creators.CaptureFrame = __webpack_require__(23675); + GameObjects.Creators.Shader = __webpack_require__(54935); + GameObjects.Creators.NineSlice = __webpack_require__(28279); + GameObjects.Creators.PointLight = __webpack_require__(39829); + GameObjects.Creators.SpriteGPULayer = __webpack_require__(16193); + + GameObjects.Light = __webpack_require__(41432); + GameObjects.LightsManager = __webpack_require__(61356); + GameObjects.LightsPlugin = __webpack_require__(88992); +} + +module.exports = GameObjects; + + +/***/ }), + +/***/ 93595: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlendModes = __webpack_require__(10312); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var ComponentsToJSON = __webpack_require__(53774); +var DataManager = __webpack_require__(45893); +var EventEmitter = __webpack_require__(50792); +var GameObjectEvents = __webpack_require__(51708); +var List = __webpack_require__(73162); +var Render = __webpack_require__(33963); +var SceneEvents = __webpack_require__(44594); +var StableSort = __webpack_require__(19186); + +/** + * @classdesc + * A Layer Game Object. + * + * A Layer is a special type of Game Object that acts as a Display List. You can add any type of Game Object + * to a Layer, just as you would to a Scene. Layers can be used to visually group together 'layers' of Game + * Objects: + * + * ```javascript + * const spaceman = this.add.sprite(150, 300, 'spaceman'); + * const bunny = this.add.sprite(400, 300, 'bunny'); + * const elephant = this.add.sprite(650, 300, 'elephant'); + * + * const layer = this.add.layer(); + * + * layer.add([ spaceman, bunny, elephant ]); + * ``` + * + * The 3 sprites in the example above will now be managed by the Layer they were added to. Therefore, + * if you then set `layer.setVisible(false)` they would all vanish from the display. + * + * You can also control the depth of the Game Objects within the Layer. For example, calling the + * `setDepth` method of a child of a Layer will allow you to adjust the depth of that child _within the + * Layer itself_, rather than the whole Scene. The Layer, too, can have its depth set as well. + * + * The Layer class also offers many different methods for manipulating the list, such as the + * methods `moveUp`, `moveDown`, `sendToBack`, `bringToTop` and so on. These allow you to change the + * display list position of the Layers children, causing it to adjust the order in which they are + * rendered. Using `setDepth` on a child allows you to override this. + * + * Layers have no position or size within the Scene. This means you cannot enable a Layer for + * physics or input, or change the position, rotation or scale of a Layer. They also have no scroll + * factor, texture, tint, origin, crop or bounds. + * + * If you need those kind of features then you should use a Container instead. Containers can be added + * to Layers, but Layers cannot be added to Containers. + * + * However, you can set the Alpha, Blend Mode, Depth, Mask and Visible state of a Layer. These settings + * will impact all children being rendered by the Layer. + * + * @class Layer + * @extends Phaser.Structs.List. + * @memberof Phaser.GameObjects + * @constructor + * @since 3.50.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Filters + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderSteps + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {Phaser.GameObjects.GameObject[]} [children] - An optional array of Game Objects to add to this Layer. + */ +var Layer = new Class({ + + Extends: List, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.Filters, + Components.Mask, + Components.RenderSteps, // This does not extend GameObject so it must mixin RenderSteps here. + Components.Visible, + EventEmitter, + Render + ], + + initialize: + + function Layer (scene, children) + { + List.call(this, scene); + EventEmitter.call(this); + + /** + * A reference to the Scene to which this Game Object belongs. + * + * Game Objects can only belong to one Scene. + * + * You should consider this property as being read-only. You cannot move a + * Game Object to another Scene by simply changing it. + * + * @name Phaser.GameObjects.Layer#scene + * @type {Phaser.Scene} + * @since 3.50.0 + */ + this.scene = scene; + + /** + * Holds a reference to the Display List that contains this Game Object. + * + * This is set automatically when this Game Object is added to a Scene or Layer. + * + * You should treat this property as being read-only. + * + * @name Phaser.GameObjects.Layer#displayList + * @type {(Phaser.GameObjects.DisplayList|Phaser.GameObjects.Layer)} + * @default null + * @since 3.50.0 + */ + this.displayList = null; + + /** + * A textual representation of this Game Object, i.e. `sprite`. + * Used internally by Phaser but is available for your own custom classes to populate. + * + * @name Phaser.GameObjects.Layer#type + * @type {string} + * @since 3.50.0 + */ + this.type = 'Layer'; + + /** + * The current state of this Game Object. + * + * Phaser itself will never modify this value, although plugins may do so. + * + * Use this property to track the state of a Game Object during its lifetime. For example, it could change from + * a state of 'moving', to 'attacking', to 'dead'. The state value should be an integer (ideally mapped to a constant + * in your game code), or a string. These are recommended to keep it light and simple, with fast comparisons. + * If you need to store complex data about your Game Object, look at using the Data Component instead. + * + * @name Phaser.GameObjects.Layer#state + * @type {(number|string)} + * @since 3.50.0 + */ + this.state = 0; + + /** + * A Layer cannot be placed inside a Container. + * + * This property is kept purely so a Layer has the same + * shape as a Game Object. + * + * @name Phaser.GameObjects.Layer#parentContainer + * @type {Phaser.GameObjects.Container} + * @since 3.51.0 + */ + this.parentContainer = null; + + /** + * The name of this Game Object. + * Empty by default and never populated by Phaser, this is left for developers to use. + * + * @name Phaser.GameObjects.Layer#name + * @type {string} + * @default '' + * @since 3.50.0 + */ + this.name = ''; + + /** + * The active state of this Game Object. + * A Game Object with an active state of `true` is processed by the Scenes UpdateList, if added to it. + * An active object is one which is having its logic and internal systems updated. + * + * @name Phaser.GameObjects.Layer#active + * @type {boolean} + * @default true + * @since 3.50.0 + */ + this.active = true; + + /** + * The Tab Index of the Game Object. + * Reserved for future use by plugins and the Input Manager. + * + * @name Phaser.GameObjects.Layer#tabIndex + * @type {number} + * @default -1 + * @since 3.51.0 + */ + this.tabIndex = -1; + + /** + * A Data Manager. + * It allows you to store, query and get key/value paired information specific to this Game Object. + * `null` by default. Automatically created if you use `getData` or `setData` or `setDataEnabled`. + * + * @name Phaser.GameObjects.Layer#data + * @type {Phaser.Data.DataManager} + * @default null + * @since 3.50.0 + */ + this.data = null; + + /** + * The flags that are compared against `RENDER_MASK` to determine if this Game Object will render or not. + * The bits are 0001 | 0010 | 0100 | 1000 set by the components Visible, Alpha, Transform and Texture respectively. + * If those components are not used by your custom class then you can use this bitmask as you wish. + * + * @name Phaser.GameObjects.Layer#renderFlags + * @type {number} + * @default 15 + * @since 3.50.0 + */ + this.renderFlags = 15; + + /** + * A bitmask that controls if this Game Object is drawn by a Camera or not. + * Not usually set directly, instead call `Camera.ignore`, however you can + * set this property directly using the Camera.id property: + * + * @example + * this.cameraFilter |= camera.id + * + * @name Phaser.GameObjects.Layer#cameraFilter + * @type {number} + * @default 0 + * @since 3.50.0 + */ + this.cameraFilter = 0; + + /** + * This property is kept purely so a Layer has the same + * shape as a Game Object. You cannot input enable a Layer. + * + * @name Phaser.GameObjects.Layer#input + * @type {?Phaser.Types.Input.InteractiveObject} + * @default null + * @since 3.51.0 + */ + this.input = null; + + /** + * This property is kept purely so a Layer has the same + * shape as a Game Object. You cannot give a Layer a physics body. + * + * @name Phaser.GameObjects.Layer#body + * @type {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|MatterJS.BodyType)} + * @default null + * @since 3.51.0 + */ + this.body = null; + + /** + * This Game Object will ignore all calls made to its destroy method if this flag is set to `true`. + * This includes calls that may come from a Group, Container or the Scene itself. + * While it allows you to persist a Game Object across Scenes, please understand you are entirely + * responsible for managing references to and from this Game Object. + * + * @name Phaser.GameObjects.Layer#ignoreDestroy + * @type {boolean} + * @default false + * @since 3.50.0 + */ + this.ignoreDestroy = false; + + /** + * A reference to the Scene Systems. + * + * @name Phaser.GameObjects.Layer#systems + * @type {Phaser.Scenes.Systems} + * @since 3.50.0 + */ + this.systems = scene.sys; + + /** + * A reference to the Scene Event Emitter. + * + * @name Phaser.GameObjects.Layer#events + * @type {Phaser.Events.EventEmitter} + * @since 3.50.0 + */ + this.events = scene.sys.events; + + /** + * The flag the determines whether Game Objects should be sorted when `depthSort()` is called. + * + * @name Phaser.GameObjects.Layer#sortChildrenFlag + * @type {boolean} + * @default false + * @since 3.50.0 + */ + this.sortChildrenFlag = false; + + // Set the List callbacks + this.addCallback = this.addChildCallback; + this.removeCallback = this.removeChildCallback; + + this.clearAlpha(); + + this.setBlendMode(BlendModes.SKIP_CHECK); + + if (children) + { + this.add(children); + } + + // Initialize RenderSteps mixin. + if (this.addRenderStep) + { + this.addRenderStep(this.renderWebGL); + } + + // Tell the Scene to re-sort the children + scene.sys.queueDepthSort(); + }, + + /** + * Sets the `active` property of this Game Object and returns this Game Object for further chaining. + * A Game Object with its `active` property set to `true` will be updated by the Scenes UpdateList. + * + * @method Phaser.GameObjects.Layer#setActive + * @since 3.50.0 + * + * @param {boolean} value - True if this Game Object should be set as active, false if not. + * + * @return {this} This GameObject. + */ + setActive: function (value) + { + this.active = value; + + return this; + }, + + /** + * Sets the `name` property of this Game Object and returns this Game Object for further chaining. + * The `name` property is not populated by Phaser and is presented for your own use. + * + * @method Phaser.GameObjects.Layer#setName + * @since 3.50.0 + * + * @param {string} value - The name to be given to this Game Object. + * + * @return {this} This GameObject. + */ + setName: function (value) + { + this.name = value; + + return this; + }, + + /** + * Sets the current state of this Game Object. + * + * Phaser itself will never modify the State of a Game Object, although plugins may do so. + * + * For example, a Game Object could change from a state of 'moving', to 'attacking', to 'dead'. + * The state value should typically be an integer (ideally mapped to a constant + * in your game code), but could also be a string. It is recommended to keep it light and simple. + * If you need to store complex data about your Game Object, look at using the Data Component instead. + * + * @method Phaser.GameObjects.Layer#setState + * @since 3.50.0 + * + * @param {(number|string)} value - The state of the Game Object. + * + * @return {this} This GameObject. + */ + setState: function (value) + { + this.state = value; + + return this; + }, + + /** + * Adds a Data Manager component to this Game Object. + * + * @method Phaser.GameObjects.Layer#setDataEnabled + * @since 3.50.0 + * @see Phaser.Data.DataManager + * + * @return {this} This GameObject. + */ + setDataEnabled: function () + { + if (!this.data) + { + this.data = new DataManager(this); + } + + return this; + }, + + /** + * Allows you to store a key value pair within this Game Objects Data Manager. + * + * If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled + * before setting the value. + * + * If the key doesn't already exist in the Data Manager then it is created. + * + * ```javascript + * sprite.setData('name', 'Red Gem Stone'); + * ``` + * + * You can also pass in an object of key value pairs as the first argument: + * + * ```javascript + * sprite.setData({ name: 'Red Gem Stone', level: 2, owner: 'Link', gold: 50 }); + * ``` + * + * To get a value back again you can call `getData`: + * + * ```javascript + * sprite.getData('gold'); + * ``` + * + * Or you can access the value directly via the `values` property, where it works like any other variable: + * + * ```javascript + * sprite.data.values.gold += 50; + * ``` + * + * When the value is first set, a `setdata` event is emitted from this Game Object. + * + * If the key already exists, a `changedata` event is emitted instead, along an event named after the key. + * For example, if you updated an existing key called `PlayerLives` then it would emit the event `changedata-PlayerLives`. + * These events will be emitted regardless if you use this method to set the value, or the direct `values` setter. + * + * Please note that the data keys are case-sensitive and must be valid JavaScript Object property strings. + * This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager. + * + * @method Phaser.GameObjects.Layer#setData + * @since 3.50.0 + * + * @param {(string|object)} key - The key to set the value for. Or an object of key value pairs. If an object the `data` argument is ignored. + * @param {*} [data] - The value to set for the given key. If an object is provided as the key this argument is ignored. + * + * @return {this} This GameObject. + */ + setData: function (key, value) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + this.data.set(key, value); + + return this; + }, + + /** + * Increase a value for the given key within this Game Objects Data Manager. If the key doesn't already exist in the Data Manager then it is increased from 0. + * + * If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled + * before setting the value. + * + * If the key doesn't already exist in the Data Manager then it is created. + * + * When the value is first set, a `setdata` event is emitted from this Game Object. + * + * @method Phaser.GameObjects.Layer#incData + * @since 3.50.0 + * + * @param {(string|object)} key - The key to increase the value for. + * @param {*} [data] - The value to increase for the given key. + * + * @return {this} This GameObject. + */ + incData: function (key, value) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + this.data.inc(key, value); + + return this; + }, + + /** + * Toggle a boolean value for the given key within this Game Objects Data Manager. If the key doesn't already exist in the Data Manager then it is toggled from false. + * + * If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled + * before setting the value. + * + * If the key doesn't already exist in the Data Manager then it is created. + * + * When the value is first set, a `setdata` event is emitted from this Game Object. + * + * @method Phaser.GameObjects.Layer#toggleData + * @since 3.50.0 + * + * @param {(string|object)} key - The key to toggle the value for. + * + * @return {this} This GameObject. + */ + toggleData: function (key) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + this.data.toggle(key); + + return this; + }, + + /** + * Retrieves the value for the given key in this Game Objects Data Manager, or undefined if it doesn't exist. + * + * You can also access values via the `values` object. For example, if you had a key called `gold` you can do either: + * + * ```javascript + * sprite.getData('gold'); + * ``` + * + * Or access the value directly: + * + * ```javascript + * sprite.data.values.gold; + * ``` + * + * You can also pass in an array of keys, in which case an array of values will be returned: + * + * ```javascript + * sprite.getData([ 'gold', 'armor', 'health' ]); + * ``` + * + * This approach is useful for destructuring arrays in ES6. + * + * @method Phaser.GameObjects.Layer#getData + * @since 3.50.0 + * + * @param {(string|string[])} key - The key of the value to retrieve, or an array of keys. + * + * @return {*} The value belonging to the given key, or an array of values, the order of which will match the input array. + */ + getData: function (key) + { + if (!this.data) + { + this.data = new DataManager(this); + } + + return this.data.get(key); + }, + + /** + * A Layer cannot be enabled for input. + * + * This method does nothing and is kept to ensure + * the Layer has the same shape as a Game Object. + * + * @method Phaser.GameObjects.Layer#setInteractive + * @since 3.51.0 + * + * @return {this} This GameObject. + */ + setInteractive: function () + { + return this; + }, + + /** + * A Layer cannot be enabled for input. + * + * This method does nothing and is kept to ensure + * the Layer has the same shape as a Game Object. + * + * @method Phaser.GameObjects.Layer#disableInteractive + * @since 3.51.0 + * + * @return {this} This GameObject. + */ + disableInteractive: function () + { + return this; + }, + + /** + * A Layer cannot be enabled for input. + * + * This method does nothing and is kept to ensure + * the Layer has the same shape as a Game Object. + * + * @method Phaser.GameObjects.Layer#removeInteractive + * @since 3.51.0 + * + * @return {this} This GameObject. + */ + removeInteractive: function () + { + return this; + }, + + /** + * This callback is invoked when this Game Object is added to a Scene. + * + * Can be overriden by custom Game Objects, but be aware of some Game Objects that + * will use this, such as Sprites, to add themselves into the Update List. + * + * You can also listen for the `ADDED_TO_SCENE` event from this Game Object. + * + * @method Phaser.GameObjects.Layer#addedToScene + * @since 3.50.0 + */ + addedToScene: function () + { + }, + + /** + * This callback is invoked when this Game Object is removed from a Scene. + * + * Can be overriden by custom Game Objects, but be aware of some Game Objects that + * will use this, such as Sprites, to removed themselves from the Update List. + * + * You can also listen for the `REMOVED_FROM_SCENE` event from this Game Object. + * + * @method Phaser.GameObjects.Layer#removedFromScene + * @since 3.50.0 + */ + removedFromScene: function () + { + }, + + /** + * To be overridden by custom GameObjects. Allows base objects to be used in a Pool. + * + * @method Phaser.GameObjects.Layer#update + * @since 3.50.0 + * + * @param {...*} [args] - args + */ + update: function () + { + }, + + /** + * Returns a JSON representation of the Game Object. + * + * @method Phaser.GameObjects.Layer#toJSON + * @since 3.50.0 + * + * @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object. + */ + toJSON: function () + { + return ComponentsToJSON(this); + }, + + /** + * Compares the renderMask with the renderFlags to see if this Game Object will render or not. + * Also checks the Game Object against the given Cameras exclusion list. + * + * @method Phaser.GameObjects.Layer#willRender + * @since 3.50.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to check against this Game Object. + * + * @return {boolean} True if the Game Object should be rendered, otherwise false. + */ + willRender: function (camera) + { + return !(this.renderFlags !== 15 || this.list.length === 0 || (this.cameraFilter !== 0 && (this.cameraFilter & camera.id))); + }, + + /** + * Returns an array containing the display list index of either this Game Object, or if it has one, + * its parent Container. It then iterates up through all of the parent containers until it hits the + * root of the display list (which is index 0 in the returned array). + * + * Used internally by the InputPlugin but also useful if you wish to find out the display depth of + * this Game Object and all of its ancestors. + * + * @method Phaser.GameObjects.Layer#getIndexList + * @since 3.51.0 + * + * @return {number[]} An array of display list position indexes. + */ + getIndexList: function () + { + // eslint-disable-next-line consistent-this + var child = this; + var parent = this.parentContainer; + + var indexes = []; + + while (parent) + { + indexes.unshift(parent.getIndex(child)); + + child = parent; + + if (!parent.parentContainer) + { + break; + } + else + { + parent = parent.parentContainer; + } + } + + indexes.unshift(this.displayList.getIndex(child)); + + return indexes; + }, + + /** + * Internal method called from `List.addCallback`. + * + * @method Phaser.GameObjects.Layer#addChildCallback + * @private + * @fires Phaser.Scenes.Events#ADDED_TO_SCENE + * @fires Phaser.GameObjects.Events#ADDED_TO_SCENE + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the list. + */ + addChildCallback: function (gameObject) + { + var displayList = gameObject.displayList; + + if (displayList && displayList !== this) + { + gameObject.removeFromDisplayList(); + } + + if (!gameObject.displayList) + { + this.queueDepthSort(); + + gameObject.displayList = this; + + gameObject.emit(GameObjectEvents.ADDED_TO_SCENE, gameObject, this.scene); + + this.events.emit(SceneEvents.ADDED_TO_SCENE, gameObject, this.scene); + } + }, + + /** + * Internal method called from `List.removeCallback`. + * + * @method Phaser.GameObjects.Layer#removeChildCallback + * @private + * @fires Phaser.Scenes.Events#REMOVED_FROM_SCENE + * @fires Phaser.GameObjects.Events#REMOVED_FROM_SCENE + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the list. + */ + removeChildCallback: function (gameObject) + { + this.queueDepthSort(); + + gameObject.displayList = null; + + gameObject.emit(GameObjectEvents.REMOVED_FROM_SCENE, gameObject, this.scene); + + this.events.emit(SceneEvents.REMOVED_FROM_SCENE, gameObject, this.scene); + }, + + /** + * Force a sort of the display list on the next call to depthSort. + * + * @method Phaser.GameObjects.Layer#queueDepthSort + * @since 3.50.0 + */ + queueDepthSort: function () + { + this.sortChildrenFlag = true; + }, + + /** + * Immediately sorts the display list if the flag is set. + * + * @method Phaser.GameObjects.Layer#depthSort + * @since 3.50.0 + */ + depthSort: function () + { + if (this.sortChildrenFlag) + { + StableSort(this.list, this.sortByDepth); + + this.sortChildrenFlag = false; + } + }, + + /** + * Compare the depth of two Game Objects. + * + * @method Phaser.GameObjects.Layer#sortByDepth + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} childA - The first Game Object. + * @param {Phaser.GameObjects.GameObject} childB - The second Game Object. + * + * @return {number} The difference between the depths of each Game Object. + */ + sortByDepth: function (childA, childB) + { + return childA._depth - childB._depth; + }, + + /** + * Returns a reference to the array which contains all Game Objects in this Layer. + * + * This is a reference, not a copy of it, so be very careful not to mutate it. + * + * @method Phaser.GameObjects.Layer#getChildren + * @since 3.50.0 + * + * @return {Phaser.GameObjects.GameObject[]} An array of Game Objects within this Layer. + */ + getChildren: function () + { + return this.list; + }, + + /** + * Adds this Layer to the given Display List. + * + * If no Display List is specified, it will default to the Display List owned by the Scene to which + * this Layer belongs. + * + * A Layer can only exist on one Display List at any given time, but may move freely between them. + * + * If this Layer is already on another Display List when this method is called, it will first + * be removed from it, before being added to the new list. + * + * You can query which list it is on by looking at the `Phaser.GameObjects.Layer#displayList` property. + * + * If a Layer isn't on any display list, it will not be rendered. If you just wish to temporarily + * disable it from rendering, consider using the `setVisible` method, instead. + * + * @method Phaser.GameObjects.Layer#addToDisplayList + * @fires Phaser.Scenes.Events#ADDED_TO_SCENE + * @fires Phaser.GameObjects.Events#ADDED_TO_SCENE + * @since 3.60.0 + * + * @param {(Phaser.GameObjects.DisplayList|Phaser.GameObjects.Layer)} [displayList] - The Display List to add to. Defaults to the Scene Display List. + * + * @return {this} This Layer instance. + */ + addToDisplayList: function (displayList) + { + if (displayList === undefined) { displayList = this.scene.sys.displayList; } + + if (this.displayList && this.displayList !== displayList) + { + this.removeFromDisplayList(); + } + + // Don't repeat if it's already on this list + if (!displayList.exists(this)) + { + this.displayList = displayList; + + displayList.add(this, true); + + displayList.queueDepthSort(); + + this.emit(GameObjectEvents.ADDED_TO_SCENE, this, this.scene); + + displayList.events.emit(SceneEvents.ADDED_TO_SCENE, this, this.scene); + } + + return this; + }, + + /** + * Removes this Layer from the Display List it is currently on. + * + * A Layer can only exist on one Display List at any given time, but may move freely removed + * and added back at a later stage. + * + * You can query which list it is on by looking at the `Phaser.GameObjects.GameObject#displayList` property. + * + * If a Layer isn't on any Display List, it will not be rendered. If you just wish to temporarily + * disable it from rendering, consider using the `setVisible` method, instead. + * + * @method Phaser.GameObjects.Layer#removeFromDisplayList + * @fires Phaser.Scenes.Events#REMOVED_FROM_SCENE + * @fires Phaser.GameObjects.Events#REMOVED_FROM_SCENE + * @since 3.60.0 + * + * @return {this} This Layer instance. + */ + removeFromDisplayList: function () + { + var displayList = this.displayList || this.scene.sys.displayList; + + if (displayList.exists(this)) + { + displayList.remove(this, true); + + displayList.queueDepthSort(); + + this.displayList = null; + + this.emit(GameObjectEvents.REMOVED_FROM_SCENE, this, this.scene); + + displayList.events.emit(SceneEvents.REMOVED_FROM_SCENE, this, this.scene); + } + + return this; + }, + + /** + * Returns a reference to the underlying display list _array_ that contains this Game Object, + * which will be either the Scene's Display List or the internal list belonging + * to its parent Container, if it has one. + * + * If this Game Object is not on a display list or in a container, it will return `null`. + * + * You should be very careful with this method, and understand that it returns a direct reference to the + * internal array used by the Display List. Mutating this array directly can cause all kinds of subtle + * and difficult to debug issues in your game. + * + * @method Phaser.GameObjects.Layer#getDisplayList + * @since 3.88.0 + * + * @return {?Phaser.GameObjects.GameObject[]} The internal Display List array of Game Objects, or `null`. + */ + getDisplayList: function () + { + var list = null; + + if (this.parentContainer) + { + list = this.parentContainer.list; + } + else if (this.displayList) + { + list = this.displayList.list; + } + + return list; + }, + + /** + * Destroys this Layer removing it from the Display List and Update List and + * severing all ties to parent resources. + * + * Also destroys all children of this Layer. If you do not wish for the + * children to be destroyed, you should move them from this Layer first. + * + * Use this to remove this Layer from your game if you don't ever plan to use it again. + * As long as no reference to it exists within your own code it should become free for + * garbage collection by the browser. + * + * If you just want to temporarily disable an object then look at using the + * Game Object Pool instead of destroying it, as destroyed objects cannot be resurrected. + * + * @method Phaser.GameObjects.Layer#destroy + * @fires Phaser.GameObjects.Events#DESTROY + * @since 3.50.0 + * + * @param {boolean} [fromScene=false] - `True` if this Game Object is being destroyed by the Scene, `false` if not. + */ + destroy: function (fromScene) + { + // This Game Object has already been destroyed + if (!this.scene || this.ignoreDestroy) + { + return; + } + + this.emit(GameObjectEvents.DESTROY, this); + + var list = this.list; + + while (list.length) + { + list[0].destroy(fromScene); + } + + this.removeAllListeners(); + + if (this.displayList) + { + this.displayList.remove(this, true, false); + + this.displayList.queueDepthSort(); + } + + if (this.data) + { + this.data.destroy(); + + this.data = undefined; + } + + if (this.filterCamera) + { + this.filterCamera.destroy(); + + this.filterCamera = undefined; + } + + this.active = false; + this.visible = false; + + this.list = undefined; + this.scene = undefined; + this.displayList = undefined; + this.systems = undefined; + this.events = undefined; + } + + /** + * Return an array listing the events for which the emitter has registered listeners. + * + * @method Phaser.GameObjects.Layer#eventNames + * @since 3.50.0 + * + * @return {Array.} + */ + + /** + * Return the listeners registered for a given event. + * + * @method Phaser.GameObjects.Layer#listeners + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * + * @return {Function[]} The registered listeners. + */ + + /** + * Return the number of listeners listening to a given event. + * + * @method Phaser.GameObjects.Layer#listenerCount + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * + * @return {number} The number of listeners. + */ + + /** + * Calls each of the listeners registered for a given event. + * + * @method Phaser.GameObjects.Layer#emit + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * @param {...*} [args] - Additional arguments that will be passed to the event handler. + * + * @return {boolean} `true` if the event had listeners, else `false`. + */ + + /** + * Add a listener for a given event. + * + * @method Phaser.GameObjects.Layer#on + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} fn - The listener function. + * @param {*} [context=this] - The context to invoke the listener with. + * + * @return {this} This Layer instance. + */ + + /** + * Add a listener for a given event. + * + * @method Phaser.GameObjects.Layer#addListener + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} fn - The listener function. + * @param {*} [context=this] - The context to invoke the listener with. + * + * @return {this} This Layer instance. + */ + + /** + * Add a one-time listener for a given event. + * + * @method Phaser.GameObjects.Layer#once + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} fn - The listener function. + * @param {*} [context=this] - The context to invoke the listener with. + * + * @return {this} This Layer instance. + */ + + /** + * Remove the listeners of a given event. + * + * @method Phaser.GameObjects.Layer#removeListener + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} [fn] - Only remove the listeners that match this function. + * @param {*} [context] - Only remove the listeners that have this context. + * @param {boolean} [once] - Only remove one-time listeners. + * + * @return {this} This Layer instance. + */ + + /** + * Remove the listeners of a given event. + * + * @method Phaser.GameObjects.Layer#off + * @since 3.50.0 + * + * @param {(string|symbol)} event - The event name. + * @param {function} [fn] - Only remove the listeners that match this function. + * @param {*} [context] - Only remove the listeners that have this context. + * @param {boolean} [once] - Only remove one-time listeners. + * + * @return {this} This Layer instance. + */ + + /** + * Remove all listeners, or those of the specified event. + * + * @method Phaser.GameObjects.Layer#removeAllListeners + * @since 3.50.0 + * + * @param {(string|symbol)} [event] - The event name. + * + * @return {this} This Layer instance. + */ + +}); + +module.exports = Layer; + + +/***/ }), + +/***/ 2956: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Layer#renderCanvas + * @since 3.50.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Layer} layer - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + */ +var LayerCanvasRenderer = function (renderer, layer, camera) +{ + var children = layer.list; + + if (children.length === 0) + { + return; + } + + layer.depthSort(); + + var layerHasBlendMode = (layer.blendMode !== -1); + + if (!layerHasBlendMode) + { + // If Layer is SKIP_TEST then set blend mode to be Normal + renderer.setBlendMode(0); + } + + var alpha = layer._alpha; + + if (layer.mask) + { + layer.mask.preRenderCanvas(renderer, null, camera); + } + + for (var i = 0; i < children.length; i++) + { + var child = children[i]; + + if (!child.willRender(camera)) + { + continue; + } + + var childAlpha = child.alpha; + + if (!layerHasBlendMode && child.blendMode !== renderer.currentBlendMode) + { + // If Layer doesn't have its own blend mode, then a child can have one + renderer.setBlendMode(child.blendMode); + } + + // Set parent values + child.setAlpha(childAlpha * alpha); + + // Render + child.renderCanvas(renderer, child, camera); + + // Restore original values + child.setAlpha(childAlpha); + } + + if (layer.mask) + { + layer.mask.postRenderCanvas(renderer); + } +}; + +module.exports = LayerCanvasRenderer; + + +/***/ }), + +/***/ 25179: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var Layer = __webpack_require__(93595); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); + +/** + * Creates a new Layer Game Object and returns it. + * + * Note: This method will only be available if the Layer Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#layer + * @since 3.50.0 + * + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Layer} The Game Object that was created. + */ +GameObjectCreator.register('layer', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var children = GetAdvancedValue(config, 'children', null); + + var layer = new Layer(this.scene, children); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, layer, config); + + return layer; +}); + + +/***/ }), + +/***/ 20005: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Layer = __webpack_require__(93595); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Layer Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Layer Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#layer + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} [children] - An optional array of Game Objects to add to this Layer. + * + * @return {Phaser.GameObjects.Layer} The Game Object that was created. + */ +GameObjectFactory.register('layer', function (children) +{ + return this.displayList.add(new Layer(this.scene, children)); +}); + + +/***/ }), + +/***/ 33963: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(15869); +} + +if (true) +{ + renderCanvas = __webpack_require__(2956); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 15869: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(8054); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Layer#renderWebGL + * @since 3.50.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Layer} layer - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + * @param {number} renderStep - The index of this function in the Game Object's list of render processes. Used to support multiple rendering functions. + * * @param {Phaser.GameObjects.GameObject[]} displayList - The display list which is currently being rendered. + * @param {number} displayListIndex - The index of the Game Object within the display list. + */ +var LayerWebGLRenderer = function (renderer, layer, drawingContext, parentMatrix, renderStep, displayList, displayListIndex) +{ + var children = layer.list; + var childCount = children.length; + + if (childCount === 0) + { + return; + } + + var currentContext = drawingContext; + var camera = currentContext.camera; + + layer.depthSort(); + + var layerHasBlendMode = (layer.blendMode !== CONST.BlendModes.SKIP_CHECK); + + if (!layerHasBlendMode && currentContext.blendMode !== 0) + { + // If Layer is SKIP_TEST then set blend mode to be Normal + currentContext = currentContext.getClone(); + currentContext.setBlendMode(0); + currentContext.use(); + } + + var alpha = layer.alpha; + + for (var i = 0; i < childCount; i++) + { + var child = children[i]; + + if (!child.willRender(camera)) + { + continue; + } + + var childAlphaTopLeft; + var childAlphaTopRight; + var childAlphaBottomLeft; + var childAlphaBottomRight; + + if (child.alphaTopLeft !== undefined) + { + childAlphaTopLeft = child.alphaTopLeft; + childAlphaTopRight = child.alphaTopRight; + childAlphaBottomLeft = child.alphaBottomLeft; + childAlphaBottomRight = child.alphaBottomRight; + } + else + { + var childAlpha = child.alpha; + + childAlphaTopLeft = childAlpha; + childAlphaTopRight = childAlpha; + childAlphaBottomLeft = childAlpha; + childAlphaBottomRight = childAlpha; + } + + if ( + !layerHasBlendMode && + child.blendMode !== currentContext.blendMode && + child.blendMode !== CONST.BlendModes.SKIP_CHECK + ) + { + // If Layer doesn't have its own blend mode, then a child can have one + currentContext = currentContext.getClone(); + currentContext.setBlendMode(child.blendMode); + currentContext.use(); + } + + child.setAlpha(childAlphaTopLeft * alpha, childAlphaTopRight * alpha, childAlphaBottomLeft * alpha, childAlphaBottomRight * alpha); + + // Render + child.renderWebGLStep(renderer, child, currentContext, undefined, undefined, displayList, displayListIndex); + + // Restore original values + child.setAlpha(childAlphaTopLeft, childAlphaTopRight, childAlphaBottomLeft, childAlphaBottomRight); + } + + // Release any remaining context. + if (currentContext !== drawingContext) + { + currentContext.release(); + } +}; + +module.exports = LayerWebGLRenderer; + + +/***/ }), + +/***/ 41432: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circle = __webpack_require__(96503); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var RGB = __webpack_require__(51767); +var Utils = __webpack_require__(70554); + +/** + * @classdesc + * A 2D Light. + * + * These are created by the {@link Phaser.GameObjects.LightsManager}, available from within a scene via `this.lights`. + * + * Any Game Objects with the Lighting Component, and `setLighting(true)`, + * will then be affected by these Lights. + * If they have a normal map, it will be used. + * If they don't, the Lights will use the default normal map, a flat surface. + * + * They can also simply be used to represent a point light for your own purposes. + * + * Lights cannot be added to Containers. They are designed to exist in the root of a Scene. + * + * @class Light + * @extends Phaser.Geom.Circle + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Visible + * + * @param {number} x - The horizontal position of the light. + * @param {number} y - The vertical position of the light. + * @param {number} radius - The radius of the light. + * @param {number} r - The red color of the light. A value between 0 and 1. + * @param {number} g - The green color of the light. A value between 0 and 1. + * @param {number} b - The blue color of the light. A value between 0 and 1. + * @param {number} intensity - The intensity of the light. + * @param {number} [z] - The z position of the light. If not given, it will be set to `radius * 0.1`. + */ +var Light = new Class({ + + Extends: Circle, + + Mixins: [ + Components.Origin, + Components.ScrollFactor, + Components.Visible + ], + + initialize: + + function Light (x, y, radius, r, g, b, intensity, z) + { + Circle.call(this, x, y, radius); + + /** + * The color of the light. + * + * @name Phaser.GameObjects.Light#color + * @type {Phaser.Display.RGB} + * @since 3.50.0 + */ + this.color = new RGB(r, g, b); + + /** + * The intensity of the light. + * + * @name Phaser.GameObjects.Light#intensity + * @type {number} + * @since 3.50.0 + */ + this.intensity = intensity; + + /** + * The z position of the light. + * This affects the relief effect created by the light. + * A higher value will make the light appear more raised. + * + * Lit game objects are considered to be at z=0. + * Thus, if z is larger than the radius of the light, + * the light will not affect them. + * Strong values are in the range of 0 to radius/2. + * + * This is not a true position, and won't be affected by + * perspective or camera position. It won't be set by `setTo`. + * Use `setZ` to set it, or `setZNormal` to set it to a fraction + * of the radius. + * + * @name Phaser.GameObjects.Light#z + * @type {number} + * @since 4.0.0 + */ + this.z = z === undefined ? radius * 0.1 : z; + + /** + * The flags that are compared against `RENDER_MASK` to determine if this Game Object will render or not. + * The bits are 0001 | 0010 | 0100 | 1000 set by the components Visible, Alpha, Transform and Texture respectively. + * If those components are not used by your custom class then you can use this bitmask as you wish. + * + * @name Phaser.GameObjects.Light#renderFlags + * @type {number} + * @default 15 + * @since 3.0.0 + */ + this.renderFlags = 15; + + /** + * A bitmask that controls if this Game Object is drawn by a Camera or not. + * Not usually set directly, instead call `Camera.ignore`, however you can + * set this property directly using the Camera.id property: + * + * @example + * this.cameraFilter |= camera.id + * + * @name Phaser.GameObjects.Light#cameraFilter + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.cameraFilter = 0; + + this.setScrollFactor(1, 1); + this.setOrigin(); + this.setDisplayOrigin(radius); + }, + + /** + * The width of this Light Game Object. This is the same as `Light.diameter`. + * + * @name Phaser.GameObjects.Light#displayWidth + * @type {number} + * @since 3.60.0 + */ + displayWidth: { + + get: function () + { + return this.diameter; + }, + + set: function (value) + { + this.diameter = value; + } + + }, + + /** + * The height of this Light Game Object. This is the same as `Light.diameter`. + * + * @name Phaser.GameObjects.Light#displayHeight + * @type {number} + * @since 3.60.0 + */ + displayHeight: { + + get: function () + { + return this.diameter; + }, + + set: function (value) + { + this.diameter = value; + } + + }, + + /** + * The width of this Light Game Object. This is the same as `Light.diameter`. + * + * @name Phaser.GameObjects.Light#width + * @type {number} + * @since 3.60.0 + */ + width: { + + get: function () + { + return this.diameter; + }, + + set: function (value) + { + this.diameter = value; + } + + }, + + /** + * The height of this Light Game Object. This is the same as `Light.diameter`. + * + * @name Phaser.GameObjects.Light#height + * @type {number} + * @since 3.60.0 + */ + height: { + + get: function () + { + return this.diameter; + }, + + set: function (value) + { + this.diameter = value; + } + + }, + + /** + * The z position of the light, as a fraction of the radius. + * This affects the relief effect created by the light. + * A higher value will make the light appear more raised. + * Strong values are in the range of 0 to 0.5. + * + * @name Phaser.GameObjects.Light#zNormal + * @type {number} + * @since 4.0.0 + */ + zNormal: { + get: function () + { + return this.z / this.radius; + }, + + set: function (value) + { + this.z = value * this.radius; + } + }, + + /** + * Compares the renderMask with the renderFlags to see if this Game Object will render or not. + * Also checks the Game Object against the given Cameras exclusion list. + * + * @method Phaser.GameObjects.Light#willRender + * @since 3.50.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to check against this Game Object. + * + * @return {boolean} True if the Game Object should be rendered, otherwise false. + */ + willRender: function (camera) + { + return !(Light.RENDER_MASK !== this.renderFlags || (this.cameraFilter !== 0 && (this.cameraFilter & camera.id))); + }, + + /** + * Set the color of the light from a single integer RGB value. + * + * @method Phaser.GameObjects.Light#setColor + * @since 3.0.0 + * + * @param {number} rgb - The integer RGB color of the light. + * + * @return {this} This Light object. + */ + setColor: function (rgb) + { + var color = Utils.getFloatsFromUintRGB(rgb); + + this.color.set(color[0], color[1], color[2]); + + return this; + }, + + /** + * Set the intensity of the light. + * + * @method Phaser.GameObjects.Light#setIntensity + * @since 3.0.0 + * + * @param {number} intensity - The intensity of the light. + * + * @return {this} This Light object. + */ + setIntensity: function (intensity) + { + this.intensity = intensity; + + return this; + }, + + /** + * Set the radius of the light. + * + * @method Phaser.GameObjects.Light#setRadius + * @since 3.0.0 + * + * @param {number} radius - The radius of the light. + * + * @return {this} This Light object. + */ + setRadius: function (radius) + { + this.radius = radius; + + return this; + }, + + /** + * Set the z position of the light. + * + * @method Phaser.GameObjects.Light#setZ + * @since 4.0.0 + * + * @param {number} z - The z position of the light. + * + * @return {this} This Light object. + */ + setZ: function (z) + { + this.z = z; + + return this; + }, + + /** + * Set the z position of the light as a fraction of the radius. + * This affects the relief effect created by the light. + * A higher value will make the light appear more raised. + * Strong values are in the range of 0 to 0.5. + * + * @method Phaser.GameObjects.Light#setZNormal + * @since 4.0.0 + * + * @param {number} z - The normalized z position of the light. + * + * @return {this} This Light object. + */ + setZNormal: function (z) + { + this.z = z * this.radius; + + return this; + } + +}); + +/** + * The bitmask that `GameObject.renderFlags` is compared against to determine if the Game Object will render or not. + * + * @constant {number} RENDER_MASK + * @memberof Phaser.GameObjects.Light + * @default + */ +Light.RENDER_MASK = 15; + +module.exports = Light; + + +/***/ }), + +/***/ 61356: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CircleToRectangle = __webpack_require__(81491); +var Class = __webpack_require__(83419); +var DistanceBetween = __webpack_require__(20339); +var Light = __webpack_require__(41432); +var PointLight = __webpack_require__(80321); +var RGB = __webpack_require__(51767); +var SpliceOne = __webpack_require__(19133); +var StableSort = __webpack_require__(19186); +var Utils = __webpack_require__(70554); + +/** + * @callback LightForEach + * + * @param {Phaser.GameObjects.Light} light - The Light. + */ + +/** + * @classdesc + * Manages Lights for a Scene. + * + * Affects the rendering of Game Objects with `lighting` enabled. + * + * @class LightsManager + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + */ +var LightsManager = new Class({ + + initialize: + + function LightsManager () + { + /** + * The Lights in the Scene. + * + * @name Phaser.GameObjects.LightsManager#lights + * @type {Phaser.GameObjects.Light[]} + * @default [] + * @since 3.0.0 + */ + this.lights = []; + + /** + * The ambient color. + * + * @name Phaser.GameObjects.LightsManager#ambientColor + * @type {Phaser.Display.RGB} + * @since 3.50.0 + */ + this.ambientColor = new RGB(0.1, 0.1, 0.1); + + /** + * Whether the Lights Manager is enabled. + * + * @name Phaser.GameObjects.LightsManager#active + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.active = false; + + /** + * The maximum number of lights that a single Camera and the lights shader can process. + * Change this via the `maxLights` property in your game config, as it cannot be changed at runtime. + * + * @name Phaser.GameObjects.LightsManager#maxLights + * @type {number} + * @readonly + * @since 3.15.0 + */ + this.maxLights = -1; + + /** + * The number of lights processed in the _previous_ frame. + * + * @name Phaser.GameObjects.LightsManager#visibleLights + * @type {number} + * @readonly + * @since 3.50.0 + */ + this.visibleLights = 0; + }, + + /** + * Creates a new Point Light Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Point Light Game Object has been built into Phaser. + * + * The Point Light Game Object provides a way to add a point light effect into your game, + * without the expensive shader processing requirements of the traditional Light Game Object. + * + * The difference is that the Point Light renders using a custom shader, designed to give the + * impression of a point light source, of variable radius, intensity and color, in your game. + * However, unlike the Light Game Object, it does not impact any other Game Objects, or use their + * normal maps for calcuations. This makes them extremely fast to render compared to Lights + * and perfect for special effects, such as flickering torches or muzzle flashes. + * + * For maximum performance you should batch Point Light Game Objects together. This means + * ensuring they follow each other consecutively on the display list. Ideally, use a Layer + * Game Object and then add just Point Lights to it, so that it can batch together the rendering + * of the lights. You don't _have_ to do this, and if you've only a handful of Point Lights in + * your game then it's perfectly safe to mix them into the display list as normal. However, if + * you're using a large number of them, please consider how they are mixed into the display list. + * + * The renderer will automatically cull Point Lights. Those with a radius that does not intersect + * with the Camera will be skipped in the rendering list. This happens automatically and the + * culled state is refreshed every frame, for every camera. + * + * The origin of a Point Light is always 0.5 and it cannot be changed. + * + * Point Lights are a WebGL only feature and do not have a Canvas counterpart. + * + * @method Phaser.GameObjects.LightsManager#addPointLight + * @since 3.50.0 + * + * @param {number} x - The horizontal position of this Point Light in the world. + * @param {number} y - The vertical position of this Point Light in the world. + * @param {number} [color=0xffffff] - The color of the Point Light, given as a hex value. + * @param {number} [radius=128] - The radius of the Point Light. + * @param {number} [intensity=1] - The intensity, or color blend, of the Point Light. + * @param {number} [attenuation=0.1] - The attenuation of the Point Light. This is the reduction of light from the center point. + * + * @return {Phaser.GameObjects.PointLight} The Game Object that was created. + */ + addPointLight: function (x, y, color, radius, intensity, attenuation) + { + return this.systems.displayList.add(new PointLight(this.scene, x, y, color, radius, intensity, attenuation)); + }, + + /** + * Enable the Lights Manager. + * + * @method Phaser.GameObjects.LightsManager#enable + * @since 3.0.0 + * + * @return {this} This Lights Manager instance. + */ + enable: function () + { + if (this.maxLights === -1) + { + this.maxLights = this.systems.renderer.config.maxLights; + } + + this.active = true; + + return this; + }, + + /** + * Disable the Lights Manager. + * + * @method Phaser.GameObjects.LightsManager#disable + * @since 3.0.0 + * + * @return {this} This Lights Manager instance. + */ + disable: function () + { + this.active = false; + + return this; + }, + + /** + * Get all lights that can be seen by the given Camera. + * + * It will automatically cull lights that are outside the world view of the Camera. + * + * If more lights are returned than supported by the renderer, the lights are then culled + * based on the distance from the center of the camera. Only those closest are rendered. + * + * @method Phaser.GameObjects.LightsManager#getLights + * @since 3.50.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to cull Lights for. + * + * @return {Phaser.GameObjects.Light[]} The culled Lights. + */ + getLights: function (camera) + { + var lights = this.lights; + var worldView = camera.worldView; + + var visibleLights = []; + + for (var i = 0; i < lights.length; i++) + { + var light = lights[i]; + + if (light.willRender(camera) && CircleToRectangle(light, worldView)) + { + visibleLights.push({ + light: light, + distance: DistanceBetween(light.x, light.y, worldView.centerX, worldView.centerY) + }); + } + } + + if (visibleLights.length > this.maxLights) + { + // We've got too many lights, so sort by distance from camera and cull those far away + // This isn't ideal because it doesn't factor in the radius of the lights, but it'll do for now + // and is significantly better than we had before! + + StableSort(visibleLights, this.sortByDistance); + + visibleLights = visibleLights.slice(0, this.maxLights); + } + + this.visibleLights = visibleLights.length; + + return visibleLights; + }, + + sortByDistance: function (a, b) + { + return (a.distance >= b.distance); + }, + + /** + * Set the ambient light color. + * + * @method Phaser.GameObjects.LightsManager#setAmbientColor + * @since 3.0.0 + * + * @param {number} rgb - The integer RGB color of the ambient light. + * + * @return {this} This Lights Manager instance. + */ + setAmbientColor: function (rgb) + { + var color = Utils.getFloatsFromUintRGB(rgb); + + this.ambientColor.set(color[0], color[1], color[2]); + + return this; + }, + + /** + * Returns the maximum number of Lights allowed to appear at once. + * + * @method Phaser.GameObjects.LightsManager#getMaxVisibleLights + * @since 3.0.0 + * + * @return {number} The maximum number of Lights allowed to appear at once. + */ + getMaxVisibleLights: function () + { + return this.maxLights; + }, + + /** + * Get the number of Lights managed by this Lights Manager. + * + * @method Phaser.GameObjects.LightsManager#getLightCount + * @since 3.0.0 + * + * @return {number} The number of Lights managed by this Lights Manager. + */ + getLightCount: function () + { + return this.lights.length; + }, + + /** + * Add a Light. + * + * @method Phaser.GameObjects.LightsManager#addLight + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal position of the Light. + * @param {number} [y=0] - The vertical position of the Light. + * @param {number} [radius=128] - The radius of the Light. + * @param {number} [rgb=0xffffff] - The integer RGB color of the light. + * @param {number} [intensity=1] - The intensity of the Light. + * @param {number} [z] - The z position of the light. If omitted, it will be set to `radius * 0.1`. + * + * @return {Phaser.GameObjects.Light} The Light that was added. + */ + addLight: function (x, y, radius, rgb, intensity, z) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (radius === undefined) { radius = 128; } + if (rgb === undefined) { rgb = 0xffffff; } + if (intensity === undefined) { intensity = 1; } + if (z === undefined) { z = radius * 0.1; } + + var color = Utils.getFloatsFromUintRGB(rgb); + + var light = new Light(x, y, radius, color[0], color[1], color[2], intensity, z); + + this.lights.push(light); + + return light; + }, + + /** + * Remove a Light. + * + * @method Phaser.GameObjects.LightsManager#removeLight + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Light} light - The Light to remove. + * + * @return {this} This Lights Manager instance. + */ + removeLight: function (light) + { + var index = this.lights.indexOf(light); + + if (index >= 0) + { + SpliceOne(this.lights, index); + } + + return this; + }, + + /** + * Shut down the Lights Manager. + * + * Recycles all active Lights into the Light pool, resets ambient light color and clears the lists of Lights and + * culled Lights. + * + * @method Phaser.GameObjects.LightsManager#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + this.lights.length = 0; + }, + + /** + * Destroy the Lights Manager. + * + * Cleans up all references by calling {@link Phaser.GameObjects.LightsManager#shutdown}. + * + * @method Phaser.GameObjects.LightsManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + } + +}); + +module.exports = LightsManager; + + +/***/ }), + +/***/ 88992: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var LightsManager = __webpack_require__(61356); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * A Scene plugin that provides a {@link Phaser.GameObjects.LightsManager} for rendering objects with dynamic lighting. + * + * Available from within a Scene via `this.lights`. + * + * Add Lights using the {@link Phaser.GameObjects.LightsManager#addLight} method: + * + * ```javascript + * // Enable the Lights Manager because it is disabled by default + * this.lights.enable(); + * + * // Create a Light at [400, 300] with a radius of 200 + * this.lights.addLight(400, 300, 200); + * ``` + * + * For Game Objects to be affected by the Lights when rendered, you will need to set them to use lighting like so: + * + * ```javascript + * sprite.setLighting(true); + * ``` + * + * @class LightsPlugin + * @extends Phaser.GameObjects.LightsManager + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that this Lights Plugin belongs to. + */ +var LightsPlugin = new Class({ + + Extends: LightsManager, + + initialize: + + function LightsPlugin (scene) + { + /** + * A reference to the Scene that this Lights Plugin belongs to. + * + * @name Phaser.GameObjects.LightsPlugin#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene's systems. + * + * @name Phaser.GameObjects.LightsPlugin#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + if (!scene.sys.settings.isBooted) + { + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + } + + LightsManager.call(this); + }, + + /** + * Boot the Lights Plugin. + * + * @method Phaser.GameObjects.LightsPlugin#boot + * @since 3.0.0 + */ + boot: function () + { + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.SHUTDOWN, this.shutdown, this); + eventEmitter.on(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * Destroy the Lights Plugin. + * + * Cleans up all references. + * + * @method Phaser.GameObjects.LightsPlugin#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.scene = undefined; + this.systems = undefined; + } + +}); + +PluginCache.register('LightsPlugin', LightsPlugin, 'lights'); + +module.exports = LightsPlugin; + + +/***/ }), + +/***/ 28103: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultNineSliceNodes = __webpack_require__(30529); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var NineSliceRender = __webpack_require__(78023); +var Vertex = __webpack_require__(82513); + +/** + * @classdesc + * A Nine Slice Game Object allows you to display a texture-based object that + * can be stretched both horizontally and vertically, but that retains + * fixed-sized corners. The dimensions of the corners are set via the + * parameters to this class. + * + * This is extremely useful for UI and button like elements, where you need + * them to expand to accommodate the content without distorting the texture. + * + * The texture you provide for this Game Object should be based on the + * following layout structure: + * + * ``` + * A B + * +---+----------------------+---+ + * C | 1 | 2 | 3 | + * +---+----------------------+---+ + * | | | | + * | 4 | 5 | 6 | + * | | | | + * +---+----------------------+---+ + * D | 7 | 8 | 9 | + * +---+----------------------+---+ + * ``` + * + * When changing this objects width and / or height: + * + * areas 1, 3, 7 and 9 (the corners) will remain unscaled + * areas 2 and 8 will be stretched horizontally only + * areas 4 and 6 will be stretched vertically only + * area 5 will be stretched both horizontally and vertically + * + * You can also create a 3 slice Game Object: + * + * This works in a similar way, except you can only stretch it horizontally. + * Therefore, it requires less configuration: + * + * ``` + * A B + * +---+----------------------+---+ + * | | | | + * C | 1 | 2 | 3 | + * | | | | + * +---+----------------------+---+ + * ``` + * + * When changing this objects width (you cannot change its height) + * + * areas 1 and 3 will remain unscaled + * area 2 will be stretched horizontally + * + * The above configuration concept is adapted from the Pixi NineSlicePlane. + * + * To specify a 3 slice object instead of a 9 slice you should only + * provide the `leftWidth` and `rightWidth` parameters. To create a 9 slice + * you must supply all parameters. + * + * The _minimum_ width this Game Object can be is the total of + * `leftWidth` + `rightWidth`. The _minimum_ height this Game Object + * can be is the total of `topHeight` + `bottomHeight`. + * If you need to display this object at a smaller size, you can scale it. + * + * In terms of performance, using a 3 slice Game Object is the equivalent of + * having 3 Sprites in a row. Using a 9 slice Game Object is the equivalent + * of having 9 Sprites in a row. The vertices of this object are all batched + * together and can co-exist with other Sprites and graphics on the display + * list, without incurring any additional overhead. + * + * As of Phaser 3.60 this Game Object is WebGL only. + * + * As of Phaser 3.70 this Game Object can now populate its values automatically + * if they have been set within Texture Packer 7.1.0 or above and exported with + * the atlas json. If this is the case, you can just call this method without + * specifying anything more than the texture key and frame and it will pull the + * area data from the atlas. + * + * This object does not support trimmed textures from Texture Packer. + * Trimming interferes with the ability to stretch the texture correctly. + * + * @class NineSlice + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.60.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of the center of this Game Object in the world. + * @param {number} y - The vertical position of the center of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * @param {number} [width=256] - The width of the Nine Slice Game Object. You can adjust the width post-creation. + * @param {number} [height=256] - The height of the Nine Slice Game Object. If this is a 3 slice object the height will be fixed to the height of the texture and cannot be changed. + * @param {number} [leftWidth=10] - The size of the left vertical column (A). + * @param {number} [rightWidth=10] - The size of the right vertical column (B). + * @param {number} [topHeight=0] - The size of the top horizontal row (C). Set to zero or undefined to create a 3 slice object. + * @param {number} [bottomHeight=0] - The size of the bottom horizontal row (D). Set to zero or undefined to create a 3 slice object. + */ +var NineSlice = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.GetBounds, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.Texture, + Components.Transform, + Components.Visible, + NineSliceRender + ], + + initialize: + + function NineSlice (scene, x, y, texture, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight) + { + // if (width === undefined) { width = 256; } + // if (height === undefined) { height = 256; } + + // if (leftWidth === undefined) { leftWidth = 10; } + // if (rightWidth === undefined) { rightWidth = 10; } + // if (topHeight === undefined) { topHeight = 0; } + // if (bottomHeight === undefined) { bottomHeight = 0; } + + GameObject.call(this, scene, 'NineSlice'); + + /** + * Internal width value. Do not modify this property directly. + * + * @name Phaser.GameObjects.NineSlice#_width + * @private + * @type {number} + * @since 3.60.0 + */ + this._width; + + /** + * Internal height value. Do not modify this property directly. + * + * @name Phaser.GameObjects.NineSlice#_height + * @private + * @type {number} + * @since 3.60.0 + */ + this._height; + + /** + * Internal originX value. Do not modify this property directly. + * + * @name Phaser.GameObjects.NineSlice#_originX + * @private + * @type {number} + * @since 3.60.0 + */ + this._originX = 0.5; + + /** + * Internal originY value. Do not modify this property directly. + * + * @name Phaser.GameObjects.NineSlice#_originY + * @private + * @type {number} + * @since 3.60.0 + */ + this._originY = 0.5; + + /** + * Internal component value. Do not modify this property directly. + * + * @name Phaser.GameObjects.NineSlice#_sizeComponent + * @private + * @type {boolean} + * @since 3.60.0 + */ + this._sizeComponent = true; + + /** + * An array of Vertex objects that correspond to the quads that make-up + * this Nine Slice Game Object. They are stored in the following order: + * + * Top Left - Indexes 0 - 5 + * Top Center - Indexes 6 - 11 + * Top Right - Indexes 12 - 17 + * Center Left - Indexes 18 - 23 + * Center - Indexes 24 - 29 + * Center Right - Indexes 30 - 35 + * Bottom Left - Indexes 36 - 41 + * Bottom Center - Indexes 42 - 47 + * Bottom Right - Indexes 48 - 53 + * + * Each quad is represented by 6 Vertex instances. + * + * This array will contain 18 elements for a 3 slice object + * and 54 for a nine slice object. + * + * You should never modify this array once it has been populated. + * + * @name Phaser.GameObjects.NineSlice#vertices + * @type {Phaser.GameObjects.NineSliceVertex[]} + * @since 3.60.0 + */ + this.vertices = []; + + /** + * The size of the left vertical bar (A). + * + * @name Phaser.GameObjects.NineSlice#leftWidth + * @type {number} + * @readonly + * @since 3.60.0 + */ + this.leftWidth; + + /** + * The size of the right vertical bar (B). + * + * @name Phaser.GameObjects.NineSlice#rightWidth + * @type {number} + * @readonly + * @since 3.60.0 + */ + this.rightWidth; + + /** + * The size of the top horizontal bar (C). + * + * If this is a 3 slice object this property will be set to the + * height of the texture being used. + * + * @name Phaser.GameObjects.NineSlice#topHeight + * @type {number} + * @readonly + * @since 3.60.0 + */ + this.topHeight; + + /** + * The size of the bottom horizontal bar (D). + * + * If this is a 3 slice object this property will be set to zero. + * + * @name Phaser.GameObjects.NineSlice#bottomHeight + * @type {number} + * @readonly + * @since 3.60.0 + */ + this.bottomHeight; + + /** + * The tint value being applied to the top-left vertice of the Game Object. + * This value is interpolated from the corner to the center of the Game Object. + * The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple. + * + * @name Phaser.GameObjects.NineSlice#tint + * @type {number} + * @default 0xffffff + * @since 3.60.0 + */ + this.tint = 0xffffff; + + /** + * The tint fill mode. + * + * `false` = An additive tint (the default), where vertices colors are blended with the texture. + * `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha. + * + * @name Phaser.GameObjects.NineSlice#tintFill + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.tintFill = false; + + var textureFrame = scene.textures.getFrame(texture, frame); + + /** + * This property is `true` if this Nine Slice Game Object was configured + * with just `leftWidth` and `rightWidth` values, making it a 3-slice + * instead of a 9-slice object. + * + * @name Phaser.GameObjects.NineSlice#is3Slice + * @type {boolean} + * @since 3.60.0 + */ + this.is3Slice = (!topHeight && !bottomHeight); + + if (textureFrame && textureFrame.scale9) + { + // If we're using the scale9 data from the frame, override the values from above + this.is3Slice = textureFrame.is3Slice; + } + + var size = this.is3Slice ? 18 : 54; + + for (var i = 0; i < size; i++) + { + this.vertices.push(new Vertex()); + } + + this.setPosition(x, y); + + this.setTexture(texture, frame); + + this.setSlices(width, height, leftWidth, rightWidth, topHeight, bottomHeight, false); + + this.updateDisplayOrigin(); + + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.NineSlice#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultNineSliceNodes; + } + }, + + /** + * Resets the width, height and slices for this NineSlice Game Object. + * + * This allows you to modify the texture being used by this object and then reset the slice configuration, + * to avoid having to destroy this Game Object in order to use it for a different game element. + * + * Please note that you cannot change a 9-slice to a 3-slice or vice versa. + * + * @method Phaser.GameObjects.NineSlice#setSlices + * @since 3.60.0 + * + * @param {number} [width=256] - The width of the Nine Slice Game Object. You can adjust the width post-creation. + * @param {number} [height=256] - The height of the Nine Slice Game Object. If this is a 3 slice object the height will be fixed to the height of the texture and cannot be changed. + * @param {number} [leftWidth=10] - The size of the left vertical column (A). + * @param {number} [rightWidth=10] - The size of the right vertical column (B). + * @param {number} [topHeight=0] - The size of the top horizontal row (C). Set to zero or undefined to create a 3 slice object. + * @param {number} [bottomHeight=0] - The size of the bottom horizontal row (D). Set to zero or undefined to create a 3 slice object. + * @param {boolean} [skipScale9=false] -If this Nine Slice was created from Texture Packer scale9 atlas data, set this property to use the given column sizes instead of those specified in the JSON. + * + * @return {this} This Game Object instance. + */ + setSlices: function (width, height, leftWidth, rightWidth, topHeight, bottomHeight, skipScale9) + { + if (leftWidth === undefined) { leftWidth = 10; } + if (rightWidth === undefined) { rightWidth = 10; } + if (topHeight === undefined) { topHeight = 0; } + if (bottomHeight === undefined) { bottomHeight = 0; } + + if (skipScale9 === undefined) { skipScale9 = false; } + + var frame = this.frame; + + var sliceChange = false; + + if (this.is3Slice && skipScale9 && topHeight !== 0 && bottomHeight !== 0) + { + sliceChange = true; + } + + if (sliceChange) + { + console.warn('Cannot change 9 slice to 3 slice'); + } + else + { + if (frame && frame.scale9 && !skipScale9) + { + var data = frame.data.scale9Borders; + + var x = data.x; + var y = data.y; + + leftWidth = x; + rightWidth = frame.width - data.w - x; + topHeight = y; + bottomHeight = frame.height - data.h - y; + + if (width === undefined) + { + width = frame.width; + } + + if (height === undefined) + { + height = frame.height; + } + } + else + { + if (width === undefined) { width = 256; } + if (height === undefined) { height = 256; } + } + + this._width = width; + this._height = height; + + this.leftWidth = leftWidth; + this.rightWidth = rightWidth; + this.topHeight = topHeight; + this.bottomHeight = bottomHeight; + + if (this.is3Slice) + { + height = frame.height; + + this._height = height; + this.topHeight = height; + this.bottomHeight = 0; + } + + this.updateVertices(); + this.updateUVs(); + } + + return this; + }, + + /** + * Updates all of the vertice UV coordinates. This is called automatically + * when the NineSlice Game Object is created, or if the texture frame changes. + * + * Unlike with the `updateVertice` method, you do not need to call this + * method if the Nine Slice changes size. Only if it changes texture frame. + * + * @method Phaser.GameObjects.NineSlice#updateUVs + * @since 3.60.0 + */ + updateUVs: function () + { + var left = this.leftWidth; + var right = this.rightWidth; + var top = this.topHeight; + var bot = this.bottomHeight; + + var width = this.frame.width; + var height = this.frame.height; + + this.updateQuadUVs(0, 0, 0, left / width, top / height); + this.updateQuadUVs(6, left / width, 0, 1 - (right / width), top / height); + this.updateQuadUVs(12, 1 - (right / width), 0, 1, top / height); + + if (!this.is3Slice) + { + this.updateQuadUVs(18, 0, top / height, left / width, 1 - (bot / height)); + this.updateQuadUVs(24, left / width, top / height, 1 - right / width, 1 - (bot / height)); + this.updateQuadUVs(30, 1 - right / width, top / height, 1, 1 - (bot / height)); + this.updateQuadUVs(36, 0, 1 - bot / height, left / width, 1); + this.updateQuadUVs(42, left / width, 1 - bot / height, 1 - right / width, 1); + this.updateQuadUVs(48, 1 - right / width, 1 - bot / height, 1, 1); + } + }, + + /** + * Recalculates all of the vertices in this Nine Slice Game Object + * based on the `leftWidth`, `rightWidth`, `topHeight` and `bottomHeight` + * properties, combined with the Game Object size. + * + * This method is called automatically when this object is created + * or if it's origin is changed. + * + * You should not typically need to call this method directly, but it + * is left public should you find a need to modify one of those properties + * after creation. + * + * @method Phaser.GameObjects.NineSlice#updateVertices + * @since 3.60.0 + */ + updateVertices: function () + { + var left = this.leftWidth; + var right = this.rightWidth; + var top = this.topHeight; + var bot = this.bottomHeight; + + var width = this.width; + var height = this.height; + + this.updateQuad(0, -0.5, 0.5, -0.5 + (left / width), 0.5 - (top / height)); + this.updateQuad(6, -0.5 + (left / width), 0.5, 0.5 - (right / width), 0.5 - (top / height)); + this.updateQuad(12, 0.5 - (right / width), 0.5, 0.5, 0.5 - (top / height)); + + if (!this.is3Slice) + { + this.updateQuad(18, -0.5, 0.5 - (top / height), -0.5 + (left / width), -0.5 + (bot / height)); + this.updateQuad(24, -0.5 + (left / width), 0.5 - (top / height), 0.5 - (right / width), -0.5 + (bot / height)); + this.updateQuad(30, 0.5 - (right / width), 0.5 - (top / height), 0.5, -0.5 + (bot / height)); + this.updateQuad(36, -0.5, -0.5 + (bot / height), -0.5 + (left / width), -0.5); + this.updateQuad(42, -0.5 + (left / width), -0.5 + (bot / height), 0.5 - (right / width), -0.5); + this.updateQuad(48, 0.5 - (right / width), -0.5 + (bot / height), 0.5, -0.5); + } + }, + + /** + * Internally updates the position coordinates across all vertices of the + * given quad offset. + * + * You should not typically need to call this method directly, but it + * is left public should an extended class require it. + * + * @method Phaser.GameObjects.NineSlice#updateQuad + * @since 3.60.0 + * + * @param {number} offset - The offset in the vertices array of the quad to update. + * @param {number} x1 - The top-left quad coordinate. + * @param {number} y1 - The top-left quad coordinate. + * @param {number} x2 - The bottom-right quad coordinate. + * @param {number} y2 - The bottom-right quad coordinate. + */ + updateQuad: function (offset, x1, y1, x2, y2) + { + var width = this.width; + var height = this.height; + var originX = this.originX; + var originY = this.originY; + + var verts = this.vertices; + + verts[offset + 0].resize(x1, y1, width, height, originX, originY); + verts[offset + 1].resize(x1, y2, width, height, originX, originY); + verts[offset + 2].resize(x2, y1, width, height, originX, originY); + verts[offset + 3].resize(x1, y2, width, height, originX, originY); + verts[offset + 4].resize(x2, y2, width, height, originX, originY); + verts[offset + 5].resize(x2, y1, width, height, originX, originY); + }, + + /** + * Internally updates the UV coordinates across all vertices of the + * given quad offset, based on the frame size. + * + * You should not typically need to call this method directly, but it + * is left public should an extended class require it. + * + * @method Phaser.GameObjects.NineSlice#updateQuadUVs + * @since 3.60.0 + * + * @param {number} offset - The offset in the vertices array of the quad to update. + * @param {number} u1 - The top-left UV coordinate. + * @param {number} v1 - The top-left UV coordinate. + * @param {number} u2 - The bottom-right UV coordinate. + * @param {number} v2 - The bottom-right UV coordinate. + */ + updateQuadUVs: function (offset, u1, v1, u2, v2) + { + var verts = this.vertices; + + // Adjust for frame offset + // Incoming values will always be in the range 0-1 + var frame = this.frame; + + var fu1 = frame.u0; + var fv1 = frame.v0; + var fu2 = frame.u1; + var fv2 = frame.v1; + + if (fu1 !== 0 || fu2 !== 1) + { + // adjust horizontal + var udiff = fu2 - fu1; + u1 = fu1 + u1 * udiff; + u2 = fu1 + u2 * udiff; + } + + if (fv1 !== 0 || fv2 !== 1) + { + // adjust vertical + var vdiff = fv2 - fv1; + v1 = fv1 + v1 * vdiff; + v2 = fv1 + v2 * vdiff; + } + + verts[offset + 0].setUVs(u1, v1); + verts[offset + 1].setUVs(u1, v2); + verts[offset + 2].setUVs(u2, v1); + verts[offset + 3].setUVs(u1, v2); + verts[offset + 4].setUVs(u2, v2); + verts[offset + 5].setUVs(u2, v1); + }, + + /** + * Clears all tint values associated with this Game Object. + * + * Immediately sets the color values back to 0xffffff and the tint type to 'additive', + * which results in no visible change to the texture. + * + * @method Phaser.GameObjects.NineSlice#clearTint + * @webglOnly + * @since 3.60.0 + * + * @return {this} This Game Object instance. + */ + clearTint: function () + { + this.setTint(0xffffff); + + return this; + }, + + /** + * Sets an additive tint on this Game Object. + * + * The tint works by taking the pixel color values from the Game Objects texture, and then + * multiplying it by the color value of the tint. + * + * To modify the tint color once set, either call this method again with new values or use the + * `tint` property. + * + * To remove a tint call `clearTint`, or call this method with no parameters. + * + * To swap this from being an additive tint to a fill based tint set the property `tintFill` to `true`. + * + * @method Phaser.GameObjects.NineSlice#setTint + * @webglOnly + * @since 3.60.0 + * + * @param {number} [color=0xffffff] - The tint being applied to the entire Game Object. + * + * @return {this} This Game Object instance. + */ + setTint: function (color) + { + if (color === undefined) { color = 0xffffff; } + + this.tint = color; + + this.tintFill = false; + + return this; + }, + + /** + * Sets a fill-based tint on this Game Object. + * + * Unlike an additive tint, a fill-tint literally replaces the pixel colors from the texture + * with those in the tint. You can use this for effects such as making a player flash 'white' + * if hit by something. The whole Game Object will be rendered in the given color. + * + * To modify the tint color once set, either call this method again with new values or use the + * `tint` property. + * + * To remove a tint call `clearTint`, or call this method with no parameters. + * + * To swap this from being a fill-tint to an additive tint set the property `tintFill` to `false`. + * + * @method Phaser.GameObjects.NineSlice#setTintFill + * @webglOnly + * @since 3.60.0 + * + * @param {number} [color=0xffffff] - The tint being applied to the entire Game Object. + * + * @return {this} This Game Object instance. + */ + setTintFill: function (color) + { + this.setTint(color); + + this.tintFill = true; + + return this; + }, + + /** + * Does this Game Object have a tint applied? + * + * It checks to see if the tint property is set to a value other than 0xffffff. + * This indicates that a Game Object is tinted. + * + * @name Phaser.GameObjects.NineSlice#isTinted + * @type {boolean} + * @webglOnly + * @readonly + * @since 3.60.0 + */ + isTinted: { + + get: function () + { + return (this.tint !== 0xffffff); + } + + }, + + /** + * The displayed width of this Game Object. + * + * Setting this value will adjust the way in which this Nine Slice + * object scales horizontally, if configured to do so. + * + * The _minimum_ width this Game Object can be is the total of + * `leftWidth` + `rightWidth`. If you need to display this object + * at a smaller size, you can also scale it. + * + * @name Phaser.GameObjects.NineSlice#width + * @type {number} + * @since 3.60.0 + */ + width: { + + get: function () + { + return this._width; + }, + + set: function (value) + { + this._width = Math.max(value, this.leftWidth + this.rightWidth); + + this.updateVertices(); + } + + }, + + /** + * The displayed height of this Game Object. + * + * Setting this value will adjust the way in which this Nine Slice + * object scales vertically, if configured to do so. + * + * The _minimum_ height this Game Object can be is the total of + * `topHeight` + `bottomHeight`. If you need to display this object + * at a smaller size, you can also scale it. + * + * If this is a 3-slice object, you can only stretch it horizontally + * and changing the height will be ignored. + * + * @name Phaser.GameObjects.NineSlice#height + * @type {number} + * @since 3.60.0 + */ + height: { + + get: function () + { + return this._height; + }, + + set: function (value) + { + if (!this.is3Slice) + { + this._height = Math.max(value, this.topHeight + this.bottomHeight); + + this.updateVertices(); + } + } + + }, + + /** + * The displayed width of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.NineSlice#displayWidth + * @type {number} + * @since 3.60.0 + */ + displayWidth: { + + get: function () + { + return this.scaleX * this.width; + }, + + set: function (value) + { + this.scaleX = value / this.width; + } + + }, + + /** + * The displayed height of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.NineSlice#displayHeight + * @type {number} + * @since 3.60.0 + */ + displayHeight: { + + get: function () + { + return this.scaleY * this.height; + }, + + set: function (value) + { + this.scaleY = value / this.height; + } + + }, + + /** + * Sets the size of this Game Object. + * + * For a Nine Slice Game Object this means it will be stretched (or shrunk) horizontally + * and vertically depending on the dimensions given to this method, in accordance with + * how it has been configured for the various corner sizes. + * + * If this is a 3-slice object, you can only stretch it horizontally + * and changing the height will be ignored. + * + * If you have enabled this Game Object for input, changing the size will also change the + * size of the hit area. + * + * @method Phaser.GameObjects.NineSlice#setSize + * @since 3.60.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + + this.updateDisplayOrigin(); + + var input = this.input; + + if (input && !input.customHitArea) + { + input.hitArea.width = this.width; + input.hitArea.height = this.height; + } + + return this; + }, + + /** + * Sets the display size of this Game Object. + * + * Calling this will adjust the scale. + * + * @method Phaser.GameObjects.NineSlice#setDisplaySize + * @since 3.60.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setDisplaySize: function (width, height) + { + this.displayWidth = width; + this.displayHeight = height; + + return this; + }, + + /** + * The horizontal origin of this Game Object. + * The origin maps the relationship between the size and position of the Game Object. + * The default value is 0.5, meaning all Game Objects are positioned based on their center. + * Setting the value to 0 means the position now relates to the left of the Game Object. + * + * @name Phaser.GameObjects.NineSlice#originX + * @type {number} + * @since 3.60.0 + */ + originX: { + + get: function () + { + return this._originX; + }, + + set: function (value) + { + this._originX = value; + this.updateVertices(); + } + + }, + + /** + * The vertical origin of this Game Object. + * The origin maps the relationship between the size and position of the Game Object. + * The default value is 0.5, meaning all Game Objects are positioned based on their center. + * Setting the value to 0 means the position now relates to the top of the Game Object. + * + * @name Phaser.GameObjects.NineSlice#originY + * @type {number} + * @since 3.60.0 + */ + originY: { + + get: function () + { + return this._originY; + }, + + set: function (value) + { + this._originY = value; + this.updateVertices(); + } + + }, + + /** + * Sets the origin of this Game Object. + * + * The values are given in the range 0 to 1. + * + * @method Phaser.GameObjects.NineSlice#setOrigin + * @since 3.60.0 + * + * @param {number} [x=0.5] - The horizontal origin value. + * @param {number} [y=x] - The vertical origin value. If not defined it will be set to the value of `x`. + * + * @return {this} This Game Object instance. + */ + setOrigin: function (x, y) + { + if (x === undefined) { x = 0.5; } + if (y === undefined) { y = x; } + + this._originX = x; + this._originY = y; + + this.updateVertices(); + + return this.updateDisplayOrigin(); + }, + + /** + * This method is included but does nothing for the Nine Slice Game Object, + * because the size of the object isn't based on the texture frame. + * + * You should not call this method. + * + * @method Phaser.GameObjects.NineSlice#setSizeToFrame + * @since 3.60.0 + * + * @return {this} This Game Object instance. + */ + setSizeToFrame: function () + { + if (this.is3Slice) + { + var height = this.frame.height; + + this._height = height; + this.topHeight = height; + this.bottomHeight = 0; + } + + this.updateUVs(); + + return this; + }, + + /** + * Handles the pre-destroy step for the Nine Slice, which removes the vertices. + * + * @method Phaser.GameObjects.NineSlice#preDestroy + * @private + * @since 3.60.0 + */ + preDestroy: function () + { + this.vertices = []; + } + +}); + +module.exports = NineSlice; + + +/***/ }), + +/***/ 28279: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var GetValue = __webpack_require__(35154); +var NineSlice = __webpack_require__(28103); + +/** + * Creates a new Nine Slice Game Object and returns it. + * + * Note: This method will only be available if the Nine Slice Game Object and WebGL support have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#nineslice + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.NineSlice.NineSliceConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.NineSlice} The Game Object that was created. + */ +GameObjectCreator.register('nineslice', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var frame = GetAdvancedValue(config, 'frame', null); + var width = GetValue(config, 'width', 256); + var height = GetValue(config, 'height', 256); + var leftWidth = GetValue(config, 'leftWidth', 10); + var rightWidth = GetValue(config, 'rightWidth', 10); + var topHeight = GetValue(config, 'topHeight', 0); + var bottomHeight = GetValue(config, 'bottomHeight', 0); + + var nineslice = new NineSlice(this.scene, 0, 0, key, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, nineslice, config); + + return nineslice; +}); + + +/***/ }), + +/***/ 47521: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NineSlice = __webpack_require__(28103); +var GameObjectFactory = __webpack_require__(39429); + +/** + * A Nine Slice Game Object allows you to display a texture-based object that + * can be stretched both horizontally and vertically, but that retains + * fixed-sized corners. The dimensions of the corners are set via the + * parameters to this class. + * + * This is extremely useful for UI and button like elements, where you need + * them to expand to accommodate the content without distorting the texture. + * + * The texture you provide for this Game Object should be based on the + * following layout structure: + * + * ``` + * A B + * +---+----------------------+---+ + * C | 1 | 2 | 3 | + * +---+----------------------+---+ + * | | | | + * | 4 | 5 | 6 | + * | | | | + * +---+----------------------+---+ + * D | 7 | 8 | 9 | + * +---+----------------------+---+ + * ``` + * + * When changing this objects width and / or height: + * + * areas 1, 3, 7 and 9 (the corners) will remain unscaled + * areas 2 and 8 will be stretched horizontally only + * areas 4 and 6 will be stretched vertically only + * area 5 will be stretched both horizontally and vertically + * + * You can also create a 3 slice Game Object: + * + * This works in a similar way, except you can only stretch it horizontally. + * Therefore, it requires less configuration: + * + * ``` + * A B + * +---+----------------------+---+ + * | | | | + * C | 1 | 2 | 3 | + * | | | | + * +---+----------------------+---+ + * ``` + * + * When changing this objects width (you cannot change its height) + * + * areas 1 and 3 will remain unscaled + * area 2 will be stretched horizontally + * + * The above configuration concept is adapted from the Pixi NineSlicePlane. + * + * To specify a 3 slice object instead of a 9 slice you should only + * provide the `leftWidth` and `rightWidth` parameters. To create a 9 slice + * you must supply all parameters. + * + * The _minimum_ width this Game Object can be is the total of + * `leftWidth` + `rightWidth`. The _minimum_ height this Game Object + * can be is the total of `topHeight` + `bottomHeight`. + * If you need to display this object at a smaller size, you can scale it. + * + * In terms of performance, using a 3 slice Game Object is the equivalent of + * having 3 Sprites in a row. Using a 9 slice Game Object is the equivalent + * of having 9 Sprites in a row. The vertices of this object are all batched + * together and can co-exist with other Sprites and graphics on the display + * list, without incurring any additional overhead. + * + * As of Phaser 3.60 this Game Object is WebGL only. + * + * @method Phaser.GameObjects.GameObjectFactory#nineslice + * @webglOnly + * @since 3.60.0 + * + * @param {number} x - The horizontal position of the center of this Game Object in the world. + * @param {number} y - The vertical position of the center of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * @param {number} [width=256] - The width of the Nine Slice Game Object. You can adjust the width post-creation. + * @param {number} [height=256] - The height of the Nine Slice Game Object. If this is a 3 slice object the height will be fixed to the height of the texture and cannot be changed. + * @param {number} [leftWidth=10] - The size of the left vertical column (A). + * @param {number} [rightWidth=10] - The size of the right vertical column (B). + * @param {number} [topHeight=0] - The size of the top horiztonal row (C). Set to zero or undefined to create a 3 slice object. + * @param {number} [bottomHeight=0] - The size of the bottom horiztonal row (D). Set to zero or undefined to create a 3 slice object. + * + * @return {Phaser.GameObjects.NineSlice} The Game Object that was created. + */ +if (true) +{ + GameObjectFactory.register('nineslice', function (x, y, texture, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight) + { + return this.displayList.add(new NineSlice(this.scene, x, y, texture, frame, width, height, leftWidth, rightWidth, topHeight, bottomHeight)); + }); +} + + +/***/ }), + +/***/ 78023: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(52230); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 82513: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * Vertex data for the NineSlice Game Object. + * + * This class consists of all the information required for a single vertex. + * + * @class NineSliceVertex + * @memberof Phaser.GameObjects + * @constructor + * @extends Phaser.Math.Vector2 + * @since 4.0.0 + * + * @param {number} x - The x position of the vertex. + * @param {number} y - The y position of the vertex. + * @param {number} u - The UV u coordinate of the vertex. + * @param {number} v - The UV v coordinate of the vertex. + */ +var Vertex = new Class({ + + Extends: Vector2, + + initialize: + + function Vertex (x, y, u, v) + { + Vector2.call(this, x, y); + + /** + * The projected x coordinate of this vertex. + * + * @name Phaser.GameObjects.NineSliceVertex#vx + * @type {number} + * @since 4.0.0 + */ + this.vx = 0; + + /** + * The projected y coordinate of this vertex. + * + * @name Phaser.GameObjects.NineSliceVertex#vy + * @type {number} + * @since 4.0.0 + */ + this.vy = 0; + + /** + * UV u coordinate of this vertex. + * + * @name Phaser.GameObjects.NineSliceVertex#u + * @type {number} + * @since 4.0.0 + */ + this.u = u; + + /** + * UV v coordinate of this vertex. + * + * @name Phaser.GameObjects.NineSliceVertex#v + * @type {number} + * @since 4.0.0 + */ + this.v = v; + }, + + /** + * Sets the U and V properties. + * + * @method Phaser.GameObjects.NineSliceVertex#setUVs + * @since 4.0.0 + * + * @param {number} u - The UV u coordinate of the vertex. + * @param {number} v - The UV v coordinate of the vertex. + * + * @return {this} This Vertex. + */ + setUVs: function (u, v) + { + this.u = u; + this.v = v; + + return this; + }, + + /** + * Resizes this Vertex by setting the x and y coordinates, then transforms this vertex + * by an identity matrix and dimensions, storing the results in `vx` and `vy`. + * + * @method Phaser.GameObjects.NineSliceVertex#resize + * @since 4.0.0 + * + * @param {number} x - The x position of the vertex. + * @param {number} y - The y position of the vertex. + * @param {number} width - The width of the parent object. + * @param {number} height - The height of the parent object. + * @param {number} originX - The originX of the parent object. + * @param {number} originY - The originY of the parent object. + * + * @return {this} This Vertex. + */ + resize: function (x, y, width, height, originX, originY) + { + this.x = x; + this.y = y; + + this.vx = this.x * width; + this.vy = -this.y * height; + + if (originX < 0.5) + { + this.vx += width * (0.5 - originX); + } + else if (originX > 0.5) + { + this.vx -= width * (originX - 0.5); + } + + if (originY < 0.5) + { + this.vy += height * (0.5 - originY); + } + else if (originY > 0.5) + { + this.vy -= height * (originY - 0.5); + } + + return this; + } +}); + +module.exports = Vertex; + + +/***/ }), + +/***/ 52230: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); + +var fixedRenderOptions = { multiTexturing: true }; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.NineSlice#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.NineSlice} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var NineSliceWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var verts = src.vertices; + var totalVerts = verts.length; + + if (totalVerts === 0) + { + return; + } + + var camera = drawingContext.camera; + + camera.addToRenderList(src); + + var alpha = src.alpha; + var batchHandler = src.customRenderNodes.BatchHandler || src.defaultRenderNodes.BatchHandler; + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + var color = Utils.getTintAppendFloatAlpha(src.tint, alpha); + var glTexture = src.frame.source.glTexture; + var tintEffect = src.tintFill; + + var quad, vtl, vbr; + + for (var i = 0; i < totalVerts; i += 6) + { + // Of the 6 vertices, we only need these 2 to define a quad. + // They are the top-left and bottom-right. + vtl = verts[i + 1]; + vbr = verts[i + 2]; + + quad = calcMatrix.setQuad( + vtl.vx, vtl.vy, + vbr.vx, vbr.vy + ); + + batchHandler.batch( + drawingContext, + + glTexture, + + // Transformed quad in order TL, BL, TR, BR: + quad[0], quad[1], + quad[2], quad[3], + quad[6], quad[7], + quad[4], quad[5], + + // Texture coordinates in X, Y, Width, Height: + vtl.u, vtl.v, vbr.u - vtl.u, vbr.v - vtl.v, + + tintEffect, + + // Tint colors in order TL, BL, TR, BR: + color, color, color, color, + + // Render options: + fixedRenderOptions + ); + } +}; + +module.exports = NineSliceWebGLRenderer; + + +/***/ }), + +/***/ 76472: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EmitterOp = __webpack_require__(44777); +var GetColor = __webpack_require__(37589); +var GetEaseFunction = __webpack_require__(6113); +var GetInterpolationFunction = __webpack_require__(91389); +var IntegerToRGB = __webpack_require__(90664); + +/** + * @classdesc + * This class is responsible for taking control over the color property + * in the Particle class and managing its emission and updating functions. + * + * See the `ParticleEmitter` class for more details on emitter op configuration. + * + * @class EmitterColorOp + * @extends Phaser.GameObjects.Particles.EmitterOp + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.60.0 + * + * @param {string} key - The name of the property. + */ +var EmitterColorOp = new Class({ + + Extends: EmitterOp, + + initialize: + + function EmitterColorOp (key) + { + EmitterOp.call(this, key, null, false); + + this.active = false; + + this.easeName = 'Linear'; + + /** + * An array containing the red color values. + * + * Populated during the `setMethods` method. + * + * @name Phaser.GameObjects.Particles.EmitterColorOp#r + * @type {number[]} + * @since 3.60.0 + */ + this.r = []; + + /** + * An array containing the green color values. + * + * Populated during the `setMethods` method. + * + * @name Phaser.GameObjects.Particles.EmitterColorOp#g + * @type {number[]} + * @since 3.60.0 + */ + this.g = []; + + /** + * An array containing the blue color values. + * + * Populated during the `setMethods` method. + * + * @name Phaser.GameObjects.Particles.EmitterColorOp#b + * @type {number[]} + * @since 3.60.0 + */ + this.b = []; + }, + + /** + * Checks the type of `EmitterOp.propertyValue` to determine which + * method is required in order to return values from this op function. + * + * @method Phaser.GameObjects.Particles.EmitterColorOp#getMethod + * @since 3.60.0 + * + * @return {number} A number between 0 and 9 which should be passed to `setMethods`. + */ + getMethod: function () + { + return (this.propertyValue === null) ? 0 : 9; + }, + + /** + * Sets the EmitterColorOp method values, if in use. + * + * @method Phaser.GameObjects.Particles.EmitterColorOp#setMethods + * @since 3.60.0 + * + * @return {this} This Emitter Op object. + */ + setMethods: function () + { + var value = this.propertyValue; + var current = value; + + var onEmit = this.defaultEmit; + var onUpdate = this.defaultUpdate; + + if (this.method === 9) + { + this.start = value[0]; + this.ease = GetEaseFunction('Linear'); + this.interpolation = GetInterpolationFunction('linear'); + + onEmit = this.easedValueEmit; + onUpdate = this.easeValueUpdate; + current = value[0]; + + this.active = true; + + this.r.length = 0; + this.g.length = 0; + this.b.length = 0; + + // Populate the r,g,b arrays + for (var i = 0; i < value.length; i++) + { + // in hex format 0xff0000 + var color = IntegerToRGB(value[i]); + + this.r.push(color.r); + this.g.push(color.g); + this.b.push(color.b); + } + } + + this.onEmit = onEmit; + this.onUpdate = onUpdate; + this.current = current; + + return this; + }, + + /** + * Sets the Ease function to use for Color interpolation. + * + * @method Phaser.GameObjects.Particles.EmitterColorOp#setEase + * @since 3.60.0 + * + * @param {string} ease - The string-based name of the Ease function to use. + */ + setEase: function (value) + { + this.easeName = value; + + this.ease = GetEaseFunction(value); + }, + + /** + * An `onEmit` callback for an eased property. + * + * It prepares the particle for easing by {@link Phaser.GameObjects.Particles.EmitterColorOp#easeValueUpdate}. + * + * @method Phaser.GameObjects.Particles.EmitterColorOp#easedValueEmit + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * + * @return {number} {@link Phaser.GameObjects.Particles.EmitterColorOp#start}, as the new value of the property. + */ + easedValueEmit: function () + { + this.current = this.start; + + return this.start; + }, + + /** + * An `onUpdate` callback that returns an eased value between the + * {@link Phaser.GameObjects.Particles.EmitterColorOp#start} and {@link Phaser.GameObjects.Particles.EmitterColorOp#end} + * range. + * + * @method Phaser.GameObjects.Particles.EmitterColorOp#easeValueUpdate + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + * + * @return {number} The new value of the property. + */ + easeValueUpdate: function (particle, key, t) + { + var v = this.ease(t); + + var r = this.interpolation(this.r, v); + var g = this.interpolation(this.g, v); + var b = this.interpolation(this.b, v); + + var current = GetColor(r, g, b); + + this.current = current; + + return current; + } + +}); + +module.exports = EmitterColorOp; + + +/***/ }), + +/***/ 44777: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Between = __webpack_require__(30976); +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var FloatBetween = __webpack_require__(99472); +var GetEaseFunction = __webpack_require__(6113); +var GetFastValue = __webpack_require__(95540); +var GetInterpolationFunction = __webpack_require__(91389); +var SnapTo = __webpack_require__(77720); +var Wrap = __webpack_require__(15994); + +/** + * @classdesc + * This class is responsible for taking control over a single property + * in the Particle class and managing its emission and updating functions. + * + * Particles properties such as `x`, `y`, `scaleX`, `lifespan` and others all use + * EmitterOp instances to manage them, as they can be given in a variety of + * formats: from simple values, to functions, to dynamic callbacks. + * + * See the `ParticleEmitter` class for more details on emitter op configuration. + * + * @class EmitterOp + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.0.0 + * + * @param {string} key - The name of the property. + * @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType} defaultValue - The default value of the property. + * @param {boolean} [emitOnly=false] - Whether the property can only be modified when a Particle is emitted. + */ +var EmitterOp = new Class({ + + initialize: + + function EmitterOp (key, defaultValue, emitOnly) + { + if (emitOnly === undefined) { emitOnly = false; } + + /** + * The name of this property. + * + * @name Phaser.GameObjects.Particles.EmitterOp#propertyKey + * @type {string} + * @since 3.0.0 + */ + this.propertyKey = key; + + /** + * The current value of this property. + * + * This can be a simple value, an array, a function or an onEmit + * configuration object. + * + * @name Phaser.GameObjects.Particles.EmitterOp#propertyValue + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType} + * @since 3.0.0 + */ + this.propertyValue = defaultValue; + + /** + * The default value of this property. + * + * This can be a simple value, an array, a function or an onEmit + * configuration object. + * + * @name Phaser.GameObjects.Particles.EmitterOp#defaultValue + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType} + * @since 3.0.0 + */ + this.defaultValue = defaultValue; + + /** + * The number of steps for stepped easing between {@link Phaser.GameObjects.Particles.EmitterOp#start} and + * {@link Phaser.GameObjects.Particles.EmitterOp#end} values, per emit. + * + * @name Phaser.GameObjects.Particles.EmitterOp#steps + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.steps = 0; + + /** + * The step counter for stepped easing, per emit. + * + * @name Phaser.GameObjects.Particles.EmitterOp#counter + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.counter = 0; + + /** + * When the step counter reaches it's maximum, should it then + * yoyo back to the start again, or flip over to it? + * + * @name Phaser.GameObjects.Particles.EmitterOp#yoyo + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.yoyo = false; + + /** + * The counter direction. 0 for up and 1 for down. + * + * @name Phaser.GameObjects.Particles.EmitterOp#direction + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.direction = 0; + + /** + * The start value for this property to ease between. + * + * If an interpolation this holds a reference to the number data array. + * + * @name Phaser.GameObjects.Particles.EmitterOp#start + * @type {number|number[]} + * @default 0 + * @since 3.0.0 + */ + this.start = 0; + + /** + * The most recently calculated value. Updated every time an + * emission or update method is called. Treat as read-only. + * + * @name Phaser.GameObjects.Particles.EmitterOp#current + * @type {number} + * @since 3.60.0 + */ + this.current = 0; + + /** + * The end value for this property to ease between. + * + * @name Phaser.GameObjects.Particles.EmitterOp#end + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.end = 0; + + /** + * The easing function to use for updating this property, if any. + * + * @name Phaser.GameObjects.Particles.EmitterOp#ease + * @type {?function} + * @since 3.0.0 + */ + this.ease = null; + + /** + * The interpolation function to use for updating this property, if any. + * + * @name Phaser.GameObjects.Particles.EmitterOp#interpolation + * @type {?function} + * @since 3.60.0 + */ + this.interpolation = null; + + /** + * Whether this property can only be modified when a Particle is emitted. + * + * Set to `true` to allow only {@link Phaser.GameObjects.Particles.EmitterOp#onEmit} callbacks to be set and + * affect this property. + * + * Set to `false` to allow both {@link Phaser.GameObjects.Particles.EmitterOp#onEmit} and + * {@link Phaser.GameObjects.Particles.EmitterOp#onUpdate} callbacks to be set and affect this property. + * + * @name Phaser.GameObjects.Particles.EmitterOp#emitOnly + * @type {boolean} + * @since 3.0.0 + */ + this.emitOnly = emitOnly; + + /** + * The callback to run for Particles when they are emitted from the Particle Emitter. + * + * @name Phaser.GameObjects.Particles.EmitterOp#onEmit + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback} + * @since 3.0.0 + */ + this.onEmit = this.defaultEmit; + + /** + * The callback to run for Particles when they are updated. + * + * @name Phaser.GameObjects.Particles.EmitterOp#onUpdate + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback} + * @since 3.0.0 + */ + this.onUpdate = this.defaultUpdate; + + /** + * Set to `false` to disable this EmitterOp. + * + * @name Phaser.GameObjects.Particles.EmitterOp#active + * @type {boolean} + * @since 3.60.0 + */ + this.active = true; + + /** + * The onEmit method type of this EmitterOp. + * + * Set as part of `setMethod` and cached here to avoid + * re-setting when only the value changes. + * + * @name Phaser.GameObjects.Particles.EmitterOp#method + * @type {number} + * @since 3.60.0 + */ + this.method = 0; + + /** + * The callback to run for Particles when they are emitted from the Particle Emitter. + * This is set during `setMethods` and used by `proxyEmit`. + * + * @name Phaser.GameObjects.Particles.EmitterOp#_onEmit + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitCallback} + * @private + * @since 3.60.0 + */ + this._onEmit; + + /** + * The callback to run for Particles when they are updated. + * This is set during `setMethods` and used by `proxyUpdate`. + * + * @name Phaser.GameObjects.Particles.EmitterOp#_onUpdate + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateCallback} + * @private + * @since 3.60.0 + */ + this._onUpdate; + }, + + /** + * Load the property from a Particle Emitter configuration object. + * + * Optionally accepts a new property key to use, replacing the current one. + * + * @method Phaser.GameObjects.Particles.EmitterOp#loadConfig + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} [config] - Settings for the Particle Emitter that owns this property. + * @param {string} [newKey] - The new key to use for this property, if any. + */ + loadConfig: function (config, newKey) + { + if (config === undefined) + { + config = {}; + } + + if (newKey) + { + this.propertyKey = newKey; + } + + this.propertyValue = GetFastValue( + config, + this.propertyKey, + this.defaultValue + ); + + this.method = this.getMethod(); + + this.setMethods(); + + if (this.emitOnly) + { + // Reset it back again + this.onUpdate = this.defaultUpdate; + } + }, + + /** + * Build a JSON representation of this Particle Emitter property. + * + * @method Phaser.GameObjects.Particles.EmitterOp#toJSON + * @since 3.0.0 + * + * @return {object} A JSON representation of this Particle Emitter property. + */ + toJSON: function () + { + return JSON.stringify(this.propertyValue); + }, + + /** + * Change the current value of the property and update its callback methods. + * + * @method Phaser.GameObjects.Particles.EmitterOp#onChange + * @since 3.0.0 + * + * @param {number} value - The new numeric value of this property. + * + * @return {this} This Emitter Op object. + */ + onChange: function (value) + { + var current; + + switch (this.method) + { + // Number + // Custom Callback (onEmit only) + // Custom onEmit and/or onUpdate callbacks + case 1: + case 3: + case 8: + current = value; + break; + + // Random Array + case 2: + if (this.propertyValue.indexOf(value) >= 0) + { + current = value; + } + break; + + // Stepped start/end + case 4: + var step = (this.end - this.start) / this.steps; + current = SnapTo(value, step); + this.counter = current; + break; + + // Eased start/end + // min/max (random float or int) + // Random object (random integer) + case 5: + case 6: + case 7: + current = Clamp(value, this.start, this.end); + break; + + // Interpolation + case 9: + current = this.start[0]; + break; + } + + this.current = current; + + return this; + }, + + /** + * Checks the type of `EmitterOp.propertyValue` to determine which + * method is required in order to return values from this op function. + * + * @method Phaser.GameObjects.Particles.EmitterOp#getMethod + * @since 3.60.0 + * + * @return {number} A number between 0 and 9 which should be passed to `setMethods`. + */ + getMethod: function () + { + var value = this.propertyValue; + + // `moveToX` and `moveToY` are null by default + if (value === null) + { + return 0; + } + + var t = typeof value; + + if (t === 'number') + { + // Number + return 1; + } + else if (Array.isArray(value)) + { + // Random Array + return 2; + } + else if (t === 'function') + { + // Custom Callback + return 3; + } + else if (t === 'object') + { + if (this.hasBoth(value, 'start', 'end')) + { + if (this.has(value, 'steps')) + { + // Stepped start/end + return 4; + } + else + { + // Eased start/end + return 5; + } + } + else if (this.hasBoth(value, 'min', 'max')) + { + // min/max + return 6; + } + else if (this.has(value, 'random')) + { + // Random object + return 7; + } + else if (this.hasEither(value, 'onEmit', 'onUpdate')) + { + // Custom onEmit onUpdate + return 8; + } + else if (this.hasEither(value, 'values', 'interpolation')) + { + // Interpolation + return 9; + } + } + + return 0; + }, + + /** + * Update the {@link Phaser.GameObjects.Particles.EmitterOp#onEmit} and + * {@link Phaser.GameObjects.Particles.EmitterOp#onUpdate} callbacks based on the method returned + * from `getMethod`. The method is stored in the `EmitterOp.method` property + * and is a number between 0 and 9 inclusively. + * + * @method Phaser.GameObjects.Particles.EmitterOp#setMethods + * @since 3.0.0 + * + * @return {this} This Emitter Op object. + */ + setMethods: function () + { + var value = this.propertyValue; + var current = value; + + var onEmit = this.defaultEmit; + var onUpdate = this.defaultUpdate; + + switch (this.method) + { + // Number + case 1: + onEmit = this.staticValueEmit; + break; + + // Random Array + case 2: + onEmit = this.randomStaticValueEmit; + current = value[0]; + break; + + // Custom Callback (onEmit only) + case 3: + this._onEmit = value; + onEmit = this.proxyEmit; + current = this.defaultValue; + break; + + // Stepped start/end + case 4: + this.start = value.start; + this.end = value.end; + this.steps = value.steps; + this.counter = this.start; + this.yoyo = this.has(value, 'yoyo') ? value.yoyo : false; + this.direction = 0; + onEmit = this.steppedEmit; + current = this.start; + break; + + // Eased start/end + case 5: + this.start = value.start; + this.end = value.end; + var easeType = this.has(value, 'ease') ? value.ease : 'Linear'; + this.ease = GetEaseFunction(easeType, value.easeParams); + onEmit = (this.has(value, 'random') && value.random) ? this.randomRangedValueEmit : this.easedValueEmit; + onUpdate = this.easeValueUpdate; + current = this.start; + break; + + // min/max (random float or int) + case 6: + this.start = value.min; + this.end = value.max; + onEmit = (this.has(value, 'int') && value.int) ? this.randomRangedIntEmit : this.randomRangedValueEmit; + current = this.start; + break; + + // Random object (random integer) + case 7: + var rnd = value.random; + + if (Array.isArray(rnd)) + { + this.start = rnd[0]; + this.end = rnd[1]; + } + + onEmit = this.randomRangedIntEmit; + current = this.start; + break; + + // Custom onEmit and/or onUpdate callbacks + case 8: + this._onEmit = (this.has(value, 'onEmit')) ? value.onEmit : this.defaultEmit; + this._onUpdate = (this.has(value, 'onUpdate')) ? value.onUpdate : this.defaultUpdate; + onEmit = this.proxyEmit; + onUpdate = this.proxyUpdate; + current = this.defaultValue; + break; + + // Interpolation + case 9: + this.start = value.values; + var easeTypeI = this.has(value, 'ease') ? value.ease : 'Linear'; + this.ease = GetEaseFunction(easeTypeI, value.easeParams); + this.interpolation = GetInterpolationFunction(value.interpolation); + onEmit = this.easedValueEmit; + onUpdate = this.easeValueUpdate; + current = this.start[0]; + break; + } + + this.onEmit = onEmit; + this.onUpdate = onUpdate; + this.current = current; + + return this; + }, + + /** + * Check whether an object has the given property. + * + * @method Phaser.GameObjects.Particles.EmitterOp#has + * @since 3.0.0 + * + * @param {object} object - The object to check. + * @param {string} key - The key of the property to look for in the object. + * + * @return {boolean} `true` if the property exists in the object, `false` otherwise. + */ + has: function (object, key) + { + return object.hasOwnProperty(key); + }, + + /** + * Check whether an object has both of the given properties. + * + * @method Phaser.GameObjects.Particles.EmitterOp#hasBoth + * @since 3.0.0 + * + * @param {object} object - The object to check. + * @param {string} key1 - The key of the first property to check the object for. + * @param {string} key2 - The key of the second property to check the object for. + * + * @return {boolean} `true` if both properties exist in the object, `false` otherwise. + */ + hasBoth: function (object, key1, key2) + { + return object.hasOwnProperty(key1) && object.hasOwnProperty(key2); + }, + + /** + * Check whether an object has at least one of the given properties. + * + * @method Phaser.GameObjects.Particles.EmitterOp#hasEither + * @since 3.0.0 + * + * @param {object} object - The object to check. + * @param {string} key1 - The key of the first property to check the object for. + * @param {string} key2 - The key of the second property to check the object for. + * + * @return {boolean} `true` if at least one of the properties exists in the object, `false` if neither exist. + */ + hasEither: function (object, key1, key2) + { + return object.hasOwnProperty(key1) || object.hasOwnProperty(key2); + }, + + /** + * The returned value sets what the property will be at the START of the particles life, on emit. + * + * @method Phaser.GameObjects.Particles.EmitterOp#defaultEmit + * @since 3.0.0 + * + * @return {number} The new value of the property. + */ + defaultEmit: function () + { + return this.defaultValue; + }, + + /** + * The returned value updates the property for the duration of the particles life. + * + * @method Phaser.GameObjects.Particles.EmitterOp#defaultUpdate + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + * @param {number} value - The current value of the property. + * + * @return {number} The new value of the property. + */ + defaultUpdate: function (particle, key, t, value) + { + return value; + }, + + /** + * The returned value sets what the property will be at the START of the particles life, on emit. + * + * This method is only used when you have provided a custom emit callback. + * + * @method Phaser.GameObjects.Particles.EmitterOp#proxyEmit + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * @param {number} [value] - The current value of the property. + * + * @return {number} The new value of the property. + */ + proxyEmit: function (particle, key, value) + { + var result = this._onEmit(particle, key, value); + + this.current = result; + + return result; + }, + + /** + * The returned value updates the property for the duration of the particles life. + * + * This method is only used when you have provided a custom update callback. + * + * @method Phaser.GameObjects.Particles.EmitterOp#proxyUpdate + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + * @param {number} value - The current value of the property. + * + * @return {number} The new value of the property. + */ + proxyUpdate: function (particle, key, t, value) + { + var result = this._onUpdate(particle, key, t, value); + + this.current = result; + + return result; + }, + + /** + * An `onEmit` callback that returns the current value of the property. + * + * @method Phaser.GameObjects.Particles.EmitterOp#staticValueEmit + * @since 3.0.0 + * + * @return {number} The current value of the property. + */ + staticValueEmit: function () + { + return this.current; + }, + + /** + * An `onUpdate` callback that returns the current value of the property. + * + * @method Phaser.GameObjects.Particles.EmitterOp#staticValueUpdate + * @since 3.0.0 + * + * @return {number} The current value of the property. + */ + staticValueUpdate: function () + { + return this.current; + }, + + /** + * An `onEmit` callback that returns a random value from the current value array. + * + * @method Phaser.GameObjects.Particles.EmitterOp#randomStaticValueEmit + * @since 3.0.0 + * + * @return {number} The new value of the property. + */ + randomStaticValueEmit: function () + { + var randomIndex = Math.floor(Math.random() * this.propertyValue.length); + + this.current = this.propertyValue[randomIndex]; + + return this.current; + }, + + /** + * An `onEmit` callback that returns a value between the {@link Phaser.GameObjects.Particles.EmitterOp#start} and + * {@link Phaser.GameObjects.Particles.EmitterOp#end} range. + * + * @method Phaser.GameObjects.Particles.EmitterOp#randomRangedValueEmit + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The key of the property. + * + * @return {number} The new value of the property. + */ + randomRangedValueEmit: function (particle, key) + { + var value = FloatBetween(this.start, this.end); + + if (particle && particle.data[key]) + { + particle.data[key].min = value; + particle.data[key].max = this.end; + } + + this.current = value; + + return value; + }, + + /** + * An `onEmit` callback that returns a value between the {@link Phaser.GameObjects.Particles.EmitterOp#start} and + * {@link Phaser.GameObjects.Particles.EmitterOp#end} range. + * + * @method Phaser.GameObjects.Particles.EmitterOp#randomRangedIntEmit + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The key of the property. + * + * @return {number} The new value of the property. + */ + randomRangedIntEmit: function (particle, key) + { + var value = Between(this.start, this.end); + + if (particle && particle.data[key]) + { + particle.data[key].min = value; + particle.data[key].max = this.end; + } + + this.current = value; + + return value; + }, + + /** + * An `onEmit` callback that returns a stepped value between the + * {@link Phaser.GameObjects.Particles.EmitterOp#start} and {@link Phaser.GameObjects.Particles.EmitterOp#end} + * range. + * + * @method Phaser.GameObjects.Particles.EmitterOp#steppedEmit + * @since 3.0.0 + * + * @return {number} The new value of the property. + */ + steppedEmit: function () + { + var current = this.counter; + + var next = current; + + var step = (this.end - this.start) / this.steps; + + if (this.yoyo) + { + var over; + + if (this.direction === 0) + { + // Add step to the current value + next += step; + + if (next >= this.end) + { + over = next - this.end; + + next = this.end - over; + + this.direction = 1; + } + } + else + { + // Down + next -= step; + + if (next <= this.start) + { + over = this.start - next; + + next = this.start + over; + + this.direction = 0; + } + } + + this.counter = next; + } + else + { + this.counter = Wrap(next + step, this.start, this.end); + } + + this.current = current; + + return current; + }, + + /** + * An `onEmit` callback for an eased property. + * + * It prepares the particle for easing by {@link Phaser.GameObjects.Particles.EmitterOp#easeValueUpdate}. + * + * @method Phaser.GameObjects.Particles.EmitterOp#easedValueEmit + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * + * @return {number} {@link Phaser.GameObjects.Particles.EmitterOp#start}, as the new value of the property. + */ + easedValueEmit: function (particle, key) + { + if (particle && particle.data[key]) + { + var data = particle.data[key]; + + data.min = this.start; + data.max = this.end; + } + + this.current = this.start; + + return this.start; + }, + + /** + * An `onUpdate` callback that returns an eased value between the + * {@link Phaser.GameObjects.Particles.EmitterOp#start} and {@link Phaser.GameObjects.Particles.EmitterOp#end} + * range. + * + * @method Phaser.GameObjects.Particles.EmitterOp#easeValueUpdate + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle. + * @param {string} key - The name of the property. + * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + * + * @return {number} The new value of the property. + */ + easeValueUpdate: function (particle, key, t) + { + var data = particle.data[key]; + + var current; + var v = this.ease(t); + + if (this.interpolation) + { + current = this.interpolation(this.start, v); + } + else + { + current = (data.max - data.min) * v + data.min; + } + + this.current = current; + + return current; + }, + + /** + * Destroys this EmitterOp instance and all of its references. + * + * Called automatically when the ParticleEmitter that owns this + * EmitterOp is destroyed. + * + * @method Phaser.GameObjects.Particles.EmitterOp#destroy + * @since 3.60.0 + */ + destroy: function () + { + this.propertyValue = null; + this.defaultValue = null; + this.ease = null; + this.interpolation = null; + this._onEmit = null; + this._onUpdate = null; + } +}); + +module.exports = EmitterOp; + + +/***/ }), + +/***/ 24502: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetFastValue = __webpack_require__(95540); +var ParticleProcessor = __webpack_require__(20286); + +/** + * @classdesc + * The Gravity Well Particle Processor applies a force on the particles to draw + * them towards, or repel them from, a single point. + * + * The force applied is inversely proportional to the square of the distance + * from the particle to the point, in accordance with Newton's law of gravity. + * + * This simulates the effect of gravity over large distances (as between planets, for example). + * + * @class GravityWell + * @extends Phaser.GameObjects.Particles.ParticleProcessor + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.0.0 + * + * @param {(number|Phaser.Types.GameObjects.Particles.GravityWellConfig)} [x=0] - The x coordinate of the Gravity Well, in world space. + * @param {number} [y=0] - The y coordinate of the Gravity Well, in world space. + * @param {number} [power=0] - The strength of the gravity force - larger numbers produce a stronger force. + * @param {number} [epsilon=100] - The minimum distance for which the gravity force is calculated. + * @param {number} [gravity=50] - The gravitational force of this Gravity Well. + */ +var GravityWell = new Class({ + + Extends: ParticleProcessor, + + initialize: + + function GravityWell (x, y, power, epsilon, gravity) + { + if (typeof x === 'object') + { + var config = x; + + x = GetFastValue(config, 'x', 0); + y = GetFastValue(config, 'y', 0); + power = GetFastValue(config, 'power', 0); + epsilon = GetFastValue(config, 'epsilon', 100); + gravity = GetFastValue(config, 'gravity', 50); + } + else + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (power === undefined) { power = 0; } + if (epsilon === undefined) { epsilon = 100; } + if (gravity === undefined) { gravity = 50; } + } + + ParticleProcessor.call(this, x, y, true); + + /** + * Internal gravity value. + * + * @name Phaser.GameObjects.Particles.GravityWell#_gravity + * @type {number} + * @private + * @since 3.0.0 + */ + this._gravity = gravity; + + /** + * Internal power value. + * + * @name Phaser.GameObjects.Particles.GravityWell#_power + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._power = power * gravity; + + /** + * Internal epsilon value. + * + * @name Phaser.GameObjects.Particles.GravityWell#_epsilon + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._epsilon = epsilon * epsilon; + }, + + /** + * Takes a Particle and updates it based on the properties of this Gravity Well. + * + * @method Phaser.GameObjects.Particles.GravityWell#update + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The Particle to update. + * @param {number} delta - The delta time in ms. + * @param {number} step - The delta value divided by 1000. + */ + update: function (particle, delta) + { + var x = this.x - particle.x; + var y = this.y - particle.y; + var dSq = x * x + y * y; + + if (dSq === 0) + { + return; + } + + var d = Math.sqrt(dSq); + + if (dSq < this._epsilon) + { + dSq = this._epsilon; + } + + var factor = ((this._power * delta) / (dSq * d)) * 100; + + particle.velocityX += x * factor; + particle.velocityY += y * factor; + }, + + /** + * The minimum distance for which the gravity force is calculated. + * + * Defaults to 100. + * + * @name Phaser.GameObjects.Particles.GravityWell#epsilon + * @type {number} + * @since 3.0.0 + */ + epsilon: { + + get: function () + { + return Math.sqrt(this._epsilon); + }, + + set: function (value) + { + this._epsilon = value * value; + } + + }, + + /** + * The strength of the gravity force - larger numbers produce a stronger force. + * + * Defaults to 0. + * + * @name Phaser.GameObjects.Particles.GravityWell#power + * @type {number} + * @since 3.0.0 + */ + power: { + + get: function () + { + return this._power / this._gravity; + }, + + set: function (value) + { + this._power = value * this._gravity; + } + + }, + + /** + * The gravitational force of this Gravity Well. + * + * Defaults to 50. + * + * @name Phaser.GameObjects.Particles.GravityWell#gravity + * @type {number} + * @since 3.0.0 + */ + gravity: { + + get: function () + { + return this._gravity; + }, + + set: function (value) + { + var pwr = this.power; + this._gravity = value; + this.power = pwr; + } + + } + +}); + +module.exports = GravityWell; + + +/***/ }), + +/***/ 56480: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AnimationState = __webpack_require__(9674); +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var DegToRad = __webpack_require__(39506); +var Rectangle = __webpack_require__(87841); +var RotateAround = __webpack_require__(11520); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Particle is a simple object owned and controlled by a Particle Emitter. + * + * It encapsulates all of the properties required to move and update according + * to the Emitters operations. + * + * @class Particle + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - The Emitter to which this Particle belongs. + */ +var Particle = new Class({ + + initialize: + + function Particle (emitter) + { + /** + * The Emitter to which this Particle belongs. + * + * A Particle can only belong to a single Emitter and is created, updated and destroyed by it. + * + * @name Phaser.GameObjects.Particles.Particle#emitter + * @type {Phaser.GameObjects.Particles.ParticleEmitter} + * @since 3.0.0 + */ + this.emitter = emitter; + + /** + * The texture used by this Particle when it renders. + * + * @name Phaser.GameObjects.Particles.Particle#texture + * @type {Phaser.Textures.Texture} + * @default null + * @since 3.60.0 + */ + this.texture = null; + + /** + * The texture frame used by this Particle when it renders. + * + * @name Phaser.GameObjects.Particles.Particle#frame + * @type {Phaser.Textures.Frame} + * @default null + * @since 3.0.0 + */ + this.frame = null; + + /** + * The x coordinate of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = 0; + + /** + * The y coordinate of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = 0; + + /** + * The coordinates of this Particle in world space. + * + * Updated as part of `computeVelocity`. + * + * @name Phaser.GameObjects.Particles.Particle#worldPosition + * @type {Phaser.Math.Vector2} + * @since 3.60.0 + */ + this.worldPosition = new Vector2(); + + /** + * The x velocity of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#velocityX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.velocityX = 0; + + /** + * The y velocity of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#velocityY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.velocityY = 0; + + /** + * The x acceleration of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#accelerationX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.accelerationX = 0; + + /** + * The y acceleration of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#accelerationY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.accelerationY = 0; + + /** + * The maximum horizontal velocity this Particle can travel at. + * + * @name Phaser.GameObjects.Particles.Particle#maxVelocityX + * @type {number} + * @default 10000 + * @since 3.0.0 + */ + this.maxVelocityX = 10000; + + /** + * The maximum vertical velocity this Particle can travel at. + * + * @name Phaser.GameObjects.Particles.Particle#maxVelocityY + * @type {number} + * @default 10000 + * @since 3.0.0 + */ + this.maxVelocityY = 10000; + + /** + * The bounciness, or restitution, of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#bounce + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.bounce = 0; + + /** + * The horizontal scale of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#scaleX + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.scaleX = 1; + + /** + * The vertical scale of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#scaleY + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.scaleY = 1; + + /** + * The alpha value of this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#alpha + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.alpha = 1; + + /** + * The angle of this Particle in degrees. + * + * @name Phaser.GameObjects.Particles.Particle#angle + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.angle = 0; + + /** + * The angle of this Particle in radians. + * + * @name Phaser.GameObjects.Particles.Particle#rotation + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.rotation = 0; + + /** + * The tint applied to this Particle. + * + * @name Phaser.GameObjects.Particles.Particle#tint + * @type {number} + * @webglOnly + * @since 3.0.0 + */ + this.tint = 0xffffff; + + /** + * The lifespan of this Particle in ms. + * + * @name Phaser.GameObjects.Particles.Particle#life + * @type {number} + * @default 1000 + * @since 3.0.0 + */ + this.life = 1000; + + /** + * The current life of this Particle in ms. + * + * @name Phaser.GameObjects.Particles.Particle#lifeCurrent + * @type {number} + * @default 1000 + * @since 3.0.0 + */ + this.lifeCurrent = 1000; + + /** + * The delay applied to this Particle upon emission, in ms. + * + * @name Phaser.GameObjects.Particles.Particle#delayCurrent + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.delayCurrent = 0; + + /** + * The hold applied to this Particle before it expires, in ms. + * + * @name Phaser.GameObjects.Particles.Particle#holdCurrent + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.holdCurrent = 0; + + /** + * The normalized lifespan T value, where 0 is the start and 1 is the end. + * + * @name Phaser.GameObjects.Particles.Particle#lifeT + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.lifeT = 0; + + /** + * The data used by the ease equation. + * + * @name Phaser.GameObjects.Particles.Particle#data + * @type {Phaser.Types.GameObjects.Particles.ParticleData} + * @since 3.0.0 + */ + this.data = { + tint: { min: 0xffffff, max: 0xffffff }, + alpha: { min: 1, max: 1 }, + rotate: { min: 0, max: 0 }, + scaleX: { min: 1, max: 1 }, + scaleY: { min: 1, max: 1 }, + x: { min: 0, max: 0 }, + y: { min: 0, max: 0 }, + accelerationX: { min: 0, max: 0 }, + accelerationY: { min: 0, max: 0 }, + maxVelocityX: { min: 0, max: 0 }, + maxVelocityY: { min: 0, max: 0 }, + moveToX: { min: 0, max: 0 }, + moveToY: { min: 0, max: 0 }, + bounce: { min: 0, max: 0 } + }; + + /** + * Internal private value. + * + * @name Phaser.GameObjects.Particles.Particle#isCropped + * @type {boolean} + * @private + * @readonly + * @since 3.60.0 + */ + this.isCropped = false; + + /** + * A reference to the Scene to which this Game Object belongs. + * + * Game Objects can only belong to one Scene. + * + * You should consider this property as being read-only. You cannot move a + * Game Object to another Scene by simply changing it. + * + * @name Phaser.GameObjects.Particles.Particle#scene + * @type {Phaser.Scene} + * @since 3.60.0 + */ + this.scene = emitter.scene; + + /** + * The Animation State component of this Particle. + * + * This component provides features to apply animations to this Particle. + * It is responsible for playing, loading, queuing animations for later playback, + * mixing between animations and setting the current animation frame to this Particle. + * + * It is created only if the Particle's Emitter has at least one Animation. + * + * @name Phaser.GameObjects.Particles.Particle#anims + * @type {?Phaser.Animations.AnimationState} + * @since 3.60.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setAnim + */ + this.anims = null; + + if (this.emitter.anims.length > 0) + { + this.anims = new AnimationState(this); + } + + /** + * A rectangle that holds the bounds of this Particle after a call to + * the `Particle.getBounds` method has been made. + * + * @name Phaser.GameObjects.Particles.Particle#bounds + * @type {Phaser.Geom.Rectangle} + * @since 3.60.0 + */ + this.bounds = new Rectangle(); + }, + + /** + * The Event Emitter proxy. + * + * Passes on all parameters to the `ParticleEmitter` to emit directly. + * + * @method Phaser.GameObjects.Particles.Particle#emit + * @since 3.60.0 + * + * @param {(string|Symbol)} event - The event name. + * @param {any} [a1] - Optional argument 1. + * @param {any} [a2] - Optional argument 2. + * @param {any} [a3] - Optional argument 3. + * @param {any} [a4] - Optional argument 4. + * @param {any} [a5] - Optional argument 5. + * + * @return {boolean} `true` if the event had listeners, else `false`. + */ + emit: function (event, a1, a2, a3, a4, a5) + { + return this.emitter.emit(event, a1, a2, a3, a4, a5); + }, + + /** + * Checks to see if this Particle is alive and updating. + * + * @method Phaser.GameObjects.Particles.Particle#isAlive + * @since 3.0.0 + * + * @return {boolean} `true` if this Particle is alive and updating, otherwise `false`. + */ + isAlive: function () + { + return (this.lifeCurrent > 0); + }, + + /** + * Kills this particle. This sets the `lifeCurrent` value to 0, which forces + * the Particle to be removed the next time its parent Emitter runs an update. + * + * @method Phaser.GameObjects.Particles.Particle#kill + * @since 3.60.0 + */ + kill: function () + { + this.lifeCurrent = 0; + }, + + /** + * Sets the position of this particle to the given x/y coordinates. + * + * If the parameters are left undefined, it resets the particle back to 0x0. + * + * @method Phaser.GameObjects.Particles.Particle#setPosition + * @since 3.60.0 + * + * @param {number} [x=0] - The x coordinate to set this Particle to. + * @param {number} [y=0] - The y coordinate to set this Particle to. + */ + setPosition: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + this.x = x; + this.y = y; + }, + + /** + * Starts this Particle from the given coordinates. + * + * @method Phaser.GameObjects.Particles.Particle#fire + * @since 3.0.0 + * + * @param {number} [x] - The x coordinate to launch this Particle from. + * @param {number} [y] - The y coordinate to launch this Particle from. + * + * @return {boolean} `true` if the Particle is alive, or `false` if it was spawned inside a DeathZone. + */ + fire: function (x, y) + { + var emitter = this.emitter; + var ops = emitter.ops; + + var anim = emitter.getAnim(); + + if (anim) + { + this.anims.play(anim); + } + else + { + this.frame = emitter.getFrame(); + this.texture = this.frame.texture; + } + + if (!this.frame) + { + throw new Error('Particle has no texture frame'); + } + + // Updates particle.x and particle.y during this call + emitter.getEmitZone(this); + + if (x === undefined) + { + this.x += ops.x.onEmit(this, 'x'); + } + else if (ops.x.steps > 0) + { + // EmitterOp is stepped but x was forced (follower?) so use it + this.x += x + ops.x.onEmit(this, 'x'); + } + else + { + this.x += x; + } + + if (y === undefined) + { + this.y += ops.y.onEmit(this, 'y'); + } + else if (ops.y.steps > 0) + { + // EmitterOp is stepped but y was forced (follower?) so use it + this.y += y + ops.y.onEmit(this, 'y'); + } + else + { + this.y += y; + } + + this.life = ops.lifespan.onEmit(this, 'lifespan'); + this.lifeCurrent = this.life; + this.lifeT = 0; + + this.delayCurrent = ops.delay.onEmit(this, 'delay'); + this.holdCurrent = ops.hold.onEmit(this, 'hold'); + + this.scaleX = ops.scaleX.onEmit(this, 'scaleX'); + this.scaleY = (ops.scaleY.active) ? ops.scaleY.onEmit(this, 'scaleY') : this.scaleX; + + this.angle = ops.rotate.onEmit(this, 'rotate'); + + this.rotation = DegToRad(this.angle); + + emitter.worldMatrix.transformPoint(this.x, this.y, this.worldPosition); + + // Check we didn't spawn in the middle of a DeathZone + if (this.delayCurrent === 0 && emitter.getDeathZone(this)) + { + this.lifeCurrent = 0; + + return false; + } + + var sx = ops.speedX.onEmit(this, 'speedX'); + var sy = (ops.speedY.active) ? ops.speedY.onEmit(this, 'speedY') : sx; + + if (emitter.radial) + { + var rad = DegToRad(ops.angle.onEmit(this, 'angle')); + + this.velocityX = Math.cos(rad) * Math.abs(sx); + this.velocityY = Math.sin(rad) * Math.abs(sy); + } + else if (emitter.moveTo) + { + var mx = ops.moveToX.onEmit(this, 'moveToX'); + var my = ops.moveToY.onEmit(this, 'moveToY'); + var lifeS = this.life / 1000; + + this.velocityX = (mx - this.x) / lifeS; + this.velocityY = (my - this.y) / lifeS; + } + else + { + this.velocityX = sx; + this.velocityY = sy; + } + + if (emitter.acceleration) + { + this.accelerationX = ops.accelerationX.onEmit(this, 'accelerationX'); + this.accelerationY = ops.accelerationY.onEmit(this, 'accelerationY'); + } + + this.maxVelocityX = ops.maxVelocityX.onEmit(this, 'maxVelocityX'); + this.maxVelocityY = ops.maxVelocityY.onEmit(this, 'maxVelocityY'); + + this.bounce = ops.bounce.onEmit(this, 'bounce'); + + this.alpha = ops.alpha.onEmit(this, 'alpha'); + + if (ops.color.active) + { + this.tint = ops.color.onEmit(this, 'tint'); + } + else + { + this.tint = ops.tint.onEmit(this, 'tint'); + } + + return true; + }, + + /** + * The main update method for this Particle. + * + * Updates its life values, computes the velocity and repositions the Particle. + * + * @method Phaser.GameObjects.Particles.Particle#update + * @since 3.0.0 + * + * @param {number} delta - The delta time in ms. + * @param {number} step - The delta value divided by 1000. + * @param {Phaser.GameObjects.Particles.ParticleProcessor[]} processors - An array of all active Particle Processors. + * + * @return {boolean} Returns `true` if this Particle has now expired and should be removed, otherwise `false` if still active. + */ + update: function (delta, step, processors) + { + if (this.lifeCurrent <= 0) + { + // Particle is dead via `Particle.kill` method, or being held + if (this.holdCurrent > 0) + { + this.holdCurrent -= delta; + + return (this.holdCurrent <= 0); + } + else + { + return true; + } + } + + if (this.delayCurrent > 0) + { + this.delayCurrent -= delta; + + return false; + } + + if (this.anims) + { + this.anims.update(0, delta); + } + + var emitter = this.emitter; + var ops = emitter.ops; + + // How far along in life is this particle? (t = 0 to 1) + var t = 1 - (this.lifeCurrent / this.life); + + this.lifeT = t; + + this.x = ops.x.onUpdate(this, 'x', t, this.x); + this.y = ops.y.onUpdate(this, 'y', t, this.y); + + if (emitter.moveTo) + { + var mx = ops.moveToX.onUpdate(this, 'moveToX', t, emitter.moveToX); + var my = ops.moveToY.onUpdate(this, 'moveToY', t, emitter.moveToY); + var lifeS = this.lifeCurrent / 1000; + + this.velocityX = (mx - this.x) / lifeS; + this.velocityY = (my - this.y) / lifeS; + } + + this.computeVelocity(emitter, delta, step, processors, t); + + this.scaleX = ops.scaleX.onUpdate(this, 'scaleX', t, this.scaleX); + + if (ops.scaleY.active) + { + this.scaleY = ops.scaleY.onUpdate(this, 'scaleY', t, this.scaleY); + } + else + { + this.scaleY = this.scaleX; + } + + this.angle = ops.rotate.onUpdate(this, 'rotate', t, this.angle); + + this.rotation = DegToRad(this.angle); + + if (emitter.getDeathZone(this)) + { + this.lifeCurrent = 0; + + // No need to go any further, particle has been killed + return true; + } + + this.alpha = Clamp(ops.alpha.onUpdate(this, 'alpha', t, this.alpha), 0, 1); + + if (ops.color.active) + { + this.tint = ops.color.onUpdate(this, 'color', t, this.tint); + } + else + { + this.tint = ops.tint.onUpdate(this, 'tint', t, this.tint); + } + + this.lifeCurrent -= delta; + + return (this.lifeCurrent <= 0 && this.holdCurrent <= 0); + }, + + /** + * An internal method that calculates the velocity of the Particle and + * its world position. It also runs it against any active Processors + * that are set on the Emitter. + * + * @method Phaser.GameObjects.Particles.Particle#computeVelocity + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - The Emitter that is updating this Particle. + * @param {number} delta - The delta time in ms. + * @param {number} step - The delta value divided by 1000. + * @param {Phaser.GameObjects.Particles.ParticleProcessor[]} processors - An array of all active Particle Processors. + * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + */ + computeVelocity: function (emitter, delta, step, processors, t) + { + var ops = emitter.ops; + + var vx = this.velocityX; + var vy = this.velocityY; + + var ax = ops.accelerationX.onUpdate(this, 'accelerationX', t, this.accelerationX); + var ay = ops.accelerationY.onUpdate(this, 'accelerationY', t, this.accelerationY); + + var mx = ops.maxVelocityX.onUpdate(this, 'maxVelocityX', t, this.maxVelocityX); + var my = ops.maxVelocityY.onUpdate(this, 'maxVelocityY', t, this.maxVelocityY); + + this.bounce = ops.bounce.onUpdate(this, 'bounce', t, this.bounce); + + vx += (emitter.gravityX * step) + (ax * step); + vy += (emitter.gravityY * step) + (ay * step); + + vx = Clamp(vx, -mx, mx); + vy = Clamp(vy, -my, my); + + this.velocityX = vx; + this.velocityY = vy; + + // Integrate back in to the position + this.x += vx * step; + this.y += vy * step; + + emitter.worldMatrix.transformPoint(this.x, this.y, this.worldPosition); + + // Apply any additional processors (these can update velocity and/or position) + for (var i = 0; i < processors.length; i++) + { + var processor = processors[i]; + + if (processor.active) + { + processor.update(this, delta, step, t); + } + } + }, + + /** + * This is a NOOP method and does nothing when called. + * + * @method Phaser.GameObjects.Particles.Particle#setSizeToFrame + * @since 3.60.0 + */ + setSizeToFrame: function () + { + // NOOP + }, + + /** + * Gets the bounds of this particle as a Geometry Rectangle, factoring in any + * transforms of the parent emitter and anything else above it in the display list. + * + * Once calculated the bounds can be accessed via the `Particle.bounds` property. + * + * @method Phaser.GameObjects.Particles.Particle#getBounds + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} [matrix] - Optional transform matrix to apply to this particle. + * + * @return {Phaser.Geom.Rectangle} A Rectangle containing the transformed bounds of this particle. + */ + getBounds: function (matrix) + { + if (matrix === undefined) { matrix = this.emitter.getWorldTransformMatrix(); } + + var sx = Math.abs(matrix.scaleX) * this.scaleX; + var sy = Math.abs(matrix.scaleY) * this.scaleY; + + var x = this.x; + var y = this.y; + var rotation = this.rotation; + var width = (this.frame.width * sx) / 2; + var height = (this.frame.height * sy) / 2; + + var bounds = this.bounds; + + var topLeft = new Vector2(x - width, y - height); + var topRight = new Vector2(x + width, y - height); + var bottomLeft = new Vector2(x - width, y + height); + var bottomRight = new Vector2(x + width, y + height); + + if (rotation !== 0) + { + RotateAround(topLeft, x, y, rotation); + RotateAround(topRight, x, y, rotation); + RotateAround(bottomLeft, x, y, rotation); + RotateAround(bottomRight, x, y, rotation); + } + + matrix.transformPoint(topLeft.x, topLeft.y, topLeft); + matrix.transformPoint(topRight.x, topRight.y, topRight); + matrix.transformPoint(bottomLeft.x, bottomLeft.y, bottomLeft); + matrix.transformPoint(bottomRight.x, bottomRight.y, bottomRight); + + bounds.x = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); + bounds.y = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); + bounds.width = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x) - bounds.x; + bounds.height = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y) - bounds.y; + + return bounds; + }, + + /** + * Destroys this Particle. + * + * @method Phaser.GameObjects.Particles.Particle#destroy + * @since 3.60.0 + */ + destroy: function () + { + if (this.anims) + { + this.anims.destroy(); + } + + this.anims = null; + this.emitter = null; + this.texture = null; + this.frame = null; + this.scene = null; + } + +}); + +module.exports = Particle; + + +/***/ }), + +/***/ 69601: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var ParticleProcessor = __webpack_require__(20286); +var Rectangle = __webpack_require__(87841); + +/** + * @classdesc + * The Particle Bounds Processor. + * + * Defines a rectangular region, in world space, within which particle movement + * is restrained. + * + * Use the properties `collideLeft`, `collideRight`, `collideTop` and + * `collideBottom` to control if a particle will rebound off the sides + * of this boundary, or not. + * + * This happens when the particles worldPosition x/y coordinate hits the boundary. + * + * The strength of the rebound is determined by the `Particle.bounce` property. + * + * @class ParticleBounds + * @extends Phaser.GameObjects.Particles.ParticleProcessor + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.60.0 + * + * @param {number} x - The x position (top-left) of the bounds, in world space. + * @param {number} y - The y position (top-left) of the bounds, in world space. + * @param {number} width - The width of the bounds. + * @param {number} height - The height of the bounds. + * @param {boolean} [collideLeft=true] - Whether particles interact with the left edge of the bounds. + * @param {boolean} [collideRight=true] - Whether particles interact with the right edge of the bounds. + * @param {boolean} [collideTop=true] - Whether particles interact with the top edge of the bounds. + * @param {boolean} [collideBottom=true] - Whether particles interact with the bottom edge of the bounds. + */ +var ParticleBounds = new Class({ + + Extends: ParticleProcessor, + + initialize: + + function ParticleBounds (x, y, width, height, collideLeft, collideRight, collideTop, collideBottom) + { + if (collideLeft === undefined) { collideLeft = true; } + if (collideRight === undefined) { collideRight = true; } + if (collideTop === undefined) { collideTop = true; } + if (collideBottom === undefined) { collideBottom = true; } + + ParticleProcessor.call(this, x, y, true); + + /** + * A rectangular boundary constraining particle movement. Use the Emitter properties `collideLeft`, + * `collideRight`, `collideTop` and `collideBottom` to control if a particle will rebound off + * the sides of this boundary, or not. This happens when the particles x/y coordinate hits + * the boundary. + * + * @name Phaser.GameObjects.Particles.ParticleBounds#bounds + * @type {Phaser.Geom.Rectangle} + * @since 3.60.0 + */ + this.bounds = new Rectangle(x, y, width, height); + + /** + * Whether particles interact with the left edge of the emitter {@link Phaser.GameObjects.Particles.ParticleEmitter#bounds}. + * + * @name Phaser.GameObjects.Particles.ParticleBounds#collideLeft + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.collideLeft = collideLeft; + + /** + * Whether particles interact with the right edge of the emitter {@link Phaser.GameObjects.Particles.ParticleBounds#bounds}. + * + * @name Phaser.GameObjects.Particles.ParticleBounds#collideRight + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.collideRight = collideRight; + + /** + * Whether particles interact with the top edge of the emitter {@link Phaser.GameObjects.Particles.ParticleBounds#bounds}. + * + * @name Phaser.GameObjects.Particles.ParticleBounds#collideTop + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.collideTop = collideTop; + + /** + * Whether particles interact with the bottom edge of the emitter {@link Phaser.GameObjects.Particles.ParticleBounds#bounds}. + * + * @name Phaser.GameObjects.Particles.ParticleBounds#collideBottom + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.collideBottom = collideBottom; + }, + + /** + * Takes a Particle and updates it against the bounds. + * + * @method Phaser.GameObjects.Particles.ParticleBounds#update + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The Particle to update. + */ + update: function (particle) + { + var bounds = this.bounds; + var bounce = -particle.bounce; + var pos = particle.worldPosition; + + if (pos.x < bounds.x && this.collideLeft) + { + particle.x += bounds.x - pos.x; + particle.velocityX *= bounce; + } + else if (pos.x > bounds.right && this.collideRight) + { + particle.x -= pos.x - bounds.right; + particle.velocityX *= bounce; + } + + if (pos.y < bounds.y && this.collideTop) + { + particle.y += bounds.y - pos.y; + particle.velocityY *= bounce; + } + else if (pos.y > bounds.bottom && this.collideBottom) + { + particle.y -= pos.y - bounds.bottom; + particle.velocityY *= bounce; + } + } + +}); + +module.exports = ParticleBounds; + + +/***/ }), + +/***/ 31600: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultParticleEmitterNodes = __webpack_require__(68668); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var ComponentsToJSON = __webpack_require__(53774); +var CopyFrom = __webpack_require__(43459); +var DeathZone = __webpack_require__(26388); +var EdgeZone = __webpack_require__(19909); +var EmitterColorOp = __webpack_require__(76472); +var EmitterOp = __webpack_require__(44777); +var Events = __webpack_require__(20696); +var GameObject = __webpack_require__(95643); +var GetFastValue = __webpack_require__(95540); +var GetRandom = __webpack_require__(26546); +var GravityWell = __webpack_require__(24502); +var HasAll = __webpack_require__(69036); +var HasAny = __webpack_require__(1985); +var HasValue = __webpack_require__(97022); +var Inflate = __webpack_require__(86091); +var List = __webpack_require__(73162); +var MergeRect = __webpack_require__(20074); +var MergeRight = __webpack_require__(269); +var Particle = __webpack_require__(56480); +var ParticleBounds = __webpack_require__(69601); +var RandomZone = __webpack_require__(68875); +var Rectangle = __webpack_require__(87841); +var RectangleToRectangle = __webpack_require__(59996); +var Remove = __webpack_require__(72905); +var Render = __webpack_require__(90668); +var StableSort = __webpack_require__(19186); +var TransformMatrix = __webpack_require__(61340); +var Vector2 = __webpack_require__(26099); +var Wrap = __webpack_require__(15994); + +/** + * Names of simple configuration properties. + * + * @ignore + */ +var configFastMap = [ + 'active', + 'advance', + 'blendMode', + 'colorEase', + 'deathCallback', + 'deathCallbackScope', + 'duration', + 'emitCallback', + 'emitCallbackScope', + 'follow', + 'frequency', + 'gravityX', + 'gravityY', + 'maxAliveParticles', + 'maxParticles', + 'name', + 'emitting', + 'particleBringToTop', + 'particleClass', + 'radial', + 'sortCallback', + 'sortOrderAsc', + 'sortProperty', + 'stopAfter', + 'tintFill', + 'timeScale', + 'trackVisible', + 'visible' +]; + +/** + * Names of complex configuration properties. + * + * @ignore + */ +var configOpMap = [ + 'accelerationX', + 'accelerationY', + 'alpha', + 'angle', + 'bounce', + 'color', + 'delay', + 'hold', + 'lifespan', + 'maxVelocityX', + 'maxVelocityY', + 'moveToX', + 'moveToY', + 'quantity', + 'rotate', + 'scaleX', + 'scaleY', + 'speedX', + 'speedY', + 'tint', + 'x', + 'y' +]; + +/** + * @classdesc + * A Particle Emitter is a special kind of Game Object that controls a pool of {@link Phaser.GameObjects.Particles.Particle Particles}. + * + * Particle Emitters are created via a configuration object. The properties of this object + * can be specified in a variety of formats, given you plenty of scope over the values they + * return, leading to complex visual effects. Here are the different forms of configuration + * value you can give: + * + * ## An explicit static value: + * + * ```js + * x: 400 + * ``` + * + * The x value will always be 400 when the particle is spawned. + * + * ## A random value: + * + * ```js + * x: [ 100, 200, 300, 400 ] + * ``` + * + * The x value will be one of the 4 elements in the given array, picked at random on emission. + * + * ## A custom callback: + * + * ```js + * x: (particle, key, t, value) => { + * return value + 50; + * } + * ``` + * + * The x value is the result of calling this function. This is only used when the + * particle is emitted, so it provides it's initial starting value. It is not used + * when the particle is updated (see the onUpdate callback for that) + * + * ## A start / end object: + * + * This allows you to control the change in value between the given start and + * end parameters over the course of the particles lifetime: + * + * ```js + * scale: { start: 0, end: 1 } + * ``` + * + * The particle scale will start at 0 when emitted and ease to a scale of 1 + * over the course of its lifetime. You can also specify the ease function + * used for this change (the default is Linear): + * + * ```js + * scale: { start: 0, end: 1, ease: 'bounce.out' } + * ``` + * + * ## A start / end random object: + * + * The start and end object can have an optional `random` parameter. + * This forces it to pick a random value between the two values and use + * this as the starting value, then easing to the 'end' parameter over + * its lifetime. + * + * ```js + * scale: { start: 4, end: 0.5, random: true } + * ``` + * + * The particle will start with a random scale between 0.5 and 4 and then + * scale to the end value over its lifetime. You can combine the above + * with the `ease` parameter as well to control the value easing. + * + * ## An interpolation object: + * + * You can provide an array of values which will be used for interpolation + * during the particles lifetime. You can also define the interpolation + * function to be used. There are three provided: `linear` (the default), + * `bezier` and `catmull`, or you can provide your own function. + * + * ```js + * x: { values: [ 50, 500, 200, 800 ], interpolation: 'catmull' } + * ``` + * + * The particle scale will interpolate from 50 when emitted to 800 via the other + * points over the course of its lifetime. You can also specify an ease function + * used to control the rate of change through the values (the default is Linear): + * + * ```js + * x: { values: [ 50, 500, 200, 800 ], interpolation: 'catmull', ease: 'bounce.out } + * ``` + * + * ## A stepped emitter object: + * + * The `steps` parameter allows you to control the placement of sequential + * particles across the start-end range: + * + * ```js + * x: { steps: 32, start: 0, end: 576 } + * ``` + * + * Here we have a range of 576 (start to end). This is divided into 32 steps. + * + * The first particle will emit at the x position of 0. The next will emit + * at the next 'step' along, which would be 18. The following particle will emit + * at the next step, which is 36, and so on. Because the range of 576 has been + * divided by 32, creating 18 pixels steps. When a particle reaches the 'end' + * value the next one will start from the beginning again. + * + * ## A stepped emitter object with yoyo: + * + * You can add the optional `yoyo` property to a stepped object: + * + * ```js + * x: { steps: 32, start: 0, end: 576, yoyo: true } + * ``` + * + * As with the stepped emitter, particles are emitted in sequence, from 'start' + * to 'end' in step sized jumps. Normally, when a stepped emitter reaches the + * end it snaps around to the start value again. However, if you provide the 'yoyo' + * parameter then when it reaches the end it will reverse direction and start + * emitting back down to 'start' again. Depending on the effect you require this + * can often look better. + * + * ## A min / max object: + * + * This allows you to pick a random float value between the min and max properties: + * + * ```js + * x: { min: 100, max: 700 } + * ``` + * + * The x value will be a random float between min and max. + * + * You can force it select an integer by setting the 'int' flag: + * + * ```js + * x: { min: 100, max: 700, int: true } + * ``` + * + * Or, you could use the 'random' array approach (see below) + * + * ## A random object: + * + * This allows you to pick a random integer value between the first and second array elements: + * + * ```js + * x: { random: [ 100, 700 ] } + * ``` + * + * The x value will be a random integer between 100 and 700 as it takes the first + * element in the 'random' array as the 'min' value and the 2nd element as the 'max' value. + * + * ## Custom onEmit and onUpdate callbacks: + * + * If the above won't give you the effect you're after, you can provide your own + * callbacks that will be used when the particle is both emitted and updated: + * + * ```js + * x: { + * onEmit: (particle, key, t, value) => { + * return value; + * }, + * onUpdate: (particle, key, t, value) => { + * return value; + * } + * } + * ``` + * + * You can provide either one or both functions. The `onEmit` is called at the + * start of the particles life and defines the value of the property on birth. + * + * The `onUpdate` function is called every time the Particle Emitter updates + * until the particle dies. Both must return a value. + * + * The properties are: + * + * particle - A reference to the Particle instance. + * key - The string based key of the property, i.e. 'x' or 'lifespan'. + * t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + * value - The current property value. At a minimum you should return this. + * + * By using the above configuration options you have an unlimited about of + * control over how your particles behave. + * + * ## v3.55 Differences + * + * Prior to v3.60 Phaser used a `ParticleEmitterManager`. This was removed in v3.60 + * and now calling `this.add.particles` returns a `ParticleEmitter` instance instead. + * + * In order to streamline memory and the display list we have removed the + * `ParticleEmitterManager` entirely. When you call `this.add.particles` you're now + * creating a `ParticleEmitter` instance, which is being added directly to the + * display list and can be manipulated just like any other Game Object, i.e. + * scaled, rotated, positioned, added to a Container, etc. It now extends the + * `GameObject` base class, meaning it's also an event emitter, which allowed us + * to create some handy new events for particles. + * + * So, to create an emitter, you now give it an xy coordinate, a texture and an + * emitter configuration object (you can also set this later, but most commonly + * you'd do it on creation). I.e.: + * + * ```js + * const emitter = this.add.particles(100, 300, 'flares', { + * frame: 'red', + * angle: { min: -30, max: 30 }, + * speed: 150 + * }); + * ``` + * + * This will create a 'red flare' emitter at 100 x 300. + * + * Please update your code to ensure it adheres to the new function signatures. + * + * @class ParticleEmitter + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.60.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x] - The horizontal position of this Game Object in the world. + * @param {number} [y] - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} [texture] - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} [config] - Settings for this emitter. + */ +var ParticleEmitter = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.Lighting, + Components.Mask, + Components.RenderNodes, + Components.ScrollFactor, + Components.Texture, + Components.Transform, + Components.Visible, + Render + ], + + initialize: + + function ParticleEmitter (scene, x, y, texture, config) + { + GameObject.call(this, scene, 'ParticleEmitter'); + + /** + * The Particle Class which will be emitted by this Emitter. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleClass + * @type {function} + * @default Phaser.GameObjects.Particles.Particle + * @since 3.0.0 + * @see Phaser.Types.GameObjects.Particles.ParticleClassConstructor + */ + this.particleClass = Particle; + + /** + * An internal object holding the configuration for the Emitter. + * + * These are populated as part of the Emitter configuration parsing. + * + * You typically do not access them directly, but instead use the + * `ParticleEmitter.setConfig` or `ParticleEmitter.updateConfig` methods. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#config + * @type {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} + * @since 3.85.0 + */ + this.config = null; + + /** + * An internal object holding all of the EmitterOp instances. + * + * These are populated as part of the Emitter configuration parsing. + * + * You typically do not access them directly, but instead use the + * provided getters and setters on this class, such as `ParticleEmitter.speedX` etc. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#ops + * @type {Phaser.Types.GameObjects.Particles.ParticleEmitterOps} + * @since 3.60.0 + */ + this.ops = { + accelerationX: new EmitterOp('accelerationX', 0), + accelerationY: new EmitterOp('accelerationY', 0), + alpha: new EmitterOp('alpha', 1), + angle: new EmitterOp('angle', { min: 0, max: 360 }, true), + bounce: new EmitterOp('bounce', 0), + color: new EmitterColorOp('color'), + delay: new EmitterOp('delay', 0, true), + hold: new EmitterOp('hold', 0, true), + lifespan: new EmitterOp('lifespan', 1000, true), + maxVelocityX: new EmitterOp('maxVelocityX', 10000), + maxVelocityY: new EmitterOp('maxVelocityY', 10000), + moveToX: new EmitterOp('moveToX', 0), + moveToY: new EmitterOp('moveToY', 0), + quantity: new EmitterOp('quantity', 1, true), + rotate: new EmitterOp('rotate', 0), + scaleX: new EmitterOp('scaleX', 1), + scaleY: new EmitterOp('scaleY', 1), + speedX: new EmitterOp('speedX', 0, true), + speedY: new EmitterOp('speedY', 0, true), + tint: new EmitterOp('tint', 0xffffff), + x: new EmitterOp('x', 0), + y: new EmitterOp('y', 0) + }; + + /** + * A radial emitter will emit particles in all directions between angle min and max, + * using {@link Phaser.GameObjects.Particles.ParticleEmitter#speed} as the value. If set to false then this acts as a point Emitter. + * A point emitter will emit particles only in the direction derived from the speedX and speedY values. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#radial + * @type {boolean} + * @default true + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setRadial + */ + this.radial = true; + + /** + * Horizontal acceleration applied to emitted particles, in pixels per second squared. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#gravityX + * @type {number} + * @default 0 + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setGravity + */ + this.gravityX = 0; + + /** + * Vertical acceleration applied to emitted particles, in pixels per second squared. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#gravityY + * @type {number} + * @default 0 + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setGravity + */ + this.gravityY = 0; + + /** + * Whether accelerationX and accelerationY are non-zero. Set automatically during configuration. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#acceleration + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.acceleration = false; + + /** + * Whether moveToX and moveToY are set. Set automatically during configuration. + * + * When true the particles move toward the moveToX and moveToY coordinates and arrive at the end of their life. + * Emitter angle, speedX, and speedY are ignored. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#moveTo + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.moveTo = false; + + /** + * A function to call when a particle is emitted. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#emitCallback + * @type {?Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} + * @default null + * @since 3.0.0 + */ + this.emitCallback = null; + + /** + * The calling context for {@link Phaser.GameObjects.Particles.ParticleEmitter#emitCallback}. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#emitCallbackScope + * @type {?*} + * @default null + * @since 3.0.0 + */ + this.emitCallbackScope = null; + + /** + * A function to call when a particle dies. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#deathCallback + * @type {?Phaser.Types.GameObjects.Particles.ParticleDeathCallback} + * @default null + * @since 3.0.0 + */ + this.deathCallback = null; + + /** + * The calling context for {@link Phaser.GameObjects.Particles.ParticleEmitter#deathCallback}. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#deathCallbackScope + * @type {?*} + * @default null + * @since 3.0.0 + */ + this.deathCallbackScope = null; + + /** + * Set to hard limit the amount of particle objects this emitter is allowed to create + * in total. This is the number of `Particle` instances it can create, not the number + * of 'alive' particles. + * + * 0 means unlimited. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#maxParticles + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.maxParticles = 0; + + /** + * The maximum number of alive and rendering particles this emitter will update. + * When this limit is reached, a particle needs to die before another can be emitted. + * + * 0 means no limits. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#maxAliveParticles + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.maxAliveParticles = 0; + + /** + * If set, either via the Emitter config, or by directly setting this property, + * the Particle Emitter will stop emitting particles once this total has been + * reached. It will then enter a 'stopped' state, firing the `STOP` + * event. Note that entering a stopped state doesn't mean all the particles + * have finished, just that it's not emitting any further ones. + * + * To know when the final particle expires, listen for the COMPLETE event. + * + * Use this if you wish to launch an exact number of particles and then stop + * your emitter afterwards. + * + * The counter is reset each time the `ParticleEmitter.start` method is called. + * + * 0 means the emitter will not stop based on total emitted particles. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#stopAfter + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.stopAfter = 0; + + /** + * The number of milliseconds this emitter will emit particles for when in flow mode, + * before it stops emission. A value of 0 (the default) means there is no duration. + * + * When the duration expires the `STOP` event is emitted. Note that entering a + * stopped state doesn't mean all the particles have finished, just that it's + * not emitting any further ones. + * + * To know when the final particle expires, listen for the COMPLETE event. + * + * The counter is reset each time the `ParticleEmitter.start` method is called. + * + * 0 means the emitter will not stop based on duration. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#duration + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.duration = 0; + + /** + * For a flow emitter, the time interval (>= 0) between particle flow cycles in ms. + * A value of 0 means there is one particle flow cycle for each logic update (the maximum flow frequency). This is the default setting. + * For an exploding emitter, this value will be -1. + * Calling {@link Phaser.GameObjects.Particles.ParticleEmitter#flow} also puts the emitter in flow mode (frequency >= 0). + * Calling {@link Phaser.GameObjects.Particles.ParticleEmitter#explode} also puts the emitter in explode mode (frequency = -1). + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#frequency + * @type {number} + * @default 0 + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setFrequency + */ + this.frequency = 0; + + /** + * Controls if the emitter is currently emitting a particle flow (when frequency >= 0). + * + * Already alive particles will continue to update until they expire. + * + * Controlled by {@link Phaser.GameObjects.Particles.ParticleEmitter#start} and {@link Phaser.GameObjects.Particles.ParticleEmitter#stop}. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#emitting + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.emitting = true; + + /** + * Newly emitted particles are added to the top of the particle list, i.e. rendered above those already alive. + * + * Set to false to send them to the back. + * + * Also see the `sortOrder` property for more complex particle sorting. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleBringToTop + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.particleBringToTop = true; + + /** + * The time rate applied to active particles, affecting lifespan, movement, and tweens. Values larger than 1 are faster than normal. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#timeScale + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.timeScale = 1; + + /** + * An array containing Particle Emission Zones. These can be either EdgeZones or RandomZones. + * + * Particles are emitted from a randomly selected zone from this array. + * + * Prior to Phaser v3.60 an Emitter could only have one single Emission Zone. + * In 3.60 they can now have an array of Emission Zones. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#emitZones + * @type {Phaser.Types.GameObjects.Particles.EmitZoneObject[]} + * @since 3.60.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setEmitZone + */ + this.emitZones = []; + + /** + * An array containing Particle Death Zone objects. A particle is immediately killed as soon as its x/y coordinates + * intersect with any of the configured Death Zones. + * + * Prior to Phaser v3.60 an Emitter could only have one single Death Zone. + * In 3.60 they can now have an array of Death Zones. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#deathZones + * @type {Phaser.GameObjects.Particles.Zones.DeathZone[]} + * @since 3.60.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setDeathZone + */ + this.deathZones = []; + + /** + * An optional Rectangle object that is used during rendering to cull Particles from + * display. For example, if your particles are limited to only move within a 300x300 + * sized area from their origin, then you can set this Rectangle to those dimensions. + * + * The renderer will check to see if the `viewBounds` Rectangle intersects with the + * Camera bounds during the render step and if not it will skip rendering the Emitter + * entirely. + * + * This allows you to create many emitters in a Scene without the cost of + * rendering if the contents aren't visible. + * + * Note that the Emitter will not perform any checks to see if the Particles themselves + * are outside of these bounds, or not. It will simply check the bounds against the + * camera. Use the `getBounds` method with the `advance` parameter to help define + * the location and placement of the view bounds. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#viewBounds + * @type {?Phaser.Geom.Rectangle} + * @default null + * @since 3.60.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setViewBounds + */ + this.viewBounds = null; + + /** + * A Game Object whose position is used as the particle origin. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#follow + * @type {?Phaser.Types.Math.Vector2Like} + * @default null + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#startFollow + * @see Phaser.GameObjects.Particles.ParticleEmitter#stopFollow + */ + this.follow = null; + + /** + * The offset of the particle origin from the {@link Phaser.GameObjects.Particles.ParticleEmitter#follow} target. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#followOffset + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#startFollow + */ + this.followOffset = new Vector2(); + + /** + * Whether the emitter's {@link Phaser.GameObjects.Particles.ParticleEmitter#visible} state will track + * the {@link Phaser.GameObjects.Particles.ParticleEmitter#follow} target's visibility state. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#trackVisible + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#startFollow + */ + this.trackVisible = false; + + /** + * The texture frames assigned to particles. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#frames + * @type {Phaser.Textures.Frame[]} + * @since 3.0.0 + */ + this.frames = []; + + /** + * Whether texture {@link Phaser.GameObjects.Particles.ParticleEmitter#frames} are selected at random. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#randomFrame + * @type {boolean} + * @default true + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setEmitterFrame + */ + this.randomFrame = true; + + /** + * The number of consecutive particles that receive a single texture frame (per frame cycle). + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#frameQuantity + * @type {number} + * @default 1 + * @since 3.0.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setEmitterFrame + */ + this.frameQuantity = 1; + + /** + * The animations assigned to particles. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#anims + * @type {string[]} + * @since 3.60.0 + */ + this.anims = []; + + /** + * Whether animations {@link Phaser.GameObjects.Particles.ParticleEmitter#anims} are selected at random. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#randomAnim + * @type {boolean} + * @default true + * @since 3.60.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setAnim + */ + this.randomAnim = true; + + /** + * The number of consecutive particles that receive a single animation (per frame cycle). + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#animQuantity + * @type {number} + * @default 1 + * @since 3.60.0 + * @see Phaser.GameObjects.Particles.ParticleEmitter#setAnim + */ + this.animQuantity = 1; + + /** + * An array containing all currently inactive Particle instances. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#dead + * @type {Phaser.GameObjects.Particles.Particle[]} + * @private + * @since 3.0.0 + */ + this.dead = []; + + /** + * An array containing all currently live and rendering Particle instances. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#alive + * @type {Phaser.GameObjects.Particles.Particle[]} + * @private + * @since 3.0.0 + */ + this.alive = []; + + /** + * Internal array that holds counter data: + * + * 0 - flowCounter - The time until next flow cycle. + * 1 - frameCounter - Counts up to {@link Phaser.GameObjects.Particles.ParticleEmitter#frameQuantity}. + * 2 - animCounter - Counts up to animQuantity. + * 3 - elapsed - The time remaining until the `duration` limit is reached. + * 4 - stopCounter - The number of particles remaining until `stopAfter` limit is reached. + * 5 - completeFlag - Has the COMPLETE event been emitted? + * 6 - zoneIndex - The emit zone index counter. + * 7 - zoneTotal - The emit zone total counter. + * 8 - currentFrame - The current texture frame, as an index of {@link Phaser.GameObjects.Particles.ParticleEmitter#frames}. + * 9 - currentAnim - The current animation, as an index of {@link Phaser.GameObjects.Particles.ParticleEmitter#anims}. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#counters + * @type {Float32Array} + * @private + * @since 3.60.0 + */ + this.counters = new Float32Array(10); + + /** + * An internal property used to tell when the emitter is in fast-forwarc mode. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#skipping + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.skipping = false; + + /** + * An internal Transform Matrix used to cache this emitters world matrix. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#worldMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 3.60.0 + */ + this.worldMatrix = new TransformMatrix(); + + /** + * Optionally sort the particles before they render based on this + * property. The property must exist on the `Particle` class, such + * as `y`, `lifeT`, `scaleX`, etc. + * + * When set this overrides the `particleBringToTop` setting. + * + * To reset this and disable sorting, so this property to an empty string. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#sortProperty + * @type {string} + * @since 3.60.0 + */ + this.sortProperty = ''; + + /** + * When `sortProperty` is defined this controls the sorting order, + * either ascending or descending. Toggle to control the visual effect. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#sortOrderAsc + * @type {boolean} + * @since 3.60.0 + */ + this.sortOrderAsc = true; + + /** + * The callback used to sort the particles. Only used if `sortProperty` + * has been set. Set this via the `setSortCallback` method. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#sortCallback + * @type {?Phaser.Types.GameObjects.Particles.ParticleSortCallback} + * @since 3.60.0 + */ + this.sortCallback = this.depthSortCallback; + + /** + * A list of Particle Processors being managed by this Emitter. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#processors + * @type {Phaser.Structs.List.} + * @since 3.60.0 + */ + this.processors = new List(this); + + /** + * The tint fill mode used by the Particles in this Emitter. + * + * `false` = An additive tint (the default), where vertices colors are blended with the texture. + * `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#tintFill + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.tintFill = false; + + this.initRenderNodes(this._defaultRenderNodesMap); + + this.setPosition(x, y); + this.setTexture(texture); + + if (config) + { + this.setConfig(config); + } + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultParticleEmitterNodes; + } + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + /** + * Takes an Emitter Configuration file and resets this Emitter, using any + * properties defined in the config to then set it up again. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setConfig + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} config - Settings for this emitter. + * + * @return {this} This Particle Emitter. + */ + setConfig: function (config) + { + if (!config) + { + return this; + } + + this.config = config; + + var i = 0; + var key = ''; + + var ops = this.ops; + + for (i = 0; i < configOpMap.length; i++) + { + key = configOpMap[i]; + + ops[key].loadConfig(config); + } + + for (i = 0; i < configFastMap.length; i++) + { + key = configFastMap[i]; + + // Only update properties from their current state if they exist in the given config + if (HasValue(config, key)) + { + this[key] = GetFastValue(config, key); + } + } + + this.acceleration = (this.accelerationX !== 0 || this.accelerationY !== 0); + + this.moveTo = HasAll(config, [ 'moveToX', 'moveToY' ]); + + // Special 'speed' override + + if (HasValue(config, 'speed')) + { + ops.speedX.loadConfig(config, 'speed'); + ops.speedY.active = false; + } + + // If you specify speedX, speedY or moveTo then it changes the emitter from radial to a point emitter + if (HasAny(config, [ 'speedX', 'speedY' ]) || this.moveTo) + { + this.radial = false; + } + + // Special 'scale' override + + if (HasValue(config, 'scale')) + { + ops.scaleX.loadConfig(config, 'scale'); + ops.scaleY.active = false; + } + + if (HasValue(config, 'callbackScope')) + { + var callbackScope = GetFastValue(config, 'callbackScope', null); + + this.emitCallbackScope = callbackScope; + this.deathCallbackScope = callbackScope; + } + + if (HasValue(config, 'emitZone')) + { + this.addEmitZone(config.emitZone); + } + + if (HasValue(config, 'deathZone')) + { + this.addDeathZone(config.deathZone); + } + + if (HasValue(config, 'bounds')) + { + var bounds = this.addParticleBounds(config.bounds); + + bounds.collideLeft = GetFastValue(config, 'collideLeft', true); + bounds.collideRight = GetFastValue(config, 'collideRight', true); + bounds.collideTop = GetFastValue(config, 'collideTop', true); + bounds.collideBottom = GetFastValue(config, 'collideBottom', true); + } + + if (HasValue(config, 'followOffset')) + { + this.followOffset.setFromObject(GetFastValue(config, 'followOffset', 0)); + } + + if (HasValue(config, 'texture')) + { + this.setTexture(config.texture); + } + + if (HasValue(config, 'frame')) + { + this.setEmitterFrame(config.frame); + } + else if (HasValue(config, 'anim')) + { + this.setAnim(config.anim); + } + + if (HasValue(config, 'reserve')) + { + this.reserve(config.reserve); + } + + if (HasValue(config, 'advance')) + { + this.fastForward(config.advance); + } + + this.resetCounters(this.frequency, this.emitting); + + if (this.emitting) + { + this.emit(Events.START, this); + } + + return this; + }, + + /** + * Takes an existing Emitter Configuration file and updates this Emitter. + * Existing properties are overriden while new properties are added. The + * updated configuration is then passed to the `setConfig` method to reset + * the Emitter with the updated configuration. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#updateConfig + * @since 3.85.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} config - Settings for this emitter. + * + * @return {this} This Particle Emitter. + */ + updateConfig: function (config) + { + if (config) + { + if (!this.config) + { + this.setConfig(config); + } + else + { + this.setConfig(MergeRight(this.config, config)); + } + } + + return this; + }, + + /** + * Creates a description of this emitter suitable for JSON serialization. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object. + */ + toJSON: function () + { + var output = ComponentsToJSON(this); + + var i = 0; + var key = ''; + + for (i = 0; i < configFastMap.length; i++) + { + key = configFastMap[i]; + + output[key] = this[key]; + } + + var ops = this.ops; + + for (i = 0; i < configOpMap.length; i++) + { + key = configOpMap[i]; + + if (ops[key]) + { + output[key] = ops[key].toJSON(); + } + } + + // special handlers + if (!ops.speedY.active) + { + delete output.speedX; + output.speed = ops.speedX.toJSON(); + } + + if (this.scaleX === this.scaleY) + { + delete output.scaleX; + delete output.scaleY; + output.scale = ops.scaleX.toJSON(); + } + + return output; + }, + + /** + * Resets the internal counter trackers. + * + * You shouldn't ever need to call this directly. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#resetCounters + * @since 3.60.0 + * + * @param {number} frequency - The frequency counter. + * @param {boolean} on - Set the complete flag. + */ + resetCounters: function (frequency, on) + { + var counters = this.counters; + + counters.fill(0); + + counters[0] = frequency; + + if (on) + { + counters[5] = 1; + } + }, + + /** + * Continuously moves the particle origin to follow a Game Object's position. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#startFollow + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} target - The Object to follow. + * @param {number} [offsetX=0] - Horizontal offset of the particle origin from the Game Object. + * @param {number} [offsetY=0] - Vertical offset of the particle origin from the Game Object. + * @param {boolean} [trackVisible=false] - Whether the emitter's visible state will track the target's visible state. + * + * @return {this} This Particle Emitter. + */ + startFollow: function (target, offsetX, offsetY, trackVisible) + { + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + if (trackVisible === undefined) { trackVisible = false; } + + this.follow = target; + this.followOffset.set(offsetX, offsetY); + this.trackVisible = trackVisible; + + return this; + }, + + /** + * Stops following a Game Object. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#stopFollow + * @since 3.0.0 + * + * @return {this} This Particle Emitter. + */ + stopFollow: function () + { + this.follow = null; + this.followOffset.set(0, 0); + this.trackVisible = false; + + return this; + }, + + /** + * Chooses a texture frame from {@link Phaser.GameObjects.Particles.ParticleEmitter#frames}. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getFrame + * @since 3.0.0 + * + * @return {Phaser.Textures.Frame} The texture frame. + */ + getFrame: function () + { + var frames = this.frames; + var len = frames.length; + var current; + + if (len === 1) + { + current = frames[0]; + } + else if (this.randomFrame) + { + current = GetRandom(frames); + } + else + { + current = frames[this.currentFrame]; + + this.frameCounter++; + + if (this.frameCounter === this.frameQuantity) + { + this.frameCounter = 0; + + this.currentFrame++; + + if (this.currentFrame === len) + { + this.currentFrame = 0; + } + } + } + + return this.texture.get(current); + }, + + /** + * Sets a pattern for assigning texture frames to emitted particles. The `frames` configuration can be any of: + * + * frame: 0 + * frame: 'red' + * frame: [ 0, 1, 2, 3 ] + * frame: [ 'red', 'green', 'blue', 'pink', 'white' ] + * frame: { frames: [ 'red', 'green', 'blue', 'pink', 'white' ], [cycle: bool], [quantity: int] } + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setEmitterFrame + * @since 3.0.0 + * + * @param {(array|string|number|Phaser.Types.GameObjects.Particles.ParticleEmitterFrameConfig)} frames - One or more texture frames, or a configuration object. + * @param {boolean} [pickRandom=true] - Whether frames should be assigned at random from `frames`. + * @param {number} [quantity=1] - The number of consecutive particles that will receive each frame. + * + * @return {this} This Particle Emitter. + */ + setEmitterFrame: function (frames, pickRandom, quantity) + { + if (pickRandom === undefined) { pickRandom = true; } + if (quantity === undefined) { quantity = 1; } + + this.randomFrame = pickRandom; + this.frameQuantity = quantity; + + this.currentFrame = 0; + + var t = typeof (frames); + + this.frames.length = 0; + + if (Array.isArray(frames)) + { + this.frames = this.frames.concat(frames); + } + else if (t === 'string' || t === 'number') + { + this.frames.push(frames); + } + else if (t === 'object') + { + var frameConfig = frames; + + frames = GetFastValue(frameConfig, 'frames', null); + + if (frames) + { + this.frames = this.frames.concat(frames); + } + + var isCycle = GetFastValue(frameConfig, 'cycle', false); + + this.randomFrame = (isCycle) ? false : true; + + this.frameQuantity = GetFastValue(frameConfig, 'quantity', quantity); + } + + if (this.frames.length === 1) + { + this.frameQuantity = 1; + this.randomFrame = false; + } + + return this; + }, + + /** + * Chooses an animation from {@link Phaser.GameObjects.Particles.ParticleEmitter#anims}, if populated. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getAnim + * @since 3.60.0 + * + * @return {string} The animation to play, or `null` if there aren't any. + */ + getAnim: function () + { + var anims = this.anims; + var len = anims.length; + + if (len === 0) + { + return null; + } + else if (len === 1) + { + return anims[0]; + } + else if (this.randomAnim) + { + return GetRandom(anims); + } + else + { + var anim = anims[this.currentAnim]; + + this.animCounter++; + + if (this.animCounter >= this.animQuantity) + { + this.animCounter = 0; + this.currentAnim = Wrap(this.currentAnim + 1, 0, len); + } + + return anim; + } + }, + + /** + * Sets a pattern for assigning animations to emitted particles. The `anims` configuration can be any of: + * + * anim: 'red' + * anim: [ 'red', 'green', 'blue', 'pink', 'white' ] + * anim: { anims: [ 'red', 'green', 'blue', 'pink', 'white' ], [cycle: bool], [quantity: int] } + * + * Call this method at least once before any particles are created, or set `anim` in the Particle Emitter's configuration when creating the Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setAnim + * @since 3.60.0 + * + * @param {(string|string[]|Phaser.Types.GameObjects.Particles.ParticleEmitterAnimConfig)} anims - One or more animations, or a configuration object. + * @param {boolean} [pickRandom=true] - Whether animations should be assigned at random from `anims`. If a config object is given, this parameter is ignored. + * @param {number} [quantity=1] - The number of consecutive particles that will receive each animation. If a config object is given, this parameter is ignored. + * + * @return {this} This Particle Emitter. + */ + setAnim: function (anims, pickRandom, quantity) + { + if (pickRandom === undefined) { pickRandom = true; } + if (quantity === undefined) { quantity = 1; } + + this.randomAnim = pickRandom; + this.animQuantity = quantity; + + this.currentAnim = 0; + + var t = typeof (anims); + + this.anims.length = 0; + + if (Array.isArray(anims)) + { + this.anims = this.anims.concat(anims); + } + else if (t === 'string') + { + this.anims.push(anims); + } + else if (t === 'object') + { + var animConfig = anims; + + anims = GetFastValue(animConfig, 'anims', null); + + if (anims) + { + this.anims = this.anims.concat(anims); + } + + var isCycle = GetFastValue(animConfig, 'cycle', false); + + this.randomAnim = (isCycle) ? false : true; + + this.animQuantity = GetFastValue(animConfig, 'quantity', quantity); + } + + if (this.anims.length === 1) + { + this.animQuantity = 1; + this.randomAnim = false; + } + + return this; + }, + + /** + * Turns {@link Phaser.GameObjects.Particles.ParticleEmitter#radial} particle movement on or off. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setRadial + * @since 3.0.0 + * + * @param {boolean} [value=true] - Radial mode (true) or point mode (true). + * + * @return {this} This Particle Emitter. + */ + setRadial: function (value) + { + if (value === undefined) { value = true; } + + this.radial = value; + + return this; + }, + + /** + * Creates a Particle Bounds processor and adds it to this Emitter. + * + * This processor will check to see if any of the active Particles hit + * the defined boundary, as specified by a Rectangle shape in world-space. + * + * If so, they are 'rebounded' back again by having their velocity adjusted. + * + * The strength of the rebound is controlled by the `Particle.bounce` + * property. + * + * You should be careful to ensure that you emit particles within a bounds, + * if set, otherwise it will lead to unpredictable visual results as the + * particles are hastily repositioned. + * + * The Particle Bounds processor is returned from this method. If you wish + * to modify the area you can directly change its `bounds` property, along + * with the `collideLeft` etc values. + * + * To disable the bounds you can either set its `active` property to `false`, + * or if you no longer require it, call `ParticleEmitter.removeParticleProcessor`. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#addParticleBounds + * @since 3.60.0 + * + * @param {(number|Phaser.Types.GameObjects.Particles.ParticleEmitterBounds|Phaser.Types.GameObjects.Particles.ParticleEmitterBoundsAlt)} x - The x-coordinate of the left edge of the boundary, or an object representing a rectangle. + * @param {number} [y] - The y-coordinate of the top edge of the boundary. + * @param {number} [width] - The width of the boundary. + * @param {number} [height] - The height of the boundary. + * @param {boolean} [collideLeft=true] - Whether particles interact with the left edge of the bounds. + * @param {boolean} [collideRight=true] - Whether particles interact with the right edge of the bounds. + * @param {boolean} [collideTop=true] - Whether particles interact with the top edge of the bounds. + * @param {boolean} [collideBottom=true] - Whether particles interact with the bottom edge of the bounds. + * + * @return {Phaser.GameObjects.Particles.ParticleBounds} The Particle Bounds processor. + */ + addParticleBounds: function (x, y, width, height, collideLeft, collideRight, collideTop, collideBottom) + { + if (typeof x === 'object') + { + var obj = x; + + x = obj.x; + y = obj.y; + width = (HasValue(obj, 'w')) ? obj.w : obj.width; + height = (HasValue(obj, 'h')) ? obj.h : obj.height; + } + + return this.addParticleProcessor(new ParticleBounds(x, y, width, height, collideLeft, collideRight, collideTop, collideBottom)); + }, + + /** + * Sets the initial radial speed of emitted particles. + * + * Changes the emitter to radial mode. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleSpeed + * @since 3.60.0 + * + * @param {number} x - The horizontal speed of the emitted Particles. + * @param {number} [y=x] - The vertical speed of emitted Particles. If not set it will use the `x` value. + * + * @return {this} This Particle Emitter. + */ + setParticleSpeed: function (x, y) + { + if (y === undefined) { y = x; } + + this.ops.speedX.onChange(x); + + if (x === y) + { + this.ops.speedY.active = false; + } + else + { + this.ops.speedY.onChange(y); + } + + // If you specify speedX and Y then it changes the emitter from radial to a point emitter + this.radial = true; + + return this; + }, + + /** + * Sets the vertical and horizontal scale of the emitted particles. + * + * You can also set the scale of the entire emitter via `setScale`. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleScale + * @since 3.60.0 + * + * @param {number} [x=1] - The horizontal scale of the emitted Particles. + * @param {number} [y=x] - The vertical scale of emitted Particles. If not set it will use the `x` value. + * + * @return {this} This Particle Emitter. + */ + setParticleScale: function (x, y) + { + if (x === undefined) { x = 1; } + if (y === undefined) { y = x; } + + this.ops.scaleX.onChange(x); + this.ops.scaleY.onChange(y); + + return this; + }, + + /** + * Sets the gravity applied to emitted particles. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleGravity + * @since 3.60.0 + * + * @param {number} x - Horizontal acceleration due to gravity, in pixels per second squared. Set to zero for no gravity. + * @param {number} y - Vertical acceleration due to gravity, in pixels per second squared. Set to zero for no gravity. + * + * @return {this} This Particle Emitter. + */ + setParticleGravity: function (x, y) + { + this.gravityX = x; + this.gravityY = y; + + return this; + }, + + /** + * Sets the opacity (alpha) of emitted particles. + * + * You can also set the alpha of the entire emitter via `setAlpha`. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleAlpha + * @since 3.60.0 + * + * @param {(Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType)} value - A value between 0 (transparent) and 1 (opaque). + * + * @return {this} This Particle Emitter. + */ + setParticleAlpha: function (value) + { + this.ops.alpha.onChange(value); + + return this; + }, + + /** + * Sets the color tint of emitted particles. + * + * This is a WebGL only feature. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleTint + * @since 3.60.0 + * @webglOnly + * + * @param {(Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType)} value - A value between 0 and 0xffffff. + * + * @return {this} This Particle Emitter. + */ + setParticleTint: function (value) + { + this.ops.tint.onChange(value); + + return this; + }, + + /** + * Sets the angle of a {@link Phaser.GameObjects.Particles.ParticleEmitter#radial} particle stream. + * + * The value is given in degrees using Phaser's right-handed coordinate system. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setEmitterAngle + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} value - The angle of the initial velocity of emitted particles, in degrees. + * + * @return {this} This Particle Emitter. + */ + setEmitterAngle: function (value) + { + this.ops.angle.onChange(value); + + return this; + }, + + /** + * Sets the lifespan of newly emitted particles in milliseconds. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setParticleLifespan + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} value - The lifespan of a particle, in ms. + * + * @return {this} This Particle Emitter. + */ + setParticleLifespan: function (value) + { + this.ops.lifespan.onChange(value); + + return this; + }, + + /** + * Sets the number of particles released at each flow cycle or explosion. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setQuantity + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} quantity - The number of particles to release at each flow cycle or explosion. + * + * @return {this} This Particle Emitter. + */ + setQuantity: function (quantity) + { + this.quantity = quantity; + + return this; + }, + + /** + * Sets the emitter's {@link Phaser.GameObjects.Particles.ParticleEmitter#frequency} + * and {@link Phaser.GameObjects.Particles.ParticleEmitter#quantity}. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setFrequency + * @since 3.0.0 + * + * @param {number} frequency - The time interval (>= 0) of each flow cycle, in ms; or -1 to put the emitter in explosion mode. + * @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} [quantity] - The number of particles to release at each flow cycle or explosion. + * + * @return {this} This Particle Emitter. + */ + setFrequency: function (frequency, quantity) + { + this.frequency = frequency; + + this.flowCounter = (frequency > 0) ? frequency : 0; + + if (quantity) + { + this.quantity = quantity; + } + + return this; + }, + + /** + * Adds a new Particle Death Zone to this Emitter. + * + * A particle is immediately killed as soon as its x/y coordinates intersect + * with any of the configured Death Zones. + * + * The `source` can be a Geometry Shape, such as a Circle, Rectangle or Triangle. + * Any valid object from the `Phaser.Geometry` namespace is allowed, as long as + * it supports a `contains` function. You can set the `type` to be either `onEnter` + * or `onLeave`. + * + * A single Death Zone instance can only exist once within this Emitter, but can belong + * to multiple Emitters. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#addDeathZone + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.Particles.DeathZoneObject|Phaser.Types.GameObjects.Particles.DeathZoneObject[]} config - A Death Zone configuration object, a Death Zone instance, a valid Geometry object or an array of them. + * + * @return {Phaser.GameObjects.Particles.Zones.DeathZone[]} An array of the Death Zones that were added to this Emitter. + */ + addDeathZone: function (config) + { + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var zone; + var output = []; + + for (var i = 0; i < config.length; i++) + { + zone = config[i]; + + if (zone instanceof DeathZone) + { + output.push(zone); + } + else if (typeof zone.contains === 'function') + { + zone = new DeathZone(zone, true); + + output.push(zone); + } + else + { + var type = GetFastValue(zone, 'type', 'onEnter'); + var source = GetFastValue(zone, 'source', null); + + if (source && typeof source.contains === 'function') + { + var killOnEnter = (type === 'onEnter') ? true : false; + + zone = new DeathZone(source, killOnEnter); + + output.push(zone); + } + } + } + + this.deathZones = this.deathZones.concat(output); + + return output; + }, + + /** + * Removes the given Particle Death Zone from this Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#removeDeathZone + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Zones.DeathZone} zone - The Death Zone that should be removed from this Emitter. + * + * @return {this} This Particle Emitter. + */ + removeDeathZone: function (zone) + { + Remove(this.deathZones, zone); + + return this; + }, + + /** + * Clear all Death Zones from this Particle Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#clearDeathZones + * @since 3.70.0 + * + * @return {this} This Particle Emitter. + */ + clearDeathZones: function () + { + this.deathZones.length = 0; + + return this; + }, + + /** + * Adds a new Particle Emission Zone to this Emitter. + * + * An {@link Phaser.Types.GameObjects.Particles.ParticleEmitterEdgeZoneConfig EdgeZone} places particles on its edges. + * Its {@link Phaser.Types.GameObjects.Particles.EdgeZoneSource source} can be a Curve, Path, Circle, Ellipse, Line, Polygon, Rectangle, or Triangle; + * or any object with a suitable {@link Phaser.Types.GameObjects.Particles.EdgeZoneSourceCallback getPoints} method. + * + * A {@link Phaser.Types.GameObjects.Particles.ParticleEmitterRandomZoneConfig RandomZone} places the particles randomly within its interior. + * Its {@link Phaser.GameObjects.Particles.Zones.RandomZone#source source} can be a Circle, Ellipse, Line, Polygon, Rectangle, or Triangle; or any object with a suitable {@link Phaser.Types.GameObjects.Particles.RandomZoneSourceCallback getRandomPoint} method. + * + * An Emission Zone can only exist once within this Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#addEmitZone + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.Particles.EmitZoneData|Phaser.Types.GameObjects.Particles.EmitZoneData[]} zone - An Emission Zone configuration object, a RandomZone or EdgeZone instance, or an array of them. + * + * @return {Phaser.Types.GameObjects.Particles.EmitZoneObject[]} An array of the Emission Zones that were added to this Emitter. + */ + addEmitZone: function (config) + { + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var zone; + var output = []; + + for (var i = 0; i < config.length; i++) + { + zone = config[i]; + + if (zone instanceof RandomZone || zone instanceof EdgeZone) + { + output.push(zone); + } + else + { + // Where source = Geom like Circle, or a Path or Curve + // emitZone: { type: 'random', source: X } + // emitZone: { type: 'edge', source: X, quantity: 32, [stepRate=0], [yoyo=false], [seamless=true], [total=1] } + + var source = GetFastValue(zone, 'source', null); + + if (source) + { + var type = GetFastValue(zone, 'type', 'random'); + + if (type === 'random' && typeof source.getRandomPoint === 'function') + { + zone = new RandomZone(source); + + output.push(zone); + } + else if (type === 'edge' && typeof source.getPoints === 'function') + { + var quantity = GetFastValue(zone, 'quantity', 1); + var stepRate = GetFastValue(zone, 'stepRate', 0); + var yoyo = GetFastValue(zone, 'yoyo', false); + var seamless = GetFastValue(zone, 'seamless', true); + var total = GetFastValue(zone, 'total', -1); + + zone = new EdgeZone(source, quantity, stepRate, yoyo, seamless, total); + + output.push(zone); + } + } + } + } + + this.emitZones = this.emitZones.concat(output); + + return output; + }, + + /** + * Removes the given Particle Emission Zone from this Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#removeEmitZone + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Zones.EdgeZone|Phaser.GameObjects.Particles.Zones.RandomZone} zone - The Emission Zone that should be removed from this Emitter. + * + * @return {this} This Particle Emitter. + */ + removeEmitZone: function (zone) + { + Remove(this.emitZones, zone); + + this.zoneIndex = 0; + + return this; + }, + + /** + * Clear all Emission Zones from this Particle Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#clearEmitZones + * @since 3.70.0 + * + * @return {this} This Particle Emitter. + */ + clearEmitZones: function () + { + this.emitZones.length = 0; + + this.zoneIndex = 0; + + return this; + }, + + /** + * Takes the given particle and sets its x/y coordinates to match the next available + * emission zone, if any have been configured. This method is called automatically + * as part of the `Particle.fire` process. + * + * The Emit Zones are iterated in sequence. Once a zone has had a particle emitted + * from it, then the next zone is used and so on, in a loop. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getEmitZone + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle to set the emission zone for. + */ + getEmitZone: function (particle) + { + var zones = this.emitZones; + var len = zones.length; + + if (len === 0) + { + return; + } + else + { + var zone = zones[this.zoneIndex]; + + zone.getPoint(particle); + + if (zone.total > -1) + { + this.zoneTotal++; + + if (this.zoneTotal === zone.total) + { + this.zoneTotal = 0; + + this.zoneIndex++; + + if (this.zoneIndex === len) + { + this.zoneIndex = 0; + } + } + } + } + }, + + /** + * Takes the given particle and checks to see if any of the configured Death Zones + * will kill it and returns the result. This method is called automatically as part + * of the `Particle.update` process. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getDeathZone + * @fires Phaser.GameObjects.Particles.Events#DEATH_ZONE + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle to test against the Death Zones. + * + * @return {boolean} `true` if the particle should be killed, otherwise `false`. + */ + getDeathZone: function (particle) + { + var zones = this.deathZones; + + for (var i = 0; i < zones.length; i++) + { + var zone = zones[i]; + + if (zone.willKill(particle)) + { + this.emit(Events.DEATH_ZONE, this, particle, zone); + + return true; + } + } + + return false; + }, + + /** + * Changes the currently active Emission Zone. The zones should have already + * been added to this Emitter either via the emitter config, or the + * `addEmitZone` method. + * + * Call this method by passing either a numeric zone index value, or + * the zone instance itself. + * + * Prior to v3.60 an Emitter could only have a single Emit Zone and this + * method was how you set it. From 3.60 and up it now performs a different + * function and swaps between all available active zones. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setEmitZone + * @since 3.0.0 + * + * @param {number|Phaser.GameObjects.Particles.Zones.EdgeZone|Phaser.GameObjects.Particles.Zones.RandomZone} zone - The Emit Zone to set as the active zone. + * + * @return {this} This Particle Emitter. + */ + setEmitZone: function (zone) + { + var index; + + if (isFinite(zone)) + { + index = zone; + } + else + { + index = this.emitZones.indexOf(zone); + } + + if (index >= 0) + { + this.zoneIndex = index; + } + + return this; + }, + + /** + * Adds a Particle Processor, such as a Gravity Well, to this Emitter. + * + * It will start processing particles from the next update as long as its `active` + * property is set. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#addParticleProcessor + * @since 3.60.0 + * + * @generic {Phaser.GameObjects.Particles.ParticleProcessor} T + * @param {T} processor - The Particle Processor to add to this Emitter Manager. + * + * @return {T} The Particle Processor that was added to this Emitter Manager. + */ + addParticleProcessor: function (processor) + { + if (!this.processors.exists(processor)) + { + if (processor.emitter) + { + processor.emitter.removeParticleProcessor(processor); + } + + this.processors.add(processor); + + processor.emitter = this; + } + + return processor; + }, + + /** + * Removes a Particle Processor from this Emitter. + * + * The Processor must belong to this Emitter to be removed. + * + * It is not destroyed when removed, allowing you to move it to another Emitter Manager, + * so if you no longer require it you should call its `destroy` method directly. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#removeParticleProcessor + * @since 3.60.0 + * + * @generic {Phaser.GameObjects.Particles.ParticleProcessor} T + * @param {T} processor - The Particle Processor to remove from this Emitter Manager. + * + * @return {?T} The Particle Processor that was removed, or null if it could not be found. + */ + removeParticleProcessor: function (processor) + { + if (this.processors.exists(processor)) + { + this.processors.remove(processor, true); + + processor.emitter = null; + } + + return processor; + }, + + /** + * Gets all active Particle Processors. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getProcessors + * @since 3.60.0 + * + * @return {Phaser.GameObjects.Particles.ParticleProcessor[]} - An array of active Particle Processors. + */ + getProcessors: function () + { + return this.processors.getAll('active', true); + }, + + /** + * Creates a new Gravity Well, adds it to this Emitter and returns a reference to it. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#createGravityWell + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.Particles.GravityWellConfig} config - Configuration settings for the Gravity Well to create. + * + * @return {Phaser.GameObjects.Particles.GravityWell} The Gravity Well that was created. + */ + createGravityWell: function (config) + { + return this.addParticleProcessor(new GravityWell(config)); + }, + + /** + * Creates inactive particles and adds them to this emitter's pool. + * + * If `ParticleEmitter.maxParticles` is set it will limit the + * value passed to this method to make sure it's not exceeded. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#reserve + * @since 3.0.0 + * + * @param {number} count - The number of particles to create. + * + * @return {this} This Particle Emitter. + */ + reserve: function (count) + { + var dead = this.dead; + + if (this.maxParticles > 0) + { + var total = this.getParticleCount(); + + if (total + count > this.maxParticles) + { + count = this.maxParticles - (total + count); + } + } + + for (var i = 0; i < count; i++) + { + dead.push(new this.particleClass(this)); + } + + return this; + }, + + /** + * Gets the number of active (in-use) particles in this emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getAliveParticleCount + * @since 3.0.0 + * + * @return {number} The number of particles with `active=true`. + */ + getAliveParticleCount: function () + { + return this.alive.length; + }, + + /** + * Gets the number of inactive (available) particles in this emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getDeadParticleCount + * @since 3.0.0 + * + * @return {number} The number of particles with `active=false`. + */ + getDeadParticleCount: function () + { + return this.dead.length; + }, + + /** + * Gets the total number of particles in this emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getParticleCount + * @since 3.0.0 + * + * @return {number} The number of particles, including both alive and dead. + */ + getParticleCount: function () + { + return this.getAliveParticleCount() + this.getDeadParticleCount(); + }, + + /** + * Whether this emitter is at either its hard-cap limit (maxParticles), if set, or + * the max allowed number of 'alive' particles (maxAliveParticles). + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#atLimit + * @since 3.0.0 + * + * @return {boolean} Returns `true` if this Emitter is at its limit, or `false` if no limit, or below the `maxParticles` level. + */ + atLimit: function () + { + if (this.maxParticles > 0 && this.getParticleCount() >= this.maxParticles) + { + return true; + } + + return (this.maxAliveParticles > 0 && this.getAliveParticleCount() >= this.maxAliveParticles); + }, + + /** + * Sets a function to call for each newly emitted particle. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#onParticleEmit + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} callback - The function. + * @param {*} [context] - The calling context. + * + * @return {this} This Particle Emitter. + */ + onParticleEmit: function (callback, context) + { + if (callback === undefined) + { + // Clear any previously set callback + this.emitCallback = null; + this.emitCallbackScope = null; + } + else if (typeof callback === 'function') + { + this.emitCallback = callback; + + if (context) + { + this.emitCallbackScope = context; + } + } + + return this; + }, + + /** + * Sets a function to call for each particle death. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#onParticleDeath + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleDeathCallback} callback - The function. + * @param {*} [context] - The function's calling context. + * + * @return {this} This Particle Emitter. + */ + onParticleDeath: function (callback, context) + { + if (callback === undefined) + { + // Clear any previously set callback + this.deathCallback = null; + this.deathCallbackScope = null; + } + else if (typeof callback === 'function') + { + this.deathCallback = callback; + + if (context) + { + this.deathCallbackScope = context; + } + } + + return this; + }, + + /** + * Deactivates every particle in this emitter immediately. + * + * This particles are killed but do not emit an event or callback. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#killAll + * @since 3.0.0 + * + * @return {this} This Particle Emitter. + */ + killAll: function () + { + var dead = this.dead; + var alive = this.alive; + + while (alive.length > 0) + { + dead.push(alive.pop()); + } + + return this; + }, + + /** + * Calls a function for each active particle in this emitter. The function is + * sent two parameters: a reference to the Particle instance and to this Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#forEachAlive + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} callback - The function. + * @param {*} context - The functions calling context. + * + * @return {this} This Particle Emitter. + */ + forEachAlive: function (callback, context) + { + var alive = this.alive; + var length = alive.length; + + for (var i = 0; i < length; i++) + { + // Sends the Particle and the Emitter + callback.call(context, alive[i], this); + } + + return this; + }, + + /** + * Calls a function for each inactive particle in this emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#forEachDead + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCallback} callback - The function. + * @param {*} context - The functions calling context. + * + * @return {this} This Particle Emitter. + */ + forEachDead: function (callback, context) + { + var dead = this.dead; + var length = dead.length; + + for (var i = 0; i < length; i++) + { + callback.call(context, dead[i], this); + } + + return this; + }, + + /** + * Turns {@link Phaser.GameObjects.Particles.ParticleEmitter#on} the emitter and resets the flow counter. + * + * If this emitter is in flow mode (frequency >= 0; the default), the particle flow will start (or restart). + * + * If this emitter is in explode mode (frequency = -1), nothing will happen. + * Use {@link Phaser.GameObjects.Particles.ParticleEmitter#explode} or {@link Phaser.GameObjects.Particles.ParticleEmitter#flow} instead. + * + * Calling this method will emit the `START` event. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#start + * @fires Phaser.GameObjects.Particles.Events#START + * @since 3.0.0 + * + * @param {number} [advance=0] - Advance this number of ms in time through the emitter. + * @param {number} [duration=0] - Limit this emitter to only emit particles for the given number of ms. Setting this parameter will override any duration already set in the Emitter configuration object. + * + * @return {this} This Particle Emitter. + */ + start: function (advance, duration) + { + if (advance === undefined) { advance = 0; } + + if (!this.emitting) + { + if (advance > 0) + { + this.fastForward(advance); + } + + this.emitting = true; + + this.resetCounters(this.frequency, true); + + if (duration !== undefined) + { + this.duration = Math.abs(duration); + } + + this.emit(Events.START, this); + } + + return this; + }, + + /** + * Turns {@link Phaser.GameObjects.Particles.ParticleEmitter#emitting off} the emitter and + * stops it from emitting further particles. Currently alive particles will remain + * active until they naturally expire unless you set the `kill` parameter to `true`. + * + * Calling this method will emit the `STOP` event. When the final particle has + * expired the `COMPLETE` event will be emitted. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#stop + * @fires Phaser.GameObjects.Particles.Events#STOP + * @since 3.11.0 + * + * @param {boolean} [kill=false] - Kill all particles immediately (true), or leave them to die after their lifespan expires? (false, the default) + * + * @return {this} This Particle Emitter. + */ + stop: function (kill) + { + if (kill === undefined) { kill = false; } + + if (this.emitting) + { + this.emitting = false; + + if (kill) + { + this.killAll(); + } + + this.emit(Events.STOP, this); + } + + return this; + }, + + /** + * {@link Phaser.GameObjects.Particles.ParticleEmitter#active Deactivates} the emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#pause + * @since 3.0.0 + * + * @return {this} This Particle Emitter. + */ + pause: function () + { + this.active = false; + + return this; + }, + + /** + * {@link Phaser.GameObjects.Particles.ParticleEmitter#active Activates} the emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#resume + * @since 3.0.0 + * + * @return {this} This Particle Emitter. + */ + resume: function () + { + this.active = true; + + return this; + }, + + /** + * Set the property by which active particles are sorted prior to be rendered. + * + * It allows you to control the rendering order of the particles. + * + * This can be any valid property of the `Particle` class, such as `y`, `alpha` + * or `lifeT`. + * + * The 'alive' particles array is sorted in place each game frame. Setting a + * sort property will override the `particleBringToTop` setting. + * + * If you wish to use your own sorting function, see `setSortCallback` instead. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setSortProperty + * @since 3.60.0 + * + * @param {string} [property] - The property on the `Particle` class to sort by. + * @param {boolean} [ascending=true] - Should the particles be sorted in ascending or descending order? + * + * @return {this} This Particle Emitter. + */ + setSortProperty: function (property, ascending) + { + if (property === undefined) { property = ''; } + if (ascending === undefined) { ascending = this.true; } + + this.sortProperty = property; + this.sortOrderAsc = ascending; + this.sortCallback = this.depthSortCallback; + + return this; + }, + + /** + * Sets a callback to be used to sort the particles before rendering each frame. + * + * This allows you to define your own logic and behavior in the callback. + * + * The callback will be sent two parameters: the two Particles being compared, + * and must adhere to the criteria of the `compareFn` in `Array.sort`: + * + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description + * + * Call this method with no parameters to reset the sort callback. + * + * Setting your own callback will override both the `particleBringToTop` and + * `sortProperty` settings of this Emitter. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#setSortCallback + * @since 3.60.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleSortCallback} [callback] - The callback to invoke when the particles are sorted. Leave undefined to reset to the default. + * + * @return {this} This Particle Emitter. + */ + setSortCallback: function (callback) + { + if (this.sortProperty !== '') + { + callback = this.depthSortCallback; + } + else + { + callback = null; + } + + this.sortCallback = callback; + + return this; + }, + + /** + * Sorts active particles with {@link Phaser.GameObjects.Particles.ParticleEmitter#depthSortCallback}. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#depthSort + * @since 3.0.0 + * + * @return {this} This Particle Emitter. + */ + depthSort: function () + { + StableSort(this.alive, this.sortCallback.bind(this)); + + return this; + }, + + /** + * Calculates the difference of two particles, for sorting them by depth. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#depthSortCallback + * @since 3.0.0 + * + * @param {object} a - The first particle. + * @param {object} b - The second particle. + * + * @return {number} The difference of a and b's y coordinates. + */ + depthSortCallback: function (a, b) + { + var key = this.sortProperty; + + if (this.sortOrderAsc) + { + return a[key] - b[key]; + } + else + { + return b[key] - a[key]; + } + }, + + /** + * Puts the emitter in flow mode (frequency >= 0) and starts (or restarts) a particle flow. + * + * To resume a flow at the current frequency and quantity, use {@link Phaser.GameObjects.Particles.ParticleEmitter#start} instead. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#flow + * @fires Phaser.GameObjects.Particles.Events#START + * @since 3.0.0 + * + * @param {number} frequency - The time interval (>= 0) of each flow cycle, in ms. + * @param {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} [count=1] - The number of particles to emit at each flow cycle. + * @param {number} [stopAfter] - Stop this emitter from firing any more particles once this value is reached. Set to zero for unlimited. Setting this parameter will override any `stopAfter` value already set in the Emitter configuration object. + * + * @return {this} This Particle Emitter. + */ + flow: function (frequency, count, stopAfter) + { + if (count === undefined) { count = 1; } + + this.emitting = false; + + this.frequency = frequency; + this.quantity = count; + + if (stopAfter !== undefined) + { + this.stopAfter = stopAfter; + } + + return this.start(); + }, + + /** + * Puts the emitter in explode mode (frequency = -1), stopping any current particle flow, and emits several particles all at once. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#explode + * @fires Phaser.GameObjects.Particles.Events#EXPLODE + * @since 3.0.0 + * + * @param {number} [count=this.quantity] - The number of Particles to emit. + * @param {number} [x=this.x] - The x coordinate to emit the Particles from. + * @param {number} [y=this.x] - The y coordinate to emit the Particles from. + * + * @return {(Phaser.GameObjects.Particles.Particle|undefined)} The most recently emitted Particle, or `undefined` if the emitter is at its limit. + */ + explode: function (count, x, y) + { + this.frequency = -1; + + this.resetCounters(-1, true); + + var particle = this.emitParticle(count, x, y); + + this.emit(Events.EXPLODE, this, particle); + + return particle; + }, + + /** + * Emits particles at the given position. If no position is given, it will + * emit from this Emitters current location. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#emitParticleAt + * @since 3.0.0 + * + * @param {number} [x=this.x] - The x coordinate to emit the Particles from. + * @param {number} [y=this.x] - The y coordinate to emit the Particles from. + * @param {number} [count=this.quantity] - The number of Particles to emit. + * + * @return {(Phaser.GameObjects.Particles.Particle|undefined)} The most recently emitted Particle, or `undefined` if the emitter is at its limit. + */ + emitParticleAt: function (x, y, count) + { + return this.emitParticle(count, x, y); + }, + + /** + * Emits particles at a given position (or the emitters current position). + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#emitParticle + * @since 3.0.0 + * + * @param {number} [count=this.quantity] - The number of Particles to emit. + * @param {number} [x=this.x] - The x coordinate to emit the Particles from. + * @param {number} [y=this.x] - The y coordinate to emit the Particles from. + * + * @return {(Phaser.GameObjects.Particles.Particle|undefined)} The most recently emitted Particle, or `undefined` if the emitter is at its limit. + * + * @see Phaser.GameObjects.Particles.Particle#fire + */ + emitParticle: function (count, x, y) + { + if (this.atLimit()) + { + return; + } + + if (count === undefined) + { + count = this.ops.quantity.onEmit(); + } + + var dead = this.dead; + var stopAfter = this.stopAfter; + + var followX = (this.follow) ? this.follow.x + this.followOffset.x : x; + var followY = (this.follow) ? this.follow.y + this.followOffset.y : y; + + for (var i = 0; i < count; i++) + { + var particle = dead.pop(); + + if (!particle) + { + particle = new this.particleClass(this); + } + + if (particle.fire(followX, followY)) + { + if (this.particleBringToTop) + { + this.alive.push(particle); + } + else + { + this.alive.unshift(particle); + } + + if (this.emitCallback) + { + this.emitCallback.call(this.emitCallbackScope, particle, this); + } + } + else + { + this.dead.push(particle); + } + + if (stopAfter > 0) + { + this.stopCounter++; + + if (this.stopCounter >= stopAfter) + { + break; + } + } + + if (this.atLimit()) + { + break; + } + } + + return particle; + }, + + /** + * Fast forwards this Particle Emitter and all of its particles. + * + * Works by running the Emitter `preUpdate` handler in a loop until the `time` + * has been reached at `delta` steps per loop. + * + * All callbacks and emitter related events that would normally be fired + * will still be invoked. + * + * You can make an emitter 'fast forward' via the emitter config using the + * `advance` property. Set this value to the number of ms you wish the + * emitter to be fast-forwarded by. Or, call this method post-creation. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#fastForward + * @since 3.60.0 + * + * @param {number} time - The number of ms to advance the Particle Emitter by. + * @param {number} [delta] - The amount of delta to use for each step. Defaults to 1000 / 60. + * + * @return {this} This Particle Emitter. + */ + fastForward: function (time, delta) + { + if (delta === undefined) { delta = 1000 / 60; } + + var total = 0; + + this.skipping = true; + + while (total < Math.abs(time)) + { + this.preUpdate(0, delta); + + total += delta; + } + + this.skipping = false; + + return this; + }, + + /** + * Updates this emitter and its particles. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#preUpdate + * @fires Phaser.GameObjects.Particles.Events#COMPLETE + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + preUpdate: function (time, delta) + { + // Scale the delta + delta *= this.timeScale; + + var step = (delta / 1000); + + if (this.trackVisible) + { + this.visible = this.follow.visible; + } + + this.getWorldTransformMatrix(this.worldMatrix); + + // Any particle processors? + var processors = this.getProcessors(); + + var particles = this.alive; + var dead = this.dead; + + var i = 0; + var rip = []; + var length = particles.length; + + for (i = 0; i < length; i++) + { + var particle = particles[i]; + + // update returns `true` if the particle is now dead (lifeCurrent <= 0) + if (particle.update(delta, step, processors)) + { + rip.push({ index: i, particle: particle }); + } + } + + // Move dead particles to the dead array + length = rip.length; + + if (length > 0) + { + var deathCallback = this.deathCallback; + var deathCallbackScope = this.deathCallbackScope; + + for (i = length - 1; i >= 0; i--) + { + var entry = rip[i]; + + // Remove from particles array + particles.splice(entry.index, 1); + + // Add to dead array + dead.push(entry.particle); + + // Callback + if (deathCallback) + { + deathCallback.call(deathCallbackScope, entry.particle); + } + + entry.particle.setPosition(); + } + } + + if (!this.emitting && !this.skipping) + { + if (this.completeFlag === 1 && particles.length === 0) + { + this.completeFlag = 0; + + this.emit(Events.COMPLETE, this); + } + + return; + } + + if (this.frequency === 0) + { + this.emitParticle(); + } + else if (this.frequency > 0) + { + this.flowCounter -= delta; + + while (this.flowCounter <= 0) + { + // Emits the 'quantity' number of particles + this.emitParticle(); + + // counter = frequency - remainder from previous delta + this.flowCounter += this.frequency; + } + } + + // Duration or stopAfter set? + if (!this.skipping) + { + if (this.duration > 0) + { + // elapsed + this.elapsed += delta; + + if (this.elapsed >= this.duration) + { + this.stop(); + } + } + + if (this.stopAfter > 0 && this.stopCounter >= this.stopAfter) + { + this.stop(); + } + } + }, + + /** + * Takes either a Rectangle Geometry object or an Arcade Physics Body and tests + * to see if it intersects with any currently alive Particle in this Emitter. + * + * Overlapping particles are returned in an array, where you can perform further + * processing on them. If nothing overlaps then the array will be empty. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#overlap + * @since 3.60.0 + * + * @param {(Phaser.Geom.Rectangle|Phaser.Physics.Arcade.Body)} target - A Rectangle or Arcade Physics Body to check for intersection against all alive particles. + * + * @return {Phaser.GameObjects.Particles.Particle[]} An array of Particles that overlap with the given target. + */ + overlap: function (target) + { + var matrix = this.getWorldTransformMatrix(); + + var alive = this.alive; + var length = alive.length; + + var output = []; + + for (var i = 0; i < length; i++) + { + var particle = alive[i]; + + if (RectangleToRectangle(target, particle.getBounds(matrix))) + { + output.push(particle); + } + } + + return output; + }, + + /** + * Returns a bounds Rectangle calculated from the bounds of all currently + * _active_ Particles in this Emitter. If this Emitter has only just been + * created and not yet rendered, then calling this method will return a Rectangle + * with a max safe integer for dimensions. Use the `advance` parameter to + * avoid this. + * + * Typically it takes a few seconds for a flow Emitter to 'warm up'. You can + * use the `advance` and `delta` parameters to force the Emitter to + * 'fast forward' in time to try and allow the bounds to be more accurate, + * as it will calculate the bounds based on the particle bounds across all + * timesteps, giving a better result. + * + * You can also use the `padding` parameter to increase the size of the + * bounds. Emitters with a lot of randomness in terms of direction or lifespan + * can often return a bounds smaller than their possible maximum. By using + * the `padding` (and `advance` if needed) you can help limit this. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#getBounds + * @since 3.60.0 + * + * @param {number} [padding] - The amount of padding, in pixels, to add to the bounds Rectangle. + * @param {number} [advance] - The number of ms to advance the Particle Emitter by. Defaults to 0, i.e. not used. + * @param {number} [delta] - The amount of delta to use for each step. Defaults to 1000 / 60. + * @param {Phaser.Geom.Rectangle} [output] - The Rectangle to store the results in. If not given a new one will be created. + * + * @return {Phaser.Geom.Rectangle} A Rectangle containing the calculated bounds of this Emitter. + */ + getBounds: function (padding, advance, delta, output) + { + if (padding === undefined) { padding = 0; } + if (advance === undefined) { advance = 0; } + if (delta === undefined) { delta = 1000 / 60; } + if (output === undefined) { output = new Rectangle(); } + + var matrix = this.getWorldTransformMatrix(); + + var i; + var bounds; + var alive = this.alive; + var setFirst = false; + + output.setTo(0, 0, 0, 0); + + if (advance > 0) + { + var total = 0; + + this.skipping = true; + + while (total < Math.abs(advance)) + { + this.preUpdate(0, delta); + + for (i = 0; i < alive.length; i++) + { + bounds = alive[i].getBounds(matrix); + + if (!setFirst) + { + setFirst = true; + + CopyFrom(bounds, output); + } + else + { + MergeRect(output, bounds); + } + } + + total += delta; + } + + this.skipping = false; + } + else + { + for (i = 0; i < alive.length; i++) + { + bounds = alive[i].getBounds(matrix); + + if (!setFirst) + { + setFirst = true; + + CopyFrom(bounds, output); + } + else + { + MergeRect(output, bounds); + } + } + } + + if (padding > 0) + { + Inflate(output, padding, padding); + } + + return output; + }, + + /** + * Prints a warning to the console if you mistakenly call this function + * thinking it works the same way as Phaser v3.55. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#createEmitter + * @since 3.60.0 + */ + createEmitter: function () + { + throw new Error('createEmitter removed. See ParticleEmitter docs for info'); + }, + + /** + * The x coordinate the particles are emitted from. + * + * This is relative to the Emitters x coordinate and that of any parent. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleX + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType} + * @since 3.60.0 + */ + particleX: { + + get: function () + { + return this.ops.x.current; + }, + + set: function (value) + { + this.ops.x.onChange(value); + } + + }, + + /** + * The y coordinate the particles are emitted from. + * + * This is relative to the Emitters x coordinate and that of any parent. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleY + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType|Phaser.Types.GameObjects.Particles.EmitterOpOnUpdateType} + * @since 3.60.0 + */ + particleY: { + + get: function () + { + return this.ops.y.current; + }, + + set: function (value) + { + this.ops.y.onChange(value); + } + + }, + + /** + * The horizontal acceleration applied to emitted particles, in pixels per second squared. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#accelerationX + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + accelerationX: { + + get: function () + { + return this.ops.accelerationX.current; + }, + + set: function (value) + { + this.ops.accelerationX.onChange(value); + } + + }, + + /** + * The vertical acceleration applied to emitted particles, in pixels per second squared. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#accelerationY + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + accelerationY: { + + get: function () + { + return this.ops.accelerationY.current; + }, + + set: function (value) + { + this.ops.accelerationY.onChange(value); + } + + }, + + /** + * The maximum horizontal velocity emitted particles can reach, in pixels per second squared. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#maxVelocityX + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + * @default 10000 + */ + maxVelocityX: { + + get: function () + { + return this.ops.maxVelocityX.current; + }, + + set: function (value) + { + this.ops.maxVelocityX.onChange(value); + } + + }, + + /** + * The maximum vertical velocity emitted particles can reach, in pixels per second squared. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#maxVelocityY + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + * @default 10000 + */ + maxVelocityY: { + + get: function () + { + return this.ops.maxVelocityY.current; + }, + + set: function (value) + { + this.ops.maxVelocityY.onChange(value); + } + + }, + + /** + * The initial speed of emitted particles, in pixels per second. + * + * If using this as a getter it will return the `speedX` value. + * + * If using it as a setter it will update both `speedX` and `speedY` to the + * given value. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#speed + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + speed: { + + get: function () + { + return this.ops.speedX.current; + }, + + set: function (value) + { + this.ops.speedX.onChange(value); + this.ops.speedY.onChange(value); + } + + }, + + /** + * The initial horizontal speed of emitted particles, in pixels per second. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#speedX + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + speedX: { + + get: function () + { + return this.ops.speedX.current; + }, + + set: function (value) + { + this.ops.speedX.onChange(value); + } + + }, + + /** + * The initial vertical speed of emitted particles, in pixels per second. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#speedY + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + speedY: { + + get: function () + { + return this.ops.speedY.current; + }, + + set: function (value) + { + this.ops.speedY.onChange(value); + } + + }, + + /** + * The x coordinate emitted particles move toward, when {@link Phaser.GameObjects.Particles.ParticleEmitter#moveTo} is true. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#moveToX + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + moveToX: { + + get: function () + { + return this.ops.moveToX.current; + }, + + set: function (value) + { + this.ops.moveToX.onChange(value); + } + + }, + + /** + * The y coordinate emitted particles move toward, when {@link Phaser.GameObjects.Particles.ParticleEmitter#moveTo} is true. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#moveToY + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + moveToY: { + + get: function () + { + return this.ops.moveToY.current; + }, + + set: function (value) + { + this.ops.moveToY.onChange(value); + } + + }, + + /** + * The amount of velocity particles will use when rebounding off the + * emitter bounds, if set. A value of 0 means no bounce. A value of 1 + * means a full rebound. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#bounce + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + bounce: { + + get: function () + { + return this.ops.bounce.current; + }, + + set: function (value) + { + this.ops.bounce.onChange(value); + } + + }, + + /** + * The horizontal scale of emitted particles. + * + * This is relative to the Emitters scale and that of any parent. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleScaleX + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleScaleX: { + + get: function () + { + return this.ops.scaleX.current; + }, + + set: function (value) + { + this.ops.scaleX.onChange(value); + } + + }, + + /** + * The vertical scale of emitted particles. + * + * This is relative to the Emitters scale and that of any parent. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleScaleY + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleScaleY: { + + get: function () + { + return this.ops.scaleY.current; + }, + + set: function (value) + { + this.ops.scaleY.onChange(value); + } + + }, + + /** + * A color tint value that is applied to the texture of the emitted + * particle. The value should be given in hex format, i.e. 0xff0000 + * for a red tint, and should not include the alpha channel. + * + * Tints are additive, meaning a tint value of white (0xffffff) will + * effectively reset the tint to nothing. + * + * Modify the `ParticleEmitter.tintFill` property to change between + * an additive and replacement tint mode. + * + * When you define the color via the Emitter config you should give + * it as an array of color values. The Particle will then interpolate + * through these colors over the course of its lifespan. Setting this + * will override any `tint` value that may also be given. + * + * This is a WebGL only feature. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleColor + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleColor: { + + get: function () + { + return this.ops.color.current; + }, + + set: function (value) + { + this.ops.color.onChange(value); + } + + }, + + /** + * Controls the easing function used when you have created an + * Emitter that uses the `color` property to interpolate the + * tint of Particles over their lifetime. + * + * Setting this has no effect if you haven't also applied a + * `particleColor` to this Emitter. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#colorEase + * @type {string} + * @since 3.60.0 + */ + colorEase: { + + get: function () + { + return this.ops.color.easeName; + }, + + set: function (value) + { + this.ops.color.setEase(value); + } + + }, + + /** + * A color tint value that is applied to the texture of the emitted + * particle. The value should be given in hex format, i.e. 0xff0000 + * for a red tint, and should not include the alpha channel. + * + * Tints are additive, meaning a tint value of white (0xffffff) will + * effectively reset the tint to nothing. + * + * Modify the `ParticleEmitter.tintFill` property to change between + * an additive and replacement tint mode. + * + * The `tint` value will be overriden if a `color` array is provided. + * + * This is a WebGL only feature. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleTint + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleTint: { + + get: function () + { + return this.ops.tint.current; + }, + + set: function (value) + { + this.ops.tint.onChange(value); + } + + }, + + /** + * The alpha value of the emitted particles. This is a value + * between 0 and 1. Particles with alpha zero are invisible + * and are therefore not rendered, but are still processed + * by the Emitter. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleAlpha + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleAlpha: { + + get: function () + { + return this.ops.alpha.current; + }, + + set: function (value) + { + this.ops.alpha.onChange(value); + } + + }, + + /** + * The lifespan of the emitted particles. This value is given + * in milliseconds and defaults to 1000ms (1 second). When a + * particle reaches this amount it is killed. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#lifespan + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + lifespan: { + + get: function () + { + return this.ops.lifespan.current; + }, + + set: function (value) + { + this.ops.lifespan.onChange(value); + } + + }, + + /** + * The angle at which the particles are emitted. The values are + * given in degrees. This allows you to control the direction + * of the emitter. If you wish instead to change the rotation + * of the particles themselves, see the `particleRotate` property. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleAngle + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleAngle: { + + get: function () + { + return this.ops.angle.current; + }, + + set: function (value) + { + this.ops.angle.onChange(value); + } + + }, + + /** + * The rotation (or angle) of each particle when it is emitted. + * The value is given in degrees and uses a right-handed + * coordinate system, where 0 degrees points to the right, 90 degrees + * points down and -90 degrees points up. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#particleRotate + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + particleRotate: { + + get: function () + { + return this.ops.rotate.current; + }, + + set: function (value) + { + this.ops.rotate.onChange(value); + } + + }, + + /** + * The number of particles that are emitted each time an emission + * occurs, i.e. from one 'explosion' or each frame in a 'flow' cycle. + * + * The default is 1. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#quantity + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @see Phaser.GameObjects.Particles.ParticleEmitter#setFrequency + * @see Phaser.GameObjects.Particles.ParticleEmitter#setQuantity + * @since 3.60.0 + */ + quantity: { + + get: function () + { + return this.ops.quantity.current; + }, + + set: function (value) + { + this.ops.quantity.onChange(value); + } + + }, + + /** + * The number of milliseconds to wait after emission before + * the particles start updating. This allows you to emit particles + * that appear 'static' or still on-screen and then, after this value, + * begin to move. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#delay + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + delay: { + + get: function () + { + return this.ops.delay.current; + }, + + set: function (value) + { + this.ops.delay.onChange(value); + } + + }, + + /** + * The number of milliseconds to wait after a particle has finished + * its life before it will be removed. This allows you to 'hold' a + * particle on the screen once it has reached its final state + * before it then vanishes. + * + * Note that all particle updates will cease, including changing + * alpha, scale, movement or animation. + * + * Accessing this property should typically return a number. + * However, it can be set to any valid EmitterOp onEmit type. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#hold + * @type {Phaser.Types.GameObjects.Particles.EmitterOpOnEmitType} + * @since 3.60.0 + */ + hold: { + + get: function () + { + return this.ops.hold.current; + }, + + set: function (value) + { + this.ops.hold.onChange(value); + } + + }, + + /** + * The internal flow counter. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#flowCounter + * @type {number} + * @since 3.60.0 + */ + flowCounter: { + + get: function () + { + return this.counters[0]; + }, + + set: function (value) + { + this.counters[0] = value; + } + + }, + + /** + * The internal frame counter. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#frameCounter + * @type {number} + * @since 3.60.0 + */ + frameCounter: { + + get: function () + { + return this.counters[1]; + }, + + set: function (value) + { + this.counters[1] = value; + } + + }, + + /** + * The internal animation counter. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#animCounter + * @type {number} + * @since 3.60.0 + */ + animCounter: { + + get: function () + { + return this.counters[2]; + }, + + set: function (value) + { + this.counters[2] = value; + } + + }, + + /** + * The internal elasped counter. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#elapsed + * @type {number} + * @since 3.60.0 + */ + elapsed: { + + get: function () + { + return this.counters[3]; + }, + + set: function (value) + { + this.counters[3] = value; + } + + }, + + /** + * The internal stop counter. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#stopCounter + * @type {number} + * @since 3.60.0 + */ + stopCounter: { + + get: function () + { + return this.counters[4]; + }, + + set: function (value) + { + this.counters[4] = value; + } + + }, + + /** + * The internal complete flag. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#completeFlag + * @type {boolean} + * @since 3.60.0 + */ + completeFlag: { + + get: function () + { + return this.counters[5]; + }, + + set: function (value) + { + this.counters[5] = value; + } + + }, + + /** + * The internal zone index. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#zoneIndex + * @type {number} + * @since 3.60.0 + */ + zoneIndex: { + + get: function () + { + return this.counters[6]; + }, + + set: function (value) + { + this.counters[6] = value; + } + + }, + + /** + * The internal zone total. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#zoneTotal + * @type {number} + * @since 3.60.0 + */ + zoneTotal: { + + get: function () + { + return this.counters[7]; + }, + + set: function (value) + { + this.counters[7] = value; + } + + }, + + /** + * The current frame index. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#currentFrame + * @type {number} + * @since 3.60.0 + */ + currentFrame: { + + get: function () + { + return this.counters[8]; + }, + + set: function (value) + { + this.counters[8] = value; + } + + }, + + /** + * The current animation index. + * + * Treat this property as read-only. + * + * @name Phaser.GameObjects.Particles.ParticleEmitter#currentAnim + * @type {number} + * @since 3.60.0 + */ + currentAnim: { + + get: function () + { + return this.counters[9]; + }, + + set: function (value) + { + this.counters[9] = value; + } + + }, + + /** + * Destroys this Particle Emitter and all Particles it owns. + * + * @method Phaser.GameObjects.Particles.ParticleEmitter#preDestroy + * @since 3.60.0 + */ + preDestroy: function () + { + this.texture = null; + this.frames = null; + this.anims = null; + this.emitCallback = null; + this.emitCallbackScope = null; + this.deathCallback = null; + this.deathCallbackScope = null; + this.emitZones = null; + this.deathZones = null; + this.bounds = null; + this.follow = null; + this.counters = null; + + var i; + + var ops = this.ops; + + for (i = 0; i < configOpMap.length; i++) + { + var key = configOpMap[i]; + + ops[key].destroy(); + } + + for (i = 0; i < this.alive.length; i++) + { + this.alive[i].destroy(); + } + + for (i = 0; i < this.dead.length; i++) + { + this.dead[i].destroy(); + } + + this.ops = null; + this.alive = []; + this.dead = []; + this.worldMatrix.destroy(); + } + +}); + +module.exports = ParticleEmitter; + + +/***/ }), + +/***/ 9871: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RectangleToRectangle = __webpack_require__(59996); +var TransformMatrix = __webpack_require__(61340); + +var camMatrix = new TransformMatrix(); +var calcMatrix = new TransformMatrix(); +var particleMatrix = new TransformMatrix(); +var managerMatrix = new TransformMatrix(); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Particles.Emitter#renderCanvas + * @since 3.60.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ParticleEmitterCanvasRenderer = function (renderer, emitter, camera, parentMatrix) +{ + camera.addToRenderList(emitter); + + camMatrix.copyWithScrollFactorFrom( + camera.matrix, + camera.scrollX, camera.scrollY, + emitter.scrollFactorX, emitter.scrollFactorY + ); + + if (parentMatrix) + { + camMatrix.multiply(parentMatrix); + } + + managerMatrix.applyITRS( + emitter.x, emitter.y, + emitter.rotation, + emitter.scaleX, emitter.scaleY + ); + + camMatrix.multiply(managerMatrix); + + var ctx = renderer.currentContext; + var roundPixels = camera.roundPixels; + var camerAlpha = camera.alpha; + var emitterAlpha = emitter.alpha; + + var particles = emitter.alive; + var particleCount = particles.length; + var viewBounds = emitter.viewBounds; + + if (!emitter.visible || particleCount === 0 || (viewBounds && !RectangleToRectangle(viewBounds, camera.worldView))) + { + return; + } + + if (emitter.sortCallback) + { + emitter.depthSort(); + } + + ctx.save(); + + ctx.globalCompositeOperation = renderer.blendModes[emitter.blendMode]; + + for (var i = 0; i < particleCount; i++) + { + var particle = particles[i]; + + var alpha = particle.alpha * emitterAlpha * camerAlpha; + + if (alpha <= 0 || particle.scaleX === 0 || particle.scaleY === 0) + { + continue; + } + + particleMatrix.applyITRS(particle.x, particle.y, particle.rotation, particle.scaleX, particle.scaleY); + + // Multiply by the particle matrix, store result in calcMatrix + camMatrix.multiply(particleMatrix, calcMatrix); + + var frame = particle.frame; + var cd = frame.canvasData; + + if (cd.width > 0 && cd.height > 0) + { + var x = -(frame.halfWidth); + var y = -(frame.halfHeight); + + ctx.globalAlpha = alpha; + + ctx.save(); + + calcMatrix.setToContext(ctx); + + if (roundPixels) + { + x = Math.round(x); + y = Math.round(y); + } + + ctx.imageSmoothingEnabled = !frame.source.scaleMode; + + ctx.drawImage(frame.source.image, cd.x, cd.y, cd.width, cd.height, x, y, cd.width, cd.height); + + ctx.restore(); + } + } + + ctx.restore(); +}; + +module.exports = ParticleEmitterCanvasRenderer; + + +/***/ }), + +/***/ 92730: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var GetFastValue = __webpack_require__(95540); +var ParticleEmitter = __webpack_require__(31600); + +/** + * Creates a new Particle Emitter Game Object and returns it. + * + * Prior to Phaser v3.60 this function would create a `ParticleEmitterManager`. These were removed + * in v3.60 and replaced with creating a `ParticleEmitter` instance directly. Please see the + * updated function parameters and class documentation for more details. + * + * Note: This method will only be available if the Particles Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#particles + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterCreatorConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Particles.ParticleEmitter} The Game Object that was created. + */ +GameObjectCreator.register('particles', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var emitterConfig = GetFastValue(config, 'config', null); + + var emitter = new ParticleEmitter(this.scene, 0, 0, key); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, emitter, config); + + if (emitterConfig) + { + emitter.setConfig(emitterConfig); + } + + return emitter; +}); + + +/***/ }), + +/***/ 676: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var ParticleEmitter = __webpack_require__(31600); + +/** + * Creates a new Particle Emitter Game Object and adds it to the Scene. + * + * If you wish to configure the Emitter after creating it, use the `ParticleEmitter.setConfig` method. + * + * Prior to Phaser v3.60 this function would create a `ParticleEmitterManager`. These were removed + * in v3.60 and replaced with creating a `ParticleEmitter` instance directly. Please see the + * updated function parameters and class documentation for more details. + * + * Note: This method will only be available if the Particles Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#particles + * @since 3.60.0 + * + * @param {number} [x] - The horizontal position of this Game Object in the world. + * @param {number} [y] - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} [texture] - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {Phaser.Types.GameObjects.Particles.ParticleEmitterConfig} [config] - Configuration settings for the Particle Emitter. + * + * @return {Phaser.GameObjects.Particles.ParticleEmitter} The Game Object that was created. + */ +GameObjectFactory.register('particles', function (x, y, texture, config) +{ + if (x !== undefined && typeof x === 'string') + { + console.warn('ParticleEmitterManager was removed in Phaser 3.60. See documentation for details'); + } + + return this.displayList.add(new ParticleEmitter(this.scene, x, y, texture, config)); +}); + + +/***/ }), + +/***/ 90668: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(21188); +} + +if (true) +{ + renderCanvas = __webpack_require__(9871); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 21188: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RectangleToRectangle = __webpack_require__(59996); +var TransformMatrix = __webpack_require__(61340); +var Utils = __webpack_require__(70554); + +var camMatrix = new TransformMatrix(); +var calcMatrix = new TransformMatrix(); +var particleMatrix = new TransformMatrix(); +var managerMatrix = new TransformMatrix(); + +var tempTexturer = {}; +var tempTinter = {}; +var tempTransformer = { quad: new Float32Array(8) }; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Particles.Emitter#renderWebGL + * @since 3.60.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ParticleEmitterWebGLRenderer = function (renderer, emitter, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + + camera.addToRenderList(emitter); + + camMatrix.copyWithScrollFactorFrom( + camera.getViewMatrix(!drawingContext.useCanvas), + camera.scrollX, camera.scrollY, + emitter.scrollFactorX, emitter.scrollFactorY + ); + + if (parentMatrix) + { + camMatrix.multiply(parentMatrix); + } + + managerMatrix.applyITRS( + emitter.x, emitter.y, + emitter.rotation, + emitter.scaleX, emitter.scaleY + ); + + camMatrix.multiply(managerMatrix); + + var getTint = Utils.getTintAppendFloatAlpha; + var emitterAlpha = emitter.alpha; + + var particles = emitter.alive; + var particleCount = particles.length; + var viewBounds = emitter.viewBounds; + + if (particleCount === 0 || (viewBounds && !RectangleToRectangle(viewBounds, camera.worldView))) + { + return; + } + + if (emitter.sortCallback) + { + emitter.depthSort(); + } + + var tintFill = emitter.tintFill; + + for (var i = 0; i < particleCount; i++) + { + var particle = particles[i]; + + var alpha = particle.alpha * emitterAlpha; + + if (alpha <= 0 || particle.scaleX === 0 || particle.scaleY === 0) + { + continue; + } + + particleMatrix.applyITRS(particle.x, particle.y, particle.rotation, particle.scaleX, particle.scaleY); + + // Multiply by the particle matrix, store result in calcMatrix + camMatrix.multiply(particleMatrix, calcMatrix); + + var frame = particle.frame; + + var x = -frame.halfWidth; + var y = -frame.halfHeight; + + calcMatrix.setQuad(x, y, x + frame.width, y + frame.height, tempTransformer.quad); + + if (tempTexturer.frame !== frame) + { + tempTexturer.frame = frame; + tempTexturer.uvSource = frame; + } + + var tint = getTint(particle.tint, alpha); + tempTinter.tintTopLeft = tint; + tempTinter.tintBottomLeft = tint; + tempTinter.tintTopRight = tint; + tempTinter.tintBottomRight = tint; + tempTinter.tintFill = tintFill; + + var normalMap, normalMapRotation; + + if (emitter.lighting) + { + if (particle.texture) + { + normalMap = frame.texture.dataSource[frame.sourceIndex]; + } + + normalMapRotation = particle.rotation; + if (emitter.parentContainer) + { + var matrix = emitter.getWorldTransformMatrix(camMatrix, calcMatrix).rotate(particle.rotation); + + normalMapRotation = matrix.rotationNormalized; + } + } + + var customRenderNodes = emitter.customRenderNodes; + var defaultRenderNodes = emitter.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + emitter, + parentMatrix, + 0, + tempTexturer, + tempTransformer, + tempTinter, + + // Optional normal map overrides + normalMap, normalMapRotation + ); + } +}; + +module.exports = ParticleEmitterWebGLRenderer; + + +/***/ }), + +/***/ 20286: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * This class provides the structured required for all Particle Processors. + * + * You should extend it and add the functionality required for your processor, + * including tidying up any resources this may create in the `destroy` method. + * + * See the GravityWell for an example of a processor. + * + * @class ParticleProcessor + * @memberof Phaser.GameObjects.Particles + * @constructor + * @since 3.60.0 + * + * @param {number} [x=0] - The x coordinate of the Particle Processor, in world space. + * @param {number} [y=0] - The y coordinate of the Particle Processor, in world space. + * @param {boolean} [active=true] - The active state of this Particle Processor. + */ +var ParticleProcessor = new Class({ + + initialize: + + function ParticleProcessor (x, y, active) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (active === undefined) { active = true; } + + /** + * A reference to the Particle Emitter that owns this Processor. + * This is set automatically when the Processor is added to an Emitter + * and nulled when removed or destroyed. + * + * @name Phaser.GameObjects.Particles.ParticleProcessor#manager + * @type {Phaser.GameObjects.Particles.ParticleEmitter} + * @since 3.60.0 + */ + this.emitter; + + /** + * The x coordinate of the Particle Processor, in world space. + * + * @name Phaser.GameObjects.Particles.ParticleProcessor#x + * @type {number} + * @since 3.60.0 + */ + this.x = x; + + /** + * The y coordinate of the Particle Processor, in world space. + * + * @name Phaser.GameObjects.Particles.ParticleProcessor#y + * @type {number} + * @since 3.60.0 + */ + this.y = y; + + /** + * The active state of the Particle Processor. + * + * An inactive Particle Processor will be skipped for processing by + * its parent Emitter. + * + * @name Phaser.GameObjects.Particles.ParticleProcessor#active + * @type {boolean} + * @since 3.60.0 + */ + this.active = active; + }, + + /** + * The Particle Processor update method should be overriden by your own + * method and handle the processing of the particles, typically modifying + * their velocityX/Y values based on the criteria of this processor. + * + * @method Phaser.GameObjects.Particles.ParticleProcessor#update + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The Particle to update. + * @param {number} delta - The delta time in ms. + * @param {number} step - The delta value divided by 1000. + * @param {number} t - The current normalized lifetime of the particle, between 0 (birth) and 1 (death). + */ + update: function () + { + }, + + /** + * Destroys this Particle Processor by removing all external references. + * + * This is called automatically when the owning Particle Emitter is destroyed. + * + * @method Phaser.GameObjects.Particles.ParticleProcessor#destroy + * @since 3.60.0 + */ + destroy: function () + { + this.emitter = null; + } + +}); + +module.exports = ParticleProcessor; + + +/***/ }), + +/***/ 9774: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Particle Emitter Complete Event. + * + * This event is dispatched when the final particle, emitted from a Particle Emitter that + * has been stopped, dies. Upon receipt of this event you know that no particles are + * still rendering at this point in time. + * + * Listen for it on a Particle Emitter instance using `ParticleEmitter.on('complete', listener)`. + * + * @event Phaser.GameObjects.Particles.Events#COMPLETE + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - A reference to the Particle Emitter that just completed. + */ +module.exports = 'complete'; + + +/***/ }), + +/***/ 812: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Particle Emitter Death Zone Event. + * + * This event is dispatched when a Death Zone kills a Particle instance. + * + * Listen for it on a Particle Emitter instance using `ParticleEmitter.on('deathzone', listener)`. + * + * If you wish to know when the final particle is killed, see the `COMPLETE` event. + * + * @event Phaser.GameObjects.Particles.Events#DEATH_ZONE + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - A reference to the Particle Emitter that owns the Particle and Death Zone. + * @param {Phaser.GameObjects.Particles.Particle} particle - The Particle that has been killed. + * @param {Phaser.GameObjects.Particles.Zones.DeathZone} zone - The Death Zone that killed the particle. + */ +module.exports = 'deathzone'; + + +/***/ }), + +/***/ 30522: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Particle Emitter Explode Event. + * + * This event is dispatched when a Particle Emitter explodes a set of particles. + * + * Listen for it on a Particle Emitter instance using `ParticleEmitter.on('explode', listener)`. + * + * @event Phaser.GameObjects.Particles.Events#EXPLODE + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - A reference to the Particle Emitter that just completed. + * @param {Phaser.GameObjects.Particles.Particle} particle - The most recently emitted Particle. + */ +module.exports = 'explode'; + + +/***/ }), + +/***/ 96695: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Particle Emitter Start Event. + * + * This event is dispatched when a Particle Emitter starts emission of particles. + * + * Listen for it on a Particle Emitter instance using `ParticleEmitter.on('start', listener)`. + * + * @event Phaser.GameObjects.Particles.Events#START + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - A reference to the Particle Emitter that just completed. + */ +module.exports = 'start'; + + +/***/ }), + +/***/ 18677: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Particle Emitter Stop Event. + * + * This event is dispatched when a Particle Emitter is stopped. This can happen either + * when you directly call the `ParticleEmitter.stop` method, or if the emitter has + * been configured to stop after a set time via the `duration` property, or after a + * set number of particles via the `stopAfter` property. + * + * Listen for it on a Particle Emitter instance using `ParticleEmitter.on('stop', listener)`. + * + * Note that just because the emitter has stopped, that doesn't mean there aren't still + * particles alive and rendering. It just means the emitter has stopped emitting particles. + * + * If you wish to know when the final particle is killed, see the `COMPLETE` event. + * + * @event Phaser.GameObjects.Particles.Events#STOP + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.GameObjects.Particles.ParticleEmitter} emitter - A reference to the Particle Emitter that just completed. + */ +module.exports = 'stop'; + + +/***/ }), + +/***/ 20696: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.GameObjects.Particles.Events + */ + +module.exports = { + + COMPLETE: __webpack_require__(9774), + DEATH_ZONE: __webpack_require__(812), + EXPLODE: __webpack_require__(30522), + START: __webpack_require__(96695), + STOP: __webpack_require__(18677) + +}; + + +/***/ }), + +/***/ 18404: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.GameObjects.Particles + */ + +module.exports = { + + EmitterColorOp: __webpack_require__(76472), + EmitterOp: __webpack_require__(44777), + Events: __webpack_require__(20696), + GravityWell: __webpack_require__(24502), + Particle: __webpack_require__(56480), + ParticleBounds: __webpack_require__(69601), + ParticleEmitter: __webpack_require__(31600), + ParticleProcessor: __webpack_require__(20286), + Zones: __webpack_require__(21024) + +}; + + +/***/ }), + +/***/ 26388: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A Death Zone. + * + * A Death Zone is a special type of zone that will kill a Particle as soon as it either enters, or leaves, the zone. + * + * The zone consists of a `source` which could be a Geometric shape, such as a Rectangle or Ellipse, or your own + * object as long as it includes a `contains` method for which the Particles can be tested against. + * + * @class DeathZone + * @memberof Phaser.GameObjects.Particles.Zones + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.DeathZoneSource} source - An object instance that has a `contains` method that returns a boolean when given `x` and `y` arguments. + * @param {boolean} killOnEnter - Should the Particle be killed when it enters the zone? `true` or leaves it? `false` + */ +var DeathZone = new Class({ + + initialize: + + function DeathZone (source, killOnEnter) + { + /** + * An object instance that has a `contains` method that returns a boolean when given `x` and `y` arguments. + * This could be a Geometry shape, such as `Phaser.Geom.Circle`, or your own custom object. + * + * @name Phaser.GameObjects.Particles.Zones.DeathZone#source + * @type {Phaser.Types.GameObjects.Particles.DeathZoneSource} + * @since 3.0.0 + */ + this.source = source; + + /** + * Set to `true` if the Particle should be killed if it enters this zone. + * Set to `false` to kill the Particle if it leaves this zone. + * + * @name Phaser.GameObjects.Particles.Zones.DeathZone#killOnEnter + * @type {boolean} + * @since 3.0.0 + */ + this.killOnEnter = killOnEnter; + }, + + /** + * Checks if the given Particle will be killed or not by this zone. + * + * @method Phaser.GameObjects.Particles.Zones.DeathZone#willKill + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The particle to test against this Death Zones. + * + * @return {boolean} Return `true` if the Particle is to be killed, otherwise return `false`. + */ + willKill: function (particle) + { + var pos = particle.worldPosition; + var withinZone = this.source.contains(pos.x, pos.y); + + return (withinZone && this.killOnEnter || !withinZone && !this.killOnEnter); + } + +}); + +module.exports = DeathZone; + + +/***/ }), + +/***/ 19909: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A zone that places particles on a shape's edges. + * + * @class EdgeZone + * @memberof Phaser.GameObjects.Particles.Zones + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.EdgeZoneSource} source - An object instance with a `getPoints(quantity, stepRate)` method returning an array of points. + * @param {number} quantity - The number of particles to place on the source edge. Set to 0 to use `stepRate` instead. + * @param {number} [stepRate] - The distance between each particle. When set, `quantity` is implied and should be set to 0. + * @param {boolean} [yoyo=false] - Whether particles are placed from start to end and then end to start. + * @param {boolean} [seamless=true] - Whether one endpoint will be removed if it's identical to the other. + * @param {number} [total=-1] - The total number of particles this zone will emit before passing over to the next emission zone in the Emitter. -1 means it will never pass over and you must use `setEmitZone` to change it. + */ +var EdgeZone = new Class({ + + initialize: + + function EdgeZone (source, quantity, stepRate, yoyo, seamless, total) + { + if (yoyo === undefined) { yoyo = false; } + if (seamless === undefined) { seamless = true; } + if (total === undefined) { total = -1; } + + /** + * An object instance with a `getPoints(quantity, stepRate)` method returning an array of points. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#source + * @type {Phaser.Types.GameObjects.Particles.EdgeZoneSource|Phaser.Types.GameObjects.Particles.RandomZoneSource} + * @since 3.0.0 + */ + this.source = source; + + /** + * The points placed on the source edge. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#points + * @type {Phaser.Math.Vector2[]} + * @default [] + * @since 3.0.0 + */ + this.points = []; + + /** + * The number of particles to place on the source edge. Set to 0 to use `stepRate` instead. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#quantity + * @type {number} + * @since 3.0.0 + */ + this.quantity = quantity; + + /** + * The distance between each particle. When set, `quantity` is implied and should be set to 0. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#stepRate + * @type {number} + * @since 3.0.0 + */ + this.stepRate = stepRate; + + /** + * Whether particles are placed from start to end and then end to start. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#yoyo + * @type {boolean} + * @since 3.0.0 + */ + this.yoyo = yoyo; + + /** + * The counter used for iterating the EdgeZone's points. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#counter + * @type {number} + * @default -1 + * @since 3.0.0 + */ + this.counter = -1; + + /** + * Whether one endpoint will be removed if it's identical to the other. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#seamless + * @type {boolean} + * @since 3.0.0 + */ + this.seamless = seamless; + + /** + * An internal count of the points belonging to this EdgeZone. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#_length + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._length = 0; + + /** + * An internal value used to keep track of the current iteration direction for the EdgeZone's points. + * + * 0 = forwards, 1 = backwards + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#_direction + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._direction = 0; + + /** + * The total number of particles this zone will emit before the Emitter + * transfers control over to the next zone in its emission zone list. + * + * By default this is -1, meaning it will never pass over from this + * zone to another one. You can call the `ParticleEmitter.setEmitZone` + * method to change it, or set this value to something else via the + * config, or directly at runtime. + * + * A value of 1 would mean the zones rotate in order, but it can + * be set to any integer value. + * + * @name Phaser.GameObjects.Particles.Zones.EdgeZone#total + * @type {number} + * @since 3.60.0 + */ + this.total = total; + + this.updateSource(); + }, + + /** + * Update the {@link Phaser.GameObjects.Particles.Zones.EdgeZone#points} from the EdgeZone's + * {@link Phaser.GameObjects.Particles.Zones.EdgeZone#source}. + * + * Also updates internal properties. + * + * @method Phaser.GameObjects.Particles.Zones.EdgeZone#updateSource + * @since 3.0.0 + * + * @return {this} This Edge Zone. + */ + updateSource: function () + { + this.points = this.source.getPoints(this.quantity, this.stepRate); + + // Remove ends? + if (this.seamless) + { + var a = this.points[0]; + var b = this.points[this.points.length - 1]; + + if (a.x === b.x && a.y === b.y) + { + this.points.pop(); + } + } + + var oldLength = this._length; + + this._length = this.points.length; + + // Adjust counter if we now have less points than before + if (this._length < oldLength && this.counter > this._length) + { + this.counter = this._length - 1; + } + + return this; + }, + + /** + * Change the source of the EdgeZone. + * + * @method Phaser.GameObjects.Particles.Zones.EdgeZone#changeSource + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.EdgeZoneSource} source - An object instance with a `getPoints(quantity, stepRate)` method returning an array of points. + * + * @return {this} This Edge Zone. + */ + changeSource: function (source) + { + this.source = source; + + return this.updateSource(); + }, + + /** + * Get the next point in the Zone and set its coordinates on the given Particle. + * + * @method Phaser.GameObjects.Particles.Zones.EdgeZone#getPoint + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The Particle. + */ + getPoint: function (particle) + { + if (this._direction === 0) + { + this.counter++; + + if (this.counter >= this._length) + { + if (this.yoyo) + { + this._direction = 1; + this.counter = this._length - 1; + } + else + { + this.counter = 0; + } + } + } + else + { + this.counter--; + + if (this.counter === -1) + { + if (this.yoyo) + { + this._direction = 0; + this.counter = 0; + } + else + { + this.counter = this._length - 1; + } + } + } + + var point = this.points[this.counter]; + + if (point) + { + particle.x = point.x; + particle.y = point.y; + } + } + +}); + +module.exports = EdgeZone; + + +/***/ }), + +/***/ 68875: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A zone that places particles randomly within a shapes area. + * + * @class RandomZone + * @memberof Phaser.GameObjects.Particles.Zones + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Particles.RandomZoneSource} source - An object instance with a `getRandomPoint(point)` method. + */ +var RandomZone = new Class({ + + initialize: + + function RandomZone (source) + { + /** + * An object instance with a `getRandomPoint(point)` method. + * + * @name Phaser.GameObjects.Particles.Zones.RandomZone#source + * @type {Phaser.Types.GameObjects.Particles.RandomZoneSource} + * @since 3.0.0 + */ + this.source = source; + + /** + * Internal calculation vector. + * + * @name Phaser.GameObjects.Particles.Zones.RandomZone#_tempVec + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tempVec = new Vector2(); + + /** + * The total number of particles this zone will emit before the Emitter + * transfers control over to the next zone in its emission zone list. + * + * By default this is -1, meaning it will never pass over from this + * zone to another one. You can call the `ParticleEmitter.setEmitZone` + * method to change it, or set this value to something else via the + * config, or directly at runtime. + * + * A value of 1 would mean the zones rotate in order, but it can + * be set to any integer value. + * + * @name Phaser.GameObjects.Particles.Zones.RandomZone#total + * @type {number} + * @since 3.60.0 + */ + this.total = -1; + }, + + /** + * Get the next point in the Zone and set its coordinates on the given Particle. + * + * @method Phaser.GameObjects.Particles.Zones.RandomZone#getPoint + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Particles.Particle} particle - The Particle. + */ + getPoint: function (particle) + { + var vec = this._tempVec; + + this.source.getRandomPoint(vec); + + particle.x = vec.x; + particle.y = vec.y; + } + +}); + +module.exports = RandomZone; + + +/***/ }), + +/***/ 21024: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.GameObjects.Particles.Zones + */ + +module.exports = { + + DeathZone: __webpack_require__(26388), + EdgeZone: __webpack_require__(19909), + RandomZone: __webpack_require__(68875) + +}; + + +/***/ }), + +/***/ 1159: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var Sprite = __webpack_require__(68287); + +/** + * @classdesc + * A PathFollower Game Object. + * + * A PathFollower is a Sprite Game Object with some extra helpers to allow it to follow a Path automatically. + * + * Anything you can do with a standard Sprite can be done with this PathFollower, such as animate it, tint it, + * scale it and so on. + * + * PathFollowers are bound to a single Path at any one time and can traverse the length of the Path, from start + * to finish, forwards or backwards, or from any given point on the Path to its end. They can optionally rotate + * to face the direction of the path, be offset from the path coordinates or rotate independently of the Path. + * + * @class PathFollower + * @extends Phaser.GameObjects.Sprite + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.PathFollower + * + * @param {Phaser.Scene} scene - The Scene to which this PathFollower belongs. + * @param {Phaser.Curves.Path} path - The Path this PathFollower is following. It can only follow one Path at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + */ +var PathFollower = new Class({ + + Extends: Sprite, + + Mixins: [ + Components.PathFollower + ], + + initialize: + + function PathFollower (scene, path, x, y, texture, frame) + { + Sprite.call(this, scene, x, y, texture, frame); + + this.path = path; + }, + + /** + * Internal update handler that advances this PathFollower along the path. + * + * Called automatically by the Scene step, should not typically be called directly. + * + * @method Phaser.GameObjects.PathFollower#preUpdate + * @protected + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + preUpdate: function (time, delta) + { + this.anims.update(time, delta); + this.pathUpdate(time); + } + +}); + +module.exports = PathFollower; + + +/***/ }), + +/***/ 90145: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var PathFollower = __webpack_require__(1159); + +/** + * Creates a new PathFollower Game Object and adds it to the Scene. + * + * Note: This method will only be available if the PathFollower Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#follower + * @since 3.0.0 + * + * @param {Phaser.Curves.Path} path - The Path this PathFollower is connected to. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.GameObjects.PathFollower} The Game Object that was created. + */ +GameObjectFactory.register('follower', function (path, x, y, key, frame) +{ + var sprite = new PathFollower(this.scene, path, x, y, key, frame); + + this.displayList.add(sprite); + this.updateList.add(sprite); + + return sprite; +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 80321: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultPointLightNodes = __webpack_require__(43246); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var IntegerToColor = __webpack_require__(30100); +var Render = __webpack_require__(67277); + +/** + * @classdesc + * The Point Light Game Object provides a way to add a point light effect into your game, + * without the expensive shader processing requirements of the traditional Light Game Object. + * + * The difference is that the Point Light renders using a custom shader, designed to give the + * impression of a point light source, of variable radius, intensity and color, in your game. + * However, unlike the Light Game Object, it does not impact any other Game Objects, or use their + * normal maps for calculations. This makes them extremely fast to render compared to Lights + * and perfect for special effects, such as flickering torches or muzzle flashes. + * + * For maximum performance you should batch Point Light Game Objects together. This means + * ensuring they follow each other consecutively on the display list. Ideally, use a Layer + * Game Object and then add just Point Lights to it, so that it can batch together the rendering + * of the lights. You don't _have_ to do this, and if you've only a handful of Point Lights in + * your game then it's perfectly safe to mix them into the display list as normal. However, if + * you're using a large number of them, please consider how they are mixed into the display list. + * + * The renderer will automatically cull Point Lights. Those with a radius that does not intersect + * with the Camera will be skipped in the rendering list. This happens automatically and the + * culled state is refreshed every frame, for every camera. + * + * The origin of a Point Light is always 0.5 and it cannot be changed. + * + * Point Lights are a WebGL only feature and do not have a Canvas counterpart. + * + * @class PointLight + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.50.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Point Light belongs. A Point Light can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Point Light in the world. + * @param {number} y - The vertical position of this Point Light in the world. + * @param {number} [color=0xffffff] - The color of the Point Light, given as a hex value. + * @param {number} [radius=128] - The radius of the Point Light. + * @param {number} [intensity=1] - The intensity, or color blend, of the Point Light. + * @param {number} [attenuation=0.1] - The attenuation of the Point Light. This is the reduction of light from the center point. + */ +var PointLight = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.Mask, + Components.RenderNodes, + Components.ScrollFactor, + Components.Transform, + Components.Visible, + Render + ], + + initialize: + + function PointLight (scene, x, y, color, radius, intensity, attenuation) + { + if (color === undefined) { color = 0xffffff; } + if (radius === undefined) { radius = 128; } + if (intensity === undefined) { intensity = 1; } + if (attenuation === undefined) { attenuation = 0.1; } + + GameObject.call(this, scene, 'PointLight'); + + this.initRenderNodes(this._defaultRenderNodesMap); + + this.setPosition(x, y); + + /** + * The color of this Point Light. This property is an instance of a + * Color object, so you can use the methods within it, such as `setTo(r, g, b)` + * to change the color value. + * + * @name Phaser.GameObjects.PointLight#color + * @type {Phaser.Display.Color} + * @since 3.50.0 + */ + this.color = IntegerToColor(color); + + /** + * The intensity of the Point Light. + * + * The colors of the light are multiplied by this value during rendering. + * + * @name Phaser.GameObjects.PointLight#intensity + * @type {number} + * @since 3.50.0 + */ + this.intensity = intensity; + + /** + * The attenuation of the Point Light. + * + * This value controls the force with which the light falls-off from the center of the light. + * + * Use small float-based values, i.e. 0.1. + * + * @name Phaser.GameObjects.PointLight#attenuation + * @type {number} + * @since 3.50.0 + */ + this.attenuation = attenuation; + + // read only: + this.width = radius * 2; + this.height = radius * 2; + + this._radius = radius; + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.PointLight#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultPointLightNodes; + } + }, + + /** + * The radius of the Point Light. + * + * @name Phaser.GameObjects.PointLight#radius + * @type {number} + * @since 3.50.0 + */ + radius: { + + get: function () + { + return this._radius; + }, + + set: function (value) + { + this._radius = value; + this.width = value * 2; + this.height = value * 2; + } + + }, + + originX: { + + get: function () + { + return 0.5; + } + + }, + + originY: { + + get: function () + { + return 0.5; + } + + }, + + displayOriginX: { + + get: function () + { + return this._radius; + } + + }, + + displayOriginY: { + + get: function () + { + return this._radius; + } + + } + +}); + +module.exports = PointLight; + + +/***/ }), + +/***/ 39829: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var PointLight = __webpack_require__(80321); + +/** + * Creates a new Point Light Game Object and returns it. + * + * Note: This method will only be available if the Point Light Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#pointlight + * @since 3.50.0 + * + * @param {object} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.PointLight} The Game Object that was created. + */ +GameObjectCreator.register('pointlight', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var color = GetAdvancedValue(config, 'color', 0xffffff); + var radius = GetAdvancedValue(config, 'radius', 128); + var intensity = GetAdvancedValue(config, 'intensity', 1); + var attenuation = GetAdvancedValue(config, 'attenuation', 0.1); + + var layer = new PointLight(this.scene, 0, 0, color, radius, intensity, attenuation); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, layer, config); + + return layer; +}); + + +/***/ }), + +/***/ 71255: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var PointLight = __webpack_require__(80321); + +/** + * Creates a new Point Light Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Point Light Game Object has been built into Phaser. + * + * The Point Light Game Object provides a way to add a point light effect into your game, + * without the expensive shader processing requirements of the traditional Light Game Object. + * + * The difference is that the Point Light renders using a custom shader, designed to give the + * impression of a point light source, of variable radius, intensity and color, in your game. + * However, unlike the Light Game Object, it does not impact any other Game Objects, or use their + * normal maps for calcuations. This makes them extremely fast to render compared to Lights + * and perfect for special effects, such as flickering torches or muzzle flashes. + * + * For maximum performance you should batch Point Light Game Objects together. This means + * ensuring they follow each other consecutively on the display list. Ideally, use a Layer + * Game Object and then add just Point Lights to it, so that it can batch together the rendering + * of the lights. You don't _have_ to do this, and if you've only a handful of Point Lights in + * your game then it's perfectly safe to mix them into the display list as normal. However, if + * you're using a large number of them, please consider how they are mixed into the display list. + * + * The renderer will automatically cull Point Lights. Those with a radius that does not intersect + * with the Camera will be skipped in the rendering list. This happens automatically and the + * culled state is refreshed every frame, for every camera. + * + * The origin of a Point Light is always 0.5 and it cannot be changed. + * + * Point Lights are a WebGL only feature and do not have a Canvas counterpart. + * + * @method Phaser.GameObjects.GameObjectFactory#pointlight + * @since 3.50.0 + * + * @param {number} x - The horizontal position of this Point Light in the world. + * @param {number} y - The vertical position of this Point Light in the world. + * @param {number} [color=0xffffff] - The color of the Point Light, given as a hex value. + * @param {number} [radius=128] - The radius of the Point Light. + * @param {number} [intensity=1] - The intensity, or color blend, of the Point Light. + * @param {number} [attenuation=0.1] - The attenuation of the Point Light. This is the reduction of light from the center point. + * + * @return {Phaser.GameObjects.PointLight} The Game Object that was created. + */ +GameObjectFactory.register('pointlight', function (x, y, color, radius, intensity, attenuation) +{ + return this.displayList.add(new PointLight(this.scene, x, y, color, radius, intensity, attenuation)); +}); + + +/***/ }), + +/***/ 67277: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(57787); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 57787: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.PointLight#renderWebGL + * @since 3.50.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.PointLight} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var PointLightWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var width = src.width; + var height = src.height; + + var x = -src._radius; + var y = -src._radius; + + var xw = x + width; + var yh = y + height; + + var lightX = calcMatrix.getX(0, 0); + var lightY = calcMatrix.getY(0, 0); + + var txTL = calcMatrix.getX(x, y); + var tyTL = calcMatrix.getY(x, y); + + var txBL = calcMatrix.getX(x, yh); + var tyBL = calcMatrix.getY(x, yh); + + var txBR = calcMatrix.getX(xw, yh); + var tyBR = calcMatrix.getY(xw, yh); + + var txTR = calcMatrix.getX(xw, y); + var tyTR = calcMatrix.getY(xw, y); + + (src.customRenderNodes.BatchHandler || src.defaultRenderNodes.BatchHandler).batch( + drawingContext, + src, + txTL, tyTL, + txBL, tyBL, + txTR, tyTR, + txBR, tyBR, + lightX, lightY + ); +}; + +module.exports = PointLightWebGLRenderer; + + +/***/ }), + +/***/ 591: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var UUID = __webpack_require__(45650); +var Image = __webpack_require__(88571); +var RenderTextureRender = __webpack_require__(83999); +var RenderTextureRenderModes = __webpack_require__(58855); + +/** + * @classdesc + * A Render Texture is a combination of Dynamic Texture and an Image Game Object, that uses the + * Dynamic Texture to display itself with. + * + * A Dynamic Texture is a special texture that allows you to draw textures, frames and most kind of + * Game Objects directly to it. + * + * You can take many complex objects and draw them to this one texture, which can then be used as the + * base texture for other Game Objects, such as Sprites. Should you then update this texture, all + * Game Objects using it will instantly be updated as well, reflecting the changes immediately. + * + * It's a powerful way to generate dynamic textures at run-time that are WebGL friendly and don't invoke + * expensive GPU uploads on each change. + * + * In versions of Phaser before 3.60 a Render Texture was the only way you could create a texture + * like this, that had the ability to be drawn on. But in 3.60 we split the core functions out to + * the Dynamic Texture class as it made a lot more sense for them to reside in there. As a result, + * the Render Texture is now a light-weight shim that sits on-top of an Image Game Object and offers + * proxy methods to the features available from a Dynamic Texture. + * + * **When should you use a Render Texture vs. a Dynamic Texture?** + * + * You should use a Dynamic Texture if the texture is going to be used by multiple Game Objects, + * or you want to use it across multiple Scenes, because textures are globally stored. + * + * You should use a Dynamic Texture if the texture isn't going to be displayed in-game, but is + * instead going to be used for something like a mask or shader. + * + * You should use a Render Texture if you need to display the texture in-game on a single Game Object, + * as it provides the convenience of wrapping an Image and Dynamic Texture together for you. + * + * Under WebGL1, a FrameBuffer, which is what this Dynamic Texture uses internally, cannot be anti-aliased. + * This means that when drawing objects such as Shapes or Graphics instances to this texture, they may appear + * to be drawn with no aliasing around the edges. This is a technical limitation of WebGL1. To get around it, + * create your shape as a texture in an art package, then draw that to this texture. + * + * @class RenderTexture + * @extends Phaser.GameObjects.Image + * @memberof Phaser.GameObjects + * @constructor + * @since 3.2.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=32] - The width of the Render Texture. + * @param {number} [height=32] - The height of the Render Texture. + * @param {boolean} [forceEven=true] - Force the given width and height to be rounded to even values. This significantly improves the rendering quality. Set to false if you know you need an odd sized texture. + */ +var RenderTexture = new Class({ + + Extends: Image, + + Mixins: [ + RenderTextureRender + ], + + initialize: + + function RenderTexture (scene, x, y, width, height, forceEven) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 32; } + if (height === undefined) { height = 32; } + if (forceEven === undefined) { forceEven = true; } + + var dynamicTexture = scene.sys.textures.addDynamicTexture(UUID(), width, height, forceEven); + + Image.call(this, scene, x, y, dynamicTexture); + + this.type = 'RenderTexture'; + + /** + * An internal Camera that can be used to move around this Render Texture. + * + * Control it just like you would any Scene Camera. The difference is that it only impacts + * the placement of Game Objects that you then draw to this texture. + * + * You can scroll, zoom and rotate this Camera. + * + * This property is a reference to `RenderTexture.texture.camera`. + * + * @name Phaser.GameObjects.RenderTexture#camera + * @type {Phaser.Cameras.Scene2D.BaseCamera} + * @since 3.12.0 + */ + this.camera = this.texture.camera; + + /** + * Internal saved texture flag. + * + * @name Phaser.GameObjects.RenderTexture#_saved + * @type {boolean} + * @private + * @since 3.12.0 + */ + this._saved = false; + + /** + * The render mode of this Render Texture. + * Set this property to change how the Render Texture is rendered. + * + * - 'render' mode draws the contents of the Render Texture to each frame. + * - 'redraw' mode calls `render()` and redraws the texture every frame, + * but does not render itself. This is useful for updating textures + * for reuse by other objects. + * - 'all' mode calls `render()` then draws the texture to the frame. + * + * @name Phaser.GameObjects.RenderTexture#renderMode + * @type {'render'|'redraw'|'all'} + * @default 'render' + * @since 4.0.0 + */ + this.renderMode = RenderTextureRenderModes.RENDER; + + /** + * Whether this RenderTexture is currently executing `renderWebGL`. + * This is used to prevent infinite loops when drawing containers. + * You should not set this property directly. + * + * @name Phaser.GameObjects.RenderTexture#isCurrentlyRendering + * @type {boolean} + * @readonly + * @since 4.0.0 + */ + this.isCurrentlyRendering = false; + }, + + /** + * Sets the internal size of this Render Texture, as used for frame or physics body creation. + * + * This will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or call the + * `setDisplaySize` method, which is the same thing as changing the scale but allows you + * to do so by giving pixel values. You could also call the `resize` method, as that + * will resize the underlying texture. + * + * If you have enabled this Game Object for input, changing the size will also change the + * size of the hit area, unless you have defined a custom hit area. + * + * @method Phaser.GameObjects.RenderTexture#setSize + * @since 3.0.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + + this.updateDisplayOrigin(); + + var input = this.input; + + if (input && !input.customHitArea) + { + input.hitArea.width = width; + input.hitArea.height = height; + } + + return this; + }, + + /** + * Resizes the Render Texture to the new dimensions given. + * + * In WebGL it will destroy and then re-create the frame buffer being used by the Render Texture. + * In Canvas it will resize the underlying canvas element. + * + * Both approaches will erase everything currently drawn to the Render Texture. + * + * Calling this will then invoke the `setSize` method, setting the internal size of this Game Object + * to the values given to this method. + * + * If the dimensions given are the same as those already being used, calling this method will do nothing. + * + * @method Phaser.GameObjects.RenderTexture#resize + * @since 3.10.0 + * + * @param {number} width - The new width of the Render Texture. + * @param {number} [height=width] - The new height of the Render Texture. If not specified, will be set the same as the `width`. + * @param {boolean} [forceEven=true] - Force the given width and height to be rounded to even values. This significantly improves the rendering quality. Set to false if you know you need an odd sized texture. + * + * @return {this} This Render Texture. + */ + resize: function (width, height, forceEven) + { + this.texture.setSize(width, height, forceEven); + + this.setSize(this.texture.width, this.texture.height); + + return this; + }, + + /** + * Stores a copy of this Render Texture in the Texture Manager using the given key. + * + * After doing this, any texture based Game Object, such as a Sprite, can use the contents of this + * Render Texture by using the texture key: + * + * ```javascript + * var rt = this.add.renderTexture(0, 0, 128, 128); + * + * // Draw something to the Render Texture + * + * rt.saveTexture('doodle'); + * + * this.add.image(400, 300, 'doodle'); + * ``` + * + * Updating the contents of this Render Texture will automatically update _any_ Game Object + * that is using it as a texture. Calling `saveTexture` again will not save another copy + * of the same texture, it will just rename the key of the existing copy. + * + * By default it will create a single base texture. You can add frames to the texture + * by using the `Texture.add` method. After doing this, you can then allow Game Objects + * to use a specific frame from a Render Texture. + * + * If you destroy this Render Texture, any Game Object using it via the Texture Manager will + * stop rendering. Ensure you remove the texture from the Texture Manager and any Game Objects + * using it first, before destroying this Render Texture. + * + * @method Phaser.GameObjects.RenderTexture#saveTexture + * @since 3.12.0 + * + * @param {string} key - The unique key to store the texture as within the global Texture Manager. + * + * @return {Phaser.Textures.DynamicTexture} The Texture that was saved. + */ + saveTexture: function (key) + { + var texture = this.texture; + + texture.key = key; + + if (texture.manager.addDynamicTexture(texture)) + { + this._saved = true; + } + + return texture; + }, + + /** + * Set the `renderMode` of this Render Texture. + * Set this to change how the Render Texture is rendered. + * + * - 'render' mode draws the contents of the Render Texture to each frame. + * - 'redraw' mode calls `render()` and redraws the texture every frame, + * but does not render itself. This is useful for updating textures + * for reuse by other objects. + * - 'all' mode calls `render()` then draws the texture to the frame. + * + * @method Phaser.GameObjects.RenderTexture#setRenderMode + * @since 4.0.0 + * @param {'render'|'redraw'|'all'} mode - The render mode to set. + * @param {boolean} [preserve=false] - Whether to call `preserve(true)` to preserve the current command buffer. + * @returns {this} This Render Texture instance. + */ + setRenderMode: function (mode, preserve) + { + this.renderMode = mode; + + if (preserve) + { + this.texture.preserve(true); + } + + return this; + }, + + /** + * Render the buffered drawing commands to this Dynamic Texture. + * You must do this in order to see anything drawn to it. + * + * @method Phaser.GameObjects.RenderTexture#render + * @since 4.0.0 + */ + render: function () + { + this.texture.render(); + + return this; + }, + + /** + * Fills this Render Texture with the given color. + * + * By default it will fill the entire texture, however you can set it to fill a specific + * rectangular area by using the x, y, width and height arguments. + * + * The color should be given in hex format, i.e. 0xff0000 for red, 0x00ff00 for green, etc. + * + * @method Phaser.GameObjects.RenderTexture#fill + * @since 3.2.0 + * + * @param {number} rgb - The color to fill this Render Texture with, such as 0xff0000 for red. + * @param {number} [alpha=1] - The alpha value used by the fill. + * @param {number} [x=0] - The left coordinate of the fill rectangle. + * @param {number} [y=0] - The top coordinate of the fill rectangle. + * @param {number} [width=this.width] - The width of the fill rectangle. + * @param {number} [height=this.height] - The height of the fill rectangle. + * + * @return {this} This Render Texture instance. + */ + fill: function (rgb, alpha, x, y, width, height) + { + this.texture.fill(rgb, alpha, x, y, width, height); + + return this; + }, + + /** + * Clears a portion or everything from this Render Texture by erasing it and resetting it back to + * a blank, transparent, texture. To clear an area, specify the `x`, `y`, `width` and `height`. + * + * @method Phaser.GameObjects.RenderTexture#clear + * @since 3.2.0 + * + * @param {number} [x=0] - The left coordinate of the fill rectangle. + * @param {number} [y=0] - The top coordinate of the fill rectangle. + * @param {number} [width=this.width] - The width of the fill rectangle. + * @param {number} [height=this.height] - The height of the fill rectangle. + * + * @return {this} This Render Texture instance. + */ + clear: function (x, y, width, height) + { + this.texture.clear(x, y, width, height); + + return this; + }, + + /** + * Takes the given texture key and frame and then stamps it at the given + * x and y coordinates. You can use the optional 'config' argument to provide + * lots more options about how the stamp is applied, including the alpha, + * tint, angle, scale and origin. + * + * By default, the frame will stamp on the x/y coordinates based on its center. + * + * If you wish to stamp from the top-left, set the config `originX` and + * `originY` properties both to zero. + * + * This method ignores the `camera` property of the Dynamic Texture. + * + * @method Phaser.GameObjects.RenderTexture#stamp + * @since 3.60.0 + * + * @param {string} key - The key of the texture to be used, as stored in the Texture Manager. + * @param {(string|number)} [frame] - The name or index of the frame within the Texture. Set to `null` to skip this argument if not required. + * @param {number} [x=0] - The x position to draw the frame at. + * @param {number} [y=0] - The y position to draw the frame at. + * @param {Phaser.Types.Textures.StampConfig} [config] - The stamp configuration object, allowing you to set the alpha, tint, angle, scale and origin of the stamp. + * + * @return {this} This Render Texture instance. + */ + stamp: function (key, frame, x, y, config) + { + this.texture.stamp(key, frame, x, y, config); + + return this; + }, + + /** + * Draws the given object, or an array of objects, to this Render Texture using a blend mode of ERASE. + * This has the effect of erasing any filled pixels present in the objects from this texture. + * + * This method uses the `draw` method internally, + * and the parameters behave the same way. + * + * @method Phaser.GameObjects.RenderTexture#erase + * @since 3.16.0 + * + * @param {any} entries - Any renderable Game Object, or Group, Container, Display List, Render Texture, Texture Frame, or an array of any of these. + * @param {number} [x=0] - The x position to draw the Frame at, or the offset applied to the object. + * @param {number} [y=0] - The y position to draw the Frame at, or the offset applied to the object. + * + * @return {this} This Render Texture instance. + */ + erase: function (entries, x, y) + { + this.texture.erase(entries, x, y); + + return this; + }, + + /** + * Draws the given object, or an array of objects, to this RenderTexture. + * + * It can accept any of the following: + * + * * Any renderable Game Object, such as a Sprite, Text, Graphics or TileSprite. + * * Tilemap Layers. + * * A Group. The contents of which will be iterated and drawn in turn. + * * A Container. The contents of which will be iterated fully, and drawn in turn. + * * A Scene Display List. Pass in `Scene.children` to draw the whole list. + * * Another Dynamic Texture, or a Render Texture. + * * A Texture Frame instance. + * * A string. This is used to look-up the texture from the Texture Manager. + * + * Note 1: You cannot draw a Render Texture to itself. + * + * Note 2: GameObjects will use the camera, while textures and frames will not. + * Textures and frames are drawn using the `stamp` method. + * + * If passing in a Group or Container it will only draw children that return `true` + * when their `willRender()` method is called. I.e. a Container with 10 children, + * 5 of which have `visible=false` will only draw the 5 visible ones. + * + * If passing in an array of Game Objects it will draw them all, regardless if + * they pass a `willRender` check or not. + * + * You can pass in a string in which case it will look for a texture in the Texture + * Manager matching that string, and draw the base frame. If you need to specify + * exactly which frame to draw then use the method `drawFrame` instead. + * + * You can pass in the `x` and `y` coordinates to draw the objects at. The use of + * the coordinates differ based on what objects are being drawn. If the object is + * a Group, Container or Display List, the coordinates are _added_ to the positions + * of the children. For all other types of object, the coordinates are exact. + * For textures and frames, the `x` and `y` values are the middle of the texture. + * + * The `alpha` and `tint` values are only used by Texture Frames. + * Game Objects use their own alpha and tint values when being drawn. + * + * @method Phaser.GameObjects.RenderTexture#draw + * @since 3.2.0 + * + * @param {any} entries - Any renderable Game Object, or Group, Container, Display List, other Render Texture, Texture Frame or an array of any of these. + * @param {number} [x=0] - The x position to draw the Frame at, or the offset applied to the object. + * @param {number} [y=0] - The y position to draw the Frame at, or the offset applied to the object. + * @param {number} [alpha=1] - The alpha value. Only used when drawing Texture Frames to this texture. Game Objects use their own alpha. + * @param {number} [tint=0xffffff] - The tint color value. Only used when drawing Texture Frames to this texture. Game Objects use their own tint. WebGL only. + * + * @return {this} This Render Texture instance. + */ + draw: function (entries, x, y, alpha, tint) + { + this.texture.draw(entries, x, y, alpha, tint); + + return this; + }, + + /** + * Draws the given object to this Render Texture. + * This allows you to draw the object as it appears in the game world, + * or with various parameter overrides in the config. + * + * @method Phaser.GameObjects.RenderTexture#capture + * @since 4.0.0 + * + * @param {Phaser.GameObjects.GameObject} entry - Any renderable GameObject. + * @param {Phaser.Types.Textures.CaptureConfig} config - The configuration object for the capture. + * + * @return {this} This Dynamic Texture instance. + */ + capture: function (entry, config) + { + this.texture.capture(entry, config); + + return this; + }, + + /** + * Takes the given Texture Frame and draws it to this Dynamic Texture as a fill pattern, + * i.e. in a grid-layout based on the frame dimensions. + * It uses a `TileSprite` internally to draw the frame repeatedly. + * + * Textures are referenced by their string-based keys, as stored in the Texture Manager. + * + * You can optionally provide a position, width, height, alpha and tint value to apply to + * the frames before they are drawn. The position controls the top-left where the repeating + * fill will start from. The width and height control the size of the filled area. + * + * The position can be negative if required, but the dimensions cannot. + * + * This method respects the camera settings of the Dynamic Texture. + * + * @method Phaser.GameObjects.RenderTexture#repeat + * @since 3.60.0 + * + * @param {string} key - The key of the texture to be used, as stored in the Texture Manager. + * @param {(string|number)} [frame] - The name or index of the frame within the Texture. Set to `null` to skip this argument if not required. + * @param {number} [x=0] - The x position to start drawing the frames from (can be negative to offset). + * @param {number} [y=0] - The y position to start drawing the frames from (can be negative to offset). + * @param {number} [width=this.width] - The width of the area to repeat the frame within. Defaults to the width of this Dynamic Texture. + * @param {number} [height=this.height] - The height of the area to repeat the frame within. Defaults to the height of this Dynamic Texture. + * @param {Phaser.Types.GameObjects.TileSprite.TileSpriteConfig} [config] - The configuration object for the TileSprite which repeats the texture, allowing you to set further properties on it. + * + * @return {this} This Render Texture instance. + */ + repeat: function (key, frame, x, y, width, height, config) + { + this.texture.repeat(key, frame, x, y, width, height, config); + + return this; + }, + + /** + * Sets the preserve flag for this Dynamic Texture. + * Ordinarily, after each render, the command buffer is cleared. + * When this flag is set to `true`, the command buffer is preserved between renders. + * This makes it possible to repeat the same drawing commands on each render. + * + * Make sure to call `clear()` at the start if you don't want to accumulate + * drawing detail over the top of itself. + * + * @method Phaser.GameObjects.RenderTexture#preserve + * @since 4.0.0 + * @param {boolean} preserve - Whether to preserve the command buffer after rendering. + * @returns {this} This Render Texture instance. + */ + preserve: function (preserve) + { + this.texture.preserve(preserve); + + return this; + }, + + /** + * Adds a callback to run during the render process. + * This callback runs as a step in the command buffer. + * It can be used to set up conditions for the next draw step. + * + * Note that this will only execute after `render()` is called. + * + * @method Phaser.GameObjects.RenderTexture#callback + * @since 4.0.0 + * @param {Function} callback - A callback function to run during the render process. + * @returns {this} This Render Texture instance. + */ + callback: function (callback) + { + this.texture.callback(callback); + + return this; + }, + + /** + * Takes a snapshot of the given area of this Render Texture. + * + * The snapshot is taken immediately, but the results are returned via the given callback. + * + * To capture the whole Render Texture see the `snapshot` method. + * To capture just a specific pixel, see the `snapshotPixel` method. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer + * into an ArrayBufferView. It then parses this, copying the contents to a temporary Canvas and finally + * creating an Image object from it, which is the image returned to the callback provided. + * + * All in all, this is a computationally expensive and blocking process, which gets more expensive + * the larger the resolution this Render Texture has, so please be careful how you employ this in your game. + * + * @method Phaser.GameObjects.RenderTexture#snapshotArea + * @since 3.19.0 + * + * @param {number} x - The x coordinate to grab from. + * @param {number} y - The y coordinate to grab from. + * @param {number} width - The width of the area to grab. + * @param {number} height - The height of the area to grab. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This Render Texture instance. + */ + snapshotArea: function (x, y, width, height, callback, type, encoderOptions) + { + this.texture.snapshotArea(x, y, width, height, callback, type, encoderOptions); + + return this; + }, + + /** + * Takes a snapshot of the whole of this Render Texture. + * + * The snapshot is taken immediately, but the results are returned via the given callback. + * + * To capture a portion of this Render Texture see the `snapshotArea` method. + * To capture just a specific pixel, see the `snapshotPixel` method. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer + * into an ArrayBufferView. It then parses this, copying the contents to a temporary Canvas and finally + * creating an Image object from it, which is the image returned to the callback provided. + * + * All in all, this is a computationally expensive and blocking process, which gets more expensive + * the larger the resolution this Render Texture has, so please be careful how you employ this in your game. + * + * @method Phaser.GameObjects.RenderTexture#snapshot + * @since 3.19.0 + * + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This Render Texture instance. + */ + snapshot: function (callback, type, encoderOptions) + { + return this.texture.snapshot(callback, type, encoderOptions); + }, + + /** + * Takes a snapshot of the given pixel from this Render Texture. + * + * The snapshot is taken immediately, but the results are returned via the given callback. + * + * To capture the whole Render Texture see the `snapshot` method. + * To capture a portion of this Render Texture see the `snapshotArea` method. + * + * Unlike the two other snapshot methods, this one will send your callback a `Color` object + * containing the color data for the requested pixel. It doesn't need to create an internal + * Canvas or Image object, so is a lot faster to execute, using less memory than the other snapshot methods. + * + * @method Phaser.GameObjects.RenderTexture#snapshotPixel + * @since 3.19.0 + * + * @param {number} x - The x coordinate of the pixel to get. + * @param {number} y - The y coordinate of the pixel to get. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot pixel data is extracted. + * + * @return {this} This Render Texture instance. + */ + snapshotPixel: function (x, y, callback) + { + return this.texture.snapshotPixel(x, y, callback); + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.RenderTexture#preDestroy + * @protected + * @since 3.9.0 + */ + preDestroy: function () + { + this.camera = null; + + if (!this._saved) + { + this.texture.destroy(); + } + } + +}); + +module.exports = RenderTexture; + + +/***/ }), + +/***/ 97272: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ImageCanvasRenderer = __webpack_require__(40652); +var RenderTextureRenderModes = __webpack_require__(58855); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.RenderTexture#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.RenderTexture} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var RenderTextureCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + var redraw = true; + var render = true; + if (src.renderMode === RenderTextureRenderModes.REDRAW) + { + render = false; + } + else if (src.renderMode === RenderTextureRenderModes.RENDER) + { + redraw = false; + } + + if (redraw) + { + src.render(); + } + + if (render) + { + ImageCanvasRenderer(renderer, src, camera, parentMatrix); + } +}; + +module.exports = RenderTextureCanvasRenderer; + + +/***/ }), + +/***/ 34495: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var RenderTexture = __webpack_require__(591); + +/** + * Creates a new Render Texture Game Object and returns it. + * + * Note: This method will only be available if the Render Texture Game Object has been built into Phaser. + * + * A Render Texture is a combination of Dynamic Texture and an Image Game Object, that uses the + * Dynamic Texture to display itself with. + * + * A Dynamic Texture is a special texture that allows you to draw textures, frames and most kind of + * Game Objects directly to it. + * + * You can take many complex objects and draw them to this one texture, which can then be used as the + * base texture for other Game Objects, such as Sprites. Should you then update this texture, all + * Game Objects using it will instantly be updated as well, reflecting the changes immediately. + * + * It's a powerful way to generate dynamic textures at run-time that are WebGL friendly and don't invoke + * expensive GPU uploads on each change. + * + * @method Phaser.GameObjects.GameObjectCreator#renderTexture + * @since 3.2.0 + * + * @param {Phaser.Types.GameObjects.RenderTexture.RenderTextureConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.RenderTexture} The Game Object that was created. + */ +GameObjectCreator.register('renderTexture', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var x = GetAdvancedValue(config, 'x', 0); + var y = GetAdvancedValue(config, 'y', 0); + var width = GetAdvancedValue(config, 'width', 32); + var height = GetAdvancedValue(config, 'height', 32); + + var renderTexture = new RenderTexture(this.scene, x, y, width, height); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, renderTexture, config); + + return renderTexture; +}); + + +/***/ }), + +/***/ 60505: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var RenderTexture = __webpack_require__(591); + +/** + * Creates a new Render Texture Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Render Texture Game Object has been built into Phaser. + * + * A Render Texture is a combination of Dynamic Texture and an Image Game Object, that uses the + * Dynamic Texture to display itself with. + * + * A Dynamic Texture is a special texture that allows you to draw textures, frames and most kind of + * Game Objects directly to it. + * + * You can take many complex objects and draw them to this one texture, which can then be used as the + * base texture for other Game Objects, such as Sprites. Should you then update this texture, all + * Game Objects using it will instantly be updated as well, reflecting the changes immediately. + * + * It's a powerful way to generate dynamic textures at run-time that are WebGL friendly and don't invoke + * expensive GPU uploads on each change. + * + * @method Phaser.GameObjects.GameObjectFactory#renderTexture + * @since 3.2.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {number} [width=32] - The width of the Render Texture. + * @param {number} [height=32] - The height of the Render Texture. + * + * @return {Phaser.GameObjects.RenderTexture} The Game Object that was created. + */ +GameObjectFactory.register('renderTexture', function (x, y, width, height) +{ + return this.displayList.add(new RenderTexture(this.scene, x, y, width, height)); +}); + + +/***/ }), + +/***/ 83999: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(53937); +} + +if (true) +{ + renderCanvas = __webpack_require__(97272); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 58855: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +module.exports = { + + RENDER: 'render', + REDRAW: 'redraw', + ALL: 'all' + +}; + + +/***/ }), + +/***/ 53937: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ImageWebGLRenderer = __webpack_require__(99517); +var RenderTextureRenderModes = __webpack_require__(58855); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.RenderTexture#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.RenderTexture} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var RenderTextureWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + if (src.isCurrentlyRendering) + { + return; + } + src.isCurrentlyRendering = true; + + var redraw = true; + var render = true; + if (src.renderMode === RenderTextureRenderModes.REDRAW) + { + render = false; + } + else if (src.renderMode === RenderTextureRenderModes.RENDER) + { + redraw = false; + } + + if (redraw) + { + src.render(); + } + + if (render) + { + ImageWebGLRenderer(renderer, src, drawingContext, parentMatrix); + } + + src.isCurrentlyRendering = false; +}; + +module.exports = RenderTextureWebGLRenderer; + + +/***/ }), + +/***/ 77757: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AnimationState = __webpack_require__(9674); +var DefaultRopeNodes = __webpack_require__(85760); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var RopeRender = __webpack_require__(38745); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Rope Game Object. + * + * The Rope object is WebGL only and does not have a Canvas counterpart. + * + * A Rope is a special kind of Game Object that has a texture is stretched along its entire length. + * + * Unlike a Sprite, it isn't restricted to using just a quad and can have as many vertices as you define + * when creating it. The vertices can be arranged in a horizontal or vertical strip and have their own + * color and alpha values as well. + * + * A Ropes origin is always 0.5 x 0.5 and cannot be changed. + * + * This object does not support trimmed textures from Texture Packer. + * Trimming may interfere with the vertex arrangement. + * + * @class Rope + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @webglOnly + * @since 3.23.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * @extends Phaser.GameObjects.Components.ScrollFactor + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {string} [texture] - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager. If not given, `__DEFAULT` is used. + * @param {(string|number|null)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * @param {(number|Phaser.Types.Math.Vector2Like[])} [points=2] - An array containing the vertices data for this Rope, or a number that indicates how many segments to split the texture frame into. If none is provided a simple quad is created. See `setPoints` to set this post-creation. + * @param {boolean} [horizontal=true] - Should the vertices of this Rope be aligned horizontally (`true`), or vertically (`false`)? + * @param {number[]} [colors] - An optional array containing the color data for this Rope. You should provide one color value per pair of vertices. + * @param {number[]} [alphas] - An optional array containing the alpha data for this Rope. You should provide one alpha value per pair of vertices. + */ +var Rope = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.Flip, + Components.Mask, + Components.RenderNodes, + Components.Size, + Components.Texture, + Components.Transform, + Components.Visible, + Components.ScrollFactor, + RopeRender + ], + + initialize: + + function Rope (scene, x, y, texture, frame, points, horizontal, colors, alphas) + { + if (texture === undefined) { texture = '__DEFAULT'; } + if (points === undefined) { points = 2; } + if (horizontal === undefined) { horizontal = true; } + + GameObject.call(this, scene, 'Rope'); + + /** + * The Animation State of this Rope. + * + * @name Phaser.GameObjects.Rope#anims + * @type {Phaser.Animations.AnimationState} + * @since 3.23.0 + */ + this.anims = new AnimationState(this); + + /** + * An array containing the points data for this Rope. + * + * Each point should be given as a Vector2Like object (i.e. a Vector2 or object with public x/y properties). + * + * The point coordinates are given in local space, where 0 x 0 is the start of the Rope strip. + * + * You can modify the contents of this array directly in real-time to create interesting effects. + * If you do so, be sure to call `setDirty` _after_ modifying this array, so that the vertices data is + * updated before the next render. Alternatively, you can use the `setPoints` method instead. + * + * Should you need to change the _size_ of this array, then you should always use the `setPoints` method. + * + * @name Phaser.GameObjects.Rope#points + * @type {Phaser.Types.Math.Vector2Like[]} + * @since 3.23.0 + */ + this.points = points; + + /** + * An array containing the vertices data for this Rope. + * + * This data is calculated automatically in the `updateVertices` method, based on the points provided. + * + * @name Phaser.GameObjects.Rope#vertices + * @type {Float32Array} + * @since 3.23.0 + */ + this.vertices; + + /** + * An array containing the uv data for this Rope. + * + * This data is calculated automatically in the `setPoints` method, based on the points provided. + * + * @name Phaser.GameObjects.Rope#uv + * @type {Float32Array} + * @since 3.23.0 + */ + this.uv; + + /** + * An array containing the color data for this Rope. + * + * Colors should be given as numeric RGB values, such as 0xff0000. + * You should provide _two_ color values for every point in the Rope, one for the top and one for the bottom of each quad. + * + * You can modify the contents of this array directly in real-time, however, should you need to change the _size_ + * of the array, then you should use the `setColors` method instead. + * + * @name Phaser.GameObjects.Rope#colors + * @type {Uint32Array} + * @since 3.23.0 + */ + this.colors; + + /** + * An array containing the alpha data for this Rope. + * + * Alphas should be given as float values, such as 0.5. + * You should provide _two_ alpha values for every point in the Rope, one for the top and one for the bottom of each quad. + * + * You can modify the contents of this array directly in real-time, however, should you need to change the _size_ + * of the array, then you should use the `setAlphas` method instead. + * + * @name Phaser.GameObjects.Rope#alphas + * @type {Float32Array} + * @since 3.23.0 + */ + this.alphas; + + /** + * The tint fill mode. + * + * `false` = An additive tint (the default), where vertices colors are blended with the texture. + * `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha. + * + * @name Phaser.GameObjects.Rope#tintFill + * @type {boolean} + * @since 3.23.0 + */ + this.tintFill = (texture === '__DEFAULT') ? true : false; + + /** + * If the Rope is marked as `dirty` it will automatically recalculate its vertices + * the next time it renders. You can also force this by calling `updateVertices`. + * + * @name Phaser.GameObjects.Rope#dirty + * @type {boolean} + * @since 3.23.0 + */ + this.dirty = false; + + /** + * Are the Rope vertices aligned horizontally, in a strip, or vertically, in a column? + * + * This property is set during instantiation and cannot be changed directly. + * See the `setVertical` and `setHorizontal` methods. + * + * @name Phaser.GameObjects.Rope#horizontal + * @type {boolean} + * @readonly + * @since 3.23.0 + */ + this.horizontal = horizontal; + + /** + * The horizontally flipped state of the Game Object. + * + * A Game Object that is flipped horizontally will render inversed on the horizontal axis. + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @name Phaser.GameObjects.Rope#_flipX + * @type {boolean} + * @default false + * @private + * @since 3.23.0 + */ + this._flipX = false; + + /** + * The vertically flipped state of the Game Object. + * + * A Game Object that is flipped vertically will render inversed on the vertical axis (i.e. upside down) + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @name Phaser.GameObjects.Rope#_flipY + * @type {boolean} + * @default false + * @private + * @since 3.23.0 + */ + this._flipY = false; + + /** + * Internal Vector2 used for vertices updates. + * + * @name Phaser.GameObjects.Rope#_perp + * @type {Phaser.Math.Vector2} + * @private + * @since 3.23.0 + */ + this._perp = new Vector2(); + + /** + * You can optionally choose to render the vertices of this Rope to a Graphics instance. + * + * Achieve this by setting the `debugCallback` and the `debugGraphic` properties. + * + * You can do this in a single call via the `Rope.setDebug` method, which will use the + * built-in debug function. You can also set it to your own callback. The callback + * will be invoked _once per render_ and sent the following parameters: + * + * `debugCallback(src, meshLength, verts)` + * + * `src` is the Rope instance being debugged. + * `meshLength` is the number of mesh vertices in total. + * `verts` is an array of the translated vertex coordinates. + * + * To disable rendering, set this property back to `null`. + * + * @name Phaser.GameObjects.Rope#debugCallback + * @type {function} + * @since 3.23.0 + */ + this.debugCallback = null; + + /** + * The Graphics instance that the debug vertices will be drawn to, if `setDebug` has + * been called. + * + * @name Phaser.GameObjects.Rope#debugGraphic + * @type {Phaser.GameObjects.Graphics} + * @since 3.23.0 + */ + this.debugGraphic = null; + + this.setTexture(texture, frame); + this.setPosition(x, y); + this.setSizeToFrame(); + this.initRenderNodes(this._defaultRenderNodesMap); + + if (Array.isArray(points)) + { + this.resizeArrays(points.length); + } + + this.setPoints(points, colors, alphas); + + this.updateVertices(); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Rope#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultRopeNodes; + } + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + /** + * The Rope update loop. + * + * @method Phaser.GameObjects.Rope#preUpdate + * @protected + * @since 3.23.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + preUpdate: function (time, delta) + { + var prevFrame = this.anims.currentFrame; + + this.anims.update(time, delta); + + if (this.anims.currentFrame !== prevFrame) + { + this.updateUVs(); + this.updateVertices(); + } + }, + + /** + * Start playing the given animation. + * + * @method Phaser.GameObjects.Rope#play + * @since 3.23.0 + * + * @param {string} key - The string-based key of the animation to play. + * @param {boolean} [ignoreIfPlaying=false] - If an animation is already playing then ignore this call. + * @param {number} [startFrame=0] - Optionally start the animation playing from this frame index. + * + * @return {this} This Game Object. + */ + play: function (key, ignoreIfPlaying, startFrame) + { + this.anims.play(key, ignoreIfPlaying, startFrame); + + return this; + }, + + /** + * Flags this Rope as being dirty. A dirty rope will recalculate all of its vertices data + * the _next_ time it renders. You should set this rope as dirty if you update the points + * array directly. + * + * @method Phaser.GameObjects.Rope#setDirty + * @since 3.23.0 + * + * @return {this} This Game Object instance. + */ + setDirty: function () + { + this.dirty = true; + + return this; + }, + + /** + * Sets the alignment of the points in this Rope to be horizontal, in a strip format. + * + * Calling this method will reset this Rope. The current points, vertices, colors and alpha + * values will be reset to thoes values given as parameters. + * + * @method Phaser.GameObjects.Rope#setHorizontal + * @since 3.23.0 + * + * @param {(number|Phaser.Types.Math.Vector2Like[])} [points] - An array containing the vertices data for this Rope, or a number that indicates how many segments to split the texture frame into. If none is provided the current points length is used. + * @param {(number|number[])} [colors] - Either a single color value, or an array of values. + * @param {(number|number[])} [alphas] - Either a single alpha value, or an array of values. + * + * @return {this} This Game Object instance. + */ + setHorizontal: function (points, colors, alphas) + { + if (points === undefined) { points = this.points.length; } + + if (this.horizontal) + { + return this; + } + + this.horizontal = true; + + return this.setPoints(points, colors, alphas); + }, + + /** + * Sets the alignment of the points in this Rope to be vertical, in a column format. + * + * Calling this method will reset this Rope. The current points, vertices, colors and alpha + * values will be reset to thoes values given as parameters. + * + * @method Phaser.GameObjects.Rope#setVertical + * @since 3.23.0 + * + * @param {(number|Phaser.Types.Math.Vector2Like[])} [points] - An array containing the vertices data for this Rope, or a number that indicates how many segments to split the texture frame into. If none is provided the current points length is used. + * @param {(number|number[])} [colors] - Either a single color value, or an array of values. + * @param {(number|number[])} [alphas] - Either a single alpha value, or an array of values. + * + * @return {this} This Game Object instance. + */ + setVertical: function (points, colors, alphas) + { + if (points === undefined) { points = this.points.length; } + + if (!this.horizontal) + { + return this; + } + + this.horizontal = false; + + return this.setPoints(points, colors, alphas); + }, + + /** + * Sets the tint fill mode. + * + * Mode 0 (`false`) is an additive tint, the default, which blends the vertices colors with the texture. + * This mode respects the texture alpha. + * + * Mode 1 (`true`) is a fill tint. Unlike an additive tint, a fill-tint literally replaces the pixel colors + * from the texture with those in the tint. You can use this for effects such as making a player flash 'white' + * if hit by something. This mode respects the texture alpha. + * + * See the `setColors` method for details of how to color each of the vertices. + * + * @method Phaser.GameObjects.Rope#setTintFill + * @webglOnly + * @since 3.23.0 + * + * @param {boolean} [value=false] - Set to `false` for an Additive tint or `true` fill tint with alpha. + * + * @return {this} This Game Object instance. + */ + setTintFill: function (value) + { + if (value === undefined) { value = false; } + + this.tintFill = value; + + return this; + }, + + /** + * Set the alpha values used by the Rope during rendering. + * + * You can provide the values in a number of ways: + * + * 1) One single numeric value: `setAlphas(0.5)` - This will set a single alpha for the whole Rope. + * 2) Two numeric value: `setAlphas(1, 0.5)` - This will set a 'top' and 'bottom' alpha value across the whole Rope. + * 3) An array of values: `setAlphas([ 1, 0.5, 0.2 ])` + * + * If you provide an array of values and the array has exactly the same number of values as `points` in the Rope, it + * will use each alpha value per rope segment. + * + * If the provided array has a different number of values than `points` then it will use the values in order, from + * the first Rope segment and on, until it runs out of values. This allows you to control the alpha values at all + * vertices in the Rope. + * + * Note this method is called `setAlphas` (plural) and not `setAlpha`. + * + * @method Phaser.GameObjects.Rope#setAlphas + * @since 3.23.0 + * + * @param {(number|number[])} [alphas] - Either a single alpha value, or an array of values. If nothing is provided alpha is reset to 1. + * @param {number} [bottomAlpha] - An optional bottom alpha value. See the method description for details. + * + * @return {this} This Game Object instance. + */ + setAlphas: function (alphas, bottomAlpha) + { + var total = this.points.length; + + if (total < 1) + { + return this; + } + + var currentAlphas = this.alphas; + + if (alphas === undefined) + { + alphas = [ 1 ]; + } + else if (!Array.isArray(alphas) && bottomAlpha === undefined) + { + alphas = [ alphas ]; + } + + var i; + var index = 0; + + if (bottomAlpha !== undefined) + { + // Top / Bottom alpha pair + for (i = 0; i < total; i++) + { + index = i * 2; + + currentAlphas[index] = alphas; + currentAlphas[index + 1] = bottomAlpha; + } + } + else if (alphas.length === total) + { + // If there are exactly the same number of alphas as points, we'll combine the alphas + for (i = 0; i < total; i++) + { + index = i * 2; + + currentAlphas[index] = alphas[i]; + currentAlphas[index + 1] = alphas[i]; + } + } + else + { + var prevAlpha = alphas[0]; + + for (i = 0; i < total; i++) + { + index = i * 2; + + if (alphas.length > index) + { + prevAlpha = alphas[index]; + } + + currentAlphas[index] = prevAlpha; + + if (alphas.length > index + 1) + { + prevAlpha = alphas[index + 1]; + } + + currentAlphas[index + 1] = prevAlpha; + } + } + + return this; + + }, + + /** + * Set the color values used by the Rope during rendering. + * + * Colors are used to control the level of tint applied across the Rope texture. + * + * You can provide the values in a number of ways: + * + * * One single numeric value: `setColors(0xff0000)` - This will set a single color tint for the whole Rope. + * * An array of values: `setColors([ 0xff0000, 0x00ff00, 0x0000ff ])` + * + * If you provide an array of values and the array has exactly the same number of values as `points` in the Rope, it + * will use each color per rope segment. + * + * If the provided array has a different number of values than `points` then it will use the values in order, from + * the first Rope segment and on, until it runs out of values. This allows you to control the color values at all + * vertices in the Rope. + * + * @method Phaser.GameObjects.Rope#setColors + * @since 3.23.0 + * + * @param {(number|number[])} [colors] - Either a single color value, or an array of values. If nothing is provided color is reset to 0xffffff. + * + * @return {this} This Game Object instance. + */ + setColors: function (colors) + { + var total = this.points.length; + + if (total < 1) + { + return this; + } + + var currentColors = this.colors; + + if (colors === undefined) + { + colors = [ 0xffffff ]; + } + else if (!Array.isArray(colors)) + { + colors = [ colors ]; + } + + var i; + var index = 0; + + if (colors.length === total) + { + // If there are exactly the same number of colors as points, we'll combine the colors + for (i = 0; i < total; i++) + { + index = i * 2; + + currentColors[index] = colors[i]; + currentColors[index + 1] = colors[i]; + } + } + else + { + var prevColor = colors[0]; + + for (i = 0; i < total; i++) + { + index = i * 2; + + if (colors.length > index) + { + prevColor = colors[index]; + } + + currentColors[index] = prevColor; + + if (colors.length > index + 1) + { + prevColor = colors[index + 1]; + } + + currentColors[index + 1] = prevColor; + } + } + + return this; + }, + + /** + * Sets the points used by this Rope. + * + * The points should be provided as an array of Vector2, or vector2-like objects (i.e. those with public x/y properties). + * + * Each point corresponds to one segment of the Rope. The more points in the array, the more segments the rope has. + * + * Point coordinates are given in local-space, not world-space, and are directly related to the size of the texture + * this Rope object is using. + * + * For example, a Rope using a 512 px wide texture, split into 4 segments (128px each) would use the following points: + * + * ```javascript + * rope.setPoints([ + * { x: 0, y: 0 }, + * { x: 128, y: 0 }, + * { x: 256, y: 0 }, + * { x: 384, y: 0 } + * ]); + * ``` + * + * Or, you can provide an integer to do the same thing: + * + * ```javascript + * rope.setPoints(4); + * ``` + * + * Which will divide the Rope into 4 equally sized segments based on the frame width. + * + * Note that calling this method with a different number of points than the Rope has currently will + * _reset_ the color and alpha values, unless you provide them as arguments to this method. + * + * @method Phaser.GameObjects.Rope#setPoints + * @since 3.23.0 + * + * @param {(number|Phaser.Types.Math.Vector2Like[])} [points=2] - An array containing the vertices data for this Rope, or a number that indicates how many segments to split the texture frame into. If none is provided a simple quad is created. + * @param {(number|number[])} [colors] - Either a single color value, or an array of values. + * @param {(number|number[])} [alphas] - Either a single alpha value, or an array of values. + * + * @return {this} This Game Object instance. + */ + setPoints: function (points, colors, alphas) + { + if (points === undefined) { points = 2; } + + if (typeof points === 'number') + { + // Generate an array based on the points + var segments = points; + + if (segments < 2) + { + segments = 2; + } + + points = []; + + var s; + var frameSegment; + var offset; + + if (this.horizontal) + { + offset = -(this.frame.halfWidth); + frameSegment = this.frame.width / (segments - 1); + + for (s = 0; s < segments; s++) + { + points.push({ x: offset + s * frameSegment, y: 0 }); + } + } + else + { + offset = -(this.frame.halfHeight); + frameSegment = this.frame.height / (segments - 1); + + for (s = 0; s < segments; s++) + { + points.push({ x: 0, y: offset + s * frameSegment }); + } + } + } + + var total = points.length; + var currentTotal = this.points.length; + + if (total < 1) + { + console.warn('Rope: Not enough points given'); + + return this; + } + else if (total === 1) + { + points.unshift({ x: 0, y: 0 }); + total++; + } + + if (currentTotal !== total) + { + this.resizeArrays(total); + } + + this.dirty = true; + + this.points = points; + + this.updateUVs(); + + if (colors !== undefined && colors !== null) + { + this.setColors(colors); + } + + if (alphas !== undefined && alphas !== null) + { + this.setAlphas(alphas); + } + + return this; + }, + + /** + * Updates all of the UVs based on the Rope.points and `flipX` and `flipY` settings. + * + * @method Phaser.GameObjects.Rope#updateUVs + * @since 3.23.0 + * + * @return {this} This Game Object instance. + */ + updateUVs: function () + { + var currentUVs = this.uv; + var total = this.points.length; + + var u0 = this.frame.u0; + var v0 = this.frame.v0; + var u1 = this.frame.u1; + var v1 = this.frame.v1; + + var partH = (u1 - u0) / (total - 1); + var partV = (v1 - v0) / (total - 1); + + for (var i = 0; i < total; i++) + { + var index = i * 4; + + var uv0; + var uv1; + var uv2; + var uv3; + + if (this.horizontal) + { + if (this._flipX) + { + uv0 = u1 - (i * partH); + uv2 = u1 - (i * partH); + } + else + { + uv0 = u0 + (i * partH); + uv2 = u0 + (i * partH); + } + + if (this._flipY) + { + uv1 = v1; + uv3 = v0; + } + else + { + uv1 = v0; + uv3 = v1; + } + } + else + { + if (this._flipX) + { + uv0 = u0; + uv2 = u1; + } + else + { + uv0 = u1; + uv2 = u0; + } + + if (this._flipY) + { + uv1 = v1 - (i * partV); + uv3 = v1 - (i * partV); + } + else + { + uv1 = v0 + (i * partV); + uv3 = v0 + (i * partV); + } + } + + currentUVs[index + 0] = uv0; + currentUVs[index + 1] = uv1; + currentUVs[index + 2] = uv2; + currentUVs[index + 3] = uv3; + } + + return this; + }, + + /** + * Resizes all of the internal arrays: `vertices`, `uv`, `colors` and `alphas` to the new + * given Rope segment total. + * + * @method Phaser.GameObjects.Rope#resizeArrays + * @since 3.23.0 + * + * @param {number} newSize - The amount of segments to split the Rope in to. + * + * @return {this} This Game Object instance. + */ + resizeArrays: function (newSize) + { + var colors = this.colors; + var alphas = this.alphas; + + this.vertices = new Float32Array(newSize * 4); + this.uv = new Float32Array(newSize * 4); + + colors = new Uint32Array(newSize * 2); + alphas = new Float32Array(newSize * 2); + + for (var i = 0; i < newSize * 2; i++) + { + colors[i] = 0xffffff; + alphas[i] = 1; + } + + this.colors = colors; + this.alphas = alphas; + + // updateVertices during next render + this.dirty = true; + + return this; + }, + + /** + * Updates the vertices based on the Rope points. + * + * This method is called automatically during rendering if `Rope.dirty` is `true`, which is set + * by the `setPoints` and `setDirty` methods. You should flag the Rope as being dirty if you modify + * the Rope points directly. + * + * @method Phaser.GameObjects.Rope#updateVertices + * @since 3.23.0 + * + * @return {this} This Game Object instance. + */ + updateVertices: function () + { + var perp = this._perp; + var points = this.points; + var vertices = this.vertices; + + var total = points.length; + + this.dirty = false; + + if (total < 1) + { + return; + } + + var nextPoint; + var lastPoint = points[0]; + + var frameSize = (this.horizontal) ? this.frame.halfHeight : this.frame.halfWidth; + + for (var i = 0; i < total; i++) + { + var point = points[i]; + var index = i * 4; + + if (i < total - 1) + { + nextPoint = points[i + 1]; + } + else + { + nextPoint = point; + } + + perp.x = nextPoint.y - lastPoint.y; + perp.y = -(nextPoint.x - lastPoint.x); + + var perpLength = perp.length(); + + perp.x /= perpLength; + perp.y /= perpLength; + + perp.x *= frameSize; + perp.y *= frameSize; + + vertices[index] = point.x + perp.x; + vertices[index + 1] = point.y + perp.y; + vertices[index + 2] = point.x - perp.x; + vertices[index + 3] = point.y - perp.y; + + lastPoint = point; + } + + return this; + }, + + /** + * This method enables rendering of the Rope vertices to the given Graphics instance. + * + * If you enable this feature, you **must** call `Graphics.clear()` in your Scene `update`, + * otherwise the Graphics instance you provide to debug will fill-up with draw calls, + * eventually crashing the browser. This is not done automatically to allow you to debug + * draw multiple Rope objects to a single Graphics instance. + * + * The Rope class has a built-in debug rendering callback `Rope.renderDebugVerts`, however + * you can also provide your own callback to be used instead. Do this by setting the `callback` parameter. + * + * The callback is invoked _once per render_ and sent the following parameters: + * + * `callback(src, meshLength, verts)` + * + * `src` is the Rope instance being debugged. + * `meshLength` is the number of mesh vertices in total. + * `verts` is an array of the translated vertex coordinates. + * + * If using your own callback you do not have to provide a Graphics instance to this method. + * + * To disable debug rendering, to either your own callback or the built-in one, call this method + * with no arguments. + * + * @method Phaser.GameObjects.Rope#setDebug + * @since 3.23.0 + * + * @param {Phaser.GameObjects.Graphics} [graphic] - The Graphic instance to render to if using the built-in callback. + * @param {function} [callback] - The callback to invoke during debug render. Leave as undefined to use the built-in callback. + * + * @return {this} This Game Object instance. + */ + setDebug: function (graphic, callback) + { + this.debugGraphic = graphic; + + if (!graphic && !callback) + { + this.debugCallback = null; + } + else if (!callback) + { + this.debugCallback = this.renderDebugVerts; + } + else + { + this.debugCallback = callback; + } + + return this; + }, + + /** + * The built-in Rope vertices debug rendering method. + * + * See `Rope.setDebug` for more details. + * + * @method Phaser.GameObjects.Rope#renderDebugVerts + * @since 3.23.0 + * + * @param {Phaser.GameObjects.Rope} src - The Rope object being rendered. + * @param {number} meshLength - The number of vertices in the mesh. + * @param {number[]} verts - An array of translated vertex coordinates. + */ + renderDebugVerts: function (src, meshLength, verts) + { + var graphic = src.debugGraphic; + + var px0 = verts[0]; + var py0 = verts[1]; + var px1 = verts[2]; + var py1 = verts[3]; + + graphic.lineBetween(px0, py0, px1, py1); + + for (var i = 4; i < meshLength; i += 4) + { + var x0 = verts[i + 0]; + var y0 = verts[i + 1]; + var x1 = verts[i + 2]; + var y1 = verts[i + 3]; + + graphic.lineBetween(px0, py0, x0, y0); + graphic.lineBetween(px1, py1, x1, y1); + graphic.lineBetween(px1, py1, x0, y0); + graphic.lineBetween(x0, y0, x1, y1); + + px0 = x0; + py0 = y0; + px1 = x1; + py1 = y1; + } + }, + + /** + * Handles the pre-destroy step for the Rope, which removes the Animation component and typed arrays. + * + * @method Phaser.GameObjects.Rope#preDestroy + * @private + * @since 3.23.0 + */ + preDestroy: function () + { + this.anims.destroy(); + + this.anims = undefined; + + this.points = null; + this.vertices = null; + this.uv = null; + this.colors = null; + this.alphas = null; + + this.debugCallback = null; + this.debugGraphic = null; + }, + + /** + * The horizontally flipped state of the Game Object. + * + * A Game Object that is flipped horizontally will render inversed on the horizontal axis. + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @name Phaser.GameObjects.Rope#flipX + * @type {boolean} + * @default false + * @since 3.23.0 + */ + flipX: { + + get: function () + { + return this._flipX; + }, + + set: function (value) + { + this._flipX = value; + + return this.updateUVs(); + } + + }, + + /** + * The vertically flipped state of the Game Object. + * + * A Game Object that is flipped vertically will render inversed on the vertical axis (i.e. upside down) + * Flipping always takes place from the middle of the texture and does not impact the scale value. + * If this Game Object has a physics body, it will not change the body. This is a rendering toggle only. + * + * @name Phaser.GameObjects.Rope#flipY + * @type {boolean} + * @default false + * @since 3.23.0 + */ + flipY: { + + get: function () + { + return this._flipY; + }, + + set: function (value) + { + this._flipY = value; + + return this.updateUVs(); + } + + } + +}); + +module.exports = Rope; + + +/***/ }), + +/***/ 95262: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * This is a stub function for Rope.Render. There is no Canvas renderer for Rope objects. + * + * @method Phaser.GameObjects.Rope#renderCanvas + * @since 3.23.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Rope} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + */ +var RopeCanvasRenderer = function () +{ +}; + +module.exports = RopeCanvasRenderer; + + +/***/ }), + +/***/ 26209: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var GetValue = __webpack_require__(35154); +var Rope = __webpack_require__(77757); + +/** + * Creates a new Rope Game Object and returns it. + * + * Note: This method will only be available if the Rope Game Object and WebGL support have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#rope + * @since 3.23.0 + * + * @param {Phaser.Types.GameObjects.Rope.RopeConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Rope} The Game Object that was created. + */ +GameObjectCreator.register('rope', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var frame = GetAdvancedValue(config, 'frame', null); + var horizontal = GetAdvancedValue(config, 'horizontal', true); + var points = GetValue(config, 'points', undefined); + var colors = GetValue(config, 'colors', undefined); + var alphas = GetValue(config, 'alphas', undefined); + + var rope = new Rope(this.scene, 0, 0, key, frame, points, horizontal, colors, alphas); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, rope, config); + + return rope; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 96819: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rope = __webpack_require__(77757); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Rope Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Rope Game Object and WebGL support have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#rope + * @webglOnly + * @since 3.23.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * @param {Phaser.Types.Math.Vector2Like[]} [points] - An array containing the vertices data for this Rope. If none is provided a simple quad is created. See `setPoints` to set this post-creation. + * @param {boolean} [horizontal=true] - Should the vertices of this Rope be aligned horizontally (`true`), or vertically (`false`)? + * @param {number[]} [colors] - An optional array containing the color data for this Rope. You should provide one color value per pair of vertices. + * @param {number[]} [alphas] - An optional array containing the alpha data for this Rope. You should provide one alpha value per pair of vertices. + * + * @return {Phaser.GameObjects.Rope} The Game Object that was created. + */ +if (true) +{ + GameObjectFactory.register('rope', function (x, y, texture, frame, points, horizontal, colors, alphas) + { + return this.displayList.add(new Rope(this.scene, x, y, texture, frame, points, horizontal, colors, alphas)); + }); +} + + +/***/ }), + +/***/ 38745: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(20439); +} + +if (true) +{ + renderCanvas = __webpack_require__(95262); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 20439: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); + +var renderOptions = { + multiTexturing: false, + smoothPixelArt: false +}; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Rope#renderWebGL + * @since 3.23.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Rope} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var RopeWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + if (src.dirty) + { + src.updateVertices(); + } + + // Get smooth pixel art option. + var smoothPixelArt; + var srcTexture = src.texture; + if (srcTexture && srcTexture.smoothPixelArt !== null) + { + smoothPixelArt = srcTexture.smoothPixelArt; + } + else + { + smoothPixelArt = src.scene.sys.game.config.smoothPixelArt; + } + renderOptions.smoothPixelArt = smoothPixelArt; + + (src.customRenderNodes.BatchHandler || src.defaultRenderNodes.BatchHandler).batchStrip( + drawingContext, + src, + calcMatrix, + src.texture.source[0].glTexture, + src.vertices, + src.uv, + src.colors, + src.alphas, + src.alpha, + src.tintFill, + renderOptions, + src.debugCallback + ); +}; + +module.exports = RopeWebGLRenderer; + + +/***/ }), + +/***/ 20071: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Camera = __webpack_require__(71911); +var Vector2 = __webpack_require__(26099); +var ShaderQuad = __webpack_require__(55403); +var DrawingContext = __webpack_require__(87774); +var Class = __webpack_require__(83419); +var GetFastValue = __webpack_require__(95540); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var ShaderRender = __webpack_require__(25479); + +/** + * @classdesc + * A Shader Game Object. + * + * This Game Object allows you to easily add a quad with its own shader + * into the display list, and manipulate it as you would any other Game Object, + * including scaling, rotating, positioning and adding to Containers. + * The Shader can be made interactive and used for input events. + * It can also be used in filters to create visually stunning effects. + * + * It works by creating a custom RenderNode which runs a custom shader program + * to draw a quad. The shader program can be loaded from the Shader Cache, + * or provided in-line as strings. + * + * Please see the Phaser 3 Examples GitHub repo for several examples + * of loading and creating shaders dynamically. + * + * Due to the way in which they work, you cannot directly change the alpha + * of a Shader. It should be handled via uniforms in the shader code itself. + * + * By default, a Shader has a uniform called `uProjectionMatrix` + * which is set automatically. + * You can control additional uniforms using the `setupUniforms` method + * in the Shader configuration object, which runs every time the shader renders. + * + * Shaders are stand-alone renders: they finish any current render batch + * and run once by themselves. As this costs a draw call, you should use them sparingly. + * If you need to have a fully batched custom shader, then please look at using + * a custom RenderNode instead. However, for background or special masking effects, + * they are extremely effective. + * + * Note: be careful when using texture coordinates in shader code. + * The built-in variable `gl_FragCoord` and the default uniform `outTexCoord` + * both use WebGL coordinates, which are `0,0` in the bottom-left. + * Additionally, `gl_FragCoord` says it's in "window relative" coordinates. + * But this is actually relative to the framebuffer size. + * + * @example + * // Loading a shader from the cache (good for simple shaders) + * function preload () + * { + * this.load.glsl('fire', 'shaders/fire.glsl.js'); + * } + * + * function create () + * { + * this.add.shader('fire', 400, 300, 512, 512); + * } + * + * @example + * // Using a configuration object (good for more control) + * function create () + * { + * this.add.shader({ + * fragmentKey: 'fire', // This will be overridden by fragmentSource + * fragmentSource: '// your fragment shader source', + * setupUniforms: (setUniform, drawingContext) => { + * setUniform('time', this.game.loop.getDuration()); + * } + * }, 400, 300, 512, 512); + * } + * + * @class Shader + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.17.0 + * + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. + * @param {string|Phaser.Types.GameObjects.Shader.ShaderQuadConfig} config - The configuration object this Shader will use. It can also be a key that corresponds to a shader in the shader cache, which will be used as `fragmentKey` in a new config object. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the Game Object. + * @param {number} [height=128] - The height of the Game Object. + * @param {string[]|Phaser.Textures.Texture[]} [textures] - The textures that the shader uses, if any. If you intend to define the textures later, use `'__DEFAULT'` as a placeholder, to avoid initialization errors. + */ +var Shader = new Class({ + Extends: GameObject, + + Mixins: [ + Components.BlendMode, + Components.ComputedSize, + Components.Depth, + Components.GetBounds, + Components.Origin, + Components.ScrollFactor, + Components.Transform, + Components.Visible, + ShaderRender + ], + + initialize: function Shader (scene, config, x, y, width, height, textures) + { + if (config === undefined) { config = {}; } + if (typeof config === 'string') + { + config = { fragmentKey: config }; + } + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 128; } + if (height === undefined) { height = 128; } + + GameObject.call(this, scene, 'Shader'); + + var renderer = scene.sys.renderer; + + /** + * The textures that the shader uses. + * These will be assigned to texture units 0 to N when the shader is + * rendered, where N is `textures.length - 1`. + * + * @name Phaser.GameObjects.Shader#textures + * @type {Phaser.Textures.Texture[]} + * @since 4.0.0 + */ + this.textures = []; + + /** + * The underlying RenderNode object that the shader uses to render with. + * + * @name Phaser.GameObjects.Shader#renderNode + * @type {Phaser.Renderer.WebGL.RenderNodes.ShaderQuad} + * @since 4.0.0 + */ + this.renderNode = new ShaderQuad(renderer.renderNodes, config); + + this.setupUniforms = GetFastValue(config, 'setupUniforms', function () {}); + + if (config.updateShaderConfig) + { + this.renderNode.updateShaderConfig = config.updateShaderConfig; + } + + /** + * The drawing context containing the framebuffer and texture that the shader is rendered to. + * This is only set if the shader is rendering to a texture. + * + * @name Phaser.GameObjects.Shader#drawingContext + * @type {?Phaser.Renderer.WebGL.DrawingContext} + * @since 4.0.0 + */ + this.drawingContext = null; + + /** + * A reference to the WebGLTextureWrapper this Shader is rendering to. + * This property is only set if you have called `Shader.setRenderToTexture`. + * + * @name Phaser.GameObjects.Shader#glTexture + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @since 3.19.0 + */ + this.glTexture = null; + + /** + * A flag that indicates if this Shader has been set to render to a texture instead of the display list. + * + * This property is `true` if you have called `Shader.setRenderToTexture`, otherwise it's `false`. + * + * A Shader that is rendering to a texture _does not_ appear on the display list. + * + * @name Phaser.GameObjects.Shader#renderToTexture + * @type {boolean} + * @readonly + * @since 3.19.0 + */ + this.renderToTexture = false; + + /** + * A reference to the Phaser.Textures.Texture that has been stored in the Texture Manager for this Shader. + * + * This property is only set if you have called `Shader.setRenderToTexture` with a key, otherwise it is `null`. + * + * @name Phaser.GameObjects.Shader#texture + * @type {Phaser.Textures.Texture} + * @since 3.19.0 + */ + this.texture = null; + + /** + * The top-left texture coordinate of the shader. + * This is set to 0,1 by default. It uses WebGL texture coordinates. + * + * @name Phaser.GameObjects.Shader#textureCoordinateTopLeft + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + */ + this.textureCoordinateTopLeft = new Vector2(0, 1); + + /** + * The top-right texture coordinate of the shader. + * This is set to 1,1 by default. It uses WebGL texture coordinates. + * + * @name Phaser.GameObjects.Shader#textureCoordinateTopRight + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + */ + this.textureCoordinateTopRight = new Vector2(1, 1); + + /** + * The bottom-left texture coordinate of the shader. + * This is set to 0,0 by default. It uses WebGL texture coordinates. + * + * @name Phaser.GameObjects.Shader#textureCoordinateBottomLeft + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + */ + this.textureCoordinateBottomLeft = new Vector2(0, 0); + + /** + * The bottom-right texture coordinate of the shader. + * This is set to 1,0 by default. It uses WebGL texture coordinates. + * + * @name Phaser.GameObjects.Shader#textureCoordinateBottomRight + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + */ + this.textureCoordinateBottomRight = new Vector2(1, 0); + + this.setTextures(textures); + this.setPosition(x, y); + this.setSize(width, height); + this.setOrigin(0.5, 0.5); + }, + + /** + * Returns the current value of a uniform from the render node. + * This value is actually copied to all shaders that use it. + * Modifications to non-primitive values such as arrays and objects + * will modify the original. + * + * It's generally better to use the `setupUniforms` function in the + * shader configuration object to set the uniform values. + * This method is provided in the spirit of reading back the values. + * + * @method Phaser.GameObjects.Shader#getUniform + * @since 4.0.0 + * @param {string} name - The name of the uniform to get. + * @return {any} The value of the uniform. + */ + getUniform: function (name) + { + return this.renderNode.programManager.uniforms[name]; + }, + + /** + * Set the textures that the shader uses. + * + * Some shaders don't use any textures. Some may use one or more. + * The textures are assigned to texture units 0 to N when the shader is rendered, + * where N is `textures.length - 1`. + * You must set the uniforms in your shader to match these texture units. + * + * Calling this method will replace the existing textures array with the new one. + * + * @example + * // In the shader source, use the `sampler2D` type. + * sampler2D uMainSampler; + * sampler2D uNormalSampler; + * + * // When creating the shader, set the textures. + * var shader = this.add.shader({ + * fragmentKey: 'myShader', + * setupUniforms: (setUniform) => { + * // In the `setupUniforms` function, set the texture to its array position. + * setUniform('uMainSampler', 0); + * setUniform('uNormalSampler', 1); + * } + * }, x, y, width, height, ['metal', 'normal']); + * + * @method Phaser.GameObjects.Shader#setTextures + * @since 4.0.0 + * @param {string[]|Phaser.Textures.Texture[]} [textures] - The textures that the shader uses. + */ + setTextures: function (textures) + { + if (textures === undefined) { textures = []; } + + this.textures.length = 0; + + for (var i = 0; i < textures.length; i++) + { + var texture = textures[i]; + if (typeof texture === 'string') + { + texture = this.scene.textures.get(texture); + } + this.textures.push(texture); + } + + return this; + }, + + /** + * Changes this Shader so instead of rendering to the display list + * it renders to a WebGL Framebuffer and Texture instead. + * This allows you to use the output of this shader as a texture. + * + * After calling this method the following properties are populated: + * - `Shader.drawingContext` + * - `Shader.glTexture` + * + * Additionally, you can provide a key to this method. + * Doing so will create a Phaser Texture from this Shader, + * store it in `Shader.texture`, + * and save it into the Texture Manager, allowing you to then use it for + * any texture-based Game Object, such as a Sprite or Image: + * + * ```javascript + * var shader = this.add.shader('myShader', x, y, width, height); + * + * shader.setRenderToTexture('doodle'); + * + * this.add.image(400, 300, 'doodle'); + * ``` + * + * Note that it stores an active reference to this Shader. That means as this shader updates, + * so does the texture and any object using it to render with. Also, if you destroy this + * shader, be sure to clear any objects that may have been using it as a texture too. + * + * By default it will create a single base texture. You can add frames to the texture + * by using the `Texture.add` method. After doing this, you can then allow Game Objects + * to use a specific frame from a Render Texture. + * + * If you want to update a texture only sporadically, don't use this method. + * Instead, use a DynamicTexture: + * + * ```javascript + * var shader = this.add.shader('myShader', x, y, width, height); + * + * var dynamic = this.textures.addDynamicTexture('myTexture', shader.width, shader.height); + * + * // To update the texture: + * dynamic.clear().draw(shader).render(); + * ``` + * + * @method Phaser.GameObjects.Shader#setRenderToTexture + * @since 3.19.0 + * + * @param {string} [key] - The unique key to store the texture as within the global Texture Manager. + * + * @return {this} This Shader instance. + */ + setRenderToTexture: function (key) + { + if (this.renderToTexture) + { + return this; + } + + var width = this.width; + var height = this.height; + var renderer = this.scene.sys.renderer; + var scene = this.scene; + + var camera = new Camera(0, 0, width, height).setScene(scene.game.scene.systemScene, false); + + this.drawingContext = new DrawingContext(renderer, { + width: width, + height: height, + camera: camera + }); + + this.glTexture = this.drawingContext.texture; + + if (key) + { + this.texture = scene.sys.textures.addGLTexture(key, this.glTexture); + } + + this.renderToTexture = true; + + // Render at least once, so our texture isn't blank on the first update + this.renderWebGLStep(renderer, this, this.drawingContext); + + return this; + }, + + /** + * The function which sets uniforms for the shader. + * This is called automatically during rendering. + * It is set from the `config` object passed in the constructor. + * You should use this function to set any uniform values you need for your shader to run. + * + * You can set this function directly after object creation, + * but it's recommended to use the `config` object + * to keep your logic encapsulated. + * + * The function is invoked with two arguments: `setUniform` and `drawingContext`. + * `setUniform` is a function that takes two arguments: a string (the name of the uniform) and a value. + * Ensure that the value matches the expected type in the shader. + * You don't need to be too precise, as the system will convert + * e.g. Array and Float32Array types as needed. + * To set an array in a shader, append `[0]` to the uniform name. + * `drawingContext` is a reference to the current drawing context, + * which may be useful if you need to query the camera or similar. + * + * Note that `uProjectionMatrix`is set for you automatically. + * + * @method Phaser.GameObjects.Shader#setupUniforms + * @since 4.0.0 + * @param {function} setUniform - The function which sets uniforms. `(name: string, value: any) => void`. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - A reference to the current drawing context. + */ + setupUniforms: function (setUniform, drawingContext) + { + // NOOP + }, + + /** + * A NOOP method so you can pass a Shader to a Container. + * Calling this method will do nothing. It is intentionally empty. + * + * @method Phaser.GameObjects.Shader#setAlpha + * @private + * @since 3.17.0 + * @return {this} This Shader instance. + */ + setAlpha: function () + { + return this; + }, + + /** + * Set the texture coordinates of the shader. + * These values are used to provide texture mapping to the shader, + * and are commonly used to drive generative output. + * + * By default, the shader uses the whole texture, the range 0-1. + * The coordinates are in WebGL texture space, which is 0,0 in the bottom-left. + * This method allows you to specify a region of the texture to use, + * or even go outside the 0-1 bounds. + * This can be useful if you want to use a single frame from a texture, + * repeat the shader's texture, use a larger numeric range, + * or distort the shader. + * + * Note that a quad is made of two triangles, divided by the diagonal + * from the top-left to the bottom-right. This means that some permutations + * of coordinates may affect just one or the other triangle. + * This can cause abrupt warping along the diagonal. + * Keep an eye on your output. Rectangles and parallelograms are safe bets. + * So are rotation and scaling transforms. Moving a single point is risky. + * + * Call this method with no arguments to reset the shader to use the whole texture. + * + * @method Phaser.GameObjects.Shader#setTextureCoordinates + * @since 4.0.0 + * @param {number} [topLeftX=0] - The top-left x coordinate of the texture. + * @param {number} [topLeftY=1] - The top-left y coordinate of the texture. + * @param {number} [topRightX=1] - The top-right x coordinate of the texture. + * @param {number} [topRightY=1] - The top-right y coordinate of the texture. + * @param {number} [bottomLeftX=0] - The bottom-left x coordinate of the texture. + * @param {number} [bottomLeftY=0] - The bottom-left y coordinate of the texture. + * @param {number} [bottomRightX=1] - The bottom-right x coordinate of the texture. + * @param {number} [bottomRightY=0] - The bottom-right y coordinate of the texture. + * @return {this} This Shader instance + */ + setTextureCoordinates: function ( + topLeftX, topLeftY, + topRightX, topRightY, + bottomLeftX, bottomLeftY, + bottomRightX, bottomRightY + ) + { + if (topLeftX === undefined) { topLeftX = 0; } + if (topLeftY === undefined) { topLeftY = 1; } + if (topRightX === undefined) { topRightX = 1; } + if (topRightY === undefined) { topRightY = 1; } + if (bottomLeftX === undefined) { bottomLeftX = 0; } + if (bottomLeftY === undefined) { bottomLeftY = 0; } + if (bottomRightX === undefined) { bottomRightX = 1; } + if (bottomRightY === undefined) { bottomRightY = 0; } + + this.textureCoordinateTopLeft.set(topLeftX, topLeftY); + this.textureCoordinateTopRight.set(topRightX, topRightY); + this.textureCoordinateBottomLeft.set(bottomLeftX, bottomLeftY); + this.textureCoordinateBottomRight.set(bottomRightX, bottomRightY); + + return this; + }, + + /** + * Set the texture coordinates of the shader from a frame. + * This is a convenience method that sets the texture coordinates + * to match a frame from a texture. + * + * @method Phaser.GameObjects.Shader#setTextureCoordinatesFromFrame + * @since 4.0.0 + * @param {Phaser.Textures.Frame|string} frame - The frame to set the texture coordinates from. If a string is given, it will be used to look up the frame in the texture. + * @param {Phaser.Textures.Texture|string} [texture] - The texture that the frame is from. This is only used if `frame` is a string. If a string is given, it will be used to look up the texture in the Texture Manager. If not given, the first member of `Shader.textures` is used. If `Shader.textures` is empty, an error will occur. + */ + setTextureCoordinatesFromFrame: function (frame, texture) + { + if (typeof frame === 'string') + { + if (!texture) + { + texture = this.textures[0]; + } + else if (typeof texture === 'string') + { + texture = this.scene.textures.get(texture); + } + frame = texture.get(frame); + } + + var u0 = frame.u0; + var v0 = frame.v0; + var u1 = frame.u1; + var v1 = frame.v1; + + this.setTextureCoordinates(u0, v0, u1, v0, u0, v1, u1, v1); + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.Shader#preDestroy + * @protected + * @since 3.17.0 + */ + preDestroy: function () + { + this.renderNode = null; + + this.textures.length = 0; + + if (this.drawingContext) + { + this.drawingContext.destroy(); + if (this.texture) + { + this.texture.destroy(); + } + + this.drawingContext = null; + this.glTexture = null; + this.texture = null; + } + } +}); + +module.exports = Shader; + + +/***/ }), + +/***/ 80464: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * This is a stub function for Shader.Render. There is no Canvas renderer for Shader objects. + * + * @method Phaser.GameObjects.Shader#renderCanvas + * @since 3.17.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Shader} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + */ +var ShaderCanvasRenderer = function () +{ +}; + +module.exports = ShaderCanvasRenderer; + + +/***/ }), + +/***/ 54935: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Shader = __webpack_require__(20071); + +/** + * Creates a new Shader Game Object and returns it. + * + * Note: This method will only be available if the Shader Game Object and WebGL support have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#shader + * @since 3.17.0 + * + * @param {Phaser.Types.GameObjects.Shader.ShaderConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Shader} The Game Object that was created. + */ +GameObjectCreator.register('shader', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var quadConfig = GetAdvancedValue(config, 'config', null); + var x = GetAdvancedValue(config, 'x', 0); + var y = GetAdvancedValue(config, 'y', 0); + var width = GetAdvancedValue(config, 'width', 128); + var height = GetAdvancedValue(config, 'height', 128); + + var shader = new Shader(this.scene, quadConfig, x, y, width, height); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, shader, config); + + return shader; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 74177: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Shader = __webpack_require__(20071); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Shader Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Shader Game Object and WebGL support have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#shader + * @webglOnly + * @since 3.17.0 + * + * @param {(string|Phaser.Types.GameObjects.Shader.ShaderQuadConfig)} config - The configuration object this Shader will use. It can also be a key that corresponds to a shader in the shader cache, which will be used as `fragmentKey` in a new config object. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the Game Object. + * @param {number} [height=128] - The height of the Game Object. + * @param {string[]} [textures] - Optional array of texture keys to bind to the iChannel0...3 uniforms. The textures must already exist in the Texture Manager. + * @param {object} [textureData] - Optional additional texture data. + * + * @return {Phaser.GameObjects.Shader} The Game Object that was created. + */ +if (true) +{ + GameObjectFactory.register('shader', function (config, x, y, width, height, textures, textureData) + { + return this.displayList.add(new Shader(this.scene, config, x, y, width, height, textures, textureData)); + }); +} + + +/***/ }), + +/***/ 25479: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(19257); +} + +if (true) +{ + renderCanvas = __webpack_require__(80464); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 19257: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Shader#renderWebGL + * @since 3.17.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Shader} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ShaderWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + + camera.addToRenderList(src); + + if (src.renderToTexture) + { + drawingContext = src.drawingContext; + + if (drawingContext.width !== src.width || drawingContext.height !== src.height) + { + var width = src.width; + var height = src.height; + drawingContext.resize(width, height); + drawingContext.camera.setSize(width, height); + } + + drawingContext.use(); + } + + src.renderNode.run(drawingContext, src, parentMatrix); + + if (src.renderToTexture) + { + drawingContext.release(); + } +}; + +module.exports = ShaderWebGLRenderer; + + +/***/ }), + +/***/ 10441: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Utils = __webpack_require__(70554); + +/** + * Renders a filled path for the given Shape. + * + * @method Phaser.GameObjects.Shape#FillPathWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} submitter - The Submitter node to use. + * @param {Phaser.GameObjects.Components.TransformMatrix} calcMatrix - The transform matrix used to get the position values. + * @param {Phaser.GameObjects.Shape} src - The Game Object shape being rendered in this call. + * @param {number} alpha - The base alpha value. + * @param {number} dx - The source displayOriginX. + * @param {number} dy - The source displayOriginY. + */ +var FillPathWebGL = function (drawingContext, submitter, calcMatrix, src, alpha, dx, dy) +{ + // This is very similar to the FillPath RenderNode, but it already + // has access to the Earcut indexes, so it doesn't need to calculate them. + + var fillTintColor = Utils.getTintAppendFloatAlpha(src.fillColor, src.fillAlpha * alpha); + + var path = src.pathData; + var pathIndexes = src.pathIndexes; + + var length = path.length; + var pathIndex, pointX, pointY, x, y; + + var vertices = Array(length * 2); + var colors = Array(length); + + var verticesIndex = 0; + var colorsIndex = 0; + + for (pathIndex = 0; pathIndex < length; pathIndex += 2) + { + pointX = path[pathIndex] - dx; + pointY = path[pathIndex + 1] - dy; + + // Transform the point. + x = calcMatrix.getX(pointX, pointY); + y = calcMatrix.getY(pointX, pointY); + + vertices[verticesIndex++] = x; + vertices[verticesIndex++] = y; + colors[colorsIndex++] = fillTintColor; + } + + submitter.batch( + drawingContext, + pathIndexes, + vertices, + colors + ); +}; + +module.exports = FillPathWebGL; + + +/***/ }), + +/***/ 65960: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sets the fillStyle on the target context based on the given Shape. + * + * @method Phaser.GameObjects.Shape#FillStyleCanvas + * @since 3.13.0 + * @private + * + * @param {CanvasRenderingContext2D} ctx - The context to set the fill style on. + * @param {Phaser.GameObjects.Shape} src - The Game Object to set the fill style from. + * @param {number} [altColor] - An alternative color to render with. + * @param {number} [altAlpha] - An alternative alpha to render with. + */ +var FillStyleCanvas = function (ctx, src, altColor, altAlpha) +{ + var fillColor = (altColor) ? altColor : src.fillColor; + var fillAlpha = (altAlpha) ? altAlpha : src.fillAlpha; + + var red = ((fillColor & 0xFF0000) >>> 16); + var green = ((fillColor & 0xFF00) >>> 8); + var blue = (fillColor & 0xFF); + + ctx.fillStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + fillAlpha + ')'; +}; + +module.exports = FillStyleCanvas; + + +/***/ }), + +/***/ 75177: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sets the strokeStyle and lineWidth on the target context based on the given Shape. + * + * @method Phaser.GameObjects.Shape#LineStyleCanvas + * @since 3.13.0 + * @private + * + * @param {CanvasRenderingContext2D} ctx - The context to set the stroke style on. + * @param {Phaser.GameObjects.Shape} src - The Game Object to set the stroke style from. + * @param {number} [altColor] - An alternative color to render with. + * @param {number} [altAlpha] - An alternative alpha to render with. + */ +var LineStyleCanvas = function (ctx, src, altColor, altAlpha) +{ + var strokeColor = (altColor) ? altColor : src.strokeColor; + var strokeAlpha = (altAlpha) ? altAlpha : src.strokeAlpha; + + var red = ((strokeColor & 0xFF0000) >>> 16); + var green = ((strokeColor & 0xFF00) >>> 8); + var blue = (strokeColor & 0xFF); + + ctx.strokeStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + strokeAlpha + ')'; + ctx.lineWidth = src.lineWidth; +}; + +module.exports = LineStyleCanvas; + + +/***/ }), + +/***/ 17803: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultGraphicsNodes = __webpack_require__(87891); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var Line = __webpack_require__(23031); + +/** + * @classdesc + * The Shape Game Object is a base class for the various different shapes, such as the Arc, Star or Polygon. + * You cannot add a Shape directly to your Scene, it is meant as a base for your own custom Shape classes. + * + * Shape objects use the same batch as the Graphics Game Object to render in WebGL. + * They do not support gradients, path detail threshold, or other advanced Graphics features. + * In return, they have precomputed internal data for quick rendering of the geometry. + * + * @class Shape + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {string} [type] - The internal type of the Shape. + * @param {any} [data] - The data of the source shape geometry, if any. + */ +var Shape = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.AlphaSingle, + Components.BlendMode, + Components.Depth, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.Transform, + Components.Visible + ], + + initialize: + + function Shape (scene, type, data) + { + if (type === undefined) { type = 'Shape'; } + + GameObject.call(this, scene, type); + + /** + * The source Shape data. Typically a geometry object. + * You should not manipulate this directly. + * + * @name Phaser.GameObjects.Shape#geom + * @type {any} + * @readonly + * @since 3.13.0 + */ + this.geom = data; + + /** + * Holds the polygon path data for filled rendering. + * + * @name Phaser.GameObjects.Shape#pathData + * @type {number[]} + * @readonly + * @since 3.13.0 + */ + this.pathData = []; + + /** + * Holds the earcut polygon path index data for filled rendering. + * + * @name Phaser.GameObjects.Shape#pathIndexes + * @type {number[]} + * @readonly + * @since 3.13.0 + */ + this.pathIndexes = []; + + /** + * The fill color used by this Shape. + * + * @name Phaser.GameObjects.Shape#fillColor + * @type {number} + * @since 3.13.0 + */ + this.fillColor = 0xffffff; + + /** + * The fill alpha value used by this Shape. + * + * @name Phaser.GameObjects.Shape#fillAlpha + * @type {number} + * @since 3.13.0 + */ + this.fillAlpha = 1; + + /** + * The stroke color used by this Shape. + * + * @name Phaser.GameObjects.Shape#strokeColor + * @type {number} + * @since 3.13.0 + */ + this.strokeColor = 0xffffff; + + /** + * The stroke alpha value used by this Shape. + * + * @name Phaser.GameObjects.Shape#strokeAlpha + * @type {number} + * @since 3.13.0 + */ + this.strokeAlpha = 1; + + /** + * The stroke line width used by this Shape. + * + * @name Phaser.GameObjects.Shape#lineWidth + * @type {number} + * @since 3.13.0 + */ + this.lineWidth = 1; + + /** + * Controls if this Shape is filled or not. + * Note that some Shapes do not support being filled (such as Line shapes) + * + * @name Phaser.GameObjects.Shape#isFilled + * @type {boolean} + * @since 3.13.0 + */ + this.isFilled = false; + + /** + * Controls if this Shape is stroked or not. + * Note that some Shapes do not support being stroked (such as Iso Box shapes) + * + * @name Phaser.GameObjects.Shape#isStroked + * @type {boolean} + * @since 3.13.0 + */ + this.isStroked = false; + + /** + * Controls if this Shape path is closed during rendering when stroked. + * Note that some Shapes are always closed when stroked (such as Ellipse shapes) + * + * @name Phaser.GameObjects.Shape#closePath + * @type {boolean} + * @since 3.13.0 + */ + this.closePath = true; + + /** + * Private internal value. + * A Line used when parsing internal path data to avoid constant object re-creation. + * + * @name Phaser.GameObjects.Shape#_tempLine + * @type {Phaser.Geom.Line} + * @private + * @since 3.13.0 + */ + this._tempLine = new Line(); + + /** + * The native (un-scaled) width of this Game Object. + * + * Changing this value will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or use + * the `displayWidth` property. + * + * @name Phaser.GameObjects.Shape#width + * @type {number} + * @since 3.13.0 + */ + this.width = 0; + + /** + * The native (un-scaled) height of this Game Object. + * + * Changing this value will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or use + * the `displayHeight` property. + * + * @name Phaser.GameObjects.Shape#height + * @type {number} + * @since 3.0.0 + */ + this.height = 0; + + if (this.enableFilters) + { + // Prevent Shape stroke from being cut off in filters. + this.filtersFocusContext = true; + } + + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Shape#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultGraphicsNodes; + } + }, + + /** + * Sets the fill color and alpha for this Shape. + * + * If you wish for the Shape to not be filled then call this method with no arguments, or just set `isFilled` to `false`. + * + * Note that some Shapes do not support fill colors, such as the Line shape. + * + * This call can be chained. + * + * @method Phaser.GameObjects.Shape#setFillStyle + * @since 3.13.0 + * + * @param {number} [color] - The color used to fill this shape. If not provided the Shape will not be filled. + * @param {number} [alpha=1] - The alpha value used when filling this shape, if a fill color is given. + * + * @return {this} This Game Object instance. + */ + setFillStyle: function (color, alpha) + { + if (alpha === undefined) { alpha = 1; } + + if (color === undefined) + { + this.isFilled = false; + } + else + { + this.fillColor = color; + this.fillAlpha = alpha; + this.isFilled = true; + } + + return this; + }, + + /** + * Sets the stroke color and alpha for this Shape. + * + * If you wish for the Shape to not be stroked then call this method with no arguments, or just set `isStroked` to `false`. + * + * Note that some Shapes do not support being stroked, such as the Iso Box shape. + * + * This call can be chained. + * + * @method Phaser.GameObjects.Shape#setStrokeStyle + * @since 3.13.0 + * + * @param {number} [lineWidth] - The width of line to stroke with. If not provided or undefined the Shape will not be stroked. + * @param {number} [color] - The color used to stroke this shape. If not provided the Shape will not be stroked. + * @param {number} [alpha=1] - The alpha value used when stroking this shape, if a stroke color is given. + * + * @return {this} This Game Object instance. + */ + setStrokeStyle: function (lineWidth, color, alpha) + { + if (alpha === undefined) { alpha = 1; } + + if (lineWidth === undefined) + { + this.isStroked = false; + } + else + { + this.lineWidth = lineWidth; + this.strokeColor = color; + this.strokeAlpha = alpha; + this.isStroked = true; + } + + return this; + }, + + /** + * Sets if this Shape path is closed during rendering when stroked. + * Note that some Shapes are always closed when stroked (such as Ellipse shapes) + * + * This call can be chained. + * + * @method Phaser.GameObjects.Shape#setClosePath + * @since 3.13.0 + * + * @param {boolean} value - Set to `true` if the Shape should be closed when stroked, otherwise `false`. + * + * @return {this} This Game Object instance. + */ + setClosePath: function (value) + { + this.closePath = value; + + return this; + }, + + /** + * Sets the internal size of this Game Object, as used for frame or physics body creation. + * + * This will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or call the + * `setDisplaySize` method, which is the same thing as changing the scale but allows you + * to do so by giving pixel values. + * + * If you have enabled this Game Object for input, changing the size will _not_ change the + * size of the hit area. To do this you should adjust the `input.hitArea` object directly. + * + * @method Phaser.GameObjects.Shape#setSize + * @private + * @since 3.13.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + + return this; + }, + + /** + * Sets the display size of this Shape. + * + * Calling this will adjust the scale. + * + * @method Phaser.GameObjects.Shape#setDisplaySize + * @since 3.53.0 + * + * @param {number} width - The display width of this Shape. + * @param {number} height - The display height of this Shape. + * + * @return {this} This Shape instance. + */ + setDisplaySize: function (width, height) + { + this.displayWidth = width; + this.displayHeight = height; + + return this; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.Shape#preDestroy + * @protected + * @since 3.13.0 + */ + preDestroy: function () + { + this.geom = null; + this._tempLine = null; + this.pathData = []; + this.pathIndexes = []; + }, + + /** + * The displayed width of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.Shape#displayWidth + * @type {number} + * @since 3.13.0 + */ + displayWidth: { + + get: function () + { + return this.scaleX * this.width; + }, + + set: function (value) + { + this.scaleX = value / this.width; + } + + }, + + /** + * The displayed height of this Game Object. + * + * This value takes into account the scale factor. + * + * Setting this value will adjust the Game Object's scale property. + * + * @name Phaser.GameObjects.Shape#displayHeight + * @type {number} + * @since 3.13.0 + */ + displayHeight: { + + get: function () + { + return this.scaleY * this.height; + }, + + set: function (value) + { + this.scaleY = value / this.height; + } + + } + +}); + +module.exports = Shape; + + +/***/ }), + +/***/ 34682: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Utils = __webpack_require__(70554); + +/** + * Renders a stroke outline around the given Shape. + * + * @method Phaser.GameObjects.Shape#StrokePathWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} submitter - The Submitter node to use. + * @param {Phaser.GameObjects.Components.TransformMatrix} matrix - The current transform matrix. + * @param {Phaser.GameObjects.Shape} src - The Game Object shape being rendered in this call. + * @param {number} alpha - The base alpha value. + * @param {number} dx - The source displayOriginX. + * @param {number} dy - The source displayOriginY. + */ +var StrokePathWebGL = function (drawingContext, submitter, matrix, src, alpha, dx, dy) +{ + var strokeTintColor = Utils.getTintAppendFloatAlpha(src.strokeColor, src.strokeAlpha * alpha); + + var path = src.pathData; + var pathLength = path.length - 1; + var lineWidth = src.lineWidth; + var openPath = !src.closePath; + + var strokePath = src.customRenderNodes.StrokePath || src.defaultRenderNodes.StrokePath; + + var pointPath = []; + + // Don't add the last point to open paths. + if (openPath) + { + pathLength -= 2; + } + + for (var i = 0; i < pathLength; i += 2) + { + var x = path[i] - dx; + var y = path[i + 1] - dy; + if (i > 0) + { + if (x === path[i - 2] && y === path[i - 1]) + { + // Duplicate point, skip it + continue; + } + } + pointPath.push({ + x: x, + y: y, + width: lineWidth + }); + } + + strokePath.run( + drawingContext, + submitter, + pointPath, + lineWidth, + openPath, + matrix, + strokeTintColor, strokeTintColor, strokeTintColor, strokeTintColor + ); +}; + +module.exports = StrokePathWebGL; + + +/***/ }), + +/***/ 23629: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArcRender = __webpack_require__(13609); +var Class = __webpack_require__(83419); +var DegToRad = __webpack_require__(39506); +var Earcut = __webpack_require__(94811); +var GeomCircle = __webpack_require__(96503); +var MATH_CONST = __webpack_require__(36383); +var Shape = __webpack_require__(17803); + +/** + * @classdesc + * The Arc Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * When it renders it displays an arc shape. You can control the start and end angles of the arc, + * as well as if the angles are winding clockwise or anti-clockwise. With the default settings + * it renders as a complete circle. By changing the angles you can create other arc shapes, + * such as half-circles. + * + * Arcs also have an `iterations` property and corresponding `setIterations` method. This allows + * you to control how smooth the shape renders in WebGL, by controlling the number of iterations + * that take place during construction. + * + * @class Arc + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [radius=128] - The radius of the arc. + * @param {number} [startAngle=0] - The start angle of the arc, in degrees. + * @param {number} [endAngle=360] - The end angle of the arc, in degrees. + * @param {boolean} [anticlockwise=false] - The winding order of the start and end angles. + * @param {number} [fillColor] - The color the arc will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the arc will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Arc = new Class({ + + Extends: Shape, + + Mixins: [ + ArcRender + ], + + initialize: + + function Arc (scene, x, y, radius, startAngle, endAngle, anticlockwise, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (radius === undefined) { radius = 128; } + if (startAngle === undefined) { startAngle = 0; } + if (endAngle === undefined) { endAngle = 360; } + if (anticlockwise === undefined) { anticlockwise = false; } + + Shape.call(this, scene, 'Arc', new GeomCircle(0, 0, radius)); + + /** + * Private internal value. Holds the start angle in degrees. + * + * @name Phaser.GameObjects.Arc#_startAngle + * @type {number} + * @private + * @since 3.13.0 + */ + this._startAngle = startAngle; + + /** + * Private internal value. Holds the end angle in degrees. + * + * @name Phaser.GameObjects.Arc#_endAngle + * @type {number} + * @private + * @since 3.13.0 + */ + this._endAngle = endAngle; + + /** + * Private internal value. Holds the winding order of the start and end angles. + * + * @name Phaser.GameObjects.Arc#_anticlockwise + * @type {boolean} + * @private + * @since 3.13.0 + */ + this._anticlockwise = anticlockwise; + + /** + * Private internal value. Holds the number of iterations used when drawing the arc. + * + * @name Phaser.GameObjects.Arc#_iterations + * @type {number} + * @default 0.01 + * @private + * @since 3.13.0 + */ + this._iterations = 0.01; + + this.setPosition(x, y); + + var diameter = this.geom.radius * 2; + this.setSize(diameter, diameter); + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateDisplayOrigin(); + this.updateData(); + }, + + /** + * The number of iterations used when drawing the arc. + * Increase this value for smoother arcs, at the cost of more polygons being rendered. + * Modify this value by small amounts, such as 0.01. + * + * @name Phaser.GameObjects.Arc#iterations + * @type {number} + * @default 0.01 + * @since 3.13.0 + */ + iterations: { + + get: function () + { + return this._iterations; + }, + + set: function (value) + { + this._iterations = value; + + this.updateData(); + } + + }, + + /** + * The radius of the arc. + * + * @name Phaser.GameObjects.Arc#radius + * @type {number} + * @since 3.13.0 + */ + radius: { + + get: function () + { + return this.geom.radius; + }, + + set: function (value) + { + this.geom.radius = value; + + var diameter = value * 2; + this.setSize(diameter, diameter); + this.updateDisplayOrigin(); + this.updateData(); + } + + }, + + /** + * The start angle of the arc, in degrees. + * + * @name Phaser.GameObjects.Arc#startAngle + * @type {number} + * @since 3.13.0 + */ + startAngle: { + + get: function () + { + return this._startAngle; + }, + + set: function (value) + { + this._startAngle = value; + + this.updateData(); + } + + }, + + /** + * The end angle of the arc, in degrees. + * + * @name Phaser.GameObjects.Arc#endAngle + * @type {number} + * @since 3.13.0 + */ + endAngle: { + + get: function () + { + return this._endAngle; + }, + + set: function (value) + { + this._endAngle = value; + + this.updateData(); + } + + }, + + /** + * The winding order of the start and end angles. + * + * @name Phaser.GameObjects.Arc#anticlockwise + * @type {boolean} + * @since 3.13.0 + */ + anticlockwise: { + + get: function () + { + return this._anticlockwise; + }, + + set: function (value) + { + this._anticlockwise = value; + + this.updateData(); + } + + }, + + /** + * Sets the radius of the arc. + * This call can be chained. + * + * @method Phaser.GameObjects.Arc#setRadius + * @since 3.13.0 + * + * @param {number} value - The value to set the radius to. + * + * @return {this} This Game Object instance. + */ + setRadius: function (value) + { + this.radius = value; + + return this; + }, + + /** + * Sets the number of iterations used when drawing the arc. + * Increase this value for smoother arcs, at the cost of more polygons being rendered. + * Modify this value by small amounts, such as 0.01. + * This call can be chained. + * + * @method Phaser.GameObjects.Arc#setIterations + * @since 3.13.0 + * + * @param {number} value - The value to set the iterations to. + * + * @return {this} This Game Object instance. + */ + setIterations: function (value) + { + if (value === undefined) { value = 0.01; } + + this.iterations = value; + + return this; + }, + + /** + * Sets the starting angle of the arc, in degrees. + * This call can be chained. + * + * @method Phaser.GameObjects.Arc#setStartAngle + * @since 3.13.0 + * + * @param {number} value - The value to set the starting angle to. + * + * @return {this} This Game Object instance. + */ + setStartAngle: function (angle, anticlockwise) + { + this._startAngle = angle; + + if (anticlockwise !== undefined) + { + this._anticlockwise = anticlockwise; + } + + return this.updateData(); + }, + + /** + * Sets the ending angle of the arc, in degrees. + * This call can be chained. + * + * @method Phaser.GameObjects.Arc#setEndAngle + * @since 3.13.0 + * + * @param {number} value - The value to set the ending angle to. + * + * @return {this} This Game Object instance. + */ + setEndAngle: function (angle, anticlockwise) + { + this._endAngle = angle; + + if (anticlockwise !== undefined) + { + this._anticlockwise = anticlockwise; + } + + return this.updateData(); + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Arc#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + var step = this._iterations; + var iteration = step; + + var radius = this.geom.radius; + var startAngle = DegToRad(this._startAngle); + var endAngle = DegToRad(this._endAngle); + var anticlockwise = this._anticlockwise; + + var x = radius; + var y = radius; + + endAngle -= startAngle; + + if (anticlockwise) + { + if (endAngle < -MATH_CONST.TAU) + { + endAngle = -MATH_CONST.TAU; + } + else if (endAngle > 0) + { + endAngle = -MATH_CONST.TAU + endAngle % MATH_CONST.TAU; + } + } + else if (endAngle > MATH_CONST.TAU) + { + endAngle = MATH_CONST.TAU; + } + else if (endAngle < 0) + { + endAngle = MATH_CONST.TAU + endAngle % MATH_CONST.TAU; + } + + var path = [ x + Math.cos(startAngle) * radius, y + Math.sin(startAngle) * radius ]; + + var ta; + + while (iteration < 1) + { + ta = endAngle * iteration + startAngle; + + path.push(x + Math.cos(ta) * radius, y + Math.sin(ta) * radius); + + iteration += step; + } + + ta = endAngle + startAngle; + + path.push(x + Math.cos(ta) * radius, y + Math.sin(ta) * radius); + + path.push(x + Math.cos(startAngle) * radius, y + Math.sin(startAngle) * radius); + + this.pathIndexes = Earcut(path); + this.pathData = path; + + return this; + } + +}); + +module.exports = Arc; + + +/***/ }), + +/***/ 42542: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DegToRad = __webpack_require__(39506); +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Arc#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Arc} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ArcCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var radius = src.radius; + + ctx.beginPath(); + + ctx.arc( + (radius) - src.originX * (radius * 2), + (radius) - src.originY * (radius * 2), + radius, + DegToRad(src._startAngle), + DegToRad(src._endAngle), + src.anticlockwise + ); + + if (src.closePath) + { + ctx.closePath(); + } + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + ctx.fill(); + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = ArcCanvasRenderer; + + +/***/ }), + +/***/ 42563: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Arc = __webpack_require__(23629); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Arc Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Arc Game Object has been built into Phaser. + * + * The Arc Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * When it renders it displays an arc shape. You can control the start and end angles of the arc, + * as well as if the angles are winding clockwise or anti-clockwise. With the default settings + * it renders as a complete circle. By changing the angles you can create other arc shapes, + * such as half-circles. + * + * @method Phaser.GameObjects.GameObjectFactory#arc + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [radius=128] - The radius of the arc. + * @param {number} [startAngle=0] - The start angle of the arc, in degrees. + * @param {number} [endAngle=360] - The end angle of the arc, in degrees. + * @param {boolean} [anticlockwise=false] - The winding order of the start and end angles. + * @param {number} [fillColor] - The color the arc will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the arc will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Arc} The Game Object that was created. + */ +GameObjectFactory.register('arc', function (x, y, radius, startAngle, endAngle, anticlockwise, fillColor, fillAlpha) +{ + return this.displayList.add(new Arc(this.scene, x, y, radius, startAngle, endAngle, anticlockwise, fillColor, fillAlpha)); +}); + +/** + * Creates a new Circle Shape Game Object and adds it to the Scene. + * + * A Circle is an Arc with no defined start and end angle, making it render as a complete circle. + * + * Note: This method will only be available if the Arc Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#circle + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [radius=128] - The radius of the circle. + * @param {number} [fillColor] - The color the circle will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the circle will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Arc} The Game Object that was created. + */ +GameObjectFactory.register('circle', function (x, y, radius, fillColor, fillAlpha) +{ + return this.displayList.add(new Arc(this.scene, x, y, radius, 0, 360, false, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 13609: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(41447); +} + +if (true) +{ + renderCanvas = __webpack_require__(42542); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 41447: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var FillPathWebGL = __webpack_require__(10441); +var StrokePathWebGL = __webpack_require__(34682); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Arc#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Arc} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var ArcWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var alpha = src.alpha; + + var submitter = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + if (src.isFilled) + { + FillPathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = ArcWebGLRenderer; + + +/***/ }), + +/***/ 89: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CurveRender = __webpack_require__(33141); +var Earcut = __webpack_require__(94811); +var Rectangle = __webpack_require__(87841); +var Shape = __webpack_require__(17803); + +/** + * @classdesc + * The Curve Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * To render a Curve Shape you must first create a `Phaser.Curves.Curve` object, then pass it to + * the Curve Shape in the constructor. + * + * The Curve shape also has a `smoothness` property and corresponding `setSmoothness` method. + * This allows you to control how smooth the shape renders in WebGL, by controlling the number of iterations + * that take place during construction. Increase and decrease the default value for smoother, or more + * jagged, shapes. + * + * @class Curve + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {Phaser.Curves.Curve} [curve] - The Curve object to use to create the Shape. + * @param {number} [fillColor] - The color the curve will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the curve will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Curve = new Class({ + + Extends: Shape, + + Mixins: [ + CurveRender + ], + + initialize: + + function Curve (scene, x, y, curve, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + Shape.call(this, scene, 'Curve', curve); + + /** + * Private internal value. + * The number of points used to draw the curve. Higher values create smoother renders at the cost of more triangles being drawn. + * + * @name Phaser.GameObjects.Curve#_smoothness + * @type {number} + * @private + * @since 3.13.0 + */ + this._smoothness = 32; + + /** + * Private internal value. + * The Curve bounds rectangle. + * + * @name Phaser.GameObjects.Curve#_curveBounds + * @type {Phaser.Geom.Rectangle} + * @private + * @since 3.13.0 + */ + this._curveBounds = new Rectangle(); + + this.closePath = false; + + this.setPosition(x, y); + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateData(); + }, + + /** + * The smoothness of the curve. The number of points used when rendering it. + * Increase this value for smoother curves, at the cost of more polygons being rendered. + * + * @name Phaser.GameObjects.Curve#smoothness + * @type {number} + * @default 32 + * @since 3.13.0 + */ + smoothness: { + + get: function () + { + return this._smoothness; + }, + + set: function (value) + { + this._smoothness = value; + + this.updateData(); + } + + }, + + /** + * Sets the smoothness of the curve. The number of points used when rendering it. + * Increase this value for smoother curves, at the cost of more polygons being rendered. + * This call can be chained. + * + * @method Phaser.GameObjects.Curve#setSmoothness + * @since 3.13.0 + * + * @param {number} value - The value to set the smoothness to. + * + * @return {this} This Game Object instance. + */ + setSmoothness: function (value) + { + this._smoothness = value; + + return this.updateData(); + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Curve#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + var bounds = this._curveBounds; + var smoothness = this._smoothness; + + // Update the bounds in case the underlying data has changed + this.geom.getBounds(bounds, smoothness); + + this.setSize(bounds.width, bounds.height); + this.updateDisplayOrigin(); + + var path = []; + var points = this.geom.getPoints(smoothness); + + for (var i = 0; i < points.length; i++) + { + path.push(points[i].x, points[i].y); + } + + path.push(points[0].x, points[0].y); + + this.pathIndexes = Earcut(path); + this.pathData = path; + + return this; + } + +}); + +module.exports = Curve; + + +/***/ }), + +/***/ 3170: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Curve#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Curve} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var CurveCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX + src._curveBounds.x; + var dy = src._displayOriginY + src._curveBounds.y; + + var path = src.pathData; + var pathLength = path.length - 1; + + var px1 = path[0] - dx; + var py1 = path[1] - dy; + + ctx.beginPath(); + + ctx.moveTo(px1, py1); + + if (!src.closePath) + { + pathLength -= 2; + } + + for (var i = 2; i < pathLength; i += 2) + { + var px2 = path[i] - dx; + var py2 = path[i + 1] - dy; + + ctx.lineTo(px2, py2); + } + + if (src.closePath) + { + ctx.closePath(); + } + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + ctx.fill(); + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = CurveCanvasRenderer; + + +/***/ }), + +/***/ 40511: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Curve = __webpack_require__(89); + +/** + * Creates a new Curve Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Curve Game Object has been built into Phaser. + * + * The Curve Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * To render a Curve Shape you must first create a `Phaser.Curves.Curve` object, then pass it to + * the Curve Shape in the constructor. + * + * The Curve shape also has a `smoothness` property and corresponding `setSmoothness` method. + * This allows you to control how smooth the shape renders in WebGL, by controlling the number of iterations + * that take place during construction. Increase and decrease the default value for smoother, or more + * jagged, shapes. + * + * @method Phaser.GameObjects.GameObjectFactory#curve + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {Phaser.Curves.Curve} [curve] - The Curve object to use to create the Shape. + * @param {number} [fillColor] - The color the curve will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the curve will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Curve} The Game Object that was created. + */ +GameObjectFactory.register('curve', function (x, y, curve, fillColor, fillAlpha) +{ + return this.displayList.add(new Curve(this.scene, x, y, curve, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 33141: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(53987); +} + +if (true) +{ + renderCanvas = __webpack_require__(3170); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 53987: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillPathWebGL = __webpack_require__(10441); +var GetCalcMatrix = __webpack_require__(91296); +var StrokePathWebGL = __webpack_require__(34682); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Curve#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Curve} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var CurveWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + // Note use of _curveBounds, unlike other path-based Shape objects. + var dx = src._displayOriginX + src._curveBounds.x; + var dy = src._displayOriginY + src._curveBounds.y; + + var alpha = src.alpha; + + var submitter = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + if (src.isFilled) + { + FillPathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = CurveWebGLRenderer; + + +/***/ }), + +/***/ 19921: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Earcut = __webpack_require__(94811); +var EllipseRender = __webpack_require__(54205); +var GeomEllipse = __webpack_require__(8497); +var Shape = __webpack_require__(17803); + +/** + * @classdesc + * The Ellipse Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * When it renders it displays an ellipse shape. You can control the width and height of the ellipse. + * If the width and height match it will render as a circle. If the width is less than the height, + * it will look more like an egg shape. + * + * The Ellipse shape also has a `smoothness` property and corresponding `setSmoothness` method. + * This allows you to control how smooth the shape renders in WebGL, by controlling the number of iterations + * that take place during construction. Increase and decrease the default value for smoother, or more + * jagged, shapes. + * + * @class Ellipse + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the ellipse. An ellipse with equal width and height renders as a circle. + * @param {number} [height=128] - The height of the ellipse. An ellipse with equal width and height renders as a circle. + * @param {number} [fillColor] - The color the ellipse will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the ellipse will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Ellipse = new Class({ + + Extends: Shape, + + Mixins: [ + EllipseRender + ], + + initialize: + + function Ellipse (scene, x, y, width, height, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 128; } + if (height === undefined) { height = 128; } + + Shape.call(this, scene, 'Ellipse', new GeomEllipse(width / 2, height / 2, width, height)); + + /** + * Private internal value. + * The number of points used to draw the curve. Higher values create smoother renders at the cost of more triangles being drawn. + * + * @name Phaser.GameObjects.Ellipse#_smoothness + * @type {number} + * @private + * @since 3.13.0 + */ + this._smoothness = 64; + + this.setPosition(x, y); + + this.width = width; + this.height = height; + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateDisplayOrigin(); + this.updateData(); + }, + + /** + * The smoothness of the ellipse. The number of points used when rendering it. + * Increase this value for a smoother ellipse, at the cost of more polygons being rendered. + * + * @name Phaser.GameObjects.Ellipse#smoothness + * @type {number} + * @default 64 + * @since 3.13.0 + */ + smoothness: { + + get: function () + { + return this._smoothness; + }, + + set: function (value) + { + this._smoothness = value; + + this.updateData(); + } + + }, + + /** + * Sets the size of the ellipse by changing the underlying geometry data, rather than scaling the object. + * This call can be chained. + * + * @method Phaser.GameObjects.Ellipse#setSize + * @since 3.13.0 + * + * @param {number} width - The width of the ellipse. + * @param {number} height - The height of the ellipse. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + this.geom.setPosition(width / 2, height / 2); + this.geom.setSize(width, height); + + this.updateDisplayOrigin(); + + return this.updateData(); + }, + + /** + * Sets the smoothness of the ellipse. The number of points used when rendering it. + * Increase this value for a smoother ellipse, at the cost of more polygons being rendered. + * This call can be chained. + * + * @method Phaser.GameObjects.Ellipse#setSmoothness + * @since 3.13.0 + * + * @param {number} value - The value to set the smoothness to. + * + * @return {this} This Game Object instance. + */ + setSmoothness: function (value) + { + this._smoothness = value; + + return this.updateData(); + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Ellipse#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + var path = []; + var points = this.geom.getPoints(this._smoothness); + + for (var i = 0; i < points.length; i++) + { + path.push(points[i].x, points[i].y); + } + + path.push(points[0].x, points[0].y); + + this.pathIndexes = Earcut(path); + this.pathData = path; + + return this; + } + +}); + +module.exports = Ellipse; + + +/***/ }), + +/***/ 7930: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Ellipse#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Ellipse} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var EllipseCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var path = src.pathData; + var pathLength = path.length - 1; + + var px1 = path[0] - dx; + var py1 = path[1] - dy; + + ctx.beginPath(); + + ctx.moveTo(px1, py1); + + if (!src.closePath) + { + pathLength -= 2; + } + + for (var i = 2; i < pathLength; i += 2) + { + var px2 = path[i] - dx; + var py2 = path[i + 1] - dy; + + ctx.lineTo(px2, py2); + } + + ctx.closePath(); + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + ctx.fill(); + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = EllipseCanvasRenderer; + + +/***/ }), + +/***/ 1543: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Ellipse = __webpack_require__(19921); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Ellipse Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Ellipse Game Object has been built into Phaser. + * + * The Ellipse Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * When it renders it displays an ellipse shape. You can control the width and height of the ellipse. + * If the width and height match it will render as a circle. If the width is less than the height, + * it will look more like an egg shape. + * + * The Ellipse shape also has a `smoothness` property and corresponding `setSmoothness` method. + * This allows you to control how smooth the shape renders in WebGL, by controlling the number of iterations + * that take place during construction. Increase and decrease the default value for smoother, or more + * jagged, shapes. + * + * @method Phaser.GameObjects.GameObjectFactory#ellipse + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the ellipse. An ellipse with equal width and height renders as a circle. + * @param {number} [height=128] - The height of the ellipse. An ellipse with equal width and height renders as a circle. + * @param {number} [fillColor] - The color the ellipse will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the ellipse will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Ellipse} The Game Object that was created. + */ +GameObjectFactory.register('ellipse', function (x, y, width, height, fillColor, fillAlpha) +{ + return this.displayList.add(new Ellipse(this.scene, x, y, width, height, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 54205: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(19467); +} + +if (true) +{ + renderCanvas = __webpack_require__(7930); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 19467: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillPathWebGL = __webpack_require__(10441); +var GetCalcMatrix = __webpack_require__(91296); +var StrokePathWebGL = __webpack_require__(34682); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Ellipse#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Ellipse} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var EllipseWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var alpha = src.alpha; + + var submitter = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + if (src.isFilled) + { + FillPathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = EllipseWebGLRenderer; + + +/***/ }), + +/***/ 30479: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Shape = __webpack_require__(17803); +var GridRender = __webpack_require__(26015); + +/** + * @classdesc + * The Grid Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * A Grid Shape allows you to display a grid in your game, where you can control the size of the + * grid as well as the width and height of the grid cells. You can set a fill color for each grid + * cell as well as an alternate fill color. When the alternate fill color is set then the grid + * cells will alternate the fill colors as they render, creating a chess-board effect. You can + * also optionally have a stroke fill color. If set, this draws lines between the grid cells + * in the given color. If you specify a stroke color with an alpha of zero, then it will draw + * the cells spaced out, but without the lines between them. + * + * @class Grid + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the grid. + * @param {number} [height=128] - The height of the grid. + * @param {number} [cellWidth=32] - The width of one cell in the grid. + * @param {number} [cellHeight=32] - The height of one cell in the grid. + * @param {number} [fillColor] - The color the grid cells will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the grid cells will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * @param {number} [strokeFillColor] - The color of the lines between the grid cells. See the `setStrokeStyle` method. + * @param {number} [strokeFillAlpha] - The alpha of the lines between the grid cells. + */ +var Grid = new Class({ + + Extends: Shape, + + Mixins: [ + GridRender + ], + + initialize: + + function Grid (scene, x, y, width, height, cellWidth, cellHeight, fillColor, fillAlpha, strokeFillColor, strokeFillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 128; } + if (height === undefined) { height = 128; } + if (cellWidth === undefined) { cellWidth = 32; } + if (cellHeight === undefined) { cellHeight = 32; } + + Shape.call(this, scene, 'Grid', null); + + /** + * The width of each grid cell. + * Must be a positive value. + * + * @name Phaser.GameObjects.Grid#cellWidth + * @type {number} + * @since 3.13.0 + */ + this.cellWidth = cellWidth; + + /** + * The height of each grid cell. + * Must be a positive value. + * + * @name Phaser.GameObjects.Grid#cellHeight + * @type {number} + * @since 3.13.0 + */ + this.cellHeight = cellHeight; + + /** + * Will the grid render the alternating cells in the `altFillColor`? + * + * @name Phaser.GameObjects.Grid#showAltCells + * @type {boolean} + * @since 3.13.0 + */ + this.showAltCells = false; + + /** + * The color the alternating grid cells will be filled with, i.e. 0xff0000 for red. + * + * @name Phaser.GameObjects.Grid#altFillColor + * @type {number} + * @since 3.13.0 + */ + this.altFillColor; + + /** + * The alpha the alternating grid cells will be filled with. + * You can also set the alpha of the overall Shape using its `alpha` property. + * + * @name Phaser.GameObjects.Grid#altFillAlpha + * @type {number} + * @since 3.13.0 + */ + this.altFillAlpha; + + /** + * The padding around each cell. The effective gutter between cells is + * twice this value. + * + * @name Phaser.GameObjects.Grid#cellPadding + * @type {number} + * @since 4.0.0 + * @default 0.5 + */ + this.cellPadding = 0.5; + + /** + * Whether to stroke on the outside edges of the Grid object. + * + * @name Phaser.GameObjects.Grid#strokeOutside + * @type {boolean} + * @since 4.0.0 + * @default false + */ + this.strokeOutside = false; + + /** + * Whether to stroke on the outside edges of the Grid object + * when the cell is incomplete, e.g. the grid size does not + * evenly fit the cell size. + * + * This only has an effect if `strokeOutside` is `true`. + * It will affect the right and bottom edges of the grid. + * + * @name Phaser.GameObjects.Grid#strokeOutsideIncomplete + * @type {boolean} + * @since 4.0.0 + * @default false + */ + this.strokeOutsideIncomplete = true; + + this.setPosition(x, y); + this.setSize(width, height); + + this.setFillStyle(fillColor, fillAlpha); + + if (strokeFillColor !== undefined) + { + this.setStrokeStyle(strokeFillColor, strokeFillAlpha); + } + + this.updateDisplayOrigin(); + }, + + /** + * Sets the fill color and alpha level that the alternating grid cells will use. + * + * If this method is called with no values then alternating grid cells will not be rendered in a different color. + * + * Also see the `setStrokeStyle` and `setFillStyle` methods. + * + * This call can be chained. + * + * @method Phaser.GameObjects.Grid#setAltFillStyle + * @since 3.13.0 + * + * @param {number} [fillColor] - The color the alternating grid cells will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha=1] - The alpha the alternating grid cells will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {this} This Game Object instance. + */ + setAltFillStyle: function (fillColor, fillAlpha) + { + if (fillAlpha === undefined) { fillAlpha = 1; } + + if (fillColor === undefined) + { + this.showAltCells = false; + } + else + { + this.altFillColor = fillColor; + this.altFillAlpha = fillAlpha; + this.showAltCells = true; + } + + return this; + }, + + /** + * Sets the cell padding for the grid. + * The cell padding is the space around each cell, between the cells. + * The effective gutter between cells is twice this value. + * + * If this method is called with no value then the cell padding is set to zero. + * + * This call can be chained. + * + * @method Phaser.GameObjects.Grid#setCellPadding + * @since 4.0.0 + * @param {number} [value] - The cell padding value. + * @return {this} This Game Object instance. + */ + setCellPadding: function (value) + { + this.cellPadding = value || 0; + + return this; + }, + + /** + * Sets how to stroke the outside of the Grid object. + * + * This call can be chained. + * + * @method Phaser.GameObjects.Grid#setStrokeOutside + * @since 4.0.0 + * @param {boolean} strokeOutside - Whether to stroke the outside edges of the Grid object. + * @param {boolean} [strokeOutsideIncomplete] - Whether to stroke the outside edges of the Grid object when the cell is incomplete. + */ + setStrokeOutside: function (strokeOutside, strokeOutsideIncomplete) + { + this.strokeOutside = strokeOutside; + + if (strokeOutsideIncomplete !== undefined) + { + this.strokeOutsideIncomplete = strokeOutsideIncomplete; + } + + return this; + } + +}); + +module.exports = Grid; + + +/***/ }), + +/***/ 49912: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Grid#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Grid} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var GridCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = -src._displayOriginX; + var dy = -src._displayOriginY; + + var alpha = camera.alpha * src.alpha; + + // Work out the grid size + + var width = src.width; + var height = src.height; + + var cellWidth = src.cellWidth; + var cellHeight = src.cellHeight; + + var gridWidth = Math.ceil(width / cellWidth); + var gridHeight = Math.ceil(height / cellHeight); + + var cellWidthA = cellWidth; + var cellHeightA = cellHeight; + + var cellWidthB = cellWidth - ((gridWidth * cellWidth) - width); + var cellHeightB = cellHeight - ((gridHeight * cellHeight) - height); + + var showCells = src.isFilled; + var showAltCells = src.showAltCells; + var showOutline = src.isStroked; + + var cellPadding = src.cellPadding; + + var lineWidth = src.lineWidth; + var halfLineWidth = lineWidth / 2; + + var x = 0; + var y = 0; + var r = 0; + var cw = 0; + var ch = 0; + + if (cellPadding) + { + cellWidthA -= cellPadding * 2; + cellHeightA -= cellPadding * 2; + + + cellWidthB -= cellPadding * 2; + cellHeightB -= cellPadding * 2; + } + + if (showCells && src.fillAlpha > 0) + { + FillStyleCanvas(ctx, src); + + for (y = 0; y < gridHeight; y++) + { + if (showAltCells) + { + r = y % 2; + } + + for (x = 0; x < gridWidth; x++) + { + if (showAltCells && r) + { + r = 0; + continue; + } + + r++; + + cw = (x < gridWidth - 1) ? cellWidthA : cellWidthB; + ch = (y < gridHeight - 1) ? cellHeightA : cellHeightB; + + if (cw > 0 && ch > 0) + { + ctx.fillRect( + dx + x * cellWidth + cellPadding, + dy + y * cellHeight + cellPadding, + cw, + ch + ); + } + } + } + } + + if (showAltCells && src.altFillAlpha > 0) + { + FillStyleCanvas(ctx, src, src.altFillColor, src.altFillAlpha * alpha); + + for (y = 0; y < gridHeight; y++) + { + if (showAltCells) + { + r = y % 2; + } + + for (x = 0; x < gridWidth; x++) + { + if (showAltCells && !r) + { + r = 1; + continue; + } + + r = 0; + + cw = (x < gridWidth - 1) ? cellWidthA : cellWidthB; + ch = (y < gridHeight - 1) ? cellHeightA : cellHeightB; + + if (cw > 0 && ch > 0) + { + ctx.fillRect( + dx + x * cellWidth + cellPadding, + dy + y * cellHeight + cellPadding, + cw, + ch + ); + } + } + } + } + + if (showOutline && src.strokeAlpha > 0) + { + LineStyleCanvas(ctx, src, src.strokeColor, src.strokeAlpha * alpha); + + var start = src.strokeOutside ? 0 : 1; + + for (x = start; x < gridWidth; x++) + { + var x1 = x * cellWidth; + + ctx.beginPath(); + + ctx.moveTo(x1 + dx, dy); + ctx.lineTo(x1 + dx, height + dy); + + ctx.stroke(); + } + + for (y = start; y < gridHeight; y++) + { + var y1 = y * cellHeight; + + ctx.beginPath(); + + ctx.moveTo(dx, y1 + dy); + ctx.lineTo(dx + width, y1 + dy); + + ctx.stroke(); + } + + // Render remaining outer strokes. + if (src.strokeOutside) + { + if (width > halfLineWidth) + { + ctx.beginPath(); + + ctx.moveTo(width + dx, dy); + ctx.lineTo(width + dx, height + dy); + + ctx.stroke(); + } + + if (height > halfLineWidth) + { + ctx.beginPath(); + + ctx.moveTo(dx, height + dy); + ctx.lineTo(width + dx, height + dy); + + ctx.stroke(); + } + } + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = GridCanvasRenderer; + + +/***/ }), + +/***/ 34137: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Grid = __webpack_require__(30479); + +/** + * Creates a new Grid Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Grid Game Object has been built into Phaser. + * + * The Grid Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only fill colors and cannot be stroked. + * + * A Grid Shape allows you to display a grid in your game, where you can control the size of the + * grid as well as the width and height of the grid cells. You can set a fill color for each grid + * cell as well as an alternate fill color. When the alternate fill color is set then the grid + * cells will alternate the fill colors as they render, creating a chess-board effect. You can + * also optionally have an outline fill color. If set, this draws lines between the grid cells + * in the given color. If you specify an outline color with an alpha of zero, then it will draw + * the cells spaced out, but without the lines between them. + * + * @method Phaser.GameObjects.GameObjectFactory#grid + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the grid. + * @param {number} [height=128] - The height of the grid. + * @param {number} [cellWidth=32] - The width of one cell in the grid. + * @param {number} [cellHeight=32] - The height of one cell in the grid. + * @param {number} [fillColor] - The color the grid cells will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the grid cells will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * @param {number} [outlineFillColor] - The color of the lines between the grid cells. + * @param {number} [outlineFillAlpha] - The alpha of the lines between the grid cells. + * + * @return {Phaser.GameObjects.Grid} The Game Object that was created. + */ +GameObjectFactory.register('grid', function (x, y, width, height, cellWidth, cellHeight, fillColor, fillAlpha, outlineFillColor, outlineFillAlpha) +{ + return this.displayList.add(new Grid(this.scene, x, y, width, height, cellWidth, cellHeight, fillColor, fillAlpha, outlineFillColor, outlineFillAlpha)); +}); + + +/***/ }), + +/***/ 26015: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(46161); +} + +if (true) +{ + renderCanvas = __webpack_require__(49912); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 46161: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Grid#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Grid} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var GridWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var fillRectNode = src.customRenderNodes.FillRect || src.defaultRenderNodes.FillRect; + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + calcMatrix.translate(-src._displayOriginX, -src._displayOriginY); + + var alpha = src.alpha; + + // Work out the grid size + + var width = src.width; + var height = src.height; + + var cellWidth = src.cellWidth; + var cellHeight = src.cellHeight; + + var gridWidth = Math.ceil(width / cellWidth); + var gridHeight = Math.ceil(height / cellHeight); + + var cellWidthA = cellWidth; + var cellHeightA = cellHeight; + + var cellWidthB = cellWidth - ((gridWidth * cellWidth) - width); + var cellHeightB = cellHeight - ((gridHeight * cellHeight) - height); + + var fillTintColor; + + var showCells = src.isFilled; + var showAltCells = src.showAltCells; + var showOutline = src.isStroked; + + var cellPadding = src.cellPadding; + + var lineWidth = src.lineWidth; + var halfLineWidth = lineWidth / 2; + + var x = 0; + var y = 0; + var r = 0; + var cw = 0; + var ch = 0; + + if (cellPadding) + { + cellWidthA -= cellPadding * 2; + cellHeightA -= cellPadding * 2; + + cellWidthB -= cellPadding * 2; + cellHeightB -= cellPadding * 2; + } + + if (showCells && src.fillAlpha > 0) + { + fillTintColor = Utils.getTintAppendFloatAlpha(src.fillColor, src.fillAlpha * alpha); + + for (y = 0; y < gridHeight; y++) + { + if (showAltCells) + { + r = y % 2; + } + + for (x = 0; x < gridWidth; x++) + { + if (showAltCells && r) + { + r = 0; + continue; + } + + r++; + + cw = (x < gridWidth - 1) ? cellWidthA : cellWidthB; + ch = (y < gridHeight - 1) ? cellHeightA : cellHeightB; + + if (cw > 0 && ch > 0) + { + fillRectNode.run( + drawingContext, + calcMatrix, + submitterNode, + x * cellWidth + cellPadding, y * cellHeight + cellPadding, + cw, ch, + fillTintColor, fillTintColor, fillTintColor, fillTintColor + ); + } + } + } + } + + if (showAltCells && src.altFillAlpha > 0) + { + fillTintColor = Utils.getTintAppendFloatAlpha(src.altFillColor, src.altFillAlpha * alpha); + + for (y = 0; y < gridHeight; y++) + { + if (showAltCells) + { + r = y % 2; + } + + for (x = 0; x < gridWidth; x++) + { + if (showAltCells && !r) + { + r = 1; + continue; + } + + r = 0; + + cw = (x < gridWidth - 1) ? cellWidthA : cellWidthB; + ch = (y < gridHeight - 1) ? cellHeightA : cellHeightB; + + if (cw > 0 && ch > 0) + { + fillRectNode.run( + drawingContext, + calcMatrix, + submitterNode, + x * cellWidth + cellPadding, y * cellHeight + cellPadding, + cw, ch, + fillTintColor, fillTintColor, fillTintColor, fillTintColor + ); + } + } + } + } + + if (showOutline && src.strokeAlpha > 0) + { + var color = Utils.getTintAppendFloatAlpha(src.strokeColor, src.strokeAlpha * alpha); + + var start = src.strokeOutside ? 0 : 1; + + for (x = start; x < gridWidth; x++) + { + var x1 = x * cellWidth - halfLineWidth; + + fillRectNode.run( + drawingContext, + calcMatrix, + submitterNode, + x1, 0, + lineWidth, height, + color, color, color, color + ); + } + + for (y = start; y < gridHeight; y++) + { + var y1 = y * cellHeight - halfLineWidth; + + fillRectNode.run( + drawingContext, + calcMatrix, + submitterNode, + 0, y1, + width, lineWidth, + color, color, color, color + ); + } + + // Render remaining outer strokes. + if (src.strokeOutside && src.strokeOutsideIncomplete) + { + if (width > halfLineWidth) + { + fillRectNode.run( + drawingContext, + calcMatrix, + submitterNode, + width - halfLineWidth, 0, + lineWidth, height, + color, color, color, color + ); + } + + if (height > halfLineWidth) + { + fillRectNode.run( + drawingContext, + calcMatrix, + submitterNode, + 0, height - halfLineWidth, + width, lineWidth, + color, color, color, color + ); + } + } + } +}; + +module.exports = GridWebGLRenderer; + + +/***/ }), + +/***/ 61475: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var IsoBoxRender = __webpack_require__(99651); +var Class = __webpack_require__(83419); +var Shape = __webpack_require__(17803); + +/** + * @classdesc + * The IsoBox Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only fill colors and cannot be stroked. + * + * An IsoBox is an 'isometric' rectangle. Each face of it has a different fill color. You can set + * the color of the top, left and right faces of the rectangle respectively. You can also choose + * which of the faces are rendered via the `showTop`, `showLeft` and `showRight` properties. + * + * You cannot view an IsoBox from under-neath, however you can change the 'angle' by setting + * the `projection` property. + * + * @class IsoBox + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [size=48] - The width of the iso box in pixels. The left and right faces will be exactly half this value. + * @param {number} [height=32] - The height of the iso box. The left and right faces will be this tall. The overall height of the isobox will be this value plus half the `size` value. + * @param {number} [fillTop=0xeeeeee] - The fill color of the top face of the iso box. + * @param {number} [fillLeft=0x999999] - The fill color of the left face of the iso box. + * @param {number} [fillRight=0xcccccc] - The fill color of the right face of the iso box. + */ +var IsoBox = new Class({ + + Extends: Shape, + + Mixins: [ + IsoBoxRender + ], + + initialize: + + function IsoBox (scene, x, y, size, height, fillTop, fillLeft, fillRight) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (size === undefined) { size = 48; } + if (height === undefined) { height = 32; } + if (fillTop === undefined) { fillTop = 0xeeeeee; } + if (fillLeft === undefined) { fillLeft = 0x999999; } + if (fillRight === undefined) { fillRight = 0xcccccc; } + + Shape.call(this, scene, 'IsoBox', null); + + /** + * The projection level of the iso box. Change this to change the 'angle' at which you are looking at the box. + * + * @name Phaser.GameObjects.IsoBox#projection + * @type {number} + * @default 4 + * @since 3.13.0 + */ + this.projection = 4; + + /** + * The color used to fill in the top of the iso box. + * + * @name Phaser.GameObjects.IsoBox#fillTop + * @type {number} + * @since 3.13.0 + */ + this.fillTop = fillTop; + + /** + * The color used to fill in the left-facing side of the iso box. + * + * @name Phaser.GameObjects.IsoBox#fillLeft + * @type {number} + * @since 3.13.0 + */ + this.fillLeft = fillLeft; + + /** + * The color used to fill in the right-facing side of the iso box. + * + * @name Phaser.GameObjects.IsoBox#fillRight + * @type {number} + * @since 3.13.0 + */ + this.fillRight = fillRight; + + /** + * Controls if the top-face of the iso box be rendered. + * + * @name Phaser.GameObjects.IsoBox#showTop + * @type {boolean} + * @default true + * @since 3.13.0 + */ + this.showTop = true; + + /** + * Controls if the left-face of the iso box be rendered. + * + * @name Phaser.GameObjects.IsoBox#showLeft + * @type {boolean} + * @default true + * @since 3.13.0 + */ + this.showLeft = true; + + /** + * Controls if the right-face of the iso box be rendered. + * + * @name Phaser.GameObjects.IsoBox#showRight + * @type {boolean} + * @default true + * @since 3.13.0 + */ + this.showRight = true; + + this.isFilled = true; + + this.setPosition(x, y); + this.setSize(size, height); + + this.updateDisplayOrigin(); + }, + + /** + * Sets the projection level of the iso box. Change this to change the 'angle' at which you are looking at the box. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoBox#setProjection + * @since 3.13.0 + * + * @param {number} value - The value to set the projection to. + * + * @return {this} This Game Object instance. + */ + setProjection: function (value) + { + this.projection = value; + + return this; + }, + + /** + * Sets which faces of the iso box will be rendered. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoBox#setFaces + * @since 3.13.0 + * + * @param {boolean} [showTop=true] - Show the top-face of the iso box. + * @param {boolean} [showLeft=true] - Show the left-face of the iso box. + * @param {boolean} [showRight=true] - Show the right-face of the iso box. + * + * @return {this} This Game Object instance. + */ + setFaces: function (showTop, showLeft, showRight) + { + if (showTop === undefined) { showTop = true; } + if (showLeft === undefined) { showLeft = true; } + if (showRight === undefined) { showRight = true; } + + this.showTop = showTop; + this.showLeft = showLeft; + this.showRight = showRight; + + return this; + }, + + /** + * Sets the fill colors for each face of the iso box. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoBox#setFillStyle + * @since 3.13.0 + * + * @param {number} [fillTop] - The color used to fill the top of the iso box. + * @param {number} [fillLeft] - The color used to fill in the left-facing side of the iso box. + * @param {number} [fillRight] - The color used to fill in the right-facing side of the iso box. + * + * @return {this} This Game Object instance. + */ + setFillStyle: function (fillTop, fillLeft, fillRight) + { + this.fillTop = fillTop; + this.fillLeft = fillLeft; + this.fillRight = fillRight; + + this.isFilled = true; + + return this; + } + +}); + +module.exports = IsoBox; + + +/***/ }), + +/***/ 11508: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.IsoBox#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.IsoBox} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var IsoBoxCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix) && src.isFilled) + { + var size = src.width; + var height = src.height; + + var sizeA = size / 2; + var sizeB = size / src.projection; + + // Top Face + + if (src.showTop) + { + FillStyleCanvas(ctx, src, src.fillTop); + + ctx.beginPath(); + + ctx.moveTo(-sizeA, -height); + ctx.lineTo(0, -sizeB - height); + ctx.lineTo(sizeA, -height); + ctx.lineTo(sizeA, -1); + ctx.lineTo(0, sizeB - 1); + ctx.lineTo(-sizeA, -1); + ctx.lineTo(-sizeA, -height); + + ctx.fill(); + } + + // Left Face + + if (src.showLeft) + { + FillStyleCanvas(ctx, src, src.fillLeft); + + ctx.beginPath(); + + ctx.moveTo(-sizeA, 0); + ctx.lineTo(0, sizeB); + ctx.lineTo(0, sizeB - height); + ctx.lineTo(-sizeA, -height); + ctx.lineTo(-sizeA, 0); + + ctx.fill(); + } + + // Right Face + + if (src.showRight) + { + FillStyleCanvas(ctx, src, src.fillRight); + + ctx.beginPath(); + + ctx.moveTo(sizeA, 0); + ctx.lineTo(0, sizeB); + ctx.lineTo(0, sizeB - height); + ctx.lineTo(sizeA, -height); + ctx.lineTo(sizeA, 0); + + ctx.fill(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = IsoBoxCanvasRenderer; + + +/***/ }), + +/***/ 3933: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var IsoBox = __webpack_require__(61475); + +/** + * Creates a new IsoBox Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the IsoBox Game Object has been built into Phaser. + * + * The IsoBox Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only fill colors and cannot be stroked. + * + * An IsoBox is an 'isometric' rectangle. Each face of it has a different fill color. You can set + * the color of the top, left and right faces of the rectangle respectively. You can also choose + * which of the faces are rendered via the `showTop`, `showLeft` and `showRight` properties. + * + * You cannot view an IsoBox from under-neath, however you can change the 'angle' by setting + * the `projection` property. + * + * @method Phaser.GameObjects.GameObjectFactory#isobox + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [size=48] - The width of the iso box in pixels. The left and right faces will be exactly half this value. + * @param {number} [height=32] - The height of the iso box. The left and right faces will be this tall. The overall height of the isobox will be this value plus half the `size` value. + * @param {number} [fillTop=0xeeeeee] - The fill color of the top face of the iso box. + * @param {number} [fillLeft=0x999999] - The fill color of the left face of the iso box. + * @param {number} [fillRight=0xcccccc] - The fill color of the right face of the iso box. + * + * @return {Phaser.GameObjects.IsoBox} The Game Object that was created. + */ +GameObjectFactory.register('isobox', function (x, y, size, height, fillTop, fillLeft, fillRight) +{ + return this.displayList.add(new IsoBox(this.scene, x, y, size, height, fillTop, fillLeft, fillRight)); +}); + + +/***/ }), + +/***/ 99651: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(68149); +} + +if (true) +{ + renderCanvas = __webpack_require__(11508); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 68149: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.IsoBox#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.IsoBox} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var IsoBoxWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + if (!src.isFilled) + { + return; + } + + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var fillTriNode = src.customRenderNodes.FillTri || src.defaultRenderNodes.FillTri; + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var size = src.width; + var height = src.height; + + var sizeA = size / 2; + var sizeB = size / src.projection; + + var alpha = src.alpha; + + var tint; + + var x0; + var y0; + + var x1; + var y1; + + var x2; + var y2; + + var x3; + var y3; + + // Top Face + + if (src.showTop) + { + tint = Utils.getTintAppendFloatAlpha(src.fillTop, alpha); + + x0 = -sizeA; + y0 = -height; + + x1 = 0; + y1 = -sizeB - height; + + x2 = sizeA; + y2 = -height; + + x3 = 0; + y3 = sizeB - height; + + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x0, y0, x1, y1, x2, y2, tint, tint, tint); + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x2, y2, x3, y3, x0, y0, tint, tint, tint); + } + + // Left Face + + if (src.showLeft) + { + tint = Utils.getTintAppendFloatAlpha(src.fillLeft, alpha); + + x0 = -sizeA; + y0 = 0; + + x1 = 0; + y1 = sizeB; + + x2 = 0; + y2 = sizeB - height; + + x3 = -sizeA; + y3 = -height; + + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x0, y0, x1, y1, x2, y2, tint, tint, tint); + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x2, y2, x3, y3, x0, y0, tint, tint, tint); + } + + // Right Face + + if (src.showRight) + { + tint = Utils.getTintAppendFloatAlpha(src.fillRight, alpha); + + x0 = sizeA; + y0 = 0; + + x1 = 0; + y1 = sizeB; + + x2 = 0; + y2 = sizeB - height; + + x3 = sizeA; + y3 = -height; + + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x0, y0, x1, y1, x2, y2, tint, tint, tint); + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x2, y2, x3, y3, x0, y0, tint, tint, tint); + } +}; + +module.exports = IsoBoxWebGLRenderer; + + +/***/ }), + +/***/ 16933: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var IsoTriangleRender = __webpack_require__(60561); +var Shape = __webpack_require__(17803); + +/** + * @classdesc + * The IsoTriangle Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only fill colors and cannot be stroked. + * + * An IsoTriangle is an 'isometric' triangle. Think of it like a pyramid. Each face has a different + * fill color. You can set the color of the top, left and right faces of the triangle respectively + * You can also choose which of the faces are rendered via the `showTop`, `showLeft` and `showRight` properties. + * + * You cannot view an IsoTriangle from under-neath, however you can change the 'angle' by setting + * the `projection` property. The `reversed` property controls if the IsoTriangle is rendered upside + * down or not. + * + * @class IsoTriangle + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [size=48] - The width of the iso triangle in pixels. The left and right faces will be exactly half this value. + * @param {number} [height=32] - The height of the iso triangle. The left and right faces will be this tall. The overall height of the iso triangle will be this value plus half the `size` value. + * @param {boolean} [reversed=false] - Is the iso triangle upside down? + * @param {number} [fillTop=0xeeeeee] - The fill color of the top face of the iso triangle. + * @param {number} [fillLeft=0x999999] - The fill color of the left face of the iso triangle. + * @param {number} [fillRight=0xcccccc] - The fill color of the right face of the iso triangle. + */ +var IsoTriangle = new Class({ + + Extends: Shape, + + Mixins: [ + IsoTriangleRender + ], + + initialize: + + function IsoTriangle (scene, x, y, size, height, reversed, fillTop, fillLeft, fillRight) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (size === undefined) { size = 48; } + if (height === undefined) { height = 32; } + if (reversed === undefined) { reversed = false; } + if (fillTop === undefined) { fillTop = 0xeeeeee; } + if (fillLeft === undefined) { fillLeft = 0x999999; } + if (fillRight === undefined) { fillRight = 0xcccccc; } + + Shape.call(this, scene, 'IsoTriangle', null); + + /** + * The projection level of the iso box. Change this to change the 'angle' at which you are looking at the box. + * + * @name Phaser.GameObjects.IsoTriangle#projection + * @type {number} + * @default 4 + * @since 3.13.0 + */ + this.projection = 4; + + /** + * The color used to fill in the top of the iso triangle. This is only used if the triangle is reversed. + * + * @name Phaser.GameObjects.IsoTriangle#fillTop + * @type {number} + * @since 3.13.0 + */ + this.fillTop = fillTop; + + /** + * The color used to fill in the left-facing side of the iso triangle. + * + * @name Phaser.GameObjects.IsoTriangle#fillLeft + * @type {number} + * @since 3.13.0 + */ + this.fillLeft = fillLeft; + + /** + * The color used to fill in the right-facing side of the iso triangle. + * + * @name Phaser.GameObjects.IsoTriangle#fillRight + * @type {number} + * @since 3.13.0 + */ + this.fillRight = fillRight; + + /** + * Controls if the top-face of the iso triangle be rendered. + * + * @name Phaser.GameObjects.IsoTriangle#showTop + * @type {boolean} + * @default true + * @since 3.13.0 + */ + this.showTop = true; + + /** + * Controls if the left-face of the iso triangle be rendered. + * + * @name Phaser.GameObjects.IsoTriangle#showLeft + * @type {boolean} + * @default true + * @since 3.13.0 + */ + this.showLeft = true; + + /** + * Controls if the right-face of the iso triangle be rendered. + * + * @name Phaser.GameObjects.IsoTriangle#showRight + * @type {boolean} + * @default true + * @since 3.13.0 + */ + this.showRight = true; + + /** + * Sets if the iso triangle will be rendered upside down or not. + * + * @name Phaser.GameObjects.IsoTriangle#isReversed + * @type {boolean} + * @default false + * @since 3.13.0 + */ + this.isReversed = reversed; + + this.isFilled = true; + + this.setPosition(x, y); + this.setSize(size, height); + + this.updateDisplayOrigin(); + }, + + /** + * Sets the projection level of the iso triangle. Change this to change the 'angle' at which you are looking at the pyramid. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoTriangle#setProjection + * @since 3.13.0 + * + * @param {number} value - The value to set the projection to. + * + * @return {this} This Game Object instance. + */ + setProjection: function (value) + { + this.projection = value; + + return this; + }, + + /** + * Sets if the iso triangle will be rendered upside down or not. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoTriangle#setReversed + * @since 3.13.0 + * + * @param {boolean} reversed - Sets if the iso triangle will be rendered upside down or not. + * + * @return {this} This Game Object instance. + */ + setReversed: function (reversed) + { + this.isReversed = reversed; + + return this; + }, + + /** + * Sets which faces of the iso triangle will be rendered. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoTriangle#setFaces + * @since 3.13.0 + * + * @param {boolean} [showTop=true] - Show the top-face of the iso triangle (only if `reversed` is true) + * @param {boolean} [showLeft=true] - Show the left-face of the iso triangle. + * @param {boolean} [showRight=true] - Show the right-face of the iso triangle. + * + * @return {this} This Game Object instance. + */ + setFaces: function (showTop, showLeft, showRight) + { + if (showTop === undefined) { showTop = true; } + if (showLeft === undefined) { showLeft = true; } + if (showRight === undefined) { showRight = true; } + + this.showTop = showTop; + this.showLeft = showLeft; + this.showRight = showRight; + + return this; + }, + + /** + * Sets the fill colors for each face of the iso triangle. + * This call can be chained. + * + * @method Phaser.GameObjects.IsoTriangle#setFillStyle + * @since 3.13.0 + * + * @param {number} [fillTop] - The color used to fill the top of the iso triangle. + * @param {number} [fillLeft] - The color used to fill in the left-facing side of the iso triangle. + * @param {number} [fillRight] - The color used to fill in the right-facing side of the iso triangle. + * + * @return {this} This Game Object instance. + */ + setFillStyle: function (fillTop, fillLeft, fillRight) + { + this.fillTop = fillTop; + this.fillLeft = fillLeft; + this.fillRight = fillRight; + + this.isFilled = true; + + return this; + } + +}); + +module.exports = IsoTriangle; + + +/***/ }), + +/***/ 79590: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.IsoTriangle#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.IsoTriangle} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var IsoTriangleCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix) && src.isFilled) + { + var size = src.width; + var height = src.height; + + var sizeA = size / 2; + var sizeB = size / src.projection; + + var reversed = src.isReversed; + + // Top Face + + if (src.showTop && reversed) + { + FillStyleCanvas(ctx, src, src.fillTop); + + ctx.beginPath(); + + ctx.moveTo(-sizeA, -height); + ctx.lineTo(0, -sizeB - height); + ctx.lineTo(sizeA, -height); + ctx.lineTo(0, sizeB - height); + + ctx.fill(); + } + + // Left Face + + if (src.showLeft) + { + FillStyleCanvas(ctx, src, src.fillLeft); + + ctx.beginPath(); + + if (reversed) + { + ctx.moveTo(-sizeA, -height); + ctx.lineTo(0, sizeB); + ctx.lineTo(0, sizeB - height); + } + else + { + ctx.moveTo(-sizeA, 0); + ctx.lineTo(0, sizeB); + ctx.lineTo(0, sizeB - height); + } + + ctx.fill(); + } + + // Right Face + + if (src.showRight) + { + FillStyleCanvas(ctx, src, src.fillRight); + + ctx.beginPath(); + + if (reversed) + { + ctx.moveTo(sizeA, -height); + ctx.lineTo(0, sizeB); + ctx.lineTo(0, sizeB - height); + } + else + { + ctx.moveTo(sizeA, 0); + ctx.lineTo(0, sizeB); + ctx.lineTo(0, sizeB - height); + } + + ctx.fill(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = IsoTriangleCanvasRenderer; + + +/***/ }), + +/***/ 49803: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var IsoTriangle = __webpack_require__(16933); + +/** + * Creates a new IsoTriangle Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the IsoTriangle Game Object has been built into Phaser. + * + * The IsoTriangle Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only fill colors and cannot be stroked. + * + * An IsoTriangle is an 'isometric' triangle. Think of it like a pyramid. Each face has a different + * fill color. You can set the color of the top, left and right faces of the triangle respectively + * You can also choose which of the faces are rendered via the `showTop`, `showLeft` and `showRight` properties. + * + * You cannot view an IsoTriangle from under-neath, however you can change the 'angle' by setting + * the `projection` property. The `reversed` property controls if the IsoTriangle is rendered upside + * down or not. + * + * @method Phaser.GameObjects.GameObjectFactory#isotriangle + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [size=48] - The width of the iso triangle in pixels. The left and right faces will be exactly half this value. + * @param {number} [height=32] - The height of the iso triangle. The left and right faces will be this tall. The overall height of the iso triangle will be this value plus half the `size` value. + * @param {boolean} [reversed=false] - Is the iso triangle upside down? + * @param {number} [fillTop=0xeeeeee] - The fill color of the top face of the iso triangle. + * @param {number} [fillLeft=0x999999] - The fill color of the left face of the iso triangle. + * @param {number} [fillRight=0xcccccc] - The fill color of the right face of the iso triangle. + * + * @return {Phaser.GameObjects.IsoTriangle} The Game Object that was created. + */ +GameObjectFactory.register('isotriangle', function (x, y, size, height, reversed, fillTop, fillLeft, fillRight) +{ + return this.displayList.add(new IsoTriangle(this.scene, x, y, size, height, reversed, fillTop, fillLeft, fillRight)); +}); + + +/***/ }), + +/***/ 60561: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(51503); +} + +if (true) +{ + renderCanvas = __webpack_require__(79590); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 51503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.IsoTriangle#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.IsoTriangle} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var IsoTriangleWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + if (!src.isFilled) + { + return; + } + + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var fillTriNode = src.customRenderNodes.FillTri || src.defaultRenderNodes.FillTri; + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var size = src.width; + var height = src.height; + + var sizeA = size / 2; + var sizeB = size / src.projection; + + var reversed = src.isReversed; + + var alpha = src.alpha; + + var tint; + + var x0; + var y0; + + var x1; + var y1; + + var x2; + var y2; + + // Top Face + + if (src.showTop && reversed) + { + tint = Utils.getTintAppendFloatAlpha(src.fillTop, alpha); + + x0 = -sizeA; + y0 = -height; + + x1 = 0; + y1 = -sizeB - height; + + x2 = sizeA; + y2 = -height; + + var x3 = 0; + var y3 = sizeB - height; + + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x0, y0, x1, y1, x2, y2, tint, tint, tint); + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x2, y2, x3, y3, x0, y0, tint, tint, tint); + } + + // Left Face + + if (src.showLeft) + { + tint = Utils.getTintAppendFloatAlpha(src.fillLeft, alpha); + + if (reversed) + { + x0 = -sizeA; + y0 = -height; + + x1 = 0; + y1 = sizeB; + + x2 = 0; + y2 = sizeB - height; + } + else + { + x0 = -sizeA; + y0 = 0; + + x1 = 0; + y1 = sizeB; + + x2 = 0; + y2 = sizeB - height; + } + + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x0, y0, x1, y1, x2, y2, tint, tint, tint); + } + + // Right Face + + if (src.showRight) + { + tint = Utils.getTintAppendFloatAlpha(src.fillRight, alpha); + + if (reversed) + { + x0 = sizeA; + y0 = -height; + + x1 = 0; + y1 = sizeB; + + x2 = 0; + y2 = sizeB - height; + } + else + { + x0 = sizeA; + y0 = 0; + + x1 = 0; + y1 = sizeB; + + x2 = 0; + y2 = sizeB - height; + } + + fillTriNode.run(drawingContext, calcMatrix, submitterNode, x0, y0, x1, y1, x2, y2, tint, tint, tint); + } +}; + +module.exports = IsoTriangleWebGLRenderer; + + +/***/ }), + +/***/ 57847: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Shape = __webpack_require__(17803); +var GeomLine = __webpack_require__(23031); +var LineRender = __webpack_require__(36823); + +/** + * @classdesc + * The Line Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only stroke colors and cannot be filled. + * + * A Line Shape allows you to draw a line between two points in your game. You can control the + * stroke color and thickness of the line. In WebGL only you can also specify a different + * thickness for the start and end of the line, allowing you to render lines that taper-off. + * + * If you need to draw multiple lines in a sequence you may wish to use the Polygon Shape instead. + * + * Be aware that as with all Game Objects the default origin is 0.5. If you need to draw a Line + * between two points and want the x1/y1 values to match the x/y values, then set the origin to 0. + * + * @class Line + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [x1=0] - The horizontal position of the start of the line. + * @param {number} [y1=0] - The vertical position of the start of the line. + * @param {number} [x2=128] - The horizontal position of the end of the line. + * @param {number} [y2=0] - The vertical position of the end of the line. + * @param {number} [strokeColor] - The color the line will be drawn in, i.e. 0xff0000 for red. + * @param {number} [strokeAlpha] - The alpha the line will be drawn in. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Line = new Class({ + + Extends: Shape, + + Mixins: [ + LineRender + ], + + initialize: + + function Line (scene, x, y, x1, y1, x2, y2, strokeColor, strokeAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (x1 === undefined) { x1 = 0; } + if (y1 === undefined) { y1 = 0; } + if (x2 === undefined) { x2 = 128; } + if (y2 === undefined) { y2 = 0; } + + Shape.call(this, scene, 'Line', new GeomLine(x1, y1, x2, y2)); + + var width = Math.max(1, this.geom.right - this.geom.left); + var height = Math.max(1, this.geom.bottom - this.geom.top); + + /** + * The width (or thickness) of the line. + * See the setLineWidth method for extra details on changing this on WebGL. + * + * @name Phaser.GameObjects.Line#lineWidth + * @type {number} + * @since 3.13.0 + */ + this.lineWidth = 1; + + /** + * Private internal value. Holds the start width of the line. + * + * @name Phaser.GameObjects.Line#_startWidth + * @type {number} + * @private + * @since 3.13.0 + */ + this._startWidth = 1; + + /** + * Private internal value. Holds the end width of the line. + * + * @name Phaser.GameObjects.Line#_endWidth + * @type {number} + * @private + * @since 3.13.0 + */ + this._endWidth = 1; + + this.setPosition(x, y); + this.setSize(width, height); + + if (strokeColor !== undefined) + { + this.setStrokeStyle(1, strokeColor, strokeAlpha); + } + + this.updateDisplayOrigin(); + }, + + /** + * Sets the width of the line. + * + * When using the WebGL renderer you can have different start and end widths. + * When using the Canvas renderer only the `startWidth` value is used. The `endWidth` is ignored. + * + * This call can be chained. + * + * @method Phaser.GameObjects.Line#setLineWidth + * @since 3.13.0 + * + * @param {number} startWidth - The start width of the line. + * @param {number} [endWidth] - The end width of the line. Only used in WebGL. + * + * @return {this} This Game Object instance. + */ + setLineWidth: function (startWidth, endWidth) + { + if (endWidth === undefined) { endWidth = startWidth; } + + this._startWidth = startWidth; + this._endWidth = endWidth; + + this.lineWidth = startWidth; + + return this; + }, + + /** + * Sets the start and end coordinates of this Line. + * + * @method Phaser.GameObjects.Line#setTo + * @since 3.13.0 + * + * @param {number} [x1=0] - The horizontal position of the start of the line. + * @param {number} [y1=0] - The vertical position of the start of the line. + * @param {number} [x2=0] - The horizontal position of the end of the line. + * @param {number} [y2=0] - The vertical position of the end of the line. + * + * @return {this} This Line object. + */ + setTo: function (x1, y1, x2, y2) + { + this.geom.setTo(x1, y1, x2, y2); + + return this; + } + +}); + +module.exports = Line; + + +/***/ }), + +/***/ 17440: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Line#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Line} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var LineCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.beginPath(); + + ctx.moveTo(src.geom.x1 - dx, src.geom.y1 - dy); + ctx.lineTo(src.geom.x2 - dx, src.geom.y2 - dy); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = LineCanvasRenderer; + + +/***/ }), + +/***/ 2481: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Line = __webpack_require__(57847); + +/** + * Creates a new Line Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Line Game Object has been built into Phaser. + * + * The Line Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports only stroke colors and cannot be filled. + * + * A Line Shape allows you to draw a line between two points in your game. You can control the + * stroke color and thickness of the line. In WebGL only you can also specify a different + * thickness for the start and end of the line, allowing you to render lines that taper-off. + * + * If you need to draw multiple lines in a sequence you may wish to use the Polygon Shape instead. + * + * @method Phaser.GameObjects.GameObjectFactory#line + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [x1=0] - The horizontal position of the start of the line. + * @param {number} [y1=0] - The vertical position of the start of the line. + * @param {number} [x2=128] - The horizontal position of the end of the line. + * @param {number} [y2=0] - The vertical position of the end of the line. + * @param {number} [strokeColor] - The color the line will be drawn in, i.e. 0xff0000 for red. + * @param {number} [strokeAlpha] - The alpha the line will be drawn in. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Line} The Game Object that was created. + */ +GameObjectFactory.register('line', function (x, y, x1, y1, x2, y2, strokeColor, strokeAlpha) +{ + return this.displayList.add(new Line(this.scene, x, y, x1, y1, x2, y2, strokeColor, strokeAlpha)); +}); + + +/***/ }), + +/***/ 36823: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(77385); +} + +if (true) +{ + renderCanvas = __webpack_require__(17440); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 77385: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var Utils = __webpack_require__(70554); + +var tempPath = [ + { + x: 0, y: 0, width: 0 + }, + { + x: 0, y: 0, width: 0 + } +]; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Line#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Line} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var LineWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + var alpha = src.alpha; + + if (src.isStroked) + { + var color = Utils.getTintAppendFloatAlpha(src.strokeColor, src.strokeAlpha * alpha); + + tempPath[0].x = src.geom.x1 - dx; + tempPath[0].y = src.geom.y1 - dy; + tempPath[0].width = src._startWidth; + + tempPath[1].x = src.geom.x2 - dx; + tempPath[1].y = src.geom.y2 - dy; + tempPath[1].width = src._endWidth; + + (src.customRenderNodes.StrokePath || src.defaultRenderNodes.StrokePath).run( + drawingContext, + src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter, + tempPath, + 1, + true, + calcMatrix, + color, color, color, color + ); + } +}; + +module.exports = LineWebGLRenderer; + + +/***/ }), + +/***/ 24949: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PolygonRender = __webpack_require__(90273); +var Class = __webpack_require__(83419); +var Earcut = __webpack_require__(94811); +var GetAABB = __webpack_require__(13829); +var GeomPolygon = __webpack_require__(25717); +var Shape = __webpack_require__(17803); +var Smooth = __webpack_require__(5469); + +/** + * @classdesc + * The Polygon Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * The Polygon Shape is created by providing a list of points, which are then used to create an + * internal Polygon geometry object. The points can be set from a variety of formats: + * + * - A string containing paired values separated by a single space: `'40 0 40 20 100 20 100 80 40 80 40 100 0 50'` + * - An array of Point or Vector2 objects: `[new Phaser.Math.Vector2(x1, y1), ...]` + * - An array of objects with public x/y properties: `[obj1, obj2, ...]` + * - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]` + * - An array of arrays with two elements representing x/y coordinates: `[[x1, y1], [x2, y2], ...]` + * + * By default the `x` and `y` coordinates of this Shape refer to the center of it. However, depending + * on the coordinates of the points provided, the final shape may be rendered offset from its origin. + * + * Note: The method `getBounds` will return incorrect bounds if any of the points in the Polygon are negative. + * If this is the case, please use the function `Phaser.Geom.Polygon.GetAABB(polygon.geom)` instead and then + * adjust the returned Rectangle position accordingly. + * + * @class Polygon + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {any} [points] - The points that make up the polygon. + * @param {number} [fillColor] - The color the polygon will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the polygon will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Polygon = new Class({ + + Extends: Shape, + + Mixins: [ + PolygonRender + ], + + initialize: + + function Polygon (scene, x, y, points, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + Shape.call(this, scene, 'Polygon', new GeomPolygon(points)); + + var bounds = GetAABB(this.geom); + + this.setPosition(x, y); + this.setSize(bounds.width, bounds.height); + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateDisplayOrigin(); + this.updateData(); + }, + + /** + * Smooths the polygon over the number of iterations specified. + * The base polygon data will be updated and replaced with the smoothed values. + * This call can be chained. + * + * @method Phaser.GameObjects.Polygon#smooth + * @since 3.13.0 + * + * @param {number} [iterations=1] - The number of times to apply the polygon smoothing. + * + * @return {this} This Game Object instance. + */ + smooth: function (iterations) + { + if (iterations === undefined) { iterations = 1; } + + for (var i = 0; i < iterations; i++) + { + Smooth(this.geom); + } + + return this.updateData(); + }, + + /** + * Sets this Polygon to the given points. + * + * The points can be set from a variety of formats: + * + * - A string containing paired values separated by a single space: `'40 0 40 20 100 20 100 80 40 80 40 100 0 50'` + * - An array of Point objects: `[new Phaser.Point(x1, y1), ...]` + * - An array of objects with public x/y properties: `[obj1, obj2, ...]` + * - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]` + * - An array of arrays with two elements representing x/y coordinates: `[[x1, y1], [x2, y2], ...]` + * + * Calling this method will reset the size (width, height) and display origin of this Shape. + * + * It also runs both GetAABB and EarCut on the given points, so please be careful not to do this + * at a high frequency, or with too many points. + * + * @method Phaser.GameObjects.Polygon#setTo + * @since 3.60.0 + * + * @param {(string|number[]|Phaser.Types.Math.Vector2Like[])} [points] - Points defining the perimeter of this polygon. Please check function description above for the different supported formats. + * + * @return {this} This Game Object instance. + */ + setTo: function (points) + { + this.geom.setTo(points); + + var bounds = GetAABB(this.geom); + + this.setSize(bounds.width, bounds.height); + + this.updateDisplayOrigin(); + + return this.updateData(); + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Polygon#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + var path = []; + var points = this.geom.points; + + for (var i = 0; i < points.length; i++) + { + path.push(points[i].x, points[i].y); + } + + path.push(points[0].x, points[0].y); + + this.pathIndexes = Earcut(path); + this.pathData = path; + + return this; + } + +}); + +module.exports = Polygon; + + +/***/ }), + +/***/ 38710: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Polygon#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Polygon} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var PolygonCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var path = src.pathData; + var pathLength = path.length - 1; + + var px1 = path[0] - dx; + var py1 = path[1] - dy; + + ctx.beginPath(); + + ctx.moveTo(px1, py1); + + if (!src.closePath) + { + pathLength -= 2; + } + + for (var i = 2; i < pathLength; i += 2) + { + var px2 = path[i] - dx; + var py2 = path[i + 1] - dy; + + ctx.lineTo(px2, py2); + } + + if (src.closePath) + { + ctx.closePath(); + } + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + ctx.fill(); + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = PolygonCanvasRenderer; + + +/***/ }), + +/***/ 64827: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Polygon = __webpack_require__(24949); + +/** + * Creates a new Polygon Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Polygon Game Object has been built into Phaser. + * + * The Polygon Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * The Polygon Shape is created by providing a list of points, which are then used to create an + * internal Polygon geometry object. The points can be set from a variety of formats: + * + * - An array of Point or Vector2 objects: `[new Phaser.Math.Vector2(x1, y1), ...]` + * - An array of objects with public x/y properties: `[obj1, obj2, ...]` + * - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]` + * - An array of arrays with two elements representing x/y coordinates: `[[x1, y1], [x2, y2], ...]` + * + * By default the `x` and `y` coordinates of this Shape refer to the center of it. However, depending + * on the coordinates of the points provided, the final shape may be rendered offset from its origin. + * + * @method Phaser.GameObjects.GameObjectFactory#polygon + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {any} [points] - The points that make up the polygon. + * @param {number} [fillColor] - The color the polygon will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the polygon will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Polygon} The Game Object that was created. + */ +GameObjectFactory.register('polygon', function (x, y, points, fillColor, fillAlpha) +{ + return this.displayList.add(new Polygon(this.scene, x, y, points, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 90273: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(73695); +} + +if (true) +{ + renderCanvas = __webpack_require__(38710); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 73695: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillPathWebGL = __webpack_require__(10441); +var GetCalcMatrix = __webpack_require__(91296); +var StrokePathWebGL = __webpack_require__(34682); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Polygon#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Polygon} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var PolygonWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var alpha = src.alpha; + + var submitter = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + if (src.isFilled) + { + FillPathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = PolygonWebGLRenderer; + + +/***/ }), + +/***/ 74561: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Earcut = __webpack_require__(94811); +var GeomRectangle = __webpack_require__(87841); +var Shape = __webpack_require__(17803); +var RectangleRender = __webpack_require__(95597); + +/** + * @classdesc + * The Rectangle Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * You can change the size of the rectangle by changing the `width` and `height` properties. + * + * @class Rectangle + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the rectangle. + * @param {number} [height=128] - The height of the rectangle. + * @param {number} [fillColor] - The color the rectangle will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the rectangle will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Rectangle = new Class({ + + Extends: Shape, + + Mixins: [ + RectangleRender + ], + + initialize: + + function Rectangle (scene, x, y, width, height, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 128; } + if (height === undefined) { height = 128; } + + Shape.call(this, scene, 'Rectangle', new GeomRectangle(0, 0, width, height)); + + /** + * The radius of the rectangle if this is set to use rounded corners. + * + * Do not modify this property. Instead, call the method `setRounded` to set the + * radius of the rounded corners. + * + * @name Phaser.GameObjects.Shape#radius + * @type {number} + * @readonly + * @since 3.89.0 + */ + this.radius = 20; + + /** + * Does this Rectangle have rounded corners? + * + * Do not modify this property. Instead, call the method `setRounded` to set the + * radius state of this rectangle. + * + * @name Phaser.GameObjects.Shape#isRounded + * @type {boolean} + * @readonly + * @since 3.89.0 + */ + this.isRounded = false; + + this.setPosition(x, y); + this.setSize(width, height); + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateDisplayOrigin(); + this.updateData(); + }, + + /** + * Sets this rectangle to have rounded corners by specifying the radius of the corner. + * + * The radius of the rounded corners is limited by the smallest dimension of the rectangle. + * + * To disable rounded corners, set the `radius` parameter to 0. + * + * @method Phaser.GameObjects.Rectangle#setRounded + * @since 3.89.0 + * + * @param {number} [radius=16] - The radius of all four rounded corners. + * + * @return {this} This Game Object instance. + */ + setRounded: function (radius) + { + if (radius === undefined) { radius = 16; } + + this.radius = radius; + this.isRounded = radius > 0; + + return this.updateRoundedData(); + }, + + /** + * Sets the internal size of this Rectangle, as used for frame or physics body creation. + * + * If you have assigned a custom input hit area for this Rectangle, changing the Rectangle size will _not_ change the + * size of the hit area. To do this you should adjust the `input.hitArea` object directly. + * + * @method Phaser.GameObjects.Rectangle#setSize + * @since 3.13.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object instance. + */ + setSize: function (width, height) + { + this.width = width; + this.height = height; + + this.geom.setSize(width, height); + + this.updateData(); + + this.updateDisplayOrigin(); + + var input = this.input; + + if (input && !input.customHitArea) + { + input.hitArea.width = width; + input.hitArea.height = height; + } + + return this; + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Rectangle#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + if (this.isRounded) + { + return this.updateRoundedData(); + } + + var path = []; + var rect = this.geom; + var line = this._tempLine; + + rect.getLineA(line); + + path.push(line.x1, line.y1, line.x2, line.y2); + + rect.getLineB(line); + + path.push(line.x2, line.y2); + + rect.getLineC(line); + + path.push(line.x2, line.y2); + + rect.getLineD(line); + + path.push(line.x2, line.y2); + + this.pathData = path; + + return this; + }, + + /** + * Internal method that updates the data and path values when this rectangle is rounded. + * + * @method Phaser.GameObjects.Rectangle#updateRoundedData + * @private + * @since 3.89.0 + * + * @return {this} This Game Object instance. + */ + updateRoundedData: function () + { + var path = []; + var halfWidth = this.width / 2; + var halfHeight = this.height / 2; + + // Limit max radius to half the smallest dimension + var maxRadius = Math.min(halfWidth, halfHeight); + var radius = Math.min(this.radius, maxRadius); + + var x = halfWidth; + var y = halfHeight; + + // The number of segments is based on radius (more segments = larger radius) + var segments = Math.max(1, Math.floor(radius / 5)); + + // Create points going clockwise from top-left + + // Top-left corner + this.arcTo(path, x - halfWidth + radius, y - halfHeight + radius, radius, Math.PI, Math.PI * 1.5, segments); + + // Top edge and top-right corner + path.push(x + halfWidth - radius, y - halfHeight); + + this.arcTo(path, x + halfWidth - radius, y - halfHeight + radius, radius, Math.PI * 1.5, Math.PI * 2, segments); + + // Right edge and bottom-right corner + path.push(x + halfWidth, y + halfHeight - radius); + + this.arcTo(path, x + halfWidth - radius, y + halfHeight - radius, radius, 0, Math.PI * 0.5, segments); + + // Bottom edge and bottom-left corner + path.push(x - halfWidth + radius, y + halfHeight); + + this.arcTo(path, x - halfWidth + radius, y + halfHeight - radius, radius, Math.PI * 0.5, Math.PI, segments); + + // Left edge (connects back to first point) + path.push(x - halfWidth, y - halfHeight + radius); + + this.pathIndexes = Earcut(path); + this.pathData = path; + + return this; + }, + + /** + * Internal method placing points around the circumference of a circle for the rounded corners. + * + * @method Phaser.GameObjects.Rectangle#arcTo + * @private + * @since 3.89.0 + * + * @param {number[]} path - The array to push the points into. + * @param {number} centerX - The center x coordinate of the circle. + * @param {number} centerY - The center y coordinate of the circle. + * @param {number} radius - The radius of the circle. + * @param {number} startAngle - The starting angle of the arc. + * @param {number} endAngle - The ending angle of the arc. + * @param {number} segments - The number of segments to create. + * + * @return {this} This Game Object instance. + */ + arcTo: function (path, centerX, centerY, radius, startAngle, endAngle, segments) + { + var angleInc = (endAngle - startAngle) / segments; + + for (var i = 0; i <= segments; i++) + { + var angle = startAngle + (angleInc * i); + + path.push( + centerX + Math.cos(angle) * radius, + centerY + Math.sin(angle) * radius + ); + } + } + +}); + +module.exports = Rectangle; + + +/***/ }), + +/***/ 48682: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +var DrawRoundedRect = function (ctx, x, y, width, height, radius) +{ + // Limit radius to half of the smaller dimension + var maxRadius = Math.min(width / 2, height / 2); + var r = Math.min(radius, maxRadius); + + if (r === 0) + { + // Fall back to normal rectangle if radius is 0 + ctx.rect(x, y, width, height); + return; + } + + // Start at top-left, after the corner + ctx.moveTo(x + r, y); + + // Top edge and top-right corner + ctx.lineTo(x + width - r, y); + ctx.arcTo(x + width, y, x + width, y + r, r); + + // Right edge and bottom-right corner + ctx.lineTo(x + width, y + height - r); + ctx.arcTo(x + width, y + height, x + width - r, y + height, r); + + // Bottom edge and bottom-left corner + ctx.lineTo(x + r, y + height); + ctx.arcTo(x, y + height, x, y + height - r, r); + + // Left edge and top-left corner + ctx.lineTo(x, y + r); + ctx.arcTo(x, y, x + r, y, r); + + ctx.closePath(); +}; + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Rectangle#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Rectangle} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var RectangleCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + if (src.isRounded) + { + ctx.beginPath(); + DrawRoundedRect(ctx, -dx, -dy, src.width, src.height, src.radius); + ctx.fill(); + } + else + { + ctx.fillRect( + -dx, + -dy, + src.width, + src.height + ); + } + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.beginPath(); + + if (src.isRounded) + { + DrawRoundedRect(ctx, -dx, -dy, src.width, src.height, src.radius); + } + else + { + ctx.rect( + -dx, + -dy, + src.width, + src.height + ); + } + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = RectangleCanvasRenderer; + + +/***/ }), + +/***/ 87959: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Rectangle = __webpack_require__(74561); + +/** + * Creates a new Rectangle Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Rectangle Game Object has been built into Phaser. + * + * The Rectangle Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * You can change the size of the rectangle by changing the `width` and `height` properties. + * + * @method Phaser.GameObjects.GameObjectFactory#rectangle + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [width=128] - The width of the rectangle. + * @param {number} [height=128] - The height of the rectangle. + * @param {number} [fillColor] - The color the rectangle will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the rectangle will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Rectangle} The Game Object that was created. + */ +GameObjectFactory.register('rectangle', function (x, y, width, height, fillColor, fillAlpha) +{ + return this.displayList.add(new Rectangle(this.scene, x, y, width, height, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 95597: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(52059); +} + +if (true) +{ + renderCanvas = __webpack_require__(48682); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 52059: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillPathWebGL = __webpack_require__(10441); +var GetCalcMatrix = __webpack_require__(91296); +var StrokePathWebGL = __webpack_require__(34682); +var Utils = __webpack_require__(70554); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Rectangle#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Rectangle} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var RectangleWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + var alpha = src.alpha; + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + var submitter = customRenderNodes.Submitter || defaultRenderNodes.Submitter; + + if (src.isFilled) + { + if (src.isRounded) + { + FillPathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } + else + { + var fillTintColor = Utils.getTintAppendFloatAlpha(src.fillColor, src.fillAlpha * alpha); + + (customRenderNodes.FillRect || defaultRenderNodes.FillRect).run( + drawingContext, + calcMatrix, + submitter, + -dx, -dy, + src.width, src.height, + fillTintColor, + fillTintColor, + fillTintColor, + fillTintColor + ); + } + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = RectangleWebGLRenderer; + + +/***/ }), + +/***/ 55911: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var StarRender = __webpack_require__(81991); +var Class = __webpack_require__(83419); +var Earcut = __webpack_require__(94811); +var Shape = __webpack_require__(17803); + +/** + * @classdesc + * The Star Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * As the name implies, the Star shape will display a star in your game. You can control several + * aspects of it including the number of points that constitute the star. The default is 5. If + * you change it to 4 it will render as a diamond. If you increase them, you'll get a more spiky + * star shape. + * + * You can also control the inner and outer radius, which is how 'long' each point of the star is. + * Modify these values to create more interesting shapes. + * + * @class Star + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [points=5] - The number of points on the star. + * @param {number} [innerRadius=32] - The inner radius of the star. + * @param {number} [outerRadius=64] - The outer radius of the star. + * @param {number} [fillColor] - The color the star will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the star will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Star = new Class({ + + Extends: Shape, + + Mixins: [ + StarRender + ], + + initialize: + + function Star (scene, x, y, points, innerRadius, outerRadius, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (points === undefined) { points = 5; } + if (innerRadius === undefined) { innerRadius = 32; } + if (outerRadius === undefined) { outerRadius = 64; } + + Shape.call(this, scene, 'Star', null); + + /** + * Private internal value. + * The number of points in the star. + * + * @name Phaser.GameObjects.Star#_points + * @type {number} + * @private + * @since 3.13.0 + */ + this._points = points; + + /** + * Private internal value. + * The inner radius of the star. + * + * @name Phaser.GameObjects.Star#_innerRadius + * @type {number} + * @private + * @since 3.13.0 + */ + this._innerRadius = innerRadius; + + /** + * Private internal value. + * The outer radius of the star. + * + * @name Phaser.GameObjects.Star#_outerRadius + * @type {number} + * @private + * @since 3.13.0 + */ + this._outerRadius = outerRadius; + + this.setPosition(x, y); + this.setSize(outerRadius * 2, outerRadius * 2); + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateDisplayOrigin(); + this.updateData(); + }, + + /** + * Sets the number of points that make up the Star shape. + * This call can be chained. + * + * @method Phaser.GameObjects.Star#setPoints + * @since 3.13.0 + * + * @param {number} value - The amount of points the Star will have. + * + * @return {this} This Game Object instance. + */ + setPoints: function (value) + { + this._points = value; + + return this.updateData(); + }, + + /** + * Sets the inner radius of the Star shape. + * This call can be chained. + * + * @method Phaser.GameObjects.Star#setInnerRadius + * @since 3.13.0 + * + * @param {number} value - The amount to set the inner radius to. + * + * @return {this} This Game Object instance. + */ + setInnerRadius: function (value) + { + this._innerRadius = value; + + return this.updateData(); + }, + + /** + * Sets the outer radius of the Star shape. + * This call can be chained. + * + * @method Phaser.GameObjects.Star#setOuterRadius + * @since 3.13.0 + * + * @param {number} value - The amount to set the outer radius to. + * + * @return {this} This Game Object instance. + */ + setOuterRadius: function (value) + { + this._outerRadius = value; + + return this.updateData(); + }, + + /** + * The number of points that make up the Star shape. + * + * @name Phaser.GameObjects.Star#points + * @type {number} + * @default 5 + * @since 3.13.0 + */ + points: { + + get: function () + { + return this._points; + }, + + set: function (value) + { + this._points = value; + + this.updateData(); + } + + }, + + /** + * The inner radius of the Star shape. + * + * @name Phaser.GameObjects.Star#innerRadius + * @type {number} + * @default 32 + * @since 3.13.0 + */ + innerRadius: { + + get: function () + { + return this._innerRadius; + }, + + set: function (value) + { + this._innerRadius = value; + + this.updateData(); + } + + }, + + /** + * The outer radius of the Star shape. + * + * @name Phaser.GameObjects.Star#outerRadius + * @type {number} + * @default 64 + * @since 3.13.0 + */ + outerRadius: { + + get: function () + { + return this._outerRadius; + }, + + set: function (value) + { + this._outerRadius = value; + + this.updateData(); + } + + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Star#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + var path = []; + + var points = this._points; + var innerRadius = this._innerRadius; + var outerRadius = this._outerRadius; + + var rot = Math.PI / 2 * 3; + var step = Math.PI / points; + + // So origin 0.5 = the center of the star + var x = outerRadius; + var y = outerRadius; + + path.push(x, y + -outerRadius); + + for (var i = 0; i < points; i++) + { + path.push(x + Math.cos(rot) * outerRadius, y + Math.sin(rot) * outerRadius); + + rot += step; + + path.push(x + Math.cos(rot) * innerRadius, y + Math.sin(rot) * innerRadius); + + rot += step; + } + + path.push(x, y + -outerRadius); + + this.pathIndexes = Earcut(path); + this.pathData = path; + + return this; + } + +}); + +module.exports = Star; + + +/***/ }), + +/***/ 64272: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Star#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Star} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var StarCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var path = src.pathData; + var pathLength = path.length - 1; + + var px1 = path[0] - dx; + var py1 = path[1] - dy; + + ctx.beginPath(); + + ctx.moveTo(px1, py1); + + if (!src.closePath) + { + pathLength -= 2; + } + + for (var i = 2; i < pathLength; i += 2) + { + var px2 = path[i] - dx; + var py2 = path[i + 1] - dy; + + ctx.lineTo(px2, py2); + } + + ctx.closePath(); + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + ctx.fill(); + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = StarCanvasRenderer; + + +/***/ }), + +/***/ 93697: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Star = __webpack_require__(55911); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Star Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Star Game Object has been built into Phaser. + * + * The Star Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * As the name implies, the Star shape will display a star in your game. You can control several + * aspects of it including the number of points that constitute the star. The default is 5. If + * you change it to 4 it will render as a diamond. If you increase them, you'll get a more spiky + * star shape. + * + * You can also control the inner and outer radius, which is how 'long' each point of the star is. + * Modify these values to create more interesting shapes. + * + * @method Phaser.GameObjects.GameObjectFactory#star + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [points=5] - The number of points on the star. + * @param {number} [innerRadius=32] - The inner radius of the star. + * @param {number} [outerRadius=64] - The outer radius of the star. + * @param {number} [fillColor] - The color the star will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the star will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Star} The Game Object that was created. + */ +GameObjectFactory.register('star', function (x, y, points, innerRadius, outerRadius, fillColor, fillAlpha) +{ + return this.displayList.add(new Star(this.scene, x, y, points, innerRadius, outerRadius, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 81991: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(57017); +} + +if (true) +{ + renderCanvas = __webpack_require__(64272); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 57017: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillPathWebGL = __webpack_require__(10441); +var GetCalcMatrix = __webpack_require__(91296); +var StrokePathWebGL = __webpack_require__(34682); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Star#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Star} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var StarWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var alpha = src.alpha; + + var submitter = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + if (src.isFilled) + { + FillPathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = StarWebGLRenderer; + + +/***/ }), + +/***/ 36931: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Shape = __webpack_require__(17803); +var GeomTriangle = __webpack_require__(16483); +var TriangleRender = __webpack_require__(96195); + +/** + * @classdesc + * The Triangle Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * The Triangle consists of 3 lines, joining up to form a triangular shape. You can control the + * position of each point of these lines. The triangle is always closed and cannot have an open + * face. If you require that, consider using a Polygon instead. + * + * @class Triangle + * @extends Phaser.GameObjects.Shape + * @memberof Phaser.GameObjects + * @constructor + * @since 3.13.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [x1=0] - The horizontal position of the first point in the triangle. + * @param {number} [y1=128] - The vertical position of the first point in the triangle. + * @param {number} [x2=64] - The horizontal position of the second point in the triangle. + * @param {number} [y2=0] - The vertical position of the second point in the triangle. + * @param {number} [x3=128] - The horizontal position of the third point in the triangle. + * @param {number} [y3=128] - The vertical position of the third point in the triangle. + * @param {number} [fillColor] - The color the triangle will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the triangle will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + */ +var Triangle = new Class({ + + Extends: Shape, + + Mixins: [ + TriangleRender + ], + + initialize: + + function Triangle (scene, x, y, x1, y1, x2, y2, x3, y3, fillColor, fillAlpha) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (x1 === undefined) { x1 = 0; } + if (y1 === undefined) { y1 = 128; } + if (x2 === undefined) { x2 = 64; } + if (y2 === undefined) { y2 = 0; } + if (x3 === undefined) { x3 = 128; } + if (y3 === undefined) { y3 = 128; } + + Shape.call(this, scene, 'Triangle', new GeomTriangle(x1, y1, x2, y2, x3, y3)); + + var width = this.geom.right - this.geom.left; + var height = this.geom.bottom - this.geom.top; + + this.setPosition(x, y); + this.setSize(width, height); + + if (fillColor !== undefined) + { + this.setFillStyle(fillColor, fillAlpha); + } + + this.updateDisplayOrigin(); + this.updateData(); + }, + + /** + * Sets the data for the lines that make up this Triangle shape. + * + * @method Phaser.GameObjects.Triangle#setTo + * @since 3.13.0 + * + * @param {number} [x1=0] - The horizontal position of the first point in the triangle. + * @param {number} [y1=0] - The vertical position of the first point in the triangle. + * @param {number} [x2=0] - The horizontal position of the second point in the triangle. + * @param {number} [y2=0] - The vertical position of the second point in the triangle. + * @param {number} [x3=0] - The horizontal position of the third point in the triangle. + * @param {number} [y3=0] - The vertical position of the third point in the triangle. + * + * @return {this} This Game Object instance. + */ + setTo: function (x1, y1, x2, y2, x3, y3) + { + this.geom.setTo(x1, y1, x2, y2, x3, y3); + + return this.updateData(); + }, + + /** + * Internal method that updates the data and path values. + * + * @method Phaser.GameObjects.Triangle#updateData + * @private + * @since 3.13.0 + * + * @return {this} This Game Object instance. + */ + updateData: function () + { + var path = []; + var tri = this.geom; + var line = this._tempLine; + + tri.getLineA(line); + + path.push(line.x1, line.y1, line.x2, line.y2); + + tri.getLineB(line); + + path.push(line.x2, line.y2); + + tri.getLineC(line); + + path.push(line.x2, line.y2); + + this.pathData = path; + + return this; + } + +}); + +module.exports = Triangle; + + +/***/ }), + +/***/ 85172: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FillStyleCanvas = __webpack_require__(65960); +var LineStyleCanvas = __webpack_require__(75177); +var SetTransform = __webpack_require__(20926); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Triangle#renderCanvas + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Triangle} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TriangleCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + var ctx = renderer.currentContext; + + if (SetTransform(renderer, ctx, src, camera, parentMatrix)) + { + var dx = src._displayOriginX; + var dy = src._displayOriginY; + + var x1 = src.geom.x1 - dx; + var y1 = src.geom.y1 - dy; + var x2 = src.geom.x2 - dx; + var y2 = src.geom.y2 - dy; + var x3 = src.geom.x3 - dx; + var y3 = src.geom.y3 - dy; + + ctx.beginPath(); + + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.lineTo(x3, y3); + + ctx.closePath(); + + if (src.isFilled) + { + FillStyleCanvas(ctx, src); + + ctx.fill(); + } + + if (src.isStroked) + { + LineStyleCanvas(ctx, src); + + ctx.stroke(); + } + + // Restore the context saved in SetTransform + ctx.restore(); + } +}; + +module.exports = TriangleCanvasRenderer; + + +/***/ }), + +/***/ 45245: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Triangle = __webpack_require__(36931); + +/** + * Creates a new Triangle Shape Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Triangle Game Object has been built into Phaser. + * + * The Triangle Shape is a Game Object that can be added to a Scene, Group or Container. You can + * treat it like any other Game Object in your game, such as tweening it, scaling it, or enabling + * it for input or physics. It provides a quick and easy way for you to render this shape in your + * game without using a texture, while still taking advantage of being fully batched in WebGL. + * + * This shape supports both fill and stroke colors. + * + * The Triangle consists of 3 lines, joining up to form a triangular shape. You can control the + * position of each point of these lines. The triangle is always closed and cannot have an open + * face. If you require that, consider using a Polygon instead. + * + * @method Phaser.GameObjects.GameObjectFactory#triangle + * @since 3.13.0 + * + * @param {number} [x=0] - The horizontal position of this Game Object in the world. + * @param {number} [y=0] - The vertical position of this Game Object in the world. + * @param {number} [x1=0] - The horizontal position of the first point in the triangle. + * @param {number} [y1=128] - The vertical position of the first point in the triangle. + * @param {number} [x2=64] - The horizontal position of the second point in the triangle. + * @param {number} [y2=0] - The vertical position of the second point in the triangle. + * @param {number} [x3=128] - The horizontal position of the third point in the triangle. + * @param {number} [y3=128] - The vertical position of the third point in the triangle. + * @param {number} [fillColor] - The color the triangle will be filled with, i.e. 0xff0000 for red. + * @param {number} [fillAlpha] - The alpha the triangle will be filled with. You can also set the alpha of the overall Shape using its `alpha` property. + * + * @return {Phaser.GameObjects.Triangle} The Game Object that was created. + */ +GameObjectFactory.register('triangle', function (x, y, x1, y1, x2, y2, x3, y3, fillColor, fillAlpha) +{ + return this.displayList.add(new Triangle(this.scene, x, y, x1, y1, x2, y2, x3, y3, fillColor, fillAlpha)); +}); + + +/***/ }), + +/***/ 96195: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(83253); +} + +if (true) +{ + renderCanvas = __webpack_require__(85172); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 83253: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); +var StrokePathWebGL = __webpack_require__(34682); +var Utils = __webpack_require__(70554); + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Triangle#renderWebGL + * @since 3.13.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Triangle} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TriangleWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix, !drawingContext.useCanvas).calc; + + var dx = src._displayOriginX; + var dy = src._displayOriginY; + var alpha = src.alpha; + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + var submitter = customRenderNodes.Submitter || defaultRenderNodes.Submitter; + + if (src.isFilled) + { + var fillTintColor = Utils.getTintAppendFloatAlpha(src.fillColor, src.fillAlpha * alpha); + + var x1 = src.geom.x1 - dx; + var y1 = src.geom.y1 - dy; + var x2 = src.geom.x2 - dx; + var y2 = src.geom.y2 - dy; + var x3 = src.geom.x3 - dx; + var y3 = src.geom.y3 - dy; + + (customRenderNodes.FillTri || defaultRenderNodes.FillTri).run( + drawingContext, + calcMatrix, + submitter, + x1, + y1, + x2, + y2, + x3, + y3, + fillTintColor, + fillTintColor, + fillTintColor + ); + } + + if (src.isStroked) + { + StrokePathWebGL(drawingContext, submitter, calcMatrix, src, alpha, dx, dy); + } +}; + +module.exports = TriangleWebGLRenderer; + + +/***/ }), + +/***/ 68287: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AnimationState = __webpack_require__(9674); +var DefaultImageNodes = __webpack_require__(40939); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var SpriteRender = __webpack_require__(92751); + +/** + * @classdesc + * A Sprite Game Object. + * + * A Sprite Game Object is used for the display of both static and animated images in your game. + * Sprites can have input events and physics bodies. They can also be tweened, tinted, scrolled + * and animated. + * + * The main difference between a Sprite and an Image Game Object is that you cannot animate Images. + * As such, Sprites take a fraction longer to process and have a larger API footprint due to the Animation + * Component. If you do not require animation then you can safely use Images to replace Sprites in all cases. + * + * @class Sprite + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.TextureCrop + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + */ +var Sprite = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.Depth, + Components.Flip, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.Size, + Components.TextureCrop, + Components.Tint, + Components.Transform, + Components.Visible, + SpriteRender + ], + + initialize: + + function Sprite (scene, x, y, texture, frame) + { + GameObject.call(this, scene, 'Sprite'); + + /** + * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method. + * + * @name Phaser.GameObjects.Sprite#_crop + * @type {object} + * @private + * @since 3.11.0 + */ + this._crop = this.resetCropObject(); + + /** + * The Animation State component of this Sprite. + * + * This component provides features to apply animations to this Sprite. + * It is responsible for playing, loading, queuing animations for later playback, + * mixing between animations and setting the current animation frame to this Sprite. + * + * @name Phaser.GameObjects.Sprite#anims + * @type {Phaser.Animations.AnimationState} + * @since 3.0.0 + */ + this.anims = new AnimationState(this); + + this.setTexture(texture, frame); + this.setPosition(x, y); + this.setSizeToFrame(); + this.setOriginFromFrame(); + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Sprite#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultImageNodes; + } + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + /** + * Update this Sprite's animations. + * + * @method Phaser.GameObjects.Sprite#preUpdate + * @protected + * @since 3.0.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + preUpdate: function (time, delta) + { + this.anims.update(time, delta); + }, + + /** + * Start playing the given animation on this Sprite. + * + * Animations in Phaser can either belong to the global Animation Manager, or specifically to this Sprite. + * + * The benefit of a global animation is that multiple Sprites can all play the same animation, without + * having to duplicate the data. You can just create it once and then play it on any Sprite. + * + * The following code shows how to create a global repeating animation. The animation will be created + * from all of the frames within the sprite sheet that was loaded with the key 'muybridge': + * + * ```javascript + * var config = { + * key: 'run', + * frames: 'muybridge', + * frameRate: 15, + * repeat: -1 + * }; + * + * // This code should be run from within a Scene: + * this.anims.create(config); + * ``` + * + * However, if you wish to create an animation that is unique to this Sprite, and this Sprite alone, + * you can call the `Animation.create` method instead. It accepts the exact same parameters as when + * creating a global animation, however the resulting data is kept locally in this Sprite. + * + * With the animation created, either globally or locally, you can now play it on this Sprite: + * + * ```javascript + * this.add.sprite(x, y).play('run'); + * ``` + * + * Alternatively, if you wish to run it at a different frame rate, for example, you can pass a config + * object instead: + * + * ```javascript + * this.add.sprite(x, y).play({ key: 'run', frameRate: 24 }); + * ``` + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * If you need a Sprite to be able to play both local and global animations, make sure they don't + * have conflicting keys. + * + * See the documentation for the `PlayAnimationConfig` config object for more details about this. + * + * Also, see the documentation in the Animation Manager for further details on creating animations. + * + * @method Phaser.GameObjects.Sprite#play + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.0.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {boolean} [ignoreIfPlaying=false] - If an animation is already playing then ignore this call. + * + * @return {this} This Game Object. + */ + play: function (key, ignoreIfPlaying) + { + return this.anims.play(key, ignoreIfPlaying); + }, + + /** + * Start playing the given animation on this Sprite, in reverse. + * + * Animations in Phaser can either belong to the global Animation Manager, or specifically to this Sprite. + * + * The benefit of a global animation is that multiple Sprites can all play the same animation, without + * having to duplicate the data. You can just create it once and then play it on any Sprite. + * + * The following code shows how to create a global repeating animation. The animation will be created + * from all of the frames within the sprite sheet that was loaded with the key 'muybridge': + * + * ```javascript + * var config = { + * key: 'run', + * frames: 'muybridge', + * frameRate: 15, + * repeat: -1 + * }; + * + * // This code should be run from within a Scene: + * this.anims.create(config); + * ``` + * + * However, if you wish to create an animation that is unique to this Sprite, and this Sprite alone, + * you can call the `Animation.create` method instead. It accepts the exact same parameters as when + * creating a global animation, however the resulting data is kept locally in this Sprite. + * + * With the animation created, either globally or locally, you can now play it on this Sprite: + * + * ```javascript + * this.add.sprite(x, y).playReverse('run'); + * ``` + * + * Alternatively, if you wish to run it at a different frame rate, for example, you can pass a config + * object instead: + * + * ```javascript + * this.add.sprite(x, y).playReverse({ key: 'run', frameRate: 24 }); + * ``` + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * If you need a Sprite to be able to play both local and global animations, make sure they don't + * have conflicting keys. + * + * See the documentation for the `PlayAnimationConfig` config object for more details about this. + * + * Also, see the documentation in the Animation Manager for further details on creating animations. + * + * @method Phaser.GameObjects.Sprite#playReverse + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {boolean} [ignoreIfPlaying=false] - If an animation is already playing then ignore this call. + * + * @return {this} This Game Object. + */ + playReverse: function (key, ignoreIfPlaying) + { + return this.anims.playReverse(key, ignoreIfPlaying); + }, + + /** + * Waits for the specified delay, in milliseconds, then starts playback of the given animation. + * + * If the animation _also_ has a delay value set in its config, it will be **added** to the delay given here. + * + * If an animation is already running and a new animation is given to this method, it will wait for + * the given delay before starting the new animation. + * + * If no animation is currently running, the given one begins after the delay. + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * Prior to Phaser 3.50 this method was called 'delayedPlay'. + * + * @method Phaser.GameObjects.Sprite#playAfterDelay + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {number} delay - The delay, in milliseconds, to wait before starting the animation playing. + * + * @return {this} This Game Object. + */ + playAfterDelay: function (key, delay) + { + return this.anims.playAfterDelay(key, delay); + }, + + /** + * Waits for the current animation to complete the `repeatCount` number of repeat cycles, then starts playback + * of the given animation. + * + * You can use this to ensure there are no harsh jumps between two sets of animations, i.e. going from an + * idle animation to a walking animation, by making them blend smoothly into each other. + * + * If no animation is currently running, the given one will start immediately. + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * @method Phaser.GameObjects.Sprite#playAfterRepeat + * @fires Phaser.Animations.Events#ANIMATION_START + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig)} key - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object. + * @param {number} [repeatCount=1] - How many times should the animation repeat before the next one starts? + * + * @return {this} This Game Object. + */ + playAfterRepeat: function (key, repeatCount) + { + return this.anims.playAfterRepeat(key, repeatCount); + }, + + /** + * Sets an animation, or an array of animations, to be played immediately after the current one completes or stops. + * + * The current animation must enter a 'completed' state for this to happen, i.e. finish all of its repeats, delays, etc, + * or have the `stop` method called directly on it. + * + * An animation set to repeat forever will never enter a completed state. + * + * You can chain a new animation at any point, including before the current one starts playing, during it, + * or when it ends (via its `animationcomplete` event). + * + * Chained animations are specific to a Game Object, meaning different Game Objects can have different chained + * animations without impacting the animation they're playing. + * + * Call this method with no arguments to reset all currently chained animations. + * + * When playing an animation on a Sprite it will first check to see if it can find a matching key + * locally within the Sprite. If it can, it will play the local animation. If not, it will then + * search the global Animation Manager and look for it there. + * + * @method Phaser.GameObjects.Sprite#chain + * @since 3.50.0 + * + * @param {(string|Phaser.Animations.Animation|Phaser.Types.Animations.PlayAnimationConfig|string[]|Phaser.Animations.Animation[]|Phaser.Types.Animations.PlayAnimationConfig[])} [key] - The string-based key of the animation to play, or an Animation instance, or a `PlayAnimationConfig` object, or an array of them. + * + * @return {this} This Game Object. + */ + chain: function (key) + { + return this.anims.chain(key); + }, + + /** + * Immediately stops the current animation from playing and dispatches the `ANIMATION_STOP` events. + * + * If no animation is playing, no event will be dispatched. + * + * If there is another animation queued (via the `chain` method) then it will start playing immediately. + * + * @method Phaser.GameObjects.Sprite#stop + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.50.0 + * + * @return {this} This Game Object. + */ + stop: function () + { + return this.anims.stop(); + }, + + /** + * Stops the current animation from playing after the specified time delay, given in milliseconds. + * + * It then dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing, + * when the current one stops. + * + * @method Phaser.GameObjects.Sprite#stopAfterDelay + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.50.0 + * + * @param {number} delay - The number of milliseconds to wait before stopping this animation. + * + * @return {this} This Game Object. + */ + stopAfterDelay: function (delay) + { + return this.anims.stopAfterDelay(delay); + }, + + /** + * Stops the current animation from playing after the given number of repeats. + * + * It then dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing, + * when the current one stops. + * + * @method Phaser.GameObjects.Sprite#stopAfterRepeat + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.50.0 + * + * @param {number} [repeatCount=1] - How many times should the animation repeat before stopping? + * + * @return {this} This Game Object. + */ + stopAfterRepeat: function (repeatCount) + { + return this.anims.stopAfterRepeat(repeatCount); + }, + + /** + * Stops the current animation from playing when it next sets the given frame. + * If this frame doesn't exist within the animation it will not stop it from playing. + * + * It then dispatches the `ANIMATION_STOP` event. + * + * If no animation is running, no events will be dispatched. + * + * If there is another animation in the queue (set via the `chain` method) then it will start playing, + * when the current one stops. + * + * @method Phaser.GameObjects.Sprite#stopOnFrame + * @fires Phaser.Animations.Events#ANIMATION_STOP + * @since 3.50.0 + * + * @param {Phaser.Animations.AnimationFrame} frame - The frame to check before stopping this animation. + * + * @return {this} This Game Object. + */ + stopOnFrame: function (frame) + { + return this.anims.stopOnFrame(frame); + }, + + /** + * Build a JSON representation of this Sprite. + * + * @method Phaser.GameObjects.Sprite#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object. + */ + toJSON: function () + { + return Components.ToJSON(this); + }, + + /** + * Handles the pre-destroy step for the Sprite, which removes the Animation component. + * + * @method Phaser.GameObjects.Sprite#preDestroy + * @private + * @since 3.14.0 + */ + preDestroy: function () + { + this.anims.destroy(); + + this.anims = undefined; + } + +}); + +module.exports = Sprite; + + +/***/ }), + +/***/ 76552: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Sprite#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Sprite} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var SpriteCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + camera.addToRenderList(src); + + renderer.batchSprite(src, src.frame, camera, parentMatrix); +}; + +module.exports = SpriteCanvasRenderer; + + +/***/ }), + +/***/ 15567: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var BuildGameObjectAnimation = __webpack_require__(13059); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Sprite = __webpack_require__(68287); + +/** + * Creates a new Sprite Game Object and returns it. + * + * Note: This method will only be available if the Sprite Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#sprite + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene=true] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Sprite} The Game Object that was created. + */ +GameObjectCreator.register('sprite', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var frame = GetAdvancedValue(config, 'frame', null); + + var sprite = new Sprite(this.scene, 0, 0, key, frame); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, sprite, config); + + // Sprite specific config options: + + BuildGameObjectAnimation(sprite, config); + + return sprite; +}); + + +/***/ }), + +/***/ 46409: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var Sprite = __webpack_require__(68287); + +/** + * Creates a new Sprite Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Sprite Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#sprite + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.GameObjects.Sprite} The Game Object that was created. + */ +GameObjectFactory.register('sprite', function (x, y, texture, frame) +{ + return this.displayList.add(new Sprite(this.scene, x, y, texture, frame)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 92751: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(9409); +} + +if (true) +{ + renderCanvas = __webpack_require__(76552); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 9409: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Sprite#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Sprite} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var SpriteWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + drawingContext.camera.addToRenderList(src); + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + src, + parentMatrix, + 0, + customRenderNodes.Texturer || defaultRenderNodes.Texturer, + customRenderNodes.Transformer || defaultRenderNodes.Transformer + ); +}; + +module.exports = SpriteWebGLRenderer; + + +/***/ }), + +/***/ 18207: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Easing function identifiers. + * + * @ignore + */ +var EasingEncoding = { + None: 0, + + Power0: 1, + Power1: 10, + Power2: 20, + Power3: 30, + Power4: 40, + Linear: 1, + + Gravity: 2, + + Quad: 10, + 'Quad.easeOut': 10, + 'Quad.easeIn': 11, + 'Quad.easeInOut': 12, + + Cubic: 20, + 'Cubic.easeOut': 20, + 'Cubic.easeIn': 21, + 'Cubic.easeInOut': 22, + + Quart: 30, + 'Quart.easeOut': 30, + 'Quart.easeIn': 31, + 'Quart.easeInOut': 32, + + Quint: 40, + 'Quint.easeOut': 40, + 'Quint.easeIn': 41, + 'Quint.easeInOut': 42, + + Sine: 50, + 'Sine.easeOut': 50, + 'Sine.easeIn': 51, + 'Sine.easeInOut': 52, + + Expo: 60, + 'Expo.easeOut': 60, + 'Expo.easeIn': 61, + 'Expo.easeInOut': 62, + + Circ: 70, + 'Circ.easeOut': 70, + 'Circ.easeIn': 71, + 'Circ.easeInOut': 72, + + // // Elastic requires extra parameters, so we skip it. + // Elastic: 80, + // 'Elastic.easeOut': 80, + // 'Elastic.easeIn': 81, + // 'Elastic.easeInOut': 82, + + Back: 90, + 'Back.easeOut': 90, + 'Back.easeIn': 91, + 'Back.easeInOut': 92, + + Bounce: 100, + 'Bounce.easeOut': 100, + 'Bounce.easeIn': 101, + 'Bounce.easeInOut': 102, + + // Stepped could require extra parameters, but we assume just 2. + Stepped: 110, + + Smoothstep: 120, + 'Smoothstep.easeOut': 120, + 'Smoothstep.easeIn': 121, + 'Smoothstep.easeInOut': 122 +}; + +module.exports = EasingEncoding; + + +/***/ }), + +/***/ 68218: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var EasingEncoding = __webpack_require__(18207); + +/** + * Easing function identifiers. + * This is a reverse mapping of EasingEncoding, + * mapping numbers to their string names. + * + * @ignore + */ +var EasingNaming = {}; + +var animations = Object.keys(EasingEncoding); +var animLen = animations.length; + +for (var i = 0; i < animLen; i++) +{ + var key = animations[i]; + var value = EasingEncoding[key]; + EasingNaming[value] = key; +} + +module.exports = EasingNaming; + + +/***/ }), + +/***/ 76573: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var SubmitterSpriteGPULayer = __webpack_require__(53384); +var Utils = __webpack_require__(70554); +var EasingEncoding = __webpack_require__(18207); +var EasingNaming = __webpack_require__(68218); +var SpriteGPULayerRender = __webpack_require__(71238); + +var getTint = Utils.getTintAppendFloatAlpha; + +/** + * @classdesc + * A SpriteGPULayer GameObject. This is a WebGL only GameObject. + * It is optimized for rendering very large numbers of quads + * following simple tween animations. + * It is suited to complex backgrounds with animation. + * + * A SpriteGPULayer is a composite object that contains a collection of + * Member objects. It stores the rendering data for these + * objects in a GPU buffer, and renders them in a single draw call. + * Because it only updates the GPU buffer when necessary, + * it is up to 100 times faster than rendering the objects individually. + * Avoid changing the contents of the SpriteGPULayer frequently, as this + * requires the whole buffer to be updated. + * + * The layer can generally perform well with a million small quads. + * The exact performance will depend on the device and the size of the quads. + * If the quads are large, the layer will be fill-rate limited. + * Avoid drawing more than a few million pixels per frame. + * + * When populating the SpriteGPULayer, use `addMember` to add a new member + * to the top of the layer. You should populate the layer all at once, + * and leave it unchanged, rather than frequently adding and removing members, + * because it is expensive to update the buffer. + * + * Rather than create a new `SpriteGPULayer.Member` object for each `addMember` call, + * you can reuse the same object. This is more efficient, + * because creating millions of objects has a major performance cost + * and may cause garbage collection issues. + * + * Notes on modifying the SpriteGPULayer: + * + * The following operations are expensive. They require some or all of the + * buffer to be updated: + * + * - `addData` + * - `addMember` + * - `editMember` + * - `patchMember` + * - `resize` + * - `removeMembers` + * + * Members are added at the end of the buffer. Removed members are spliced out + * of the buffer, causing the whole buffer to be updated. + * The index of later members will change if you remove an earlier member. + * If you need to maintain a structure, such as a grid of tiles, + * it's best to "remove" a member by setting its scaleX, scaleY, and alpha to 0. + * It is still rendered, but it does not fill any pixels. + * + * Changes to a small segment of the buffer are less expensive. + * The buffer is split into several segments, and each segment can be updated + * independently. Editing and patching members will only update the segments + * that contain the members being edited. + * Updating occurs at render time, so edits all happen at once. + * This can reduce the amount of data that needs to be updated, + * but it is still more expensive than not updating the buffer at all. + * If you're updating a large number of segments, it may be more efficient + * to call `setAllSegmentsNeedUpdate` and update the whole buffer at once + * rather than make several segment updates in a row. + * + * The animations in the initial member data are used to compile the shader + * and `frameDataTexture`. If you add new animations after the initial + * compilation, the shader and texture will be rebuilt, which is expensive. + * + * Notes on textures: + * + * This layer gains much of its speed from inflexibility. It can only use one + * texture, and that texture must be a single image. + * It cannot use multi-atlas textures. + * + * Further, if the texture is not a power of two in size, + * some texture seaming may occur if you line up sprites exactly. + * This is because the GPU precision is limited by binary logic, + * and texture coordinates will only be perfectly accurate for power of two textures. + * This can be avoided by adding/extruding a pixel of padding around each frame + * in the texture, or by using a power of two texture. + * + * Which should you use? + * + * - If you are using pixel art mode or round pixels, + * you should aim to use a power of two texture. + * - If you are using smooth mode, you can use a non-power of two texture, + * but you should add padding around each frame to avoid seaming. + * - If you are using a single image, or none of the frames in the texture + * need to tile, it doesn't matter. + * + * @class SpriteGPULayer + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @webglOnly + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.ElapseTimer + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.TextureCrop + * @extends Phaser.GameObjects.Components.Visible + * + * @constructor + * @since 4.0.0 + * @param {Phaser.Scene} scene - The Scene to which this SpriteGPULayer belongs. + * @param {Phaser.Textures.Texture} texture - The texture that will be used to render the SpriteGPULayer. This must be sourced from a single image; a multi atlas will not work. + * @param {number} size - The maximum number of quads that this SpriteGPULayer will hold. This can be increased later if necessary. + */ +var SpriteGPULayer = new Class({ + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.Depth, + Components.ElapseTimer, + Components.Lighting, + Components.Mask, + Components.RenderNodes, + Components.TextureCrop, + Components.Visible, + SpriteGPULayerRender + ], + + initialize: function SpriteGPULayer (scene, texture, size) + { + GameObject.call(this, scene, 'SpriteGPULayer'); + + /** + * The number of quad members in the SpriteGPULayer. + * + * @name Phaser.GameObjects.SpriteGPULayer#memberCount + * @type {number} + * @since 4.0.0 + */ + this.memberCount = 0; + + /** + * The maximum number of quad members that can be in the SpriteGPULayer. + * This value is read-only. Change buffer size with `resize`. + * + * @name Phaser.GameObjects.SpriteGPULayer#size + * @type {number} + * @since 4.0.0 + * @readonly + */ + this.size = Math.max(size, 0); + + /** + * The number of segments in the buffer. + * This helps to optimize buffer updates by dividing them into smaller segments. + * This is a constant value and should not be altered. + * If you do, all hell will break loose. + * + * Segments divide the buffer into sequential chunks. + * Only updated segments will be uploaded to the GPU. + * Each upload has a fixed cost, but reducing the total amount of data + * can improve performance. + * + * Don't change this value to anything higher than 31. + * Segment logic uses bitwise operations, which are limited to 32 bits, + * so going that high will cause overflows and break everything. + * + * @name Phaser.GameObjects.SpriteGPULayer#_segments + * @type {number} + * @since 4.0.0 + * @readonly + * @private + */ + this._segments = 24; + + /** + * The state of `bufferUpdateSegments` when it's full. + * This is a constant value and should not be altered. + * If you do, all hell will break loose. + * + * @name Phaser.GameObjects.SpriteGPULayer#MAX_BUFFER_UPDATE_SEGMENTS_FULL + * @type {number} + * @since 4.0.0 + * @readonly + * @default 0xffffff + */ + this.MAX_BUFFER_UPDATE_SEGMENTS_FULL = 0xffffff; + + /** + * Which segments of the buffer require updates. + * This is a bitfield with segments equal to `_segments`. + * + * @name Phaser.GameObjects.SpriteGPULayer#bufferUpdateSegments + * @type {number} + * @since 4.0.0 + */ + this.bufferUpdateSegments = 0; + + /** + * The size of each segment of the buffer that requires updates. + * + * @name Phaser.GameObjects.SpriteGPULayer#bufferUpdateSegmentSize + * @type {number} + * @since 4.0.0 + */ + this.bufferUpdateSegmentSize = Math.ceil(this.size / this._segments); + + /** + * The gravity used by member animations in 'Gravity' mode. + * This is the acceleration in pixels per second squared. + * The default is 1024 pixels per second squared. + * + * Any animation can be set to `ease: 'Gravity'` to use this value. + * Instead of `amplitude`, the animation takes + * `velocity` (a number of pixels) and + * `gravityFactor` (0-1) parameters. + * + * @name Phaser.GameObjects.SpriteGPULayer#gravity + * @type {number} + * @since 4.0.0 + * @default 1024 + */ + this.gravity = 1024; + + /** + * The animations enabled for the SpriteGPULayer. + * This is a map of animation names from `this.EASE` to boolean values. + * Adjust these values with `setAnimationEnabled`. + * + * @name Phaser.GameObjects.SpriteGPULayer#_animationsEnabled + * @type {object} + * @since 4.0.0 + * @private + */ + this._animationsEnabled = {}; + + var animations = Object.keys(EasingEncoding); + var animLen = animations.length; + for (var i = 0; i < animLen; i++) + { + this._animationsEnabled[animations[i]] = false; + } + + /** + * Strings for valid easing functions that can be assigned to + * the `ease` property of an SpriteGPULayerMemberAnimation. + * This is the reverse mapping of `this.EASE_CODES`. + * + * @name Phaser.GameObjects.SpriteGPULayer#EASE + * @type {object} + * @since 4.0.0 + * @readonly + */ + this.EASE = EasingEncoding; + + /** + * Codes for valid easing functions that can be assigned to + * the `ease` property of an SpriteGPULayerMemberAnimation. + * This is the reverse mapping of `this.EASE`. + * + * @name Phaser.GameObjects.SpriteGPULayer#EASE_CODES + * @type {object} + * @since 4.0.0 + * @readonly + */ + this.EASE_CODES = EasingNaming; + + this.setTexture(texture); + this.initRenderNodes(new Phaser.Structs.Map()); + + /** + * A texture containing the frame data for the SpriteGPULayer. + * This is used by the vertex shader. + * + * The texture is composed of pixel strides, where each stride + * is interpreted as 6 16-bit unsigned integers, + * representing the x, y, width, height, and origin x and y of a frame. + * The texture will be up to 4096 pixels wide and as tall as necessary. + * + * There are two sets of data in the texture: frames and animations. + * Frames are taken from the `texture`. + * Animations are defined by calling `setAnimations`, + * and consist of runs of frames suited to shader animation. + * Although the texture will be regenerated by `setAnimations`, + * the frames are stored first, so their indices won't change. + * + * If you change the `texture` of this layer, you will need to + * regenerate this by calling `generateFrameDataTexture`. + * + * @name Phaser.GameObjects.SpriteGPULayer#frameDataTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @since 4.0.0 + */ + this.frameDataTexture = null; + + /** + * A map of frame names to indices in the frame data texture. + * This is used to convert frame names to indices for the vertex shader. + * + * @name Phaser.GameObjects.SpriteGPULayer#frameDataIndices + * @type {object} + * @since 4.0.0 + */ + this.frameDataIndices = {}; + + /** + * A map of indices to frame names in the frame data texture. + * This is used to convert frame indices back to names for debugging. + * + * @name Phaser.GameObjects.SpriteGPULayer#frameDataIndicesInv + * @type {object} + * @since 4.0.0 + */ + this.frameDataIndicesInv = {}; + + /** + * An ordered list of animations in the frame data texture. + * + * @name Phaser.GameObjects.SpriteGPULayer#animationData + * @type {object[]} + * @since 4.0.0 + */ + this.animationData = []; + + /** + * A map of animation names to animation parameters in + * the frame data texture. + * This is used to convert animation names to indices and durations + * for the vertex shader. + * + * @name Phaser.GameObjects.SpriteGPULayer#animationDataNames + * @type {object} + * @since 4.0.0 + */ + this.animationDataNames = {}; + + /** + * A map of frame indices to animation parameters in + * the frame data texture. + * These are the starting frame indices used by the vertex shader. + * They can be used to map back to names in `animationDataIndices`. + * + * @name Phaser.GameObjects.SpriteGPULayer#animationDataIndices + * @type {object} + * @since 4.0.0 + */ + this.animationDataIndices = {}; + + this.generateFrameDataTexture(); + + /** + * The SubmitterSpriteGPULayer RenderNode for this SpriteGPULayer. + * + * This handles rendering the SpriteGPULayer to the GPU. + * It is created automatically when the SpriteGPULayer is initialized. + * Most RenderNodes are singletons stored in the RenderNodeManager, + * but because this one holds very specific data, + * it is stored in the SpriteGPULayer itself. + * + * @name Phaser.GameObjects.SpriteGPULayer#submitterNode + * @type {Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer} + * @since 4.0.0 + */ + this.submitterNode = new SubmitterSpriteGPULayer(scene.renderer.renderNodes, {}, this); + + this.defaultRenderNodes['Submitter'] = this.submitterNode; + this.renderNodeData[this.submitterNode.name] = {}; + + this.resize(this.size); + + /** + * The next member buffer, used to store member data + * before it is added to the GPU buffer. + * + * @name Phaser.GameObjects.SpriteGPULayer#nextMember + * @type {ArrayBuffer} + * @since 4.0.0 + */ + this.nextMember = new ArrayBuffer(this.getDataByteSize()); + + /** + * A Float32Array view of the next member buffer. + * + * @name Phaser.GameObjects.SpriteGPULayer#nextMemberF32 + * @type {Float32Array} + * @since 4.0.0 + */ + this.nextMemberF32 = new Float32Array(this.nextMember); + + /** + * A Uint32Array view of the next member buffer. + * This is used to write 32-bit integer data to the buffer. + * It is used for color data. + * + * @name Phaser.GameObjects.SpriteGPULayer#nextMemberU32 + * @type {Uint32Array} + * @since 4.0.0 + */ + this.nextMemberU32 = new Uint32Array(this.nextMember); + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + preUpdate: function (time, delta) + { + this.updateTimer(time, delta); + }, + + /** + * Get the number of bytes used to define a member. + * If you are directly editing the buffer, you will need this value + * as a 'stride' to move through the buffer. + * + * @method Phaser.GameObjects.SpriteGPULayer#getDataByteSize + * @returns {number} The number of bytes used for each member. + */ + getDataByteSize: function () + { + return this.submitterNode.instanceBufferLayout.layout.stride; + }, + + /** + * Return a list of features to enable in the shader program. + * This is used when the shader program is compiled. + * + * @method Phaser.GameObjects.SpriteGPULayer#getShaderFeatures + * @since 4.0.0 + * @return {string[]} An array of features to enable in the shader program. + */ + getShaderFeatures: function () + { + var features = []; + + // Add enabled animations. + var animations = Object.keys(this._animationsEnabled); + var animLen = animations.length; + for (var i = 0; i < animLen; i++) + { + if (this._animationsEnabled[animations[i]]) + { + features.push(animations[i]); + } + } + + return features; + }, + + /** + * Set the animations available to the SpriteGPULayer. + * This will call `generateFrameDataTexture` to regenerate + * `frameDataTexture`. + * + * Each animation can be either an Animation object, or an object + * containing a name, duration, and an array of frame names/numbers. + * If an Animation is used, it will be converted to the object form, + * discarding any custom individual frame durations + * and using the animation's duration as default. + * + * This is not a Phaser Animation. It is intended to cycle automatically + * on the GPU without supervision or interaction. It will not emit events, + * allow you to pause the animation, set number of repeats, etc. + * + * @method Phaser.GameObjects.SpriteGPULayer#setAnimations + * @since 4.0.0 + * @param {Phaser.Animations.Animation[]|Phaser.Types.GameObjects.SpriteGPULayer.SetAnimation[]} animations - An array of animations to set. + * @returns {this} This SpriteGPULayer object. + */ + setAnimations: function (animations) + { + var animLen = animations.length; + + // Animation frames will start after the texture frames. + var frameNames = this.texture.getFrameNames(true); + var index = frameNames.length; + + for (var i = 0; i < animLen; i++) + { + var anim = animations[i]; + var data = {}; + if (anim.key) + { + // This is a Phaser.Animations.Animation class. + data.name = anim.key; + data.duration = anim.duration; + data.frames = anim.frames; + } + else + { + data.name = anim.name; + data.duration = anim.duration; + data.frames = anim.frames.slice(); + } + + // Add frame indexing data. + data.index = index; + data.frameCount = data.frames.length; + index += data.frameCount; + + // Store animation. + this.animationData.push(data); + this.animationDataNames[data.name] = data; + this.animationDataIndices[data.index] = data; + } + + this.generateFrameDataTexture(); + + return this; + }, + + /** + * Generate `frameDataTexture` for the SpriteGPULayer. + * This is used by the vertex shader to access frame data. + * + * @method Phaser.GameObjects.SpriteGPULayer#generateFrameDataTexture + * @since 4.0.0 + */ + generateFrameDataTexture: function () + { + // Get the frame data. + var texture = this.texture; + var frames = texture.getFrameNames(true); + var frameLen = frames.length; + + // Update the frame data indices. + this.frameDataIndices = {}; + this.frameDataIndicesInv = {}; + for (var i = 0; i < frameLen; i++) + { + var frameName = frames[i]; + var frame = texture.get(frameName); + this.frameDataIndices[frameName] = i; + this.frameDataIndicesInv[i] = frameName; + } + + // Append frames from animations. + var anims = this.animationData; + var animsLen = anims.length; + for (i = 0; i < animsLen; i++) + { + var anim = this.animationData[i]; + var frameCount = anim.frameCount; + for (var j = 0; j < frameCount; j++) + { + frames.push(anim.frames[j]); + } + } + + frameLen = frames.length; + var valuesPerFrame = 3; + var pixelCount = frameLen * valuesPerFrame; + var width = Math.min(pixelCount, 4096); + var height = Math.ceil(pixelCount / 4096); + var dataSize = width * height * 4; + + var textureManager = texture.manager; + + // Generate a Uint8Array with the frame data. + var data = new ArrayBuffer(dataSize); + var u16 = new Uint16Array(data); + var u8 = new Uint8Array(data); + for (i = 0; i < frameLen; i++) + { + var animFrame = frames[i]; + if (typeof animFrame === 'string') + { + frame = texture.get(frames[i]); + } + else if (animFrame && animFrame.key !== undefined) + { + // animFrame comes from a SetAnimation object. + var animTexture = textureManager.get(animFrame.key); + frame = animTexture.get(animFrame.frame); + } + else + { + // animFrame is an AnimationFrame object. + frame = animFrame.frame; + } + + var offset = i * valuesPerFrame * u16.BYTES_PER_ELEMENT; + + // Position + u16[offset] = frame.cutX; + u16[offset + 1] = frame.cutY; + + // Size + u16[offset + 2] = frame.cutWidth; + u16[offset + 3] = frame.cutHeight; + + // Pivot offset + // Multiplied by the size to convert to pixels. + // Offset by 32768 to effectively store as a 16-bit signed integer. + var pivotX = 0.5; + var pivotY = 0.5; + if (frame.customPivot) + { + pivotX = frame.pivotX; + pivotY = frame.pivotY; + } + u16[offset + 4] = Math.round((pivotX - 0.5) * frame.cutWidth) + 32768; + u16[offset + 5] = Math.round((pivotY - 0.5) * frame.cutHeight) + 32768; + } + + // Create or update a texture with the frame data. + if (this.frameDataTexture) + { + this.frameDataTexture.destroy(); + } + this.frameDataTexture = this.scene.renderer.createUint8ArrayTexture(u8, width, height, false, false); + }, + + /** + * Resizes the SpriteGPULayer buffer to a new size. + * Optionally, clears the buffer. + * + * This is an expensive operation, as it requires the whole buffer to be updated. + * It can take many frames to complete. + * + * @method Phaser.GameObjects.SpriteGPULayer#resize + * @since 4.0.0 + * @param {number} count - The new number of members in the SpriteGPULayer. + * @param {boolean} [clear=false] - Whether to clear the buffer. + * @returns {this} This SpriteGPULayer object. + */ + resize: function (count, clear) + { + var layout = this.submitterNode.instanceBufferLayout; + var buffer = layout.buffer; + var u8 = buffer.viewU8; + var targetByteSize = count * layout.layout.stride; + + this.size = count; + + buffer.resize(targetByteSize); + + if (clear) + { + this.memberCount = 0; + } + else + { + // Copy data from the old buffer to the new buffer. + var newBuffer = buffer.viewU8; + newBuffer.set(u8.subarray(0, Math.min(newBuffer.byteLength, targetByteSize))); + this.memberCount = Math.min(this.memberCount, count); + } + + this.bufferUpdateSegmentSize = Math.ceil(this.size / this._segments); + this.setAllSegmentsNeedUpdate(); + + return this; + }, + + /** + * Sets a segment of the buffer to require an update. + * + * @method Phaser.GameObjects.SpriteGPULayer#setSegmentNeedsUpdate + * @since 4.0.0 + * @param {number} index - The index at which an update occurred, which requires the segment to be updated. + */ + setSegmentNeedsUpdate: function (index) + { + if ( + index < 0 || + index >= this.size || + this.bufferUpdateSegments === this.MAX_BUFFER_UPDATE_SEGMENTS_FULL + ) + { + return; + } + var segment = Math.floor(index / this.bufferUpdateSegmentSize); + this.bufferUpdateSegments |= (1 << segment); + }, + + /** + * Sets all segments of the buffer to require an update. + * + * @method Phaser.GameObjects.SpriteGPULayer#setAllSegmentsNeedUpdate + * @since 4.0.0 + */ + setAllSegmentsNeedUpdate: function () + { + this.bufferUpdateSegments = this.MAX_BUFFER_UPDATE_SEGMENTS_FULL; + }, + + /** + * Clears all segments of the buffer that require an update. + * + * @method Phaser.GameObjects.SpriteGPULayer#clearAllSegmentsNeedUpdate + * @since 4.0.0 + */ + clearAllSegmentsNeedUpdate: function () + { + this.bufferUpdateSegments = 0; + }, + + /** + * Adds data to the SpriteGPULayer buffer. + * It is inserted at the end of the buffer. + * + * This is mostly used internally by the SpriteGPULayer. + * It takes raw data as a buffer, which is very efficient, + * but `addMember` is easier to use. + * + * Note that, if you add a member with an animation, + * the animation must either already be enabled, + * or you must enable it with `setAnimationEnabled`, + * e.g. `layer.setAnimationEnabled('Linear', true)` or + * `layer.setAnimationEnabled(layer.EASE_CODES[layer.EASE.Linear], true)`. + * + * This is a buffer modification, and is expensive. + * + * @method Phaser.GameObjects.SpriteGPULayer#addData + * @since 4.0.0 + * @param {Float32Array} member - The raw data to add to the buffer. + * @returns {this} This SpriteGPULayer object. + */ + addData: function (member) + { + if (this.memberCount >= this.size) + { + return this; + } + + var layout = this.submitterNode.instanceBufferLayout; + var f32 = layout.buffer.viewF32; + var offset = this.memberCount * layout.layout.stride; + + f32.set(member, offset / f32.BYTES_PER_ELEMENT); + + this.setSegmentNeedsUpdate(this.memberCount); + this.memberCount++; + + return this; + }, + + /** + * Adds a member to the SpriteGPULayer. + * This is the easiest way to add a member to the SpriteGPULayer. + * + * This is a buffer modification, and is expensive. + * + * @method Phaser.GameObjects.SpriteGPULayer#addMember + * @since 4.0.0 + * @param {Partial} [member] - The member to add to the SpriteGPULayer. + * @returns {this} This SpriteGPULayer object. + */ + addMember: function (member) + { + if (this.memberCount >= this.size) + { + return this; + } + + var f32 = this.nextMemberF32; + var u32 = this.nextMemberU32; + + if (!member) + { + member = {}; + } + + var frame = this.frame; + if (member.frame !== undefined) + { + frame = member.frame.base ? member.frame.base : member.frame; + } + if (typeof frame === 'string') + { + frame = this.texture.get(frame); + + if (!frame) + { + return this; + } + } + + var offset = 0; + + this._setAnimatedValue(member.x, offset); + offset += 4; + + this._setAnimatedValue(member.y, offset); + offset += 4; + + this._setAnimatedValue(member.rotation, offset); + offset += 4; + + this._setAnimatedValue(member.scaleX, offset, 1); + offset += 4; + + this._setAnimatedValue(member.scaleY, offset, 1); + offset += 4; + + this._setAnimatedValue(member.alpha, offset, 1); + offset += 4; + + var animation = member.animation; + if (animation) + { + // Use frame animation. + var animData; + if ( + (typeof animation === 'string') || + (typeof animation === 'number') + ) + { + if (typeof animation === 'string') + { + animData = this.animationDataNames[animation]; + } + else + { + animData = this.animationDataIndices[animation]; + } + this._setAnimatedValue({ + base: animData.index, + amplitude: animData.frameCount, + duration: animData.duration, + ease: EasingEncoding.Linear, + yoyo: false + }, offset); + } + else + { + var base = animation.base; + if (typeof base === 'string') + { + animData = this.animationDataNames[base]; + } + else if (typeof base === 'number') + { + animData = this.animationDataIndices[base]; + } + else + { + // Bad data; fall back to first animation. + animData = this.animationData[0]; + } + this._setAnimatedValue({ + base: animData.index, + amplitude: (typeof animation.amplitude === 'number') ? animation.amplitude : animData.frameCount, + duration: animation.duration || animData.duration, + delay: animation.delay || 0, + ease: animation.ease || EasingEncoding.Linear, + yoyo: !!animation.yoyo + }, offset); + } + } + else + { + // Use single frame. + var frameIndex = this.frameDataIndices[frame.name]; + var memberFrame = member.frame; + if (memberFrame && memberFrame.base !== undefined) + { + this._setAnimatedValue({ + base: frameIndex, + amplitude: memberFrame.amplitude, + duration: memberFrame.duration, + delay: memberFrame.delay, + ease: memberFrame.ease, + yoyo: memberFrame.yoyo + }, offset); + } + else + { + this._setAnimatedValue(frameIndex, offset); + } + } + offset += 4; + + this._setAnimatedValue(member.tintBlend, offset, 1); + offset += 4; + + var tintBottomLeft = member.tintBottomLeft === undefined ? 0xffffff : member.tintBottomLeft; + var tintTopLeft = member.tintTopLeft === undefined ? 0xffffff : member.tintTopLeft; + var tintBottomRight = member.tintBottomRight === undefined ? 0xffffff : member.tintBottomRight; + var tintTopRight = member.tintTopRight === undefined ? 0xffffff : member.tintTopRight; + + var alphaBottomLeft = member.alphaBottomLeft === undefined ? 1 : member.alphaBottomLeft; + var alphaTopLeft = member.alphaTopLeft === undefined ? 1 : member.alphaTopLeft; + var alphaBottomRight = member.alphaBottomRight === undefined ? 1 : member.alphaBottomRight; + var alphaTopRight = member.alphaTopRight === undefined ? 1 : member.alphaTopRight; + + u32[offset++] = getTint( + tintBottomLeft, + alphaBottomLeft + ); + u32[offset++] = getTint( + tintTopLeft, + alphaTopLeft + ); + u32[offset++] = getTint( + tintBottomRight, + alphaBottomRight + ); + u32[offset++] = getTint( + tintTopRight, + alphaTopRight + ); + + f32[offset++] = member.originX === undefined ? 0.5 : member.originX; + f32[offset++] = member.originY === undefined ? 0.5 : member.originY; + + f32[offset++] = member.tintFill ? 1 : 0; + + f32[offset++] = member.creationTime || this.timeElapsed; + + f32[offset++] = member.scrollFactorX === undefined ? 1 : member.scrollFactorX; + f32[offset++] = member.scrollFactorY === undefined ? 1 : member.scrollFactorY; + + this.addData(this.nextMemberF32); + + return this; + }, + + /** + * Edits a member of the SpriteGPULayer. + * This will update the member's data in the GPU buffer. + * This is an expensive operation, as it requires the whole buffer to be updated. + * + * @method Phaser.GameObjects.SpriteGPULayer#editMember + * @since 4.0.0 + * @param {number} index - The index of the member to edit. + * @param {Partial} member - The new member data. + * @returns {this} This SpriteGPULayer object. + */ + editMember: function (index, member) + { + if (index < 0 || index >= this.memberCount) + { + return this; + } + + var currentMemberCount = this.memberCount; + this.memberCount = index; + this.addMember(member); + this.memberCount = currentMemberCount; + + return this; + }, + + /** + * Update a member of the SpriteGPULayer with raw data. + * This will update the member's data in the GPU buffer. + * This is an expensive operation, as it requires the whole buffer to be updated. + * + * You can supply a mask to control which properties are updated. + * This can be useful for updating only a subset of properties. + * Try using `getMemberData` to copy an existing member's data, + * then modify the data you want to change. + * + * The data must be passed in as an Uint32Array. + * This will preserve data that other TypedArrays would not. + * As it uses an underlying ArrayBuffer, you can work on the data + * with any TypedArray view before submitting it. + * + * @method Phaser.GameObjects.SpriteGPULayer#patchMember + * @since 4.0.0 + * @param {number} index - The index of the member to patch. + * @param {Uint32Array} member - The new member data. + * @param {number[]} [mask] - The mask to apply to the member data. A value of 1 will update the member data, a value of 0 will keep the existing member data. + */ + patchMember: function (index, member, mask) + { + if (index < 0 || index >= this.memberCount) + { + return; + } + + var layout = this.submitterNode.instanceBufferLayout; + var buffer = layout.buffer; + var stride = layout.layout.stride; + var byteOffset = index * stride; + var u32 = buffer.viewU32; + + var offset = byteOffset / 4; + + if (mask) + { + for (var i = 0; i < member.length; i++) + { + if (mask[i]) + { + u32[offset + i] = member[i]; + } + } + } + else + { + u32.set(member, offset); + } + + this.setSegmentNeedsUpdate(index); + }, + + /** + * Returns a member of the SpriteGPULayer. + * + * This returns an object copied from the buffer. + * Editing it will not change anything in the SpriteGPULayer. + * The object will be functionally identical to the data used to + * create the buffer, but some values may be different. + * + * - Properties that support animation, but have no amplitude or duration or have easing 'None' (0), will be presented as numbers. + * - Animation easing values will be presented as numbers (the values + * in `this.EASE`). + * - Animation delay values will be normalized to the duration, + * e.g. a delay of 150 with a duration of 100 will return 50. + * - Some rounding may occur due to floating point precision. + * + * @method Phaser.GameObjects.SpriteGPULayer#getMember + * @since 4.0.0 + * @param {number} index - The index of the member to get. + * @returns {?Phaser.Types.GameObjects.SpriteGPULayer.Member} The member data, or null if the index is out of bounds. + */ + getMember: function (index) + { + if (index < 0 || index >= this.memberCount) + { + return null; + } + + var layout = this.submitterNode.instanceBufferLayout; + var buffer = layout.buffer; + var stride = layout.layout.stride; + var byteOffset = index * stride; + var f32 = buffer.viewF32; + var u32 = buffer.viewU32; + + var member = {}; + + var offset = byteOffset / f32.BYTES_PER_ELEMENT; + + member.x = this._getAnimatedValue(offset); + offset += 4; + + member.y = this._getAnimatedValue(offset); + offset += 4; + + member.rotation = this._getAnimatedValue(offset); + offset += 4; + + member.scaleX = this._getAnimatedValue(offset); + offset += 4; + + member.scaleY = this._getAnimatedValue(offset); + offset += 4; + + member.alpha = this._getAnimatedValue(offset); + offset += 4; + + // Determine frame or animation values. + var frame = this._getAnimatedValue(offset); + offset += 4; + + if (typeof frame !== 'number') + { + frame = frame.base; + } + + // Get name from frame index. + var frameName = this.frameDataIndicesInv[frame]; + if (frameName === undefined) + { + // Get name from animation index. + var animData = this.animationDataIndices[frame]; + if (animData) + { + member.animation = animData.name; + } + } + else + { + member.frame = frameName; + } + + member.tintBlend = this._getAnimatedValue(offset); + offset += 4; + + member.tintBottomLeft = u32[offset++]; + member.tintTopLeft = u32[offset++]; + member.tintBottomRight = u32[offset++]; + member.tintTopRight = u32[offset++]; + member.alphaBottomLeft = (member.tintBottomLeft >>> 24) / 255; + member.alphaTopLeft = (member.tintTopLeft >>> 24) / 255; + member.alphaBottomRight = (member.tintBottomRight >>> 24) / 255; + member.alphaTopRight = (member.tintTopRight >>> 24) / 255; + member.tintBottomLeft &= 0xffffff; + member.tintTopLeft &= 0xffffff; + member.tintBottomRight &= 0xffffff; + member.tintTopRight &= 0xffffff; + + member.originX = f32[offset++]; + member.originY = f32[offset++]; + member.tintFill = !!f32[offset++]; + member.creationTime = f32[offset++]; + + member.scrollFactorX = f32[offset++]; + member.scrollFactorY = f32[offset++]; + + return member; + }, + + /** + * Returns the raw data of a member of the SpriteGPULayer. + * This can be useful as the base of efficient editing operations, + * including calls to `addData` and `patchMember`, + * so no data has to be converted. + * + * This returns an Uint32Array copied from the buffer. + * Editing it will not change anything in the SpriteGPULayer. + * The array will be functionally identical to the data used to + * create the buffer. + * + * By default, the data is copied into `this.nextMember`. + * You can use the views `this.nextMemberF32` and `this.nextMemberU32` + * to access the data in different formats. + * If you provide an `out` parameter, the data will be copied to that array, + * and you must construct your own views. + * + * The primary data view is a 41-element array of 32-bit floats. + * Some values are grouped to form animations, of the form: + * + * - 0: base value + * - 1: amplitude + * - 2: duration (if negative, the animation will yoyo) + * - 3: delay (the integer part is the easing, the decimal part is the delay divided by 2 * duration; if negative, the animation will not loop) + * + * The overall structure is thus: + * + * - 0-3: x (animation) + * - 4-7: y (animation) + * - 8-11: rotation (animation) + * - 12-15: scaleX (animation) + * - 16-19: scaleY (animation) + * - 20-23: alpha (animation) + * - 24-27: frame index (animation) + * - 28-31: tintBlend (animation) + * - 32-35: no data + * - 36: originX + * - 37: originY + * - 38: tintFill + * - 39: creationTime + * - 40: scrollFactorX + * - 41: scrollFactorY + * + * Elements 32-35 are only visible in the Uint32Array view. + * They store 32-bit RGBA values for the four corners of the tint: + * + * - 32: bottom-left + * - 33: top-left + * - 34: bottom-right + * - 35: top-right + * + * If the ease for an animation is 'Gravity', the amplitude is replaced + * with a two-part value: the integer part is the `velocity`, + * and the fractional part is the `gravityFactor`. + * + * @method Phaser.GameObjects.SpriteGPULayer#getMemberData + * @since 4.0.0 + * @param {number} index - The index of the member to get. + * @param {Uint32Array} [out] - An optional array to copy the data to. If not provided, `this.nextMember` will be populated, and `nextMemberU32` will be returned. + * @returns {?Uint32Array} The member data, or null if the index is out of bounds. + */ + getMemberData: function (index, out) + { + if (index < 0 || index >= this.memberCount) + { + return null; + } + + var layout = this.submitterNode.instanceBufferLayout; + var buffer = layout.buffer; + var stride = layout.layout.stride; + var byteOffset = index * stride; + + if (!out) + { + out = this.nextMemberU32; + } + + var viewU32 = buffer.viewU32; + var bytesPerElement = viewU32.BYTES_PER_ELEMENT; + + out.set(viewU32.subarray(byteOffset / bytesPerElement, byteOffset / bytesPerElement + stride / bytesPerElement)); + + return out; + }, + + /** + * Removes a member or a number of members from the SpriteGPULayer. + * This will update the GPU buffer. + * This is an expensive operation, as it requires the whole buffer to be updated. + * + * The buffer is not resized. + * + * @method Phaser.GameObjects.SpriteGPULayer#removeMembers + * @since 4.0.0 + * @param {number} index - The index of the member to remove. + * @param {number} [count=1] - The number of members to remove, default 1. + * @returns {this} This SpriteGPULayer object. + */ + removeMembers: function (index, count) + { + if (index < 0 || index >= this.memberCount) + { + return this; + } + + if (count === undefined) + { + count = 1; + } + + count = Math.min(count, this.memberCount - index); + + var layout = this.submitterNode.instanceBufferLayout; + var stride = layout.layout.stride; + var byteOffset = index * stride; + var byteLength = count * stride; + + var u8 = layout.buffer.viewU8; + u8.set(u8.subarray(byteOffset + byteLength), byteOffset); + + // Mark segments for update. + for (var i = index; i < this.memberCount; i += this.bufferUpdateSegmentSize) + { + this.setSegmentNeedsUpdate(i); + } + + // Update layer properties. + this.memberCount -= count; + + return this; + }, + + /** + * Inserts members into the SpriteGPULayer. + * This will update the GPU buffer. + * This is an expensive operation, as it requires the whole buffer to be + * updated after the insertion point. + * + * @method Phaser.GameObjects.SpriteGPULayer#insertMembers + * @since 4.0.0 + * @param {number} index - The index at which to insert members. + * @param {Phaser.Types.GameObjects.SpriteGPULayer.Member|Phaser.Types.GameObjects.SpriteGPULayer.Member[]} members - The members to insert. + * @returns {this} This SpriteGPULayer object. + */ + insertMembers: function (index, members) + { + if (index < 0 || index > this.memberCount) + { + return this; + } + + if (!Array.isArray(members)) + { + members = [ members ]; + } + + var oldMemberCount = this.memberCount; + var layout = this.submitterNode.instanceBufferLayout; + var stride = layout.layout.stride; + var byteOffset = index * stride; + var byteLength = members.length * stride; + + // Move the data after the insertion point. + layout.buffer.viewU8.copyWithin( + + // Target + byteOffset + byteLength, + + // Source + byteOffset, + + // End + oldMemberCount * stride + ); + + // Insert members. + this.memberCount = index; + for (var i = 0; i < members.length; i++) + { + this.addMember(members[i]); + } + + this.memberCount = Math.min(this.size, oldMemberCount + members.length); + + // Mark segments for update. + for (i = index; i < this.memberCount; i += this.bufferUpdateSegmentSize) + { + this.setSegmentNeedsUpdate(i); + } + + return this; + }, + + /** + * Inserts raw data into the SpriteGPULayer. + * This will update the GPU buffer. + * This is an expensive operation, as it requires the whole buffer to be + * updated after the insertion point. + * + * The data must be passed in as a Uint32Array. + * This will preserve data that other TypedArrays would not. + * As it uses an underlying ArrayBuffer, you can work on the data + * with any TypedArray view before submitting it. + * + * The buffer can contain 1 or more members. + * Ensure that the buffer is the correct size for the number of members. + * See `getMemberData` for the structure of the data. + * + * Note that, if you add a member with an animation, + * the animation must either already be enabled, + * or you must enable it with `setAnimationEnabled`, + * e.g. `layer.setAnimationEnabled('Linear', true)` or + * `layer.setAnimationEnabled(layer.EASE_CODES[layer.EASE.Linear], true)`. + * + * @method Phaser.GameObjects.SpriteGPULayer#insertMembersData + * @since 4.0.0 + * @param {number} index - The index at which to insert members. + * @param {Uint32Array} data - The members to insert. + * @returns {this} This SpriteGPULayer object. + */ + insertMembersData: function (index, data) + { + if (index < 0 || index > this.memberCount) + { + return this; + } + + var byteLength = data.length * data.BYTES_PER_ELEMENT; + var layout = this.submitterNode.instanceBufferLayout; + var stride = layout.layout.stride; + var byteOffset = index * stride; + + // Move the data after the insertion point. + layout.buffer.viewU8.copyWithin( + + // Target + byteOffset + byteLength, + + // Source + byteOffset, + + // End + this.memberCount * stride + ); + + // Insert members. + layout.buffer.viewU32.set(data, byteOffset / data.BYTES_PER_ELEMENT); + + this.memberCount = Math.min(this.size, this.memberCount + byteLength / stride); + + // Mark segments for update. + for (var i = index; i < this.memberCount; i += this.bufferUpdateSegmentSize) + { + this.setSegmentNeedsUpdate(i); + } + + return this; + }, + + /** + * Sets the values of an animation for a member of this SpriteGPULayer. + * The values are set on `nextMember`, used to add data. + * + * @method Phaser.GameObjects.SpriteGPULayer#_setAnimatedValue + * @since 4.0.0 + * @private + * @param {undefined|number|Phaser.Types.GameObjects.SpriteGPULayer.MemberAnimation} value - The value to set. + * @param {number} index - The offset in `nextMember` to write to. + * @param {number} [defaultValue=0] - A default value to use if `value` is undefined. + */ + _setAnimatedValue: function (value, index, defaultValue) + { + var f32 = this.nextMemberF32; + + if (defaultValue === undefined) + { + defaultValue = 0; + } + + if (typeof value === 'number') + { + f32[index++] = value; + f32[index++] = 0; + f32[index++] = 0; + f32[index] = 0; + } + else if (value === undefined) + { + f32[index++] = defaultValue; + f32[index++] = 0; + f32[index++] = 0; + f32[index] = 0; + } + else + { + var base = value.base || 0; + var ease = value.ease || 0; + var amplitude = value.amplitude || 0; + var duration = Math.abs(value.duration || 0); + var delay = value.delay || 0; + var yoyo = value.yoyo !== undefined ? value.yoyo : true; + var loop = value.loop !== undefined ? value.loop : true; + + if (typeof ease === 'string') + { + ease = this.EASE[ease] || 0; + } + + // Enable the chosen animation type. + var easeString = this.EASE_CODES[ease]; + if (!this._animationsEnabled[easeString]) + { + this.setAnimationEnabled(easeString, true); + } + + if (ease === EasingEncoding.Gravity) + { + var velocity = value.velocity || 0; + var gravityFactor = value.gravityFactor || 1; + + if (gravityFactor >= 1) + { + gravityFactor = 0; + } + else if (gravityFactor < -1) + { + gravityFactor = -0.999; + } + + // Map gravityFactor range [-1,1] to [0,1]. + gravityFactor = (gravityFactor + 1) / 2; + + // Encode values into amplitude. + amplitude = Math.floor(velocity) + gravityFactor; + } + + // Normalize delay. + // We double the range of the delay to allow for yoyo. + if (duration > 0) + { + delay = (delay / duration) % 2; + } + else + { + delay = 0; + } + if (delay < 0) + { + delay += 2; + } + delay /= 2; + + // Add an integer to encode the type. + delay += ease; + + // Encode yoyo in the sign of duration, which must be positive. + if (yoyo) + { + duration = -duration; + } + + // Encode loop in the sign of delay, which must be positive. + if (!loop) + { + delay = -delay; + } + + f32[index++] = base; + f32[index++] = amplitude; + f32[index++] = duration; + f32[index] = delay; + } + }, + + /** + * Return the values of an animation for a member of this SpriteGPULayer + * in the buffer. + * + * @method Phaser.GameObjects.SpriteGPULayer#_getAnimatedValue + * @since 4.0.0 + * @private + * @param {number} index - The index where the animation begins in the buffer. + * @returns {number|Phaser.Types.GameObjects.SpriteGPULayer.MemberAnimation} The animation values. + */ + _getAnimatedValue: function (index) + { + var f32 = this.submitterNode.instanceBufferLayout.buffer.viewF32; + + var base = f32[index++]; + var amplitude = f32[index++]; + var duration = f32[index++]; + var delay = f32[index]; + + if (amplitude === 0 || duration === 0 || ease === 0) + { + return base; + } + + var loop = delay > 0; + if (!loop) + { + delay = -delay; + } + + var yoyo = duration < 0; + if (yoyo) + { + duration = -duration; + } + + // Negate ease after duration, so duration has the correct sign. + var ease = Math.floor(delay); + delay -= ease; + delay = (delay * duration * 2) % duration; + + // Check for Gravity mode. + if (ease === EasingEncoding.Gravity) + { + var velocity = Math.floor(amplitude); + var gravityFactor = (amplitude - velocity) * 2 - 1; + if (gravityFactor === 0) + { + gravityFactor = 1; + } + return { + base: base, + ease: ease, + duration: duration, + delay: delay, + yoyo: yoyo, + velocity: velocity, + gravityFactor: gravityFactor + }; + } + + return { + base: base, + ease: ease, + amplitude: amplitude, + duration: duration, + delay: delay, + yoyo: yoyo + }; + }, + + /** + * Set the enabled state of an animation. + * This will enable or disable the animation in the shader program. + * This method is called automatically when animations are added with + * `addMember`, so you should not need to call it manually. + * + * Every enabled animation has a cost in the shader program. + * In particular, low-end devices may be unable to compile a large number + * of animations, so be careful when enabling many animations. + * + * Note that animations are not disabled automatically, + * even if they are not used by any members. + * There are probably too many members for this to be efficient. + * + * @method Phaser.GameObjects.SpriteGPULayer#setAnimationEnabled + * @since 4.0.0 + * @param {string} name - The name of the animation to enable or disable. + * @param {boolean} enabled - Whether to enable or disable the animation. + * @returns {this} This SpriteGPULayer object + */ + setAnimationEnabled: function (name, enabled) + { + this._animationsEnabled[name] = !!enabled; + + return this; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.SpriteGPULayer#preDestroy + * @protected + * @since 4.0.0 + */ + preDestroy: function () + { + this.frameDataTexture.destroy(); + + // TODO: Destroy the Submitter RenderNode. + } +}); + +module.exports = SpriteGPULayer; + + +/***/ }), + +/***/ 16193: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlendModes = __webpack_require__(10312); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var SpriteGPULayer = __webpack_require__(76573); + +/** + * Creates a new SpriteGPULayer Game Object and returns it. + * + * Note: This method will only be available if the SpriteGPULayer Game Object + * has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#spriteGPULayer + * @since 4.0.0 + * + * @param {Phaser.Types.GameObjects.SpriteGPULayer.SpriteGPULayerConfig} config - The configuration object this Game Object will use to create itself. Must include `{ size: number }`. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.SpriteGPULayer} The Game Object that was created. + */ +GameObjectCreator.register('spriteGPULayer', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var size = GetAdvancedValue(config, 'size', 1); + + var gpuLayer = new SpriteGPULayer(this.scene, key, size); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + // Alpha + gpuLayer.alpha = GetAdvancedValue(config, 'alpha', 1); + + // Blend Mode + gpuLayer.blendMode = GetAdvancedValue(config, 'blendMode', BlendModes.NORMAL); + + // Visible + gpuLayer.visible = GetAdvancedValue(config, 'visible', true); + + if (addToScene) + { + this.scene.sys.displayList.add(gpuLayer); + } + + return gpuLayer; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 96019: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SpriteGPULayer = __webpack_require__(76573); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new SpriteGPULayer Game Object and adds it to the Scene. + * + * Note: This method will only be available if the SpriteGPULayer Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#spriteGPULayer + * @since 4.0.0 + * + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {number} [size] - The number of members the SpriteGPULayer will accommodate. Default 1. + * + * @return {Phaser.GameObjects.SpriteGPULayer} The Game Object that was created. + */ +GameObjectFactory.register('spriteGPULayer', function (texture, size) +{ + return this.displayList.add(new SpriteGPULayer(this.scene, texture, size)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 71238: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = __webpack_require__(97591); +var renderCanvas = NOOP; + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 97591: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.SpriteGPULayer#renderWebGL + * @since 4.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested. + */ +var SpriteGPULayerWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + drawingContext.camera.addToRenderList(src); + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext + ); +}; + +module.exports = SpriteGPULayerWebGLRenderer; + + +/***/ }), + +/***/ 14727: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultStampNodes = __webpack_require__(78705); +var Class = __webpack_require__(83419); +var Image = __webpack_require__(88571); +var StampRender = __webpack_require__(74759); + +/** + * @classdesc + * A Stamp Game Object. + * + * A Stamp is a light-weight Game Object which ignores camera scroll and transform, + * so it is rendered at a fixed position on-screen. + * This is useful for HUDs, counters, etc. + * Its main role is for DynamicTexture rendering. + * It is otherwise similar to Image. + * + * @class Stamp + * @extends Phaser.GameObjects.Image + * @memberof Phaser.GameObjects + * @constructor + * @since 4.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.TextureCrop + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + */ +var Stamp = new Class({ + Extends: Image, + + Mixins: [ + StampRender + ], + + initialize: function Stamp (scene, x, y, texture, frame) + { + Image.call(this, scene, x, y, texture, frame); + + this.type = 'Stamp'; + }, + + _defaultRenderNodesMap: { + get: function () + { + return DefaultStampNodes; + } + } +}); + +module.exports = Stamp; + + +/***/ }), + +/***/ 656: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); + +var tempMatrix = new TransformMatrix(); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Stamp#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Stamp} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + */ +var StampCanvasRenderer = function (renderer, src, camera) +{ + camera.addToRenderList(src); + + tempMatrix.copyFrom(camera.matrix); + camera.matrix.loadIdentity(); + var scrollX = camera.scrollX; + var scrollY = camera.scrollY; + camera.scrollX = 0; + camera.scrollY = 0; + + renderer.batchSprite(src, src.frame, camera); + + camera.scrollX = scrollX; + camera.scrollY = scrollY; + camera.matrix.copyFrom(tempMatrix); +}; + +module.exports = StampCanvasRenderer; + + +/***/ }), + +/***/ 31479: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Stamp = __webpack_require__(14727); + +/** + * Creates a new Stamp Game Object and returns it. + * + * Note: This method will only be available if the Stamp Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#stamp + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Stamp} The Game Object that was created. + */ +GameObjectCreator.register('stamp', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + var frame = GetAdvancedValue(config, 'frame', null); + + var stamp = new Stamp(this.scene, 0, 0, key, frame); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, stamp, config); + + return stamp; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 85326: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Stamp = __webpack_require__(14727); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Stamp Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Stamp Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#stamp + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.GameObjects.Stamp} The Game Object that was created. + */ +GameObjectFactory.register('stamp', function (x, y, texture, frame) +{ + return this.displayList.add(new Stamp(this.scene, x, y, texture, frame)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 74759: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// The Stamp inherits WebGL rendering properties from the Image class. + +var NOOP = __webpack_require__(29747); +var renderCanvas = NOOP; + +if (true) +{ + renderCanvas = __webpack_require__(656); +} + +module.exports = { + + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 14220: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns an object containing dimensions of the Text object. + * + * @function Phaser.GameObjects.GetTextSize + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Text} text - The Text object to calculate the size from. + * @param {Phaser.Types.GameObjects.Text.TextMetrics} size - The Text metrics to use when calculating the size. + * @param {string[]} lines - The lines of text to calculate the size from. + * + * @return {Phaser.Types.GameObjects.Text.GetTextSizeObject} An object containing dimensions of the Text object. + */ +var GetTextSize = function (text, size, lines) +{ + var canvas = text.canvas; + var context = text.context; + var style = text.style; + + var lineWidths = []; + var maxLineWidth = 0; + var drawnLines = lines.length; + + if (style.maxLines > 0 && style.maxLines < lines.length) + { + drawnLines = style.maxLines; + } + + style.syncFont(canvas, context); + + // Text Width + var letterSpacing = text.letterSpacing; + + for (var i = 0; i < drawnLines; i++) + { + var lineWidth = style.strokeThickness; + + if (letterSpacing === 0) + { + lineWidth += context.measureText(lines[i]).width; + } + else + { + var line = lines[i]; + + for (var j = 0; j < line.length; j++) + { + lineWidth += context.measureText(line[j]).width; + } + + if (line.length > 1) + { + lineWidth += letterSpacing * (line.length - 1); + } + } + + // Adjust for wrapped text + if (style.wordWrap) + { + lineWidth -= context.measureText(' ').width; + } + + lineWidths[i] = Math.ceil(lineWidth); + maxLineWidth = Math.max(maxLineWidth, lineWidths[i]); + } + + // Text Height + + var lineHeight = size.fontSize + style.strokeThickness; + var height = lineHeight * drawnLines; + var lineSpacing = text.lineSpacing; + + // Adjust for line spacing + if (drawnLines > 1) + { + height += lineSpacing * (drawnLines - 1); + } + + return { + width: maxLineWidth, + height: height, + lines: drawnLines, + lineWidths: lineWidths, + lineSpacing: lineSpacing, + lineHeight: lineHeight + }; +}; + +module.exports = GetTextSize; + + +/***/ }), + +/***/ 79557: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasPool = __webpack_require__(27919); + +/** + * Calculates the ascent, descent and fontSize of a given font style. + * + * @function Phaser.GameObjects.MeasureText + * @since 3.0.0 + * + * @param {Phaser.GameObjects.TextStyle} textStyle - The TextStyle object to measure. + * + * @return {Phaser.Types.GameObjects.Text.TextMetrics} An object containing the ascent, descent and fontSize of the TextStyle. + */ +var MeasureText = function (textStyle) +{ + var canvas = CanvasPool.create(this); + var context = canvas.getContext('2d', { willReadFrequently: true }); + + textStyle.syncFont(canvas, context); + + var metrics = context.measureText(textStyle.testString); + + if ('actualBoundingBoxAscent' in metrics) + { + var ascent = metrics.actualBoundingBoxAscent; + var descent = metrics.actualBoundingBoxDescent; + + CanvasPool.remove(canvas); + + return { + ascent: ascent, + descent: descent, + fontSize: ascent + descent + }; + } + + var width = Math.ceil(metrics.width * textStyle.baselineX); + var baseline = width; + var height = 2 * baseline; + + baseline = baseline * textStyle.baselineY | 0; + + canvas.width = width; + canvas.height = height; + + context.fillStyle = '#f00'; + context.fillRect(0, 0, width, height); + + context.font = textStyle._font; + + context.textBaseline = 'alphabetic'; + context.fillStyle = '#000'; + context.fillText(textStyle.testString, 0, baseline); + + var output = { + ascent: 0, + descent: 0, + fontSize: 0 + }; + + var imagedata = context.getImageData(0, 0, width, height); + + if (!imagedata) + { + output.ascent = baseline; + output.descent = baseline + 6; + output.fontSize = output.ascent + output.descent; + + CanvasPool.remove(canvas); + + return output; + } + + var pixels = imagedata.data; + var numPixels = pixels.length; + var line = width * 4; + var i; + var j; + var idx = 0; + var stop = false; + + // ascent. scan from top to bottom until we find a non red pixel + for (i = 0; i < baseline; i++) + { + for (j = 0; j < line; j += 4) + { + if (pixels[idx + j] !== 255) + { + stop = true; + break; + } + } + + if (!stop) + { + idx += line; + } + else + { + break; + } + } + + output.ascent = baseline - i; + + idx = numPixels - line; + stop = false; + + // descent. scan from bottom to top until we find a non red pixel + for (i = height; i > baseline; i--) + { + for (j = 0; j < line; j += 4) + { + if (pixels[idx + j] !== 255) + { + stop = true; + break; + } + } + + if (!stop) + { + idx -= line; + } + else + { + break; + } + } + + output.descent = (i - baseline); + output.fontSize = output.ascent + output.descent; + + CanvasPool.remove(canvas); + + return output; +}; + +module.exports = MeasureText; + + +/***/ }), + +/***/ 50171: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AddToDOM = __webpack_require__(40366); +var CanvasPool = __webpack_require__(27919); +var DefaultImageNodes = __webpack_require__(40939); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var GetTextSize = __webpack_require__(14220); +var GetValue = __webpack_require__(35154); +var RemoveFromDOM = __webpack_require__(35846); +var TextRender = __webpack_require__(61771); +var TextStyle = __webpack_require__(35762); +var UUID = __webpack_require__(45650); + +/** + * @classdesc + * A Text Game Object. + * + * Text objects work by creating their own internal hidden Canvas and then renders text to it using + * the standard Canvas `fillText` API. It then creates a texture from this canvas which is rendered + * to your game during the render pass. + * + * Because it uses the Canvas API you can take advantage of all the features this offers, such as + * applying gradient fills to the text, or strokes, shadows and more. You can also use custom fonts + * loaded externally, such as Google or TypeKit Web fonts. + * + * **Important:** The font name must be quoted if it contains certain combinations of digits or + * special characters, either when creating the Text object, or when setting the font via `setFont` + * or `setFontFamily`, e.g.: + * + * ```javascript + * this.add.text(0, 0, 'Hello World', { fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif' }); + * ``` + * + * ```javascript + * this.add.text(0, 0, 'Hello World', { font: '"Press Start 2P"' }); + * ``` + * + * You can only display fonts that are currently loaded and available to the browser: therefore fonts must + * be pre-loaded. Phaser does not do this for you, so you will require the use of a 3rd party font loader, + * or have the fonts ready available in the CSS on the page in which your Phaser game resides. + * + * See {@link http://www.jordanm.co.uk/tinytype this compatibility table} for the available default fonts + * across mobile browsers. + * + * A note on performance: Every time the contents of a Text object changes, i.e. changing the text being + * displayed, or the style of the text, it needs to remake the Text canvas, and if on WebGL, re-upload the + * new texture to the GPU. This can be an expensive operation if used often, or with large quantities of + * Text objects in your game. If you run into performance issues you would be better off using Bitmap Text + * instead, as it benefits from batching and avoids expensive Canvas API calls. + * + * @class Text + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize + * @extends Phaser.GameObjects.Components.Crop + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|string[])} text - The text this Text object will display. + * @param {Phaser.Types.GameObjects.Text.TextStyle} style - The text style configuration object. + * + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#Valid_family_names + */ +var Text = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.ComputedSize, + Components.Crop, + Components.Depth, + Components.Flip, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.Tint, + Components.Transform, + Components.Visible, + TextRender + ], + + initialize: + + function Text (scene, x, y, text, style) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + GameObject.call(this, scene, 'Text'); + + /** + * The renderer in use by this Text object. + * + * @name Phaser.GameObjects.Text#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.12.0 + */ + this.renderer = scene.sys.renderer; + + this.setPosition(x, y); + this.setOrigin(0, 0); + this.initRenderNodes(this._defaultRenderNodesMap); + + /** + * The canvas element that the text is rendered to. + * + * @name Phaser.GameObjects.Text#canvas + * @type {HTMLCanvasElement} + * @since 3.0.0 + */ + this.canvas = CanvasPool.create(this); + + /** + * The context of the canvas element that the text is rendered to. + * + * @name Phaser.GameObjects.Text#context + * @type {CanvasRenderingContext2D} + * @since 3.0.0 + */ + this.context; + + /** + * The Text Style object. + * + * Manages the style of this Text object. + * + * @name Phaser.GameObjects.Text#style + * @type {Phaser.GameObjects.TextStyle} + * @since 3.0.0 + */ + this.style = new TextStyle(this, style); + + /** + * Whether to automatically round line positions. + * + * @name Phaser.GameObjects.Text#autoRound + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.autoRound = true; + + /** + * The Regular Expression that is used to split the text up into lines, in + * multi-line text. By default this is `/(?:\r\n|\r|\n)/`. + * You can change this RegExp to be anything else that you may need. + * + * @name Phaser.GameObjects.Text#splitRegExp + * @type {object} + * @since 3.0.0 + */ + this.splitRegExp = /(?:\r\n|\r|\n)/; + + /** + * The text to display. + * + * @name Phaser.GameObjects.Text#_text + * @type {string} + * @private + * @since 3.12.0 + */ + this._text = undefined; + + /** + * Specify a padding value which is added to the line width and height when calculating the Text size. + * Allows you to add extra spacing if the browser is unable to accurately determine the true font dimensions. + * + * @name Phaser.GameObjects.Text#padding + * @type {Phaser.Types.GameObjects.Text.TextPadding} + * @since 3.0.0 + */ + this.padding = { left: 0, right: 0, top: 0, bottom: 0 }; + + /** + * The width of this Text object. + * + * @name Phaser.GameObjects.Text#width + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.width = 1; + + /** + * The height of this Text object. + * + * @name Phaser.GameObjects.Text#height + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.height = 1; + + /** + * The line spacing value. + * This value is added to the font height to calculate the overall line height. + * Only has an effect if this Text object contains multiple lines of text. + * + * If you update this property directly, instead of using the `setLineSpacing` method, then + * be sure to call `updateText` after, or you won't see the change reflected in the Text object. + * + * @name Phaser.GameObjects.Text#lineSpacing + * @type {number} + * @since 3.13.0 + */ + this.lineSpacing = 0; + + /** + * Adds / Removes spacing between characters. + * Can be a negative or positive number. + * + * If you update this property directly, instead of using the `setLetterSpacing` method, then + * be sure to call `updateText` after, or you won't see the change reflected in the Text object. + * + * @name Phaser.GameObjects.Text#letterSpacing + * @type {number} + * @since 3.60.0 + */ + this.letterSpacing = 0; + + // If resolution wasn't set, force it to 1 + if (this.style.resolution === 0) + { + this.style.resolution = 1; + } + + /** + * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method. + * + * @name Phaser.GameObjects.Text#_crop + * @type {object} + * @private + * @since 3.12.0 + */ + this._crop = this.resetCropObject(); + + /** + * The internal unique key to refer to the texture in the TextureManager. + * + * @name Phaser.GameObjects.Text#_textureKey + * @type {string} + * @private + * @since 3.80.0 + */ + this._textureKey = UUID(); + + // Create a Texture for this Text object + this.texture = scene.sys.textures.addCanvas(this._textureKey, this.canvas); + + // Set the context to be the CanvasTexture context + this.context = this.texture.context; + + // Get the frame + this.frame = this.texture.get(); + + // Set the resolution + this.frame.source.resolution = this.style.resolution; + + if (this.renderer && this.renderer.gl) + { + // Clear the default 1x1 glTexture, as we override it later + this.renderer.deleteTexture(this.frame.source.glTexture); + + this.frame.source.glTexture = null; + } + + this.initRTL(); + + this.setText(text); + + if (style && style.padding) + { + this.setPadding(style.padding); + } + + if (style && style.lineSpacing) + { + this.setLineSpacing(style.lineSpacing); + } + + if (style && style.letterSpacing) + { + this.setLetterSpacing(style.letterSpacing); + } + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.Text#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultImageNodes; + } + }, + + /** + * Initialize right to left text. + * + * @method Phaser.GameObjects.Text#initRTL + * @since 3.0.0 + */ + initRTL: function () + { + if (!this.style.rtl) + { + this.canvas.dir = 'ltr'; + this.context.direction = 'ltr'; + return; + } + + // Here is where the crazy starts. + // + // Due to browser implementation issues, you cannot fillText BiDi text to a canvas + // that is not part of the DOM. It just completely ignores the direction property. + + this.canvas.dir = 'rtl'; + + // Experimental atm, but one day ... + this.context.direction = 'rtl'; + + // Add it to the DOM, but hidden within the parent canvas. + this.canvas.style.display = 'none'; + + AddToDOM(this.canvas, this.scene.sys.canvas); + + // And finally we set the x origin + this.originX = 1; + }, + + /** + * Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal + * bounds. + * + * @method Phaser.GameObjects.Text#runWordWrap + * @since 3.0.0 + * + * @param {string} text - The text to perform word wrap detection against. + * + * @return {string} The text after wrapping has been applied. + */ + runWordWrap: function (text) + { + var style = this.style; + + if (style.wordWrapCallback) + { + var wrappedLines = style.wordWrapCallback.call(style.wordWrapCallbackScope, text, this); + + if (Array.isArray(wrappedLines)) + { + wrappedLines = wrappedLines.join('\n'); + } + + return wrappedLines; + } + else if (style.wordWrapWidth) + { + if (style.wordWrapUseAdvanced) + { + return this.advancedWordWrap(text, this.context, this.style.wordWrapWidth); + } + else + { + return this.basicWordWrap(text, this.context, this.style.wordWrapWidth); + } + } + else + { + return text; + } + }, + + /** + * Advanced wrapping algorithm that will wrap words as the line grows longer than its horizontal + * bounds. Consecutive spaces will be collapsed and replaced with a single space. Lines will be + * trimmed of white space before processing. Throws an error if wordWrapWidth is less than a + * single character. + * + * @method Phaser.GameObjects.Text#advancedWordWrap + * @since 3.0.0 + * + * @param {string} text - The text to perform word wrap detection against. + * @param {CanvasRenderingContext2D} context - The Canvas Rendering Context. + * @param {number} wordWrapWidth - The word wrap width. + * + * @return {string} The wrapped text. + */ + advancedWordWrap: function (text, context, wordWrapWidth) + { + var output = ''; + + // Condense consecutive spaces and split into lines + var lines = text + .replace(/ +/gi, ' ') + .split(this.splitRegExp); + + var linesCount = lines.length; + + for (var i = 0; i < linesCount; i++) + { + var line = lines[i]; + var out = ''; + + // Trim whitespace + line = line.replace(/^ *|\s*$/gi, ''); + + // If entire line is less than wordWrapWidth append the entire line and exit early + var lineLetterSpacingWidth = line.length * this.letterSpacing; + var lineWidth = context.measureText(line).width + lineLetterSpacingWidth; + + if (lineWidth < wordWrapWidth) + { + output += line + '\n'; + continue; + } + + // Otherwise, calculate new lines + var currentLineWidth = wordWrapWidth; + + // Split into words + var words = line.split(' '); + + for (var j = 0; j < words.length; j++) + { + var word = words[j]; + var wordWithSpace = word + ' '; + var letterSpacingWidth = wordWithSpace.length * this.letterSpacing; + var wordWidth = context.measureText(wordWithSpace).width + letterSpacingWidth; + + if (wordWidth > currentLineWidth) + { + // Break word + if (j === 0) + { + // Shave off letters from word until it's small enough + var newWord = wordWithSpace; + + while (newWord.length) + { + newWord = newWord.slice(0, -1); + var newLetterSpacingWidth = newWord.length * this.letterSpacing; + wordWidth = context.measureText(newWord).width + newLetterSpacingWidth; + + if (wordWidth <= currentLineWidth) + { + break; + } + } + + // If wordWrapWidth is too small for even a single letter, shame user + // failure with a fatal error + if (!newWord.length) + { + throw new Error('wordWrapWidth < a single character'); + } + + // Replace current word in array with remainder + var secondPart = word.substr(newWord.length); + + words[j] = secondPart; + + // Append first piece to output + out += newWord; + } + + // If existing word length is 0, don't include it + var offset = (words[j].length) ? j : j + 1; + + // Collapse rest of sentence and remove any trailing white space + var remainder = words.slice(offset).join(' ').replace(/[ \n]*$/gi, ''); + + // Prepend remainder to next line + lines.splice(i + 1, 0, remainder); + + linesCount = lines.length; + break; // Processing on this line + + // Append word with space to output + } + else + { + out += wordWithSpace; + currentLineWidth -= wordWidth; + } + } + + // Append processed line to output + output += out.replace(/[ \n]*$/gi, '') + '\n'; + } + + // Trim the end of the string + output = output.replace(/[\s|\n]*$/gi, ''); + + return output; + }, + + /** + * Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal + * bounds. Spaces are not collapsed and whitespace is not trimmed. + * + * @method Phaser.GameObjects.Text#basicWordWrap + * @since 3.0.0 + * + * @param {string} text - The text to perform word wrap detection against. + * @param {CanvasRenderingContext2D} context - The Canvas Rendering Context. + * @param {number} wordWrapWidth - The word wrap width. + * + * @return {string} The wrapped text. + */ + basicWordWrap: function (text, context, wordWrapWidth) + { + var result = ''; + var lines = text.split(this.splitRegExp); + var lastLineIndex = lines.length - 1; + var whiteSpaceWidth = context.measureText(' ').width; + + for (var i = 0; i <= lastLineIndex; i++) + { + var spaceLeft = wordWrapWidth; + var words = lines[i].split(' '); + var lastWordIndex = words.length - 1; + + for (var j = 0; j <= lastWordIndex; j++) + { + var word = words[j]; + var letterSpacingWidth = word.length * this.letterSpacing; + var wordWidth = context.measureText(word).width + letterSpacingWidth; + var wordWidthWithSpace = wordWidth; + + if (j < lastWordIndex) + { + wordWidthWithSpace += whiteSpaceWidth; + } + + if (wordWidthWithSpace > spaceLeft) + { + // Skip printing the newline if it's the first word of the line that is greater + // than the word wrap width. + if (j > 0) + { + result += '\n'; + spaceLeft = wordWrapWidth; + } + } + + result += word; + + if (j < lastWordIndex) + { + result += ' '; + spaceLeft -= wordWidthWithSpace; + } + else + { + spaceLeft -= wordWidth; + } + } + + if (i < lastLineIndex) + { + result += '\n'; + } + } + + return result; + }, + + /** + * Runs the given text through this Text objects word wrapping and returns the results as an + * array, where each element of the array corresponds to a wrapped line of text. + * + * @method Phaser.GameObjects.Text#getWrappedText + * @since 3.0.0 + * + * @param {string} [text] - The text for which the wrapping will be calculated. If unspecified, the Text objects current text will be used. + * + * @return {string[]} An array of strings with the pieces of wrapped text. + */ + getWrappedText: function (text) + { + if (text === undefined) { text = this._text; } + + this.style.syncFont(this.canvas, this.context); + + var wrappedLines = this.runWordWrap(text); + + return wrappedLines.split(this.splitRegExp); + }, + + /** + * Set the text to display. + * + * An array of strings will be joined with `\n` line breaks. + * + * @method Phaser.GameObjects.Text#setText + * @since 3.0.0 + * + * @param {(string|string[])} value - The string, or array of strings, to be set as the content of this Text object. + * + * @return {this} This Text object. + */ + setText: function (value) + { + if (!value && value !== 0) + { + value = ''; + } + + if (Array.isArray(value)) + { + value = value.join('\n'); + } + + if (value !== this._text) + { + this._text = value.toString(); + + this.updateText(); + } + + return this; + }, + + /** + * Appends the given text to the content already being displayed by this Text object. + * + * An array of strings will be joined with `\n` line breaks. + * + * @method Phaser.GameObjects.Text#appendText + * @since 3.60.0 + * + * @param {(string|string[])} value - The string, or array of strings, to be appended to the existing content of this Text object. + * @param {boolean} [addCR=true] - Insert a carriage-return before the string value. + * + * @return {this} This Text object. + */ + appendText: function (value, addCR) + { + if (addCR === undefined) { addCR = true; } + + if (!value && value !== 0) + { + value = ''; + } + + if (Array.isArray(value)) + { + value = value.join('\n'); + } + + value = value.toString(); + + var newText = this._text.concat((addCR) ? '\n' + value : value); + + if (newText !== this._text) + { + this._text = newText; + + this.updateText(); + } + + return this; + }, + + /** + * Set the text style. + * + * @example + * text.setStyle({ + * fontSize: '64px', + * fontFamily: 'Arial', + * color: '#ffffff', + * align: 'center', + * backgroundColor: '#ff00ff' + * }); + * + * @method Phaser.GameObjects.Text#setStyle + * @since 3.0.0 + * + * @param {object} style - The style settings to set. + * + * @return {this} This Text object. + */ + setStyle: function (style) + { + return this.style.setStyle(style); + }, + + /** + * Set the font. + * + * If a string is given, the font family is set. + * + * If an object is given, the `fontFamily`, `fontSize` and `fontStyle` + * properties of that object are set. + * + * **Important:** The font name must be quoted if it contains certain combinations of digits or + * special characters: + * + * ```javascript + * Text.setFont('"Press Start 2P"'); + * ``` + * + * Equally, if you wish to provide a list of fallback fonts, then you should ensure they are all + * quoted properly, too: + * + * ```javascript + * Text.setFont('Georgia, "Goudy Bookletter 1911", Times, serif'); + * ``` + * + * @method Phaser.GameObjects.Text#setFont + * @since 3.0.0 + * + * @param {string} font - The font family or font settings to set. + * + * @return {this} This Text object. + * + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#Valid_family_names + */ + setFont: function (font) + { + return this.style.setFont(font); + }, + + /** + * Set the font family. + * + * **Important:** The font name must be quoted if it contains certain combinations of digits or + * special characters: + * + * ```javascript + * Text.setFont('"Press Start 2P"'); + * ``` + * + * Equally, if you wish to provide a list of fallback fonts, then you should ensure they are all + * quoted properly, too: + * + * ```javascript + * Text.setFont('Georgia, "Goudy Bookletter 1911", Times, serif'); + * ``` + * + * @method Phaser.GameObjects.Text#setFontFamily + * @since 3.0.0 + * + * @param {string} family - The font family. + * + * @return {this} This Text object. + * + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/font-family#Valid_family_names + */ + setFontFamily: function (family) + { + return this.style.setFontFamily(family); + }, + + /** + * Set the font size. Can be a string with a valid CSS unit, i.e. `16px`, or a number. + * + * @method Phaser.GameObjects.Text#setFontSize + * @since 3.0.0 + * + * @param {(string|number)} size - The font size. + * + * @return {this} This Text object. + */ + setFontSize: function (size) + { + return this.style.setFontSize(size); + }, + + /** + * Set the font style. + * + * @method Phaser.GameObjects.Text#setFontStyle + * @since 3.0.0 + * + * @param {string} style - The font style. + * + * @return {this} This Text object. + */ + setFontStyle: function (style) + { + return this.style.setFontStyle(style); + }, + + /** + * Set a fixed width and height for the text. + * + * Pass in `0` for either of these parameters to disable fixed width or height respectively. + * + * @method Phaser.GameObjects.Text#setFixedSize + * @since 3.0.0 + * + * @param {number} width - The fixed width to set. `0` disables fixed width. + * @param {number} height - The fixed height to set. `0` disables fixed height. + * + * @return {this} This Text object. + */ + setFixedSize: function (width, height) + { + return this.style.setFixedSize(width, height); + }, + + /** + * Set the background color. + * + * @method Phaser.GameObjects.Text#setBackgroundColor + * @since 3.0.0 + * + * @param {string} color - The background color. + * + * @return {this} This Text object. + */ + setBackgroundColor: function (color) + { + return this.style.setBackgroundColor(color); + }, + + /** + * Set the fill style to be used by the Text object. + * + * This can be any valid CanvasRenderingContext2D fillStyle value, such as + * a color (in hex, rgb, rgba, hsl or named values), a gradient or a pattern. + * + * See the [MDN fillStyle docs](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle) for more details. + * + * @method Phaser.GameObjects.Text#setFill + * @since 3.0.0 + * + * @param {(string|CanvasGradient|CanvasPattern)} color - The text fill style. Can be any valid CanvasRenderingContext `fillStyle` value. + * + * @return {this} This Text object. + */ + setFill: function (fillStyle) + { + return this.style.setFill(fillStyle); + }, + + /** + * Set the text fill color. + * + * @method Phaser.GameObjects.Text#setColor + * @since 3.0.0 + * + * @param {(string|CanvasGradient|CanvasPattern)} color - The text fill color. + * + * @return {this} This Text object. + */ + setColor: function (color) + { + return this.style.setColor(color); + }, + + /** + * Set the stroke settings. + * + * @method Phaser.GameObjects.Text#setStroke + * @since 3.0.0 + * + * @param {(string|CanvasGradient|CanvasPattern)} color - The stroke color. + * @param {number} thickness - The stroke thickness. + * + * @return {this} This Text object. + */ + setStroke: function (color, thickness) + { + return this.style.setStroke(color, thickness); + }, + + /** + * Set the shadow settings. + * + * @method Phaser.GameObjects.Text#setShadow + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal shadow offset. + * @param {number} [y=0] - The vertical shadow offset. + * @param {string} [color='#000'] - The shadow color. + * @param {number} [blur=0] - The shadow blur radius. + * @param {boolean} [shadowStroke=false] - Whether to stroke the shadow. + * @param {boolean} [shadowFill=true] - Whether to fill the shadow. + * + * @return {this} This Text object. + */ + setShadow: function (x, y, color, blur, shadowStroke, shadowFill) + { + return this.style.setShadow(x, y, color, blur, shadowStroke, shadowFill); + }, + + /** + * Set the shadow offset. + * + * @method Phaser.GameObjects.Text#setShadowOffset + * @since 3.0.0 + * + * @param {number} x - The horizontal shadow offset. + * @param {number} y - The vertical shadow offset. + * + * @return {this} This Text object. + */ + setShadowOffset: function (x, y) + { + return this.style.setShadowOffset(x, y); + }, + + /** + * Set the shadow color. + * + * @method Phaser.GameObjects.Text#setShadowColor + * @since 3.0.0 + * + * @param {string} color - The shadow color. + * + * @return {this} This Text object. + */ + setShadowColor: function (color) + { + return this.style.setShadowColor(color); + }, + + /** + * Set the shadow blur radius. + * + * @method Phaser.GameObjects.Text#setShadowBlur + * @since 3.0.0 + * + * @param {number} blur - The shadow blur radius. + * + * @return {this} This Text object. + */ + setShadowBlur: function (blur) + { + return this.style.setShadowBlur(blur); + }, + + /** + * Enable or disable shadow stroke. + * + * @method Phaser.GameObjects.Text#setShadowStroke + * @since 3.0.0 + * + * @param {boolean} enabled - Whether shadow stroke is enabled or not. + * + * @return {this} This Text object. + */ + setShadowStroke: function (enabled) + { + return this.style.setShadowStroke(enabled); + }, + + /** + * Enable or disable shadow fill. + * + * @method Phaser.GameObjects.Text#setShadowFill + * @since 3.0.0 + * + * @param {boolean} enabled - Whether shadow fill is enabled or not. + * + * @return {this} This Text object. + */ + setShadowFill: function (enabled) + { + return this.style.setShadowFill(enabled); + }, + + /** + * Set the width (in pixels) to use for wrapping lines. Pass in null to remove wrapping by width. + * + * @method Phaser.GameObjects.Text#setWordWrapWidth + * @since 3.0.0 + * + * @param {number | null} width - The maximum width of a line in pixels. Set to null to remove wrapping. + * @param {boolean} [useAdvancedWrap=false] - Whether or not to use the advanced wrapping + * algorithm. If true, spaces are collapsed and whitespace is trimmed from lines. If false, + * spaces and whitespace are left as is. + * + * @return {this} This Text object. + */ + setWordWrapWidth: function (width, useAdvancedWrap) + { + return this.style.setWordWrapWidth(width, useAdvancedWrap); + }, + + /** + * Set a custom callback for wrapping lines. Pass in null to remove wrapping by callback. + * + * @method Phaser.GameObjects.Text#setWordWrapCallback + * @since 3.0.0 + * + * @param {TextStyleWordWrapCallback} callback - A custom function that will be responsible for wrapping the + * text. It will receive two arguments: text (the string to wrap), textObject (this Text + * instance). It should return the wrapped lines either as an array of lines or as a string with + * newline characters in place to indicate where breaks should happen. + * @param {object} [scope=null] - The scope that will be applied when the callback is invoked. + * + * @return {this} This Text object. + */ + setWordWrapCallback: function (callback, scope) + { + return this.style.setWordWrapCallback(callback, scope); + }, + + /** + * Set the alignment of the text in this Text object. + * + * The argument can be one of: `left`, `right`, `center` or `justify`. + * + * Alignment only works if the Text object has more than one line of text. + * + * @method Phaser.GameObjects.Text#setAlign + * @since 3.0.0 + * + * @param {string} [align='left'] - The text alignment for multi-line text. + * + * @return {this} This Text object. + */ + setAlign: function (align) + { + return this.style.setAlign(align); + }, + + /** + * Set the resolution used by this Text object. + * + * It allows for much clearer text on High DPI devices, at the cost of memory because it uses larger + * internal Canvas textures for the Text. + * + * Therefore, please use with caution, as the more high res Text you have, the more memory it uses. + * + * @method Phaser.GameObjects.Text#setResolution + * @since 3.12.0 + * + * @param {number} value - The resolution for this Text object to use. + * + * @return {this} This Text object. + */ + setResolution: function (value) + { + return this.style.setResolution(value); + }, + + /** + * Sets the line spacing value. + * + * This value is _added_ to the height of the font when calculating the overall line height. + * This only has an effect if this Text object consists of multiple lines of text. + * + * @method Phaser.GameObjects.Text#setLineSpacing + * @since 3.13.0 + * + * @param {number} value - The amount to add to the font height to achieve the overall line height. + * + * @return {this} This Text object. + */ + setLineSpacing: function (value) + { + this.lineSpacing = value; + + return this.updateText(); + }, + + /** + * Sets the letter spacing value. + * + * This will add, or remove spacing between each character of this Text Game Object. The value can be + * either positive or negative. Positive values increase the space between each character, whilst negative + * values decrease it. Note that some fonts are spaced naturally closer together than others. + * + * Please understand that enabling this feature will cause Phaser to render each character in this Text object + * one by one, rather than use a draw for the whole string. This makes it extremely expensive when used with + * either long strings, or lots of strings in total. You will be better off creating bitmap font text if you + * need to display large quantities of characters with fine control over the letter spacing. + * + * @method Phaser.GameObjects.Text#setLetterSpacing + * @since 3.70.0 + * + * @param {number} value - The amount to add to the letter width. Set to zero to disable. + * + * @return {this} This Text object. + */ + setLetterSpacing: function (value) + { + this.letterSpacing = value; + + return this.updateText(); + }, + + /** + * Set the text padding. + * + * 'left' can be an object. + * + * If only 'left' and 'top' are given they are treated as 'x' and 'y'. + * + * @method Phaser.GameObjects.Text#setPadding + * @since 3.0.0 + * + * @param {(number|Phaser.Types.GameObjects.Text.TextPadding)} left - The left padding value, or a padding config object. + * @param {number} [top] - The top padding value. + * @param {number} [right] - The right padding value. + * @param {number} [bottom] - The bottom padding value. + * + * @return {this} This Text object. + */ + setPadding: function (left, top, right, bottom) + { + if (typeof left === 'object') + { + var config = left; + + // If they specify x and/or y this applies to all + var x = GetValue(config, 'x', null); + + if (x !== null) + { + left = x; + right = x; + } + else + { + left = GetValue(config, 'left', 0); + right = GetValue(config, 'right', left); + } + + var y = GetValue(config, 'y', null); + + if (y !== null) + { + top = y; + bottom = y; + } + else + { + top = GetValue(config, 'top', 0); + bottom = GetValue(config, 'bottom', top); + } + } + else + { + if (left === undefined) { left = 0; } + if (top === undefined) { top = left; } + if (right === undefined) { right = left; } + if (bottom === undefined) { bottom = top; } + } + + this.padding.left = left; + this.padding.top = top; + this.padding.right = right; + this.padding.bottom = bottom; + + return this.updateText(); + }, + + /** + * Set the maximum number of lines to draw. + * + * @method Phaser.GameObjects.Text#setMaxLines + * @since 3.0.0 + * + * @param {number} [max=0] - The maximum number of lines to draw. + * + * @return {this} This Text object. + */ + setMaxLines: function (max) + { + return this.style.setMaxLines(max); + }, + + /** + * Render text from right-to-left or left-to-right. + * + * @method Phaser.GameObjects.Text#setRTL + * @since 3.70.0 + * + * @param {boolean} [rtl=true] - Set to `true` to render from right-to-left. + * + * @return {this} This Text object. + */ + setRTL: function (rtl) + { + if (rtl === undefined) { rtl = true; } + + var style = this.style; + + if (style.rtl === rtl) + { + return this; + } + + style.rtl = rtl; + + if (rtl) + { + this.canvas.dir = 'rtl'; + this.context.direction = 'rtl'; + this.canvas.style.display = 'none'; + + AddToDOM(this.canvas, this.scene.sys.canvas); + } + else + { + this.canvas.dir = 'ltr'; + this.context.direction = 'ltr'; + } + + if (style.align === 'left') + { + style.align = 'right'; + } + else if (style.align === 'right') + { + style.align = 'left'; + } + + return this; + }, + + /** + * Update the displayed text. + * + * @method Phaser.GameObjects.Text#updateText + * @since 3.0.0 + * + * @return {this} This Text object. + */ + updateText: function () + { + var canvas = this.canvas; + var context = this.context; + var style = this.style; + var resolution = style.resolution; + var size = style.metrics; + + style.syncFont(canvas, context); + + var outputText = this._text; + + if (style.wordWrapWidth || style.wordWrapCallback) + { + outputText = this.runWordWrap(this._text); + } + + // Split text into lines + var lines = outputText.split(this.splitRegExp); + + var textSize = GetTextSize(this, size, lines); + + var padding = this.padding; + + var textWidth; + + if (style.fixedWidth === 0) + { + this.width = textSize.width + padding.left + padding.right; + + textWidth = textSize.width; + } + else + { + this.width = style.fixedWidth; + + textWidth = this.width - padding.left - padding.right; + + if (textWidth < textSize.width) + { + textWidth = textSize.width; + } + } + + if (style.fixedHeight === 0) + { + this.height = textSize.height + padding.top + padding.bottom; + } + else + { + this.height = style.fixedHeight; + } + + var w = this.width; + var h = this.height; + + this.updateDisplayOrigin(); + + w *= resolution; + h *= resolution; + + w = Math.max(w, 1); + h = Math.max(h, 1); + + if (canvas.width !== w || canvas.height !== h) + { + canvas.width = w; + canvas.height = h; + + this.frame.setSize(w, h); + + // Resizing the canvas changes the size of the texture source. + // Because this is a dedicated texture for this Text object, + // we know this is a simple resize. + this.frame.source.updateSize(w, h); + this.frame.source.resolution = resolution; + this.frame.updateUVs(); + + // Because resizing the canvas resets the context + style.syncFont(canvas, context); + + if (style.rtl) + { + context.direction = 'rtl'; + } + } + else + { + context.clearRect(0, 0, w, h); + } + + context.save(); + + context.scale(resolution, resolution); + + if (style.backgroundColor) + { + context.fillStyle = style.backgroundColor; + context.fillRect(0, 0, w, h); + } + + style.syncStyle(canvas, context); + + // Apply padding + context.translate(padding.left, padding.top); + + var linePositionX; + var linePositionY; + + // Draw text line by line + for (var i = 0; i < textSize.lines; i++) + { + linePositionX = style.strokeThickness / 2; + linePositionY = (style.strokeThickness / 2 + i * textSize.lineHeight) + size.ascent; + + if (i > 0) + { + linePositionY += (textSize.lineSpacing * i); + } + + if (style.rtl) + { + linePositionX = w - linePositionX - padding.left - padding.right; + } + else if (style.align === 'right') + { + linePositionX += textWidth - textSize.lineWidths[i]; + } + else if (style.align === 'center') + { + linePositionX += (textWidth - textSize.lineWidths[i]) / 2; + } + else if (style.align === 'justify') + { + // To justify text line its width must be no less than 85% of defined width + var minimumLengthToApplyJustification = 0.85; + + if (textSize.lineWidths[i] / textSize.width >= minimumLengthToApplyJustification) + { + var extraSpace = textSize.width - textSize.lineWidths[i]; + var spaceSize = context.measureText(' ').width; + var trimmedLine = lines[i].trim(); + var array = trimmedLine.split(' '); + + extraSpace += (lines[i].length - trimmedLine.length) * spaceSize; + + var extraSpaceCharacters = Math.floor(extraSpace / spaceSize); + var idx = 0; + + while (extraSpaceCharacters > 0) + { + array[idx] += ' '; + idx = (idx + 1) % (array.length - 1 || 1); + --extraSpaceCharacters; + } + + lines[i] = array.join(' '); + } + } + + if (this.autoRound) + { + linePositionX = Math.round(linePositionX); + linePositionY = Math.round(linePositionY); + } + + var letterSpacing = this.letterSpacing; + + // Apply stroke to the whole line only if there's no custom letter spacing + + if (style.strokeThickness && letterSpacing === 0) + { + style.syncShadow(context, style.shadowStroke); + + context.strokeText(lines[i], linePositionX, linePositionY); + } + + if (style.color) + { + style.syncShadow(context, style.shadowFill); + + // Looping fillText could be an expensive operation, we should ignore it if it is not needed + + if (letterSpacing !== 0) + { + var charPositionX = 0; + + var line = lines[i].split(''); + + // Draw text letter by letter + for (var l = 0; l < line.length; l++) + { + if (style.strokeThickness) + { + style.syncShadow(context, style.shadowStroke); + + context.strokeText(line[l], linePositionX + charPositionX, linePositionY); + + style.syncShadow(context, style.shadowFill); + } + + context.fillText(line[l], linePositionX + charPositionX, linePositionY); + + charPositionX += context.measureText(line[l]).width + letterSpacing; + } + } + else + { + context.fillText(lines[i], linePositionX, linePositionY); + } + } + } + + context.restore(); + + if (this.renderer && this.renderer.gl) + { + this.frame.source.glTexture = this.renderer.canvasToTexture(canvas, this.frame.source.glTexture, true); + + if (false) + {} + } + + var input = this.input; + + if (input && !input.customHitArea) + { + input.hitArea.width = this.width; + input.hitArea.height = this.height; + } + + return this; + }, + + /** + * Get the current text metrics. + * + * @method Phaser.GameObjects.Text#getTextMetrics + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.Text.TextMetrics} The text metrics. + */ + getTextMetrics: function () + { + return this.style.getTextMetrics(); + }, + + /** + * The text string being rendered by this Text Game Object. + * + * @name Phaser.GameObjects.Text#text + * @type {string} + * @since 3.0.0 + */ + text: { + + get: function () + { + return this._text; + }, + + set: function (value) + { + this.setText(value); + } + + }, + + /** + * Build a JSON representation of the Text object. + * + * @method Phaser.GameObjects.Text#toJSON + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Text object. + */ + toJSON: function () + { + var out = Components.ToJSON(this); + + // Extra Text data is added here + + var data = { + autoRound: this.autoRound, + text: this._text, + style: this.style.toJSON(), + padding: { + left: this.padding.left, + right: this.padding.right, + top: this.padding.top, + bottom: this.padding.bottom + } + }; + + out.data = data; + + return out; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.Text#preDestroy + * @protected + * @since 3.0.0 + */ + preDestroy: function () + { + RemoveFromDOM(this.canvas); + + CanvasPool.remove(this.canvas); + + var texture = this.texture; + + if (texture) + { + texture.destroy(); + } + } + + /** + * The horizontal origin of this Game Object. + * The origin maps the relationship between the size and position of the Game Object. + * The default value is 0.5, meaning all Game Objects are positioned based on their center. + * Setting the value to 0 means the position now relates to the left of the Game Object. + * + * @name Phaser.GameObjects.Text#originX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + + /** + * The vertical origin of this Game Object. + * The origin maps the relationship between the size and position of the Game Object. + * The default value is 0.5, meaning all Game Objects are positioned based on their center. + * Setting the value to 0 means the position now relates to the top of the Game Object. + * + * @name Phaser.GameObjects.Text#originY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + +}); + +module.exports = Text; + + +/***/ }), + +/***/ 79724: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Text#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Text} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TextCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + if (src.width === 0 || src.height === 0) + { + return; + } + + camera.addToRenderList(src); + + renderer.batchSprite(src, src.frame, camera, parentMatrix); +}; + +module.exports = TextCanvasRenderer; + + +/***/ }), + +/***/ 71259: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Text = __webpack_require__(50171); + +/** + * Creates a new Text Game Object and returns it. + * + * Note: This method will only be available if the Text Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#text + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Text.TextConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Text} The Game Object that was created. + */ +GameObjectCreator.register('text', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + // style Object = { + // font: [ 'font', '16px Courier' ], + // backgroundColor: [ 'backgroundColor', null ], + // fill: [ 'fill', '#fff' ], + // stroke: [ 'stroke', '#fff' ], + // strokeThickness: [ 'strokeThickness', 0 ], + // shadowOffsetX: [ 'shadow.offsetX', 0 ], + // shadowOffsetY: [ 'shadow.offsetY', 0 ], + // shadowColor: [ 'shadow.color', '#000' ], + // shadowBlur: [ 'shadow.blur', 0 ], + // shadowStroke: [ 'shadow.stroke', false ], + // shadowFill: [ 'shadow.fill', false ], + // align: [ 'align', 'left' ], + // maxLines: [ 'maxLines', 0 ], + // fixedWidth: [ 'fixedWidth', false ], + // fixedHeight: [ 'fixedHeight', false ], + // rtl: [ 'rtl', false ] + // } + + var content = GetAdvancedValue(config, 'text', ''); + var style = GetAdvancedValue(config, 'style', null); + + // Padding + // { padding: 2 } + // { padding: { x: , y: }} + // { padding: { left: , top: }} + // { padding: { left: , right: , top: , bottom: }} + + var padding = GetAdvancedValue(config, 'padding', null); + + if (padding !== null) + { + style.padding = padding; + } + + var text = new Text(this.scene, 0, 0, content, style); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, text, config); + + // Text specific config options: + + text.autoRound = GetAdvancedValue(config, 'autoRound', true); + text.resolution = GetAdvancedValue(config, 'resolution', 1); + + return text; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 68005: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Text = __webpack_require__(50171); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Text Game Object and adds it to the Scene. + * + * A Text Game Object. + * + * Text objects work by creating their own internal hidden Canvas and then renders text to it using + * the standard Canvas `fillText` API. It then creates a texture from this canvas which is rendered + * to your game during the render pass. + * + * Because it uses the Canvas API you can take advantage of all the features this offers, such as + * applying gradient fills to the text, or strokes, shadows and more. You can also use custom fonts + * loaded externally, such as Google or TypeKit Web fonts. + * + * You can only display fonts that are currently loaded and available to the browser: therefore fonts must + * be pre-loaded. Phaser does not do this for you, so you will require the use of a 3rd party font loader, + * or have the fonts ready available in the CSS on the page in which your Phaser game resides. + * + * See {@link http://www.jordanm.co.uk/tinytype this compatibility table} for the available default fonts + * across mobile browsers. + * + * A note on performance: Every time the contents of a Text object changes, i.e. changing the text being + * displayed, or the style of the text, it needs to remake the Text canvas, and if on WebGL, re-upload the + * new texture to the GPU. This can be an expensive operation if used often, or with large quantities of + * Text objects in your game. If you run into performance issues you would be better off using Bitmap Text + * instead, as it benefits from batching and avoids expensive Canvas API calls. + * + * Note: This method will only be available if the Text Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#text + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|string[])} text - The text this Text object will display. + * @param {Phaser.Types.GameObjects.Text.TextStyle} [style] - The Text style configuration object. + * + * @return {Phaser.GameObjects.Text} The Game Object that was created. + */ +GameObjectFactory.register('text', function (x, y, text, style) +{ + return this.displayList.add(new Text(this.scene, x, y, text, style)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 61771: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(34397); +} + +if (true) +{ + renderCanvas = __webpack_require__(79724); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 35762: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetAdvancedValue = __webpack_require__(23568); +var GetValue = __webpack_require__(35154); +var MeasureText = __webpack_require__(79557); + +// Key: [ Object Key, Default Value ] + +var propertyMap = { + fontFamily: [ 'fontFamily', 'Courier' ], + fontSize: [ 'fontSize', '16px' ], + fontStyle: [ 'fontStyle', '' ], + backgroundColor: [ 'backgroundColor', null ], + color: [ 'color', '#fff' ], + stroke: [ 'stroke', '#fff' ], + strokeThickness: [ 'strokeThickness', 0 ], + shadowOffsetX: [ 'shadow.offsetX', 0 ], + shadowOffsetY: [ 'shadow.offsetY', 0 ], + shadowColor: [ 'shadow.color', '#000' ], + shadowBlur: [ 'shadow.blur', 0 ], + shadowStroke: [ 'shadow.stroke', false ], + shadowFill: [ 'shadow.fill', false ], + align: [ 'align', 'left' ], + maxLines: [ 'maxLines', 0 ], + fixedWidth: [ 'fixedWidth', 0 ], + fixedHeight: [ 'fixedHeight', 0 ], + resolution: [ 'resolution', 0 ], + rtl: [ 'rtl', false ], + testString: [ 'testString', '|MÉqgy' ], + baselineX: [ 'baselineX', 1.2 ], + baselineY: [ 'baselineY', 1.4 ], + wordWrapWidth: [ 'wordWrap.width', null ], + wordWrapCallback: [ 'wordWrap.callback', null ], + wordWrapCallbackScope: [ 'wordWrap.callbackScope', null ], + wordWrapUseAdvanced: [ 'wordWrap.useAdvancedWrap', false ] +}; + +/** + * @classdesc + * A TextStyle class manages all of the style settings for a Text object. + * + * Text Game Objects create a TextStyle instance automatically, which is + * accessed via the `Text.style` property. You do not normally need to + * instantiate one yourself. + * + * @class TextStyle + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Text} text - The Text object that this TextStyle is styling. + * @param {Phaser.Types.GameObjects.Text.TextStyle} style - The style settings to set. + */ +var TextStyle = new Class({ + + initialize: + + function TextStyle (text, style) + { + /** + * The Text object that this TextStyle is styling. + * + * @name Phaser.GameObjects.TextStyle#parent + * @type {Phaser.GameObjects.Text} + * @since 3.0.0 + */ + this.parent = text; + + /** + * The font family. + * + * @name Phaser.GameObjects.TextStyle#fontFamily + * @type {string} + * @default 'Courier' + * @since 3.0.0 + */ + this.fontFamily; + + /** + * The font size. + * + * @name Phaser.GameObjects.TextStyle#fontSize + * @type {(string|number)} + * @default '16px' + * @since 3.0.0 + */ + this.fontSize; + + /** + * The font style. + * + * @name Phaser.GameObjects.TextStyle#fontStyle + * @type {string} + * @since 3.0.0 + */ + this.fontStyle; + + /** + * The background color. + * + * @name Phaser.GameObjects.TextStyle#backgroundColor + * @type {string} + * @since 3.0.0 + */ + this.backgroundColor; + + /** + * The text fill color. + * + * @name Phaser.GameObjects.TextStyle#color + * @type {(string|CanvasGradient|CanvasPattern)} + * @default '#fff' + * @since 3.0.0 + */ + this.color; + + /** + * The text stroke color. + * + * @name Phaser.GameObjects.TextStyle#stroke + * @type {(string|CanvasGradient|CanvasPattern)} + * @default '#fff' + * @since 3.0.0 + */ + this.stroke; + + /** + * The text stroke thickness. + * + * @name Phaser.GameObjects.TextStyle#strokeThickness + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.strokeThickness; + + /** + * The horizontal shadow offset. + * + * @name Phaser.GameObjects.TextStyle#shadowOffsetX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.shadowOffsetX; + + /** + * The vertical shadow offset. + * + * @name Phaser.GameObjects.TextStyle#shadowOffsetY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.shadowOffsetY; + + /** + * The shadow color. + * + * @name Phaser.GameObjects.TextStyle#shadowColor + * @type {string} + * @default '#000' + * @since 3.0.0 + */ + this.shadowColor; + + /** + * The shadow blur radius. + * + * @name Phaser.GameObjects.TextStyle#shadowBlur + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.shadowBlur; + + /** + * Whether shadow stroke is enabled or not. + * + * @name Phaser.GameObjects.TextStyle#shadowStroke + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.shadowStroke; + + /** + * Whether shadow fill is enabled or not. + * + * @name Phaser.GameObjects.TextStyle#shadowFill + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.shadowFill; + + /** + * The text alignment. + * + * @name Phaser.GameObjects.TextStyle#align + * @type {string} + * @default 'left' + * @since 3.0.0 + */ + this.align; + + /** + * The maximum number of lines to draw. + * + * @name Phaser.GameObjects.TextStyle#maxLines + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.maxLines; + + /** + * The fixed width of the text. + * + * `0` means no fixed with. + * + * @name Phaser.GameObjects.TextStyle#fixedWidth + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.fixedWidth; + + /** + * The fixed height of the text. + * + * `0` means no fixed height. + * + * @name Phaser.GameObjects.TextStyle#fixedHeight + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.fixedHeight; + + /** + * The resolution the text is rendered to its internal canvas at. + * The default is 0, which means it will use the resolution set in the Game Config. + * + * @name Phaser.GameObjects.TextStyle#resolution + * @type {number} + * @default 0 + * @since 3.12.0 + */ + this.resolution; + + /** + * Whether the text should render right to left. + * + * @name Phaser.GameObjects.TextStyle#rtl + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.rtl; + + /** + * The test string to use when measuring the font. + * + * @name Phaser.GameObjects.TextStyle#testString + * @type {string} + * @default '|MÉqgy' + * @since 3.0.0 + */ + this.testString; + + /** + * The amount of horizontal padding added to the width of the text when calculating the font metrics. + * + * @name Phaser.GameObjects.TextStyle#baselineX + * @type {number} + * @default 1.2 + * @since 3.3.0 + */ + this.baselineX; + + /** + * The amount of vertical padding added to the height of the text when calculating the font metrics. + * + * @name Phaser.GameObjects.TextStyle#baselineY + * @type {number} + * @default 1.4 + * @since 3.3.0 + */ + this.baselineY; + + /** + * The maximum width of a line of text in pixels. Null means no line wrapping. Setting this + * property directly will not re-run the word wrapping algorithm. To change the width and + * re-wrap, use {@link Phaser.GameObjects.TextStyle#setWordWrapWidth}. + * + * @name Phaser.GameObjects.TextStyle#wordWrapWidth + * @type {number | null} + * @default null + * @since 3.24.0 + */ + this.wordWrapWidth; + + /** + * A custom function that will be responsible for wrapping the text. It will receive two + * arguments: text (the string to wrap), textObject (this Text instance). It should return + * the wrapped lines either as an array of lines or as a string with newline characters in + * place to indicate where breaks should happen. Setting this directly will not re-run the + * word wrapping algorithm. To change the callback and re-wrap, use + * {@link Phaser.GameObjects.TextStyle#setWordWrapCallback}. + * + * @name Phaser.GameObjects.TextStyle#wordWrapCallback + * @type {TextStyleWordWrapCallback | null} + * @default null + * @since 3.24.0 + */ + this.wordWrapCallback; + + /** + * The scope that will be applied when the wordWrapCallback is invoked. Setting this directly will not re-run the + * word wrapping algorithm. To change the callback and re-wrap, use + * {@link Phaser.GameObjects.TextStyle#setWordWrapCallback}. + * + * @name Phaser.GameObjects.TextStyle#wordWrapCallbackScope + * @type {object | null} + * @default null + * @since 3.24.0 + */ + this.wordWrapCallbackScope; + + /** + * Whether or not to use the advanced wrapping algorithm. If true, spaces are collapsed and + * whitespace is trimmed from lines. If false, spaces and whitespace are left as is. Setting + * this property directly will not re-run the word wrapping algorithm. To change the + * advanced setting and re-wrap, use {@link Phaser.GameObjects.TextStyle#setWordWrapWidth}. + * + * @name Phaser.GameObjects.TextStyle#wordWrapUseAdvanced + * @type {boolean} + * @default false + * @since 3.24.0 + */ + this.wordWrapUseAdvanced; + + /** + * The font style, size and family. + * + * @name Phaser.GameObjects.TextStyle#_font + * @type {string} + * @private + * @since 3.0.0 + */ + this._font; + + // Set to defaults + user style + this.setStyle(style, false, true); + }, + + /** + * Set the text style. + * + * @example + * text.setStyle({ + * fontSize: '64px', + * fontFamily: 'Arial', + * color: '#ffffff', + * align: 'center', + * backgroundColor: '#ff00ff' + * }); + * + * @method Phaser.GameObjects.TextStyle#setStyle + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Text.TextStyle} style - The style settings to set. + * @param {boolean} [updateText=true] - Whether to update the text immediately. + * @param {boolean} [setDefaults=false] - Use the default values if not set, or the local values. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setStyle: function (style, updateText, setDefaults) + { + if (updateText === undefined) { updateText = true; } + if (setDefaults === undefined) { setDefaults = false; } + + for (var key in propertyMap) + { + var value = (setDefaults) ? propertyMap[key][1] : this[key]; + + if (key === 'wordWrapCallback' || key === 'wordWrapCallbackScope') + { + // Callback & scope should be set without processing the values + this[key] = GetValue(style, propertyMap[key][0], value); + } + else if (style && key === 'fontSize' && typeof style.fontSize === 'number') + { + this[key] = style.fontSize.toString() + 'px'; + } + else + { + this[key] = GetAdvancedValue(style, propertyMap[key][0], value); + } + } + + // Allow for 'font' override + var font = GetValue(style, 'font', null); + + if (font !== null) + { + this.setFont(font, false); + } + + this._font = [ this.fontStyle, this.fontSize, this.fontFamily ].join(' ').trim(); + + // Allow for 'fill' to be used in place of 'color' + var fill = GetValue(style, 'fill', null); + + if (fill !== null) + { + this.color = fill; + } + + var metrics = GetValue(style, 'metrics', false); + + // Provide optional TextMetrics in the style object to avoid the canvas look-up / scanning + // Doing this is reset if you then change the font of this TextStyle after creation + if (metrics) + { + this.metrics = { + ascent: GetValue(metrics, 'ascent', 0), + descent: GetValue(metrics, 'descent', 0), + fontSize: GetValue(metrics, 'fontSize', 0) + }; + } + else if (updateText || !this.metrics) + { + this.metrics = MeasureText(this); + } + + if (updateText) + { + return this.parent.updateText(); + } + else + { + return this.parent; + } + }, + + /** + * Synchronize the font settings to the given Canvas Rendering Context. + * + * @method Phaser.GameObjects.TextStyle#syncFont + * @since 3.0.0 + * + * @param {HTMLCanvasElement} canvas - The Canvas Element. + * @param {CanvasRenderingContext2D} context - The Canvas Rendering Context. + */ + syncFont: function (canvas, context) + { + context.font = this._font; + }, + + /** + * Synchronize the text style settings to the given Canvas Rendering Context. + * + * @method Phaser.GameObjects.TextStyle#syncStyle + * @since 3.0.0 + * + * @param {HTMLCanvasElement} canvas - The Canvas Element. + * @param {CanvasRenderingContext2D} context - The Canvas Rendering Context. + */ + syncStyle: function (canvas, context) + { + context.textBaseline = 'alphabetic'; + + context.fillStyle = this.color; + context.strokeStyle = this.stroke; + + context.lineWidth = this.strokeThickness; + context.lineCap = 'round'; + context.lineJoin = 'round'; + }, + + /** + * Synchronize the shadow settings to the given Canvas Rendering Context. + * + * @method Phaser.GameObjects.TextStyle#syncShadow + * @since 3.0.0 + * + * @param {CanvasRenderingContext2D} context - The Canvas Rendering Context. + * @param {boolean} enabled - Whether shadows are enabled or not. + */ + syncShadow: function (context, enabled) + { + if (enabled) + { + context.shadowOffsetX = this.shadowOffsetX; + context.shadowOffsetY = this.shadowOffsetY; + context.shadowColor = this.shadowColor; + context.shadowBlur = this.shadowBlur; + } + else + { + context.shadowOffsetX = 0; + context.shadowOffsetY = 0; + context.shadowColor = 0; + context.shadowBlur = 0; + } + }, + + /** + * Update the style settings for the parent Text object. + * + * @method Phaser.GameObjects.TextStyle#update + * @since 3.0.0 + * + * @param {boolean} recalculateMetrics - Whether to recalculate font and text metrics. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + update: function (recalculateMetrics) + { + if (recalculateMetrics) + { + this._font = [ this.fontStyle, this.fontSize, this.fontFamily ].join(' ').trim(); + + this.metrics = MeasureText(this); + } + + return this.parent.updateText(); + }, + + /** + * Set the font. + * + * If a string is given, the font family is set. + * + * If an object is given, the `fontFamily`, `fontSize` and `fontStyle` + * properties of that object are set. + * + * @method Phaser.GameObjects.TextStyle#setFont + * @since 3.0.0 + * + * @param {(string|object)} font - The font family or font settings to set. + * @param {boolean} [updateText=true] - Whether to update the text immediately. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setFont: function (font, updateText) + { + if (updateText === undefined) { updateText = true; } + + var fontFamily = font; + var fontSize = ''; + var fontStyle = ''; + + if (typeof font !== 'string') + { + fontFamily = GetValue(font, 'fontFamily', 'Courier'); + fontSize = GetValue(font, 'fontSize', '16px'); + fontStyle = GetValue(font, 'fontStyle', ''); + } + else + { + var fontSplit = font.split(' '); + + var i = 0; + + fontStyle = (fontSplit.length > 2) ? fontSplit[i++] : ''; + fontSize = fontSplit[i++] || '16px'; + fontFamily = fontSplit[i++] || 'Courier'; + } + + if (fontFamily !== this.fontFamily || fontSize !== this.fontSize || fontStyle !== this.fontStyle) + { + this.fontFamily = fontFamily; + this.fontSize = fontSize; + this.fontStyle = fontStyle; + + if (updateText) + { + this.update(true); + } + } + + return this.parent; + }, + + /** + * Set the font family. + * + * @method Phaser.GameObjects.TextStyle#setFontFamily + * @since 3.0.0 + * + * @param {string} family - The font family. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setFontFamily: function (family) + { + if (this.fontFamily !== family) + { + this.fontFamily = family; + + this.update(true); + } + + return this.parent; + }, + + /** + * Set the font style. + * + * @method Phaser.GameObjects.TextStyle#setFontStyle + * @since 3.0.0 + * + * @param {string} style - The font style. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setFontStyle: function (style) + { + if (this.fontStyle !== style) + { + this.fontStyle = style; + + this.update(true); + } + + return this.parent; + }, + + /** + * Set the font size. Can be a string with a valid CSS unit, i.e. `16px`, or a number. + * + * @method Phaser.GameObjects.TextStyle#setFontSize + * @since 3.0.0 + * + * @param {(number|string)} size - The font size. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setFontSize: function (size) + { + if (typeof size === 'number') + { + size = size.toString() + 'px'; + } + + if (this.fontSize !== size) + { + this.fontSize = size; + + this.update(true); + } + + return this.parent; + }, + + /** + * Set the test string to use when measuring the font. + * + * @method Phaser.GameObjects.TextStyle#setTestString + * @since 3.0.0 + * + * @param {string} string - The test string to use when measuring the font. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setTestString: function (string) + { + this.testString = string; + + return this.update(true); + }, + + /** + * Set a fixed width and height for the text. + * + * Pass in `0` for either of these parameters to disable fixed width or height respectively. + * + * @method Phaser.GameObjects.TextStyle#setFixedSize + * @since 3.0.0 + * + * @param {number} width - The fixed width to set. + * @param {number} height - The fixed height to set. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setFixedSize: function (width, height) + { + this.fixedWidth = width; + this.fixedHeight = height; + + if (width) + { + this.parent.width = width; + } + + if (height) + { + this.parent.height = height; + } + + return this.update(false); + }, + + /** + * Set the background color. + * + * @method Phaser.GameObjects.TextStyle#setBackgroundColor + * @since 3.0.0 + * + * @param {string} color - The background color. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setBackgroundColor: function (color) + { + this.backgroundColor = color; + + return this.update(false); + }, + + /** + * Set the text fill color. + * + * @method Phaser.GameObjects.TextStyle#setFill + * @since 3.0.0 + * + * @param {(string|CanvasGradient|CanvasPattern)} color - The text fill color. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setFill: function (color) + { + this.color = color; + + return this.update(false); + }, + + /** + * Set the text fill color. + * + * @method Phaser.GameObjects.TextStyle#setColor + * @since 3.0.0 + * + * @param {(string|CanvasGradient|CanvasPattern)} color - The text fill color. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setColor: function (color) + { + this.color = color; + + return this.update(false); + }, + + /** + * Set the resolution used by the Text object. + * + * It allows for much clearer text on High DPI devices, at the cost of memory because + * it uses larger internal Canvas textures for the Text. + * + * Please use with caution, as the more high res Text you have, the more memory it uses up. + * + * @method Phaser.GameObjects.TextStyle#setResolution + * @since 3.12.0 + * + * @param {number} value - The resolution for this Text object to use. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setResolution: function (value) + { + this.resolution = value; + + return this.update(false); + }, + + /** + * Set the stroke settings. + * + * @method Phaser.GameObjects.TextStyle#setStroke + * @since 3.0.0 + * + * @param {(string|CanvasGradient|CanvasPattern)} color - The stroke color. + * @param {number} thickness - The stroke thickness. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setStroke: function (color, thickness) + { + if (thickness === undefined) { thickness = this.strokeThickness; } + + if (color === undefined && this.strokeThickness !== 0) + { + // Reset the stroke to zero (disabling it) + this.strokeThickness = 0; + + this.update(true); + } + else if (this.stroke !== color || this.strokeThickness !== thickness) + { + this.stroke = color; + this.strokeThickness = thickness; + + this.update(true); + } + + return this.parent; + }, + + /** + * Set the shadow settings. + * + * Calling this method always re-measures the parent Text object, + * so only call it when you actually change the shadow settings. + * + * @method Phaser.GameObjects.TextStyle#setShadow + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal shadow offset. + * @param {number} [y=0] - The vertical shadow offset. + * @param {string} [color='#000'] - The shadow color. + * @param {number} [blur=0] - The shadow blur radius. + * @param {boolean} [shadowStroke=false] - Whether to stroke the shadow. + * @param {boolean} [shadowFill=true] - Whether to fill the shadow. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setShadow: function (x, y, color, blur, shadowStroke, shadowFill) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (color === undefined) { color = '#000'; } + if (blur === undefined) { blur = 0; } + if (shadowStroke === undefined) { shadowStroke = false; } + if (shadowFill === undefined) { shadowFill = true; } + + this.shadowOffsetX = x; + this.shadowOffsetY = y; + this.shadowColor = color; + this.shadowBlur = blur; + this.shadowStroke = shadowStroke; + this.shadowFill = shadowFill; + + return this.update(false); + }, + + /** + * Set the shadow offset. + * + * @method Phaser.GameObjects.TextStyle#setShadowOffset + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal shadow offset. + * @param {number} [y=0] - The vertical shadow offset. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setShadowOffset: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = x; } + + this.shadowOffsetX = x; + this.shadowOffsetY = y; + + return this.update(false); + }, + + /** + * Set the shadow color. + * + * @method Phaser.GameObjects.TextStyle#setShadowColor + * @since 3.0.0 + * + * @param {string} [color='#000'] - The shadow color. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setShadowColor: function (color) + { + if (color === undefined) { color = '#000'; } + + this.shadowColor = color; + + return this.update(false); + }, + + /** + * Set the shadow blur radius. + * + * @method Phaser.GameObjects.TextStyle#setShadowBlur + * @since 3.0.0 + * + * @param {number} [blur=0] - The shadow blur radius. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setShadowBlur: function (blur) + { + if (blur === undefined) { blur = 0; } + + this.shadowBlur = blur; + + return this.update(false); + }, + + /** + * Enable or disable shadow stroke. + * + * @method Phaser.GameObjects.TextStyle#setShadowStroke + * @since 3.0.0 + * + * @param {boolean} enabled - Whether shadow stroke is enabled or not. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setShadowStroke: function (enabled) + { + this.shadowStroke = enabled; + + return this.update(false); + }, + + /** + * Enable or disable shadow fill. + * + * @method Phaser.GameObjects.TextStyle#setShadowFill + * @since 3.0.0 + * + * @param {boolean} enabled - Whether shadow fill is enabled or not. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setShadowFill: function (enabled) + { + this.shadowFill = enabled; + + return this.update(false); + }, + + /** + * Set the width (in pixels) to use for wrapping lines. + * + * Pass in null to remove wrapping by width. + * + * @method Phaser.GameObjects.TextStyle#setWordWrapWidth + * @since 3.0.0 + * + * @param {number | null} width - The maximum width of a line in pixels. Set to null to remove wrapping. + * @param {boolean} [useAdvancedWrap=false] - Whether or not to use the advanced wrapping + * algorithm. If true, spaces are collapsed and whitespace is trimmed from lines. If false, + * spaces and whitespace are left as is. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setWordWrapWidth: function (width, useAdvancedWrap) + { + if (useAdvancedWrap === undefined) { useAdvancedWrap = false; } + + this.wordWrapWidth = width; + this.wordWrapUseAdvanced = useAdvancedWrap; + + return this.update(false); + }, + + /** + * Set a custom callback for wrapping lines. + * + * Pass in null to remove wrapping by callback. + * + * @method Phaser.GameObjects.TextStyle#setWordWrapCallback + * @since 3.0.0 + * + * @param {TextStyleWordWrapCallback} callback - A custom function that will be responsible for wrapping the + * text. It will receive two arguments: text (the string to wrap), textObject (this Text + * instance). It should return the wrapped lines either as an array of lines or as a string with + * newline characters in place to indicate where breaks should happen. + * @param {object} [scope=null] - The scope that will be applied when the callback is invoked. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setWordWrapCallback: function (callback, scope) + { + if (scope === undefined) { scope = null; } + + this.wordWrapCallback = callback; + this.wordWrapCallbackScope = scope; + + return this.update(false); + }, + + /** + * Set the alignment of the text in this Text object. + * + * The argument can be one of: `left`, `right`, `center` or `justify`. + * + * Alignment only works if the Text object has more than one line of text. + * + * @method Phaser.GameObjects.TextStyle#setAlign + * @since 3.0.0 + * + * @param {string} [align='left'] - The text alignment for multi-line text. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setAlign: function (align) + { + if (align === undefined) { align = 'left'; } + + this.align = align; + + return this.update(false); + }, + + /** + * Set the maximum number of lines to draw. + * + * @method Phaser.GameObjects.TextStyle#setMaxLines + * @since 3.0.0 + * + * @param {number} [max=0] - The maximum number of lines to draw. + * + * @return {Phaser.GameObjects.Text} The parent Text object. + */ + setMaxLines: function (max) + { + if (max === undefined) { max = 0; } + + this.maxLines = max; + + return this.update(false); + }, + + /** + * Get the current text metrics. + * + * @method Phaser.GameObjects.TextStyle#getTextMetrics + * @since 3.0.0 + * + * @return {Phaser.Types.GameObjects.Text.TextMetrics} The text metrics. + */ + getTextMetrics: function () + { + var metrics = this.metrics; + + return { + ascent: metrics.ascent, + descent: metrics.descent, + fontSize: metrics.fontSize + }; + }, + + /** + * Build a JSON representation of this Text Style. + * + * @method Phaser.GameObjects.TextStyle#toJSON + * @since 3.0.0 + * + * @return {object} A JSON representation of this Text Style. + */ + toJSON: function () + { + var output = {}; + + for (var key in propertyMap) + { + output[key] = this[key]; + } + + output.metrics = this.getTextMetrics(); + + return output; + }, + + /** + * Destroy this Text Style. + * + * @method Phaser.GameObjects.TextStyle#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.parent = undefined; + } + +}); + +module.exports = TextStyle; + + +/***/ }), + +/***/ 34397: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Text#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Text} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TextWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + if (src.width === 0 || src.height === 0) + { + return; + } + + drawingContext.camera.addToRenderList(src); + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + src, + parentMatrix, + 0, + customRenderNodes.Texturer || defaultRenderNodes.Texturer, + customRenderNodes.Transformer || defaultRenderNodes.Transformer + ); +}; + +module.exports = TextWebGLRenderer; + + +/***/ }), + +/***/ 20839: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AnimationState = __webpack_require__(9674); +var CanvasPool = __webpack_require__(27919); +var DefaultTileSpriteNodes = __webpack_require__(41571); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var Smoothing = __webpack_require__(68703); +var TileSpriteRender = __webpack_require__(56295); +var UUID = __webpack_require__(45650); +var Vector2 = __webpack_require__(26099); + +// bitmask flag for GameObject.renderMask +var _FLAG = 8; // 1000 + +/** + * @classdesc + * A TileSprite is a Sprite that has a repeating texture. + * + * The texture can be scrolled and scaled independently of the TileSprite itself. Textures will automatically wrap and + * are designed so that you can create game backdrops using seamless textures as a source. + * + * You shouldn't ever create a TileSprite any larger than your actual canvas size. If you want to create a large repeating background + * that scrolls across the whole map of your game, then you create a TileSprite that fits the canvas size and then use the `tilePosition` + * property to scroll the texture as the player moves. If you create a TileSprite that is thousands of pixels in size then it will + * consume huge amounts of memory and cause performance issues. Remember: use `tilePosition` to scroll your texture and `tileScale` to + * adjust the scale of the texture - don't resize the sprite itself or make it larger than it needs. + * + * Prior to Phaser 4, TileSprite did not support rotation. + * In WebGL, it required the texture to be a power of two in size, + * and did not support compressed textures or DynamicTextures. + * It could introduce aliasing artifacts for textures that were not + * a power of two in size. + * These restrictions have been lifted in v4. + * + * @class TileSprite + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize + * @extends Phaser.GameObjects.Components.Crop + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.TextureCrop + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {number} width - The width of the Game Object. If zero it will use the size of the texture frame. + * @param {number} height - The height of the Game Object. If zero it will use the size of the texture frame. + * @param {string} textureKey - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager. Cannot be a DynamicTexture. + * @param {(string|number)} [frameKey] - An optional frame from the Texture this Game Object is rendering with. + */ +var TileSprite = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.ComputedSize, + Components.Crop, + Components.Depth, + Components.Flip, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.TextureCrop, + Components.Tint, + Components.Transform, + Components.Visible, + TileSpriteRender + ], + + initialize: + + function TileSprite (scene, x, y, width, height, textureKey, frameKey) + { + var renderer = scene.sys.renderer; + + var isCanvas = renderer && !renderer.gl; + + GameObject.call(this, scene, 'TileSprite'); + + var displayTexture = scene.sys.textures.get(textureKey); + var displayFrame = displayTexture.get(frameKey); + + width = width ? Math.floor(width) : displayFrame.width; + height = height ? Math.floor(height) : displayFrame.height; + + /** + * Internal tile position vector. + * + * @name Phaser.GameObjects.TileSprite#_tilePosition + * @type {Phaser.Math.Vector2} + * @private + * @since 3.12.0 + */ + this._tilePosition = new Vector2(); + + /** + * Internal tile scale vector. + * + * @name Phaser.GameObjects.TileSprite#_tileScale + * @type {Phaser.Math.Vector2} + * @private + * @since 3.12.0 + */ + this._tileScale = new Vector2(1, 1); + + /** + * Internal tile rotation value. + * + * @name Phaser.GameObjects.TileSprite#_tileRotation + * @type {number} + * @private + * @since 4.0.0 + */ + this._tileRotation = 0; + + /** + * Whether the Tile Sprite has changed in some way, requiring an re-render of its tile texture. + * + * Such changes include the texture frame and scroll position of the Tile Sprite. + * + * This is irrelevant in WebGL mode. + * + * @name Phaser.GameObjects.TileSprite#dirty + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.dirty = false; + + /** + * The renderer in use by this Tile Sprite. + * + * @name Phaser.GameObjects.TileSprite#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.0.0 + */ + this.renderer = renderer; + + /** + * The Canvas element that the TileSprite renders its fill pattern in to. + * Only used in Canvas mode. + * + * @name Phaser.GameObjects.TileSprite#canvas + * @type {?HTMLCanvasElement} + * @since 3.12.0 + */ + this.canvas = isCanvas ? CanvasPool.create(this, width, height) : null; + + /** + * The Context of the Canvas element that the TileSprite renders its fill pattern in to. + * Only used in Canvas mode. + * + * @name Phaser.GameObjects.TileSprite#context + * @type {?CanvasRenderingContext2D} + * @since 3.12.0 + */ + this.context = isCanvas ? this.canvas.getContext('2d', { willReadFrequently: false }) : null; + + /** + * The internal unique key to refer to the texture in the TextureManager. + * + * @name Phaser.GameObjects.TileSprite#_displayTextureKey + * @type {string} + * @private + * @since 3.80.0 + */ + this._displayTextureKey = UUID(); + + /** + * The internal Texture to which the TileSprite renders its fill pattern. Only used in Canvas mode. + * + * @name Phaser.GameObjects.TileSprite#displayTexture + * @type {?(Phaser.Textures.Texture|Phaser.Textures.CanvasTexture)} + * @private + * @since 3.12.0 + */ + this.displayTexture = isCanvas ? scene.sys.textures.addCanvas(this._displayTextureKey, this.canvas) : null; + + /** + * The internal Texture Frame the TileSprite is using as its fill pattern. Only used in Canvas mode. + * + * @name Phaser.GameObjects.TileSprite#displayFrame + * @type {?Phaser.Textures.Frame} + * @private + * @since 3.12.0 + */ + this.displayFrame = this.displayTexture ? this.displayTexture.get() : null; + + /** + * The frame currently displayed. This is used internally to track + * animation updates. + * + * @name Phaser.GameObjects.TileSprite#currentFrame + * @type {Phaser.Textures.Frame} + * @private + * @since 4.0.0 + */ + this.currentFrame = null; + + /** + * The Canvas that the TileSprites texture is rendered to. + * This is used to create a WebGL texture from. + * + * @name Phaser.GameObjects.TileSprite#fillCanvas + * @type {HTMLCanvasElement} + * @since 3.12.0 + */ + this.fillCanvas = isCanvas ? CanvasPool.create2D(this, displayFrame.width, this.displayFrame.height) : null; + + /** + * The Canvas Context used to render the TileSprites texture. + * + * @name Phaser.GameObjects.TileSprite#fillContext + * @type {CanvasRenderingContext2D} + * @since 3.12.0 + */ + this.fillContext = this.fillCanvas ? this.fillCanvas.getContext('2d', { willReadFrequently: false }) : null; + + /** + * The texture that the Tile Sprite is rendered to, which is then rendered to a Scene. + * In WebGL this is a WebGLTextureWrapper. In Canvas it's a Canvas Fill Pattern. + * + * @name Phaser.GameObjects.TileSprite#fillPattern + * @type {?(Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper|CanvasPattern)} + * @since 3.12.0 + */ + this.fillPattern = null; + + /** + * The Animation State component of this TileSprite. + * + * This component provides features to apply animations to this TileSprite. + * It is responsible for playing, loading, queuing animations for later playback, + * mixing between animations and setting the current animation frame to this Sprite. + * + * @name Phaser.GameObjects.TileSprite#anims + * @type {Phaser.Animations.AnimationState} + * @since 3.0.0 + */ + this.anims = new AnimationState(this); + + this.setTexture(textureKey, frameKey); + this.setPosition(x, y); + this.setSize(width, height); + this.setOrigin(0.5, 0.5); + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.GameObjects.TileSprite#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultTileSpriteNodes; + } + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + /** + * Update this TileSprite's animations. + * + * @method Phaser.GameObjects.TileSprite#preUpdate + * @protected + * @since 3.0.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + preUpdate: function (time, delta) + { + this.anims.update(time, delta); + }, + + /** + * Sets the frame this Game Object will use to render with. + * + * The Frame has to belong to the current Texture being used. + * + * It can be either a string or an index. + * + * @method Phaser.GameObjects.TileSprite#setFrame + * @since 3.0.0 + * + * @param {(string|number)} frame - The name or index of the frame within the Texture. + * + * @return {this} This Game Object instance. + */ + setFrame: function (frame) + { + var newFrame = this.texture.get(frame); + + if (!newFrame.cutWidth || !newFrame.cutHeight) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + + this.frame = newFrame; + + this.dirty = true; + + return this; + }, + + /** + * No-op method for compatibility with Animation. + * + * @method Phaser.GameObjects.TileSprite#setSizeToFrame + * @since 4.0.0 + * @return {this} This Tile Sprite instance. + */ + setSizeToFrame: function () + { + return this; + }, + + /** + * Sets {@link Phaser.GameObjects.TileSprite#tilePositionX} and {@link Phaser.GameObjects.TileSprite#tilePositionY}. + * + * @method Phaser.GameObjects.TileSprite#setTilePosition + * @since 3.3.0 + * + * @param {number} [x] - The x position of this sprite's tiling texture. + * @param {number} [y] - The y position of this sprite's tiling texture. + * + * @return {this} This Tile Sprite instance. + */ + setTilePosition: function (x, y) + { + if (x !== undefined) + { + this.tilePositionX = x; + } + + if (y !== undefined) + { + this.tilePositionY = y; + } + + return this; + }, + + /** + * Sets {@link Phaser.GameObjects.TileSprite#tileRotation}. + * + * @method Phaser.GameObjects.TileSprite#setTileRotation + * @since 4.0.0 + * + * @param {number} [radians=0] - The rotation of the tiling texture, in radians. + */ + setTileRotation: function (radians) + { + if (radians === undefined) { radians = 0; } + + this.tileRotation = radians; + + return this; + }, + + /** + * Sets {@link Phaser.GameObjects.TileSprite#tileScaleX} and {@link Phaser.GameObjects.TileSprite#tileScaleY}. + * + * @method Phaser.GameObjects.TileSprite#setTileScale + * @since 3.12.0 + * + * @param {number} [x] - The horizontal scale of the tiling texture. If not given it will use the current `tileScaleX` value. + * @param {number} [y=x] - The vertical scale of the tiling texture. If not given it will use the `x` value. + * + * @return {this} This Tile Sprite instance. + */ + setTileScale: function (x, y) + { + if (x === undefined) { x = this.tileScaleX; } + if (y === undefined) { y = x; } + + this.tileScaleX = x; + this.tileScaleY = y; + + return this; + }, + + /** + * Render the tile texture if it is dirty, or if the frame has changed. + * + * This is called automatically during Canvas rendering. + * It is not used by WebGL. + * + * @method Phaser.GameObjects.TileSprite#updateTileTexture + * @private + * @since 3.0.0 + */ + updateTileTexture: function () + { + if (!this.renderer || this.renderer.gl) + { + return; + } + + // Draw the texture to our fillCanvas + + var frame = this.frame; + + var ctx = this.fillContext; + var canvas = this.fillCanvas; + + var fw = frame.cutWidth; + var fh = frame.cutHeight; + + ctx.clearRect(0, 0, fw, fh); + + canvas.width = fw; + canvas.height = fh; + + ctx.drawImage( + frame.source.image, + frame.cutX, frame.cutY, + frame.cutWidth, frame.cutHeight, + 0, 0, + fw, fh + ); + + this.fillPattern = ctx.createPattern(canvas, 'repeat'); + + this.currentFrame = frame; + }, + + /** + * Draw the fill pattern to the internal canvas. + * + * This is called automatically during Canvas rendering. + * It is not used by WebGL. + * + * @method Phaser.GameObjects.TileSprite#updateCanvas + * @private + * @since 3.12.0 + */ + updateCanvas: function () + { + var canvas = this.canvas; + var width = this.width; + var height = this.height; + + var newFrame = this.currentFrame !== this.frame; + + if (canvas.width !== width || canvas.height !== height || newFrame) + { + canvas.width = width; + canvas.height = height; + + this.displayFrame.setSize(width, height); + this.updateDisplayOrigin(); + + if (newFrame) + { + this.updateTileTexture(); + } + + this.dirty = true; + } + + if (!this.dirty || this.renderer && this.renderer.gl) + { + this.dirty = false; + return; + } + + var ctx = this.context; + + if (!this.scene.sys.game.config.antialias) + { + Smoothing.disable(ctx); + } + + var scaleX = this._tileScale.x; + var scaleY = this._tileScale.y; + + var positionX = this._tilePosition.x; + var positionY = this._tilePosition.y; + + ctx.clearRect(0, 0, width, height); + + ctx.save(); + + ctx.rotate(this._tileRotation); + + ctx.scale(scaleX, scaleY); + + ctx.translate(-positionX, -positionY); + + ctx.fillStyle = this.fillPattern; + + var scaledWidth = Math.max(width, Math.abs(width / scaleX)); + var scaledHeight = Math.max(height, Math.abs(height / scaleY)); + var hypotenuse = Math.sqrt(scaledWidth * scaledWidth + scaledHeight * scaledHeight); + + ctx.fillRect( + positionX - hypotenuse, + positionY - hypotenuse, + 2 * hypotenuse, + 2 * hypotenuse + ); + + ctx.restore(); + + this.dirty = false; + }, + + /** + * Internal destroy handler, called as part of the destroy process. + * + * @method Phaser.GameObjects.TileSprite#preDestroy + * @protected + * @since 3.9.0 + */ + preDestroy: function () + { + if (this.canvas) + { + CanvasPool.remove(this.canvas); + } + if (this.fillCanvas) + { + CanvasPool.remove(this.fillCanvas); + } + + this.fillPattern = null; + this.fillContext = null; + this.fillCanvas = null; + + this.displayTexture = null; + this.displayFrame = null; + + this.renderer = null; + + this.anims.destroy(); + + this.anims = undefined; + }, + + /** + * The horizontal scroll position of the Tile Sprite. + * + * @name Phaser.GameObjects.TileSprite#tilePositionX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + tilePositionX: { + + get: function () + { + return this._tilePosition.x; + }, + + set: function (value) + { + this._tilePosition.x = value; + this.dirty = true; + } + + }, + + /** + * The vertical scroll position of the Tile Sprite. + * + * @name Phaser.GameObjects.TileSprite#tilePositionY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + tilePositionY: { + + get: function () + { + return this._tilePosition.y; + }, + + set: function (value) + { + this._tilePosition.y = value; + this.dirty = true; + } + + }, + + /** + * The rotation of the Tile Sprite texture, in radians. + * + * @name Phaser.GameObjects.TileSprite#tileRotation + * @type {number} + * @default 0 + * @since 4.0.0 + */ + tileRotation: { + get: function () + { + return this._tileRotation; + }, + + set: function (radians) + { + this._tileRotation = radians; + this.dirty = true; + } + }, + + /** + * The horizontal scale of the Tile Sprite texture. + * + * @name Phaser.GameObjects.TileSprite#tileScaleX + * @type {number} + * @default 1 + * @since 3.11.0 + */ + tileScaleX: { + + get: function () + { + return this._tileScale.x; + }, + + set: function (value) + { + this._tileScale.x = value; + this.dirty = true; + } + + }, + + /** + * The vertical scale of the Tile Sprite texture. + * + * @name Phaser.GameObjects.TileSprite#tileScaleY + * @type {number} + * @default 1 + * @since 3.11.0 + */ + tileScaleY: { + + get: function () + { + return this._tileScale.y; + }, + + set: function (value) + { + this._tileScale.y = value; + this.dirty = true; + } + + } + +}); + +module.exports = TileSprite; + + +/***/ }), + +/***/ 46992: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.TileSprite#renderCanvas + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.TileSprite} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TileSpriteCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + src.updateCanvas(); + + camera.addToRenderList(src); + + renderer.batchSprite(src, src.displayFrame, camera, parentMatrix); +}; + +module.exports = TileSpriteCanvasRenderer; + + +/***/ }), + +/***/ 14167: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var TileSprite = __webpack_require__(20839); + +/** + * Creates a new TileSprite Game Object and returns it. + * + * Note: This method will only be available if the TileSprite Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#tileSprite + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.TileSprite.TileSpriteConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.TileSprite} The Game Object that was created. + */ +GameObjectCreator.register('tileSprite', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var x = GetAdvancedValue(config, 'x', 0); + var y = GetAdvancedValue(config, 'y', 0); + var width = GetAdvancedValue(config, 'width', 512); + var height = GetAdvancedValue(config, 'height', 512); + var key = GetAdvancedValue(config, 'key', ''); + var frame = GetAdvancedValue(config, 'frame', ''); + + var tile = new TileSprite(this.scene, x, y, width, height, key, frame); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, tile, config); + + return tile; +}); + + +/***/ }), + +/***/ 91681: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TileSprite = __webpack_require__(20839); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new TileSprite Game Object and adds it to the Scene. + * + * Note: This method will only be available if the TileSprite Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#tileSprite + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {number} width - The width of the Game Object. If zero it will use the size of the texture frame. + * @param {number} height - The height of the Game Object. If zero it will use the size of the texture frame. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. Cannot be a DynamicTexture. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.GameObjects.TileSprite} The Game Object that was created. + */ +GameObjectFactory.register('tileSprite', function (x, y, width, height, texture, frame) +{ + return this.displayList.add(new TileSprite(this.scene, x, y, width, height, texture, frame)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 56295: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(18553); +} + +if (true) +{ + renderCanvas = __webpack_require__(46992); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 18553: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.TileSprite#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.TileSprite} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TileSpriteWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var width = src.width; + var height = src.height; + + if (width === 0 || height === 0) + { + return; + } + + var camera = drawingContext.camera; + camera.addToRenderList(src); + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + src, + parentMatrix, + 0, + customRenderNodes.Texturer || defaultRenderNodes.Texturer, + customRenderNodes.Transformer || defaultRenderNodes.Transformer + ); +}; + +module.exports = TileSpriteWebGLRenderer; + + +/***/ }), + +/***/ 18471: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var DefaultImageNodes = __webpack_require__(40939); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var Events = __webpack_require__(51708); +var GameEvents = __webpack_require__(8443); +var GameObject = __webpack_require__(95643); +var MATH_CONST = __webpack_require__(36383); +var SoundEvents = __webpack_require__(14463); +var UUID = __webpack_require__(45650); +var VideoRender = __webpack_require__(10247); + +/** + * @classdesc + * A Video Game Object. + * + * This Game Object is capable of handling playback of a video file, video stream or media stream. + * + * You can optionally 'preload' the video into the Phaser Video Cache: + * + * ```javascript + * preload () { + * this.load.video('ripley', 'assets/aliens.mp4'); + * } + * + * create () { + * this.add.video(400, 300, 'ripley'); + * } + * ``` + * + * You don't have to 'preload' the video. You can also play it directly from a URL: + * + * ```javascript + * create () { + * this.add.video(400, 300).loadURL('assets/aliens.mp4'); + * } + * ``` + * + * To all intents and purposes, a video is a standard Game Object, just like a Sprite. And as such, you can do + * all the usual things to it, such as scaling, rotating, cropping, tinting, making interactive, giving a + * physics body, etc. + * + * Transparent videos are also possible via the WebM file format. Providing the video file has was encoded with + * an alpha channel, and providing the browser supports WebM playback (not all of them do), then it will render + * in-game with full transparency. + * + * Transparent videos are supported by the HEVC (H.265) codec, + * but only on some devices and browsers, and sometimes the alpha channel is ignored, + * which can be a problem if you're aiming for a consistent experience. + * We advise against relying on HEVC. + * + * Playback is handled entirely via the Request Video Frame API, which is supported by most modern browsers. + * A polyfill is provided for older browsers. + * + * ### Autoplaying Videos + * + * Videos can only autoplay if the browser has been unlocked with an interaction, or satisfies the MEI settings. + * The policies that control autoplaying are vast and vary between browser. You can, and should, read more about + * it here: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide + * + * If your video doesn't contain any audio, then set the `noAudio` parameter to `true` when the video is _loaded_, + * and it will often allow the video to play immediately: + * + * ```javascript + * preload () { + * this.load.video('pixar', 'nemo.mp4', true); + * } + * ``` + * + * The 3rd parameter in the load call tells Phaser that the video doesn't contain any audio tracks. Video without + * audio can autoplay without requiring a user interaction. Video with audio cannot do this unless it satisfies + * the browsers MEI settings. See the MDN Autoplay Guide for further details. + * + * Or: + * + * ```javascript + * create () { + * this.add.video(400, 300).loadURL('assets/aliens.mp4', true); + * } + * ``` + * + * You can set the `noAudio` parameter to `true` even if the video does contain audio. It will still allow the video + * to play immediately, but the audio will not start. + * + * Note that due to a bug in IE11 you cannot play a video texture to a Sprite in WebGL. For IE11 force Canvas mode. + * + * More details about video playback and the supported media formats can be found on MDN: + * + * https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement + * https://developer.mozilla.org/en-US/docs/Web/Media/Formats + * + * @class Video + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.20.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.TextureCrop + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {string} [key] - Optional key of the Video this Game Object will play, as stored in the Video Cache. + */ +var Video = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.ComputedSize, + Components.Depth, + Components.Flip, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.ScrollFactor, + Components.TextureCrop, + Components.Tint, + Components.Transform, + Components.Visible, + VideoRender + ], + + initialize: + + function Video (scene, x, y, key) + { + GameObject.call(this, scene, 'Video'); + + /** + * A reference to the HTML Video Element this Video Game Object is playing. + * + * Will be `undefined` until a video is loaded for playback. + * + * @name Phaser.GameObjects.Video#video + * @type {?HTMLVideoElement} + * @since 3.20.0 + */ + this.video; + + /** + * The Phaser Texture this Game Object is using to render the video to. + * + * Will be `undefined` until a video is loaded for playback. + * + * @name Phaser.GameObjects.Video#videoTexture + * @type {?Phaser.Textures.Texture} + * @since 3.20.0 + */ + this.videoTexture; + + /** + * A reference to the TextureSource backing the `videoTexture` Texture object. + * + * Will be `undefined` until a video is loaded for playback. + * + * @name Phaser.GameObjects.Video#videoTextureSource + * @type {?Phaser.Textures.TextureSource} + * @since 3.20.0 + */ + this.videoTextureSource; + + /** + * A Phaser `CanvasTexture` instance that holds the most recent snapshot taken from the video. + * + * This will only be set if the `snapshot` or `snapshotArea` methods have been called. + * + * Until those methods are called, this property will be `undefined`. + * + * @name Phaser.GameObjects.Video#snapshotTexture + * @type {?Phaser.Textures.CanvasTexture} + * @since 3.20.0 + */ + this.snapshotTexture; + + /** + * If you have saved this video to a texture via the `saveTexture` method, this controls if the video + * is rendered with `flipY` in WebGL or not. + * If you find your video is appearing upside down within a shader or + * custom renderer, flip this property. + * + * @name Phaser.GameObjects.Video#glFlipY + * @type {boolean} + * @since 4.0.0 + */ + this.glFlipY = true; + + /** + * The key used by the texture as stored in the Texture Manager. + * + * @name Phaser.GameObjects.Video#_key + * @type {string} + * @private + * @since 3.20.0 + */ + this._key = UUID(); + + /** + * An internal flag holding the current state of the video lock, should document interaction be required + * before playback can begin. + * + * @name Phaser.GameObjects.Video#touchLocked + * @type {boolean} + * @readonly + * @since 3.20.0 + */ + this.touchLocked = false; + + /** + * Should the video auto play when document interaction is required and happens? + * + * @name Phaser.GameObjects.Video#playWhenUnlocked + * @type {boolean} + * @since 3.20.0 + */ + this.playWhenUnlocked = false; + + /** + * Has the video created its texture and populated it with the first frame of video? + * + * @name Phaser.GameObjects.Video#frameReady + * @type {boolean} + * @since 3.60.0 + */ + this.frameReady = false; + + /** + * This read-only property returns `true` if the video is currently stalled, i.e. it has stopped + * playing due to a lack of data, or too much data, but hasn't yet reached the end of the video. + * + * This is set if the Video DOM element emits any of the following events: + * + * `stalled` + * `suspend` + * `waiting` + * + * And is cleared if the Video DOM element emits the `playing` event, or handles + * a requestVideoFrame call. + * + * Listen for the Phaser Event `VIDEO_STALLED` to be notified and inspect the event + * to see which DOM event caused it. + * + * Note that being stalled isn't always a negative thing. A video can be stalled if it + * has downloaded enough data in to its buffer to not need to download any more until + * the current batch of frames have rendered. + * + * @name Phaser.GameObjects.Video#isStalled + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.isStalled = false; + + /** + * Records the number of times the video has failed to play, + * typically because the user hasn't interacted with the page yet. + * + * @name Phaser.GameObjects.Video#failedPlayAttempts + * @type {number} + * @since 3.60.0 + */ + this.failedPlayAttempts = 0; + + /** + * If the browser supports the Request Video Frame API then this + * property will hold the metadata that is returned from + * the callback each time it is invoked. + * + * See https://wicg.github.io/video-rvfc/#video-frame-metadata-callback + * for a complete list of all properties that will be in this object. + * Likely of most interest is the `mediaTime` property: + * + * The media presentation timestamp (PTS) in seconds of the frame presented + * (e.g. its timestamp on the video.currentTime timeline). MAY have a zero + * value for live-streams or WebRTC applications. + * + * If the browser doesn't support the API then this property will be undefined. + * + * @name Phaser.GameObjects.Video#metadata + * @type {VideoFrameCallbackMetadata} + * @since 3.60.0 + */ + this.metadata; + + /** + * The current retry elapsed time. + * + * @name Phaser.GameObjects.Video#retry + * @type {number} + * @since 3.20.0 + */ + this.retry = 0; + + /** + * If a video fails to play due to a lack of user interaction, this is the + * amount of time, in ms, that the video will wait before trying again to + * play. The default is 500ms. + * + * @name Phaser.GameObjects.Video#retryInterval + * @type {number} + * @since 3.20.0 + */ + this.retryInterval = 500; + + /** + * The video was muted due to a system event, such as the game losing focus. + * + * @name Phaser.GameObjects.Video#_systemMuted + * @type {boolean} + * @private + * @since 3.20.0 + */ + this._systemMuted = false; + + /** + * The video was muted due to game code, not a system event. + * + * @name Phaser.GameObjects.Video#_codeMuted + * @type {boolean} + * @private + * @since 3.20.0 + */ + this._codeMuted = false; + + /** + * The video was paused due to a system event, such as the game losing focus. + * + * @name Phaser.GameObjects.Video#_systemPaused + * @type {boolean} + * @private + * @since 3.20.0 + */ + this._systemPaused = false; + + /** + * The video was paused due to game code, not a system event. + * + * @name Phaser.GameObjects.Video#_codePaused + * @type {boolean} + * @private + * @since 3.20.0 + */ + this._codePaused = false; + + /** + * The locally bound event callback handlers. + * + * @name Phaser.GameObjects.Video#_callbacks + * @type {any} + * @private + * @since 3.20.0 + */ + this._callbacks = { + ended: this.completeHandler.bind(this), + legacy: this.legacyPlayHandler.bind(this), + playing: this.playingHandler.bind(this), + seeked: this.seekedHandler.bind(this), + seeking: this.seekingHandler.bind(this), + stalled: this.stalledHandler.bind(this), + suspend: this.stalledHandler.bind(this), + waiting: this.stalledHandler.bind(this) + }; + + /** + * The locally bound callback handler specifically for load and load error events. + * + * @name Phaser.GameObjects.Video#_loadCallbackHandler + * @type {function} + * @private + * @since 3.60.0 + */ + this._loadCallbackHandler = this.loadErrorHandler.bind(this); + + /** + * The locally bound callback handler specifically for the loadedmetadata event. + * + * @name Phaser.GameObjects.Video#_metadataCallbackHandler + * @type {function} + * @private + * @since 3.80.0 + */ + this._metadataCallbackHandler = this.metadataHandler.bind(this); + + /** + * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method. + * + * @name Phaser.GameObjects.Video#_crop + * @type {object} + * @private + * @since 3.20.0 + */ + this._crop = this.resetCropObject(); + + /** + * An object containing in and out markers for sequence playback. + * + * @name Phaser.GameObjects.Video#markers + * @type {any} + * @since 3.20.0 + */ + this.markers = {}; + + /** + * The in marker. + * + * @name Phaser.GameObjects.Video#_markerIn + * @type {number} + * @private + * @since 3.20.0 + */ + this._markerIn = 0; + + /** + * The out marker. + * + * @name Phaser.GameObjects.Video#_markerOut + * @type {number} + * @private + * @since 3.20.0 + */ + this._markerOut = 0; + + /** + * Are we playing a marked segment of the video? + * + * @name Phaser.GameObjects.Video#_playingMarker + * @type {boolean} + * @private + * @since 3.60.0 + */ + this._playingMarker = false; + + /** + * The previous frames mediaTime. + * + * @name Phaser.GameObjects.Video#_lastUpdate + * @type {number} + * @private + * @since 3.60.0 + */ + this._lastUpdate = 0; + + /** + * The key of the current video as stored in the Video cache. + * + * If the video did not come from the cache this will be an empty string. + * + * @name Phaser.GameObjects.Video#cacheKey + * @type {string} + * @readonly + * @since 3.60.0 + */ + this.cacheKey = ''; + + /** + * Is the video currently seeking? + * + * This is set to `true` when the `seeking` event is fired, + * and set to `false` when the `seeked` event is fired. + * + * @name Phaser.GameObjects.Video#isSeeking + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.isSeeking = false; + + /** + * Has Video.play been called? This is reset if a new Video is loaded. + * + * @name Phaser.GameObjects.Video#_playCalled + * @type {boolean} + * @private + * @since 3.60.0 + */ + this._playCalled = false; + + /** + * Has Video.getFirstFrame been called? This is reset if a new Video is loaded or played. + * + * @name Phaser.GameObjects.Video#_getFrame + * @type {boolean} + * @private + * @since 3.85.0 + */ + this._getFrame = false; + + /** + * The Callback ID returned by Request Video Frame. + * + * @name Phaser.GameObjects.Video#_rfvCallbackId + * @type {number} + * @private + * @since 3.60.0 + */ + this._rfvCallbackId = 0; + + var game = scene.sys.game; + + /** + * A reference to Device.Video. + * + * @name Phaser.GameObjects.Video#_device + * @type {string[]} + * @private + * @since 3.60.0 + */ + this._device = game.device.video; + + this.setPosition(x, y); + this.setSize(256, 256); + this.initRenderNodes(this._defaultRenderNodesMap); + + game.events.on(GameEvents.PAUSE, this.globalPause, this); + game.events.on(GameEvents.RESUME, this.globalResume, this); + + var sound = scene.sys.sound; + + if (sound) + { + sound.on(SoundEvents.GLOBAL_MUTE, this.globalMute, this); + } + + if (key) + { + this.load(key); + } + }, + + /** + * The default render node map for this Game Object. + * + * @name Phaser.GameObjects.Video#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultImageNodes; + } + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + /** + * Loads a Video from the Video Cache, ready for playback with the `Video.play` method. + * + * If a video is already playing, this method allows you to change the source of the current video element. + * It works by first stopping the current video and then starts playback of the new source through the existing video element. + * + * The reason you may wish to do this is because videos that require interaction to unlock, remain in an unlocked + * state, even if you change the source of the video. By changing the source to a new video you avoid having to + * go through the unlock process again. + * + * @method Phaser.GameObjects.Video#load + * @since 3.60.0 + * + * @param {string} key - The key of the Video this Game Object will play, as stored in the Video Cache. + * + * @return {this} This Video Game Object for method chaining. + */ + load: function (key) + { + var video = this.scene.sys.cache.video.get(key); + + if (video) + { + this.cacheKey = key; + + this.loadHandler(video.url, video.noAudio, video.crossOrigin); + } + else + { + console.warn('No video in cache for key: ' + key); + } + + return this; + }, + + /** + * This method allows you to change the source of the current video element. It works by first stopping the + * current video, if playing. Then deleting the video texture, if one has been created. Finally, it makes a + * new video texture and starts playback of the new source through the existing video element. + * + * The reason you may wish to do this is because videos that require interaction to unlock, remain in an unlocked + * state, even if you change the source of the video. By changing the source to a new video you avoid having to + * go through the unlock process again. + * + * @method Phaser.GameObjects.Video#changeSource + * @since 3.20.0 + * + * @param {string} key - The key of the Video this Game Object will swap to playing, as stored in the Video Cache. + * @param {boolean} [autoplay=true] - Should the video start playing immediately, once the swap is complete? + * @param {boolean} [loop=false] - Should the video loop automatically when it reaches the end? Please note that not all browsers support _seamless_ video looping for all encoding formats. + * @param {number} [markerIn] - Optional in marker time, in seconds, for playback of a sequence of the video. + * @param {number} [markerOut] - Optional out marker time, in seconds, for playback of a sequence of the video. + * + * @return {this} This Video Game Object for method chaining. + */ + changeSource: function (key, autoplay, loop, markerIn, markerOut) + { + if (autoplay === undefined) { autoplay = true; } + if (loop === undefined) { loop = false; } + + if (this.cacheKey !== key) + { + this.load(key); + + if (autoplay) + { + this.play(loop, markerIn, markerOut); + } + } + }, + + /** + * Returns the key of the currently played video, as stored in the Video Cache. + * + * If the video did not come from the cache this will return an empty string. + * + * @method Phaser.GameObjects.Video#getVideoKey + * @since 3.20.0 + * + * @return {string} The key of the video being played from the Video Cache, if any. + */ + getVideoKey: function () + { + return this.cacheKey; + }, + + /** + * Loads a Video from the given URL, ready for playback with the `Video.play` method. + * + * If a video is already playing, this method allows you to change the source of the current video element. + * It works by first stopping the current video and then starts playback of the new source through the existing video element. + * + * The reason you may wish to do this is because videos that require interaction to unlock, remain in an unlocked + * state, even if you change the source of the video. By changing the source to a new video you avoid having to + * go through the unlock process again. + * + * @method Phaser.GameObjects.Video#loadURL + * @since 3.60.0 + * + * @param {(string|string[]|Phaser.Types.Loader.FileTypes.VideoFileURLConfig|Phaser.Types.Loader.FileTypes.VideoFileURLConfig[])} [urls] - The absolute or relative URL to load the video files from. + * @param {boolean} [noAudio=false] - Does the video have an audio track? If not you can enable auto-playing on it. + * @param {string} [crossOrigin] - The value to use for the `crossOrigin` property in the video load request. Either undefined, `anonymous` or `use-credentials`. If no value is given, `crossorigin` will not be set in the request. + * + * @return {this} This Video Game Object for method chaining. + */ + loadURL: function (urls, noAudio, crossOrigin) + { + if (noAudio === undefined) { noAudio = false; } + + var urlConfig = this._device.getVideoURL(urls); + + if (!urlConfig) + { + console.warn('No supported video format found for ' + urls); + } + else + { + this.cacheKey = ''; + + this.loadHandler(urlConfig.url, noAudio, crossOrigin); + } + + return this; + }, + + /** + * Loads a Video from the given MediaStream object, ready for playback with the `Video.play` method. + * + * @method Phaser.GameObjects.Video#loadMediaStream + * @since 3.50.0 + * + * @param {MediaStream} stream - The MediaStream object. + * @param {boolean} [noAudio=false] - Does the video have an audio track? If not you can enable auto-playing on it. + * @param {string} [crossOrigin] - The value to use for the `crossOrigin` property in the video load request. Either undefined, `anonymous` or `use-credentials`. If no value is given, `crossorigin` will not be set in the request. + * + * @return {this} This Video Game Object for method chaining. + */ + loadMediaStream: function (stream, noAudio, crossOrigin) + { + return this.loadHandler(null, noAudio, crossOrigin, stream); + }, + + /** + * Internal method that loads a Video from the given URL, ready for playback with the + * `Video.play` method. + * + * Normally you don't call this method directly, but instead use the `Video.loadURL` method, + * or the `Video.load` method if you have preloaded the video. + * + * Calling this method will skip checking if the browser supports the given format in + * the URL, where-as the other two methods enforce these checks. + * + * @method Phaser.GameObjects.Video#loadHandler + * @since 3.60.0 + * + * @param {string} [url] - The absolute or relative URL to load the video file from. Set to `null` if passing in a MediaStream object. + * @param {boolean} [noAudio] - Does the video have an audio track? If not you can enable auto-playing on it. + * @param {string} [crossOrigin] - The value to use for the `crossOrigin` property in the video load request. Either undefined, `anonymous` or `use-credentials`. If no value is given, `crossorigin` will not be set in the request. + * @param {string} [stream] - A MediaStream object if this is playing a stream instead of a file. + * + * @return {this} This Video Game Object for method chaining. + */ + loadHandler: function (url, noAudio, crossOrigin, stream) + { + if (!noAudio) { noAudio = false; } + + var video = this.video; + + if (video) + { + // Re-use the existing video element + + this.removeLoadEventHandlers(); + + this.stop(); + } + else + { + video = document.createElement('video'); + + video.controls = false; + + video.setAttribute('playsinline', 'playsinline'); + video.setAttribute('preload', 'auto'); + video.setAttribute('disablePictureInPicture', 'true'); + } + + if (noAudio) + { + video.muted = true; + video.defaultMuted = true; + + video.setAttribute('autoplay', 'autoplay'); + } + else + { + video.muted = false; + video.defaultMuted = false; + + video.removeAttribute('autoplay'); + } + + if (!crossOrigin) + { + video.removeAttribute('crossorigin'); + } + else + { + video.setAttribute('crossorigin', crossOrigin); + } + + if (stream) + { + if ('srcObject' in video) + { + try + { + video.srcObject = stream; + } + catch (err) + { + if (err.name !== 'TypeError') + { + throw err; + } + + video.src = URL.createObjectURL(stream); + } + } + else + { + video.src = URL.createObjectURL(stream); + } + } + else + { + video.src = url; + } + + this.retry = 0; + this.video = video; + + this._playCalled = false; + + video.load(); + + this.addLoadEventHandlers(); + + var texture = this.scene.sys.textures.get(this._key); + + this.setTexture(texture); + + return this; + }, + + /** + * This method handles the Request Video Frame callback. + * + * It is called by the browser when a new video frame is ready to be displayed. + * + * It's also responsible for the creation of the video texture, if it doesn't + * already exist. If it does, it updates the texture as required. + * + * For more details about the Request Video Frame callback, see: + * https://web.dev/requestvideoframecallback-rvfc + * + * @method Phaser.GameObjects.Video#requestVideoFrame + * @fires Phaser.GameObjects.Events#VIDEO_CREATED + * @fires Phaser.GameObjects.Events#VIDEO_LOOP + * @fires Phaser.GameObjects.Events#VIDEO_COMPLETE + * @fires Phaser.GameObjects.Events#VIDEO_PLAY + * @fires Phaser.GameObjects.Events#VIDEO_TEXTURE + * @since 3.60.0 + * + * @param {DOMHighResTimeStamp} now - The current time in milliseconds. + * @param {VideoFrameCallbackMetadata} metadata - Useful metadata about the video frame that was most recently presented for composition. See https://wicg.github.io/video-rvfc/#video-frame-metadata-callback + */ + requestVideoFrame: function (now, metadata) + { + var video = this.video; + + if (!video) + { + return; + } + + var width = metadata.width; + var height = metadata.height; + + var texture = this.videoTexture; + var textureSource = this.videoTextureSource; + var newVideo = (!texture || textureSource.source !== video); + + if (newVideo) + { + // First frame of a new video + this._codePaused = video.paused; + this._codeMuted = video.muted; + + if (!texture) + { + texture = this.scene.sys.textures.create(this._key, video, width, height); + + texture.add('__BASE', 0, 0, 0, width, height); + + this.setTexture(texture); + + this.videoTexture = texture; + this.videoTextureSource = texture.source[0]; + + this.videoTextureSource.setFlipY(this.glFlipY); + + this.emit(Events.VIDEO_TEXTURE, this, texture); + } + else + { + // Re-use the existing texture + textureSource.source = video; + textureSource.width = width; + textureSource.height = height; + + // Resize base frame + texture.get().setSize(width, height); + } + + this.setSizeToFrame(); + this.updateDisplayOrigin(); + } + else + { + textureSource.update(); + } + + this.isStalled = false; + + this.metadata = metadata; + + var currentTime = metadata.mediaTime; + + if (newVideo) + { + this._lastUpdate = currentTime; + + this.emit(Events.VIDEO_CREATED, this, width, height); + + if (!this.frameReady) + { + this.frameReady = true; + + this.emit(Events.VIDEO_PLAY, this); + } + } + + if (this._playingMarker) + { + if (currentTime >= this._markerOut) + { + if (video.loop) + { + video.currentTime = this._markerIn; + + this.emit(Events.VIDEO_LOOP, this); + } + else + { + this.stop(false); + + this.emit(Events.VIDEO_COMPLETE, this); + } + } + } + else if (currentTime < this._lastUpdate) + { + this.emit(Events.VIDEO_LOOP, this); + } + + this._lastUpdate = currentTime; + + if (this._getFrame) + { + this.removeEventHandlers(); + + video.pause(); + + this._getFrame = false; + } + else + { + this._rfvCallbackId = this.video.requestVideoFrameCallback(this.requestVideoFrame.bind(this)); + } + }, + + /** + * Starts this video playing. + * + * If the video is already playing, or has been queued to play with `changeSource` then this method just returns. + * + * Videos can only autoplay if the browser has been unlocked. This happens if you have interacted with the browser, i.e. + * by clicking on it or pressing a key, or due to server settings. The policies that control autoplaying are vast and + * vary between browser. You can read more here: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide + * + * If your video doesn't contain any audio, then set the `noAudio` parameter to `true` when the video is loaded, + * and it will often allow the video to play immediately: + * + * ```javascript + * preload () { + * this.load.video('pixar', 'nemo.mp4', true); + * } + * ``` + * + * The 3rd parameter in the load call tells Phaser that the video doesn't contain any audio tracks. Video without + * audio can autoplay without requiring a user interaction. Video with audio cannot do this unless it satisfies + * the browsers MEI settings. See the MDN Autoplay Guide for details. + * + * If you need audio in your videos, then you'll have to consider the fact that the video cannot start playing until the + * user has interacted with the browser, into your game flow. + * + * @method Phaser.GameObjects.Video#play + * @since 3.20.0 + * + * @param {boolean} [loop=false] - Should the video loop automatically when it reaches the end? Please note that not all browsers support _seamless_ video looping for all encoding formats. + * @param {number} [markerIn] - Optional in marker time, in seconds, for playback of a sequence of the video. + * @param {number} [markerOut] - Optional out marker time, in seconds, for playback of a sequence of the video. + * + * @return {this} This Video Game Object for method chaining. + */ + play: function (loop, markerIn, markerOut) + { + if (markerIn === undefined) { markerIn = -1; } + if (markerOut === undefined) { markerOut = MATH_CONST.MAX_SAFE_INTEGER; } + + var video = this.video; + + if (!video || this.isPlaying()) + { + if (!video) + { + console.warn('Video not loaded'); + } + + return this; + } + + // We can reset these each time play is called, even if the video hasn't started yet + + if (loop === undefined) { loop = video.loop; } + + video.loop = loop; + + this._markerIn = markerIn; + this._markerOut = markerOut; + this._playingMarker = (markerIn > -1 && markerOut > markerIn && markerOut < MATH_CONST.MAX_SAFE_INTEGER); + + // But we go no further if play has already been called + + if (!this._playCalled) + { + this._getFrame = false; + + this._rfvCallbackId = video.requestVideoFrameCallback(this.requestVideoFrame.bind(this)); + + this._playCalled = true; + + this.createPlayPromise(); + } + + return this; + }, + + /** + * Attempts to get the first frame of the video by running the `requestVideoFrame` callback once, + * then stopping. This is useful if you need to grab the first frame of the video to display behind + * a 'play' button, without actually calling the 'play' method. + * + * If the video is already playing, or has been queued to play with `changeSource` then this method just returns. + * + * @method Phaser.GameObjects.Video#getFirstFrame + * @since 3.85.0 + * + * @return {this} This Video Game Object for method chaining. + */ + getFirstFrame: function () + { + var video = this.video; + + if (!video || this.isPlaying()) + { + if (!video) + { + console.warn('Video not loaded'); + } + + return this; + } + + if (!this._playCalled) + { + this._getFrame = true; + + this._rfvCallbackId = video.requestVideoFrameCallback(this.requestVideoFrame.bind(this)); + + this.createPlayPromise(); + } + + return this; + }, + + /** + * Adds the loading specific event handlers to the video element. + * + * @method Phaser.GameObjects.Video#addLoadEventHandlers + * @since 3.60.0 + */ + addLoadEventHandlers: function () + { + var video = this.video; + + if (video) + { + video.addEventListener('error', this._loadCallbackHandler); + video.addEventListener('abort', this._loadCallbackHandler); + video.addEventListener('loadedmetadata', this._metadataCallbackHandler); + } + }, + + /** + * Removes the loading specific event handlers from the video element. + * + * @method Phaser.GameObjects.Video#removeLoadEventHandlers + * @since 3.60.0 + */ + removeLoadEventHandlers: function () + { + var video = this.video; + + if (video) + { + video.removeEventListener('error', this._loadCallbackHandler); + video.removeEventListener('abort', this._loadCallbackHandler); + } + }, + + /** + * Adds the playback specific event handlers to the video element. + * + * @method Phaser.GameObjects.Video#addEventHandlers + * @since 3.60.0 + */ + addEventHandlers: function () + { + var video = this.video; + + // Set these _after_ calling `video.play` or they don't fire + // (really useful, thanks browsers!) + + if (video) + { + var callbacks = this._callbacks; + + for (var callback in callbacks) + { + video.addEventListener(callback, callbacks[callback]); + } + } + }, + + /** + * Removes the playback specific event handlers from the video element. + * + * @method Phaser.GameObjects.Video#removeEventHandlers + * @since 3.60.0 + */ + removeEventHandlers: function () + { + var video = this.video; + + if (video) + { + var callbacks = this._callbacks; + + for (var callback in callbacks) + { + video.removeEventListener(callback, callbacks[callback]); + } + } + }, + + /** + * Creates the video.play promise and adds the success and error handlers to it. + * + * Not all browsers support the video.play promise, so this method will fall back to + * the old-school way of handling the video.play call. + * + * See https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play#browser_compatibility for details. + * + * @method Phaser.GameObjects.Video#createPlayPromise + * @since 3.60.0 + * + * @param {boolean} [catchError=true] - Should the error be caught and the video marked as failed to play? + */ + createPlayPromise: function (catchError) + { + if (catchError === undefined) { catchError = true; } + + var video = this.video; + + var playPromise = video.play(); + + if (playPromise !== undefined) + { + var success = this.playSuccess.bind(this); + var error = this.playError.bind(this); + + if (!catchError) + { + var _this = this; + + error = function () + { + _this.failedPlayAttempts++; + }; + } + + playPromise.then(success).catch(error); + } + else + { + // Old-school fallback here for pre-2019 browsers + video.addEventListener('playing', this._callbacks.legacy); + + if (!catchError) + { + this.failedPlayAttempts++; + } + } + }, + + /** + * Adds a sequence marker to this video. + * + * Markers allow you to split a video up into sequences, delineated by a start and end time, given in seconds. + * + * You can then play back specific markers via the `playMarker` method. + * + * Note that marker timing is _not_ frame-perfect. You should construct your videos in such a way that you allow for + * plenty of extra padding before and after each sequence to allow for discrepancies in browser seek and currentTime accuracy. + * + * See https://github.com/w3c/media-and-entertainment/issues/4 for more details about this issue. + * + * @method Phaser.GameObjects.Video#addMarker + * @since 3.20.0 + * + * @param {string} key - A unique name to give this marker. + * @param {number} markerIn - The time, in seconds, representing the start of this marker. + * @param {number} markerOut - The time, in seconds, representing the end of this marker. + * + * @return {this} This Video Game Object for method chaining. + */ + addMarker: function (key, markerIn, markerOut) + { + if (!isNaN(markerIn) && markerIn >= 0 && !isNaN(markerOut) && markerOut > markerIn) + { + this.markers[key] = [ markerIn, markerOut ]; + } + + return this; + }, + + /** + * Plays a pre-defined sequence in this video. + * + * Markers allow you to split a video up into sequences, delineated by a start and end time, given in seconds and + * specified via the `addMarker` method. + * + * Note that marker timing is _not_ frame-perfect. You should construct your videos in such a way that you allow for + * plenty of extra padding before and after each sequence to allow for discrepancies in browser seek and currentTime accuracy. + * + * See https://github.com/w3c/media-and-entertainment/issues/4 for more details about this issue. + * + * @method Phaser.GameObjects.Video#playMarker + * @since 3.20.0 + * + * @param {string} key - The name of the marker sequence to play. + * @param {boolean} [loop=false] - Should the video loop automatically when it reaches the end? Please note that not all browsers support _seamless_ video looping for all encoding formats. + * + * @return {this} This Video Game Object for method chaining. + */ + playMarker: function (key, loop) + { + var marker = this.markers[key]; + + if (marker) + { + this.play(loop, marker[0], marker[1]); + } + + return this; + }, + + /** + * Removes a previously set marker from this video. + * + * If the marker is currently playing it will _not_ stop playback. + * + * @method Phaser.GameObjects.Video#removeMarker + * @since 3.20.0 + * + * @param {string} key - The name of the marker to remove. + * + * @return {this} This Video Game Object for method chaining. + */ + removeMarker: function (key) + { + delete this.markers[key]; + + return this; + }, + + /** + * Takes a snapshot of the current frame of the video and renders it to a CanvasTexture object, + * which is then returned. You can optionally resize the grab by passing a width and height. + * + * This method returns a reference to the `Video.snapshotTexture` object. Calling this method + * multiple times will overwrite the previous snapshot with the most recent one. + * + * @method Phaser.GameObjects.Video#snapshot + * @since 3.20.0 + * + * @param {number} [width] - The width of the resulting CanvasTexture. + * @param {number} [height] - The height of the resulting CanvasTexture. + * + * @return {Phaser.Textures.CanvasTexture} + */ + snapshot: function (width, height) + { + if (width === undefined) { width = this.width; } + if (height === undefined) { height = this.height; } + + return this.snapshotArea(0, 0, this.width, this.height, width, height); + }, + + /** + * Takes a snapshot of the specified area of the current frame of the video and renders it to a CanvasTexture object, + * which is then returned. You can optionally resize the grab by passing a different `destWidth` and `destHeight`. + * + * This method returns a reference to the `Video.snapshotTexture` object. Calling this method + * multiple times will overwrite the previous snapshot with the most recent one. + * + * @method Phaser.GameObjects.Video#snapshotArea + * @since 3.20.0 + * + * @param {number} [x=0] - The horizontal location of the top-left of the area to grab from. + * @param {number} [y=0] - The vertical location of the top-left of the area to grab from. + * @param {number} [srcWidth] - The width of area to grab from the video. If not given it will grab the full video dimensions. + * @param {number} [srcHeight] - The height of area to grab from the video. If not given it will grab the full video dimensions. + * @param {number} [destWidth] - The destination width of the grab, allowing you to resize it. + * @param {number} [destHeight] - The destination height of the grab, allowing you to resize it. + * + * @return {Phaser.Textures.CanvasTexture} + */ + snapshotArea: function (x, y, srcWidth, srcHeight, destWidth, destHeight) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (srcWidth === undefined) { srcWidth = this.width; } + if (srcHeight === undefined) { srcHeight = this.height; } + if (destWidth === undefined) { destWidth = srcWidth; } + if (destHeight === undefined) { destHeight = srcHeight; } + + var video = this.video; + var snap = this.snapshotTexture; + + if (!snap) + { + snap = this.scene.sys.textures.createCanvas(UUID(), destWidth, destHeight); + + this.snapshotTexture = snap; + + if (video) + { + snap.context.drawImage(video, x, y, srcWidth, srcHeight, 0, 0, destWidth, destHeight); + } + } + else + { + snap.setSize(destWidth, destHeight); + + if (video) + { + snap.context.drawImage(video, x, y, srcWidth, srcHeight, 0, 0, destWidth, destHeight); + } + } + + return snap.update(); + }, + + /** + * Stores a copy of this Videos `snapshotTexture` in the Texture Manager using the given key. + * + * This texture is created when the `snapshot` or `snapshotArea` methods are called. + * + * After doing this, any texture based Game Object, such as a Sprite, can use the contents of the + * snapshot by using the texture key: + * + * ```javascript + * var vid = this.add.video(0, 0, 'intro'); + * + * vid.snapshot(); + * + * vid.saveSnapshotTexture('doodle'); + * + * this.add.image(400, 300, 'doodle'); + * ``` + * + * Updating the contents of the `snapshotTexture`, for example by calling `snapshot` again, + * will automatically update _any_ Game Object that is using it as a texture. + * Calling `saveSnapshotTexture` again will not save another copy of the same texture, + * it will just rename the existing one. + * + * By default it will create a single base texture. You can add frames to the texture + * by using the `Texture.add` method. After doing this, you can then allow Game Objects + * to use a specific frame. + * + * @method Phaser.GameObjects.Video#saveSnapshotTexture + * @since 3.20.0 + * + * @param {string} key - The unique key to store the texture as within the global Texture Manager. + * + * @return {Phaser.Textures.CanvasTexture} The Texture that was saved. + */ + saveSnapshotTexture: function (key) + { + if (this.snapshotTexture) + { + this.scene.sys.textures.renameTexture(this.snapshotTexture.key, key); + } + else + { + this.snapshotTexture = this.scene.sys.textures.createCanvas(key, this.width, this.height); + } + + return this.snapshotTexture; + }, + + /** + * This internal method is called automatically if the playback Promise resolves successfully. + * + * @method Phaser.GameObjects.Video#playSuccess + * @fires Phaser.GameObjects.Events#VIDEO_UNLOCKED + * @since 3.60.0 + */ + playSuccess: function () + { + if (!this._playCalled) + { + // The stop method has been called but the Promise has resolved + // after this, so we need to just abort. + return; + } + + this.addEventHandlers(); + + this._codePaused = false; + + if (this.touchLocked) + { + this.touchLocked = false; + + this.emit(Events.VIDEO_UNLOCKED, this); + } + + var sound = this.scene.sys.sound; + + if (sound && sound.mute) + { + // Mute will be set based on the global mute state of the Sound Manager (if there is one) + this.setMute(true); + } + + if (this._markerIn > -1) + { + this.video.currentTime = this._markerIn; + } + }, + + /** + * This internal method is called automatically if the playback Promise fails to resolve. + * + * @method Phaser.GameObjects.Video#playError + * @fires Phaser.GameObjects.Events#VIDEO_ERROR + * @fires Phaser.GameObjects.Events#VIDEO_UNSUPPORTED + * @fires Phaser.GameObjects.Events#VIDEO_LOCKED + * @since 3.60.0 + * + * @param {DOMException} error - The Promise DOM Exception error. + */ + playError: function (error) + { + var name = error.name; + + if (name === 'NotAllowedError') + { + this.touchLocked = true; + this.playWhenUnlocked = true; + this.failedPlayAttempts = 1; + + this.emit(Events.VIDEO_LOCKED, this); + } + else if (name === 'NotSupportedError') + { + this.stop(false); + + this.emit(Events.VIDEO_UNSUPPORTED, this, error); + } + else + { + this.stop(false); + + this.emit(Events.VIDEO_ERROR, this, error); + } + }, + + /** + * Called when the video emits a `playing` event. + * + * This is the legacy handler for browsers that don't support Promise based playback. + * + * @method Phaser.GameObjects.Video#legacyPlayHandler + * @since 3.60.0 + */ + legacyPlayHandler: function () + { + var video = this.video; + + if (video) + { + this.playSuccess(); + + video.removeEventListener('playing', this._callbacks.legacy); + } + }, + + /** + * Called when the video emits a `playing` event. + * + * @method Phaser.GameObjects.Video#playingHandler + * @fires Phaser.GameObjects.Events#VIDEO_PLAYING + * @since 3.60.0 + */ + playingHandler: function () + { + this.isStalled = false; + + this.emit(Events.VIDEO_PLAYING, this); + }, + + /** + * This internal method is called automatically if the video fails to load. + * + * @method Phaser.GameObjects.Video#loadErrorHandler + * @fires Phaser.GameObjects.Events#VIDEO_ERROR + * @since 3.20.0 + * + * @param {Event} event - The error Event. + */ + loadErrorHandler: function (event) + { + this.stop(false); + + this.emit(Events.VIDEO_ERROR, this, event); + }, + + /** + * This internal method is called automatically when the video metadata is available. + * + * @method Phaser.GameObjects.Video#metadataHandler + * @fires Phaser.GameObjects.Events#VIDEO_METADATA + * @since 3.80.0 + * + * @param {Event} event - The loadedmetadata Event. + */ + metadataHandler: function (event) + { + this.emit(Events.VIDEO_METADATA, this, event); + }, + + /** + * Sets the size of this Game Object to be that of the given Frame. + * + * This will not change the size that the Game Object is rendered in-game. + * For that you need to either set the scale of the Game Object (`setScale`) or call the + * `setDisplaySize` method, which is the same thing as changing the scale but allows you + * to do so by giving pixel values. + * + * If you have enabled this Game Object for input, changing the size will _not_ change the + * size of the hit area. To do this you should adjust the `input.hitArea` object directly. + * + * @method Phaser.GameObjects.Video#setSizeToFrame + * @since 3.0.0 + * + * @param {Phaser.Textures.Frame|boolean} [frame] - The frame to base the size of this Game Object on. + * + * @return {this} This Game Object instance. + */ + setSizeToFrame: function (frame) + { + if (!frame) { frame = this.frame; } + + this.width = frame.realWidth; + this.height = frame.realHeight; + + if (this.scaleX !== 1) + { + this.scaleX = this.displayWidth / this.width; + } + + if (this.scaleY !== 1) + { + this.scaleY = this.displayHeight / this.height; + } + + var input = this.input; + + if (input && !input.customHitArea) + { + input.hitArea.width = this.width; + input.hitArea.height = this.height; + } + + return this; + }, + + /** + * This internal method is called automatically if the video stalls, for whatever reason. + * + * @method Phaser.GameObjects.Video#stalledHandler + * @fires Phaser.GameObjects.Events#VIDEO_STALLED + * @since 3.60.0 + * + * @param {Event} event - The error Event. + */ + stalledHandler: function (event) + { + this.isStalled = true; + + this.emit(Events.VIDEO_STALLED, this, event); + }, + + /** + * Called when the video completes playback, i.e. reaches an `ended` state. + * + * This will never happen if the video is coming from a live stream, where the duration is `Infinity`. + * + * @method Phaser.GameObjects.Video#completeHandler + * @fires Phaser.GameObjects.Events#VIDEO_COMPLETE + * @since 3.20.0 + */ + completeHandler: function () + { + this._playCalled = false; + + this.emit(Events.VIDEO_COMPLETE, this); + }, + + /** + * The internal update step. + * + * @method Phaser.GameObjects.Video#preUpdate + * @private + * @since 3.20.0 + * + * @param {number} time - The current timestamp. + * @param {number} delta - The delta time in ms since the last frame. + */ + preUpdate: function (time, delta) + { + var video = this.video; + + if (!video || !this._playCalled) + { + return; + } + + if (this.touchLocked && this.playWhenUnlocked) + { + this.retry += delta; + + if (this.retry >= this.retryInterval) + { + this.createPlayPromise(false); + + this.retry = 0; + } + } + }, + + /** + * Seeks to a given point in the video. The value is given as a float between 0 and 1, + * where 0 represents the start of the video and 1 represents the end. + * + * Seeking only works if the video has a duration, so will not work for live streams. + * + * When seeking begins, this video will emit a `seeking` event. When the video completes + * seeking (i.e. reaches its designated timestamp) it will emit a `seeked` event. + * + * If you wish to seek based on time instead, use the `Video.setCurrentTime` method. + * + * Unfortunately, the DOM video element does not guarantee frame-accurate seeking. + * This has been an ongoing subject of discussion: https://github.com/w3c/media-and-entertainment/issues/4 + * + * @method Phaser.GameObjects.Video#seekTo + * @since 3.20.0 + * + * @param {number} value - The point in the video to seek to. A value between 0 and 1. + * + * @return {this} This Video Game Object for method chaining. + */ + seekTo: function (value) + { + var video = this.video; + + if (video) + { + var duration = video.duration; + + if (duration !== Infinity && !isNaN(duration)) + { + var seekTime = duration * value; + + this.setCurrentTime(seekTime); + } + } + + return this; + }, + + /** + * A double-precision floating-point value indicating the current playback time in seconds. + * + * If the media has not started to play and has not been seeked, this value is the media's initial playback time. + * + * For a more accurate value, use the `Video.metadata.mediaTime` property instead. + * + * @method Phaser.GameObjects.Video#getCurrentTime + * @since 3.20.0 + * + * @return {number} A double-precision floating-point value indicating the current playback time in seconds. + */ + getCurrentTime: function () + { + return (this.video) ? this.video.currentTime : 0; + }, + + /** + * Seeks to a given playback time in the video. The value is given in _seconds_ or as a string. + * + * Seeking only works if the video has a duration, so will not work for live streams. + * + * When seeking begins, this video will emit a `seeking` event. When the video completes + * seeking (i.e. reaches its designated timestamp) it will emit a `seeked` event. + * + * You can provide a string prefixed with either a `+` or a `-`, such as `+2.5` or `-2.5`. + * In this case it will seek to +/- the value given, relative to the _current time_. + * + * If you wish to seek based on a duration percentage instead, use the `Video.seekTo` method. + * + * @method Phaser.GameObjects.Video#setCurrentTime + * @since 3.20.0 + * + * @param {(string|number)} value - The playback time to seek to in seconds. Can be expressed as a string, such as `+2` to seek 2 seconds ahead from the current time. + * + * @return {this} This Video Game Object for method chaining. + */ + setCurrentTime: function (value) + { + var video = this.video; + + if (video) + { + if (typeof value === 'string') + { + var op = value[0]; + var num = parseFloat(value.substr(1)); + + if (op === '+') + { + value = video.currentTime + num; + } + else if (op === '-') + { + value = video.currentTime - num; + } + } + + video.currentTime = value; + } + + return this; + }, + + /** + * Internal seeking handler. + * + * @method Phaser.GameObjects.Video#seekingHandler + * @fires Phaser.GameObjects.Events#VIDEO_SEEKING + * @private + * @since 3.20.0 + */ + seekingHandler: function () + { + this.isSeeking = true; + + this.emit(Events.VIDEO_SEEKING, this); + }, + + /** + * Internal seeked handler. + * + * @method Phaser.GameObjects.Video#seekedHandler + * @fires Phaser.GameObjects.Events#VIDEO_SEEKED + * @private + * @since 3.20.0 + */ + seekedHandler: function () + { + this.isSeeking = false; + + this.emit(Events.VIDEO_SEEKED, this); + }, + + /** + * Returns the current progress of the video as a float. + * + * Progress is defined as a value between 0 (the start) and 1 (the end). + * + * Progress can only be returned if the video has a duration. Some videos, + * such as those coming from a live stream, do not have a duration. In this + * case the method will return -1. + * + * @method Phaser.GameObjects.Video#getProgress + * @since 3.20.0 + * + * @return {number} The current progress of playback. If the video has no duration, will always return -1. + */ + getProgress: function () + { + var video = this.video; + + if (video) + { + var duration = video.duration; + + if (duration !== Infinity && !isNaN(duration)) + { + return video.currentTime / duration; + } + } + + return -1; + }, + + /** + * A double-precision floating-point value which indicates the duration (total length) of the media in seconds, + * on the media's timeline. If no media is present on the element, or the media is not valid, the returned value is NaN. + * + * If the media has no known end (such as for live streams of unknown duration, web radio, media incoming from WebRTC, + * and so forth), this value is +Infinity. + * + * If no video has been loaded, this method will return 0. + * + * @method Phaser.GameObjects.Video#getDuration + * @since 3.20.0 + * + * @return {number} A double-precision floating-point value indicating the duration of the media in seconds. + */ + getDuration: function () + { + return (this.video) ? this.video.duration : 0; + }, + + /** + * Sets the muted state of the currently playing video, if one is loaded. + * + * @method Phaser.GameObjects.Video#setMute + * @since 3.20.0 + * + * @param {boolean} [value=true] - The mute value. `true` if the video should be muted, otherwise `false`. + * + * @return {this} This Video Game Object for method chaining. + */ + setMute: function (value) + { + if (value === undefined) { value = true; } + + this._codeMuted = value; + + var video = this.video; + + if (video) + { + video.muted = (this._systemMuted) ? true : value; + } + + return this; + }, + + /** + * Returns a boolean indicating if this Video is currently muted. + * + * @method Phaser.GameObjects.Video#isMuted + * @since 3.20.0 + * + * @return {boolean} A boolean indicating if this Video is currently muted, or not. + */ + isMuted: function () + { + return this._codeMuted; + }, + + /** + * Internal global mute handler. Will mute the video, if playing, if the global sound system mutes. + * + * @method Phaser.GameObjects.Video#globalMute + * @private + * @since 3.20.0 + * + * @param {(Phaser.Sound.WebAudioSoundManager|Phaser.Sound.HTML5AudioSoundManager)} soundManager - A reference to the Sound Manager that emitted the event. + * @param {boolean} mute - The mute value. `true` if the Sound Manager is now muted, otherwise `false`. + */ + globalMute: function (soundManager, value) + { + this._systemMuted = value; + + var video = this.video; + + if (video) + { + video.muted = (this._codeMuted) ? true : value; + } + }, + + /** + * Internal global pause handler. Will pause the video if the Game itself pauses. + * + * @method Phaser.GameObjects.Video#globalPause + * @private + * @since 3.20.0 + */ + globalPause: function () + { + this._systemPaused = true; + + if (this.video && !this.video.ended) + { + this.removeEventHandlers(); + + this.video.pause(); + } + }, + + /** + * Internal global resume handler. Will resume a paused video if the Game itself resumes. + * + * @method Phaser.GameObjects.Video#globalResume + * @private + * @since 3.20.0 + */ + globalResume: function () + { + this._systemPaused = false; + + if (this.video && !this._codePaused && !this.video.ended) + { + this.createPlayPromise(); + } + }, + + /** + * Sets the paused state of the currently loaded video. + * + * If the video is playing, calling this method with `true` will pause playback. + * If the video is paused, calling this method with `false` will resume playback. + * + * If no video is loaded, this method does nothing. + * + * If the video has not yet been played, `Video.play` will be called with no parameters. + * + * If the video has ended, this method will do nothing. + * + * @method Phaser.GameObjects.Video#setPaused + * @since 3.20.0 + * + * @param {boolean} [value=true] - The paused value. `true` if the video should be paused, `false` to resume it. + * + * @return {this} This Video Game Object for method chaining. + */ + setPaused: function (value) + { + if (value === undefined) { value = true; } + + var video = this.video; + + this._codePaused = value; + + if (video && !video.ended) + { + if (value) + { + if (!video.paused) + { + this.removeEventHandlers(); + + video.pause(); + } + } + else if (!value) + { + if (!this._playCalled) + { + this.play(); + } + else if (video.paused && !this._systemPaused) + { + this.createPlayPromise(); + } + } + } + + return this; + }, + + /** + * Pauses the current Video, if one is playing. + * + * If no video is loaded, this method does nothing. + * + * Call `Video.resume` to resume playback. + * + * @method Phaser.GameObjects.Video#pause + * @since 3.60.0 + * + * @return {this} This Video Game Object for method chaining. + */ + pause: function () + { + return this.setPaused(true); + }, + + /** + * Resumes the current Video, if one was previously playing and has been paused. + * + * If no video is loaded, this method does nothing. + * + * Call `Video.pause` to pause playback. + * + * @method Phaser.GameObjects.Video#resume + * @since 3.60.0 + * + * @return {this} This Video Game Object for method chaining. + */ + resume: function () + { + return this.setPaused(false); + }, + + /** + * Returns a double indicating the audio volume, from 0.0 (silent) to 1.0 (loudest). + * + * @method Phaser.GameObjects.Video#getVolume + * @since 3.20.0 + * + * @return {number} A double indicating the audio volume, from 0.0 (silent) to 1.0 (loudest). + */ + getVolume: function () + { + return (this.video) ? this.video.volume : 1; + }, + + /** + * Sets the volume of the currently playing video. + * + * The value given is a double indicating the audio volume, from 0.0 (silent) to 1.0 (loudest). + * + * @method Phaser.GameObjects.Video#setVolume + * @since 3.20.0 + * + * @param {number} [value=1] - A double indicating the audio volume, from 0.0 (silent) to 1.0 (loudest). + * + * @return {this} This Video Game Object for method chaining. + */ + setVolume: function (value) + { + if (value === undefined) { value = 1; } + + if (this.video) + { + this.video.volume = Clamp(value, 0, 1); + } + + return this; + }, + + /** + * Returns a double that indicates the rate at which the media is being played back. + * + * @method Phaser.GameObjects.Video#getPlaybackRate + * @since 3.20.0 + * + * @return {number} A double that indicates the rate at which the media is being played back. + */ + getPlaybackRate: function () + { + return (this.video) ? this.video.playbackRate : 1; + }, + + /** + * Sets the playback rate of the current video. + * + * The value given is a double that indicates the rate at which the media is being played back. + * + * @method Phaser.GameObjects.Video#setPlaybackRate + * @since 3.20.0 + * + * @param {number} [rate] - A double that indicates the rate at which the media is being played back. + * + * @return {this} This Video Game Object for method chaining. + */ + setPlaybackRate: function (rate) + { + if (this.video) + { + this.video.playbackRate = rate; + } + + return this; + }, + + /** + * Returns a boolean which indicates whether the media element should start over when it reaches the end. + * + * @method Phaser.GameObjects.Video#getLoop + * @since 3.20.0 + * + * @return {boolean} A boolean which indicates whether the media element will start over when it reaches the end. + */ + getLoop: function () + { + return (this.video) ? this.video.loop : false; + }, + + /** + * Sets the loop state of the current video. + * + * The value given is a boolean which indicates whether the media element will start over when it reaches the end. + * + * Not all videos can loop, for example live streams. + * + * Please note that not all browsers support _seamless_ video looping for all encoding formats. + * + * @method Phaser.GameObjects.Video#setLoop + * @since 3.20.0 + * + * @param {boolean} [value=true] - A boolean which indicates whether the media element will start over when it reaches the end. + * + * @return {this} This Video Game Object for method chaining. + */ + setLoop: function (value) + { + if (value === undefined) { value = true; } + + if (this.video) + { + this.video.loop = value; + } + + return this; + }, + + /** + * Returns a boolean which indicates whether the video is currently playing. + * + * @method Phaser.GameObjects.Video#isPlaying + * @since 3.20.0 + * + * @return {boolean} A boolean which indicates whether the video is playing, or not. + */ + isPlaying: function () + { + return (this.video) ? !(this.video.paused || this.video.ended) : false; + }, + + /** + * Returns a boolean which indicates whether the video is currently paused. + * + * @method Phaser.GameObjects.Video#isPaused + * @since 3.20.0 + * + * @return {boolean} A boolean which indicates whether the video is paused, or not. + */ + isPaused: function () + { + return ((this.video && this._playCalled && this.video.paused) || this._codePaused || this._systemPaused); + }, + + /** + * Stores this Video in the Texture Manager using the given key as a dynamic texture, + * which any texture-based Game Object, such as a Sprite, can use as its source: + * + * ```javascript + * const vid = this.add.video(0, 0, 'intro'); + * + * vid.play(); + * + * vid.saveTexture('doodle'); + * + * this.add.image(400, 300, 'doodle'); + * ``` + * + * If the video is not yet playing then you need to listen for the `TEXTURE_READY` event before + * you can use this texture on a Game Object: + * + * ```javascript + * const vid = this.add.video(0, 0, 'intro'); + * + * vid.play(); + * + * vid.once('textureready', (video, texture, key) => { + * + * this.add.image(400, 300, key); + * + * }); + * + * vid.saveTexture('doodle'); + * ``` + * + * The saved texture is automatically updated as the video plays. If you pause this video, + * or change its source, then the saved texture updates instantly. + * + * Calling `saveTexture` again will not save another copy of the same texture, it will just rename the existing one. + * + * By default it will create a single base texture. You can add frames to the texture + * by using the `Texture.add` method. After doing this, you can then allow Game Objects + * to use a specific frame. + * + * If you intend to save the texture so you can use it as the input for a Shader, you may need to toggle the + * `flipY` parameter if you find the video renders upside down in your shader. + * + * @method Phaser.GameObjects.Video#saveTexture + * @since 3.20.0 + * + * @param {string} key - The unique key to store the texture as within the global Texture Manager. + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y` during upload? + * + * @return {boolean} Returns `true` if the texture is available immediately, otherwise returns `false` and you should listen for the `TEXTURE_READY` event. + */ + saveTexture: function (key, flipY) + { + if (flipY === undefined) { flipY = true; } + + if (this.videoTexture) + { + this.scene.sys.textures.renameTexture(this._key, key); + this.videoTextureSource.setFlipY(flipY); + } + + this._key = key; + this.glFlipY = flipY; + + return (this.videoTexture) ? true : false; + }, + + /** + * Stops the video playing and clears all internal event listeners. + * + * If you only wish to pause playback of the video, and resume it a later time, use the `Video.pause` method instead. + * + * If the video hasn't finished downloading, calling this method will not abort the download. To do that you need to + * call `destroy` instead. + * + * @method Phaser.GameObjects.Video#stop + * @fires Phaser.GameObjects.Events#VIDEO_STOP + * @since 3.20.0 + * + * @param {boolean} [emitStopEvent=true] - Should the `VIDEO_STOP` event be emitted? + * + * @return {this} This Video Game Object for method chaining. + */ + stop: function (emitStopEvent) + { + if (emitStopEvent === undefined) { emitStopEvent = true; } + + var video = this.video; + + if (video) + { + this.removeEventHandlers(); + + video.cancelVideoFrameCallback(this._rfvCallbackId); + + video.pause(); + } + + this.retry = 0; + this._playCalled = false; + + if (emitStopEvent) + { + this.emit(Events.VIDEO_STOP, this); + } + + return this; + }, + + /** + * Removes the Video element from the DOM by calling parentNode.removeChild on itself. + * + * Also removes the autoplay and src attributes and nulls the `Video.video` reference. + * + * If you loaded an external video via `Video.loadURL` then you should call this function + * to clear up once you are done with the instance, but don't want to destroy this + * Video Game Object. + * + * This method is called automatically by `Video.destroy`. + * + * @method Phaser.GameObjects.Video#removeVideoElement + * @since 3.20.0 + */ + removeVideoElement: function () + { + var video = this.video; + + if (!video) + { + return; + } + + if (video.parentNode) + { + video.parentNode.removeChild(video); + } + + while (video.hasChildNodes()) + { + video.removeChild(video.firstChild); + } + + video.removeAttribute('autoplay'); + video.removeAttribute('src'); + + this.video = null; + }, + + /** + * Handles the pre-destroy step for the Video object. + * + * This calls `Video.stop` and optionally `Video.removeVideoElement`. + * + * If any Sprites are using this Video as their texture it is up to you to manage those. + * + * @method Phaser.GameObjects.Video#preDestroy + * @private + * @since 3.21.0 + */ + preDestroy: function () + { + this.stop(false); + + this.removeLoadEventHandlers(); + + this.removeVideoElement(); + + var game = this.scene.sys.game.events; + + game.off(GameEvents.PAUSE, this.globalPause, this); + game.off(GameEvents.RESUME, this.globalResume, this); + + var sound = this.scene.sys.sound; + + if (sound) + { + sound.off(SoundEvents.GLOBAL_MUTE, this.globalMute, this); + } + } + +}); + +module.exports = Video; + + +/***/ }), + +/***/ 58352: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Video#renderCanvas + * @since 3.20.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Video} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var VideoCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + if (src.videoTexture) + { + camera.addToRenderList(src); + + renderer.batchSprite(src, src.frame, camera, parentMatrix); + } +}; + +module.exports = VideoCanvasRenderer; + + +/***/ }), + +/***/ 11511: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildGameObject = __webpack_require__(25305); +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Video = __webpack_require__(18471); + +/** + * Creates a new Video Game Object and returns it. + * + * Note: This method will only be available if the Video Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#video + * @since 3.20.0 + * + * @param {Phaser.Types.GameObjects.Video.VideoConfig} config - The configuration object this Game Object will use to create itself. + * @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object. + * + * @return {Phaser.GameObjects.Video} The Game Object that was created. + */ +GameObjectCreator.register('video', function (config, addToScene) +{ + if (config === undefined) { config = {}; } + + var key = GetAdvancedValue(config, 'key', null); + + var video = new Video(this.scene, 0, 0, key); + + if (addToScene !== undefined) + { + config.add = addToScene; + } + + BuildGameObject(this.scene, video, config); + + return video; +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 89025: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Video = __webpack_require__(18471); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Video Game Object and adds it to the Scene. + * + * This Game Object is capable of handling playback of a video file, video stream or media stream. + * + * You can optionally 'preload' the video into the Phaser Video Cache: + * + * ```javascript + * preload () { + * this.load.video('ripley', 'assets/aliens.mp4'); + * } + * + * create () { + * this.add.video(400, 300, 'ripley'); + * } + * ``` + * + * You don't have to 'preload' the video. You can also play it directly from a URL: + * + * ```javascript + * create () { + * this.add.video(400, 300).loadURL('assets/aliens.mp4'); + * } + * ``` + * + * To all intents and purposes, a video is a standard Game Object, just like a Sprite. And as such, you can do + * all the usual things to it, such as scaling, rotating, cropping, tinting, making interactive, giving a + * physics body, etc. + * + * Transparent videos are also possible via the WebM file format. Providing the video file has was encoded with + * an alpha channel, and providing the browser supports WebM playback (not all of them do), then it will render + * in-game with full transparency. + * + * ### Autoplaying Videos + * + * Videos can only autoplay if the browser has been unlocked with an interaction, or satisfies the MEI settings. + * The policies that control autoplaying are vast and vary between browser. You can, and should, read more about + * it here: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide + * + * If your video doesn't contain any audio, then set the `noAudio` parameter to `true` when the video is _loaded_, + * and it will often allow the video to play immediately: + * + * ```javascript + * preload () { + * this.load.video('pixar', 'nemo.mp4', true); + * } + * ``` + * + * The 3rd parameter in the load call tells Phaser that the video doesn't contain any audio tracks. Video without + * audio can autoplay without requiring a user interaction. Video with audio cannot do this unless it satisfies + * the browsers MEI settings. See the MDN Autoplay Guide for further details. + * + * Or: + * + * ```javascript + * create () { + * this.add.video(400, 300).loadURL('assets/aliens.mp4', true); + * } + * ``` + * + * You can set the `noAudio` parameter to `true` even if the video does contain audio. It will still allow the video + * to play immediately, but the audio will not start. + * + * Note that due to a bug in IE11 you cannot play a video texture to a Sprite in WebGL. For IE11 force Canvas mode. + * + * More details about video playback and the supported media formats can be found on MDN: + * + * https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement + * https://developer.mozilla.org/en-US/docs/Web/Media/Formats + * + * Note: This method will only be available if the Video Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#video + * @since 3.20.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {string} [key] - Optional key of the Video this Game Object will play, as stored in the Video Cache. + * + * @return {Phaser.GameObjects.Video} The Game Object that was created. + */ +GameObjectFactory.register('video', function (x, y, key) +{ + return this.displayList.add(new Video(this.scene, x, y, key)); +}); + + +/***/ }), + +/***/ 10247: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(29849); +} + +if (true) +{ + renderCanvas = __webpack_require__(58352); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 29849: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.GameObjects.Video#renderWebGL + * @since 3.20.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Video} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var VideoWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + if (!src.videoTexture) + { + return; + } + + drawingContext.camera.addToRenderList(src); + + var customRenderNodes = src.customRenderNodes; + var defaultRenderNodes = src.defaultRenderNodes; + + (customRenderNodes.Submitter || defaultRenderNodes.Submitter).run( + drawingContext, + src, + parentMatrix, + 0, + customRenderNodes.Texturer || defaultRenderNodes.Texturer, + customRenderNodes.Transformer || defaultRenderNodes.Transformer + ); +}; + +module.exports = VideoWebGLRenderer; + + +/***/ }), + +/***/ 41481: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlendModes = __webpack_require__(10312); +var Circle = __webpack_require__(96503); +var CircleContains = __webpack_require__(87902); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var Rectangle = __webpack_require__(87841); +var RectangleContains = __webpack_require__(37303); + +/** + * @classdesc + * A Zone Game Object. + * + * A Zone is a non-rendering rectangular Game Object that has a position and size. + * It has no texture and never displays, but does live on the display list and + * can be moved, scaled and rotated like any other Game Object. + * + * Its primary use is for creating Drop Zones and Input Hit Areas and it has a couple of helper methods + * specifically for this. It is also useful for object overlap checks, or as a base for your own + * non-displaying Game Objects. + + * The default origin is 0.5, the center of the Zone, the same as with Game Objects. + * + * @class Zone + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.GameObjects + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {number} [width=1] - The width of the Game Object. + * @param {number} [height=1] - The height of the Game Object. + */ +var Zone = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Depth, + Components.GetBounds, + Components.Origin, + Components.Transform, + Components.ScrollFactor, + Components.Visible + ], + + initialize: + + function Zone (scene, x, y, width, height) + { + if (width === undefined) { width = 1; } + if (height === undefined) { height = width; } + + GameObject.call(this, scene, 'Zone'); + + this.setPosition(x, y); + + /** + * The native (un-scaled) width of this Game Object. + * + * @name Phaser.GameObjects.Zone#width + * @type {number} + * @since 3.0.0 + */ + this.width = width; + + /** + * The native (un-scaled) height of this Game Object. + * + * @name Phaser.GameObjects.Zone#height + * @type {number} + * @since 3.0.0 + */ + this.height = height; + + /** + * The Blend Mode of the Game Object. + * Although a Zone never renders, it still has a blend mode to allow it to fit seamlessly into + * display lists without causing a batch flush. + * + * @name Phaser.GameObjects.Zone#blendMode + * @type {number} + * @since 3.0.0 + */ + this.blendMode = BlendModes.NORMAL; + + this.updateDisplayOrigin(); + }, + + /** + * The displayed width of this Game Object. + * This value takes into account the scale factor. + * + * @name Phaser.GameObjects.Zone#displayWidth + * @type {number} + * @since 3.0.0 + */ + displayWidth: { + + get: function () + { + return this.scaleX * this.width; + }, + + set: function (value) + { + this.scaleX = value / this.width; + } + + }, + + /** + * The displayed height of this Game Object. + * This value takes into account the scale factor. + * + * @name Phaser.GameObjects.Zone#displayHeight + * @type {number} + * @since 3.0.0 + */ + displayHeight: { + + get: function () + { + return this.scaleY * this.height; + }, + + set: function (value) + { + this.scaleY = value / this.height; + } + + }, + + /** + * Sets the size of this Game Object. + * + * @method Phaser.GameObjects.Zone#setSize + * @since 3.0.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * @param {boolean} [resizeInput=true] - If this Zone has a Rectangle for a hit area this argument will resize the hit area as well. + * + * @return {this} This Game Object. + */ + setSize: function (width, height, resizeInput) + { + if (resizeInput === undefined) { resizeInput = true; } + + this.width = width; + this.height = height; + + this.updateDisplayOrigin(); + + var input = this.input; + + if (resizeInput && input && !input.customHitArea) + { + input.hitArea.width = width; + input.hitArea.height = height; + } + + return this; + }, + + /** + * Sets the display size of this Game Object. + * Calling this will adjust the scale. + * + * @method Phaser.GameObjects.Zone#setDisplaySize + * @since 3.0.0 + * + * @param {number} width - The width of this Game Object. + * @param {number} height - The height of this Game Object. + * + * @return {this} This Game Object. + */ + setDisplaySize: function (width, height) + { + this.displayWidth = width; + this.displayHeight = height; + + return this; + }, + + /** + * Sets this Zone to be a Circular Drop Zone. + * The circle is centered on this Zones `x` and `y` coordinates. + * + * @method Phaser.GameObjects.Zone#setCircleDropZone + * @since 3.0.0 + * + * @param {number} radius - The radius of the Circle that will form the Drop Zone. + * + * @return {this} This Game Object. + */ + setCircleDropZone: function (radius) + { + return this.setDropZone(new Circle(0, 0, radius), CircleContains); + }, + + /** + * Sets this Zone to be a Rectangle Drop Zone. + * The rectangle is centered on this Zones `x` and `y` coordinates. + * + * @method Phaser.GameObjects.Zone#setRectangleDropZone + * @since 3.0.0 + * + * @param {number} width - The width of the rectangle drop zone. + * @param {number} height - The height of the rectangle drop zone. + * + * @return {this} This Game Object. + */ + setRectangleDropZone: function (width, height) + { + return this.setDropZone(new Rectangle(0, 0, width, height), RectangleContains); + }, + + /** + * Allows you to define your own Geometry shape to be used as a Drop Zone. + * + * @method Phaser.GameObjects.Zone#setDropZone + * @since 3.0.0 + * + * @param {object} [hitArea] - A Geometry shape instance, such as Phaser.Geom.Ellipse, or your own custom shape. If not given it will try to create a Rectangle based on the size of this zone. + * @param {Phaser.Types.Input.HitAreaCallback} [hitAreaCallback] - A function that will return `true` if the given x/y coords it is sent are within the shape. If you provide a shape you must also provide a callback. + * + * @return {this} This Game Object. + */ + setDropZone: function (hitArea, hitAreaCallback) + { + if (!this.input) + { + this.setInteractive(hitArea, hitAreaCallback, true); + } + + return this; + }, + + /** + * A NOOP method so you can pass a Zone to a Container. + * Calling this method will do nothing. It is intentionally empty. + * + * @method Phaser.GameObjects.Zone#setAlpha + * @private + * @since 3.11.0 + */ + setAlpha: function () + { + }, + + /** + * A NOOP method so you can pass a Zone to a Container in Canvas. + * Calling this method will do nothing. It is intentionally empty. + * + * @method Phaser.GameObjects.Zone#setBlendMode + * @private + * @since 3.16.2 + */ + setBlendMode: function () + { + }, + + /** + * A Zone does not render. + * + * @method Phaser.GameObjects.Zone#renderCanvas + * @private + * @since 3.53.0 + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ + renderCanvas: function (renderer, src, camera) + { + camera.addToRenderList(src); + }, + + /** + * A Zone does not render. + * + * @method Phaser.GameObjects.Zone#renderWebGL + * @private + * @since 3.53.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + renderWebGL: function (renderer, src, drawingContext) + { + drawingContext.camera.addToRenderList(src); + } + +}); + +module.exports = Zone; + + +/***/ }), + +/***/ 95261: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectCreator = __webpack_require__(44603); +var GetAdvancedValue = __webpack_require__(23568); +var Zone = __webpack_require__(41481); + +/** + * Creates a new Zone Game Object and returns it. + * + * Note: This method will only be available if the Zone Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#zone + * @since 3.0.0 + * + * @param {Phaser.Types.GameObjects.Zone.ZoneConfig} config - The configuration object this Game Object will use to create itself. + * + * @return {Phaser.GameObjects.Zone} The Game Object that was created. + */ +GameObjectCreator.register('zone', function (config) +{ + var x = GetAdvancedValue(config, 'x', 0); + var y = GetAdvancedValue(config, 'y', 0); + var width = GetAdvancedValue(config, 'width', 1); + var height = GetAdvancedValue(config, 'height', width); + + return new Zone(this.scene, x, y, width, height); +}); + +// When registering a factory function 'this' refers to the GameObjectCreator context. + + +/***/ }), + +/***/ 84175: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Zone = __webpack_require__(41481); +var GameObjectFactory = __webpack_require__(39429); + +/** + * Creates a new Zone Game Object and adds it to the Scene. + * + * Note: This method will only be available if the Zone Game Object has been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#zone + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {number} width - The width of the Game Object. + * @param {number} height - The height of the Game Object. + * + * @return {Phaser.GameObjects.Zone} The Game Object that was created. + */ +GameObjectFactory.register('zone', function (x, y, width, height) +{ + return this.displayList.add(new Zone(this.scene, x, y, width, height)); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 95166: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the area of the circle. + * + * @function Phaser.Geom.Circle.Area + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The Circle to get the area of. + * + * @return {number} The area of the Circle. + */ +var Area = function (circle) +{ + return (circle.radius > 0) ? Math.PI * circle.radius * circle.radius : 0; +}; + +module.exports = Area; + + +/***/ }), + +/***/ 96503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Contains = __webpack_require__(87902); +var GetPoint = __webpack_require__(26241); +var GetPoints = __webpack_require__(79124); +var GEOM_CONST = __webpack_require__(23777); +var Random = __webpack_require__(28176); + +/** + * @classdesc + * A Circle object. + * + * This is a geometry object, containing numerical values and related methods to inspect and modify them. + * It is not a Game Object, in that you cannot add it to the display list, and it has no texture. + * To render a Circle you should look at the capabilities of the Graphics class. + * + * @class Circle + * @memberof Phaser.Geom + * @constructor + * @since 3.0.0 + * + * @param {number} [x=0] - The x position of the center of the circle. + * @param {number} [y=0] - The y position of the center of the circle. + * @param {number} [radius=0] - The radius of the circle. + */ +var Circle = new Class({ + + initialize: + + function Circle (x, y, radius) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (radius === undefined) { radius = 0; } + + /** + * The geometry constant type of this object: `GEOM_CONST.CIRCLE`. + * Used for fast type comparisons. + * + * @name Phaser.Geom.Circle#type + * @type {number} + * @readonly + * @since 3.19.0 + */ + this.type = GEOM_CONST.CIRCLE; + + /** + * The x position of the center of the circle. + * + * @name Phaser.Geom.Circle#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = x; + + /** + * The y position of the center of the circle. + * + * @name Phaser.Geom.Circle#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = y; + + /** + * The internal radius of the circle. + * + * @name Phaser.Geom.Circle#_radius + * @type {number} + * @private + * @since 3.0.0 + */ + this._radius = radius; + + /** + * The internal diameter of the circle. + * + * @name Phaser.Geom.Circle#_diameter + * @type {number} + * @private + * @since 3.0.0 + */ + this._diameter = radius * 2; + }, + + /** + * Check to see if the Circle contains the given x / y coordinates. + * + * @method Phaser.Geom.Circle#contains + * @since 3.0.0 + * + * @param {number} x - The x coordinate to check within the circle. + * @param {number} y - The y coordinate to check within the circle. + * + * @return {boolean} True if the coordinates are within the circle, otherwise false. + */ + contains: function (x, y) + { + return Contains(this, x, y); + }, + + /** + * Returns a Point object containing the coordinates of a point on the circumference of the Circle + * based on the given angle normalized to the range 0 to 1. I.e. a value of 0.5 will give the point + * at 180 degrees around the circle. + * + * @method Phaser.Geom.Circle#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} position - A value between 0 and 1, where 0 equals 0 degrees, 0.5 equals 180 degrees and 1 equals 360 around the circle. + * @param {Phaser.Math.Vector2} [out] - A Vector2 to store the return values in. If not given a Vector2 object will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 containing the coordinates of the point around the circle. + */ + getPoint: function (position, out) + { + return GetPoint(this, position, out); + }, + + /** + * Returns an array of Point objects containing the coordinates of the points around the circumference of the Circle, + * based on the given quantity or stepRate values. + * + * @method Phaser.Geom.Circle#getPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [output,$return] + * + * @param {number} quantity - The amount of points to return. If a falsey value the quantity will be derived from the `stepRate` instead. + * @param {number} [stepRate] - Sets the quantity by getting the circumference of the circle and dividing it by the stepRate. + * @param {Phaser.Math.Vector2[]} [output] - An array to insert the Vector2s in to. If not provided a new array will be created. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects pertaining to the points around the circumference of the circle. + */ + getPoints: function (quantity, stepRate, output) + { + return GetPoints(this, quantity, stepRate, output); + }, + + /** + * Returns a uniformly distributed random point from anywhere within the Circle. + * + * @method Phaser.Geom.Circle#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [point,$return] + * + * @param {Phaser.Math.Vector2} [vec] - A Vector2 object to set the random `x` and `y` values in. + * + * @return {Phaser.Math.Vector2} A Vector2 object with the random values set in the `x` and `y` properties. + */ + getRandomPoint: function (vec) + { + return Random(this, vec); + }, + + /** + * Sets the x, y and radius of this circle. + * + * @method Phaser.Geom.Circle#setTo + * @since 3.0.0 + * + * @param {number} [x=0] - The x position of the center of the circle. + * @param {number} [y=0] - The y position of the center of the circle. + * @param {number} [radius=0] - The radius of the circle. + * + * @return {this} This Circle object. + */ + setTo: function (x, y, radius) + { + this.x = x; + this.y = y; + this._radius = radius; + this._diameter = radius * 2; + + return this; + }, + + /** + * Sets this Circle to be empty with a radius of zero. + * Does not change its position. + * + * @method Phaser.Geom.Circle#setEmpty + * @since 3.0.0 + * + * @return {this} This Circle object. + */ + setEmpty: function () + { + this._radius = 0; + this._diameter = 0; + + return this; + }, + + /** + * Sets the position of this Circle. + * + * @method Phaser.Geom.Circle#setPosition + * @since 3.0.0 + * + * @param {number} [x=0] - The x position of the center of the circle. + * @param {number} [y=0] - The y position of the center of the circle. + * + * @return {this} This Circle object. + */ + setPosition: function (x, y) + { + if (y === undefined) { y = x; } + + this.x = x; + this.y = y; + + return this; + }, + + /** + * Checks to see if the Circle is empty: has a radius of zero. + * + * @method Phaser.Geom.Circle#isEmpty + * @since 3.0.0 + * + * @return {boolean} True if the Circle is empty, otherwise false. + */ + isEmpty: function () + { + return (this._radius <= 0); + }, + + /** + * The radius of the Circle. + * + * @name Phaser.Geom.Circle#radius + * @type {number} + * @since 3.0.0 + */ + radius: { + + get: function () + { + return this._radius; + }, + + set: function (value) + { + this._radius = value; + this._diameter = value * 2; + } + + }, + + /** + * The diameter of the Circle. + * + * @name Phaser.Geom.Circle#diameter + * @type {number} + * @since 3.0.0 + */ + diameter: { + + get: function () + { + return this._diameter; + }, + + set: function (value) + { + this._diameter = value; + this._radius = value * 0.5; + } + + }, + + /** + * The left position of the Circle. + * + * @name Phaser.Geom.Circle#left + * @type {number} + * @since 3.0.0 + */ + left: { + + get: function () + { + return this.x - this._radius; + }, + + set: function (value) + { + this.x = value + this._radius; + } + + }, + + /** + * The right position of the Circle. + * + * @name Phaser.Geom.Circle#right + * @type {number} + * @since 3.0.0 + */ + right: { + + get: function () + { + return this.x + this._radius; + }, + + set: function (value) + { + this.x = value - this._radius; + } + + }, + + /** + * The top position of the Circle. + * + * @name Phaser.Geom.Circle#top + * @type {number} + * @since 3.0.0 + */ + top: { + + get: function () + { + return this.y - this._radius; + }, + + set: function (value) + { + this.y = value + this._radius; + } + + }, + + /** + * The bottom position of the Circle. + * + * @name Phaser.Geom.Circle#bottom + * @type {number} + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return this.y + this._radius; + }, + + set: function (value) + { + this.y = value - this._radius; + } + + } + +}); + +module.exports = Circle; + + +/***/ }), + +/***/ 71562: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the circumference of the given Circle. + * + * @function Phaser.Geom.Circle.Circumference + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The Circle to get the circumference of. + * + * @return {number} The circumference of the Circle. + */ +var Circumference = function (circle) +{ + return 2 * (Math.PI * circle.radius); +}; + +module.exports = Circumference; + + +/***/ }), + +/***/ 92110: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a Vector2 object containing the coordinates of a point on the circumference of the Circle based on the given angle. + * + * @function Phaser.Geom.Circle.CircumferencePoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Circle} circle - The Circle to get the circumference point on. + * @param {number} angle - The angle from the center of the Circle to the circumference to return the point from. Given in radians. + * @param {Phaser.Math.Vector2} [out] - A Vector2 to store the results in. If not given a Point will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 object where the `x` and `y` properties are the point on the circumference. + */ +var CircumferencePoint = function (circle, angle, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = circle.x + (circle.radius * Math.cos(angle)); + out.y = circle.y + (circle.radius * Math.sin(angle)); + + return out; +}; + +module.exports = CircumferencePoint; + + +/***/ }), + +/***/ 42250: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circle = __webpack_require__(96503); + +/** + * Creates a new Circle instance based on the values contained in the given source. + * + * @function Phaser.Geom.Circle.Clone + * @since 3.0.0 + * + * @param {(Phaser.Geom.Circle|object)} source - The Circle to be cloned. Can be an instance of a Circle or a circle-like object, with x, y and radius properties. + * + * @return {Phaser.Geom.Circle} A clone of the source Circle. + */ +var Clone = function (source) +{ + return new Circle(source.x, source.y, source.radius); +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 87902: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check to see if the Circle contains the given x / y coordinates. + * + * @function Phaser.Geom.Circle.Contains + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The Circle to check. + * @param {number} x - The x coordinate to check within the circle. + * @param {number} y - The y coordinate to check within the circle. + * + * @return {boolean} True if the coordinates are within the circle, otherwise false. + */ +var Contains = function (circle, x, y) +{ + // Check if x/y are within the bounds first + if (circle.radius > 0 && x >= circle.left && x <= circle.right && y >= circle.top && y <= circle.bottom) + { + var dx = (circle.x - x) * (circle.x - x); + var dy = (circle.y - y) * (circle.y - y); + + return (dx + dy) <= (circle.radius * circle.radius); + } + else + { + return false; + } +}; + +module.exports = Contains; + + +/***/ }), + +/***/ 5698: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(87902); + +/** + * Check to see if the Circle contains the given x and y coordinates as stored in the Vector2. + * + * @function Phaser.Geom.Circle.ContainsPoint + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The Circle to check. + * @param {Phaser.Math.Vector2} vec - The Vector2 object to check if its coordinates are within the Circle or not. + * + * @return {boolean} True if the Vector2 coordinates are within the circle, otherwise false. + */ +var ContainsPoint = function (circle, vec) +{ + return Contains(circle, vec.x, vec.y); +}; + +module.exports = ContainsPoint; + + +/***/ }), + +/***/ 70588: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(87902); + +/** + * Check to see if the Circle contains all four points of the given Rectangle object. + * + * @function Phaser.Geom.Circle.ContainsRect + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The Circle to check. + * @param {(Phaser.Geom.Rectangle|object)} rect - The Rectangle object to check if it's within the Circle or not. + * + * @return {boolean} True if all of the Rectangle coordinates are within the circle, otherwise false. + */ +var ContainsRect = function (circle, rect) +{ + return ( + Contains(circle, rect.x, rect.y) && + Contains(circle, rect.right, rect.y) && + Contains(circle, rect.x, rect.bottom) && + Contains(circle, rect.right, rect.bottom) + ); +}; + +module.exports = ContainsRect; + + +/***/ }), + +/***/ 26394: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Copies the `x`, `y` and `radius` properties from the `source` Circle + * into the given `dest` Circle, then returns the `dest` Circle. + * + * @function Phaser.Geom.Circle.CopyFrom + * @since 3.0.0 + * + * @generic {Phaser.Geom.Circle} O - [dest,$return] + * + * @param {Phaser.Geom.Circle} source - The source Circle to copy the values from. + * @param {Phaser.Geom.Circle} dest - The destination Circle to copy the values to. + * + * @return {Phaser.Geom.Circle} The destination Circle. + */ +var CopyFrom = function (source, dest) +{ + return dest.setTo(source.x, source.y, source.radius); +}; + +module.exports = CopyFrom; + + +/***/ }), + +/***/ 76278: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compares the `x`, `y` and `radius` properties of the two given Circles. + * Returns `true` if they all match, otherwise returns `false`. + * + * @function Phaser.Geom.Circle.Equals + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The first Circle to compare. + * @param {Phaser.Geom.Circle} toCompare - The second Circle to compare. + * + * @return {boolean} `true` if the two Circles equal each other, otherwise `false`. + */ +var Equals = function (circle, toCompare) +{ + return ( + circle.x === toCompare.x && + circle.y === toCompare.y && + circle.radius === toCompare.radius + ); +}; + +module.exports = Equals; + + +/***/ }), + +/***/ 2074: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Returns the bounds of the Circle object. + * + * @function Phaser.Geom.Circle.GetBounds + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {Phaser.Geom.Circle} circle - The Circle to get the bounds from. + * @param {(Phaser.Geom.Rectangle|object)} [out] - A Rectangle, or rectangle-like object, to store the circle bounds in. If not given a new Rectangle will be created. + * + * @return {(Phaser.Geom.Rectangle|object)} The Rectangle object containing the Circles bounds. + */ +var GetBounds = function (circle, out) +{ + if (out === undefined) { out = new Rectangle(); } + + out.x = circle.left; + out.y = circle.top; + out.width = circle.diameter; + out.height = circle.diameter; + + return out; +}; + +module.exports = GetBounds; + + +/***/ }), + +/***/ 26241: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CircumferencePoint = __webpack_require__(92110); +var FromPercent = __webpack_require__(62945); +var MATH_CONST = __webpack_require__(36383); +var Vector2 = __webpack_require__(26099); + +/** + * Returns a Vector2 object containing the coordinates of a point on the circumference of the Circle + * based on the given angle normalized to the range 0 to 1. I.e. a value of 0.5 will give the point + * at 180 degrees around the circle. + * + * @function Phaser.Geom.Circle.GetPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Circle} circle - The Circle to get the circumference point on. + * @param {number} position - A value between 0 and 1, where 0 equals 0 degrees, 0.5 equals 180 degrees and 1 equals 360 around the circle. + * @param {Phaser.Math.Vector2} [out] - A Vector2 instance to store the return values in. If not given a new Vector2 object will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 containing the coordinates of the point around the circle. + */ +var GetPoint = function (circle, position, out) +{ + if (out === undefined) { out = new Vector2(); } + + var angle = FromPercent(position, 0, MATH_CONST.TAU); + + return CircumferencePoint(circle, angle, out); +}; + +module.exports = GetPoint; + + +/***/ }), + +/***/ 79124: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circumference = __webpack_require__(71562); +var CircumferencePoint = __webpack_require__(92110); +var FromPercent = __webpack_require__(62945); +var MATH_CONST = __webpack_require__(36383); + +/** + * Returns an array of Vector2 objects containing the coordinates of the points around the circumference of the Circle, + * based on the given quantity or stepRate values. + * + * @function Phaser.Geom.Circle.GetPoints + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The Circle to get the points from. + * @param {number} quantity - The amount of points to return. If a falsey value the quantity will be derived from the `stepRate` instead. + * @param {number} [stepRate] - Sets the quantity by getting the circumference of the circle and dividing it by the stepRate. + * @param {array} [output] - An array to insert the points in to. If not provided a new array will be created. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects pertaining to the points around the circumference of the circle. + */ +var GetPoints = function (circle, quantity, stepRate, out) +{ + if (out === undefined) { out = []; } + + // If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!quantity && stepRate > 0) + { + quantity = Circumference(circle) / stepRate; + } + + for (var i = 0; i < quantity; i++) + { + var angle = FromPercent(i / quantity, 0, MATH_CONST.TAU); + + out.push(CircumferencePoint(circle, angle)); + } + + return out; +}; + +module.exports = GetPoints; + + +/***/ }), + +/***/ 50884: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Offsets the Circle by the values given. + * + * @function Phaser.Geom.Circle.Offset + * @since 3.0.0 + * + * @generic {Phaser.Geom.Circle} O - [circle,$return] + * + * @param {Phaser.Geom.Circle} circle - The Circle to be offset (translated.) + * @param {number} x - The amount to horizontally offset the Circle by. + * @param {number} y - The amount to vertically offset the Circle by. + * + * @return {Phaser.Geom.Circle} The Circle that was offset. + */ +var Offset = function (circle, x, y) +{ + circle.x += x; + circle.y += y; + + return circle; +}; + +module.exports = Offset; + + +/***/ }), + +/***/ 39212: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Offsets the Circle by the values given in the `x` and `y` properties of the Vector2 object. + * + * @function Phaser.Geom.Circle.OffsetPoint + * @since 3.0.0 + * + * @generic {Phaser.Geom.Circle} O - [circle,$return] + * + * @param {Phaser.Geom.Circle} circle - The Circle to be offset (translated.) + * @param {Phaser.Math.Vector2} vec - The Vector2 object containing the values to offset the Circle by. + * + * @return {Phaser.Geom.Circle} The Circle that was offset. + */ +var OffsetPoint = function (circle, vec) +{ + circle.x += vec.x; + circle.y += vec.y; + + return circle; +}; + +module.exports = OffsetPoint; + + +/***/ }), + +/***/ 28176: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a uniformly distributed random point from anywhere within the given Circle. + * + * @function Phaser.Geom.Circle.Random + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Circle} circle - The Circle to get a random point from. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to set the random `x` and `y` values in. + * + * @return {Phaser.Math.Vector2} A Vector2 object with the random values set in the `x` and `y` properties. + */ +var Random = function (circle, out) +{ + if (out === undefined) { out = new Vector2(); } + + var t = 2 * Math.PI * Math.random(); + var u = Math.random() + Math.random(); + var r = (u > 1) ? 2 - u : u; + var x = r * Math.cos(t); + var y = r * Math.sin(t); + + out.x = circle.x + (x * circle.radius); + out.y = circle.y + (y * circle.radius); + + return out; +}; + +module.exports = Random; + + +/***/ }), + +/***/ 88911: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circle = __webpack_require__(96503); + +Circle.Area = __webpack_require__(95166); +Circle.Circumference = __webpack_require__(71562); +Circle.CircumferencePoint = __webpack_require__(92110); +Circle.Clone = __webpack_require__(42250); +Circle.Contains = __webpack_require__(87902); +Circle.ContainsPoint = __webpack_require__(5698); +Circle.ContainsRect = __webpack_require__(70588); +Circle.CopyFrom = __webpack_require__(26394); +Circle.Equals = __webpack_require__(76278); +Circle.GetBounds = __webpack_require__(2074); +Circle.GetPoint = __webpack_require__(26241); +Circle.GetPoints = __webpack_require__(79124); +Circle.Offset = __webpack_require__(50884); +Circle.OffsetPoint = __webpack_require__(39212); +Circle.Random = __webpack_require__(28176); + +module.exports = Circle; + + +/***/ }), + +/***/ 23777: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GEOM_CONST = { + + /** + * A Circle Geometry object type. + * + * @name Phaser.Geom.CIRCLE + * @type {number} + * @since 3.19.0 + */ + CIRCLE: 0, + + /** + * An Ellipse Geometry object type. + * + * @name Phaser.Geom.ELLIPSE + * @type {number} + * @since 3.19.0 + */ + ELLIPSE: 1, + + /** + * A Line Geometry object type. + * + * @name Phaser.Geom.LINE + * @type {number} + * @since 3.19.0 + */ + LINE: 2, + + /** + * A Point Geometry object type. + * This object type was removed in 4.0.0. Use Vector2 instead. + * + * @name Phaser.Geom.POINT + * @type {number} + * @since 3.19.0 + */ + POINT: 3, + + /** + * A Polygon Geometry object type. + * + * @name Phaser.Geom.POLYGON + * @type {number} + * @since 3.19.0 + */ + POLYGON: 4, + + /** + * A Rectangle Geometry object type. + * + * @name Phaser.Geom.RECTANGLE + * @type {number} + * @since 3.19.0 + */ + RECTANGLE: 5, + + /** + * A Triangle Geometry object type. + * + * @name Phaser.Geom.TRIANGLE + * @type {number} + * @since 3.19.0 + */ + TRIANGLE: 6 + +}; + +module.exports = GEOM_CONST; + + +/***/ }), + +/***/ 78874: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the area of the Ellipse. + * + * @function Phaser.Geom.Ellipse.Area + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get the area of. + * + * @return {number} The area of the Ellipse. + */ +var Area = function (ellipse) +{ + if (ellipse.isEmpty()) + { + return 0; + } + + // units squared + return (ellipse.getMajorRadius() * ellipse.getMinorRadius() * Math.PI); +}; + +module.exports = Area; + + +/***/ }), + +/***/ 92990: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the circumference of the given Ellipse. + * + * @function Phaser.Geom.Ellipse.Circumference + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get the circumference of. + * + * @return {number} The circumference of th Ellipse. + */ +var Circumference = function (ellipse) +{ + var rx = ellipse.width / 2; + var ry = ellipse.height / 2; + var h = Math.pow((rx - ry), 2) / Math.pow((rx + ry), 2); + + return (Math.PI * (rx + ry)) * (1 + ((3 * h) / (10 + Math.sqrt(4 - (3 * h))))); +}; + +module.exports = Circumference; + + +/***/ }), + +/***/ 79522: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a Vector2 containing the coordinates of a point on the circumference of the Ellipse based on the given angle. + * + * @function Phaser.Geom.Ellipse.CircumferencePoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get the circumference point on. + * @param {number} angle - The angle from the center of the Ellipse to the circumference to return the point from. Given in radians. + * @param {Phaser.Math.Vector2} [out] - A Vector2 to store the results in. If not given a Point will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 object where the `x` and `y` properties are the point on the circumference. + */ +var CircumferencePoint = function (ellipse, angle, out) +{ + if (out === undefined) { out = new Vector2(); } + + var halfWidth = ellipse.width / 2; + var halfHeight = ellipse.height / 2; + + out.x = ellipse.x + halfWidth * Math.cos(angle); + out.y = ellipse.y + halfHeight * Math.sin(angle); + + return out; +}; + +module.exports = CircumferencePoint; + + +/***/ }), + +/***/ 58102: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Ellipse = __webpack_require__(8497); + +/** + * Creates a new Ellipse instance based on the values contained in the given source. + * + * @function Phaser.Geom.Ellipse.Clone + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} source - The Ellipse to be cloned. Can be an instance of an Ellipse or a ellipse-like object, with x, y, width and height properties. + * + * @return {Phaser.Geom.Ellipse} A clone of the source Ellipse. + */ +var Clone = function (source) +{ + return new Ellipse(source.x, source.y, source.width, source.height); +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 81154: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check to see if the Ellipse contains the given x / y coordinates. + * + * @function Phaser.Geom.Ellipse.Contains + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to check. + * @param {number} x - The x coordinate to check within the ellipse. + * @param {number} y - The y coordinate to check within the ellipse. + * + * @return {boolean} True if the coordinates are within the ellipse, otherwise false. + */ +var Contains = function (ellipse, x, y) +{ + if (ellipse.width <= 0 || ellipse.height <= 0) + { + return false; + } + + // Normalize the coords to an ellipse with center 0,0 and a radius of 0.5 + var normx = ((x - ellipse.x) / ellipse.width); + var normy = ((y - ellipse.y) / ellipse.height); + + normx *= normx; + normy *= normy; + + return (normx + normy < 0.25); +}; + +module.exports = Contains; + + +/***/ }), + +/***/ 46662: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(81154); + +/** + * Check to see if the Ellipse contains the given x and y coordinates as stored in the Vector2. + * + * @function Phaser.Geom.Ellipse.ContainsPoint + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to check. + * @param {Phaser.Math.Vector2} vec - The Vector2 object to check if its coordinates are within the Ellipse or not. + * + * @return {boolean} True if the Vector2 coordinates are within the ellipse, otherwise false. + */ +var ContainsPoint = function (ellipse, vec) +{ + return Contains(ellipse, vec.x, vec.y); +}; + +module.exports = ContainsPoint; + + +/***/ }), + +/***/ 1632: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(81154); + +/** + * Check to see if the Ellipse contains all four points of the given Rectangle object. + * + * @function Phaser.Geom.Ellipse.ContainsRect + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to check. + * @param {(Phaser.Geom.Rectangle|object)} rect - The Rectangle object to check if it's within the Ellipse or not. + * + * @return {boolean} True if all of the Rectangle coordinates are within the ellipse, otherwise false. + */ +var ContainsRect = function (ellipse, rect) +{ + return ( + Contains(ellipse, rect.x, rect.y) && + Contains(ellipse, rect.right, rect.y) && + Contains(ellipse, rect.x, rect.bottom) && + Contains(ellipse, rect.right, rect.bottom) + ); +}; + +module.exports = ContainsRect; + + +/***/ }), + +/***/ 65534: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Copies the `x`, `y`, `width` and `height` properties from the `source` Ellipse + * into the given `dest` Ellipse, then returns the `dest` Ellipse. + * + * @function Phaser.Geom.Ellipse.CopyFrom + * @since 3.0.0 + * + * @generic {Phaser.Geom.Ellipse} O - [dest,$return] + * + * @param {Phaser.Geom.Ellipse} source - The source Ellipse to copy the values from. + * @param {Phaser.Geom.Ellipse} dest - The destination Ellipse to copy the values to. + * + * @return {Phaser.Geom.Ellipse} The destination Ellipse. + */ +var CopyFrom = function (source, dest) +{ + return dest.setTo(source.x, source.y, source.width, source.height); +}; + +module.exports = CopyFrom; + + +/***/ }), + +/***/ 8497: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Contains = __webpack_require__(81154); +var GetPoint = __webpack_require__(90549); +var GetPoints = __webpack_require__(48320); +var GEOM_CONST = __webpack_require__(23777); +var Random = __webpack_require__(24820); + +/** + * @classdesc + * An Ellipse object. + * + * This is a geometry object, containing numerical values and related methods to inspect and modify them. + * It is not a Game Object, in that you cannot add it to the display list, and it has no texture. + * To render an Ellipse you should look at the capabilities of the Graphics class. + * + * @class Ellipse + * @memberof Phaser.Geom + * @constructor + * @since 3.0.0 + * + * @param {number} [x=0] - The x position of the center of the ellipse. + * @param {number} [y=0] - The y position of the center of the ellipse. + * @param {number} [width=0] - The width of the ellipse. + * @param {number} [height=0] - The height of the ellipse. + */ +var Ellipse = new Class({ + + initialize: + + function Ellipse (x, y, width, height) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 0; } + if (height === undefined) { height = 0; } + + /** + * The geometry constant type of this object: `GEOM_CONST.ELLIPSE`. + * Used for fast type comparisons. + * + * @name Phaser.Geom.Ellipse#type + * @type {number} + * @readonly + * @since 3.19.0 + */ + this.type = GEOM_CONST.ELLIPSE; + + /** + * The x position of the center of the ellipse. + * + * @name Phaser.Geom.Ellipse#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = x; + + /** + * The y position of the center of the ellipse. + * + * @name Phaser.Geom.Ellipse#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = y; + + /** + * The width of the ellipse. + * + * @name Phaser.Geom.Ellipse#width + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.width = width; + + /** + * The height of the ellipse. + * + * @name Phaser.Geom.Ellipse#height + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.height = height; + }, + + /** + * Check to see if the Ellipse contains the given x / y coordinates. + * + * @method Phaser.Geom.Ellipse#contains + * @since 3.0.0 + * + * @param {number} x - The x coordinate to check within the ellipse. + * @param {number} y - The y coordinate to check within the ellipse. + * + * @return {boolean} True if the coordinates are within the ellipse, otherwise false. + */ + contains: function (x, y) + { + return Contains(this, x, y); + }, + + /** + * Returns a Point object containing the coordinates of a point on the circumference of the Ellipse + * based on the given angle normalized to the range 0 to 1. I.e. a value of 0.5 will give the point + * at 180 degrees around the circle. + * + * @method Phaser.Geom.Ellipse#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {number} position - A value between 0 and 1, where 0 equals 0 degrees, 0.5 equals 180 degrees and 1 equals 360 around the ellipse. + * @param {Phaser.Math.Vector2} [out] - A Vector2 to store the return values in. If not given a Vector2 object will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 instance containing the coordinates of the point around the ellipse. + */ + getPoint: function (position, point) + { + return GetPoint(this, position, point); + }, + + /** + * Returns an array of Vector2 objects containing the coordinates of the points around the circumference of the Ellipse, + * based on the given quantity or stepRate values. + * + * @method Phaser.Geom.Ellipse#getPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [output,$return] + * + * @param {number} quantity - The amount of points to return. If a falsey value the quantity will be derived from the `stepRate` instead. + * @param {number} [stepRate] - Sets the quantity by getting the circumference of the ellipse and dividing it by the stepRate. + * @param {Phaser.Math.Vector2[]} [output] - An array to insert the Vector2s in. If not provided a new array will be created. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects pertaining to the points around the circumference of the ellipse. + */ + getPoints: function (quantity, stepRate, output) + { + return GetPoints(this, quantity, stepRate, output); + }, + + /** + * Returns a uniformly distributed random point from anywhere within the given Ellipse. + * + * @method Phaser.Geom.Ellipse#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [point,$return] + * + * @param {Phaser.Math.Vector2} [vec] - A Vector2 object to set the random `x` and `y` values in. + * + * @return {Phaser.Math.Vector2} A Vector2 object with the random values set in the `x` and `y` properties. + */ + getRandomPoint: function (vec) + { + return Random(this, vec); + }, + + /** + * Sets the x, y, width and height of this ellipse. + * + * @method Phaser.Geom.Ellipse#setTo + * @since 3.0.0 + * + * @param {number} x - The x position of the center of the ellipse. + * @param {number} y - The y position of the center of the ellipse. + * @param {number} width - The width of the ellipse. + * @param {number} height - The height of the ellipse. + * + * @return {this} This Ellipse object. + */ + setTo: function (x, y, width, height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + + return this; + }, + + /** + * Sets this Ellipse to be empty with a width and height of zero. + * Does not change its position. + * + * @method Phaser.Geom.Ellipse#setEmpty + * @since 3.0.0 + * + * @return {this} This Ellipse object. + */ + setEmpty: function () + { + this.width = 0; + this.height = 0; + + return this; + }, + + /** + * Sets the position of this Ellipse. + * + * @method Phaser.Geom.Ellipse#setPosition + * @since 3.0.0 + * + * @param {number} x - The x position of the center of the ellipse. + * @param {number} y - The y position of the center of the ellipse. + * + * @return {this} This Ellipse object. + */ + setPosition: function (x, y) + { + if (y === undefined) { y = x; } + + this.x = x; + this.y = y; + + return this; + }, + + /** + * Sets the size of this Ellipse. + * Does not change its position. + * + * @method Phaser.Geom.Ellipse#setSize + * @since 3.0.0 + * + * @param {number} width - The width of the ellipse. + * @param {number} [height=width] - The height of the ellipse. + * + * @return {this} This Ellipse object. + */ + setSize: function (width, height) + { + if (height === undefined) { height = width; } + + this.width = width; + this.height = height; + + return this; + }, + + /** + * Checks to see if the Ellipse is empty: has a width or height equal to zero. + * + * @method Phaser.Geom.Ellipse#isEmpty + * @since 3.0.0 + * + * @return {boolean} True if the Ellipse is empty, otherwise false. + */ + isEmpty: function () + { + return (this.width <= 0 || this.height <= 0); + }, + + /** + * Returns the minor radius of the ellipse. Also known as the Semi Minor Axis. + * + * @method Phaser.Geom.Ellipse#getMinorRadius + * @since 3.0.0 + * + * @return {number} The minor radius. + */ + getMinorRadius: function () + { + return Math.min(this.width, this.height) / 2; + }, + + /** + * Returns the major radius of the ellipse. Also known as the Semi Major Axis. + * + * @method Phaser.Geom.Ellipse#getMajorRadius + * @since 3.0.0 + * + * @return {number} The major radius. + */ + getMajorRadius: function () + { + return Math.max(this.width, this.height) / 2; + }, + + /** + * The left position of the Ellipse. + * + * @name Phaser.Geom.Ellipse#left + * @type {number} + * @since 3.0.0 + */ + left: { + + get: function () + { + return this.x - (this.width / 2); + }, + + set: function (value) + { + this.x = value + (this.width / 2); + } + + }, + + /** + * The right position of the Ellipse. + * + * @name Phaser.Geom.Ellipse#right + * @type {number} + * @since 3.0.0 + */ + right: { + + get: function () + { + return this.x + (this.width / 2); + }, + + set: function (value) + { + this.x = value - (this.width / 2); + } + + }, + + /** + * The top position of the Ellipse. + * + * @name Phaser.Geom.Ellipse#top + * @type {number} + * @since 3.0.0 + */ + top: { + + get: function () + { + return this.y - (this.height / 2); + }, + + set: function (value) + { + this.y = value + (this.height / 2); + } + + }, + + /** + * The bottom position of the Ellipse. + * + * @name Phaser.Geom.Ellipse#bottom + * @type {number} + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return this.y + (this.height / 2); + }, + + set: function (value) + { + this.y = value - (this.height / 2); + } + + } + +}); + +module.exports = Ellipse; + + +/***/ }), + +/***/ 36146: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compares the `x`, `y`, `width` and `height` properties of the two given Ellipses. + * Returns `true` if they all match, otherwise returns `false`. + * + * @function Phaser.Geom.Ellipse.Equals + * @since 3.0.0 + * + * @param {Phaser.Geom.Ellipse} ellipse - The first Ellipse to compare. + * @param {Phaser.Geom.Ellipse} toCompare - The second Ellipse to compare. + * + * @return {boolean} `true` if the two Ellipse equal each other, otherwise `false`. + */ +var Equals = function (ellipse, toCompare) +{ + return ( + ellipse.x === toCompare.x && + ellipse.y === toCompare.y && + ellipse.width === toCompare.width && + ellipse.height === toCompare.height + ); +}; + +module.exports = Equals; + + +/***/ }), + +/***/ 23694: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Returns the bounds of the Ellipse object. + * + * @function Phaser.Geom.Ellipse.GetBounds + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get the bounds from. + * @param {(Phaser.Geom.Rectangle|object)} [out] - A Rectangle, or rectangle-like object, to store the ellipse bounds in. If not given a new Rectangle will be created. + * + * @return {(Phaser.Geom.Rectangle|object)} The Rectangle object containing the Ellipse bounds. + */ +var GetBounds = function (ellipse, out) +{ + if (out === undefined) { out = new Rectangle(); } + + out.x = ellipse.left; + out.y = ellipse.top; + out.width = ellipse.width; + out.height = ellipse.height; + + return out; +}; + +module.exports = GetBounds; + + +/***/ }), + +/***/ 90549: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CircumferencePoint = __webpack_require__(79522); +var FromPercent = __webpack_require__(62945); +var MATH_CONST = __webpack_require__(36383); +var Vector2 = __webpack_require__(26099); + +/** + * Returns a Vector2 object containing the coordinates of a point on the circumference of the Ellipse + * based on the given angle normalized to the range 0 to 1. I.e. a value of 0.5 will give the point + * at 180 degrees around the circle. + * + * @function Phaser.Geom.Ellipse.GetPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get the circumference point on. + * @param {number} position - A value between 0 and 1, where 0 equals 0 degrees, 0.5 equals 180 degrees and 1 equals 360 around the ellipse. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the return values in. If not given a new Vector2 object will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 object, containing the coordinates of the point around the ellipse. + */ +var GetPoint = function (ellipse, position, out) +{ + if (out === undefined) { out = new Vector2(); } + + var angle = FromPercent(position, 0, MATH_CONST.TAU); + + return CircumferencePoint(ellipse, angle, out); +}; + +module.exports = GetPoint; + + +/***/ }), + +/***/ 48320: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circumference = __webpack_require__(92990); +var CircumferencePoint = __webpack_require__(79522); +var FromPercent = __webpack_require__(62945); +var MATH_CONST = __webpack_require__(36383); + +/** + * Returns an array of Vector2 objects containing the coordinates of the points around the circumference of the Ellipse, + * based on the given quantity or stepRate values. + * + * @function Phaser.Geom.Ellipse.GetPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [out,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get the points from. + * @param {number} quantity - The amount of points to return. If a falsey value the quantity will be derived from the `stepRate` instead. + * @param {number} [stepRate] - Sets the quantity by getting the circumference of the ellipse and dividing it by the stepRate. + * @param {Phaser.Math.Vector2[]} [out] - An array to insert the Vector2 objects in to. If not provided a new array will be created. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects pertaining to the points around the circumference of the ellipse. + */ +var GetPoints = function (ellipse, quantity, stepRate, out) +{ + if (out === undefined) { out = []; } + + // If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!quantity && stepRate > 0) + { + quantity = Circumference(ellipse) / stepRate; + } + + for (var i = 0; i < quantity; i++) + { + var angle = FromPercent(i / quantity, 0, MATH_CONST.TAU); + + out.push(CircumferencePoint(ellipse, angle)); + } + + return out; +}; + +module.exports = GetPoints; + + +/***/ }), + +/***/ 73424: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Offsets the Ellipse by the values given. + * + * @function Phaser.Geom.Ellipse.Offset + * @since 3.0.0 + * + * @generic {Phaser.Geom.Ellipse} O - [ellipse,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to be offset (translated.) + * @param {number} x - The amount to horizontally offset the Ellipse by. + * @param {number} y - The amount to vertically offset the Ellipse by. + * + * @return {Phaser.Geom.Ellipse} The Ellipse that was offset. + */ +var Offset = function (ellipse, x, y) +{ + ellipse.x += x; + ellipse.y += y; + + return ellipse; +}; + +module.exports = Offset; + + +/***/ }), + +/***/ 44808: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Offsets the Ellipse by the values given in the `x` and `y` properties of the Vector2 object. + * + * @function Phaser.Geom.Ellipse.OffsetPoint + * @since 3.0.0 + * + * @generic {Phaser.Geom.Ellipse} O - [ellipse,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to be offset (translated.) + * @param {Phaser.Math.Vector2} vec - The Vector2 object containing the values to offset the Ellipse by. + * + * @return {Phaser.Geom.Ellipse} The Ellipse that was offset. + */ +var OffsetPoint = function (ellipse, vec) +{ + ellipse.x += vec.x; + ellipse.y += vec.y; + + return ellipse; +}; + +module.exports = OffsetPoint; + + +/***/ }), + +/***/ 24820: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a uniformly distributed random point from anywhere within the given Ellipse. + * + * @function Phaser.Geom.Ellipse.Random + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Ellipse} ellipse - The Ellipse to get a random point from. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to set the random `x` and `y` values in. + * + * @return {Phaser.Math.Vector2} A Vector2 object with the random values set in the `x` and `y` properties. + */ +var Random = function (ellipse, out) +{ + if (out === undefined) { out = new Vector2(); } + + var p = Math.random() * Math.PI * 2; + var s = Math.sqrt(Math.random()); + + out.x = ellipse.x + ((s * Math.cos(p)) * ellipse.width / 2); + out.y = ellipse.y + ((s * Math.sin(p)) * ellipse.height / 2); + + return out; +}; + +module.exports = Random; + + +/***/ }), + +/***/ 49203: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Ellipse = __webpack_require__(8497); + +Ellipse.Area = __webpack_require__(78874); +Ellipse.Circumference = __webpack_require__(92990); +Ellipse.CircumferencePoint = __webpack_require__(79522); +Ellipse.Clone = __webpack_require__(58102); +Ellipse.Contains = __webpack_require__(81154); +Ellipse.ContainsPoint = __webpack_require__(46662); +Ellipse.ContainsRect = __webpack_require__(1632); +Ellipse.CopyFrom = __webpack_require__(65534); +Ellipse.Equals = __webpack_require__(36146); +Ellipse.GetBounds = __webpack_require__(23694); +Ellipse.GetPoint = __webpack_require__(90549); +Ellipse.GetPoints = __webpack_require__(48320); +Ellipse.Offset = __webpack_require__(73424); +Ellipse.OffsetPoint = __webpack_require__(44808); +Ellipse.Random = __webpack_require__(24820); + +module.exports = Ellipse; + + +/***/ }), + +/***/ 55738: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(23777); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Geom + */ + +var Geom = { + + Circle: __webpack_require__(88911), + Ellipse: __webpack_require__(49203), + Intersects: __webpack_require__(91865), + Line: __webpack_require__(2529), + Polygon: __webpack_require__(58423), + Rectangle: __webpack_require__(93232), + Triangle: __webpack_require__(84435) + +}; + +// Merge in the consts +Geom = Extend(false, Geom, CONST); + +module.exports = Geom; + + +/***/ }), + +/***/ 2044: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DistanceBetween = __webpack_require__(20339); + +/** + * Checks if two Circles intersect. + * + * @function Phaser.Geom.Intersects.CircleToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circleA - The first Circle to check for intersection. + * @param {Phaser.Geom.Circle} circleB - The second Circle to check for intersection. + * + * @return {boolean} `true` if the two Circles intersect, otherwise `false`. + */ +var CircleToCircle = function (circleA, circleB) +{ + return (DistanceBetween(circleA.x, circleA.y, circleB.x, circleB.y) <= (circleA.radius + circleB.radius)); +}; + +module.exports = CircleToCircle; + + +/***/ }), + +/***/ 81491: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks for intersection between a circle and a rectangle. + * + * @function Phaser.Geom.Intersects.CircleToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The circle to be checked. + * @param {Phaser.Geom.Rectangle} rect - The rectangle to be checked. + * + * @return {boolean} `true` if the two objects intersect, otherwise `false`. + */ +var CircleToRectangle = function (circle, rect) +{ + var halfWidth = rect.width / 2; + var halfHeight = rect.height / 2; + + var cx = Math.abs(circle.x - rect.x - halfWidth); + var cy = Math.abs(circle.y - rect.y - halfHeight); + var xDist = halfWidth + circle.radius; + var yDist = halfHeight + circle.radius; + + if (cx > xDist || cy > yDist) + { + return false; + } + else if (cx <= halfWidth || cy <= halfHeight) + { + return true; + } + else + { + var xCornerDist = cx - halfWidth; + var yCornerDist = cy - halfHeight; + var xCornerDistSq = xCornerDist * xCornerDist; + var yCornerDistSq = yCornerDist * yCornerDist; + var maxCornerDistSq = circle.radius * circle.radius; + + return (xCornerDistSq + yCornerDistSq <= maxCornerDistSq); + } +}; + +module.exports = CircleToRectangle; + + +/***/ }), + +/***/ 63376: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var CircleToCircle = __webpack_require__(2044); + +/** + * Checks if two Circles intersect and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetCircleToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circleA - The first Circle to check for intersection. + * @param {Phaser.Geom.Circle} circleB - The second Circle to check for intersection. + * @param {Phaser.Math.Vector2[]} [out] - An optional array of Vector2 objects in which to store the points of intersection. + * + * @return {Phaser.Math.Vector2[]} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetCircleToCircle = function (circleA, circleB, out) +{ + if (out === undefined) { out = []; } + + if (CircleToCircle(circleA, circleB)) + { + var x0 = circleA.x; + var y0 = circleA.y; + var r0 = circleA.radius; + + var x1 = circleB.x; + var y1 = circleB.y; + var r1 = circleB.radius; + + var coefficientA, coefficientB, coefficientC, lambda, x; + + if (y0 === y1) + { + x = ((r1 * r1) - (r0 * r0) - (x1 * x1) + (x0 * x0)) / (2 * (x0 - x1)); + + coefficientA = 1; + coefficientB = -2 * y1; + coefficientC = (x1 * x1) + (x * x) - (2 * x1 * x) + (y1 * y1) - (r1 * r1); + + lambda = (coefficientB * coefficientB) - (4 * coefficientA * coefficientC); + + if (lambda === 0) + { + out.push(new Vector2(x, (-coefficientB / (2 * coefficientA)))); + } + else if (lambda > 0) + { + out.push(new Vector2(x, (-coefficientB + Math.sqrt(lambda)) / (2 * coefficientA))); + out.push(new Vector2(x, (-coefficientB - Math.sqrt(lambda)) / (2 * coefficientA))); + } + } + else + { + var v1 = (x0 - x1) / (y0 - y1); + var n = (r1 * r1 - r0 * r0 - x1 * x1 + x0 * x0 - y1 * y1 + y0 * y0) / (2 * (y0 - y1)); + + coefficientA = (v1 * v1) + 1; + coefficientB = (2 * y0 * v1) - (2 * n * v1) - (2 * x0); + coefficientC = (x0 * x0) + (y0 * y0) + (n * n) - (r0 * r0) - (2 * y0 * n); + + lambda = (coefficientB * coefficientB) - (4 * coefficientA * coefficientC); + + if (lambda === 0) + { + x = (-coefficientB / (2 * coefficientA)); + out.push(new Vector2(x, (n - (x * v1)))); + } + else if (lambda > 0) + { + x = (-coefficientB + Math.sqrt(lambda)) / (2 * coefficientA); + out.push(new Vector2(x, (n - (x * v1)))); + x = (-coefficientB - Math.sqrt(lambda)) / (2 * coefficientA); + out.push(new Vector2(x, (n - (x * v1)))); + } + } + } + + return out; +}; + +module.exports = GetCircleToCircle; + + +/***/ }), + +/***/ 97439: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLineToCircle = __webpack_require__(4042); +var CircleToRectangle = __webpack_require__(81491); + +/** + * Checks for intersection between a circle and a rectangle, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetCircleToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The circle to be checked. + * @param {Phaser.Geom.Rectangle} rect - The rectangle to be checked. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetCircleToRectangle = function (circle, rect, out) +{ + if (out === undefined) { out = []; } + + if (CircleToRectangle(circle, rect)) + { + var lineA = rect.getLineA(); + var lineB = rect.getLineB(); + var lineC = rect.getLineC(); + var lineD = rect.getLineD(); + + GetLineToCircle(lineA, circle, out); + GetLineToCircle(lineB, circle, out); + GetLineToCircle(lineC, circle, out); + GetLineToCircle(lineD, circle, out); + } + + return out; +}; + +module.exports = GetCircleToRectangle; + + +/***/ }), + +/***/ 4042: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var LineToCircle = __webpack_require__(80462); + +/** + * Checks for intersection between the line segment and circle, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetLineToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line segment to check. + * @param {Phaser.Geom.Circle} circle - The circle to check against the line. + * @param {Phaser.Math.Vector2[]} [out] - An optional array of Vector2 objects in which to store the points of intersection. + * + * @return {Phaser.Math.Vector2[]} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetLineToCircle = function (line, circle, out) +{ + if (out === undefined) { out = []; } + + if (LineToCircle(line, circle)) + { + var lx1 = line.x1; + var ly1 = line.y1; + + var lx2 = line.x2; + var ly2 = line.y2; + + var cx = circle.x; + var cy = circle.y; + var cr = circle.radius; + + var lDirX = lx2 - lx1; + var lDirY = ly2 - ly1; + var oDirX = lx1 - cx; + var oDirY = ly1 - cy; + + var coefficientA = lDirX * lDirX + lDirY * lDirY; + var coefficientB = 2 * (lDirX * oDirX + lDirY * oDirY); + var coefficientC = oDirX * oDirX + oDirY * oDirY - cr * cr; + + var lambda = (coefficientB * coefficientB) - (4 * coefficientA * coefficientC); + + var x, y; + + if (lambda === 0) + { + var root = -coefficientB / (2 * coefficientA); + + x = lx1 + root * lDirX; + y = ly1 + root * lDirY; + + if (root >= 0 && root <= 1) + { + out.push(new Vector2(x, y)); + } + } + else if (lambda > 0) + { + var root1 = (-coefficientB - Math.sqrt(lambda)) / (2 * coefficientA); + + x = lx1 + root1 * lDirX; + y = ly1 + root1 * lDirY; + + if (root1 >= 0 && root1 <= 1) + { + out.push(new Vector2(x, y)); + } + + var root2 = (-coefficientB + Math.sqrt(lambda)) / (2 * coefficientA); + + x = lx1 + root2 * lDirX; + y = ly1 + root2 * lDirY; + + if (root2 >= 0 && root2 <= 1) + { + out.push(new Vector2(x, y)); + } + } + } + + return out; +}; + +module.exports = GetLineToCircle; + + +/***/ }), + +/***/ 36100: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector3 = __webpack_require__(25836); + +/** + * Checks for intersection between the two line segments, or a ray and a line segment, + * and returns the intersection point as a Vector3, or `null` if the lines are parallel, or do not intersect. + * + * The `z` property of the Vector3 contains the intersection distance, which can be used to find + * the closest intersecting point from a group of line segments. + * + * @function Phaser.Geom.Intersects.GetLineToLine + * @since 3.50.0 + * + * @param {Phaser.Geom.Line} line1 - The first line segment, or a ray, to check. + * @param {Phaser.Geom.Line} line2 - The second line segment to check. + * @param {boolean} [isRay=false] - Is `line1` a ray or a line segment? + * @param {Phaser.Math.Vector3} [out] - A Vector3 to store the intersection results in. + * + * @return {Phaser.Math.Vector3} A Vector3 containing the intersection results, or `null`. + */ +var GetLineToLine = function (line1, line2, isRay, out) +{ + if (isRay === undefined) { isRay = false; } + + var x1 = line1.x1; + var y1 = line1.y1; + var x2 = line1.x2; + var y2 = line1.y2; + + var x3 = line2.x1; + var y3 = line2.y1; + var x4 = line2.x2; + var y4 = line2.y2; + + var dx1 = x2 - x1; + var dy1 = y2 - y1; + + var dx2 = x4 - x3; + var dy2 = y4 - y3; + + var denom = (dx1 * dy2 - dy1 * dx2); + + // Add co-linear check + + // Make sure there is not a division by zero - this also indicates that the lines are parallel. + // If numA and numB were both equal to zero the lines would be on top of each other (coincidental). + // This check is not done because it is not necessary for this implementation (the parallel check accounts for this). + + if (denom === 0) + { + return null; + } + + var t; + var u; + var s; + + if (isRay) + { + t = (dx1 * (y3 - y1) + dy1 * (x1 - x3)) / (dx2 * dy1 - dy2 * dx1); + + if (dx1 !== 0) + { + u = (x3 + dx2 * t - x1) / dx1; + } + else if (dy1 !== 0) + { + u = (y3 + dy2 * t - y1) / dy1; + } + else + { + return null; // degenerate line segment + } + + // Intersects? + if (u < 0 || t < 0 || t > 1) + { + return null; + } + + s = u; + } + else + { + t = ((x3 - x1) * dy2 - (y3 - y1) * dx2) / denom; + u = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / denom; + + // Intersects? + if (t < 0 || t > 1 || u < 0 || u > 1) + { + return null; + } + + s = t; + } + + if (out === undefined) + { + out = new Vector3(); + } + + return out.set( + x1 + dx1 * s, + y1 + dy1 * s, + s + ); +}; + +module.exports = GetLineToLine; + + +/***/ }), + +/***/ 3073: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLineToLine = __webpack_require__(36100); +var Line = __webpack_require__(23031); +var Vector3 = __webpack_require__(25836); + +// Temp calculation segment +var segment = new Line(); + +// Temp vec3 +var tempIntersect = new Vector3(); + +/** + * Checks for the closest point of intersection between a line segment and an array of points, where each pair + * of points are converted to line segments for the intersection tests. + * + * If no intersection is found, this function returns `null`. + * + * If intersection was found, a Vector3 is returned with the following properties: + * + * The `x` and `y` components contain the point of the intersection. + * The `z` component contains the closest distance. + * + * @function Phaser.Geom.Intersects.GetLineToPoints + * @since 3.50.0 + * + * @param {Phaser.Geom.Line} line - The line segment, or ray, to check. If a ray, set the `isRay` parameter to `true`. + * @param {Phaser.Math.Vector2[] | Phaser.Math.Vector2[]} points - An array of points to check. + * @param {boolean} [isRay=false] - Is `line` a ray or a line segment? + * @param {Phaser.Math.Vector3} [out] - A Vector3 to store the intersection results in. + * + * @return {Phaser.Math.Vector3} A Vector3 containing the intersection results, or `null`. + */ +var GetLineToPoints = function (line, points, isRay, out) +{ + if (isRay === undefined) { isRay = false; } + if (out === undefined) { out = new Vector3(); } + + var closestIntersect = false; + + // Reset our vec3s + out.set(); + tempIntersect.set(); + + var prev = points[points.length - 1]; + + for (var i = 0; i < points.length; i++) + { + var current = points[i]; + + segment.setTo(prev.x, prev.y, current.x, current.y); + + prev = current; + + if (GetLineToLine(line, segment, isRay, tempIntersect)) + { + if (!closestIntersect || tempIntersect.z < out.z) + { + out.copy(tempIntersect); + + closestIntersect = true; + } + } + } + + return (closestIntersect) ? out : null; +}; + +module.exports = GetLineToPoints; + + +/***/ }), + +/***/ 56362: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector3 = __webpack_require__(25836); +var Vector4 = __webpack_require__(61369); +var GetLineToPoints = __webpack_require__(3073); + +// Temp vec3 +var tempIntersect = new Vector3(); + +/** + * Checks for the closest point of intersection between a line segment and an array of polygons. + * + * If no intersection is found, this function returns `null`. + * + * If intersection was found, a Vector4 is returned with the following properties: + * + * The `x` and `y` components contain the point of the intersection. + * The `z` component contains the closest distance. + * The `w` component contains the index of the polygon, in the given array, that triggered the intersection. + * + * @function Phaser.Geom.Intersects.GetLineToPolygon + * @since 3.50.0 + * + * @param {Phaser.Geom.Line} line - The line segment, or ray, to check. If a ray, set the `isRay` parameter to `true`. + * @param {Phaser.Geom.Polygon | Phaser.Geom.Polygon[]} polygons - A single polygon, or array of polygons, to check. + * @param {boolean} [isRay=false] - Is `line` a ray or a line segment? + * @param {Phaser.Math.Vector4} [out] - A Vector4 to store the intersection results in. + * + * @return {Phaser.Math.Vector4} A Vector4 containing the intersection results, or `null`. + */ +var GetLineToPolygon = function (line, polygons, isRay, out) +{ + if (out === undefined) { out = new Vector4(); } + + if (!Array.isArray(polygons)) + { + polygons = [ polygons ]; + } + + var closestIntersect = false; + + // Reset our vec4s + out.set(); + tempIntersect.set(); + + for (var i = 0; i < polygons.length; i++) + { + if (GetLineToPoints(line, polygons[i].points, isRay, tempIntersect)) + { + if (!closestIntersect || tempIntersect.z < out.z) + { + out.set(tempIntersect.x, tempIntersect.y, tempIntersect.z, i); + + closestIntersect = true; + } + } + } + + return (closestIntersect) ? out : null; +}; + +module.exports = GetLineToPolygon; + + +/***/ }), + +/***/ 60646: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var LineToLine = __webpack_require__(76112); +var LineToRectangle = __webpack_require__(92773); + +/** + * Checks for intersection between the Line and a Rectangle shape, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetLineToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The Line to check for intersection. + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to check for intersection. + * @param {Phaser.Math.Vector2[]} [out] - An optional array of Vector2 objects in which to store the points of intersection. + * + * @return {Phaser.Math.Vector2[]} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetLineToRectangle = function (line, rect, out) +{ + if (out === undefined) { out = []; } + + if (LineToRectangle(line, rect)) + { + var lineA = rect.getLineA(); + var lineB = rect.getLineB(); + var lineC = rect.getLineC(); + var lineD = rect.getLineD(); + + var output = [ new Vector2(), new Vector2(), new Vector2(), new Vector2() ]; + + var result = [ + LineToLine(lineA, line, output[0]), + LineToLine(lineB, line, output[1]), + LineToLine(lineC, line, output[2]), + LineToLine(lineD, line, output[3]) + ]; + + for (var i = 0; i < 4; i++) + { + if (result[i]) + { + out.push(output[i]); + } + } + } + + return out; +}; + +module.exports = GetLineToRectangle; + + +/***/ }), + +/***/ 71147: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector4 = __webpack_require__(61369); +var GetLineToPolygon = __webpack_require__(56362); +var Line = __webpack_require__(23031); + +// Temp calculation segment +var segment = new Line(); + +/** + * @ignore + */ +function CheckIntersects (angle, x, y, polygons, intersects) +{ + var dx = Math.cos(angle); + var dy = Math.sin(angle); + + segment.setTo(x, y, x + dx, y + dy); + + var closestIntersect = GetLineToPolygon(segment, polygons, true); + + if (closestIntersect) + { + intersects.push(new Vector4(closestIntersect.x, closestIntersect.y, angle, closestIntersect.w)); + } +} + +/** + * @ignore + */ +function SortIntersects (a, b) +{ + return a.z - b.z; +} + +/** + * Projects rays out from the given point to each line segment of the polygons. + * + * If the rays intersect with the polygons, the points of intersection are returned in an array. + * + * If no intersections are found, the returned array will be empty. + * + * Each Vector4 intersection result has the following properties: + * + * The `x` and `y` components contain the point of the intersection. + * The `z` component contains the angle of intersection. + * The `w` component contains the index of the polygon, in the given array, that triggered the intersection. + * + * @function Phaser.Geom.Intersects.GetRaysFromPointToPolygon + * @since 3.50.0 + * + * @param {number} x - The x coordinate to project the rays from. + * @param {number} y - The y coordinate to project the rays from. + * @param {Phaser.Geom.Polygon | Phaser.Geom.Polygon[]} polygons - A single polygon, or array of polygons, to check against the rays. + * + * @return {Phaser.Math.Vector4[]} An array containing all intersections in Vector4s. + */ +var GetRaysFromPointToPolygon = function (x, y, polygons) +{ + if (!Array.isArray(polygons)) + { + polygons = [ polygons ]; + } + + var intersects = []; + var angles = []; + + for (var i = 0; i < polygons.length; i++) + { + var points = polygons[i].points; + + for (var p = 0; p < points.length; p++) + { + var angle = Math.atan2(points[p].y - y, points[p].x - x); + + if (angles.indexOf(angle) === -1) + { + // +- 0.00001 rads to catch lines behind segment corners + + CheckIntersects(angle, x, y, polygons, intersects); + CheckIntersects(angle - 0.00001, x, y, polygons, intersects); + CheckIntersects(angle + 0.00001, x, y, polygons, intersects); + + angles.push(angle); + } + } + } + + return intersects.sort(SortIntersects); +}; + +module.exports = GetRaysFromPointToPolygon; + + +/***/ }), + +/***/ 68389: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var RectangleToRectangle = __webpack_require__(59996); + +/** + * Checks if two Rectangle shapes intersect and returns the area of this intersection as Rectangle object. + * + * If optional `output` parameter is omitted, new Rectangle object is created and returned. If there is intersection, it will contain intersection area. If there is no intersection, it wil be empty Rectangle (all values set to zero). + * + * If Rectangle object is passed as `output` and there is intersection, then intersection area data will be loaded into it and it will be returned. If there is no intersection, it will be returned without any change. + * + * @function Phaser.Geom.Intersects.GetRectangleIntersection + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [output,$return] + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle object. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle object. + * @param {Phaser.Geom.Rectangle} [output] - Optional Rectangle object. If given, the intersection data will be loaded into it (in case of no intersection, it will be left unchanged). Otherwise, new Rectangle object will be created and returned with either intersection data or empty (all values set to zero), if there is no intersection. + * + * @return {Phaser.Geom.Rectangle} A rectangle object with intersection data. + */ +var GetRectangleIntersection = function (rectA, rectB, output) +{ + if (output === undefined) { output = new Rectangle(); } + + if (RectangleToRectangle(rectA, rectB)) + { + output.x = Math.max(rectA.x, rectB.x); + output.y = Math.max(rectA.y, rectB.y); + output.width = Math.min(rectA.right, rectB.right) - output.x; + output.height = Math.min(rectA.bottom, rectB.bottom) - output.y; + } + + return output; +}; + +module.exports = GetRectangleIntersection; + + +/***/ }), + +/***/ 52784: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLineToRectangle = __webpack_require__(60646); +var RectangleToRectangle = __webpack_require__(59996); + +/** + * Checks if two Rectangles intersect and returns the intersection points as a Point object array. + * + * A Rectangle intersects another Rectangle if any part of its bounds is within the other Rectangle's bounds. As such, the two Rectangles are considered "solid". A Rectangle with no width or no height will never intersect another Rectangle. + * + * @function Phaser.Geom.Intersects.GetRectangleToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check for intersection. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetRectangleToRectangle = function (rectA, rectB, out) +{ + if (out === undefined) { out = []; } + + if (RectangleToRectangle(rectA, rectB)) + { + var lineA = rectA.getLineA(); + var lineB = rectA.getLineB(); + var lineC = rectA.getLineC(); + var lineD = rectA.getLineD(); + + GetLineToRectangle(lineA, rectB, out); + GetLineToRectangle(lineB, rectB, out); + GetLineToRectangle(lineC, rectB, out); + GetLineToRectangle(lineD, rectB, out); + } + + return out; +}; + +module.exports = GetRectangleToRectangle; + + +/***/ }), + +/***/ 26341: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RectangleToTriangle = __webpack_require__(89265); +var GetLineToRectangle = __webpack_require__(60646); + +/** + * Checks for intersection between Rectangle shape and Triangle shape, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetRectangleToTriangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - Rectangle object to test. + * @param {Phaser.Geom.Triangle} triangle - Triangle object to test. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetRectangleToTriangle = function (rect, triangle, out) +{ + if (out === undefined) { out = []; } + + if (RectangleToTriangle(rect, triangle)) + { + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + GetLineToRectangle(lineA, rect, out); + GetLineToRectangle(lineB, rect, out); + GetLineToRectangle(lineC, rect, out); + } + + return out; +}; + +module.exports = GetRectangleToTriangle; + + +/***/ }), + +/***/ 38720: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetLineToCircle = __webpack_require__(4042); +var TriangleToCircle = __webpack_require__(67636); + +/** + * Checks if a Triangle and a Circle intersect, and returns the intersection points as a Point object array. + * + * A Circle intersects a Triangle if its center is located within it or if any of the Triangle's sides intersect the Circle. As such, the Triangle and the Circle are considered "solid" for the intersection. + * + * @function Phaser.Geom.Intersects.GetTriangleToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check for intersection. + * @param {Phaser.Geom.Circle} circle - The Circle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetTriangleToCircle = function (triangle, circle, out) +{ + if (out === undefined) { out = []; } + + if (TriangleToCircle(triangle, circle)) + { + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + GetLineToCircle(lineA, circle, out); + GetLineToCircle(lineB, circle, out); + GetLineToCircle(lineC, circle, out); + } + + return out; +}; + +module.exports = GetTriangleToCircle; + + +/***/ }), + +/***/ 13882: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var TriangleToLine = __webpack_require__(2822); +var LineToLine = __webpack_require__(76112); + +/** + * Checks if a Triangle and a Line intersect, and returns the intersection points as a Point object array. + * + * The Line intersects the Triangle if it starts inside of it, ends inside of it, or crosses any of the Triangle's sides. Thus, the Triangle is considered "solid". + * + * @function Phaser.Geom.Intersects.GetTriangleToLine + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check with. + * @param {Phaser.Geom.Line} line - The Line to check with. + * @param {Phaser.Math.Vector2[]} [out] - An optional array of Vector2 objects in which to store the points of intersection. + * + * @return {Phaser.Math.Vector2[]} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetTriangleToLine = function (triangle, line, out) +{ + if (out === undefined) { out = []; } + + if (TriangleToLine(triangle, line)) + { + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + var output = [ new Vector2(), new Vector2(), new Vector2() ]; + + var result = [ + LineToLine(lineA, line, output[0]), + LineToLine(lineB, line, output[1]), + LineToLine(lineC, line, output[2]) + ]; + + for (var i = 0; i < 3; i++) + { + if (result[i]) + { + out.push(output[i]); + } + } + } + + return out; +}; + +module.exports = GetTriangleToLine; + + +/***/ }), + +/***/ 75636: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Florian Vazelle + * @author Geoffrey Glaive + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TriangleToTriangle = __webpack_require__(82944); +var GetTriangleToLine = __webpack_require__(13882); + +/** + * Checks if two Triangles intersect, and returns the intersection points as a Point object array. + * + * A Triangle intersects another Triangle if any pair of their lines intersects or if any point of one Triangle is within the other Triangle. Thus, the Triangles are considered "solid". + * + * @function Phaser.Geom.Intersects.GetTriangleToTriangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangleA - The first Triangle to check for intersection. + * @param {Phaser.Geom.Triangle} triangleB - The second Triangle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetTriangleToTriangle = function (triangleA, triangleB, out) +{ + if (out === undefined) { out = []; } + + if (TriangleToTriangle(triangleA, triangleB)) + { + var lineA = triangleB.getLineA(); + var lineB = triangleB.getLineB(); + var lineC = triangleB.getLineC(); + + GetTriangleToLine(triangleA, lineA, out); + GetTriangleToLine(triangleA, lineB, out); + GetTriangleToLine(triangleA, lineC, out); + } + + return out; +}; + +module.exports = GetTriangleToTriangle; + + +/***/ }), + +/***/ 80462: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(87902); +var Vector2 = __webpack_require__(26099); + +var tmp = new Vector2(); + +/** + * Checks for intersection between the line segment and circle. + * + * Based on code by [Matt DesLauriers](https://github.com/mattdesl/line-circle-collision/blob/master/LICENSE.md). + * + * @function Phaser.Geom.Intersects.LineToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line segment to check. + * @param {Phaser.Geom.Circle} circle - The circle to check against the line. + * @param {Phaser.Math.Vector2} [nearest] - An optional Vector2 object. If given the closest point on the Line where the circle intersects will be stored in this object. + * + * @return {boolean} `true` if the two objects intersect, otherwise `false`. + */ +var LineToCircle = function (line, circle, nearest) +{ + if (nearest === undefined) { nearest = tmp; } + + if (Contains(circle, line.x1, line.y1)) + { + nearest.x = line.x1; + nearest.y = line.y1; + + return true; + } + + if (Contains(circle, line.x2, line.y2)) + { + nearest.x = line.x2; + nearest.y = line.y2; + + return true; + } + + var dx = line.x2 - line.x1; + var dy = line.y2 - line.y1; + + var lcx = circle.x - line.x1; + var lcy = circle.y - line.y1; + + // project lc onto d, resulting in vector p + var dLen2 = (dx * dx) + (dy * dy); + var px = dx; + var py = dy; + + if (dLen2 > 0) + { + var dp = ((lcx * dx) + (lcy * dy)) / dLen2; + + px *= dp; + py *= dp; + } + + nearest.x = line.x1 + px; + nearest.y = line.y1 + py; + + // len2 of p + var pLen2 = (px * px) + (py * py); + + return ( + pLen2 <= dLen2 && + ((px * dx) + (py * dy)) >= 0 && + Contains(circle, nearest.x, nearest.y) + ); +}; + +module.exports = LineToCircle; + + +/***/ }), + +/***/ 76112: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// This is based off an explanation and expanded math presented by Paul Bourke: +// See http://paulbourke.net/geometry/pointlineplane/ + +/** + * Checks if two Lines intersect. If the Lines are identical, they will be treated as parallel and thus non-intersecting. + * + * @function Phaser.Geom.Intersects.LineToLine + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line1 - The first Line to check. + * @param {Phaser.Geom.Line} line2 - The second Line to check. + * @param {Phaser.Types.Math.Vector2Like} [out] - An optional point-like object in which to store the coordinates of intersection, if needed. + * + * @return {boolean} `true` if the two Lines intersect, and the `out` object will be populated, if given. Otherwise, `false`. + */ +var LineToLine = function (line1, line2, out) +{ + var x1 = line1.x1; + var y1 = line1.y1; + var x2 = line1.x2; + var y2 = line1.y2; + + var x3 = line2.x1; + var y3 = line2.y1; + var x4 = line2.x2; + var y4 = line2.y2; + + // Check that none of the lines are length zero + if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) + { + return false; + } + + var denom = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + + // Make sure there is not a division by zero - this also indicates that the lines are parallel. + // If numA and numB were both equal to zero the lines would be on top of each other (coincidental). + // This check is not done because it is not necessary for this implementation (the parallel check accounts for this). + + if (denom === 0) + { + // Lines are parallel + return false; + } + + // Calculate the intermediate fractional point that the lines potentially intersect. + + var ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; + var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; + + // The fractional point will be between 0 and 1 inclusive if the lines intersect. + // If the fractional calculation is larger than 1 or smaller than 0 the lines would need to be longer to intersect. + + if (ua < 0 || ua > 1 || ub < 0 || ub > 1) + { + return false; + } + else + { + if (out) + { + out.x = x1 + ua * (x2 - x1); + out.y = y1 + ua * (y2 - y1); + } + + return true; + } +}; + +module.exports = LineToLine; + + +/***/ }), + +/***/ 92773: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks for intersection between the Line and a Rectangle shape, or a rectangle-like + * object, with public `x`, `y`, `right` and `bottom` properties, such as a Sprite or Body. + * + * An intersection is considered valid if: + * + * The line starts within, or ends within, the Rectangle. + * The line segment intersects one of the 4 rectangle edges. + * + * The for the purposes of this function rectangles are considered 'solid'. + * + * @function Phaser.Geom.Intersects.LineToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The Line to check for intersection. + * @param {(Phaser.Geom.Rectangle|object)} rect - The Rectangle to check for intersection. + * + * @return {boolean} `true` if the Line and the Rectangle intersect, `false` otherwise. + */ +var LineToRectangle = function (line, rect) +{ + var x1 = line.x1; + var y1 = line.y1; + + var x2 = line.x2; + var y2 = line.y2; + + var bx1 = rect.x; + var by1 = rect.y; + var bx2 = rect.right; + var by2 = rect.bottom; + + var t = 0; + + // If the start or end of the line is inside the rect then we assume + // collision, as rects are solid for our use-case. + + if ((x1 >= bx1 && x1 <= bx2 && y1 >= by1 && y1 <= by2) || + (x2 >= bx1 && x2 <= bx2 && y2 >= by1 && y2 <= by2)) + { + return true; + } + + if (x1 < bx1 && x2 >= bx1) + { + // Left edge + t = y1 + (y2 - y1) * (bx1 - x1) / (x2 - x1); + + if (t > by1 && t <= by2) + { + return true; + } + } + else if (x1 > bx2 && x2 <= bx2) + { + // Right edge + t = y1 + (y2 - y1) * (bx2 - x1) / (x2 - x1); + + if (t >= by1 && t <= by2) + { + return true; + } + } + + if (y1 < by1 && y2 >= by1) + { + // Top edge + t = x1 + (x2 - x1) * (by1 - y1) / (y2 - y1); + + if (t >= bx1 && t <= bx2) + { + return true; + } + } + else if (y1 > by2 && y2 <= by2) + { + // Bottom edge + t = x1 + (x2 - x1) * (by2 - y1) / (y2 - y1); + + if (t >= bx1 && t <= bx2) + { + return true; + } + } + + return false; +}; + +module.exports = LineToRectangle; + + +/***/ }), + +/***/ 16204: +/***/ ((module) => { + +/** + * @author Richard Davey + * @author Florian Mertens + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if the a Point falls between the two end-points of a Line, based on the given line thickness. + * + * Assumes that the line end points are circular, not square. + * + * @function Phaser.Geom.Intersects.PointToLine + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|any)} point - The point, or point-like object to check. + * @param {Phaser.Geom.Line} line - The line segment to test for intersection on. + * @param {number} [lineThickness=1] - The line thickness. Assumes that the line end points are circular. + * + * @return {boolean} `true` if the Point falls on the Line, otherwise `false`. + */ +var PointToLine = function (point, line, lineThickness) +{ + if (lineThickness === undefined) { lineThickness = 1; } + + var x1 = line.x1; + var y1 = line.y1; + + var x2 = line.x2; + var y2 = line.y2; + + var px = point.x; + var py = point.y; + + var L2 = (((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))); + + if (L2 === 0) + { + return false; + } + + var r = (((px - x1) * (x2 - x1)) + ((py - y1) * (y2 - y1))) / L2; + + // Assume line thickness is circular + if (r < 0) + { + // Outside line1 + return (Math.sqrt(((x1 - px) * (x1 - px)) + ((y1 - py) * (y1 - py))) <= lineThickness); + } + else if ((r >= 0) && (r <= 1)) + { + // On the line segment + var s = (((y1 - py) * (x2 - x1)) - ((x1 - px) * (y2 - y1))) / L2; + + return (Math.abs(s) * Math.sqrt(L2) <= lineThickness); + } + else + { + // Outside line2 + return (Math.sqrt(((x2 - px) * (x2 - px)) + ((y2 - py) * (y2 - py))) <= lineThickness); + } +}; + +module.exports = PointToLine; + + +/***/ }), + +/***/ 14199: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PointToLine = __webpack_require__(16204); + +/** + * Checks if a Point is located on the given line segment. + * + * @function Phaser.Geom.Intersects.PointToLineSegment + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2} point - The Point to check for intersection. + * @param {Phaser.Geom.Line} line - The line segment to check for intersection. + * + * @return {boolean} `true` if the Point is on the given line segment, otherwise `false`. + */ +var PointToLineSegment = function (point, line) +{ + if (!PointToLine(point, line)) + { + return false; + } + + var xMin = Math.min(line.x1, line.x2); + var xMax = Math.max(line.x1, line.x2); + var yMin = Math.min(line.y1, line.y2); + var yMax = Math.max(line.y1, line.y2); + + return ((point.x >= xMin && point.x <= xMax) && (point.y >= yMin && point.y <= yMax)); +}; + +module.exports = PointToLineSegment; + + +/***/ }), + +/***/ 59996: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if two Rectangles intersect. + * + * A Rectangle intersects another Rectangle if any part of its bounds is within the other Rectangle's bounds. + * As such, the two Rectangles are considered "solid". + * A Rectangle with no width or no height will never intersect another Rectangle. + * + * @function Phaser.Geom.Intersects.RectangleToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check for intersection. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check for intersection. + * + * @return {boolean} `true` if the two Rectangles intersect, otherwise `false`. + */ +var RectangleToRectangle = function (rectA, rectB) +{ + if (rectA.width <= 0 || rectA.height <= 0 || rectB.width <= 0 || rectB.height <= 0) + { + return false; + } + + return !(rectA.right < rectB.x || rectA.bottom < rectB.y || rectA.x > rectB.right || rectA.y > rectB.bottom); +}; + +module.exports = RectangleToRectangle; + + +/***/ }), + +/***/ 89265: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var LineToLine = __webpack_require__(76112); +var Contains = __webpack_require__(37303); +var ContainsArray = __webpack_require__(48653); +var Decompose = __webpack_require__(77493); + +/** + * Checks for intersection between Rectangle shape and Triangle shape. + * + * @function Phaser.Geom.Intersects.RectangleToTriangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - Rectangle object to test. + * @param {Phaser.Geom.Triangle} triangle - Triangle object to test. + * + * @return {boolean} A value of `true` if objects intersect; otherwise `false`. + */ +var RectangleToTriangle = function (rect, triangle) +{ + // First the cheapest ones: + + if ( + triangle.left > rect.right || + triangle.right < rect.left || + triangle.top > rect.bottom || + triangle.bottom < rect.top) + { + return false; + } + + var triA = triangle.getLineA(); + var triB = triangle.getLineB(); + var triC = triangle.getLineC(); + + // Are any of the triangle points within the rectangle? + + if (Contains(rect, triA.x1, triA.y1) || Contains(rect, triA.x2, triA.y2)) + { + return true; + } + + if (Contains(rect, triB.x1, triB.y1) || Contains(rect, triB.x2, triB.y2)) + { + return true; + } + + if (Contains(rect, triC.x1, triC.y1) || Contains(rect, triC.x2, triC.y2)) + { + return true; + } + + // Cheap tests over, now to see if any of the lines intersect ... + + var rectA = rect.getLineA(); + var rectB = rect.getLineB(); + var rectC = rect.getLineC(); + var rectD = rect.getLineD(); + + if (LineToLine(triA, rectA) || LineToLine(triA, rectB) || LineToLine(triA, rectC) || LineToLine(triA, rectD)) + { + return true; + } + + if (LineToLine(triB, rectA) || LineToLine(triB, rectB) || LineToLine(triB, rectC) || LineToLine(triB, rectD)) + { + return true; + } + + if (LineToLine(triC, rectA) || LineToLine(triC, rectB) || LineToLine(triC, rectC) || LineToLine(triC, rectD)) + { + return true; + } + + // None of the lines intersect, so are any rectangle points within the triangle? + + var points = Decompose(rect); + var within = ContainsArray(triangle, points, true); + + return (within.length > 0); +}; + +module.exports = RectangleToTriangle; + + +/***/ }), + +/***/ 84411: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check if rectangle intersects with values. + * + * @function Phaser.Geom.Intersects.RectangleToValues + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The rectangle object + * @param {number} left - The x coordinate of the left of the Rectangle. + * @param {number} right - The x coordinate of the right of the Rectangle. + * @param {number} top - The y coordinate of the top of the Rectangle. + * @param {number} bottom - The y coordinate of the bottom of the Rectangle. + * @param {number} [tolerance=0] - Tolerance allowed in the calculation, expressed in pixels. + * + * @return {boolean} Returns true if there is an intersection. + */ +var RectangleToValues = function (rect, left, right, top, bottom, tolerance) +{ + if (tolerance === undefined) { tolerance = 0; } + + return !( + left > rect.right + tolerance || + right < rect.left - tolerance || + top > rect.bottom + tolerance || + bottom < rect.top - tolerance + ); +}; + +module.exports = RectangleToValues; + + +/***/ }), + +/***/ 67636: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var LineToCircle = __webpack_require__(80462); +var Contains = __webpack_require__(10690); + +/** + * Checks if a Triangle and a Circle intersect. + * + * A Circle intersects a Triangle if its center is located within it or if any of the Triangle's sides intersect the Circle. As such, the Triangle and the Circle are considered "solid" for the intersection. + * + * @function Phaser.Geom.Intersects.TriangleToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check for intersection. + * @param {Phaser.Geom.Circle} circle - The Circle to check for intersection. + * + * @return {boolean} `true` if the Triangle and the `Circle` intersect, otherwise `false`. + */ +var TriangleToCircle = function (triangle, circle) +{ + // First the cheapest ones: + + if ( + triangle.left > circle.right || + triangle.right < circle.left || + triangle.top > circle.bottom || + triangle.bottom < circle.top) + { + return false; + } + + if (Contains(triangle, circle.x, circle.y)) + { + return true; + } + + if (LineToCircle(triangle.getLineA(), circle)) + { + return true; + } + + if (LineToCircle(triangle.getLineB(), circle)) + { + return true; + } + + if (LineToCircle(triangle.getLineC(), circle)) + { + return true; + } + + return false; +}; + +module.exports = TriangleToCircle; + + +/***/ }), + +/***/ 2822: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var LineToLine = __webpack_require__(76112); + +/** + * Checks if a Triangle and a Line intersect. + * + * The Line intersects the Triangle if it starts inside of it, ends inside of it, or crosses any of the Triangle's sides. Thus, the Triangle is considered "solid". + * + * @function Phaser.Geom.Intersects.TriangleToLine + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check with. + * @param {Phaser.Geom.Line} line - The Line to check with. + * + * @return {boolean} `true` if the Triangle and the Line intersect, otherwise `false`. + */ +var TriangleToLine = function (triangle, line) +{ + // If the Triangle contains either the start or end point of the line, it intersects + if (triangle.contains(line.x1, line.y1) || triangle.contains(line.x2, line.y2)) + { + return true; + } + + // Now check the line against each line of the Triangle + if (LineToLine(triangle.getLineA(), line)) + { + return true; + } + + if (LineToLine(triangle.getLineB(), line)) + { + return true; + } + + if (LineToLine(triangle.getLineC(), line)) + { + return true; + } + + return false; +}; + +module.exports = TriangleToLine; + + +/***/ }), + +/***/ 82944: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ContainsArray = __webpack_require__(48653); +var Decompose = __webpack_require__(71694); +var LineToLine = __webpack_require__(76112); + +/** + * Checks if two Triangles intersect. + * + * A Triangle intersects another Triangle if any pair of their lines intersects or if any point of one Triangle is within the other Triangle. Thus, the Triangles are considered "solid". + * + * @function Phaser.Geom.Intersects.TriangleToTriangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangleA - The first Triangle to check for intersection. + * @param {Phaser.Geom.Triangle} triangleB - The second Triangle to check for intersection. + * + * @return {boolean} `true` if the Triangles intersect, otherwise `false`. + */ +var TriangleToTriangle = function (triangleA, triangleB) +{ + // First the cheapest ones: + + if ( + triangleA.left > triangleB.right || + triangleA.right < triangleB.left || + triangleA.top > triangleB.bottom || + triangleA.bottom < triangleB.top) + { + return false; + } + + var lineAA = triangleA.getLineA(); + var lineAB = triangleA.getLineB(); + var lineAC = triangleA.getLineC(); + + var lineBA = triangleB.getLineA(); + var lineBB = triangleB.getLineB(); + var lineBC = triangleB.getLineC(); + + // Now check the lines against each line of TriangleB + if (LineToLine(lineAA, lineBA) || LineToLine(lineAA, lineBB) || LineToLine(lineAA, lineBC)) + { + return true; + } + + if (LineToLine(lineAB, lineBA) || LineToLine(lineAB, lineBB) || LineToLine(lineAB, lineBC)) + { + return true; + } + + if (LineToLine(lineAC, lineBA) || LineToLine(lineAC, lineBB) || LineToLine(lineAC, lineBC)) + { + return true; + } + + // Nope, so check to see if any of the points of triangleA are within triangleB + + var points = Decompose(triangleA); + var within = ContainsArray(triangleB, points, true); + + if (within.length > 0) + { + return true; + } + + // Finally check to see if any of the points of triangleB are within triangleA + + points = Decompose(triangleB); + within = ContainsArray(triangleA, points, true); + + if (within.length > 0) + { + return true; + } + + return false; +}; + +module.exports = TriangleToTriangle; + + +/***/ }), + +/***/ 91865: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Geom.Intersects + */ + +module.exports = { + + CircleToCircle: __webpack_require__(2044), + CircleToRectangle: __webpack_require__(81491), + GetCircleToCircle: __webpack_require__(63376), + GetCircleToRectangle: __webpack_require__(97439), + GetLineToCircle: __webpack_require__(4042), + GetLineToLine: __webpack_require__(36100), + GetLineToPoints: __webpack_require__(3073), + GetLineToPolygon: __webpack_require__(56362), + GetLineToRectangle: __webpack_require__(60646), + GetRaysFromPointToPolygon: __webpack_require__(71147), + GetRectangleIntersection: __webpack_require__(68389), + GetRectangleToRectangle: __webpack_require__(52784), + GetRectangleToTriangle: __webpack_require__(26341), + GetTriangleToCircle: __webpack_require__(38720), + GetTriangleToLine: __webpack_require__(13882), + GetTriangleToTriangle: __webpack_require__(75636), + LineToCircle: __webpack_require__(80462), + LineToLine: __webpack_require__(76112), + LineToRectangle: __webpack_require__(92773), + PointToLine: __webpack_require__(16204), + PointToLineSegment: __webpack_require__(14199), + RectangleToRectangle: __webpack_require__(59996), + RectangleToTriangle: __webpack_require__(89265), + RectangleToValues: __webpack_require__(84411), + TriangleToCircle: __webpack_require__(67636), + TriangleToLine: __webpack_require__(2822), + TriangleToTriangle: __webpack_require__(82944) + +}; + + +/***/ }), + +/***/ 91938: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the angle of the line in radians. + * + * @function Phaser.Geom.Line.Angle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the angle of. + * + * @return {number} The angle of the line, in radians. + */ +var Angle = function (line) +{ + return Math.atan2(line.y2 - line.y1, line.x2 - line.x1); +}; + +module.exports = Angle; + + +/***/ }), + +/***/ 84993: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Using Bresenham's line algorithm this will return an array of all coordinates on this line. + * + * The `start` and `end` points are rounded before this runs as the algorithm works on integers. + * + * @function Phaser.Geom.Line.BresenhamPoints + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line. + * @param {number} [stepRate=1] - The optional step rate for the points on the line. + * @param {Phaser.Types.Math.Vector2Like[]} [results] - An optional array to push the resulting coordinates into. + * + * @return {Phaser.Types.Math.Vector2Like[]} The array of coordinates on the line. + */ +var BresenhamPoints = function (line, stepRate, results) +{ + if (stepRate === undefined) { stepRate = 1; } + if (results === undefined) { results = []; } + + var x1 = Math.round(line.x1); + var y1 = Math.round(line.y1); + var x2 = Math.round(line.x2); + var y2 = Math.round(line.y2); + + var dx = Math.abs(x2 - x1); + var dy = Math.abs(y2 - y1); + var sx = (x1 < x2) ? 1 : -1; + var sy = (y1 < y2) ? 1 : -1; + var err = dx - dy; + + results.push({ x: x1, y: y1 }); + + var i = 1; + + while (!((x1 === x2) && (y1 === y2))) + { + var e2 = err << 1; + + if (e2 > -dy) + { + err -= dy; + x1 += sx; + } + + if (e2 < dx) + { + err += dx; + y1 += sy; + } + + if (i % stepRate === 0) + { + results.push({ x: x1, y: y1 }); + } + + i++; + } + + return results; +}; + +module.exports = BresenhamPoints; + + +/***/ }), + +/***/ 36469: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + + +/** + * Center a line on the given coordinates. + * + * @function Phaser.Geom.Line.CenterOn + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to center. + * @param {number} x - The horizontal coordinate to center the line on. + * @param {number} y - The vertical coordinate to center the line on. + * + * @return {Phaser.Geom.Line} The centered line. + */ +var CenterOn = function (line, x, y) +{ + var tx = x - ((line.x1 + line.x2) / 2); + var ty = y - ((line.y1 + line.y2) / 2); + + line.x1 += tx; + line.y1 += ty; + + line.x2 += tx; + line.y2 += ty; + + return line; +}; + +module.exports = CenterOn; + + +/***/ }), + +/***/ 31116: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Line = __webpack_require__(23031); + +/** + * Clone the given line. + * + * @function Phaser.Geom.Line.Clone + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} source - The source line to clone. + * + * @return {Phaser.Geom.Line} The cloned line. + */ +var Clone = function (source) +{ + return new Line(source.x1, source.y1, source.x2, source.y2); +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 59944: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Copy the values of one line to a destination line. + * + * @function Phaser.Geom.Line.CopyFrom + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [dest,$return] + * + * @param {Phaser.Geom.Line} source - The source line to copy the values from. + * @param {Phaser.Geom.Line} dest - The destination line to copy the values to. + * + * @return {Phaser.Geom.Line} The destination line. + */ +var CopyFrom = function (source, dest) +{ + return dest.setTo(source.x1, source.y1, source.x2, source.y2); +}; + +module.exports = CopyFrom; + + +/***/ }), + +/***/ 59220: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compare two lines for strict equality. + * + * @function Phaser.Geom.Line.Equals + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The first line to compare. + * @param {Phaser.Geom.Line} toCompare - The second line to compare. + * + * @return {boolean} Whether the two lines are equal. + */ +var Equals = function (line, toCompare) +{ + return ( + line.x1 === toCompare.x1 && + line.y1 === toCompare.y1 && + line.x2 === toCompare.x2 && + line.y2 === toCompare.y2 + ); +}; + +module.exports = Equals; + + +/***/ }), + +/***/ 78177: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Length = __webpack_require__(35001); + +/** + * Extends the start and end points of a Line by the given amounts. + * + * The amounts can be positive or negative. Positive points will increase the length of the line, + * while negative ones will decrease it. + * + * If no `right` value is provided it will extend the length of the line equally in both directions. + * + * Pass a value of zero to leave the start or end point unchanged. + * + * @function Phaser.Geom.Line.Extend + * @since 3.16.0 + * + * @param {Phaser.Geom.Line} line - The line instance to extend. + * @param {number} left - The amount to extend the start of the line by. + * @param {number} [right] - The amount to extend the end of the line by. If not given it will be set to the `left` value. + * + * @return {Phaser.Geom.Line} The modified Line instance. + */ +var Extend = function (line, left, right) +{ + if (right === undefined) { right = left; } + + var length = Length(line); + + var slopX = line.x2 - line.x1; + var slopY = line.y2 - line.y1; + + if (left) + { + line.x1 = line.x1 - slopX / length * left; + line.y1 = line.y1 - slopY / length * left; + } + + if (right) + { + line.x2 = line.x2 + slopX / length * right; + line.y2 = line.y2 + slopY / length * right; + } + + return line; +}; + +module.exports = Extend; + + +/***/ }), + +/***/ 26708: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DistanceBetweenPoints = __webpack_require__(52816); +var GetEaseFunction = __webpack_require__(6113); +var Vector2 = __webpack_require__(26099); + +/** + * Returns an array of `quantity` Points where each point is taken from the given Line, + * spaced out according to the ease function specified. + * + * ```javascript + * const line = new Phaser.Geom.Line(100, 300, 700, 300); + * const points = Phaser.Geom.Line.GetEasedPoints(line, 'sine.out', 32) + * ``` + * + * In the above example, the `points` array will contain 32 points spread-out across + * the length of `line`, where the position of each point is determined by the `Sine.out` + * ease function. + * + * You can optionally provide a collinear threshold. In this case, the resulting points + * are checked against each other, and if they are `< collinearThreshold` distance apart, + * they are dropped from the results. This can help avoid lots of clustered points at + * far ends of the line with tightly-packed eases such as Quartic. Leave the value set + * to zero to skip this check. + * + * Note that if you provide a collinear threshold, the resulting array may not always + * contain `quantity` points. + * + * @function Phaser.Geom.Line.GetEasedPoints + * @since 3.23.0 + * + * @generic {Phaser.Math.Vector2[]} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The Line object. + * @param {(string|function)} ease - The ease to use. This can be either a string from the EaseMap, or a custom function. + * @param {number} quantity - The number of points to return. Note that if you provide a `collinearThreshold`, the resulting array may not always contain this number of points. + * @param {number} [collinearThreshold=0] - An optional threshold. The final array is reduced so that each point is spaced out at least this distance apart. This helps reduce clustering in noisey eases. + * @param {number[]} [easeParams] - An optional array of ease parameters to go with the ease. + * + * @return {Phaser.Math.Vector2[]} An array of Math.Vector2s containing the coordinates of the points on the line. + */ +var GetEasedPoints = function (line, ease, quantity, collinearThreshold, easeParams) +{ + if (collinearThreshold === undefined) { collinearThreshold = 0; } + if (easeParams === undefined) { easeParams = []; } + + var results = []; + + var x1 = line.x1; + var y1 = line.y1; + + var spaceX = line.x2 - x1; + var spaceY = line.y2 - y1; + + var easeFunc = GetEaseFunction(ease, easeParams); + + var i; + var v; + var q = quantity - 1; + + for (i = 0; i < q; i++) + { + v = easeFunc(i / q); + + results.push(new Vector2(x1 + (spaceX * v), y1 + (spaceY * v))); + } + + // Always include the end of the line + v = easeFunc(1); + + results.push(new Vector2(x1 + (spaceX * v), y1 + (spaceY * v))); + + // Remove collinear parts + if (collinearThreshold > 0) + { + var prevPoint = results[0]; + + // Store the new results here + var sortedResults = [ prevPoint ]; + + for (i = 1; i < results.length - 1; i++) + { + var point = results[i]; + + if (DistanceBetweenPoints(prevPoint, point) >= collinearThreshold) + { + sortedResults.push(point); + prevPoint = point; + } + } + + // Top and tail + var endPoint = results[results.length - 1]; + + if (DistanceBetweenPoints(prevPoint, endPoint) < collinearThreshold) + { + sortedResults.pop(); + } + + sortedResults.push(endPoint); + + return sortedResults; + } + else + { + return results; + } +}; + +module.exports = GetEasedPoints; + + +/***/ }), + +/***/ 32125: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Get the midpoint of the given line. + * + * @function Phaser.Geom.Line.GetMidPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The line to get the midpoint of. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 object to store the midpoint in. + * + * @return {Phaser.Math.Vector2} The midpoint of the Line. + */ +var GetMidPoint = function (line, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = (line.x1 + line.x2) / 2; + out.y = (line.y1 + line.y2) / 2; + + return out; +}; + +module.exports = GetMidPoint; + + +/***/ }), + +/***/ 99569: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Florian Mertens + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Get the nearest point on a line perpendicular to the given point. + * + * @function Phaser.Geom.Line.GetNearestPoint + * @since 3.16.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The line to get the nearest point on. + * @param {Phaser.Math.Vector2} vec - The Vector2 to get the nearest point to. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 object, to store the coordinates of the nearest point on the line. + * + * @return {Phaser.Math.Vector2} The nearest point on the line. + */ +var GetNearestPoint = function (line, vec, out) +{ + if (out === undefined) { out = new Vector2(); } + + var x1 = line.x1; + var y1 = line.y1; + + var x2 = line.x2; + var y2 = line.y2; + + var L2 = (((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))); + + if (L2 === 0) + { + return out; + } + + var r = (((vec.x - x1) * (x2 - x1)) + ((vec.y - y1) * (y2 - y1))) / L2; + + out.x = x1 + (r * (x2 - x1)); + out.y = y1 + (r * (y2 - y1)); + + return out; +}; + +module.exports = GetNearestPoint; + + +/***/ }), + +/***/ 34638: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = __webpack_require__(36383); +var Angle = __webpack_require__(91938); +var Vector2 = __webpack_require__(26099); + +/** + * Calculate the normal of the given line. + * + * The normal of a line is a vector that points perpendicular from it. + * + * @function Phaser.Geom.Line.GetNormal + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The line to calculate the normal of. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 object to store the normal in. + * + * @return {Phaser.Math.Vector2} The normal of the Line. + */ +var GetNormal = function (line, out) +{ + if (out === undefined) { out = new Vector2(); } + + var a = Angle(line) - MATH_CONST.PI_OVER_2; + + out.x = Math.cos(a); + out.y = Math.sin(a); + + return out; +}; + +module.exports = GetNormal; + + +/***/ }), + +/***/ 13151: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Get a point on a line that's a given percentage along its length. + * + * @function Phaser.Geom.Line.GetPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The line. + * @param {number} position - A value between 0 and 1, where 0 is the start, 0.5 is the middle and 1 is the end of the line. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 object to store the coordinates of the point on the line. + * + * @return {Phaser.Math.Vector2} The point on the line. + */ +var GetPoint = function (line, position, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = line.x1 + (line.x2 - line.x1) * position; + out.y = line.y1 + (line.y2 - line.y1) * position; + + return out; +}; + +module.exports = GetPoint; + + +/***/ }), + +/***/ 15258: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Length = __webpack_require__(35001); +var Vector2 = __webpack_require__(26099); + +/** + * Get a number of points along a line's length. + * + * Provide a `quantity` to get an exact number of points along the line. + * + * Provide a `stepRate` to ensure a specific distance between each point on the line. Set `quantity` to `0` when + * providing a `stepRate`. + * + * See also `GetEasedPoints` for a way to distribute the points across the line according to an ease type or input function. + * + * @function Phaser.Geom.Line.GetPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The line. + * @param {number} quantity - The number of points to place on the line. Set to `0` to use `stepRate` instead. + * @param {number} [stepRate] - The distance between each point on the line. When set, `quantity` is implied and should be set to `0`. + * @param {Phaser.Math.Vector2[]} [out] - An optional array of Vector2 objects to store the coordinates of the points on the line. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects containing the coordinates of the points on the line. + */ +var GetPoints = function (line, quantity, stepRate, out) +{ + if (out === undefined) { out = []; } + + // If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!quantity && stepRate > 0) + { + quantity = Length(line) / stepRate; + } + + var x1 = line.x1; + var y1 = line.y1; + + var x2 = line.x2; + var y2 = line.y2; + + for (var i = 0; i < quantity; i++) + { + var position = i / quantity; + + var x = x1 + (x2 - x1) * position; + var y = y1 + (y2 - y1) * position; + + out.push(new Vector2(x, y)); + } + + return out; +}; + +module.exports = GetPoints; + + +/***/ }), + +/***/ 26408: +/***/ ((module) => { + +/** + * @author Richard Davey + * @author Florian Mertens + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Get the shortest distance from a Line to the given Point. + * + * @function Phaser.Geom.Line.GetShortestDistance + * @since 3.16.0 + * + * @param {Phaser.Geom.Line} line - The line to get the distance from. + * @param {Phaser.Types.Math.Vector2Like} point - The point to get the shortest distance to. + * + * @return {(boolean|number)} The shortest distance from the line to the point, or `false`. + */ +var GetShortestDistance = function (line, point) +{ + var x1 = line.x1; + var y1 = line.y1; + + var x2 = line.x2; + var y2 = line.y2; + + var L2 = (((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))); + + if (L2 === 0) + { + return false; + } + + var s = (((y1 - point.y) * (x2 - x1)) - ((x1 - point.x) * (y2 - y1))) / L2; + + return Math.abs(s) * Math.sqrt(L2); +}; + +module.exports = GetShortestDistance; + + +/***/ }), + +/***/ 98770: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the height of the given line. + * + * @function Phaser.Geom.Line.Height + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the height of. + * + * @return {number} The height of the line. + */ +var Height = function (line) +{ + return Math.abs(line.y1 - line.y2); +}; + +module.exports = Height; + + +/***/ }), + +/***/ 35001: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the length of the given line. + * + * @function Phaser.Geom.Line.Length + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the length of. + * + * @return {number} The length of the line. + */ +var Length = function (line) +{ + return Math.sqrt((line.x2 - line.x1) * (line.x2 - line.x1) + (line.y2 - line.y1) * (line.y2 - line.y1)); +}; + +module.exports = Length; + + +/***/ }), + +/***/ 23031: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetPoint = __webpack_require__(13151); +var GetPoints = __webpack_require__(15258); +var GEOM_CONST = __webpack_require__(23777); +var Random = __webpack_require__(65822); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * Defines a Line segment, a part of a line between two endpoints. + * + * @class Line + * @memberof Phaser.Geom + * @constructor + * @since 3.0.0 + * + * @param {number} [x1=0] - The x coordinate of the lines starting point. + * @param {number} [y1=0] - The y coordinate of the lines starting point. + * @param {number} [x2=0] - The x coordinate of the lines ending point. + * @param {number} [y2=0] - The y coordinate of the lines ending point. + */ +var Line = new Class({ + + initialize: + + function Line (x1, y1, x2, y2) + { + if (x1 === undefined) { x1 = 0; } + if (y1 === undefined) { y1 = 0; } + if (x2 === undefined) { x2 = 0; } + if (y2 === undefined) { y2 = 0; } + + /** + * The geometry constant type of this object: `GEOM_CONST.LINE`. + * Used for fast type comparisons. + * + * @name Phaser.Geom.Line#type + * @type {number} + * @readonly + * @since 3.19.0 + */ + this.type = GEOM_CONST.LINE; + + /** + * The x coordinate of the lines starting point. + * + * @name Phaser.Geom.Line#x1 + * @type {number} + * @since 3.0.0 + */ + this.x1 = x1; + + /** + * The y coordinate of the lines starting point. + * + * @name Phaser.Geom.Line#y1 + * @type {number} + * @since 3.0.0 + */ + this.y1 = y1; + + /** + * The x coordinate of the lines ending point. + * + * @name Phaser.Geom.Line#x2 + * @type {number} + * @since 3.0.0 + */ + this.x2 = x2; + + /** + * The y coordinate of the lines ending point. + * + * @name Phaser.Geom.Line#y2 + * @type {number} + * @since 3.0.0 + */ + this.y2 = y2; + }, + + /** + * Get a point on a line that's a given percentage along its length. + * + * @method Phaser.Geom.Line#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [output,$return] + * + * @param {number} position - A value between 0 and 1, where 0 is the start, 0.5 is the middle and 1 is the end of the line. + * @param {Phaser.Math.Vector2} [output] - An optional Vector2 object to store the coordinates of the point on the line. + * + * @return {Phaser.Math.Vector2} A Vector2 object containing the coordinates of the point on the line. + */ + getPoint: function (position, output) + { + return GetPoint(this, position, output); + }, + + /** + * Get a number of points along a line's length. + * + * Provide a `quantity` to get an exact number of points along the line. + * + * Provide a `stepRate` to ensure a specific distance between each point on the line. Set `quantity` to `0` when + * providing a `stepRate`. + * + * @method Phaser.Geom.Line#getPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [output,$return] + * + * @param {number} quantity - The number of points to place on the line. Set to `0` to use `stepRate` instead. + * @param {number} [stepRate] - The distance between each point on the line. When set, `quantity` is implied and should be set to `0`. + * @param {Phaser.Math.Vector2[]} [output] - An optional array of Vector2 objects to store the coordinates of the points on the line. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects containing the coordinates of the points on the line. + */ + getPoints: function (quantity, stepRate, output) + { + return GetPoints(this, quantity, stepRate, output); + }, + + /** + * Get a random Point on the Line. + * + * @method Phaser.Geom.Line#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [point,$return] + * + * @param {Phaser.Math.Vector2} [point] - An instance of a Vector2 to be modified. + * + * @return {Phaser.Math.Vector2} A random point on the Line. + */ + getRandomPoint: function (point) + { + return Random(this, point); + }, + + /** + * Set new coordinates for the line endpoints. + * + * @method Phaser.Geom.Line#setTo + * @since 3.0.0 + * + * @param {number} [x1=0] - The x coordinate of the lines starting point. + * @param {number} [y1=0] - The y coordinate of the lines starting point. + * @param {number} [x2=0] - The x coordinate of the lines ending point. + * @param {number} [y2=0] - The y coordinate of the lines ending point. + * + * @return {this} This Line object. + */ + setTo: function (x1, y1, x2, y2) + { + if (x1 === undefined) { x1 = 0; } + if (y1 === undefined) { y1 = 0; } + if (x2 === undefined) { x2 = 0; } + if (y2 === undefined) { y2 = 0; } + + this.x1 = x1; + this.y1 = y1; + + this.x2 = x2; + this.y2 = y2; + + return this; + }, + + /** + * Sets this Line to match the x/y coordinates of the two given Vector2Like objects. + * + * @method Phaser.Geom.Line#setFromObjects + * @since 3.70.0 + * + * @param {Phaser.Types.Math.Vector2Like} start - Any object with public `x` and `y` properties, whose values will be assigned to the x1/y1 components of this Line. + * @param {Phaser.Types.Math.Vector2Like} end - Any object with public `x` and `y` properties, whose values will be assigned to the x2/y2 components of this Line. + * + * @return {this} This Line object. + */ + setFromObjects: function (start, end) + { + this.x1 = start.x; + this.y1 = start.y; + + this.x2 = end.x; + this.y2 = end.y; + + return this; + }, + + /** + * Returns a Vector2 object that corresponds to the start of this Line. + * + * @method Phaser.Geom.Line#getPointA + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [vec2,$return] + * + * @param {Phaser.Math.Vector2} [vec2] - A Vector2 object to set the results in. If `undefined` a new Vector2 will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 object that corresponds to the start of this Line. + */ + getPointA: function (vec2) + { + if (vec2 === undefined) { vec2 = new Vector2(); } + + vec2.set(this.x1, this.y1); + + return vec2; + }, + + /** + * Returns a Vector2 object that corresponds to the end of this Line. + * + * @method Phaser.Geom.Line#getPointB + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [vec2,$return] + * + * @param {Phaser.Math.Vector2} [vec2] - A Vector2 object to set the results in. If `undefined` a new Vector2 will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 object that corresponds to the end of this Line. + */ + getPointB: function (vec2) + { + if (vec2 === undefined) { vec2 = new Vector2(); } + + vec2.set(this.x2, this.y2); + + return vec2; + }, + + /** + * The left position of the Line. + * + * @name Phaser.Geom.Line#left + * @type {number} + * @since 3.0.0 + */ + left: { + + get: function () + { + return Math.min(this.x1, this.x2); + }, + + set: function (value) + { + if (this.x1 <= this.x2) + { + this.x1 = value; + } + else + { + this.x2 = value; + } + } + + }, + + /** + * The right position of the Line. + * + * @name Phaser.Geom.Line#right + * @type {number} + * @since 3.0.0 + */ + right: { + + get: function () + { + return Math.max(this.x1, this.x2); + }, + + set: function (value) + { + if (this.x1 > this.x2) + { + this.x1 = value; + } + else + { + this.x2 = value; + } + } + + }, + + /** + * The top position of the Line. + * + * @name Phaser.Geom.Line#top + * @type {number} + * @since 3.0.0 + */ + top: { + + get: function () + { + return Math.min(this.y1, this.y2); + }, + + set: function (value) + { + if (this.y1 <= this.y2) + { + this.y1 = value; + } + else + { + this.y2 = value; + } + } + + }, + + /** + * The bottom position of the Line. + * + * @name Phaser.Geom.Line#bottom + * @type {number} + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return Math.max(this.y1, this.y2); + }, + + set: function (value) + { + if (this.y1 > this.y2) + { + this.y1 = value; + } + else + { + this.y2 = value; + } + } + + } + +}); + +module.exports = Line; + + +/***/ }), + +/***/ 64795: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = __webpack_require__(36383); +var Wrap = __webpack_require__(15994); +var Angle = __webpack_require__(91938); + +/** + * Get the angle of the normal of the given line in radians. + * + * @function Phaser.Geom.Line.NormalAngle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the angle of the normal of. + * + * @return {number} The angle of the normal of the line in radians. + */ +var NormalAngle = function (line) +{ + var angle = Angle(line) - MATH_CONST.PI_OVER_2; + + return Wrap(angle, -Math.PI, Math.PI); +}; + +module.exports = NormalAngle; + + +/***/ }), + +/***/ 52616: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = __webpack_require__(36383); +var Angle = __webpack_require__(91938); + +/** + * Returns the x component of the normal vector of the given line. + * + * @function Phaser.Geom.Line.NormalX + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The Line object to get the normal value from. + * + * @return {number} The x component of the normal vector of the line. + */ +var NormalX = function (line) +{ + return Math.cos(Angle(line) - MATH_CONST.PI_OVER_2); +}; + +module.exports = NormalX; + + +/***/ }), + +/***/ 87231: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = __webpack_require__(36383); +var Angle = __webpack_require__(91938); + +/** + * The Y value of the normal of the given line. + * The normal of a line is a vector that points perpendicular from it. + * + * @function Phaser.Geom.Line.NormalY + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the normal of. + * + * @return {number} The Y value of the normal of the Line. + */ +var NormalY = function (line) +{ + return Math.sin(Angle(line) - MATH_CONST.PI_OVER_2); +}; + +module.exports = NormalY; + + +/***/ }), + +/***/ 89662: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Offset a line by the given amount. + * + * @function Phaser.Geom.Line.Offset + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} line - The line to offset. + * @param {number} x - The horizontal offset to add to the line. + * @param {number} y - The vertical offset to add to the line. + * + * @return {Phaser.Geom.Line} The offset line. + */ +var Offset = function (line, x, y) +{ + line.x1 += x; + line.y1 += y; + + line.x2 += x; + line.y2 += y; + + return line; +}; + +module.exports = Offset; + + +/***/ }), + +/***/ 71165: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the perpendicular slope of the given line. + * + * @function Phaser.Geom.Line.PerpSlope + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the perpendicular slope of. + * + * @return {number} The perpendicular slope of the line. + */ +var PerpSlope = function (line) +{ + return -((line.x2 - line.x1) / (line.y2 - line.y1)); +}; + +module.exports = PerpSlope; + + +/***/ }), + +/***/ 65822: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a random point on a given Line. + * + * @function Phaser.Geom.Line.Random + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Line} line - The Line to calculate the random point on. + * @param {Phaser.Math.Vector2} [out] - An instance of a Vector2 to be modified. + * + * @return {Phaser.Math.Vector2} A random point on the Line stored in a Vector2. + */ +var Random = function (line, out) +{ + if (out === undefined) { out = new Vector2(); } + + var t = Math.random(); + + out.x = line.x1 + t * (line.x2 - line.x1); + out.y = line.y1 + t * (line.y2 - line.y1); + + return out; +}; + +module.exports = Random; + + +/***/ }), + +/***/ 69777: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Angle = __webpack_require__(91938); +var NormalAngle = __webpack_require__(64795); + +/** + * Calculate the reflected angle between two lines. + * + * This is the outgoing angle based on the angle of Line 1 and the normalAngle of Line 2. + * + * @function Phaser.Geom.Line.ReflectAngle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} lineA - The first line. + * @param {Phaser.Geom.Line} lineB - The second line. + * + * @return {number} The reflected angle between each line. + */ +var ReflectAngle = function (lineA, lineB) +{ + return (2 * NormalAngle(lineB) - Math.PI - Angle(lineA)); +}; + +module.exports = ReflectAngle; + + +/***/ }), + +/***/ 39706: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateAroundXY = __webpack_require__(64400); + +/** + * Rotate a line around its midpoint by the given angle in radians. + * + * @function Phaser.Geom.Line.Rotate + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} line - The line to rotate. + * @param {number} angle - The angle of rotation in radians. + * + * @return {Phaser.Geom.Line} The rotated line. + */ +var Rotate = function (line, angle) +{ + var x = (line.x1 + line.x2) / 2; + var y = (line.y1 + line.y2) / 2; + + return RotateAroundXY(line, x, y, angle); +}; + +module.exports = Rotate; + + +/***/ }), + +/***/ 82585: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateAroundXY = __webpack_require__(64400); + +/** + * Rotate a line around a point by the given angle in radians. + * + * @function Phaser.Geom.Line.RotateAroundPoint + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} line - The line to rotate. + * @param {Phaser.Math.Vector2} point - The point to rotate the line around. + * @param {number} angle - The angle of rotation in radians. + * + * @return {Phaser.Geom.Line} The rotated line. + */ +var RotateAroundPoint = function (line, point, angle) +{ + return RotateAroundXY(line, point.x, point.y, angle); +}; + +module.exports = RotateAroundPoint; + + +/***/ }), + +/***/ 64400: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rotate a line around the given coordinates by the given angle in radians. + * + * @function Phaser.Geom.Line.RotateAroundXY + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} line - The line to rotate. + * @param {number} x - The horizontal coordinate to rotate the line around. + * @param {number} y - The vertical coordinate to rotate the line around. + * @param {number} angle - The angle of rotation in radians. + * + * @return {Phaser.Geom.Line} The rotated line. + */ +var RotateAroundXY = function (line, x, y, angle) +{ + var c = Math.cos(angle); + var s = Math.sin(angle); + + var tx = line.x1 - x; + var ty = line.y1 - y; + + line.x1 = tx * c - ty * s + x; + line.y1 = tx * s + ty * c + y; + + tx = line.x2 - x; + ty = line.y2 - y; + + line.x2 = tx * c - ty * s + x; + line.y2 = tx * s + ty * c + y; + + return line; +}; + +module.exports = RotateAroundXY; + + +/***/ }), + +/***/ 62377: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Set a line to a given position, angle and length. + * + * @function Phaser.Geom.Line.SetToAngle + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} line - The line to set. + * @param {number} x - The horizontal start position of the line. + * @param {number} y - The vertical start position of the line. + * @param {number} angle - The angle of the line in radians. + * @param {number} length - The length of the line. + * + * @return {Phaser.Geom.Line} The updated line. + */ +var SetToAngle = function (line, x, y, angle, length) +{ + line.x1 = x; + line.y1 = y; + + line.x2 = x + (Math.cos(angle) * length); + line.y2 = y + (Math.sin(angle) * length); + + return line; +}; + +module.exports = SetToAngle; + + +/***/ }), + +/***/ 71366: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the slope of the given line. + * + * @function Phaser.Geom.Line.Slope + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the slope of. + * + * @return {number} The slope of the line. + */ +var Slope = function (line) +{ + return (line.y2 - line.y1) / (line.x2 - line.x1); +}; + +module.exports = Slope; + + +/***/ }), + +/***/ 10809: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the width of the given line. + * + * @function Phaser.Geom.Line.Width + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line to calculate the width of. + * + * @return {number} The width of the line. + */ +var Width = function (line) +{ + return Math.abs(line.x1 - line.x2); +}; + +module.exports = Width; + + +/***/ }), + +/***/ 2529: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Line = __webpack_require__(23031); + +Line.Angle = __webpack_require__(91938); +Line.BresenhamPoints = __webpack_require__(84993); +Line.CenterOn = __webpack_require__(36469); +Line.Clone = __webpack_require__(31116); +Line.CopyFrom = __webpack_require__(59944); +Line.Equals = __webpack_require__(59220); +Line.Extend = __webpack_require__(78177); +Line.GetEasedPoints = __webpack_require__(26708); +Line.GetMidPoint = __webpack_require__(32125); +Line.GetNearestPoint = __webpack_require__(99569); +Line.GetNormal = __webpack_require__(34638); +Line.GetPoint = __webpack_require__(13151); +Line.GetPoints = __webpack_require__(15258); +Line.GetShortestDistance = __webpack_require__(26408); +Line.Height = __webpack_require__(98770); +Line.Length = __webpack_require__(35001); +Line.NormalAngle = __webpack_require__(64795); +Line.NormalX = __webpack_require__(52616); +Line.NormalY = __webpack_require__(87231); +Line.Offset = __webpack_require__(89662); +Line.PerpSlope = __webpack_require__(71165); +Line.Random = __webpack_require__(65822); +Line.ReflectAngle = __webpack_require__(69777); +Line.Rotate = __webpack_require__(39706); +Line.RotateAroundPoint = __webpack_require__(82585); +Line.RotateAroundXY = __webpack_require__(64400); +Line.SetToAngle = __webpack_require__(62377); +Line.Slope = __webpack_require__(71366); +Line.Width = __webpack_require__(10809); + +module.exports = Line; + + +/***/ }), + +/***/ 12306: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Polygon = __webpack_require__(25717); + +/** + * Create a new polygon which is a copy of the specified polygon + * + * @function Phaser.Geom.Polygon.Clone + * @since 3.0.0 + * + * @param {Phaser.Geom.Polygon} polygon - The polygon to create a clone of + * + * @return {Phaser.Geom.Polygon} A new separate Polygon cloned from the specified polygon, based on the same points. + */ +var Clone = function (polygon) +{ + return new Polygon(polygon.points); +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 63814: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Checks whether the x and y coordinates are contained within this polygon. +// Adapted from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html by Jonas Raoni Soares Silva + +/** + * Checks if a point is within the bounds of a Polygon. + * + * @function Phaser.Geom.Polygon.Contains + * @since 3.0.0 + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon to check against. + * @param {number} x - The X coordinate of the point to check. + * @param {number} y - The Y coordinate of the point to check. + * + * @return {boolean} `true` if the point is within the bounds of the Polygon, otherwise `false`. + */ +var Contains = function (polygon, x, y) +{ + var inside = false; + + for (var i = -1, j = polygon.points.length - 1; ++i < polygon.points.length; j = i) + { + var ix = polygon.points[i].x; + var iy = polygon.points[i].y; + + var jx = polygon.points[j].x; + var jy = polygon.points[j].y; + + if (((iy <= y && y < jy) || (jy <= y && y < iy)) && (x < (jx - ix) * (y - iy) / (jy - iy) + ix)) + { + inside = !inside; + } + } + + return inside; +}; + +module.exports = Contains; + + +/***/ }), + +/***/ 99338: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(63814); + +/** + * Checks the given Point again the Polygon to see if the Point lays within its vertices. + * + * @function Phaser.Geom.Polygon.ContainsPoint + * @since 3.0.0 + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon to check. + * @param {Phaser.Math.Vector2} vec - The Vector2 point to check if it's within the Polygon. + * + * @return {boolean} `true` if the point is within the Polygon, otherwise `false`. + */ +var ContainsPoint = function (polygon, vec) +{ + return Contains(polygon, vec.x, vec.y); +}; + +module.exports = ContainsPoint; + + +/***/ }), + +/***/ 94811: +/***/ ((module) => { + +"use strict"; +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * This module implements a modified ear slicing algorithm, optimized by z-order curve hashing and extended to + * handle holes, twisted polygons, degeneracies and self-intersections in a way that doesn't guarantee correctness + * of triangulation, but attempts to always produce acceptable results for practical data. + * + * Example: + * + * ```javascript + * const triangles = Phaser.Geom.Polygon.Earcut([10,0, 0,50, 60,60, 70,10]); // returns [1,0,3, 3,2,1] + * ``` + * + * Each group of three vertex indices in the resulting array forms a triangle. + * + * ```javascript + * // triangulating a polygon with a hole + * earcut([0,0, 100,0, 100,100, 0,100, 20,20, 80,20, 80,80, 20,80], [4]); + * // [3,0,4, 5,4,0, 3,4,7, 5,0,1, 2,3,7, 6,5,1, 2,7,6, 6,1,2] + * + * // triangulating a polygon with 3d coords + * earcut([10,0,1, 0,50,2, 60,60,3, 70,10,4], null, 3); + * // [1,0,3, 3,2,1] + * ``` + * + * If you pass a single vertex as a hole, Earcut treats it as a Steiner point. + * + * If your input is a multi-dimensional array (e.g. GeoJSON Polygon), you can convert it to the format + * expected by Earcut with `Phaser.Geom.Polygon.Earcut.flatten`: + * + * ```javascript + * var data = earcut.flatten(geojson.geometry.coordinates); + * var triangles = earcut(data.vertices, data.holes, data.dimensions); + * ``` + * + * After getting a triangulation, you can verify its correctness with `Phaser.Geom.Polygon.Earcut.deviation`: + * + * ```javascript + * var deviation = earcut.deviation(vertices, holes, dimensions, triangles); + * ``` + * Returns the relative difference between the total area of triangles and the area of the input polygon. + * 0 means the triangulation is fully correct. + * + * For more information see https://github.com/mapbox/earcut + * + * @function Phaser.Geom.Polygon.Earcut + * @since 3.50.0 + * + * @param {number[]} data - A flat array of vertex coordinate, like [x0,y0, x1,y1, x2,y2, ...] + * @param {number[]} [holeIndices] - An array of hole indices if any (e.g. [5, 8] for a 12-vertex input would mean one hole with vertices 5–7 and another with 8–11). + * @param {number} [dimensions=2] - The number of coordinates per vertex in the input array (2 by default). + * + * @return {number[]} An array of triangulated data. + */ + + // Earcut 2.2.4 (July 5th 2022) + +/* + * ISC License + * + * Copyright (c) 2016, Mapbox + * + * Permission to use, copy, modify, and/or distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright notice + * and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + * THIS SOFTWARE. + */ + + + +function earcut(data, holeIndices, dim) { + + dim = dim || 2; + + var hasHoles = holeIndices && holeIndices.length, + outerLen = hasHoles ? holeIndices[0] * dim : data.length, + outerNode = linkedList(data, 0, outerLen, dim, true), + triangles = []; + + if (!outerNode || outerNode.next === outerNode.prev) return triangles; + + var minX, minY, maxX, maxY, x, y, invSize; + + if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + if (data.length > 80 * dim) { + minX = maxX = data[0]; + minY = maxY = data[1]; + + for (var i = dim; i < outerLen; i += dim) { + x = data[i]; + y = data[i + 1]; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + + // minX, minY and invSize are later used to transform coords into integers for z-order calculation + invSize = Math.max(maxX - minX, maxY - minY); + invSize = invSize !== 0 ? 32767 / invSize : 0; + } + + earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0); + + return triangles; +} + +// create a circular doubly linked list from polygon points in the specified winding order +function linkedList(data, start, end, dim, clockwise) { + var i, last; + + if (clockwise === (signedArea(data, start, end, dim) > 0)) { + for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); + } else { + for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); + } + + if (last && equals(last, last.next)) { + removeNode(last); + last = last.next; + } + + return last; +} + +// eliminate colinear or duplicate points +function filterPoints(start, end) { + if (!start) return start; + if (!end) end = start; + + var p = start, + again; + do { + again = false; + + if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + removeNode(p); + p = end = p.prev; + if (p === p.next) break; + again = true; + + } else { + p = p.next; + } + } while (again || p !== end); + + return end; +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) { + if (!ear) return; + + // interlink polygon nodes in z-order + if (!pass && invSize) indexCurve(ear, minX, minY, invSize); + + var stop = ear, + prev, next; + + // iterate through ears, slicing them one by one + while (ear.prev !== ear.next) { + prev = ear.prev; + next = ear.next; + + if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) { + // cut off the triangle + triangles.push(prev.i / dim | 0); + triangles.push(ear.i / dim | 0); + triangles.push(next.i / dim | 0); + + removeNode(ear); + + // skipping the next vertex leads to less sliver triangles + ear = next.next; + stop = next.next; + + continue; + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if (ear === stop) { + // try filtering points and slicing again + if (!pass) { + earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); + + // if this didn't work, try curing all small self-intersections locally + } else if (pass === 1) { + ear = cureLocalIntersections(filterPoints(ear), triangles, dim); + earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); + + // as a last resort, try splitting the remaining polygon into two + } else if (pass === 2) { + splitEarcut(ear, triangles, dim, minX, minY, invSize); + } + + break; + } + } +} + +// check whether a polygon node forms a valid ear with adjacent nodes +function isEar(ear) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; + + // triangle bbox; min & max are calculated like this for speed + var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx), + y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy), + x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx), + y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy); + + var p = c.next; + while (p !== a) { + if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && + pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.next; + } + + return true; +} + +function isEarHashed(ear, minX, minY, invSize) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + var ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; + + // triangle bbox; min & max are calculated like this for speed + var x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx), + y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy), + x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx), + y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy); + + // z-order range for the current triangle bbox; + var minZ = zOrder(x0, y0, minX, minY, invSize), + maxZ = zOrder(x1, y1, minX, minY, invSize); + + var p = ear.prevZ, + n = ear.nextZ; + + // look for points inside the triangle in both directions + while (p && p.z >= minZ && n && n.z <= maxZ) { + if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && + pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + + if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && + pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false; + n = n.nextZ; + } + + // look for remaining points in decreasing z-order + while (p && p.z >= minZ) { + if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && + pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + } + + // look for remaining points in increasing z-order + while (n && n.z <= maxZ) { + if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && + pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false; + n = n.nextZ; + } + + return true; +} + +// go through all polygon nodes and cure small local self-intersections +function cureLocalIntersections(start, triangles, dim) { + var p = start; + do { + var a = p.prev, + b = p.next.next; + + if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { + + triangles.push(a.i / dim | 0); + triangles.push(p.i / dim | 0); + triangles.push(b.i / dim | 0); + + // remove two nodes involved + removeNode(p); + removeNode(p.next); + + p = start = b; + } + p = p.next; + } while (p !== start); + + return filterPoints(p); +} + +// try splitting polygon into two and triangulate them independently +function splitEarcut(start, triangles, dim, minX, minY, invSize) { + // look for a valid diagonal that divides the polygon into two + var a = start; + do { + var b = a.next.next; + while (b !== a.prev) { + if (a.i !== b.i && isValidDiagonal(a, b)) { + // split the polygon in two by the diagonal + var c = splitPolygon(a, b); + + // filter colinear points around the cuts + a = filterPoints(a, a.next); + c = filterPoints(c, c.next); + + // run earcut on each half + earcutLinked(a, triangles, dim, minX, minY, invSize, 0); + earcutLinked(c, triangles, dim, minX, minY, invSize, 0); + return; + } + b = b.next; + } + a = a.next; + } while (a !== start); +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +function eliminateHoles(data, holeIndices, outerNode, dim) { + var queue = [], + i, len, start, end, list; + + for (i = 0, len = holeIndices.length; i < len; i++) { + start = holeIndices[i] * dim; + end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + list = linkedList(data, start, end, dim, false); + if (list === list.next) list.steiner = true; + queue.push(getLeftmost(list)); + } + + queue.sort(compareX); + + // process holes from left to right + for (i = 0; i < queue.length; i++) { + outerNode = eliminateHole(queue[i], outerNode); + } + + return outerNode; +} + +function compareX(a, b) { + return a.x - b.x; +} + +// find a bridge between vertices that connects hole with an outer ring and and link it +function eliminateHole(hole, outerNode) { + var bridge = findHoleBridge(hole, outerNode); + if (!bridge) { + return outerNode; + } + + var bridgeReverse = splitPolygon(bridge, hole); + + // filter collinear points around the cuts + filterPoints(bridgeReverse, bridgeReverse.next); + return filterPoints(bridge, bridge.next); +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +function findHoleBridge(hole, outerNode) { + var p = outerNode, + hx = hole.x, + hy = hole.y, + qx = -Infinity, + m; + + // find a segment intersected by a ray from the hole's leftmost point to the left; + // segment's endpoint with lesser x will be potential connection point + do { + if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { + var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); + if (x <= hx && x > qx) { + qx = x; + m = p.x < p.next.x ? p : p.next; + if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint + } + } + p = p.next; + } while (p !== outerNode); + + if (!m) return null; + + // look for points inside the triangle of hole point, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the point of the minimum angle with the ray as connection point + + var stop = m, + mx = m.x, + my = m.y, + tanMin = Infinity, + tan; + + p = m; + + do { + if (hx >= p.x && p.x >= mx && hx !== p.x && + pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { + + tan = Math.abs(hy - p.y) / (hx - p.x); // tangential + + if (locallyInside(p, hole) && + (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) { + m = p; + tanMin = tan; + } + } + + p = p.next; + } while (p !== stop); + + return m; +} + +// whether sector in vertex m contains sector in vertex p in the same coordinates +function sectorContainsSector(m, p) { + return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0; +} + +// interlink polygon nodes in z-order +function indexCurve(start, minX, minY, invSize) { + var p = start; + do { + if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + } while (p !== start); + + p.prevZ.nextZ = null; + p.prevZ = null; + + sortLinked(p); +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +function sortLinked(list) { + var i, p, q, e, tail, numMerges, pSize, qSize, + inSize = 1; + + do { + p = list; + list = null; + tail = null; + numMerges = 0; + + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q.nextZ; + if (!q) break; + } + qSize = inSize; + + while (pSize > 0 || (qSize > 0 && q)) { + + if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { + e = p; + p = p.nextZ; + pSize--; + } else { + e = q; + q = q.nextZ; + qSize--; + } + + if (tail) tail.nextZ = e; + else list = e; + + e.prevZ = tail; + tail = e; + } + + p = q; + } + + tail.nextZ = null; + inSize *= 2; + + } while (numMerges > 1); + + return list; +} + +// z-order of a point given coords and inverse of the longer side of data bbox +function zOrder(x, y, minX, minY, invSize) { + // coords are transformed into non-negative 15-bit integer range + x = (x - minX) * invSize | 0; + y = (y - minY) * invSize | 0; + + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +// find the leftmost node of a polygon ring +function getLeftmost(start) { + var p = start, + leftmost = start; + do { + if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p; + p = p.next; + } while (p !== start); + + return leftmost; +} + +// check if a point lies within a convex triangle +function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { + return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && + (ax - px) * (by - py) >= (bx - px) * (ay - py) && + (bx - px) * (cy - py) >= (cx - px) * (by - py); +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +function isValidDiagonal(a, b) { + return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges + (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible + (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors + equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case +} + +// signed area of a triangle +function area(p, q, r) { + return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); +} + +// check if two points are equal +function equals(p1, p2) { + return p1.x === p2.x && p1.y === p2.y; +} + +// check if two segments intersect +function intersects(p1, q1, p2, q2) { + var o1 = sign(area(p1, q1, p2)); + var o2 = sign(area(p1, q1, q2)); + var o3 = sign(area(p2, q2, p1)); + var o4 = sign(area(p2, q2, q1)); + + if (o1 !== o2 && o3 !== o4) return true; // general case + + if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 + if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 + if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 + if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 + + return false; +} + +// for collinear points p, q, r, check if point q lies on segment pr +function onSegment(p, q, r) { + return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y); +} + +function sign(num) { + return num > 0 ? 1 : num < 0 ? -1 : 0; +} + +// check if a polygon diagonal intersects any polygon segments +function intersectsPolygon(a, b) { + var p = a; + do { + if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && + intersects(p, p.next, a, b)) return true; + p = p.next; + } while (p !== a); + + return false; +} + +// check if a polygon diagonal is locally inside the polygon +function locallyInside(a, b) { + return area(a.prev, a, a.next) < 0 ? + area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : + area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; +} + +// check if the middle point of a polygon diagonal is inside the polygon +function middleInside(a, b) { + var p = a, + inside = false, + px = (a.x + b.x) / 2, + py = (a.y + b.y) / 2; + do { + if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y && + (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) + inside = !inside; + p = p.next; + } while (p !== a); + + return inside; +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; +// if one belongs to the outer ring and another to a hole, it merges it into a single ring +function splitPolygon(a, b) { + var a2 = new Node(a.i, a.x, a.y), + b2 = new Node(b.i, b.x, b.y), + an = a.next, + bp = b.prev; + + a.next = b; + b.prev = a; + + a2.next = an; + an.prev = a2; + + b2.next = a2; + a2.prev = b2; + + bp.next = b2; + b2.prev = bp; + + return b2; +} + +// create a node and optionally link it with previous one (in a circular doubly linked list) +function insertNode(i, x, y, last) { + var p = new Node(i, x, y); + + if (!last) { + p.prev = p; + p.next = p; + + } else { + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + } + return p; +} + +function removeNode(p) { + p.next.prev = p.prev; + p.prev.next = p.next; + + if (p.prevZ) p.prevZ.nextZ = p.nextZ; + if (p.nextZ) p.nextZ.prevZ = p.prevZ; +} + +function Node(i, x, y) { + // vertex index in coordinates array + this.i = i; + + // vertex coordinates + this.x = x; + this.y = y; + + // previous and next vertex nodes in a polygon ring + this.prev = null; + this.next = null; + + // z-order curve value + this.z = 0; + + // previous and next nodes in z-order + this.prevZ = null; + this.nextZ = null; + + // indicates whether this is a steiner point + this.steiner = false; +} + +// return a percentage difference between the polygon area and its triangulation area; +// used to verify correctness of triangulation +earcut.deviation = function (data, holeIndices, dim, triangles) { + var hasHoles = holeIndices && holeIndices.length; + var outerLen = hasHoles ? holeIndices[0] * dim : data.length; + + var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim)); + if (hasHoles) { + for (var i = 0, len = holeIndices.length; i < len; i++) { + var start = holeIndices[i] * dim; + var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + polygonArea -= Math.abs(signedArea(data, start, end, dim)); + } + } + + var trianglesArea = 0; + for (i = 0; i < triangles.length; i += 3) { + var a = triangles[i] * dim; + var b = triangles[i + 1] * dim; + var c = triangles[i + 2] * dim; + trianglesArea += Math.abs( + (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - + (data[a] - data[b]) * (data[c + 1] - data[a + 1])); + } + + return polygonArea === 0 && trianglesArea === 0 ? 0 : + Math.abs((trianglesArea - polygonArea) / polygonArea); +}; + +function signedArea(data, start, end, dim) { + var sum = 0; + for (var i = start, j = end - dim; i < end; i += dim) { + sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); + j = i; + } + return sum; +} + +// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts +earcut.flatten = function (data) { + var dim = data[0][0].length, + result = {vertices: [], holes: [], dimensions: dim}, + holeIndex = 0; + + for (var i = 0; i < data.length; i++) { + for (var j = 0; j < data[i].length; j++) { + for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]); + } + if (i > 0) { + holeIndex += data[i - 1].length; + result.holes.push(holeIndex); + } + } + return result; +}; + +module.exports = earcut; + + +/***/ }), + +/***/ 13829: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Calculates the bounding AABB rectangle of a polygon. + * + * @function Phaser.Geom.Polygon.GetAABB + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {Phaser.Geom.Polygon} polygon - The polygon that should be calculated. + * @param {(Phaser.Geom.Rectangle|object)} [out] - The rectangle or object that has x, y, width, and height properties to store the result. Optional. + * + * @return {(Phaser.Geom.Rectangle|object)} The resulting rectangle or object that is passed in with position and dimensions of the polygon's AABB. + */ +var GetAABB = function (polygon, out) +{ + if (out === undefined) { out = new Rectangle(); } + + var minX = Infinity; + var minY = Infinity; + var maxX = -minX; + var maxY = -minY; + var p; + + for (var i = 0; i < polygon.points.length; i++) + { + p = polygon.points[i]; + + minX = Math.min(minX, p.x); + minY = Math.min(minY, p.y); + maxX = Math.max(maxX, p.x); + maxY = Math.max(maxY, p.y); + } + + out.x = minX; + out.y = minY; + out.width = maxX - minX; + out.height = maxY - minY; + + return out; +}; + +module.exports = GetAABB; + + +/***/ }), + +/***/ 26173: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Export the points as an array of flat numbers, following the sequence [ x,y, x,y, x,y ] + +/** + * Stores all of the points of a Polygon into a flat array of numbers following the sequence [ x,y, x,y, x,y ], + * i.e. each point of the Polygon, in the order it's defined, corresponds to two elements of the resultant + * array for the point's X and Y coordinate. + * + * @function Phaser.Geom.Polygon.GetNumberArray + * @since 3.0.0 + * + * @generic {number[]} O - [output,$return] + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon whose points to export. + * @param {(array|number[])} [output] - An array to which the points' coordinates should be appended. + * + * @return {(array|number[])} The modified `output` array, or a new array if none was given. + */ +var GetNumberArray = function (polygon, output) +{ + if (output === undefined) { output = []; } + + for (var i = 0; i < polygon.points.length; i++) + { + output.push(polygon.points[i].x); + output.push(polygon.points[i].y); + } + + return output; +}; + +module.exports = GetNumberArray; + + +/***/ }), + +/***/ 9564: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Length = __webpack_require__(35001); +var Line = __webpack_require__(23031); +var Perimeter = __webpack_require__(30052); + +/** + * Returns an array of Vector2 objects containing the coordinates of the points around the perimeter of the Polygon, + * based on the given quantity or stepRate values. + * + * @function Phaser.Geom.Polygon.GetPoints + * @since 3.12.0 + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon to get the points from. + * @param {number} quantity - The amount of points to return. If a falsey value the quantity will be derived from the `stepRate` instead. + * @param {number} [stepRate] - Sets the quantity by getting the perimeter of the Polygon and dividing it by the stepRate. + * @param {array} [output] - An array to insert the points in to. If not provided a new array will be created. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects pertaining to the points around the perimeter of the Polygon. + */ +var GetPoints = function (polygon, quantity, stepRate, out) +{ + if (out === undefined) { out = []; } + + var points = polygon.points; + var perimeter = Perimeter(polygon); + + // If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!quantity && stepRate > 0) + { + quantity = perimeter / stepRate; + } + + for (var i = 0; i < quantity; i++) + { + var position = perimeter * (i / quantity); + var accumulatedPerimeter = 0; + + for (var j = 0; j < points.length; j++) + { + var pointA = points[j]; + var pointB = points[(j + 1) % points.length]; + var line = new Line( + pointA.x, + pointA.y, + pointB.x, + pointB.y + ); + var length = Length(line); + + if (position < accumulatedPerimeter || position > accumulatedPerimeter + length) + { + accumulatedPerimeter += length; + continue; + } + + var point = line.getPoint((position - accumulatedPerimeter) / length); + out.push(point); + + break; + } + } + + return out; +}; + +module.exports = GetPoints; + + +/***/ }), + +/***/ 30052: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Length = __webpack_require__(35001); +var Line = __webpack_require__(23031); + +/** + * Returns the perimeter of the given Polygon. + * + * @function Phaser.Geom.Polygon.Perimeter + * @since 3.12.0 + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon to get the perimeter of. + * + * @return {number} The perimeter of the Polygon. + */ +var Perimeter = function (polygon) +{ + var points = polygon.points; + var perimeter = 0; + + for (var i = 0; i < points.length; i++) + { + var pointA = points[i]; + var pointB = points[(i + 1) % points.length]; + var line = new Line( + pointA.x, + pointA.y, + pointB.x, + pointB.y + ); + + perimeter += Length(line); + } + + return perimeter; +}; + +module.exports = Perimeter; + + +/***/ }), + +/***/ 25717: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Contains = __webpack_require__(63814); +var GetPoints = __webpack_require__(9564); +var GEOM_CONST = __webpack_require__(23777); + +/** + * @classdesc + * A Polygon object + * + * The polygon is a closed shape consists of a series of connected straight lines defined by list of ordered points. + * Several formats are supported to define the list of points, check the setTo method for details. + * This is a geometry object allowing you to define and inspect the shape. + * It is not a Game Object, in that you cannot add it to the display list, and it has no texture. + * To render a Polygon you should look at the capabilities of the Graphics class. + * + * @class Polygon + * @memberof Phaser.Geom + * @constructor + * @since 3.0.0 + * + * @param {(string|number[]|Phaser.Types.Math.Vector2Like[])} [points] - List of points defining the perimeter of this Polygon. Several formats are supported: + * - A string containing paired x y values separated by a single space: `'40 0 40 20 100 20 100 80 40 80 40 100 0 50'` + * - An array of Point objects: `[new Phaser.Point(x1, y1), ...]` + * - An array of objects with public x y properties: `[obj1, obj2, ...]` + * - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]` + * - An array of arrays with two elements representing x/y coordinates: `[[x1, y1], [x2, y2], ...]` + */ +var Polygon = new Class({ + + initialize: + + function Polygon (points) + { + /** + * The geometry constant type of this object: `GEOM_CONST.POLYGON`. + * Used for fast type comparisons. + * + * @name Phaser.Geom.Polygon#type + * @type {number} + * @readonly + * @since 3.19.0 + */ + this.type = GEOM_CONST.POLYGON; + + /** + * The area of this Polygon. + * + * @name Phaser.Geom.Polygon#area + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.area = 0; + + /** + * An array of number pair objects that make up this polygon. I.e. [ {x,y}, {x,y}, {x,y} ] + * + * @name Phaser.Geom.Polygon#points + * @type {Phaser.Math.Vector2[]} + * @since 3.0.0 + */ + this.points = []; + + if (points) + { + this.setTo(points); + } + }, + + /** + * Check to see if the Polygon contains the given x / y coordinates. + * + * @method Phaser.Geom.Polygon#contains + * @since 3.0.0 + * + * @param {number} x - The x coordinate to check within the polygon. + * @param {number} y - The y coordinate to check within the polygon. + * + * @return {boolean} `true` if the coordinates are within the polygon, otherwise `false`. + */ + contains: function (x, y) + { + return Contains(this, x, y); + }, + + /** + * Sets this Polygon to the given points. + * + * The points can be set from a variety of formats: + * + * - A string containing paired values separated by a single space: `'40 0 40 20 100 20 100 80 40 80 40 100 0 50'` + * - An array of Point objects: `[new Phaser.Point(x1, y1), ...]` + * - An array of objects with public x/y properties: `[obj1, obj2, ...]` + * - An array of paired numbers that represent point coordinates: `[x1,y1, x2,y2, ...]` + * - An array of arrays with two elements representing x/y coordinates: `[[x1, y1], [x2, y2], ...]` + * + * `setTo` may also be called without any arguments to remove all points. + * + * @method Phaser.Geom.Polygon#setTo + * @since 3.0.0 + * + * @param {(string|number[]|Phaser.Types.Math.Vector2Like[])} [points] - Points defining the perimeter of this polygon. Please check function description above for the different supported formats. + * + * @return {this} This Polygon object. + */ + setTo: function (points) + { + this.area = 0; + this.points = []; + + if (typeof points === 'string') + { + points = points.split(' '); + } + + if (!Array.isArray(points)) + { + return this; + } + + var p; + + // The points argument is an array, so iterate through it + for (var i = 0; i < points.length; i++) + { + p = { x: 0, y: 0 }; + + if (typeof points[i] === 'number' || typeof points[i] === 'string') + { + p.x = parseFloat(points[i]); + p.y = parseFloat(points[i + 1]); + i++; + } + else if (Array.isArray(points[i])) + { + // An array of arrays? + p.x = points[i][0]; + p.y = points[i][1]; + } + else + { + p.x = points[i].x; + p.y = points[i].y; + } + + this.points.push(p); + } + + this.calculateArea(); + + return this; + }, + + /** + * Calculates the area of the Polygon. This is available in the property Polygon.area + * + * @method Phaser.Geom.Polygon#calculateArea + * @since 3.0.0 + * + * @return {number} The area of the polygon. + */ + calculateArea: function () + { + if (this.points.length < 3) + { + this.area = 0; + + return this.area; + } + + var sum = 0; + var p1; + var p2; + + for (var i = 0; i < this.points.length - 1; i++) + { + p1 = this.points[i]; + p2 = this.points[i + 1]; + + sum += (p2.x - p1.x) * (p1.y + p2.y); + } + + p1 = this.points[0]; + p2 = this.points[this.points.length - 1]; + + sum += (p1.x - p2.x) * (p2.y + p1.y); + + this.area = -sum * 0.5; + + return this.area; + }, + + /** + * Returns an array of Vector2 objects containing the coordinates of the points around the perimeter of the Polygon, + * based on the given quantity or stepRate values. + * + * @method Phaser.Geom.Polygon#getPoints + * @since 3.12.0 + * + * @generic {Phaser.Math.Vector2[]} O - [output,$return] + * + * @param {number} quantity - The amount of points to return. If a falsey value the quantity will be derived from the `stepRate` instead. + * @param {number} [stepRate] - Sets the quantity by getting the perimeter of the Polygon and dividing it by the stepRate. + * @param {Phaser.Math.Vector2[]} [output] - An array to insert the points in to. If not provided a new array will be created. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 objects pertaining to the points around the perimeter of the Polygon. + */ + getPoints: function (quantity, step, output) + { + return GetPoints(this, quantity, step, output); + } + +}); + +module.exports = Polygon; + + +/***/ }), + +/***/ 8133: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Reverses the order of the points of a Polygon. + * + * @function Phaser.Geom.Polygon.Reverse + * @since 3.0.0 + * + * @generic {Phaser.Geom.Polygon} O - [polygon,$return] + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon to modify. + * + * @return {Phaser.Geom.Polygon} The modified Polygon. + */ +var Reverse = function (polygon) +{ + polygon.points.reverse(); + + return polygon; +}; + +module.exports = Reverse; + + +/***/ }), + +/***/ 29524: +/***/ ((module) => { + +/** + * @author Richard Davey + * @author Vladimir Agafonkin + * @see Based on Simplify.js mourner.github.io/simplify-js + */ + +/** + * Copyright (c) 2017, Vladimir Agafonkin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND 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 THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @ignore + */ +function getSqDist (p1, p2) +{ + var dx = p1.x - p2.x, + dy = p1.y - p2.y; + + return dx * dx + dy * dy; +} + +/** + * Square distance from a point to a segment + * + * @ignore + */ +function getSqSegDist (p, p1, p2) +{ + var x = p1.x, + y = p1.y, + dx = p2.x - x, + dy = p2.y - y; + + if (dx !== 0 || dy !== 0) + { + var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy); + + if (t > 1) + { + x = p2.x; + y = p2.y; + } + else if (t > 0) + { + x += dx * t; + y += dy * t; + } + } + + dx = p.x - x; + dy = p.y - y; + + return dx * dx + dy * dy; +} + +/** + * Basic distance-based simplification + * + * @ignore + */ +function simplifyRadialDist (points, sqTolerance) +{ + var prevPoint = points[0], + newPoints = [ prevPoint ], + point; + + for (var i = 1, len = points.length; i < len; i++) + { + point = points[i]; + + if (getSqDist(point, prevPoint) > sqTolerance) + { + newPoints.push(point); + prevPoint = point; + } + } + + if (prevPoint !== point) + { + newPoints.push(point); + } + + return newPoints; +} + +/** + * @ignore + */ +function simplifyDPStep (points, first, last, sqTolerance, simplified) +{ + var maxSqDist = sqTolerance, + index; + + for (var i = first + 1; i < last; i++) + { + var sqDist = getSqSegDist(points[i], points[first], points[last]); + + if (sqDist > maxSqDist) + { + index = i; + maxSqDist = sqDist; + } + } + + if (maxSqDist > sqTolerance) + { + if (index - first > 1) + { + simplifyDPStep(points, first, index, sqTolerance, simplified); + } + + simplified.push(points[index]); + + if (last - index > 1) + { + simplifyDPStep(points, index, last, sqTolerance, simplified); + } + } +} + +/** + * Simplification using Ramer-Douglas-Peucker algorithm + * + * @ignore + */ +function simplifyDouglasPeucker (points, sqTolerance) +{ + var last = points.length - 1; + + var simplified = [ points[0] ]; + + simplifyDPStep(points, 0, last, sqTolerance, simplified); + + simplified.push(points[last]); + + return simplified; +} + +/** + * Takes a Polygon object and simplifies the points by running them through a combination of + * Douglas-Peucker and Radial Distance algorithms. Simplification dramatically reduces the number of + * points in a polygon while retaining its shape, giving a huge performance boost when processing + * it and also reducing visual noise. + * + * @function Phaser.Geom.Polygon.Simplify + * @since 3.50.0 + * + * @generic {Phaser.Geom.Polygon} O - [polygon,$return] + * + * @param {Phaser.Geom.Polygon} polygon - The polygon to be simplified. The polygon will be modified in-place and returned. + * @param {number} [tolerance=1] - Affects the amount of simplification (in the same metric as the point coordinates). + * @param {boolean} [highestQuality=false] - Excludes distance-based preprocessing step which leads to highest quality simplification but runs ~10-20 times slower. + * + * @return {Phaser.Geom.Polygon} The input polygon. + */ +var Simplify = function (polygon, tolerance, highestQuality) +{ + if (tolerance === undefined) { tolerance = 1; } + if (highestQuality === undefined) { highestQuality = false; } + + var points = polygon.points; + + if (points.length > 2) + { + var sqTolerance = tolerance * tolerance; + + if (!highestQuality) + { + points = simplifyRadialDist(points, sqTolerance); + } + + polygon.setTo(simplifyDouglasPeucker(points, sqTolerance)); + } + + return polygon; +}; + +module.exports = Simplify; + + +/***/ }), + +/***/ 5469: +/***/ ((module) => { + +/** + * @author Richard Davey + * @author Igor Ognichenko + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @ignore + */ +var copy = function (out, a) +{ + out[0] = a[0]; + out[1] = a[1]; + + return out; +}; + +/** + * Takes a Polygon object and applies Chaikin's smoothing algorithm on its points. + * + * @function Phaser.Geom.Polygon.Smooth + * @since 3.13.0 + * + * @generic {Phaser.Geom.Polygon} O - [polygon,$return] + * + * @param {Phaser.Geom.Polygon} polygon - The polygon to be smoothed. The polygon will be modified in-place and returned. + * + * @return {Phaser.Geom.Polygon} The input polygon. + */ +var Smooth = function (polygon) +{ + var i; + var points = []; + var data = polygon.points; + + for (i = 0; i < data.length; i++) + { + points.push([ data[i].x, data[i].y ]); + } + + var output = []; + + if (points.length > 0) + { + output.push(copy([ 0, 0 ], points[0])); + } + + for (i = 0; i < points.length - 1; i++) + { + var p0 = points[i]; + var p1 = points[i + 1]; + var p0x = p0[0]; + var p0y = p0[1]; + var p1x = p1[0]; + var p1y = p1[1]; + + output.push([ 0.85 * p0x + 0.15 * p1x, 0.85 * p0y + 0.15 * p1y ]); + output.push([ 0.15 * p0x + 0.85 * p1x, 0.15 * p0y + 0.85 * p1y ]); + } + + if (points.length > 1) + { + output.push(copy([ 0, 0 ], points[points.length - 1])); + } + + return polygon.setTo(output); +}; + +module.exports = Smooth; + + +/***/ }), + +/***/ 24709: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Tranlates the points of the given Polygon. + * + * @function Phaser.Geom.Polygon.Translate + * @since 3.50.0 + * + * @generic {Phaser.Geom.Polygon} O - [polygon,$return] + * + * @param {Phaser.Geom.Polygon} polygon - The Polygon to modify. + * @param {number} x - The amount to horizontally translate the points by. + * @param {number} y - The amount to vertically translate the points by. + * + * @return {Phaser.Geom.Polygon} The modified Polygon. + */ +var Translate = function (polygon, x, y) +{ + var points = polygon.points; + + for (var i = 0; i < points.length; i++) + { + points[i].x += x; + points[i].y += y; + } + + return polygon; +}; + +module.exports = Translate; + + +/***/ }), + +/***/ 58423: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Polygon = __webpack_require__(25717); + +Polygon.Clone = __webpack_require__(12306); +Polygon.Contains = __webpack_require__(63814); +Polygon.ContainsPoint = __webpack_require__(99338); +Polygon.Earcut = __webpack_require__(94811); +Polygon.GetAABB = __webpack_require__(13829); +Polygon.GetNumberArray = __webpack_require__(26173); +Polygon.GetPoints = __webpack_require__(9564); +Polygon.Perimeter = __webpack_require__(30052); +Polygon.Reverse = __webpack_require__(8133); +Polygon.Simplify = __webpack_require__(29524); +Polygon.Smooth = __webpack_require__(5469); +Polygon.Translate = __webpack_require__(24709); + +module.exports = Polygon; + + +/***/ }), + +/***/ 62224: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the area of the given Rectangle object. + * + * @function Phaser.Geom.Rectangle.Area + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The rectangle to calculate the area of. + * + * @return {number} The area of the Rectangle object. + */ +var Area = function (rect) +{ + return rect.width * rect.height; +}; + +module.exports = Area; + + +/***/ }), + +/***/ 98615: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rounds a Rectangle's position up to the smallest integer greater than or equal to each current coordinate. + * + * @function Phaser.Geom.Rectangle.Ceil + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to adjust. + * + * @return {Phaser.Geom.Rectangle} The adjusted Rectangle. + */ +var Ceil = function (rect) +{ + rect.x = Math.ceil(rect.x); + rect.y = Math.ceil(rect.y); + + return rect; +}; + +module.exports = Ceil; + + +/***/ }), + +/***/ 31688: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rounds a Rectangle's position and size up to the smallest integer greater than or equal to each respective value. + * + * @function Phaser.Geom.Rectangle.CeilAll + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to modify. + * + * @return {Phaser.Geom.Rectangle} The modified Rectangle. + */ +var CeilAll = function (rect) +{ + rect.x = Math.ceil(rect.x); + rect.y = Math.ceil(rect.y); + rect.width = Math.ceil(rect.width); + rect.height = Math.ceil(rect.height); + + return rect; +}; + +module.exports = CeilAll; + + +/***/ }), + +/***/ 67502: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the top-left corner of a Rectangle so that its center is at the given coordinates. + * + * @function Phaser.Geom.Rectangle.CenterOn + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to be centered. + * @param {number} x - The X coordinate of the Rectangle's center. + * @param {number} y - The Y coordinate of the Rectangle's center. + * + * @return {Phaser.Geom.Rectangle} The centered rectangle. + */ +var CenterOn = function (rect, x, y) +{ + rect.x = x - (rect.width / 2); + rect.y = y - (rect.height / 2); + + return rect; +}; + +module.exports = CenterOn; + + +/***/ }), + +/***/ 65085: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Creates a new Rectangle which is identical to the given one. + * + * @function Phaser.Geom.Rectangle.Clone + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} source - The Rectangle to clone. + * + * @return {Phaser.Geom.Rectangle} The newly created Rectangle, which is separate from the given one. + */ +var Clone = function (source) +{ + return new Rectangle(source.x, source.y, source.width, source.height); +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 37303: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if a given point is inside a Rectangle's bounds. + * + * @function Phaser.Geom.Rectangle.Contains + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to check. + * @param {number} x - The X coordinate of the point to check. + * @param {number} y - The Y coordinate of the point to check. + * + * @return {boolean} `true` if the point is within the Rectangle's bounds, otherwise `false`. + */ +var Contains = function (rect, x, y) +{ + if (rect.width <= 0 || rect.height <= 0) + { + return false; + } + + return (rect.x <= x && rect.x + rect.width >= x && rect.y <= y && rect.y + rect.height >= y); +}; + +module.exports = Contains; + + +/***/ }), + +/***/ 96553: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(37303); + +/** + * Determines whether the specified point is contained within the rectangular region defined by this Rectangle object. + * + * @function Phaser.Geom.Rectangle.ContainsPoint + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle object. + * @param {Phaser.Math.Vector2} vec - The Vector2 object to check the coordinates of. + * + * @return {boolean} A value of true if the Rectangle object contains the specified point, otherwise false. + */ +var ContainsPoint = function (rect, vec) +{ + return Contains(rect, vec.x, vec.y); +}; + +module.exports = ContainsPoint; + + +/***/ }), + +/***/ 70273: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Tests if one rectangle fully contains another. + * + * @function Phaser.Geom.Rectangle.ContainsRect + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rectA - The first rectangle. + * @param {Phaser.Geom.Rectangle} rectB - The second rectangle. + * + * @return {boolean} True only if rectA fully contains rectB. + */ +var ContainsRect = function (rectA, rectB) +{ + // Volume check (if rectB volume > rectA then rectA cannot contain it) + if ((rectB.width * rectB.height) > (rectA.width * rectA.height)) + { + return false; + } + + return ( + (rectB.x > rectA.x && rectB.x < rectA.right) && + (rectB.right > rectA.x && rectB.right < rectA.right) && + (rectB.y > rectA.y && rectB.y < rectA.bottom) && + (rectB.bottom > rectA.y && rectB.bottom < rectA.bottom) + ); +}; + +module.exports = ContainsRect; + + +/***/ }), + +/***/ 43459: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Copy the values of one Rectangle to a destination Rectangle. + * + * @function Phaser.Geom.Rectangle.CopyFrom + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [dest,$return] + * + * @param {Phaser.Geom.Rectangle} source - The source Rectangle to copy the values from. + * @param {Phaser.Geom.Rectangle} dest - The destination Rectangle to copy the values to. + * + * @return {Phaser.Geom.Rectangle} The destination Rectangle. + */ +var CopyFrom = function (source, dest) +{ + return dest.setTo(source.x, source.y, source.width, source.height); +}; + +module.exports = CopyFrom; + + +/***/ }), + +/***/ 77493: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Create an array of points for each corner of a Rectangle + * If an array is specified, each point object will be added to the end of the array, otherwise a new array will be created. + * + * @function Phaser.Geom.Rectangle.Decompose + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle object to be decomposed. + * @param {array} [out] - If provided, each point will be added to this array. + * + * @return {array} Will return the array you specified or a new array containing the points of the Rectangle. + */ +var Decompose = function (rect, out) +{ + if (out === undefined) { out = []; } + + out.push({ x: rect.x, y: rect.y }); + out.push({ x: rect.right, y: rect.y }); + out.push({ x: rect.right, y: rect.bottom }); + out.push({ x: rect.x, y: rect.bottom }); + + return out; +}; + +module.exports = Decompose; + + +/***/ }), + +/***/ 9219: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compares the `x`, `y`, `width` and `height` properties of two rectangles. + * + * @function Phaser.Geom.Rectangle.Equals + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - Rectangle A + * @param {Phaser.Geom.Rectangle} toCompare - Rectangle B + * + * @return {boolean} `true` if the rectangles' properties are an exact match, otherwise `false`. + */ +var Equals = function (rect, toCompare) +{ + return ( + rect.x === toCompare.x && + rect.y === toCompare.y && + rect.width === toCompare.width && + rect.height === toCompare.height + ); +}; + +module.exports = Equals; + + +/***/ }), + +/***/ 53751: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetAspectRatio = __webpack_require__(8249); + +/** + * Adjusts the target rectangle, changing its width, height and position, + * so that it fits inside the area of the source rectangle, while maintaining its original + * aspect ratio. + * + * Unlike the `FitOutside` function, there may be some space inside the source area not covered. + * + * @function Phaser.Geom.Rectangle.FitInside + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [target,$return] + * + * @param {Phaser.Geom.Rectangle} target - The target rectangle to adjust. + * @param {Phaser.Geom.Rectangle} source - The source rectangle to envelop the target in. + * + * @return {Phaser.Geom.Rectangle} The modified target rectangle instance. + */ +var FitInside = function (target, source) +{ + var ratio = GetAspectRatio(target); + + if (ratio < GetAspectRatio(source)) + { + // Taller than Wide + target.setSize(source.height * ratio, source.height); + } + else + { + // Wider than Tall + target.setSize(source.width, source.width / ratio); + } + + return target.setPosition( + source.centerX - (target.width / 2), + source.centerY - (target.height / 2) + ); +}; + +module.exports = FitInside; + + +/***/ }), + +/***/ 16088: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetAspectRatio = __webpack_require__(8249); + +/** + * Adjusts the target rectangle, changing its width, height and position, + * so that it fully covers the area of the source rectangle, while maintaining its original + * aspect ratio. + * + * Unlike the `FitInside` function, the target rectangle may extend further out than the source. + * + * @function Phaser.Geom.Rectangle.FitOutside + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [target,$return] + * + * @param {Phaser.Geom.Rectangle} target - The target rectangle to adjust. + * @param {Phaser.Geom.Rectangle} source - The source rectangle to envelope the target in. + * + * @return {Phaser.Geom.Rectangle} The modified target rectangle instance. + */ +var FitOutside = function (target, source) +{ + var ratio = GetAspectRatio(target); + + if (ratio > GetAspectRatio(source)) + { + // Wider than Tall + target.setSize(source.height * ratio, source.height); + } + else + { + // Taller than Wide + target.setSize(source.width, source.width / ratio); + } + + return target.setPosition( + source.centerX - target.width / 2, + source.centerY - target.height / 2 + ); +}; + +module.exports = FitOutside; + + +/***/ }), + +/***/ 80774: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rounds down (floors) the top left X and Y coordinates of the given Rectangle to the largest integer less than or equal to them + * + * @function Phaser.Geom.Rectangle.Floor + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The rectangle to floor the top left X and Y coordinates of + * + * @return {Phaser.Geom.Rectangle} The rectangle that was passed to this function with its coordinates floored. + */ +var Floor = function (rect) +{ + rect.x = Math.floor(rect.x); + rect.y = Math.floor(rect.y); + + return rect; +}; + +module.exports = Floor; + + +/***/ }), + +/***/ 83859: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rounds a Rectangle's position and size down to the largest integer less than or equal to each current coordinate or dimension. + * + * @function Phaser.Geom.Rectangle.FloorAll + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to adjust. + * + * @return {Phaser.Geom.Rectangle} The adjusted Rectangle. + */ +var FloorAll = function (rect) +{ + rect.x = Math.floor(rect.x); + rect.y = Math.floor(rect.y); + rect.width = Math.floor(rect.width); + rect.height = Math.floor(rect.height); + + return rect; +}; + +module.exports = FloorAll; + + +/***/ }), + +/***/ 19217: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var MATH_CONST = __webpack_require__(36383); + +/** + * Constructs new Rectangle or repositions and resizes an existing Rectangle so that all of the given points are on or within its bounds. + * + * The `points` parameter is an array of Point-like objects: + * + * ```js + * const points = [ + * [100, 200], + * [200, 400], + * { x: 30, y: 60 } + * ] + * ``` + * + * @function Phaser.Geom.Rectangle.FromPoints + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {array} points - An array of points (either arrays with two elements corresponding to the X and Y coordinate or an object with public `x` and `y` properties) which should be surrounded by the Rectangle. + * @param {Phaser.Geom.Rectangle} [out] - Optional Rectangle to adjust. + * + * @return {Phaser.Geom.Rectangle} The adjusted `out` Rectangle, or a new Rectangle if none was provided. + */ +var FromPoints = function (points, out) +{ + if (out === undefined) { out = new Rectangle(); } + + if (points.length === 0) + { + return out; + } + + var minX = Number.MAX_VALUE; + var minY = Number.MAX_VALUE; + + var maxX = MATH_CONST.MIN_SAFE_INTEGER; + var maxY = MATH_CONST.MIN_SAFE_INTEGER; + + var p; + var px; + var py; + + for (var i = 0; i < points.length; i++) + { + p = points[i]; + + if (Array.isArray(p)) + { + px = p[0]; + py = p[1]; + } + else + { + px = p.x; + py = p.y; + } + + minX = Math.min(minX, px); + minY = Math.min(minY, py); + + maxX = Math.max(maxX, px); + maxY = Math.max(maxY, py); + } + + out.x = minX; + out.y = minY; + out.width = maxX - minX; + out.height = maxY - minY; + + return out; +}; + +module.exports = FromPoints; + + +/***/ }), + +/***/ 9477: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Create the smallest Rectangle containing two coordinate pairs. + * + * @function Phaser.Geom.Rectangle.FromXY + * @since 3.23.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {number} x1 - The X coordinate of the first point. + * @param {number} y1 - The Y coordinate of the first point. + * @param {number} x2 - The X coordinate of the second point. + * @param {number} y2 - The Y coordinate of the second point. + * @param {Phaser.Geom.Rectangle} [out] - Optional Rectangle to adjust. + * + * @return {Phaser.Geom.Rectangle} The adjusted `out` Rectangle, or a new Rectangle if none was provided. + */ +var FromXY = function (x1, y1, x2, y2, out) +{ + if (out === undefined) { out = new Rectangle(); } + + return out.setTo( + Math.min(x1, x2), + Math.min(y1, y2), + Math.abs(x1 - x2), + Math.abs(y1 - y2) + ); +}; + +module.exports = FromXY; + + +/***/ }), + +/***/ 8249: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the width/height ratio of a rectangle. + * + * @function Phaser.Geom.Rectangle.GetAspectRatio + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The rectangle. + * + * @return {number} The width/height ratio of the rectangle. + */ +var GetAspectRatio = function (rect) +{ + return (rect.height === 0) ? NaN : rect.width / rect.height; +}; + +module.exports = GetAspectRatio; + + +/***/ }), + +/***/ 27165: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns the center of a Rectangle as a Point. + * + * @function Phaser.Geom.Rectangle.GetCenter + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to get the center of. + * @param {Phaser.Math.Vector2} [out] - Optional Vector2 object to update with the center coordinates. + * + * @return {Phaser.Math.Vector2} The modified `out` object, or a new Vector2 if none was provided. + */ +var GetCenter = function (rect, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = rect.centerX; + out.y = rect.centerY; + + return out; +}; + +module.exports = GetCenter; + + +/***/ }), + +/***/ 20812: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Perimeter = __webpack_require__(13019); +var Vector2 = __webpack_require__(26099); + +/** + * Calculates the coordinates of a point at a certain `position` on the Rectangle's perimeter. + * + * The `position` is a fraction between 0 and 1 which defines how far into the perimeter the point is. + * + * A value of 0 or 1 returns the point at the top left corner of the rectangle, while a value of 0.5 returns the point at the bottom right corner of the rectangle. Values between 0 and 0.5 are on the top or the right side and values between 0.5 and 1 are on the bottom or the left side. + * + * @function Phaser.Geom.Rectangle.GetPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rectangle - The Rectangle to get the perimeter point from. + * @param {number} position - The normalized distance into the Rectangle's perimeter to return. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to update with the `x` and `y` coordinates of the point. + * + * @return {Phaser.Math.Vector2} The updated `output` object, or a new Vector2 if no `output` object was given. + */ +var GetPoint = function (rectangle, position, out) +{ + if (out === undefined) { out = new Vector2(); } + + if (position <= 0 || position >= 1) + { + out.x = rectangle.x; + out.y = rectangle.y; + + return out; + } + + var p = Perimeter(rectangle) * position; + + if (position > 0.5) + { + p -= (rectangle.width + rectangle.height); + + if (p <= rectangle.width) + { + // Face 3 + out.x = rectangle.right - p; + out.y = rectangle.bottom; + } + else + { + // Face 4 + out.x = rectangle.x; + out.y = rectangle.bottom - (p - rectangle.width); + } + } + else if (p <= rectangle.width) + { + // Face 1 + out.x = rectangle.x + p; + out.y = rectangle.y; + } + else + { + // Face 2 + out.x = rectangle.right; + out.y = rectangle.y + (p - rectangle.width); + } + + return out; +}; + +module.exports = GetPoint; + + +/***/ }), + +/***/ 34819: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetPoint = __webpack_require__(20812); +var Perimeter = __webpack_require__(13019); + +/** + * Return an array of Vector2 points from the perimeter of the rectangle, each spaced out based on the quantity or step required. + * + * @function Phaser.Geom.Rectangle.GetPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rectangle - The Rectangle object to get the points from. + * @param {number} step - Step between points. Used to calculate the number of points to return when quantity is falsey. Ignored if quantity is positive. + * @param {number} quantity - The number of evenly spaced points from the rectangles perimeter to return. If falsey, step param will be used to calculate the number of points. + * @param {Phaser.Math.Vector2[]} [out] - An optional array to store the points in. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2 points from the perimeter of the rectangle. + */ +var GetPoints = function (rectangle, quantity, stepRate, out) +{ + if (out === undefined) { out = []; } + + // If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!quantity && stepRate > 0) + { + quantity = Perimeter(rectangle) / stepRate; + } + + for (var i = 0; i < quantity; i++) + { + var position = i / quantity; + + out.push(GetPoint(rectangle, position)); + } + + return out; +}; + +module.exports = GetPoints; + + +/***/ }), + +/***/ 51313: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns the size of the Rectangle, expressed as a Vector2 object. + * With the value of the `width` as the `x` property and the `height` as the `y` property. + * + * @function Phaser.Geom.Rectangle.GetSize + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to get the size from. + * @param {Phaser.Math.Vector2} [out] - The Vector2 object to store the size in. If not given, a new Vector2 instance is created. + * + * @return {Phaser.Math.Vector2} A Vector2 object where `x` holds the width and `y` holds the height of the Rectangle. + */ +var GetSize = function (rect, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = rect.width; + out.y = rect.height; + + return out; +}; + +module.exports = GetSize; + + +/***/ }), + +/***/ 86091: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CenterOn = __webpack_require__(67502); + +/** + * Increases the size of a Rectangle by a specified amount. + * + * The center of the Rectangle stays the same. The amounts are added to each side, so the actual increase in width or height is two times bigger than the respective argument. + * + * @function Phaser.Geom.Rectangle.Inflate + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to inflate. + * @param {number} x - How many pixels the left and the right side should be moved by horizontally. + * @param {number} y - How many pixels the top and the bottom side should be moved by vertically. + * + * @return {Phaser.Geom.Rectangle} The inflated Rectangle. + */ +var Inflate = function (rect, x, y) +{ + var cx = rect.centerX; + var cy = rect.centerY; + + rect.setSize(rect.width + (x * 2), rect.height + (y * 2)); + + return CenterOn(rect, cx, cy); +}; + +module.exports = Inflate; + + +/***/ }), + +/***/ 53951: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var Intersects = __webpack_require__(59996); + +/** + * Takes two Rectangles and first checks to see if they intersect. + * If they intersect it will return the area of intersection in the `out` Rectangle. + * If they do not intersect, the `out` Rectangle will have a width and height of zero. + * + * @function Phaser.Geom.Rectangle.Intersection + * @since 3.11.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to get the intersection from. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to get the intersection from. + * @param {Phaser.Geom.Rectangle} [out] - A Rectangle to store the intersection results in. + * + * @return {Phaser.Geom.Rectangle} The intersection result. If the width and height are zero, no intersection occurred. + */ +var Intersection = function (rectA, rectB, out) +{ + if (out === undefined) { out = new Rectangle(); } + + if (Intersects(rectA, rectB)) + { + out.x = Math.max(rectA.x, rectB.x); + out.y = Math.max(rectA.y, rectB.y); + out.width = Math.min(rectA.right, rectB.right) - out.x; + out.height = Math.min(rectA.bottom, rectB.bottom) - out.y; + } + else + { + out.setEmpty(); + } + + return out; +}; + +module.exports = Intersection; + + +/***/ }), + +/***/ 14649: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Perimeter = __webpack_require__(13019); +var Vector2 = __webpack_require__(26099); + +/** + * Returns an array of Vector2 points from the perimeter of the Rectangle, where each point is spaced out based + * on either the `step` value, or the `quantity`. + * + * @function Phaser.Geom.Rectangle.MarchingAnts + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to get the perimeter points from. + * @param {number} [step] - The distance between each point of the perimeter. Set to `null` if you wish to use the `quantity` parameter instead. + * @param {number} [quantity] - The total number of points to return. The step is then calculated based on the length of the Rectangle, divided by this value. + * @param {Phaser.Math.Vector2[]} [out] - An array in which the perimeter points will be stored. If not given, a new array instance is created. + * + * @return {Phaser.Math.Vector2[]} An array containing the perimeter points from the Rectangle. + */ +var MarchingAnts = function (rect, step, quantity, out) +{ + if (out === undefined) { out = []; } + + if (!step && !quantity) + { + // Bail out + return out; + } + + // If step is a falsey value (false, null, 0, undefined, etc) then we calculate + // it based on the quantity instead, otherwise we always use the step value + if (!step) + { + step = Perimeter(rect) / quantity; + } + else + { + quantity = Math.round(Perimeter(rect) / step); + } + + var x = rect.x; + var y = rect.y; + var face = 0; + + // Loop across each face of the rectangle + + for (var i = 0; i < quantity; i++) + { + out.push(new Vector2(x, y)); + + switch (face) + { + + // Top face + case 0: + x += step; + + if (x >= rect.right) + { + face = 1; + y += (x - rect.right); + x = rect.right; + } + break; + + // Right face + case 1: + y += step; + + if (y >= rect.bottom) + { + face = 2; + x -= (y - rect.bottom); + y = rect.bottom; + } + break; + + // Bottom face + case 2: + x -= step; + + if (x <= rect.left) + { + face = 3; + y -= (rect.left - x); + x = rect.left; + } + break; + + // Left face + case 3: + y -= step; + + if (y <= rect.top) + { + face = 0; + y = rect.top; + } + break; + } + } + + return out; +}; + +module.exports = MarchingAnts; + + +/***/ }), + +/***/ 33595: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Merges a Rectangle with a list of points by repositioning and/or resizing it such that all points are located on or within its bounds. + * + * @function Phaser.Geom.Rectangle.MergePoints + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [target,$return] + * + * @param {Phaser.Geom.Rectangle} target - The Rectangle which should be merged. + * @param {Phaser.Math.Vector2[]} points - An array of Vector2 objects which should be merged with the Rectangle. + * + * @return {Phaser.Geom.Rectangle} The modified Rectangle. + */ +var MergePoints = function (target, points) +{ + var minX = target.x; + var maxX = target.right; + var minY = target.y; + var maxY = target.bottom; + + for (var i = 0; i < points.length; i++) + { + minX = Math.min(minX, points[i].x); + maxX = Math.max(maxX, points[i].x); + minY = Math.min(minY, points[i].y); + maxY = Math.max(maxY, points[i].y); + } + + target.x = minX; + target.y = minY; + target.width = maxX - minX; + target.height = maxY - minY; + + return target; +}; + +module.exports = MergePoints; + + +/***/ }), + +/***/ 20074: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Merges the source rectangle into the target rectangle and returns the target. + * Neither rectangle should have a negative width or height. + * + * @function Phaser.Geom.Rectangle.MergeRect + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [target,$return] + * + * @param {Phaser.Geom.Rectangle} target - Target rectangle. Will be modified to include source rectangle. + * @param {Phaser.Geom.Rectangle} source - Rectangle that will be merged into target rectangle. + * + * @return {Phaser.Geom.Rectangle} Modified target rectangle that contains source rectangle. + */ +var MergeRect = function (target, source) +{ + var minX = Math.min(target.x, source.x); + var maxX = Math.max(target.right, source.right); + + target.x = minX; + target.width = maxX - minX; + + var minY = Math.min(target.y, source.y); + var maxY = Math.max(target.bottom, source.bottom); + + target.y = minY; + target.height = maxY - minY; + + return target; +}; + +module.exports = MergeRect; + + +/***/ }), + +/***/ 92171: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Merges a Rectangle with a point by repositioning and/or resizing it so that the point is on or within its bounds. + * + * @function Phaser.Geom.Rectangle.MergeXY + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [target,$return] + * + * @param {Phaser.Geom.Rectangle} target - The Rectangle which should be merged and modified. + * @param {number} x - The X coordinate of the point which should be merged. + * @param {number} y - The Y coordinate of the point which should be merged. + * + * @return {Phaser.Geom.Rectangle} The modified `target` Rectangle. + */ +var MergeXY = function (target, x, y) +{ + var minX = Math.min(target.x, x); + var maxX = Math.max(target.right, x); + + target.x = minX; + target.width = maxX - minX; + + var minY = Math.min(target.y, y); + var maxY = Math.max(target.bottom, y); + + target.y = minY; + target.height = maxY - minY; + + return target; +}; + +module.exports = MergeXY; + + +/***/ }), + +/***/ 42981: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Nudges (translates) the top left corner of a Rectangle by a given offset. + * + * @function Phaser.Geom.Rectangle.Offset + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to adjust. + * @param {number} x - The distance to move the Rectangle horizontally. + * @param {number} y - The distance to move the Rectangle vertically. + * + * @return {Phaser.Geom.Rectangle} The adjusted Rectangle. + */ +var Offset = function (rect, x, y) +{ + rect.x += x; + rect.y += y; + + return rect; +}; + +module.exports = Offset; + + +/***/ }), + +/***/ 46907: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Translates the top-left corner of a Rectangle by the coordinates of a translation vector. + * + * @function Phaser.Geom.Rectangle.OffsetPoint + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to adjust. + * @param {Phaser.Math.Vector2} vec - The Vector2 point whose coordinates should be used as an offset. + * + * @return {Phaser.Geom.Rectangle} The adjusted Rectangle. + */ +var OffsetPoint = function (rect, vec) +{ + rect.x += vec.x; + rect.y += vec.y; + + return rect; +}; + +module.exports = OffsetPoint; + + +/***/ }), + +/***/ 60170: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if two Rectangles overlap. If a Rectangle is within another Rectangle, the two will be considered overlapping. Thus, the Rectangles are treated as "solid". + * + * @function Phaser.Geom.Rectangle.Overlaps + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check. + * + * @return {boolean} `true` if the two Rectangles overlap, `false` otherwise. + */ +var Overlaps = function (rectA, rectB) +{ + return ( + rectA.x < rectB.right && + rectA.right > rectB.x && + rectA.y < rectB.bottom && + rectA.bottom > rectB.y + ); +}; + +module.exports = Overlaps; + + +/***/ }), + +/***/ 13019: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the perimeter of a Rectangle. + * + * @function Phaser.Geom.Rectangle.Perimeter + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to use. + * + * @return {number} The perimeter of the Rectangle, equal to `(width * 2) + (height * 2)`. + */ +var Perimeter = function (rect) +{ + return 2 * (rect.width + rect.height); +}; + +module.exports = Perimeter; + + +/***/ }), + +/***/ 85133: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var DegToRad = __webpack_require__(39506); + +/** + * Returns a Point from the perimeter of a Rectangle based on the given angle. + * + * @function Phaser.Geom.Rectangle.PerimeterPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rectangle - The Rectangle to get the perimeter point from. + * @param {number} angle - The angle of the point, in degrees. + * @param {Phaser.Math.Vector2} [out] - The Vector2 object to store the position in. If not given, a new Vector2 instance is created. + * + * @return {Phaser.Math.Vector2} A Vector2 object holding the coordinates of the Rectangle perimeter. + */ +var PerimeterPoint = function (rectangle, angle, out) +{ + if (out === undefined) { out = new Vector2(); } + + angle = DegToRad(angle); + + var s = Math.sin(angle); + var c = Math.cos(angle); + + var dx = (c > 0) ? rectangle.width / 2 : rectangle.width / -2; + var dy = (s > 0) ? rectangle.height / 2 : rectangle.height / -2; + + if (Math.abs(dx * s) < Math.abs(dy * c)) + { + dy = (dx * s) / c; + } + else + { + dx = (dy * c) / s; + } + + out.x = dx + rectangle.centerX; + out.y = dy + rectangle.centerY; + + return out; +}; + +module.exports = PerimeterPoint; + + +/***/ }), + +/***/ 26597: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a random point within a Rectangle. + * + * @function Phaser.Geom.Rectangle.Random + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The Rectangle to return a point from. + * @param {Phaser.Math.Vector2} out - The object to update with the point's coordinates. + * + * @return {Phaser.Math.Vector2} The modified `out` object, or a new Point if none was provided. + */ +var Random = function (rect, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = rect.x + (Math.random() * rect.width); + out.y = rect.y + (Math.random() * rect.height); + + return out; +}; + +module.exports = Random; + + +/***/ }), + +/***/ 86470: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Between = __webpack_require__(30976); +var ContainsRect = __webpack_require__(70273); +var Vector2 = __webpack_require__(26099); + +/** + * Calculates a random point that lies within the `outer` Rectangle, but outside of the `inner` Rectangle. + * The inner Rectangle must be fully contained within the outer rectangle. + * + * @function Phaser.Geom.Rectangle.RandomOutside + * @since 3.10.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} outer - The outer Rectangle to get the random point within. + * @param {Phaser.Geom.Rectangle} inner - The inner Rectangle to exclude from the returned point. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the result in. If not specified, a new Vector2 will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 object containing the random values in its `x` and `y` properties. + */ +var RandomOutside = function (outer, inner, out) +{ + if (out === undefined) { out = new Vector2(); } + + if (ContainsRect(outer, inner)) + { + // Pick a random quadrant + // + // The quadrants don't extend the full widths / heights of the outer rect to give + // us a better uniformed distribution, otherwise you get clumping in the corners where + // the 4 quads would overlap + + switch (Between(0, 3)) + { + case 0: // Top + out.x = outer.x + (Math.random() * (inner.right - outer.x)); + out.y = outer.y + (Math.random() * (inner.top - outer.y)); + break; + + case 1: // Bottom + out.x = inner.x + (Math.random() * (outer.right - inner.x)); + out.y = inner.bottom + (Math.random() * (outer.bottom - inner.bottom)); + break; + + case 2: // Left + out.x = outer.x + (Math.random() * (inner.x - outer.x)); + out.y = inner.y + (Math.random() * (outer.bottom - inner.y)); + break; + + case 3: // Right + out.x = inner.right + (Math.random() * (outer.right - inner.right)); + out.y = outer.y + (Math.random() * (inner.bottom - outer.y)); + break; + } + } + + return out; +}; + +module.exports = RandomOutside; + + +/***/ }), + +/***/ 87841: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Contains = __webpack_require__(37303); +var GetPoint = __webpack_require__(20812); +var GetPoints = __webpack_require__(34819); +var GEOM_CONST = __webpack_require__(23777); +var Line = __webpack_require__(23031); +var Random = __webpack_require__(26597); + +/** + * @classdesc + * Encapsulates a 2D rectangle defined by its corner point in the top-left and its extends in x (width) and y (height) + * + * @class Rectangle + * @memberof Phaser.Geom + * @constructor + * @since 3.0.0 + * + * @param {number} [x=0] - The X coordinate of the top left corner of the Rectangle. + * @param {number} [y=0] - The Y coordinate of the top left corner of the Rectangle. + * @param {number} [width=0] - The width of the Rectangle. + * @param {number} [height=0] - The height of the Rectangle. + */ +var Rectangle = new Class({ + + initialize: + + function Rectangle (x, y, width, height) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = 0; } + if (height === undefined) { height = 0; } + + /** + * The geometry constant type of this object: `GEOM_CONST.RECTANGLE`. + * Used for fast type comparisons. + * + * @name Phaser.Geom.Rectangle#type + * @type {number} + * @readonly + * @since 3.19.0 + */ + this.type = GEOM_CONST.RECTANGLE; + + /** + * The X coordinate of the top left corner of the Rectangle. + * + * @name Phaser.Geom.Rectangle#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = x; + + /** + * The Y coordinate of the top left corner of the Rectangle. + * + * @name Phaser.Geom.Rectangle#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = y; + + /** + * The width of the Rectangle, i.e. the distance between its left side (defined by `x`) and its right side. + * + * @name Phaser.Geom.Rectangle#width + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.width = width; + + /** + * The height of the Rectangle, i.e. the distance between its top side (defined by `y`) and its bottom side. + * + * @name Phaser.Geom.Rectangle#height + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.height = height; + }, + + /** + * Checks if the given point is inside the Rectangle's bounds. + * + * @method Phaser.Geom.Rectangle#contains + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the point to check. + * @param {number} y - The Y coordinate of the point to check. + * + * @return {boolean} `true` if the point is within the Rectangle's bounds, otherwise `false`. + */ + contains: function (x, y) + { + return Contains(this, x, y); + }, + + /** + * Calculates the coordinates of a point at a certain `position` on the Rectangle's perimeter. + * + * The `position` is a fraction between 0 and 1 which defines how far into the perimeter the point is. + * + * A value of 0 or 1 returns the point at the top left corner of the rectangle, while a value of 0.5 returns the point at the bottom right corner of the rectangle. Values between 0 and 0.5 are on the top or the right side and values between 0.5 and 1 are on the bottom or the left side. + * + * @method Phaser.Geom.Rectangle#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [output,$return] + * + * @param {number} position - The normalized distance into the Rectangle's perimeter to return. + * @param {Phaser.Math.Vector2} [output] - A Vector2 instance to update with the `x` and `y` coordinates of the point. + * + * @return {Phaser.Math.Vector2} The updated `output` object, or a new Vector2 if no `output` object was given. + */ + getPoint: function (position, output) + { + return GetPoint(this, position, output); + }, + + /** + * Returns an array of points from the perimeter of the Rectangle, each spaced out based on the quantity or step required. + * + * @method Phaser.Geom.Rectangle#getPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [output,$return] + * + * @param {number} quantity - The number of points to return. Set to `false` or 0 to return an arbitrary number of points (`perimeter / stepRate`) evenly spaced around the Rectangle based on the `stepRate`. + * @param {number} [stepRate] - If `quantity` is 0, determines the normalized distance between each returned point. + * @param {Phaser.Math.Vector2[]} [output] - An array to which to append the points. + * + * @return {Phaser.Math.Vector2[]} The modified `output` array, or a new array if none was provided. + */ + getPoints: function (quantity, stepRate, output) + { + return GetPoints(this, quantity, stepRate, output); + }, + + /** + * Returns a random point within the Rectangle's bounds. + * + * @method Phaser.Geom.Rectangle#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [point,$return] + * + * @param {Phaser.Math.Vector2} [vec] - The object in which to store the `x` and `y` coordinates of the point. + * + * @return {Phaser.Math.Vector2} The updated `vec`, or a new Vector2 if none was provided. + */ + getRandomPoint: function (vec) + { + return Random(this, vec); + }, + + /** + * Sets the position, width, and height of the Rectangle. + * + * @method Phaser.Geom.Rectangle#setTo + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the top left corner of the Rectangle. + * @param {number} y - The Y coordinate of the top left corner of the Rectangle. + * @param {number} width - The width of the Rectangle. + * @param {number} height - The height of the Rectangle. + * + * @return {this} This Rectangle object. + */ + setTo: function (x, y, width, height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + + return this; + }, + + /** + * Resets the position, width, and height of the Rectangle to 0. + * + * @method Phaser.Geom.Rectangle#setEmpty + * @since 3.0.0 + * + * @return {this} This Rectangle object. + */ + setEmpty: function () + { + return this.setTo(0, 0, 0, 0); + }, + + /** + * Sets the position of the Rectangle. + * + * @method Phaser.Geom.Rectangle#setPosition + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the top left corner of the Rectangle. + * @param {number} [y=x] - The Y coordinate of the top left corner of the Rectangle. + * + * @return {this} This Rectangle object. + */ + setPosition: function (x, y) + { + if (y === undefined) { y = x; } + + this.x = x; + this.y = y; + + return this; + }, + + /** + * Sets the width and height of the Rectangle. + * + * @method Phaser.Geom.Rectangle#setSize + * @since 3.0.0 + * + * @param {number} width - The width to set the Rectangle to. + * @param {number} [height=width] - The height to set the Rectangle to. + * + * @return {this} This Rectangle object. + */ + setSize: function (width, height) + { + if (height === undefined) { height = width; } + + this.width = width; + this.height = height; + + return this; + }, + + /** + * Determines if the Rectangle is empty. A Rectangle is empty if its width or height is less than or equal to 0. + * + * @method Phaser.Geom.Rectangle#isEmpty + * @since 3.0.0 + * + * @return {boolean} `true` if the Rectangle is empty. A Rectangle object is empty if its width or height is less than or equal to 0. + */ + isEmpty: function () + { + return (this.width <= 0 || this.height <= 0); + }, + + /** + * Returns a Line object that corresponds to the top of this Rectangle. + * + * @method Phaser.Geom.Rectangle#getLineA + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to the top of this Rectangle. + */ + getLineA: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.x, this.y, this.right, this.y); + + return line; + }, + + /** + * Returns a Line object that corresponds to the right of this Rectangle. + * + * @method Phaser.Geom.Rectangle#getLineB + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to the right of this Rectangle. + */ + getLineB: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.right, this.y, this.right, this.bottom); + + return line; + }, + + /** + * Returns a Line object that corresponds to the bottom of this Rectangle. + * + * @method Phaser.Geom.Rectangle#getLineC + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to the bottom of this Rectangle. + */ + getLineC: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.right, this.bottom, this.x, this.bottom); + + return line; + }, + + /** + * Returns a Line object that corresponds to the left of this Rectangle. + * + * @method Phaser.Geom.Rectangle#getLineD + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to the left of this Rectangle. + */ + getLineD: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.x, this.bottom, this.x, this.y); + + return line; + }, + + /** + * The x coordinate of the left of the Rectangle. + * Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property. + * + * @name Phaser.Geom.Rectangle#left + * @type {number} + * @since 3.0.0 + */ + left: { + + get: function () + { + return this.x; + }, + + set: function (value) + { + if (value >= this.right) + { + this.width = 0; + } + else + { + this.width = this.right - value; + } + + this.x = value; + } + + }, + + /** + * The sum of the x and width properties. + * Changing the right property of a Rectangle object has no effect on the x, y and height properties, however it does affect the width property. + * + * @name Phaser.Geom.Rectangle#right + * @type {number} + * @since 3.0.0 + */ + right: { + + get: function () + { + return this.x + this.width; + }, + + set: function (value) + { + if (value <= this.x) + { + this.width = 0; + } + else + { + this.width = value - this.x; + } + } + + }, + + /** + * The y coordinate of the top of the Rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties. + * However it does affect the height property, whereas changing the y value does not affect the height property. + * + * @name Phaser.Geom.Rectangle#top + * @type {number} + * @since 3.0.0 + */ + top: { + + get: function () + { + return this.y; + }, + + set: function (value) + { + if (value >= this.bottom) + { + this.height = 0; + } + else + { + this.height = (this.bottom - value); + } + + this.y = value; + } + + }, + + /** + * The sum of the y and height properties. + * Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property. + * + * @name Phaser.Geom.Rectangle#bottom + * @type {number} + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return this.y + this.height; + }, + + set: function (value) + { + if (value <= this.y) + { + this.height = 0; + } + else + { + this.height = value - this.y; + } + } + + }, + + /** + * The x coordinate of the center of the Rectangle. + * + * @name Phaser.Geom.Rectangle#centerX + * @type {number} + * @since 3.0.0 + */ + centerX: { + + get: function () + { + return this.x + (this.width / 2); + }, + + set: function (value) + { + this.x = value - (this.width / 2); + } + + }, + + /** + * The y coordinate of the center of the Rectangle. + * + * @name Phaser.Geom.Rectangle#centerY + * @type {number} + * @since 3.0.0 + */ + centerY: { + + get: function () + { + return this.y + (this.height / 2); + }, + + set: function (value) + { + this.y = value - (this.height / 2); + } + + } + +}); + +module.exports = Rectangle; + + +/***/ }), + +/***/ 94845: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Determines if the two objects (either Rectangles or Rectangle-like) have the same width and height values under strict equality. + * + * @function Phaser.Geom.Rectangle.SameDimensions + * @since 3.15.0 + * + * @param {Phaser.Geom.Rectangle} rect - The first Rectangle object. + * @param {Phaser.Geom.Rectangle} toCompare - The second Rectangle object. + * + * @return {boolean} `true` if the objects have equivalent values for the `width` and `height` properties, otherwise `false`. + */ +var SameDimensions = function (rect, toCompare) +{ + return (rect.width === toCompare.width && rect.height === toCompare.height); +}; + +module.exports = SameDimensions; + + +/***/ }), + +/***/ 31730: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Scales the width and height of this Rectangle by the given amounts. + * + * @function Phaser.Geom.Rectangle.Scale + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [rect,$return] + * + * @param {Phaser.Geom.Rectangle} rect - The `Rectangle` object that will be scaled by the specified amount(s). + * @param {number} x - The factor by which to scale the rectangle horizontally. + * @param {number} y - The amount by which to scale the rectangle vertically. If this is not specified, the rectangle will be scaled by the factor `x` in both directions. + * + * @return {Phaser.Geom.Rectangle} The rectangle object with updated `width` and `height` properties as calculated from the scaling factor(s). + */ +var Scale = function (rect, x, y) +{ + if (y === undefined) { y = x; } + + rect.width *= x; + rect.height *= y; + + return rect; +}; + +module.exports = Scale; + + +/***/ }), + +/***/ 36899: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Creates a new Rectangle or repositions and/or resizes an existing Rectangle so that it encompasses the two given Rectangles, i.e. calculates their union. + * + * @function Phaser.Geom.Rectangle.Union + * @since 3.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to use. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to use. + * @param {Phaser.Geom.Rectangle} [out] - The Rectangle to store the union in. + * + * @return {Phaser.Geom.Rectangle} The modified `out` Rectangle, or a new Rectangle if none was provided. + */ +var Union = function (rectA, rectB, out) +{ + if (out === undefined) { out = new Rectangle(); } + + // Cache vars so we can use one of the input rects as the output rect + var x = Math.min(rectA.x, rectB.x); + var y = Math.min(rectA.y, rectB.y); + var w = Math.max(rectA.right, rectB.right) - x; + var h = Math.max(rectA.bottom, rectB.bottom) - y; + + return out.setTo(x, y, w, h); +}; + +module.exports = Union; + + +/***/ }), + +/***/ 93232: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +Rectangle.Area = __webpack_require__(62224); +Rectangle.Ceil = __webpack_require__(98615); +Rectangle.CeilAll = __webpack_require__(31688); +Rectangle.CenterOn = __webpack_require__(67502); +Rectangle.Clone = __webpack_require__(65085); +Rectangle.Contains = __webpack_require__(37303); +Rectangle.ContainsPoint = __webpack_require__(96553); +Rectangle.ContainsRect = __webpack_require__(70273); +Rectangle.CopyFrom = __webpack_require__(43459); +Rectangle.Decompose = __webpack_require__(77493); +Rectangle.Equals = __webpack_require__(9219); +Rectangle.FitInside = __webpack_require__(53751); +Rectangle.FitOutside = __webpack_require__(16088); +Rectangle.Floor = __webpack_require__(80774); +Rectangle.FloorAll = __webpack_require__(83859); +Rectangle.FromPoints = __webpack_require__(19217); +Rectangle.FromXY = __webpack_require__(9477); +Rectangle.GetAspectRatio = __webpack_require__(8249); +Rectangle.GetCenter = __webpack_require__(27165); +Rectangle.GetPoint = __webpack_require__(20812); +Rectangle.GetPoints = __webpack_require__(34819); +Rectangle.GetSize = __webpack_require__(51313); +Rectangle.Inflate = __webpack_require__(86091); +Rectangle.Intersection = __webpack_require__(53951); +Rectangle.MarchingAnts = __webpack_require__(14649); +Rectangle.MergePoints = __webpack_require__(33595); +Rectangle.MergeRect = __webpack_require__(20074); +Rectangle.MergeXY = __webpack_require__(92171); +Rectangle.Offset = __webpack_require__(42981); +Rectangle.OffsetPoint = __webpack_require__(46907); +Rectangle.Overlaps = __webpack_require__(60170); +Rectangle.Perimeter = __webpack_require__(13019); +Rectangle.PerimeterPoint = __webpack_require__(85133); +Rectangle.Random = __webpack_require__(26597); +Rectangle.RandomOutside = __webpack_require__(86470); +Rectangle.SameDimensions = __webpack_require__(94845); +Rectangle.Scale = __webpack_require__(31730); +Rectangle.Union = __webpack_require__(36899); + +module.exports = Rectangle; + + +/***/ }), + +/***/ 41658: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// The 2D area of a triangle. The area value is always non-negative. + +/** + * Returns the area of a Triangle. + * + * @function Phaser.Geom.Triangle.Area + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to use. + * + * @return {number} The area of the Triangle, always non-negative. + */ +var Area = function (triangle) +{ + var x1 = triangle.x1; + var y1 = triangle.y1; + + var x2 = triangle.x2; + var y2 = triangle.y2; + + var x3 = triangle.x3; + var y3 = triangle.y3; + + return Math.abs(((x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1)) / 2); +}; + +module.exports = Area; + + +/***/ }), + +/***/ 39208: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Triangle = __webpack_require__(16483); + +/** + * Builds an equilateral triangle. In the equilateral triangle, all the sides are the same length (congruent) and all the angles are the same size (congruent). + * The x/y specifies the top-middle of the triangle (x1/y1) and length is the length of each side. + * + * @function Phaser.Geom.Triangle.BuildEquilateral + * @since 3.0.0 + * + * @param {number} x - x coordinate of the top point of the triangle. + * @param {number} y - y coordinate of the top point of the triangle. + * @param {number} length - Length of each side of the triangle. + * + * @return {Phaser.Geom.Triangle} The Triangle object of the given size. + */ +var BuildEquilateral = function (x, y, length) +{ + var height = length * (Math.sqrt(3) / 2); + + var x1 = x; + var y1 = y; + + var x2 = x + (length / 2); + var y2 = y + height; + + var x3 = x - (length / 2); + var y3 = y + height; + + return new Triangle(x1, y1, x2, y2, x3, y3); +}; + +module.exports = BuildEquilateral; + + +/***/ }), + +/***/ 39545: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var EarCut = __webpack_require__(94811); +var Triangle = __webpack_require__(16483); + +/** + * Takes an array of vertex coordinates, and optionally an array of hole indices, then returns an array + * of Triangle instances, where the given vertices have been decomposed into a series of triangles. + * + * @function Phaser.Geom.Triangle.BuildFromPolygon + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle[]} O - [out,$return] + * + * @param {array} data - A flat array of vertex coordinates like [x0,y0, x1,y1, x2,y2, ...] + * @param {array} [holes=null] - An array of hole indices if any (e.g. [5, 8] for a 12-vertex input would mean one hole with vertices 5–7 and another with 8–11). + * @param {number} [scaleX=1] - Horizontal scale factor to multiply the resulting points by. + * @param {number} [scaleY=1] - Vertical scale factor to multiply the resulting points by. + * @param {(array|Phaser.Geom.Triangle[])} [out] - An array to store the resulting Triangle instances in. If not provided, a new array is created. + * + * @return {(array|Phaser.Geom.Triangle[])} An array of Triangle instances, where each triangle is based on the decomposed vertices data. + */ +var BuildFromPolygon = function (data, holes, scaleX, scaleY, out) +{ + if (holes === undefined) { holes = null; } + if (scaleX === undefined) { scaleX = 1; } + if (scaleY === undefined) { scaleY = 1; } + if (out === undefined) { out = []; } + + var tris = EarCut(data, holes); + + var a; + var b; + var c; + + var x1; + var y1; + + var x2; + var y2; + + var x3; + var y3; + + for (var i = 0; i < tris.length; i += 3) + { + a = tris[i]; + b = tris[i + 1]; + c = tris[i + 2]; + + x1 = data[a * 2] * scaleX; + y1 = data[(a * 2) + 1] * scaleY; + + x2 = data[b * 2] * scaleX; + y2 = data[(b * 2) + 1] * scaleY; + + x3 = data[c * 2] * scaleX; + y3 = data[(c * 2) + 1] * scaleY; + + out.push(new Triangle(x1, y1, x2, y2, x3, y3)); + } + + return out; +}; + +module.exports = BuildFromPolygon; + + +/***/ }), + +/***/ 90301: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Triangle = __webpack_require__(16483); + +// Builds a right triangle, with one 90 degree angle and two acute angles +// The x/y is the coordinate of the 90 degree angle (and will map to x1/y1 in the resulting Triangle) +// w/h can be positive or negative and represent the length of each side + +/** + * Builds a right triangle, i.e. one which has a 90-degree angle and two acute angles. + * + * @function Phaser.Geom.Triangle.BuildRight + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the right angle, which will also be the first X coordinate of the constructed Triangle. + * @param {number} y - The Y coordinate of the right angle, which will also be the first Y coordinate of the constructed Triangle. + * @param {number} width - The length of the side which is to the left or to the right of the right angle. + * @param {number} height - The length of the side which is above or below the right angle. + * + * @return {Phaser.Geom.Triangle} The constructed right Triangle. + */ +var BuildRight = function (x, y, width, height) +{ + if (height === undefined) { height = width; } + + // 90 degree angle + var x1 = x; + var y1 = y; + + var x2 = x; + var y2 = y - height; + + var x3 = x + width; + var y3 = y; + + return new Triangle(x1, y1, x2, y2, x3, y3); +}; + +module.exports = BuildRight; + + +/***/ }), + +/***/ 23707: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Centroid = __webpack_require__(97523); +var Offset = __webpack_require__(13584); + +/** + * @callback CenterFunction + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to return the center coordinates of. + * + * @return {Phaser.Math.Vector2} The center point of the Triangle according to the function. + */ + +/** + * Positions the Triangle so that it is centered on the given coordinates. + * + * @function Phaser.Geom.Triangle.CenterOn + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle} O - [triangle,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The triangle to be positioned. + * @param {number} x - The horizontal coordinate to center on. + * @param {number} y - The vertical coordinate to center on. + * @param {CenterFunction} [centerFunc] - The function used to center the triangle. Defaults to Centroid centering. + * + * @return {Phaser.Geom.Triangle} The Triangle that was centered. + */ +var CenterOn = function (triangle, x, y, centerFunc) +{ + if (centerFunc === undefined) { centerFunc = Centroid; } + + // Get the center of the triangle + var center = centerFunc(triangle); + + // Difference + var diffX = x - center.x; + var diffY = y - center.y; + + return Offset(triangle, diffX, diffY); +}; + +module.exports = CenterOn; + + +/***/ }), + +/***/ 97523: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Calculates the position of a Triangle's centroid, which is also its center of mass (center of gravity). + * + * The centroid is the point in a Triangle at which its three medians (the lines drawn from the vertices to the bisectors of the opposite sides) meet. It divides each one in a 2:1 ratio. + * + * @function Phaser.Geom.Triangle.Centroid + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to use. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the coordinates in. + * + * @return {Phaser.Math.Vector2} The `out` object with modified `x` and `y` properties, or a new Vector2 if none was provided. + */ +var Centroid = function (triangle, out) +{ + if (out === undefined) { out = new Vector2(); } + + out.x = (triangle.x1 + triangle.x2 + triangle.x3) / 3; + out.y = (triangle.y1 + triangle.y2 + triangle.y3) / 3; + + return out; +}; + +module.exports = Centroid; + + +/***/ }), + +/***/ 24951: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Computes the determinant of a 2x2 matrix. Uses standard double-precision arithmetic, so is susceptible to round-off error. + * + * @function det + * @private + * @since 3.0.0 + * + * @param {number} m00 - The [0,0] entry of the matrix. + * @param {number} m01 - The [0,1] entry of the matrix. + * @param {number} m10 - The [1,0] entry of the matrix. + * @param {number} m11 - The [1,1] entry of the matrix. + * + * @return {number} the determinant. + */ +function det (m00, m01, m10, m11) +{ + return (m00 * m11) - (m01 * m10); +} + +/** + * Computes the circumcentre of a triangle. The circumcentre is the centre of + * the circumcircle, the smallest circle which encloses the triangle. It is also + * the common intersection point of the perpendicular bisectors of the sides of + * the triangle, and is the only point which has equal distance to all three + * vertices of the triangle. + * + * Adapted from http://bjornharrtell.github.io/jsts/doc/api/jsts_geom_Triangle.js.html + * + * @function Phaser.Geom.Triangle.CircumCenter + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to get the circumcenter of. + * @param {Phaser.Math.Vector2} [out] - The Vector2 object to store the position in. If not given, a new Vector2 instance is created. + * + * @return {Phaser.Math.Vector2} A Vector2 object holding the coordinates of the circumcenter of the Triangle. + */ +var CircumCenter = function (triangle, out) +{ + if (out === undefined) { out = new Vector2(); } + + var cx = triangle.x3; + var cy = triangle.y3; + + var ax = triangle.x1 - cx; + var ay = triangle.y1 - cy; + + var bx = triangle.x2 - cx; + var by = triangle.y2 - cy; + + var denom = 2 * det(ax, ay, bx, by); + var numx = det(ay, ax * ax + ay * ay, by, bx * bx + by * by); + var numy = det(ax, ax * ax + ay * ay, bx, bx * bx + by * by); + + out.x = cx - numx / denom; + out.y = cy + numy / denom; + + return out; +}; + +module.exports = CircumCenter; + + +/***/ }), + +/***/ 85614: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circle = __webpack_require__(96503); + +/** + * Finds the circumscribed circle (circumcircle) of a Triangle object. The circumcircle is the circle which touches all of the triangle's vertices. + * + * Adapted from https://gist.github.com/mutoo/5617691 + * + * @function Phaser.Geom.Triangle.CircumCircle + * @since 3.0.0 + * + * @generic {Phaser.Geom.Circle} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to use as input. + * @param {Phaser.Geom.Circle} [out] - An optional Circle to store the result in. + * + * @return {Phaser.Geom.Circle} The updated `out` Circle, or a new Circle if none was provided. + */ +var CircumCircle = function (triangle, out) +{ + if (out === undefined) { out = new Circle(); } + + // A + var x1 = triangle.x1; + var y1 = triangle.y1; + + // B + var x2 = triangle.x2; + var y2 = triangle.y2; + + // C + var x3 = triangle.x3; + var y3 = triangle.y3; + + var A = x2 - x1; + var B = y2 - y1; + var C = x3 - x1; + var D = y3 - y1; + var E = A * (x1 + x2) + B * (y1 + y2); + var F = C * (x1 + x3) + D * (y1 + y3); + var G = 2 * (A * (y3 - y2) - B * (x3 - x2)); + + var dx; + var dy; + + // If the points of the triangle are collinear, then just find the + // extremes and use the midpoint as the center of the circumcircle. + + if (Math.abs(G) < 0.000001) + { + var minX = Math.min(x1, x2, x3); + var minY = Math.min(y1, y2, y3); + dx = (Math.max(x1, x2, x3) - minX) * 0.5; + dy = (Math.max(y1, y2, y3) - minY) * 0.5; + + out.x = minX + dx; + out.y = minY + dy; + out.radius = Math.sqrt(dx * dx + dy * dy); + } + else + { + out.x = (D * E - B * F) / G; + out.y = (A * F - C * E) / G; + dx = out.x - x1; + dy = out.y - y1; + out.radius = Math.sqrt(dx * dx + dy * dy); + } + + return out; +}; + +module.exports = CircumCircle; + + +/***/ }), + +/***/ 74422: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Triangle = __webpack_require__(16483); + +/** + * Clones a Triangle object. + * + * @function Phaser.Geom.Triangle.Clone + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} source - The Triangle to clone. + * + * @return {Phaser.Geom.Triangle} A new Triangle identical to the given one but separate from it. + */ +var Clone = function (source) +{ + return new Triangle(source.x1, source.y1, source.x2, source.y2, source.x3, source.y3); +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 10690: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// http://www.blackpawn.com/texts/pointinpoly/ + +/** + * Checks if a point (as a pair of coordinates) is inside a Triangle's bounds. + * + * @function Phaser.Geom.Triangle.Contains + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check. + * @param {number} x - The X coordinate of the point to check. + * @param {number} y - The Y coordinate of the point to check. + * + * @return {boolean} `true` if the point is inside the Triangle, otherwise `false`. + */ +var Contains = function (triangle, x, y) +{ + var v0x = triangle.x3 - triangle.x1; + var v0y = triangle.y3 - triangle.y1; + + var v1x = triangle.x2 - triangle.x1; + var v1y = triangle.y2 - triangle.y1; + + var v2x = x - triangle.x1; + var v2y = y - triangle.y1; + + var dot00 = (v0x * v0x) + (v0y * v0y); + var dot01 = (v0x * v1x) + (v0y * v1y); + var dot02 = (v0x * v2x) + (v0y * v2y); + var dot11 = (v1x * v1x) + (v1y * v1y); + var dot12 = (v1x * v2x) + (v1y * v2y); + + // Compute barycentric coordinates + var b = ((dot00 * dot11) - (dot01 * dot01)); + var inv = (b === 0) ? 0 : (1 / b); + var u = ((dot11 * dot02) - (dot01 * dot12)) * inv; + var v = ((dot00 * dot12) - (dot01 * dot02)) * inv; + + return (u >= 0 && v >= 0 && (u + v < 1)); +}; + +module.exports = Contains; + + +/***/ }), + +/***/ 48653: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Filters an array of point-like objects to only those contained within a triangle. + * + * If `returnFirst` is true, will return an array containing only the first point in the provided array that is within the triangle (or an empty array if there are no such points). + * + * @function Phaser.Geom.Triangle.ContainsArray + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The triangle that the points are being checked in. + * @param {Phaser.Math.Vector2[]} points - An array of Vector2 objects to check if they are within the triangle. + * @param {boolean} [returnFirst=false] - If `true`, return an array containing only the first point found that is within the triangle. + * @param {array} [out] - If provided, the points that are within the triangle will be appended to this array instead of being added to a new array. If `returnFirst` is true, only the first point found within the triangle will be appended. This array will also be returned by this function. + * + * @return {Phaser.Math.Vector2[]} An array containing all the points from `points` that are within the triangle, if an array was provided as `out`, points will be appended to that array and it will also be returned here. + */ +var ContainsArray = function (triangle, points, returnFirst, out) +{ + if (returnFirst === undefined) { returnFirst = false; } + if (out === undefined) { out = []; } + + var v0x = triangle.x3 - triangle.x1; + var v0y = triangle.y3 - triangle.y1; + + var v1x = triangle.x2 - triangle.x1; + var v1y = triangle.y2 - triangle.y1; + + var dot00 = (v0x * v0x) + (v0y * v0y); + var dot01 = (v0x * v1x) + (v0y * v1y); + var dot11 = (v1x * v1x) + (v1y * v1y); + + // Compute barycentric coordinates + var b = ((dot00 * dot11) - (dot01 * dot01)); + var inv = (b === 0) ? 0 : (1 / b); + + var u; + var v; + var v2x; + var v2y; + var dot02; + var dot12; + + var x1 = triangle.x1; + var y1 = triangle.y1; + + for (var i = 0; i < points.length; i++) + { + v2x = points[i].x - x1; + v2y = points[i].y - y1; + + dot02 = (v0x * v2x) + (v0y * v2y); + dot12 = (v1x * v2x) + (v1y * v2y); + + u = ((dot11 * dot02) - (dot01 * dot12)) * inv; + v = ((dot00 * dot12) - (dot01 * dot02)) * inv; + + if (u >= 0 && v >= 0 && (u + v < 1)) + { + out.push({ x: points[i].x, y: points[i].y }); + + if (returnFirst) + { + break; + } + } + } + + return out; +}; + +module.exports = ContainsArray; + + +/***/ }), + +/***/ 96006: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Contains = __webpack_require__(10690); + +/** + * Tests if a triangle contains a point. + * + * @function Phaser.Geom.Triangle.ContainsPoint + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The triangle. + * @param {Phaser.Math.Vector2} vec - The Vector2 point to test if it's within the triangle. + * + * @return {boolean} `true` if the point is within the triangle, otherwise `false`. + */ +var ContainsPoint = function (triangle, vec) +{ + return Contains(triangle, vec.x, vec.y); +}; + +module.exports = ContainsPoint; + + +/***/ }), + +/***/ 71326: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Copy the values of one Triangle to a destination Triangle. + * + * @function Phaser.Geom.Triangle.CopyFrom + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle} O - [dest,$return] + * + * @param {Phaser.Geom.Triangle} source - The source Triangle to copy the values from. + * @param {Phaser.Geom.Triangle} dest - The destination Triangle to copy the values to. + * + * @return {Phaser.Geom.Triangle} The destination Triangle. + */ +var CopyFrom = function (source, dest) +{ + return dest.setTo(source.x1, source.y1, source.x2, source.y2, source.x3, source.y3); +}; + +module.exports = CopyFrom; + + +/***/ }), + +/***/ 71694: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Decomposes a Triangle into an array of its points. + * + * @function Phaser.Geom.Triangle.Decompose + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to decompose. + * @param {array} [out] - An array to store the points into. + * + * @return {array} The provided `out` array, or a new array if none was provided, with three objects with `x` and `y` properties representing each point of the Triangle appended to it. + */ +var Decompose = function (triangle, out) +{ + if (out === undefined) { out = []; } + + out.push({ x: triangle.x1, y: triangle.y1 }); + out.push({ x: triangle.x2, y: triangle.y2 }); + out.push({ x: triangle.x3, y: triangle.y3 }); + + return out; +}; + +module.exports = Decompose; + + +/***/ }), + +/***/ 33522: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns true if two triangles have the same coordinates. + * + * @function Phaser.Geom.Triangle.Equals + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The first triangle to check. + * @param {Phaser.Geom.Triangle} toCompare - The second triangle to check. + * + * @return {boolean} `true` if the two given triangles have the exact same coordinates, otherwise `false`. + */ +var Equals = function (triangle, toCompare) +{ + return ( + triangle.x1 === toCompare.x1 && + triangle.y1 === toCompare.y1 && + triangle.x2 === toCompare.x2 && + triangle.y2 === toCompare.y2 && + triangle.x3 === toCompare.x3 && + triangle.y3 === toCompare.y3 + ); +}; + +module.exports = Equals; + + +/***/ }), + +/***/ 20437: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var Length = __webpack_require__(35001); + +/** + * Returns a Vector2 point from around the perimeter of a Triangle. + * + * @function Phaser.Geom.Triangle.GetPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to get the point on its perimeter from. + * @param {number} position - The position along the perimeter of the triangle. A value between 0 and 1. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 point to store the value in. If not given a new Vector2 will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 point object containing the given position from the perimeter of the triangle. + */ +var GetPoint = function (triangle, position, out) +{ + if (out === undefined) { out = new Vector2(); } + + var line1 = triangle.getLineA(); + var line2 = triangle.getLineB(); + var line3 = triangle.getLineC(); + + if (position <= 0 || position >= 1) + { + out.x = line1.x1; + out.y = line1.y1; + + return out; + } + + var length1 = Length(line1); + var length2 = Length(line2); + var length3 = Length(line3); + + var perimeter = length1 + length2 + length3; + + var p = perimeter * position; + var localPosition = 0; + + // Which line is it on? + + if (p < length1) + { + // Line 1 + localPosition = p / length1; + + out.x = line1.x1 + (line1.x2 - line1.x1) * localPosition; + out.y = line1.y1 + (line1.y2 - line1.y1) * localPosition; + } + else if (p > length1 + length2) + { + // Line 3 + p -= length1 + length2; + localPosition = p / length3; + + out.x = line3.x1 + (line3.x2 - line3.x1) * localPosition; + out.y = line3.y1 + (line3.y2 - line3.y1) * localPosition; + } + else + { + // Line 2 + p -= length1; + localPosition = p / length2; + + out.x = line2.x1 + (line2.x2 - line2.x1) * localPosition; + out.y = line2.y1 + (line2.y2 - line2.y1) * localPosition; + } + + return out; +}; + +module.exports = GetPoint; + + +/***/ }), + +/***/ 80672: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Length = __webpack_require__(35001); +var Vector2 = __webpack_require__(26099); + +/** + * Returns an array of evenly spaced points on the perimeter of a Triangle. + * + * @function Phaser.Geom.Triangle.GetPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to get the points from. + * @param {number} quantity - The number of evenly spaced points to return. Set to 0 to return an arbitrary number of points based on the `stepRate`. + * @param {number} stepRate - If `quantity` is 0, the distance between each returned point. + * @param {Phaser.Math.Vector2[]} [out] - An array to which the points should be appended. + * + * @return {Phaser.Math.Vector2[]} The modified `out` array, or a new array if none was provided. + */ +var GetPoints = function (triangle, quantity, stepRate, out) +{ + if (out === undefined) { out = []; } + + var line1 = triangle.getLineA(); + var line2 = triangle.getLineB(); + var line3 = triangle.getLineC(); + + var length1 = Length(line1); + var length2 = Length(line2); + var length3 = Length(line3); + + var perimeter = length1 + length2 + length3; + + // If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead. + if (!quantity && stepRate > 0) + { + quantity = perimeter / stepRate; + } + + for (var i = 0; i < quantity; i++) + { + var p = perimeter * (i / quantity); + var localPosition = 0; + + var point = new Vector2(); + + // Which line is it on? + + if (p < length1) + { + // Line 1 + localPosition = p / length1; + + point.x = line1.x1 + (line1.x2 - line1.x1) * localPosition; + point.y = line1.y1 + (line1.y2 - line1.y1) * localPosition; + } + else if (p > length1 + length2) + { + // Line 3 + p -= length1 + length2; + localPosition = p / length3; + + point.x = line3.x1 + (line3.x2 - line3.x1) * localPosition; + point.y = line3.y1 + (line3.y2 - line3.y1) * localPosition; + } + else + { + // Line 2 + p -= length1; + localPosition = p / length2; + + point.x = line2.x1 + (line2.x2 - line2.x1) * localPosition; + point.y = line2.y1 + (line2.y2 - line2.y1) * localPosition; + } + + out.push(point); + } + + return out; +}; + +module.exports = GetPoints; + + +/***/ }), + +/***/ 39757: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +// The three angle bisectors of a triangle meet in one point called the incenter. +// It is the center of the incircle, the circle inscribed in the triangle. + +function getLength (x1, y1, x2, y2) +{ + var x = x1 - x2; + var y = y1 - y2; + var magnitude = (x * x) + (y * y); + + return Math.sqrt(magnitude); +} + +/** + * Calculates the position of the incenter of a Triangle object. This is the point where its three angle bisectors meet and it's also the center of the incircle, which is the circle inscribed in the triangle. + * + * @function Phaser.Geom.Triangle.InCenter + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to find the incenter of. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 point in which to store the coordinates. + * + * @return {Phaser.Math.Vector2} The center of the triangle in a Vector2. + */ +var InCenter = function (triangle, out) +{ + if (out === undefined) { out = new Vector2(); } + + var x1 = triangle.x1; + var y1 = triangle.y1; + + var x2 = triangle.x2; + var y2 = triangle.y2; + + var x3 = triangle.x3; + var y3 = triangle.y3; + + var d1 = getLength(x3, y3, x2, y2); + var d2 = getLength(x1, y1, x3, y3); + var d3 = getLength(x2, y2, x1, y1); + + var p = d1 + d2 + d3; + + out.x = (x1 * d1 + x2 * d2 + x3 * d3) / p; + out.y = (y1 * d1 + y2 * d2 + y3 * d3) / p; + + return out; +}; + +module.exports = InCenter; + + +/***/ }), + +/***/ 13584: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves each point (vertex) of a Triangle by a given offset, thus moving the entire Triangle by that offset. + * + * @function Phaser.Geom.Triangle.Offset + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle} O - [triangle,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to move. + * @param {number} x - The horizontal offset (distance) by which to move each point. Can be positive or negative. + * @param {number} y - The vertical offset (distance) by which to move each point. Can be positive or negative. + * + * @return {Phaser.Geom.Triangle} The modified Triangle. + */ +var Offset = function (triangle, x, y) +{ + triangle.x1 += x; + triangle.y1 += y; + + triangle.x2 += x; + triangle.y2 += y; + + triangle.x3 += x; + triangle.y3 += y; + + return triangle; +}; + +module.exports = Offset; + + +/***/ }), + +/***/ 1376: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Length = __webpack_require__(35001); + +/** + * Gets the length of the perimeter of the given triangle. + * Calculated by adding together the length of each of the three sides. + * + * @function Phaser.Geom.Triangle.Perimeter + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to get the length from. + * + * @return {number} The length of the Triangle. + */ +var Perimeter = function (triangle) +{ + var line1 = triangle.getLineA(); + var line2 = triangle.getLineB(); + var line3 = triangle.getLineC(); + + return (Length(line1) + Length(line2) + Length(line3)); +}; + +module.exports = Perimeter; + + +/***/ }), + +/***/ 90260: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a random Point from within the area of the given Triangle. + * + * @function Phaser.Geom.Triangle.Random + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to get a random point from. + * @param {Phaser.Math.Vector2} [out] - The Vector2 point object to store the position in. If not given, a new Vector2 instance is created. + * + * @return {Phaser.Math.Vector2} A Vector2 point object holding the coordinates of a random position within the Triangle. + */ +var Random = function (triangle, out) +{ + if (out === undefined) { out = new Vector2(); } + + // Basis vectors + var ux = triangle.x2 - triangle.x1; + var uy = triangle.y2 - triangle.y1; + + var vx = triangle.x3 - triangle.x1; + var vy = triangle.y3 - triangle.y1; + + // Random point within the unit square + var r = Math.random(); + var s = Math.random(); + + // Point outside the triangle? Remap it. + if (r + s >= 1) + { + r = 1 - r; + s = 1 - s; + } + + out.x = triangle.x1 + ((ux * r) + (vx * s)); + out.y = triangle.y1 + ((uy * r) + (vy * s)); + + return out; +}; + +module.exports = Random; + + +/***/ }), + +/***/ 52172: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateAroundXY = __webpack_require__(99614); +var InCenter = __webpack_require__(39757); + +/** + * Rotates a Triangle about its incenter, which is the point at which its three angle bisectors meet. + * + * @function Phaser.Geom.Triangle.Rotate + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle} O - [triangle,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to rotate. + * @param {number} angle - The angle by which to rotate the Triangle, in radians. + * + * @return {Phaser.Geom.Triangle} The rotated Triangle. + */ +var Rotate = function (triangle, angle) +{ + var point = InCenter(triangle); + + return RotateAroundXY(triangle, point.x, point.y, angle); +}; + +module.exports = Rotate; + + +/***/ }), + +/***/ 49907: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateAroundXY = __webpack_require__(99614); + +/** + * Rotates a Triangle at a certain angle about a given Vector2 point. + * + * @function Phaser.Geom.Triangle.RotateAroundPoint + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle} O - [triangle,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to rotate. + * @param {Phaser.Math.Vector2} point - The Vector2 point to rotate the Triangle around. + * @param {number} angle - The angle by which to rotate the Triangle, in radians. + * + * @return {Phaser.Geom.Triangle} The rotated Triangle. + */ +var RotateAroundPoint = function (triangle, point, angle) +{ + return RotateAroundXY(triangle, point.x, point.y, angle); +}; + +module.exports = RotateAroundPoint; + + +/***/ }), + +/***/ 99614: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rotates an entire Triangle at a given angle about a specific point. + * + * @function Phaser.Geom.Triangle.RotateAroundXY + * @since 3.0.0 + * + * @generic {Phaser.Geom.Triangle} O - [triangle,$return] + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to rotate. + * @param {number} x - The X coordinate of the point to rotate the Triangle about. + * @param {number} y - The Y coordinate of the point to rotate the Triangle about. + * @param {number} angle - The angle by which to rotate the Triangle, in radians. + * + * @return {Phaser.Geom.Triangle} The rotated Triangle. + */ +var RotateAroundXY = function (triangle, x, y, angle) +{ + var c = Math.cos(angle); + var s = Math.sin(angle); + + var tx = triangle.x1 - x; + var ty = triangle.y1 - y; + + triangle.x1 = tx * c - ty * s + x; + triangle.y1 = tx * s + ty * c + y; + + tx = triangle.x2 - x; + ty = triangle.y2 - y; + + triangle.x2 = tx * c - ty * s + x; + triangle.y2 = tx * s + ty * c + y; + + tx = triangle.x3 - x; + ty = triangle.y3 - y; + + triangle.x3 = tx * c - ty * s + x; + triangle.y3 = tx * s + ty * c + y; + + return triangle; +}; + +module.exports = RotateAroundXY; + + +/***/ }), + +/***/ 16483: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Contains = __webpack_require__(10690); +var GetPoint = __webpack_require__(20437); +var GetPoints = __webpack_require__(80672); +var GEOM_CONST = __webpack_require__(23777); +var Line = __webpack_require__(23031); +var Random = __webpack_require__(90260); + +/** + * @classdesc + * A triangle is a plane created by connecting three points. + * The first two arguments specify the first point, the middle two arguments + * specify the second point, and the last two arguments specify the third point. + * + * @class Triangle + * @memberof Phaser.Geom + * @constructor + * @since 3.0.0 + * + * @param {number} [x1=0] - `x` coordinate of the first point. + * @param {number} [y1=0] - `y` coordinate of the first point. + * @param {number} [x2=0] - `x` coordinate of the second point. + * @param {number} [y2=0] - `y` coordinate of the second point. + * @param {number} [x3=0] - `x` coordinate of the third point. + * @param {number} [y3=0] - `y` coordinate of the third point. + */ +var Triangle = new Class({ + + initialize: + + function Triangle (x1, y1, x2, y2, x3, y3) + { + if (x1 === undefined) { x1 = 0; } + if (y1 === undefined) { y1 = 0; } + if (x2 === undefined) { x2 = 0; } + if (y2 === undefined) { y2 = 0; } + if (x3 === undefined) { x3 = 0; } + if (y3 === undefined) { y3 = 0; } + + /** + * The geometry constant type of this object: `GEOM_CONST.TRIANGLE`. + * Used for fast type comparisons. + * + * @name Phaser.Geom.Triangle#type + * @type {number} + * @readonly + * @since 3.19.0 + */ + this.type = GEOM_CONST.TRIANGLE; + + /** + * `x` coordinate of the first point. + * + * @name Phaser.Geom.Triangle#x1 + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x1 = x1; + + /** + * `y` coordinate of the first point. + * + * @name Phaser.Geom.Triangle#y1 + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y1 = y1; + + /** + * `x` coordinate of the second point. + * + * @name Phaser.Geom.Triangle#x2 + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x2 = x2; + + /** + * `y` coordinate of the second point. + * + * @name Phaser.Geom.Triangle#y2 + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y2 = y2; + + /** + * `x` coordinate of the third point. + * + * @name Phaser.Geom.Triangle#x3 + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x3 = x3; + + /** + * `y` coordinate of the third point. + * + * @name Phaser.Geom.Triangle#y3 + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y3 = y3; + }, + + /** + * Checks whether a given points lies within the triangle. + * + * @method Phaser.Geom.Triangle#contains + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the point to check. + * @param {number} y - The y coordinate of the point to check. + * + * @return {boolean} `true` if the coordinate pair is within the triangle, otherwise `false`. + */ + contains: function (x, y) + { + return Contains(this, x, y); + }, + + /** + * Returns a specific point on the triangle. + * + * @method Phaser.Geom.Triangle#getPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [output,$return] + * + * @param {number} position - Position as float within `0` and `1`. `0` equals the first point. + * @param {Phaser.Math.Vector2} [output] - Optional Vector2 point that the calculated point will be written to. + * + * @return {Phaser.Math.Vector2} Calculated Vetor2 that represents the requested position. It is the same as `output` when this parameter has been given. + */ + getPoint: function (position, output) + { + return GetPoint(this, position, output); + }, + + /** + * Calculates a list of evenly distributed points on the triangle. It is either possible to pass an amount of points to be generated (`quantity`) or the distance between two points (`stepRate`). + * + * @method Phaser.Geom.Triangle#getPoints + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2[]} O - [output,$return] + * + * @param {number} quantity - Number of points to be generated. Can be falsey when `stepRate` should be used. All points have the same distance along the triangle. + * @param {number} [stepRate] - Distance between two points. Will only be used when `quantity` is falsey. + * @param {Phaser.Math.Vector2[]} [output] - Optional array of Vector2 points for writing the calculated points into. Otherwise a new array will be created. + * + * @return {Phaser.Math.Vector2[]} Returns a list of calculated `Vector2` instances or the filled array passed as parameter `output`. + */ + getPoints: function (quantity, stepRate, output) + { + return GetPoints(this, quantity, stepRate, output); + }, + + /** + * Returns a random point along the triangle. + * + * @method Phaser.Geom.Triangle#getRandomPoint + * @since 3.0.0 + * + * @generic {Phaser.Math.Vector2} O - [point,$return] + * + * @param {Phaser.Math.Vector2} [vec] - Optional Vector2 point that will be modified. Otherwise a new one will be created. + * + * @return {Phaser.Math.Vector2} Random Vector2. When parameter `vec` has been provided it will be returned. + */ + getRandomPoint: function (vec) + { + return Random(this, vec); + }, + + /** + * Sets all three points of the triangle. Leaving out any coordinate sets it to be `0`. + * + * @method Phaser.Geom.Triangle#setTo + * @since 3.0.0 + * + * @param {number} [x1=0] - `x` coordinate of the first point. + * @param {number} [y1=0] - `y` coordinate of the first point. + * @param {number} [x2=0] - `x` coordinate of the second point. + * @param {number} [y2=0] - `y` coordinate of the second point. + * @param {number} [x3=0] - `x` coordinate of the third point. + * @param {number} [y3=0] - `y` coordinate of the third point. + * + * @return {this} This Triangle object. + */ + setTo: function (x1, y1, x2, y2, x3, y3) + { + if (x1 === undefined) { x1 = 0; } + if (y1 === undefined) { y1 = 0; } + if (x2 === undefined) { x2 = 0; } + if (y2 === undefined) { y2 = 0; } + if (x3 === undefined) { x3 = 0; } + if (y3 === undefined) { y3 = 0; } + + this.x1 = x1; + this.y1 = y1; + + this.x2 = x2; + this.y2 = y2; + + this.x3 = x3; + this.y3 = y3; + + return this; + }, + + /** + * Returns a Line object that corresponds to Line A of this Triangle. + * + * @method Phaser.Geom.Triangle#getLineA + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to line A of this Triangle. + */ + getLineA: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.x1, this.y1, this.x2, this.y2); + + return line; + }, + + /** + * Returns a Line object that corresponds to Line B of this Triangle. + * + * @method Phaser.Geom.Triangle#getLineB + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to line B of this Triangle. + */ + getLineB: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.x2, this.y2, this.x3, this.y3); + + return line; + }, + + /** + * Returns a Line object that corresponds to Line C of this Triangle. + * + * @method Phaser.Geom.Triangle#getLineC + * @since 3.0.0 + * + * @generic {Phaser.Geom.Line} O - [line,$return] + * + * @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created. + * + * @return {Phaser.Geom.Line} A Line object that corresponds to line C of this Triangle. + */ + getLineC: function (line) + { + if (line === undefined) { line = new Line(); } + + line.setTo(this.x3, this.y3, this.x1, this.y1); + + return line; + }, + + /** + * Left most X coordinate of the triangle. Setting it moves the triangle on the X axis accordingly. + * + * @name Phaser.Geom.Triangle#left + * @type {number} + * @since 3.0.0 + */ + left: { + + get: function () + { + return Math.min(this.x1, this.x2, this.x3); + }, + + set: function (value) + { + var diff = 0; + + if (this.x1 <= this.x2 && this.x1 <= this.x3) + { + diff = this.x1 - value; + } + else if (this.x2 <= this.x1 && this.x2 <= this.x3) + { + diff = this.x2 - value; + } + else + { + diff = this.x3 - value; + } + + this.x1 -= diff; + this.x2 -= diff; + this.x3 -= diff; + } + + }, + + /** + * Right most X coordinate of the triangle. Setting it moves the triangle on the X axis accordingly. + * + * @name Phaser.Geom.Triangle#right + * @type {number} + * @since 3.0.0 + */ + right: { + + get: function () + { + return Math.max(this.x1, this.x2, this.x3); + }, + + set: function (value) + { + var diff = 0; + + if (this.x1 >= this.x2 && this.x1 >= this.x3) + { + diff = this.x1 - value; + } + else if (this.x2 >= this.x1 && this.x2 >= this.x3) + { + diff = this.x2 - value; + } + else + { + diff = this.x3 - value; + } + + this.x1 -= diff; + this.x2 -= diff; + this.x3 -= diff; + } + + }, + + /** + * Top most Y coordinate of the triangle. Setting it moves the triangle on the Y axis accordingly. + * + * @name Phaser.Geom.Triangle#top + * @type {number} + * @since 3.0.0 + */ + top: { + + get: function () + { + return Math.min(this.y1, this.y2, this.y3); + }, + + set: function (value) + { + var diff = 0; + + if (this.y1 <= this.y2 && this.y1 <= this.y3) + { + diff = this.y1 - value; + } + else if (this.y2 <= this.y1 && this.y2 <= this.y3) + { + diff = this.y2 - value; + } + else + { + diff = this.y3 - value; + } + + this.y1 -= diff; + this.y2 -= diff; + this.y3 -= diff; + } + + }, + + /** + * Bottom most Y coordinate of the triangle. Setting it moves the triangle on the Y axis accordingly. + * + * @name Phaser.Geom.Triangle#bottom + * @type {number} + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return Math.max(this.y1, this.y2, this.y3); + }, + + set: function (value) + { + var diff = 0; + + if (this.y1 >= this.y2 && this.y1 >= this.y3) + { + diff = this.y1 - value; + } + else if (this.y2 >= this.y1 && this.y2 >= this.y3) + { + diff = this.y2 - value; + } + else + { + diff = this.y3 - value; + } + + this.y1 -= diff; + this.y2 -= diff; + this.y3 -= diff; + } + + } + +}); + +module.exports = Triangle; + + +/***/ }), + +/***/ 84435: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Triangle = __webpack_require__(16483); + +Triangle.Area = __webpack_require__(41658); +Triangle.BuildEquilateral = __webpack_require__(39208); +Triangle.BuildFromPolygon = __webpack_require__(39545); +Triangle.BuildRight = __webpack_require__(90301); +Triangle.CenterOn = __webpack_require__(23707); +Triangle.Centroid = __webpack_require__(97523); +Triangle.CircumCenter = __webpack_require__(24951); +Triangle.CircumCircle = __webpack_require__(85614); +Triangle.Clone = __webpack_require__(74422); +Triangle.Contains = __webpack_require__(10690); +Triangle.ContainsArray = __webpack_require__(48653); +Triangle.ContainsPoint = __webpack_require__(96006); +Triangle.CopyFrom = __webpack_require__(71326); +Triangle.Decompose = __webpack_require__(71694); +Triangle.Equals = __webpack_require__(33522); +Triangle.GetPoint = __webpack_require__(20437); +Triangle.GetPoints = __webpack_require__(80672); +Triangle.InCenter = __webpack_require__(39757); +Triangle.Perimeter = __webpack_require__(1376); +Triangle.Offset = __webpack_require__(13584); +Triangle.Random = __webpack_require__(90260); +Triangle.Rotate = __webpack_require__(52172); +Triangle.RotateAroundPoint = __webpack_require__(49907); +Triangle.RotateAroundXY = __webpack_require__(99614); + +module.exports = Triangle; + + +/***/ }), + +/***/ 74457: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Creates a new Interactive Object. + * + * This is called automatically by the Input Manager when you enable a Game Object for input. + * + * The resulting Interactive Object is mapped to the Game Object's `input` property. + * + * @function Phaser.Input.CreateInteractiveObject + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to which this Interactive Object is bound. + * @param {any} hitArea - The hit area for this Interactive Object. Typically a geometry shape, like a Rectangle or Circle. + * @param {Phaser.Types.Input.HitAreaCallback} hitAreaCallback - The 'contains' check callback that the hit area shape will use for all hit tests. + * + * @return {Phaser.Types.Input.InteractiveObject} The new Interactive Object. + */ +var CreateInteractiveObject = function (gameObject, hitArea, hitAreaCallback) +{ + return { + + gameObject: gameObject, + + enabled: true, + draggable: false, + dropZone: false, + cursor: false, + + target: null, + + camera: null, + + hitArea: hitArea, + hitAreaCallback: hitAreaCallback, + hitAreaDebug: null, + + // Has the dev specified their own shape, or is this bound to the texture size? + customHitArea: false, + + localX: 0, + localY: 0, + + // 0 = Not being dragged + // 1 = Being checked for dragging + // 2 = Being dragged + dragState: 0, + + dragStartX: 0, + dragStartY: 0, + dragStartXGlobal: 0, + dragStartYGlobal: 0, + dragStartCamera: null, + + dragX: 0, + dragY: 0 + + }; +}; + +module.exports = CreateInteractiveObject; + + +/***/ }), + +/***/ 84409: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Creates a new Pixel Perfect Handler function. + * + * Access via `InputPlugin.makePixelPerfect` rather than calling it directly. + * + * @function Phaser.Input.CreatePixelPerfectHandler + * @since 3.10.0 + * + * @param {Phaser.Textures.TextureManager} textureManager - A reference to the Texture Manager. + * @param {number} alphaTolerance - The alpha level that the pixel should be above to be included as a successful interaction. + * + * @return {function} The new Pixel Perfect Handler function. + */ +var CreatePixelPerfectHandler = function (textureManager, alphaTolerance) +{ + return function (hitArea, x, y, gameObject) + { + var alpha = textureManager.getPixelAlpha(x, y, gameObject.texture.key, gameObject.frame.name); + + return (alpha && alpha >= alphaTolerance); + }; +}; + +module.exports = CreatePixelPerfectHandler; + + +/***/ }), + +/***/ 7003: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(93301); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(8214); +var GameEvents = __webpack_require__(8443); +var Keyboard = __webpack_require__(78970); +var Mouse = __webpack_require__(85098); +var Pointer = __webpack_require__(42515); +var Touch = __webpack_require__(36210); +var TransformMatrix = __webpack_require__(61340); +var TransformXY = __webpack_require__(85955); + +/** + * @classdesc + * The Input Manager is responsible for handling the pointer related systems in a single Phaser Game instance. + * + * Based on the Game Config it will create handlers for mouse and touch support. + * + * Keyboard and Gamepad are plugins, handled directly by the InputPlugin class. + * + * It then manages the events, pointer creation and general hit test related operations. + * + * You rarely need to interact with the Input Manager directly, and as such, all of its properties and methods + * should be considered private. Instead, you should use the Input Plugin, which is a Scene level system, responsible + * for dealing with all input events for a Scene. + * + * @class InputManager + * @memberof Phaser.Input + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Game instance that owns the Input Manager. + * @param {object} config - The Input Configuration object, as set in the Game Config. + */ +var InputManager = new Class({ + + initialize: + + function InputManager (game, config) + { + /** + * The Game instance that owns the Input Manager. + * A Game only maintains one instance of the Input Manager at any time. + * + * @name Phaser.Input.InputManager#game + * @type {Phaser.Game} + * @readonly + * @since 3.0.0 + */ + this.game = game; + + /** + * A reference to the global Game Scale Manager. + * Used for all bounds checks and pointer scaling. + * + * @name Phaser.Input.InputManager#scaleManager + * @type {Phaser.Scale.ScaleManager} + * @since 3.16.0 + */ + this.scaleManager; + + /** + * The Canvas that is used for all DOM event input listeners. + * + * @name Phaser.Input.InputManager#canvas + * @type {HTMLCanvasElement} + * @since 3.0.0 + */ + this.canvas; + + /** + * The Game Configuration object, as set during the game boot. + * + * @name Phaser.Input.InputManager#config + * @type {Phaser.Core.Config} + * @since 3.0.0 + */ + this.config = config; + + /** + * If set, the Input Manager will run its update loop every frame. + * + * @name Phaser.Input.InputManager#enabled + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.enabled = true; + + /** + * The Event Emitter instance that the Input Manager uses to emit events from. + * + * @name Phaser.Input.InputManager#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events = new EventEmitter(); + + /** + * Are any mouse or touch pointers currently over the game canvas? + * This is updated automatically by the canvas over and out handlers. + * + * @name Phaser.Input.InputManager#isOver + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + this.isOver = true; + + /** + * The default CSS cursor to be used when interacting with your game. + * + * See the `setDefaultCursor` method for more details. + * + * @name Phaser.Input.InputManager#defaultCursor + * @type {string} + * @since 3.10.0 + */ + this.defaultCursor = ''; + + /** + * A reference to the Keyboard Manager class, if enabled via the `input.keyboard` Game Config property. + * + * @name Phaser.Input.InputManager#keyboard + * @type {?Phaser.Input.Keyboard.KeyboardManager} + * @since 3.16.0 + */ + this.keyboard = (config.inputKeyboard) ? new Keyboard(this) : null; + + /** + * A reference to the Mouse Manager class, if enabled via the `input.mouse` Game Config property. + * + * @name Phaser.Input.InputManager#mouse + * @type {?Phaser.Input.Mouse.MouseManager} + * @since 3.0.0 + */ + this.mouse = (config.inputMouse) ? new Mouse(this) : null; + + /** + * A reference to the Touch Manager class, if enabled via the `input.touch` Game Config property. + * + * @name Phaser.Input.InputManager#touch + * @type {Phaser.Input.Touch.TouchManager} + * @since 3.0.0 + */ + this.touch = (config.inputTouch) ? new Touch(this) : null; + + /** + * An array of Pointers that have been added to the game. + * The first entry is reserved for the Mouse Pointer, the rest are Touch Pointers. + * + * By default there is 1 touch pointer enabled. If you need more use the `addPointer` method to start them, + * or set the `input.activePointers` property in the Game Config. + * + * @name Phaser.Input.InputManager#pointers + * @type {Phaser.Input.Pointer[]} + * @since 3.10.0 + */ + this.pointers = []; + + /** + * The number of touch objects activated and being processed each update. + * + * You can change this by either calling `addPointer` at run-time, or by + * setting the `input.activePointers` property in the Game Config. + * + * @name Phaser.Input.InputManager#pointersTotal + * @type {number} + * @readonly + * @since 3.10.0 + */ + this.pointersTotal = config.inputActivePointers; + + for (var i = 0; i <= this.pointersTotal; i++) + { + var pointer = new Pointer(this, i); + + pointer.smoothFactor = config.inputSmoothFactor; + + this.pointers.push(pointer); + } + + /** + * The mouse has its own unique Pointer object, which you can reference directly if making a _desktop specific game_. + * If you are supporting both desktop and touch devices then do not use this property, instead use `activePointer` + * which will always map to the most recently interacted pointer. + * + * @name Phaser.Input.InputManager#mousePointer + * @type {?Phaser.Input.Pointer} + * @since 3.10.0 + */ + this.mousePointer = (config.inputMouse) ? this.pointers[0] : null; + + /** + * The most recently active Pointer object. + * + * If you've only 1 Pointer in your game then this will accurately be either the first finger touched, or the mouse. + * + * If your game doesn't need to support multi-touch then you can safely use this property in all of your game + * code and it will adapt to be either the mouse or the touch, based on device. + * + * @name Phaser.Input.InputManager#activePointer + * @type {Phaser.Input.Pointer} + * @since 3.0.0 + */ + this.activePointer = this.pointers[0]; + + /** + * If the top-most Scene in the Scene List receives an input it will stop input from + * propagating any lower down the scene list, i.e. if you have a UI Scene at the top + * and click something on it, that click will not then be passed down to any other + * Scene below. Disable this to have input events passed through all Scenes, all the time. + * + * @name Phaser.Input.InputManager#globalTopOnly + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.globalTopOnly = true; + + /** + * The time this Input Manager was last updated. + * This value is populated by the Game Step each frame. + * + * @name Phaser.Input.InputManager#time + * @type {number} + * @readonly + * @since 3.16.2 + */ + this.time = 0; + + /** + * A re-cycled point-like object to store hit test values in. + * + * @name Phaser.Input.InputManager#_tempPoint + * @type {{x:number, y:number}} + * @private + * @since 3.0.0 + */ + this._tempPoint = { x: 0, y: 0 }; + + /** + * A re-cycled array to store hit results in. + * + * @name Phaser.Input.InputManager#_tempHitTest + * @type {array} + * @private + * @default [] + * @since 3.0.0 + */ + this._tempHitTest = []; + + /** + * A re-cycled matrix used in hit test calculations. + * + * @name Phaser.Input.InputManager#_tempMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 3.4.0 + */ + this._tempMatrix = new TransformMatrix(); + + /** + * A re-cycled matrix used in hit test calculations. + * + * @name Phaser.Input.InputManager#_tempMatrix2 + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 3.12.0 + */ + this._tempMatrix2 = new TransformMatrix(); + + /** + * An internal private var that records Scenes aborting event processing. + * + * @name Phaser.Input.InputManager#_tempSkip + * @type {boolean} + * @private + * @since 3.18.0 + */ + this._tempSkip = false; + + /** + * An internal private array that avoids needing to create a new array on every DOM mouse event. + * + * @name Phaser.Input.InputManager#mousePointerContainer + * @type {Phaser.Input.Pointer[]} + * @private + * @since 3.18.0 + */ + this.mousePointerContainer = [ this.mousePointer ]; + + game.events.once(GameEvents.BOOT, this.boot, this); + }, + + /** + * The Boot handler is called by Phaser.Game when it first starts up. + * The renderer is available by now. + * + * @method Phaser.Input.InputManager#boot + * @protected + * @fires Phaser.Input.Events#MANAGER_BOOT + * @since 3.0.0 + */ + boot: function () + { + var game = this.game; + var events = game.events; + + this.canvas = game.canvas; + + this.scaleManager = game.scale; + + this.events.emit(Events.MANAGER_BOOT); + + events.on(GameEvents.PRE_RENDER, this.preRender, this); + + events.once(GameEvents.DESTROY, this.destroy, this); + }, + + /** + * Internal canvas state change, called automatically by the Mouse Manager. + * + * @method Phaser.Input.InputManager#setCanvasOver + * @fires Phaser.Input.Events#GAME_OVER + * @private + * @since 3.16.0 + * + * @param {(MouseEvent|TouchEvent)} event - The DOM Event. + */ + setCanvasOver: function (event) + { + this.isOver = true; + + this.events.emit(Events.GAME_OVER, event); + }, + + /** + * Internal canvas state change, called automatically by the Mouse Manager. + * + * @method Phaser.Input.InputManager#setCanvasOut + * @fires Phaser.Input.Events#GAME_OUT + * @private + * @since 3.16.0 + * + * @param {(MouseEvent|TouchEvent)} event - The DOM Event. + */ + setCanvasOut: function (event) + { + this.isOver = false; + + this.events.emit(Events.GAME_OUT, event); + }, + + /** + * Internal update, called automatically by the Game Step right at the start. + * + * @method Phaser.Input.InputManager#preRender + * @private + * @since 3.18.0 + */ + preRender: function () + { + var time = this.game.loop.now; + var delta = this.game.loop.delta; + var scenes = this.game.scene.getScenes(true, true); + + this.time = time; + + this.events.emit(Events.MANAGER_UPDATE); + + for (var i = 0; i < scenes.length; i++) + { + var scene = scenes[i]; + + if (scene.sys.input && scene.sys.input.updatePoll(time, delta) && this.globalTopOnly) + { + // If the Scene returns true, it means it captured some input that no other Scene should get, so we bail out + return; + } + } + }, + + /** + * Tells the Input system to set a custom cursor. + * + * This cursor will be the default cursor used when interacting with the game canvas. + * + * If an Interactive Object also sets a custom cursor, this is the cursor that is reset after its use. + * + * Any valid CSS cursor value is allowed, including paths to image files, i.e.: + * + * ```javascript + * this.input.setDefaultCursor('url(assets/cursors/sword.cur), pointer'); + * ``` + * + * Please read about the differences between browsers when it comes to the file formats and sizes they support: + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/cursor + * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_User_Interface/Using_URL_values_for_the_cursor_property + * + * It's up to you to pick a suitable cursor format that works across the range of browsers you need to support. + * + * @method Phaser.Input.InputManager#setDefaultCursor + * @since 3.10.0 + * + * @param {string} cursor - The CSS to be used when setting the default cursor. + */ + setDefaultCursor: function (cursor) + { + this.defaultCursor = cursor; + + if (this.canvas.style.cursor !== cursor) + { + this.canvas.style.cursor = cursor; + } + }, + + /** + * Called by the InputPlugin when processing over and out events. + * + * Tells the Input Manager to set a custom cursor during its postUpdate step. + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/cursor + * + * @method Phaser.Input.InputManager#setCursor + * @private + * @since 3.10.0 + * + * @param {Phaser.Types.Input.InteractiveObject} interactiveObject - The Interactive Object that called this method. + */ + setCursor: function (interactiveObject) + { + if (interactiveObject.cursor) + { + this.canvas.style.cursor = interactiveObject.cursor; + } + }, + + /** + * Called by the InputPlugin when processing over and out events. + * + * Tells the Input Manager to clear the hand cursor, if set, during its postUpdate step. + * + * @method Phaser.Input.InputManager#resetCursor + * @private + * @since 3.10.0 + * + * @param {Phaser.Types.Input.InteractiveObject} interactiveObject - The Interactive Object that called this method. Pass `null` if you just want to set the force value. + * @param {boolean} [forceReset=false] - Should the reset happen regardless of the object's cursor state? Default false. + */ + resetCursor: function (interactiveObject, forceReset) + { + if ((forceReset || (interactiveObject && interactiveObject.cursor)) && this.canvas) + { + this.canvas.style.cursor = this.defaultCursor; + } + }, + + /** + * Adds new Pointer objects to the Input Manager. + * + * By default Phaser creates 2 pointer objects: `mousePointer` and `pointer1`. + * + * You can create more either by calling this method, or by setting the `input.activePointers` property + * in the Game Config, up to a maximum of 10 pointers. + * + * The first 10 pointers are available via the `InputPlugin.pointerX` properties, once they have been added + * via this method. + * + * @method Phaser.Input.InputManager#addPointer + * @since 3.10.0 + * + * @param {number} [quantity=1] The number of new Pointers to create. A maximum of 10 is allowed in total. + * + * @return {Phaser.Input.Pointer[]} An array containing all of the new Pointer objects that were created. + */ + addPointer: function (quantity) + { + if (quantity === undefined) { quantity = 1; } + + var output = []; + + if (this.pointersTotal + quantity > 10) + { + quantity = 10 - this.pointersTotal; + } + + for (var i = 0; i < quantity; i++) + { + var id = this.pointers.length; + + var pointer = new Pointer(this, id); + + pointer.smoothFactor = this.config.inputSmoothFactor; + + this.pointers.push(pointer); + + this.pointersTotal++; + + output.push(pointer); + } + + return output; + }, + + /** + * Internal method that gets a list of all the active Input Plugins in the game + * and updates each of them in turn, in reverse order (top to bottom), to allow + * for DOM top-level event handling simulation. + * + * @method Phaser.Input.InputManager#updateInputPlugins + * @since 3.16.0 + * + * @param {number} type - The type of event to process. + * @param {Phaser.Input.Pointer[]} pointers - An array of Pointers on which the event occurred. + */ + updateInputPlugins: function (type, pointers) + { + var scenes = this.game.scene.getScenes(false, true); + + this._tempSkip = false; + + for (var i = 0; i < scenes.length; i++) + { + var scene = scenes[i]; + + if (scene.sys.input) + { + var capture = scene.sys.input.update(type, pointers); + + if ((capture && this.globalTopOnly) || this._tempSkip) + { + // If the Scene returns true, or called stopPropagation, it means it captured some input that no other Scene should get, so we bail out + return; + } + } + } + }, + + // event.targetTouches = list of all touches on the TARGET ELEMENT (i.e. game dom element) + // event.touches = list of all touches on the ENTIRE DOCUMENT, not just the target element + // event.changedTouches = the touches that CHANGED in this event, not the total number of them + + /** + * Processes a touch start event, as passed in by the TouchManager. + * + * @method Phaser.Input.InputManager#onTouchStart + * @private + * @since 3.18.0 + * + * @param {TouchEvent} event - The native DOM Touch event. + */ + onTouchStart: function (event) + { + var pointers = this.pointers; + var changed = []; + + for (var c = 0; c < event.changedTouches.length; c++) + { + var changedTouch = event.changedTouches[c]; + + for (var i = 1; i < pointers.length; i++) + { + var pointer = pointers[i]; + + if (!pointer.active) + { + pointer.touchstart(changedTouch, event); + + this.activePointer = pointer; + + changed.push(pointer); + + break; + } + } + } + + this.updateInputPlugins(CONST.TOUCH_START, changed); + }, + + /** + * Processes a touch move event, as passed in by the TouchManager. + * + * @method Phaser.Input.InputManager#onTouchMove + * @private + * @since 3.18.0 + * + * @param {TouchEvent} event - The native DOM Touch event. + */ + onTouchMove: function (event) + { + var pointers = this.pointers; + var changed = []; + + for (var c = 0; c < event.changedTouches.length; c++) + { + var changedTouch = event.changedTouches[c]; + + for (var i = 1; i < pointers.length; i++) + { + var pointer = pointers[i]; + + if (pointer.active && pointer.identifier === changedTouch.identifier) + { + var element = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY); + var overCanvas = element === this.canvas; + + if (!this.isOver && overCanvas) + { + this.setCanvasOver(event); + } + else if (this.isOver && !overCanvas) + { + this.setCanvasOut(event); + } + + if (this.isOver) + { + pointer.touchmove(changedTouch, event); + + this.activePointer = pointer; + + changed.push(pointer); + } + + break; + } + } + } + + this.updateInputPlugins(CONST.TOUCH_MOVE, changed); + }, + + // For touch end its a list of the touch points that have been removed from the surface + // https://developer.mozilla.org/en-US/docs/DOM/TouchList + // event.changedTouches = the touches that CHANGED in this event, not the total number of them + + /** + * Processes a touch end event, as passed in by the TouchManager. + * + * @method Phaser.Input.InputManager#onTouchEnd + * @private + * @since 3.18.0 + * + * @param {TouchEvent} event - The native DOM Touch event. + */ + onTouchEnd: function (event) + { + var pointers = this.pointers; + var changed = []; + + for (var c = 0; c < event.changedTouches.length; c++) + { + var changedTouch = event.changedTouches[c]; + + for (var i = 1; i < pointers.length; i++) + { + var pointer = pointers[i]; + + if (pointer.active && pointer.identifier === changedTouch.identifier) + { + pointer.touchend(changedTouch, event); + + changed.push(pointer); + + break; + } + } + } + + this.updateInputPlugins(CONST.TOUCH_END, changed); + }, + + /** + * Processes a touch cancel event, as passed in by the TouchManager. + * + * @method Phaser.Input.InputManager#onTouchCancel + * @private + * @since 3.18.0 + * + * @param {TouchEvent} event - The native DOM Touch event. + */ + onTouchCancel: function (event) + { + var pointers = this.pointers; + var changed = []; + + for (var c = 0; c < event.changedTouches.length; c++) + { + var changedTouch = event.changedTouches[c]; + + for (var i = 1; i < pointers.length; i++) + { + var pointer = pointers[i]; + + if (pointer.active && pointer.identifier === changedTouch.identifier) + { + pointer.touchcancel(changedTouch, event); + + changed.push(pointer); + + break; + } + } + } + + this.updateInputPlugins(CONST.TOUCH_CANCEL, changed); + }, + + /** + * Processes a mouse down event, as passed in by the MouseManager. + * + * @method Phaser.Input.InputManager#onMouseDown + * @private + * @since 3.18.0 + * + * @param {MouseEvent} event - The native DOM Mouse event. + */ + onMouseDown: function (event) + { + var mousePointer = this.mousePointer; + + mousePointer.down(event); + + mousePointer.updateMotion(); + + this.activePointer = mousePointer; + + this.updateInputPlugins(CONST.MOUSE_DOWN, this.mousePointerContainer); + }, + + /** + * Processes a mouse move event, as passed in by the MouseManager. + * + * @method Phaser.Input.InputManager#onMouseMove + * @private + * @since 3.18.0 + * + * @param {MouseEvent} event - The native DOM Mouse event. + */ + onMouseMove: function (event) + { + var mousePointer = this.mousePointer; + + mousePointer.move(event); + + mousePointer.updateMotion(); + + this.activePointer = mousePointer; + + this.updateInputPlugins(CONST.MOUSE_MOVE, this.mousePointerContainer); + }, + + /** + * Processes a mouse up event, as passed in by the MouseManager. + * + * @method Phaser.Input.InputManager#onMouseUp + * @private + * @since 3.18.0 + * + * @param {MouseEvent} event - The native DOM Mouse event. + */ + onMouseUp: function (event) + { + var mousePointer = this.mousePointer; + + mousePointer.up(event); + + mousePointer.updateMotion(); + + this.activePointer = mousePointer; + + this.updateInputPlugins(CONST.MOUSE_UP, this.mousePointerContainer); + }, + + /** + * Processes a mouse wheel event, as passed in by the MouseManager. + * + * @method Phaser.Input.InputManager#onMouseWheel + * @private + * @since 3.18.0 + * + * @param {WheelEvent} event - The native DOM Wheel event. + */ + onMouseWheel: function (event) + { + var mousePointer = this.mousePointer; + + mousePointer.wheel(event); + + this.activePointer = mousePointer; + + this.updateInputPlugins(CONST.MOUSE_WHEEL, this.mousePointerContainer); + }, + + /** + * Processes a pointer lock change event, as passed in by the MouseManager. + * + * @method Phaser.Input.InputManager#onPointerLockChange + * @fires Phaser.Input.Events#POINTERLOCK_CHANGE + * @private + * @since 3.19.0 + * + * @param {MouseEvent} event - The native DOM Mouse event. + */ + onPointerLockChange: function (event) + { + var isLocked = this.mouse.locked; + + this.mousePointer.locked = isLocked; + + this.events.emit(Events.POINTERLOCK_CHANGE, event, isLocked); + }, + + /** + * Checks if the given Game Object should be considered as a candidate for input or not. + * + * Checks if the Game Object has an input component that is enabled, that it will render, + * and finally, if it has a parent, that the parent parent, or any ancestor, is visible or not. + * + * @method Phaser.Input.InputManager#inputCandidate + * @private + * @since 3.10.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to test. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera which is being tested against. + * + * @return {boolean} `true` if the Game Object should be considered for input, otherwise `false`. + */ + inputCandidate: function (gameObject, camera) + { + var input = gameObject.input; + + if (!input || !input.enabled || !gameObject.willRender(camera)) + { + return false; + } + + var visible = true; + var parent = gameObject.parentContainer; + + if (parent) + { + do + { + if (!parent.willRender(camera)) + { + visible = false; + break; + } + + parent = parent.parentContainer; + + } while (parent); + } + + return visible; + }, + + /** + * Performs a hit test using the given Pointer and camera, against an array of interactive Game Objects. + * + * The Game Objects are culled against the camera, and then the coordinates are translated into the local camera space + * and used to determine if they fall within the remaining Game Objects hit areas or not. + * + * If nothing is matched an empty array is returned. + * + * This method is called automatically by InputPlugin.hitTestPointer and doesn't usually need to be invoked directly. + * + * @method Phaser.Input.InputManager#hitTest + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to test against. + * @param {array} gameObjects - An array of interactive Game Objects to check. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera which is being tested against. + * @param {array} [output] - An array to store the results in. If not given, a new empty array is created. + * + * @return {array} An array of the Game Objects that were hit during this hit test. + */ + hitTest: function (pointer, gameObjects, camera, output) + { + if (output === undefined) { output = this._tempHitTest; } + + var tempPoint = this._tempPoint; + + var csx = camera.scrollX; + var csy = camera.scrollY; + + output.length = 0; + + var x = pointer.x; + var y = pointer.y; + + // Stores the world point inside of tempPoint + camera.getWorldPoint(x, y, tempPoint); + + pointer.worldX = tempPoint.x; + pointer.worldY = tempPoint.y; + + var point = { x: 0, y: 0 }; + + var matrix = this._tempMatrix; + var parentMatrix = this._tempMatrix2; + + for (var i = 0; i < gameObjects.length; i++) + { + var gameObject = gameObjects[i]; + + // Checks if the Game Object can receive input (isn't being ignored by the camera, invisible, etc) + // and also checks all of its parents, if any + if (!this.inputCandidate(gameObject, camera)) + { + continue; + } + + var px = tempPoint.x + (csx * gameObject.scrollFactorX) - csx; + var py = tempPoint.y + (csy * gameObject.scrollFactorY) - csy; + + if (gameObject.parentContainer) + { + gameObject.getWorldTransformMatrix(matrix, parentMatrix); + + matrix.applyInverse(px, py, point); + } + else + { + TransformXY(px, py, gameObject.x, gameObject.y, gameObject.rotation, gameObject.scaleX, gameObject.scaleY, point); + } + + if (this.pointWithinHitArea(gameObject, point.x, point.y)) + { + output.push(gameObject); + } + } + + return output; + }, + + /** + * Checks if the given x and y coordinate are within the hit area of the Game Object. + * + * This method assumes that the coordinate values have already been translated into the space of the Game Object. + * + * If the coordinates are within the hit area they are set into the Game Objects Input `localX` and `localY` properties. + * + * @method Phaser.Input.InputManager#pointWithinHitArea + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object to check against. + * @param {number} x - The translated x coordinate for the hit test. + * @param {number} y - The translated y coordinate for the hit test. + * + * @return {boolean} `true` if the coordinates were inside the Game Objects hit area, otherwise `false`. + */ + pointWithinHitArea: function (gameObject, x, y) + { + // Normalize the origin + x += gameObject.displayOriginX; + y += gameObject.displayOriginY; + + var input = gameObject.input; + + if (input && input.hitAreaCallback(input.hitArea, x, y, gameObject)) + { + input.localX = x; + input.localY = y; + + return true; + } + else + { + return false; + } + }, + + /** + * Checks if the given x and y coordinate are within the hit area of the Interactive Object. + * + * This method assumes that the coordinate values have already been translated into the space of the Interactive Object. + * + * If the coordinates are within the hit area they are set into the Interactive Objects Input `localX` and `localY` properties. + * + * @method Phaser.Input.InputManager#pointWithinInteractiveObject + * @since 3.0.0 + * + * @param {Phaser.Types.Input.InteractiveObject} object - The Interactive Object to check against. + * @param {number} x - The translated x coordinate for the hit test. + * @param {number} y - The translated y coordinate for the hit test. + * + * @return {boolean} `true` if the coordinates were inside the Game Objects hit area, otherwise `false`. + */ + pointWithinInteractiveObject: function (object, x, y) + { + if (!object.hitArea) + { + return false; + } + + // Normalize the origin + x += object.gameObject.displayOriginX; + y += object.gameObject.displayOriginY; + + object.localX = x; + object.localY = y; + + return object.hitAreaCallback(object.hitArea, x, y, object); + }, + + /** + * Transforms the pageX and pageY values of a Pointer into the scaled coordinate space of the Input Manager. + * + * @method Phaser.Input.InputManager#transformPointer + * @since 3.10.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to transform the values for. + * @param {number} pageX - The Page X value. + * @param {number} pageY - The Page Y value. + * @param {boolean} wasMove - Are we transforming the Pointer from a move event, or an up / down event? + */ + transformPointer: function (pointer, pageX, pageY, wasMove) + { + var p0 = pointer.position; + var p1 = pointer.prevPosition; + + // Store previous position + p1.x = p0.x; + p1.y = p0.y; + + // Translate coordinates + var x = this.scaleManager.transformX(pageX); + var y = this.scaleManager.transformY(pageY); + + var a = pointer.smoothFactor; + + if (!wasMove || a === 0) + { + // Set immediately + p0.x = x; + p0.y = y; + } + else + { + // Apply smoothing + p0.x = x * a + p1.x * (1 - a); + p0.y = y * a + p1.y * (1 - a); + } + }, + + /** + * Destroys the Input Manager and all of its systems. + * + * There is no way to recover from doing this. + * + * @method Phaser.Input.InputManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.events.removeAllListeners(); + + this.game.events.off(GameEvents.PRE_RENDER); + + if (this.keyboard) + { + this.keyboard.destroy(); + } + + if (this.mouse) + { + this.mouse.destroy(); + } + + if (this.touch) + { + this.touch.destroy(); + } + + for (var i = 0; i < this.pointers.length; i++) + { + this.pointers[i].destroy(); + } + + this.pointers = []; + this._tempHitTest = []; + this._tempMatrix.destroy(); + this.canvas = null; + this.game = null; + } + +}); + +module.exports = InputManager; + + +/***/ }), + +/***/ 48205: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Circle = __webpack_require__(96503); +var CircleContains = __webpack_require__(87902); +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(93301); +var CreateInteractiveObject = __webpack_require__(74457); +var CreatePixelPerfectHandler = __webpack_require__(84409); +var DistanceBetween = __webpack_require__(20339); +var Ellipse = __webpack_require__(8497); +var EllipseContains = __webpack_require__(81154); +var Events = __webpack_require__(8214); +var EventEmitter = __webpack_require__(50792); +var GetFastValue = __webpack_require__(95540); +var GEOM_CONST = __webpack_require__(23777); +var InputPluginCache = __webpack_require__(89639); +var IsPlainObject = __webpack_require__(41212); +var PluginCache = __webpack_require__(37277); +var Rectangle = __webpack_require__(87841); +var RectangleContains = __webpack_require__(37303); +var SceneEvents = __webpack_require__(44594); +var Triangle = __webpack_require__(16483); +var TriangleContains = __webpack_require__(10690); + +/** + * @classdesc + * The Input Plugin belongs to a Scene and handles all input related events and operations for it. + * + * You can access it from within a Scene using `this.input`. + * + * It emits events directly. For example, you can do: + * + * ```javascript + * this.input.on('pointerdown', callback, context); + * ``` + * + * To listen for a pointer down event anywhere on the game canvas. + * + * Game Objects can be enabled for input by calling their `setInteractive` method. After which they + * will directly emit input events: + * + * ```javascript + * var sprite = this.add.sprite(x, y, texture); + * sprite.setInteractive(); + * sprite.on('pointerdown', callback, context); + * ``` + * + * There are lots of game configuration options available relating to input. + * See the [Input Config object]{@linkcode Phaser.Types.Core.InputConfig} for more details, including how to deal with Phaser + * listening for input events outside of the canvas, how to set a default number of pointers, input + * capture settings and more. + * + * Please also see the Input examples and tutorials for further information. + * + * **Incorrect input coordinates with Angular** + * + * If you are using Phaser within Angular, and use nglf or the router, to make the component in which the Phaser game resides + * change state (i.e. appear or disappear) then you'll need to notify the Scale Manager about this, as Angular will mess with + * the DOM in a way in which Phaser can't detect directly. Call `this.scale.updateBounds()` as part of your game init in order + * to refresh the canvas DOM bounds values, which Phaser uses for input point position calculations. + * + * @class InputPlugin + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Input + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - A reference to the Scene that this Input Plugin is responsible for. + */ +var InputPlugin = new Class({ + + Extends: EventEmitter, + + initialize: + + function InputPlugin (scene) + { + EventEmitter.call(this); + + /** + * A reference to the Scene that this Input Plugin is responsible for. + * + * @name Phaser.Input.InputPlugin#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene Systems class. + * + * @name Phaser.Input.InputPlugin#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * A reference to the Scene Systems Settings. + * + * @name Phaser.Input.InputPlugin#settings + * @type {Phaser.Types.Scenes.SettingsObject} + * @since 3.5.0 + */ + this.settings = scene.sys.settings; + + /** + * A reference to the Game Input Manager. + * + * @name Phaser.Input.InputPlugin#manager + * @type {Phaser.Input.InputManager} + * @since 3.0.0 + */ + this.manager = scene.sys.game.input; + + /** + * Internal event queue used for plugins only. + * + * @name Phaser.Input.InputPlugin#pluginEvents + * @type {Phaser.Events.EventEmitter} + * @private + * @since 3.10.0 + */ + this.pluginEvents = new EventEmitter(); + + /** + * If `true` this Input Plugin will process DOM input events. + * + * @name Phaser.Input.InputPlugin#enabled + * @type {boolean} + * @default true + * @since 3.5.0 + */ + this.enabled = true; + + /** + * A reference to the Scene Display List. This property is set during the `boot` method. + * + * @name Phaser.Input.InputPlugin#displayList + * @type {Phaser.GameObjects.DisplayList} + * @since 3.0.0 + */ + this.displayList; + + /** + * A reference to the Scene Cameras Manager. This property is set during the `boot` method. + * + * @name Phaser.Input.InputPlugin#cameras + * @type {Phaser.Cameras.Scene2D.CameraManager} + * @since 3.0.0 + */ + this.cameras; + + // Inject the available input plugins into this class + InputPluginCache.install(this); + + /** + * A reference to the Mouse Manager. + * + * This property is only set if Mouse support has been enabled in your Game Configuration file. + * + * If you just wish to get access to the mouse pointer, use the `mousePointer` property instead. + * + * @name Phaser.Input.InputPlugin#mouse + * @type {?Phaser.Input.Mouse.MouseManager} + * @since 3.0.0 + */ + this.mouse = this.manager.mouse; + + /** + * When set to `true` (the default) the Input Plugin will emulate DOM behavior by only emitting events from + * the top-most Game Objects in the Display List. + * + * If set to `false` it will emit events from all Game Objects below a Pointer, not just the top one. + * + * @name Phaser.Input.InputPlugin#topOnly + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.topOnly = true; + + /** + * How often should the Pointers be checked? + * + * The value is a time, given in ms, and is the time that must have elapsed between game steps before + * the Pointers will be polled again. When a pointer is polled it runs a hit test to see which Game + * Objects are currently below it, or being interacted with it. + * + * Pointers will *always* be checked if they have been moved by the user, or press or released. + * + * This property only controls how often they will be polled if they have not been updated. + * You should set this if you want to have Game Objects constantly check against the pointers, even + * if the pointer didn't itself move. + * + * Set to 0 to poll constantly. Set to -1 to only poll on user movement. + * + * @name Phaser.Input.InputPlugin#pollRate + * @type {number} + * @default -1 + * @since 3.0.0 + */ + this.pollRate = -1; + + /** + * Internal poll timer value. + * + * @name Phaser.Input.InputPlugin#_pollTimer + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._pollTimer = 0; + + var _eventData = { cancelled: false }; + + /** + * Internal event propagation callback container. + * + * @name Phaser.Input.InputPlugin#_eventContainer + * @type {Phaser.Types.Input.EventData} + * @private + * @since 3.13.0 + */ + this._eventContainer = { + stopPropagation: function () + { + _eventData.cancelled = true; + } + }; + + /** + * Internal event propagation data object. + * + * @name Phaser.Input.InputPlugin#_eventData + * @type {object} + * @private + * @since 3.13.0 + */ + this._eventData = _eventData; + + /** + * The distance, in pixels, a pointer has to move while being held down, before it thinks it is being dragged. + * + * @name Phaser.Input.InputPlugin#dragDistanceThreshold + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.dragDistanceThreshold = 0; + + /** + * The amount of time, in ms, a pointer has to be held down before it thinks it is dragging. + * + * The default polling rate is to poll only on move so once the time threshold is reached the + * drag event will not start until you move the mouse. If you want it to start immediately + * when the time threshold is reached, you must increase the polling rate by calling + * [setPollAlways]{@linkcode Phaser.Input.InputPlugin#setPollAlways} or + * [setPollRate]{@linkcode Phaser.Input.InputPlugin#setPollRate}. + * + * @name Phaser.Input.InputPlugin#dragTimeThreshold + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.dragTimeThreshold = 0; + + /** + * Used to temporarily store the results of the Hit Test + * + * @name Phaser.Input.InputPlugin#_temp + * @type {array} + * @private + * @default [] + * @since 3.0.0 + */ + this._temp = []; + + /** + * Used to temporarily store the results of the Hit Test dropZones + * + * @name Phaser.Input.InputPlugin#_tempZones + * @type {array} + * @private + * @default [] + * @since 3.0.0 + */ + this._tempZones = []; + + /** + * A list of all Game Objects that have been set to be interactive in the Scene this Input Plugin is managing. + * + * @name Phaser.Input.InputPlugin#_list + * @type {Phaser.GameObjects.GameObject[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._list = []; + + /** + * Objects waiting to be inserted to the list on the next call to 'begin'. + * + * @name Phaser.Input.InputPlugin#_pendingInsertion + * @type {Phaser.GameObjects.GameObject[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._pendingInsertion = []; + + /** + * Objects waiting to be removed from the list on the next call to 'begin'. + * + * @name Phaser.Input.InputPlugin#_pendingRemoval + * @type {Phaser.GameObjects.GameObject[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._pendingRemoval = []; + + /** + * A list of all Game Objects that have been enabled for dragging. + * + * @name Phaser.Input.InputPlugin#_draggable + * @type {Phaser.GameObjects.GameObject[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._draggable = []; + + /** + * A list of all Interactive Objects currently considered as being 'draggable' by any pointer, indexed by pointer ID. + * + * @name Phaser.Input.InputPlugin#_drag + * @type {{0:Array,1:Array,2:Array,3:Array,4:Array,5:Array,6:Array,7:Array,8:Array,9:Array,10:Array}} + * @private + * @since 3.0.0 + */ + this._drag = { 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: [] }; + + /** + * A array containing the dragStates, for this Scene, index by the Pointer ID. + * + * @name Phaser.Input.InputPlugin#_dragState + * @type {number[]} + * @private + * @since 3.16.0 + */ + this._dragState = []; + + /** + * A list of all Interactive Objects currently considered as being 'over' by any pointer, indexed by pointer ID. + * + * @name Phaser.Input.InputPlugin#_over + * @type {{0:Array,1:Array,2:Array,3:Array,4:Array,5:Array,6:Array,7:Array,8:Array,9:Array,10:Array}} + * @private + * @since 3.0.0 + */ + this._over = { 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: [] }; + + /** + * A list of valid DOM event types. + * + * @name Phaser.Input.InputPlugin#_validTypes + * @type {string[]} + * @private + * @since 3.0.0 + */ + this._validTypes = [ 'onDown', 'onUp', 'onOver', 'onOut', 'onMove', 'onDragStart', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragLeave', 'onDragOver', 'onDrop' ]; + + /** + * Internal property that tracks frame event state. + * + * @name Phaser.Input.InputPlugin#_updatedThisFrame + * @type {boolean} + * @private + * @since 3.18.0 + */ + this._updatedThisFrame = false; + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Input.InputPlugin#boot + * @fires Phaser.Input.Events#BOOT + * @private + * @since 3.5.1 + */ + boot: function () + { + this.cameras = this.systems.cameras; + + this.displayList = this.systems.displayList; + + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + + // Registered input plugins listen for this + this.pluginEvents.emit(Events.BOOT); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Input.InputPlugin#start + * @fires Phaser.Input.Events#START + * @private + * @since 3.5.0 + */ + start: function () + { + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.TRANSITION_START, this.transitionIn, this); + eventEmitter.on(SceneEvents.TRANSITION_OUT, this.transitionOut, this); + eventEmitter.on(SceneEvents.TRANSITION_COMPLETE, this.transitionComplete, this); + eventEmitter.on(SceneEvents.PRE_UPDATE, this.preUpdate, this); + eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this); + + this.manager.events.on(Events.GAME_OUT, this.onGameOut, this); + this.manager.events.on(Events.GAME_OVER, this.onGameOver, this); + + this.enabled = true; + + // Populate the pointer drag states + this._dragState = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + + // Registered input plugins listen for this + this.pluginEvents.emit(Events.START); + }, + + /** + * Game Over handler. + * + * @method Phaser.Input.InputPlugin#onGameOver + * @fires Phaser.Input.Events#GAME_OVER + * @private + * @since 3.16.2 + */ + onGameOver: function (event) + { + if (this.isActive()) + { + this.emit(Events.GAME_OVER, event.timeStamp, event); + } + }, + + /** + * Game Out handler. + * + * @method Phaser.Input.InputPlugin#onGameOut + * @fires Phaser.Input.Events#GAME_OUT + * @private + * @since 3.16.2 + */ + onGameOut: function (event) + { + if (this.isActive()) + { + this.emit(Events.GAME_OUT, event.timeStamp, event); + } + }, + + /** + * The pre-update handler is responsible for checking the pending removal and insertion lists and + * deleting old Game Objects. + * + * @method Phaser.Input.InputPlugin#preUpdate + * @private + * @fires Phaser.Input.Events#PRE_UPDATE + * @since 3.0.0 + */ + preUpdate: function () + { + // Registered input plugins listen for this + this.pluginEvents.emit(Events.PRE_UPDATE); + + var removeList = this._pendingRemoval; + var insertList = this._pendingInsertion; + + var toRemove = removeList.length; + var toInsert = insertList.length; + + if (toRemove === 0 && toInsert === 0) + { + // Quick bail + return; + } + + var current = this._list; + + // Delete old gameObjects + for (var i = 0; i < toRemove; i++) + { + var gameObject = removeList[i]; + + var index = current.indexOf(gameObject); + + if (index > -1) + { + current.splice(index, 1); + + this.clear(gameObject, true); + } + } + + // Clear the removal list + this._pendingRemoval.length = 0; + + // Move pendingInsertion to list (also clears pendingInsertion at the same time) + this._list = current.concat(insertList.splice(0)); + }, + + /** + * Checks to see if the Input Manager, this plugin and the Scene to which it belongs are all active and input enabled. + * + * @method Phaser.Input.InputPlugin#isActive + * @since 3.10.0 + * + * @return {boolean} `true` if the plugin and the Scene it belongs to is active. + */ + isActive: function () + { + return (this.manager && this.manager.enabled && this.enabled && this.scene.sys.canInput()); + }, + + /** + * Sets a custom cursor on the parent canvas element of the game, based on the `cursor` + * setting of the given Interactive Object (i.e. a Sprite). + * + * See the CSS property `cursor` for more information on MDN: + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/cursor + * + * @method Phaser.Input.InputPlugin#setCursor + * @since 3.85.0 + * + * @param {Phaser.Types.Input.InteractiveObject} interactiveObject - The Interactive Object that will set the cursor on the canvas. + */ + setCursor: function (interactiveObject) + { + if (this.manager) + { + this.manager.setCursor(interactiveObject); + } + }, + + /** + * Forces the Input Manager to clear the custom or hand cursor, regardless of the + * interactive state of any Game Objects. + * + * @method Phaser.Input.InputPlugin#resetCursor + * @since 3.85.0 + */ + resetCursor: function () + { + if (this.manager) + { + this.manager.resetCursor(null, true); + } + }, + + /** + * This is called automatically by the Input Manager. + * It emits events for plugins to listen to and also handles polling updates, if enabled. + * + * @method Phaser.Input.InputPlugin#updatePoll + * @since 3.18.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + * + * @return {boolean} `true` if the plugin and the Scene it belongs to is active. + */ + updatePoll: function (time, delta) + { + if (!this.isActive()) + { + return false; + } + + // The plugins should update every frame, regardless if there has been + // any DOM input events or not (such as the Gamepad and Keyboard) + this.pluginEvents.emit(Events.UPDATE, time, delta); + + // We can leave now if we've already updated once this frame via the immediate DOM event handlers + if (this._updatedThisFrame) + { + this._updatedThisFrame = false; + + return false; + } + + var i; + var manager = this.manager; + + var pointers = manager.pointers; + + for (i = 0; i < pointers.length; i++) + { + pointers[i].updateMotion(); + } + + // No point going any further if there aren't any interactive objects + if (this._list.length === 0) + { + return false; + } + + var rate = this.pollRate; + + if (rate === -1) + { + return false; + } + else if (rate > 0) + { + this._pollTimer -= delta; + + if (this._pollTimer < 0) + { + // Discard timer diff, we're ready to poll again + this._pollTimer = this.pollRate; + } + else + { + // Not enough time has elapsed since the last poll, so abort now + return false; + } + } + + // We got this far? Then we should poll for movement + var captured = false; + + for (i = 0; i < pointers.length; i++) + { + var total = 0; + + var pointer = pointers[i]; + + // Always reset this array + this._tempZones = []; + + // _temp contains a hit tested and camera culled list of IO objects + this._temp = this.hitTestPointer(pointer); + + this.sortGameObjects(this._temp, pointer); + this.sortDropZones(this._tempZones); + + if (this.topOnly) + { + // Only the top-most one counts now, so safely ignore the rest + if (this._temp.length) + { + this._temp.splice(1); + } + + if (this._tempZones.length) + { + this._tempZones.splice(1); + } + } + + total += this.processOverOutEvents(pointer); + + if (this.getDragState(pointer) === 2) + { + this.processDragThresholdEvent(pointer, time); + } + + if (total > 0) + { + // We interacted with an event in this Scene, so block any Scenes below us from doing the same this frame + captured = true; + } + } + + return captured; + }, + + /** + * This method is called when a DOM Event is received by the Input Manager. It handles dispatching the events + * to relevant input enabled Game Objects in this scene. + * + * @method Phaser.Input.InputPlugin#update + * @private + * @fires Phaser.Input.Events#UPDATE + * @since 3.0.0 + * + * @param {number} type - The type of event to process. + * @param {Phaser.Input.Pointer[]} pointers - An array of Pointers on which the event occurred. + * + * @return {boolean} `true` if this Scene has captured the input events from all other Scenes, otherwise `false`. + */ + update: function (type, pointers) + { + if (!this.isActive()) + { + return false; + } + + var captured = false; + + for (var i = 0; i < pointers.length; i++) + { + var total = 0; + var pointer = pointers[i]; + + // Always reset this array + this._tempZones = []; + + // _temp contains a hit tested and camera culled list of IO objects + this._temp = this.hitTestPointer(pointer); + + this.sortGameObjects(this._temp, pointer); + this.sortDropZones(this._tempZones); + + if (this.topOnly) + { + // Only the top-most one counts now, so safely ignore the rest + if (this._temp.length) + { + this._temp.splice(1); + } + + if (this._tempZones.length) + { + this._tempZones.splice(1); + } + } + + switch (type) + { + case CONST.MOUSE_DOWN: + total += this.processDragDownEvent(pointer); + total += this.processDownEvents(pointer); + total += this.processOverOutEvents(pointer); + break; + + case CONST.MOUSE_UP: + total += this.processDragUpEvent(pointer); + total += this.processUpEvents(pointer); + total += this.processOverOutEvents(pointer); + break; + + case CONST.TOUCH_START: + total += this.processDragDownEvent(pointer); + total += this.processDownEvents(pointer); + total += this.processOverEvents(pointer); + break; + + case CONST.TOUCH_END: + case CONST.TOUCH_CANCEL: + total += this.processDragUpEvent(pointer); + total += this.processUpEvents(pointer); + total += this.processOutEvents(pointer); + break; + + case CONST.MOUSE_MOVE: + case CONST.TOUCH_MOVE: + total += this.processDragMoveEvent(pointer); + total += this.processMoveEvents(pointer); + total += this.processOverOutEvents(pointer); + break; + + case CONST.MOUSE_WHEEL: + total += this.processWheelEvent(pointer); + break; + } + + if (total > 0) + { + // We interacted with an event in this Scene, so block any Scenes below us from doing the same this frame + captured = true; + } + } + + this._updatedThisFrame = true; + + return captured; + }, + + /** + * Clears a Game Object so it no longer has an Interactive Object associated with it. + * The Game Object is then queued for removal from the Input Plugin on the next update. + * + * @method Phaser.Input.InputPlugin#clear + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will have its Interactive Object removed. + * @param {boolean} [skipQueue=false] - Skip adding this Game Object into the removal queue? + * + * @return {Phaser.GameObjects.GameObject} The Game Object that had its Interactive Object removed. + */ + clear: function (gameObject, skipQueue) + { + if (skipQueue === undefined) { skipQueue = false; } + + this.disable(gameObject); + + var input = gameObject.input; + + // If GameObject.input already cleared from higher class + if (input) + { + this.removeDebug(gameObject); + this.manager.resetCursor(input); + + input.gameObject = undefined; + input.target = undefined; + input.hitArea = undefined; + input.hitAreaCallback = undefined; + input.callbackContext = undefined; + + gameObject.input = null; + } + + if (!skipQueue) + { + this.queueForRemoval(gameObject); + } + + var index = this._draggable.indexOf(gameObject); + + if (index > -1) + { + this._draggable.splice(index, 1); + } + + return gameObject; + }, + + /** + * Disables Input on a single Game Object. + * + * An input disabled Game Object still retains its Interactive Object component and can be re-enabled + * at any time, by passing it to `InputPlugin.enable`. + * + * @method Phaser.Input.InputPlugin#disable + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to have its input system disabled. + * @param {boolean} [resetCursor=false] - Reset the cursor to the default? + * + * @return {this} This Input Plugin. + */ + disable: function (gameObject, resetCursor) + { + if (resetCursor === undefined) { resetCursor = false; } + + var input = gameObject.input; + + if (input) + { + input.enabled = false; + input.dragState = 0; + } + + // Clear from _drag and _over + var drag = this._drag; + var over = this._over; + var manager = this.manager; + + for (var i = 0, index; i < manager.pointers.length; i++) + { + index = drag[i].indexOf(gameObject); + + if (index > -1) + { + drag[i].splice(index, 1); + } + + index = over[i].indexOf(gameObject); + + if (index > -1) + { + over[i].splice(index, 1); + } + } + + if (resetCursor) + { + this.resetCursor(); + } + + return this; + }, + + /** + * Enable a Game Object for interaction. + * + * If the Game Object already has an Interactive Object component, it is enabled and returned. + * + * Otherwise, a new Interactive Object component is created and assigned to the Game Object's `input` property. + * + * Input works by using hit areas, these are nearly always geometric shapes, such as rectangles or circles, that act as the hit area + * for the Game Object. However, you can provide your own hit area shape and callback, should you wish to handle some more advanced + * input detection. + * + * If no arguments are provided it will try and create a rectangle hit area based on the texture frame the Game Object is using. If + * this isn't a texture-bound object, such as a Graphics or BitmapText object, this will fail, and you'll need to provide a specific + * shape for it to use. + * + * You can also provide an Input Configuration Object as the only argument to this method. + * + * @method Phaser.Input.InputPlugin#enable + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to be enabled for input. + * @param {(Phaser.Types.Input.InputConfiguration|any)} [hitArea] - Either an input configuration object, or a geometric shape that defines the hit area for the Game Object. If not specified a Rectangle will be used. + * @param {Phaser.Types.Input.HitAreaCallback} [hitAreaCallback] - The 'contains' function to invoke to check if the pointer is within the hit area. + * @param {boolean} [dropZone=false] - Is this Game Object a drop zone or not? + * + * @return {this} This Input Plugin. + */ + enable: function (gameObject, hitArea, hitAreaCallback, dropZone) + { + if (dropZone === undefined) { dropZone = false; } + + if (gameObject.input) + { + // If it already has an InteractiveObject then just enable it and return + gameObject.input.enabled = true; + } + else + { + // Create an InteractiveObject and enable it + this.setHitArea(gameObject, hitArea, hitAreaCallback); + } + + if (gameObject.input && dropZone && !gameObject.input.dropZone) + { + gameObject.input.dropZone = dropZone; + } + + return this; + }, + + /** + * Takes the given Pointer and performs a hit test against it, to see which interactive Game Objects + * it is currently above. + * + * The hit test is performed against which-ever Camera the Pointer is over. If it is over multiple + * cameras, it starts checking the camera at the top of the camera list, and if nothing is found, iterates down the list. + * + * @method Phaser.Input.InputPlugin#hitTestPointer + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to check against the Game Objects. + * + * @return {Phaser.GameObjects.GameObject[]} An array of all the interactive Game Objects the Pointer was above. + */ + hitTestPointer: function (pointer) + { + var cameras = this.cameras.getCamerasBelowPointer(pointer); + + for (var c = 0; c < cameras.length; c++) + { + var camera = cameras[c]; + + // Get a list of all objects that can be seen by the camera below the pointer in the scene and store in 'over' array. + // All objects in this array are input enabled, as checked by the hitTest method, so we don't need to check later on as well. + var over = this.manager.hitTest(pointer, this._list, camera); + + // Filter out the drop zones + for (var i = 0; i < over.length; i++) + { + var obj = over[i]; + + if (obj.input.dropZone) + { + this._tempZones.push(obj); + } + } + + if (over.length > 0) + { + pointer.camera = camera; + + return over; + } + } + + // If we got this far then there were no Game Objects below the pointer, but it was still over + // a camera, so set that the top-most one into the pointer + + pointer.camera = cameras[0]; + + return []; + }, + + /** + * An internal method that handles the Pointer down event. + * + * @method Phaser.Input.InputPlugin#processDownEvents + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_DOWN + * @fires Phaser.Input.Events#GAMEOBJECT_DOWN + * @fires Phaser.Input.Events#POINTER_DOWN + * @fires Phaser.Input.Events#POINTER_DOWN_OUTSIDE + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer being tested. + * + * @return {number} The total number of objects interacted with. + */ + processDownEvents: function (pointer) + { + var total = 0; + var currentlyOver = this._temp; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + // Go through all objects the pointer was over and fire their events / callbacks + for (var i = 0; i < currentlyOver.length; i++) + { + var gameObject = currentlyOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + total++; + + // 1) GAMEOBJECT_POINTER_DOWN + gameObject.emit(Events.GAMEOBJECT_POINTER_DOWN, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + // 2) GAMEOBJECT_DOWN + + this.emit(Events.GAMEOBJECT_DOWN, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + // If they pressed down outside the canvas, dispatch that event. + if (!_eventData.cancelled && this.isActive()) + { + if (pointer.downElement === this.manager.game.canvas) + { + // 3) POINTER_DOWN + this.emit(Events.POINTER_DOWN, pointer, currentlyOver); + } + else + { + // 4) POINTER_DOWN_OUTSIDE + this.emit(Events.POINTER_DOWN_OUTSIDE, pointer); + } + } + + return total; + }, + + /** + * Returns the drag state of the given Pointer for this Input Plugin. + * + * The state will be one of the following: + * + * 0 = Not dragging anything + * 1 = Primary button down and objects below, so collect a draglist + * 2 = Pointer being checked if meets drag criteria + * 3 = Pointer meets criteria, notify the draglist + * 4 = Pointer actively dragging the draglist and has moved + * 5 = Pointer actively dragging but has been released, notify draglist + * + * @method Phaser.Input.InputPlugin#getDragState + * @since 3.16.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to get the drag state for. + * + * @return {number} The drag state of the given Pointer. + */ + getDragState: function (pointer) + { + return this._dragState[pointer.id]; + }, + + /** + * Sets the drag state of the given Pointer for this Input Plugin. + * + * The state must be one of the following values: + * + * 0 = Not dragging anything + * 1 = Primary button down and objects below, so collect a draglist + * 2 = Pointer being checked if meets drag criteria + * 3 = Pointer meets criteria, notify the draglist + * 4 = Pointer actively dragging the draglist and has moved + * 5 = Pointer actively dragging but has been released, notify draglist + * + * @method Phaser.Input.InputPlugin#setDragState + * @since 3.16.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to set the drag state for. + * @param {number} state - The drag state value. An integer between 0 and 5. + */ + setDragState: function (pointer, state) + { + this._dragState[pointer.id] = state; + }, + + /** + * Checks to see if a Pointer is ready to drag the objects below it, based on either a distance + * or time threshold. + * + * @method Phaser.Input.InputPlugin#processDragThresholdEvent + * @private + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to check the drag thresholds on. + * @param {number} time - The current time. + */ + processDragThresholdEvent: function (pointer, time) + { + var passed = false; + var timeThreshold = this.dragTimeThreshold; + var distanceThreshold = this.dragDistanceThreshold; + + if (distanceThreshold > 0 && DistanceBetween(pointer.x, pointer.y, pointer.downX, pointer.downY) >= distanceThreshold) + { + // It has moved far enough to be considered a drag + passed = true; + } + else if (timeThreshold > 0 && (time >= pointer.downTime + timeThreshold)) + { + // It has been held down long enough to be considered a drag + passed = true; + } + + if (passed) + { + this.setDragState(pointer, 3); + + return this.processDragStartList(pointer); + } + }, + + /** + * Processes the drag list for the given pointer and dispatches the start events for each object on it. + * + * @method Phaser.Input.InputPlugin#processDragStartList + * @private + * @fires Phaser.Input.Events#DRAG_START + * @fires Phaser.Input.Events#GAMEOBJECT_DRAG_START + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to process the drag event on. + * + * @return {number} The number of items that DRAG_START was called on. + */ + processDragStartList: function (pointer) + { + // 3 = Pointer meets criteria and is freshly down, notify the draglist + if (this.getDragState(pointer) !== 3) + { + return 0; + } + + var list = this._drag[pointer.id]; + + if (list.length > 1) + { + list = list.slice(0); + } + + for (var i = 0; i < list.length; i++) + { + var gameObject = list[i]; + + var input = gameObject.input; + + input.dragState = 2; + + input.dragStartX = gameObject.x; + input.dragStartY = gameObject.y; + + input.dragStartXGlobal = pointer.worldX; + input.dragStartYGlobal = pointer.worldY; + + input.dragStartCamera = pointer.camera; + + input.dragX = input.dragStartXGlobal - input.dragStartX; + input.dragY = input.dragStartYGlobal - input.dragStartY; + + gameObject.emit(Events.GAMEOBJECT_DRAG_START, pointer, input.dragX, input.dragY); + + this.emit(Events.DRAG_START, pointer, gameObject); + } + + this.setDragState(pointer, 4); + + return list.length; + }, + + /** + * Processes a 'drag down' event for the given pointer. Checks the pointer state, builds-up the drag list + * and prepares them all for interaction. + * + * @method Phaser.Input.InputPlugin#processDragDownEvent + * @private + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to process the drag event on. + * + * @return {number} The number of items that were collected on the drag list. + */ + processDragDownEvent: function (pointer) + { + var currentlyOver = this._temp; + + if (this._draggable.length === 0 || currentlyOver.length === 0 || !pointer.primaryDown || this.getDragState(pointer) !== 0) + { + // There are no draggable items, no over items or the pointer isn't down, so let's not even bother going further + return 0; + } + + // 1 = Primary button down and objects below, so collect a draglist + this.setDragState(pointer, 1); + + // Get draggable objects, sort them, pick the top (or all) and store them somewhere + var draglist = []; + + for (var i = 0; i < currentlyOver.length; i++) + { + var gameObject = currentlyOver[i]; + + if (gameObject.input.draggable && (gameObject.input.dragState === 0)) + { + draglist.push(gameObject); + } + } + + if (draglist.length === 0) + { + this.setDragState(pointer, 0); + + return 0; + } + else if (draglist.length > 1) + { + this.sortGameObjects(draglist, pointer); + + if (this.topOnly) + { + draglist.splice(1); + } + } + + // draglist now contains all potential candidates for dragging + this._drag[pointer.id] = draglist; + + if (this.dragDistanceThreshold === 0 && this.dragTimeThreshold === 0) + { + // No drag criteria, so snap immediately to mode 3 + this.setDragState(pointer, 3); + + return this.processDragStartList(pointer); + } + else + { + // Check the distance / time on the next event + this.setDragState(pointer, 2); + + return 0; + } + }, + + /** + * Processes a 'drag move' event for the given pointer. + * + * @method Phaser.Input.InputPlugin#processDragMoveEvent + * @private + * @fires Phaser.Input.Events#DRAG_ENTER + * @fires Phaser.Input.Events#DRAG + * @fires Phaser.Input.Events#DRAG_LEAVE + * @fires Phaser.Input.Events#DRAG_OVER + * @fires Phaser.Input.Events#GAMEOBJECT_DRAG_ENTER + * @fires Phaser.Input.Events#GAMEOBJECT_DRAG + * @fires Phaser.Input.Events#GAMEOBJECT_DRAG_LEAVE + * @fires Phaser.Input.Events#GAMEOBJECT_DRAG_OVER + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to process the drag event on. + * + * @return {number} The number of items that were updated by this drag event. + */ + processDragMoveEvent: function (pointer) + { + // 2 = Pointer being checked if meets drag criteria + if (this.getDragState(pointer) === 2) + { + this.processDragThresholdEvent(pointer, this.manager.game.loop.now); + } + + if (this.getDragState(pointer) !== 4) + { + return 0; + } + + // 4 = Pointer actively dragging the draglist and has moved + var dropZones = this._tempZones; + + var list = this._drag[pointer.id]; + + if (list.length > 1) + { + list = list.slice(0); + } + + for (var i = 0; i < list.length; i++) + { + var gameObject = list[i]; + + var input = gameObject.input; + + var target = input.target; + + // If this GO has a target then let's check it + if (target) + { + var index = dropZones.indexOf(target); + + // Got a target, are we still over it? + if (index === 0) + { + // We're still over it, and it's still the top of the display list, phew ... + gameObject.emit(Events.GAMEOBJECT_DRAG_OVER, pointer, target); + + this.emit(Events.DRAG_OVER, pointer, gameObject, target); + } + else if (index > 0) + { + // Still over it but it's no longer top of the display list (targets must always be at the top) + gameObject.emit(Events.GAMEOBJECT_DRAG_LEAVE, pointer, target); + + this.emit(Events.DRAG_LEAVE, pointer, gameObject, target); + + input.target = dropZones[0]; + + target = input.target; + + gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, target); + + this.emit(Events.DRAG_ENTER, pointer, gameObject, target); + } + else + { + // Nope, we've moved on (or the target has!), leave the old target + gameObject.emit(Events.GAMEOBJECT_DRAG_LEAVE, pointer, target); + + this.emit(Events.DRAG_LEAVE, pointer, gameObject, target); + + // Anything new to replace it? + // Yup! + if (dropZones[0]) + { + input.target = dropZones[0]; + + target = input.target; + + gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, target); + + this.emit(Events.DRAG_ENTER, pointer, gameObject, target); + } + else + { + // Nope + input.target = null; + } + } + } + else if (!target && dropZones[0]) + { + input.target = dropZones[0]; + + target = input.target; + + gameObject.emit(Events.GAMEOBJECT_DRAG_ENTER, pointer, target); + + this.emit(Events.DRAG_ENTER, pointer, gameObject, target); + } + + var dragX; + var dragY; + + var dragWorldXY = pointer.positionToCamera(input.dragStartCamera); + + if (!gameObject.parentContainer) + { + dragX = dragWorldXY.x - input.dragX; + dragY = dragWorldXY.y - input.dragY; + } + else + { + var dx = dragWorldXY.x - input.dragStartXGlobal; + var dy = dragWorldXY.y - input.dragStartYGlobal; + + var rotation = gameObject.getParentRotation(); + + var dxRotated = dx * Math.cos(rotation) + dy * Math.sin(rotation); + var dyRotated = dy * Math.cos(rotation) - dx * Math.sin(rotation); + + dxRotated *= (1 / gameObject.parentContainer.scaleX); + dyRotated *= (1 / gameObject.parentContainer.scaleY); + + dragX = dxRotated + input.dragStartX; + dragY = dyRotated + input.dragStartY; + } + + gameObject.emit(Events.GAMEOBJECT_DRAG, pointer, dragX, dragY); + + this.emit(Events.DRAG, pointer, gameObject, dragX, dragY); + } + + return list.length; + }, + + /** + * Processes a 'drag down' event for the given pointer. Checks the pointer state, builds-up the drag list + * and prepares them all for interaction. + * + * @method Phaser.Input.InputPlugin#processDragUpEvent + * @fires Phaser.Input.Events#DRAG_END + * @fires Phaser.Input.Events#DROP + * @fires Phaser.Input.Events#GAMEOBJECT_DRAG_END + * @fires Phaser.Input.Events#GAMEOBJECT_DROP + * @private + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to process the drag event on. + * + * @return {number} The number of items that were updated by this drag event. + */ + processDragUpEvent: function (pointer) + { + // 5 = Pointer was actively dragging but has been released, notify draglist + var list = this._drag[pointer.id]; + + if (list.length > 1) + { + list = list.slice(0); + } + + for (var i = 0; i < list.length; i++) + { + var gameObject = list[i]; + + var input = gameObject.input; + + if (input && input.dragState === 2) + { + input.dragState = 0; + + input.dragX = input.localX - gameObject.displayOriginX; + input.dragY = input.localY - gameObject.displayOriginY; + + input.dragStartCamera = null; + + var dropped = false; + + var target = input.target; + + if (target) + { + gameObject.emit(Events.GAMEOBJECT_DROP, pointer, target); + + this.emit(Events.DROP, pointer, gameObject, target); + + input.target = null; + + dropped = true; + } + + // And finally the dragend event + + if (gameObject.input && gameObject.input.enabled) + { + gameObject.emit(Events.GAMEOBJECT_DRAG_END, pointer, input.dragX, input.dragY, dropped); + + this.emit(Events.DRAG_END, pointer, gameObject, dropped); + } + } + } + + this.setDragState(pointer, 0); + + list.splice(0); + + return 0; + }, + + /** + * An internal method that handles the Pointer movement event. + * + * @method Phaser.Input.InputPlugin#processMoveEvents + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_MOVE + * @fires Phaser.Input.Events#GAMEOBJECT_MOVE + * @fires Phaser.Input.Events#POINTER_MOVE + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to check for events against. + * + * @return {number} The total number of objects interacted with. + */ + processMoveEvents: function (pointer) + { + var total = 0; + var currentlyOver = this._temp; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + // Go through all objects the pointer was over and fire their events / callbacks + for (var i = 0; i < currentlyOver.length; i++) + { + var gameObject = currentlyOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + total++; + + gameObject.emit(Events.GAMEOBJECT_POINTER_MOVE, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + this.emit(Events.GAMEOBJECT_MOVE, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + if (this.topOnly) + { + break; + } + } + } + + if (!_eventData.cancelled && this.isActive()) + { + this.emit(Events.POINTER_MOVE, pointer, currentlyOver); + } + + return total; + }, + + /** + * An internal method that handles a mouse wheel event. + * + * @method Phaser.Input.InputPlugin#processWheelEvent + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_WHEEL + * @fires Phaser.Input.Events#GAMEOBJECT_WHEEL + * @fires Phaser.Input.Events#POINTER_WHEEL + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to check for events against. + * + * @return {number} The total number of objects interacted with. + */ + processWheelEvent: function (pointer) + { + var total = 0; + var currentlyOver = this._temp; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + var dx = pointer.deltaX; + var dy = pointer.deltaY; + var dz = pointer.deltaZ; + + // Go through all objects the pointer was over and fire their events / callbacks + for (var i = 0; i < currentlyOver.length; i++) + { + var gameObject = currentlyOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + total++; + + gameObject.emit(Events.GAMEOBJECT_POINTER_WHEEL, pointer, dx, dy, dz, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + this.emit(Events.GAMEOBJECT_WHEEL, pointer, gameObject, dx, dy, dz, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + if (!_eventData.cancelled && this.isActive()) + { + this.emit(Events.POINTER_WHEEL, pointer, currentlyOver, dx, dy, dz); + } + + return total; + }, + + /** + * An internal method that handles the Pointer over events. + * This is called when a touch input hits the canvas, having previously been off of it. + * + * @method Phaser.Input.InputPlugin#processOverEvents + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_OVER + * @fires Phaser.Input.Events#GAMEOBJECT_OVER + * @fires Phaser.Input.Events#POINTER_OVER + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to check for events against. + * + * @return {number} The total number of objects interacted with. + */ + processOverEvents: function (pointer) + { + var currentlyOver = this._temp; + + var totalInteracted = 0; + + var total = currentlyOver.length; + + var justOver = []; + + if (total > 0) + { + var manager = this.manager; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + for (var i = 0; i < total; i++) + { + var gameObject = currentlyOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + justOver.push(gameObject); + + manager.setCursor(gameObject.input); + + gameObject.emit(Events.GAMEOBJECT_POINTER_OVER, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); + + totalInteracted++; + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + this.emit(Events.GAMEOBJECT_OVER, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + if (!_eventData.cancelled && this.isActive()) + { + this.emit(Events.POINTER_OVER, pointer, justOver); + } + } + + // Then sort it into display list order + this._over[pointer.id] = justOver; + + return totalInteracted; + }, + + /** + * An internal method that handles the Pointer out events. + * This is called when a touch input leaves the canvas, as it can never be 'over' in this case. + * + * @method Phaser.Input.InputPlugin#processOutEvents + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_OUT + * @fires Phaser.Input.Events#GAMEOBJECT_OUT + * @fires Phaser.Input.Events#POINTER_OUT + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to check for events against. + * + * @return {number} The total number of objects interacted with. + */ + processOutEvents: function (pointer) + { + var previouslyOver = this._over[pointer.id]; + + var totalInteracted = 0; + + var total = previouslyOver.length; + + if (total > 0) + { + var manager = this.manager; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + this.sortGameObjects(previouslyOver, pointer); + + for (var i = 0; i < total; i++) + { + var gameObject = previouslyOver[i]; + + // Call onOut for everything in the previouslyOver array + gameObject = previouslyOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + manager.resetCursor(gameObject.input); + + gameObject.emit(Events.GAMEOBJECT_POINTER_OUT, pointer, _eventContainer); + + totalInteracted++; + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + if (gameObject.input && gameObject.input.enabled) + { + this.emit(Events.GAMEOBJECT_OUT, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + if (!_eventData.cancelled && this.isActive()) + { + this.emit(Events.POINTER_OUT, pointer, previouslyOver); + } + + this._over[pointer.id] = []; + } + + return totalInteracted; + }, + + /** + * An internal method that handles the Pointer over and out events. + * + * @method Phaser.Input.InputPlugin#processOverOutEvents + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_OVER + * @fires Phaser.Input.Events#GAMEOBJECT_OVER + * @fires Phaser.Input.Events#POINTER_OVER + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_OUT + * @fires Phaser.Input.Events#GAMEOBJECT_OUT + * @fires Phaser.Input.Events#POINTER_OUT + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to check for events against. + * + * @return {number} The total number of objects interacted with. + */ + processOverOutEvents: function (pointer) + { + var currentlyOver = this._temp; + + var i; + var gameObject; + var justOut = []; + var justOver = []; + var stillOver = []; + var previouslyOver = this._over[pointer.id]; + var currentlyDragging = this._drag[pointer.id]; + + var manager = this.manager; + + // Go through all objects the pointer was previously over, and see if it still is. + // Splits the previouslyOver array into two parts: justOut and stillOver + + for (i = 0; i < previouslyOver.length; i++) + { + gameObject = previouslyOver[i]; + + if (currentlyOver.indexOf(gameObject) === -1 && currentlyDragging.indexOf(gameObject) === -1) + { + // Not in the currentlyOver array, so must be outside of this object now + justOut.push(gameObject); + } + else + { + // In the currentlyOver array + stillOver.push(gameObject); + } + } + + // Go through all objects the pointer is currently over (the hit test results) + // and if not in the previouslyOver array we know it's a new entry, so add to justOver + for (i = 0; i < currentlyOver.length; i++) + { + gameObject = currentlyOver[i]; + + // Is this newly over? + + if (previouslyOver.indexOf(gameObject) === -1) + { + justOver.push(gameObject); + } + } + + // By this point the arrays are filled, so now we can process what happened... + + // Process the Just Out objects + var total = justOut.length; + + var totalInteracted = 0; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + if (total > 0) + { + this.sortGameObjects(justOut, pointer); + + // Call onOut for everything in the justOut array + for (i = 0; i < total; i++) + { + gameObject = justOut[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + // Reset cursor before we emit the event, in case they want to change it during the event + manager.resetCursor(gameObject.input); + + gameObject.emit(Events.GAMEOBJECT_POINTER_OUT, pointer, _eventContainer); + + totalInteracted++; + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + this.emit(Events.GAMEOBJECT_OUT, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + if (!_eventData.cancelled || this.isActive()) + { + this.emit(Events.POINTER_OUT, pointer, justOut); + } + } + + // Process the Just Over objects + total = justOver.length; + + _eventData.cancelled = false; + + if (total > 0) + { + this.sortGameObjects(justOver, pointer); + + // Call onOver for everything in the justOver array + for (i = 0; i < total; i++) + { + gameObject = justOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + // Set cursor before we emit the event, in case they want to change it during the event + manager.setCursor(gameObject.input); + + gameObject.emit(Events.GAMEOBJECT_POINTER_OVER, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); + + totalInteracted++; + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + this.emit(Events.GAMEOBJECT_OVER, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + if (!_eventData.cancelled && this.isActive()) + { + this.emit(Events.POINTER_OVER, pointer, justOver); + } + } + + // Add the contents of justOver to the previously over array + previouslyOver = stillOver.concat(justOver); + + // Then sort it into display list order + this._over[pointer.id] = this.sortGameObjects(previouslyOver, pointer); + + return totalInteracted; + }, + + /** + * An internal method that handles the Pointer up events. + * + * @method Phaser.Input.InputPlugin#processUpEvents + * @private + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_UP + * @fires Phaser.Input.Events#GAMEOBJECT_UP + * @fires Phaser.Input.Events#POINTER_UP + * @fires Phaser.Input.Events#POINTER_UP_OUTSIDE + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to check for events against. + * + * @return {number} The total number of objects interacted with. + */ + processUpEvents: function (pointer) + { + var currentlyOver = this._temp; + + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + // Go through all objects the pointer was over and fire their events / callbacks + for (var i = 0; i < currentlyOver.length; i++) + { + var gameObject = currentlyOver[i]; + + if (!gameObject.input || !gameObject.input.enabled) + { + continue; + } + + // 1) GAMEOBJECT_POINTER_UP + gameObject.emit(Events.GAMEOBJECT_POINTER_UP, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + + // Check that the game object wasn't input disabled or destroyed as a result of its input event + if (gameObject.input && gameObject.input.enabled) + { + // 2) GAMEOBJECT_UP + + this.emit(Events.GAMEOBJECT_UP, pointer, gameObject, _eventContainer); + + if (_eventData.cancelled || !this.isActive()) + { + // They cancelled the whole event, it can't go any further + break; + } + } + } + + // If they released outside the canvas, but pressed down inside it, we'll still dispatch the event. + if (!_eventData.cancelled && this.isActive()) + { + if (pointer.upElement === this.manager.game.canvas) + { + this.emit(Events.POINTER_UP, pointer, currentlyOver); + } + else + { + this.emit(Events.POINTER_UP_OUTSIDE, pointer); + } + } + + return currentlyOver.length; + }, + + /** + * This method will force the given Game Object into the 'down' input state. + * + * This will check to see if the Game Object is enabled for input, and if so, + * it will emit the `GAMEOBJECT_POINTER_DOWN` event for it. If that doesn't change + * the input state, it will then emit the `GAMEOBJECT_DOWN` event. + * + * The Game Object is not checked against the Pointer to see if it can enter this state, + * that is up to you to do before calling this method. + * + * @method Phaser.Input.InputPlugin#forceDownState + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_DOWN + * @fires Phaser.Input.Events#GAMEOBJECT_DOWN + * @since 3.85.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to use when setting the state. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to have its state set. + */ + forceDownState: function (pointer, gameObject) + { + this.forceState(pointer, gameObject, Events.GAMEOBJECT_POINTER_DOWN, Events.GAMEOBJECT_DOWN, false); + }, + + /** + * This method will force the given Game Object into the 'up' input state. + * + * This will check to see if the Game Object is enabled for input, and if so, + * it will emit the `GAMEOBJECT_POINTER_UP` event for it. If that doesn't change + * the input state, it will then emit the `GAMEOBJECT_UP` event. + * + * The Game Object is not checked against the Pointer to see if it can enter this state, + * that is up to you to do before calling this method. + * + * @method Phaser.Input.InputPlugin#forceUpState + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_UP + * @fires Phaser.Input.Events#GAMEOBJECT_UP + * @since 3.85.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to use when setting the state. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to have its state set. + */ + forceUpState: function (pointer, gameObject) + { + this.forceState(pointer, gameObject, Events.GAMEOBJECT_POINTER_UP, Events.GAMEOBJECT_UP, false); + }, + + /** + * This method will force the given Game Object into the 'over' input state. + * + * This will check to see if the Game Object is enabled for input, and if so, + * it will emit the `GAMEOBJECT_POINTER_OVER` event for it. If that doesn't change + * the input state, it will then emit the `GAMEOBJECT_OVER` event. + * + * The Game Object is not checked against the Pointer to see if it can enter this state, + * that is up to you to do before calling this method. + * + * @method Phaser.Input.InputPlugin#forceOverState + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_OVER + * @fires Phaser.Input.Events#GAMEOBJECT_OVER + * @since 3.85.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to use when setting the state. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to have its state set. + */ + forceOverState: function (pointer, gameObject) + { + this.forceState(pointer, gameObject, Events.GAMEOBJECT_POINTER_OVER, Events.GAMEOBJECT_OVER, true); + }, + + /** + * This method will force the given Game Object into the 'out' input state. + * + * This will check to see if the Game Object is enabled for input, and if so, + * it will emit the `GAMEOBJECT_POINTER_OUT` event for it. If that doesn't change + * the input state, it will then emit the `GAMEOBJECT_OUT` event. + * + * The Game Object is not checked against the Pointer to see if it can enter this state, + * that is up to you to do before calling this method. + * + * @method Phaser.Input.InputPlugin#forceOutState + * @fires Phaser.Input.Events#GAMEOBJECT_POINTER_OUT + * @fires Phaser.Input.Events#GAMEOBJECT_OUT + * @since 3.85.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to use when setting the state. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to have its state set. + */ + forceOutState: function (pointer, gameObject) + { + this.forceState(pointer, gameObject, Events.GAMEOBJECT_POINTER_OUT, Events.GAMEOBJECT_OUT, false); + }, + + /** + * This method will force the given Game Object into the given input state. + * + * @method Phaser.Input.InputPlugin#forceState + * @since 3.85.0 + * + * @param {Phaser.Input.Pointer} pointer - The pointer to use when setting the state. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to have its state set. + * @param {string} gameObjectEvent - The event to emit on the Game Object. + * @param {string} inputPluginEvent - The event to emit on the Input Plugin. + * @param {boolean} [setCursor=false] - Should the cursor be set to the Game Object's cursor? + */ + forceState: function (pointer, gameObject, gameObjectEvent, inputPluginEvent, setCursor) + { + var _eventData = this._eventData; + var _eventContainer = this._eventContainer; + + _eventData.cancelled = false; + + if (gameObject.input && gameObject.input.enabled) + { + gameObject.emit(gameObjectEvent, pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); + + if (setCursor) + { + this.setCursor(gameObject.input); + } + + if (!_eventData.cancelled && this.isActive() && gameObject.input && gameObject.input.enabled) + { + this.emit(inputPluginEvent, pointer, gameObject, _eventContainer); + } + } + }, + + /** + * Queues a Game Object for insertion into this Input Plugin on the next update. + * + * @method Phaser.Input.InputPlugin#queueForInsertion + * @private + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to add. + * + * @return {this} This InputPlugin object. + */ + queueForInsertion: function (child) + { + if (this._pendingInsertion.indexOf(child) === -1 && this._list.indexOf(child) === -1) + { + this._pendingInsertion.push(child); + } + + return this; + }, + + /** + * Queues a Game Object for removal from this Input Plugin on the next update. + * + * @method Phaser.Input.InputPlugin#queueForRemoval + * @private + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to remove. + * + * @return {this} This InputPlugin object. + */ + queueForRemoval: function (child) + { + this._pendingRemoval.push(child); + + return this; + }, + + /** + * Sets the draggable state of the given array of Game Objects. + * + * They can either be set to be draggable, or can have their draggable state removed by passing `false`. + * + * A Game Object will not fire drag events unless it has been specifically enabled for drag. + * + * @method Phaser.Input.InputPlugin#setDraggable + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to change the draggable state on. + * @param {boolean} [value=true] - Set to `true` if the Game Objects should be made draggable, `false` if they should be unset. + * + * @return {this} This InputPlugin object. + */ + setDraggable: function (gameObjects, value) + { + if (value === undefined) { value = true; } + + if (!Array.isArray(gameObjects)) + { + gameObjects = [ gameObjects ]; + } + + for (var i = 0; i < gameObjects.length; i++) + { + var gameObject = gameObjects[i]; + + gameObject.input.draggable = value; + + var index = this._draggable.indexOf(gameObject); + + if (value && index === -1) + { + this._draggable.push(gameObject); + } + else if (!value && index > -1) + { + this._draggable.splice(index, 1); + } + } + + return this; + }, + + /** + * Creates a function that can be passed to `setInteractive`, `enable` or `setHitArea` that will handle + * pixel-perfect input detection on an Image or Sprite based Game Object, or any custom class that extends them. + * + * The following will create a sprite that is clickable on any pixel that has an alpha value >= 1. + * + * ```javascript + * this.add.sprite(x, y, key).setInteractive(this.input.makePixelPerfect()); + * ``` + * + * The following will create a sprite that is clickable on any pixel that has an alpha value >= 150. + * + * ```javascript + * this.add.sprite(x, y, key).setInteractive(this.input.makePixelPerfect(150)); + * ``` + * + * Once you have made an Interactive Object pixel perfect it impacts all input related events for it: down, up, + * dragstart, drag, etc. + * + * As a pointer interacts with the Game Object it will constantly poll the texture, extracting a single pixel from + * the given coordinates and checking its color values. This is an expensive process, so should only be enabled on + * Game Objects that really need it. + * + * You cannot make non-texture based Game Objects pixel perfect. So this will not work on Graphics, BitmapText, + * Render Textures, Text, Tilemaps, Containers or Particles. + * + * @method Phaser.Input.InputPlugin#makePixelPerfect + * @since 3.10.0 + * + * @param {number} [alphaTolerance=1] - The alpha level that the pixel should be above to be included as a successful interaction. + * + * @return {function} A Pixel Perfect Handler for use as a hitArea shape callback. + */ + makePixelPerfect: function (alphaTolerance) + { + if (alphaTolerance === undefined) { alphaTolerance = 1; } + + var textureManager = this.systems.textures; + + return CreatePixelPerfectHandler(textureManager, alphaTolerance); + }, + + /** + * Sets the hit area for the given array of Game Objects. + * + * A hit area is typically one of the geometric shapes Phaser provides, such as a `Phaser.Geom.Rectangle` + * or `Phaser.Geom.Circle`. However, it can be any object as long as it works with the provided callback. + * + * If no hit area is provided a Rectangle is created based on the size of the Game Object, if possible + * to calculate. + * + * The hit area callback is the function that takes an `x` and `y` coordinate and returns a boolean if + * those values fall within the area of the shape or not. All of the Phaser geometry objects provide this, + * such as `Phaser.Geom.Rectangle.Contains`. + * + * A hit area callback can be supplied to the `hitArea` parameter without using the `hitAreaCallback` parameter. + * + * @method Phaser.Input.InputPlugin#setHitArea + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to set the hit area on. + * @param {(Phaser.Types.Input.InputConfiguration|Phaser.Types.Input.HitAreaCallback|any)} [hitArea] - Either an input configuration object, a geometric shape that defines the hit area or a hit area callback. If not specified a Rectangle hit area will be used. + * @param {Phaser.Types.Input.HitAreaCallback} [hitAreaCallback] - The 'contains' function to invoke to check if the pointer is within the hit area. + * + * @return {this} This InputPlugin object. + */ + setHitArea: function (gameObjects, hitArea, hitAreaCallback) + { + if (hitArea === undefined) + { + return this.setHitAreaFromTexture(gameObjects); + } + + if (!Array.isArray(gameObjects)) + { + gameObjects = [ gameObjects ]; + } + + var draggable = false; + var dropZone = false; + var cursor = false; + var useHandCursor = false; + var pixelPerfect = false; + var customHitArea = true; + + // Config object? + if (IsPlainObject(hitArea) && Object.keys(hitArea).length) + { + var config = hitArea; + + hitArea = GetFastValue(config, 'hitArea', null); + hitAreaCallback = GetFastValue(config, 'hitAreaCallback', null); + + pixelPerfect = GetFastValue(config, 'pixelPerfect', false); + var alphaTolerance = GetFastValue(config, 'alphaTolerance', 1); + + if (pixelPerfect) + { + hitArea = {}; + hitAreaCallback = this.makePixelPerfect(alphaTolerance); + } + + draggable = GetFastValue(config, 'draggable', false); + dropZone = GetFastValue(config, 'dropZone', false); + cursor = GetFastValue(config, 'cursor', false); + useHandCursor = GetFastValue(config, 'useHandCursor', false); + + // Still no hitArea or callback? + if (!hitArea || !hitAreaCallback) + { + this.setHitAreaFromTexture(gameObjects); + customHitArea = false; + } + } + else if (typeof hitArea === 'function' && !hitAreaCallback) + { + hitAreaCallback = hitArea; + hitArea = {}; + } + + for (var i = 0; i < gameObjects.length; i++) + { + var gameObject = gameObjects[i]; + + if (pixelPerfect && gameObject.type === 'Container') + { + console.warn('Cannot pixelPerfect test a Container. Use a custom callback.'); + continue; + } + + var io = (!gameObject.input) ? CreateInteractiveObject(gameObject, hitArea, hitAreaCallback) : gameObject.input; + + io.customHitArea = customHitArea; + io.dropZone = dropZone; + io.cursor = (useHandCursor) ? 'pointer' : cursor; + + gameObject.input = io; + + if (draggable) + { + this.setDraggable(gameObject); + } + + this.queueForInsertion(gameObject); + } + + return this; + }, + + /** + * Sets the hit area for an array of Game Objects to be a `Phaser.Geom.Circle` shape, using + * the given coordinates and radius to control its position and size. + * + * @method Phaser.Input.InputPlugin#setHitAreaCircle + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to set as having a circle hit area. + * @param {number} x - The center of the circle. + * @param {number} y - The center of the circle. + * @param {number} radius - The radius of the circle. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The hit area callback. If undefined it uses Circle.Contains. + * + * @return {this} This InputPlugin object. + */ + setHitAreaCircle: function (gameObjects, x, y, radius, callback) + { + if (callback === undefined) { callback = CircleContains; } + + var shape = new Circle(x, y, radius); + + return this.setHitArea(gameObjects, shape, callback); + }, + + /** + * Sets the hit area for an array of Game Objects to be a `Phaser.Geom.Ellipse` shape, using + * the given coordinates and dimensions to control its position and size. + * + * @method Phaser.Input.InputPlugin#setHitAreaEllipse + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to set as having an ellipse hit area. + * @param {number} x - The center of the ellipse. + * @param {number} y - The center of the ellipse. + * @param {number} width - The width of the ellipse. + * @param {number} height - The height of the ellipse. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The hit area callback. If undefined it uses Ellipse.Contains. + * + * @return {this} This InputPlugin object. + */ + setHitAreaEllipse: function (gameObjects, x, y, width, height, callback) + { + if (callback === undefined) { callback = EllipseContains; } + + var shape = new Ellipse(x, y, width, height); + + return this.setHitArea(gameObjects, shape, callback); + }, + + /** + * Sets the hit area for an array of Game Objects to be a `Phaser.Geom.Rectangle` shape, using + * the Game Objects texture frame to define the position and size of the hit area. + * + * @method Phaser.Input.InputPlugin#setHitAreaFromTexture + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to set as having an ellipse hit area. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The hit area callback. If undefined it uses Rectangle.Contains. + * + * @return {this} This InputPlugin object. + */ + setHitAreaFromTexture: function (gameObjects, callback) + { + if (callback === undefined) { callback = RectangleContains; } + + if (!Array.isArray(gameObjects)) + { + gameObjects = [ gameObjects ]; + } + + for (var i = 0; i < gameObjects.length; i++) + { + var gameObject = gameObjects[i]; + + var frame = gameObject.frame; + + var width = 0; + var height = 0; + + if (gameObject.width) + { + width = gameObject.width; + height = gameObject.height; + } + else if (frame) + { + width = frame.realWidth; + height = frame.realHeight; + } + + if (gameObject.type === 'Container' && (width === 0 || height === 0)) + { + console.warn('Container.setInteractive must specify a Shape or call setSize() first'); + continue; + } + + if (width !== 0 && height !== 0) + { + gameObject.input = CreateInteractiveObject(gameObject, new Rectangle(0, 0, width, height), callback); + + this.queueForInsertion(gameObject); + } + } + + return this; + }, + + /** + * Sets the hit area for an array of Game Objects to be a `Phaser.Geom.Rectangle` shape, using + * the given coordinates and dimensions to control its position and size. + * + * @method Phaser.Input.InputPlugin#setHitAreaRectangle + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to set as having a rectangular hit area. + * @param {number} x - The top-left of the rectangle. + * @param {number} y - The top-left of the rectangle. + * @param {number} width - The width of the rectangle. + * @param {number} height - The height of the rectangle. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The hit area callback. If undefined it uses Rectangle.Contains. + * + * @return {this} This InputPlugin object. + */ + setHitAreaRectangle: function (gameObjects, x, y, width, height, callback) + { + if (callback === undefined) { callback = RectangleContains; } + + var shape = new Rectangle(x, y, width, height); + + return this.setHitArea(gameObjects, shape, callback); + }, + + /** + * Sets the hit area for an array of Game Objects to be a `Phaser.Geom.Triangle` shape, using + * the given coordinates to control the position of its points. + * + * @method Phaser.Input.InputPlugin#setHitAreaTriangle + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[])} gameObjects - An array of Game Objects to set as having a triangular hit area. + * @param {number} x1 - The x coordinate of the first point of the triangle. + * @param {number} y1 - The y coordinate of the first point of the triangle. + * @param {number} x2 - The x coordinate of the second point of the triangle. + * @param {number} y2 - The y coordinate of the second point of the triangle. + * @param {number} x3 - The x coordinate of the third point of the triangle. + * @param {number} y3 - The y coordinate of the third point of the triangle. + * @param {Phaser.Types.Input.HitAreaCallback} [callback] - The hit area callback. If undefined it uses Triangle.Contains. + * + * @return {this} This InputPlugin object. + */ + setHitAreaTriangle: function (gameObjects, x1, y1, x2, y2, x3, y3, callback) + { + if (callback === undefined) { callback = TriangleContains; } + + var shape = new Triangle(x1, y1, x2, y2, x3, y3); + + return this.setHitArea(gameObjects, shape, callback); + }, + + /** + * Creates an Input Debug Shape for the given Game Object. + * + * The Game Object must have _already_ been enabled for input prior to calling this method. + * + * This is intended to assist you during development and debugging. + * + * Debug Shapes can only be created for Game Objects that are using standard Phaser Geometry for input, + * including: Circle, Ellipse, Line, Polygon, Rectangle and Triangle. + * + * Game Objects that are using their automatic hit areas are using Rectangles by default, so will also work. + * + * The Debug Shape is created and added to the display list and is then kept in sync with the Game Object + * it is connected with. Should you need to modify it yourself, such as to hide it, you can access it via + * the Game Object property: `GameObject.input.hitAreaDebug`. + * + * Calling this method on a Game Object that already has a Debug Shape will first destroy the old shape, + * before creating a new one. If you wish to remove the Debug Shape entirely, you should call the + * method `InputPlugin.removeDebug`. + * + * Note that the debug shape will only show the outline of the input area. If the input test is using a + * pixel perfect check, for example, then this is not displayed. If you are using a custom shape, that + * doesn't extend one of the base Phaser Geometry objects, as your hit area, then this method will not + * work. + * + * @method Phaser.Input.InputPlugin#enableDebug + * @since 3.19.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to create the input debug shape for. + * @param {number} [color=0x00ff00] - The outline color of the debug shape. + * + * @return {this} This Input Plugin. + */ + enableDebug: function (gameObject, color) + { + if (color === undefined) { color = 0x00ff00; } + + var input = gameObject.input; + + if (!input || !input.hitArea) + { + return this; + } + + var shape = input.hitArea; + var shapeType = shape.type; + var debug = input.hitAreaDebug; + var factory = this.systems.add; + var updateList = this.systems.updateList; + + if (debug) + { + updateList.remove(debug); + + debug.destroy(); + + debug = null; + } + + var offsetx = 0; + var offsety = 0; + + switch (shapeType) + { + case GEOM_CONST.CIRCLE: + debug = factory.arc(0, 0, shape.radius); + offsetx = shape.x - shape.radius; + offsety = shape.y - shape.radius; + break; + + case GEOM_CONST.ELLIPSE: + debug = factory.ellipse(0, 0, shape.width, shape.height); + offsetx = shape.x - shape.width / 2; + offsety = shape.y - shape.height / 2; + break; + + case GEOM_CONST.LINE: + debug = factory.line(0, 0, shape.x1, shape.y1, shape.x2, shape.y2); + break; + + case GEOM_CONST.POLYGON: + debug = factory.polygon(0, 0, shape.points); + break; + + case GEOM_CONST.RECTANGLE: + debug = factory.rectangle(0, 0, shape.width, shape.height); + offsetx = shape.x; + offsety = shape.y; + break; + + case GEOM_CONST.TRIANGLE: + debug = factory.triangle(0, 0, shape.x1, shape.y1, shape.x2, shape.y2, shape.x3, shape.y3); + break; + } + + if (debug) + { + debug.isFilled = false; + debug.strokeColor = color; + + debug.preUpdate = function () + { + debug.setVisible(gameObject.visible); + + debug.setStrokeStyle(1 / gameObject.scale, debug.strokeColor); + + debug.setDisplayOrigin(gameObject.displayOriginX, gameObject.displayOriginY); + + var x = gameObject.x; + var y = gameObject.y; + var rotation = gameObject.rotation; + var scaleX = gameObject.scaleX; + var scaleY = gameObject.scaleY; + + if (gameObject.parentContainer) + { + var matrix = gameObject.getWorldTransformMatrix(); + + x = matrix.tx; + y = matrix.ty; + rotation = matrix.rotation; + scaleX = matrix.scaleX; + scaleY = matrix.scaleY; + } + + debug.setRotation(rotation); + debug.setScale(scaleX, scaleY); + debug.setPosition(x + offsetx * scaleX, y + offsety * scaleY); + debug.setScrollFactor(gameObject.scrollFactorX, gameObject.scrollFactorY); + debug.setDepth(gameObject.depth); + }; + + updateList.add(debug); + + input.hitAreaDebug = debug; + } + + return this; + }, + + /** + * Removes an Input Debug Shape from the given Game Object. + * + * The shape is destroyed immediately and the `hitAreaDebug` property is set to `null`. + * + * @method Phaser.Input.InputPlugin#removeDebug + * @since 3.19.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to remove the input debug shape from. + * + * @return {this} This Input Plugin. + */ + removeDebug: function (gameObject) + { + var input = gameObject.input; + + if (input && input.hitAreaDebug) + { + var debug = input.hitAreaDebug; + + // This will remove it from both the display list and update list + debug.destroy(); + + input.hitAreaDebug = null; + } + + return this; + }, + + /** + * Sets the Pointers to always poll. + * + * When a pointer is polled it runs a hit test to see which Game Objects are currently below it, + * or being interacted with it, regardless if the Pointer has actually moved or not. + * + * You should enable this if you want objects in your game to fire over / out events, and the objects + * are constantly moving, but the pointer may not have. Polling every frame has additional computation + * costs, especially if there are a large number of interactive objects in your game. + * + * @method Phaser.Input.InputPlugin#setPollAlways + * @since 3.0.0 + * + * @return {this} This InputPlugin object. + */ + setPollAlways: function () + { + return this.setPollRate(0); + }, + + /** + * Sets the Pointers to only poll when they are moved or updated. + * + * When a pointer is polled it runs a hit test to see which Game Objects are currently below it, + * or being interacted with it. + * + * @method Phaser.Input.InputPlugin#setPollOnMove + * @since 3.0.0 + * + * @return {this} This InputPlugin object. + */ + setPollOnMove: function () + { + return this.setPollRate(-1); + }, + + /** + * Sets the poll rate value. This is the amount of time that should have elapsed before a pointer + * will be polled again. See the `setPollAlways` and `setPollOnMove` methods. + * + * @method Phaser.Input.InputPlugin#setPollRate + * @since 3.0.0 + * + * @param {number} value - The amount of time, in ms, that should elapsed before re-polling the pointers. + * + * @return {this} This InputPlugin object. + */ + setPollRate: function (value) + { + this.pollRate = value; + this._pollTimer = 0; + + return this; + }, + + /** + * When set to `true` the global Input Manager will emulate DOM behavior by only emitting events from + * the top-most Scene in the Scene List. By default, if a Scene receives an input event it will then stop the event + * from flowing down to any Scenes below it in the Scene list. To disable this behavior call this method with `false`. + * + * @method Phaser.Input.InputPlugin#setGlobalTopOnly + * @since 3.0.0 + * + * @param {boolean} value - Set to `true` to stop processing input events on the Scene that receives it, or `false` to let the event continue down the Scene list. + * + * @return {this} This InputPlugin object. + */ + setGlobalTopOnly: function (value) + { + this.manager.globalTopOnly = value; + + return this; + }, + + /** + * When set to `true` this Input Plugin will emulate DOM behavior by only emitting events from + * the top-most Game Objects in the Display List. + * + * If set to `false` it will emit events from all Game Objects below a Pointer, not just the top one. + * + * @method Phaser.Input.InputPlugin#setTopOnly + * @since 3.0.0 + * + * @param {boolean} value - `true` to only include the top-most Game Object, or `false` to include all Game Objects in a hit test. + * + * @return {this} This InputPlugin object. + */ + setTopOnly: function (value) + { + this.topOnly = value; + + return this; + }, + + /** + * Given an array of Game Objects and a Pointer, sort the array and return it, + * so that the objects are in render order with the lowest at the bottom. + * + * @method Phaser.Input.InputPlugin#sortGameObjects + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject[]} gameObjects - An array of Game Objects to be sorted. + * @param {Phaser.Input.Pointer} pointer - The Pointer to check against the Game Objects. + * + * @return {Phaser.GameObjects.GameObject[]} The sorted array of Game Objects. + */ + sortGameObjects: function (gameObjects, pointer) + { + if (gameObjects.length < 2 || !pointer.camera) + { + return gameObjects; + } + + var list = pointer.camera.renderList; + + return gameObjects.sort(function (childA, childB) + { + var indexA = Math.max(list.indexOf(childA), 0); + var indexB = Math.max(list.indexOf(childB), 0); + + return indexB - indexA; + }); + }, + + /** + * Given an array of Drop Zone Game Objects, sort the array and return it, + * so that the objects are in depth index order with the lowest at the bottom. + * + * @method Phaser.Input.InputPlugin#sortDropZones + * @since 3.52.0 + * + * @param {Phaser.GameObjects.GameObject[]} gameObjects - An array of Game Objects to be sorted. + * + * @return {Phaser.GameObjects.GameObject[]} The sorted array of Game Objects. + */ + sortDropZones: function (gameObjects) + { + if (gameObjects.length < 2) + { + return gameObjects; + } + + this.scene.sys.depthSort(); + + return gameObjects.sort(this.sortDropZoneHandler.bind(this)); + }, + + /** + * Return the child lowest down the display list (with the smallest index) + * Will iterate through all parent containers, if present. + * + * Prior to version 3.52.0 this method was called `sortHandlerGO`. + * + * @method Phaser.Input.InputPlugin#sortDropZoneHandler + * @private + * @since 3.52.0 + * + * @param {Phaser.GameObjects.GameObject} childA - The first Game Object to compare. + * @param {Phaser.GameObjects.GameObject} childB - The second Game Object to compare. + * + * @return {number} Returns either a negative or positive integer, or zero if they match. + */ + sortDropZoneHandler: function (childA, childB) + { + if (!childA.parentContainer && !childB.parentContainer) + { + // Quick bail out when neither child has a container + return this.displayList.getIndex(childB) - this.displayList.getIndex(childA); + } + else if (childA.parentContainer === childB.parentContainer) + { + // Quick bail out when both children have the same container + return childB.parentContainer.getIndex(childB) - childA.parentContainer.getIndex(childA); + } + else if (childA.parentContainer === childB) + { + // Quick bail out when childA is a child of childB + return -1; + } + else if (childB.parentContainer === childA) + { + // Quick bail out when childA is a child of childB + return 1; + } + else + { + // Container index check + var listA = childA.getIndexList(); + var listB = childB.getIndexList(); + var len = Math.min(listA.length, listB.length); + + for (var i = 0; i < len; i++) + { + var indexA = listA[i]; + var indexB = listB[i]; + + if (indexA === indexB) + { + // Go to the next level down + continue; + } + else + { + // Non-matching parents, so return + return indexB - indexA; + } + } + + return listB.length - listA.length; + } + + // Technically this shouldn't happen, but ... + // eslint-disable-next-line no-unreachable + return 0; + }, + + /** + * This method should be called from within an input event handler, such as `pointerdown`. + * + * When called, it stops the Input Manager from allowing _this specific event_ to be processed by any other Scene + * not yet handled in the scene list. + * + * @method Phaser.Input.InputPlugin#stopPropagation + * @since 3.0.0 + * + * @return {this} This InputPlugin object. + */ + stopPropagation: function () + { + this.manager._tempSkip = true; + + return this; + }, + + /** + * Adds new Pointer objects to the Input Manager. + * + * By default Phaser creates 2 pointer objects: `mousePointer` and `pointer1`. + * + * You can create more either by calling this method, or by setting the `input.activePointers` property + * in the Game Config, up to a maximum of 10 pointers. + * + * The first 10 pointers are available via the `InputPlugin.pointerX` properties, once they have been added + * via this method. + * + * @method Phaser.Input.InputPlugin#addPointer + * @since 3.10.0 + * + * @param {number} [quantity=1] The number of new Pointers to create. A maximum of 10 is allowed in total. + * + * @return {Phaser.Input.Pointer[]} An array containing all of the new Pointer objects that were created. + */ + addPointer: function (quantity) + { + return this.manager.addPointer(quantity); + }, + + /** + * Tells the Input system to set a custom cursor. + * + * This cursor will be the default cursor used when interacting with the game canvas. + * + * If an Interactive Object also sets a custom cursor, this is the cursor that is reset after its use. + * + * Any valid CSS cursor value is allowed, including paths to image files, i.e.: + * + * ```javascript + * this.input.setDefaultCursor('url(assets/cursors/sword.cur), pointer'); + * ``` + * + * Please read about the differences between browsers when it comes to the file formats and sizes they support: + * + * https://developer.mozilla.org/en-US/docs/Web/CSS/cursor + * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_User_Interface/Using_URL_values_for_the_cursor_property + * + * It's up to you to pick a suitable cursor format that works across the range of browsers you need to support. + * + * @method Phaser.Input.InputPlugin#setDefaultCursor + * @since 3.10.0 + * + * @param {string} cursor - The CSS to be used when setting the default cursor. + * + * @return {this} This Input instance. + */ + setDefaultCursor: function (cursor) + { + this.manager.setDefaultCursor(cursor); + + return this; + }, + + /** + * The Scene that owns this plugin is transitioning in. + * + * @method Phaser.Input.InputPlugin#transitionIn + * @private + * @since 3.5.0 + */ + transitionIn: function () + { + this.enabled = this.settings.transitionAllowInput; + }, + + /** + * The Scene that owns this plugin has finished transitioning in. + * + * @method Phaser.Input.InputPlugin#transitionComplete + * @private + * @since 3.5.0 + */ + transitionComplete: function () + { + if (!this.settings.transitionAllowInput) + { + this.enabled = true; + } + }, + + /** + * The Scene that owns this plugin is transitioning out. + * + * @method Phaser.Input.InputPlugin#transitionOut + * @private + * @since 3.5.0 + */ + transitionOut: function () + { + this.enabled = this.settings.transitionAllowInput; + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Input.InputPlugin#shutdown + * @fires Phaser.Input.Events#SHUTDOWN + * @private + * @since 3.0.0 + */ + shutdown: function () + { + // Registered input plugins listen for this + this.pluginEvents.emit(Events.SHUTDOWN); + + this._temp.length = 0; + this._list.length = 0; + this._draggable.length = 0; + this._pendingRemoval.length = 0; + this._pendingInsertion.length = 0; + this._dragState.length = 0; + + for (var i = 0; i < 10; i++) + { + this._drag[i] = []; + this._over[i] = []; + } + + this.removeAllListeners(); + + var manager = this.manager; + + manager.canvas.style.cursor = manager.defaultCursor; + + var eventEmitter = this.systems.events; + + eventEmitter.off(SceneEvents.TRANSITION_START, this.transitionIn, this); + eventEmitter.off(SceneEvents.TRANSITION_OUT, this.transitionOut, this); + eventEmitter.off(SceneEvents.TRANSITION_COMPLETE, this.transitionComplete, this); + eventEmitter.off(SceneEvents.PRE_UPDATE, this.preUpdate, this); + + manager.events.off(Events.GAME_OUT, this.onGameOut, this); + manager.events.off(Events.GAME_OVER, this.onGameOver, this); + + eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Loops through all of the Input Manager Pointer instances and calls `reset` on them. + * + * Use this function if you find that input has been stolen from Phaser via a 3rd + * party component, such as Vue, and you need to tell Phaser to reset the Pointer states. + * + * @method Phaser.Input.InputPlugin#resetPointers + * @since 3.60.0 + */ + resetPointers: function () + { + var pointers = this.manager.pointers; + + for (var i = 0; i < pointers.length; i++) + { + pointers[i].reset(); + } + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Input.InputPlugin#destroy + * @fires Phaser.Input.Events#DESTROY + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + // Registered input plugins listen for this + this.pluginEvents.emit(Events.DESTROY); + + this.pluginEvents.removeAllListeners(); + + this.scene.sys.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.cameras = null; + this.manager = null; + this.events = null; + this.mouse = null; + }, + + /** + * The x coordinates of the ActivePointer based on the first camera in the camera list. + * This is only safe to use if your game has just 1 non-transformed camera and doesn't use multi-touch. + * + * @name Phaser.Input.InputPlugin#x + * @type {number} + * @readonly + * @since 3.0.0 + */ + x: { + + get: function () + { + return this.manager.activePointer.x; + } + + }, + + /** + * The y coordinates of the ActivePointer based on the first camera in the camera list. + * This is only safe to use if your game has just 1 non-transformed camera and doesn't use multi-touch. + * + * @name Phaser.Input.InputPlugin#y + * @type {number} + * @readonly + * @since 3.0.0 + */ + y: { + + get: function () + { + return this.manager.activePointer.y; + } + + }, + + /** + * Are any mouse or touch pointers currently over the game canvas? + * + * @name Phaser.Input.InputPlugin#isOver + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + isOver: { + + get: function () + { + return this.manager.isOver; + } + + }, + + /** + * The mouse has its own unique Pointer object, which you can reference directly if making a _desktop specific game_. + * If you are supporting both desktop and touch devices then do not use this property, instead use `activePointer` + * which will always map to the most recently interacted pointer. + * + * @name Phaser.Input.InputPlugin#mousePointer + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + mousePointer: { + + get: function () + { + return this.manager.mousePointer; + } + + }, + + /** + * The current active input Pointer. + * + * @name Phaser.Input.InputPlugin#activePointer + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.0.0 + */ + activePointer: { + + get: function () + { + return this.manager.activePointer; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer1 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer1: { + + get: function () + { + return this.manager.pointers[1]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer2 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer2: { + + get: function () + { + return this.manager.pointers[2]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer3 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer3: { + + get: function () + { + return this.manager.pointers[3]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer4 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer4: { + + get: function () + { + return this.manager.pointers[4]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer5 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer5: { + + get: function () + { + return this.manager.pointers[5]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer6 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer6: { + + get: function () + { + return this.manager.pointers[6]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer7 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer7: { + + get: function () + { + return this.manager.pointers[7]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer8 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer8: { + + get: function () + { + return this.manager.pointers[8]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer9 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer9: { + + get: function () + { + return this.manager.pointers[9]; + } + + }, + + /** + * A touch-based Pointer object. + * This will be `undefined` by default unless you add a new Pointer using `addPointer`. + * + * @name Phaser.Input.InputPlugin#pointer10 + * @type {Phaser.Input.Pointer} + * @readonly + * @since 3.10.0 + */ + pointer10: { + + get: function () + { + return this.manager.pointers[10]; + } + + } + +}); + +PluginCache.register('InputPlugin', InputPlugin, 'input'); + +module.exports = InputPlugin; + + +/***/ }), + +/***/ 89639: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetValue = __webpack_require__(35154); + +// Contains the plugins that Phaser uses globally and locally. +// These are the source objects, not instantiated. +var inputPlugins = {}; + +/** + * @namespace Phaser.Input.InputPluginCache + */ + +var InputPluginCache = {}; + +/** + * Static method called directly by the Core internal Plugins. + * Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin) + * Plugin is the object to instantiate to create the plugin + * Mapping is what the plugin is injected into the Scene.Systems as (i.e. input) + * + * @function Phaser.Input.InputPluginCache.register + * @static + * @since 3.10.0 + * + * @param {string} key - A reference used to get this plugin from the plugin cache. + * @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated. + * @param {string} mapping - If this plugin is to be injected into the Input Plugin, this is the property key used. + * @param {string} settingsKey - The key in the Scene Settings to check to see if this plugin should install or not. + * @param {string} configKey - The key in the Game Config to check to see if this plugin should install or not. + */ +InputPluginCache.register = function (key, plugin, mapping, settingsKey, configKey) +{ + inputPlugins[key] = { plugin: plugin, mapping: mapping, settingsKey: settingsKey, configKey: configKey }; +}; + +/** + * Returns the input plugin object from the cache based on the given key. + * + * @function Phaser.Input.InputPluginCache.getPlugin + * @static + * @since 3.10.0 + * + * @param {string} key - The key of the input plugin to get. + * + * @return {Phaser.Types.Input.InputPluginContainer} The input plugin object. + */ +InputPluginCache.getPlugin = function (key) +{ + return inputPlugins[key]; +}; + +/** + * Installs all of the registered Input Plugins into the given target. + * + * @function Phaser.Input.InputPluginCache.install + * @static + * @since 3.10.0 + * + * @param {Phaser.Input.InputPlugin} target - The target InputPlugin to install the plugins into. + */ +InputPluginCache.install = function (target) +{ + var sys = target.scene.sys; + var settings = sys.settings.input; + var config = sys.game.config; + + for (var key in inputPlugins) + { + var source = inputPlugins[key].plugin; + var mapping = inputPlugins[key].mapping; + var settingsKey = inputPlugins[key].settingsKey; + var configKey = inputPlugins[key].configKey; + + if (GetValue(settings, settingsKey, config[configKey])) + { + target[mapping] = new source(target); + } + } +}; + +/** + * Removes an input plugin based on the given key. + * + * @function Phaser.Input.InputPluginCache.remove + * @static + * @since 3.10.0 + * + * @param {string} key - The key of the input plugin to remove. + */ +InputPluginCache.remove = function (key) +{ + if (inputPlugins.hasOwnProperty(key)) + { + delete inputPlugins[key]; + } +}; + +module.exports = InputPluginCache; + + +/***/ }), + +/***/ 42515: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Angle = __webpack_require__(31040); +var Class = __webpack_require__(83419); +var Distance = __webpack_require__(20339); +var FuzzyEqual = __webpack_require__(43855); +var SmoothStepInterpolation = __webpack_require__(47235); +var Vector2 = __webpack_require__(26099); +var OS = __webpack_require__(25892); + +/** + * @classdesc + * A Pointer object encapsulates both mouse and touch input within Phaser. + * + * By default, Phaser will create 2 pointers for your game to use. If you require more, i.e. for a multi-touch + * game, then use the `InputPlugin.addPointer` method to do so, rather than instantiating this class directly, + * otherwise it won't be managed by the input system. + * + * You can reference the current active pointer via `InputPlugin.activePointer`. You can also use the properties + * `InputPlugin.pointer1` through to `pointer10`, for each pointer you have enabled in your game. + * + * The properties of this object are set by the Input Plugin during processing. This object is then sent in all + * input related events that the Input Plugin emits, so you can reference properties from it directly in your + * callbacks. + * + * @class Pointer + * @memberof Phaser.Input + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.InputManager} manager - A reference to the Input Manager. + * @param {number} id - The internal ID of this Pointer. + */ +var Pointer = new Class({ + + initialize: + + function Pointer (manager, id) + { + /** + * A reference to the Input Manager. + * + * @name Phaser.Input.Pointer#manager + * @type {Phaser.Input.InputManager} + * @since 3.0.0 + */ + this.manager = manager; + + /** + * The internal ID of this Pointer. + * + * @name Phaser.Input.Pointer#id + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.id = id; + + /** + * The most recent native DOM Event this Pointer has processed. + * + * @name Phaser.Input.Pointer#event + * @type {(TouchEvent|MouseEvent|WheelEvent)} + * @since 3.0.0 + */ + this.event; + + /** + * The DOM element the Pointer was pressed down on, taken from the DOM event. + * In a default set-up this will be the Canvas that Phaser is rendering to, or the Window element. + * + * @name Phaser.Input.Pointer#downElement + * @type {any} + * @readonly + * @since 3.16.0 + */ + this.downElement; + + /** + * The DOM element the Pointer was released on, taken from the DOM event. + * In a default set-up this will be the Canvas that Phaser is rendering to, or the Window element. + * + * @name Phaser.Input.Pointer#upElement + * @type {any} + * @readonly + * @since 3.16.0 + */ + this.upElement; + + /** + * The camera the Pointer interacted with during its last update. + * + * A Pointer can only ever interact with one camera at once, which will be the top-most camera + * in the list should multiple cameras be positioned on-top of each other. + * + * @name Phaser.Input.Pointer#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @default null + * @since 3.0.0 + */ + this.camera = null; + + /** + * A read-only property that indicates which button was pressed, or released, on the pointer + * during the most recent event. It is only set during `up` and `down` events. + * + * On Touch devices the value is always 0. + * + * Users may change the configuration of buttons on their pointing device so that if an event's button property + * is zero, it may not have been caused by the button that is physically left–most on the pointing device; + * however, it should behave as if the left button was clicked in the standard button layout. + * + * @name Phaser.Input.Pointer#button + * @type {number} + * @readonly + * @default 0 + * @since 3.18.0 + */ + this.button = 0; + + /** + * 0: No button or un-initialized + * 1: Left button + * 2: Right button + * 4: Wheel button or middle button + * 8: 4th button (typically the "Browser Back" button) + * 16: 5th button (typically the "Browser Forward" button) + * + * For a mouse configured for left-handed use, the button actions are reversed. + * In this case, the values are read from right to left. + * + * @name Phaser.Input.Pointer#buttons + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.buttons = 0; + + /** + * The position of the Pointer in screen space. + * + * @name Phaser.Input.Pointer#position + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.0.0 + */ + this.position = new Vector2(); + + /** + * The previous position of the Pointer in screen space. + * + * The old x and y values are stored in here during the InputManager.transformPointer call. + * + * Use the properties `velocity`, `angle` and `distance` to create your own gesture recognition. + * + * @name Phaser.Input.Pointer#prevPosition + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.11.0 + */ + this.prevPosition = new Vector2(); + + /** + * An internal vector used for calculations of the pointer speed and angle. + * + * @name Phaser.Input.Pointer#midPoint + * @type {Phaser.Math.Vector2} + * @private + * @since 3.16.0 + */ + this.midPoint = new Vector2(-1, -1); + + /** + * The current velocity of the Pointer, based on its current and previous positions. + * + * This value is smoothed out each frame, according to the `motionFactor` property. + * + * This property is updated whenever the Pointer moves, regardless of any button states. In other words, + * it changes based on movement alone - a button doesn't have to be pressed first. + * + * @name Phaser.Input.Pointer#velocity + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.16.0 + */ + this.velocity = new Vector2(); + + /** + * The current angle the Pointer is moving, in radians, based on its previous and current position. + * + * The angle is based on the old position facing to the current position. + * + * This property is updated whenever the Pointer moves, regardless of any button states. In other words, + * it changes based on movement alone - a button doesn't have to be pressed first. + * + * @name Phaser.Input.Pointer#angle + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.angle = 0; + + /** + * The distance the Pointer has moved, based on its previous and current position. + * + * This value is smoothed out each frame, according to the `motionFactor` property. + * + * This property is updated whenever the Pointer moves, regardless of any button states. In other words, + * it changes based on movement alone - a button doesn't have to be pressed first. + * + * If you need the total distance travelled since the primary buttons was pressed down, + * then use the `Pointer.getDistance` method. + * + * @name Phaser.Input.Pointer#distance + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.distance = 0; + + /** + * The smoothing factor to apply to the Pointer position. + * + * Due to their nature, pointer positions are inherently noisy. While this is fine for lots of games, if you need cleaner positions + * then you can set this value to apply an automatic smoothing to the positions as they are recorded. + * + * The default value of zero means 'no smoothing'. + * Set to a small value, such as 0.2, to apply an average level of smoothing between positions. You can do this by changing this + * value directly, or by setting the `input.smoothFactor` property in the Game Config. + * + * Positions are only smoothed when the pointer moves. If the primary button on this Pointer enters an Up or Down state, then the position + * is always precise, and not smoothed. + * + * @name Phaser.Input.Pointer#smoothFactor + * @type {number} + * @default 0 + * @since 3.16.0 + */ + this.smoothFactor = 0; + + /** + * The factor applied to the motion smoothing each frame. + * + * This value is passed to the Smooth Step Interpolation that is used to calculate the velocity, + * angle and distance of the Pointer. It's applied every frame, until the midPoint reaches the current + * position of the Pointer. 0.2 provides a good average but can be increased if you need a + * quicker update and are working in a high performance environment. Never set this value to + * zero. + * + * @name Phaser.Input.Pointer#motionFactor + * @type {number} + * @default 0.2 + * @since 3.16.0 + */ + this.motionFactor = 0.2; + + /** + * The x position of this Pointer, translated into the coordinate space of the most recent Camera it interacted with. + * + * If you wish to use this value _outside_ of an input event handler then you should update it first by calling + * the `Pointer.updateWorldPoint` method. + * + * @name Phaser.Input.Pointer#worldX + * @type {number} + * @default 0 + * @since 3.10.0 + */ + this.worldX = 0; + + /** + * The y position of this Pointer, translated into the coordinate space of the most recent Camera it interacted with. + * + * If you wish to use this value _outside_ of an input event handler then you should update it first by calling + * the `Pointer.updateWorldPoint` method. + * + * @name Phaser.Input.Pointer#worldY + * @type {number} + * @default 0 + * @since 3.10.0 + */ + this.worldY = 0; + + /** + * Time when this Pointer was most recently moved (regardless of the state of its buttons, if any) + * + * @name Phaser.Input.Pointer#moveTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.moveTime = 0; + + /** + * X coordinate of the Pointer when Button 1 (left button), or Touch, was pressed, used for dragging objects. + * + * @name Phaser.Input.Pointer#downX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.downX = 0; + + /** + * Y coordinate of the Pointer when Button 1 (left button), or Touch, was pressed, used for dragging objects. + * + * @name Phaser.Input.Pointer#downY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.downY = 0; + + /** + * The Event timestamp when the first button, or Touch input, was pressed. Used for dragging objects. + * + * @name Phaser.Input.Pointer#downTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.downTime = 0; + + /** + * X coordinate of the Pointer when Button 1 (left button), or Touch, was released, used for dragging objects. + * + * @name Phaser.Input.Pointer#upX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.upX = 0; + + /** + * Y coordinate of the Pointer when Button 1 (left button), or Touch, was released, used for dragging objects. + * + * @name Phaser.Input.Pointer#upY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.upY = 0; + + /** + * The Event timestamp when the final button, or Touch input, was released. Used for dragging objects. + * + * @name Phaser.Input.Pointer#upTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.upTime = 0; + + /** + * Is the primary button down? (usually button 0, the left mouse button) + * + * @name Phaser.Input.Pointer#primaryDown + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.primaryDown = false; + + /** + * Is _any_ button on this pointer considered as being down? + * + * @name Phaser.Input.Pointer#isDown + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isDown = false; + + /** + * Did the previous input event come from a Touch input (true) or Mouse? (false) + * + * @name Phaser.Input.Pointer#wasTouch + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.wasTouch = false; + + /** + * Did this Pointer get canceled by a touchcancel event? + * + * Note: "canceled" is the American-English spelling of "cancelled". Please don't submit PRs correcting it! + * + * @name Phaser.Input.Pointer#wasCanceled + * @type {boolean} + * @default false + * @since 3.15.0 + */ + this.wasCanceled = false; + + /** + * If the mouse is locked, the horizontal relative movement of the Pointer in pixels since last frame. + * + * @name Phaser.Input.Pointer#movementX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.movementX = 0; + + /** + * If the mouse is locked, the vertical relative movement of the Pointer in pixels since last frame. + * + * @name Phaser.Input.Pointer#movementY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.movementY = 0; + + /** + * The identifier property of the Pointer as set by the DOM event when this Pointer is started. + * + * @name Phaser.Input.Pointer#identifier + * @type {number} + * @since 3.10.0 + */ + this.identifier = 0; + + /** + * The pointerId property of the Pointer as set by the DOM event when this Pointer is started. + * The browser can and will recycle this value. + * + * @name Phaser.Input.Pointer#pointerId + * @type {number} + * @since 3.10.0 + */ + this.pointerId = null; + + /** + * An active Pointer is one that is currently pressed down on the display. + * A Mouse is always considered as active. + * + * @name Phaser.Input.Pointer#active + * @type {boolean} + * @since 3.10.0 + */ + this.active = (id === 0) ? true : false; + + /** + * Is this pointer Pointer Locked? + * + * Only a mouse pointer can be locked and it only becomes locked when requested via + * the browsers Pointer Lock API. + * + * You can request this by calling the `this.input.mouse.requestPointerLock()` method from + * a `pointerdown` or `pointerup` event handler. + * + * @name Phaser.Input.Pointer#locked + * @readonly + * @type {boolean} + * @since 3.19.0 + */ + this.locked = false; + + /** + * The horizontal scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * + * @name Phaser.Input.Pointer#deltaX + * @type {number} + * @default 0 + * @since 3.18.0 + */ + this.deltaX = 0; + + /** + * The vertical scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * This value will typically be less than 0 if the user scrolls up and greater than zero if scrolling down. + * + * @name Phaser.Input.Pointer#deltaY + * @type {number} + * @default 0 + * @since 3.18.0 + */ + this.deltaY = 0; + + /** + * The z-axis scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * + * @name Phaser.Input.Pointer#deltaZ + * @type {number} + * @default 0 + * @since 3.18.0 + */ + this.deltaZ = 0; + }, + + /** + * Takes a Camera and updates this Pointer's `worldX` and `worldY` values so they are + * the result of a translation through the given Camera. + * + * Note that the values will be automatically replaced the moment the Pointer is + * updated by an input event, such as a mouse move, so should be used immediately. + * + * @method Phaser.Input.Pointer#updateWorldPoint + * @since 3.19.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera which is being tested against. + * + * @return {this} This Pointer object. + */ + updateWorldPoint: function (camera) + { + // Stores the world point inside of tempPoint + var temp = camera.getWorldPoint(this.x, this.y); + + this.worldX = temp.x; + this.worldY = temp.y; + + return this; + }, + + /** + * Takes a Camera and returns a Vector2 containing the translated position of this Pointer + * within that Camera. This can be used to convert this Pointers position into camera space. + * + * @method Phaser.Input.Pointer#positionToCamera + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use for the translation. + * @param {(Phaser.Math.Vector2|object)} [output] - A Vector2-like object in which to store the translated position. + * + * @return {(Phaser.Math.Vector2|object)} A Vector2 containing the translated coordinates of this Pointer, based on the given camera. + */ + positionToCamera: function (camera, output) + { + return camera.getWorldPoint(this.x, this.y, output); + }, + + /** + * Calculates the motion of this Pointer, including its velocity and angle of movement. + * This method is called automatically each frame by the Input Manager. + * + * @method Phaser.Input.Pointer#updateMotion + * @private + * @since 3.16.0 + */ + updateMotion: function () + { + var cx = this.position.x; + var cy = this.position.y; + + var mx = this.midPoint.x; + var my = this.midPoint.y; + + if (cx === mx && cy === my) + { + // Nothing to do here + return; + } + + // Moving towards our goal ... + var vx = SmoothStepInterpolation(this.motionFactor, mx, cx); + var vy = SmoothStepInterpolation(this.motionFactor, my, cy); + + if (FuzzyEqual(vx, cx, 0.1)) + { + vx = cx; + } + + if (FuzzyEqual(vy, cy, 0.1)) + { + vy = cy; + } + + this.midPoint.set(vx, vy); + + var dx = cx - vx; + var dy = cy - vy; + + this.velocity.set(dx, dy); + + this.angle = Angle(vx, vy, cx, cy); + + this.distance = Math.sqrt(dx * dx + dy * dy); + }, + + /** + * Internal method to handle a Mouse Up Event. + * + * @method Phaser.Input.Pointer#up + * @private + * @since 3.0.0 + * + * @param {MouseEvent} event - The Mouse Event to process. + */ + up: function (event) + { + if ('buttons' in event) + { + this.buttons = event.buttons; + } + + this.event = event; + + this.button = event.button; + + this.upElement = event.target; + + // Sets the local x/y properties + this.manager.transformPointer(this, event.pageX, event.pageY, false); + + // 0: Main button pressed, usually the left button or the un-initialized state + if (event.button === 0) + { + this.primaryDown = false; + this.upX = this.x; + this.upY = this.y; + } + + if (this.buttons === 0) + { + // No more buttons are still down + this.isDown = false; + + this.upTime = event.timeStamp; + + this.wasTouch = false; + } + }, + + /** + * Internal method to handle a Mouse Down Event. + * + * @method Phaser.Input.Pointer#down + * @private + * @since 3.0.0 + * + * @param {MouseEvent} event - The Mouse Event to process. + */ + down: function (event) + { + if ('buttons' in event) + { + this.buttons = event.buttons; + } + + this.event = event; + + this.button = event.button; + + this.downElement = event.target; + + // Sets the local x/y properties + this.manager.transformPointer(this, event.pageX, event.pageY, false); + + // 0: Main button pressed, usually the left button or the un-initialized state + if (event.button === 0) + { + this.primaryDown = true; + this.downX = this.x; + this.downY = this.y; + } + + if (OS.macOS && event.ctrlKey) + { + // Override button settings on macOS + this.buttons = 2; + this.primaryDown = false; + } + + if (!this.isDown) + { + this.isDown = true; + + this.downTime = event.timeStamp; + } + + this.wasTouch = false; + }, + + /** + * Internal method to handle a Mouse Move Event. + * + * @method Phaser.Input.Pointer#move + * @private + * @since 3.0.0 + * + * @param {MouseEvent} event - The Mouse Event to process. + */ + move: function (event) + { + if ('buttons' in event) + { + this.buttons = event.buttons; + } + + this.event = event; + + // Sets the local x/y properties + this.manager.transformPointer(this, event.pageX, event.pageY, true); + + if (this.locked) + { + // Multiple DOM events may occur within one frame, but only one Phaser event will fire + this.movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + this.movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + } + + this.moveTime = event.timeStamp; + + this.wasTouch = false; + }, + + /** + * Internal method to handle a Mouse Wheel Event. + * + * @method Phaser.Input.Pointer#wheel + * @private + * @since 3.18.0 + * + * @param {WheelEvent} event - The Wheel Event to process. + */ + wheel: function (event) + { + if ('buttons' in event) + { + this.buttons = event.buttons; + } + + this.event = event; + + // Sets the local x/y properties + this.manager.transformPointer(this, event.pageX, event.pageY, false); + + this.deltaX = event.deltaX; + this.deltaY = event.deltaY; + this.deltaZ = event.deltaZ; + + this.wasTouch = false; + }, + + /** + * Internal method to handle a Touch Start Event. + * + * @method Phaser.Input.Pointer#touchstart + * @private + * @since 3.0.0 + * + * @param {Touch} touch - The Changed Touch from the Touch Event. + * @param {TouchEvent} event - The full Touch Event. + */ + touchstart: function (touch, event) + { + if (touch['pointerId']) + { + this.pointerId = touch.pointerId; + } + + this.identifier = touch.identifier; + this.target = touch.target; + this.active = true; + + this.buttons = 1; + + this.event = event; + + this.downElement = touch.target; + + // Sets the local x/y properties + this.manager.transformPointer(this, touch.pageX, touch.pageY, false); + + this.primaryDown = true; + this.downX = this.x; + this.downY = this.y; + this.downTime = event.timeStamp; + + this.isDown = true; + + this.wasTouch = true; + this.wasCanceled = false; + + this.updateMotion(); + }, + + /** + * Internal method to handle a Touch Move Event. + * + * @method Phaser.Input.Pointer#touchmove + * @private + * @since 3.0.0 + * + * @param {Touch} touch - The Changed Touch from the Touch Event. + * @param {TouchEvent} event - The full Touch Event. + */ + touchmove: function (touch, event) + { + this.event = event; + + // Sets the local x/y properties + this.manager.transformPointer(this, touch.pageX, touch.pageY, true); + + this.moveTime = event.timeStamp; + + this.wasTouch = true; + + this.updateMotion(); + }, + + /** + * Internal method to handle a Touch End Event. + * + * @method Phaser.Input.Pointer#touchend + * @private + * @since 3.0.0 + * + * @param {Touch} touch - The Changed Touch from the Touch Event. + * @param {TouchEvent} event - The full Touch Event. + */ + touchend: function (touch, event) + { + this.buttons = 0; + + this.event = event; + + this.upElement = touch.target; + + // Sets the local x/y properties + this.manager.transformPointer(this, touch.pageX, touch.pageY, false); + + this.primaryDown = false; + this.upX = this.x; + this.upY = this.y; + this.upTime = event.timeStamp; + + this.isDown = false; + + this.wasTouch = true; + this.wasCanceled = false; + + this.active = false; + + this.updateMotion(); + }, + + /** + * Internal method to handle a Touch Cancel Event. + * + * @method Phaser.Input.Pointer#touchcancel + * @private + * @since 3.15.0 + * + * @param {Touch} touch - The Changed Touch from the Touch Event. + * @param {TouchEvent} event - The full Touch Event. + */ + touchcancel: function (touch, event) + { + this.buttons = 0; + + this.event = event; + + this.upElement = touch.target; + + // Sets the local x/y properties + this.manager.transformPointer(this, touch.pageX, touch.pageY, false); + + this.primaryDown = false; + this.upX = this.x; + this.upY = this.y; + this.upTime = event.timeStamp; + + this.isDown = false; + + this.wasTouch = true; + this.wasCanceled = true; + + this.active = false; + }, + + /** + * Checks to see if any buttons are being held down on this Pointer. + * + * @method Phaser.Input.Pointer#noButtonDown + * @since 3.0.0 + * + * @return {boolean} `true` if no buttons are being held down. + */ + noButtonDown: function () + { + return (this.buttons === 0); + }, + + /** + * Checks to see if the left button is being held down on this Pointer. + * + * @method Phaser.Input.Pointer#leftButtonDown + * @since 3.0.0 + * + * @return {boolean} `true` if the left button is being held down. + */ + leftButtonDown: function () + { + return (this.buttons & 1) ? true : false; + }, + + /** + * Checks to see if the right button is being held down on this Pointer. + * + * @method Phaser.Input.Pointer#rightButtonDown + * @since 3.0.0 + * + * @return {boolean} `true` if the right button is being held down. + */ + rightButtonDown: function () + { + return (this.buttons & 2) ? true : false; + }, + + /** + * Checks to see if the middle button is being held down on this Pointer. + * + * @method Phaser.Input.Pointer#middleButtonDown + * @since 3.0.0 + * + * @return {boolean} `true` if the middle button is being held down. + */ + middleButtonDown: function () + { + return (this.buttons & 4) ? true : false; + }, + + /** + * Checks to see if the back button is being held down on this Pointer. + * + * @method Phaser.Input.Pointer#backButtonDown + * @since 3.0.0 + * + * @return {boolean} `true` if the back button is being held down. + */ + backButtonDown: function () + { + return (this.buttons & 8) ? true : false; + }, + + /** + * Checks to see if the forward button is being held down on this Pointer. + * + * @method Phaser.Input.Pointer#forwardButtonDown + * @since 3.0.0 + * + * @return {boolean} `true` if the forward button is being held down. + */ + forwardButtonDown: function () + { + return (this.buttons & 16) ? true : false; + }, + + /** + * Checks to see if the release of the left button was the most recent activity on this Pointer. + * + * @method Phaser.Input.Pointer#leftButtonReleased + * @since 3.18.0 + * + * @return {boolean} `true` if the release of the left button was the most recent activity on this Pointer. + */ + leftButtonReleased: function () + { + return this.buttons === 0 ? (this.button === 0 && !this.isDown) : this.button === 0; + }, + + /** + * Checks to see if the release of the right button was the most recent activity on this Pointer. + * + * @method Phaser.Input.Pointer#rightButtonReleased + * @since 3.18.0 + * + * @return {boolean} `true` if the release of the right button was the most recent activity on this Pointer. + */ + rightButtonReleased: function () + { + return this.buttons === 0 ? (this.button === 2 && !this.isDown) : this.button === 2; + }, + + /** + * Checks to see if the release of the middle button was the most recent activity on this Pointer. + * + * @method Phaser.Input.Pointer#middleButtonReleased + * @since 3.18.0 + * + * @return {boolean} `true` if the release of the middle button was the most recent activity on this Pointer. + */ + middleButtonReleased: function () + { + return this.buttons === 0 ? (this.button === 1 && !this.isDown) : this.button === 1; + }, + + /** + * Checks to see if the release of the back button was the most recent activity on this Pointer. + * + * @method Phaser.Input.Pointer#backButtonReleased + * @since 3.18.0 + * + * @return {boolean} `true` if the release of the back button was the most recent activity on this Pointer. + */ + backButtonReleased: function () + { + return this.buttons === 0 ? (this.button === 3 && !this.isDown) : this.button === 3; + }, + + /** + * Checks to see if the release of the forward button was the most recent activity on this Pointer. + * + * @method Phaser.Input.Pointer#forwardButtonReleased + * @since 3.18.0 + * + * @return {boolean} `true` if the release of the forward button was the most recent activity on this Pointer. + */ + forwardButtonReleased: function () + { + return this.buttons === 0 ? (this.button === 4 && !this.isDown) : this.button === 4; + }, + + /** + * If the Pointer has a button pressed down at the time this method is called, it will return the + * distance between the Pointer's `downX` and `downY` values and the current position. + * + * If no button is held down, it will return the last recorded distance, based on where + * the Pointer was when the button was released. + * + * If you wish to get the distance being travelled currently, based on the velocity of the Pointer, + * then see the `Pointer.distance` property. + * + * @method Phaser.Input.Pointer#getDistance + * @since 3.13.0 + * + * @return {number} The distance the Pointer moved. + */ + getDistance: function () + { + if (this.isDown) + { + return Distance(this.downX, this.downY, this.x, this.y); + } + else + { + return Distance(this.downX, this.downY, this.upX, this.upY); + } + }, + + /** + * If the Pointer has a button pressed down at the time this method is called, it will return the + * horizontal distance between the Pointer's `downX` and `downY` values and the current position. + * + * If no button is held down, it will return the last recorded horizontal distance, based on where + * the Pointer was when the button was released. + * + * @method Phaser.Input.Pointer#getDistanceX + * @since 3.16.0 + * + * @return {number} The horizontal distance the Pointer moved. + */ + getDistanceX: function () + { + if (this.isDown) + { + return Math.abs(this.downX - this.x); + } + else + { + return Math.abs(this.downX - this.upX); + } + }, + + /** + * If the Pointer has a button pressed down at the time this method is called, it will return the + * vertical distance between the Pointer's `downX` and `downY` values and the current position. + * + * If no button is held down, it will return the last recorded vertical distance, based on where + * the Pointer was when the button was released. + * + * @method Phaser.Input.Pointer#getDistanceY + * @since 3.16.0 + * + * @return {number} The vertical distance the Pointer moved. + */ + getDistanceY: function () + { + if (this.isDown) + { + return Math.abs(this.downY - this.y); + } + else + { + return Math.abs(this.downY - this.upY); + } + }, + + /** + * If the Pointer has a button pressed down at the time this method is called, it will return the + * duration since the button was pressed down. + * + * If no button is held down, it will return the last recorded duration, based on the time + * the last button on the Pointer was released. + * + * @method Phaser.Input.Pointer#getDuration + * @since 3.16.0 + * + * @return {number} The duration the Pointer was held down for in milliseconds. + */ + getDuration: function () + { + if (this.isDown) + { + return (this.manager.time - this.downTime); + } + else + { + return (this.upTime - this.downTime); + } + }, + + /** + * If the Pointer has a button pressed down at the time this method is called, it will return the + * angle between the Pointer's `downX` and `downY` values and the current position. + * + * If no button is held down, it will return the last recorded angle, based on where + * the Pointer was when the button was released. + * + * The angle is based on the old position facing to the current position. + * + * If you wish to get the current angle, based on the velocity of the Pointer, then + * see the `Pointer.angle` property. + * + * @method Phaser.Input.Pointer#getAngle + * @since 3.16.0 + * + * @return {number} The angle between the Pointer's coordinates in radians. + */ + getAngle: function () + { + if (this.isDown) + { + return Angle(this.downX, this.downY, this.x, this.y); + } + else + { + return Angle(this.downX, this.downY, this.upX, this.upY); + } + }, + + /** + * Takes the previous and current Pointer positions and then generates an array of interpolated values between + * the two. The array will be populated up to the size of the `steps` argument. + * + * ```javaScript + * var points = pointer.getInterpolatedPosition(4); + * + * // points[0] = { x: 0, y: 0 } + * // points[1] = { x: 2, y: 1 } + * // points[2] = { x: 3, y: 2 } + * // points[3] = { x: 6, y: 3 } + * ``` + * + * Use this if you need to get smoothed values between the previous and current pointer positions. DOM pointer + * events can often fire faster than the main browser loop, and this will help you avoid janky movement + * especially if you have an object following a Pointer. + * + * Note that if you provide an output array it will only be populated up to the number of steps provided. + * It will not clear any previous data that may have existed beyond the range of the steps count. + * + * Internally it uses the Smooth Step interpolation calculation. + * + * @method Phaser.Input.Pointer#getInterpolatedPosition + * @since 3.11.0 + * + * @param {number} [steps=10] - The number of interpolation steps to use. + * @param {array} [out] - An array to store the results in. If not provided a new one will be created. + * + * @return {array} An array of interpolated values. + */ + getInterpolatedPosition: function (steps, out) + { + if (steps === undefined) { steps = 10; } + if (out === undefined) { out = []; } + + var prevX = this.prevPosition.x; + var prevY = this.prevPosition.y; + + var curX = this.position.x; + var curY = this.position.y; + + for (var i = 0; i < steps; i++) + { + var t = (1 / steps) * i; + + out[i] = { x: SmoothStepInterpolation(t, prevX, curX), y: SmoothStepInterpolation(t, prevY, curY) }; + } + + return out; + }, + + /** + * Fully reset this Pointer back to its unitialized state. + * + * @method Phaser.Input.Pointer#reset + * @since 3.60.0 + */ + reset: function () + { + this.event = null; + this.downElement = null; + this.upElement = null; + + this.button = 0; + this.buttons = 0; + + this.position.set(0, 0); + this.prevPosition.set(0, 0); + this.midPoint.set(-1, -1); + this.velocity.set(0, 0); + this.angle = 0; + this.distance = 0; + this.worldX = 0; + this.worldY = 0; + this.downX = 0; + this.downY = 0; + this.upX = 0; + this.upY = 0; + this.moveTime = 0; + this.upTime = 0; + this.downTime = 0; + this.primaryDown = false; + this.isDown = false; + this.wasTouch = false; + this.wasCanceled = false; + this.movementX = 0; + this.movementY = 0; + this.identifier = 0; + this.pointerId = null; + this.deltaX = 0; + this.deltaY = 0; + this.deltaZ = 0; + + this.active = (this.id === 0) ? true : false; + }, + + /** + * Destroys this Pointer instance and resets its external references. + * + * @method Phaser.Input.Pointer#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.camera = null; + this.manager = null; + this.position = null; + }, + + /** + * The x position of this Pointer. + * The value is in screen space. + * See `worldX` to get a camera converted position. + * + * @name Phaser.Input.Pointer#x + * @type {number} + * @since 3.0.0 + */ + x: { + + get: function () + { + return this.position.x; + }, + + set: function (value) + { + this.position.x = value; + } + + }, + + /** + * The y position of this Pointer. + * The value is in screen space. + * See `worldY` to get a camera converted position. + * + * @name Phaser.Input.Pointer#y + * @type {number} + * @since 3.0.0 + */ + y: { + + get: function () + { + return this.position.y; + }, + + set: function (value) + { + this.position.y = value; + } + + }, + + /** + * Time when this Pointer was most recently updated by a DOM Event. + * This comes directly from the `event.timeStamp` property. + * If no event has yet taken place, it will return zero. + * + * @name Phaser.Input.Pointer#time + * @type {number} + * @readonly + * @since 3.16.0 + */ + time: { + + get: function () + { + return (this.event) ? this.event.timeStamp : 0; + } + + } + +}); + +module.exports = Pointer; + + +/***/ }), + +/***/ 93301: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var INPUT_CONST = { + + /** + * The mouse pointer is being held down. + * + * @name Phaser.Input.MOUSE_DOWN + * @type {number} + * @since 3.10.0 + */ + MOUSE_DOWN: 0, + + /** + * The mouse pointer is being moved. + * + * @name Phaser.Input.MOUSE_MOVE + * @type {number} + * @since 3.10.0 + */ + MOUSE_MOVE: 1, + + /** + * The mouse pointer is released. + * + * @name Phaser.Input.MOUSE_UP + * @type {number} + * @since 3.10.0 + */ + MOUSE_UP: 2, + + /** + * A touch pointer has been started. + * + * @name Phaser.Input.TOUCH_START + * @type {number} + * @since 3.10.0 + */ + TOUCH_START: 3, + + /** + * A touch pointer has been started. + * + * @name Phaser.Input.TOUCH_MOVE + * @type {number} + * @since 3.10.0 + */ + TOUCH_MOVE: 4, + + /** + * A touch pointer has been started. + * + * @name Phaser.Input.TOUCH_END + * @type {number} + * @since 3.10.0 + */ + TOUCH_END: 5, + + /** + * The pointer lock has changed. + * + * @name Phaser.Input.POINTER_LOCK_CHANGE + * @type {number} + * @since 3.10.0 + */ + POINTER_LOCK_CHANGE: 6, + + /** + * A touch pointer has been been cancelled by the browser. + * + * @name Phaser.Input.TOUCH_CANCEL + * @type {number} + * @since 3.15.0 + */ + TOUCH_CANCEL: 7, + + /** + * The mouse wheel changes. + * + * @name Phaser.Input.MOUSE_WHEEL + * @type {number} + * @since 3.18.0 + */ + MOUSE_WHEEL: 8 + +}; + +module.exports = INPUT_CONST; + + +/***/ }), + +/***/ 7179: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Boot Event. + * + * This internal event is dispatched by the Input Plugin when it boots, signalling to all of its systems to create themselves. + * + * @event Phaser.Input.Events#BOOT + * @type {string} + * @since 3.0.0 + */ +module.exports = 'boot'; + + +/***/ }), + +/***/ 85375: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Destroy Event. + * + * This internal event is dispatched by the Input Plugin when it is destroyed, signalling to all of its systems to destroy themselves. + * + * @event Phaser.Input.Events#DESTROY + * @type {string} + * @since 3.0.0 + */ +module.exports = 'destroy'; + + +/***/ }), + +/***/ 39843: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drag End Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer stops dragging a Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('dragend', listener)`. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DRAG_END]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DRAG_END} event instead. + * + * @event Phaser.Input.Events#DRAG_END + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer stopped dragging. + * @param {boolean} dropped - Whether the Game Object was dropped onto a target. + */ +module.exports = 'dragend'; + + +/***/ }), + +/***/ 23388: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drag Enter Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer drags a Game Object into a Drag Target. + * + * Listen to this event from within a Scene using: `this.input.on('dragenter', listener)`. + * + * A Pointer can only drag a single Game Object at once. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DRAG_ENTER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DRAG_ENTER} event instead. + * + * @event Phaser.Input.Events#DRAG_ENTER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer is dragging. + * @param {Phaser.GameObjects.GameObject} target - The drag target that this pointer has moved into. + */ +module.exports = 'dragenter'; + + +/***/ }), + +/***/ 16133: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drag Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer moves while dragging a Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('drag', listener)`. + * + * A Pointer can only drag a single Game Object at once. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DRAG]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DRAG} event instead. + * + * @event Phaser.Input.Events#DRAG + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer is dragging. + * @param {number} dragX - The x coordinate where the Pointer is currently dragging the Game Object, in world space. + * @param {number} dragY - The y coordinate where the Pointer is currently dragging the Game Object, in world space. + */ +module.exports = 'drag'; + + +/***/ }), + +/***/ 27829: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drag Leave Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer drags a Game Object out of a Drag Target. + * + * Listen to this event from within a Scene using: `this.input.on('dragleave', listener)`. + * + * A Pointer can only drag a single Game Object at once. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DRAG_LEAVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DRAG_LEAVE} event instead. + * + * @event Phaser.Input.Events#DRAG_LEAVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer is dragging. + * @param {Phaser.GameObjects.GameObject} target - The drag target that this pointer has left. + */ +module.exports = 'dragleave'; + + +/***/ }), + +/***/ 53904: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drag Over Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer drags a Game Object over a Drag Target. + * + * When the Game Object first enters the drag target it will emit a `dragenter` event. If it then moves while within + * the drag target, it will emit this event instead. + * + * Listen to this event from within a Scene using: `this.input.on('dragover', listener)`. + * + * A Pointer can only drag a single Game Object at once. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DRAG_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DRAG_OVER} event instead. + * + * @event Phaser.Input.Events#DRAG_OVER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer is dragging. + * @param {Phaser.GameObjects.GameObject} target - The drag target that this pointer has moved over. + */ +module.exports = 'dragover'; + + +/***/ }), + +/***/ 56058: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drag Start Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer starts to drag any Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('dragstart', listener)`. + * + * A Pointer can only drag a single Game Object at once. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DRAG_START]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DRAG_START} event instead. + * + * @event Phaser.Input.Events#DRAG_START + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer is dragging. + */ +module.exports = 'dragstart'; + + +/***/ }), + +/***/ 2642: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Drop Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer drops a Game Object on a Drag Target. + * + * Listen to this event from within a Scene using: `this.input.on('drop', listener)`. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_DROP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DROP} event instead. + * + * @event Phaser.Input.Events#DROP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The interactive Game Object that this pointer was dragging. + * @param {Phaser.GameObjects.GameObject} target - The Drag Target the `gameObject` has been dropped on. + */ +module.exports = 'drop'; + + +/***/ }), + +/***/ 88171: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Down Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is pressed down on _any_ interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('gameobjectdown', listener)`. + * + * To receive this event, the Game Objects must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_POINTER_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_DOWN} event instead. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_DOWN} + * 2. [GAMEOBJECT_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DOWN} + * 3. [POINTER_DOWN]{@linkcode Phaser.Input.Events#event:POINTER_DOWN} or [POINTER_DOWN_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_DOWN_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_DOWN + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the pointer was pressed down on. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'gameobjectdown'; + + +/***/ }), + +/***/ 36147: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drag End Event. + * + * This event is dispatched by an interactive Game Object if a pointer stops dragging it. + * + * Listen to this event from a Game Object using: `gameObject.on('dragend', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive](Phaser.GameObjects.GameObject#setInteractive) for more details. + * + * @event Phaser.Input.Events#GAMEOBJECT_DRAG_END + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} dragX - The x coordinate where the Pointer stopped dragging the Game Object, in world space. + * @param {number} dragY - The y coordinate where the Pointer stopped dragging the Game Object, in world space. + * @param {boolean} dropped - Whether the Game Object was dropped onto a target. + */ +module.exports = 'dragend'; + + +/***/ }), + +/***/ 71692: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drag Enter Event. + * + * This event is dispatched by an interactive Game Object if a pointer drags it into a drag target. + * + * Listen to this event from a Game Object using: `gameObject.on('dragenter', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * @event Phaser.Input.Events#GAMEOBJECT_DRAG_ENTER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} target - The drag target that this pointer has moved into. + */ +module.exports = 'dragenter'; + + +/***/ }), + +/***/ 96149: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drag Event. + * + * This event is dispatched by an interactive Game Object if a pointer moves while dragging it. + * + * Listen to this event from a Game Object using: `gameObject.on('drag', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * @event Phaser.Input.Events#GAMEOBJECT_DRAG + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} dragX - The x coordinate where the Pointer is currently dragging the Game Object, in world space. + * @param {number} dragY - The y coordinate where the Pointer is currently dragging the Game Object, in world space. + */ +module.exports = 'drag'; + + +/***/ }), + +/***/ 81285: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drag Leave Event. + * + * This event is dispatched by an interactive Game Object if a pointer drags it out of a drag target. + * + * Listen to this event from a Game Object using: `gameObject.on('dragleave', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * @event Phaser.Input.Events#GAMEOBJECT_DRAG_LEAVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} target - The drag target that this pointer has left. + */ +module.exports = 'dragleave'; + + +/***/ }), + +/***/ 74048: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drag Over Event. + * + * This event is dispatched by an interactive Game Object if a pointer drags it over a drag target. + * + * When the Game Object first enters the drag target it will emit a `dragenter` event. If it then moves while within + * the drag target, it will emit this event instead. + * + * Listen to this event from a Game Object using: `gameObject.on('dragover', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * @event Phaser.Input.Events#GAMEOBJECT_DRAG_OVER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} target - The drag target that this pointer has moved over. + */ +module.exports = 'dragover'; + + +/***/ }), + +/***/ 21322: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drag Start Event. + * + * This event is dispatched by an interactive Game Object if a pointer starts to drag it. + * + * Listen to this event from a Game Object using: `gameObject.on('dragstart', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * There are lots of useful drag related properties that are set within the Game Object when dragging occurs. + * For example, `gameObject.input.dragStartX`, `dragStartY` and so on. + * + * @event Phaser.Input.Events#GAMEOBJECT_DRAG_START + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} dragX - The x coordinate where the Pointer is currently dragging the Game Object, in world space. + * @param {number} dragY - The y coordinate where the Pointer is currently dragging the Game Object, in world space. + */ +module.exports = 'dragstart'; + + +/***/ }), + +/***/ 49378: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Drop Event. + * + * This event is dispatched by an interactive Game Object if a pointer drops it on a Drag Target. + * + * Listen to this event from a Game Object using: `gameObject.on('drop', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive and enabled for drag. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * @event Phaser.Input.Events#GAMEOBJECT_DROP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} target - The Drag Target the `gameObject` has been dropped on. + */ +module.exports = 'drop'; + + +/***/ }), + +/***/ 86754: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Move Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is moved across _any_ interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('gameobjectmove', listener)`. + * + * To receive this event, the Game Objects must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_POINTER_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_MOVE} event instead. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_MOVE} + * 2. [GAMEOBJECT_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_MOVE} + * 3. [POINTER_MOVE]{@linkcode Phaser.Input.Events#event:POINTER_MOVE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_MOVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the pointer was moved on. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'gameobjectmove'; + + +/***/ }), + +/***/ 86433: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Out Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer moves out of _any_ interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('gameobjectout', listener)`. + * + * To receive this event, the Game Objects must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_POINTER_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OUT} event instead. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OUT} + * 2. [GAMEOBJECT_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_OUT} + * 3. [POINTER_OUT]{@linkcode Phaser.Input.Events#event:POINTER_OUT} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * If the pointer leaves the game canvas itself, it will not trigger an this event. To handle those cases, + * please listen for the [GAME_OUT]{@linkcode Phaser.Input.Events#event:GAME_OUT} event. + * + * @event Phaser.Input.Events#GAMEOBJECT_OUT + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the pointer moved out of. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'gameobjectout'; + + +/***/ }), + +/***/ 60709: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Over Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer moves over _any_ interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('gameobjectover', listener)`. + * + * To receive this event, the Game Objects must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_POINTER_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OVER} event instead. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OVER} + * 2. [GAMEOBJECT_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_OVER} + * 3. [POINTER_OVER]{@linkcode Phaser.Input.Events#event:POINTER_OVER} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_OVER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the pointer moved over. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'gameobjectover'; + + +/***/ }), + +/***/ 24081: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Pointer Down Event. + * + * This event is dispatched by an interactive Game Object if a pointer is pressed down on it. + * + * Listen to this event from a Game Object using: `gameObject.on('pointerdown', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_DOWN} + * 2. [GAMEOBJECT_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DOWN} + * 3. [POINTER_DOWN]{@linkcode Phaser.Input.Events#event:POINTER_DOWN} or [POINTER_DOWN_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_DOWN_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_POINTER_DOWN + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} localX - The x coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {number} localY - The y coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'pointerdown'; + + +/***/ }), + +/***/ 11172: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Pointer Move Event. + * + * This event is dispatched by an interactive Game Object if a pointer is moved while over it. + * + * Listen to this event from a Game Object using: `gameObject.on('pointermove', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_MOVE} + * 2. [GAMEOBJECT_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_MOVE} + * 3. [POINTER_MOVE]{@linkcode Phaser.Input.Events#event:POINTER_MOVE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_POINTER_MOVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} localX - The x coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {number} localY - The y coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'pointermove'; + + +/***/ }), + +/***/ 18907: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Pointer Out Event. + * + * This event is dispatched by an interactive Game Object if a pointer moves out of it. + * + * Listen to this event from a Game Object using: `gameObject.on('pointerout', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OUT} + * 2. [GAMEOBJECT_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_OUT} + * 3. [POINTER_OUT]{@linkcode Phaser.Input.Events#event:POINTER_OUT} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * If the pointer leaves the game canvas itself, it will not trigger an this event. To handle those cases, + * please listen for the [GAME_OUT]{@linkcode Phaser.Input.Events#event:GAME_OUT} event. + * + * @event Phaser.Input.Events#GAMEOBJECT_POINTER_OUT + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'pointerout'; + + +/***/ }), + +/***/ 95579: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Pointer Over Event. + * + * This event is dispatched by an interactive Game Object if a pointer moves over it. + * + * Listen to this event from a Game Object using: `gameObject.on('pointerover', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OVER} + * 2. [GAMEOBJECT_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_OVER} + * 3. [POINTER_OVER]{@linkcode Phaser.Input.Events#event:POINTER_OVER} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_POINTER_OVER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} localX - The x coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {number} localY - The y coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'pointerover'; + + +/***/ }), + +/***/ 35368: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Pointer Up Event. + * + * This event is dispatched by an interactive Game Object if a pointer is released while over it. + * + * Listen to this event from a Game Object using: `gameObject.on('pointerup', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_UP} + * 2. [GAMEOBJECT_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_UP} + * 3. [POINTER_UP]{@linkcode Phaser.Input.Events#event:POINTER_UP} or [POINTER_UP_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_UP_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_POINTER_UP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} localX - The x coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {number} localY - The y coordinate that the Pointer interacted with this object on, relative to the Game Object's top-left position. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'pointerup'; + + +/***/ }), + +/***/ 26972: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Pointer Wheel Event. + * + * This event is dispatched by an interactive Game Object if a pointer has its wheel moved while over it. + * + * Listen to this event from a Game Object using: `gameObject.on('wheel', listener)`. + * Note that the scope of the listener is automatically set to be the Game Object instance itself. + * + * To receive this event, the Game Object must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_WHEEL} + * 2. [GAMEOBJECT_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_WHEEL} + * 3. [POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:POINTER_WHEEL} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_POINTER_WHEEL + * @type {string} + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {number} deltaX - The horizontal scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * @param {number} deltaY - The vertical scroll amount that occurred due to the user moving a mouse wheel or similar input device. This value will typically be less than 0 if the user scrolls up and greater than zero if scrolling down. + * @param {number} deltaZ - The z-axis scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'wheel'; + + +/***/ }), + +/***/ 47078: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Up Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is released while over _any_ interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('gameobjectup', listener)`. + * + * To receive this event, the Game Objects must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_POINTER_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_UP} event instead. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_UP} + * 2. [GAMEOBJECT_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_UP} + * 3. [POINTER_UP]{@linkcode Phaser.Input.Events#event:POINTER_UP} or [POINTER_UP_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_UP_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_UP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the pointer was over when released. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'gameobjectup'; + + +/***/ }), + +/***/ 73802: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Wheel Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer has its wheel moved while over _any_ interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('gameobjectwheel', listener)`. + * + * To receive this event, the Game Objects must have been set as interactive. + * See [GameObject.setInteractive]{@link Phaser.GameObjects.GameObject#setInteractive} for more details. + * + * To listen for this event from a _specific_ Game Object, use the [GAMEOBJECT_POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_WHEEL} event instead. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_WHEEL} + * 2. [GAMEOBJECT_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_WHEEL} + * 3. [POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:POINTER_WHEEL} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#GAMEOBJECT_WHEEL + * @type {string} + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the pointer was over when the wheel changed. + * @param {number} deltaX - The horizontal scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * @param {number} deltaY - The vertical scroll amount that occurred due to the user moving a mouse wheel or similar input device. This value will typically be less than 0 if the user scrolls up and greater than zero if scrolling down. + * @param {number} deltaZ - The z-axis scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * @param {Phaser.Types.Input.EventData} event - The Phaser input event. You can call `stopPropagation()` to halt it from going any further in the event flow. + */ +module.exports = 'gameobjectwheel'; + + +/***/ }), + +/***/ 56718: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Game Out Event. + * + * This event is dispatched by the Input Plugin if the active pointer leaves the game canvas and is now + * outside of it, elsewhere on the web page. + * + * Listen to this event from within a Scene using: `this.input.on('gameout', listener)`. + * + * @event Phaser.Input.Events#GAME_OUT + * @type {string} + * @since 3.16.1 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {(MouseEvent|TouchEvent)} event - The DOM Event that triggered the canvas out. + */ +module.exports = 'gameout'; + + +/***/ }), + +/***/ 25936: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Game Over Event. + * + * This event is dispatched by the Input Plugin if the active pointer enters the game canvas and is now + * over of it, having previously been elsewhere on the web page. + * + * Listen to this event from within a Scene using: `this.input.on('gameover', listener)`. + * + * @event Phaser.Input.Events#GAME_OVER + * @type {string} + * @since 3.16.1 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {(MouseEvent|TouchEvent)} event - The DOM Event that triggered the canvas over. + */ +module.exports = 'gameover'; + + +/***/ }), + +/***/ 27503: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Manager Boot Event. + * + * This internal event is dispatched by the Input Manager when it boots. + * + * @event Phaser.Input.Events#MANAGER_BOOT + * @type {string} + * @since 3.0.0 + */ +module.exports = 'boot'; + + +/***/ }), + +/***/ 50852: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Manager Process Event. + * + * This internal event is dispatched by the Input Manager when not using the legacy queue system, + * and it wants the Input Plugins to update themselves. + * + * @event Phaser.Input.Events#MANAGER_PROCESS + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'process'; + + +/***/ }), + +/***/ 96438: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Manager Update Event. + * + * This internal event is dispatched by the Input Manager as part of its update step. + * + * @event Phaser.Input.Events#MANAGER_UPDATE + * @type {string} + * @since 3.0.0 + */ +module.exports = 'update'; + + +/***/ }), + +/***/ 59152: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Manager Pointer Lock Change Event. + * + * This event is dispatched by the Input Manager when it is processing a native Pointer Lock Change DOM Event. + * + * @event Phaser.Input.Events#POINTERLOCK_CHANGE + * @type {string} + * @since 3.0.0 + * + * @param {Event} event - The native DOM Event. + * @param {boolean} locked - The locked state of the Mouse Pointer. + */ +module.exports = 'pointerlockchange'; + + +/***/ }), + +/***/ 47777: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Down Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is pressed down anywhere. + * + * Listen to this event from within a Scene using: `this.input.on('pointerdown', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_DOWN} + * 2. [GAMEOBJECT_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DOWN} + * 3. [POINTER_DOWN]{@linkcode Phaser.Input.Events#event:POINTER_DOWN} or [POINTER_DOWN_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_DOWN_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_DOWN + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject[]} currentlyOver - An array containing all interactive Game Objects that the pointer was over when the event was created. + */ +module.exports = 'pointerdown'; + + +/***/ }), + +/***/ 27957: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Down Outside Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is pressed down anywhere outside of the game canvas. + * + * Listen to this event from within a Scene using: `this.input.on('pointerdownoutside', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_DOWN} + * 2. [GAMEOBJECT_DOWN]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_DOWN} + * 3. [POINTER_DOWN]{@linkcode Phaser.Input.Events#event:POINTER_DOWN} or [POINTER_DOWN_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_DOWN_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_DOWN_OUTSIDE + * @type {string} + * @since 3.16.1 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + */ +module.exports = 'pointerdownoutside'; + + +/***/ }), + +/***/ 19444: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Move Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is moved anywhere. + * + * Listen to this event from within a Scene using: `this.input.on('pointermove', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_MOVE} + * 2. [GAMEOBJECT_MOVE]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_MOVE} + * 3. [POINTER_MOVE]{@linkcode Phaser.Input.Events#event:POINTER_MOVE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_MOVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject[]} currentlyOver - An array containing all interactive Game Objects that the pointer was over when the event was created. + */ +module.exports = 'pointermove'; + + +/***/ }), + +/***/ 54251: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Out Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer moves out of any interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('pointerout', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OUT} + * 2. [GAMEOBJECT_OUT]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_OUT} + * 3. [POINTER_OUT]{@linkcode Phaser.Input.Events#event:POINTER_OUT} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * If the pointer leaves the game canvas itself, it will not trigger an this event. To handle those cases, + * please listen for the [GAME_OUT]{@linkcode Phaser.Input.Events#event:GAME_OUT} event. + * + * @event Phaser.Input.Events#POINTER_OUT + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject[]} justOut - An array containing all interactive Game Objects that the pointer moved out of when the event was created. + */ +module.exports = 'pointerout'; + + +/***/ }), + +/***/ 18667: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Over Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer moves over any interactive Game Object. + * + * Listen to this event from within a Scene using: `this.input.on('pointerover', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_OVER} + * 2. [GAMEOBJECT_OVER]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_OVER} + * 3. [POINTER_OVER]{@linkcode Phaser.Input.Events#event:POINTER_OVER} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_OVER + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject[]} justOver - An array containing all interactive Game Objects that the pointer moved over when the event was created. + */ +module.exports = 'pointerover'; + + +/***/ }), + +/***/ 27192: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Up Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is released anywhere. + * + * Listen to this event from within a Scene using: `this.input.on('pointerup', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_UP} + * 2. [GAMEOBJECT_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_UP} + * 3. [POINTER_UP]{@linkcode Phaser.Input.Events#event:POINTER_UP} or [POINTER_UP_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_UP_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_UP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject[]} currentlyOver - An array containing all interactive Game Objects that the pointer was over when the event was created. + */ +module.exports = 'pointerup'; + + +/***/ }), + +/***/ 24652: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Up Outside Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer is released anywhere outside of the game canvas. + * + * Listen to this event from within a Scene using: `this.input.on('pointerupoutside', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_UP} + * 2. [GAMEOBJECT_UP]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_UP} + * 3. [POINTER_UP]{@linkcode Phaser.Input.Events#event:POINTER_UP} or [POINTER_UP_OUTSIDE]{@linkcode Phaser.Input.Events#event:POINTER_UP_OUTSIDE} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_UP_OUTSIDE + * @type {string} + * @since 3.16.1 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + */ +module.exports = 'pointerupoutside'; + + +/***/ }), + +/***/ 45132: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pointer Wheel Input Event. + * + * This event is dispatched by the Input Plugin belonging to a Scene if a pointer has its wheel updated. + * + * Listen to this event from within a Scene using: `this.input.on('wheel', listener)`. + * + * The event hierarchy is as follows: + * + * 1. [GAMEOBJECT_POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_POINTER_WHEEL} + * 2. [GAMEOBJECT_WHEEL]{@linkcode Phaser.Input.Events#event:GAMEOBJECT_WHEEL} + * 3. [POINTER_WHEEL]{@linkcode Phaser.Input.Events#event:POINTER_WHEEL} + * + * With the top event being dispatched first and then flowing down the list. Note that higher-up event handlers can stop + * the propagation of this event. + * + * @event Phaser.Input.Events#POINTER_WHEEL + * @type {string} + * @since 3.18.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer responsible for triggering this event. + * @param {Phaser.GameObjects.GameObject[]} currentlyOver - An array containing all interactive Game Objects that the pointer was over when the event was created. + * @param {number} deltaX - The horizontal scroll amount that occurred due to the user moving a mouse wheel or similar input device. + * @param {number} deltaY - The vertical scroll amount that occurred due to the user moving a mouse wheel or similar input device. This value will typically be less than 0 if the user scrolls up and greater than zero if scrolling down. + * @param {number} deltaZ - The z-axis scroll amount that occurred due to the user moving a mouse wheel or similar input device. + */ +module.exports = 'wheel'; + + +/***/ }), + +/***/ 44512: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Pre-Update Event. + * + * This internal event is dispatched by the Input Plugin at the start of its `preUpdate` method. + * This hook is designed specifically for input plugins, but can also be listened to from user-land code. + * + * @event Phaser.Input.Events#PRE_UPDATE + * @type {string} + * @since 3.0.0 + */ +module.exports = 'preupdate'; + + +/***/ }), + +/***/ 15757: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Shutdown Event. + * + * This internal event is dispatched by the Input Plugin when it shuts down, signalling to all of its systems to shut themselves down. + * + * @event Phaser.Input.Events#SHUTDOWN + * @type {string} + * @since 3.0.0 + */ +module.exports = 'shutdown'; + + +/***/ }), + +/***/ 41637: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Start Event. + * + * This internal event is dispatched by the Input Plugin when it has finished setting-up, + * signalling to all of its internal systems to start. + * + * @event Phaser.Input.Events#START + * @type {string} + * @since 3.0.0 + */ +module.exports = 'start'; + + +/***/ }), + +/***/ 93802: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Input Plugin Update Event. + * + * This internal event is dispatched by the Input Plugin at the start of its `update` method. + * This hook is designed specifically for input plugins, but can also be listened to from user-land code. + * + * @event Phaser.Input.Events#UPDATE + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'update'; + + +/***/ }), + +/***/ 8214: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Events + */ + +module.exports = { + + BOOT: __webpack_require__(7179), + DESTROY: __webpack_require__(85375), + DRAG_END: __webpack_require__(39843), + DRAG_ENTER: __webpack_require__(23388), + DRAG: __webpack_require__(16133), + DRAG_LEAVE: __webpack_require__(27829), + DRAG_OVER: __webpack_require__(53904), + DRAG_START: __webpack_require__(56058), + DROP: __webpack_require__(2642), + GAME_OUT: __webpack_require__(56718), + GAME_OVER: __webpack_require__(25936), + GAMEOBJECT_DOWN: __webpack_require__(88171), + GAMEOBJECT_DRAG_END: __webpack_require__(36147), + GAMEOBJECT_DRAG_ENTER: __webpack_require__(71692), + GAMEOBJECT_DRAG: __webpack_require__(96149), + GAMEOBJECT_DRAG_LEAVE: __webpack_require__(81285), + GAMEOBJECT_DRAG_OVER: __webpack_require__(74048), + GAMEOBJECT_DRAG_START: __webpack_require__(21322), + GAMEOBJECT_DROP: __webpack_require__(49378), + GAMEOBJECT_MOVE: __webpack_require__(86754), + GAMEOBJECT_OUT: __webpack_require__(86433), + GAMEOBJECT_OVER: __webpack_require__(60709), + GAMEOBJECT_POINTER_DOWN: __webpack_require__(24081), + GAMEOBJECT_POINTER_MOVE: __webpack_require__(11172), + GAMEOBJECT_POINTER_OUT: __webpack_require__(18907), + GAMEOBJECT_POINTER_OVER: __webpack_require__(95579), + GAMEOBJECT_POINTER_UP: __webpack_require__(35368), + GAMEOBJECT_POINTER_WHEEL: __webpack_require__(26972), + GAMEOBJECT_UP: __webpack_require__(47078), + GAMEOBJECT_WHEEL: __webpack_require__(73802), + MANAGER_BOOT: __webpack_require__(27503), + MANAGER_PROCESS: __webpack_require__(50852), + MANAGER_UPDATE: __webpack_require__(96438), + POINTER_DOWN: __webpack_require__(47777), + POINTER_DOWN_OUTSIDE: __webpack_require__(27957), + POINTER_MOVE: __webpack_require__(19444), + POINTER_OUT: __webpack_require__(54251), + POINTER_OVER: __webpack_require__(18667), + POINTER_UP: __webpack_require__(27192), + POINTER_UP_OUTSIDE: __webpack_require__(24652), + POINTER_WHEEL: __webpack_require__(45132), + POINTERLOCK_CHANGE: __webpack_require__(59152), + PRE_UPDATE: __webpack_require__(44512), + SHUTDOWN: __webpack_require__(15757), + START: __webpack_require__(41637), + UPDATE: __webpack_require__(93802) + +}; + + +/***/ }), + +/***/ 97421: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * Contains information about a specific Gamepad Axis. + * Axis objects are created automatically by the Gamepad as they are needed. + * + * @class Axis + * @memberof Phaser.Input.Gamepad + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.Gamepad.Gamepad} pad - A reference to the Gamepad that this Axis belongs to. + * @param {number} index - The index of this Axis. + */ +var Axis = new Class({ + + initialize: + + function Axis (pad, index) + { + /** + * A reference to the Gamepad that this Axis belongs to. + * + * @name Phaser.Input.Gamepad.Axis#pad + * @type {Phaser.Input.Gamepad.Gamepad} + * @since 3.0.0 + */ + this.pad = pad; + + /** + * An event emitter to use to emit the axis events. + * + * @name Phaser.Input.Gamepad.Axis#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events = pad.events; + + /** + * The index of this Axis. + * + * @name Phaser.Input.Gamepad.Axis#index + * @type {number} + * @since 3.0.0 + */ + this.index = index; + + /** + * The raw axis value, between -1 and 1 with 0 being dead center. + * Use the method `getValue` to get a normalized value with the threshold applied. + * + * @name Phaser.Input.Gamepad.Axis#value + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.value = 0; + + /** + * Movement tolerance threshold below which axis values are ignored in `getValue`. + * + * @name Phaser.Input.Gamepad.Axis#threshold + * @type {number} + * @default 0.1 + * @since 3.0.0 + */ + this.threshold = 0.1; + }, + + /** + * Internal update handler for this Axis. + * Called automatically by the Gamepad as part of its update. + * + * @method Phaser.Input.Gamepad.Axis#update + * @private + * @since 3.0.0 + * + * @param {number} value - The value of the axis movement. + */ + update: function (value) + { + this.value = value; + }, + + /** + * Applies the `threshold` value to the axis and returns it. + * + * @method Phaser.Input.Gamepad.Axis#getValue + * @since 3.0.0 + * + * @return {number} The axis value, adjusted for the movement threshold. + */ + getValue: function () + { + return (Math.abs(this.value) < this.threshold) ? 0 : this.value; + }, + + /** + * Destroys this Axis instance and releases external references it holds. + * + * @method Phaser.Input.Gamepad.Axis#destroy + * @since 3.10.0 + */ + destroy: function () + { + this.pad = null; + this.events = null; + } + +}); + +module.exports = Axis; + + +/***/ }), + +/***/ 28884: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Events = __webpack_require__(92734); + +/** + * @classdesc + * Contains information about a specific button on a Gamepad. + * Button objects are created automatically by the Gamepad as they are needed. + * + * @class Button + * @memberof Phaser.Input.Gamepad + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.Gamepad.Gamepad} pad - A reference to the Gamepad that this Button belongs to. + * @param {number} index - The index of this Button. + */ +var Button = new Class({ + + initialize: + + function Button (pad, index) + { + /** + * A reference to the Gamepad that this Button belongs to. + * + * @name Phaser.Input.Gamepad.Button#pad + * @type {Phaser.Input.Gamepad.Gamepad} + * @since 3.0.0 + */ + this.pad = pad; + + /** + * An event emitter to use to emit the button events. + * + * @name Phaser.Input.Gamepad.Button#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events = pad.manager; + + /** + * The index of this Button. + * + * @name Phaser.Input.Gamepad.Button#index + * @type {number} + * @since 3.0.0 + */ + this.index = index; + + /** + * Between 0 and 1. + * + * @name Phaser.Input.Gamepad.Button#value + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.value = 0; + + /** + * Can be set for analogue buttons to enable a 'pressure' threshold, + * before a button is considered as being 'pressed'. + * + * @name Phaser.Input.Gamepad.Button#threshold + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.threshold = 1; + + /** + * Is the Button being pressed down or not? + * + * @name Phaser.Input.Gamepad.Button#pressed + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.pressed = false; + }, + + /** + * Internal update handler for this Button. + * Called automatically by the Gamepad as part of its update. + * + * @method Phaser.Input.Gamepad.Button#update + * @fires Phaser.Input.Gamepad.Events#BUTTON_DOWN + * @fires Phaser.Input.Gamepad.Events#BUTTON_UP + * @fires Phaser.Input.Gamepad.Events#GAMEPAD_BUTTON_DOWN + * @fires Phaser.Input.Gamepad.Events#GAMEPAD_BUTTON_UP + * @private + * @since 3.0.0 + * + * @param {number} value - The value of the button. Between 0 and 1. + */ + update: function (value) + { + this.value = value; + + var pad = this.pad; + var index = this.index; + + if (value >= this.threshold) + { + if (!this.pressed) + { + this.pressed = true; + this.events.emit(Events.BUTTON_DOWN, pad, this, value); + this.pad.emit(Events.GAMEPAD_BUTTON_DOWN, index, value, this); + } + } + else if (this.pressed) + { + this.pressed = false; + this.events.emit(Events.BUTTON_UP, pad, this, value); + this.pad.emit(Events.GAMEPAD_BUTTON_UP, index, value, this); + } + }, + + /** + * Destroys this Button instance and releases external references it holds. + * + * @method Phaser.Input.Gamepad.Button#destroy + * @since 3.10.0 + */ + destroy: function () + { + this.pad = null; + this.events = null; + } + +}); + +module.exports = Button; + + +/***/ }), + +/***/ 99125: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Axis = __webpack_require__(97421); +var Button = __webpack_require__(28884); +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A single Gamepad. + * + * These are created, updated and managed by the Gamepad Plugin. + * + * @class Gamepad + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Input.Gamepad + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.Gamepad.GamepadPlugin} manager - A reference to the Gamepad Plugin. + * @param {Phaser.Types.Input.Gamepad.Pad} pad - The Gamepad object, as extracted from GamepadEvent. + */ +var Gamepad = new Class({ + + Extends: EventEmitter, + + initialize: + + function Gamepad (manager, pad) + { + EventEmitter.call(this); + + /** + * A reference to the Gamepad Plugin. + * + * @name Phaser.Input.Gamepad.Gamepad#manager + * @type {Phaser.Input.Gamepad.GamepadPlugin} + * @since 3.0.0 + */ + this.manager = manager; + + /** + * A reference to the native Gamepad object that is connected to the browser. + * + * @name Phaser.Input.Gamepad.Gamepad#pad + * @type {any} + * @since 3.10.0 + */ + this.pad = pad; + + /** + * A string containing some information about the controller. + * + * This is not strictly specified, but in Firefox it will contain three pieces of information + * separated by dashes (-): two 4-digit hexadecimal strings containing the USB vendor and + * product id of the controller, and the name of the controller as provided by the driver. + * In Chrome it will contain the name of the controller as provided by the driver, + * followed by vendor and product 4-digit hexadecimal strings. + * + * @name Phaser.Input.Gamepad.Gamepad#id + * @type {string} + * @since 3.0.0 + */ + this.id = pad.id; + + /** + * An integer that is unique for each Gamepad currently connected to the system. + * This can be used to distinguish multiple controllers. + * Note that disconnecting a device and then connecting a new device may reuse the previous index. + * + * @name Phaser.Input.Gamepad.Gamepad#index + * @type {number} + * @since 3.0.0 + */ + this.index = pad.index; + + var buttons = []; + + for (var i = 0; i < pad.buttons.length; i++) + { + buttons.push(new Button(this, i)); + } + + /** + * An array of Gamepad Button objects, corresponding to the different buttons available on the Gamepad. + * + * @name Phaser.Input.Gamepad.Gamepad#buttons + * @type {Phaser.Input.Gamepad.Button[]} + * @since 3.0.0 + */ + this.buttons = buttons; + + var axes = []; + + for (i = 0; i < pad.axes.length; i++) + { + axes.push(new Axis(this, i)); + } + + /** + * An array of Gamepad Axis objects, corresponding to the different axes available on the Gamepad, if any. + * + * @name Phaser.Input.Gamepad.Gamepad#axes + * @type {Phaser.Input.Gamepad.Axis[]} + * @since 3.0.0 + */ + this.axes = axes; + + /** + * The Gamepad's Haptic Actuator (Vibration / Rumble support). + * This is highly experimental and only set if both present on the device, + * and exposed by both the hardware and browser. + * + * @name Phaser.Input.Gamepad.Gamepad#vibration + * @type {GamepadHapticActuator} + * @since 3.10.0 + */ + this.vibration = pad.vibrationActuator; + + // https://w3c.github.io/gamepad/#remapping + + var _noButton = { value: 0, pressed: false }; + + /** + * A reference to the Left Button in the Left Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_LCLeft + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._LCLeft = (buttons[14]) ? buttons[14] : _noButton; + + /** + * A reference to the Right Button in the Left Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_LCRight + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._LCRight = (buttons[15]) ? buttons[15] : _noButton; + + /** + * A reference to the Top Button in the Left Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_LCTop + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._LCTop = (buttons[12]) ? buttons[12] : _noButton; + + /** + * A reference to the Bottom Button in the Left Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_LCBottom + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._LCBottom = (buttons[13]) ? buttons[13] : _noButton; + + /** + * A reference to the Left Button in the Right Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_RCLeft + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._RCLeft = (buttons[2]) ? buttons[2] : _noButton; + + /** + * A reference to the Right Button in the Right Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_RCRight + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._RCRight = (buttons[1]) ? buttons[1] : _noButton; + + /** + * A reference to the Top Button in the Right Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_RCTop + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._RCTop = (buttons[3]) ? buttons[3] : _noButton; + + /** + * A reference to the Bottom Button in the Right Cluster. + * + * @name Phaser.Input.Gamepad.Gamepad#_RCBottom + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._RCBottom = (buttons[0]) ? buttons[0] : _noButton; + + /** + * A reference to the Top Left Front Button (L1 Shoulder Button) + * + * @name Phaser.Input.Gamepad.Gamepad#_FBLeftTop + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._FBLeftTop = (buttons[4]) ? buttons[4] : _noButton; + + /** + * A reference to the Bottom Left Front Button (L2 Shoulder Button) + * + * @name Phaser.Input.Gamepad.Gamepad#_FBLeftBottom + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._FBLeftBottom = (buttons[6]) ? buttons[6] : _noButton; + + /** + * A reference to the Top Right Front Button (R1 Shoulder Button) + * + * @name Phaser.Input.Gamepad.Gamepad#_FBRightTop + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._FBRightTop = (buttons[5]) ? buttons[5] : _noButton; + + /** + * A reference to the Bottom Right Front Button (R2 Shoulder Button) + * + * @name Phaser.Input.Gamepad.Gamepad#_FBRightBottom + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._FBRightBottom = (buttons[7]) ? buttons[7] : _noButton; + + var _noAxis = { value: 0 }; + + /** + * A reference to the Horizontal Axis for the Left Stick. + * + * @name Phaser.Input.Gamepad.Gamepad#_HAxisLeft + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._HAxisLeft = (axes[0]) ? axes[0] : _noAxis; + + /** + * A reference to the Vertical Axis for the Left Stick. + * + * @name Phaser.Input.Gamepad.Gamepad#_VAxisLeft + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._VAxisLeft = (axes[1]) ? axes[1] : _noAxis; + + /** + * A reference to the Horizontal Axis for the Right Stick. + * + * @name Phaser.Input.Gamepad.Gamepad#_HAxisRight + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._HAxisRight = (axes[2]) ? axes[2] : _noAxis; + + /** + * A reference to the Vertical Axis for the Right Stick. + * + * @name Phaser.Input.Gamepad.Gamepad#_VAxisRight + * @type {Phaser.Input.Gamepad.Button} + * @private + * @since 3.10.0 + */ + this._VAxisRight = (axes[3]) ? axes[3] : _noAxis; + + /** + * A Vector2 containing the most recent values from the Gamepad's left axis stick. + * This is updated automatically as part of the Gamepad.update cycle. + * The H Axis is mapped to the `Vector2.x` property, and the V Axis to the `Vector2.y` property. + * The values are based on the Axis thresholds. + * If the Gamepad does not have a left axis stick, the values will always be zero. + * + * @name Phaser.Input.Gamepad.Gamepad#leftStick + * @type {Phaser.Math.Vector2} + * @since 3.10.0 + */ + this.leftStick = new Vector2(); + + /** + * A Vector2 containing the most recent values from the Gamepad's right axis stick. + * This is updated automatically as part of the Gamepad.update cycle. + * The H Axis is mapped to the `Vector2.x` property, and the V Axis to the `Vector2.y` property. + * The values are based on the Axis thresholds. + * If the Gamepad does not have a right axis stick, the values will always be zero. + * + * @name Phaser.Input.Gamepad.Gamepad#rightStick + * @type {Phaser.Math.Vector2} + * @since 3.10.0 + */ + this.rightStick = new Vector2(); + + /** + * When was this Gamepad created? Used to avoid duplicate event spamming in the update loop. + * + * @name Phaser.Input.Gamepad.Gamepad#_created + * @type {number} + * @private + * @since 3.50.0 + */ + this._created = performance.now(); + }, + + /** + * Gets the total number of axis this Gamepad claims to support. + * + * @method Phaser.Input.Gamepad.Gamepad#getAxisTotal + * @since 3.10.0 + * + * @return {number} The total number of axes this Gamepad claims to support. + */ + getAxisTotal: function () + { + return this.axes.length; + }, + + /** + * Gets the value of an axis based on the given index. + * The index must be valid within the range of axes supported by this Gamepad. + * The return value will be a float between 0 and 1. + * + * @method Phaser.Input.Gamepad.Gamepad#getAxisValue + * @since 3.10.0 + * + * @param {number} index - The index of the axes to get the value for. + * + * @return {number} The value of the axis, between 0 and 1. + */ + getAxisValue: function (index) + { + return this.axes[index].getValue(); + }, + + /** + * Sets the threshold value of all axis on this Gamepad. + * The value is a float between 0 and 1 and is the amount below which the axis is considered as not having been moved. + * + * @method Phaser.Input.Gamepad.Gamepad#setAxisThreshold + * @since 3.10.0 + * + * @param {number} value - A value between 0 and 1. + */ + setAxisThreshold: function (value) + { + for (var i = 0; i < this.axes.length; i++) + { + this.axes[i].threshold = value; + } + }, + + /** + * Gets the total number of buttons this Gamepad claims to have. + * + * @method Phaser.Input.Gamepad.Gamepad#getButtonTotal + * @since 3.10.0 + * + * @return {number} The total number of buttons this Gamepad claims to have. + */ + getButtonTotal: function () + { + return this.buttons.length; + }, + + /** + * Gets the value of a button based on the given index. + * The index must be valid within the range of buttons supported by this Gamepad. + * + * The return value will be either 0 or 1 for an analogue button, or a float between 0 and 1 + * for a pressure-sensitive digital button, such as the shoulder buttons on a Dual Shock. + * + * @method Phaser.Input.Gamepad.Gamepad#getButtonValue + * @since 3.10.0 + * + * @param {number} index - The index of the button to get the value for. + * + * @return {number} The value of the button, between 0 and 1. + */ + getButtonValue: function (index) + { + return this.buttons[index].value; + }, + + /** + * Returns if the button is pressed down or not. + * The index must be valid within the range of buttons supported by this Gamepad. + * + * @method Phaser.Input.Gamepad.Gamepad#isButtonDown + * @since 3.10.0 + * + * @param {number} index - The index of the button to get the value for. + * + * @return {boolean} `true` if the button is considered as being pressed down, otherwise `false`. + */ + isButtonDown: function (index) + { + return this.buttons[index].pressed; + }, + + /** + * Internal update handler for this Gamepad. + * Called automatically by the Gamepad Manager as part of its update. + * + * @method Phaser.Input.Gamepad.Gamepad#update + * @private + * @since 3.0.0 + */ + update: function (pad) + { + if (pad.timestamp < this._created) + { + return; + } + + var i; + + // Sync the button values + + var localButtons = this.buttons; + var gamepadButtons = pad.buttons; + + var len = localButtons.length; + + for (i = 0; i < len; i++) + { + localButtons[i].update(gamepadButtons[i].value); + } + + // Sync the axis values + + var localAxes = this.axes; + var gamepadAxes = pad.axes; + + len = localAxes.length; + + for (i = 0; i < len; i++) + { + localAxes[i].update(gamepadAxes[i]); + } + + if (len >= 2) + { + this.leftStick.set(localAxes[0].getValue(), localAxes[1].getValue()); + + if (len >= 4) + { + this.rightStick.set(localAxes[2].getValue(), localAxes[3].getValue()); + } + } + }, + + /** + * Destroys this Gamepad instance, its buttons and axes, and releases external references it holds. + * + * @method Phaser.Input.Gamepad.Gamepad#destroy + * @since 3.10.0 + */ + destroy: function () + { + this.removeAllListeners(); + + this.manager = null; + this.pad = null; + + var i; + + for (i = 0; i < this.buttons.length; i++) + { + this.buttons[i].destroy(); + } + + for (i = 0; i < this.axes.length; i++) + { + this.axes[i].destroy(); + } + + this.buttons = []; + this.axes = []; + }, + + /** + * Is this Gamepad currently connected or not? + * + * @name Phaser.Input.Gamepad.Gamepad#connected + * @type {boolean} + * @default true + * @since 3.0.0 + */ + connected: { + + get: function () + { + return this.pad.connected; + } + + }, + + /** + * A timestamp containing the most recent time this Gamepad was updated. + * + * @name Phaser.Input.Gamepad.Gamepad#timestamp + * @type {number} + * @since 3.0.0 + */ + timestamp: { + + get: function () + { + return this.pad.timestamp; + } + + }, + + /** + * Is the Gamepad's Left button being pressed? + * If the Gamepad doesn't have this button it will always return false. + * This is the d-pad left button under standard Gamepad mapping. + * + * @name Phaser.Input.Gamepad.Gamepad#left + * @type {boolean} + * @since 3.10.0 + */ + left: { + + get: function () + { + return this._LCLeft.pressed; + } + + }, + + /** + * Is the Gamepad's Right button being pressed? + * If the Gamepad doesn't have this button it will always return false. + * This is the d-pad right button under standard Gamepad mapping. + * + * @name Phaser.Input.Gamepad.Gamepad#right + * @type {boolean} + * @since 3.10.0 + */ + right: { + + get: function () + { + return this._LCRight.pressed; + } + + }, + + /** + * Is the Gamepad's Up button being pressed? + * If the Gamepad doesn't have this button it will always return false. + * This is the d-pad up button under standard Gamepad mapping. + * + * @name Phaser.Input.Gamepad.Gamepad#up + * @type {boolean} + * @since 3.10.0 + */ + up: { + + get: function () + { + return this._LCTop.pressed; + } + + }, + + /** + * Is the Gamepad's Down button being pressed? + * If the Gamepad doesn't have this button it will always return false. + * This is the d-pad down button under standard Gamepad mapping. + * + * @name Phaser.Input.Gamepad.Gamepad#down + * @type {boolean} + * @since 3.10.0 + */ + down: { + + get: function () + { + return this._LCBottom.pressed; + } + + }, + + /** + * Is the Gamepad's bottom button in the right button cluster being pressed? + * If the Gamepad doesn't have this button it will always return false. + * On a Dual Shock controller it's the X button. + * On an XBox controller it's the A button. + * + * @name Phaser.Input.Gamepad.Gamepad#A + * @type {boolean} + * @since 3.10.0 + */ + A: { + + get: function () + { + return this._RCBottom.pressed; + } + + }, + + /** + * Is the Gamepad's top button in the right button cluster being pressed? + * If the Gamepad doesn't have this button it will always return false. + * On a Dual Shock controller it's the Triangle button. + * On an XBox controller it's the Y button. + * + * @name Phaser.Input.Gamepad.Gamepad#Y + * @type {boolean} + * @since 3.10.0 + */ + Y: { + + get: function () + { + return this._RCTop.pressed; + } + + }, + + /** + * Is the Gamepad's left button in the right button cluster being pressed? + * If the Gamepad doesn't have this button it will always return false. + * On a Dual Shock controller it's the Square button. + * On an XBox controller it's the X button. + * + * @name Phaser.Input.Gamepad.Gamepad#X + * @type {boolean} + * @since 3.10.0 + */ + X: { + + get: function () + { + return this._RCLeft.pressed; + } + + }, + + /** + * Is the Gamepad's right button in the right button cluster being pressed? + * If the Gamepad doesn't have this button it will always return false. + * On a Dual Shock controller it's the Circle button. + * On an XBox controller it's the B button. + * + * @name Phaser.Input.Gamepad.Gamepad#B + * @type {boolean} + * @since 3.10.0 + */ + B: { + + get: function () + { + return this._RCRight.pressed; + } + + }, + + /** + * Returns the value of the Gamepad's top left shoulder button. + * If the Gamepad doesn't have this button it will always return zero. + * The value is a float between 0 and 1, corresponding to how depressed the button is. + * On a Dual Shock controller it's the L1 button. + * On an XBox controller it's the LB button. + * + * @name Phaser.Input.Gamepad.Gamepad#L1 + * @type {number} + * @since 3.10.0 + */ + L1: { + + get: function () + { + return this._FBLeftTop.value; + } + + }, + + /** + * Returns the value of the Gamepad's bottom left shoulder button. + * If the Gamepad doesn't have this button it will always return zero. + * The value is a float between 0 and 1, corresponding to how depressed the button is. + * On a Dual Shock controller it's the L2 button. + * On an XBox controller it's the LT button. + * + * @name Phaser.Input.Gamepad.Gamepad#L2 + * @type {number} + * @since 3.10.0 + */ + L2: { + + get: function () + { + return this._FBLeftBottom.value; + } + + }, + + /** + * Returns the value of the Gamepad's top right shoulder button. + * If the Gamepad doesn't have this button it will always return zero. + * The value is a float between 0 and 1, corresponding to how depressed the button is. + * On a Dual Shock controller it's the R1 button. + * On an XBox controller it's the RB button. + * + * @name Phaser.Input.Gamepad.Gamepad#R1 + * @type {number} + * @since 3.10.0 + */ + R1: { + + get: function () + { + return this._FBRightTop.value; + } + + }, + + /** + * Returns the value of the Gamepad's bottom right shoulder button. + * If the Gamepad doesn't have this button it will always return zero. + * The value is a float between 0 and 1, corresponding to how depressed the button is. + * On a Dual Shock controller it's the R2 button. + * On an XBox controller it's the RT button. + * + * @name Phaser.Input.Gamepad.Gamepad#R2 + * @type {number} + * @since 3.10.0 + */ + R2: { + + get: function () + { + return this._FBRightBottom.value; + } + + } + +}); + +module.exports = Gamepad; + + +/***/ }), + +/***/ 56654: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(92734); +var Gamepad = __webpack_require__(99125); +var GetValue = __webpack_require__(35154); +var InputPluginCache = __webpack_require__(89639); +var InputEvents = __webpack_require__(8214); + +/** + * @classdesc + * The Gamepad Plugin is an input plugin that belongs to the Scene-owned Input system. + * + * Its role is to listen for native DOM Gamepad Events and then process them. + * + * You do not need to create this class directly, the Input system will create an instance of it automatically. + * + * You can access it from within a Scene using `this.input.gamepad`. + * + * To listen for a gamepad being connected: + * + * ```javascript + * this.input.gamepad.once('connected', function (pad) { + * // 'pad' is a reference to the gamepad that was just connected + * }); + * ``` + * + * Note that the browser may require you to press a button on a gamepad before it will allow you to access it, + * this is for security reasons. However, it may also trust the page already, in which case you won't get the + * 'connected' event and instead should check `GamepadPlugin.total` to see if it thinks there are any gamepads + * already connected. + * + * Once you have received the connected event, or polled the gamepads and found them enabled, you can access + * them via the built-in properties `GamepadPlugin.pad1` to `pad4`, for up to 4 game pads. With a reference + * to the gamepads you can poll its buttons and axis sticks. See the properties and methods available on + * the `Gamepad` class for more details. + * + * As of September 2020 Chrome, and likely other browsers, will soon start to require that games requesting + * access to the Gamepad API are running under SSL. They will actively block API access if they are not. + * + * For more information about Gamepad support in browsers see the following resources: + * + * https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API + * https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API/Using_the_Gamepad_API + * https://www.smashingmagazine.com/2015/11/gamepad-api-in-web-games/ + * http://html5gamepad.com/ + * + * @class GamepadPlugin + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Input.Gamepad + * @constructor + * @since 3.10.0 + * + * @param {Phaser.Input.InputPlugin} sceneInputPlugin - A reference to the Scene Input Plugin that the KeyboardPlugin belongs to. + */ +var GamepadPlugin = new Class({ + + Extends: EventEmitter, + + initialize: + + function GamepadPlugin (sceneInputPlugin) + { + EventEmitter.call(this); + + /** + * A reference to the Scene that this Input Plugin is responsible for. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#scene + * @type {Phaser.Scene} + * @since 3.10.0 + */ + this.scene = sceneInputPlugin.scene; + + /** + * A reference to the Scene Systems Settings. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#settings + * @type {Phaser.Types.Scenes.SettingsObject} + * @since 3.10.0 + */ + this.settings = this.scene.sys.settings; + + /** + * A reference to the Scene Input Plugin that created this Keyboard Plugin. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#sceneInputPlugin + * @type {Phaser.Input.InputPlugin} + * @since 3.10.0 + */ + this.sceneInputPlugin = sceneInputPlugin; + + /** + * A boolean that controls if the Gamepad Manager is enabled or not. + * Can be toggled on the fly. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#enabled + * @type {boolean} + * @default true + * @since 3.10.0 + */ + this.enabled = true; + + /** + * The Gamepad Event target, as defined in the Game Config. + * Typically the browser window, but can be any interactive DOM element. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#target + * @type {any} + * @since 3.10.0 + */ + this.target; + + /** + * An array of the connected Gamepads. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#gamepads + * @type {Phaser.Input.Gamepad.Gamepad[]} + * @default [] + * @since 3.10.0 + */ + this.gamepads = []; + + /** + * An internal event queue. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#queue + * @type {GamepadEvent[]} + * @private + * @since 3.10.0 + */ + this.queue = []; + + /** + * Internal event handler. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#onGamepadHandler + * @type {function} + * @private + * @since 3.10.0 + */ + this.onGamepadHandler; + + /** + * Internal Gamepad reference. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#_pad1 + * @type {Phaser.Input.Gamepad.Gamepad} + * @private + * @since 3.10.0 + */ + this._pad1; + + /** + * Internal Gamepad reference. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#_pad2 + * @type {Phaser.Input.Gamepad.Gamepad} + * @private + * @since 3.10.0 + */ + this._pad2; + + /** + * Internal Gamepad reference. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#_pad3 + * @type {Phaser.Input.Gamepad.Gamepad} + * @private + * @since 3.10.0 + */ + this._pad3; + + /** + * Internal Gamepad reference. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#_pad4 + * @type {Phaser.Input.Gamepad.Gamepad} + * @private + * @since 3.10.0 + */ + this._pad4; + + sceneInputPlugin.pluginEvents.once(InputEvents.BOOT, this.boot, this); + sceneInputPlugin.pluginEvents.on(InputEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#boot + * @private + * @since 3.10.0 + */ + boot: function () + { + var game = this.scene.sys.game; + var settings = this.settings.input; + var config = game.config; + + this.enabled = GetValue(settings, 'gamepad', config.inputGamepad) && game.device.input.gamepads; + this.target = GetValue(settings, 'gamepad.target', config.inputGamepadEventTarget); + + this.sceneInputPlugin.pluginEvents.once(InputEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#start + * @private + * @since 3.10.0 + */ + start: function () + { + if (this.enabled) + { + this.startListeners(); + + this.refreshPads(); + } + + this.sceneInputPlugin.pluginEvents.once(InputEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Checks to see if both this plugin and the Scene to which it belongs is active. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#isActive + * @since 3.10.0 + * + * @return {boolean} `true` if the plugin and the Scene it belongs to is active. + */ + isActive: function () + { + return (this.enabled && this.scene.sys.isActive()); + }, + + /** + * Starts the Gamepad Event listeners running. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#startListeners + * @private + * @since 3.10.0 + */ + startListeners: function () + { + var _this = this; + var target = this.target; + + var handler = function (event) + { + if (event.defaultPrevented || !_this.isActive()) + { + // Do nothing if event already handled + return; + } + + _this.refreshPads(); + + _this.queue.push(event); + }; + + this.onGamepadHandler = handler; + + target.addEventListener('gamepadconnected', handler, false); + target.addEventListener('gamepaddisconnected', handler, false); + + // FF also supports gamepadbuttondown, gamepadbuttonup and gamepadaxismove but + // nothing else does, and we can get those values via the gamepads anyway, so we will + // until more browsers support this + + // Finally, listen for an update event from the Input Plugin + this.sceneInputPlugin.pluginEvents.on(InputEvents.UPDATE, this.update, this); + }, + + /** + * Stops the Gamepad Event listeners. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#stopListeners + * @private + * @since 3.10.0 + */ + stopListeners: function () + { + this.target.removeEventListener('gamepadconnected', this.onGamepadHandler); + this.target.removeEventListener('gamepaddisconnected', this.onGamepadHandler); + + this.sceneInputPlugin.pluginEvents.off(InputEvents.UPDATE, this.update); + + for (var i = 0; i < this.gamepads.length; i++) + { + this.gamepads[i].removeAllListeners(); + } + }, + + /** + * Disconnects all current Gamepads. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#disconnectAll + * @since 3.10.0 + */ + disconnectAll: function () + { + for (var i = 0; i < this.gamepads.length; i++) + { + this.gamepads[i].pad.connected = false; + } + }, + + /** + * Refreshes the list of connected Gamepads. + * + * This is called automatically when a gamepad is connected or disconnected, + * and during the update loop. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#refreshPads + * @private + * @since 3.10.0 + */ + refreshPads: function () + { + var connectedPads = navigator.getGamepads(); + + if (!connectedPads) + { + this.disconnectAll(); + } + else + { + var currentPads = this.gamepads; + + for (var i = 0; i < connectedPads.length; i++) + { + var livePad = connectedPads[i]; + + // Because sometimes they're null (yes, really) + if (!livePad) + { + continue; + } + + var id = livePad.id; + var index = livePad.index; + var currentPad = currentPads[index]; + + if (!currentPad) + { + // A new Gamepad, not currently stored locally + var newPad = new Gamepad(this, livePad); + + currentPads[index] = newPad; + + if (!this._pad1) + { + this._pad1 = newPad; + } + else if (!this._pad2) + { + this._pad2 = newPad; + } + else if (!this._pad3) + { + this._pad3 = newPad; + } + else if (!this._pad4) + { + this._pad4 = newPad; + } + } + else if (currentPad.id !== id) + { + // A new Gamepad with a different vendor string, but it has got the same index as an old one + currentPad.destroy(); + + currentPads[index] = new Gamepad(this, livePad); + } + else + { + // If neither of these, it's a pad we've already got, so update it + currentPad.update(livePad); + } + } + } + }, + + /** + * Returns an array of all currently connected Gamepads. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#getAll + * @since 3.10.0 + * + * @return {Phaser.Input.Gamepad.Gamepad[]} An array of all currently connected Gamepads. + */ + getAll: function () + { + var out = []; + var pads = this.gamepads; + + for (var i = 0; i < pads.length; i++) + { + if (pads[i]) + { + out.push(pads[i]); + } + } + + return out; + }, + + /** + * Looks-up a single Gamepad based on the given index value. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#getPad + * @since 3.10.0 + * + * @param {number} index - The index of the Gamepad to get. + * + * @return {Phaser.Input.Gamepad.Gamepad} The Gamepad matching the given index, or undefined if none were found. + */ + getPad: function (index) + { + var pads = this.gamepads; + + for (var i = 0; i < pads.length; i++) + { + if (pads[i] && pads[i].index === index) + { + return pads[i]; + } + } + }, + + /** + * The internal update loop. Refreshes all connected gamepads and processes their events. + * + * Called automatically by the Input Manager, invoked from the Game step. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#update + * @private + * @fires Phaser.Input.Gamepad.Events#CONNECTED + * @fires Phaser.Input.Gamepad.Events#DISCONNECTED + * @since 3.10.0 + */ + update: function () + { + if (!this.enabled) + { + return; + } + + this.refreshPads(); + + var len = this.queue.length; + + if (len === 0) + { + return; + } + + var queue = this.queue.splice(0, len); + + // Process the event queue, dispatching all of the events that have stored up + for (var i = 0; i < len; i++) + { + var event = queue[i]; + var pad = this.getPad(event.gamepad.index); + + if (event.type === 'gamepadconnected') + { + this.emit(Events.CONNECTED, pad, event); + } + else if (event.type === 'gamepaddisconnected') + { + this.emit(Events.DISCONNECTED, pad, event); + } + } + }, + + /** + * Shuts the Gamepad Plugin down. + * All this does is remove any listeners bound to it. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#shutdown + * @private + * @since 3.10.0 + */ + shutdown: function () + { + this.stopListeners(); + + this.removeAllListeners(); + }, + + /** + * Destroys this Gamepad Plugin, disconnecting all Gamepads and releasing internal references. + * + * @method Phaser.Input.Gamepad.GamepadPlugin#destroy + * @private + * @since 3.10.0 + */ + destroy: function () + { + this.shutdown(); + + for (var i = 0; i < this.gamepads.length; i++) + { + if (this.gamepads[i]) + { + this.gamepads[i].destroy(); + } + } + + this.gamepads = []; + + this.scene = null; + this.settings = null; + this.sceneInputPlugin = null; + this.target = null; + }, + + /** + * The total number of connected game pads. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#total + * @type {number} + * @since 3.10.0 + */ + total: { + + get: function () + { + return this.gamepads.length; + } + + }, + + /** + * A reference to the first connected Gamepad. + * + * This will be undefined if either no pads are connected, or the browser + * has not yet issued a gamepadconnect, which can happen even if a Gamepad + * is plugged in, but hasn't yet had any buttons pressed on it. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#pad1 + * @type {Phaser.Input.Gamepad.Gamepad} + * @since 3.10.0 + */ + pad1: { + + get: function () + { + return this._pad1; + } + + }, + + /** + * A reference to the second connected Gamepad. + * + * This will be undefined if either no pads are connected, or the browser + * has not yet issued a gamepadconnect, which can happen even if a Gamepad + * is plugged in, but hasn't yet had any buttons pressed on it. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#pad2 + * @type {Phaser.Input.Gamepad.Gamepad} + * @since 3.10.0 + */ + pad2: { + + get: function () + { + return this._pad2; + } + + }, + + /** + * A reference to the third connected Gamepad. + * + * This will be undefined if either no pads are connected, or the browser + * has not yet issued a gamepadconnect, which can happen even if a Gamepad + * is plugged in, but hasn't yet had any buttons pressed on it. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#pad3 + * @type {Phaser.Input.Gamepad.Gamepad} + * @since 3.10.0 + */ + pad3: { + + get: function () + { + return this._pad3; + } + + }, + + /** + * A reference to the fourth connected Gamepad. + * + * This will be undefined if either no pads are connected, or the browser + * has not yet issued a gamepadconnect, which can happen even if a Gamepad + * is plugged in, but hasn't yet had any buttons pressed on it. + * + * @name Phaser.Input.Gamepad.GamepadPlugin#pad4 + * @type {Phaser.Input.Gamepad.Gamepad} + * @since 3.10.0 + */ + pad4: { + + get: function () + { + return this._pad4; + } + + } + +}); + +/** + * An instance of the Gamepad Plugin class, if enabled via the `input.gamepad` Scene or Game Config property. + * Use this to create access Gamepads connected to the browser and respond to gamepad buttons. + * + * @name Phaser.Input.InputPlugin#gamepad + * @type {?Phaser.Input.Gamepad.GamepadPlugin} + * @since 3.10.0 + */ +InputPluginCache.register('GamepadPlugin', GamepadPlugin, 'gamepad', 'gamepad', 'inputGamepad'); + +module.exports = GamepadPlugin; + + +/***/ }), + +/***/ 89651: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Tatar SNES USB Controller Gamepad Configuration. + * USB Gamepad (STANDARD GAMEPAD Vendor: 0079 Product: 0011) + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB + * @namespace + * @since 3.0.0 + */ +module.exports = { + + /** + * D-Pad up + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.UP + * @const + * @type {number} + * @since 3.0.0 + */ + UP: 12, + + /** + * D-Pad down + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.DOWN + * @const + * @type {number} + * @since 3.0.0 + */ + DOWN: 13, + + /** + * D-Pad left + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.LEFT + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT: 14, + + /** + * D-Pad right + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.RIGHT + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT: 15, + + /** + * Select button + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.SELECT + * @const + * @type {number} + * @since 3.0.0 + */ + SELECT: 8, + + /** + * Start button + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.START + * @const + * @type {number} + * @since 3.0.0 + */ + START: 9, + + /** + * B Button (Bottom) + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.B + * @const + * @type {number} + * @since 3.0.0 + */ + B: 0, + + /** + * A Button (Right) + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.A + * @const + * @type {number} + * @since 3.0.0 + */ + A: 1, + + /** + * Y Button (Left) + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.Y + * @const + * @type {number} + * @since 3.0.0 + */ + Y: 2, + + /** + * X Button (Top) + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.X + * @const + * @type {number} + * @since 3.0.0 + */ + X: 3, + + /** + * Left bumper + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.LEFT_SHOULDER + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT_SHOULDER: 4, + + /** + * Right bumper + * + * @name Phaser.Input.Gamepad.Configs.SNES_USB.RIGHT_SHOULDER + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT_SHOULDER: 5 + +}; + + +/***/ }), + +/***/ 65294: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * PlayStation DualShock 4 Gamepad Configuration. + * Sony PlayStation DualShock 4 (v2) wireless controller + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4 + * @namespace + * @since 3.0.0 + */ +module.exports = { + + /** + * D-Pad up + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.UP + * @const + * @type {number} + * @since 3.0.0 + */ + UP: 12, + + /** + * D-Pad down + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.DOWN + * @const + * @type {number} + * @since 3.0.0 + */ + DOWN: 13, + + /** + * D-Pad left + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.LEFT + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT: 14, + + /** + * D-Pad up + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.RIGHT + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT: 15, + + /** + * Share button + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.SHARE + * @const + * @type {number} + * @since 3.0.0 + */ + SHARE: 8, + + /** + * Options button + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.OPTIONS + * @const + * @type {number} + * @since 3.0.0 + */ + OPTIONS: 9, + + /** + * PlayStation logo button + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.PS + * @const + * @type {number} + * @since 3.0.0 + */ + PS: 16, + + /** + * Touchpad click + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.TOUCHBAR + * @const + * @type {number} + * @since 3.0.0 + */ + TOUCHBAR: 17, + + /** + * Cross button (Bottom) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.X + * @const + * @type {number} + * @since 3.0.0 + */ + X: 0, + + /** + * Circle button (Right) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.CIRCLE + * @const + * @type {number} + * @since 3.0.0 + */ + CIRCLE: 1, + + /** + * Square button (Left) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.SQUARE + * @const + * @type {number} + * @since 3.0.0 + */ + SQUARE: 2, + + /** + * Triangle button (Top) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.TRIANGLE + * @const + * @type {number} + * @since 3.0.0 + */ + TRIANGLE: 3, + + /** + * Left bumper (L1) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.L1 + * @const + * @type {number} + * @since 3.0.0 + */ + L1: 4, + + /** + * Right bumper (R1) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.R1 + * @const + * @type {number} + * @since 3.0.0 + */ + R1: 5, + + /** + * Left trigger (L2) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.L2 + * @const + * @type {number} + * @since 3.0.0 + */ + L2: 6, + + /** + * Right trigger (R2) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.R2 + * @const + * @type {number} + * @since 3.0.0 + */ + R2: 7, + + /** + * Left stick click (L3) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.L3 + * @const + * @type {number} + * @since 3.0.0 + */ + L3: 10, + + /** + * Right stick click (R3) + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.R3 + * @const + * @type {number} + * @since 3.0.0 + */ + R3: 11, + + /** + * Left stick horizontal + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.LEFT_STICK_H + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT_STICK_H: 0, + + /** + * Left stick vertical + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.LEFT_STICK_V + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT_STICK_V: 1, + + /** + * Right stick horizontal + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.RIGHT_STICK_H + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT_STICK_H: 2, + + /** + * Right stick vertical + * + * @name Phaser.Input.Gamepad.Configs.DUALSHOCK_4.RIGHT_STICK_V + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT_STICK_V: 3 + +}; + + +/***/ }), + +/***/ 90089: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * XBox 360 Gamepad Configuration. + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360 + * @namespace + * @since 3.0.0 + */ +module.exports = { + + /** + * D-Pad up + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.UP + * @const + * @type {number} + * @since 3.0.0 + */ + UP: 12, + + /** + * D-Pad down + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.DOWN + * @const + * @type {number} + * @since 3.0.0 + */ + DOWN: 13, + + /** + * D-Pad left + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.LEFT + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT: 14, + + /** + * D-Pad right + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.RIGHT + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT: 15, + + /** + * XBox menu button + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.MENU + * @const + * @type {number} + * @since 3.0.0 + */ + MENU: 16, + + /** + * A button (Bottom) + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.A + * @const + * @type {number} + * @since 3.0.0 + */ + A: 0, + + /** + * B button (Right) + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.B + * @const + * @type {number} + * @since 3.0.0 + */ + B: 1, + + /** + * X button (Left) + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.X + * @const + * @type {number} + * @since 3.0.0 + */ + X: 2, + + /** + * Y button (Top) + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.Y + * @const + * @type {number} + * @since 3.0.0 + */ + Y: 3, + + /** + * Left Bumper + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.LB + * @const + * @type {number} + * @since 3.0.0 + */ + LB: 4, + + /** + * Right Bumper + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.RB + * @const + * @type {number} + * @since 3.0.0 + */ + RB: 5, + + /** + * Left Trigger + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.LT + * @const + * @type {number} + * @since 3.0.0 + */ + LT: 6, + + /** + * Right Trigger + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.RT + * @const + * @type {number} + * @since 3.0.0 + */ + RT: 7, + + /** + * Back / Change View button + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.BACK + * @const + * @type {number} + * @since 3.0.0 + */ + BACK: 8, + + /** + * Start button + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.START + * @const + * @type {number} + * @since 3.0.0 + */ + START: 9, + + /** + * Left Stick press + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.LS + * @const + * @type {number} + * @since 3.0.0 + */ + LS: 10, + + /** + * Right stick press + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.RS + * @const + * @type {number} + * @since 3.0.0 + */ + RS: 11, + + /** + * Left Stick horizontal + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.LEFT_STICK_H + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT_STICK_H: 0, + + /** + * Left Stick vertical + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.LEFT_STICK_V + * @const + * @type {number} + * @since 3.0.0 + */ + LEFT_STICK_V: 1, + + /** + * Right Stick horizontal + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.RIGHT_STICK_H + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT_STICK_H: 2, + + /** + * Right Stick vertical + * + * @name Phaser.Input.Gamepad.Configs.XBOX_360.RIGHT_STICK_V + * @const + * @type {number} + * @since 3.0.0 + */ + RIGHT_STICK_V: 3 + +}; + + +/***/ }), + +/***/ 64894: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Gamepad.Configs + */ + +module.exports = { + + DUALSHOCK_4: __webpack_require__(65294), + SNES_USB: __webpack_require__(89651), + XBOX_360: __webpack_require__(90089) + +}; + + +/***/ }), + +/***/ 46008: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Gamepad Button Down Event. + * + * This event is dispatched by the Gamepad Plugin when a button has been pressed on any active Gamepad. + * + * Listen to this event from within a Scene using: `this.input.gamepad.on('down', listener)`. + * + * You can also listen for a DOWN event from a Gamepad instance. See the [GAMEPAD_BUTTON_DOWN]{@linkcode Phaser.Input.Gamepad.Events#event:GAMEPAD_BUTTON_DOWN} event for details. + * + * @event Phaser.Input.Gamepad.Events#BUTTON_DOWN + * @type {string} + * @since 3.10.0 + * + * @param {Phaser.Input.Gamepad} pad - A reference to the Gamepad on which the button was pressed. + * @param {Phaser.Input.Gamepad.Button} button - A reference to the Button which was pressed. + * @param {number} value - The value of the button at the time it was pressed. Between 0 and 1. Some Gamepads have pressure-sensitive buttons. + */ +module.exports = 'down'; + + +/***/ }), + +/***/ 7629: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Gamepad Button Up Event. + * + * This event is dispatched by the Gamepad Plugin when a button has been released on any active Gamepad. + * + * Listen to this event from within a Scene using: `this.input.gamepad.on('up', listener)`. + * + * You can also listen for an UP event from a Gamepad instance. See the [GAMEPAD_BUTTON_UP]{@linkcode Phaser.Input.Gamepad.Events#event:GAMEPAD_BUTTON_UP} event for details. + * + * @event Phaser.Input.Gamepad.Events#BUTTON_UP + * @type {string} + * @since 3.10.0 + * + * @param {Phaser.Input.Gamepad} pad - A reference to the Gamepad on which the button was released. + * @param {Phaser.Input.Gamepad.Button} button - A reference to the Button which was released. + * @param {number} value - The value of the button at the time it was released. Between 0 and 1. Some Gamepads have pressure-sensitive buttons. + */ +module.exports = 'up'; + + +/***/ }), + +/***/ 42206: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Gamepad Connected Event. + * + * This event is dispatched by the Gamepad Plugin when a Gamepad has been connected. + * + * Listen to this event from within a Scene using: `this.input.gamepad.once('connected', listener)`. + * + * Note that the browser may require you to press a button on a gamepad before it will allow you to access it, + * this is for security reasons. However, it may also trust the page already, in which case you won't get the + * 'connected' event and instead should check `GamepadPlugin.total` to see if it thinks there are any gamepads + * already connected. + * + * @event Phaser.Input.Gamepad.Events#CONNECTED + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Gamepad} pad - A reference to the Gamepad which was connected. + * @param {Event} event - The native DOM Event that triggered the connection. + */ +module.exports = 'connected'; + + +/***/ }), + +/***/ 86544: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Gamepad Disconnected Event. + * + * This event is dispatched by the Gamepad Plugin when a Gamepad has been disconnected. + * + * Listen to this event from within a Scene using: `this.input.gamepad.once('disconnected', listener)`. + * + * @event Phaser.Input.Gamepad.Events#DISCONNECTED + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Gamepad} pad - A reference to the Gamepad which was disconnected. + * @param {Event} event - The native DOM Event that triggered the disconnection. + */ +module.exports = 'disconnected'; + + +/***/ }), + +/***/ 94784: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Gamepad Button Down Event. + * + * This event is dispatched by a Gamepad instance when a button has been pressed on it. + * + * Listen to this event from a Gamepad instance. Once way to get this is from the `pad1`, `pad2`, etc properties on the Gamepad Plugin: + * `this.input.gamepad.pad1.on('down', listener)`. + * + * Note that you will not receive any Gamepad button events until the browser considers the Gamepad as being 'connected'. + * + * You can also listen for a DOWN event from the Gamepad Plugin. See the [BUTTON_DOWN]{@linkcode Phaser.Input.Gamepad.Events#event:BUTTON_DOWN} event for details. + * + * @event Phaser.Input.Gamepad.Events#GAMEPAD_BUTTON_DOWN + * @type {string} + * @since 3.10.0 + * + * @param {number} index - The index of the button that was pressed. + * @param {number} value - The value of the button at the time it was pressed. Between 0 and 1. Some Gamepads have pressure-sensitive buttons. + * @param {Phaser.Input.Gamepad.Button} button - A reference to the Button which was pressed. + */ +module.exports = 'down'; + + +/***/ }), + +/***/ 14325: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Gamepad Button Up Event. + * + * This event is dispatched by a Gamepad instance when a button has been released on it. + * + * Listen to this event from a Gamepad instance. Once way to get this is from the `pad1`, `pad2`, etc properties on the Gamepad Plugin: + * `this.input.gamepad.pad1.on('up', listener)`. + * + * Note that you will not receive any Gamepad button events until the browser considers the Gamepad as being 'connected'. + * + * You can also listen for an UP event from the Gamepad Plugin. See the [BUTTON_UP]{@linkcode Phaser.Input.Gamepad.Events#event:BUTTON_UP} event for details. + * + * @event Phaser.Input.Gamepad.Events#GAMEPAD_BUTTON_UP + * @type {string} + * @since 3.10.0 + * + * @param {number} index - The index of the button that was released. + * @param {number} value - The value of the button at the time it was released. Between 0 and 1. Some Gamepads have pressure-sensitive buttons. + * @param {Phaser.Input.Gamepad.Button} button - A reference to the Button which was released. + */ +module.exports = 'up'; + + +/***/ }), + +/***/ 92734: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Gamepad.Events + */ + +module.exports = { + + BUTTON_DOWN: __webpack_require__(46008), + BUTTON_UP: __webpack_require__(7629), + CONNECTED: __webpack_require__(42206), + DISCONNECTED: __webpack_require__(86544), + GAMEPAD_BUTTON_DOWN: __webpack_require__(94784), + GAMEPAD_BUTTON_UP: __webpack_require__(14325) + +}; + + +/***/ }), + +/***/ 48646: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Gamepad + */ + +module.exports = { + + Axis: __webpack_require__(97421), + Button: __webpack_require__(28884), + Events: __webpack_require__(92734), + Gamepad: __webpack_require__(99125), + GamepadPlugin: __webpack_require__(56654), + + Configs: __webpack_require__(64894) +}; + + +/***/ }), + +/***/ 14350: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(93301); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Input + */ + +var Input = { + + CreatePixelPerfectHandler: __webpack_require__(84409), + CreateInteractiveObject: __webpack_require__(74457), + Events: __webpack_require__(8214), + Gamepad: __webpack_require__(48646), + InputManager: __webpack_require__(7003), + InputPlugin: __webpack_require__(48205), + InputPluginCache: __webpack_require__(89639), + Keyboard: __webpack_require__(51442), + Mouse: __webpack_require__(87078), + Pointer: __webpack_require__(42515), + Touch: __webpack_require__(95618) + +}; + +// Merge in the consts +Input = Extend(false, Input, CONST); + +module.exports = Input; + + +/***/ }), + +/***/ 78970: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayRemove = __webpack_require__(72905); +var Class = __webpack_require__(83419); +var GameEvents = __webpack_require__(8443); +var InputEvents = __webpack_require__(8214); +var KeyCodes = __webpack_require__(46032); +var NOOP = __webpack_require__(29747); + +/** + * @classdesc + * The Keyboard Manager is a helper class that belongs to the global Input Manager. + * + * Its role is to listen for native DOM Keyboard Events and then store them for further processing by the Keyboard Plugin. + * + * You do not need to create this class directly, the Input Manager will create an instance of it automatically if keyboard + * input has been enabled in the Game Config. + * + * @class KeyboardManager + * @memberof Phaser.Input.Keyboard + * @constructor + * @since 3.16.0 + * + * @param {Phaser.Input.InputManager} inputManager - A reference to the Input Manager. + */ +var KeyboardManager = new Class({ + + initialize: + + function KeyboardManager (inputManager) + { + /** + * A reference to the Input Manager. + * + * @name Phaser.Input.Keyboard.KeyboardManager#manager + * @type {Phaser.Input.InputManager} + * @since 3.16.0 + */ + this.manager = inputManager; + + /** + * An internal event queue. + * + * @name Phaser.Input.Keyboard.KeyboardManager#queue + * @type {KeyboardEvent[]} + * @private + * @since 3.16.0 + */ + this.queue = []; + + /** + * A flag that controls if the non-modified keys, matching those stored in the `captures` array, + * have `preventDefault` called on them or not. + * + * A non-modified key is one that doesn't have a modifier key held down with it. The modifier keys are + * shift, control, alt and the meta key (Command on a Mac, the Windows Key on Windows). + * Therefore, if the user presses shift + r, it won't prevent this combination, because of the modifier. + * However, if the user presses just the r key on its own, it will have its event prevented. + * + * If you wish to stop capturing the keys, for example switching out to a DOM based element, then + * you can toggle this property at run-time. + * + * @name Phaser.Input.Keyboard.KeyboardManager#preventDefault + * @type {boolean} + * @since 3.16.0 + */ + this.preventDefault = true; + + /** + * An array of Key Code values that will automatically have `preventDefault` called on them, + * as long as the `KeyboardManager.preventDefault` boolean is set to `true`. + * + * By default the array is empty. + * + * The key must be non-modified when pressed in order to be captured. + * + * A non-modified key is one that doesn't have a modifier key held down with it. The modifier keys are + * shift, control, alt and the meta key (Command on a Mac, the Windows Key on Windows). + * Therefore, if the user presses shift + r, it won't prevent this combination, because of the modifier. + * However, if the user presses just the r key on its own, it will have its event prevented. + * + * If you wish to stop capturing the keys, for example switching out to a DOM based element, then + * you can toggle the `KeyboardManager.preventDefault` boolean at run-time. + * + * If you need more specific control, you can create Key objects and set the flag on each of those instead. + * + * This array can be populated via the Game Config by setting the `input.keyboard.capture` array, or you + * can call the `addCapture` method. See also `removeCapture` and `clearCaptures`. + * + * @name Phaser.Input.Keyboard.KeyboardManager#captures + * @type {number[]} + * @since 3.16.0 + */ + this.captures = []; + + /** + * A boolean that controls if the Keyboard Manager is enabled or not. + * Can be toggled on the fly. + * + * @name Phaser.Input.Keyboard.KeyboardManager#enabled + * @type {boolean} + * @default false + * @since 3.16.0 + */ + this.enabled = false; + + /** + * The Keyboard Event target, as defined in the Game Config. + * Typically the window in which the game is rendering, but can be any interactive DOM element. + * + * @name Phaser.Input.Keyboard.KeyboardManager#target + * @type {any} + * @since 3.16.0 + */ + this.target; + + /** + * The Key Down Event handler. + * This function is sent the native DOM KeyEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Keyboard.KeyboardManager#onKeyDown + * @type {function} + * @since 3.16.00 + */ + this.onKeyDown = NOOP; + + /** + * The Key Up Event handler. + * This function is sent the native DOM KeyEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Keyboard.KeyboardManager#onKeyUp + * @type {function} + * @since 3.16.00 + */ + this.onKeyUp = NOOP; + + inputManager.events.once(InputEvents.MANAGER_BOOT, this.boot, this); + }, + + /** + * The Keyboard Manager boot process. + * + * @method Phaser.Input.Keyboard.KeyboardManager#boot + * @private + * @since 3.16.0 + */ + boot: function () + { + var config = this.manager.config; + + this.enabled = config.inputKeyboard; + this.target = config.inputKeyboardEventTarget; + + this.addCapture(config.inputKeyboardCapture); + + if (!this.target && window) + { + this.target = window; + } + + if (this.enabled && this.target) + { + this.startListeners(); + } + + this.manager.game.events.on(GameEvents.POST_STEP, this.postUpdate, this); + }, + + /** + * Starts the Keyboard Event listeners running. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Keyboard.KeyboardManager#startListeners + * @since 3.16.0 + */ + startListeners: function () + { + var _this = this; + + this.onKeyDown = function (event) + { + if (event.defaultPrevented || !_this.enabled || !_this.manager) + { + // Do nothing if event already handled + return; + } + + _this.queue.push(event); + + _this.manager.events.emit(InputEvents.MANAGER_PROCESS); + + var modified = (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey); + + if (_this.preventDefault && !modified && _this.captures.indexOf(event.keyCode) > -1) + { + event.preventDefault(); + } + }; + + this.onKeyUp = function (event) + { + if (event.defaultPrevented || !_this.enabled || !_this.manager) + { + // Do nothing if event already handled + return; + } + + _this.queue.push(event); + + _this.manager.events.emit(InputEvents.MANAGER_PROCESS); + + var modified = (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey); + + if (_this.preventDefault && !modified && _this.captures.indexOf(event.keyCode) > -1) + { + event.preventDefault(); + } + }; + + var target = this.target; + + if (target) + { + target.addEventListener('keydown', this.onKeyDown, false); + target.addEventListener('keyup', this.onKeyUp, false); + + this.enabled = true; + } + }, + + /** + * Stops the Key Event listeners. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Keyboard.KeyboardManager#stopListeners + * @since 3.16.0 + */ + stopListeners: function () + { + var target = this.target; + + target.removeEventListener('keydown', this.onKeyDown, false); + target.removeEventListener('keyup', this.onKeyUp, false); + + this.enabled = false; + }, + + /** + * Clears the event queue. + * Called automatically by the Input Manager. + * + * @method Phaser.Input.Keyboard.KeyboardManager#postUpdate + * @private + * @since 3.16.0 + */ + postUpdate: function () + { + this.queue = []; + }, + + /** + * By default when a key is pressed Phaser will not stop the event from propagating up to the browser. + * There are some keys this can be annoying for, like the arrow keys or space bar, which make the browser window scroll. + * + * This `addCapture` method enables consuming keyboard event for specific keys so it doesn't bubble up to the the browser + * and cause the default browser behavior. + * + * Please note that keyboard captures are global. This means that if you call this method from within a Scene, to say prevent + * the SPACE BAR from triggering a page scroll, then it will prevent it for any Scene in your game, not just the calling one. + * + * You can pass in a single key code value, or an array of key codes, or a string: + * + * ```javascript + * this.input.keyboard.addCapture(62); + * ``` + * + * An array of key codes: + * + * ```javascript + * this.input.keyboard.addCapture([ 62, 63, 64 ]); + * ``` + * + * Or a string: + * + * ```javascript + * this.input.keyboard.addCapture('W,S,A,D'); + * ``` + * + * To use non-alpha numeric keys, use a string, such as 'UP', 'SPACE' or 'LEFT'. + * + * You can also provide an array mixing both strings and key code integers. + * + * If there are active captures after calling this method, the `preventDefault` property is set to `true`. + * + * @method Phaser.Input.Keyboard.KeyboardManager#addCapture + * @since 3.16.0 + * + * @param {(string|number|number[]|any[])} keycode - The Key Codes to enable capture for, preventing them reaching the browser. + */ + addCapture: function (keycode) + { + if (typeof keycode === 'string') + { + keycode = keycode.split(','); + } + + if (!Array.isArray(keycode)) + { + keycode = [ keycode ]; + } + + var captures = this.captures; + + for (var i = 0; i < keycode.length; i++) + { + var code = keycode[i]; + + if (typeof code === 'string') + { + code = KeyCodes[code.trim().toUpperCase()]; + } + + if (captures.indexOf(code) === -1) + { + captures.push(code); + } + } + + this.preventDefault = captures.length > 0; + }, + + /** + * Removes an existing key capture. + * + * Please note that keyboard captures are global. This means that if you call this method from within a Scene, to remove + * the capture of a key, then it will remove it for any Scene in your game, not just the calling one. + * + * You can pass in a single key code value, or an array of key codes, or a string: + * + * ```javascript + * this.input.keyboard.removeCapture(62); + * ``` + * + * An array of key codes: + * + * ```javascript + * this.input.keyboard.removeCapture([ 62, 63, 64 ]); + * ``` + * + * Or a string: + * + * ```javascript + * this.input.keyboard.removeCapture('W,S,A,D'); + * ``` + * + * To use non-alpha numeric keys, use a string, such as 'UP', 'SPACE' or 'LEFT'. + * + * You can also provide an array mixing both strings and key code integers. + * + * If there are no captures left after calling this method, the `preventDefault` property is set to `false`. + * + * @method Phaser.Input.Keyboard.KeyboardManager#removeCapture + * @since 3.16.0 + * + * @param {(string|number|number[]|any[])} keycode - The Key Codes to disable capture for, allowing them reaching the browser again. + */ + removeCapture: function (keycode) + { + if (typeof keycode === 'string') + { + keycode = keycode.split(','); + } + + if (!Array.isArray(keycode)) + { + keycode = [ keycode ]; + } + + var captures = this.captures; + + for (var i = 0; i < keycode.length; i++) + { + var code = keycode[i]; + + if (typeof code === 'string') + { + code = KeyCodes[code.toUpperCase()]; + } + + ArrayRemove(captures, code); + } + + this.preventDefault = captures.length > 0; + }, + + /** + * Removes all keyboard captures and sets the `preventDefault` property to `false`. + * + * @method Phaser.Input.Keyboard.KeyboardManager#clearCaptures + * @since 3.16.0 + */ + clearCaptures: function () + { + this.captures = []; + + this.preventDefault = false; + }, + + /** + * Destroys this Keyboard Manager instance. + * + * @method Phaser.Input.Keyboard.KeyboardManager#destroy + * @since 3.16.0 + */ + destroy: function () + { + this.stopListeners(); + + this.clearCaptures(); + + this.queue = []; + + this.manager.game.events.off(GameEvents.POST_RENDER, this.postUpdate, this); + + this.target = null; + this.enabled = false; + this.manager = null; + } + +}); + +module.exports = KeyboardManager; + + +/***/ }), + +/***/ 28846: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(95922); +var GameEvents = __webpack_require__(8443); +var GetValue = __webpack_require__(35154); +var InputEvents = __webpack_require__(8214); +var InputPluginCache = __webpack_require__(89639); +var Key = __webpack_require__(30472); +var KeyCodes = __webpack_require__(46032); +var KeyCombo = __webpack_require__(87960); +var KeyMap = __webpack_require__(74600); +var SceneEvents = __webpack_require__(44594); +var SnapFloor = __webpack_require__(56583); + +/** + * @classdesc + * The Keyboard Plugin is an input plugin that belongs to the Scene-owned Input system. + * + * Its role is to listen for native DOM Keyboard Events and then process them. + * + * You do not need to create this class directly, the Input system will create an instance of it automatically. + * + * You can access it from within a Scene using `this.input.keyboard`. For example, you can do: + * + * ```javascript + * this.input.keyboard.on('keydown', callback, context); + * ``` + * + * Or, to listen for a specific key: + * + * ```javascript + * this.input.keyboard.on('keydown-A', callback, context); + * ``` + * + * You can also create Key objects, which you can then poll in your game loop: + * + * ```javascript + * var spaceBar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); + * ``` + * + * If you have multiple parallel Scenes, each trying to get keyboard input, be sure to disable capture on them to stop them from + * stealing input from another Scene in the list. You can do this with `this.input.keyboard.enabled = false` within the + * Scene to stop all input, or `this.input.keyboard.preventDefault = false` to stop a Scene halting input on another Scene. + * + * _Note_: Many keyboards are unable to process certain combinations of keys due to hardware limitations known as ghosting. + * See http://www.html5gamedevs.com/topic/4876-impossible-to-use-more-than-2-keyboard-input-buttons-at-the-same-time/ for more details + * and use the site https://w3c.github.io/uievents/tools/key-event-viewer.html to test your n-key support in browser. + * + * Also please be aware that certain browser extensions can disable or override Phaser keyboard handling. + * For example the Chrome extension vimium is known to disable Phaser from using the D key, while EverNote disables the backtick key. + * And there are others. So, please check your extensions before opening Phaser issues about keys that don't work. + * + * @class KeyboardPlugin + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Input.Keyboard + * @constructor + * @since 3.10.0 + * + * @param {Phaser.Input.InputPlugin} sceneInputPlugin - A reference to the Scene Input Plugin that the KeyboardPlugin belongs to. + */ +var KeyboardPlugin = new Class({ + + Extends: EventEmitter, + + initialize: + + function KeyboardPlugin (sceneInputPlugin) + { + EventEmitter.call(this); + + /** + * A reference to the core game, so we can listen for visibility events. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#game + * @type {Phaser.Game} + * @since 3.16.0 + */ + this.game = sceneInputPlugin.systems.game; + + /** + * A reference to the Scene that this Input Plugin is responsible for. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#scene + * @type {Phaser.Scene} + * @since 3.10.0 + */ + this.scene = sceneInputPlugin.scene; + + /** + * A reference to the Scene Systems Settings. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#settings + * @type {Phaser.Types.Scenes.SettingsObject} + * @since 3.10.0 + */ + this.settings = this.scene.sys.settings; + + /** + * A reference to the Scene Input Plugin that created this Keyboard Plugin. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#sceneInputPlugin + * @type {Phaser.Input.InputPlugin} + * @since 3.10.0 + */ + this.sceneInputPlugin = sceneInputPlugin; + + /** + * A reference to the global Keyboard Manager. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#manager + * @type {Phaser.Input.Keyboard.KeyboardManager} + * @since 3.16.0 + */ + this.manager = sceneInputPlugin.manager.keyboard; + + /** + * A boolean that controls if this Keyboard Plugin is enabled or not. + * Can be toggled on the fly. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#enabled + * @type {boolean} + * @default true + * @since 3.10.0 + */ + this.enabled = true; + + /** + * An array of Key objects to process. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#keys + * @type {Phaser.Input.Keyboard.Key[]} + * @since 3.10.0 + */ + this.keys = []; + + /** + * An array of KeyCombo objects to process. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#combos + * @type {Phaser.Input.Keyboard.KeyCombo[]} + * @since 3.10.0 + */ + this.combos = []; + + /** + * Internal repeat key flag. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#prevCode + * @type {string} + * @private + * @since 3.50.0 + */ + this.prevCode = null; + + /** + * Internal repeat key flag. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#prevTime + * @type {number} + * @private + * @since 3.50.0 + */ + this.prevTime = 0; + + /** + * Internal repeat key flag. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#prevType + * @type {string} + * @private + * @since 3.50.1 + */ + this.prevType = null; + + sceneInputPlugin.pluginEvents.once(InputEvents.BOOT, this.boot, this); + sceneInputPlugin.pluginEvents.on(InputEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#boot + * @private + * @since 3.10.0 + */ + boot: function () + { + var settings = this.settings.input; + + this.enabled = GetValue(settings, 'keyboard', true); + + var captures = GetValue(settings, 'keyboard.capture', null); + + if (captures) + { + this.addCaptures(captures); + } + + this.sceneInputPlugin.pluginEvents.once(InputEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#start + * @private + * @since 3.10.0 + */ + start: function () + { + this.sceneInputPlugin.manager.events.on(InputEvents.MANAGER_PROCESS, this.update, this); + + this.sceneInputPlugin.pluginEvents.once(InputEvents.SHUTDOWN, this.shutdown, this); + + this.game.events.on(GameEvents.BLUR, this.resetKeys, this); + + this.scene.sys.events.on(SceneEvents.PAUSE, this.resetKeys, this); + this.scene.sys.events.on(SceneEvents.SLEEP, this.resetKeys, this); + }, + + /** + * Checks to see if both this plugin and the Scene to which it belongs is active. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#isActive + * @since 3.10.0 + * + * @return {boolean} `true` if the plugin and the Scene it belongs to is active. + */ + isActive: function () + { + return (this.enabled && this.scene.sys.canInput()); + }, + + /** + * By default when a key is pressed Phaser will not stop the event from propagating up to the browser. + * There are some keys this can be annoying for, like the arrow keys or space bar, which make the browser window scroll. + * + * This `addCapture` method enables consuming keyboard events for specific keys, so they don't bubble up the browser + * and cause the default behaviors. + * + * Please note that keyboard captures are global. This means that if you call this method from within a Scene, to say prevent + * the SPACE BAR from triggering a page scroll, then it will prevent it for any Scene in your game, not just the calling one. + * + * You can pass a single key code value: + * + * ```javascript + * this.input.keyboard.addCapture(62); + * ``` + * + * An array of key codes: + * + * ```javascript + * this.input.keyboard.addCapture([ 62, 63, 64 ]); + * ``` + * + * Or, a comma-delimited string: + * + * ```javascript + * this.input.keyboard.addCapture('W,S,A,D'); + * ``` + * + * To use non-alpha numeric keys, use a string, such as 'UP', 'SPACE' or 'LEFT'. + * + * You can also provide an array mixing both strings and key code integers. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#addCapture + * @since 3.16.0 + * + * @param {(string|number|number[]|any[])} keycode - The Key Codes to enable event capture for. + * + * @return {this} This KeyboardPlugin object. + */ + addCapture: function (keycode) + { + this.manager.addCapture(keycode); + + return this; + }, + + /** + * Removes an existing key capture. + * + * Please note that keyboard captures are global. This means that if you call this method from within a Scene, to remove + * the capture of a key, then it will remove it for any Scene in your game, not just the calling one. + * + * You can pass a single key code value: + * + * ```javascript + * this.input.keyboard.removeCapture(62); + * ``` + * + * An array of key codes: + * + * ```javascript + * this.input.keyboard.removeCapture([ 62, 63, 64 ]); + * ``` + * + * Or, a comma-delimited string: + * + * ```javascript + * this.input.keyboard.removeCapture('W,S,A,D'); + * ``` + * + * To use non-alpha numeric keys, use a string, such as 'UP', 'SPACE' or 'LEFT'. + * + * You can also provide an array mixing both strings and key code integers. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#removeCapture + * @since 3.16.0 + * + * @param {(string|number|number[]|any[])} keycode - The Key Codes to disable event capture for. + * + * @return {this} This KeyboardPlugin object. + */ + removeCapture: function (keycode) + { + this.manager.removeCapture(keycode); + + return this; + }, + + /** + * Returns an array that contains all of the keyboard captures currently enabled. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#getCaptures + * @since 3.16.0 + * + * @return {number[]} An array of all the currently capturing key codes. + */ + getCaptures: function () + { + return this.manager.captures; + }, + + /** + * Allows Phaser to prevent any key captures you may have defined from bubbling up the browser. + * You can use this to re-enable event capturing if you had paused it via `disableGlobalCapture`. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#enableGlobalCapture + * @since 3.16.0 + * + * @return {this} This KeyboardPlugin object. + */ + enableGlobalCapture: function () + { + this.manager.preventDefault = true; + + return this; + }, + + /** + * Disables Phaser from preventing any key captures you may have defined, without actually removing them. + * You can use this to temporarily disable event capturing if, for example, you swap to a DOM element. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#disableGlobalCapture + * @since 3.16.0 + * + * @return {this} This KeyboardPlugin object. + */ + disableGlobalCapture: function () + { + this.manager.preventDefault = false; + + return this; + }, + + /** + * Removes all keyboard captures. + * + * Note that this is a global change. It will clear all event captures across your game, not just for this specific Scene. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#clearCaptures + * @since 3.16.0 + * + * @return {this} This KeyboardPlugin object. + */ + clearCaptures: function () + { + this.manager.clearCaptures(); + + return this; + }, + + /** + * Creates and returns an object containing 4 hotkeys for Up, Down, Left and Right, and also Space Bar and shift. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#createCursorKeys + * @since 3.10.0 + * + * @return {Phaser.Types.Input.Keyboard.CursorKeys} An object containing the properties: `up`, `down`, `left`, `right`, `space` and `shift`. + */ + createCursorKeys: function () + { + return this.addKeys({ + up: KeyCodes.UP, + down: KeyCodes.DOWN, + left: KeyCodes.LEFT, + right: KeyCodes.RIGHT, + space: KeyCodes.SPACE, + shift: KeyCodes.SHIFT + }); + }, + + /** + * A practical way to create an object containing user selected hotkeys. + * + * For example: + * + * ```javascript + * this.input.keyboard.addKeys({ 'up': Phaser.Input.Keyboard.KeyCodes.W, 'down': Phaser.Input.Keyboard.KeyCodes.S }); + * ``` + * + * would return an object containing the properties (`up` and `down`) mapped to W and S {@link Phaser.Input.Keyboard.Key} objects. + * + * You can also pass in a comma-separated string: + * + * ```javascript + * this.input.keyboard.addKeys('W,S,A,D'); + * ``` + * + * Which will return an object with the properties W, S, A and D mapped to the relevant Key objects. + * + * To use non-alpha numeric keys, use a string, such as 'UP', 'SPACE' or 'LEFT'. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#addKeys + * @since 3.10.0 + * + * @param {(object|string)} keys - An object containing Key Codes, or a comma-separated string. + * @param {boolean} [enableCapture=true] - Automatically call `preventDefault` on the native DOM browser event for the key codes being added. + * @param {boolean} [emitOnRepeat=false] - Controls if the Key will continuously emit a 'down' event while being held down (true), or emit the event just once (false, the default). + * + * @return {object} An object containing Key objects mapped to the input properties. + */ + addKeys: function (keys, enableCapture, emitOnRepeat) + { + if (enableCapture === undefined) { enableCapture = true; } + if (emitOnRepeat === undefined) { emitOnRepeat = false; } + + var output = {}; + + if (typeof keys === 'string') + { + keys = keys.split(','); + + for (var i = 0; i < keys.length; i++) + { + var currentKey = keys[i].trim(); + + if (currentKey) + { + output[currentKey] = this.addKey(currentKey, enableCapture, emitOnRepeat); + } + } + } + else + { + for (var key in keys) + { + output[key] = this.addKey(keys[key], enableCapture, emitOnRepeat); + } + } + + return output; + }, + + /** + * Adds a Key object to this Keyboard Plugin. + * + * The given argument can be either an existing Key object, a string, such as `A` or `SPACE`, or a key code value. + * + * If a Key object is given, and one already exists matching the same key code, the existing one is replaced with the new one. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#addKey + * @since 3.10.0 + * + * @param {(Phaser.Input.Keyboard.Key|string|number)} key - Either a Key object, a string, such as `A` or `SPACE`, or a key code value. + * @param {boolean} [enableCapture=true] - Automatically call `preventDefault` on the native DOM browser event for the key codes being added. + * @param {boolean} [emitOnRepeat=false] - Controls if the Key will continuously emit a 'down' event while being held down (true), or emit the event just once (false, the default). + * + * @return {Phaser.Input.Keyboard.Key} The newly created Key object, or a reference to it if it already existed in the keys array. + */ + addKey: function (key, enableCapture, emitOnRepeat) + { + if (enableCapture === undefined) { enableCapture = true; } + if (emitOnRepeat === undefined) { emitOnRepeat = false; } + + var keys = this.keys; + + if (key instanceof Key) + { + var idx = keys.indexOf(key); + + if (idx > -1) + { + keys[idx] = key; + } + else + { + keys[key.keyCode] = key; + } + + if (enableCapture) + { + this.addCapture(key.keyCode); + } + + key.setEmitOnRepeat(emitOnRepeat); + + return key; + } + + if (typeof key === 'string') + { + key = KeyCodes[key.toUpperCase()]; + } + + if (!keys[key]) + { + keys[key] = new Key(this, key); + + if (enableCapture) + { + this.addCapture(key); + } + + keys[key].setEmitOnRepeat(emitOnRepeat); + } + + return keys[key]; + }, + + /** + * Removes a Key object from this Keyboard Plugin. + * + * The given argument can be either a Key object, a string, such as `A` or `SPACE`, or a key code value. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#removeKey + * @since 3.10.0 + * + * @param {(Phaser.Input.Keyboard.Key|string|number)} key - Either a Key object, a string, such as `A` or `SPACE`, or a key code value. + * @param {boolean} [destroy=false] - Call `Key.destroy` on the removed Key object? + * @param {boolean} [removeCapture=false] - Remove this Key from being captured? Only applies if set to capture when created. + * + * @return {this} This KeyboardPlugin object. + */ + removeKey: function (key, destroy, removeCapture) + { + if (destroy === undefined) { destroy = false; } + if (removeCapture === undefined) { removeCapture = false; } + + var keys = this.keys; + var ref; + + if (key instanceof Key) + { + var idx = keys.indexOf(key); + + if (idx > -1) + { + ref = this.keys[idx]; + + this.keys[idx] = undefined; + } + } + else if (typeof key === 'string') + { + key = KeyCodes[key.toUpperCase()]; + } + + if (keys[key]) + { + ref = keys[key]; + + keys[key] = undefined; + } + + if (ref) + { + ref.plugin = null; + + if (removeCapture) + { + this.removeCapture(ref.keyCode); + } + + if (destroy) + { + ref.destroy(); + } + } + + return this; + }, + + /** + * Removes all Key objects created by _this_ Keyboard Plugin. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#removeAllKeys + * @since 3.24.0 + * + * @param {boolean} [destroy=false] - Call `Key.destroy` on each removed Key object? + * @param {boolean} [removeCapture=false] - Remove all key captures for Key objects owened by this plugin? + * + * @return {this} This KeyboardPlugin object. + */ + removeAllKeys: function (destroy, removeCapture) + { + if (destroy === undefined) { destroy = false; } + if (removeCapture === undefined) { removeCapture = false; } + + var keys = this.keys; + + for (var i = 0; i < keys.length; i++) + { + var key = keys[i]; + + if (key) + { + keys[i] = undefined; + + if (removeCapture) + { + this.removeCapture(key.keyCode); + } + + if (destroy) + { + key.destroy(); + } + } + } + + return this; + }, + + /** + * Creates a new KeyCombo. + * + * A KeyCombo will listen for a specific string of keys from the Keyboard, and when it receives them + * it will emit a `keycombomatch` event from this Keyboard Plugin. + * + * The keys to be listened for can be defined as: + * + * A string (i.e. 'ATARI') + * An array of either integers (key codes) or strings, or a mixture of both + * An array of objects (such as Key objects) with a public 'keyCode' property + * + * For example, to listen for the Konami code (up, up, down, down, left, right, left, right, b, a, enter) + * you could pass the following array of key codes: + * + * ```javascript + * this.input.keyboard.createCombo([ 38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13 ], { resetOnMatch: true }); + * + * this.input.keyboard.on('keycombomatch', function (event) { + * console.log('Konami Code entered!'); + * }); + * ``` + * + * Or, to listen for the user entering the word PHASER: + * + * ```javascript + * this.input.keyboard.createCombo('PHASER'); + * ``` + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#createCombo + * @since 3.10.0 + * + * @param {(string|number[]|object[])} keys - The keys that comprise this combo. + * @param {Phaser.Types.Input.Keyboard.KeyComboConfig} [config] - A Key Combo configuration object. + * + * @return {Phaser.Input.Keyboard.KeyCombo} The new KeyCombo object. + */ + createCombo: function (keys, config) + { + return new KeyCombo(this, keys, config); + }, + + /** + * Checks if the given Key object is currently being held down. + * + * The difference between this method and checking the `Key.isDown` property directly is that you can provide + * a duration to this method. For example, if you wanted a key press to fire a bullet, but you only wanted + * it to be able to fire every 100ms, then you can call this method with a `duration` of 100 and it + * will only return `true` every 100ms. + * + * If the Keyboard Plugin has been disabled, this method will always return `false`. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#checkDown + * @since 3.11.0 + * + * @param {Phaser.Input.Keyboard.Key} key - A Key object. + * @param {number} [duration=0] - The duration which must have elapsed before this Key is considered as being down. + * + * @return {boolean} `true` if the Key is down within the duration specified, otherwise `false`. + */ + checkDown: function (key, duration) + { + if (duration === undefined) { duration = 0; } + + if (this.enabled && key.isDown) + { + var t = SnapFloor(this.time - key.timeDown, duration); + + if (t > key._tick) + { + key._tick = t; + + return true; + } + } + + return false; + }, + + /** + * Internal update handler called by the Input Plugin, which is in turn invoked by the Game step. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#update + * @private + * @since 3.10.0 + */ + update: function () + { + var queue = this.manager.queue; + var len = queue.length; + + if (!this.isActive() || len === 0) + { + return; + } + + var keys = this.keys; + + // Process the event queue, dispatching all of the events that have stored up + for (var i = 0; i < len; i++) + { + var event = queue[i]; + var code = event.keyCode; + var key = keys[code]; + var repeat = false; + + // Override the default functions (it's too late for the browser to use them anyway, so we may as well) + if (event.cancelled === undefined) + { + // Event allowed to flow across all handlers in this Scene, and any other Scene in the Scene list + event.cancelled = 0; + + // Won't reach any more local (Scene level) handlers + event.stopImmediatePropagation = function () + { + event.cancelled = 1; + }; + + // Won't reach any more handlers in any Scene further down the Scene list + event.stopPropagation = function () + { + event.cancelled = -1; + }; + } + + if (event.cancelled === -1) + { + // This event has been stopped from broadcasting to any other Scene, so abort. + continue; + } + + // Duplicate event bailout + if (code === this.prevCode && event.timeStamp === this.prevTime && event.type === this.prevType) + { + // On some systems, the exact same event will fire multiple times. This prevents it. + continue; + } + + this.prevCode = code; + this.prevTime = event.timeStamp; + this.prevType = event.type; + + if (event.type === 'keydown') + { + // Key specific callback first + if (key) + { + repeat = key.isDown; + + key.onDown(event); + } + + if (!event.cancelled && (!key || !repeat)) + { + if (KeyMap[code]) + { + this.emit(Events.KEY_DOWN + KeyMap[code], event); + } + + if (!event.cancelled) + { + this.emit(Events.ANY_KEY_DOWN, event); + } + } + } + else + { + // Key specific callback first + if (key) + { + key.onUp(event); + } + + if (!event.cancelled) + { + if (KeyMap[code]) + { + this.emit(Events.KEY_UP + KeyMap[code], event); + } + + if (!event.cancelled) + { + this.emit(Events.ANY_KEY_UP, event); + } + } + } + + // Reset the cancel state for other Scenes to use + if (event.cancelled === 1) + { + event.cancelled = 0; + } + } + }, + + /** + * Resets all Key objects created by _this_ Keyboard Plugin back to their default un-pressed states. + * This can only reset keys created via the `addKey`, `addKeys` or `createCursorKeys` methods. + * If you have created a Key object directly you'll need to reset it yourself. + * + * This method is called automatically when the Keyboard Plugin shuts down, but can be + * invoked directly at any time you require. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#resetKeys + * @since 3.15.0 + * + * @return {this} This KeyboardPlugin object. + */ + resetKeys: function () + { + var keys = this.keys; + + for (var i = 0; i < keys.length; i++) + { + // Because it's a sparsely populated array + if (keys[i]) + { + keys[i].reset(); + } + } + + return this; + }, + + /** + * Shuts this Keyboard Plugin down. This performs the following tasks: + * + * 1 - Removes all keys created by this Keyboard plugin. + * 2 - Stops and removes the keyboard event listeners. + * 3 - Clears out any pending requests in the queue, without processing them. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#shutdown + * @private + * @since 3.10.0 + */ + shutdown: function () + { + this.removeAllKeys(true); + this.removeAllListeners(); + + this.sceneInputPlugin.manager.events.off(InputEvents.MANAGER_PROCESS, this.update, this); + + this.game.events.off(GameEvents.BLUR, this.resetKeys); + + this.scene.sys.events.off(SceneEvents.PAUSE, this.resetKeys, this); + this.scene.sys.events.off(SceneEvents.SLEEP, this.resetKeys, this); + + this.queue = []; + }, + + /** + * Destroys this Keyboard Plugin instance and all references it holds, plus clears out local arrays. + * + * @method Phaser.Input.Keyboard.KeyboardPlugin#destroy + * @private + * @since 3.10.0 + */ + destroy: function () + { + this.shutdown(); + + var keys = this.keys; + + for (var i = 0; i < keys.length; i++) + { + // Because it's a sparsely populated array + if (keys[i]) + { + keys[i].destroy(); + } + } + + this.keys = []; + this.combos = []; + this.queue = []; + + this.scene = null; + this.settings = null; + this.sceneInputPlugin = null; + this.manager = null; + }, + + /** + * Internal time value. + * + * @name Phaser.Input.Keyboard.KeyboardPlugin#time + * @type {number} + * @private + * @since 3.11.0 + */ + time: { + + get: function () + { + return this.sceneInputPlugin.manager.time; + } + + } + +}); + +/** + * An instance of the Keyboard Plugin class, if enabled via the `input.keyboard` Scene or Game Config property. + * Use this to create Key objects and listen for keyboard specific events. + * + * @name Phaser.Input.InputPlugin#keyboard + * @type {?Phaser.Input.Keyboard.KeyboardPlugin} + * @since 3.10.0 + */ +InputPluginCache.register('KeyboardPlugin', KeyboardPlugin, 'keyboard', 'keyboard', 'inputKeyboard'); + +module.exports = KeyboardPlugin; + + +/***/ }), + +/***/ 66970: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Used internally by the KeyCombo class. + * Return `true` if it reached the end of the combo, `false` if not. + * + * @function Phaser.Input.Keyboard.AdvanceKeyCombo + * @private + * @since 3.0.0 + * + * @param {KeyboardEvent} event - The native Keyboard Event. + * @param {Phaser.Input.Keyboard.KeyCombo} combo - The KeyCombo object to advance. + * + * @return {boolean} `true` if it reached the end of the combo, `false` if not. + */ +var AdvanceKeyCombo = function (event, combo) +{ + combo.timeLastMatched = event.timeStamp; + combo.index++; + + if (combo.index === combo.size) + { + return true; + } + else + { + combo.current = combo.keyCodes[combo.index]; + return false; + } +}; + +module.exports = AdvanceKeyCombo; + + +/***/ }), + +/***/ 87960: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Events = __webpack_require__(95922); +var GetFastValue = __webpack_require__(95540); +var ProcessKeyCombo = __webpack_require__(68769); +var ResetKeyCombo = __webpack_require__(92803); + +/** + * @classdesc + * A KeyCombo will listen for a specific string of keys from the Keyboard, and when it receives them + * it will emit a `keycombomatch` event from the Keyboard Manager. + * + * The keys to be listened for can be defined as: + * + * A string (i.e. 'ATARI') + * An array of either integers (key codes) or strings, or a mixture of both + * An array of objects (such as Key objects) with a public 'keyCode' property + * + * For example, to listen for the Konami code (up, up, down, down, left, right, left, right, b, a, enter) + * you could pass the following array of key codes: + * + * ```javascript + * this.input.keyboard.createCombo([ 38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13 ], { resetOnMatch: true }); + * + * this.input.keyboard.on('keycombomatch', function (event) { + * console.log('Konami Code entered!'); + * }); + * ``` + * + * Or, to listen for the user entering the word PHASER: + * + * ```javascript + * this.input.keyboard.createCombo('PHASER'); + * ``` + * + * @class KeyCombo + * @memberof Phaser.Input.Keyboard + * @constructor + * @listens Phaser.Input.Keyboard.Events#ANY_KEY_DOWN + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.KeyboardPlugin} keyboardPlugin - A reference to the Keyboard Plugin. + * @param {(string|number[]|object[])} keys - The keys that comprise this combo. + * @param {Phaser.Types.Input.Keyboard.KeyComboConfig} [config] - A Key Combo configuration object. + */ +var KeyCombo = new Class({ + + initialize: + + function KeyCombo (keyboardPlugin, keys, config) + { + if (config === undefined) { config = {}; } + + // Can't have a zero or single length combo (string or array based) + if (keys.length < 2) + { + return false; + } + + /** + * A reference to the Keyboard Manager + * + * @name Phaser.Input.Keyboard.KeyCombo#manager + * @type {Phaser.Input.Keyboard.KeyboardPlugin} + * @since 3.0.0 + */ + this.manager = keyboardPlugin; + + /** + * A flag that controls if this Key Combo is actively processing keys or not. + * + * @name Phaser.Input.Keyboard.KeyCombo#enabled + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.enabled = true; + + /** + * An array of the keycodes that comprise this combo. + * + * @name Phaser.Input.Keyboard.KeyCombo#keyCodes + * @type {array} + * @default [] + * @since 3.0.0 + */ + this.keyCodes = []; + + // if 'keys' is a string we need to get the keycode of each character in it + + for (var i = 0; i < keys.length; i++) + { + var char = keys[i]; + + if (typeof char === 'string') + { + this.keyCodes.push(char.toUpperCase().charCodeAt(0)); + } + else if (typeof char === 'number') + { + this.keyCodes.push(char); + } + else if (char.hasOwnProperty('keyCode')) + { + this.keyCodes.push(char.keyCode); + } + } + + /** + * The current keyCode the combo is waiting for. + * + * @name Phaser.Input.Keyboard.KeyCombo#current + * @type {number} + * @since 3.0.0 + */ + this.current = this.keyCodes[0]; + + /** + * The current index of the key being waited for in the 'keys' string. + * + * @name Phaser.Input.Keyboard.KeyCombo#index + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.index = 0; + + /** + * The length of this combo (in keycodes) + * + * @name Phaser.Input.Keyboard.KeyCombo#size + * @type {number} + * @since 3.0.0 + */ + this.size = this.keyCodes.length; + + /** + * The time the previous key in the combo was matched. + * + * @name Phaser.Input.Keyboard.KeyCombo#timeLastMatched + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.timeLastMatched = 0; + + /** + * Has this Key Combo been matched yet? + * + * @name Phaser.Input.Keyboard.KeyCombo#matched + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.matched = false; + + /** + * The time the entire combo was matched. + * + * @name Phaser.Input.Keyboard.KeyCombo#timeMatched + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.timeMatched = 0; + + /** + * If they press the wrong key do we reset the combo? + * + * @name Phaser.Input.Keyboard.KeyCombo#resetOnWrongKey + * @type {boolean} + * @default 0 + * @since 3.0.0 + */ + this.resetOnWrongKey = GetFastValue(config, 'resetOnWrongKey', true); + + /** + * The max delay in ms between each key press. Above this the combo is reset. 0 means disabled. + * + * @name Phaser.Input.Keyboard.KeyCombo#maxKeyDelay + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.maxKeyDelay = GetFastValue(config, 'maxKeyDelay', 0); + + /** + * If previously matched and they press the first key of the combo again, will it reset? + * + * @name Phaser.Input.Keyboard.KeyCombo#resetOnMatch + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.resetOnMatch = GetFastValue(config, 'resetOnMatch', false); + + /** + * If the combo matches, will it delete itself? + * + * @name Phaser.Input.Keyboard.KeyCombo#deleteOnMatch + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.deleteOnMatch = GetFastValue(config, 'deleteOnMatch', false); + + var _this = this; + + var onKeyDownHandler = function (event) + { + if (_this.matched || !_this.enabled) + { + return; + } + + var matched = ProcessKeyCombo(event, _this); + + if (matched) + { + _this.manager.emit(Events.COMBO_MATCH, _this, event); + + if (_this.resetOnMatch) + { + ResetKeyCombo(_this); + } + else if (_this.deleteOnMatch) + { + _this.destroy(); + } + } + }; + + /** + * The internal Key Down handler. + * + * @name Phaser.Input.Keyboard.KeyCombo#onKeyDown + * @private + * @type {KeyboardKeydownCallback} + * @fires Phaser.Input.Keyboard.Events#COMBO_MATCH + * @since 3.0.0 + */ + this.onKeyDown = onKeyDownHandler; + + this.manager.on(Events.ANY_KEY_DOWN, this.onKeyDown); + }, + + /** + * How far complete is this combo? A value between 0 and 1. + * + * @name Phaser.Input.Keyboard.KeyCombo#progress + * @type {number} + * @readonly + * @since 3.0.0 + */ + progress: { + + get: function () + { + return this.index / this.size; + } + + }, + + /** + * Destroys this Key Combo and all of its references. + * + * @method Phaser.Input.Keyboard.KeyCombo#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.enabled = false; + this.keyCodes = []; + + this.manager.off(Events.ANY_KEY_DOWN, this.onKeyDown); + + this.manager = null; + } + +}); + +module.exports = KeyCombo; + + +/***/ }), + +/***/ 68769: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AdvanceKeyCombo = __webpack_require__(66970); + +/** + * Used internally by the KeyCombo class. + * + * @function Phaser.Input.Keyboard.ProcessKeyCombo + * @private + * @since 3.0.0 + * + * @param {KeyboardEvent} event - The native Keyboard Event. + * @param {Phaser.Input.Keyboard.KeyCombo} combo - The KeyCombo object to be processed. + * + * @return {boolean} `true` if the combo was matched, otherwise `false`. + */ +var ProcessKeyCombo = function (event, combo) +{ + if (combo.matched) + { + return true; + } + + var comboMatched = false; + var keyMatched = false; + + if (event.keyCode === combo.current) + { + // Key was correct + + if (combo.index > 0 && combo.maxKeyDelay > 0) + { + // We have to check to see if the delay between + // the new key and the old one was too long (if enabled) + + var timeLimit = combo.timeLastMatched + combo.maxKeyDelay; + + // Check if they pressed it in time or not + if (event.timeStamp <= timeLimit) + { + keyMatched = true; + comboMatched = AdvanceKeyCombo(event, combo); + } + } + else + { + keyMatched = true; + + // We don't check the time for the first key pressed, so just advance it + comboMatched = AdvanceKeyCombo(event, combo); + } + } + + if (!keyMatched && combo.resetOnWrongKey) + { + // Wrong key was pressed + combo.index = 0; + combo.current = combo.keyCodes[0]; + } + + if (comboMatched) + { + combo.timeLastMatched = event.timeStamp; + combo.matched = true; + combo.timeMatched = event.timeStamp; + } + + return comboMatched; +}; + +module.exports = ProcessKeyCombo; + + +/***/ }), + +/***/ 92803: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Used internally by the KeyCombo class. + * + * @function Phaser.Input.Keyboard.ResetKeyCombo + * @private + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.KeyCombo} combo - The KeyCombo to reset. + * + * @return {Phaser.Input.Keyboard.KeyCombo} The KeyCombo. + */ +var ResetKeyCombo = function (combo) +{ + combo.current = combo.keyCodes[0]; + combo.index = 0; + combo.timeLastMatched = 0; + combo.matched = false; + combo.timeMatched = 0; + + return combo; +}; + +module.exports = ResetKeyCombo; + + +/***/ }), + +/***/ 92612: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Global Key Down Event. + * + * This event is dispatched by the Keyboard Plugin when any key on the keyboard is pressed down. + * + * Listen to this event from within a Scene using: `this.input.keyboard.on('keydown', listener)`. + * + * You can also listen for a specific key being pressed. See [Keyboard.Events.KEY_DOWN]{@linkcode Phaser.Input.Keyboard.Events#event:KEY_DOWN} for details. + * + * Finally, you can create Key objects, which you can also listen for events from. See [Keyboard.Events.DOWN]{@linkcode Phaser.Input.Keyboard.Events#event:DOWN} for details. + * + * _Note_: Many keyboards are unable to process certain combinations of keys due to hardware limitations known as ghosting. + * Read [this article on ghosting]{@link http://www.html5gamedevs.com/topic/4876-impossible-to-use-more-than-2-keyboard-input-buttons-at-the-same-time/} for details. + * + * Also, please be aware that some browser extensions can disable or override Phaser keyboard handling. + * For example, the Chrome extension vimium is known to disable Phaser from using the D key, while EverNote disables the backtick key. + * There are others. So, please check your extensions if you find you have specific keys that don't work. + * + * @event Phaser.Input.Keyboard.Events#ANY_KEY_DOWN + * @type {string} + * @since 3.0.0 + * + * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about the key that was pressed, any modifiers, etc. + */ +module.exports = 'keydown'; + + +/***/ }), + +/***/ 23345: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Global Key Up Event. + * + * This event is dispatched by the Keyboard Plugin when any key on the keyboard is released. + * + * Listen to this event from within a Scene using: `this.input.keyboard.on('keyup', listener)`. + * + * You can also listen for a specific key being released. See [Keyboard.Events.KEY_UP]{@linkcode Phaser.Input.Keyboard.Events#event:KEY_UP} for details. + * + * Finally, you can create Key objects, which you can also listen for events from. See [Keyboard.Events.UP]{@linkcode Phaser.Input.Keyboard.Events#event:UP} for details. + * + * @event Phaser.Input.Keyboard.Events#ANY_KEY_UP + * @type {string} + * @since 3.0.0 + * + * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about the key that was released, any modifiers, etc. + */ +module.exports = 'keyup'; + + +/***/ }), + +/***/ 21957: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Key Combo Match Event. + * + * This event is dispatched by the Keyboard Plugin when a [Key Combo]{@link Phaser.Input.Keyboard.KeyCombo} is matched. + * + * Listen for this event from the Key Plugin after a combo has been created: + * + * ```javascript + * this.input.keyboard.createCombo([ 38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13 ], { resetOnMatch: true }); + * + * this.input.keyboard.on('keycombomatch', function (event) { + * console.log('Konami Code entered!'); + * }); + * ``` + * + * @event Phaser.Input.Keyboard.Events#COMBO_MATCH + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.KeyCombo} keycombo - The Key Combo object that was matched. + * @param {KeyboardEvent} event - The native DOM Keyboard Event of the final key in the combo. You can inspect this to learn more about any modifiers, etc. + */ +module.exports = 'keycombomatch'; + + +/***/ }), + +/***/ 44743: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Key Down Event. + * + * This event is dispatched by a [Key]{@link Phaser.Input.Keyboard.Key} object when it is pressed. + * + * Listen for this event from the Key object instance directly: + * + * ```javascript + * var spaceBar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); + * + * spaceBar.on('down', listener) + * ``` + * + * You can also create a generic 'global' listener. See [Keyboard.Events.ANY_KEY_DOWN]{@linkcode Phaser.Input.Keyboard.Events#event:ANY_KEY_DOWN} for details. + * + * @event Phaser.Input.Keyboard.Events#DOWN + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.Key} key - The Key object that was pressed. + * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about any modifiers, etc. + */ +module.exports = 'down'; + + +/***/ }), + +/***/ 3771: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Key Down Event. + * + * This event is dispatched by the Keyboard Plugin when any key on the keyboard is pressed down. + * + * Unlike the `ANY_KEY_DOWN` event, this one has a special dynamic event name. For example, to listen for the `A` key being pressed + * use the following from within a Scene: `this.input.keyboard.on('keydown-A', listener)`. You can replace the `-A` part of the event + * name with any valid [Key Code string]{@link Phaser.Input.Keyboard.KeyCodes}. For example, this will listen for the space bar: + * `this.input.keyboard.on('keydown-SPACE', listener)`. + * + * You can also create a generic 'global' listener. See [Keyboard.Events.ANY_KEY_DOWN]{@linkcode Phaser.Input.Keyboard.Events#event:ANY_KEY_DOWN} for details. + * + * Finally, you can create Key objects, which you can also listen for events from. See [Keyboard.Events.DOWN]{@linkcode Phaser.Input.Keyboard.Events#event:DOWN} for details. + * + * _Note_: Many keyboards are unable to process certain combinations of keys due to hardware limitations known as ghosting. + * Read [this article on ghosting]{@link http://www.html5gamedevs.com/topic/4876-impossible-to-use-more-than-2-keyboard-input-buttons-at-the-same-time/} for details. + * + * Also, please be aware that some browser extensions can disable or override Phaser keyboard handling. + * For example, the Chrome extension vimium is known to disable Phaser from using the D key, while EverNote disables the backtick key. + * There are others. So, please check your extensions if you find you have specific keys that don't work. + * + * @event Phaser.Input.Keyboard.Events#KEY_DOWN + * @type {string} + * @since 3.0.0 + * + * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about the key that was pressed, any modifiers, etc. + */ +module.exports = 'keydown-'; + + +/***/ }), + +/***/ 46358: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Key Up Event. + * + * This event is dispatched by the Keyboard Plugin when any key on the keyboard is released. + * + * Unlike the `ANY_KEY_UP` event, this one has a special dynamic event name. For example, to listen for the `A` key being released + * use the following from within a Scene: `this.input.keyboard.on('keyup-A', listener)`. You can replace the `-A` part of the event + * name with any valid [Key Code string]{@link Phaser.Input.Keyboard.KeyCodes}. For example, this will listen for the space bar: + * `this.input.keyboard.on('keyup-SPACE', listener)`. + * + * You can also create a generic 'global' listener. See [Keyboard.Events.ANY_KEY_UP]{@linkcode Phaser.Input.Keyboard.Events#event:ANY_KEY_UP} for details. + * + * Finally, you can create Key objects, which you can also listen for events from. See [Keyboard.Events.UP]{@linkcode Phaser.Input.Keyboard.Events#event:UP} for details. + * + * @event Phaser.Input.Keyboard.Events#KEY_UP + * @type {string} + * @since 3.0.0 + * + * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about the key that was released, any modifiers, etc. + */ +module.exports = 'keyup-'; + + +/***/ }), + +/***/ 75674: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Key Up Event. + * + * This event is dispatched by a [Key]{@link Phaser.Input.Keyboard.Key} object when it is released. + * + * Listen for this event from the Key object instance directly: + * + * ```javascript + * var spaceBar = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); + * + * spaceBar.on('up', listener) + * ``` + * + * You can also create a generic 'global' listener. See [Keyboard.Events.ANY_KEY_UP]{@linkcode Phaser.Input.Keyboard.Events#event:ANY_KEY_UP} for details. + * + * @event Phaser.Input.Keyboard.Events#UP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.Key} key - The Key object that was released. + * @param {KeyboardEvent} event - The native DOM Keyboard Event. You can inspect this to learn more about any modifiers, etc. + */ +module.exports = 'up'; + + +/***/ }), + +/***/ 95922: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Keyboard.Events + */ + +module.exports = { + + ANY_KEY_DOWN: __webpack_require__(92612), + ANY_KEY_UP: __webpack_require__(23345), + COMBO_MATCH: __webpack_require__(21957), + DOWN: __webpack_require__(44743), + KEY_DOWN: __webpack_require__(3771), + KEY_UP: __webpack_require__(46358), + UP: __webpack_require__(75674) + +}; + + +/***/ }), + +/***/ 51442: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Keyboard + */ + +module.exports = { + + Events: __webpack_require__(95922), + + KeyboardManager: __webpack_require__(78970), + KeyboardPlugin: __webpack_require__(28846), + + Key: __webpack_require__(30472), + KeyCodes: __webpack_require__(46032), + + KeyCombo: __webpack_require__(87960), + + AdvanceKeyCombo: __webpack_require__(66970), + ProcessKeyCombo: __webpack_require__(68769), + ResetKeyCombo: __webpack_require__(92803), + + JustDown: __webpack_require__(90229), + JustUp: __webpack_require__(38796), + DownDuration: __webpack_require__(37015), + UpDuration: __webpack_require__(41170) + +}; + + +/***/ }), + +/***/ 37015: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns `true` if the Key was pressed down within the `duration` value given, based on the current + * game clock time. Or `false` if it either isn't down, or was pressed down longer ago than the given duration. + * + * @function Phaser.Input.Keyboard.DownDuration + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.Key} key - The Key object to test. + * @param {number} [duration=50] - The duration, in ms, within which the key must have been pressed down. + * + * @return {boolean} `true` if the Key was pressed down within `duration` ms ago, otherwise `false`. + */ +var DownDuration = function (key, duration) +{ + if (duration === undefined) { duration = 50; } + + var current = key.plugin.game.loop.time - key.timeDown; + + return (key.isDown && current < duration); +}; + +module.exports = DownDuration; + + +/***/ }), + +/***/ 90229: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The justDown value allows you to test if this Key has just been pressed down or not. + * + * When you check this value it will return `true` if the Key is down, otherwise `false`. + * + * You can only call justDown once per key press. It will only return `true` once, until the Key is released and pressed down again. + * This allows you to use it in situations where you want to check if this key is down without using an event, such as in a core game loop. + * + * @function Phaser.Input.Keyboard.JustDown + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.Key} key - The Key to check to see if it's just down or not. + * + * @return {boolean} `true` if the Key was just pressed, otherwise `false`. + */ +var JustDown = function (key) +{ + if (key._justDown) + { + key._justDown = false; + + return true; + } + else + { + return false; + } +}; + +module.exports = JustDown; + + +/***/ }), + +/***/ 38796: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The justUp value allows you to test if this Key has just been released or not. + * + * When you check this value it will return `true` if the Key is up, otherwise `false`. + * + * You can only call JustUp once per key release. It will only return `true` once, until the Key is pressed down and released again. + * This allows you to use it in situations where you want to check if this key is up without using an event, such as in a core game loop. + * + * @function Phaser.Input.Keyboard.JustUp + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.Key} key - The Key to check to see if it's just up or not. + * + * @return {boolean} `true` if the Key was just released, otherwise `false`. + */ +var JustUp = function (key) +{ + if (key._justUp) + { + key._justUp = false; + + return true; + } + else + { + return false; + } +}; + +module.exports = JustUp; + + +/***/ }), + +/***/ 30472: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(95922); + +/** + * @classdesc + * A generic Key object which can be passed to the Process functions (and so on) + * keycode must be an integer + * + * @class Key + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Input.Keyboard + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.KeyboardPlugin} plugin - The Keyboard Plugin instance that owns this Key object. + * @param {number} keyCode - The keycode of this key. + */ +var Key = new Class({ + + Extends: EventEmitter, + + initialize: + + function Key (plugin, keyCode) + { + EventEmitter.call(this); + + /** + * The Keyboard Plugin instance that owns this Key object. + * + * @name Phaser.Input.Keyboard.Key#plugin + * @type {Phaser.Input.Keyboard.KeyboardPlugin} + * @since 3.17.0 + */ + this.plugin = plugin; + + /** + * The keycode of this key. + * + * @name Phaser.Input.Keyboard.Key#keyCode + * @type {number} + * @since 3.0.0 + */ + this.keyCode = keyCode; + + /** + * The original DOM event. + * + * @name Phaser.Input.Keyboard.Key#originalEvent + * @type {KeyboardEvent} + * @since 3.0.0 + */ + this.originalEvent = undefined; + + /** + * Can this Key be processed? + * + * @name Phaser.Input.Keyboard.Key#enabled + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.enabled = true; + + /** + * The "down" state of the key. This will remain `true` for as long as the keyboard thinks this key is held down. + * + * @name Phaser.Input.Keyboard.Key#isDown + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isDown = false; + + /** + * The "up" state of the key. This will remain `true` for as long as the keyboard thinks this key is up. + * + * @name Phaser.Input.Keyboard.Key#isUp + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.isUp = true; + + /** + * The down state of the ALT key, if pressed at the same time as this key. + * + * @name Phaser.Input.Keyboard.Key#altKey + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.altKey = false; + + /** + * The down state of the CTRL key, if pressed at the same time as this key. + * + * @name Phaser.Input.Keyboard.Key#ctrlKey + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.ctrlKey = false; + + /** + * The down state of the SHIFT key, if pressed at the same time as this key. + * + * @name Phaser.Input.Keyboard.Key#shiftKey + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.shiftKey = false; + + /** + * The down state of the Meta key, if pressed at the same time as this key. + * On a Mac the Meta Key is the Command key. On Windows keyboards, it's the Windows key. + * + * @name Phaser.Input.Keyboard.Key#metaKey + * @type {boolean} + * @default false + * @since 3.16.0 + */ + this.metaKey = false; + + /** + * The location of the modifier key. 0 for standard (or unknown), 1 for left, 2 for right, 3 for numpad. + * + * @name Phaser.Input.Keyboard.Key#location + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.location = 0; + + /** + * The timestamp when the key was last pressed down. + * + * @name Phaser.Input.Keyboard.Key#timeDown + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.timeDown = 0; + + /** + * The number of milliseconds this key was held down for in the previous down - up sequence. + * This value isn't updated every game step, only when the Key changes state. + * To get the current duration use the `getDuration` method. + * + * @name Phaser.Input.Keyboard.Key#duration + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.duration = 0; + + /** + * The timestamp when the key was last released. + * + * @name Phaser.Input.Keyboard.Key#timeUp + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.timeUp = 0; + + /** + * When a key is held down should it continuously fire the `down` event each time it repeats? + * + * By default it will emit the `down` event just once, but if you wish to receive the event + * for each repeat as well, enable this property. + * + * @name Phaser.Input.Keyboard.Key#emitOnRepeat + * @type {boolean} + * @default false + * @since 3.16.0 + */ + this.emitOnRepeat = false; + + /** + * If a key is held down this holds down the number of times the key has 'repeated'. + * + * @name Phaser.Input.Keyboard.Key#repeats + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.repeats = 0; + + /** + * True if the key has just been pressed (NOTE: requires to be reset, see justDown getter) + * + * @name Phaser.Input.Keyboard.Key#_justDown + * @type {boolean} + * @private + * @default false + * @since 3.0.0 + */ + this._justDown = false; + + /** + * True if the key has just been pressed (NOTE: requires to be reset, see justDown getter) + * + * @name Phaser.Input.Keyboard.Key#_justUp + * @type {boolean} + * @private + * @default false + * @since 3.0.0 + */ + this._justUp = false; + + /** + * Internal tick counter. + * + * @name Phaser.Input.Keyboard.Key#_tick + * @type {number} + * @private + * @since 3.11.0 + */ + this._tick = -1; + }, + + /** + * Controls if this Key will continuously emit a `down` event while being held down (true), + * or emit the event just once, on first press, and then skip future events (false). + * + * @method Phaser.Input.Keyboard.Key#setEmitOnRepeat + * @since 3.16.0 + * + * @param {boolean} value - Emit `down` events on repeated key down actions, or just once? + * + * @return {this} This Key instance. + */ + setEmitOnRepeat: function (value) + { + this.emitOnRepeat = value; + + return this; + }, + + /** + * Processes the Key Down action for this Key. + * Called automatically by the Keyboard Plugin. + * + * @method Phaser.Input.Keyboard.Key#onDown + * @fires Phaser.Input.Keyboard.Events#DOWN + * @since 3.16.0 + * + * @param {KeyboardEvent} event - The native DOM Keyboard event. + */ + onDown: function (event) + { + this.originalEvent = event; + + if (!this.enabled) + { + return; + } + + this.altKey = event.altKey; + this.ctrlKey = event.ctrlKey; + this.shiftKey = event.shiftKey; + this.metaKey = event.metaKey; + this.location = event.location; + + this.repeats++; + + if (!this.isDown) + { + this.isDown = true; + this.isUp = false; + this.timeDown = event.timeStamp; + this.duration = 0; + this._justDown = true; + this._justUp = false; + + this.emit(Events.DOWN, this, event); + } + else if (this.emitOnRepeat) + { + this.emit(Events.DOWN, this, event); + } + }, + + /** + * Processes the Key Up action for this Key. + * Called automatically by the Keyboard Plugin. + * + * @method Phaser.Input.Keyboard.Key#onUp + * @fires Phaser.Input.Keyboard.Events#UP + * @since 3.16.0 + * + * @param {KeyboardEvent} event - The native DOM Keyboard event. + */ + onUp: function (event) + { + this.originalEvent = event; + + if (!this.enabled) + { + return; + } + + this.isDown = false; + this.isUp = true; + this.timeUp = event.timeStamp; + this.duration = this.timeUp - this.timeDown; + this.repeats = 0; + + this._justDown = false; + this._justUp = true; + this._tick = -1; + + this.emit(Events.UP, this, event); + }, + + /** + * Resets this Key object back to its default un-pressed state. + * + * As of version 3.60.0 it no longer resets the `enabled` or `preventDefault` flags. + * + * @method Phaser.Input.Keyboard.Key#reset + * @since 3.6.0 + * + * @return {this} This Key instance. + */ + reset: function () + { + this.isDown = false; + this.isUp = true; + this.altKey = false; + this.ctrlKey = false; + this.shiftKey = false; + this.metaKey = false; + this.timeDown = 0; + this.duration = 0; + this.timeUp = 0; + this.repeats = 0; + this._justDown = false; + this._justUp = false; + this._tick = -1; + + return this; + }, + + /** + * Returns the duration, in ms, that the Key has been held down for. + * + * If the key is not currently down it will return zero. + * + * To get the duration the Key was held down for in the previous up-down cycle, + * use the `Key.duration` property value instead. + * + * @method Phaser.Input.Keyboard.Key#getDuration + * @since 3.17.0 + * + * @return {number} The duration, in ms, that the Key has been held down for if currently down. + */ + getDuration: function () + { + if (this.isDown) + { + return (this.plugin.game.loop.time - this.timeDown); + } + else + { + return 0; + } + }, + + /** + * Removes any bound event handlers and removes local references. + * + * @method Phaser.Input.Keyboard.Key#destroy + * @since 3.16.0 + */ + destroy: function () + { + this.removeAllListeners(); + + this.originalEvent = null; + + this.plugin = null; + } + +}); + +module.exports = Key; + + +/***/ }), + +/***/ 46032: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Keyboard Codes. + * + * @namespace Phaser.Input.Keyboard.KeyCodes + * @memberof Phaser.Input.Keyboard + * @since 3.0.0 + */ + +var KeyCodes = { + + /** + * The BACKSPACE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.BACKSPACE + * @type {number} + * @since 3.0.0 + */ + BACKSPACE: 8, + + /** + * The TAB key. + * + * @name Phaser.Input.Keyboard.KeyCodes.TAB + * @type {number} + * @since 3.0.0 + */ + TAB: 9, + + /** + * The ENTER key. + * + * @name Phaser.Input.Keyboard.KeyCodes.ENTER + * @type {number} + * @since 3.0.0 + */ + ENTER: 13, + + /** + * The SHIFT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.SHIFT + * @type {number} + * @since 3.0.0 + */ + SHIFT: 16, + + /** + * The CTRL key. + * + * @name Phaser.Input.Keyboard.KeyCodes.CTRL + * @type {number} + * @since 3.0.0 + */ + CTRL: 17, + + /** + * The ALT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.ALT + * @type {number} + * @since 3.0.0 + */ + ALT: 18, + + /** + * The PAUSE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.PAUSE + * @type {number} + * @since 3.0.0 + */ + PAUSE: 19, + + /** + * The CAPS_LOCK key. + * + * @name Phaser.Input.Keyboard.KeyCodes.CAPS_LOCK + * @type {number} + * @since 3.0.0 + */ + CAPS_LOCK: 20, + + /** + * The ESC key. + * + * @name Phaser.Input.Keyboard.KeyCodes.ESC + * @type {number} + * @since 3.0.0 + */ + ESC: 27, + + /** + * The SPACE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.SPACE + * @type {number} + * @since 3.0.0 + */ + SPACE: 32, + + /** + * The PAGE_UP key. + * + * @name Phaser.Input.Keyboard.KeyCodes.PAGE_UP + * @type {number} + * @since 3.0.0 + */ + PAGE_UP: 33, + + /** + * The PAGE_DOWN key. + * + * @name Phaser.Input.Keyboard.KeyCodes.PAGE_DOWN + * @type {number} + * @since 3.0.0 + */ + PAGE_DOWN: 34, + + /** + * The END key. + * + * @name Phaser.Input.Keyboard.KeyCodes.END + * @type {number} + * @since 3.0.0 + */ + END: 35, + + /** + * The HOME key. + * + * @name Phaser.Input.Keyboard.KeyCodes.HOME + * @type {number} + * @since 3.0.0 + */ + HOME: 36, + + /** + * The LEFT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.LEFT + * @type {number} + * @since 3.0.0 + */ + LEFT: 37, + + /** + * The UP key. + * + * @name Phaser.Input.Keyboard.KeyCodes.UP + * @type {number} + * @since 3.0.0 + */ + UP: 38, + + /** + * The RIGHT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.RIGHT + * @type {number} + * @since 3.0.0 + */ + RIGHT: 39, + + /** + * The DOWN key. + * + * @name Phaser.Input.Keyboard.KeyCodes.DOWN + * @type {number} + * @since 3.0.0 + */ + DOWN: 40, + + /** + * The PRINT_SCREEN key. + * + * @name Phaser.Input.Keyboard.KeyCodes.PRINT_SCREEN + * @type {number} + * @since 3.0.0 + */ + PRINT_SCREEN: 42, + + /** + * The INSERT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.INSERT + * @type {number} + * @since 3.0.0 + */ + INSERT: 45, + + /** + * The DELETE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.DELETE + * @type {number} + * @since 3.0.0 + */ + DELETE: 46, + + /** + * The ZERO key. + * + * @name Phaser.Input.Keyboard.KeyCodes.ZERO + * @type {number} + * @since 3.0.0 + */ + ZERO: 48, + + /** + * The ONE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.ONE + * @type {number} + * @since 3.0.0 + */ + ONE: 49, + + /** + * The TWO key. + * + * @name Phaser.Input.Keyboard.KeyCodes.TWO + * @type {number} + * @since 3.0.0 + */ + TWO: 50, + + /** + * The THREE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.THREE + * @type {number} + * @since 3.0.0 + */ + THREE: 51, + + /** + * The FOUR key. + * + * @name Phaser.Input.Keyboard.KeyCodes.FOUR + * @type {number} + * @since 3.0.0 + */ + FOUR: 52, + + /** + * The FIVE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.FIVE + * @type {number} + * @since 3.0.0 + */ + FIVE: 53, + + /** + * The SIX key. + * + * @name Phaser.Input.Keyboard.KeyCodes.SIX + * @type {number} + * @since 3.0.0 + */ + SIX: 54, + + /** + * The SEVEN key. + * + * @name Phaser.Input.Keyboard.KeyCodes.SEVEN + * @type {number} + * @since 3.0.0 + */ + SEVEN: 55, + + /** + * The EIGHT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.EIGHT + * @type {number} + * @since 3.0.0 + */ + EIGHT: 56, + + /** + * The NINE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NINE + * @type {number} + * @since 3.0.0 + */ + NINE: 57, + + /** + * The NUMPAD_ZERO key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_ZERO + * @type {number} + * @since 3.0.0 + */ + NUMPAD_ZERO: 96, + + /** + * The NUMPAD_ONE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_ONE + * @type {number} + * @since 3.0.0 + */ + NUMPAD_ONE: 97, + + /** + * The NUMPAD_TWO key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_TWO + * @type {number} + * @since 3.0.0 + */ + NUMPAD_TWO: 98, + + /** + * The NUMPAD_THREE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_THREE + * @type {number} + * @since 3.0.0 + */ + NUMPAD_THREE: 99, + + /** + * The NUMPAD_FOUR key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_FOUR + * @type {number} + * @since 3.0.0 + */ + NUMPAD_FOUR: 100, + + /** + * The NUMPAD_FIVE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_FIVE + * @type {number} + * @since 3.0.0 + */ + NUMPAD_FIVE: 101, + + /** + * The NUMPAD_SIX key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_SIX + * @type {number} + * @since 3.0.0 + */ + NUMPAD_SIX: 102, + + /** + * The NUMPAD_SEVEN key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_SEVEN + * @type {number} + * @since 3.0.0 + */ + NUMPAD_SEVEN: 103, + + /** + * The NUMPAD_EIGHT key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_EIGHT + * @type {number} + * @since 3.0.0 + */ + NUMPAD_EIGHT: 104, + + /** + * The NUMPAD_NINE key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_NINE + * @type {number} + * @since 3.0.0 + */ + NUMPAD_NINE: 105, + + /** + * The Numpad Addition (+) key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD + * @type {number} + * @since 3.21.0 + */ + NUMPAD_ADD: 107, + + /** + * The Numpad Subtraction (-) key. + * + * @name Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBTRACT + * @type {number} + * @since 3.21.0 + */ + NUMPAD_SUBTRACT: 109, + + /** + * The A key. + * + * @name Phaser.Input.Keyboard.KeyCodes.A + * @type {number} + * @since 3.0.0 + */ + A: 65, + + /** + * The B key. + * + * @name Phaser.Input.Keyboard.KeyCodes.B + * @type {number} + * @since 3.0.0 + */ + B: 66, + + /** + * The C key. + * + * @name Phaser.Input.Keyboard.KeyCodes.C + * @type {number} + * @since 3.0.0 + */ + C: 67, + + /** + * The D key. + * + * @name Phaser.Input.Keyboard.KeyCodes.D + * @type {number} + * @since 3.0.0 + */ + D: 68, + + /** + * The E key. + * + * @name Phaser.Input.Keyboard.KeyCodes.E + * @type {number} + * @since 3.0.0 + */ + E: 69, + + /** + * The F key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F + * @type {number} + * @since 3.0.0 + */ + F: 70, + + /** + * The G key. + * + * @name Phaser.Input.Keyboard.KeyCodes.G + * @type {number} + * @since 3.0.0 + */ + G: 71, + + /** + * The H key. + * + * @name Phaser.Input.Keyboard.KeyCodes.H + * @type {number} + * @since 3.0.0 + */ + H: 72, + + /** + * The I key. + * + * @name Phaser.Input.Keyboard.KeyCodes.I + * @type {number} + * @since 3.0.0 + */ + I: 73, + + /** + * The J key. + * + * @name Phaser.Input.Keyboard.KeyCodes.J + * @type {number} + * @since 3.0.0 + */ + J: 74, + + /** + * The K key. + * + * @name Phaser.Input.Keyboard.KeyCodes.K + * @type {number} + * @since 3.0.0 + */ + K: 75, + + /** + * The L key. + * + * @name Phaser.Input.Keyboard.KeyCodes.L + * @type {number} + * @since 3.0.0 + */ + L: 76, + + /** + * The M key. + * + * @name Phaser.Input.Keyboard.KeyCodes.M + * @type {number} + * @since 3.0.0 + */ + M: 77, + + /** + * The N key. + * + * @name Phaser.Input.Keyboard.KeyCodes.N + * @type {number} + * @since 3.0.0 + */ + N: 78, + + /** + * The O key. + * + * @name Phaser.Input.Keyboard.KeyCodes.O + * @type {number} + * @since 3.0.0 + */ + O: 79, + + /** + * The P key. + * + * @name Phaser.Input.Keyboard.KeyCodes.P + * @type {number} + * @since 3.0.0 + */ + P: 80, + + /** + * The Q key. + * + * @name Phaser.Input.Keyboard.KeyCodes.Q + * @type {number} + * @since 3.0.0 + */ + Q: 81, + + /** + * The R key. + * + * @name Phaser.Input.Keyboard.KeyCodes.R + * @type {number} + * @since 3.0.0 + */ + R: 82, + + /** + * The S key. + * + * @name Phaser.Input.Keyboard.KeyCodes.S + * @type {number} + * @since 3.0.0 + */ + S: 83, + + /** + * The T key. + * + * @name Phaser.Input.Keyboard.KeyCodes.T + * @type {number} + * @since 3.0.0 + */ + T: 84, + + /** + * The U key. + * + * @name Phaser.Input.Keyboard.KeyCodes.U + * @type {number} + * @since 3.0.0 + */ + U: 85, + + /** + * The V key. + * + * @name Phaser.Input.Keyboard.KeyCodes.V + * @type {number} + * @since 3.0.0 + */ + V: 86, + + /** + * The W key. + * + * @name Phaser.Input.Keyboard.KeyCodes.W + * @type {number} + * @since 3.0.0 + */ + W: 87, + + /** + * The X key. + * + * @name Phaser.Input.Keyboard.KeyCodes.X + * @type {number} + * @since 3.0.0 + */ + X: 88, + + /** + * The Y key. + * + * @name Phaser.Input.Keyboard.KeyCodes.Y + * @type {number} + * @since 3.0.0 + */ + Y: 89, + + /** + * The Z key. + * + * @name Phaser.Input.Keyboard.KeyCodes.Z + * @type {number} + * @since 3.0.0 + */ + Z: 90, + + /** + * The F1 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F1 + * @type {number} + * @since 3.0.0 + */ + F1: 112, + + /** + * The F2 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F2 + * @type {number} + * @since 3.0.0 + */ + F2: 113, + + /** + * The F3 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F3 + * @type {number} + * @since 3.0.0 + */ + F3: 114, + + /** + * The F4 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F4 + * @type {number} + * @since 3.0.0 + */ + F4: 115, + + /** + * The F5 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F5 + * @type {number} + * @since 3.0.0 + */ + F5: 116, + + /** + * The F6 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F6 + * @type {number} + * @since 3.0.0 + */ + F6: 117, + + /** + * The F7 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F7 + * @type {number} + * @since 3.0.0 + */ + F7: 118, + + /** + * The F8 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F8 + * @type {number} + * @since 3.0.0 + */ + F8: 119, + + /** + * The F9 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F9 + * @type {number} + * @since 3.0.0 + */ + F9: 120, + + /** + * The F10 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F10 + * @type {number} + * @since 3.0.0 + */ + F10: 121, + + /** + * The F11 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F11 + * @type {number} + * @since 3.0.0 + */ + F11: 122, + + /** + * The F12 key. + * + * @name Phaser.Input.Keyboard.KeyCodes.F12 + * @type {number} + * @since 3.0.0 + */ + F12: 123, + + /** + * The SEMICOLON key. + * + * @name Phaser.Input.Keyboard.KeyCodes.SEMICOLON + * @type {number} + * @since 3.0.0 + */ + SEMICOLON: 186, + + /** + * The PLUS key. + * + * @name Phaser.Input.Keyboard.KeyCodes.PLUS + * @type {number} + * @since 3.0.0 + */ + PLUS: 187, + + /** + * The COMMA key. + * + * @name Phaser.Input.Keyboard.KeyCodes.COMMA + * @type {number} + * @since 3.0.0 + */ + COMMA: 188, + + /** + * The MINUS key. + * + * @name Phaser.Input.Keyboard.KeyCodes.MINUS + * @type {number} + * @since 3.0.0 + */ + MINUS: 189, + + /** + * The PERIOD key. + * + * @name Phaser.Input.Keyboard.KeyCodes.PERIOD + * @type {number} + * @since 3.0.0 + */ + PERIOD: 190, + + /** + * The FORWARD_SLASH key. + * + * @name Phaser.Input.Keyboard.KeyCodes.FORWARD_SLASH + * @type {number} + * @since 3.0.0 + */ + FORWARD_SLASH: 191, + + /** + * The BACK_SLASH key. + * + * @name Phaser.Input.Keyboard.KeyCodes.BACK_SLASH + * @type {number} + * @since 3.0.0 + */ + BACK_SLASH: 220, + + /** + * The QUOTES key. + * + * @name Phaser.Input.Keyboard.KeyCodes.QUOTES + * @type {number} + * @since 3.0.0 + */ + QUOTES: 222, + + /** + * The BACKTICK key. + * + * @name Phaser.Input.Keyboard.KeyCodes.BACKTICK + * @type {number} + * @since 3.0.0 + */ + BACKTICK: 192, + + /** + * The OPEN_BRACKET key. + * + * @name Phaser.Input.Keyboard.KeyCodes.OPEN_BRACKET + * @type {number} + * @since 3.0.0 + */ + OPEN_BRACKET: 219, + + /** + * The CLOSED_BRACKET key. + * + * @name Phaser.Input.Keyboard.KeyCodes.CLOSED_BRACKET + * @type {number} + * @since 3.0.0 + */ + CLOSED_BRACKET: 221, + + /** + * The SEMICOLON_FIREFOX key. + * + * @name Phaser.Input.Keyboard.KeyCodes.SEMICOLON_FIREFOX + * @type {number} + * @since 3.0.0 + */ + SEMICOLON_FIREFOX: 59, + + /** + * The COLON key. + * + * @name Phaser.Input.Keyboard.KeyCodes.COLON + * @type {number} + * @since 3.0.0 + */ + COLON: 58, + + /** + * The COMMA_FIREFOX_WINDOWS key. + * + * @name Phaser.Input.Keyboard.KeyCodes.COMMA_FIREFOX_WINDOWS + * @type {number} + * @since 3.0.0 + */ + COMMA_FIREFOX_WINDOWS: 60, + + /** + * The COMMA_FIREFOX key. + * + * @name Phaser.Input.Keyboard.KeyCodes.COMMA_FIREFOX + * @type {number} + * @since 3.0.0 + */ + COMMA_FIREFOX: 62, + + /** + * The BRACKET_RIGHT_FIREFOX key. + * + * @name Phaser.Input.Keyboard.KeyCodes.BRACKET_RIGHT_FIREFOX + * @type {number} + * @since 3.0.0 + */ + BRACKET_RIGHT_FIREFOX: 174, + + /** + * The BRACKET_LEFT_FIREFOX key. + * + * @name Phaser.Input.Keyboard.KeyCodes.BRACKET_LEFT_FIREFOX + * @type {number} + * @since 3.0.0 + */ + BRACKET_LEFT_FIREFOX: 175 +}; + +module.exports = KeyCodes; + + +/***/ }), + +/***/ 74600: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var KeyCodes = __webpack_require__(46032); + +var KeyMap = {}; + +for (var key in KeyCodes) +{ + KeyMap[KeyCodes[key]] = key; +} + +module.exports = KeyMap; + + +/***/ }), + +/***/ 41170: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns `true` if the Key was released within the `duration` value given, based on the current + * game clock time. Or returns `false` if it either isn't up, or was released longer ago than the given duration. + * + * @function Phaser.Input.Keyboard.UpDuration + * @since 3.0.0 + * + * @param {Phaser.Input.Keyboard.Key} key - The Key object to test. + * @param {number} [duration=50] - The duration, in ms, within which the key must have been released. + * + * @return {boolean} `true` if the Key was released within `duration` ms ago, otherwise `false`. + */ +var UpDuration = function (key, duration) +{ + if (duration === undefined) { duration = 50; } + + var current = key.plugin.game.loop.time - key.timeUp; + + return (key.isUp && current < duration); +}; + +module.exports = UpDuration; + + +/***/ }), + +/***/ 85098: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Features = __webpack_require__(89357); +var InputEvents = __webpack_require__(8214); +var NOOP = __webpack_require__(29747); + +// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent +// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + +/** + * @classdesc + * The Mouse Manager is a helper class that belongs to the Input Manager. + * + * Its role is to listen for native DOM Mouse Events and then pass them onto the Input Manager for further processing. + * + * You do not need to create this class directly, the Input Manager will create an instance of it automatically. + * + * @class MouseManager + * @memberof Phaser.Input.Mouse + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.InputManager} inputManager - A reference to the Input Manager. + */ +var MouseManager = new Class({ + + initialize: + + function MouseManager (inputManager) + { + /** + * A reference to the Input Manager. + * + * @name Phaser.Input.Mouse.MouseManager#manager + * @type {Phaser.Input.InputManager} + * @since 3.0.0 + */ + this.manager = inputManager; + + /** + * If `true` the DOM `mousedown` event will have `preventDefault` set. + * + * @name Phaser.Input.Mouse.MouseManager#preventDefaultDown + * @type {boolean} + * @default true + * @since 3.50.0 + */ + this.preventDefaultDown = true; + + /** + * If `true` the DOM `mouseup` event will have `preventDefault` set. + * + * @name Phaser.Input.Mouse.MouseManager#preventDefaultUp + * @type {boolean} + * @default true + * @since 3.50.0 + */ + this.preventDefaultUp = true; + + /** + * If `true` the DOM `mousemove` event will have `preventDefault` set. + * + * @name Phaser.Input.Mouse.MouseManager#preventDefaultMove + * @type {boolean} + * @default true + * @since 3.50.0 + */ + this.preventDefaultMove = true; + + /** + * If `true` the DOM `wheel` event will have `preventDefault` set. + * + * @name Phaser.Input.Mouse.MouseManager#preventDefaultWheel + * @type {boolean} + * @default true + * @since 3.50.0 + */ + this.preventDefaultWheel = false; + + /** + * A boolean that controls if the Mouse Manager is enabled or not. + * Can be toggled on the fly. + * + * @name Phaser.Input.Mouse.MouseManager#enabled + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.enabled = false; + + /** + * The Mouse target, as defined in the Game Config. + * Typically the canvas to which the game is rendering, but can be any interactive DOM element. + * + * @name Phaser.Input.Mouse.MouseManager#target + * @type {any} + * @since 3.0.0 + */ + this.target; + + /** + * If the mouse has been pointer locked successfully this will be set to true. + * + * @name Phaser.Input.Mouse.MouseManager#locked + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.locked = false; + + /** + * The Mouse Move Event handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseMove + * @type {function} + * @since 3.10.0 + */ + this.onMouseMove = NOOP; + + /** + * The Mouse Down Event handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseDown + * @type {function} + * @since 3.10.0 + */ + this.onMouseDown = NOOP; + + /** + * The Mouse Up Event handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseUp + * @type {function} + * @since 3.10.0 + */ + this.onMouseUp = NOOP; + + /** + * The Mouse Down Event handler specifically for events on the Window. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseDownWindow + * @type {function} + * @since 3.17.0 + */ + this.onMouseDownWindow = NOOP; + + /** + * The Mouse Up Event handler specifically for events on the Window. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseUpWindow + * @type {function} + * @since 3.17.0 + */ + this.onMouseUpWindow = NOOP; + + /** + * The Mouse Over Event handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseOver + * @type {function} + * @since 3.16.0 + */ + this.onMouseOver = NOOP; + + /** + * The Mouse Out Event handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseOut + * @type {function} + * @since 3.16.0 + */ + this.onMouseOut = NOOP; + + /** + * The Mouse Wheel Event handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#onMouseWheel + * @type {function} + * @since 3.18.0 + */ + this.onMouseWheel = NOOP; + + /** + * Internal pointerLockChange handler. + * This function is sent the native DOM MouseEvent. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Mouse.MouseManager#pointerLockChange + * @type {function} + * @since 3.0.0 + */ + this.pointerLockChange = NOOP; + + /** + * Are the event listeners hooked into `window.top` or `window`? + * + * This is set during the `boot` sequence. If the browser does not have access to `window.top`, + * such as in cross-origin iframe environments, this property gets set to `false` and the events + * are hooked into `window` instead. + * + * @name Phaser.Input.Mouse.MouseManager#isTop + * @type {boolean} + * @readonly + * @since 3.50.0 + */ + this.isTop = true; + + inputManager.events.once(InputEvents.MANAGER_BOOT, this.boot, this); + }, + + /** + * The Touch Manager boot process. + * + * @method Phaser.Input.Mouse.MouseManager#boot + * @private + * @since 3.0.0 + */ + boot: function () + { + var config = this.manager.config; + + this.enabled = config.inputMouse; + this.target = config.inputMouseEventTarget; + this.passive = config.inputMousePassive; + + this.preventDefaultDown = config.inputMousePreventDefaultDown; + this.preventDefaultUp = config.inputMousePreventDefaultUp; + this.preventDefaultMove = config.inputMousePreventDefaultMove; + this.preventDefaultWheel = config.inputMousePreventDefaultWheel; + + if (!this.target) + { + this.target = this.manager.game.canvas; + } + else if (typeof this.target === 'string') + { + this.target = document.getElementById(this.target); + } + + if (config.disableContextMenu) + { + this.disableContextMenu(); + } + + if (this.enabled && this.target) + { + this.startListeners(); + } + }, + + /** + * Attempts to disable the context menu from appearing if you right-click on the game canvas, or specified input target. + * + * Works by listening for the `contextmenu` event and prevent defaulting it. + * + * Use this if you need to enable right-button mouse support in your game, and the context + * menu keeps getting in the way. + * + * @method Phaser.Input.Mouse.MouseManager#disableContextMenu + * @since 3.0.0 + * + * @return {this} This Mouse Manager instance. + */ + disableContextMenu: function () + { + this.target.addEventListener('contextmenu', function (event) + { + event.preventDefault(); + return false; + }); + + return this; + }, + + /** + * If the browser supports it, you can request that the pointer be locked to the browser window. + * + * This is classically known as 'FPS controls', where the pointer can't leave the browser until + * the user presses an exit key. + * + * If the browser successfully enters a locked state, a `POINTER_LOCK_CHANGE_EVENT` will be dispatched, + * from the games Input Manager, with an `isPointerLocked` property. + * + * It is important to note that pointer lock can only be enabled after an 'engagement gesture', + * see: https://w3c.github.io/pointerlock/#dfn-engagement-gesture. + * + * Note for Firefox: There is a bug in certain Firefox releases that cause native DOM events like + * `mousemove` to fire continuously when in pointer lock mode. You can get around this by setting + * `this.preventDefaultMove` to `false` in this class. You may also need to do the same for + * `preventDefaultDown` and/or `preventDefaultUp`. Please test combinations of these if you encounter + * the error. + * + * @method Phaser.Input.Mouse.MouseManager#requestPointerLock + * @since 3.0.0 + */ + requestPointerLock: function () + { + if (Features.pointerLock) + { + var element = this.target; + + element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock; + + element.requestPointerLock(); + } + }, + + /** + * If the browser supports pointer lock, this will request that the pointer lock is released. If + * the browser successfully enters a locked state, a 'POINTER_LOCK_CHANGE_EVENT' will be + * dispatched - from the game's input manager - with an `isPointerLocked` property. + * + * @method Phaser.Input.Mouse.MouseManager#releasePointerLock + * @since 3.0.0 + */ + releasePointerLock: function () + { + if (Features.pointerLock) + { + document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock; + document.exitPointerLock(); + } + }, + + /** + * Starts the Mouse Event listeners running. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Mouse.MouseManager#startListeners + * @since 3.0.0 + */ + startListeners: function () + { + var target = this.target; + + if (!target) + { + return; + } + + var _this = this; + var manager = this.manager; + var canvas = manager.canvas; + var autoFocus = (window && window.focus && manager.game.config.autoFocus); + + this.onMouseMove = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onMouseMove(event); + + if (_this.preventDefaultMove) + { + event.preventDefault(); + } + } + }; + + this.onMouseDown = function (event) + { + if (autoFocus) + { + window.focus(); + } + + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onMouseDown(event); + + if (_this.preventDefaultDown && event.target === canvas) + { + event.preventDefault(); + } + } + }; + + this.onMouseDownWindow = function (event) + { + if (event.sourceCapabilities && event.sourceCapabilities.firesTouchEvents) + { + return; + } + + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled && event.target !== canvas) + { + // Only process the event if the target isn't the canvas + manager.onMouseDown(event); + } + }; + + this.onMouseUp = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onMouseUp(event); + + if (_this.preventDefaultUp && event.target === canvas) + { + event.preventDefault(); + } + } + }; + + this.onMouseUpWindow = function (event) + { + if (event.sourceCapabilities && event.sourceCapabilities.firesTouchEvents) + { + return; + } + + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled && event.target !== canvas) + { + // Only process the event if the target isn't the canvas + manager.onMouseUp(event); + } + }; + + this.onMouseOver = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.setCanvasOver(event); + } + }; + + this.onMouseOut = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.setCanvasOut(event); + } + }; + + this.onMouseWheel = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onMouseWheel(event); + } + + if (_this.preventDefaultWheel && event.target === canvas) + { + event.preventDefault(); + } + }; + + var passive = { passive: true }; + + target.addEventListener('mousemove', this.onMouseMove); + target.addEventListener('mousedown', this.onMouseDown); + target.addEventListener('mouseup', this.onMouseUp); + target.addEventListener('mouseover', this.onMouseOver, passive); + target.addEventListener('mouseout', this.onMouseOut, passive); + + if (this.preventDefaultWheel) + { + target.addEventListener('wheel', this.onMouseWheel, { passive: false }); + } + else + { + target.addEventListener('wheel', this.onMouseWheel, passive); + } + + if (window && manager.game.config.inputWindowEvents) + { + try + { + window.top.addEventListener('mousedown', this.onMouseDownWindow, passive); + window.top.addEventListener('mouseup', this.onMouseUpWindow, passive); + } + catch (exception) + { + window.addEventListener('mousedown', this.onMouseDownWindow, passive); + window.addEventListener('mouseup', this.onMouseUpWindow, passive); + + this.isTop = false; + } + } + + if (Features.pointerLock) + { + this.pointerLockChange = function (event) + { + var element = _this.target; + + _this.locked = (document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element) ? true : false; + + manager.onPointerLockChange(event); + }; + + document.addEventListener('pointerlockchange', this.pointerLockChange, true); + document.addEventListener('mozpointerlockchange', this.pointerLockChange, true); + document.addEventListener('webkitpointerlockchange', this.pointerLockChange, true); + } + + this.enabled = true; + }, + + /** + * Stops the Mouse Event listeners. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Mouse.MouseManager#stopListeners + * @since 3.0.0 + */ + stopListeners: function () + { + var target = this.target; + + target.removeEventListener('mousemove', this.onMouseMove); + target.removeEventListener('mousedown', this.onMouseDown); + target.removeEventListener('mouseup', this.onMouseUp); + target.removeEventListener('mouseover', this.onMouseOver); + target.removeEventListener('mouseout', this.onMouseOut); + + if (window) + { + target = (this.isTop) ? window.top : window; + + target.removeEventListener('mousedown', this.onMouseDownWindow); + target.removeEventListener('mouseup', this.onMouseUpWindow); + } + + if (Features.pointerLock) + { + document.removeEventListener('pointerlockchange', this.pointerLockChange, true); + document.removeEventListener('mozpointerlockchange', this.pointerLockChange, true); + document.removeEventListener('webkitpointerlockchange', this.pointerLockChange, true); + } + }, + + /** + * Destroys this Mouse Manager instance. + * + * @method Phaser.Input.Mouse.MouseManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.stopListeners(); + + this.target = null; + this.enabled = false; + this.manager = null; + } + +}); + +module.exports = MouseManager; + + +/***/ }), + +/***/ 87078: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Mouse + */ + +/* eslint-disable */ +module.exports = { + + MouseManager: __webpack_require__(85098) + +}; +/* eslint-enable */ + + +/***/ }), + +/***/ 36210: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var InputEvents = __webpack_require__(8214); +var NOOP = __webpack_require__(29747); + +// https://developer.mozilla.org/en-US/docs/Web/API/Touch_events +// https://patrickhlauke.github.io/touch/tests/results/ +// https://www.html5rocks.com/en/mobile/touch/ + +/** + * @classdesc + * The Touch Manager is a helper class that belongs to the Input Manager. + * + * Its role is to listen for native DOM Touch Events and then pass them onto the Input Manager for further processing. + * + * You do not need to create this class directly, the Input Manager will create an instance of it automatically. + * + * @class TouchManager + * @memberof Phaser.Input.Touch + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Input.InputManager} inputManager - A reference to the Input Manager. + */ +var TouchManager = new Class({ + + initialize: + + function TouchManager (inputManager) + { + /** + * A reference to the Input Manager. + * + * @name Phaser.Input.Touch.TouchManager#manager + * @type {Phaser.Input.InputManager} + * @since 3.0.0 + */ + this.manager = inputManager; + + /** + * If true the DOM events will have event.preventDefault applied to them, if false they will propagate fully. + * + * @name Phaser.Input.Touch.TouchManager#capture + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.capture = true; + + /** + * A boolean that controls if the Touch Manager is enabled or not. + * Can be toggled on the fly. + * + * @name Phaser.Input.Touch.TouchManager#enabled + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.enabled = false; + + /** + * The Touch Event target, as defined in the Game Config. + * Typically the canvas to which the game is rendering, but can be any interactive DOM element. + * + * @name Phaser.Input.Touch.TouchManager#target + * @type {any} + * @since 3.0.0 + */ + this.target; + + /** + * The Touch Start event handler function. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchStart + * @type {function} + * @since 3.0.0 + */ + this.onTouchStart = NOOP; + + /** + * The Touch Start event handler function specifically for events on the Window. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchStartWindow + * @type {function} + * @since 3.17.0 + */ + this.onTouchStartWindow = NOOP; + + /** + * The Touch Move event handler function. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchMove + * @type {function} + * @since 3.0.0 + */ + this.onTouchMove = NOOP; + + /** + * The Touch End event handler function. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchEnd + * @type {function} + * @since 3.0.0 + */ + this.onTouchEnd = NOOP; + + /** + * The Touch End event handler function specifically for events on the Window. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchEndWindow + * @type {function} + * @since 3.17.0 + */ + this.onTouchEndWindow = NOOP; + + /** + * The Touch Cancel event handler function. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchCancel + * @type {function} + * @since 3.15.0 + */ + this.onTouchCancel = NOOP; + + /** + * The Touch Cancel event handler function specifically for events on the Window. + * Initially empty and bound in the `startListeners` method. + * + * @name Phaser.Input.Touch.TouchManager#onTouchCancelWindow + * @type {function} + * @since 3.18.0 + */ + this.onTouchCancelWindow = NOOP; + + /** + * Are the event listeners hooked into `window.top` or `window`? + * + * This is set during the `boot` sequence. If the browser does not have access to `window.top`, + * such as in cross-origin iframe environments, this property gets set to `false` and the events + * are hooked into `window` instead. + * + * @name Phaser.Input.Touch.TouchManager#isTop + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.isTop = true; + + inputManager.events.once(InputEvents.MANAGER_BOOT, this.boot, this); + }, + + /** + * The Touch Manager boot process. + * + * @method Phaser.Input.Touch.TouchManager#boot + * @private + * @since 3.0.0 + */ + boot: function () + { + var config = this.manager.config; + + this.enabled = config.inputTouch; + this.target = config.inputTouchEventTarget; + this.capture = config.inputTouchCapture; + + if (!this.target) + { + this.target = this.manager.game.canvas; + } + else if (typeof this.target === 'string') + { + this.target = document.getElementById(this.target); + } + + if (config.disableContextMenu) + { + this.disableContextMenu(); + } + + if (this.enabled && this.target) + { + this.startListeners(); + } + }, + + /** + * Attempts to disable the context menu from appearing if you touch-hold on the browser. + * + * Works by listening for the `contextmenu` event and prevent defaulting it. + * + * Use this if you need to disable the OS context menu on mobile. + * + * @method Phaser.Input.Touch.TouchManager#disableContextMenu + * @since 3.20.0 + * + * @return {this} This Touch Manager instance. + */ + disableContextMenu: function () + { + this.target.addEventListener('contextmenu', function (event) + { + event.preventDefault(); + return false; + }); + + return this; + }, + + /** + * Starts the Touch Event listeners running as long as an input target is set. + * + * This method is called automatically if Touch Input is enabled in the game config, + * which it is by default. However, you can call it manually should you need to + * delay input capturing until later in the game. + * + * @method Phaser.Input.Touch.TouchManager#startListeners + * @since 3.0.0 + */ + startListeners: function () + { + var target = this.target; + + if (!target) + { + return; + } + + var _this = this; + var manager = this.manager; + var canvas = manager.canvas; + var autoFocus = (window && window.focus && manager.game.config.autoFocus); + + this.onTouchMove = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onTouchMove(event); + + if (_this.capture && event.cancelable) + { + event.preventDefault(); + } + } + }; + + this.onTouchStart = function (event) + { + if (autoFocus) + { + window.focus(); + } + + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onTouchStart(event); + + if (_this.capture && event.cancelable && event.target === canvas) + { + event.preventDefault(); + } + } + }; + + this.onTouchStartWindow = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled && event.target !== canvas) + { + // Only process the event if the target isn't the canvas + manager.onTouchStart(event); + } + }; + + this.onTouchEnd = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onTouchEnd(event); + + if (_this.capture && event.cancelable && event.target === canvas) + { + event.preventDefault(); + } + } + }; + + this.onTouchEndWindow = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled && event.target !== canvas) + { + // Only process the event if the target isn't the canvas + manager.onTouchEnd(event); + } + }; + + this.onTouchCancel = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onTouchCancel(event); + + if (_this.capture) + { + event.preventDefault(); + } + } + }; + + this.onTouchCancelWindow = function (event) + { + if (!event.defaultPrevented && _this.enabled && manager && manager.enabled) + { + manager.onTouchCancel(event); + } + }; + + var capture = this.capture; + var passive = { passive: true }; + var nonPassive = { passive: false }; + + target.addEventListener('touchstart', this.onTouchStart, (capture) ? nonPassive : passive); + target.addEventListener('touchmove', this.onTouchMove, (capture) ? nonPassive : passive); + target.addEventListener('touchend', this.onTouchEnd, (capture) ? nonPassive : passive); + target.addEventListener('touchcancel', this.onTouchCancel, (capture) ? nonPassive : passive); + + if (window && manager.game.config.inputWindowEvents) + { + try + { + window.top.addEventListener('touchstart', this.onTouchStartWindow, nonPassive); + window.top.addEventListener('touchend', this.onTouchEndWindow, nonPassive); + window.top.addEventListener('touchcancel', this.onTouchCancelWindow, nonPassive); + } + catch (exception) + { + window.addEventListener('touchstart', this.onTouchStartWindow, nonPassive); + window.addEventListener('touchend', this.onTouchEndWindow, nonPassive); + window.addEventListener('touchcancel', this.onTouchCancelWindow, nonPassive); + + this.isTop = false; + } + } + + this.enabled = true; + }, + + /** + * Stops the Touch Event listeners. + * This is called automatically and does not need to be manually invoked. + * + * @method Phaser.Input.Touch.TouchManager#stopListeners + * @since 3.0.0 + */ + stopListeners: function () + { + var target = this.target; + + target.removeEventListener('touchstart', this.onTouchStart); + target.removeEventListener('touchmove', this.onTouchMove); + target.removeEventListener('touchend', this.onTouchEnd); + target.removeEventListener('touchcancel', this.onTouchCancel); + + if (window) + { + target = (this.isTop) ? window.top : window; + + target.removeEventListener('touchstart', this.onTouchStartWindow); + target.removeEventListener('touchend', this.onTouchEndWindow); + target.removeEventListener('touchcancel', this.onTouchCancelWindow); + } + }, + + /** + * Destroys this Touch Manager instance. + * + * @method Phaser.Input.Touch.TouchManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.stopListeners(); + + this.target = null; + this.enabled = false; + this.manager = null; + } + +}); + +module.exports = TouchManager; + + +/***/ }), + +/***/ 95618: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Input.Touch + */ + +/* eslint-disable */ +module.exports = { + + TouchManager: __webpack_require__(36210) + +}; +/* eslint-enable */ + + +/***/ }), + +/***/ 41299: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var Events = __webpack_require__(54899); +var GetFastValue = __webpack_require__(95540); +var GetURL = __webpack_require__(98356); +var MergeXHRSettings = __webpack_require__(3374); +var XHRLoader = __webpack_require__(84376); +var XHRSettings = __webpack_require__(92638); + +/** + * @classdesc + * The base File class used by all File Types that the Loader can support. + * You shouldn't create an instance of a File directly, but should extend it with your own class, setting a custom type and processing methods. + * + * @class File + * @memberof Phaser.Loader + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - The Loader that is going to load this File. + * @param {Phaser.Types.Loader.FileConfig} fileConfig - The file configuration object, as created by the file type. + */ +var File = new Class({ + + initialize: + + function File (loader, fileConfig) + { + /** + * A reference to the Loader that is going to load this file. + * + * @name Phaser.Loader.File#loader + * @type {Phaser.Loader.LoaderPlugin} + * @since 3.0.0 + */ + this.loader = loader; + + /** + * A reference to the Cache, or Texture Manager, that is going to store this file if it loads. + * + * @name Phaser.Loader.File#cache + * @type {(Phaser.Cache.BaseCache|Phaser.Textures.TextureManager)} + * @since 3.7.0 + */ + this.cache = GetFastValue(fileConfig, 'cache', false); + + /** + * The file type string (image, json, etc) for sorting within the Loader. + * + * @name Phaser.Loader.File#type + * @type {string} + * @since 3.0.0 + */ + this.type = GetFastValue(fileConfig, 'type', false); + + if (!this.type) + { + throw new Error('Invalid File type: ' + this.type); + } + + /** + * Unique cache key (unique within its file type) + * + * @name Phaser.Loader.File#key + * @type {string} + * @since 3.0.0 + */ + this.key = GetFastValue(fileConfig, 'key', false); + + var loadKey = this.key; + + if (loader.prefix && loader.prefix !== '') + { + this.key = loader.prefix + loadKey; + } + + if (!this.key) + { + throw new Error('Invalid File key: ' + this.key); + } + + var url = GetFastValue(fileConfig, 'url'); + + if (url === undefined) + { + url = loader.path + loadKey + '.' + GetFastValue(fileConfig, 'extension', ''); + } + else if (typeof url === 'string' && !url.match(/^(?:blob:|data:|capacitor:\/\/|http:\/\/|https:\/\/|\/\/)/)) + { + url = loader.path + url; + } + + /** + * The URL of the file, not including baseURL. + * + * Automatically has Loader.path prepended to it if a string. + * + * Can also be a JavaScript Object, such as the results of parsing JSON data. + * + * @name Phaser.Loader.File#url + * @type {object|string} + * @since 3.0.0 + */ + this.url = url; + + /** + * The final URL this file will load from, including baseURL and path. + * Set automatically when the Loader calls 'load' on this file. + * + * @name Phaser.Loader.File#src + * @type {string} + * @since 3.0.0 + */ + this.src = ''; + + /** + * The merged XHRSettings for this file. + * + * @name Phaser.Loader.File#xhrSettings + * @type {Phaser.Types.Loader.XHRSettingsObject} + * @since 3.0.0 + */ + this.xhrSettings = XHRSettings(GetFastValue(fileConfig, 'responseType', undefined)); + + if (GetFastValue(fileConfig, 'xhrSettings', false)) + { + this.xhrSettings = MergeXHRSettings(this.xhrSettings, GetFastValue(fileConfig, 'xhrSettings', {})); + } + + /** + * The XMLHttpRequest instance (as created by XHR Loader) that is loading this File. + * + * @name Phaser.Loader.File#xhrLoader + * @type {?XMLHttpRequest} + * @since 3.0.0 + */ + this.xhrLoader = null; + + /** + * The current state of the file. One of the FILE_CONST values. + * + * @name Phaser.Loader.File#state + * @type {number} + * @since 3.0.0 + */ + this.state = (typeof(this.url) === 'function') ? CONST.FILE_POPULATED : CONST.FILE_PENDING; + + /** + * The total size of this file. + * Set by onProgress and only if loading via XHR. + * + * @name Phaser.Loader.File#bytesTotal + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.bytesTotal = 0; + + /** + * Updated as the file loads. + * Only set if loading via XHR. + * + * @name Phaser.Loader.File#bytesLoaded + * @type {number} + * @default -1 + * @since 3.0.0 + */ + this.bytesLoaded = -1; + + /** + * A percentage value between 0 and 1 indicating how much of this file has loaded. + * Only set if loading via XHR. + * + * @name Phaser.Loader.File#percentComplete + * @type {number} + * @default -1 + * @since 3.0.0 + */ + this.percentComplete = -1; + + /** + * For CORs based loading. + * If this is undefined then the File will check BaseLoader.crossOrigin and use that (if set) + * + * @name Phaser.Loader.File#crossOrigin + * @type {(string|undefined)} + * @since 3.0.0 + */ + this.crossOrigin = undefined; + + /** + * The processed file data, stored here after the file has loaded. + * + * @name Phaser.Loader.File#data + * @type {*} + * @since 3.0.0 + */ + this.data = undefined; + + /** + * A config object that can be used by file types to store transitional data. + * + * @name Phaser.Loader.File#config + * @type {*} + * @since 3.0.0 + */ + this.config = GetFastValue(fileConfig, 'config', {}); + + /** + * If this is a multipart file, i.e. an atlas and its json together, then this is a reference + * to the parent MultiFile. Set and used internally by the Loader or specific file types. + * + * @name Phaser.Loader.File#multiFile + * @type {?Phaser.Loader.MultiFile} + * @since 3.7.0 + */ + this.multiFile; + + /** + * Does this file have an associated linked file? Such as an image and a normal map. + * Atlases and Bitmap Fonts use the multiFile, because those files need loading together but aren't + * actually bound by data, where-as a linkFile is. + * + * @name Phaser.Loader.File#linkFile + * @type {?Phaser.Loader.File} + * @since 3.7.0 + */ + this.linkFile; + + /** + * Does this File contain a data URI? + * + * @name Phaser.Loader.File#base64 + * @type {boolean} + * @since 3.80.0 + */ + this.base64 = (typeof url === 'string') && (url.indexOf('data:') === 0); + + /** + * The counter for the number of times to retry loading this file before it fails. + * + * You can set this property value in the FileConfig object. If not present, + * this property is read from the `LoaderPlugin.maxRetries` property when + * this File instance is created. + * + * You can set this value via the Game Config, or you can adjust the `LoaderPlugin` property + * at any point after the Loader has started. However, it will not apply to files + * that have already been added to the Loader, only those added after this value + * is changed. + * + * @name Phaser.Loader.File#retryAttempts + * @type {number} + * @default 2 + * @since 3.85.0 + */ + this.retryAttempts = GetFastValue(fileConfig, 'maxRetries', loader.maxRetries); + }, + + /** + * Links this File with another, so they depend upon each other for loading and processing. + * + * @method Phaser.Loader.File#setLink + * @since 3.7.0 + * + * @param {Phaser.Loader.File} fileB - The file to link to this one. + */ + setLink: function (fileB) + { + this.linkFile = fileB; + + fileB.linkFile = this; + }, + + /** + * Resets the XHRLoader instance this file is using. + * + * @method Phaser.Loader.File#resetXHR + * @since 3.0.0 + */ + resetXHR: function () + { + if (this.xhrLoader) + { + this.xhrLoader.onload = undefined; + this.xhrLoader.onerror = undefined; + this.xhrLoader.onprogress = undefined; + } + }, + + /** + * Called by the Loader, starts the actual file downloading. + * During the load the methods onLoad, onError and onProgress are called, based on the XHR events. + * You shouldn't normally call this method directly, it's meant to be invoked by the Loader. + * + * @method Phaser.Loader.File#load + * @since 3.0.0 + */ + load: function () + { + if (this.state === CONST.FILE_POPULATED) + { + // Can happen for example in a JSONFile if they've provided a JSON object instead of a URL + this.loader.nextFile(this, true); + } + else + { + this.state = CONST.FILE_LOADING; + + this.src = GetURL(this, this.loader.baseURL); + + if (!this.src) + { + throw new Error('URL Error in File: ' + this.key + ' from: ' + this.url); + } + + if (this.src.indexOf('data:') === 0) + { + this.base64 = true; + } + + this.xhrLoader = XHRLoader(this, this.loader.xhr); + } + }, + + /** + * Called when the file finishes loading, is sent a DOM ProgressEvent. + * + * @method Phaser.Loader.File#onLoad + * @since 3.0.0 + * + * @param {XMLHttpRequest} xhr - The XMLHttpRequest that caused this onload event. + * @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this load. + */ + onLoad: function (xhr, event) + { + var isLocalFile = xhr.responseURL && this.loader.localSchemes.some(function (scheme) + { + return xhr.responseURL.indexOf(scheme) === 0; + }); + + var localFileOk = (isLocalFile && event.target.status === 0); + + var success = !(event.target && event.target.status !== 200) || localFileOk; + + // Handle HTTP status codes of 4xx and 5xx as errors, even if xhr.onerror was not called. + if (xhr.readyState === 4 && xhr.status >= 400 && xhr.status <= 599) + { + success = false; + } + + this.state = CONST.FILE_LOADED; + + this.resetXHR(); + + this.loader.nextFile(this, success); + }, + + /** + * Called by the XHRLoader if it was given a File with base64 data to load. + * + * @method Phaser.Loader.File#onBase64Load + * @since 3.80.0 + * + * @param {XMLHttpRequest} xhr - The FakeXHR object containing the decoded base64 data. + */ + onBase64Load: function (xhr) + { + this.xhrLoader = xhr; + + this.state = CONST.FILE_LOADED; + + this.percentComplete = 1; + + this.loader.emit(Events.FILE_PROGRESS, this, this.percentComplete); + + this.loader.nextFile(this, true); + }, + + /** + * Called if the file errors while loading, is sent a DOM ProgressEvent. + * + * @method Phaser.Loader.File#onError + * @since 3.0.0 + * + * @param {XMLHttpRequest} xhr - The XMLHttpRequest that caused this onload event. + * @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this error. + */ + onError: function () + { + this.resetXHR(); + + if (this.retryAttempts > 0) + { + this.retryAttempts--; + + this.load(); + } + else + { + this.loader.nextFile(this, false); + } + }, + + /** + * Called during the file load progress. Is sent a DOM ProgressEvent. + * + * @method Phaser.Loader.File#onProgress + * @fires Phaser.Loader.Events#FILE_PROGRESS + * @since 3.0.0 + * + * @param {ProgressEvent} event - The DOM ProgressEvent. + */ + onProgress: function (event) + { + if (event.lengthComputable) + { + this.bytesLoaded = event.loaded; + this.bytesTotal = event.total; + + this.percentComplete = Math.min((this.bytesLoaded / this.bytesTotal), 1); + + this.loader.emit(Events.FILE_PROGRESS, this, this.percentComplete); + } + }, + + /** + * Usually overridden by the FileTypes and is called by Loader.nextFile. + * This method controls what extra work this File does with its loaded data, for example a JSON file will parse itself during this stage. + * + * @method Phaser.Loader.File#onProcess + * @since 3.0.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.onProcessComplete(); + }, + + /** + * Called when the File has completed processing. + * Checks on the state of its multifile, if set. + * + * @method Phaser.Loader.File#onProcessComplete + * @since 3.7.0 + */ + onProcessComplete: function () + { + this.state = CONST.FILE_COMPLETE; + + if (this.multiFile) + { + this.multiFile.onFileComplete(this); + } + + this.loader.fileProcessComplete(this); + }, + + /** + * Called when the File has completed processing but it generated an error. + * Checks on the state of its multifile, if set. + * + * @method Phaser.Loader.File#onProcessError + * @since 3.7.0 + */ + onProcessError: function () + { + // eslint-disable-next-line no-console + console.error('Failed to process file: %s "%s"', this.type, this.key); + + this.state = CONST.FILE_ERRORED; + + if (this.multiFile) + { + this.multiFile.onFileFailed(this); + } + + this.loader.fileProcessComplete(this); + }, + + /** + * Checks if a key matching the one used by this file exists in the target Cache or not. + * This is called automatically by the LoaderPlugin to decide if the file can be safely + * loaded or will conflict. + * + * @method Phaser.Loader.File#hasCacheConflict + * @since 3.7.0 + * + * @return {boolean} `true` if adding this file will cause a conflict, otherwise `false`. + */ + hasCacheConflict: function () + { + return (this.cache && this.cache.exists(this.key)); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * This method is often overridden by specific file types. + * + * @method Phaser.Loader.File#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.cache && this.data) + { + this.cache.add(this.key, this.data); + } + }, + + /** + * Called once the file has been added to its cache and is now ready for deletion from the Loader. + * It will emit a `filecomplete` event from the LoaderPlugin. + * + * @method Phaser.Loader.File#pendingDestroy + * @fires Phaser.Loader.Events#FILE_COMPLETE + * @fires Phaser.Loader.Events#FILE_KEY_COMPLETE + * @since 3.7.0 + */ + pendingDestroy: function (data) + { + if (this.state === CONST.FILE_PENDING_DESTROY) + { + return; + } + + if (data === undefined) { data = this.data; } + + var key = this.key; + var type = this.type; + + this.loader.emit(Events.FILE_COMPLETE, key, type, data); + this.loader.emit(Events.FILE_KEY_COMPLETE + type + '-' + key, key, type, data); + + this.loader.flagForRemoval(this); + + this.state = CONST.FILE_PENDING_DESTROY; + }, + + /** + * Destroy this File and any references it holds. + * + * @method Phaser.Loader.File#destroy + * @since 3.7.0 + */ + destroy: function () + { + this.loader = null; + this.cache = null; + this.xhrSettings = null; + this.multiFile = null; + this.linkFile = null; + this.data = null; + } + +}); + +/** + * Static method for creating object URL using URL API and setting it as image 'src' attribute. + * If URL API is not supported (usually on old browsers) it falls back to creating Base64 encoded url using FileReader. + * + * @method Phaser.Loader.File.createObjectURL + * @static + * @since 3.7.0 + * + * @param {HTMLImageElement} image - Image object which 'src' attribute should be set to object URL. + * @param {Blob} blob - A Blob object to create an object URL for. + * @param {string} defaultType - Default mime type used if blob type is not available. + */ +File.createObjectURL = function (image, blob, defaultType) +{ + if (typeof URL === 'function') + { + image.src = URL.createObjectURL(blob); + } + else + { + var reader = new FileReader(); + + reader.onload = function () + { + image.removeAttribute('crossOrigin'); + image.src = 'data:' + (blob.type || defaultType) + ';base64,' + reader.result.split(',')[1]; + }; + + reader.onerror = image.onerror; + + reader.readAsDataURL(blob); + } +}; + +/** + * Static method for releasing an existing object URL which was previously created + * by calling {@link Phaser.Loader.File.createObjectURL} method. + * + * @method Phaser.Loader.File.revokeObjectURL + * @static + * @since 3.7.0 + * + * @param {HTMLImageElement} image - Image object which 'src' attribute should be revoked. + */ +File.revokeObjectURL = function (image) +{ + if (typeof URL === 'function') + { + URL.revokeObjectURL(image.src); + } +}; + +module.exports = File; + + +/***/ }), + +/***/ 74099: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var types = {}; + +/** + * @namespace Phaser.Loader.FileTypesManager + */ + +var FileTypesManager = { + + /** + * Static method called when a LoaderPlugin is created. + * + * Loops through the local types object and injects all of them as + * properties into the LoaderPlugin instance. + * + * @method Phaser.Loader.FileTypesManager.install + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - The LoaderPlugin to install the types into. + */ + install: function (loader) + { + for (var key in types) + { + loader[key] = types[key]; + } + }, + + /** + * Static method called directly by the File Types. + * + * The key is a reference to the function used to load the files via the Loader, i.e. `image`. + * + * @method Phaser.Loader.FileTypesManager.register + * @since 3.0.0 + * + * @param {string} key - The key that will be used as the method name in the LoaderPlugin. + * @param {function} factoryFunction - The function that will be called when LoaderPlugin.key is invoked. + */ + register: function (key, factoryFunction) + { + types[key] = factoryFunction; + }, + + /** + * Removed all associated file types. + * + * @method Phaser.Loader.FileTypesManager.destroy + * @since 3.0.0 + */ + destroy: function () + { + types = {}; + } + +}; + +module.exports = FileTypesManager; + + +/***/ }), + +/***/ 98356: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Given a File and a baseURL value this returns the URL the File will use to download from. + * + * @function Phaser.Loader.GetURL + * @since 3.0.0 + * + * @param {Phaser.Loader.File} file - The File object. + * @param {string} baseURL - A default base URL. + * + * @return {string} The URL the File will use. + */ +var GetURL = function (file, baseURL) +{ + if (!file.url) + { + return false; + } + + if (file.url.match(/^(?:blob:|data:|capacitor:\/\/|http:\/\/|https:\/\/|\/\/)/)) + { + return file.url; + } + else + { + return baseURL + file.url; + } +}; + +module.exports = GetURL; + + +/***/ }), + +/***/ 74261: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(54899); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var IsPlainObject = __webpack_require__(41212); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); +var XHRSettings = __webpack_require__(92638); + +/** + * @classdesc + * The Loader handles loading all external content such as Images, Sounds, Texture Atlases and data files. + * You typically interact with it via `this.load` in your Scene. Scenes can have a `preload` method, which is always + * called before the Scenes `create` method, allowing you to preload assets that the Scene may need. + * + * If you call any `this.load` methods from outside of `Scene.preload` then you need to start the Loader going + * yourself by calling `Loader.start()`. It's only automatically started during the Scene preload. + * + * The Loader uses a combination of tag loading (eg. Audio elements) and XHR and provides progress and completion events. + * Files are loaded in parallel by default. The amount of concurrent connections can be controlled in your Game Configuration. + * + * Once the Loader has started loading you are still able to add files to it. These can be injected as a result of a loader + * event, the type of file being loaded (such as a pack file) or other external events. As long as the Loader hasn't finished + * simply adding a new file to it, while running, will ensure it's added into the current queue. + * + * Every Scene has its own instance of the Loader and they are bound to the Scene in which they are created. However, + * assets loaded by the Loader are placed into global game-level caches. For example, loading an XML file will place that + * file inside `Game.cache.xml`, which is accessible from every Scene in your game, no matter who was responsible + * for loading it. The same is true of Textures. A texture loaded in one Scene is instantly available to all other Scenes + * in your game. + * + * The Loader works by using custom File Types. These are stored in the FileTypesManager, which injects them into the Loader + * when it's instantiated. You can create your own custom file types by extending either the File or MultiFile classes. + * See those files for more details. + * + * @class LoaderPlugin + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Loader + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene which owns this Loader instance. + */ +var LoaderPlugin = new Class({ + + Extends: EventEmitter, + + initialize: + + function LoaderPlugin (scene) + { + EventEmitter.call(this); + + var gameConfig = scene.sys.game.config; + var sceneConfig = scene.sys.settings.loader; + + /** + * The Scene which owns this Loader instance. + * + * @name Phaser.Loader.LoaderPlugin#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene Systems. + * + * @name Phaser.Loader.LoaderPlugin#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * A reference to the global Cache Manager. + * + * @name Phaser.Loader.LoaderPlugin#cacheManager + * @type {Phaser.Cache.CacheManager} + * @since 3.7.0 + */ + this.cacheManager = scene.sys.cache; + + /** + * A reference to the global Texture Manager. + * + * @name Phaser.Loader.LoaderPlugin#textureManager + * @type {Phaser.Textures.TextureManager} + * @since 3.7.0 + */ + this.textureManager = scene.sys.textures; + + /** + * A reference to the global Scene Manager. + * + * @name Phaser.Loader.LoaderPlugin#sceneManager + * @type {Phaser.Scenes.SceneManager} + * @protected + * @since 3.16.0 + */ + this.sceneManager = scene.sys.game.scene; + + // Inject the available filetypes into the Loader + FileTypesManager.install(this); + + /** + * An optional prefix that is automatically prepended to the start of every file key. + * If prefix was `MENU.` and you load an image with the key 'Background' the resulting key would be `MENU.Background`. + * You can set this directly, or call `Loader.setPrefix()`. It will then affect every file added to the Loader + * from that point on. It does _not_ change any file already in the load queue. + * + * @name Phaser.Loader.LoaderPlugin#prefix + * @type {string} + * @default '' + * @since 3.7.0 + */ + this.prefix = ''; + + /** + * The value of `path`, if set, is placed before any _relative_ file path given. For example: + * + * ```javascript + * this.load.path = "images/sprites/"; + * this.load.image("ball", "ball.png"); + * this.load.image("tree", "level1/oaktree.png"); + * this.load.image("boom", "http://server.com/explode.png"); + * ``` + * + * Would load the `ball` file from `images/sprites/ball.png` and the tree from + * `images/sprites/level1/oaktree.png` but the file `boom` would load from the URL + * given as it's an absolute URL. + * + * Please note that the path is added before the filename but *after* the baseURL (if set.) + * + * If you set this property directly then it _must_ end with a "/". Alternatively, call `setPath()` and it'll do it for you. + * + * @name Phaser.Loader.LoaderPlugin#path + * @type {string} + * @default '' + * @since 3.0.0 + */ + this.path = ''; + + /** + * If you want to append a URL before the path of any asset you can set this here. + * + * Useful if allowing the asset base url to be configured outside of the game code. + * + * If you set this property directly then it _must_ end with a "/". Alternatively, call `setBaseURL()` and it'll do it for you. + * + * @name Phaser.Loader.LoaderPlugin#baseURL + * @type {string} + * @default '' + * @since 3.0.0 + */ + this.baseURL = ''; + + this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL)); + + this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath)); + + this.setPrefix(GetFastValue(sceneConfig, 'prefix', gameConfig.loaderPrefix)); + + /** + * The number of concurrent / parallel resources to try and fetch at once. + * + * Old browsers limit 6 requests per domain; modern ones, especially those with HTTP/2 don't limit it at all. + * + * The default is 32 but you can change this in your Game Config, or by changing this property before the Loader starts. + * + * @name Phaser.Loader.LoaderPlugin#maxParallelDownloads + * @type {number} + * @since 3.0.0 + */ + this.maxParallelDownloads = GetFastValue(sceneConfig, 'maxParallelDownloads', gameConfig.loaderMaxParallelDownloads); + + /** + * xhr specific global settings (can be overridden on a per-file basis) + * + * @name Phaser.Loader.LoaderPlugin#xhr + * @type {Phaser.Types.Loader.XHRSettingsObject} + * @since 3.0.0 + */ + this.xhr = XHRSettings( + GetFastValue(sceneConfig, 'responseType', gameConfig.loaderResponseType), + GetFastValue(sceneConfig, 'async', gameConfig.loaderAsync), + GetFastValue(sceneConfig, 'user', gameConfig.loaderUser), + GetFastValue(sceneConfig, 'password', gameConfig.loaderPassword), + GetFastValue(sceneConfig, 'timeout', gameConfig.loaderTimeout), + GetFastValue(sceneConfig, 'withCredentials', gameConfig.loaderWithCredentials) + ); + + /** + * The crossOrigin value applied to loaded images. Very often this needs to be set to 'anonymous'. + * + * @name Phaser.Loader.LoaderPlugin#crossOrigin + * @type {string} + * @since 3.0.0 + */ + this.crossOrigin = GetFastValue(sceneConfig, 'crossOrigin', gameConfig.loaderCrossOrigin); + + /** + * Optional load type for image files. `XHR` is the default. Set to `HTMLImageElement` to load images using the Image tag instead. + * + * @name Phaser.Loader.LoaderPlugin#imageLoadType + * @type {string} + * @since 3.60.0 + */ + this.imageLoadType = GetFastValue(sceneConfig, 'imageLoadType', gameConfig.loaderImageLoadType); + + /** + * An array of all schemes that the Loader considers as being 'local'. + * + * This is populated by the `Phaser.Core.Config#loaderLocalScheme` game configuration setting and defaults to + * `[ 'file://', 'capacitor://' ]`. Additional local schemes can be added to this array as needed. + * + * @name Phaser.Loader.LoaderPlugin#localSchemes + * @type {string[]} + * @since 3.60.0 + */ + this.localSchemes = GetFastValue(sceneConfig, 'localScheme', gameConfig.loaderLocalScheme); + + /** + * The total number of files to load. It may not always be accurate because you may add to the Loader during the process + * of loading, especially if you load a Pack File. Therefore this value can change, but in most cases remains static. + * + * @name Phaser.Loader.LoaderPlugin#totalToLoad + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.totalToLoad = 0; + + /** + * The progress of the current load queue, as a float value between 0 and 1. + * This is updated automatically as files complete loading. + * Note that it is possible for this value to go down again if you add content to the current load queue during a load. + * + * @name Phaser.Loader.LoaderPlugin#progress + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.progress = 0; + + /** + * Files are placed in this Set when they're added to the Loader via `addFile`. + * + * They are moved to the `inflight` Set when they start loading, and assuming a successful + * load, to the `queue` Set for further processing. + * + * By the end of the load process this Set will be empty. + * + * @name Phaser.Loader.LoaderPlugin#list + * @type {Set.} + * @since 3.0.0 + */ + this.list = new Set(); + + /** + * Files are stored in this Set while they're in the process of being loaded. + * + * Upon a successful load they are moved to the `queue` Set. + * + * By the end of the load process this Set will be empty. + * + * @name Phaser.Loader.LoaderPlugin#inflight + * @type {Set.} + * @since 3.0.0 + */ + this.inflight = new Set(); + + /** + * Files are stored in this Set while they're being processed. + * + * If the process is successful they are moved to their final destination, which could be + * a Cache or the Texture Manager. + * + * At the end of the load process this Set will be empty. + * + * @name Phaser.Loader.LoaderPlugin#queue + * @type {Set.} + * @since 3.0.0 + */ + this.queue = new Set(); + + /** + * A temporary Set in which files are stored after processing, + * awaiting destruction at the end of the load process. + * + * @name Phaser.Loader.LoaderPlugin#_deleteQueue + * @type {Set.} + * @private + * @since 3.7.0 + */ + this._deleteQueue = new Set(); + + /** + * The total number of files that failed to load during the most recent load. + * This value is reset when you call `Loader.start`. + * + * @name Phaser.Loader.LoaderPlugin#totalFailed + * @type {number} + * @default 0 + * @since 3.7.0 + */ + this.totalFailed = 0; + + /** + * The total number of files that successfully loaded during the most recent load. + * This value is reset when you call `Loader.start`. + * + * @name Phaser.Loader.LoaderPlugin#totalComplete + * @type {number} + * @default 0 + * @since 3.7.0 + */ + this.totalComplete = 0; + + /** + * The current state of the Loader. + * + * @name Phaser.Loader.LoaderPlugin#state + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.state = CONST.LOADER_IDLE; + + /** + * The current index being used by multi-file loaders to avoid key clashes. + * + * @name Phaser.Loader.LoaderPlugin#multiKeyIndex + * @type {number} + * @private + * @since 3.20.0 + */ + this.multiKeyIndex = 0; + + /** + * The number of times to retry loading a single file before it fails. + * + * This property is read by the `File` object when it is created and set to + * the internal property of the same name. It's not used by the Loader itself. + * + * You can set this value via the Game Config, or you can adjust this property + * at any point after the Loader has started. However, it will not apply to files + * that have already been added to the Loader, only those added after this value + * is changed. + * + * @name Phaser.Loader.LoaderPlugin#maxRetries + * @type {number} + * @default 2 + * @since 3.85.0 + */ + this.maxRetries = GetFastValue(sceneConfig, 'maxRetries', gameConfig.loaderMaxRetries); + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.pluginStart, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Loader.LoaderPlugin#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Loader.LoaderPlugin#pluginStart + * @private + * @since 3.5.1 + */ + pluginStart: function () + { + this.systems.events.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * If you want to append a URL before the path of any asset you can set this here. + * + * Useful if allowing the asset base url to be configured outside of the game code. + * + * Once a base URL is set it will affect every file loaded by the Loader from that point on. It does _not_ change any + * file _already_ being loaded. To reset it, call this method with no arguments. + * + * @method Phaser.Loader.LoaderPlugin#setBaseURL + * @since 3.0.0 + * + * @param {string} [url] - The URL to use. Leave empty to reset. + * + * @return {this} This Loader object. + */ + setBaseURL: function (url) + { + if (url === undefined) { url = ''; } + + if (url !== '' && url.substr(-1) !== '/') + { + url = url.concat('/'); + } + + this.baseURL = url; + + return this; + }, + + /** + * The value of `path`, if set, is placed before any _relative_ file path given. For example: + * + * ```javascript + * this.load.setPath("images/sprites/"); + * this.load.image("ball", "ball.png"); + * this.load.image("tree", "level1/oaktree.png"); + * this.load.image("boom", "http://server.com/explode.png"); + * ``` + * + * Would load the `ball` file from `images/sprites/ball.png` and the tree from + * `images/sprites/level1/oaktree.png` but the file `boom` would load from the URL + * given as it's an absolute URL. + * + * Please note that the path is added before the filename but *after* the baseURL (if set.) + * + * Once a path is set it will then affect every file added to the Loader from that point on. It does _not_ change any + * file _already_ in the load queue. To reset it, call this method with no arguments. + * + * @method Phaser.Loader.LoaderPlugin#setPath + * @since 3.0.0 + * + * @param {string} [path] - The path to use. Leave empty to reset. + * + * @return {this} This Loader object. + */ + setPath: function (path) + { + if (path === undefined) { path = ''; } + + if (path !== '' && path.substr(-1) !== '/') + { + path = path.concat('/'); + } + + this.path = path; + + return this; + }, + + /** + * An optional prefix that is automatically prepended to the start of every file key. + * + * If prefix was `MENU.` and you load an image with the key 'Background' the resulting key would be `MENU.Background`. + * + * Once a prefix is set it will then affect every file added to the Loader from that point on. It does _not_ change any + * file _already_ in the load queue. To reset it, call this method with no arguments. + * + * @method Phaser.Loader.LoaderPlugin#setPrefix + * @since 3.7.0 + * + * @param {string} [prefix] - The prefix to use. Leave empty to reset. + * + * @return {this} This Loader object. + */ + setPrefix: function (prefix) + { + if (prefix === undefined) { prefix = ''; } + + this.prefix = prefix; + + return this; + }, + + /** + * Sets the Cross Origin Resource Sharing value used when loading files. + * + * Files can override this value on a per-file basis by specifying an alternative `crossOrigin` value in their file config. + * + * Once CORs is set it will then affect every file loaded by the Loader from that point on, as long as they don't have + * their own CORs setting. To reset it, call this method with no arguments. + * + * For more details about CORs see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS + * + * @method Phaser.Loader.LoaderPlugin#setCORS + * @since 3.0.0 + * + * @param {string} [crossOrigin] - The value to use for the `crossOrigin` property in the load request. + * + * @return {this} This Loader object. + */ + setCORS: function (crossOrigin) + { + this.crossOrigin = crossOrigin; + + return this; + }, + + /** + * Adds a file, or array of files, into the load queue. + * + * The file must be an instance of `Phaser.Loader.File`, or a class that extends it. The Loader will check that the key + * used by the file won't conflict with any other key either in the loader, the inflight queue or the target cache. + * If allowed it will then add the file into the pending list, read for the load to start. Or, if the load has already + * started, ready for the next batch of files to be pulled from the list to the inflight queue. + * + * You should not normally call this method directly, but rather use one of the Loader methods like `image` or `atlas`, + * however you can call this as long as the file given to it is well formed. + * + * @method Phaser.Loader.LoaderPlugin#addFile + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(Phaser.Loader.File|Phaser.Loader.File[])} file - The file, or array of files, to be added to the load queue. + */ + addFile: function (file) + { + if (!Array.isArray(file)) + { + file = [ file ]; + } + + for (var i = 0; i < file.length; i++) + { + var item = file[i]; + + // Does the file already exist in the cache or texture manager? + // Or will it conflict with a file already in the queue or inflight? + if (!this.keyExists(item)) + { + this.list.add(item); + + this.emit(Events.ADD, item.key, item.type, this, item); + + if (this.isLoading()) + { + this.totalToLoad++; + this.updateProgress(); + } + } + } + }, + + /** + * Checks the key and type of the given file to see if it will conflict with anything already + * in a Cache, the Texture Manager, or the list or inflight queues. + * + * @method Phaser.Loader.LoaderPlugin#keyExists + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The file to check the key of. + * + * @return {boolean} `true` if adding this file will cause a cache or queue conflict, otherwise `false`. + */ + keyExists: function (file) + { + var keyConflict = file.hasCacheConflict(); + + if (!keyConflict) + { + this.list.forEach(function (item) + { + if (item.type === file.type && item.key === file.key) + { + keyConflict = true; + + return false; + } + + }); + } + + if (!keyConflict && this.isLoading()) + { + this.inflight.forEach(function (item) + { + if (item.type === file.type && item.key === file.key) + { + keyConflict = true; + + return false; + } + + }); + + this.queue.forEach(function (item) + { + if (item.type === file.type && item.key === file.key) + { + keyConflict = true; + + return false; + } + + }); + } + + return keyConflict; + }, + + /** + * Takes a well formed, fully parsed pack file object and adds its entries into the load queue. Usually you do not call + * this method directly, but instead use `Loader.pack` and supply a path to a JSON file that holds the + * pack data. However, if you've got the data prepared you can pass it to this method. + * + * You can also provide an optional key. If you do then it will only add the entries from that part of the pack into + * to the load queue. If not specified it will add all entries it finds. For more details about the pack file format + * see the `LoaderPlugin.pack` method. + * + * @method Phaser.Loader.LoaderPlugin#addPack + * @since 3.7.0 + * + * @param {any} pack - The Pack File data to be parsed and each entry of it to added to the load queue. + * @param {string} [packKey] - An optional key to use from the pack file data. + * + * @return {boolean} `true` if any files were added to the queue, otherwise `false`. + */ + addPack: function (pack, packKey) + { + // if no packKey provided we'll add everything to the queue + if (typeof(packKey) === 'string') + { + var subPack = GetValue(pack, packKey); + + if (subPack) + { + pack = { packKey: subPack }; + } + } + + var total = 0; + + // Store the loader settings in case this pack replaces them + var currentBaseURL = this.baseURL; + var currentPath = this.path; + var currentPrefix = this.prefix; + + // Here we go ... + for (var key in pack) + { + if (!Object.prototype.hasOwnProperty.call(pack, key)) + { + continue; + } + + var config = pack[key]; + + // Any meta data to process? + var baseURL = GetFastValue(config, 'baseURL', currentBaseURL); + var path = GetFastValue(config, 'path', currentPath); + var prefix = GetFastValue(config, 'prefix', currentPrefix); + var files = GetFastValue(config, 'files', null); + var defaultType = GetFastValue(config, 'defaultType', 'void'); + + if (Array.isArray(files)) + { + this.setBaseURL(baseURL); + this.setPath(path); + this.setPrefix(prefix); + + for (var i = 0; i < files.length; i++) + { + var file = files[i]; + var type = (file.hasOwnProperty('type')) ? file.type : defaultType; + + if (this[type]) + { + this[type](file); + total++; + } + } + } + } + + // Reset the loader settings + this.setBaseURL(currentBaseURL); + this.setPath(currentPath); + this.setPrefix(currentPrefix); + + return (total > 0); + }, + + /** + * Remove the resources listed in an Asset Pack. + * + * This removes Animations from the Animation Manager, Textures from the Texture Manager, and all other assets from their respective caches. + * It doesn't remove the Pack itself from the JSON cache, if it exists there. + * If the Pack includes another Pack, its resources will be removed too. + * + * @method Phaser.Loader.LoaderPlugin#removePack + * @since 3.85.0 + * + * @param {(string|object)} packKey - The key of an Asset Pack in the JSON cache, or a Pack File data. + * @param {string} [dataKey] - A key in the Pack data, if you want to process only a section of it. + */ + removePack: function (packKey, dataKey) + { + var animationManager = this.systems.anims; + var cacheManager = this.cacheManager; + var textureManager = this.textureManager; + + var cacheMap = { + animation: 'json', + aseprite: 'json', + audio: 'audio', + audioSprite: 'audio', + binary: 'binary', + bitmapFont: 'bitmapFont', + css: null, + glsl: 'shader', + html: 'html', + json: 'json', + obj: 'obj', + plugin: null, + scenePlugin: null, + script: null, + spine: 'json', + text: 'text', + tilemapCSV: 'tilemap', + tilemapImpact: 'tilemap', + tilemapTiledJSON: 'tilemap', + video: 'video', + xml: 'xml' + }; + + var pack; + + if (IsPlainObject(packKey)) + { + pack = packKey; + } + else + { + pack = cacheManager.json.get(packKey); + + if (!pack) + { + console.warn('Asset Pack not found in JSON cache:', packKey); + + return; + } + } + + if (dataKey) + { + pack = { _: pack[dataKey] }; + } + + for (var configKey in pack) + { + var config = pack[configKey]; + var prefix = GetFastValue(config, 'prefix', ''); + var files = GetFastValue(config, 'files'); + var defaultType = GetFastValue(config, 'defaultType'); + + if (Array.isArray(files)) + { + for (var i = 0; i < files.length; i++) + { + var file = files[i]; + var type = (file.hasOwnProperty('type')) ? file.type : defaultType; + + if (!type) + { + console.warn('No type:', file); + + continue; + } + + var fileKey = prefix + file.key; + + if (type === 'animation') + { + animationManager.remove(fileKey); + } + + if (type === 'aseprite' || type === 'atlas' || type === 'atlasXML' || type === 'htmlTexture' || type === 'image' || type === 'multiatlas' || type === 'spritesheet' || type === 'svg' || type === 'texture' || type === 'unityAtlas') + { + textureManager.remove(fileKey); + + if (!cacheMap[type]) + { + continue; + } + } + + if (type === 'pack') + { + this.removePack(fileKey, file.dataKey); + + continue; + } + + if (type === 'spine') + { + var spineAtlas = cacheManager.custom.spine.get(fileKey); + + if (!spineAtlas) + { + continue; + } + + var spinePrefix = (spineAtlas.prefix === undefined) ? '' : spineAtlas.prefix; + + cacheManager.custom.spine.remove(fileKey); + + var spineTexture = cacheManager.custom.spineTextures.get(fileKey); + + if (!spineTexture) + { + continue; + } + + cacheManager.custom.spineTextures.remove(fileKey); + + for (var j = 0; j < spineTexture.pages.length; j++) + { + var page = spineTexture.pages[j]; + var textureKey = spinePrefix + page.name; + var altTextureKey = fileKey + ':' + textureKey; + + if (textureManager.exists(altTextureKey)) + { + textureManager.remove(altTextureKey); + } + else + { + textureManager.remove(textureKey); + } + } + } + + var cacheName = cacheMap[type]; + + if (cacheName === null) + { + // Nothing to remove. + + continue; + } + + if (!cacheName) + { + console.warn('Unknown type:', type); + + continue; + } + + var cache = cacheManager[cacheName]; + + cache.remove(fileKey); + } + } + } + }, + + /** + * Is the Loader actively loading, or processing loaded files? + * + * @method Phaser.Loader.LoaderPlugin#isLoading + * @since 3.0.0 + * + * @return {boolean} `true` if the Loader is busy loading or processing, otherwise `false`. + */ + isLoading: function () + { + return (this.state === CONST.LOADER_LOADING || this.state === CONST.LOADER_PROCESSING); + }, + + /** + * Is the Loader ready to start a new load? + * + * @method Phaser.Loader.LoaderPlugin#isReady + * @since 3.0.0 + * + * @return {boolean} `true` if the Loader is ready to start a new load, otherwise `false`. + */ + isReady: function () + { + return (this.state === CONST.LOADER_IDLE || this.state === CONST.LOADER_COMPLETE); + }, + + /** + * Starts the Loader running. This will reset the progress and totals and then emit a `start` event. + * If there is nothing in the queue the Loader will immediately complete, otherwise it will start + * loading the first batch of files. + * + * The Loader is started automatically if the queue is populated within your Scenes `preload` method. + * + * However, outside of this, you need to call this method to start it. + * + * If the Loader is already running this method will simply return. + * + * @method Phaser.Loader.LoaderPlugin#start + * @fires Phaser.Loader.Events#START + * @since 3.0.0 + */ + start: function () + { + if (!this.isReady()) + { + return; + } + + this.progress = 0; + + this.totalFailed = 0; + this.totalComplete = 0; + this.totalToLoad = this.list.size; + + this.emit(Events.START, this); + + if (this.list.size === 0) + { + this.loadComplete(); + } + else + { + this.state = CONST.LOADER_LOADING; + + this.inflight.clear(); + this.queue.clear(); + + this.updateProgress(); + + this.checkLoadQueue(); + + this.systems.events.on(SceneEvents.UPDATE, this.update, this); + } + }, + + /** + * Called automatically during the load process. + * It updates the `progress` value and then emits a progress event, which you can use to + * display a loading bar in your game. + * + * @method Phaser.Loader.LoaderPlugin#updateProgress + * @fires Phaser.Loader.Events#PROGRESS + * @since 3.0.0 + */ + updateProgress: function () + { + this.progress = 1 - ((this.list.size + this.inflight.size) / this.totalToLoad); + + this.emit(Events.PROGRESS, this.progress); + }, + + /** + * Called automatically during the load process. + * + * @method Phaser.Loader.LoaderPlugin#update + * @since 3.10.0 + */ + update: function () + { + if (this.state === CONST.LOADER_LOADING && this.list.size > 0 && this.inflight.size < this.maxParallelDownloads) + { + this.checkLoadQueue(); + } + }, + + /** + * An internal method called by the Loader. + * + * It will check to see if there are any more files in the pending list that need loading, and if so it will move + * them from the list Set into the inflight Set, set their CORs flag and start them loading. + * + * It will carrying on doing this for each file in the pending list until it runs out, or hits the max allowed parallel downloads. + * + * @method Phaser.Loader.LoaderPlugin#checkLoadQueue + * @private + * @since 3.7.0 + */ + checkLoadQueue: function () + { + this.list.forEach(function (file) + { + if (file.state === CONST.FILE_POPULATED || (file.state === CONST.FILE_PENDING && this.inflight.size < this.maxParallelDownloads)) + { + this.inflight.add(file); + + this.list.delete(file); + + // If the file doesn't have its own crossOrigin set, we'll use the Loaders (which is undefined by default) + if (!file.crossOrigin) + { + file.crossOrigin = this.crossOrigin; + } + + file.load(); + } + + if (this.inflight.size === this.maxParallelDownloads) + { + // Tells the Set iterator to abort + return false; + } + + }, this); + }, + + /** + * An internal method called automatically by the XHRLoader belonging to a File. + * + * This method will remove the given file from the inflight Set and update the load progress. + * If the file was successful its `onProcess` method is called, otherwise it is added to the delete queue. + * + * @method Phaser.Loader.LoaderPlugin#nextFile + * @fires Phaser.Loader.Events#FILE_LOAD + * @fires Phaser.Loader.Events#FILE_LOAD_ERROR + * @since 3.0.0 + * + * @param {Phaser.Loader.File} file - The File that just finished loading, or errored during load. + * @param {boolean} success - `true` if the file loaded successfully, otherwise `false`. + */ + nextFile: function (file, success) + { + // Has the game been destroyed during load? If so, bail out now. + if (!this.inflight) + { + return; + } + + this.inflight.delete(file); + + this.updateProgress(); + + if (success) + { + this.totalComplete++; + + this.queue.add(file); + + this.emit(Events.FILE_LOAD, file); + + file.onProcess(); + } + else + { + this.totalFailed++; + + this._deleteQueue.add(file); + + this.emit(Events.FILE_LOAD_ERROR, file); + + this.fileProcessComplete(file); + } + }, + + /** + * An internal method that is called automatically by the File when it has finished processing. + * + * If the process was successful, and the File isn't part of a MultiFile, its `addToCache` method is called. + * + * It is then removed from the queue. If there are no more files to load `loadComplete` is called. + * + * @method Phaser.Loader.LoaderPlugin#fileProcessComplete + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The file that has finished processing. + */ + fileProcessComplete: function (file) + { + // Has the game been destroyed during load? If so, bail out now. + if (!this.scene || !this.systems || !this.systems.game || this.systems.game.pendingDestroy) + { + return; + } + + // This file has failed, so move it to the failed Set + if (file.state === CONST.FILE_ERRORED) + { + if (file.multiFile) + { + file.multiFile.onFileFailed(file); + } + } + else if (file.state === CONST.FILE_COMPLETE) + { + if (file.multiFile) + { + if (file.multiFile.isReadyToProcess()) + { + // If we got here then all files the link file needs are ready to add to the cache + file.multiFile.addToCache(); + file.multiFile.pendingDestroy(); + } + } + else + { + // If we got here, then the file processed, so let it add itself to its cache + file.addToCache(); + file.pendingDestroy(); + } + } + + // Remove it from the queue + this.queue.delete(file); + + // Nothing left to do? + + if (this.list.size === 0 && this.inflight.size === 0 && this.queue.size === 0) + { + this.loadComplete(); + } + }, + + /** + * Called at the end when the load queue is exhausted and all files have either loaded or errored. + * By this point every loaded file will now be in its associated cache and ready for use. + * + * Also clears down the Sets, puts progress to 1 and clears the deletion queue. + * + * @method Phaser.Loader.LoaderPlugin#loadComplete + * @fires Phaser.Loader.Events#COMPLETE + * @fires Phaser.Loader.Events#POST_PROCESS + * @since 3.7.0 + */ + loadComplete: function () + { + this.emit(Events.POST_PROCESS, this); + + this.list.clear(); + this.inflight.clear(); + this.queue.clear(); + + this.progress = 1; + + this.state = CONST.LOADER_COMPLETE; + + this.systems.events.off(SceneEvents.UPDATE, this.update, this); + + // Call 'destroy' on each file ready for deletion + this._deleteQueue.forEach(function (file) + { + file.destroy(); + }); + + this._deleteQueue.clear(); + + this.emit(Events.COMPLETE, this, this.totalComplete, this.totalFailed); + }, + + /** + * Adds a File into the pending-deletion queue. + * + * @method Phaser.Loader.LoaderPlugin#flagForRemoval + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The File to be queued for deletion when the Loader completes. + */ + flagForRemoval: function (file) + { + this._deleteQueue.add(file); + }, + + /** + * Converts the given JSON data into a file that the browser then prompts you to download so you can save it locally. + * + * The data must be well formed JSON and ready-parsed, not a JavaScript object. + * + * @method Phaser.Loader.LoaderPlugin#saveJSON + * @since 3.0.0 + * + * @param {*} data - The JSON data, ready parsed. + * @param {string} [filename=file.json] - The name to save the JSON file as. + * + * @return {this} This Loader plugin. + */ + saveJSON: function (data, filename) + { + return this.save(JSON.stringify(data), filename); + }, + + /** + * Causes the browser to save the given data as a file to its default Downloads folder. + * + * Creates a DOM level anchor link, assigns it as being a `download` anchor, sets the href + * to be an ObjectURL based on the given data, and then invokes a click event. + * + * @method Phaser.Loader.LoaderPlugin#save + * @since 3.0.0 + * + * @param {*} data - The data to be saved. Will be passed through URL.createObjectURL. + * @param {string} [filename=file.json] - The filename to save the file as. + * @param {string} [filetype=application/json] - The file type to use when saving the file. Defaults to JSON. + * + * @return {this} This Loader plugin. + */ + save: function (data, filename, filetype) + { + if (filename === undefined) { filename = 'file.json'; } + if (filetype === undefined) { filetype = 'application/json'; } + + var blob = new Blob([ data ], { type: filetype }); + + var url = URL.createObjectURL(blob); + + var a = document.createElement('a'); + + a.download = filename; + a.textContent = 'Download ' + filename; + a.href = url; + a.click(); + + return this; + }, + + /** + * Resets the Loader. + * + * This will clear all lists and reset the base URL, path and prefix. + * + * Warning: If the Loader is currently downloading files, or has files in its queue, they will be aborted. + * + * @method Phaser.Loader.LoaderPlugin#reset + * @since 3.0.0 + */ + reset: function () + { + this.list.clear(); + this.inflight.clear(); + this.queue.clear(); + + var gameConfig = this.systems.game.config; + var sceneConfig = this.systems.settings.loader; + + this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL)); + this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath)); + this.setPrefix(GetFastValue(sceneConfig, 'prefix', gameConfig.loaderPrefix)); + + this.state = CONST.LOADER_IDLE; + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Loader.LoaderPlugin#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + this.reset(); + + this.state = CONST.LOADER_SHUTDOWN; + + this.removeAllListeners(); + + this.systems.events.off(SceneEvents.UPDATE, this.update, this); + this.systems.events.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Loader.LoaderPlugin#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.state = CONST.LOADER_DESTROYED; + + this.systems.events.off(SceneEvents.UPDATE, this.update, this); + this.systems.events.off(SceneEvents.START, this.pluginStart, this); + + this.list = null; + this.inflight = null; + this.queue = null; + + this.scene = null; + this.systems = null; + this.textureManager = null; + this.cacheManager = null; + this.sceneManager = null; + } + +}); + +PluginCache.register('Loader', LoaderPlugin, 'load'); + +module.exports = LoaderPlugin; + + +/***/ }), + +/***/ 3374: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Extend = __webpack_require__(79291); +var XHRSettings = __webpack_require__(92638); + +/** + * Takes two XHRSettings Objects and creates a new XHRSettings object from them. + * + * The new object is seeded by the values given in the global settings, but any setting in + * the local object overrides the global ones. + * + * @function Phaser.Loader.MergeXHRSettings + * @since 3.0.0 + * + * @param {Phaser.Types.Loader.XHRSettingsObject} global - The global XHRSettings object. + * @param {Phaser.Types.Loader.XHRSettingsObject} local - The local XHRSettings object. + * + * @return {Phaser.Types.Loader.XHRSettingsObject} A newly formed XHRSettings object. + */ +var MergeXHRSettings = function (global, local) +{ + var output = (global === undefined) ? XHRSettings() : Extend({}, global); + + if (local) + { + for (var setting in local) + { + if (local[setting] !== undefined) + { + output[setting] = local[setting]; + } + } + } + + return output; +}; + +module.exports = MergeXHRSettings; + + +/***/ }), + +/***/ 26430: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var Events = __webpack_require__(54899); + +/** + * @classdesc + * A MultiFile is a special kind of parent that contains two, or more, Files as children and looks after + * the loading and processing of them all. It is commonly extended and used as a base class for file types such as AtlasJSON or BitmapFont. + * + * You shouldn't create an instance of a MultiFile directly, but should extend it with your own class, setting a custom type and processing methods. + * + * @class MultiFile + * @memberof Phaser.Loader + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - The Loader that is going to load this File. + * @param {string} type - The file type string for sorting within the Loader. + * @param {string} key - The key of the file within the loader. + * @param {Phaser.Loader.File[]} files - An array of Files that make-up this MultiFile. + */ +var MultiFile = new Class({ + + initialize: + + function MultiFile (loader, type, key, files) + { + var finalFiles = []; + + // Clean out any potential 'null' or 'undefined' file entries + files.forEach(function (file) + { + if (file) + { + finalFiles.push(file); + } + }); + + /** + * A reference to the Loader that is going to load this file. + * + * @name Phaser.Loader.MultiFile#loader + * @type {Phaser.Loader.LoaderPlugin} + * @since 3.7.0 + */ + this.loader = loader; + + /** + * The file type string for sorting within the Loader. + * + * @name Phaser.Loader.MultiFile#type + * @type {string} + * @since 3.7.0 + */ + this.type = type; + + /** + * Unique cache key (unique within its file type) + * + * @name Phaser.Loader.MultiFile#key + * @type {string} + * @since 3.7.0 + */ + this.key = key; + + var loadKey = this.key; + + if (loader.prefix && loader.prefix !== '') + { + this.key = loader.prefix + loadKey; + } + + /** + * The current index being used by multi-file loaders to avoid key clashes. + * + * @name Phaser.Loader.MultiFile#multiKeyIndex + * @type {number} + * @private + * @since 3.20.0 + */ + this.multiKeyIndex = loader.multiKeyIndex++; + + /** + * Array of files that make up this MultiFile. + * + * @name Phaser.Loader.MultiFile#files + * @type {Phaser.Loader.File[]} + * @since 3.7.0 + */ + this.files = finalFiles; + + /** + * The current state of the file. One of the FILE_CONST values. + * + * @name Phaser.Loader.MultiFile#state + * @type {number} + * @since 3.60.0 + */ + this.state = CONST.FILE_PENDING; + + /** + * The completion status of this MultiFile. + * + * @name Phaser.Loader.MultiFile#complete + * @type {boolean} + * @default false + * @since 3.7.0 + */ + this.complete = false; + + /** + * The number of files to load. + * + * @name Phaser.Loader.MultiFile#pending + * @type {number} + * @since 3.7.0 + */ + + this.pending = finalFiles.length; + + /** + * The number of files that failed to load. + * + * @name Phaser.Loader.MultiFile#failed + * @type {number} + * @default 0 + * @since 3.7.0 + */ + this.failed = 0; + + /** + * A storage container for transient data that the loading files need. + * + * @name Phaser.Loader.MultiFile#config + * @type {any} + * @since 3.7.0 + */ + this.config = {}; + + /** + * A reference to the Loaders baseURL at the time this MultiFile was created. + * Used to populate child-files. + * + * @name Phaser.Loader.MultiFile#baseURL + * @type {string} + * @since 3.20.0 + */ + this.baseURL = loader.baseURL; + + /** + * A reference to the Loaders path at the time this MultiFile was created. + * Used to populate child-files. + * + * @name Phaser.Loader.MultiFile#path + * @type {string} + * @since 3.20.0 + */ + this.path = loader.path; + + /** + * A reference to the Loaders prefix at the time this MultiFile was created. + * Used to populate child-files. + * + * @name Phaser.Loader.MultiFile#prefix + * @type {string} + * @since 3.20.0 + */ + this.prefix = loader.prefix; + + // Link the files + for (var i = 0; i < finalFiles.length; i++) + { + finalFiles[i].multiFile = this; + } + }, + + /** + * Checks if this MultiFile is ready to process its children or not. + * + * @method Phaser.Loader.MultiFile#isReadyToProcess + * @since 3.7.0 + * + * @return {boolean} `true` if all children of this MultiFile have loaded, otherwise `false`. + */ + isReadyToProcess: function () + { + return (this.pending === 0 && this.failed === 0 && !this.complete); + }, + + /** + * Adds another child to this MultiFile, increases the pending count and resets the completion status. + * + * @method Phaser.Loader.MultiFile#addToMultiFile + * @since 3.7.0 + * + * @param {Phaser.Loader.File} files - The File to add to this MultiFile. + * + * @return {Phaser.Loader.MultiFile} This MultiFile instance. + */ + addToMultiFile: function (file) + { + this.files.push(file); + + file.multiFile = this; + + this.pending++; + + this.complete = false; + + return this; + }, + + /** + * Called by each File when it finishes loading. + * + * @method Phaser.Loader.MultiFile#onFileComplete + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The File that has completed processing. + */ + onFileComplete: function (file) + { + var index = this.files.indexOf(file); + + if (index !== -1) + { + this.pending--; + } + }, + + /** + * Called by each File that fails to load. + * + * @method Phaser.Loader.MultiFile#onFileFailed + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The File that has failed to load. + */ + onFileFailed: function (file) + { + var index = this.files.indexOf(file); + + if (index !== -1) + { + this.failed++; + + // eslint-disable-next-line no-console + console.error('File failed: %s "%s" (via %s "%s")', this.type, this.key, file.type, file.key); + } + }, + + /** + * Called once all children of this multi file have been added to their caches and is now + * ready for deletion from the Loader. + * + * It will emit a `filecomplete` event from the LoaderPlugin. + * + * @method Phaser.Loader.MultiFile#pendingDestroy + * @fires Phaser.Loader.Events#FILE_COMPLETE + * @fires Phaser.Loader.Events#FILE_KEY_COMPLETE + * @since 3.60.0 + */ + pendingDestroy: function () + { + if (this.state === CONST.FILE_PENDING_DESTROY) + { + return; + } + + var key = this.key; + var type = this.type; + + this.loader.emit(Events.FILE_COMPLETE, key, type); + this.loader.emit(Events.FILE_KEY_COMPLETE + type + '-' + key, key, type); + + this.loader.flagForRemoval(this); + + for (var i = 0; i < this.files.length; i++) + { + this.files[i].pendingDestroy(); + } + + this.state = CONST.FILE_PENDING_DESTROY; + }, + + /** + * Destroy this Multi File and any references it holds. + * + * @method Phaser.Loader.MultiFile#destroy + * @since 3.60.0 + */ + destroy: function () + { + this.loader = null; + this.files = null; + this.config = null; + } + +}); + +module.exports = MultiFile; + + +/***/ }), + +/***/ 84376: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MergeXHRSettings = __webpack_require__(3374); + +/** + * Creates a new XMLHttpRequest (xhr) object based on the given File and XHRSettings + * and starts the download of it. It uses the Files own XHRSettings and merges them + * with the global XHRSettings object to set the xhr values before download. + * + * @function Phaser.Loader.XHRLoader + * @since 3.0.0 + * + * @param {Phaser.Loader.File} file - The File to download. + * @param {Phaser.Types.Loader.XHRSettingsObject} globalXHRSettings - The global XHRSettings object. + * + * @return {XMLHttpRequest} The XHR object, or a FakeXHR Object in the base of base64 data. + */ +var XHRLoader = function (file, globalXHRSettings) +{ + var config = MergeXHRSettings(globalXHRSettings, file.xhrSettings); + + if (file.base64) + { + var base64Data = file.url.split(';base64,').pop() || file.url.split(',').pop(); + + var fakeXHR = { + responseText: atob(base64Data) + }; + + file.onBase64Load(fakeXHR); + + return; + } + + var xhr = new XMLHttpRequest(); + + xhr.open('GET', file.src, config.async, config.user, config.password); + + xhr.responseType = file.xhrSettings.responseType; + xhr.timeout = config.timeout; + + if (config.headers) + { + for (var key in config.headers) + { + xhr.setRequestHeader(key, config.headers[key]); + } + } + + if (config.header && config.headerValue) + { + xhr.setRequestHeader(config.header, config.headerValue); + } + + if (config.requestedWith) + { + xhr.setRequestHeader('X-Requested-With', config.requestedWith); + } + + if (config.overrideMimeType) + { + xhr.overrideMimeType(config.overrideMimeType); + } + + if (config.withCredentials) + { + xhr.withCredentials = true; + } + + // After a successful request, the xhr.response property will contain the requested data as a DOMString, ArrayBuffer, Blob, or Document (depending on what was set for responseType.) + + xhr.onload = file.onLoad.bind(file, xhr); + xhr.onerror = file.onError.bind(file, xhr); + xhr.onprogress = file.onProgress.bind(file); + xhr.ontimeout = file.onError.bind(file, xhr); + + // This is the only standard method, the ones above are browser additions (maybe not universal?) + // xhr.onreadystatechange + + xhr.send(); + + return xhr; +}; + +module.exports = XHRLoader; + + +/***/ }), + +/***/ 92638: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Creates an XHRSettings Object with default values. + * + * @function Phaser.Loader.XHRSettings + * @since 3.0.0 + * + * @param {XMLHttpRequestResponseType} [responseType=''] - The responseType, such as 'text'. + * @param {boolean} [async=true] - Should the XHR request use async or not? + * @param {string} [user=''] - Optional username for the XHR request. + * @param {string} [password=''] - Optional password for the XHR request. + * @param {number} [timeout=0] - Optional XHR timeout value. + * @param {boolean} [withCredentials=false] - Optional XHR withCredentials value. + * + * @return {Phaser.Types.Loader.XHRSettingsObject} The XHRSettings object as used by the Loader. + */ +var XHRSettings = function (responseType, async, user, password, timeout, withCredentials) +{ + if (responseType === undefined) { responseType = ''; } + if (async === undefined) { async = true; } + if (user === undefined) { user = ''; } + if (password === undefined) { password = ''; } + if (timeout === undefined) { timeout = 0; } + if (withCredentials === undefined) { withCredentials = false; } + + // Before sending a request, set the xhr.responseType to "text", + // "arraybuffer", "blob", or "document", depending on your data needs. + // Note, setting xhr.responseType = '' (or omitting) will default the response to "text". + + return { + + // Ignored by the Loader, only used by File. + responseType: responseType, + + async: async, + + // credentials + user: user, + password: password, + + // timeout in ms (0 = no timeout) + timeout: timeout, + + // setRequestHeader + headers: undefined, + header: undefined, + headerValue: undefined, + requestedWith: false, + + // overrideMimeType + overrideMimeType: undefined, + + // withCredentials + withCredentials: withCredentials + + }; +}; + +module.exports = XHRSettings; + + +/***/ }), + +/***/ 23906: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FILE_CONST = { + + /** + * The Loader is idle. + * + * @name Phaser.Loader.LOADER_IDLE + * @type {number} + * @since 3.0.0 + */ + LOADER_IDLE: 0, + + /** + * The Loader is actively loading. + * + * @name Phaser.Loader.LOADER_LOADING + * @type {number} + * @since 3.0.0 + */ + LOADER_LOADING: 1, + + /** + * The Loader is processing files is has loaded. + * + * @name Phaser.Loader.LOADER_PROCESSING + * @type {number} + * @since 3.0.0 + */ + LOADER_PROCESSING: 2, + + /** + * The Loader has completed loading and processing. + * + * @name Phaser.Loader.LOADER_COMPLETE + * @type {number} + * @since 3.0.0 + */ + LOADER_COMPLETE: 3, + + /** + * The Loader is shutting down. + * + * @name Phaser.Loader.LOADER_SHUTDOWN + * @type {number} + * @since 3.0.0 + */ + LOADER_SHUTDOWN: 4, + + /** + * The Loader has been destroyed. + * + * @name Phaser.Loader.LOADER_DESTROYED + * @type {number} + * @since 3.0.0 + */ + LOADER_DESTROYED: 5, + + /** + * File is in the load queue but not yet started. + * + * @name Phaser.Loader.FILE_PENDING + * @type {number} + * @since 3.0.0 + */ + FILE_PENDING: 10, + + /** + * File has been started to load by the loader (onLoad called) + * + * @name Phaser.Loader.FILE_LOADING + * @type {number} + * @since 3.0.0 + */ + FILE_LOADING: 11, + + /** + * File has loaded successfully, awaiting processing. + * + * @name Phaser.Loader.FILE_LOADED + * @type {number} + * @since 3.0.0 + */ + FILE_LOADED: 12, + + /** + * File failed to load. + * + * @name Phaser.Loader.FILE_FAILED + * @type {number} + * @since 3.0.0 + */ + FILE_FAILED: 13, + + /** + * File is being processed (onProcess callback) + * + * @name Phaser.Loader.FILE_PROCESSING + * @type {number} + * @since 3.0.0 + */ + FILE_PROCESSING: 14, + + /** + * The File has errored somehow during processing. + * + * @name Phaser.Loader.FILE_ERRORED + * @type {number} + * @since 3.0.0 + */ + FILE_ERRORED: 16, + + /** + * File has finished processing. + * + * @name Phaser.Loader.FILE_COMPLETE + * @type {number} + * @since 3.0.0 + */ + FILE_COMPLETE: 17, + + /** + * File has been destroyed. + * + * @name Phaser.Loader.FILE_DESTROYED + * @type {number} + * @since 3.0.0 + */ + FILE_DESTROYED: 18, + + /** + * File was populated from local data and doesn't need an HTTP request. + * + * @name Phaser.Loader.FILE_POPULATED + * @type {number} + * @since 3.0.0 + */ + FILE_POPULATED: 19, + + /** + * File is pending being destroyed. + * + * @name Phaser.Loader.FILE_PENDING_DESTROY + * @type {number} + * @since 3.60.0 + */ + FILE_PENDING_DESTROY: 20 + +}; + +module.exports = FILE_CONST; + + +/***/ }), + +/***/ 42155: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Loader Plugin Add File Event. + * + * This event is dispatched when a new file is successfully added to the Loader and placed into the load queue. + * + * Listen to it from a Scene using: `this.load.on('addfile', listener)`. + * + * If you add lots of files to a Loader from a `preload` method, it will dispatch this event for each one of them. + * + * @event Phaser.Loader.Events#ADD + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The unique key of the file that was added to the Loader. + * @param {string} type - The [file type]{@link Phaser.Loader.File#type} string of the file that was added to the Loader, i.e. `image`. + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event. + * @param {Phaser.Loader.File} file - A reference to the File which was added to the Loader. + */ +module.exports = 'addfile'; + + +/***/ }), + +/***/ 38991: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Loader Plugin Complete Event. + * + * This event is dispatched when the Loader has fully processed everything in the load queue. + * By this point every loaded file will now be in its associated cache and ready for use. + * + * Listen to it from a Scene using: `this.load.on('complete', listener)`. + * + * @event Phaser.Loader.Events#COMPLETE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event. + * @param {number} totalComplete - The total number of files that successfully loaded. + * @param {number} totalFailed - The total number of files that failed to load. + */ +module.exports = 'complete'; + + +/***/ }), + +/***/ 27540: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The File Load Complete Event. + * + * This event is dispatched by the Loader Plugin when _any_ file in the queue finishes loading. + * + * Listen to it from a Scene using: `this.load.on('filecomplete', listener)`. + * + * Make sure you remove this listener when you have finished, or it will continue to fire if the Scene reloads. + * + * You can also listen for the completion of a specific file. See the [FILE_KEY_COMPLETE]{@linkcode Phaser.Loader.Events#event:FILE_KEY_COMPLETE} event. + * + * @event Phaser.Loader.Events#FILE_COMPLETE + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the file that just loaded and finished processing. + * @param {string} type - The [file type]{@link Phaser.Loader.File#type} of the file that just loaded, i.e. `image`. + * @param {any} [data] - The raw data the file contained. If the file was a multi-file, like an atlas or bitmap font, this parameter will be undefined. + */ +module.exports = 'filecomplete'; + + +/***/ }), + +/***/ 87464: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The File Load Complete Event. + * + * This event is dispatched by the Loader Plugin when any file in the queue finishes loading. + * + * It uses a special dynamic event name constructed from the key and type of the file. + * + * For example, if you have loaded an `image` with a key of `monster`, you can listen for it + * using the following: + * + * ```javascript + * this.load.on('filecomplete-image-monster', function (key, type, data) { + * // Your handler code + * }); + * ``` + * + * Or, if you have loaded a texture `atlas` with a key of `Level1`: + * + * ```javascript + * this.load.on('filecomplete-atlasjson-Level1', function (key, type, data) { + * // Your handler code + * }); + * ``` + * + * Or, if you have loaded a sprite sheet with a key of `Explosion` and a prefix of `GAMEOVER`: + * + * ```javascript + * this.load.on('filecomplete-spritesheet-GAMEOVERExplosion', function (key, type, data) { + * // Your handler code + * }); + * ``` + * + * Make sure you remove your listeners when you have finished, or they will continue to fire if the Scene reloads. + * + * You can also listen for the generic completion of files. See the [FILE_COMPLETE]{@linkcode Phaser.Loader.Events#event:FILE_COMPLETE} event. + * + * @event Phaser.Loader.Events#FILE_KEY_COMPLETE + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the file that just loaded and finished processing. + * @param {string} type - The [file type]{@link Phaser.Loader.File#type} of the file that just loaded, i.e. `image`. + * @param {any} [data] - The raw data the file contained. If the file was a multi-file, like an atlas or bitmap font, this parameter will be undefined. + */ +module.exports = 'filecomplete-'; + + +/***/ }), + +/***/ 94486: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The File Load Error Event. + * + * This event is dispatched by the Loader Plugin when a file fails to load. + * + * Listen to it from a Scene using: `this.load.on('loaderror', listener)`. + * + * @event Phaser.Loader.Events#FILE_LOAD_ERROR + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Loader.File} file - A reference to the File which errored during load. + */ +module.exports = 'loaderror'; + + +/***/ }), + +/***/ 13035: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The File Load Event. + * + * This event is dispatched by the Loader Plugin when a file finishes loading, + * but _before_ it is processed and added to the internal Phaser caches. + * + * Listen to it from a Scene using: `this.load.on('load', listener)`. + * + * @event Phaser.Loader.Events#FILE_LOAD + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Loader.File} file - A reference to the File which just finished loading. + */ +module.exports = 'load'; + + +/***/ }), + +/***/ 38144: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The File Load Progress Event. + * + * This event is dispatched by the Loader Plugin during the load of a file, if the browser receives a DOM ProgressEvent and + * the `lengthComputable` event property is true. Depending on the size of the file and browser in use, this may, or may not happen. + * + * Listen to it from a Scene using: `this.load.on('fileprogress', listener)`. + * + * @event Phaser.Loader.Events#FILE_PROGRESS + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Loader.File} file - A reference to the File which errored during load. + * @param {number} percentComplete - A value between 0 and 1 indicating how 'complete' this file is. + */ +module.exports = 'fileprogress'; + + +/***/ }), + +/***/ 97520: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Loader Plugin Post Process Event. + * + * This event is dispatched by the Loader Plugin when the Loader has finished loading everything in the load queue. + * It is dispatched before the internal lists are cleared and each File is destroyed. + * + * Use this hook to perform any last minute processing of files that can only happen once the + * Loader has completed, but prior to it emitting the `complete` event. + * + * Listen to it from a Scene using: `this.load.on('postprocess', listener)`. + * + * @event Phaser.Loader.Events#POST_PROCESS + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event. + */ +module.exports = 'postprocess'; + + +/***/ }), + +/***/ 85595: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Loader Plugin Progress Event. + * + * This event is dispatched when the Loader updates its load progress, typically as a result of a file having completed loading. + * + * Listen to it from a Scene using: `this.load.on('progress', listener)`. + * + * @event Phaser.Loader.Events#PROGRESS + * @type {string} + * @since 3.0.0 + * + * @param {number} progress - The current progress of the load. A value between 0 and 1. + */ +module.exports = 'progress'; + + +/***/ }), + +/***/ 55680: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Loader Plugin Start Event. + * + * This event is dispatched when the Loader starts running. At this point load progress is zero. + * + * This event is dispatched even if there aren't any files in the load queue. + * + * Listen to it from a Scene using: `this.load.on('start', listener)`. + * + * @event Phaser.Loader.Events#START + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event. + */ +module.exports = 'start'; + + +/***/ }), + +/***/ 54899: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Loader.Events + */ + +module.exports = { + + ADD: __webpack_require__(42155), + COMPLETE: __webpack_require__(38991), + FILE_COMPLETE: __webpack_require__(27540), + FILE_KEY_COMPLETE: __webpack_require__(87464), + FILE_LOAD_ERROR: __webpack_require__(94486), + FILE_LOAD: __webpack_require__(13035), + FILE_PROGRESS: __webpack_require__(38144), + POST_PROCESS: __webpack_require__(97520), + PROGRESS: __webpack_require__(85595), + START: __webpack_require__(55680) + +}; + + +/***/ }), + +/***/ 14135: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var JSONFile = __webpack_require__(518); +var LoaderEvents = __webpack_require__(54899); + +/** + * @classdesc + * A single Animation JSON File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#animation method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#animation. + * + * @class AnimationJSONFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + * @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache. + */ +var AnimationJSONFile = new Class({ + + Extends: JSONFile, + + initialize: + + // url can either be a string, in which case it is treated like a proper url, or an object, in which case it is treated as a ready-made JS Object + // dataKey allows you to pluck a specific object out of the JSON and put just that into the cache, rather than the whole thing + + function AnimationJSONFile (loader, key, url, xhrSettings, dataKey) + { + JSONFile.call(this, loader, key, url, xhrSettings, dataKey); + + this.type = 'animationJSON'; + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.AnimationJSONFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + // We need to hook into this event: + this.loader.once(LoaderEvents.POST_PROCESS, this.onLoadComplete, this); + + // But the rest is the same as a normal JSON file + JSONFile.prototype.onProcess.call(this); + }, + + /** + * Called at the end of the load process, after the Loader has finished all files in its queue. + * + * @method Phaser.Loader.FileTypes.AnimationJSONFile#onLoadComplete + * @since 3.7.0 + */ + onLoadComplete: function () + { + this.loader.systems.anims.fromJSON(this.data); + } + +}); + +/** + * Adds an Animation JSON Data file, or array of Animation JSON files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.animation('baddieAnims', 'files/BaddieAnims.json'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * The key must be a unique String. It is used to add the file to the global JSON Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the JSON Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the JSON Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.animation({ + * key: 'baddieAnims', + * url: 'files/BaddieAnims.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.JSONFileConfig` for more details. + * + * Once the file has finished loading it will automatically be passed to the global Animation Managers `fromJSON` method. + * This will parse all of the JSON data and create animation data from it. This process happens at the very end + * of the Loader, once every other file in the load queue has finished. The reason for this is to allow you to load + * both animation data and the images it relies upon in the same load call. + * + * Once the animation data has been parsed you will be able to play animations using that data. + * Please see the Animation Manager `fromJSON` method for more details about the format and playback. + * + * You can also access the raw animation data from its Cache using its key: + * + * ```javascript + * this.load.animation('baddieAnims', 'files/BaddieAnims.json'); + * // and later in your game ... + * var data = this.cache.json.get('baddieAnims'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Waves` the final key will be `LEVEL1.Waves` and + * this is what you would use to retrieve the text from the JSON Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "data" + * and no URL is given then the Loader will set the URL to be "data.json". It will always add `.json` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * You can also optionally provide a `dataKey` to use. This allows you to extract only a part of the JSON and store it in the Cache, + * rather than the whole file. For example, if your JSON data had a structure like this: + * + * ```json + * { + * "level1": { + * "baddies": { + * "aliens": {}, + * "boss": {} + * } + * }, + * "level2": {}, + * "level3": {} + * } + * ``` + * + * And if you only wanted to create animations from the `boss` data, then you could pass `level1.baddies.boss`as the `dataKey`. + * + * Note: The ability to load this type of file will only be available if the JSON File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#animation + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig|Phaser.Types.Loader.FileTypes.JSONFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {string} [dataKey] - When the Animation JSON file loads only this property will be stored in the Cache and used to create animation data. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('animation', function (key, url, dataKey, xhrSettings) +{ + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + this.addFile(new AnimationJSONFile(this, key[i])); + } + } + else + { + this.addFile(new AnimationJSONFile(this, key, url, xhrSettings, dataKey)); + } + + return this; +}); + +module.exports = AnimationJSONFile; + + +/***/ }), + +/***/ 76272: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var JSONFile = __webpack_require__(518); +var MultiFile = __webpack_require__(26430); + +/** + * @classdesc + * A single JSON based Texture Atlas File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#atlas method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#atlas. + * + * https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3?source=photonstorm + * + * @class AsepriteFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.50.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.AsepriteFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {object|string} [atlasURL] - The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, a well formed JSON object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas json file. Used in replacement of the Loaders default XHR Settings. + */ +var AsepriteFile = new Class({ + + Extends: MultiFile, + + initialize: + + function AsepriteFile (loader, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) + { + var image; + var data; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + + image = new ImageFile(loader, { + key: key, + url: GetFastValue(config, 'textureURL'), + extension: GetFastValue(config, 'textureExtension', 'png'), + normalMap: GetFastValue(config, 'normalMap'), + xhrSettings: GetFastValue(config, 'textureXhrSettings') + }); + + data = new JSONFile(loader, { + key: key, + url: GetFastValue(config, 'atlasURL'), + extension: GetFastValue(config, 'atlasExtension', 'json'), + xhrSettings: GetFastValue(config, 'atlasXhrSettings') + }); + } + else + { + image = new ImageFile(loader, key, textureURL, textureXhrSettings); + data = new JSONFile(loader, key, atlasURL, atlasXhrSettings); + } + + if (image.linkFile) + { + // Image has a normal map + MultiFile.call(this, loader, 'atlasjson', key, [ image, data, image.linkFile ]); + } + else + { + MultiFile.call(this, loader, 'atlasjson', key, [ image, data ]); + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.AsepriteFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var image = this.files[0]; + var json = this.files[1]; + var normalMap = (this.files[2]) ? this.files[2].data : null; + + this.loader.textureManager.addAtlas(image.key, image.data, json.data, normalMap); + + json.addToCache(); + + this.complete = true; + } + } + +}); + +/** + * Aseprite is a powerful animated sprite editor and pixel art tool. + * + * You can find more details at https://www.aseprite.org/ + * + * Adds a JSON based Aseprite Animation, or array of animations, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.aseprite('gladiator', 'images/Gladiator.png', 'images/Gladiator.json'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * To export a compatible JSON file in Aseprite, please do the following: + * + * 1. Go to "File - Export Sprite Sheet" + * + * 2. On the **Layout** tab: + * 2a. Set the "Sheet type" to "Packed" + * 2b. Set the "Constraints" to "None" + * 2c. Check the "Merge Duplicates" checkbox + * + * 3. On the **Sprite** tab: + * 3a. Set "Layers" to "Visible layers" + * 3b. Set "Frames" to "All frames", unless you only wish to export a sub-set of tags + * + * 4. On the **Borders** tab: + * 4a. Check the "Trim Sprite" and "Trim Cells" options + * 4b. Ensure "Border Padding", "Spacing" and "Inner Padding" are all > 0 (1 is usually enough) + * + * 5. On the **Output** tab: + * 5a. Check "Output File", give your image a name and make sure you choose "png files" as the file type + * 5b. Check "JSON Data" and give your json file a name + * 5c. The JSON Data type can be either a Hash or Array, Phaser doesn't mind. + * 5d. Make sure "Tags" is checked in the Meta options + * 5e. In the "Item Filename" input box, make sure it says just "{frame}" and nothing more. + * + * 6. Click export + * + * This was tested with Aseprite 1.2.25. + * + * This will export a png and json file which you can load using the Aseprite Loader, i.e.: + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.aseprite({ + * key: 'gladiator', + * textureURL: 'images/Gladiator.png', + * atlasURL: 'images/Gladiator.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.AsepriteFileConfig` for more details. + * + * Instead of passing a URL for the JSON data you can also pass in a well formed JSON object instead. + * + * Once loaded, you can call this method from within a Scene with the 'atlas' key: + * + * ```javascript + * this.anims.createFromAseprite('paladin'); + * ``` + * + * Any animations defined in the JSON will now be available to use in Phaser and you play them + * via their Tag name. For example, if you have an animation called 'War Cry' on your Aseprite timeline, + * you can play it in Phaser using that Tag name: + * + * ```javascript + * this.add.sprite(400, 300).play('War Cry'); + * ``` + * + * When calling this method you can optionally provide an array of tag names, and only those animations + * will be created. For example: + * + * ```javascript + * this.anims.createFromAseprite('paladin', [ 'step', 'War Cry', 'Magnum Break' ]); + * ``` + * + * This will only create the 3 animations defined. Note that the tag names are case-sensitive. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Aseprite File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#aseprite + * @fires Phaser.Loader.Events#ADD + * @since 3.50.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.AsepriteFileConfig|Phaser.Types.Loader.FileTypes.AsepriteFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {object|string} [atlasURL] - The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, a well formed JSON object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas json file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('aseprite', function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new AsepriteFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new AsepriteFile(this, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = AsepriteFile; + + +/***/ }), + +/***/ 38734: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var JSONFile = __webpack_require__(518); +var MultiFile = __webpack_require__(26430); + +/** + * @classdesc + * A single JSON based Texture Atlas File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#atlas method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#atlas. + * + * https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3?source=photonstorm + * + * @class AtlasJSONFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {object|string} [atlasURL] - The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, a well formed JSON object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas json file. Used in replacement of the Loaders default XHR Settings. + */ +var AtlasJSONFile = new Class({ + + Extends: MultiFile, + + initialize: + + function AtlasJSONFile (loader, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) + { + var image; + var data; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + + image = new ImageFile(loader, { + key: key, + url: GetFastValue(config, 'textureURL'), + extension: GetFastValue(config, 'textureExtension', 'png'), + normalMap: GetFastValue(config, 'normalMap'), + xhrSettings: GetFastValue(config, 'textureXhrSettings') + }); + + data = new JSONFile(loader, { + key: key, + url: GetFastValue(config, 'atlasURL'), + extension: GetFastValue(config, 'atlasExtension', 'json'), + xhrSettings: GetFastValue(config, 'atlasXhrSettings') + }); + } + else + { + image = new ImageFile(loader, key, textureURL, textureXhrSettings); + data = new JSONFile(loader, key, atlasURL, atlasXhrSettings); + } + + if (image.linkFile) + { + // Image has a normal map + MultiFile.call(this, loader, 'atlasjson', key, [ image, data, image.linkFile ]); + } + else + { + MultiFile.call(this, loader, 'atlasjson', key, [ image, data ]); + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.AtlasJSONFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var image = this.files[0]; + var json = this.files[1]; + var normalMap = (this.files[2]) ? this.files[2].data : null; + + this.loader.textureManager.addAtlas(image.key, image.data, json.data, normalMap); + + this.complete = true; + } + } + +}); + +/** + * Adds a JSON based Texture Atlas, or array of atlases, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.atlas('mainmenu', 'images/MainMenu.png', 'images/MainMenu.json'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * Phaser expects the atlas data to be provided in a JSON file, using either the JSON Hash or JSON Array format. + * + * These files are created by software such as: + * + * * [Texture Packer](https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3?source=photonstorm) + * * [Shoebox](https://renderhjs.net/shoebox/) + * * [Gamma Texture Packer](https://gammafp.com/tool/atlas-packer/) + * * [Adobe Flash / Animate](https://www.adobe.com/uk/products/animate.html) + * * [Free Texture Packer](http://free-tex-packer.com/) + * * [Leshy SpriteSheet Tool](https://www.leshylabs.com/apps/sstool/) + * + * If you are using Texture Packer and have enabled multi-atlas support, then please use the Phaser Multi Atlas loader + * instead of this one. + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.atlas({ + * key: 'mainmenu', + * textureURL: 'images/MainMenu.png', + * atlasURL: 'images/MainMenu.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig` for more details. + * + * Instead of passing a URL for the atlas JSON data you can also pass in a well formed JSON object instead. + * + * Once the atlas has finished loading you can use frames from it as textures for a Game Object by referencing its key: + * + * ```javascript + * this.load.atlas('mainmenu', 'images/MainMenu.png', 'images/MainMenu.json'); + * // and later in your game ... + * this.add.image(x, y, 'mainmenu', 'background'); + * ``` + * + * To get a list of all available frames within an atlas please consult your Texture Atlas software. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image, + * then you can specify it by providing an array as the `url` where the second element is the normal map: + * + * ```javascript + * this.load.atlas('mainmenu', [ 'images/MainMenu.png', 'images/MainMenu-n.png' ], 'images/MainMenu.json'); + * ``` + * + * Or, if you are using a config object use the `normalMap` property: + * + * ```javascript + * this.load.atlas({ + * key: 'mainmenu', + * textureURL: 'images/MainMenu.png', + * normalMap: 'images/MainMenu-n.png', + * atlasURL: 'images/MainMenu.json' + * }); + * ``` + * + * The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings. + * Normal maps are a WebGL only feature. + * + * Note: The ability to load this type of file will only be available if the Atlas JSON File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#atlas + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig|Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {object|string} [atlasURL] - The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, a well formed JSON object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas json file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('atlas', function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new AtlasJSONFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new AtlasJSONFile(this, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = AtlasJSONFile; + + +/***/ }), + +/***/ 74599: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var MultiFile = __webpack_require__(26430); +var XMLFile = __webpack_require__(57318); + +/** + * @classdesc + * A single XML based Texture Atlas File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#atlasXML method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#atlasXML. + * + * @class AtlasXMLFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas xml data file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was "alien" then the URL will be "alien.xml". + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas xml file. Used in replacement of the Loaders default XHR Settings. + */ +var AtlasXMLFile = new Class({ + + Extends: MultiFile, + + initialize: + + function AtlasXMLFile (loader, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) + { + var image; + var data; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + + image = new ImageFile(loader, { + key: key, + url: GetFastValue(config, 'textureURL'), + extension: GetFastValue(config, 'textureExtension', 'png'), + normalMap: GetFastValue(config, 'normalMap'), + xhrSettings: GetFastValue(config, 'textureXhrSettings') + }); + + data = new XMLFile(loader, { + key: key, + url: GetFastValue(config, 'atlasURL'), + extension: GetFastValue(config, 'atlasExtension', 'xml'), + xhrSettings: GetFastValue(config, 'atlasXhrSettings') + }); + } + else + { + image = new ImageFile(loader, key, textureURL, textureXhrSettings); + data = new XMLFile(loader, key, atlasURL, atlasXhrSettings); + } + + if (image.linkFile) + { + // Image has a normal map + MultiFile.call(this, loader, 'atlasxml', key, [ image, data, image.linkFile ]); + } + else + { + MultiFile.call(this, loader, 'atlasxml', key, [ image, data ]); + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.AtlasXMLFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var image = this.files[0]; + var xml = this.files[1]; + var normalMap = (this.files[2]) ? this.files[2].data : null; + + this.loader.textureManager.addAtlasXML(image.key, image.data, xml.data, normalMap); + + this.complete = true; + } + } + +}); + +/** + * Adds an XML based Texture Atlas, or array of atlases, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.atlasXML('mainmenu', 'images/MainMenu.png', 'images/MainMenu.xml'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * Phaser expects the atlas data to be provided in an XML file format. + * These files are created by software such as Shoebox and Adobe Flash / Animate. + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.atlasXML({ + * key: 'mainmenu', + * textureURL: 'images/MainMenu.png', + * atlasURL: 'images/MainMenu.xml' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig` for more details. + * + * Once the atlas has finished loading you can use frames from it as textures for a Game Object by referencing its key: + * + * ```javascript + * this.load.atlasXML('mainmenu', 'images/MainMenu.png', 'images/MainMenu.xml'); + * // and later in your game ... + * this.add.image(x, y, 'mainmenu', 'background'); + * ``` + * + * To get a list of all available frames within an atlas please consult your Texture Atlas software. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image, + * then you can specify it by providing an array as the `url` where the second element is the normal map: + * + * ```javascript + * this.load.atlasXML('mainmenu', [ 'images/MainMenu.png', 'images/MainMenu-n.png' ], 'images/MainMenu.xml'); + * ``` + * + * Or, if you are using a config object use the `normalMap` property: + * + * ```javascript + * this.load.atlasXML({ + * key: 'mainmenu', + * textureURL: 'images/MainMenu.png', + * normalMap: 'images/MainMenu-n.png', + * atlasURL: 'images/MainMenu.xml' + * }); + * ``` + * + * The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings. + * Normal maps are a WebGL only feature. + * + * Note: The ability to load this type of file will only be available if the Atlas XML File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#atlasXML + * @fires Phaser.Loader.Events#ADD + * @since 3.7.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig|Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas xml data file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was "alien" then the URL will be "alien.xml". + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas xml file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('atlasXML', function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new AtlasXMLFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new AtlasXMLFile(this, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = AtlasXMLFile; + + +/***/ }), + +/***/ 21097: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var HTML5AudioFile = __webpack_require__(89749); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Audio File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#audio method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#audio. + * + * @class AudioFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.AudioFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {Phaser.Types.Loader.FileTypes.AudioFileURLConfig} [urlConfig] - The absolute or relative URL to load this file from in a config object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + * @param {AudioContext} [audioContext] - The AudioContext this file will use to process itself. + */ +var AudioFile = new Class({ + + Extends: File, + + initialize: + + // URL is an object created by AudioFile.findAudioURL + function AudioFile (loader, key, urlConfig, xhrSettings, audioContext) + { + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + audioContext = GetFastValue(config, 'context', audioContext); + } + + var fileConfig = { + type: 'audio', + cache: loader.cacheManager.audio, + extension: urlConfig.type, + responseType: 'arraybuffer', + key: key, + url: urlConfig.url, + xhrSettings: xhrSettings, + config: { context: audioContext } + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.AudioFile#onProcess + * @since 3.0.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + var _this = this; + + // interesting read https://github.com/WebAudio/web-audio-api/issues/1305 + this.config.context.decodeAudioData(this.xhrLoader.response, + function (audioBuffer) + { + _this.data = audioBuffer; + + _this.onProcessComplete(); + }, + function (e) + { + // eslint-disable-next-line no-console + console.error('Error decoding audio: ' + _this.key + ' - ', e ? e.message : null); + + _this.onProcessError(); + } + ); + + this.config.context = null; + } + +}); + +AudioFile.create = function (loader, key, urls, config, xhrSettings) +{ + var game = loader.systems.game; + var audioConfig = game.config.audio; + var deviceAudio = game.device.audio; + + // url may be inside key, which may be an object + if (IsPlainObject(key)) + { + urls = GetFastValue(key, 'url', []); + config = GetFastValue(key, 'config', {}); + } + + var urlConfig = AudioFile.getAudioURL(game, urls); + + if (!urlConfig) + { + console.warn('No audio URLs for "%s" can play on this device', key); + + return null; + } + + // https://developers.google.com/web/updates/2012/02/HTML5-audio-and-the-Web-Audio-API-are-BFFs + // var stream = GetFastValue(config, 'stream', false); + + if (deviceAudio.webAudio && !audioConfig.disableWebAudio) + { + return new AudioFile(loader, key, urlConfig, xhrSettings, game.sound.context); + } + else + { + return new HTML5AudioFile(loader, key, urlConfig, config); + } +}; + +AudioFile.getAudioURL = function (game, urls) +{ + if (!Array.isArray(urls)) + { + urls = [ urls ]; + } + + for (var i = 0; i < urls.length; i++) + { + var url = GetFastValue(urls[i], 'url', urls[i]); + + if (url.indexOf('blob:') === 0 || url.indexOf('data:') === 0) + { + return { + url: url, + type: '' + }; + } + + var audioType = url.match(/\.([a-zA-Z0-9]+)($|\?)/); + + audioType = GetFastValue(urls[i], 'type', (audioType) ? audioType[1] : '').toLowerCase(); + + if (game.device.audio[audioType]) + { + return { + url: url, + type: audioType + }; + } + } + + return null; +}; + +/** + * Adds an Audio or HTML5Audio file, or array of audio files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.audio('title', [ 'music/Title.ogg', 'music/Title.mp3', 'music/Title.m4a' ]); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Audio Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Audio Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Audio Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.audio({ + * key: 'title', + * url: [ 'music/Title.ogg', 'music/Title.mp3', 'music/Title.m4a' ] + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.AudioFileConfig` for more details. + * + * The URLs can be relative or absolute. If the URLs are relative the `Loader.baseURL` and `Loader.path` values will be prepended to them. + * + * Due to different browsers supporting different audio file types you should usually provide your audio files in a variety of formats. + * ogg, mp3 and m4a are the most common. If you provide an array of URLs then the Loader will determine which _one_ file to load based on + * browser support. + * + * If audio has been disabled in your game, either via the game config, or lack of support from the device, then no audio will be loaded. + * + * Note: The ability to load this type of file will only be available if the Audio File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#audio + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.AudioFileConfig|Phaser.Types.Loader.FileTypes.AudioFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {(string|string[]|Phaser.Types.Loader.FileTypes.AudioFileURLConfig|Phaser.Types.Loader.FileTypes.AudioFileURLConfig[])} [urls] - The absolute or relative URL to load the audio files from. + * @param {any} [config] - An object containing an `instances` property for HTML5Audio. Defaults to 1. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('audio', function (key, urls, config, xhrSettings) +{ + var game = this.systems.game; + var audioConfig = game.config.audio; + var deviceAudio = game.device.audio; + + if (audioConfig.noAudio || (!deviceAudio.webAudio && !deviceAudio.audioData)) + { + // Sounds are disabled, so skip loading audio + return this; + } + + var audioFile; + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + audioFile = AudioFile.create(this, key[i]); + + if (audioFile) + { + this.addFile(audioFile); + } + } + } + else + { + audioFile = AudioFile.create(this, key, urls, config, xhrSettings); + + if (audioFile) + { + this.addFile(audioFile); + } + } + + return this; +}); + +module.exports = AudioFile; + + +/***/ }), + +/***/ 89524: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AudioFile = __webpack_require__(21097); +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); +var JSONFile = __webpack_require__(518); +var MultiFile = __webpack_require__(26430); + +/** + * @classdesc + * An Audio Sprite File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#audioSprite method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#audioSprite. + * + * @class AudioSpriteFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.AudioSpriteFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} jsonURL - The absolute or relative URL to load the json file from. Or a well formed JSON object to use instead. + * @param {{(string|string[])}} [audioURL] - The absolute or relative URL to load the audio file from. If empty it will be obtained by parsing the JSON file. + * @param {any} [audioConfig] - The audio configuration options. + * @param {Phaser.Types.Loader.XHRSettingsObject} [audioXhrSettings] - An XHR Settings configuration object for the audio file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json file. Used in replacement of the Loaders default XHR Settings. + */ +var AudioSpriteFile = new Class({ + + Extends: MultiFile, + + initialize: + + function AudioSpriteFile (loader, key, jsonURL, audioURL, audioConfig, audioXhrSettings, jsonXhrSettings) + { + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + jsonURL = GetFastValue(config, 'jsonURL'); + audioURL = GetFastValue(config, 'audioURL'); + audioConfig = GetFastValue(config, 'audioConfig'); + audioXhrSettings = GetFastValue(config, 'audioXhrSettings'); + jsonXhrSettings = GetFastValue(config, 'jsonXhrSettings'); + } + + var data; + + // No url? then we're going to do a json load and parse it from that + if (!audioURL) + { + data = new JSONFile(loader, key, jsonURL, jsonXhrSettings); + + MultiFile.call(this, loader, 'audiosprite', key, [ data ]); + + this.config.resourceLoad = true; + this.config.audioConfig = audioConfig; + this.config.audioXhrSettings = audioXhrSettings; + } + else + { + var audio = AudioFile.create(loader, key, audioURL, audioConfig, audioXhrSettings); + + if (audio) + { + data = new JSONFile(loader, key, jsonURL, jsonXhrSettings); + + MultiFile.call(this, loader, 'audiosprite', key, [ audio, data ]); + + this.config.resourceLoad = false; + } + } + }, + + /** + * Called by each File when it finishes loading. + * + * @method Phaser.Loader.FileTypes.AudioSpriteFile#onFileComplete + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The File that has completed processing. + */ + onFileComplete: function (file) + { + var index = this.files.indexOf(file); + + if (index !== -1) + { + this.pending--; + + if (this.config.resourceLoad && file.type === 'json' && file.data.hasOwnProperty('resources')) + { + // Inspect the data for the files to now load + var urls = file.data.resources; + + var audioConfig = GetFastValue(this.config, 'audioConfig'); + var audioXhrSettings = GetFastValue(this.config, 'audioXhrSettings'); + + var audio = AudioFile.create(this.loader, file.key, urls, audioConfig, audioXhrSettings); + + if (audio) + { + this.addToMultiFile(audio); + + this.loader.addFile(audio); + } + } + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.AudioSpriteFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var fileA = this.files[0]; + var fileB = this.files[1]; + + fileA.addToCache(); + fileB.addToCache(); + + this.complete = true; + } + } + +}); + +/** + * Adds a JSON based Audio Sprite, or array of audio sprites, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.audioSprite('kyobi', 'kyobi.json', [ + * 'kyobi.ogg', + * 'kyobi.mp3', + * 'kyobi.m4a' + * ]); + * } + * ``` + * + * Audio Sprites are a combination of audio files and a JSON configuration. + * The JSON follows the format of that created by https://github.com/tonistiigi/audiosprite + * + * If the JSON file includes a 'resource' object then you can let Phaser parse it and load the audio + * files automatically based on its content. To do this exclude the audio URLs from the load: + * + * ```javascript + * function preload () + * { + * this.load.audioSprite('kyobi', 'kyobi.json'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * The key must be a unique String. It is used to add the file to the global Audio Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Audio Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Audio Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.audioSprite({ + * key: 'kyobi', + * jsonURL: 'audio/Kyobi.json', + * audioURL: [ + * 'audio/Kyobi.ogg', + * 'audio/Kyobi.mp3', + * 'audio/Kyobi.m4a' + * ] + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.AudioSpriteFileConfig` for more details. + * + * Instead of passing a URL for the audio JSON data you can also pass in a well formed JSON object instead. + * + * Once the audio has finished loading you can use it create an Audio Sprite by referencing its key: + * + * ```javascript + * this.load.audioSprite('kyobi', 'kyobi.json'); + * // and later in your game ... + * var music = this.sound.addAudioSprite('kyobi'); + * music.play('title'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * Due to different browsers supporting different audio file types you should usually provide your audio files in a variety of formats. + * ogg, mp3 and m4a are the most common. If you provide an array of URLs then the Loader will determine which _one_ file to load based on + * browser support. + * + * If audio has been disabled in your game, either via the game config, or lack of support from the device, then no audio will be loaded. + * + * Note: The ability to load this type of file will only be available if the Audio Sprite File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#audioSprite + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.AudioSpriteFileConfig|Phaser.Types.Loader.FileTypes.AudioSpriteFileConfig[])} key - The key to use for this file, or a file configuration object, or an array of objects. + * @param {string} jsonURL - The absolute or relative URL to load the json file from. Or a well formed JSON object to use instead. + * @param {(string|string[])} [audioURL] - The absolute or relative URL to load the audio file from. If empty it will be obtained by parsing the JSON file. + * @param {any} [audioConfig] - The audio configuration options. + * @param {Phaser.Types.Loader.XHRSettingsObject} [audioXhrSettings] - An XHR Settings configuration object for the audio file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader. + */ +FileTypesManager.register('audioSprite', function (key, jsonURL, audioURL, audioConfig, audioXhrSettings, jsonXhrSettings) +{ + var game = this.systems.game; + var gameAudioConfig = game.config.audio; + var deviceAudio = game.device.audio; + + if ((gameAudioConfig && gameAudioConfig.noAudio) || (!deviceAudio.webAudio && !deviceAudio.audioData)) + { + // Sounds are disabled, so skip loading audio + return this; + } + + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new AudioSpriteFile(this, key[i]); + + if (multifile.files) + { + this.addFile(multifile.files); + } + } + } + else + { + multifile = new AudioSpriteFile(this, key, jsonURL, audioURL, audioConfig, audioXhrSettings, jsonXhrSettings); + + if (multifile.files) + { + this.addFile(multifile.files); + } + } + + return this; +}); + + +/***/ }), + +/***/ 85722: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Binary File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#binary method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#binary. + * + * @class BinaryFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.BinaryFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.bin`, i.e. if `key` was "alien" then the URL will be "alien.bin". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + * @param {any} [dataType] - Optional type to cast the binary file to once loaded. For example, `Uint8Array`. + */ +var BinaryFile = new Class({ + + Extends: File, + + initialize: + + function BinaryFile (loader, key, url, xhrSettings, dataType) + { + var extension = 'bin'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + dataType = GetFastValue(config, 'dataType', dataType); + } + + var fileConfig = { + type: 'binary', + cache: loader.cacheManager.binary, + extension: extension, + responseType: 'arraybuffer', + key: key, + url: url, + xhrSettings: xhrSettings, + config: { dataType: dataType } + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.BinaryFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + var ctor = this.config.dataType; + + this.data = (ctor) ? new ctor(this.xhrLoader.response) : this.xhrLoader.response; + + this.onProcessComplete(); + } + +}); + +/** + * Adds a Binary file, or array of Binary files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.binary('doom', 'files/Doom.wad'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Binary Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Binary Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Binary Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.binary({ + * key: 'doom', + * url: 'files/Doom.wad', + * dataType: Uint8Array + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.BinaryFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.binary('doom', 'files/Doom.wad'); + * // and later in your game ... + * var data = this.cache.binary.get('doom'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Data` the final key will be `LEVEL1.Data` and + * this is what you would use to retrieve the text from the Binary Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "doom" + * and no URL is given then the Loader will set the URL to be "doom.bin". It will always add `.bin` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Binary File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#binary + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.BinaryFileConfig|Phaser.Types.Loader.FileTypes.BinaryFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.bin`, i.e. if `key` was "alien" then the URL will be "alien.bin". + * @param {any} [dataType] - Optional type to cast the binary file to once loaded. For example, `Uint8Array`. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('binary', function (key, url, dataType, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new BinaryFile(this, key[i])); + } + } + else + { + this.addFile(new BinaryFile(this, key, url, xhrSettings, dataType)); + } + + return this; +}); + +module.exports = BinaryFile; + + +/***/ }), + +/***/ 97025: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var MultiFile = __webpack_require__(26430); +var ParseXMLBitmapFont = __webpack_require__(21859); +var XMLFile = __webpack_require__(57318); + +/** + * @classdesc + * A single Bitmap Font based File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#bitmapFont method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#bitmapFont. + * + * @class BitmapFontFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.BitmapFontFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the font image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {string} [fontDataURL] - The absolute or relative URL to load the font xml data file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was "alien" then the URL will be "alien.xml". + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the font image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [fontDataXhrSettings] - An XHR Settings configuration object for the font data xml file. Used in replacement of the Loaders default XHR Settings. + */ +var BitmapFontFile = new Class({ + + Extends: MultiFile, + + initialize: + + function BitmapFontFile (loader, key, textureURL, fontDataURL, textureXhrSettings, fontDataXhrSettings) + { + var image; + var data; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + + image = new ImageFile(loader, { + key: key, + url: GetFastValue(config, 'textureURL'), + extension: GetFastValue(config, 'textureExtension', 'png'), + normalMap: GetFastValue(config, 'normalMap'), + xhrSettings: GetFastValue(config, 'textureXhrSettings') + }); + + data = new XMLFile(loader, { + key: key, + url: GetFastValue(config, 'fontDataURL'), + extension: GetFastValue(config, 'fontDataExtension', 'xml'), + xhrSettings: GetFastValue(config, 'fontDataXhrSettings') + }); + } + else + { + image = new ImageFile(loader, key, textureURL, textureXhrSettings); + data = new XMLFile(loader, key, fontDataURL, fontDataXhrSettings); + } + + if (image.linkFile) + { + // Image has a normal map + MultiFile.call(this, loader, 'bitmapfont', key, [ image, data, image.linkFile ]); + } + else + { + MultiFile.call(this, loader, 'bitmapfont', key, [ image, data ]); + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.BitmapFontFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var image = this.files[0]; + var xml = this.files[1]; + + image.addToCache(); + + var texture = image.cache.get(image.key); + + var data = ParseXMLBitmapFont(xml.data, image.cache.getFrame(image.key), 0, 0, texture); + + this.loader.cacheManager.bitmapFont.add(image.key, { data: data, texture: image.key, frame: null }); + + this.complete = true; + } + } + +}); + +/** + * Adds an XML based Bitmap Font, or array of fonts, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + + * ```javascript + * function preload () + * { + * this.load.bitmapFont('goldenFont', 'images/GoldFont.png', 'images/GoldFont.xml'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * Phaser expects the font data to be provided in an XML file format. + * These files are created by software such as the [Angelcode Bitmap Font Generator](http://www.angelcode.com/products/bmfont/), + * [Littera](http://kvazars.com/littera/) or [Glyph Designer](https://71squared.com/glyphdesigner) + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.bitmapFont({ + * key: 'goldenFont', + * textureURL: 'images/GoldFont.png', + * fontDataURL: 'images/GoldFont.xml' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.BitmapFontFileConfig` for more details. + * + * Once the atlas has finished loading you can use key of it when creating a Bitmap Text Game Object: + * + * ```javascript + * this.load.bitmapFont('goldenFont', 'images/GoldFont.png', 'images/GoldFont.xml'); + * // and later in your game ... + * this.add.bitmapText(x, y, 'goldenFont', 'Hello World'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use when creating a Bitmap Text object. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image, + * then you can specify it by providing an array as the `url` where the second element is the normal map: + * + * ```javascript + * this.load.bitmapFont('goldenFont', [ 'images/GoldFont.png', 'images/GoldFont-n.png' ], 'images/GoldFont.xml'); + * ``` + * + * Or, if you are using a config object use the `normalMap` property: + * + * ```javascript + * this.load.bitmapFont({ + * key: 'goldenFont', + * textureURL: 'images/GoldFont.png', + * normalMap: 'images/GoldFont-n.png', + * fontDataURL: 'images/GoldFont.xml' + * }); + * ``` + * + * The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings. + * Normal maps are a WebGL only feature. + * + * Note: The ability to load this type of file will only be available if the Bitmap Font File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#bitmapFont + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.BitmapFontFileConfig|Phaser.Types.Loader.FileTypes.BitmapFontFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the font image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {string} [fontDataURL] - The absolute or relative URL to load the font xml data file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was "alien" then the URL will be "alien.xml". + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the font image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [fontDataXhrSettings] - An XHR Settings configuration object for the font data xml file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('bitmapFont', function (key, textureURL, fontDataURL, textureXhrSettings, fontDataXhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new BitmapFontFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new BitmapFontFile(this, key, textureURL, fontDataURL, textureXhrSettings, fontDataXhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = BitmapFontFile; + + +/***/ }), + +/***/ 16024: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single CSS File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#css method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#css. + * + * @class CSSFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.17.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.CSSFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var CSSFile = new Class({ + + Extends: File, + + initialize: + + function CSSFile (loader, key, url, xhrSettings) + { + var extension = 'css'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'script', + cache: false, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.CSSFile#onProcess + * @since 3.17.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = document.createElement('style'); + this.data.defer = false; + this.data.innerHTML = this.xhrLoader.responseText; + + document.head.appendChild(this.data); + + this.onProcessComplete(); + } + +}); + +/** + * Adds a CSS file, or array of CSS files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.css('headers', 'styles/headers.css'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String and not already in-use by another file in the Loader. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.css({ + * key: 'headers', + * url: 'styles/headers.css' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.CSSFileConfig` for more details. + * + * Once the file has finished loading it will automatically be converted into a style DOM element + * via `document.createElement('style')`. It will have its `defer` property set to false and then the + * resulting element will be appended to `document.head`. The CSS styles are then applied to the current document. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.css". It will always add `.css` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the CSS File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#css + * @fires Phaser.Loader.Events#ADD + * @since 3.17.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.CSSFileConfig|Phaser.Types.Loader.FileTypes.CSSFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.css`, i.e. if `key` was "alien" then the URL will be "alien.css". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('css', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new CSSFile(this, key[i])); + } + } + else + { + this.addFile(new CSSFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = CSSFile; + + +/***/ }), + +/***/ 69559: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2021 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AtlasJSONFile = __webpack_require__(38734); +var BinaryFile = __webpack_require__(85722); +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var JSONFile = __webpack_require__(518); +var KTXParser = __webpack_require__(31403); +var Merge = __webpack_require__(46975); +var MultiAtlasFile = __webpack_require__(59327); +var MultiFile = __webpack_require__(26430); +var PVRParser = __webpack_require__(82038); +var verifyCompressedTexture = __webpack_require__(55222); + +/** + * @classdesc + * A Compressed Texture File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#texture method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#texture. + * + * @class CompressedTextureFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {string} key - The key to use for this file. + * @param {Phaser.Types.Loader.FileTypes.CompressedTextureFileEntry} entry - The compressed texture file entry to load. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var CompressedTextureFile = new Class({ + + Extends: MultiFile, + + initialize: + + function CompressedTextureFile (loader, key, entry, xhrSettings) + { + if (entry.multiAtlasURL) + { + var multi = new JSONFile(loader, { + key: key, + url: entry.multiAtlasURL, + xhrSettings: xhrSettings, + config: entry + }); + + MultiFile.call(this, loader, 'texture', key, [ multi ]); + } + else + { + var extension = entry.textureURL.substr(entry.textureURL.length - 3); + + if (!entry.type) + { + entry.type = (extension.toLowerCase() === 'ktx') ? 'KTX' : 'PVR'; + } + + var image = new BinaryFile(loader, { + key: key, + url: entry.textureURL, + extension: extension, + xhrSettings: xhrSettings, + config: entry + }); + + if (entry.atlasURL) + { + var data = new JSONFile(loader, { + key: key, + url: entry.atlasURL, + xhrSettings: xhrSettings, + config: entry + }); + + MultiFile.call(this, loader, 'texture', key, [ image, data ]); + } + else + { + MultiFile.call(this, loader, 'texture', key, [ image ]); + } + } + + this.config = entry; + }, + + /** + * Called by each File when it finishes loading. + * + * @method Phaser.Loader.FileTypes.CompressedTextureFile#onFileComplete + * @since 3.60.0 + * + * @param {Phaser.Loader.File} file - The File that has completed processing. + */ + onFileComplete: function (file) + { + var index = this.files.indexOf(file); + + if (index !== -1) + { + this.pending--; + + if (!this.config.multiAtlasURL) + { + return; + } + + if (file.type === 'json' && file.data.hasOwnProperty('textures')) + { + // Inspect the data for the files to now load + var textures = file.data.textures; + + var config = this.config; + var loader = this.loader; + + var currentBaseURL = loader.baseURL; + var currentPath = loader.path; + var currentPrefix = loader.prefix; + + var baseURL = GetFastValue(config, 'multiBaseURL', this.baseURL); + var path = GetFastValue(config, 'multiPath', this.path); + var prefix = GetFastValue(config, 'prefix', this.prefix); + var textureXhrSettings = GetFastValue(config, 'textureXhrSettings'); + + if (baseURL) + { + loader.setBaseURL(baseURL); + } + + if (path) + { + loader.setPath(path); + } + + if (prefix) + { + loader.setPrefix(prefix); + } + + for (var i = 0; i < textures.length; i++) + { + // "image": "texture-packer-multi-atlas-0.png", + var textureURL = textures[i].image; + + var key = 'CMA' + this.multiKeyIndex + '_' + textureURL; + + var image = new BinaryFile(loader, key, textureURL, textureXhrSettings); + + this.addToMultiFile(image); + + loader.addFile(image); + + // "normalMap": "texture-packer-multi-atlas-0_n.png", + if (textures[i].normalMap) + { + var normalMap = new BinaryFile(loader, key, textures[i].normalMap, textureXhrSettings); + + normalMap.type = 'normalMap'; + + image.setLink(normalMap); + + this.addToMultiFile(normalMap); + + loader.addFile(normalMap); + } + } + + // Reset the loader settings + loader.setBaseURL(currentBaseURL); + loader.setPath(currentPath); + loader.setPrefix(currentPrefix); + } + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.CompressedTextureFile#addToCache + * @since 3.60.0 + */ + addToCache: function () + { + function compressionWarning (message) + { + console.warn('Compressed Texture Invalid: "' + image.key + '". ' + message); + } + + if (this.isReadyToProcess()) + { + var entry = this.config; + + if (entry.multiAtlasURL) + { + this.addMultiToCache(); + } + else + { + var renderer = this.loader.systems.renderer; + var textureManager = this.loader.textureManager; + var textureData; + + var image = this.files[0]; + var json = this.files[1]; + + if (entry.type === 'PVR') + { + textureData = PVRParser(image.data); + } + else if (entry.type === 'KTX') + { + textureData = KTXParser(image.data); + if (!textureData) + { + compressionWarning('KTX file contains unsupported format.'); + } + } + + // Check block size. + if (textureData && !verifyCompressedTexture(textureData)) + { + compressionWarning('Texture dimensions failed verification. Check the texture format specifications for ' + entry.format + ' 0x' + textureData.internalFormat.toString(16) + '.'); + textureData = null; + } + + // Check texture compression. + if (textureData && !renderer.supportsCompressedTexture(entry.format, textureData.internalFormat)) + { + compressionWarning('Texture format ' + entry.format + ' with internal format ' + textureData.internalFormat + ' not supported by the GPU. Texture invalid. This is often due to the texture using sRGB instead of linear RGB.'); + textureData = null; + } + + if (textureData) + { + textureData.format = renderer.getCompressedTextureName(entry.format, textureData.internalFormat); + + var atlasData = (json && json.data) ? json.data : null; + + textureManager.addCompressedTexture(image.key, textureData, atlasData); + } + } + + this.complete = true; + } + }, + + /** + * Adds all of the multi-file entties to their target caches upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.CompressedTextureFile#addMultiToCache + * @since 3.60.0 + */ + addMultiToCache: function () + { + var entry = this.config; + var json = this.files[0]; + + var data = []; + var images = []; + var normalMaps = []; + + var renderer = this.loader.systems.renderer; + var textureManager = this.loader.textureManager; + var textureData; + + for (var i = 1; i < this.files.length; i++) + { + var file = this.files[i]; + + if (file.type === 'normalMap') + { + continue; + } + + var pos = file.key.indexOf('_'); + var key = file.key.substr(pos + 1); + + var image = file.data; + + // Now we need to find out which json entry this mapped to + for (var t = 0; t < json.data.textures.length; t++) + { + var item = json.data.textures[t]; + + if (item.image === key) + { + if (entry.type === 'PVR') + { + textureData = PVRParser(image); + } + else if (entry.type === 'KTX') + { + textureData = KTXParser(image); + } + + if (textureData && renderer.supportsCompressedTexture(entry.format, textureData.internalFormat)) + { + textureData.format = renderer.getCompressedTextureName(entry.format, textureData.internalFormat); + + images.push(textureData); + + data.push(item); + + if (file.linkFile) + { + normalMaps.push(file.linkFile.data); + } + } + + break; + } + } + } + + if (normalMaps.length === 0) + { + normalMaps = undefined; + } + + textureManager.addAtlasJSONArray(this.key, images, data, normalMaps); + + this.complete = true; + } + +}); + +/** + * Adds a Compressed Texture file to the current load queue. This feature is WebGL only. + * + * This method takes a key and a configuration object, which lists the different formats + * and files associated with them. + * + * The texture format object should be ordered in GPU priority order, with IMG as the last entry. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * preload () + * { + * this.load.texture('yourPic', { + * ASTC: { type: 'PVR', textureURL: 'pic-astc-4x4.pvr' }, + * PVRTC: { type: 'PVR', textureURL: 'pic-pvrtc-4bpp-rgba.pvr' }, + * S3TC: { type: 'PVR', textureURL: 'pic-dxt5.pvr' }, + * IMG: { textureURL: 'pic.png' } + * }); + * ``` + * + * If you wish to load a texture atlas, provide the `atlasURL` property: + * + * ```javascript + * preload () + * { + * const path = 'assets/compressed'; + * + * this.load.texture('yourAtlas', { + * 'ASTC': { type: 'PVR', textureURL: `${path}/textures-astc-4x4.pvr`, atlasURL: `${path}/textures.json` }, + * 'PVRTC': { type: 'PVR', textureURL: `${path}/textures-pvrtc-4bpp-rgba.pvr`, atlasURL: `${path}/textures-pvrtc-4bpp-rgba.json` }, + * 'S3TC': { type: 'PVR', textureURL: `${path}/textures-dxt5.pvr`, atlasURL: `${path}/textures-dxt5.json` }, + * 'IMG': { textureURL: `${path}/textures.png`, atlasURL: `${path}/textures.json` } + * }); + * } + * ``` + * + * If you wish to load a Multi Atlas, as exported from Texture Packer Pro, use the `multiAtlasURL` property instead: + * + * ```javascript + * preload () + * { + * const path = 'assets/compressed'; + * + * this.load.texture('yourAtlas', { + * 'ASTC': { type: 'PVR', multiAtlasURL: `${path}/textures.json`, multiPath: `${path}` }, + * 'PVRTC': { type: 'PVR', multiAtlasURL: `${path}/textures-pvrtc-4bpp-rgba.json`, multiPath: `${path}` }, + * 'S3TC': { type: 'PVR', multiAtlasURL: `${path}/textures-dxt5.json`, multiPath: `${path}` }, + * 'IMG': { multiAtlasURL: `${path}/textures.json`, multiPath: `${path}` } + * }); + * } + * ``` + * + * When loading a Multi Atlas you do not need to specify the `textureURL` property as it will be read from the JSON file. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.texture({ + * key: 'yourPic', + * url: { + * ASTC: { type: 'PVR', textureURL: 'pic-astc-4x4.pvr' }, + * PVRTC: { type: 'PVR', textureURL: 'pic-pvrtc-4bpp-rgba.pvr' }, + * S3TC: { type: 'PVR', textureURL: 'pic-dxt5.pvr' }, + * IMG: { textureURL: 'pic.png' } + * } + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.CompressedTextureFileConfig` for more details. + * + * The number of formats you provide to this function is up to you, but you should ensure you + * cover the primary platforms where appropriate. + * + * The 'IMG' entry is a fallback to a JPG or PNG, should the browser be unable to load any of the other + * formats presented to this function. You should really always include this, although it is optional. + * + * Phaser supports loading both the PVR and KTX container formats. Within those, it can parse + * the following texture compression formats: + * + * ETC + * ETC1 + * ATC + * ASTC + * BPTC + * RGTC + * PVRTC + * S3TC + * S3TCSRGB + * + * For more information about the benefits of compressed textures please see the + * following articles: + * + * Texture Compression in 2020 (https://aras-p.info/blog/2020/12/08/Texture-Compression-in-2020/) + * Compressed GPU Texture Formats (https://themaister.net/blog/2020/08/12/compressed-gpu-texture-formats-a-review-and-compute-shader-decoders-part-1/) + * + * To create compressed texture files use a 3rd party application such as: + * + * Texture Packer (https://www.codeandweb.com/texturepacker/tutorials/how-to-create-sprite-sheets-for-phaser3?utm_source=ad&utm_medium=banner&utm_campaign=phaser-2018-10-16) + * PVRTexTool (https://developer.imaginationtech.com/pvrtextool/) - available for Windows, macOS and Linux. + * ASTC Encoder (https://github.com/ARM-software/astc-encoder) + * + * Compressed textures will appear darker than normal textures. This is because + * the Web uses sRGB colorspace, but compressed textures are sampled as linear + * colorspace. You must adjust your textures to be lighter before compression. + * See https://imagemagick.org/Usage/color_basics/#srgb for more details. + * You can do this with ImageMagick (https://imagemagick.org/index.php) using + * the following command: + * + * `magick input.png -set colorspace RGB -colorspace sRGB output.png` + * + * You must ensure that compressed textures meet the following standards for use + * in WebGL and Phaser: + * + * - PVRTC must have a power-of-two width and height. + * - MIPMaps, if present, must have a power-of-two width and height. + * - S3TC S3TCSRGB, RGTC, and BPTC must have width and height divisible by 4. + * - ASTC must have a Channel Type of Unsigned Normalized Bytes (UNorm). In fact, all compressed textures should be UNorm, but ASTC presents many other options. + * + * If in doubt, a power-of-two resolution is always a safe bet. + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Data` the final key will be `LEVEL1.Data` and + * this is what you would use to retrieve the text from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * Unlike other file loaders in Phaser, the URLs must include the file extension. + * + * Note: The ability to load this type of file will only be available if the Compressed Texture File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#texture + * @fires Phaser.Loader.Events#ADD + * @since 3.60.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.CompressedTextureFileConfig|Phaser.Types.Loader.FileTypes.CompressedTextureFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {Phaser.Types.Loader.FileTypes.CompressedTextureFileConfig} [url] - The compressed texture configuration object. Not required if passing a config object as the `key` parameter. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('texture', function (key, url, xhrSettings) +{ + var renderer = this.systems.renderer; + + var AddEntry = function (loader, key, urls, xhrSettings) + { + var entry = { + format: null, + type: null, + textureURL: undefined, + atlasURL: undefined, + multiAtlasURL: undefined, + multiPath: undefined, + multiBaseURL: undefined + }; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + urls = GetFastValue(config, 'url'), + xhrSettings = GetFastValue(config, 'xhrSettings'); + } + + var matched = false; + + for (var textureBaseFormat in urls) + { + if (renderer.supportsCompressedTexture(textureBaseFormat)) + { + var urlEntry = urls[textureBaseFormat]; + + if (typeof urlEntry === 'string') + { + entry.textureURL = urlEntry; + } + else + { + entry = Merge(urlEntry, entry); + } + + entry.format = textureBaseFormat.toUpperCase(); + + matched = true; + + break; + } + } + + if (!matched) + { + console.warn('No supported compressed texture format or IMG fallback', key); + } + else if (entry.format === 'IMG') + { + var file; + var multifile; + + if (entry.multiAtlasURL) + { + multifile = new MultiAtlasFile(loader, key, entry.multiAtlasURL, entry.multiPath, entry.multiBaseURL, xhrSettings); + + file = multifile.files; + } + else if (entry.atlasURL) + { + multifile = new AtlasJSONFile(loader, key, entry.textureURL, entry.atlasURL, xhrSettings); + + file = multifile.files; + } + else + { + file = new ImageFile(loader, key, entry.textureURL, xhrSettings); + } + + loader.addFile(file); + } + else + { + var texture = new CompressedTextureFile(loader, key, entry, xhrSettings); + + loader.addFile(texture.files); + } + }; + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + AddEntry(this, key[i]); + } + } + else + { + AddEntry(this, key, url, xhrSettings); + } + + return this; +}); + +module.exports = CompressedTextureFile; + + +/***/ }), + +/***/ 87674: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var GetURL = __webpack_require__(98356); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Font File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#font method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#font. + * + * @class FontFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.87.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.FontFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.ttf`, i.e. if `key` was "alien" then the URL will be "alien.ttf". + * @param {string} [format='truetype'] - The font type. Should be a string, like 'truetype' or 'opentype'. + * @param {object} [descriptors] - An optional object containing font descriptors for the Font Face. See https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace#descriptors for more details. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var FontFile = new Class({ + + Extends: File, + + initialize: + + function FontFile (loader, key, url, format, descriptors, xhrSettings) + { + var extension = 'ttf'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + format = GetFastValue(config, 'format', 'truetype'); + descriptors = GetFastValue(config, 'descriptors', null); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + else if (format === undefined) + { + format = 'truetype'; + } + + var fileConfig = { + type: 'font', + cache: false, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + + this.data = { + format: format, + descriptors: descriptors + }; + + this.state = CONST.FILE_POPULATED; + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.FontFile#onProcess + * @since 3.87.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.src = GetURL(this, this.loader.baseURL); + + var font; + var key = this.key; + var source = 'url(' + this.src + ') format("' + this.data.format + '")'; + + if (this.data.descriptors) + { + font = new FontFace(key, source, this.data.descriptors); + } + else + { + font = new FontFace(key, source); + } + + var _this = this; + + font.load().then(function () + { + document.fonts.add(font); + document.body.classList.add('fonts-loaded'); + + _this.onProcessComplete(); + + }).catch(function () + { + console.warn('Font failed to load', source); + + _this.onProcessComplete(); + }); + } + +}); + +/** + * Adds a Font file, or array of Font files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.font('Nokia', 'assets/nokia.ttf', 'truetype'); + * } + * ``` + * + * If the font file is open type, you can specify the format: + * + * ```javascript + * function preload () + * { + * this.load.font('Nokia', 'assets/nokia.otf', 'opentype'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String and not already in-use by another file in the Loader. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.font({ + * key: 'Nokia', + * url: 'assets/nokia.ttf', + * format: 'truetype', + * descriptors: { style: 'normal', weight: '400' } + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.FontFileConfig` for more details. + * + * See the MDN documentation at https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace#descriptors for details about the descriptors. + * + * When this file is handled by the Loader, it will create a new Font Face DOM element for it and add it to the document. + * + * You should use the same key given for the font in your Text objects, such as: + * + * ```javascript + * this.add.text(x, y, 'Hello World', { fontFamily: 'Nokia', fontSize: 48 }); + * ``` + * + * See https://developer.mozilla.org/en-US/docs/Web/API/FontFace for more details. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.ttf". It will always add `.ttf` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Font File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#font + * @fires Phaser.Loader.Events#ADD + * @since 3.87.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.FontFileConfig|Phaser.Types.Loader.FileTypes.FontFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.ttf`, i.e. if `key` was "alien" then the URL will be "alien.ttf". + * @param {string} [format='truetype'] - The font type. Should be a string, like 'truetype' or 'opentype'. + * @param {object} [descriptors] - An optional object containing font descriptors for the Font Face. See https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace#descriptors for more details. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('font', function (key, url, format, descriptors, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new FontFile(this, key[i])); + } + } + else + { + this.addFile(new FontFile(this, key, url, format, descriptors, xhrSettings)); + } + + return this; +}); + +module.exports = FontFile; + + +/***/ }), + +/***/ 47931: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); +var Shader = __webpack_require__(73894); + +/** + * @classdesc + * A single GLSL File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#glsl method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#glsl. + * + * @class GLSLFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.GLSLFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.glsl`, i.e. if `key` was "alien" then the URL will be "alien.glsl". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var GLSLFile = new Class({ + + Extends: File, + + initialize: + + function GLSLFile (loader, key, url, xhrSettings) + { + var extension = 'glsl'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'glsl', + cache: loader.cacheManager.shader, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.GLSLFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = this.xhrLoader.responseText; + + this.onProcessComplete(); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.GLSLFile#addToCache + * @since 3.17.0 + */ + addToCache: function () + { + this.cache.add(this.key, new Shader(this.key, this.data)); + } +}); + +/** + * Adds a GLSL file, or array of GLSL files, to the current load queue. + * In Phaser 3 GLSL files are just plain Text files containing source code. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.glsl('plasma', 'shaders/Plasma.glsl'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Shader Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Shader Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Shader Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.glsl({ + * key: 'plasma', + * url: 'shaders/Plasma.glsl' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.GLSLFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.glsl('plasma', 'shaders/Plasma.glsl'); + * // and later in your game ... + * var data = this.cache.shader.get('plasma'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this file's + * key. For example, if the prefix was `FX.` and the key was `Plasma` the final key will be `FX.Plasma` and + * this is what you would use to retrieve the text from the Shader Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "plasma" + * and no URL is given then the Loader will set the URL to be "plasma.glsl". It will always add `.glsl` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the GLSL File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#glsl + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.GLSLFileConfig|Phaser.Types.Loader.FileTypes.GLSLFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.glsl`, i.e. if `key` was "alien" then the URL will be "alien.glsl". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('glsl', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new GLSLFile(this, key[i])); + } + } + else + { + this.addFile(new GLSLFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = GLSLFile; + + +/***/ }), + +/***/ 89749: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Events = __webpack_require__(54899); +var File = __webpack_require__(41299); +var GetFastValue = __webpack_require__(95540); +var GetURL = __webpack_require__(98356); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Audio File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#audio method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#audio. + * + * @class HTML5AudioFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.AudioFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [urlConfig] - The absolute or relative URL to load this file from. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var HTML5AudioFile = new Class({ + + Extends: File, + + initialize: + + function HTML5AudioFile (loader, key, urlConfig, audioConfig) + { + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + audioConfig = GetFastValue(config, 'config', audioConfig); + } + + var fileConfig = { + type: 'audio', + cache: loader.cacheManager.audio, + extension: urlConfig.type, + key: key, + url: urlConfig.url, + config: audioConfig + }; + + File.call(this, loader, fileConfig); + + // New properties specific to this class + this.locked = 'ontouchstart' in window; + this.loaded = false; + this.filesLoaded = 0; + this.filesTotal = 0; + }, + + /** + * Called when the file finishes loading. + * + * @method Phaser.Loader.FileTypes.HTML5AudioFile#onLoad + * @since 3.0.0 + */ + onLoad: function () + { + if (this.loaded) + { + return; + } + + this.loaded = true; + + this.loader.nextFile(this, true); + }, + + /** + * Called if the file errors while loading. + * + * @method Phaser.Loader.FileTypes.HTML5AudioFile#onError + * @since 3.0.0 + */ + onError: function () + { + for (var i = 0; i < this.data.length; i++) + { + var audio = this.data[i]; + + audio.oncanplaythrough = null; + audio.onerror = null; + } + + this.loader.nextFile(this, false); + }, + + /** + * Called during the file load progress. Is sent a DOM ProgressEvent. + * + * @method Phaser.Loader.FileTypes.HTML5AudioFile#onProgress + * @fires Phaser.Loader.Events#FILE_PROGRESS + * @since 3.0.0 + */ + onProgress: function (event) + { + var audio = event.target; + + audio.oncanplaythrough = null; + audio.onerror = null; + + this.filesLoaded++; + + this.percentComplete = Math.min((this.filesLoaded / this.filesTotal), 1); + + this.loader.emit(Events.FILE_PROGRESS, this, this.percentComplete); + + if (this.filesLoaded === this.filesTotal) + { + this.onLoad(); + } + }, + + /** + * Called by the Loader, starts the actual file downloading. + * During the load the methods onLoad, onError and onProgress are called, based on the XHR events. + * You shouldn't normally call this method directly, it's meant to be invoked by the Loader. + * + * @method Phaser.Loader.FileTypes.HTML5AudioFile#load + * @since 3.0.0 + */ + load: function () + { + this.data = []; + + var instances = (this.config && this.config.instances) || 1; + + this.filesTotal = instances; + this.filesLoaded = 0; + this.percentComplete = 0; + + for (var i = 0; i < instances; i++) + { + var audio = new Audio(); + + if (!audio.dataset) + { + audio.dataset = {}; + } + + audio.dataset.name = this.key + ('0' + i).slice(-2); + audio.dataset.used = 'false'; + + if (this.locked) + { + audio.dataset.locked = 'true'; + } + else + { + audio.dataset.locked = 'false'; + + audio.preload = 'auto'; + audio.oncanplaythrough = this.onProgress.bind(this); + audio.onerror = this.onError.bind(this); + } + + this.data.push(audio); + } + + for (i = 0; i < this.data.length; i++) + { + audio = this.data[i]; + audio.src = GetURL(this, this.loader.baseURL); + + if (!this.locked) + { + audio.load(); + } + } + + if (this.locked) + { + // This is super-dangerous but works. Race condition potential high. + // Is there another way? + setTimeout(this.onLoad.bind(this)); + } + } + +}); + +module.exports = HTML5AudioFile; + + +/***/ }), + +/***/ 88470: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single HTML File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#html method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#html. + * + * @class HTMLFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.12.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.HTMLFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.html`, i.e. if `key` was "alien" then the URL will be "alien.html". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var HTMLFile = new Class({ + + Extends: File, + + initialize: + + function HTMLFile (loader, key, url, xhrSettings) + { + var extension = 'html'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'text', + cache: loader.cacheManager.html, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.HTMLFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = this.xhrLoader.responseText; + + this.onProcessComplete(); + } + +}); + +/** + * Adds an HTML file, or array of HTML files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.html('story', 'files/LoginForm.html'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global HTML Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the HTML Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the HTML Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.html({ + * key: 'login', + * url: 'files/LoginForm.html' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.HTMLFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.html('login', 'files/LoginForm.html'); + * // and later in your game ... + * var data = this.cache.html.get('login'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Story` the final key will be `LEVEL1.Story` and + * this is what you would use to retrieve the html from the HTML Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "story" + * and no URL is given then the Loader will set the URL to be "story.html". It will always add `.html` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the HTML File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#html + * @fires Phaser.Loader.Events#ADD + * @since 3.12.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.HTMLFileConfig|Phaser.Types.Loader.FileTypes.HTMLFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.html`, i.e. if `key` was "alien" then the URL will be "alien.html". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('html', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new HTMLFile(this, key[i])); + } + } + else + { + this.addFile(new HTMLFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = HTMLFile; + + +/***/ }), + +/***/ 14643: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single HTML File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#htmlTexture method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#htmlTexture. + * + * @class HTMLTextureFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.12.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.HTMLTextureFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {number} [width] - The width of the texture the HTML will be rendered to. + * @param {number} [height] - The height of the texture the HTML will be rendered to. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var HTMLTextureFile = new Class({ + + Extends: File, + + initialize: + + function HTMLTextureFile (loader, key, url, width, height, xhrSettings) + { + if (width === undefined) { width = 512; } + if (height === undefined) { height = 512; } + + var extension = 'html'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + width = GetFastValue(config, 'width', width); + height = GetFastValue(config, 'height', height); + } + + var fileConfig = { + type: 'html', + cache: loader.textureManager, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings, + config: { + width: width, + height: height + } + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.HTMLTextureFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + var w = this.config.width; + var h = this.config.height; + + var data = []; + + data.push(''); + data.push(''); + data.push(''); + data.push(this.xhrLoader.responseText); + data.push(''); + data.push(''); + data.push(''); + + var svg = [ data.join('\n') ]; + var _this = this; + + try + { + var blob = new window.Blob(svg, { type: 'image/svg+xml;charset=utf-8' }); + } + catch (e) + { + _this.state = CONST.FILE_ERRORED; + + _this.onProcessComplete(); + + return; + } + + this.data = new Image(); + + this.data.crossOrigin = this.crossOrigin; + + this.data.onload = function () + { + File.revokeObjectURL(_this.data); + + _this.onProcessComplete(); + }; + + this.data.onerror = function () + { + File.revokeObjectURL(_this.data); + + _this.onProcessError(); + }; + + File.createObjectURL(this.data, blob, 'image/svg+xml'); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.HTMLTextureFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + this.cache.addImage(this.key, this.data); + } + +}); + +/** + * Adds an HTML File, or array of HTML Files, to the current load queue. When the files are loaded they + * will be rendered to textures and stored in the Texture Manager. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.htmlTexture('instructions', 'content/intro.html', 256, 512); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.htmlTexture({ + * key: 'instructions', + * url: 'content/intro.html', + * width: 256, + * height: 512 + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.HTMLTextureFileConfig` for more details. + * + * Once the file has finished loading you can use it as a texture for a Game Object by referencing its key: + * + * ```javascript + * this.load.htmlTexture('instructions', 'content/intro.html', 256, 512); + * // and later in your game ... + * this.add.image(x, y, 'instructions'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.html". It will always add `.html` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * The width and height are the size of the texture to which the HTML will be rendered. It's not possible to determine these + * automatically, so you will need to provide them, either as arguments or in the file config object. + * When the HTML file has loaded a new SVG element is created with a size and viewbox set to the width and height given. + * The SVG file has a body tag added to it, with the HTML file contents included. It then calls `window.Blob` on the SVG, + * and if successful is added to the Texture Manager, otherwise it fails processing. The overall quality of the rendered + * HTML depends on your browser, and some of them may not even support the svg / blob process used. Be aware that there are + * limitations on what HTML can be inside an SVG. You can find out more details in this + * [Mozilla MDN entry](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas). + * + * Note: The ability to load this type of file will only be available if the HTMLTextureFile File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#htmlTexture + * @fires Phaser.Loader.Events#ADD + * @since 3.12.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.HTMLTextureFileConfig|Phaser.Types.Loader.FileTypes.HTMLTextureFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.html`, i.e. if `key` was "alien" then the URL will be "alien.html". + * @param {number} [width=512] - The width of the texture the HTML will be rendered to. + * @param {number} [height=512] - The height of the texture the HTML will be rendered to. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('htmlTexture', function (key, url, width, height, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new HTMLTextureFile(this, key[i])); + } + } + else + { + this.addFile(new HTMLTextureFile(this, key, url, width, height, xhrSettings)); + } + + return this; +}); + +module.exports = HTMLTextureFile; + + +/***/ }), + +/***/ 19550: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); +var GetURL = __webpack_require__(98356); + +/** + * @classdesc + * A single Image File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#image method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#image. + * + * @class ImageFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.ImageFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + * @param {Phaser.Types.Loader.FileTypes.ImageFrameConfig} [frameConfig] - The frame configuration object. Only provided for, and used by, Sprite Sheets. + */ +var ImageFile = new Class({ + + Extends: File, + + initialize: + + function ImageFile (loader, key, url, xhrSettings, frameConfig) + { + var extension = 'png'; + var normalMapURL; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + normalMapURL = GetFastValue(config, 'normalMap'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + frameConfig = GetFastValue(config, 'frameConfig'); + } + + if (Array.isArray(url)) + { + normalMapURL = url[1]; + url = url[0]; + } + + var fileConfig = { + type: 'image', + cache: loader.textureManager, + extension: extension, + responseType: 'blob', + key: key, + url: url, + xhrSettings: xhrSettings, + config: frameConfig + }; + + File.call(this, loader, fileConfig); + + // Do we have a normal map to load as well? + if (normalMapURL) + { + var normalMap = new ImageFile(loader, this.key, normalMapURL, xhrSettings, frameConfig); + + normalMap.type = 'normalMap'; + + this.setLink(normalMap); + + loader.addFile(normalMap); + } + + this.useImageElementLoad = (loader.imageLoadType === 'HTMLImageElement') || this.base64; + + if (this.useImageElementLoad) + { + this.load = this.loadImage; + this.onProcess = this.onProcessImage; + } + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.ImageFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = new Image(); + + this.data.crossOrigin = this.crossOrigin; + + var _this = this; + + this.data.onload = function () + { + File.revokeObjectURL(_this.data); + + _this.onProcessComplete(); + }; + + this.data.onerror = function () + { + File.revokeObjectURL(_this.data); + + _this.onProcessError(); + }; + + File.createObjectURL(this.data, this.xhrLoader.response, 'image/png'); + }, + + /** + * Handles image load processing. + * + * @method Phaser.Loader.FileTypes.ImageFile#onProcessImage + * @private + * @since 3.60.0 + */ + onProcessImage: function () + { + var result = this.state; + + this.state = CONST.FILE_PROCESSING; + + if (result === CONST.FILE_LOADED) + { + this.onProcessComplete(); + } + else + { + this.onProcessError(); + } + }, + + /** + * Loads the image using either XHR or an Image tag. + * + * @method Phaser.Loader.FileTypes.ImageFile#loadImage + * @private + * @since 3.60.0 + */ + loadImage: function () + { + this.state = CONST.FILE_LOADING; + + this.src = GetURL(this, this.loader.baseURL); + + this.data = new Image(); + + this.data.crossOrigin = this.crossOrigin; + + var _this = this; + + this.data.onload = function () + { + _this.state = CONST.FILE_LOADED; + + _this.loader.nextFile(_this, true); + }; + + this.data.onerror = function () + { + _this.loader.nextFile(_this, false); + }; + + this.data.src = this.src; + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.ImageFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + // Check if we have a linked normal map + var linkFile = this.linkFile; + + if (linkFile) + { + // We do, but has it loaded? + if (linkFile.state >= CONST.FILE_COMPLETE) + { + if (linkFile.type === 'spritesheet') + { + linkFile.addToCache(); + } + else if (this.type === 'normalMap') + { + // linkFile.data = Image + // this.data = Normal Map + this.cache.addImage(this.key, linkFile.data, this.data); + } + else + { + // linkFile.data = Normal Map + // this.data = Image + this.cache.addImage(this.key, this.data, linkFile.data); + } + } + + // Nothing to do here, we'll use the linkFile `addToCache` call + // to process this pair + } + else + { + this.cache.addImage(this.key, this.data); + } + } + +}); + +/** + * Adds an Image, or array of Images, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.image('logo', 'images/phaserLogo.png'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * If you try to load an animated gif only the first frame will be rendered. Browsers do not natively support playback + * of animated gifs to Canvas elements. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.image({ + * key: 'logo', + * url: 'images/AtariLogo.png' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.ImageFileConfig` for more details. + * + * Once the file has finished loading you can use it as a texture for a Game Object by referencing its key: + * + * ```javascript + * this.load.image('logo', 'images/AtariLogo.png'); + * // and later in your game ... + * this.add.image(x, y, 'logo'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image, + * then you can specify it by providing an array as the `url` where the second element is the normal map: + * + * ```javascript + * this.load.image('logo', [ 'images/AtariLogo.png', 'images/AtariLogo-n.png' ]); + * ``` + * + * Or, if you are using a config object use the `normalMap` property: + * + * ```javascript + * this.load.image({ + * key: 'logo', + * url: 'images/AtariLogo.png', + * normalMap: 'images/AtariLogo-n.png' + * }); + * ``` + * + * The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings. + * Normal maps are a WebGL only feature. + * + * In Phaser 3.60 a new property was added that allows you to control how images are loaded. By default, images are loaded via XHR as Blobs. + * However, you can set `loader.imageLoadType: "HTMLImageElement"` in the Game Configuration and instead, the Loader will load all images + * via the Image tag instead. + * + * Note: The ability to load this type of file will only be available if the Image File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#image + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.ImageFileConfig|Phaser.Types.Loader.FileTypes.ImageFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string|string[]} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('image', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new ImageFile(this, key[i])); + } + } + else + { + this.addFile(new ImageFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = ImageFile; + + +/***/ }), + +/***/ 518: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single JSON File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#json method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#json. + * + * @class JSONFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {(object|string)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, can be a fully formed JSON Object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + * @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache. + */ +var JSONFile = new Class({ + + Extends: File, + + initialize: + + // url can either be a string, in which case it is treated like a proper url, or an object, in which case it is treated as a ready-made JS Object + // dataKey allows you to pluck a specific object out of the JSON and put just that into the cache, rather than the whole thing + + function JSONFile (loader, key, url, xhrSettings, dataKey) + { + var extension = 'json'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + dataKey = GetFastValue(config, 'dataKey', dataKey); + } + + var fileConfig = { + type: 'json', + cache: loader.cacheManager.json, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings, + config: dataKey + }; + + File.call(this, loader, fileConfig); + + // A JSON object has been provided (instead of a URL), so we'll use it directly as the File.data. No need to load it. + if (IsPlainObject(url)) + { + if (dataKey) + { + this.data = GetValue(url, dataKey); + } + else + { + this.data = url; + } + + this.state = CONST.FILE_POPULATED; + } + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.JSONFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + if (this.state !== CONST.FILE_POPULATED) + { + this.state = CONST.FILE_PROCESSING; + + try + { + var json = JSON.parse(this.xhrLoader.responseText); + } + catch (e) + { + this.onProcessError(); + + throw e; + } + + var key = this.config; + + if (typeof key === 'string') + { + this.data = GetValue(json, key, json); + } + else + { + this.data = json; + } + } + + this.onProcessComplete(); + } + +}); + +/** + * Adds a JSON file, or array of JSON files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.json('wavedata', 'files/AlienWaveData.json'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global JSON Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the JSON Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the JSON Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.json({ + * key: 'wavedata', + * url: 'files/AlienWaveData.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.JSONFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.json('wavedata', 'files/AlienWaveData.json'); + * // and later in your game ... + * var data = this.cache.json.get('wavedata'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Waves` the final key will be `LEVEL1.Waves` and + * this is what you would use to retrieve the text from the JSON Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "data" + * and no URL is given then the Loader will set the URL to be "data.json". It will always add `.json` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * You can also optionally provide a `dataKey` to use. This allows you to extract only a part of the JSON and store it in the Cache, + * rather than the whole file. For example, if your JSON data had a structure like this: + * + * ```json + * { + * "level1": { + * "baddies": { + * "aliens": {}, + * "boss": {} + * } + * }, + * "level2": {}, + * "level3": {} + * } + * ``` + * + * And you only wanted to store the `boss` data in the Cache, then you could pass `level1.baddies.boss`as the `dataKey`. + * + * Note: The ability to load this type of file will only be available if the JSON File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#json + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig|Phaser.Types.Loader.FileTypes.JSONFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {(object|string)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, can be a fully formed JSON Object. + * @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('json', function (key, url, dataKey, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new JSONFile(this, key[i])); + } + } + else + { + this.addFile(new JSONFile(this, key, url, xhrSettings, dataKey)); + } + + return this; +}); + +module.exports = JSONFile; + + +/***/ }), + +/***/ 59327: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var JSONFile = __webpack_require__(518); +var MultiFile = __webpack_require__(26430); + +/** + * @classdesc + * A single Multi Texture Atlas File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#multiatlas method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#multiatlas. + * + * @class MultiAtlasFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.MultiAtlasFileConfig)} key - The key of the file. Must be unique within both the Loader and the Texture Manager. Or a config object. + * @param {string} [atlasURL] - The absolute or relative URL to load the multi atlas json file from. + * @param {string} [path] - Optional path to use when loading the textures defined in the atlas data. + * @param {string} [baseURL] - Optional Base URL to use when loading the textures defined in the atlas data. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - Extra XHR Settings specifically for the atlas json file. + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - Extra XHR Settings specifically for the texture files. + */ +var MultiAtlasFile = new Class({ + + Extends: MultiFile, + + initialize: + + function MultiAtlasFile (loader, key, atlasURL, path, baseURL, atlasXhrSettings, textureXhrSettings) + { + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + + if (GetFastValue(config, 'url', false)) + { + atlasURL = GetFastValue(config, 'url'); + } + else + { + atlasURL = GetFastValue(config, 'atlasURL'); + } + + atlasXhrSettings = GetFastValue(config, 'xhrSettings'); + path = GetFastValue(config, 'path'); + baseURL = GetFastValue(config, 'baseURL'); + textureXhrSettings = GetFastValue(config, 'textureXhrSettings'); + } + + var data = new JSONFile(loader, key, atlasURL, atlasXhrSettings); + + MultiFile.call(this, loader, 'multiatlas', key, [ data ]); + + this.config.path = path; + this.config.baseURL = baseURL; + this.config.textureXhrSettings = textureXhrSettings; + }, + + /** + * Called by each File when it finishes loading. + * + * @method Phaser.Loader.FileTypes.MultiAtlasFile#onFileComplete + * @since 3.7.0 + * + * @param {Phaser.Loader.File} file - The File that has completed processing. + */ + onFileComplete: function (file) + { + var index = this.files.indexOf(file); + + if (index !== -1) + { + this.pending--; + + if (file.type === 'json' && file.data.hasOwnProperty('textures')) + { + // Inspect the data for the files to now load + var textures = file.data.textures; + + var config = this.config; + var loader = this.loader; + + var currentBaseURL = loader.baseURL; + var currentPath = loader.path; + var currentPrefix = loader.prefix; + + var baseURL = GetFastValue(config, 'baseURL', this.baseURL); + var path = GetFastValue(config, 'path', this.path); + var prefix = GetFastValue(config, 'prefix', this.prefix); + var textureXhrSettings = GetFastValue(config, 'textureXhrSettings'); + + loader.setBaseURL(baseURL); + loader.setPath(path); + loader.setPrefix(prefix); + + for (var i = 0; i < textures.length; i++) + { + // "image": "texture-packer-multi-atlas-0.png", + var textureURL = textures[i].image; + + var key = 'MA' + this.multiKeyIndex + '_' + textureURL; + + var image = new ImageFile(loader, key, textureURL, textureXhrSettings); + + this.addToMultiFile(image); + + loader.addFile(image); + + // "normalMap": "texture-packer-multi-atlas-0_n.png", + if (textures[i].normalMap) + { + var normalMap = new ImageFile(loader, key, textures[i].normalMap, textureXhrSettings); + + normalMap.type = 'normalMap'; + + image.setLink(normalMap); + + this.addToMultiFile(normalMap); + + loader.addFile(normalMap); + } + } + + // Reset the loader settings + loader.setBaseURL(currentBaseURL); + loader.setPath(currentPath); + loader.setPrefix(currentPrefix); + } + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.MultiAtlasFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var fileJSON = this.files[0]; + + var data = []; + var images = []; + var normalMaps = []; + + for (var i = 1; i < this.files.length; i++) + { + var file = this.files[i]; + + if (file.type === 'normalMap') + { + continue; + } + + var pos = file.key.indexOf('_'); + var key = file.key.substr(pos + 1); + + var image = file.data; + + // Now we need to find out which json entry this mapped to + for (var t = 0; t < fileJSON.data.textures.length; t++) + { + var item = fileJSON.data.textures[t]; + + if (item.image === key) + { + images.push(image); + + data.push(item); + + if (file.linkFile) + { + normalMaps.push(file.linkFile.data); + } + + break; + } + } + } + + if (normalMaps.length === 0) + { + normalMaps = undefined; + } + + this.loader.textureManager.addAtlasJSONArray(this.key, images, data, normalMaps); + + this.complete = true; + } + } + +}); + +/** + * Adds a Multi Texture Atlas, or array of multi atlases, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.multiatlas('level1', 'images/Level1.json'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * Phaser expects the atlas data to be provided in a JSON file as exported from the application Texture Packer, + * version 4.6.3 or above, where you have made sure to use the Phaser 3 Export option. + * + * The way it works internally is that you provide a URL to the JSON file. Phaser then loads this JSON, parses it and + * extracts which texture files it also needs to load to complete the process. If the JSON also defines normal maps, + * Phaser will load those as well. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.multiatlas({ + * key: 'level1', + * atlasURL: 'images/Level1.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.MultiAtlasFileConfig` for more details. + * + * Instead of passing a URL for the atlas JSON data you can also pass in a well formed JSON object instead. + * + * Once the atlas has finished loading you can use frames from it as textures for a Game Object by referencing its key: + * + * ```javascript + * this.load.multiatlas('level1', 'images/Level1.json'); + * // and later in your game ... + * this.add.image(x, y, 'level1', 'background'); + * ``` + * + * To get a list of all available frames within an atlas please consult your Texture Atlas software. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Multi Atlas File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#multiatlas + * @fires Phaser.Loader.Events#ADD + * @since 3.7.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.MultiAtlasFileConfig|Phaser.Types.Loader.FileTypes.MultiAtlasFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {string} [path] - Optional path to use when loading the textures defined in the atlas data. + * @param {string} [baseURL] - Optional Base URL to use when loading the textures defined in the atlas data. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas json file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('multiatlas', function (key, atlasURL, path, baseURL, atlasXhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new MultiAtlasFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new MultiAtlasFile(this, key, atlasURL, path, baseURL, atlasXhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = MultiAtlasFile; + + +/***/ }), + +/***/ 99297: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); +var MultiFile = __webpack_require__(26430); +var ScriptFile = __webpack_require__(34328); + +/** + * @classdesc + * A Multi Script File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#scripts method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#scripts. + * + * @class MultiScriptFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.17.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.MultiScriptFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string[]} [url] - An array of absolute or relative URLs to load the script files from. They are processed in the order given in the array. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object for the script files. Used in replacement of the Loaders default XHR Settings. + */ +var MultiScriptFile = new Class({ + + Extends: MultiFile, + + initialize: + + function MultiScriptFile (loader, key, url, xhrSettings) + { + var extension = 'js'; + var files = []; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + if (!Array.isArray(url)) + { + url = [ url ]; + } + + for (var i = 0; i < url.length; i++) + { + var scriptFile = new ScriptFile(loader, { + key: key + '_' + i.toString(), + url: url[i], + extension: extension, + xhrSettings: xhrSettings + }); + + // Override the default onProcess function + scriptFile.onProcess = function () + { + this.onProcessComplete(); + }; + + files.push(scriptFile); + } + + MultiFile.call(this, loader, 'scripts', key, files); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.MultiScriptFile#addToCache + * @since 3.17.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + for (var i = 0; i < this.files.length; i++) + { + var file = this.files[i]; + + file.data = document.createElement('script'); + file.data.language = 'javascript'; + file.data.type = 'text/javascript'; + file.data.defer = false; + file.data.text = file.xhrLoader.responseText; + + document.head.appendChild(file.data); + } + + this.complete = true; + } + } + +}); + +/** + * Adds an array of Script files to the current load queue. + * + * The difference between this and the `ScriptFile` file type is that you give an array of scripts to this method, + * and the scripts are then processed _exactly_ in that order. This allows you to load a bunch of scripts that + * may have dependencies on each other without worrying about the async nature of traditional script loading. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.scripts('PostProcess', [ + * 'libs/shaders/CopyShader.js', + * 'libs/postprocessing/EffectComposer.js', + * 'libs/postprocessing/RenderPass.js', + * 'libs/postprocessing/MaskPass.js', + * 'libs/postprocessing/ShaderPass.js', + * 'libs/postprocessing/AfterimagePass.js' + * ]); + * } + * ``` + * + * In the code above the script files will all be loaded in parallel but only processed (i.e. invoked) in the exact + * order given in the array. + * + * The files are **not** loaded right away. They are added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the files are queued + * it means you cannot use the files immediately after calling this method, but must wait for the files to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String and not already in-use by another file in the Loader. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.scripts({ + * key: 'PostProcess', + * url: [ + * 'libs/shaders/CopyShader.js', + * 'libs/postprocessing/EffectComposer.js', + * 'libs/postprocessing/RenderPass.js', + * 'libs/postprocessing/MaskPass.js', + * 'libs/postprocessing/ShaderPass.js', + * 'libs/postprocessing/AfterimagePass.js' + * ] + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.MultiScriptFileConfig` for more details. + * + * Once all the files have finished loading they will automatically be converted into a script element + * via `document.createElement('script')`. They will have their language set to JavaScript, `defer` set to + * false and then the resulting element will be appended to `document.head`. Any code then in the + * script will be executed. This is done in the exact order the files are specified in the url array. + * + * The URLs can be relative or absolute. If the URLs are relative the `Loader.baseURL` and `Loader.path` values will be prepended to them. + * + * Note: The ability to load this type of file will only be available if the MultiScript File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#scripts + * @fires Phaser.Loader.Events#ADD + * @since 3.17.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.MultiScriptFileConfig|Phaser.Types.Loader.FileTypes.MultiScriptFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string[]} [url] - An array of absolute or relative URLs to load the script files from. They are processed in the order given in the array. + * @param {string} [extension='js'] - The default file extension to use if no url is provided. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for these files. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('scripts', function (key, url, xhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new MultiScriptFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new MultiScriptFile(this, key, url, xhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = MultiScriptFile; + + +/***/ }), + +/***/ 58610: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var FileTypesManager = __webpack_require__(74099); +var JSONFile = __webpack_require__(518); + +/** + * @classdesc + * A single JSON Pack File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#pack method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#pack. + * + * @class PackFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.PackFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {(string|any)} [url] - The absolute or relative URL to load this file from or a ready formed JSON object. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + * @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache. + */ +var PackFile = new Class({ + + Extends: JSONFile, + + initialize: + + // url can either be a string, in which case it is treated like a proper url, or an object, in which case it is treated as a ready-made JS Object + // dataKey allows you to pluck a specific object out of the JSON and put just that into the cache, rather than the whole thing + + function PackFile (loader, key, url, xhrSettings, dataKey) + { + JSONFile.call(this, loader, key, url, xhrSettings, dataKey); + + this.type = 'packfile'; + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.PackFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + if (this.state !== CONST.FILE_POPULATED) + { + this.state = CONST.FILE_PROCESSING; + + this.data = JSON.parse(this.xhrLoader.responseText); + } + + if (this.data.hasOwnProperty('files') && this.config) + { + var newData = {}; + + newData[this.config] = this.data; + + this.data = newData; + } + + // Let's pass the pack file data over to the Loader ... + this.loader.addPack(this.data, this.config); + + this.onProcessComplete(); + } + +}); + +/** + * Adds a JSON File Pack, or array of packs, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.pack('level1', 'data/Level1Files.json'); + * } + * ``` + * + * A File Pack is a JSON file (or object) that contains details about other files that should be added into the Loader. + * Here is a small example: + * + * ```json + * { + * "test1": { + * "files": [ + * { + * "type": "image", + * "key": "taikodrummaster", + * "url": "assets/pics/taikodrummaster.jpg" + * }, + * { + * "type": "image", + * "key": "sukasuka-chtholly", + * "url": "assets/pics/sukasuka-chtholly.png" + * } + * ] + * }, + * "meta": { + * "generated": "1401380327373", + * "app": "Phaser 3 Asset Packer", + * "url": "https://phaser.io", + * "version": "1.0", + * "copyright": "Photon Storm Ltd. 2018" + * } + * } + * ``` + * + * The pack can be split into sections. In the example above you'll see a section called `test1`. You can tell + * the `load.pack` method to parse only a particular section of a pack. The pack is stored in the JSON Cache, + * so you can pass it to the Loader to process additional sections as needed in your game, or you can just load + * them all at once without specifying anything. + * + * The pack file can contain an entry for any type of file that Phaser can load. The object structures exactly + * match that of the file type configs, and all properties available within the file type configs can be used + * in the pack file too. An entry's `type` is the name of the Loader method that will load it, e.g., 'image'. + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * The key must be a unique String. It is used to add the file to the global JSON Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the JSON Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the JSON Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.pack({ + * key: 'level1', + * url: 'data/Level1Files.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.PackFileConfig` for more details. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Waves` the final key will be `LEVEL1.Waves` and + * this is what you would use to retrieve the text from the JSON Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "data" + * and no URL is given then the Loader will set the URL to be "data.json". It will always add `.json` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * You can also optionally provide a `dataKey` to use. This allows you to extract only a part of the JSON and store it in the Cache, + * rather than the whole file. For example, if your JSON data had a structure like this: + * + * ```json + * { + * "level1": { + * "baddies": { + * "aliens": {}, + * "boss": {} + * } + * }, + * "level2": {}, + * "level3": {} + * } + * ``` + * + * And you only wanted to store the `boss` data in the Cache, then you could pass `level1.baddies.boss`as the `dataKey`. + * + * Note: The ability to load this type of file will only be available if the Pack File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#pack + * @fires Phaser.Loader.Events#ADD + * @since 3.7.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.PackFileConfig|Phaser.Types.Loader.FileTypes.PackFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('pack', function (key, url, dataKey, xhrSettings) +{ + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + this.addFile(new PackFile(this, key[i])); + } + } + else + { + this.addFile(new PackFile(this, key, url, xhrSettings, dataKey)); + } + + return this; +}); + +module.exports = PackFile; + + +/***/ }), + +/***/ 48988: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Plugin Script File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#plugin method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#plugin. + * + * @class PluginFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.PluginFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {boolean} [start=false] - Automatically start the plugin after loading? + * @param {string} [mapping] - If this plugin is to be injected into the Scene, this is the property key used. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var PluginFile = new Class({ + + Extends: File, + + initialize: + + function PluginFile (loader, key, url, start, mapping, xhrSettings) + { + var extension = 'js'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + start = GetFastValue(config, 'start'); + mapping = GetFastValue(config, 'mapping'); + } + + var fileConfig = { + type: 'plugin', + cache: false, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings, + config: { + start: start, + mapping: mapping + } + }; + + File.call(this, loader, fileConfig); + + // If the url variable refers to a class, add the plugin directly + if (typeof url === 'function') + { + this.data = url; + + this.state = CONST.FILE_POPULATED; + } + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.PluginFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + var pluginManager = this.loader.systems.plugins; + var config = this.config; + + var start = GetFastValue(config, 'start', false); + var mapping = GetFastValue(config, 'mapping', null); + + if (this.state === CONST.FILE_POPULATED) + { + pluginManager.install(this.key, this.data, start, mapping); + } + else + { + // Plugin added via a js file + this.state = CONST.FILE_PROCESSING; + + this.data = document.createElement('script'); + this.data.language = 'javascript'; + this.data.type = 'text/javascript'; + this.data.defer = false; + this.data.text = this.xhrLoader.responseText; + + document.head.appendChild(this.data); + + var plugin = pluginManager.install(this.key, window[this.key], start, mapping); + + if (start || mapping) + { + // Install into the current Scene Systems and Scene + this.loader.systems[mapping] = plugin; + this.loader.scene[mapping] = plugin; + } + } + + this.onProcessComplete(); + } + +}); + +/** + * Adds a Plugin Script file, or array of plugin files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.plugin('modplayer', 'plugins/ModPlayer.js'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String and not already in-use by another file in the Loader. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.plugin({ + * key: 'modplayer', + * url: 'plugins/ModPlayer.js' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.PluginFileConfig` for more details. + * + * Once the file has finished loading it will automatically be converted into a script element + * via `document.createElement('script')`. It will have its language set to JavaScript, `defer` set to + * false and then the resulting element will be appended to `document.head`. Any code then in the + * script will be executed. It will then be passed to the Phaser PluginCache.register method. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.js". It will always add `.js` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Plugin File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#plugin + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.PluginFileConfig|Phaser.Types.Loader.FileTypes.PluginFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {(string|function)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". Or, a plugin function. + * @param {boolean} [start] - Automatically start the plugin after loading? + * @param {string} [mapping] - If this plugin is to be injected into the Scene, this is the property key used. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('plugin', function (key, url, start, mapping, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new PluginFile(this, key[i])); + } + } + else + { + this.addFile(new PluginFile(this, key, url, start, mapping, xhrSettings)); + } + + return this; +}); + +module.exports = PluginFile; + + +/***/ }), + +/***/ 67397: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single SVG File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#svg method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#svg. + * + * @class SVGFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.SVGFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.svg`, i.e. if `key` was "alien" then the URL will be "alien.svg". + * @param {Phaser.Types.Loader.FileTypes.SVGSizeConfig} [svgConfig] - The svg size configuration object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var SVGFile = new Class({ + + Extends: File, + + initialize: + + function SVGFile (loader, key, url, svgConfig, xhrSettings) + { + var extension = 'svg'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + svgConfig = GetFastValue(config, 'svgConfig', {}); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'svg', + cache: loader.textureManager, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings, + config: { + width: GetFastValue(svgConfig, 'width'), + height: GetFastValue(svgConfig, 'height'), + scale: GetFastValue(svgConfig, 'scale') + } + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.SVGFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + var text = this.xhrLoader.responseText; + var svg = [ text ]; + var width = this.config.width; + var height = this.config.height; + var scale = this.config.scale; + + resize: if (width && height || scale) + { + var xml = null; + var parser = new DOMParser(); + xml = parser.parseFromString(text, 'text/xml'); + var svgXML = xml.getElementsByTagName('svg')[0]; + + var hasViewBox = svgXML.hasAttribute('viewBox'); + var svgWidth = parseFloat(svgXML.getAttribute('width')); + var svgHeight = parseFloat(svgXML.getAttribute('height')); + + if (!hasViewBox && svgWidth && svgHeight) + { + // If there's no viewBox attribute, set one + svgXML.setAttribute('viewBox', '0 0 ' + svgWidth + ' ' + svgHeight); + } + else if (hasViewBox && !svgWidth && !svgHeight) + { + // Get the w/h from the viewbox + var viewBox = svgXML.getAttribute('viewBox').split(/\s+|,/); + + svgWidth = viewBox[2]; + svgHeight = viewBox[3]; + } + + if (scale) + { + if (svgWidth && svgHeight) + { + width = svgWidth * scale; + height = svgHeight * scale; + } + else + { + break resize; + } + } + + svgXML.setAttribute('width', width.toString() + 'px'); + svgXML.setAttribute('height', height.toString() + 'px'); + + svg = [ (new XMLSerializer()).serializeToString(svgXML) ]; + } + + try + { + var blob = new window.Blob(svg, { type: 'image/svg+xml;charset=utf-8' }); + } + catch (e) + { + this.onProcessError(); + + return; + } + + this.data = new Image(); + + this.data.crossOrigin = this.crossOrigin; + + var _this = this; + var retry = false; + + this.data.onload = function () + { + if (!retry) + { + File.revokeObjectURL(_this.data); + } + + _this.onProcessComplete(); + }; + + this.data.onerror = function () + { + // Safari 8 re-try + if (!retry) + { + retry = true; + + File.revokeObjectURL(_this.data); + + _this.data.src = 'data:image/svg+xml,' + encodeURIComponent(svg.join('')); + } + else + { + _this.onProcessError(); + } + }; + + File.createObjectURL(this.data, blob, 'image/svg+xml'); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.SVGFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + this.cache.addImage(this.key, this.data); + } + +}); + +/** + * Adds an SVG File, or array of SVG Files, to the current load queue. When the files are loaded they + * will be rendered to bitmap textures and stored in the Texture Manager. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.svg('morty', 'images/Morty.svg'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.svg({ + * key: 'morty', + * url: 'images/Morty.svg' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.SVGFileConfig` for more details. + * + * Once the file has finished loading you can use it as a texture for a Game Object by referencing its key: + * + * ```javascript + * this.load.svg('morty', 'images/Morty.svg'); + * // and later in your game ... + * this.add.image(x, y, 'morty'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.html". It will always add `.html` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * You can optionally pass an SVG Resize Configuration object when you load an SVG file. By default the SVG will be rendered to a texture + * at the same size defined in the SVG file attributes. However, this isn't always desirable. You may wish to resize the SVG (either down + * or up) to improve texture clarity, or reduce texture memory consumption. You can either specify an exact width and height to resize + * the SVG to: + * + * ```javascript + * function preload () + * { + * this.load.svg('morty', 'images/Morty.svg', { width: 300, height: 600 }); + * } + * ``` + * + * Or when using a configuration object: + * + * ```javascript + * this.load.svg({ + * key: 'morty', + * url: 'images/Morty.svg', + * svgConfig: { + * width: 300, + * height: 600 + * } + * }); + * ``` + * + * Alternatively, you can just provide a scale factor instead: + * + * ```javascript + * function preload () + * { + * this.load.svg('morty', 'images/Morty.svg', { scale: 2.5 }); + * } + * ``` + * + * Or when using a configuration object: + * + * ```javascript + * this.load.svg({ + * key: 'morty', + * url: 'images/Morty.svg', + * svgConfig: { + * scale: 2.5 + * } + * }); + * ``` + * + * If scale, width and height values are all given, the scale has priority and the width and height values are ignored. + * + * Note: The ability to load this type of file will only be available if the SVG File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#svg + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.SVGFileConfig|Phaser.Types.Loader.FileTypes.SVGFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.svg`, i.e. if `key` was "alien" then the URL will be "alien.svg". + * @param {Phaser.Types.Loader.FileTypes.SVGSizeConfig} [svgConfig] - The svg size configuration object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('svg', function (key, url, svgConfig, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new SVGFile(this, key[i])); + } + } + else + { + this.addFile(new SVGFile(this, key, url, svgConfig, xhrSettings)); + } + + return this; +}); + +module.exports = SVGFile; + + + +/***/ }), + +/***/ 88423: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * An external Scene JavaScript File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#sceneFile method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#sceneFile. + * + * @class SceneFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.16.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.SceneFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var SceneFile = new Class({ + + Extends: File, + + initialize: + + function SceneFile (loader, key, url, xhrSettings) + { + var extension = 'js'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'text', + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.SceneFile#onProcess + * @since 3.16.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = this.xhrLoader.responseText; + + this.onProcessComplete(); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.SceneFile#addToCache + * @since 3.16.0 + */ + addToCache: function () + { + var code = this.data.concat('(function(){\n' + 'return new ' + this.key + '();\n' + '}).call(this);'); + + // Stops rollup from freaking out during build + var eval2 = eval; + + this.loader.sceneManager.add(this.key, eval2(code)); + + this.complete = true; + } + +}); + +/** + * Adds an external Scene file, or array of Scene files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.sceneFile('Level1', 'src/Level1.js'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Scene Manager upon a successful load. + * + * For a Scene File it's vitally important that the key matches the class name in the JavaScript file. + * + * For example here is the source file: + * + * ```javascript + * class ExternalScene extends Phaser.Scene { + * + * constructor () + * { + * super('myScene'); + * } + * + * } + * ``` + * + * Because the class is called `ExternalScene` that is the exact same key you must use when loading it: + * + * ```javascript + * function preload () + * { + * this.load.sceneFile('ExternalScene', 'src/yourScene.js'); + * } + * ``` + * + * The key that is used within the Scene Manager can either be set to the same, or you can override it in the Scene + * constructor, as we've done in the example above, where the Scene key was changed to `myScene`. + * + * The key should be unique both in terms of files being loaded and Scenes already present in the Scene Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Scene Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.sceneFile({ + * key: 'Level1', + * url: 'src/Level1.js' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.SceneFileConfig` for more details. + * + * Once the file has finished loading it will be added to the Scene Manager. + * + * ```javascript + * this.load.sceneFile('Level1', 'src/Level1.js'); + * // and later in your game ... + * this.scene.start('Level1'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `WORLD1.` and the key was `Story` the final key will be `WORLD1.Story` and + * this is what you would use to retrieve the text from the Scene Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "story" + * and no URL is given then the Loader will set the URL to be "story.js". It will always add `.js` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Scene File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#sceneFile + * @fires Phaser.Loader.Events#ADD + * @since 3.16.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.SceneFileConfig|Phaser.Types.Loader.FileTypes.SceneFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('sceneFile', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new SceneFile(this, key[i])); + } + } + else + { + this.addFile(new SceneFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = SceneFile; + + +/***/ }), + +/***/ 56812: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Scene Plugin Script File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#scenePlugin method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#scenePlugin. + * + * @class ScenePluginFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.8.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.ScenePluginFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {string} [systemKey] - If this plugin is to be added to Scene.Systems, this is the property key for it. + * @param {string} [sceneKey] - If this plugin is to be added to the Scene, this is the property key for it. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var ScenePluginFile = new Class({ + + Extends: File, + + initialize: + + function ScenePluginFile (loader, key, url, systemKey, sceneKey, xhrSettings) + { + var extension = 'js'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + systemKey = GetFastValue(config, 'systemKey'); + sceneKey = GetFastValue(config, 'sceneKey'); + } + + var fileConfig = { + type: 'scenePlugin', + cache: false, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings, + config: { + systemKey: systemKey, + sceneKey: sceneKey + } + }; + + File.call(this, loader, fileConfig); + + // If the url variable refers to a class, add the plugin directly + if (typeof url === 'function') + { + this.data = url; + + this.state = CONST.FILE_POPULATED; + } + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.ScenePluginFile#onProcess + * @since 3.8.0 + */ + onProcess: function () + { + var pluginManager = this.loader.systems.plugins; + var config = this.config; + + var key = this.key; + var systemKey = GetFastValue(config, 'systemKey', key); + var sceneKey = GetFastValue(config, 'sceneKey', key); + + if (this.state === CONST.FILE_POPULATED) + { + pluginManager.installScenePlugin(systemKey, this.data, sceneKey, this.loader.scene, true); + } + else + { + // Plugin added via a js file + this.state = CONST.FILE_PROCESSING; + + this.data = document.createElement('script'); + this.data.language = 'javascript'; + this.data.type = 'text/javascript'; + this.data.defer = false; + this.data.text = this.xhrLoader.responseText; + + document.head.appendChild(this.data); + + pluginManager.installScenePlugin(systemKey, window[this.key], sceneKey, this.loader.scene, true); + } + + this.onProcessComplete(); + } + +}); + +/** + * Adds a Scene Plugin Script file, or array of plugin files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.scenePlugin('ModPlayer', 'plugins/ModPlayer.js', 'modPlayer', 'mods'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String and not already in-use by another file in the Loader. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.scenePlugin({ + * key: 'modplayer', + * url: 'plugins/ModPlayer.js' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.ScenePluginFileConfig` for more details. + * + * Once the file has finished loading it will automatically be converted into a script element + * via `document.createElement('script')`. It will have its language set to JavaScript, `defer` set to + * false and then the resulting element will be appended to `document.head`. Any code then in the + * script will be executed. It will then be passed to the Phaser PluginCache.register method. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.js". It will always add `.js` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Script File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#scenePlugin + * @fires Phaser.Loader.Events#ADD + * @since 3.8.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.ScenePluginFileConfig|Phaser.Types.Loader.FileTypes.ScenePluginFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {(string|function)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". Or, set to a plugin function. + * @param {string} [systemKey] - If this plugin is to be added to Scene.Systems, this is the property key for it. + * @param {string} [sceneKey] - If this plugin is to be added to the Scene, this is the property key for it. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('scenePlugin', function (key, url, systemKey, sceneKey, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new ScenePluginFile(this, key[i])); + } + } + else + { + this.addFile(new ScenePluginFile(this, key, url, systemKey, sceneKey, xhrSettings)); + } + + return this; +}); + +module.exports = ScenePluginFile; + + +/***/ }), + +/***/ 34328: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Script File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#script method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#script. + * + * @class ScriptFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.ScriptFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {string} [type='script'] - The script type. Should be either 'script' for classic JavaScript, or 'module' if the file contains an exported module. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var ScriptFile = new Class({ + + Extends: File, + + initialize: + + function ScriptFile (loader, key, url, type, xhrSettings) + { + var extension = 'js'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + type = GetFastValue(config, 'type', 'script'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + else if (type === undefined) + { + type = 'script'; + } + + var fileConfig = { + type: type, + cache: false, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.ScriptFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = document.createElement('script'); + this.data.language = 'javascript'; + this.data.type = 'text/javascript'; + this.data.defer = false; + this.data.text = this.xhrLoader.responseText; + + document.head.appendChild(this.data); + + this.onProcessComplete(); + } + +}); + +/** + * Adds a Script file, or array of Script files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.script('aliens', 'lib/aliens.js'); + * } + * ``` + * + * If the script file contains a module, then you should specify that using the 'type' parameter: + * + * ```javascript + * function preload () + * { + * this.load.script('aliens', 'lib/aliens.js', 'module'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String and not already in-use by another file in the Loader. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.script({ + * key: 'aliens', + * url: 'lib/aliens.js', + * type: 'script' // or 'module' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.ScriptFileConfig` for more details. + * + * Once the file has finished loading it will automatically be converted into a script element + * via `document.createElement('script')`. It will have its language set to JavaScript, `defer` set to + * false and then the resulting element will be appended to `document.head`. Any code then in the + * script will be executed. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.js". It will always add `.js` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Script File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#script + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.ScriptFileConfig|Phaser.Types.Loader.FileTypes.ScriptFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.js`, i.e. if `key` was "alien" then the URL will be "alien.js". + * @param {string} [type='script'] - The script type. Should be either 'script' for classic JavaScript, or 'module' if the file contains an exported module. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('script', function (key, url, type, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new ScriptFile(this, key[i])); + } + } + else + { + this.addFile(new ScriptFile(this, key, url, type, xhrSettings)); + } + + return this; +}); + +module.exports = ScriptFile; + + +/***/ }), + +/***/ 85035: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var FileTypesManager = __webpack_require__(74099); +var ImageFile = __webpack_require__(19550); + +/** + * @classdesc + * A single Sprite Sheet Image File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#spritesheet method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#spritesheet. + * + * @class SpriteSheetFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.SpriteSheetFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {Phaser.Types.Loader.FileTypes.ImageFrameConfig} [frameConfig] - The frame configuration object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var SpriteSheetFile = new Class({ + + Extends: ImageFile, + + initialize: + + function SpriteSheetFile (loader, key, url, frameConfig, xhrSettings) + { + ImageFile.call(this, loader, key, url, xhrSettings, frameConfig); + + this.type = 'spritesheet'; + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.SpriteSheetFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + // Check if we have a linked normal map + var linkFile = this.linkFile; + + if (linkFile) + { + // We do, but has it loaded? + if (linkFile.state >= CONST.FILE_COMPLETE) + { + // Both files have loaded + if (this.type === 'normalMap') + { + // linkFile.data = Image + // this.data = Normal Map + this.cache.addSpriteSheet(this.key, linkFile.data, this.config, this.data); + } + else + { + // linkFile.data = Normal Map + // this.data = Image + this.cache.addSpriteSheet(this.key, this.data, this.config, linkFile.data); + } + } + + // Nothing to do here, we'll use the linkFile `addToCache` call + // to process this pair + } + else + { + this.cache.addSpriteSheet(this.key, this.data, this.config); + } + } + +}); + +/** + * Adds a Sprite Sheet Image, or array of Sprite Sheet Images, to the current load queue. + * + * The term 'Sprite Sheet' in Phaser means a fixed-size sheet. Where every frame in the sheet is the exact same size, + * and you reference those frames using numbers, not frame names. This is not the same thing as a Texture Atlas, where + * the frames are packed in a way where they take up the least amount of space, and are referenced by their names, + * not numbers. Some articles and software use the term 'Sprite Sheet' to mean Texture Atlas, so please be aware of + * what sort of file you're actually trying to load. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.spritesheet('bot', 'images/robot.png', { frameWidth: 32, frameHeight: 38 }); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * If you try to load an animated gif only the first frame will be rendered. Browsers do not natively support playback + * of animated gifs to Canvas elements. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.spritesheet({ + * key: 'bot', + * url: 'images/robot.png', + * frameConfig: { + * frameWidth: 32, + * frameHeight: 38, + * startFrame: 0, + * endFrame: 8 + * } + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.SpriteSheetFileConfig` for more details. + * + * Once the file has finished loading you can use it as a texture for a Game Object by referencing its key: + * + * ```javascript + * this.load.spritesheet('bot', 'images/robot.png', { frameWidth: 32, frameHeight: 38 }); + * // and later in your game ... + * this.add.image(x, y, 'bot', 0); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `PLAYER.` and the key was `Running` the final key will be `PLAYER.Running` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image, + * then you can specify it by providing an array as the `url` where the second element is the normal map: + * + * ```javascript + * this.load.spritesheet('logo', [ 'images/AtariLogo.png', 'images/AtariLogo-n.png' ], { frameWidth: 256, frameHeight: 80 }); + * ``` + * + * Or, if you are using a config object use the `normalMap` property: + * + * ```javascript + * this.load.spritesheet({ + * key: 'logo', + * url: 'images/AtariLogo.png', + * normalMap: 'images/AtariLogo-n.png', + * frameConfig: { + * frameWidth: 256, + * frameHeight: 80 + * } + * }); + * ``` + * + * The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings. + * Normal maps are a WebGL only feature. + * + * Note: The ability to load this type of file will only be available if the Sprite Sheet File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#spritesheet + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.SpriteSheetFileConfig|Phaser.Types.Loader.FileTypes.SpriteSheetFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {Phaser.Types.Loader.FileTypes.ImageFrameConfig} [frameConfig] - The frame configuration object. At a minimum it should have a `frameWidth` property. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('spritesheet', function (key, url, frameConfig, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new SpriteSheetFile(this, key[i])); + } + } + else + { + this.addFile(new SpriteSheetFile(this, key, url, frameConfig, xhrSettings)); + } + + return this; +}); + +module.exports = SpriteSheetFile; + + +/***/ }), + +/***/ 78776: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Text File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#text method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#text. + * + * @class TextFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.TextFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var TextFile = new Class({ + + Extends: File, + + initialize: + + function TextFile (loader, key, url, xhrSettings) + { + var type = 'text'; + var extension = 'txt'; + var cache = loader.cacheManager.text; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + type = GetFastValue(config, 'type', type); + cache = GetFastValue(config, 'cache', cache); + } + + var fileConfig = { + type: type, + cache: cache, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.TextFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = this.xhrLoader.responseText; + + this.onProcessComplete(); + } + +}); + +/** + * Adds a Text file, or array of Text files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.text('story', 'files/IntroStory.txt'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Text Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Text Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Text Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.text({ + * key: 'story', + * url: 'files/IntroStory.txt' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.TextFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.text('story', 'files/IntroStory.txt'); + * // and later in your game ... + * var data = this.cache.text.get('story'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Story` the final key will be `LEVEL1.Story` and + * this is what you would use to retrieve the text from the Text Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "story" + * and no URL is given then the Loader will set the URL to be "story.txt". It will always add `.txt` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Text File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#text + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.TextFileConfig|Phaser.Types.Loader.FileTypes.TextFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('text', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new TextFile(this, key[i])); + } + } + else + { + this.addFile(new TextFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = TextFile; + + +/***/ }), + +/***/ 49477: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); +var TILEMAP_FORMATS = __webpack_require__(80341); + +/** + * @classdesc + * A single Tilemap CSV File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#tilemapCSV method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#tilemapCSV. + * + * @class TilemapCSVFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.TilemapCSVFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.csv`, i.e. if `key` was "alien" then the URL will be "alien.csv". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var TilemapCSVFile = new Class({ + + Extends: File, + + initialize: + + function TilemapCSVFile (loader, key, url, xhrSettings) + { + var extension = 'csv'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'tilemapCSV', + cache: loader.cacheManager.tilemap, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + + this.tilemapFormat = TILEMAP_FORMATS.CSV; + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.TilemapCSVFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = this.xhrLoader.responseText; + + this.onProcessComplete(); + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.TilemapCSVFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + var tiledata = { format: this.tilemapFormat, data: this.data }; + + this.cache.add(this.key, tiledata); + } + +}); + +/** + * Adds a CSV Tilemap file, or array of CSV files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.tilemapCSV('level1', 'maps/Level1.csv'); + * } + * ``` + * + * Tilemap CSV data can be created in a text editor, or a 3rd party app that exports as CSV. + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Tilemap Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Tilemap Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Text Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.tilemapCSV({ + * key: 'level1', + * url: 'maps/Level1.csv' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.TilemapCSVFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.tilemapCSV('level1', 'maps/Level1.csv'); + * // and later in your game ... + * var map = this.make.tilemap({ key: 'level1' }); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Story` the final key will be `LEVEL1.Story` and + * this is what you would use to retrieve the text from the Tilemap Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "level" + * and no URL is given then the Loader will set the URL to be "level.csv". It will always add `.csv` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Tilemap CSV File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#tilemapCSV + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.TilemapCSVFileConfig|Phaser.Types.Loader.FileTypes.TilemapCSVFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.csv`, i.e. if `key` was "alien" then the URL will be "alien.csv". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('tilemapCSV', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new TilemapCSVFile(this, key[i])); + } + } + else + { + this.addFile(new TilemapCSVFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = TilemapCSVFile; + + +/***/ }), + +/***/ 40807: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var JSONFile = __webpack_require__(518); +var TILEMAP_FORMATS = __webpack_require__(80341); + +/** + * @classdesc + * A single Impact.js Tilemap JSON File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#tilemapImpact method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#tilemapImpact. + * + * @class TilemapImpactFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.TilemapImpactFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var TilemapImpactFile = new Class({ + + Extends: JSONFile, + + initialize: + + function TilemapImpactFile (loader, key, url, xhrSettings) + { + JSONFile.call(this, loader, key, url, xhrSettings); + + this.type = 'tilemapJSON'; + + this.cache = loader.cacheManager.tilemap; + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.TilemapImpactFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + var tiledata = { format: TILEMAP_FORMATS.WELTMEISTER, data: this.data }; + + this.cache.add(this.key, tiledata); + } + +}); + +/** + * Adds an Impact.js Tilemap file, or array of map files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.tilemapImpact('level1', 'maps/Level1.json'); + * } + * ``` + * + * Impact Tilemap data is created the Impact.js Map Editor called Weltmeister. + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Tilemap Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Tilemap Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Text Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.tilemapImpact({ + * key: 'level1', + * url: 'maps/Level1.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.TilemapImpactFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.tilemapImpact('level1', 'maps/Level1.json'); + * // and later in your game ... + * var map = this.make.tilemap({ key: 'level1' }); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Story` the final key will be `LEVEL1.Story` and + * this is what you would use to retrieve the text from the Tilemap Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "level" + * and no URL is given then the Loader will set the URL to be "level.json". It will always add `.json` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Tilemap Impact File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#tilemapImpact + * @fires Phaser.Loader.Events#ADD + * @since 3.7.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.TilemapImpactFileConfig|Phaser.Types.Loader.FileTypes.TilemapImpactFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('tilemapImpact', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new TilemapImpactFile(this, key[i])); + } + } + else + { + this.addFile(new TilemapImpactFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = TilemapImpactFile; + + +/***/ }), + +/***/ 56775: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var JSONFile = __webpack_require__(518); +var TILEMAP_FORMATS = __webpack_require__(80341); + +/** + * @classdesc + * A single Tiled Tilemap JSON File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#tilemapTiledJSON method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#tilemapTiledJSON. + * + * @class TilemapJSONFile + * @extends Phaser.Loader.FileTypes.JSONFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.TilemapJSONFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {object|string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, a well formed JSON object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var TilemapJSONFile = new Class({ + + Extends: JSONFile, + + initialize: + + function TilemapJSONFile (loader, key, url, xhrSettings) + { + JSONFile.call(this, loader, key, url, xhrSettings); + + this.type = 'tilemapJSON'; + + this.cache = loader.cacheManager.tilemap; + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.TilemapJSONFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + var tiledata = { format: TILEMAP_FORMATS.TILED_JSON, data: this.data }; + + this.cache.add(this.key, tiledata); + } + +}); + +/** + * Adds a Tiled JSON Tilemap file, or array of map files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.tilemapTiledJSON('level1', 'maps/Level1.json'); + * } + * ``` + * + * The Tilemap data is created using the Tiled Map Editor and selecting JSON as the export format. + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Tilemap Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Tilemap Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Text Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.tilemapTiledJSON({ + * key: 'level1', + * url: 'maps/Level1.json' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.TilemapJSONFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.tilemapTiledJSON('level1', 'maps/Level1.json'); + * // and later in your game ... + * var map = this.make.tilemap({ key: 'level1' }); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Story` the final key will be `LEVEL1.Story` and + * this is what you would use to retrieve the text from the Tilemap Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "level" + * and no URL is given then the Loader will set the URL to be "level.json". It will always add `.json` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the Tilemap JSON File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#tilemapTiledJSON + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.TilemapJSONFileConfig|Phaser.Types.Loader.FileTypes.TilemapJSONFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {object|string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, a well formed JSON object. + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('tilemapTiledJSON', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new TilemapJSONFile(this, key[i])); + } + } + else + { + this.addFile(new TilemapJSONFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = TilemapJSONFile; + + +/***/ }), + +/***/ 25771: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var ImageFile = __webpack_require__(19550); +var IsPlainObject = __webpack_require__(41212); +var MultiFile = __webpack_require__(26430); +var TextFile = __webpack_require__(78776); + +/** + * @classdesc + * A single text file based Unity Texture Atlas File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#unityAtlas method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#unityAtlas. + * + * @class UnityAtlasFile + * @extends Phaser.Loader.MultiFile + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.UnityAtlasFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas data file from. If undefined or `null` it will be set to `.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt". + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings. + */ +var UnityAtlasFile = new Class({ + + Extends: MultiFile, + + initialize: + + function UnityAtlasFile (loader, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) + { + var image; + var data; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + + image = new ImageFile(loader, { + key: key, + url: GetFastValue(config, 'textureURL'), + extension: GetFastValue(config, 'textureExtension', 'png'), + normalMap: GetFastValue(config, 'normalMap'), + xhrSettings: GetFastValue(config, 'textureXhrSettings') + }); + + data = new TextFile(loader, { + key: key, + url: GetFastValue(config, 'atlasURL'), + extension: GetFastValue(config, 'atlasExtension', 'txt'), + xhrSettings: GetFastValue(config, 'atlasXhrSettings') + }); + } + else + { + image = new ImageFile(loader, key, textureURL, textureXhrSettings); + data = new TextFile(loader, key, atlasURL, atlasXhrSettings); + } + + if (image.linkFile) + { + // Image has a normal map + MultiFile.call(this, loader, 'unityatlas', key, [ image, data, image.linkFile ]); + } + else + { + MultiFile.call(this, loader, 'unityatlas', key, [ image, data ]); + } + }, + + /** + * Adds this file to its target cache upon successful loading and processing. + * + * @method Phaser.Loader.FileTypes.UnityAtlasFile#addToCache + * @since 3.7.0 + */ + addToCache: function () + { + if (this.isReadyToProcess()) + { + var image = this.files[0]; + var text = this.files[1]; + var normalMap = (this.files[2]) ? this.files[2].data : null; + + this.loader.textureManager.addUnityAtlas(image.key, image.data, text.data, normalMap); + + this.complete = true; + } + } + +}); + +/** + * Adds a Unity YAML based Texture Atlas, or array of atlases, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.unityAtlas('mainmenu', 'images/MainMenu.png', 'images/MainMenu.txt'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring + * its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details. + * + * Phaser expects the atlas data to be provided in a YAML formatted text file as exported from Unity. + * + * Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle. + * + * The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Texture Manager. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Texture Manager first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.unityAtlas({ + * key: 'mainmenu', + * textureURL: 'images/MainMenu.png', + * atlasURL: 'images/MainMenu.txt' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.UnityAtlasFileConfig` for more details. + * + * Once the atlas has finished loading you can use frames from it as textures for a Game Object by referencing its key: + * + * ```javascript + * this.load.unityAtlas('mainmenu', 'images/MainMenu.png', 'images/MainMenu.json'); + * // and later in your game ... + * this.add.image(x, y, 'mainmenu', 'background'); + * ``` + * + * To get a list of all available frames within an atlas please consult your Texture Atlas software. + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and + * this is what you would use to retrieve the image from the Texture Manager. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien" + * and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image, + * then you can specify it by providing an array as the `url` where the second element is the normal map: + * + * ```javascript + * this.load.unityAtlas('mainmenu', [ 'images/MainMenu.png', 'images/MainMenu-n.png' ], 'images/MainMenu.txt'); + * ``` + * + * Or, if you are using a config object use the `normalMap` property: + * + * ```javascript + * this.load.unityAtlas({ + * key: 'mainmenu', + * textureURL: 'images/MainMenu.png', + * normalMap: 'images/MainMenu-n.png', + * atlasURL: 'images/MainMenu.txt' + * }); + * ``` + * + * The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings. + * Normal maps are a WebGL only feature. + * + * Note: The ability to load this type of file will only be available if the Unity Atlas File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#unityAtlas + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.UnityAtlasFileConfig|Phaser.Types.Loader.FileTypes.UnityAtlasFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string|string[]} [textureURL] - The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was "alien" then the URL will be "alien.png". + * @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas data file from. If undefined or `null` it will be set to `.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt". + * @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the atlas image file. Used in replacement of the Loaders default XHR Settings. + * @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('unityAtlas', function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) +{ + var multifile; + + // Supports an Object file definition in the key argument + // Or an array of objects in the key argument + // Or a single entry where all arguments have been defined + + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + multifile = new UnityAtlasFile(this, key[i]); + + this.addFile(multifile.files); + } + } + else + { + multifile = new UnityAtlasFile(this, key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings); + + this.addFile(multifile.files); + } + + return this; +}); + +module.exports = UnityAtlasFile; + + +/***/ }), + +/***/ 33720: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetURL = __webpack_require__(98356); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * A single Video File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#video method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#video. + * + * @class VideoFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.20.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.VideoFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {(string|string[]|Phaser.Types.Loader.FileTypes.VideoFileURLConfig|Phaser.Types.Loader.FileTypes.VideoFileURLConfig[])} [urls] - The absolute or relative URL to load the video files from. + * @param {boolean} [noAudio=false] - Does the video have an audio track? If not you can enable auto-playing on it. + */ +var VideoFile = new Class({ + + Extends: File, + + initialize: + + function VideoFile (loader, key, url, noAudio) + { + if (noAudio === undefined) { noAudio = false; } + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url', []); + noAudio = GetFastValue(config, 'noAudio', false); + } + + var urlConfig = loader.systems.game.device.video.getVideoURL(url); + + if (!urlConfig) + { + console.warn('VideoFile: No supported format for ' + key); + } + + var fileConfig = { + type: 'video', + cache: loader.cacheManager.video, + extension: urlConfig.type, + key: key, + url: urlConfig.url, + config: { + noAudio: noAudio + } + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.VideoFile#onProcess + * @since 3.20.0 + */ + onProcess: function () + { + this.data = { + url: this.src, + noAudio: this.config.noAudio, + crossOrigin: this.crossOrigin + }; + + this.onProcessComplete(); + }, + + /** + * Called by the Loader, starts the actual file downloading. + * During the load the methods onLoad, onError and onProgress are called, based on the XHR events. + * You shouldn't normally call this method directly, it's meant to be invoked by the Loader. + * + * @method Phaser.Loader.FileTypes.VideoFile#load + * @since 3.20.0 + */ + load: function () + { + // We set these, but we don't actually load anything (the Video Game Object does that) + + this.src = GetURL(this, this.loader.baseURL); + + this.state = CONST.FILE_LOADED; + + this.loader.nextFile(this, true); + } + +}); + +/** + * Adds a Video file, or array of video files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.video('intro', [ 'video/level1.mp4', 'video/level1.webm', 'video/level1.mov' ]); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global Video Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the Video Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the Video Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.video({ + * key: 'intro', + * url: [ 'video/level1.mp4', 'video/level1.webm', 'video/level1.mov' ], + * noAudio: true + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.VideoFileConfig` for more details. + * + * The URLs can be relative or absolute. If the URLs are relative the `Loader.baseURL` and `Loader.path` values will be prepended to them. + * + * Due to different browsers supporting different video file types you should usually provide your video files in a variety of formats. + * mp4, mov and webm are the most common. If you provide an array of URLs then the Loader will determine which _one_ file to load based on + * browser support, starting with the first in the array and progressing to the end. + * + * Unlike most asset-types, videos do not _need_ to be preloaded. You can create a Video Game Object and then call its `loadURL` method, + * to load a video at run-time, rather than in advance. + * + * Note: The ability to load this type of file will only be available if the Video File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#video + * @fires Phaser.Loader.Events#ADD + * @since 3.20.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.VideoFileConfig|Phaser.Types.Loader.FileTypes.VideoFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {(string|string[]|Phaser.Types.Loader.FileTypes.VideoFileURLConfig|Phaser.Types.Loader.FileTypes.VideoFileURLConfig[])} [urls] - The absolute or relative URL to load the video files from. + * @param {boolean} [noAudio=false] - Does the video have an audio track? If not you can enable auto-playing on it. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('video', function (key, urls, noAudio) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + this.addFile(new VideoFile(this, key[i])); + } + } + else + { + this.addFile(new VideoFile(this, key, urls, noAudio)); + } + + return this; +}); + +module.exports = VideoFile; + + +/***/ }), + +/***/ 57318: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(23906); +var File = __webpack_require__(41299); +var FileTypesManager = __webpack_require__(74099); +var GetFastValue = __webpack_require__(95540); +var IsPlainObject = __webpack_require__(41212); +var ParseXML = __webpack_require__(56836); + +/** + * @classdesc + * A single XML File suitable for loading by the Loader. + * + * These are created when you use the Phaser.Loader.LoaderPlugin#xml method and are not typically created directly. + * + * For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#xml. + * + * @class XMLFile + * @extends Phaser.Loader.File + * @memberof Phaser.Loader.FileTypes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file. + * @param {(string|Phaser.Types.Loader.FileTypes.XMLFileConfig)} key - The key to use for this file, or a file configuration object. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was "alien" then the URL will be "alien.xml". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file. + */ +var XMLFile = new Class({ + + Extends: File, + + initialize: + + function XMLFile (loader, key, url, xhrSettings) + { + var extension = 'xml'; + + if (IsPlainObject(key)) + { + var config = key; + + key = GetFastValue(config, 'key'); + url = GetFastValue(config, 'url'); + xhrSettings = GetFastValue(config, 'xhrSettings'); + extension = GetFastValue(config, 'extension', extension); + } + + var fileConfig = { + type: 'xml', + cache: loader.cacheManager.xml, + extension: extension, + responseType: 'text', + key: key, + url: url, + xhrSettings: xhrSettings + }; + + File.call(this, loader, fileConfig); + }, + + /** + * Called automatically by Loader.nextFile. + * This method controls what extra work this File does with its loaded data. + * + * @method Phaser.Loader.FileTypes.XMLFile#onProcess + * @since 3.7.0 + */ + onProcess: function () + { + this.state = CONST.FILE_PROCESSING; + + this.data = ParseXML(this.xhrLoader.responseText); + + if (this.data) + { + this.onProcessComplete(); + } + else + { + this.onProcessError(); + } + } + +}); + +/** + * Adds an XML file, or array of XML files, to the current load queue. + * + * You can call this method from within your Scene's `preload`, along with any other files you wish to load: + * + * ```javascript + * function preload () + * { + * this.load.xml('wavedata', 'files/AlienWaveData.xml'); + * } + * ``` + * + * The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts, + * or if it's already running, when the next free load slot becomes available. This happens automatically if you + * are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued + * it means you cannot use the file immediately after calling this method, but must wait for the file to complete. + * The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the + * Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been + * loaded. + * + * The key must be a unique String. It is used to add the file to the global XML Cache upon a successful load. + * The key should be unique both in terms of files being loaded and files already present in the XML Cache. + * Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file + * then remove it from the XML Cache first, before loading a new one. + * + * Instead of passing arguments you can pass a configuration object, such as: + * + * ```javascript + * this.load.xml({ + * key: 'wavedata', + * url: 'files/AlienWaveData.xml' + * }); + * ``` + * + * See the documentation for `Phaser.Types.Loader.FileTypes.XMLFileConfig` for more details. + * + * Once the file has finished loading you can access it from its Cache using its key: + * + * ```javascript + * this.load.xml('wavedata', 'files/AlienWaveData.xml'); + * // and later in your game ... + * var data = this.cache.xml.get('wavedata'); + * ``` + * + * If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files + * key. For example, if the prefix was `LEVEL1.` and the key was `Waves` the final key will be `LEVEL1.Waves` and + * this is what you would use to retrieve the text from the XML Cache. + * + * The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it. + * + * If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "data" + * and no URL is given then the Loader will set the URL to be "data.xml". It will always add `.xml` as the extension, although + * this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL. + * + * Note: The ability to load this type of file will only be available if the XML File type has been built into Phaser. + * It is available in the default build but can be excluded from custom builds. + * + * @method Phaser.Loader.LoaderPlugin#xml + * @fires Phaser.Loader.Events#ADD + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Loader.FileTypes.XMLFileConfig|Phaser.Types.Loader.FileTypes.XMLFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them. + * @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was "alien" then the URL will be "alien.xml". + * @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings. + * + * @return {this} The Loader instance. + */ +FileTypesManager.register('xml', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(new XMLFile(this, key[i])); + } + } + else + { + this.addFile(new XMLFile(this, key, url, xhrSettings)); + } + + return this; +}); + +module.exports = XMLFile; + + +/***/ }), + +/***/ 64589: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Loader.FileTypes + */ + +module.exports = { + + AnimationJSONFile: __webpack_require__(14135), + AsepriteFile: __webpack_require__(76272), + AtlasJSONFile: __webpack_require__(38734), + AtlasXMLFile: __webpack_require__(74599), + AudioFile: __webpack_require__(21097), + AudioSpriteFile: __webpack_require__(89524), + BinaryFile: __webpack_require__(85722), + BitmapFontFile: __webpack_require__(97025), + CompressedTextureFile: __webpack_require__(69559), + CSSFile: __webpack_require__(16024), + FontFile: __webpack_require__(87674), + GLSLFile: __webpack_require__(47931), + HTML5AudioFile: __webpack_require__(89749), + HTMLFile: __webpack_require__(88470), + HTMLTextureFile: __webpack_require__(14643), + ImageFile: __webpack_require__(19550), + JSONFile: __webpack_require__(518), + MultiAtlasFile: __webpack_require__(59327), + MultiScriptFile: __webpack_require__(99297), + PackFile: __webpack_require__(58610), + PluginFile: __webpack_require__(48988), + SceneFile: __webpack_require__(88423), + ScenePluginFile: __webpack_require__(56812), + ScriptFile: __webpack_require__(34328), + SpriteSheetFile: __webpack_require__(85035), + SVGFile: __webpack_require__(67397), + TextFile: __webpack_require__(78776), + TilemapCSVFile: __webpack_require__(49477), + TilemapImpactFile: __webpack_require__(40807), + TilemapJSONFile: __webpack_require__(56775), + UnityAtlasFile: __webpack_require__(25771), + VideoFile: __webpack_require__(33720), + XMLFile: __webpack_require__(57318) + +}; + + +/***/ }), + +/***/ 57777: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(23906); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Loader + */ + +var Loader = { + + Events: __webpack_require__(54899), + + FileTypes: __webpack_require__(64589), + + File: __webpack_require__(41299), + FileTypesManager: __webpack_require__(74099), + GetURL: __webpack_require__(98356), + LoaderPlugin: __webpack_require__(74261), + MergeXHRSettings: __webpack_require__(3374), + MultiFile: __webpack_require__(26430), + XHRLoader: __webpack_require__(84376), + XHRSettings: __webpack_require__(92638) + +}; + +// Merge in the consts +Loader = Extend(false, Loader, CONST); + +module.exports = Loader; + + +/***/ }), + +/***/ 53307: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the mean average of the given values. + * + * @function Phaser.Math.Average + * @since 3.0.0 + * + * @param {number[]} values - The values to average. + * + * @return {number} The average value. + */ +var Average = function (values) +{ + var sum = 0; + + for (var i = 0; i < values.length; i++) + { + sum += (+values[i]); + } + + return sum / values.length; +}; + +module.exports = Average; + + +/***/ }), + +/***/ 85710: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Factorial = __webpack_require__(6411); + +/** + * Calculates the Bernstein basis from the three factorial coefficients. + * + * @function Phaser.Math.Bernstein + * @since 3.0.0 + * + * @param {number} n - The first value. + * @param {number} i - The second value. + * + * @return {number} The Bernstein basis of Factorial(n) / Factorial(i) / Factorial(n - i) + */ +var Bernstein = function (n, i) +{ + return Factorial(n) / Factorial(i) / Factorial(n - i); +}; + +module.exports = Bernstein; + + +/***/ }), + +/***/ 30976: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compute a random integer between the `min` and `max` values, inclusive. + * + * @function Phaser.Math.Between + * @since 3.0.0 + * + * @param {number} min - The minimum value. + * @param {number} max - The maximum value. + * + * @return {number} The random integer. + */ +var Between = function (min, max) +{ + return Math.floor(Math.random() * (max - min + 1) + min); +}; + +module.exports = Between; + + +/***/ }), + +/***/ 87842: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates a Catmull-Rom value from the given points, based on an alpha of 0.5. + * + * @function Phaser.Math.CatmullRom + * @since 3.0.0 + * + * @param {number} t - The amount to interpolate by. + * @param {number} p0 - The first control point. + * @param {number} p1 - The second control point. + * @param {number} p2 - The third control point. + * @param {number} p3 - The fourth control point. + * + * @return {number} The Catmull-Rom value. + */ +var CatmullRom = function (t, p0, p1, p2, p3) +{ + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + var t2 = t * t; + var t3 = t * t2; + + return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; +}; + +module.exports = CatmullRom; + + +/***/ }), + +/***/ 26302: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Ceils to some place comparative to a `base`, default is 10 for decimal place. + * + * The `place` is represented by the power applied to `base` to get that place. + * + * @function Phaser.Math.CeilTo + * @since 3.0.0 + * + * @param {number} value - The value to round. + * @param {number} [place=0] - The place to round to. + * @param {number} [base=10] - The base to round in. Default is 10 for decimal. + * + * @return {number} The rounded value. + */ +var CeilTo = function (value, place, base) +{ + if (place === undefined) { place = 0; } + if (base === undefined) { base = 10; } + + var p = Math.pow(base, -place); + + return Math.ceil(value * p) / p; +}; + +module.exports = CeilTo; + + +/***/ }), + +/***/ 45319: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Force a value within the boundaries by clamping it to the range `min`, `max`. + * + * @function Phaser.Math.Clamp + * @since 3.0.0 + * + * @param {number} value - The value to be clamped. + * @param {number} min - The minimum bounds. + * @param {number} max - The maximum bounds. + * + * @return {number} The clamped value. + */ +var Clamp = function (value, min, max) +{ + return Math.max(min, Math.min(max, value)); +}; + +module.exports = Clamp; + + +/***/ }), + +/***/ 39506: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(36383); + +/** + * Convert the given angle from degrees, to the equivalent angle in radians. + * + * @function Phaser.Math.DegToRad + * @since 3.0.0 + * + * @param {number} degrees - The angle (in degrees) to convert to radians. + * + * @return {number} The given angle converted to radians. + */ +var DegToRad = function (degrees) +{ + return degrees * CONST.DEG_TO_RAD; +}; + +module.exports = DegToRad; + + +/***/ }), + +/***/ 61241: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the positive difference of two given numbers. + * + * @function Phaser.Math.Difference + * @since 3.0.0 + * + * @param {number} a - The first number in the calculation. + * @param {number} b - The second number in the calculation. + * + * @return {number} The positive difference of the two given numbers. + */ +var Difference = function (a, b) +{ + return Math.abs(a - b); +}; + +module.exports = Difference; + + +/***/ }), + +/***/ 38857: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Matrix4 = __webpack_require__(37867); +var NOOP = __webpack_require__(29747); + +var tempMatrix = new Matrix4(); + +/** + * @classdesc + * + * @class Euler + * @memberof Phaser.Math + * @constructor + * @since 3.50.0 + * + * @param {number} [x] - The x component. + * @param {number} [y] - The y component. + * @param {number} [z] - The z component. + */ +var Euler = new Class({ + + initialize: + + function Euler (x, y, z, order) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (z === undefined) { z = 0; } + if (order === undefined) { order = Euler.DefaultOrder; } + + this._x = x; + this._y = y; + this._z = z; + this._order = order; + + this.onChangeCallback = NOOP; + }, + + x: { + get: function () + { + return this._x; + }, + + set: function (value) + { + this._x = value; + + this.onChangeCallback(this); + } + }, + + y: { + get: function () + { + return this._y; + }, + + set: function (value) + { + this._y = value; + + this.onChangeCallback(this); + } + }, + + z: { + get: function () + { + return this._z; + }, + + set: function (value) + { + this._z = value; + + this.onChangeCallback(this); + } + }, + + order: { + get: function () + { + return this._order; + }, + + set: function (value) + { + this._order = value; + + this.onChangeCallback(this); + } + }, + + set: function (x, y, z, order) + { + if (order === undefined) { order = this._order; } + + this._x = x; + this._y = y; + this._z = z; + this._order = order; + + this.onChangeCallback(this); + + return this; + }, + + copy: function (euler) + { + return this.set(euler.x, euler.y, euler.z, euler.order); + }, + + setFromQuaternion: function (quaternion, order, update) + { + if (order === undefined) { order = this._order; } + if (update === undefined) { update = false; } + + tempMatrix.fromQuat(quaternion); + + return this.setFromRotationMatrix(tempMatrix, order, update); + }, + + setFromRotationMatrix: function (matrix, order, update) + { + if (order === undefined) { order = this._order; } + if (update === undefined) { update = false; } + + var elements = matrix.val; + + // Upper 3x3 of matrix is un-scaled rotation matrix + var m11 = elements[0]; + var m12 = elements[4]; + var m13 = elements[8]; + var m21 = elements[1]; + var m22 = elements[5]; + var m23 = elements[9]; + var m31 = elements[2]; + var m32 = elements[6]; + var m33 = elements[10]; + + var x = 0; + var y = 0; + var z = 0; + var epsilon = 0.99999; + + switch (order) + { + case 'XYZ': + { + y = Math.asin(Clamp(m13, -1, 1)); + + if (Math.abs(m13) < epsilon) + { + x = Math.atan2(-m23, m33); + z = Math.atan2(-m12, m11); + } + else + { + x = Math.atan2(m32, m22); + } + + break; + } + + case 'YXZ': + { + x = Math.asin(-Clamp(m23, -1, 1)); + + if (Math.abs(m23) < epsilon) + { + y = Math.atan2(m13, m33); + z = Math.atan2(m21, m22); + } + else + { + y = Math.atan2(-m31, m11); + } + + break; + } + + case 'ZXY': + { + x = Math.asin(Clamp(m32, -1, 1)); + + if (Math.abs(m32) < epsilon) + { + y = Math.atan2(-m31, m33); + z = Math.atan2(-m12, m22); + } + else + { + z = Math.atan2(m21, m11); + } + + break; + } + + case 'ZYX': + { + y = Math.asin(-Clamp(m31, -1, 1)); + + if (Math.abs(m31) < epsilon) + { + x = Math.atan2(m32, m33); + z = Math.atan2(m21, m11); + } + else + { + z = Math.atan2(-m12, m22); + } + + break; + } + + case 'YZX': + { + z = Math.asin(Clamp(m21, -1, 1)); + + if (Math.abs(m21) < epsilon) + { + x = Math.atan2(-m23, m22); + y = Math.atan2(-m31, m11); + } + else + { + y = Math.atan2(m13, m33); + } + + break; + } + + case 'XZY': + { + z = Math.asin(-Clamp(m12, -1, 1)); + + if (Math.abs(m12) < epsilon) + { + x = Math.atan2(m32, m22); + y = Math.atan2(m13, m11); + } + else + { + x = Math.atan2(-m23, m33); + } + + break; + } + } + + this._x = x; + this._y = y; + this._z = z; + this._order = order; + + if (update) + { + this.onChangeCallback(this); + } + + return this; + } + +}); + +Euler.RotationOrders = [ 'XYZ', 'YXZ', 'ZXY', 'ZYX', 'YZX', 'XZY' ]; + +Euler.DefaultOrder = 'XYZ'; + +module.exports = Euler; + + +/***/ }), + +/***/ 6411: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates the factorial of a given number for integer values greater than 0. + * + * @function Phaser.Math.Factorial + * @since 3.0.0 + * + * @param {number} value - A positive integer to calculate the factorial of. + * + * @return {number} The factorial of the given number. + */ +var Factorial = function (value) +{ + if (value === 0) + { + return 1; + } + + var res = value; + + while (--value) + { + res *= value; + } + + return res; +}; + +module.exports = Factorial; + + +/***/ }), + +/***/ 99472: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Generate a random floating point number between the two given bounds, minimum inclusive, maximum exclusive. + * + * @function Phaser.Math.FloatBetween + * @since 3.0.0 + * + * @param {number} min - The lower bound for the float, inclusive. + * @param {number} max - The upper bound for the float exclusive. + * + * @return {number} A random float within the given range. + */ +var FloatBetween = function (min, max) +{ + return Math.random() * (max - min) + min; +}; + +module.exports = FloatBetween; + + +/***/ }), + +/***/ 77623: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Floors to some place comparative to a `base`, default is 10 for decimal place. + * + * The `place` is represented by the power applied to `base` to get that place. + * + * @function Phaser.Math.FloorTo + * @since 3.0.0 + * + * @param {number} value - The value to round. + * @param {number} [place=0] - The place to round to. + * @param {number} [base=10] - The base to round in. Default is 10 for decimal. + * + * @return {number} The rounded value. + */ +var FloorTo = function (value, place, base) +{ + if (place === undefined) { place = 0; } + if (base === undefined) { base = 10; } + + var p = Math.pow(base, -place); + + return Math.floor(value * p) / p; +}; + +module.exports = FloorTo; + + +/***/ }), + +/***/ 62945: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); + +/** + * Return a value based on the range between `min` and `max` and the percentage given. + * + * @function Phaser.Math.FromPercent + * @since 3.0.0 + * + * @param {number} percent - A value between 0 and 1 representing the percentage. + * @param {number} min - The minimum value. + * @param {number} [max] - The maximum value. + * + * @return {number} The value that is `percent` percent between `min` and `max`. + */ +var FromPercent = function (percent, min, max) +{ + percent = Clamp(percent, 0, 1); + + return (max - min) * percent + min; +}; + +module.exports = FromPercent; + + +/***/ }), + +/***/ 2672: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Get the centroid or geometric center of a plane figure (the arithmetic mean position of all the points in the figure). + * Informally, it is the point at which a cutout of the shape could be perfectly balanced on the tip of a pin. + * + * @function Phaser.Math.GetCentroid + * @since 4.0.0 + * + * @generic {Phaser.Math.Vector2} O - [out,$return] + * + * @param {Phaser.Types.Math.Vector2Like[]} points - An array of Vector2Like objects to get the geometric center of. + * @param {Phaser.Math.Vector2} [out] - A Vector2 object to store the output coordinates in. If not given, a new Vector2 instance is created. + * + * @return {Phaser.Math.Vector2} A Vector2 object representing the geometric center of the given points. + */ +var GetCentroid = function (points, out) +{ + if (out === undefined) { out = new Vector2(); } + + var len = points.length; + + if (!Array.isArray(points) || len === 0) + { + throw new Error('GetCentroid points be a non-empty array'); + } + + if (len === 1) + { + out.x = points[0].x; + out.y = points[0].y; + } + else + { + for (var i = 0; i < len; i++) + { + out.x += points[i].x; + out.y += points[i].y; + } + + out.x /= len; + out.y /= len; + } + + return out; +}; + +module.exports = GetCentroid; + + +/***/ }), + +/***/ 38265: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate a per-ms speed from a distance and time (given in seconds). + * + * @function Phaser.Math.GetSpeed + * @since 3.0.0 + * + * @param {number} distance - The distance. + * @param {number} time - The time, in seconds. + * + * @return {number} The speed, in distance per ms. + * + * @example + * // 400px over 1 second is 0.4 px/ms + * Phaser.Math.GetSpeed(400, 1) // -> 0.4 + */ +var GetSpeed = function (distance, time) +{ + return (distance / time) / 1000; +}; + +module.exports = GetSpeed; + + +/***/ }), + +/***/ 55133: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); + +/** + * Calculates the Axis Aligned Bounding Box (or aabb) from an array of points. + * + * @function Phaser.Math.GetVec2Bounds + * @since 4.0.0 + * + * @generic {Phaser.Geom.Rectangle} O - [out,$return] + * + * @param {Phaser.Types.Math.Vector2Like[]} points - An array of Vector2Like objects to get the AABB from. + * @param {Phaser.Geom.Rectangle} [out] - A Rectangle object to store the results in. If not given, a new Rectangle instance is created. + * + * @return {Phaser.Geom.Rectangle} A Rectangle object holding the AABB values for the given points. + */ +var GetVec2Bounds = function (points, out) +{ + if (out === undefined) { out = new Rectangle(); } + + var xMax = Number.NEGATIVE_INFINITY; + var xMin = Number.POSITIVE_INFINITY; + var yMax = Number.NEGATIVE_INFINITY; + var yMin = Number.POSITIVE_INFINITY; + + for (var i = 0; i < points.length; i++) + { + var point = points[i]; + + if (point.x > xMax) + { + xMax = point.x; + } + + if (point.x < xMin) + { + xMin = point.x; + } + + if (point.y > yMax) + { + yMax = point.y; + } + + if (point.y < yMin) + { + yMin = point.y; + } + } + + out.x = xMin; + out.y = yMin; + out.width = xMax - xMin; + out.height = yMax - yMin; + + return out; +}; + +module.exports = GetVec2Bounds; + + +/***/ }), + +/***/ 78702: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check if a given value is an even number. + * + * @function Phaser.Math.IsEven + * @since 3.0.0 + * + * @param {number} value - The number to perform the check with. + * + * @return {boolean} Whether the number is even or not. + */ +var IsEven = function (value) +{ + // Use abstract equality == for "is number" test + + // eslint-disable-next-line eqeqeq + return (value == parseFloat(value)) ? !(value % 2) : void 0; +}; + +module.exports = IsEven; + + +/***/ }), + +/***/ 94883: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check if a given value is an even number using a strict type check. + * + * @function Phaser.Math.IsEvenStrict + * @since 3.0.0 + * + * @param {number} value - The number to perform the check with. + * + * @return {boolean} Whether the number is even or not. + */ +var IsEvenStrict = function (value) +{ + // Use strict equality === for "is number" test + return (value === parseFloat(value)) ? !(value % 2) : void 0; +}; + +module.exports = IsEvenStrict; + + +/***/ }), + +/***/ 28915: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates a linear (interpolation) value over t. + * + * @function Phaser.Math.Linear + * @since 3.0.0 + * + * @param {number} p0 - The first point. + * @param {number} p1 - The second point. + * @param {number} t - The percentage between p0 and p1 to return, represented as a number between 0 and 1. + * + * @return {number} The step t% of the way between p0 and p1. + */ +var Linear = function (p0, p1, t) +{ + return (p1 - p0) * t + p0; +}; + +module.exports = Linear; + + +/***/ }), + +/***/ 94908: +/***/ ((module) => { + +/** + * @author Greg McLean + * @copyright 2021 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Interpolates two given Vectors and returns a new Vector between them. + * + * Does not modify either of the passed Vectors. + * + * @function Phaser.Math.LinearXY + * @since 3.60.0 + * + * @param {Phaser.Math.Vector2} vector1 - Starting vector + * @param {Phaser.Math.Vector2} vector2 - Ending vector + * @param {number} [t=0] - The percentage between vector1 and vector2 to return, represented as a number between 0 and 1. + * + * @return {Phaser.Math.Vector2} The step t% of the way between vector1 and vector2. + */ +var LinearXY = function (vector1, vector2, t) +{ + if (t === undefined) { t = 0; } + + return vector1.clone().lerp(vector2, t); +}; + +module.exports = LinearXY; + + +/***/ }), + +/***/ 94434: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji +// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A three-dimensional matrix. + * + * Defaults to the identity matrix when instantiated. + * + * @class Matrix3 + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} [m] - Optional Matrix3 to copy values from. + */ +var Matrix3 = new Class({ + + initialize: + + function Matrix3 (m) + { + /** + * The matrix values. + * + * @name Phaser.Math.Matrix3#val + * @type {Float32Array} + * @since 3.0.0 + */ + this.val = new Float32Array(9); + + if (m) + { + // Assume Matrix3 with val: + this.copy(m); + } + else + { + // Default to identity + this.identity(); + } + }, + + /** + * Make a clone of this Matrix3. + * + * @method Phaser.Math.Matrix3#clone + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix3} A clone of this Matrix3. + */ + clone: function () + { + return new Matrix3(this); + }, + + /** + * This method is an alias for `Matrix3.copy`. + * + * @method Phaser.Math.Matrix3#set + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} src - The Matrix to set the values of this Matrix's from. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + set: function (src) + { + return this.copy(src); + }, + + /** + * Copy the values of a given Matrix into this Matrix. + * + * @method Phaser.Math.Matrix3#copy + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} src - The Matrix to copy the values from. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + copy: function (src) + { + var out = this.val; + var a = src.val; + + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + + return this; + }, + + /** + * Copy the values of a given Matrix4 into this Matrix3. + * + * @method Phaser.Math.Matrix3#fromMat4 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} m - The Matrix4 to copy the values from. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + fromMat4: function (m) + { + var a = m.val; + var out = this.val; + + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[4]; + out[4] = a[5]; + out[5] = a[6]; + out[6] = a[8]; + out[7] = a[9]; + out[8] = a[10]; + + return this; + }, + + /** + * Set the values of this Matrix from the given array. + * + * @method Phaser.Math.Matrix3#fromArray + * @since 3.0.0 + * + * @param {array} a - The array to copy the values from. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + fromArray: function (a) + { + var out = this.val; + + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + + return this; + }, + + /** + * Reset this Matrix to an identity (default) matrix. + * + * @method Phaser.Math.Matrix3#identity + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + identity: function () + { + var out = this.val; + + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 1; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 1; + + return this; + }, + + /** + * Transpose this Matrix. + * + * @method Phaser.Math.Matrix3#transpose + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + transpose: function () + { + var a = this.val; + var a01 = a[1]; + var a02 = a[2]; + var a12 = a[5]; + + a[1] = a[3]; + a[2] = a[6]; + a[3] = a01; + a[5] = a[7]; + a[6] = a02; + a[7] = a12; + + return this; + }, + + /** + * Invert this Matrix. + * + * @method Phaser.Math.Matrix3#invert + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + invert: function () + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a10 = a[3]; + var a11 = a[4]; + var a12 = a[5]; + var a20 = a[6]; + var a21 = a[7]; + var a22 = a[8]; + + var b01 = a22 * a11 - a12 * a21; + var b11 = -a22 * a10 + a12 * a20; + var b21 = a21 * a10 - a11 * a20; + + // Calculate the determinant + var det = a00 * b01 + a01 * b11 + a02 * b21; + + if (!det) + { + return null; + } + + det = 1 / det; + + a[0] = b01 * det; + a[1] = (-a22 * a01 + a02 * a21) * det; + a[2] = (a12 * a01 - a02 * a11) * det; + a[3] = b11 * det; + a[4] = (a22 * a00 - a02 * a20) * det; + a[5] = (-a12 * a00 + a02 * a10) * det; + a[6] = b21 * det; + a[7] = (-a21 * a00 + a01 * a20) * det; + a[8] = (a11 * a00 - a01 * a10) * det; + + return this; + }, + + /** + * Calculate the adjoint, or adjugate, of this Matrix. + * + * @method Phaser.Math.Matrix3#adjoint + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + adjoint: function () + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a10 = a[3]; + var a11 = a[4]; + var a12 = a[5]; + var a20 = a[6]; + var a21 = a[7]; + var a22 = a[8]; + + a[0] = (a11 * a22 - a12 * a21); + a[1] = (a02 * a21 - a01 * a22); + a[2] = (a01 * a12 - a02 * a11); + a[3] = (a12 * a20 - a10 * a22); + a[4] = (a00 * a22 - a02 * a20); + a[5] = (a02 * a10 - a00 * a12); + a[6] = (a10 * a21 - a11 * a20); + a[7] = (a01 * a20 - a00 * a21); + a[8] = (a00 * a11 - a01 * a10); + + return this; + }, + + /** + * Calculate the determinant of this Matrix. + * + * @method Phaser.Math.Matrix3#determinant + * @since 3.0.0 + * + * @return {number} The determinant of this Matrix. + */ + determinant: function () + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a10 = a[3]; + var a11 = a[4]; + var a12 = a[5]; + var a20 = a[6]; + var a21 = a[7]; + var a22 = a[8]; + + return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20); + }, + + /** + * Multiply this Matrix by the given Matrix. + * + * @method Phaser.Math.Matrix3#multiply + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} src - The Matrix to multiply this Matrix by. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + multiply: function (src) + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a10 = a[3]; + var a11 = a[4]; + var a12 = a[5]; + var a20 = a[6]; + var a21 = a[7]; + var a22 = a[8]; + + var b = src.val; + + var b00 = b[0]; + var b01 = b[1]; + var b02 = b[2]; + var b10 = b[3]; + var b11 = b[4]; + var b12 = b[5]; + var b20 = b[6]; + var b21 = b[7]; + var b22 = b[8]; + + a[0] = b00 * a00 + b01 * a10 + b02 * a20; + a[1] = b00 * a01 + b01 * a11 + b02 * a21; + a[2] = b00 * a02 + b01 * a12 + b02 * a22; + + a[3] = b10 * a00 + b11 * a10 + b12 * a20; + a[4] = b10 * a01 + b11 * a11 + b12 * a21; + a[5] = b10 * a02 + b11 * a12 + b12 * a22; + + a[6] = b20 * a00 + b21 * a10 + b22 * a20; + a[7] = b20 * a01 + b21 * a11 + b22 * a21; + a[8] = b20 * a02 + b21 * a12 + b22 * a22; + + return this; + }, + + /** + * Translate this Matrix using the given Vector. + * + * @method Phaser.Math.Matrix3#translate + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to translate this Matrix with. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + translate: function (v) + { + var a = this.val; + var x = v.x; + var y = v.y; + + a[6] = x * a[0] + y * a[3] + a[6]; + a[7] = x * a[1] + y * a[4] + a[7]; + a[8] = x * a[2] + y * a[5] + a[8]; + + return this; + }, + + /** + * Apply a rotation transformation to this Matrix. + * + * @method Phaser.Math.Matrix3#rotate + * @since 3.0.0 + * + * @param {number} rad - The angle in radians to rotate by. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + rotate: function (rad) + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a10 = a[3]; + var a11 = a[4]; + var a12 = a[5]; + + var s = Math.sin(rad); + var c = Math.cos(rad); + + a[0] = c * a00 + s * a10; + a[1] = c * a01 + s * a11; + a[2] = c * a02 + s * a12; + + a[3] = c * a10 - s * a00; + a[4] = c * a11 - s * a01; + a[5] = c * a12 - s * a02; + + return this; + }, + + /** + * Apply a scale transformation to this Matrix. + * + * Uses the `x` and `y` components of the given Vector to scale the Matrix. + * + * @method Phaser.Math.Matrix3#scale + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to scale this Matrix with. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + scale: function (v) + { + var a = this.val; + var x = v.x; + var y = v.y; + + a[0] = x * a[0]; + a[1] = x * a[1]; + a[2] = x * a[2]; + + a[3] = y * a[3]; + a[4] = y * a[4]; + a[5] = y * a[5]; + + return this; + }, + + /** + * Set the values of this Matrix from the given Quaternion. + * + * @method Phaser.Math.Matrix3#fromQuat + * @since 3.0.0 + * + * @param {Phaser.Math.Quaternion} q - The Quaternion to set the values of this Matrix from. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + fromQuat: function (q) + { + var x = q.x; + var y = q.y; + var z = q.z; + var w = q.w; + + var x2 = x + x; + var y2 = y + y; + var z2 = z + z; + + var xx = x * x2; + var xy = x * y2; + var xz = x * z2; + + var yy = y * y2; + var yz = y * z2; + var zz = z * z2; + + var wx = w * x2; + var wy = w * y2; + var wz = w * z2; + + var out = this.val; + + out[0] = 1 - (yy + zz); + out[3] = xy + wz; + out[6] = xz - wy; + + out[1] = xy - wz; + out[4] = 1 - (xx + zz); + out[7] = yz + wx; + + out[2] = xz + wy; + out[5] = yz - wx; + out[8] = 1 - (xx + yy); + + return this; + }, + + /** + * Set the values of this Matrix3 to be normalized from the given Matrix4. + * + * @method Phaser.Math.Matrix3#normalFromMat4 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} m - The Matrix4 to normalize the values from. + * + * @return {Phaser.Math.Matrix3} This Matrix3. + */ + normalFromMat4: function (m) + { + var a = m.val; + var out = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + var b00 = a00 * a11 - a01 * a10; + var b01 = a00 * a12 - a02 * a10; + var b02 = a00 * a13 - a03 * a10; + var b03 = a01 * a12 - a02 * a11; + + var b04 = a01 * a13 - a03 * a11; + var b05 = a02 * a13 - a03 * a12; + var b06 = a20 * a31 - a21 * a30; + var b07 = a20 * a32 - a22 * a30; + + var b08 = a20 * a33 - a23 * a30; + var b09 = a21 * a32 - a22 * a31; + var b10 = a21 * a33 - a23 * a31; + var b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) + { + return null; + } + + det = 1 / det; + + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + + out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + + out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + + return this; + } + +}); + +module.exports = Matrix3; + + +/***/ }), + +/***/ 37867: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Vector3 = __webpack_require__(25836); + +/** + * @ignore + */ +var EPSILON = 0.000001; + +/** + * @classdesc + * A four-dimensional matrix. + * + * Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji + * and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl + * + * @class Matrix4 + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} [m] - Optional Matrix4 to copy values from. + */ +var Matrix4 = new Class({ + + initialize: + + function Matrix4 (m) + { + /** + * The matrix values. + * + * @name Phaser.Math.Matrix4#val + * @type {Float32Array} + * @since 3.0.0 + */ + this.val = new Float32Array(16); + + if (m) + { + // Assume Matrix4 with val: + this.copy(m); + } + else + { + // Default to identity + this.identity(); + } + }, + + /** + * Make a clone of this Matrix4. + * + * @method Phaser.Math.Matrix4#clone + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix4} A clone of this Matrix4. + */ + clone: function () + { + return new Matrix4(this); + }, + + /** + * This method is an alias for `Matrix4.copy`. + * + * @method Phaser.Math.Matrix4#set + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} src - The Matrix to set the values of this Matrix's from. + * + * @return {this} This Matrix4. + */ + set: function (src) + { + return this.copy(src); + }, + + /** + * Sets all values of this Matrix4. + * + * @method Phaser.Math.Matrix4#setValues + * @since 3.50.0 + * + * @param {number} m00 - The m00 value. + * @param {number} m01 - The m01 value. + * @param {number} m02 - The m02 value. + * @param {number} m03 - The m03 value. + * @param {number} m10 - The m10 value. + * @param {number} m11 - The m11 value. + * @param {number} m12 - The m12 value. + * @param {number} m13 - The m13 value. + * @param {number} m20 - The m20 value. + * @param {number} m21 - The m21 value. + * @param {number} m22 - The m22 value. + * @param {number} m23 - The m23 value. + * @param {number} m30 - The m30 value. + * @param {number} m31 - The m31 value. + * @param {number} m32 - The m32 value. + * @param {number} m33 - The m33 value. + * + * @return {this} This Matrix4 instance. + */ + setValues: function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) + { + var out = this.val; + + out[0] = m00; + out[1] = m01; + out[2] = m02; + out[3] = m03; + out[4] = m10; + out[5] = m11; + out[6] = m12; + out[7] = m13; + out[8] = m20; + out[9] = m21; + out[10] = m22; + out[11] = m23; + out[12] = m30; + out[13] = m31; + out[14] = m32; + out[15] = m33; + + return this; + }, + + /** + * Copy the values of a given Matrix into this Matrix. + * + * @method Phaser.Math.Matrix4#copy + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} src - The Matrix to copy the values from. + * + * @return {this} This Matrix4. + */ + copy: function (src) + { + var a = src.val; + + return this.setValues(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); + }, + + /** + * Set the values of this Matrix from the given array. + * + * @method Phaser.Math.Matrix4#fromArray + * @since 3.0.0 + * + * @param {number[]} a - The array to copy the values from. Must have at least 16 elements. + * + * @return {this} This Matrix4. + */ + fromArray: function (a) + { + return this.setValues(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); + }, + + /** + * Reset this Matrix. + * + * Sets all values to `0`. + * + * @method Phaser.Math.Matrix4#zero + * @since 3.0.0 + * + * @return {Phaser.Math.Matrix4} This Matrix4. + */ + zero: function () + { + return this.setValues(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + }, + + /** + * Generates a transform matrix based on the given position, scale and rotation. + * + * @method Phaser.Math.Matrix4#transform + * @since 3.50.0 + * + * @param {Phaser.Math.Vector3} position - The position vector. + * @param {Phaser.Math.Vector3} scale - The scale vector. + * @param {Phaser.Math.Quaternion} rotation - The rotation quaternion. + * + * @return {this} This Matrix4. + */ + transform: function (position, scale, rotation) + { + var rotMatrix = _tempMat1.fromQuat(rotation); + + var rm = rotMatrix.val; + + var sx = scale.x; + var sy = scale.y; + var sz = scale.z; + + return this.setValues( + rm[0] * sx, + rm[1] * sx, + rm[2] * sx, + 0, + + rm[4] * sy, + rm[5] * sy, + rm[6] * sy, + 0, + + rm[8] * sz, + rm[9] * sz, + rm[10] * sz, + 0, + + position.x, + position.y, + position.z, + 1 + ); + }, + + /** + * Set the `x`, `y` and `z` values of this Matrix. + * + * @method Phaser.Math.Matrix4#xyz + * @since 3.0.0 + * + * @param {number} x - The x value. + * @param {number} y - The y value. + * @param {number} z - The z value. + * + * @return {this} This Matrix4. + */ + xyz: function (x, y, z) + { + this.identity(); + + var out = this.val; + + out[12] = x; + out[13] = y; + out[14] = z; + + return this; + }, + + /** + * Set the scaling values of this Matrix. + * + * @method Phaser.Math.Matrix4#scaling + * @since 3.0.0 + * + * @param {number} x - The x scaling value. + * @param {number} y - The y scaling value. + * @param {number} z - The z scaling value. + * + * @return {this} This Matrix4. + */ + scaling: function (x, y, z) + { + this.zero(); + + var out = this.val; + + out[0] = x; + out[5] = y; + out[10] = z; + out[15] = 1; + + return this; + }, + + /** + * Reset this Matrix to an identity (default) matrix. + * + * @method Phaser.Math.Matrix4#identity + * @since 3.0.0 + * + * @return {this} This Matrix4. + */ + identity: function () + { + return this.setValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + }, + + /** + * Transpose this Matrix. + * + * @method Phaser.Math.Matrix4#transpose + * @since 3.0.0 + * + * @return {this} This Matrix4. + */ + transpose: function () + { + var a = this.val; + + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + var a12 = a[6]; + var a13 = a[7]; + var a23 = a[11]; + + a[1] = a[4]; + a[2] = a[8]; + a[3] = a[12]; + a[4] = a01; + a[6] = a[9]; + a[7] = a[13]; + a[8] = a02; + a[9] = a12; + a[11] = a[14]; + a[12] = a03; + a[13] = a13; + a[14] = a23; + + return this; + }, + + /** + * Copies the given Matrix4 into this Matrix and then inverses it. + * + * @method Phaser.Math.Matrix4#getInverse + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} m - The Matrix4 to invert into this Matrix4. + * + * @return {this} This Matrix4. + */ + getInverse: function (m) + { + this.copy(m); + + return this.invert(); + }, + + /** + * Invert this Matrix. + * + * @method Phaser.Math.Matrix4#invert + * @since 3.0.0 + * + * @return {this} This Matrix4. + */ + invert: function () + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + var b00 = a00 * a11 - a01 * a10; + var b01 = a00 * a12 - a02 * a10; + var b02 = a00 * a13 - a03 * a10; + var b03 = a01 * a12 - a02 * a11; + + var b04 = a01 * a13 - a03 * a11; + var b05 = a02 * a13 - a03 * a12; + var b06 = a20 * a31 - a21 * a30; + var b07 = a20 * a32 - a22 * a30; + + var b08 = a20 * a33 - a23 * a30; + var b09 = a21 * a32 - a22 * a31; + var b10 = a21 * a33 - a23 * a31; + var b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + + if (!det) + { + return this; + } + + det = 1 / det; + + return this.setValues( + (a11 * b11 - a12 * b10 + a13 * b09) * det, + (a02 * b10 - a01 * b11 - a03 * b09) * det, + (a31 * b05 - a32 * b04 + a33 * b03) * det, + (a22 * b04 - a21 * b05 - a23 * b03) * det, + (a12 * b08 - a10 * b11 - a13 * b07) * det, + (a00 * b11 - a02 * b08 + a03 * b07) * det, + (a32 * b02 - a30 * b05 - a33 * b01) * det, + (a20 * b05 - a22 * b02 + a23 * b01) * det, + (a10 * b10 - a11 * b08 + a13 * b06) * det, + (a01 * b08 - a00 * b10 - a03 * b06) * det, + (a30 * b04 - a31 * b02 + a33 * b00) * det, + (a21 * b02 - a20 * b04 - a23 * b00) * det, + (a11 * b07 - a10 * b09 - a12 * b06) * det, + (a00 * b09 - a01 * b07 + a02 * b06) * det, + (a31 * b01 - a30 * b03 - a32 * b00) * det, + (a20 * b03 - a21 * b01 + a22 * b00) * det + ); + }, + + /** + * Calculate the adjoint, or adjugate, of this Matrix. + * + * @method Phaser.Math.Matrix4#adjoint + * @since 3.0.0 + * + * @return {this} This Matrix4. + */ + adjoint: function () + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + return this.setValues( + (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)), + -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)), + (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)), + -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)), + -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)), + (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)), + -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)), + (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)), + (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)), + -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)), + (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)), + -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)), + -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)), + (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)), + -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)), + (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11)) + ); + }, + + /** + * Calculate the determinant of this Matrix. + * + * @method Phaser.Math.Matrix4#determinant + * @since 3.0.0 + * + * @return {number} The determinant of this Matrix. + */ + determinant: function () + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + var b00 = a00 * a11 - a01 * a10; + var b01 = a00 * a12 - a02 * a10; + var b02 = a00 * a13 - a03 * a10; + var b03 = a01 * a12 - a02 * a11; + var b04 = a01 * a13 - a03 * a11; + var b05 = a02 * a13 - a03 * a12; + var b06 = a20 * a31 - a21 * a30; + var b07 = a20 * a32 - a22 * a30; + var b08 = a20 * a33 - a23 * a30; + var b09 = a21 * a32 - a22 * a31; + var b10 = a21 * a33 - a23 * a31; + var b11 = a22 * a33 - a23 * a32; + + // Calculate the determinant + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; + }, + + /** + * Multiply this Matrix by the given Matrix. + * + * @method Phaser.Math.Matrix4#multiply + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} src - The Matrix to multiply this Matrix by. + * + * @return {this} This Matrix4. + */ + multiply: function (src) + { + var a = this.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + var b = src.val; + + // Cache only the current line of the second matrix + var b0 = b[0]; + var b1 = b[1]; + var b2 = b[2]; + var b3 = b[3]; + + a[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + a[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + a[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + a[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + b0 = b[4]; + b1 = b[5]; + b2 = b[6]; + b3 = b[7]; + + a[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + a[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + a[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + a[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + b0 = b[8]; + b1 = b[9]; + b2 = b[10]; + b3 = b[11]; + + a[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + a[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + a[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + a[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + b0 = b[12]; + b1 = b[13]; + b2 = b[14]; + b3 = b[15]; + + a[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; + a[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; + a[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; + a[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; + + return this; + }, + + /** + * Multiply the values of this Matrix4 by those given in the `src` argument. + * + * @method Phaser.Math.Matrix4#multiplyLocal + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} src - The source Matrix4 that this Matrix4 is multiplied by. + * + * @return {this} This Matrix4. + */ + multiplyLocal: function (src) + { + var a = this.val; + var b = src.val; + + return this.setValues( + a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12], + a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13], + a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14], + a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15], + + a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12], + a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13], + a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14], + a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15], + + a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12], + a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13], + a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14], + a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15], + + a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12], + a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13], + a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14], + a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15] + ); + }, + + /** + * Multiplies the given Matrix4 object with this Matrix. + * + * This is the same as calling `multiplyMatrices(m, this)`. + * + * @method Phaser.Math.Matrix4#premultiply + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} m - The Matrix4 to multiply with this one. + * + * @return {this} This Matrix4. + */ + premultiply: function (m) + { + return this.multiplyMatrices(m, this); + }, + + /** + * Multiplies the two given Matrix4 objects and stores the results in this Matrix. + * + * @method Phaser.Math.Matrix4#multiplyMatrices + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} a - The first Matrix4 to multiply. + * @param {Phaser.Math.Matrix4} b - The second Matrix4 to multiply. + * + * @return {this} This Matrix4. + */ + multiplyMatrices: function (a, b) + { + var am = a.val; + var bm = b.val; + + var a11 = am[0]; + var a12 = am[4]; + var a13 = am[8]; + var a14 = am[12]; + var a21 = am[1]; + var a22 = am[5]; + var a23 = am[9]; + var a24 = am[13]; + var a31 = am[2]; + var a32 = am[6]; + var a33 = am[10]; + var a34 = am[14]; + var a41 = am[3]; + var a42 = am[7]; + var a43 = am[11]; + var a44 = am[15]; + + var b11 = bm[0]; + var b12 = bm[4]; + var b13 = bm[8]; + var b14 = bm[12]; + var b21 = bm[1]; + var b22 = bm[5]; + var b23 = bm[9]; + var b24 = bm[13]; + var b31 = bm[2]; + var b32 = bm[6]; + var b33 = bm[10]; + var b34 = bm[14]; + var b41 = bm[3]; + var b42 = bm[7]; + var b43 = bm[11]; + var b44 = bm[15]; + + return this.setValues( + a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41, + a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41, + a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41, + a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41, + a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42, + a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42, + a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42, + a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42, + a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43, + a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43, + a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43, + a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43, + a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44, + a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44, + a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44, + a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44 + ); + }, + + /** + * Translate this Matrix using the given Vector. + * + * @method Phaser.Math.Matrix4#translate + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to translate this Matrix with. + * + * @return {this} This Matrix4. + */ + translate: function (v) + { + return this.translateXYZ(v.x, v.y, v.z); + }, + + /** + * Translate this Matrix using the given values. + * + * @method Phaser.Math.Matrix4#translateXYZ + * @since 3.16.0 + * + * @param {number} x - The x component. + * @param {number} y - The y component. + * @param {number} z - The z component. + * + * @return {this} This Matrix4. + */ + translateXYZ: function (x, y, z) + { + var a = this.val; + + a[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; + a[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; + a[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; + a[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; + + return this; + }, + + /** + * Apply a scale transformation to this Matrix. + * + * Uses the `x`, `y` and `z` components of the given Vector to scale the Matrix. + * + * @method Phaser.Math.Matrix4#scale + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to scale this Matrix with. + * + * @return {this} This Matrix4. + */ + scale: function (v) + { + return this.scaleXYZ(v.x, v.y, v.z); + }, + + /** + * Apply a scale transformation to this Matrix. + * + * @method Phaser.Math.Matrix4#scaleXYZ + * @since 3.16.0 + * + * @param {number} x - The x component. + * @param {number} y - The y component. + * @param {number} z - The z component. + * + * @return {this} This Matrix4. + */ + scaleXYZ: function (x, y, z) + { + var a = this.val; + + a[0] = a[0] * x; + a[1] = a[1] * x; + a[2] = a[2] * x; + a[3] = a[3] * x; + + a[4] = a[4] * y; + a[5] = a[5] * y; + a[6] = a[6] * y; + a[7] = a[7] * y; + + a[8] = a[8] * z; + a[9] = a[9] * z; + a[10] = a[10] * z; + a[11] = a[11] * z; + + return this; + }, + + /** + * Derive a rotation matrix around the given axis. + * + * @method Phaser.Math.Matrix4#makeRotationAxis + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector3|Phaser.Math.Vector4)} axis - The rotation axis. + * @param {number} angle - The rotation angle in radians. + * + * @return {this} This Matrix4. + */ + makeRotationAxis: function (axis, angle) + { + // Based on http://www.gamedev.net/reference/articles/article1199.asp + + var c = Math.cos(angle); + var s = Math.sin(angle); + var t = 1 - c; + var x = axis.x; + var y = axis.y; + var z = axis.z; + var tx = t * x; + var ty = t * y; + + return this.setValues( + tx * x + c, tx * y - s * z, tx * z + s * y, 0, + tx * y + s * z, ty * y + c, ty * z - s * x, 0, + tx * z - s * y, ty * z + s * x, t * z * z + c, 0, + 0, 0, 0, 1 + ); + }, + + /** + * Apply a rotation transformation to this Matrix. + * + * @method Phaser.Math.Matrix4#rotate + * @since 3.0.0 + * + * @param {number} rad - The angle in radians to rotate by. + * @param {Phaser.Math.Vector3} axis - The axis to rotate upon. + * + * @return {this} This Matrix4. + */ + rotate: function (rad, axis) + { + var a = this.val; + var x = axis.x; + var y = axis.y; + var z = axis.z; + var len = Math.sqrt(x * x + y * y + z * z); + + if (Math.abs(len) < EPSILON) + { + return this; + } + + len = 1 / len; + x *= len; + y *= len; + z *= len; + + var s = Math.sin(rad); + var c = Math.cos(rad); + var t = 1 - c; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + // Construct the elements of the rotation matrix + var b00 = x * x * t + c; + var b01 = y * x * t + z * s; + var b02 = z * x * t - y * s; + + var b10 = x * y * t - z * s; + var b11 = y * y * t + c; + var b12 = z * y * t + x * s; + + var b20 = x * z * t + y * s; + var b21 = y * z * t - x * s; + var b22 = z * z * t + c; + + // Perform rotation-specific matrix multiplication + return this.setValues( + a00 * b00 + a10 * b01 + a20 * b02, + a01 * b00 + a11 * b01 + a21 * b02, + a02 * b00 + a12 * b01 + a22 * b02, + a03 * b00 + a13 * b01 + a23 * b02, + a00 * b10 + a10 * b11 + a20 * b12, + a01 * b10 + a11 * b11 + a21 * b12, + a02 * b10 + a12 * b11 + a22 * b12, + a03 * b10 + a13 * b11 + a23 * b12, + a00 * b20 + a10 * b21 + a20 * b22, + a01 * b20 + a11 * b21 + a21 * b22, + a02 * b20 + a12 * b21 + a22 * b22, + a03 * b20 + a13 * b21 + a23 * b22, + a30, a31, a32, a33 + ); + }, + + /** + * Rotate this matrix on its X axis. + * + * @method Phaser.Math.Matrix4#rotateX + * @since 3.0.0 + * + * @param {number} rad - The angle in radians to rotate by. + * + * @return {this} This Matrix4. + */ + rotateX: function (rad) + { + var a = this.val; + var s = Math.sin(rad); + var c = Math.cos(rad); + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + // Perform axis-specific matrix multiplication + a[4] = a10 * c + a20 * s; + a[5] = a11 * c + a21 * s; + a[6] = a12 * c + a22 * s; + a[7] = a13 * c + a23 * s; + a[8] = a20 * c - a10 * s; + a[9] = a21 * c - a11 * s; + a[10] = a22 * c - a12 * s; + a[11] = a23 * c - a13 * s; + + return this; + }, + + /** + * Rotate this matrix on its Y axis. + * + * @method Phaser.Math.Matrix4#rotateY + * @since 3.0.0 + * + * @param {number} rad - The angle to rotate by, in radians. + * + * @return {this} This Matrix4. + */ + rotateY: function (rad) + { + var a = this.val; + var s = Math.sin(rad); + var c = Math.cos(rad); + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + + // Perform axis-specific matrix multiplication + a[0] = a00 * c - a20 * s; + a[1] = a01 * c - a21 * s; + a[2] = a02 * c - a22 * s; + a[3] = a03 * c - a23 * s; + a[8] = a00 * s + a20 * c; + a[9] = a01 * s + a21 * c; + a[10] = a02 * s + a22 * c; + a[11] = a03 * s + a23 * c; + + return this; + }, + + /** + * Rotate this matrix on its Z axis. + * + * @method Phaser.Math.Matrix4#rotateZ + * @since 3.0.0 + * + * @param {number} rad - The angle to rotate by, in radians. + * + * @return {this} This Matrix4. + */ + rotateZ: function (rad) + { + var a = this.val; + var s = Math.sin(rad); + var c = Math.cos(rad); + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + + // Perform axis-specific matrix multiplication + a[0] = a00 * c + a10 * s; + a[1] = a01 * c + a11 * s; + a[2] = a02 * c + a12 * s; + a[3] = a03 * c + a13 * s; + a[4] = a10 * c - a00 * s; + a[5] = a11 * c - a01 * s; + a[6] = a12 * c - a02 * s; + a[7] = a13 * c - a03 * s; + + return this; + }, + + /** + * Set the values of this Matrix from the given rotation Quaternion and translation Vector. + * + * @method Phaser.Math.Matrix4#fromRotationTranslation + * @since 3.0.0 + * + * @param {Phaser.Math.Quaternion} q - The Quaternion to set rotation from. + * @param {Phaser.Math.Vector3} v - The Vector to set translation from. + * + * @return {this} This Matrix4. + */ + fromRotationTranslation: function (q, v) + { + // Quaternion math + var x = q.x; + var y = q.y; + var z = q.z; + var w = q.w; + + var x2 = x + x; + var y2 = y + y; + var z2 = z + z; + + var xx = x * x2; + var xy = x * y2; + var xz = x * z2; + + var yy = y * y2; + var yz = y * z2; + var zz = z * z2; + + var wx = w * x2; + var wy = w * y2; + var wz = w * z2; + + return this.setValues( + 1 - (yy + zz), + xy + wz, + xz - wy, + 0, + + xy - wz, + 1 - (xx + zz), + yz + wx, + 0, + + xz + wy, + yz - wx, + 1 - (xx + yy), + 0, + + v.x, + v.y, + v.z, + 1 + ); + }, + + /** + * Set the values of this Matrix from the given Quaternion. + * + * @method Phaser.Math.Matrix4#fromQuat + * @since 3.0.0 + * + * @param {Phaser.Math.Quaternion} q - The Quaternion to set the values of this Matrix from. + * + * @return {this} This Matrix4. + */ + fromQuat: function (q) + { + var x = q.x; + var y = q.y; + var z = q.z; + var w = q.w; + + var x2 = x + x; + var y2 = y + y; + var z2 = z + z; + + var xx = x * x2; + var xy = x * y2; + var xz = x * z2; + + var yy = y * y2; + var yz = y * z2; + var zz = z * z2; + + var wx = w * x2; + var wy = w * y2; + var wz = w * z2; + + return this.setValues( + 1 - (yy + zz), + xy + wz, + xz - wy, + 0, + + xy - wz, + 1 - (xx + zz), + yz + wx, + 0, + + xz + wy, + yz - wx, + 1 - (xx + yy), + 0, + + 0, + 0, + 0, + 1 + ); + }, + + /** + * Generate a frustum matrix with the given bounds. + * + * @method Phaser.Math.Matrix4#frustum + * @since 3.0.0 + * + * @param {number} left - The left bound of the frustum. + * @param {number} right - The right bound of the frustum. + * @param {number} bottom - The bottom bound of the frustum. + * @param {number} top - The top bound of the frustum. + * @param {number} near - The near bound of the frustum. + * @param {number} far - The far bound of the frustum. + * + * @return {this} This Matrix4. + */ + frustum: function (left, right, bottom, top, near, far) + { + var rl = 1 / (right - left); + var tb = 1 / (top - bottom); + var nf = 1 / (near - far); + + return this.setValues( + (near * 2) * rl, + 0, + 0, + 0, + + 0, + (near * 2) * tb, + 0, + 0, + + (right + left) * rl, + (top + bottom) * tb, + (far + near) * nf, + -1, + + 0, + 0, + (far * near * 2) * nf, + 0 + ); + }, + + /** + * Generate a perspective projection matrix with the given bounds. + * + * @method Phaser.Math.Matrix4#perspective + * @since 3.0.0 + * + * @param {number} fovy - Vertical field of view in radians + * @param {number} aspect - Aspect ratio. Typically viewport width /height. + * @param {number} near - Near bound of the frustum. + * @param {number} far - Far bound of the frustum. + * + * @return {this} This Matrix4. + */ + perspective: function (fovy, aspect, near, far) + { + var f = 1.0 / Math.tan(fovy / 2); + var nf = 1 / (near - far); + + return this.setValues( + f / aspect, + 0, + 0, + 0, + + 0, + f, + 0, + 0, + + 0, + 0, + (far + near) * nf, + -1, + + 0, + 0, + (2 * far * near) * nf, + 0 + ); + }, + + /** + * Generate a perspective projection matrix with the given bounds. + * + * @method Phaser.Math.Matrix4#perspectiveLH + * @since 3.0.0 + * + * @param {number} width - The width of the frustum. + * @param {number} height - The height of the frustum. + * @param {number} near - Near bound of the frustum. + * @param {number} far - Far bound of the frustum. + * + * @return {this} This Matrix4. + */ + perspectiveLH: function (width, height, near, far) + { + return this.setValues( + (2 * near) / width, + 0, + 0, + 0, + + 0, + (2 * near) / height, + 0, + 0, + + 0, + 0, + -far / (near - far), + 1, + + 0, + 0, + (near * far) / (near - far), + 0 + ); + }, + + /** + * Generate an orthogonal projection matrix with the given bounds. + * + * @method Phaser.Math.Matrix4#ortho + * @since 3.0.0 + * + * @param {number} left - The left bound of the frustum. + * @param {number} right - The right bound of the frustum. + * @param {number} bottom - The bottom bound of the frustum. + * @param {number} top - The top bound of the frustum. + * @param {number} near - The near bound of the frustum. + * @param {number} far - The far bound of the frustum. + * + * @return {this} This Matrix4. + */ + ortho: function (left, right, bottom, top, near, far) + { + var lr = left - right; + var bt = bottom - top; + var nf = near - far; + + // Avoid division by zero + lr = (lr === 0) ? lr : 1 / lr; + bt = (bt === 0) ? bt : 1 / bt; + nf = (nf === 0) ? nf : 1 / nf; + + return this.setValues( + -2 * lr, + 0, + 0, + 0, + + 0, + -2 * bt, + 0, + 0, + + 0, + 0, + 2 * nf, + 0, + + (left + right) * lr, + (top + bottom) * bt, + (far + near) * nf, + 1 + ); + }, + + /** + * Generate a right-handed look-at matrix with the given eye position, target and up axis. + * + * @method Phaser.Math.Matrix4#lookAtRH + * @since 3.50.0 + * + * @param {Phaser.Math.Vector3} eye - Position of the viewer. + * @param {Phaser.Math.Vector3} target - Point the viewer is looking at. + * @param {Phaser.Math.Vector3} up - vec3 pointing up. + * + * @return {this} This Matrix4. + */ + lookAtRH: function (eye, target, up) + { + var m = this.val; + + _z.subVectors(eye, target); + + if (_z.lengthSq() === 0) + { + // eye and target are in the same position + _z.z = 1; + } + + _z.normalize(); + _x.crossVectors(up, _z); + + if (_x.lengthSq() === 0) + { + // up and z are parallel + + if (Math.abs(up.z) === 1) + { + _z.x += 0.0001; + } + else + { + _z.z += 0.0001; + } + + _z.normalize(); + _x.crossVectors(up, _z); + } + + _x.normalize(); + _y.crossVectors(_z, _x); + + m[0] = _x.x; + m[1] = _x.y; + m[2] = _x.z; + m[4] = _y.x; + m[5] = _y.y; + m[6] = _y.z; + m[8] = _z.x; + m[9] = _z.y; + m[10] = _z.z; + + return this; + }, + + /** + * Generate a look-at matrix with the given eye position, focal point, and up axis. + * + * @method Phaser.Math.Matrix4#lookAt + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} eye - Position of the viewer + * @param {Phaser.Math.Vector3} center - Point the viewer is looking at + * @param {Phaser.Math.Vector3} up - vec3 pointing up. + * + * @return {this} This Matrix4. + */ + lookAt: function (eye, center, up) + { + var eyex = eye.x; + var eyey = eye.y; + var eyez = eye.z; + + var upx = up.x; + var upy = up.y; + var upz = up.z; + + var centerx = center.x; + var centery = center.y; + var centerz = center.z; + + if (Math.abs(eyex - centerx) < EPSILON && + Math.abs(eyey - centery) < EPSILON && + Math.abs(eyez - centerz) < EPSILON) + { + return this.identity(); + } + + var z0 = eyex - centerx; + var z1 = eyey - centery; + var z2 = eyez - centerz; + + var len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); + + z0 *= len; + z1 *= len; + z2 *= len; + + var x0 = upy * z2 - upz * z1; + var x1 = upz * z0 - upx * z2; + var x2 = upx * z1 - upy * z0; + + len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); + + if (!len) + { + x0 = 0; + x1 = 0; + x2 = 0; + } + else + { + len = 1 / len; + x0 *= len; + x1 *= len; + x2 *= len; + } + + var y0 = z1 * x2 - z2 * x1; + var y1 = z2 * x0 - z0 * x2; + var y2 = z0 * x1 - z1 * x0; + + len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); + + if (!len) + { + y0 = 0; + y1 = 0; + y2 = 0; + } + else + { + len = 1 / len; + y0 *= len; + y1 *= len; + y2 *= len; + } + + return this.setValues( + x0, + y0, + z0, + 0, + + x1, + y1, + z1, + 0, + + x2, + y2, + z2, + 0, + + -(x0 * eyex + x1 * eyey + x2 * eyez), + -(y0 * eyex + y1 * eyey + y2 * eyez), + -(z0 * eyex + z1 * eyey + z2 * eyez), + 1 + ); + }, + + /** + * Set the values of this matrix from the given `yaw`, `pitch` and `roll` values. + * + * @method Phaser.Math.Matrix4#yawPitchRoll + * @since 3.0.0 + * + * @param {number} yaw - The yaw value. + * @param {number} pitch - The pitch value. + * @param {number} roll - The roll value. + * + * @return {this} This Matrix4. + */ + yawPitchRoll: function (yaw, pitch, roll) + { + this.zero(); + _tempMat1.zero(); + _tempMat2.zero(); + + var m0 = this.val; + var m1 = _tempMat1.val; + var m2 = _tempMat2.val; + + // Rotate Z + var s = Math.sin(roll); + var c = Math.cos(roll); + + m0[10] = 1; + m0[15] = 1; + m0[0] = c; + m0[1] = s; + m0[4] = -s; + m0[5] = c; + + // Rotate X + s = Math.sin(pitch); + c = Math.cos(pitch); + + m1[0] = 1; + m1[15] = 1; + m1[5] = c; + m1[10] = c; + m1[9] = -s; + m1[6] = s; + + // Rotate Y + s = Math.sin(yaw); + c = Math.cos(yaw); + + m2[5] = 1; + m2[15] = 1; + m2[0] = c; + m2[2] = -s; + m2[8] = s; + m2[10] = c; + + this.multiplyLocal(_tempMat1); + this.multiplyLocal(_tempMat2); + + return this; + }, + + /** + * Generate a world matrix from the given rotation, position, scale, view matrix and projection matrix. + * + * @method Phaser.Math.Matrix4#setWorldMatrix + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} rotation - The rotation of the world matrix. + * @param {Phaser.Math.Vector3} position - The position of the world matrix. + * @param {Phaser.Math.Vector3} scale - The scale of the world matrix. + * @param {Phaser.Math.Matrix4} [viewMatrix] - The view matrix. + * @param {Phaser.Math.Matrix4} [projectionMatrix] - The projection matrix. + * + * @return {this} This Matrix4. + */ + setWorldMatrix: function (rotation, position, scale, viewMatrix, projectionMatrix) + { + this.yawPitchRoll(rotation.y, rotation.x, rotation.z); + + _tempMat1.scaling(scale.x, scale.y, scale.z); + _tempMat2.xyz(position.x, position.y, position.z); + + this.multiplyLocal(_tempMat1); + this.multiplyLocal(_tempMat2); + + if (viewMatrix) + { + this.multiplyLocal(viewMatrix); + } + + if (projectionMatrix) + { + this.multiplyLocal(projectionMatrix); + } + + return this; + }, + + /** + * Multiplies this Matrix4 by the given `src` Matrix4 and stores the results in the `out` Matrix4. + * + * @method Phaser.Math.Matrix4#multiplyToMat4 + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} src - The Matrix4 to multiply with this one. + * @param {Phaser.Math.Matrix4} out - The receiving Matrix. + * + * @return {Phaser.Math.Matrix4} This `out` Matrix4. + */ + multiplyToMat4: function (src, out) + { + var a = this.val; + var b = src.val; + + var a00 = a[0]; + var a01 = a[1]; + var a02 = a[2]; + var a03 = a[3]; + var a10 = a[4]; + var a11 = a[5]; + var a12 = a[6]; + var a13 = a[7]; + var a20 = a[8]; + var a21 = a[9]; + var a22 = a[10]; + var a23 = a[11]; + var a30 = a[12]; + var a31 = a[13]; + var a32 = a[14]; + var a33 = a[15]; + + var b00 = b[0]; + var b01 = b[1]; + var b02 = b[2]; + var b03 = b[3]; + var b10 = b[4]; + var b11 = b[5]; + var b12 = b[6]; + var b13 = b[7]; + var b20 = b[8]; + var b21 = b[9]; + var b22 = b[10]; + var b23 = b[11]; + var b30 = b[12]; + var b31 = b[13]; + var b32 = b[14]; + var b33 = b[15]; + + return out.setValues( + b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30, + b01 * a01 + b01 * a11 + b02 * a21 + b03 * a31, + b02 * a02 + b01 * a12 + b02 * a22 + b03 * a32, + b03 * a03 + b01 * a13 + b02 * a23 + b03 * a33, + + b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30, + b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31, + b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32, + b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33, + + b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30, + b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31, + b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32, + b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33, + + b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30, + b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31, + b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32, + b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33 + ); + }, + + /** + * Takes the rotation and position vectors and builds this Matrix4 from them. + * + * @method Phaser.Math.Matrix4#fromRotationXYTranslation + * @since 3.50.0 + * + * @param {Phaser.Math.Vector3} rotation - The rotation vector. + * @param {Phaser.Math.Vector3} position - The position vector. + * @param {boolean} translateFirst - Should the operation translate then rotate (`true`), or rotate then translate? (`false`) + * + * @return {this} This Matrix4. + */ + fromRotationXYTranslation: function (rotation, position, translateFirst) + { + var x = position.x; + var y = position.y; + var z = position.z; + + var sx = Math.sin(rotation.x); + var cx = Math.cos(rotation.x); + + var sy = Math.sin(rotation.y); + var cy = Math.cos(rotation.y); + + var a30 = x; + var a31 = y; + var a32 = z; + + // Rotate X + + var b21 = -sx; + + // Rotate Y + + var c01 = 0 - b21 * sy; + + var c02 = 0 - cx * sy; + + var c21 = b21 * cy; + + var c22 = cx * cy; + + // Translate + if (!translateFirst) + { + // a30 = cy * x + 0 * y + sy * z; + a30 = cy * x + sy * z; + a31 = c01 * x + cx * y + c21 * z; + a32 = c02 * x + sx * y + c22 * z; + } + + return this.setValues( + cy, + c01, + c02, + 0, + 0, + cx, + sx, + 0, + sy, + c21, + c22, + 0, + a30, + a31, + a32, + 1 + ); + }, + + /** + * Returns the maximum axis scale from this Matrix4. + * + * @method Phaser.Math.Matrix4#getMaxScaleOnAxis + * @since 3.50.0 + * + * @return {number} The maximum axis scale. + */ + getMaxScaleOnAxis: function () + { + var m = this.val; + + var scaleXSq = m[0] * m[0] + m[1] * m[1] + m[2] * m[2]; + var scaleYSq = m[4] * m[4] + m[5] * m[5] + m[6] * m[6]; + var scaleZSq = m[8] * m[8] + m[9] * m[9] + m[10] * m[10]; + + return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq)); + } + +}); + +/** + * @ignore + */ +var _tempMat1 = new Matrix4(); + +/** + * @ignore + */ +var _tempMat2 = new Matrix4(); + +/** + * @ignore + */ +var _x = new Vector3(); + +/** + * @ignore + */ +var _y = new Vector3(); + +/** + * @ignore + */ +var _z = new Vector3(); + +module.exports = Matrix4; + + +/***/ }), + +/***/ 86883: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Add an `amount` to a `value`, limiting the maximum result to `max`. + * + * @function Phaser.Math.MaxAdd + * @since 3.0.0 + * + * @param {number} value - The value to add to. + * @param {number} amount - The amount to add. + * @param {number} max - The maximum value to return. + * + * @return {number} The resulting value. + */ +var MaxAdd = function (value, amount, max) +{ + return Math.min(value + amount, max); +}; + +module.exports = MaxAdd; + + +/***/ }), + +/***/ 50040: +/***/ ((module) => { + +/** + * @author Vladislav Forsh + * @copyright 2021 RoboWhale + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the median of the given values. The values are sorted and the middle value is returned. + * In case of an even number of values, the average of the two middle values is returned. + * + * @function Phaser.Math.Median + * @since 3.54.0 + * + * @param {number[]} values - The values to average. + * + * @return {number} The median value. + */ +var Median = function (values) +{ + var valuesNum = values.length; + if (valuesNum === 0) + { + return 0; + } + + values.sort(function (a, b) { return a - b; }); + + var halfIndex = Math.floor(valuesNum / 2); + + return valuesNum % 2 === 0 + ? (values[halfIndex] + values[halfIndex - 1]) / 2 + : values[halfIndex]; +}; + +module.exports = Median; + + +/***/ }), + +/***/ 37204: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Subtract an `amount` from `value`, limiting the minimum result to `min`. + * + * @function Phaser.Math.MinSub + * @since 3.0.0 + * + * @param {number} value - The value to subtract from. + * @param {number} amount - The amount to subtract. + * @param {number} min - The minimum value to return. + * + * @return {number} The resulting value. + */ +var MinSub = function (value, amount, min) +{ + return Math.max(value - amount, min); +}; + +module.exports = MinSub; + + +/***/ }), + +/***/ 65201: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Work out what percentage `value` is of the range between `min` and `max`. + * If `max` isn't given then it will return the percentage of `value` to `min`. + * + * You can optionally specify an `upperMax` value, which is a mid-way point in the range that represents 100%, after which the % starts to go down to zero again. + * + * @function Phaser.Math.Percent + * @since 3.0.0 + * + * @param {number} value - The value to determine the percentage of. + * @param {number} min - The minimum value. + * @param {number} [max] - The maximum value. + * @param {number} [upperMax] - The mid-way point in the range that represents 100%. + * + * @return {number} A value between 0 and 1 representing the percentage. + */ +var Percent = function (value, min, max, upperMax) +{ + if (max === undefined) { max = min + 1; } + + var percentage = (value - min) / (max - min); + + if (percentage > 1) + { + if (upperMax !== undefined) + { + percentage = ((upperMax - value)) / (upperMax - max); + + if (percentage < 0) + { + percentage = 0; + } + } + else + { + percentage = 1; + } + } + else if (percentage < 0) + { + percentage = 0; + } + + return percentage; +}; + +module.exports = Percent; + + +/***/ }), + +/***/ 15746: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji +// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl + +var Class = __webpack_require__(83419); +var Matrix3 = __webpack_require__(94434); +var NOOP = __webpack_require__(29747); +var Vector3 = __webpack_require__(25836); + +var EPSILON = 0.000001; + +// Some shared 'private' arrays +var siNext = new Int8Array([ 1, 2, 0 ]); +var tmp = new Float32Array([ 0, 0, 0 ]); + +var xUnitVec3 = new Vector3(1, 0, 0); +var yUnitVec3 = new Vector3(0, 1, 0); + +var tmpvec = new Vector3(); +var tmpMat3 = new Matrix3(); + +/** + * @classdesc + * A quaternion. + * + * @class Quaternion + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {number} [x=0] - The x component. + * @param {number} [y=0] - The y component. + * @param {number} [z=0] - The z component. + * @param {number} [w=1] - The w component. + */ +var Quaternion = new Class({ + + initialize: + + function Quaternion (x, y, z, w) + { + /** + * The x component of this Quaternion. + * + * @name Phaser.Math.Quaternion#_x + * @type {number} + * @default 0 + * @private + * @since 3.50.0 + */ + + /** + * The y component of this Quaternion. + * + * @name Phaser.Math.Quaternion#_y + * @type {number} + * @default 0 + * @private + * @since 3.50.0 + */ + + /** + * The z component of this Quaternion. + * + * @name Phaser.Math.Quaternion#_z + * @type {number} + * @default 0 + * @private + * @since 3.50.0 + */ + + /** + * The w component of this Quaternion. + * + * @name Phaser.Math.Quaternion#_w + * @type {number} + * @default 0 + * @private + * @since 3.50.0 + */ + + /** + * This callback is invoked, if set, each time a value in this quaternion is changed. + * The callback is passed one argument, a reference to this quaternion. + * + * @name Phaser.Math.Quaternion#onChangeCallback + * @type {function} + * @since 3.50.0 + */ + this.onChangeCallback = NOOP; + + this.set(x, y, z, w); + }, + + /** + * The x component of this Quaternion. + * + * @name Phaser.Math.Quaternion#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + x: { + get: function () + { + return this._x; + }, + + set: function (value) + { + this._x = value; + + this.onChangeCallback(this); + } + }, + + /** + * The y component of this Quaternion. + * + * @name Phaser.Math.Quaternion#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + y: { + get: function () + { + return this._y; + }, + + set: function (value) + { + this._y = value; + + this.onChangeCallback(this); + } + }, + + /** + * The z component of this Quaternion. + * + * @name Phaser.Math.Quaternion#z + * @type {number} + * @default 0 + * @since 3.0.0 + */ + z: { + get: function () + { + return this._z; + }, + + set: function (value) + { + this._z = value; + + this.onChangeCallback(this); + } + }, + + /** + * The w component of this Quaternion. + * + * @name Phaser.Math.Quaternion#w + * @type {number} + * @default 0 + * @since 3.0.0 + */ + w: { + get: function () + { + return this._w; + }, + + set: function (value) + { + this._w = value; + + this.onChangeCallback(this); + } + }, + + /** + * Copy the components of a given Quaternion or Vector into this Quaternion. + * + * @method Phaser.Math.Quaternion#copy + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} src - The Quaternion or Vector to copy the components from. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + copy: function (src) + { + return this.set(src); + }, + + /** + * Set the components of this Quaternion and optionally call the `onChangeCallback`. + * + * @method Phaser.Math.Quaternion#set + * @since 3.0.0 + * + * @param {(number|object)} [x=0] - The x component, or an object containing x, y, z, and w components. + * @param {number} [y=0] - The y component. + * @param {number} [z=0] - The z component. + * @param {number} [w=0] - The w component. + * @param {boolean} [update=true] - Call the `onChangeCallback`? + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + set: function (x, y, z, w, update) + { + if (update === undefined) { update = true; } + + if (typeof x === 'object') + { + this._x = x.x || 0; + this._y = x.y || 0; + this._z = x.z || 0; + this._w = x.w || 0; + } + else + { + this._x = x || 0; + this._y = y || 0; + this._z = z || 0; + this._w = w || 0; + } + + if (update) + { + this.onChangeCallback(this); + } + + return this; + }, + + /** + * Add a given Quaternion or Vector to this Quaternion. Addition is component-wise. + * + * @method Phaser.Math.Quaternion#add + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to add to this Quaternion. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + add: function (v) + { + this._x += v.x; + this._y += v.y; + this._z += v.z; + this._w += v.w; + + this.onChangeCallback(this); + + return this; + }, + + /** + * Subtract a given Quaternion or Vector from this Quaternion. Subtraction is component-wise. + * + * @method Phaser.Math.Quaternion#subtract + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to subtract from this Quaternion. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + subtract: function (v) + { + this._x -= v.x; + this._y -= v.y; + this._z -= v.z; + this._w -= v.w; + + this.onChangeCallback(this); + + return this; + }, + + /** + * Scale this Quaternion by the given value. + * + * @method Phaser.Math.Quaternion#scale + * @since 3.0.0 + * + * @param {number} scale - The value to scale this Quaternion by. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + scale: function (scale) + { + this._x *= scale; + this._y *= scale; + this._z *= scale; + this._w *= scale; + + this.onChangeCallback(this); + + return this; + }, + + /** + * Calculate the length of this Quaternion. + * + * @method Phaser.Math.Quaternion#length + * @since 3.0.0 + * + * @return {number} The length of this Quaternion. + */ + length: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + + return Math.sqrt(x * x + y * y + z * z + w * w); + }, + + /** + * Calculate the length of this Quaternion squared. + * + * @method Phaser.Math.Quaternion#lengthSq + * @since 3.0.0 + * + * @return {number} The length of this Quaternion, squared. + */ + lengthSq: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + + return x * x + y * y + z * z + w * w; + }, + + /** + * Normalize this Quaternion. + * + * @method Phaser.Math.Quaternion#normalize + * @since 3.0.0 + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + normalize: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + var len = x * x + y * y + z * z + w * w; + + if (len > 0) + { + len = 1 / Math.sqrt(len); + + this._x = x * len; + this._y = y * len; + this._z = z * len; + this._w = w * len; + } + + this.onChangeCallback(this); + + return this; + }, + + /** + * Calculate the dot product of this Quaternion and the given Quaternion or Vector. + * + * @method Phaser.Math.Quaternion#dot + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to dot product with this Quaternion. + * + * @return {number} The dot product of this Quaternion and the given Quaternion or Vector. + */ + dot: function (v) + { + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + }, + + /** + * Linearly interpolate this Quaternion towards the given Quaternion or Vector. + * + * @method Phaser.Math.Quaternion#lerp + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to interpolate towards. + * @param {number} [t=0] - The percentage of interpolation. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + lerp: function (v, t) + { + if (t === undefined) { t = 0; } + + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + return this.set( + ax + t * (v.x - ax), + ay + t * (v.y - ay), + az + t * (v.z - az), + aw + t * (v.w - aw) + ); + }, + + /** + * Rotates this Quaternion based on the two given vectors. + * + * @method Phaser.Math.Quaternion#rotationTo + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} a - The transform rotation vector. + * @param {Phaser.Math.Vector3} b - The target rotation vector. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + rotationTo: function (a, b) + { + var dot = a.x * b.x + a.y * b.y + a.z * b.z; + + if (dot < -0.999999) + { + if (tmpvec.copy(xUnitVec3).cross(a).length() < EPSILON) + { + tmpvec.copy(yUnitVec3).cross(a); + } + + tmpvec.normalize(); + + return this.setAxisAngle(tmpvec, Math.PI); + + } + else if (dot > 0.999999) + { + return this.set(0, 0, 0, 1); + } + else + { + tmpvec.copy(a).cross(b); + + this._x = tmpvec.x; + this._y = tmpvec.y; + this._z = tmpvec.z; + this._w = 1 + dot; + + return this.normalize(); + } + }, + + /** + * Set the axes of this Quaternion. + * + * @method Phaser.Math.Quaternion#setAxes + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} view - The view axis. + * @param {Phaser.Math.Vector3} right - The right axis. + * @param {Phaser.Math.Vector3} up - The upwards axis. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + setAxes: function (view, right, up) + { + var m = tmpMat3.val; + + m[0] = right.x; + m[3] = right.y; + m[6] = right.z; + + m[1] = up.x; + m[4] = up.y; + m[7] = up.z; + + m[2] = -view.x; + m[5] = -view.y; + m[8] = -view.z; + + return this.fromMat3(tmpMat3).normalize(); + }, + + /** + * Reset this Matrix to an identity (default) Quaternion. + * + * @method Phaser.Math.Quaternion#identity + * @since 3.0.0 + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + identity: function () + { + return this.set(0, 0, 0, 1); + }, + + /** + * Set the axis angle of this Quaternion. + * + * @method Phaser.Math.Quaternion#setAxisAngle + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} axis - The axis. + * @param {number} rad - The angle in radians. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + setAxisAngle: function (axis, rad) + { + rad = rad * 0.5; + + var s = Math.sin(rad); + + return this.set( + s * axis.x, + s * axis.y, + s * axis.z, + Math.cos(rad) + ); + }, + + /** + * Multiply this Quaternion by the given Quaternion or Vector. + * + * @method Phaser.Math.Quaternion#multiply + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} b - The Quaternion or Vector to multiply this Quaternion by. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + multiply: function (b) + { + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + var bx = b.x; + var by = b.y; + var bz = b.z; + var bw = b.w; + + return this.set( + ax * bw + aw * bx + ay * bz - az * by, + ay * bw + aw * by + az * bx - ax * bz, + az * bw + aw * bz + ax * by - ay * bx, + aw * bw - ax * bx - ay * by - az * bz + ); + }, + + /** + * Smoothly linearly interpolate this Quaternion towards the given Quaternion or Vector. + * + * @method Phaser.Math.Quaternion#slerp + * @since 3.0.0 + * + * @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} b - The Quaternion or Vector to interpolate towards. + * @param {number} t - The percentage of interpolation. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + slerp: function (b, t) + { + // benchmarks: http://jsperf.com/quaternion-slerp-implementations + + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + var bx = b.x; + var by = b.y; + var bz = b.z; + var bw = b.w; + + // calc cosine + var cosom = ax * bx + ay * by + az * bz + aw * bw; + + // adjust signs (if necessary) + if (cosom < 0) + { + cosom = -cosom; + bx = - bx; + by = - by; + bz = - bz; + bw = - bw; + } + + // "from" and "to" quaternions are very close + // ... so we can do a linear interpolation + var scale0 = 1 - t; + var scale1 = t; + + // calculate coefficients + if ((1 - cosom) > EPSILON) + { + // standard case (slerp) + var omega = Math.acos(cosom); + var sinom = Math.sin(omega); + + scale0 = Math.sin((1.0 - t) * omega) / sinom; + scale1 = Math.sin(t * omega) / sinom; + } + + // calculate final values + return this.set( + scale0 * ax + scale1 * bx, + scale0 * ay + scale1 * by, + scale0 * az + scale1 * bz, + scale0 * aw + scale1 * bw + ); + }, + + /** + * Invert this Quaternion. + * + * @method Phaser.Math.Quaternion#invert + * @since 3.0.0 + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + invert: function () + { + var a0 = this.x; + var a1 = this.y; + var a2 = this.z; + var a3 = this.w; + + var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; + var invDot = (dot) ? 1 / dot : 0; + + return this.set( + -a0 * invDot, + -a1 * invDot, + -a2 * invDot, + a3 * invDot + ); + }, + + /** + * Convert this Quaternion into its conjugate. + * + * Sets the x, y and z components. + * + * @method Phaser.Math.Quaternion#conjugate + * @since 3.0.0 + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + conjugate: function () + { + this._x = -this.x; + this._y = -this.y; + this._z = -this.z; + + this.onChangeCallback(this); + + return this; + }, + + /** + * Rotate this Quaternion on the X axis. + * + * @method Phaser.Math.Quaternion#rotateX + * @since 3.0.0 + * + * @param {number} rad - The rotation angle in radians. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + rotateX: function (rad) + { + rad *= 0.5; + + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + var bx = Math.sin(rad); + var bw = Math.cos(rad); + + return this.set( + ax * bw + aw * bx, + ay * bw + az * bx, + az * bw - ay * bx, + aw * bw - ax * bx + ); + }, + + /** + * Rotate this Quaternion on the Y axis. + * + * @method Phaser.Math.Quaternion#rotateY + * @since 3.0.0 + * + * @param {number} rad - The rotation angle in radians. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + rotateY: function (rad) + { + rad *= 0.5; + + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + var by = Math.sin(rad); + var bw = Math.cos(rad); + + return this.set( + ax * bw - az * by, + ay * bw + aw * by, + az * bw + ax * by, + aw * bw - ay * by + ); + }, + + /** + * Rotate this Quaternion on the Z axis. + * + * @method Phaser.Math.Quaternion#rotateZ + * @since 3.0.0 + * + * @param {number} rad - The rotation angle in radians. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + rotateZ: function (rad) + { + rad *= 0.5; + + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + var bz = Math.sin(rad); + var bw = Math.cos(rad); + + return this.set( + ax * bw + ay * bz, + ay * bw - ax * bz, + az * bw + aw * bz, + aw * bw - az * bz + ); + }, + + /** + * Create a unit (or rotation) Quaternion from its x, y, and z components. + * + * Sets the w component. + * + * @method Phaser.Math.Quaternion#calculateW + * @since 3.0.0 + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + calculateW: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + + this.w = -Math.sqrt(1.0 - x * x - y * y - z * z); + + return this; + }, + + /** + * Set this Quaternion from the given Euler, based on Euler order. + * + * @method Phaser.Math.Quaternion#setFromEuler + * @since 3.50.0 + * + * @param {Phaser.Math.Euler} euler - The Euler to convert from. + * @param {boolean} [update=true] - Run the `onChangeCallback`? + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + setFromEuler: function (euler, update) + { + var x = euler.x / 2; + var y = euler.y / 2; + var z = euler.z / 2; + + var c1 = Math.cos(x); + var c2 = Math.cos(y); + var c3 = Math.cos(z); + + var s1 = Math.sin(x); + var s2 = Math.sin(y); + var s3 = Math.sin(z); + + switch (euler.order) + { + case 'XYZ': + { + this.set( + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3, + c1 * c2 * c3 - s1 * s2 * s3, + update + ); + + break; + } + + case 'YXZ': + { + this.set( + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3, + c1 * c2 * c3 + s1 * s2 * s3, + update + ); + + break; + } + + case 'ZXY': + { + this.set( + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3, + c1 * c2 * c3 - s1 * s2 * s3, + update + ); + + break; + } + + case 'ZYX': + { + this.set( + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3, + c1 * c2 * c3 + s1 * s2 * s3, + update + ); + + break; + } + + case 'YZX': + { + this.set( + s1 * c2 * c3 + c1 * s2 * s3, + c1 * s2 * c3 + s1 * c2 * s3, + c1 * c2 * s3 - s1 * s2 * c3, + c1 * c2 * c3 - s1 * s2 * s3, + update + ); + + break; + } + + case 'XZY': + { + this.set( + s1 * c2 * c3 - c1 * s2 * s3, + c1 * s2 * c3 - s1 * c2 * s3, + c1 * c2 * s3 + s1 * s2 * c3, + c1 * c2 * c3 + s1 * s2 * s3, + update + ); + + break; + } + } + + return this; + }, + + /** + * Sets the rotation of this Quaternion from the given Matrix4. + * + * @method Phaser.Math.Quaternion#setFromRotationMatrix + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to set the rotation from. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + setFromRotationMatrix: function (mat4) + { + var m = mat4.val; + + var m11 = m[0]; + var m12 = m[4]; + var m13 = m[8]; + var m21 = m[1]; + var m22 = m[5]; + var m23 = m[9]; + var m31 = m[2]; + var m32 = m[6]; + var m33 = m[10]; + + var trace = m11 + m22 + m33; + var s; + + if (trace > 0) + { + s = 0.5 / Math.sqrt(trace + 1.0); + + this.set( + (m32 - m23) * s, + (m13 - m31) * s, + (m21 - m12) * s, + 0.25 / s + ); + } + else if (m11 > m22 && m11 > m33) + { + s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33); + + this.set( + 0.25 * s, + (m12 + m21) / s, + (m13 + m31) / s, + (m32 - m23) / s + ); + } + else if (m22 > m33) + { + s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33); + + this.set( + (m12 + m21) / s, + 0.25 * s, + (m23 + m32) / s, + (m13 - m31) / s + ); + } + else + { + s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22); + + this.set( + (m13 + m31) / s, + (m23 + m32) / s, + 0.25 * s, + (m21 - m12) / s + ); + } + + return this; + }, + + /** + * Convert the given Matrix into this Quaternion. + * + * @method Phaser.Math.Quaternion#fromMat3 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} mat - The Matrix to convert from. + * + * @return {Phaser.Math.Quaternion} This Quaternion. + */ + fromMat3: function (mat) + { + // benchmarks: + // http://jsperf.com/typed-array-access-speed + // http://jsperf.com/conversion-of-3x3-matrix-to-quaternion + + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + var m = mat.val; + var fTrace = m[0] + m[4] + m[8]; + var fRoot; + + if (fTrace > 0) + { + // |w| > 1/2, may as well choose w > 1/2 + fRoot = Math.sqrt(fTrace + 1.0); // 2w + + this.w = 0.5 * fRoot; + + fRoot = 0.5 / fRoot; // 1/(4w) + + this._x = (m[7] - m[5]) * fRoot; + this._y = (m[2] - m[6]) * fRoot; + this._z = (m[3] - m[1]) * fRoot; + } + else + { + // |w| <= 1/2 + var i = 0; + + if (m[4] > m[0]) + { + i = 1; + } + + if (m[8] > m[i * 3 + i]) + { + i = 2; + } + + var j = siNext[i]; + var k = siNext[j]; + + // This isn't quite as clean without array access + fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1); + tmp[i] = 0.5 * fRoot; + + fRoot = 0.5 / fRoot; + + tmp[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot; + tmp[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot; + + this._x = tmp[0]; + this._y = tmp[1]; + this._z = tmp[2]; + this._w = (m[k * 3 + j] - m[j * 3 + k]) * fRoot; + } + + this.onChangeCallback(this); + + return this; + } + +}); + +module.exports = Quaternion; + + +/***/ }), + +/***/ 43396: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(36383); + +/** + * Convert the given angle in radians, to the equivalent angle in degrees. + * + * @function Phaser.Math.RadToDeg + * @since 3.0.0 + * + * @param {number} radians - The angle in radians to convert ot degrees. + * + * @return {number} The given angle converted to degrees. + */ +var RadToDeg = function (radians) +{ + return radians * CONST.RAD_TO_DEG; +}; + +module.exports = RadToDeg; + + +/***/ }), + +/***/ 74362: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compute a random unit vector. + * + * Computes random values for the given vector between -1 and 1 that can be used to represent a direction. + * + * Optionally accepts a scale value to scale the resulting vector by. + * + * @function Phaser.Math.RandomXY + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2} vector - The Vector to compute random values for. + * @param {number} [scale=1] - The scale of the random values. + * + * @return {Phaser.Math.Vector2} The given Vector. + */ +var RandomXY = function (vector, scale) +{ + if (scale === undefined) { scale = 1; } + + var r = Math.random() * 2 * Math.PI; + + vector.x = Math.cos(r) * scale; + vector.y = Math.sin(r) * scale; + + return vector; +}; + +module.exports = RandomXY; + + +/***/ }), + +/***/ 60706: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compute a random position vector in a spherical area, optionally defined by the given radius. + * + * @function Phaser.Math.RandomXYZ + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} vec3 - The Vector to compute random values for. + * @param {number} [radius=1] - The radius. + * + * @return {Phaser.Math.Vector3} The given Vector. + */ +var RandomXYZ = function (vec3, radius) +{ + if (radius === undefined) { radius = 1; } + + var r = Math.random() * 2 * Math.PI; + var z = (Math.random() * 2) - 1; + var zScale = Math.sqrt(1 - z * z) * radius; + + vec3.x = Math.cos(r) * zScale; + vec3.y = Math.sin(r) * zScale; + vec3.z = z * radius; + + return vec3; +}; + +module.exports = RandomXYZ; + + +/***/ }), + +/***/ 67421: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Compute a random four-dimensional vector. + * + * @function Phaser.Math.RandomXYZW + * @since 3.0.0 + * + * @param {Phaser.Math.Vector4} vec4 - The Vector to compute random values for. + * @param {number} [scale=1] - The scale of the random values. + * + * @return {Phaser.Math.Vector4} The given Vector. + */ +var RandomXYZW = function (vec4, scale) +{ + if (scale === undefined) { scale = 1; } + + vec4.x = (Math.random() * 2 - 1) * scale; + vec4.y = (Math.random() * 2 - 1) * scale; + vec4.z = (Math.random() * 2 - 1) * scale; + vec4.w = (Math.random() * 2 - 1) * scale; + + return vec4; +}; + +module.exports = RandomXYZW; + + +/***/ }), + +/***/ 36305: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rotate a given point by a given angle around the origin (0, 0), in an anti-clockwise direction. + * + * @function Phaser.Math.Rotate + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} T - [point,$return] + * + * @param {Phaser.Types.Math.Vector2Like} point - The point to be rotated. + * @param {number} angle - The angle to be rotated by in an anticlockwise direction. + * + * @return {Phaser.Types.Math.Vector2Like} The given point, rotated by the given angle in an anticlockwise direction. + */ +var Rotate = function (point, angle) +{ + var x = point.x; + var y = point.y; + + point.x = (x * Math.cos(angle)) - (y * Math.sin(angle)); + point.y = (x * Math.sin(angle)) + (y * Math.cos(angle)); + + return point; +}; + +module.exports = Rotate; + + +/***/ }), + +/***/ 11520: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rotate a `point` around `x` and `y` to the given `angle`, at the same distance. + * + * In polar notation, this maps a point from (r, t) to (r, angle), vs. the origin (x, y). + * + * @function Phaser.Math.RotateAround + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} T - [point,$return] + * + * @param {Phaser.Types.Math.Vector2Like} point - The point to be rotated. + * @param {number} x - The horizontal coordinate to rotate around. + * @param {number} y - The vertical coordinate to rotate around. + * @param {number} angle - The angle of rotation in radians. + * + * @return {Phaser.Types.Math.Vector2Like} The given point. + */ +var RotateAround = function (point, x, y, angle) +{ + var c = Math.cos(angle); + var s = Math.sin(angle); + + var tx = point.x - x; + var ty = point.y - y; + + point.x = tx * c - ty * s + x; + point.y = tx * s + ty * c + y; + + return point; +}; + +module.exports = RotateAround; + + +/***/ }), + +/***/ 1163: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Rotate a `point` around `x` and `y` by the given `angle` and `distance`. + * + * In polar notation, this maps a point from (r, t) to (distance, t + angle), vs. the origin (x, y). + * + * @function Phaser.Math.RotateAroundDistance + * @since 3.0.0 + * + * @generic {Phaser.Types.Math.Vector2Like} T - [point,$return] + * + * @param {Phaser.Types.Math.Vector2Like} point - The point to be rotated. + * @param {number} x - The horizontal coordinate to rotate around. + * @param {number} y - The vertical coordinate to rotate around. + * @param {number} angle - The angle of rotation in radians. + * @param {number} distance - The distance from (x, y) to place the point at. + * + * @return {Phaser.Types.Math.Vector2Like} The given point. + */ +var RotateAroundDistance = function (point, x, y, angle, distance) +{ + var t = angle + Math.atan2(point.y - y, point.x - x); + + point.x = x + (distance * Math.cos(t)); + point.y = y + (distance * Math.sin(t)); + + return point; +}; + +module.exports = RotateAroundDistance; + + +/***/ }), + +/***/ 70336: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Position a `point` at the given `angle` and `distance` to (`x`, `y`). + * + * @function Phaser.Math.RotateTo + * @since 3.24.0 + * + * @generic {Phaser.Types.Math.Vector2Like} T - [point,$return] + * + * @param {Phaser.Types.Math.Vector2Like} point - The point to be positioned. + * @param {number} x - The horizontal coordinate to position from. + * @param {number} y - The vertical coordinate to position from. + * @param {number} angle - The angle of rotation in radians. + * @param {number} distance - The distance from (x, y) to place the point at. + * + * @return {Phaser.Types.Math.Vector2Like} The given point. + */ +var RotateTo = function (point, x, y, angle, distance) +{ + point.x = x + (distance * Math.cos(angle)); + point.y = y + (distance * Math.sin(angle)); + + return point; +}; + +module.exports = RotateTo; + + +/***/ }), + +/***/ 72678: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector3 = __webpack_require__(25836); +var Matrix4 = __webpack_require__(37867); +var Quaternion = __webpack_require__(15746); + +var tmpMat4 = new Matrix4(); +var tmpQuat = new Quaternion(); +var tmpVec3 = new Vector3(); + +/** + * Rotates a vector in place by axis angle. + * + * This is the same as transforming a point by an + * axis-angle quaternion, but it has higher precision. + * + * @function Phaser.Math.RotateVec3 + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} vec - The vector to be rotated. + * @param {Phaser.Math.Vector3} axis - The axis to rotate around. + * @param {number} radians - The angle of rotation in radians. + * + * @return {Phaser.Math.Vector3} The given vector. + */ +var RotateVec3 = function (vec, axis, radians) +{ + // Set the quaternion to our axis angle + tmpQuat.setAxisAngle(axis, radians); + + // Create a rotation matrix from the axis angle + tmpMat4.fromRotationTranslation(tmpQuat, tmpVec3.set(0, 0, 0)); + + // Multiply our vector by the rotation matrix + return vec.transformMat4(tmpMat4); +}; + +module.exports = RotateVec3; + + +/***/ }), + +/***/ 2284: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Round a given number so it is further away from zero. That is, positive numbers are rounded up, and negative numbers are rounded down. + * + * @function Phaser.Math.RoundAwayFromZero + * @since 3.0.0 + * + * @param {number} value - The number to round. + * + * @return {number} The rounded number, rounded away from zero. + */ +var RoundAwayFromZero = function (value) +{ + // "Opposite" of truncate. + return (value > 0) ? Math.ceil(value) : Math.floor(value); +}; + +module.exports = RoundAwayFromZero; + + +/***/ }), + +/***/ 41013: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Round a value to the given precision. + * + * For example: + * + * ```javascript + * RoundTo(123.456, 0) = 123 + * RoundTo(123.456, 1) = 120 + * RoundTo(123.456, 2) = 100 + * ``` + * + * To round the decimal, i.e. to round to precision, pass in a negative `place`: + * + * ```javascript + * RoundTo(123.456789, 0) = 123 + * RoundTo(123.456789, -1) = 123.5 + * RoundTo(123.456789, -2) = 123.46 + * RoundTo(123.456789, -3) = 123.457 + * ``` + * + * @function Phaser.Math.RoundTo + * @since 3.0.0 + * + * @param {number} value - The value to round. + * @param {number} [place=0] - The place to round to. Positive to round the units, negative to round the decimal. + * @param {number} [base=10] - The base to round in. Default is 10 for decimal. + * + * @return {number} The rounded value. + */ +var RoundTo = function (value, place, base) +{ + if (place === undefined) { place = 0; } + if (base === undefined) { base = 10; } + + var p = Math.pow(base, -place); + + return Math.round(value * p) / p; +}; + +module.exports = RoundTo; + + +/***/ }), + +/***/ 7602: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate a smooth interpolation percentage of `x` between `min` and `max`. + * + * The function receives the number `x` as an argument and returns 0 if `x` is less than or equal to the left edge, + * 1 if `x` is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial, + * between 0 and 1 otherwise. + * + * @function Phaser.Math.SmoothStep + * @since 3.0.0 + * @see {@link https://en.wikipedia.org/wiki/Smoothstep} + * + * @param {number} x - The input value. + * @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'. + * @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'. + * + * @return {number} The percentage of interpolation, between 0 and 1. + */ +var SmoothStep = function (x, min, max) +{ + if (x <= min) + { + return 0; + } + + if (x >= max) + { + return 1; + } + + x = (x - min) / (max - min); + + return x * x * (3 - 2 * x); +}; + +module.exports = SmoothStep; + + +/***/ }), + +/***/ 54261: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate a smoother interpolation percentage of `x` between `min` and `max`. + * + * The function receives the number `x` as an argument and returns 0 if `x` is less than or equal to the left edge, + * 1 if `x` is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial, + * between 0 and 1 otherwise. + * + * Produces an even smoother interpolation than {@link Phaser.Math.SmoothStep}. + * + * @function Phaser.Math.SmootherStep + * @since 3.0.0 + * @see {@link https://en.wikipedia.org/wiki/Smoothstep#Variations} + * + * @param {number} x - The input value. + * @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'. + * @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'. + * + * @return {number} The percentage of interpolation, between 0 and 1. + */ +var SmootherStep = function (x, min, max) +{ + x = Math.max(0, Math.min(1, (x - min) / (max - min))); + + return x * x * x * (x * (x * 6 - 15) + 10); +}; + +module.exports = SmootherStep; + + +/***/ }), + +/***/ 44408: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Returns a Vector2 containing the x and y position of the given index in a `width` x `height` sized grid. + * + * For example, in a 6 x 4 grid, index 16 would equal x: 4 y: 2. + * + * If the given index is out of range an empty Vector2 is returned. + * + * @function Phaser.Math.ToXY + * @since 3.19.0 + * + * @param {number} index - The position within the grid to get the x/y value for. + * @param {number} width - The width of the grid. + * @param {number} height - The height of the grid. + * @param {Phaser.Math.Vector2} [out] - An optional Vector2 to store the result in. If not given, a new Vector2 instance will be created. + * + * @return {Phaser.Math.Vector2} A Vector2 where the x and y properties contain the given grid index. + */ +var ToXY = function (index, width, height, out) +{ + if (out === undefined) { out = new Vector2(); } + + var x = 0; + var y = 0; + var total = width * height; + + if (index > 0 && index <= total) + { + if (index > width - 1) + { + y = Math.floor(index / width); + x = index - (y * width); + } + else + { + x = index; + } + } + + return out.set(x, y); +}; + +module.exports = ToXY; + + +/***/ }), + +/***/ 85955: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Takes the `x` and `y` coordinates and transforms them into the same space as + * defined by the position, rotation and scale values. + * + * @function Phaser.Math.TransformXY + * @since 3.0.0 + * + * @param {number} x - The x coordinate to be transformed. + * @param {number} y - The y coordinate to be transformed. + * @param {number} positionX - Horizontal position of the transform point. + * @param {number} positionY - Vertical position of the transform point. + * @param {number} rotation - Rotation of the transform point, in radians. + * @param {number} scaleX - Horizontal scale of the transform point. + * @param {number} scaleY - Vertical scale of the transform point. + * @param {Phaser.Types.Math.Vector2Like} [output] - The output vector, point or object for the translated coordinates. + * + * @return {Phaser.Types.Math.Vector2Like} The translated point. + */ +var TransformXY = function (x, y, positionX, positionY, rotation, scaleX, scaleY, output) +{ + if (output === undefined) { output = new Vector2(); } + + var radianSin = Math.sin(rotation); + var radianCos = Math.cos(rotation); + + // Rotate and Scale + var a = radianCos * scaleX; + var b = radianSin * scaleX; + var c = -radianSin * scaleY; + var d = radianCos * scaleY; + + // Invert + var id = 1 / ((a * d) + (c * -b)); + + output.x = (d * id * x) + (-c * id * y) + (((positionY * c) - (positionX * d)) * id); + output.y = (a * id * y) + (-b * id * x) + (((-positionY * a) + (positionX * b)) * id); + + return output; +}; + +module.exports = TransformXY; + + +/***/ }), + +/***/ 26099: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji +// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl + +var Class = __webpack_require__(83419); +var FuzzyEqual = __webpack_require__(43855); + +/** + * @classdesc + * A representation of a vector in 2D space. + * + * A two-component vector. + * + * @class Vector2 + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {number|Phaser.Types.Math.Vector2Like} [x=0] - The x component, or an object with `x` and `y` properties. + * @param {number} [y=x] - The y component. + */ +var Vector2 = new Class({ + + initialize: + + function Vector2 (x, y) + { + /** + * The x component of this Vector. + * + * @name Phaser.Math.Vector2#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = 0; + + /** + * The y component of this Vector. + * + * @name Phaser.Math.Vector2#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = 0; + + if (typeof x === 'object') + { + this.x = x.x || 0; + this.y = x.y || 0; + } + else + { + if (y === undefined) { y = x; } + + this.x = x || 0; + this.y = y || 0; + } + }, + + /** + * Make a clone of this Vector2. + * + * @method Phaser.Math.Vector2#clone + * @since 3.0.0 + * + * @return {Phaser.Math.Vector2} A clone of this Vector2. + */ + clone: function () + { + return new Vector2(this.x, this.y); + }, + + /** + * Copy the components of a given Vector into this Vector. + * + * @method Phaser.Math.Vector2#copy + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to copy the components from. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + copy: function (src) + { + this.x = src.x || 0; + this.y = src.y || 0; + + return this; + }, + + /** + * Set the component values of this Vector from a given Vector2Like object. + * + * @method Phaser.Math.Vector2#setFromObject + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} obj - The object containing the component values to set for this Vector. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + setFromObject: function (obj) + { + this.x = obj.x || 0; + this.y = obj.y || 0; + + return this; + }, + + /** + * Set the `x` and `y` components of the this Vector to the given `x` and `y` values. + * + * @method Phaser.Math.Vector2#set + * @since 3.0.0 + * + * @param {number} x - The x value to set for this Vector. + * @param {number} [y=x] - The y value to set for this Vector. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + set: function (x, y) + { + if (y === undefined) { y = x; } + + this.x = x; + this.y = y; + + return this; + }, + + /** + * This method is an alias for `Vector2.set`. + * + * @method Phaser.Math.Vector2#setTo + * @since 3.4.0 + * + * @param {number} x - The x value to set for this Vector. + * @param {number} [y=x] - The y value to set for this Vector. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + setTo: function (x, y) + { + return this.set(x, y); + }, + + /** + * Runs the x and y components of this Vector2 through Math.ceil and then sets them. + * + * @method Phaser.Math.Vector2#ceil + * @since 4.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + ceil: function () + { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + + return this; + }, + + /** + * Runs the x and y components of this Vector2 through Math.floor and then sets them. + * + * @method Phaser.Math.Vector2#floor + * @since 4.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + floor: function () + { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + + return this; + }, + + /** + * Swaps the x and y components of this Vector2. + * + * @method Phaser.Math.Vector2#invert + * @since 4.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + invert: function () + { + return this.set(this.y, this.x); + }, + + /** + * Sets the `x` and `y` values of this object from a given polar coordinate. + * + * @method Phaser.Math.Vector2#setToPolar + * @since 3.0.0 + * + * @param {number} azimuth - The angular coordinate, in radians. + * @param {number} [radius=1] - The radial coordinate (length). + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + setToPolar: function (azimuth, radius) + { + if (radius == null) { radius = 1; } + + this.x = Math.cos(azimuth) * radius; + this.y = Math.sin(azimuth) * radius; + + return this; + }, + + /** + * Check whether this Vector is equal to a given Vector. + * + * Performs a strict equality check against each Vector's components. + * + * @method Phaser.Math.Vector2#equals + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} v - The vector to compare with this Vector. + * + * @return {boolean} Whether the given Vector is equal to this Vector. + */ + equals: function (v) + { + return ((this.x === v.x) && (this.y === v.y)); + }, + + /** + * Check whether this Vector is approximately equal to a given Vector. + * + * @method Phaser.Math.Vector2#fuzzyEquals + * @since 3.23.0 + * + * @param {Phaser.Types.Math.Vector2Like} v - The vector to compare with this Vector. + * @param {number} [epsilon=0.0001] - The tolerance value. + * + * @return {boolean} Whether both absolute differences of the x and y components are smaller than `epsilon`. + */ + fuzzyEquals: function (v, epsilon) + { + return (FuzzyEqual(this.x, v.x, epsilon) && FuzzyEqual(this.y, v.y, epsilon)); + }, + + /** + * Calculate the angle between this Vector and the positive x-axis, in radians. + * + * @method Phaser.Math.Vector2#angle + * @since 3.0.0 + * + * @return {number} The angle between this Vector, and the positive x-axis, given in radians. + */ + angle: function () + { + // computes the angle in radians with respect to the positive x-axis + + var angle = Math.atan2(this.y, this.x); + + if (angle < 0) + { + angle += 2 * Math.PI; + } + + return angle; + }, + + /** + * Set the angle of this Vector. + * + * @method Phaser.Math.Vector2#setAngle + * @since 3.23.0 + * + * @param {number} angle - The angle, in radians. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + setAngle: function (angle) + { + return this.setToPolar(angle, this.length()); + }, + + /** + * Add a given Vector to this Vector. Addition is component-wise. + * + * @method Phaser.Math.Vector2#add + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to add to this Vector. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + add: function (src) + { + this.x += src.x; + this.y += src.y; + + return this; + }, + + /** + * Subtract the given Vector from this Vector. Subtraction is component-wise. + * + * @method Phaser.Math.Vector2#subtract + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to subtract from this Vector. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + subtract: function (src) + { + this.x -= src.x; + this.y -= src.y; + + return this; + }, + + /** + * Perform a component-wise multiplication between this Vector and the given Vector. + * + * Multiplies this Vector by the given Vector. + * + * @method Phaser.Math.Vector2#multiply + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to multiply this Vector by. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + multiply: function (src) + { + this.x *= src.x; + this.y *= src.y; + + return this; + }, + + /** + * Scale this Vector by the given value. + * + * @method Phaser.Math.Vector2#scale + * @since 3.0.0 + * + * @param {number} value - The value to scale this Vector by. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + scale: function (value) + { + if (isFinite(value)) + { + this.x *= value; + this.y *= value; + } + else + { + this.x = 0; + this.y = 0; + } + + return this; + }, + + /** + * Perform a component-wise division between this Vector and the given Vector. + * + * Divides this Vector by the given Vector. + * + * @method Phaser.Math.Vector2#divide + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to divide this Vector by. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + divide: function (src) + { + this.x /= src.x; + this.y /= src.y; + + return this; + }, + + /** + * Negate the `x` and `y` components of this Vector. + * + * @method Phaser.Math.Vector2#negate + * @since 3.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + negate: function () + { + this.x = -this.x; + this.y = -this.y; + + return this; + }, + + /** + * Calculate the distance between this Vector and the given Vector. + * + * @method Phaser.Math.Vector2#distance + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to calculate the distance to. + * + * @return {number} The distance from this Vector to the given Vector. + */ + distance: function (src) + { + var dx = src.x - this.x; + var dy = src.y - this.y; + + return Math.sqrt(dx * dx + dy * dy); + }, + + /** + * Calculate the distance between this Vector and the given Vector, squared. + * + * @method Phaser.Math.Vector2#distanceSq + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector to calculate the distance to. + * + * @return {number} The distance from this Vector to the given Vector, squared. + */ + distanceSq: function (src) + { + var dx = src.x - this.x; + var dy = src.y - this.y; + + return dx * dx + dy * dy; + }, + + /** + * Calculate the length (or magnitude) of this Vector. + * + * @method Phaser.Math.Vector2#length + * @since 3.0.0 + * + * @return {number} The length of this Vector. + */ + length: function () + { + var x = this.x; + var y = this.y; + + return Math.sqrt(x * x + y * y); + }, + + /** + * Set the length (or magnitude) of this Vector. + * + * @method Phaser.Math.Vector2#setLength + * @since 3.23.0 + * + * @param {number} length - The new magnitude of this Vector. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + setLength: function (length) + { + return this.normalize().scale(length); + }, + + /** + * Calculate the length of this Vector squared. + * + * @method Phaser.Math.Vector2#lengthSq + * @since 3.0.0 + * + * @return {number} The length of this Vector, squared. + */ + lengthSq: function () + { + var x = this.x; + var y = this.y; + + return x * x + y * y; + }, + + /** + * Normalize this Vector. + * + * Makes the vector a unit length vector (magnitude of 1) in the same direction. + * + * @method Phaser.Math.Vector2#normalize + * @since 3.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + normalize: function () + { + var x = this.x; + var y = this.y; + var len = x * x + y * y; + + if (len > 0) + { + len = 1 / Math.sqrt(len); + + this.x = x * len; + this.y = y * len; + } + + return this; + }, + + /** + * Rotate this Vector to its perpendicular, in the positive direction. + * + * @method Phaser.Math.Vector2#normalizeRightHand + * @since 3.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + normalizeRightHand: function () + { + var x = this.x; + + this.x = this.y * -1; + this.y = x; + + return this; + }, + + /** + * Rotate this Vector to its perpendicular, in the negative direction. + * + * @method Phaser.Math.Vector2#normalizeLeftHand + * @since 3.23.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + normalizeLeftHand: function () + { + var x = this.x; + + this.x = this.y; + this.y = x * -1; + + return this; + }, + + /** + * Calculate the dot product of this Vector and the given Vector. + * + * @method Phaser.Math.Vector2#dot + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector2 to dot product with this Vector2. + * + * @return {number} The dot product of this Vector and the given Vector. + */ + dot: function (src) + { + return this.x * src.x + this.y * src.y; + }, + + /** + * Calculate the cross product of this Vector and the given Vector. + * + * @method Phaser.Math.Vector2#cross + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector2 to cross with this Vector2. + * + * @return {number} The cross product of this Vector and the given Vector. + */ + cross: function (src) + { + return this.x * src.y - this.y * src.x; + }, + + /** + * Linearly interpolate between this Vector and the given Vector. + * + * Interpolates this Vector towards the given Vector. + * + * @method Phaser.Math.Vector2#lerp + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} src - The Vector2 to interpolate towards. + * @param {number} [t=0] - The interpolation percentage, between 0 and 1. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + lerp: function (src, t) + { + if (t === undefined) { t = 0; } + + var ax = this.x; + var ay = this.y; + + this.x = ax + t * (src.x - ax); + this.y = ay + t * (src.y - ay); + + return this; + }, + + /** + * Transform this Vector with the given Matrix. + * + * @method Phaser.Math.Vector2#transformMat3 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} mat - The Matrix3 to transform this Vector2 with. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + transformMat3: function (mat) + { + var x = this.x; + var y = this.y; + var m = mat.val; + + this.x = m[0] * x + m[3] * y + m[6]; + this.y = m[1] * x + m[4] * y + m[7]; + + return this; + }, + + /** + * Transform this Vector with the given Matrix. + * + * @method Phaser.Math.Vector2#transformMat4 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector2 with. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + transformMat4: function (mat) + { + var x = this.x; + var y = this.y; + var m = mat.val; + + this.x = m[0] * x + m[4] * y + m[12]; + this.y = m[1] * x + m[5] * y + m[13]; + + return this; + }, + + /** + * Make this Vector the zero vector (0, 0). + * + * @method Phaser.Math.Vector2#reset + * @since 3.0.0 + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + reset: function () + { + this.x = 0; + this.y = 0; + + return this; + }, + + /** + * Limit the length (or magnitude) of this Vector. + * + * @method Phaser.Math.Vector2#limit + * @since 3.23.0 + * + * @param {number} max - The maximum length. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + limit: function (max) + { + var len = this.length(); + + if (len && len > max) + { + this.scale(max / len); + } + + return this; + }, + + /** + * Reflect this Vector off a line defined by a normal. + * + * @method Phaser.Math.Vector2#reflect + * @since 3.23.0 + * + * @param {Phaser.Math.Vector2} normal - A vector perpendicular to the line. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + reflect: function (normal) + { + normal = normal.clone().normalize(); + + return this.subtract(normal.scale(2 * this.dot(normal))); + }, + + /** + * Reflect this Vector across another. + * + * @method Phaser.Math.Vector2#mirror + * @since 3.23.0 + * + * @param {Phaser.Math.Vector2} axis - A vector to reflect across. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + mirror: function (axis) + { + return this.reflect(axis).negate(); + }, + + /** + * Rotate this Vector by an angle amount. + * + * @method Phaser.Math.Vector2#rotate + * @since 3.23.0 + * + * @param {number} delta - The angle to rotate by, in radians. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + rotate: function (delta) + { + var cos = Math.cos(delta); + var sin = Math.sin(delta); + + return this.set(cos * this.x - sin * this.y, sin * this.x + cos * this.y); + }, + + /** + * Project this Vector onto another. + * + * @method Phaser.Math.Vector2#project + * @since 3.60.0 + * + * @param {Phaser.Math.Vector2} src - The vector to project onto. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + project: function (src) + { + var scalar = this.dot(src) / src.dot(src); + + return this.copy(src).scale(scalar); + }, + + /** + * Calculates the vector projection of this Vector2 onto the non-zero `vecB`. This is the + * orthogonal projection of this vector onto a straight line parallel to `vecB`. + * + * @method Phaser.Math.Vector2#projectUnit + * @since 4.0.0 + * + * @param {Phaser.Math.Vector2} vecB - The vector to project onto. + * @param {Phaser.Math.Vector2} [out] - The Vector2 object to store the position in. If not given, a new Vector2 instance is created. + * + * @return {Phaser.Math.Vector2} This Vector2. + */ + projectUnit: function (vecB, out) + { + if (out === undefined) { out = new Vector2(); } + + var amt = ((this.x * vecB.x) + (this.y * vecB.y)); + + if (amt !== 0) + { + out.x = amt * vecB.x; + out.y = amt * vecB.y; + } + + return out; + } + +}); + +/** + * A static zero Vector2 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector2.ZERO + * @type {Phaser.Math.Vector2} + * @since 3.1.0 + */ +Vector2.ZERO = new Vector2(); + +/** + * A static right Vector2 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector2.RIGHT + * @type {Phaser.Math.Vector2} + * @since 3.16.0 + */ +Vector2.RIGHT = new Vector2(1, 0); + +/** + * A static left Vector2 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector2.LEFT + * @type {Phaser.Math.Vector2} + * @since 3.16.0 + */ +Vector2.LEFT = new Vector2(-1, 0); + +/** + * A static up Vector2 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector2.UP + * @type {Phaser.Math.Vector2} + * @since 3.16.0 + */ +Vector2.UP = new Vector2(0, -1); + +/** + * A static down Vector2 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector2.DOWN + * @type {Phaser.Math.Vector2} + * @since 3.16.0 + */ +Vector2.DOWN = new Vector2(0, 1); + +/** + * A static one Vector2 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector2.ONE + * @type {Phaser.Math.Vector2} + * @since 3.16.0 + */ +Vector2.ONE = new Vector2(1, 1); + +module.exports = Vector2; + + +/***/ }), + +/***/ 25836: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji +// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A representation of a vector in 3D space. + * + * A three-component vector. + * + * @class Vector3 + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {number} [x] - The x component. + * @param {number} [y] - The y component. + * @param {number} [z] - The z component. + */ +var Vector3 = new Class({ + + initialize: + + function Vector3 (x, y, z) + { + /** + * The x component of this Vector. + * + * @name Phaser.Math.Vector3#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = 0; + + /** + * The y component of this Vector. + * + * @name Phaser.Math.Vector3#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = 0; + + /** + * The z component of this Vector. + * + * @name Phaser.Math.Vector3#z + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.z = 0; + + if (typeof x === 'object') + { + this.x = x.x || 0; + this.y = x.y || 0; + this.z = x.z || 0; + } + else + { + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + } + }, + + /** + * Set this Vector to point up. + * + * Sets the y component of the vector to 1, and the others to 0. + * + * @method Phaser.Math.Vector3#up + * @since 3.0.0 + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + up: function () + { + this.x = 0; + this.y = 1; + this.z = 0; + + return this; + }, + + /** + * Sets the components of this Vector to be the `Math.min` result from the given vector. + * + * @method Phaser.Math.Vector3#min + * @since 3.50.0 + * + * @param {Phaser.Math.Vector3} v - The Vector3 to check the minimum values against. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + min: function (v) + { + this.x = Math.min(this.x, v.x); + this.y = Math.min(this.y, v.y); + this.z = Math.min(this.z, v.z); + + return this; + }, + + /** + * Sets the components of this Vector to be the `Math.max` result from the given vector. + * + * @method Phaser.Math.Vector3#max + * @since 3.50.0 + * + * @param {Phaser.Math.Vector3} v - The Vector3 to check the maximum values against. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + max: function (v) + { + this.x = Math.max(this.x, v.x); + this.y = Math.max(this.y, v.y); + this.z = Math.max(this.z, v.z); + + return this; + }, + + /** + * Make a clone of this Vector3. + * + * @method Phaser.Math.Vector3#clone + * @since 3.0.0 + * + * @return {Phaser.Math.Vector3} A new Vector3 object containing this Vectors values. + */ + clone: function () + { + return new Vector3(this.x, this.y, this.z); + }, + + /** + * Adds the two given Vector3s and sets the results into this Vector3. + * + * @method Phaser.Math.Vector3#addVectors + * @since 3.50.0 + * + * @param {Phaser.Math.Vector3} a - The first Vector to add. + * @param {Phaser.Math.Vector3} b - The second Vector to add. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + addVectors: function (a, b) + { + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + + return this; + }, + + /** + * Subtracts the two given Vector3s and sets the results into this Vector3. + * + * @method Phaser.Math.Vector3#subVectors + * @since 3.85.0 + * + * @param {Phaser.Math.Vector3} a - The first Vector to sub. + * @param {Phaser.Math.Vector3} b - The second Vector to sub. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + subVectors: function (a, b) + { + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + + return this; + }, + + /** + * Calculate the cross (vector) product of two given Vectors. + * + * @method Phaser.Math.Vector3#crossVectors + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} a - The first Vector to multiply. + * @param {Phaser.Math.Vector3} b - The second Vector to multiply. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + crossVectors: function (a, b) + { + var ax = a.x; + var ay = a.y; + var az = a.z; + var bx = b.x; + var by = b.y; + var bz = b.z; + + this.x = ay * bz - az * by; + this.y = az * bx - ax * bz; + this.z = ax * by - ay * bx; + + return this; + }, + + /** + * Check whether this Vector is equal to a given Vector. + * + * Performs a strict equality check against each Vector's components. + * + * @method Phaser.Math.Vector3#equals + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} v - The Vector3 to compare against. + * + * @return {boolean} True if the two vectors strictly match, otherwise false. + */ + equals: function (v) + { + return ((this.x === v.x) && (this.y === v.y) && (this.z === v.z)); + }, + + /** + * Copy the components of a given Vector into this Vector. + * + * @method Phaser.Math.Vector3#copy + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} src - The Vector to copy the components from. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + copy: function (src) + { + this.x = src.x; + this.y = src.y; + this.z = src.z || 0; + + return this; + }, + + /** + * Set the `x`, `y`, and `z` components of this Vector to the given `x`, `y`, and `z` values. + * + * @method Phaser.Math.Vector3#set + * @since 3.0.0 + * + * @param {(number|object)} x - The x value to set for this Vector, or an object containing x, y and z components. + * @param {number} [y] - The y value to set for this Vector. + * @param {number} [z] - The z value to set for this Vector. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + set: function (x, y, z) + { + if (typeof x === 'object') + { + this.x = x.x || 0; + this.y = x.y || 0; + this.z = x.z || 0; + } + else + { + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + } + + return this; + }, + + /** + * Sets the components of this Vector3 from the position of the given Matrix4. + * + * @method Phaser.Math.Vector3#setFromMatrixPosition + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to get the position from. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + setFromMatrixPosition: function (m) + { + return this.fromArray(m.val, 12); + }, + + /** + * Sets the components of this Vector3 from the Matrix4 column specified. + * + * @method Phaser.Math.Vector3#setFromMatrixColumn + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to get the column from. + * @param {number} index - The column index. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + setFromMatrixColumn: function (mat4, index) + { + return this.fromArray(mat4.val, index * 4); + }, + + /** + * Sets the components of this Vector3 from the given array, based on the offset. + * + * Vector3.x = array[offset] + * Vector3.y = array[offset + 1] + * Vector3.z = array[offset + 2] + * + * @method Phaser.Math.Vector3#fromArray + * @since 3.50.0 + * + * @param {number[]} array - The array of values to get this Vector from. + * @param {number} [offset=0] - The offset index into the array. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + fromArray: function (array, offset) + { + if (offset === undefined) { offset = 0; } + + this.x = array[offset]; + this.y = array[offset + 1]; + this.z = array[offset + 2]; + + return this; + }, + + /** + * Add a given Vector to this Vector. Addition is component-wise. + * + * @method Phaser.Math.Vector3#add + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to add to this Vector. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + add: function (v) + { + this.x += v.x; + this.y += v.y; + this.z += v.z || 0; + + return this; + }, + + /** + * Add the given value to each component of this Vector. + * + * @method Phaser.Math.Vector3#addScalar + * @since 3.50.0 + * + * @param {number} s - The amount to add to this Vector. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + addScalar: function (s) + { + this.x += s; + this.y += s; + this.z += s; + + return this; + }, + + /** + * Add and scale a given Vector to this Vector. Addition is component-wise. + * + * @method Phaser.Math.Vector3#addScale + * @since 3.50.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to add to this Vector. + * @param {number} scale - The amount to scale `v` by. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + addScale: function (v, scale) + { + this.x += v.x * scale; + this.y += v.y * scale; + this.z += v.z * scale || 0; + + return this; + }, + + /** + * Subtract the given Vector from this Vector. Subtraction is component-wise. + * + * @method Phaser.Math.Vector3#subtract + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to subtract from this Vector. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + subtract: function (v) + { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z || 0; + + return this; + }, + + /** + * Perform a component-wise multiplication between this Vector and the given Vector. + * + * Multiplies this Vector by the given Vector. + * + * @method Phaser.Math.Vector3#multiply + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to multiply this Vector by. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + multiply: function (v) + { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z || 1; + + return this; + }, + + /** + * Scale this Vector by the given value. + * + * @method Phaser.Math.Vector3#scale + * @since 3.0.0 + * + * @param {number} scale - The value to scale this Vector by. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + scale: function (scale) + { + if (isFinite(scale)) + { + this.x *= scale; + this.y *= scale; + this.z *= scale; + } + else + { + this.x = 0; + this.y = 0; + this.z = 0; + } + + return this; + }, + + /** + * Perform a component-wise division between this Vector and the given Vector. + * + * Divides this Vector by the given Vector. + * + * @method Phaser.Math.Vector3#divide + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to divide this Vector by. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + divide: function (v) + { + this.x /= v.x; + this.y /= v.y; + this.z /= v.z || 1; + + return this; + }, + + /** + * Negate the `x`, `y` and `z` components of this Vector. + * + * @method Phaser.Math.Vector3#negate + * @since 3.0.0 + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + negate: function () + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + + return this; + }, + + /** + * Calculate the distance between this Vector and the given Vector. + * + * @method Phaser.Math.Vector3#distance + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to calculate the distance to. + * + * @return {number} The distance from this Vector to the given Vector. + */ + distance: function (v) + { + var dx = v.x - this.x; + var dy = v.y - this.y; + var dz = v.z - this.z || 0; + + return Math.sqrt(dx * dx + dy * dy + dz * dz); + }, + + /** + * Calculate the distance between this Vector and the given Vector, squared. + * + * @method Phaser.Math.Vector3#distanceSq + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to calculate the distance to. + * + * @return {number} The distance from this Vector to the given Vector, squared. + */ + distanceSq: function (v) + { + var dx = v.x - this.x; + var dy = v.y - this.y; + var dz = v.z - this.z || 0; + + return dx * dx + dy * dy + dz * dz; + }, + + /** + * Calculate the length (or magnitude) of this Vector. + * + * @method Phaser.Math.Vector3#length + * @since 3.0.0 + * + * @return {number} The length of this Vector. + */ + length: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + + return Math.sqrt(x * x + y * y + z * z); + }, + + /** + * Calculate the length of this Vector squared. + * + * @method Phaser.Math.Vector3#lengthSq + * @since 3.0.0 + * + * @return {number} The length of this Vector, squared. + */ + lengthSq: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + + return x * x + y * y + z * z; + }, + + /** + * Normalize this Vector. + * + * Makes the vector a unit length vector (magnitude of 1) in the same direction. + * + * @method Phaser.Math.Vector3#normalize + * @since 3.0.0 + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + normalize: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var len = x * x + y * y + z * z; + + if (len > 0) + { + len = 1 / Math.sqrt(len); + + this.x = x * len; + this.y = y * len; + this.z = z * len; + } + + return this; + }, + + /** + * Calculate the dot product of this Vector and the given Vector. + * + * @method Phaser.Math.Vector3#dot + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} v - The Vector3 to dot product with this Vector3. + * + * @return {number} The dot product of this Vector and `v`. + */ + dot: function (v) + { + return this.x * v.x + this.y * v.y + this.z * v.z; + }, + + /** + * Calculate the cross (vector) product of this Vector (which will be modified) and the given Vector. + * + * @method Phaser.Math.Vector3#cross + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} v - The Vector to cross product with. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + cross: function (v) + { + var ax = this.x; + var ay = this.y; + var az = this.z; + var bx = v.x; + var by = v.y; + var bz = v.z; + + this.x = ay * bz - az * by; + this.y = az * bx - ax * bz; + this.z = ax * by - ay * bx; + + return this; + }, + + /** + * Linearly interpolate between this Vector and the given Vector. + * + * Interpolates this Vector towards the given Vector. + * + * @method Phaser.Math.Vector3#lerp + * @since 3.0.0 + * + * @param {Phaser.Math.Vector3} v - The Vector3 to interpolate towards. + * @param {number} [t=0] - The interpolation percentage, between 0 and 1. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + lerp: function (v, t) + { + if (t === undefined) { t = 0; } + + var ax = this.x; + var ay = this.y; + var az = this.z; + + this.x = ax + t * (v.x - ax); + this.y = ay + t * (v.y - ay); + this.z = az + t * (v.z - az); + + return this; + }, + + /** + * Takes a Matrix3 and applies it to this Vector3. + * + * @method Phaser.Math.Vector3#applyMatrix3 + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix3} mat3 - The Matrix3 to apply to this Vector3. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + applyMatrix3: function (mat3) + { + var x = this.x; + var y = this.y; + var z = this.z; + var m = mat3.val; + + this.x = m[0] * x + m[3] * y + m[6] * z; + this.y = m[1] * x + m[4] * y + m[7] * z; + this.z = m[2] * x + m[5] * y + m[8] * z; + + return this; + }, + + /** + * Takes a Matrix4 and applies it to this Vector3. + * + * @method Phaser.Math.Vector3#applyMatrix4 + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to apply to this Vector3. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + applyMatrix4: function (mat4) + { + var x = this.x; + var y = this.y; + var z = this.z; + var m = mat4.val; + + var w = 1 / (m[3] * x + m[7] * y + m[11] * z + m[15]); + + this.x = (m[0] * x + m[4] * y + m[8] * z + m[12]) * w; + this.y = (m[1] * x + m[5] * y + m[9] * z + m[13]) * w; + this.z = (m[2] * x + m[6] * y + m[10] * z + m[14]) * w; + + return this; + }, + + /** + * Transform this Vector with the given Matrix. + * + * @method Phaser.Math.Vector3#transformMat3 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix3} mat - The Matrix3 to transform this Vector3 with. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + transformMat3: function (mat) + { + var x = this.x; + var y = this.y; + var z = this.z; + var m = mat.val; + + this.x = x * m[0] + y * m[3] + z * m[6]; + this.y = x * m[1] + y * m[4] + z * m[7]; + this.z = x * m[2] + y * m[5] + z * m[8]; + + return this; + }, + + /** + * Transform this Vector with the given Matrix4. + * + * @method Phaser.Math.Vector3#transformMat4 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector3 with. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + transformMat4: function (mat) + { + var x = this.x; + var y = this.y; + var z = this.z; + var m = mat.val; + + this.x = m[0] * x + m[4] * y + m[8] * z + m[12]; + this.y = m[1] * x + m[5] * y + m[9] * z + m[13]; + this.z = m[2] * x + m[6] * y + m[10] * z + m[14]; + + return this; + }, + + /** + * Transforms the coordinates of this Vector3 with the given Matrix4. + * + * @method Phaser.Math.Vector3#transformCoordinates + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector3 with. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + transformCoordinates: function (mat) + { + var x = this.x; + var y = this.y; + var z = this.z; + var m = mat.val; + + var tx = (x * m[0]) + (y * m[4]) + (z * m[8]) + m[12]; + var ty = (x * m[1]) + (y * m[5]) + (z * m[9]) + m[13]; + var tz = (x * m[2]) + (y * m[6]) + (z * m[10]) + m[14]; + var tw = (x * m[3]) + (y * m[7]) + (z * m[11]) + m[15]; + + this.x = tx / tw; + this.y = ty / tw; + this.z = tz / tw; + + return this; + }, + + /** + * Transform this Vector with the given Quaternion. + * + * @method Phaser.Math.Vector3#transformQuat + * @since 3.0.0 + * + * @param {Phaser.Math.Quaternion} q - The Quaternion to transform this Vector with. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + transformQuat: function (q) + { + // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations + var x = this.x; + var y = this.y; + var z = this.z; + var qx = q.x; + var qy = q.y; + var qz = q.z; + var qw = q.w; + + // calculate quat * vec + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + + return this; + }, + + /** + * Multiplies this Vector3 by the specified matrix, applying a W divide. This is useful for projection, + * e.g. unprojecting a 2D point into 3D space. + * + * @method Phaser.Math.Vector3#project + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} mat - The Matrix4 to multiply this Vector3 with. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + project: function (mat) + { + var x = this.x; + var y = this.y; + var z = this.z; + var m = mat.val; + + var a00 = m[0]; + var a01 = m[1]; + var a02 = m[2]; + var a03 = m[3]; + var a10 = m[4]; + var a11 = m[5]; + var a12 = m[6]; + var a13 = m[7]; + var a20 = m[8]; + var a21 = m[9]; + var a22 = m[10]; + var a23 = m[11]; + var a30 = m[12]; + var a31 = m[13]; + var a32 = m[14]; + var a33 = m[15]; + + var lw = 1 / (x * a03 + y * a13 + z * a23 + a33); + + this.x = (x * a00 + y * a10 + z * a20 + a30) * lw; + this.y = (x * a01 + y * a11 + z * a21 + a31) * lw; + this.z = (x * a02 + y * a12 + z * a22 + a32) * lw; + + return this; + }, + + /** + * Multiplies this Vector3 by the given view and projection matrices. + * + * @method Phaser.Math.Vector3#projectViewMatrix + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} viewMatrix - A View Matrix. + * @param {Phaser.Math.Matrix4} projectionMatrix - A Projection Matrix. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + projectViewMatrix: function (viewMatrix, projectionMatrix) + { + return this.applyMatrix4(viewMatrix).applyMatrix4(projectionMatrix); + }, + + /** + * Multiplies this Vector3 by the given inversed projection matrix and world matrix. + * + * @method Phaser.Math.Vector3#unprojectViewMatrix + * @since 3.50.0 + * + * @param {Phaser.Math.Matrix4} projectionMatrix - An inversed Projection Matrix. + * @param {Phaser.Math.Matrix4} worldMatrix - A World View Matrix. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + unprojectViewMatrix: function (projectionMatrix, worldMatrix) + { + return this.applyMatrix4(projectionMatrix).applyMatrix4(worldMatrix); + }, + + /** + * Unproject this point from 2D space to 3D space. + * The point should have its x and y properties set to + * 2D screen space, and the z either at 0 (near plane) + * or 1 (far plane). The provided matrix is assumed to already + * be combined, i.e. projection * view * model. + * + * After this operation, this vector's (x, y, z) components will + * represent the unprojected 3D coordinate. + * + * @method Phaser.Math.Vector3#unproject + * @since 3.0.0 + * + * @param {Phaser.Math.Vector4} viewport - Screen x, y, width and height in pixels. + * @param {Phaser.Math.Matrix4} invProjectionView - Combined projection and view matrix. + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + unproject: function (viewport, invProjectionView) + { + var viewX = viewport.x; + var viewY = viewport.y; + var viewWidth = viewport.z; + var viewHeight = viewport.w; + + var x = this.x - viewX; + var y = (viewHeight - this.y - 1) - viewY; + var z = this.z; + + this.x = (2 * x) / viewWidth - 1; + this.y = (2 * y) / viewHeight - 1; + this.z = 2 * z - 1; + + return this.project(invProjectionView); + }, + + /** + * Make this Vector the zero vector (0, 0, 0). + * + * @method Phaser.Math.Vector3#reset + * @since 3.0.0 + * + * @return {Phaser.Math.Vector3} This Vector3. + */ + reset: function () + { + this.x = 0; + this.y = 0; + this.z = 0; + + return this; + } + +}); + +/** + * A static zero Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.ZERO + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.ZERO = new Vector3(); + +/** + * A static right Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.RIGHT + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.RIGHT = new Vector3(1, 0, 0); + +/** + * A static left Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.LEFT + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.LEFT = new Vector3(-1, 0, 0); + +/** + * A static up Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.UP + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.UP = new Vector3(0, -1, 0); + +/** + * A static down Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.DOWN + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.DOWN = new Vector3(0, 1, 0); + +/** + * A static forward Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.FORWARD + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.FORWARD = new Vector3(0, 0, 1); + +/** + * A static back Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.BACK + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.BACK = new Vector3(0, 0, -1); + +/** + * A static one Vector3 for use by reference. + * + * This constant is meant for comparison operations and should not be modified directly. + * + * @constant + * @name Phaser.Math.Vector3.ONE + * @type {Phaser.Math.Vector3} + * @since 3.16.0 + */ +Vector3.ONE = new Vector3(1, 1, 1); + +module.exports = Vector3; + + +/***/ }), + +/***/ 61369: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji +// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A representation of a vector in 4D space. + * + * A four-component vector. + * + * @class Vector4 + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {number} [x] - The x component. + * @param {number} [y] - The y component. + * @param {number} [z] - The z component. + * @param {number} [w] - The w component. + */ +var Vector4 = new Class({ + + initialize: + + function Vector4 (x, y, z, w) + { + /** + * The x component of this Vector. + * + * @name Phaser.Math.Vector4#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = 0; + + /** + * The y component of this Vector. + * + * @name Phaser.Math.Vector4#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = 0; + + /** + * The z component of this Vector. + * + * @name Phaser.Math.Vector4#z + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.z = 0; + + /** + * The w component of this Vector. + * + * @name Phaser.Math.Vector4#w + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.w = 0; + + if (typeof x === 'object') + { + this.x = x.x || 0; + this.y = x.y || 0; + this.z = x.z || 0; + this.w = x.w || 0; + } + else + { + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + this.w = w || 0; + } + }, + + /** + * Make a clone of this Vector4. + * + * @method Phaser.Math.Vector4#clone + * @since 3.0.0 + * + * @return {Phaser.Math.Vector4} A clone of this Vector4. + */ + clone: function () + { + return new Vector4(this.x, this.y, this.z, this.w); + }, + + /** + * Copy the components of a given Vector into this Vector. + * + * @method Phaser.Math.Vector4#copy + * @since 3.0.0 + * + * @param {Phaser.Math.Vector4} src - The Vector to copy the components from. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + copy: function (src) + { + this.x = src.x; + this.y = src.y; + this.z = src.z || 0; + this.w = src.w || 0; + + return this; + }, + + /** + * Check whether this Vector is equal to a given Vector. + * + * Performs a strict quality check against each Vector's components. + * + * @method Phaser.Math.Vector4#equals + * @since 3.0.0 + * + * @param {Phaser.Math.Vector4} v - The vector to check equality with. + * + * @return {boolean} A boolean indicating whether the two Vectors are equal or not. + */ + equals: function (v) + { + return ((this.x === v.x) && (this.y === v.y) && (this.z === v.z) && (this.w === v.w)); + }, + + /** + * Set the `x`, `y`, `z` and `w` components of the this Vector to the given `x`, `y`, `z` and `w` values. + * + * @method Phaser.Math.Vector4#set + * @since 3.0.0 + * + * @param {(number|object)} x - The x value to set for this Vector, or an object containing x, y, z and w components. + * @param {number} y - The y value to set for this Vector. + * @param {number} z - The z value to set for this Vector. + * @param {number} w - The z value to set for this Vector. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + set: function (x, y, z, w) + { + if (typeof x === 'object') + { + this.x = x.x || 0; + this.y = x.y || 0; + this.z = x.z || 0; + this.w = x.w || 0; + } + else + { + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + this.w = w || 0; + } + + return this; + }, + + /** + * Add a given Vector to this Vector. Addition is component-wise. + * + * @method Phaser.Math.Vector4#add + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to add to this Vector. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + add: function (v) + { + this.x += v.x; + this.y += v.y; + this.z += v.z || 0; + this.w += v.w || 0; + + return this; + }, + + /** + * Subtract the given Vector from this Vector. Subtraction is component-wise. + * + * @method Phaser.Math.Vector4#subtract + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to subtract from this Vector. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + subtract: function (v) + { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z || 0; + this.w -= v.w || 0; + + return this; + }, + + /** + * Scale this Vector by the given value. + * + * @method Phaser.Math.Vector4#scale + * @since 3.0.0 + * + * @param {number} scale - The value to scale this Vector by. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + scale: function (scale) + { + this.x *= scale; + this.y *= scale; + this.z *= scale; + this.w *= scale; + + return this; + }, + + /** + * Calculate the length (or magnitude) of this Vector. + * + * @method Phaser.Math.Vector4#length + * @since 3.0.0 + * + * @return {number} The length of this Vector. + */ + length: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + + return Math.sqrt(x * x + y * y + z * z + w * w); + }, + + /** + * Calculate the length of this Vector squared. + * + * @method Phaser.Math.Vector4#lengthSq + * @since 3.0.0 + * + * @return {number} The length of this Vector, squared. + */ + lengthSq: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + + return x * x + y * y + z * z + w * w; + }, + + /** + * Normalize this Vector. + * + * Makes the vector a unit length vector (magnitude of 1) in the same direction. + * + * @method Phaser.Math.Vector4#normalize + * @since 3.0.0 + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + normalize: function () + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + var len = x * x + y * y + z * z + w * w; + + if (len > 0) + { + len = 1 / Math.sqrt(len); + + this.x = x * len; + this.y = y * len; + this.z = z * len; + this.w = w * len; + } + + return this; + }, + + /** + * Calculate the dot product of this Vector and the given Vector. + * + * @method Phaser.Math.Vector4#dot + * @since 3.0.0 + * + * @param {Phaser.Math.Vector4} v - The Vector4 to dot product with this Vector4. + * + * @return {number} The dot product of this Vector and the given Vector. + */ + dot: function (v) + { + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; + }, + + /** + * Linearly interpolate between this Vector and the given Vector. + * + * Interpolates this Vector towards the given Vector. + * + * @method Phaser.Math.Vector4#lerp + * @since 3.0.0 + * + * @param {Phaser.Math.Vector4} v - The Vector4 to interpolate towards. + * @param {number} [t=0] - The interpolation percentage, between 0 and 1. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + lerp: function (v, t) + { + if (t === undefined) { t = 0; } + + var ax = this.x; + var ay = this.y; + var az = this.z; + var aw = this.w; + + this.x = ax + t * (v.x - ax); + this.y = ay + t * (v.y - ay); + this.z = az + t * (v.z - az); + this.w = aw + t * (v.w - aw); + + return this; + }, + + /** + * Perform a component-wise multiplication between this Vector and the given Vector. + * + * Multiplies this Vector by the given Vector. + * + * @method Phaser.Math.Vector4#multiply + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to multiply this Vector by. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + multiply: function (v) + { + this.x *= v.x; + this.y *= v.y; + this.z *= v.z || 1; + this.w *= v.w || 1; + + return this; + }, + + /** + * Perform a component-wise division between this Vector and the given Vector. + * + * Divides this Vector by the given Vector. + * + * @method Phaser.Math.Vector4#divide + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to divide this Vector by. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + divide: function (v) + { + this.x /= v.x; + this.y /= v.y; + this.z /= v.z || 1; + this.w /= v.w || 1; + + return this; + }, + + /** + * Calculate the distance between this Vector and the given Vector. + * + * @method Phaser.Math.Vector4#distance + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to calculate the distance to. + * + * @return {number} The distance from this Vector to the given Vector. + */ + distance: function (v) + { + var dx = v.x - this.x; + var dy = v.y - this.y; + var dz = v.z - this.z || 0; + var dw = v.w - this.w || 0; + + return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw); + }, + + /** + * Calculate the distance between this Vector and the given Vector, squared. + * + * @method Phaser.Math.Vector4#distanceSq + * @since 3.0.0 + * + * @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to calculate the distance to. + * + * @return {number} The distance from this Vector to the given Vector, squared. + */ + distanceSq: function (v) + { + var dx = v.x - this.x; + var dy = v.y - this.y; + var dz = v.z - this.z || 0; + var dw = v.w - this.w || 0; + + return dx * dx + dy * dy + dz * dz + dw * dw; + }, + + /** + * Negate the `x`, `y`, `z` and `w` components of this Vector. + * + * @method Phaser.Math.Vector4#negate + * @since 3.0.0 + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + negate: function () + { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + this.w = -this.w; + + return this; + }, + + /** + * Transform this Vector with the given Matrix. + * + * @method Phaser.Math.Vector4#transformMat4 + * @since 3.0.0 + * + * @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector4 with. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + transformMat4: function (mat) + { + var x = this.x; + var y = this.y; + var z = this.z; + var w = this.w; + var m = mat.val; + + this.x = m[0] * x + m[4] * y + m[8] * z + m[12] * w; + this.y = m[1] * x + m[5] * y + m[9] * z + m[13] * w; + this.z = m[2] * x + m[6] * y + m[10] * z + m[14] * w; + this.w = m[3] * x + m[7] * y + m[11] * z + m[15] * w; + + return this; + }, + + /** + * Transform this Vector with the given Quaternion. + * + * @method Phaser.Math.Vector4#transformQuat + * @since 3.0.0 + * + * @param {Phaser.Math.Quaternion} q - The Quaternion to transform this Vector with. + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + transformQuat: function (q) + { + var x = this.x; + var y = this.y; + var z = this.z; + var qx = q.x; + var qy = q.y; + var qz = q.z; + var qw = q.w; + + // calculate quat * vec + var ix = qw * x + qy * z - qz * y; + var iy = qw * y + qz * x - qx * z; + var iz = qw * z + qx * y - qy * x; + var iw = -qx * x - qy * y - qz * z; + + // calculate result * inverse quat + this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; + this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; + this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; + + return this; + }, + + /** + * Make this Vector the zero vector (0, 0, 0, 0). + * + * @method Phaser.Math.Vector4#reset + * @since 3.0.0 + * + * @return {Phaser.Math.Vector4} This Vector4. + */ + reset: function () + { + this.x = 0; + this.y = 0; + this.z = 0; + this.w = 0; + + return this; + } + +}); + +Vector4.prototype.sub = Vector4.prototype.subtract; +Vector4.prototype.mul = Vector4.prototype.multiply; +Vector4.prototype.div = Vector4.prototype.divide; +Vector4.prototype.dist = Vector4.prototype.distance; +Vector4.prototype.distSq = Vector4.prototype.distanceSq; +Vector4.prototype.len = Vector4.prototype.length; +Vector4.prototype.lenSq = Vector4.prototype.lengthSq; + +module.exports = Vector4; + + +/***/ }), + +/***/ 60417: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if the two values are within the given `tolerance` of each other. + * + * @function Phaser.Math.Within + * @since 3.0.0 + * + * @param {number} a - The first value to use in the calculation. + * @param {number} b - The second value to use in the calculation. + * @param {number} tolerance - The tolerance. Anything equal to or less than this value is considered as being within range. + * + * @return {boolean} Returns `true` if `a` is less than or equal to the tolerance of `b`. + */ +var Within = function (a, b, tolerance) +{ + return (Math.abs(a - b) <= tolerance); +}; + +module.exports = Within; + + +/***/ }), + +/***/ 15994: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Wrap the given `value` between `min` and `max`. + * + * @function Phaser.Math.Wrap + * @since 3.0.0 + * + * @param {number} value - The value to wrap. + * @param {number} min - The minimum value. + * @param {number} max - The maximum value. + * + * @return {number} The wrapped value. + */ +var Wrap = function (value, min, max) +{ + var range = max - min; + + return (min + ((((value - min) % range) + range) % range)); +}; + +module.exports = Wrap; + + +/***/ }), + +/***/ 31040: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Find the angle of a segment from (x1, y1) -> (x2, y2). + * + * @function Phaser.Math.Angle.Between + * @since 3.0.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * + * @return {number} The angle in radians. + */ +var Between = function (x1, y1, x2, y2) +{ + return Math.atan2(y2 - y1, x2 - x1); +}; + +module.exports = Between; + + +/***/ }), + +/***/ 55495: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Find the angle of a segment from (point1.x, point1.y) -> (point2.x, point2.y). + * + * Calculates the angle of the vector from the first point to the second point. + * + * @function Phaser.Math.Angle.BetweenPoints + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} point1 - The first point. + * @param {Phaser.Types.Math.Vector2Like} point2 - The second point. + * + * @return {number} The angle in radians. + */ +var BetweenPoints = function (point1, point2) +{ + return Math.atan2(point2.y - point1.y, point2.x - point1.x); +}; + +module.exports = BetweenPoints; + + +/***/ }), + +/***/ 128: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Find the angle of a segment from (point1.x, point1.y) -> (point2.x, point2.y). + * + * The difference between this method and {@link Phaser.Math.Angle.BetweenPoints} is that this assumes the y coordinate + * travels down the screen. + * + * @function Phaser.Math.Angle.BetweenPointsY + * @since 3.0.0 + * + * @param {Phaser.Types.Math.Vector2Like} point1 - The first point. + * @param {Phaser.Types.Math.Vector2Like} point2 - The second point. + * + * @return {number} The angle in radians. + */ +var BetweenPointsY = function (point1, point2) +{ + return Math.atan2(point2.x - point1.x, point2.y - point1.y); +}; + +module.exports = BetweenPointsY; + + +/***/ }), + +/***/ 41273: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Find the angle of a segment from (x1, y1) -> (x2, y2). + * + * The difference between this method and {@link Phaser.Math.Angle.Between} is that this assumes the y coordinate + * travels down the screen. + * + * @function Phaser.Math.Angle.BetweenY + * @since 3.0.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * + * @return {number} The angle in radians. + */ +var BetweenY = function (x1, y1, x2, y2) +{ + return Math.atan2(x2 - x1, y2 - y1); +}; + +module.exports = BetweenY; + + +/***/ }), + +/***/ 1432: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(36383); + +/** + * Takes an angle in Phasers default clockwise format and converts it so that + * 0 is North, 90 is West, 180 is South and 270 is East, + * therefore running counter-clockwise instead of clockwise. + * + * You can pass in the angle from a Game Object using: + * + * ```javascript + * var converted = CounterClockwise(gameobject.rotation); + * ``` + * + * All values for this function are in radians. + * + * @function Phaser.Math.Angle.CounterClockwise + * @since 3.16.0 + * + * @param {number} angle - The angle to convert, in radians. + * + * @return {number} The converted angle, in radians. + */ +var CounterClockwise = function (angle) +{ + if (angle > Math.PI) + { + angle -= CONST.TAU; + } + + return Math.abs((((angle + CONST.PI_OVER_2) % CONST.TAU) - CONST.TAU) % CONST.TAU); +}; + +module.exports = CounterClockwise; + + +/***/ }), + +/***/ 12407: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Normalize an angle to the [0, 2pi] range. + * + * @function Phaser.Math.Angle.Normalize + * @since 3.0.0 + * + * @param {number} angle - The angle to normalize, in radians. + * + * @return {number} The normalized angle, in radians. + */ +var Normalize = function (angle) +{ + angle = angle % (2 * Math.PI); + + if (angle >= 0) + { + return angle; + } + else + { + return angle + 2 * Math.PI; + } +}; + +module.exports = Normalize; + + +/***/ }), + +/***/ 53993: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author @samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FloatBetween = __webpack_require__(99472); + +/** + * Returns a random angle in the range [-pi, pi]. + * + * @function Phaser.Math.Angle.Random + * @since 3.23.0 + * + * @return {number} The angle, in radians. + */ +var Random = function () +{ + return FloatBetween(-Math.PI, Math.PI); +}; + +module.exports = Random; + + +/***/ }), + +/***/ 86564: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author @samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FloatBetween = __webpack_require__(99472); + +/** + * Returns a random angle in the range [-180, 180]. + * + * @function Phaser.Math.Angle.RandomDegrees + * @since 3.23.0 + * + * @return {number} The angle, in degrees. + */ +var RandomDegrees = function () +{ + return FloatBetween(-180, 180); +}; + +module.exports = RandomDegrees; + + +/***/ }), + +/***/ 90154: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Normalize = __webpack_require__(12407); + +/** + * Reverse the given angle. + * + * @function Phaser.Math.Angle.Reverse + * @since 3.0.0 + * + * @param {number} angle - The angle to reverse, in radians. + * + * @return {number} The reversed angle, in radians. + */ +var Reverse = function (angle) +{ + return Normalize(angle + Math.PI); +}; + +module.exports = Reverse; + + +/***/ }), + +/***/ 48736: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = __webpack_require__(36383); + +/** + * Rotates `currentAngle` towards `targetAngle`, taking the shortest rotation distance. The `lerp` argument is the amount to rotate by in this call. + * + * @function Phaser.Math.Angle.RotateTo + * @since 3.0.0 + * + * @param {number} currentAngle - The current angle, in radians. + * @param {number} targetAngle - The target angle to rotate to, in radians. + * @param {number} [lerp=0.05] - The lerp value to add to the current angle. + * + * @return {number} The adjusted angle. + */ +var RotateTo = function (currentAngle, targetAngle, lerp) +{ + if (lerp === undefined) { lerp = 0.05; } + + if (currentAngle === targetAngle) + { + return currentAngle; + } + + if (Math.abs(targetAngle - currentAngle) <= lerp || Math.abs(targetAngle - currentAngle) >= (MATH_CONST.TAU - lerp)) + { + currentAngle = targetAngle; + } + else + { + if (Math.abs(targetAngle - currentAngle) > Math.PI) + { + if (targetAngle < currentAngle) + { + targetAngle += MATH_CONST.TAU; + } + else + { + targetAngle -= MATH_CONST.TAU; + } + } + + if (targetAngle > currentAngle) + { + currentAngle += lerp; + } + else if (targetAngle < currentAngle) + { + currentAngle -= lerp; + } + } + + return currentAngle; +}; + +module.exports = RotateTo; + + +/***/ }), + +/***/ 61430: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Gets the shortest angle between `angle1` and `angle2`. + * + * Both angles must be in the range -180 to 180, which is the same clamped + * range that `sprite.angle` uses, so you can pass in two sprite angles to + * this method and get the shortest angle back between the two of them. + * + * The angle returned will be in the same range. If the returned angle is + * greater than 0 then it's a counter-clockwise rotation, if < 0 then it's + * a clockwise rotation. + * + * @function Phaser.Math.Angle.ShortestBetween + * @since 3.0.0 + * + * @param {number} angle1 - The first angle in the range -180 to 180. + * @param {number} angle2 - The second angle in the range -180 to 180. + * + * @return {number} The shortest angle, in degrees. If greater than zero it's a counter-clockwise rotation. + */ +var ShortestBetween = function (angle1, angle2) +{ + var difference = angle2 - angle1; + + if (difference === 0) + { + return 0; + } + + var times = Math.floor((difference - (-180)) / 360); + + return difference - (times * 360); + +}; + +module.exports = ShortestBetween; + + +/***/ }), + +/***/ 86554: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MathWrap = __webpack_require__(15994); + +/** + * Wrap an angle. + * + * Wraps the angle to a value in the range of -PI to PI. + * + * @function Phaser.Math.Angle.Wrap + * @since 3.0.0 + * + * @param {number} angle - The angle to wrap, in radians. + * + * @return {number} The wrapped angle, in radians. + */ +var Wrap = function (angle) +{ + return MathWrap(angle, -Math.PI, Math.PI); +}; + +module.exports = Wrap; + + +/***/ }), + +/***/ 30954: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Wrap = __webpack_require__(15994); + +/** + * Wrap an angle in degrees. + * + * Wraps the angle to a value in the range of -180 to 180. + * + * @function Phaser.Math.Angle.WrapDegrees + * @since 3.0.0 + * + * @param {number} angle - The angle to wrap, in degrees. + * + * @return {number} The wrapped angle, in degrees. + */ +var WrapDegrees = function (angle) +{ + return Wrap(angle, -180, 180); +}; + +module.exports = WrapDegrees; + + +/***/ }), + +/***/ 25588: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Angle + */ + +module.exports = { + + Between: __webpack_require__(31040), + BetweenPoints: __webpack_require__(55495), + BetweenPointsY: __webpack_require__(128), + BetweenY: __webpack_require__(41273), + CounterClockwise: __webpack_require__(1432), + Normalize: __webpack_require__(12407), + Random: __webpack_require__(53993), + RandomDegrees: __webpack_require__(86564), + Reverse: __webpack_require__(90154), + RotateTo: __webpack_require__(48736), + ShortestBetween: __webpack_require__(61430), + Wrap: __webpack_require__(86554), + WrapDegrees: __webpack_require__(30954) + +}; + + +/***/ }), + +/***/ 36383: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH_CONST = { + + /** + * The value of PI * 2. + * + * @name Phaser.Math.TAU + * @type {number} + * @since 4.0.0 + */ + TAU: Math.PI * 2, + + /** + * The value of PI / 2, or 90 degrees, in radians. + * + * @name Phaser.Math.PI_OVER_2 + * @type {number} + * @since 3.0.0 + */ + PI_OVER_2: Math.PI / 2, + + /** + * An epsilon value (1.0e-6) + * + * @name Phaser.Math.EPSILON + * @type {number} + * @since 3.0.0 + */ + EPSILON: 1.0e-6, + + /** + * For converting degrees to radians (PI / 180) + * + * @name Phaser.Math.DEG_TO_RAD + * @type {number} + * @since 3.0.0 + */ + DEG_TO_RAD: Math.PI / 180, + + /** + * For converting radians to degrees (180 / PI) + * + * @name Phaser.Math.RAD_TO_DEG + * @type {number} + * @since 3.0.0 + */ + RAD_TO_DEG: 180 / Math.PI, + + /** + * An instance of the Random Number Generator. + * This is not set until the Game boots. + * + * @name Phaser.Math.RND + * @type {Phaser.Math.RandomDataGenerator} + * @since 3.0.0 + */ + RND: null, + + /** + * The minimum safe integer this browser supports. + * We use a const for backward compatibility with Internet Explorer. + * + * @name Phaser.Math.MIN_SAFE_INTEGER + * @type {number} + * @since 3.21.0 + */ + MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER || -9007199254740991, + + /** + * The maximum safe integer this browser supports. + * We use a const for backward compatibility with Internet Explorer. + * + * @name Phaser.Math.MAX_SAFE_INTEGER + * @type {number} + * @since 3.21.0 + */ + MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER || 9007199254740991 + +}; + +module.exports = MATH_CONST; + + +/***/ }), + +/***/ 20339: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the distance between two sets of coordinates (points). + * + * @function Phaser.Math.Distance.Between + * @since 3.0.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * + * @return {number} The distance between each point. + */ +var DistanceBetween = function (x1, y1, x2, y2) +{ + var dx = x1 - x2; + var dy = y1 - y2; + + return Math.sqrt(dx * dx + dy * dy); +}; + +module.exports = DistanceBetween; + + +/***/ }), + +/***/ 52816: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the distance between two points. + * + * @function Phaser.Math.Distance.BetweenPoints + * @since 3.22.0 + * + * @param {Phaser.Types.Math.Vector2Like} a - The first point. + * @param {Phaser.Types.Math.Vector2Like} b - The second point. + * + * @return {number} The distance between the points. + */ +var DistanceBetweenPoints = function (a, b) +{ + var dx = a.x - b.x; + var dy = a.y - b.y; + + return Math.sqrt(dx * dx + dy * dy); +}; + +module.exports = DistanceBetweenPoints; + + +/***/ }), + +/***/ 64559: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the squared distance between two points. + * + * @function Phaser.Math.Distance.BetweenPointsSquared + * @since 3.22.0 + * + * @param {Phaser.Types.Math.Vector2Like} a - The first point. + * @param {Phaser.Types.Math.Vector2Like} b - The second point. + * + * @return {number} The squared distance between the points. + */ +var DistanceBetweenPointsSquared = function (a, b) +{ + var dx = a.x - b.x; + var dy = a.y - b.y; + + return dx * dx + dy * dy; +}; + +module.exports = DistanceBetweenPointsSquared; + + +/***/ }), + +/***/ 82340: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the Chebyshev distance between two sets of coordinates (points). + * + * Chebyshev distance (or chessboard distance) is the maximum of the horizontal and vertical distances. + * It's the effective distance when movement can be horizontal, vertical, or diagonal. + * + * @function Phaser.Math.Distance.Chebyshev + * @since 3.22.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * + * @return {number} The distance between each point. + */ +var ChebyshevDistance = function (x1, y1, x2, y2) +{ + return Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2)); +}; + +module.exports = ChebyshevDistance; + + +/***/ }), + +/***/ 14390: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the distance between two sets of coordinates (points) to the power of `pow`. + * + * @function Phaser.Math.Distance.Power + * @since 3.0.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * @param {number} pow - The exponent. + * + * @return {number} The distance between each point. + */ +var DistancePower = function (x1, y1, x2, y2, pow) +{ + if (pow === undefined) { pow = 2; } + + return Math.sqrt(Math.pow(x2 - x1, pow) + Math.pow(y2 - y1, pow)); +}; + +module.exports = DistancePower; + + +/***/ }), + +/***/ 2243: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the snake distance between two sets of coordinates (points). + * + * Snake distance (rectilinear distance, Manhattan distance) is the sum of the horizontal and vertical distances. + * It's the effective distance when movement is allowed only horizontally or vertically (but not both). + * + * @function Phaser.Math.Distance.Snake + * @since 3.22.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * + * @return {number} The distance between each point. + */ +var SnakeDistance = function (x1, y1, x2, y2) +{ + return Math.abs(x1 - x2) + Math.abs(y1 - y2); +}; + +module.exports = SnakeDistance; + + +/***/ }), + +/***/ 89774: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the distance between two sets of coordinates (points), squared. + * + * @function Phaser.Math.Distance.Squared + * @since 3.0.0 + * + * @param {number} x1 - The x coordinate of the first point. + * @param {number} y1 - The y coordinate of the first point. + * @param {number} x2 - The x coordinate of the second point. + * @param {number} y2 - The y coordinate of the second point. + * + * @return {number} The distance between each point, squared. + */ +var DistanceSquared = function (x1, y1, x2, y2) +{ + var dx = x1 - x2; + var dy = y1 - y2; + + return dx * dx + dy * dy; +}; + +module.exports = DistanceSquared; + + +/***/ }), + +/***/ 50994: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Distance + */ + +module.exports = { + + Between: __webpack_require__(20339), + BetweenPoints: __webpack_require__(52816), + BetweenPointsSquared: __webpack_require__(64559), + Chebyshev: __webpack_require__(82340), + Power: __webpack_require__(14390), + Snake: __webpack_require__(2243), + Squared: __webpack_require__(89774) + +}; + + +/***/ }), + +/***/ 62640: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Back = __webpack_require__(54178); +var Bounce = __webpack_require__(41521); +var Circular = __webpack_require__(79980); +var Cubic = __webpack_require__(85433); +var Elastic = __webpack_require__(99140); +var Expo = __webpack_require__(48857); +var Linear = __webpack_require__(81596); +var Quadratic = __webpack_require__(59133); +var Quartic = __webpack_require__(98516); +var Quintic = __webpack_require__(35248); +var Sine = __webpack_require__(82500); +var Stepped = __webpack_require__(49752); + +// EaseMap +module.exports = { + + Power0: Linear, + Power1: Quadratic.Out, + Power2: Cubic.Out, + Power3: Quartic.Out, + Power4: Quintic.Out, + + Linear: Linear, + Quad: Quadratic.Out, + Cubic: Cubic.Out, + Quart: Quartic.Out, + Quint: Quintic.Out, + Sine: Sine.Out, + Expo: Expo.Out, + Circ: Circular.Out, + Elastic: Elastic.Out, + Back: Back.Out, + Bounce: Bounce.Out, + Stepped: Stepped, + + 'Quad.easeIn': Quadratic.In, + 'Cubic.easeIn': Cubic.In, + 'Quart.easeIn': Quartic.In, + 'Quint.easeIn': Quintic.In, + 'Sine.easeIn': Sine.In, + 'Expo.easeIn': Expo.In, + 'Circ.easeIn': Circular.In, + 'Elastic.easeIn': Elastic.In, + 'Back.easeIn': Back.In, + 'Bounce.easeIn': Bounce.In, + + 'Quad.easeOut': Quadratic.Out, + 'Cubic.easeOut': Cubic.Out, + 'Quart.easeOut': Quartic.Out, + 'Quint.easeOut': Quintic.Out, + 'Sine.easeOut': Sine.Out, + 'Expo.easeOut': Expo.Out, + 'Circ.easeOut': Circular.Out, + 'Elastic.easeOut': Elastic.Out, + 'Back.easeOut': Back.Out, + 'Bounce.easeOut': Bounce.Out, + + 'Quad.easeInOut': Quadratic.InOut, + 'Cubic.easeInOut': Cubic.InOut, + 'Quart.easeInOut': Quartic.InOut, + 'Quint.easeInOut': Quintic.InOut, + 'Sine.easeInOut': Sine.InOut, + 'Expo.easeInOut': Expo.InOut, + 'Circ.easeInOut': Circular.InOut, + 'Elastic.easeInOut': Elastic.InOut, + 'Back.easeInOut': Back.InOut, + 'Bounce.easeInOut': Bounce.InOut + +}; + + +/***/ }), + +/***/ 1639: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Back ease-in. + * + * @function Phaser.Math.Easing.Back.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [overshoot=1.70158] - The overshoot amount. + * + * @return {number} The tweened value. + */ +var In = function (v, overshoot) +{ + if (overshoot === undefined) { overshoot = 1.70158; } + + return v * v * ((overshoot + 1) * v - overshoot); +}; + +module.exports = In; + + +/***/ }), + +/***/ 50099: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Back ease-in/out. + * + * @function Phaser.Math.Easing.Back.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [overshoot=1.70158] - The overshoot amount. + * + * @return {number} The tweened value. + */ +var InOut = function (v, overshoot) +{ + if (overshoot === undefined) { overshoot = 1.70158; } + + var s = overshoot * 1.525; + + if ((v *= 2) < 1) + { + return 0.5 * (v * v * ((s + 1) * v - s)); + } + else + { + return 0.5 * ((v -= 2) * v * ((s + 1) * v + s) + 2); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 41286: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Back ease-out. + * + * @function Phaser.Math.Easing.Back.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [overshoot=1.70158] - The overshoot amount. + * + * @return {number} The tweened value. + */ +var Out = function (v, overshoot) +{ + if (overshoot === undefined) { overshoot = 1.70158; } + + return --v * v * ((overshoot + 1) * v + overshoot) + 1; +}; + +module.exports = Out; + + +/***/ }), + +/***/ 54178: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Back + */ + +module.exports = { + + In: __webpack_require__(1639), + Out: __webpack_require__(41286), + InOut: __webpack_require__(50099) + +}; + + +/***/ }), + +/***/ 59590: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Bounce ease-in. + * + * @function Phaser.Math.Easing.Bounce.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + v = 1 - v; + + if (v < 1 / 2.75) + { + return 1 - (7.5625 * v * v); + } + else if (v < 2 / 2.75) + { + return 1 - (7.5625 * (v -= 1.5 / 2.75) * v + 0.75); + } + else if (v < 2.5 / 2.75) + { + return 1 - (7.5625 * (v -= 2.25 / 2.75) * v + 0.9375); + } + else + { + return 1 - (7.5625 * (v -= 2.625 / 2.75) * v + 0.984375); + } +}; + +module.exports = In; + + +/***/ }), + +/***/ 41788: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Bounce ease-in/out. + * + * @function Phaser.Math.Easing.Bounce.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + var reverse = false; + + if (v < 0.5) + { + v = 1 - (v * 2); + reverse = true; + } + else + { + v = (v * 2) - 1; + } + + if (v < 1 / 2.75) + { + v = 7.5625 * v * v; + } + else if (v < 2 / 2.75) + { + v = 7.5625 * (v -= 1.5 / 2.75) * v + 0.75; + } + else if (v < 2.5 / 2.75) + { + v = 7.5625 * (v -= 2.25 / 2.75) * v + 0.9375; + } + else + { + v = 7.5625 * (v -= 2.625 / 2.75) * v + 0.984375; + } + + if (reverse) + { + return (1 - v) * 0.5; + } + else + { + return v * 0.5 + 0.5; + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 69905: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Bounce ease-out. + * + * @function Phaser.Math.Easing.Bounce.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + if (v < 1 / 2.75) + { + return 7.5625 * v * v; + } + else if (v < 2 / 2.75) + { + return 7.5625 * (v -= 1.5 / 2.75) * v + 0.75; + } + else if (v < 2.5 / 2.75) + { + return 7.5625 * (v -= 2.25 / 2.75) * v + 0.9375; + } + else + { + return 7.5625 * (v -= 2.625 / 2.75) * v + 0.984375; + } +}; + +module.exports = Out; + + +/***/ }), + +/***/ 41521: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Bounce + */ + +module.exports = { + + In: __webpack_require__(59590), + Out: __webpack_require__(69905), + InOut: __webpack_require__(41788) + +}; + + +/***/ }), + +/***/ 91861: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Circular ease-in. + * + * @function Phaser.Math.Easing.Circular.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + return 1 - Math.sqrt(1 - v * v); +}; + +module.exports = In; + + +/***/ }), + +/***/ 4177: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Circular ease-in/out. + * + * @function Phaser.Math.Easing.Circular.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if ((v *= 2) < 1) + { + return -0.5 * (Math.sqrt(1 - v * v) - 1); + } + else + { + return 0.5 * (Math.sqrt(1 - (v -= 2) * v) + 1); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 57512: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Circular ease-out. + * + * @function Phaser.Math.Easing.Circular.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + return Math.sqrt(1 - (--v * v)); +}; + +module.exports = Out; + + +/***/ }), + +/***/ 79980: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Circular + */ + +module.exports = { + + In: __webpack_require__(91861), + Out: __webpack_require__(57512), + InOut: __webpack_require__(4177) + +}; + + +/***/ }), + +/***/ 51150: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Cubic ease-in. + * + * @function Phaser.Math.Easing.Cubic.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + return v * v * v; +}; + +module.exports = In; + + +/***/ }), + +/***/ 82820: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Cubic ease-in/out. + * + * @function Phaser.Math.Easing.Cubic.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if ((v *= 2) < 1) + { + return 0.5 * v * v * v; + } + else + { + return 0.5 * ((v -= 2) * v * v + 2); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 35033: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Cubic ease-out. + * + * @function Phaser.Math.Easing.Cubic.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + return --v * v * v + 1; +}; + +module.exports = Out; + + +/***/ }), + +/***/ 85433: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Cubic + */ + +module.exports = { + + In: __webpack_require__(51150), + Out: __webpack_require__(35033), + InOut: __webpack_require__(82820) + +}; + + +/***/ }), + +/***/ 69965: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Elastic ease-in. + * + * @function Phaser.Math.Easing.Elastic.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [amplitude=0.1] - The amplitude of the elastic ease. + * @param {number} [period=0.1] - Sets how tight the sine-wave is, where smaller values are tighter waves, which result in more cycles. + * + * @return {number} The tweened value. + */ +var In = function (v, amplitude, period) +{ + if (amplitude === undefined) { amplitude = 0.1; } + if (period === undefined) { period = 0.1; } + + if (v === 0) + { + return 0; + } + else if (v === 1) + { + return 1; + } + else + { + var s = period / 4; + + if (amplitude < 1) + { + amplitude = 1; + } + else + { + s = period * Math.asin(1 / amplitude) / (2 * Math.PI); + } + + return -(amplitude * Math.pow(2, 10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / period)); + } +}; + +module.exports = In; + + +/***/ }), + +/***/ 50665: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Elastic ease-in/out. + * + * @function Phaser.Math.Easing.Elastic.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [amplitude=0.1] - The amplitude of the elastic ease. + * @param {number} [period=0.1] - Sets how tight the sine-wave is, where smaller values are tighter waves, which result in more cycles. + * + * @return {number} The tweened value. + */ +var InOut = function (v, amplitude, period) +{ + if (amplitude === undefined) { amplitude = 0.1; } + if (period === undefined) { period = 0.1; } + + if (v === 0) + { + return 0; + } + else if (v === 1) + { + return 1; + } + else + { + var s = period / 4; + + if (amplitude < 1) + { + amplitude = 1; + } + else + { + s = period * Math.asin(1 / amplitude) / (2 * Math.PI); + } + + if ((v *= 2) < 1) + { + return -0.5 * (amplitude * Math.pow(2, 10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / period)); + } + else + { + return amplitude * Math.pow(2, -10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / period) * 0.5 + 1; + } + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 7744: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Elastic ease-out. + * + * @function Phaser.Math.Easing.Elastic.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [amplitude=0.1] - The amplitude of the elastic ease. + * @param {number} [period=0.1] - Sets how tight the sine-wave is, where smaller values are tighter waves, which result in more cycles. + * + * @return {number} The tweened value. + */ +var Out = function (v, amplitude, period) +{ + if (amplitude === undefined) { amplitude = 0.1; } + if (period === undefined) { period = 0.1; } + + if (v === 0) + { + return 0; + } + else if (v === 1) + { + return 1; + } + else + { + var s = period / 4; + + if (amplitude < 1) + { + amplitude = 1; + } + else + { + s = period * Math.asin(1 / amplitude) / (2 * Math.PI); + } + + return (amplitude * Math.pow(2, -10 * v) * Math.sin((v - s) * (2 * Math.PI) / period) + 1); + } +}; + +module.exports = Out; + + +/***/ }), + +/***/ 99140: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Elastic + */ + +module.exports = { + + In: __webpack_require__(69965), + Out: __webpack_require__(7744), + InOut: __webpack_require__(50665) + +}; + + +/***/ }), + +/***/ 24590: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Exponential ease-in. + * + * @function Phaser.Math.Easing.Expo.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + return Math.pow(2, 10 * (v - 1)) - 0.001; +}; + +module.exports = In; + + +/***/ }), + +/***/ 87844: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Exponential ease-in/out. + * + * @function Phaser.Math.Easing.Expo.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if ((v *= 2) < 1) + { + return 0.5 * Math.pow(2, 10 * (v - 1)); + } + else + { + return 0.5 * (2 - Math.pow(2, -10 * (v - 1))); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 89433: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Exponential ease-out. + * + * @function Phaser.Math.Easing.Expo.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + return 1 - Math.pow(2, -10 * v); +}; + +module.exports = Out; + + +/***/ }), + +/***/ 48857: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Expo + */ + +module.exports = { + + In: __webpack_require__(24590), + Out: __webpack_require__(89433), + InOut: __webpack_require__(87844) + +}; + + +/***/ }), + +/***/ 48820: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing + */ + +module.exports = { + + Back: __webpack_require__(54178), + Bounce: __webpack_require__(41521), + Circular: __webpack_require__(79980), + Cubic: __webpack_require__(85433), + Elastic: __webpack_require__(99140), + Expo: __webpack_require__(48857), + Linear: __webpack_require__(81596), + Quadratic: __webpack_require__(59133), + Quartic: __webpack_require__(98516), + Quintic: __webpack_require__(35248), + Sine: __webpack_require__(82500), + Stepped: __webpack_require__(49752) + +}; + + +/***/ }), + +/***/ 7147: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Linear easing (no variation). + * + * @function Phaser.Math.Easing.Linear + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Linear = function (v) +{ + return v; +}; + +module.exports = Linear; + + +/***/ }), + +/***/ 81596: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +module.exports = __webpack_require__(7147); + + +/***/ }), + +/***/ 34826: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quadratic ease-in. + * + * @function Phaser.Math.Easing.Quadratic.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + return v * v; +}; + +module.exports = In; + + +/***/ }), + +/***/ 20544: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quadratic ease-in/out. + * + * @function Phaser.Math.Easing.Quadratic.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if ((v *= 2) < 1) + { + return 0.5 * v * v; + } + else + { + return -0.5 * (--v * (v - 2) - 1); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 92029: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quadratic ease-out. + * + * @function Phaser.Math.Easing.Quadratic.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + return v * (2 - v); +}; + +module.exports = Out; + + +/***/ }), + +/***/ 59133: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Quadratic + */ + +module.exports = { + + In: __webpack_require__(34826), + Out: __webpack_require__(92029), + InOut: __webpack_require__(20544) + +}; + + +/***/ }), + +/***/ 64413: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quartic ease-in. + * + * @function Phaser.Math.Easing.Quartic.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + return v * v * v * v; +}; + +module.exports = In; + + +/***/ }), + +/***/ 78137: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quartic ease-in/out. + * + * @function Phaser.Math.Easing.Quartic.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if ((v *= 2) < 1) + { + return 0.5 * v * v * v * v; + } + else + { + return -0.5 * ((v -= 2) * v * v * v - 2); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 45840: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quartic ease-out. + * + * @function Phaser.Math.Easing.Quartic.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + return 1 - (--v * v * v * v); +}; + +module.exports = Out; + + +/***/ }), + +/***/ 98516: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Quartic + */ + +module.exports = { + + In: __webpack_require__(64413), + Out: __webpack_require__(45840), + InOut: __webpack_require__(78137) + +}; + + +/***/ }), + +/***/ 87745: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quintic ease-in. + * + * @function Phaser.Math.Easing.Quintic.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + return v * v * v * v * v; +}; + +module.exports = In; + + +/***/ }), + +/***/ 16509: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quintic ease-in/out. + * + * @function Phaser.Math.Easing.Quintic.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if ((v *= 2) < 1) + { + return 0.5 * v * v * v * v * v; + } + else + { + return 0.5 * ((v -= 2) * v * v * v * v + 2); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 17868: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Quintic ease-out. + * + * @function Phaser.Math.Easing.Quintic.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + return --v * v * v * v * v + 1; +}; + +module.exports = Out; + + +/***/ }), + +/***/ 35248: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Quintic + */ + +module.exports = { + + In: __webpack_require__(87745), + Out: __webpack_require__(17868), + InOut: __webpack_require__(16509) + +}; + + +/***/ }), + +/***/ 80461: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sinusoidal ease-in. + * + * @function Phaser.Math.Easing.Sine.In + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var In = function (v) +{ + if (v === 0) + { + return 0; + } + else if (v === 1) + { + return 1; + } + else + { + return 1 - Math.cos(v * Math.PI / 2); + } +}; + +module.exports = In; + + +/***/ }), + +/***/ 34025: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sinusoidal ease-in/out. + * + * @function Phaser.Math.Easing.Sine.InOut + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var InOut = function (v) +{ + if (v === 0) + { + return 0; + } + else if (v === 1) + { + return 1; + } + else + { + return 0.5 * (1 - Math.cos(Math.PI * v)); + } +}; + +module.exports = InOut; + + +/***/ }), + +/***/ 52768: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sinusoidal ease-out. + * + * @function Phaser.Math.Easing.Sine.Out + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * + * @return {number} The tweened value. + */ +var Out = function (v) +{ + if (v === 0) + { + return 0; + } + else if (v === 1) + { + return 1; + } + else + { + return Math.sin(v * Math.PI / 2); + } +}; + +module.exports = Out; + + +/***/ }), + +/***/ 82500: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Sine + */ + +module.exports = { + + In: __webpack_require__(80461), + Out: __webpack_require__(52768), + InOut: __webpack_require__(34025) + +}; + + +/***/ }), + +/***/ 72251: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Stepped easing. + * + * @function Phaser.Math.Easing.Stepped + * @since 3.0.0 + * + * @param {number} v - The value to be tweened. + * @param {number} [steps=1] - The number of steps in the ease. + * + * @return {number} The tweened value. + */ +var Stepped = function (v, steps) +{ + if (steps === undefined) { steps = 1; } + + if (v <= 0) + { + return 0; + } + else if (v >= 1) + { + return 1; + } + else + { + return (((steps * v) | 0) + 1) * (1 / steps); + } +}; + +module.exports = Stepped; + + +/***/ }), + +/***/ 49752: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Easing.Stepped + */ + +module.exports = __webpack_require__(72251); + + +/***/ }), + +/***/ 75698: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the fuzzy ceiling of the given value. + * + * @function Phaser.Math.Fuzzy.Ceil + * @since 3.0.0 + * + * @param {number} value - The value. + * @param {number} [epsilon=0.0001] - The epsilon. + * + * @return {number} The fuzzy ceiling of the value. + */ +var Ceil = function (value, epsilon) +{ + if (epsilon === undefined) { epsilon = 0.0001; } + + return Math.ceil(value - epsilon); +}; + +module.exports = Ceil; + + +/***/ }), + +/***/ 43855: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check whether the given values are fuzzily equal. + * + * Two numbers are fuzzily equal if their difference is less than `epsilon`. + * + * @function Phaser.Math.Fuzzy.Equal + * @since 3.0.0 + * + * @param {number} a - The first value. + * @param {number} b - The second value. + * @param {number} [epsilon=0.0001] - The epsilon. + * + * @return {boolean} `true` if the values are fuzzily equal, otherwise `false`. + */ +var Equal = function (a, b, epsilon) +{ + if (epsilon === undefined) { epsilon = 0.0001; } + + return Math.abs(a - b) < epsilon; +}; + +module.exports = Equal; + + +/***/ }), + +/***/ 25777: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculate the fuzzy floor of the given value. + * + * @function Phaser.Math.Fuzzy.Floor + * @since 3.0.0 + * + * @param {number} value - The value. + * @param {number} [epsilon=0.0001] - The epsilon. + * + * @return {number} The floor of the value. + */ +var Floor = function (value, epsilon) +{ + if (epsilon === undefined) { epsilon = 0.0001; } + + return Math.floor(value + epsilon); +}; + +module.exports = Floor; + + +/***/ }), + +/***/ 5470: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check whether `a` is fuzzily greater than `b`. + * + * `a` is fuzzily greater than `b` if it is more than `b - epsilon`. + * + * @function Phaser.Math.Fuzzy.GreaterThan + * @since 3.0.0 + * + * @param {number} a - The first value. + * @param {number} b - The second value. + * @param {number} [epsilon=0.0001] - The epsilon. + * + * @return {boolean} `true` if `a` is fuzzily greater than than `b`, otherwise `false`. + */ +var GreaterThan = function (a, b, epsilon) +{ + if (epsilon === undefined) { epsilon = 0.0001; } + + return a > b - epsilon; +}; + +module.exports = GreaterThan; + + +/***/ }), + +/***/ 94977: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Check whether `a` is fuzzily less than `b`. + * + * `a` is fuzzily less than `b` if it is less than `b + epsilon`. + * + * @function Phaser.Math.Fuzzy.LessThan + * @since 3.0.0 + * + * @param {number} a - The first value. + * @param {number} b - The second value. + * @param {number} [epsilon=0.0001] - The epsilon. + * + * @return {boolean} `true` if `a` is fuzzily less than `b`, otherwise `false`. + */ +var LessThan = function (a, b, epsilon) +{ + if (epsilon === undefined) { epsilon = 0.0001; } + + return a < b + epsilon; +}; + +module.exports = LessThan; + + +/***/ }), + +/***/ 48379: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Fuzzy + */ + +module.exports = { + + Ceil: __webpack_require__(75698), + Equal: __webpack_require__(43855), + Floor: __webpack_require__(25777), + GreaterThan: __webpack_require__(5470), + LessThan: __webpack_require__(94977) + +}; + + +/***/ }), + +/***/ 75508: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(36383); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Math + */ + +var PhaserMath = { + + // Collections of functions + Angle: __webpack_require__(25588), + Distance: __webpack_require__(50994), + Easing: __webpack_require__(48820), + Fuzzy: __webpack_require__(48379), + Interpolation: __webpack_require__(38289), + Pow2: __webpack_require__(49001), + Snap: __webpack_require__(73697), + + // Expose the RNG Class + RandomDataGenerator: __webpack_require__(28453), + + // Single functions + Average: __webpack_require__(53307), + Bernstein: __webpack_require__(85710), + Between: __webpack_require__(30976), + CatmullRom: __webpack_require__(87842), + CeilTo: __webpack_require__(26302), + Clamp: __webpack_require__(45319), + DegToRad: __webpack_require__(39506), + Difference: __webpack_require__(61241), + Euler: __webpack_require__(38857), + Factorial: __webpack_require__(6411), + FloatBetween: __webpack_require__(99472), + FloorTo: __webpack_require__(77623), + FromPercent: __webpack_require__(62945), + GetCentroid: __webpack_require__(2672), + GetSpeed: __webpack_require__(38265), + GetVec2Bounds: __webpack_require__(55133), + IsEven: __webpack_require__(78702), + IsEvenStrict: __webpack_require__(94883), + Linear: __webpack_require__(28915), + LinearXY: __webpack_require__(94908), + MaxAdd: __webpack_require__(86883), + Median: __webpack_require__(50040), + MinSub: __webpack_require__(37204), + Percent: __webpack_require__(65201), + RadToDeg: __webpack_require__(43396), + RandomXY: __webpack_require__(74362), + RandomXYZ: __webpack_require__(60706), + RandomXYZW: __webpack_require__(67421), + Rotate: __webpack_require__(36305), + RotateAround: __webpack_require__(11520), + RotateAroundDistance: __webpack_require__(1163), + RotateTo: __webpack_require__(70336), + RoundAwayFromZero: __webpack_require__(2284), + RoundTo: __webpack_require__(41013), + SmootherStep: __webpack_require__(54261), + SmoothStep: __webpack_require__(7602), + ToXY: __webpack_require__(44408), + TransformXY: __webpack_require__(85955), + Within: __webpack_require__(60417), + Wrap: __webpack_require__(15994), + + // Vector classes + Vector2: __webpack_require__(26099), + Vector3: __webpack_require__(25836), + Vector4: __webpack_require__(61369), + Matrix3: __webpack_require__(94434), + Matrix4: __webpack_require__(37867), + Quaternion: __webpack_require__(15746), + RotateVec3: __webpack_require__(72678) + +}; + +// Merge in the consts + +PhaserMath = Extend(false, PhaserMath, CONST); + +// Export it + +module.exports = PhaserMath; + + +/***/ }), + +/***/ 89318: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bernstein = __webpack_require__(85710); + +/** + * A bezier interpolation method. + * + * @function Phaser.Math.Interpolation.Bezier + * @since 3.0.0 + * + * @param {number[]} v - The input array of values to interpolate between. + * @param {number} k - The percentage of interpolation, between 0 and 1. + * + * @return {number} The interpolated value. + */ +var BezierInterpolation = function (v, k) +{ + var b = 0; + var n = v.length - 1; + + for (var i = 0; i <= n; i++) + { + b += Math.pow(1 - k, n - i) * Math.pow(k, i) * v[i] * Bernstein(n, i); + } + + return b; +}; + +module.exports = BezierInterpolation; + + +/***/ }), + +/***/ 77259: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CatmullRom = __webpack_require__(87842); + +/** + * A Catmull-Rom interpolation method. + * + * @function Phaser.Math.Interpolation.CatmullRom + * @since 3.0.0 + * + * @param {number[]} v - The input array of values to interpolate between. + * @param {number} k - The percentage of interpolation, between 0 and 1. + * + * @return {number} The interpolated value. + */ +var CatmullRomInterpolation = function (v, k) +{ + var m = v.length - 1; + var f = m * k; + var i = Math.floor(f); + + if (v[0] === v[m]) + { + if (k < 0) + { + i = Math.floor(f = m * (1 + k)); + } + + return CatmullRom(f - i, v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m]); + } + else + { + if (k < 0) + { + return v[0] - (CatmullRom(-f, v[0], v[0], v[1], v[1]) - v[0]); + } + + if (k > 1) + { + return v[m] - (CatmullRom(f - m, v[m], v[m], v[m - 1], v[m - 1]) - v[m]); + } + + return CatmullRom(f - i, v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2]); + } +}; + +module.exports = CatmullRomInterpolation; + + +/***/ }), + +/***/ 36316: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @ignore + */ +function P0 (t, p) +{ + var k = 1 - t; + + return k * k * k * p; +} + +/** + * @ignore + */ +function P1 (t, p) +{ + var k = 1 - t; + + return 3 * k * k * t * p; +} + +/** + * @ignore + */ +function P2 (t, p) +{ + return 3 * (1 - t) * t * t * p; +} + +/** + * @ignore + */ +function P3 (t, p) +{ + return t * t * t * p; +} + +/** + * A cubic bezier interpolation method. + * + * https://medium.com/@adrian_cooney/bezier-interpolation-13b68563313a + * + * @function Phaser.Math.Interpolation.CubicBezier + * @since 3.0.0 + * + * @param {number} t - The percentage of interpolation, between 0 and 1. + * @param {number} p0 - The start point. + * @param {number} p1 - The first control point. + * @param {number} p2 - The second control point. + * @param {number} p3 - The end point. + * + * @return {number} The interpolated value. + */ +var CubicBezierInterpolation = function (t, p0, p1, p2, p3) +{ + return P0(t, p0) + P1(t, p1) + P2(t, p2) + P3(t, p3); +}; + +module.exports = CubicBezierInterpolation; + + +/***/ }), + +/***/ 28392: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Linear = __webpack_require__(28915); + +/** + * A linear interpolation method. + * + * @function Phaser.Math.Interpolation.Linear + * @since 3.0.0 + * @see {@link https://en.wikipedia.org/wiki/Linear_interpolation} + * + * @param {number[]} v - The input array of values to interpolate between. + * @param {!number} k - The percentage of interpolation, between 0 and 1. + * + * @return {!number} The interpolated value. + */ +var LinearInterpolation = function (v, k) +{ + var m = v.length - 1; + var f = m * k; + var i = Math.floor(f); + + if (k < 0) + { + return Linear(v[0], v[1], f); + } + else if (k > 1) + { + return Linear(v[m], v[m - 1], m - f); + } + else + { + return Linear(v[i], v[(i + 1 > m) ? m : i + 1], f - i); + } +}; + +module.exports = LinearInterpolation; + + +/***/ }), + +/***/ 32112: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @ignore + */ +function P0 (t, p) +{ + var k = 1 - t; + + return k * k * p; +} + +/** + * @ignore + */ +function P1 (t, p) +{ + return 2 * (1 - t) * t * p; +} + +/** + * @ignore + */ +function P2 (t, p) +{ + return t * t * p; +} + +// https://github.com/mrdoob/three.js/blob/master/src/extras/core/Interpolations.js + +/** + * A quadratic bezier interpolation method. + * + * @function Phaser.Math.Interpolation.QuadraticBezier + * @since 3.2.0 + * + * @param {number} t - The percentage of interpolation, between 0 and 1. + * @param {number} p0 - The start point. + * @param {number} p1 - The control point. + * @param {number} p2 - The end point. + * + * @return {number} The interpolated value. + */ +var QuadraticBezierInterpolation = function (t, p0, p1, p2) +{ + return P0(t, p0) + P1(t, p1) + P2(t, p2); +}; + +module.exports = QuadraticBezierInterpolation; + + +/***/ }), + +/***/ 47235: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SmoothStep = __webpack_require__(7602); + +/** + * A Smooth Step interpolation method. + * + * @function Phaser.Math.Interpolation.SmoothStep + * @since 3.9.0 + * @see {@link https://en.wikipedia.org/wiki/Smoothstep} + * + * @param {number} t - The percentage of interpolation, between 0 and 1. + * @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'. + * @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'. + * + * @return {number} The interpolated value. + */ +var SmoothStepInterpolation = function (t, min, max) +{ + return min + (max - min) * SmoothStep(t, 0, 1); +}; + +module.exports = SmoothStepInterpolation; + + +/***/ }), + +/***/ 50178: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SmootherStep = __webpack_require__(54261); + +/** + * A Smoother Step interpolation method. + * + * @function Phaser.Math.Interpolation.SmootherStep + * @since 3.9.0 + * @see {@link https://en.wikipedia.org/wiki/Smoothstep#Variations} + * + * @param {number} t - The percentage of interpolation, between 0 and 1. + * @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'. + * @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'. + * + * @return {number} The interpolated value. + */ +var SmootherStepInterpolation = function (t, min, max) +{ + return min + (max - min) * SmootherStep(t, 0, 1); +}; + +module.exports = SmootherStepInterpolation; + + +/***/ }), + +/***/ 38289: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Interpolation + */ + +module.exports = { + + Bezier: __webpack_require__(89318), + CatmullRom: __webpack_require__(77259), + CubicBezier: __webpack_require__(36316), + Linear: __webpack_require__(28392), + QuadraticBezier: __webpack_require__(32112), + SmoothStep: __webpack_require__(47235), + SmootherStep: __webpack_require__(50178) + +}; + + +/***/ }), + +/***/ 98439: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the nearest power of 2 to the given `value`. + * + * @function Phaser.Math.Pow2.GetNext + * @since 3.0.0 + * + * @param {number} value - The value. + * + * @return {number} The nearest power of 2 to `value`. + */ +var GetPowerOfTwo = function (value) +{ + var index = Math.log(value) / 0.6931471805599453; + + return (1 << Math.ceil(index)); +}; + +module.exports = GetPowerOfTwo; + + +/***/ }), + +/***/ 50030: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if the given `width` and `height` are a power of two. + * Useful for checking texture dimensions. + * + * @function Phaser.Math.Pow2.IsSize + * @since 3.0.0 + * + * @param {number} width - The width. + * @param {number} height - The height. + * + * @return {boolean} `true` if `width` and `height` are a power of two, otherwise `false`. + */ +var IsSizePowerOfTwo = function (width, height) +{ + return (width > 0 && (width & (width - 1)) === 0 && height > 0 && (height & (height - 1)) === 0); +}; + +module.exports = IsSizePowerOfTwo; + + +/***/ }), + +/***/ 81230: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Tests the value and returns `true` if it is a power of two. + * + * @function Phaser.Math.Pow2.IsValue + * @since 3.0.0 + * + * @param {number} value - The value to check if it's a power of two. + * + * @return {boolean} Returns `true` if `value` is a power of two, otherwise `false`. + */ +var IsValuePowerOfTwo = function (value) +{ + return (value > 0 && (value & (value - 1)) === 0); +}; + +module.exports = IsValuePowerOfTwo; + + +/***/ }), + +/***/ 49001: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Pow2 + */ + +module.exports = { + + GetNext: __webpack_require__(98439), + IsSize: __webpack_require__(50030), + IsValue: __webpack_require__(81230) + +}; + + +/***/ }), + +/***/ 28453: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A seeded Random Data Generator. + * + * Access via `Phaser.Math.RND` which is an instance of this class pre-defined + * by Phaser. Or, create your own instance to use as you require. + * + * The `Math.RND` generator is seeded by the Game Config property value `seed`. + * If no such config property exists, a random number is used. + * + * If you create your own instance of this class you should provide a seed for it. + * If no seed is given it will use a 'random' one based on Date.now. + * + * @class RandomDataGenerator + * @memberof Phaser.Math + * @constructor + * @since 3.0.0 + * + * @param {(string|string[])} [seeds] - The seeds to use for the random number generator. + */ +var RandomDataGenerator = new Class({ + + initialize: + + function RandomDataGenerator (seeds) + { + if (seeds === undefined) { seeds = [ (Date.now() * Math.random()).toString() ]; } + + /** + * Internal var. + * + * @name Phaser.Math.RandomDataGenerator#c + * @type {number} + * @default 1 + * @private + * @since 3.0.0 + */ + this.c = 1; + + /** + * Internal var. + * + * @name Phaser.Math.RandomDataGenerator#s0 + * @type {number} + * @default 0 + * @private + * @since 3.0.0 + */ + this.s0 = 0; + + /** + * Internal var. + * + * @name Phaser.Math.RandomDataGenerator#s1 + * @type {number} + * @default 0 + * @private + * @since 3.0.0 + */ + this.s1 = 0; + + /** + * Internal var. + * + * @name Phaser.Math.RandomDataGenerator#s2 + * @type {number} + * @default 0 + * @private + * @since 3.0.0 + */ + this.s2 = 0; + + /** + * Internal var. + * + * @name Phaser.Math.RandomDataGenerator#n + * @type {number} + * @default 0 + * @private + * @since 3.2.0 + */ + this.n = 0; + + /** + * Signs to choose from. + * + * @name Phaser.Math.RandomDataGenerator#signs + * @type {number[]} + * @since 3.0.0 + */ + this.signs = [ -1, 1 ]; + + if (seeds) + { + this.init(seeds); + } + }, + + /** + * Private random helper. + * + * @method Phaser.Math.RandomDataGenerator#rnd + * @since 3.0.0 + * @private + * + * @return {number} A random number. + */ + rnd: function () + { + var t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32 + + this.c = t | 0; + this.s0 = this.s1; + this.s1 = this.s2; + this.s2 = t - this.c; + + return this.s2; + }, + + /** + * Internal method that creates a seed hash. + * + * @method Phaser.Math.RandomDataGenerator#hash + * @since 3.0.0 + * @private + * + * @param {string} data - The value to hash. + * + * @return {number} The hashed value. + */ + hash: function (data) + { + var h; + var n = this.n; + + data = data.toString(); + + for (var i = 0; i < data.length; i++) + { + n += data.charCodeAt(i); + h = 0.02519603282416938 * n; + n = h >>> 0; + h -= n; + h *= n; + n = h >>> 0; + h -= n; + n += h * 0x100000000;// 2^32 + } + + this.n = n; + + return (n >>> 0) * 2.3283064365386963e-10;// 2^-32 + }, + + /** + * Initialize the state of the random data generator. + * + * @method Phaser.Math.RandomDataGenerator#init + * @since 3.0.0 + * + * @param {(string|string[])} seeds - The seeds to initialize the random data generator with. + */ + init: function (seeds) + { + if (typeof seeds === 'string') + { + this.state(seeds); + } + else + { + this.sow(seeds); + } + }, + + /** + * Reset the seed of the random data generator. + * + * _Note_: the seed array is only processed up to the first `undefined` (or `null`) value, should such be present. + * + * @method Phaser.Math.RandomDataGenerator#sow + * @since 3.0.0 + * + * @param {string[]} seeds - The array of seeds: the `toString()` of each value is used. + */ + sow: function (seeds) + { + // Always reset to default seed + this.n = 0xefc8249d; + this.s0 = this.hash(' '); + this.s1 = this.hash(' '); + this.s2 = this.hash(' '); + this.c = 1; + + if (!seeds) + { + return; + } + + // Apply any seeds + for (var i = 0; i < seeds.length && (seeds[i] != null); i++) + { + var seed = seeds[i]; + + this.s0 -= this.hash(seed); + this.s0 += ~~(this.s0 < 0); + this.s1 -= this.hash(seed); + this.s1 += ~~(this.s1 < 0); + this.s2 -= this.hash(seed); + this.s2 += ~~(this.s2 < 0); + } + }, + + /** + * Returns a random integer between 0 and 2^32. + * + * @method Phaser.Math.RandomDataGenerator#integer + * @since 3.0.0 + * + * @return {number} A random integer between 0 and 2^32. + */ + integer: function () + { + // 2^32 + return this.rnd() * 0x100000000; + }, + + /** + * Returns a random real number between 0 and 1. + * + * @method Phaser.Math.RandomDataGenerator#frac + * @since 3.0.0 + * + * @return {number} A random real number between 0 and 1. + */ + frac: function () + { + // 2^-53 + return this.rnd() + (this.rnd() * 0x200000 | 0) * 1.1102230246251565e-16; + }, + + /** + * Returns a random real number between 0 and 2^32. + * + * @method Phaser.Math.RandomDataGenerator#real + * @since 3.0.0 + * + * @return {number} A random real number between 0 and 2^32. + */ + real: function () + { + return this.integer() + this.frac(); + }, + + /** + * Returns a random integer between and including min and max. + * + * @method Phaser.Math.RandomDataGenerator#integerInRange + * @since 3.0.0 + * + * @param {number} min - The minimum value in the range. + * @param {number} max - The maximum value in the range. + * + * @return {number} A random number between min and max. + */ + integerInRange: function (min, max) + { + return Math.floor(this.realInRange(0, max - min + 1) + min); + }, + + /** + * Returns a random integer between and including min and max. + * This method is an alias for RandomDataGenerator.integerInRange. + * + * @method Phaser.Math.RandomDataGenerator#between + * @since 3.0.0 + * + * @param {number} min - The minimum value in the range. + * @param {number} max - The maximum value in the range. + * + * @return {number} A random number between min and max. + */ + between: function (min, max) + { + return Math.floor(this.realInRange(0, max - min + 1) + min); + }, + + /** + * Returns a random real number between min and max. + * + * @method Phaser.Math.RandomDataGenerator#realInRange + * @since 3.0.0 + * + * @param {number} min - The minimum value in the range. + * @param {number} max - The maximum value in the range. + * + * @return {number} A random number between min and max. + */ + realInRange: function (min, max) + { + return this.frac() * (max - min) + min; + }, + + /** + * Returns a random real number between -1 and 1. + * + * @method Phaser.Math.RandomDataGenerator#normal + * @since 3.0.0 + * + * @return {number} A random real number between -1 and 1. + */ + normal: function () + { + return 1 - (2 * this.frac()); + }, + + /** + * Returns a valid RFC4122 version4 ID hex string from https://gist.github.com/1308368 + * + * @method Phaser.Math.RandomDataGenerator#uuid + * @since 3.0.0 + * + * @return {string} A valid RFC4122 version4 ID hex string + */ + uuid: function () + { + var a = ''; + var b = ''; + + for (b = a = ''; a++ < 36; b += ~a % 5 | a * 3 & 4 ? (a ^ 15 ? 8 ^ this.frac() * (a ^ 20 ? 16 : 4) : 4).toString(16) : '-') + { + // eslint-disable-next-line no-empty + } + + return b; + }, + + /** + * Returns a random element from within the given array. + * + * @method Phaser.Math.RandomDataGenerator#pick + * @since 3.0.0 + * + * @generic T + * @genericUse {T[]} - [array] + * @genericUse {T} - [$return] + * + * @param {T[]} array - The array to pick a random element from. + * + * @return {T} A random member of the array. + */ + pick: function (array) + { + return array[this.integerInRange(0, array.length - 1)]; + }, + + /** + * Returns a sign to be used with multiplication operator. + * + * @method Phaser.Math.RandomDataGenerator#sign + * @since 3.0.0 + * + * @return {number} -1 or +1. + */ + sign: function () + { + return this.pick(this.signs); + }, + + /** + * Returns a random element from within the given array, favoring the earlier entries. + * + * @method Phaser.Math.RandomDataGenerator#weightedPick + * @since 3.0.0 + * + * @generic T + * @genericUse {T[]} - [array] + * @genericUse {T} - [$return] + * + * @param {T[]} array - The array to pick a random element from. + * + * @return {T} A random member of the array. + */ + weightedPick: function (array) + { + return array[~~(Math.pow(this.frac(), 2) * (array.length - 0.5) + 0.5)]; + }, + + /** + * Returns a random timestamp between min and max, or between the beginning of 2000 and the end of 2020 if min and max aren't specified. + * + * @method Phaser.Math.RandomDataGenerator#timestamp + * @since 3.0.0 + * + * @param {number} min - The minimum value in the range. + * @param {number} max - The maximum value in the range. + * + * @return {number} A random timestamp between min and max. + */ + timestamp: function (min, max) + { + return this.realInRange(min || 946684800000, max || 1577862000000); + }, + + /** + * Returns a random angle between -180 and 180. + * + * @method Phaser.Math.RandomDataGenerator#angle + * @since 3.0.0 + * + * @return {number} A random number between -180 and 180. + */ + angle: function () + { + return this.integerInRange(-180, 180); + }, + + /** + * Returns a random rotation in radians, between -3.141 and 3.141 + * + * @method Phaser.Math.RandomDataGenerator#rotation + * @since 3.0.0 + * + * @return {number} A random number between -3.141 and 3.141 + */ + rotation: function () + { + return this.realInRange(-3.1415926, 3.1415926); + }, + + /** + * Gets or Sets the state of the generator. This allows you to retain the values + * that the generator is using between games, i.e. in a game save file. + * + * To seed this generator with a previously saved state you can pass it as the + * `seed` value in your game config, or call this method directly after Phaser has booted. + * + * Call this method with no parameters to return the current state. + * + * If providing a state it should match the same format that this method + * returns, which is a string with a header `!rnd` followed by the `c`, + * `s0`, `s1` and `s2` values respectively, each comma-delimited. + * + * @method Phaser.Math.RandomDataGenerator#state + * @since 3.0.0 + * + * @param {string} [state] - Generator state to be set. + * + * @return {string} The current state of the generator. + */ + state: function (state) + { + if (typeof state === 'string' && state.match(/^!rnd/)) + { + state = state.split(','); + + this.c = parseFloat(state[1]); + this.s0 = parseFloat(state[2]); + this.s1 = parseFloat(state[3]); + this.s2 = parseFloat(state[4]); + } + + return [ '!rnd', this.c, this.s0, this.s1, this.s2 ].join(','); + }, + + /** + * Shuffles the given array, using the current seed. + * + * @method Phaser.Math.RandomDataGenerator#shuffle + * @since 3.7.0 + * + * @generic T + * @genericUse {T[]} - [array,$return] + * + * @param {T[]} [array] - The array to be shuffled. + * + * @return {T[]} The shuffled array. + */ + shuffle: function (array) + { + var len = array.length - 1; + + for (var i = len; i > 0; i--) + { + var randomIndex = Math.floor(this.frac() * (i + 1)); + var itemAtIndex = array[randomIndex]; + + array[randomIndex] = array[i]; + array[i] = itemAtIndex; + } + + return array; + } + +}); + +module.exports = RandomDataGenerator; + + +/***/ }), + +/***/ 63448: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Snap a value to nearest grid slice, using ceil. + * + * Example: if you have an interval gap of `5` and a position of `12`... you will snap to `15`. + * As will `14` snap to `15`... but `16` will snap to `20`. + * + * @function Phaser.Math.Snap.Ceil + * @since 3.0.0 + * + * @param {number} value - The value to snap. + * @param {number} gap - The interval gap of the grid. + * @param {number} [start=0] - Optional starting offset for gap. + * @param {boolean} [divide=false] - If `true` it will divide the snapped value by the gap before returning. + * + * @return {number} The snapped value. + */ +var SnapCeil = function (value, gap, start, divide) +{ + if (start === undefined) { start = 0; } + + if (gap === 0) + { + return value; + } + + value -= start; + value = gap * Math.ceil(value / gap); + + return (divide) ? (start + value) / gap : start + value; +}; + +module.exports = SnapCeil; + + +/***/ }), + +/***/ 56583: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Snap a value to nearest grid slice, using floor. + * + * Example: if you have an interval gap of `5` and a position of `12`... you will snap to `10`. + * As will `14` snap to `10`... but `16` will snap to `15`. + * + * @function Phaser.Math.Snap.Floor + * @since 3.0.0 + * + * @param {number} value - The value to snap. + * @param {number} gap - The interval gap of the grid. + * @param {number} [start=0] - Optional starting offset for gap. + * @param {boolean} [divide=false] - If `true` it will divide the snapped value by the gap before returning. + * + * @return {number} The snapped value. + */ +var SnapFloor = function (value, gap, start, divide) +{ + if (start === undefined) { start = 0; } + + if (gap === 0) + { + return value; + } + + value -= start; + value = gap * Math.floor(value / gap); + + return (divide) ? (start + value) / gap : start + value; +}; + +module.exports = SnapFloor; + + +/***/ }), + +/***/ 77720: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Snap a value to nearest grid slice, using rounding. + * + * Example: if you have an interval gap of `5` and a position of `12`... you will snap to `10` whereas `14` will snap to `15`. + * + * @function Phaser.Math.Snap.To + * @since 3.0.0 + * + * @param {number} value - The value to snap. + * @param {number} gap - The interval gap of the grid. + * @param {number} [start=0] - Optional starting offset for gap. + * @param {boolean} [divide=false] - If `true` it will divide the snapped value by the gap before returning. + * + * @return {number} The snapped value. + */ +var SnapTo = function (value, gap, start, divide) +{ + if (start === undefined) { start = 0; } + + if (gap === 0) + { + return value; + } + + value -= start; + value = gap * Math.round(value / gap); + + return (divide) ? (start + value) / gap : start + value; +}; + +module.exports = SnapTo; + + +/***/ }), + +/***/ 73697: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Math.Snap + */ + +module.exports = { + + Ceil: __webpack_require__(63448), + Floor: __webpack_require__(56583), + To: __webpack_require__(77720) + +}; + + +/***/ }), + +/***/ 85454: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +__webpack_require__(63595); + +var CONST = __webpack_require__(8054); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser + */ + +var Phaser = { + + Actions: __webpack_require__(61061), + Animations: __webpack_require__(60421), + BlendModes: __webpack_require__(10312), + Cache: __webpack_require__(83388), + Cameras: __webpack_require__(26638), + Core: __webpack_require__(42857), + Class: __webpack_require__(83419), + Curves: __webpack_require__(25410), + Data: __webpack_require__(44965), + Display: __webpack_require__(27460), + DOM: __webpack_require__(84902), + Events: __webpack_require__(93055), + Filters: __webpack_require__(11889), + Game: __webpack_require__(50127), + GameObjects: __webpack_require__(77856), + Geom: __webpack_require__(55738), + Input: __webpack_require__(14350), + Loader: __webpack_require__(57777), + Math: __webpack_require__(75508), + Physics: __webpack_require__(44563), + Plugins: __webpack_require__(18922), + Renderer: __webpack_require__(36909), + Scale: __webpack_require__(93364), + ScaleModes: __webpack_require__(29795), + Scene: __webpack_require__(97482), + Scenes: __webpack_require__(62194), + Structs: __webpack_require__(41392), + Textures: __webpack_require__(27458), + Tilemaps: __webpack_require__(62501), + Time: __webpack_require__(90291), + Tweens: __webpack_require__(43066), + Utils: __webpack_require__(91799) + +}; + +// Merge in the optional plugins and WebGL only features + +if (true) +{ + Phaser.Sound = __webpack_require__(23717); +} + +// Merge in the consts + +Phaser = Extend(false, Phaser, CONST); + +/** + * The root types namespace. + * + * @namespace Phaser.Types + * @since 3.17.0 + */ + +// Export it + +module.exports = Phaser; + +__webpack_require__.g.Phaser = Phaser; + +/* + * "Documentation is like pizza: when it is good, it is very, very good; + * and when it is bad, it is better than nothing." + * -- Dick Brandon + */ + + +/***/ }), + +/***/ 71289: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(92209); +var Image = __webpack_require__(88571); + +/** + * @classdesc + * An Arcade Physics Image is an Image with an Arcade Physics body and related components. + * The body can be dynamic or static. + * + * The main difference between an Arcade Image and an Arcade Sprite is that you cannot animate an Arcade Image. + * + * @class Image + * @extends Phaser.GameObjects.Image + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Arcade.Components.Acceleration + * @extends Phaser.Physics.Arcade.Components.Angular + * @extends Phaser.Physics.Arcade.Components.Bounce + * @extends Phaser.Physics.Arcade.Components.Collision + * @extends Phaser.Physics.Arcade.Components.Debug + * @extends Phaser.Physics.Arcade.Components.Drag + * @extends Phaser.Physics.Arcade.Components.Enable + * @extends Phaser.Physics.Arcade.Components.Friction + * @extends Phaser.Physics.Arcade.Components.Gravity + * @extends Phaser.Physics.Arcade.Components.Immovable + * @extends Phaser.Physics.Arcade.Components.Mass + * @extends Phaser.Physics.Arcade.Components.Pushable + * @extends Phaser.Physics.Arcade.Components.Size + * @extends Phaser.Physics.Arcade.Components.Velocity + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + */ +var ArcadeImage = new Class({ + + Extends: Image, + + Mixins: [ + Components.Acceleration, + Components.Angular, + Components.Bounce, + Components.Collision, + Components.Debug, + Components.Drag, + Components.Enable, + Components.Friction, + Components.Gravity, + Components.Immovable, + Components.Mass, + Components.Pushable, + Components.Size, + Components.Velocity + ], + + initialize: + + function ArcadeImage (scene, x, y, texture, frame) + { + Image.call(this, scene, x, y, texture, frame); + + /** + * This Game Object's Physics Body. + * + * @name Phaser.Physics.Arcade.Image#body + * @type {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)} + * @default null + * @since 3.0.0 + */ + this.body = null; + } + +}); + +module.exports = ArcadeImage; + + +/***/ }), + +/***/ 86689: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var DegToRad = __webpack_require__(39506); +var DistanceBetween = __webpack_require__(20339); +var DistanceSquared = __webpack_require__(89774); +var Factory = __webpack_require__(66022); +var GetFastValue = __webpack_require__(95540); +var Merge = __webpack_require__(46975); +var OverlapCirc = __webpack_require__(72441); +var OverlapRect = __webpack_require__(47956); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); +var Vector2 = __webpack_require__(26099); +var World = __webpack_require__(82248); + +/** + * @classdesc + * The Arcade Physics Plugin belongs to a Scene and sets up and manages the Scene's physics simulation. + * It also holds some useful methods for moving and rotating Arcade Physics Bodies. + * + * You can access it from within a Scene using `this.physics`. + * + * Arcade Physics uses the Projection Method of collision resolution and separation. While it's fast and suitable + * for 'arcade' style games it lacks stability when multiple objects are in close proximity or resting upon each other. + * The separation that stops two objects penetrating may create a new penetration against a different object. If you + * require a high level of stability please consider using an alternative physics system, such as Matter.js. + * + * @class ArcadePhysics + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that this Plugin belongs to. + */ +var ArcadePhysics = new Class({ + + initialize: + + function ArcadePhysics (scene) + { + /** + * The Scene that this Plugin belongs to. + * + * @name Phaser.Physics.Arcade.ArcadePhysics#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The Scene's Systems. + * + * @name Phaser.Physics.Arcade.ArcadePhysics#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * A configuration object. Union of the `physics.arcade.*` properties of the GameConfig and SceneConfig objects. + * + * @name Phaser.Physics.Arcade.ArcadePhysics#config + * @type {Phaser.Types.Physics.Arcade.ArcadeWorldConfig} + * @since 3.0.0 + */ + this.config = this.getConfig(); + + /** + * The physics simulation. + * + * @name Phaser.Physics.Arcade.ArcadePhysics#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world; + + /** + * An object holding the Arcade Physics factory methods. + * + * @name Phaser.Physics.Arcade.ArcadePhysics#add + * @type {Phaser.Physics.Arcade.Factory} + * @since 3.0.0 + */ + this.add; + + /** + * Holds the internal collision filter category. + * + * @name Phaser.Physics.Arcade.World#_category + * @private + * @type {number} + * @since 3.70.0 + */ + this._category = 0x0001; + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.world = new World(this.scene, this.config); + this.add = new Factory(this.world); + + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#start + * @private + * @since 3.5.0 + */ + start: function () + { + if (!this.world) + { + this.world = new World(this.scene, this.config); + this.add = new Factory(this.world); + } + + var eventEmitter = this.systems.events; + + if (!GetFastValue(this.config, 'customUpdate', false)) + { + eventEmitter.on(SceneEvents.UPDATE, this.world.update, this.world); + } + + eventEmitter.on(SceneEvents.POST_UPDATE, this.world.postUpdate, this.world); + eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Causes `World.update` to be automatically called each time the Scene + * emits and `UPDATE` event. This is the default setting, so only needs + * calling if you have specifically disabled it. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#enableUpdate + * @since 3.50.0 + */ + enableUpdate: function () + { + this.systems.events.on(SceneEvents.UPDATE, this.world.update, this.world); + }, + + /** + * Causes `World.update` to **not** be automatically called each time the Scene + * emits and `UPDATE` event. + * + * If you wish to run the World update at your own rate, or from your own + * component, then you should call this method to disable the built-in link, + * and then call `World.update(time, delta)` accordingly. + * + * Note that `World.postUpdate` is always automatically called when the Scene + * emits a `POST_UPDATE` event, regardless of this setting. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#disableUpdate + * @since 3.50.0 + */ + disableUpdate: function () + { + this.systems.events.off(SceneEvents.UPDATE, this.world.update, this.world); + }, + + /** + * Creates the physics configuration for the current Scene. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#getConfig + * @since 3.0.0 + * + * @return {Phaser.Types.Physics.Arcade.ArcadeWorldConfig} The physics configuration. + */ + getConfig: function () + { + var gameConfig = this.systems.game.config.physics; + var sceneConfig = this.systems.settings.physics; + + var config = Merge( + GetFastValue(sceneConfig, 'arcade', {}), + GetFastValue(gameConfig, 'arcade', {}) + ); + + return config; + }, + + /** + * Returns the next available collision category. + * + * You can have a maximum of 32 categories. + * + * By default all bodies collide with all other bodies. + * + * Use the `Body.setCollisionCategory()` and + * `Body.setCollidesWith()` methods to change this. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#nextCategory + * @since 3.70.0 + * + * @return {number} The next collision category. + */ + nextCategory: function () + { + this._category = this._category << 1; + + return this._category; + }, + + /** + * Tests if Game Objects overlap. See {@link Phaser.Physics.Arcade.World#overlap} + * + * @method Phaser.Physics.Arcade.ArcadePhysics#overlap + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object or array of objects to check. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} [object2] - The second object or array of objects to check, or `undefined`. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [overlapCallback] - An optional callback function that is called if the objects overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they overlap. If this is set then `overlapCallback` will only be called if this callback returns `true`. + * @param {*} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if at least one Game Object overlaps another. + * + * @see Phaser.Physics.Arcade.World#overlap + */ + overlap: function (object1, object2, overlapCallback, processCallback, callbackContext) + { + if (overlapCallback === undefined) { overlapCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = overlapCallback; } + + return this.world.collideObjects(object1, object2, overlapCallback, processCallback, callbackContext, true); + }, + + /** + * Performs a collision check and separation between the two physics enabled objects given, which can be single + * Game Objects, arrays of Game Objects, Physics Groups, arrays of Physics Groups or normal Groups. + * + * If you don't require separation then use {@link #overlap} instead. + * + * If two Groups or arrays are passed, each member of one will be tested against each member of the other. + * + * If **only** one Group is passed (as `object1`), each member of the Group will be collided against the other members. + * + * If **only** one Array is passed, the array is iterated and every element in it is tested against the others. + * + * Two callbacks can be provided. The `collideCallback` is invoked if a collision occurs and the two colliding + * objects are passed to it. + * + * Arcade Physics uses the Projection Method of collision resolution and separation. While it's fast and suitable + * for 'arcade' style games it lacks stability when multiple objects are in close proximity or resting upon each other. + * The separation that stops two objects penetrating may create a new penetration against a different object. If you + * require a high level of stability please consider using an alternative physics system, such as Matter.js. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#collide + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object or array of objects to check. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} [object2] - The second object or array of objects to check, or `undefined`. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {*} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if any overlapping Game Objects were separated, otherwise false. + * + * @see Phaser.Physics.Arcade.World#collide + */ + collide: function (object1, object2, collideCallback, processCallback, callbackContext) + { + if (collideCallback === undefined) { collideCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = collideCallback; } + + return this.world.collideObjects(object1, object2, collideCallback, processCallback, callbackContext, false); + }, + + /** + * This advanced method is specifically for testing for collision between a single Sprite and an array of Tile objects. + * + * You should generally use the `collide` method instead, with a Sprite vs. a Tilemap Layer, as that will perform + * tile filtering and culling for you, as well as handle the interesting face collision automatically. + * + * This method is offered for those who would like to check for collision with specific Tiles in a layer, without + * having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic collisions + * on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method, + * you should filter them before passing them to this method. + * + * Important: Use of this method skips the `interesting faces` system that Tilemap Layers use. This means if you have + * say a row or column of tiles, and you jump into, or walk over them, it's possible to get stuck on the edges of the + * tiles as the interesting face calculations are skipped. However, for quick-fire small collision set tests on + * dynamic maps, this method can prove very useful. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#collideTiles + * @fires Phaser.Physics.Arcade.Events#TILE_COLLIDE + * @since 3.17.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.Tilemaps.Tile[]} tiles - An array of Tiles to check for collision against. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideTiles: function (sprite, tiles, collideCallback, processCallback, callbackContext) + { + return this.world.collideTiles(sprite, tiles, collideCallback, processCallback, callbackContext); + }, + + /** + * This advanced method is specifically for testing for overlaps between a single Sprite and an array of Tile objects. + * + * You should generally use the `overlap` method instead, with a Sprite vs. a Tilemap Layer, as that will perform + * tile filtering and culling for you, as well as handle the interesting face collision automatically. + * + * This method is offered for those who would like to check for overlaps with specific Tiles in a layer, without + * having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic overlap + * tests on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method, + * you should filter them before passing them to this method. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#overlapTiles + * @fires Phaser.Physics.Arcade.Events#TILE_OVERLAP + * @since 3.17.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.Tilemaps.Tile[]} tiles - An array of Tiles to check for collision against. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [overlapCallback] - An optional callback function that is called if the objects overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `overlapCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + overlapTiles: function (sprite, tiles, overlapCallback, processCallback, callbackContext) + { + return this.world.overlapTiles(sprite, tiles, overlapCallback, processCallback, callbackContext); + }, + + /** + * Pauses the simulation. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#pause + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.World} The simulation. + */ + pause: function () + { + return this.world.pause(); + }, + + /** + * Resumes the simulation (if paused). + * + * @method Phaser.Physics.Arcade.ArcadePhysics#resume + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.World} The simulation. + */ + resume: function () + { + return this.world.resume(); + }, + + /** + * Sets the acceleration.x/y property on the game object so it will move towards the x/y coordinates at the given rate (in pixels per second squared) + * + * You must give a maximum speed value, beyond which the game object won't go any faster. + * + * Note: The game object does not continuously track the target. If the target changes location during transit the game object will not modify its course. + * Note: The game object doesn't stop moving once it reaches the destination coordinates. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#accelerateTo + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - Any Game Object with an Arcade Physics body. + * @param {number} x - The x coordinate to accelerate towards. + * @param {number} y - The y coordinate to accelerate towards. + * @param {number} [speed=60] - The acceleration (change in speed) in pixels per second squared. + * @param {number} [xSpeedMax=500] - The maximum x velocity the game object can reach. + * @param {number} [ySpeedMax=500] - The maximum y velocity the game object can reach. + * + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. + */ + accelerateTo: function (gameObject, x, y, speed, xSpeedMax, ySpeedMax) + { + if (speed === undefined) { speed = 60; } + + var angle = Math.atan2(y - gameObject.y, x - gameObject.x); + + gameObject.body.acceleration.setToPolar(angle, speed); + + if (xSpeedMax !== undefined && ySpeedMax !== undefined) + { + gameObject.body.maxVelocity.set(xSpeedMax, ySpeedMax); + } + + return angle; + }, + + /** + * Sets the acceleration.x/y property on the game object so it will move towards the x/y coordinates at the given rate (in pixels per second squared) + * + * You must give a maximum speed value, beyond which the game object won't go any faster. + * + * Note: The game object does not continuously track the target. If the target changes location during transit the game object will not modify its course. + * Note: The game object doesn't stop moving once it reaches the destination coordinates. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#accelerateToObject + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - Any Game Object with an Arcade Physics body. + * @param {Phaser.GameObjects.GameObject} destination - The Game Object to move towards. Can be any object but must have visible x/y properties. + * @param {number} [speed=60] - The acceleration (change in speed) in pixels per second squared. + * @param {number} [xSpeedMax=500] - The maximum x velocity the game object can reach. + * @param {number} [ySpeedMax=500] - The maximum y velocity the game object can reach. + * + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. + */ + accelerateToObject: function (gameObject, destination, speed, xSpeedMax, ySpeedMax) + { + return this.accelerateTo(gameObject, destination.x, destination.y, speed, xSpeedMax, ySpeedMax); + }, + + /** + * Finds the Body or Game Object closest to a source point or object. + * + * If a `targets` argument is passed, this method finds the closest of those. + * The targets can be Arcade Physics Game Objects, Dynamic Bodies, or Static Bodies. + * + * If no `targets` argument is passed, this method finds the closest Dynamic Body. + * + * If two or more targets are the exact same distance from the source point, only the first target + * is returned. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#closest + * @since 3.0.0 + * + * @generic {Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|Phaser.GameObjects.GameObject} Target + * @param {Phaser.Types.Math.Vector2Like} source - Any object with public `x` and `y` properties, such as a Game Object or Geometry object. + * @param {Target[]} [targets] - The targets. + * + * @return {Target|null} The target closest to the given source point. + */ + closest: function (source, targets) + { + if (!targets) + { + targets = this.world.bodies.entries; + } + + var min = Number.MAX_VALUE; + var closest = null; + var x = source.x; + var y = source.y; + var len = targets.length; + + for (var i = 0; i < len; i++) + { + var target = targets[i]; + var body = target.body || target; + + if (source === target || source === body || source === body.gameObject || source === body.center) + { + continue; + } + + var distance = DistanceSquared(x, y, body.center.x, body.center.y); + + if (distance < min) + { + closest = target; + min = distance; + } + } + + return closest; + }, + + /** + * Finds the Body or Game Object farthest from a source point or object. + * + * If a `targets` argument is passed, this method finds the farthest of those. + * The targets can be Arcade Physics Game Objects, Dynamic Bodies, or Static Bodies. + * + * If no `targets` argument is passed, this method finds the farthest Dynamic Body. + * + * If two or more targets are the exact same distance from the source point, only the first target + * is returned. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#furthest + * @since 3.0.0 + * + * @param {any} source - Any object with public `x` and `y` properties, such as a Game Object or Geometry object. + * @param {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[]|Phaser.GameObjects.GameObject[])} [targets] - The targets. + * + * @return {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|Phaser.GameObjects.GameObject)} The target farthest from the given source point. + */ + furthest: function (source, targets) + { + if (!targets) + { + targets = this.world.bodies.entries; + } + + var max = -1; + var farthest = null; + var x = source.x; + var y = source.y; + var len = targets.length; + + for (var i = 0; i < len; i++) + { + var target = targets[i]; + var body = target.body || target; + + if (source === target || source === body || source === body.gameObject || source === body.center) + { + continue; + } + + var distance = DistanceSquared(x, y, body.center.x, body.center.y); + + if (distance > max) + { + farthest = target; + max = distance; + } + + } + + return farthest; + }, + + /** + * Move the given display object towards the x/y coordinates at a steady velocity. + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds. + * Timings are approximate due to the way browser timers work. Allow for a variance of +- 50ms. + * Note: The display object does not continuously track the target. If the target changes location during transit the display object will not modify its course. + * Note: The display object doesn't stop moving once it reaches the destination coordinates. + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you've set drag or acceleration too high this object may not move at all) + * + * @method Phaser.Physics.Arcade.ArcadePhysics#moveTo + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - Any Game Object with an Arcade Physics body. + * @param {number} x - The x coordinate to move towards. + * @param {number} y - The y coordinate to move towards. + * @param {number} [speed=60] - The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} [maxTime=0] - Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the object will arrive at destination in the given number of ms. + * + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. + */ + moveTo: function (gameObject, x, y, speed, maxTime) + { + if (speed === undefined) { speed = 60; } + if (maxTime === undefined) { maxTime = 0; } + + var angle = Math.atan2(y - gameObject.y, x - gameObject.x); + + if (maxTime > 0) + { + // We know how many pixels we need to move, but how fast? + speed = DistanceBetween(gameObject.x, gameObject.y, x, y) / (maxTime / 1000); + } + + gameObject.body.velocity.setToPolar(angle, speed); + + return angle; + }, + + /** + * Move the given display object towards the destination object at a steady velocity. + * If you specify a maxTime then it will adjust the speed (overwriting what you set) so it arrives at the destination in that number of seconds. + * Timings are approximate due to the way browser timers work. Allow for a variance of +- 50ms. + * Note: The display object does not continuously track the target. If the target changes location during transit the display object will not modify its course. + * Note: The display object doesn't stop moving once it reaches the destination coordinates. + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you've set drag or acceleration too high this object may not move at all) + * + * @method Phaser.Physics.Arcade.ArcadePhysics#moveToObject + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - Any Game Object with an Arcade Physics body. + * @param {object} destination - Any object with public `x` and `y` properties, such as a Game Object or Geometry object. + * @param {number} [speed=60] - The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} [maxTime=0] - Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the object will arrive at destination in the given number of ms. + * + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. + */ + moveToObject: function (gameObject, destination, speed, maxTime) + { + return this.moveTo(gameObject, destination.x, destination.y, speed, maxTime); + }, + + /** + * Given the angle (in degrees) and speed calculate the velocity and return it as a vector, or set it to the given vector object. + * One way to use this is: velocityFromAngle(angle, 200, sprite.body.velocity) which will set the values directly to the sprite's velocity and not create a new vector object. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#velocityFromAngle + * @since 3.0.0 + * + * @param {number} angle - The angle in degrees calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * @param {number} [speed=60] - The speed it will move, in pixels per second squared. + * @param {Phaser.Math.Vector2} [vec2] - The Vector2 in which the x and y properties will be set to the calculated velocity. + * + * @return {Phaser.Math.Vector2} The Vector2 that stores the velocity. + */ + velocityFromAngle: function (angle, speed, vec2) + { + if (speed === undefined) { speed = 60; } + if (vec2 === undefined) { vec2 = new Vector2(); } + + return vec2.setToPolar(DegToRad(angle), speed); + }, + + /** + * Given the rotation (in radians) and speed calculate the velocity and return it as a vector, or set it to the given vector object. + * One way to use this is: velocityFromRotation(rotation, 200, sprite.body.velocity) which will set the values directly to the sprite's velocity and not create a new vector object. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#velocityFromRotation + * @since 3.0.0 + * + * @param {number} rotation - The angle in radians. + * @param {number} [speed=60] - The speed it will move, in pixels per second squared + * @param {Phaser.Math.Vector2} [vec2] - The Vector2 in which the x and y properties will be set to the calculated velocity. + * + * @return {Phaser.Math.Vector2} The Vector2 that stores the velocity. + */ + velocityFromRotation: function (rotation, speed, vec2) + { + if (speed === undefined) { speed = 60; } + if (vec2 === undefined) { vec2 = new Vector2(); } + + return vec2.setToPolar(rotation, speed); + }, + + /** + * This method will search the given rectangular area and return an array of all physics bodies that + * overlap with it. It can return either Dynamic, Static bodies or a mixture of both. + * + * A body only has to intersect with the search area to be considered, it doesn't have to be fully + * contained within it. + * + * If Arcade Physics is set to use the RTree (which it is by default) then the search for is extremely fast, + * otherwise the search is O(N) for Dynamic Bodies. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#overlapRect + * @since 3.17.0 + * + * @param {number} x - The top-left x coordinate of the area to search within. + * @param {number} y - The top-left y coordinate of the area to search within. + * @param {number} width - The width of the area to search within. + * @param {number} height - The height of the area to search within. + * @param {boolean} [includeDynamic=true] - Should the search include Dynamic Bodies? + * @param {boolean} [includeStatic=false] - Should the search include Static Bodies? + * + * @return {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[])} An array of bodies that overlap with the given area. + */ + overlapRect: function (x, y, width, height, includeDynamic, includeStatic) + { + return OverlapRect(this.world, x, y, width, height, includeDynamic, includeStatic); + }, + + /** + * This method will search the given circular area and return an array of all physics bodies that + * overlap with it. It can return either Dynamic, Static bodies or a mixture of both. + * + * A body only has to intersect with the search area to be considered, it doesn't have to be fully + * contained within it. + * + * If Arcade Physics is set to use the RTree (which it is by default) then the search is rather fast, + * otherwise the search is O(N) for Dynamic Bodies. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#overlapCirc + * @since 3.21.0 + * + * @param {number} x - The x coordinate of the center of the area to search within. + * @param {number} y - The y coordinate of the center of the area to search within. + * @param {number} radius - The radius of the area to search within. + * @param {boolean} [includeDynamic=true] - Should the search include Dynamic Bodies? + * @param {boolean} [includeStatic=false] - Should the search include Static Bodies? + * + * @return {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[])} An array of bodies that overlap with the given area. + */ + overlapCirc: function (x, y, radius, includeDynamic, includeStatic) + { + return OverlapCirc(this.world, x, y, radius, includeDynamic, includeStatic); + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + if (!this.world) + { + // Already destroyed + return; + } + + var eventEmitter = this.systems.events; + + eventEmitter.off(SceneEvents.UPDATE, this.world.update, this.world); + eventEmitter.off(SceneEvents.POST_UPDATE, this.world.postUpdate, this.world); + eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this); + + this.add.destroy(); + this.world.destroy(); + + this.add = null; + this.world = null; + this._category = 1; + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Physics.Arcade.ArcadePhysics#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.scene.sys.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + } + +}); + +PluginCache.register('ArcadePhysics', ArcadePhysics, 'arcadePhysics'); + +module.exports = ArcadePhysics; + + +/***/ }), + +/***/ 13759: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(92209); +var Sprite = __webpack_require__(68287); + +/** + * @classdesc + * An Arcade Physics Sprite is a Sprite with an Arcade Physics body and related components. + * The body can be dynamic or static. + * + * The main difference between an Arcade Sprite and an Arcade Image is that you cannot animate an Arcade Image. + * If you do not require animation then you can safely use Arcade Images instead of Arcade Sprites. + * + * @class Sprite + * @extends Phaser.GameObjects.Sprite + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Arcade.Components.Acceleration + * @extends Phaser.Physics.Arcade.Components.Angular + * @extends Phaser.Physics.Arcade.Components.Bounce + * @extends Phaser.Physics.Arcade.Components.Collision + * @extends Phaser.Physics.Arcade.Components.Debug + * @extends Phaser.Physics.Arcade.Components.Drag + * @extends Phaser.Physics.Arcade.Components.Enable + * @extends Phaser.Physics.Arcade.Components.Friction + * @extends Phaser.Physics.Arcade.Components.Gravity + * @extends Phaser.Physics.Arcade.Components.Immovable + * @extends Phaser.Physics.Arcade.Components.Mass + * @extends Phaser.Physics.Arcade.Components.Pushable + * @extends Phaser.Physics.Arcade.Components.Size + * @extends Phaser.Physics.Arcade.Components.Velocity + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + */ +var ArcadeSprite = new Class({ + + Extends: Sprite, + + Mixins: [ + Components.Acceleration, + Components.Angular, + Components.Bounce, + Components.Collision, + Components.Debug, + Components.Drag, + Components.Enable, + Components.Friction, + Components.Gravity, + Components.Immovable, + Components.Mass, + Components.Pushable, + Components.Size, + Components.Velocity + ], + + initialize: + + function ArcadeSprite (scene, x, y, texture, frame) + { + Sprite.call(this, scene, x, y, texture, frame); + + /** + * This Game Object's Physics Body. + * + * @name Phaser.Physics.Arcade.Sprite#body + * @type {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)} + * @default null + * @since 3.0.0 + */ + this.body = null; + } + +}); + +module.exports = ArcadeSprite; + + +/***/ }), + +/***/ 37742: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CollisionComponent = __webpack_require__(78389); +var CONST = __webpack_require__(37747); +var Events = __webpack_require__(63012); +var RadToDeg = __webpack_require__(43396); +var Rectangle = __webpack_require__(87841); +var RectangleContains = __webpack_require__(37303); +var SetCollisionObject = __webpack_require__(95829); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Dynamic Arcade Body. + * + * Its static counterpart is {@link Phaser.Physics.Arcade.StaticBody}. + * + * @class Body + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Arcade.Components.Collision + * + * @param {Phaser.Physics.Arcade.World} world - The Arcade Physics simulation this Body belongs to. + * @param {Phaser.GameObjects.GameObject} [gameObject] - The Game Object this Body belongs to. As of Phaser 3.60 this is now optional. + */ +var Body = new Class({ + + Mixins: [ + CollisionComponent + ], + + initialize: + + function Body (world, gameObject) + { + var width = 64; + var height = 64; + + var dummyGameObject = { + x: 0, + y: 0, + angle: 0, + rotation: 0, + scaleX: 1, + scaleY: 1, + displayOriginX: 0, + displayOriginY: 0 + }; + + var hasGameObject = (gameObject !== undefined); + + if (hasGameObject && gameObject.displayWidth) + { + width = gameObject.displayWidth; + height = gameObject.displayHeight; + } + + if (!hasGameObject) + { + gameObject = dummyGameObject; + } + + /** + * The Arcade Physics simulation this Body belongs to. + * + * @name Phaser.Physics.Arcade.Body#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The Game Object this Body belongs to. + * + * As of Phaser 3.60 this is now optional and can be undefined. + * + * @name Phaser.Physics.Arcade.Body#gameObject + * @type {Phaser.GameObjects.GameObject} + * @since 3.0.0 + */ + this.gameObject = (hasGameObject) ? gameObject : undefined; + + /** + * A quick-test flag that signifies this is a Body, used in the World collision handler. + * + * @name Phaser.Physics.Arcade.Body#isBody + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.isBody = true; + + /** + * Transformations applied to this Body. + * + * @name Phaser.Physics.Arcade.Body#transform + * @type {object} + * @since 3.4.0 + */ + this.transform = { + x: gameObject.x, + y: gameObject.y, + rotation: gameObject.angle, + scaleX: gameObject.scaleX, + scaleY: gameObject.scaleY, + displayOriginX: gameObject.displayOriginX, + displayOriginY: gameObject.displayOriginY + }; + + /** + * Whether the Body is drawn to the debug display. + * + * @name Phaser.Physics.Arcade.Body#debugShowBody + * @type {boolean} + * @since 3.0.0 + */ + this.debugShowBody = world.defaults.debugShowBody; + + /** + * Whether the Body's velocity is drawn to the debug display. + * + * @name Phaser.Physics.Arcade.Body#debugShowVelocity + * @type {boolean} + * @since 3.0.0 + */ + this.debugShowVelocity = world.defaults.debugShowVelocity; + + /** + * The color of this Body on the debug display. + * + * @name Phaser.Physics.Arcade.Body#debugBodyColor + * @type {number} + * @since 3.0.0 + */ + this.debugBodyColor = world.defaults.bodyDebugColor; + + /** + * Whether this Body is updated by the physics simulation. + * + * @name Phaser.Physics.Arcade.Body#enable + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.enable = true; + + /** + * Whether this Body is circular (true) or rectangular (false). + * + * @name Phaser.Physics.Arcade.Body#isCircle + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#setCircle + */ + this.isCircle = false; + + /** + * If this Body is circular, this is the unscaled radius of the Body, as set by setCircle(), in source pixels. + * The true radius is equal to `halfWidth`. + * + * @name Phaser.Physics.Arcade.Body#radius + * @type {number} + * @default 0 + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#setCircle + */ + this.radius = 0; + + /** + * The offset of this Body's position from its Game Object's position, in source pixels. + * + * @name Phaser.Physics.Arcade.Body#offset + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#setOffset + */ + this.offset = new Vector2(); + + /** + * The position of this Body within the simulation. + * + * @name Phaser.Physics.Arcade.Body#position + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.position = new Vector2( + gameObject.x - gameObject.scaleX * gameObject.displayOriginX, + gameObject.y - gameObject.scaleY * gameObject.displayOriginY + ); + + /** + * The position of this Body during the previous step. + * + * @name Phaser.Physics.Arcade.Body#prev + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.prev = this.position.clone(); + + /** + * The position of this Body during the previous frame. + * + * @name Phaser.Physics.Arcade.Body#prevFrame + * @type {Phaser.Math.Vector2} + * @since 3.20.0 + */ + this.prevFrame = this.position.clone(); + + /** + * Whether this Body's `rotation` is affected by its angular acceleration and angular velocity. + * + * @name Phaser.Physics.Arcade.Body#allowRotation + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.allowRotation = true; + + /** + * This body's rotation, in degrees, based on its angular acceleration and angular velocity. + * The Body's rotation controls the `angle` of its Game Object. + * It doesn't rotate the Body's own geometry, which is always an axis-aligned rectangle or a circle. + * + * @name Phaser.Physics.Arcade.Body#rotation + * @type {number} + * @since 3.0.0 + */ + this.rotation = gameObject.angle; + + /** + * The Body rotation, in degrees, during the previous step. + * + * @name Phaser.Physics.Arcade.Body#preRotation + * @type {number} + * @since 3.0.0 + */ + this.preRotation = gameObject.angle; + + /** + * The width of the Body, in pixels. + * If the Body is circular, this is also the diameter. + * If you wish to change the width use the `Body.setSize` method. + * + * @name Phaser.Physics.Arcade.Body#width + * @type {number} + * @readonly + * @default 64 + * @since 3.0.0 + */ + this.width = width; + + /** + * The height of the Body, in pixels. + * If the Body is circular, this is also the diameter. + * If you wish to change the height use the `Body.setSize` method. + * + * @name Phaser.Physics.Arcade.Body#height + * @type {number} + * @readonly + * @default 64 + * @since 3.0.0 + */ + this.height = height; + + /** + * The unscaled width of the Body, in source pixels, as set by setSize(). + * The default is the width of the Body's Game Object's texture frame. + * + * @name Phaser.Physics.Arcade.Body#sourceWidth + * @type {number} + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#setSize + */ + this.sourceWidth = width; + + /** + * The unscaled height of the Body, in source pixels, as set by setSize(). + * The default is the height of the Body's Game Object's texture frame. + * + * @name Phaser.Physics.Arcade.Body#sourceHeight + * @type {number} + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#setSize + */ + this.sourceHeight = height; + + if (gameObject.frame) + { + this.sourceWidth = gameObject.frame.realWidth; + this.sourceHeight = gameObject.frame.realHeight; + } + + /** + * Half the Body's width, in pixels. + * + * @name Phaser.Physics.Arcade.Body#halfWidth + * @type {number} + * @since 3.0.0 + */ + this.halfWidth = Math.abs(width / 2); + + /** + * Half the Body's height, in pixels. + * + * @name Phaser.Physics.Arcade.Body#halfHeight + * @type {number} + * @since 3.0.0 + */ + this.halfHeight = Math.abs(height / 2); + + /** + * The center of the Body. + * The midpoint of its `position` (top-left corner) and its bottom-right corner. + * + * @name Phaser.Physics.Arcade.Body#center + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.center = new Vector2(this.position.x + this.halfWidth, this.position.y + this.halfHeight); + + /** + * The Body's velocity, in pixels per second. + * + * @name Phaser.Physics.Arcade.Body#velocity + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.velocity = new Vector2(); + + /** + * The Body's change in position (due to velocity) at the last step, in pixels. + * + * The size of this value depends on the simulation's step rate. + * + * @name Phaser.Physics.Arcade.Body#newVelocity + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.0.0 + */ + this.newVelocity = new Vector2(); + + /** + * The Body's absolute maximum change in position, in pixels per step. + * + * @name Phaser.Physics.Arcade.Body#deltaMax + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.deltaMax = new Vector2(); + + /** + * The Body's change in velocity, in pixels per second squared. + * + * @name Phaser.Physics.Arcade.Body#acceleration + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.acceleration = new Vector2(); + + /** + * Whether this Body's velocity is affected by its `drag`. + * + * @name Phaser.Physics.Arcade.Body#allowDrag + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.allowDrag = true; + + /** + * When `useDamping` is false (the default), this is absolute loss of velocity due to movement, in pixels per second squared. + * + * When `useDamping` is true, this is a damping multiplier between 0 and 1. + * A value of 0 means the Body stops instantly. + * A value of 0.01 mean the Body keeps 1% of its velocity per second, losing 99%. + * A value of 0.1 means the Body keeps 10% of its velocity per second, losing 90%. + * A value of 1 means the Body loses no velocity. + * You can use very small values (e.g., 0.001) to stop the Body quickly. + * + * The x and y components are applied separately. + * + * Drag is applied only when `acceleration` is zero. + * + * @name Phaser.Physics.Arcade.Body#drag + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.drag = new Vector2(); + + /** + * Whether this Body's position is affected by gravity (local or world). + * + * @name Phaser.Physics.Arcade.Body#allowGravity + * @type {boolean} + * @default true + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#gravity + * @see Phaser.Physics.Arcade.World#gravity + */ + this.allowGravity = true; + + /** + * Acceleration due to gravity (specific to this Body), in pixels per second squared. + * Total gravity is the sum of this vector and the simulation's `gravity`. + * + * @name Phaser.Physics.Arcade.Body#gravity + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + * @see Phaser.Physics.Arcade.World#gravity + */ + this.gravity = new Vector2(); + + /** + * Rebound following a collision, relative to 1. + * + * @name Phaser.Physics.Arcade.Body#bounce + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.bounce = new Vector2(); + + /** + * Rebound following a collision with the world boundary, relative to 1. + * If null, `bounce` is used instead. + * + * @name Phaser.Physics.Arcade.Body#worldBounce + * @type {?Phaser.Math.Vector2} + * @default null + * @since 3.0.0 + */ + this.worldBounce = null; + + /** + * The rectangle used for world boundary collisions. + * + * By default it is set to the world boundary rectangle. Or, if this Body was + * created by a Physics Group, then whatever rectangle that Group defined. + * + * You can also change it by using the `Body.setBoundsRectangle` method. + * + * @name Phaser.Physics.Arcade.Body#customBoundsRectangle + * @type {Phaser.Geom.Rectangle} + * @since 3.20 + */ + this.customBoundsRectangle = world.bounds; + + /** + * Whether the simulation emits a `worldbounds` event when this Body collides with the world boundary + * (and `collideWorldBounds` is also true). + * + * @name Phaser.Physics.Arcade.Body#onWorldBounds + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.Physics.Arcade.World#WORLD_BOUNDS + */ + this.onWorldBounds = false; + + /** + * Whether the simulation emits a `collide` event when this Body collides with another. + * + * @name Phaser.Physics.Arcade.Body#onCollide + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.Physics.Arcade.World#COLLIDE + */ + this.onCollide = false; + + /** + * Whether the simulation emits an `overlap` event when this Body overlaps with another. + * + * @name Phaser.Physics.Arcade.Body#onOverlap + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.Physics.Arcade.World#OVERLAP + */ + this.onOverlap = false; + + /** + * The absolute maximum velocity of this body, in pixels per second. + * The horizontal and vertical components are applied separately. + * + * @name Phaser.Physics.Arcade.Body#maxVelocity + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.maxVelocity = new Vector2(10000, 10000); + + /** + * The maximum speed this Body is allowed to reach, in pixels per second. + * + * If not negative it limits the scalar value of speed. + * + * Any negative value means no maximum is being applied (the default). + * + * @name Phaser.Physics.Arcade.Body#maxSpeed + * @type {number} + * @default -1 + * @since 3.16.0 + */ + this.maxSpeed = -1; + + /** + * If this Body is `immovable` and in motion, `friction` is the proportion of this Body's motion received by the riding Body on each axis, relative to 1. + * The horizontal component (x) is applied only when two colliding Bodies are separated vertically. + * The vertical component (y) is applied only when two colliding Bodies are separated horizontally. + * The default value (1, 0) moves the riding Body horizontally in equal proportion to this Body and vertically not at all. + * + * @name Phaser.Physics.Arcade.Body#friction + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.friction = new Vector2(1, 0); + + /** + * If this Body is using `drag` for deceleration this property controls how the drag is applied. + * If set to `true` drag will use a damping effect rather than a linear approach. If you are + * creating a game where the Body moves freely at any angle (i.e. like the way the ship moves in + * the game Asteroids) then you will get a far smoother and more visually correct deceleration + * by using damping, avoiding the axis-drift that is prone with linear deceleration. + * + * If you enable this property then you should use far smaller `drag` values than with linear, as + * they are used as a multiplier on the velocity. Values such as 0.05 will give a nice slow + * deceleration. + * + * @name Phaser.Physics.Arcade.Body#useDamping + * @type {boolean} + * @default false + * @since 3.10.0 + */ + this.useDamping = false; + + /** + * The rate of change of this Body's `rotation`, in degrees per second. + * + * @name Phaser.Physics.Arcade.Body#angularVelocity + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.angularVelocity = 0; + + /** + * The Body's angular acceleration (change in angular velocity), in degrees per second squared. + * + * @name Phaser.Physics.Arcade.Body#angularAcceleration + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.angularAcceleration = 0; + + /** + * Loss of angular velocity due to angular movement, in degrees per second. + * + * Angular drag is applied only when angular acceleration is zero. + * + * @name Phaser.Physics.Arcade.Body#angularDrag + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.angularDrag = 0; + + /** + * The Body's maximum angular velocity, in degrees per second. + * + * @name Phaser.Physics.Arcade.Body#maxAngular + * @type {number} + * @default 1000 + * @since 3.0.0 + */ + this.maxAngular = 1000; + + /** + * The Body's inertia, relative to a default unit (1). + * With `bounce`, this affects the exchange of momentum (velocities) during collisions. + * + * @name Phaser.Physics.Arcade.Body#mass + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.mass = 1; + + /** + * The calculated angle of this Body's velocity vector, in radians, during the last step. + * + * @name Phaser.Physics.Arcade.Body#angle + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.angle = 0; + + /** + * The calculated magnitude of the Body's velocity, in pixels per second, during the last step. + * + * @name Phaser.Physics.Arcade.Body#speed + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.speed = 0; + + /** + * The direction of the Body's velocity, as calculated during the last step. + * This is a numeric constant value (FACING_UP, FACING_DOWN, FACING_LEFT, FACING_RIGHT). + * If the Body is moving on both axes, this describes motion on the vertical axis only. + * + * @name Phaser.Physics.Arcade.Body#facing + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.FACING_UP + * @see Phaser.Physics.Arcade.FACING_DOWN + * @see Phaser.Physics.Arcade.FACING_LEFT + * @see Phaser.Physics.Arcade.FACING_RIGHT + */ + this.facing = CONST.FACING_NONE; + + /** + * Whether this Body can be moved by collisions with another Body. + * + * @name Phaser.Physics.Arcade.Body#immovable + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.immovable = false; + + /** + * Sets if this Body can be pushed by another Body. + * + * A body that cannot be pushed will reflect back all of the velocity it is given to the + * colliding body. If that body is also not pushable, then the separation will be split + * between them evenly. + * + * If you want your body to never move or seperate at all, see the `setImmovable` method. + * + * By default, Dynamic Bodies are always pushable. + * + * @name Phaser.Physics.Arcade.Body#pushable + * @type {boolean} + * @default true + * @since 3.50.0 + * @see Phaser.GameObjects.Components.Pushable#setPushable + */ + this.pushable = true; + + /** + * The Slide Factor of this Body. + * + * The Slide Factor controls how much velocity is preserved when + * this Body is pushed by another Body. + * + * The default value is 1, which means that it will take on all + * velocity given in the push. You can adjust this value to control + * how much velocity is retained by this Body when the push ends. + * + * A value of 0, for example, will allow this Body to be pushed + * but then remain completely still after the push ends, such as + * you see in a game like Sokoban. + * + * Or you can set a mid-point, such as 0.25 which will allow it + * to keep 25% of the original velocity when the push ends. You + * can combine this with the `setDrag()` method to create deceleration. + * + * @name Phaser.Physics.Arcade.Body#slideFactor + * @type {Phaser.Math.Vector2} + * @since 3.70.0 + * @see Phaser.GameObjects.Components.Pushable#setSlideFactor + */ + this.slideFactor = new Vector2(1, 1); + + /** + * Whether the Body's position and rotation are affected by its velocity, acceleration, drag, and gravity. + * + * @name Phaser.Physics.Arcade.Body#moves + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.moves = true; + + /** + * A flag disabling the default horizontal separation of colliding bodies. + * Pass your own `collideCallback` to the collider. + * + * @name Phaser.Physics.Arcade.Body#customSeparateX + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.customSeparateX = false; + + /** + * A flag disabling the default vertical separation of colliding bodies. + * Pass your own `collideCallback` to the collider. + * + * @name Phaser.Physics.Arcade.Body#customSeparateY + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.customSeparateY = false; + + /** + * The amount of horizontal overlap (before separation), if this Body is colliding with another. + * + * @name Phaser.Physics.Arcade.Body#overlapX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.overlapX = 0; + + /** + * The amount of vertical overlap (before separation), if this Body is colliding with another. + * + * @name Phaser.Physics.Arcade.Body#overlapY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.overlapY = 0; + + /** + * The amount of overlap (before separation), if this Body is circular and colliding with another circular body. + * + * @name Phaser.Physics.Arcade.Body#overlapR + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.overlapR = 0; + + /** + * Whether this Body is overlapped with another and both are not moving, on at least one axis. + * + * @name Phaser.Physics.Arcade.Body#embedded + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.embedded = false; + + /** + * Whether this Body interacts with the world boundary. + * + * @name Phaser.Physics.Arcade.Body#collideWorldBounds + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.collideWorldBounds = false; + + /** + * Whether this Body is checked for collisions and for which directions. + * You can set `checkCollision.none = true` to disable collision checks. + * + * @name Phaser.Physics.Arcade.Body#checkCollision + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + */ + this.checkCollision = SetCollisionObject(false); + + /** + * Whether this Body is colliding with a Body or Static Body and in which direction. + * In a collision where both bodies have zero velocity, `embedded` will be set instead. + * + * @name Phaser.Physics.Arcade.Body#touching + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#blocked + * @see Phaser.Physics.Arcade.Body#embedded + */ + this.touching = SetCollisionObject(true); + + /** + * This Body's `touching` value during the previous step. + * + * @name Phaser.Physics.Arcade.Body#wasTouching + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#touching + */ + this.wasTouching = SetCollisionObject(true); + + /** + * Whether this Body is colliding with a Static Body, a tile, or the world boundary. + * In a collision with a Static Body, if this Body has zero velocity then `embedded` will be set instead. + * + * @name Phaser.Physics.Arcade.Body#blocked + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#embedded + * @see Phaser.Physics.Arcade.Body#touching + */ + this.blocked = SetCollisionObject(true); + + /** + * Whether to automatically synchronize this Body's dimensions to the dimensions of its Game Object's visual bounds. + * + * @name Phaser.Physics.Arcade.Body#syncBounds + * @type {boolean} + * @default false + * @since 3.0.0 + * @see Phaser.GameObjects.Components.GetBounds#getBounds + */ + this.syncBounds = false; + + /** + * The Body's physics type (dynamic or static). + * + * @name Phaser.Physics.Arcade.Body#physicsType + * @type {number} + * @readonly + * @default Phaser.Physics.Arcade.DYNAMIC_BODY + * @since 3.0.0 + */ + this.physicsType = CONST.DYNAMIC_BODY; + + /** + * The Arcade Physics Body Collision Category. + * + * This can be set to any valid collision bitfield value. + * + * See the `setCollisionCategory` method for more details. + * + * @name Phaser.Physics.Arcade.Body#collisionCategory + * @type {number} + * @since 3.70.0 + */ + this.collisionCategory = 0x0001; + + /** + * The Arcade Physics Body Collision Mask. + * + * See the `setCollidesWith` method for more details. + * + * @name Phaser.Physics.Arcade.Body#collisionMask + * @type {number} + * @since 3.70.0 + */ + this.collisionMask = 1; + + /** + * Cached horizontal scale of the Body's Game Object. + * + * @name Phaser.Physics.Arcade.Body#_sx + * @type {number} + * @private + * @since 3.0.0 + */ + this._sx = gameObject.scaleX; + + /** + * Cached vertical scale of the Body's Game Object. + * + * @name Phaser.Physics.Arcade.Body#_sy + * @type {number} + * @private + * @since 3.0.0 + */ + this._sy = gameObject.scaleY; + + /** + * The calculated change in the Body's horizontal position during the last step. + * + * @name Phaser.Physics.Arcade.Body#_dx + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._dx = 0; + + /** + * The calculated change in the Body's vertical position during the last step. + * + * @name Phaser.Physics.Arcade.Body#_dy + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._dy = 0; + + /** + * The final calculated change in the Body's horizontal position as of `postUpdate`. + * + * @name Phaser.Physics.Arcade.Body#_tx + * @type {number} + * @private + * @default 0 + * @since 3.22.0 + */ + this._tx = 0; + + /** + * The final calculated change in the Body's vertical position as of `postUpdate`. + * + * @name Phaser.Physics.Arcade.Body#_ty + * @type {number} + * @private + * @default 0 + * @since 3.22.0 + */ + this._ty = 0; + + /** + * Stores the Game Object's bounds. + * + * @name Phaser.Physics.Arcade.Body#_bounds + * @type {Phaser.Geom.Rectangle} + * @private + * @since 3.0.0 + */ + this._bounds = new Rectangle(); + + /** + * Is this Body under direct control, outside of the physics engine? For example, + * are you trying to move it via a Tween? Or have it follow a path? If so then + * you can enable this boolean so that the Body will calculate its velocity based + * purely on its change in position each frame. This allows you to then tween + * the position and still have it collide with other objects. However, setting + * the velocity will have no impact on this Body while this is set. + * + * @name Phaser.Physics.Arcade.Body#directControl + * @type {boolean} + * @since 3.70.0 + */ + this.directControl = false; + + /** + * Stores the previous position of the Game Object when directControl is enabled. + * + * @name Phaser.Physics.Arcade.Body#autoFrame + * @type {Phaser.Math.Vector2} + * @private + * @since 3.70.0 + */ + this.autoFrame = this.position.clone(); + }, + + /** + * Updates the Body's `transform`, `width`, `height`, and `center` from its Game Object. + * The Body's `position` isn't changed. + * + * @method Phaser.Physics.Arcade.Body#updateBounds + * @since 3.0.0 + */ + updateBounds: function () + { + var sprite = this.gameObject; + + // Container? + + var transform = this.transform; + + if (sprite.parentContainer) + { + var matrix = sprite.getWorldTransformMatrix(this.world._tempMatrix, this.world._tempMatrix2); + + transform.x = matrix.tx; + transform.y = matrix.ty; + transform.rotation = RadToDeg(matrix.rotation); + transform.scaleX = matrix.scaleX; + transform.scaleY = matrix.scaleY; + transform.displayOriginX = sprite.displayOriginX; + transform.displayOriginY = sprite.displayOriginY; + } + else + { + transform.x = sprite.x; + transform.y = sprite.y; + transform.rotation = sprite.angle; + transform.scaleX = sprite.scaleX; + transform.scaleY = sprite.scaleY; + transform.displayOriginX = sprite.displayOriginX; + transform.displayOriginY = sprite.displayOriginY; + } + + var recalc = false; + + if (this.syncBounds) + { + var b = sprite.getBounds(this._bounds); + + this.width = b.width; + this.height = b.height; + recalc = true; + } + else + { + var asx = Math.abs(transform.scaleX); + var asy = Math.abs(transform.scaleY); + + if (this._sx !== asx || this._sy !== asy) + { + this.width = this.sourceWidth * asx; + this.height = this.sourceHeight * asy; + this._sx = asx; + this._sy = asy; + recalc = true; + } + } + + if (recalc) + { + this.halfWidth = Math.floor(this.width / 2); + this.halfHeight = Math.floor(this.height / 2); + this.updateCenter(); + } + }, + + /** + * Updates the Body's `center` from its `position`, `width`, and `height`. + * + * @method Phaser.Physics.Arcade.Body#updateCenter + * @since 3.0.0 + */ + updateCenter: function () + { + this.center.set(this.position.x + this.halfWidth, this.position.y + this.halfHeight); + }, + + /** + * Updates the Body's `position`, `width`, `height`, and `center` from its Game Object and `offset`. + * + * You don't need to call this for Dynamic Bodies, as it happens automatically during the physics step. + * But you could use it if you have modified the Body offset or Game Object transform and need to immediately + * read the Body's new `position` or `center`. + * + * To resynchronize the Body with its Game Object, use `reset()` instead. + * + * @method Phaser.Physics.Arcade.Body#updateFromGameObject + * @since 3.24.0 + */ + updateFromGameObject: function () + { + this.updateBounds(); + + var transform = this.transform; + + this.position.x = transform.x + transform.scaleX * (this.offset.x - transform.displayOriginX); + this.position.y = transform.y + transform.scaleY * (this.offset.y - transform.displayOriginY); + + this.updateCenter(); + }, + + /** + * Prepares the Body for a physics step by resetting the `wasTouching`, `touching` and `blocked` states. + * + * This method is only called if the physics world is going to run a step this frame. + * + * @method Phaser.Physics.Arcade.Body#resetFlags + * @since 3.18.0 + * + * @param {boolean} [clear=false] - Set the `wasTouching` values to their defaults. + */ + resetFlags: function (clear) + { + if (clear === undefined) + { + clear = false; + } + + // Store and reset collision flags + var wasTouching = this.wasTouching; + var touching = this.touching; + var blocked = this.blocked; + + if (clear) + { + SetCollisionObject(true, wasTouching); + } + else + { + wasTouching.none = touching.none; + wasTouching.up = touching.up; + wasTouching.down = touching.down; + wasTouching.left = touching.left; + wasTouching.right = touching.right; + } + + SetCollisionObject(true, touching); + SetCollisionObject(true, blocked); + + this.overlapR = 0; + this.overlapX = 0; + this.overlapY = 0; + + this.embedded = false; + }, + + /** + * Syncs the position body position with the parent Game Object. + * + * This method is called every game frame, regardless if the world steps or not. + * + * @method Phaser.Physics.Arcade.Body#preUpdate + * @since 3.17.0 + * + * @param {boolean} willStep - Will this Body run an update as well? + * @param {number} delta - The delta time, in seconds, elapsed since the last frame. + */ + preUpdate: function (willStep, delta) + { + if (willStep) + { + this.resetFlags(); + } + + if (this.gameObject) + { + this.updateFromGameObject(); + } + + this.rotation = this.transform.rotation; + this.preRotation = this.rotation; + + if (this.moves) + { + var pos = this.position; + + this.prev.x = pos.x; + this.prev.y = pos.y; + + this.prevFrame.x = pos.x; + this.prevFrame.y = pos.y; + } + + if (willStep) + { + this.update(delta); + } + }, + + /** + * Performs a single physics step and updates the body velocity, angle, speed and other properties. + * + * This method can be called multiple times per game frame, depending on the physics step rate. + * + * The results are synced back to the Game Object in `postUpdate`. + * + * @method Phaser.Physics.Arcade.Body#update + * @fires Phaser.Physics.Arcade.Events#WORLD_BOUNDS + * @since 3.0.0 + * + * @param {number} delta - The delta time, in seconds, elapsed since the last frame. + */ + update: function (delta) + { + var prev = this.prev; + var pos = this.position; + var vel = this.velocity; + + prev.set(pos.x, pos.y); + + if (!this.moves) + { + this._dx = pos.x - prev.x; + this._dy = pos.y - prev.y; + + return; + } + + if (this.directControl) + { + var autoFrame = this.autoFrame; + + vel.set( + (pos.x - autoFrame.x) / delta, + (pos.y - autoFrame.y) / delta + ); + + this.world.updateMotion(this, delta); + + this._dx = pos.x - autoFrame.x; + this._dy = pos.y - autoFrame.y; + } + else + { + this.world.updateMotion(this, delta); + + this.newVelocity.set(vel.x * delta, vel.y * delta); + + pos.add(this.newVelocity); + + this._dx = pos.x - prev.x; + this._dy = pos.y - prev.y; + } + + var vx = vel.x; + var vy = vel.y; + + this.updateCenter(); + + this.angle = Math.atan2(vy, vx); + this.speed = Math.sqrt(vx * vx + vy * vy); + + // Now the update will throw collision checks at the Body + // And finally we'll integrate the new position back to the Sprite in postUpdate + + if (this.collideWorldBounds && this.checkWorldBounds() && this.onWorldBounds) + { + var blocked = this.blocked; + + this.world.emit(Events.WORLD_BOUNDS, this, blocked.up, blocked.down, blocked.left, blocked.right); + } + }, + + /** + * Feeds the Body results back into the parent Game Object. + * + * This method is called every game frame, regardless if the world steps or not. + * + * @method Phaser.Physics.Arcade.Body#postUpdate + * @since 3.0.0 + */ + postUpdate: function () + { + var pos = this.position; + + var dx = pos.x - this.prevFrame.x; + var dy = pos.y - this.prevFrame.y; + + var gameObject = this.gameObject; + + if (this.moves) + { + var mx = this.deltaMax.x; + var my = this.deltaMax.y; + + if (mx !== 0 && dx !== 0) + { + if (dx < 0 && dx < -mx) + { + dx = -mx; + } + else if (dx > 0 && dx > mx) + { + dx = mx; + } + } + + if (my !== 0 && dy !== 0) + { + if (dy < 0 && dy < -my) + { + dy = -my; + } + else if (dy > 0 && dy > my) + { + dy = my; + } + } + + if (gameObject) + { + gameObject.x += dx; + gameObject.y += dy; + } + } + + if (dx < 0) + { + this.facing = CONST.FACING_LEFT; + } + else if (dx > 0) + { + this.facing = CONST.FACING_RIGHT; + } + + if (dy < 0) + { + this.facing = CONST.FACING_UP; + } + else if (dy > 0) + { + this.facing = CONST.FACING_DOWN; + } + + if (this.allowRotation && gameObject) + { + gameObject.angle += this.deltaZ(); + } + + this._tx = dx; + this._ty = dy; + + this.autoFrame.set(pos.x, pos.y); + }, + + /** + * Sets a custom collision boundary rectangle. Use if you want to have a custom + * boundary instead of the world boundaries. + * + * @method Phaser.Physics.Arcade.Body#setBoundsRectangle + * @since 3.20 + * + * @param {?Phaser.Geom.Rectangle} [bounds] - The new boundary rectangle. Pass `null` to use the World bounds. + * + * @return {this} This Body object. + */ + setBoundsRectangle: function (bounds) + { + this.customBoundsRectangle = (!bounds) ? this.world.bounds : bounds; + + return this; + }, + + /** + * Checks for collisions between this Body and the world boundary and separates them. + * + * @method Phaser.Physics.Arcade.Body#checkWorldBounds + * @since 3.0.0 + * + * @return {boolean} True if this Body is colliding with the world boundary. + */ + checkWorldBounds: function () + { + var pos = this.position; + var vel = this.velocity; + var blocked = this.blocked; + var bounds = this.customBoundsRectangle; + var check = this.world.checkCollision; + + var bx = (this.worldBounce) ? -this.worldBounce.x : -this.bounce.x; + var by = (this.worldBounce) ? -this.worldBounce.y : -this.bounce.y; + + var wasSet = false; + + if (pos.x < bounds.x && check.left) + { + pos.x = bounds.x; + vel.x *= bx; + blocked.left = true; + wasSet = true; + } + else if (this.right > bounds.right && check.right) + { + pos.x = bounds.right - this.width; + vel.x *= bx; + blocked.right = true; + wasSet = true; + } + + if (pos.y < bounds.y && check.up) + { + pos.y = bounds.y; + vel.y *= by; + blocked.up = true; + wasSet = true; + } + else if (this.bottom > bounds.bottom && check.down) + { + pos.y = bounds.bottom - this.height; + vel.y *= by; + blocked.down = true; + wasSet = true; + } + + if (wasSet) + { + this.blocked.none = false; + this.updateCenter(); + } + + return wasSet; + }, + + /** + * Sets the offset of the Body's position from its Game Object's position. + * The Body's `position` isn't changed until the next `preUpdate`. + * + * @method Phaser.Physics.Arcade.Body#setOffset + * @since 3.0.0 + * + * @param {number} x - The horizontal offset, in source pixels. + * @param {number} [y=x] - The vertical offset, in source pixels. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setOffset: function (x, y) + { + if (y === undefined) { y = x; } + + this.offset.set(x, y); + + return this; + }, + + /** + * Assign this Body to a new Game Object. + * + * Removes this body from the Physics World, assigns to the new Game Object, calls `setSize` and then + * adds this body back into the World again, setting it enabled, unless the `enable` argument is set to `false`. + * + * If this body already has a Game Object, then it will remove itself from that Game Object first. + * + * If the given `gameObject` doesn't have a `body` property, it is created and this Body is assigned to it. + * + * @method Phaser.Physics.Arcade.Body#setGameObject + * @since 3.60.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to assign this Body to. + * @param {boolean} [enable=true] - Automatically enable this Body for physics. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setGameObject: function (gameObject, enable) + { + if (enable === undefined) { enable = true; } + + if (!gameObject || !gameObject.hasTransformComponent) + { + // We need a valid Game Object to continue + return this; + } + + var world = this.world; + + if (this.gameObject && this.gameObject.body) + { + world.disable(this.gameObject); + + // Disconnect the current Game Object + this.gameObject.body = null; + } + + if (gameObject.body) + { + // Remove the body from the world, but don't disable the Game Object + world.disable(gameObject); + } + + this.gameObject = gameObject; + + gameObject.body = this; + + // This will remove the body from the tree, if it's in there and add the new one in + this.setSize(); + + this.enable = enable; + + return this; + }, + + /** + * Sizes and positions this Body, as a rectangle. + * Modifies the Body `offset` if `center` is true (the default). + * Resets the width and height to match current frame, if no width and height provided and a frame is found. + * + * @method Phaser.Physics.Arcade.Body#setSize + * @since 3.0.0 + * + * @param {number} [width] - The width of the Body in pixels. Cannot be zero. If not given, and the parent Game Object has a frame, it will use the frame width. + * @param {number} [height] - The height of the Body in pixels. Cannot be zero. If not given, and the parent Game Object has a frame, it will use the frame height. + * @param {boolean} [center=true] - Modify the Body's `offset`, placing the Body's center on its Game Object's center. Only works if the Game Object has the `getCenter` method. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setSize: function (width, height, center) + { + if (center === undefined) { center = true; } + + var gameObject = this.gameObject; + + if (gameObject) + { + if (!width && gameObject.frame) + { + width = gameObject.frame.realWidth; + } + + if (!height && gameObject.frame) + { + height = gameObject.frame.realHeight; + } + } + + this.sourceWidth = width; + this.sourceHeight = height; + + this.width = this.sourceWidth * this._sx; + this.height = this.sourceHeight * this._sy; + + this.halfWidth = Math.floor(this.width / 2); + this.halfHeight = Math.floor(this.height / 2); + + this.updateCenter(); + + if (center && gameObject && gameObject.getCenter) + { + var ox = (gameObject.width - width) / 2; + var oy = (gameObject.height - height) / 2; + + this.offset.set(ox, oy); + } + + this.isCircle = false; + this.radius = 0; + + return this; + }, + + /** + * Sizes and positions this Body, as a circle. + * + * @method Phaser.Physics.Arcade.Body#setCircle + * @since 3.0.0 + * + * @param {number} radius - The radius of the Body, in source pixels. + * @param {number} [offsetX] - The horizontal offset of the Body from its Game Object, in source pixels. + * @param {number} [offsetY] - The vertical offset of the Body from its Game Object, in source pixels. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setCircle: function (radius, offsetX, offsetY) + { + if (offsetX === undefined) { offsetX = this.offset.x; } + if (offsetY === undefined) { offsetY = this.offset.y; } + + if (radius > 0) + { + this.isCircle = true; + this.radius = radius; + + this.sourceWidth = radius * 2; + this.sourceHeight = radius * 2; + + this.width = this.sourceWidth * this._sx; + this.height = this.sourceHeight * this._sy; + + this.halfWidth = Math.floor(this.width / 2); + this.halfHeight = Math.floor(this.height / 2); + + this.offset.set(offsetX, offsetY); + + this.updateCenter(); + } + else + { + this.isCircle = false; + } + + return this; + }, + + /** + * Sets this Body's parent Game Object to the given coordinates and resets this Body at the new coordinates. + * If the Body had any velocity or acceleration it is lost as a result of calling this. + * + * @method Phaser.Physics.Arcade.Body#reset + * @since 3.0.0 + * + * @param {number} x - The horizontal position to place the Game Object. + * @param {number} y - The vertical position to place the Game Object. + */ + reset: function (x, y) + { + this.stop(); + + var gameObject = this.gameObject; + + if (gameObject) + { + gameObject.setPosition(x, y); + + this.rotation = gameObject.angle; + this.preRotation = gameObject.angle; + } + + var pos = this.position; + + if (gameObject && gameObject.getTopLeft) + { + gameObject.getTopLeft(pos); + } + else + { + pos.set(x, y); + } + + this.prev.copy(pos); + this.prevFrame.copy(pos); + this.autoFrame.copy(pos); + + if (gameObject) + { + this.updateBounds(); + } + + this.updateCenter(); + + if (this.collideWorldBounds) + { + this.checkWorldBounds(); + } + + this.resetFlags(true); + }, + + /** + * Sets acceleration, velocity, and speed to zero. + * + * @method Phaser.Physics.Arcade.Body#stop + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + stop: function () + { + this.velocity.set(0); + this.acceleration.set(0); + this.speed = 0; + this.angularVelocity = 0; + this.angularAcceleration = 0; + + return this; + }, + + /** + * Copies the coordinates of this Body's edges into an object. + * + * @method Phaser.Physics.Arcade.Body#getBounds + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeBodyBounds} obj - An object to copy the values into. + * + * @return {Phaser.Types.Physics.Arcade.ArcadeBodyBounds} - An object with {x, y, right, bottom}. + */ + getBounds: function (obj) + { + obj.x = this.x; + obj.y = this.y; + obj.right = this.right; + obj.bottom = this.bottom; + + return obj; + }, + + /** + * Tests if the coordinates are within this Body. + * + * @method Phaser.Physics.Arcade.Body#hitTest + * @since 3.0.0 + * + * @param {number} x - The horizontal coordinate. + * @param {number} y - The vertical coordinate. + * + * @return {boolean} True if (x, y) is within this Body. + */ + hitTest: function (x, y) + { + if (!this.isCircle) + { + return RectangleContains(this, x, y); + } + + // Check if x/y are within the bounds first + if (this.radius > 0 && x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) + { + var dx = (this.center.x - x) * (this.center.x - x); + var dy = (this.center.y - y) * (this.center.y - y); + + return (dx + dy) <= (this.radius * this.radius); + } + + return false; + }, + + /** + * Whether this Body is touching a tile or the world boundary while moving down. + * + * @method Phaser.Physics.Arcade.Body#onFloor + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#blocked + * + * @return {boolean} True if touching. + */ + onFloor: function () + { + return this.blocked.down; + }, + + /** + * Whether this Body is touching a tile or the world boundary while moving up. + * + * @method Phaser.Physics.Arcade.Body#onCeiling + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#blocked + * + * @return {boolean} True if touching. + */ + onCeiling: function () + { + return this.blocked.up; + }, + + /** + * Whether this Body is touching a tile or the world boundary while moving left or right. + * + * @method Phaser.Physics.Arcade.Body#onWall + * @since 3.0.0 + * @see Phaser.Physics.Arcade.Body#blocked + * + * @return {boolean} True if touching. + */ + onWall: function () + { + return (this.blocked.left || this.blocked.right); + }, + + /** + * The absolute (non-negative) change in this Body's horizontal position from the previous step. + * + * @method Phaser.Physics.Arcade.Body#deltaAbsX + * @since 3.0.0 + * + * @return {number} The delta value. + */ + deltaAbsX: function () + { + return (this._dx > 0) ? this._dx : -this._dx; + }, + + /** + * The absolute (non-negative) change in this Body's vertical position from the previous step. + * + * @method Phaser.Physics.Arcade.Body#deltaAbsY + * @since 3.0.0 + * + * @return {number} The delta value. + */ + deltaAbsY: function () + { + return (this._dy > 0) ? this._dy : -this._dy; + }, + + /** + * The change in this Body's horizontal position from the previous step. + * This value is set during the Body's update phase. + * + * As a Body can update multiple times per step this may not hold the final + * delta value for the Body. In this case, please see the `deltaXFinal` method. + * + * @method Phaser.Physics.Arcade.Body#deltaX + * @since 3.0.0 + * + * @return {number} The delta value. + */ + deltaX: function () + { + return this._dx; + }, + + /** + * The change in this Body's vertical position from the previous step. + * This value is set during the Body's update phase. + * + * As a Body can update multiple times per step this may not hold the final + * delta value for the Body. In this case, please see the `deltaYFinal` method. + * + * @method Phaser.Physics.Arcade.Body#deltaY + * @since 3.0.0 + * + * @return {number} The delta value. + */ + deltaY: function () + { + return this._dy; + }, + + /** + * The change in this Body's horizontal position from the previous game update. + * + * This value is set during the `postUpdate` phase and takes into account the + * `deltaMax` and final position of the Body. + * + * Because this value is not calculated until `postUpdate`, you must listen for it + * during a Scene `POST_UPDATE` or `RENDER` event, and not in `update`, as it will + * not be calculated by that point. If you _do_ use these values in `update` they + * will represent the delta from the _previous_ game frame. + * + * @method Phaser.Physics.Arcade.Body#deltaXFinal + * @since 3.22.0 + * + * @return {number} The final delta x value. + */ + deltaXFinal: function () + { + return this._tx; + }, + + /** + * The change in this Body's vertical position from the previous game update. + * + * This value is set during the `postUpdate` phase and takes into account the + * `deltaMax` and final position of the Body. + * + * Because this value is not calculated until `postUpdate`, you must listen for it + * during a Scene `POST_UPDATE` or `RENDER` event, and not in `update`, as it will + * not be calculated by that point. If you _do_ use these values in `update` they + * will represent the delta from the _previous_ game frame. + * + * @method Phaser.Physics.Arcade.Body#deltaYFinal + * @since 3.22.0 + * + * @return {number} The final delta y value. + */ + deltaYFinal: function () + { + return this._ty; + }, + + /** + * The change in this Body's rotation from the previous step, in degrees. + * + * @method Phaser.Physics.Arcade.Body#deltaZ + * @since 3.0.0 + * + * @return {number} The delta value. + */ + deltaZ: function () + { + return this.rotation - this.preRotation; + }, + + /** + * Disables this Body and marks it for deletion by the simulation. + * + * @method Phaser.Physics.Arcade.Body#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.enable = false; + + if (this.world) + { + this.world.pendingDestroy.add(this); + } + }, + + /** + * Draws this Body and its velocity, if enabled. + * + * @method Phaser.Physics.Arcade.Body#drawDebug + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Graphics} graphic - The Graphics object to draw on. + */ + drawDebug: function (graphic) + { + var pos = this.position; + + var x = pos.x + this.halfWidth; + var y = pos.y + this.halfHeight; + + if (this.debugShowBody) + { + graphic.lineStyle(graphic.defaultStrokeWidth, this.debugBodyColor); + + if (this.isCircle) + { + graphic.strokeCircle(x, y, this.width / 2); + } + else + { + // Only draw the sides where checkCollision is true, similar to debugger in layer + if (this.checkCollision.up) + { + graphic.lineBetween(pos.x, pos.y, pos.x + this.width, pos.y); + } + + if (this.checkCollision.right) + { + graphic.lineBetween(pos.x + this.width, pos.y, pos.x + this.width, pos.y + this.height); + } + + if (this.checkCollision.down) + { + graphic.lineBetween(pos.x, pos.y + this.height, pos.x + this.width, pos.y + this.height); + } + + if (this.checkCollision.left) + { + graphic.lineBetween(pos.x, pos.y, pos.x, pos.y + this.height); + } + } + } + + if (this.debugShowVelocity) + { + graphic.lineStyle(graphic.defaultStrokeWidth, this.world.defaults.velocityDebugColor, 1); + graphic.lineBetween(x, y, x + this.velocity.x / 2, y + this.velocity.y / 2); + } + }, + + /** + * Whether this Body will be drawn to the debug display. + * + * @method Phaser.Physics.Arcade.Body#willDrawDebug + * @since 3.0.0 + * + * @return {boolean} True if either `debugShowBody` or `debugShowVelocity` are enabled. + */ + willDrawDebug: function () + { + return (this.debugShowBody || this.debugShowVelocity); + }, + + /** + * Sets whether this Body should calculate its velocity based on its change in + * position every frame. The default, which is to not do this, means that you + * make this Body move by setting the velocity directly. However, if you are + * trying to move this Body via a Tween, or have it follow a Path, then you + * should enable this instead. This will allow it to still collide with other + * bodies, something that isn't possible if you're just changing its position directly. + * + * @method Phaser.Physics.Arcade.Body#setDirectControl + * @since 3.70.0 + * + * @param {boolean} [value=true] - `true` if the Body calculate velocity based on changes in position, otherwise `false`. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setDirectControl: function (value) + { + if (value === undefined) { value = true; } + + this.directControl = value; + + return this; + }, + + /** + * Sets whether this Body collides with the world boundary. + * + * Optionally also sets the World Bounce and `onWorldBounds` values. + * + * @method Phaser.Physics.Arcade.Body#setCollideWorldBounds + * @since 3.0.0 + * + * @param {boolean} [value=true] - `true` if the Body should collide with the world bounds, otherwise `false`. + * @param {number} [bounceX] - If given this replaces the Body's `worldBounce.x` value. + * @param {number} [bounceY] - If given this replaces the Body's `worldBounce.y` value. + * @param {boolean} [onWorldBounds] - If given this replaces the Body's `onWorldBounds` value. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setCollideWorldBounds: function (value, bounceX, bounceY, onWorldBounds) + { + if (value === undefined) { value = true; } + + this.collideWorldBounds = value; + + var setBounceX = (bounceX !== undefined); + var setBounceY = (bounceY !== undefined); + + if (setBounceX || setBounceY) + { + if (!this.worldBounce) + { + this.worldBounce = new Vector2(); + } + + if (setBounceX) + { + this.worldBounce.x = bounceX; + } + + if (setBounceY) + { + this.worldBounce.y = bounceY; + } + } + + if (onWorldBounds !== undefined) + { + this.onWorldBounds = onWorldBounds; + } + + return this; + }, + + /** + * Sets the Body's velocity. + * + * @method Phaser.Physics.Arcade.Body#setVelocity + * @since 3.0.0 + * + * @param {number} x - The horizontal velocity, in pixels per second. + * @param {number} [y=x] - The vertical velocity, in pixels per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setVelocity: function (x, y) + { + this.velocity.set(x, y); + + x = this.velocity.x; + y = this.velocity.y; + + this.speed = Math.sqrt(x * x + y * y); + + return this; + }, + + /** + * Sets the Body's horizontal velocity. + * + * @method Phaser.Physics.Arcade.Body#setVelocityX + * @since 3.0.0 + * + * @param {number} value - The velocity, in pixels per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setVelocityX: function (value) + { + return this.setVelocity(value, this.velocity.y); + }, + + /** + * Sets the Body's vertical velocity. + * + * @method Phaser.Physics.Arcade.Body#setVelocityY + * @since 3.0.0 + * + * @param {number} value - The velocity, in pixels per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setVelocityY: function (value) + { + return this.setVelocity(this.velocity.x, value); + }, + + /** + * Sets the Body's maximum velocity. + * + * @method Phaser.Physics.Arcade.Body#setMaxVelocity + * @since 3.10.0 + * + * @param {number} x - The horizontal velocity, in pixels per second. + * @param {number} [y=x] - The vertical velocity, in pixels per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setMaxVelocity: function (x, y) + { + this.maxVelocity.set(x, y); + + return this; + }, + + /** + * Sets the Body's maximum horizontal velocity. + * + * @method Phaser.Physics.Arcade.Body#setMaxVelocityX + * @since 3.50.0 + * + * @param {number} value - The maximum horizontal velocity, in pixels per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setMaxVelocityX: function (value) + { + this.maxVelocity.x = value; + + return this; + }, + + /** + * Sets the Body's maximum vertical velocity. + * + * @method Phaser.Physics.Arcade.Body#setMaxVelocityY + * @since 3.50.0 + * + * @param {number} value - The maximum vertical velocity, in pixels per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setMaxVelocityY: function (value) + { + this.maxVelocity.y = value; + + return this; + }, + + /** + * Sets the maximum speed the Body can move. + * + * @method Phaser.Physics.Arcade.Body#setMaxSpeed + * @since 3.16.0 + * + * @param {number} value - The maximum speed value, in pixels per second. Set to a negative value to disable. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setMaxSpeed: function (value) + { + this.maxSpeed = value; + + return this; + }, + + /** + * Sets the Slide Factor of this Body. + * + * The Slide Factor controls how much velocity is preserved when + * this Body is pushed by another Body. + * + * The default value is 1, which means that it will take on all + * velocity given in the push. You can adjust this value to control + * how much velocity is retained by this Body when the push ends. + * + * A value of 0, for example, will allow this Body to be pushed + * but then remain completely still after the push ends, such as + * you see in a game like Sokoban. + * + * Or you can set a mid-point, such as 0.25 which will allow it + * to keep 25% of the original velocity when the push ends. You + * can combine this with the `setDrag()` method to create deceleration. + * + * @method Phaser.Physics.Arcade.Body#setSlideFactor + * @since 3.70.0 + * + * @param {number} x - The horizontal slide factor. A value between 0 and 1. + * @param {number} [y=x] - The vertical slide factor. A value between 0 and 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setSlideFactor: function (x, y) + { + this.slideFactor.set(x, y); + + return this; + }, + + /** + * Sets the Body's bounce. + * + * @method Phaser.Physics.Arcade.Body#setBounce + * @since 3.0.0 + * + * @param {number} x - The horizontal bounce, relative to 1. + * @param {number} [y=x] - The vertical bounce, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setBounce: function (x, y) + { + this.bounce.set(x, y); + + return this; + }, + + /** + * Sets the Body's horizontal bounce. + * + * @method Phaser.Physics.Arcade.Body#setBounceX + * @since 3.0.0 + * + * @param {number} value - The bounce, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setBounceX: function (value) + { + this.bounce.x = value; + + return this; + }, + + /** + * Sets the Body's vertical bounce. + * + * @method Phaser.Physics.Arcade.Body#setBounceY + * @since 3.0.0 + * + * @param {number} value - The bounce, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setBounceY: function (value) + { + this.bounce.y = value; + + return this; + }, + + /** + * Sets the Body's acceleration. + * + * @method Phaser.Physics.Arcade.Body#setAcceleration + * @since 3.0.0 + * + * @param {number} x - The horizontal component, in pixels per second squared. + * @param {number} [y=x] - The vertical component, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAcceleration: function (x, y) + { + this.acceleration.set(x, y); + + return this; + }, + + /** + * Sets the Body's horizontal acceleration. + * + * @method Phaser.Physics.Arcade.Body#setAccelerationX + * @since 3.0.0 + * + * @param {number} value - The acceleration, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAccelerationX: function (value) + { + this.acceleration.x = value; + + return this; + }, + + /** + * Sets the Body's vertical acceleration. + * + * @method Phaser.Physics.Arcade.Body#setAccelerationY + * @since 3.0.0 + * + * @param {number} value - The acceleration, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAccelerationY: function (value) + { + this.acceleration.y = value; + + return this; + }, + + /** + * Enables or disables drag. + * + * @method Phaser.Physics.Arcade.Body#setAllowDrag + * @since 3.9.0 + * @see Phaser.Physics.Arcade.Body#allowDrag + * + * @param {boolean} [value=true] - `true` to allow drag on this body, or `false` to disable it. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAllowDrag: function (value) + { + if (value === undefined) { value = true; } + + this.allowDrag = value; + + return this; + }, + + /** + * Enables or disables gravity's effect on this Body. + * + * @method Phaser.Physics.Arcade.Body#setAllowGravity + * @since 3.9.0 + * @see Phaser.Physics.Arcade.Body#allowGravity + * + * @param {boolean} [value=true] - `true` to allow gravity on this body, or `false` to disable it. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAllowGravity: function (value) + { + if (value === undefined) { value = true; } + + this.allowGravity = value; + + return this; + }, + + /** + * Enables or disables rotation. + * + * @method Phaser.Physics.Arcade.Body#setAllowRotation + * @since 3.9.0 + * @see Phaser.Physics.Arcade.Body#allowRotation + * + * @param {boolean} [value=true] - `true` to allow rotation on this body, or `false` to disable it. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAllowRotation: function (value) + { + if (value === undefined) { value = true; } + + this.allowRotation = value; + + return this; + }, + + /** + * Sets the Body's drag. + * + * @method Phaser.Physics.Arcade.Body#setDrag + * @since 3.0.0 + * + * @param {number} x - The horizontal component, in pixels per second squared. + * @param {number} [y=x] - The vertical component, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setDrag: function (x, y) + { + this.drag.set(x, y); + + return this; + }, + + /** + * If this Body is using `drag` for deceleration this property controls how the drag is applied. + * If set to `true` drag will use a damping effect rather than a linear approach. If you are + * creating a game where the Body moves freely at any angle (i.e. like the way the ship moves in + * the game Asteroids) then you will get a far smoother and more visually correct deceleration + * by using damping, avoiding the axis-drift that is prone with linear deceleration. + * + * If you enable this property then you should use far smaller `drag` values than with linear, as + * they are used as a multiplier on the velocity. Values such as 0.95 will give a nice slow + * deceleration, where-as smaller values, such as 0.5 will stop an object almost immediately. + * + * @method Phaser.Physics.Arcade.Body#setDamping + * @since 3.50.0 + * + * @param {boolean} value - `true` to use damping, or `false` to use drag. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setDamping: function (value) + { + this.useDamping = value; + + return this; + }, + + /** + * Sets the Body's horizontal drag. + * + * @method Phaser.Physics.Arcade.Body#setDragX + * @since 3.0.0 + * + * @param {number} value - The drag, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setDragX: function (value) + { + this.drag.x = value; + + return this; + }, + + /** + * Sets the Body's vertical drag. + * + * @method Phaser.Physics.Arcade.Body#setDragY + * @since 3.0.0 + * + * @param {number} value - The drag, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setDragY: function (value) + { + this.drag.y = value; + + return this; + }, + + /** + * Sets the Body's gravity. + * + * @method Phaser.Physics.Arcade.Body#setGravity + * @since 3.0.0 + * + * @param {number} x - The horizontal component, in pixels per second squared. + * @param {number} [y=x] - The vertical component, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setGravity: function (x, y) + { + this.gravity.set(x, y); + + return this; + }, + + /** + * Sets the Body's horizontal gravity. + * + * @method Phaser.Physics.Arcade.Body#setGravityX + * @since 3.0.0 + * + * @param {number} value - The gravity, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setGravityX: function (value) + { + this.gravity.x = value; + + return this; + }, + + /** + * Sets the Body's vertical gravity. + * + * @method Phaser.Physics.Arcade.Body#setGravityY + * @since 3.0.0 + * + * @param {number} value - The gravity, in pixels per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setGravityY: function (value) + { + this.gravity.y = value; + + return this; + }, + + /** + * Sets the Body's friction. + * + * @method Phaser.Physics.Arcade.Body#setFriction + * @since 3.0.0 + * + * @param {number} x - The horizontal component, relative to 1. + * @param {number} [y=x] - The vertical component, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setFriction: function (x, y) + { + this.friction.set(x, y); + + return this; + }, + + /** + * Sets the Body's horizontal friction. + * + * @method Phaser.Physics.Arcade.Body#setFrictionX + * @since 3.0.0 + * + * @param {number} value - The friction value, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setFrictionX: function (value) + { + this.friction.x = value; + + return this; + }, + + /** + * Sets the Body's vertical friction. + * + * @method Phaser.Physics.Arcade.Body#setFrictionY + * @since 3.0.0 + * + * @param {number} value - The friction value, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setFrictionY: function (value) + { + this.friction.y = value; + + return this; + }, + + /** + * Sets the Body's angular velocity. + * + * @method Phaser.Physics.Arcade.Body#setAngularVelocity + * @since 3.0.0 + * + * @param {number} value - The velocity, in degrees per second. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAngularVelocity: function (value) + { + this.angularVelocity = value; + + return this; + }, + + /** + * Sets the Body's angular acceleration. + * + * @method Phaser.Physics.Arcade.Body#setAngularAcceleration + * @since 3.0.0 + * + * @param {number} value - The acceleration, in degrees per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAngularAcceleration: function (value) + { + this.angularAcceleration = value; + + return this; + }, + + /** + * Sets the Body's angular drag. + * + * @method Phaser.Physics.Arcade.Body#setAngularDrag + * @since 3.0.0 + * + * @param {number} value - The drag, in degrees per second squared. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setAngularDrag: function (value) + { + this.angularDrag = value; + + return this; + }, + + /** + * Sets the Body's mass. + * + * @method Phaser.Physics.Arcade.Body#setMass + * @since 3.0.0 + * + * @param {number} value - The mass value, relative to 1. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setMass: function (value) + { + this.mass = value; + + return this; + }, + + /** + * Sets the Body's `immovable` property. + * + * @method Phaser.Physics.Arcade.Body#setImmovable + * @since 3.0.0 + * + * @param {boolean} [value=true] - The value to assign to `immovable`. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setImmovable: function (value) + { + if (value === undefined) { value = true; } + + this.immovable = value; + + return this; + }, + + /** + * Sets the Body's `enable` property. + * + * @method Phaser.Physics.Arcade.Body#setEnable + * @since 3.15.0 + * + * @param {boolean} [value=true] - The value to assign to `enable`. + * + * @return {Phaser.Physics.Arcade.Body} This Body object. + */ + setEnable: function (value) + { + if (value === undefined) { value = true; } + + this.enable = value; + + return this; + }, + + /** + * This is an internal handler, called by the `ProcessX` function as part + * of the collision step. You should almost never call this directly. + * + * @method Phaser.Physics.Arcade.Body#processX + * @since 3.50.0 + * + * @param {number} x - The amount to add to the Body position. + * @param {number} [vx] - The amount to add to the Body velocity. + * @param {boolean} [left] - Set the blocked.left value? + * @param {boolean} [right] - Set the blocked.right value? + */ + processX: function (x, vx, left, right) + { + this.x += x; + + this.updateCenter(); + + if (vx !== null) + { + this.velocity.x = vx * this.slideFactor.x; + } + + var blocked = this.blocked; + + if (left) + { + blocked.left = true; + blocked.none = false; + } + + if (right) + { + blocked.right = true; + blocked.none = false; + } + }, + + /** + * This is an internal handler, called by the `ProcessY` function as part + * of the collision step. You should almost never call this directly. + * + * @method Phaser.Physics.Arcade.Body#processY + * @since 3.50.0 + * + * @param {number} y - The amount to add to the Body position. + * @param {number} [vy] - The amount to add to the Body velocity. + * @param {boolean} [up] - Set the blocked.up value? + * @param {boolean} [down] - Set the blocked.down value? + */ + processY: function (y, vy, up, down) + { + this.y += y; + + this.updateCenter(); + + if (vy !== null) + { + this.velocity.y = vy * this.slideFactor.y; + } + + var blocked = this.blocked; + + if (up) + { + blocked.up = true; + blocked.none = false; + } + + if (down) + { + blocked.down = true; + blocked.none = false; + } + }, + + /** + * The Bodys horizontal position (left edge). + * + * @name Phaser.Physics.Arcade.Body#x + * @type {number} + * @since 3.0.0 + */ + x: { + + get: function () + { + return this.position.x; + }, + + set: function (value) + { + this.position.x = value; + } + + }, + + /** + * The Bodys vertical position (top edge). + * + * @name Phaser.Physics.Arcade.Body#y + * @type {number} + * @since 3.0.0 + */ + y: { + + get: function () + { + return this.position.y; + }, + + set: function (value) + { + this.position.y = value; + } + + }, + + /** + * The left edge of the Body. Identical to x. + * + * @name Phaser.Physics.Arcade.Body#left + * @type {number} + * @readonly + * @since 3.0.0 + */ + left: { + + get: function () + { + return this.position.x; + } + + }, + + /** + * The right edge of the Body. + * + * @name Phaser.Physics.Arcade.Body#right + * @type {number} + * @readonly + * @since 3.0.0 + */ + right: { + + get: function () + { + return this.position.x + this.width; + } + + }, + + /** + * The top edge of the Body. Identical to y. + * + * @name Phaser.Physics.Arcade.Body#top + * @type {number} + * @readonly + * @since 3.0.0 + */ + top: { + + get: function () + { + return this.position.y; + } + + }, + + /** + * The bottom edge of this Body. + * + * @name Phaser.Physics.Arcade.Body#bottom + * @type {number} + * @readonly + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return this.position.y + this.height; + } + + } + +}); + +module.exports = Body; + + +/***/ }), + +/***/ 79342: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * An Arcade Physics Collider will automatically check for collision, or overlaps, between two objects + * every step. If a collision, or overlap, occurs it will invoke the given callbacks. + * + * Note, if setting `overlapOnly` to `true`, and one of the objects is a `TilemapLayer`, every tile in the layer, regardless of tile ID, will be checked for collision. + * Even if the layer has had only a subset of tile IDs enabled for collision, all tiles will still be checked for overlap. + * + * @class Collider + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.World} world - The Arcade physics World that will manage the collisions. + * @param {boolean} overlapOnly - Whether to check for collisions or overlaps. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object2 - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} collideCallback - The callback to invoke when the two objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} processCallback - The callback to invoke when the two objects collide. Must return a boolean. + * @param {any} callbackContext - The scope in which to call the callbacks. + */ +var Collider = new Class({ + + initialize: + + function Collider (world, overlapOnly, object1, object2, collideCallback, processCallback, callbackContext) + { + /** + * The world in which the bodies will collide. + * + * @name Phaser.Physics.Arcade.Collider#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The name of the collider (unused by Phaser). + * + * @name Phaser.Physics.Arcade.Collider#name + * @type {string} + * @since 3.1.0 + */ + this.name = ''; + + /** + * Whether the collider is active. + * + * @name Phaser.Physics.Arcade.Collider#active + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.active = true; + + /** + * Whether to check for collisions or overlaps. + * + * @name Phaser.Physics.Arcade.Collider#overlapOnly + * @type {boolean} + * @since 3.0.0 + */ + this.overlapOnly = overlapOnly; + + /** + * The first object to check for collision. + * + * @name Phaser.Physics.Arcade.Collider#object1 + * @type {Phaser.Types.Physics.Arcade.ArcadeColliderType} + * @since 3.0.0 + */ + this.object1 = object1; + + /** + * The second object to check for collision. + * + * @name Phaser.Physics.Arcade.Collider#object2 + * @type {Phaser.Types.Physics.Arcade.ArcadeColliderType} + * @since 3.0.0 + */ + this.object2 = object2; + + /** + * The callback to invoke when the two objects collide. + * + * @name Phaser.Physics.Arcade.Collider#collideCallback + * @type {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} + * @since 3.0.0 + */ + this.collideCallback = collideCallback; + + /** + * If a processCallback exists it must return true or collision checking will be skipped. + * + * @name Phaser.Physics.Arcade.Collider#processCallback + * @type {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} + * @since 3.0.0 + */ + this.processCallback = processCallback; + + /** + * The context the collideCallback and processCallback will run in. + * + * @name Phaser.Physics.Arcade.Collider#callbackContext + * @type {object} + * @since 3.0.0 + */ + this.callbackContext = callbackContext; + }, + + /** + * A name for the Collider. + * + * Phaser does not use this value, it's for your own reference. + * + * @method Phaser.Physics.Arcade.Collider#setName + * @since 3.1.0 + * + * @param {string} name - The name to assign to the Collider. + * + * @return {Phaser.Physics.Arcade.Collider} This Collider instance. + */ + setName: function (name) + { + this.name = name; + + return this; + }, + + /** + * Called by World as part of its step processing, initial operation of collision checking. + * + * @method Phaser.Physics.Arcade.Collider#update + * @since 3.0.0 + */ + update: function () + { + this.world.collideObjects( + this.object1, + this.object2, + this.collideCallback, + this.processCallback, + this.callbackContext, + this.overlapOnly + ); + }, + + /** + * Removes Collider from World and disposes of its resources. + * + * @method Phaser.Physics.Arcade.Collider#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.world.removeCollider(this); + + this.active = false; + + this.world = null; + + this.object1 = null; + this.object2 = null; + + this.collideCallback = null; + this.processCallback = null; + this.callbackContext = null; + } + +}); + +module.exports = Collider; + + +/***/ }), + +/***/ 66022: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArcadeImage = __webpack_require__(71289); +var ArcadeSprite = __webpack_require__(13759); +var Body = __webpack_require__(37742); +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(37747); +var PhysicsGroup = __webpack_require__(60758); +var StaticBody = __webpack_require__(72624); +var StaticPhysicsGroup = __webpack_require__(71464); + +/** + * @classdesc + * The Arcade Physics Factory allows you to easily create Arcade Physics enabled Game Objects. + * Objects that are created by this Factory are automatically added to the physics world. + * + * @class Factory + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.World} world - The Arcade Physics World instance. + */ +var Factory = new Class({ + + initialize: + + function Factory (world) + { + /** + * A reference to the Arcade Physics World. + * + * @name Phaser.Physics.Arcade.Factory#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * A reference to the Scene this Arcade Physics instance belongs to. + * + * @name Phaser.Physics.Arcade.Factory#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = world.scene; + + /** + * A reference to the Scene.Systems this Arcade Physics instance belongs to. + * + * @name Phaser.Physics.Arcade.Factory#sys + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.sys = world.scene.sys; + }, + + /** + * Creates a new Arcade Physics Collider object. + * + * @method Phaser.Physics.Arcade.Factory#collider + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object2 - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - The callback to invoke when the two objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - The callback to invoke when the two objects collide. Must return a boolean. + * @param {*} [callbackContext] - The scope in which to call the callbacks. + * + * @return {Phaser.Physics.Arcade.Collider} The Collider that was created. + */ + collider: function (object1, object2, collideCallback, processCallback, callbackContext) + { + return this.world.addCollider(object1, object2, collideCallback, processCallback, callbackContext); + }, + + /** + * Creates a new Arcade Physics Collider Overlap object. + * + * @method Phaser.Physics.Arcade.Factory#overlap + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object to check for overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object2 - The second object to check for overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - The callback to invoke when the two objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - The callback to invoke when the two objects collide. Must return a boolean. + * @param {*} [callbackContext] - The scope in which to call the callbacks. + * + * @return {Phaser.Physics.Arcade.Collider} The Collider that was created. + */ + overlap: function (object1, object2, collideCallback, processCallback, callbackContext) + { + return this.world.addOverlap(object1, object2, collideCallback, processCallback, callbackContext); + }, + + /** + * Adds an Arcade Physics Body to the given Game Object. + * + * @method Phaser.Physics.Arcade.Factory#existing + * @since 3.0.0 + * + * @generic {Phaser.GameObjects.GameObject} G - [gameObject,$return] + * + * @param {Phaser.GameObjects.GameObject} gameObject - A Game Object. + * @param {boolean} [isStatic=false] - Create a Static body (true) or Dynamic body (false). + * + * @return {Phaser.Types.Physics.Arcade.GameObjectWithBody} The Game Object. + */ + existing: function (gameObject, isStatic) + { + var type = (isStatic) ? CONST.STATIC_BODY : CONST.DYNAMIC_BODY; + + this.world.enableBody(gameObject, type); + + return gameObject; + }, + + /** + * Creates a new Arcade Image object with a Static body. + * + * @method Phaser.Physics.Arcade.Factory#staticImage + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.Types.Physics.Arcade.ImageWithStaticBody} The Image object that was created. + */ + staticImage: function (x, y, key, frame) + { + var image = new ArcadeImage(this.scene, x, y, key, frame); + + this.sys.displayList.add(image); + + this.world.enableBody(image, CONST.STATIC_BODY); + + return image; + }, + + /** + * Creates a new Arcade Image object with a Dynamic body. + * + * @method Phaser.Physics.Arcade.Factory#image + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.Types.Physics.Arcade.ImageWithDynamicBody} The Image object that was created. + */ + image: function (x, y, key, frame) + { + var image = new ArcadeImage(this.scene, x, y, key, frame); + + this.sys.displayList.add(image); + + this.world.enableBody(image, CONST.DYNAMIC_BODY); + + return image; + }, + + /** + * Creates a new Arcade Sprite object with a Static body. + * + * @method Phaser.Physics.Arcade.Factory#staticSprite + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.Types.Physics.Arcade.SpriteWithStaticBody} The Sprite object that was created. + */ + staticSprite: function (x, y, key, frame) + { + var sprite = new ArcadeSprite(this.scene, x, y, key, frame); + + this.sys.displayList.add(sprite); + this.sys.updateList.add(sprite); + + this.world.enableBody(sprite, CONST.STATIC_BODY); + + return sprite; + }, + + /** + * Creates a new Arcade Sprite object with a Dynamic body. + * + * @method Phaser.Physics.Arcade.Factory#sprite + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * + * @return {Phaser.Types.Physics.Arcade.SpriteWithDynamicBody} The Sprite object that was created. + */ + sprite: function (x, y, key, frame) + { + var sprite = new ArcadeSprite(this.scene, x, y, key, frame); + + this.sys.displayList.add(sprite); + this.sys.updateList.add(sprite); + + this.world.enableBody(sprite, CONST.DYNAMIC_BODY); + + return sprite; + }, + + /** + * Creates a Static Physics Group object. + * All Game Objects created by this Group will automatically be static Arcade Physics objects. + * + * @method Phaser.Physics.Arcade.Factory#staticGroup + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject[]|Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig)} [children] - Game Objects to add to this group; or the `config` argument. + * @param {Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} [config] - Settings for this group. + * + * @return {Phaser.Physics.Arcade.StaticGroup} The Static Group object that was created. + */ + staticGroup: function (children, config) + { + return this.sys.updateList.add(new StaticPhysicsGroup(this.world, this.world.scene, children, config)); + }, + + /** + * Creates a Physics Group object. + * All Game Objects created by this Group will automatically be dynamic Arcade Physics objects. + * + * @method Phaser.Physics.Arcade.Factory#group + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject[]|Phaser.Types.Physics.Arcade.PhysicsGroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig)} [children] - Game Objects to add to this group; or the `config` argument. + * @param {Phaser.Types.Physics.Arcade.PhysicsGroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} [config] - Settings for this group. + * + * @return {Phaser.Physics.Arcade.Group} The Group object that was created. + */ + group: function (children, config) + { + return this.sys.updateList.add(new PhysicsGroup(this.world, this.world.scene, children, config)); + }, + + /** + * Creates a new physics Body with the given position and size. + * + * This Body is not associated with any Game Object, but still exists within the world + * and can be tested for collision, have velocity, etc. + * + * @method Phaser.Physics.Arcade.Factory#body + * @since 3.60.0 + * + * @param {number} x - The horizontal position of this Body in the physics world. + * @param {number} y - The vertical position of this Body in the physics world. + * @param {number} [width=64] - The width of the Body in pixels. Cannot be negative or zero. + * @param {number} [height=64] - The height of the Body in pixels. Cannot be negative or zero. + * + * @return {Phaser.Physics.Arcade.Body} The Body that was created. + */ + body: function (x, y, width, height) + { + var body = new Body(this.world); + + body.position.set(x, y); + + if (width && height) + { + body.setSize(width, height); + } + + this.world.add(body, CONST.DYNAMIC_BODY); + + return body; + }, + + /** + * Creates a new static physics Body with the given position and size. + * + * This Body is not associated with any Game Object, but still exists within the world + * and can be tested for collision, etc. + * + * @method Phaser.Physics.Arcade.Factory#staticBody + * @since 3.60.0 + * + * @param {number} x - The horizontal position of this Body in the physics world. + * @param {number} y - The vertical position of this Body in the physics world. + * @param {number} [width=64] - The width of the Body in pixels. Cannot be negative or zero. + * @param {number} [height=64] - The height of the Body in pixels. Cannot be negative or zero. + * + * @return {Phaser.Physics.Arcade.StaticBody} The Static Body that was created. + */ + staticBody: function (x, y, width, height) + { + var body = new StaticBody(this.world); + + body.position.set(x, y); + + if (width && height) + { + body.setSize(width, height); + } + + this.world.add(body, CONST.STATIC_BODY); + + return body; + }, + + /** + * Destroys this Factory. + * + * @method Phaser.Physics.Arcade.Factory#destroy + * @since 3.5.0 + */ + destroy: function () + { + this.world = null; + this.scene = null; + this.sys = null; + } + +}); + +module.exports = Factory; + + +/***/ }), + +/***/ 79599: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Calculates and returns the bitmask needed to determine if the given + * categories will collide with each other or not. + * + * @function Phaser.Physics.Arcade.GetCollidesWith + * @since 3.70.0 + * + * @param {(number|number[])} categories - A unique category bitfield, or an array of them. + * + * @return {number} The collision mask. + */ +var GetCollidesWith = function (categories) +{ + var flags = 0; + + if (!Array.isArray(categories)) + { + flags = categories; + } + else + { + for (var i = 0; i < categories.length; i++) + { + flags |= categories[i]; + } + } + + return flags; +}; + +module.exports = GetCollidesWith; + + +/***/ }), + +/***/ 64897: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(37747); + +/** + * Calculates and returns the horizontal overlap between two arcade physics bodies and sets their properties + * accordingly, including: `touching.left`, `touching.right`, `touching.none` and `overlapX'. + * + * @function Phaser.Physics.Arcade.GetOverlapX + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first Body to separate. + * @param {Phaser.Physics.Arcade.Body} body2 - The second Body to separate. + * @param {boolean} overlapOnly - Is this an overlap only check, or part of separation? + * @param {number} bias - A value added to the delta values during collision checks. Increase it to prevent sprite tunneling(sprites passing through another instead of colliding). + * + * @return {number} The amount of overlap. + */ +var GetOverlapX = function (body1, body2, overlapOnly, bias) +{ + var overlap = 0; + var maxOverlap = body1.deltaAbsX() + body2.deltaAbsX() + bias; + + if (body1._dx === 0 && body2._dx === 0) + { + // They overlap but neither of them are moving + body1.embedded = true; + body2.embedded = true; + } + else if (body1._dx > body2._dx) + { + // Body1 is moving right and / or Body2 is moving left + overlap = body1.right - body2.x; + + if ((overlap > maxOverlap && !overlapOnly) || body1.checkCollision.right === false || body2.checkCollision.left === false) + { + overlap = 0; + } + else + { + body1.touching.none = false; + body1.touching.right = true; + + body2.touching.none = false; + body2.touching.left = true; + + if (body2.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body1.blocked.none = false; + body1.blocked.right = true; + } + + if (body1.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body2.blocked.none = false; + body2.blocked.left = true; + } + } + } + else if (body1._dx < body2._dx) + { + // Body1 is moving left and/or Body2 is moving right + overlap = body1.x - body2.width - body2.x; + + if ((-overlap > maxOverlap && !overlapOnly) || body1.checkCollision.left === false || body2.checkCollision.right === false) + { + overlap = 0; + } + else + { + body1.touching.none = false; + body1.touching.left = true; + + body2.touching.none = false; + body2.touching.right = true; + + if (body2.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body1.blocked.none = false; + body1.blocked.left = true; + } + + if (body1.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body2.blocked.none = false; + body2.blocked.right = true; + } + } + } + + // Resets the overlapX to zero if there is no overlap, or to the actual pixel value if there is + body1.overlapX = overlap; + body2.overlapX = overlap; + + return overlap; +}; + +module.exports = GetOverlapX; + + +/***/ }), + +/***/ 45170: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(37747); + +/** + * Calculates and returns the vertical overlap between two arcade physics bodies and sets their properties + * accordingly, including: `touching.up`, `touching.down`, `touching.none` and `overlapY'. + * + * @function Phaser.Physics.Arcade.GetOverlapY + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first Body to separate. + * @param {Phaser.Physics.Arcade.Body} body2 - The second Body to separate. + * @param {boolean} overlapOnly - Is this an overlap only check, or part of separation? + * @param {number} bias - A value added to the delta values during collision checks. Increase it to prevent sprite tunneling(sprites passing through another instead of colliding). + * + * @return {number} The amount of overlap. + */ +var GetOverlapY = function (body1, body2, overlapOnly, bias) +{ + var overlap = 0; + var maxOverlap = body1.deltaAbsY() + body2.deltaAbsY() + bias; + + if (body1._dy === 0 && body2._dy === 0) + { + // They overlap but neither of them are moving + body1.embedded = true; + body2.embedded = true; + } + else if (body1._dy > body2._dy) + { + // Body1 is moving down and/or Body2 is moving up + overlap = body1.bottom - body2.y; + + if ((overlap > maxOverlap && !overlapOnly) || body1.checkCollision.down === false || body2.checkCollision.up === false) + { + overlap = 0; + } + else + { + body1.touching.none = false; + body1.touching.down = true; + + body2.touching.none = false; + body2.touching.up = true; + + if (body2.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body1.blocked.none = false; + body1.blocked.down = true; + } + + if (body1.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body2.blocked.none = false; + body2.blocked.up = true; + } + } + } + else if (body1._dy < body2._dy) + { + // Body1 is moving up and/or Body2 is moving down + overlap = body1.y - body2.bottom; + + if ((-overlap > maxOverlap && !overlapOnly) || body1.checkCollision.up === false || body2.checkCollision.down === false) + { + overlap = 0; + } + else + { + body1.touching.none = false; + body1.touching.up = true; + + body2.touching.none = false; + body2.touching.down = true; + + if (body2.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body1.blocked.none = false; + body1.blocked.up = true; + } + + if (body1.physicsType === CONST.STATIC_BODY && !overlapOnly) + { + body2.blocked.none = false; + body2.blocked.down = true; + } + } + } + + // Resets the overlapY to zero if there is no overlap, or to the actual pixel value if there is + body1.overlapY = overlap; + body2.overlapY = overlap; + + return overlap; +}; + +module.exports = GetOverlapY; + + +/***/ }), + +/***/ 60758: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArcadeSprite = __webpack_require__(13759); +var Class = __webpack_require__(83419); +var CollisionComponent = __webpack_require__(78389); +var CONST = __webpack_require__(37747); +var GetFastValue = __webpack_require__(95540); +var Group = __webpack_require__(26479); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * An Arcade Physics Group object. + * + * The primary use of a Physics Group is a way to collect together physics enable objects + * that share the same intrinsic structure into a single pool. They can they be easily + * compared against other Groups, or Game Objects. + * + * All Game Objects created by, or added to this Group will automatically be given **dynamic** + * Arcade Physics bodies (if they have no body already) and the bodies will receive the + * Groups {@link Phaser.Physics.Arcade.Group#defaults default values}. + * + * You should not pass objects into this Group that should not receive a body. For example, + * do not add basic Geometry or Tilemap Layers into a Group, as they will not behave in the + * way you may expect. Groups should all ideally have objects of the same type in them. + * + * If you wish to create a Group filled with Static Bodies, please see {@link Phaser.Physics.Arcade.StaticGroup}. + * + * @class Group + * @extends Phaser.GameObjects.Group + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Arcade.Components.Collision + * + * @param {Phaser.Physics.Arcade.World} world - The physics simulation. + * @param {Phaser.Scene} scene - The scene this group belongs to. + * @param {(Phaser.GameObjects.GameObject[]|Phaser.Types.Physics.Arcade.PhysicsGroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig)} [children] - Game Objects to add to this group; or the `config` argument. + * @param {Phaser.Types.Physics.Arcade.PhysicsGroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} [config] - Settings for this group. + */ +var PhysicsGroup = new Class({ + + Extends: Group, + + Mixins: [ + CollisionComponent + ], + + initialize: + + function PhysicsGroup (world, scene, children, config) + { + if (!children && !config) + { + config = { + internalCreateCallback: this.createCallbackHandler, + internalRemoveCallback: this.removeCallbackHandler + }; + } + else if (IsPlainObject(children)) + { + // children is a plain object, so swizzle them: + config = children; + children = null; + + config.internalCreateCallback = this.createCallbackHandler; + config.internalRemoveCallback = this.removeCallbackHandler; + } + else if (Array.isArray(children) && IsPlainObject(children[0])) + { + // children is an array of plain objects (i.e., configs) + var _this = this; + + children.forEach(function (singleConfig) + { + singleConfig.internalCreateCallback = _this.createCallbackHandler; + singleConfig.internalRemoveCallback = _this.removeCallbackHandler; + singleConfig.classType = GetFastValue(singleConfig, 'classType', ArcadeSprite); + }); + + config = null; + } + else + { + // config is not defined and children is not a plain object nor an array of plain objects + config = { + internalCreateCallback: this.createCallbackHandler, + internalRemoveCallback: this.removeCallbackHandler + }; + } + + /** + * The physics simulation. + * + * @name Phaser.Physics.Arcade.Group#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The class to create new Group members from. + * + * This should be either `Phaser.Physics.Arcade.Image`, `Phaser.Physics.Arcade.Sprite`, or a class extending one of those. + * + * @name Phaser.Physics.Arcade.Group#classType + * @type {function} + * @default ArcadeSprite + * @since 3.0.0 + * @see Phaser.Types.GameObjects.Group.GroupClassTypeConstructor + */ + if (config) + { + config.classType = GetFastValue(config, 'classType', ArcadeSprite); + } + + /** + * The physics type of the Group's members. + * + * @name Phaser.Physics.Arcade.Group#physicsType + * @type {number} + * @default Phaser.Physics.Arcade.DYNAMIC_BODY + * @since 3.0.0 + */ + this.physicsType = CONST.DYNAMIC_BODY; + + /** + * The Arcade Physics Group Collision Category. + * + * This can be set to any valid collision bitfield value. + * + * See the `setCollisionCategory` method for more details. + * + * @name Phaser.Physics.Arcade.Group#collisionCategory + * @type {number} + * @since 3.70.0 + */ + this.collisionCategory = 0x0001; + + /** + * The Arcade Physics Group Collision Mask. + * + * See the `setCollidesWith` method for more details. + * + * @name Phaser.Physics.Arcade.Group#collisionMask + * @type {number} + * @since 3.70.0 + */ + this.collisionMask = 2147483647; + + /** + * Default physics properties applied to Game Objects added to the Group or created by the Group. Derived from the `config` argument. + * + * You can remove the default values by setting this property to `{}`. + * + * @name Phaser.Physics.Arcade.Group#defaults + * @type {Phaser.Types.Physics.Arcade.PhysicsGroupDefaults} + * @since 3.0.0 + */ + this.defaults = { + setCollideWorldBounds: GetFastValue(config, 'collideWorldBounds', false), + setBoundsRectangle: GetFastValue(config, 'customBoundsRectangle', null), + setAccelerationX: GetFastValue(config, 'accelerationX', 0), + setAccelerationY: GetFastValue(config, 'accelerationY', 0), + setAllowDrag: GetFastValue(config, 'allowDrag', true), + setAllowGravity: GetFastValue(config, 'allowGravity', true), + setAllowRotation: GetFastValue(config, 'allowRotation', true), + setDamping: GetFastValue(config, 'useDamping', false), + setBounceX: GetFastValue(config, 'bounceX', 0), + setBounceY: GetFastValue(config, 'bounceY', 0), + setDragX: GetFastValue(config, 'dragX', 0), + setDragY: GetFastValue(config, 'dragY', 0), + setEnable: GetFastValue(config, 'enable', true), + setGravityX: GetFastValue(config, 'gravityX', 0), + setGravityY: GetFastValue(config, 'gravityY', 0), + setFrictionX: GetFastValue(config, 'frictionX', 0), + setFrictionY: GetFastValue(config, 'frictionY', 0), + setMaxSpeed: GetFastValue(config, 'maxSpeed', -1), + setMaxVelocityX: GetFastValue(config, 'maxVelocityX', 10000), + setMaxVelocityY: GetFastValue(config, 'maxVelocityY', 10000), + setVelocityX: GetFastValue(config, 'velocityX', 0), + setVelocityY: GetFastValue(config, 'velocityY', 0), + setAngularVelocity: GetFastValue(config, 'angularVelocity', 0), + setAngularAcceleration: GetFastValue(config, 'angularAcceleration', 0), + setAngularDrag: GetFastValue(config, 'angularDrag', 0), + setMass: GetFastValue(config, 'mass', 1), + setImmovable: GetFastValue(config, 'immovable', false) + }; + + Group.call(this, scene, children, config); + + /** + * A textual representation of this Game Object. + * Used internally by Phaser but is available for your own custom classes to populate. + * + * @name Phaser.Physics.Arcade.Group#type + * @type {string} + * @default 'PhysicsGroup' + * @since 3.21.0 + */ + this.type = 'PhysicsGroup'; + }, + + /** + * Enables a Game Object's Body and assigns `defaults`. Called when a Group member is added or created. + * + * @method Phaser.Physics.Arcade.Group#createCallbackHandler + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object being added. + */ + createCallbackHandler: function (child) + { + if (!child.body) + { + this.world.enableBody(child, CONST.DYNAMIC_BODY); + } + + var body = child.body; + + for (var key in this.defaults) + { + body[key](this.defaults[key]); + } + }, + + /** + * Disables a Game Object's Body. Called when a Group member is removed. + * + * @method Phaser.Physics.Arcade.Group#removeCallbackHandler + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object being removed. + */ + removeCallbackHandler: function (child) + { + if (child.body) + { + this.world.disableBody(child); + } + }, + + /** + * Sets the velocity of each Group member. + * + * @method Phaser.Physics.Arcade.Group#setVelocity + * @since 3.0.0 + * + * @param {number} x - The horizontal velocity. + * @param {number} y - The vertical velocity. + * @param {number} [step=0] - The velocity increment. When set, the first member receives velocity (x, y), the second (x + step, y + step), and so on. + * + * @return {Phaser.Physics.Arcade.Group} This Physics Group object. + */ + setVelocity: function (x, y, step) + { + if (step === undefined) { step = 0; } + + var items = this.getChildren(); + + for (var i = 0; i < items.length; i++) + { + items[i].body.velocity.set(x + (i * step), y + (i * step)); + } + + return this; + }, + + /** + * Sets the horizontal velocity of each Group member. + * + * @method Phaser.Physics.Arcade.Group#setVelocityX + * @since 3.0.0 + * + * @param {number} value - The velocity value. + * @param {number} [step=0] - The velocity increment. When set, the first member receives velocity (x), the second (x + step), and so on. + * + * @return {Phaser.Physics.Arcade.Group} This Physics Group object. + */ + setVelocityX: function (value, step) + { + if (step === undefined) { step = 0; } + + var items = this.getChildren(); + + for (var i = 0; i < items.length; i++) + { + items[i].body.velocity.x = value + (i * step); + } + + return this; + }, + + /** + * Sets the vertical velocity of each Group member. + * + * @method Phaser.Physics.Arcade.Group#setVelocityY + * @since 3.0.0 + * + * @param {number} value - The velocity value. + * @param {number} [step=0] - The velocity increment. When set, the first member receives velocity (y), the second (y + step), and so on. + * + * @return {Phaser.Physics.Arcade.Group} This Physics Group object. + */ + setVelocityY: function (value, step) + { + if (step === undefined) { step = 0; } + + var items = this.getChildren(); + + for (var i = 0; i < items.length; i++) + { + items[i].body.velocity.y = value + (i * step); + } + + return this; + } + +}); + +module.exports = PhysicsGroup; + + +/***/ }), + +/***/ 3017: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var body1; +var body2; +var body1Pushable; +var body2Pushable; +var body1MassImpact; +var body2MassImpact; +var body1FullImpact; +var body2FullImpact; +var body1MovingLeft; +var body1MovingRight; +var body1Stationary; +var body2MovingLeft; +var body2MovingRight; +var body2Stationary; +var body1OnLeft; +var body2OnLeft; +var overlap; + +/** + * Sets all of the local processing values and calculates the velocity exchanges. + * + * Then runs `BlockCheck` and returns the value from it. + * + * This method is called by `Phaser.Physics.Arcade.SeparateX` and should not be + * called directly. + * + * @function Phaser.Physics.Arcade.ProcessX.Set + * @ignore + * @since 3.50.0 + * + * @param {Phaser.Physics.Arcade.Body} b1 - The first Body to separate. + * @param {Phaser.Physics.Arcade.Body} b2 - The second Body to separate. + * @param {number} ov - The overlap value. + * + * @return {number} The BlockCheck result. 0 = not blocked. 1 = Body 1 blocked. 2 = Body 2 blocked. + */ +var Set = function (b1, b2, ov) +{ + body1 = b1; + body2 = b2; + + var v1 = body1.velocity.x; + var v2 = body2.velocity.x; + + body1Pushable = body1.pushable; + body1MovingLeft = body1._dx < 0; + body1MovingRight = body1._dx > 0; + body1Stationary = body1._dx === 0; + body1OnLeft = Math.abs(body1.right - body2.x) <= Math.abs(body2.right - body1.x); + body1FullImpact = v2 - v1 * body1.bounce.x; + + body2Pushable = body2.pushable; + body2MovingLeft = body2._dx < 0; + body2MovingRight = body2._dx > 0; + body2Stationary = body2._dx === 0; + body2OnLeft = !body1OnLeft; + body2FullImpact = v1 - v2 * body2.bounce.x; + + // negative delta = up, positive delta = down (inc. gravity) + overlap = Math.abs(ov); + + return BlockCheck(); +}; + +/** + * Blocked Direction checks, because it doesn't matter if an object can be pushed + * or not, blocked is blocked. + * + * @function Phaser.Physics.Arcade.ProcessX.BlockCheck + * @ignore + * @since 3.50.0 + * + * @return {number} The BlockCheck result. 0 = not blocked. 1 = Body 1 blocked. 2 = Body 2 blocked. + */ +var BlockCheck = function () +{ + // Body1 is moving right and Body2 is blocked from going right any further + if (body1MovingRight && body1OnLeft && body2.blocked.right) + { + body1.processX(-overlap, body1FullImpact, false, true); + + return 1; + } + + // Body1 is moving left and Body2 is blocked from going left any further + if (body1MovingLeft && body2OnLeft && body2.blocked.left) + { + body1.processX(overlap, body1FullImpact, true); + + return 1; + } + + // Body2 is moving right and Body1 is blocked from going right any further + if (body2MovingRight && body2OnLeft && body1.blocked.right) + { + body2.processX(-overlap, body2FullImpact, false, true); + + return 2; + } + + // Body2 is moving left and Body1 is blocked from going left any further + if (body2MovingLeft && body1OnLeft && body1.blocked.left) + { + body2.processX(overlap, body2FullImpact, true); + + return 2; + } + + return 0; +}; + +/** + * The main check function. Runs through one of the four possible tests and returns the results. + * + * @function Phaser.Physics.Arcade.ProcessX.Check + * @ignore + * @since 3.50.0 + * + * @return {boolean} `true` if a check passed, otherwise `false`. + */ +var Check = function () +{ + var v1 = body1.velocity.x; + var v2 = body2.velocity.x; + + var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1); + var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1); + var avg = (nv1 + nv2) * 0.5; + + nv1 -= avg; + nv2 -= avg; + + body1MassImpact = avg + nv1 * body1.bounce.x; + body2MassImpact = avg + nv2 * body2.bounce.x; + + // Body1 hits Body2 on the right hand side + if (body1MovingLeft && body2OnLeft) + { + return Run(0); + } + + // Body2 hits Body1 on the right hand side + if (body2MovingLeft && body1OnLeft) + { + return Run(1); + } + + // Body1 hits Body2 on the left hand side + if (body1MovingRight && body1OnLeft) + { + return Run(2); + } + + // Body2 hits Body1 on the left hand side + if (body2MovingRight && body2OnLeft) + { + return Run(3); + } + + return false; +}; + +/** + * The main check function. Runs through one of the four possible tests and returns the results. + * + * @function Phaser.Physics.Arcade.ProcessX.Run + * @ignore + * @since 3.50.0 + * + * @param {number} side - The side to test. As passed in by the `Check` function. + * + * @return {boolean} Always returns `true`. + */ +var Run = function (side) +{ + if (body1Pushable && body2Pushable) + { + // Both pushable, or both moving at the same time, so equal rebound + overlap *= 0.5; + + if (side === 0 || side === 3) + { + // body1MovingLeft && body2OnLeft + // body2MovingRight && body2OnLeft + body1.processX(overlap, body1MassImpact); + body2.processX(-overlap, body2MassImpact); + } + else + { + // body2MovingLeft && body1OnLeft + // body1MovingRight && body1OnLeft + body1.processX(-overlap, body1MassImpact); + body2.processX(overlap, body2MassImpact); + } + } + else if (body1Pushable && !body2Pushable) + { + // Body1 pushable, Body2 not + + if (side === 0 || side === 3) + { + // body1MovingLeft && body2OnLeft + // body2MovingRight && body2OnLeft + body1.processX(overlap, body1FullImpact, true); + } + else + { + // body2MovingLeft && body1OnLeft + // body1MovingRight && body1OnLeft + body1.processX(-overlap, body1FullImpact, false, true); + } + } + else if (!body1Pushable && body2Pushable) + { + // Body2 pushable, Body1 not + + if (side === 0 || side === 3) + { + // body1MovingLeft && body2OnLeft + // body2MovingRight && body2OnLeft + body2.processX(-overlap, body2FullImpact, false, true); + } + else + { + // body2MovingLeft && body1OnLeft + // body1MovingRight && body1OnLeft + body2.processX(overlap, body2FullImpact, true); + } + } + else + { + // Neither body is pushable, so base it on movement + + var halfOverlap = overlap * 0.5; + + if (side === 0) + { + // body1MovingLeft && body2OnLeft + + if (body2Stationary) + { + body1.processX(overlap, 0, true); + body2.processX(0, null, false, true); + } + else if (body2MovingRight) + { + body1.processX(halfOverlap, 0, true); + body2.processX(-halfOverlap, 0, false, true); + } + else + { + // Body2 moving same direction as Body1 + body1.processX(halfOverlap, body2.velocity.x, true); + body2.processX(-halfOverlap, null, false, true); + } + } + else if (side === 1) + { + // body2MovingLeft && body1OnLeft + + if (body1Stationary) + { + body1.processX(0, null, false, true); + body2.processX(overlap, 0, true); + } + else if (body1MovingRight) + { + body1.processX(-halfOverlap, 0, false, true); + body2.processX(halfOverlap, 0, true); + } + else + { + // Body1 moving same direction as Body2 + body1.processX(-halfOverlap, null, false, true); + body2.processX(halfOverlap, body1.velocity.x, true); + } + } + else if (side === 2) + { + // body1MovingRight && body1OnLeft + + if (body2Stationary) + { + body1.processX(-overlap, 0, false, true); + body2.processX(0, null, true); + } + else if (body2MovingLeft) + { + body1.processX(-halfOverlap, 0, false, true); + body2.processX(halfOverlap, 0, true); + } + else + { + // Body2 moving same direction as Body1 + body1.processX(-halfOverlap, body2.velocity.x, false, true); + body2.processX(halfOverlap, null, true); + } + } + else if (side === 3) + { + // body2MovingRight && body2OnLeft + + if (body1Stationary) + { + body1.processX(0, null, true); + body2.processX(-overlap, 0, false, true); + } + else if (body1MovingLeft) + { + body1.processX(halfOverlap, 0, true); + body2.processX(-halfOverlap, 0, false, true); + } + else + { + // Body1 moving same direction as Body2 + body1.processX(halfOverlap, body2.velocity.y, true); + body2.processX(-halfOverlap, null, false, true); + } + } + } + + return true; +}; + +/** + * This function is run when Body1 is Immovable and Body2 is not. + * + * @function Phaser.Physics.Arcade.ProcessX.RunImmovableBody1 + * @ignore + * @since 3.50.0 + * + * @param {number} blockedState - The block state value. + */ +var RunImmovableBody1 = function (blockedState) +{ + if (blockedState === 1) + { + // But Body2 cannot go anywhere either, so we cancel out velocity + // Separation happened in the block check + body2.velocity.x = 0; + } + else if (body1OnLeft) + { + body2.processX(overlap, body2FullImpact, true); + } + else + { + body2.processX(-overlap, body2FullImpact, false, true); + } + + // This is special case code that handles things like vertically moving platforms you can ride + if (body1.moves) + { + var body1Distance = body1.directControl ? (body1.y - body1.autoFrame.y) : (body1.y - body1.prev.y); + + body2.y += body1Distance * body1.friction.y; + body2._dy = body2.y - body2.prev.y; + } +}; + +/** + * This function is run when Body2 is Immovable and Body1 is not. + * + * @function Phaser.Physics.Arcade.ProcessX.RunImmovableBody2 + * @ignore + * @since 3.50.0 + * + * @param {number} blockedState - The block state value. + */ +var RunImmovableBody2 = function (blockedState) +{ + if (blockedState === 2) + { + // But Body1 cannot go anywhere either, so we cancel out velocity + // Separation happened in the block check + body1.velocity.x = 0; + } + else if (body2OnLeft) + { + body1.processX(overlap, body1FullImpact, true); + } + else + { + body1.processX(-overlap, body1FullImpact, false, true); + } + + // This is special case code that handles things like vertically moving platforms you can ride + if (body2.moves) + { + var body2Distance = body2.directControl ? (body2.y - body2.autoFrame.y) : (body2.y - body2.prev.y); + + body1.y += body2Distance * body2.friction.y; + body1._dy = body1.y - body1.prev.y; + } +}; + +/** + * @namespace Phaser.Physics.Arcade.ProcessX + * @ignore + */ + +module.exports = { + BlockCheck: BlockCheck, + Check: Check, + Set: Set, + Run: Run, + RunImmovableBody1: RunImmovableBody1, + RunImmovableBody2: RunImmovableBody2 +}; + + +/***/ }), + +/***/ 47962: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var body1; +var body2; +var body1Pushable; +var body2Pushable; +var body1MassImpact; +var body2MassImpact; +var body1FullImpact; +var body2FullImpact; +var body1MovingUp; +var body1MovingDown; +var body1Stationary; +var body2MovingUp; +var body2MovingDown; +var body2Stationary; +var body1OnTop; +var body2OnTop; +var overlap; + +/** + * Sets all of the local processing values and calculates the velocity exchanges. + * + * Then runs `BlockCheck` and returns the value from it. + * + * This method is called by `Phaser.Physics.Arcade.SeparateY` and should not be + * called directly. + * + * @function Phaser.Physics.Arcade.ProcessY.Set + * @ignore + * @since 3.50.0 + * + * @param {Phaser.Physics.Arcade.Body} b1 - The first Body to separate. + * @param {Phaser.Physics.Arcade.Body} b2 - The second Body to separate. + * @param {number} ov - The overlap value. + * + * @return {number} The BlockCheck result. 0 = not blocked. 1 = Body 1 blocked. 2 = Body 2 blocked. + */ +var Set = function (b1, b2, ov) +{ + body1 = b1; + body2 = b2; + + var v1 = body1.velocity.y; + var v2 = body2.velocity.y; + + body1Pushable = body1.pushable; + body1MovingUp = body1._dy < 0; + body1MovingDown = body1._dy > 0; + body1Stationary = body1._dy === 0; + body1OnTop = Math.abs(body1.bottom - body2.y) <= Math.abs(body2.bottom - body1.y); + body1FullImpact = v2 - v1 * body1.bounce.y; + + body2Pushable = body2.pushable; + body2MovingUp = body2._dy < 0; + body2MovingDown = body2._dy > 0; + body2Stationary = body2._dy === 0; + body2OnTop = !body1OnTop; + body2FullImpact = v1 - v2 * body2.bounce.y; + + // negative delta = up, positive delta = down (inc. gravity) + overlap = Math.abs(ov); + + return BlockCheck(); +}; + +/** + * Blocked Direction checks, because it doesn't matter if an object can be pushed + * or not, blocked is blocked. + * + * @function Phaser.Physics.Arcade.ProcessY.BlockCheck + * @ignore + * @since 3.50.0 + * + * @return {number} The BlockCheck result. 0 = not blocked. 1 = Body 1 blocked. 2 = Body 2 blocked. + */ +var BlockCheck = function () +{ + // Body1 is moving down and Body2 is blocked from going down any further + if (body1MovingDown && body1OnTop && body2.blocked.down) + { + body1.processY(-overlap, body1FullImpact, false, true); + + return 1; + } + + // Body1 is moving up and Body2 is blocked from going up any further + if (body1MovingUp && body2OnTop && body2.blocked.up) + { + body1.processY(overlap, body1FullImpact, true); + + return 1; + } + + // Body2 is moving down and Body1 is blocked from going down any further + if (body2MovingDown && body2OnTop && body1.blocked.down) + { + body2.processY(-overlap, body2FullImpact, false, true); + + return 2; + } + + // Body2 is moving up and Body1 is blocked from going up any further + if (body2MovingUp && body1OnTop && body1.blocked.up) + { + body2.processY(overlap, body2FullImpact, true); + + return 2; + } + + return 0; +}; + +/** + * The main check function. Runs through one of the four possible tests and returns the results. + * + * @function Phaser.Physics.Arcade.ProcessY.Check + * @ignore + * @since 3.50.0 + * + * @return {boolean} `true` if a check passed, otherwise `false`. + */ +var Check = function () +{ + var v1 = body1.velocity.y; + var v2 = body2.velocity.y; + + var nv1 = Math.sqrt((v2 * v2 * body2.mass) / body1.mass) * ((v2 > 0) ? 1 : -1); + var nv2 = Math.sqrt((v1 * v1 * body1.mass) / body2.mass) * ((v1 > 0) ? 1 : -1); + var avg = (nv1 + nv2) * 0.5; + + nv1 -= avg; + nv2 -= avg; + + body1MassImpact = avg + nv1 * body1.bounce.y; + body2MassImpact = avg + nv2 * body2.bounce.y; + + // Body1 hits Body2 on the bottom side + if (body1MovingUp && body2OnTop) + { + return Run(0); + } + + // Body2 hits Body1 on the bottom side + if (body2MovingUp && body1OnTop) + { + return Run(1); + } + + // Body1 hits Body2 on the top side + if (body1MovingDown && body1OnTop) + { + return Run(2); + } + + // Body2 hits Body1 on the top side + if (body2MovingDown && body2OnTop) + { + return Run(3); + } + + return false; +}; + +/** + * The main check function. Runs through one of the four possible tests and returns the results. + * + * @function Phaser.Physics.Arcade.ProcessY.Run + * @ignore + * @since 3.50.0 + * + * @param {number} side - The side to test. As passed in by the `Check` function. + * + * @return {boolean} Always returns `true`. + */ +var Run = function (side) +{ + if (body1Pushable && body2Pushable) + { + // Both pushable, or both moving at the same time, so equal rebound + overlap *= 0.5; + + if (side === 0 || side === 3) + { + // body1MovingUp && body2OnTop + // body2MovingDown && body2OnTop + body1.processY(overlap, body1MassImpact); + body2.processY(-overlap, body2MassImpact); + } + else + { + // body2MovingUp && body1OnTop + // body1MovingDown && body1OnTop + body1.processY(-overlap, body1MassImpact); + body2.processY(overlap, body2MassImpact); + } + } + else if (body1Pushable && !body2Pushable) + { + // Body1 pushable, Body2 not + + if (side === 0 || side === 3) + { + // body1MovingUp && body2OnTop + // body2MovingDown && body2OnTop + body1.processY(overlap, body1FullImpact, true); + } + else + { + // body2MovingUp && body1OnTop + // body1MovingDown && body1OnTop + body1.processY(-overlap, body1FullImpact, false, true); + } + } + else if (!body1Pushable && body2Pushable) + { + // Body2 pushable, Body1 not + + if (side === 0 || side === 3) + { + // body1MovingUp && body2OnTop + // body2MovingDown && body2OnTop + body2.processY(-overlap, body2FullImpact, false, true); + } + else + { + // body2MovingUp && body1OnTop + // body1MovingDown && body1OnTop + body2.processY(overlap, body2FullImpact, true); + } + } + else + { + // Neither body is pushable, so base it on movement + + var halfOverlap = overlap * 0.5; + + if (side === 0) + { + // body1MovingUp && body2OnTop + + if (body2Stationary) + { + body1.processY(overlap, 0, true); + body2.processY(0, null, false, true); + } + else if (body2MovingDown) + { + body1.processY(halfOverlap, 0, true); + body2.processY(-halfOverlap, 0, false, true); + } + else + { + // Body2 moving same direction as Body1 + body1.processY(halfOverlap, body2.velocity.y, true); + body2.processY(-halfOverlap, null, false, true); + } + } + else if (side === 1) + { + // body2MovingUp && body1OnTop + + if (body1Stationary) + { + body1.processY(0, null, false, true); + body2.processY(overlap, 0, true); + } + else if (body1MovingDown) + { + body1.processY(-halfOverlap, 0, false, true); + body2.processY(halfOverlap, 0, true); + } + else + { + // Body1 moving same direction as Body2 + body1.processY(-halfOverlap, null, false, true); + body2.processY(halfOverlap, body1.velocity.y, true); + } + } + else if (side === 2) + { + // body1MovingDown && body1OnTop + + if (body2Stationary) + { + body1.processY(-overlap, 0, false, true); + body2.processY(0, null, true); + } + else if (body2MovingUp) + { + body1.processY(-halfOverlap, 0, false, true); + body2.processY(halfOverlap, 0, true); + } + else + { + // Body2 moving same direction as Body1 + body1.processY(-halfOverlap, body2.velocity.y, false, true); + body2.processY(halfOverlap, null, true); + } + } + else if (side === 3) + { + // body2MovingDown && body2OnTop + + if (body1Stationary) + { + body1.processY(0, null, true); + body2.processY(-overlap, 0, false, true); + } + else if (body1MovingUp) + { + body1.processY(halfOverlap, 0, true); + body2.processY(-halfOverlap, 0, false, true); + } + else + { + // Body1 moving same direction as Body2 + body1.processY(halfOverlap, body2.velocity.y, true); + body2.processY(-halfOverlap, null, false, true); + } + } + } + + return true; +}; + +/** + * This function is run when Body1 is Immovable and Body2 is not. + * + * @function Phaser.Physics.Arcade.ProcessY.RunImmovableBody1 + * @ignore + * @since 3.50.0 + * + * @param {number} blockedState - The block state value. + */ +var RunImmovableBody1 = function (blockedState) +{ + if (blockedState === 1) + { + // But Body2 cannot go anywhere either, so we cancel out velocity + // Separation happened in the block check + body2.velocity.y = 0; + } + else if (body1OnTop) + { + body2.processY(overlap, body2FullImpact, true); + } + else + { + body2.processY(-overlap, body2FullImpact, false, true); + } + + // This is special case code that handles things like horizontally moving platforms you can ride + if (body1.moves) + { + var body1Distance = body1.directControl ? (body1.x - body1.autoFrame.x) : (body1.x - body1.prev.x); + + body2.x += body1Distance * body1.friction.x; + body2._dx = body2.x - body2.prev.x; + } +}; + +/** + * This function is run when Body2 is Immovable and Body1 is not. + * + * @function Phaser.Physics.Arcade.ProcessY.RunImmovableBody2 + * @ignore + * @since 3.50.0 + * + * @param {number} blockedState - The block state value. + */ +var RunImmovableBody2 = function (blockedState) +{ + if (blockedState === 2) + { + // But Body1 cannot go anywhere either, so we cancel out velocity + // Separation happened in the block check + body1.velocity.y = 0; + } + else if (body2OnTop) + { + body1.processY(overlap, body1FullImpact, true); + } + else + { + body1.processY(-overlap, body1FullImpact, false, true); + } + + // This is special case code that handles things like horizontally moving platforms you can ride + if (body2.moves) + { + var body2Distance = body2.directControl ? (body2.x - body2.autoFrame.x) : (body2.x - body2.prev.x); + + body1.x += body2Distance * body2.friction.x; + body1._dx = body1.x - body1.prev.x; + } +}; + +/** + * @namespace Phaser.Physics.Arcade.ProcessY + * @ignore + */ + +module.exports = { + BlockCheck: BlockCheck, + Check: Check, + Set: Set, + Run: Run, + RunImmovableBody1: RunImmovableBody1, + RunImmovableBody2: RunImmovableBody2 +}; + + +/***/ }), + +/***/ 14087: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetOverlapX = __webpack_require__(64897); +var ProcessX = __webpack_require__(3017); + +/** + * Separates two overlapping bodies on the X-axis (horizontally). + * + * Separation involves moving two overlapping bodies so they don't overlap anymore and adjusting their velocities based on their mass. This is a core part of collision detection. + * + * The bodies won't be separated if there is no horizontal overlap between them, if they are static, or if either one uses custom logic for its separation. + * + * @function Phaser.Physics.Arcade.SeparateX + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first Body to separate. + * @param {Phaser.Physics.Arcade.Body} body2 - The second Body to separate. + * @param {boolean} overlapOnly - If `true`, the bodies will only have their overlap data set and no separation will take place. + * @param {number} bias - A value to add to the delta value during overlap checking. Used to prevent sprite tunneling. + * @param {number} [overlap] - If given then this value will be used as the overlap and no check will be run. + * + * @return {boolean} `true` if the two bodies overlap vertically, otherwise `false`. + */ +var SeparateX = function (body1, body2, overlapOnly, bias, overlap) +{ + if (overlap === undefined) { overlap = GetOverlapX(body1, body2, overlapOnly, bias); } + + var body1Immovable = body1.immovable; + var body2Immovable = body2.immovable; + + // Can't separate two immovable bodies, or a body with its own custom separation logic + if (overlapOnly || overlap === 0 || (body1Immovable && body2Immovable) || body1.customSeparateX || body2.customSeparateX) + { + // return true if there was some overlap, otherwise false + return (overlap !== 0) || (body1.embedded && body2.embedded); + } + + var blockedState = ProcessX.Set(body1, body2, overlap); + + if (!body1Immovable && !body2Immovable) + { + if (blockedState > 0) + { + return true; + } + + return ProcessX.Check(); + } + else if (body1Immovable) + { + ProcessX.RunImmovableBody1(blockedState); + } + else if (body2Immovable) + { + ProcessX.RunImmovableBody2(blockedState); + } + + // If we got this far then there WAS overlap, and separation is complete, so return true + return true; +}; + +module.exports = SeparateX; + + +/***/ }), + +/***/ 89936: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetOverlapY = __webpack_require__(45170); +var ProcessY = __webpack_require__(47962); + +/** + * Separates two overlapping bodies on the Y-axis (vertically). + * + * Separation involves moving two overlapping bodies so they don't overlap anymore and adjusting their velocities based on their mass. This is a core part of collision detection. + * + * The bodies won't be separated if there is no vertical overlap between them, if they are static, or if either one uses custom logic for its separation. + * + * @function Phaser.Physics.Arcade.SeparateY + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first Body to separate. + * @param {Phaser.Physics.Arcade.Body} body2 - The second Body to separate. + * @param {boolean} overlapOnly - If `true`, the bodies will only have their overlap data set and no separation will take place. + * @param {number} bias - A value to add to the delta value during overlap checking. Used to prevent sprite tunneling. + * @param {number} [overlap] - If given then this value will be used as the overlap and no check will be run. + * + * @return {boolean} `true` if the two bodies overlap vertically, otherwise `false`. + */ +var SeparateY = function (body1, body2, overlapOnly, bias, overlap) +{ + if (overlap === undefined) { overlap = GetOverlapY(body1, body2, overlapOnly, bias); } + + var body1Immovable = body1.immovable; + var body2Immovable = body2.immovable; + + // Can't separate two immovable bodies, or a body with its own custom separation logic + if (overlapOnly || overlap === 0 || (body1Immovable && body2Immovable) || body1.customSeparateY || body2.customSeparateY) + { + // return true if there was some overlap, otherwise false + return (overlap !== 0) || (body1.embedded && body2.embedded); + } + + var blockedState = ProcessY.Set(body1, body2, overlap); + + if (!body1Immovable && !body2Immovable) + { + if (blockedState > 0) + { + return true; + } + + return ProcessY.Check(); + } + else if (body1Immovable) + { + ProcessY.RunImmovableBody1(blockedState); + } + else if (body2Immovable) + { + ProcessY.RunImmovableBody2(blockedState); + } + + // If we got this far then there WAS overlap, and separation is complete, so return true + return true; +}; + +module.exports = SeparateY; + + +/***/ }), + +/***/ 95829: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Either sets or creates the Arcade Body Collision object. + * + * Mostly only used internally. + * + * @function Phaser.Physics.Arcade.SetCollisionObject + * @since 3.70.0 + * + * @param {boolean} noneFlip - Is `none` true or false? + * @param {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} [data] - The collision data object to populate, or create if not given. + * + * @return {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} The collision data. + */ +var SetCollisionObject = function (noneFlip, data) +{ + if (data === undefined) { data = {}; } + + data.none = noneFlip; + data.up = false; + data.down = false; + data.left = false; + data.right = false; + + if (!noneFlip) + { + data.up = true; + data.down = true; + data.left = true; + data.right = true; + } + + return data; +}; + +module.exports = SetCollisionObject; + + +/***/ }), + +/***/ 72624: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CircleContains = __webpack_require__(87902); +var Class = __webpack_require__(83419); +var CollisionComponent = __webpack_require__(78389); +var CONST = __webpack_require__(37747); +var RectangleContains = __webpack_require__(37303); +var SetCollisionObject = __webpack_require__(95829); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Static Arcade Physics Body. + * + * A Static Body never moves, and isn't automatically synchronized with its parent Game Object. + * That means if you make any change to the parent's origin, position, or scale after creating or adding the body, you'll need to update the Static Body manually. + * + * A Static Body can collide with other Bodies, but is never moved by collisions. + * + * Its dynamic counterpart is {@link Phaser.Physics.Arcade.Body}. + * + * @class StaticBody + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Arcade.Components.Collision + * + * @param {Phaser.Physics.Arcade.World} world - The Arcade Physics simulation this Static Body belongs to. + * @param {Phaser.GameObjects.GameObject} [gameObject] - The Game Object this Body belongs to. As of Phaser 3.60 this is now optional. + */ +var StaticBody = new Class({ + + Mixins: [ + CollisionComponent + ], + + initialize: + + function StaticBody (world, gameObject) + { + var width = 64; + var height = 64; + + var dummyGameObject = { + x: 0, + y: 0, + angle: 0, + rotation: 0, + scaleX: 1, + scaleY: 1, + displayOriginX: 0, + displayOriginY: 0 + }; + + var hasGameObject = (gameObject !== undefined); + + if (hasGameObject && gameObject.displayWidth) + { + width = gameObject.displayWidth; + height = gameObject.displayHeight; + } + + if (!hasGameObject) + { + gameObject = dummyGameObject; + } + + /** + * The Arcade Physics simulation this Static Body belongs to. + * + * @name Phaser.Physics.Arcade.StaticBody#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The Game Object this Static Body belongs to. + * + * As of Phaser 3.60 this is now optional and can be undefined. + * + * @name Phaser.Physics.Arcade.StaticBody#gameObject + * @type {Phaser.GameObjects.GameObject} + * @since 3.0.0 + */ + this.gameObject = (hasGameObject) ? gameObject : undefined; + + /** + * A quick-test flag that signifies this is a Body, used in the World collision handler. + * + * @name Phaser.Physics.Arcade.StaticBody#isBody + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.isBody = true; + + /** + * Whether the Static Body's boundary is drawn to the debug display. + * + * @name Phaser.Physics.Arcade.StaticBody#debugShowBody + * @type {boolean} + * @since 3.0.0 + */ + this.debugShowBody = world.defaults.debugShowStaticBody; + + /** + * The color of this Static Body on the debug display. + * + * @name Phaser.Physics.Arcade.StaticBody#debugBodyColor + * @type {number} + * @since 3.0.0 + */ + this.debugBodyColor = world.defaults.staticBodyDebugColor; + + /** + * Whether this Static Body is updated by the physics simulation. + * + * @name Phaser.Physics.Arcade.StaticBody#enable + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.enable = true; + + /** + * Whether this Static Body's boundary is circular (`true`) or rectangular (`false`). + * + * @name Phaser.Physics.Arcade.StaticBody#isCircle + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isCircle = false; + + /** + * If this Static Body is circular, this is the radius of the boundary, as set by {@link Phaser.Physics.Arcade.StaticBody#setCircle}, in pixels. + * Equal to `halfWidth`. + * + * @name Phaser.Physics.Arcade.StaticBody#radius + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.radius = 0; + + /** + * The offset set by {@link Phaser.Physics.Arcade.StaticBody#setCircle} or {@link Phaser.Physics.Arcade.StaticBody#setSize}. + * + * This doesn't affect the Static Body's position, because a Static Body does not follow its Game Object. + * + * @name Phaser.Physics.Arcade.StaticBody#offset + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.0.0 + */ + this.offset = new Vector2(); + + /** + * The position of this Static Body within the simulation. + * + * @name Phaser.Physics.Arcade.StaticBody#position + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.position = new Vector2(gameObject.x - (width * gameObject.originX), gameObject.y - (height * gameObject.originY)); + + /** + * The width of the Static Body's boundary, in pixels. + * If the Static Body is circular, this is also the Static Body's diameter. + * + * @name Phaser.Physics.Arcade.StaticBody#width + * @type {number} + * @since 3.0.0 + */ + this.width = width; + + /** + * The height of the Static Body's boundary, in pixels. + * If the Static Body is circular, this is also the Static Body's diameter. + * + * @name Phaser.Physics.Arcade.StaticBody#height + * @type {number} + * @since 3.0.0 + */ + this.height = height; + + /** + * Half the Static Body's width, in pixels. + * If the Static Body is circular, this is also the Static Body's radius. + * + * @name Phaser.Physics.Arcade.StaticBody#halfWidth + * @type {number} + * @since 3.0.0 + */ + this.halfWidth = Math.abs(this.width / 2); + + /** + * Half the Static Body's height, in pixels. + * If the Static Body is circular, this is also the Static Body's radius. + * + * @name Phaser.Physics.Arcade.StaticBody#halfHeight + * @type {number} + * @since 3.0.0 + */ + this.halfHeight = Math.abs(this.height / 2); + + /** + * The center of the Static Body's boundary. + * This is the midpoint of its `position` (top-left corner) and its bottom-right corner. + * + * @name Phaser.Physics.Arcade.StaticBody#center + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.center = new Vector2(this.position.x + this.halfWidth, this.position.y + this.halfHeight); + + /** + * A constant zero velocity used by the Arcade Physics simulation for calculations. + * + * @name Phaser.Physics.Arcade.StaticBody#velocity + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.0.0 + */ + this.velocity = Vector2.ZERO; + + /** + * A constant `false` value expected by the Arcade Physics simulation. + * + * @name Phaser.Physics.Arcade.StaticBody#allowGravity + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.allowGravity = false; + + /** + * Gravitational force applied specifically to this Body. Values are in pixels per second squared. Always zero for a Static Body. + * + * @name Phaser.Physics.Arcade.StaticBody#gravity + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.0.0 + */ + this.gravity = Vector2.ZERO; + + /** + * Rebound, or restitution, following a collision, relative to 1. Always zero for a Static Body. + * + * @name Phaser.Physics.Arcade.StaticBody#bounce + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.0.0 + */ + this.bounce = Vector2.ZERO; + + // If true this Body will dispatch events + + /** + * Whether the simulation emits a `worldbounds` event when this StaticBody collides with the world boundary. + * Always false for a Static Body. (Static Bodies never collide with the world boundary and never trigger a `worldbounds` event.) + * + * @name Phaser.Physics.Arcade.StaticBody#onWorldBounds + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.onWorldBounds = false; + + /** + * Whether the simulation emits a `collide` event when this StaticBody collides with another. + * + * @name Phaser.Physics.Arcade.StaticBody#onCollide + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.onCollide = false; + + /** + * Whether the simulation emits an `overlap` event when this StaticBody overlaps with another. + * + * @name Phaser.Physics.Arcade.StaticBody#onOverlap + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.onOverlap = false; + + /** + * The StaticBody's inertia, relative to a default unit (1). With `bounce`, this affects the exchange of momentum (velocities) during collisions. + * + * @name Phaser.Physics.Arcade.StaticBody#mass + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.mass = 1; + + /** + * Whether this object can be moved by collisions with another body. + * + * @name Phaser.Physics.Arcade.StaticBody#immovable + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.immovable = true; + + /** + * Sets if this Body can be pushed by another Body. + * + * A body that cannot be pushed will reflect back all of the velocity it is given to the + * colliding body. If that body is also not pushable, then the separation will be split + * between them evenly. + * + * If you want your body to never move or seperate at all, see the `setImmovable` method. + * + * By default, Static Bodies are not pushable. + * + * @name Phaser.Physics.Arcade.StaticBody#pushable + * @type {boolean} + * @default false + * @since 3.50.0 + * @see Phaser.GameObjects.Components.Pushable#setPushable + */ + this.pushable = false; + + /** + * A flag disabling the default horizontal separation of colliding bodies. Pass your own `collideHandler` to the collider. + * + * @name Phaser.Physics.Arcade.StaticBody#customSeparateX + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.customSeparateX = false; + + /** + * A flag disabling the default vertical separation of colliding bodies. Pass your own `collideHandler` to the collider. + * + * @name Phaser.Physics.Arcade.StaticBody#customSeparateY + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.customSeparateY = false; + + /** + * The amount of horizontal overlap (before separation), if this Body is colliding with another. + * + * @name Phaser.Physics.Arcade.StaticBody#overlapX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.overlapX = 0; + + /** + * The amount of vertical overlap (before separation), if this Body is colliding with another. + * + * @name Phaser.Physics.Arcade.StaticBody#overlapY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.overlapY = 0; + + /** + * The amount of overlap (before separation), if this StaticBody is circular and colliding with another circular body. + * + * @name Phaser.Physics.Arcade.StaticBody#overlapR + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.overlapR = 0; + + /** + * Whether this StaticBody has ever overlapped with another while both were not moving. + * + * @name Phaser.Physics.Arcade.StaticBody#embedded + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.embedded = false; + + /** + * Whether this StaticBody interacts with the world boundary. + * Always false for a Static Body. (Static Bodies never collide with the world boundary.) + * + * @name Phaser.Physics.Arcade.StaticBody#collideWorldBounds + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.collideWorldBounds = false; + + /** + * Whether this StaticBody is checked for collisions and for which directions. You can set `checkCollision.none = false` to disable collision checks. + * + * @name Phaser.Physics.Arcade.StaticBody#checkCollision + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + */ + this.checkCollision = SetCollisionObject(false); + + /** + * This property is kept for compatibility with Dynamic Bodies. + * Avoid using it. + * + * @name Phaser.Physics.Arcade.StaticBody#touching + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + */ + this.touching = SetCollisionObject(true); + + /** + * This property is kept for compatibility with Dynamic Bodies. + * Avoid using it. + * The values are always false for a Static Body. + * + * @name Phaser.Physics.Arcade.StaticBody#wasTouching + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + */ + this.wasTouching = SetCollisionObject(true); + + /** + * This property is kept for compatibility with Dynamic Bodies. + * Avoid using it. + * + * @name Phaser.Physics.Arcade.StaticBody#blocked + * @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision} + * @since 3.0.0 + */ + this.blocked = SetCollisionObject(true); + + /** + * The StaticBody's physics type (static by default). + * + * @name Phaser.Physics.Arcade.StaticBody#physicsType + * @type {number} + * @default Phaser.Physics.Arcade.STATIC_BODY + * @since 3.0.0 + */ + this.physicsType = CONST.STATIC_BODY; + + /** + * The Arcade Physics Body Collision Category. + * + * This can be set to any valid collision bitfield value. + * + * See the `setCollisionCategory` method for more details. + * + * @name Phaser.Physics.Arcade.StaticBody#collisionCategory + * @type {number} + * @since 3.70.0 + */ + this.collisionCategory = 0x0001; + + /** + * The Arcade Physics Body Collision Mask. + * + * See the `setCollidesWith` method for more details. + * + * @name Phaser.Physics.Arcade.StaticBody#collisionMask + * @type {number} + * @since 3.70.0 + */ + this.collisionMask = 1; + + /** + * The calculated change in the Static Body's horizontal position during the current step. + * For a static body this is always zero. + * + * @name Phaser.Physics.Arcade.StaticBody#_dx + * @type {number} + * @private + * @default 0 + * @since 3.10.0 + */ + this._dx = 0; + + /** + * The calculated change in the Static Body's vertical position during the current step. + * For a static body this is always zero. + * + * @name Phaser.Physics.Arcade.StaticBody#_dy + * @type {number} + * @private + * @default 0 + * @since 3.10.0 + */ + this._dy = 0; + }, + + /** + * Changes the Game Object this Body is bound to. + * + * First it removes its reference from the old Game Object, then sets the new one. + * + * This body will be resized to match the frame dimensions of the given Game Object, if it has a texture frame. + * You can optionally update the position and dimensions of this Body to reflect that of the new Game Object. + * + * @method Phaser.Physics.Arcade.StaticBody#setGameObject + * @since 3.1.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to assign this Body to. + * @param {boolean} [update=true] - Reposition and resize this Body to match the new Game Object? + * @param {boolean} [enable=true] - Automatically enable this Body for physics. + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + * + * @see Phaser.Physics.Arcade.StaticBody#updateFromGameObject + */ + setGameObject: function (gameObject, update, enable) + { + if (update === undefined) { update = true; } + if (enable === undefined) { enable = true; } + + if (!gameObject || !gameObject.hasTransformComponent) + { + // We need a valid Game Object to continue + return this; + } + + var world = this.world; + + if (this.gameObject && this.gameObject.body) + { + world.disable(this.gameObject); + + // Disconnect the current Game Object + this.gameObject.body = null; + } + + if (gameObject.body) + { + // Remove the body from the world, but don't disable the Game Object + world.disable(gameObject); + } + + this.gameObject = gameObject; + + gameObject.body = this; + + // This will remove the body from the tree, if it's in there and add the new one in + this.setSize(); + + if (update) + { + this.updateFromGameObject(); + } + + this.enable = enable; + + return this; + }, + + /** + * Syncs the Static Body's position and size with its parent Game Object. + * + * @method Phaser.Physics.Arcade.StaticBody#updateFromGameObject + * @since 3.1.0 + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + */ + updateFromGameObject: function () + { + this.world.staticTree.remove(this); + + var gameObject = this.gameObject; + + gameObject.getTopLeft(this.position); + + this.width = gameObject.displayWidth; + this.height = gameObject.displayHeight; + + this.halfWidth = Math.abs(this.width / 2); + this.halfHeight = Math.abs(this.height / 2); + + this.center.set(this.position.x + this.halfWidth, this.position.y + this.halfHeight); + + this.world.staticTree.insert(this); + + return this; + }, + + /** + * Positions the Static Body at an offset from its Game Object. + * + * @method Phaser.Physics.Arcade.StaticBody#setOffset + * @since 3.4.0 + * + * @param {number} x - The horizontal offset of the Static Body from the Game Object's `x`. + * @param {number} y - The vertical offset of the Static Body from the Game Object's `y`. + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + */ + setOffset: function (x, y) + { + if (y === undefined) { y = x; } + + this.world.staticTree.remove(this); + + this.position.x -= this.offset.x; + this.position.y -= this.offset.y; + + this.offset.set(x, y); + + this.position.x += this.offset.x; + this.position.y += this.offset.y; + + this.updateCenter(); + + this.world.staticTree.insert(this); + + return this; + }, + + /** + * Sets the size of the Static Body. + * When `center` is true, also repositions it. + * Resets the width and height to match current frame, if no width and height provided and a frame is found. + * + * @method Phaser.Physics.Arcade.StaticBody#setSize + * @since 3.0.0 + * + * @param {number} [width] - The width of the Static Body in pixels. Cannot be zero. If not given, and the parent Game Object has a frame, it will use the frame width. + * @param {number} [height] - The height of the Static Body in pixels. Cannot be zero. If not given, and the parent Game Object has a frame, it will use the frame height. + * @param {boolean} [center=true] - Place the Static Body's center on its Game Object's center. Only works if the Game Object has the `getCenter` method. + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + */ + setSize: function (width, height, center) + { + if (center === undefined) { center = true; } + + var gameObject = this.gameObject; + + if (gameObject && gameObject.frame) + { + if (!width) + { + width = gameObject.frame.realWidth; + } + + if (!height) + { + height = gameObject.frame.realHeight; + } + } + + this.world.staticTree.remove(this); + + this.width = width; + this.height = height; + + this.halfWidth = Math.floor(width / 2); + this.halfHeight = Math.floor(height / 2); + + if (center && gameObject && gameObject.getCenter) + { + var ox = gameObject.displayWidth / 2; + var oy = gameObject.displayHeight / 2; + + this.position.x -= this.offset.x; + this.position.y -= this.offset.y; + + this.offset.set(ox - this.halfWidth, oy - this.halfHeight); + + this.position.x += this.offset.x; + this.position.y += this.offset.y; + } + + this.updateCenter(); + + this.isCircle = false; + this.radius = 0; + + this.world.staticTree.insert(this); + + return this; + }, + + /** + * Sets this Static Body to have a circular body and sets its size and position. + * + * @method Phaser.Physics.Arcade.StaticBody#setCircle + * @since 3.0.0 + * + * @param {number} radius - The radius of the StaticBody, in pixels. + * @param {number} [offsetX] - The horizontal offset of the StaticBody from its Game Object, in pixels. + * @param {number} [offsetY] - The vertical offset of the StaticBody from its Game Object, in pixels. + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + */ + setCircle: function (radius, offsetX, offsetY) + { + if (offsetX === undefined) { offsetX = this.offset.x; } + if (offsetY === undefined) { offsetY = this.offset.y; } + + if (radius > 0) + { + this.world.staticTree.remove(this); + + this.isCircle = true; + + this.radius = radius; + + this.width = radius * 2; + this.height = radius * 2; + + this.halfWidth = Math.floor(this.width / 2); + this.halfHeight = Math.floor(this.height / 2); + + this.offset.set(offsetX, offsetY); + + this.updateCenter(); + + this.world.staticTree.insert(this); + } + else + { + this.isCircle = false; + } + + return this; + }, + + /** + * Updates the StaticBody's `center` from its `position` and dimensions. + * + * @method Phaser.Physics.Arcade.StaticBody#updateCenter + * @since 3.0.0 + */ + updateCenter: function () + { + this.center.set(this.position.x + this.halfWidth, this.position.y + this.halfHeight); + }, + + /** + * Resets this Static Body to its parent Game Object's position. + * + * If `x` and `y` are given, the parent Game Object is placed there and this Static Body is centered on it. + * Otherwise this Static Body is centered on the Game Object's current position. + * + * @method Phaser.Physics.Arcade.StaticBody#reset + * @since 3.0.0 + * + * @param {number} [x] - The x coordinate to reset the body to. If not given will use the parent Game Object's coordinate. + * @param {number} [y] - The y coordinate to reset the body to. If not given will use the parent Game Object's coordinate. + */ + reset: function (x, y) + { + var gameObject = this.gameObject; + + if (x === undefined) { x = gameObject.x; } + if (y === undefined) { y = gameObject.y; } + + this.world.staticTree.remove(this); + + gameObject.setPosition(x, y); + + gameObject.getTopLeft(this.position); + + this.position.x += this.offset.x; + this.position.y += this.offset.y; + + this.updateCenter(); + + this.world.staticTree.insert(this); + }, + + /** + * NOOP function. A Static Body cannot be stopped. + * + * @method Phaser.Physics.Arcade.StaticBody#stop + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + */ + stop: function () + { + return this; + }, + + /** + * Returns the x and y coordinates of the top left and bottom right points of the StaticBody. + * + * @method Phaser.Physics.Arcade.StaticBody#getBounds + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeBodyBounds} obj - The object which will hold the coordinates of the bounds. + * + * @return {Phaser.Types.Physics.Arcade.ArcadeBodyBounds} The same object that was passed with `x`, `y`, `right` and `bottom` values matching the respective values of the StaticBody. + */ + getBounds: function (obj) + { + obj.x = this.x; + obj.y = this.y; + obj.right = this.right; + obj.bottom = this.bottom; + + return obj; + }, + + /** + * Checks to see if a given x,y coordinate is colliding with this Static Body. + * + * @method Phaser.Physics.Arcade.StaticBody#hitTest + * @since 3.0.0 + * + * @param {number} x - The x coordinate to check against this body. + * @param {number} y - The y coordinate to check against this body. + * + * @return {boolean} `true` if the given coordinate lies within this body, otherwise `false`. + */ + hitTest: function (x, y) + { + return (this.isCircle) ? CircleContains(this, x, y) : RectangleContains(this, x, y); + }, + + /** + * NOOP + * + * @method Phaser.Physics.Arcade.StaticBody#postUpdate + * @since 3.12.0 + */ + postUpdate: function () + { + }, + + /** + * The absolute (non-negative) change in this StaticBody's horizontal position from the previous step. Always zero. + * + * @method Phaser.Physics.Arcade.StaticBody#deltaAbsX + * @since 3.0.0 + * + * @return {number} Always zero for a Static Body. + */ + deltaAbsX: function () + { + return 0; + }, + + /** + * The absolute (non-negative) change in this StaticBody's vertical position from the previous step. Always zero. + * + * @method Phaser.Physics.Arcade.StaticBody#deltaAbsY + * @since 3.0.0 + * + * @return {number} Always zero for a Static Body. + */ + deltaAbsY: function () + { + return 0; + }, + + /** + * The change in this StaticBody's horizontal position from the previous step. Always zero. + * + * @method Phaser.Physics.Arcade.StaticBody#deltaX + * @since 3.0.0 + * + * @return {number} The change in this StaticBody's velocity from the previous step. Always zero. + */ + deltaX: function () + { + return 0; + }, + + /** + * The change in this StaticBody's vertical position from the previous step. Always zero. + * + * @method Phaser.Physics.Arcade.StaticBody#deltaY + * @since 3.0.0 + * + * @return {number} The change in this StaticBody's velocity from the previous step. Always zero. + */ + deltaY: function () + { + return 0; + }, + + /** + * The change in this StaticBody's rotation from the previous step. Always zero. + * + * @method Phaser.Physics.Arcade.StaticBody#deltaZ + * @since 3.0.0 + * + * @return {number} The change in this StaticBody's rotation from the previous step. Always zero. + */ + deltaZ: function () + { + return 0; + }, + + /** + * Disables this Body and marks it for destruction during the next step. + * + * @method Phaser.Physics.Arcade.StaticBody#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.enable = false; + + this.world.pendingDestroy.add(this); + }, + + /** + * Draws a graphical representation of the StaticBody for visual debugging purposes. + * + * @method Phaser.Physics.Arcade.StaticBody#drawDebug + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Graphics} graphic - The Graphics object to use for the debug drawing of the StaticBody. + */ + drawDebug: function (graphic) + { + var pos = this.position; + + var x = pos.x + this.halfWidth; + var y = pos.y + this.halfHeight; + + if (this.debugShowBody) + { + graphic.lineStyle(graphic.defaultStrokeWidth, this.debugBodyColor, 1); + + if (this.isCircle) + { + graphic.strokeCircle(x, y, this.width / 2); + } + else + { + graphic.strokeRect(pos.x, pos.y, this.width, this.height); + } + + } + }, + + /** + * Indicates whether the StaticBody is going to be showing a debug visualization during postUpdate. + * + * @method Phaser.Physics.Arcade.StaticBody#willDrawDebug + * @since 3.0.0 + * + * @return {boolean} Whether or not the StaticBody is going to show the debug visualization during postUpdate. + */ + willDrawDebug: function () + { + return this.debugShowBody; + }, + + /** + * Sets the Mass of the StaticBody. Will set the Mass to 0.1 if the value passed is less than or equal to zero. + * + * @method Phaser.Physics.Arcade.StaticBody#setMass + * @since 3.0.0 + * + * @param {number} value - The value to set the Mass to. Values of zero or less are changed to 0.1. + * + * @return {Phaser.Physics.Arcade.StaticBody} This Static Body object. + */ + setMass: function (value) + { + if (value <= 0) + { + // Causes havoc otherwise + value = 0.1; + } + + this.mass = value; + + return this; + }, + + /** + * The x coordinate of the StaticBody. + * + * @name Phaser.Physics.Arcade.StaticBody#x + * @type {number} + * @since 3.0.0 + */ + x: { + + get: function () + { + return this.position.x; + }, + + set: function (value) + { + this.world.staticTree.remove(this); + + this.position.x = value; + + this.world.staticTree.insert(this); + } + + }, + + /** + * The y coordinate of the StaticBody. + * + * @name Phaser.Physics.Arcade.StaticBody#y + * @type {number} + * @since 3.0.0 + */ + y: { + + get: function () + { + return this.position.y; + }, + + set: function (value) + { + this.world.staticTree.remove(this); + + this.position.y = value; + + this.world.staticTree.insert(this); + } + + }, + + /** + * Returns the left-most x coordinate of the area of the StaticBody. + * + * @name Phaser.Physics.Arcade.StaticBody#left + * @type {number} + * @readonly + * @since 3.0.0 + */ + left: { + + get: function () + { + return this.position.x; + } + + }, + + /** + * The right-most x coordinate of the area of the StaticBody. + * + * @name Phaser.Physics.Arcade.StaticBody#right + * @type {number} + * @readonly + * @since 3.0.0 + */ + right: { + + get: function () + { + return this.position.x + this.width; + } + + }, + + /** + * The highest y coordinate of the area of the StaticBody. + * + * @name Phaser.Physics.Arcade.StaticBody#top + * @type {number} + * @readonly + * @since 3.0.0 + */ + top: { + + get: function () + { + return this.position.y; + } + + }, + + /** + * The lowest y coordinate of the area of the StaticBody. (y + height) + * + * @name Phaser.Physics.Arcade.StaticBody#bottom + * @type {number} + * @readonly + * @since 3.0.0 + */ + bottom: { + + get: function () + { + return this.position.y + this.height; + } + + } + +}); + +module.exports = StaticBody; + + +/***/ }), + +/***/ 71464: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArcadeSprite = __webpack_require__(13759); +var Class = __webpack_require__(83419); +var CollisionComponent = __webpack_require__(78389); +var CONST = __webpack_require__(37747); +var GetFastValue = __webpack_require__(95540); +var Group = __webpack_require__(26479); +var IsPlainObject = __webpack_require__(41212); + +/** + * @classdesc + * An Arcade Physics Static Group object. + * + * All Game Objects created by or added to this Group will automatically be given static Arcade Physics bodies, if they have no body. + * + * Its dynamic counterpart is {@link Phaser.Physics.Arcade.Group}. + * + * @class StaticGroup + * @extends Phaser.GameObjects.Group + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Arcade.Components.Collision + * + * @param {Phaser.Physics.Arcade.World} world - The physics simulation. + * @param {Phaser.Scene} scene - The scene this group belongs to. + * @param {(Phaser.GameObjects.GameObject[]|Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig)} [children] - Game Objects to add to this group; or the `config` argument. + * @param {Phaser.Types.GameObjects.Group.GroupConfig|Phaser.Types.GameObjects.Group.GroupCreateConfig} [config] - Settings for this group. + */ +var StaticPhysicsGroup = new Class({ + + Extends: Group, + + Mixins: [ + CollisionComponent + ], + + initialize: + + function StaticPhysicsGroup (world, scene, children, config) + { + if (!children && !config) + { + config = { + internalCreateCallback: this.createCallbackHandler, + internalRemoveCallback: this.removeCallbackHandler, + createMultipleCallback: this.createMultipleCallbackHandler, + classType: ArcadeSprite + }; + } + else if (IsPlainObject(children)) + { + // children is a plain object, so swizzle them: + config = children; + children = null; + + config.internalCreateCallback = this.createCallbackHandler; + config.internalRemoveCallback = this.removeCallbackHandler; + config.createMultipleCallback = this.createMultipleCallbackHandler; + config.classType = GetFastValue(config, 'classType', ArcadeSprite); + } + else if (Array.isArray(children) && IsPlainObject(children[0])) + { + // children is an array of plain objects + config = children; + children = null; + + config.forEach(function (singleConfig) + { + singleConfig.internalCreateCallback = this.createCallbackHandler; + singleConfig.internalRemoveCallback = this.removeCallbackHandler; + singleConfig.createMultipleCallback = this.createMultipleCallbackHandler; + singleConfig.classType = GetFastValue(singleConfig, 'classType', ArcadeSprite); + }); + } + else + { + // config is not defined and children is not a plain object nor an array of plain objects + config = { + internalCreateCallback: this.createCallbackHandler, + internalRemoveCallback: this.removeCallbackHandler + }; + } + + /** + * The physics simulation. + * + * @name Phaser.Physics.Arcade.StaticGroup#world + * @type {Phaser.Physics.Arcade.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The scene this group belongs to. + * + * @name Phaser.Physics.Arcade.StaticGroup#physicsType + * @type {number} + * @default Phaser.Physics.Arcade.STATIC_BODY + * @since 3.0.0 + */ + this.physicsType = CONST.STATIC_BODY; + + /** + * The Arcade Physics Static Group Collision Category. + * + * This can be set to any valid collision bitfield value. + * + * See the `setCollisionCategory` method for more details. + * + * @name Phaser.Physics.Arcade.StaticGroup#collisionCategory + * @type {number} + * @since 3.70.0 + */ + this.collisionCategory = 0x0001; + + /** + * The Arcade Physics Static Group Collision Mask. + * + * See the `setCollidesWith` method for more details. + * + * @name Phaser.Physics.Arcade.StaticGroup#collisionMask + * @type {number} + * @since 3.70.0 + */ + this.collisionMask = 1; + + Group.call(this, scene, children, config); + + /** + * A textual representation of this Game Object. + * Used internally by Phaser but is available for your own custom classes to populate. + * + * @name Phaser.Physics.Arcade.StaticGroup#type + * @type {string} + * @default 'StaticPhysicsGroup' + * @since 3.21.0 + */ + this.type = 'StaticPhysicsGroup'; + }, + + /** + * Adds a static physics body to the new group member (if it lacks one) and adds it to the simulation. + * + * @method Phaser.Physics.Arcade.StaticGroup#createCallbackHandler + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The new group member. + * + * @see Phaser.Physics.Arcade.World#enableBody + */ + createCallbackHandler: function (child) + { + if (!child.body) + { + this.world.enableBody(child, CONST.STATIC_BODY); + } + }, + + /** + * Disables the group member's physics body, removing it from the simulation. + * + * @method Phaser.Physics.Arcade.StaticGroup#removeCallbackHandler + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} child - The group member being removed. + * + * @see Phaser.Physics.Arcade.World#disableBody + */ + removeCallbackHandler: function (child) + { + if (child.body) + { + this.world.disableBody(child); + } + }, + + /** + * Refreshes the group. + * + * @method Phaser.Physics.Arcade.StaticGroup#createMultipleCallbackHandler + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject[]} entries - The newly created group members. + * + * @see Phaser.Physics.Arcade.StaticGroup#refresh + */ + createMultipleCallbackHandler: function () + { + this.refresh(); + }, + + /** + * Resets each Body to the position of its parent Game Object. + * Body sizes aren't changed (use {@link Phaser.Physics.Arcade.Components.Enable#refreshBody} for that). + * + * @method Phaser.Physics.Arcade.StaticGroup#refresh + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.StaticGroup} This group. + * + * @see Phaser.Physics.Arcade.StaticBody#reset + */ + refresh: function () + { + var children = Array.from(this.children); + + for (var i = 0; i < children.length; i++) + { + children[i].body.reset(); + } + + return this; + } + +}); + +module.exports = StaticPhysicsGroup; + + +/***/ }), + +/***/ 82248: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AngleBetweenPoints = __webpack_require__(55495); +var Body = __webpack_require__(37742); +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Collider = __webpack_require__(79342); +var CONST = __webpack_require__(37747); +var DistanceBetween = __webpack_require__(20339); +var DistanceBetweenPoints = __webpack_require__(52816); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(63012); +var FuzzyEqual = __webpack_require__(43855); +var FuzzyGreaterThan = __webpack_require__(5470); +var FuzzyLessThan = __webpack_require__(94977); +var GetOverlapX = __webpack_require__(64897); +var GetOverlapY = __webpack_require__(45170); +var GetTilesWithinWorldXY = __webpack_require__(96523); +var GetValue = __webpack_require__(35154); +var MATH_CONST = __webpack_require__(36383); +var ProcessQueue = __webpack_require__(25774); +var ProcessTileCallbacks = __webpack_require__(96602); +var Rectangle = __webpack_require__(87841); +var RTree = __webpack_require__(59542); +var SeparateTile = __webpack_require__(40012); +var SeparateX = __webpack_require__(14087); +var SeparateY = __webpack_require__(89936); +var StaticBody = __webpack_require__(72624); +var TileIntersectsBody = __webpack_require__(2483); +var TransformMatrix = __webpack_require__(61340); +var Vector2 = __webpack_require__(26099); +var Wrap = __webpack_require__(15994); + +/** + * @classdesc + * The Arcade Physics World. + * + * The World is responsible for creating, managing, colliding and updating all of the bodies within it. + * + * An instance of the World belongs to a Phaser.Scene and is accessed via the property `physics.world`. + * + * @class World + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Physics.Arcade + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this World instance belongs. + * @param {Phaser.Types.Physics.Arcade.ArcadeWorldConfig} config - An Arcade Physics Configuration object. + */ +var World = new Class({ + + Extends: EventEmitter, + + initialize: + + function World (scene, config) + { + EventEmitter.call(this); + + /** + * The Scene this simulation belongs to. + * + * @name Phaser.Physics.Arcade.World#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * Dynamic Bodies in this simulation. + * + * @name Phaser.Physics.Arcade.World#bodies + * @type {Set.} + * @since 3.0.0 + */ + this.bodies = new Set(); + + /** + * Static Bodies in this simulation. + * + * @name Phaser.Physics.Arcade.World#staticBodies + * @type {Set.} + * @since 3.0.0 + */ + this.staticBodies = new Set(); + + /** + * Static Bodies marked for deletion. + * + * @name Phaser.Physics.Arcade.World#pendingDestroy + * @type {Set.<(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)>} + * @since 3.1.0 + */ + this.pendingDestroy = new Set(); + + /** + * This simulation's collision processors. + * + * @name Phaser.Physics.Arcade.World#colliders + * @type {Phaser.Structs.ProcessQueue.} + * @since 3.0.0 + */ + this.colliders = new ProcessQueue(); + + /** + * Acceleration of Bodies due to gravity, in pixels per second. + * + * @name Phaser.Physics.Arcade.World#gravity + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.gravity = new Vector2(GetValue(config, 'gravity.x', 0), GetValue(config, 'gravity.y', 0)); + + /** + * A boundary constraining Bodies. + * + * @name Phaser.Physics.Arcade.World#bounds + * @type {Phaser.Geom.Rectangle} + * @since 3.0.0 + */ + this.bounds = new Rectangle( + GetValue(config, 'x', 0), + GetValue(config, 'y', 0), + GetValue(config, 'width', scene.sys.scale.width), + GetValue(config, 'height', scene.sys.scale.height) + ); + + /** + * The boundary edges that Bodies can collide with. + * + * @name Phaser.Physics.Arcade.World#checkCollision + * @type {Phaser.Types.Physics.Arcade.CheckCollisionObject} + * @since 3.0.0 + */ + this.checkCollision = { + up: GetValue(config, 'checkCollision.up', true), + down: GetValue(config, 'checkCollision.down', true), + left: GetValue(config, 'checkCollision.left', true), + right: GetValue(config, 'checkCollision.right', true) + }; + + /** + * The number of physics steps to be taken per second. + * + * This property is read-only. Use the `setFPS` method to modify it at run-time. + * + * @name Phaser.Physics.Arcade.World#fps + * @readonly + * @type {number} + * @default 60 + * @since 3.10.0 + */ + this.fps = GetValue(config, 'fps', 60); + + /** + * Should Physics use a fixed update time-step (true) or sync to the render fps (false)?. + * False value of this property disables fps and timeScale properties. + * + * @name Phaser.Physics.Arcade.World#fixedStep + * @type {boolean} + * @default true + * @since 3.23.0 + */ + this.fixedStep = GetValue(config, 'fixedStep', true); + + /** + * The amount of elapsed ms since the last frame. + * + * @name Phaser.Physics.Arcade.World#_elapsed + * @private + * @type {number} + * @since 3.10.0 + */ + this._elapsed = 0; + + /** + * Internal frame time value. + * + * @name Phaser.Physics.Arcade.World#_frameTime + * @private + * @type {number} + * @since 3.10.0 + */ + this._frameTime = 1 / this.fps; + + /** + * Internal frame time ms value. + * + * @name Phaser.Physics.Arcade.World#_frameTimeMS + * @private + * @type {number} + * @since 3.10.0 + */ + this._frameTimeMS = 1000 * this._frameTime; + + /** + * The number of steps that took place in the last frame. + * + * @name Phaser.Physics.Arcade.World#stepsLastFrame + * @readonly + * @type {number} + * @since 3.10.0 + */ + this.stepsLastFrame = 0; + + /** + * Scaling factor applied to the frame rate. + * + * - 1.0 = normal speed + * - 2.0 = half speed + * - 0.5 = double speed + * + * @name Phaser.Physics.Arcade.World#timeScale + * @type {number} + * @default 1 + * @since 3.10.0 + */ + this.timeScale = GetValue(config, 'timeScale', 1); + + /** + * The maximum absolute difference of a Body's per-step velocity and its overlap with another Body that will result in separation on *each axis*. + * Larger values favor separation. + * Smaller values favor no separation. + * + * @name Phaser.Physics.Arcade.World#OVERLAP_BIAS + * @type {number} + * @default 4 + * @since 3.0.0 + */ + this.OVERLAP_BIAS = GetValue(config, 'overlapBias', 4); + + /** + * The maximum absolute value of a Body's overlap with a tile that will result in separation on *each axis*. + * Larger values favor separation. + * Smaller values favor no separation. + * The optimum value may be similar to the tile size. + * + * @name Phaser.Physics.Arcade.World#TILE_BIAS + * @type {number} + * @default 16 + * @since 3.0.0 + */ + this.TILE_BIAS = GetValue(config, 'tileBias', 16); + + /** + * Always separate overlapping Bodies horizontally before vertically. + * False (the default) means Bodies are first separated on the axis of greater gravity, or the vertical axis if neither is greater. + * + * @name Phaser.Physics.Arcade.World#forceX + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.forceX = GetValue(config, 'forceX', false); + + /** + * Whether the simulation advances with the game loop. + * + * @name Phaser.Physics.Arcade.World#isPaused + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.isPaused = GetValue(config, 'isPaused', false); + + /** + * Temporary total of colliding Bodies. + * + * @name Phaser.Physics.Arcade.World#_total + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._total = 0; + + /** + * Enables the debug display. + * + * @name Phaser.Physics.Arcade.World#drawDebug + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.drawDebug = GetValue(config, 'debug', false); + + /** + * The graphics object drawing the debug display. + * + * @name Phaser.Physics.Arcade.World#debugGraphic + * @type {Phaser.GameObjects.Graphics} + * @since 3.0.0 + */ + this.debugGraphic; + + /** + * Default debug display settings for new Bodies. + * + * @name Phaser.Physics.Arcade.World#defaults + * @type {Phaser.Types.Physics.Arcade.ArcadeWorldDefaults} + * @since 3.0.0 + */ + this.defaults = { + debugShowBody: GetValue(config, 'debugShowBody', true), + debugShowStaticBody: GetValue(config, 'debugShowStaticBody', true), + debugShowVelocity: GetValue(config, 'debugShowVelocity', true), + bodyDebugColor: GetValue(config, 'debugBodyColor', 0xff00ff), + staticBodyDebugColor: GetValue(config, 'debugStaticBodyColor', 0x0000ff), + velocityDebugColor: GetValue(config, 'debugVelocityColor', 0x00ff00) + }; + + /** + * The maximum number of items per node on the RTree. + * + * This is ignored if `useTree` is `false`. If you have a large number of bodies in + * your world then you may find search performance improves by increasing this value, + * to allow more items per node and less node division. + * + * @name Phaser.Physics.Arcade.World#maxEntries + * @type {number} + * @default 16 + * @since 3.0.0 + */ + this.maxEntries = GetValue(config, 'maxEntries', 16); + + /** + * Should this Arcade Physics World use an RTree for Dynamic bodies? + * + * An RTree is a fast way of spatially sorting of all the bodies in the world. + * However, at certain limits, the cost of clearing and inserting the bodies into the + * tree every frame becomes more expensive than the search speed gains it provides. + * + * If you have a large number of dynamic bodies in your world then it may be best to + * disable the use of the RTree by setting this property to `false` in the physics config. + * + * The number it can cope with depends on browser and device, but a conservative estimate + * of around 5,000 bodies should be considered the max before disabling it. + * + * This only applies to dynamic bodies. Static bodies are always kept in an RTree, + * because they don't have to be cleared every frame, so you benefit from the + * massive search speeds all the time. + * + * @name Phaser.Physics.Arcade.World#useTree + * @type {boolean} + * @default true + * @since 3.10.0 + */ + this.useTree = GetValue(config, 'useTree', true); + + /** + * The spatial index of Dynamic Bodies. + * + * @name Phaser.Physics.Arcade.World#tree + * @type {Phaser.Structs.RTree} + * @since 3.0.0 + */ + this.tree = new RTree(this.maxEntries); + + /** + * The spatial index of Static Bodies. + * + * @name Phaser.Physics.Arcade.World#staticTree + * @type {Phaser.Structs.RTree} + * @since 3.0.0 + */ + this.staticTree = new RTree(this.maxEntries); + + /** + * Recycled input for tree searches. + * + * @name Phaser.Physics.Arcade.World#treeMinMax + * @type {Phaser.Types.Physics.Arcade.ArcadeWorldTreeMinMax} + * @since 3.0.0 + */ + this.treeMinMax = { minX: 0, minY: 0, maxX: 0, maxY: 0 }; + + /** + * A temporary Transform Matrix used by bodies for calculations without them needing their own local copy. + * + * @name Phaser.Physics.Arcade.World#_tempMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 3.12.0 + */ + this._tempMatrix = new TransformMatrix(); + + /** + * A temporary Transform Matrix used by bodies for calculations without them needing their own local copy. + * + * @name Phaser.Physics.Arcade.World#_tempMatrix2 + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 3.12.0 + */ + this._tempMatrix2 = new TransformMatrix(); + + /** + * The Filtering Options passed to `GetTilesWithinWorldXY` as part of the `collideSpriteVsTilemapLayer` check. + * + * @name Phaser.Physics.Arcade.World#tileFilterOptions + * @type {Phaser.Types.Tilemaps.FilteringOptions} + * @since 3.60.0 + */ + this.tileFilterOptions = { isColliding: true, isNotEmpty: true, hasInterestingFace: true }; + + if (this.drawDebug) + { + this.createDebugGraphic(); + } + }, + + /** + * Adds an Arcade Physics Body to a Game Object, an array of Game Objects, or the children of a Group. + * + * The difference between this and the `enableBody` method is that you can pass arrays or Groups + * to this method. + * + * You can specify if the bodies are to be Dynamic or Static. A dynamic body can move via velocity and + * acceleration. A static body remains fixed in place and as such is able to use an optimized search + * tree, making it ideal for static elements such as level objects. You can still collide and overlap + * with static bodies. + * + * Normally, rather than calling this method directly, you'd use the helper methods available in the + * Arcade Physics Factory, such as: + * + * ```javascript + * this.physics.add.image(x, y, textureKey); + * this.physics.add.sprite(x, y, textureKey); + * ``` + * + * Calling factory methods encapsulates the creation of a Game Object and the creation of its + * body at the same time. If you are creating custom classes then you can pass them to this + * method to have their bodies created. + * + * @method Phaser.Physics.Arcade.World#enable + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]|Phaser.GameObjects.Group|Phaser.GameObjects.Group[])} object - The object, or objects, on which to create the bodies. + * @param {number} [bodyType] - The type of Body to create. Either `DYNAMIC_BODY` or `STATIC_BODY`. + */ + enable: function (object, bodyType) + { + if (bodyType === undefined) { bodyType = CONST.DYNAMIC_BODY; } + + if (!Array.isArray(object)) + { + object = [ object ]; + } + + for (var i = 0; i < object.length; i++) + { + var entry = object[i]; + + if (entry.isParent) + { + var children = entry.getChildren(); + + for (var c = 0; c < children.length; c++) + { + var child = children[c]; + + if (child.isParent) + { + // Handle Groups nested inside of Groups + this.enable(child, bodyType); + } + else + { + this.enableBody(child, bodyType); + } + } + } + else + { + this.enableBody(entry, bodyType); + } + } + }, + + /** + * Creates an Arcade Physics Body on a single Game Object. + * + * If the Game Object already has a body, this method will simply add it back into the simulation. + * + * You can specify if the body is Dynamic or Static. A dynamic body can move via velocity and + * acceleration. A static body remains fixed in place and as such is able to use an optimized search + * tree, making it ideal for static elements such as level objects. You can still collide and overlap + * with static bodies. + * + * Normally, rather than calling this method directly, you'd use the helper methods available in the + * Arcade Physics Factory, such as: + * + * ```javascript + * this.physics.add.image(x, y, textureKey); + * this.physics.add.sprite(x, y, textureKey); + * ``` + * + * Calling factory methods encapsulates the creation of a Game Object and the creation of its + * body at the same time. If you are creating custom classes then you can pass them to this + * method to have their bodies created. + * + * @method Phaser.Physics.Arcade.World#enableBody + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} object - The Game Object on which to create the body. + * @param {number} [bodyType] - The type of Body to create. Either `DYNAMIC_BODY` or `STATIC_BODY`. + * + * @return {Phaser.GameObjects.GameObject} The Game Object on which the body was created. + */ + enableBody: function (object, bodyType) + { + if (bodyType === undefined) { bodyType = CONST.DYNAMIC_BODY; } + + if (object.hasTransformComponent) + { + if (!object.body) + { + if (bodyType === CONST.DYNAMIC_BODY) + { + object.body = new Body(this, object); + } + else if (bodyType === CONST.STATIC_BODY) + { + object.body = new StaticBody(this, object); + } + } + + this.add(object.body); + } + + return object; + }, + + /** + * Adds an existing Arcade Physics Body or StaticBody to the simulation. + * + * The body is enabled and added to the local search trees. + * + * @method Phaser.Physics.Arcade.World#add + * @since 3.10.0 + * + * @param {(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)} body - The Body to be added to the simulation. + * + * @return {(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)} The Body that was added to the simulation. + */ + add: function (body) + { + if (body.physicsType === CONST.DYNAMIC_BODY) + { + this.bodies.add(body); + } + else if (body.physicsType === CONST.STATIC_BODY) + { + this.staticBodies.add(body); + + this.staticTree.insert(body); + } + + body.enable = true; + + return body; + }, + + /** + * Disables the Arcade Physics Body of a Game Object, an array of Game Objects, or the children of a Group. + * + * The difference between this and the `disableBody` method is that you can pass arrays or Groups + * to this method. + * + * The body itself is not deleted, it just has its `enable` property set to false, which + * means you can re-enable it again at any point by passing it to enable `World.enable` or `World.add`. + * + * @method Phaser.Physics.Arcade.World#disable + * @since 3.0.0 + * + * @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]|Phaser.GameObjects.Group|Phaser.GameObjects.Group[])} object - The object, or objects, on which to disable the bodies. + */ + disable: function (object) + { + if (!Array.isArray(object)) + { + object = [ object ]; + } + + for (var i = 0; i < object.length; i++) + { + var entry = object[i]; + + if (entry.isParent) + { + var children = entry.getChildren(); + + for (var c = 0; c < children.length; c++) + { + var child = children[c]; + + if (child.isParent) + { + // Handle Groups nested inside of Groups + this.disable(child); + } + else + { + this.disableBody(child.body); + } + } + } + else + { + this.disableBody(entry.body); + } + } + }, + + /** + * Disables an existing Arcade Physics Body or StaticBody and removes it from the simulation. + * + * The body is disabled and removed from the local search trees. + * + * The body itself is not deleted, it just has its `enable` property set to false, which + * means you can re-enable it again at any point by passing it to enable `World.enable` or `World.add`. + * + * @method Phaser.Physics.Arcade.World#disableBody + * @since 3.0.0 + * + * @param {(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)} body - The Body to be disabled. + */ + disableBody: function (body) + { + this.remove(body); + + body.enable = false; + }, + + /** + * Removes an existing Arcade Physics Body or StaticBody from the simulation. + * + * The body is disabled and removed from the local search trees. + * + * The body itself is not deleted, it just has its `enabled` property set to false, which + * means you can re-enable it again at any point by passing it to enable `enable` or `add`. + * + * @method Phaser.Physics.Arcade.World#remove + * @since 3.0.0 + * + * @param {(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody)} body - The body to be removed from the simulation. + */ + remove: function (body) + { + if (body.physicsType === CONST.DYNAMIC_BODY) + { + this.tree.remove(body); + this.bodies.delete(body); + } + else if (body.physicsType === CONST.STATIC_BODY) + { + this.staticBodies.delete(body); + this.staticTree.remove(body); + } + }, + + /** + * Creates a Graphics Game Object that the world will use to render the debug display to. + * + * This is called automatically when the World is instantiated if the `debug` config property + * was set to `true`. However, you can call it at any point should you need to display the + * debug Graphic from a fixed point. + * + * You can control which objects are drawn to the Graphics object, and the colors they use, + * by setting the debug properties in the physics config. + * + * You should not typically use this in a production game. Use it to aid during debugging. + * + * @method Phaser.Physics.Arcade.World#createDebugGraphic + * @since 3.0.0 + * + * @return {Phaser.GameObjects.Graphics} The Graphics object that was created for use by the World. + */ + createDebugGraphic: function () + { + var graphic = this.scene.sys.add.graphics({ x: 0, y: 0 }); + + graphic.setDepth(Number.MAX_VALUE); + + this.debugGraphic = graphic; + + this.drawDebug = true; + + return graphic; + }, + + /** + * Sets the position, size and properties of the World boundary. + * + * The World boundary is an invisible rectangle that defines the edges of the World. + * If a Body is set to collide with the world bounds then it will automatically stop + * when it reaches any of the edges. You can optionally set which edges of the boundary + * should be checked against. + * + * @method Phaser.Physics.Arcade.World#setBounds + * @since 3.0.0 + * + * @param {number} x - The top-left x coordinate of the boundary. + * @param {number} y - The top-left y coordinate of the boundary. + * @param {number} width - The width of the boundary. + * @param {number} height - The height of the boundary. + * @param {boolean} [checkLeft] - Should bodies check against the left edge of the boundary? + * @param {boolean} [checkRight] - Should bodies check against the right edge of the boundary? + * @param {boolean} [checkUp] - Should bodies check against the top edge of the boundary? + * @param {boolean} [checkDown] - Should bodies check against the bottom edge of the boundary? + * + * @return {Phaser.Physics.Arcade.World} This World object. + */ + setBounds: function (x, y, width, height, checkLeft, checkRight, checkUp, checkDown) + { + this.bounds.setTo(x, y, width, height); + + if (checkLeft !== undefined) + { + this.setBoundsCollision(checkLeft, checkRight, checkUp, checkDown); + } + + return this; + }, + + /** + * Enables or disables collisions on each edge of the World boundary. + * + * @method Phaser.Physics.Arcade.World#setBoundsCollision + * @since 3.0.0 + * + * @param {boolean} [left=true] - Should bodies check against the left edge of the boundary? + * @param {boolean} [right=true] - Should bodies check against the right edge of the boundary? + * @param {boolean} [up=true] - Should bodies check against the top edge of the boundary? + * @param {boolean} [down=true] - Should bodies check against the bottom edge of the boundary? + * + * @return {Phaser.Physics.Arcade.World} This World object. + */ + setBoundsCollision: function (left, right, up, down) + { + if (left === undefined) { left = true; } + if (right === undefined) { right = true; } + if (up === undefined) { up = true; } + if (down === undefined) { down = true; } + + this.checkCollision.left = left; + this.checkCollision.right = right; + this.checkCollision.up = up; + this.checkCollision.down = down; + + return this; + }, + + /** + * Pauses the simulation. + * + * A paused simulation does not update any existing bodies, or run any Colliders. + * + * However, you can still enable and disable bodies within it, or manually run collide or overlap + * checks. + * + * @method Phaser.Physics.Arcade.World#pause + * @fires Phaser.Physics.Arcade.Events#PAUSE + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.World} This World object. + */ + pause: function () + { + this.isPaused = true; + + this.emit(Events.PAUSE); + + return this; + }, + + /** + * Resumes the simulation, if paused. + * + * @method Phaser.Physics.Arcade.World#resume + * @fires Phaser.Physics.Arcade.Events#RESUME + * @since 3.0.0 + * + * @return {Phaser.Physics.Arcade.World} This World object. + */ + resume: function () + { + this.isPaused = false; + + this.emit(Events.RESUME); + + return this; + }, + + /** + * Creates a new Collider object and adds it to the simulation. + * + * A Collider is a way to automatically perform collision checks between two objects, + * calling the collide and process callbacks if they occur. + * + * Colliders are run as part of the World update, after all of the Bodies have updated. + * + * By creating a Collider you don't need then call `World.collide` in your `update` loop, + * as it will be handled for you automatically. + * + * @method Phaser.Physics.Arcade.World#addCollider + * @since 3.0.0 + * @see Phaser.Physics.Arcade.World#collide + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object2 - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - The callback to invoke when the two objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - The callback to invoke when the two objects collide. Must return a boolean. + * @param {*} [callbackContext] - The scope in which to call the callbacks. + * + * @return {Phaser.Physics.Arcade.Collider} The Collider that was created. + */ + addCollider: function (object1, object2, collideCallback, processCallback, callbackContext) + { + if (collideCallback === undefined) { collideCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = collideCallback; } + + var collider = new Collider(this, false, object1, object2, collideCallback, processCallback, callbackContext); + + this.colliders.add(collider); + + return collider; + }, + + /** + * Creates a new Overlap Collider object and adds it to the simulation. + * + * A Collider is a way to automatically perform overlap checks between two objects, + * calling the collide and process callbacks if they occur. + * + * Colliders are run as part of the World update, after all of the Bodies have updated. + * + * By creating a Collider you don't need then call `World.overlap` in your `update` loop, + * as it will be handled for you automatically. + * + * @method Phaser.Physics.Arcade.World#addOverlap + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object to check for overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object2 - The second object to check for overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - The callback to invoke when the two objects overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - The callback to invoke when the two objects overlap. Must return a boolean. + * @param {*} [callbackContext] - The scope in which to call the callbacks. + * + * @return {Phaser.Physics.Arcade.Collider} The Collider that was created. + */ + addOverlap: function (object1, object2, collideCallback, processCallback, callbackContext) + { + if (collideCallback === undefined) { collideCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = collideCallback; } + + var collider = new Collider(this, true, object1, object2, collideCallback, processCallback, callbackContext); + + this.colliders.add(collider); + + return collider; + }, + + /** + * Removes a Collider from the simulation so it is no longer processed. + * + * This method does not destroy the Collider. If you wish to add it back at a later stage you can call + * `World.colliders.add(Collider)`. + * + * If you no longer need the Collider you can call the `Collider.destroy` method instead, which will + * automatically clear all of its references and then remove it from the World. If you call destroy on + * a Collider you _don't_ need to pass it to this method too. + * + * @method Phaser.Physics.Arcade.World#removeCollider + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Collider} collider - The Collider to remove from the simulation. + * + * @return {Phaser.Physics.Arcade.World} This World object. + */ + removeCollider: function (collider) + { + this.colliders.remove(collider); + + return this; + }, + + /** + * Sets the frame rate to run the simulation at. + * + * The frame rate value is used to simulate a fixed update time step. This fixed + * time step allows for a straightforward implementation of a deterministic game state. + * + * This frame rate is independent of the frequency at which the game is rendering. The + * higher you set the fps, the more physics simulation steps will occur per game step. + * Conversely, the lower you set it, the less will take place. + * + * You can optionally advance the simulation directly yourself by calling the `step` method. + * + * @method Phaser.Physics.Arcade.World#setFPS + * @since 3.10.0 + * + * @param {number} framerate - The frame rate to advance the simulation at. + * + * @return {this} This World object. + */ + setFPS: function (framerate) + { + this.fps = framerate; + this._frameTime = 1 / this.fps; + this._frameTimeMS = 1000 * this._frameTime; + + return this; + }, + + /** + * Advances the simulation based on the elapsed time and fps rate. + * + * This is called automatically by your Scene and does not need to be invoked directly. + * + * @method Phaser.Physics.Arcade.World#update + * @fires Phaser.Physics.Arcade.Events#WORLD_STEP + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time, in ms, elapsed since the last frame. + */ + update: function (time, delta) + { + if (this.isPaused || this.bodies.size === 0) + { + return; + } + + var i; + var fixedDelta = this._frameTime; + var msPerFrame = this._frameTimeMS * this.timeScale; + + this._elapsed += delta; + + // Update all active bodies + var body; + var bodies = this.bodies; + + // Will a step happen this frame? + var willStep = (this._elapsed >= msPerFrame); + + if (!this.fixedStep) + { + fixedDelta = delta * 0.001; + willStep = true; + this._elapsed = 0; + } + + bodies.forEach(function (body) + { + if (body.enable) + { + body.preUpdate(willStep, fixedDelta); + } + }); + + // We know that a step will happen this frame, so let's bundle it all together to save branching and iteration costs + if (willStep) + { + this._elapsed -= msPerFrame; + this.stepsLastFrame = 1; + + // Optionally populate our dynamic collision tree + if (this.useTree) + { + this.tree.clear(); + this.tree.load(Array.from(bodies)); + } + + // Process any colliders + var colliders = this.colliders.update(); + + for (i = 0; i < colliders.length; i++) + { + var collider = colliders[i]; + + if (collider.active) + { + collider.update(); + } + } + + this.emit(Events.WORLD_STEP, fixedDelta); + } + + // Process any additional steps this frame + while (this._elapsed >= msPerFrame) + { + this._elapsed -= msPerFrame; + + this.step(fixedDelta); + } + }, + + /** + * Advances the simulation by a time increment. + * + * @method Phaser.Physics.Arcade.World#step + * @fires Phaser.Physics.Arcade.Events#WORLD_STEP + * @since 3.10.0 + * + * @param {number} delta - The delta time amount, in seconds, by which to advance the simulation. + */ + step: function (delta) + { + // Update all active bodies + var bodies = this.bodies; + + bodies.forEach(function (body) + { + if (body.enable) + { + body.update(delta); + } + }); + + // Optionally populate our dynamic collision tree + if (this.useTree) + { + this.tree.clear(); + this.tree.load(Array.from(bodies)); + } + + // Process any colliders + var colliders = this.colliders.update(); + + for (var i = 0; i < colliders.length; i++) + { + var collider = colliders[i]; + + if (collider.active) + { + collider.update(); + } + } + + this.emit(Events.WORLD_STEP, delta); + + this.stepsLastFrame++; + }, + + /** + * Advances the simulation by a single step. + * + * @method Phaser.Physics.Arcade.World#singleStep + * @fires Phaser.Physics.Arcade.Events#WORLD_STEP + * @since 3.70.0 + */ + singleStep: function () + { + this.update(0, this._frameTimeMS); + + this.postUpdate(); + }, + + /** + * Updates bodies, draws the debug display, and handles pending queue operations. + * + * @method Phaser.Physics.Arcade.World#postUpdate + * @since 3.0.0 + */ + postUpdate: function () + { + var dynamic = this.bodies; + var staticBodies = this.staticBodies; + + // We don't need to postUpdate if there wasn't a step this frame + if (this.stepsLastFrame) + { + this.stepsLastFrame = 0; + + dynamic.forEach(function (body) + { + if (body.enable) + { + body.postUpdate(); + } + }); + } + + if (this.drawDebug) + { + var graphics = this.debugGraphic; + + graphics.clear(); + + dynamic.forEach(function (body) + { + if (body.willDrawDebug()) + { + body.drawDebug(graphics); + } + }); + + staticBodies.forEach(function (body) + { + if (body.willDrawDebug()) + { + body.drawDebug(graphics); + } + }); + } + + var pending = this.pendingDestroy; + + if (pending.size > 0) + { + var dynamicTree = this.tree; + var staticTree = this.staticTree; + + pending.forEach(function (body) + { + if (body.physicsType === CONST.DYNAMIC_BODY) + { + dynamicTree.remove(body); + dynamic.delete(body); + } + else if (body.physicsType === CONST.STATIC_BODY) + { + staticTree.remove(body); + staticBodies.delete(body); + } + + body.world = undefined; + body.gameObject = undefined; + }); + + pending.clear(); + } + }, + + /** + * Calculates a Body's velocity and updates its position. + * + * @method Phaser.Physics.Arcade.World#updateMotion + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body to be updated. + * @param {number} delta - The delta value to be used in the motion calculations, in seconds. + */ + updateMotion: function (body, delta) + { + if (body.allowRotation) + { + this.computeAngularVelocity(body, delta); + } + + this.computeVelocity(body, delta); + }, + + /** + * Calculates a Body's angular velocity. + * + * @method Phaser.Physics.Arcade.World#computeAngularVelocity + * @since 3.10.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body to compute the velocity for. + * @param {number} delta - The delta value to be used in the calculation, in seconds. + */ + computeAngularVelocity: function (body, delta) + { + var velocity = body.angularVelocity; + var acceleration = body.angularAcceleration; + var drag = body.angularDrag; + var max = body.maxAngular; + + if (acceleration) + { + velocity += acceleration * delta; + } + else if (body.allowDrag && drag) + { + drag *= delta; + + if (FuzzyGreaterThan(velocity - drag, 0, 0.1)) + { + velocity -= drag; + } + else if (FuzzyLessThan(velocity + drag, 0, 0.1)) + { + velocity += drag; + } + else + { + velocity = 0; + } + } + + velocity = Clamp(velocity, -max, max); + + var velocityDelta = velocity - body.angularVelocity; + + body.angularVelocity += velocityDelta; + body.rotation += (body.angularVelocity * delta); + }, + + /** + * Calculates a Body's per-axis velocity. + * + * @method Phaser.Physics.Arcade.World#computeVelocity + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body to compute the velocity for. + * @param {number} delta - The delta value to be used in the calculation, in seconds. + */ + computeVelocity: function (body, delta) + { + var velocityX = body.velocity.x; + var accelerationX = body.acceleration.x; + var dragX = body.drag.x; + var maxX = body.maxVelocity.x; + + var velocityY = body.velocity.y; + var accelerationY = body.acceleration.y; + var dragY = body.drag.y; + var maxY = body.maxVelocity.y; + + var speed = body.speed; + var maxSpeed = body.maxSpeed; + var allowDrag = body.allowDrag; + var useDamping = body.useDamping; + + if (body.allowGravity) + { + velocityX += (this.gravity.x + body.gravity.x) * delta; + velocityY += (this.gravity.y + body.gravity.y) * delta; + } + + if (accelerationX) + { + velocityX += accelerationX * delta; + } + else if (allowDrag && dragX) + { + if (useDamping) + { + // Damping based deceleration + dragX = Math.pow(dragX, delta); + + velocityX *= dragX; + + speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY); + + if (FuzzyEqual(speed, 0, 0.001)) + { + velocityX = 0; + } + } + else + { + // Linear deceleration + dragX *= delta; + + if (FuzzyGreaterThan(velocityX - dragX, 0, 0.01)) + { + velocityX -= dragX; + } + else if (FuzzyLessThan(velocityX + dragX, 0, 0.01)) + { + velocityX += dragX; + } + else + { + velocityX = 0; + } + } + } + + if (accelerationY) + { + velocityY += accelerationY * delta; + } + else if (allowDrag && dragY) + { + if (useDamping) + { + // Damping based deceleration + dragY = Math.pow(dragY, delta); + + velocityY *= dragY; + + speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY); + + if (FuzzyEqual(speed, 0, 0.001)) + { + velocityY = 0; + } + } + else + { + // Linear deceleration + dragY *= delta; + + if (FuzzyGreaterThan(velocityY - dragY, 0, 0.01)) + { + velocityY -= dragY; + } + else if (FuzzyLessThan(velocityY + dragY, 0, 0.01)) + { + velocityY += dragY; + } + else + { + velocityY = 0; + } + } + } + + velocityX = Clamp(velocityX, -maxX, maxX); + velocityY = Clamp(velocityY, -maxY, maxY); + + body.velocity.set(velocityX, velocityY); + + if (maxSpeed > -1 && body.velocity.length() > maxSpeed) + { + body.velocity.normalize().scale(maxSpeed); + speed = maxSpeed; + } + + body.speed = speed; + }, + + /** + * Separates two Bodies. + * + * @method Phaser.Physics.Arcade.World#separate + * @fires Phaser.Physics.Arcade.Events#COLLIDE + * @fires Phaser.Physics.Arcade.Events#OVERLAP + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first Body to be separated. + * @param {Phaser.Physics.Arcade.Body} body2 - The second Body to be separated. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - The process callback. + * @param {*} [callbackContext] - The context in which to invoke the callback. + * @param {boolean} [overlapOnly] - If this a collide or overlap check? + * + * @return {boolean} True if separation occurred, otherwise false. + */ + separate: function (body1, body2, processCallback, callbackContext, overlapOnly) + { + var overlapX; + var overlapY; + + var result = false; + var runSeparation = true; + + if ( + !body1.enable || + !body2.enable || + body1.checkCollision.none || + body2.checkCollision.none || + !this.intersects(body1, body2)) + { + return result; + } + + // They overlap. Is there a custom process callback? If it returns true then we can carry on, otherwise we should abort. + if (processCallback && processCallback.call(callbackContext, (body1.gameObject || body1), (body2.gameObject || body2)) === false) + { + return result; + } + + // Circle vs. Circle, or Circle vs. Rect + if (body1.isCircle || body2.isCircle) + { + var circleResults = this.separateCircle(body1, body2, overlapOnly); + + if (circleResults.result) + { + // We got a satisfactory result from the separateCircle method + result = true; + runSeparation = false; + } + else + { + // Further processing required + overlapX = circleResults.x; + overlapY = circleResults.y; + runSeparation = true; + } + } + + if (runSeparation) + { + var resultX = false; + var resultY = false; + var bias = this.OVERLAP_BIAS; + + // Do we separate on x first or y first or both? + if (overlapOnly) + { + // No separation but we need to calculate overlapX, overlapY, etc. + resultX = SeparateX(body1, body2, overlapOnly, bias, overlapX); + resultY = SeparateY(body1, body2, overlapOnly, bias, overlapY); + } + else if (this.forceX || Math.abs(this.gravity.y + body1.gravity.y) < Math.abs(this.gravity.x + body1.gravity.x)) + { + resultX = SeparateX(body1, body2, overlapOnly, bias, overlapX); + + // Are they still intersecting? Let's do the other axis then + if (this.intersects(body1, body2)) + { + resultY = SeparateY(body1, body2, overlapOnly, bias, overlapY); + } + } + else + { + resultY = SeparateY(body1, body2, overlapOnly, bias, overlapY); + + // Are they still intersecting? Let's do the other axis then + if (this.intersects(body1, body2)) + { + resultX = SeparateX(body1, body2, overlapOnly, bias, overlapX); + } + } + + result = (resultX || resultY); + } + + if (result) + { + if (overlapOnly) + { + if (body1.onOverlap || body2.onOverlap) + { + this.emit(Events.OVERLAP, body1.gameObject, body2.gameObject, body1, body2); + } + } + else if (body1.onCollide || body2.onCollide) + { + this.emit(Events.COLLIDE, body1.gameObject, body2.gameObject, body1, body2); + } + } + + return result; + }, + + /** + * Separates two Bodies, when both are circular. + * + * @method Phaser.Physics.Arcade.World#separateCircle + * @fires Phaser.Physics.Arcade.Events#COLLIDE + * @fires Phaser.Physics.Arcade.Events#OVERLAP + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first Body to be separated. + * @param {Phaser.Physics.Arcade.Body} body2 - The second Body to be separated. + * @param {boolean} [overlapOnly] - If this a collide or overlap check? + * + * @return {boolean} True if separation occurred, otherwise false. + */ + separateCircle: function (body1, body2, overlapOnly) + { + // Set the AABB overlap, blocked and touching values into the bodies (we don't use the return values here) + GetOverlapX(body1, body2, false, 0); + GetOverlapY(body1, body2, false, 0); + + var body1IsCircle = body1.isCircle; + var body2IsCircle = body2.isCircle; + var body1Center = body1.center; + var body2Center = body2.center; + var body1Immovable = body1.immovable; + var body2Immovable = body2.immovable; + var body1Velocity = body1.velocity; + var body2Velocity = body2.velocity; + + var overlap = 0; + var twoCircles = true; + + if (body1IsCircle !== body2IsCircle) + { + twoCircles = false; + + var circleX = body1Center.x; + var circleY = body1Center.y; + var circleRadius = body1.halfWidth; + + var rectX = body2.position.x; + var rectY = body2.position.y; + var rectRight = body2.right; + var rectBottom = body2.bottom; + + if (body2IsCircle) + { + circleX = body2Center.x; + circleY = body2Center.y; + circleRadius = body2.halfWidth; + + rectX = body1.position.x; + rectY = body1.position.y; + rectRight = body1.right; + rectBottom = body1.bottom; + } + + if (circleY < rectY) + { + if (circleX < rectX) + { + overlap = DistanceBetween(circleX, circleY, rectX, rectY) - circleRadius; + } + else if (circleX > rectRight) + { + overlap = DistanceBetween(circleX, circleY, rectRight, rectY) - circleRadius; + } + } + else if (circleY > rectBottom) + { + if (circleX < rectX) + { + overlap = DistanceBetween(circleX, circleY, rectX, rectBottom) - circleRadius; + } + else if (circleX > rectRight) + { + overlap = DistanceBetween(circleX, circleY, rectRight, rectBottom) - circleRadius; + } + } + + // If a collision occurs in the corner points of the rectangle + // then the bodies behave like circles + overlap *= -1; + } + else + { + overlap = (body1.halfWidth + body2.halfWidth) - DistanceBetweenPoints(body1Center, body2Center); + } + + body1.overlapR = overlap; + body2.overlapR = overlap; + + var angle = AngleBetweenPoints(body1Center, body2Center); + var overlapX = (overlap + MATH_CONST.EPSILON) * Math.cos(angle); + var overlapY = (overlap + MATH_CONST.EPSILON) * Math.sin(angle); + + var results = { overlap: overlap, result: false, x: overlapX, y: overlapY }; + + // We know the AABBs already intersect before we enter this method + if (overlapOnly && (!twoCircles || (twoCircles && overlap !== 0))) + { + // Now we know the rect vs circle overlaps, or two circles do + results.result = true; + + return results; + } + + // Can't separate (in this method): + // Two immovable bodies + // A body with its own custom separation logic + // A circle vs. a rect with a face-on collision + if ((!twoCircles && overlap === 0) || (body1Immovable && body2Immovable) || body1.customSeparateX || body2.customSeparateX) + { + // Let SeparateX / SeparateY handle this + results.x = undefined; + results.y = undefined; + + return results; + } + + // If we get this far we either have circle vs. circle + // or circle vs. rect with corner collision + + var deadlock = (!body1.pushable && !body2.pushable); + + if (twoCircles) + { + var dx = body1Center.x - body2Center.x; + var dy = body1Center.y - body2Center.y; + var d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + var nx = ((body2Center.x - body1Center.x) / d) || 0; + var ny = ((body2Center.y - body1Center.y) / d) || 0; + var p = 2 * (body1Velocity.x * nx + body1Velocity.y * ny - body2Velocity.x * nx - body2Velocity.y * ny) / (body1.mass + body2.mass); + + if (body1Immovable || body2Immovable || !body1.pushable || !body2.pushable) + { + p *= 2; + } + + if (!body1Immovable && body1.pushable) + { + body1Velocity.x = (body1Velocity.x - p / body1.mass * nx); + body1Velocity.y = (body1Velocity.y - p / body1.mass * ny); + body1Velocity.multiply(body1.bounce); + } + + if (!body2Immovable && body2.pushable) + { + body2Velocity.x = (body2Velocity.x + p / body2.mass * nx); + body2Velocity.y = (body2Velocity.y + p / body2.mass * ny); + body2Velocity.multiply(body2.bounce); + } + + if (!body1Immovable && !body2Immovable) + { + overlapX *= 0.5; + overlapY *= 0.5; + } + + if (!body1Immovable || body1.pushable || deadlock) + { + body1.x -= overlapX; + body1.y -= overlapY; + + body1.updateCenter(); + } + + if (!body2Immovable || body2.pushable || deadlock) + { + body2.x += overlapX; + body2.y += overlapY; + + body2.updateCenter(); + } + + results.result = true; + } + else + { + // Circle vs. Rect + // We'll only move the circle (if we can) and let + // the runSeparation handle the rectangle + + if (!body1Immovable || body1.pushable || deadlock) + { + body1.x -= overlapX; + body1.y -= overlapY; + + body1.updateCenter(); + } + + if (!body2Immovable || body2.pushable || deadlock) + { + body2.x += overlapX; + body2.y += overlapY; + + body2.updateCenter(); + } + + // Let SeparateX / SeparateY handle this further + results.x = undefined; + results.y = undefined; + } + + return results; + }, + + /** + * Checks to see if two Bodies intersect at all. + * + * @method Phaser.Physics.Arcade.World#intersects + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body1 - The first body to check. + * @param {Phaser.Physics.Arcade.Body} body2 - The second body to check. + * + * @return {boolean} True if the two bodies intersect, otherwise false. + */ + intersects: function (body1, body2) + { + if (body1 === body2) + { + return false; + } + + if (!body1.isCircle && !body2.isCircle) + { + // Rect vs. Rect + return !( + body1.right <= body2.left || + body1.bottom <= body2.top || + body1.left >= body2.right || + body1.top >= body2.bottom + ); + } + else if (body1.isCircle) + { + if (body2.isCircle) + { + // Circle vs. Circle + return DistanceBetweenPoints(body1.center, body2.center) <= (body1.halfWidth + body2.halfWidth); + } + else + { + // Circle vs. Rect + return this.circleBodyIntersects(body1, body2); + } + } + else + { + // Rect vs. Circle + return this.circleBodyIntersects(body2, body1); + } + }, + + /** + * Tests if a circular Body intersects with another Body. + * + * @method Phaser.Physics.Arcade.World#circleBodyIntersects + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} circle - The circular body to test. + * @param {Phaser.Physics.Arcade.Body} body - The rectangular body to test. + * + * @return {boolean} True if the two bodies intersect, otherwise false. + */ + circleBodyIntersects: function (circle, body) + { + var x = Clamp(circle.center.x, body.left, body.right); + var y = Clamp(circle.center.y, body.top, body.bottom); + + var dx = (circle.center.x - x) * (circle.center.x - x); + var dy = (circle.center.y - y) * (circle.center.y - y); + + return (dx + dy) <= (circle.halfWidth * circle.halfWidth); + }, + + /** + * Tests if Game Objects overlap. + * + * See details in {@link Phaser.Physics.Arcade.World#collide}. + * + * @method Phaser.Physics.Arcade.World#overlap + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object or array of objects to check. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} [object2] - The second object or array of objects to check, or `undefined`. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [overlapCallback] - An optional callback function that is called if the objects overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they overlap. If this is set then `overlapCallback` will only be called if this callback returns `true`. + * @param {*} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if at least one Game Object overlaps another. + * + * @see Phaser.Physics.Arcade.World#collide + */ + overlap: function (object1, object2, overlapCallback, processCallback, callbackContext) + { + if (overlapCallback === undefined) { overlapCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = overlapCallback; } + + return this.collideObjects(object1, object2, overlapCallback, processCallback, callbackContext, true); + }, + + /** + * Performs a collision check and separation between the two physics enabled objects given, which can be single + * Game Objects, arrays of Game Objects, Physics Groups, arrays of Physics Groups or normal Groups. + * + * If you don't require separation then use {@link Phaser.Physics.Arcade.World#overlap} instead. + * + * If two Groups or arrays are passed, each member of one will be tested against each member of the other. + * + * If **only** one Group is passed (as `object1`), each member of the Group will be collided against the other members. + * + * If **only** one Array is passed, the array is iterated and every element in it is tested against the others. + * + * Two callbacks can be provided; they receive the colliding game objects as arguments. + * If an overlap is detected, the `processCallback` is called first. It can cancel the collision by returning false. + * Next the objects are separated and `collideCallback` is invoked. + * + * Arcade Physics uses the Projection Method of collision resolution and separation. While it's fast and suitable + * for 'arcade' style games it lacks stability when multiple objects are in close proximity or resting upon each other. + * The separation that stops two objects penetrating may create a new penetration against a different object. If you + * require a high level of stability please consider using an alternative physics system, such as Matter.js. + * + * @method Phaser.Physics.Arcade.World#collide + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object or array of objects to check. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} [object2] - The second object or array of objects to check, or `undefined`. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} `true` if any overlapping Game Objects were separated, otherwise `false`. + */ + collide: function (object1, object2, collideCallback, processCallback, callbackContext) + { + if (collideCallback === undefined) { collideCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = collideCallback; } + + return this.collideObjects(object1, object2, collideCallback, processCallback, callbackContext, false); + }, + + /** + * Internal helper function. Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideObjects + * @private + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} [object2] - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} collideCallback - The callback to invoke when the two objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} processCallback - The callback to invoke when the two objects collide. Must return a boolean. + * @param {any} callbackContext - The scope in which to call the callbacks. + * @param {boolean} overlapOnly - Whether this is a collision or overlap check. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideObjects: function (object1, object2, collideCallback, processCallback, callbackContext, overlapOnly) + { + var i; + var j; + + if (object1.isParent && (object1.physicsType === undefined || object2 === undefined || object1 === object2)) + { + object1 = Array.from(object1.children); + } + + if (object2 && object2.isParent && object2.physicsType === undefined) + { + object2 = Array.from(object2.children); + } + + var object1isArray = Array.isArray(object1); + var object2isArray = Array.isArray(object2); + + this._total = 0; + + if (!object1isArray && !object2isArray) + { + // Neither of them are arrays - do this first as it's the most common use-case + this.collideHandler(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + else if (!object1isArray && object2isArray) + { + // Object 2 is an Array + for (i = 0; i < object2.length; i++) + { + this.collideHandler(object1, object2[i], collideCallback, processCallback, callbackContext, overlapOnly); + } + } + else if (object1isArray && !object2isArray) + { + // Object 1 is an Array + if (!object2) + { + // Special case for array vs. self + for (i = 0; i < object1.length; i++) + { + var child = object1[i]; + + for (j = i + 1; j < object1.length; j++) + { + if (i === j) + { + continue; + } + + this.collideHandler(child, object1[j], collideCallback, processCallback, callbackContext, overlapOnly); + } + } + } + else + { + for (i = 0; i < object1.length; i++) + { + this.collideHandler(object1[i], object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + } + } + else + { + // They're both arrays + for (i = 0; i < object1.length; i++) + { + for (j = 0; j < object2.length; j++) + { + this.collideHandler(object1[i], object2[j], collideCallback, processCallback, callbackContext, overlapOnly); + } + } + } + + return (this._total > 0); + }, + + /** + * Internal helper function. Please use Phaser.Physics.Arcade.World#collide and Phaser.Physics.Arcade.World#overlap instead. + * + * @method Phaser.Physics.Arcade.World#collideHandler + * @private + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object1 - The first object or array of objects to check. + * @param {Phaser.Types.Physics.Arcade.ArcadeColliderType} object2 - The second object or array of objects to check, or `undefined`. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} collideCallback - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} processCallback - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} callbackContext - The context in which to run the callbacks. + * @param {boolean} overlapOnly - Whether this is a collision or overlap check. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideHandler: function (object1, object2, collideCallback, processCallback, callbackContext, overlapOnly) + { + // Collide Group with Self + // Only collide valid objects + if (object2 === undefined && object1.isParent) + { + return this.collideGroupVsGroup(object1, object1, collideCallback, processCallback, callbackContext, overlapOnly); + } + + // If neither of the objects are set then bail out + if (!object1 || !object2) + { + return false; + } + + // SPRITE + if (object1.body || object1.isBody) + { + if (object2.body || object2.isBody) + { + return this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + else if (object2.isParent) + { + return this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + else if (object2.isTilemap) + { + return this.collideSpriteVsTilemapLayer(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + } + + // GROUPS + else if (object1.isParent) + { + if (object2.body || object2.isBody) + { + return this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); + } + else if (object2.isParent) + { + return this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + else if (object2.isTilemap) + { + return this.collideGroupVsTilemapLayer(object1, object2, collideCallback, processCallback, callbackContext, overlapOnly); + } + } + + // TILEMAP LAYERS + else if (object1.isTilemap) + { + if (object2.body || object2.isBody) + { + return this.collideSpriteVsTilemapLayer(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); + } + else if (object2.isParent) + { + return this.collideGroupVsTilemapLayer(object2, object1, collideCallback, processCallback, callbackContext, overlapOnly); + } + } + }, + + /** + * Checks if the two given Arcade Physics bodies will collide, or not, + * based on their collision mask and collision categories. + * + * @method Phaser.Physics.Arcade.World#canCollide + * @since 3.70.0 + * + * @param {Phaser.Types.Physics.Arcade.ArcadeCollider} body1 - The first body to check. + * @param {Phaser.Types.Physics.Arcade.ArcadeCollider} body2 - The second body to check. + * + * @return {boolean} True if the two bodies will collide, otherwise false. + */ + canCollide: function (body1, body2) + { + return ( + (body1 && body2) && + (body1.collisionMask & body2.collisionCategory) !== 0 && + (body2.collisionMask & body1.collisionCategory) !== 0 + ); + }, + + /** + * Internal handler for Sprite vs. Sprite collisions. + * Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideSpriteVsSprite + * @private + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} sprite1 - The first object to check for collision. + * @param {Phaser.GameObjects.GameObject} sprite2 - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * @param {boolean} overlapOnly - Whether this is a collision or overlap check. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideSpriteVsSprite: function (sprite1, sprite2, collideCallback, processCallback, callbackContext, overlapOnly) + { + var body1 = (sprite1.isBody) ? sprite1 : sprite1.body; + var body2 = (sprite2.isBody) ? sprite2 : sprite2.body; + + if (!this.canCollide(body1, body2)) + { + return false; + } + + if (this.separate(body1, body2, processCallback, callbackContext, overlapOnly)) + { + if (collideCallback) + { + collideCallback.call(callbackContext, sprite1, sprite2); + } + + this._total++; + } + + return true; + }, + + /** + * Internal handler for Sprite vs. Group collisions. + * Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideSpriteVsGroup + * @private + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.GameObjects.Group} group - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} collideCallback - The callback to invoke when the two objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} processCallback - The callback to invoke when the two objects collide. Must return a boolean. + * @param {any} callbackContext - The scope in which to call the callbacks. + * @param {boolean} overlapOnly - Whether this is a collision or overlap check. + */ + collideSpriteVsGroup: function (sprite, group, collideCallback, processCallback, callbackContext, overlapOnly) + { + var bodyA = (sprite.isBody) ? sprite : sprite.body; + + if (group.getLength() === 0 || !bodyA || !bodyA.enable || bodyA.checkCollision.none || !this.canCollide(bodyA, group)) + { + return; + } + + // Does sprite collide with anything? + + var i; + var len; + var bodyB; + + if (this.useTree || group.physicsType === CONST.STATIC_BODY) + { + var minMax = this.treeMinMax; + + minMax.minX = bodyA.left; + minMax.minY = bodyA.top; + minMax.maxX = bodyA.right; + minMax.maxY = bodyA.bottom; + + var results = (group.physicsType === CONST.DYNAMIC_BODY) ? this.tree.search(minMax) : this.staticTree.search(minMax); + + len = results.length; + + for (i = 0; i < len; i++) + { + bodyB = results[i]; + + if (bodyA === bodyB || !bodyB.enable || bodyB.checkCollision.none || !group.contains(bodyB.gameObject)) + { + // Skip if comparing against itself, or if bodyB isn't collidable, or if bodyB isn't actually part of the Group + continue; + } + + if (this.separate(bodyA, bodyB, processCallback, callbackContext, overlapOnly)) + { + if (collideCallback) + { + collideCallback.call(callbackContext, bodyA.gameObject, bodyB.gameObject); + } + + this._total++; + } + } + } + else + { + var children = group.getChildren(); + var skipIndex = children.indexOf(sprite); + + len = children.length; + + for (i = 0; i < len; i++) + { + bodyB = children[i].body; + + if (!bodyB || i === skipIndex || !bodyB.enable) + { + continue; + } + + if (this.separate(bodyA, bodyB, processCallback, callbackContext, overlapOnly)) + { + if (collideCallback) + { + collideCallback.call(callbackContext, bodyA.gameObject, bodyB.gameObject); + } + + this._total++; + } + } + } + }, + + /** + * Internal handler for Group vs. Tilemap collisions. + * Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideGroupVsTilemapLayer + * @private + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Group} group - The first object to check for collision. + * @param {Phaser.Tilemaps.TilemapLayer} tilemapLayer - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} collideCallback - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} processCallback - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} callbackContext - The context in which to run the callbacks. + * @param {boolean} overlapOnly - Whether this is a collision or overlap check. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideGroupVsTilemapLayer: function (group, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) + { + if (!this.canCollide(group, tilemapLayer)) + { + return false; + } + + var children = group.getChildren(); + + if (children.length === 0) + { + return false; + } + + var didCollide = false; + + for (var i = 0; i < children.length; i++) + { + if (children[i].body || children[i].isBody) + { + if (this.collideSpriteVsTilemapLayer(children[i], tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly)) + { + didCollide = true; + } + } + } + + return didCollide; + }, + + /** + * This advanced method is specifically for testing for collision between a single Sprite and an array of Tile objects. + * + * You should generally use the `collide` method instead, with a Sprite vs. a Tilemap Layer, as that will perform + * tile filtering and culling for you, as well as handle the interesting face collision automatically. + * + * This method is offered for those who would like to check for collision with specific Tiles in a layer, without + * having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic collisions + * on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method, + * you should filter them before passing them to this method. + * + * Important: Use of this method skips the `interesting faces` system that Tilemap Layers use. This means if you have + * say a row or column of tiles, and you jump into, or walk over them, it's possible to get stuck on the edges of the + * tiles as the interesting face calculations are skipped. However, for quick-fire small collision set tests on + * dynamic maps, this method can prove very useful. + * + * This method does not factor in the Collision Mask or Category. + * + * @method Phaser.Physics.Arcade.World#collideTiles + * @fires Phaser.Physics.Arcade.Events#TILE_COLLIDE + * @since 3.17.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.Tilemaps.Tile[]} tiles - An array of Tiles to check for collision against. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideTiles: function (sprite, tiles, collideCallback, processCallback, callbackContext) + { + if (tiles.length === 0 || (sprite.body && !sprite.body.enable) || (sprite.isBody && !sprite.enable)) + { + return false; + } + else + { + return this.collideSpriteVsTilesHandler(sprite, tiles, collideCallback, processCallback, callbackContext, false, false); + } + }, + + /** + * This advanced method is specifically for testing for overlaps between a single Sprite and an array of Tile objects. + * + * You should generally use the `overlap` method instead, with a Sprite vs. a Tilemap Layer, as that will perform + * tile filtering and culling for you, as well as handle the interesting face collision automatically. + * + * This method is offered for those who would like to check for overlaps with specific Tiles in a layer, without + * having to set any collision attributes on the tiles in question. This allows you to perform quick dynamic overlap + * tests on small sets of Tiles. As such, no culling or checks are made to the array of Tiles given to this method, + * you should filter them before passing them to this method. + * + * This method does not factor in the Collision Mask or Category. + * + * @method Phaser.Physics.Arcade.World#overlapTiles + * @fires Phaser.Physics.Arcade.Events#TILE_OVERLAP + * @since 3.17.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.Tilemaps.Tile[]} tiles - An array of Tiles to check for collision against. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [overlapCallback] - An optional callback function that is called if the objects overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `overlapCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + overlapTiles: function (sprite, tiles, overlapCallback, processCallback, callbackContext) + { + if (tiles.length === 0 || (sprite.body && !sprite.body.enable) || (sprite.isBody && !sprite.enable)) + { + return false; + } + else + { + return this.collideSpriteVsTilesHandler(sprite, tiles, overlapCallback, processCallback, callbackContext, true, false); + } + }, + + /** + * Internal handler for Sprite vs. Tilemap collisions. + * Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideSpriteVsTilemapLayer + * @fires Phaser.Physics.Arcade.Events#TILE_COLLIDE + * @fires Phaser.Physics.Arcade.Events#TILE_OVERLAP + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.Tilemaps.TilemapLayer} tilemapLayer - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * @param {boolean} [overlapOnly] - Whether this is a collision or overlap check. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideSpriteVsTilemapLayer: function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) + { + var body = (sprite.isBody) ? sprite : sprite.body; + + if (!body.enable || body.checkCollision.none || !this.canCollide(body, tilemapLayer)) + { + return false; + } + + var layerData = tilemapLayer.layer; + + // Increase the hit area of the body by the size of the tiles * the scale + // This will allow GetTilesWithinWorldXY to include the tiles around the body + + var x = body.x - (layerData.tileWidth * tilemapLayer.scaleX); + var y = body.y - (layerData.tileHeight * tilemapLayer.scaleY); + var w = body.width + (layerData.tileWidth * tilemapLayer.scaleX); + var h = body.height + layerData.tileHeight * tilemapLayer.scaleY; + + var options = (overlapOnly) ? null : this.tileFilterOptions; + + var mapData = GetTilesWithinWorldXY(x, y, w, h, options, tilemapLayer.scene.cameras.main, tilemapLayer.layer); + + if (mapData.length === 0) + { + return false; + } + else + { + return this.collideSpriteVsTilesHandler(sprite, mapData, collideCallback, processCallback, callbackContext, overlapOnly, true); + } + }, + + /** + * Internal handler for Sprite vs. Tilemap collisions. + * Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideSpriteVsTilesHandler + * @fires Phaser.Physics.Arcade.Events#TILE_COLLIDE + * @fires Phaser.Physics.Arcade.Events#TILE_OVERLAP + * @private + * @since 3.17.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The first object to check for collision. + * @param {Phaser.Tilemaps.TilemapLayer} tilemapLayer - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * @param {boolean} [overlapOnly] - Whether this is a collision or overlap check. + * @param {boolean} [isLayer] - Is this check coming from a TilemapLayer or an array of tiles? + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideSpriteVsTilesHandler: function (sprite, tiles, collideCallback, processCallback, callbackContext, overlapOnly, isLayer) + { + var body = (sprite.isBody) ? sprite : sprite.body; + + var tile; + var tileWorldRect = { left: 0, right: 0, top: 0, bottom: 0 }; + var tilemapLayer; + var collision = false; + + for (var i = 0; i < tiles.length; i++) + { + tile = tiles[i]; + + tilemapLayer = tile.tilemapLayer; + + var point = tilemapLayer.tileToWorldXY(tile.x, tile.y); + + tileWorldRect.left = point.x; + tileWorldRect.top = point.y; + + tileWorldRect.right = tileWorldRect.left + tile.width * tilemapLayer.scaleX; + tileWorldRect.bottom = tileWorldRect.top + tile.height * tilemapLayer.scaleY; + + if ( + TileIntersectsBody(tileWorldRect, body) && + (!processCallback || processCallback.call(callbackContext, sprite, tile)) && + ProcessTileCallbacks(tile, sprite) && + (overlapOnly || SeparateTile(i, body, tile, tileWorldRect, tilemapLayer, this.TILE_BIAS, isLayer))) + { + this._total++; + + collision = true; + + if (collideCallback) + { + collideCallback.call(callbackContext, sprite, tile); + } + + if (overlapOnly && body.onOverlap) + { + this.emit(Events.TILE_OVERLAP, sprite, tile, body); + } + else if (body.onCollide) + { + this.emit(Events.TILE_COLLIDE, sprite, tile, body); + } + } + } + + return collision; + }, + + /** + * Internal helper for Group vs. Group collisions. + * Please use Phaser.Physics.Arcade.World#collide instead. + * + * @method Phaser.Physics.Arcade.World#collideGroupVsGroup + * @private + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Group} group1 - The first object to check for collision. + * @param {Phaser.GameObjects.Group} group2 - The second object to check for collision. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [collideCallback] - An optional callback function that is called if the objects collide. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two objects if they collide. If this is set then `collideCallback` will only be called if this callback returns `true`. + * @param {any} [callbackContext] - The context in which to run the callbacks. + * @param {boolean} overlapOnly - Whether this is a collision or overlap check. + * + * @return {boolean} True if any objects overlap (with `overlapOnly`); or true if any overlapping objects were separated. + */ + collideGroupVsGroup: function (group1, group2, collideCallback, processCallback, callbackContext, overlapOnly) + { + if (group1.getLength() === 0 || group2.getLength() === 0 || !this.canCollide(group1, group2)) + { + return; + } + + var children = group1.getChildren(); + + for (var i = 0; i < children.length; i++) + { + this.collideSpriteVsGroup(children[i], group2, collideCallback, processCallback, callbackContext, overlapOnly); + } + }, + + /** + * Wrap an object's coordinates (or several objects' coordinates) within {@link Phaser.Physics.Arcade.World#bounds}. + * + * If the object is outside any boundary edge (left, top, right, bottom), it will be moved to the same offset from the opposite edge (the interior). + * + * @method Phaser.Physics.Arcade.World#wrap + * @since 3.3.0 + * + * @param {any} object - A Game Object, a Group, an object with `x` and `y` coordinates, or an array of such objects. + * @param {number} [padding=0] - An amount added to each boundary edge during the operation. + */ + wrap: function (object, padding) + { + if (object.body) + { + this.wrapObject(object, padding); + } + else if (object.getChildren) + { + this.wrapArray(object.getChildren(), padding); + } + else if (Array.isArray(object)) + { + this.wrapArray(object, padding); + } + else + { + this.wrapObject(object, padding); + } + }, + + /** + * Wrap each object's coordinates within {@link Phaser.Physics.Arcade.World#bounds}. + * + * @method Phaser.Physics.Arcade.World#wrapArray + * @since 3.3.0 + * + * @param {Array.<*>} objects - An array of objects to be wrapped. + * @param {number} [padding=0] - An amount added to the boundary. + */ + wrapArray: function (objects, padding) + { + for (var i = 0; i < objects.length; i++) + { + this.wrapObject(objects[i], padding); + } + }, + + /** + * Wrap an object's coordinates within {@link Phaser.Physics.Arcade.World#bounds}. + * + * @method Phaser.Physics.Arcade.World#wrapObject + * @since 3.3.0 + * + * @param {*} object - A Game Object, a Physics Body, or any object with `x` and `y` coordinates + * @param {number} [padding=0] - An amount added to the boundary. + */ + wrapObject: function (object, padding) + { + if (padding === undefined) { padding = 0; } + + object.x = Wrap(object.x, this.bounds.left - padding, this.bounds.right + padding); + object.y = Wrap(object.y, this.bounds.top - padding, this.bounds.bottom + padding); + }, + + /** + * Shuts down the simulation, clearing physics data and removing listeners. + * + * @method Phaser.Physics.Arcade.World#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + this.tree.clear(); + this.staticTree.clear(); + this.bodies.clear(); + this.staticBodies.clear(); + this.colliders.destroy(); + + this.removeAllListeners(); + }, + + /** + * Shuts down the simulation and disconnects it from the current scene. + * + * @method Phaser.Physics.Arcade.World#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.scene = null; + + if (this.debugGraphic) + { + this.debugGraphic.destroy(); + this.debugGraphic = null; + } + } + +}); + +module.exports = World; + + +/***/ }), + +/***/ 1093: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the acceleration properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Acceleration + * @since 3.0.0 + */ +var Acceleration = { + + /** + * Sets the body's horizontal and vertical acceleration. If the vertical acceleration value is not provided, the vertical acceleration is set to the same value as the horizontal acceleration. + * + * @method Phaser.Physics.Arcade.Components.Acceleration#setAcceleration + * @since 3.0.0 + * + * @param {number} x - The horizontal acceleration + * @param {number} [y=x] - The vertical acceleration + * + * @return {this} This Game Object. + */ + setAcceleration: function (x, y) + { + this.body.acceleration.set(x, y); + + return this; + }, + + /** + * Sets the body's horizontal acceleration. + * + * @method Phaser.Physics.Arcade.Components.Acceleration#setAccelerationX + * @since 3.0.0 + * + * @param {number} value - The horizontal acceleration + * + * @return {this} This Game Object. + */ + setAccelerationX: function (value) + { + this.body.acceleration.x = value; + + return this; + }, + + /** + * Sets the body's vertical acceleration. + * + * @method Phaser.Physics.Arcade.Components.Acceleration#setAccelerationY + * @since 3.0.0 + * + * @param {number} value - The vertical acceleration + * + * @return {this} This Game Object. + */ + setAccelerationY: function (value) + { + this.body.acceleration.y = value; + + return this; + } + +}; + +module.exports = Acceleration; + + +/***/ }), + +/***/ 59023: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the angular acceleration properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Angular + * @since 3.0.0 + */ +var Angular = { + + /** + * Sets the angular velocity of the body. + * + * In Arcade Physics, bodies cannot rotate. They are always axis-aligned. + * However, they can have angular motion, which is passed on to the Game Object bound to the body, + * causing them to visually rotate, even though the body remains axis-aligned. + * + * @method Phaser.Physics.Arcade.Components.Angular#setAngularVelocity + * @since 3.0.0 + * + * @param {number} value - The amount of angular velocity. + * + * @return {this} This Game Object. + */ + setAngularVelocity: function (value) + { + this.body.angularVelocity = value; + + return this; + }, + + /** + * Sets the angular acceleration of the body. + * + * In Arcade Physics, bodies cannot rotate. They are always axis-aligned. + * However, they can have angular motion, which is passed on to the Game Object bound to the body, + * causing them to visually rotate, even though the body remains axis-aligned. + * + * @method Phaser.Physics.Arcade.Components.Angular#setAngularAcceleration + * @since 3.0.0 + * + * @param {number} value - The amount of angular acceleration. + * + * @return {this} This Game Object. + */ + setAngularAcceleration: function (value) + { + this.body.angularAcceleration = value; + + return this; + }, + + /** + * Sets the angular drag of the body. Drag is applied to the current velocity, providing a form of deceleration. + * + * @method Phaser.Physics.Arcade.Components.Angular#setAngularDrag + * @since 3.0.0 + * + * @param {number} value - The amount of drag. + * + * @return {this} This Game Object. + */ + setAngularDrag: function (value) + { + this.body.angularDrag = value; + + return this; + } + +}; + +module.exports = Angular; + + +/***/ }), + +/***/ 62069: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the bounce properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Bounce + * @since 3.0.0 + */ +var Bounce = { + + /** + * Sets the bounce values of this body. + * + * Bounce is the amount of restitution, or elasticity, the body has when it collides with another object. + * A value of 1 means that it will retain its full velocity after the rebound. A value of 0 means it will not rebound at all. + * + * @method Phaser.Physics.Arcade.Components.Bounce#setBounce + * @since 3.0.0 + * + * @param {number} x - The amount of horizontal bounce to apply on collision. A float, typically between 0 and 1. + * @param {number} [y=x] - The amount of vertical bounce to apply on collision. A float, typically between 0 and 1. + * + * @return {this} This Game Object. + */ + setBounce: function (x, y) + { + this.body.bounce.set(x, y); + + return this; + }, + + /** + * Sets the horizontal bounce value for this body. + * + * @method Phaser.Physics.Arcade.Components.Bounce#setBounceX + * @since 3.0.0 + * + * @param {number} value - The amount of horizontal bounce to apply on collision. A float, typically between 0 and 1. + * + * @return {this} This Game Object. + */ + setBounceX: function (value) + { + this.body.bounce.x = value; + + return this; + }, + + /** + * Sets the vertical bounce value for this body. + * + * @method Phaser.Physics.Arcade.Components.Bounce#setBounceY + * @since 3.0.0 + * + * @param {number} value - The amount of vertical bounce to apply on collision. A float, typically between 0 and 1. + * + * @return {this} This Game Object. + */ + setBounceY: function (value) + { + this.body.bounce.y = value; + + return this; + }, + + /** + * Sets whether this Body collides with the world boundary. + * + * Optionally also sets the World Bounce values. If the `Body.worldBounce` is null, it's set to a new Phaser.Math.Vector2 first. + * + * @method Phaser.Physics.Arcade.Components.Bounce#setCollideWorldBounds + * @since 3.0.0 + * + * @param {boolean} [value=true] - `true` if this body should collide with the world bounds, otherwise `false`. + * @param {number} [bounceX] - If given this will be replace the `worldBounce.x` value. + * @param {number} [bounceY] - If given this will be replace the `worldBounce.y` value. + * @param {boolean} [onWorldBounds] - If given this replaces the Body's `onWorldBounds` value. + * + * @return {this} This Game Object. + */ + setCollideWorldBounds: function (value, bounceX, bounceY, onWorldBounds) + { + this.body.setCollideWorldBounds(value, bounceX, bounceY, onWorldBounds); + + return this; + } + +}; + +module.exports = Bounce; + + +/***/ }), + +/***/ 78389: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCollidesWith = __webpack_require__(79599); + +/** + * Provides methods used for setting the collision category and mask of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Collision + * @since 3.70.0 + */ +var Collision = { + + /** + * Sets the Collision Category that this Arcade Physics Body + * will use in order to determine what it can collide with. + * + * It can only have one single category assigned to it. + * + * If you wish to reset the collision category and mask, call + * the `resetCollisionCategory` method. + * + * @method Phaser.Physics.Arcade.Components.Collision#setCollisionCategory + * @since 3.70.0 + * + * @param {number} category - The collision category. + * + * @return {this} This Game Object. + */ + setCollisionCategory: function (category) + { + var target = (this.body) ? this.body : this; + + target.collisionCategory = category; + + return this; + }, + + /** + * Checks to see if the given Collision Category will collide with + * this Arcade Physics object or not. + * + * @method Phaser.Physics.Arcade.Components.Collision#willCollideWith + * @since 3.70.0 + * + * @param {number} category - Collision category value to test. + * + * @return {boolean} `true` if the given category will collide with this object, otherwise `false`. + */ + willCollideWith: function (category) + { + var target = (this.body) ? this.body : this; + + return (target.collisionMask & category) !== 0; + }, + + /** + * Adds the given Collision Category to the list of those that this + * Arcade Physics Body will collide with. + * + * @method Phaser.Physics.Arcade.Components.Collision#addCollidesWith + * @since 3.70.0 + * + * @param {number} category - The collision category to add. + * + * @return {this} This Game Object. + */ + addCollidesWith: function (category) + { + var target = (this.body) ? this.body : this; + + target.collisionMask = target.collisionMask | category; + + return this; + }, + + /** + * Removes the given Collision Category from the list of those that this + * Arcade Physics Body will collide with. + * + * @method Phaser.Physics.Arcade.Components.Collision#removeCollidesWith + * @since 3.70.0 + * + * @param {number} category - The collision category to add. + * + * @return {this} This Game Object. + */ + removeCollidesWith: function (category) + { + var target = (this.body) ? this.body : this; + + target.collisionMask = target.collisionMask & ~category; + + return this; + }, + + /** + * Sets all of the Collision Categories that this Arcade Physics Body + * will collide with. You can either pass a single category value, or + * an array of them. + * + * Calling this method will reset all of the collision categories, + * so only those passed to this method are enabled. + * + * If you wish to add a new category to the existing mask, call + * the `addCollisionCategory` method. + * + * If you wish to reset the collision category and mask, call + * the `resetCollisionCategory` method. + * + * @method Phaser.Physics.Arcade.Components.Collision#setCollidesWith + * @since 3.70.0 + * + * @param {(number|number[])} categories - The collision category to collide with, or an array of them. + * + * @return {this} This Game Object. + */ + setCollidesWith: function (categories) + { + var target = (this.body) ? this.body : this; + + target.collisionMask = GetCollidesWith(categories); + + return this; + }, + + /** + * Resets the Collision Category and Mask back to the defaults, + * which is to collide with everything. + * + * @method Phaser.Physics.Arcade.Components.Collision#resetCollisionCategory + * @since 3.70.0 + * + * @return {this} This Game Object. + */ + resetCollisionCategory: function () + { + var target = (this.body) ? this.body : this; + + target.collisionCategory = 0x0001; + target.collisionMask = 2147483647; + + return this; + } + +}; + +module.exports = Collision; + + +/***/ }), + +/***/ 87118: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the debug properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Debug + * @since 3.0.0 + */ +var Debug = { + + /** + * Sets the debug values of this body. + * + * Bodies will only draw their debug if debug has been enabled for Arcade Physics as a whole. + * Note that there is a performance cost in drawing debug displays. It should never be used in production. + * + * @method Phaser.Physics.Arcade.Components.Debug#setDebug + * @since 3.0.0 + * + * @param {boolean} showBody - Set to `true` to have this body render its outline to the debug display. + * @param {boolean} showVelocity - Set to `true` to have this body render a velocity marker to the debug display. + * @param {number} bodyColor - The color of the body outline when rendered to the debug display. + * + * @return {this} This Game Object. + */ + setDebug: function (showBody, showVelocity, bodyColor) + { + this.debugShowBody = showBody; + this.debugShowVelocity = showVelocity; + this.debugBodyColor = bodyColor; + + return this; + }, + + /** + * Sets the color of the body outline when it renders to the debug display. + * + * @method Phaser.Physics.Arcade.Components.Debug#setDebugBodyColor + * @since 3.0.0 + * + * @param {number} value - The color of the body outline when rendered to the debug display. + * + * @return {this} This Game Object. + */ + setDebugBodyColor: function (value) + { + this.body.debugBodyColor = value; + + return this; + }, + + /** + * Set to `true` to have this body render its outline to the debug display. + * + * @name Phaser.Physics.Arcade.Components.Debug#debugShowBody + * @type {boolean} + * @since 3.0.0 + */ + debugShowBody: { + + get: function () + { + return this.body.debugShowBody; + }, + + set: function (value) + { + this.body.debugShowBody = value; + } + + }, + + /** + * Set to `true` to have this body render a velocity marker to the debug display. + * + * @name Phaser.Physics.Arcade.Components.Debug#debugShowVelocity + * @type {boolean} + * @since 3.0.0 + */ + debugShowVelocity: { + + get: function () + { + return this.body.debugShowVelocity; + }, + + set: function (value) + { + this.body.debugShowVelocity = value; + } + + }, + + /** + * The color of the body outline when it renders to the debug display. + * + * @name Phaser.Physics.Arcade.Components.Debug#debugBodyColor + * @type {number} + * @since 3.0.0 + */ + debugBodyColor: { + + get: function () + { + return this.body.debugBodyColor; + }, + + set: function (value) + { + this.body.debugBodyColor = value; + } + + } + +}; + +module.exports = Debug; + + +/***/ }), + +/***/ 52819: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the drag properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Drag + * @since 3.0.0 + */ +var Drag = { + + /** + * Sets the body's horizontal and vertical drag. If the vertical drag value is not provided, the vertical drag is set to the same value as the horizontal drag. + * + * Drag can be considered as a form of deceleration that will return the velocity of a body back to zero over time. + * It is the absolute loss of velocity due to movement, in pixels per second squared. + * The x and y components are applied separately. + * + * When `useDamping` is true, this is 1 minus the damping factor. + * A value of 1 means the Body loses no velocity. + * A value of 0.95 means the Body loses 5% of its velocity per step. + * A value of 0.5 means the Body loses 50% of its velocity per step. + * + * Drag is applied only when `acceleration` is zero. + * + * @method Phaser.Physics.Arcade.Components.Drag#setDrag + * @since 3.0.0 + * + * @param {number} x - The amount of horizontal drag to apply. + * @param {number} [y=x] - The amount of vertical drag to apply. + * + * @return {this} This Game Object. + */ + setDrag: function (x, y) + { + this.body.drag.set(x, y); + + return this; + }, + + /** + * Sets the body's horizontal drag. + * + * Drag can be considered as a form of deceleration that will return the velocity of a body back to zero over time. + * It is the absolute loss of velocity due to movement, in pixels per second squared. + * The x and y components are applied separately. + * + * When `useDamping` is true, this is 1 minus the damping factor. + * A value of 1 means the Body loses no velocity. + * A value of 0.95 means the Body loses 5% of its velocity per step. + * A value of 0.5 means the Body loses 50% of its velocity per step. + * + * Drag is applied only when `acceleration` is zero. + * + * @method Phaser.Physics.Arcade.Components.Drag#setDragX + * @since 3.0.0 + * + * @param {number} value - The amount of horizontal drag to apply. + * + * @return {this} This Game Object. + */ + setDragX: function (value) + { + this.body.drag.x = value; + + return this; + }, + + /** + * Sets the body's vertical drag. + * + * Drag can be considered as a form of deceleration that will return the velocity of a body back to zero over time. + * It is the absolute loss of velocity due to movement, in pixels per second squared. + * The x and y components are applied separately. + * + * When `useDamping` is true, this is 1 minus the damping factor. + * A value of 1 means the Body loses no velocity. + * A value of 0.95 means the Body loses 5% of its velocity per step. + * A value of 0.5 means the Body loses 50% of its velocity per step. + * + * Drag is applied only when `acceleration` is zero. + * + * @method Phaser.Physics.Arcade.Components.Drag#setDragY + * @since 3.0.0 + * + * @param {number} value - The amount of vertical drag to apply. + * + * @return {this} This Game Object. + */ + setDragY: function (value) + { + this.body.drag.y = value; + + return this; + }, + + /** + * If this Body is using `drag` for deceleration this function controls how the drag is applied. + * If set to `true` drag will use a damping effect rather than a linear approach. If you are + * creating a game where the Body moves freely at any angle (i.e. like the way the ship moves in + * the game Asteroids) then you will get a far smoother and more visually correct deceleration + * by using damping, avoiding the axis-drift that is prone with linear deceleration. + * + * If you enable this property then you should use far smaller `drag` values than with linear, as + * they are used as a multiplier on the velocity. Values such as 0.95 will give a nice slow + * deceleration, where-as smaller values, such as 0.5 will stop an object almost immediately. + * + * @method Phaser.Physics.Arcade.Components.Drag#setDamping + * @since 3.10.0 + * + * @param {boolean} value - `true` to use damping for deceleration, or `false` to use linear deceleration. + * + * @return {this} This Game Object. + */ + setDamping: function (value) + { + this.body.useDamping = value; + + return this; + } + +}; + +module.exports = Drag; + + +/***/ }), + +/***/ 4074: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the enable properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Enable + * @since 3.0.0 + */ +var Enable = { + + /** + * Sets whether this Body should calculate its velocity based on its change in + * position every frame. The default, which is to not do this, means that you + * make this Body move by setting the velocity directly. However, if you are + * trying to move this Body via a Tween, or have it follow a Path, then you + * should enable this instead. This will allow it to still collide with other + * bodies, something that isn't possible if you're just changing its position directly. + * + * @method Phaser.Physics.Arcade.Components.Enable#setDirectControl + * @since 3.70.0 + * + * @param {boolean} [value=true] - `true` if the Body calculate velocity based on changes in position, otherwise `false`. + * + * @return {this} This Game Object. + */ + setDirectControl: function (value) + { + this.body.setDirectControl(value); + + return this; + }, + + /** + * Enables this Game Object's Body. + * If you reset the Body you must also pass `x` and `y`. + * + * @method Phaser.Physics.Arcade.Components.Enable#enableBody + * @since 3.0.0 + * + * @param {boolean} [reset] - Also reset the Body and place the Game Object at (x, y). + * @param {number} [x] - The horizontal position to place the Game Object, if `reset` is true. + * @param {number} [y] - The horizontal position to place the Game Object, if `reset` is true. + * @param {boolean} [enableGameObject] - Also set this Game Object's `active` to true. + * @param {boolean} [showGameObject] - Also set this Game Object's `visible` to true. + * + * @return {this} This Game Object. + * + * @see Phaser.Physics.Arcade.Body#enable + * @see Phaser.Physics.Arcade.StaticBody#enable + * @see Phaser.Physics.Arcade.Body#reset + * @see Phaser.Physics.Arcade.StaticBody#reset + * @see Phaser.GameObjects.GameObject#active + * @see Phaser.GameObjects.GameObject#visible + */ + enableBody: function (reset, x, y, enableGameObject, showGameObject) + { + if (reset) + { + this.body.reset(x, y); + } + + if (enableGameObject) + { + this.body.gameObject.active = true; + } + + if (showGameObject) + { + this.body.gameObject.visible = true; + } + + this.body.enable = true; + + return this; + }, + + /** + * Stops and disables this Game Object's Body. + * + * @method Phaser.Physics.Arcade.Components.Enable#disableBody + * @since 3.0.0 + * + * @param {boolean} [disableGameObject=false] - Also set this Game Object's `active` to false. + * @param {boolean} [hideGameObject=false] - Also set this Game Object's `visible` to false. + * + * @return {this} This Game Object. + * + * @see Phaser.Physics.Arcade.Body#enable + * @see Phaser.Physics.Arcade.StaticBody#enable + * @see Phaser.GameObjects.GameObject#active + * @see Phaser.GameObjects.GameObject#visible + */ + disableBody: function (disableGameObject, hideGameObject) + { + if (disableGameObject === undefined) { disableGameObject = false; } + if (hideGameObject === undefined) { hideGameObject = false; } + + this.body.stop(); + + this.body.enable = false; + + if (disableGameObject) + { + this.body.gameObject.active = false; + } + + if (hideGameObject) + { + this.body.gameObject.visible = false; + } + + return this; + }, + + /** + * Syncs the Body's position and size with its parent Game Object. + * You don't need to call this for Dynamic Bodies, as it happens automatically. + * But for Static bodies it's a useful way of modifying the position of a Static Body + * in the Physics World, based on its Game Object. + * + * @method Phaser.Physics.Arcade.Components.Enable#refreshBody + * @since 3.1.0 + * + * @return {this} This Game Object. + * + * @see Phaser.Physics.Arcade.StaticBody#updateFromGameObject + */ + refreshBody: function () + { + this.body.updateFromGameObject(); + + return this; + } + +}; + +module.exports = Enable; + + +/***/ }), + +/***/ 40831: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Methods for setting the friction of an Arcade Physics Body. + * + * In Arcade Physics, friction is a special case of motion transfer from an "immovable" body to a riding body. + * + * @namespace Phaser.Physics.Arcade.Components.Friction + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#friction + */ +var Friction = { + + /** + * Sets the friction of this game object's physics body. + * In Arcade Physics, friction is a special case of motion transfer from an "immovable" body to a riding body. + * + * @method Phaser.Physics.Arcade.Components.Friction#setFriction + * @since 3.0.0 + * + * @param {number} x - The amount of horizontal friction to apply, [0, 1]. + * @param {number} [y=x] - The amount of vertical friction to apply, [0, 1]. + * + * @return {this} This Game Object. + * + * @see Phaser.Physics.Arcade.Body#friction + */ + setFriction: function (x, y) + { + this.body.friction.set(x, y); + + return this; + }, + + /** + * Sets the horizontal friction of this game object's physics body. + * This can move a riding body horizontally when it collides with this one on the vertical axis. + * + * @method Phaser.Physics.Arcade.Components.Friction#setFrictionX + * @since 3.0.0 + * + * @param {number} x - The amount of friction to apply, [0, 1]. + * + * @return {this} This Game Object. + * + * @see Phaser.Physics.Arcade.Body#friction + */ + setFrictionX: function (x) + { + this.body.friction.x = x; + + return this; + }, + + /** + * Sets the vertical friction of this game object's physics body. + * This can move a riding body vertically when it collides with this one on the horizontal axis. + * + * @method Phaser.Physics.Arcade.Components.Friction#setFrictionY + * @since 3.0.0 + * + * @param {number} y - The amount of friction to apply, [0, 1]. + * + * @return {this} This Game Object. + * + * @see Phaser.Physics.Arcade.Body#friction + */ + setFrictionY: function (y) + { + this.body.friction.y = y; + + return this; + } + +}; + +module.exports = Friction; + + +/***/ }), + +/***/ 26775: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods for setting the gravity properties of an Arcade Physics Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.Physics.Arcade.Components.Gravity + * @since 3.0.0 + */ +var Gravity = { + + /** + * Set the X and Y values of the gravitational pull to act upon this Arcade Physics Game Object. Values can be positive or negative. Larger values result in a stronger effect. + * + * If only one value is provided, this value will be used for both the X and Y axis. + * + * @method Phaser.Physics.Arcade.Components.Gravity#setGravity + * @since 3.0.0 + * + * @param {number} x - The gravitational force to be applied to the X-axis. + * @param {number} [y=x] - The gravitational force to be applied to the Y-axis. If this is not specified, the X value will be used. + * + * @return {this} This Game Object. + */ + setGravity: function (x, y) + { + this.body.gravity.set(x, y); + + return this; + }, + + /** + * Set the gravitational force to be applied to the X axis. Value can be positive or negative. Larger values result in a stronger effect. + * + * @method Phaser.Physics.Arcade.Components.Gravity#setGravityX + * @since 3.0.0 + * + * @param {number} x - The gravitational force to be applied to the X-axis. + * + * @return {this} This Game Object. + */ + setGravityX: function (x) + { + this.body.gravity.x = x; + + return this; + }, + + /** + * Set the gravitational force to be applied to the Y axis. Value can be positive or negative. Larger values result in a stronger effect. + * + * @method Phaser.Physics.Arcade.Components.Gravity#setGravityY + * @since 3.0.0 + * + * @param {number} y - The gravitational force to be applied to the Y-axis. + * + * @return {this} This Game Object. + */ + setGravityY: function (y) + { + this.body.gravity.y = y; + + return this; + } + +}; + +module.exports = Gravity; + + +/***/ }), + +/***/ 9437: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the immovable properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Immovable + * @since 3.0.0 + */ +var Immovable = { + + /** + * Sets if this Body can be separated during collisions with other bodies. + * + * When a body is immovable it means it won't move at all, not even to separate it from collision + * overlap. If you just wish to prevent a body from being knocked around by other bodies, see + * the `setPushable` method instead. + * + * @method Phaser.Physics.Arcade.Components.Immovable#setImmovable + * @since 3.0.0 + * + * @param {boolean} [value=true] - Sets if this body will be separated during collisions with other bodies. + * + * @return {this} This Game Object. + */ + setImmovable: function (value) + { + if (value === undefined) { value = true; } + + this.body.immovable = value; + + return this; + } + +}; + +module.exports = Immovable; + + +/***/ }), + +/***/ 30621: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the mass properties of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Mass + * @since 3.0.0 + */ +var Mass = { + + /** + * Sets the mass of the physics body + * + * @method Phaser.Physics.Arcade.Components.Mass#setMass + * @since 3.0.0 + * + * @param {number} value - New value for the mass of the body. + * + * @return {this} This Game Object. + */ + setMass: function (value) + { + this.body.mass = value; + + return this; + } + +}; + +module.exports = Mass; + + +/***/ }), + +/***/ 72441: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var OverlapRect = __webpack_require__(47956); +var Circle = __webpack_require__(96503); +var CircleToCircle = __webpack_require__(2044); +var CircleToRectangle = __webpack_require__(81491); + +/** + * This method will search the given circular area and return an array of all physics bodies that + * overlap with it. It can return either Dynamic, Static bodies or a mixture of both. + * + * A body only has to intersect with the search area to be considered, it doesn't have to be fully + * contained within it. + * + * If Arcade Physics is set to use the RTree (which it is by default) then the search is rather fast, + * otherwise the search is O(N) for Dynamic Bodies. + * + * @function Phaser.Physics.Arcade.Components.OverlapCirc + * @since 3.21.0 + * + * @param {number} x - The x coordinate of the center of the area to search within. + * @param {number} y - The y coordinate of the center of the area to search within. + * @param {number} radius - The radius of the area to search within. + * @param {boolean} [includeDynamic=true] - Should the search include Dynamic Bodies? + * @param {boolean} [includeStatic=false] - Should the search include Static Bodies? + * + * @return {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[])} An array of bodies that overlap with the given area. + */ +var OverlapCirc = function (world, x, y, radius, includeDynamic, includeStatic) +{ + var bodiesInRect = OverlapRect(world, x - radius, y - radius, 2 * radius, 2 * radius, includeDynamic, includeStatic); + + if (bodiesInRect.length === 0) + { + return bodiesInRect; + } + + var area = new Circle(x, y, radius); + var circFromBody = new Circle(); + var bodiesInArea = []; + + for (var i = 0; i < bodiesInRect.length; i++) + { + var body = bodiesInRect[i]; + + if (body.isCircle) + { + circFromBody.setTo(body.center.x, body.center.y, body.halfWidth); + + if (CircleToCircle(area, circFromBody)) + { + bodiesInArea.push(body); + } + } + else if (CircleToRectangle(area, body)) + { + bodiesInArea.push(body); + } + } + + return bodiesInArea; +}; + +module.exports = OverlapCirc; + + +/***/ }), + +/***/ 47956: +/***/ ((module) => { + +/** + * This method will search the given rectangular area and return an array of all physics bodies that + * overlap with it. It can return either Dynamic, Static bodies or a mixture of both. + * + * A body only has to intersect with the search area to be considered, it doesn't have to be fully + * contained within it. + * + * If Arcade Physics is set to use the RTree (which it is by default) then the search for is extremely fast, + * otherwise the search is O(N) for Dynamic Bodies. + * + * @function Phaser.Physics.Arcade.Components.OverlapRect + * @since 3.17.0 + * + * @param {number} x - The top-left x coordinate of the area to search within. + * @param {number} y - The top-left y coordinate of the area to search within. + * @param {number} width - The width of the area to search within. + * @param {number} height - The height of the area to search within. + * @param {boolean} [includeDynamic=true] - Should the search include Dynamic Bodies? + * @param {boolean} [includeStatic=false] - Should the search include Static Bodies? + * + * @return {(Phaser.Physics.Arcade.Body[]|Phaser.Physics.Arcade.StaticBody[])} An array of bodies that overlap with the given area. + */ +var OverlapRect = function (world, x, y, width, height, includeDynamic, includeStatic) +{ + if (includeDynamic === undefined) { includeDynamic = true; } + if (includeStatic === undefined) { includeStatic = false; } + + var dynamicBodies = []; + var staticBodies = []; + + var minMax = world.treeMinMax; + + minMax.minX = x; + minMax.minY = y; + minMax.maxX = x + width; + minMax.maxY = y + height; + + if (includeStatic) + { + staticBodies = world.staticTree.search(minMax); + } + + if (includeDynamic && world.useTree) + { + dynamicBodies = world.tree.search(minMax); + } + else if (includeDynamic) + { + var bodies = world.bodies; + + var fakeBody = + { + position: { + x: x, + y: y + }, + left: x, + top: y, + right: x + width, + bottom: y + height, + isCircle: false + }; + + var intersects = world.intersects; + + bodies.iterate(function (target) + { + if (intersects(target, fakeBody)) + { + dynamicBodies.push(target); + } + + }); + } + + return staticBodies.concat(dynamicBodies); +}; + +module.exports = OverlapRect; + + +/***/ }), + +/***/ 62121: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods used for setting the pushable property of an Arcade Physics Body. + * + * @namespace Phaser.Physics.Arcade.Components.Pushable + * @since 3.50.0 + */ +var Pushable = { + + /** + * Sets if this Body can be pushed by another Body. + * + * A body that cannot be pushed will reflect back all of the velocity it is given to the + * colliding body. If that body is also not pushable, then the separation will be split + * between them evenly. + * + * If you want your body to never move or seperate at all, see the `setImmovable` method. + * + * @method Phaser.Physics.Arcade.Components.Pushable#setPushable + * @since 3.50.0 + * + * @param {boolean} [value=true] - Sets if this body can be pushed by collisions with another Body. + * + * @return {this} This Game Object. + */ + setPushable: function (value) + { + if (value === undefined) { value = true; } + + this.body.pushable = value; + + return this; + } + +}; + +module.exports = Pushable; + + +/***/ }), + +/***/ 29384: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods for setting the size of an Arcade Physics Game Object. + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.Physics.Arcade.Components.Size + * @since 3.0.0 + */ +var Size = { + + /** + * Sets the body offset. This allows you to adjust the difference between the center of the body + * and the x and y coordinates of the parent Game Object. + * + * @method Phaser.Physics.Arcade.Components.Size#setOffset + * @since 3.0.0 + * + * @param {number} x - The amount to offset the body from the parent Game Object along the x-axis. + * @param {number} [y=x] - The amount to offset the body from the parent Game Object along the y-axis. Defaults to the value given for the x-axis. + * + * @return {this} This Game Object. + */ + setOffset: function (x, y) + { + this.body.setOffset(x, y); + + return this; + }, + + /** + * **DEPRECATED**: Please use `setBodySize` instead. + * + * Sets the size of this physics body. Setting the size does not adjust the dimensions of the parent Game Object. + * + * @method Phaser.Physics.Arcade.Components.Size#setSize + * @since 3.0.0 + * @deprecated + * + * @param {number} width - The new width of the physics body, in pixels. + * @param {number} height - The new height of the physics body, in pixels. + * @param {boolean} [center=true] - Should the body be re-positioned so its center aligns with the parent Game Object? + * + * @return {this} This Game Object. + */ + setSize: function (width, height, center) + { + this.body.setSize(width, height, center); + + return this; + }, + + /** + * Sets the size of this physics body. Setting the size does not adjust the dimensions of the parent Game Object. + * + * @method Phaser.Physics.Arcade.Components.Size#setBodySize + * @since 3.24.0 + * + * @param {number} width - The new width of the physics body, in pixels. + * @param {number} height - The new height of the physics body, in pixels. + * @param {boolean} [center=true] - Should the body be re-positioned so its center aligns with the parent Game Object? + * + * @return {this} This Game Object. + */ + setBodySize: function (width, height, center) + { + this.body.setSize(width, height, center); + + return this; + }, + + /** + * Sets this physics body to use a circle for collision instead of a rectangle. + * + * @method Phaser.Physics.Arcade.Components.Size#setCircle + * @since 3.0.0 + * + * @param {number} radius - The radius of the physics body, in pixels. + * @param {number} [offsetX] - The amount to offset the body from the parent Game Object along the x-axis. + * @param {number} [offsetY] - The amount to offset the body from the parent Game Object along the y-axis. + * + * @return {this} This Game Object. + */ + setCircle: function (radius, offsetX, offsetY) + { + this.body.setCircle(radius, offsetX, offsetY); + + return this; + } + +}; + +module.exports = Size; + + +/***/ }), + +/***/ 15098: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Provides methods for modifying the velocity of an Arcade Physics body. + * + * Should be applied as a mixin and not used directly. + * + * @namespace Phaser.Physics.Arcade.Components.Velocity + * @since 3.0.0 + */ +var Velocity = { + + /** + * Sets the velocity of the Body. + * + * @method Phaser.Physics.Arcade.Components.Velocity#setVelocity + * @since 3.0.0 + * + * @param {number} x - The horizontal velocity of the body, in pixels per second. Positive values move the body to the right, while negative values move it to the left. + * @param {number} [y=x] - The vertical velocity of the body, in pixels per second. Positive values move the body down, while negative values move it up. + * + * @return {this} This Game Object. + */ + setVelocity: function (x, y) + { + this.body.setVelocity(x, y); + + return this; + }, + + /** + * Sets the horizontal component of the body's velocity. + * + * Positive values move the body to the right, while negative values move it to the left. + * + * @method Phaser.Physics.Arcade.Components.Velocity#setVelocityX + * @since 3.0.0 + * + * @param {number} x - The new horizontal velocity, in pixels per second. + * + * @return {this} This Game Object. + */ + setVelocityX: function (x) + { + this.body.setVelocityX(x); + + return this; + }, + + /** + * Sets the vertical component of the body's velocity. + * + * Positive values move the body down, while negative values move it up. + * + * @method Phaser.Physics.Arcade.Components.Velocity#setVelocityY + * @since 3.0.0 + * + * @param {number} y - The new vertical velocity, in pixels per second. + * + * @return {this} This Game Object. + */ + setVelocityY: function (y) + { + this.body.setVelocityY(y); + + return this; + }, + + /** + * Sets the maximum velocity of the body. + * + * @method Phaser.Physics.Arcade.Components.Velocity#setMaxVelocity + * @since 3.0.0 + * + * @param {number} x - The new maximum horizontal velocity, in pixels per second. + * @param {number} [y=x] - The new maximum vertical velocity, in pixels per second. + * + * @return {this} This Game Object. + */ + setMaxVelocity: function (x, y) + { + this.body.maxVelocity.set(x, y); + + return this; + } + +}; + +module.exports = Velocity; + + +/***/ }), + +/***/ 92209: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Arcade.Components + */ + +module.exports = { + + Acceleration: __webpack_require__(1093), + Angular: __webpack_require__(59023), + Bounce: __webpack_require__(62069), + Collision: __webpack_require__(78389), + Debug: __webpack_require__(87118), + Drag: __webpack_require__(52819), + Enable: __webpack_require__(4074), + Friction: __webpack_require__(40831), + Gravity: __webpack_require__(26775), + Immovable: __webpack_require__(9437), + Mass: __webpack_require__(30621), + OverlapCirc: __webpack_require__(72441), + OverlapRect: __webpack_require__(47956), + Pushable: __webpack_require__(62121), + Size: __webpack_require__(29384), + Velocity: __webpack_require__(15098) + +}; + + +/***/ }), + +/***/ 37747: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Arcade Physics consts. + * + * @ignore + */ + +var CONST = { + + /** + * Dynamic Body. + * + * @name Phaser.Physics.Arcade.DYNAMIC_BODY + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#physicsType + * @see Phaser.Physics.Arcade.Group#physicsType + */ + DYNAMIC_BODY: 0, + + /** + * Static Body. + * + * @name Phaser.Physics.Arcade.STATIC_BODY + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#physicsType + * @see Phaser.Physics.Arcade.StaticBody#physicsType + */ + STATIC_BODY: 1, + + /** + * Arcade Physics Group containing Dynamic Bodies. + * + * @name Phaser.Physics.Arcade.GROUP + * @readonly + * @type {number} + * @since 3.0.0 + */ + GROUP: 2, + + /** + * A Tilemap Layer. + * + * @name Phaser.Physics.Arcade.TILEMAPLAYER + * @readonly + * @type {number} + * @since 3.0.0 + */ + TILEMAPLAYER: 3, + + /** + * Facing no direction (initial value). + * + * @name Phaser.Physics.Arcade.FACING_NONE + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#facing + */ + FACING_NONE: 10, + + /** + * Facing up. + * + * @name Phaser.Physics.Arcade.FACING_UP + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#facing + */ + FACING_UP: 11, + + /** + * Facing down. + * + * @name Phaser.Physics.Arcade.FACING_DOWN + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#facing + */ + FACING_DOWN: 12, + + /** + * Facing left. + * + * @name Phaser.Physics.Arcade.FACING_LEFT + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#facing + */ + FACING_LEFT: 13, + + /** + * Facing right. + * + * @name Phaser.Physics.Arcade.FACING_RIGHT + * @readonly + * @type {number} + * @since 3.0.0 + * + * @see Phaser.Physics.Arcade.Body#facing + */ + FACING_RIGHT: 14 + +}; + +module.exports = CONST; + + +/***/ }), + +/***/ 20009: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics World Collide Event. + * + * This event is dispatched by an Arcade Physics World instance if two bodies collide _and_ at least + * one of them has their [onCollide]{@link Phaser.Physics.Arcade.Body#onCollide} property set to `true`. + * + * It provides an alternative means to handling collide events rather than using the callback approach. + * + * Listen to it from a Scene using: `this.physics.world.on('collide', listener)`. + * + * Please note that 'collide' and 'overlap' are two different things in Arcade Physics. + * + * @event Phaser.Physics.Arcade.Events#COLLIDE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject1 - The first Game Object involved in the collision. This is the parent of `body1`. + * @param {Phaser.GameObjects.GameObject} gameObject2 - The second Game Object involved in the collision. This is the parent of `body2`. + * @param {Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody} body1 - The first Physics Body involved in the collision. + * @param {Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody} body2 - The second Physics Body involved in the collision. + */ +module.exports = 'collide'; + + +/***/ }), + +/***/ 36768: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics World Overlap Event. + * + * This event is dispatched by an Arcade Physics World instance if two bodies overlap _and_ at least + * one of them has their [onOverlap]{@link Phaser.Physics.Arcade.Body#onOverlap} property set to `true`. + * + * It provides an alternative means to handling overlap events rather than using the callback approach. + * + * Listen to it from a Scene using: `this.physics.world.on('overlap', listener)`. + * + * Please note that 'collide' and 'overlap' are two different things in Arcade Physics. + * + * @event Phaser.Physics.Arcade.Events#OVERLAP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject1 - The first Game Object involved in the overlap. This is the parent of `body1`. + * @param {Phaser.GameObjects.GameObject} gameObject2 - The second Game Object involved in the overlap. This is the parent of `body2`. + * @param {Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody} body1 - The first Physics Body involved in the overlap. + * @param {Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody} body2 - The second Physics Body involved in the overlap. + */ +module.exports = 'overlap'; + + +/***/ }), + +/***/ 60473: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics World Pause Event. + * + * This event is dispatched by an Arcade Physics World instance when it is paused. + * + * Listen to it from a Scene using: `this.physics.world.on('pause', listener)`. + * + * @event Phaser.Physics.Arcade.Events#PAUSE + * @type {string} + * @since 3.0.0 + */ +module.exports = 'pause'; + + +/***/ }), + +/***/ 89954: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics World Resume Event. + * + * This event is dispatched by an Arcade Physics World instance when it resumes from a paused state. + * + * Listen to it from a Scene using: `this.physics.world.on('resume', listener)`. + * + * @event Phaser.Physics.Arcade.Events#RESUME + * @type {string} + * @since 3.0.0 + */ +module.exports = 'resume'; + + +/***/ }), + +/***/ 61804: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics Tile Collide Event. + * + * This event is dispatched by an Arcade Physics World instance if a body collides with a Tile _and_ + * has its [onCollide]{@link Phaser.Physics.Arcade.Body#onCollide} property set to `true`. + * + * It provides an alternative means to handling collide events rather than using the callback approach. + * + * Listen to it from a Scene using: `this.physics.world.on('tilecollide', listener)`. + * + * Please note that 'collide' and 'overlap' are two different things in Arcade Physics. + * + * @event Phaser.Physics.Arcade.Events#TILE_COLLIDE + * @type {string} + * @since 3.16.1 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object involved in the collision. This is the parent of `body`. + * @param {Phaser.Tilemaps.Tile} tile - The tile the body collided with. + * @param {Phaser.Physics.Arcade.Body} body - The Arcade Physics Body of the Game Object involved in the collision. + */ +module.exports = 'tilecollide'; + + +/***/ }), + +/***/ 7161: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics Tile Overlap Event. + * + * This event is dispatched by an Arcade Physics World instance if a body overlaps with a Tile _and_ + * has its [onOverlap]{@link Phaser.Physics.Arcade.Body#onOverlap} property set to `true`. + * + * It provides an alternative means to handling overlap events rather than using the callback approach. + * + * Listen to it from a Scene using: `this.physics.world.on('tileoverlap', listener)`. + * + * Please note that 'collide' and 'overlap' are two different things in Arcade Physics. + * + * @event Phaser.Physics.Arcade.Events#TILE_OVERLAP + * @type {string} + * @since 3.16.1 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object involved in the overlap. This is the parent of `body`. + * @param {Phaser.Tilemaps.Tile} tile - The tile the body overlapped. + * @param {Phaser.Physics.Arcade.Body} body - The Arcade Physics Body of the Game Object involved in the overlap. + */ +module.exports = 'tileoverlap'; + + +/***/ }), + +/***/ 34689: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics World Bounds Event. + * + * This event is dispatched by an Arcade Physics World instance if a body makes contact with the world bounds _and_ + * it has its [onWorldBounds]{@link Phaser.Physics.Arcade.Body#onWorldBounds} property set to `true`. + * + * It provides an alternative means to handling collide events rather than using the callback approach. + * + * Listen to it from a Scene using: `this.physics.world.on('worldbounds', listener)`. + * + * @event Phaser.Physics.Arcade.Events#WORLD_BOUNDS + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Arcade Physics Body that hit the world bounds. + * @param {boolean} up - Is the Body blocked up? I.e. collided with the top of the world bounds. + * @param {boolean} down - Is the Body blocked down? I.e. collided with the bottom of the world bounds. + * @param {boolean} left - Is the Body blocked left? I.e. collided with the left of the world bounds. + * @param {boolean} right - Is the Body blocked right? I.e. collided with the right of the world bounds. + */ +module.exports = 'worldbounds'; + + +/***/ }), + +/***/ 16006: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Arcade Physics World Step Event. + * + * This event is dispatched by an Arcade Physics World instance whenever a physics step is run. + * It is emitted _after_ the bodies and colliders have been updated. + * + * In high framerate settings this can be multiple times per game frame. + * + * Listen to it from a Scene using: `this.physics.world.on('worldstep', listener)`. + * + * @event Phaser.Physics.Arcade.Events#WORLD_STEP + * @type {string} + * @since 3.18.0 + * + * @param {number} delta - The delta time amount of this step, in seconds. + */ +module.exports = 'worldstep'; + + +/***/ }), + +/***/ 63012: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Arcade.Events + */ + +module.exports = { + + COLLIDE: __webpack_require__(20009), + OVERLAP: __webpack_require__(36768), + PAUSE: __webpack_require__(60473), + RESUME: __webpack_require__(89954), + TILE_COLLIDE: __webpack_require__(61804), + TILE_OVERLAP: __webpack_require__(7161), + WORLD_BOUNDS: __webpack_require__(34689), + WORLD_STEP: __webpack_require__(16006) + +}; + + +/***/ }), + +/***/ 27064: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(37747); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Physics.Arcade + */ + +var Arcade = { + + ArcadePhysics: __webpack_require__(86689), + Body: __webpack_require__(37742), + Collider: __webpack_require__(79342), + Components: __webpack_require__(92209), + Events: __webpack_require__(63012), + Factory: __webpack_require__(66022), + GetCollidesWith: __webpack_require__(79599), + GetOverlapX: __webpack_require__(64897), + GetOverlapY: __webpack_require__(45170), + SeparateX: __webpack_require__(14087), + SeparateY: __webpack_require__(89936), + Group: __webpack_require__(60758), + Image: __webpack_require__(71289), + Sprite: __webpack_require__(13759), + StaticBody: __webpack_require__(72624), + StaticGroup: __webpack_require__(71464), + Tilemap: __webpack_require__(55173), + World: __webpack_require__(82248) + +}; + +// Merge in the consts +Arcade = Extend(false, Arcade, CONST); + +module.exports = Arcade; + + +/***/ }), + +/***/ 96602: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * A function to process the collision callbacks between a single tile and an Arcade Physics enabled Game Object. + * + * @function Phaser.Physics.Arcade.Tilemap.ProcessTileCallbacks + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.Tile} tile - The Tile to process. + * @param {Phaser.GameObjects.Sprite} sprite - The Game Object to process with the Tile. + * + * @return {boolean} The result of the callback, `true` for further processing, or `false` to skip this pair. + */ +var ProcessTileCallbacks = function (tile, sprite) +{ + // Tile callbacks take priority over layer level callbacks + if (tile.collisionCallback) + { + return !tile.collisionCallback.call(tile.collisionCallbackContext, sprite, tile); + } + else if (tile.layer.callbacks[tile.index]) + { + return !tile.layer.callbacks[tile.index].callback.call( + tile.layer.callbacks[tile.index].callbackContext, sprite, tile + ); + } + + return true; +}; + +module.exports = ProcessTileCallbacks; + + +/***/ }), + +/***/ 36294: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Internal function to process the separation of a physics body from a tile. + * + * @function Phaser.Physics.Arcade.Tilemap.ProcessTileSeparationX + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. + * @param {number} x - The x separation amount. + */ +var ProcessTileSeparationX = function (body, x) +{ + if (x < 0) + { + body.blocked.none = false; + body.blocked.left = true; + } + else if (x > 0) + { + body.blocked.none = false; + body.blocked.right = true; + } + + body.position.x -= x; + body.updateCenter(); + + if (body.bounce.x === 0) + { + body.velocity.x = 0; + } + else + { + body.velocity.x = -body.velocity.x * body.bounce.x; + } +}; + +module.exports = ProcessTileSeparationX; + + +/***/ }), + +/***/ 67013: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Internal function to process the separation of a physics body from a tile. + * + * @function Phaser.Physics.Arcade.Tilemap.ProcessTileSeparationY + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. + * @param {number} y - The y separation amount. + */ +var ProcessTileSeparationY = function (body, y) +{ + if (y < 0) + { + body.blocked.none = false; + body.blocked.up = true; + } + else if (y > 0) + { + body.blocked.none = false; + body.blocked.down = true; + } + + body.position.y -= y; + body.updateCenter(); + + if (body.bounce.y === 0) + { + body.velocity.y = 0; + } + else + { + body.velocity.y = -body.velocity.y * body.bounce.y; + } +}; + +module.exports = ProcessTileSeparationY; + + +/***/ }), + +/***/ 40012: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TileCheckX = __webpack_require__(21329); +var TileCheckY = __webpack_require__(53442); +var TileIntersectsBody = __webpack_require__(2483); + +/** + * The core separation function to separate a physics body and a tile. + * + * @function Phaser.Physics.Arcade.Tilemap.SeparateTile + * @since 3.0.0 + * + * @param {number} i - The index of the tile within the map data. + * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. + * @param {Phaser.Tilemaps.Tile} tile - The tile to collide against. + * @param {Phaser.Geom.Rectangle} tileWorldRect - A rectangle-like object defining the dimensions of the tile. + * @param {Phaser.Tilemaps.TilemapLayer} tilemapLayer - The tilemapLayer to collide against. + * @param {number} tileBias - The tile bias value. Populated by the `World.TILE_BIAS` constant. + * @param {boolean} isLayer - Is this check coming from a TilemapLayer or an array of tiles? + * + * @return {boolean} `true` if the body was separated, otherwise `false`. + */ +var SeparateTile = function (i, body, tile, tileWorldRect, tilemapLayer, tileBias, isLayer) +{ + var tileLeft = tileWorldRect.left; + var tileTop = tileWorldRect.top; + var tileRight = tileWorldRect.right; + var tileBottom = tileWorldRect.bottom; + var faceHorizontal = tile.faceLeft || tile.faceRight; + var faceVertical = tile.faceTop || tile.faceBottom; + + if (!isLayer) + { + faceHorizontal = true; + faceVertical = true; + } + + // We don't need to go any further if this tile doesn't actually have any colliding faces. This + // could happen if the tile was meant to be collided with re: a callback, but otherwise isn't + // needed for separation. + if (!faceHorizontal && !faceVertical) + { + return false; + } + + var ox = 0; + var oy = 0; + var minX = 0; + var minY = 1; + + if (body.deltaAbsX() > body.deltaAbsY()) + { + // Moving faster horizontally, check X axis first + minX = -1; + } + else if (body.deltaAbsX() < body.deltaAbsY()) + { + // Moving faster vertically, check Y axis first + minY = -1; + } + + if (body.deltaX() !== 0 && body.deltaY() !== 0 && faceHorizontal && faceVertical) + { + // We only need do this if both axes have colliding faces AND we're moving in both + // directions + minX = Math.min(Math.abs(body.position.x - tileRight), Math.abs(body.right - tileLeft)); + minY = Math.min(Math.abs(body.position.y - tileBottom), Math.abs(body.bottom - tileTop)); + } + + if (minX < minY) + { + if (faceHorizontal) + { + ox = TileCheckX(body, tile, tileLeft, tileRight, tileBias, isLayer); + + // That's horizontal done, check if we still intersects? If not then we can return now + if (ox !== 0 && !TileIntersectsBody(tileWorldRect, body)) + { + return true; + } + } + + if (faceVertical) + { + oy = TileCheckY(body, tile, tileTop, tileBottom, tileBias, isLayer); + } + } + else + { + if (faceVertical) + { + oy = TileCheckY(body, tile, tileTop, tileBottom, tileBias, isLayer); + + // That's vertical done, check if we still intersects? If not then we can return now + if (oy !== 0 && !TileIntersectsBody(tileWorldRect, body)) + { + return true; + } + } + + if (faceHorizontal) + { + ox = TileCheckX(body, tile, tileLeft, tileRight, tileBias, isLayer); + } + } + + return (ox !== 0 || oy !== 0); +}; + +module.exports = SeparateTile; + + +/***/ }), + +/***/ 21329: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ProcessTileSeparationX = __webpack_require__(36294); + +/** + * Check the body against the given tile on the X axis. + * Used internally by the SeparateTile function. + * + * @function Phaser.Physics.Arcade.Tilemap.TileCheckX + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. + * @param {Phaser.Tilemaps.Tile} tile - The tile to check. + * @param {number} tileLeft - The left position of the tile within the tile world. + * @param {number} tileRight - The right position of the tile within the tile world. + * @param {number} tileBias - The tile bias value. Populated by the `World.TILE_BIAS` constant. + * @param {boolean} isLayer - Is this check coming from a TilemapLayer or an array of tiles? + * + * @return {number} The amount of separation that occurred. + */ +var TileCheckX = function (body, tile, tileLeft, tileRight, tileBias, isLayer) +{ + var ox = 0; + + var faceLeft = tile.faceLeft; + var faceRight = tile.faceRight; + var collideLeft = tile.collideLeft; + var collideRight = tile.collideRight; + + if (!isLayer) + { + faceLeft = true; + faceRight = true; + collideLeft = true; + collideRight = true; + } + + if (body.deltaX() < 0 && collideRight && body.checkCollision.left) + { + // Body is moving LEFT + if (faceRight && body.x < tileRight) + { + ox = body.x - tileRight; + + if (ox < -tileBias) + { + ox = 0; + } + } + } + else if (body.deltaX() > 0 && collideLeft && body.checkCollision.right) + { + // Body is moving RIGHT + if (faceLeft && body.right > tileLeft) + { + ox = body.right - tileLeft; + + if (ox > tileBias) + { + ox = 0; + } + } + } + + if (ox !== 0) + { + if (body.customSeparateX) + { + body.overlapX = ox; + } + else + { + ProcessTileSeparationX(body, ox); + } + } + + return ox; +}; + +module.exports = TileCheckX; + + +/***/ }), + +/***/ 53442: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ProcessTileSeparationY = __webpack_require__(67013); + +/** + * Check the body against the given tile on the Y axis. + * Used internally by the SeparateTile function. + * + * @function Phaser.Physics.Arcade.Tilemap.TileCheckY + * @since 3.0.0 + * + * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate. + * @param {Phaser.Tilemaps.Tile} tile - The tile to check. + * @param {number} tileTop - The top position of the tile within the tile world. + * @param {number} tileBottom - The bottom position of the tile within the tile world. + * @param {number} tileBias - The tile bias value. Populated by the `World.TILE_BIAS` constant. + * @param {boolean} isLayer - Is this check coming from a TilemapLayer or an array of tiles? + * + * @return {number} The amount of separation that occurred. + */ +var TileCheckY = function (body, tile, tileTop, tileBottom, tileBias, isLayer) +{ + var oy = 0; + + var faceTop = tile.faceTop; + var faceBottom = tile.faceBottom; + var collideUp = tile.collideUp; + var collideDown = tile.collideDown; + + if (!isLayer) + { + faceTop = true; + faceBottom = true; + collideUp = true; + collideDown = true; + } + + if (body.deltaY() < 0 && collideDown && body.checkCollision.up) + { + // Body is moving UP + if (faceBottom && body.y < tileBottom) + { + oy = body.y - tileBottom; + + if (oy < -tileBias) + { + oy = 0; + } + } + } + else if (body.deltaY() > 0 && collideUp && body.checkCollision.down) + { + // Body is moving DOWN + if (faceTop && body.bottom > tileTop) + { + oy = body.bottom - tileTop; + + if (oy > tileBias) + { + oy = 0; + } + } + } + + if (oy !== 0) + { + if (body.customSeparateY) + { + body.overlapY = oy; + } + else + { + ProcessTileSeparationY(body, oy); + } + } + + return oy; +}; + +module.exports = TileCheckY; + + +/***/ }), + +/***/ 2483: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks for intersection between the given tile rectangle-like object and an Arcade Physics body. + * + * @function Phaser.Physics.Arcade.Tilemap.TileIntersectsBody + * @since 3.0.0 + * + * @param {{ left: number, right: number, top: number, bottom: number }} tileWorldRect - A rectangle object that defines the tile placement in the world. + * @param {Phaser.Physics.Arcade.Body} body - The body to check for intersection against. + * + * @return {boolean} Returns `true` of the tile intersects with the body, otherwise `false`. + */ +var TileIntersectsBody = function (tileWorldRect, body) +{ + // Currently, all bodies are treated as rectangles when colliding with a Tile. + + return !( + body.right <= tileWorldRect.left || + body.bottom <= tileWorldRect.top || + body.position.x >= tileWorldRect.right || + body.position.y >= tileWorldRect.bottom + ); +}; + +module.exports = TileIntersectsBody; + + +/***/ }), + +/***/ 55173: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Arcade.Tilemap + */ + +var Tilemap = { + + ProcessTileCallbacks: __webpack_require__(96602), + ProcessTileSeparationX: __webpack_require__(36294), + ProcessTileSeparationY: __webpack_require__(67013), + SeparateTile: __webpack_require__(40012), + TileCheckX: __webpack_require__(21329), + TileCheckY: __webpack_require__(53442), + TileIntersectsBody: __webpack_require__(2483) + +}; + +module.exports = Tilemap; + + +/***/ }), + +/***/ 44563: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics + */ + +/** + * @namespace Phaser.Types.Physics + */ + +module.exports = { + + Arcade: __webpack_require__(27064), + Matter: __webpack_require__(3875) + +}; + + +/***/ }), + +/***/ 68174: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * + * The Body Bounds class contains methods to help you extract the world coordinates from various points around + * the bounds of a Matter Body. Because Matter bodies are positioned based on their center of mass, and not a + * dimension based center, you often need to get the bounds coordinates in order to properly align them in the world. + * + * You can access this class via the MatterPhysics class from a Scene, i.e.: + * + * ```javascript + * this.matter.bodyBounds.getTopLeft(body); + * ``` + * + * See also the `MatterPhysics.alignBody` method. + * + * @class BodyBounds + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.22.0 + */ +var BodyBounds = new Class({ + + initialize: + + function BodyBounds () + { + /** + * A Vector2 that stores the temporary bounds center value during calculations by methods in this class. + * + * @name Phaser.Physics.Matter.BodyBounds#boundsCenter + * @type {Phaser.Math.Vector2} + * @since 3.22.0 + */ + this.boundsCenter = new Vector2(); + + /** + * A Vector2 that stores the temporary center diff values during calculations by methods in this class. + * + * @name Phaser.Physics.Matter.BodyBounds#centerDiff + * @type {Phaser.Math.Vector2} + * @since 3.22.0 + */ + this.centerDiff = new Vector2(); + }, + + /** + * Parses the given body to get the bounds diff values from it. + * + * They're stored in this class in the temporary properties `boundsCenter` and `centerDiff`. + * + * This method is called automatically by all other methods in this class. + * + * @method Phaser.Physics.Matter.BodyBounds#parseBody + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the bounds position from. + * + * @return {boolean} `true` if it was able to get the bounds, otherwise `false`. + */ + parseBody: function (body) + { + body = (body.hasOwnProperty('body')) ? body.body : body; + + if (!body.hasOwnProperty('bounds') || !body.hasOwnProperty('centerOfMass')) + { + return false; + } + + var boundsCenter = this.boundsCenter; + var centerDiff = this.centerDiff; + + var boundsWidth = body.bounds.max.x - body.bounds.min.x; + var boundsHeight = body.bounds.max.y - body.bounds.min.y; + + var bodyCenterX = boundsWidth * body.centerOfMass.x; + var bodyCenterY = boundsHeight * body.centerOfMass.y; + + boundsCenter.set(boundsWidth / 2, boundsHeight / 2); + centerDiff.set(bodyCenterX - boundsCenter.x, bodyCenterY - boundsCenter.y); + + return true; + }, + + /** + * Takes a Body and returns the world coordinates of the top-left of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getTopLeft + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getTopLeft: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x + center.x + diff.x, + y + center.y + diff.y + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the top-center of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getTopCenter + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getTopCenter: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x + diff.x, + y + center.y + diff.y + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the top-right of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getTopRight + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getTopRight: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x - (center.x - diff.x), + y + center.y + diff.y + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the left-center of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getLeftCenter + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getLeftCenter: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x + center.x + diff.x, + y + diff.y + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the center of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getCenter + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getCenter: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var diff = this.centerDiff; + + return new Vector2( + x + diff.x, + y + diff.y + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the right-center of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getRightCenter + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getRightCenter: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x - (center.x - diff.x), + y + diff.y + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the bottom-left of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getBottomLeft + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getBottomLeft: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x + center.x + diff.x, + y - (center.y - diff.y) + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the bottom-center of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getBottomCenter + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getBottomCenter: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x + diff.x, + y - (center.y - diff.y) + ); + } + + return false; + }, + + /** + * Takes a Body and returns the world coordinates of the bottom-right of its _bounds_. + * + * Body bounds are updated by Matter each step and factor in scale and rotation. + * This will return the world coordinate based on the bodies _current_ position and bounds. + * + * @method Phaser.Physics.Matter.BodyBounds#getBottomRight + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to get the position from. + * @param {number} [x=0] - Optional horizontal offset to add to the returned coordinates. + * @param {number} [y=0] - Optional vertical offset to add to the returned coordinates. + * + * @return {(Phaser.Math.Vector2|false)} A Vector2 containing the coordinates, or `false` if it was unable to parse the body. + */ + getBottomRight: function (body, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + if (this.parseBody(body)) + { + var center = this.boundsCenter; + var diff = this.centerDiff; + + return new Vector2( + x - (center.x - diff.x), + y - (center.y - diff.y) + ); + } + + return false; + } + +}); + +module.exports = BodyBounds; + + +/***/ }), + +/***/ 19933: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Matter.Matter + */ + +var Matter = __webpack_require__(6790); + +Matter.Body = __webpack_require__(22562); +Matter.Composite = __webpack_require__(69351); +Matter.World = __webpack_require__(4372); + +Matter.Collision = __webpack_require__(52284); +Matter.Detector = __webpack_require__(81388); +Matter.Pairs = __webpack_require__(99561); +Matter.Pair = __webpack_require__(4506); +Matter.Query = __webpack_require__(73296); +Matter.Resolver = __webpack_require__(66272); + +Matter.Constraint = __webpack_require__(48140); + +Matter.Common = __webpack_require__(53402); +Matter.Engine = __webpack_require__(48413); +Matter.Events = __webpack_require__(35810); +Matter.Sleeping = __webpack_require__(53614); +Matter.Plugin = __webpack_require__(73832); + +Matter.Bodies = __webpack_require__(66280); +Matter.Composites = __webpack_require__(74116); + +Matter.Axes = __webpack_require__(66615); +Matter.Bounds = __webpack_require__(15647); +Matter.Svg = __webpack_require__(74058); +Matter.Vector = __webpack_require__(31725); +Matter.Vertices = __webpack_require__(41598); + +// aliases + +Matter.World.add = Matter.Composite.add; +Matter.World.remove = Matter.Composite.remove; +Matter.World.addComposite = Matter.Composite.addComposite; +Matter.World.addBody = Matter.Composite.addBody; +Matter.World.addConstraint = Matter.Composite.addConstraint; +Matter.World.clear = Matter.Composite.clear; + +module.exports = Matter; + + +/***/ }), + +/***/ 28137: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bodies = __webpack_require__(66280); +var Class = __webpack_require__(83419); +var Composites = __webpack_require__(74116); +var Constraint = __webpack_require__(48140); +var Svg = __webpack_require__(74058); +var MatterGameObject = __webpack_require__(75803); +var MatterImage = __webpack_require__(23181); +var MatterSprite = __webpack_require__(34803); +var MatterTileBody = __webpack_require__(73834); +var PhysicsEditorParser = __webpack_require__(19496); +var PhysicsJSONParser = __webpack_require__(85791); +var PointerConstraint = __webpack_require__(98713); +var Vertices = __webpack_require__(41598); + +/** + * @classdesc + * The Matter Factory is responsible for quickly creating a variety of different types of + * bodies, constraints and Game Objects and adding them into the physics world. + * + * You access the factory from within a Scene using `add`: + * + * ```javascript + * this.matter.add.rectangle(x, y, width, height); + * ``` + * + * Use of the Factory is optional. All of the objects it creates can also be created + * directly via your own code or constructors. It is provided as a means to keep your + * code concise. + * + * @class Factory + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.World} world - The Matter World which this Factory adds to. + */ +var Factory = new Class({ + + initialize: + + function Factory (world) + { + /** + * The Matter World which this Factory adds to. + * + * @name Phaser.Physics.Matter.Factory#world + * @type {Phaser.Physics.Matter.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The Scene which this Factory's Matter World belongs to. + * + * @name Phaser.Physics.Matter.Factory#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = world.scene; + + /** + * A reference to the Scene.Systems this Matter Physics instance belongs to. + * + * @name Phaser.Physics.Matter.Factory#sys + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.sys = world.scene.sys; + }, + + /** + * Creates a new rigid rectangular Body and adds it to the World. + * + * @method Phaser.Physics.Matter.Factory#rectangle + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the center of the Body. + * @param {number} y - The Y coordinate of the center of the Body. + * @param {number} width - The width of the Body. + * @param {number} height - The height of the Body. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + rectangle: function (x, y, width, height, options) + { + var body = Bodies.rectangle(x, y, width, height, options); + + this.world.add(body); + + return body; + }, + + /** + * Creates a new rigid trapezoidal Body and adds it to the World. + * + * @method Phaser.Physics.Matter.Factory#trapezoid + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the center of the Body. + * @param {number} y - The Y coordinate of the center of the Body. + * @param {number} width - The width of the trapezoid Body. + * @param {number} height - The height of the trapezoid Body. + * @param {number} slope - The slope of the trapezoid. 0 creates a rectangle, while 1 creates a triangle. Positive values make the top side shorter, while negative values make the bottom side shorter. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + trapezoid: function (x, y, width, height, slope, options) + { + var body = Bodies.trapezoid(x, y, width, height, slope, options); + + this.world.add(body); + + return body; + }, + + /** + * Creates a new rigid circular Body and adds it to the World. + * + * @method Phaser.Physics.Matter.Factory#circle + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the center of the Body. + * @param {number} y - The Y coordinate of the center of the Body. + * @param {number} radius - The radius of the circle. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * @param {number} [maxSides] - The maximum amount of sides to use for the polygon which will approximate this circle. + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + circle: function (x, y, radius, options, maxSides) + { + var body = Bodies.circle(x, y, radius, options, maxSides); + + this.world.add(body); + + return body; + }, + + /** + * Creates a new rigid polygonal Body and adds it to the World. + * + * @method Phaser.Physics.Matter.Factory#polygon + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the center of the Body. + * @param {number} y - The Y coordinate of the center of the Body. + * @param {number} sides - The number of sides the polygon will have. + * @param {number} radius - The "radius" of the polygon, i.e. the distance from its center to any vertex. This is also the radius of its circumcircle. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + polygon: function (x, y, sides, radius, options) + { + var body = Bodies.polygon(x, y, sides, radius, options); + + this.world.add(body); + + return body; + }, + + /** + * Creates a body using the supplied vertices (or an array containing multiple sets of vertices) and adds it to the World. + * If the vertices are convex, they will pass through as supplied. Otherwise, if the vertices are concave, they will be decomposed. Note that this process is not guaranteed to support complex sets of vertices, e.g. ones with holes. + * + * @method Phaser.Physics.Matter.Factory#fromVertices + * @since 3.0.0 + * + * @param {number} x - The X coordinate of the center of the Body. + * @param {number} y - The Y coordinate of the center of the Body. + * @param {(string|array)} vertexSets - The vertices data. Either a path string or an array of vertices. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * @param {boolean} [flagInternal=false] - Flag internal edges (coincident part edges) + * @param {number} [removeCollinear=0.01] - Whether Matter.js will discard collinear edges (to improve performance). + * @param {number} [minimumArea=10] - During decomposition discard parts that have an area less than this. + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + fromVertices: function (x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea) + { + if (typeof vertexSets === 'string') + { + vertexSets = Vertices.fromPath(vertexSets); + } + + var body = Bodies.fromVertices(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea); + + this.world.add(body); + + return body; + }, + + /** + * Creates a body using data exported from the application PhysicsEditor (https://www.codeandweb.com/physicseditor) + * + * The PhysicsEditor file should be loaded as JSON: + * + * ```javascript + * preload () + * { + * this.load.json('vehicles', 'assets/vehicles.json); + * } + * + * create () + * { + * const vehicleShapes = this.cache.json.get('vehicles'); + * this.matter.add.fromPhysicsEditor(400, 300, vehicleShapes.truck); + * } + * ``` + * + * Do not pass the entire JSON file to this method, but instead pass one of the shapes contained within it. + * + * If you pas in an `options` object, any settings in there will override those in the PhysicsEditor config object. + * + * @method Phaser.Physics.Matter.Factory#fromPhysicsEditor + * @since 3.22.0 + * + * @param {number} x - The horizontal world location of the body. + * @param {number} y - The vertical world location of the body. + * @param {any} config - The JSON data exported from PhysicsEditor. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World? + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + fromPhysicsEditor: function (x, y, config, options, addToWorld) + { + if (addToWorld === undefined) { addToWorld = true; } + + var body = PhysicsEditorParser.parseBody(x, y, config, options); + + if (addToWorld && !this.world.has(body)) + { + this.world.add(body); + } + + return body; + }, + + /** + * Creates a body using the path data from an SVG file. + * + * SVG Parsing requires the pathseg polyfill from https://github.com/progers/pathseg + * + * The SVG file should be loaded as XML, as this method requires the ability to extract + * the path data from it. I.e.: + * + * ```javascript + * preload () + * { + * this.load.xml('face', 'assets/face.svg); + * } + * + * create () + * { + * this.matter.add.fromSVG(400, 300, this.cache.xml.get('face')); + * } + * ``` + * + * @method Phaser.Physics.Matter.Factory#fromSVG + * @since 3.22.0 + * + * @param {number} x - The X coordinate of the body. + * @param {number} y - The Y coordinate of the body. + * @param {object} xml - The SVG Path data. + * @param {number} [scale=1] - Scale the vertices by this amount after creation. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World? + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + fromSVG: function (x, y, xml, scale, options, addToWorld) + { + if (scale === undefined) { scale = 1; } + if (options === undefined) { options = {}; } + if (addToWorld === undefined) { addToWorld = true; } + + var path = xml.getElementsByTagName('path'); + var vertexSets = []; + + for (var i = 0; i < path.length; i++) + { + var points = Svg.pathToVertices(path[i], 30); + + if (scale !== 1) + { + Vertices.scale(points, scale, scale); + } + + vertexSets.push(points); + } + + var body = Bodies.fromVertices(x, y, vertexSets, options); + + if (addToWorld) + { + this.world.add(body); + } + + return body; + }, + + /** + * Creates a body using the supplied physics data, as provided by a JSON file. + * + * The data file should be loaded as JSON: + * + * ```javascript + * preload () + * { + * this.load.json('ninjas', 'assets/ninjas.json); + * } + * + * create () + * { + * const ninjaShapes = this.cache.json.get('ninjas'); + * + * this.matter.add.fromJSON(400, 300, ninjaShapes.shinobi); + * } + * ``` + * + * Do not pass the entire JSON file to this method, but instead pass one of the shapes contained within it. + * + * If you pas in an `options` object, any settings in there will override those in the config object. + * + * The structure of the JSON file is as follows: + * + * ```text + * { + * 'generator_info': // The name of the application that created the JSON data + * 'shapeName': { + * 'type': // The type of body + * 'label': // Optional body label + * 'vertices': // An array, or an array of arrays, containing the vertex data in x/y object pairs + * } + * } + * ``` + * + * At the time of writing, only the Phaser Physics Tracer App exports in this format. + * + * @method Phaser.Physics.Matter.Factory#fromJSON + * @since 3.22.0 + * + * @param {number} x - The X coordinate of the body. + * @param {number} y - The Y coordinate of the body. + * @param {any} config - The JSON physics data. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World? + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + fromJSON: function (x, y, config, options, addToWorld) + { + if (options === undefined) { options = {}; } + if (addToWorld === undefined) { addToWorld = true; } + + var body = PhysicsJSONParser.parseBody(x, y, config, options); + + if (body && addToWorld) + { + this.world.add(body); + } + + return body; + }, + + /** + * Create a new composite containing Matter Image objects created in a grid arrangement. + * This function uses the body bounds to prevent overlaps. + * + * @method Phaser.Physics.Matter.Factory#imageStack + * @since 3.0.0 + * + * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} frame - An optional frame from the Texture this Game Object is rendering with. Set to `null` to skip this value. + * @param {number} x - The horizontal position of this composite in the world. + * @param {number} y - The vertical position of this composite in the world. + * @param {number} columns - The number of columns in the grid. + * @param {number} rows - The number of rows in the grid. + * @param {number} [columnGap=0] - The distance between each column. + * @param {number} [rowGap=0] - The distance between each row. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.CompositeType} A Matter JS Composite Stack. + */ + imageStack: function (key, frame, x, y, columns, rows, columnGap, rowGap, options) + { + if (columnGap === undefined) { columnGap = 0; } + if (rowGap === undefined) { rowGap = 0; } + if (options === undefined) { options = {}; } + + var world = this.world; + var displayList = this.sys.displayList; + + options.addToWorld = false; + + var stack = Composites.stack(x, y, columns, rows, columnGap, rowGap, function (x, y) + { + var image = new MatterImage(world, x, y, key, frame, options); + + displayList.add(image); + + return image.body; + }); + + world.add(stack); + + return stack; + }, + + /** + * Create a new composite containing bodies created in the callback in a grid arrangement. + * + * This function uses the body bounds to prevent overlaps. + * + * @method Phaser.Physics.Matter.Factory#stack + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this composite in the world. + * @param {number} y - The vertical position of this composite in the world. + * @param {number} columns - The number of columns in the grid. + * @param {number} rows - The number of rows in the grid. + * @param {number} columnGap - The distance between each column. + * @param {number} rowGap - The distance between each row. + * @param {function} callback - The callback that creates the stack. + * + * @return {MatterJS.CompositeType} A new composite containing objects created in the callback. + */ + stack: function (x, y, columns, rows, columnGap, rowGap, callback) + { + var stack = Composites.stack(x, y, columns, rows, columnGap, rowGap, callback); + + this.world.add(stack); + + return stack; + }, + + /** + * Create a new composite containing bodies created in the callback in a pyramid arrangement. + * This function uses the body bounds to prevent overlaps. + * + * @method Phaser.Physics.Matter.Factory#pyramid + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this composite in the world. + * @param {number} y - The vertical position of this composite in the world. + * @param {number} columns - The number of columns in the pyramid. + * @param {number} rows - The number of rows in the pyramid. + * @param {number} columnGap - The distance between each column. + * @param {number} rowGap - The distance between each row. + * @param {function} callback - The callback function to be invoked. + * + * @return {MatterJS.CompositeType} A Matter JS Composite pyramid. + */ + pyramid: function (x, y, columns, rows, columnGap, rowGap, callback) + { + var stack = Composites.pyramid(x, y, columns, rows, columnGap, rowGap, callback); + + this.world.add(stack); + + return stack; + }, + + /** + * Chains all bodies in the given composite together using constraints. + * + * @method Phaser.Physics.Matter.Factory#chain + * @since 3.0.0 + * + * @param {MatterJS.CompositeType} composite - The composite in which all bodies will be chained together sequentially. + * @param {number} xOffsetA - The horizontal offset of the BodyA constraint. This is a percentage based on the body size, not a world position. + * @param {number} yOffsetA - The vertical offset of the BodyA constraint. This is a percentage based on the body size, not a world position. + * @param {number} xOffsetB - The horizontal offset of the BodyB constraint. This is a percentage based on the body size, not a world position. + * @param {number} yOffsetB - The vertical offset of the BodyB constraint. This is a percentage based on the body size, not a world position. + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.CompositeType} The original composite that was passed to this method. + */ + chain: function (composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) + { + return Composites.chain(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options); + }, + + /** + * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces. + * + * @method Phaser.Physics.Matter.Factory#mesh + * @since 3.0.0 + * + * @param {MatterJS.CompositeType} composite - The composite in which all bodies will be chained together. + * @param {number} columns - The number of columns in the mesh. + * @param {number} rows - The number of rows in the mesh. + * @param {boolean} crossBrace - Create cross braces for the mesh as well? + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.CompositeType} The original composite that was passed to this method. + */ + mesh: function (composite, columns, rows, crossBrace, options) + { + return Composites.mesh(composite, columns, rows, crossBrace, options); + }, + + /** + * Creates a composite with a Newton's Cradle setup of bodies and constraints. + * + * @method Phaser.Physics.Matter.Factory#newtonsCradle + * @since 3.0.0 + * + * @param {number} x - The horizontal position of the start of the cradle. + * @param {number} y - The vertical position of the start of the cradle. + * @param {number} number - The number of balls in the cradle. + * @param {number} size - The radius of each ball in the cradle. + * @param {number} length - The length of the 'string' the balls hang from. + * + * @return {MatterJS.CompositeType} A Newton's cradle composite. + */ + newtonsCradle: function (x, y, number, size, length) + { + var composite = Composites.newtonsCradle(x, y, number, size, length); + + this.world.add(composite); + + return composite; + }, + + /** + * Creates a composite with simple car setup of bodies and constraints. + * + * @method Phaser.Physics.Matter.Factory#car + * @since 3.0.0 + * + * @param {number} x - The horizontal position of the car in the world. + * @param {number} y - The vertical position of the car in the world. + * @param {number} width - The width of the car chasis. + * @param {number} height - The height of the car chasis. + * @param {number} wheelSize - The radius of the car wheels. + * + * @return {MatterJS.CompositeType} A new composite car body. + */ + car: function (x, y, width, height, wheelSize) + { + var composite = Composites.car(x, y, width, height, wheelSize); + + this.world.add(composite); + + return composite; + }, + + /** + * Creates a simple soft body like object. + * + * @method Phaser.Physics.Matter.Factory#softBody + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this composite in the world. + * @param {number} y - The vertical position of this composite in the world. + * @param {number} columns - The number of columns in the Composite. + * @param {number} rows - The number of rows in the Composite. + * @param {number} columnGap - The distance between each column. + * @param {number} rowGap - The distance between each row. + * @param {boolean} crossBrace - `true` to create cross braces between the bodies, or `false` to create just straight braces. + * @param {number} particleRadius - The radius of this circlular composite. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [particleOptions] - An optional Body configuration object that is used to set initial Body properties on creation. + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [constraintOptions] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.CompositeType} A new composite simple soft body. + */ + softBody: function (x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) + { + var composite = Composites.softBody(x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions); + + this.world.add(composite); + + return composite; + }, + + /** + * This method is an alias for `Factory.constraint`. + * + * Constraints (or joints) are used for specifying that a fixed distance must be maintained + * between two bodies, or a body and a fixed world-space position. + * + * The stiffness of constraints can be modified to create springs or elastic. + * + * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` + * value (e.g. `0.7` or above). + * + * If the constraint is unstable, try lowering the `stiffness` value and / or increasing + * `constraintIterations` within the Matter Config. + * + * For compound bodies, constraints must be applied to the parent body and not one of its parts. + * + * @method Phaser.Physics.Matter.Factory#joint + * @since 3.0.0 + * + * @param {MatterJS.BodyType} bodyA - The first possible `Body` that this constraint is attached to. + * @param {MatterJS.BodyType} bodyB - The second possible `Body` that this constraint is attached to. + * @param {number} [length] - A Number that specifies the target resting length of the constraint. If not given it is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * @param {number} [stiffness=1] - A Number that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. A value of `1` means the constraint should be very stiff. A value of `0.2` means the constraint acts as a soft spring. + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.ConstraintType} A Matter JS Constraint. + */ + joint: function (bodyA, bodyB, length, stiffness, options) + { + return this.constraint(bodyA, bodyB, length, stiffness, options); + }, + + /** + * This method is an alias for `Factory.constraint`. + * + * Constraints (or joints) are used for specifying that a fixed distance must be maintained + * between two bodies, or a body and a fixed world-space position. + * + * The stiffness of constraints can be modified to create springs or elastic. + * + * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` + * value (e.g. `0.7` or above). + * + * If the constraint is unstable, try lowering the `stiffness` value and / or increasing + * `constraintIterations` within the Matter Config. + * + * For compound bodies, constraints must be applied to the parent body and not one of its parts. + * + * @method Phaser.Physics.Matter.Factory#spring + * @since 3.0.0 + * + * @param {MatterJS.BodyType} bodyA - The first possible `Body` that this constraint is attached to. + * @param {MatterJS.BodyType} bodyB - The second possible `Body` that this constraint is attached to. + * @param {number} [length] - A Number that specifies the target resting length of the constraint. If not given it is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * @param {number} [stiffness=1] - A Number that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. A value of `1` means the constraint should be very stiff. A value of `0.2` means the constraint acts as a soft spring. + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.ConstraintType} A Matter JS Constraint. + */ + spring: function (bodyA, bodyB, length, stiffness, options) + { + return this.constraint(bodyA, bodyB, length, stiffness, options); + }, + + /** + * Constraints (or joints) are used for specifying that a fixed distance must be maintained + * between two bodies, or a body and a fixed world-space position. + * + * The stiffness of constraints can be modified to create springs or elastic. + * + * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` + * value (e.g. `0.7` or above). + * + * If the constraint is unstable, try lowering the `stiffness` value and / or increasing + * `constraintIterations` within the Matter Config. + * + * For compound bodies, constraints must be applied to the parent body and not one of its parts. + * + * @method Phaser.Physics.Matter.Factory#constraint + * @since 3.0.0 + * + * @param {MatterJS.BodyType} bodyA - The first possible `Body` that this constraint is attached to. + * @param {MatterJS.BodyType} bodyB - The second possible `Body` that this constraint is attached to. + * @param {number} [length] - A Number that specifies the target resting length of the constraint. If not given it is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * @param {number} [stiffness=1] - A Number that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. A value of `1` means the constraint should be very stiff. A value of `0.2` means the constraint acts as a soft spring. + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.ConstraintType} A Matter JS Constraint. + */ + constraint: function (bodyA, bodyB, length, stiffness, options) + { + if (stiffness === undefined) { stiffness = 1; } + if (options === undefined) { options = {}; } + + options.bodyA = (bodyA.type === 'body') ? bodyA : bodyA.body; + options.bodyB = (bodyB.type === 'body') ? bodyB : bodyB.body; + + if (!isNaN(length)) + { + options.length = length; + } + + options.stiffness = stiffness; + + var constraint = Constraint.create(options); + + this.world.add(constraint); + + return constraint; + }, + + /** + * Constraints (or joints) are used for specifying that a fixed distance must be maintained + * between two bodies, or a body and a fixed world-space position. + * + * A world constraint has only one body, you should specify a `pointA` position in + * the constraint options parameter to attach the constraint to the world. + * + * The stiffness of constraints can be modified to create springs or elastic. + * + * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` + * value (e.g. `0.7` or above). + * + * If the constraint is unstable, try lowering the `stiffness` value and / or increasing + * `constraintIterations` within the Matter Config. + * + * For compound bodies, constraints must be applied to the parent body and not one of its parts. + * + * @method Phaser.Physics.Matter.Factory#worldConstraint + * @since 3.0.0 + * + * @param {MatterJS.BodyType} body - The Matter `Body` that this constraint is attached to. + * @param {number} [length] - A number that specifies the target resting length of the constraint. If not given it is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * @param {number} [stiffness=1] - A Number that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. A value of `1` means the constraint should be very stiff. A value of `0.2` means the constraint acts as a soft spring. + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.ConstraintType} A Matter JS Constraint. + */ + worldConstraint: function (body, length, stiffness, options) + { + if (stiffness === undefined) { stiffness = 1; } + if (options === undefined) { options = {}; } + + options.bodyB = (body.type === 'body') ? body : body.body; + + if (!isNaN(length)) + { + options.length = length; + } + + options.stiffness = stiffness; + + var constraint = Constraint.create(options); + + this.world.add(constraint); + + return constraint; + }, + + /** + * This method is an alias for `Factory.pointerConstraint`. + * + * A Pointer Constraint is a special type of constraint that allows you to click + * and drag bodies in a Matter World. It monitors the active Pointers in a Scene, + * and when one is pressed down it checks to see if that hit any part of any active + * body in the world. If it did, and the body has input enabled, it will begin to + * drag it until either released, or you stop it via the `stopDrag` method. + * + * You can adjust the stiffness, length and other properties of the constraint via + * the `options` object on creation. + * + * @method Phaser.Physics.Matter.Factory#mouseSpring + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.ConstraintType} A Matter JS Constraint. + */ + mouseSpring: function (options) + { + return this.pointerConstraint(options); + }, + + /** + * A Pointer Constraint is a special type of constraint that allows you to click + * and drag bodies in a Matter World. It monitors the active Pointers in a Scene, + * and when one is pressed down it checks to see if that hit any part of any active + * body in the world. If it did, and the body has input enabled, it will begin to + * drag it until either released, or you stop it via the `stopDrag` method. + * + * You can adjust the stiffness, length and other properties of the constraint via + * the `options` object on creation. + * + * @method Phaser.Physics.Matter.Factory#pointerConstraint + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Matter.MatterConstraintConfig} [options] - An optional Constraint configuration object that is used to set initial Constraint properties on creation. + * + * @return {MatterJS.ConstraintType} A Matter JS Constraint. + */ + pointerConstraint: function (options) + { + if (options === undefined) { options = {}; } + + if (!options.hasOwnProperty('render')) + { + options.render = { visible: false }; + } + + var pointerConstraint = new PointerConstraint(this.scene, this.world, options); + + this.world.add(pointerConstraint.constraint); + + return pointerConstraint; + }, + + /** + * Creates a Matter Physics Image Game Object. + * + * An Image is a light-weight Game Object useful for the display of static images in your game, + * such as logos, backgrounds, scenery or other non-animated elements. Images can have input + * events and physics bodies, or be tweened, tinted or scrolled. The main difference between an + * Image and a Sprite is that you cannot animate an Image as they do not have the Animation component. + * + * @method Phaser.Physics.Matter.Factory#image + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. Set to `null` to skip this value. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {Phaser.Physics.Matter.Image} The Matter Image Game Object. + */ + image: function (x, y, key, frame, options) + { + var image = new MatterImage(this.world, x, y, key, frame, options); + + this.sys.displayList.add(image); + + return image; + }, + + /** + * Creates a wrapper around a Tile that provides access to a corresponding Matter body. A tile can only + * have one Matter body associated with it. You can either pass in an existing Matter body for + * the tile or allow the constructor to create the corresponding body for you. If the Tile has a + * collision group (defined in Tiled), those shapes will be used to create the body. If not, the + * tile's rectangle bounding box will be used. + * + * The corresponding body will be accessible on the Tile itself via Tile.physics.matterBody. + * + * Note: not all Tiled collision shapes are supported. See + * Phaser.Physics.Matter.TileBody#setFromTileCollision for more information. + * + * @method Phaser.Physics.Matter.Factory#tileBody + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.Tile} tile - The target tile that should have a Matter body. + * @param {Phaser.Types.Physics.Matter.MatterTileOptions} [options] - Options to be used when creating the Matter body. + * + * @return {Phaser.Physics.Matter.TileBody} The Matter Tile Body Game Object. + */ + tileBody: function (tile, options) + { + return new MatterTileBody(this.world, tile, options); + }, + + /** + * Creates a Matter Physics Sprite Game Object. + * + * A Sprite Game Object is used for the display of both static and animated images in your game. + * Sprites can have input events and physics bodies. They can also be tweened, tinted, scrolled + * and animated. + * + * The main difference between a Sprite and an Image Game Object is that you cannot animate Images. + * As such, Sprites take a fraction longer to process and have a larger API footprint due to the Animation + * Component. If you do not require animation then you can safely use Images to replace Sprites in all cases. + * + * @method Phaser.Physics.Matter.Factory#sprite + * @since 3.0.0 + * + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {string} key - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. Set to `null` to skip this value. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {Phaser.Physics.Matter.Sprite} The Matter Sprite Game Object. + */ + sprite: function (x, y, key, frame, options) + { + var sprite = new MatterSprite(this.world, x, y, key, frame, options); + + this.sys.displayList.add(sprite); + this.sys.updateList.add(sprite); + + return sprite; + }, + + /** + * Takes an existing Game Object and injects all of the Matter Components into it. + * + * This enables you to use component methods such as `setVelocity` or `isSensor` directly from + * this Game Object. + * + * You can also pass in either a Matter Body Configuration object, or a Matter Body instance + * to link with this Game Object. + * + * @method Phaser.Physics.Matter.Factory#gameObject + * @since 3.3.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to inject the Matter Components in to. + * @param {(Phaser.Types.Physics.Matter.MatterBodyConfig|MatterJS.Body)} [options] - A Matter Body configuration object, or an instance of a Matter Body. + * @param {boolean} [addToWorld=true] - Add this Matter Body to the World? + * + * @return {(Phaser.Physics.Matter.Image|Phaser.Physics.Matter.Sprite|Phaser.GameObjects.GameObject)} The Game Object that had the Matter Components injected into it. + */ + gameObject: function (gameObject, options, addToWorld) + { + return MatterGameObject(this.world, gameObject, options, addToWorld); + }, + + /** + * Destroys this Factory. + * + * @method Phaser.Physics.Matter.Factory#destroy + * @since 3.5.0 + */ + destroy: function () + { + this.world = null; + this.scene = null; + this.sys = null; + } + +}); + +module.exports = Factory; + + +/***/ }), + +/***/ 75803: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Components = __webpack_require__(9503); +var GetFastValue = __webpack_require__(95540); +var Vector2 = __webpack_require__(26099); + +/** + * Internal function to check if the object has a getter or setter. + * + * @function hasGetterOrSetter + * @private + * + * @param {object} def - The object to check. + * + * @return {boolean} True if it has a getter or setter, otherwise false. + */ +function hasGetterOrSetter (def) +{ + return (!!def.get && typeof def.get === 'function') || (!!def.set && typeof def.set === 'function'); +} + +/** + * A Matter Game Object is a generic object that allows you to combine any Phaser Game Object, + * including those you have extended or created yourself, with all of the Matter Components. + * + * This enables you to use component methods such as `setVelocity` or `isSensor` directly from + * this Game Object. + * + * @function Phaser.Physics.Matter.MatterGameObject + * @since 3.3.0 + * + * @param {Phaser.Physics.Matter.World} world - The Matter world to add the body to. + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will have the Matter body applied to it. + * @param {(Phaser.Types.Physics.Matter.MatterBodyConfig|MatterJS.Body)} [options] - A Matter Body configuration object, or an instance of a Matter Body. + * @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World? + * + * @return {Phaser.GameObjects.GameObject} The Game Object that was created with the Matter body. + */ +var MatterGameObject = function (world, gameObject, options, addToWorld) +{ + if (options === undefined) { options = {}; } + if (addToWorld === undefined) { addToWorld = true; } + + var x = gameObject.x; + var y = gameObject.y; + + // Temp body pos to avoid body null checks + gameObject.body = { + temp: true, + position: { + x: x, + y: y + } + }; + + var mixins = [ + Components.Bounce, + Components.Collision, + Components.Force, + Components.Friction, + Components.Gravity, + Components.Mass, + Components.Sensor, + Components.SetBody, + Components.Sleep, + Components.Static, + Components.Transform, + Components.Velocity + ]; + + // First let's inject all of the components into the Game Object + mixins.forEach(function (mixin) + { + for (var key in mixin) + { + if (hasGetterOrSetter(mixin[key])) + { + Object.defineProperty(gameObject, key, { + get: mixin[key].get, + set: mixin[key].set + }); + } + else + { + Object.defineProperty(gameObject, key, {value: mixin[key]}); + } + } + + }); + + gameObject.world = world; + + gameObject._tempVec2 = new Vector2(x, y); + + if (options.hasOwnProperty('type') && options.type === 'body') + { + gameObject.setExistingBody(options, addToWorld); + } + else + { + var shape = GetFastValue(options, 'shape', null); + + if (!shape) + { + shape = 'rectangle'; + } + + options.addToWorld = addToWorld; + + gameObject.setBody(shape, options); + } + + return gameObject; +}; + +module.exports = MatterGameObject; + + +/***/ }), + +/***/ 23181: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(9503); +var GameObject = __webpack_require__(95643); +var GetFastValue = __webpack_require__(95540); +var Image = __webpack_require__(88571); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Matter Physics Image Game Object. + * + * An Image is a light-weight Game Object useful for the display of static images in your game, + * such as logos, backgrounds, scenery or other non-animated elements. Images can have input + * events and physics bodies, or be tweened, tinted or scrolled. The main difference between an + * Image and a Sprite is that you cannot animate an Image as they do not have the Animation component. + * + * @class Image + * @extends Phaser.GameObjects.Image + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Matter.Components.Bounce + * @extends Phaser.Physics.Matter.Components.Collision + * @extends Phaser.Physics.Matter.Components.Force + * @extends Phaser.Physics.Matter.Components.Friction + * @extends Phaser.Physics.Matter.Components.Gravity + * @extends Phaser.Physics.Matter.Components.Mass + * @extends Phaser.Physics.Matter.Components.Sensor + * @extends Phaser.Physics.Matter.Components.SetBody + * @extends Phaser.Physics.Matter.Components.Sleep + * @extends Phaser.Physics.Matter.Components.Static + * @extends Phaser.Physics.Matter.Components.Transform + * @extends Phaser.Physics.Matter.Components.Velocity + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Physics.Matter.World} world - A reference to the Matter.World instance that this body belongs to. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + */ +var MatterImage = new Class({ + + Extends: Image, + + Mixins: [ + Components.Bounce, + Components.Collision, + Components.Force, + Components.Friction, + Components.Gravity, + Components.Mass, + Components.Sensor, + Components.SetBody, + Components.Sleep, + Components.Static, + Components.Transform, + Components.Velocity + ], + + initialize: + + function MatterImage (world, x, y, texture, frame, options) + { + GameObject.call(this, world.scene, 'Image'); + + /** + * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method. + * + * @name Phaser.Physics.Matter.Image#_crop + * @type {object} + * @private + * @since 3.24.0 + */ + this._crop = this.resetCropObject(); + + this.setTexture(texture, frame); + this.setSizeToFrame(); + this.setOrigin(); + this.initRenderNodes(this._defaultRenderNodesMap); + + /** + * A reference to the Matter.World instance that this body belongs to. + * + * @name Phaser.Physics.Matter.Image#world + * @type {Phaser.Physics.Matter.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * An internal temp vector used for velocity and force calculations. + * + * @name Phaser.Physics.Matter.Image#_tempVec2 + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tempVec2 = new Vector2(x, y); + + var shape = GetFastValue(options, 'shape', null); + + if (shape) + { + this.setBody(shape, options); + } + else + { + this.setRectangle(this.width, this.height, options); + } + + this.setPosition(x, y); + } + +}); + +module.exports = MatterImage; + + +/***/ }), + +/***/ 42045: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ALIGN_CONST = __webpack_require__(60461); +var Axes = __webpack_require__(66615); +var Bodies = __webpack_require__(66280); +var Body = __webpack_require__(22562); +var BodyBounds = __webpack_require__(68174); +var Bounds = __webpack_require__(15647); +var Class = __webpack_require__(83419); +var Collision = __webpack_require__(52284); +var Common = __webpack_require__(53402); +var Composite = __webpack_require__(69351); +var Composites = __webpack_require__(74116); +var Constraint = __webpack_require__(48140); +var Detector = __webpack_require__(81388); +var DistanceBetween = __webpack_require__(20339); +var Factory = __webpack_require__(28137); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var Merge = __webpack_require__(46975); +var Pair = __webpack_require__(4506); +var Pairs = __webpack_require__(99561); +var PluginCache = __webpack_require__(37277); +var Query = __webpack_require__(73296); +var Resolver = __webpack_require__(66272); +var SceneEvents = __webpack_require__(44594); +var Svg = __webpack_require__(74058); +var Vector = __webpack_require__(31725); +var Vertices = __webpack_require__(41598); +var World = __webpack_require__(68243); + +Common.setDecomp(__webpack_require__(55973)); + +/** + * @classdesc + * The Phaser Matter plugin provides the ability to use the Matter JS Physics Engine within your Phaser games. + * + * Unlike Arcade Physics, the other physics system provided with Phaser, Matter JS is a full-body physics system. + * It features: + * + * * Rigid bodies + * * Compound bodies + * * Composite bodies + * * Concave and convex hulls + * * Physical properties (mass, area, density etc.) + * * Restitution (elastic and inelastic collisions) + * * Collisions (broad-phase, mid-phase and narrow-phase) + * * Stable stacking and resting + * * Conservation of momentum + * * Friction and resistance + * * Constraints + * * Gravity + * * Sleeping and static bodies + * * Rounded corners (chamfering) + * * Views (translate, zoom) + * * Collision queries (raycasting, region tests) + * * Time scaling (slow-mo, speed-up) + * + * Configuration of Matter is handled via the Matter World Config object, which can be passed in either the + * Phaser Game Config, or Phaser Scene Config. Here is a basic example: + * + * ```js + * physics: { + * default: 'matter', + * matter: { + * enableSleeping: true, + * gravity: { + * y: 0 + * }, + * debug: { + * showBody: true, + * showStaticBody: true + * } + * } + * } + * ``` + * + * This class acts as an interface between a Phaser Scene and a single instance of the Matter Engine. + * + * Use it to access the most common Matter features and helper functions. + * + * You can find details, documentation and examples on the Matter JS website: https://brm.io/matter-js/ + * + * @class MatterPhysics + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Phaser Scene that owns this Matter Physics instance. + */ +var MatterPhysics = new Class({ + + initialize: + + function MatterPhysics (scene) + { + /** + * The Phaser Scene that owns this Matter Physics instance + * + * @name Phaser.Physics.Matter.MatterPhysics#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Scene Systems that belong to the Scene owning this Matter Physics instance. + * + * @name Phaser.Physics.Matter.MatterPhysics#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * The parsed Matter Configuration object. + * + * @name Phaser.Physics.Matter.MatterPhysics#config + * @type {Phaser.Types.Physics.Matter.MatterWorldConfig} + * @since 3.0.0 + */ + this.config = this.getConfig(); + + /** + * An instance of the Matter World class. This class is responsible for the updating of the + * Matter Physics world, as well as handling debug drawing functions. + * + * @name Phaser.Physics.Matter.MatterPhysics#world + * @type {Phaser.Physics.Matter.World} + * @since 3.0.0 + */ + this.world; + + /** + * An instance of the Matter Factory. This class provides lots of functions for creating a + * wide variety of physics objects and adds them automatically to the Matter World. + * + * You can use this class to cut-down on the amount of code required in your game, however, + * use of the Factory is entirely optional and should be seen as a development aid. It's + * perfectly possible to create and add components to the Matter world without using it. + * + * @name Phaser.Physics.Matter.MatterPhysics#add + * @type {Phaser.Physics.Matter.Factory} + * @since 3.0.0 + */ + this.add; + + /** + * An instance of the Body Bounds class. This class contains functions used for getting the + * world position from various points around the bounds of a physics body. + * + * @name Phaser.Physics.Matter.MatterPhysics#bodyBounds + * @type {Phaser.Physics.Matter.BodyBounds} + * @since 3.22.0 + */ + this.bodyBounds; + + // Body + + /** + * A reference to the `Matter.Body` module. + * + * The `Matter.Body` module contains methods for creating and manipulating body models. + * A `Matter.Body` is a rigid body that can be simulated by a `Matter.Engine`. + * Factories for commonly used body configurations (such as rectangles, circles and other polygons) can be found in the `Bodies` module. + * + * @name Phaser.Physics.Matter.MatterPhysics#body + * @type {MatterJS.BodyFactory} + * @since 3.18.0 + */ + this.body = Body; + + /** + * A reference to the `Matter.Composite` module. + * + * The `Matter.Composite` module contains methods for creating and manipulating composite bodies. + * A composite body is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`, therefore composites form a tree structure. + * It is important to use the functions in this module to modify composites, rather than directly modifying their properties. + * Note that the `Matter.World` object is also a type of `Matter.Composite` and as such all composite methods here can also operate on a `Matter.World`. + * + * @name Phaser.Physics.Matter.MatterPhysics#composite + * @type {MatterJS.CompositeFactory} + * @since 3.22.0 + */ + this.composite = Composite; + + // Collision: + + /** + * A reference to the `Matter.Collision` module. + * + * The `Matter.Collision` module contains methods for detecting collisions between a given pair of bodies. + * + * For efficient detection between a list of bodies, see `Matter.Detector` and `Matter.Query`. + * + * @name Phaser.Physics.Matter.MatterPhysics#collision + * @type {MatterJS.Collision} + * @since 3.60.0 + */ + this.collision = Collision; + + /** + * A reference to the `Matter.Detector` module. + * + * The `Matter.Detector` module contains methods for detecting collisions given a set of pairs. + * + * @name Phaser.Physics.Matter.MatterPhysics#detector + * @type {MatterJS.DetectorFactory} + * @since 3.22.0 + */ + this.detector = Detector; + + /** + * A reference to the `Matter.Pair` module. + * + * The `Matter.Pair` module contains methods for creating and manipulating collision pairs. + * + * @name Phaser.Physics.Matter.MatterPhysics#pair + * @type {MatterJS.PairFactory} + * @since 3.22.0 + */ + this.pair = Pair; + + /** + * A reference to the `Matter.Pairs` module. + * + * The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets. + * + * @name Phaser.Physics.Matter.MatterPhysics#pairs + * @type {MatterJS.PairsFactory} + * @since 3.22.0 + */ + this.pairs = Pairs; + + /** + * A reference to the `Matter.Query` module. + * + * The `Matter.Query` module contains methods for performing collision queries. + * + * @name Phaser.Physics.Matter.MatterPhysics#query + * @type {MatterJS.QueryFactory} + * @since 3.22.0 + */ + this.query = Query; + + /** + * A reference to the `Matter.Resolver` module. + * + * The `Matter.Resolver` module contains methods for resolving collision pairs. + * + * @name Phaser.Physics.Matter.MatterPhysics#resolver + * @type {MatterJS.ResolverFactory} + * @since 3.22.0 + */ + this.resolver = Resolver; + + // Constraint + + /** + * A reference to the `Matter.Constraint` module. + * + * The `Matter.Constraint` module contains methods for creating and manipulating constraints. + * Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position). + * The stiffness of constraints can be modified to create springs or elastic. + * + * @name Phaser.Physics.Matter.MatterPhysics#constraint + * @type {MatterJS.ConstraintFactory} + * @since 3.22.0 + */ + this.constraint = Constraint; + + // Factory + + /** + * A reference to the `Matter.Bodies` module. + * + * The `Matter.Bodies` module contains factory methods for creating rigid bodies + * with commonly used body configurations (such as rectangles, circles and other polygons). + * + * @name Phaser.Physics.Matter.MatterPhysics#bodies + * @type {MatterJS.BodiesFactory} + * @since 3.18.0 + */ + this.bodies = Bodies; + + /** + * A reference to the `Matter.Composites` module. + * + * The `Matter.Composites` module contains factory methods for creating composite bodies + * with commonly used configurations (such as stacks and chains). + * + * @name Phaser.Physics.Matter.MatterPhysics#composites + * @type {MatterJS.CompositesFactory} + * @since 3.22.0 + */ + this.composites = Composites; + + // Geometry + + /** + * A reference to the `Matter.Axes` module. + * + * The `Matter.Axes` module contains methods for creating and manipulating sets of axes. + * + * @name Phaser.Physics.Matter.MatterPhysics#axes + * @type {MatterJS.AxesFactory} + * @since 3.22.0 + */ + this.axes = Axes; + + /** + * A reference to the `Matter.Bounds` module. + * + * The `Matter.Bounds` module contains methods for creating and manipulating axis-aligned bounding boxes (AABB). + * + * @name Phaser.Physics.Matter.MatterPhysics#bounds + * @type {MatterJS.BoundsFactory} + * @since 3.22.0 + */ + this.bounds = Bounds; + + /** + * A reference to the `Matter.Svg` module. + * + * The `Matter.Svg` module contains methods for converting SVG images into an array of vector points. + * + * To use this module you also need the SVGPathSeg polyfill: https://github.com/progers/pathseg + * + * @name Phaser.Physics.Matter.MatterPhysics#svg + * @type {MatterJS.SvgFactory} + * @since 3.22.0 + */ + this.svg = Svg; + + /** + * A reference to the `Matter.Vector` module. + * + * The `Matter.Vector` module contains methods for creating and manipulating vectors. + * Vectors are the basis of all the geometry related operations in the engine. + * A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`. + * + * @name Phaser.Physics.Matter.MatterPhysics#vector + * @type {MatterJS.VectorFactory} + * @since 3.22.0 + */ + this.vector = Vector; + + /** + * A reference to the `Matter.Vertices` module. + * + * The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices. + * A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`. + * A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull). + * + * @name Phaser.Physics.Matter.MatterPhysics#vertices + * @type {MatterJS.VerticesFactory} + * @since 3.22.0 + */ + this.vertices = Vertices; + + /** + * A reference to the `Matter.Vertices` module. + * + * The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices. + * A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`. + * A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull). + * + * @name Phaser.Physics.Matter.MatterPhysics#verts + * @type {MatterJS.VerticesFactory} + * @since 3.14.0 + */ + this.verts = Vertices; + + /** + * An internal temp vector used for velocity and force calculations. + * + * @name Phaser.Physics.Matter.MatterPhysics#_tempVec2 + * @type {MatterJS.Vector} + * @private + * @since 3.22.0 + */ + this._tempVec2 = Vector.create(); + + Resolver._restingThresh = GetValue(this.config, 'restingThresh', 4); + Resolver._restingThreshTangent = GetValue(this.config, 'restingThreshTangent', 6); + Resolver._positionDampen = GetValue(this.config, 'positionDampen', 0.9); + Resolver._positionWarming = GetValue(this.config, 'positionWarming', 0.8); + Resolver._frictionNormalMultiplier = GetValue(this.config, 'frictionNormalMultiplier', 5); + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Physics.Matter.MatterPhysics#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.world = new World(this.scene, this.config); + this.add = new Factory(this.world); + this.bodyBounds = new BodyBounds(); + + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Physics.Matter.MatterPhysics#start + * @private + * @since 3.5.0 + */ + start: function () + { + if (!this.world) + { + this.world = new World(this.scene, this.config); + this.add = new Factory(this.world); + } + + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.UPDATE, this.world.update, this.world); + eventEmitter.on(SceneEvents.POST_UPDATE, this.world.postUpdate, this.world); + eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * This internal method is called when this class starts and retrieves the final Matter World Config. + * + * @method Phaser.Physics.Matter.MatterPhysics#getConfig + * @since 3.0.0 + * + * @return {Phaser.Types.Physics.Matter.MatterWorldConfig} The Matter World Config. + */ + getConfig: function () + { + var gameConfig = this.systems.game.config.physics; + var sceneConfig = this.systems.settings.physics; + + var config = Merge( + GetFastValue(sceneConfig, 'matter', {}), + GetFastValue(gameConfig, 'matter', {}) + ); + + return config; + }, + + /** + * Pauses the Matter World instance and sets `enabled` to `false`. + * + * A paused world will not run any simulations for the duration it is paused. + * + * @method Phaser.Physics.Matter.MatterPhysics#pause + * @fires Phaser.Physics.Matter.Events#PAUSE + * @since 3.0.0 + * + * @return {Phaser.Physics.Matter.World} The Matter World object. + */ + pause: function () + { + return this.world.pause(); + }, + + /** + * Resumes this Matter World instance from a paused state and sets `enabled` to `true`. + * + * @method Phaser.Physics.Matter.MatterPhysics#resume + * @since 3.0.0 + * + * @return {Phaser.Physics.Matter.World} The Matter World object. + */ + resume: function () + { + return this.world.resume(); + }, + + /** + * Sets the Matter Engine to run at fixed timestep of 60Hz and enables `autoUpdate`. + * If you have set a custom `getDelta` function then this will override it. + * + * @method Phaser.Physics.Matter.MatterPhysics#set60Hz + * @since 3.4.0 + * + * @return {this} This Matter Physics instance. + */ + set60Hz: function () + { + this.world.getDelta = this.world.update60Hz; + this.world.autoUpdate = true; + + return this; + }, + + /** + * Sets the Matter Engine to run at fixed timestep of 30Hz and enables `autoUpdate`. + * If you have set a custom `getDelta` function then this will override it. + * + * @method Phaser.Physics.Matter.MatterPhysics#set30Hz + * @since 3.4.0 + * + * @return {this} This Matter Physics instance. + */ + set30Hz: function () + { + this.world.getDelta = this.world.update30Hz; + this.world.autoUpdate = true; + + return this; + }, + + /** + * Manually advances the physics simulation by one iteration. + * + * You can optionally pass in the `delta` and `correction` values to be used by Engine.update. + * If undefined they use the Matter defaults of 60Hz and no correction. + * + * Calling `step` directly bypasses any checks of `enabled` or `autoUpdate`. + * + * It also ignores any custom `getDelta` functions, as you should be passing the delta + * value in to this call. + * + * You can adjust the number of iterations that Engine.update performs internally. + * Use the Scene Matter Physics config object to set the following properties: + * + * positionIterations (defaults to 6) + * velocityIterations (defaults to 4) + * constraintIterations (defaults to 2) + * + * Adjusting these values can help performance in certain situations, depending on the physics requirements + * of your game. + * + * @method Phaser.Physics.Matter.MatterPhysics#step + * @since 3.4.0 + * + * @param {number} [delta=16.666] - The delta value. + * @param {number} [correction=1] - Optional delta correction value. + */ + step: function (delta, correction) + { + this.world.step(delta, correction); + }, + + /** + * Checks if the vertices of the given body, or an array of bodies, contains the given point, or not. + * + * You can pass in either a single body, or an array of bodies to be checked. This method will + * return `true` if _any_ of the bodies in the array contain the point. See the `intersectPoint` method if you need + * to get a list of intersecting bodies. + * + * The point should be transformed into the Matter World coordinate system in advance. This happens by + * default with Input Pointers, but if you wish to use points from another system you may need to + * transform them before passing them. + * + * @method Phaser.Physics.Matter.MatterPhysics#containsPoint + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} body - The body, or an array of bodies, to check against the point. + * @param {number} x - The horizontal coordinate of the point. + * @param {number} y - The vertical coordinate of the point. + * + * @return {boolean} `true` if the point is within one of the bodies given, otherwise `false`. + */ + containsPoint: function (body, x, y) + { + body = this.getMatterBodies(body); + + var position = Vector.create(x, y); + + var result = Query.point(body, position); + + return (result.length > 0) ? true : false; + }, + + /** + * Checks the given coordinates to see if any vertices of the given bodies contain it. + * + * If no bodies are provided it will search all bodies in the Matter World, including within Composites. + * + * The coordinates should be transformed into the Matter World coordinate system in advance. This happens by + * default with Input Pointers, but if you wish to use coordinates from another system you may need to + * transform them before passing them. + * + * @method Phaser.Physics.Matter.MatterPhysics#intersectPoint + * @since 3.22.0 + * + * @param {number} x - The horizontal coordinate of the point. + * @param {number} y - The vertical coordinate of the point. + * @param {Phaser.Types.Physics.Matter.MatterBody[]} [bodies] - An array of bodies to check. If not provided it will search all bodies in the world. + * + * @return {Phaser.Types.Physics.Matter.MatterBody[]} An array of bodies which contain the given point. + */ + intersectPoint: function (x, y, bodies) + { + bodies = this.getMatterBodies(bodies); + + var position = Vector.create(x, y); + + var output = []; + + var result = Query.point(bodies, position); + + result.forEach(function (body) + { + if (output.indexOf(body) === -1) + { + output.push(body); + } + }); + + return output; + }, + + /** + * Checks the given rectangular area to see if any vertices of the given bodies intersect with it. + * Or, if the `outside` parameter is set to `true`, it checks to see which bodies do not + * intersect with it. + * + * If no bodies are provided it will search all bodies in the Matter World, including within Composites. + * + * @method Phaser.Physics.Matter.MatterPhysics#intersectRect + * @since 3.22.0 + * + * @param {number} x - The horizontal coordinate of the top-left of the area. + * @param {number} y - The vertical coordinate of the top-left of the area. + * @param {number} width - The width of the area. + * @param {number} height - The height of the area. + * @param {boolean} [outside=false] - If `false` it checks for vertices inside the area, if `true` it checks for vertices outside the area. + * @param {Phaser.Types.Physics.Matter.MatterBody[]} [bodies] - An array of bodies to check. If not provided it will search all bodies in the world. + * + * @return {Phaser.Types.Physics.Matter.MatterBody[]} An array of bodies that intersect with the given area. + */ + intersectRect: function (x, y, width, height, outside, bodies) + { + if (outside === undefined) { outside = false; } + + bodies = this.getMatterBodies(bodies); + + var bounds = { + min: { x: x, y: y }, + max: { x: x + width, y: y + height } + }; + + var output = []; + + var result = Query.region(bodies, bounds, outside); + + result.forEach(function (body) + { + if (output.indexOf(body) === -1) + { + output.push(body); + } + }); + + return output; + }, + + /** + * Checks the given ray segment to see if any vertices of the given bodies intersect with it. + * + * If no bodies are provided it will search all bodies in the Matter World. + * + * The width of the ray can be specified via the `rayWidth` parameter. + * + * @method Phaser.Physics.Matter.MatterPhysics#intersectRay + * @since 3.22.0 + * + * @param {number} x1 - The horizontal coordinate of the start of the ray segment. + * @param {number} y1 - The vertical coordinate of the start of the ray segment. + * @param {number} x2 - The horizontal coordinate of the end of the ray segment. + * @param {number} y2 - The vertical coordinate of the end of the ray segment. + * @param {number} [rayWidth=1] - The width of the ray segment. + * @param {Phaser.Types.Physics.Matter.MatterBody[]} [bodies] - An array of bodies to check. If not provided it will search all bodies in the world. + * + * @return {Phaser.Types.Physics.Matter.MatterBody[]} An array of bodies whos vertices intersect with the ray segment. + */ + intersectRay: function (x1, y1, x2, y2, rayWidth, bodies) + { + if (rayWidth === undefined) { rayWidth = 1; } + + bodies = this.getMatterBodies(bodies); + + var result = []; + var collisions = Query.ray(bodies, Vector.create(x1, y1), Vector.create(x2, y2), rayWidth); + + for (var i = 0; i < collisions.length; i++) + { + result.push(collisions[i].body); + } + + return result; + }, + + /** + * Checks the given Matter Body to see if it intersects with any of the given bodies. + * + * If no bodies are provided it will check against all bodies in the Matter World. + * + * @method Phaser.Physics.Matter.MatterPhysics#intersectBody + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The target body. + * @param {Phaser.Types.Physics.Matter.MatterBody[]} [bodies] - An array of bodies to check the target body against. If not provided it will search all bodies in the world. + * + * @return {Phaser.Types.Physics.Matter.MatterBody[]} An array of bodies whos vertices intersect with target body. + */ + intersectBody: function (body, bodies) + { + bodies = this.getMatterBodies(bodies); + + var result = []; + var collisions = Query.collides(body, bodies); + + for (var i = 0; i < collisions.length; i++) + { + var pair = collisions[i]; + + if (pair.bodyA === body) + { + result.push(pair.bodyB); + } + else + { + result.push(pair.bodyA); + } + } + + return result; + }, + + /** + * Checks to see if the target body, or an array of target bodies, intersects with any of the given bodies. + * + * If intersection occurs this method will return `true` and, if provided, invoke the callbacks. + * + * If no bodies are provided for the second parameter the target will check against all bodies in the Matter World. + * + * **Note that bodies can only overlap if they are in non-colliding collision groups or categories.** + * + * If you provide a `processCallback` then the two bodies that overlap are sent to it. This callback + * must return a boolean and is used to allow you to perform additional processing tests before a final + * outcome is decided. If it returns `true` then the bodies are finally passed to the `overlapCallback`, if set. + * + * If you provide an `overlapCallback` then the matching pairs of overlapping bodies will be sent to it. + * + * Both callbacks have the following signature: `function (bodyA, bodyB, collisionInfo)` where `bodyA` is always + * the target body. The `collisionInfo` object contains additional data, such as the angle and depth of penetration. + * + * @method Phaser.Physics.Matter.MatterPhysics#overlap + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} target - The target body, or array of target bodies, to check. + * @param {Phaser.Types.Physics.Matter.MatterBody[]} [bodies] - The second body, or array of bodies, to check. If falsey it will check against all bodies in the world. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [overlapCallback] - An optional callback function that is called if the bodies overlap. + * @param {Phaser.Types.Physics.Arcade.ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two bodies if they overlap. If this is set then `overlapCallback` will only be invoked if this callback returns `true`. + * @param {*} [callbackContext] - The context, or scope, in which to run the callbacks. + * + * @return {boolean} `true` if the target body intersects with _any_ of the bodies given, otherwise `false`. + */ + overlap: function (target, bodies, overlapCallback, processCallback, callbackContext) + { + if (overlapCallback === undefined) { overlapCallback = null; } + if (processCallback === undefined) { processCallback = null; } + if (callbackContext === undefined) { callbackContext = overlapCallback; } + + if (!Array.isArray(target)) + { + target = [ target ]; + } + + target = this.getMatterBodies(target); + bodies = this.getMatterBodies(bodies); + + var match = false; + + for (var i = 0; i < target.length; i++) + { + var entry = target[i]; + + var collisions = Query.collides(entry, bodies); + + for (var c = 0; c < collisions.length; c++) + { + var info = collisions[c]; + var bodyB = (info.bodyA.id === entry.id) ? info.bodyB : info.bodyA; + + if (!processCallback || processCallback.call(callbackContext, entry, bodyB, info)) + { + match = true; + + if (overlapCallback) + { + overlapCallback.call(callbackContext, entry, bodyB, info); + } + else if (!processCallback) + { + // If there are no callbacks we don't need to test every body, just exit when the first is found + return true; + } + } + } + } + + return match; + }, + + /** + * Sets the collision filter category of all given Matter Bodies to the given value. + * + * This number must be a power of two between 2^0 (= 1) and 2^31. + * + * Bodies with different collision groups (see {@link #setCollisionGroup}) will only collide if their collision + * categories are included in their collision masks (see {@link #setCollidesWith}). + * + * @method Phaser.Physics.Matter.MatterPhysics#setCollisionCategory + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody[]} bodies - An array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} value - Unique category bitfield. + * + * @return {this} This Matter Physics instance. + */ + setCollisionCategory: function (bodies, value) + { + bodies = this.getMatterBodies(bodies); + + bodies.forEach(function (body) + { + body.collisionFilter.category = value; + }); + + return this; + }, + + /** + * Sets the collision filter group of all given Matter Bodies to the given value. + * + * If the group value is zero, or if two Matter Bodies have different group values, + * they will collide according to the usual collision filter rules (see {@link #setCollisionCategory} and {@link #setCollisionGroup}). + * + * If two Matter Bodies have the same positive group value, they will always collide; + * if they have the same negative group value they will never collide. + * + * @method Phaser.Physics.Matter.MatterPhysics#setCollisionGroup + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody[]} bodies - An array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} value - Unique group index. + * + * @return {this} This Matter Physics instance. + */ + setCollisionGroup: function (bodies, value) + { + bodies = this.getMatterBodies(bodies); + + bodies.forEach(function (body) + { + body.collisionFilter.group = value; + }); + + return this; + }, + + /** + * Sets the collision filter mask of all given Matter Bodies to the given value. + * + * Two Matter Bodies with different collision groups will only collide if each one includes the others + * category in its mask based on a bitwise AND operation: `(categoryA & maskB) !== 0` and + * `(categoryB & maskA) !== 0` are both true. + * + * @method Phaser.Physics.Matter.MatterPhysics#setCollidesWith + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody[]} bodies - An array of bodies to update. If falsey it will use all bodies in the world. + * @param {(number|number[])} categories - A unique category bitfield, or an array of them. + * + * @return {this} This Matter Physics instance. + */ + setCollidesWith: function (bodies, categories) + { + bodies = this.getMatterBodies(bodies); + + var flags = 0; + + if (!Array.isArray(categories)) + { + flags = categories; + } + else + { + for (var i = 0; i < categories.length; i++) + { + flags |= categories[i]; + } + } + + bodies.forEach(function (body) + { + body.collisionFilter.mask = flags; + }); + + return this; + }, + + /** + * Takes an array and returns a new array made from all of the Matter Bodies found in the original array. + * + * For example, passing in Matter Game Objects, such as a bunch of Matter Sprites, to this method, would + * return an array containing all of their native Matter Body objects. + * + * If the `bodies` argument is falsey, it will return all bodies in the world. + * + * @method Phaser.Physics.Matter.MatterPhysics#getMatterBodies + * @since 3.22.0 + * + * @param {array} [bodies] - An array of objects to extract the bodies from. If falsey, it will return all bodies in the world. + * + * @return {MatterJS.BodyType[]} An array of native Matter Body objects. + */ + getMatterBodies: function (bodies) + { + if (!bodies) + { + return this.world.getAllBodies(); + } + + if (!Array.isArray(bodies)) + { + bodies = [ bodies ]; + } + + var output = []; + + for (var i = 0; i < bodies.length; i++) + { + var body = (bodies[i].hasOwnProperty('body')) ? bodies[i].body : bodies[i]; + + output.push(body); + } + + return output; + }, + + /** + * Sets both the horizontal and vertical linear velocity of the physics bodies. + * + * @method Phaser.Physics.Matter.MatterPhysics#setVelocity + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} x - The horizontal linear velocity value. + * @param {number} y - The vertical linear velocity value. + * + * @return {this} This Matter Physics instance. + */ + setVelocity: function (bodies, x, y) + { + bodies = this.getMatterBodies(bodies); + + var vec2 = this._tempVec2; + + vec2.x = x; + vec2.y = y; + + bodies.forEach(function (body) + { + Body.setVelocity(body, vec2); + }); + + return this; + }, + + /** + * Sets just the horizontal linear velocity of the physics bodies. + * The vertical velocity of the body is unchanged. + * + * @method Phaser.Physics.Matter.MatterPhysics#setVelocityX + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} x - The horizontal linear velocity value. + * + * @return {this} This Matter Physics instance. + */ + setVelocityX: function (bodies, x) + { + bodies = this.getMatterBodies(bodies); + + var vec2 = this._tempVec2; + + vec2.x = x; + + bodies.forEach(function (body) + { + vec2.y = body.velocity.y; + Body.setVelocity(body, vec2); + }); + + return this; + }, + + /** + * Sets just the vertical linear velocity of the physics bodies. + * The horizontal velocity of the body is unchanged. + * + * @method Phaser.Physics.Matter.MatterPhysics#setVelocityY + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} y - The vertical linear velocity value. + * + * @return {this} This Matter Physics instance. + */ + setVelocityY: function (bodies, y) + { + bodies = this.getMatterBodies(bodies); + + var vec2 = this._tempVec2; + + vec2.y = y; + + bodies.forEach(function (body) + { + vec2.x = body.velocity.x; + Body.setVelocity(body, vec2); + }); + + return this; + }, + + /** + * Sets the angular velocity of the bodies instantly. + * Position, angle, force etc. are unchanged. + * + * @method Phaser.Physics.Matter.MatterPhysics#setAngularVelocity + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} value - The angular velocity. + * + * @return {this} This Matter Physics instance. + */ + setAngularVelocity: function (bodies, value) + { + bodies = this.getMatterBodies(bodies); + + bodies.forEach(function (body) + { + Body.setAngularVelocity(body, value); + }); + + return this; + }, + + /** + * Applies a force to a body, at the bodies current position, including resulting torque. + * + * @method Phaser.Physics.Matter.MatterPhysics#applyForce + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {Phaser.Types.Math.Vector2Like} force - A Vector that specifies the force to apply. + * + * @return {this} This Matter Physics instance. + */ + applyForce: function (bodies, force) + { + bodies = this.getMatterBodies(bodies); + + var vec2 = this._tempVec2; + + bodies.forEach(function (body) + { + vec2.x = body.position.x; + vec2.y = body.position.y; + + Body.applyForce(body, vec2, force); + }); + + return this; + }, + + /** + * Applies a force to a body, from the given world position, including resulting torque. + * If no angle is given, the current body angle is used. + * + * Use very small speed values, such as 0.1, depending on the mass and required velocity. + * + * @method Phaser.Physics.Matter.MatterPhysics#applyForceFromPosition + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {Phaser.Types.Math.Vector2Like} position - A Vector that specifies the world-space position to apply the force at. + * @param {number} speed - A speed value to be applied to a directional force. + * @param {number} [angle] - The angle, in radians, to apply the force from. Leave undefined to use the current body angle. + * + * @return {this} This Matter Physics instance. + */ + applyForceFromPosition: function (bodies, position, speed, angle) + { + bodies = this.getMatterBodies(bodies); + + var vec2 = this._tempVec2; + + bodies.forEach(function (body) + { + if (angle === undefined) + { + angle = body.angle; + } + + vec2.x = speed * Math.cos(angle); + vec2.y = speed * Math.sin(angle); + + Body.applyForce(body, position, vec2); + }); + + return this; + }, + + /** + * Apply a force to a body based on the given angle and speed. + * If no angle is given, the current body angle is used. + * + * Use very small speed values, such as 0.1, depending on the mass and required velocity. + * + * @method Phaser.Physics.Matter.MatterPhysics#applyForceFromAngle + * @since 3.22.0 + * + * @param {(Phaser.Types.Physics.Matter.MatterBody|Phaser.Types.Physics.Matter.MatterBody[])} bodies - Either a single Body, or an array of bodies to update. If falsey it will use all bodies in the world. + * @param {number} speed - A speed value to be applied to a directional force. + * @param {number} [angle] - The angle, in radians, to apply the force from. Leave undefined to use the current body angle. + * + * @return {this} This Matter Physics instance. + */ + applyForceFromAngle: function (bodies, speed, angle) + { + bodies = this.getMatterBodies(bodies); + + var vec2 = this._tempVec2; + + bodies.forEach(function (body) + { + if (angle === undefined) + { + angle = body.angle; + } + + vec2.x = speed * Math.cos(angle); + vec2.y = speed * Math.sin(angle); + + Body.applyForce(body, { x: body.position.x, y: body.position.y }, vec2); + }); + + return this; + }, + + /** + * Returns the length of the given constraint, which is the distance between the two points. + * + * @method Phaser.Physics.Matter.MatterPhysics#getConstraintLength + * @since 3.22.0 + * + * @param {MatterJS.ConstraintType} constraint - The constraint to get the length from. + * + * @return {number} The length of the constraint. + */ + getConstraintLength: function (constraint) + { + var aX = constraint.pointA.x; + var aY = constraint.pointA.y; + var bX = constraint.pointB.x; + var bY = constraint.pointB.y; + + if (constraint.bodyA) + { + aX += constraint.bodyA.position.x; + aY += constraint.bodyA.position.y; + } + + if (constraint.bodyB) + { + bX += constraint.bodyB.position.x; + bY += constraint.bodyB.position.y; + } + + return DistanceBetween(aX, aY, bX, bY); + }, + + /** + * Aligns a Body, or Matter Game Object, against the given coordinates. + * + * The alignment takes place using the body bounds, which take into consideration things + * like body scale and rotation. + * + * Although a Body has a `position` property, it is based on the center of mass for the body, + * not a dimension based center. This makes aligning bodies difficult, especially if they have + * rotated or scaled. This method will derive the correct position based on the body bounds and + * its center of mass offset, in order to align the body with the given coordinate. + * + * For example, if you wanted to align a body so it sat in the bottom-center of the + * Scene, and the world was 800 x 600 in size: + * + * ```javascript + * this.matter.alignBody(body, 400, 600, Phaser.Display.Align.BOTTOM_CENTER); + * ``` + * + * You pass in 400 for the x coordinate, because that is the center of the world, and 600 for + * the y coordinate, as that is the base of the world. + * + * @method Phaser.Physics.Matter.MatterPhysics#alignBody + * @since 3.22.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBody} body - The Body to align. + * @param {number} x - The horizontal position to align the body to. + * @param {number} y - The vertical position to align the body to. + * @param {number} align - One of the `Phaser.Display.Align` constants, such as `Phaser.Display.Align.TOP_LEFT`. + * + * @return {this} This Matter Physics instance. + */ + alignBody: function (body, x, y, align) + { + body = (body.hasOwnProperty('body')) ? body.body : body; + + var pos; + + switch (align) + { + case ALIGN_CONST.TOP_LEFT: + case ALIGN_CONST.LEFT_TOP: + pos = this.bodyBounds.getTopLeft(body, x, y); + break; + + case ALIGN_CONST.TOP_CENTER: + pos = this.bodyBounds.getTopCenter(body, x, y); + break; + + case ALIGN_CONST.TOP_RIGHT: + case ALIGN_CONST.RIGHT_TOP: + pos = this.bodyBounds.getTopRight(body, x, y); + break; + + case ALIGN_CONST.LEFT_CENTER: + pos = this.bodyBounds.getLeftCenter(body, x, y); + break; + + case ALIGN_CONST.CENTER: + pos = this.bodyBounds.getCenter(body, x, y); + break; + + case ALIGN_CONST.RIGHT_CENTER: + pos = this.bodyBounds.getRightCenter(body, x, y); + break; + + case ALIGN_CONST.LEFT_BOTTOM: + case ALIGN_CONST.BOTTOM_LEFT: + pos = this.bodyBounds.getBottomLeft(body, x, y); + break; + + case ALIGN_CONST.BOTTOM_CENTER: + pos = this.bodyBounds.getBottomCenter(body, x, y); + break; + + case ALIGN_CONST.BOTTOM_RIGHT: + case ALIGN_CONST.RIGHT_BOTTOM: + pos = this.bodyBounds.getBottomRight(body, x, y); + break; + } + + if (pos) + { + Body.setPosition(body, pos); + } + + return this; + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Physics.Matter.MatterPhysics#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + var eventEmitter = this.systems.events; + + if (this.world) + { + eventEmitter.off(SceneEvents.UPDATE, this.world.update, this.world); + eventEmitter.off(SceneEvents.POST_UPDATE, this.world.postUpdate, this.world); + } + + eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this); + + if (this.add) + { + this.add.destroy(); + } + + if (this.world) + { + this.world.destroy(); + } + + this.add = null; + this.world = null; + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Physics.Matter.MatterPhysics#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.scene.sys.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + } + +}); + +PluginCache.register('MatterPhysics', MatterPhysics, 'matterPhysics'); + +module.exports = MatterPhysics; + + +/***/ }), + +/***/ 34803: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AnimationState = __webpack_require__(9674); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(9503); +var GameObject = __webpack_require__(95643); +var GetFastValue = __webpack_require__(95540); +var Sprite = __webpack_require__(68287); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Matter Physics Sprite Game Object. + * + * A Sprite Game Object is used for the display of both static and animated images in your game. + * Sprites can have input events and physics bodies. They can also be tweened, tinted, scrolled + * and animated. + * + * The main difference between a Sprite and an Image Game Object is that you cannot animate Images. + * As such, Sprites take a fraction longer to process and have a larger API footprint due to the Animation + * Component. If you do not require animation then you can safely use Images to replace Sprites in all cases. + * + * @class Sprite + * @extends Phaser.GameObjects.Sprite + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Matter.Components.Bounce + * @extends Phaser.Physics.Matter.Components.Collision + * @extends Phaser.Physics.Matter.Components.Force + * @extends Phaser.Physics.Matter.Components.Friction + * @extends Phaser.Physics.Matter.Components.Gravity + * @extends Phaser.Physics.Matter.Components.Mass + * @extends Phaser.Physics.Matter.Components.Sensor + * @extends Phaser.Physics.Matter.Components.SetBody + * @extends Phaser.Physics.Matter.Components.Sleep + * @extends Phaser.Physics.Matter.Components.Static + * @extends Phaser.Physics.Matter.Components.Transform + * @extends Phaser.Physics.Matter.Components.Velocity + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Size + * @extends Phaser.GameObjects.Components.Texture + * @extends Phaser.GameObjects.Components.Tint + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Physics.Matter.World} world - A reference to the Matter.World instance that this body belongs to. + * @param {number} x - The horizontal position of this Game Object in the world. + * @param {number} y - The vertical position of this Game Object in the world. + * @param {(string|Phaser.Textures.Texture)} texture - The key, or instance of the Texture this Game Object will use to render with, as stored in the Texture Manager. + * @param {(string|number)} [frame] - An optional frame from the Texture this Game Object is rendering with. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + */ +var MatterSprite = new Class({ + + Extends: Sprite, + + Mixins: [ + Components.Bounce, + Components.Collision, + Components.Force, + Components.Friction, + Components.Gravity, + Components.Mass, + Components.Sensor, + Components.SetBody, + Components.Sleep, + Components.Static, + Components.Transform, + Components.Velocity + ], + + initialize: + + function MatterSprite (world, x, y, texture, frame, options) + { + GameObject.call(this, world.scene, 'Sprite'); + + /** + * The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method. + * + * @name Phaser.Physics.Matter.Sprite#_crop + * @type {object} + * @private + * @since 3.24.0 + */ + this._crop = this.resetCropObject(); + + this.anims = new AnimationState(this); + + this.setTexture(texture, frame); + this.setSizeToFrame(); + this.setOrigin(); + this.initRenderNodes(this._defaultRenderNodesMap); + + /** + * A reference to the Matter.World instance that this body belongs to. + * + * @name Phaser.Physics.Matter.Sprite#world + * @type {Phaser.Physics.Matter.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * An internal temp vector used for velocity and force calculations. + * + * @name Phaser.Physics.Matter.Sprite#_tempVec2 + * @type {Phaser.Math.Vector2} + * @private + * @since 3.0.0 + */ + this._tempVec2 = new Vector2(x, y); + + var shape = GetFastValue(options, 'shape', null); + + if (shape) + { + this.setBody(shape, options); + } + else + { + this.setRectangle(this.width, this.height, options); + } + + this.setPosition(x, y); + } + +}); + +module.exports = MatterSprite; + + +/***/ }), + +/***/ 73834: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bodies = __webpack_require__(66280); +var Body = __webpack_require__(22562); +var Class = __webpack_require__(83419); +var Components = __webpack_require__(9503); +var DeepCopy = __webpack_require__(62644); +var EventEmitter = __webpack_require__(50792); +var GetFastValue = __webpack_require__(95540); +var HasValue = __webpack_require__(97022); +var Vertices = __webpack_require__(41598); + +/** + * @classdesc + * A wrapper around a Tile that provides access to a corresponding Matter body. A tile can only + * have one Matter body associated with it. You can either pass in an existing Matter body for + * the tile or allow the constructor to create the corresponding body for you. If the Tile has a + * collision group (defined in Tiled), those shapes will be used to create the body. If not, the + * tile's rectangle bounding box will be used. + * + * The corresponding body will be accessible on the Tile itself via Tile.physics.matterBody. + * + * Note: not all Tiled collision shapes are supported. See + * Phaser.Physics.Matter.TileBody#setFromTileCollision for more information. + * + * @class TileBody + * @memberof Phaser.Physics.Matter + * @extends Phaser.Events.EventEmitter + * @constructor + * @since 3.0.0 + * + * @extends Phaser.Physics.Matter.Components.Bounce + * @extends Phaser.Physics.Matter.Components.Collision + * @extends Phaser.Physics.Matter.Components.Friction + * @extends Phaser.Physics.Matter.Components.Gravity + * @extends Phaser.Physics.Matter.Components.Mass + * @extends Phaser.Physics.Matter.Components.Sensor + * @extends Phaser.Physics.Matter.Components.Sleep + * @extends Phaser.Physics.Matter.Components.Static + * + * @param {Phaser.Physics.Matter.World} world - The Matter world instance this body belongs to. + * @param {Phaser.Tilemaps.Tile} tile - The target tile that should have a Matter body. + * @param {Phaser.Types.Physics.Matter.MatterTileOptions} [options] - Options to be used when creating the Matter body. + */ +var MatterTileBody = new Class({ + + Extends: EventEmitter, + + Mixins: [ + Components.Bounce, + Components.Collision, + Components.Friction, + Components.Gravity, + Components.Mass, + Components.Sensor, + Components.Sleep, + Components.Static + ], + + initialize: + + function MatterTileBody (world, tile, options) + { + EventEmitter.call(this); + + /** + * The tile object the body is associated with. + * + * @name Phaser.Physics.Matter.TileBody#tile + * @type {Phaser.Tilemaps.Tile} + * @since 3.0.0 + */ + this.tile = tile; + + /** + * The Matter world the body exists within. + * + * @name Phaser.Physics.Matter.TileBody#world + * @type {Phaser.Physics.Matter.World} + * @since 3.0.0 + */ + this.world = world; + + // Install a reference to 'this' on the tile and ensure there can only be one matter body + // associated with the tile + if (tile.physics.matterBody) + { + tile.physics.matterBody.destroy(); + } + + tile.physics.matterBody = this; + + // Set the body either from an existing body (if provided), the shapes in the tileset + // collision layer (if it exists) or a rectangle matching the tile. + var body = GetFastValue(options, 'body', null); + + var addToWorld = GetFastValue(options, 'addToWorld', true); + + if (!body) + { + var collisionGroup = tile.getCollisionGroup(); + var collisionObjects = GetFastValue(collisionGroup, 'objects', []); + + if (collisionObjects.length > 0) + { + this.setFromTileCollision(options); + } + else + { + this.setFromTileRectangle(options); + } + } + else + { + this.setBody(body, addToWorld); + } + + if (tile.flipX || tile.flipY) + { + var rotationPoint = { x: tile.getCenterX(), y: tile.getCenterY() }; + var scaleX = (tile.flipX) ? -1 : 1; + var scaleY = (tile.flipY) ? -1 : 1; + + Body.scale(body, scaleX, scaleY, rotationPoint); + } + }, + + /** + * Sets the current body to a rectangle that matches the bounds of the tile. + * + * @method Phaser.Physics.Matter.TileBody#setFromTileRectangle + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBodyTileOptions} [options] - Options to be used when creating the Matter body. See MatterJS.Body for a list of what Matter accepts. + * + * @return {Phaser.Physics.Matter.TileBody} This TileBody object. + */ + setFromTileRectangle: function (options) + { + if (options === undefined) { options = {}; } + if (!HasValue(options, 'isStatic')) { options.isStatic = true; } + if (!HasValue(options, 'addToWorld')) { options.addToWorld = true; } + + var bounds = this.tile.getBounds(); + var cx = bounds.x + (bounds.width / 2); + var cy = bounds.y + (bounds.height / 2); + var body = Bodies.rectangle(cx, cy, bounds.width, bounds.height, options); + + this.setBody(body, options.addToWorld); + + return this; + }, + + /** + * Sets the current body from the collision group associated with the Tile. This is typically + * set up in Tiled's collision editor. + * + * Note: Matter doesn't support all shapes from Tiled. Rectangles and polygons are directly + * supported. Ellipses are converted into circle bodies. Polylines are treated as if they are + * closed polygons. If a tile has multiple shapes, a multi-part body will be created. Concave + * shapes are supported if poly-decomp library is included. Decomposition is not guaranteed to + * work for complex shapes (e.g. holes), so it's often best to manually decompose a concave + * polygon into multiple convex polygons yourself. + * + * @method Phaser.Physics.Matter.TileBody#setFromTileCollision + * @since 3.0.0 + * + * @param {Phaser.Types.Physics.Matter.MatterBodyTileOptions} [options] - Options to be used when creating the Matter body. See MatterJS.Body for a list of what Matter accepts. + * + * @return {Phaser.Physics.Matter.TileBody} This TileBody object. + */ + setFromTileCollision: function (options) + { + if (options === undefined) { options = {}; } + if (!HasValue(options, 'isStatic')) { options.isStatic = true; } + if (!HasValue(options, 'addToWorld')) { options.addToWorld = true; } + + var sx = this.tile.tilemapLayer.scaleX; + var sy = this.tile.tilemapLayer.scaleY; + var tileX = this.tile.getLeft(); + var tileY = this.tile.getTop(); + var collisionGroup = this.tile.getCollisionGroup(); + var collisionObjects = GetFastValue(collisionGroup, 'objects', []); + + var parts = []; + + for (var i = 0; i < collisionObjects.length; i++) + { + var object = collisionObjects[i]; + var ox = tileX + (object.x * sx); + var oy = tileY + (object.y * sy); + var ow = object.width * sx; + var oh = object.height * sy; + var body = null; + + if (object.rectangle) + { + body = Bodies.rectangle(ox + ow / 2, oy + oh / 2, ow, oh, options); + } + else if (object.ellipse) + { + body = Bodies.circle(ox + ow / 2, oy + oh / 2, ow / 2, options); + } + else if (object.polygon || object.polyline) + { + // Polygons and polylines are both treated as closed polygons + var originalPoints = object.polygon ? object.polygon : object.polyline; + + var points = originalPoints.map(function (p) + { + return { x: p.x * sx, y: p.y * sy }; + }); + + var vertices = Vertices.create(points); + + // Points are relative to the object's origin (first point placed in Tiled), but + // matter expects points to be relative to the center of mass. This only applies to + // convex shapes. When a concave shape is decomposed, multiple parts are created and + // the individual parts are positioned relative to (ox, oy). + // + // Update: 8th January 2019 - the latest version of Matter needs the Vertices adjusted, + // regardless if convex or concave. + + var center = Vertices.centre(vertices); + + ox += center.x; + oy += center.y; + + body = Bodies.fromVertices(ox, oy, vertices, options); + } + + if (body) + { + parts.push(body); + } + } + + if (parts.length === 1) + { + this.setBody(parts[0], options.addToWorld); + } + else if (parts.length > 1) + { + var tempOptions = DeepCopy(options); + + tempOptions.parts = parts; + + this.setBody(Body.create(tempOptions), tempOptions.addToWorld); + } + + return this; + }, + + /** + * Sets the current body to the given body. This will remove the previous body, if one already + * exists. + * + * @method Phaser.Physics.Matter.TileBody#setBody + * @since 3.0.0 + * + * @param {MatterJS.BodyType} body - The new Matter body to use. + * @param {boolean} [addToWorld=true] - Whether or not to add the body to the Matter world. + * + * @return {Phaser.Physics.Matter.TileBody} This TileBody object. + */ + setBody: function (body, addToWorld) + { + if (addToWorld === undefined) { addToWorld = true; } + + if (this.body) + { + this.removeBody(); + } + + this.body = body; + this.body.gameObject = this; + + if (addToWorld) + { + this.world.add(this.body); + } + + return this; + }, + + /** + * Removes the current body from the TileBody and from the Matter world + * + * @method Phaser.Physics.Matter.TileBody#removeBody + * @since 3.0.0 + * + * @return {Phaser.Physics.Matter.TileBody} This TileBody object. + */ + removeBody: function () + { + if (this.body) + { + this.world.remove(this.body); + this.body.gameObject = undefined; + this.body = undefined; + } + + return this; + }, + + /** + * Removes the current body from the tile and the world. + * + * @method Phaser.Physics.Matter.TileBody#destroy + * @since 3.0.0 + * + * @return {Phaser.Physics.Matter.TileBody} This TileBody object. + */ + destroy: function () + { + this.removeBody(); + this.tile.physics.matterBody = undefined; + this.removeAllListeners(); + } + +}); + +module.exports = MatterTileBody; + + +/***/ }), + +/***/ 19496: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Joachim Grill + * @author Richard Davey + * @copyright 2018 CodeAndWeb GmbH + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bodies = __webpack_require__(66280); +var Body = __webpack_require__(22562); +var Common = __webpack_require__(53402); +var GetFastValue = __webpack_require__(95540); +var Vertices = __webpack_require__(41598); + +/** + * Use PhysicsEditorParser.parseBody() to build a Matter body object, based on a physics data file + * created and exported with PhysicsEditor (https://www.codeandweb.com/physicseditor). + * + * @namespace Phaser.Physics.Matter.PhysicsEditorParser + * @since 3.10.0 + */ +var PhysicsEditorParser = { + + /** + * Parses a body element exported by PhysicsEditor. + * + * @function Phaser.Physics.Matter.PhysicsEditorParser.parseBody + * @since 3.10.0 + * + * @param {number} x - The horizontal world location of the body. + * @param {number} y - The vertical world location of the body. + * @param {object} config - The body configuration and fixture (child body) definitions, as exported by PhysicsEditor. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.BodyType} A compound Matter JS Body. + */ + parseBody: function (x, y, config, options) + { + if (options === undefined) { options = {}; } + + var fixtureConfigs = GetFastValue(config, 'fixtures', []); + var fixtures = []; + + for (var fc = 0; fc < fixtureConfigs.length; fc++) + { + var fixtureParts = this.parseFixture(fixtureConfigs[fc]); + + for (var i = 0; i < fixtureParts.length; i++) + { + fixtures.push(fixtureParts[i]); + } + } + + var matterConfig = Common.clone(config, true); + + Common.extend(matterConfig, options, true); + + delete matterConfig.fixtures; + delete matterConfig.type; + + var body = Body.create(matterConfig); + + Body.setParts(body, fixtures); + + Body.setPosition(body, { x: x, y: y }); + + return body; + }, + + /** + * Parses an element of the "fixtures" list exported by PhysicsEditor + * + * @function Phaser.Physics.Matter.PhysicsEditorParser.parseFixture + * @since 3.10.0 + * + * @param {object} fixtureConfig - The fixture object to parse. + * + * @return {MatterJS.BodyType[]} - An array of Matter JS Bodies. + */ + parseFixture: function (fixtureConfig) + { + var matterConfig = Common.extend({}, false, fixtureConfig); + + delete matterConfig.circle; + delete matterConfig.vertices; + + var fixtures; + + if (fixtureConfig.circle) + { + var x = GetFastValue(fixtureConfig.circle, 'x'); + var y = GetFastValue(fixtureConfig.circle, 'y'); + var r = GetFastValue(fixtureConfig.circle, 'radius'); + fixtures = [ Bodies.circle(x, y, r, matterConfig) ]; + } + else if (fixtureConfig.vertices) + { + fixtures = this.parseVertices(fixtureConfig.vertices, matterConfig); + } + + return fixtures; + }, + + /** + * Parses the "vertices" lists exported by PhysicsEditor. + * + * @function Phaser.Physics.Matter.PhysicsEditorParser.parseVertices + * @since 3.10.0 + * + * @param {array} vertexSets - The vertex lists to parse. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.BodyType[]} - An array of Matter JS Bodies. + */ + parseVertices: function (vertexSets, options) + { + if (options === undefined) { options = {}; } + + var parts = []; + + for (var v = 0; v < vertexSets.length; v++) + { + Vertices.clockwiseSort(vertexSets[v]); + + parts.push(Body.create(Common.extend({ + position: Vertices.centre(vertexSets[v]), + vertices: vertexSets[v] + }, options))); + } + + // flag coincident part edges + return Bodies.flagCoincidentParts(parts); + } +}; + +module.exports = PhysicsEditorParser; + + +/***/ }), + +/***/ 85791: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bodies = __webpack_require__(66280); +var Body = __webpack_require__(22562); + +/** + * Creates a body using the supplied physics data, as provided by a JSON file. + * + * The data file should be loaded as JSON: + * + * ```javascript + * preload () + * { + * this.load.json('ninjas', 'assets/ninjas.json); + * } + * + * create () + * { + * const ninjaShapes = this.cache.json.get('ninjas'); + * + * this.matter.add.fromJSON(400, 300, ninjaShapes.shinobi); + * } + * ``` + * + * Do not pass the entire JSON file to this method, but instead pass one of the shapes contained within it. + * + * If you pas in an `options` object, any settings in there will override those in the config object. + * + * The structure of the JSON file is as follows: + * + * ```text + * { + * 'generator_info': // The name of the application that created the JSON data + * 'shapeName': { + * 'type': // The type of body + * 'label': // Optional body label + * 'vertices': // An array, or an array of arrays, containing the vertex data in x/y object pairs + * } + * } + * ``` + * + * At the time of writing, only the Phaser Physics Tracer App exports in this format. + * + * @namespace Phaser.Physics.Matter.PhysicsJSONParser + * @since 3.22.0 + */ +var PhysicsJSONParser = { + + /** + * Parses a body element from the given JSON data. + * + * @function Phaser.Physics.Matter.PhysicsJSONParser.parseBody + * @since 3.22.0 + * + * @param {number} x - The horizontal world location of the body. + * @param {number} y - The vertical world location of the body. + * @param {object} config - The body configuration data. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {MatterJS.BodyType} A Matter JS Body. + */ + parseBody: function (x, y, config, options) + { + if (options === undefined) { options = {}; } + + var body; + var vertexSets = config.vertices; + + if (vertexSets.length === 1) + { + // Just a single Body + options.vertices = vertexSets[0]; + + body = Body.create(options); + + Bodies.flagCoincidentParts(body.parts); + } + else + { + var parts = []; + + for (var i = 0; i < vertexSets.length; i++) + { + var part = Body.create({ + vertices: vertexSets[i] + }); + + parts.push(part); + } + + Bodies.flagCoincidentParts(parts); + + options.parts = parts; + + body = Body.create(options); + } + + body.label = config.label; + + Body.setPosition(body, { x: x, y: y }); + + return body; + } + +}; + +module.exports = PhysicsJSONParser; + + +/***/ }), + +/***/ 98713: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bounds = __webpack_require__(15647); +var Class = __webpack_require__(83419); +var Composite = __webpack_require__(69351); +var Constraint = __webpack_require__(48140); +var Detector = __webpack_require__(81388); +var Events = __webpack_require__(1121); +var InputEvents = __webpack_require__(8214); +var Merge = __webpack_require__(46975); +var Sleeping = __webpack_require__(53614); +var Vector2 = __webpack_require__(26099); +var Vertices = __webpack_require__(41598); + +/** + * @classdesc + * A Pointer Constraint is a special type of constraint that allows you to click + * and drag bodies in a Matter World. It monitors the active Pointers in a Scene, + * and when one is pressed down it checks to see if that hit any part of any active + * body in the world. If it did, and the body has input enabled, it will begin to + * drag it until either released, or you stop it via the `stopDrag` method. + * + * You can adjust the stiffness, length and other properties of the constraint via + * the `options` object on creation. + * + * @class PointerConstraint + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - A reference to the Scene to which this Pointer Constraint belongs. + * @param {Phaser.Physics.Matter.World} world - A reference to the Matter World instance to which this Constraint belongs. + * @param {object} [options] - A Constraint configuration object. + */ +var PointerConstraint = new Class({ + + initialize: + + function PointerConstraint (scene, world, options) + { + if (options === undefined) { options = {}; } + + // Defaults + var defaults = { + label: 'Pointer Constraint', + pointA: { x: 0, y: 0 }, + pointB: { x: 0, y: 0 }, + length: 0.01, + stiffness: 0.1, + angularStiffness: 1, + collisionFilter: { + category: 0x0001, + mask: 0xFFFFFFFF, + group: 0 + } + }; + + /** + * A reference to the Scene to which this Pointer Constraint belongs. + * This is the same Scene as the Matter World instance. + * + * @name Phaser.Physics.Matter.PointerConstraint#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Matter World instance to which this Constraint belongs. + * + * @name Phaser.Physics.Matter.PointerConstraint#world + * @type {Phaser.Physics.Matter.World} + * @since 3.0.0 + */ + this.world = world; + + /** + * The Camera the Pointer was interacting with when the input + * down event was processed. + * + * @name Phaser.Physics.Matter.PointerConstraint#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 3.0.0 + */ + this.camera = null; + + /** + * A reference to the Input Pointer that activated this Constraint. + * This is set in the `onDown` handler. + * + * @name Phaser.Physics.Matter.PointerConstraint#pointer + * @type {Phaser.Input.Pointer} + * @default null + * @since 3.0.0 + */ + this.pointer = null; + + /** + * Is this Constraint active or not? + * + * An active constraint will be processed each update. An inactive one will be skipped. + * Use this to toggle a Pointer Constraint on and off. + * + * @name Phaser.Physics.Matter.PointerConstraint#active + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.active = true; + + /** + * The internal transformed position. + * + * @name Phaser.Physics.Matter.PointerConstraint#position + * @type {Phaser.Math.Vector2} + * @since 3.0.0 + */ + this.position = new Vector2(); + + /** + * The body that is currently being dragged, if any. + * + * @name Phaser.Physics.Matter.PointerConstraint#body + * @type {?MatterJS.BodyType} + * @since 3.16.2 + */ + this.body = null; + + /** + * The part of the body that was clicked on to start the drag. + * + * @name Phaser.Physics.Matter.PointerConstraint#part + * @type {?MatterJS.BodyType} + * @since 3.16.2 + */ + this.part = null; + + /** + * The native Matter Constraint that is used to attach to bodies. + * + * @name Phaser.Physics.Matter.PointerConstraint#constraint + * @type {MatterJS.ConstraintType} + * @since 3.0.0 + */ + this.constraint = Constraint.create(Merge(options, defaults)); + + this.world.on(Events.BEFORE_UPDATE, this.update, this); + + scene.sys.input.on(InputEvents.POINTER_DOWN, this.onDown, this); + scene.sys.input.on(InputEvents.POINTER_UP, this.onUp, this); + }, + + /** + * A Pointer has been pressed down onto the Scene. + * + * If this Constraint doesn't have an active Pointer then a hit test is set to + * run against all active bodies in the world during the _next_ call to `update`. + * If a body is found, it is bound to this constraint and the drag begins. + * + * @method Phaser.Physics.Matter.PointerConstraint#onDown + * @since 3.0.0 + * + * @param {Phaser.Input.Pointer} pointer - A reference to the Pointer that was pressed. + */ + onDown: function (pointer) + { + if (!this.pointer) + { + this.pointer = pointer; + this.camera = pointer.camera; + } + }, + + /** + * A Pointer has been released from the Scene. If it was the one this constraint was using, it's cleared. + * + * @method Phaser.Physics.Matter.PointerConstraint#onUp + * @since 3.22.0 + * + * @param {Phaser.Input.Pointer} pointer - A reference to the Pointer that was pressed. + */ + onUp: function (pointer) + { + if (pointer === this.pointer) + { + this.pointer = null; + } + }, + + /** + * Scans all active bodies in the current Matter World to see if any of them + * are hit by the Pointer. The _first one_ found to hit is set as the active contraint + * body. + * + * @method Phaser.Physics.Matter.PointerConstraint#getBody + * @fires Phaser.Physics.Matter.Events#DRAG_START + * @since 3.16.2 + * + * @return {boolean} `true` if a body was found and set, otherwise `false`. + */ + getBody: function (pointer) + { + var pos = this.position; + var constraint = this.constraint; + + this.camera.getWorldPoint(pointer.x, pointer.y, pos); + + var bodies = Composite.allBodies(this.world.localWorld); + + for (var i = 0; i < bodies.length; i++) + { + var body = bodies[i]; + + if (!body.ignorePointer && + Bounds.contains(body.bounds, pos) && + Detector.canCollide(body.collisionFilter, constraint.collisionFilter)) + { + if (this.hitTestBody(body, pos)) + { + this.world.emit(Events.DRAG_START, body, this.part, this); + + return true; + } + } + } + + return false; + }, + + /** + * Scans the current body to determine if a part of it was clicked on. + * If a part is found the body is set as the `constraint.bodyB` property, + * as well as the `body` property of this class. The part is also set. + * + * @method Phaser.Physics.Matter.PointerConstraint#hitTestBody + * @since 3.16.2 + * + * @param {MatterJS.BodyType} body - The Matter Body to check. + * @param {Phaser.Math.Vector2} position - A translated hit test position. + * + * @return {boolean} `true` if a part of the body was hit, otherwise `false`. + */ + hitTestBody: function (body, position) + { + var constraint = this.constraint; + var partsLength = body.parts.length; + + var start = (partsLength > 1) ? 1 : 0; + + for (var i = start; i < partsLength; i++) + { + var part = body.parts[i]; + + if (Vertices.contains(part.vertices, position)) + { + constraint.pointA = position; + constraint.pointB = { x: position.x - body.position.x, y: position.y - body.position.y }; + + constraint.bodyB = body; + constraint.angleB = body.angle; + + Sleeping.set(body, false); + + this.part = part; + this.body = body; + + return true; + } + } + + return false; + }, + + /** + * Internal update handler. Called in the Matter BEFORE_UPDATE step. + * + * @method Phaser.Physics.Matter.PointerConstraint#update + * @fires Phaser.Physics.Matter.Events#DRAG + * @since 3.0.0 + */ + update: function () + { + var pointer = this.pointer; + var body = this.body; + + if (!this.active || !pointer) + { + if (body) + { + this.stopDrag(); + } + + return; + } + + if (!pointer.isDown && body) + { + this.stopDrag(); + + return; + } + else if (pointer.isDown) + { + if (!this.camera || (!body && !this.getBody(pointer))) + { + return; + } + + body = this.body; + + var pos = this.position; + var constraint = this.constraint; + + this.camera.getWorldPoint(pointer.x, pointer.y, pos); + + // Drag update + constraint.pointA.x = pos.x; + constraint.pointA.y = pos.y; + + Sleeping.set(body, false); + + this.world.emit(Events.DRAG, body, this); + } + }, + + /** + * Stops the Pointer Constraint from dragging the body any further. + * + * This is called automatically if the Pointer is released while actively + * dragging a body. Or, you can call it manually to release a body from a + * constraint without having to first release the pointer. + * + * @method Phaser.Physics.Matter.PointerConstraint#stopDrag + * @fires Phaser.Physics.Matter.Events#DRAG_END + * @since 3.16.2 + */ + stopDrag: function () + { + var body = this.body; + var constraint = this.constraint; + + constraint.bodyB = null; + constraint.pointB = null; + + this.pointer = null; + this.body = null; + this.part = null; + + if (body) + { + this.world.emit(Events.DRAG_END, body, this); + } + }, + + /** + * Destroys this Pointer Constraint instance and all of its references. + * + * @method Phaser.Physics.Matter.PointerConstraint#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.world.removeConstraint(this.constraint); + + this.pointer = null; + this.constraint = null; + this.body = null; + this.part = null; + + this.world.off(Events.BEFORE_UPDATE, this.update); + + this.scene.sys.input.off(InputEvents.POINTER_DOWN, this.onDown, this); + this.scene.sys.input.off(InputEvents.POINTER_UP, this.onUp, this); + } + +}); + +module.exports = PointerConstraint; + + +/***/ }), + +/***/ 68243: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bodies = __webpack_require__(66280); +var Body = __webpack_require__(22562); +var Class = __webpack_require__(83419); +var Common = __webpack_require__(53402); +var Composite = __webpack_require__(69351); +var Engine = __webpack_require__(48413); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(1121); +var GetFastValue = __webpack_require__(95540); +var GetValue = __webpack_require__(35154); +var MatterBody = __webpack_require__(22562); +var MatterEvents = __webpack_require__(35810); +var MatterTileBody = __webpack_require__(73834); +var MatterWorld = __webpack_require__(4372); +var MatterRunner = __webpack_require__(13037); +var Vector = __webpack_require__(31725); + +/** + * @classdesc + * The Matter World class is responsible for managing one single instance of a Matter Physics World for Phaser. + * + * Access this via `this.matter.world` from within a Scene. + * + * This class creates a Matter JS World Composite along with the Matter JS Engine during instantiation. It also + * handles delta timing, bounds, body and constraint creation and debug drawing. + * + * If you wish to access the Matter JS World object directly, see the `localWorld` property. + * If you wish to access the Matter Engine directly, see the `engine` property. + * + * This class is an Event Emitter and will proxy _all_ Matter JS events, as they are received. + * + * @class World + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Physics.Matter + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Matter World instance belongs. + * @param {Phaser.Types.Physics.Matter.MatterWorldConfig} config - The Matter World configuration object. + */ +var World = new Class({ + + Extends: EventEmitter, + + initialize: + + function World (scene, config) + { + EventEmitter.call(this); + + /** + * The Scene to which this Matter World instance belongs. + * + * @name Phaser.Physics.Matter.World#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * An instance of the MatterJS Engine. + * + * @name Phaser.Physics.Matter.World#engine + * @type {MatterJS.Engine} + * @since 3.0.0 + */ + this.engine = Engine.create(config); + + /** + * A `World` composite object that will contain all simulated bodies and constraints. + * + * @name Phaser.Physics.Matter.World#localWorld + * @type {MatterJS.World} + * @since 3.0.0 + */ + this.localWorld = this.engine.world; + + var gravity = GetValue(config, 'gravity', null); + + if (gravity) + { + this.setGravity(gravity.x, gravity.y, gravity.scale); + } + else if (gravity === false) + { + this.setGravity(0, 0, 0); + } + + /** + * An object containing the 4 wall bodies that bound the physics world. + * + * @name Phaser.Physics.Matter.World#walls + * @type {Phaser.Types.Physics.Matter.MatterWalls} + * @since 3.0.0 + */ + this.walls = { left: null, right: null, top: null, bottom: null }; + + /** + * A flag that toggles if the world is enabled or not. + * + * @name Phaser.Physics.Matter.World#enabled + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.enabled = GetValue(config, 'enabled', true); + + /** + * This function is called every time the core game loop steps, which is bound to the + * Request Animation Frame frequency unless otherwise modified. + * + * The function is passed two values: `time` and `delta`, both of which come from the game step values. + * + * It must return a number. This number is used as the delta value passed to Matter.Engine.update. + * + * You can override this function with your own to define your own timestep. + * + * If you need to update the Engine multiple times in a single game step then call + * `World.update` as many times as required. Each call will trigger the `getDelta` function. + * If you wish to have full control over when the Engine updates then see the property `autoUpdate`. + * + * You can also adjust the number of iterations that Engine.update performs. + * Use the Scene Matter Physics config object to set the following properties: + * + * positionIterations (defaults to 6) + * velocityIterations (defaults to 4) + * constraintIterations (defaults to 2) + * + * Adjusting these values can help performance in certain situations, depending on the physics requirements + * of your game. + * + * @name Phaser.Physics.Matter.World#getDelta + * @type {function} + * @since 3.4.0 + */ + this.getDelta = GetValue(config, 'getDelta', this.update60Hz); + + var runnerConfig = GetFastValue(config, 'runner', {}); + + var hasFPS = GetFastValue(runnerConfig, 'fps', false); + + if (hasFPS) + { + runnerConfig.delta = 1000 / GetFastValue(runnerConfig, 'fps', 60); + } + + /** + * The Matter JS Runner Configuration object. + * + * This object is populated via the Matter Configuration object's `runner` property and is + * updated constantly during the game step. + * + * @name Phaser.Physics.Matter.World#runner + * @type {Phaser.Types.Physics.Matter.MatterRunnerConfig} + * @since 3.22.0 + */ + this.runner = MatterRunner.create(runnerConfig); + + /** + * Automatically call Engine.update every time the game steps. + * If you disable this then you are responsible for calling `World.step` directly from your game. + * If you call `set60Hz` or `set30Hz` then `autoUpdate` is reset to `true`. + * + * @name Phaser.Physics.Matter.World#autoUpdate + * @type {boolean} + * @default true + * @since 3.4.0 + */ + this.autoUpdate = GetValue(config, 'autoUpdate', true); + + var debugConfig = GetValue(config, 'debug', false); + + /** + * A flag that controls if the debug graphics will be drawn to or not. + * + * @name Phaser.Physics.Matter.World#drawDebug + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.drawDebug = (typeof(debugConfig) === 'object') ? true : debugConfig; + + /** + * An instance of the Graphics object the debug bodies are drawn to, if enabled. + * + * @name Phaser.Physics.Matter.World#debugGraphic + * @type {Phaser.GameObjects.Graphics} + * @since 3.0.0 + */ + this.debugGraphic; + + /** + * The debug configuration object. + * + * The values stored in this object are read from the Matter World Config `debug` property. + * + * When a new Body or Constraint is _added to the World_, they are given the values stored in this object, + * unless they have their own `render` object set that will override them. + * + * Note that while you can modify the values of properties in this object at run-time, it will not change + * any of the Matter objects _already added_. It will only impact objects newly added to the world, or one + * that is removed and then re-added at a later time. + * + * @name Phaser.Physics.Matter.World#debugConfig + * @type {Phaser.Types.Physics.Matter.MatterDebugConfig} + * @since 3.22.0 + */ + this.debugConfig = { + showAxes: GetFastValue(debugConfig, 'showAxes', false), + showAngleIndicator: GetFastValue(debugConfig, 'showAngleIndicator', false), + angleColor: GetFastValue(debugConfig, 'angleColor', 0xe81153), + + showBroadphase: GetFastValue(debugConfig, 'showBroadphase', false), + broadphaseColor: GetFastValue(debugConfig, 'broadphaseColor', 0xffb400), + + showBounds: GetFastValue(debugConfig, 'showBounds', false), + boundsColor: GetFastValue(debugConfig, 'boundsColor', 0xffffff), + + showVelocity: GetFastValue(debugConfig, 'showVelocity', false), + velocityColor: GetFastValue(debugConfig, 'velocityColor', 0x00aeef), + + showCollisions: GetFastValue(debugConfig, 'showCollisions', false), + collisionColor: GetFastValue(debugConfig, 'collisionColor', 0xf5950c), + + showSeparations: GetFastValue(debugConfig, 'showSeparations', false), + separationColor: GetFastValue(debugConfig, 'separationColor', 0xffa500), + + showBody: GetFastValue(debugConfig, 'showBody', true), + showStaticBody: GetFastValue(debugConfig, 'showStaticBody', true), + showInternalEdges: GetFastValue(debugConfig, 'showInternalEdges', false), + + renderFill: GetFastValue(debugConfig, 'renderFill', false), + renderLine: GetFastValue(debugConfig, 'renderLine', true), + + fillColor: GetFastValue(debugConfig, 'fillColor', 0x106909), + fillOpacity: GetFastValue(debugConfig, 'fillOpacity', 1), + lineColor: GetFastValue(debugConfig, 'lineColor', 0x28de19), + lineOpacity: GetFastValue(debugConfig, 'lineOpacity', 1), + lineThickness: GetFastValue(debugConfig, 'lineThickness', 1), + + staticFillColor: GetFastValue(debugConfig, 'staticFillColor', 0x0d177b), + staticLineColor: GetFastValue(debugConfig, 'staticLineColor', 0x1327e4), + + showSleeping: GetFastValue(debugConfig, 'showSleeping', false), + staticBodySleepOpacity: GetFastValue(debugConfig, 'staticBodySleepOpacity', 0.7), + sleepFillColor: GetFastValue(debugConfig, 'sleepFillColor', 0x464646), + sleepLineColor: GetFastValue(debugConfig, 'sleepLineColor', 0x999a99), + + showSensors: GetFastValue(debugConfig, 'showSensors', true), + sensorFillColor: GetFastValue(debugConfig, 'sensorFillColor', 0x0d177b), + sensorLineColor: GetFastValue(debugConfig, 'sensorLineColor', 0x1327e4), + + showPositions: GetFastValue(debugConfig, 'showPositions', true), + positionSize: GetFastValue(debugConfig, 'positionSize', 4), + positionColor: GetFastValue(debugConfig, 'positionColor', 0xe042da), + + showJoint: GetFastValue(debugConfig, 'showJoint', true), + jointColor: GetFastValue(debugConfig, 'jointColor', 0xe0e042), + jointLineOpacity: GetFastValue(debugConfig, 'jointLineOpacity', 1), + jointLineThickness: GetFastValue(debugConfig, 'jointLineThickness', 2), + + pinSize: GetFastValue(debugConfig, 'pinSize', 4), + pinColor: GetFastValue(debugConfig, 'pinColor', 0x42e0e0), + + springColor: GetFastValue(debugConfig, 'springColor', 0xe042e0), + + anchorColor: GetFastValue(debugConfig, 'anchorColor', 0xefefef), + anchorSize: GetFastValue(debugConfig, 'anchorSize', 4), + + showConvexHulls: GetFastValue(debugConfig, 'showConvexHulls', false), + hullColor: GetFastValue(debugConfig, 'hullColor', 0xd703d0) + }; + + if (this.drawDebug) + { + this.createDebugGraphic(); + } + + this.setEventsProxy(); + + // Create the walls + + if (GetFastValue(config, 'setBounds', false)) + { + var boundsConfig = config['setBounds']; + + if (typeof boundsConfig === 'boolean') + { + this.setBounds(); + } + else + { + var x = GetFastValue(boundsConfig, 'x', 0); + var y = GetFastValue(boundsConfig, 'y', 0); + var width = GetFastValue(boundsConfig, 'width', scene.sys.scale.width); + var height = GetFastValue(boundsConfig, 'height', scene.sys.scale.height); + var thickness = GetFastValue(boundsConfig, 'thickness', 64); + var left = GetFastValue(boundsConfig, 'left', true); + var right = GetFastValue(boundsConfig, 'right', true); + var top = GetFastValue(boundsConfig, 'top', true); + var bottom = GetFastValue(boundsConfig, 'bottom', true); + + this.setBounds(x, y, width, height, thickness, left, right, top, bottom); + } + } + }, + + /** + * Sets the debug render style for the children of the given Matter Composite. + * + * Composites themselves do not render, but they can contain bodies, constraints and other composites that may do. + * So the children of this composite are passed to the `setBodyRenderStyle`, `setCompositeRenderStyle` and + * `setConstraintRenderStyle` methods accordingly. + * + * @method Phaser.Physics.Matter.World#setCompositeRenderStyle + * @since 3.22.0 + * + * @param {MatterJS.CompositeType} composite - The Matter Composite to set the render style on. + * + * @return {this} This Matter World instance for method chaining. + */ + setCompositeRenderStyle: function (composite) + { + var bodies = composite.bodies; + var constraints = composite.constraints; + var composites = composite.composites; + + var i; + var obj; + var render; + + for (i = 0; i < bodies.length; i++) + { + obj = bodies[i]; + render = obj.render; + + this.setBodyRenderStyle(obj, render.lineColor, render.lineOpacity, render.lineThickness, render.fillColor, render.fillOpacity); + } + + for (i = 0; i < constraints.length; i++) + { + obj = constraints[i]; + render = obj.render; + + this.setConstraintRenderStyle(obj, render.lineColor, render.lineOpacity, render.lineThickness, render.pinSize, render.anchorColor, render.anchorSize); + } + + for (i = 0; i < composites.length; i++) + { + obj = composites[i]; + + this.setCompositeRenderStyle(obj); + } + + return this; + }, + + /** + * Sets the debug render style for the given Matter Body. + * + * If you are using this on a Phaser Game Object, such as a Matter Sprite, then pass in the body property + * to this method, not the Game Object itself. + * + * If you wish to skip a parameter, so it retains its current value, pass `false` for it. + * + * If you wish to reset the Body render colors to the defaults found in the World Debug Config, then call + * this method with just the `body` parameter provided and no others. + * + * @method Phaser.Physics.Matter.World#setBodyRenderStyle + * @since 3.22.0 + * + * @param {MatterJS.BodyType} body - The Matter Body to set the render style on. + * @param {number} [lineColor] - The line color. If `null` it will use the World Debug Config value. + * @param {number} [lineOpacity] - The line opacity, between 0 and 1. If `null` it will use the World Debug Config value. + * @param {number} [lineThickness] - The line thickness. If `null` it will use the World Debug Config value. + * @param {number} [fillColor] - The fill color. If `null` it will use the World Debug Config value. + * @param {number} [fillOpacity] - The fill opacity, between 0 and 1. If `null` it will use the World Debug Config value. + * + * @return {this} This Matter World instance for method chaining. + */ + setBodyRenderStyle: function (body, lineColor, lineOpacity, lineThickness, fillColor, fillOpacity) + { + var render = body.render; + var config = this.debugConfig; + + if (!render) + { + return this; + } + + if (lineColor === undefined || lineColor === null) + { + lineColor = (body.isStatic) ? config.staticLineColor : config.lineColor; + } + + if (lineOpacity === undefined || lineOpacity === null) + { + lineOpacity = config.lineOpacity; + } + + if (lineThickness === undefined || lineThickness === null) + { + lineThickness = config.lineThickness; + } + + if (fillColor === undefined || fillColor === null) + { + fillColor = (body.isStatic) ? config.staticFillColor : config.fillColor; + } + + if (fillOpacity === undefined || fillOpacity === null) + { + fillOpacity = config.fillOpacity; + } + + if (lineColor !== false) + { + render.lineColor = lineColor; + } + + if (lineOpacity !== false) + { + render.lineOpacity = lineOpacity; + } + + if (lineThickness !== false) + { + render.lineThickness = lineThickness; + } + + if (fillColor !== false) + { + render.fillColor = fillColor; + } + + if (fillOpacity !== false) + { + render.fillOpacity = fillOpacity; + } + + return this; + }, + + /** + * Sets the debug render style for the given Matter Constraint. + * + * If you are using this on a Phaser Game Object, then pass in the body property + * to this method, not the Game Object itself. + * + * If you wish to skip a parameter, so it retains its current value, pass `false` for it. + * + * If you wish to reset the Constraint render colors to the defaults found in the World Debug Config, then call + * this method with just the `constraint` parameter provided and no others. + * + * @method Phaser.Physics.Matter.World#setConstraintRenderStyle + * @since 3.22.0 + * + * @param {MatterJS.ConstraintType} constraint - The Matter Constraint to set the render style on. + * @param {number} [lineColor] - The line color. If `null` it will use the World Debug Config value. + * @param {number} [lineOpacity] - The line opacity, between 0 and 1. If `null` it will use the World Debug Config value. + * @param {number} [lineThickness] - The line thickness. If `null` it will use the World Debug Config value. + * @param {number} [pinSize] - If this constraint is a pin, this sets the size of the pin circle. If `null` it will use the World Debug Config value. + * @param {number} [anchorColor] - The color used when rendering this constraints anchors. If `null` it will use the World Debug Config value. + * @param {number} [anchorSize] - The size of the anchor circle, if this constraint has anchors. If `null` it will use the World Debug Config value. + * + * @return {this} This Matter World instance for method chaining. + */ + setConstraintRenderStyle: function (constraint, lineColor, lineOpacity, lineThickness, pinSize, anchorColor, anchorSize) + { + var render = constraint.render; + var config = this.debugConfig; + + if (!render) + { + return this; + } + + // Reset them + if (lineColor === undefined || lineColor === null) + { + var type = render.type; + + if (type === 'line') + { + lineColor = config.jointColor; + } + else if (type === 'pin') + { + lineColor = config.pinColor; + } + else if (type === 'spring') + { + lineColor = config.springColor; + } + } + + if (lineOpacity === undefined || lineOpacity === null) + { + lineOpacity = config.jointLineOpacity; + } + + if (lineThickness === undefined || lineThickness === null) + { + lineThickness = config.jointLineThickness; + } + + if (pinSize === undefined || pinSize === null) + { + pinSize = config.pinSize; + } + + if (anchorColor === undefined || anchorColor === null) + { + anchorColor = config.anchorColor; + } + + if (anchorSize === undefined || anchorSize === null) + { + anchorSize = config.anchorSize; + } + + if (lineColor !== false) + { + render.lineColor = lineColor; + } + + if (lineOpacity !== false) + { + render.lineOpacity = lineOpacity; + } + + if (lineThickness !== false) + { + render.lineThickness = lineThickness; + } + + if (pinSize !== false) + { + render.pinSize = pinSize; + } + + if (anchorColor !== false) + { + render.anchorColor = anchorColor; + } + + if (anchorSize !== false) + { + render.anchorSize = anchorSize; + } + + return this; + }, + + /** + * This internal method acts as a proxy between all of the Matter JS events and then re-emits them + * via this class. + * + * @method Phaser.Physics.Matter.World#setEventsProxy + * @since 3.0.0 + */ + setEventsProxy: function () + { + var _this = this; + var engine = this.engine; + var world = this.localWorld; + + // Inject debug styles + + if (this.drawDebug) + { + MatterEvents.on(world, 'compositeModified', function (composite) + { + _this.setCompositeRenderStyle(composite); + }); + + MatterEvents.on(world, 'beforeAdd', function (event) + { + var objects = [].concat(event.object); + + for (var i = 0; i < objects.length; i++) + { + var obj = objects[i]; + var render = obj.render; + + if (obj.type === 'body') + { + _this.setBodyRenderStyle(obj, render.lineColor, render.lineOpacity, render.lineThickness, render.fillColor, render.fillOpacity); + } + else if (obj.type === 'composite') + { + _this.setCompositeRenderStyle(obj); + } + else if (obj.type === 'constraint') + { + _this.setConstraintRenderStyle(obj, render.lineColor, render.lineOpacity, render.lineThickness, render.pinSize, render.anchorColor, render.anchorSize); + } + } + }); + } + + MatterEvents.on(world, 'beforeAdd', function (event) + { + _this.emit(Events.BEFORE_ADD, event); + }); + + MatterEvents.on(world, 'afterAdd', function (event) + { + _this.emit(Events.AFTER_ADD, event); + }); + + MatterEvents.on(world, 'beforeRemove', function (event) + { + _this.emit(Events.BEFORE_REMOVE, event); + }); + + MatterEvents.on(world, 'afterRemove', function (event) + { + _this.emit(Events.AFTER_REMOVE, event); + }); + + MatterEvents.on(engine, 'beforeUpdate', function (event) + { + _this.emit(Events.BEFORE_UPDATE, event); + }); + + MatterEvents.on(engine, 'afterUpdate', function (event) + { + _this.emit(Events.AFTER_UPDATE, event); + }); + + MatterEvents.on(engine, 'collisionStart', function (event) + { + var pairs = event.pairs; + var bodyA; + var bodyB; + + if (pairs.length > 0) + { + pairs.map(function (pair) + { + bodyA = pair.bodyA; + bodyB = pair.bodyB; + + if (bodyA.gameObject) + { + bodyA.gameObject.emit('collide', bodyA, bodyB, pair); + } + + if (bodyB.gameObject) + { + bodyB.gameObject.emit('collide', bodyB, bodyA, pair); + } + + MatterEvents.trigger(bodyA, 'onCollide', { pair: pair }); + MatterEvents.trigger(bodyB, 'onCollide', { pair: pair }); + + if (bodyA.onCollideCallback) + { + bodyA.onCollideCallback(pair); + } + + if (bodyB.onCollideCallback) + { + bodyB.onCollideCallback(pair); + } + + if (bodyA.onCollideWith[bodyB.id]) + { + bodyA.onCollideWith[bodyB.id](bodyB, pair); + } + + if (bodyB.onCollideWith[bodyA.id]) + { + bodyB.onCollideWith[bodyA.id](bodyA, pair); + } + }); + } + + _this.emit(Events.COLLISION_START, event, bodyA, bodyB); + }); + + MatterEvents.on(engine, 'collisionActive', function (event) + { + var pairs = event.pairs; + var bodyA; + var bodyB; + + if (pairs.length > 0) + { + pairs.map(function (pair) + { + bodyA = pair.bodyA; + bodyB = pair.bodyB; + + if (bodyA.gameObject) + { + bodyA.gameObject.emit('collideActive', bodyA, bodyB, pair); + } + + if (bodyB.gameObject) + { + bodyB.gameObject.emit('collideActive', bodyB, bodyA, pair); + } + + MatterEvents.trigger(bodyA, 'onCollideActive', { pair: pair }); + MatterEvents.trigger(bodyB, 'onCollideActive', { pair: pair }); + + if (bodyA.onCollideActiveCallback) + { + bodyA.onCollideActiveCallback(pair); + } + + if (bodyB.onCollideActiveCallback) + { + bodyB.onCollideActiveCallback(pair); + } + }); + } + + _this.emit(Events.COLLISION_ACTIVE, event, bodyA, bodyB); + }); + + MatterEvents.on(engine, 'collisionEnd', function (event) + { + var pairs = event.pairs; + var bodyA; + var bodyB; + + if (pairs.length > 0) + { + pairs.map(function (pair) + { + bodyA = pair.bodyA; + bodyB = pair.bodyB; + + if (bodyA.gameObject) + { + bodyA.gameObject.emit('collideEnd', bodyA, bodyB, pair); + } + + if (bodyB.gameObject) + { + bodyB.gameObject.emit('collideEnd', bodyB, bodyA, pair); + } + + MatterEvents.trigger(bodyA, 'onCollideEnd', { pair: pair }); + MatterEvents.trigger(bodyB, 'onCollideEnd', { pair: pair }); + + if (bodyA.onCollideEndCallback) + { + bodyA.onCollideEndCallback(pair); + } + + if (bodyB.onCollideEndCallback) + { + bodyB.onCollideEndCallback(pair); + } + }); + } + + _this.emit(Events.COLLISION_END, event, bodyA, bodyB); + }); + }, + + /** + * Sets the bounds of the Physics world to match the given world pixel dimensions. + * + * You can optionally set which 'walls' to create: left, right, top or bottom. + * If none of the walls are given it will default to use the walls settings it had previously. + * I.e. if you previously told it to not have the left or right walls, and you then adjust the world size + * the newly created bounds will also not have the left and right walls. + * Explicitly state them in the parameters to override this. + * + * @method Phaser.Physics.Matter.World#setBounds + * @since 3.0.0 + * + * @param {number} [x=0] - The x coordinate of the top-left corner of the bounds. + * @param {number} [y=0] - The y coordinate of the top-left corner of the bounds. + * @param {number} [width] - The width of the bounds. + * @param {number} [height] - The height of the bounds. + * @param {number} [thickness=64] - The thickness of each wall, in pixels. + * @param {boolean} [left=true] - If true will create the left bounds wall. + * @param {boolean} [right=true] - If true will create the right bounds wall. + * @param {boolean} [top=true] - If true will create the top bounds wall. + * @param {boolean} [bottom=true] - If true will create the bottom bounds wall. + * + * @return {Phaser.Physics.Matter.World} This Matter World object. + */ + setBounds: function (x, y, width, height, thickness, left, right, top, bottom) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.scene.sys.scale.width; } + if (height === undefined) { height = this.scene.sys.scale.height; } + if (thickness === undefined) { thickness = 64; } + if (left === undefined) { left = true; } + if (right === undefined) { right = true; } + if (top === undefined) { top = true; } + if (bottom === undefined) { bottom = true; } + + this.updateWall(left, 'left', x - thickness, y - thickness, thickness, height + (thickness * 2)); + this.updateWall(right, 'right', x + width, y - thickness, thickness, height + (thickness * 2)); + this.updateWall(top, 'top', x, y - thickness, width, thickness); + this.updateWall(bottom, 'bottom', x, y + height, width, thickness); + + return this; + }, + + /** + * Updates the 4 rectangle bodies that were created, if `setBounds` was set in the Matter config, to use + * the new positions and sizes. This method is usually only called internally via the `setBounds` method. + * + * @method Phaser.Physics.Matter.World#updateWall + * @since 3.0.0 + * + * @param {boolean} add - `true` if the walls are being added or updated, `false` to remove them from the world. + * @param {string} [position] - Either `left`, `right`, `top` or `bottom`. Only optional if `add` is `false`. + * @param {number} [x] - The horizontal position to place the walls at. Only optional if `add` is `false`. + * @param {number} [y] - The vertical position to place the walls at. Only optional if `add` is `false`. + * @param {number} [width] - The width of the walls, in pixels. Only optional if `add` is `false`. + * @param {number} [height] - The height of the walls, in pixels. Only optional if `add` is `false`. + */ + updateWall: function (add, position, x, y, width, height) + { + var wall = this.walls[position]; + + if (add) + { + if (wall) + { + MatterWorld.remove(this.localWorld, wall); + } + + // adjust center + x += (width / 2); + y += (height / 2); + + this.walls[position] = this.create(x, y, width, height, { isStatic: true, friction: 0, frictionStatic: 0 }); + } + else + { + if (wall) + { + MatterWorld.remove(this.localWorld, wall); + } + + this.walls[position] = null; + } + }, + + /** + * Creates a Phaser.GameObjects.Graphics object that is used to render all of the debug bodies and joints to. + * + * This method is called automatically by the constructor, if debugging has been enabled. + * + * The created Graphics object is automatically added to the Scene at 0x0 and given a depth of `Number.MAX_VALUE`, + * so it renders above all else in the Scene. + * + * The Graphics object is assigned to the `debugGraphic` property of this class and `drawDebug` is enabled. + * + * @method Phaser.Physics.Matter.World#createDebugGraphic + * @since 3.0.0 + * + * @return {Phaser.GameObjects.Graphics} The newly created Graphics object. + */ + createDebugGraphic: function () + { + var graphic = this.scene.sys.add.graphics({ x: 0, y: 0 }); + + graphic.setDepth(Number.MAX_VALUE); + + this.debugGraphic = graphic; + + this.drawDebug = true; + + return graphic; + }, + + /** + * Sets the world gravity and gravity scale to 0. + * + * @method Phaser.Physics.Matter.World#disableGravity + * @since 3.0.0 + * + * @return {this} This Matter World object. + */ + disableGravity: function () + { + this.localWorld.gravity.x = 0; + this.localWorld.gravity.y = 0; + this.localWorld.gravity.scale = 0; + + return this; + }, + + /** + * Sets the worlds gravity to the values given. + * + * Gravity effects all bodies in the world, unless they have the `ignoreGravity` flag set. + * + * @method Phaser.Physics.Matter.World#setGravity + * @since 3.0.0 + * + * @param {number} [x=0] - The world gravity x component. + * @param {number} [y=1] - The world gravity y component. + * @param {number} [scale=0.001] - The gravity scale factor. + * + * @return {this} This Matter World object. + */ + setGravity: function (x, y, scale) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 1; } + if (scale === undefined) { scale = 0.001; } + + this.localWorld.gravity.x = x; + this.localWorld.gravity.y = y; + this.localWorld.gravity.scale = scale; + + return this; + }, + + /** + * Creates a rectangle Matter body and adds it to the world. + * + * @method Phaser.Physics.Matter.World#create + * @since 3.0.0 + * + * @param {number} x - The horizontal position of the body in the world. + * @param {number} y - The vertical position of the body in the world. + * @param {number} width - The width of the body. + * @param {number} height - The height of the body. + * @param {object} options - Optional Matter configuration object. + * + * @return {MatterJS.BodyType} The Matter.js body that was created. + */ + create: function (x, y, width, height, options) + { + var body = Bodies.rectangle(x, y, width, height, options); + + MatterWorld.add(this.localWorld, body); + + return body; + }, + + /** + * Adds a Matter JS object, or array of objects, to the world. + * + * The objects should be valid Matter JS entities, such as a Body, Composite or Constraint. + * + * Triggers `beforeAdd` and `afterAdd` events. + * + * @method Phaser.Physics.Matter.World#add + * @since 3.0.0 + * + * @param {(object|object[])} object - Can be single object, or an array, and can be a body, composite or constraint. + * + * @return {this} This Matter World object. + */ + add: function (object) + { + MatterWorld.add(this.localWorld, object); + + return this; + }, + + /** + * Removes a Matter JS object, or array of objects, from the world. + * + * The objects should be valid Matter JS entities, such as a Body, Composite or Constraint. + * + * Triggers `beforeRemove` and `afterRemove` events. + * + * @method Phaser.Physics.Matter.World#remove + * @since 3.0.0 + * + * @param {(object|object[])} object - Can be single object, or an array, and can be a body, composite or constraint. + * @param {boolean} [deep=false] - Optionally search the objects children and recursively remove those as well. + * + * @return {this} This Matter World object. + */ + remove: function (object, deep) + { + if (!Array.isArray(object)) + { + object = [ object ]; + } + + for (var i = 0; i < object.length; i++) + { + var entity = object[i]; + + var body = (entity.body) ? entity.body : entity; + + Composite.remove(this.localWorld, body, deep); + } + + return this; + }, + + /** + * Removes a Matter JS constraint, or array of constraints, from the world. + * + * Triggers `beforeRemove` and `afterRemove` events. + * + * @method Phaser.Physics.Matter.World#removeConstraint + * @since 3.0.0 + * + * @param {(MatterJS.ConstraintType|MatterJS.ConstraintType[])} constraint - A Matter JS Constraint, or an array of constraints, to be removed. + * @param {boolean} [deep=false] - Optionally search the objects children and recursively remove those as well. + * + * @return {this} This Matter World object. + */ + removeConstraint: function (constraint, deep) + { + Composite.remove(this.localWorld, constraint, deep); + + return this; + }, + + /** + * Adds `MatterTileBody` instances for all the colliding tiles within the given tilemap layer. + * + * Set the appropriate tiles in your layer to collide before calling this method! + * + * If you modify the map after calling this method, i.e. via a function like `putTileAt` then + * you should call the `Phaser.Physics.Matter.World.convertTiles` function directly, passing + * it an array of the tiles you've added to your map. + * + * @method Phaser.Physics.Matter.World#convertTilemapLayer + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.TilemapLayer} tilemapLayer - An array of tiles. + * @param {object} [options] - Options to be passed to the MatterTileBody constructor. {@see Phaser.Physics.Matter.TileBody} + * + * @return {this} This Matter World object. + */ + convertTilemapLayer: function (tilemapLayer, options) + { + var layerData = tilemapLayer.layer; + var tiles = tilemapLayer.getTilesWithin(0, 0, layerData.width, layerData.height, { isColliding: true }); + + this.convertTiles(tiles, options); + + return this; + }, + + /** + * Creates `MatterTileBody` instances for all of the given tiles. This creates bodies regardless of whether the + * tiles are set to collide or not, or if they have a body already, or not. + * + * If you wish to pass an array of tiles that may already have bodies, you should filter the array before hand. + * + * @method Phaser.Physics.Matter.World#convertTiles + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.Tile[]} tiles - An array of tiles. + * @param {object} [options] - Options to be passed to the MatterTileBody constructor. {@see Phaser.Physics.Matter.TileBody} + * + * @return {this} This Matter World object. + */ + convertTiles: function (tiles, options) + { + if (tiles.length === 0) + { + return this; + } + + for (var i = 0; i < tiles.length; i++) + { + new MatterTileBody(this, tiles[i], options); + } + + return this; + }, + + /** + * Returns the next unique group index for which bodies will collide. + * If `isNonColliding` is `true`, returns the next unique group index for which bodies will not collide. + * + * @method Phaser.Physics.Matter.World#nextGroup + * @since 3.0.0 + * + * @param {boolean} [isNonColliding=false] - If `true`, returns the next unique group index for which bodies will _not_ collide. + * + * @return {number} Unique category bitfield + */ + nextGroup: function (isNonColliding) + { + return MatterBody.nextGroup(isNonColliding); + }, + + /** + * Returns the next unique category bitfield (starting after the initial default category 0x0001). + * There are 32 available. + * + * @method Phaser.Physics.Matter.World#nextCategory + * @since 3.0.0 + * + * @return {number} Unique category bitfield + */ + nextCategory: function () + { + return MatterBody.nextCategory(); + }, + + /** + * Pauses this Matter World instance and sets `enabled` to `false`. + * + * A paused world will not run any simulations for the duration it is paused. + * + * @method Phaser.Physics.Matter.World#pause + * @fires Phaser.Physics.Matter.Events#PAUSE + * @since 3.0.0 + * + * @return {this} This Matter World object. + */ + pause: function () + { + this.enabled = false; + + this.emit(Events.PAUSE); + + return this; + }, + + /** + * Resumes this Matter World instance from a paused state and sets `enabled` to `true`. + * + * @method Phaser.Physics.Matter.World#resume + * @fires Phaser.Physics.Matter.Events#RESUME + * @since 3.0.0 + * + * @return {this} This Matter World object. + */ + resume: function () + { + this.enabled = true; + + this.runner.timeLastTick = Common.now(); + + this.emit(Events.RESUME); + + return this; + }, + + /** + * The internal update method. This is called automatically by the parent Scene. + * + * Moves the simulation forward in time by delta ms. Uses `World.correction` value as an optional number that + * specifies the time correction factor to apply to the update. This can help improve the accuracy of the + * simulation in cases where delta is changing between updates. The value of correction is defined as `delta / lastDelta`, + * i.e. the percentage change of delta over the last step. Therefore the value is always 1 (no correction) when + * delta is constant (or when no correction is desired, which is the default). + * See the paper on Time Corrected Verlet for more information. + * + * Triggers `beforeUpdate` and `afterUpdate` events. Triggers `collisionStart`, `collisionActive` and `collisionEnd` events. + * + * If the World is paused, `update` is still run, but exits early and does not update the Matter Engine. + * + * @method Phaser.Physics.Matter.World#update + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + update: function (time) + { + if (!this.enabled || !this.autoUpdate) + { + return; + } + + var engine = this.engine; + var runner = this.runner; + + var tickStartTime = Common.now(), + engineDelta = runner.delta, + updateCount = 0; + + // find frame delta time since last call + var frameDelta = time - runner.timeLastTick; + + // fallback for unusable frame delta values (e.g. 0, NaN, on first frame or long pauses) + if (!frameDelta || !runner.timeLastTick || frameDelta > Math.max(MatterRunner._maxFrameDelta, runner.maxFrameTime)) + { + // reuse last accepted frame delta else fallback + frameDelta = runner.frameDelta || MatterRunner._frameDeltaFallback; + } + + if (runner.frameDeltaSmoothing) + { + // record frame delta over a number of frames + runner.frameDeltaHistory.push(frameDelta); + runner.frameDeltaHistory = runner.frameDeltaHistory.slice(-runner.frameDeltaHistorySize); + + // sort frame delta history + var deltaHistorySorted = runner.frameDeltaHistory.slice(0).sort(); + + // sample a central window to limit outliers + var deltaHistoryWindow = runner.frameDeltaHistory.slice( + deltaHistorySorted.length * MatterRunner._smoothingLowerBound, + deltaHistorySorted.length * MatterRunner._smoothingUpperBound + ); + + // take the mean of the central window + var frameDeltaSmoothed = MatterRunner._mean(deltaHistoryWindow); + frameDelta = frameDeltaSmoothed || frameDelta; + } + + if (runner.frameDeltaSnapping) + { + // snap frame delta to the nearest 1 Hz + frameDelta = 1000 / Math.round(1000 / frameDelta); + } + + // update runner values for next call + runner.frameDelta = frameDelta; + runner.timeLastTick = time; + + // accumulate elapsed time + runner.timeBuffer += runner.frameDelta; + + // limit time buffer size to a single frame of updates + runner.timeBuffer = Common.clamp( + runner.timeBuffer, 0, runner.frameDelta + engineDelta * MatterRunner._timeBufferMargin + ); + + // reset count of over budget updates + runner.lastUpdatesDeferred = 0; + + // get max updates per frame + var maxUpdates = runner.maxUpdates || Math.ceil(runner.maxFrameTime / engineDelta); + + var updateStartTime = Common.now(); + + // simulate time elapsed between calls + while (engineDelta > 0 && runner.timeBuffer >= engineDelta * MatterRunner._timeBufferMargin) + { + // update the engine + Engine.update(engine, engineDelta); + + // consume time simulated from buffer + runner.timeBuffer -= engineDelta; + updateCount += 1; + + // find elapsed time during this tick + var elapsedTimeTotal = Common.now() - tickStartTime, + elapsedTimeUpdates = Common.now() - updateStartTime, + elapsedNextEstimate = elapsedTimeTotal + MatterRunner._elapsedNextEstimate * elapsedTimeUpdates / updateCount; + + // defer updates if over performance budgets for this frame + if (updateCount >= maxUpdates || elapsedNextEstimate > runner.maxFrameTime) + { + runner.lastUpdatesDeferred = Math.round(Math.max(0, (runner.timeBuffer / engineDelta) - MatterRunner._timeBufferMargin)); + break; + } + } + }, + + /** + * Manually advances the physics simulation by one iteration. + * + * You can optionally pass in the `delta` and `correction` values to be used by Engine.update. + * If undefined they use the Matter defaults of 60Hz and no correction. + * + * Calling `step` directly bypasses any checks of `enabled` or `autoUpdate`. + * + * It also ignores any custom `getDelta` functions, as you should be passing the delta + * value in to this call. + * + * You can adjust the number of iterations that Engine.update performs internally. + * Use the Scene Matter Physics config object to set the following properties: + * + * positionIterations (defaults to 6) + * velocityIterations (defaults to 4) + * constraintIterations (defaults to 2) + * + * Adjusting these values can help performance in certain situations, depending on the physics requirements + * of your game. + * + * @method Phaser.Physics.Matter.World#step + * @since 3.4.0 + * + * @param {number} [delta=16.666] - The delta value. + */ + step: function (delta) + { + Engine.update(this.engine, delta); + }, + + /** + * Runs the Matter Engine.update at a fixed timestep of 60Hz. + * + * @method Phaser.Physics.Matter.World#update60Hz + * @since 3.4.0 + * + * @return {number} The delta value to be passed to Engine.update. + */ + update60Hz: function () + { + return 1000 / 60; + }, + + /** + * Runs the Matter Engine.update at a fixed timestep of 30Hz. + * + * @method Phaser.Physics.Matter.World#update30Hz + * @since 3.4.0 + * + * @return {number} The delta value to be passed to Engine.update. + */ + update30Hz: function () + { + return 1000 / 30; + }, + + /** + * Returns `true` if the given body can be found within the World. + * + * @method Phaser.Physics.Matter.World#has + * @since 3.22.0 + * + * @param {(MatterJS.Body|Phaser.GameObjects.GameObject)} body - The Matter Body, or Game Object, to search for within the world. + * + * @return {MatterJS.BodyType[]} An array of all the Matter JS Bodies in this World. + */ + has: function (body) + { + var src = (body.hasOwnProperty('body')) ? body.body : body; + + return (Composite.get(this.localWorld, src.id, src.type) !== null); + }, + + /** + * Returns all the bodies in the Matter World, including all bodies in children, recursively. + * + * @method Phaser.Physics.Matter.World#getAllBodies + * @since 3.22.0 + * + * @return {MatterJS.BodyType[]} An array of all the Matter JS Bodies in this World. + */ + getAllBodies: function () + { + return Composite.allBodies(this.localWorld); + }, + + /** + * Returns all the constraints in the Matter World, including all constraints in children, recursively. + * + * @method Phaser.Physics.Matter.World#getAllConstraints + * @since 3.22.0 + * + * @return {MatterJS.ConstraintType[]} An array of all the Matter JS Constraints in this World. + */ + getAllConstraints: function () + { + return Composite.allConstraints(this.localWorld); + }, + + /** + * Returns all the composites in the Matter World, including all composites in children, recursively. + * + * @method Phaser.Physics.Matter.World#getAllComposites + * @since 3.22.0 + * + * @return {MatterJS.CompositeType[]} An array of all the Matter JS Composites in this World. + */ + getAllComposites: function () + { + return Composite.allComposites(this.localWorld); + }, + + /** + * Handles the rendering of bodies and debug information to the debug Graphics object, if enabled. + * + * This method is called automatically by the Scene after all processing has taken place. + * + * @method Phaser.Physics.Matter.World#postUpdate + * @private + * @since 3.0.0 + */ + postUpdate: function () + { + if (!this.drawDebug) + { + return; + } + + var config = this.debugConfig; + var engine = this.engine; + var graphics = this.debugGraphic; + + var bodies = Composite.allBodies(this.localWorld); + + this.debugGraphic.clear(); + + if (config.showBroadphase && engine.broadphase.controller) + { + this.renderGrid(engine.broadphase, graphics, config.broadphaseColor, 0.5); + } + + if (config.showBounds) + { + this.renderBodyBounds(bodies, graphics, config.boundsColor, 0.5); + } + + if (config.showBody || config.showStaticBody) + { + this.renderBodies(bodies); + } + + if (config.showJoint) + { + this.renderJoints(); + } + + if (config.showAxes || config.showAngleIndicator) + { + this.renderBodyAxes(bodies, graphics, config.showAxes, config.angleColor, 0.5); + } + + if (config.showVelocity) + { + this.renderBodyVelocity(bodies, graphics, config.velocityColor, 1, 2); + } + + if (config.showSeparations) + { + this.renderSeparations(engine.pairs.list, graphics, config.separationColor); + } + + if (config.showCollisions) + { + this.renderCollisions(engine.pairs.list, graphics, config.collisionColor); + } + }, + + /** + * Renders the Engine Broadphase Controller Grid to the given Graphics instance. + * + * The debug renderer calls this method if the `showBroadphase` config value is set. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render the Grid to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderGrid + * @since 3.22.0 + * + * @param {MatterJS.Grid} grid - The Matter Grid to be rendered. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} lineColor - The line color. + * @param {number} lineOpacity - The line opacity, between 0 and 1. + * + * @return {this} This Matter World instance for method chaining. + */ + renderGrid: function (grid, graphics, lineColor, lineOpacity) + { + graphics.lineStyle(1, lineColor, lineOpacity); + + var bucketKeys = Common.keys(grid.buckets); + + for (var i = 0; i < bucketKeys.length; i++) + { + var bucketId = bucketKeys[i]; + + if (grid.buckets[bucketId].length < 2) + { + continue; + } + + var region = bucketId.split(/C|R/); + + graphics.strokeRect( + parseInt(region[1], 10) * grid.bucketWidth, + parseInt(region[2], 10) * grid.bucketHeight, + grid.bucketWidth, + grid.bucketHeight + ); + } + + return this; + }, + + /** + * Renders the list of Pair separations to the given Graphics instance. + * + * The debug renderer calls this method if the `showSeparations` config value is set. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render the Grid to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderSeparations + * @since 3.22.0 + * + * @param {MatterJS.Pair[]} pairs - An array of Matter Pairs to be rendered. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} lineColor - The line color. + * + * @return {this} This Matter World instance for method chaining. + */ + renderSeparations: function (pairs, graphics, lineColor) + { + graphics.lineStyle(1, lineColor, 1); + + for (var i = 0; i < pairs.length; i++) + { + var pair = pairs[i]; + + if (!pair.isActive) + { + continue; + } + + var collision = pair.collision; + var bodyA = collision.bodyA; + var bodyB = collision.bodyB; + var posA = bodyA.position; + var posB = bodyB.position; + var penetration = collision.penetration; + + var k = (!bodyA.isStatic && !bodyB.isStatic) ? 4 : 1; + + if (bodyB.isStatic) + { + k = 0; + } + + graphics.lineBetween( + posB.x, + posB.y, + posB.x - (penetration.x * k), + posB.y - (penetration.y * k) + ); + + k = (!bodyA.isStatic && !bodyB.isStatic) ? 4 : 1; + + if (bodyA.isStatic) + { + k = 0; + } + + graphics.lineBetween( + posA.x, + posA.y, + posA.x - (penetration.x * k), + posA.y - (penetration.y * k) + ); + } + + return this; + }, + + /** + * Renders the list of collision points and normals to the given Graphics instance. + * + * The debug renderer calls this method if the `showCollisions` config value is set. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render the Grid to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderCollisions + * @since 3.22.0 + * + * @param {MatterJS.Pair[]} pairs - An array of Matter Pairs to be rendered. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} lineColor - The line color. + * + * @return {this} This Matter World instance for method chaining. + */ + renderCollisions: function (pairs, graphics, lineColor) + { + graphics.lineStyle(1, lineColor, 0.5); + graphics.fillStyle(lineColor, 1); + + var i; + var pair; + + // Collision Positions + + for (i = 0; i < pairs.length; i++) + { + pair = pairs[i]; + + if (!pair.isActive) + { + continue; + } + + for (var j = 0; j < pair.contactCount; j++) + { + var contact = pair.contacts[j]; + var vertex = contact.vertex; + + if (vertex) + { + graphics.fillRect(vertex.x - 2, vertex.y - 2, 5, 5); + } + } + } + + // Collision Normals + + for (i = 0; i < pairs.length; i++) + { + pair = pairs[i]; + + if (!pair.isActive) + { + continue; + } + + var collision = pair.collision; + var contacts = pair.contacts; + + if (pair.contactCount > 0) + { + var normalPosX = contacts[0].vertex.x; + var normalPosY = contacts[0].vertex.y; + + if (pair.contactCount === 2) + { + normalPosX = (contacts[0].vertex.x + contacts[1].vertex.x) / 2; + normalPosY = (contacts[0].vertex.y + contacts[1].vertex.y) / 2; + } + + if (collision.bodyB === collision.supports[0].body || collision.bodyA.isStatic) + { + graphics.lineBetween( + normalPosX - collision.normal.x * 8, + normalPosY - collision.normal.y * 8, + normalPosX, + normalPosY + ); + } + else + { + graphics.lineBetween( + normalPosX + collision.normal.x * 8, + normalPosY + collision.normal.y * 8, + normalPosX, + normalPosY + ); + } + } + } + + return this; + }, + + /** + * Renders the bounds of an array of Bodies to the given Graphics instance. + * + * If the body is a compound body, it will render the bounds for the parent compound. + * + * The debug renderer calls this method if the `showBounds` config value is set. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render bounds to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderBodyBounds + * @since 3.22.0 + * + * @param {array} bodies - An array of bodies from the localWorld. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} lineColor - The line color. + * @param {number} lineOpacity - The line opacity, between 0 and 1. + */ + renderBodyBounds: function (bodies, graphics, lineColor, lineOpacity) + { + graphics.lineStyle(1, lineColor, lineOpacity); + + for (var i = 0; i < bodies.length; i++) + { + var body = bodies[i]; + + // 1) Don't show invisible bodies + if (!body.render.visible) + { + continue; + } + + var bounds = body.bounds; + + if (bounds) + { + graphics.strokeRect( + bounds.min.x, + bounds.min.y, + bounds.max.x - bounds.min.x, + bounds.max.y - bounds.min.y + ); + } + else + { + var parts = body.parts; + + for (var j = parts.length > 1 ? 1 : 0; j < parts.length; j++) + { + var part = parts[j]; + + graphics.strokeRect( + part.bounds.min.x, + part.bounds.min.y, + part.bounds.max.x - part.bounds.min.x, + part.bounds.max.y - part.bounds.min.y + ); + } + } + } + + return this; + }, + + /** + * Renders either all axes, or a single axis indicator, for an array of Bodies, to the given Graphics instance. + * + * The debug renderer calls this method if the `showAxes` or `showAngleIndicator` config values are set. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render bounds to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderBodyAxes + * @since 3.22.0 + * + * @param {array} bodies - An array of bodies from the localWorld. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {boolean} showAxes - If `true` it will render all body axes. If `false` it will render a single axis indicator. + * @param {number} lineColor - The line color. + * @param {number} lineOpacity - The line opacity, between 0 and 1. + */ + renderBodyAxes: function (bodies, graphics, showAxes, lineColor, lineOpacity) + { + graphics.lineStyle(1, lineColor, lineOpacity); + + for (var i = 0; i < bodies.length; i++) + { + var body = bodies[i]; + var parts = body.parts; + + // 1) Don't show invisible bodies + if (!body.render.visible) + { + continue; + } + + var part; + var j; + var k; + + if (showAxes) + { + for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) + { + part = parts[j]; + + for (k = 0; k < part.axes.length; k++) + { + var axis = part.axes[k]; + + graphics.lineBetween( + part.position.x, + part.position.y, + part.position.x + axis.x * 20, + part.position.y + axis.y * 20 + ); + } + } + } + else + { + for (j = parts.length > 1 ? 1 : 0; j < parts.length; j++) + { + part = parts[j]; + + for (k = 0; k < part.axes.length; k++) + { + graphics.lineBetween( + part.position.x, + part.position.y, + (part.vertices[0].x + part.vertices[part.vertices.length - 1].x) / 2, + (part.vertices[0].y + part.vertices[part.vertices.length - 1].y) / 2 + ); + } + } + } + } + + return this; + }, + + /** + * Renders a velocity indicator for an array of Bodies, to the given Graphics instance. + * + * The debug renderer calls this method if the `showVelocity` config value is set. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render bounds to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderBodyVelocity + * @since 3.22.0 + * + * @param {array} bodies - An array of bodies from the localWorld. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} lineColor - The line color. + * @param {number} lineOpacity - The line opacity, between 0 and 1. + * @param {number} lineThickness - The line thickness. + */ + renderBodyVelocity: function (bodies, graphics, lineColor, lineOpacity, lineThickness) + { + graphics.lineStyle(lineThickness, lineColor, lineOpacity); + + for (var i = 0; i < bodies.length; i++) + { + var body = bodies[i]; + + // 1) Don't show invisible bodies + if (!body.render.visible) + { + continue; + } + + graphics.lineBetween( + body.position.x, + body.position.y, + body.position.x + (body.position.x - body.positionPrev.x) * 2, + body.position.y + (body.position.y - body.positionPrev.y) * 2 + ); + } + + return this; + }, + + /** + * Renders the given array of Bodies to the debug graphics instance. + * + * Called automatically by the `postUpdate` method. + * + * @method Phaser.Physics.Matter.World#renderBodies + * @private + * @since 3.14.0 + * + * @param {array} bodies - An array of bodies from the localWorld. + */ + renderBodies: function (bodies) + { + var graphics = this.debugGraphic; + + var config = this.debugConfig; + + var showBody = config.showBody; + var showStaticBody = config.showStaticBody; + var showSleeping = config.showSleeping; + var showInternalEdges = config.showInternalEdges; + var showConvexHulls = config.showConvexHulls; + + var renderFill = config.renderFill; + var renderLine = config.renderLine; + + var staticBodySleepOpacity = config.staticBodySleepOpacity; + var sleepFillColor = config.sleepFillColor; + var sleepLineColor = config.sleepLineColor; + + var hullColor = config.hullColor; + + for (var i = 0; i < bodies.length; i++) + { + var body = bodies[i]; + + // 1) Don't show invisible bodies + if (!body.render.visible) + { + continue; + } + + // 2) Don't show static bodies, OR + // 3) Don't show dynamic bodies + if ((!showStaticBody && body.isStatic) || (!showBody && !body.isStatic)) + { + continue; + } + + var lineColor = body.render.lineColor; + var lineOpacity = body.render.lineOpacity; + var lineThickness = body.render.lineThickness; + var fillColor = body.render.fillColor; + var fillOpacity = body.render.fillOpacity; + + if (showSleeping && body.isSleeping) + { + if (body.isStatic) + { + lineOpacity *= staticBodySleepOpacity; + fillOpacity *= staticBodySleepOpacity; + } + else + { + lineColor = sleepLineColor; + fillColor = sleepFillColor; + } + } + + if (!renderFill) + { + fillColor = null; + } + + if (!renderLine) + { + lineColor = null; + } + + this.renderBody(body, graphics, showInternalEdges, lineColor, lineOpacity, lineThickness, fillColor, fillOpacity); + + var partsLength = body.parts.length; + + if (showConvexHulls && partsLength > 1) + { + this.renderConvexHull(body, graphics, hullColor, lineThickness); + } + } + }, + + /** + * Renders a single Matter Body to the given Phaser Graphics Game Object. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render a Body to your own Graphics instance. + * + * If you don't wish to render a line around the body, set the `lineColor` parameter to `null`. + * Equally, if you don't wish to render a fill, set the `fillColor` parameter to `null`. + * + * @method Phaser.Physics.Matter.World#renderBody + * @since 3.22.0 + * + * @param {MatterJS.BodyType} body - The Matter Body to be rendered. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {boolean} showInternalEdges - Render internal edges of the polygon? + * @param {number} [lineColor] - The line color. + * @param {number} [lineOpacity] - The line opacity, between 0 and 1. + * @param {number} [lineThickness=1] - The line thickness. + * @param {number} [fillColor] - The fill color. + * @param {number} [fillOpacity] - The fill opacity, between 0 and 1. + * + * @return {this} This Matter World instance for method chaining. + */ + renderBody: function (body, graphics, showInternalEdges, lineColor, lineOpacity, lineThickness, fillColor, fillOpacity) + { + if (lineColor === undefined) { lineColor = null; } + if (lineOpacity === undefined) { lineOpacity = null; } + if (lineThickness === undefined) { lineThickness = 1; } + if (fillColor === undefined) { fillColor = null; } + if (fillOpacity === undefined) { fillOpacity = null; } + + var config = this.debugConfig; + + var sensorFillColor = config.sensorFillColor; + var sensorLineColor = config.sensorLineColor; + + // Handle compound parts + var parts = body.parts; + var partsLength = parts.length; + + for (var k = (partsLength > 1) ? 1 : 0; k < partsLength; k++) + { + var part = parts[k]; + var render = part.render; + var opacity = render.opacity; + + if (!render.visible || opacity === 0 || (part.isSensor && !config.showSensors)) + { + continue; + } + + // Part polygon + var circleRadius = part.circleRadius; + + graphics.beginPath(); + + if (part.isSensor) + { + if (fillColor !== null) + { + graphics.fillStyle(sensorFillColor, fillOpacity * opacity); + } + + if (lineColor !== null) + { + graphics.lineStyle(lineThickness, sensorLineColor, lineOpacity * opacity); + } + } + else + { + if (fillColor !== null) + { + graphics.fillStyle(fillColor, fillOpacity * opacity); + } + + if (lineColor !== null) + { + graphics.lineStyle(lineThickness, lineColor, lineOpacity * opacity); + } + } + + if (circleRadius) + { + graphics.arc(part.position.x, part.position.y, circleRadius, 0, 2 * Math.PI); + } + else + { + var vertices = part.vertices; + var vertLength = vertices.length; + + graphics.moveTo(vertices[0].x, vertices[0].y); + + for (var j = 1; j < vertLength; j++) + { + var vert = vertices[j]; + + if (!vertices[j - 1].isInternal || showInternalEdges) + { + graphics.lineTo(vert.x, vert.y); + } + else + { + graphics.moveTo(vert.x, vert.y); + } + + if (j < vertLength && vert.isInternal && !showInternalEdges) + { + var nextIndex = (j + 1) % vertLength; + + graphics.moveTo(vertices[nextIndex].x, vertices[nextIndex].y); + } + } + + graphics.closePath(); + } + + if (fillColor !== null) + { + graphics.fillPath(); + } + + if (lineColor !== null) + { + graphics.strokePath(); + } + } + + if (config.showPositions && !body.isStatic) + { + var px = body.position.x; + var py = body.position.y; + var hs = Math.ceil(config.positionSize / 2); + + graphics.fillStyle(config.positionColor, 1); + graphics.fillRect(px - hs, py - hs, config.positionSize, config.positionSize); + } + + return this; + }, + + /** + * Renders the Convex Hull for a single Matter Body to the given Phaser Graphics Game Object. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render a Body hull to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderConvexHull + * @since 3.22.0 + * + * @param {MatterJS.BodyType} body - The Matter Body to be rendered. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} hullColor - The color used to render the hull. + * @param {number} [lineThickness=1] - The hull line thickness. + * + * @return {this} This Matter World instance for method chaining. + */ + renderConvexHull: function (body, graphics, hullColor, lineThickness) + { + if (lineThickness === undefined) { lineThickness = 1; } + + var parts = body.parts; + var partsLength = parts.length; + + // Render Convex Hulls + if (partsLength > 1) + { + var verts = body.vertices; + + graphics.lineStyle(lineThickness, hullColor); + + graphics.beginPath(); + + graphics.moveTo(verts[0].x, verts[0].y); + + for (var v = 1; v < verts.length; v++) + { + graphics.lineTo(verts[v].x, verts[v].y); + } + + graphics.lineTo(verts[0].x, verts[0].y); + + graphics.strokePath(); + } + + return this; + }, + + /** + * Renders all of the constraints in the world (unless they are specifically set to invisible). + * + * Called automatically by the `postUpdate` method. + * + * @method Phaser.Physics.Matter.World#renderJoints + * @private + * @since 3.14.0 + */ + renderJoints: function () + { + var graphics = this.debugGraphic; + + // Render constraints + var constraints = Composite.allConstraints(this.localWorld); + + for (var i = 0; i < constraints.length; i++) + { + var config = constraints[i].render; + + var lineColor = config.lineColor; + var lineOpacity = config.lineOpacity; + var lineThickness = config.lineThickness; + var pinSize = config.pinSize; + var anchorColor = config.anchorColor; + var anchorSize = config.anchorSize; + + this.renderConstraint(constraints[i], graphics, lineColor, lineOpacity, lineThickness, pinSize, anchorColor, anchorSize); + } + }, + + /** + * Renders a single Matter Constraint, such as a Pin or a Spring, to the given Phaser Graphics Game Object. + * + * This method is used internally by the Matter Debug Renderer, but is also exposed publically should + * you wish to render a Constraint to your own Graphics instance. + * + * @method Phaser.Physics.Matter.World#renderConstraint + * @since 3.22.0 + * + * @param {MatterJS.ConstraintType} constraint - The Matter Constraint to render. + * @param {Phaser.GameObjects.Graphics} graphics - The Graphics object to render to. + * @param {number} lineColor - The line color. + * @param {number} lineOpacity - The line opacity, between 0 and 1. + * @param {number} lineThickness - The line thickness. + * @param {number} pinSize - If this constraint is a pin, this sets the size of the pin circle. + * @param {number} anchorColor - The color used when rendering this constraints anchors. Set to `null` to not render anchors. + * @param {number} anchorSize - The size of the anchor circle, if this constraint has anchors and is rendering them. + * + * @return {this} This Matter World instance for method chaining. + */ + renderConstraint: function (constraint, graphics, lineColor, lineOpacity, lineThickness, pinSize, anchorColor, anchorSize) + { + var render = constraint.render; + + if (!render.visible || !constraint.pointA || !constraint.pointB) + { + return this; + } + + graphics.lineStyle(lineThickness, lineColor, lineOpacity); + + var bodyA = constraint.bodyA; + var bodyB = constraint.bodyB; + var start; + var end; + + if (bodyA) + { + start = Vector.add(bodyA.position, constraint.pointA); + } + else + { + start = constraint.pointA; + } + + if (render.type === 'pin') + { + graphics.strokeCircle(start.x, start.y, pinSize); + } + else + { + if (bodyB) + { + end = Vector.add(bodyB.position, constraint.pointB); + } + else + { + end = constraint.pointB; + } + + graphics.beginPath(); + graphics.moveTo(start.x, start.y); + + if (render.type === 'spring') + { + var delta = Vector.sub(end, start); + var normal = Vector.perp(Vector.normalise(delta)); + var coils = Math.ceil(Common.clamp(constraint.length / 5, 12, 20)); + var offset; + + for (var j = 1; j < coils; j += 1) + { + offset = (j % 2 === 0) ? 1 : -1; + + graphics.lineTo( + start.x + delta.x * (j / coils) + normal.x * offset * 4, + start.y + delta.y * (j / coils) + normal.y * offset * 4 + ); + } + } + + graphics.lineTo(end.x, end.y); + } + + graphics.strokePath(); + + if (render.anchors && anchorSize > 0) + { + graphics.fillStyle(anchorColor); + graphics.fillCircle(start.x, start.y, anchorSize); + graphics.fillCircle(end.x, end.y, anchorSize); + } + + return this; + }, + + /** + * Resets the internal collision IDs that Matter.JS uses for Body collision groups. + * + * You should call this before destroying your game if you need to restart the game + * again on the same page, without first reloading the page. Or, if you wish to + * consistently destroy a Scene that contains Matter.js and then run it again + * later in the same game. + * + * @method Phaser.Physics.Matter.World#resetCollisionIDs + * @since 3.17.0 + */ + resetCollisionIDs: function () + { + Body._nextCollidingGroupId = 1; + Body._nextNonCollidingGroupId = -1; + Body._nextCategory = 0x0001; + + return this; + }, + + /** + * Will remove all Matter physics event listeners and clear the matter physics world, + * engine and any debug graphics, if any. + * + * @method Phaser.Physics.Matter.World#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + MatterEvents.off(this.engine); + + this.removeAllListeners(); + + MatterWorld.clear(this.localWorld, false); + + Engine.clear(this.engine); + + if (this.drawDebug) + { + this.debugGraphic.destroy(); + } + }, + + /** + * Will remove all Matter physics event listeners and clear the matter physics world, + * engine and any debug graphics, if any. + * + * After destroying the world it cannot be re-used again. + * + * @method Phaser.Physics.Matter.World#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + } + +}); + +module.exports = World; + + +/***/ }), + +/***/ 70410: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * A component to set restitution on objects. + * + * @namespace Phaser.Physics.Matter.Components.Bounce + * @since 3.0.0 + */ +var Bounce = { + + /** + * Sets the restitution on the physics object. + * + * @method Phaser.Physics.Matter.Components.Bounce#setBounce + * @since 3.0.0 + * + * @param {number} value - A Number that defines the restitution (elasticity) of the body. The value is always positive and is in the range (0, 1). A value of 0 means collisions may be perfectly inelastic and no bouncing may occur. A value of 0.8 means the body may bounce back with approximately 80% of its kinetic energy. Note that collision response is based on pairs of bodies, and that restitution values are combined with the following formula: `Math.max(bodyA.restitution, bodyB.restitution)` + * + * @return {this} This Game Object instance. + */ + setBounce: function (value) + { + this.body.restitution = value; + + return this; + } + +}; + +module.exports = Bounce; + + +/***/ }), + +/***/ 66968: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Contains methods for changing the collision filter of a Matter Body. Should be used as a mixin and not called directly. + * + * @namespace Phaser.Physics.Matter.Components.Collision + * @since 3.0.0 + */ +var Collision = { + + /** + * Sets the collision category of this Game Object's Matter Body. This number must be a power of two between 2^0 (= 1) and 2^31. + * Two bodies with different collision groups (see {@link #setCollisionGroup}) will only collide if their collision + * categories are included in their collision masks (see {@link #setCollidesWith}). + * + * @method Phaser.Physics.Matter.Components.Collision#setCollisionCategory + * @since 3.0.0 + * + * @param {number} value - Unique category bitfield. + * + * @return {this} This Game Object instance. + */ + setCollisionCategory: function (value) + { + this.body.collisionFilter.category = value; + + return this; + }, + + /** + * Sets the collision group of this Game Object's Matter Body. If this is zero or two Matter Bodies have different values, + * they will collide according to the usual rules (see {@link #setCollisionCategory} and {@link #setCollisionGroup}). + * If two Matter Bodies have the same positive value, they will always collide; if they have the same negative value, + * they will never collide. + * + * @method Phaser.Physics.Matter.Components.Collision#setCollisionGroup + * @since 3.0.0 + * + * @param {number} value - Unique group index. + * + * @return {this} This Game Object instance. + */ + setCollisionGroup: function (value) + { + this.body.collisionFilter.group = value; + + return this; + }, + + /** + * Sets the collision mask for this Game Object's Matter Body. Two Matter Bodies with different collision groups will only + * collide if each one includes the other's category in its mask based on a bitwise AND, i.e. `(categoryA & maskB) !== 0` + * and `(categoryB & maskA) !== 0` are both true. + * + * @method Phaser.Physics.Matter.Components.Collision#setCollidesWith + * @since 3.0.0 + * + * @param {(number|number[])} categories - A unique category bitfield, or an array of them. + * + * @return {this} This Game Object instance. + */ + setCollidesWith: function (categories) + { + var flags = 0; + + if (!Array.isArray(categories)) + { + flags = categories; + } + else + { + for (var i = 0; i < categories.length; i++) + { + flags |= categories[i]; + } + } + + this.body.collisionFilter.mask = flags; + + return this; + }, + + /** + * The callback is sent a `Phaser.Types.Physics.Matter.MatterCollisionData` object. + * + * This does not change the bodies collision category, group or filter. Those must be set in addition + * to the callback. + * + * @method Phaser.Physics.Matter.Components.Collision#setOnCollide + * @since 3.22.0 + * + * @param {function} callback - The callback to invoke when this body starts colliding with another. + * + * @return {this} This Game Object instance. + */ + setOnCollide: function (callback) + { + this.body.onCollideCallback = callback; + + return this; + }, + + /** + * The callback is sent a `Phaser.Types.Physics.Matter.MatterCollisionData` object. + * + * This does not change the bodies collision category, group or filter. Those must be set in addition + * to the callback. + * + * @method Phaser.Physics.Matter.Components.Collision#setOnCollideEnd + * @since 3.22.0 + * + * @param {function} callback - The callback to invoke when this body stops colliding with another. + * + * @return {this} This Game Object instance. + */ + setOnCollideEnd: function (callback) + { + this.body.onCollideEndCallback = callback; + + return this; + }, + + /** + * The callback is sent a `Phaser.Types.Physics.Matter.MatterCollisionData` object. + * + * This does not change the bodies collision category, group or filter. Those must be set in addition + * to the callback. + * + * @method Phaser.Physics.Matter.Components.Collision#setOnCollideActive + * @since 3.22.0 + * + * @param {function} callback - The callback to invoke for the duration of this body colliding with another. + * + * @return {this} This Game Object instance. + */ + setOnCollideActive: function (callback) + { + this.body.onCollideActiveCallback = callback; + + return this; + }, + + /** + * The callback is sent a reference to the other body, along with a `Phaser.Types.Physics.Matter.MatterCollisionData` object. + * + * This does not change the bodies collision category, group or filter. Those must be set in addition + * to the callback. + * + * @method Phaser.Physics.Matter.Components.Collision#setOnCollideWith + * @since 3.22.0 + * + * @param {(MatterJS.Body|MatterJS.Body[])} body - The body, or an array of bodies, to test for collisions with. + * @param {function} callback - The callback to invoke when this body collides with the given body or bodies. + * + * @return {this} This Game Object instance. + */ + setOnCollideWith: function (body, callback) + { + if (!Array.isArray(body)) + { + body = [ body ]; + } + + for (var i = 0; i < body.length; i++) + { + var src = (body[i].hasOwnProperty('body')) ? body[i].body : body[i]; + + this.body.setOnCollideWith(src, callback); + } + + return this; + } + +}; + +module.exports = Collision; + + +/***/ }), + +/***/ 51607: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Body = __webpack_require__(22562); + +/** + * A component to apply force to Matter.js bodies. + * + * @namespace Phaser.Physics.Matter.Components.Force + * @since 3.0.0 + */ +var Force = { + + // force = vec2 / point + + /** + * Applies a force to a body. + * + * @method Phaser.Physics.Matter.Components.Force#applyForce + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2} force - A Vector that specifies the force to apply. + * + * @return {this} This Game Object instance. + */ + applyForce: function (force) + { + this._tempVec2.set(this.body.position.x, this.body.position.y); + + Body.applyForce(this.body, this._tempVec2, force); + + return this; + }, + + /** + * Applies a force to a body from a given position. + * + * @method Phaser.Physics.Matter.Components.Force#applyForceFrom + * @since 3.0.0 + * + * @param {Phaser.Math.Vector2} position - The position in which the force comes from. + * @param {Phaser.Math.Vector2} force - A Vector that specifies the force to apply. + * + * @return {this} This Game Object instance. + */ + applyForceFrom: function (position, force) + { + Body.applyForce(this.body, position, force); + + return this; + }, + + /** + * Apply thrust to the forward position of the body. + * + * Use very small values, such as 0.1, depending on the mass and required speed. + * + * @method Phaser.Physics.Matter.Components.Force#thrust + * @since 3.0.0 + * + * @param {number} speed - A speed value to be applied to a directional force. + * + * @return {this} This Game Object instance. + */ + thrust: function (speed) + { + var angle = this.body.angle; + + this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle)); + + Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2); + + return this; + }, + + /** + * Apply thrust to the left position of the body. + * + * Use very small values, such as 0.1, depending on the mass and required speed. + * + * @method Phaser.Physics.Matter.Components.Force#thrustLeft + * @since 3.0.0 + * + * @param {number} speed - A speed value to be applied to a directional force. + * + * @return {this} This Game Object instance. + */ + thrustLeft: function (speed) + { + var angle = this.body.angle - Math.PI / 2; + + this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle)); + + Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2); + + return this; + }, + + /** + * Apply thrust to the right position of the body. + * + * Use very small values, such as 0.1, depending on the mass and required speed. + * + * @method Phaser.Physics.Matter.Components.Force#thrustRight + * @since 3.0.0 + * + * @param {number} speed - A speed value to be applied to a directional force. + * + * @return {this} This Game Object instance. + */ + thrustRight: function (speed) + { + var angle = this.body.angle + Math.PI / 2; + + this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle)); + + Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2); + + return this; + }, + + /** + * Apply thrust to the back position of the body. + * + * Use very small values, such as 0.1, depending on the mass and required speed. + * + * @method Phaser.Physics.Matter.Components.Force#thrustBack + * @since 3.0.0 + * + * @param {number} speed - A speed value to be applied to a directional force. + * + * @return {this} This Game Object instance. + */ + thrustBack: function (speed) + { + var angle = this.body.angle - Math.PI; + + this._tempVec2.set(speed * Math.cos(angle), speed * Math.sin(angle)); + + Body.applyForce(this.body, { x: this.body.position.x, y: this.body.position.y }, this._tempVec2); + + return this; + } + +}; + +module.exports = Force; + + +/***/ }), + +/***/ 5436: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Contains methods for changing the friction of a Game Object's Matter Body. Should be used a mixin, not called directly. + * + * @namespace Phaser.Physics.Matter.Components.Friction + * @since 3.0.0 + */ +var Friction = { + + /** + * Sets new friction values for this Game Object's Matter Body. + * + * @method Phaser.Physics.Matter.Components.Friction#setFriction + * @since 3.0.0 + * + * @param {number} value - The new friction of the body, between 0 and 1, where 0 allows the Body to slide indefinitely, while 1 allows it to stop almost immediately after a force is applied. + * @param {number} [air] - If provided, the new air resistance of the Body. The higher the value, the faster the Body will slow as it moves through space. 0 means the body has no air resistance. + * @param {number} [fstatic] - If provided, the new static friction of the Body. The higher the value (e.g. 10), the more force it will take to initially get the Body moving when it is nearly stationary. 0 means the body will never "stick" when it is nearly stationary. + * + * @return {this} This Game Object instance. + */ + setFriction: function (value, air, fstatic) + { + this.body.friction = value; + + if (air !== undefined) + { + this.body.frictionAir = air; + } + + if (fstatic !== undefined) + { + this.body.frictionStatic = fstatic; + } + + return this; + }, + + /** + * Sets a new air resistance for this Game Object's Matter Body. + * A value of 0 means the Body will never slow as it moves through space. + * The higher the value, the faster a Body slows when moving through space. + * + * @method Phaser.Physics.Matter.Components.Friction#setFrictionAir + * @since 3.0.0 + * + * @param {number} value - The new air resistance for the Body. + * + * @return {this} This Game Object instance. + */ + setFrictionAir: function (value) + { + this.body.frictionAir = value; + + return this; + }, + + /** + * Sets a new static friction for this Game Object's Matter Body. + * A value of 0 means the Body will never "stick" when it is nearly stationary. + * The higher the value (e.g. 10), the more force it will take to initially get the Body moving when it is nearly stationary. + * + * @method Phaser.Physics.Matter.Components.Friction#setFrictionStatic + * @since 3.0.0 + * + * @param {number} value - The new static friction for the Body. + * + * @return {this} This Game Object instance. + */ + setFrictionStatic: function (value) + { + this.body.frictionStatic = value; + + return this; + } + +}; + +module.exports = Friction; + + +/***/ }), + +/***/ 39858: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * A component to manipulate world gravity for Matter.js bodies. + * + * @namespace Phaser.Physics.Matter.Components.Gravity + * @since 3.0.0 + */ +var Gravity = { + + /** + * A togglable function for ignoring world gravity in real-time on the current body. + * + * @method Phaser.Physics.Matter.Components.Gravity#setIgnoreGravity + * @since 3.0.0 + * + * @param {boolean} value - Set to true to ignore the effect of world gravity, or false to not ignore it. + * + * @return {this} This Game Object instance. + */ + setIgnoreGravity: function (value) + { + this.body.ignoreGravity = value; + + return this; + } + +}; + +module.exports = Gravity; + + +/***/ }), + +/***/ 37302: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Body = __webpack_require__(22562); +var Vector2 = __webpack_require__(26099); + +/** + * Allows accessing the mass, density, and center of mass of a Matter-enabled Game Object. Should be used as a mixin and not directly. + * + * @namespace Phaser.Physics.Matter.Components.Mass + * @since 3.0.0 + */ +var Mass = { + + /** + * Sets the mass of the Game Object's Matter Body. + * + * @method Phaser.Physics.Matter.Components.Mass#setMass + * @since 3.0.0 + * + * @param {number} value - The new mass of the body. + * + * @return {this} This Game Object instance. + */ + setMass: function (value) + { + Body.setMass(this.body, value); + + return this; + }, + + /** + * Sets density of the body. + * + * @method Phaser.Physics.Matter.Components.Mass#setDensity + * @since 3.0.0 + * + * @param {number} value - The new density of the body. + * + * @return {this} This Game Object instance. + */ + setDensity: function (value) + { + Body.setDensity(this.body, value); + + return this; + }, + + /** + * The body's center of mass. + * + * Calling this creates a new `Vector2 each time to avoid mutation. + * + * If you only need to read the value and won't change it, you can get it from `GameObject.body.centerOfMass`. + * + * @name Phaser.Physics.Matter.Components.Mass#centerOfMass + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.10.0 + * + * @return {Phaser.Math.Vector2} The center of mass. + */ + centerOfMass: { + + get: function () + { + return new Vector2(this.body.centerOfMass.x, this.body.centerOfMass.y); + } + } + +}; + +module.exports = Mass; + + +/***/ }), + +/***/ 39132: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Enables a Matter-enabled Game Object to be a sensor. Should be used as a mixin and not directly. + * + * @namespace Phaser.Physics.Matter.Components.Sensor + * @since 3.0.0 + */ +var Sensor = { + + /** + * Set the body belonging to this Game Object to be a sensor. + * Sensors trigger collision events, but don't react with colliding body physically. + * + * @method Phaser.Physics.Matter.Components.Sensor#setSensor + * @since 3.0.0 + * + * @param {boolean} value - `true` to set the body as a sensor, or `false` to disable it. + * + * @return {this} This Game Object instance. + */ + setSensor: function (value) + { + this.body.isSensor = value; + + return this; + }, + + /** + * Is the body belonging to this Game Object a sensor or not? + * + * @method Phaser.Physics.Matter.Components.Sensor#isSensor + * @since 3.0.0 + * + * @return {boolean} `true` if the body is a sensor, otherwise `false`. + */ + isSensor: function () + { + return this.body.isSensor; + } + +}; + +module.exports = Sensor; + + +/***/ }), + +/***/ 57772: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bodies = __webpack_require__(66280); +var Body = __webpack_require__(22562); +var FuzzyEquals = __webpack_require__(43855); +var GetFastValue = __webpack_require__(95540); +var PhysicsEditorParser = __webpack_require__(19496); +var PhysicsJSONParser = __webpack_require__(85791); +var Vertices = __webpack_require__(41598); + +/** + * Enables a Matter-enabled Game Object to set its Body. Should be used as a mixin and not directly. + * + * @namespace Phaser.Physics.Matter.Components.SetBody + * @since 3.0.0 + */ +var SetBody = { + + /** + * Set this Game Objects Matter physics body to be a rectangle shape. + * + * Calling this methods resets all previous properties you may have set on the body, including + * plugins, mass, friction, collision categories, etc. So be sure to re-apply these as needed. + * + * @method Phaser.Physics.Matter.Components.SetBody#setRectangle + * @since 3.0.0 + * + * @param {number} width - Width of the rectangle. + * @param {number} height - Height of the rectangle. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {this} This Game Object instance. + */ + setRectangle: function (width, height, options) + { + return this.setBody({ type: 'rectangle', width: width, height: height }, options); + }, + + /** + * Set this Game Objects Matter physics body to be a circle shape. + * + * Calling this methods resets all previous properties you may have set on the body, including + * plugins, mass, friction, collision categories, etc. So be sure to re-apply these as needed. + * + * @method Phaser.Physics.Matter.Components.SetBody#setCircle + * @since 3.0.0 + * + * @param {number} radius - The radius of the circle. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {this} This Game Object instance. + */ + setCircle: function (radius, options) + { + return this.setBody({ type: 'circle', radius: radius }, options); + }, + + /** + * Set this Game Objects Matter physics body to be a polygon shape. + * + * Calling this methods resets all previous properties you may have set on the body, including + * plugins, mass, friction, collision categories, etc. So be sure to re-apply these as needed. + * + * @method Phaser.Physics.Matter.Components.SetBody#setPolygon + * @since 3.0.0 + * + * @param {number} radius - The "radius" of the polygon, i.e. the distance from its center to any vertex. This is also the radius of its circumcircle. + * @param {number} sides - The number of sides the polygon will have. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {this} This Game Object instance. + */ + setPolygon: function (radius, sides, options) + { + return this.setBody({ type: 'polygon', sides: sides, radius: radius }, options); + }, + + /** + * Set this Game Objects Matter physics body to be a trapezoid shape. + * + * Calling this methods resets all previous properties you may have set on the body, including + * plugins, mass, friction, collision categories, etc. So be sure to re-apply these as needed. + * + * @method Phaser.Physics.Matter.Components.SetBody#setTrapezoid + * @since 3.0.0 + * + * @param {number} width - The width of the trapezoid Body. + * @param {number} height - The height of the trapezoid Body. + * @param {number} slope - The slope of the trapezoid. 0 creates a rectangle, while 1 creates a triangle. Positive values make the top side shorter, while negative values make the bottom side shorter. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {this} This Game Object instance. + */ + setTrapezoid: function (width, height, slope, options) + { + return this.setBody({ type: 'trapezoid', width: width, height: height, slope: slope }, options); + }, + + /** + * Set this Game Object to use the given existing Matter Body. + * + * The body is first removed from the world before being added to this Game Object. + * + * @method Phaser.Physics.Matter.Components.SetBody#setExistingBody + * @since 3.0.0 + * + * @param {MatterJS.BodyType} body - The Body this Game Object should use. + * @param {boolean} [addToWorld=true] - Should the body be immediately added to the World? + * + * @return {this} This Game Object instance. + */ + setExistingBody: function (body, addToWorld) + { + if (addToWorld === undefined) { addToWorld = true; } + + if (this.body) + { + this.world.remove(this.body, true); + } + + this.body = body; + + for (var i = 0; i < body.parts.length; i++) + { + body.parts[i].gameObject = this; + } + + var _this = this; + + body.destroy = function destroy () + { + _this.world.remove(_this.body, true); + _this.body.gameObject = null; + }; + + if (addToWorld) + { + if (this.world.has(body)) + { + // Because it could be part of another Composite + this.world.remove(body, true); + } + + this.world.add(body); + } + + if (this._originComponent) + { + var rx = body.render.sprite.xOffset; + var ry = body.render.sprite.yOffset; + + var comx = body.centerOfMass.x; + var comy = body.centerOfMass.y; + + if (FuzzyEquals(comx, 0.5) && FuzzyEquals(comy, 0.5)) + { + this.setOrigin(rx + 0.5, ry + 0.5); + } + else + { + var cx = body.centerOffset.x; + var cy = body.centerOffset.y; + + this.setOrigin(rx + (cx / this.displayWidth), ry + (cy / this.displayHeight)); + } + } + + return this; + }, + + /** + * Set this Game Object to create and use a new Body based on the configuration object given. + * + * Calling this methods resets all previous properties you may have set on the body, including + * plugins, mass, friction, collision categories, etc. So be sure to re-apply these as needed. + * + * @method Phaser.Physics.Matter.Components.SetBody#setBody + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Physics.Matter.MatterSetBodyConfig)} config - Either a string, such as `circle`, or a Matter Set Body Configuration object. + * @param {Phaser.Types.Physics.Matter.MatterBodyConfig} [options] - An optional Body configuration object that is used to set initial Body properties on creation. + * + * @return {this} This Game Object instance. + */ + setBody: function (config, options) + { + if (!config) + { + return this; + } + + var body; + + // Allow them to do: shape: 'circle' instead of shape: { type: 'circle' } + if (typeof config === 'string') + { + // Using defaults + config = { type: config }; + } + + var shapeType = GetFastValue(config, 'type', 'rectangle'); + var bodyX = GetFastValue(config, 'x', this._tempVec2.x); + var bodyY = GetFastValue(config, 'y', this._tempVec2.y); + var bodyWidth = GetFastValue(config, 'width', this.width); + var bodyHeight = GetFastValue(config, 'height', this.height); + + switch (shapeType) + { + case 'rectangle': + body = Bodies.rectangle(bodyX, bodyY, bodyWidth, bodyHeight, options); + break; + + case 'circle': + var radius = GetFastValue(config, 'radius', Math.max(bodyWidth, bodyHeight) / 2); + var maxSides = GetFastValue(config, 'maxSides', 25); + body = Bodies.circle(bodyX, bodyY, radius, options, maxSides); + break; + + case 'trapezoid': + var slope = GetFastValue(config, 'slope', 0.5); + body = Bodies.trapezoid(bodyX, bodyY, bodyWidth, bodyHeight, slope, options); + break; + + case 'polygon': + var sides = GetFastValue(config, 'sides', 5); + var pRadius = GetFastValue(config, 'radius', Math.max(bodyWidth, bodyHeight) / 2); + body = Bodies.polygon(bodyX, bodyY, sides, pRadius, options); + break; + + case 'fromVertices': + case 'fromVerts': + + var verts = GetFastValue(config, 'verts', null); + + if (verts) + { + // Has the verts array come from Vertices.fromPath, or is it raw? + if (typeof verts === 'string') + { + verts = Vertices.fromPath(verts); + } + + if (this.body && !this.body.hasOwnProperty('temp')) + { + Body.setVertices(this.body, verts); + + body = this.body; + } + else + { + var flagInternal = GetFastValue(config, 'flagInternal', false); + var removeCollinear = GetFastValue(config, 'removeCollinear', 0.01); + var minimumArea = GetFastValue(config, 'minimumArea', 10); + + body = Bodies.fromVertices(bodyX, bodyY, verts, options, flagInternal, removeCollinear, minimumArea); + } + } + + break; + + case 'fromPhysicsEditor': + body = PhysicsEditorParser.parseBody(bodyX, bodyY, config, options); + break; + + case 'fromPhysicsTracer': + body = PhysicsJSONParser.parseBody(bodyX, bodyY, config, options); + break; + } + + if (body) + { + this.setExistingBody(body, config.addToWorld); + } + + return this; + } + +}; + +module.exports = SetBody; + + +/***/ }), + +/***/ 38083: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Events = __webpack_require__(1121); +var Sleeping = __webpack_require__(53614); +var MatterEvents = __webpack_require__(35810); + +/** + * Enables a Matter-enabled Game Object to be able to go to sleep. Should be used as a mixin and not directly. + * + * @namespace Phaser.Physics.Matter.Components.Sleep + * @since 3.0.0 + */ +var Sleep = { + + /** + * Sets this Body to sleep. + * + * @method Phaser.Physics.Matter.Components.Sleep#setToSleep + * @since 3.22.0 + * + * @return {this} This Game Object instance. + */ + setToSleep: function () + { + Sleeping.set(this.body, true); + + return this; + }, + + /** + * Wakes this Body if asleep. + * + * @method Phaser.Physics.Matter.Components.Sleep#setAwake + * @since 3.22.0 + * + * @return {this} This Game Object instance. + */ + setAwake: function () + { + Sleeping.set(this.body, false); + + return this; + }, + + /** + * Sets the number of updates in which this body must have near-zero velocity before it is set as sleeping (if sleeping is enabled by the engine). + * + * @method Phaser.Physics.Matter.Components.Sleep#setSleepThreshold + * @since 3.0.0 + * + * @param {number} [value=60] - A `Number` that defines the number of updates in which this body must have near-zero velocity before it is set as sleeping. + * + * @return {this} This Game Object instance. + */ + setSleepThreshold: function (value) + { + if (value === undefined) { value = 60; } + + this.body.sleepThreshold = value; + + return this; + }, + + /** + * Enable sleep and wake events for this body. + * + * By default when a body goes to sleep, or wakes up, it will not emit any events. + * + * The events are emitted by the Matter World instance and can be listened to via + * the `SLEEP_START` and `SLEEP_END` events. + * + * @method Phaser.Physics.Matter.Components.Sleep#setSleepEvents + * @since 3.0.0 + * + * @param {boolean} start - `true` if you want the sleep start event to be emitted for this body. + * @param {boolean} end - `true` if you want the sleep end event to be emitted for this body. + * + * @return {this} This Game Object instance. + */ + setSleepEvents: function (start, end) + { + this.setSleepStartEvent(start); + this.setSleepEndEvent(end); + + return this; + }, + + /** + * Enables or disables the Sleep Start event for this body. + * + * @method Phaser.Physics.Matter.Components.Sleep#setSleepStartEvent + * @since 3.0.0 + * + * @param {boolean} value - `true` to enable the sleep event, or `false` to disable it. + * + * @return {this} This Game Object instance. + */ + setSleepStartEvent: function (value) + { + if (value) + { + var world = this.world; + + MatterEvents.on(this.body, 'sleepStart', function (event) + { + world.emit(Events.SLEEP_START, event, this); + }); + } + else + { + MatterEvents.off(this.body, 'sleepStart'); + } + + return this; + }, + + /** + * Enables or disables the Sleep End event for this body. + * + * @method Phaser.Physics.Matter.Components.Sleep#setSleepEndEvent + * @since 3.0.0 + * + * @param {boolean} value - `true` to enable the sleep event, or `false` to disable it. + * + * @return {this} This Game Object instance. + */ + setSleepEndEvent: function (value) + { + if (value) + { + var world = this.world; + + MatterEvents.on(this.body, 'sleepEnd', function (event) + { + world.emit(Events.SLEEP_END, event, this); + }); + } + else + { + MatterEvents.off(this.body, 'sleepEnd'); + } + + return this; + } + +}; + +module.exports = Sleep; + + +/***/ }), + +/***/ 90556: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Body = __webpack_require__(22562); + +/** + * Provides methods used for getting and setting the static state of a physics body. + * + * @namespace Phaser.Physics.Matter.Components.Static + * @since 3.0.0 + */ +var Static = { + + /** + * Changes the physics body to be either static `true` or dynamic `false`. + * + * @method Phaser.Physics.Matter.Components.Static#setStatic + * @since 3.0.0 + * + * @param {boolean} value - `true` to set the body as being static, or `false` to make it dynamic. + * + * @return {this} This Game Object instance. + */ + setStatic: function (value) + { + Body.setStatic(this.body, value); + + return this; + }, + + /** + * Returns `true` if the body is static, otherwise `false` for a dynamic body. + * + * @method Phaser.Physics.Matter.Components.Static#isStatic + * @since 3.0.0 + * + * @return {boolean} `true` if the body is static, otherwise `false`. + */ + isStatic: function () + { + return this.body.isStatic; + } + +}; + +module.exports = Static; + + +/***/ }), + +/***/ 85436: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Body = __webpack_require__(22562); +var MATH_CONST = __webpack_require__(36383); +var WrapAngle = __webpack_require__(86554); +var WrapAngleDegrees = __webpack_require__(30954); + +// global bitmask flag for GameObject.renderMask (used by Scale) +var _FLAG = 4; // 0100 + +// Transform Component + +/** + * Provides methods used for getting and setting the position, scale and rotation of a Game Object. + * + * @namespace Phaser.Physics.Matter.Components.Transform + * @since 3.0.0 + */ +var Transform = { + + /** + * The x position of this Game Object. + * + * @name Phaser.Physics.Matter.Components.Transform#x + * @type {number} + * @since 3.0.0 + */ + x: { + + get: function () + { + return this.body.position.x; + }, + + set: function (value) + { + this._tempVec2.set(value, this.y); + + Body.setPosition(this.body, this._tempVec2); + } + + }, + + /** + * The y position of this Game Object. + * + * @name Phaser.Physics.Matter.Components.Transform#y + * @type {number} + * @since 3.0.0 + */ + y: { + + get: function () + { + return this.body.position.y; + }, + + set: function (value) + { + this._tempVec2.set(this.x, value); + + Body.setPosition(this.body, this._tempVec2); + } + + }, + + /** + * This is a special setter that allows you to set both the horizontal and vertical scale of this Game Object + * to the same value, at the same time. When reading this value the result returned is `(scaleX + scaleY) / 2`. + * + * Use of this property implies you wish the horizontal and vertical scales to be equal to each other. If this + * isn't the case, use the `scaleX` or `scaleY` properties instead. + * + * @name Phaser.Physics.Matter.Components.Transform#scale + * @type {number} + * @since 3.88.0 + */ + scale: { + + get: function () + { + return (this._scaleX + this._scaleY) / 2; + }, + + set: function (value) + { + this.setScale(value, value); + } + + }, + + /** + * The horizontal scale of this Game Object. + * + * @name Phaser.Physics.Matter.Components.Transform#scaleX + * @type {number} + * @since 3.0.0 + */ + scaleX: { + + get: function () + { + return this._scaleX; + }, + + set: function (value) + { + var factorX = 1 / this._scaleX; + var factorY = 1 / this._scaleY; + + this._scaleX = value; + + if (this._scaleX === 0) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + + // Reset Matter scale back to 1 (sigh) + Body.scale(this.body, factorX, factorY); + + Body.scale(this.body, value, this._scaleY); + } + + }, + + /** + * The vertical scale of this Game Object. + * + * @name Phaser.Physics.Matter.Components.Transform#scaleY + * @type {number} + * @since 3.0.0 + */ + scaleY: { + + get: function () + { + return this._scaleY; + }, + + set: function (value) + { + var factorX = 1 / this._scaleX; + var factorY = 1 / this._scaleY; + + this._scaleY = value; + + if (this._scaleY === 0) + { + this.renderFlags &= ~_FLAG; + } + else + { + this.renderFlags |= _FLAG; + } + + Body.scale(this.body, factorX, factorY); + + Body.scale(this.body, this._scaleX, value); + } + + }, + + /** + * Use `angle` to set or get rotation of the physics body associated to this GameObject. + * Unlike rotation, when using set the value can be in degrees, which will be converted to radians internally. + * + * @name Phaser.Physics.Matter.Components.Transform#angle + * @type {number} + * @since 3.0.0 + */ + angle: { + + get: function () + { + return WrapAngleDegrees(this.body.angle * MATH_CONST.RAD_TO_DEG); + }, + + set: function (value) + { + // value is in degrees + this.rotation = WrapAngleDegrees(value) * MATH_CONST.DEG_TO_RAD; + } + }, + + /** + * Use `rotation` to set or get the rotation of the physics body associated with this GameObject. + * The value when set must be in radians. + * + * @name Phaser.Physics.Matter.Components.Transform#rotation + * @type {number} + * @since 3.0.0 + */ + rotation: { + + get: function () + { + return this.body.angle; + }, + + set: function (value) + { + // value is in radians + this._rotation = WrapAngle(value); + + Body.setAngle(this.body, this._rotation); + } + }, + + /** + * Sets the position of the physics body along x and y axes. + * Both the parameters to this function are optional and if not passed any they default to 0. + * Velocity, angle, force etc. are unchanged. + * + * @method Phaser.Physics.Matter.Components.Transform#setPosition + * @since 3.0.0 + * + * @param {number} [x=0] - The horizontal position of the body. + * @param {number} [y=x] - The vertical position of the body. + * + * @return {this} This Game Object instance. + */ + setPosition: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = x; } + + this._tempVec2.set(x, y); + + Body.setPosition(this.body, this._tempVec2); + + return this; + }, + + /** + * Immediately sets the angle of the Body. + * Angular velocity, position, force etc. are unchanged. + * + * @method Phaser.Physics.Matter.Components.Transform#setRotation + * @since 3.0.0 + * + * @param {number} [radians=0] - The angle of the body, in radians. + * + * @return {this} This Game Object instance. + */ + setRotation: function (radians) + { + if (radians === undefined) { radians = 0; } + + this._rotation = WrapAngle(radians); + + Body.setAngle(this.body, radians); + + return this; + }, + + /** + * Setting fixed rotation sets the Body inertia to Infinity, which stops it + * from being able to rotate when forces are applied to it. + * + * @method Phaser.Physics.Matter.Components.Transform#setFixedRotation + * @since 3.0.0 + * + * @return {this} This Game Object instance. + */ + setFixedRotation: function () + { + Body.setInertia(this.body, Infinity); + + return this; + }, + + /** + * Immediately sets the angle of the Body. + * Angular velocity, position, force etc. are unchanged. + * + * @method Phaser.Physics.Matter.Components.Transform#setAngle + * @since 3.0.0 + * + * @param {number} [degrees=0] - The angle to set, in degrees. + * + * @return {this} This Game Object instance. + */ + setAngle: function (degrees) + { + if (degrees === undefined) { degrees = 0; } + + this.angle = degrees; + + Body.setAngle(this.body, this.rotation); + + return this; + }, + + /** + * Sets the scale of this Game Object. + * + * @method Phaser.Physics.Matter.Components.Transform#setScale + * @since 3.0.0 + * + * @param {number} [x=1] - The horizontal scale of this Game Object. + * @param {number} [y=x] - The vertical scale of this Game Object. If not set it will use the x value. + * @param {Phaser.Math.Vector2} [point] - The point (Vector2) from which scaling will occur. + * + * @return {this} This Game Object instance. + */ + setScale: function (x, y, point) + { + if (x === undefined) { x = 1; } + if (y === undefined) { y = x; } + + var factorX = 1 / this._scaleX; + var factorY = 1 / this._scaleY; + + this._scaleX = x; + this._scaleY = y; + + Body.scale(this.body, factorX, factorY, point); + + Body.scale(this.body, x, y, point); + + return this; + } + +}; + +module.exports = Transform; + + +/***/ }), + +/***/ 42081: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Body = __webpack_require__(22562); + +/** + * Contains methods for changing the velocity of a Matter Body. Should be used as a mixin and not called directly. + * + * @namespace Phaser.Physics.Matter.Components.Velocity + * @since 3.0.0 + */ +var Velocity = { + + /** + * Sets the horizontal velocity of the physics body. + * + * @method Phaser.Physics.Matter.Components.Velocity#setVelocityX + * @since 3.0.0 + * + * @param {number} x - The horizontal velocity value. + * + * @return {this} This Game Object instance. + */ + setVelocityX: function (x) + { + this._tempVec2.set(x, this.body.velocity.y); + + Body.setVelocity(this.body, this._tempVec2); + + return this; + }, + + /** + * Sets vertical velocity of the physics body. + * + * @method Phaser.Physics.Matter.Components.Velocity#setVelocityY + * @since 3.0.0 + * + * @param {number} y - The vertical velocity value. + * + * @return {this} This Game Object instance. + */ + setVelocityY: function (y) + { + this._tempVec2.set(this.body.velocity.x, y); + + Body.setVelocity(this.body, this._tempVec2); + + return this; + }, + + /** + * Sets both the horizontal and vertical velocity of the physics body. + * + * @method Phaser.Physics.Matter.Components.Velocity#setVelocity + * @since 3.0.0 + * + * @param {number} x - The horizontal velocity value. + * @param {number} [y=x] - The vertical velocity value, it can be either positive or negative. If not given, it will be the same as the `x` value. + * + * @return {this} This Game Object instance. + */ + setVelocity: function (x, y) + { + this._tempVec2.set(x, y); + + Body.setVelocity(this.body, this._tempVec2); + + return this; + }, + + /** + * Gets the current linear velocity of the physics body. + * + * @method Phaser.Physics.Matter.Components.Velocity#getVelocity + * @since 3.60.0 + * + * @return {Phaser.Types.Math.Vector2Like} The current linear velocity of the body. + */ + getVelocity: function () + { + return Body.getVelocity(this.body); + }, + + /** + * Sets the angular velocity of the body instantly. + * Position, angle, force etc. are unchanged. + * + * @method Phaser.Physics.Matter.Components.Velocity#setAngularVelocity + * @since 3.0.0 + * + * @param {number} velocity - The angular velocity. + * + * @return {this} This Game Object instance. + */ + setAngularVelocity: function (velocity) + { + Body.setAngularVelocity(this.body, velocity); + + return this; + }, + + /** + * Gets the current rotational velocity of the body. + * + * @method Phaser.Physics.Matter.Components.Velocity#getAngularVelocity + * @since 3.60.0 + * + * @return {number} The current angular velocity of the body. + */ + getAngularVelocity: function () + { + return Body.getAngularVelocity(this.body); + }, + + /** + * Sets the current rotational speed of the body. + * Direction is maintained. Affects body angular velocity. + * + * @method Phaser.Physics.Matter.Components.Velocity#setAngularSpeed + * @since 3.60.0 + * + * @param {number} speed - The angular speed. + * + * @return {this} This Game Object instance. + */ + setAngularSpeed: function (speed) + { + Body.setAngularSpeed(this.body, speed); + + return this; + }, + + /** + * Gets the current rotational speed of the body. + * Equivalent to the magnitude of its angular velocity. + * + * @method Phaser.Physics.Matter.Components.Velocity#getAngularSpeed + * @since 3.60.0 + * + * @return {number} The current angular velocity of the body. + */ + getAngularSpeed: function () + { + return Body.getAngularSpeed(this.body); + } + +}; + +module.exports = Velocity; + + +/***/ }), + +/***/ 9503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Matter.Components + */ + +module.exports = { + + Bounce: __webpack_require__(70410), + Collision: __webpack_require__(66968), + Force: __webpack_require__(51607), + Friction: __webpack_require__(5436), + Gravity: __webpack_require__(39858), + Mass: __webpack_require__(37302), + Sensor: __webpack_require__(39132), + SetBody: __webpack_require__(57772), + Sleep: __webpack_require__(38083), + Static: __webpack_require__(90556), + Transform: __webpack_require__(85436), + Velocity: __webpack_require__(42081) + +}; + + +/***/ }), + +/***/ 85608: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.AfterAddEvent + * + * @property {any[]} object - An array of the object(s) that have been added. May be a single body, constraint, composite or a mixture of these. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics After Add Event. + * + * This event is dispatched by a Matter Physics World instance at the end of the process when a new Body + * or Constraint has just been added to the world. + * + * Listen to it from a Scene using: `this.matter.world.on('afteradd', listener)`. + * + * @event Phaser.Physics.Matter.Events#AFTER_ADD + * @type {string} + * @since 3.22.0 + * + * @param {Phaser.Physics.Matter.Events.AfterAddEvent} event - The Add Event object. + */ +module.exports = 'afteradd'; + + +/***/ }), + +/***/ 1213: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.AfterRemoveEvent + * + * @property {any[]} object - An array of the object(s) that were removed. May be a single body, constraint, composite or a mixture of these. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics After Remove Event. + * + * This event is dispatched by a Matter Physics World instance at the end of the process when a + * Body or Constraint was removed from the world. + * + * Listen to it from a Scene using: `this.matter.world.on('afterremove', listener)`. + * + * @event Phaser.Physics.Matter.Events#AFTER_REMOVE + * @type {string} + * @since 3.22.0 + * + * @param {Phaser.Physics.Matter.Events.AfterRemoveEvent} event - The Remove Event object. + */ +module.exports = 'afterremove'; + + +/***/ }), + +/***/ 25968: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.AfterUpdateEvent + * + * @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics After Update Event. + * + * This event is dispatched by a Matter Physics World instance after the engine has updated and all collision events have resolved. + * + * Listen to it from a Scene using: `this.matter.world.on('afterupdate', listener)`. + * + * @event Phaser.Physics.Matter.Events#AFTER_UPDATE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.AfterUpdateEvent} event - The Update Event object. + */ +module.exports = 'afterupdate'; + + +/***/ }), + +/***/ 67205: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.BeforeAddEvent + * + * @property {any[]} object - An array of the object(s) to be added. May be a single body, constraint, composite or a mixture of these. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Before Add Event. + * + * This event is dispatched by a Matter Physics World instance at the start of the process when a new Body + * or Constraint is being added to the world. + * + * Listen to it from a Scene using: `this.matter.world.on('beforeadd', listener)`. + * + * @event Phaser.Physics.Matter.Events#BEFORE_ADD + * @type {string} + * @since 3.22.0 + * + * @param {Phaser.Physics.Matter.Events.BeforeAddEvent} event - The Add Event object. + */ +module.exports = 'beforeadd'; + + +/***/ }), + +/***/ 39438: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.BeforeRemoveEvent + * + * @property {any[]} object - An array of the object(s) to be removed. May be a single body, constraint, composite or a mixture of these. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Before Remove Event. + * + * This event is dispatched by a Matter Physics World instance at the start of the process when a + * Body or Constraint is being removed from the world. + * + * Listen to it from a Scene using: `this.matter.world.on('beforeremove', listener)`. + * + * @event Phaser.Physics.Matter.Events#BEFORE_REMOVE + * @type {string} + * @since 3.22.0 + * + * @param {Phaser.Physics.Matter.Events.BeforeRemoveEvent} event - The Remove Event object. + */ +module.exports = 'beforeremove'; + + +/***/ }), + +/***/ 44823: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.BeforeUpdateEvent + * + * @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Before Update Event. + * + * This event is dispatched by a Matter Physics World instance right before all the collision processing takes place. + * + * Listen to it from a Scene using: `this.matter.world.on('beforeupdate', listener)`. + * + * @event Phaser.Physics.Matter.Events#BEFORE_UPDATE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.BeforeUpdateEvent} event - The Update Event object. + */ +module.exports = 'beforeupdate'; + + +/***/ }), + +/***/ 92593: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.CollisionActiveEvent + * + * @property {Phaser.Types.Physics.Matter.MatterCollisionPair[]} pairs - A list of all affected pairs in the collision. + * @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Collision Active Event. + * + * This event is dispatched by a Matter Physics World instance after the engine has updated. + * It provides a list of all pairs that are colliding in the current tick (if any). + * + * Listen to it from a Scene using: `this.matter.world.on('collisionactive', listener)`. + * + * @event Phaser.Physics.Matter.Events#COLLISION_ACTIVE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.CollisionActiveEvent} event - The Collision Event object. + * @param {MatterJS.BodyType} bodyA - The first body of the first colliding pair. The `event.pairs` array may contain more colliding bodies. + * @param {MatterJS.BodyType} bodyB - The second body of the first colliding pair. The `event.pairs` array may contain more colliding bodies. + */ +module.exports = 'collisionactive'; + + +/***/ }), + +/***/ 60128: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.CollisionEndEvent + * + * @property {Phaser.Types.Physics.Matter.MatterCollisionPair[]} pairs - A list of all affected pairs in the collision. + * @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Collision End Event. + * + * This event is dispatched by a Matter Physics World instance after the engine has updated. + * It provides a list of all pairs that have finished colliding in the current tick (if any). + * + * Listen to it from a Scene using: `this.matter.world.on('collisionend', listener)`. + * + * @event Phaser.Physics.Matter.Events#COLLISION_END + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.CollisionEndEvent} event - The Collision Event object. + * @param {MatterJS.BodyType} bodyA - The first body of the first colliding pair. The `event.pairs` array may contain more colliding bodies. + * @param {MatterJS.BodyType} bodyB - The second body of the first colliding pair. The `event.pairs` array may contain more colliding bodies. + */ +module.exports = 'collisionend'; + + +/***/ }), + +/***/ 76861: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.CollisionStartEvent + * + * @property {Phaser.Types.Physics.Matter.MatterCollisionPair[]} pairs - A list of all affected pairs in the collision. + * @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event. + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Collision Start Event. + * + * This event is dispatched by a Matter Physics World instance after the engine has updated. + * It provides a list of all pairs that have started to collide in the current tick (if any). + * + * Listen to it from a Scene using: `this.matter.world.on('collisionstart', listener)`. + * + * @event Phaser.Physics.Matter.Events#COLLISION_START + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.CollisionStartEvent} event - The Collision Event object. + * @param {MatterJS.BodyType} bodyA - The first body of the first colliding pair. The `event.pairs` array may contain more colliding bodies. + * @param {MatterJS.BodyType} bodyB - The second body of the first colliding pair. The `event.pairs` array may contain more colliding bodies. + */ +module.exports = 'collisionstart'; + + +/***/ }), + +/***/ 92362: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Matter Physics Drag End Event. + * + * This event is dispatched by a Matter Physics World instance when a Pointer Constraint + * stops dragging a body. + * + * Listen to it from a Scene using: `this.matter.world.on('dragend', listener)`. + * + * @event Phaser.Physics.Matter.Events#DRAG_END + * @type {string} + * @since 3.16.2 + * + * @param {MatterJS.BodyType} body - The Body that has stopped being dragged. This is a Matter Body, not a Phaser Game Object. + * @param {Phaser.Physics.Matter.PointerConstraint} constraint - The Pointer Constraint that was dragging the body. + */ +module.exports = 'dragend'; + + +/***/ }), + +/***/ 76408: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Matter Physics Drag Event. + * + * This event is dispatched by a Matter Physics World instance when a Pointer Constraint + * is actively dragging a body. It is emitted each time the pointer moves. + * + * Listen to it from a Scene using: `this.matter.world.on('drag', listener)`. + * + * @event Phaser.Physics.Matter.Events#DRAG + * @type {string} + * @since 3.16.2 + * + * @param {MatterJS.BodyType} body - The Body that is being dragged. This is a Matter Body, not a Phaser Game Object. + * @param {Phaser.Physics.Matter.PointerConstraint} constraint - The Pointer Constraint that is dragging the body. + */ +module.exports = 'drag'; + + +/***/ }), + +/***/ 93971: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Matter Physics Drag Start Event. + * + * This event is dispatched by a Matter Physics World instance when a Pointer Constraint + * starts dragging a body. + * + * Listen to it from a Scene using: `this.matter.world.on('dragstart', listener)`. + * + * @event Phaser.Physics.Matter.Events#DRAG_START + * @type {string} + * @since 3.16.2 + * + * @param {MatterJS.BodyType} body - The Body that has started being dragged. This is a Matter Body, not a Phaser Game Object. + * @param {MatterJS.BodyType} part - The part of the body that was clicked on. + * @param {Phaser.Physics.Matter.PointerConstraint} constraint - The Pointer Constraint that is dragging the body. + */ +module.exports = 'dragstart'; + + +/***/ }), + +/***/ 5656: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Matter Physics World Pause Event. + * + * This event is dispatched by an Matter Physics World instance when it is paused. + * + * Listen to it from a Scene using: `this.matter.world.on('pause', listener)`. + * + * @event Phaser.Physics.Matter.Events#PAUSE + * @type {string} + * @since 3.0.0 + */ +module.exports = 'pause'; + + +/***/ }), + +/***/ 47861: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Matter Physics World Resume Event. + * + * This event is dispatched by an Matter Physics World instance when it resumes from a paused state. + * + * Listen to it from a Scene using: `this.matter.world.on('resume', listener)`. + * + * @event Phaser.Physics.Matter.Events#RESUME + * @type {string} + * @since 3.0.0 + */ +module.exports = 'resume'; + + +/***/ }), + +/***/ 79099: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.SleepEndEvent + * + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Sleep End Event. + * + * This event is dispatched by a Matter Physics World instance when a Body stop sleeping. + * + * Listen to it from a Scene using: `this.matter.world.on('sleepend', listener)`. + * + * @event Phaser.Physics.Matter.Events#SLEEP_END + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.SleepEndEvent} event - The Sleep Event object. + * @param {MatterJS.BodyType} body - The body that has stopped sleeping. + */ +module.exports = 'sleepend'; + + +/***/ }), + +/***/ 35906: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Physics.Matter.Events.SleepStartEvent + * + * @property {any} source - The source object of the event. + * @property {string} name - The name of the event. + */ + +/** + * The Matter Physics Sleep Start Event. + * + * This event is dispatched by a Matter Physics World instance when a Body goes to sleep. + * + * Listen to it from a Scene using: `this.matter.world.on('sleepstart', listener)`. + * + * @event Phaser.Physics.Matter.Events#SLEEP_START + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Physics.Matter.Events.SleepStartEvent} event - The Sleep Event object. + * @param {MatterJS.BodyType} body - The body that has gone to sleep. + */ +module.exports = 'sleepstart'; + + +/***/ }), + +/***/ 1121: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Matter.Events + */ + +module.exports = { + + AFTER_ADD: __webpack_require__(85608), + AFTER_REMOVE: __webpack_require__(1213), + AFTER_UPDATE: __webpack_require__(25968), + BEFORE_ADD: __webpack_require__(67205), + BEFORE_REMOVE: __webpack_require__(39438), + BEFORE_UPDATE: __webpack_require__(44823), + COLLISION_ACTIVE: __webpack_require__(92593), + COLLISION_END: __webpack_require__(60128), + COLLISION_START: __webpack_require__(76861), + DRAG_END: __webpack_require__(92362), + DRAG: __webpack_require__(76408), + DRAG_START: __webpack_require__(93971), + PAUSE: __webpack_require__(5656), + RESUME: __webpack_require__(47861), + SLEEP_END: __webpack_require__(79099), + SLEEP_START: __webpack_require__(35906) + +}; + + +/***/ }), + +/***/ 3875: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Physics.Matter + */ + +module.exports = { + + BodyBounds: __webpack_require__(68174), + Components: __webpack_require__(9503), + Events: __webpack_require__(1121), + Factory: __webpack_require__(28137), + MatterGameObject: __webpack_require__(75803), + Image: __webpack_require__(23181), + Matter: __webpack_require__(19933), + MatterPhysics: __webpack_require__(42045), + PolyDecomp: __webpack_require__(55973), + Sprite: __webpack_require__(34803), + TileBody: __webpack_require__(73834), + PhysicsEditorParser: __webpack_require__(19496), + PhysicsJSONParser: __webpack_require__(85791), + PointerConstraint: __webpack_require__(98713), + World: __webpack_require__(68243) + +}; + + +/***/ }), + +/***/ 22562: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * The `Matter.Body` module contains methods for creating and manipulating body models. + * A `Matter.Body` is a rigid body that can be simulated by a `Matter.Engine`. + * Factories for commonly used body configurations (such as rectangles, circles and other polygons) can be found in the module `Matter.Bodies`. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * @class Body + */ + +var Body = {}; + +module.exports = Body; + +var Vertices = __webpack_require__(41598); +var Vector = __webpack_require__(31725); +var Sleeping = __webpack_require__(53614); +var Common = __webpack_require__(53402); +var Bounds = __webpack_require__(15647); +var Axes = __webpack_require__(66615); + +(function() { + + Body._timeCorrection = true; + Body._inertiaScale = 4; + Body._nextCollidingGroupId = 1; + Body._nextNonCollidingGroupId = -1; + Body._nextCategory = 0x0001; + Body._baseDelta = 1000 / 60; + + /** + * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * Vertices must be specified in clockwise order. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {} options + * @return {body} body + */ + Body.create = function(options) { + var defaults = { + id: Common.nextId(), + type: 'body', + label: 'Body', + parts: [], + plugin: {}, + attractors: options.attractors || [], + wrapBounds: null, + angle: 0, + vertices: null, // Phaser change: no point calling fromPath if they pass in vertices anyway + position: { x: 0, y: 0 }, + force: { x: 0, y: 0 }, + torque: 0, + positionImpulse: { x: 0, y: 0 }, + constraintImpulse: { x: 0, y: 0, angle: 0 }, + totalContacts: 0, + speed: 0, + angularSpeed: 0, + velocity: { x: 0, y: 0 }, + angularVelocity: 0, + isSensor: false, + isStatic: false, + isSleeping: false, + motion: 0, + sleepThreshold: 60, + density: 0.001, + restitution: 0, + friction: 0.1, + frictionStatic: 0.5, + frictionAir: 0.01, + collisionFilter: { + category: 0x0001, + mask: 0xFFFFFFFF, + group: 0 + }, + slop: 0.05, + timeScale: 1, + events: null, + bounds: null, + chamfer: null, + circleRadius: 0, + positionPrev: null, + anglePrev: 0, + parent: null, + axes: null, + area: 0, + mass: 0, + inverseMass: 0, + inertia: 0, + deltaTime: 1000 / 60, + inverseInertia: 0, + _original: null, + render: { + visible: true, + opacity: 1, + sprite: { + xOffset: 0, + yOffset: 0 + }, + fillColor: null, // custom Phaser property + fillOpacity: null, // custom Phaser property + lineColor: null, // custom Phaser property + lineOpacity: null, // custom Phaser property + lineThickness: null // custom Phaser property + }, + gameObject: null, // custom Phaser property + scale: { x: 1, y: 1 }, // custom Phaser property + centerOfMass: { x: 0, y: 0 }, // custom Phaser property (float, 0 - 1) + centerOffset: { x: 0, y: 0 }, // custom Phaser property (pixel values) + gravityScale: { x: 1, y: 1 }, // custom Phaser property + ignoreGravity: false, // custom Phaser property + ignorePointer: false, // custom Phaser property + onCollideCallback: null, // custom Phaser property + onCollideEndCallback: null, // custom Phaser property + onCollideActiveCallback: null, // custom Phaser property + onCollideWith: {} // custom Phaser property + }; + + if (!options.hasOwnProperty('position') && options.hasOwnProperty('vertices')) + { + options.position = Vertices.centre(options.vertices); + } + else if (!options.hasOwnProperty('vertices')) + { + defaults.vertices = Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'); + } + + var body = Common.extend(defaults, options); + + _initProperties(body, options); + + // Helper function + body.setOnCollideWith = function (body, callback) + { + if (callback) + { + this.onCollideWith[body.id] = callback; + } + else + { + delete this.onCollideWith[body.id]; + } + + return this; + } + + return body; + }; + + /** + * Returns the next unique group index for which bodies will collide. + * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide. + * See `body.collisionFilter` for more information. + * @method nextGroup + * @param {bool} [isNonColliding=false] + * @return {Number} Unique group index + */ + Body.nextGroup = function(isNonColliding) { + if (isNonColliding) + return Body._nextNonCollidingGroupId--; + + return Body._nextCollidingGroupId++; + }; + + /** + * Returns the next unique category bitfield (starting after the initial default category `0x0001`). + * There are 32 available. See `body.collisionFilter` for more information. + * @method nextCategory + * @return {Number} Unique category bitfield + */ + Body.nextCategory = function() { + Body._nextCategory = Body._nextCategory << 1; + return Body._nextCategory; + }; + + /** + * Initialises body properties. + * @method _initProperties + * @private + * @param {body} body + * @param {} [options] + */ + var _initProperties = function(body, options) { + options = options || {}; + + // init required properties (order is important) + Body.set(body, { + bounds: body.bounds || Bounds.create(body.vertices), + positionPrev: body.positionPrev || Vector.clone(body.position), + anglePrev: body.anglePrev || body.angle, + vertices: body.vertices, + parts: body.parts || [body], + isStatic: body.isStatic, + isSleeping: body.isSleeping, + parent: body.parent || body + }); + + Vertices.rotate(body.vertices, body.angle, body.position); + Axes.rotate(body.axes, body.angle); + Bounds.update(body.bounds, body.vertices, body.velocity); + + // allow options to override the automatically calculated properties + Body.set(body, { + axes: options.axes || body.axes, + area: options.area || body.area, + mass: options.mass || body.mass, + inertia: options.inertia || body.inertia + }); + + if (body.parts.length === 1) + { + var bounds = body.bounds; + + var centerOfMass = body.centerOfMass; + var centerOffset = body.centerOffset; + + var bodyWidth = bounds.max.x - bounds.min.x; + var bodyHeight = bounds.max.y - bounds.min.y; + + centerOfMass.x = -(bounds.min.x - body.position.x) / bodyWidth; + centerOfMass.y = -(bounds.min.y - body.position.y) / bodyHeight; + + centerOffset.x = bodyWidth * centerOfMass.x; + centerOffset.y = bodyHeight * centerOfMass.y; + } + + // From Matter render code: + // body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x); + // body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y); + }; + + /** + * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist. + * Prefer to use the actual setter functions in performance critical situations. + * @method set + * @param {body} body + * @param {} settings A property name (or map of properties and values) to set on the body. + * @param {} value The value to set if `settings` is a single property name. + */ + Body.set = function(body, settings, value) { + var property; + + if (typeof settings === 'string') { + property = settings; + settings = {}; + settings[property] = value; + } + + for (property in settings) { + if (!Object.prototype.hasOwnProperty.call(settings, property)) + continue; + + value = settings[property]; + switch (property) { + + case 'isStatic': + Body.setStatic(body, value); + break; + case 'isSleeping': + Sleeping.set(body, value); + break; + case 'mass': + Body.setMass(body, value); + break; + case 'density': + Body.setDensity(body, value); + break; + case 'inertia': + Body.setInertia(body, value); + break; + case 'vertices': + Body.setVertices(body, value); + break; + case 'position': + Body.setPosition(body, value); + break; + case 'angle': + Body.setAngle(body, value); + break; + case 'velocity': + Body.setVelocity(body, value); + break; + case 'angularVelocity': + Body.setAngularVelocity(body, value); + break; + case 'speed': + Body.setSpeed(body, value); + break; + case 'angularSpeed': + Body.setAngularSpeed(body, value); + break; + case 'parts': + Body.setParts(body, value); + break; + case 'centre': + Body.setCentre(body, value); + break; + default: + body[property] = value; + } + } + }; + + /** + * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity. + * @method setStatic + * @param {body} body + * @param {bool} isStatic + */ + Body.setStatic = function(body, isStatic) { + for (var i = 0; i < body.parts.length; i++) { + var part = body.parts[i]; + + if (isStatic) { + if (!part.isStatic) { + part._original = { + restitution: part.restitution, + friction: part.friction, + mass: part.mass, + inertia: part.inertia, + density: part.density, + inverseMass: part.inverseMass, + inverseInertia: part.inverseInertia + }; + } + + part.restitution = 0; + part.friction = 1; + part.mass = part.inertia = part.density = Infinity; + part.inverseMass = part.inverseInertia = 0; + + part.positionPrev.x = part.position.x; + part.positionPrev.y = part.position.y; + part.anglePrev = part.angle; + part.angularVelocity = 0; + part.speed = 0; + part.angularSpeed = 0; + part.motion = 0; + } else if (part._original) { + part.restitution = part._original.restitution; + part.friction = part._original.friction; + part.mass = part._original.mass; + part.inertia = part._original.inertia; + part.density = part._original.density; + part.inverseMass = part._original.inverseMass; + part.inverseInertia = part._original.inverseInertia; + + part._original = null; + } + part.isStatic = isStatic; + } + }; + + /** + * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change. + * @method setMass + * @param {body} body + * @param {number} mass + */ + Body.setMass = function(body, mass) { + var moment = body.inertia / (body.mass / 6); + body.inertia = moment * (mass / 6); + body.inverseInertia = 1 / body.inertia; + + body.mass = mass; + body.inverseMass = 1 / body.mass; + body.density = body.mass / body.area; + }; + + /** + * Sets the density of the body. Mass and inertia are automatically updated to reflect the change. + * @method setDensity + * @param {body} body + * @param {number} density + */ + Body.setDensity = function(body, density) { + Body.setMass(body, density * body.area); + body.density = density; + }; + + /** + * Sets the moment of inertia (i.e. second moment of area) of the body. + * Inverse inertia is automatically updated to reflect the change. Mass is not changed. + * @method setInertia + * @param {body} body + * @param {number} inertia + */ + Body.setInertia = function(body, inertia) { + body.inertia = inertia; + body.inverseInertia = 1 / body.inertia; + }; + + /** + * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`). + * Vertices will be automatically transformed to be orientated around their centre of mass as the origin. + * They are then automatically translated to world space based on `body.position`. + * + * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array). + * Vertices must form a convex hull, concave hulls are not supported. + * + * @method setVertices + * @param {body} body + * @param {vector[]} vertices + */ + Body.setVertices = function(body, vertices) { + // change vertices + if (vertices[0].body === body) { + body.vertices = vertices; + } else { + body.vertices = Vertices.create(vertices, body); + } + + // update properties + body.axes = Axes.fromVertices(body.vertices); + body.area = Vertices.area(body.vertices); + Body.setMass(body, body.density * body.area); + + // orient vertices around the centre of mass at origin (0, 0) + var centre = Vertices.centre(body.vertices); + Vertices.translate(body.vertices, centre, -1); + + // update inertia while vertices are at origin (0, 0) + Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass)); + + // update geometry + Vertices.translate(body.vertices, body.position); + + Bounds.update(body.bounds, body.vertices, body.velocity); + }; + + /** + * Sets the parts of the `body` and updates mass, inertia and centroid. + * Each part will have its parent set to `body`. + * By default the convex hull will be automatically computed and set on `body`, unless `autoHull` is set to `false.` + * Note that this method will ensure that the first part in `body.parts` will always be the `body`. + * @method setParts + * @param {body} body + * @param [body] parts + * @param {bool} [autoHull=true] + */ + Body.setParts = function(body, parts, autoHull) { + var i; + + // add all the parts, ensuring that the first part is always the parent body + parts = parts.slice(0); + body.parts.length = 0; + body.parts.push(body); + body.parent = body; + + for (i = 0; i < parts.length; i++) { + var part = parts[i]; + if (part !== body) { + part.parent = body; + body.parts.push(part); + } + } + + if (body.parts.length === 1) + return; + + autoHull = typeof autoHull !== 'undefined' ? autoHull : true; + + // find the convex hull of all parts to set on the parent body + if (autoHull) { + var vertices = []; + for (i = 0; i < parts.length; i++) { + vertices = vertices.concat(parts[i].vertices); + } + + Vertices.clockwiseSort(vertices); + + var hull = Vertices.hull(vertices), + hullCentre = Vertices.centre(hull); + + Body.setVertices(body, hull); + Vertices.translate(body.vertices, hullCentre); + } + + // sum the properties of all compound parts of the parent body + var total = Body._totalProperties(body); + + // Phaser addition + var cx = total.centre.x; + var cy = total.centre.y; + + var bounds = body.bounds; + var centerOfMass = body.centerOfMass; + var centerOffset = body.centerOffset; + + Bounds.update(bounds, body.vertices, body.velocity); + + centerOfMass.x = -(bounds.min.x - cx) / (bounds.max.x - bounds.min.x); + centerOfMass.y = -(bounds.min.y - cy) / (bounds.max.y - bounds.min.y); + + centerOffset.x = cx; + centerOffset.y = cy; + + body.area = total.area; + body.parent = body; + body.position.x = cx; + body.position.y = cy; + body.positionPrev.x = cx; + body.positionPrev.y = cy; + + // Matter.js original + // body.position.x = total.centre.x; + // body.position.y = total.centre.y; + // body.positionPrev.x = total.centre.x; + // body.positionPrev.y = total.centre.y; + + Body.setMass(body, total.mass); + Body.setInertia(body, total.inertia); + Body.setPosition(body, total.centre); + }; + + /** + * Set the centre of mass of the body. + * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation. + * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density. + * This is equal to moving `body.position` but not the `body.vertices`. + * Invalid if the `centre` falls outside the body's convex hull. + * @method setCentre + * @param {body} body + * @param {vector} centre + * @param {bool} relative + */ + Body.setCentre = function(body, centre, relative) { + if (!relative) { + body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x); + body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y); + body.position.x = centre.x; + body.position.y = centre.y; + } else { + body.positionPrev.x += centre.x; + body.positionPrev.y += centre.y; + body.position.x += centre.x; + body.position.y += centre.y; + } + }; + + /** + * Sets the position of the body instantly. Velocity, angle, force etc. are unchanged. + * @method setPosition + * @param {body} body + * @param {vector} position + * @param {boolean} [updateVelocity=false] + */ + Body.setPosition = function(body, position, updateVelocity) { + var delta = Vector.sub(position, body.position); + if (updateVelocity) { + body.positionPrev.x = body.position.x; + body.positionPrev.y = body.position.y; + body.velocity.x = delta.x; + body.velocity.y = delta.y; + body.speed = Vector.magnitude(delta); + } else { + body.positionPrev.x += delta.x; + body.positionPrev.y += delta.y; + } + + for (var i = 0; i < body.parts.length; i++) { + var part = body.parts[i]; + part.position.x += delta.x; + part.position.y += delta.y; + Vertices.translate(part.vertices, delta); + Bounds.update(part.bounds, part.vertices, body.velocity); + } + }; + + /** + * Sets the angle of the body instantly. Angular velocity, position, force etc. are unchanged. + * @method setAngle + * @param {body} body + * @param {number} angle + * @param {boolean} [updateVelocity=false] + */ + Body.setAngle = function(body, angle, updateVelocity) { + var delta = angle - body.angle; + if (updateVelocity) { + body.anglePrev = body.angle; + body.angularVelocity = delta; + body.angularSpeed = Math.abs(delta); + } else { + body.anglePrev += delta; + } + + for (var i = 0; i < body.parts.length; i++) { + var part = body.parts[i]; + part.angle += delta; + Vertices.rotate(part.vertices, delta, body.position); + Axes.rotate(part.axes, delta); + Bounds.update(part.bounds, part.vertices, body.velocity); + if (i > 0) { + Vector.rotateAbout(part.position, delta, body.position, part.position); + } + } + }; + + /** + * Sets the linear velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`. + * @method setVelocity + * @param {body} body + * @param {vector} velocity + */ + Body.setVelocity = function(body, velocity) { + var timeScale = body.deltaTime / Body._baseDelta; + body.positionPrev.x = body.position.x - velocity.x * timeScale; + body.positionPrev.y = body.position.y - velocity.y * timeScale; + body.velocity.x = (body.position.x - body.positionPrev.x) / timeScale; + body.velocity.y = (body.position.y - body.positionPrev.y) / timeScale; + body.speed = Vector.magnitude(body.velocity); + }; + + /** + * Gets the current linear velocity of the body. + * @method getVelocity + * @param {body} body + * @return {vector} velocity + */ + Body.getVelocity = function(body) { + var timeScale = Body._baseDelta / body.deltaTime; + + return { + x: (body.position.x - body.positionPrev.x) * timeScale, + y: (body.position.y - body.positionPrev.y) * timeScale + }; + }; + + /** + * Gets the current linear speed of the body. + * Equivalent to the magnitude of its velocity. + * @method getSpeed + * @param {body} body + * @return {number} speed + */ + Body.getSpeed = function(body) { + return Vector.magnitude(Body.getVelocity(body)); + }; + + /** + * Sets the current linear speed of the body. + * Direction is maintained. Affects body velocity. + * @method setSpeed + * @param {body} body + * @param {number} speed + */ + Body.setSpeed = function(body, speed) { + Body.setVelocity(body, Vector.mult(Vector.normalise(Body.getVelocity(body)), speed)); + }; + + /** + * Sets the angular velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`. + * @method setAngularVelocity + * @param {body} body + * @param {number} velocity + */ + Body.setAngularVelocity = function(body, velocity) { + var timeScale = body.deltaTime / Body._baseDelta; + body.anglePrev = body.angle - velocity * timeScale; + body.angularVelocity = (body.angle - body.anglePrev) / timeScale; + body.angularSpeed = Math.abs(body.angularVelocity); + }; + + /** + * Gets the current rotational velocity of the body. + * @method getAngularVelocity + * @param {body} body + * @return {number} angular velocity + */ + Body.getAngularVelocity = function(body) { + return (body.angle - body.anglePrev) * Body._baseDelta / body.deltaTime; + }; + + /** + * Gets the current rotational speed of the body. + * Equivalent to the magnitude of its angular velocity. + * @method getAngularSpeed + * @param {body} body + * @return {number} angular speed + */ + Body.getAngularSpeed = function(body) { + return Math.abs(Body.getAngularVelocity(body)); + }; + + /** + * Sets the current rotational speed of the body. + * Direction is maintained. Affects body angular velocity. + * @method setAngularSpeed + * @param {body} body + * @param {number} speed + */ + Body.setAngularSpeed = function(body, speed) { + Body.setAngularVelocity(body, Common.sign(Body.getAngularVelocity(body)) * speed); + }; + + /** + * Moves a body by a given vector relative to its current position, without imparting any velocity. + * @method translate + * @param {body} body + * @param {vector} translation + * @param {boolean} [updateVelocity=false] + */ + Body.translate = function(body, translation, updateVelocity) { + Body.setPosition(body, Vector.add(body.position, translation), updateVelocity); + }; + + /** + * Rotates a body by a given angle relative to its current angle, without imparting any angular velocity. + * @method rotate + * @param {body} body + * @param {number} rotation + * @param {vector} [point] + * @param {boolean} [updateVelocity=false] + */ + Body.rotate = function(body, rotation, point, updateVelocity) { + if (!point) { + Body.setAngle(body, body.angle + rotation, updateVelocity); + } else { + var cos = Math.cos(rotation), + sin = Math.sin(rotation), + dx = body.position.x - point.x, + dy = body.position.y - point.y; + + Body.setPosition(body, { + x: point.x + (dx * cos - dy * sin), + y: point.y + (dx * sin + dy * cos) + }, updateVelocity); + + Body.setAngle(body, body.angle + rotation, updateVelocity); + } + }; + + /** + * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre). + * @method scale + * @param {body} body + * @param {number} scaleX + * @param {number} scaleY + * @param {vector} [point] + */ + Body.scale = function(body, scaleX, scaleY, point) { + var totalArea = 0, + totalInertia = 0; + + point = point || body.position; + + var wasFixedRotation = (body.inertia === Infinity) ? true : false; + + for (var i = 0; i < body.parts.length; i++) { + var part = body.parts[i]; + + part.scale.x = scaleX; + part.scale.y = scaleY; + + // scale vertices + Vertices.scale(part.vertices, scaleX, scaleY, point); + + // update properties + part.axes = Axes.fromVertices(part.vertices); + part.area = Vertices.area(part.vertices); + Body.setMass(part, body.density * part.area); + + // update inertia (requires vertices to be at origin) + Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y }); + Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass)); + Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y }); + + if (i > 0) { + totalArea += part.area; + totalInertia += part.inertia; + } + + // scale position + part.position.x = point.x + (part.position.x - point.x) * scaleX; + part.position.y = point.y + (part.position.y - point.y) * scaleY; + + // update bounds + Bounds.update(part.bounds, part.vertices, body.velocity); + } + + // handle parent body + if (body.parts.length > 1) { + body.area = totalArea; + + if (!body.isStatic) { + Body.setMass(body, body.density * totalArea); + Body.setInertia(body, totalInertia); + } + } + + // handle circles + if (body.circleRadius) { + if (scaleX === scaleY) { + body.circleRadius *= scaleX; + } else { + // body is no longer a circle + body.circleRadius = null; + } + } + + if (wasFixedRotation) + { + Body.setInertia(body, Infinity); + } + }; + + /** + * Performs a simulation step for the given `body`, including updating position and angle using Verlet integration. + * @method update + * @param {body} body + * @param {number} deltaTime + */ + Body.update = function(body, deltaTime) { + deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : (1000 / 60)) * body.timeScale; + var deltaTimeSquared = deltaTime * deltaTime, + correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1; + + // from the previous step + var frictionAir = 1 - body.frictionAir * (deltaTime / Common._baseDelta), + velocityPrevX = (body.position.x - body.positionPrev.x) * correction, + velocityPrevY = (body.position.y - body.positionPrev.y) * correction; + + // update velocity with Verlet integration + body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared; + body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared; + + body.positionPrev.x = body.position.x; + body.positionPrev.y = body.position.y; + body.position.x += body.velocity.x; + body.position.y += body.velocity.y; + body.deltaTime = deltaTime; + + // update angular velocity with Verlet integration + body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared; + body.anglePrev = body.angle; + body.angle += body.angularVelocity; + + // track speed and acceleration + body.speed = Vector.magnitude(body.velocity); + body.angularSpeed = Math.abs(body.angularVelocity); + + // transform the body geometry + for (var i = 0; i < body.parts.length; i++) { + var part = body.parts[i]; + + Vertices.translate(part.vertices, body.velocity); + + if (i > 0) { + part.position.x += body.velocity.x; + part.position.y += body.velocity.y; + } + + if (body.angularVelocity !== 0) { + Vertices.rotate(part.vertices, body.angularVelocity, body.position); + Axes.rotate(part.axes, body.angularVelocity); + if (i > 0) { + Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position); + } + } + + Bounds.update(part.bounds, part.vertices, body.velocity); + } + }; + + /** + * Updates properties `body.velocity`, `body.speed`, `body.angularVelocity` and `body.angularSpeed` which are normalised in relation to `Body._baseDelta`. + * @method updateVelocities + * @param {body} body + */ + Body.updateVelocities = function(body) { + var timeScale = Body._baseDelta / body.deltaTime, + bodyVelocity = body.velocity; + + bodyVelocity.x = (body.position.x - body.positionPrev.x) * timeScale; + bodyVelocity.y = (body.position.y - body.positionPrev.y) * timeScale; + body.speed = Math.sqrt((bodyVelocity.x * bodyVelocity.x) + (bodyVelocity.y * bodyVelocity.y)); + + body.angularVelocity = (body.angle - body.anglePrev) * timeScale; + body.angularSpeed = Math.abs(body.angularVelocity); + }; + + /** + * Applies a force to a body from a given world-space position, including resulting torque. + * @method applyForce + * @param {body} body + * @param {vector} position + * @param {vector} force + */ + Body.applyForce = function(body, position, force) { + var offset = { x: position.x - body.position.x, y: position.y - body.position.y }; + body.force.x += force.x; + body.force.y += force.y; + body.torque += offset.x * force.y - offset.y * force.x; + }; + + /** + * Returns the sums of the properties of all compound parts of the parent body. + * @method _totalProperties + * @private + * @param {body} body + * @return {} + */ + Body._totalProperties = function(body) { + // from equations at: + // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory + // http://output.to/sideway/default.asp?qno=121100087 + + var properties = { + mass: 0, + area: 0, + inertia: 0, + centre: { x: 0, y: 0 } + }; + + // sum the properties of all compound parts of the parent body + for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) { + var part = body.parts[i], + mass = part.mass !== Infinity ? part.mass : 1; + + properties.mass += mass; + properties.area += part.area; + properties.inertia += part.inertia; + properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass)); + } + + properties.centre = Vector.div(properties.centre, properties.mass); + + return properties; + }; + + /** + * Wraps the `body` position such that it always stays within the given bounds. + * Upon crossing a boundary the body will appear on the opposite side of the bounds, + * while maintaining its velocity. + * @function wrap + * @param {body} body The body to wrap. + * @param {Matter.Bounds} bounds The bounds to wrap the body inside. + * @returns {?Matter.Vector} The translation vector that was applied (only if wrapping was required). + */ + Body.wrap = function(body, bounds) { + var translation = Bounds.wrap(body.bounds, bounds); + + if (translation) { + Body.translate(body, translation); + } + + return translation; + }; + + /* + * + * Events Documentation + * + */ + + /** + * Fired when a body starts sleeping (where `this` is the body). + * + * @event sleepStart + * @this {body} The body that has started sleeping + * @param {} event An event object + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired when a body ends sleeping (where `this` is the body). + * + * @event sleepEnd + * @this {body} The body that has ended sleeping + * @param {} event An event object + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /* + * + * Properties Documentation + * + */ + + /** + * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`. + * + * @property id + * @type number + */ + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "body" + * @readOnly + */ + + /** + * An arbitrary `String` name to help the user identify and manage bodies. + * + * @property label + * @type string + * @default "Body" + */ + + /** + * An array of bodies that make up this body. + * The first body in the array must always be a self reference to the current body instance. + * All bodies in the `parts` array together form a single rigid compound body. + * Parts are allowed to overlap, have gaps or holes or even form concave bodies. + * Parts themselves should never be added to a `World`, only the parent body should be. + * Use `Body.setParts` when setting parts to ensure correct updates of all properties. + * + * @property parts + * @type body[] + */ + + /** + * An object reserved for storing plugin-specific properties. + * + * @property plugin + * @type {} + */ + + /** + * A self reference if the body is _not_ a part of another body. + * Otherwise this is a reference to the body that this is a part of. + * See `body.parts`. + * + * @property parent + * @type body + */ + + /** + * An object storing axis-aligned bounding boxes (AABB). + * + * @property wrapBounds + * @type {} + */ + + /** + * An array of callback functions that will be called automatically + * for every pair of bodies, on every engine update. + * + * @property attractors + * @type Function[] + */ + + /** + * A `Number` specifying the angle of the body, in radians. + * + * @property angle + * @type number + * @default 0 + */ + + /** + * An array of `Vector` objects that specify the convex hull of the rigid body. + * These should be provided about the origin `(0, 0)`. E.g. + * + * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }] + * + * When passed via `Body.create`, the vertices are translated relative to `body.position` (i.e. world-space, and constantly updated by `Body.update` during simulation). + * The `Vector` objects are also augmented with additional properties required for efficient collision detection. + * + * Other properties such as `inertia` and `bounds` are automatically calculated from the passed vertices (unless provided via `options`). + * Concave hulls are not currently supported. The module `Matter.Vertices` contains useful methods for working with vertices. + * + * @property vertices + * @type vector[] + */ + + /** + * A `Vector` that specifies the current world-space position of the body. + * + * @property position + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A `Vector` that holds the current scale values as set by `Body.setScale`. + * + * @property scale + * @type vector + * @default { x: 1, y: 1 } + */ + + /** + * A `Vector` that specifies the force to apply in the current step. It is zeroed after every `Body.update`. See also `Body.applyForce`. + * + * @property force + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A `Number` that specifies the torque (turning force) to apply in the current step. It is zeroed after every `Body.update`. + * + * @property torque + * @type number + * @default 0 + */ + + /** + * A `Number` that _measures_ the current speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.velocity`). + * + * @readOnly + * @property speed + * @type number + * @default 0 + */ + + /** + * A `Number` that _measures_ the current angular speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.angularVelocity`). + * + * @readOnly + * @property angularSpeed + * @type number + * @default 0 + */ + + /** + * A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only. + * If you need to modify a body's velocity directly, you should either apply a force or simply change the body's `position` (as the engine uses position-Verlet integration). + * + * @readOnly + * @property velocity + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A `Number` that _measures_ the current angular velocity of the body after the last `Body.update`. It is read-only. + * If you need to modify a body's angular velocity directly, you should apply a torque or simply change the body's `angle` (as the engine uses position-Verlet integration). + * + * @readOnly + * @property angularVelocity + * @type number + * @default 0 + */ + + /** + * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed. + * If you need to set a body as static after its creation, you should use `Body.setStatic` as this requires more than just setting this flag. + * + * @property isStatic + * @type boolean + * @default false + */ + + /** + * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically. + * + * @property isSensor + * @type boolean + * @default false + */ + + /** + * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken. + * If you need to set a body as sleeping, you should use `Sleeping.set` as this requires more than just setting this flag. + * + * @property isSleeping + * @type boolean + * @default false + */ + + /** + * A `Number` that _measures_ the amount of movement a body currently has (a combination of `speed` and `angularSpeed`). It is read-only and always positive. + * It is used and updated by the `Matter.Sleeping` module during simulation to decide if a body has come to rest. + * + * @readOnly + * @property motion + * @type number + * @default 0 + */ + + /** + * A `Number` that defines the number of updates in which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine). + * + * @property sleepThreshold + * @type number + * @default 60 + */ + + /** + * A `Number` that defines the density of the body, that is its mass per unit area. + * If you pass the density via `Body.create` the `mass` property is automatically calculated for you based on the size (area) of the object. + * This is generally preferable to simply setting mass and allows for more intuitive definition of materials (e.g. rock has a higher density than wood). + * + * @property density + * @type number + * @default 0.001 + */ + + /** + * A `Number` that defines the mass of the body, although it may be more appropriate to specify the `density` property instead. + * If you modify this value, you must also modify the `body.inverseMass` property (`1 / mass`). + * + * @property mass + * @type number + */ + + /** + * A `Number` that defines the inverse mass of the body (`1 / mass`). + * If you modify this value, you must also modify the `body.mass` property. + * + * @property inverseMass + * @type number + */ + + /** + * A `Number` that defines the moment of inertia (i.e. second moment of area) of the body. + * It is automatically calculated from the given convex hull (`vertices` array) and density in `Body.create`. + * If you modify this value, you must also modify the `body.inverseInertia` property (`1 / inertia`). + * + * @property inertia + * @type number + */ + + /** + * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`). + * If you modify this value, you must also modify the `body.inertia` property. + * + * @property inverseInertia + * @type number + */ + + /** + * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`. + * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. + * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy. + * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula: + * + * Math.max(bodyA.restitution, bodyB.restitution) + * + * @property restitution + * @type number + * @default 0 + */ + + /** + * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`. + * A value of `0` means that the body may slide indefinitely. + * A value of `1` means the body may come to a stop almost instantly after a force is applied. + * + * The effects of the value may be non-linear. + * High values may be unstable depending on the body. + * The engine uses a Coulomb friction model including static and kinetic friction. + * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula: + * + * Math.min(bodyA.friction, bodyB.friction) + * + * @property friction + * @type number + * @default 0.1 + */ + + /** + * A `Number` that defines the static friction of the body (in the Coulomb friction model). + * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used. + * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary. + * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction. + * + * @property frictionStatic + * @type number + * @default 0.5 + */ + + /** + * A `Number` that defines the air friction of the body (air resistance). + * A value of `0` means the body will never slow as it moves through space. + * The higher the value, the faster a body slows when moving through space. + * The effects of the value are non-linear. + * + * @property frictionAir + * @type number + * @default 0.01 + */ + + /** + * An `Object` that specifies the collision filtering properties of this body. + * + * Collisions between two bodies will obey the following rules: + * - If the two bodies have the same non-zero value of `collisionFilter.group`, + * they will always collide if the value is positive, and they will never collide + * if the value is negative. + * - If the two bodies have different values of `collisionFilter.group` or if one + * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows: + * + * Each body belongs to a collision category, given by `collisionFilter.category`. This + * value is used as a bit field and the category should have only one bit set, meaning that + * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32 + * different collision categories available. + * + * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies + * the categories it collides with (the value is the bitwise AND value of all these categories). + * + * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's + * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0` + * are both true. + * + * @property collisionFilter + * @type object + */ + + /** + * An Integer `Number`, that specifies the collision group this body belongs to. + * See `body.collisionFilter` for more information. + * + * @property collisionFilter.group + * @type object + * @default 0 + */ + + /** + * A bit field that specifies the collision category this body belongs to. + * The category value should have only one bit set, for example `0x0001`. + * This means there are up to 32 unique collision categories available. + * See `body.collisionFilter` for more information. + * + * @property collisionFilter.category + * @type object + * @default 1 + */ + + /** + * A bit mask that specifies the collision categories this body may collide with. + * See `body.collisionFilter` for more information. + * + * @property collisionFilter.mask + * @type object + * @default -1 + */ + + /** + * A `Number` that specifies a tolerance on how far a body is allowed to 'sink' or rotate into other bodies. + * Avoid changing this value unless you understand the purpose of `slop` in physics engines. + * The default should generally suffice, although very large bodies may require larger values for stable stacking. + * + * @property slop + * @type number + * @default 0.05 + */ + + /** + * A `Number` that allows per-body time scaling, e.g. a force-field where bodies inside are in slow-motion, while others are at full speed. + * + * @property timeScale + * @type number + * @default 1 + */ + + /** + * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. + * + * @property render + * @type object + */ + + /** + * A flag that indicates if the body should be rendered. + * + * @property render.visible + * @type boolean + * @default true + */ + + /** + * Sets the opacity to use when rendering. + * + * @property render.opacity + * @type number + * @default 1 + */ + + /** + * An `Object` that defines the sprite properties to use when rendering, if any. + * + * @property render.sprite + * @type object + */ + + /** + * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width). + * + * @property render.sprite.xOffset + * @type number + * @default 0 + */ + + /** + * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height). + * + * @property render.sprite.yOffset + * @type number + * @default 0 + */ + + /** + * A hex color value that defines the fill color to use when rendering the body. + * + * @property render.fillColor + * @type number + */ + + /** + * A value that defines the fill opacity to use when rendering the body. + * + * @property render.fillOpacity + * @type number + */ + + /** + * A hex color value that defines the line color to use when rendering the body. + * + * @property render.lineColor + * @type number + */ + + /** + * A value that defines the line opacity to use when rendering the body. + * + * @property render.lineOpacity + * @type number + */ + + /** + * A `Number` that defines the line width to use when rendering the body outline. + * + * @property render.lineThickness + * @type number + */ + + /** + * An array of unique axis vectors (edge normals) used for collision detection. + * These are automatically calculated from the given convex hull (`vertices` array) in `Body.create`. + * They are constantly updated by `Body.update` during the simulation. + * + * @property axes + * @type vector[] + */ + + /** + * A `Number` that _measures_ the area of the body's convex hull, calculated at creation by `Body.create`. + * + * @property area + * @type string + * @default + */ + + /** + * A `Bounds` object that defines the AABB region for the body. + * It is automatically calculated from the given convex hull (`vertices` array) in `Body.create` and constantly updated by `Body.update` during simulation. + * + * @property bounds + * @type bounds + */ + + /** + * A reference to the Phaser Game Object this body belongs to, if any. + * + * @property gameObject + * @type Phaser.GameObjects.GameObject + */ + + /** + * The center of mass of the Body. + * + * @property centerOfMass + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * The center of the body in pixel values. + * Used by Phaser for texture aligment. + * + * @property centerOffset + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * Will this Body ignore World gravity during the Engine update? + * + * @property ignoreGravity + * @type boolean + * @default false + */ + + /** + * Scale the influence of World gravity when applied to this body. + * + * @property gravityScale + * @type vector + * @default { x: 1, y: 1 } + */ + + /** + * Will this Body ignore Phaser Pointer input events? + * + * @property ignorePointer + * @type boolean + * @default false + */ + + /** + * A callback that is invoked when this Body starts colliding with any other Body. + * + * You can register callbacks by providing a function of type `( pair: Matter.Pair) => void`. + * + * @property onCollideCallback + * @type function + * @default null + */ + + /** + * A callback that is invoked when this Body stops colliding with any other Body. + * + * You can register callbacks by providing a function of type `( pair: Matter.Pair) => void`. + * + * @property onCollideEndCallback + * @type function + * @default null + */ + + /** + * A callback that is invoked for the duration that this Body is colliding with any other Body. + * + * You can register callbacks by providing a function of type `( pair: Matter.Pair) => void`. + * + * @property onCollideActiveCallback + * @type function + * @default null + */ + + /** + * A collision callback dictionary used by the `Body.setOnCollideWith` function. + * + * @property onCollideWith + * @type object + * @default null + */ + +})(); + + +/***/ }), + +/***/ 69351: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Composite` module contains methods for creating and manipulating composite bodies. +* A composite body is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`, therefore composites form a tree structure. +* It is important to use the functions in this module to modify composites, rather than directly modifying their properties. +* Note that the `Matter.World` object is also a type of `Matter.Composite` and as such all composite methods here can also operate on a `Matter.World`. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Composite +*/ + +var Composite = {}; + +module.exports = Composite; + +var Events = __webpack_require__(35810); +var Common = __webpack_require__(53402); +var Bounds = __webpack_require__(15647); +var Body = __webpack_require__(22562); + +(function() { + + /** + * Creates a new composite. The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properites section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {} [options] + * @return {composite} A new composite + */ + Composite.create = function(options) { + return Common.extend({ + id: Common.nextId(), + type: 'composite', + parent: null, + isModified: false, + bodies: [], + constraints: [], + composites: [], + label: 'Composite', + plugin: {}, + wrapBounds: null, + cache: { + allBodies: null, + allConstraints: null, + allComposites: null + } + }, options); + }; + + /** + * Sets the composite's `isModified` flag. + * If `updateParents` is true, all parents will be set (default: false). + * If `updateChildren` is true, all children will be set (default: false). + * @method setModified + * @param {composite} composite + * @param {boolean} isModified + * @param {boolean} [updateParents=false] + * @param {boolean} [updateChildren=false] + */ + Composite.setModified = function(composite, isModified, updateParents, updateChildren) { + + Events.trigger(composite, 'compositeModified', composite); + + composite.isModified = isModified; + + if (isModified && composite.cache) { + composite.cache.allBodies = null; + composite.cache.allConstraints = null; + composite.cache.allComposites = null; + } + + if (updateParents && composite.parent) { + Composite.setModified(composite.parent, isModified, updateParents, updateChildren); + } + + if (updateChildren) { + for (var i = 0; i < composite.composites.length; i++) { + var childComposite = composite.composites[i]; + Composite.setModified(childComposite, isModified, updateParents, updateChildren); + } + } + }; + + /** + * Generic single or multi-add function. Adds a single or an array of body(s), constraint(s) or composite(s) to the given composite. + * Triggers `beforeAdd` and `afterAdd` events on the `composite`. + * @method add + * @param {composite} composite + * @param {object|array} object A single or an array of body(s), constraint(s) or composite(s) + * @return {composite} The original composite with the objects added + */ + Composite.add = function(composite, object) { + var objects = [].concat(object); + + Events.trigger(composite, 'beforeAdd', { object: object }); + + for (var i = 0; i < objects.length; i++) { + var obj = objects[i]; + + switch (obj.type) { + + case 'body': + // skip adding compound parts + if (obj.parent !== obj) { + Common.warn('Composite.add: skipped adding a compound body part (you must add its parent instead)'); + break; + } + + Composite.addBody(composite, obj); + break; + case 'constraint': + Composite.addConstraint(composite, obj); + break; + case 'composite': + Composite.addComposite(composite, obj); + break; + case 'mouseConstraint': + Composite.addConstraint(composite, obj.constraint); + break; + + } + } + + Events.trigger(composite, 'afterAdd', { object: object }); + + return composite; + }; + + /** + * Generic remove function. Removes one or many body(s), constraint(s) or a composite(s) to the given composite. + * Optionally searching its children recursively. + * Triggers `beforeRemove` and `afterRemove` events on the `composite`. + * @method remove + * @param {composite} composite + * @param {object|array} object + * @param {boolean} [deep=false] + * @return {composite} The original composite with the objects removed + */ + Composite.remove = function(composite, object, deep) { + var objects = [].concat(object); + + Events.trigger(composite, 'beforeRemove', { object: object }); + + for (var i = 0; i < objects.length; i++) { + var obj = objects[i]; + + switch (obj.type) { + + case 'body': + Composite.removeBody(composite, obj, deep); + break; + case 'constraint': + Composite.removeConstraint(composite, obj, deep); + break; + case 'composite': + Composite.removeComposite(composite, obj, deep); + break; + case 'mouseConstraint': + Composite.removeConstraint(composite, obj.constraint); + break; + + } + } + + Events.trigger(composite, 'afterRemove', { object: object }); + + return composite; + }; + + /** + * Adds a composite to the given composite. + * @private + * @method addComposite + * @param {composite} compositeA + * @param {composite} compositeB + * @return {composite} The original compositeA with the objects from compositeB added + */ + Composite.addComposite = function(compositeA, compositeB) { + compositeA.composites.push(compositeB); + compositeB.parent = compositeA; + Composite.setModified(compositeA, true, true, false); + return compositeA; + }; + + /** + * Removes a composite from the given composite, and optionally searching its children recursively. + * @private + * @method removeComposite + * @param {composite} compositeA + * @param {composite} compositeB + * @param {boolean} [deep=false] + * @return {composite} The original compositeA with the composite removed + */ + Composite.removeComposite = function(compositeA, compositeB, deep) { + var position = Common.indexOf(compositeA.composites, compositeB); + if (position !== -1) { + var bodies = Composite.allBodies(compositeB); + Composite.removeCompositeAt(compositeA, position); + for (var i = 0; i < bodies.length; i++) { + bodies[i].sleepCounter = 0; + } + } + + if (deep) { + for (var i = 0; i < compositeA.composites.length; i++){ + Composite.removeComposite(compositeA.composites[i], compositeB, true); + } + } + + return compositeA; + }; + + /** + * Removes a composite from the given composite. + * @private + * @method removeCompositeAt + * @param {composite} composite + * @param {number} position + * @return {composite} The original composite with the composite removed + */ + Composite.removeCompositeAt = function(composite, position) { + composite.composites.splice(position, 1); + Composite.setModified(composite, true, true, false); + return composite; + }; + + /** + * Adds a body to the given composite. + * @private + * @method addBody + * @param {composite} composite + * @param {body} body + * @return {composite} The original composite with the body added + */ + Composite.addBody = function(composite, body) { + composite.bodies.push(body); + Composite.setModified(composite, true, true, false); + return composite; + }; + + /** + * Removes a body from the given composite, and optionally searching its children recursively. + * @private + * @method removeBody + * @param {composite} composite + * @param {body} body + * @param {boolean} [deep=false] + * @return {composite} The original composite with the body removed + */ + Composite.removeBody = function(composite, body, deep) { + var position = Common.indexOf(composite.bodies, body); + if (position !== -1) { + Composite.removeBodyAt(composite, position); + body.sleepCounter = 0; + } + + if (deep) { + for (var i = 0; i < composite.composites.length; i++){ + Composite.removeBody(composite.composites[i], body, true); + } + } + + return composite; + }; + + /** + * Removes a body from the given composite. + * @private + * @method removeBodyAt + * @param {composite} composite + * @param {number} position + * @return {composite} The original composite with the body removed + */ + Composite.removeBodyAt = function(composite, position) { + composite.bodies.splice(position, 1); + Composite.setModified(composite, true, true, false); + return composite; + }; + + /** + * Adds a constraint to the given composite. + * @private + * @method addConstraint + * @param {composite} composite + * @param {constraint} constraint + * @return {composite} The original composite with the constraint added + */ + Composite.addConstraint = function(composite, constraint) { + composite.constraints.push(constraint); + Composite.setModified(composite, true, true, false); + return composite; + }; + + /** + * Removes a constraint from the given composite, and optionally searching its children recursively. + * @private + * @method removeConstraint + * @param {composite} composite + * @param {constraint} constraint + * @param {boolean} [deep=false] + * @return {composite} The original composite with the constraint removed + */ + Composite.removeConstraint = function(composite, constraint, deep) { + var position = Common.indexOf(composite.constraints, constraint); + if (position !== -1) { + Composite.removeConstraintAt(composite, position); + } + + if (deep) { + for (var i = 0; i < composite.composites.length; i++){ + Composite.removeConstraint(composite.composites[i], constraint, true); + } + } + + return composite; + }; + + /** + * Removes a body from the given composite. + * @private + * @method removeConstraintAt + * @param {composite} composite + * @param {number} position + * @return {composite} The original composite with the constraint removed + */ + Composite.removeConstraintAt = function(composite, position) { + composite.constraints.splice(position, 1); + Composite.setModified(composite, true, true, false); + return composite; + }; + + /** + * Removes all bodies, constraints and composites from the given composite. + * Optionally clearing its children recursively. + * @method clear + * @param {composite} composite + * @param {boolean} keepStatic + * @param {boolean} [deep=false] + */ + Composite.clear = function(composite, keepStatic, deep) { + if (deep) { + for (var i = 0; i < composite.composites.length; i++){ + Composite.clear(composite.composites[i], keepStatic, true); + } + } + + if (keepStatic) { + composite.bodies = composite.bodies.filter(function(body) { return body.isStatic; }); + } else { + composite.bodies.length = 0; + } + + composite.constraints.length = 0; + composite.composites.length = 0; + + Composite.setModified(composite, true, true, false); + + return composite; + }; + + /** + * Returns all bodies in the given composite, including all bodies in its children, recursively. + * @method allBodies + * @param {composite} composite + * @return {body[]} All the bodies + */ + Composite.allBodies = function(composite) { + if (composite.cache && composite.cache.allBodies) { + return composite.cache.allBodies; + } + + var bodies = [].concat(composite.bodies); + + for (var i = 0; i < composite.composites.length; i++) + bodies = bodies.concat(Composite.allBodies(composite.composites[i])); + + if (composite.cache) { + composite.cache.allBodies = bodies; + } + + return bodies; + }; + + /** + * Returns all constraints in the given composite, including all constraints in its children, recursively. + * @method allConstraints + * @param {composite} composite + * @return {constraint[]} All the constraints + */ + Composite.allConstraints = function(composite) { + if (composite.cache && composite.cache.allConstraints) { + return composite.cache.allConstraints; + } + + var constraints = [].concat(composite.constraints); + + for (var i = 0; i < composite.composites.length; i++) + constraints = constraints.concat(Composite.allConstraints(composite.composites[i])); + + if (composite.cache) { + composite.cache.allConstraints = constraints; + } + + return constraints; + }; + + /** + * Returns all composites in the given composite, including all composites in its children, recursively. + * @method allComposites + * @param {composite} composite + * @return {composite[]} All the composites + */ + Composite.allComposites = function(composite) { + if (composite.cache && composite.cache.allComposites) { + return composite.cache.allComposites; + } + + var composites = [].concat(composite.composites); + + for (var i = 0; i < composite.composites.length; i++) + composites = composites.concat(Composite.allComposites(composite.composites[i])); + + if (composite.cache) { + composite.cache.allComposites = composites; + } + + return composites; + }; + + /** + * Searches the composite recursively for an object matching the type and id supplied, null if not found. + * @method get + * @param {composite} composite + * @param {number} id + * @param {string} type + * @return {object} The requested object, if found + */ + Composite.get = function(composite, id, type) { + var objects, + object; + + switch (type) { + case 'body': + objects = Composite.allBodies(composite); + break; + case 'constraint': + objects = Composite.allConstraints(composite); + break; + case 'composite': + objects = Composite.allComposites(composite).concat(composite); + break; + } + + if (!objects) + return null; + + object = objects.filter(function(object) { + return object.id.toString() === id.toString(); + }); + + return object.length === 0 ? null : object[0]; + }; + + /** + * Moves the given object(s) from compositeA to compositeB (equal to a remove followed by an add). + * @method move + * @param {compositeA} compositeA + * @param {object[]} objects + * @param {compositeB} compositeB + * @return {composite} Returns compositeA + */ + Composite.move = function(compositeA, objects, compositeB) { + Composite.remove(compositeA, objects); + Composite.add(compositeB, objects); + return compositeA; + }; + + /** + * Assigns new ids for all objects in the composite, recursively. + * @method rebase + * @param {composite} composite + * @return {composite} Returns composite + */ + Composite.rebase = function(composite) { + var objects = Composite.allBodies(composite) + .concat(Composite.allConstraints(composite)) + .concat(Composite.allComposites(composite)); + + for (var i = 0; i < objects.length; i++) { + objects[i].id = Common.nextId(); + } + + return composite; + }; + + /** + * Translates all children in the composite by a given vector relative to their current positions, + * without imparting any velocity. + * @method translate + * @param {composite} composite + * @param {vector} translation + * @param {bool} [recursive=true] + */ + Composite.translate = function(composite, translation, recursive) { + var bodies = recursive ? Composite.allBodies(composite) : composite.bodies; + + for (var i = 0; i < bodies.length; i++) { + Body.translate(bodies[i], translation); + } + + return composite; + }; + + /** + * Rotates all children in the composite by a given angle about the given point, without imparting any angular velocity. + * @method rotate + * @param {composite} composite + * @param {number} rotation + * @param {vector} point + * @param {bool} [recursive=true] + */ + Composite.rotate = function(composite, rotation, point, recursive) { + var cos = Math.cos(rotation), + sin = Math.sin(rotation), + bodies = recursive ? Composite.allBodies(composite) : composite.bodies; + + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i], + dx = body.position.x - point.x, + dy = body.position.y - point.y; + + Body.setPosition(body, { + x: point.x + (dx * cos - dy * sin), + y: point.y + (dx * sin + dy * cos) + }); + + Body.rotate(body, rotation); + } + + return composite; + }; + + /** + * Scales all children in the composite, including updating physical properties (mass, area, axes, inertia), from a world-space point. + * @method scale + * @param {composite} composite + * @param {number} scaleX + * @param {number} scaleY + * @param {vector} point + * @param {bool} [recursive=true] + */ + Composite.scale = function(composite, scaleX, scaleY, point, recursive) { + var bodies = recursive ? Composite.allBodies(composite) : composite.bodies; + + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i], + dx = body.position.x - point.x, + dy = body.position.y - point.y; + + Body.setPosition(body, { + x: point.x + dx * scaleX, + y: point.y + dy * scaleY + }); + + Body.scale(body, scaleX, scaleY); + } + + return composite; + }; + + /** + * Returns the union of the bounds of all of the composite's bodies. + * @method bounds + * @param {composite} composite The composite. + * @returns {bounds} The composite bounds. + */ + Composite.bounds = function(composite) { + var bodies = Composite.allBodies(composite), + vertices = []; + + for (var i = 0; i < bodies.length; i += 1) { + var body = bodies[i]; + vertices.push(body.bounds.min, body.bounds.max); + } + + return Bounds.create(vertices); + }; + + /** + * Wraps the `composite` position such that it always stays within the given bounds. + * Upon crossing a boundary the composite will appear on the opposite side of the bounds, + * while maintaining its velocity. + * This is called automatically by the plugin. + * @function wrap + * @param {composite} composite The composite to wrap. + * @param {bounds} bounds The bounds to wrap the composite inside. + * @returns {?Matter.Vector} The translation vector that was applied (only if wrapping was required). + */ + Composite.wrap = function(composite, bounds) { + var translation = Bounds.wrap( + Composite.bounds(composite), + bounds + ); + + if (translation) { + Composite.translate(composite, translation); + } + + return translation; + }; + + /* + * + * Events Documentation + * + */ + + /** + * Fired when a call to `Composite.add` is made, before objects have been added. + * + * @event beforeAdd + * @param {} event An event object + * @param {} event.object The object(s) to be added (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired when a call to `Composite.add` is made, after objects have been added. + * + * @event afterAdd + * @param {} event An event object + * @param {} event.object The object(s) that have been added (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired when a call to `Composite.remove` is made, before objects have been removed. + * + * @event beforeRemove + * @param {} event An event object + * @param {} event.object The object(s) to be removed (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired when a call to `Composite.remove` is made, after objects have been removed. + * + * @event afterRemove + * @param {} event An event object + * @param {} event.object The object(s) that have been removed (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /* + * + * Properties Documentation + * + */ + + /** + * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. + * + * @property id + * @type number + */ + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "composite" + * @readOnly + */ + + /** + * An arbitrary `String` name to help the user identify and manage composites. + * + * @property label + * @type string + * @default "Composite" + */ + + /** + * A flag that specifies whether the composite has been modified during the current step. + * Most `Matter.Composite` methods will automatically set this flag to `true` to inform the engine of changes to be handled. + * If you need to change it manually, you should use the `Composite.setModified` method. + * + * @property isModified + * @type boolean + * @default false + */ + + /** + * The `Composite` that is the parent of this composite. It is automatically managed by the `Matter.Composite` methods. + * + * @property parent + * @type composite + * @default null + */ + + /** + * An array of `Body` that are _direct_ children of this composite. + * To add or remove bodies you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allBodies` method. + * + * @property bodies + * @type body[] + * @default [] + */ + + /** + * An array of `Constraint` that are _direct_ children of this composite. + * To add or remove constraints you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allConstraints` method. + * + * @property constraints + * @type constraint[] + * @default [] + */ + + /** + * An array of `Composite` that are _direct_ children of this composite. + * To add or remove composites you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allComposites` method. + * + * @property composites + * @type composite[] + * @default [] + */ + + /** + * An object reserved for storing plugin-specific properties. + * + * @property plugin + * @type {} + */ + + /** + * An object storing axis-aligned bounding boxes (AABB). + * + * @property wrapBounds + * @type {} + */ + + /** + * An object used for storing cached results for performance reasons. + * This is used internally only and is automatically managed. + * + * @private + * @property cache + * @type {} + */ + +})(); + + +/***/ }), + +/***/ 4372: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* This module has now been replaced by `Matter.Composite`. +* +* All usage should be migrated to the equivalent functions found on `Matter.Composite`. +* For example `World.add(world, body)` now becomes `Composite.add(world, body)`. +* +* The property `world.gravity` has been moved to `engine.gravity`. +* +* For back-compatibility purposes this module will remain as a direct alias to `Matter.Composite` in the short term during migration. +* Eventually this alias module will be marked as deprecated and then later removed in a future release. +* +* @class World +* @extends Composite +*/ + +var World = {}; + +module.exports = World; + +var Composite = __webpack_require__(69351); + +(function() { + + /** + * See above, aliases for back compatibility only + */ + World.create = Composite.create; + World.add = Composite.add; + World.remove = Composite.remove; + World.clear = Composite.clear; + World.addComposite = Composite.addComposite; + World.addBody = Composite.addBody; + World.addConstraint = Composite.addConstraint; + + /* + * + * Properties Documentation + * + */ + + /** + * The gravity to apply on the world. + * + * @property gravity + * @type object + */ + + /** + * The gravity x component. + * + * @property gravity.x + * @type object + * @default 0 + */ + + /** + * The gravity y component. + * + * @property gravity.y + * @type object + * @default 1 + */ + + /** + * The gravity scale factor. + * + * @property gravity.scale + * @type object + * @default 0.001 + */ + + /** + * A `Bounds` object that defines the world bounds for collision detection. + * + * @property bounds + * @type bounds + * @default { min: { x: -Infinity, y: -Infinity }, max: { x: Infinity, y: Infinity } } + */ + + // World is a Composite body + // see src/module/Outro.js for these aliases: + + /** + * An alias for Composite.add + * @method add + * @param {world} world + * @param {} object + * @return {composite} The original world with the objects added + */ + + /** + * An alias for Composite.remove + * @method remove + * @param {world} world + * @param {} object + * @param {boolean} [deep=false] + * @return {composite} The original world with the objects removed + */ + + /** + * An alias for Composite.clear + * @method clear + * @param {world} world + * @param {boolean} keepStatic + */ + + /** + * An alias for Composite.addComposite + * @method addComposite + * @param {world} world + * @param {composite} composite + * @return {world} The original world with the objects from composite added + */ + + /** + * An alias for Composite.addBody + * @method addBody + * @param {world} world + * @param {body} body + * @return {world} The original world with the body added + */ + + /** + * An alias for Composite.addConstraint + * @method addConstraint + * @param {world} world + * @param {constraint} constraint + * @return {world} The original world with the constraint added + */ + +})(); + + +/***/ }), + +/***/ 52284: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Collision` module contains methods for detecting collisions between a given pair of bodies. +* +* For efficient detection between a list of bodies, see `Matter.Detector` and `Matter.Query`. +* +* See `Matter.Engine` for collision events. +* +* @class Collision +*/ + +var Collision = {}; + +module.exports = Collision; + +var Vertices = __webpack_require__(41598); +var Pair = __webpack_require__(4506); + +(function() { + var _supports = []; + + var _overlapAB = { + overlap: 0, + axis: null + }; + + var _overlapBA = { + overlap: 0, + axis: null + }; + + /** + * Creates a new collision record. + * @method create + * @param {body} bodyA The first body part represented by the collision record + * @param {body} bodyB The second body part represented by the collision record + * @return {collision} A new collision record + */ + Collision.create = function(bodyA, bodyB) { + return { + pair: null, + collided: false, + bodyA: bodyA, + bodyB: bodyB, + parentA: bodyA.parent, + parentB: bodyB.parent, + depth: 0, + normal: { x: 0, y: 0 }, + tangent: { x: 0, y: 0 }, + penetration: { x: 0, y: 0 }, + supports: [null, null], + supportCount: 0 + }; + }; + + /** + * Detect collision between two bodies. + * @method collides + * @param {body} bodyA + * @param {body} bodyB + * @param {pairs} [pairs] Optionally reuse collision records from existing pairs. + * @return {collision|null} A collision record if detected, otherwise null + */ + Collision.collides = function(bodyA, bodyB, pairs) { + Collision._overlapAxes(_overlapAB, bodyA.vertices, bodyB.vertices, bodyA.axes); + + if (_overlapAB.overlap <= 0) { + return null; + } + + Collision._overlapAxes(_overlapBA, bodyB.vertices, bodyA.vertices, bodyB.axes); + + if (_overlapBA.overlap <= 0) { + return null; + } + + // reuse collision records for gc efficiency + var pair = pairs && pairs.table[Pair.id(bodyA, bodyB)], + collision; + + if (!pair) { + collision = Collision.create(bodyA, bodyB); + collision.collided = true; + collision.bodyA = bodyA.id < bodyB.id ? bodyA : bodyB; + collision.bodyB = bodyA.id < bodyB.id ? bodyB : bodyA; + collision.parentA = collision.bodyA.parent; + collision.parentB = collision.bodyB.parent; + } else { + collision = pair.collision; + } + + bodyA = collision.bodyA; + bodyB = collision.bodyB; + + var minOverlap; + + if (_overlapAB.overlap < _overlapBA.overlap) { + minOverlap = _overlapAB; + } else { + minOverlap = _overlapBA; + } + + var normal = collision.normal, + tangent = collision.tangent, + penetration = collision.penetration, + supports = collision.supports, + depth = minOverlap.overlap, + minAxis = minOverlap.axis, + normalX = minAxis.x, + normalY = minAxis.y, + deltaX = bodyB.position.x - bodyA.position.x, + deltaY = bodyB.position.y - bodyA.position.y; + + // ensure normal is facing away from bodyA + if (normalX * deltaX + normalY * deltaY >= 0) { + normalX = -normalX; + normalY = -normalY; + } + normal.x = normalX; + normal.y = normalY; + + tangent.x = -normalY; + tangent.y = normalX; + + + penetration.x = normalX * depth; + penetration.y = normalY * depth; + collision.depth = depth; + + // find support points, there is always either exactly one or two + var supportsB = Collision._findSupports(bodyA, bodyB, normal, 1), + supportCount = 0; + + // find the supports from bodyB that are inside bodyA + if (Vertices.contains(bodyA.vertices, supportsB[0])) { + supports[supportCount++] = supportsB[0]; + } + + if (Vertices.contains(bodyA.vertices, supportsB[1])) { + supports[supportCount++] = supportsB[1]; + } + + // find the supports from bodyA that are inside bodyB + if (supportCount < 2) { + var supportsA = Collision._findSupports(bodyB, bodyA, normal, -1); + + if (Vertices.contains(bodyB.vertices, supportsA[0])) { + supports[supportCount++] = supportsA[0]; + } + + if (supportCount < 2 && Vertices.contains(bodyB.vertices, supportsA[1])) { + supports[supportCount++] = supportsA[1]; + } + } + + // account for the edge case of overlapping but no vertex containment + if (supportCount === 0) { + supports[supportCount++] = supportsB[0]; + } + + // update supports array size + collision.supportCount = supportCount; + + return collision; + }; + + /** + * Find the overlap between two sets of vertices. + * @method _overlapAxes + * @private + * @param {object} result + * @param {vertices} verticesA + * @param {vertices} verticesB + * @param {axes} axes + */ + Collision._overlapAxes = function(result, verticesA, verticesB, axes) { + var verticesALength = verticesA.length, + verticesBLength = verticesB.length, + verticesAX = verticesA[0].x, + verticesAY = verticesA[0].y, + verticesBX = verticesB[0].x, + verticesBY = verticesB[0].y, + axesLength = axes.length, + overlapMin = Number.MAX_VALUE, + overlapAxisNumber = 0, + overlap, + overlapAB, + overlapBA, + dot, + i, + j; + + for (i = 0; i < axesLength; i++) { + var axis = axes[i], + axisX = axis.x, + axisY = axis.y, + minA = verticesAX * axisX + verticesAY * axisY, + minB = verticesBX * axisX + verticesBY * axisY, + maxA = minA, + maxB = minB; + + for (j = 1; j < verticesALength; j += 1) { + dot = verticesA[j].x * axisX + verticesA[j].y * axisY; + + if (dot > maxA) { + maxA = dot; + } else if (dot < minA) { + minA = dot; + } + } + + for (j = 1; j < verticesBLength; j += 1) { + dot = verticesB[j].x * axisX + verticesB[j].y * axisY; + + if (dot > maxB) { + maxB = dot; + } else if (dot < minB) { + minB = dot; + } + } + + overlapAB = maxA - minB; + overlapBA = maxB - minA; + overlap = overlapAB < overlapBA ? overlapAB : overlapBA; + + if (overlap < overlapMin) { + overlapMin = overlap; + overlapAxisNumber = i; + + if (overlap <= 0) { + // can not be intersecting + break; + } + } + } + + result.axis = axes[overlapAxisNumber]; + result.overlap = overlapMin; + }; + + /** + * Finds supporting vertices given two bodies along a given direction using hill-climbing. + * @method _findSupports + * @private + * @param {body} bodyA + * @param {body} bodyB + * @param {vector} normal + * @param {number} direction + * @return [vector] + */ + Collision._findSupports = function(bodyA, bodyB, normal, direction) { + var vertices = bodyB.vertices, + verticesLength = vertices.length, + bodyAPositionX = bodyA.position.x, + bodyAPositionY = bodyA.position.y, + normalX = normal.x * direction, + normalY = normal.y * direction, + vertexA = vertices[0], + vertexB = vertexA, + nearestDistance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y), + vertexC, + distance, + j; + + // find deepest vertex relative to the axis + for (j = 1; j < verticesLength; j += 1) { + vertexB = vertices[j]; + distance = normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y); + + // convex hill-climbing + if (distance < nearestDistance) { + nearestDistance = distance; + vertexA = vertexB; + } + } + + // measure next vertex + vertexC = vertices[(verticesLength + vertexA.index - 1) % verticesLength]; + nearestDistance = normalX * (bodyAPositionX - vertexC.x) + normalY * (bodyAPositionY - vertexC.y); + + // compare with previous vertex + vertexB = vertices[(vertexA.index + 1) % verticesLength]; + if (normalX * (bodyAPositionX - vertexB.x) + normalY * (bodyAPositionY - vertexB.y) < nearestDistance) { + _supports[0] = vertexA; + _supports[1] = vertexB; + + return _supports; + } + + _supports[0] = vertexA; + _supports[1] = vertexC; + + return _supports; + }; + + /* + * + * Properties Documentation + * + */ + + /** + * A reference to the pair using this collision record, if there is one. + * + * @property pair + * @type {pair|null} + * @default null + */ + + /** + * A flag that indicates if the bodies were colliding when the collision was last updated. + * + * @property collided + * @type boolean + * @default false + */ + + /** + * The first body part represented by the collision (see also `collision.parentA`). + * + * @property bodyA + * @type body + */ + + /** + * The second body part represented by the collision (see also `collision.parentB`). + * + * @property bodyB + * @type body + */ + + /** + * The first body represented by the collision (i.e. `collision.bodyA.parent`). + * + * @property parentA + * @type body + */ + + /** + * The second body represented by the collision (i.e. `collision.bodyB.parent`). + * + * @property parentB + * @type body + */ + + /** + * A `Number` that represents the minimum separating distance between the bodies along the collision normal. + * + * @readOnly + * @property depth + * @type number + * @default 0 + */ + + /** + * A normalised `Vector` that represents the direction between the bodies that provides the minimum separating distance. + * + * @property normal + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A normalised `Vector` that is the tangent direction to the collision normal. + * + * @property tangent + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A `Vector` that represents the direction and depth of the collision. + * + * @property penetration + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * An array of body vertices that represent the support points in the collision. + * These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices. + * + * @property supports + * @type vector[] + * @default [] + */ + +})(); + + +/***/ }), + +/***/ 43424: +/***/ ((module) => { + +/** +* The `Matter.Contact` module contains methods for creating and manipulating collision contacts. +* +* @class Contact +*/ + +var Contact = {}; + +module.exports = Contact; + +(function() { + + /** + * Creates a new contact. + * @method create + * @param {vertex} vertex + * @return {contact} A new contact + */ + Contact.create = function(vertex) { + return { + vertex: vertex, + normalImpulse: 0, + tangentImpulse: 0 + }; + }; + +})(); + + +/***/ }), + +/***/ 81388: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm. +* +* @class Detector +*/ + +var Detector = {}; + +module.exports = Detector; + +var Common = __webpack_require__(53402); +var Collision = __webpack_require__(52284); + +(function() { + + /** + * Creates a new collision detector. + * @method create + * @param {} options + * @return {detector} A new collision detector + */ + Detector.create = function(options) { + var defaults = { + bodies: [], + collisions: [], + pairs: null + }; + + return Common.extend(defaults, options); + }; + + /** + * Sets the list of bodies in the detector. + * @method setBodies + * @param {detector} detector + * @param {body[]} bodies + */ + Detector.setBodies = function(detector, bodies) { + detector.bodies = bodies.slice(0); + }; + + /** + * Clears the detector including its list of bodies. + * @method clear + * @param {detector} detector + */ + Detector.clear = function(detector) { + detector.bodies = []; + detector.collisions = []; + }; + + /** + * Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm. + * + * _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons. + * If a specific ordering is required then apply a sort to the resulting array. + * @method collisions + * @param {detector} detector + * @return {collision[]} collisions + */ + Detector.collisions = function(detector) { + var pairs = detector.pairs, + bodies = detector.bodies, + bodiesLength = bodies.length, + canCollide = Detector.canCollide, + collides = Collision.collides, + collisions = detector.collisions, + collisionIndex = 0, + i, + j; + + bodies.sort(Detector._compareBoundsX); + + for (i = 0; i < bodiesLength; i++) { + var bodyA = bodies[i], + boundsA = bodyA.bounds, + boundXMax = bodyA.bounds.max.x, + boundYMax = bodyA.bounds.max.y, + boundYMin = bodyA.bounds.min.y, + bodyAStatic = bodyA.isStatic || bodyA.isSleeping, + partsALength = bodyA.parts.length, + partsASingle = partsALength === 1; + + for (j = i + 1; j < bodiesLength; j++) { + var bodyB = bodies[j], + boundsB = bodyB.bounds; + + if (boundsB.min.x > boundXMax) { + break; + } + + if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) { + continue; + } + + if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) { + continue; + } + + if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) { + continue; + } + + var partsBLength = bodyB.parts.length; + + if (partsASingle && partsBLength === 1) { + var collision = collides(bodyA, bodyB, pairs); + + if (collision) { + collisions[collisionIndex++] = collision; + } + } else { + var partsAStart = partsALength > 1 ? 1 : 0, + partsBStart = partsBLength > 1 ? 1 : 0; + + for (var k = partsAStart; k < partsALength; k++) { + var partA = bodyA.parts[k], + boundsA = partA.bounds; + + for (var z = partsBStart; z < partsBLength; z++) { + var partB = bodyB.parts[z], + boundsB = partB.bounds; + + if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x + || boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) { + continue; + } + + var collision = collides(partA, partB, pairs); + + if (collision) { + collisions[collisionIndex++] = collision; + } + } + } + } + } + } + if (collisions.length !== collisionIndex) { + collisions.length = collisionIndex; + } + + return collisions; + }; + + /** + * Returns `true` if both supplied collision filters will allow a collision to occur. + * See `body.collisionFilter` for more information. + * @method canCollide + * @param {} filterA + * @param {} filterB + * @return {bool} `true` if collision can occur + */ + Detector.canCollide = function(filterA, filterB) { + if (filterA.group === filterB.group && filterA.group !== 0) + return filterA.group > 0; + + return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0; + }; + + /** + * The comparison function used in the broadphase algorithm. + * Returns the signed delta of the bodies bounds on the x-axis. + * @private + * @method _sortCompare + * @param {body} bodyA + * @param {body} bodyB + * @return {number} The signed delta used for sorting + */ + Detector._compareBoundsX = function(bodyA, bodyB) { + return bodyA.bounds.min.x - bodyB.bounds.min.x; + }; + + /* + * + * Properties Documentation + * + */ + + /** + * The array of `Matter.Body` between which the detector finds collisions. + * + * _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector. + * @property bodies + * @type body[] + * @default [] + */ + + /** + * The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector. + * @property collisions + * @type collision[] + * @default [] + */ + + /** + * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage. + * @property pairs + * @type {pairs|null} + * @default null + */ + +})(); + + +/***/ }), + +/***/ 4506: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Pair` module contains methods for creating and manipulating collision pairs. +* +* @class Pair +*/ + +var Pair = {}; + +module.exports = Pair; + +var Contact = __webpack_require__(43424); + +(function() { + + /** + * Creates a pair. + * @method create + * @param {collision} collision + * @param {number} timestamp + * @return {pair} A new pair + */ + Pair.create = function(collision, timestamp) { + var bodyA = collision.bodyA, + bodyB = collision.bodyB; + + var pair = { + id: Pair.id(bodyA, bodyB), + bodyA: bodyA, + bodyB: bodyB, + collision: collision, + contacts: [Contact.create(), Contact.create()], + contactCount: 0, + separation: 0, + isActive: true, + isSensor: bodyA.isSensor || bodyB.isSensor, + timeCreated: timestamp, + timeUpdated: timestamp, + inverseMass: 0, + friction: 0, + frictionStatic: 0, + restitution: 0, + slop: 0 + }; + + Pair.update(pair, collision, timestamp); + + return pair; + }; + + /** + * Updates a pair given a collision. + * @method update + * @param {pair} pair + * @param {collision} collision + * @param {number} timestamp + */ + Pair.update = function(pair, collision, timestamp) { + var supports = collision.supports, + supportCount = collision.supportCount, + contacts = pair.contacts, + parentA = collision.parentA, + parentB = collision.parentB; + + pair.isActive = true; + pair.timeUpdated = timestamp; + pair.collision = collision; + pair.separation = collision.depth; + pair.inverseMass = parentA.inverseMass + parentB.inverseMass; + pair.friction = parentA.friction < parentB.friction ? parentA.friction : parentB.friction; + pair.frictionStatic = parentA.frictionStatic > parentB.frictionStatic ? parentA.frictionStatic : parentB.frictionStatic; + pair.restitution = parentA.restitution > parentB.restitution ? parentA.restitution : parentB.restitution; + pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; + + pair.contactCount = supportCount; + collision.pair = pair; + var supportA = supports[0], + contactA = contacts[0], + + supportB = supports[1], + contactB = contacts[1]; + if (contactB.vertex === supportA || contactA.vertex === supportB) { + contacts[1] = contactA; + contacts[0] = contactA = contactB; + + contactB = contacts[1]; + } + + contactA.vertex = supportA; + contactB.vertex = supportB; + }; + + /** + * Set a pair as active or inactive. + * @method setActive + * @param {pair} pair + * @param {bool} isActive + * @param {number} timestamp + */ + Pair.setActive = function(pair, isActive, timestamp) { + if (isActive) { + pair.isActive = true; + pair.timeUpdated = timestamp; + } else { + pair.isActive = false; + pair.contactCount = 0; + } + }; + + /** + * Get the id for the given pair. + * @method id + * @param {body} bodyA + * @param {body} bodyB + * @return {string} Unique pairId + */ + Pair.id = function(bodyA, bodyB) { + return bodyA.id < bodyB.id ? bodyA.id.toString(36) + ':' + bodyB.id.toString(36) + : bodyB.id.toString(36) + ':' + bodyA.id.toString(36); + }; + +})(); + + +/***/ }), + +/***/ 99561: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets. +* +* @class Pairs +*/ + +var Pairs = {}; + +module.exports = Pairs; + +var Pair = __webpack_require__(4506); +var Common = __webpack_require__(53402); + +(function() { + + /** + * Creates a new pairs structure. + * @method create + * @param {object} options + * @return {pairs} A new pairs structure + */ + Pairs.create = function(options) { + return Common.extend({ + table: {}, + list: [], + collisionStart: [], + collisionActive: [], + collisionEnd: [] + }, options); + }; + + /** + * Updates pairs given a list of collisions. + * @method update + * @param {object} pairs + * @param {collision[]} collisions + * @param {number} timestamp + */ + Pairs.update = function(pairs, collisions, timestamp) { + var pairUpdate = Pair.update, + pairCreate = Pair.create, + pairSetActive = Pair.setActive, + pairsTable = pairs.table, + pairsList = pairs.list, + pairsListLength = pairsList.length, + pairsListIndex = pairsListLength, + collisionStart = pairs.collisionStart, + collisionEnd = pairs.collisionEnd, + collisionActive = pairs.collisionActive, + collisionsLength = collisions.length, + collisionStartIndex = 0, + collisionEndIndex = 0, + collisionActiveIndex = 0, + collision, + pair, + i; + + // clear collision state arrays, but maintain old reference + + + for (i = 0; i < collisionsLength; i++) { + collision = collisions[i]; + pair = collision.pair; + + if (pair) { + // pair already exists (but may or may not be active) + if (pair.isActive) { + // pair exists and is active + collisionActive[collisionActiveIndex++] = pair; + // pair exists but was inactive, so a collision has just started again + } + + // update the pair + pairUpdate(pair, collision, timestamp); + } else { + // pair did not exist, create a new pair + pair = pairCreate(collision, timestamp); + pairsTable[pair.id] = pair; + + // push the new pair + collisionStart[collisionStartIndex++] = pair; + pairsList[pairsListIndex++] = pair; + } + } + + // find pairs that are no longer active + pairsListIndex = 0; + pairsListLength = pairsList.length; + + for (i = 0; i < pairsListLength; i++) { + pair = pairsList[i]; + + if (pair.timeUpdated >= timestamp) { + pairsList[pairsListIndex++] = pair; + } else { + pairSetActive(pair, false, timestamp); + + if (pair.collision.bodyA.sleepCounter > 0 && pair.collision.bodyB.sleepCounter > 0) { + pairsList[pairsListIndex++] = pair; + } else { + collisionEnd[collisionEndIndex++] = pair; + delete pairsTable[pair.id]; + } + } + } + + // remove inactive pairs + if (pairsList.length !== pairsListIndex) { + pairsList.length = pairsListIndex; + } + if (collisionStart.length !== collisionStartIndex) { + collisionStart.length = collisionStartIndex; + } + if (collisionEnd.length !== collisionEndIndex) { + collisionEnd.length = collisionEndIndex; + } + if (collisionActive.length !== collisionActiveIndex) { + collisionActive.length = collisionActiveIndex; + } + }; + + /** + * Clears the given pairs structure. + * @method clear + * @param {pairs} pairs + * @return {pairs} pairs + */ + Pairs.clear = function(pairs) { + pairs.table = {}; + pairs.list.length = 0; + pairs.collisionStart.length = 0; + pairs.collisionActive.length = 0; + pairs.collisionEnd.length = 0; + return pairs; + }; + +})(); + + +/***/ }), + +/***/ 73296: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Query` module contains methods for performing collision queries. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Query +*/ + +var Query = {}; + +module.exports = Query; + +var Vector = __webpack_require__(31725); +var Collision = __webpack_require__(52284); +var Bounds = __webpack_require__(15647); +var Bodies = __webpack_require__(66280); +var Vertices = __webpack_require__(41598); + +(function() { + + /** + * Returns a list of collisions between `body` and `bodies`. + * @method collides + * @param {body} body + * @param {body[]} bodies + * @return {collision[]} Collisions + */ + Query.collides = function(body, bodies) { + var collisions = [], + bodiesLength = bodies.length, + bounds = body.bounds, + collides = Collision.collides, + overlaps = Bounds.overlaps; + + for (var i = 0; i < bodiesLength; i++) { + var bodyA = bodies[i], + partsALength = bodyA.parts.length, + partsAStart = partsALength === 1 ? 0 : 1; + + // Phaser addition - skip same body checks + if (body === bodyA) + { + continue; + } + + if (overlaps(bodyA.bounds, bounds)) { + for (var j = partsAStart; j < partsALength; j++) { + var part = bodyA.parts[j]; + + if (overlaps(part.bounds, bounds)) { + var collision = collides(part, body); + + if (collision) { + collisions.push(collision); + break; + } + } + } + } + } + + return collisions; + }; + + /** + * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided. + * @method ray + * @param {body[]} bodies + * @param {vector} startPoint + * @param {vector} endPoint + * @param {number} [rayWidth] + * @return {collision[]} Collisions + */ + Query.ray = function(bodies, startPoint, endPoint, rayWidth) { + rayWidth = rayWidth || 1e-100; + + var rayAngle = Vector.angle(startPoint, endPoint), + rayLength = Vector.magnitude(Vector.sub(startPoint, endPoint)), + rayX = (endPoint.x + startPoint.x) * 0.5, + rayY = (endPoint.y + startPoint.y) * 0.5, + ray = Bodies.rectangle(rayX, rayY, rayLength, rayWidth, { angle: rayAngle }), + collisions = Query.collides(ray, bodies); + + for (var i = 0; i < collisions.length; i += 1) { + var collision = collisions[i]; + collision.body = collision.bodyB = collision.bodyA; + } + + return collisions; + }; + + /** + * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies. + * @method region + * @param {body[]} bodies + * @param {bounds} bounds + * @param {bool} [outside=false] + * @return {body[]} The bodies matching the query + */ + Query.region = function(bodies, bounds, outside) { + var result = []; + + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i], + overlaps = Bounds.overlaps(body.bounds, bounds); + if ((overlaps && !outside) || (!overlaps && outside)) + result.push(body); + } + + return result; + }; + + /** + * Returns all bodies whose vertices contain the given point, from the given set of bodies. + * @method point + * @param {body[]} bodies + * @param {vector} point + * @return {body[]} The bodies matching the query + */ + Query.point = function(bodies, point) { + var result = []; + + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i]; + + if (Bounds.contains(body.bounds, point)) { + for (var j = body.parts.length === 1 ? 0 : 1; j < body.parts.length; j++) { + var part = body.parts[j]; + + if (Bounds.contains(part.bounds, point) + && Vertices.contains(part.vertices, point)) { + result.push(body); + break; + } + } + } + } + + return result; + }; + +})(); + + +/***/ }), + +/***/ 66272: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Resolver` module contains methods for resolving collision pairs. +* +* @class Resolver +*/ + +var Resolver = {}; + +module.exports = Resolver; + +var Vertices = __webpack_require__(41598); +var Common = __webpack_require__(53402); +var Bounds = __webpack_require__(15647); + +(function() { + + Resolver._restingThresh = 2; + Resolver._restingThreshTangent = Math.sqrt(6); + Resolver._positionDampen = 0.9; + Resolver._positionWarming = 0.8; + Resolver._frictionNormalMultiplier = 5; + Resolver._frictionMaxStatic = Number.MAX_VALUE; + + /** + * Prepare pairs for position solving. + * @method preSolvePosition + * @param {pair[]} pairs + */ + Resolver.preSolvePosition = function(pairs) { + var i, + pair, + contactCount, + pairsLength = pairs.length; + + // find total contacts on each body + for (i = 0; i < pairsLength; i++) { + pair = pairs[i]; + + if (!pair.isActive) + continue; + + contactCount = pair.contactCount; + pair.collision.parentA.totalContacts += contactCount; + pair.collision.parentB.totalContacts += contactCount; + } + }; + + /** + * Find a solution for pair positions. + * @method solvePosition + * @param {pair[]} pairs + * @param {number} delta + * @param {number} [damping=1] + */ + Resolver.solvePosition = function(pairs, delta, damping) { + var i, + pair, + collision, + bodyA, + bodyB, + normal, + contactShare, + positionImpulse, + positionDampen = Resolver._positionDampen * (damping || 1), + slopDampen = Common.clamp(delta / Common._baseDelta, 0, 1), + pairsLength = pairs.length; + + // find impulses required to resolve penetration + for (i = 0; i < pairsLength; i++) { + pair = pairs[i]; + + if (!pair.isActive || pair.isSensor) + continue; + + collision = pair.collision; + bodyA = collision.parentA; + bodyB = collision.parentB; + normal = collision.normal; + + // get current separation between body edges involved in collision + pair.separation = + collision.depth + normal.x * (bodyB.positionImpulse.x - bodyA.positionImpulse.x) + + normal.y * (bodyB.positionImpulse.y - bodyA.positionImpulse.y); + } + + for (i = 0; i < pairsLength; i++) { + pair = pairs[i]; + + if (!pair.isActive || pair.isSensor) + continue; + + collision = pair.collision; + bodyA = collision.parentA; + bodyB = collision.parentB; + normal = collision.normal; + positionImpulse = pair.separation - pair.slop * slopDampen; + + if (bodyA.isStatic || bodyB.isStatic) + positionImpulse *= 2; + + if (!(bodyA.isStatic || bodyA.isSleeping)) { + contactShare = positionDampen / bodyA.totalContacts; + bodyA.positionImpulse.x += normal.x * positionImpulse * contactShare; + bodyA.positionImpulse.y += normal.y * positionImpulse * contactShare; + } + + if (!(bodyB.isStatic || bodyB.isSleeping)) { + contactShare = positionDampen / bodyB.totalContacts; + bodyB.positionImpulse.x -= normal.x * positionImpulse * contactShare; + bodyB.positionImpulse.y -= normal.y * positionImpulse * contactShare; + } + } + }; + + /** + * Apply position resolution. + * @method postSolvePosition + * @param {body[]} bodies + */ + Resolver.postSolvePosition = function(bodies) { + var positionWarming = Resolver._positionWarming, + bodiesLength = bodies.length, + verticesTranslate = Vertices.translate, + boundsUpdate = Bounds.update; + + for (var i = 0; i < bodiesLength; i++) { + var body = bodies[i], + positionImpulse = body.positionImpulse, + positionImpulseX = positionImpulse.x, + positionImpulseY = positionImpulse.y, + velocity = body.velocity; + + // reset contact count + body.totalContacts = 0; + + if (positionImpulseX !== 0 || positionImpulseY !== 0) { + // update body geometry + for (var j = 0; j < body.parts.length; j++) { + var part = body.parts[j]; + verticesTranslate(part.vertices, positionImpulse); + boundsUpdate(part.bounds, part.vertices, velocity); + part.position.x += positionImpulseX; + part.position.y += positionImpulseY; + } + + // move the body without changing velocity + body.positionPrev.x += positionImpulseX; + body.positionPrev.y += positionImpulseY; + + if (positionImpulseX * velocity.x + positionImpulseY * velocity.y < 0) { + // reset cached impulse if the body has velocity along it + positionImpulse.x = 0; + positionImpulse.y = 0; + } else { + // warm the next iteration + positionImpulse.x *= positionWarming; + positionImpulse.y *= positionWarming; + } + } + } + }; + + /** + * Prepare pairs for velocity solving. + * @method preSolveVelocity + * @param {pair[]} pairs + */ + Resolver.preSolveVelocity = function(pairs) { + var pairsLength = pairs.length, + i, + j; + + for (i = 0; i < pairsLength; i++) { + var pair = pairs[i]; + + if (!pair.isActive || pair.isSensor) + continue; + + var contacts = pair.contacts, + contactCount = pair.contactCount, + collision = pair.collision, + bodyA = collision.parentA, + bodyB = collision.parentB, + normal = collision.normal, + tangent = collision.tangent; + + // resolve each contact + for (j = 0; j < contactCount; j++) { + var contact = contacts[j], + contactVertex = contact.vertex, + normalImpulse = contact.normalImpulse, + tangentImpulse = contact.tangentImpulse; + + if (normalImpulse !== 0 || tangentImpulse !== 0) { + // total impulse from contact + var impulseX = normal.x * normalImpulse + tangent.x * tangentImpulse, + impulseY = normal.y * normalImpulse + tangent.y * tangentImpulse; + + // apply impulse from contact + if (!(bodyA.isStatic || bodyA.isSleeping)) { + bodyA.positionPrev.x += impulseX * bodyA.inverseMass; + bodyA.positionPrev.y += impulseY * bodyA.inverseMass; + bodyA.anglePrev += bodyA.inverseInertia * ( + (contactVertex.x - bodyA.position.x) * impulseY + - (contactVertex.y - bodyA.position.y) * impulseX + ); + } + + if (!(bodyB.isStatic || bodyB.isSleeping)) { + bodyB.positionPrev.x -= impulseX * bodyB.inverseMass; + bodyB.positionPrev.y -= impulseY * bodyB.inverseMass; + bodyB.anglePrev -= bodyB.inverseInertia * ( + (contactVertex.x - bodyB.position.x) * impulseY + - (contactVertex.y - bodyB.position.y) * impulseX + ); + } + } + } + } + }; + + /** + * Find a solution for pair velocities. + * @method solveVelocity + * @param {pair[]} pairs + * @param {number} delta + */ + Resolver.solveVelocity = function(pairs, delta) { + var timeScale = delta / Common._baseDelta, + timeScaleSquared = timeScale * timeScale, + timeScaleCubed = timeScaleSquared * timeScale, + restingThresh = -Resolver._restingThresh * timeScale, + restingThreshTangent = Resolver._restingThreshTangent, + frictionNormalMultiplier = Resolver._frictionNormalMultiplier * timeScale, + frictionMaxStatic = Resolver._frictionMaxStatic, + pairsLength = pairs.length, + tangentImpulse, + maxFriction, + i, + j; + + for (i = 0; i < pairsLength; i++) { + var pair = pairs[i]; + + if (!pair.isActive || pair.isSensor) + continue; + + var collision = pair.collision, + bodyA = collision.parentA, + bodyB = collision.parentB, + normalX = collision.normal.x, + normalY = collision.normal.y, + tangentX = collision.tangent.x, + tangentY = collision.tangent.y, + inverseMassTotal = pair.inverseMass, + friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier, + contacts = pair.contacts, + contactCount = pair.contactCount, + contactShare = 1 / contactCount; + + // update body velocities + var bodyAVelocityX = bodyA.position.x - bodyA.positionPrev.x, + bodyAVelocityY = bodyA.position.y - bodyA.positionPrev.y, + bodyAAngularVelocity = bodyA.angle - bodyA.anglePrev, + bodyBVelocityX = bodyB.position.x - bodyB.positionPrev.x, + bodyBVelocityY = bodyB.position.y - bodyB.positionPrev.y, + bodyBAngularVelocity = bodyB.angle - bodyB.anglePrev; + + // resolve each contact + for (j = 0; j < contactCount; j++) { + var contact = contacts[j], + contactVertex = contact.vertex; + + var offsetAX = contactVertex.x - bodyA.position.x, + offsetAY = contactVertex.y - bodyA.position.y, + offsetBX = contactVertex.x - bodyB.position.x, + offsetBY = contactVertex.y - bodyB.position.y; + + var velocityPointAX = bodyAVelocityX - offsetAY * bodyAAngularVelocity, + velocityPointAY = bodyAVelocityY + offsetAX * bodyAAngularVelocity, + velocityPointBX = bodyBVelocityX - offsetBY * bodyBAngularVelocity, + velocityPointBY = bodyBVelocityY + offsetBX * bodyBAngularVelocity; + + var relativeVelocityX = velocityPointAX - velocityPointBX, + relativeVelocityY = velocityPointAY - velocityPointBY; + + var normalVelocity = normalX * relativeVelocityX + normalY * relativeVelocityY, + tangentVelocity = tangentX * relativeVelocityX + tangentY * relativeVelocityY; + + // coulomb friction + var normalOverlap = pair.separation + normalVelocity; + var normalForce = Math.min(normalOverlap, 1); + normalForce = normalOverlap < 0 ? 0 : normalForce; + + var frictionLimit = normalForce * friction; + + if (tangentVelocity < -frictionLimit || tangentVelocity > frictionLimit) { + maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity); + tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleCubed; + + if (tangentImpulse < -maxFriction) { + tangentImpulse = -maxFriction; + } else if (tangentImpulse > maxFriction) { + tangentImpulse = maxFriction; + } + } else { + tangentImpulse = tangentVelocity; + maxFriction = frictionMaxStatic; + } + + // account for mass, inertia and contact offset + var oAcN = offsetAX * normalY - offsetAY * normalX, + oBcN = offsetBX * normalY - offsetBY * normalX, + share = contactShare / (inverseMassTotal + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN); + + // raw impulses + var normalImpulse = (1 + pair.restitution) * normalVelocity * share; + tangentImpulse *= share; + + // handle high velocity and resting collisions separately + if (normalVelocity < restingThresh) { + // high normal velocity so clear cached contact normal impulse + contact.normalImpulse = 0; + } else { + // solve resting collision constraints using Erin Catto's method (GDC08) + // impulse constraint tends to 0 + var contactNormalImpulse = contact.normalImpulse; + contact.normalImpulse += normalImpulse; + if (contact.normalImpulse > 0) contact.normalImpulse = 0; + normalImpulse = contact.normalImpulse - contactNormalImpulse; + } + + // handle high velocity and resting collisions separately + if (tangentVelocity < -restingThreshTangent || tangentVelocity > restingThreshTangent) { + // high tangent velocity so clear cached contact tangent impulse + contact.tangentImpulse = 0; + } else { + // solve resting collision constraints using Erin Catto's method (GDC08) + // tangent impulse tends to -tangentSpeed or +tangentSpeed + var contactTangentImpulse = contact.tangentImpulse; + contact.tangentImpulse += tangentImpulse; + if (contact.tangentImpulse < -maxFriction) contact.tangentImpulse = -maxFriction; + if (contact.tangentImpulse > maxFriction) contact.tangentImpulse = maxFriction; + tangentImpulse = contact.tangentImpulse - contactTangentImpulse; + } + + // total impulse from contact + var impulseX = normalX * normalImpulse + tangentX * tangentImpulse, + impulseY = normalY * normalImpulse + tangentY * tangentImpulse; + + // apply impulse from contact + if (!(bodyA.isStatic || bodyA.isSleeping)) { + bodyA.positionPrev.x += impulseX * bodyA.inverseMass; + bodyA.positionPrev.y += impulseY * bodyA.inverseMass; + bodyA.anglePrev += (offsetAX * impulseY - offsetAY * impulseX) * bodyA.inverseInertia; + } + + if (!(bodyB.isStatic || bodyB.isSleeping)) { + bodyB.positionPrev.x -= impulseX * bodyB.inverseMass; + bodyB.positionPrev.y -= impulseY * bodyB.inverseMass; + bodyB.anglePrev -= (offsetBX * impulseY - offsetBY * impulseX) * bodyB.inverseInertia; + } + } + } + }; + +})(); + + +/***/ }), + +/***/ 48140: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Constraint` module contains methods for creating and manipulating constraints. +* Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position). +* The stiffness of constraints can be modified to create springs or elastic. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Constraint +*/ + +var Constraint = {}; + +module.exports = Constraint; + +var Vertices = __webpack_require__(41598); +var Vector = __webpack_require__(31725); +var Sleeping = __webpack_require__(53614); +var Bounds = __webpack_require__(15647); +var Axes = __webpack_require__(66615); +var Common = __webpack_require__(53402); + +(function() { + + Constraint._warming = 0.4; + Constraint._torqueDampen = 1; + Constraint._minLength = 0.000001; + + /** + * Creates a new constraint. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * To simulate a revolute constraint (or pin joint) set `length: 0` and a high `stiffness` value (e.g. `0.7` or above). + * If the constraint is unstable, try lowering the `stiffness` value and / or increasing `engine.constraintIterations`. + * For compound bodies, constraints must be applied to the parent body (not one of its parts). + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {} options + * @return {constraint} constraint + */ + Constraint.create = function(options) { + var constraint = options; + + // if bodies defined but no points, use body centre + if (constraint.bodyA && !constraint.pointA) + constraint.pointA = { x: 0, y: 0 }; + if (constraint.bodyB && !constraint.pointB) + constraint.pointB = { x: 0, y: 0 }; + + // calculate static length using initial world space points + var initialPointA = constraint.bodyA ? Vector.add(constraint.bodyA.position, constraint.pointA) : constraint.pointA, + initialPointB = constraint.bodyB ? Vector.add(constraint.bodyB.position, constraint.pointB) : constraint.pointB, + length = Vector.magnitude(Vector.sub(initialPointA, initialPointB)); + + constraint.length = typeof constraint.length !== 'undefined' ? constraint.length : length; + + // option defaults + constraint.id = constraint.id || Common.nextId(); + constraint.label = constraint.label || 'Constraint'; + constraint.type = 'constraint'; + constraint.stiffness = constraint.stiffness || (constraint.length > 0 ? 1 : 0.7); + constraint.damping = constraint.damping || 0; + constraint.angularStiffness = constraint.angularStiffness || 0; + constraint.angleA = constraint.bodyA ? constraint.bodyA.angle : constraint.angleA; + constraint.angleB = constraint.bodyB ? constraint.bodyB.angle : constraint.angleB; + constraint.plugin = {}; + + // render + var render = { + visible: true, + type: 'line', + anchors: true, + lineColor: null, // custom Phaser property + lineOpacity: null, // custom Phaser property + lineThickness: null, // custom Phaser property + pinSize: null, // custom Phaser property + anchorColor: null, // custom Phaser property + anchorSize: null // custom Phaser property + }; + + if (constraint.length === 0 && constraint.stiffness > 0.1) { + render.type = 'pin'; + render.anchors = false; + } else if (constraint.stiffness < 0.9) { + render.type = 'spring'; + } + + constraint.render = Common.extend(render, constraint.render); + + return constraint; + }; + + /** + * Prepares for solving by constraint warming. + * @private + * @method preSolveAll + * @param {body[]} bodies + */ + Constraint.preSolveAll = function(bodies) { + for (var i = 0; i < bodies.length; i += 1) { + var body = bodies[i], + impulse = body.constraintImpulse; + + if (body.isStatic || (impulse.x === 0 && impulse.y === 0 && impulse.angle === 0)) { + continue; + } + + body.position.x += impulse.x; + body.position.y += impulse.y; + body.angle += impulse.angle; + } + }; + + /** + * Solves all constraints in a list of collisions. + * @private + * @method solveAll + * @param {constraint[]} constraints + * @param {number} delta + */ + Constraint.solveAll = function(constraints, delta) { + var timeScale = Common.clamp(delta / Common._baseDelta, 0, 1); + // Solve fixed constraints first. + for (var i = 0; i < constraints.length; i += 1) { + var constraint = constraints[i], + fixedA = !constraint.bodyA || (constraint.bodyA && constraint.bodyA.isStatic), + fixedB = !constraint.bodyB || (constraint.bodyB && constraint.bodyB.isStatic); + + if (fixedA || fixedB) { + Constraint.solve(constraints[i], timeScale); + } + } + + // Solve free constraints last. + for (i = 0; i < constraints.length; i += 1) { + constraint = constraints[i]; + fixedA = !constraint.bodyA || (constraint.bodyA && constraint.bodyA.isStatic); + fixedB = !constraint.bodyB || (constraint.bodyB && constraint.bodyB.isStatic); + + if (!fixedA && !fixedB) { + Constraint.solve(constraints[i], timeScale); + } + } + }; + + /** + * Solves a distance constraint with Gauss-Siedel method. + * @private + * @method solve + * @param {constraint} constraint + * @param {number} timeScale + */ + Constraint.solve = function(constraint, timeScale) { + var bodyA = constraint.bodyA, + bodyB = constraint.bodyB, + pointA = constraint.pointA, + pointB = constraint.pointB; + + if (!bodyA && !bodyB) + return; + + // update reference angle + if (bodyA && !bodyA.isStatic) { + Vector.rotate(pointA, bodyA.angle - constraint.angleA, pointA); + constraint.angleA = bodyA.angle; + } + + // update reference angle + if (bodyB && !bodyB.isStatic) { + Vector.rotate(pointB, bodyB.angle - constraint.angleB, pointB); + constraint.angleB = bodyB.angle; + } + + var pointAWorld = pointA, + pointBWorld = pointB; + + if (bodyA) pointAWorld = Vector.add(bodyA.position, pointA); + if (bodyB) pointBWorld = Vector.add(bodyB.position, pointB); + + if (!pointAWorld || !pointBWorld) + return; + + var delta = Vector.sub(pointAWorld, pointBWorld), + currentLength = Vector.magnitude(delta); + + // prevent singularity + if (currentLength < Constraint._minLength) { + currentLength = Constraint._minLength; + } + + // solve distance constraint with Gauss-Siedel method + var difference = (currentLength - constraint.length) / currentLength, + isRigid = constraint.stiffness >= 1 || constraint.length === 0, + stiffness = isRigid ? constraint.stiffness * timeScale + : constraint.stiffness * timeScale * timeScale, + damping = constraint.damping * timeScale, + force = Vector.mult(delta, difference * stiffness), + massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0), + inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0), + resistanceTotal = massTotal + inertiaTotal, + torque, + share, + normal, + normalVelocity, + relativeVelocity; + + if (damping > 0) { + var zero = Vector.create(); + normal = Vector.div(delta, currentLength); + + relativeVelocity = Vector.sub( + bodyB && Vector.sub(bodyB.position, bodyB.positionPrev) || zero, + bodyA && Vector.sub(bodyA.position, bodyA.positionPrev) || zero + ); + + normalVelocity = Vector.dot(normal, relativeVelocity); + } + + if (bodyA && !bodyA.isStatic) { + share = bodyA.inverseMass / massTotal; + + // keep track of applied impulses for post solving + bodyA.constraintImpulse.x -= force.x * share; + bodyA.constraintImpulse.y -= force.y * share; + + // apply forces + bodyA.position.x -= force.x * share; + bodyA.position.y -= force.y * share; + + // apply damping + if (damping > 0) { + bodyA.positionPrev.x -= damping * normal.x * normalVelocity * share; + bodyA.positionPrev.y -= damping * normal.y * normalVelocity * share; + } + + // apply torque + torque = (Vector.cross(pointA, force) / resistanceTotal) * Constraint._torqueDampen * bodyA.inverseInertia * (1 - constraint.angularStiffness); + bodyA.constraintImpulse.angle -= torque; + bodyA.angle -= torque; + } + + if (bodyB && !bodyB.isStatic) { + share = bodyB.inverseMass / massTotal; + + // keep track of applied impulses for post solving + bodyB.constraintImpulse.x += force.x * share; + bodyB.constraintImpulse.y += force.y * share; + + // apply forces + bodyB.position.x += force.x * share; + bodyB.position.y += force.y * share; + + // apply damping + if (damping > 0) { + bodyB.positionPrev.x += damping * normal.x * normalVelocity * share; + bodyB.positionPrev.y += damping * normal.y * normalVelocity * share; + } + + // apply torque + torque = (Vector.cross(pointB, force) / resistanceTotal) * Constraint._torqueDampen * bodyB.inverseInertia * (1 - constraint.angularStiffness); + bodyB.constraintImpulse.angle += torque; + bodyB.angle += torque; + } + + }; + + /** + * Performs body updates required after solving constraints. + * @private + * @method postSolveAll + * @param {body[]} bodies + */ + Constraint.postSolveAll = function(bodies) { + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i], + impulse = body.constraintImpulse; + + if (body.isStatic || (impulse.x === 0 && impulse.y === 0 && impulse.angle === 0)) { + continue; + } + + Sleeping.set(body, false); + + // update geometry and reset + for (var j = 0; j < body.parts.length; j++) { + var part = body.parts[j]; + + Vertices.translate(part.vertices, impulse); + + if (j > 0) { + part.position.x += impulse.x; + part.position.y += impulse.y; + } + + if (impulse.angle !== 0) { + Vertices.rotate(part.vertices, impulse.angle, body.position); + Axes.rotate(part.axes, impulse.angle); + if (j > 0) { + Vector.rotateAbout(part.position, impulse.angle, body.position, part.position); + } + } + + Bounds.update(part.bounds, part.vertices, body.velocity); + } + + // dampen the cached impulse for warming next step + impulse.angle *= Constraint._warming; + impulse.x *= Constraint._warming; + impulse.y *= Constraint._warming; + } + }; + + /** + * Returns the world-space position of `constraint.pointA`, accounting for `constraint.bodyA`. + * @method pointAWorld + * @param {constraint} constraint + * @returns {vector} the world-space position + */ + Constraint.pointAWorld = function(constraint) { + return { + x: (constraint.bodyA ? constraint.bodyA.position.x : 0) + + (constraint.pointA ? constraint.pointA.x : 0), + y: (constraint.bodyA ? constraint.bodyA.position.y : 0) + + (constraint.pointA ? constraint.pointA.y : 0) + }; + }; + + /** + * Returns the world-space position of `constraint.pointB`, accounting for `constraint.bodyB`. + * @method pointBWorld + * @param {constraint} constraint + * @returns {vector} the world-space position + */ + Constraint.pointBWorld = function(constraint) { + return { + x: (constraint.bodyB ? constraint.bodyB.position.x : 0) + + (constraint.pointB ? constraint.pointB.x : 0), + y: (constraint.bodyB ? constraint.bodyB.position.y : 0) + + (constraint.pointB ? constraint.pointB.y : 0) + }; + }; + + /** + * Returns the current length of the constraint. + * This is the distance between both of the constraint's end points. + * See `constraint.length` for the target rest length. + * @method currentLength + * @param {constraint} constraint + * @returns {number} the current length + */ + Constraint.currentLength = function(constraint) { + var pointAX = (constraint.bodyA ? constraint.bodyA.position.x : 0) + + (constraint.pointA ? constraint.pointA.x : 0); + + var pointAY = (constraint.bodyA ? constraint.bodyA.position.y : 0) + + (constraint.pointA ? constraint.pointA.y : 0); + + var pointBX = (constraint.bodyB ? constraint.bodyB.position.x : 0) + + (constraint.pointB ? constraint.pointB.x : 0); + + var pointBY = (constraint.bodyB ? constraint.bodyB.position.y : 0) + + (constraint.pointB ? constraint.pointB.y : 0); + + var deltaX = pointAX - pointBX; + var deltaY = pointAY - pointBY; + + return Math.sqrt(deltaX * deltaX + deltaY * deltaY); + }; + /* + * + * Properties Documentation + * + */ + + /** + * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. + * + * @property id + * @type number + */ + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "constraint" + * @readOnly + */ + + /** + * An arbitrary `String` name to help the user identify and manage bodies. + * + * @property label + * @type string + * @default "Constraint" + */ + + /** + * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. + * + * @property render + * @type object + */ + + /** + * A flag that indicates if the constraint should be rendered. + * + * @property render.visible + * @type boolean + * @default true + */ + + /** + * A `Number` that defines the line width to use when rendering the constraint outline. + * A value of `0` means no outline will be rendered. + * + * @property render.lineWidth + * @type number + * @default 2 + */ + + /** + * A `String` that defines the stroke style to use when rendering the constraint outline. + * It is the same as when using a canvas, so it accepts CSS style property values. + * + * @property render.strokeStyle + * @type string + * @default a random colour + */ + + /** + * A `String` that defines the constraint rendering type. + * The possible values are 'line', 'pin', 'spring'. + * An appropriate render type will be automatically chosen unless one is given in options. + * + * @property render.type + * @type string + * @default 'line' + */ + + /** + * A `Boolean` that defines if the constraint's anchor points should be rendered. + * + * @property render.anchors + * @type boolean + * @default true + */ + + /** + * The first possible `Body` that this constraint is attached to. + * + * @property bodyA + * @type body + * @default null + */ + + /** + * The second possible `Body` that this constraint is attached to. + * + * @property bodyB + * @type body + * @default null + */ + + /** + * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position. + * + * @property pointA + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyB` if defined, otherwise a world-space position. + * + * @property pointB + * @type vector + * @default { x: 0, y: 0 } + */ + + /** + * A `Number` that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. + * A value of `1` means the constraint should be very stiff. + * A value of `0.2` means the constraint acts like a soft spring. + * + * @property stiffness + * @type number + * @default 1 + */ + + /** + * A `Number` that specifies the damping of the constraint, + * i.e. the amount of resistance applied to each body based on their velocities to limit the amount of oscillation. + * Damping will only be apparent when the constraint also has a very low `stiffness`. + * A value of `0.1` means the constraint will apply heavy damping, resulting in little to no oscillation. + * A value of `0` means the constraint will apply no damping. + * + * @property damping + * @type number + * @default 0 + */ + + /** + * A `Number` that specifies the target resting length of the constraint. + * It is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * + * @property length + * @type number + */ + + /** + * An object reserved for storing plugin-specific properties. + * + * @property plugin + * @type {} + */ + +})(); + + +/***/ }), + +/***/ 53402: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Common` module contains utility functions that are common to all modules. +* +* @class Common +*/ + +var Common = {}; + +module.exports = Common; + +(function() { + + Common._baseDelta = 1000 / 60; + Common._nextId = 0; + Common._seed = 0; + Common._nowStartTime = +(new Date()); + Common._warnedOnce = {}; + Common._decomp = null; + + /** + * Extends the object in the first argument using the object in the second argument. + * @method extend + * @param {} obj + * @param {boolean} deep + * @return {} obj extended + */ + Common.extend = function(obj, deep) { + var argsStart, + args, + deepClone; + + if (typeof deep === 'boolean') { + argsStart = 2; + deepClone = deep; + } else { + argsStart = 1; + deepClone = true; + } + + for (var i = argsStart; i < arguments.length; i++) { + var source = arguments[i]; + + if (source) { + for (var prop in source) { + if (deepClone && source[prop] && source[prop].constructor === Object) { + if (!obj[prop] || obj[prop].constructor === Object) { + obj[prop] = obj[prop] || {}; + Common.extend(obj[prop], deepClone, source[prop]); + } else { + obj[prop] = source[prop]; + } + } else { + obj[prop] = source[prop]; + } + } + } + } + + return obj; + }; + + /** + * Creates a new clone of the object, if deep is true references will also be cloned. + * @method clone + * @param {} obj + * @param {bool} deep + * @return {} obj cloned + */ + Common.clone = function(obj, deep) { + return Common.extend({}, deep, obj); + }; + + /** + * Returns the list of keys for the given object. + * @method keys + * @param {} obj + * @return {string[]} keys + */ + Common.keys = function(obj) { + if (Object.keys) + return Object.keys(obj); + + // avoid hasOwnProperty for performance + var keys = []; + for (var key in obj) + keys.push(key); + return keys; + }; + + /** + * Returns the list of values for the given object. + * @method values + * @param {} obj + * @return {array} Array of the objects property values + */ + Common.values = function(obj) { + var values = []; + + if (Object.keys) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + values.push(obj[keys[i]]); + } + return values; + } + + // avoid hasOwnProperty for performance + for (var key in obj) + values.push(obj[key]); + return values; + }; + + /** + * Gets a value from `base` relative to the `path` string. + * @method get + * @param {} obj The base object + * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz' + * @param {number} [begin] Path slice begin + * @param {number} [end] Path slice end + * @return {} The object at the given path + */ + Common.get = function(obj, path, begin, end) { + path = path.split('.').slice(begin, end); + + for (var i = 0; i < path.length; i += 1) { + obj = obj[path[i]]; + } + + return obj; + }; + + /** + * Sets a value on `base` relative to the given `path` string. + * @method set + * @param {} obj The base object + * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz' + * @param {} val The value to set + * @param {number} [begin] Path slice begin + * @param {number} [end] Path slice end + * @return {} Pass through `val` for chaining + */ + Common.set = function(obj, path, val, begin, end) { + var parts = path.split('.').slice(begin, end); + Common.get(obj, path, 0, -1)[parts[parts.length - 1]] = val; + return val; + }; + + /** + * Shuffles the given array in-place. + * The function uses a seeded random generator. + * @method shuffle + * @param {array} array + * @return {array} array shuffled randomly + */ + Common.shuffle = function(array) { + for (var i = array.length - 1; i > 0; i--) { + var j = Math.floor(Common.random() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + return array; + }; + + /** + * Randomly chooses a value from a list with equal probability. + * The function uses a seeded random generator. + * @method choose + * @param {array} choices + * @return {object} A random choice object from the array + */ + Common.choose = function(choices) { + return choices[Math.floor(Common.random() * choices.length)]; + }; + + /** + * Returns true if the object is a HTMLElement, otherwise false. + * @method isElement + * @param {object} obj + * @return {boolean} True if the object is a HTMLElement, otherwise false + */ + Common.isElement = function(obj) { + if (typeof HTMLElement !== 'undefined') { + return obj instanceof HTMLElement; + } + + return !!(obj && obj.nodeType && obj.nodeName); + }; + + /** + * Returns true if the object is an array. + * @method isArray + * @param {object} obj + * @return {boolean} True if the object is an array, otherwise false + */ + Common.isArray = function(obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + + /** + * Returns true if the object is a function. + * @method isFunction + * @param {object} obj + * @return {boolean} True if the object is a function, otherwise false + */ + Common.isFunction = function(obj) { + return typeof obj === "function"; + }; + + /** + * Returns true if the object is a plain object. + * @method isPlainObject + * @param {object} obj + * @return {boolean} True if the object is a plain object, otherwise false + */ + Common.isPlainObject = function(obj) { + return typeof obj === 'object' && obj.constructor === Object; + }; + + /** + * Returns true if the object is a string. + * @method isString + * @param {object} obj + * @return {boolean} True if the object is a string, otherwise false + */ + Common.isString = function(obj) { + return toString.call(obj) === '[object String]'; + }; + + /** + * Returns the given value clamped between a minimum and maximum value. + * @method clamp + * @param {number} value + * @param {number} min + * @param {number} max + * @return {number} The value clamped between min and max inclusive + */ + Common.clamp = function(value, min, max) { + if (value < min) + return min; + if (value > max) + return max; + return value; + }; + + /** + * Returns the sign of the given value. + * @method sign + * @param {number} value + * @return {number} -1 if negative, +1 if 0 or positive + */ + Common.sign = function(value) { + return value < 0 ? -1 : 1; + }; + + /** + * Returns the current timestamp since the time origin (e.g. from page load). + * The result is in milliseconds and will use high-resolution timing if available. + * @method now + * @return {number} the current timestamp in milliseconds + */ + Common.now = function() { + if (typeof window !== 'undefined' && window.performance) { + if (window.performance.now) { + return window.performance.now(); + } else if (window.performance.webkitNow) { + return window.performance.webkitNow(); + } + } + + if (Date.now) { + return Date.now(); + } + + return (new Date()) - Common._nowStartTime; + }; + + /** + * Returns a random value between a minimum and a maximum value inclusive. + * The function uses a seeded random generator. + * @method random + * @param {number} min + * @param {number} max + * @return {number} A random number between min and max inclusive + */ + Common.random = function(min, max) { + min = (typeof min !== "undefined") ? min : 0; + max = (typeof max !== "undefined") ? max : 1; + return min + _seededRandom() * (max - min); + }; + + var _seededRandom = function() { + // https://en.wikipedia.org/wiki/Linear_congruential_generator + Common._seed = (Common._seed * 9301 + 49297) % 233280; + return Common._seed / 233280; + }; + + /** + * Converts a CSS hex colour string into an integer. + * @method colorToNumber + * @param {string} colorString + * @return {number} An integer representing the CSS hex string + */ + Common.colorToNumber = function(colorString) { + colorString = colorString.replace('#',''); + + if (colorString.length == 3) { + colorString = colorString.charAt(0) + colorString.charAt(0) + + colorString.charAt(1) + colorString.charAt(1) + + colorString.charAt(2) + colorString.charAt(2); + } + + return parseInt(colorString, 16); + }; + + /** + * The console logging level to use, where each level includes all levels above and excludes the levels below. + * The default level is 'debug' which shows all console messages. + * + * Possible level values are: + * - 0 = None + * - 1 = Debug + * - 2 = Info + * - 3 = Warn + * - 4 = Error + * @property Common.logLevel + * @type {Number} + * @default 1 + */ + Common.logLevel = 1; + + /** + * Shows a `console.log` message only if the current `Common.logLevel` allows it. + * The message will be prefixed with 'matter-js' to make it easily identifiable. + * @method log + * @param ...objs {} The objects to log. + */ + Common.log = function() { + if (console && Common.logLevel > 0 && Common.logLevel <= 3) { + console.log.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments))); + } + }; + + /** + * Shows a `console.info` message only if the current `Common.logLevel` allows it. + * The message will be prefixed with 'matter-js' to make it easily identifiable. + * @method info + * @param ...objs {} The objects to log. + */ + Common.info = function() { + if (console && Common.logLevel > 0 && Common.logLevel <= 2) { + console.info.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments))); + } + }; + + /** + * Shows a `console.warn` message only if the current `Common.logLevel` allows it. + * The message will be prefixed with 'matter-js' to make it easily identifiable. + * @method warn + * @param ...objs {} The objects to log. + */ + Common.warn = function() { + if (console && Common.logLevel > 0 && Common.logLevel <= 3) { + console.warn.apply(console, ['matter-js:'].concat(Array.prototype.slice.call(arguments))); + } + }; + + /** + * Uses `Common.warn` to log the given message one time only. + * @method warnOnce + * @param ...objs {} The objects to log. + */ + Common.warnOnce = function() { + var message = Array.prototype.slice.call(arguments).join(' '); + + if (!Common._warnedOnce[message]) { + Common.warn(message); + Common._warnedOnce[message] = true; + } + }; + + /** + * Shows a deprecated console warning when the function on the given object is called. + * The target function will be replaced with a new function that first shows the warning + * and then calls the original function. + * @method deprecated + * @param {object} obj The object or module + * @param {string} name The property name of the function on obj + * @param {string} warning The one-time message to show if the function is called + */ + Common.deprecated = function(obj, prop, warning) { + obj[prop] = Common.chain(function() { + Common.warnOnce('🔅 deprecated 🔅', warning); + }, obj[prop]); + }; + + /** + * Returns the next unique sequential ID. + * @method nextId + * @return {Number} Unique sequential ID + */ + Common.nextId = function() { + return Common._nextId++; + }; + + /** + * A cross browser compatible indexOf implementation. + * @method indexOf + * @param {array} haystack + * @param {object} needle + * @return {number} The position of needle in haystack, otherwise -1. + */ + Common.indexOf = function(haystack, needle) { + if (haystack.indexOf) + return haystack.indexOf(needle); + + for (var i = 0; i < haystack.length; i++) { + if (haystack[i] === needle) + return i; + } + + return -1; + }; + + /** + * A cross browser compatible array map implementation. + * @method map + * @param {array} list + * @param {function} func + * @return {array} Values from list transformed by func. + */ + Common.map = function(list, func) { + if (list.map) { + return list.map(func); + } + + var mapped = []; + + for (var i = 0; i < list.length; i += 1) { + mapped.push(func(list[i])); + } + + return mapped; + }; + + /** + * Takes a directed graph and returns the partially ordered set of vertices in topological order. + * Circular dependencies are allowed. + * @method topologicalSort + * @param {object} graph + * @return {array} Partially ordered set of vertices in topological order. + */ + Common.topologicalSort = function(graph) { + // https://github.com/mgechev/javascript-algorithms + // Copyright (c) Minko Gechev (MIT license) + // Modifications: tidy formatting and naming + var result = [], + visited = [], + temp = []; + + for (var node in graph) { + if (!visited[node] && !temp[node]) { + Common._topologicalSort(node, visited, temp, graph, result); + } + } + + return result; + }; + + Common._topologicalSort = function(node, visited, temp, graph, result) { + var neighbors = graph[node] || []; + temp[node] = true; + + for (var i = 0; i < neighbors.length; i += 1) { + var neighbor = neighbors[i]; + + if (temp[neighbor]) { + // skip circular dependencies + continue; + } + + if (!visited[neighbor]) { + Common._topologicalSort(neighbor, visited, temp, graph, result); + } + } + + temp[node] = false; + visited[node] = true; + + result.push(node); + }; + + /** + * Takes _n_ functions as arguments and returns a new function that calls them in order. + * The arguments applied when calling the new function will also be applied to every function passed. + * The value of `this` refers to the last value returned in the chain that was not `undefined`. + * Therefore if a passed function does not return a value, the previously returned value is maintained. + * After all passed functions have been called the new function returns the last returned value (if any). + * If any of the passed functions are a chain, then the chain will be flattened. + * @method chain + * @param ...funcs {function} The functions to chain. + * @return {function} A new function that calls the passed functions in order. + */ + Common.chain = function() { + var funcs = []; + + for (var i = 0; i < arguments.length; i += 1) { + var func = arguments[i]; + + if (func._chained) { + // flatten already chained functions + funcs.push.apply(funcs, func._chained); + } else { + funcs.push(func); + } + } + + var chain = function() { + // https://github.com/GoogleChrome/devtools-docs/issues/53#issuecomment-51941358 + var lastResult, + args = new Array(arguments.length); + + for (var i = 0, l = arguments.length; i < l; i++) { + args[i] = arguments[i]; + } + + for (i = 0; i < funcs.length; i += 1) { + var result = funcs[i].apply(lastResult, args); + + if (typeof result !== 'undefined') { + lastResult = result; + } + } + + return lastResult; + }; + + chain._chained = funcs; + + return chain; + }; + + /** + * Chains a function to excute before the original function on the given `path` relative to `base`. + * See also docs for `Common.chain`. + * @method chainPathBefore + * @param {} base The base object + * @param {string} path The path relative to `base` + * @param {function} func The function to chain before the original + * @return {function} The chained function that replaced the original + */ + Common.chainPathBefore = function(base, path, func) { + return Common.set(base, path, Common.chain( + func, + Common.get(base, path) + )); + }; + + /** + * Chains a function to excute after the original function on the given `path` relative to `base`. + * See also docs for `Common.chain`. + * @method chainPathAfter + * @param {} base The base object + * @param {string} path The path relative to `base` + * @param {function} func The function to chain after the original + * @return {function} The chained function that replaced the original + */ + Common.chainPathAfter = function(base, path, func) { + return Common.set(base, path, Common.chain( + Common.get(base, path), + func + )); + }; + + /** + * Provide the [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module to enable + * concave vertex decomposition support when using `Bodies.fromVertices` e.g. `Common.setDecomp(require('poly-decomp'))`. + * @method setDecomp + * @param {} decomp The [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module. + */ + Common.setDecomp = function(decomp) { + Common._decomp = decomp; + }; + + /** + * Returns the [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module provided through `Common.setDecomp`, + * otherwise returns the global `decomp` if set. + * @method getDecomp + * @return {} The [poly-decomp](https://github.com/schteppe/poly-decomp.js) library module if provided. + */ + Common.getDecomp = function() { + // get user provided decomp if set + var decomp = Common._decomp; + + try { + // otherwise from window global + if (!decomp && typeof window !== 'undefined') { + decomp = window.decomp; + } + + // otherwise from node global + if (!decomp && typeof __webpack_require__.g !== 'undefined') { + decomp = __webpack_require__.g.decomp; + } + } catch (e) { + // decomp not available + decomp = null; + } + + return decomp; + }; +})(); + + +/***/ }), + +/***/ 48413: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Engine` module contains methods for creating and manipulating engines. +* An engine is a controller that manages updating the simulation of the world. +* See `Matter.Runner` for an optional game loop utility. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Engine +*/ + +var Engine = {}; + +module.exports = Engine; + +var Sleeping = __webpack_require__(53614); +var Resolver = __webpack_require__(66272); +var Detector = __webpack_require__(81388); +var Pairs = __webpack_require__(99561); +var Events = __webpack_require__(35810); +var Composite = __webpack_require__(69351); +var Constraint = __webpack_require__(48140); +var Common = __webpack_require__(53402); +var Body = __webpack_require__(22562); + +(function() { + + Engine._deltaMax = 1000 / 60; + /** + * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {object} [options] + * @return {engine} engine + */ + Engine.create = function(options) { + options = options || {}; + + var defaults = { + positionIterations: 6, + velocityIterations: 4, + constraintIterations: 2, + enableSleeping: false, + events: [], + plugin: {}, + gravity: { + x: 0, + y: 1, + scale: 0.001 + }, + timing: { + timestamp: 0, + timeScale: 1, + lastDelta: 0, + lastElapsed: 0, + lastUpdatesPerFrame: 0 + } + }; + + var engine = Common.extend(defaults, options); + + engine.world = options.world || Composite.create({ label: 'World' }); + engine.pairs = options.pairs || Pairs.create(); + engine.detector = options.detector || Detector.create(); + engine.detector.pairs = engine.pairs; + + // for temporary back compatibility only + engine.grid = { buckets: [] }; + engine.world.gravity = engine.gravity; + engine.broadphase = engine.grid; + engine.metrics = {}; + + return engine; + }; + + /** + * Moves the simulation forward in time by `delta` ms. + * Triggers `beforeUpdate` and `afterUpdate` events. + * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events. + * @method update + * @param {engine} engine + * @param {number} [delta=16.666] + */ + Engine.update = function(engine, delta) { + var startTime = Common.now(); + + var world = engine.world, + detector = engine.detector, + pairs = engine.pairs, + timing = engine.timing, + timestamp = timing.timestamp, + i; + if (delta > Engine._deltaMax) { + Common.warnOnce( + 'Matter.Engine.update: delta argument is recommended to be less than or equal to', Engine._deltaMax.toFixed(3), 'ms.' + ); + } + + delta = typeof delta !== 'undefined' ? delta : Common._baseDelta; + delta *= timing.timeScale; + + // increment timestamp + timing.timestamp += delta; + timing.lastDelta = delta; + + // create an event object + var event = { + timestamp: timing.timestamp, + delta: delta + }; + + Events.trigger(engine, 'beforeUpdate', event); + + // get all bodies and all constraints in the world + var allBodies = Composite.allBodies(world), + allConstraints = Composite.allConstraints(world), + allComposites = Composite.allComposites(world); + + // if the world has changed + if (world.isModified) { + // update the detector bodies + Detector.setBodies(detector, allBodies); + + // reset all composite modified flags + Composite.setModified(world, false, false, true); + } + + // update sleeping if enabled + if (engine.enableSleeping) + Sleeping.update(allBodies, delta); + + // apply gravity to all bodies + Engine._bodiesApplyGravity(allBodies, engine.gravity); + + Engine.wrap(allBodies, allComposites); + Engine.attractors(allBodies); + + // update all body position and rotation by integration + if (delta > 0) { + Engine._bodiesUpdate(allBodies, delta); + } + + Events.trigger(engine, 'beforeSolve', event); + + // update all constraints (first pass) + Constraint.preSolveAll(allBodies); + for (i = 0; i < engine.constraintIterations; i++) { + Constraint.solveAll(allConstraints, delta); + } + Constraint.postSolveAll(allBodies); + + // find all collisions + var collisions = Detector.collisions(detector); + + // update collision pairs + Pairs.update(pairs, collisions, timestamp); + + // wake up bodies involved in collisions + if (engine.enableSleeping) + Sleeping.afterCollisions(pairs.list); + + // trigger collision events + if (pairs.collisionStart.length > 0) { + Events.trigger(engine, 'collisionStart', { + pairs: pairs.collisionStart, + timestamp: timing.timestamp, + delta: delta + }); + } + + // iteratively resolve position between collisions + var positionDamping = Common.clamp(20 / engine.positionIterations, 0, 1); + + Resolver.preSolvePosition(pairs.list); + for (i = 0; i < engine.positionIterations; i++) { + Resolver.solvePosition(pairs.list, delta, positionDamping); + } + Resolver.postSolvePosition(allBodies); + + // update all constraints (second pass) + Constraint.preSolveAll(allBodies); + for (i = 0; i < engine.constraintIterations; i++) { + Constraint.solveAll(allConstraints, delta); + } + Constraint.postSolveAll(allBodies); + + // iteratively resolve velocity between collisions + Resolver.preSolveVelocity(pairs.list); + for (i = 0; i < engine.velocityIterations; i++) { + Resolver.solveVelocity(pairs.list, delta); + } + + // update body speed and velocity properties + Engine._bodiesUpdateVelocities(allBodies); + + // trigger collision events + if (pairs.collisionActive.length > 0) { + Events.trigger(engine, 'collisionActive', { + pairs: pairs.collisionActive, + timestamp: timing.timestamp, + delta: delta + }); + } + + if (pairs.collisionEnd.length > 0) { + Events.trigger(engine, 'collisionEnd', { + pairs: pairs.collisionEnd, + timestamp: timing.timestamp, + delta: delta + }); + } + + // clear force buffers + Engine._bodiesClearForces(allBodies); + + Events.trigger(engine, 'afterUpdate', event); + + // log the time elapsed computing this update + engine.timing.lastElapsed = Common.now() - startTime; + + return engine; + }; + + /** + * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`. + * @method merge + * @param {engine} engineA + * @param {engine} engineB + */ + Engine.merge = function(engineA, engineB) { + Common.extend(engineA, engineB); + + if (engineB.world) { + engineA.world = engineB.world; + + Engine.clear(engineA); + + var bodies = Composite.allBodies(engineA.world); + + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i]; + Sleeping.set(body, false); + body.id = Common.nextId(); + } + } + }; + + /** + * Clears the engine pairs and detector. + * @method clear + * @param {engine} engine + */ + Engine.clear = function(engine) { + Pairs.clear(engine.pairs); + Detector.clear(engine.detector); + }; + + /** + * Zeroes the `body.force` and `body.torque` force buffers. + * @method _bodiesClearForces + * @private + * @param {body[]} bodies + */ + Engine._bodiesClearForces = function(bodies) { + var bodiesLength = bodies.length; + for (var i = 0; i < bodiesLength; i++) { + var body = bodies[i]; + + // reset force buffers + body.force.x = 0; + body.force.y = 0; + body.torque = 0; + } + }; + + /** + * Applys a mass dependant force to all given bodies. + * @method _bodiesApplyGravity + * @private + * @param {body[]} bodies + * @param {vector} gravity + */ + Engine._bodiesApplyGravity = function(bodies, gravity) { + var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001, + bodiesLength = bodies.length; + + if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) { + return; + } + + for (var i = 0; i < bodiesLength; i++) { + var body = bodies[i]; + + if (body.ignoreGravity || body.isStatic || body.isSleeping) + continue; + + // add the resultant force of gravity + body.force.y += body.mass * gravity.y * gravityScale; + body.force.x += body.mass * gravity.x * gravityScale; + } + }; + + /** + * Applies `Body.update` to all given `bodies`. + * @method _bodiesUpdate + * @private + * @param {body[]} bodies + * @param {number} delta The amount of time elapsed between updates + */ + Engine._bodiesUpdate = function(bodies, delta) { + var bodiesLength = bodies.length; + + for (var i = 0; i < bodiesLength; i++) { + var body = bodies[i]; + + if (body.isStatic || body.isSleeping) + continue; + + Body.update(body, delta); + } + }; + + /** + * Applies `Body.updateVelocities` to all given `bodies`. + * @method _bodiesUpdateVelocities + * @private + * @param {body[]} bodies + */ + Engine._bodiesUpdateVelocities = function(bodies) { + var bodiesLength = bodies.length; + + for (var i = 0; i < bodiesLength; i++) { + Body.updateVelocities(bodies[i]); + } + }; + + /** + * Applies `Body.wrap` and `Composite.wrap` and to all given `bodies`. + * @method wrap + * @private + * @param {body[]} bodies + */ + Engine.wrap = function(bodies, composites) { + // wrap bodies within the wrapBounds parameters + for (var i = 0; i < bodies.length; i += 1) { + var body = bodies[i]; + + if (body.wrapBounds !== null) { + Body.wrap(body, body.wrapBounds); + } + } + + // wrap composites within the wrapBounds parameters + for (i = 0; i < composites.length; i += 1) { + var composite = composites[i]; + + if (composite.wrapBounds !== null) { + Composite.wrap(composite, composite.wrapBounds); + } + } + }; + + /** + * Applies all attractors for all bodies in the `engine`. + * This is called automatically. + * @method attractors + * @private + * @param {body[]} bodies + */ + Engine.attractors = function(bodies) { + for (var i = 0; i < bodies.length; i++) + { + var bodyA = bodies[i]; + var attractors = bodyA.attractors; + + if (attractors && attractors.length > 0) + { + for (var j = 0; j < bodies.length; j++) + { + var bodyB = bodies[j]; + + if (i !== j) + { + for (var k = 0; k < attractors.length; k++) + { + var attractor = attractors[k]; + var forceVector = attractor; + + if (Common.isFunction(attractor)) + { + forceVector = attractor(bodyA, bodyB); + } + + if (forceVector) + { + Body.applyForce(bodyB, bodyB.position, forceVector); + } + } + } + } + } + } + }; + + /** + * A deprecated alias for `Runner.run`, use `Matter.Runner.run(engine)` instead and see `Matter.Runner` for more information. + * @deprecated use Matter.Runner.run(engine) instead + * @method run + * @param {engine} engine + */ + + /** + * Fired just before an update + * + * @event beforeUpdate + * @param {object} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {engine} event.source The source object of the event + * @param {string} event.name The name of the event + */ + + /** + * Fired after engine update and all collision events + * + * @event afterUpdate + * @param {object} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {engine} event.source The source object of the event + * @param {string} event.name The name of the event + */ + + /** + * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any) + * + * @event collisionStart + * @param {object} event An event object + * @param {pair[]} event.pairs List of affected pairs + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {engine} event.source The source object of the event + * @param {string} event.name The name of the event + */ + + /** + * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any) + * + * @event collisionActive + * @param {object} event An event object + * @param {pair[]} event.pairs List of affected pairs + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {engine} event.source The source object of the event + * @param {string} event.name The name of the event + */ + + /** + * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any) + * + * @event collisionEnd + * @param {object} event An event object + * @param {pair[]} event.pairs List of affected pairs + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {engine} event.source The source object of the event + * @param {string} event.name The name of the event + */ + + /* + * + * Properties Documentation + * + */ + + /** + * An integer `Number` that specifies the number of position iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * + * @property positionIterations + * @type number + * @default 6 + */ + + /** + * An integer `Number` that specifies the number of velocity iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * + * @property velocityIterations + * @type number + * @default 4 + */ + + /** + * An integer `Number` that specifies the number of constraint iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * The default value of `2` is usually very adequate. + * + * @property constraintIterations + * @type number + * @default 2 + */ + + /** + * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module. + * Sleeping can improve stability and performance, but often at the expense of accuracy. + * + * @property enableSleeping + * @type boolean + * @default false + */ + + /** + * An `Object` containing properties regarding the timing systems of the engine. + * + * @property timing + * @type object + */ + + /** + * A `Number` that specifies the global scaling factor of time for all bodies. + * A value of `0` freezes the simulation. + * A value of `0.1` gives a slow-motion effect. + * A value of `1.2` gives a speed-up effect. + * + * @property timing.timeScale + * @type number + * @default 1 + */ + + /** + * A `Number` that specifies the current simulation-time in milliseconds starting from `0`. + * It is incremented on every `Engine.update` by the given `delta` argument. + * + * @property timing.timestamp + * @type number + * @default 0 + */ + + /** + * A `Number` that represents the total execution time elapsed during the last `Engine.update` in milliseconds. + * It is updated by timing from the start of the last `Engine.update` call until it ends. + * + * This value will also include the total execution time of all event handlers directly or indirectly triggered by the engine update. + * + * @property timing.lastElapsed + * @type number + * @default 0 + */ + + /** + * A `Number` that represents the `delta` value used in the last engine update. + * + * @property timing.lastDelta + * @type number + * @default 0 + */ + + /** + * A `Matter.Detector` instance. + * + * @property detector + * @type detector + * @default a Matter.Detector instance + */ + + /** + * A `Matter.Grid` instance. + * + * @deprecated replaced by `engine.detector` + * @property grid + * @type grid + * @default a Matter.Grid instance + */ + + /** + * Replaced by and now alias for `engine.grid`. + * + * @deprecated replaced by `engine.detector` + * @property broadphase + * @type grid + * @default a Matter.Grid instance + */ + + /** + * The root `Matter.Composite` instance that will contain all bodies, constraints and other composites to be simulated by this engine. + * + * @property world + * @type composite + * @default a Matter.Composite instance + */ + + /** + * An object reserved for storing plugin-specific properties. + * + * @property plugin + * @type {} + */ + + /** + * The gravity to apply on all bodies in `engine.world`. + * + * @property gravity + * @type object + */ + + /** + * The gravity x component. + * + * @property gravity.x + * @type object + * @default 0 + */ + + /** + * The gravity y component. + * + * @property gravity.y + * @type object + * @default 1 + */ + + /** + * The gravity scale factor. + * + * @property gravity.scale + * @type object + * @default 0.001 + */ + +})(); + + +/***/ }), + +/***/ 35810: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Events` module contains methods to fire and listen to events on other objects. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Events +*/ + +var Events = {}; + +module.exports = Events; + +var Common = __webpack_require__(53402); + +(function() { + + /** + * Subscribes a callback function to the given object's `eventName`. + * @method on + * @param {} object + * @param {string} eventNames + * @param {function} callback + */ + Events.on = function(object, eventNames, callback) { + var names = eventNames.split(' '), + name; + + for (var i = 0; i < names.length; i++) { + name = names[i]; + object.events = object.events || {}; + object.events[name] = object.events[name] || []; + object.events[name].push(callback); + } + + return callback; + }; + + /** + * Removes the given event callback. If no callback, clears all callbacks in `eventNames`. If no `eventNames`, clears all events. + * @method off + * @param {} object + * @param {string} eventNames + * @param {function} callback + */ + Events.off = function(object, eventNames, callback) { + if (!eventNames) { + object.events = {}; + return; + } + + // handle Events.off(object, callback) + if (typeof eventNames === 'function') { + callback = eventNames; + eventNames = Common.keys(object.events).join(' '); + } + + var names = eventNames.split(' '); + + for (var i = 0; i < names.length; i++) { + var callbacks = object.events[names[i]], + newCallbacks = []; + + if (callback && callbacks) { + for (var j = 0; j < callbacks.length; j++) { + if (callbacks[j] !== callback) + newCallbacks.push(callbacks[j]); + } + } + + object.events[names[i]] = newCallbacks; + } + }; + + /** + * Fires all the callbacks subscribed to the given object's `eventName`, in the order they subscribed, if any. + * @method trigger + * @param {} object + * @param {string} eventNames + * @param {} event + */ + Events.trigger = function(object, eventNames, event) { + var names, + name, + callbacks, + eventClone; + + var events = object.events; + + if (events && Common.keys(events).length > 0) { + if (!event) + event = {}; + + names = eventNames.split(' '); + + for (var i = 0; i < names.length; i++) { + name = names[i]; + callbacks = events[name]; + + if (callbacks) { + eventClone = Common.clone(event, false); + eventClone.name = name; + eventClone.source = object; + + for (var j = 0; j < callbacks.length; j++) { + callbacks[j].apply(object, [eventClone]); + } + } + } + } + }; + +})(); + + +/***/ }), + +/***/ 6790: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter` module is the top level namespace. It also includes a function for installing plugins on top of the library. +* +* @class Matter +*/ + +var Matter = {}; + +module.exports = Matter; + +var Plugin = __webpack_require__(73832); +var Common = __webpack_require__(53402); + +(function() { + + /** + * The library name. + * @property name + * @readOnly + * @type {String} + */ + Matter.name = 'matter-js'; + + /** + * The library version. + * @property version + * @readOnly + * @type {String} + */ + Matter.version = '0.20.0'; + + /** + * A list of plugin dependencies to be installed. These are normally set and installed through `Matter.use`. + * Alternatively you may set `Matter.uses` manually and install them by calling `Plugin.use(Matter)`. + * @property uses + * @type {Array} + */ + Matter.uses = []; + + /** + * The plugins that have been installed through `Matter.Plugin.install`. Read only. + * @property used + * @readOnly + * @type {Array} + */ + Matter.used = []; + + /** + * Installs the given plugins on the `Matter` namespace. + * This is a short-hand for `Plugin.use`, see it for more information. + * Call this function once at the start of your code, with all of the plugins you wish to install as arguments. + * Avoid calling this function multiple times unless you intend to manually control installation order. + * @method use + * @param ...plugin {Function} The plugin(s) to install on `base` (multi-argument). + */ + Matter.use = function() { + Plugin.use(Matter, Array.prototype.slice.call(arguments)); + }; + + /** + * Chains a function to excute before the original function on the given `path` relative to `Matter`. + * See also docs for `Common.chain`. + * @method before + * @param {string} path The path relative to `Matter` + * @param {function} func The function to chain before the original + * @return {function} The chained function that replaced the original + */ + Matter.before = function(path, func) { + path = path.replace(/^Matter./, ''); + return Common.chainPathBefore(Matter, path, func); + }; + + /** + * Chains a function to excute after the original function on the given `path` relative to `Matter`. + * See also docs for `Common.chain`. + * @method after + * @param {string} path The path relative to `Matter` + * @param {function} func The function to chain after the original + * @return {function} The chained function that replaced the original + */ + Matter.after = function(path, func) { + path = path.replace(/^Matter./, ''); + return Common.chainPathAfter(Matter, path, func); + }; + +})(); + + +/***/ }), + +/***/ 73832: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Plugin` module contains functions for registering and installing plugins on modules. +* +* @class Plugin +*/ + +var Plugin = {}; + +module.exports = Plugin; + +var Common = __webpack_require__(53402); + +(function() { + + Plugin._registry = {}; + + /** + * Registers a plugin object so it can be resolved later by name. + * @method register + * @param plugin {} The plugin to register. + * @return {object} The plugin. + */ + Plugin.register = function(plugin) { + if (!Plugin.isPlugin(plugin)) { + Common.warn('Plugin.register:', Plugin.toString(plugin), 'does not implement all required fields.'); + } + + if (plugin.name in Plugin._registry) { + var registered = Plugin._registry[plugin.name], + pluginVersion = Plugin.versionParse(plugin.version).number, + registeredVersion = Plugin.versionParse(registered.version).number; + + if (pluginVersion > registeredVersion) { + Common.warn('Plugin.register:', Plugin.toString(registered), 'was upgraded to', Plugin.toString(plugin)); + Plugin._registry[plugin.name] = plugin; + } else if (pluginVersion < registeredVersion) { + Common.warn('Plugin.register:', Plugin.toString(registered), 'can not be downgraded to', Plugin.toString(plugin)); + } else if (plugin !== registered) { + Common.warn('Plugin.register:', Plugin.toString(plugin), 'is already registered to different plugin object'); + } + } else { + Plugin._registry[plugin.name] = plugin; + } + + return plugin; + }; + + /** + * Resolves a dependency to a plugin object from the registry if it exists. + * The `dependency` may contain a version, but only the name matters when resolving. + * @method resolve + * @param dependency {string} The dependency. + * @return {object} The plugin if resolved, otherwise `undefined`. + */ + Plugin.resolve = function(dependency) { + return Plugin._registry[Plugin.dependencyParse(dependency).name]; + }; + + /** + * Returns a pretty printed plugin name and version. + * @method toString + * @param plugin {} The plugin. + * @return {string} Pretty printed plugin name and version. + */ + Plugin.toString = function(plugin) { + return typeof plugin === 'string' ? plugin : (plugin.name || 'anonymous') + '@' + (plugin.version || plugin.range || '0.0.0'); + }; + + /** + * Returns `true` if the object meets the minimum standard to be considered a plugin. + * This means it must define the following properties: + * - `name` + * - `version` + * - `install` + * @method isPlugin + * @param obj {} The obj to test. + * @return {boolean} `true` if the object can be considered a plugin otherwise `false`. + */ + Plugin.isPlugin = function(obj) { + return obj && obj.name && obj.version && obj.install; + }; + + /** + * Returns `true` if a plugin with the given `name` been installed on `module`. + * @method isUsed + * @param module {} The module. + * @param name {string} The plugin name. + * @return {boolean} `true` if a plugin with the given `name` been installed on `module`, otherwise `false`. + */ + Plugin.isUsed = function(module, name) { + return module.used.indexOf(name) > -1; + }; + + /** + * Returns `true` if `plugin.for` is applicable to `module` by comparing against `module.name` and `module.version`. + * If `plugin.for` is not specified then it is assumed to be applicable. + * The value of `plugin.for` is a string of the format `'module-name'` or `'module-name@version'`. + * @method isFor + * @param plugin {} The plugin. + * @param module {} The module. + * @return {boolean} `true` if `plugin.for` is applicable to `module`, otherwise `false`. + */ + Plugin.isFor = function(plugin, module) { + var parsed = plugin.for && Plugin.dependencyParse(plugin.for); + return !plugin.for || (module.name === parsed.name && Plugin.versionSatisfies(module.version, parsed.range)); + }; + + /** + * Installs the plugins by calling `plugin.install` on each plugin specified in `plugins` if passed, otherwise `module.uses`. + * For installing plugins on `Matter` see the convenience function `Matter.use`. + * Plugins may be specified either by their name or a reference to the plugin object. + * Plugins themselves may specify further dependencies, but each plugin is installed only once. + * Order is important, a topological sort is performed to find the best resulting order of installation. + * This sorting attempts to satisfy every dependency's requested ordering, but may not be exact in all cases. + * This function logs the resulting status of each dependency in the console, along with any warnings. + * - A green tick ✅ indicates a dependency was resolved and installed. + * - An orange diamond 🔶 indicates a dependency was resolved but a warning was thrown for it or one if its dependencies. + * - A red cross ❌ indicates a dependency could not be resolved. + * Avoid calling this function multiple times on the same module unless you intend to manually control installation order. + * @method use + * @param module {} The module install plugins on. + * @param [plugins=module.uses] {} The plugins to install on module (optional, defaults to `module.uses`). + */ + Plugin.use = function(module, plugins) { + module.uses = (module.uses || []).concat(plugins || []); + + if (module.uses.length === 0) { + Common.warn('Plugin.use:', Plugin.toString(module), 'does not specify any dependencies to install.'); + return; + } + + var dependencies = Plugin.dependencies(module), + sortedDependencies = Common.topologicalSort(dependencies), + status = []; + + for (var i = 0; i < sortedDependencies.length; i += 1) { + if (sortedDependencies[i] === module.name) { + continue; + } + + var plugin = Plugin.resolve(sortedDependencies[i]); + + if (!plugin) { + status.push('❌ ' + sortedDependencies[i]); + continue; + } + + if (Plugin.isUsed(module, plugin.name)) { + continue; + } + + if (!Plugin.isFor(plugin, module)) { + Common.warn('Plugin.use:', Plugin.toString(plugin), 'is for', plugin.for, 'but installed on', Plugin.toString(module) + '.'); + plugin._warned = true; + } + + if (plugin.install) { + plugin.install(module); + } else { + Common.warn('Plugin.use:', Plugin.toString(plugin), 'does not specify an install function.'); + plugin._warned = true; + } + + if (plugin._warned) { + status.push('🔶 ' + Plugin.toString(plugin)); + delete plugin._warned; + } else { + status.push('✅ ' + Plugin.toString(plugin)); + } + + module.used.push(plugin.name); + } + + if (status.length > 0 && !plugin.silent) { + Common.info(status.join(' ')); + } + }; + + /** + * Recursively finds all of a module's dependencies and returns a flat dependency graph. + * @method dependencies + * @param module {} The module. + * @return {object} A dependency graph. + */ + Plugin.dependencies = function(module, tracked) { + var parsedBase = Plugin.dependencyParse(module), + name = parsedBase.name; + + tracked = tracked || {}; + + if (name in tracked) { + return; + } + + module = Plugin.resolve(module) || module; + + tracked[name] = Common.map(module.uses || [], function(dependency) { + if (Plugin.isPlugin(dependency)) { + Plugin.register(dependency); + } + + var parsed = Plugin.dependencyParse(dependency), + resolved = Plugin.resolve(dependency); + + if (resolved && !Plugin.versionSatisfies(resolved.version, parsed.range)) { + Common.warn( + 'Plugin.dependencies:', Plugin.toString(resolved), 'does not satisfy', + Plugin.toString(parsed), 'used by', Plugin.toString(parsedBase) + '.' + ); + + resolved._warned = true; + module._warned = true; + } else if (!resolved) { + Common.warn( + 'Plugin.dependencies:', Plugin.toString(dependency), 'used by', + Plugin.toString(parsedBase), 'could not be resolved.' + ); + + module._warned = true; + } + + return parsed.name; + }); + + for (var i = 0; i < tracked[name].length; i += 1) { + Plugin.dependencies(tracked[name][i], tracked); + } + + return tracked; + }; + + /** + * Parses a dependency string into its components. + * The `dependency` is a string of the format `'module-name'` or `'module-name@version'`. + * See documentation for `Plugin.versionParse` for a description of the format. + * This function can also handle dependencies that are already resolved (e.g. a module object). + * @method dependencyParse + * @param dependency {string} The dependency of the format `'module-name'` or `'module-name@version'`. + * @return {object} The dependency parsed into its components. + */ + Plugin.dependencyParse = function(dependency) { + if (Common.isString(dependency)) { + var pattern = /^[\w-]+(@(\*|[\^~]?\d+\.\d+\.\d+(-[0-9A-Za-z-+]+)?))?$/; + + if (!pattern.test(dependency)) { + Common.warn('Plugin.dependencyParse:', dependency, 'is not a valid dependency string.'); + } + + return { + name: dependency.split('@')[0], + range: dependency.split('@')[1] || '*' + }; + } + + return { + name: dependency.name, + range: dependency.range || dependency.version + }; + }; + + /** + * Parses a version string into its components. + * Versions are strictly of the format `x.y.z` (as in [semver](http://semver.org/)). + * Versions may optionally have a prerelease tag in the format `x.y.z-alpha`. + * Ranges are a strict subset of [npm ranges](https://docs.npmjs.com/misc/semver#advanced-range-syntax). + * Only the following range types are supported: + * - Tilde ranges e.g. `~1.2.3` + * - Caret ranges e.g. `^1.2.3` + * - Greater than ranges e.g. `>1.2.3` + * - Greater than or equal ranges e.g. `>=1.2.3` + * - Exact version e.g. `1.2.3` + * - Any version `*` + * @method versionParse + * @param range {string} The version string. + * @return {object} The version range parsed into its components. + */ + Plugin.versionParse = function(range) { + var pattern = /^(\*)|(\^|~|>=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-+]+)?$/; + + if (!pattern.test(range)) { + Common.warn('Plugin.versionParse:', range, 'is not a valid version or range.'); + } + + var parts = pattern.exec(range); + var major = Number(parts[4]); + var minor = Number(parts[5]); + var patch = Number(parts[6]); + + return { + isRange: Boolean(parts[1] || parts[2]), + version: parts[3], + range: range, + operator: parts[1] || parts[2] || '', + major: major, + minor: minor, + patch: patch, + parts: [major, minor, patch], + prerelease: parts[7], + number: major * 1e8 + minor * 1e4 + patch + }; + }; + + /** + * Returns `true` if `version` satisfies the given `range`. + * See documentation for `Plugin.versionParse` for a description of the format. + * If a version or range is not specified, then any version (`*`) is assumed to satisfy. + * @method versionSatisfies + * @param version {string} The version string. + * @param range {string} The range string. + * @return {boolean} `true` if `version` satisfies `range`, otherwise `false`. + */ + Plugin.versionSatisfies = function(version, range) { + range = range || '*'; + + var r = Plugin.versionParse(range), + v = Plugin.versionParse(version); + + if (r.isRange) { + if (r.operator === '*' || version === '*') { + return true; + } + + if (r.operator === '>') { + return v.number > r.number; + } + + if (r.operator === '>=') { + return v.number >= r.number; + } + + if (r.operator === '~') { + return v.major === r.major && v.minor === r.minor && v.patch >= r.patch; + } + + if (r.operator === '^') { + if (r.major > 0) { + return v.major === r.major && v.number >= r.number; + } + + if (r.minor > 0) { + return v.minor === r.minor && v.patch >= r.patch; + } + + return v.patch === r.patch; + } + } + + return version === range || version === '*'; + }; + +})(); + + +/***/ }), + +/***/ 13037: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Runner` module is an optional utility which provides a game loop, +* that handles continuously updating a `Matter.Engine` for you within a browser. +* It is intended for development and debugging purposes, but may also be suitable for simple games. +* If you are using your own game loop instead, then you do not need the `Matter.Runner` module. +* Instead just call `Engine.update(engine, delta)` in your own loop. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Runner +*/ + +var Runner = {}; + +module.exports = Runner; + +var Events = __webpack_require__(35810); +var Engine = __webpack_require__(48413); +var Common = __webpack_require__(53402); + +(function() { + + Runner._maxFrameDelta = 1000 / 15; + Runner._frameDeltaFallback = 1000 / 60; + Runner._timeBufferMargin = 1.5; + Runner._elapsedNextEstimate = 1; + Runner._smoothingLowerBound = 0.1; + Runner._smoothingUpperBound = 0.9; + + + /** + * Creates a new Runner. The options parameter is an object that specifies any properties you wish to override the defaults. + * @method create + * @param {} options + */ + Runner.create = function(options) { + var defaults = { + delta: 1000 / 60, + frameDelta: null, + frameDeltaSmoothing: true, + frameDeltaSnapping: true, + frameDeltaHistory: [], + frameDeltaHistorySize: 100, + frameRequestId: null, + timeBuffer: 0, + timeLastTick: null, + maxUpdates: null, + maxFrameTime: 1000 / 30, + lastUpdatesDeferred: 0, + enabled: true + }; + + var runner = Common.extend(defaults, options); + + // for temporary back compatibility only + runner.fps = 0; + + return runner; + }; + + /** + * Continuously ticks a `Matter.Engine` by calling `Runner.tick` on the `requestAnimationFrame` event. + * @method run + * @param {engine} engine + */ + Runner.run = function(runner, engine) { + // create runner if engine is first argument + runner.timeBuffer = Runner._frameDeltaFallback; + + (function onFrame(time){ + runner.frameRequestId = Runner._onNextFrame(runner, onFrame); + + if (time && runner.enabled) { + Runner.tick(runner, engine, time); + } + })(); + + return runner; + }; + + /** + * A game loop utility that updates the engine and renderer by one step (a 'tick'). + * Features delta smoothing, time correction and fixed or dynamic timing. + * Consider just `Engine.update(engine, delta)` if you're using your own loop. + * @method tick + * @param {runner} runner + * @param {engine} engine + * @param {number} time + */ + Runner.tick = function(runner, engine, time) { + var tickStartTime = Common.now(), + engineDelta = runner.delta, + updateCount = 0; + + // fixed timestep + var frameDelta = time - runner.timeLastTick; + + if (!frameDelta || !runner.timeLastTick || frameDelta > Math.max(Runner._maxFrameDelta, runner.maxFrameTime)) { + // dynamic timestep based on wall clock between calls + frameDelta = runner.frameDelta || Runner._frameDeltaFallback; + } + + if (runner.frameDeltaSmoothing) { + // optimistically filter delta over a few frames, to improve stability + runner.frameDeltaHistory.push(frameDelta); + runner.frameDeltaHistory = runner.frameDeltaHistory.slice(-runner.frameDeltaHistorySize); + var deltaHistorySorted = runner.frameDeltaHistory.slice(0).sort(); + + // limit delta + var deltaHistoryWindow = runner.frameDeltaHistory.slice( + deltaHistorySorted.length * Runner._smoothingLowerBound, + deltaHistorySorted.length * Runner._smoothingUpperBound + ); + + // update engine timing object + var frameDeltaSmoothed = _mean(deltaHistoryWindow); + frameDelta = frameDeltaSmoothed || frameDelta; + } + + if (runner.frameDeltaSnapping) { + frameDelta = 1000 / Math.round(1000 / frameDelta); + } + runner.frameDelta = frameDelta; + runner.timeLastTick = time; + runner.timeBuffer += runner.frameDelta; + runner.timeBuffer = Common.clamp( + runner.timeBuffer, 0, runner.frameDelta + engineDelta * Runner._timeBufferMargin + ); + runner.lastUpdatesDeferred = 0; + var maxUpdates = runner.maxUpdates || Math.ceil(runner.maxFrameTime / engineDelta); + // create an event object + var event = { + timestamp: engine.timing.timestamp + }; + + Events.trigger(runner, 'beforeTick', event); + + // fps counter + + Events.trigger(runner, 'tick', event); + + var updateStartTime = Common.now(); + while (engineDelta > 0 && runner.timeBuffer >= engineDelta * Runner._timeBufferMargin) { + // update + Events.trigger(runner, 'beforeUpdate', event); + + Engine.update(engine, engineDelta); + Events.trigger(runner, 'afterUpdate', event); + + runner.timeBuffer -= engineDelta; + updateCount += 1; + var elapsedTimeTotal = Common.now() - tickStartTime, + elapsedTimeUpdates = Common.now() - updateStartTime, + elapsedNextEstimate = elapsedTimeTotal + Runner._elapsedNextEstimate * elapsedTimeUpdates / updateCount; + if (updateCount >= maxUpdates || elapsedNextEstimate > runner.maxFrameTime) { + runner.lastUpdatesDeferred = Math.round(Math.max(0, (runner.timeBuffer / engineDelta) - Runner._timeBufferMargin)); + break; + } + } + engine.timing.lastUpdatesPerFrame = updateCount; + Events.trigger(runner, 'afterTick', event); + if (runner.frameDeltaHistory.length >= 100) { + if (runner.lastUpdatesDeferred && Math.round(runner.frameDelta / engineDelta) > maxUpdates) { + Common.warnOnce('Matter.Runner: runner reached runner.maxUpdates, see docs.'); + } else if (runner.lastUpdatesDeferred) { + Common.warnOnce('Matter.Runner: runner reached runner.maxFrameTime, see docs.'); + } + if (typeof runner.isFixed !== 'undefined') { + Common.warnOnce('Matter.Runner: runner.isFixed is now redundant, see docs.'); + } + if (runner.deltaMin || runner.deltaMax) { + Common.warnOnce('Matter.Runner: runner.deltaMin and runner.deltaMax were removed, see docs.'); + } + if (runner.fps !== 0) { + Common.warnOnce('Matter.Runner: runner.fps was replaced by runner.delta, see docs.'); + } + } + }; + + /** + * Ends execution of `Runner.run` on the given `runner`, by canceling the animation frame request event loop. + * If you wish to only temporarily pause the engine, see `engine.enabled` instead. + * @method stop + * @param {runner} runner + */ + Runner.stop = function(runner) { + Runner._cancelNextFrame(runner); + }; + + /** + * Alias for `Runner.run`. + * @method start + * @param {runner} runner + * @param {engine} engine + */ + Runner._onNextFrame = function(runner, callback) { + if (typeof window !== 'undefined' && window.requestAnimationFrame) { + runner.frameRequestId = window.requestAnimationFrame(callback); + } else { + throw new Error('Matter.Runner: missing required global window.requestAnimationFrame.'); + } + return runner.frameRequestId; + }; + Runner._cancelNextFrame = function(runner) { + if (typeof window !== 'undefined' && window.cancelAnimationFrame) { + window.cancelAnimationFrame(runner.frameRequestId); + } else { + throw new Error('Matter.Runner: missing required global window.cancelAnimationFrame.'); + } + }; + + var _mean = function(values) { + var result = 0, + valuesLength = values.length; + for (var i = 0; i < valuesLength; i += 1) { + result += values[i]; + } + return (result / valuesLength) || 0; + }; + Runner._mean = _mean; + /* + * + * Events Documentation + * + */ + + /** + * Fired at the start of a tick, before any updates to the engine or timing + * + * @event beforeTick + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired after engine timing updated, but just before update + * + * @event tick + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired at the end of a tick, after engine update and after rendering + * + * @event afterTick + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired before update + * + * @event beforeUpdate + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /** + * Fired after update + * + * @event afterUpdate + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + + /* + * + * Properties Documentation + * + */ + + /** + * A flag that specifies whether the runner is running or not. + * + * @property enabled + * @type boolean + * @default true + */ + + /** + * A `Number` that specifies the time step between updates in milliseconds. + * + * @property delta + * @type number + * @default 1000 / 60 + */ + +})(); + + +/***/ }), + +/***/ 53614: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Sleeping` module contains methods to manage the sleeping state of bodies. +* +* @class Sleeping +*/ + +var Sleeping = {}; + +module.exports = Sleeping; + +var Body = __webpack_require__(22562); +var Events = __webpack_require__(35810); +var Common = __webpack_require__(53402); + +(function() { + + Sleeping._motionWakeThreshold = 0.18; + Sleeping._motionSleepThreshold = 0.08; + Sleeping._minBias = 0.9; + + /** + * Puts bodies to sleep or wakes them up depending on their motion. + * @method update + * @param {body[]} bodies + * @param {number} delta + */ + Sleeping.update = function(bodies, delta) { + var timeScale = delta / Common._baseDelta, + motionSleepThreshold = Sleeping._motionSleepThreshold; + + // update bodies sleeping status + for (var i = 0; i < bodies.length; i++) { + var body = bodies[i], + speed = Body.getSpeed(body), + angularSpeed = Body.getAngularSpeed(body), + motion = speed * speed + angularSpeed * angularSpeed; + + // wake up bodies if they have a force applied + if (body.force.x !== 0 || body.force.y !== 0) { + Sleeping.set(body, false); + continue; + } + + var minMotion = Math.min(body.motion, motion), + maxMotion = Math.max(body.motion, motion); + + // biased average motion estimation between frames + body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion; + + if (body.sleepThreshold > 0 && body.motion < motionSleepThreshold) { + body.sleepCounter += 1; + + if (body.sleepCounter >= body.sleepThreshold / timeScale) { + Sleeping.set(body, true); + } + } else if (body.sleepCounter > 0) { + body.sleepCounter -= 1; + } + } + }; + + /** + * Given a set of colliding pairs, wakes the sleeping bodies involved. + * @method afterCollisions + * @param {pair[]} pairs + */ + Sleeping.afterCollisions = function(pairs) { + var motionSleepThreshold = Sleeping._motionSleepThreshold; + + // wake up bodies involved in collisions + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + + // don't wake inactive pairs + if (!pair.isActive) + continue; + + var collision = pair.collision, + bodyA = collision.bodyA.parent, + bodyB = collision.bodyB.parent; + + // don't wake if at least one body is static + if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic) + continue; + + if (bodyA.isSleeping || bodyB.isSleeping) { + var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB, + movingBody = sleepingBody === bodyA ? bodyB : bodyA; + + if (!sleepingBody.isStatic && movingBody.motion > motionSleepThreshold) { + Sleeping.set(sleepingBody, false); + } + } + } + }; + + /** + * Set a body as sleeping or awake. + * @method set + * @param {body} body + * @param {boolean} isSleeping + */ + Sleeping.set = function(body, isSleeping) { + var wasSleeping = body.isSleeping; + + if (isSleeping) { + body.isSleeping = true; + body.sleepCounter = body.sleepThreshold; + + body.positionImpulse.x = 0; + body.positionImpulse.y = 0; + + body.positionPrev.x = body.position.x; + body.positionPrev.y = body.position.y; + + body.anglePrev = body.angle; + body.speed = 0; + body.angularSpeed = 0; + body.motion = 0; + + if (!wasSleeping) { + Events.trigger(body, 'sleepStart'); + } + } else { + body.isSleeping = false; + body.sleepCounter = 0; + + if (wasSleeping) { + Events.trigger(body, 'sleepEnd'); + } + } + }; + +})(); + + +/***/ }), + +/***/ 66280: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Bodies` module contains factory methods for creating rigid body models +* with commonly used body configurations (such as rectangles, circles and other polygons). +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Bodies +*/ + +// TODO: true circle bodies + +var Bodies = {}; + +module.exports = Bodies; + +var Vertices = __webpack_require__(41598); +var Common = __webpack_require__(53402); +var Body = __webpack_require__(22562); +var Bounds = __webpack_require__(15647); +var Vector = __webpack_require__(31725); + +(function() { + + /** + * Creates a new rigid body model with a rectangle hull. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method rectangle + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + * @param {object} [options] + * @return {body} A new rectangle body + */ + Bodies.rectangle = function(x, y, width, height, options) { + options = options || {}; + + var rectangle = { + label: 'Rectangle Body', + position: { x: x, y: y }, + vertices: Vertices.fromPath('L 0 0 L ' + width + ' 0 L ' + width + ' ' + height + ' L 0 ' + height) + }; + + if (options.chamfer) { + var chamfer = options.chamfer; + rectangle.vertices = Vertices.chamfer(rectangle.vertices, chamfer.radius, + chamfer.quality, chamfer.qualityMin, chamfer.qualityMax); + delete options.chamfer; + } + + return Body.create(Common.extend({}, rectangle, options)); + }; + + /** + * Creates a new rigid body model with a trapezoid hull. + * The `slope` is parameterised as a fraction of `width` and must be < 1 to form a valid trapezoid. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method trapezoid + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + * @param {number} slope Must be a number < 1. + * @param {object} [options] + * @return {body} A new trapezoid body + */ + Bodies.trapezoid = function(x, y, width, height, slope, options) { + options = options || {}; + + if (slope >= 1) { + Common.warn('Bodies.trapezoid: slope parameter must be < 1.'); + } + slope *= 0.5; + var roof = (1 - (slope * 2)) * width; + + var x1 = width * slope, + x2 = x1 + roof, + x3 = x2 + x1, + verticesPath; + + if (slope < 0.5) { + verticesPath = 'L 0 0 L ' + x1 + ' ' + (-height) + ' L ' + x2 + ' ' + (-height) + ' L ' + x3 + ' 0'; + } else { + verticesPath = 'L 0 0 L ' + x2 + ' ' + (-height) + ' L ' + x3 + ' 0'; + } + + var trapezoid = { + label: 'Trapezoid Body', + position: { x: x, y: y }, + vertices: Vertices.fromPath(verticesPath) + }; + + if (options.chamfer) { + var chamfer = options.chamfer; + trapezoid.vertices = Vertices.chamfer(trapezoid.vertices, chamfer.radius, + chamfer.quality, chamfer.qualityMin, chamfer.qualityMax); + delete options.chamfer; + } + + return Body.create(Common.extend({}, trapezoid, options)); + }; + + /** + * Creates a new rigid body model with a circle hull. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method circle + * @param {number} x + * @param {number} y + * @param {number} radius + * @param {object} [options] + * @param {number} [maxSides] + * @return {body} A new circle body + */ + Bodies.circle = function(x, y, radius, options, maxSides) { + options = options || {}; + + var circle = { + label: 'Circle Body', + circleRadius: radius + }; + + // approximate circles with polygons until true circles implemented in SAT + maxSides = maxSides || 25; + var sides = Math.ceil(Math.max(10, Math.min(maxSides, radius))); + + // optimisation: always use even number of sides (half the number of unique axes) + if (sides % 2 === 1) + sides += 1; + + return Bodies.polygon(x, y, sides, radius, Common.extend({}, circle, options)); + }; + + /** + * Creates a new rigid body model with a regular polygon hull with the given number of sides. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method polygon + * @param {number} x + * @param {number} y + * @param {number} sides + * @param {number} radius + * @param {object} [options] + * @return {body} A new regular polygon body + */ + Bodies.polygon = function(x, y, sides, radius, options) { + options = options || {}; + + if (sides < 3) + return Bodies.circle(x, y, radius, options); + + var theta = 2 * Math.PI / sides, + path = '', + offset = theta * 0.5; + + for (var i = 0; i < sides; i += 1) { + var angle = offset + (i * theta), + xx = Math.cos(angle) * radius, + yy = Math.sin(angle) * radius; + + path += 'L ' + xx.toFixed(3) + ' ' + yy.toFixed(3) + ' '; + } + + var polygon = { + label: 'Polygon Body', + position: { x: x, y: y }, + vertices: Vertices.fromPath(path) + }; + + if (options.chamfer) { + var chamfer = options.chamfer; + polygon.vertices = Vertices.chamfer(polygon.vertices, chamfer.radius, + chamfer.quality, chamfer.qualityMin, chamfer.qualityMax); + delete options.chamfer; + } + + return Body.create(Common.extend({}, polygon, options)); + }; + + /** + * Utility to create a compound body based on set(s) of vertices. + * + * _Note:_ To optionally enable automatic concave vertices decomposition the [poly-decomp](https://github.com/schteppe/poly-decomp.js) + * package must be first installed and provided see `Common.setDecomp`, otherwise the convex hull of each vertex set will be used. + * + * The resulting vertices are reorientated about their centre of mass, + * and offset such that `body.position` corresponds to this point. + * + * The resulting offset may be found if needed by subtracting `body.bounds` from the original input bounds. + * To later move the centre of mass see `Body.setCentre`. + * + * Note that automatic conconcave decomposition results are not always optimal. + * For best results, simplify the input vertices as much as possible first. + * By default this function applies some addtional simplification to help. + * + * Some outputs may also require further manual processing afterwards to be robust. + * In particular some parts may need to be overlapped to avoid collision gaps. + * Thin parts and sharp points should be avoided or removed where possible. + * + * The options parameter object specifies any `Matter.Body` properties you wish to override the defaults. + * + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method fromVertices + * @param {number} x + * @param {number} y + * @param {array} vertexSets One or more arrays of vertex points e.g. `[[{ x: 0, y: 0 }...], ...]`. + * @param {object} [options] The body options. + * @param {bool} [flagInternal=false] Optionally marks internal edges with `isInternal`. + * @param {number} [removeCollinear=0.01] Threshold when simplifying vertices along the same edge. + * @param {number} [minimumArea=10] Threshold when removing small parts. + * @param {number} [removeDuplicatePoints=0.01] Threshold when simplifying nearby vertices. + * @return {body} + */ + Bodies.fromVertices = function(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea, removeDuplicatePoints) { + var decomp = Common.getDecomp(), + canDecomp, + body, + parts, + isConvex, + isConcave, + vertices, + i, + j, + k, + v, + z; + + // check decomp is as expected + canDecomp = Boolean(decomp && decomp.quickDecomp); + + options = options || {}; + parts = []; + + flagInternal = typeof flagInternal !== 'undefined' ? flagInternal : false; + removeCollinear = typeof removeCollinear !== 'undefined' ? removeCollinear : 0.01; + minimumArea = typeof minimumArea !== 'undefined' ? minimumArea : 10; + removeDuplicatePoints = typeof removeDuplicatePoints !== 'undefined' ? removeDuplicatePoints : 0.01; + + // ensure vertexSets is an array of arrays + if (!Common.isArray(vertexSets[0])) { + vertexSets = [vertexSets]; + } + + for (v = 0; v < vertexSets.length; v += 1) { + vertices = vertexSets[v]; + isConvex = Vertices.isConvex(vertices); + isConcave = !isConvex; + + if (isConcave && !canDecomp) { + Common.warnOnce( + 'Bodies.fromVertices: Install the \'poly-decomp\' library and use Common.setDecomp or provide \'decomp\' as a global to decompose concave vertices.' + ); + } + + if (isConvex || !canDecomp) { + if (isConvex) { + vertices = Vertices.clockwiseSort(vertices); + } else { + // fallback to convex hull when decomposition is not possible + vertices = Vertices.hull(vertices); + } + + parts.push({ + position: { x: x, y: y }, + vertices: vertices + }); + } else { + // initialise a decomposition + var concave = vertices.map(function(vertex) { + return [vertex.x, vertex.y]; + }); + + // vertices are concave and simple, we can decompose into parts + decomp.makeCCW(concave); + if (removeCollinear !== false) + decomp.removeCollinearPoints(concave, removeCollinear); + if (removeDuplicatePoints !== false && decomp.removeDuplicatePoints) + decomp.removeDuplicatePoints(concave, removeDuplicatePoints); + + // use the quick decomposition algorithm (Bayazit) + var decomposed = decomp.quickDecomp(concave); + + // for each decomposed chunk + for (i = 0; i < decomposed.length; i++) { + var chunk = decomposed[i]; + + // convert vertices into the correct structure + var chunkVertices = chunk.map(function(vertices) { + return { + x: vertices[0], + y: vertices[1] + }; + }); + + // skip small chunks + if (minimumArea > 0 && Vertices.area(chunkVertices) < minimumArea) + continue; + + // create a compound part + parts.push({ + position: Vertices.centre(chunkVertices), + vertices: chunkVertices + }); + } + } + } + + // create body parts + for (i = 0; i < parts.length; i++) { + parts[i] = Body.create(Common.extend(parts[i], options)); + } + + // flag internal edges (coincident part edges) + if (flagInternal) { + var coincident_max_dist = 5; + + for (i = 0; i < parts.length; i++) { + var partA = parts[i]; + + for (j = i + 1; j < parts.length; j++) { + var partB = parts[j]; + + if (Bounds.overlaps(partA.bounds, partB.bounds)) { + var pav = partA.vertices, + pbv = partB.vertices; + + // iterate vertices of both parts + for (k = 0; k < partA.vertices.length; k++) { + for (z = 0; z < partB.vertices.length; z++) { + // find distances between the vertices + var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z])), + db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length])); + + // if both vertices are very close, consider the edge concident (internal) + if (da < coincident_max_dist && db < coincident_max_dist) { + pav[k].isInternal = true; + pbv[z].isInternal = true; + } + } + } + + } + } + } + } + + if (parts.length > 1) { + // create the parent body to be returned, that contains generated compound parts + body = Body.create(Common.extend({ parts: parts.slice(0) }, options)); + + // offset such that body.position is at the centre off mass + Body.setPosition(body, { x: x, y: y }); + + return body; + } else { + return parts[0]; + } + }; + + /** + * Takes an array of Body objects and flags all internal edges (coincident parts) based on the maxDistance + * value. The array is changed in-place and returned, so you can pass this function a `Body.parts` property. + * + * @method flagCoincidentParts + * @param {body[]} parts - The Body parts, or array of bodies, to flag. + * @param {number} [maxDistance=5] + * @return {body[]} The modified `parts` parameter. + */ + Bodies.flagCoincidentParts = function (parts, maxDistance) + { + if (maxDistance === undefined) { maxDistance = 5; } + + for (var i = 0; i < parts.length; i++) + { + var partA = parts[i]; + + for (var j = i + 1; j < parts.length; j++) + { + var partB = parts[j]; + + if (Bounds.overlaps(partA.bounds, partB.bounds)) + { + var pav = partA.vertices; + var pbv = partB.vertices; + + // iterate vertices of both parts + for (var k = 0; k < partA.vertices.length; k++) + { + for (var z = 0; z < partB.vertices.length; z++) + { + // find distances between the vertices + var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z])); + var db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length])); + + // if both vertices are very close, consider the edge concident (internal) + if (da < maxDistance && db < maxDistance) + { + pav[k].isInternal = true; + pbv[z].isInternal = true; + } + } + } + } + } + } + + return parts; + }; + +})(); + + +/***/ }), + +/***/ 74116: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Composites` module contains factory methods for creating composite bodies +* with commonly used configurations (such as stacks and chains). +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Composites +*/ + +var Composites = {}; + +module.exports = Composites; + +var Composite = __webpack_require__(69351); +var Constraint = __webpack_require__(48140); +var Common = __webpack_require__(53402); +var Body = __webpack_require__(22562); +var Bodies = __webpack_require__(66280); + +(function() { + + /** + * Create a new composite containing bodies created in the callback in a grid arrangement. + * This function uses the body's bounds to prevent overlaps. + * @method stack + * @param {number} x Starting position in X. + * @param {number} y Starting position in Y. + * @param {number} columns + * @param {number} rows + * @param {number} columnGap + * @param {number} rowGap + * @param {function} callback + * @return {composite} A new composite containing objects created in the callback + */ + Composites.stack = function(x, y, columns, rows, columnGap, rowGap, callback) { + var stack = Composite.create({ label: 'Stack' }), + currentX = x, + currentY = y, + lastBody, + i = 0; + + for (var row = 0; row < rows; row++) { + var maxHeight = 0; + + for (var column = 0; column < columns; column++) { + var body = callback(currentX, currentY, column, row, lastBody, i); + + if (body) { + var bodyHeight = body.bounds.max.y - body.bounds.min.y, + bodyWidth = body.bounds.max.x - body.bounds.min.x; + + if (bodyHeight > maxHeight) + maxHeight = bodyHeight; + + Body.translate(body, { x: bodyWidth * 0.5, y: bodyHeight * 0.5 }); + + currentX = body.bounds.max.x + columnGap; + + Composite.addBody(stack, body); + + lastBody = body; + i += 1; + } else { + currentX += columnGap; + } + } + + currentY += maxHeight + rowGap; + currentX = x; + } + + return stack; + }; + + /** + * Chains all bodies in the given composite together using constraints. + * @method chain + * @param {composite} composite + * @param {number} xOffsetA + * @param {number} yOffsetA + * @param {number} xOffsetB + * @param {number} yOffsetB + * @param {object} options + * @return {composite} A new composite containing objects chained together with constraints + */ + Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) { + var bodies = composite.bodies; + + for (var i = 1; i < bodies.length; i++) { + var bodyA = bodies[i - 1], + bodyB = bodies[i], + bodyAHeight = bodyA.bounds.max.y - bodyA.bounds.min.y, + bodyAWidth = bodyA.bounds.max.x - bodyA.bounds.min.x, + bodyBHeight = bodyB.bounds.max.y - bodyB.bounds.min.y, + bodyBWidth = bodyB.bounds.max.x - bodyB.bounds.min.x; + + var defaults = { + bodyA: bodyA, + pointA: { x: bodyAWidth * xOffsetA, y: bodyAHeight * yOffsetA }, + bodyB: bodyB, + pointB: { x: bodyBWidth * xOffsetB, y: bodyBHeight * yOffsetB } + }; + + var constraint = Common.extend(defaults, options); + + Composite.addConstraint(composite, Constraint.create(constraint)); + } + + composite.label += ' Chain'; + + return composite; + }; + + /** + * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces. + * @method mesh + * @param {composite} composite + * @param {number} columns + * @param {number} rows + * @param {boolean} crossBrace + * @param {object} options + * @return {composite} The composite containing objects meshed together with constraints + */ + Composites.mesh = function(composite, columns, rows, crossBrace, options) { + var bodies = composite.bodies, + row, + col, + bodyA, + bodyB, + bodyC; + + for (row = 0; row < rows; row++) { + for (col = 1; col < columns; col++) { + bodyA = bodies[(col - 1) + (row * columns)]; + bodyB = bodies[col + (row * columns)]; + Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options))); + } + + if (row > 0) { + for (col = 0; col < columns; col++) { + bodyA = bodies[col + ((row - 1) * columns)]; + bodyB = bodies[col + (row * columns)]; + Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options))); + + if (crossBrace && col > 0) { + bodyC = bodies[(col - 1) + ((row - 1) * columns)]; + Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options))); + } + + if (crossBrace && col < columns - 1) { + bodyC = bodies[(col + 1) + ((row - 1) * columns)]; + Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options))); + } + } + } + } + + composite.label += ' Mesh'; + + return composite; + }; + + /** + * Create a new composite containing bodies created in the callback in a pyramid arrangement. + * This function uses the body's bounds to prevent overlaps. + * @method pyramid + * @param {number} x Starting position in X. + * @param {number} y Starting position in Y. + * @param {number} columns + * @param {number} rows + * @param {number} columnGap + * @param {number} rowGap + * @param {function} callback + * @return {composite} A new composite containing objects created in the callback + */ + Composites.pyramid = function(x, y, columns, rows, columnGap, rowGap, callback) { + return Composites.stack(x, y, columns, rows, columnGap, rowGap, function(stackX, stackY, column, row, lastBody, i) { + var actualRows = Math.min(rows, Math.ceil(columns / 2)), + lastBodyWidth = lastBody ? lastBody.bounds.max.x - lastBody.bounds.min.x : 0; + + if (row > actualRows) + return; + + // reverse row order + row = actualRows - row; + + var start = row, + end = columns - 1 - row; + + if (column < start || column > end) + return; + + // retroactively fix the first body's position, since width was unknown + if (i === 1) { + Body.translate(lastBody, { x: (column + (columns % 2 === 1 ? 1 : -1)) * lastBodyWidth, y: 0 }); + } + + var xOffset = lastBody ? column * lastBodyWidth : 0; + + return callback(x + xOffset + column * columnGap, stackY, column, row, lastBody, i); + }); + }; + + /** + * This has now moved to the [newtonsCradle example](https://github.com/liabru/matter-js/blob/master/examples/newtonsCradle.js), follow that instead as this function is deprecated here. + * @deprecated moved to newtonsCradle example + * @method newtonsCradle + * @param {number} x Starting position in X. + * @param {number} y Starting position in Y. + * @param {number} number + * @param {number} size + * @param {number} length + * @return {composite} A new composite newtonsCradle body + */ + Composites.newtonsCradle = function(x, y, number, size, length) { + var newtonsCradle = Composite.create({ label: 'Newtons Cradle' }); + + for (var i = 0; i < number; i++) { + var separation = 1.9, + circle = Bodies.circle(x + i * (size * separation), y + length, size, + { inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }), + constraint = Constraint.create({ pointA: { x: x + i * (size * separation), y: y }, bodyB: circle }); + + Composite.addBody(newtonsCradle, circle); + Composite.addConstraint(newtonsCradle, constraint); + } + + return newtonsCradle; + }; + + /** + * This has now moved to the [car example](https://github.com/liabru/matter-js/blob/master/examples/car.js), follow that instead as this function is deprecated here. + * @deprecated moved to car example + * @method car + * @param {number} x Starting position in X. + * @param {number} y Starting position in Y. + * @param {number} width + * @param {number} height + * @param {number} wheelSize + * @return {composite} A new composite car body + */ + Composites.car = function(x, y, width, height, wheelSize) { + var group = Body.nextGroup(true), + wheelBase = 20, + wheelAOffset = -width * 0.5 + wheelBase, + wheelBOffset = width * 0.5 - wheelBase, + wheelYOffset = 0; + + var car = Composite.create({ label: 'Car' }), + body = Bodies.rectangle(x, y, width, height, { + collisionFilter: { + group: group + }, + chamfer: { + radius: height * 0.5 + }, + density: 0.0002 + }); + + var wheelA = Bodies.circle(x + wheelAOffset, y + wheelYOffset, wheelSize, { + collisionFilter: { + group: group + }, + friction: 0.8 + }); + + var wheelB = Bodies.circle(x + wheelBOffset, y + wheelYOffset, wheelSize, { + collisionFilter: { + group: group + }, + friction: 0.8 + }); + + var axelA = Constraint.create({ + bodyB: body, + pointB: { x: wheelAOffset, y: wheelYOffset }, + bodyA: wheelA, + stiffness: 1, + length: 0 + }); + + var axelB = Constraint.create({ + bodyB: body, + pointB: { x: wheelBOffset, y: wheelYOffset }, + bodyA: wheelB, + stiffness: 1, + length: 0 + }); + + Composite.addBody(car, body); + Composite.addBody(car, wheelA); + Composite.addBody(car, wheelB); + Composite.addConstraint(car, axelA); + Composite.addConstraint(car, axelB); + + return car; + }; + + /** + * This has now moved to the [softBody example](https://github.com/liabru/matter-js/blob/master/examples/softBody.js) + * and the [cloth example](https://github.com/liabru/matter-js/blob/master/examples/cloth.js), follow those instead as this function is deprecated here. + * @deprecated moved to softBody and cloth examples + * @method softBody + * @param {number} x Starting position in X. + * @param {number} y Starting position in Y. + * @param {number} columns + * @param {number} rows + * @param {number} columnGap + * @param {number} rowGap + * @param {boolean} crossBrace + * @param {number} particleRadius + * @param {} particleOptions + * @param {} constraintOptions + * @return {composite} A new composite softBody + */ + Composites.softBody = function(x, y, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) { + particleOptions = Common.extend({ inertia: Infinity }, particleOptions); + constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions); + + var softBody = Composites.stack(x, y, columns, rows, columnGap, rowGap, function(stackX, stackY) { + return Bodies.circle(stackX, stackY, particleRadius, particleOptions); + }); + + Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions); + + softBody.label = 'Soft Body'; + + return softBody; + }; + +})(); + + +/***/ }), + +/***/ 66615: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Axes` module contains methods for creating and manipulating sets of axes. +* +* @class Axes +*/ + +var Axes = {}; + +module.exports = Axes; + +var Vector = __webpack_require__(31725); +var Common = __webpack_require__(53402); + +(function() { + + /** + * Creates a new set of axes from the given vertices. + * @method fromVertices + * @param {vertices} vertices + * @return {axes} A new axes from the given vertices + */ + Axes.fromVertices = function(vertices) { + var axes = {}; + + // find the unique axes, using edge normal gradients + for (var i = 0; i < vertices.length; i++) { + var j = (i + 1) % vertices.length, + normal = Vector.normalise({ + x: vertices[j].y - vertices[i].y, + y: vertices[i].x - vertices[j].x + }), + gradient = (normal.y === 0) ? Infinity : (normal.x / normal.y); + + // limit precision + gradient = gradient.toFixed(3).toString(); + axes[gradient] = normal; + } + + return Common.values(axes); + }; + + /** + * Rotates a set of axes by the given angle. + * @method rotate + * @param {axes} axes + * @param {number} angle + */ + Axes.rotate = function(axes, angle) { + if (angle === 0) + return; + + var cos = Math.cos(angle), + sin = Math.sin(angle); + + for (var i = 0; i < axes.length; i++) { + var axis = axes[i], + xx; + xx = axis.x * cos - axis.y * sin; + axis.y = axis.x * sin + axis.y * cos; + axis.x = xx; + } + }; + +})(); + + +/***/ }), + +/***/ 15647: +/***/ ((module) => { + +/** +* The `Matter.Bounds` module contains methods for creating and manipulating axis-aligned bounding boxes (AABB). +* +* @class Bounds +*/ + +var Bounds = {}; + +module.exports = Bounds; + +(function() { + + /** + * Creates a new axis-aligned bounding box (AABB) for the given vertices. + * @method create + * @param {vertices} vertices + * @return {bounds} A new bounds object + */ + Bounds.create = function(vertices) { + var bounds = { + min: { x: 0, y: 0 }, + max: { x: 0, y: 0 } + }; + + if (vertices) + Bounds.update(bounds, vertices); + + return bounds; + }; + + /** + * Updates bounds using the given vertices and extends the bounds given a velocity. + * @method update + * @param {bounds} bounds + * @param {vertices} vertices + * @param {vector} velocity + */ + Bounds.update = function(bounds, vertices, velocity) { + bounds.min.x = Infinity; + bounds.max.x = -Infinity; + bounds.min.y = Infinity; + bounds.max.y = -Infinity; + + for (var i = 0; i < vertices.length; i++) { + var vertex = vertices[i]; + if (vertex.x > bounds.max.x) bounds.max.x = vertex.x; + if (vertex.x < bounds.min.x) bounds.min.x = vertex.x; + if (vertex.y > bounds.max.y) bounds.max.y = vertex.y; + if (vertex.y < bounds.min.y) bounds.min.y = vertex.y; + } + + if (velocity) { + if (velocity.x > 0) { + bounds.max.x += velocity.x; + } else { + bounds.min.x += velocity.x; + } + + if (velocity.y > 0) { + bounds.max.y += velocity.y; + } else { + bounds.min.y += velocity.y; + } + } + }; + + /** + * Returns true if the bounds contains the given point. + * @method contains + * @param {bounds} bounds + * @param {vector} point + * @return {boolean} True if the bounds contain the point, otherwise false + */ + Bounds.contains = function(bounds, point) { + return point.x >= bounds.min.x && point.x <= bounds.max.x + && point.y >= bounds.min.y && point.y <= bounds.max.y; + }; + + /** + * Returns true if the two bounds intersect. + * @method overlaps + * @param {bounds} boundsA + * @param {bounds} boundsB + * @return {boolean} True if the bounds overlap, otherwise false + */ + Bounds.overlaps = function(boundsA, boundsB) { + return (boundsA.min.x <= boundsB.max.x && boundsA.max.x >= boundsB.min.x + && boundsA.max.y >= boundsB.min.y && boundsA.min.y <= boundsB.max.y); + }; + + /** + * Translates the bounds by the given vector. + * @method translate + * @param {bounds} bounds + * @param {vector} vector + */ + Bounds.translate = function(bounds, vector) { + bounds.min.x += vector.x; + bounds.max.x += vector.x; + bounds.min.y += vector.y; + bounds.max.y += vector.y; + }; + + /** + * Shifts the bounds to the given position. + * @method shift + * @param {bounds} bounds + * @param {vector} position + */ + Bounds.shift = function(bounds, position) { + var deltaX = bounds.max.x - bounds.min.x, + deltaY = bounds.max.y - bounds.min.y; + + bounds.min.x = position.x; + bounds.max.x = position.x + deltaX; + bounds.min.y = position.y; + bounds.max.y = position.y + deltaY; + }; + + /** + * Returns a translation vector that wraps the `objectBounds` inside the `bounds`. + * @method wrap + * @param {bounds} objectBounds The bounds of the object to wrap inside the bounds. + * @param {bounds} bounds The bounds to wrap the body inside. + * @param {number} [padding=0] - An amount added to the boundary. + * @returns {?Matter.Vector} A translation vector (only if wrapping is required). + */ + Bounds.wrap = function(objectBounds, bounds, padding) { + var x = null, + y = null; + + if (typeof bounds.min.x !== 'undefined' && typeof bounds.max.x !== 'undefined') { + if (objectBounds.min.x > bounds.max.x) { + x = bounds.min.x - objectBounds.max.x; + } else if (objectBounds.max.x < bounds.min.x) { + x = bounds.max.x - objectBounds.min.x; + } + } + + if (typeof bounds.min.y !== 'undefined' && typeof bounds.max.y !== 'undefined') { + if (objectBounds.min.y > bounds.max.y) { + y = bounds.min.y - objectBounds.max.y; + } else if (objectBounds.max.y < bounds.min.y) { + y = bounds.max.y - objectBounds.min.y; + } + } + + if (x !== null || y !== null) { + return { + x: x || 0, + y: y || 0 + }; + } + }; + +})(); + + +/***/ }), + +/***/ 74058: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Svg` module contains methods for converting SVG images into an array of vector points. +* +* To use this module you also need the SVGPathSeg polyfill: https://github.com/progers/pathseg +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Svg +*/ + +var Svg = {}; + +module.exports = Svg; + +var Bounds = __webpack_require__(15647); +var Common = __webpack_require__(53402); + +(function() { + + /** + * Converts an SVG path into an array of vector points. + * If the input path forms a concave shape, you must decompose the result into convex parts before use. + * See `Bodies.fromVertices` which provides support for this. + * Note that this function is not guaranteed to support complex paths (such as those with holes). + * You must load the `pathseg.js` polyfill on newer browsers. + * @method pathToVertices + * @param {SVGPathElement} path + * @param {Number} [sampleLength=15] + * @return {Vector[]} points + */ + Svg.pathToVertices = function(path, sampleLength) { + if (typeof window !== 'undefined' && !('SVGPathSeg' in window)) { + Common.warn('Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.'); + } + + // https://github.com/wout/svg.topoly.js/blob/master/svg.topoly.js + var i, il, total, point, segment, segments, + segmentsQueue, lastSegment, + lastPoint, segmentIndex, points = [], + lx, ly, length = 0, x = 0, y = 0; + + sampleLength = sampleLength || 15; + + var addPoint = function(px, py, pathSegType) { + // all odd-numbered path types are relative except PATHSEG_CLOSEPATH (1) + var isRelative = pathSegType % 2 === 1 && pathSegType > 1; + + // when the last point doesn't equal the current point add the current point + if (!lastPoint || px != lastPoint.x || py != lastPoint.y) { + if (lastPoint && isRelative) { + lx = lastPoint.x; + ly = lastPoint.y; + } else { + lx = 0; + ly = 0; + } + + var point = { + x: lx + px, + y: ly + py + }; + + // set last point + if (isRelative || !lastPoint) { + lastPoint = point; + } + + points.push(point); + + x = lx + px; + y = ly + py; + } + }; + + var addSegmentPoint = function(segment) { + var segType = segment.pathSegTypeAsLetter.toUpperCase(); + + // skip path ends + if (segType === 'Z') + return; + + // map segment to x and y + switch (segType) { + + case 'M': + case 'L': + case 'T': + case 'C': + case 'S': + case 'Q': + x = segment.x; + y = segment.y; + break; + case 'H': + x = segment.x; + break; + case 'V': + y = segment.y; + break; + } + + addPoint(x, y, segment.pathSegType); + }; + + // ensure path is absolute + Svg._svgPathToAbsolute(path); + + // get total length + total = path.getTotalLength(); + + // queue segments + segments = []; + for (i = 0; i < path.pathSegList.numberOfItems; i += 1) + segments.push(path.pathSegList.getItem(i)); + + segmentsQueue = segments.concat(); + + // sample through path + while (length < total) { + // get segment at position + segmentIndex = path.getPathSegAtLength(length); + segment = segments[segmentIndex]; + + // new segment + if (segment != lastSegment) { + while (segmentsQueue.length && segmentsQueue[0] != segment) + addSegmentPoint(segmentsQueue.shift()); + + lastSegment = segment; + } + + // add points in between when curving + // TODO: adaptive sampling + switch (segment.pathSegTypeAsLetter.toUpperCase()) { + + case 'C': + case 'T': + case 'S': + case 'Q': + case 'A': + point = path.getPointAtLength(length); + addPoint(point.x, point.y, 0); + break; + + } + + // increment by sample value + length += sampleLength; + } + + // add remaining segments not passed by sampling + for (i = 0, il = segmentsQueue.length; i < il; ++i) + addSegmentPoint(segmentsQueue[i]); + + return points; + }; + + Svg._svgPathToAbsolute = function(path) { + // http://phrogz.net/convert-svg-path-to-all-absolute-commands + // Copyright (c) Gavin Kistner + // http://phrogz.net/js/_ReuseLicense.txt + // Modifications: tidy formatting and naming + var x0, y0, x1, y1, x2, y2, segs = path.pathSegList, + x = 0, y = 0, len = segs.numberOfItems; + + for (var i = 0; i < len; ++i) { + var seg = segs.getItem(i), + segType = seg.pathSegTypeAsLetter; + + if (/[MLHVCSQTA]/.test(segType)) { + if ('x' in seg) x = seg.x; + if ('y' in seg) y = seg.y; + } else { + if ('x1' in seg) x1 = x + seg.x1; + if ('x2' in seg) x2 = x + seg.x2; + if ('y1' in seg) y1 = y + seg.y1; + if ('y2' in seg) y2 = y + seg.y2; + if ('x' in seg) x += seg.x; + if ('y' in seg) y += seg.y; + + switch (segType) { + + case 'm': + segs.replaceItem(path.createSVGPathSegMovetoAbs(x, y), i); + break; + case 'l': + segs.replaceItem(path.createSVGPathSegLinetoAbs(x, y), i); + break; + case 'h': + segs.replaceItem(path.createSVGPathSegLinetoHorizontalAbs(x), i); + break; + case 'v': + segs.replaceItem(path.createSVGPathSegLinetoVerticalAbs(y), i); + break; + case 'c': + segs.replaceItem(path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i); + break; + case 's': + segs.replaceItem(path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i); + break; + case 'q': + segs.replaceItem(path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i); + break; + case 't': + segs.replaceItem(path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i); + break; + case 'a': + segs.replaceItem(path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle, seg.largeArcFlag, seg.sweepFlag), i); + break; + case 'z': + case 'Z': + x = x0; + y = y0; + break; + + } + } + + if (segType == 'M' || segType == 'm') { + x0 = x; + y0 = y; + } + } + }; + +})(); + +/***/ }), + +/***/ 31725: +/***/ ((module) => { + +/** +* The `Matter.Vector` module contains methods for creating and manipulating vectors. +* Vectors are the basis of all the geometry related operations in the engine. +* A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`. +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Vector +*/ + +// TODO: consider params for reusing vector objects + +var Vector = {}; + +module.exports = Vector; + +(function() { + + /** + * Creates a new vector. + * @method create + * @param {number} x + * @param {number} y + * @return {vector} A new vector + */ + Vector.create = function(x, y) { + return { x: x || 0, y: y || 0 }; + }; + + /** + * Returns a new vector with `x` and `y` copied from the given `vector`. + * @method clone + * @param {vector} vector + * @return {vector} A new cloned vector + */ + Vector.clone = function(vector) { + return { x: vector.x, y: vector.y }; + }; + + /** + * Returns the magnitude (length) of a vector. + * @method magnitude + * @param {vector} vector + * @return {number} The magnitude of the vector + */ + Vector.magnitude = function(vector) { + return Math.sqrt((vector.x * vector.x) + (vector.y * vector.y)); + }; + + /** + * Returns the magnitude (length) of a vector (therefore saving a `sqrt` operation). + * @method magnitudeSquared + * @param {vector} vector + * @return {number} The squared magnitude of the vector + */ + Vector.magnitudeSquared = function(vector) { + return (vector.x * vector.x) + (vector.y * vector.y); + }; + + /** + * Rotates the vector about (0, 0) by specified angle. + * @method rotate + * @param {vector} vector + * @param {number} angle + * @param {vector} [output] + * @return {vector} The vector rotated about (0, 0) + */ + Vector.rotate = function(vector, angle, output) { + var cos = Math.cos(angle), sin = Math.sin(angle); + if (!output) output = {}; + var x = vector.x * cos - vector.y * sin; + output.y = vector.x * sin + vector.y * cos; + output.x = x; + return output; + }; + + /** + * Rotates the vector about a specified point by specified angle. + * @method rotateAbout + * @param {vector} vector + * @param {number} angle + * @param {vector} point + * @param {vector} [output] + * @return {vector} A new vector rotated about the point + */ + Vector.rotateAbout = function(vector, angle, point, output) { + var cos = Math.cos(angle), sin = Math.sin(angle); + if (!output) output = {}; + var x = point.x + ((vector.x - point.x) * cos - (vector.y - point.y) * sin); + output.y = point.y + ((vector.x - point.x) * sin + (vector.y - point.y) * cos); + output.x = x; + return output; + }; + + /** + * Normalises a vector (such that its magnitude is `1`). + * @method normalise + * @param {vector} vector + * @return {vector} A new vector normalised + */ + Vector.normalise = function(vector) { + var magnitude = Vector.magnitude(vector); + if (magnitude === 0) + return { x: 0, y: 0 }; + return { x: vector.x / magnitude, y: vector.y / magnitude }; + }; + + /** + * Returns the dot-product of two vectors. + * @method dot + * @param {vector} vectorA + * @param {vector} vectorB + * @return {number} The dot product of the two vectors + */ + Vector.dot = function(vectorA, vectorB) { + return (vectorA.x * vectorB.x) + (vectorA.y * vectorB.y); + }; + + /** + * Returns the cross-product of two vectors. + * @method cross + * @param {vector} vectorA + * @param {vector} vectorB + * @return {number} The cross product of the two vectors + */ + Vector.cross = function(vectorA, vectorB) { + return (vectorA.x * vectorB.y) - (vectorA.y * vectorB.x); + }; + + /** + * Returns the cross-product of three vectors. + * @method cross3 + * @param {vector} vectorA + * @param {vector} vectorB + * @param {vector} vectorC + * @return {number} The cross product of the three vectors + */ + Vector.cross3 = function(vectorA, vectorB, vectorC) { + return (vectorB.x - vectorA.x) * (vectorC.y - vectorA.y) - (vectorB.y - vectorA.y) * (vectorC.x - vectorA.x); + }; + + /** + * Adds the two vectors. + * @method add + * @param {vector} vectorA + * @param {vector} vectorB + * @param {vector} [output] + * @return {vector} A new vector of vectorA and vectorB added + */ + Vector.add = function(vectorA, vectorB, output) { + if (!output) output = {}; + output.x = vectorA.x + vectorB.x; + output.y = vectorA.y + vectorB.y; + return output; + }; + + /** + * Subtracts the two vectors. + * @method sub + * @param {vector} vectorA + * @param {vector} vectorB + * @param {vector} [output] + * @return {vector} A new vector of vectorA and vectorB subtracted + */ + Vector.sub = function(vectorA, vectorB, output) { + if (!output) output = {}; + output.x = vectorA.x - vectorB.x; + output.y = vectorA.y - vectorB.y; + return output; + }; + + /** + * Multiplies a vector and a scalar. + * @method mult + * @param {vector} vector + * @param {number} scalar + * @return {vector} A new vector multiplied by scalar + */ + Vector.mult = function(vector, scalar) { + return { x: vector.x * scalar, y: vector.y * scalar }; + }; + + /** + * Divides a vector and a scalar. + * @method div + * @param {vector} vector + * @param {number} scalar + * @return {vector} A new vector divided by scalar + */ + Vector.div = function(vector, scalar) { + return { x: vector.x / scalar, y: vector.y / scalar }; + }; + + /** + * Returns the perpendicular vector. Set `negate` to true for the perpendicular in the opposite direction. + * @method perp + * @param {vector} vector + * @param {bool} [negate=false] + * @return {vector} The perpendicular vector + */ + Vector.perp = function(vector, negate) { + negate = negate === true ? -1 : 1; + return { x: negate * -vector.y, y: negate * vector.x }; + }; + + /** + * Negates both components of a vector such that it points in the opposite direction. + * @method neg + * @param {vector} vector + * @return {vector} The negated vector + */ + Vector.neg = function(vector) { + return { x: -vector.x, y: -vector.y }; + }; + + /** + * Returns the angle between the vector `vectorB - vectorA` and the x-axis in radians. + * @method angle + * @param {vector} vectorA + * @param {vector} vectorB + * @return {number} The angle in radians + */ + Vector.angle = function(vectorA, vectorB) { + return Math.atan2(vectorB.y - vectorA.y, vectorB.x - vectorA.x); + }; + + /** + * Temporary vector pool (not thread-safe). + * @property _temp + * @type {vector[]} + * @private + */ + Vector._temp = [ + Vector.create(), Vector.create(), + Vector.create(), Vector.create(), + Vector.create(), Vector.create() + ]; + +})(); + +/***/ }), + +/***/ 41598: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices. +* A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`. +* A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull). +* +* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). +* +* @class Vertices +*/ + +var Vertices = {}; + +module.exports = Vertices; + +var Vector = __webpack_require__(31725); +var Common = __webpack_require__(53402); + +(function() { + + /** + * Creates a new set of `Matter.Body` compatible vertices. + * The `points` argument accepts an array of `Matter.Vector` points orientated around the origin `(0, 0)`, for example: + * + * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }] + * + * The `Vertices.create` method returns a new array of vertices, which are similar to Matter.Vector objects, + * but with some additional references required for efficient collision detection routines. + * + * Vertices must be specified in clockwise order. + * + * Note that the `body` argument is not optional, a `Matter.Body` reference must be provided. + * + * @method create + * @param {vector[]} points + * @param {body} body + */ + Vertices.create = function(points, body) { + var vertices = []; + + for (var i = 0; i < points.length; i++) { + var point = points[i], + vertex = { + x: point.x, + y: point.y, + index: i, + body: body, + isInternal: false + }; + + vertices.push(vertex); + } + + return vertices; + }; + + /** + * Parses a string containing ordered x y pairs separated by spaces (and optionally commas), + * into a `Matter.Vertices` object for the given `Matter.Body`. + * For parsing SVG paths, see `Svg.pathToVertices`. + * @method fromPath + * @param {string} path + * @param {body} body + * @return {vertices} vertices + */ + Vertices.fromPath = function(path, body) { + var pathPattern = /L?\s*([-\d.e]+)[\s,]*([-\d.e]+)*/ig, + points = []; + + path.replace(pathPattern, function(match, x, y) { + points.push({ x: parseFloat(x), y: parseFloat(y) }); + }); + + return Vertices.create(points, body); + }; + + /** + * Returns the centre (centroid) of the set of vertices. + * @method centre + * @param {vertices} vertices + * @return {vector} The centre point + */ + Vertices.centre = function(vertices) { + var area = Vertices.area(vertices, true), + centre = { x: 0, y: 0 }, + cross, + temp, + j; + + for (var i = 0; i < vertices.length; i++) { + j = (i + 1) % vertices.length; + cross = Vector.cross(vertices[i], vertices[j]); + temp = Vector.mult(Vector.add(vertices[i], vertices[j]), cross); + centre = Vector.add(centre, temp); + } + + return Vector.div(centre, 6 * area); + }; + + /** + * Returns the average (mean) of the set of vertices. + * @method mean + * @param {vertices} vertices + * @return {vector} The average point + */ + Vertices.mean = function(vertices) { + var average = { x: 0, y: 0 }; + + for (var i = 0; i < vertices.length; i++) { + average.x += vertices[i].x; + average.y += vertices[i].y; + } + + return Vector.div(average, vertices.length); + }; + + /** + * Returns the area of the set of vertices. + * @method area + * @param {vertices} vertices + * @param {bool} signed + * @return {number} The area + */ + Vertices.area = function(vertices, signed) { + var area = 0, + j = vertices.length - 1; + + for (var i = 0; i < vertices.length; i++) { + area += (vertices[j].x - vertices[i].x) * (vertices[j].y + vertices[i].y); + j = i; + } + + if (signed) + return area / 2; + + return Math.abs(area) / 2; + }; + + /** + * Returns the moment of inertia (second moment of area) of the set of vertices given the total mass. + * @method inertia + * @param {vertices} vertices + * @param {number} mass + * @return {number} The polygon's moment of inertia + */ + Vertices.inertia = function(vertices, mass) { + var numerator = 0, + denominator = 0, + v = vertices, + cross, + j; + + // find the polygon's moment of inertia, using second moment of area + // from equations at http://www.physicsforums.com/showthread.php?t=25293 + for (var n = 0; n < v.length; n++) { + j = (n + 1) % v.length; + cross = Math.abs(Vector.cross(v[j], v[n])); + numerator += cross * (Vector.dot(v[j], v[j]) + Vector.dot(v[j], v[n]) + Vector.dot(v[n], v[n])); + denominator += cross; + } + + return (mass / 6) * (numerator / denominator); + }; + + /** + * Translates the set of vertices in-place. + * @method translate + * @param {vertices} vertices + * @param {vector} vector + * @param {number} scalar + */ + Vertices.translate = function(vertices, vector, scalar) { + scalar = typeof scalar !== 'undefined' ? scalar : 1; + + var verticesLength = vertices.length, + translateX = vector.x * scalar, + translateY = vector.y * scalar, + i; + + for (i = 0; i < verticesLength; i++) { + vertices[i].x += translateX; + vertices[i].y += translateY; + } + + return vertices; + }; + + /** + * Rotates the set of vertices in-place. + * @method rotate + * @param {vertices} vertices + * @param {number} angle + * @param {vector} point + */ + Vertices.rotate = function(vertices, angle, point) { + if (angle === 0) + return; + + var cos = Math.cos(angle), + sin = Math.sin(angle), + pointX = point.x, + pointY = point.y, + verticesLength = vertices.length, + vertex, + dx, + dy, + i; + + for (i = 0; i < verticesLength; i++) { + vertex = vertices[i]; + dx = vertex.x - pointX; + dy = vertex.y - pointY; + vertex.x = pointX + (dx * cos - dy * sin); + vertex.y = pointY + (dx * sin + dy * cos); + } + + return vertices; + }; + + /** + * Returns `true` if the `point` is inside the set of `vertices`. + * @method contains + * @param {vertices} vertices + * @param {vector} point + * @return {boolean} True if the vertices contains point, otherwise false + */ + Vertices.contains = function(vertices, point) { + var pointX = point.x, + pointY = point.y, + verticesLength = vertices.length, + vertex = vertices[verticesLength - 1], + nextVertex; + + for (var i = 0; i < verticesLength; i++) { + nextVertex = vertices[i]; + + if ((pointX - vertex.x) * (nextVertex.y - vertex.y) + + (pointY - vertex.y) * (vertex.x - nextVertex.x) > 0) { + return false; + } + + vertex = nextVertex; + } + + return true; + }; + + /** + * Scales the vertices from a point (default is centre) in-place. + * @method scale + * @param {vertices} vertices + * @param {number} scaleX + * @param {number} scaleY + * @param {vector} point + */ + Vertices.scale = function(vertices, scaleX, scaleY, point) { + if (scaleX === 1 && scaleY === 1) + return vertices; + + point = point || Vertices.centre(vertices); + + var vertex, + delta; + + for (var i = 0; i < vertices.length; i++) { + vertex = vertices[i]; + delta = Vector.sub(vertex, point); + vertices[i].x = point.x + delta.x * scaleX; + vertices[i].y = point.y + delta.y * scaleY; + } + + return vertices; + }; + + /** + * Chamfers a set of vertices by giving them rounded corners, returns a new set of vertices. + * The radius parameter is a single number or an array to specify the radius for each vertex. + * @method chamfer + * @param {vertices} vertices + * @param {number[]} radius + * @param {number} quality + * @param {number} qualityMin + * @param {number} qualityMax + */ + Vertices.chamfer = function(vertices, radius, quality, qualityMin, qualityMax) { + if (typeof radius === 'number') { + radius = [radius]; + } else { + radius = radius || [8]; + } + + // quality defaults to -1, which is auto + quality = (typeof quality !== 'undefined') ? quality : -1; + qualityMin = qualityMin || 2; + qualityMax = qualityMax || 14; + + var newVertices = []; + + for (var i = 0; i < vertices.length; i++) { + var prevVertex = vertices[i - 1 >= 0 ? i - 1 : vertices.length - 1], + vertex = vertices[i], + nextVertex = vertices[(i + 1) % vertices.length], + currentRadius = radius[i < radius.length ? i : radius.length - 1]; + + if (currentRadius === 0) { + newVertices.push(vertex); + continue; + } + + var prevNormal = Vector.normalise({ + x: vertex.y - prevVertex.y, + y: prevVertex.x - vertex.x + }); + + var nextNormal = Vector.normalise({ + x: nextVertex.y - vertex.y, + y: vertex.x - nextVertex.x + }); + + var diagonalRadius = Math.sqrt(2 * Math.pow(currentRadius, 2)), + radiusVector = Vector.mult(Common.clone(prevNormal), currentRadius), + midNormal = Vector.normalise(Vector.mult(Vector.add(prevNormal, nextNormal), 0.5)), + scaledVertex = Vector.sub(vertex, Vector.mult(midNormal, diagonalRadius)); + + var precision = quality; + + if (quality === -1) { + // automatically decide precision + precision = Math.pow(currentRadius, 0.32) * 1.75; + } + + precision = Common.clamp(precision, qualityMin, qualityMax); + + // use an even value for precision, more likely to reduce axes by using symmetry + if (precision % 2 === 1) + precision += 1; + + var alpha = Math.acos(Vector.dot(prevNormal, nextNormal)), + theta = alpha / precision; + + for (var j = 0; j < precision; j++) { + newVertices.push(Vector.add(Vector.rotate(radiusVector, theta * j), scaledVertex)); + } + } + + return newVertices; + }; + + /** + * Sorts the input vertices into clockwise order in place. + * @method clockwiseSort + * @param {vertices} vertices + * @return {vertices} vertices + */ + Vertices.clockwiseSort = function(vertices) { + var centre = Vertices.mean(vertices); + + vertices.sort(function(vertexA, vertexB) { + return Vector.angle(centre, vertexA) - Vector.angle(centre, vertexB); + }); + + return vertices; + }; + + /** + * Returns true if the vertices form a convex shape (vertices must be in clockwise order). + * @method isConvex + * @param {vertices} vertices + * @return {bool} `true` if the `vertices` are convex, `false` if not (or `null` if not computable). + */ + Vertices.isConvex = function(vertices) { + // http://paulbourke.net/geometry/polygonmesh/ + // Copyright (c) Paul Bourke (use permitted) + + var flag = 0, + n = vertices.length, + i, + j, + k, + z; + + if (n < 3) + return null; + + for (i = 0; i < n; i++) { + j = (i + 1) % n; + k = (i + 2) % n; + z = (vertices[j].x - vertices[i].x) * (vertices[k].y - vertices[j].y); + z -= (vertices[j].y - vertices[i].y) * (vertices[k].x - vertices[j].x); + + if (z < 0) { + flag |= 1; + } else if (z > 0) { + flag |= 2; + } + + if (flag === 3) { + return false; + } + } + + if (flag !== 0){ + return true; + } else { + return null; + } + }; + + /** + * Returns the convex hull of the input vertices as a new array of points. + * @method hull + * @param {vertices} vertices + * @return [vertex] vertices + */ + Vertices.hull = function(vertices) { + // http://geomalgorithms.com/a10-_hull-1.html + + var upper = [], + lower = [], + vertex, + i; + + // sort vertices on x-axis (y-axis for ties) + vertices = vertices.slice(0); + vertices.sort(function(vertexA, vertexB) { + var dx = vertexA.x - vertexB.x; + return dx !== 0 ? dx : vertexA.y - vertexB.y; + }); + + // build lower hull + for (i = 0; i < vertices.length; i += 1) { + vertex = vertices[i]; + + while (lower.length >= 2 + && Vector.cross3(lower[lower.length - 2], lower[lower.length - 1], vertex) <= 0) { + lower.pop(); + } + + lower.push(vertex); + } + + // build upper hull + for (i = vertices.length - 1; i >= 0; i -= 1) { + vertex = vertices[i]; + + while (upper.length >= 2 + && Vector.cross3(upper[upper.length - 2], upper[upper.length - 1], vertex) <= 0) { + upper.pop(); + } + + upper.push(vertex); + } + + // concatenation of the lower and upper hulls gives the convex hull + // omit last points because they are repeated at the beginning of the other list + upper.pop(); + lower.pop(); + + return upper.concat(lower); + }; + +})(); + + +/***/ }), + +/***/ 55973: +/***/ ((module) => { + +/** + * @author Stefan Hedman (http://steffe.se) + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// v0.3.0 + +module.exports = { + decomp: polygonDecomp, + quickDecomp: polygonQuickDecomp, + isSimple: polygonIsSimple, + removeCollinearPoints: polygonRemoveCollinearPoints, + removeDuplicatePoints: polygonRemoveDuplicatePoints, + makeCCW: polygonMakeCCW +}; + +/** + * Compute the intersection between two lines. + * @static + * @method lineInt + * @param {Array} l1 Line vector 1 + * @param {Array} l2 Line vector 2 + * @param {Number} precision Precision to use when checking if the lines are parallel + * @return {Array} The intersection point. + */ +function lineInt(l1,l2,precision){ + precision = precision || 0; + var i = [0,0]; // point + var a1, b1, c1, a2, b2, c2, det; // scalars + a1 = l1[1][1] - l1[0][1]; + b1 = l1[0][0] - l1[1][0]; + c1 = a1 * l1[0][0] + b1 * l1[0][1]; + a2 = l2[1][1] - l2[0][1]; + b2 = l2[0][0] - l2[1][0]; + c2 = a2 * l2[0][0] + b2 * l2[0][1]; + det = a1 * b2 - a2*b1; + if (!scalar_eq(det, 0, precision)) { // lines are not parallel + i[0] = (b2 * c1 - b1 * c2) / det; + i[1] = (a1 * c2 - a2 * c1) / det; + } + return i; +} + +/** + * Checks if two line segments intersects. + * @method segmentsIntersect + * @param {Array} p1 The start vertex of the first line segment. + * @param {Array} p2 The end vertex of the first line segment. + * @param {Array} q1 The start vertex of the second line segment. + * @param {Array} q2 The end vertex of the second line segment. + * @return {Boolean} True if the two line segments intersect + */ +function lineSegmentsIntersect(p1, p2, q1, q2){ + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + var da = q2[0] - q1[0]; + var db = q2[1] - q1[1]; + + // segments are parallel + if((da*dy - db*dx) === 0){ + return false; + } + + var s = (dx * (q1[1] - p1[1]) + dy * (p1[0] - q1[0])) / (da * dy - db * dx); + var t = (da * (p1[1] - q1[1]) + db * (q1[0] - p1[0])) / (db * dx - da * dy); + + return (s>=0 && s<=1 && t>=0 && t<=1); +} + +/** + * Get the area of a triangle spanned by the three given points. Note that the area will be negative if the points are not given in counter-clockwise order. + * @static + * @method area + * @param {Array} a + * @param {Array} b + * @param {Array} c + * @return {Number} + */ +function triangleArea(a,b,c){ + return (((b[0] - a[0])*(c[1] - a[1]))-((c[0] - a[0])*(b[1] - a[1]))); +} + +function isLeft(a,b,c){ + return triangleArea(a,b,c) > 0; +} + +function isLeftOn(a,b,c) { + return triangleArea(a, b, c) >= 0; +} + +function isRight(a,b,c) { + return triangleArea(a, b, c) < 0; +} + +function isRightOn(a,b,c) { + return triangleArea(a, b, c) <= 0; +} + +var tmpPoint1 = [], + tmpPoint2 = []; + +/** + * Check if three points are collinear + * @method collinear + * @param {Array} a + * @param {Array} b + * @param {Array} c + * @param {Number} [thresholdAngle=0] Threshold angle to use when comparing the vectors. The function will return true if the angle between the resulting vectors is less than this value. Use zero for max precision. + * @return {Boolean} + */ +function collinear(a,b,c,thresholdAngle) { + if(!thresholdAngle){ + return triangleArea(a, b, c) === 0; + } else { + var ab = tmpPoint1, + bc = tmpPoint2; + + ab[0] = b[0]-a[0]; + ab[1] = b[1]-a[1]; + bc[0] = c[0]-b[0]; + bc[1] = c[1]-b[1]; + + var dot = ab[0]*bc[0] + ab[1]*bc[1], + magA = Math.sqrt(ab[0]*ab[0] + ab[1]*ab[1]), + magB = Math.sqrt(bc[0]*bc[0] + bc[1]*bc[1]), + angle = Math.acos(dot/(magA*magB)); + return angle < thresholdAngle; + } +} + +function sqdist(a,b){ + var dx = b[0] - a[0]; + var dy = b[1] - a[1]; + return dx * dx + dy * dy; +} + +/** + * Get a vertex at position i. It does not matter if i is out of bounds, this function will just cycle. + * @method at + * @param {Number} i + * @return {Array} + */ +function polygonAt(polygon, i){ + var s = polygon.length; + return polygon[i < 0 ? i % s + s : i % s]; +} + +/** + * Clear the polygon data + * @method clear + * @return {Array} + */ +function polygonClear(polygon){ + polygon.length = 0; +} + +/** + * Append points "from" to "to"-1 from an other polygon "poly" onto this one. + * @method append + * @param {Polygon} poly The polygon to get points from. + * @param {Number} from The vertex index in "poly". + * @param {Number} to The end vertex index in "poly". Note that this vertex is NOT included when appending. + * @return {Array} + */ +function polygonAppend(polygon, poly, from, to){ + for(var i=from; i v[br][0])) { + br = i; + } + } + + // reverse poly if clockwise + if (!isLeft(polygonAt(polygon, br - 1), polygonAt(polygon, br), polygonAt(polygon, br + 1))) { + polygonReverse(polygon); + return true; + } else { + return false; + } +} + +/** + * Reverse the vertices in the polygon + * @method reverse + */ +function polygonReverse(polygon){ + var tmp = []; + var N = polygon.length; + for(var i=0; i!==N; i++){ + tmp.push(polygon.pop()); + } + for(var i=0; i!==N; i++){ + polygon[i] = tmp[i]; + } +} + +/** + * Check if a point in the polygon is a reflex point + * @method isReflex + * @param {Number} i + * @return {Boolean} + */ +function polygonIsReflex(polygon, i){ + return isRight(polygonAt(polygon, i - 1), polygonAt(polygon, i), polygonAt(polygon, i + 1)); +} + +var tmpLine1=[], + tmpLine2=[]; + +/** + * Check if two vertices in the polygon can see each other + * @method canSee + * @param {Number} a Vertex index 1 + * @param {Number} b Vertex index 2 + * @return {Boolean} + */ +function polygonCanSee(polygon, a,b) { + var p, dist, l1=tmpLine1, l2=tmpLine2; + + if (isLeftOn(polygonAt(polygon, a + 1), polygonAt(polygon, a), polygonAt(polygon, b)) && isRightOn(polygonAt(polygon, a - 1), polygonAt(polygon, a), polygonAt(polygon, b))) { + return false; + } + dist = sqdist(polygonAt(polygon, a), polygonAt(polygon, b)); + for (var i = 0; i !== polygon.length; ++i) { // for each edge + if ((i + 1) % polygon.length === a || i === a){ // ignore incident edges + continue; + } + if (isLeftOn(polygonAt(polygon, a), polygonAt(polygon, b), polygonAt(polygon, i + 1)) && isRightOn(polygonAt(polygon, a), polygonAt(polygon, b), polygonAt(polygon, i))) { // if diag intersects an edge + l1[0] = polygonAt(polygon, a); + l1[1] = polygonAt(polygon, b); + l2[0] = polygonAt(polygon, i); + l2[1] = polygonAt(polygon, i + 1); + p = lineInt(l1,l2); + if (sqdist(polygonAt(polygon, a), p) < dist) { // if edge is blocking visibility to b + return false; + } + } + } + + return true; +} + +/** + * Check if two vertices in the polygon can see each other + * @method canSee2 + * @param {Number} a Vertex index 1 + * @param {Number} b Vertex index 2 + * @return {Boolean} + */ +function polygonCanSee2(polygon, a,b) { + // for each edge + for (var i = 0; i !== polygon.length; ++i) { + // ignore incident edges + if (i === a || i === b || (i + 1) % polygon.length === a || (i + 1) % polygon.length === b){ + continue; + } + if( lineSegmentsIntersect(polygonAt(polygon, a), polygonAt(polygon, b), polygonAt(polygon, i), polygonAt(polygon, i+1)) ){ + return false; + } + } + return true; +} + +/** + * Copy the polygon from vertex i to vertex j. + * @method copy + * @param {Number} i + * @param {Number} j + * @param {Polygon} [targetPoly] Optional target polygon to save in. + * @return {Polygon} The resulting copy. + */ +function polygonCopy(polygon, i,j,targetPoly){ + var p = targetPoly || []; + polygonClear(p); + if (i < j) { + // Insert all vertices from i to j + for(var k=i; k<=j; k++){ + p.push(polygon[k]); + } + + } else { + + // Insert vertices 0 to j + for(var k=0; k<=j; k++){ + p.push(polygon[k]); + } + + // Insert vertices i to end + for(var k=i; k 0){ + return polygonSlice(polygon, edges); + } else { + return [polygon]; + } +} + +/** + * Slices the polygon given one or more cut edges. If given one, this function will return two polygons (false on failure). If many, an array of polygons. + * @method slice + * @param {Array} cutEdges A list of edges, as returned by .getCutEdges() + * @return {Array} + */ +function polygonSlice(polygon, cutEdges){ + if(cutEdges.length === 0){ + return [polygon]; + } + if(cutEdges instanceof Array && cutEdges.length && cutEdges[0] instanceof Array && cutEdges[0].length===2 && cutEdges[0][0] instanceof Array){ + + var polys = [polygon]; + + for(var i=0; i maxlevel){ + console.warn("quickDecomp: max level ("+maxlevel+") reached."); + return result; + } + + for (var i = 0; i < polygon.length; ++i) { + if (polygonIsReflex(poly, i)) { + reflexVertices.push(poly[i]); + upperDist = lowerDist = Number.MAX_VALUE; + + + for (var j = 0; j < polygon.length; ++j) { + if (isLeft(polygonAt(poly, i - 1), polygonAt(poly, i), polygonAt(poly, j)) && isRightOn(polygonAt(poly, i - 1), polygonAt(poly, i), polygonAt(poly, j - 1))) { // if line intersects with an edge + p = getIntersectionPoint(polygonAt(poly, i - 1), polygonAt(poly, i), polygonAt(poly, j), polygonAt(poly, j - 1)); // find the point of intersection + if (isRight(polygonAt(poly, i + 1), polygonAt(poly, i), p)) { // make sure it's inside the poly + d = sqdist(poly[i], p); + if (d < lowerDist) { // keep only the closest intersection + lowerDist = d; + lowerInt = p; + lowerIndex = j; + } + } + } + if (isLeft(polygonAt(poly, i + 1), polygonAt(poly, i), polygonAt(poly, j + 1)) && isRightOn(polygonAt(poly, i + 1), polygonAt(poly, i), polygonAt(poly, j))) { + p = getIntersectionPoint(polygonAt(poly, i + 1), polygonAt(poly, i), polygonAt(poly, j), polygonAt(poly, j + 1)); + if (isLeft(polygonAt(poly, i - 1), polygonAt(poly, i), p)) { + d = sqdist(poly[i], p); + if (d < upperDist) { + upperDist = d; + upperInt = p; + upperIndex = j; + } + } + } + } + + // if there are no vertices to connect to, choose a point in the middle + if (lowerIndex === (upperIndex + 1) % polygon.length) { + //console.log("Case 1: Vertex("+i+"), lowerIndex("+lowerIndex+"), upperIndex("+upperIndex+"), poly.size("+polygon.length+")"); + p[0] = (lowerInt[0] + upperInt[0]) / 2; + p[1] = (lowerInt[1] + upperInt[1]) / 2; + steinerPoints.push(p); + + if (i < upperIndex) { + //lowerPoly.insert(lowerPoly.end(), poly.begin() + i, poly.begin() + upperIndex + 1); + polygonAppend(lowerPoly, poly, i, upperIndex+1); + lowerPoly.push(p); + upperPoly.push(p); + if (lowerIndex !== 0){ + //upperPoly.insert(upperPoly.end(), poly.begin() + lowerIndex, poly.end()); + polygonAppend(upperPoly, poly,lowerIndex,poly.length); + } + //upperPoly.insert(upperPoly.end(), poly.begin(), poly.begin() + i + 1); + polygonAppend(upperPoly, poly,0,i+1); + } else { + if (i !== 0){ + //lowerPoly.insert(lowerPoly.end(), poly.begin() + i, poly.end()); + polygonAppend(lowerPoly, poly,i,poly.length); + } + //lowerPoly.insert(lowerPoly.end(), poly.begin(), poly.begin() + upperIndex + 1); + polygonAppend(lowerPoly, poly,0,upperIndex+1); + lowerPoly.push(p); + upperPoly.push(p); + //upperPoly.insert(upperPoly.end(), poly.begin() + lowerIndex, poly.begin() + i + 1); + polygonAppend(upperPoly, poly,lowerIndex,i+1); + } + } else { + // connect to the closest point within the triangle + //console.log("Case 2: Vertex("+i+"), closestIndex("+closestIndex+"), poly.size("+polygon.length+")\n"); + + if (lowerIndex > upperIndex) { + upperIndex += polygon.length; + } + closestDist = Number.MAX_VALUE; + + if(upperIndex < lowerIndex){ + return result; + } + + for (var j = lowerIndex; j <= upperIndex; ++j) { + if ( + isLeftOn(polygonAt(poly, i - 1), polygonAt(poly, i), polygonAt(poly, j)) && + isRightOn(polygonAt(poly, i + 1), polygonAt(poly, i), polygonAt(poly, j)) + ) { + d = sqdist(polygonAt(poly, i), polygonAt(poly, j)); + if (d < closestDist && polygonCanSee2(poly, i, j)) { + closestDist = d; + closestIndex = j % polygon.length; + } + } + } + + if (i < closestIndex) { + polygonAppend(lowerPoly, poly,i,closestIndex+1); + if (closestIndex !== 0){ + polygonAppend(upperPoly, poly,closestIndex,v.length); + } + polygonAppend(upperPoly, poly,0,i+1); + } else { + if (i !== 0){ + polygonAppend(lowerPoly, poly,i,v.length); + } + polygonAppend(lowerPoly, poly,0,closestIndex+1); + polygonAppend(upperPoly, poly,closestIndex,i+1); + } + } + + // solve smallest poly first + if (lowerPoly.length < upperPoly.length) { + polygonQuickDecomp(lowerPoly,result,reflexVertices,steinerPoints,delta,maxlevel,level); + polygonQuickDecomp(upperPoly,result,reflexVertices,steinerPoints,delta,maxlevel,level); + } else { + polygonQuickDecomp(upperPoly,result,reflexVertices,steinerPoints,delta,maxlevel,level); + polygonQuickDecomp(lowerPoly,result,reflexVertices,steinerPoints,delta,maxlevel,level); + } + + return result; + } + } + result.push(polygon); + + return result; +} + +/** + * Remove collinear points in the polygon. + * @method removeCollinearPoints + * @param {Number} [precision] The threshold angle to use when determining whether two edges are collinear. Use zero for finest precision. + * @return {Number} The number of points removed + */ +function polygonRemoveCollinearPoints(polygon, precision){ + var num = 0; + for(var i=polygon.length-1; polygon.length>3 && i>=0; --i){ + if(collinear(polygonAt(polygon, i-1),polygonAt(polygon, i),polygonAt(polygon, i+1),precision)){ + // Remove the middle point + polygon.splice(i%polygon.length,1); + num++; + } + } + return num; +} + +/** + * Remove duplicate points in the polygon. + * @method removeDuplicatePoints + * @param {Number} [precision] The threshold to use when determining whether two points are the same. Use zero for best precision. + */ +function polygonRemoveDuplicatePoints(polygon, precision){ + for(var i=polygon.length-1; i>=1; --i){ + var pi = polygon[i]; + for(var j=i-1; j>=0; --j){ + if(points_eq(pi, polygon[j], precision)){ + polygon.splice(i,1); + continue; + } + } + } +} + +/** + * Check if two scalars are equal + * @static + * @method eq + * @param {Number} a + * @param {Number} b + * @param {Number} [precision] + * @return {Boolean} + */ +function scalar_eq(a,b,precision){ + precision = precision || 0; + return Math.abs(a-b) <= precision; +} + +/** + * Check if two points are equal + * @static + * @method points_eq + * @param {Array} a + * @param {Array} b + * @param {Number} [precision] + * @return {Boolean} + */ +function points_eq(a,b,precision){ + return scalar_eq(a[0],b[0],precision) && scalar_eq(a[1],b[1],precision); +} + + +/***/ }), + +/***/ 52018: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* @author Richard Davey +* @copyright 2013-2025 Phaser Studio Inc. +* @license {@link https://github.com/photonstorm/phaser3-plugin-template/blob/master/LICENSE|MIT License} +*/ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A Global Plugin is installed just once into the Game owned Plugin Manager. + * It can listen for Game events and respond to them. + * + * @class BasePlugin + * @memberof Phaser.Plugins + * @constructor + * @since 3.8.0 + * + * @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Plugin Manager. + */ +var BasePlugin = new Class({ + + initialize: + + function BasePlugin (pluginManager) + { + /** + * A handy reference to the Plugin Manager that is responsible for this plugin. + * Can be used as a route to gain access to game systems and events. + * + * @name Phaser.Plugins.BasePlugin#pluginManager + * @type {Phaser.Plugins.PluginManager} + * @protected + * @since 3.8.0 + */ + this.pluginManager = pluginManager; + + /** + * A reference to the Game instance this plugin is running under. + * + * @name Phaser.Plugins.BasePlugin#game + * @type {Phaser.Game} + * @protected + * @since 3.8.0 + */ + this.game = pluginManager.game; + }, + + /** + * The PluginManager calls this method on a Global Plugin when the plugin is first instantiated. + * It will never be called again on this instance. + * In here you can set-up whatever you need for this plugin to run. + * If a plugin is set to automatically start then `BasePlugin.start` will be called immediately after this. + * On a Scene Plugin, this method is never called. Use {@link Phaser.Plugins.ScenePlugin#boot} instead. + * + * @method Phaser.Plugins.BasePlugin#init + * @since 3.8.0 + * + * @param {?any} [data] - A value specified by the user, if any, from the `data` property of the plugin's configuration object (if started at game boot) or passed in the PluginManager's `install` method (if started manually). + */ + init: function () + { + }, + + /** + * The PluginManager calls this method on a Global Plugin when the plugin is started. + * If a plugin is stopped, and then started again, this will get called again. + * Typically called immediately after `BasePlugin.init`. + * On a Scene Plugin, this method is never called. + * + * @method Phaser.Plugins.BasePlugin#start + * @since 3.8.0 + */ + start: function () + { + // Here are the game-level events you can listen to. + // At the very least you should offer a destroy handler for when the game closes down. + + // var eventEmitter = this.game.events; + + // eventEmitter.once('destroy', this.gameDestroy, this); + // eventEmitter.on('pause', this.gamePause, this); + // eventEmitter.on('resume', this.gameResume, this); + // eventEmitter.on('resize', this.gameResize, this); + // eventEmitter.on('prestep', this.gamePreStep, this); + // eventEmitter.on('step', this.gameStep, this); + // eventEmitter.on('poststep', this.gamePostStep, this); + // eventEmitter.on('prerender', this.gamePreRender, this); + // eventEmitter.on('postrender', this.gamePostRender, this); + }, + + /** + * The PluginManager calls this method on a Global Plugin when the plugin is stopped. + * The game code has requested that your plugin stop doing whatever it does. + * It is now considered as 'inactive' by the PluginManager. + * Handle that process here (i.e. stop listening for events, etc) + * If the plugin is started again then `BasePlugin.start` will be called again. + * On a Scene Plugin, this method is never called. + * + * @method Phaser.Plugins.BasePlugin#stop + * @since 3.8.0 + */ + stop: function () + { + }, + + /** + * Game instance has been destroyed. + * You must release everything in here, all references, all objects, free it all up. + * + * @method Phaser.Plugins.BasePlugin#destroy + * @since 3.8.0 + */ + destroy: function () + { + this.pluginManager = null; + this.game = null; + this.scene = null; + this.systems = null; + } + +}); + +module.exports = BasePlugin; + + +/***/ }), + +/***/ 42363: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Default Plugins. + * + * @namespace Phaser.Plugins.DefaultPlugins + * @memberof Phaser.Plugins + * @since 3.0.0 + */ + +var DefaultPlugins = { + + /** + * These are the Global Managers that are created by the Phaser.Game instance. + * They are referenced from Scene.Systems so that plugins can use them. + * + * @name Phaser.Plugins.DefaultPlugins.Global + * @type {array} + * @since 3.0.0 + */ + Global: [ + + 'game', + 'anims', + 'cache', + 'plugins', + 'registry', + 'scale', + 'sound', + 'textures', + 'renderer' + + ], + + /** + * These are the core plugins that are installed into every Scene.Systems instance, no matter what. + * They are optionally exposed in the Scene as well (see the InjectionMap for details) + * + * They are created in the order in which they appear in this array and EventEmitter is always first. + * + * @name Phaser.Plugins.DefaultPlugins.CoreScene + * @type {array} + * @since 3.0.0 + */ + CoreScene: [ + + 'EventEmitter', + + 'CameraManager', + 'GameObjectCreator', + 'GameObjectFactory', + 'ScenePlugin', + 'DisplayList', + 'UpdateList' + + ], + + /** + * These plugins are created in Scene.Systems in addition to the CoreScenePlugins. + * + * You can elect not to have these plugins by either creating a DefaultPlugins object as part + * of the Game Config, by creating a Plugins object as part of a Scene Config, or by modifying this array + * and building your own bundle. + * + * They are optionally exposed in the Scene as well (see the InjectionMap for details) + * + * They are always created in the order in which they appear in the array. + * + * @name Phaser.Plugins.DefaultPlugins.DefaultScene + * @type {array} + * @since 3.0.0 + */ + DefaultScene: [ + + 'Clock', + 'DataManagerPlugin', + 'InputPlugin', + 'Loader', + 'TweenManager', + 'LightsPlugin' + + ] + +}; + +if (typeof PLUGIN_CAMERA3D) +{ + DefaultPlugins.DefaultScene.push('CameraManager3D'); +} + +if (typeof PLUGIN_FBINSTANT) +{ + DefaultPlugins.Global.push('facebook'); +} + +module.exports = DefaultPlugins; + + +/***/ }), + +/***/ 37277: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Contains the plugins that Phaser uses globally and locally. +// These are the source objects, not instantiated. +var corePlugins = {}; + +// Contains the plugins that the dev has loaded into their game +// These are the source objects, not instantiated. +var customPlugins = {}; + +var PluginCache = {}; + +/** + * @namespace Phaser.Plugins.PluginCache + */ + +/** + * Static method called directly by the Core internal Plugins. + * Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin) + * Plugin is the object to instantiate to create the plugin + * Mapping is what the plugin is injected into the Scene.Systems as (i.e. input) + * + * @method Phaser.Plugins.PluginCache.register + * @since 3.8.0 + * + * @param {string} key - A reference used to get this plugin from the plugin cache. + * @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated. + * @param {string} mapping - If this plugin is to be injected into the Scene Systems, this is the property key map used. + * @param {boolean} [custom=false] - Core Scene plugin or a Custom Scene plugin? + */ +PluginCache.register = function (key, plugin, mapping, custom) +{ + if (custom === undefined) { custom = false; } + + corePlugins[key] = { plugin: plugin, mapping: mapping, custom: custom }; +}; + +/** + * Stores a custom plugin in the global plugin cache. + * The key must be unique, within the scope of the cache. + * + * @method Phaser.Plugins.PluginCache.registerCustom + * @since 3.8.0 + * + * @param {string} key - A reference used to get this plugin from the plugin cache. + * @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated. + * @param {string} mapping - If this plugin is to be injected into the Scene Systems, this is the property key map used. + * @param {?any} data - A value to be passed to the plugin's `init` method. + */ +PluginCache.registerCustom = function (key, plugin, mapping, data) +{ + customPlugins[key] = { plugin: plugin, mapping: mapping, data: data }; +}; + +/** + * Checks if the given key is already being used in the core plugin cache. + * + * @method Phaser.Plugins.PluginCache.hasCore + * @since 3.8.0 + * + * @param {string} key - The key to check for. + * + * @return {boolean} `true` if the key is already in use in the core cache, otherwise `false`. + */ +PluginCache.hasCore = function (key) +{ + return corePlugins.hasOwnProperty(key); +}; + +/** + * Checks if the given key is already being used in the custom plugin cache. + * + * @method Phaser.Plugins.PluginCache.hasCustom + * @since 3.8.0 + * + * @param {string} key - The key to check for. + * + * @return {boolean} `true` if the key is already in use in the custom cache, otherwise `false`. + */ +PluginCache.hasCustom = function (key) +{ + return customPlugins.hasOwnProperty(key); +}; + +/** + * Returns the core plugin object from the cache based on the given key. + * + * @method Phaser.Plugins.PluginCache.getCore + * @since 3.8.0 + * + * @param {string} key - The key of the core plugin to get. + * + * @return {Phaser.Types.Plugins.CorePluginContainer} The core plugin object. + */ +PluginCache.getCore = function (key) +{ + return corePlugins[key]; +}; + +/** + * Returns the custom plugin object from the cache based on the given key. + * + * @method Phaser.Plugins.PluginCache.getCustom + * @since 3.8.0 + * + * @param {string} key - The key of the custom plugin to get. + * + * @return {Phaser.Types.Plugins.CustomPluginContainer} The custom plugin object. + */ +PluginCache.getCustom = function (key) +{ + return customPlugins[key]; +}; + +/** + * Returns an object from the custom cache based on the given key that can be instantiated. + * + * @method Phaser.Plugins.PluginCache.getCustomClass + * @since 3.8.0 + * + * @param {string} key - The key of the custom plugin to get. + * + * @return {function} The custom plugin object. + */ +PluginCache.getCustomClass = function (key) +{ + return (customPlugins.hasOwnProperty(key)) ? customPlugins[key].plugin : null; +}; + +/** + * Removes a core plugin based on the given key. + * + * @method Phaser.Plugins.PluginCache.remove + * @since 3.8.0 + * + * @param {string} key - The key of the core plugin to remove. + */ +PluginCache.remove = function (key) +{ + if (corePlugins.hasOwnProperty(key)) + { + delete corePlugins[key]; + } +}; + +/** + * Removes a custom plugin based on the given key. + * + * @method Phaser.Plugins.PluginCache.removeCustom + * @since 3.8.0 + * + * @param {string} key - The key of the custom plugin to remove. + */ +PluginCache.removeCustom = function (key) +{ + if (customPlugins.hasOwnProperty(key)) + { + delete customPlugins[key]; + } +}; + +/** + * Removes all Core Plugins. + * + * This includes all of the internal system plugins that Phaser needs, like the Input Plugin and Loader Plugin. + * So be sure you only call this if you do not wish to run Phaser again. + * + * @method Phaser.Plugins.PluginCache.destroyCorePlugins + * @since 3.12.0 + */ +PluginCache.destroyCorePlugins = function () +{ + for (var key in corePlugins) + { + if (corePlugins.hasOwnProperty(key)) + { + delete corePlugins[key]; + } + } +}; + +/** + * Removes all Custom Plugins. + * + * @method Phaser.Plugins.PluginCache.destroyCustomPlugins + * @since 3.12.0 + */ +PluginCache.destroyCustomPlugins = function () +{ + for (var key in customPlugins) + { + if (customPlugins.hasOwnProperty(key)) + { + delete customPlugins[key]; + } + } +}; + +module.exports = PluginCache; + + +/***/ }), + +/***/ 77332: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GameEvents = __webpack_require__(8443); +var EventEmitter = __webpack_require__(50792); +var FileTypesManager = __webpack_require__(74099); +var GameObjectCreator = __webpack_require__(44603); +var GameObjectFactory = __webpack_require__(39429); +var GetFastValue = __webpack_require__(95540); +var PluginCache = __webpack_require__(37277); +var Remove = __webpack_require__(72905); +var CONST = __webpack_require__(8054); + +/** + * @classdesc + * The PluginManager is responsible for installing and adding plugins to Phaser. + * + * It is a global system and therefore belongs to the Game instance, not a specific Scene. + * + * It works in conjunction with the PluginCache. Core internal plugins automatically register themselves + * with the Cache, but it's the Plugin Manager that is responsible for injecting them into the Scenes. + * + * There are two types of plugin: + * + * 1. A Global Plugin + * 2. A Scene Plugin + * + * A Global Plugin is a plugin that lives within the Plugin Manager rather than a Scene. You can get + * access to it by calling `PluginManager.get` and providing a key. Any Scene that requests a plugin in + * this way will get access to the same plugin instance, allowing you to use a single plugin across + * multiple Scenes. + * + * A Scene Plugin is a plugin dedicated to running within a Scene. These are different to Global Plugins + * in that their instances do not live within the Plugin Manager, but within the Scene Systems class instead. + * Also, every Scene created is given its own unique instance of a Scene Plugin. Examples of core Scene + * Plugins include the Input Plugin, the Tween Plugin and the physics Plugins. + * + * You can add a plugin to Phaser in three different ways: + * + * 1. Preload it + * 2. Include it in your source code and install it via the Game Config + * 3. Include it in your source code and install it within a Scene + * + * For examples of all of these approaches please see the Phaser 3 Examples Repo `plugins` folder. + * + * For information on creating your own plugin please see the Phaser 3 Plugin Template. + * + * @class PluginManager + * @memberof Phaser.Plugins + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - The game instance that owns this Plugin Manager. + */ +var PluginManager = new Class({ + + Extends: EventEmitter, + + initialize: + + function PluginManager (game) + { + EventEmitter.call(this); + + /** + * The game instance that owns this Plugin Manager. + * + * @name Phaser.Plugins.PluginManager#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game = game; + + /** + * The global plugins currently running and managed by this Plugin Manager. + * A plugin must have been started at least once in order to appear in this list. + * + * @name Phaser.Plugins.PluginManager#plugins + * @type {Phaser.Types.Plugins.GlobalPlugin[]} + * @since 3.8.0 + */ + this.plugins = []; + + /** + * A list of plugin keys that should be installed into Scenes as well as the Core Plugins. + * + * @name Phaser.Plugins.PluginManager#scenePlugins + * @type {string[]} + * @since 3.8.0 + */ + this.scenePlugins = []; + + /** + * A temporary list of plugins to install when the game has booted. + * + * @name Phaser.Plugins.PluginManager#_pendingGlobal + * @private + * @type {array} + * @since 3.8.0 + */ + this._pendingGlobal = []; + + /** + * A temporary list of scene plugins to install when the game has booted. + * + * @name Phaser.Plugins.PluginManager#_pendingScene + * @private + * @type {array} + * @since 3.8.0 + */ + this._pendingScene = []; + + if (game.isBooted || game.config.renderType === CONST.HEADLESS) + { + this.boot(); + } + else + { + game.events.once(GameEvents.BOOT, this.boot, this); + } + }, + + /** + * Runs once the game has booted and installs all of the plugins configured in the Game Config. + * + * @method Phaser.Plugins.PluginManager#boot + * @protected + * @since 3.0.0 + */ + boot: function () + { + var i; + var entry; + var key; + var plugin; + var start; + var mapping; + var data; + var config = this.game.config; + + // Any plugins to install? + var list = config.installGlobalPlugins; + + // Any plugins added outside of the game config, but before the game booted? + list = list.concat(this._pendingGlobal); + + for (i = 0; i < list.length; i++) + { + entry = list[i]; + + // { key: 'TestPlugin', plugin: TestPlugin, start: true, mapping: 'test', data: { msg: 'The plugin is alive' } } + + key = GetFastValue(entry, 'key', null); + plugin = GetFastValue(entry, 'plugin', null); + start = GetFastValue(entry, 'start', false); + mapping = GetFastValue(entry, 'mapping', null); + data = GetFastValue(entry, 'data', null); + + if (key) + { + if (plugin) + { + this.install(key, plugin, start, mapping, data); + } + else + { + console.warn('Missing `plugin` for key: ' + key); + } + + } + } + + // Any scene plugins to install? + list = config.installScenePlugins; + + // Any plugins added outside of the game config, but before the game booted? + list = list.concat(this._pendingScene); + + for (i = 0; i < list.length; i++) + { + entry = list[i]; + + // { key: 'moveSpritePlugin', plugin: MoveSpritePlugin, , mapping: 'move' } + + key = GetFastValue(entry, 'key', null); + plugin = GetFastValue(entry, 'plugin', null); + mapping = GetFastValue(entry, 'mapping', null); + + if (key) + { + if (plugin) + { + this.installScenePlugin(key, plugin, mapping); + } + else + { + console.warn('Missing `plugin` for key: ' + key); + } + } + } + + this._pendingGlobal = []; + this._pendingScene = []; + + this.game.events.once(GameEvents.DESTROY, this.destroy, this); + }, + + /** + * Called by the Scene Systems class. Tells the plugin manager to install all Scene plugins into it. + * + * First it will install global references, i.e. references from the Game systems into the Scene Systems (and Scene if mapped.) + * Then it will install Core Scene Plugins followed by Scene Plugins registered with the PluginManager. + * Finally it will install any references to Global Plugins that have a Scene mapping property into the Scene itself. + * + * @method Phaser.Plugins.PluginManager#addToScene + * @protected + * @since 3.8.0 + * + * @param {Phaser.Scenes.Systems} sys - The Scene Systems class to install all the plugins in to. + * @param {array} globalPlugins - An array of global plugins to install. + * @param {array} scenePlugins - An array of scene plugins to install. + */ + addToScene: function (sys, globalPlugins, scenePlugins) + { + var i; + var pluginKey; + var pluginList; + var game = this.game; + var scene = sys.scene; + var map = sys.settings.map; + var isBooted = sys.settings.isBooted; + + // Reference the GlobalPlugins from Game into Scene.Systems + for (i = 0; i < globalPlugins.length; i++) + { + pluginKey = globalPlugins[i]; + + if (game[pluginKey]) + { + sys[pluginKey] = game[pluginKey]; + + // Scene level injection + if (map.hasOwnProperty(pluginKey)) + { + scene[map[pluginKey]] = sys[pluginKey]; + } + } + else if (pluginKey === 'game' && map.hasOwnProperty(pluginKey)) + { + scene[map[pluginKey]] = game; + } + } + + for (var s = 0; s < scenePlugins.length; s++) + { + pluginList = scenePlugins[s]; + + for (i = 0; i < pluginList.length; i++) + { + pluginKey = pluginList[i]; + + if (!PluginCache.hasCore(pluginKey)) + { + continue; + } + + var source = PluginCache.getCore(pluginKey); + + var mapKey = source.mapping; + + var plugin = new source.plugin(scene, this, mapKey); + + sys[mapKey] = plugin; + + // Scene level injection + if (source.custom) + { + scene[mapKey] = plugin; + } + else if (map.hasOwnProperty(mapKey)) + { + scene[map[mapKey]] = plugin; + } + + // Scene is already booted, usually because this method is being called at run-time, so boot the plugin + if (isBooted) + { + plugin.boot(); + } + } + } + + // And finally, inject any 'global scene plugins' + pluginList = this.plugins; + + for (i = 0; i < pluginList.length; i++) + { + var entry = pluginList[i]; + + if (entry.mapping) + { + scene[entry.mapping] = entry.plugin; + } + } + }, + + /** + * Called by the Scene Systems class. Returns a list of plugins to be installed. + * + * @method Phaser.Plugins.PluginManager#getDefaultScenePlugins + * @protected + * @since 3.8.0 + * + * @return {string[]} A list keys of all the Scene Plugins to install. + */ + getDefaultScenePlugins: function () + { + var list = this.game.config.defaultPlugins; + + // Merge in custom Scene plugins + list = list.concat(this.scenePlugins); + + return list; + }, + + /** + * Installs a new Scene Plugin into the Plugin Manager and optionally adds it + * to the given Scene as well. A Scene Plugin added to the manager in this way + * will be automatically installed into all new Scenes using the key and mapping given. + * + * The `key` property is what the plugin is injected into Scene.Systems as. + * The `mapping` property is optional, and if specified is what the plugin is installed into + * the Scene as. For example: + * + * ```javascript + * this.plugins.installScenePlugin('powerupsPlugin', pluginCode, 'powerups'); + * + * // and from within the scene: + * this.sys.powerupsPlugin; // key value + * this.powerups; // mapping value + * ``` + * + * This method is called automatically by Phaser if you install your plugins using either the + * Game Configuration object, or by preloading them via the Loader. + * + * @method Phaser.Plugins.PluginManager#installScenePlugin + * @since 3.8.0 + * + * @param {string} key - The property key that will be used to add this plugin to Scene.Systems. + * @param {function} plugin - The plugin code. This should be the non-instantiated version. + * @param {string} [mapping] - If this plugin is injected into the Phaser.Scene class, this is the property key to use. + * @param {Phaser.Scene} [addToScene] - Optionally automatically add this plugin to the given Scene. + * @param {boolean} [fromLoader=false] - Is this being called by the Loader? + */ + installScenePlugin: function (key, plugin, mapping, addToScene, fromLoader) + { + if (fromLoader === undefined) { fromLoader = false; } + + if (typeof plugin !== 'function') + { + console.warn('Invalid Scene Plugin: ' + key); + return; + } + + if (!PluginCache.hasCore(key)) + { + // Plugin is freshly loaded + PluginCache.register(key, plugin, mapping, true); + } + + if (this.scenePlugins.indexOf(key) === -1) + { + this.scenePlugins.push(key); + } + else if (!fromLoader && PluginCache.hasCore(key)) + { + // Plugin wasn't from the loader but already exists + console.warn('Scene Plugin key in use: ' + key); + return; + } + + if (addToScene) + { + var instance = new plugin(addToScene, this, key); + + addToScene.sys[key] = instance; + + if (mapping && mapping !== '') + { + addToScene[mapping] = instance; + } + + instance.boot(); + } + }, + + /** + * Installs a new Global Plugin into the Plugin Manager and optionally starts it running. + * A global plugin belongs to the Plugin Manager, rather than a specific Scene, and can be accessed + * and used by all Scenes in your game. + * + * The `key` property is what you use to access this plugin from the Plugin Manager. + * + * ```javascript + * this.plugins.install('powerupsPlugin', pluginCode); + * + * // and from within the scene: + * this.plugins.get('powerupsPlugin'); + * ``` + * + * This method is called automatically by Phaser if you install your plugins using either the + * Game Configuration object, or by preloading them via the Loader. + * + * The same plugin can be installed multiple times into the Plugin Manager by simply giving each + * instance its own unique key. + * + * @method Phaser.Plugins.PluginManager#install + * @since 3.8.0 + * + * @param {string} key - The unique handle given to this plugin within the Plugin Manager. + * @param {function} plugin - The plugin code. This should be the non-instantiated version. + * @param {boolean} [start=false] - Automatically start the plugin running? This is always `true` if you provide a mapping value. + * @param {string} [mapping] - If this plugin is injected into the Phaser.Scene class, this is the property key to use. + * @param {any} [data] - A value passed to the plugin's `init` method. + * + * @return {?Phaser.Plugins.BasePlugin} The plugin that was started, or `null` if `start` was false, or game isn't yet booted. + */ + install: function (key, plugin, start, mapping, data) + { + if (start === undefined) { start = false; } + if (mapping === undefined) { mapping = null; } + if (data === undefined) { data = null; } + + if (typeof plugin !== 'function') + { + console.warn('Invalid Plugin: ' + key); + return null; + } + + if (PluginCache.hasCustom(key)) + { + console.warn('Plugin key in use: ' + key); + return null; + } + + if (mapping !== null) + { + start = true; + } + + if (!this.game.isBooted) + { + this._pendingGlobal.push({ key: key, plugin: plugin, start: start, mapping: mapping, data: data }); + } + else + { + // Add it to the plugin store + PluginCache.registerCustom(key, plugin, mapping, data); + + if (start) + { + return this.start(key); + } + } + + return null; + }, + + /** + * Gets an index of a global plugin based on the given key. + * + * @method Phaser.Plugins.PluginManager#getIndex + * @protected + * @since 3.8.0 + * + * @param {string} key - The unique plugin key. + * + * @return {number} The index of the plugin within the plugins array. + */ + getIndex: function (key) + { + var list = this.plugins; + + for (var i = 0; i < list.length; i++) + { + var entry = list[i]; + + if (entry.key === key) + { + return i; + } + } + + return -1; + }, + + /** + * Gets a global plugin based on the given key. + * + * @method Phaser.Plugins.PluginManager#getEntry + * @protected + * @since 3.8.0 + * + * @param {string} key - The unique plugin key. + * + * @return {Phaser.Types.Plugins.GlobalPlugin} The plugin entry. + */ + getEntry: function (key) + { + var idx = this.getIndex(key); + + if (idx !== -1) + { + return this.plugins[idx]; + } + }, + + /** + * Checks if the given global plugin, based on its key, is active or not. + * + * @method Phaser.Plugins.PluginManager#isActive + * @since 3.8.0 + * + * @param {string} key - The unique plugin key. + * + * @return {boolean} `true` if the plugin is active, otherwise `false`. + */ + isActive: function (key) + { + var entry = this.getEntry(key); + + return (entry && entry.active); + }, + + /** + * Starts a global plugin running. + * + * If the plugin was previously active then calling `start` will reset it to an active state and then + * call its `start` method. + * + * If the plugin has never been run before a new instance of it will be created within the Plugin Manager, + * its active state set and then both of its `init` and `start` methods called, in that order. + * + * If the plugin is already running under the given key then nothing happens. + * + * @method Phaser.Plugins.PluginManager#start + * @since 3.8.0 + * + * @param {string} key - The key of the plugin to start. + * @param {string} [runAs] - Run the plugin under a new key. This allows you to run one plugin multiple times. + * + * @return {?Phaser.Plugins.BasePlugin} The plugin that was started, or `null` if invalid key given or plugin is already stopped. + */ + start: function (key, runAs) + { + if (runAs === undefined) { runAs = key; } + + var entry = this.getEntry(runAs); + + // Plugin already running under this key? + if (entry && !entry.active) + { + // It exists, we just need to start it up again + entry.active = true; + entry.plugin.start(); + } + else if (!entry) + { + entry = this.createEntry(key, runAs); + } + + return (entry) ? entry.plugin : null; + }, + + /** + * Creates a new instance of a global plugin, adds an entry into the plugins array and returns it. + * + * @method Phaser.Plugins.PluginManager#createEntry + * @private + * @since 3.9.0 + * + * @param {string} key - The key of the plugin to create an instance of. + * @param {string} [runAs] - Run the plugin under a new key. This allows you to run one plugin multiple times. + * + * @return {?Phaser.Plugins.BasePlugin} The plugin that was started, or `null` if invalid key given. + */ + createEntry: function (key, runAs) + { + var entry = PluginCache.getCustom(key); + + if (entry) + { + var instance = new entry.plugin(this); + + entry = { + key: runAs, + plugin: instance, + active: true, + mapping: entry.mapping, + data: entry.data + }; + + this.plugins.push(entry); + + instance.init(entry.data); + instance.start(); + } + + return entry; + }, + + /** + * Stops a global plugin from running. + * + * If the plugin is active then its active state will be set to false and the plugins `stop` method + * will be called. + * + * If the plugin is not already running, nothing will happen. + * + * @method Phaser.Plugins.PluginManager#stop + * @since 3.8.0 + * + * @param {string} key - The key of the plugin to stop. + * + * @return {this} The Plugin Manager. + */ + stop: function (key) + { + var entry = this.getEntry(key); + + if (entry && entry.active) + { + entry.active = false; + entry.plugin.stop(); + } + + return this; + }, + + /** + * Gets a global plugin from the Plugin Manager based on the given key and returns it. + * + * If it cannot find an active plugin based on the key, but there is one in the Plugin Cache with the same key, + * then it will create a new instance of the cached plugin and return that. + * + * @method Phaser.Plugins.PluginManager#get + * @since 3.8.0 + * + * @param {string} key - The key of the plugin to get. + * @param {boolean} [autoStart=true] - Automatically start a new instance of the plugin if found in the cache, but not actively running. + * + * @return {?(Phaser.Plugins.BasePlugin|function)} The plugin, or `null` if no plugin was found matching the key. + */ + get: function (key, autoStart) + { + if (autoStart === undefined) { autoStart = true; } + + var entry = this.getEntry(key); + + if (entry) + { + return entry.plugin; + } + else + { + var plugin = this.getClass(key); + + if (plugin && autoStart) + { + entry = this.createEntry(key, key); + + return (entry) ? entry.plugin : null; + } + else if (plugin) + { + return plugin; + } + } + + return null; + }, + + /** + * Returns the plugin class from the cache. + * Used internally by the Plugin Manager. + * + * @method Phaser.Plugins.PluginManager#getClass + * @since 3.8.0 + * + * @param {string} key - The key of the plugin to get. + * + * @return {Phaser.Plugins.BasePlugin} A Plugin object + */ + getClass: function (key) + { + return PluginCache.getCustomClass(key); + }, + + /** + * Removes a global plugin from the Plugin Manager and Plugin Cache. + * + * It is up to you to remove all references to this plugin that you may hold within your game code. + * + * @method Phaser.Plugins.PluginManager#removeGlobalPlugin + * @since 3.8.0 + * + * @param {string} key - The key of the plugin to remove. + */ + removeGlobalPlugin: function (key) + { + var entry = this.getEntry(key); + + if (entry) + { + Remove(this.plugins, entry); + } + + PluginCache.removeCustom(key); + }, + + /** + * Removes a scene plugin from the Plugin Manager and Plugin Cache. + * + * This will not remove the plugin from any active Scenes that are already using it. + * + * It is up to you to remove all references to this plugin that you may hold within your game code. + * + * @method Phaser.Plugins.PluginManager#removeScenePlugin + * @since 3.8.0 + * + * @param {string} key - The key of the plugin to remove. + */ + removeScenePlugin: function (key) + { + Remove(this.scenePlugins, key); + + PluginCache.remove(key); + }, + + /** + * Registers a new type of Game Object with the global Game Object Factory and / or Creator. + * This is usually called from within your Plugin code and is a helpful short-cut for creating + * new Game Objects. + * + * The key is the property that will be injected into the factories and used to create the + * Game Object. For example: + * + * ```javascript + * this.plugins.registerGameObject('clown', clownFactoryCallback, clownCreatorCallback); + * // later in your game code: + * this.add.clown(); + * this.make.clown(); + * ``` + * + * The callbacks are what are called when the factories try to create a Game Object + * matching the given key. It's important to understand that the callbacks are invoked within + * the context of the GameObjectFactory. In this context there are several properties available + * to use: + * + * this.scene - A reference to the Scene that owns the GameObjectFactory. + * this.displayList - A reference to the Display List the Scene owns. + * this.updateList - A reference to the Update List the Scene owns. + * + * See the GameObjectFactory and GameObjectCreator classes for more details. + * Any public property or method listed is available from your callbacks under `this`. + * + * @method Phaser.Plugins.PluginManager#registerGameObject + * @since 3.8.0 + * + * @param {string} key - The key of the Game Object that the given callbacks will create, i.e. `image`, `sprite`. + * @param {function} [factoryCallback] - The callback to invoke when the Game Object Factory is called. + * @param {function} [creatorCallback] - The callback to invoke when the Game Object Creator is called. + */ + registerGameObject: function (key, factoryCallback, creatorCallback) + { + if (factoryCallback) + { + GameObjectFactory.register(key, factoryCallback); + } + + if (creatorCallback) + { + GameObjectCreator.register(key, creatorCallback); + } + + return this; + }, + + /** + * Removes a previously registered Game Object from the global Game Object Factory and / or Creator. + * This is usually called from within your Plugin destruction code to help clean-up after your plugin has been removed. + * + * @method Phaser.Plugins.PluginManager#removeGameObject + * @since 3.19.0 + * + * @param {string} key - The key of the Game Object to be removed from the factories. + * @param {boolean} [removeFromFactory=true] - Should the Game Object be removed from the Game Object Factory? + * @param {boolean} [removeFromCreator=true] - Should the Game Object be removed from the Game Object Creator? + */ + removeGameObject: function (key, removeFromFactory, removeFromCreator) + { + if (removeFromFactory === undefined) { removeFromFactory = true; } + if (removeFromCreator === undefined) { removeFromCreator = true; } + + if (removeFromFactory) + { + GameObjectFactory.remove(key); + } + + if (removeFromCreator) + { + GameObjectCreator.remove(key); + } + + return this; + }, + + /** + * Registers a new file type with the global File Types Manager, making it available to all Loader + * Plugins created after this. + * + * This is usually called from within your Plugin code and is a helpful short-cut for creating + * new loader file types. + * + * The key is the property that will be injected into the Loader Plugin and used to load the + * files. For example: + * + * ```javascript + * this.plugins.registerFileType('wad', doomWadLoaderCallback); + * // later in your preload code: + * this.load.wad(); + * ``` + * + * The callback is what is called when the loader tries to load a file matching the given key. + * It's important to understand that the callback is invoked within + * the context of the LoaderPlugin. In this context there are several properties / methods available + * to use: + * + * this.addFile - A method to add the new file to the load queue. + * this.scene - The Scene that owns the Loader Plugin instance. + * + * See the LoaderPlugin class for more details. Any public property or method listed is available from + * your callback under `this`. + * + * @method Phaser.Plugins.PluginManager#registerFileType + * @since 3.8.0 + * + * @param {string} key - The key of the Game Object that the given callbacks will create, i.e. `image`, `sprite`. + * @param {function} callback - The callback to invoke when the Game Object Factory is called. + * @param {Phaser.Scene} [addToScene] - Optionally add this file type into the Loader Plugin owned by the given Scene. + */ + registerFileType: function (key, callback, addToScene) + { + FileTypesManager.register(key, callback); + + if (addToScene && addToScene.sys.load) + { + addToScene.sys.load[key] = callback; + } + }, + + /** + * Destroys this Plugin Manager and all associated plugins. + * It will iterate all plugins found and call their `destroy` methods. + * + * The PluginCache will remove all custom plugins. + * + * @method Phaser.Plugins.PluginManager#destroy + * @since 3.8.0 + */ + destroy: function () + { + for (var i = 0; i < this.plugins.length; i++) + { + this.plugins[i].plugin.destroy(); + } + + PluginCache.destroyCustomPlugins(); + + if (this.game.noReturn) + { + PluginCache.destroyCorePlugins(); + } + + this.game = null; + this.plugins = []; + this.scenePlugins = []; + } + +}); + +/* + * "Sometimes, the elegant implementation is just a function. + * Not a method. Not a class. Not a framework. Just a function." + * -- John Carmack + */ + +module.exports = PluginManager; + + +/***/ }), + +/***/ 45145: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** +* @author Richard Davey +* @copyright 2013-2025 Phaser Studio Inc. +* @license {@link https://github.com/photonstorm/phaser3-plugin-template/blob/master/LICENSE|MIT License} +*/ + +var BasePlugin = __webpack_require__(52018); +var Class = __webpack_require__(83419); +var SceneEvents = __webpack_require__(44594); + +/** + * @classdesc + * A Scene Level Plugin is installed into every Scene and belongs to that Scene. + * It can listen for Scene events and respond to them. + * It can map itself to a Scene property, or into the Scene Systems, or both. + * + * @class ScenePlugin + * @memberof Phaser.Plugins + * @extends Phaser.Plugins.BasePlugin + * @constructor + * @since 3.8.0 + * + * @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin. + * @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Plugin Manager. + * @param {string} pluginKey - The key under which this plugin has been installed into the Scene Systems. + */ +var ScenePlugin = new Class({ + + Extends: BasePlugin, + + initialize: + + function ScenePlugin (scene, pluginManager, pluginKey) + { + BasePlugin.call(this, pluginManager); + + /** + * A reference to the Scene that has installed this plugin. + * Only set if it's a Scene Plugin, otherwise `null`. + * This property is only set when the plugin is instantiated and added to the Scene, not before. + * You can use it during the `boot` method. + * + * @name Phaser.Plugins.ScenePlugin#scene + * @type {?Phaser.Scene} + * @protected + * @since 3.8.0 + */ + this.scene = scene; + + /** + * A reference to the Scene Systems of the Scene that has installed this plugin. + * Only set if it's a Scene Plugin, otherwise `null`. + * This property is only set when the plugin is instantiated and added to the Scene, not before. + * You can use it during the `boot` method. + * + * @name Phaser.Plugins.ScenePlugin#systems + * @type {?Phaser.Scenes.Systems} + * @protected + * @since 3.8.0 + */ + this.systems = scene.sys; + + /** + * The key under which this plugin was installed into the Scene Systems. + * + * This property is only set when the plugin is instantiated and added to the Scene, not before. + * You can use it during the `boot` method. + * + * @name Phaser.Plugins.ScenePlugin#pluginKey + * @type {string} + * @readonly + * @since 3.54.0 + */ + this.pluginKey = pluginKey; + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + }, + + /** + * This method is called when the Scene boots. It is only ever called once. + * + * By this point the plugin properties `scene` and `systems` will have already been set. + * + * In here you can listen for {@link Phaser.Scenes.Events Scene events} and set-up whatever you need for this plugin to run. + * Here are the Scene events you can listen to: + * + * - start + * - ready + * - preupdate + * - update + * - postupdate + * - resize + * - pause + * - resume + * - sleep + * - wake + * - transitioninit + * - transitionstart + * - transitioncomplete + * - transitionout + * - shutdown + * - destroy + * + * At the very least you should offer a destroy handler for when the Scene closes down, i.e: + * + * ```javascript + * var eventEmitter = this.systems.events; + * eventEmitter.once('destroy', this.sceneDestroy, this); + * ``` + * + * @method Phaser.Plugins.ScenePlugin#boot + * @since 3.8.0 + */ + boot: function () + { + }, + + /** + * Game instance has been destroyed. + * + * You must release everything in here, all references, all objects, free it all up. + * + * @method Phaser.Plugins.ScenePlugin#destroy + * @since 3.8.0 + */ + destroy: function () + { + this.pluginManager = null; + this.game = null; + this.scene = null; + this.systems = null; + } + +}); + +module.exports = ScenePlugin; + + +/***/ }), + +/***/ 18922: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Plugins + */ + +module.exports = { + + BasePlugin: __webpack_require__(52018), + DefaultPlugins: __webpack_require__(42363), + PluginCache: __webpack_require__(37277), + PluginManager: __webpack_require__(77332), + ScenePlugin: __webpack_require__(45145) + +}; + + +/***/ }), + +/***/ 63595: +/***/ (() => { + +// From https://github.com/ThaUnknown/rvfc-polyfill + +if (typeof HTMLVideoElement !== 'undefined' && !('requestVideoFrameCallback' in HTMLVideoElement.prototype) && 'getVideoPlaybackQuality' in HTMLVideoElement.prototype) +{ + HTMLVideoElement.prototype._rvfcpolyfillmap = {} + HTMLVideoElement.prototype.requestVideoFrameCallback = function (callback) { + const handle = performance.now() + const quality = this.getVideoPlaybackQuality() + const baseline = this.mozPresentedFrames || this.mozPaintedFrames || quality.totalVideoFrames - quality.droppedVideoFrames + + const check = (old, now) => { + const newquality = this.getVideoPlaybackQuality() + const presentedFrames = this.mozPresentedFrames || this.mozPaintedFrames || newquality.totalVideoFrames - newquality.droppedVideoFrames + if (presentedFrames > baseline) { + const processingDuration = this.mozFrameDelay || (newquality.totalFrameDelay - quality.totalFrameDelay) || 0 + const timediff = now - old // HighRes diff + callback(now, { + presentationTime: now + processingDuration * 1000, + expectedDisplayTime: now + timediff, + width: this.videoWidth, + height: this.videoHeight, + mediaTime: Math.max(0, this.currentTime || 0) + timediff / 1000, + presentedFrames, + processingDuration + }) + delete this._rvfcpolyfillmap[handle] + } else { + this._rvfcpolyfillmap[handle] = requestAnimationFrame(newer => check(now, newer)) + } + } + this._rvfcpolyfillmap[handle] = requestAnimationFrame(newer => check(handle, newer)) + return handle + } + + HTMLVideoElement.prototype.cancelVideoFrameCallback = function (handle) { + cancelAnimationFrame(this._rvfcpolyfillmap[handle]) + delete this._rvfcpolyfillmap[handle] + } +} + + +/***/ }), + +/***/ 10312: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Blend Modes. + * + * @namespace Phaser.BlendModes + * @since 3.0.0 + */ + +module.exports = { + + /** + * Skips the Blend Mode check in the renderer. + * + * @name Phaser.BlendModes.SKIP_CHECK + * @type {number} + * @const + * @since 3.0.0 + */ + SKIP_CHECK: -1, + + /** + * Normal blend mode. For Canvas and WebGL. + * This is the default setting and draws new shapes on top of the existing canvas content. + * + * @name Phaser.BlendModes.NORMAL + * @type {number} + * @const + * @since 3.0.0 + */ + NORMAL: 0, + + /** + * Add blend mode. For Canvas and WebGL. + * Where both shapes overlap the color is determined by adding color values. + * + * @name Phaser.BlendModes.ADD + * @type {number} + * @const + * @since 3.0.0 + */ + ADD: 1, + + /** + * Multiply blend mode. For Canvas and WebGL. + * The pixels are of the top layer are multiplied with the corresponding pixel of the bottom layer. A darker picture is the result. + * + * @name Phaser.BlendModes.MULTIPLY + * @type {number} + * @const + * @since 3.0.0 + */ + MULTIPLY: 2, + + /** + * Screen blend mode. For Canvas and WebGL. + * The pixels are inverted, multiplied, and inverted again. A lighter picture is the result (opposite of multiply) + * + * @name Phaser.BlendModes.SCREEN + * @type {number} + * @const + * @since 3.0.0 + */ + SCREEN: 3, + + /** + * Overlay blend mode. For Canvas only. + * A combination of multiply and screen. Dark parts on the base layer become darker, and light parts become lighter. + * + * @name Phaser.BlendModes.OVERLAY + * @type {number} + * @const + * @since 3.0.0 + */ + OVERLAY: 4, + + /** + * Darken blend mode. For Canvas only. + * Retains the darkest pixels of both layers. + * + * @name Phaser.BlendModes.DARKEN + * @type {number} + * @const + * @since 3.0.0 + */ + DARKEN: 5, + + /** + * Lighten blend mode. For Canvas only. + * Retains the lightest pixels of both layers. + * + * @name Phaser.BlendModes.LIGHTEN + * @type {number} + * @const + * @since 3.0.0 + */ + LIGHTEN: 6, + + /** + * Color Dodge blend mode. For Canvas only. + * Divides the bottom layer by the inverted top layer. + * + * @name Phaser.BlendModes.COLOR_DODGE + * @type {number} + * @const + * @since 3.0.0 + */ + COLOR_DODGE: 7, + + /** + * Color Burn blend mode. For Canvas only. + * Divides the inverted bottom layer by the top layer, and then inverts the result. + * + * @name Phaser.BlendModes.COLOR_BURN + * @type {number} + * @const + * @since 3.0.0 + */ + COLOR_BURN: 8, + + /** + * Hard Light blend mode. For Canvas only. + * A combination of multiply and screen like overlay, but with top and bottom layer swapped. + * + * @name Phaser.BlendModes.HARD_LIGHT + * @type {number} + * @const + * @since 3.0.0 + */ + HARD_LIGHT: 9, + + /** + * Soft Light blend mode. For Canvas only. + * A softer version of hard-light. Pure black or white does not result in pure black or white. + * + * @name Phaser.BlendModes.SOFT_LIGHT + * @type {number} + * @const + * @since 3.0.0 + */ + SOFT_LIGHT: 10, + + /** + * Difference blend mode. For Canvas only. + * Subtracts the bottom layer from the top layer or the other way round to always get a positive value. + * + * @name Phaser.BlendModes.DIFFERENCE + * @type {number} + * @const + * @since 3.0.0 + */ + DIFFERENCE: 11, + + /** + * Exclusion blend mode. For Canvas only. + * Like difference, but with lower contrast. + * + * @name Phaser.BlendModes.EXCLUSION + * @type {number} + * @const + * @since 3.0.0 + */ + EXCLUSION: 12, + + /** + * Hue blend mode. For Canvas only. + * Preserves the luma and chroma of the bottom layer, while adopting the hue of the top layer. + * + * @name Phaser.BlendModes.HUE + * @type {number} + * @const + * @since 3.0.0 + */ + HUE: 13, + + /** + * Saturation blend mode. For Canvas only. + * Preserves the luma and hue of the bottom layer, while adopting the chroma of the top layer. + * + * @name Phaser.BlendModes.SATURATION + * @type {number} + * @const + * @since 3.0.0 + */ + SATURATION: 14, + + /** + * Color blend mode. For Canvas only. + * Preserves the luma of the bottom layer, while adopting the hue and chroma of the top layer. + * + * @name Phaser.BlendModes.COLOR + * @type {number} + * @const + * @since 3.0.0 + */ + COLOR: 15, + + /** + * Luminosity blend mode. For Canvas only. + * Preserves the hue and chroma of the bottom layer, while adopting the luma of the top layer. + * + * @name Phaser.BlendModes.LUMINOSITY + * @type {number} + * @const + * @since 3.0.0 + */ + LUMINOSITY: 16, + + /** + * Alpha erase blend mode. For Canvas and WebGL. + * + * @name Phaser.BlendModes.ERASE + * @type {number} + * @const + * @since 3.0.0 + */ + ERASE: 17, + + /** + * Source-in blend mode. For Canvas only. + * The new shape is drawn only where both the new shape and the destination canvas overlap. Everything else is made transparent. + * + * @name Phaser.BlendModes.SOURCE_IN + * @type {number} + * @const + * @since 3.0.0 + */ + SOURCE_IN: 18, + + /** + * Source-out blend mode. For Canvas only. + * The new shape is drawn where it doesn't overlap the existing canvas content. + * + * @name Phaser.BlendModes.SOURCE_OUT + * @type {number} + * @const + * @since 3.0.0 + */ + SOURCE_OUT: 19, + + /** + * Source-out blend mode. For Canvas only. + * The new shape is only drawn where it overlaps the existing canvas content. + * + * @name Phaser.BlendModes.SOURCE_ATOP + * @type {number} + * @const + * @since 3.0.0 + */ + SOURCE_ATOP: 20, + + /** + * Destination-over blend mode. For Canvas only. + * New shapes are drawn behind the existing canvas content. + * + * @name Phaser.BlendModes.DESTINATION_OVER + * @type {number} + * @const + * @since 3.0.0 + */ + DESTINATION_OVER: 21, + + /** + * Destination-in blend mode. For Canvas only. + * The existing canvas content is kept where both the new shape and existing canvas content overlap. Everything else is made transparent. + * + * @name Phaser.BlendModes.DESTINATION_IN + * @type {number} + * @const + * @since 3.0.0 + */ + DESTINATION_IN: 22, + + /** + * Destination-out blend mode. For Canvas only. + * The existing content is kept where it doesn't overlap the new shape. + * + * @name Phaser.BlendModes.DESTINATION_OUT + * @type {number} + * @const + * @since 3.0.0 + */ + DESTINATION_OUT: 23, + + /** + * Destination-out blend mode. For Canvas only. + * The existing canvas is only kept where it overlaps the new shape. The new shape is drawn behind the canvas content. + * + * @name Phaser.BlendModes.DESTINATION_ATOP + * @type {number} + * @const + * @since 3.0.0 + */ + DESTINATION_ATOP: 24, + + /** + * Lighten blend mode. For Canvas only. + * Where both shapes overlap the color is determined by adding color values. + * + * @name Phaser.BlendModes.LIGHTER + * @type {number} + * @const + * @since 3.0.0 + */ + LIGHTER: 25, + + /** + * Copy blend mode. For Canvas only. + * Only the new shape is shown. + * + * @name Phaser.BlendModes.COPY + * @type {number} + * @const + * @since 3.0.0 + */ + COPY: 26, + + /** + * Xor blend mode. For Canvas only. + * Shapes are made transparent where both overlap and drawn normal everywhere else. + * + * @name Phaser.BlendModes.XOR + * @type {number} + * @const + * @since 3.0.0 + */ + XOR: 27 + +}; + + +/***/ }), + +/***/ 29795: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Scale Modes. + * + * @namespace Phaser.ScaleModes + * @since 3.0.0 + */ + +var ScaleModes = { + + /** + * Default Scale Mode (Linear). + * + * @name Phaser.ScaleModes.DEFAULT + * @type {number} + * @readonly + * @since 3.0.0 + */ + DEFAULT: 0, + + /** + * Linear Scale Mode. + * + * @name Phaser.ScaleModes.LINEAR + * @type {number} + * @readonly + * @since 3.0.0 + */ + LINEAR: 0, + + /** + * Nearest Scale Mode. + * + * @name Phaser.ScaleModes.NEAREST + * @type {number} + * @readonly + * @since 3.0.0 + */ + NEAREST: 1 + +}; + +module.exports = ScaleModes; + + +/***/ }), + +/***/ 68627: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CameraEvents = __webpack_require__(19715); +var CanvasSnapshot = __webpack_require__(32880); +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(8054); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(92503); +var GetBlendModes = __webpack_require__(56373); +var ScaleEvents = __webpack_require__(97480); +var TextureEvents = __webpack_require__(69442); +var GameEvents = __webpack_require__(8443); +var TransformMatrix = __webpack_require__(61340); + +/** + * @classdesc + * The Canvas Renderer is responsible for managing 2D canvas rendering contexts, + * including the one used by the Games canvas. It tracks the internal state of a + * given context and can renderer textured Game Objects to it, taking into + * account alpha, blending, and scaling. + * + * @class CanvasRenderer + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Renderer.Canvas + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Phaser Game instance that owns this renderer. + */ +var CanvasRenderer = new Class({ + + Extends: EventEmitter, + + initialize: + + function CanvasRenderer (game) + { + EventEmitter.call(this); + + var gameConfig = game.config; + + /** + * The local configuration settings of the CanvasRenderer. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#config + * @type {object} + * @since 3.0.0 + */ + this.config = { + clearBeforeRender: gameConfig.clearBeforeRender, + backgroundColor: gameConfig.backgroundColor, + antialias: gameConfig.antialias, + roundPixels: gameConfig.roundPixels, + transparent: gameConfig.transparent + }; + + /** + * The Phaser Game instance that owns this renderer. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game = game; + + /** + * A constant which allows the renderer to be easily identified as a Canvas Renderer. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#type + * @type {number} + * @since 3.0.0 + */ + this.type = CONST.CANVAS; + + /** + * The total number of Game Objects which were rendered in a frame. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#drawCount + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.drawCount = 0; + + /** + * The width of the canvas being rendered to. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#width + * @type {number} + * @since 3.0.0 + */ + this.width = 0; + + /** + * The height of the canvas being rendered to. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#height + * @type {number} + * @since 3.0.0 + */ + this.height = 0; + + /** + * The canvas element which the Game uses. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#gameCanvas + * @type {HTMLCanvasElement} + * @since 3.0.0 + */ + this.gameCanvas = game.canvas; + + var contextOptions = { + alpha: gameConfig.transparent, + desynchronized: gameConfig.desynchronized, + willReadFrequently: false + }; + + /** + * The canvas context used to render all Cameras in all Scenes during the game loop. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#gameContext + * @type {CanvasRenderingContext2D} + * @since 3.0.0 + */ + this.gameContext = (gameConfig.context) ? gameConfig.context : this.gameCanvas.getContext('2d', contextOptions); + + /** + * The canvas context currently used by the CanvasRenderer for all rendering operations. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#currentContext + * @type {CanvasRenderingContext2D} + * @since 3.0.0 + */ + this.currentContext = this.gameContext; + + /** + * Should the Canvas use Image Smoothing or not when drawing Sprites? + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#antialias + * @type {boolean} + * @since 3.20.0 + */ + this.antialias = gameConfig.antialias; + + /** + * The blend modes supported by the Canvas Renderer. + * + * This object maps the {@link Phaser.BlendModes} to canvas compositing operations. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#blendModes + * @type {array} + * @since 3.0.0 + */ + this.blendModes = GetBlendModes(); + + /** + * Details about the currently scheduled snapshot. + * + * If a non-null `callback` is set in this object, a snapshot of the canvas will be taken after the current frame is fully rendered. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#snapshotState + * @type {Phaser.Types.Renderer.Snapshot.SnapshotState} + * @since 3.16.0 + */ + this.snapshotState = { + x: 0, + y: 0, + width: 1, + height: 1, + getPixel: false, + callback: null, + type: 'image/png', + encoder: 0.92 + }; + + /** + * A temporary Transform Matrix, re-used internally during batching. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#_tempMatrix1 + * @private + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 3.11.0 + */ + this._tempMatrix1 = new TransformMatrix(); + + /** + * A temporary Transform Matrix, re-used internally during batching. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#_tempMatrix2 + * @private + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 3.11.0 + */ + this._tempMatrix2 = new TransformMatrix(); + + /** + * A temporary Transform Matrix, re-used internally during batching. + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#_tempMatrix3 + * @private + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 3.11.0 + */ + this._tempMatrix3 = new TransformMatrix(); + + /** + * Has this renderer fully booted yet? + * + * @name Phaser.Renderer.Canvas.CanvasRenderer#isBooted + * @type {boolean} + * @since 3.50.0 + */ + this.isBooted = false; + + this.init(); + }, + + /** + * Prepares the game canvas for rendering. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#init + * @since 3.0.0 + */ + init: function () + { + var game = this.game; + + game.events.once(GameEvents.BOOT, function () + { + var config = this.config; + + if (!config.transparent) + { + var ctx = this.gameContext; + var gameCanvas = this.gameCanvas; + + ctx.fillStyle = config.backgroundColor.rgba; + ctx.fillRect(0, 0, gameCanvas.width, gameCanvas.height); + } + + }, this); + + game.textures.once(TextureEvents.READY, this.boot, this); + }, + + /** + * Internal boot handler. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#boot + * @private + * @since 3.50.0 + */ + boot: function () + { + var game = this.game; + + var baseSize = game.scale.baseSize; + + this.width = baseSize.width; + this.height = baseSize.height; + + this.isBooted = true; + + game.scale.on(ScaleEvents.RESIZE, this.onResize, this); + + this.resize(baseSize.width, baseSize.height); + }, + + /** + * The event handler that manages the `resize` event dispatched by the Scale Manager. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#onResize + * @since 3.16.0 + * + * @param {Phaser.Structs.Size} gameSize - The default Game Size object. This is the un-modified game dimensions. + * @param {Phaser.Structs.Size} baseSize - The base Size object. The game dimensions multiplied by the resolution. The canvas width / height values match this. + */ + onResize: function (gameSize, baseSize) + { + // Has the underlying canvas size changed? + if (baseSize.width !== this.width || baseSize.height !== this.height) + { + this.resize(baseSize.width, baseSize.height); + } + }, + + /** + * Resize the main game canvas. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#resize + * @fires Phaser.Renderer.Events#RESIZE + * @since 3.0.0 + * + * @param {number} [width] - The new width of the renderer. + * @param {number} [height] - The new height of the renderer. + */ + resize: function (width, height) + { + this.width = width; + this.height = height; + + this.emit(Events.RESIZE, width, height); + }, + + /** + * Resets the transformation matrix of the current context to the identity matrix, thus resetting any transformation. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#resetTransform + * @since 3.0.0 + */ + resetTransform: function () + { + this.currentContext.setTransform(1, 0, 0, 1, 0, 0); + }, + + /** + * Sets the blend mode (compositing operation) of the current context. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#setBlendMode + * @since 3.0.0 + * + * @param {string} blendMode - The new blend mode which should be used. + * + * @return {this} This CanvasRenderer object. + */ + setBlendMode: function (blendMode) + { + this.currentContext.globalCompositeOperation = blendMode; + + return this; + }, + + /** + * Changes the Canvas Rendering Context that all draw operations are performed against. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#setContext + * @since 3.12.0 + * + * @param {?CanvasRenderingContext2D} [ctx] - The new Canvas Rendering Context to draw everything to. Leave empty to reset to the Game Canvas. + * + * @return {this} The Canvas Renderer instance. + */ + setContext: function (ctx) + { + this.currentContext = (ctx) ? ctx : this.gameContext; + + return this; + }, + + /** + * Sets the global alpha of the current context. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#setAlpha + * @since 3.0.0 + * + * @param {number} alpha - The new alpha to use, where 0 is fully transparent and 1 is fully opaque. + * + * @return {this} This CanvasRenderer object. + */ + setAlpha: function (alpha) + { + this.currentContext.globalAlpha = alpha; + + return this; + }, + + /** + * Called at the start of the render loop. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#preRender + * @fires Phaser.Renderer.Events#PRE_RENDER_CLEAR + * @fires Phaser.Renderer.Events#PRE_RENDER + * @since 3.0.0 + */ + preRender: function () + { + var ctx = this.gameContext; + var config = this.config; + + var width = this.width; + var height = this.height; + + ctx.globalAlpha = 1; + ctx.globalCompositeOperation = 'source-over'; + ctx.setTransform(1, 0, 0, 1, 0, 0); + + this.emit(Events.PRE_RENDER_CLEAR); + + if (config.clearBeforeRender) + { + ctx.clearRect(0, 0, width, height); + + if (!config.transparent) + { + ctx.fillStyle = config.backgroundColor.rgba; + ctx.fillRect(0, 0, width, height); + } + } + + ctx.save(); + + this.drawCount = 0; + + this.emit(Events.PRE_RENDER); + }, + + /** + * The core render step for a Scene Camera. + * + * Iterates through the given array of Game Objects and renders them with the given Camera. + * + * This is called by the `CameraManager.render` method. The Camera Manager instance belongs to a Scene, and is invoked + * by the Scene Systems.render method. + * + * This method is not called if `Camera.visible` is `false`, or `Camera.alpha` is zero. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#render + * @fires Phaser.Renderer.Events#RENDER + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to render. + * @param {Phaser.GameObjects.GameObject[]} children - An array of filtered Game Objects that can be rendered by the given Camera. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Scene Camera to render with. + */ + render: function (scene, children, camera) + { + var childCount = children.length; + + this.emit(Events.RENDER, scene, camera); + + var cx = camera.x; + var cy = camera.y; + var cw = camera.width; + var ch = camera.height; + + var ctx = (camera.renderToTexture) ? camera.context : scene.sys.context; + + // Save context pre-clip + ctx.save(); + + if (this.game.scene.customViewports) + { + ctx.beginPath(); + ctx.rect(cx, cy, cw, ch); + ctx.clip(); + } + + camera.emit(CameraEvents.PRE_RENDER, camera); + + this.currentContext = ctx; + + var mask = camera.mask; + + if (mask) + { + mask.preRenderCanvas(this, null, camera._maskCamera); + } + + if (!camera.transparent) + { + ctx.fillStyle = camera.backgroundColor.rgba; + ctx.fillRect(cx, cy, cw, ch); + } + + ctx.globalAlpha = camera.alpha; + + ctx.globalCompositeOperation = 'source-over'; + + this.drawCount += childCount; + + if (camera.renderToTexture) + { + camera.emit(CameraEvents.PRE_RENDER, camera); + } + + camera.matrix.copyToContext(ctx); + + for (var i = 0; i < childCount; i++) + { + var child = children[i]; + + if (child.mask) + { + child.mask.preRenderCanvas(this, child, camera); + } + + child.renderCanvas(this, child, camera); + + if (child.mask) + { + child.mask.postRenderCanvas(this, child, camera); + } + } + + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.globalCompositeOperation = 'source-over'; + ctx.globalAlpha = 1; + + camera.flashEffect.postRenderCanvas(ctx); + camera.fadeEffect.postRenderCanvas(ctx); + + camera.dirty = false; + + if (mask) + { + mask.postRenderCanvas(this); + } + + // Restore pre-clip context + ctx.restore(); + + if (camera.renderToTexture) + { + camera.emit(CameraEvents.POST_RENDER, camera); + + if (camera.renderToGame) + { + scene.sys.context.drawImage(camera.canvas, cx, cy); + } + } + + camera.emit(CameraEvents.POST_RENDER, camera); + }, + + /** + * Restores the game context's global settings and takes a snapshot if one is scheduled. + * + * The post-render step happens after all Cameras in all Scenes have been rendered. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#postRender + * @fires Phaser.Renderer.Events#POST_RENDER + * @since 3.0.0 + */ + postRender: function () + { + var ctx = this.gameContext; + + ctx.restore(); + + this.emit(Events.POST_RENDER); + + var state = this.snapshotState; + + if (state.callback) + { + CanvasSnapshot(this.gameCanvas, state); + + state.callback = null; + } + }, + + /** + * Takes a snapshot of the given area of the given canvas. + * + * Unlike the other snapshot methods, this one is processed immediately and doesn't wait for the next render. + * + * Snapshots work by creating an Image object from the canvas data, this is a blocking process, which gets + * more expensive the larger the canvas size gets, so please be careful how you employ this in your game. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#snapshotCanvas + * @since 3.19.0 + * + * @param {HTMLCanvasElement} canvas - The canvas to grab from. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {boolean} [getPixel=false] - Grab a single pixel as a Color object, or an area as an Image object? + * @param {number} [x=0] - The x coordinate to grab from. + * @param {number} [y=0] - The y coordinate to grab from. + * @param {number} [width=canvas.width] - The width of the area to grab. + * @param {number} [height=canvas.height] - The height of the area to grab. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This Canvas Renderer. + */ + snapshotCanvas: function (canvas, callback, getPixel, x, y, width, height, type, encoderOptions) + { + if (getPixel === undefined) { getPixel = false; } + + this.snapshotArea(x, y, width, height, callback, type, encoderOptions); + + var state = this.snapshotState; + + state.getPixel = getPixel; + + CanvasSnapshot(canvas, state); + + state.callback = null; + + return this; + }, + + /** + * Schedules a snapshot of the entire game viewport to be taken after the current frame is rendered. + * + * To capture a specific area see the `snapshotArea` method. To capture a specific pixel, see `snapshotPixel`. + * + * Only one snapshot can be active _per frame_. If you have already called `snapshotPixel`, for example, then + * calling this method will override it. + * + * Snapshots work by creating an Image object from the canvas data, this is a blocking process, which gets + * more expensive the larger the canvas size gets, so please be careful how you employ this in your game. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#snapshot + * @since 3.0.0 + * + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This WebGL Renderer. + */ + snapshot: function (callback, type, encoderOptions) + { + return this.snapshotArea(0, 0, this.gameCanvas.width, this.gameCanvas.height, callback, type, encoderOptions); + }, + + /** + * Schedules a snapshot of the given area of the game viewport to be taken after the current frame is rendered. + * + * To capture the whole game viewport see the `snapshot` method. To capture a specific pixel, see `snapshotPixel`. + * + * Only one snapshot can be active _per frame_. If you have already called `snapshotPixel`, for example, then + * calling this method will override it. + * + * Snapshots work by creating an Image object from the canvas data, this is a blocking process, which gets + * more expensive the larger the canvas size gets, so please be careful how you employ this in your game. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#snapshotArea + * @since 3.16.0 + * + * @param {number} x - The x coordinate to grab from. + * @param {number} y - The y coordinate to grab from. + * @param {number} width - The width of the area to grab. + * @param {number} height - The height of the area to grab. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This WebGL Renderer. + */ + snapshotArea: function (x, y, width, height, callback, type, encoderOptions) + { + var state = this.snapshotState; + + state.callback = callback; + state.type = type; + state.encoder = encoderOptions; + state.getPixel = false; + state.x = x; + state.y = y; + state.width = Math.min(width, this.gameCanvas.width); + state.height = Math.min(height, this.gameCanvas.height); + + return this; + }, + + /** + * Schedules a snapshot of the given pixel from the game viewport to be taken after the current frame is rendered. + * + * To capture the whole game viewport see the `snapshot` method. To capture a specific area, see `snapshotArea`. + * + * Only one snapshot can be active _per frame_. If you have already called `snapshotArea`, for example, then + * calling this method will override it. + * + * Unlike the other two snapshot methods, this one will return a `Color` object containing the color data for + * the requested pixel. It doesn't need to create an internal Canvas or Image object, so is a lot faster to execute, + * using less memory. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#snapshotPixel + * @since 3.16.0 + * + * @param {number} x - The x coordinate of the pixel to get. + * @param {number} y - The y coordinate of the pixel to get. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot pixel data is extracted. + * + * @return {this} This WebGL Renderer. + */ + snapshotPixel: function (x, y, callback) + { + this.snapshotArea(x, y, 1, 1, callback); + + this.snapshotState.getPixel = true; + + return this; + }, + + /** + * Takes a Sprite Game Object, or any object that extends it, and draws it to the current context. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#batchSprite + * @since 3.12.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The texture based Game Object to draw. + * @param {Phaser.Textures.Frame} frame - The frame to draw, doesn't have to be that owned by the Game Object. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use for the rendering transform. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentTransformMatrix] - The transform matrix of the parent container, if set. + */ + batchSprite: function (sprite, frame, camera, parentTransformMatrix) + { + var alpha = camera.alpha * sprite.alpha; + + if (alpha === 0) + { + // Nothing to see, so abort early + return; + } + + var ctx = this.currentContext; + + var camMatrix = this._tempMatrix1; + var spriteMatrix = this._tempMatrix2; + + var cd = frame.canvasData; + + var frameX = cd.x; + var frameY = cd.y; + var frameWidth = frame.cutWidth; + var frameHeight = frame.cutHeight; + var customPivot = frame.customPivot; + + var res = frame.source.resolution; + + var displayOriginX = sprite.displayOriginX; + var displayOriginY = sprite.displayOriginY; + + var x = -displayOriginX + frame.x; + var y = -displayOriginY + frame.y; + + if (sprite.isCropped) + { + var crop = sprite._crop; + + if (crop.flipX !== sprite.flipX || crop.flipY !== sprite.flipY) + { + frame.updateCropUVs(crop, sprite.flipX, sprite.flipY); + } + + frameWidth = crop.cw; + frameHeight = crop.ch; + + frameX = crop.cx; + frameY = crop.cy; + + x = -displayOriginX + crop.x; + y = -displayOriginY + crop.y; + + if (sprite.flipX) + { + if (x >= 0) + { + x = -(x + frameWidth); + } + else if (x < 0) + { + x = (Math.abs(x) - frameWidth); + } + } + + if (sprite.flipY) + { + if (y >= 0) + { + y = -(y + frameHeight); + } + else if (y < 0) + { + y = (Math.abs(y) - frameHeight); + } + } + } + + var flipX = 1; + var flipY = 1; + + if (sprite.flipX) + { + if (!customPivot) + { + x += (-frame.realWidth + (displayOriginX * 2)); + } + + flipX = -1; + } + + // Auto-invert the flipY if this is coming from a GLTexture + if (sprite.flipY) + { + if (!customPivot) + { + y += (-frame.realHeight + (displayOriginY * 2)); + } + + flipY = -1; + } + + var gx = sprite.x; + var gy = sprite.y; + + if (camera.roundPixels) + { + gx = Math.floor(gx); + gy = Math.floor(gy); + } + + spriteMatrix.applyITRS(gx, gy, sprite.rotation, sprite.scaleX * flipX, sprite.scaleY * flipY); + + camMatrix.copyWithScrollFactorFrom( + camera.matrixCombined, + camera.scrollX, camera.scrollY, + sprite.scrollFactorX, sprite.scrollFactorY + ); + + if (parentTransformMatrix) + { + camMatrix.multiply(parentTransformMatrix); + } + + // Multiply by the Sprite matrix + camMatrix.multiply(spriteMatrix); + + if (camera.renderRoundPixels) + { + camMatrix.e = Math.floor(camMatrix.e + 0.5); + camMatrix.f = Math.floor(camMatrix.f + 0.5); + } + + ctx.save(); + + camMatrix.setToContext(ctx); + + ctx.globalCompositeOperation = this.blendModes[sprite.blendMode]; + + ctx.globalAlpha = alpha; + + ctx.imageSmoothingEnabled = !frame.source.scaleMode; + + if (sprite.mask) + { + sprite.mask.preRenderCanvas(this, sprite, camera); + } + + if (frameWidth > 0 && frameHeight > 0) + { + var fw = frameWidth / res; + var fh = frameHeight / res; + + if (camera.roundPixels) + { + x = Math.floor(x + 0.5); + y = Math.floor(y + 0.5); + fw += 0.5; + fh += 0.5; + } + + ctx.drawImage( + frame.source.image, + frameX, frameY, + frameWidth, frameHeight, + x, y, + fw, fh + ); + } + + if (sprite.mask) + { + sprite.mask.postRenderCanvas(this, sprite, camera); + } + + ctx.restore(); + }, + + /** + * Destroys all object references in the Canvas Renderer. + * + * @method Phaser.Renderer.Canvas.CanvasRenderer#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.removeAllListeners(); + + this.game = null; + this.gameCanvas = null; + this.gameContext = null; + } + +}); + +module.exports = CanvasRenderer; + + +/***/ }), + +/***/ 55830: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.Canvas + */ + +module.exports = { + + CanvasRenderer: __webpack_require__(68627), + GetBlendModes: __webpack_require__(56373), + SetTransform: __webpack_require__(20926) + +}; + + +/***/ }), + +/***/ 56373: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var modes = __webpack_require__(10312); +var CanvasFeatures = __webpack_require__(89289); + +/** + * Returns an array which maps the default blend modes to supported Canvas blend modes. + * + * If the browser doesn't support a blend mode, it will default to the normal `source-over` blend mode. + * + * @function Phaser.Renderer.Canvas.GetBlendModes + * @since 3.0.0 + * + * @return {array} Which Canvas blend mode corresponds to which default Phaser blend mode. + */ +var GetBlendModes = function () +{ + var output = []; + var useNew = CanvasFeatures.supportNewBlendModes; + var so = 'source-over'; + + output[modes.NORMAL] = so; + output[modes.ADD] = 'lighter'; + output[modes.MULTIPLY] = (useNew) ? 'multiply' : so; + output[modes.SCREEN] = (useNew) ? 'screen' : so; + output[modes.OVERLAY] = (useNew) ? 'overlay' : so; + output[modes.DARKEN] = (useNew) ? 'darken' : so; + output[modes.LIGHTEN] = (useNew) ? 'lighten' : so; + output[modes.COLOR_DODGE] = (useNew) ? 'color-dodge' : so; + output[modes.COLOR_BURN] = (useNew) ? 'color-burn' : so; + output[modes.HARD_LIGHT] = (useNew) ? 'hard-light' : so; + output[modes.SOFT_LIGHT] = (useNew) ? 'soft-light' : so; + output[modes.DIFFERENCE] = (useNew) ? 'difference' : so; + output[modes.EXCLUSION] = (useNew) ? 'exclusion' : so; + output[modes.HUE] = (useNew) ? 'hue' : so; + output[modes.SATURATION] = (useNew) ? 'saturation' : so; + output[modes.COLOR] = (useNew) ? 'color' : so; + output[modes.LUMINOSITY] = (useNew) ? 'luminosity' : so; + output[modes.ERASE] = 'destination-out'; + output[modes.SOURCE_IN] = 'source-in'; + output[modes.SOURCE_OUT] = 'source-out'; + output[modes.SOURCE_ATOP] = 'source-atop'; + output[modes.DESTINATION_OVER] = 'destination-over'; + output[modes.DESTINATION_IN] = 'destination-in'; + output[modes.DESTINATION_OUT] = 'destination-out'; + output[modes.DESTINATION_ATOP] = 'destination-atop'; + output[modes.LIGHTER] = 'lighter'; + output[modes.COPY] = 'copy'; + output[modes.XOR] = 'xor'; + + return output; +}; + +module.exports = GetBlendModes; + + +/***/ }), + +/***/ 20926: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetCalcMatrix = __webpack_require__(91296); + +/** + * Takes a reference to the Canvas Renderer, a Canvas Rendering Context, a Game Object, a Camera and a parent matrix + * and then performs the following steps: + * + * 1. Checks the alpha of the source combined with the Camera alpha. If 0 or less it aborts. + * 2. Takes the Camera and Game Object matrix and multiplies them, combined with the parent matrix if given. + * 3. Sets the blend mode of the context to be that used by the Game Object. + * 4. Sets the alpha value of the context to be that used by the Game Object combined with the Camera. + * 5. Saves the context state. + * 6. Sets the final matrix values into the context via setTransform. + * 7. If the Game Object has a texture frame, imageSmoothingEnabled is set based on frame.source.scaleMode. + * 8. If the Game Object does not have a texture frame, imageSmoothingEnabled is set based on Renderer.antialias. + * + * This function is only meant to be used internally. Most of the Canvas Renderer classes use it. + * + * @function Phaser.Renderer.Canvas.SetTransform + * @since 3.12.0 + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {CanvasRenderingContext2D} ctx - The canvas context to set the transform on. + * @param {Phaser.GameObjects.GameObject} src - The Game Object being rendered. Can be any type that extends the base class. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - A parent transform matrix to apply to the Game Object before rendering. + * + * @return {boolean} `true` if the Game Object context was set, otherwise `false`. + */ +var SetTransform = function (renderer, ctx, src, camera, parentMatrix) +{ + var alpha = camera.alpha * src.alpha; + + if (alpha <= 0) + { + // Nothing to see, so don't waste time calculating stuff + return false; + } + + var calcMatrix = GetCalcMatrix(src, camera, parentMatrix).calc; + + // Blend Mode + ctx.globalCompositeOperation = renderer.blendModes[src.blendMode]; + + // Alpha + ctx.globalAlpha = alpha; + + ctx.save(); + + calcMatrix.setToContext(ctx); + + ctx.imageSmoothingEnabled = src.frame ? !src.frame.source.scaleMode : renderer.antialias; + + return true; +}; + +module.exports = SetTransform; + + +/***/ }), + +/***/ 63899: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Lose WebGL Event. + * + * This event is dispatched by the WebGLRenderer when the WebGL context + * is lost. + * + * Context can be lost for a variety of reasons, like leaving the browser tab. + * The game canvas DOM object will dispatch `webglcontextlost`. + * All WebGL resources get wiped, and the context is reset. + * + * While WebGL is lost, the game will continue to run, but all WebGL resources + * are lost, and new ones cannot be created. + * + * Once the context is restored and the renderer has automatically restored + * the state, the renderer will emit a `RESTORE_WEBGL` event. At that point, + * it is safe to continue. + * + * @event Phaser.Renderer.Events#LOSE_WEBGL + * @type {string} + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - the renderer that owns the WebGL context + */ +module.exports = 'losewebgl'; + + +/***/ }), + +/***/ 6119: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Post-Render Event. + * + * This event is dispatched by the Renderer when all rendering, for all cameras in all Scenes, + * has completed, but before any pending snap shots have been taken. + * + * @event Phaser.Renderer.Events#POST_RENDER + * @type {string} + * @since 3.50.0 + */ +module.exports = 'postrender'; + + +/***/ }), + +/***/ 31124: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pre-Render Clear Event. + * + * This event is dispatched by the Phaser Renderer. It happens at the start of the render step, before + * the WebGL gl.clear function has been called. This allows you to toggle the `config.clearBeforeRender` property + * as required, to have fine-grained control over when the canvas is cleared during rendering. + * + * Listen to it from within a Scene using: `this.renderer.events.on('prerenderclear', listener)`. + * + * It's very important to understand that this event is called _before_ the scissor and mask stacks are cleared. + * This means you should not use this event to modify the scissor or mask. Instead, use the `prerender` event for that. + * + * If using the Canvas Renderer, this event is dispatched before the canvas is cleared, but after the context globalAlpha + * and transform have been reset. + * + * @event Phaser.Renderer.Events#PRE_RENDER_CLEAR + * @type {string} + * @since 3.85.0 + */ +module.exports = 'prerenderclear'; + + +/***/ }), + +/***/ 48070: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pre-Render Event. + * + * This event is dispatched by the Phaser Renderer. This happens right at the start of the render + * process, after the context has been cleared, the scissors enabled (WebGL only) and everything has been + * reset ready for the render. + * + * @event Phaser.Renderer.Events#PRE_RENDER + * @type {string} + * @since 3.50.0 + */ +module.exports = 'prerender'; + + +/***/ }), + +/***/ 15640: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Render Event. + * + * This event is dispatched by the Phaser Renderer for every camera in every Scene. + * + * It is dispatched before any of the children in the Scene have been rendered. + * + * @event Phaser.Renderer.Events#RENDER + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.Scene} scene - The Scene being rendered. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Scene Camera being rendered. + */ +module.exports = 'render'; + + +/***/ }), + +/***/ 8912: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Renderer Resize Event. + * + * This event is dispatched by the Phaser Renderer when it is resized, usually as a result + * of the Scale Manager resizing. + * + * @event Phaser.Renderer.Events#RESIZE + * @type {string} + * @since 3.50.0 + * + * @param {number} width - The new width of the renderer. + * @param {number} height - The new height of the renderer. + */ +module.exports = 'resize'; + + +/***/ }), + +/***/ 87124: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Restore WebGL Event. + * + * This event is dispatched by the WebGLRenderer when the WebGL context + * is restored. + * + * It is dispatched after all WebGL resources have been recreated. + * Most resources should come back automatically, but you will need to redraw + * dynamic textures that were GPU bound. + * Listen to this event to know when you can safely do that. + * + * Context can be lost for a variety of reasons, like leaving the browser tab. + * The game canvas DOM object will dispatch `webglcontextlost`. + * All WebGL resources get wiped, and the context is reset. + * + * Once the context is restored, the canvas will dispatch + * `webglcontextrestored`. Phaser uses this to re-create necessary resources. + * Please wait for Phaser to dispatch the `RESTORE_WEBGL` event before + * re-creating any resources of your own. + * + * @event Phaser.Renderer.Events#RESTORE_WEBGL + * @type {string} + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - the renderer that owns the WebGL context + */ +module.exports = 'restorewebgl'; + + +/***/ }), + +/***/ 53998: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Set Parallel Texture Units Event. + * + * This event is dispatched by the RenderNodeManager when + * `maxParallelTextureUnits` is set after boot. + * This advises the listener of the number of texture units + * that should be used in parallel, for performance reasons. + * + * In general, the number of units is either + * the number of texture units available on the device, + * or 1 if the device is expected to perform badly with + * multiple texture units in parallel. + * + * The primary consumer of this event is batch render nodes. + * + * @event Phaser.Renderer.Events#SET_PARALLEL_TEXTURE_UNITS + * @type {string} + * @since 4.0.0 + * + * @param {number} units - The number of texture units advised. + */ +module.exports = 'setparalleltextureunits'; + + +/***/ }), + +/***/ 92503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.Events + */ + +module.exports = { + + LOSE_WEBGL: __webpack_require__(63899), + POST_RENDER: __webpack_require__(6119), + PRE_RENDER: __webpack_require__(48070), + PRE_RENDER_CLEAR: __webpack_require__(31124), + RENDER: __webpack_require__(15640), + RESIZE: __webpack_require__(8912), + RESTORE_WEBGL: __webpack_require__(87124), + SET_PARALLEL_TEXTURE_UNITS: __webpack_require__(53998) + +}; + + +/***/ }), + +/***/ 36909: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer + */ + +/** + * @namespace Phaser.Types.Renderer + */ + +module.exports = { + + Events: __webpack_require__(92503), + Snapshot: __webpack_require__(89966) + +}; + +if (true) +{ + module.exports.Canvas = __webpack_require__(55830); +} + +if (true) +{ + module.exports.WebGL = __webpack_require__(4159); +} + + +/***/ }), + +/***/ 32880: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasPool = __webpack_require__(27919); +var Color = __webpack_require__(40987); +var GetFastValue = __webpack_require__(95540); + +/** + * Takes a snapshot of an area from the current frame displayed by a canvas. + * + * This is then copied to an Image object. When this loads, the results are sent + * to the callback provided in the Snapshot Configuration object. + * + * @function Phaser.Renderer.Snapshot.Canvas + * @since 3.0.0 + * + * @param {HTMLCanvasElement} sourceCanvas - The canvas to take a snapshot of. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotState} config - The snapshot configuration object. + */ +var CanvasSnapshot = function (canvas, config) +{ + var callback = GetFastValue(config, 'callback'); + var type = GetFastValue(config, 'type', 'image/png'); + var encoderOptions = GetFastValue(config, 'encoder', 0.92); + var x = Math.abs(Math.round(GetFastValue(config, 'x', 0))); + var y = Math.abs(Math.round(GetFastValue(config, 'y', 0))); + var width = Math.floor(GetFastValue(config, 'width', canvas.width)); + var height = Math.floor(GetFastValue(config, 'height', canvas.height)); + var getPixel = GetFastValue(config, 'getPixel', false); + + if (getPixel) + { + var context = canvas.getContext('2d', { willReadFrequently: false }); + var imageData = context.getImageData(x, y, 1, 1); + var data = imageData.data; + + callback.call(null, new Color(data[0], data[1], data[2], data[3])); + } + else if (x !== 0 || y !== 0 || width !== canvas.width || height !== canvas.height) + { + // Area Grab + var copyCanvas = CanvasPool.createWebGL(this, width, height); + var ctx = copyCanvas.getContext('2d', { willReadFrequently: true }); + + if (width > 0 && height > 0) + { + ctx.drawImage(canvas, x, y, width, height, 0, 0, width, height); + } + + var image1 = new Image(); + + image1.onerror = function () + { + callback.call(null); + + CanvasPool.remove(copyCanvas); + }; + + image1.onload = function () + { + callback.call(null, image1); + + CanvasPool.remove(copyCanvas); + }; + + image1.src = copyCanvas.toDataURL(type, encoderOptions); + } + else + { + // Full Grab + var image2 = new Image(); + + image2.onerror = function () + { + callback.call(null); + }; + + image2.onload = function () + { + callback.call(null, image2); + }; + + image2.src = canvas.toDataURL(type, encoderOptions); + } +}; + +module.exports = CanvasSnapshot; + + +/***/ }), + +/***/ 88815: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasPool = __webpack_require__(27919); +var Color = __webpack_require__(40987); +var GetFastValue = __webpack_require__(95540); + +/** + * Takes a snapshot of an area from the current frame displayed by a WebGL canvas. + * + * This is then copied to an Image object. When this loads, the results are sent + * to the callback provided in the Snapshot Configuration object. + * + * @function Phaser.Renderer.Snapshot.WebGL + * @since 3.0.0 + * + * @param {WebGLRenderingContext} sourceContext - The WebGL context to take a snapshot of. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotState} config - The snapshot configuration object. + */ +var WebGLSnapshot = function (sourceContext, config) +{ + var gl = sourceContext; + + var callback = GetFastValue(config, 'callback'); + var type = GetFastValue(config, 'type', 'image/png'); + var encoderOptions = GetFastValue(config, 'encoder', 0.92); + var x = Math.abs(Math.round(GetFastValue(config, 'x', 0))); + var y = Math.abs(Math.round(GetFastValue(config, 'y', 0))); + + var getPixel = GetFastValue(config, 'getPixel', false); + + var isFramebuffer = GetFastValue(config, 'isFramebuffer', false); + + var bufferWidth = (isFramebuffer) ? GetFastValue(config, 'bufferWidth', 1) : gl.drawingBufferWidth; + var bufferHeight = (isFramebuffer) ? GetFastValue(config, 'bufferHeight', 1) : gl.drawingBufferHeight; + + if (getPixel) + { + var pixel = new Uint8Array(4); + + var destY = bufferHeight - y; + + gl.readPixels(x, destY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); + + callback.call(null, new Color(pixel[0], pixel[1], pixel[2], pixel[3])); + } + else + { + var width = Math.floor(GetFastValue(config, 'width', bufferWidth)); + var height = Math.floor(GetFastValue(config, 'height', bufferHeight)); + + var total = width * height * 4; + + var pixels = new Uint8Array(total); + + gl.readPixels(x, bufferHeight - y - height, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + var canvas = CanvasPool.createWebGL(this, width, height); + var ctx = canvas.getContext('2d', { willReadFrequently: true }); + + var imageData = ctx.getImageData(0, 0, width, height); + + var data = imageData.data; + + for (var py = 0; py < height; py++) + { + for (var px = 0; px < width; px++) + { + var sourceIndex = ((height - py - 1) * width + px) * 4; + var destIndex = (py * width + px) * 4; + + var r = pixels[sourceIndex + 0]; + var g = pixels[sourceIndex + 1]; + var b = pixels[sourceIndex + 2]; + var a = pixels[sourceIndex + 3]; + + // Un-premultiplication. + if (config.unpremultiplyAlpha && a !== 0) + { + var ratio = 255 / a; + + r = Math.floor(r * ratio); + g = Math.floor(g * ratio); + b = Math.floor(b * ratio); + } + + data[destIndex + 0] = r; + data[destIndex + 1] = g; + data[destIndex + 2] = b; + data[destIndex + 3] = a; + } + } + + ctx.putImageData(imageData, 0, 0); + + var image = new Image(); + + image.onerror = function () + { + callback.call(null); + + CanvasPool.remove(canvas); + }; + + image.onload = function () + { + callback.call(null, image); + + CanvasPool.remove(canvas); + }; + + image.src = canvas.toDataURL(type, encoderOptions); + } +}; + +module.exports = WebGLSnapshot; + + +/***/ }), + +/***/ 89966: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.Snapshot + */ + +module.exports = { + + Canvas: __webpack_require__(32880), + WebGL: __webpack_require__(88815) + +}; + + +/***/ }), + +/***/ 87774: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * Descriptor of the context within which a drawing operation is performed. + * + * This consists of a subset of the global WebGL state. It includes the following: + * + * - Framebuffer + * - Viewport + * - Scissor box + * - Blend mode + * - Clear color + * + * This is analogous to a drafting table in a studio. The paper is the + * framebuffer, while the rest of the data specifies masks, guides etc for + * drawing. + * + * A DrawingContext can be copied and thrown away, allowing temporary use of + * different drawing states on a framebuffer. + * + * @class DrawingContext + * @memberof Phaser.Renderer.WebGL + * @constructor + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this context. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.DrawingContextOptions} [options] - The options for this context. + */ +var DrawingContext = new Class({ + initialize: + + function DrawingContext (renderer, options) + { + if (options === undefined) { options = {}; } + + /** + * The renderer that owns this context. + * + * @name Phaser.Renderer.WebGL.DrawingContext#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The camera used by this context. Set this using `setCamera` to ensure + * the view matrix is updated. Ensure that this is not `null` before + * rendering. + * + * @name Phaser.Renderer.WebGL.DrawingContext#camera + * @type {?Phaser.Cameras.Scene2D.Camera} + * @since 4.0.0 + * @readonly + */ + this.camera = null; + + this.setCamera(options.camera || null); + + /** + * Relevant WebGL state for the DrawingContext. + * Contains the framebuffer, scissor box, and viewport. + * + * @name Phaser.Renderer.WebGL.DrawingContext#state + * @type {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} + */ + this.state = { + bindings: + { + framebuffer: null + }, + blend: { + // This will be automatically populated below. + }, + colorClearValue: options.clearColor || [ 0, 0, 0, 0 ], + scissor: { + box: [ 0, 0, 0, 0 ], + enable: true + }, + viewport: [ 0, 0, 0, 0 ] + }; + + /** + * The blend mode to use when rendering. + * This is an index into the renderer's blendModes array. + * It is faster to check than the state object. + * + * @name Phaser.Renderer.WebGL.DrawingContext#blendMode + * @type {number} + * @default 0 + * @since 4.0.0 + */ + this.blendMode = -1; + + this.setBlendMode(options.blendMode || 0); + + /** + * Which renderbuffers in the framebuffer to clear when the DrawingContext comes into use. + * This is the mask of buffers to clear: + * gl.COLOR_BUFFER_BIT, gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT. + * + * @name Phaser.Renderer.WebGL.DrawingContext#autoClear + * @type {number} + * @default 0 + * @since 4.0.0 + */ + this.autoClear = 0; + + if (options.autoClear === undefined || options.autoClear === true) + { + this.setAutoClear(true, true, true); + } + else if (Array.isArray(options.autoClear)) + { + this.setAutoClear.apply(this, options.autoClear); + } + + /** + * Whether to use the canvas as the framebuffer. + * + * @name Phaser.Renderer.WebGL.DrawingContext#useCanvas + * @type {boolean} + * @default false + * @since 4.0.0 + */ + this.useCanvas = !!options.useCanvas; + + /** + * The WebGLFramebufferWrapper which will hold the framebuffer output. + * This may contain the canvas. + * + * @name Phaser.Renderer.WebGL.DrawingContext#framebuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper} + * @since 4.0.0 + */ + this.framebuffer = null; + + /** + * The WebGLTextureWrapper which will hold the framebuffer output. + * This is only used if `useCanvas` is `false`. + * + * @name Phaser.Renderer.WebGL.DrawingContext#texture + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @default null + * @since 4.0.0 + */ + this.texture = null; + + /** + * The pool to return to when this context is no longer needed. + * Used only for temporary contexts. + * + * @name Phaser.Renderer.WebGL.DrawingContext#pool + * @type {Phaser.Renderer.WebGL.DrawingContextPool} + * @since 4.0.0 + * @default null + */ + this.pool = options.pool || null; + + /** + * The last time the DrawingContext was used. + * This is used to determine whether the context is a candidate + * for reuse in a pool. + * + * @name Phaser.Renderer.WebGL.DrawingContext#lastUsed + * @type {number} + * @since 4.0.0 + */ + this.lastUsed = 0; + + /** + * The width of the framebuffer. + * + * @name Phaser.Renderer.WebGL.DrawingContext#width + * @type {number} + * @since 4.0.0 + */ + this.width = 0; + + /** + * The height of the framebuffer. + * + * @name Phaser.Renderer.WebGL.DrawingContext#height + * @type {number} + * @since 4.0.0 + */ + this.height = 0; + + /** + * Locks on the DrawingContext. + * These are used to prevent the context from being released + * to its pool. + * They can be any value, so long as they are distinct. + * + * @name Phaser.Renderer.WebGL.DrawingContext#_locks + * @type {any[]} + * @private + * @since 4.0.0 + */ + this._locks = []; + + if (options.copyFrom) + { + this.copy(options.copyFrom); + } + else + { + this.resize( + options.width || renderer.width, + options.height || renderer.height + ); + } + }, + + /** + * Resize the DrawingContext. + * + * Delete the framebuffer and texture, and create new ones with the new size. The scissor box and viewport are reset to match the new size. + * + * @method Phaser.Renderer.WebGL.DrawingContext#resize + * @since 4.0.0 + * @param {number} width - The new width of the framebuffer. + * @param {number} height - The new height of the framebuffer. + */ + resize: function (width, height) + { + width = Math.round(width); + height = Math.round(height); + + if (width <= 0) + { + width = 1; + } + + if (height <= 0) + { + height = 1; + } + + if (!this.useCanvas) + { + if (!this.framebuffer) + { + var renderer = this.renderer; + this.texture = renderer.createTextureFromSource(null, width, height, 0, true); + this.framebuffer = renderer.createFramebuffer(this.texture, true, false); + } + else + { + this.framebuffer.resize(width, height); + } + } + else if (!this.framebuffer) + { + // Create a framebuffer referencing the canvas. + // This is used for the main framebuffer. + // It does not need to resize after creation. + this.framebuffer = this.renderer.createFramebuffer(null); + } + this.state.bindings.framebuffer = this.framebuffer; + + this.width = width; + this.height = height; + + this.state.scissor.box = [ 0, 0, width, height ]; + this.state.viewport = [ 0, 0, width, height ]; + }, + + /** + * Copy the state of another DrawingContext. + * + * @method Phaser.Renderer.WebGL.DrawingContext#copy + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} source - The DrawingContext to copy from. + */ + copy: function (source) + { + var state = source.state; + var blend = state.blend; + var scissor = state.scissor; + + this.autoClear = source.autoClear; + this.useCanvas = source.useCanvas; + this.framebuffer = source.framebuffer; + this.texture = source.texture; + this.camera = source.camera; + this.blendMode = source.blendMode; + this.width = source.width; + this.height = source.height; + + this.state = { + bindings: + { + framebuffer: state.bindings.framebuffer + }, + blend: { + color: blend.color && blend.color.slice(), + enable: blend.enable, + equation: blend.equation, + func: blend.func + }, + colorClearValue: state.colorClearValue.slice(), + scissor: { + box: scissor.box.slice(), + enable: scissor.enable + }, + viewport: state.viewport.slice() + }; + }, + + /** + * Create a clone of the DrawingContext. This is intended to be mutated + * for temporary use, and then thrown away. + * + * The autoClear setting is set to false unless specified. + * This is because most clones reference an existing framebuffer, + * which is intended to accumulate drawing operations. + * + * @method Phaser.Renderer.WebGL.DrawingContext#getClone + * @since 4.0.0 + * @param {boolean} [preserveAutoClear=false] - Whether to preserve the autoClear setting. + * @return {Phaser.Renderer.WebGL.DrawingContext} The cloned DrawingContext. + */ + getClone: function (preserveAutoClear) + { + var context = new DrawingContext(this.renderer, { copyFrom: this }); + + if (!preserveAutoClear) + { + context.setAutoClear(false, false, false); + } + + return context; + }, + + /** + * Set the buffers to clear when the DrawingContext comes into use. + * + * @method Phaser.Renderer.WebGL.DrawingContext#setAutoClear + * @since 4.0.0 + * @param {boolean} color - Whether to clear the color buffer. + * @param {boolean} depth - Whether to clear the depth buffer. + * @param {boolean} stencil - Whether to clear the stencil buffer. + */ + setAutoClear: function (color, depth, stencil) + { + var autoClear = 0; + var gl = this.renderer.gl; + if (color) { autoClear |= gl.COLOR_BUFFER_BIT; } + if (depth) { autoClear |= gl.DEPTH_BUFFER_BIT; } + if (stencil) { autoClear |= gl.STENCIL_BUFFER_BIT; } + this.autoClear = autoClear; + }, + + /** + * Set the blend mode for the DrawingContext. + * + * @method Phaser.Renderer.WebGL.DrawingContext#setBlendMode + * @since 4.0.0 + * @param {number} blendMode - The blend mode to set. + * @param {number[]} [blendColor] - The blend color to set. This is an array of 4 values: red, green, blue, alpha. + */ + setBlendMode: function (blendMode, blendColor) + { + if (blendMode === this.blendMode) { return; } + + var blend = this.state.blend; + var blendModeData = this.renderer.blendModes[blendMode]; + + blend.enable = blendModeData.enable; + blend.equation = blendModeData.equation; + blend.func = blendModeData.func; + + if (blendColor) + { + blend.color = blendColor; + } + else + { + blend.color = undefined; + } + + this.blendMode = blendMode; + }, + + /** + * Set the camera for the DrawingContext. + * + * @method Phaser.Renderer.WebGL.DrawingContext#setCamera + * @since 4.0.0 + * @param {Phaser.Cameras.Scene2D.Camera} camera - The camera to set. + */ + setCamera: function (camera) + { + this.camera = camera; + }, + + /** + * Set the clear color for the DrawingContext. + * No changes will be made if the color is the same as the current clear color. + * + * @method Phaser.Renderer.WebGL.DrawingContext#setClearColor + * @since 4.0.0 + * @param {number} r - The red component of the color to clear with. + * @param {number} g - The green component of the color to clear with. + * @param {number} b - The blue component of the color to clear with. + * @param {number} a - The alpha component of the color to clear with. + */ + setClearColor: function (r, g, b, a) + { + var colorClearValue = this.state.colorClearValue; + if ( + r === colorClearValue[0] && + g === colorClearValue[1] && + b === colorClearValue[2] && + a === colorClearValue[3] + ) { return; } + + this.state.colorClearValue = [ r, g, b, a ]; + }, + + /** + * Set the scissor box for the DrawingContext. + * + * @method Phaser.Renderer.WebGL.DrawingContext#setScissorBox + * @since 4.0.0 + * @param {number} x - The x coordinate of the scissor box. + * @param {number} y - The y coordinate of the scissor box. + * @param {number} width - The width of the scissor box. + * @param {number} height - The height of the scissor box. + */ + setScissorBox: function (x, y, width, height) + { + // Convert Y coordinate to WebGL space. + y = this.height - y - height; + + this.state.scissor.box = [ x, y, width, height ]; + }, + + /** + * Enable or disable the scissor box for the DrawingContext. + * + * @method Phaser.Renderer.WebGL.DrawingContext#setScissorEnable + * @since 4.0.0 + * @param {boolean} enable - Whether to enable the scissor box. + */ + setScissorEnable: function (enable) + { + this.state.scissor.enable = enable; + }, + + /** + * Begin using the DrawingContext. + * This will finish any outstanding batches and run any autoClear. + * + * @method Phaser.Renderer.WebGL.DrawingContext#use + * @since 4.0.0 + */ + use: function () + { + this.renderer.renderNodes.finishBatch(); + + if (this.autoClear) + { + this.clear(); + } + }, + + /** + * End using the DrawingContext. This marks the context as not in use, + * so its framebuffer and texture are not needed any more + * and may be cleared at any time. This will finish any outstanding batches. + * + * If there are no locks on the DrawingContext, and it comes from a pool, + * it will be returned to its pool. + * + * @method Phaser.Renderer.WebGL.DrawingContext#release + * @since 4.0.0 + */ + release: function () + { + if (this.pool && this._locks.length === 0) + { + this.lastUsed = Date.now(); + this.pool.add(this); + } + + this.renderer.renderNodes.finishBatch(); + }, + + /** + * Lock the DrawingContext to be in use. + * This prevents `release` from returning it to its pool + * until `unlock` is called with the appropriate key. + * This is used for temporary DrawingContexts, + * which may be returned to a pool. + * + * @method Phaser.Renderer.WebGL.DrawingContext#lock + * @since 4.0.0 + * @param {any} key - The key to lock the DrawingContext with. + */ + lock: function (key) + { + if (this._locks.indexOf(key) !== -1) + { + return; + } + this._locks.push(key); + }, + + /** + * Unlock the DrawingContext. + * This allows `release` to return it to its pool. + * + * @method Phaser.Renderer.WebGL.DrawingContext#unlock + * @since 4.0.0 + * @param {any} key - The key to unlock the DrawingContext with. This must be the same key used to lock it. + * @param {boolean} [release] - Whether to release the DrawingContext immediately. This will only happen if there are no other locks on it. + */ + unlock: function (key, release) + { + var index = this._locks.indexOf(key); + if (index !== -1) + { + this._locks.splice(index, 1); + } + + if (release) + { + this.release(); + } + }, + + /** + * Check whether the DrawingContext is locked. + * + * @method Phaser.Renderer.WebGL.DrawingContext#isLocked + * @since 4.0.0 + * @return {boolean} Whether the DrawingContext is locked. + */ + isLocked: function () + { + return this._locks.length > 0; + }, + + /** + * Begin drawing with the DrawingContext. + * + * This should be called before rendering to set up the framebuffer + * and other WebGL state. + * + * @method Phaser.Renderer.WebGL.DrawingContext#beginDraw + * @since 4.0.0 + */ + beginDraw: function () + { + this.renderer.glWrapper.update(this.state); + }, + + /** + * Clear the framebuffer. This will bind the framebuffer. + * + * @method Phaser.Renderer.WebGL.DrawingContext#clear + * @since 4.0.0 + */ + clear: function (bits) + { + this.beginDraw(); + + if (bits === undefined) + { + bits = this.autoClear; + } + + this.renderer.renderNodes.finishBatch(); + + this.renderer.gl.clear(bits); + }, + + /** + * Destroys the DrawingContext and its resources. + * + * @method Phaser.Renderer.WebGL.DrawingContext#destroy + * @since 4.0.0 + */ + destroy: function () + { + this.renderer.deleteTexture(this.texture); + this.renderer.deleteFramebuffer(this.state.bindings.framebuffer); + + this.renderer = null; + this.camera = null; + this.state = null; + this.framebuffer = null; + this.texture = null; + } +}); + +module.exports = DrawingContext; + + +/***/ }), + +/***/ 65656: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var DrawingContext = __webpack_require__(87774); + +/** + * @classdesc + * A pool of DrawingContexts. + * + * This class is used internally by the WebGLRenderer to manage DrawingContexts. + * It attempts to reuse DrawingContexts efficiently. When `get` is called, + * it will return a DrawingContext of the given dimensions, + * using the following priority: + * + * 1. A spare DrawingContext that has the same dimensions. + * 2. A spare DrawingContext that has not been used recently, resized. + * 3. A new DrawingContext, within the maximum pool size. + * 4. The oldest spare DrawingContext, resized. + * 5. A new DrawingContext, exceeding the maximum pool size. + * + * We assume that DrawingContexts of a given size are likely to be reused + * from frame to frame, so we try to preserve them for greater efficiency. + * + * @class DrawingContextPool + * @memberof Phaser.Renderer.WebGL + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this DrawingContextPool. + */ +var DrawingContextPool = new Class({ + initialize: function DrawingContextPool (renderer, maxAge, maxPoolSize) + { + /** + * The renderer that owns this DrawingContextPool. + * + * @name Phaser.Renderer.WebGL.DrawingContextPool#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The maximum age of a DrawingContext in milliseconds. + * After this time, the DrawingContext will be available for resizing. + * + * @name Phaser.Renderer.WebGL.DrawingContextPool#maxAge + * @type {number} + * @since 4.0.0 + */ + this.maxAge = maxAge; + + /** + * The maximum number of DrawingContexts to store. + * This is not a hard limit, but the pool will attempt to + * reuse DrawingContexts rather than create new ones. + * + * @name Phaser.Renderer.WebGL.DrawingContextPool#maxPoolSize + * @type {number} + * @since 4.0.0 + */ + this.maxPoolSize = maxPoolSize; + + /** + * The pool of DrawingContexts by age. + * This is an array of DrawingContexts, oldest first. + * + * @name Phaser.Renderer.WebGL.DrawingContextPool#agePool + * @type {Phaser.Renderer.WebGL.DrawingContext[]} + * @since 4.0.0 + */ + this.agePool = []; + + /** + * The pool of DrawingContexts by size. + * This is an object with keys of the form `${width}x${height}`. + * Each value is an array of DrawingContexts. + * + * @name Phaser.Renderer.WebGL.DrawingContextPool#sizePool + * @type {object} + * @since 4.0.0 + */ + this.sizePool = {}; + }, + + /** + * Adds a DrawingContext to the pool. + * This is used by a DrawingContext to signal that it is available for reuse. + * + * @method Phaser.Renderer.WebGL.DrawingContextPool#add + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The DrawingContext to add to the pool. + */ + add: function (drawingContext) + { + if (this.agePool.indexOf(drawingContext) !== -1) + { + return; + } + + var key = drawingContext.width + 'x' + drawingContext.height; + + if (this.sizePool[key]) + { + this.sizePool[key].push(drawingContext); + } + else + { + this.sizePool[key] = [ drawingContext ]; + } + + this.agePool.push(drawingContext); + }, + + /** + * Returns a DrawingContext of the given dimensions. + * + * @method Phaser.Renderer.WebGL.DrawingContextPool#get + * @since 4.0.0 + * @param {number} [width] - The width of the DrawingContext. + * @param {number} [height] - The height of the DrawingContext. + * @return {Phaser.Renderer.WebGL.DrawingContext} The DrawingContext. + */ + get: function (width, height) + { + var drawingContext; + + var index; + + var renderer = this.renderer; + if (width === undefined) { width = renderer.width; } + if (height === undefined) { height = renderer.height; } + if (width > 4096) { width = 4096; } + if (height > 4096) { height = 4096; } + + // Seek a DrawingContext of the given size. + + var key = width + 'x' + height; + + var sizePool = this.sizePool[key]; + + if (sizePool && sizePool.length > 0) + { + drawingContext = sizePool.pop(); + + // Extract the DrawingContext from the agePool + index = this.agePool.indexOf(drawingContext); + this.agePool.splice(index, 1); + + return drawingContext; + } + + // Seek a DrawingContext that is old enough to reuse. + + if (this.agePool.length > 0) + { + var now = Date.now(); + var maxAge = this.maxAge; + drawingContext = this.agePool[0]; + if (now - drawingContext.lastUsed > maxAge) + { + // Remove the DrawingContext from the agePool + this.agePool.shift(); + + // Remove the DrawingContext from the sizePool + var oldKey = drawingContext.width + 'x' + drawingContext.height; + sizePool = this.sizePool[oldKey]; + index = sizePool.indexOf(drawingContext); + sizePool.splice(index, 1); + + // Resize the DrawingContext + drawingContext.resize(width, height); + + return drawingContext; + } + } + + // Create a new DrawingContext within the pool size limit. + + if (this.agePool.length < this.maxPoolSize) + { + drawingContext = new DrawingContext(renderer, { + autoClear: true, + pool: this, + width: width, + height: height + }); + + return drawingContext; + } + + // Seek the oldest DrawingContext to resize. + + drawingContext = this.agePool.shift(); + if (drawingContext) + { + // Remove the DrawingContext from the sizePool + sizePool = this.sizePool[key]; + index = sizePool.indexOf(drawingContext); + sizePool.splice(index, 1); + + // Resize the DrawingContext + drawingContext.resize(width, height); + + return drawingContext; + } + + // Create a new DrawingContext exceeding the pool size limit. + + drawingContext = new DrawingContext(renderer, { + autoClear: true, + pool: this, + width: width, + height: height + }); + + return drawingContext; + }, + + /** + * Sets the maximum age of a DrawingContext in milliseconds. + * + * @method Phaser.Renderer.WebGL.DrawingContextPool#setMaxAge + * @since 4.0.0 + * @param {number} maxAge - The maximum age of a DrawingContext in milliseconds. + */ + setMaxAge: function (maxAge) + { + this.maxAge = maxAge; + }, + + /** + * Sets the maximum number of DrawingContexts to store. + * + * @method Phaser.Renderer.WebGL.DrawingContextPool#setMaxPoolSize + * @since 4.0.0 + * @param {number} maxPoolSize - The maximum number of DrawingContexts to store. + */ + setMaxPoolSize: function (maxPoolSize) + { + this.maxPoolSize = maxPoolSize; + }, + + /** + * Clears the DrawingContextPool. This will not destroy any DrawingContexts + * that are currently in use. + * + * @method Phaser.Renderer.WebGL.DrawingContextPool#clear + * @since 4.0.0 + */ + clear: function () + { + for (var i = 0; i < this.agePool.length; i++) + { + this.agePool[i].destroy(); + } + + this.sizePool = {}; + this.agePool.length = 0; + }, + + /** + * Prunes the DrawingContextPool down to the maximum pool size. + * Oldest DrawingContexts will be destroyed first. + * This will not destroy any DrawingContexts that are currently in use. + * + * @method Phaser.Renderer.WebGL.DrawingContextPool#prune + * @since 4.0.0 + */ + prune: function () + { + var sizePool = this.sizePool; + var agePool = this.agePool; + + var excess = agePool.length - this.maxPoolSize; + if (excess > 0) + { + var excessAgePool = agePool.splice(0, excess); + for (var i = 0; i < excess; i++) + { + var drawingContext = excessAgePool[i]; + var key = drawingContext.width + 'x' + drawingContext.height; + var sizePoolKey = sizePool[key]; + var index = sizePoolKey.indexOf(drawingContext); + sizePoolKey.splice(index, 1); + + drawingContext.destroy(); + } + } + } +}); + +module.exports = DrawingContextPool; + + +/***/ }), + +/***/ 56436: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var DeepCopy = __webpack_require__(62644); + +/** + * @classdesc + * The ProgramManager is a utility class used to manage + * instantiated shader programs and a suite of associated data, + * such as a VAO. It maintains a shared pool of uniforms, + * so if a different shader program is used, the uniforms + * can be applied to the new program. + * + * @class ProgramManager + * @memberof Phaser.Renderer.WebGL + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The current WebGLRenderer instance. + * @param {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout[]} attributeBufferLayouts - The attribute buffer layouts to use in the program. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} [indexBuffer] - The index buffer to use in the program, if any. + */ +var ProgramManager = new Class({ + initialize: function ProgramManager (renderer, attributeBufferLayouts, indexBuffer) + { + /** + * The current WebGLRenderer instance. + * + * @name Phaser.Renderer.WebGL.ProgramManager#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The index buffer to use in the program, if any. + * This is used to create a VAO. + * + * @name Phaser.Renderer.WebGL.ProgramManager#indexBuffer + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.indexBuffer = indexBuffer; + + /** + * The attribute buffer layouts to use in the program. + * These are used to create a VAO. + * + * @name Phaser.Renderer.WebGL.ProgramManager#attributeBufferLayouts + * @type {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout[]} + * @since 4.0.0 + */ + this.attributeBufferLayouts = attributeBufferLayouts; + + /** + * The key of the currently active shader program. + * + * @name Phaser.Renderer.WebGL.ProgramManager#currentProgramKey + * @type {?string} + * @since 4.0.0 + */ + this.currentProgramKey = null; + + /** + * The configuration object currently being assembled. + * + * @name Phaser.Renderer.WebGL.ProgramManager#currentConfig + * @type {object} + * @since 4.0.0 + */ + this.currentConfig = { + base: { + vertexShader: '', + fragmentShader: '' + }, + additions: [], + features: [] + }; + + /** + * A map of shader programs and associated data suite, + * identified by a unique key. + * + * Each key corresponds to an object of the following shape: + * + * - `program` (WebGLProgramWrapper) - The compiled shader program. + * - `vao` (WebGLVAOWrapper) - The VAO associated with the program. + * - `config` (object) - The configuration object used to create the program. + * + * @name Phaser.Renderer.WebGL.ProgramManager#programs + * @type {object} + * @since 4.0.0 + */ + this.programs = {}; + + /** + * A map of uniform values, identified by the shader uniform names. + * This allows uniforms to be kept between shader programs. + * + * @name Phaser.Renderer.WebGL.ProgramManager#uniforms + * @type {object} + * @since 4.0.0 + */ + this.uniforms = {}; + }, + + /** + * Returns a program suite based on the current configuration. + * If the program does not exist, it is created. + * + * The suite contains the following properties: + * + * - `program` (WebGLProgramWrapper) - The compiled shader program. + * - `vao` (WebGLVAOWrapper) - The VAO associated with the program. + * - `config` (object) - The configuration object used to create the program. + * + * If parallel shader compilation is enabled, + * the program may not be available immediately. + * In this case, `null` is returned. + * + * @method Phaser.Renderer.WebGL.ProgramManager#getCurrentProgramSuite + * @since 4.0.0 + * @return {?{ program: Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper, vao: Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper, config: object }} The program suite, or `null` if the program is not available. + */ + getCurrentProgramSuite: function () + { + var config = this.currentConfig; + var renderer = this.renderer; + var factory = renderer.shaderProgramFactory; + + var key = factory.getKey(config.base, config.additions, config.features); + + if (!this.programs[key]) + { + var program = factory.getShaderProgram(config.base, config.additions, config.features); + + if (program.compiling) + { + program.checkParallelCompile(); + } + + if (!program.compiling) + { + this.programs[key] = { + program: program, + vao: renderer.createVAO( + program, + this.indexBuffer, + this.attributeBufferLayouts + ), + config: DeepCopy(config) + }; + } + } + + return this.programs[key] || null; + }, + + /** + * Resets the current configuration object. + * + * @method Phaser.Renderer.WebGL.ProgramManager#resetCurrentConfig + * @since 4.0.0 + */ + resetCurrentConfig: function () + { + this.currentConfig.base.vertexShader = ''; + this.currentConfig.base.fragmentShader = ''; + this.currentConfig.additions.length = 0; + this.currentConfig.features.length = 0; + }, + + /** + * Set the value of a uniform, + * available for all shader programs in this manager. + * + * @method Phaser.Renderer.WebGL.ProgramManager#setUniform + * @since 4.0.0 + * @param {string} name - The name of the uniform. + * @param {any} value - The value of the uniform. + */ + setUniform: function (name, value) + { + this.uniforms[name] = value; + }, + + /** + * Delete a uniform value. While unused uniforms are not harmful, + * they do take time to process and can be a source of confusion. + * + * @method Phaser.Renderer.WebGL.ProgramManager#removeUniform + * @since 4.0.0 + * @param {string} name - The name of the uniform. + */ + removeUniform: function (name) + { + delete this.uniforms[name]; + }, + + /** + * Remove all uniforms. + * + * @method Phaser.Renderer.WebGL.ProgramManager#clearUniforms + * @since 4.0.0 + */ + clearUniforms: function () + { + this.uniforms.length = 0; + }, + + /** + * Set the stored uniforms on a shader program. + * + * @method Phaser.Renderer.WebGL.ProgramManager#applyUniforms + * @since 4.0.0 + */ + applyUniforms: function (program) + { + var uniforms = this.uniforms; + + for (var name in uniforms) + { + program.setUniform(name, uniforms[name]); + } + }, + + /** + * Set the base shader for the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#setBaseShader + * @since 4.0.0 + * @param {string} name - The name of the shader program. + * @param {string} vertexShader - The vertex shader source code. + * @param {string} fragmentShader - The fragment shader source code. + */ + setBaseShader: function (name, vertexShader, fragmentShader) + { + var base = this.currentConfig.base; + base.name = name; + base.vertexShader = vertexShader; + base.fragmentShader = fragmentShader; + }, + + /** + * Add a shader addition to the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#addAddition + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} addition - The shader addition to add. + * @param {number} [index] - The index at which to insert the addition. If not specified, it will be added at the end. + */ + addAddition: function (addition, index) + { + if (index === undefined) + { + this.currentConfig.additions.push(addition); + } + else + { + this.currentConfig.additions.splice(index, 0, addition); + } + }, + + /** + * Returns the addition with the given name. + * + * @method Phaser.Renderer.WebGL.ProgramManager#getAddition + * @since 4.0.0 + * @param {string} name - The name to find. + * @returns {?Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The addition, or `null` if it was not found. + */ + getAddition: function (name) + { + var additions = this.currentConfig.additions; + for (var i = 0; i < additions.length; i++) + { + var addition = additions[i]; + if (addition.name === name) + { + return addition; + } + } + return null; + }, + + /** + * Returns a list of shader additions in the current config + * that have a specific tag. + * + * @method Phaser.Renderer.WebGL.ProgramManager#getAdditionsByTag + * @since 4.0.0 + * @param {string} tag - The tag to filter by. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig[]} The shader additions with the tag. + */ + getAdditionsByTag: function (tag) + { + return this.currentConfig.additions.filter(function (addition) + { + if (!addition.tags) + { + return false; + } + return addition.tags.includes(tag); + }); + }, + + /** + * Returns the index of a shader addition with the given name. + * + * @method Phaser.Renderer.WebGL.ProgramManager#getAdditionIndex + * @since 4.0.0 + * @param {string} name - The name to find. + * @returns {number} The index of the addition, or `-1` if it was not found. + */ + getAdditionIndex: function (name) + { + return this.currentConfig.additions.findIndex(function (addition) + { + return addition.name === name; + }); + }, + + /** + * Remove a shader addition from the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#removeAddition + * @since 4.0.0 + * @param {string} name - The name of the shader addition to remove. + */ + removeAddition: function (name) + { + this.currentConfig.additions = this.currentConfig.additions.filter(function (addition) + { + return addition.name !== name; + }); + }, + + /** + * Replace a shader addition in the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#replaceAddition + * @since 4.0.0 + * @param {string} name - The name of the shader addition to replace. + * @param {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} addition - The new shader addition. + */ + replaceAddition: function (name, addition) + { + var index = this.currentConfig.additions.findIndex(function (a) + { + return a.name === name; + }); + + if (index !== -1) + { + this.currentConfig.additions[index] = addition; + } + }, + + /** + * Add a feature to the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#addFeature + * @since 4.0.0 + * @param {string} feature - The feature to add. + */ + addFeature: function (feature) + { + if (this.currentConfig.features.indexOf(feature) === -1) + { + this.currentConfig.features.push(feature); + } + }, + + /** + * Remove a feature from the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#removeFeature + * @since 4.0.0 + * @param {string} feature - The feature to remove. + */ + removeFeature: function (feature) + { + this.currentConfig.features = this.currentConfig.features.filter(function (f) + { + return f !== feature; + }); + }, + + /** + * Clear all features from the current configuration. + * + * @method Phaser.Renderer.WebGL.ProgramManager#clearFeatures + * @since 4.0.0 + */ + clearFeatures: function () + { + this.currentConfig.features.length = 0; + } +}); + +module.exports = ProgramManager; + + +/***/ }), + +/***/ 18804: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @typedef {object} BaseShaderConfig + * @property {string} name - The name of the shader program, used as a key. + * @property {string} vertexShader - The vertex shader source code. + * @property {string} fragmentShader - The fragment shader source code. + */ + +/** + * @classdesc + * The ShaderProgramFactory is a utility class used to generate + * {@link Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} objects. + * It facilitates generating variants of a shader program based on + * configuration settings. + * + * @class ShaderProgramFactory + * @memberof Phaser.Renderer.WebGL + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer that owns this ShaderProgramFactory. + */ +var ShaderProgramFactory = new Class({ + initialize: function ShaderProgramFactory (renderer) + { + /** + * The WebGLRenderer that owns this ShaderProgramFactory. + * + * @name Phaser.Renderer.WebGL.ShaderProgramFactory#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * A map of shader programs, identified by a unique key. + * + * The key of each shader program is made up of the following components: + * + * - The key of the base shader program. + * - The key of each shader addition, in addition order. + * - The key of each enabled shader feature, sorted alphabetically. + * + * @name Phaser.Renderer.WebGL.ShaderProgramFactory#programs + * @type {object} + * @since 4.0.0 + */ + this.programs = {}; + }, + + /** + * Checks if a shader program exists based on the given configuration settings. + * + * @method Phaser.Renderer.WebGL.ShaderProgramFactory#has + * @since 4.0.0 + * @param {string} key - The unique key of the shader program. + */ + has: function (key) + { + return this.programs[key] !== undefined; + }, + + /** + * Returns a shader program based on the given configuration settings. + * + * @method Phaser.Renderer.WebGL.ShaderProgramFactory#getShaderProgram + * @since 4.0.0 + * @param {BaseShaderConfig} base - The base shader configuration. + * @param {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig[]} [additions] - An array of shader addition configurations. + * @param {string[]} [features] - An array of enabled shader feature keys. + */ + getShaderProgram: function (base, additions, features) + { + var key = this.getKey(base, additions, features); + + var program = this.programs[key]; + + if (!program) + { + program = this.createShaderProgram(key, base, additions, features); + } + + return program; + }, + + /** + * Returns a unique key for a shader program based on the given configuration settings. + * + * The key is made up of the following components: + * + * - The key of the base shader program. + * - The key of each shader addition, in addition order. + * - The key of each enabled shader feature, sorted alphabetically. + * + * @method Phaser.Renderer.WebGL.ShaderProgramFactory#getKey + * @since 4.0.0 + * @param {BaseShaderConfig} base - The base shader configuration. + * @param {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig[]} [additions] - An array of shader addition configurations. + * @param {string[]} [features] - An array of enabled shader feature keys. + */ + getKey: function (base, additions, features) + { + var key = base.name; + + if (additions && additions.length > 0) + { + key += '_'; + for (var i = 0; i < additions.length; i++) + { + var addition = additions[i]; + if (!addition.disable) + { + key += '_' + addition.name; + } + } + } + + if (features && features.length > 0) + { + key += '__'; + key += features.sort().join('_'); + } + + return key; + }, + + /** + * Creates a shader program based on the given configuration settings. + * + * @method Phaser.Renderer.WebGL.ShaderProgramFactory#createShaderProgram + * @since 4.0.0 + * @param {string} name - The unique key of the shader program. + * @param {BaseShaderConfig} base - The base shader configuration. + * @param {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig[]} [additions] - An array of shader addition configurations. + * @param {string[]} [features] - An array of enabled shader feature keys. + */ + createShaderProgram: function (name, base, additions, features) + { + var vertexSource = base.vertexShader; + var fragmentSource = base.fragmentShader; + + // Remove carriage return characters from the shader source. + vertexSource = vertexSource.replace(/\r/g, ''); + fragmentSource = fragmentSource.replace(/\r/g, ''); + + if (additions) + { + var key, value; + var templates = {}; + + for (var i = 0; i < additions.length; i++) + { + var addition = additions[i]; + + if (addition.disable) + { + continue; + } + + for (key in addition.additions) + { + value = addition.additions[key]; + + // Remove carriage return characters from the shader source. + value = value.replace(/\r/g, ''); + + if (!templates[key]) + { + templates[key] = ''; + } + + templates[key] += value + '\n'; + } + } + + for (key in templates) + { + var template = '#pragma phaserTemplate(' + key + ')\n'; + value = templates[key]; + + vertexSource = vertexSource.replace(template, value); + fragmentSource = fragmentSource.replace(template, value); + } + } + + if (features) + { + var featureDefines = ''; + var reInvalid = /[^a-zA-Z0-9]/g; + + for (i = 0; i < features.length; i++) + { + var feature = features[i].toUpperCase().replace(reInvalid, '_'); + featureDefines += '#define FEATURE_' + feature + '\n'; + } + + vertexSource = vertexSource.replace('#pragma phaserTemplate(features)', featureDefines); + fragmentSource = fragmentSource.replace('#pragma phaserTemplate(features)', featureDefines); + } + + // Name the program after the key. + vertexSource = vertexSource.replace('#pragma phaserTemplate(shaderName)', '#define SHADER_NAME ' + name + '__VERTEX'); + fragmentSource = fragmentSource.replace('#pragma phaserTemplate(shaderName)', '#define SHADER_NAME ' + name + '__FRAGMENT'); + + // Remove any remaining template directives. + var rePragma = /\s*#pragma phaserTemplate\(.*/g; + vertexSource = vertexSource.replace(rePragma, ''); + fragmentSource = fragmentSource.replace(rePragma, ''); + + var program = this.renderer.createProgram(vertexSource, fragmentSource); + + this.programs[name] = program; + + return program; + } +}); + +module.exports = ShaderProgramFactory; + + +/***/ }), + +/***/ 70554: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @author Matthew Groves <@doormat> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); + +/** + * @namespace Phaser.Renderer.WebGL.Utils + * @since 3.0.0 + */ +module.exports = { + + /** + * Packs four floats on a range from 0.0 to 1.0 into a single Uint32 + * + * @function Phaser.Renderer.WebGL.Utils.getTintFromFloats + * @since 3.0.0 + * + * @param {number} r - Red component in a range from 0.0 to 1.0 + * @param {number} g - Green component in a range from 0.0 to 1.0 + * @param {number} b - Blue component in a range from 0.0 to 1.0 + * @param {number} a - Alpha component in a range from 0.0 to 1.0 + * + * @return {number} The packed RGBA values as a Uint32. + */ + getTintFromFloats: function (r, g, b, a) + { + var ur = ((r * 255) | 0) & 0xff; + var ug = ((g * 255) | 0) & 0xff; + var ub = ((b * 255) | 0) & 0xff; + var ua = ((a * 255) | 0) & 0xff; + + return ((ua << 24) | (ur << 16) | (ug << 8) | ub) >>> 0; + }, + + /** + * Packs a Uint24, representing RGB components, with a Float32, representing + * the alpha component, with a range between 0.0 and 1.0 and return a Uint32 + * + * @function Phaser.Renderer.WebGL.Utils.getTintAppendFloatAlpha + * @since 3.0.0 + * + * @param {number} rgb - Uint24 representing RGB components + * @param {number} a - Float32 representing Alpha component + * + * @return {number} Packed RGBA as Uint32 + */ + getTintAppendFloatAlpha: function (rgb, a) + { + var ua = ((a * 255) | 0) & 0xff; + + return ((ua << 24) | rgb) >>> 0; + }, + + /** + * Packs a Uint24, representing RGB components, with a Float32, representing + * the alpha component, with a range between 0.0 and 1.0 and return a + * swizzled Uint32 + * + * @function Phaser.Renderer.WebGL.Utils.getTintAppendFloatAlphaAndSwap + * @since 3.0.0 + * + * @param {number} rgb - Uint24 representing RGB components + * @param {number} a - Float32 representing Alpha component + * + * @return {number} Packed RGBA as Uint32 + */ + getTintAppendFloatAlphaAndSwap: function (rgb, a) + { + var ur = ((rgb >> 16) | 0) & 0xff; + var ug = ((rgb >> 8) | 0) & 0xff; + var ub = (rgb | 0) & 0xff; + var ua = ((a * 255) | 0) & 0xff; + + return ((ua << 24) | (ub << 16) | (ug << 8) | ur) >>> 0; + }, + + /** + * Unpacks a Uint24 RGB into an array of floats of ranges of 0.0 and 1.0 + * + * @function Phaser.Renderer.WebGL.Utils.getFloatsFromUintRGB + * @since 3.0.0 + * + * @param {number} rgb - RGB packed as a Uint24 + * + * @return {array} Array of floats representing each component as a float + */ + getFloatsFromUintRGB: function (rgb) + { + var ur = ((rgb >> 16) | 0) & 0xff; + var ug = ((rgb >> 8) | 0) & 0xff; + var ub = (rgb | 0) & 0xff; + + return [ ur / 255, ug / 255, ub / 255 ]; + }, + + /** + * Check to see how many texture units the GPU supports in a fragment shader + * and if the value specific in the game config is allowed. + * + * This value is hard-clamped to 16 for performance reasons on Android devices. + * + * @function Phaser.Renderer.WebGL.Utils.checkShaderMax + * @since 3.50.0 + * + * @param {WebGLRenderingContext} gl - The WebGLContext used to create the shaders. + * @param {number} maxTextures - The Game Config maxTextures value. + * + * @return {number} The number of texture units that is supported by this browser and GPU. + */ + checkShaderMax: function (gl, maxTextures) + { + // Note: This is the maximum number of TIUs that a _fragment_ shader supports + // https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_Unit + + // Hard-clamp this to 16 to avoid run-away texture counts such as on Android + var gpuMax = Math.min(16, gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)); + + if (!maxTextures || maxTextures === -1) + { + return gpuMax; + } + else + { + return Math.min(gpuMax, maxTextures); + } + }, + + /** + * Update lighting uniforms for a given shader program manager. + * This is a standard procedure for most lighting shaders. + * + * @function Phaser.Renderer.WebGL.Utils.updateLightingUniforms + * @since 4.0.0 + * @webglOnly + * + * @param {boolean} enable - Whether to enable lighting. + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The DrawingContext instance. + * @param {Phaser.Renderer.WebGL.ProgramManager} programManager - The ShaderProgramManager instance. + * @param {number} textureUnit - The texture unit to use for the normal map. + * @param {Phaser.Math.Vector2} vec - A Vector2 instance. + * @param {boolean} [selfShadow] - Whether to enable self-shadowing. + * @param {number} [selfShadowPenumbra] - The penumbra value for self-shadowing. + * @param {number} [selfShadowThreshold] - The threshold value for self-shadowing. + */ + updateLightingUniforms: function ( + enable, + renderer, + drawingContext, + programManager, + textureUnit, + vec, + selfShadow, + selfShadowPenumbra, + selfShadowThreshold + ) + { + var camera = drawingContext.camera; + var scene = camera.scene; + var lightManager = scene.sys.lights; + + if (!lightManager || !lightManager.active) + { + return; + } + + + var lights = lightManager.getLights(camera); + var lightsCount = lights.length; + var ambientColor = lightManager.ambientColor; + var height = renderer.height; + + if (enable) + { + programManager.setUniform( + 'uNormSampler', + textureUnit + ); + + programManager.setUniform( + 'uCamera', + [ + camera.x, + camera.y, + camera.rotation, + camera.zoom + ] + ); + programManager.setUniform( + 'uAmbientLightColor', + [ + ambientColor.r, + ambientColor.g, + ambientColor.b + ] + ); + programManager.setUniform( + 'uLightCount', + lightsCount + ); + + var camMatrix = new TransformMatrix(); + + for (var i = 0; i < lightsCount; i++) + { + var light = lights[i].light; + var color = light.color; + + var lightName = 'uLights[' + i + '].'; + + camMatrix.copyWithScrollFactorFrom( + camera.matrixCombined, + camera.scrollX, camera.scrollY, + light.scrollFactorX, light.scrollFactorY + ); + camMatrix.transformPoint( + light.x, + light.y, + vec + ); + + programManager.setUniform( + lightName + 'position', + [ + vec.x, + height - (vec.y), + light.z * camera.zoom + ] + ); + programManager.setUniform( + lightName + 'color', + [ + color.r, + color.g, + color.b + ] + ); + programManager.setUniform( + lightName + 'intensity', + light.intensity + ); + programManager.setUniform( + lightName + 'radius', + light.radius + ); + } + + if (selfShadow) + { + // Self-shadowing uniforms. + programManager.setUniform( + 'uDiffuseFlatThreshold', + selfShadowThreshold * 3 + ); + + programManager.setUniform( + 'uPenumbra', + selfShadowPenumbra + ); + } + } + else + { + // Clear lighting uniforms. + programManager.removeUniform('uNormSampler'); + programManager.removeUniform('uCamera'); + programManager.removeUniform('uAmbientLightColor'); + programManager.removeUniform('uLightCount'); + + programManager.removeUniform('uPenumbra'); + programManager.removeUniform('uDiffuseFlatThreshold'); + + for (i = 0; i < lightsCount; i++) + { + lightName = 'uLights[' + i + '].'; + + programManager.removeUniform(lightName + 'position'); + programManager.removeUniform(lightName + 'color'); + programManager.removeUniform(lightName + 'intensity'); + programManager.removeUniform(lightName + 'radius'); + } + } + } +}; + + +/***/ }), + +/***/ 74797: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Felipe Alfonso <@bitnenfer> + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayEach = __webpack_require__(95428); +var ArrayRemove = __webpack_require__(72905); +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(8054); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(92503); +var IsSizePowerOfTwo = __webpack_require__(50030); +var Matrix4 = __webpack_require__(37867); +var NOOP = __webpack_require__(29747); +var DrawingContext = __webpack_require__(87774); +var ScaleEvents = __webpack_require__(97480); +var TextureEvents = __webpack_require__(69442); +var Utils = __webpack_require__(70554); +var WebGLSnapshot = __webpack_require__(88815); +var WebGLBufferWrapper = __webpack_require__(26128); +var WebGLGlobalWrapper = __webpack_require__(37959); +var WebGLProgramWrapper = __webpack_require__(1482); +var WebGLShaderSetterWrapper = __webpack_require__(86272); +var WebGLTextureWrapper = __webpack_require__(82751); +var WebGLTextureUnitsWrapper = __webpack_require__(13760); +var WebGLFramebufferWrapper = __webpack_require__(84387); +var WebGLVAOWrapper = __webpack_require__(85788); +var WebGLBlendParametersFactory = __webpack_require__(47774); +var WebGLGlobalParametersFactory = __webpack_require__(53314); +var RenderNodeManager = __webpack_require__(30130); +var DrawingContextPool = __webpack_require__(65656); +var ShaderProgramFactory = __webpack_require__(18804); + +var DEBUG = false; + +if (false) +{ var SPECTOR; } + +/** + * @callback WebGLContextCallback + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer which owns the context. + */ + +/** + * @classdesc + * WebGLRenderer is a class that contains the needed functionality to keep the + * WebGLRenderingContext state clean. The main idea of the WebGLRenderer is to keep track of + * any context change that happens for WebGL rendering inside of Phaser. This means + * if raw webgl functions are called outside the WebGLRenderer of the Phaser WebGL + * rendering ecosystem they might pollute the current WebGLRenderingContext state producing + * unexpected behavior. It's recommended that WebGL interaction is done through + * WebGLRenderer and/or built-in RenderNodes. + * + * Persistent WebGL objects are stored in "wrappers" which are created by the WebGLRenderer. + * Wrappers contain WebGL objects and metadata about those objects. + * This can be used to recreate the WebGL state after a context loss. + * Prefer to pass references to the wrappers, rather than the raw WebGL objects, + * as the raw objects may be destroyed or replaced at any time. + * Extract them only when needed. + * + * WebGL state, such as blend mode or texture units, is managed by the WebGLRenderer. + * Use `WebGLRenderer.glWrapper` to manage the current state + * rather than setting it directly on the WebGLRenderingContext. + * The state wrapper will ensure that the state is only set if it has changed, + * and can restore the state after a context loss or external render call. + * + * @class WebGLRenderer + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Renderer.WebGL + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Game instance which owns this WebGL Renderer. + */ +var WebGLRenderer = new Class({ + + Extends: EventEmitter, + + initialize: + + function WebGLRenderer (game) + { + EventEmitter.call(this); + + var gameConfig = game.config; + + var contextCreationConfig = { + alpha: gameConfig.transparent, + desynchronized: gameConfig.desynchronized, + depth: true, + antialias: gameConfig.antialiasGL, + premultipliedAlpha: gameConfig.premultipliedAlpha, + stencil: true, + failIfMajorPerformanceCaveat: gameConfig.failIfMajorPerformanceCaveat, + powerPreference: gameConfig.powerPreference, + preserveDrawingBuffer: gameConfig.preserveDrawingBuffer, + willReadFrequently: false + }; + + /** + * The local configuration settings of this WebGL Renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#config + * @type {object} + * @since 3.0.0 + */ + this.config = { + clearBeforeRender: gameConfig.clearBeforeRender, + antialias: gameConfig.antialias, + backgroundColor: gameConfig.backgroundColor, + contextCreation: contextCreationConfig, + roundPixels: gameConfig.roundPixels, + pathDetailThreshold: gameConfig.pathDetailThreshold, + maxTextures: gameConfig.maxTextures, + maxTextureSize: gameConfig.maxTextureSize, + batchSize: gameConfig.batchSize, + maxLights: gameConfig.maxLights, + mipmapFilter: gameConfig.mipmapFilter + }; + + /** + * The Game instance which owns this WebGL Renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game = game; + + /** + * A constant which allows the renderer to be easily identified as a WebGL Renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#type + * @type {number} + * @since 3.0.0 + */ + this.type = CONST.WEBGL; + + /** + * An instance of the RenderNodeManager class which handles all + * RenderNodes used by the WebGLRenderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#renderNodes + * @type {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} + * @since 4.0.0 + */ + this.renderNodes = null; + + /** + * The RenderNode to use for rendering individual cameras. + * + * This will be populated during the `boot` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#cameraRenderNode + * @type {Phaser.Renderer.WebGL.RenderNodes.RenderNode} + * @since 4.0.0 + */ + this.cameraRenderNode = null; + + /** + * The shader program factory for managing variant shaders. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#shaderProgramFactory + * @type {Phaser.Renderer.WebGL.ShaderProgramFactory} + * @since 4.0.0 + */ + this.shaderProgramFactory = new ShaderProgramFactory(this); + + /** + * The width of the canvas being rendered to. + * This is populated in the onResize event handler. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#width + * @type {number} + * @since 3.0.0 + */ + this.width = 0; + + /** + * The height of the canvas being rendered to. + * This is populated in the onResize event handler. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#height + * @type {number} + * @since 3.0.0 + */ + this.height = 0; + + /** + * The canvas which this WebGL Renderer draws to. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#canvas + * @type {HTMLCanvasElement} + * @since 3.0.0 + */ + this.canvas = game.canvas; + + /** + * An array of blend modes supported by the WebGL Renderer. + * + * This array includes the default blend modes as well as any custom blend modes added through {@link #addBlendMode}. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#blendModes + * @type {Phaser.Types.Renderer.WebGL.WebGLBlendParameters[]} + * @default [] + * @since 3.0.0 + */ + this.blendModes = []; + + /** + * This property is set to `true` if the WebGL context of the renderer is lost. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#contextLost + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.contextLost = false; + + /** + * Details about the currently scheduled snapshot. + * + * If a non-null `callback` is set in this object, a snapshot of the canvas will be taken after the current frame is fully rendered. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#snapshotState + * @type {Phaser.Types.Renderer.Snapshot.SnapshotState} + * @since 3.0.0 + */ + this.snapshotState = { + x: 0, + y: 0, + width: 1, + height: 1, + getPixel: false, + callback: null, + type: 'image/png', + encoder: 0.92, + isFramebuffer: false, + bufferWidth: 0, + bufferHeight: 0, + unpremultiplyAlpha: true + }; + + /** + * The maximum number of textures the GPU can handle. The minimum under the WebGL1 spec is 8. + * This is set via the Game Config `maxTextures` property and should never be changed after boot. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#maxTextures + * @type {number} + * @since 3.50.0 + */ + this.maxTextures = 0; + + /** + * A list containing the indices of all available texture units. + * This is populated during the `init` method. + * It is used internally to connect texture units to shaders. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#textureUnitIndices + * @type {number[]} + * @since 4.0.0 + */ + this.textureUnitIndices = []; + + /** + * A list of all WebGLBufferWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glBufferWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper[]} + * @since 3.80.0 + */ + this.glBufferWrappers = []; + + /** + * A list of all WebGLProgramWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glProgramWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper[]} + * @since 3.80.0 + */ + this.glProgramWrappers = []; + + /** + * A list of all WebGLTextureWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glTextureWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} + * @since 3.80.0 + */ + this.glTextureWrappers = []; + + /** + * A list of all WebGLFramebufferWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glFramebufferWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper[]} + * @since 3.80.0 + */ + this.glFramebufferWrappers = []; + + /** + * A list of all WebGLVAOWrappers that have been created by this renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glVAOWrappers + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper[]} + * @since 4.0.0 + */ + this.glVAOWrappers = []; + + /** + * A generic vertex buffer. This should be used by any process + * which doesn't need persistent vertex data. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#genericVertexBuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.genericVertexBuffer = null; + + /** + * Data for a generic vertex buffer. This is used to update the + * `genericVertexBuffer`. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#genericVertexData + * @type {ArrayBuffer} + * @since 4.0.0 + */ + this.genericVertexData = null; + + /** + * A generic quad index buffer. This is a READ-ONLY buffer. + * It describes the four corners of a quad, + * a structure which is used in several places in the renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#genericQuadIndexBuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + * @readonly + */ + this.genericQuadIndexBuffer = null; + + /** + * The DrawingContext used for the base canvas. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#baseDrawingContext + * @type {Phaser.Renderer.WebGL.DrawingContext} + * @since 4.0.0 + */ + this.baseDrawingContext = null; + + /** + * The camera currently being rendered by `render`. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#currentViewCamera + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 4.0.0 + * @default null + */ + this.currentViewCamera = null; + + /** + * A pool of DrawingContexts which can be reused. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#drawingContextPool + * @type {Phaser.Renderer.WebGL.DrawingContextPool} + * @since 4.0.0 + */ + this.drawingContextPool = new DrawingContextPool(this, 1000, 1024); + + /** + * The handler to invoke when the context is lost. + * This should not be changed and is set in the boot method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#contextLostHandler + * @type {function} + * @since 3.19.0 + */ + this.contextLostHandler = NOOP; + + /** + * The handler to invoke when the context is restored. + * This should not be changed and is set in the boot method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#contextRestoredHandler + * @type {function} + * @since 3.19.0 + */ + this.contextRestoredHandler = NOOP; + + /** + * The previous contextLostHandler that was in use. + * This is set when `setContextHandlers` is called. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#previousContextLostHandler + * @type {function} + * @since 3.85.0 + */ + this.previousContextLostHandler = NOOP; + + /** + * The previous contextRestoredHandler that was in use. + * This is set when `setContextHandlers` is called. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#previousContextRestoredHandler + * @type {function} + * @since 3.85.0 + */ + this.previousContextRestoredHandler = NOOP; + + /** + * The underlying WebGL context of the renderer. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#gl + * @type {WebGLRenderingContext} + * @default null + * @since 3.0.0 + */ + this.gl = null; + + /** + * The current WebGLRenderingContext state. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glWrapper + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper} + * @default null + * @since 4.0.0 + */ + this.glWrapper = null; + + /** + * The current WebGL texture units in use. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glTextureUnits + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper} + * @default null + * @since 4.0.0 + */ + this.glTextureUnits = null; + + /** + * Array of strings that indicate which WebGL extensions are supported by the browser. + * This is populated in the `setExtensions` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#supportedExtensions + * @type {string[]} + * @default null + * @since 3.0.0 + */ + this.supportedExtensions = null; + + /** + * If the browser supports the `ANGLE_instanced_arrays` extension, this property will hold + * a reference to the glExtension for it. + * + * This is populated in the `setExtensions` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#instancedArraysExtension + * @type {ANGLE_instanced_arrays} + * @default null + * @since 3.50.0 + */ + this.instancedArraysExtension = null; + + /** + * If the browser supports the `KHR_parallel_shader_compile` extension, + * this property will hold a reference to the glExtension for it. + * + * This is populated in the `setExtensions` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#parallelShaderCompileExtension + * @type {KHR_parallel_shader_compile} + * @default null + * @since 4.0.0 + */ + this.parallelShaderCompileExtension = null; + + /** + * If the browser supports the `OES_standard_derivatives` extension, + * and the `smoothPixelArt` config option is true, + * this property will hold a reference to the glExtension for it. + * + * This is populated in the `setExtensions` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#standardDerivativesExtension + * @type {OES_standard_derivatives} + * @default null + * @since 4.0.0 + */ + this.standardDerivativesExtension = null; + + /** + * If the browser supports the `OES_vertex_array_object` extension, this property will hold + * a reference to the glExtension for it. + * + * This is populated in the `setExtensions` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#vaoExtension + * @type {OES_vertex_array_object} + * @default null + * @since 3.50.0 + */ + this.vaoExtension = null; + + /** + * The WebGL Extensions loaded into the current context. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#extensions + * @type {object} + * @default {} + * @since 3.0.0 + */ + this.extensions = {}; + + /** + * Stores the current WebGL component formats for further use. + * + * This array is populated in the `init` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#glFormats + * @type {array} + * @since 3.2.0 + */ + this.glFormats; + + /** + * Stores the WebGL texture compression formats that this device and browser supports. + * + * Support for using compressed texture formats was added in Phaser version 3.60. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#compression + * @type {Phaser.Types.Renderer.WebGL.WebGLTextureCompression} + * @since 3.8.0 + */ + this.compression; + + /** + * Cached drawing buffer height to reduce gl calls. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#drawingBufferHeight + * @type {number} + * @readonly + * @since 3.11.0 + */ + this.drawingBufferHeight = 0; + + /** + * A blank 32x32 transparent texture, as used by the Graphics system where needed. + * This is set in the `boot` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#blankTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @readonly + * @since 3.12.0 + */ + this.blankTexture = null; + + /** + * A blank 1x1 #7f7fff texture, a flat normal map, + * as used by the Graphics system where needed. + * This is set in the `boot` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#normalTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @readonly + * @since 3.80.0 + */ + this.normalTexture = null; + + /** + * A pure white 4x4 texture, as used by the Graphics system where needed. + * This is set in the `boot` method. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#whiteTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @readonly + * @since 3.50.0 + */ + this.whiteTexture = null; + + /** + * Internal gl function mapping for uniform and attribute look-up. + * + * https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniform + * + * https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#shaderSetters + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLShaderSetterWrapper} + * @since 4.0.0 + */ + this.shaderSetters = null; + + /** + * The mipmap magFilter to be used when creating textures. + * + * You can specify this as a string in the game config, i.e.: + * + * `render: { mipmapFilter: 'NEAREST_MIPMAP_LINEAR' }` + * + * The 6 options for WebGL1 are, in order from least to most computationally expensive: + * + * NEAREST (for pixel art) + * LINEAR (the default) + * NEAREST_MIPMAP_NEAREST + * LINEAR_MIPMAP_NEAREST + * NEAREST_MIPMAP_LINEAR + * LINEAR_MIPMAP_LINEAR + * + * Mipmaps only work with textures that are fully power-of-two in size. + * + * For more details see https://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html + * + * As of v3.60 no mipmaps will be generated unless a string is given in + * the game config. This saves on VRAM use when it may not be required. + * To obtain the previous result set the property to `LINEAR` in the config. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#mipmapFilter + * @type {GLenum} + * @since 3.21.0 + */ + this.mipmapFilter = null; + + /** + * Has this renderer fully booted yet? + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#isBooted + * @type {boolean} + * @since 3.50.0 + */ + this.isBooted = false; + + /** + * The global game Projection matrix, used by shaders as 'uProjectionMatrix' uniform. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#projectionMatrix + * @type {Phaser.Math.Matrix4} + * @since 3.50.0 + */ + this.projectionMatrix; + + /** + * The cached width of the Projection matrix. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#projectionWidth + * @type {number} + * @since 3.50.0 + */ + this.projectionWidth = 0; + + /** + * The cached height of the Projection matrix. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#projectionHeight + * @type {number} + * @since 3.50.0 + */ + this.projectionHeight = 0; + + /** + * The cached flipY state of the Projection matrix. + * + * This is usually `false`, preserving WebGL coordinate space. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#projectionFlipY + * @type {boolean} + * @since 4.0.0 + */ + this.projectionFlipY = false; + + /** + * An instance of SpectorJS used for WebGL Debugging. + * + * Only available in the Phaser Debug build. + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#spector + * @type {function} + * @since 3.60.0 + */ + this.spector = null; + + /** + * Is Spector currently capturing a WebGL frame? + * + * @name Phaser.Renderer.WebGL.WebGLRenderer#_debugCapture + * @type {boolean} + * @private + * @since 3.60.0 + */ + this._debugCapture = false; + + this.init(this.config); + }, + + /** + * Creates a new WebGLRenderingContext and initializes all internal state. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#init + * @since 3.0.0 + * + * @param {object} config - The configuration object for the renderer. + * + * @return {this} This WebGLRenderer instance. + */ + init: function (config) + { + var gl; + var game = this.game; + var canvas = this.canvas; + var clearColor = config.backgroundColor; + + if (DEBUG) + { + this.spector = new SPECTOR.Spector(); + + this.spector.onCapture.add(this.onCapture.bind(this)); + } + + // Did they provide their own context? + if (game.config.context) + { + gl = game.config.context; + } + else + { + gl = canvas.getContext('webgl', config.contextCreation) || canvas.getContext('experimental-webgl', config.contextCreation); + } + + if (!gl || gl.isContextLost()) + { + this.contextLost = true; + + throw new Error('WebGL unsupported'); + } + + this.gl = gl; + + this.setExtensions(); + + this.setContextHandlers(); + + // Set it back into the Game, so developers can access it from there too + game.context = gl; + + for (var i = 0; i <= 27; i++) + { + this.blendModes.push(WebGLBlendParametersFactory.createCombined(this)); + } + + // ADD + this.blendModes[1].func = [ gl.ONE, gl.DST_ALPHA, gl.ONE, gl.DST_ALPHA ]; + + // MULTIPLY + this.blendModes[2].func = [ gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA, gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA ]; + + // SCREEN + this.blendModes[3].func = [ gl.ONE, gl.ONE_MINUS_SRC_COLOR, gl.ONE, gl.ONE_MINUS_SRC_COLOR ]; + + // ERASE + this.blendModes[17].equation = [ gl.FUNC_REVERSE_SUBTRACT, gl.FUNC_REVERSE_SUBTRACT ]; + this.blendModes[17].func = [ gl.ZERO, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE_MINUS_SRC_ALPHA ]; + + this.glFormats = [ gl.BYTE, gl.SHORT, gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT, gl.FLOAT ]; + + this.shaderSetters = new WebGLShaderSetterWrapper(this); + + if (!config.maxTextures || config.maxTextures === -1) + { + config.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + } + + if (!config.maxTextureSize) + { + config.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); + } + + this.compression = this.getCompressedTextures(); + + // Setup initial WebGL state + this.glWrapper = new WebGLGlobalWrapper(this); + this.glWrapper.update(undefined, true); + + gl.clearColor(clearColor.redGL, clearColor.greenGL, clearColor.blueGL, clearColor.alphaGL); + + // Mipmaps + var validMipMaps = [ 'NEAREST', 'LINEAR', 'NEAREST_MIPMAP_NEAREST', 'LINEAR_MIPMAP_NEAREST', 'NEAREST_MIPMAP_LINEAR', 'LINEAR_MIPMAP_LINEAR' ]; + + if (validMipMaps.indexOf(config.mipmapFilter) !== -1) + { + this.mipmapFilter = gl[config.mipmapFilter]; + } + + // Check maximum supported textures + this.maxTextures = Utils.checkShaderMax(gl, config.maxTextures); + for (i = 0; i < this.maxTextures; i++) + { + this.textureUnitIndices.push(i); + } + + this.glTextureUnits = new WebGLTextureUnitsWrapper(this); + + this.projectionMatrix = new Matrix4().identity(); + + game.textures.once(TextureEvents.READY, this.boot, this); + + return this; + }, + + /** + * Internal boot handler. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#boot + * @private + * @since 3.11.0 + */ + boot: function () + { + var game = this.game; + var gl = this.gl; + + var baseSize = game.scale.baseSize; + + var width = baseSize.width; + var height = baseSize.height; + + this.width = width; + this.height = height; + + this.isBooted = true; + + // Provision the generic vertex buffer. + // The size is determined by the maximum number of vertices we want + // to handle. + // This is usually determined by the maximum amount of data we can index + // with a 16-bit unsigned integer. + // There are 65536 indices possible with 16 bits. + // We actually use a number of indices equal to the batch size + // multiplied by 4 (each batch item is a quad with 4 vertices), + // although this number is 65536 (16384 * 4) by default. + // Each index represents a vertex with 16 possible attributes. + // Each attribute has a maximum size of 4 floats. + // Each float is 4 bytes. + var genericVertexBytes = game.config.batchSize * 4 * 16 * 4 * 4; + this.genericVertexData = new ArrayBuffer(genericVertexBytes); + this.genericVertexBuffer = this.createVertexBuffer(this.genericVertexData, gl.DYNAMIC_DRAW); + + // Provision the generic quad index buffer. + // Ensure that there is no VAO bound, because the following index buffer + // will modify any currently bound VAO. + this.glWrapper.updateVAO({ vao: null }); + this.genericQuadIndexBuffer = this.createIndexBuffer(new Uint16Array([ 0, 1, 2, 3 ]), gl.STATIC_DRAW); + + // Set up render nodes. + this.renderNodes = new RenderNodeManager(this); + + this.cameraRenderNode = this.renderNodes.getNode('Camera'); + + // Set-up default textures, fbo and scissor + + this.blankTexture = game.textures.getFrame('__DEFAULT').glTexture; + this.normalTexture = game.textures.getFrame('__NORMAL').glTexture; + this.whiteTexture = game.textures.getFrame('__WHITE').glTexture; + + // Set up drawing contexts. + this.baseDrawingContext = new DrawingContext(this, + { + autoClear: true, + useCanvas: true, + clearColor: [ + this.config.backgroundColor.redGL, + this.config.backgroundColor.greenGL, + this.config.backgroundColor.blueGL, + this.config.backgroundColor.alphaGL + ] + } + ); + this.on(Events.RESIZE, this.baseDrawingContext.resize, this.baseDrawingContext); + + game.scale.on(ScaleEvents.RESIZE, this.onResize, this); + + this.resize(width, height); + }, + + /** + * Queries the GL context to get the supported extensions. + * + * Then sets them into the `supportedExtensions`, `instancedArraysExtension` and `vaoExtension` properties. + * + * Called automatically during the `init` method. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#setExtensions + * @since 3.85.2 + */ + setExtensions: function () + { + var gl = this.gl; + var game = this.game; + + var exts = gl.getSupportedExtensions(); + + this.supportedExtensions = exts; + + var angleString = 'ANGLE_instanced_arrays'; + + this.instancedArraysExtension = (exts.indexOf(angleString) > -1) ? gl.getExtension(angleString) : null; + + if (game.config.skipUnreadyShaders) + { + var parallelShaderCompileString = 'KHR_parallel_shader_compile'; + + this.parallelShaderCompileExtension = (exts.indexOf(parallelShaderCompileString) > -1) ? gl.getExtension(parallelShaderCompileString) : null; + + if (!this.parallelShaderCompileExtension) + { + // Disable the option if the extension is not supported. + game.config.skipUnreadyShaders = false; + } + } + + var vaoString = 'OES_vertex_array_object'; + + this.vaoExtension = (exts.indexOf(vaoString) > -1) ? gl.getExtension(vaoString) : null; + + if (game.config.smoothPixelArt) + { + var stdDerivativesString = 'OES_standard_derivatives'; + + this.standardDerivativesExtension = (exts.indexOf(stdDerivativesString) > -1) ? gl.getExtension(stdDerivativesString) : null; + } + }, + + /** + * Sets the handlers that are called when WebGL context is lost or restored by the browser. + * + * The default handlers are referenced via the properties `WebGLRenderer.contextLostHandler` and `WebGLRenderer.contextRestoredHandler`. + * By default, these map to the methods `WebGLRenderer.dispatchContextLost` and `WebGLRenderer.dispatchContextRestored`. + * + * You can override these handlers with your own via this method. + * + * If you do override them, make sure that your handlers invoke the methods `WebGLRenderer.dispatchContextLost` and `WebGLRenderer.dispatchContextRestored` in due course, otherwise the renderer will not be able to restore itself fully. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#setContextHandlers + * @since 3.85.0 + * + * * @param {function} [contextLost] - Custom handler for responding to the WebGL context lost event. Set as `undefined` to use the default handler. + * @param {function} [contextRestored] - Custom handler for responding to the WebGL context restored event. Set as `undefined` to use the default handler. + */ + setContextHandlers: function (contextLost, contextRestored) + { + if (this.previousContextLostHandler) + { + this.canvas.removeEventListener('webglcontextlost', this.previousContextLostHandler, false); + } + if (this.previousContextRestoredHandler) + { + this.canvas.removeEventListener('webglcontextlost', this.previousContextRestoredHandler, false); + } + + if (typeof contextLost === 'function') + { + this.contextLostHandler = contextLost.bind(this); + } + else + { + this.contextLostHandler = this.dispatchContextLost.bind(this); + } + + if (typeof contextRestored === 'function') + { + this.contextRestoredHandler = contextRestored.bind(this); + } + else + { + this.contextRestoredHandler = this.dispatchContextRestored.bind(this); + } + + this.canvas.addEventListener('webglcontextlost', this.contextLostHandler, false); + this.canvas.addEventListener('webglcontextrestored', this.contextRestoredHandler, false); + + this.previousContextLostHandler = this.contextLostHandler; + this.previousContextRestoredHandler = this.contextRestoredHandler; + }, + + /** + * This method is called when the WebGL context is lost. By default this is bound to the property `WebGLRenderer.contextLostHandler`. + * If you override the context loss handler via the `setContextHandlers` method then be sure to invoke this method in due course. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#dispatchContextLost + * @since 3.85.0 + * + * @param {WebGLContextEvent } event - The WebGL context lost Event. + */ + dispatchContextLost: function (event) + { + this.contextLost = true; + + if (console) + { + console.warn('WebGL Context lost. Renderer disabled'); + } + + this.emit(Events.LOSE_WEBGL, this); + + event.preventDefault(); + }, + + /** + * This method is called when the WebGL context is restored. By default this is bound to the property `WebGLRenderer.contextRestoredHandler`. + * If you override the context restored handler via the `setContextHandlers` method then be sure to invoke this method in due course. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#dispatchContextRestored + * @since 3.85.0 + * + * @param {WebGLContextEvent } event - The WebGL context restored Event. + + */ + dispatchContextRestored: function (event) + { + var gl = this.gl; + + if (gl.isContextLost()) + { + if (console) + { + console.log('WebGL Context restored, but context is still lost'); + } + + return; + } + + // Restore GL extensions. + this.setExtensions(); + + // Force update the GL state. + this.glWrapper.update(WebGLGlobalParametersFactory.getDefault(this), true); + this.glTextureUnits.init(); + + // Re-enable compressed texture formats. + this.compression = this.getCompressedTextures(); + + // Restore wrapped GL objects. + // Order matters, as some wrappers depend on others. + var wrapperCreateResource = function (wrapper) + { + wrapper.createResource(); + }; + ArrayEach(this.glTextureWrappers, wrapperCreateResource); + ArrayEach(this.glBufferWrappers, wrapperCreateResource); + ArrayEach(this.glFramebufferWrappers, wrapperCreateResource); + ArrayEach(this.glProgramWrappers, wrapperCreateResource); + ArrayEach(this.glVAOWrappers, wrapperCreateResource); + + // Restore texture unit assignment. + this.glTextureUnits.bindUnits(this.glTextureUnits.units, true); + + // Apply resize. + this.resize(this.game.scale.baseSize.width, this.game.scale.baseSize.height); + + // Context has been restored. + + this.contextLost = false; + + if (console) + { + console.warn('WebGL Context restored. Renderer running again.'); + } + + this.emit(Events.RESTORE_WEBGL, this); + + event.preventDefault(); + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Phaser v3.60 Debug has a build of Spector.js embedded in it, which is a WebGL inspector + * that allows for live inspection of your WebGL calls. Although it's easy to add the Spector + * extension to a desktop browsr, by embedding it in Phaser we can make it available in mobile + * browsers too, making it a powerful tool for debugging WebGL games on mobile devices where + * extensions are not permitted. + * + * See https://github.com/BabylonJS/Spector.js for more details. + * + * This method will capture the current WebGL frame and send it to the Spector.js tool for inspection. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#captureFrame + * @since 3.60.0 + * + * @param {boolean} [quickCapture=false] - If `true` thumbnails are not captured in order to speed up the capture. + * @param {boolean} [fullCapture=false] - If `true` all details are captured. + */ + captureFrame: function (quickCapture, fullCapture) + { + if (quickCapture === undefined) { quickCapture = false; } + if (fullCapture === undefined) { fullCapture = false; } + + if (DEBUG && this.spector && !this._debugCapture) + { + this.spector.captureCanvas(this.canvas, 0, quickCapture, fullCapture); + + this._debugCapture = true; + } + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Phaser v3.60 Debug has a build of Spector.js embedded in it, which is a WebGL inspector + * that allows for live inspection of your WebGL calls. Although it's easy to add the Spector + * extension to a desktop browsr, by embedding it in Phaser we can make it available in mobile + * browsers too, making it a powerful tool for debugging WebGL games on mobile devices where + * extensions are not permitted. + * + * See https://github.com/BabylonJS/Spector.js for more details. + * + * This method will capture the next WebGL frame and send it to the Spector.js tool for inspection. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#captureNextFrame + * @since 3.60.0 + */ + captureNextFrame: function () + { + if (DEBUG && this.spector && !this._debugCapture) + { + this._debugCapture = true; + + this.spector.captureNextFrame(this.canvas); + } + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Phaser v3.60 Debug has a build of Spector.js embedded in it, which is a WebGL inspector + * that allows for live inspection of your WebGL calls. Although it's easy to add the Spector + * extension to a desktop browsr, by embedding it in Phaser we can make it available in mobile + * browsers too, making it a powerful tool for debugging WebGL games on mobile devices where + * extensions are not permitted. + * + * See https://github.com/BabylonJS/Spector.js for more details. + * + * This method will return the current FPS of the WebGL canvas. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#getFps + * @since 3.60.0 + * + * @return {number} The current FPS of the WebGL canvas. + */ + getFps: function () + { + if (DEBUG && this.spector) + { + return this.spector.getFps(); + } + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Phaser v3.60 Debug has a build of Spector.js embedded in it, which is a WebGL inspector + * that allows for live inspection of your WebGL calls. Although it's easy to add the Spector + * extension to a desktop browsr, by embedding it in Phaser we can make it available in mobile + * browsers too, making it a powerful tool for debugging WebGL games on mobile devices where + * extensions are not permitted. + * + * See https://github.com/BabylonJS/Spector.js for more details. + * + * This method adds a command with the name value in the list. This can be filtered in the search. + * All logs can be filtered searching for "LOG". + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#log + * @since 3.60.0 + * + * @param {...*} arguments - The arguments to log to Spector. + * + * @return {string} The current log. + */ + log: function () + { + if (DEBUG && this.spector) + { + var t = Array.prototype.slice.call(arguments).join(' '); + + return this.spector.log(t); + } + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Phaser v3.60 Debug has a build of Spector.js embedded in it, which is a WebGL inspector + * that allows for live inspection of your WebGL calls. Although it's easy to add the Spector + * extension to a desktop browsr, by embedding it in Phaser we can make it available in mobile + * browsers too, making it a powerful tool for debugging WebGL games on mobile devices where + * extensions are not permitted. + * + * See https://github.com/BabylonJS/Spector.js for more details. + * + * This method will start a capture on the Phaser canvas. The capture will stop once it reaches + * the number of commands specified as a parameter, or after 10 seconds. If quick capture is true, + * the thumbnails are not captured in order to speed up the capture. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#startCapture + * @since 3.60.0 + * + * @param {number} [commandCount=0] - The number of commands to capture. If zero it will capture for 10 seconds. + * @param {boolean} [quickCapture=false] - If `true` thumbnails are not captured in order to speed up the capture. + * @param {boolean} [fullCapture=false] - If `true` all details are captured. + */ + startCapture: function (commandCount, quickCapture, fullCapture) + { + if (commandCount === undefined) { commandCount = 0; } + if (quickCapture === undefined) { quickCapture = false; } + if (fullCapture === undefined) { fullCapture = false; } + + if (DEBUG && this.spector && !this._debugCapture) + { + this.spector.startCapture(this.canvas, commandCount, quickCapture, fullCapture); + + this._debugCapture = true; + } + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Phaser v3.60 Debug has a build of Spector.js embedded in it, which is a WebGL inspector + * that allows for live inspection of your WebGL calls. Although it's easy to add the Spector + * extension to a desktop browsr, by embedding it in Phaser we can make it available in mobile + * browsers too, making it a powerful tool for debugging WebGL games on mobile devices where + * extensions are not permitted. + * + * See https://github.com/BabylonJS/Spector.js for more details. + * + * This method will stop the current capture and returns the result in JSON. It displays the + * result if the UI has been displayed. This returns undefined if the capture has not been completed + * or did not find any commands. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#stopCapture + * @since 3.60.0 + * + * @return {object} The current capture. + */ + stopCapture: function () + { + if (DEBUG && this.spector && this._debugCapture) + { + return this.spector.stopCapture(); + } + }, + + /** + * This method is only available in the Debug Build of Phaser, or a build with the + * `WEBGL_DEBUG` flag set in the Webpack Config. + * + * Internal onCapture handler. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#onCapture + * @private + * @since 3.60.0 + * + * @param {object} capture - The capture data. + */ + onCapture: function (capture) + { + if (DEBUG) + { + var view = this.spector.getResultUI(); + + view.display(capture); + + this._debugCapture = false; + } + }, + + /** + * The event handler that manages the `resize` event dispatched by the Scale Manager. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#onResize + * @since 3.16.0 + * + * @param {Phaser.Structs.Size} gameSize - The default Game Size object. This is the un-modified game dimensions. + * @param {Phaser.Structs.Size} baseSize - The base Size object. The game dimensions. The canvas width / height values match this. + */ + onResize: function (gameSize, baseSize) + { + // Has the underlying canvas size changed? + if (baseSize.width !== this.width || baseSize.height !== this.height) + { + this.resize(baseSize.width, baseSize.height); + } + }, + + /** + * Resizes the drawing buffer to match that required by the Scale Manager. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#resize + * @fires Phaser.Renderer.Events#RESIZE + * @since 3.0.0 + * + * @param {number} [width] - The new width of the renderer. + * @param {number} [height] - The new height of the renderer. + * + * @return {this} This WebGLRenderer instance. + */ + resize: function (width, height) + { + var gl = this.gl; + + this.width = width; + this.height = height; + + this.setProjectionMatrix(width, height); + + this.drawingBufferHeight = gl.drawingBufferHeight; + + this.glWrapper.update({ + scissor: { + box: [ 0, (gl.drawingBufferHeight - height), width, height ] + }, + viewport: [ 0, 0, width, height ] + }); + + this.emit(Events.RESIZE, width, height); + + return this; + }, + + /** + * Determines which compressed texture formats this browser and device supports. + * + * Called automatically as part of the WebGL Renderer init process. If you need to investigate + * which formats it supports, see the `Phaser.Renderer.WebGL.WebGLRenderer#compression` property instead. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#getCompressedTextures + * @since 3.60.0 + * + * @return {Phaser.Types.Renderer.WebGL.WebGLTextureCompression} The compression object. + */ + getCompressedTextures: function () + { + var extString = 'WEBGL_compressed_texture_'; + var wkExtString = 'WEBKIT_' + extString; + var extEXTString = 'EXT_texture_compression_'; + + var hasExt = function (gl, format) + { + var results = gl.getExtension(extString + format) || gl.getExtension(wkExtString + format) || gl.getExtension(extEXTString + format); + + if (results) + { + var glEnums = {}; + + for (var key in results) + { + glEnums[results[key]] = key; + } + + return glEnums; + } + }; + + var gl = this.gl; + + return { + ETC: hasExt(gl, 'etc'), + ETC1: hasExt(gl, 'etc1'), + ATC: hasExt(gl, 'atc'), + ASTC: hasExt(gl, 'astc'), + BPTC: hasExt(gl, 'bptc'), + RGTC: hasExt(gl, 'rgtc'), + PVRTC: hasExt(gl, 'pvrtc'), + S3TC: hasExt(gl, 's3tc'), + S3TCSRGB: hasExt(gl, 's3tc_srgb'), + IMG: true + }; + }, + + /** + * Returns a compressed texture format GLenum name based on the given format. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#getCompressedTextureName + * @since 3.60.0 + * + * @param {string} baseFormat - The Base Format to check. + * @param {GLenum} [format] - An optional GLenum format to check within the base format. + * + * @return {string} The compressed texture format name, as a string. + */ + getCompressedTextureName: function (baseFormat, format) + { + var supportedFormats = this.compression[baseFormat.toUpperCase()]; + + if (format in supportedFormats) + { + return supportedFormats[format]; + } + }, + + /** + * Checks if the given compressed texture format is supported, or not. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#supportsCompressedTexture + * @since 3.60.0 + * + * @param {string} baseFormat - The Base Format to check. + * @param {GLenum} [format] - An optional GLenum format to check within the base format. + * + * @return {boolean} True if the format is supported, otherwise false. + */ + supportsCompressedTexture: function (baseFormat, format) + { + var supportedFormats = this.compression[baseFormat.toUpperCase()]; + + if (supportedFormats) + { + if (format) + { + return format in supportedFormats; + } + else + { + return true; + } + } + + return false; + }, + + /** + * Gets the aspect ratio of the WebGLRenderer dimensions. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#getAspectRatio + * @since 3.50.0 + * + * @return {number} The aspect ratio of the WebGLRenderer dimensions. + */ + getAspectRatio: function () + { + return this.width / this.height; + }, + + /** + * Sets the Projection Matrix of this renderer to the given dimensions. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#setProjectionMatrix + * @since 3.50.0 + * + * @param {number} width - The new width of the Projection Matrix. + * @param {number} height - The new height of the Projection Matrix. + * @param {boolean} [flipY=false] - Should the Y axis be flipped? + * + * @return {this} This WebGLRenderer instance. + */ + setProjectionMatrix: function (width, height, flipY) + { + if (width !== this.projectionWidth || height !== this.projectionHeight || flipY !== this.projectionFlipY) + { + this.projectionWidth = width; + this.projectionHeight = height; + this.projectionFlipY = !!flipY; + + if (flipY) + { + this.projectionMatrix.ortho(0, width, 0, height, -1000, 1000); + } + else + { + this.projectionMatrix.ortho(0, width, height, 0, -1000, 1000); + } + } + + return this; + }, + + /** + * Sets the Projection Matrix of this renderer to match the given drawing context. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#setProjectionMatrixFromDrawingContext + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The drawing context to set the projection matrix from. + * + * @return {this} This WebGLRenderer instance. + */ + setProjectionMatrixFromDrawingContext: function (drawingContext) + { + return this.setProjectionMatrix( + drawingContext.width, + drawingContext.height, + false + ); + }, + + /** + * Resets the Projection Matrix back to this renderers width and height. + * + * This is called during `endCapture`, should the matrix have been changed + * as a result of the capture process. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#resetProjectionMatrix + * @since 3.50.0 + * + * @return {this} This WebGLRenderer instance. + */ + resetProjectionMatrix: function () + { + return this.setProjectionMatrix(this.width, this.height); + }, + + /** + * Checks if a WebGL extension is supported + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#hasExtension + * @since 3.0.0 + * + * @param {string} extensionName - Name of the WebGL extension + * + * @return {boolean} `true` if the extension is supported, otherwise `false`. + */ + hasExtension: function (extensionName) + { + return this.supportedExtensions ? this.supportedExtensions.indexOf(extensionName) : false; + }, + + /** + * Loads a WebGL extension + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#getExtension + * @since 3.0.0 + * + * @param {string} extensionName - The name of the extension to load. + * + * @return {object} WebGL extension if the extension is supported + */ + getExtension: function (extensionName) + { + if (!this.hasExtension(extensionName)) { return null; } + + if (!(extensionName in this.extensions)) + { + this.extensions[extensionName] = this.gl.getExtension(extensionName); + } + + return this.extensions[extensionName]; + }, + + /** + * Creates a new custom blend mode for the renderer. + * + * See https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants#Blending_modes + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#addBlendMode + * @since 3.0.0 + * + * @param {GLenum[]} func - An array containing the WebGL functions to use for the source and the destination blending factors, respectively. See the possible constants for {@link WebGLRenderingContext#blendFunc()}. + * @param {GLenum} equation - The equation to use for combining the RGB and alpha components of a new pixel with a rendered one. See the possible constants for {@link WebGLRenderingContext#blendEquation()}. + * + * @return {number} The index of the new blend mode, used for referencing it in the future. + */ + addBlendMode: function (func, equation) + { + var index = this.blendModes.push(WebGLBlendParametersFactory.createCombined(this, true, undefined, equation, func[0], func[1])) - 1; + + return index - 1; + }, + + /** + * Updates the function bound to a given custom blend mode. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#updateBlendMode + * @since 3.0.0 + * + * @param {number} index - The index of the custom blend mode. + * @param {GLenum[]} func - The function to use for the blend mode. Specify either 2 elements for src and dest, or 4 elements for separate srcRGB, destRGB, srcAlpha, destAlpha. + * @param {GLenum|GLenum[]} equation - The equation to use for the blend mode. This can be either a single equation for both source and destination, or an array containing separate equations for source and destination. + * + * @return {this} This WebGLRenderer instance. + */ + updateBlendMode: function (index, func, equation) + { + if (index > 17 && this.blendModes[index]) + { + var blendMode = this.blendModes[index]; + if (func.length === 2) + { + blendMode.func = [ func[0], func[1], func[0], func[1] ]; + } + else + { + blendMode.func = [ func[0], func[1], func[2], func[3] ]; + } + + if (typeof equation === 'number') + { + blendMode.equation = [ equation, equation ]; + } + else + { + blendMode.equation = [ equation[0], equation[1] ]; + } + } + + return this; + }, + + /** + * Removes a custom blend mode from the renderer. + * Any Game Objects still using this blend mode will error, so be sure to clear them first. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#removeBlendMode + * @since 3.0.0 + * + * @param {number} index - The index of the custom blend mode to be removed. + * + * @return {this} This WebGLRenderer instance. + */ + removeBlendMode: function (index) + { + if (index > 17 && this.blendModes[index]) + { + this.blendModes.splice(index, 1); + } + + return this; + }, + + /** + * Clear the current framebuffer to the given color. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#clearFramebuffer + * @since 4.0.0 + * @param {number[]} [color] - The color to clear to. Four values in the range 0.0 - 1.0. + * @param {number} [stencil] - The stencil value to clear to. + * @param {number} [depth] - The depth value to clear to. Currently, this is not set, and only determines whether the depth buffer is cleared. + */ + clearFramebuffer: function (color, stencil, depth) + { + var gl = this.gl; + var bits = 0; + if (color) + { + this.glWrapper.updateColorClearValue({ colorClearValue: color }); + bits = bits | gl.COLOR_BUFFER_BIT; + } + if (stencil !== undefined) + { + this.glWrapper.updateStencilClear({ stencil: { clear: stencil }}); + bits = bits | gl.STENCIL_BUFFER_BIT; + } + if (depth !== undefined) + { + bits = bits | gl.DEPTH_BUFFER_BIT; + } + gl.clear(bits); + }, + + /** + * Creates a texture from an image source. If the source is not valid it creates an empty texture. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createTextureFromSource + * @since 3.0.0 + * + * @param {object} source - The source of the texture. + * @param {number} width - The width of the texture. + * @param {number} height - The height of the texture. + * @param {number} scaleMode - The scale mode to be used by the texture. + * @param {boolean} [forceClamp=false] - Force the texture to use the CLAMP_TO_EDGE wrap mode, even if a power of two? + * @param {boolean} [flipY=true] - Sets the `UNPACK_FLIP_Y_WEBGL` flag the WebGL Texture uses during upload. + * + * @return {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The WebGLTextureWrapper that was created, or `null` if it couldn't be created. + */ + createTextureFromSource: function (source, width, height, scaleMode, forceClamp, flipY) + { + if (forceClamp === undefined) { forceClamp = false; } + + var gl = this.gl; + var minFilter = gl.NEAREST; + var magFilter = gl.NEAREST; + var wrap = gl.CLAMP_TO_EDGE; + var texture = null; + + width = source ? source.width : width; + height = source ? source.height : height; + + var pow = IsSizePowerOfTwo(width, height); + + if (pow && !forceClamp) + { + wrap = gl.REPEAT; + } + + if (scaleMode === CONST.ScaleModes.LINEAR && this.config.antialias) + { + var isCompressed = source && source.compressed; + var isMip = (!isCompressed && pow) || (isCompressed && source.mipmaps.length > 1); + + // Filters above LINEAR only work with MIPmaps. + // These are only generated for power of two (POT) textures. + // Compressed textures with mipmaps are always POT, + // but POT compressed textures might not have mipmaps. + minFilter = (this.mipmapFilter && isMip) ? this.mipmapFilter : gl.LINEAR; + magFilter = gl.LINEAR; + } + + if (!source && typeof width === 'number' && typeof height === 'number') + { + texture = this.createTexture2D(0, minFilter, magFilter, wrap, wrap, gl.RGBA, null, width, height, undefined, undefined, flipY); + } + else + { + texture = this.createTexture2D(0, minFilter, magFilter, wrap, wrap, gl.RGBA, source, undefined, undefined, undefined, undefined, flipY); + } + + return texture; + }, + + /** + * A wrapper for creating a WebGLTextureWrapper. If no pixel data is passed it will create an empty texture. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createTexture2D + * @since 3.0.0 + * + * @param {number} mipLevel - Mip level of the texture. + * @param {number} minFilter - Filtering of the texture. + * @param {number} magFilter - Filtering of the texture. + * @param {number} wrapT - Wrapping mode of the texture. + * @param {number} wrapS - Wrapping mode of the texture. + * @param {number} format - Which format does the texture use. + * @param {?object} pixels - pixel data. + * @param {?number} width - Width of the texture in pixels. If not supplied, it must be derived from `pixels`. + * @param {?number} height - Height of the texture in pixels. If not supplied, it must be derived from `pixels`. + * @param {boolean} [pma=true] - Does the texture have premultiplied alpha? + * @param {boolean} [forceSize=false] - If `true` it will use the width and height passed to this method, regardless of the pixels dimension. + * @param {boolean} [flipY=true] - Sets the `UNPACK_FLIP_Y_WEBGL` flag the WebGL Texture uses during upload. + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The WebGLTextureWrapper that was created. + */ + createTexture2D: function (mipLevel, minFilter, magFilter, wrapT, wrapS, format, pixels, width, height, pma, forceSize, flipY) + { + if (typeof width !== 'number') { width = pixels ? pixels.width : 1; } + if (typeof height !== 'number') { height = pixels ? pixels.height : 1; } + + var texture = new WebGLTextureWrapper(this, mipLevel, minFilter, magFilter, wrapT, wrapS, format, pixels, width, height, pma, forceSize, flipY); + + this.glTextureWrappers.push(texture); + + return texture; + }, + + /** + * Creates a WebGL Framebuffer object and optionally binds a depth stencil render buffer. + * + * This will unbind any currently bound framebuffer. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createFramebuffer + * @since 3.0.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper|Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]|null} renderTexture - The color texture where the color pixels are written. Specify an array for multiple color attachments, but WebGL1 only supports the first by default. Specify `null` to create a framebuffer for the base canvas. + * @param {boolean} [addStencilBuffer=false] - Create a Renderbuffer for the stencil? + * @param {boolean} [addDepthBuffer=false] - Create a Renderbuffer for the depth? + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper} Wrapped framebuffer which is safe to use with the renderer. + */ + createFramebuffer: function (renderTexture, addStencilBuffer, addDepthBuffer) + { + if (!Array.isArray(renderTexture) && renderTexture !== null) + { + renderTexture = [ renderTexture ]; + } + var framebuffer = new WebGLFramebufferWrapper( + this, + renderTexture, + addStencilBuffer, + addDepthBuffer + ); + + this.glFramebufferWrappers.push(framebuffer); + + return framebuffer; + }, + + /** + * Creates a WebGLProgram instance based on the given vertex and fragment shader source. + * + * Then compiles, attaches and links the program before wrapping and returning it. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createProgram + * @since 3.0.0 + * + * @param {string} vertexShader - The vertex shader source code as a single string. + * @param {string} fragmentShader - The fragment shader source code as a single string. + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} The wrapped, linked WebGLProgram created from the given shader source. + */ + createProgram: function (vertexShader, fragmentShader) + { + var wrapper = new WebGLProgramWrapper(this, vertexShader, fragmentShader); + this.glProgramWrappers.push(wrapper); + return wrapper; + }, + + /** + * Wrapper for creating a vertex buffer. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createVertexBuffer + * @since 3.0.0 + * + * @param {ArrayBuffer} initialDataOrSize - It's either ArrayBuffer or an integer indicating the size of the vbo + * @param {number} bufferUsage - How the buffer is used. gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} Wrapped vertex buffer + */ + createVertexBuffer: function (initialDataOrSize, bufferUsage) + { + var gl = this.gl; + var vertexBuffer = new WebGLBufferWrapper(this, initialDataOrSize, gl.ARRAY_BUFFER, bufferUsage); + this.glBufferWrappers.push(vertexBuffer); + return vertexBuffer; + }, + + /** + * Wrapper for creating a vertex buffer. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createIndexBuffer + * @since 3.0.0 + * + * @param {ArrayBuffer} initialDataOrSize - Either ArrayBuffer or an integer indicating the size of the vbo. + * @param {number} bufferUsage - How the buffer is used. gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW. + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} Wrapped index buffer + */ + createIndexBuffer: function (initialDataOrSize, bufferUsage) + { + var gl = this.gl; + var indexBuffer = new WebGLBufferWrapper(this, initialDataOrSize, gl.ELEMENT_ARRAY_BUFFER, bufferUsage); + this.glBufferWrappers.push(indexBuffer); + return indexBuffer; + }, + + /** + * Wrapper for creating a vertex array object. + * This manages a vertex attribute binding state. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createVAO + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The program to bind the VAO to. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} indexBuffer - The index buffer. + * @param {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout[]} attributeBufferLayouts - The attribute buffer layouts. + */ + createVAO: function (program, indexBuffer, attributeBufferLayouts) + { + var vao = new WebGLVAOWrapper(this, program, indexBuffer, attributeBufferLayouts); + this.glVAOWrappers.push(vao); + return vao; + }, + + /** + * Removes a texture from the GPU. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#deleteTexture + * @since 3.0.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} texture - The WebGL Texture to be deleted. + * + * @return {this} This WebGLRenderer instance. + */ + deleteTexture: function (texture) + { + if (!texture) + { + return; + } + ArrayRemove(this.glTextureWrappers, texture); + texture.destroy(); + return this; + }, + + /** + * Deletes a Framebuffer from the GL instance. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#deleteFramebuffer + * @since 3.0.0 + * + * @param {(Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper|null)} framebuffer - The Framebuffer to be deleted. + * + * @return {this} This WebGLRenderer instance. + */ + deleteFramebuffer: function (framebuffer) + { + if (!framebuffer) + { + return this; + } + ArrayRemove(this.glFramebufferWrappers, framebuffer); + framebuffer.destroy(); + return this; + }, + + /** + * Deletes a WebGLProgram from the GL instance. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#deleteProgram + * @since 3.0.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The shader program to be deleted. + * + * @return {this} This WebGLRenderer instance. + */ + deleteProgram: function (program) + { + if (program) + { + ArrayRemove(this.glProgramWrappers, program); + program.destroy(); + } + + return this; + }, + + /** + * Deletes a WebGLBuffer from the GL instance. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#deleteBuffer + * @since 3.0.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} vertexBuffer - The WebGLBuffer to be deleted. + * + * @return {this} This WebGLRenderer instance. + */ + deleteBuffer: function (buffer) + { + if (!buffer) { return this; } + ArrayRemove(this.glBufferWrappers, buffer); + buffer.destroy(); + return this; + }, + + /** + * Clears the base DrawingContext and readies it for use. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#preRender + * @fires Phaser.Renderer.Events#PRE_RENDER_CLEAR + * @fires Phaser.Renderer.Events#PRE_RENDER + * @since 3.0.0 + */ + preRender: function () + { + if (this.contextLost) { return; } + + this.emit(Events.PRE_RENDER_CLEAR); + + // Sync the background color to the DrawingContext. + var baseDrawingContext = this.baseDrawingContext; + if (this.config.clearBeforeRender) + { + var backgroundColor = this.config.backgroundColor; + baseDrawingContext.setClearColor( + backgroundColor.redGL, + backgroundColor.greenGL, + backgroundColor.blueGL, + backgroundColor.alphaGL + ); + baseDrawingContext.setAutoClear(true, true, true); + } + else + { + baseDrawingContext.setAutoClear(false, false, false); + } + + baseDrawingContext.use(); + + this.emit(Events.PRE_RENDER); + }, + + /** + * The core render step for a Scene Camera. + * + * Iterates through the given array of Game Objects and renders them with the given Camera. + * + * This is called by the `CameraManager.render` method. The Camera Manager instance belongs to a Scene, and is invoked + * by the Scene Systems.render method. + * + * This method is not called if `Camera.visible` is `false`, or `Camera.alpha` is zero. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#render + * @fires Phaser.Renderer.Events#RENDER + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to render. + * @param {Phaser.GameObjects.GameObject[]} children - An array of filtered Game Objects that can be rendered by the given Camera. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Scene Camera to render with. + */ + render: function (scene, children, camera) + { + if (this.contextLost) { return; } + + this.emit(Events.RENDER, scene, camera); + + this.currentViewCamera = camera; + + this.cameraRenderNode.run(this.baseDrawingContext, children, camera); + + this.currentViewCamera = null; + }, + + /** + * The post-render step happens after all Cameras in all Scenes have been rendered. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#postRender + * @fires Phaser.Renderer.Events#POST_RENDER + * @since 3.0.0 + */ + postRender: function () + { + this.baseDrawingContext.release(); + + if (this.contextLost) { return; } + + this.emit(Events.POST_RENDER); + + // Handle snapshot requests. + var state = this.snapshotState; + if (state.callback) + { + WebGLSnapshot(this.gl, state); + + state.callback = null; + } + }, + + /** + * Draw a number of vertices to a drawing context. + * + * This draws the vertices using an index buffer. The buffer should be + * bound to the VAO. Vertices are drawn as a `TRIANGLE_STRIP` by default. + * + * This is the primary render method. It requires all the WebGL resources + * necessary to render the vertices, so they don't have to be set up + * ad-hoc elsewhere. + * + * It does not upload vertex data to buffers. Ensure that this is done + * before calling this method. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#drawElements + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The DrawingContext to draw to. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} textures - An array of textures to bind. Textures are bound to units corresponding to their indices in the array. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The shader program to use. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper} vao - The Vertex Array Object to bind. It must have an index buffer attached. + * @param {number} count - The number of vertices to draw. Because of the TRIANGLE_STRIP topology, this should be `n + 2`, where `n` is the number of triangles to draw, including degenerate triangles. + * @param {number} offset - The offset to start drawing from in the index buffer. This is in bytes, and should be a multiple of 2 (for 16-bit `UNSIGNED_SHORT` indices). + * @param {number} topology - The type of primitives to render. Defaults to `TRIANGLE_STRIP`. + */ + drawElements: function (drawingContext, textures, program, vao, count, offset, topology) + { + var gl = this.gl; + + drawingContext.beginDraw(); + + program.bind(); + + vao.bind(); + + this.glTextureUnits.bindUnits(textures); + + gl.drawElements(topology || gl.TRIANGLE_STRIP, count, gl.UNSIGNED_SHORT, offset); + }, + + /** + * Draw a number of instances to a drawing context. + * + * This draws vertices using the ANGLE_instanced_arrays extension. + * This typically uses an instance buffer and a vertex buffer. + * Both should be bound to the VAO. Vertices are drawn as a `TRIANGLE_STRIP` by default. + * + * It does not upload vertex data to buffers. Ensure that this is done + * before calling this method. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#drawInstancedArrays + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The DrawingContext to draw to. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} textures - An array of textures to bind. Textures are bound to units corresponding to their indices in the array. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The shader program to use. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper} vao - The Vertex Array Object to bind. It does not need an index buffer attached. + * @param {number} first - The starting index in the array of vector points. + * @param {number} count - The number of vertices to draw. + * @param {number} instanceCount - The number of instances to render. + */ + drawInstancedArrays: function (drawingContext, textures, program, vao, first, count, instanceCount, topology) + { + var gl = this.gl; + + drawingContext.beginDraw(); + + program.bind(); + + vao.bind(); + + this.glTextureUnits.bindUnits(textures); + + this.instancedArraysExtension.drawArraysInstancedANGLE(topology || gl.TRIANGLE_STRIP, first, count, instanceCount); + }, + + /** + * Schedules a snapshot of the entire game viewport to be taken after the current frame is rendered. + * + * To capture a specific area see the `snapshotArea` method. To capture a specific pixel, see `snapshotPixel`. + * + * Only one snapshot can be active _per frame_. If you have already called `snapshotPixel`, for example, then + * calling this method will override it. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer into an ArrayBufferView. + * It then parses this, copying the contents to a temporary Canvas and finally creating an Image object from it, + * which is the image returned to the callback provided. All in all, this is a computationally expensive and blocking process, + * which gets more expensive the larger the canvas size gets, so please be careful how you employ this in your game. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#snapshot + * @since 3.0.0 + * + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This WebGL Renderer. + */ + snapshot: function (callback, type, encoderOptions) + { + return this.snapshotArea(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight, callback, type, encoderOptions); + }, + + /** + * Schedules a snapshot of the given area of the game viewport to be taken after the current frame is rendered. + * + * To capture the whole game viewport see the `snapshot` method. To capture a specific pixel, see `snapshotPixel`. + * + * Only one snapshot can be active _per frame_. If you have already called `snapshotPixel`, for example, then + * calling this method will override it. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer into an ArrayBufferView. + * It then parses this, copying the contents to a temporary Canvas and finally creating an Image object from it, + * which is the image returned to the callback provided. All in all, this is a computationally expensive and blocking process, + * which gets more expensive the larger the canvas size gets, so please be careful how you employ this in your game. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#snapshotArea + * @since 3.16.0 + * + * @param {number} x - The x coordinate to grab from. This is based on the game viewport, not the world. + * @param {number} y - The y coordinate to grab from. This is based on the game viewport, not the world. + * @param {number} width - The width of the area to grab. + * @param {number} height - The height of the area to grab. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This WebGL Renderer. + */ + snapshotArea: function (x, y, width, height, callback, type, encoderOptions) + { + var state = this.snapshotState; + + state.callback = callback; + state.type = type; + state.encoder = encoderOptions; + state.getPixel = false; + state.x = x; + state.y = y; + state.width = width; + state.height = height; + state.unpremultiplyAlpha = this.game.config.premultipliedAlpha; + + return this; + }, + + /** + * Schedules a snapshot of the given pixel from the game viewport to be taken after the current frame is rendered. + * + * To capture the whole game viewport see the `snapshot` method. To capture a specific area, see `snapshotArea`. + * + * Only one snapshot can be active _per frame_. If you have already called `snapshotArea`, for example, then + * calling this method will override it. + * + * Unlike the other two snapshot methods, this one will return a `Color` object containing the color data for + * the requested pixel. It doesn't need to create an internal Canvas or Image object, so is a lot faster to execute, + * using less memory. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#snapshotPixel + * @since 3.16.0 + * + * @param {number} x - The x coordinate of the pixel to get. This is based on the game viewport, not the world. + * @param {number} y - The y coordinate of the pixel to get. This is based on the game viewport, not the world. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot pixel data is extracted. + * + * @return {this} This WebGL Renderer. + */ + snapshotPixel: function (x, y, callback) + { + this.snapshotArea(x, y, 1, 1, callback); + + this.snapshotState.getPixel = true; + + return this; + }, + + /** + * Takes a snapshot of the given area of the given frame buffer. + * + * Unlike the other snapshot methods, this one is processed immediately and doesn't wait for the next render. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer into an ArrayBufferView. + * It then parses this, copying the contents to a temporary Canvas and finally creating an Image object from it, + * which is the image returned to the callback provided. All in all, this is a computationally expensive and blocking process, + * which gets more expensive the larger the canvas size gets, so please be careful how you employ this in your game. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#snapshotFramebuffer + * @since 3.19.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper} framebuffer - The framebuffer to grab from. + * @param {number} bufferWidth - The width of the framebuffer. + * @param {number} bufferHeight - The height of the framebuffer. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {boolean} [getPixel=false] - Grab a single pixel as a Color object, or an area as an Image object? + * @param {number} [x=0] - The x coordinate to grab from. This is based on the framebuffer, not the world. + * @param {number} [y=0] - The y coordinate to grab from. This is based on the framebuffer, not the world. + * @param {number} [width=bufferWidth] - The width of the area to grab. + * @param {number} [height=bufferHeight] - The height of the area to grab. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This WebGL Renderer. + */ + snapshotFramebuffer: function (framebuffer, bufferWidth, bufferHeight, callback, getPixel, x, y, width, height, type, encoderOptions) + { + if (getPixel === undefined) { getPixel = false; } + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = bufferWidth; } + if (height === undefined) { height = bufferHeight; } + + if (type === 'pixel') + { + getPixel = true; + type = 'image/png'; + } + + this.snapshotArea(x, y, width, height, callback, type, encoderOptions); + + var state = this.snapshotState; + + state.getPixel = getPixel; + + state.isFramebuffer = true; + state.bufferWidth = bufferWidth; + state.bufferHeight = bufferHeight; + + // Ensure they're not trying to grab an area larger than the framebuffer + state.width = Math.min(state.width, bufferWidth); + state.height = Math.min(state.height, bufferHeight); + + this.glWrapper.updateBindingsFramebuffer({ bindings: { framebuffer: framebuffer } }); + + WebGLSnapshot(this.gl, state); + + // We don't need to unbind the framebuffer, + // because the next time we draw it will be bound again. + + state.callback = null; + state.isFramebuffer = false; + + return this; + }, + + /** + * Creates a new WebGL Texture based on the given Canvas Element. + * + * If the `dstTexture` parameter is given, the WebGL Texture is updated, rather than created fresh. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#canvasToTexture + * @since 3.0.0 + * + * @param {HTMLCanvasElement} srcCanvas - The Canvas to create the WebGL Texture from + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [dstTexture] - The destination WebGLTextureWrapper to set. + * @param {boolean} [noRepeat=false] - Should this canvas be allowed to set `REPEAT` (such as for Text objects?) + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The newly created, or updated, WebGLTextureWrapper. + */ + canvasToTexture: function (srcCanvas, dstTexture, noRepeat, flipY) + { + if (noRepeat === undefined) { noRepeat = false; } + if (flipY === undefined) { flipY = true; } + + var gl = this.gl; + var minFilter = gl.NEAREST; + var magFilter = gl.NEAREST; + + var width = srcCanvas.width; + var height = srcCanvas.height; + + var wrapping = gl.CLAMP_TO_EDGE; + + var pow = IsSizePowerOfTwo(width, height); + + if (!noRepeat && pow) + { + wrapping = gl.REPEAT; + } + + if (this.config.antialias) + { + minFilter = (pow && this.mipmapFilter) ? this.mipmapFilter : gl.LINEAR; + magFilter = gl.LINEAR; + } + + if (!dstTexture) + { + return this.createTexture2D(0, minFilter, magFilter, wrapping, wrapping, gl.RGBA, srcCanvas, width, height, true, false, flipY); + } + else + { + dstTexture.update(srcCanvas, width, height, flipY, wrapping, wrapping, minFilter, magFilter, dstTexture.format); + + return dstTexture; + } + }, + + /** + * Creates a new WebGL Texture based on the given Canvas Element. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createCanvasTexture + * @since 3.20.0 + * + * @param {HTMLCanvasElement} srcCanvas - The Canvas to create the WebGL Texture from. + * @param {boolean} [noRepeat=false] - Should this canvas be allowed to set `REPEAT` (such as for Text objects?) + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The newly created WebGLTextureWrapper. + */ + createCanvasTexture: function (srcCanvas, noRepeat, flipY) + { + if (noRepeat === undefined) { noRepeat = false; } + if (flipY === undefined) { flipY = true; } + + return this.canvasToTexture(srcCanvas, null, noRepeat, flipY); + }, + + /** + * Updates a WebGL Texture based on the given Canvas Element. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#updateCanvasTexture + * @since 3.20.0 + * + * @param {HTMLCanvasElement} srcCanvas - The Canvas to update the WebGL Texture from. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} dstTexture - The destination WebGLTextureWrapper to update. + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * @param {boolean} [noRepeat=false] - Should this canvas be allowed to set `REPEAT` (such as for Text objects?) + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The updated WebGLTextureWrapper. This is the same wrapper object as `dstTexture`. + */ + updateCanvasTexture: function (srcCanvas, dstTexture, flipY, noRepeat) + { + if (flipY === undefined) { flipY = true; } + if (noRepeat === undefined) { noRepeat = false; } + + return this.canvasToTexture(srcCanvas, dstTexture, noRepeat, flipY); + }, + + /** + * Creates or updates a WebGL Texture based on the given HTML Video Element. + * + * If the `dstTexture` parameter is given, the WebGL Texture is updated, rather than created fresh. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#videoToTexture + * @since 4.0.0 + * + * @param {HTMLVideoElement} srcVideo - The Video to create the WebGL Texture from + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [dstTexture] - The destination WebGLTextureWrapper to set. + * @param {boolean} [noRepeat=false] - Should this canvas be allowed to set `REPEAT`? + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The newly created, or updated, WebGLTextureWrapper. + */ + videoToTexture: function (srcVideo, dstTexture, noRepeat, flipY) + { + if (noRepeat === undefined) { noRepeat = false; } + if (flipY === undefined) { flipY = true; } + + var gl = this.gl; + var minFilter = gl.NEAREST; + var magFilter = gl.NEAREST; + + var width = srcVideo.videoWidth; + var height = srcVideo.videoHeight; + + var wrapping = gl.CLAMP_TO_EDGE; + + var pow = IsSizePowerOfTwo(width, height); + + if (!noRepeat && pow) + { + wrapping = gl.REPEAT; + } + + if (this.config.antialias) + { + minFilter = (pow && this.mipmapFilter) ? this.mipmapFilter : gl.LINEAR; + magFilter = gl.LINEAR; + } + + if (!dstTexture) + { + return this.createTexture2D(0, minFilter, magFilter, wrapping, wrapping, gl.RGBA, srcVideo, width, height, true, true, flipY); + } + else + { + dstTexture.update(srcVideo, width, height, flipY, wrapping, wrapping, minFilter, magFilter, dstTexture.format); + + return dstTexture; + } + }, + + /** + * Creates a new WebGL Texture based on the given HTML Video Element. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createVideoTexture + * @since 3.20.0 + * + * @param {HTMLVideoElement} srcVideo - The Video to create the WebGL Texture from + * @param {boolean} [noRepeat=false] - Should this canvas be allowed to set `REPEAT`? + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The newly created WebGLTextureWrapper. + */ + createVideoTexture: function (srcVideo, noRepeat, flipY) + { + if (noRepeat === undefined) { noRepeat = false; } + if (flipY === undefined) { flipY = true; } + + return this.videoToTexture(srcVideo, null, noRepeat, flipY); + }, + + /** + * Updates a WebGL Texture based on the given HTML Video Element. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#updateVideoTexture + * @since 3.20.0 + * + * @param {HTMLVideoElement} srcVideo - The Video to update the WebGL Texture with. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} dstTexture - The destination WebGLTextureWrapper to update. + * @param {boolean} [flipY=true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * @param {boolean} [noRepeat=false] - Should this canvas be allowed to set `REPEAT`? + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The updated WebGLTextureWrapper. This is the same wrapper object as `dstTexture`. + */ + updateVideoTexture: function (srcVideo, dstTexture, flipY, noRepeat) + { + if (flipY === undefined) { flipY = true; } + if (noRepeat === undefined) { noRepeat = false; } + + return this.videoToTexture(srcVideo, dstTexture, noRepeat, flipY); + }, + + /** + * Create a WebGLTexture from a Uint8Array. + * + * The Uint8Array is assumed to be RGBA values, one byte per color component. + * + * The texture will be filtered with `gl.NEAREST` and will not be mipped. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#createUint8ArrayTexture + * @since 3.80.0 + * @param {Uint8Array} data - The Uint8Array to create the texture from. + * @param {number} width - The width of the texture. + * @param {number} height - The height of the texture. + * @param {boolean} [pma = true] - Should the texture be set as having premultiplied alpha? + * @param {boolean} [flipY = true] - Should the WebGL Texture set `UNPACK_MULTIPLY_FLIP_Y`? + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The newly created WebGLTextureWrapper. + */ + createUint8ArrayTexture: function (data, width, height, pma, flipY) + { + var gl = this.gl; + var minFilter = gl.NEAREST; + var magFilter = gl.NEAREST; + var wrap = gl.CLAMP_TO_EDGE; + + var pow = IsSizePowerOfTwo(width, height); + + if (pow) + { + wrap = gl.REPEAT; + } + + if (pma === undefined) { pma = true; } + if (flipY === undefined) { flipY = true; } + + return this.createTexture2D(0, minFilter, magFilter, wrap, wrap, gl.RGBA, data, width, height, pma, false, flipY); + }, + + /** + * Sets the minification and magnification filter for a texture. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#setTextureFilter + * @since 3.0.0 + * + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} texture - The texture to set the filter for. + * @param {number} filter - The filter to set. 0 for linear filtering, 1 for nearest neighbor (blocky) filtering. + * + * @return {this} This WebGL Renderer instance. + */ + setTextureFilter: function (texture, filter) + { + var gl = this.gl; + var glFilter = (filter === 0) ? gl.LINEAR : gl.NEAREST; + + var texUnits = this.glTextureUnits; + var currentTexture = texUnits.units[0]; + texUnits.bind(texture, 0); + texture.update( + texture.pixels, + texture.width, + texture.height, + texture.flipY, + texture.wrapS, + texture.wrapT, + glFilter, + glFilter, + texture.format + ); + if (currentTexture) + { + texUnits.bind(currentTexture, 0); + } + + return this; + }, + + /** + * Returns the largest texture size (either width or height) that can be created. + * Note that VRAM may not allow a texture of any given size, it just expresses + * hardware / driver support for a given size. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#getMaxTextureSize + * @since 3.8.0 + * + * @return {number} The maximum supported texture size. + */ + getMaxTextureSize: function () + { + return this.config.maxTextureSize; + }, + + /** + * Destroy this WebGLRenderer, cleaning up all related resources such as wrappers, native textures, etc. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.off(Events.RESIZE, this.baseDrawingContext.resize, this.baseDrawingContext); + + this.canvas.removeEventListener('webglcontextlost', this.contextLostHandler, false); + + this.canvas.removeEventListener('webglcontextrestored', this.contextRestoredHandler, false); + + var wrapperDestroy = function (wrapper) + { + wrapper.destroy(); + }; + ArrayEach(this.glBufferWrappers, wrapperDestroy); + ArrayEach(this.glFramebufferWrappers, wrapperDestroy); + ArrayEach(this.glProgramWrappers, wrapperDestroy); + ArrayEach(this.glTextureWrappers, wrapperDestroy); + + this.removeAllListeners(); + + this.extensions = {}; + + this.gl = null; + this.game = null; + this.canvas = null; + this.contextLost = true; + + if (DEBUG) + { + this.spector = null; + } + } +}); + +module.exports = WebGLRenderer; + + +/***/ }), + +/***/ 14500: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var WEBGL_CONST = { + + /** + * 8-bit twos complement signed integer. + * + * @name Phaser.Renderer.WebGL.BYTE + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + BYTE: { enum: 0x1400, size: 1 }, + + /** + * 8-bit twos complement unsigned integer. + * + * @name Phaser.Renderer.WebGL.UNSIGNED_BYTE + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + UNSIGNED_BYTE: { enum: 0x1401, size: 1 }, + + /** + * 16-bit twos complement signed integer. + * + * @name Phaser.Renderer.WebGL.SHORT + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + SHORT: { enum: 0x1402, size: 2 }, + + /** + * 16-bit twos complement unsigned integer. + * + * @name Phaser.Renderer.WebGL.UNSIGNED_SHORT + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + UNSIGNED_SHORT: { enum: 0x1403, size: 2 }, + + /** + * 32-bit twos complement signed integer. + * + * @name Phaser.Renderer.WebGL.INT + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + INT: { enum: 0x1404, size: 4 }, + + /** + * 32-bit twos complement unsigned integer. + * + * @name Phaser.Renderer.WebGL.UNSIGNED_INT + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + UNSIGNED_INT: { enum: 0x1405, size: 4 }, + + /** + * 32-bit IEEE floating point number. + * + * @name Phaser.Renderer.WebGL.FLOAT + * @type {Phaser.Types.Renderer.WebGL.WebGLConst} + * @since 3.50.0 + */ + FLOAT: { enum: 0x1406, size: 4 } + +}; + +module.exports = WEBGL_CONST; + + +/***/ }), + +/***/ 4159: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var WEBGL_CONST = __webpack_require__(14500); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Renderer.WebGL + */ + +var WebGL = { + + Shaders: __webpack_require__(89350), + ShaderAdditionMakers: __webpack_require__(83786), + + DrawingContext: __webpack_require__(87774), + DrawingContextPool: __webpack_require__(65656), + ProgramManager: __webpack_require__(56436), + RenderNodes: __webpack_require__(54521), + ShaderProgramFactory: __webpack_require__(18804), + Utils: __webpack_require__(70554), + WebGLRenderer: __webpack_require__(74797), + Wrappers: __webpack_require__(31884) + +}; + +// Merge in the consts + +WebGL = Extend(false, WebGL, WEBGL_CONST); + +// Export it + +module.exports = WebGL; + + +/***/ }), + +/***/ 47774: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Factory for creating a WebGLBlendParameters. + * + * @namespace Phaser.Renderer.WebGL.WebGLBlendParametersFactory + * @webglOnly + * @since 4.0.0 + */ +var WebGLBlendParametersFactory = { + /** + * Create a new WebGLBlendParameters object. + * + * Default values are for a normal blend mode. + * - enabled: true + * - color: [ 0, 0, 0, 0 ] + * - equation: gl.FUNC_ADD + * - funcSrc: gl.ONE + * - funcDst: gl.ONE_MINUS_SRC_ALPHA + * + * Where `equation`, `funcSrc`, and `funcDst` are the same for RGB and alpha. + * + * @method Phaser.Renderer.WebGL.WebGLBlendParametersFactory#createCombined + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer to create the WebGLBlendParameters for. + * @param {GLboolean} [enabled=true] - Whether blending is enabled. + * @param {GLclampf[]} [color=[0, 0, 0, 0]] - The blend color (array of 4 channels, 0-1). + * @param {GLenum} [equation=gl.FUNC_ADD] - The blend equation. + * @param {GLenum} [funcSrc=gl.ONE] - The source blend function. + * @param {GLenum} [funcDst=gl.ONE_MINUS_SRC_ALPHA] - The destination blend function. + * @returns {Phaser.Types.Renderer.WebGL.WebGLBlendParameters} The created WebGLBlendParameters. + * @since 4.0.0 + */ + createCombined: function (renderer, enabled, color, equation, funcSrc, funcDst) + { + var gl = renderer.gl; + if (enabled === undefined) { enabled = true; } + if (color === undefined) { color = [ 0, 0, 0, 0 ]; } + if (equation === undefined) { equation = gl.FUNC_ADD; } + if (funcSrc === undefined) { funcSrc = gl.ONE; } + if (funcDst === undefined) { funcDst = gl.ONE_MINUS_SRC_ALPHA; } + var parameters = { + enabled: enabled, + color: color, + equation: [ equation, equation ], + func: [ funcSrc, funcDst, funcSrc, funcDst ] + }; + + return parameters; + }, + + /** + * Create a new WebGLBlendParameters object. + * + * Default values are for a normal blend mode. + * - enabled: true + * - color: [ 0, 0, 0, 0 ] + * - equation: gl.FUNC_ADD + * - funcSrc: gl.ONE + * - funcDst: gl.ONE_MINUS_SRC_ALPHA + * + * Where `equation`, `funcSrc`, and `funcDst` are the same for RGB and alpha. + * + * @method Phaser.Renderer.WebGL.WebGLBlendParametersFactory#createSeparate + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer to create the WebGLBlendParameters for. + * @param {GLboolean} [enabled=true] - Whether blending is enabled. + * @param {GLclampf[]} [color=[0, 0, 0, 0]] - The blend color (array of 4 channels, 0-1). + * @param {GLenum} [equationRGB=gl.FUNC_ADD] - The RGB blend equation. + * @param {GLenum} [equationAlpha=gl.FUNC_ADD] - The alpha blend equation. + * @param {GLenum} [funcSrcRGB=gl.ONE] - The RGB source blend function. + * @param {GLenum} [funcDstRGB=gl.ONE_MINUS_SRC_ALPHA] - The RGB destination blend function. + * @param {GLenum} [funcSrcAlpha=gl.ONE] - The alpha source blend function. + * @param {GLenum} [funcDstAlpha=gl.ONE_MINUS_SRC_ALPHA] - The alpha destination blend function. + * @returns {Phaser.Types.Renderer.WebGL.WebGLBlendParameters} The created WebGLBlendParameters. + * @since 4.0.0 + */ + createSeparate: function (renderer, enabled, color, equationRGB, equationAlpha, funcSrcRGB, funcDstRGB, funcSrcAlpha, funcDstAlpha) + { + var gl = renderer.gl; + if (enabled === undefined) { enabled = true; } + if (color === undefined) { color = [ 0, 0, 0, 0 ]; } + if (equationRGB === undefined) { equationRGB = gl.FUNC_ADD; } + if (equationAlpha === undefined) { equationAlpha = gl.FUNC_ADD; } + if (funcSrcRGB === undefined) { funcSrcRGB = gl.ONE; } + if (funcDstRGB === undefined) { funcDstRGB = gl.ONE_MINUS_SRC_ALPHA; } + if (funcSrcAlpha === undefined) { funcSrcAlpha = gl.ONE; } + if (funcDstAlpha === undefined) { funcDstAlpha = gl.ONE_MINUS_SRC_ALPHA; } + var parameters = { + enabled: enabled, + color: color, + equation: [ equationRGB, equationAlpha ], + func: [ funcSrcRGB, funcDstRGB, funcSrcAlpha, funcDstAlpha ] + }; + + return parameters; + } +}; + +module.exports = WebGLBlendParametersFactory; + + +/***/ }), + +/***/ 53314: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(8054); +var DeepCopy = __webpack_require__(62644); +var WebGLStencilParametersFactory = __webpack_require__(71623); + +/** + * Factory for creating a WebGLGlobalParameters. + * + * @namespace Phaser.Renderer.WebGL.WebGLGlobalParametersFactory + * @webglOnly + * @since 4.0.0 + */ +var WebGLGlobalParametersFactory = { + + /** + * Creates a new WebGLGlobalParameters. + * + * @method Phaser.Renderer.WebGL.WebGLGlobalParametersFactory#getDefault + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer to create the WebGLGlobalParameters for. + * @returns {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} The default WebGLGlobalParameters. + */ + getDefault: function (renderer) + { + var parameters = { + bindings: { + activeTexture: 0, + arrayBuffer: null, + elementArrayBuffer: null, + framebuffer: null, + program: null, + renderbuffer: null + }, + blend: DeepCopy(renderer.blendModes[CONST.BlendModes.NORMAL]), + colorClearValue: [ 0, 0, 0, 1 ], + colorWritemask: [ true, true, true, true ], + cullFace: false, + depthTest: false, + scissor: { + enable: true, + box: [ 0, 0, 0, 0 ] + }, + stencil: WebGLStencilParametersFactory.create(renderer), + texturing: { + flipY: false, + premultiplyAlpha: false + }, + vao: null, + viewport: [ 0, 0, 0, 0 ] + }; + + return parameters; + } +}; + +module.exports = WebGLGlobalParametersFactory; + + +/***/ }), + +/***/ 71623: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Factory for creating a WebGLStencilParameters. + * + * @namespace Phaser.Renderer.WebGL.WebGLStencilParametersFactory + * @webglOnly + * @since 4.0.0 + */ +var WebGLStencilParametersFactory = { + /** + * Creates a new WebGLStencilParameters. + * + * @method Phaser.Renderer.WebGL.WebGLStencilParametersFactory#create + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer to create the WebGLStencilParameters for. + * @param {GLboolean} [enabled=false] - Whether the stencil test is enabled. + * @param {GLenum} [func=GL_ALWAYS] - The comparison function. + * @param {GLint} [funcRef=0] - The reference value for the stencil test. + * @param {GLuint} [funcMask=0xFF] - The mask to apply to the stencil test. + * @param {GLenum} [opFail=GL_KEEP] - The operation to perform if the stencil test fails. + * @param {GLenum} [opZfail=GL_KEEP] - The operation to perform if the depth test fails. + * @param {GLenum} [opZpass=GL_KEEP] - The operation to perform if the stencil test passes and the depth test passes or is disabled. + * @param {GLint} [clear=0] - The value to clear the stencil buffer to. + * + * @returns {Phaser.Types.Renderer.WebGL.WebGLStencilParameters} The created WebGLStencilParameters. + */ + create: function (renderer, enabled, func, funcRef, funcMask, opFail, opZfail, opZpass, clear) + { + var gl = renderer.gl; + if (enabled === undefined) { enabled = false; } + if (func === undefined) { func = gl.ALWAYS; } + if (funcRef === undefined) { funcRef = 0; } + if (funcMask === undefined) { funcMask = 0xFF; } + if (opFail === undefined) { opFail = gl.KEEP; } + if (opZfail === undefined) { opZfail = gl.KEEP; } + if (opZpass === undefined) { opZpass = gl.KEEP; } + if (clear === undefined) { clear = 0; } + var parameters = { + enabled: enabled, + func: { + func: func, + ref: funcRef, + mask: funcMask + }, + op: { + fail: opFail, + zfail: opZfail, + zpass: opZpass + }, + clear: clear + }; + + return parameters; + } +}; + +module.exports = WebGLStencilParametersFactory; + + +/***/ }), + +/***/ 13961: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var ProgramManager = __webpack_require__(56436); +var WebGLVertexBufferLayoutWrapper = __webpack_require__(40952); +var RenderNode = __webpack_require__(6141); +var Renderer = __webpack_require__(36909); + +/** + * @classdesc + * A Batch Handler Render Node. This is a base class used for other + * Batch Handler Render Nodes. + * + * A batch handler buffers data for a batch of objects to be rendered + * together. It is responsible for the vertex buffer layout and shaders + * used to render the batched items. + * + * This class is not meant to be used directly, but to be extended by + * other classes. + * + * @class BatchHandler + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} defaultConfig - The default configuration object for this RenderNode. This is used to ensure all required properties are present, so it must be complete. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this RenderNode. + */ +var BatchHandler = new Class({ + Extends: RenderNode, + + initialize: function BatchHandler (manager, defaultConfig, config) + { + var renderer = manager.renderer; + var gl = renderer.gl; + + config = this._copyAndCompleteConfig(manager, config || {}, defaultConfig); + + var name = config.name; + if (!name) + { + throw new Error('BatchHandler must have a name'); + } + + RenderNode.call(this, name, manager); + + /** + * The number of instances per batch, used to determine the size of the + * vertex buffer, and the number of instances to render. + * + * This is usually limited by the maximum number of vertices that can be + * distinguished with a 16-bit UNSIGNED_INT index buffer, + * which is 65536. This is set in the game render config as `batchSize`. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#instancesPerBatch + * @type {number} + * @since 4.0.0 + */ + this.instancesPerBatch = -1; + + /** + * The number of vertices per instance. + * + * This is usually 4 for a quad. + * + * Each vertex corresponds to an index in the element buffer. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#verticesPerInstance + * @type {number} + * @since 4.0.0 + * @default 4 + */ + this.verticesPerInstance = config.verticesPerInstance; + + // Calculate the final number of instances per batch. + var indexLimit = 65536; // 2^16 + var maxInstances = Math.floor(indexLimit / this.verticesPerInstance); + var targetInstances = config.instancesPerBatch || renderer.config.batchSize || maxInstances; + this.instancesPerBatch = Math.min(targetInstances, maxInstances); + + /** + * The number of indices per instance. + * This is usually 6 for a quad. + * Each index corresponds to a vertex in the vertex buffer. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#indicesPerInstance + * @type {number} + * @since 4.0.0 + * @default 6 + */ + this.indicesPerInstance = config.indicesPerInstance; + + /** + * The number of bytes per index per instance. + * This is used to advance the index buffer, and accounts for the + * size of a Uint16Array element. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#bytesPerIndexPerInstance + * @type {number} + * @since 4.0.0 + * @default 12 + */ + this.bytesPerIndexPerInstance = this.indicesPerInstance * Uint16Array.BYTES_PER_ELEMENT; + + /** + * The maximum number of textures per batch entry. + * This is usually set to the maximum number of texture units available, + * but it might be smaller for some uses. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#maxTexturesPerBatch + * @type {number} + * @since 4.0.0 + */ + this.maxTexturesPerBatch = 1; + + // Listen for changes to the number of draw calls per batch. + this.manager.on( + Renderer.Events.SET_PARALLEL_TEXTURE_UNITS, + this.updateTextureCount, + this + ); + + // Ensure that there is no VAO bound, because the following index buffer + // will modify any currently bound VAO. + renderer.glWrapper.updateVAO({ vao: null }); + + /** + * The index buffer defining vertex order. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#indexBuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.indexBuffer = renderer.createIndexBuffer( + this._generateElementIndices(this.instancesPerBatch), + config.indexBufferDynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW + ); + + // Prepare the vertex buffer layout. + var partialLayout = config.vertexBufferLayout; + partialLayout.count = this.instancesPerBatch * this.verticesPerInstance; + + /** + * The layout, data, and vertex buffer used to store the vertex data. + * + * The default layout is for a quad with position, texture coordinate, + * texture ID, tint effect, and tint color on each vertex. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#vertexBufferLayout + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper} + * @since 4.0.0 + */ + this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper( + renderer, + partialLayout, + config.createOwnVertexBuffer ? null : renderer.genericVertexBuffer + ); + + /** + * The program manager used to create and manage shader programs. + * This contains shader variants. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#programManager + * @type {Phaser.Renderer.WebGL.ProgramManager} + * @since 4.0.0 + */ + this.programManager = new ProgramManager( + renderer, + [ this.vertexBufferLayout ], + this.indexBuffer + ); + + // Fill in program configuration from config. + this.programManager.setBaseShader( + config.shaderName, + config.vertexSource, + config.fragmentSource + ); + if (config.shaderAdditions) + { + for (var i = 0; i < config.shaderAdditions.length; i++) + { + var addition = config.shaderAdditions[i]; + this.programManager.addAddition(addition); + } + } + if (config.shaderFeatures) + { + for (i = 0; i < config.shaderFeatures.length; i++) + { + this.programManager.addFeature(config.shaderFeatures[i]); + } + } + + /** + * The number of bytes per instance, used to determine how much of the vertex buffer to upload. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#bytesPerInstance + * @type {number} + * @since 4.0.0 + */ + this.bytesPerInstance = this.vertexBufferLayout.layout.stride * this.verticesPerInstance; + + /** + * The number of floats per instance, used to determine how much of the vertex buffer to update. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#floatsPerInstance + * @type {number} + * @since 4.0.0 + */ + this.floatsPerInstance = this.bytesPerInstance / Float32Array.BYTES_PER_ELEMENT; + + /** + * The current batch entry being filled with textures. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#currentBatchEntry + * @type {Phaser.Types.Renderer.WebGL.WebGLBatchEntry} + * @since 4.0.0 + */ + this.currentBatchEntry = { + start: 0, + count: 0, + unit: 0, + texture: [] + }; + + /** + * The entries in the batch. + * Each entry represents a "sub-batch" of quads which use the same + * pool of textures. This allows the renderer to continue to buffer + * quads into the same batch without needing to upload the vertex + * buffer. When the batch flushes, there will be one vertex buffer + * upload, and one draw call per batch entry. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#batchEntries + * @type {Phaser.Types.Renderer.WebGL.WebGLBatchEntry[]} + * @since 4.0.0 + * @default [] + */ + this.batchEntries = []; + + /** + * The number of instances currently in the batch. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#instanceCount + * @type {number} + * @since 4.0.0 + */ + this.instanceCount = 0; + + // Ensure that shader program has the correct number of textures. + this.updateTextureCount(manager.maxParallelTextureUnits); + + // Set the dimension-related uniforms and listen for resize events. + this.resize(renderer.width, renderer.height); + renderer.on(Renderer.Events.RESIZE, this.resize, this); + }, + + /** + * Copy and complete the configuration object. + * This prevents the original config object from being modified. + * + * Default values are used for any missing properties. + * These defaults are based on the default quad shader and layout. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#_copyAndCompleteConfig + * @since 4.0.0 + * @private + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} config - The configuration object. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} defaultConfig - The default configuration object. + */ + _copyAndCompleteConfig: function (manager, config, defaultConfig) + { + var newConfig = {}; + + newConfig.name = config.name || defaultConfig.name; + newConfig.verticesPerInstance = config.verticesPerInstance || defaultConfig.verticesPerInstance; + newConfig.indicesPerInstance = config.indicesPerInstance || defaultConfig.indicesPerInstance; + + newConfig.shaderName = config.shaderName || defaultConfig.shaderName; + newConfig.vertexSource = config.vertexSource || defaultConfig.vertexSource; + newConfig.fragmentSource = config.fragmentSource || defaultConfig.fragmentSource; + newConfig.shaderAdditions = config.shaderAdditions || defaultConfig.shaderAdditions; + newConfig.shaderFeatures = config.shaderFeatures || defaultConfig.shaderFeatures; + + newConfig.indexBufferDynamic = config.indexBufferDynamic || defaultConfig.indexBufferDynamic; + + // These may be left undefined to auto-calculate instance count. + newConfig.instancesPerBatch = config.instancesPerBatch; + newConfig.maxTexturesPerBatch = config.maxTexturesPerBatch; + + // Set up vertex buffer layout. + var layoutSource = config.vertexBufferLayout || defaultConfig.vertexBufferLayout; + newConfig.vertexBufferLayout = {}; + newConfig.vertexBufferLayout.usage = layoutSource.usage; + newConfig.vertexBufferLayout.layout = []; + var remove = config.vertexBufferLayoutRemove || []; + + for (var i = 0; i < layoutSource.layout.length; i++) + { + var sourceAttr = layoutSource.layout[i]; + if (remove.indexOf(sourceAttr.name) !== -1) + { + continue; + } + newConfig.vertexBufferLayout.layout[i] = { + name: sourceAttr.name, + size: sourceAttr.size || 1, + type: sourceAttr.type || 'FLOAT', + normalized: sourceAttr.normalized || false + }; + } + + if (config.vertexBufferLayoutAdd) + { + var add = config.vertexBufferLayoutAdd || []; + for (i = 0; i < add.length; i++) + { + var addAttr = add[i]; + newConfig.vertexBufferLayout.layout.push({ + name: addAttr.name, + size: addAttr.size || 1, + type: addAttr.type || 'FLOAT', + normalized: addAttr.normalized || false + }); + } + } + + return newConfig; + }, + + /** + * Generate element indices for the instance vertices. + * This should be overridden by subclasses. + * This is called automatically when the node is initialized. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#_generateElementIndices + * @since 4.0.0 + * @private + * @param {number} instances - The number of instances to define. + * @return {ArrayBuffer} The index buffer data. + */ + _generateElementIndices: function (instances) + { + // This is empty and should be overridden by subclasses. + return new ArrayBuffer(instances * this.bytesPerInstance); + }, + + /** + * Set new dimensions for the renderer. + * This should be overridden by subclasses. + * + * This is called automatically when the renderer is resized. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#resize + * @since 4.0.0 + * @param {number} width - The new width of the renderer. + * @param {number} height - The new height of the renderer. + */ + resize: function (width, height) {}, + + /** + * Update the number of draw calls per batch. + * This should be overridden by subclasses. + * + * This is called automatically by a listener + * for the `Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS` event, + * triggered by the RenderNodeManager. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#updateTextureCount + * @since 4.0.0 + * @param {number} [count] - The new number of draw calls per batch. If undefined, the maximum number of texture units is used. + */ + updateTextureCount: function (count) {}, + + /** + * Draw then empty the current batch. + * + * This method is called automatically, by either this node or the manager, + * when the batch is full, or when something else needs to be rendered. + * + * This method should be overridden by subclasses. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {...*} [args] - Additional arguments to pass to the batch handler. + */ + run: function (drawingContext) {}, + + /** + * Add an instance to the batch. Game objects call this method to add + * themselves to the batch. This method should be overridden by subclasses. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandler#batch + * @param {...*} [args] - Arguments to pass to the batch handler. These will vary depending on the handler. + * @since 4.0.0 + */ + batch: function () {} +}); + +module.exports = BatchHandler; + + +/***/ }), + +/***/ 16971: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var ShaderSourceFS = __webpack_require__(4127); +var ShaderSourceVS = __webpack_require__(89924); +var BatchHandler = __webpack_require__(13961); + +/** + * @classdesc + * This RenderNode draws PointLight Game Objects in WebGL. + * + * @class BatchHandlerPointLight + * @extends Phaser.Renderer.WebGL.RenderNodes.BatchHandler + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this handler. + */ +var BatchHandlerPointLight = new Class({ + + Extends: BatchHandler, + + initialize: function (manager, config) + { + BatchHandler.call(this, manager, this.defaultConfig, config); + + /** + * An empty texture array used internally. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerPointLight#_emptyTextures + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} + * @private + * @since 4.0.0 + * @default [] + * @readonly + */ + this._emptyTextures = []; + }, + + /** + * The default configuration for this handler. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerPointLight#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} + * @since 4.0.0 + * @readonly + */ + defaultConfig: { + name: 'BatchHandlerPointLight', + verticesPerInstance: 4, + indicesPerInstance: 6, + shaderName: 'POINTLIGHT', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + layout: [ + { + name: 'inPosition', + size: 2 + }, + { + name: 'inLightPosition', + size: 2 + }, + { + name: 'inLightRadius', + size: 1 + }, + { + name: 'inLightAttenuation', + size: 1 + }, + { + name: 'inLightColor', + size: 4 + } + ] + } + }, + + /** + * Generate element indices for the instance vertices. + * This is called automatically when the node is initialized. + * + * By default, each instance is a quad. + * Each quad is drawn as two triangles, with the vertices in the order: + * 0, 0, 1, 2, 3, 3. The quads are drawn as a TRIANGLE_STRIP, so the + * repeated vertices form degenerate triangles to connect the quads + * without being drawn. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerPointLight#_generateElementIndices + * @since 4.0.0 + * @private + * @param {number} instances - The number of instances to define. + * @return {ArrayBuffer} The index buffer data. + */ + _generateElementIndices: function (instances) + { + var buffer = new ArrayBuffer(instances * 6 * 2); + var indices = new Uint16Array(buffer); + var offset = 0; + for (var i = 0; i < instances; i++) + { + var index = i * 4; + indices[offset++] = index; + indices[offset++] = index; + indices[offset++] = index + 1; + indices[offset++] = index + 2; + indices[offset++] = index + 3; + indices[offset++] = index + 3; + } + return buffer; + }, + + /** + * Update the uniforms for the current shader program. + * + * This method is called automatically when the batch is run. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerPointLight#setupUniforms + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + setupUniforms: function (drawingContext) + { + var programManager = this.programManager; + var width = drawingContext.width; + var height = drawingContext.height; + + programManager.setUniform( + 'uCameraZoom', + drawingContext.camera.zoom + ); + + programManager.setUniform( + 'uResolution', + [ width, height ] + ); + + drawingContext.renderer.setProjectionMatrixFromDrawingContext(drawingContext); + programManager.setUniform( + 'uProjectionMatrix', + drawingContext.renderer.projectionMatrix.val + ); + }, + + /** + * Draw then empty the current batch. + * + * This method is called automatically, by either this node or the manager, + * when the batch is full, or when something else needs to be rendered. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerPointLight#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + run: function (drawingContext) + { + var instanceCount = this.instanceCount; + + if (instanceCount === 0) { return; } + + this.onRunBegin(drawingContext); + + var programManager = this.programManager; + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + + this.setupUniforms(drawingContext); + programManager.applyUniforms(program); + + // Update vertex buffers. + // Because we are probably using a generic vertex buffer + // which is larger than the current batch, we need to update + // the buffer with the correct size. + this.vertexBufferLayout.buffer.update(this.instanceCount * this.bytesPerInstance); + + this.manager.renderer.drawElements( + drawingContext, + this._emptyTextures, + program, + vao, + instanceCount * this.indicesPerInstance, + 0 + ); + } + + // Reset batch accumulation. + this.instanceCount = 0; + + this.onRunEnd(drawingContext); + }, + + /** + * Add a light to the batch. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerPointLight#batch + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.PointLight} light - The light to add to the batch. + * @param {number} xTL - The top-left x-coordinate of the light. + * @param {number} yTL - The top-left y-coordinate of the light. + * @param {number} xBL - The bottom-left x-coordinate of the light. + * @param {number} yBL - The bottom-left y-coordinate of the light. + * @param {number} xTR - The top-right x-coordinate of the light. + * @param {number} yTR - The top-right y-coordinate of the light. + * @param {number} xBR - The bottom-right x-coordinate of the light. + * @param {number} yBR - The bottom-right y-coordinate of the light. + */ + batch: function (drawingContext, light, xTL, yTL, xBL, yBL, xTR, yTR, xBR, yBR, lightX, lightY) + { + if (this.instanceCount === 0) + { + this.manager.setCurrentBatchNode(this, drawingContext); + } + + var color = light.color; + var intensity = light.intensity; + var radius = light.radius; + var attenuation = light.attenuation; + + var r = color.r * intensity; + var g = color.g * intensity; + var b = color.b * intensity; + var a = light.alpha; + + // Update the vertex buffer. + var vertexOffset32 = this.instanceCount * this.floatsPerInstance; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + + // Bottom left + vertexViewF32[vertexOffset32++] = xBL; + vertexViewF32[vertexOffset32++] = yBL; + vertexViewF32[vertexOffset32++] = lightX; + vertexViewF32[vertexOffset32++] = lightY; + vertexViewF32[vertexOffset32++] = radius; + vertexViewF32[vertexOffset32++] = attenuation; + vertexViewF32[vertexOffset32++] = r; + vertexViewF32[vertexOffset32++] = g; + vertexViewF32[vertexOffset32++] = b; + vertexViewF32[vertexOffset32++] = a; + + // Top left + vertexViewF32[vertexOffset32++] = xTL; + vertexViewF32[vertexOffset32++] = yTL; + vertexViewF32[vertexOffset32++] = lightX; + vertexViewF32[vertexOffset32++] = lightY; + vertexViewF32[vertexOffset32++] = radius; + vertexViewF32[vertexOffset32++] = attenuation; + vertexViewF32[vertexOffset32++] = r; + vertexViewF32[vertexOffset32++] = g; + vertexViewF32[vertexOffset32++] = b; + vertexViewF32[vertexOffset32++] = a; + + // Bottom right + vertexViewF32[vertexOffset32++] = xBR; + vertexViewF32[vertexOffset32++] = yBR; + vertexViewF32[vertexOffset32++] = lightX; + vertexViewF32[vertexOffset32++] = lightY; + vertexViewF32[vertexOffset32++] = radius; + vertexViewF32[vertexOffset32++] = attenuation; + vertexViewF32[vertexOffset32++] = r; + vertexViewF32[vertexOffset32++] = g; + vertexViewF32[vertexOffset32++] = b; + vertexViewF32[vertexOffset32++] = a; + + // Top right + vertexViewF32[vertexOffset32++] = xTR; + vertexViewF32[vertexOffset32++] = yTR; + vertexViewF32[vertexOffset32++] = lightX; + vertexViewF32[vertexOffset32++] = lightY; + vertexViewF32[vertexOffset32++] = radius; + vertexViewF32[vertexOffset32++] = attenuation; + vertexViewF32[vertexOffset32++] = r; + vertexViewF32[vertexOffset32++] = g; + vertexViewF32[vertexOffset32++] = b; + vertexViewF32[vertexOffset32++] = a; + + // Increment the instance count. + this.instanceCount++; + + // Check whether the batch should be rendered immediately. + // This guarantees that none of the arrays are full above. + if (this.instanceCount === this.instancesPerBatch) + { + this.run(drawingContext); + + // Now the batch is empty. + } + } +}); + +module.exports = BatchHandlerPointLight; + + +/***/ }), + +/***/ 15214: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var Class = __webpack_require__(83419); +var DeepCopy = __webpack_require__(62644); +var Utils = __webpack_require__(70554); +var ShaderSourceFS = __webpack_require__(98840); +var ShaderSourceVS = __webpack_require__(44667); +var MakeApplyLighting = __webpack_require__(81084); +var MakeApplyTint = __webpack_require__(44349); +var MakeDefineLights = __webpack_require__(6184); +var MakeDefineTexCount = __webpack_require__(11653); +var MakeGetNormalFromMap = __webpack_require__(40829); +var MakeGetTexCoordOut = __webpack_require__(42792); +var MakeGetTexRes = __webpack_require__(96049); +var MakeGetTexture = __webpack_require__(33997); +var MakeOutInverseRotation = __webpack_require__(79532); +var MakeRotationDatum = __webpack_require__(65217); +var MakeSmoothPixelArt = __webpack_require__(74505); +var BatchHandler = __webpack_require__(13961); + +/** + * @classdesc + * This RenderNode draws Standard Batch Render (SBR) quads in batches. + * + * @class BatchHandlerQuad + * @extends Phaser.Renderer.WebGL.RenderNodes.BatchHandler + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this handler. + */ +var BatchHandlerQuad = new Class({ + Extends: BatchHandler, + + initialize: function BatchHandlerQuad (manager, config) + { + // Placed before super call because the constructor needs it. + /** + * The current render options to which the batch is built. + * These help define the shader. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#renderOptions + * @type {object} + * @since 4.0.0 + */ + this.renderOptions = { + multiTexturing: false, + texRes: false, + lighting: false, + selfShadow: false, + selfShadowPenumbra: 0, + selfShadowThreshold: 0, + smoothPixelArt: false, + roundPixels: false + }; + + BatchHandler.call(this, manager, this.defaultConfig, config); + + // Main sampler will never change after initialization, + // because it addresses texture units, not textures. + this.programManager.setUniform( + 'uMainSampler[0]', + this.manager.renderer.textureUnitIndices + ); + + /** + * The render options currently being built. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#nextRenderOptions + * @type {object} + * @since 4.0.0 + */ + this.nextRenderOptions = DeepCopy(this.renderOptions); + + /** + * Whether the render options have changed. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#_renderOptionsChanged + * @type {boolean} + * @private + * @since 4.0.0 + */ + this._renderOptionsChanged = false; + + /** + * A persistent calculation vector used when processing the lights. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#_lightVector + * @type {Phaser.Math.Vector2} + * @private + * @since 4.0.0 + */ + this._lightVector = new Vector2(); + }, + + /** + * The default configuration object for this handler. + * This is merged with the `config` object passed in the constructor. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} + * @since 4.0.0 + */ + defaultConfig: { + name: 'BatchHandlerQuad', + verticesPerInstance: 4, + indicesPerInstance: 6, + shaderName: 'STANDARD', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + shaderAdditions: [ + MakeGetTexCoordOut(), + MakeGetTexRes(true), + MakeSmoothPixelArt(true), + MakeDefineTexCount(1), + MakeGetTexture(), + MakeApplyTint(), + MakeDefineLights(true), + MakeRotationDatum(true), + MakeOutInverseRotation(true), + MakeGetNormalFromMap(true), + MakeApplyLighting(true) + ], + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + layout: [ + { + name: 'inPosition', + size: 2 + }, + { + name: 'inTexCoord', + size: 2 + }, + { + name: 'inTexDatum' + }, + { + name: 'inTintEffect' + }, + { + name: 'inTint', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + } + ] + } + }, + + /** + * Generate element indices for the instance vertices. + * This is called automatically when the node is initialized. + * + * By default, each instance is a quad. + * Each quad is drawn as two triangles, with the vertices in the order: + * 0, 0, 1, 2, 3, 3. The quads are drawn as a TRIANGLE_STRIP, so the + * repeated vertices form degenerate triangles to connect the quads + * without being drawn. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#_generateElementIndices + * @since 4.0.0 + * @private + * @param {number} instances - The number of instances to define. + * @return {ArrayBuffer} The index buffer data. + */ + _generateElementIndices: function (instances) + { + var buffer = new ArrayBuffer(instances * 6 * 2); + var indices = new Uint16Array(buffer); + var offset = 0; + for (var i = 0; i < instances; i++) + { + var index = i * 4; + indices[offset++] = index; + indices[offset++] = index; + indices[offset++] = index + 1; + indices[offset++] = index + 2; + indices[offset++] = index + 3; + indices[offset++] = index + 3; + } + return buffer; + }, + + /** + * Update the number of draw calls per batch. + * This rebuilds the shader program with the new draw call count. + * The minimum number of draw calls is 1, and the maximum is the number of + * texture units defined in the renderer. + * Rebuilding the shader may be expensive, so use this sparingly. + * + * If this runs during a batch, and the new count is less than the number of + * textures in the current batch entry, the batch will be flushed before the + * shader program is rebuilt, so none of the textures are skipped. + * + * This is usually called automatically by a listener + * for the `Phaser.Renderer.Events.SET_PARALLEL_TEXTURE_UNITS` event, + * triggered by the RenderNodeManager. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#updateTextureCount + * @since 4.0.0 + * @param {number} [count] - The new number of draw calls per batch. If undefined, the maximum number of texture units is used. + */ + updateTextureCount: function (count) + { + var renderer = this.manager.renderer; + + if (count === undefined) + { + count = renderer.maxTextures; + } + + var newCount = Math.max(1, Math.min(count, renderer.maxTextures)); + if (newCount === this.maxTexturesPerBatch) + { + return; + } + + if ( + newCount < this.currentBatchEntry.unit && + this.manager.currentBatchNode === this + ) + { + // The batch is currently running. Flush the current batch entry, + // before the shader program becomes unable to handle all textures. + this.manager.finishBatch(); + } + + this.maxTexturesPerBatch = newCount; + + // Update program manager to use the new texture count. + if (this.renderOptions.multiTexturing) + { + var programManager = this.programManager; + var textureAddition = programManager.getAdditionsByTag('TEXTURE')[0]; + if (textureAddition) + { + programManager.replaceAddition( + textureAddition.name, + MakeGetTexture(this.maxTexturesPerBatch) + ); + } + } + + this.resize(renderer.width, renderer.height); + }, + + /** + * Update the uniforms for the current shader program. + * + * This method is called automatically when the batch is run. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#setupUniforms + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + setupUniforms: function (drawingContext) + { + var programManager = this.programManager; + var renderOptions = this.renderOptions; + + // Standard uniforms. + programManager.setUniform( + 'uRoundPixels', + renderOptions.roundPixels + ); + + programManager.setUniform( + 'uResolution', + [ drawingContext.width, drawingContext.height ] + ); + + drawingContext.renderer.setProjectionMatrixFromDrawingContext(drawingContext); + programManager.setUniform( + 'uProjectionMatrix', + drawingContext.renderer.projectionMatrix.val + ); + + if (this.renderOptions.lighting) + { + // Lighting uniforms. + Utils.updateLightingUniforms( + renderOptions.lighting, + this.manager.renderer, + drawingContext, + programManager, + 1, + this._lightVector, + renderOptions.selfShadow, + renderOptions.selfShadowThreshold, + renderOptions.selfShadowPenumbra + ); + } + }, + + /** + * Update the texture uniforms for the current shader program. + * + * This method is called automatically when the batch is run. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#setupTextureUniforms + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} textures - The textures to render. + */ + setupTextureUniforms: function (textures) + { + var programManager = this.programManager; + + if (this.renderOptions.multiTexturing) + { + // In the shader, this is an array of vec2s. + // But we must compose it as a flat array, + // not an array of arrays. + var dims = []; + for (var i = 0; i < textures.length; i++) + { + dims.push(textures[i].width, textures[i].height); + } + programManager.setUniform( + 'uMainResolution[0]', + dims + ); + } + else + { + programManager.setUniform( + 'uMainResolution[0]', + [ textures[0].width, textures[0].height ] + ); + } + + }, + + /** + * Update the render options for the current shader program. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#updateRenderOptions + * @since 4.0.0 + * @param {object} renderOptions - The new render options. + */ + updateRenderOptions: function (renderOptions) + { + var newRenderOptions = this.nextRenderOptions; + var oldRenderOptions = this.renderOptions; + var changed = false; + + var multiTexturing = !!renderOptions.multiTexturing && !renderOptions.lighting; + if (multiTexturing !== oldRenderOptions.multiTexturing) + { + newRenderOptions.multiTexturing = multiTexturing; + changed = true; + } + + var lighting = !!renderOptions.lighting; + if (lighting !== oldRenderOptions.lighting) + { + newRenderOptions.lighting = lighting; + changed = true; + } + + var selfShadow = lighting && renderOptions.lighting.selfShadow && renderOptions.lighting.selfShadow.enabled; + if (selfShadow !== oldRenderOptions.selfShadow) + { + newRenderOptions.selfShadow = selfShadow; + changed = true; + } + + var selfShadowPenumbra = selfShadow ? renderOptions.lighting.selfShadow.penumbra : 0; + if (selfShadowPenumbra !== oldRenderOptions.selfShadowPenumbra) + { + newRenderOptions.selfShadowPenumbra = selfShadowPenumbra; + changed = true; + } + + var selfShadowThreshold = selfShadow ? renderOptions.lighting.selfShadow.diffuseFlatThreshold : 0; + if (selfShadowThreshold !== oldRenderOptions.selfShadowThreshold) + { + newRenderOptions.selfShadowThreshold = selfShadowThreshold; + changed = true; + } + + var smoothPixelArt = !!renderOptions.smoothPixelArt; + if (smoothPixelArt !== oldRenderOptions.smoothPixelArt) + { + newRenderOptions.smoothPixelArt = smoothPixelArt; + newRenderOptions.texRes = smoothPixelArt; + changed = true; + } + + var roundPixels = !!renderOptions.roundPixels; + if (roundPixels !== oldRenderOptions.roundPixels) + { + newRenderOptions.roundPixels = roundPixels; + changed = true; + } + + this._renderOptionsChanged = changed; + }, + + /** + * Update the shader configuration based on render options. + * This is called automatically when the render options change. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#updateShaderConfig + * @since 4.0.0 + */ + updateShaderConfig: function () + { + var programManager = this.programManager; + var oldRenderOptions = this.renderOptions; + var newRenderOptions = this.nextRenderOptions; + var i; + + if (oldRenderOptions.multiTexturing !== newRenderOptions.multiTexturing) + { + var multiTexturing = newRenderOptions.multiTexturing; + oldRenderOptions.multiTexturing = multiTexturing; + + var texCountAddition = programManager.getAdditionsByTag('TexCount')[0]; + if (texCountAddition) + { + programManager.replaceAddition( + texCountAddition.name, + MakeDefineTexCount(multiTexturing ? this.maxTexturesPerBatch : 1) + ); + } + } + + if (oldRenderOptions.lighting !== newRenderOptions.lighting) + { + var lighting = newRenderOptions.lighting; + oldRenderOptions.lighting = lighting; + + var lightingAdditions = programManager.getAdditionsByTag('LIGHTING'); + for (i = 0; i < lightingAdditions.length; i++) + { + var lightingAddition = lightingAdditions[i]; + lightingAddition.disable = !lighting; + } + + if (lighting) + { + var defineLightsAddition = programManager.getAddition('DefineLights'); + if (defineLightsAddition) + { + defineLightsAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights; + } + } + } + + if (oldRenderOptions.selfShadow !== newRenderOptions.selfShadow) + { + var selfShadow = newRenderOptions.selfShadow; + oldRenderOptions.selfShadow = selfShadow; + + if (selfShadow) + { + programManager.addFeature('SELFSHADOW'); + } + else + { + programManager.removeFeature('SELFSHADOW'); + } + } + + oldRenderOptions.selfShadowPenumbra = newRenderOptions.selfShadowPenumbra; + oldRenderOptions.selfShadowThreshold = newRenderOptions.selfShadowThreshold; + + if (oldRenderOptions.smoothPixelArt !== newRenderOptions.smoothPixelArt) + { + var smoothPixelArt = newRenderOptions.smoothPixelArt; + oldRenderOptions.smoothPixelArt = smoothPixelArt; + + var smoothPixelArtAddition = programManager.getAddition('SmoothPixelArt'); + if (smoothPixelArtAddition) + { + smoothPixelArtAddition.disable = !smoothPixelArt; + } + } + + if (oldRenderOptions.texRes !== newRenderOptions.texRes) + { + var texRes = newRenderOptions.texRes; + oldRenderOptions.texRes = texRes; + + var texResAddition = programManager.getAddition('GetTexRes'); + if (texResAddition) + { + texResAddition.disable = !texRes; + } + } + + if (oldRenderOptions.roundPixels !== newRenderOptions.roundPixels) + { + var roundPixels = newRenderOptions.roundPixels; + oldRenderOptions.roundPixels = roundPixels; + + // Do not update the shader; this will be set as a uniform. + } + }, + + /** + * Draw then empty the current batch. + * + * This method is called automatically, by either this node or the manager, + * when the batch is full, or when something else needs to be rendered. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + run: function (drawingContext) + { + if (this.instanceCount === 0) { return; } + + this.onRunBegin(drawingContext); + + // Finalize the current batch entry. + this.pushCurrentBatchEntry(); + + var programManager = this.programManager; + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + + this.setupUniforms(drawingContext); + programManager.applyUniforms(program); + + var bytesPerIndexPerInstance = this.bytesPerIndexPerInstance; + var indicesPerInstance = this.indicesPerInstance; + var renderer = this.manager.renderer; + var vertexBuffer = this.vertexBufferLayout.buffer; + + // Update vertex buffers. + // Because we are probably using a generic vertex buffer + // which is larger than the current batch, we need to update + // the buffer with the correct size. + vertexBuffer.update(this.instanceCount * this.bytesPerInstance); + + var subBatches = this.batchEntries.length; + for (var i = 0; i < subBatches; i++) + { + var entry = this.batchEntries[i]; + + if (this.renderOptions.texRes) + { + this.setupTextureUniforms(entry.texture); + programManager.applyUniforms(program); + } + + renderer.drawElements( + drawingContext, + entry.texture, + program, + vao, + entry.count * indicesPerInstance, + entry.start * bytesPerIndexPerInstance + ); + } + } + + // Reset batch accumulation. + this.instanceCount = 0; + this.currentBatchEntry.start = 0; + this.batchEntries.length = 0; + + this.onRunEnd(drawingContext); + }, + + /** + * Add a quad to the batch. + * + * For compatibility with TRIANGLE_STRIP rendering, + * the vertices are added in the order: + * + * - Top-left + * - Bottom-left + * - Top-right + * - Bottom-right + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#batch + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} currentContext - The current drawing context. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} glTexture - The texture to render. + * @param {number} x0 - The x coordinate of the top-left corner. + * @param {number} y0 - The y coordinate of the top-left corner. + * @param {number} x1 - The x coordinate of the bottom-left corner. + * @param {number} y1 - The y coordinate of the bottom-left corner. + * @param {number} x2 - The x coordinate of the top-right corner. + * @param {number} y2 - The y coordinate of the top-right corner. + * @param {number} x3 - The x coordinate of the bottom-right corner. + * @param {number} y3 - The y coordinate of the bottom-right corner. + * @param {number} texX - The left u coordinate (0-1). + * @param {number} texY - The top v coordinate (0-1). + * @param {number} texWidth - The width of the texture (0-1). + * @param {number} texHeight - The height of the texture (0-1). + * @param {boolean} tintFill - Whether to tint the fill color. + * @param {number} tintTL - The top-left tint color. + * @param {number} tintBL - The bottom-left tint color. + * @param {number} tintTR - The top-right tint color. + * @param {number} tintBR - The bottom-right tint color. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerQuadRenderOptions} renderOptions - Optional render features. + * @param {...*} [args] - Additional arguments for subclasses. + */ + batch: function ( + currentContext, + glTexture, + x0, y0, + x1, y1, + x2, y2, + x3, y3, + texX, texY, + texWidth, texHeight, + tintFill, + tintTL, tintBL, tintTR, tintBR, + renderOptions + ) + { + if (this.instanceCount === 0) + { + this.manager.setCurrentBatchNode(this, currentContext); + } + + // Check render options and run the batch if they differ. + this.updateRenderOptions(renderOptions); + if (this._renderOptionsChanged) + { + this.run(currentContext); + this.updateShaderConfig(); + } + + // Process textures and get relevant data. + var textureDatum = this.batchTextures(glTexture, renderOptions); + + // Update the vertex buffer. + var vertexOffset32 = this.instanceCount * this.floatsPerInstance; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + var vertexViewU32 = vertexBuffer.viewU32; + + // Bottom-left + vertexViewF32[vertexOffset32++] = x1; + vertexViewF32[vertexOffset32++] = y1; + vertexViewF32[vertexOffset32++] = texX; + vertexViewF32[vertexOffset32++] = texY + texHeight; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintBL; + + // Top-left + vertexViewF32[vertexOffset32++] = x0; + vertexViewF32[vertexOffset32++] = y0; + vertexViewF32[vertexOffset32++] = texX; + vertexViewF32[vertexOffset32++] = texY; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintTL; + + // Bottom-right + vertexViewF32[vertexOffset32++] = x3; + vertexViewF32[vertexOffset32++] = y3; + vertexViewF32[vertexOffset32++] = texX + texWidth; + vertexViewF32[vertexOffset32++] = texY + texHeight; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintBR; + + // Top-right + vertexViewF32[vertexOffset32++] = x2; + vertexViewF32[vertexOffset32++] = y2; + vertexViewF32[vertexOffset32++] = texX + texWidth; + vertexViewF32[vertexOffset32++] = texY; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintTR; + + // Increment the instance count. + this.instanceCount++; + this.currentBatchEntry.count++; + + // Check whether the batch should be rendered immediately. + // This guarantees that none of the arrays are full above. + if (this.instanceCount === this.instancesPerBatch) + { + this.run(currentContext); + + // Now the batch is empty. + } + }, + + /** + * Process textures for batching. + * This method is called automatically by the `batch` method. + * It returns a piece of data used for various texture tasks, + * depending on the render options. + * + * The texture datum may be used for texture ID or normal map rotation. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#batchTextures + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} glTexture - The texture to render. + * @param {object} renderOptions - The current render options. + * @return {number} The texture datum. + */ + batchTextures: function (glTexture, renderOptions) + { + var newRenderOptions = this.renderOptions; + + // Texture data, used for either texture ID or normal map rotation. + var textureDatum = 0; + + var currentBatchEntry = this.currentBatchEntry; + if (newRenderOptions.multiTexturing) + { + // Multi Texture + + // Check if the texture is already in the batch. + // This could be a very expensive operation if we're not careful. + // If we just use `batchTextures.indexOf`, a linear search, + // we can use up to 20% of a frame budget. + // Instead, we cache the texture unit index on the texture itself, + // so we can immediately tell whether it's in the batch. + // We reset this value when we flush the batch. + + textureDatum = glTexture.batchUnit; + if (textureDatum === -1) + { + if (currentBatchEntry.texture.length === this.maxTexturesPerBatch) + { + // Commit the current batch entry and start a new one. + this.pushCurrentBatchEntry(); + currentBatchEntry = this.currentBatchEntry; + } + textureDatum = currentBatchEntry.unit; + glTexture.batchUnit = textureDatum; + currentBatchEntry.texture[textureDatum] = glTexture; + currentBatchEntry.unit++; + } + } + else if (newRenderOptions.lighting) + { + textureDatum = renderOptions.lighting.normalMapRotation; + + var normalGLTexture = renderOptions.lighting.normalGLTexture; + if ( + currentBatchEntry.texture[0] !== glTexture || + currentBatchEntry.texture[1] !== normalGLTexture + ) + { + this.pushCurrentBatchEntry(); + + // // Complete the entire batch if the texture changes. + // this.run(currentContext); + + // Current batch entry has been redefined. + currentBatchEntry = this.currentBatchEntry; + glTexture.batchUnit = 0; + normalGLTexture.batchUnit = 1; + currentBatchEntry.texture[0] = glTexture; + currentBatchEntry.texture[1] = normalGLTexture; + currentBatchEntry.unit = 2; + } + } + else if (currentBatchEntry.texture[0] !== glTexture) + { + // Single texture. + this.pushCurrentBatchEntry(); + + // Current batch entry has been redefined. + currentBatchEntry = this.currentBatchEntry; + glTexture.batchUnit = 0; + currentBatchEntry.texture[0] = glTexture; + currentBatchEntry.unit = 1; + } + + return textureDatum; + }, + + /** + * Push the current batch entry to the batch entry list, + * and create a new batch entry for future use. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad#pushCurrentBatchEntry + * @since 4.0.0 + */ + pushCurrentBatchEntry: function () + { + if (this.currentBatchEntry.count < 1) + { + return; + } + + this.batchEntries.push(this.currentBatchEntry); + + // Clear unit assignment on textures. + var texture = this.currentBatchEntry.texture; + for (var i = 0; i < texture.length; i++) + { + texture[i].batchUnit = -1; + } + + this.currentBatchEntry = { + start: this.instanceCount, + count: 0, + unit: 0, + texture: [] + }; + } +}); + +module.exports = BatchHandlerQuad; + + +/***/ }), + +/***/ 62791: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var ShaderSourceFS = __webpack_require__(98840); +var ShaderSourceVS = __webpack_require__(44667); +var MakeApplyTint = __webpack_require__(44349); +var MakeDefineTexCount = __webpack_require__(11653); +var MakeGetTexCoordOut = __webpack_require__(42792); +var MakeGetTexRes = __webpack_require__(96049); +var MakeSmoothPixelArt = __webpack_require__(74505); +var MakeGetTexture = __webpack_require__(33997); +var Utils = __webpack_require__(70554); +var BatchHandlerQuad = __webpack_require__(15214); + +var getTint = Utils.getTintAppendFloatAlpha; + +/** + * @classdesc + * This RenderNode renders textured triangle strips, such as for the Rope + * Game Object. It uses batches to accelerate drawing. + * + * If a strip is submitted with too many vertices (usually >32,768), + * it will throw an error. + * + * Note that you should call `batchStrip` instead of `batch` to add strips. + * + * @class BatchHandlerStrip + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} config - The configuration object for this handler. + */ +var BatchHandlerStrip = new Class({ + Extends: BatchHandlerQuad, + + initialize: function BatchHandlerStrip (manager, config) + { + BatchHandlerQuad.call(this, manager, config); + + // We do not expect to use extra textures. + this.renderOptions.multiTexturing = true; + }, + + /** + * The default configuration object for this handler. + * This is merged with the `config` object passed in the constructor. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerStrip#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} + * @since 4.0.0 + */ + defaultConfig: { + name: 'BatchHandlerStrip', + verticesPerInstance: 2, + indicesPerInstance: 2, + shaderName: 'STRIP', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + shaderAdditions: [ + MakeGetTexCoordOut(), + MakeGetTexRes(true), + MakeSmoothPixelArt(true), + MakeDefineTexCount(1), + MakeGetTexture(), + MakeApplyTint() + ], + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + layout: [ + { + name: 'inPosition', + size: 2 + }, + { + name: 'inTexCoord', + size: 2 + }, + { + name: 'inTexDatum' + }, + { + name: 'inTintEffect' + }, + { + name: 'inTint', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + } + ] + } + }, + + /** + * Generate element indices for the instance vertices. + * This is called automatically when the node is initialized. + * + * By default, each instance is a vertex pair. + * Pairs are composed into triangle strips. + * Strips in batches are linked by degenerate triangles, + * created by repeating the last and first vertices of each strip + * in an intermediate pair. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerStrip#_generateElementIndices + * @since 4.0.0 + * @private + * @param {number} instances - The number of instances to define. + * @return {ArrayBuffer} The index buffer data. + */ + _generateElementIndices: function (instances) + { + var buffer = new ArrayBuffer(instances * 2 * 2); + var indices = new Uint16Array(buffer); + var len = indices.length; + for (var i = 0; i < len; i++) + { + indices[i] = i; + } + return buffer; + }, + + /** + * Add a strip to the batch. + * + * This method would usually be named `batch`, but the call signature + * is different from the other batch handlers. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerStrip#batchStrip + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} src - The Game Object being rendered. + * @param {Phaser.GameObjects.Components.TransformMatrix} calcMatrix - The current transform matrix. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} glTexture - The texture to render. + * @param {Float32Array} vertices - The vertices of the strip. + * @param {Float32Array} uv - The UV coordinates of the strip. + * @param {Uint32Array} colors - The color values of the strip. + * @param {Float32Array} alphas - The alpha values of the strip. + * @param {number} alpha - The overall alpha value of the strip. + * @param {boolean} tintFill - Whether to tint the fill color. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerQuadRenderOptions} renderOptions - Optional render features. Strip rendering should always set `multiTexturing` to false. It can use `smoothPixelArt`. Other options are ignored. + * @param {function} [debugCallback] - The debug callback, called with an array consisting of alternating x,y values of the transformed vertices. + */ + batchStrip: function ( + drawingContext, + src, + calcMatrix, + glTexture, + vertices, + uv, + colors, + alphas, + alpha, + tintFill, + renderOptions, + debugCallback + ) + { + if (this.instanceCount === 0) + { + this.manager.setCurrentBatchNode(this, drawingContext); + } + + var submittedInstanceCount = vertices.length / (2 * this.verticesPerInstance); + if (submittedInstanceCount > this.instancesPerBatch) + { + throw new Error('BatchHandlerStrip: Vertex count exceeds maximum per batch (' + this.maxVerticesPerBatch + ')'); + } + + // Check whether the batch should be rendered immediately. + // This guarantees that none of the arrays are full below. + if (this.instanceCount + submittedInstanceCount > this.instancesPerBatch) + { + this.run(drawingContext); + + // Now the batch is empty. + } + + // Check render options and run the batch if they differ. + this.updateRenderOptions(renderOptions); + if (this._renderOptionsChanged) + { + this.run(drawingContext); + this.updateShaderConfig(); + } + + // Process textures and get relevant data. + var textureDatum = this.batchTextures(glTexture); + + // Update the vertex buffer. + var vertexOffset32 = this.instanceCount * this.floatsPerInstance; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + var vertexViewU32 = vertexBuffer.viewU32; + + var repeatFirstVertex = false; + + // Add degenerate triangles between strips. + if (this.instanceCount > 0) + { + var prevOffset = 1 + this.floatsPerInstance / this.verticesPerInstance; + + // Copy the previous vertex to the start of the next strip. + vertexViewF32[vertexOffset32++] = vertexViewF32[vertexOffset32 - prevOffset]; + vertexViewF32[vertexOffset32++] = vertexViewF32[vertexOffset32 - prevOffset]; + vertexViewF32[vertexOffset32++] = vertexViewF32[vertexOffset32 - prevOffset]; + vertexViewF32[vertexOffset32++] = vertexViewF32[vertexOffset32 - prevOffset]; + vertexViewF32[vertexOffset32++] = vertexViewF32[vertexOffset32 - prevOffset]; + vertexViewF32[vertexOffset32++] = vertexViewF32[vertexOffset32 - prevOffset]; + vertexViewU32[vertexOffset32++] = vertexViewU32[vertexOffset32 - prevOffset]; + + repeatFirstVertex = true; + } + + var debugVerts; + if (debugCallback) + { + debugVerts = []; + } + + var a = calcMatrix.a; + var b = calcMatrix.b; + var c = calcMatrix.c; + var d = calcMatrix.d; + var e = calcMatrix.e; + var f = calcMatrix.f; + + var meshVerticesLength = vertices.length; + + for (var i = 0; i < meshVerticesLength; i += 2) + { + var x = vertices[i]; + var y = vertices[i + 1]; + + var tx = x * a + y * c + e; + var ty = x * b + y * d + f; + + vertexViewF32[vertexOffset32++] = tx; + vertexViewF32[vertexOffset32++] = ty; + vertexViewF32[vertexOffset32++] = uv[i]; + vertexViewF32[vertexOffset32++] = uv[i + 1]; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = getTint( + colors[i / 2], + alphas[i / 2] * alpha + ); + + if (repeatFirstVertex) + { + // Repeat the first vertex of the strip. + i -= 2; + + // Increment the instance count. + this.instanceCount++; + this.currentBatchEntry.count++; + + repeatFirstVertex = false; + } + else if (debugVerts) + { + debugVerts.push(tx, ty); + } + + if (i % 4 === 2) + { + // Every 2 vertices is an instance. + + // Increment the instance count. + this.instanceCount++; + this.currentBatchEntry.count++; + } + } + + if (debugCallback) + { + debugCallback.call(src, src, meshVerticesLength, debugVerts); + } + } +}); + +module.exports = BatchHandlerStrip; + + +/***/ }), + +/***/ 21832: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var ShaderSourceFS = __webpack_require__(98840); +var ShaderSourceVS = __webpack_require__(44667); +var MakeApplyLighting = __webpack_require__(81084); +var MakeApplyTint = __webpack_require__(44349); +var MakeDefineLights = __webpack_require__(6184); +var MakeDefineTexCount = __webpack_require__(11653); +var MakeGetNormalFromMap = __webpack_require__(40829); +var MakeGetTexCoordOut = __webpack_require__(42792); +var MakeGetTexRes = __webpack_require__(96049); +var MakeGetTexture = __webpack_require__(33997); +var MakeOutFrame = __webpack_require__(10455); +var MakeOutInverseRotation = __webpack_require__(79532); +var MakeRotationDatum = __webpack_require__(65217); +var MakeSmoothPixelArt = __webpack_require__(74505); +var MakeTexCoordFrameClamp = __webpack_require__(44832); +var MakeTexCoordFrameWrap = __webpack_require__(23295); +var BatchHandlerQuad = __webpack_require__(15214); + +/** + * @classdesc + * This RenderNode handles batch rendering of TileSprites and Tiles. + * It supplies shaders with knowledge of the frame and texture data, + * which can be used to handle texture borders more intelligently. + * + * @class BatchHandlerTileSprite + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this handler. + */ +var BatchHandlerTileSprite = new Class({ + Extends: BatchHandlerQuad, + + initialize: function BatchHandlerTileSprite (manager, config) + { + BatchHandlerQuad.call(this, manager, config); + }, + + defaultConfig: { + name: 'BatchHandlerTileSprite', + verticesPerInstance: 4, + indicesPerInstance: 6, + shaderName: 'TILESPRITE', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + shaderAdditions: [ + MakeOutFrame(), + MakeGetTexCoordOut(), + MakeGetTexRes(true), + MakeTexCoordFrameWrap(true), + MakeTexCoordFrameClamp(true), + MakeSmoothPixelArt(true), + MakeDefineTexCount(1), + MakeGetTexture(), + MakeApplyTint(), + MakeDefineLights(true), + MakeRotationDatum(true), + MakeOutInverseRotation(true), + MakeGetNormalFromMap(true), + MakeApplyLighting(true) + ], + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + layout: [ + { + name: 'inPosition', + size: 2 + }, + { + name: 'inTexCoord', + size: 2 + }, + { + name: 'inFrame', + size: 4 + }, + { + name: 'inTexDatum' + }, + { + name: 'inTintEffect' + }, + { + name: 'inTint', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + } + ] + } + }, + + updateRenderOptions: function (renderOptions) + { + BatchHandlerQuad.prototype.updateRenderOptions.call(this, renderOptions); + + var oldRenderOptions = this.renderOptions; + var newRenderOptions = this.nextRenderOptions; + var changed = this._renderOptionsChanged; + + newRenderOptions.clampFrame = !!renderOptions.clampFrame; + if (newRenderOptions.clampFrame !== oldRenderOptions.clampFrame) + { + changed = true; + } + + newRenderOptions.wrapFrame = !!renderOptions.wrapFrame; + if (newRenderOptions.wrapFrame !== oldRenderOptions.wrapFrame) + { + changed = true; + } + + // Enable texture resolution data if not already available. + newRenderOptions.texRes = newRenderOptions.clampFrame || newRenderOptions.texRes; + if (newRenderOptions.texRes !== oldRenderOptions.texRes) + { + changed = true; + } + + if (changed) + { + this._renderOptionsChanged = true; + } + }, + + updateShaderConfig: function () + { + BatchHandlerQuad.prototype.updateShaderConfig.call(this); + + var programManager = this.programManager; + var oldRenderOptions = this.renderOptions; + var newRenderOptions = this.nextRenderOptions; + + if (newRenderOptions.clampFrame !== oldRenderOptions.clampFrame) + { + var clampFrame = newRenderOptions.clampFrame; + oldRenderOptions.clampFrame = clampFrame; + + var clampAddition = programManager.getAddition('TexCoordFrameClamp'); + clampAddition.disable = !newRenderOptions.clampFrame; + } + + if (newRenderOptions.wrapFrame !== oldRenderOptions.wrapFrame) + { + var wrapFrame = newRenderOptions.wrapFrame; + oldRenderOptions.wrapFrame = wrapFrame; + + var wrapAddition = programManager.getAddition('TexCoordFrameWrap'); + wrapAddition.disable = !wrapFrame; + } + }, + + /** + * Add a quad to the batch. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTileSprite#batch + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} glTexture - The texture to render. + * @param {number} x0 - The x-coordinate of the top-left corner. + * @param {number} y0 - The y-coordinate of the top-left corner. + * @param {number} x1 - The x-coordinate of the bottom-left corner. + * @param {number} y1 - The y-coordinate of the bottom-left corner. + * @param {number} x2 - The x-coordinate of the top-right corner. + * @param {number} y2 - The y-coordinate of the top-right corner. + * @param {number} x3 - The x-coordinate of the bottom-right corner. + * @param {number} y3 - The y-coordinate of the bottom-right corner. + * @param {number} texX - The left u coordinate (0-1). + * @param {number} texY - The top v coordinate (0-1). + * @param {number} texWidth - The width of the texture (0-1). + * @param {number} texHeight - The height of the texture (0-1). + * @param {boolean} tintFill - Whether to tint the fill color. + * @param {number} tintTL - The tint color for the top-left corner. + * @param {number} tintBL - The tint color for the bottom-left corner. + * @param {number} tintTR - The tint color for the top-right corner. + * @param {number} tintBR - The tint color for the bottom-right corner. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerQuadRenderOptions} renderOptions - Optional render features. + * @param {number} u0 - The u coordinate of the distorted top-left corner. + * @param {number} v0 - The v coordinate of the distorted top-left corner. + * @param {number} u1 - The u coordinate of the distorted bottom-left corner. + * @param {number} v1 - The v coordinate of the distorted bottom-left corner. + * @param {number} u2 - The u coordinate of the distorted top-right corner. + * @param {number} v2 - The v coordinate of the distorted top-right corner. + * @param {number} u3 - The u coordinate of the distorted bottom-right corner. + * @param {number} v3 - The v coordinate of the distorted bottom-right corner. + */ + batch: function ( + drawingContext, + glTexture, + x0, y0, + x1, y1, + x2, y2, + x3, y3, + texX, texY, + texWidth, texHeight, + tintFill, + tintTL, tintBL, tintTR, tintBR, + renderOptions, + u0, v0, u1, v1, u2, v2, u3, v3 + ) + { + if (this.instanceCount === 0) + { + this.manager.setCurrentBatchNode(this, drawingContext); + } + + // Check render options and run the batch if they differ. + this.updateRenderOptions(renderOptions); + if (this._renderOptionsChanged) + { + this.run(drawingContext); + this.updateShaderConfig(); + } + + // Process textures and get relevant data. + var textureDatum = this.batchTextures(glTexture, renderOptions); + + // Update the vertex buffer. + var vertexOffset32 = this.instanceCount * this.floatsPerInstance; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + var vertexViewU32 = vertexBuffer.viewU32; + + // Bottom-left + vertexViewF32[vertexOffset32++] = x1; + vertexViewF32[vertexOffset32++] = y1; + vertexViewF32[vertexOffset32++] = u1; + vertexViewF32[vertexOffset32++] = v1; + vertexViewF32[vertexOffset32++] = texX; + vertexViewF32[vertexOffset32++] = texY; + vertexViewF32[vertexOffset32++] = texWidth; + vertexViewF32[vertexOffset32++] = texHeight; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintBL; + + // Top-left + vertexViewF32[vertexOffset32++] = x0; + vertexViewF32[vertexOffset32++] = y0; + vertexViewF32[vertexOffset32++] = u0; + vertexViewF32[vertexOffset32++] = v0; + vertexViewF32[vertexOffset32++] = texX; + vertexViewF32[vertexOffset32++] = texY; + vertexViewF32[vertexOffset32++] = texWidth; + vertexViewF32[vertexOffset32++] = texHeight; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintTL; + + // Bottom-right + vertexViewF32[vertexOffset32++] = x3; + vertexViewF32[vertexOffset32++] = y3; + vertexViewF32[vertexOffset32++] = u3; + vertexViewF32[vertexOffset32++] = v3; + vertexViewF32[vertexOffset32++] = texX; + vertexViewF32[vertexOffset32++] = texY; + vertexViewF32[vertexOffset32++] = texWidth; + vertexViewF32[vertexOffset32++] = texHeight; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintBR; + + // Top-right + vertexViewF32[vertexOffset32++] = x2; + vertexViewF32[vertexOffset32++] = y2; + vertexViewF32[vertexOffset32++] = u2; + vertexViewF32[vertexOffset32++] = v2; + vertexViewF32[vertexOffset32++] = texX; + vertexViewF32[vertexOffset32++] = texY; + vertexViewF32[vertexOffset32++] = texWidth; + vertexViewF32[vertexOffset32++] = texHeight; + vertexViewF32[vertexOffset32++] = textureDatum; + vertexViewF32[vertexOffset32++] = tintFill; + vertexViewU32[vertexOffset32++] = tintTR; + + // Increment the instance count. + this.instanceCount++; + this.currentBatchEntry.count++; + + // Check whether the batch should be rendered immediately. + // This guarantees that none of the arrays are full above. + if (this.instanceCount === this.instancesPerBatch) + { + this.run(drawingContext); + + // Now the batch is empty. + } + } +}); + +module.exports = BatchHandlerTileSprite; + + +/***/ }), + +/***/ 62087: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); +var Class = __webpack_require__(83419); +var MakeApplyLighting = __webpack_require__(81084); +var MakeDefineLights = __webpack_require__(6184); +var MakeFlatNormal = __webpack_require__(13198); +var ShaderSourceFS = __webpack_require__(73416); +var ShaderSourceVS = __webpack_require__(91627); +var Utils = __webpack_require__(70554); +var BatchHandler = __webpack_require__(13961); + +/** + * @classdesc + * This render node draws triangles with vertex color in batches. + * + * @class BatchHandlerTriFlat + * @extends Phaser.Renderer.WebGL.RenderNodes.BatchHandler + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this handler. + */ +var BatchHandlerTriFlat = new Class({ + Extends: BatchHandler, + + initialize: function BatchHandlerTriFlat (manager, config) + { + BatchHandler.call(this, manager, this.defaultConfig, config); + + /** + * An empty array. This is an internal space filler. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#_emptyTextures + * @type {Array} + * @private + * @since 4.0.0 + * @default [] + * @readonly + */ + this._emptyTextures = []; + + /** + * The number of vertices currently in the batch. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#vertexCount + * @type {number} + * @since 4.0.0 + */ + this.vertexCount = 0; + + /** + * A persistent calculation vector used when processing the lights. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlatLight#_lightVector + * @type {Phaser.Math.Vector2} + * @private + * @since 4.0.0 + */ + this._lightVector = new Vector2(); + + /** + * The current render options to which the batch is built. + * These help define the shader. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#renderOptions + * @type {object} + * @since 4.0.0 + */ + this.renderOptions = { + lighting: false + }; + + /** + * The render options currently being built. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#nextRenderOptions + * @type {object} + * @since 4.0.0 + */ + this.nextRenderOptions = { + lighting: false + }; + + /** + * A flag indicating that the render options have changed. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#_renderOptionsChanged + * @type {boolean} + * @private + * @since 4.0.0 + */ + this._renderOptionsChanged = false; + }, + + defaultConfig: { + name: 'BatchHandlerTriFlat', + verticesPerInstance: 3, + indicesPerInstance: 3, + shaderName: 'FLAT', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + shaderAdditions: [ + MakeDefineLights(true), + MakeFlatNormal(true), + MakeApplyLighting(true) + ], + indexBufferDynamic: true, + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + layout: [ + { + name: 'inPosition', + size: 2 + }, + { + name: 'inTint', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + } + ] + } + }, + + /** + * Generate element indices for the instance vertices. + * This is called automatically when the node is initialized. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#_generateElementIndices + * @since 4.0.0 + * @private + * @param {number} instances - The number of instances to define. + * @return {ArrayBuffer} The index buffer data. + */ + _generateElementIndices: function (instances) + { + return new ArrayBuffer(instances * 3 * 2); + }, + + /** + * Update the uniforms for the current shader program. + * + * This method is called automatically when the batch is run. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#setupUniforms + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + setupUniforms: function (drawingContext) + { + var programManager = this.programManager; + + drawingContext.renderer.setProjectionMatrixFromDrawingContext(drawingContext); + programManager.setUniform( + 'uProjectionMatrix', + drawingContext.renderer.projectionMatrix.val + ); + + if (this.renderOptions.lighting) + { + // Lighting uniforms. + Utils.updateLightingUniforms( + this.renderOptions.lighting, + this.manager.renderer, + drawingContext, + programManager, + 1, + this._lightVector + ); + + programManager.setUniform( + 'uResolution', + [ drawingContext.width, drawingContext.height ] + ); + } + }, + + updateRenderOptions: function (lighting) + { + var newRenderOptions = this.nextRenderOptions; + var oldRenderOptions = this.renderOptions; + var changed = false; + + if (lighting !== oldRenderOptions.lighting) + { + newRenderOptions.lighting = lighting; + changed = true; + } + + this._renderOptionsChanged = changed; + }, + + updateShaderConfig: function () + { + var programManager = this.programManager; + var renderOptions = this.renderOptions; + var nextRenderOptions = this.nextRenderOptions; + + if (renderOptions.lighting !== nextRenderOptions.lighting) + { + var lighting = nextRenderOptions.lighting; + renderOptions.lighting = lighting; + + var lightingAdditions = programManager.getAdditionsByTag('LIGHTING'); + for (var i = 0; i < lightingAdditions.length; i++) + { + var addition = lightingAdditions[i]; + addition.disable = !lighting; + } + + if (lighting) + { + var defineLightsAddition = programManager.getAddition('DefineLights'); + if (defineLightsAddition) + { + defineLightsAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights; + } + } + } + }, + + /** + * Draw then empty the current batch. + * + * This method is called automatically, by either this node or the manager, + * when the batch is full, or when something else needs to be rendered. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + run: function (drawingContext) + { + if (this.instanceCount === 0) { return; } + + this.onRunBegin(drawingContext); + + var programManager = this.programManager; + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + + this.setupUniforms(drawingContext); + programManager.applyUniforms(program); + + var indicesPerInstance = this.indicesPerInstance; + var instanceCount = this.instanceCount; + var renderer = this.manager.renderer; + var vertexBuffer = this.vertexBufferLayout.buffer; + var stride = this.vertexBufferLayout.layout.stride; + + // Update vertex buffers. + // Because we are probably using a generic vertex buffer + // which is larger than the current batch, we need to update + // the buffer with the correct size. + vertexBuffer.update(this.vertexCount * stride); + + // Update index buffer. + // We must bind the VAO before updating the index buffer. + // Each index is a 16-bit unsigned integer, so 2 bytes. + vao.bind(); + vao.indexBuffer.update(instanceCount * indicesPerInstance * 2); + + renderer.drawElements( + drawingContext, + this._emptyTextures, + program, + vao, + instanceCount * indicesPerInstance, + 0, + renderer.gl.TRIANGLES + ); + } + + // Reset batch accumulation. + this.instanceCount = 0; + this.vertexCount = 0; + + this.onRunEnd(drawingContext); + }, + + /** + * Add data to the batch. + * + * The data is composed of vertices and indexed triangles. + * Each triangle is defined by three indices into the vertices array. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat#batch + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} currentContext - The current drawing context. + * @param {number[]} indexes - The index data. Each triangle is defined by three indices into the vertices array, so the length of this should be a multiple of 3. + * @param {number[]} vertices - The vertices data. Each vertex is defined by an x-coordinate and a y-coordinate. + * @param {number[]} colors - The color data. Each vertex has a color as a Uint32 value. + * @param {boolean} [lighting=false] - Should this batch use lighting? + */ + batch: function (currentContext, indexes, vertices, colors, lighting) + { + if (this.instanceCount === 0) + { + this.manager.setCurrentBatchNode(this, currentContext); + } + + // Check render options and run the batch if they differ. + this.updateRenderOptions(lighting); + if (this._renderOptionsChanged) + { + this.run(currentContext); + this.updateShaderConfig(); + } + + var passID = 0; + var instanceCompletion = 0; + var instancesPerBatch = this.instancesPerBatch; + + // Buffer data + var stride = this.vertexBufferLayout.layout.stride; + var verticesPerInstance = this.verticesPerInstance; + + var indexBuffer = this.indexBuffer; + var indexView16 = indexBuffer.viewU16; + var indexOffset16 = this.instanceCount * this.indicesPerInstance; + + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + var vertexViewU32 = vertexBuffer.viewU32; + var vertexOffset32 = this.vertexCount * stride / vertexViewF32.BYTES_PER_ELEMENT; + + // Track vertex usage. + var passes = []; + var passOffset = 0; + var vertexIndices = []; + var vertexIndicesOffset = 0; + + for (var i = 0; i < indexes.length; i++) + { + var index = indexes[i]; + var vertexIndex = index * 2; + + if (passes[i] !== passID) + { + // Update the vertex buffer. + vertexViewF32[vertexOffset32++] = vertices[vertexIndex]; + vertexViewF32[vertexOffset32++] = vertices[vertexIndex + 1]; + vertexViewU32[vertexOffset32++] = colors[index]; + + // Assign the vertex to the current pass. + passes[passOffset++] = passID; + + // Record the index where the vertex was stored. + vertexIndices[vertexIndicesOffset++] = this.vertexCount; + + this.vertexCount++; + } + var id = vertexIndices[vertexIndicesOffset - 1]; + + // Update the index buffer. + // There is always at least one index per vertex, + // so we can assume that the vertex buffer is large enough. + indexView16[indexOffset16++] = id; + + // Check whether the instance is complete. + instanceCompletion++; + if (instanceCompletion === verticesPerInstance) + { + this.instanceCount++; + instanceCompletion = 0; + } + + // Check whether the batch should be rendered immediately. + // This guarantees that none of the arrays are full above. + if ( + // The instance count has been reached. + this.instanceCount === instancesPerBatch || + + // This triangle is complete, and another would exceed the index buffer size. + (instanceCompletion === 0 && indexOffset16 + verticesPerInstance >= indexView16.length) + ) + { + passID++; + this.run(currentContext); + + indexOffset16 = this.instanceCount * this.indicesPerInstance; + vertexOffset32 = this.vertexCount * stride / vertexViewF32.BYTES_PER_ELEMENT; + passOffset = 0; + vertexIndicesOffset = 0; + + // Now the batch is empty. + } + } + } +}); + +module.exports = BatchHandlerTriFlat; + + +/***/ }), + +/***/ 61842: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CameraEvents = __webpack_require__(19715); +var GetColor32 = __webpack_require__(1000); +var TransformMatrix = __webpack_require__(61340); +var Rectangle = __webpack_require__(87841); +var Equal = __webpack_require__(43855); +var Class = __webpack_require__(83419); +var Utils = __webpack_require__(70554); +var RenderNode = __webpack_require__(6141); + +function getAlphaTint (alpha) +{ + return Utils.getTintAppendFloatAlpha(0xffffff, alpha); +} + +/** + * @class Camera + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var Camera = new Class({ + Extends: RenderNode, + + initialize: function Camera (manager) + { + RenderNode.call(this, 'Camera', manager); + + /** + * The RenderNode that handles batching quads. + * This is used when a camera is rendering to a framebuffer, + * and the framebuffer needs to be drawn to the parent context. + * + * @name Phaser.Renderer.WebGL.RenderNodes.Camera#batchHandlerQuadNode + * @type {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerQuad} + * @since 4.0.0 + */ + this.batchHandlerQuadNode = manager.getNode('BatchHandlerQuad'); + + /** + * The RenderNode that handles filling the camera with a + * flat color. This is used to render the camera background, + * flash effects, and fade effects. + * + * @name Phaser.Renderer.WebGL.RenderNodes.Camera#fillCameraNode + * @type {Phaser.Renderer.WebGL.RenderNodes.FillCamera} + * @since 4.0.0 + */ + this.fillCameraNode = manager.getNode('FillCamera'); + + /** + * The RenderNode that handles rendering lists of children. + * + * @name Phaser.Renderer.WebGL.RenderNodes.Camera#listCompositorNode + * @type {Phaser.Renderer.WebGL.RenderNodes.ListCompositor} + * @since 4.0.0 + */ + this.listCompositorNode = manager.getNode('ListCompositor'); + + /** + * A temporary TransformMatrix used for the parent context + * within which this camera is renderered. + * + * @name Phaser.Renderer.WebGL.RenderNodes.Camera#_parentTransformMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 4.0.0 + */ + this._parentTransformMatrix = new TransformMatrix(); + }, + + /** + * Renders the children through this camera. + * + * @method Phaser.Renderer.WebGL.RenderNodes.Camera#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {Phaser.GameObjects.GameObject[]} children - The list of children to render. + * @param {Phaser.Cameras.Scene2D.Camera} camera - Current Camera. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentTransformMatrix] - This transform matrix is defined if the camera is focused on a filtered object. + * @param {boolean} [forceFramebuffer=false] - Should the camera always draw to a new framebuffer? This will also be activated if the camera has filters enabled. + * @param {number} [renderStep=0] - Which step of the rendering process is this? This is the index of the currently running function in a list of functions. + */ + run: function ( + drawingContext, + children, + camera, + parentTransformMatrix, + forceFramebuffer, + renderStep + ) + { + this.onRunBegin(drawingContext); + + var currentContext; + var drawingContextPool = drawingContext.renderer.drawingContextPool; + var manager = this.manager; + + var alpha = camera.alpha; + + // Check if the camera has any active filters. + var internalFilters = camera.filters.internal.getActive(); + var externalFilters = camera.filters.external.getActive(); + + var useFramebuffers = forceFramebuffer || camera.forceComposite || internalFilters.length || externalFilters.length || alpha < 1; + + if (!parentTransformMatrix) + { + parentTransformMatrix = this._parentTransformMatrix.copyFrom(camera.matrixExternal); + } + else + { + camera.matrixExternal.multiply(parentTransformMatrix, parentTransformMatrix); + } + + // Check whether the parentTransformMatrix is the identity matrix. + var decomposedParent = parentTransformMatrix.decomposeMatrix(); + var parentIsIdentity = + Equal(decomposedParent.translateX, 0) && + Equal(decomposedParent.translateY, 0) && + Equal(decomposedParent.rotation, 0) && + Equal(decomposedParent.scaleX, 1) && + Equal(decomposedParent.scaleY, 1); + + var cx = camera.x; + var cy = camera.y; + var cw = camera.width; + var ch = camera.height; + + // Generate a drawing context. + var baseContext = drawingContext.getClone(); + baseContext.setCamera(camera); + + if (useFramebuffers) + { + currentContext = drawingContextPool.get(cw, ch); + currentContext.setCamera(camera); + + // Set the scissor to the camera dimensions. + currentContext.setScissorBox(0, 0, cw, ch); + } + else + { + currentContext = baseContext; + currentContext.setScissorBox(cx, cy, cw, ch); + } + + // Enter drawing context. + currentContext.use(); + + var fillCamera = this.fillCameraNode; + + // Draw camera background. + if (camera.backgroundColor.alphaGL > 0) + { + var bg = camera.backgroundColor; + var col = GetColor32(bg.red, bg.green, bg.blue, bg.alpha); + fillCamera.run(currentContext, col, useFramebuffers); + } + + // Draw children. + this.listCompositorNode.run(currentContext, children, null, renderStep); + + // Draw camera post effects. + + var flashEffect = camera.flashEffect; + if (flashEffect.postRenderWebGL()) + { + col = GetColor32(flashEffect.red, flashEffect.green, flashEffect.blue, flashEffect.alpha * 255); + fillCamera.run(currentContext, col, useFramebuffers); + } + + var fadeEffect = camera.fadeEffect; + if (fadeEffect.postRenderWebGL()) + { + col = GetColor32(fadeEffect.red, fadeEffect.green, fadeEffect.blue, fadeEffect.alpha * 255); + fillCamera.run(currentContext, col, useFramebuffers); + } + + // Finish rendering children. + manager.finishBatch(); + + + // Filters and framebuffers. + if (useFramebuffers) + { + var index, filter, padding, renderNode, tint; + + // Determine whether to use round vertex coordinates. + // Keyword: #OnlyTranslate + var cmm = camera.matrix.matrix; + var roundPixels = camera.roundPixels && (cmm[0] === 1 && cmm[1] === 0 && cmm[2] === 0 && cmm[3] === 1); + + // Set up render options. + var renderOptions = { + smoothPixelArt: manager.renderer.game.config.smoothPixelArt, + roundPixels: roundPixels + }; + + // Draw internal filters. + var coverageInternal = new Rectangle(0, 0, currentContext.width, currentContext.height); + for (index = 0; index < internalFilters.length; index++) + { + filter = internalFilters[index]; + + // Execute the filter RenderNode. + renderNode = manager.getNode(filter.renderNode); + currentContext = renderNode.run(filter, currentContext); + + // Record padding. + padding = filter.getPadding(); + coverageInternal.setTo( + coverageInternal.x + padding.x, + coverageInternal.y + padding.y, + coverageInternal.width + padding.width, + coverageInternal.height + padding.height + ); + } + var outputContext = currentContext; + + // Begin external filters. + var drawExternalFilters = externalFilters.length > 0; + var copyInternal = !drawExternalFilters; + var coverageExternal = new Rectangle(0, 0, baseContext.width, baseContext.height); + if (drawExternalFilters) + { + // Calculate coverage, starting from the final filter. + for (index = externalFilters.length - 1; index >= 0; index--) + { + filter = externalFilters[index]; + + if (!filter.active) { continue; } + + padding = filter.getPadding(); + + // Increase coverage. + coverageExternal.setTo( + coverageExternal.x + padding.x, + coverageExternal.y + padding.y, + coverageExternal.width + padding.width, + coverageExternal.height + padding.height + ); + } + + // Will the texture need to be repositioned for the external filters? + copyInternal = + coverageExternal.width !== currentContext.width || + coverageExternal.height !== currentContext.height || + !parentIsIdentity; + + if (copyInternal) + { + // Create external context. + currentContext = drawingContextPool.get(coverageExternal.width, coverageExternal.height); + currentContext.setScissorBox(0, 0, coverageExternal.width, coverageExternal.height); + currentContext.setCamera(baseContext.camera); + currentContext.use(); + } + } + else + { + currentContext = baseContext; + } + + if (copyInternal) + { + // Draw the framebuffer to the external context. + // If there are no external filters, this will be the final draw. + var externalX = coverageExternal.x; + var externalY = coverageExternal.y; + var quad; + + parentTransformMatrix.setQuad( + coverageInternal.x, + coverageInternal.y, + coverageInternal.x + coverageInternal.width, + coverageInternal.y + coverageInternal.height + ); + quad = parentTransformMatrix.quad; + + tint = drawExternalFilters ? 0xffffffff : getAlphaTint(alpha); + + this.batchHandlerQuadNode.batch( + currentContext, + + // Texture. + // While this comes from a temporary framebuffer, + // and this is a batch operation, + // so the texture might not be accessed immediately, + // any operation that accesses the framebuffer pool + // will cause the batch to flush before the texture is reassigned. + outputContext.texture, + + // Transformed quad in order TL, BL, TR, BR: + quad[0] - externalX, quad[1] - externalY, + quad[2] - externalX, quad[3] - externalY, + quad[6] - externalX, quad[7] - externalY, + quad[4] - externalX, quad[5] - externalY, + + // Texture coordinates in X, Y, Width, Height: + 0, 1, 1, -1, + + // Tint color: + false, + + // Tint colors in order TL, BL, TR, BR: + tint, tint, tint, tint, + + // Render options: + renderOptions + ); + } + + if (outputContext !== currentContext) + { + outputContext.release(); + } + + + // Draw external filters. + if (drawExternalFilters) + { + var skipDrawOut = false; + outputContext = null; + padding = new Rectangle(); + + for (index = 0; index < externalFilters.length; index++) + { + filter = externalFilters[index]; + + if ( + // The filter supports drawing to the base context. + filter.allowBaseDraw && + + // The texture is the same size as the base context. + currentContext.width === baseContext.width && + currentContext.height === baseContext.height && + + // Last filter. + index === externalFilters.length - 1 && + + // Alpha is 1. + alpha === 1 + ) + { + // Draw the final filter straight to the base context. + skipDrawOut = true; + outputContext = baseContext; + } + + // Execute the filter RenderNode. + renderNode = manager.getNode(filter.renderNode); + currentContext = renderNode.run(filter, currentContext, outputContext, padding); + + // Get and invert the padding for the next step. + padding = filter.currentPadding; + + padding.x = -padding.x; + padding.y = -padding.y; + padding.width = -padding.width; + padding.height = -padding.height; + } + + if (!skipDrawOut) + { + // Draw external stack to parent context. + tint = getAlphaTint(alpha); + + var x1 = -padding.x; + var y1 = -padding.y; + var x2 = currentContext.width + padding.right; + var y2 = currentContext.height + padding.bottom; + + this.batchHandlerQuadNode.batch( + baseContext, + + // Texture. + currentContext.texture, + + // Transformed quad in order TL, BL, TR, BR: + x1, y2, + x1, y1, + x2, y2, + x2, y1, + + // Texture coordinates in X, Y, Width, Height: + 0, 0, 1, 1, + + // Tint color: + false, + + // Tint colors in order TL, BL, TR, BR: + tint, tint, tint, tint, + + // Render options: + renderOptions + ); + + currentContext.release(); + } + } + + } + + camera.dirty = false; + + camera.emit(CameraEvents.POST_RENDER, camera); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = Camera; + + +/***/ }), + +/***/ 76409: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which computes the geometry of a line segment. + * + * @class DrawLine + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var DrawLine = new Class({ + Extends: RenderNode, + + initialize: function DrawLine (manager) + { + RenderNode.call(this, 'DrawLine', manager); + }, + + /** + * Get the transformed vertices of a line segment as a quad. + * The values are pushed to a `vertices` list in the order TL, BL, BR, TR. + * + * @method Phaser.Renderer.WebGL.RenderNodes.DrawLine#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {?Phaser.GameObjects.Components.TransformMatrix} currentMatrix - A transform matrix to apply to the vertices. If not defined, the vertices are not transformed. + * @param {number} ax - The x coordinate of the start of the line. + * @param {number} ay - The y coordinate of the start of the line. + * @param {number} bx - The x coordinate of the end of the line. + * @param {number} by - The y coordinate of the end of the line. + * @param {number} aLineWidth - The width of the line at the start. + * @param {number} bLineWidth - The width of the line at the end. + * @param {number[]} vertices - The list to which the vertices are assigned. + */ + run: function (drawingContext, currentMatrix, ax, ay, bx, by, aLineWidth, bLineWidth, vertices) + { + this.onRunBegin(drawingContext); + + var dx = bx - ax; + var dy = by - ay; + + var len = Math.sqrt(dx * dx + dy * dy); + + // A well-formed path has no zero length segments, so we don't check. + + var al0 = aLineWidth * (by - ay) / len; + var al1 = aLineWidth * (ax - bx) / len; + var bl0 = bLineWidth * (by - ay) / len; + var bl1 = bLineWidth * (ax - bx) / len; + + var lx0 = bx - bl0; + var ly0 = by - bl1; + var lx1 = ax - al0; + var ly1 = ay - al1; + var lx2 = bx + bl0; + var ly2 = by + bl1; + var lx3 = ax + al0; + var ly3 = ay + al1; + + var offset = vertices.length; + + if (currentMatrix) + { + vertices[offset + 0] = currentMatrix.getX(lx3, ly3); + vertices[offset + 1] = currentMatrix.getY(lx3, ly3); + vertices[offset + 2] = currentMatrix.getX(lx1, ly1); + vertices[offset + 3] = currentMatrix.getY(lx1, ly1); + vertices[offset + 4] = currentMatrix.getX(lx0, ly0); + vertices[offset + 5] = currentMatrix.getY(lx0, ly0); + vertices[offset + 6] = currentMatrix.getX(lx2, ly2); + vertices[offset + 7] = currentMatrix.getY(lx2, ly2); + } + else + { + vertices[offset + 0] = lx3; + vertices[offset + 1] = ly3; + vertices[offset + 2] = lx1; + vertices[offset + 3] = ly1; + vertices[offset + 4] = lx0; + vertices[offset + 5] = ly0; + vertices[offset + 6] = lx2; + vertices[offset + 7] = ly2; + } + + this.onRunEnd(drawingContext); + } +}); + +module.exports = DrawLine; + + +/***/ }), + +/***/ 95449: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CameraEvents = __webpack_require__(19715); +var DynamicTextureCommands = __webpack_require__(42538); +var Class = __webpack_require__(83419); +var BlendModes = __webpack_require__(10312); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * This RenderNode handles rendering for DynamicTextures. + * + * @class DynamicTextureHandler + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var DynamicTextureHandler = new Class({ + Extends: RenderNode, + + initialize: function DynamicTextureHandler (manager) + { + RenderNode.call(this, 'DynamicTextureHandler', manager); + + /** + * The RenderNode that draws a filled rectangle. + * + * @name Phaser.Renderer.WebGL.RenderNodes.DynamicTextureHandler#fillRectNode + * @type {Phaser.Renderer.WebGL.RenderNodes.FillRect} + * @since 4.0.0 + */ + this.fillRectNode = this.manager.getNode('FillRect'); + }, + + /** + * Renders the DynamicTexture. + * + * @method Phaser.Renderer.WebGL.RenderNodes.DynamicTextureHandler#run + * @since 4.0.0 + * @param {Phaser.Textures.DynamicTexture} dynamicTexture - The DynamicTexture to render. + */ + run: function (dynamicTexture) + { + var drawingContext = dynamicTexture.drawingContext; + var camera = drawingContext.camera; + var renderer = drawingContext.renderer; + var textureManager = dynamicTexture.manager; + + this.onRunBegin(drawingContext); + + // Ensure the framebuffer texture is not bound, + // to avoid WebGL feedback. + var glTexture = drawingContext.framebuffer.renderTexture; + if (glTexture) + { + var glTextureUnits = renderer.glTextureUnits; + var units = glTextureUnits.units; + for (var i = 0; i < units.length; i++) + { + if (units[i] === glTexture) + { + glTextureUnits.bind(null, i); + } + } + } + + drawingContext.setScissorBox( + 0, + 0, + camera.width, + camera.height + ); + + // Enter drawing context. + drawingContext.use(); + + // Big list of reused variables. + var alpha, blendMode, frame, height, key, originX, originY, rotation, scaleX, scaleY, tint, width, x, y; + + // Traverse commands. + var commandBuffer = dynamicTexture.commandBuffer; + var commandBufferLength = commandBuffer.length; + + var eraseMode = false; + var eraseContext = null; + var preserveBuffer = false; + var currentContext = drawingContext; + var gl = renderer.gl; + + for (var index = 0; index < commandBufferLength; index++) + { + var command = commandBuffer[index]; + + switch (command) + { + case DynamicTextureCommands.CLEAR: + { + x = commandBuffer[++index]; + y = commandBuffer[++index]; + width = commandBuffer[++index]; + height = commandBuffer[++index]; + + var clearContext = currentContext.getClone(); + clearContext.setScissorEnable(true); + clearContext.setScissorBox(x, y, width, height); + clearContext.use(); + + clearContext.clear( + gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT + ); + + clearContext.release(); + + break; + } + + case DynamicTextureCommands.FILL: + { + var color = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + width = commandBuffer[++index]; + height = commandBuffer[++index]; + + this.fillRectNode.run( + currentContext, + null, + null, + x, y, width, height, + color, color, color, color, + false + ); + + break; + } + + case DynamicTextureCommands.STAMP: + { + key = commandBuffer[++index]; + frame = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + alpha = commandBuffer[++index]; + tint = commandBuffer[++index]; + rotation = commandBuffer[++index]; + scaleX = commandBuffer[++index]; + scaleY = commandBuffer[++index]; + originX = commandBuffer[++index]; + originY = commandBuffer[++index]; + blendMode = commandBuffer[++index]; + + var stamp = textureManager.resetStamp(alpha, tint); + + stamp.setPosition(x, y) + .setRotation(rotation) + .setTexture(key, frame) + .setOrigin(originX, originY) + .setScale(scaleX, scaleY) + .setBlendMode(blendMode); + + currentContext = this._draw(renderer, stamp, currentContext, drawingContext, eraseContext); + + break; + } + + case DynamicTextureCommands.REPEAT: + { + key = commandBuffer[++index]; + frame = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + alpha = commandBuffer[++index]; + tint = commandBuffer[++index]; + rotation = commandBuffer[++index]; + scaleX = commandBuffer[++index]; + scaleY = commandBuffer[++index]; + originX = commandBuffer[++index]; + originY = commandBuffer[++index]; + blendMode = commandBuffer[++index]; + + width = commandBuffer[++index]; + height = commandBuffer[++index]; + var tilePositionX = commandBuffer[++index]; + var tilePositionY = commandBuffer[++index]; + var tileRotation = commandBuffer[++index]; + var tileScaleX = commandBuffer[++index]; + var tileScaleY = commandBuffer[++index]; + + var repeat = textureManager.resetTileSprite(alpha, tint); + + repeat.setPosition(x, y) + .setRotation(rotation) + .setTexture(key, frame) + .setSize(width, height) + .setOrigin(originX, originY) + .setScale(scaleX, scaleY) + .setBlendMode(blendMode) + .setTilePosition(tilePositionX, tilePositionY) + .setTileRotation(tileRotation) + .setTileScale(tileScaleX, tileScaleY); + + currentContext = this._draw(renderer, repeat, currentContext, drawingContext, eraseContext); + + break; + } + + case DynamicTextureCommands.DRAW: + { + var object = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + + if (x !== undefined) + { + var prevX = object.x; + object.x = x; + } + + if (y !== undefined) + { + var prevY = object.y; + object.y = y; + } + + currentContext = this._draw(renderer, object, currentContext, drawingContext, eraseContext); + + if (x !== undefined) + { + object.x = prevX; + } + + if (y !== undefined) + { + object.y = prevY; + } + + break; + } + + case DynamicTextureCommands.SET_ERASE: + { + eraseMode = commandBuffer[++index]; + if (eraseMode) + { + if (!eraseContext) + { + eraseContext = drawingContext.getClone(); + eraseContext.setBlendMode(BlendModes.ERASE); + } + if (currentContext !== eraseContext) + { + currentContext.release(); + currentContext = eraseContext; + eraseContext.use(); + } + } + else if (currentContext === eraseContext) + { + eraseContext.release(); + currentContext = drawingContext; + drawingContext.use(); + } + break; + } + + case DynamicTextureCommands.PRESERVE: + { + preserveBuffer = commandBuffer[++index]; + break; + } + + case DynamicTextureCommands.CALLBACK: + { + var callback = commandBuffer[++index]; + callback(); + break; + } + + case DynamicTextureCommands.CAPTURE: + { + object = commandBuffer[++index]; + var config = commandBuffer[++index]; + + var cacheConfig = dynamicTexture.startCapture(object, config); + + // Handle custom capture camera. + var viewContext = currentContext; + if (config.camera) + { + viewContext = viewContext.getClone(); + viewContext.setCamera(config.camera); + viewContext.use(); + } + + this._draw(renderer, object, viewContext, drawingContext, eraseContext, cacheConfig.transform); + dynamicTexture.finishCapture(object, cacheConfig); + + if (config.camera) + { + viewContext.release(); + } + + break; + } + } + } + + if (!preserveBuffer) + { + // Clear the command buffer. + commandBuffer.length = 0; + } + + // Finish rendering. + currentContext.release(); + + camera.emit(CameraEvents.POST_RENDER, camera); + + this.onRunEnd(drawingContext); + }, + + /** + * Draw an object to the DynamicTexture, handling blend modes. + * + * @method Phaser.Renderer.WebGL.RenderNodes.DynamicTextureHandler#_draw + * @private + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer. + * @param {Phaser.GameObjects.GameObject} object - The object to draw. + * @param {Phaser.Renderer.WebGL.DrawingContext} currentContext - The current drawing context. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The base drawing context in use. + * @param {Phaser.Renderer.WebGL.DrawingContext} eraseContext - The erase drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - The parent matrix, if any. + * + * @return {Phaser.Renderer.WebGL.DrawingContext} The new current drawing context. + */ + _draw: function (renderer, object, currentContext, drawingContext, eraseContext, parentMatrix) + { + // Handle blend mode. + if ( + currentContext !== eraseContext && + object.blendMode !== currentContext.blendMode && + object.blendMode !== BlendModes.SKIP_CHECK + ) + { + currentContext.release(); + + var blendMode = object.blendMode; + if (blendMode === drawingContext.blendMode) + { + // Reset to the base context. + currentContext = drawingContext; + } + else + { + // Change blend mode. + currentContext = drawingContext.getClone(); + currentContext.setBlendMode(blendMode); + } + currentContext.use(); + } + + object.renderWebGLStep(renderer, object, currentContext, parentMatrix); + + return currentContext; + } +}); + +module.exports = DynamicTextureHandler; + + +/***/ }), + +/***/ 61199: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which fills a camera with a color. + * + * @class FillCamera + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FillCamera = new Class({ + Extends: RenderNode, + + initialize: function FillCamera (manager) + { + RenderNode.call(this, 'FillCamera', manager); + + /** + * The RenderNode that draws a filled rectangle. + * + * @name Phaser.Renderer.WebGL.RenderNodes.FillCamera#fillRectNode + * @type {Phaser.Renderer.WebGL.RenderNodes.FillRect} + * @since 4.0.0 + */ + this.fillRectNode = this.manager.getNode('FillRect'); + }, + + /** + * Fills the camera with a color. + * This uses `FillRect`, so it is batched with other quads. + * + * @method Phaser.Renderer.WebGL.RenderNodes.FillCamera#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {number} color - The color to fill the camera with. + * @param {boolean} [isFramebufferCamera] - Is this camera rendering to a framebuffer? If so, the camera position will not be applied, on the assumption that the camera position will be used to position the framebuffer in the external context. + */ + run: function (drawingContext, color, isFramebufferCamera) + { + this.onRunBegin(drawingContext); + + var camera = drawingContext.camera; + var cx = isFramebufferCamera ? 0 : camera.x; + var cy = isFramebufferCamera ? 0 : camera.y; + var cw = camera.width; + var ch = camera.height; + + this.fillRectNode.run(drawingContext, null, null, cx, cy, cw, ch, color, color, color, color); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = FillCamera; + + +/***/ }), + +/***/ 14255: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Earcut = __webpack_require__(94811); +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which fills a path. + * + * It works by taking the array of path data and then passing it through + * Earcut, which creates a list of polygons. + * Each polygon is then added to the batch. + * The polygons are triangles, but they're rendered as quads + * to be compatible with other batched quads. + * + * @class FillPath + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FillPath = new Class({ + Extends: RenderNode, + + initialize: function FillPath (manager) + { + RenderNode.call(this, 'FillPath', manager); + }, + + /** + * Render the path using Earcut. + * + * @method Phaser.Renderer.WebGL.RenderNodes.FillPath#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {Phaser.GameObjects.Components.TransformMatrix} currentMatrix - The current transform matrix. + * @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} submitterNode - The Submitter node to use. + * @param {Phaser.Types.GameObjects.Graphics.WidePoint[]} path - The points that define the line segments. + * @param {number} tintTL - The top-left tint color. + * @param {number} tintTR - The top-right tint color. + * @param {number} tintBL - The bottom-left tint color. + * @param {number} detail - The level of detail to use when filling the path. Points which are only this far apart in screen space are combined. It is ignored if the entire path is equal to or shorter than this distance. + * @param {boolean} lighting - Whether to apply lighting effects to the path. + */ + run: function (drawingContext, currentMatrix, submitterNode, path, tintTL, tintTR, tintBL, detail, lighting) + { + this.onRunBegin(drawingContext); + + if (detail === undefined) { detail = 0; } + + var length = path.length; + var index, pathIndex, point, polygonIndexArray, x, y; + + var polygonCacheIndex = 0; + var indexedTrianglesIndex = 0; + + var polygonCache = []; + var colors = []; + var colorsIndex = 0; + + for (pathIndex = 0; pathIndex < length; pathIndex++) + { + point = path[pathIndex]; + + // Transform the point. + x = currentMatrix.getX(point.x, point.y); + y = currentMatrix.getY(point.x, point.y); + + if ( + pathIndex > 0 && + pathIndex < length - 1 && + Math.abs(x - polygonCache[polygonCacheIndex - 2]) <= detail && + Math.abs(y - polygonCache[polygonCacheIndex - 1]) <= detail + ) + { + // Skip this point if it's too close to the previous point + // and is not the first or last point in the path. + continue; + } + + polygonCache[polygonCacheIndex++] = x; + polygonCache[polygonCacheIndex++] = y; + } + + polygonIndexArray = Earcut(polygonCache); + + if (tintTL === tintTR && tintTL === tintBL) + { + // If the tint colors are all the same, + // then we can share vertices between the triangles. + + var polygonCacheLength = polygonCache.length; + + for (index = 0; index < polygonCacheLength; index += 2) + { + colors[colorsIndex++] = tintTL; + } + + submitterNode.batch(drawingContext, polygonIndexArray, polygonCache, colors, lighting); + } + else + { + // If the tint colors are different, + // then we need to create a new vertex for each triangle. + + var indexLength = polygonIndexArray.length; + + var indexedTriangles = Array(indexLength); + var vertices = Array(indexLength * 2); + var verticesIndex = 0; + + for (index = 0; index < indexLength; index += 3) + { + // Vertex A + var p = polygonIndexArray[index] * 2; + x = polygonCache[p + 0]; + y = polygonCache[p + 1]; + + vertices[verticesIndex++] = x; + vertices[verticesIndex++] = y; + + // Vertex B + p = polygonIndexArray[index + 1] * 2; + x = polygonCache[p + 0]; + y = polygonCache[p + 1]; + + vertices[verticesIndex++] = x; + vertices[verticesIndex++] = y; + + // Vertex C + p = polygonIndexArray[index + 2] * 2; + x = polygonCache[p + 0]; + y = polygonCache[p + 1]; + + vertices[verticesIndex++] = x; + vertices[verticesIndex++] = y; + + colors[colorsIndex++] = tintTL; + colors[colorsIndex++] = tintTR; + colors[colorsIndex++] = tintBL; + + // Add new indices for the triangle. + indexedTriangles[indexedTrianglesIndex++] = index + 0; + indexedTriangles[indexedTrianglesIndex++] = index + 1; + indexedTriangles[indexedTrianglesIndex++] = index + 2; + } + + submitterNode.batch(drawingContext, indexedTriangles, vertices, colors, lighting); + } + + this.onRunEnd(drawingContext); + } +}); + +module.exports = FillPath; + + +/***/ }), + +/***/ 12682: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which renders a filled rectangle. + * This is useful for full-screen effects and rectangle geometry. + * + * @class FillRect + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FillRect = new Class({ + Extends: RenderNode, + + initialize: function FillRect (manager) + { + RenderNode.call(this, 'FillRect', manager); + + /** + * The fallback batch handler for this node. + * + * @name Phaser.Renderer.WebGL.RenderNodes.FillRect#_batchHandlerDefault + * @type {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} + * @since 4.0.0 + * @private + * @readonly + */ + this._batchHandlerDefault = manager.getNode('BatchHandlerTriFlat'); + + /** + * An unchanging identity matrix. + * + * @name Phaser.Renderer.WebGL.RenderNodes.FillRect#_identityMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 4.0.0 + */ + this._identityMatrix = new TransformMatrix(); + + /** + * Vertex indices for the rectangle. + * + * @name Phaser.Renderer.WebGL.RenderNodes.FillRect#_indexedTriangles + * @type {number[]} + * @private + * @since 4.0.0 + * @default [0, 1, 2, 2, 3, 0] + * @readonly + */ + this._indexedTriangles = [ + 0, 1, 2, + 2, 3, 0 + ]; + }, + + /** + * Render the rectangle. + * + * @method Phaser.Renderer.WebGL.RenderNodes.FillRect#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {?Phaser.GameObjects.Components.TransformMatrix} currentMatrix - A transform matrix to apply to the vertices. If not defined, the identity matrix is used. + * @param {?Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} submitterNode - The Submitter node to use. If not defined, `BatchHandlerTriFlat` is used. + * @param {number} x - The x-coordinate of the rectangle. + * @param {number} y - The y-coordinate of the rectangle. + * @param {number} width - The width of the rectangle. + * @param {number} height - The height of the rectangle. + * @param {number} tintTL - The top-left tint color. + * @param {number} tintTR - The top-right tint color. + * @param {number} tintBL - The bottom-left tint color. + * @param {number} tintBR - The bottom-right tint color. + * @param {boolean} lighting - Whether to apply lighting effects to the rectangle. + */ + run: function (drawingContext, currentMatrix, submitterNode, x, y, width, height, tintTL, tintTR, tintBL, tintBR, lighting) + { + this.onRunBegin(drawingContext); + + if (!currentMatrix) + { + currentMatrix = this._identityMatrix; + } + + if (!submitterNode) + { + submitterNode = this._batchHandlerDefault; + } + + var quad = currentMatrix.setQuad(x, y, x + width, y + height); + + submitterNode.batch( + drawingContext, + this._indexedTriangles, + quad, + [ + tintTL, tintBL, tintBR, tintTR + ], + lighting + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = FillRect; + + +/***/ }), + +/***/ 13119: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which renders a filled triangle. + * + * @class FillTri + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FillTri = new Class({ + Extends: RenderNode, + + initialize: function FillTri (manager) + { + RenderNode.call(this, 'FillTri', manager); + + /** + * Vertex indices for the triangle. + * + * @name Phaser.Renderer.WebGL.RenderNodes.FillTri#_indexedTriangles + * @type {number[]} + * @private + * @since 4.0.0 + * @default [0, 1, 2] + * @readonly + */ + this._indexedTriangles = [ + 0, 1, 2 + ]; + }, + + /** + * Render the triangle. + * + * @method Phaser.Renderer.WebGL.RenderNodes.FillTri#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {?Phaser.GameObjects.Components.TransformMatrix} currentMatrix - A transform matrix to apply to the vertices. If not defined, the vertices are not transformed. + * @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} submitterNode - The Submitter node to use. + * @param {number} xA - The x-coordinate of the first vertex. + * @param {number} yA - The y-coordinate of the first vertex. + * @param {number} xB - The x-coordinate of the second vertex. + * @param {number} yB - The y-coordinate of the second vertex. + * @param {number} xC - The x-coordinate of the third vertex. + * @param {number} yC - The y-coordinate of the third vertex. + * @param {number} tintA - The tint color of the first vertex. + * @param {number} tintB - The tint color of the second vertex. + * @param {number} tintC - The tint color of the third vertex. + * @param {boolean} lighting - Whether to apply lighting effects to the triangle. + */ + run: function (drawingContext, currentMatrix, submitterNode, xA, yA, xB, yB, xC, yC, tintA, tintB, tintC, lighting) + { + this.onRunBegin(drawingContext); + + if (currentMatrix) + { + submitterNode.batch( + drawingContext, + this._indexedTriangles, + [ + currentMatrix.getX(xA, yA), + currentMatrix.getY(xA, yA), + currentMatrix.getX(xB, yB), + currentMatrix.getY(xB, yB), + currentMatrix.getX(xC, yC), + currentMatrix.getY(xC, yC) + ], + [ + tintA, + tintB, + tintC + ], + lighting + ); + } + else + { + submitterNode.batch( + drawingContext, + this._indexedTriangles, + [ + xA, + yA, + xB, + yB, + xC, + yC + ], + [ + tintA, + tintB, + tintC + ], + lighting + ); + } + + this.onRunEnd(drawingContext); + } +}); + +module.exports = FillTri; + + +/***/ }), + +/***/ 27996: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(8054); +var RenderNode = __webpack_require__(6141); + +/** + * Render a list of Game Objects. + * + * @class ListCompositor + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var ListCompositor = new Class({ + Extends: RenderNode, + + initialize: function ListCompositor (manager) + { + RenderNode.call(this, 'ListCompositor', manager); + }, + + /** + * Render each child in the display list. + * + * This allocates a new DisplayContext if a child's blend mode is different + * from the previous child. This will start a new batch if one is in progress. + * + * @method Phaser.Renderer.WebGL.RenderNodes.ListCompositor#render + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} displayContext - The context currently in use. + * @param {Phaser.GameObjects.GameObject[]} children - The list of children to render. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentTransformMatrix] - This transform matrix is defined if the game object is nested + * @param {number} [renderStep=0] - Which step of the rendering process is this? This is the index of the currently running function in a list of functions. + */ + run: function ( + displayContext, + children, + parentTransformMatrix, + renderStep + ) + { + this.onRunBegin(displayContext); + + var currentContext = displayContext; + var baseBlendMode = displayContext.blendMode; + var currentBlendMode = baseBlendMode; + var renderer = this.manager.renderer; + + // Render each child in the display list + for (var i = 0; i < children.length; i++) + { + var child = children[i]; + + if ( + child.blendMode !== currentBlendMode && + child.blendMode !== CONST.BlendModes.SKIP_CHECK + ) + { + if (currentContext !== displayContext) + { + // Only release non-base contexts. + currentContext.release(); + } + + currentBlendMode = child.blendMode; + + if (currentBlendMode === baseBlendMode) + { + // Reset to the base context. + currentContext = displayContext; + } + else + { + // Change blend mode. + currentContext = displayContext.getClone(); + currentContext.setBlendMode(currentBlendMode); + currentContext.use(); + } + } + + child.renderWebGLStep(renderer, child, currentContext, parentTransformMatrix, renderStep, children, i); + } + + // Release any remaining context. + if (currentContext !== displayContext) + { + currentContext.release(); + } + + this.onRunEnd(displayContext); + } +}); + +module.exports = ListCompositor; + + +/***/ }), + +/***/ 56432: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Merge = __webpack_require__(46975); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * RebindContext is a RenderNode which sets the WebGL context to + * a default state, resetting important properties + * that might have been changed by an external renderer. + * + * This is used by the Extern GameObject after rendering. + * It is the counterpart of YieldContext. + * + * @class RebindContext + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var RebindContext = new Class({ + Extends: RenderNode, + + initialize: function RebindContext (manager) + { + RenderNode.call(this, 'RebindContext', manager); + + /** + * The WebGL state to set when this node is run. + * This is read-only. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RebindContext#_state + * @type {Partial} + * @private + * @since 4.0.0 + * @readonly + */ + this._state = { + bindings: { + activeTexture: 0, + arrayBuffer: null, + elementArrayBuffer: null, + framebuffer: null, + program: null, + renderbuffer: null + }, + vao: null + }; + }, + + run: function (displayContext) + { + this.onRunBegin(displayContext); + + var renderer = this.manager.renderer; + var glWrapper = renderer.glWrapper; + + // Clear the current framebuffer's stencil and depth renderbuffers. + renderer.clearFramebuffer( + undefined, + undefined, // Stencil is currently not implemented by DrawingContext. + 0 + ); + + // Rebind the entire WebGL state, setting resources to null. + glWrapper.update(Merge(this._state, glWrapper.state), true); + + // Unbind all texture units, forcing rebind on use. + renderer.glTextureUnits.unbindAllUnits(); + + this.onRunEnd(displayContext); + } +}); + +module.exports = RebindContext; + + +/***/ }), + +/***/ 6141: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * A RenderNode is a node in the rendering graph. + * It is invoked by calling `run`, which takes inputs and returns outputs + * depending on the subclass implementation. + * + * @class RenderNode + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {string} name - The name of the RenderNode. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var RenderNode = new Class({ + + initialize: + + function RenderNode (name, manager) + { + /** + * The name of the RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNode#name + * @type {string} + * @since 4.0.0 + */ + this.name = name; + + /** + * The manager that owns this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNode#manager + * @type {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} + * @since 4.0.0 + */ + this.manager = manager; + + /** + * Reference to the original `run` method of this node. + * Used when `setDebug` is enabled. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNode#_run + * @type {?function} + * @private + * @since 4.0.0 + * @default null + */ + this._run = null; + }, + + /** + * Run the RenderNode. + * This is a stub method that should be overridden by the specific + * implementation. + * + * This method may be wrapped by `setDebug`. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNode#run + * @param {...*} [args] - Arguments to pass to the node. These will vary depending on the node. + * @since 4.0.0 + */ + run: function () + { + // Insert code here. + }, + + /** + * By default this is an empty method hook that you can override and use in your own custom render nodes. + * + * This method is called at the start of the `run` method. + * Don't forget to call it in your custom method. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNode#onRunBegin + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + */ + onRunBegin: function (drawingContext) + {}, + + /** + * By default this is an empty method hook that you can override and use in your own custom render nodes. + * + * This method is called at the end of the `run` method. + * Don't forget to call it in your custom method. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNode#onRunEnd + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + */ + onRunEnd: function (drawingContext) + {}, + + /** + * Set whether the node should report debug information. + * It wraps the `run` method with additional debug information. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNode#setDebug + * @since 4.0.0 + * @param {boolean} debug - Whether to report debug information. + */ + setDebug: function (debug) + { + if (debug) + { + this._run = this.run; + + this.run = function () + { + var manager = this.manager; + manager.pushDebug(this.name); + + var output = this._run.apply(this, arguments); + + manager.popDebug(); + + return output; + }; + } + else + { + this.run = this._run; + this._run = null; + } + } +}); + +module.exports = RenderNode; + + +/***/ }), + +/***/ 30130: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var EventEmitter = __webpack_require__(50792); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(92503); + +var BaseFilter = __webpack_require__(47406); +var BaseFilterShader = __webpack_require__(53663); + +var BatchHandlerPointLight = __webpack_require__(16971); +var BatchHandlerQuad = __webpack_require__(15214); +var BatchHandlerStrip = __webpack_require__(62791); +var BatchHandlerTileSprite = __webpack_require__(21832); +var BatchHandlerTriFlat = __webpack_require__(62087); + +var Camera = __webpack_require__(61842); +var DrawLine = __webpack_require__(76409); +var DynamicTextureHandler = __webpack_require__(95449); +var FillCamera = __webpack_require__(61199); +var FillPath = __webpack_require__(14255); +var FillRect = __webpack_require__(12682); +var FillTri = __webpack_require__(13119); + +var FilterBarrel = __webpack_require__(22731); +var FilterBlend = __webpack_require__(57032); +var FilterBlur = __webpack_require__(13922); +var FilterBlurHigh = __webpack_require__(33466); +var FilterBlurLow = __webpack_require__(75798); +var FilterBlurMed = __webpack_require__(90830); +var FilterBokeh = __webpack_require__(52302); +var FilterColorMatrix = __webpack_require__(34989); +var FilterDisplacement = __webpack_require__(15600); +var FilterGlow = __webpack_require__(99786); +var FilterMask = __webpack_require__(26703); +var FilterParallelFilters = __webpack_require__(55905); +var FilterPixelate = __webpack_require__(58167); +var FilterSampler = __webpack_require__(13279); +var FilterShadow = __webpack_require__(27459); +var FilterThreshold = __webpack_require__(88856); + +var ListCompositor = __webpack_require__(27996); +var RebindContext = __webpack_require__(56432); +var StrokePath = __webpack_require__(17486); +var SubmitterQuad = __webpack_require__(31029); +var SubmitterTile = __webpack_require__(94494); +var SubmitterTilemapGPULayer = __webpack_require__(87469); +var SubmitterTileSprite = __webpack_require__(89723); +var TexturerImage = __webpack_require__(12913); +var TexturerTileSprite = __webpack_require__(22995); +var TransformerImage = __webpack_require__(86081); +var TransformerStamp = __webpack_require__(88383); +var TransformerTile = __webpack_require__(34454); +var TransformerTileSprite = __webpack_require__(46211); +var YieldContext = __webpack_require__(95433); + +/** + * @typedef {object} DebugGraphNode + * @property {string} name - The name of the node. + * @property {DebugGraphNode[]} children - The children of the node. + * @property {DebugGraphNode} parent - The parent of the node. + */ + +/** + * Provides and manages the nodes in the rendering graph. + * + * @class RenderNodeManager + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer that owns this manager. + */ +var RenderNodeManager = new Class({ + Extends: EventEmitter, + + initialize: function RenderNodeManager (renderer) + { + EventEmitter.call(this); + + /** + * The renderer that owns this manager. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + var game = renderer.game; + + /** + * The maximum number of texture units to use as choices in a batch. + * Batches can bind several textures and select one of them per instance, + * allowing for larger batches. + * However, some mobile devices degrade performance when using multiple + * texture units. So if the game config option `autoMobileTextures` is + * enabled and the device is not a desktop, this will be set to 1. + * Otherwise, it will be set to the renderer's `maxTextures`. + * + * Some shaders may require more than one texture unit, + * so the actual limit on texture units per batch is `maxTextures`. + * + * This value can be changed at runtime via `setMaxParallelTextureUnits`. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#maxParallelTextureUnits + * @type {number} + * @since 4.0.0 + */ + this.maxParallelTextureUnits = (game.config.autoMobileTextures && !game.device.os.desktop) ? 1 : renderer.maxTextures; + + /** + * Nodes available for use. This is an internal object, + * where the keys are the names of the nodes. + * + * Nodes are constructed when requested by `getNode`. + * Custom nodes can be added via `addNode` or `addNodeConstructor`. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#nodes + * @type {object} + * @since 4.0.0 + * @private + */ + this._nodes = {}; + + /** + * Built-in nodes which can be constructed by name. + * Use `getNode` to either return a constructed built-in node + * from `_nodes`, or construct a new one if it does not exist. + * + * Use `addNodeConstructor` to add custom nodes + * without constructing them. + * Use `addNode` to add custom nodes that have already been constructed. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#_nodeConstructors + * @type {object} + * @since 4.0.0 + * @private + */ + this._nodeConstructors = { + BaseFilter: BaseFilter, + BaseFilterShader: BaseFilterShader, + + BatchHandlerPointLight: BatchHandlerPointLight, + BatchHandlerQuad: BatchHandlerQuad, + BatchHandlerStrip: BatchHandlerStrip, + BatchHandlerTileSprite: BatchHandlerTileSprite, + BatchHandlerTriFlat: BatchHandlerTriFlat, + + Camera: Camera, + DrawLine: DrawLine, + DynamicTextureHandler: DynamicTextureHandler, + FillCamera: FillCamera, + FillPath: FillPath, + FillRect: FillRect, + FillTri: FillTri, + + FilterBarrel: FilterBarrel, + FilterBlend: FilterBlend, + FilterBlur: FilterBlur, + FilterBlurHigh: FilterBlurHigh, + FilterBlurLow: FilterBlurLow, + FilterBlurMed: FilterBlurMed, + FilterBokeh: FilterBokeh, + FilterColorMatrix: FilterColorMatrix, + FilterDisplacement: FilterDisplacement, + FilterGlow: FilterGlow, + FilterMask: FilterMask, + FilterParallelFilters: FilterParallelFilters, + FilterPixelate: FilterPixelate, + FilterSampler: FilterSampler, + FilterShadow: FilterShadow, + FilterThreshold: FilterThreshold, + + ListCompositor: ListCompositor, + RebindContext: RebindContext, + StrokePath: StrokePath, + SubmitterQuad: SubmitterQuad, + SubmitterTile: SubmitterTile, + SubmitterTilemapGPULayer: SubmitterTilemapGPULayer, + SubmitterTileSprite: SubmitterTileSprite, + TexturerImage: TexturerImage, + TexturerTileSprite: TexturerTileSprite, + TransformerImage: TransformerImage, + TransformerStamp: TransformerStamp, + TransformerTile: TransformerTile, + TransformerTileSprite: TransformerTileSprite, + YieldContext: YieldContext + }; + + /** + * The RenderNode which is currently being filled. + * This is stored so that it can be completed when another type of + * render is run. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#currentBatchNode + * @type {?Phaser.Renderer.WebGL.RenderNodes.RenderNode} + * @default null + * @since 4.0.0 + */ + this.currentBatchNode = null; + + /** + * The drawing context of the current batch. + * This is stored here because the batch node is stateless. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#currentBatchDrawingContext + * @type {?Phaser.Renderer.WebGL.DrawingContext} + * @default null + * @since 4.0.0 + */ + this.currentBatchDrawingContext = null; + + /** + * Whether nodes should record their run method for debugging. + * This should be set via `setDebug`. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#debug + * @type {boolean} + * @since 4.0.0 + * @default false + */ + this.debug = false; + + /** + * The debug graph of nodes that have been run. + * This is used when `debug` is enabled. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#debugGraph + * @type {?DebugGraphNode} + */ + this.debugGraph = null; + + /** + * The current node in the debug graph. + * This is used when `debug` is enabled. + * + * @name Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#currentDebugNode + * @type {?DebugGraphNode} + * @default null + */ + this.currentDebugNode = null; + }, + + /** + * Add a node to the manager. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#addNode + * @since 4.0.0 + * @param {string} name - The name of the node. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} node - The node to add. + * @throws {Error} Will throw an error if the node already exists. + */ + addNode: function (name, node) + { + if (this._nodes[name]) + { + throw new Error('node ' + name + ' already exists.'); + } + this._nodes[name] = node; + + // If a node is somehow added during a debug render pass, + // ensure that it is also set to debug. + if (this.debug) + { + node.setDebug(true); + } + }, + + /** + * Add a constructor for a node to the manager. + * This will allow the node to be constructed when `getNode` is called. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#addNodeConstructor + * @since 4.0.0 + * @param {string} name - The name of the node. + * @param {function} constructor - The constructor for the node. + * @throws {Error} Will throw an error if the node constructor already exists. + */ + addNodeConstructor: function (name, constructor) + { + if (this._nodeConstructors[name]) + { + throw new Error('node constructor ' + name + ' already exists.'); + } + this._nodeConstructors[name] = constructor; + }, + + /** + * Get a node from the manager. + * + * If the node does not exist, and a constructor is available, + * it will be constructed and added to the manager, + * then returned. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#getNode + * @since 4.0.0 + * @param {string} name - The name of the node. + * @return {?Phaser.Renderer.WebGL.RenderNodes.RenderNode} The node, or null if it does not exist. + */ + getNode: function (name) + { + if (this._nodes[name]) + { + return this._nodes[name]; + } + if (this._nodeConstructors[name]) + { + var node = new this._nodeConstructors[name](this); + this.addNode(name, node); + return node; + } + return null; + }, + + /** + * Check if a node exists in the manager. + * + * If a node is not constructed, but a constructor is available, + * it will be considered to exist. Set `constructed` to true to + * require that the node has already been constructed. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#hasNode + * @since 4.0.0 + * @param {string} name - The name of the node. + * @param {boolean} [constructed=false] - Whether the node must be constructed to be considered to exist. + * @return {boolean} Whether the node exists. + */ + hasNode: function (name, constructed) + { + return !!this._nodes[name] || (!constructed && !!this._nodeConstructors[name]); + }, + + /** + * Set the current batch node. If a batch node is already in progress, + * it will be completed before the new node is set. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#setCurrentBatchNode + * @since 4.0.0 + * @param {?Phaser.Renderer.WebGL.RenderNodes.BatchHandler} node - The node to set, or null to clear the current node. + * @param {Phaser.Renderer.WebGL.DrawingContext} [drawingContext] - The drawing context. Only used if `node` is defined. + */ + setCurrentBatchNode: function (node, drawingContext) + { + if (this.currentBatchNode !== node) + { + if (this.currentBatchNode !== null) + { + this.currentBatchNode.run( + this.currentBatchDrawingContext + ); + } + + this.currentBatchNode = node; + + this.currentBatchDrawingContext = node ? drawingContext : null; + } + }, + + /** + * Set `maxParallelTextureUnits` to a new value. + * This will be clamped to the range [1, renderer.maxTextures]. + * + * This can be useful for providing the user with a way to adjust the + * performance of the game at runtime. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#setMaxParallelTextureUnits + * @since 4.0.0 + * @param {number} [value] - The new value for `maxParallelTextureUnits`. If not provided, it will be set to the renderer's `maxTextures`. + * @fires Phaser.Renderer.Events#SET_PARALLEL_TEXTURE_UNITS + */ + setMaxParallelTextureUnits: function (value) + { + this.maxParallelTextureUnits = Math.max(1, Math.min(value, this.renderer.maxTextures)); + + this.emit(Events.SET_PARALLEL_TEXTURE_UNITS, this.maxParallelTextureUnits); + }, + + /** + * Finish rendering the current batch. + * This should be called when starting a new rendering task. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#finishBatch + * @since 4.0.0 + */ + finishBatch: function () + { + if (this.currentBatchNode !== null) + { + this.setCurrentBatchNode(null); + } + }, + + /** + * Start a standalone render (SAR), which is not part of a batch. + * This will trigger batch completion if a batch is in progress. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#startStandAloneRender + * @since 4.0.0 + */ + startStandAloneRender: function () + { + this.finishBatch(); + }, + + /** + * Set whether nodes should record their run method for debugging. + * This will set the debug property on all nodes, reset the debug graph, + * and record a single frame of the graph before disabling debug. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#setDebug + * @since 4.0.0 + * @param {boolean} value - Whether nodes should record their run method for debugging. + */ + setDebug: function (value) + { + this.debug = value; + + for (var key in this._nodes) + { + this._nodes[key].setDebug(value); + } + + if (value) + { + this.debugGraph = null; + this.currentDebugNode = null; + + // Insert a synthetic root node. + this.pushDebug('[Render Tree Root]'); + + this.renderer.once( + Events.POST_RENDER, + function () + { + this.setDebug(false); + }, + this + ); + } + }, + + /** + * Record a newly run RenderNode in the debug graph. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#pushDebug + * @since 4.0.0 + * @param {string} name - The name of the node. + */ + pushDebug: function (name) + { + if (!this.debug) + { + return; + } + + var node = { + name: name, + children: [], + parent: this.currentDebugNode + }; + + if (this.debugGraph) + { + this.currentDebugNode.children.push(node); + } + else + { + this.debugGraph = node; + } + + this.currentDebugNode = node; + }, + + /** + * Pop the last recorded RenderNode from the debug graph. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#popDebug + * @since 4.0.0 + */ + popDebug: function () + { + if (!this.debug) + { + return; + } + + if (this.currentDebugNode.parent) + { + this.currentDebugNode = this.currentDebugNode.parent; + } + else + { + this.currentDebugNode = null; + } + }, + + /** + * Format the current debug graph as an indented string. + * + * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#debugToString + * @since 4.0.0 + * @return {string} The formatted debug graph. + */ + debugToString: function () + { + var output = ''; + var indent = 0; + var node = this.debugGraph; + + function indentString (indent) + { + return ' '.repeat(indent); + } + + function formatNode (node, indent) + { + var str = indentString(indent) + node.name + '\n'; + + for (var i = 0; i < node.children.length; i++) + { + str += formatNode(node.children[i], indent + 1); + } + + return str; + } + + output = formatNode(node, indent); + + return output; + } +}); + +module.exports = RenderNodeManager; + + +/***/ }), + +/***/ 55403: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var WebGLVertexBufferLayoutWrapper = __webpack_require__(40952); +var ProgramManager = __webpack_require__(56436); +var RenderNode = __webpack_require__(6141); + +var ShaderSourceVS = __webpack_require__(65884); +var ShaderSourceFS = __webpack_require__(72823); + +/** + * @classdesc + * A RenderNode that renders a quad using a shader program. + * This is used for custom rendering effects and post-processing. + * + * @class ShaderQuad + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.GameObjects.Shader.ShaderQuadConfig} config - The configuration object for this RenderNode. + */ +var ShaderQuad = new Class({ + Extends: RenderNode, + + initialize: function ShaderQuad (manager, config) + { + RenderNode.call(this, 'ShaderQuad', manager); + + var renderer = manager.renderer; + + /** + * The WebGLRenderer in use. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + config = this._completeConfig(config); + + if (config.updateShaderConfig) + { + this.updateShaderConfig = config.updateShaderConfig; + } + + /** + * The index buffer defining vertex order. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#indexBuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.indexBuffer = renderer.genericQuadIndexBuffer; + + /** + * The vertex buffer layout for this RenderNode. + * + * This consists of 4 bytes, 0-3, forming corners of a quad instance. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#vertexBufferLayout + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper} + * @since 4.0.0 + * @readonly + */ + this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper( + renderer, + config.vertexBufferLayout, + renderer.genericVertexBuffer + ); + + /** + * The program manager used to create and manage shader programs. + * This contains shader variants. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#programManager + * @type {Phaser.Renderer.WebGL.ProgramManager} + * @since 4.0.0 + */ + this.programManager = new ProgramManager( + renderer, + [ this.vertexBufferLayout ], + this.indexBuffer + ); + + // Fill in program configuration from config. + this.programManager.setBaseShader( + config.shaderName, + config.vertexSource, + config.fragmentSource + ); + for (var i = 0; i < config.shaderAdditions.length; i++) + { + var addition = config.shaderAdditions[i]; + this.programManager.addAddition(addition); + } + + /** + * The uniform callback used to set uniforms on the shader program. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#setUniform + * @type {function} + * @since 4.0.0 + */ + this.setUniform = this.programManager.setUniform.bind(this.programManager); + + /** + * The transformer node used to transform the quad for rendering. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#transformerNode + * @type {Phaser.Renderer.WebGL.RenderNodes.TransformerImage} + * @since 4.0.0 + */ + this.transformerNode = manager.getNode('TransformerImage'); + + /** + * An object which acts as a proxy for textures in the transformer. + * + * @name Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#_texturerProxy + * @type {object} + * @since 4.0.0 + */ + this._texturerProxy = { + frameWidth: 1, + frameHeight: 1, + frame: { realWidth: 1, realHeight: 1 }, + uvSource: { x: 0, y: 0 } + }; + }, + + /** + * Completes the configuration for this RenderNode. + * This method is called during initialization. + * + * @method Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#_completeConfig + * @private + * @since 4.0.0 + * @param {object} config - The configuration object for this RenderNode. + * @return {object} The completed configuration object. + */ + _completeConfig: function (config) + { + var gl = this.renderer.gl; + + var vertexSource = config.vertexSource; + if (!vertexSource) + { + var vertexKey = config.vertexKey; + if (vertexKey) + { + var baseShader = this.manager.renderer.game.cache.shader.get(vertexKey); + if (baseShader && baseShader.glsl) + { + vertexSource = baseShader.glsl; + } + } + } + if (!vertexSource) + { + vertexSource = ShaderSourceVS; + } + + var fragmentSource = config.fragmentSource; + if (!fragmentSource) + { + var fragmentKey = config.fragmentKey; + if (fragmentKey) + { + baseShader = this.manager.renderer.game.cache.shader.get(fragmentKey); + if (baseShader && baseShader.glsl) + { + fragmentSource = baseShader.glsl; + } + } + } + if (!fragmentSource) + { + fragmentSource = ShaderSourceFS; + } + + return { + name: config.name || 'ShaderQuad', + shaderName: config.shaderName || config.name || 'ShaderQuad', + vertexSource: vertexSource, + fragmentSource: fragmentSource, + shaderAdditions: config.shaderAdditions || [], + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + count: 4, + layout: [ + { + name: 'inPosition', + size: 2, + type: gl.FLOAT, + normalized: false + }, + { + name: 'inTexCoord', + size: 2, + type: gl.FLOAT, + normalized: false + } + ] + } + }; + }, + + run: function (drawingContext, gameObject, parentMatrix) + { + var manager = this.manager; + var renderer = this.renderer; + + manager.startStandAloneRender(); + + this.onRunBegin(drawingContext); + + // Get transformed quad vertices. + var width = gameObject.width; + var height = gameObject.height; + this._texturerProxy.frame.realWidth = width; + this._texturerProxy.frame.realHeight = height; + this._texturerProxy.frameWidth = width; + this._texturerProxy.frameHeight = height; + + var xTL, yTL, xBL, yBL, xBR, yBR, xTR, yTR; + + if (gameObject.renderToTexture) + { + xTL = 0; + yTL = 0; + xBL = 0; + yBL = height; + xBR = width; + yBR = height; + xTR = width; + yTR = 0; + } + else + { + var transformerNode = this.transformerNode; + transformerNode.run(drawingContext, gameObject, this._texturerProxy, parentMatrix); + var quad = transformerNode.quad; + + xTL = quad[0]; + yTL = quad[1]; + xBL = quad[2]; + yBL = quad[3]; + xBR = quad[4]; + yBR = quad[5]; + xTR = quad[6]; + yTR = quad[7]; + } + + // Populate vertex buffer. + var stride = this.vertexBufferLayout.layout.stride; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexF32 = vertexBuffer.viewF32; + var offset32 = 0; + + // Bottom Left. + vertexF32[offset32++] = xBL; + vertexF32[offset32++] = yBL; + vertexF32[offset32++] = gameObject.textureCoordinateBottomLeft.x; + vertexF32[offset32++] = gameObject.textureCoordinateBottomLeft.y; + + // Top Left. + vertexF32[offset32++] = xTL; + vertexF32[offset32++] = yTL; + vertexF32[offset32++] = gameObject.textureCoordinateTopLeft.x; + vertexF32[offset32++] = gameObject.textureCoordinateTopLeft.y; + + // Bottom Right. + vertexF32[offset32++] = xBR; + vertexF32[offset32++] = yBR; + vertexF32[offset32++] = gameObject.textureCoordinateBottomRight.x; + vertexF32[offset32++] = gameObject.textureCoordinateBottomRight.y; + + // Top Right. + vertexF32[offset32++] = xTR; + vertexF32[offset32++] = yTR; + vertexF32[offset32++] = gameObject.textureCoordinateTopRight.x; + vertexF32[offset32++] = gameObject.textureCoordinateTopRight.y; + + vertexBuffer.update(stride * 4); + + // Render. + + var programManager = this.programManager; + this.updateShaderConfig(drawingContext, gameObject, this); + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + var setUniform = this.setUniform; + + renderer.setProjectionMatrixFromDrawingContext(drawingContext); + setUniform( + 'uProjectionMatrix', + drawingContext.renderer.projectionMatrix.val + ); + + // Set user uniforms after built-ins to permit overrides. + gameObject.setupUniforms(setUniform, drawingContext); + + programManager.applyUniforms(program); + + // Draw. + renderer.drawElements( + drawingContext, + this.setupTextures(gameObject), + program, + vao, + 4, + 0 + ); + } + + this.onRunEnd(drawingContext); + }, + + setupTextures: function (gameObject) + { + var textures = gameObject.textures; + var glTextures = []; + + for (var i = 0; i < textures.length; i++) + { + var texture = textures[i]; + var glTexture = texture.get().source.glTexture; + glTextures.push(glTexture); + } + + return glTextures; + }, + + /** + * Updates the shader configuration for the current render pass. + * This is called before the shader is rendered. + * This method is a hook for custom shader configurations. + * You should override it if you need to adjust shader additions + * after initialization. + * + * @method Phaser.Renderer.WebGL.RenderNodes.ShaderQuad#updateShaderConfig + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.Renderer.WebGL.RenderNodes.ShaderQuad} renderNode - The RenderNode being rendered. + */ + updateShaderConfig: function (drawingContext, gameObject, renderNode) + { + // NOOP. + } +}); + +module.exports = ShaderQuad; + + +/***/ }), + +/***/ 17486: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which renders a stroke path consisting of several line segments, + * potentially closed at the end. + * + * @class StrokePath + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var StrokePath = new Class({ + Extends: RenderNode, + + initialize: function StrokePath (manager) + { + RenderNode.call(this, 'StrokePath', manager); + + /** + * The RenderNode that generates a line segment. + * + * @name Phaser.Renderer.WebGL.RenderNodes.StrokePath#drawLineNode + * @type {Phaser.Renderer.WebGL.RenderNodes.DrawLine} + * @since 4.0.0 + */ + this.drawLineNode = this.manager.getNode('DrawLine'); + }, + + /** + * Render a stroke path consisting of several line segments. + * + * @method Phaser.Renderer.WebGL.RenderNodes.StrokePath#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The context currently in use. + * @param {Phaser.Renderer.WebGL.RenderNodes.BatchHandlerTriFlat} submitterNode - The Submitter node to use. + * @param {Phaser.Types.GameObjects.Graphics.WidePoint[]} path - The points that define the line segments. + * @param {number} lineWidth - The width of the stroke. + * @param {boolean} open - Whether the stroke is open or closed. + * @param {Phaser.GameObjects.Components.TransformMatrix} currentMatrix - The current transform matrix. + * @param {number} tintTL - The top-left tint color. + * @param {number} tintTR - The top-right tint color. + * @param {number} tintBL - The bottom-left tint color. + * @param {number} tintBR - The bottom-right tint color. + * @param {number} detail - The level of detail to use when rendering the stroke. Points which are only this far apart in screen space are combined. It is ignored if the entire path is equal to or shorter than this distance. + * @param {boolean} lighting - Whether to apply lighting effects to the stroke. + */ + run: function (drawingContext, submitterNode, path, lineWidth, open, currentMatrix, tintTL, tintTR, tintBL, tintBR, detail, lighting) + { + this.onRunBegin(drawingContext); + + var drawLineNode = this.drawLineNode; + + var pathLength = path.length - 1; + + var point, nextPoint; + + // Determine connectivity of index array. + var connect = false; + var connectLoop = false; + + if (lineWidth > 2 && pathLength > 1) + { + // Lines will be connected by a secondary quad. + connect = true; + if (!open) + { + // The last line will be connected to the first line. + connectLoop = true; + } + } + + var indices = []; + var indexOffset = 0; + + var vertices = []; + var vertexOffset = 0; + var vertexCount; + + var colors = []; + var colorOffset = 0; + + var dx, dy, tdx, tdy; + var detailSquared = detail * detail; + + var first, last, iterate; + + for (var i = 0; i < pathLength; i += iterate) + { + first = i === 0; + last = i === pathLength - 1; + iterate = 1; + + point = path[i]; + nextPoint = path[i + iterate]; + + if (detailSquared && !last) + { + dx = nextPoint.x - point.x; + dy = nextPoint.y - point.y; + tdx = currentMatrix.getX(dx, dy) - currentMatrix.tx; + tdy = currentMatrix.getY(dx, dy) - currentMatrix.ty; + while ( + i + iterate < pathLength - 1 && + tdx * tdx + tdy * tdy <= detailSquared + ) + { + // Skip the next point if it's too close to the current point. + iterate++; + nextPoint = path[i + iterate]; + dx = nextPoint.x - point.x; + dy = nextPoint.y - point.y; + tdx = currentMatrix.getX(dx, dy) - currentMatrix.tx; + tdy = currentMatrix.getY(dx, dy) - currentMatrix.ty; + } + } + + // Compute and add the vertices for the line segment. + drawLineNode.run( + drawingContext, + currentMatrix, + point.x, + point.y, + nextPoint.x, + nextPoint.y, + point.width / 2, + nextPoint.width / 2, + vertices + ); + + // The previous operation added 4 vertices. + vertexOffset += 8; + + vertexCount = vertexOffset / 2; + + colors[colorOffset++] = tintTL; + colors[colorOffset++] = tintBL; + colors[colorOffset++] = tintBR; + colors[colorOffset++] = tintTR; + + // Draw two triangles. + // The vertices are in the order: TL, BL, BR, TR + indices[indexOffset++] = vertexCount - 4; + indices[indexOffset++] = vertexCount - 3; + indices[indexOffset++] = vertexCount - 2; + indices[indexOffset++] = vertexCount - 2; + indices[indexOffset++] = vertexCount - 1; + indices[indexOffset++] = vertexCount - 4; + + if (connect && !first) + { + // Draw a quad connecting to the previous line segment. + // The vertices are in the order: + // - TL + // - BL + // - Previous BR + // - Previous TR + indices[indexOffset++] = vertexCount - 4; + indices[indexOffset++] = vertexCount - 3; + indices[indexOffset++] = vertexCount - 6; + indices[indexOffset++] = vertexCount - 6; + indices[indexOffset++] = vertexCount - 5; + indices[indexOffset++] = vertexCount - 4; + + if (connectLoop && last) + { + // Connect the last line segment to the first. + // The vertices are in the order: + // - BR + // - TR + // - First TL + // - First BL + indices[indexOffset++] = vertexCount - 2; + indices[indexOffset++] = vertexCount - 1; + indices[indexOffset++] = 0; + indices[indexOffset++] = 0; + indices[indexOffset++] = 1; + indices[indexOffset++] = vertexCount - 2; + } + } + } + + submitterNode.batch(drawingContext, indices, vertices, colors, lighting); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = StrokePath; + + +/***/ }), + +/***/ 95433: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * YieldContext is a RenderNode which sets the WebGL context to a default state, + * ready for another renderer. + * + * This is used by the Extern Game Object to prepare the WebGL context for custom rendering. + * It is the counterpart of RebindContext. + * + * @class YieldContext + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var YieldContext = new Class({ + Extends: RenderNode, + + initialize: function YieldContext (manager) + { + RenderNode.call(this, 'YieldContext', manager); + + /** + * The WebGL state to set when this node is run. + * This is read-only. + * + * @name Phaser.Renderer.WebGL.RenderNodes.YieldContext#_state + * @type {Partial} + * @private + * @since 4.0.0 + * @readonly + */ + this._state = { + blend: this.manager.renderer.blendModes[0], + vao: null + }; + }, + + /** + * Sets the WebGL context to a default state. + * This will flush any existing batch, set the blend mode to NORMAL, + * and unbind any current VAO. + * + * @method Phaser.Renderer.WebGL.RenderNodes.YieldContext#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} displayContext - The context currently in use. + */ + run: function (displayContext) + { + this.onRunBegin(displayContext); + + var manager = this.manager; + var renderer = manager.renderer; + + manager.startStandAloneRender(); + + renderer.glWrapper.update(this._state); + + renderer.glTextureUnits.unbindAllUnits(); + + this.onRunEnd(displayContext); + } +}); + +module.exports = YieldContext; + + +/***/ }), + +/***/ 70972: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultBitmapTextNodes = new Map([ + [ 'Submitter', 'SubmitterQuad' ], + [ 'BatchHandler', 'BatchHandlerQuad' ] +]); + +module.exports = DefaultBitmapTextNodes; + + +/***/ }), + +/***/ 98682: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultBlitterNodes = new Map([ + [ 'Submitter', 'SubmitterQuad' ], + [ 'BatchHandler', 'BatchHandlerQuad' ] +]); + +module.exports = DefaultBlitterNodes; + + +/***/ }), + +/***/ 87891: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultGraphicsNodes = new Map([ + [ 'Submitter', 'BatchHandlerTriFlat' ], + [ 'FillPath', 'FillPath' ], + [ 'FillRect', 'FillRect' ], + [ 'FillTri', 'FillTri' ], + [ 'StrokePath', 'StrokePath' ] +]); + +module.exports = DefaultGraphicsNodes; + + +/***/ }), + +/***/ 40939: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultImageNodes = new Map([ + [ 'Submitter', 'SubmitterQuad' ], + [ 'BatchHandler', 'BatchHandlerQuad' ], + [ 'Transformer', 'TransformerImage' ], + [ 'Texturer', 'TexturerImage' ] +]); + +module.exports = DefaultImageNodes; + + +/***/ }), + +/***/ 68668: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultParticleEmitterNodes = new Map([ + [ 'Submitter', 'SubmitterQuad' ], + [ 'BatchHandler', 'BatchHandlerQuad' ] +]); + +module.exports = DefaultParticleEmitterNodes; + + +/***/ }), + +/***/ 43246: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultPointLightNodes = new Map([ + [ 'BatchHandler', 'BatchHandlerPointLight' ] +]); + +module.exports = DefaultPointLightNodes; + + +/***/ }), + +/***/ 30529: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultQuadNodes = new Map([ + [ 'BatchHandler', 'BatchHandlerQuad' ] +]); + +module.exports = DefaultQuadNodes; + + +/***/ }), + +/***/ 85760: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultRopeNodes = new Map([ + [ 'BatchHandler', 'BatchHandlerStrip' ] +]); + +module.exports = DefaultRopeNodes; + + +/***/ }), + +/***/ 78705: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultStampNodes = new Map([ + [ 'Submitter', 'SubmitterQuad' ], + [ 'BatchHandler', 'BatchHandlerQuad' ], + [ 'Transformer', 'TransformerStamp' ], + [ 'Texturer', 'TexturerImage' ] +]); + +module.exports = DefaultStampNodes; + + +/***/ }), + +/***/ 41571: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultTileSpriteNodes = new Map([ + [ 'Submitter', 'SubmitterTileSprite' ], + [ 'BatchHandler', 'BatchHandlerTileSprite' ], + [ 'Transformer', 'TransformerTileSprite' ], + [ 'Texturer', 'TexturerTileSprite' ] +]); + +module.exports = DefaultTileSpriteNodes; + + +/***/ }), + +/***/ 67743: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultTilemapGPULayerNodes = new Map([ + [ 'Submitter', 'SubmitterTilemapGPULayer' ] +]); + +module.exports = DefaultTilemapGPULayerNodes; + + +/***/ }), + +/***/ 79317: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); + +var DefaultTilemapLayerNodes = new Map([ + [ 'Submitter', 'SubmitterTile' ], + [ 'BatchHandler', 'BatchHandlerTileSprite' ], + [ 'Transformer', 'TransformerTile' ] +]); + +module.exports = DefaultTilemapLayerNodes; + + +/***/ }), + +/***/ 59212: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.WebGL.RenderNodes.Defaults + */ + +var Defaults = { + DefaultBitmapTextNodes: __webpack_require__(70972), + DefaultBlitterNodes: __webpack_require__(98682), + DefaultGraphicsNodes: __webpack_require__(87891), + DefaultImageNodes: __webpack_require__(40939), + DefaultParticleEmitterNodes: __webpack_require__(68668), + DefaultPointLightNodes: __webpack_require__(43246), + DefaultQuadNodes: __webpack_require__(30529), + DefaultRopeNodes: __webpack_require__(85760), + DefaultStampNodes: __webpack_require__(78705), + DefaultTilemapGPULayerNodes: __webpack_require__(67743), + DefaultTilemapLayerNodes: __webpack_require__(79317), + DefaultTileSpriteNodes: __webpack_require__(41571) +}; + +module.exports = Defaults; + + +/***/ }), + +/***/ 47406: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * This is a base class for all filters. + * It should not be used directly, but should be extended by all other filters. + * + * @class BaseFilter + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * + * @param {string} name - The name of the filter. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this filter. + */ +var BaseFilter = new Class({ + Extends: RenderNode, + + initialize: function BaseFilter (name, manager) + { + RenderNode.call(this, name, manager); + }, + + /** + * Run the filter. It returns a drawing context containing the output texture. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BaseFilter#run + * @since 4.0.0 + * @param {Phaser.Filters.Controller} controller - The filter controller. + * @param {Phaser.Renderer.WebGL.DrawingContext} inputDrawingContext - The drawing context containing the input texture. This is either the initial render, or the output of the previous filter. This will be released during the run process, and can no longer be used. + * @param {Phaser.Renderer.WebGL.DrawingContext} [outputDrawingContext] - The drawing context where the output texture will be drawn. If not specified, a new drawing context will be generated. Generally, this parameter is used for the last filter in a chain, so the output texture is drawn to the main framebuffer. + * @param {Phaser.Geom.Rectangle} [padding] - The padding to add to the input texture to create the output texture. If not specified, the controller is used to get the padding. This should be undefined for internal filters, so the controller will expand textures as needed; and defined as the negative padding of the previous filter for external filters, so the texture will shrink to the correct size. + * @returns {Phaser.Renderer.WebGL.DrawingContext} The drawing context containing the output texture. + */ + run: function (controller, inputDrawingContext, outputDrawingContext, padding) + { + // This is the base run method that all filters should override + } +}); + +module.exports = BaseFilter; + + +/***/ }), + +/***/ 53663: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var SimpleTextureVert = __webpack_require__(2807); +var MakeBoundedSampler = __webpack_require__(99501); +var ProgramManager = __webpack_require__(56436); +var WebGLVertexBufferLayoutWrapper = __webpack_require__(40952); +var BaseFilter = __webpack_require__(47406); + +/** + * @classdesc + * This is a base class for all filters that use a shader. + * Most filters will extend this class. + * + * It takes care of setting up the shader program and vertex buffer layout. + * It also provides the `run` method which handles the rendering of the filter. + * When rendering, it generates a new DrawingContext to render to, + * and releases the input DrawingContext. + * + * Note: be careful when using `gl_FragCoord` in shader code. + * This built-in variable gives you the "window relative" coordinate + * of the pixel being processed. + * But this is actually relative to the framebuffer size, + * and Phaser treats all framebuffers except the main canvas + * as being vertically flipped. + * This means that `gl_FragCoord.y = 0` in a shader will be the bottom of a framebuffer, + * but the top of the canvas. + * This means `gl_FragCoord` gives different results when it's inside a + * framebuffer (like a Render Texture or Filter) compared to the main canvas. + * Be aware of this restriction when writing shaders. + * + * @class BaseFilterShader + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilter + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {string} name - The name of the filter. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this filter. + * @param {string} [fragmentShaderKey] - The key of the fragment shader source in the shader cache. This will only be used if `fragmentShaderSource` is not set. + * @param {string} [fragmentShaderSource] - The fragment shader source. + * @param {?Phaser.Types.Renderer.WebGL.ShaderAdditionConfig[]} [shaderAdditions] - An array of shader additions to apply to the shader program. + */ +var BaseFilterShader = new Class({ + Extends: BaseFilter, + + initialize: function BaseFilterShader (name, manager, fragmentShaderKey, fragmentShaderSource, shaderAdditions) + { + if (!fragmentShaderSource) + { + var baseShader = manager.renderer.game.cache.shader.get(fragmentShaderKey); + if (!(baseShader && baseShader.glsl)) + { + throw new Error('BaseFilterShader: No fragment shader source provided and no shader found with key ' + fragmentShaderKey); + } + fragmentShaderSource = baseShader.glsl; + } + + BaseFilter.call(this, name, manager); + + var renderer = manager.renderer; + var gl = renderer.gl; + + var config = { + name: name, + shaderName: name, + vertexSource: SimpleTextureVert, + fragmentSource: fragmentShaderSource, + shaderAdditions: shaderAdditions || [], + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + count: 4, + layout: [ + { + name: 'inPosition', + size: 2, + type: gl.FLOAT, + normalized: false + }, + { + name: 'inTexCoord', + size: 2, + type: gl.FLOAT, + normalized: false + } + ] + } + }; + + // Include the BoundedSampler addition. + config.shaderAdditions.push(MakeBoundedSampler()); + + /** + * The index buffer defining vertex order. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader#indexBuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.indexBuffer = renderer.genericQuadIndexBuffer; + + /** + * The vertex buffer layout for this RenderNode. + * + * This consists of 4 bytes, 0-3, forming corners of a quad instance. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader#vertexBufferLayout + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper} + * @since 4.0.0 + * @readonly + */ + this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper( + renderer, + config.vertexBufferLayout, + renderer.genericVertexBuffer + ); + + /** + * The program manager used to create and manage shader programs. + * This contains shader variants. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader#programManager + * @type {Phaser.Renderer.WebGL.ProgramManager} + * @since 4.0.0 + */ + this.programManager = new ProgramManager( + renderer, + [ this.vertexBufferLayout ], + this.indexBuffer + ); + + // Fill in program configuration from config. + this.programManager.setBaseShader( + config.shaderName, + config.vertexSource, + config.fragmentSource + ); + for (var i = 0; i < config.shaderAdditions.length; i++) + { + var addition = config.shaderAdditions[i]; + this.programManager.addAddition(addition); + } + + // Set the shader program to use texture unit 0. + this.programManager.setUniform('uMainSampler', 0); + }, + + run: function (controller, inputDrawingContext, outputDrawingContext, padding) + { + var manager = this.manager; + var renderer = manager.renderer; + + manager.startStandAloneRender(); + + + // Get a new DrawingContext to render to. + if (!padding) + { + padding = controller.getPadding(); + } + if (!outputDrawingContext) + { + outputDrawingContext = renderer.drawingContextPool.get( + inputDrawingContext.width + padding.width, + inputDrawingContext.height + padding.height + ); + } + + outputDrawingContext.use(); + + this.onRunBegin(outputDrawingContext); + + // Assemble textures. + var textures = [ inputDrawingContext.texture ]; + this.setupTextures(controller, textures, outputDrawingContext); + + // Compute quad vertices. + var xBL = -1; + var yBL = -1; + var xTL = -1; + var yTL = 1; + var xTR = 1; + var yTR = 1; + var xBR = 1; + var yBR = -1; + + // Account for padding. + if (padding.left) + { + var paddingLeft = 2 * padding.left / outputDrawingContext.width; + xBL -= paddingLeft; + xTL -= paddingLeft; + } + if (padding.right) + { + var paddingRight = 2 * padding.right / outputDrawingContext.width; + xBR -= paddingRight; + xTR -= paddingRight; + } + if (padding.top) + { + var paddingTop = 2 * padding.top / outputDrawingContext.height; + yTL += paddingTop; + yTR += paddingTop; + } + if (padding.bottom) + { + var paddingBottom = 2 * padding.bottom / outputDrawingContext.height; + yBL += paddingBottom; + yBR += paddingBottom; + } + + // Populate vertex buffer. + var stride = this.vertexBufferLayout.layout.stride; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexF32 = vertexBuffer.viewF32; + var offset32 = 0; + + // Bottom Left. + vertexF32[offset32++] = -1; + vertexF32[offset32++] = -1; + vertexF32[offset32++] = remapCoord(0, xBL, xBR); + vertexF32[offset32++] = remapCoord(0, yBL, yBR); + + // Top Left. + vertexF32[offset32++] = -1; + vertexF32[offset32++] = 1; + vertexF32[offset32++] = remapCoord(0, xTL, xTR); + vertexF32[offset32++] = remapCoord(1, yTL, yTR); + + // Bottom Right. + vertexF32[offset32++] = 1; + vertexF32[offset32++] = -1; + vertexF32[offset32++] = remapCoord(1, xBL, xBR); + vertexF32[offset32++] = remapCoord(0, yBL, yBR); + + // Top Right. + vertexF32[offset32++] = 1; + vertexF32[offset32++] = 1; + vertexF32[offset32++] = remapCoord(1, xTL, xTR); + vertexF32[offset32++] = remapCoord(1, yTL, yTR); + + // Update vertex buffer. + // Because we are probably using a generic vertex buffer + // which is larger than the current batch, we need to update + // the buffer with the correct size. + vertexBuffer.update(stride * 4); + + + // Render. + + var programManager = this.programManager; + this.updateShaderConfig(controller, outputDrawingContext); + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + + this.setupUniforms(controller, outputDrawingContext); + programManager.applyUniforms(program); + + // Render layer. + renderer.drawElements( + outputDrawingContext, + textures, + program, + vao, + 4, + 0 + ); + } + + + // Complete render. + inputDrawingContext.release(); + this.onRunEnd(outputDrawingContext); + + return outputDrawingContext; + }, + + /** + * Set up the shader configuration for this shader. + * Override this method to handle shader configuration. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader#updateShaderConfig + * @since 4.0.0 + * @param {Phaser.Filters.Controller} controller - The filter controller. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The drawing context in use. + */ + updateShaderConfig: function (controller, drawingContext) + { + // NOOP + }, + + /** + * Run any necessary modifications on the textures array. + * Override this method to handle texture inputs. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader#setupTextures + * @since 4.0.0 + * @param {Phaser.Filters.Controller} controller - The filter controller. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} textures - The array of textures to modify in-place. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The drawing context in use. + */ + setupTextures: function (controller, textures, drawingContext) + { + // NOOP + }, + + /** + * Set up the uniforms for this shader, based on the controller. + * + * @method Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader#setupUniforms + * @since 4.0.0 + * @param {Phaser.Filters.Controller} controller - The filter controller. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The drawing context in use. + */ + setupUniforms: function (controller, drawingContext) + { + // This is the base setupUniforms method that all filters should override + } +}); + +function remapCoord (coord, low, high) +{ + // Low,high are in the range -1,1. + // Convert low,high to 0,1. + low = ((1 / low) + 1) * 0.5; + high = ((1 / high) + 1) * 0.5; + + return low + coord * (high - low); +} + +module.exports = BaseFilterShader; + + +/***/ }), + +/***/ 22731: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(10235); + +/** + * @classdesc + * This RenderNode renders the Barrel filter effect. + * See {@link Phaser.Filters.Barrel}. + * + * @class FilterBarrel + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBarrel = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterBarrel (manager) + { + BaseFilterShader.call(this, 'FilterBarrel', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('amount', controller.amount); + } +}); + +module.exports = FilterBarrel; + + +/***/ }), + +/***/ 57032: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); +var Class = __webpack_require__(83419); +var BlendModes = __webpack_require__(10312); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(65980); + +/** + * @classdesc + * This RenderNode renders the Blend filter effect. + * See {@link Phaser.Filters.Blend}. + * + * @class FilterBlend + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBlend = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterBlend (manager) + { + /** + * A map from blend mode integers to their string names. + * + * @name Phaser.Renderer.WebGL.RenderNodes.FilterBlend#_blendModeMap + * @type {Phaser.Structs.Map} + * @private + * @since 4.0.0 + */ + this._blendModeMap = new Map(); + + var blendModeMap = this._blendModeMap; + Object.entries(BlendModes).forEach(function (entry) + { + blendModeMap.set(entry[1], entry[0]); + }); + + var normal = blendModeMap.get(BlendModes.NORMAL); + + var additions = [ + { + name: normal, + additions: { + fragmentHeader: '#define BLEND ' + normal + }, + tags: [ 'blendmode' ] + } + ]; + + BaseFilterShader.call(this, 'FilterBlend', manager, null, ShaderSourceFS, additions); + }, + + updateShaderConfig: function (controller, drawingContext) + { + var blendMode = controller.blendMode; + if (blendMode === BlendModes.SKIP_CHECK) + { + blendMode = BlendModes.NORMAL; + } + var name = this._blendModeMap.get(blendMode) || this._blendModeMap.get(BlendModes.NORMAL); + + var blendModeAddition = this.programManager.getAdditionsByTag('blendmode')[0]; + blendModeAddition.name = name; + blendModeAddition.additions.fragmentHeader = '#define BLEND ' + name; + }, + + setupTextures: function (controller, textures, drawingContext) + { + // Blend texture. + textures[1] = controller.glTexture; + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('uMainSampler2', 1); + programManager.setUniform('amount', controller.amount); + programManager.setUniform('color', controller.color); + } +}); + +module.exports = FilterBlend; + + +/***/ }), + +/***/ 13922: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var Class = __webpack_require__(83419); +var BaseFilter = __webpack_require__(47406); + +/** + * @classdesc + * This RenderNode renders the Blur filter effect. + * See {@link Phaser.Filters.Blur}. + * + * This RenderNode redirects to other filters + * based on the quality setting of the controller it is running. + * + * @class FilterBlur + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilter + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBlur = new Class({ + Extends: BaseFilter, + + initialize: function FilterBlur (manager) + { + BaseFilter.call(this, 'FilterBlur', manager); + }, + + run: function (controller, inputDrawingContext, outputDrawingContext, padding) + { + this.onRunBegin(outputDrawingContext); + + var quality = controller.quality; + var steps = controller.steps; + var filter = null; + + switch (quality) + { + case 2: + { + filter = this.manager.getNode('FilterBlurHigh'); + break; + } + case 1: + { + filter = this.manager.getNode('FilterBlurMed'); + break; + } + case 0: + default: + { + filter = this.manager.getNode('FilterBlurLow'); + break; + } + } + + var proxyController = { + strength: controller.strength, + color: controller.glcolor, + x: controller.x, + y: controller.y + }; + + if (!padding) + { + padding = controller.getPadding(); + } + + var currentContext = inputDrawingContext; + + for (var i = 0; i < steps; i++) + { + /* + Render alternating horizontal and vertical passes. + Gaussian blurs are axis-separable, + so this creates the same effect as a single pass with more samples, + but is faster. + We have to break this down into steps at this level + because GLSL doesn't support a variable number of loop iterations, + so we can't pass the number of steps as a uniform. + */ + + // Horizontal pass + proxyController.x = controller.x; + proxyController.y = 0; + currentContext = filter.run(proxyController, currentContext, null, padding); + + if (i === 0) + { + // Stop adding padding after the first pass. + padding = new Rectangle(); + } + + // Vertical pass + var output = (i === steps - 1) ? outputDrawingContext : null; + proxyController.x = 0; + proxyController.y = controller.y; + currentContext = filter.run(proxyController, currentContext, output, padding); + } + + outputDrawingContext = currentContext; + + this.onRunEnd(outputDrawingContext); + + return outputDrawingContext; + } +}); + +module.exports = FilterBlur; + + +/***/ }), + +/***/ 33466: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(20784); + +/** + * @classdesc + * This RenderNode renders the BlurHigh filter effect. + * This is a high quality blur filter. + * It should not be used directly. + * It is intended to be called by the FilterBlur filter + * based on the quality setting of the controller it is running. + * + * @class FilterBlurHigh + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBlurHigh = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterBlurHigh (manager) + { + BaseFilterShader.call(this, 'FilterBlurHigh', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('resolution', [ drawingContext.width, drawingContext.height ]); + programManager.setUniform('strength', controller.strength); + programManager.setUniform('color', controller.color); + programManager.setUniform('offset', [ controller.x, controller.y ]); + } +}); + +module.exports = FilterBlurHigh; + + +/***/ }), + +/***/ 75798: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(65122); + +/** + * @classdesc + * This RenderNode renders the BlurLow filter effect. + * This is a low quality blur filter. + * It should not be used directly. + * It is intended to be called by the FilterBlur filter + * based on the quality setting of the controller it is running. + * + * @class FilterBlurLow + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBlurLow = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterBlurLow (manager) + { + BaseFilterShader.call(this, 'FilterBlurLow', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('resolution', [ drawingContext.width, drawingContext.height ]); + programManager.setUniform('strength', controller.strength); + programManager.setUniform('color', controller.color); + programManager.setUniform('offset', [ controller.x, controller.y ]); + } +}); + +module.exports = FilterBlurLow; + + +/***/ }), + +/***/ 90830: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(60942); + +/** + * @classdesc + * This RenderNode renders the BlurMed filter effect. + * This is a medium quality blur filter. + * It should not be used directly. + * It is intended to be called by the FilterBlur filter + * based on the quality setting of the controller it is running. + * + * @class FilterBlurMed + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBlurMed = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterBlurMed (manager) + { + BaseFilterShader.call(this, 'FilterBlurMed', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('resolution', [ drawingContext.width, drawingContext.height ]); + programManager.setUniform('strength', controller.strength); + programManager.setUniform('color', controller.color); + programManager.setUniform('offset', [ controller.x, controller.y ]); + } +}); + +module.exports = FilterBlurMed; + + +/***/ }), + +/***/ 52302: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(43722); + +/** + * @classdesc + * This RenderNode renders the Bokeh filter effect. + * See {@link Phaser.Filters.Bokeh}. + * + * @class FilterBokeh + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterBokeh = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterBokeh (manager) + { + BaseFilterShader.call(this, 'FilterBokeh', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('radius', controller.radius); + programManager.setUniform('amount', controller.amount); + programManager.setUniform('contrast', controller.contrast); + programManager.setUniform('strength', controller.strength); + programManager.setUniform('blur', [ controller.blurX, controller.blurY ]); + programManager.setUniform('isTiltShift', controller.isTiltShift); + programManager.setUniform('resolution', [ drawingContext.width, drawingContext.height ]); + } +}); + +module.exports = FilterBokeh; + + +/***/ }), + +/***/ 34989: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(19883); + +/** + * @classdesc + * This RenderNode renders the Color Matrix filter effect. + * See {@link Phaser.Filters.ColorMatrix}. + * + * @class FilterColorMatrix + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterColorMatrix = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterColorMatrix (manager) + { + BaseFilterShader.call(this, 'FilterColorMatrix', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('uColorMatrix[0]', controller.colorMatrix.getData()); + programManager.setUniform('uAlpha', controller.colorMatrix.alpha); + } +}); + +module.exports = FilterColorMatrix; + + +/***/ }), + +/***/ 15600: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(12886); + +/** + * @classdesc + * This RenderNode renders the Displacement filter effect. + * See {@link Phaser.Filters.Displacement}. + * + * @class FilterDisplacement + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterDisplacement = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterDisplacement (manager) + { + BaseFilterShader.call(this, 'FilterDisplacement', manager, null, ShaderSourceFS); + }, + + setupTextures: function (controller, textures) + { + // Displacement texture. + textures[1] = controller.glTexture; + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('uDisplacementSampler', 1); + programManager.setUniform('amount', [ controller.x, controller.y ]); + } +}); + +module.exports = FilterDisplacement; + + +/***/ }), + +/***/ 99786: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(33016); + +/** + * @classdesc + * This RenderNode renders the Glow filter effect. + * See {@link Phaser.Filters.Glow}. + * + * @class FilterGlow + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterGlow = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterGlow (manager) + { + var shaderAdditions = [ + { + name: 'distance_10.0', + additions: { + fragmentDefine: '#define DISTANCE 10.0' + }, + tags: [ 'distance' ] + }, + { + name: 'quality_0.1', + additions: { + fragmentDefine: '#define QUALITY 0.1' + }, + tags: [ 'quality' ] + } + ]; + + BaseFilterShader.call(this, 'FilterGlow', manager, null, ShaderSourceFS, shaderAdditions); + }, + + updateShaderConfig: function (controller, drawingContext) + { + var programManager = this.programManager; + + var distance = controller.distance.toFixed(0) + '.0'; + var distanceAddition = programManager.getAdditionsByTag('distance')[0]; + distanceAddition.name = 'distance_' + distance; + distanceAddition.additions.fragmentDefine = '#undef DISTANCE\n#define DISTANCE ' + distance; + + var quality = controller.quality.toFixed(0) + '.0'; + var qualityAddition = programManager.getAdditionsByTag('quality')[0]; + qualityAddition.name = 'quality_' + quality; + qualityAddition.additions.fragmentDefine = '#undef QUALITY\n#define QUALITY ' + quality; + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('resolution', [ drawingContext.width, drawingContext.height ]); + programManager.setUniform('glowColor', controller.glcolor); + programManager.setUniform('outerStrength', controller.outerStrength); + programManager.setUniform('innerStrength', controller.innerStrength); + programManager.setUniform('scale', controller.scale); + programManager.setUniform('knockout', controller.knockout); + } +}); + +module.exports = FilterGlow; + + +/***/ }), + +/***/ 26703: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(39603); + +/** + * @classdesc + * This RenderNode renders the Mask filter effect. + * See {@link Phaser.Filters.Mask}. + * + * @class FilterMask + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterMask = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterMask (manager) + { + BaseFilterShader.call(this, 'FilterMask', manager, null, ShaderSourceFS); + }, + + setupTextures: function (controller, textures, drawingContext) + { + // Update dynamic texture if necessary. + if (controller.maskGameObject && (controller.needsUpdate || controller.autoUpdate)) + { + controller.updateDynamicTexture(drawingContext.width, drawingContext.height); + } + + // Mask texture. + textures[1] = controller.glTexture; + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('uMaskSampler', 1); + programManager.setUniform('invert', controller.invert); + } +}); + +module.exports = FilterMask; + + +/***/ }), + +/***/ 55905: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var Class = __webpack_require__(83419); +var BlendModes = __webpack_require__(10312); +var BaseFilter = __webpack_require__(47406); + +/** + * @classdesc + * This RenderNode runs a series of filters in parallel. + * See {@link Phaser.Filters.ParallelFilters}. + * + * This filter redirects to other RenderNodes during operation. + * + * @class FilterParallelFilters + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilter + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterParallelFilters = new Class({ + Extends: BaseFilter, + + initialize: function FilterParallelFilters (manager) + { + BaseFilter.call(this, 'FilterParallelFilters', manager); + }, + + run: function (controller, inputDrawingContext, outputDrawingContext, padding) + { + this.onRunBegin(outputDrawingContext); + + // Prevent the input from being sent back to its pool. + inputDrawingContext.lock(this); + + var bottomFilters = controller.bottom.getActive(); + var topFilters = controller.top.getActive(); + var initialPadding = padding || controller.getPadding(); + + if (bottomFilters.length + topFilters.length > 0) + { + var bottomContext = inputDrawingContext; + var topContext = inputDrawingContext; + + // Process bottom filters. + + if (bottomFilters.length > 0) + { + padding = initialPadding; + + for (var i = 0; i < bottomFilters.length; i++) + { + var childController = bottomFilters[i]; + var filter = this.manager.getNode(childController.renderNode); + + bottomContext = filter.run( + childController, + bottomContext, + null, + padding + ); + + // Don't apply more padding after the first filter. + if (i === 0 && i < bottomFilters.length - 1) + { + padding = new Rectangle(); + } + } + } + + // Process top filters. + + if (topFilters.length > 0) + { + padding = initialPadding; + + for (i = 0; i < topFilters.length; i++) + { + childController = topFilters[i]; + filter = this.manager.getNode(childController.renderNode); + + topContext = filter.run( + childController, + topContext, + null, + padding + ); + + // Don't apply more padding after the first filter. + if (i === 0 && i < topFilters.length - 1) + { + padding = new Rectangle(); + } + } + } + + // Blend the top and bottom filters. + inputDrawingContext.unlock(this); + var blendController = controller.blend; + blendController.glTexture = topContext.texture; + filter = this.manager.getNode('FilterBlend'); + outputDrawingContext = this.manager.getNode('FilterBlend').run( + controller.blend, + bottomContext, + outputDrawingContext, + padding // This will be 0 because at least one filter has already been applied. + ); + + // Whether top context is new or the input, it now needs to be released. + topContext.release(); + } + else + { + // No filters to run. + // Copy the input to the output. + filter = this.manager.getNode('FilterBlend'); + var proxyController = { + blendMode: BlendModes.COPY, + glTexture: inputDrawingContext.texture, + amount: 1, + color: [ 1, 1, 1, 1 ] + }; + inputDrawingContext.unlock(this); + outputDrawingContext = filter.run( + proxyController, + inputDrawingContext, + outputDrawingContext, + initialPadding + ); + } + + this.onRunEnd(outputDrawingContext); + + return outputDrawingContext; + } +}); + +module.exports = FilterParallelFilters; + + +/***/ }), + +/***/ 58167: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(99191); + +/** + * @classdesc + * This RenderNode renders the Pixelate filter effect. + * See {@link Phaser.Filters.Pixelate}. + * + * @class FilterPixelate + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterPixelate = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterPixelate (manager) + { + BaseFilterShader.call(this, 'FilterPixelate', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('amount', controller.amount); + programManager.setUniform('resolution', [ drawingContext.width, drawingContext.height ]); + } +}); + +module.exports = FilterPixelate; + + +/***/ }), + +/***/ 13279: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilter = __webpack_require__(47406); + +/** + * @classdesc + * This RenderNode handles the Sampler filter. + * + * The Sampler filter is a special RenderNode that samples the texture + * being passed in, without any modifications. + * + * @class FilterSampler + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilter + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterSampler = new Class({ + Extends: BaseFilter, + + initialize: function FilterSampler (manager) + { + BaseFilter.call(this, 'FilterSampler', manager); + }, + + run: function (controller, inputDrawingContext, outputDrawingContext, padding) + { + this.onRunBegin(inputDrawingContext); + + var renderer = this.manager.renderer; + var x = 0; + var y = 0; + var width = 1; + var height = 1; + var bufferWidth = inputDrawingContext.width; + var bufferHeight = inputDrawingContext.height; + var getPixel = false; + + if (controller.region) + { + x = controller.region.x; + y = controller.region.y; + + if (controller.region.width !== undefined) + { + // Region is a Rectangle. + width = controller.region.width; + height = controller.region.height; + } + else + { + // Region is a point. + getPixel = true; + } + } + else + { + // Sample the whole buffer. + width = bufferWidth; + height = bufferHeight; + } + + renderer.snapshotFramebuffer( + inputDrawingContext.framebuffer, + bufferWidth, bufferHeight, + controller.callback, + getPixel, + x, y, + width, height + ); + + this.onRunEnd(inputDrawingContext); + + return inputDrawingContext; + } +}); + +module.exports = FilterSampler; + + +/***/ }), + +/***/ 27459: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(69355); + +/** + * @classdesc + * This RenderNode renders the Shadow filter effect. + * See {@link Phaser.Filters.Shadow}. + * + * @class FilterShadow + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterShadow = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterShadow (manager) + { + BaseFilterShader.call(this, 'FilterShadow', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + var samples = controller.samples; + + programManager.setUniform('lightPosition', [ controller.x, controller.y ]); + programManager.setUniform('decay', controller.decay); + programManager.setUniform('power', controller.power / samples); + programManager.setUniform('color', controller.glcolor); + programManager.setUniform('samples', samples); + programManager.setUniform('intensity', controller.intensity); + } +}); + +module.exports = FilterShadow; + + +/***/ }), + +/***/ 88856: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var BaseFilterShader = __webpack_require__(53663); + +var ShaderSourceFS = __webpack_require__(92636); + +/** + * @classdesc + * This RenderNode renders the Threshold filter effect. + * See {@link Phaser.Filters.Threshold}. + * + * @class FilterThreshold + * @extends Phaser.Renderer.WebGL.RenderNodes.BaseFilterShader + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var FilterThreshold = new Class({ + Extends: BaseFilterShader, + + initialize: function FilterThreshold (manager) + { + BaseFilterShader.call(this, 'FilterThreshold', manager, null, ShaderSourceFS); + }, + + setupUniforms: function (controller, drawingContext) + { + var programManager = this.programManager; + + programManager.setUniform('edge1', controller.edge1); + programManager.setUniform('edge2', controller.edge2); + programManager.setUniform('invert', controller.invert); + } +}); + +module.exports = FilterThreshold; + + +/***/ }), + +/***/ 54521: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.WebGL.RenderNodes + */ + +var RenderNodes = { + BaseFilter: __webpack_require__(47406), + BaseFilterShader: __webpack_require__(53663), + + BatchHandler: __webpack_require__(13961), + BatchHandlerPointLight: __webpack_require__(16971), + BatchHandlerQuad: __webpack_require__(15214), + BatchHandlerStrip: __webpack_require__(62791), + BatchHandlerTileSprite: __webpack_require__(21832), + BatchHandlerTriFlat: __webpack_require__(62087), + + Camera: __webpack_require__(61842), + Defaults: __webpack_require__(59212), + DrawLine: __webpack_require__(76409), + DynamicTextureHandler: __webpack_require__(95449), + FillCamera: __webpack_require__(61199), + FillPath: __webpack_require__(14255), + FillRect: __webpack_require__(12682), + FillTri: __webpack_require__(13119), + + FilterBarrel: __webpack_require__(22731), + FilterBlend: __webpack_require__(57032), + FilterBlur: __webpack_require__(13922), + FilterBlurHigh: __webpack_require__(33466), + FilterBlurLow: __webpack_require__(75798), + FilterBlurMed: __webpack_require__(90830), + FilterBokeh: __webpack_require__(52302), + FilterColorMatrix: __webpack_require__(34989), + FilterDisplacement: __webpack_require__(15600), + FilterGlow: __webpack_require__(99786), + FilterMask: __webpack_require__(26703), + FilterParallelFilters: __webpack_require__(55905), + FilterPixelate: __webpack_require__(58167), + FilterSampler: __webpack_require__(13279), + FilterShadow: __webpack_require__(27459), + FilterThreshold: __webpack_require__(88856), + + ListCompositor: __webpack_require__(27996), + RebindContext: __webpack_require__(56432), + RenderNode: __webpack_require__(6141), + StrokePath: __webpack_require__(17486), + SubmitterQuad: __webpack_require__(31029), + SubmitterSpriteGPULayer: __webpack_require__(53384), + SubmitterTile: __webpack_require__(94494), + SubmitterTilemapGPULayer: __webpack_require__(87469), + SubmitterTileSprite: __webpack_require__(89723), + TexturerImage: __webpack_require__(12913), + TexturerTileSprite: __webpack_require__(22995), + TransformerImage: __webpack_require__(86081), + TransformerStamp: __webpack_require__(88383), + TransformerTile: __webpack_require__(34454), + TransformerTileSprite: __webpack_require__(46211), + YieldContext: __webpack_require__(95433) +}; + +module.exports = RenderNodes; + + +/***/ }), + +/***/ 31029: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Merge = __webpack_require__(46975); +var Utils = __webpack_require__(70554); +var RenderNode = __webpack_require__(6141); + +var getTint = Utils.getTintAppendFloatAlpha; + +/** + * @classdesc + * The SubmitterQuad RenderNode submits data for rendering a single Image-like GameObject. + * It uses a BatchHandler to render the image as part of a batch. + * + * This node receives the drawing context, game object, and parent matrix. + * It also receives the texturer, tinter, and transformer nodes + * from the node that invoked it. + * This allows the behavior to be configured by setting the appropriate nodes + * on the GameObject for individual tweaks, or on the invoking Renderer node + * for global changes. + * + * @class SubmitterQuad + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.SubmitterQuadConfig} [config] - The configuration object for this RenderNode. + */ +var SubmitterQuad = new Class({ + Extends: RenderNode, + + initialize: function SubmitterQuad (manager, config) + { + config = Merge(config || {}, this.defaultConfig); + + RenderNode.call(this, config.name, manager); + + /** + * The key of the RenderNode used to render data. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad#batchHandler + * @type {string} + * @since 4.0.0 + */ + this.batchHandler = config.batchHandler; + + /** + * Persistent object reused to pass render options to the batch handler. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad#_renderOptions + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerQuadRenderOptions} + * @since 4.0.0 + * @private + */ + this._renderOptions = { + multiTexturing: true, + lighting: null, + smoothPixelArt: null, + roundPixels: false + }; + + /** + * Persistent object reused to pass lighting options to the batch handler. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad#_lightingOptions + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerQuadRenderOptionsLighting} + * @since 4.0.0 + * @private + */ + this._lightingOptions = { + normalGLTexture: null, + normalMapRotation: 0, + selfShadow: { + enabled: false, + penumbra: 0, + diffuseFlatThreshold: 0 + } + }; + }, + + /** + * The default configuration for this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.SubmitterQuadConfig} + */ + defaultConfig: { + name: 'SubmitterQuad', + role: 'Submitter', + batchHandler: 'BatchHandler' + }, + + /** + * Submit data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - The parent matrix of the GameObject. + * @param {?object} element - The specific element within the game object. This is used for objects that consist of multiple quads. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} texturerNode - The texturer node used to texture the GameObject. You may pass a TexturerImage node or an object containing equivalent data without a `run` method. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode|{ quad: Float32Array }} transformerNode - The transformer node used to transform the GameObject. You may pass a transformer node or an object with a `quad` property. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode|Omit} [tinterNode] - The tinter node used to tint the GameObject. You may pass a tinter node or an object containing equivalent data without a `run` method. If omitted, Image-style tinting will be used. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [normalMap] - The normal map texture to use for lighting. If omitted, the normal map texture of the GameObject will be used, or the default normal map texture of the renderer. + * @param {number} [normalMapRotation] - The rotation of the normal map texture. If omitted, the rotation of the GameObject will be used. + */ + run: function ( + drawingContext, + gameObject, + parentMatrix, + element, + texturerNode, + transformerNode, + tinterNode, + normalMap, + normalMapRotation + ) + { + this.onRunBegin(drawingContext); + + var tintFill, tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight; + + if (texturerNode.run) + { + texturerNode.run(drawingContext, gameObject, element); + } + if (transformerNode.run) + { + transformerNode.run(drawingContext, gameObject, texturerNode, parentMatrix, element); + } + if (tinterNode) + { + if (tinterNode.run) + { + tinterNode.run(drawingContext, gameObject, element); + } + tintFill = tinterNode.tintFill; + tintTopLeft = tinterNode.tintTopLeft; + tintBottomLeft = tinterNode.tintBottomLeft; + tintTopRight = tinterNode.tintTopRight; + tintBottomRight = tinterNode.tintBottomRight; + } + else + { + tintFill = gameObject.tintFill; + tintTopLeft = getTint(gameObject.tintTopLeft, gameObject._alphaTL); + tintBottomLeft = getTint(gameObject.tintBottomLeft, gameObject._alphaBL); + tintTopRight = getTint(gameObject.tintTopRight, gameObject._alphaTR); + tintBottomRight = getTint(gameObject.tintBottomRight, gameObject._alphaBR); + } + + var quad = transformerNode.quad; + var uvSource = texturerNode.uvSource; + var u0 = uvSource.u0; + var v0 = uvSource.v0; + var u1 = uvSource.u1; + var v1 = uvSource.v1; + + this.setRenderOptions(gameObject, normalMap, normalMapRotation); + + this._renderOptions.roundPixels = !!transformerNode.onlyTranslate && drawingContext.camera.roundPixels; + + ( + gameObject.customRenderNodes[this.batchHandler] || + gameObject.defaultRenderNodes[this.batchHandler] + ).batch( + drawingContext, + + // Use `frame.source.glTexture` instead of `frame.glTexture` + // to avoid unnecessary getter function calls. + texturerNode.frame.source.glTexture, + + // Transformed quad in order TL, BL, TR, BR: + quad[0], quad[1], + quad[2], quad[3], + quad[6], quad[7], + quad[4], quad[5], + + // Texture coordinates in X, Y, Width, Height: + u0, v0, u1 - u0, v1 - v0, + + tintFill, + + // Tint colors in order TL, BL, TR, BR: + tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight, + + // Extra render options: + this._renderOptions + ); + + this.onRunEnd(drawingContext); + }, + + setRenderOptions: function (gameObject, normalMap, normalMapRotation) + { + var renderOptions = this._renderOptions; + var baseTexture, sourceIndex; + if (gameObject.displayTexture) + { + baseTexture = gameObject.displayTexture; + sourceIndex = gameObject.displayFrame.sourceIndex; + } + else if (gameObject.texture) + { + baseTexture = gameObject.texture; + sourceIndex = gameObject.frame.sourceIndex; + } + else if (gameObject.tileset) + { + if (Array.isArray(gameObject.tileset)) + { + baseTexture = gameObject.tileset[0].image; + } + else + { + baseTexture = gameObject.tileset.image; + } + sourceIndex = 0; + } + + + if (gameObject.lighting) + { + // Get normal map. + if (!normalMap) + { + if (baseTexture) + { + normalMap = baseTexture.dataSource[sourceIndex]; + } + } + if (!normalMap) + { + normalMap = this.manager.renderer.normalTexture; + } + else + { + normalMap = normalMap.glTexture; + } + + // Get normal map rotation. + if (isNaN(normalMapRotation)) + { + normalMapRotation = gameObject.rotation; + if (gameObject.parentContainer) + { + var matrix = gameObject.getWorldTransformMatrix(this._tempMatrix, this._tempMatrix2); + normalMapRotation = matrix.rotationNormalized; + } + } + + // Get self-shadow. + var selfShadow = gameObject.selfShadow; + var selfShadowEnabled = selfShadow.enabled; + if (selfShadowEnabled === null) + { + selfShadowEnabled = gameObject.scene.sys.game.config.selfShadow; + } + + this._lightingOptions.normalGLTexture = normalMap; + this._lightingOptions.normalMapRotation = normalMapRotation; + this._lightingOptions.selfShadow.enabled = selfShadowEnabled; + this._lightingOptions.selfShadow.penumbra = selfShadow.penumbra; + this._lightingOptions.selfShadow.diffuseFlatThreshold = selfShadow.diffuseFlatThreshold; + + renderOptions.lighting = this._lightingOptions; + } + else + { + renderOptions.lighting = null; + } + + // Get smooth pixel art option. + var smoothPixelArt; + if (baseTexture && baseTexture.smoothPixelArt !== null) + { + smoothPixelArt = baseTexture.smoothPixelArt; + } + else + { + smoothPixelArt = gameObject.scene.sys.game.config.smoothPixelArt; + } + renderOptions.smoothPixelArt = smoothPixelArt; + } +}); + +module.exports = SubmitterQuad; + + +/***/ }), + +/***/ 53384: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); +var Vector2 = __webpack_require__(26099); +var Class = __webpack_require__(83419); +var Merge = __webpack_require__(46975); +var ProgramManager = __webpack_require__(56436); +var MakeApplyLighting = __webpack_require__(81084); +var MakeApplyTint = __webpack_require__(44349); +var MakeDefineLights = __webpack_require__(6184); +var MakeDefineTexCount = __webpack_require__(11653); +var MakeGetNormalFromMap = __webpack_require__(40829); +var MakeGetTexCoordOut = __webpack_require__(42792); +var MakeGetTexRes = __webpack_require__(96049); +var MakeGetTexture = __webpack_require__(33997); +var MakeOutInverseRotation = __webpack_require__(79532); +var MakeSmoothPixelArt = __webpack_require__(74505); +var Utils = __webpack_require__(70554); +var WebGLVertexBufferLayoutWrapper = __webpack_require__(40952); +var RenderNode = __webpack_require__(6141); + +var ShaderSourceFS = __webpack_require__(49119); +var ShaderSourceVS = __webpack_require__(3524); + +/** + * @classdesc + * This RenderNode handles rendering of a single SpriteGPULayer object. + * A new instance of the RenderNode should be created for each SpriteGPULayer object, + * as it stores the shader program and vertex buffer data for the object. + * + * It is a Stand Alone Render, meaning that it does not batch. + * It is best suited to rendering highly complex objects. + * + * @class SubmitterSpriteGPULayer + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {object} [config] - The configuration object for this handler. + * @param {string} [config.name='SubmitterSpriteGPULayer'] - The name of this RenderNode. + * @param {string} [config.vertexSource] - The vertex shader source. + * @param {string} [config.fragmentSource] - The fragment shader source. + */ +var SubmitterSpriteGPULayer = new Class({ + Extends: RenderNode, + + initialize: function SubmitterSpriteGPULayer (manager, config, gameObject) + { + var renderer = manager.renderer; + + var finalConfig = Merge(config || {}, this.defaultConfig); + var name = finalConfig.name; + this._completeLayout(finalConfig); + + RenderNode.call(this, name, manager); + + /** + * The completed configuration object for this RenderNode. + * This is defined by the default configuration and the user-defined configuration object. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#config + * @type {object} + * @since 4.0.0 + */ + this.config = finalConfig; + + /** + * The SpriteGPULayer GameObject this RenderNode is rendering. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#gameObject + * @type {Phaser.GameObjects.SpriteGPULayer} + * @since 4.0.0 + * @readonly + */ + this.gameObject = gameObject; + + /** + * The instance buffer layout for this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#instanceBufferLayout + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper} + * @since 4.0.0 + * @readonly + */ + this.instanceBufferLayout = new WebGLVertexBufferLayoutWrapper( + renderer, + finalConfig.instanceBufferLayout, + null + ); + + /** + * The vertex buffer layout for this RenderNode. + * + * This consists of 4 bytes, 0-3, forming corners of a quad instance. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#vertexBufferLayout + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper} + * @since 4.0.0 + * @readonly + */ + this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper( + renderer, + finalConfig.vertexBufferLayout, + null + ); + + // Set up vertex buffer. + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexBufferViewU8 = vertexBuffer.viewU8; + vertexBufferViewU8[0] = 0; + vertexBufferViewU8[1] = 1; + vertexBufferViewU8[2] = 2; + vertexBufferViewU8[3] = 3; + vertexBuffer.update(); + + /** + * The program manager used to create and manage shader programs. + * This contains shader variants. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#programManager + * @type {Phaser.Renderer.WebGL.ProgramManager} + * @since 4.0.0 + */ + this.programManager = new ProgramManager( + renderer, + [ this.vertexBufferLayout, this.instanceBufferLayout ], + this.indexBuffer + ); + + // Fill in program configuration from config. + this.programManager.setBaseShader( + finalConfig.shaderName, + finalConfig.vertexSource, + finalConfig.fragmentSource + ); + if (finalConfig.shaderAdditions) + { + for (var i = 0; i < finalConfig.shaderAdditions.length; i++) + { + var addition = finalConfig.shaderAdditions[i]; + this.programManager.addAddition(addition); + } + } + if (finalConfig.shaderFeatures) + { + for (i = 0; i < finalConfig.shaderFeatures.length; i++) + { + this.programManager.addFeature(finalConfig.shaderFeatures[i]); + } + } + + /** + * A matrix used for temporary calculations. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#_calcMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + */ + this._calcMatrix = new TransformMatrix(); + + /** + * A vector used for temporary calculations. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#_lightVector + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + * @private + */ + this._lightVector = new Vector2(); + }, + + /** + * Default configuration of this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#defaultConfig + * @type {object} + * @since 4.0.0 + * @readonly + * @property {string} name - The name of this RenderNode. + * @property {string} vertexSource - The vertex shader source. + * @property {string} fragmentSource - The fragment shader source. + */ + defaultConfig: { + name: 'SubmitterSpriteGPULayer', + count: 0, + shaderName: 'SpriteGPULayer', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + shaderAdditions: [ + MakeGetTexCoordOut(), + MakeGetTexRes(), + MakeSmoothPixelArt(true), + MakeDefineTexCount(1), + MakeGetTexture(), + MakeApplyTint(), + MakeDefineLights(true), + MakeOutInverseRotation(true), + MakeGetNormalFromMap(true), + MakeApplyLighting(true) + ], + instanceBufferLayout: { + usage: 'STATIC_DRAW', + instanceDivisor: 1, + layout: [ + { + name: 'inPositionX', + size: 4 + }, + { + name: 'inPositionY', + size: 4 + }, + { + name: 'inRotation', + size: 4 + }, + { + name: 'inScaleX', + size: 4 + }, + { + name: 'inScaleY', + size: 4 + }, + { + name: 'inAlpha', + size: 4 + }, + { + name: 'inFrame', + size: 4 + }, + { + name: 'inTintBlend', + size: 4 + }, + { + name: 'inTintBL', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + }, + { + name: 'inTintTL', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + }, + { + name: 'inTintBR', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + }, + { + name: 'inTintTR', + size: 4, + type: 'UNSIGNED_BYTE', + normalized: true + }, + { + name: 'inOriginAndTintFillAndCreationTime', + size: 4 + }, + { + name: 'inScrollFactor', + size: 2 + } + ] + }, + vertexBufferLayout: { + usage: 'STATIC_DRAW', + count: 4, + layout: [ + { + // The vertex index, 0-3. + name: 'inVertex', + type: 'UNSIGNED_BYTE' + } + ] + } + }, + + /** + * Fill out the configuration object with default values where needed. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#_completeConfig + * @since 4.0.0 + * @param {object} config - The configuration object to complete. + */ + _completeLayout: function (config) + { + // Set up vertex buffer layout. + var layoutSource = config.vertexBufferLayout; + config.vertexBufferLayout = {}; + config.vertexBufferLayout.usage = layoutSource.usage; + config.vertexBufferLayout.count = layoutSource.count; + config.vertexBufferLayout.layout = []; + var remove = config.vertexBufferLayoutRemove || []; + + for (var i = 0; i < layoutSource.layout.length; i++) + { + var sourceAttr = layoutSource.layout[i]; + if (remove.indexOf(sourceAttr.name) !== -1) + { + continue; + } + config.vertexBufferLayout.layout[i] = { + name: sourceAttr.name, + size: sourceAttr.size || 1, + type: sourceAttr.type || 'FLOAT', + normalized: sourceAttr.normalized || false + }; + } + + if (config.vertexBufferLayoutAdd) + { + var add = config.vertexBufferLayoutAdd || []; + for (i = 0; i < add.length; i++) + { + var addAttr = add[i]; + config.vertexBufferLayout.layout.push({ + name: addAttr.name, + size: addAttr.size || 1, + type: addAttr.type || 'FLOAT', + normalized: addAttr.normalized || false + }); + } + } + + // Set up instance buffer layout. + layoutSource = config.instanceBufferLayout; + config.instanceBufferLayout = {}; + config.instanceBufferLayout.usage = layoutSource.usage; + config.instanceBufferLayout.instanceDivisor = layoutSource.instanceDivisor; + config.instanceBufferLayout.layout = []; + remove = config.instanceBufferLayoutRemove || []; + + for (i = 0; i < layoutSource.layout.length; i++) + { + sourceAttr = layoutSource.layout[i]; + if (remove.indexOf(sourceAttr.name) !== -1) + { + continue; + } + config.instanceBufferLayout.layout[i] = { + name: sourceAttr.name, + size: sourceAttr.size || 1, + type: sourceAttr.type || 'FLOAT', + normalized: sourceAttr.normalized || false + }; + } + + if (config.instanceBufferLayoutAdd) + { + add = config.instanceBufferLayoutAdd || []; + for (i = 0; i < add.length; i++) + { + addAttr = add[i]; + config.instanceBufferLayout.layout.push({ + name: addAttr.name, + size: addAttr.size || 1, + type: addAttr.type || 'FLOAT', + normalized: addAttr.normalized || false + }); + } + } + }, + + setupUniforms: function (drawingContext) + { + var camera = drawingContext.camera; + var programManager = this.programManager; + var layer = this.gameObject; + + programManager.setUniform( + 'uRoundPixels', + camera.roundPixels + ); + + programManager.setUniform( + 'uResolution', + [ drawingContext.width, drawingContext.height ] + ); + + drawingContext.renderer.setProjectionMatrixFromDrawingContext(drawingContext); + programManager.setUniform( + 'uProjectionMatrix', + drawingContext.renderer.projectionMatrix.val + ); + + var cm = camera.matrixCombined; + programManager.setUniform( + 'uViewMatrix', + [ + cm.a, cm.b, 0, + cm.c, cm.d, 0, + cm.tx, cm.ty, 1 + ] + ); + + programManager.setUniform( + 'uCameraScrollAndAlpha', + [ + camera.scrollX, + camera.scrollY, + layer.alpha + ] + ); + + programManager.setUniform( + 'uTime', + layer.timeElapsed + ); + + programManager.setUniform( + 'uDiffuseResolution', + [ + layer.frame.source.width, + layer.frame.source.height + ] + ); + + programManager.setUniform( + 'uFrameDataResolution', + [ + layer.frameDataTexture.width, + layer.frameDataTexture.height + ] + ); + + programManager.setUniform( + 'uGravity', + layer.gravity + ); + + // Set texture sampler uniforms. + programManager.setUniform('uMainSampler[0]', 0); + programManager.setUniform('uFrameDataTexture', 1); + + var glTexture = layer.texture.source[0].glTexture; + programManager.setUniform('uMainResolution[0]', [ glTexture.width, glTexture.height ]); + + // Lighting uniforms. + Utils.updateLightingUniforms( + layer.lighting, + this.manager.renderer, + drawingContext, + programManager, + 2, + this._lightVector, + layer.selfShadow.enabled, + layer.selfShadow.diffuseFlatThreshold, + layer.selfShadow.penumbra + ); + }, + + updateRenderOptions: function () + { + var programManager = this.programManager; + + // Set lighting options. + var lighting = this.gameObject.lighting; + var lightingAdditions = programManager.getAdditionsByTag('LIGHTING'); + for (var i = 0; i < lightingAdditions.length; i++) + { + lightingAdditions[i].disable = !lighting; + } + + if (lighting) + { + var defineLightsAddition = programManager.getAddition('DefineLights'); + if (defineLightsAddition) + { + defineLightsAddition.additions.fragmentDefine = '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights; + } + } + + // Set smooth pixel art options. + var smoothAddition = programManager.getAddition('SmoothPixelArt'); + if (smoothAddition) + { + var smoothPixelArt = this.gameObject.texture.smoothPixelArt; + if (smoothPixelArt === null) + { + smoothPixelArt = this.gameObject.scene.game.config.smoothPixelArt; + } + smoothAddition.disable = !smoothPixelArt; + } + + // Set features. + programManager.clearFeatures(); + var shaderFeatures = this.gameObject.getShaderFeatures(); + for (i = 0; i < shaderFeatures.length; i++) + { + programManager.addFeature(shaderFeatures[i]); + } + + if (this.gameObject.selfShadow.enabled) + { + programManager.addFeature('SELFSHADOW'); + } + }, + + /** + * Render a SpriteGPULayer object. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterSpriteGPULayer#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + */ + run: function (drawingContext) + { + var i; + var layer = this.gameObject; + + if (layer.memberCount === 0) + { + return; + } + + this.manager.startStandAloneRender(); + + this.onRunBegin(drawingContext); + + // Update instance buffer if needed. + var segments = layer.bufferUpdateSegments; + if (segments > 0) + { + var buffer = this.instanceBufferLayout.buffer; + var memberCount = layer.memberCount; + + var lastSegment = Math.floor(memberCount / layer.bufferUpdateSegmentSize); + var occupiedSegmentsAllUpdated = true; + for (i = 0; i <= lastSegment; i++) + { + if (1 << i & segments) + { + continue; + } + occupiedSegmentsAllUpdated = false; + break; + } + + if ( + segments === layer.MAX_BUFFER_UPDATE_SEGMENTS_FULL || + memberCount <= layer.bufferUpdateSegmentSize || + occupiedSegmentsAllUpdated + ) + { + // Everything needs updating. + buffer.update(); + } + else + { + // Only some segments need updating. + var segmentSize = layer.bufferUpdateSegmentSize; + var segmentByteSize = segmentSize * this.instanceBufferLayout.layout.stride; + for ( + i = 0; + i < 32 && i * segmentSize < memberCount; + i++ + ) + { + if (segments & (1 << i)) + { + buffer.update(segmentByteSize, i * segmentByteSize); + } + } + } + layer.clearAllSegmentsNeedUpdate(); + } + + // Assemble textures. + var textures = [ + layer.frame.source.glTexture, + layer.frameDataTexture + ]; + + if (layer.lighting) + { + var normalMap = layer.texture.dataSource[layer.frame.sourceIndex]; + if (!normalMap) + { + normalMap = this.manager.renderer.normalTexture; + } + else + { + normalMap = normalMap.glTexture; + } + textures[2] = normalMap; + } + + this.updateRenderOptions(); + + var programManager = this.programManager; + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + + this.setupUniforms(drawingContext); + programManager.applyUniforms(program); + + // Render instances. + this.manager.renderer.drawInstancedArrays( + drawingContext, + textures, + program, + vao, + 0, + 4, + layer.memberCount + ); + } + + this.onRunEnd(drawingContext); + } +}); + +module.exports = SubmitterSpriteGPULayer; + + +/***/ }), + +/***/ 94494: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var SubmitterQuad = __webpack_require__(31029); + +/** + * @classdesc + * The SubmitterTile RenderNode submits data for tiles. + * + * @class SubmitterTile + * @extends Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} manager - The WebGLRenderer that owns this Submitter. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.SubmitterQuadConfig} [config] - The configuration object for this Submitter. This is a SubmitterQuad configuration object with the `name` defaulting to `SubmitterTile`. + */ +var SubmitterTile = new Class({ + Extends: SubmitterQuad, + + initialize: function SubmitterTile (manager, config) + { + SubmitterQuad.call(this, manager, config); + + this._renderOptions.clampFrame = true; + }, + + /** + * The default configuration for this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTile#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.SubmitterQuadConfig} + */ + defaultConfig: { + name: 'SubmitterTile', + role: 'Submitter', + batchHandler: 'BatchHandler' + }, + + /** + * Submit data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTile#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - The parent matrix of the GameObject. + * @param {?object} element - The specific element within the game object. This is used for objects that consist of multiple quads. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} texturerNode - The texturer node used to texture the GameObject. You may pass a TexturerTileSprite node or an object containing equivalent data without a `run` method. + * @param {Phaser.Renderer.WebGL.RenderNodes.TransformerTileSprite|{ quad: Float32Array }} transformerNode - The transformer node used to transform the GameObject. You may pass a transformer node or an object with a `quad` property. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode|Omit} [tinterNode] - The tinter node used to tint the GameObject. You may pass a tinter node or an object containing equivalent data without a `run` method. If omitted, no tinting will be used. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [normalMap] - The normal map texture to use for lighting. If omitted, the normal map texture of the GameObject will be used, or the default normal map texture of the renderer. + * @param {number} [normalMapRotation] - The rotation of the normal map texture. If omitted, the rotation of the GameObject will be used. + */ + run: function ( + drawingContext, + gameObject, + parentMatrix, + element, + texturerNode, + transformerNode, + tinterNode, + normalMap, + normalMapRotation + ) + { + this.onRunBegin(drawingContext); + + var tintFill, tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight; + + if (texturerNode.run) + { + texturerNode.run(drawingContext, gameObject, element); + } + if (transformerNode.run) + { + transformerNode.run(drawingContext, gameObject, texturerNode, parentMatrix, element); + } + if (tinterNode) + { + if (tinterNode.run) + { + tinterNode.run(drawingContext, gameObject, element); + } + tintFill = tinterNode.tintFill; + tintTopLeft = tinterNode.tintTopLeft; + tintBottomLeft = tinterNode.tintBottomLeft; + tintTopRight = tinterNode.tintTopRight; + tintBottomRight = tinterNode.tintBottomRight; + } + else + { + tintFill = gameObject.tintFill; + var tint = 0xffffffff; + tintTopLeft = tint; + tintBottomLeft = tint; + tintTopRight = tint; + tintBottomRight = tint; + } + + var frame = texturerNode.frame; + var quad = transformerNode.quad; + var uvSource = texturerNode.uvSource; + var u0 = uvSource.u0; + var v0 = uvSource.v0; + var u1 = uvSource.u1; + var v1 = uvSource.v1; + + this.setRenderOptions(gameObject, normalMap, normalMapRotation); + + this._renderOptions.roundPixels = !!transformerNode.onlyTranslate && drawingContext.camera.roundPixels; + + ( + gameObject.customRenderNodes[this.batchHandler] || + gameObject.defaultRenderNodes[this.batchHandler] + ).batch( + drawingContext, + + // Use `frame.source.glTexture` instead of `frame.glTexture` + // to avoid unnecessary getter function calls. + frame.source.glTexture, + + // Transformed quad in order TL, BL, TR, BR: + quad[0], quad[1], + quad[2], quad[3], + quad[6], quad[7], + quad[4], quad[5], + + // Texture coordinates in X, Y, Width, Height: + u0, v0, u1 - u0, v1 - v0, + + tintFill, + + // Tint colors in order TL, BL, TR, BR: + tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight, + + // Extra render options: + this._renderOptions, + + // Frame coordinates in order TL, BL, TR, BR: + u0, v1, + u0, v0, + u1, v1, + u1, v0 + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = SubmitterTile; + + +/***/ }), + +/***/ 89723: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Utils = __webpack_require__(70554); +var SubmitterQuad = __webpack_require__(31029); + +var getTint = Utils.getTintAppendFloatAlpha; + +/** + * @classdesc + * The SubmitterTileSprite RenderNode submits data for rendering a single TileSprite GameObject. + * It uses a BatchHandler to render the TileSprite as part of a batch. + * + * This node receives the drawing context, game object, and parent matrix. + * It also receives the texturer, tinter, and transformer nodes + * from the node that invoked it. + * This allows the behavior to be configured by setting the appropriate nodes + * on the GameObject for individual tweaks, or on the invoking Renderer node + * for global changes. + * + * @class SubmitterTileSprite + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.SubmitterQuad + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.SubmitterQuadConfig} [config] - The configuration object for this Submitter. This is a SubmitterQuad configuration object with the `name` defaulting to `SubmitterTileSprite`. + */ +var SubmitterTileSprite = new Class({ + Extends: SubmitterQuad, + + initialize: function SubmitterTileSprite (manager, config) + { + SubmitterQuad.call(this, manager, config); + + this._renderOptions.wrapFrame = true; + }, + + /** + * The default configuration for this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTileSprite#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.SubmitterQuadConfig} + */ + defaultConfig: { + name: 'SubmitterTileSprite', + role: 'Submitter', + batchHandler: 'BatchHandler' + }, + + /** + * Submit data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTileSprite#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - The parent matrix of the GameObject. + * @param {?object} element - The specific element within the game object. This is used for objects that consist of multiple quads. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} texturerNode - The texturer node used to texture the GameObject. You may pass a TexturerTileSprite node or an object containing equivalent data without a `run` method. + * @param {Phaser.Renderer.WebGL.RenderNodes.TransformerTileSprite|{ quad: Float32Array }} transformerNode - The transformer node used to transform the GameObject. You may pass a transformer node or an object with a `quad` property. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode|Omit} [tinterNode] - The tinter node used to tint the GameObject. You may pass a tinter node or an object containing equivalent data without a `run` method. If omitted, Image-style tinting will be used. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [normalMap] - The normal map texture to use for lighting. If omitted, the normal map texture of the GameObject will be used, or the default normal map texture of the renderer. + * @param {number} [normalMapRotation] - The rotation of the normal map texture. If omitted, the rotation of the GameObject will be used. + */ + run: function ( + drawingContext, + gameObject, + parentMatrix, + element, + texturerNode, + transformerNode, + tinterNode, + normalMap, + normalMapRotation + ) + { + this.onRunBegin(drawingContext); + + var tintFill, tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight; + + if (texturerNode.run) + { + texturerNode.run(drawingContext, gameObject, element); + } + if (transformerNode.run) + { + transformerNode.run(drawingContext, gameObject, texturerNode, parentMatrix, element); + } + if (tinterNode) + { + if (tinterNode.run) + { + tinterNode.run(drawingContext, gameObject, element); + } + tintFill = tinterNode.tintFill; + tintTopLeft = tinterNode.tintTopLeft; + tintBottomLeft = tinterNode.tintBottomLeft; + tintTopRight = tinterNode.tintTopRight; + tintBottomRight = tinterNode.tintBottomRight; + } + else + { + tintFill = gameObject.tintFill; + tintTopLeft = getTint(gameObject.tintTopLeft, gameObject._alphaTL); + tintBottomLeft = getTint(gameObject.tintBottomLeft, gameObject._alphaBL); + tintTopRight = getTint(gameObject.tintTopRight, gameObject._alphaTR); + tintBottomRight = getTint(gameObject.tintBottomRight, gameObject._alphaBR); + } + + var frame = texturerNode.frame; + var quad = transformerNode.quad; + var uvSource = frame; + var u0 = uvSource.u0; + var v0 = uvSource.v0; + var u1 = uvSource.u1; + var v1 = uvSource.v1; + var uvQuad = texturerNode.uvMatrix.quad; + + this.setRenderOptions(gameObject, normalMap, normalMapRotation); + + this._renderOptions.roundPixels = !!transformerNode.onlyTranslate && drawingContext.camera.roundPixels; + + // Normal map rotation must include the texture rotation. + this._lightingOptions.normalMapRotation += gameObject.tileRotation; + + ( + gameObject.customRenderNodes[this.batchHandler] || + gameObject.defaultRenderNodes[this.batchHandler] + ).batch( + drawingContext, + + // Use `frame.source.glTexture` instead of `frame.glTexture` + // to avoid unnecessary getter function calls. + frame.source.glTexture, + + // Transformed quad in order TL, BL, TR, BR: + quad[0], quad[1], + quad[2], quad[3], + quad[6], quad[7], + quad[4], quad[5], + + // Texture coordinates in X, Y, Width, Height: + u0, v0, u1 - u0, v1 - v0, + + tintFill, + + // Tint colors in order TL, BL, TR, BR: + tintTopLeft, tintBottomLeft, tintTopRight, tintBottomRight, + + // Extra render options: + this._renderOptions, + + // Dynamic UV coordinates in order TL, BL, TR, BR: + uvQuad[0], uvQuad[1], + uvQuad[2], uvQuad[3], + uvQuad[6], uvQuad[7], + uvQuad[4], uvQuad[5] + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = SubmitterTileSprite; + + +/***/ }), + +/***/ 87469: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license None + */ + +var TransformMatrix = __webpack_require__(61340); +var Vector2 = __webpack_require__(26099); +var Class = __webpack_require__(83419); +var Merge = __webpack_require__(46975); +var ProgramManager = __webpack_require__(56436); +var MakeAnimLength = __webpack_require__(84639); +var MakeApplyLighting = __webpack_require__(81084); +var MakeDefineLights = __webpack_require__(6184); +var MakeSampleNormal = __webpack_require__(747); +var MakeSmoothPixelArt = __webpack_require__(74505); +var ShaderSourceFS = __webpack_require__(57532); +var ShaderSourceVS = __webpack_require__(23879); +var WebGLVertexBufferLayoutWrapper = __webpack_require__(40952); +var RenderNode = __webpack_require__(6141); +var Utils = __webpack_require__(70554); + +/** + * @classdesc + * The SubmitterTilemapGPULayer RenderNode handles rendering of + * TilemapGPULayer objects. + * + * It is a Stand Alone Render, meaning that it does not batch. + * + * @class SubmitterTilemapGPULayer + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this handler. + */ +var SubmitterTilemapGPULayer = new Class({ + Extends: RenderNode, + + initialize: function SubmitterTilemapGPULayer (manager, config) + { + var renderer = manager.renderer; + + var finalConfig = Merge(config || {}, this.defaultConfig); + var name = finalConfig.name; + this._completeLayout(finalConfig); + + RenderNode.call(this, name, manager); + + /** + * The completed configuration object for this RenderNode. + * This is defined by the default configuration and the user-defined configuration object. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#config + * @type {object} + * @since 4.0.0 + */ + this.config = finalConfig; + + /** + * The index buffer defining vertex order. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#indexBuffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.indexBuffer = renderer.genericQuadIndexBuffer; + + /** + * The vertex buffer layout for this RenderNode. + * + * This consists of 4 bytes, 0-3, forming corners of a quad instance. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#vertexBufferLayout + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper} + * @since 4.0.0 + * @readonly + */ + this.vertexBufferLayout = new WebGLVertexBufferLayoutWrapper( + renderer, + finalConfig.vertexBufferLayout, + finalConfig.createOwnVertexBuffer ? null : renderer.genericVertexBuffer + ); + + /** + * The program manager used to create and manage shader programs. + * This contains shader variants. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#programManager + * @type {Phaser.Renderer.WebGL.ProgramManager} + * @since 4.0.0 + */ + this.programManager = new ProgramManager( + renderer, + [ this.vertexBufferLayout ], + this.indexBuffer + ); + + // Fill in program configuration from config. + this.programManager.setBaseShader( + finalConfig.shaderName, + finalConfig.vertexSource, + finalConfig.fragmentSource + ); + if (finalConfig.shaderAdditions) + { + for (var i = 0; i < finalConfig.shaderAdditions.length; i++) + { + var addition = finalConfig.shaderAdditions[i]; + this.programManager.addAddition(addition); + } + } + if (finalConfig.shaderFeatures) + { + for (i = 0; i < finalConfig.shaderFeatures.length; i++) + { + this.programManager.addFeature(finalConfig.shaderFeatures[i]); + } + } + + /** + * The matrix used internally to compute sprite transforms. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_spriteMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + * @private + */ + this._spriteMatrix = new TransformMatrix(); + + /** + * The matrix used internally to compute the final transform. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_calcMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + * @private + */ + this._calcMatrix = new TransformMatrix(); + + /** + * A vector used for temporary calculations. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_lightVector + * @type {Phaser.Math.Vector2} + * @since 4.0.0 + * @private + */ + this._lightVector = new Vector2(); + + /** + * The matrix used to store the final quad data for rendering. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_quad + * @type {Float32Array} + * @since 4.0.0 + * @private + */ + this._quad = new Float32Array(8); + }, + + /** + * Default configuration of this RenderNode. + * + * @name Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#defaultConfig + * @type {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} + * @since 4.0.0 + * @readonly + * @property {string} name - The name of this RenderNode. + * @property {string} vertexSource - The vertex shader source. + * @property {string} fragmentSource - The fragment shader source. + */ + defaultConfig: { + name: 'SubmitterTilemapGPULayer', + shaderName: 'TilemapGPULayer', + vertexSource: ShaderSourceVS, + fragmentSource: ShaderSourceFS, + shaderAdditions: [ + MakeSmoothPixelArt(true), + MakeSampleNormal(true), + MakeDefineLights(true), + MakeApplyLighting(true) + ], + vertexBufferLayout: { + usage: 'DYNAMIC_DRAW', + count: 4, + layout: [ + { + name: 'inPosition', + size: 2 + }, + { + name: 'inTexCoord', + size: 2 + } + ] + } + }, + + /** + * Fill out the configuration object with default values where needed. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#_completeConfig + * @since 4.0.0 + * @param {object} config - The configuration object to complete. + */ + _completeLayout: function (config) + { + // Set up vertex buffer layout. + var layoutSource = config.vertexBufferLayout; + config.vertexBufferLayout = {}; + config.vertexBufferLayout.usage = layoutSource.usage; + config.vertexBufferLayout.layout = []; + var remove = config.vertexBufferLayoutRemove || []; + + for (var i = 0; i < layoutSource.layout.length; i++) + { + var sourceAttr = layoutSource.layout[i]; + if (remove.indexOf(sourceAttr.name) !== -1) + { + continue; + } + config.vertexBufferLayout.layout[i] = { + name: sourceAttr.name, + size: sourceAttr.size || 1, + type: sourceAttr.type || 'FLOAT', + normalized: sourceAttr.normalized || false + }; + } + + if (config.vertexBufferLayoutAdd) + { + var add = config.vertexBufferLayoutAdd || []; + for (i = 0; i < add.length; i++) + { + var addAttr = add[i]; + config.vertexBufferLayout.layout.push({ + name: addAttr.name, + size: addAttr.size || 1, + type: addAttr.type || 'FLOAT', + normalized: addAttr.normalized || false + }); + } + } + }, + + /** + * Set up uniforms for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#setupUniforms + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.Tilemaps.TilemapGPULayer} tilemapLayer - The TilemapGPULayer being rendered. + */ + setupUniforms: function (drawingContext, tilemapLayer) + { + var camera = drawingContext.camera; + var programManager = this.programManager; + + // Standard uniforms. + + programManager.setUniform( + 'uRoundPixels', + camera.roundPixels + ); + + programManager.setUniform( + 'uResolution', + [ drawingContext.width, drawingContext.height ] + ); + + drawingContext.renderer.setProjectionMatrixFromDrawingContext(drawingContext); + programManager.setUniform( + 'uProjectionMatrix', + drawingContext.renderer.projectionMatrix.val + ); + + // TilemapGPULayer uniforms. + + var tileset = tilemapLayer.tileset; + var mainTexture = tileset.glTexture; + var layerTexture = tilemapLayer.layerDataTexture; + var animTexture = tileset.getAnimationDataTexture(drawingContext.renderer); + + programManager.setUniform('uMainSampler', 0); + programManager.setUniform('uLayerSampler', 1); + programManager.setUniform('uAnimSampler', 2); + + programManager.setUniform( + 'uMainResolution', + [ mainTexture.width, mainTexture.height ] + ); + + programManager.setUniform( + 'uLayerResolution', + [ layerTexture.width, layerTexture.height ] + ); + + programManager.setUniform( + 'uAnimResolution', + [ animTexture.width, animTexture.height ] + ); + + programManager.setUniform( + 'uTileColumns', + tileset.columns + ); + + programManager.setUniform( + 'uTileWidthHeightMarginSpacing', + [ + tileset.tileWidth, + tileset.tileHeight, + tileset.tileMargin, + tileset.tileSpacing + ] + ); + + programManager.setUniform( + 'uAlpha', + tilemapLayer.alpha + ); + + programManager.setUniform( + 'uTime', + tilemapLayer.timeElapsed + ); + + // Lighting uniforms. + Utils.updateLightingUniforms( + tilemapLayer.lighting, + this.manager.renderer, + drawingContext, + programManager, + 3, + this._lightVector, + tilemapLayer.selfShadow.enabled, + tilemapLayer.selfShadow.diffuseFlatThreshold, + tilemapLayer.selfShadow.penumbra + ); + }, + + /** + * Update render options for a TilemapGPULayer object. + * This may use a different shader program. + * This is called before rendering the object. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#updateRenderOptions + * @since 4.0.0 + * @param {Phaser.Tilemaps.TilemapGPULayer} gameObject - The TilemapGPULayer being rendered. + */ + updateRenderOptions: function (gameObject) + { + var programManager = this.programManager; + var texture = gameObject.tileset.image; + + // We do not track whether the shader program has changed. + // This is because this is not a batch renderer, + // and the program is set every time this is called. + + // Set animation options. + var animAddition = programManager.getAdditionsByTag('MAXANIMS')[0]; + if (animAddition) + { + programManager.removeAddition(animAddition.name); + } + if (gameObject.tileset.maxAnimationLength > 0) + { + programManager.addAddition( + MakeAnimLength(gameObject.tileset.maxAnimationLength) + ); + } + + // Set lighting options. + var lighting = gameObject.lighting; + var lightingAdditions = programManager.getAdditionsByTag('LIGHTING'); + for (var i = 0; i < lightingAdditions.length; i++) + { + var addition = lightingAdditions[i]; + addition.disable = !lighting; + } + + if (lighting) + { + var defineLightsAddition = programManager.getAddition('DefineLights'); + if (defineLightsAddition) + { + defineLightsAddition.additions.fragmentDefine = + '#define LIGHT_COUNT ' + this.manager.renderer.config.maxLights; + } + } + + // Set self-shadow options. + var selfShadow = gameObject.selfShadow.enabled; + if (selfShadow === null) + { + selfShadow = gameObject.scene.sys.game.config.selfShadow; + } + if (selfShadow) + { + programManager.addFeature('SELFSHADOW'); + } + else + { + programManager.removeFeature('SELFSHADOW'); + } + + // Set smooth pixel art options. + var smoothPixelArt = texture.smoothPixelArt; + if (smoothPixelArt === null) + { + smoothPixelArt = gameObject.scene.sys.game.config.smoothPixelArt; + } + var smoothPixelArtAddition = programManager.getAddition('SmoothPixelArt'); + if (smoothPixelArtAddition) + { + smoothPixelArtAddition.disable = !smoothPixelArt; + } + + // Set up border filtering options. + var borderFilter = texture.source[0].glTexture.magFilter === this.manager.renderer.gl.LINEAR; + if (borderFilter) + { + programManager.addFeature('BORDERFILTER'); + } + else + { + programManager.removeFeature('BORDERFILTER'); + } + }, + + /** + * Render a TilemapGPULayer object. + * + * @method Phaser.Renderer.WebGL.RenderNodes.SubmitterTilemapGPULayer#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.Tilemaps.TilemapGPULayer} tilemapLayer - The TilemapGPULayer being rendered. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - The parent matrix describing the game object's context. + */ + run: function ( + drawingContext, + tilemapLayer, + parentMatrix + ) + { + var manager = this.manager; + var renderer = manager.renderer; + + manager.startStandAloneRender(); + + this.onRunBegin(drawingContext); + + // Transform layer quad. + var camera = drawingContext.camera; + var spriteMatrix = this._spriteMatrix; + var calcMatrix = this._calcMatrix; + var quad = this._quad; + + var x = tilemapLayer.x; + var y = tilemapLayer.y; + var width = tilemapLayer.width; + var height = tilemapLayer.height; + + calcMatrix.copyWithScrollFactorFrom( + camera.matrix, + camera.scrollX, camera.scrollY, + tilemapLayer.scrollFactorX, tilemapLayer.scrollFactorY + ); + + if (parentMatrix) + { + calcMatrix.multiply(parentMatrix); + } + + spriteMatrix.applyITRS(x, y, 0, tilemapLayer.scaleX, tilemapLayer.scaleY); + + // Multiply by the Sprite matrix + calcMatrix.multiply(spriteMatrix); + + // Compute output quad. + calcMatrix.setQuad( + x, + y, + x + width, + y + height, + quad + ); + + // Populate vertex buffer. + var stride = this.vertexBufferLayout.layout.stride; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexF32 = vertexBuffer.viewF32; + var offset32 = 0; + + // Bottom Left. + vertexF32[offset32++] = quad[2]; + vertexF32[offset32++] = quad[3]; + vertexF32[offset32++] = 0; + vertexF32[offset32++] = 0; + + // Top Left. + vertexF32[offset32++] = quad[0]; + vertexF32[offset32++] = quad[1]; + vertexF32[offset32++] = 0; + vertexF32[offset32++] = 1; + + // Bottom Right. + vertexF32[offset32++] = quad[4]; + vertexF32[offset32++] = quad[5]; + vertexF32[offset32++] = 1; + vertexF32[offset32++] = 0; + + // Top Right. + vertexF32[offset32++] = quad[6]; + vertexF32[offset32++] = quad[7]; + vertexF32[offset32++] = 1; + vertexF32[offset32++] = 1; + + // Update vertex buffer. + // Because we are probably using a generic vertex buffer + // which is larger than the current batch, we need to update + // the buffer with the correct size. + vertexBuffer.update(stride * 4); + + // Assemble textures. + var tileset = tilemapLayer.tileset; + var mainGlTexture = tileset.glTexture; + var animated = tileset.getAnimationDataIndexMap(renderer).size > 0; + + var textures = [ + mainGlTexture, + tilemapLayer.layerDataTexture + ]; + + if (animated) + { + textures[2] = tileset.getAnimationDataTexture(renderer); + } + + if (tilemapLayer.lighting) + { + var texture = tileset.image; + var normalMap = texture.dataSource[0]; + if (!normalMap) + { + normalMap = this.manager.renderer.normalTexture; + } + else + { + normalMap = normalMap.glTexture; + } + textures[3] = normalMap; + } + + this.updateRenderOptions(tilemapLayer); + + var programManager = this.programManager; + var programSuite = programManager.getCurrentProgramSuite(); + + if (programSuite) + { + var program = programSuite.program; + var vao = programSuite.vao; + + this.setupUniforms(drawingContext, tilemapLayer); + programManager.applyUniforms(program); + + // Render layer. + renderer.drawElements( + drawingContext, + textures, + program, + vao, + 4, + 0 + ); + } + + this.onRunEnd(drawingContext); + } +}); + +module.exports = SubmitterTilemapGPULayer; + + +/***/ }), + +/***/ 12913: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which handles texturing for a single Image-like GameObject. + * + * This node stores values relevant to texturing, such as UVs and frame data. + * These values should be read off before the node is reused. + * + * @class TexturerImage + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var TexturerImage = new Class({ + Extends: RenderNode, + + initialize: function TexturerImage (manager) + { + RenderNode.call(this, 'TexturerImage', manager); + + /** + * The frame data of the GameObject being rendered. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TexturerImage#frame + * @type {Phaser.Textures.Frame} + * @since 4.0.0 + */ + this.frame = null; + + /** + * The width of the frame. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TexturerImage#frameWidth + * @type {number} + * @since 4.0.0 + */ + this.frameWidth = 0; + + /** + * The height of the frame. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TexturerImage#frameHeight + * @type {number} + * @since 4.0.0 + */ + this.frameHeight = 0; + + /** + * The object where UV coordinates and frame coordinates are stored. + * This is either a Frame or a Crop object. + * + * It should have the properties u0, v0, u1, v1, x, y. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TexturerImage#uvSource + * @type {Phaser.Textures.Frame|Phaser.GameObjects.Components.Crop} + * @since 4.0.0 + */ + this.uvSource = null; + }, + + /** + * Set this RenderNode to temporarily store the texture data for the given + * GameObject. Ensure that it is used before the node is reused. + * + * @method Phaser.Renderer.WebGL.RenderNodes.TexturerImage#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Image} gameObject - The GameObject being rendered. + * @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads. It is unused here. + */ + run: function (drawingContext, gameObject, element) + { + this.onRunBegin(drawingContext); + + var frame = gameObject.frame; + this.frame = frame; + + this.frameWidth = frame.cutWidth; + this.frameHeight = frame.cutHeight; + + this.uvSource = frame; + if (gameObject.isCropped) + { + var crop = gameObject._crop; + this.uvSource = crop; + + if (crop.flipX !== gameObject.flipX || crop.flipY !== gameObject.flipY) + { + gameObject.frame.updateCropUVs(crop, gameObject.flipX, gameObject.flipY); + } + + // Modify the frame dimensions based on the crop. + this.frameWidth = crop.width; + this.frameHeight = crop.height; + } + + var resolution = frame.source.resolution; + this.frameWidth /= resolution; + this.frameHeight /= resolution; + + this.onRunEnd(drawingContext); + } +}); + +module.exports = TexturerImage; + + +/***/ }), + +/***/ 22995: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); +var Class = __webpack_require__(83419); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which handles texturing for a single TileSprite GameObject. + * + * This node stores values relevant to texturing, such as UVs and frame data. + * These values should be read off before the node is reused. + * + * @class TexturerTileSprite + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + */ +var TexturerTileSprite = new Class({ + Extends: RenderNode, + + initialize: function TexturerTileSprite (manager) + { + RenderNode.call(this, 'TexturerTileSprite', manager); + + /** + * The frame data of the GameObject being rendered. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TexturerTileSprite#frame + * @type {Phaser.Textures.Frame} + * @since 4.0.0 + */ + this.frame = null; + + /** + * The matrix used internally to compute UV coordinates. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TexturerTileSprite#uvMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + */ + this.uvMatrix = new TransformMatrix(); + }, + + /** + * Set this RenderNode to temporarily store the texture data for the given + * GameObject. Ensure that it is used before the node is reused. + * + * @method Phaser.Renderer.WebGL.RenderNodes.TexturerTileSprite#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Image} gameObject - The GameObject being rendered. + * @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads. It is unused here. + */ + run: function (drawingContext, gameObject, element) + { + this.onRunBegin(drawingContext); + + var frame = gameObject.frame; + this.frame = frame; + + if (gameObject.isCropped) + { + var crop = gameObject._crop; + + if (crop.flipX !== gameObject.flipX || crop.flipY !== gameObject.flipY) + { + gameObject.frame.updateCropUVs(crop, gameObject.flipX, gameObject.flipY); + } + + // TODO: Is there any other crop logic to consider? + } + + // Compute UVs. + + this.uvMatrix.loadIdentity(); + + // // Normalize coordinate space. + this.uvMatrix.scale(1 / frame.width, 1 / frame.height); + + // Apply texture transformation in TSR order. + // This is necessary to avoid skew. + this.uvMatrix.translate(gameObject.tilePositionX, gameObject.tilePositionY); + this.uvMatrix.scale(1 / gameObject.tileScaleX, 1 / gameObject.tileScaleY); + this.uvMatrix.rotate(-gameObject.tileRotation); + + // Find where the GameObject area sits in normalized space. + this.uvMatrix.setQuad(0, 0, gameObject.width, gameObject.height); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = TexturerTileSprite; + + +/***/ }), + +/***/ 86081: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); +var Class = __webpack_require__(83419); +var Merge = __webpack_require__(46975); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which handles transformation data for a single Image-like GameObject. + * + * @class TransformerImage + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {object} [config] - The configuration object for this RenderNode. + */ +var TransformerImage = new Class({ + Extends: RenderNode, + + initialize: function TransformerImage (manager, config) + { + config = Merge(config || {}, this.defaultConfig); + + RenderNode.call(this, config.name, manager); + + /** + * The matrix used to store the final quad data for rendering. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerImage#quad + * @type {Float32Array} + * @since 4.0.0 + */ + this.quad = new Float32Array(8); + + /** + * Whether the transform only translates. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerImage#onlyTranslate + * @type {boolean} + * @since 4.0.0 + */ + this.onlyTranslate = false; + + /** + * The matrix used internally to compute sprite transforms. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerImage#_spriteMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + * @private + */ + this._spriteMatrix = new TransformMatrix(); + + /** + * The matrix used internally to compute the final transform. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerImage#_calcMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + * @private + */ + this._calcMatrix = new TransformMatrix(); + }, + + defaultConfig: { + name: 'TransformerImage', + role: 'Transformer' + }, + + /** + * Stores the transform data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.TransformerImage#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} texturerNode - The texturer node used to texture the GameObject. This contains relevant data on the dimensions of the object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested. + * @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads. It is unused here. + */ + run: function (drawingContext, gameObject, texturerNode, parentMatrix, element) + { + this.onRunBegin(drawingContext); + + var frame = texturerNode.frame; + var uvSource = texturerNode.uvSource; + + var frameX = uvSource.x; + var frameY = uvSource.y; + + var displayOriginX = gameObject.displayOriginX; + var displayOriginY = gameObject.displayOriginY; + + var x = -displayOriginX + frameX; + var y = -displayOriginY + frameY; + + var customPivot = frame.customPivot; + + var flipX = 1; + var flipY = 1; + + if (gameObject.flipX) + { + if (!customPivot) + { + x += (-frame.realWidth + (displayOriginX * 2)); + } + + flipX = -1; + } + + if (gameObject.flipY) + { + if (!customPivot) + { + y += (-frame.realHeight + (displayOriginY * 2)); + } + + flipY = -1; + } + + var camera = drawingContext.camera; + var spriteMatrix = this._spriteMatrix; + var calcMatrix = this._calcMatrix.copyWithScrollFactorFrom( + camera.getViewMatrix(!drawingContext.useCanvas), + camera.scrollX, camera.scrollY, + gameObject.scrollFactorX, gameObject.scrollFactorY + ); + + if (parentMatrix) + { + calcMatrix.multiply(parentMatrix); + } + + spriteMatrix.applyITRS( + gameObject.x, gameObject.y, + gameObject.rotation, + gameObject.scaleX * flipX, gameObject.scaleY * flipY + ); + + calcMatrix.multiply(spriteMatrix); + + // Determine whether the matrix does not rotate, scale, or skew. + // Keyword: #OnlyTranslate + var cmm = calcMatrix.matrix; + this.onlyTranslate = cmm[0] === 1 && cmm[1] === 0 && cmm[2] === 0 && cmm[3] === 1; + + // Store the output quad. + calcMatrix.setQuad( + x, + y, + x + texturerNode.frameWidth, + y + texturerNode.frameHeight, + this.quad + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = TransformerImage; + + +/***/ }), + +/***/ 88383: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); +var Class = __webpack_require__(83419); +var Merge = __webpack_require__(46975); +var RenderNode = __webpack_require__(6141); + +/** + * @classdesc + * A RenderNode which handles transformation data for a single Stamp-like GameObject. + * + * This is a modified version of the TransformerImage class. + * It skips the camera matrix. + * + * @class TransformerStamp + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {object} [config] - The configuration object for this RenderNode. + */ +var TransformerStamp = new Class({ + + Extends: RenderNode, + + initialize: function TransformerStamp (manager, config) + { + config = Merge(config || {}, this.defaultConfig); + + RenderNode.call(this, config.name, manager); + + /** + * The matrix used internally to compute sprite transforms. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerStamp#_spriteMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @since 4.0.0 + * @private + */ + this._spriteMatrix = new TransformMatrix(); + + /** + * The matrix used to store the final quad data for rendering. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerStamp#quad + * @type {Float32Array} + * @since 4.0.0 + */ + this.quad = this._spriteMatrix.quad; + + /** + * Whether the transform only translates. + * + * @name Phaser.Renderer.WebGL.RenderNodes.TransformerStamp#onlyTranslate + * @type {boolean} + * @since 4.0.0 + */ + this.onlyTranslate = false; + }, + + defaultConfig: { + name: 'TransformerStamp', + role: 'Transformer' + }, + + /** + * Stores the transform data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.TransformerStamp#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} texturerNode - The texturer node used to texture the GameObject. This contains relevant data on the dimensions of the object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested. It is unused here. + * @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads. It is unused here. + */ + run: function (drawingContext, gameObject, texturerNode, parentMatrix, element) + { + this.onRunBegin(drawingContext); + + var frame = texturerNode.frame; + var uvSource = texturerNode.uvSource; + + var frameX = uvSource.x; + var frameY = uvSource.y; + + var displayOriginX = gameObject.displayOriginX; + var displayOriginY = gameObject.displayOriginY; + + var x = -displayOriginX + frameX; + var y = -displayOriginY + frameY; + + var customPivot = frame.customPivot; + + var flipX = 1; + var flipY = 1; + + if (gameObject.flipX) + { + if (!customPivot) + { + x += (-frame.realWidth + (displayOriginX * 2)); + } + + flipX = -1; + } + + if (gameObject.flipY) + { + if (!customPivot) + { + y += (-frame.realHeight + (displayOriginY * 2)); + } + + flipY = -1; + } + + var gx = gameObject.x; + var gy = gameObject.y; + + var spriteMatrix = this._spriteMatrix; + + spriteMatrix.applyITRS(gx, gy, gameObject.rotation, gameObject.scaleX * flipX, gameObject.scaleY * flipY); + + // Determine whether the matrix does not rotate, scale, or skew. + var m = spriteMatrix.matrix; + this.onlyTranslate = m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1; + + // Store the output quad. + spriteMatrix.setQuad( + x, + y, + x + texturerNode.frameWidth, + y + texturerNode.frameHeight + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = TransformerStamp; + + +/***/ }), + +/***/ 34454: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var TransformerImage = __webpack_require__(86081); + +/** + * @classdesc + * A RenderNode which handles transformation data for a single Tile within a TilemapLayer. + * + * @class TransformerTile + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.TransformerImage + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {object} [config] - The configuration object for this RenderNode. + */ +var TransformerTile = new Class({ + Extends: TransformerImage, + + initialize: function TransformerTile (manager, config) + { + TransformerImage.call(this, manager, config); + }, + + defaultConfig: { + name: 'TransformerTile', + role: 'Transformer' + }, + + /** + * Stores the transform data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.TransformerTile#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} texturerNode - The texturer node used to texture the GameObject. This contains relevant data on the dimensions of the object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested. + * @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads. It is unused here. + */ + run: function (drawingContext, gameObject, texturerNode, parentMatrix, element) + { + this.onRunBegin(drawingContext); + + var camera = drawingContext.camera; + var calcMatrix = this._calcMatrix; + var spriteMatrix = this._spriteMatrix; + + // Get view matrix. + calcMatrix.copyWithScrollFactorFrom( + camera.getViewMatrix(!drawingContext.useCanvas), + camera.scrollX, camera.scrollY, + gameObject.scrollFactorX, gameObject.scrollFactorY + ); + + if (parentMatrix) + { + calcMatrix.multiply(parentMatrix); + } + + var frameWidth = texturerNode.frameWidth; + var frameHeight = texturerNode.frameHeight; + + var width = frameWidth; + var height = frameHeight; + + var halfWidth = frameWidth / 2; + var halfHeight = frameHeight / 2; + + var sx = gameObject.scaleX; + var sy = gameObject.scaleY; + + var tileset = gameObject.gidMap[element.index]; + + // TODO: Is the tileset missing? + + var tOffsetX = tileset.tileOffset.x; + var tOffsetY = tileset.tileOffset.y; + + var srcX = gameObject.x + element.pixelX * sx + (halfWidth * sx - tOffsetX); + var srcY = gameObject.y + element.pixelY * sy + (halfHeight * sy - tOffsetY); + + var x = - halfWidth; + var y = - halfHeight; + + if (element.flipX) + { + width *= -1; + x += frameWidth; + } + + if (element.flipY) + { + height *= -1; + x += frameHeight; + } + + spriteMatrix.applyITRS( + srcX, + srcY, + element.rotation, + sx, + sy + ); + + // Multiply by the Sprite matrix + calcMatrix.multiply(spriteMatrix); + + // Determine whether the matrix does not rotate, scale, or skew. + var cmm = calcMatrix.matrix; + this.onlyTranslate = cmm[0] === 1 && cmm[1] === 0 && cmm[2] === 0 && cmm[3] === 1; + + calcMatrix.setQuad( + x, + y, + x + width, + y + height, + this.quad + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = TransformerTile; + + +/***/ }), + +/***/ 46211: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var TransformerImage = __webpack_require__(86081); + +/** + * @classdesc + * A RenderNode which handles transformation data for a single TileSprite GameObject. + * + * @class TransformerTileSprite + * @memberof Phaser.Renderer.WebGL.RenderNodes + * @constructor + * @since 4.0.0 + * @extends Phaser.Renderer.WebGL.RenderNodes.TransformerImage + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode. + * @param {object} [config] - The configuration object for this RenderNode. + */ +var TransformerTileSprite = new Class({ + Extends: TransformerImage, + + initialize: function TransformerTileSprite (manager, config) + { + TransformerImage.call(this, manager, config); + }, + + defaultConfig: { + name: 'TransformerTileSprite', + role: 'Transformer' + }, + + /** + * Stores the transform data for rendering. + * + * @method Phaser.Renderer.WebGL.RenderNodes.TransformerTileSprite#run + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.GameObject} gameObject - The GameObject being rendered. + * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} [texturerNode] - The texturer node used to texture the GameObject. This contains relevant data on the dimensions of the object. It is unused here. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested. + * @param {object} [element] - The specific element within the game object. This is used for objects that consist of multiple quads. It is unused here. + */ + run: function (drawingContext, gameObject, texturerNode, parentMatrix, element) + { + this.onRunBegin(drawingContext); + + // Unlike TransformerImage, the dimensions of a TileSprite are not + // derived from the frame, but from the GameObject itself. + + var width = gameObject.width; + var height = gameObject.height; + + var displayOriginX = gameObject.displayOriginX; + var displayOriginY = gameObject.displayOriginY; + + var x = -displayOriginX; + var y = -displayOriginY; + + var flipX = 1; + var flipY = 1; + + if (gameObject.flipX) + { + x += (-width + (displayOriginX * 2)); + + flipX = -1; + } + + if (gameObject.flipY) + { + y += (-height + (displayOriginY * 2)); + + flipY = -1; + } + + var gx = gameObject.x; + var gy = gameObject.y; + + var camera = drawingContext.camera; + var calcMatrix = this._calcMatrix; + var spriteMatrix = this._spriteMatrix; + + calcMatrix.copyWithScrollFactorFrom( + camera.getViewMatrix(!drawingContext.useCanvas), + camera.scrollX, camera.scrollY, + gameObject.scrollFactorX, gameObject.scrollFactorY + ); + + if (parentMatrix) + { + calcMatrix.multiply(parentMatrix); + } + + spriteMatrix.applyITRS( + gx, gy, + gameObject.rotation, + gameObject.scaleX * flipX, gameObject.scaleY * flipY + ); + + calcMatrix.multiply(spriteMatrix); + + // Determine whether the matrix does not rotate, scale, or skew. + var cmm = calcMatrix.matrix; + this.onlyTranslate = cmm[0] === 1 && cmm[1] === 0 && cmm[2] === 0 && cmm[3] === 1; + + // Store the output quad. + calcMatrix.setQuad( + x, + y, + x + width, + y + height, + this.quad + ); + + this.onRunEnd(drawingContext); + } +}); + +module.exports = TransformerTileSprite; + + +/***/ }), + +/***/ 84547: +/***/ ((module) => { + +module.exports = [ + 'vec4 applyLighting (vec4 fragColor, vec3 normal)', + '{', + ' vec4 lighting = getLighting(fragColor, normal);', + ' return fragColor * vec4(lighting.rgb * lighting.a, lighting.a);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 11104: +/***/ ((module) => { + +module.exports = [ + 'vec4 applyTint(vec4 texture)', + '{', + ' vec4 texel = vec4(outTint.bgr * outTint.a, outTint.a);', + ' vec4 color = texture * texel;', + ' if (outTintEffect == 1.0)', + ' {', + ' color.rgb = mix(texture.rgb, outTint.bgr * outTint.a, texture.a);', + ' }', + ' else if (outTintEffect == 2.0)', + ' {', + ' color = texel;', + ' }', + ' return color;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 81556: +/***/ ((module) => { + +module.exports = [ + 'vec4 boundedSampler(sampler2D sampler, vec2 uv)', + '{', + ' if (clamp(uv, 0.0, 1.0) != uv)', + ' {', + ' return vec4(0.0, 0.0, 0.0, 0.0);', + ' }', + ' return texture2D(sampler, uv);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 96293: +/***/ ((module) => { + +module.exports = [ + '#define SHADER_NAME PHASER_COLORMATRIX_FS', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform float uColorMatrix[20];', + 'uniform float uAlpha;', + 'varying vec2 outTexCoord;', + 'void main ()', + '{', + ' vec4 c = texture2D(uMainSampler, outTexCoord);', + ' if (uAlpha == 0.0)', + ' {', + ' gl_FragColor = c;', + ' return;', + ' }', + ' if (c.a > 0.0)', + ' {', + ' c.rgb /= c.a;', + ' }', + ' vec4 result;', + ' result.r = (uColorMatrix[0] * c.r) + (uColorMatrix[1] * c.g) + (uColorMatrix[2] * c.b) + (uColorMatrix[3] * c.a) + uColorMatrix[4];', + ' result.g = (uColorMatrix[5] * c.r) + (uColorMatrix[6] * c.g) + (uColorMatrix[7] * c.b) + (uColorMatrix[8] * c.a) + uColorMatrix[9];', + ' result.b = (uColorMatrix[10] * c.r) + (uColorMatrix[11] * c.g) + (uColorMatrix[12] * c.b) + (uColorMatrix[13] * c.a) + uColorMatrix[14];', + ' result.a = (uColorMatrix[15] * c.r) + (uColorMatrix[16] * c.g) + (uColorMatrix[17] * c.b) + (uColorMatrix[18] * c.a) + uColorMatrix[19];', + ' vec3 rgb = mix(c.rgb, result.rgb, uAlpha);', + ' rgb *= result.a;', + ' gl_FragColor = vec4(rgb, result.a);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 78390: +/***/ ((module) => { + +module.exports = [ + 'vec2 v2len (vec2 a, vec2 b)', + '{', + ' return sqrt(a*a+b*b);', + '}', + 'vec2 getBlockyTexCoord (vec2 texCoord, vec2 texRes) {', + ' texCoord *= texRes;', + ' vec2 seam = floor(texCoord + 0.5);', + ' texCoord = (texCoord - seam) / v2len(dFdx(texCoord), dFdy(texCoord)) + seam;', + ' texCoord = clamp(texCoord, seam-.5, seam+.5);', + ' return texCoord / texRes;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 11719: +/***/ ((module) => { + +module.exports = [ + 'struct Light', + '{', + ' vec3 position;', + ' vec3 color;', + ' float intensity;', + ' float radius;', + '};', + 'const int kMaxLights = LIGHT_COUNT;', + 'uniform vec4 uCamera; /* x, y, rotation, zoom */', + 'uniform sampler2D uNormSampler;', + 'uniform vec3 uAmbientLightColor;', + 'uniform Light uLights[kMaxLights];', + 'uniform int uLightCount;', + '#ifdef FEATURE_SELFSHADOW', + 'uniform float uDiffuseFlatThreshold;', + 'uniform float uPenumbra;', + '#endif', + 'vec4 getLighting (vec4 fragColor, vec3 normal)', + '{', + ' vec3 finalColor = vec3(0.0);', + ' vec2 res = vec2(min(uResolution.x, uResolution.y)) * uCamera.w;', + ' #ifdef FEATURE_SELFSHADOW', + ' vec3 unpremultipliedColor = fragColor.rgb / fragColor.a;', + ' float occlusionThreshold = 1.0 - ((unpremultipliedColor.r + unpremultipliedColor.g + unpremultipliedColor.b) / uDiffuseFlatThreshold);', + ' #endif', + ' for (int index = 0; index < kMaxLights; ++index)', + ' {', + ' if (index < uLightCount)', + ' {', + ' Light light = uLights[index];', + ' vec3 lightDir = vec3((light.position.xy / res) - (gl_FragCoord.xy / res), light.position.z / res.x);', + ' vec3 lightNormal = normalize(lightDir);', + ' float distToSurf = length(lightDir) * uCamera.w;', + ' float diffuseFactor = max(dot(normal, lightNormal), 0.0);', + ' float radius = (light.radius / res.x * uCamera.w) * uCamera.w;', + ' float attenuation = clamp(1.0 - distToSurf * distToSurf / (radius * radius), 0.0, 1.0);', + ' #ifdef FEATURE_SELFSHADOW', + ' float occluded = smoothstep(0.0, 1.0, (diffuseFactor - occlusionThreshold) / uPenumbra);', + ' vec3 diffuse = light.color * diffuseFactor * occluded;', + ' #else', + ' vec3 diffuse = light.color * diffuseFactor;', + ' #endif', + ' finalColor += (attenuation * diffuse) * light.intensity;', + ' }', + ' }', + ' vec4 colorOutput = vec4(uAmbientLightColor + finalColor, 1.0);', + ' return colorOutput;', + '}' +].join('\n'); + + +/***/ }), + +/***/ 14030: +/***/ ((module) => { + +module.exports = [ + 'vec2 clampTexCoordWithinFrame (vec2 texCoord)', + '{', + ' vec2 texRes = getTexRes();', + ' vec4 frameTexel = outFrame * texRes.xyxy;', + ' vec2 frameMin = frameTexel.xy + vec2(0.5, 0.5);', + ' vec2 frameMax = frameTexel.xy + frameTexel.zw - vec2(0.5, 0.5);', + ' return clamp(texCoord, frameMin / texRes, frameMax / texRes);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 10235: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform float amount;', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(fragmentHeader)', + 'vec2 Distort(vec2 p)', + '{', + ' float theta = atan(p.y, p.x);', + ' float radius = length(p);', + ' radius = pow(radius, amount);', + ' p.x = radius * cos(theta);', + ' p.y = radius * sin(theta);', + ' return 0.5 * (p + 1.0);', + '}', + 'void main()', + '{', + ' vec2 xy = 2.0 * outTexCoord - 1.0;', + ' vec2 texCoord = outTexCoord;', + ' if (length(xy) < 1.0)', + ' {', + ' texCoord = Distort(xy);', + ' }', + ' gl_FragColor = boundedSampler(uMainSampler, texCoord);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 65980: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform sampler2D uMainSampler2;', + 'uniform float amount;', + 'uniform vec4 color;', + 'varying vec2 outTexCoord;', + 'vec4 NORMAL (vec4 base, vec4 blend)', + '{', + ' return blend + base * (1.0 - blend.a);', + '}', + 'vec4 ADD (vec4 base, vec4 blend)', + '{', + ' return base + blend;', + '}', + 'vec4 MULTIPLY (vec4 base, vec4 blend)', + '{', + ' return base * blend;', + '}', + 'vec4 SCREEN (vec4 base, vec4 blend)', + '{', + ' return 1.0 - (1.0 - base) * (1.0 - blend);', + '}', + 'float overlayChannel (float base, float blend)', + '{', + ' return base < 0.5 ? 2.0 * base * blend : 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);', + '}', + 'vec4 OVERLAY (vec4 base, vec4 blend)', + '{', + ' return vec4(', + ' overlayChannel(base.r, blend.r),', + ' overlayChannel(base.g, blend.g),', + ' overlayChannel(base.b, blend.b),', + ' overlayChannel(base.a, blend.a)', + ' );', + '}', + 'vec4 DARKEN (vec4 base, vec4 blend)', + '{', + ' return min(base, blend);', + '}', + 'vec4 LIGHTEN (vec4 base, vec4 blend)', + '{', + ' return max(base, blend);', + '}', + 'float dodgeChannel (float base, float blend)', + '{', + ' return blend == 1.0 ? blend : min(1.0, base / (1.0 - blend));', + '}', + 'vec4 COLOR_DODGE (vec4 base, vec4 blend)', + '{', + ' return vec4(', + ' dodgeChannel(base.r, blend.r),', + ' dodgeChannel(base.g, blend.g),', + ' dodgeChannel(base.b, blend.b),', + ' dodgeChannel(base.a, blend.a)', + ' );', + '}', + 'float burnChannel (float base, float blend)', + '{', + ' return blend == 0.0 ? blend : 1.0 - min(1.0, (1.0 - base) / blend);', + '}', + 'vec4 COLOR_BURN (vec4 base, vec4 blend)', + '{', + ' return vec4(', + ' burnChannel(base.r, blend.r),', + ' burnChannel(base.g, blend.g),', + ' burnChannel(base.b, blend.b),', + ' burnChannel(base.a, blend.a)', + ' );', + '}', + 'float hardLightChannel (float base, float blend)', + '{', + ' return blend < 0.5 ? 2.0 * base * blend : 1.0 - 2.0 * (1.0 - base) * (1.0 - blend);', + '}', + 'vec4 HARD_LIGHT (vec4 base, vec4 blend)', + '{', + ' return vec4(', + ' hardLightChannel(base.r, blend.r),', + ' hardLightChannel(base.g, blend.g),', + ' hardLightChannel(base.b, blend.b),', + ' hardLightChannel(base.a, blend.a)', + ' );', + '}', + 'float softLightChannel (float base, float blend)', + '{', + ' return blend < 0.5 ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend));', + '}', + 'vec4 SOFT_LIGHT (vec4 base, vec4 blend)', + '{', + ' return vec4(', + ' softLightChannel(base.r, blend.r),', + ' softLightChannel(base.g, blend.g),', + ' softLightChannel(base.b, blend.b),', + ' softLightChannel(base.a, blend.a)', + ' );', + '}', + 'vec4 DIFFERENCE (vec4 base, vec4 blend)', + '{', + ' return abs(base - blend);', + '}', + 'vec4 EXCLUSION (vec4 base, vec4 blend)', + '{', + ' return base + blend - 2.0 * base * blend;', + '}', + 'vec3 rgbToHsl (vec3 color)', + '{', + ' vec3 hsl = vec3(0.0);', + ' float fmin = min(min(color.r, color.g), color.b);', + ' float fmax = max(max(color.r, color.g), color.b);', + ' float delta = fmax - fmin;', + ' hsl.z = (fmax + fmin) / 2.0;', + ' if (delta == 0.0)', + ' {', + ' hsl.x = 0.0;', + ' hsl.y = 0.0;', + ' }', + ' else', + ' {', + ' if (hsl.z < 0.5)', + ' {', + ' hsl.y = delta / (fmax + fmin);', + ' }', + ' else', + ' {', + ' hsl.y = delta / (2.0 - fmax - fmin);', + ' }', + ' float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;', + ' float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;', + ' float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;', + ' if (color.r == fmax)', + ' {', + ' hsl.x = deltaB - deltaG;', + ' }', + ' else if (color.g == fmax)', + ' {', + ' hsl.x = (1.0 / 3.0) + deltaR - deltaB;', + ' }', + ' else if (color.b == fmax)', + ' {', + ' hsl.x = (2.0 / 3.0) + deltaG - deltaR;', + ' }', + ' if (hsl.x < 0.0)', + ' {', + ' hsl.x += 1.0;', + ' }', + ' else if (hsl.x > 1.0)', + ' {', + ' hsl.x -= 1.0;', + ' }', + ' }', + ' return hsl;', + '}', + 'vec3 hslToRgb (vec3 hsl)', + '{', + ' float p = hsl.z * (1.0 - hsl.y);', + ' float q = hsl.z * (1.0 - hsl.y * hsl.x);', + ' float t = hsl.z * (1.0 - hsl.y * (1.0 - hsl.x));', + ' if (hsl.x < 1.0 / 6.0)', + ' {', + ' return vec3(hsl.z, t, p);', + ' }', + ' else if (hsl.x < 0.5)', + ' {', + ' return vec3(q, hsl.z, p);', + ' }', + ' else if (hsl.x < 2.0 / 3.0)', + ' {', + ' return vec3(p, hsl.z, t);', + ' }', + ' return vec3(p, q, hsl.z);', + '}', + 'vec4 HUE (vec4 base, vec4 blend)', + '{', + ' vec3 baseHSL = rgbToHsl(base.rgb);', + ' vec3 blendHSL = rgbToHsl(blend.rgb);', + ' return vec4(hslToRgb(vec3(blendHSL.x, baseHSL.y, baseHSL.z)), base.a);', + '}', + 'vec4 SATURATION (vec4 base, vec4 blend)', + '{', + ' vec3 baseHSL = rgbToHsl(base.rgb);', + ' vec3 blendHSL = rgbToHsl(blend.rgb);', + ' return vec4(hslToRgb(vec3(baseHSL.x, blendHSL.y, baseHSL.z)), base.a);', + '}', + 'vec4 COLOR (vec4 base, vec4 blend)', + '{', + ' vec3 baseHSL = rgbToHsl(base.rgb);', + ' vec3 blendHSL = rgbToHsl(blend.rgb);', + ' return vec4(hslToRgb(vec3(blendHSL.x, blendHSL.y, baseHSL.z)), base.a);', + '}', + 'vec4 LUMINOSITY (vec4 base, vec4 blend)', + '{', + ' vec3 baseHSL = rgbToHsl(base.rgb);', + ' vec3 blendHSL = rgbToHsl(blend.rgb);', + ' return vec4(hslToRgb(vec3(baseHSL.x, baseHSL.y, blendHSL.z)), base.a);', + '}', + 'vec4 ERASE (vec4 base, vec4 blend)', + '{', + ' return base * (1.0 - blend.a);', + '}', + 'vec4 SOURCE_IN (vec4 base, vec4 blend)', + '{', + ' return blend * base.a;', + '}', + 'vec4 SOURCE_OUT (vec4 base, vec4 blend)', + '{', + ' return blend * (1.0 - base.a);', + '}', + 'vec4 SOURCE_ATOP (vec4 base, vec4 blend)', + '{', + ' return base * (1.0 - blend.a) + blend * base.a;', + '}', + 'vec4 DESTINATION_OVER (vec4 base, vec4 blend)', + '{', + ' return base + blend * (1.0 - base.a);', + '}', + 'vec4 DESTINATION_IN (vec4 base, vec4 blend)', + '{', + ' return base * blend.a;', + '}', + 'vec4 DESTINATION_OUT (vec4 base, vec4 blend)', + '{', + ' return base * (1.0 - blend.a);', + '}', + 'vec4 DESTINATION_ATOP (vec4 base, vec4 blend)', + '{', + ' return base * blend.a + blend * (1.0 - base.a);', + '}', + 'vec4 LIGHTER (vec4 base, vec4 blend)', + '{', + ' return ADD(base, blend);', + '}', + 'vec4 COPY (vec4 base, vec4 blend)', + '{', + ' return blend;', + '}', + 'vec4 XOR (vec4 base, vec4 blend)', + '{', + ' return base * (1.0 - blend.a) + blend * (1.0 - base.a);', + '}', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec4 base = boundedSampler(uMainSampler, outTexCoord);', + ' vec4 blend = boundedSampler(uMainSampler2, outTexCoord) * color;', + ' vec4 blended = BLEND(base, blend);', + ' gl_FragColor = mix(base, blended, amount);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 20784: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform vec2 resolution;', + 'uniform vec2 offset;', + 'uniform float strength;', + 'uniform vec3 color;', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec2 uv = outTexCoord;', + ' vec4 col = vec4(0.0);', + ' vec2 off1 = vec2(1.411764705882353) * offset * strength;', + ' vec2 off2 = vec2(3.2941176470588234) * offset * strength;', + ' vec2 off3 = vec2(5.176470588235294) * offset * strength;', + ' col += boundedSampler(uMainSampler, uv) * 0.1964825501511404;', + ' col += boundedSampler(uMainSampler, uv + (off1 / resolution)) * 0.2969069646728344;', + ' col += boundedSampler(uMainSampler, uv - (off1 / resolution)) * 0.2969069646728344;', + ' col += boundedSampler(uMainSampler, uv + (off2 / resolution)) * 0.09447039785044732;', + ' col += boundedSampler(uMainSampler, uv - (off2 / resolution)) * 0.09447039785044732;', + ' col += boundedSampler(uMainSampler, uv + (off3 / resolution)) * 0.010381362401148057;', + ' col += boundedSampler(uMainSampler, uv - (off3 / resolution)) * 0.010381362401148057;', + ' gl_FragColor = col * vec4(color, 1.0);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 65122: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform vec2 resolution;', + 'uniform vec2 offset;', + 'uniform float strength;', + 'uniform vec3 color;', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec2 uv = outTexCoord;', + ' vec4 col = vec4(0.0);', + ' vec2 offset = vec2(1.333) * offset * strength;', + ' col += boundedSampler(uMainSampler, uv) * 0.29411764705882354;', + ' col += boundedSampler(uMainSampler, uv + (offset / resolution)) * 0.35294117647058826;', + ' col += boundedSampler(uMainSampler, uv - (offset / resolution)) * 0.35294117647058826;', + ' gl_FragColor = col * vec4(color, 1.0);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 60942: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform vec2 resolution;', + 'uniform vec2 offset;', + 'uniform float strength;', + 'uniform vec3 color;', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec2 uv = outTexCoord;', + ' vec4 col = vec4(0.0);', + ' vec2 off1 = vec2(1.3846153846) * offset * strength;', + ' vec2 off2 = vec2(3.2307692308) * offset * strength;', + ' col += boundedSampler(uMainSampler, uv) * 0.2270270270;', + ' col += boundedSampler(uMainSampler, uv + (off1 / resolution)) * 0.3162162162;', + ' col += boundedSampler(uMainSampler, uv - (off1 / resolution)) * 0.3162162162;', + ' col += boundedSampler(uMainSampler, uv + (off2 / resolution)) * 0.0702702703;', + ' col += boundedSampler(uMainSampler, uv - (off2 / resolution)) * 0.0702702703;', + ' gl_FragColor = col * vec4(color, 1.0);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 43722: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + '#define ITERATIONS 100.0', + '#define ONEOVER_ITR 1.0 / ITERATIONS', + '#define PI 3.141596', + '#define GOLDEN_ANGLE 2.39996323', + 'uniform sampler2D uMainSampler;', + 'uniform vec2 resolution;', + 'uniform float radius;', + 'uniform float amount;', + 'uniform float contrast;', + 'uniform bool isTiltShift;', + 'uniform float strength;', + 'uniform vec2 blur;', + 'varying vec2 outTexCoord;', + 'vec2 Sample (in float theta, inout float r)', + '{', + ' r += 1.0 / r;', + ' return (r - 1.0) * vec2(cos(theta), sin(theta)) * 0.06;', + '}', + '#pragma phaserTemplate(fragmentHeader)', + 'vec3 Bokeh (sampler2D tex, vec2 uv, float radius)', + '{', + ' vec3 acc = vec3(0.0);', + ' vec3 div = vec3(0.0);', + ' vec2 pixel = vec2(resolution.y / resolution.x, 1.0) * radius * .025;', + ' float r = 1.0;', + ' for (float j = 0.0; j < GOLDEN_ANGLE * ITERATIONS; j += GOLDEN_ANGLE)', + ' {', + ' vec3 col = boundedSampler(tex, uv + pixel * Sample(j, r)).xyz;', + ' col = contrast > 0.0 ? col * col * (1.0 + contrast) : col;', + ' vec3 bokeh = vec3(0.5) + pow(col, vec3(10.0)) * amount;', + ' acc += col * bokeh;', + ' div += bokeh;', + ' }', + ' return acc / div;', + '}', + 'void main ()', + '{', + ' float shift = 1.0;', + ' if (isTiltShift)', + ' {', + ' vec2 uv = vec2(gl_FragCoord.xy / resolution + vec2(-0.5, -0.5)) * 2.0;', + ' float centerStrength = 1.0;', + ' shift = length(uv * blur * strength) * centerStrength;', + ' }', + ' gl_FragColor = vec4(Bokeh(uMainSampler, outTexCoord * vec2(1.0, 1.0), radius * shift), 0.0);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 19883: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform float uColorMatrix[20];', + 'uniform float uAlpha;', + 'varying vec2 outTexCoord;', + 'void main ()', + '{', + ' vec4 c = texture2D(uMainSampler, outTexCoord);', + ' if (uAlpha == 0.0)', + ' {', + ' gl_FragColor = c;', + ' return;', + ' }', + ' if (c.a > 0.0)', + ' {', + ' c.rgb /= c.a;', + ' }', + ' vec4 result;', + ' result.r = (uColorMatrix[0] * c.r) + (uColorMatrix[1] * c.g) + (uColorMatrix[2] * c.b) + (uColorMatrix[3] * c.a) + uColorMatrix[4];', + ' result.g = (uColorMatrix[5] * c.r) + (uColorMatrix[6] * c.g) + (uColorMatrix[7] * c.b) + (uColorMatrix[8] * c.a) + uColorMatrix[9];', + ' result.b = (uColorMatrix[10] * c.r) + (uColorMatrix[11] * c.g) + (uColorMatrix[12] * c.b) + (uColorMatrix[13] * c.a) + uColorMatrix[14];', + ' result.a = (uColorMatrix[15] * c.r) + (uColorMatrix[16] * c.g) + (uColorMatrix[17] * c.b) + (uColorMatrix[18] * c.a) + uColorMatrix[19];', + ' vec3 rgb = mix(c.rgb, result.rgb, uAlpha);', + ' rgb *= result.a;', + ' gl_FragColor = vec4(rgb, result.a);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 12886: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform sampler2D uDisplacementSampler;', + 'uniform vec2 amount;', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec2 disp = (-vec2(0.5, 0.5) + texture2D(uDisplacementSampler, outTexCoord).rg) * amount;', + ' gl_FragColor = boundedSampler(uMainSampler, outTexCoord + disp).rgba;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 33016: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#define DISTANCE 10.0', + '#define QUALITY 10.0', + '#pragma phaserTemplate(fragmentDefine)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'varying vec2 outTexCoord;', + 'uniform float outerStrength;', + 'uniform float innerStrength;', + 'uniform float scale;', + 'uniform vec2 resolution;', + 'uniform vec4 glowColor;', + 'uniform bool knockout;', + 'const float PI = 3.14159265358979323846264;', + 'const float MAX_ALPHA = DISTANCE * (DISTANCE + 1.0) * QUALITY / 2.0;', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec2 px = vec2(1.0 / resolution.x, 1.0 / resolution.y) * scale;', + ' float totalAlpha = 0.0;', + ' float curAngle = 0.0;', + ' vec2 direction;', + ' vec2 displaced;', + ' vec4 color;', + ' for (float curDistance = 0.0; curDistance < DISTANCE; curDistance++)', + ' {', + ' curAngle += fract(sin(dot(vec2(curDistance, outTexCoord.x + outTexCoord.y), vec2(12.9898, 78.233))) * 43758.5453);', + ' for (float i = 0.0; i < QUALITY; i++)', + ' {', + ' curAngle += PI * 2.0 / (QUALITY);', + ' direction = vec2(cos(curAngle), sin(curAngle)) * px;', + ' displaced = outTexCoord + direction * (curDistance + 1.0);', + ' color = boundedSampler(uMainSampler, displaced);', + ' totalAlpha += (DISTANCE - curDistance) * color.a;', + ' }', + ' }', + ' color = boundedSampler(uMainSampler, outTexCoord);', + ' float alphaRatio = (totalAlpha / MAX_ALPHA);', + ' float innerGlowAlpha = (1.0 - alphaRatio) * innerStrength * color.a;', + ' float innerGlowStrength = min(1.0, innerGlowAlpha);', + ' vec4 innerColor = mix(color, glowColor, innerGlowStrength);', + ' float outerGlowAlpha = alphaRatio * outerStrength * (1.0 - color.a);', + ' float outerGlowStrength = min(1.0 - innerColor.a, outerGlowAlpha);', + ' vec4 outerGlowColor = outerGlowStrength * glowColor.rgba;', + ' if (knockout)', + ' {', + ' float resultAlpha = outerGlowAlpha + innerGlowAlpha;', + ' gl_FragColor = vec4(glowColor.rgb * resultAlpha, resultAlpha);', + ' }', + ' else', + ' {', + ' gl_FragColor = innerColor + outerGlowColor;', + ' }', + '}', +].join('\n'); + + +/***/ }), + +/***/ 39603: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform sampler2D uMaskSampler;', + 'uniform bool invert;', + 'varying vec2 outTexCoord;', + 'void main ()', + '{', + ' vec4 color = texture2D(uMainSampler, outTexCoord);', + ' vec4 mask = texture2D(uMaskSampler, outTexCoord);', + ' float a = mask.a;', + ' color *= invert ? (1.0 - a) : a;', + ' gl_FragColor = color;', + '}' +].join('\n'); + + +/***/ }), + +/***/ 99191: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform vec2 resolution;', + 'uniform float amount;', + 'varying vec2 outTexCoord;', + 'void main ()', + '{', + ' float pixelSize = floor(2.0 + amount);', + ' vec2 center = pixelSize * floor(outTexCoord * resolution / pixelSize) + pixelSize * vec2(0.5, 0.5);', + ' vec2 corner1 = center + pixelSize * vec2(-0.5, -0.5);', + ' vec2 corner2 = center + pixelSize * vec2(+0.5, -0.5);', + ' vec2 corner3 = center + pixelSize * vec2(+0.5, +0.5);', + ' vec2 corner4 = center + pixelSize * vec2(-0.5, +0.5);', + ' vec4 pixel = 0.4 * texture2D(uMainSampler, center / resolution);', + ' pixel += 0.15 * texture2D(uMainSampler, corner1 / resolution);', + ' pixel += 0.15 * texture2D(uMainSampler, corner2 / resolution);', + ' pixel += 0.15 * texture2D(uMainSampler, corner3 / resolution);', + ' pixel += 0.15 * texture2D(uMainSampler, corner4 / resolution);', + ' gl_FragColor = pixel;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 69355: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'varying vec2 outTexCoord;', + 'uniform vec2 lightPosition;', + 'uniform vec4 color;', + 'uniform float decay;', + 'uniform float power;', + 'uniform float intensity;', + 'uniform int samples;', + 'const int MAX = 12;', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec4 texture = boundedSampler(uMainSampler, outTexCoord);', + ' vec2 pc = (lightPosition - outTexCoord) * intensity;', + ' float shadow = 0.0;', + ' float limit = max(float(MAX), float(samples));', + ' for (int i = 0; i < MAX; ++i)', + ' {', + ' if (i >= samples)', + ' {', + ' break;', + ' }', + ' shadow += boundedSampler(uMainSampler, outTexCoord + float(i) * decay / limit * pc).a * power;', + ' }', + ' float mask = 1.0 - texture.a;', + ' gl_FragColor = mix(texture, color, clamp(shadow * mask, 0.0, 1.0));', + '}', +].join('\n'); + + +/***/ }), + +/***/ 92636: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'uniform sampler2D uMainSampler;', + 'uniform vec4 edge1;', + 'uniform vec4 edge2;', + 'uniform vec4 invert;', + 'varying vec2 outTexCoord;', + 'void main ()', + '{', + ' vec4 color = texture2D(uMainSampler, outTexCoord);', + ' color = clamp((color - edge1) / (edge2 - edge1), 0.0, 1.0);', + ' color = mix(color, 1.0 - color, invert);', + ' gl_FragColor = color;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 73416: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#pragma phaserTemplate(fragmentDefine)', + 'uniform vec2 uResolution;', + 'varying vec4 outTint;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec4 fragColor = outTint;', + ' #pragma phaserTemplate(fragmentProcess)', + ' gl_FragColor = fragColor;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 91627: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#pragma phaserTemplate(vertexDefine)', + 'uniform mat4 uProjectionMatrix;', + 'uniform vec2 uResolution;', + 'attribute vec2 inPosition;', + 'attribute vec4 inTint;', + 'varying vec4 outTint;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(vertexHeader)', + 'void main ()', + '{', + ' gl_Position = uProjectionMatrix * vec4(inPosition, 1.0, 1.0);', + ' outTint = vec4(inTint.bgr * inTint.a, inTint.a);', + ' #pragma phaserTemplate(vertexProcess)', + '}', +].join('\n'); + + +/***/ }), + +/***/ 84220: +/***/ ((module) => { + +module.exports = [ + 'vec3 getNormalFromMap (vec2 texCoord)', + '{', + ' vec3 normalMap = texture2D(uNormSampler, texCoord).rgb;', + ' return normalize(outInverseRotationMatrix * vec3(normalMap * 2.0 - 1.0));', + '}', +].join('\n'); + + +/***/ }), + +/***/ 2860: +/***/ ((module) => { + +module.exports = [ + 'uniform vec2 uMainResolution[TEXTURE_COUNT];', + 'vec2 getTexRes ()', + '{', + ' #if TEXTURE_COUNT == 1', + ' float texId = 0.0;', + ' #else', + ' float texId = outTexDatum;', + ' #endif', + ' #pragma phaserTemplate(texIdProcess)', + ' vec2 texRes = vec2(0.0);', + ' for (int i = 0; i < TEXTURE_COUNT; i++)', + ' {', + ' if (texId == float(i))', + ' {', + ' texRes = uMainResolution[i];', + ' break;', + ' }', + ' }', + ' return texRes;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 46432: +/***/ ((module) => { + +module.exports = [ + 'uniform sampler2D uMainSampler[TEXTURE_COUNT];', + 'vec4 getTexture (vec2 texCoord)', + '{', + ' #if TEXTURE_COUNT == 1', + ' float texId = 0.0;', + ' #else', + ' float texId = outTexDatum;', + ' #endif', + ' #pragma phaserTemplate(texIdProcess)', + ' vec4 texture = vec4(0.0);', + ' for (int i = 0; i < TEXTURE_COUNT; i++)', + ' {', + ' if (texId == float(i))', + ' {', + ' texture = texture2D(uMainSampler[i], texCoord);', + ' break;', + ' }', + ' }', + ' return texture;', + '}' +].join('\n'); + + +/***/ }), + +/***/ 98840: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#pragma phaserTemplate(fragmentDefine)', + 'uniform vec2 uResolution;', + 'varying vec2 outTexCoord;', + 'varying float outTexDatum;', + 'varying float outTintEffect;', + 'varying vec4 outTint;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' #pragma phaserTemplate(fragmentProcess)', + ' gl_FragColor = fragColor;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 44667: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#define ROUND_BIAS 0.5001', + '#pragma phaserTemplate(vertexDefine)', + 'uniform mat4 uProjectionMatrix;', + 'uniform int uRoundPixels;', + 'uniform vec2 uResolution;', + 'attribute vec2 inPosition;', + 'attribute vec2 inTexCoord;', + 'attribute float inTexDatum;', + 'attribute float inTintEffect;', + 'attribute vec4 inTint;', + 'varying vec2 outTexCoord;', + 'varying float outTexDatum;', + 'varying float outTintEffect;', + 'varying vec4 outTint;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(vertexHeader)', + 'void main ()', + '{', + ' vec2 position = uRoundPixels == 1 ? floor(inPosition + ROUND_BIAS) : inPosition;', + ' gl_Position = uProjectionMatrix * vec4(position, 1.0, 1.0);', + ' outTexCoord = inTexCoord;', + ' outTexDatum = inTexDatum;', + ' outTint = inTint;', + ' outTintEffect = inTintEffect;', + ' #pragma phaserTemplate(vertexProcess)', + '}', +].join('\n'); + + +/***/ }), + +/***/ 62807: +/***/ ((module) => { + +module.exports = [ + 'float inverseRotation = -rotation - uCamera.z;', + 'float irSine = sin(inverseRotation);', + 'float irCosine = cos(inverseRotation);', + 'outInverseRotationMatrix = mat3(', + ' irCosine, irSine, 0.0,', + ' -irSine, irCosine, 0.0,', + ' 0.0, 0.0, 1.0', + ');', +].join('\n'); + + +/***/ }), + +/***/ 4127: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + 'precision mediump float;', + '#pragma phaserTemplate(fragmentDefine)', + 'uniform vec2 uResolution;', + 'uniform float uCameraZoom;', + 'varying vec4 lightPosition;', + 'varying vec4 lightColor;', + 'varying float lightRadius;', + 'varying float lightAttenuation;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec2 center = (lightPosition.xy + 1.0) * (uResolution.xy * 0.5);', + ' float distToSurf = length(center - gl_FragCoord.xy);', + ' float radius = 1.0 - distToSurf / (lightRadius * uCameraZoom);', + ' float intensity = smoothstep(0.0, 1.0, radius * lightAttenuation);', + ' vec4 color = vec4(intensity, intensity, intensity, 0.0) * lightColor;', + ' #pragma phaserTemplate(fragmentProcess)', + ' gl_FragColor = vec4(color.rgb * lightColor.a, color.a);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 89924: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + 'precision mediump float;', + '#pragma phaserTemplate(vertexDefine)', + 'uniform mat4 uProjectionMatrix;', + 'attribute vec2 inPosition;', + 'attribute vec2 inLightPosition;', + 'attribute vec4 inLightColor;', + 'attribute float inLightRadius;', + 'attribute float inLightAttenuation;', + 'varying vec4 lightPosition;', + 'varying vec4 lightColor;', + 'varying float lightRadius;', + 'varying float lightAttenuation;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(vertexHeader)', + 'void main ()', + '{', + ' lightColor = inLightColor;', + ' lightRadius = inLightRadius;', + ' lightAttenuation = inLightAttenuation;', + ' lightPosition = uProjectionMatrix * vec4(inLightPosition, 1.0, 1.0);', + ' gl_Position = uProjectionMatrix * vec4(inPosition, 1.0, 1.0);', + ' #pragma phaserTemplate(vertexProcess)', + '}', +].join('\n'); + + +/***/ }), + +/***/ 72823: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#pragma phaserTemplate(fragmentDefine)', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' vec4 fragColor = vec4(outTexCoord.xyx, 1.0);', + ' #pragma phaserTemplate(fragmentProcess)', + ' gl_FragColor = fragColor;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 65884: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#pragma phaserTemplate(vertexDefine)', + 'uniform mat4 uProjectionMatrix;', + 'attribute vec2 inPosition;', + 'attribute vec2 inTexCoord;', + 'varying vec2 outTexCoord;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(vertexHeader)', + 'void main ()', + '{', + ' gl_Position = uProjectionMatrix * vec4(inPosition, 1.0, 1.0);', + ' outTexCoord = inTexCoord;', + ' #pragma phaserTemplate(vertexProcess)', + '}', +].join('\n'); + + +/***/ }), + +/***/ 2807: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + 'precision mediump float;', + 'attribute vec2 inPosition;', + 'attribute vec2 inTexCoord;', + 'varying vec2 outFragCoord;', + 'varying vec2 outTexCoord;', + 'void main ()', + '{', + ' outFragCoord = inPosition.xy * 0.5 + 0.5;', + ' outTexCoord = inTexCoord;', + ' gl_Position = vec4(inPosition, 0, 1);', + '}', +].join('\n'); + + +/***/ }), + +/***/ 49119: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#pragma phaserTemplate(fragmentDefine)', + 'uniform vec2 uResolution;', + 'varying vec2 outTexCoord;', + 'varying float outTintEffect;', + 'varying vec4 outTint;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(fragmentHeader)', + 'void main ()', + '{', + ' #pragma phaserTemplate(fragmentProcess)', + ' gl_FragColor = fragColor;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 3524: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#define ROUND_BIAS 0.5001', + '#pragma phaserTemplate(vertexDefine)', + 'uniform mat4 uProjectionMatrix;', + 'uniform mat3 uViewMatrix;', + 'uniform vec3 uCameraScrollAndAlpha;', + 'uniform int uRoundPixels;', + 'uniform vec2 uResolution;', + 'uniform float uTime;', + 'uniform vec2 uDiffuseResolution;', + 'uniform vec2 uFrameDataResolution;', + 'uniform sampler2D uFrameDataTexture;', + 'uniform float uGravity;', + 'attribute float inVertex;', + 'attribute vec4 inPositionX;', + 'attribute vec4 inPositionY;', + 'attribute vec4 inRotation;', + 'attribute vec4 inScaleX;', + 'attribute vec4 inScaleY;', + 'attribute vec4 inAlpha;', + 'attribute vec4 inFrame;', + 'attribute vec4 inTintBlend;', + 'attribute vec4 inTintTL;', + 'attribute vec4 inTintTR;', + 'attribute vec4 inTintBL;', + 'attribute vec4 inTintBR;', + 'attribute vec4 inOriginAndTintFillAndCreationTime;', + 'attribute vec2 inScrollFactor;', + 'varying vec2 outTexCoord;', + 'varying float outTintEffect;', + 'varying vec4 outTint;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(vertexHeader)', + 'const float PI = 3.14159265359;', + 'const float HALF_PI = PI / 2.0;', + 'const float BOUNCE_OVERSHOOT = 1.70158;', + 'const float BOUNCE_OVERSHOOT_PLUS = BOUNCE_OVERSHOOT + 1.0;', + 'const float BOUNCE_OVERSHOOT_IN_OUT = BOUNCE_OVERSHOOT * 1.525;', + 'const float BOUNCE_OVERSHOOT_IN_OUT_PLUS = BOUNCE_OVERSHOOT_IN_OUT + 1.0;', + 'float animate (vec4 anim)', + '{', + ' float value = anim.x;', + ' float a = anim.y;', + ' float b = abs(anim.z);', + ' float c = abs(anim.w);', + ' bool yoyo = anim.z < 0.0;', + ' bool loop = anim.w > 0.0;', + ' int type = int(floor(c));', + ' if (type == 0|| b == 0.0)', + ' {', + ' return value;', + ' }', + ' float duration = b;', + ' float delay = mod(c, 1.0) * 2.0;', + ' float rawTime = ((uTime - inOriginAndTintFillAndCreationTime.w) / duration) - delay;', + ' float time = mod(rawTime, 1.0);', + ' if (yoyo && (mod(rawTime, 2.0) >= 1.0))', + ' {', + ' time = 1.0 - time;', + ' }', + ' float repeats = loop ? 0.0 : floor(a);', + ' float timeContinuous = loop ? time : rawTime;', + ' #ifdef FEATURE_LINEAR', + ' if (type == 1)', + ' {', + ' return value + a * timeContinuous;', + ' }', + ' #endif', + ' #ifdef FEATURE_GRAVITY', + ' if (type == 2)', + ' {', + ' float v = floor(a);', + ' float gravityFactor = (a - v) * 2.0 - 1.0;', + ' if (gravityFactor == 0.0)', + ' {', + ' gravityFactor = 1.0;', + ' }', + ' float seconds = timeContinuous * duration / 1000.0;', + ' float accel = uGravity * gravityFactor;', + ' return value + (v * seconds) + (0.5 * accel * seconds * seconds);', + ' }', + ' #endif', + ' #ifdef FEATURE_QUAD_EASEOUT', + ' if (type == 10)', + ' {', + ' return value + a * time * (2.0 - time)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUAD_EASEIN', + ' if (type == 11)', + ' {', + ' return value + a * time * time', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUAD_EASEINOUT', + ' if (type == 12)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * time * time * 0.5', + ' + repeats * a;', + ' }', + ' time -= 1.0;', + ' return value + a * -0.5 * (time * (time - 2.0) - 1.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_CUBIC_EASEOUT', + ' if (type == 20)', + ' {', + ' time -= 1.0;', + ' return value + a * (time * time * time + 1.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_CUBIC_EASEIN', + ' if (type == 21)', + ' {', + ' return value + a * time * time * time', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_CUBIC_EASEINOUT', + ' if (type == 22)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * time * time * time * 0.5', + ' + repeats * a;', + ' }', + ' time -= 2.0;', + ' return value + a * 0.5 * (time * time * time + 2.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUART_EASEOUT', + ' if (type == 30)', + ' {', + ' time -= 1.0;', + ' return value + a * (1.0 - time * time * time * time)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUART_EASEIN', + ' if (type == 31)', + ' {', + ' return value + a * time * time * time * time', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUART_EASEINOUT', + ' if (type == 32)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * time * time * time * time * 0.5', + ' + repeats * a;', + ' }', + ' time -= 2.0;', + ' return value + a * -0.5 * (time * time * time * time - 2.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUINT_EASEOUT', + ' if (type == 40)', + ' {', + ' time -= 1.0;', + ' return value + a * (time * time * time * time * time + 1.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUINT_EASEIN', + ' if (type == 41)', + ' {', + ' return value + a * time * time * time * time * time', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_QUINT_EASEINOUT', + ' if (type == 42)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * time * time * time * time * time * 0.5', + ' + repeats * a;', + ' }', + ' time -= 2.0;', + ' return value + a * 0.5 * (time * time * time * time * time + 2.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_SINE_EASEOUT', + ' if (type == 50)', + ' {', + ' return value + a * sin(time * HALF_PI)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_SINE_EASEIN', + ' if (type == 51)', + ' {', + ' return value + a * (1.0 - cos(time * HALF_PI))', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_SINE_EASEINOUT', + ' if (type == 52)', + ' {', + ' return value + a * 0.5 * (1.0 - cos(PI * time))', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_EXPO_EASEOUT', + ' if (type == 60)', + ' {', + ' return value + a * (1.0 - pow(2.0, -10.0 * time))', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_EXPO_EASEIN', + ' if (type == 61)', + ' {', + ' return value + a * pow(2.0, 10.0 * (time - 1.0) - 0.001)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_EXPO_EASEINOUT', + ' if (type == 62)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * 0.5 * pow(2.0, 10.0 * (time - 1.0))', + ' + repeats * a;', + ' }', + ' time -= 1.0;', + ' return value + a * 0.5 * (2.0 - pow(2.0, -10.0 * (time - 1.0)))', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_CIRC_EASEOUT', + ' if (type == 70)', + ' {', + ' time -= 1.0;', + ' return value + a * sqrt(1.0 - time * time)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_CIRC_EASEIN', + ' if (type == 71)', + ' {', + ' return value + a * (1.0 - sqrt(1.0 - time * time))', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_CIRC_EASEINOUT', + ' if (type == 72)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * -0.5 * (sqrt(1.0 - time * time) - 1.0)', + ' + repeats * a;', + ' }', + ' time -= 2.0;', + ' return value + a * 0.5 * (sqrt(1.0 - time * time) + 1.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_BACK_EASEOUT', + ' if (type == 90)', + ' {', + ' time -= 1.0;', + ' return value + a * (time * time * (BOUNCE_OVERSHOOT_PLUS * time + BOUNCE_OVERSHOOT) + 1.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_BACK_EASEIN', + ' if (type == 91)', + ' {', + ' return value + a * time * time * (BOUNCE_OVERSHOOT_PLUS * time - BOUNCE_OVERSHOOT)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_BACK_EASEINOUT', + ' if (type == 92)', + ' {', + ' time *= 2.0;', + ' if (time < 1.0)', + ' {', + ' return value + a * 0.5 * (time * time * (BOUNCE_OVERSHOOT_IN_OUT_PLUS * time - BOUNCE_OVERSHOOT_IN_OUT))', + ' + repeats * a;', + ' }', + ' time -= 2.0;', + ' return value + a * 0.5 * (time * time * (BOUNCE_OVERSHOOT_IN_OUT_PLUS * time + BOUNCE_OVERSHOOT_IN_OUT) + 2.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_BOUNCE_EASEOUT', + ' if (type == 100)', + ' {', + ' if (time < 1.0 / 2.75)', + ' {', + ' return value + a * (7.5625 * time * time)', + ' + repeats * a;', + ' }', + ' else if (time < 2.0 / 2.75)', + ' {', + ' time -= 1.5 / 2.75;', + ' return value + a * (7.5625 * time * time + 0.75)', + ' + repeats * a;', + ' }', + ' else if (time < 2.5 / 2.75)', + ' {', + ' time -= 2.25 / 2.75;', + ' return value + a * (7.5625 * time * time + 0.9375)', + ' + repeats * a;', + ' }', + ' else', + ' {', + ' time -= 2.625 / 2.75;', + ' return value + a * (7.5625 * time * time + 0.984375)', + ' + repeats * a;', + ' }', + ' }', + ' #endif', + ' #ifdef FEATURE_BOUNCE_EASEIN', + ' if (type == 101)', + ' {', + ' time = 1.0 - time;', + ' if (time < 1.0 / 2.75)', + ' {', + ' return value + a * (1.0 - 7.5625 * time * time)', + ' + repeats * a;', + ' }', + ' else if (time < 2.0 / 2.75)', + ' {', + ' time -= 1.5 / 2.75;', + ' return value + a * (1.0 - (7.5625 * time * time + 0.75))', + ' + repeats * a;', + ' }', + ' else if (time < 2.5 / 2.75)', + ' {', + ' time -= 2.25 / 2.75;', + ' return value + a * (1.0 - (7.5625 * time * time + 0.9375))', + ' + repeats * a;', + ' }', + ' else', + ' {', + ' time -= 2.625 / 2.75;', + ' return value + a * (1.0 - (7.5625 * time * time + 0.984375))', + ' + repeats * a;', + ' }', + ' }', + ' #endif', + ' #ifdef FEATURE_BOUNCE_EASEINOUT', + ' if (type == 102)', + ' {', + ' bool reverse = false;', + ' if (time < 0.5)', + ' {', + ' time = 1.0 - time * 2.0;', + ' reverse = true;', + ' }', + ' if (time < 1.0 / 2.75)', + ' {', + ' time = 7.5625 * time * time;', + ' }', + ' else if (time < 2.0 / 2.75)', + ' {', + ' time -= 1.5 / 2.75;', + ' time = 7.5625 * time * time + 0.75;', + ' }', + ' else if (time < 2.5 / 2.75)', + ' {', + ' time -= 2.25 / 2.75;', + ' time = 7.5625 * time * time + 0.9375;', + ' }', + ' else', + ' {', + ' time -= 2.625 / 2.75;', + ' time = 7.5625 * time * time + 0.984375;', + ' }', + ' if (reverse)', + ' {', + ' return value + a * (1.0 - time) * 0.5', + ' + repeats * a;', + ' }', + ' return value + a * time * 0.5 + 0.5', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_STEPPED', + ' if (type == 110)', + ' {', + ' return value + a * floor(time + 0.5)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_SMOOTHSTEP_EASEOUT', + ' if (type == 120)', + ' {', + ' return value + a * (smoothstep(0.0, 1.0, time / 2.0 + 0.5) * 2.0 - 1.0)', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_SMOOTHSTEP_EASEIN', + ' if (type == 121)', + ' {', + ' return value + a * smoothstep(0.0, 1.0, time / 2.0) * 2.0', + ' + repeats * a;', + ' }', + ' #endif', + ' #ifdef FEATURE_SMOOTHSTEP_EASEINOUT', + ' if (type == 122)', + ' {', + ' return value + a * smoothstep(0.0, 1.0, time)', + ' + repeats * a;', + ' }', + ' #endif', + ' return value;', + '}', + 'struct Frame {', + ' vec2 position;', + ' vec2 size;', + ' vec2 offset;', + '};', + 'Frame getFrame (float frame)', + '{', + ' float index1 = floor(frame) * 3.0;', + ' float index2 = index1 + 1.0;', + ' float index3 = index1 + 2.0;', + ' float width = uFrameDataResolution.x;', + ' float x = mod(index1, width);', + ' float y = floor(index1 / width);', + ' vec4 texelUV = texture2D(', + ' uFrameDataTexture,', + ' vec2(x + 0.5, y + 0.5) / uFrameDataResolution', + ' );', + ' x = mod(index2, width);', + ' y = floor(index2 / width);', + ' vec4 texelWH = texture2D(', + ' uFrameDataTexture,', + ' vec2(x + 0.5, y + 0.5) / uFrameDataResolution', + ' );', + ' x = mod(index3, width);', + ' y = floor(index3 / width);', + ' vec4 texelOrigin = texture2D(', + ' uFrameDataTexture,', + ' vec2(x + 0.5, y + 0.5) / uFrameDataResolution', + ' );', + ' return Frame(', + ' vec2(', + ' texelUV.r + texelUV.g * 256.0,', + ' texelUV.b + texelUV.a * 256.0', + ' ) * 255.0,', + ' vec2(', + ' texelWH.r + texelWH.g * 256.0,', + ' texelWH.b + texelWH.a * 256.0', + ' ) * 255.0,', + ' vec2(', + ' texelOrigin.r + texelOrigin.g * 256.0,', + ' texelOrigin.b + texelOrigin.a * 256.0', + ' ) * 255.0 - 32768.0', + ' );', + '}', + 'void main ()', + '{', + ' float positionX = animate(inPositionX);', + ' float positionY = animate(inPositionY);', + ' float rotation = animate(inRotation);', + ' float scaleX = animate(inScaleX);', + ' float scaleY = animate(inScaleY);', + ' float frame = animate(inFrame);', + ' float tintBlend = animate(inTintBlend);', + ' float alpha = animate(inAlpha);', + ' vec2 origin = inOriginAndTintFillAndCreationTime.xy;', + ' float tintFill = inOriginAndTintFillAndCreationTime.z;', + ' float scrollFactorX = inScrollFactor.x;', + ' float scrollFactorY = inScrollFactor.y;', + ' Frame frameData = getFrame(frame);', + ' vec2 uv = frameData.position / uDiffuseResolution;', + ' vec2 wh = frameData.size / uDiffuseResolution;', + ' float u = uv.s;', + ' float v = uv.t;', + ' float w = wh.s;', + ' float h = wh.t;', + ' float width = frameData.size.s;', + ' float height = frameData.size.t;', + ' vec4 tint = inTintTL;', + ' float x = -origin.x;', + ' float y = -origin.y;', + ' if (inVertex == 0.0)', + ' {', + ' y = 1.0 - origin.y;', + ' v += h;', + ' tint = inTintBL;', + ' }', + ' else if (inVertex == 2.0)', + ' {', + ' x = 1.0 - origin.x;', + ' y = 1.0 - origin.y;', + ' u += w;', + ' v += h;', + ' tint = inTintBR;', + ' }', + ' else if (inVertex == 3.0)', + ' {', + ' x = 1.0 - origin.x;', + ' u += w;', + ' tint = inTintTR;', + ' }', + ' vec3 position = vec3(', + ' (x * width - frameData.offset.x) * scaleX,', + ' (y * height - frameData.offset.y) * scaleY,', + ' 1.0', + ' );', + ' mat3 viewMatrix = uViewMatrix * mat3(', + ' 1.0, 0.0, 0.0,', + ' 0.0, 1.0, 0.0,', + ' uCameraScrollAndAlpha.x * (1.0 - scrollFactorX), uCameraScrollAndAlpha.y * (1.0 - scrollFactorY), 1.0', + ' );', + ' float sine = sin(rotation);', + ' float cosine = cos(rotation);', + ' mat3 transformMatrix = mat3(', + ' cosine, sine, 0.0,', + ' -sine, cosine, 0.0,', + ' positionX, positionY, 1.0', + ' );', + ' position = viewMatrix * transformMatrix * position;', + ' alpha *= uCameraScrollAndAlpha.z;', + ' tint.a *= alpha;', + ' if (uRoundPixels == 1 && rotation == 0.0 && scaleX == 1.0 && scaleY == 1.0)', + ' {', + ' position.xy = floor(position.xy + ROUND_BIAS);', + ' }', + ' gl_Position = uProjectionMatrix * vec4(position.xy, 1.0, 1.0);', + ' outTexCoord = vec2(u, 1.0 - v);', + ' outTint = mix(vec4(1.0, 1.0, 1.0, tint.a), tint, tintBlend);', + ' outTintEffect = tintFill;', + ' #pragma phaserTemplate(vertexProcess)', + '}', +].join('\n'); + + +/***/ }), + +/***/ 57532: +/***/ ((module) => { + +module.exports = [ + '#version 100', + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '/* Redefine MAX_ANIM_FRAMES to support animations with different frame numbers. */', + '#define MAX_ANIM_FRAMES 0', + '#pragma phaserTemplate(fragmentDefine)', + 'uniform vec2 uResolution;', + 'uniform int uRoundPixels;', + 'uniform sampler2D uMainSampler;', + 'uniform sampler2D uLayerSampler;', + 'uniform vec2 uMainResolution;', + 'uniform vec2 uLayerResolution;', + 'uniform float uTileColumns;', + 'uniform vec4 uTileWidthHeightMarginSpacing;', + 'uniform float uAlpha;', + 'uniform float uTime;', + '#if MAX_ANIM_FRAMES > 0', + 'uniform sampler2D uAnimSampler;', + 'uniform vec2 uAnimResolution;', + '#endif', + 'varying vec2 outTexCoord;', + 'varying vec2 outTileStride;', + '#pragma phaserTemplate(outVariables)', + 'vec2 getTexRes ()', + '{', + ' return uMainResolution;', + '}', + 'float floatTexel (vec4 texel)', + '{', + ' return texel.r * 255.0 + (texel.g * 255.0 * 256.0) + (texel.b * 255.0 * 256.0 * 256.0) + (texel.a * 255.0 * 256.0 * 256.0 * 256.0);', + '}', + 'struct Tile', + '{', + ' float index;', + ' vec2 uv; // In texels.', + ' #if MAX_ANIM_FRAMES > 0', + ' bool animated;', + ' #endif', + ' bool empty;', + '};', + 'Tile getLayerData (vec2 coord)', + '{', + ' vec2 texelCoord = coord * uLayerResolution;', + ' vec2 tile = floor(texelCoord);', + ' vec2 uv = fract(texelCoord);', + ' uv.y = 1.0 - uv.y;', + ' vec4 texel = texture2D(uLayerSampler, (tile + 0.5) / uLayerResolution) * 255.0;', + ' float flags = texel.a;', + ' /* Check for empty tile flag in bit 28. */', + ' if (flags == 16.0)', + ' {', + ' return Tile(', + ' 0.0,', + ' vec2(0.0),', + ' #if MAX_ANIM_FRAMES > 0', + ' false,', + ' #endif', + ' true', + ' );', + ' }', + ' /* Bit 31 is flipX. */', + ' bool flipX = flags > 127.0;', + ' /* Bit 30 is flipY. */', + ' bool flipY = mod(flags, 128.0) > 63.0;', + ' #if MAX_ANIM_FRAMES > 0', + ' /* Bit 29 is animation. */', + ' bool animated = mod(flags, 64.0) > 31.0;', + ' #endif', + ' if (flipX)', + ' {', + ' uv.x = 1.0 - uv.x;', + ' }', + ' if (flipY)', + ' {', + ' uv.y = 1.0 - uv.y;', + ' }', + ' float index = texel.r + (texel.g * 256.0) + (texel.b * 256.0 * 256.0);', + ' return Tile(', + ' index,', + ' uv * uTileWidthHeightMarginSpacing.xy,', + ' #if MAX_ANIM_FRAMES > 0', + ' animated,', + ' #endif', + ' false', + ' );', + '}', + 'vec2 getFrameCorner (float index)', + '{', + ' float x = mod(index, uTileColumns);', + ' float y = floor(index / uTileColumns);', + ' vec2 xy = vec2(x, y);', + ' return xy * outTileStride + uTileWidthHeightMarginSpacing.zz;', + '}', + '#if MAX_ANIM_FRAMES > 0', + 'float animationIndex (float index)', + '{', + ' float animTextureWidth = uAnimResolution.x;', + ' vec2 index2D = vec2(mod(index, animTextureWidth), floor(index / animTextureWidth));', + ' vec4 animDurationTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);', + ' index2D = vec2(mod(index + 1.0, animTextureWidth), floor((index + 1.0) / animTextureWidth));', + ' vec4 animIndexTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);', + ' float animDuration = floatTexel(animDurationTexel);', + ' float animIndex = floatTexel(animIndexTexel);', + ' float animTime = mod(uTime, animDuration);', + ' float animTimeAccum = 0.0;', + ' for (int i = 0; i < MAX_ANIM_FRAMES; i++)', + ' {', + ' index2D = vec2(mod(animIndex, animTextureWidth), floor(animIndex / animTextureWidth));', + ' animDurationTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);', + ' float frameDuration = floatTexel(animDurationTexel);', + ' animTimeAccum += frameDuration;', + ' if (animTime <= animTimeAccum)', + ' {', + ' break;', + ' }', + ' animIndex += 2.0;', + ' }', + ' animIndex += 1.0;', + ' index2D = vec2(mod(animIndex, animTextureWidth), floor(animIndex / animTextureWidth));', + ' animIndexTexel = texture2D(uAnimSampler, (index2D + 0.5) / uAnimResolution);', + ' float animFrameIndex = floatTexel(animIndexTexel);', + ' return animFrameIndex;', + '}', + '#endif', + 'vec2 getTileTexelCoord (Tile tile)', + '{', + ' if (tile.empty)', + ' {', + ' return vec2(0.0);', + ' }', + ' float index = tile.index;', + ' #if MAX_ANIM_FRAMES > 0', + ' if (tile.animated)', + ' {', + ' index = animationIndex(index);', + ' }', + ' #endif', + ' vec2 frameCorner = getFrameCorner(index);', + ' return frameCorner + tile.uv;', + '}', + '#pragma phaserTemplate(fragmentHeader)', + 'struct Samples {', + ' vec4 color;', + ' #pragma phaserTemplate(defineSamples)', + '};', + 'Samples getColorSamples (vec2 texCoord)', + '{', + ' Samples samples;', + ' samples.color = texture2D(', + ' uMainSampler,', + ' vec2(texCoord.x, 1.0 - texCoord.y)', + ' );', + ' #pragma phaserTemplate(getSamples)', + ' return samples;', + '}', + 'Samples mixSamples (Samples samples1, Samples samples2, float alpha)', + '{', + ' Samples samples;', + ' samples.color = mix(samples1.color, samples2.color, alpha);', + ' #pragma phaserTemplate(mixSamples)', + ' return samples;', + '}', + 'Samples getFinalSamples (Tile tile, vec2 layerTexCoord)', + '{', + ' vec2 texelCoord = getTileTexelCoord(tile);', + ' vec2 texCoord = texelCoord / uMainResolution;', + ' #pragma phaserTemplate(texCoord)', + ' #ifndef FEATURE_BORDERFILTER', + ' return getColorSamples(texCoord);', + ' #else', + ' #pragma phaserTemplate(finalSamples)', + ' vec2 wh = uTileWidthHeightMarginSpacing.xy;', + ' vec2 frameCorner = getFrameCorner(tile.index);', + ' vec2 frameCornerOpposite = frameCorner + wh;', + ' vec2 texCoordClamped = clamp(texCoord, (frameCorner + 0.5) / uMainResolution, (frameCornerOpposite - 0.5) / uMainResolution);', + ' vec2 dTexelCoord = (texCoord - texCoordClamped) * uMainResolution;', + ' dTexelCoord.y = -dTexelCoord.y;', + ' vec2 offsets = sign(dTexelCoord);', + ' Samples samples0 = getColorSamples(texCoordClamped);', + ' if (offsets.x == 0.0)', + ' {', + ' if (offsets.y == 0.0)', + ' {', + ' return samples0;', + ' }', + ' Tile tileY = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);', + ' vec2 texelCoordY = getTileTexelCoord(tileY);', + ' vec2 texCoordY = texelCoordY / uMainResolution;', + ' Samples samplesY = getColorSamples(texCoordY);', + ' return mixSamples(samples0, samplesY, abs(dTexelCoord.y));', + ' }', + ' else', + ' {', + ' if (offsets.y == 0.0)', + ' {', + ' Tile tileX = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);', + ' vec2 texelCoordX = getTileTexelCoord(tileX);', + ' vec2 texCoordX = texelCoordX / uMainResolution;', + ' Samples samplesX = getColorSamples(texCoordX);', + ' return mixSamples(samples0, samplesX, abs(dTexelCoord.x));', + ' }', + ' Tile tileX = getLayerData(layerTexCoord + (offsets * vec2(1.0, 0.0) - dTexelCoord) / wh / uLayerResolution);', + ' vec2 texelCoordX = getTileTexelCoord(tileX);', + ' vec2 texCoordX = texelCoordX / uMainResolution;', + ' Samples samplesX = getColorSamples(texCoordX);', + ' Tile tileY = getLayerData(layerTexCoord + (offsets * vec2(0.0, 1.0) - dTexelCoord) / wh / uLayerResolution);', + ' vec2 texelCoordY = getTileTexelCoord(tileY);', + ' vec2 texCoordY = texelCoordY / uMainResolution;', + ' Samples samplesY = getColorSamples(texCoordY);', + ' Tile tileXY = getLayerData(layerTexCoord + (offsets - dTexelCoord) / wh / uLayerResolution);', + ' vec2 texelCoordXY = getTileTexelCoord(tileXY);', + ' vec2 texCoordXY = texelCoordXY / uMainResolution;', + ' Samples samplesXY = getColorSamples(texCoordXY);', + ' Samples samples1 = mixSamples(samples0, samplesX, abs(dTexelCoord.x));', + ' Samples samples2 = mixSamples(samplesY, samplesXY, abs(dTexelCoord.x));', + ' return mixSamples(samples1, samples2, abs(dTexelCoord.y));', + ' }', + ' #endif', + '}', + 'void main ()', + '{', + ' vec2 layerTexCoord = outTexCoord;', + ' Tile tile = getLayerData(layerTexCoord);', + ' Samples samples = getFinalSamples(tile, layerTexCoord);', + ' vec4 fragColor = samples.color;', + ' #pragma phaserTemplate(declareSamples)', + ' #pragma phaserTemplate(fragmentProcess)', + ' fragColor *= uAlpha;', + ' gl_FragColor = fragColor;', + '}', +].join('\n'); + + +/***/ }), + +/***/ 23879: +/***/ ((module) => { + +module.exports = [ + '#pragma phaserTemplate(shaderName)', + '#pragma phaserTemplate(extensions)', + '#pragma phaserTemplate(features)', + '#ifdef GL_FRAGMENT_PRECISION_HIGH', + 'precision highp float;', + '#else', + 'precision mediump float;', + '#endif', + '#define ROUND_BIAS 0.5001', + '#pragma phaserTemplate(vertexDefine)', + 'uniform mat4 uProjectionMatrix;', + 'uniform int uRoundPixels;', + 'uniform vec2 uResolution;', + 'uniform vec4 uTileWidthHeightMarginSpacing;', + 'attribute vec2 inPosition;', + 'attribute vec2 inTexCoord;', + 'varying vec2 outTexCoord;', + 'varying vec2 outTileStride;', + '#pragma phaserTemplate(outVariables)', + '#pragma phaserTemplate(vertexHeader)', + 'void main ()', + '{', + ' vec2 position = uRoundPixels == 1 ? floor(inPosition + ROUND_BIAS) : inPosition;', + ' gl_Position = uProjectionMatrix * vec4(position, 1.0, 1.0);', + ' outTexCoord = inTexCoord;', + ' outTileStride = uTileWidthHeightMarginSpacing.xy + uTileWidthHeightMarginSpacing.zz;', + ' #pragma phaserTemplate(vertexProcess)', + '}', +].join('\n'); + + +/***/ }), + +/***/ 84639: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MakeAnimLength = function (maxAnims, disable) +{ + return { + name: maxAnims + 'Anims', + additions: { + fragmentDefine: '#undef MAX_ANIM_FRAMES\n#define MAX_ANIM_FRAMES ' + maxAnims + }, + tags: [ 'MAXANIMS' ], + disable: !!disable + }; +}; + +module.exports = MakeAnimLength; + + +/***/ }), + +/***/ 67155: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ApplyLighting = __webpack_require__(84547); + +/** + * Return a ShaderAdditionConfig for applying lighting to a flat piece of geometry. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeApplyFlatLighting + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeApplyFlatLighting = function (disable) +{ + return { + name: 'ApplyFlatLighting', + additions: { + fragmentHeader: ApplyLighting, + fragmentProcess: 'fragColor = applyLighting(fragColor, vec3(0.0, 0.0, 1.0));' + }, + tags: ['LIGHTING'], + disable: !!disable + }; +}; + +module.exports = MakeApplyFlatLighting; + + +/***/ }), + +/***/ 81084: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ApplyLighting = __webpack_require__(84547); + +/** + * Return a ShaderAdditionConfig for applying lighting to a texture. + * + * The `rotation` variable must be available in the vertex renderer. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeApplyLighting + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeApplyLighting = function (disable) +{ + return { + name: 'ApplyLighting', + additions: { + fragmentHeader: ApplyLighting, + fragmentProcess: 'fragColor = applyLighting(fragColor, normal);' + }, + tags: ['LIGHTING'], + disable: !!disable + }; +}; + +module.exports = MakeApplyLighting; + + +/***/ }), + +/***/ 44349: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ApplyTint = __webpack_require__(11104); + +/** + * Return a ShaderAdditionConfig for applying a tint to a texture. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeApplyTint + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeApplyTint = function (disable) +{ + return { + name: 'Tint', + additions: { + fragmentHeader: ApplyTint, + fragmentProcess: 'fragColor = applyTint(fragColor);' + }, + tags: ['TINT'], + disable: !!disable + }; +}; + +module.exports = MakeApplyTint; + + +/***/ }), + +/***/ 99501: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BoundedSampler = __webpack_require__(81556); + +/** + * Return a ShaderAdditionConfig for bounded texture sampling. + * A bounded sampler will return a transparent pixel + * if the texture coordinates are outside the texture bounds. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeBoundedSampler + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeBoundedSampler = function (disable) +{ + return { + name: 'BoundedSampler', + additions: { + fragmentHeader: BoundedSampler + }, + disable: !!disable + }; +}; + +module.exports = MakeBoundedSampler; + + +/***/ }), + +/***/ 6184: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefineLights = __webpack_require__(11719); + +/** + * Return a ShaderAdditionConfig for defining the lights and core lighting + * algorithm in the fragment shader. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeDefineLights + * @since 4.0.0 + * + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeDefineLights = function (disable) +{ + return { + name: 'DefineLights', + additions: { + fragmentDefine: '#define LIGHT_COUNT 1', + fragmentHeader: DefineLights + }, + tags: [ 'LIGHTING' ], + disable: !!disable + }; +}; + +module.exports = MakeDefineLights; + + +/***/ }), + +/***/ 11653: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MakeDefineTexCount = function (maxTextures, disable) +{ + return { + name: maxTextures + 'TexCount', + additions: { + fragmentDefine: '#define TEXTURE_COUNT ' + maxTextures + }, + tags: [ 'TexCount' ], + disable: !!disable + }; +}; + +module.exports = MakeDefineTexCount; + + +/***/ }), + +/***/ 13198: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Return a ShaderAdditionConfig for defining a flat normal. + * This is used to light objects without a normal map. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeFlatNormal + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeFlatNormal = function (disable) +{ + return { + name: 'FlatNormal', + additions: { + fragmentProcess: 'vec3 normal = vec3(0.0, 0.0, 1.0);' + }, + tags: [ 'LIGHTING' ], + disable: !!disable + }; +}; + +module.exports = MakeFlatNormal; + + +/***/ }), + +/***/ 40829: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetNormalFromMap = __webpack_require__(84220); + +/** + * Return a ShaderAdditionConfig for creating an outInverseRotationMatrix + * in the vertex shader, which is used to apply lighting to a texture. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeGetNormalFromMap + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeGetNormalFromMap = function (disable) +{ + return { + name: 'NormalMap', + additions: { + fragmentHeader: GetNormalFromMap, + fragmentProcess: 'vec3 normal = getNormalFromMap(texCoord);' + }, + tags: [ 'LIGHTING' ], + disable: !!disable + }; +}; + +module.exports = MakeGetNormalFromMap; + + +/***/ }), + +/***/ 42792: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Return a ShaderAdditionConfig for getting the texture coordinates + * from the vertex shader via the `outTexCoord` variable. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeGetTexCoordOut + * @since 4.0.0 + * + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeGetTexCoordOut = function (disable) +{ + return { + name: 'TexCoordOut', + additions: { + fragmentProcess: 'vec2 texCoord = outTexCoord;\n#pragma phaserTemplate(texCoord)' + }, + tags: [ 'TEXCOORD' ], + disable: !!disable + }; +}; + +module.exports = MakeGetTexCoordOut; + + +/***/ }), + +/***/ 96049: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTexRes = __webpack_require__(2860); + +var MakeGetTexRes = function (disable) +{ + return { + name: 'GetTexRes', + additions: { + fragmentHeader: GetTexRes + }, + tags: [ 'TEXRES' ], + disable: !!disable + }; +}; + +module.exports = MakeGetTexRes; + + +/***/ }), + +/***/ 33997: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTexture = __webpack_require__(46432); + +var MakeGetTexture = function (disable) +{ + return { + name: 'GetTexture', + additions: { + fragmentHeader: GetTexture, + fragmentProcess: 'vec4 fragColor = getTexture(texCoord);' + }, + tags: [ 'TEXTURE' ], + disable: !!disable + }; +}; + +module.exports = MakeGetTexture; + + +/***/ }), + +/***/ 10455: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns a ShaderAdditionConfig for providing the vertex shader with the `inFrame` attribute. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeOutFrame + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeOutFrame = function (disable) +{ + return { + name: 'OutFrame', + additions: { + vertexHeader: 'attribute vec4 inFrame;', + vertexProcess: 'outFrame = inFrame;', + outVariables: 'varying vec4 outFrame;', + }, + disable: !!disable + }; +}; + +module.exports = MakeOutFrame; + + +/***/ }), + +/***/ 79532: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var OutInverseRotation = __webpack_require__(62807); + +/** + * Return a ShaderAdditionConfig for creating an outInverseRotationMatrix + * in the vertex shader, which is used to apply lighting to a texture. + * + * The `rotation` variable must be available in the vertex renderer. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeOutInverseRotation + * @since 4.0.0 + * + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeOutInverseRotation = function (disable) +{ + return { + name: 'OutInverseRotation', + additions: { + vertexHeader: 'uniform vec4 uCamera;', + vertexProcess: OutInverseRotation, + outVariables: 'varying mat3 outInverseRotationMatrix;' + }, + tags: [ 'LIGHTING' ], + disable: !!disable + }; +}; + +module.exports = MakeOutInverseRotation; + + +/***/ }), + +/***/ 65217: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Return a ShaderAdditionConfig for deriving rotation from `inTexDatum`. + * This is useful for shaders that need to know their orientation. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeRotationDatum + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeRotationDatum = function (disable) +{ + return { + name: 'RotDatum', + additions: { + vertexProcess: 'float rotation = inTexDatum;' + }, + tags: ['LIGHTING'], + disable: !!disable + }; +}; + +module.exports = MakeRotationDatum; + + +/***/ }), + +/***/ 747: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Return a ShaderAdditionConfig for sampling a normal map + * in the context of a TilemapGPULayer shader. + * This shader uses a `Samples` object to collate texture samples. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeSampleNormal + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + */ +var MakeSampleNormal = function (disable) +{ + return { + name: 'SampleNormal', + additions: { + defineSamples: 'vec4 normal;', + getSamples: 'samples.normal = texture2D(uNormSampler, texCoord);', + mixSamples: 'samples.normal = mix(samples1.normal, samples2.normal, alpha);', + declareSamples: 'vec3 normal = normalize(samples.normal.rgb * 2.0 - 1.0);' + }, + tags: ['LIGHTING'], + disable: !!disable + }; +} + +module.exports = MakeSampleNormal; + + +/***/ }), + +/***/ 74505: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefineBlockyTexCoord = __webpack_require__(78390); + +var MakeSmoothPixelArt = function (disable) +{ + return { + name: 'SmoothPixelArt', + additions: { + extensions: '#extension GL_OES_standard_derivatives : enable', + fragmentHeader: DefineBlockyTexCoord, + texCoord: 'texCoord = getBlockyTexCoord(texCoord, getTexRes());' + }, + disable: !!disable + }; +}; + +module.exports = MakeSmoothPixelArt; + + +/***/ }), + +/***/ 44832: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefineTexCoordFrameClamp = __webpack_require__(14030); + + /** + * Returns a ShaderAdditionConfig for clamping coordinates inside a frame. + * This prevents bleeding across the edges of the frame. + * However, it creates a hard edge at the frame boundary. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeTexCoordFrameClamp + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeTexCoordFrameClamp = function (disable) +{ + return { + name: 'TexCoordFrameClamp', + additions: { + fragmentHeader: DefineTexCoordFrameClamp, + texCoord: 'texCoord = clampTexCoordWithinFrame(texCoord);' + }, + disable: !!disable + }; +}; + +module.exports = MakeTexCoordFrameClamp; + + +/***/ }), + +/***/ 23295: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns a ShaderAdditionConfig for wrapping coordinates inside a frame. + * This makes the texture repeat within the bounds of the frame - + * it's what makes a TileSprite work. + * + * @function Phaser.Renderer.WebGL.Shaders.MakeTexCoordFrameWrap + * @since 4.0.0 + * @param {boolean} [disable=false] - Whether to disable the shader addition on creation. + * @returns {Phaser.Types.Renderer.WebGL.ShaderAdditionConfig} The shader addition configuration. + */ +var MakeTexCoordFrameWrap = function (disable) +{ + return { + name: 'TexCoordFrameWrap', + additions: { + texCoord: '// Wrap texture coordinate into the UV space of the texture frame.\ntexCoord = mod(texCoord, 1.0) * outFrame.zw + outFrame.xy;' + }, + disable: !!disable + }; +}; + +module.exports = MakeTexCoordFrameWrap; + + +/***/ }), + +/***/ 83786: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.WebGL.ShaderAdditionMakers + */ + +module.exports = { + + MakeAnimLength: __webpack_require__(84639), + MakeApplyFlatLighting: __webpack_require__(67155), + MakeApplyLighting: __webpack_require__(81084), + MakeApplyTint: __webpack_require__(44349), + MakeBoundedSampler: __webpack_require__(99501), + MakeDefineLights: __webpack_require__(6184), + MakeDefineTexCount: __webpack_require__(11653), + MakeFlatNormal: __webpack_require__(13198), + MakeGetNormalFromMap: __webpack_require__(40829), + MakeGetTexCoordOut: __webpack_require__(42792), + MakeGetTexRes: __webpack_require__(96049), + MakeGetTexture: __webpack_require__(33997), + MakeOutFrame: __webpack_require__(10455), + MakeOutInverseRotation: __webpack_require__(79532), + MakeRotationDatum: __webpack_require__(65217), + MakeSampleNormal: __webpack_require__(747), + MakeSmoothPixelArt: __webpack_require__(74505), + MakeTexCoordFrameClamp: __webpack_require__(44832), + MakeTexCoordFrameWrap: __webpack_require__(23295) + +}; + + +/***/ }), + +/***/ 89350: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2023 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.WebGL.Shaders + */ + +module.exports = { + + ApplyLighting: __webpack_require__(84547), + ApplyTint: __webpack_require__(11104), + BoundedSampler: __webpack_require__(81556), + ColorMatrixFrag: __webpack_require__(96293), + DefineBlockyTexCoord: __webpack_require__(78390), + DefineLights: __webpack_require__(11719), + DefineTexCoordFrameClamp: __webpack_require__(14030), + FilterBarrelFrag: __webpack_require__(10235), + FilterBlendFrag: __webpack_require__(65980), + FilterBlurHighFrag: __webpack_require__(20784), + FilterBlurLowFrag: __webpack_require__(65122), + FilterBlurMedFrag: __webpack_require__(60942), + FilterBokehFrag: __webpack_require__(43722), + FilterColorMatrixFrag: __webpack_require__(19883), + FilterDisplacementFrag: __webpack_require__(12886), + FilterGlowFrag: __webpack_require__(33016), + FilterMaskFrag: __webpack_require__(39603), + FilterPixelateFrag: __webpack_require__(99191), + FilterShadowFrag: __webpack_require__(69355), + FilterThresholdFrag: __webpack_require__(92636), + FlatFrag: __webpack_require__(73416), + FlatVert: __webpack_require__(91627), + GetNormalFromMap: __webpack_require__(84220), + GetTexRes: __webpack_require__(2860), + GetTexture: __webpack_require__(46432), + MultiFrag: __webpack_require__(98840), + MultiVert: __webpack_require__(44667), + OutInverseRotation: __webpack_require__(62807), + PointLightFrag: __webpack_require__(4127), + PointLightVert: __webpack_require__(89924), + ShaderQuadFrag: __webpack_require__(72823), + ShaderQuadVert: __webpack_require__(65884), + SimpleTextureVert: __webpack_require__(2807), + SpriteGPULayerFrag: __webpack_require__(49119), + SpriteGPULayerVert: __webpack_require__(3524), + TilemapGPULayerFrag: __webpack_require__(57532), + TilemapGPULayerVert: __webpack_require__(23879) + +}; + + +/***/ }), + +/***/ 26128: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * Wrapper for a WebGL buffer, containing all the information that was used + * to create it. This can be a VertexBuffer or IndexBuffer. + * + * A WebGLBuffer should never be exposed outside the WebGLRenderer, so the + * WebGLRenderer can handle context loss and other events without other + * systems having to be aware of it. Always use WebGLBufferWrapper instead. + * + * @class WebGLBufferWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. + * @param {ArrayBuffer} dataBuffer - An ArrayBuffer of data to store. The buffer will be permanently associated with this data. + * @param {GLenum} bufferType - The type of the buffer being created. + * @param {GLenum} bufferUsage - The usage of the buffer being created. gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW. + */ +var WebGLBufferWrapper = new Class({ + + initialize: + + function WebGLBufferWrapper (renderer, dataBuffer, bufferType, bufferUsage) + { + /** + * The WebGLRenderer instance that owns this wrapper. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The WebGLBuffer being wrapped by this class. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#webGLBuffer + * @type {?WebGLBuffer} + * @default null + * @since 3.80.0 + */ + this.webGLBuffer = null; + + /** + * The data associated with the buffer. + * + * Note that this will be used to recreate the buffer if the WebGL context is lost. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#dataBuffer + * @type {ArrayBuffer} + * @since 4.0.0 + */ + this.dataBuffer = dataBuffer; + + /** + * A Float32Array view of the dataBuffer. + * + * This will be `null` if the byte length of the dataBuffer + * is not divisible by Float32Array.BYTES_PER_ELEMENT (4). + * Such a buffer is only suited for use with 16-bit indices. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewF32 + * @type {Float32Array | null} + * @since 4.0.0 + */ + this.viewF32 = null; + + /** + * A Uint8Array view of the dataBuffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewU8 + * @type {Uint8Array} + * @since 4.0.0 + */ + this.viewU8 = new Uint8Array(dataBuffer); + + /** + * A Uint16Array view of the dataBuffer. + * + * This will be `null` if the byte length of the dataBuffer + * is not divisible by Uint16Array.BYTES_PER_ELEMENT (2). + * Such a buffer is only suited for use with byte data. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewU16 + * @type {Uint16Array | null} + * @since 4.0.0 + */ + this.viewU16 = null; + + /** + * A Uint32Array view of the dataBuffer. + * + * This will be `null` if the byte length of the dataBuffer + * is not divisible by Uint32Array.BYTES_PER_ELEMENT (4). + * Such a buffer is only suited for use with 16-bit indices. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewU32 + * @type {Uint32Array | null} + * @since 4.0.0 + */ + this.viewU32 = null; + + /** + * The type of the buffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#bufferType + * @type {GLenum} + * @since 3.80.0 + */ + this.bufferType = bufferType; + + /** + * The usage of the buffer. gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#bufferUsage + * @type {GLenum} + * @since 3.80.0 + */ + this.bufferUsage = bufferUsage; + + this.createViews(); + + this.createResource(); + }, + + /** + * Creates a WebGLBuffer for this WebGLBufferWrapper. + * + * This is called automatically by the constructor. It may also be + * called again if the WebGLBuffer needs re-creating. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#createResource + * @since 3.80.0 + */ + createResource: function () + { + var gl = this.renderer.gl; + + var bufferType = this.bufferType; + var webGLBuffer = gl.createBuffer(); + + this.webGLBuffer = webGLBuffer; + + this.bind(); + gl.bufferData(bufferType, this.dataBuffer, this.bufferUsage); + this.bind(true); + }, + + /** + * Binds this WebGLBufferWrapper to the current WebGLRenderingContext. + * It uses the bufferType of this wrapper to determine which binding point to use. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#bind + * @since 4.0.0 + * @param {boolean} [unbind=false] - Whether to unbind the buffer instead. + */ + bind: function (unbind) + { + var gl = this.renderer.gl; + var bufferType = this.bufferType; + var buffer = unbind ? null : this; + + if (bufferType === gl.ARRAY_BUFFER) + { + this.renderer.glWrapper.updateBindingsArrayBuffer({ + bindings: { arrayBuffer: buffer } + }); + } + else if (bufferType === gl.ELEMENT_ARRAY_BUFFER) + { + this.renderer.glWrapper.updateBindingsElementArrayBuffer({ + bindings: { elementArrayBuffer: buffer } + }); + } + }, + + /** + * Updates the data in this WebGLBufferWrapper. + * The dataBuffer must contain the new data to be uploaded to the GPU. + * Data will preserve its range from dataBuffer to the WebGLBuffer. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#update + * @since 4.0.0 + * @param {number} [bytes] - The number of bytes to update in the buffer. If not specified, the entire buffer will be updated. + * @param {number} [offset=0] - The offset into the buffer to start updating data at. + */ + update: function (bytes, offset) + { + var gl = this.renderer.gl; + + this.bind(); + + if (offset === undefined) + { + offset = 0; + } + + if (bytes === undefined) + { + gl.bufferSubData( + this.bufferType, + offset, + this.dataBuffer + ); + } + else + { + gl.bufferSubData( + this.bufferType, + offset, + this.viewU8.subarray(offset, offset + bytes) + ); + } + }, + + /** + * Resizes the dataBuffer of this WebGLBufferWrapper. + * This will recreate `dataBuffer` and the views into it. + * All data will be lost. + * All views into `dataBuffer` will be destroyed and recreated. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#resize + * @since 4.0.0 + * @param {number} bytes - The new size of the buffer in bytes. + */ + resize: function (bytes) + { + var gl = this.renderer.gl; + + this.dataBuffer = new ArrayBuffer(bytes); + + this.createViews(); + + this.bind(); + gl.bufferData(this.bufferType, this.dataBuffer, this.bufferUsage); + }, + + /** + * Creates the views into the dataBuffer. + * This is called internally. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#createViews + * @since 4.0.0 + * @private + */ + createViews: function () + { + var dataBuffer = this.dataBuffer; + + this.viewF32 = null; + if (dataBuffer.byteLength % Float32Array.BYTES_PER_ELEMENT === 0) + { + this.viewF32 = new Float32Array(dataBuffer); + } + + this.viewU8 = new Uint8Array(dataBuffer); + + this.viewU16 = null; + if (dataBuffer.byteLength % Uint16Array.BYTES_PER_ELEMENT === 0) + { + this.viewU16 = new Uint16Array(dataBuffer); + } + + this.viewU32 = null; + if (dataBuffer.byteLength % Uint32Array.BYTES_PER_ELEMENT === 0) + { + this.viewU32 = new Uint32Array(dataBuffer); + } + }, + + /** + * Remove this WebGLBufferWrapper from the GL context. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#destroy + * @since 3.80.0 + */ + destroy: function () + { + this.renderer.gl.deleteBuffer(this.webGLBuffer); + this.webGLBuffer = null; + this.dataBuffer = null; + this.viewF32 = null; + this.viewU8 = null; + this.viewU16 = null; + this.viewU32 = null; + this.renderer = null; + } +}); + +module.exports = WebGLBufferWrapper; + + +/***/ }), + +/***/ 84387: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +// Possible errors that can be thrown by `gl.checkFramebufferStatus()`. +var errors = { + 36054: 'Incomplete Attachment', + 36055: 'Missing Attachment', + 36057: 'Incomplete Dimensions', + 36061: 'Framebuffer Unsupported' +}; + +/** + * @typedef {object} Attachment + * @since 4.0.0 + * + * @property {GLenum} attachmentPoint - The attachment point for the attachment. This is a GLenum such as `gl.COLOR_ATTACHMENT0`, `gl.DEPTH_ATTACHMENT`, `gl.STENCIL_ATTACHMENT`, or `gl.DEPTH_STENCIL_ATTACHMENT`. + * @property {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} [texture] - The texture for the attachment. Either a texture or a renderbuffer is required. + * @property {WebGLRenderbuffer} [renderbuffer] - The renderbuffer for the attachment. Either a texture or a renderbuffer is required. + * @property {GLenum} [internalFormat] - The internal format for the renderbuffer. This is a GLenum such as `gl.DEPTH_STENCIL`. + */ + +/** + * @classdesc + * Wrapper for a WebGL frame buffer, + * containing all the information that was used to create it. + * + * A WebGLFramebuffer should never be exposed outside the WebGLRenderer, + * so the WebGLRenderer can handle context loss and other events + * without other systems having to be aware of it. + * Always use WebGLFramebufferWrapper instead. + * + * This also manages the attachments to the framebuffer, + * including renderbuffer life cycle. + * + * @class WebGLFramebufferWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer this WebGLFramebuffer belongs to. + * @param {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} colorAttachments - The color textures where the color pixels are written. If empty, the canvas will be used as the color attachment. Only the first color attachment is used in default WebGL1. + * @param {boolean} [addStencilBuffer=false] - Whether to add a stencil buffer to the framebuffer. If the canvas is used as the color attachment, this will be ignored. + * @param {boolean} [addDepthBuffer=false] - Whether to add a depth buffer to the framebuffer. If depth and stencil are both provided, they will be combined into a single depth-stencil buffer. If the canvas is used as the color attachment, this will be ignored. + */ +var WebGLFramebufferWrapper = new Class({ + + initialize: + + function WebGLFramebufferWrapper (renderer, colorAttachments, addStencilBuffer, addDepthBuffer) + { + var gl = renderer.gl; + + /** + * The WebGLFramebuffer being wrapped by this class. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * If the FrameBuffer is using the canvas as the color attachment, + * this property will be `null`. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#webGLFramebuffer + * @type {?WebGLFramebuffer} + * @default null + * @since 3.80.0 + */ + this.webGLFramebuffer = null; + + /** + * The WebGLRenderer this WebGLFramebuffer belongs to. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * Whether to use the canvas as the color attachment. + * If this is true, a framebuffer will not be created. + * This is useful for the main framebuffer, which is created by the browser. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#useCanvas + * @type {boolean} + * @default false + * @since 4.0.0 + */ + this.useCanvas = !colorAttachments || colorAttachments.length === 0; + + /** + * Width of the depth stencil. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#width + * @type {number} + * @since 3.80.0 + */ + this.width = 0; + + /** + * Height of the depth stencil. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#height + * @type {number} + * @since 3.80.0 + */ + this.height = 0; + + /** + * Attachments to the framebuffer. These contain data such as + * the width, height, and renderbuffer or texture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#attachments + * @type {Attachment[]} + * @since 4.0.0 + */ + this.attachments = []; + + if (!this.useCanvas) + { + for (var i = 0; i < colorAttachments.length; i++) + { + this.attachments.push({ + texture: colorAttachments[i], + attachmentPoint: gl.COLOR_ATTACHMENT0 + i + }); + + if (i === 0) + { + this.width = colorAttachments[i].width; + this.height = colorAttachments[i].height; + } + else if (colorAttachments[i].width !== this.width || colorAttachments[i].height !== this.height) + { + throw new Error('Color attachments must have the same dimensions'); + } + } + + // Only generate depth and stencil buffers if color attachments are provided. + // Generate a depth-stencil buffer if both are requested. + // These must be attached after the color attachments, + // so that the framebuffer is complete when they're attached. + if (addDepthBuffer && addStencilBuffer) + { + this.attachments.push({ + attachmentPoint: gl.DEPTH_STENCIL_ATTACHMENT, + internalFormat: gl.DEPTH_STENCIL + }); + } + else if (addDepthBuffer) + { + this.attachments.push({ + attachmentPoint: gl.DEPTH_ATTACHMENT, + internalFormat: gl.DEPTH_COMPONENT16 + }); + } + else if (addStencilBuffer) + { + this.attachments.push({ + attachmentPoint: gl.STENCIL_ATTACHMENT, + internalFormat: gl.STENCIL_INDEX8 + }); + } + } + + /** + * The color texture where the color pixels are written. + * + * This will be `null` if the canvas is used as the color attachment. + * It is the first color attachment on the framebuffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#renderTexture + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @default null + * @since 3.80.0 + */ + this.renderTexture = null; + + if (this.attachments[0]) + { + this.renderTexture = this.attachments[0].texture; + } + + this.createResource(); + }, + + /** + * Creates a WebGLFramebuffer from the given parameters. + * + * This is called automatically by the constructor. It may also be + * called again if the WebGLFramebuffer needs re-creating. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#createResource + * @since 3.80.0 + */ + createResource: function () + { + if (this.useCanvas) { return; } + + var renderer = this.renderer; + var glWrapper = renderer.glWrapper; + var gl = renderer.gl; + + // Remove any existing framebuffer. + if (this.webGLFramebuffer) + { + gl.deleteFramebuffer(this.webGLFramebuffer); + for (var i = 0; i < this.attachments.length; i++) + { + var attachment = this.attachments[i]; + if (!attachment.texture) + { + gl.deleteRenderbuffer(attachment.renderbuffer); + } + } + } + + // Create framebuffer. + var framebuffer = gl.createFramebuffer(); + this.webGLFramebuffer = framebuffer; + glWrapper.updateBindingsFramebuffer({ + bindings: + { + framebuffer: this + } + }, true); + + // Create attachments. + for (i = 0; i < this.attachments.length; i++) + { + attachment = this.attachments[i]; + var attachmentPoint = attachment.attachmentPoint; + var texture = attachment.texture; + + if (texture) + { + texture.isRenderTexture = true; + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, texture.webGLTexture, 0); + } + else + { + // Check for completeness. + // We must do this after the color attachments are created, + // or the framebuffer will be incomplete and cannot accept + // a renderbuffer. + var complete = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (complete !== gl.FRAMEBUFFER_COMPLETE) + { + throw new Error('Framebuffer status: ' + (errors[complete] || complete)); + } + + var renderbuffer = gl.createRenderbuffer(); + glWrapper.updateBindingsRenderbuffer({ + bindings: + { + renderbuffer: renderbuffer + } + }); + gl.renderbufferStorage(gl.RENDERBUFFER, attachment.internalFormat, this.width, this.height); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, renderbuffer); + + // We could check for completeness again here, + // but the invocations were checked during development, + // and the renderbuffer is free of error. + + attachment.renderbuffer = renderbuffer; + } + } + }, + + /** + * Resizes the attachments of this WebGLFramebufferWrapper. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#resize + * @since 4.0.0 + * @param {number} width - The new width of the framebuffer. + * @param {number} height - The new height of the framebuffer. + */ + resize: function (width, height) + { + if (this.useCanvas) + { + return; + } + + this.width = width; + this.height = height; + + this.renderTexture.resize(width, height); + + this.createResource(); + }, + + /** + * Destroys this WebGLFramebufferWrapper. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLFramebufferWrapper#destroy + * @since 3.80.0 + */ + destroy: function () + { + if (this.renderer === null) + { + return; + } + + var renderer = this.renderer; + var gl = renderer.gl; + + for (var i = 0; i < this.attachments.length; i++) + { + var attachment = this.attachments[i]; + if (attachment.texture) + { + renderer.glWrapper.updateBindingsFramebuffer({ + bindings: + { + framebuffer: this + } + }); + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment.attachmentPoint, gl.TEXTURE_2D, null, 0); + renderer.deleteTexture(attachment.texture); + } + else + { + gl.deleteRenderbuffer(attachment.renderbuffer); + } + } + + gl.deleteFramebuffer(this.webGLFramebuffer); + + // Remove bindings from the global state. + renderer.glWrapper.updateBindingsFramebuffer({ + bindings: + { + framebuffer: null, + renderbuffer: null + } + }); + + this.attachments.length = 0; + this.renderTexture = null; + this.webGLFramebuffer = null; + this.renderer = null; + } +}); + +module.exports = WebGLFramebufferWrapper; + + +/***/ }), + +/***/ 37959: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var WebGLGlobalParametersFactory = __webpack_require__(53314); + +/** + * @classdesc + * Wrapper for the WebGL global state. + * + * @class WebGLGlobalWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer to create the WebGLGlobalWrapper for. + */ +var WebGLGlobalWrapper = new Class({ + + initialize: + + function WebGLGlobalWrapper (renderer) + { + /** + * The WebGLRenderer this WebGLGlobalWrapper is associated with. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The current state of the WebGL global state. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#state + * @type {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} + * @since 4.0.0 + */ + this.state = WebGLGlobalParametersFactory.getDefault(renderer); + }, + + /** + * Sets the global WebGL state. Parameters are updated on the + * WebGLRenderingContext only if they are defined in the input `state`, + * and different from the current state. + * + * When `force` is true, and `state` is defined, parameters on `state` + * are always set, regardless of the current state. + * + * When `force` is true, and `state` is undefined, the current state is + * used to reset all the parameters. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#update + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} [state] - The state to set. If undefined, the current state is used when `force` is `true`. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + * @param {boolean} [vaoLast=false] - If `true`, the VAO will be set last. + * Otherwise, it will be set first. This is useful when performing state + * changes that will affect a VAO, such as `bindings.elementArrayBuffer`. + */ + update: function (state, force, vaoLast) + { + if (state === undefined) + { + if (!force) + { + return; + } + state = this.state; + } + if (force === undefined) { force = false; } + if (vaoLast === undefined) { vaoLast = false; } + + if (state.vao !== undefined && !vaoLast) + { + this.updateVAO(state, force); + } + if (state.bindings !== undefined) + { + this.updateBindings(state, force); + } + if (state.blend !== undefined) + { + this.updateBlend(state, force); + } + if (state.colorClearValue !== undefined) + { + this.updateColorClearValue(state, force); + } + if (state.colorWritemask !== undefined) + { + this.updateColorWritemask(state, force); + } + if (state.cullFace !== undefined) + { + this.updateCullFace(state, force); + } + if (state.depthTest !== undefined) + { + this.updateDepthTest(state, force); + } + if (state.scissor !== undefined) + { + // Must happen after setting the framebuffer. + this.updateScissor(state, force); + } + if (state.stencil !== undefined) + { + this.updateStencil(state, force); + } + if (state.texturing !== undefined) + { + this.updateTexturing(state, force); + } + if (state.viewport !== undefined) + { + this.updateViewport(state, force); + } + if (state.vao !== undefined && vaoLast) + { + this.updateVAO(state, force); + } + }, + + /** + * Updates the bindings state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindings + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindings: function (state, force) + { + var bindings = state.bindings; + + if (bindings.activeTexture !== undefined) + { + this.updateBindingsActiveTexture(state, force); + } + if (bindings.arrayBuffer !== undefined) + { + this.updateBindingsArrayBuffer(state, force); + } + if (bindings.elementArrayBuffer !== undefined) + { + this.updateBindingsElementArrayBuffer(state, force); + } + if (bindings.framebuffer !== undefined) + { + this.updateBindingsFramebuffer(state, force); + } + if (bindings.program !== undefined) + { + this.updateBindingsProgram(state, force); + } + if (bindings.renderbuffer !== undefined) + { + this.updateBindingsRenderbuffer(state, force); + } + }, + + /** + * Updates the active texture unit state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindingsActiveTexture + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindingsActiveTexture: function (state, force) + { + var activeTexture = state.bindings.activeTexture; + + var different = activeTexture !== this.state.bindings.activeTexture; + + if (different) + { + this.state.bindings.activeTexture = activeTexture; + } + if (different || force) + { + var gl = this.renderer.gl; + gl.activeTexture(gl.TEXTURE0 + activeTexture); + } + }, + + /** + * Updates the vertex array buffer state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindingsArrayBuffer + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindingsArrayBuffer: function (state, force) + { + var arrayBuffer = state.bindings.arrayBuffer; + var gl = this.renderer.gl; + if ( + arrayBuffer !== null && + arrayBuffer.bufferType !== gl.ARRAY_BUFFER + ) + { + throw new Error('Invalid buffer type for ARRAY_BUFFER'); + } + + var different = arrayBuffer !== this.state.bindings.arrayBuffer; + + if (different) + { + this.state.bindings.arrayBuffer = arrayBuffer; + } + if (different || force) + { + var webGLBuffer = arrayBuffer ? arrayBuffer.webGLBuffer : null; + gl.bindBuffer(gl.ARRAY_BUFFER, webGLBuffer); + } + }, + + /** + * Updates the index array buffer state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindingsElementArrayBuffer + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindingsElementArrayBuffer: function (state, force) + { + var elementArrayBuffer = state.bindings.elementArrayBuffer; + var gl = this.renderer.gl; + if ( + elementArrayBuffer !== null && + elementArrayBuffer.bufferType !== gl.ELEMENT_ARRAY_BUFFER + ) + { + throw new Error('Invalid buffer type for ELEMENT_ARRAY_BUFFER'); + } + + var different = elementArrayBuffer !== this.state.bindings.elementArrayBuffer; + + if (different) + { + this.state.bindings.elementArrayBuffer = elementArrayBuffer; + } + if (different || force) + { + var webGLBuffer = elementArrayBuffer ? elementArrayBuffer.webGLBuffer : null; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, webGLBuffer); + } + }, + + /** + * Updates the framebuffer state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindingsFramebuffer + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindingsFramebuffer: function (state, force) + { + var framebuffer = state.bindings.framebuffer; + + var different = framebuffer !== this.state.bindings.framebuffer; + + if (different) + { + this.state.bindings.framebuffer = framebuffer; + } + if (different || force) + { + var gl = this.renderer.gl; + var webGLFramebuffer = framebuffer ? framebuffer.webGLFramebuffer : null; + gl.bindFramebuffer(gl.FRAMEBUFFER, webGLFramebuffer); + } + }, + + /** + * Updates the program state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindingsProgram + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindingsProgram: function (state, force) + { + var program = state.bindings.program; + + var different = program !== this.state.bindings.program; + + if (different) + { + this.state.bindings.program = program; + } + if (different || force) + { + var webGLProgram = program ? program.webGLProgram : null; + this.renderer.gl.useProgram(webGLProgram); + } + }, + + /** + * Updates the renderbuffer state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBindingsRenderbuffer + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBindingsRenderbuffer: function (state, force) + { + var renderbuffer = state.bindings.renderbuffer; + + var different = renderbuffer !== this.state.bindings.renderbuffer; + + if (different) + { + this.state.bindings.renderbuffer = renderbuffer; + } + if (different || force) + { + var gl = this.renderer.gl; + var webGLRenderbuffer = renderbuffer || null; + gl.bindRenderbuffer(gl.RENDERBUFFER, webGLRenderbuffer); + } + }, + + /** + * Updates the blend state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBlend + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBlend: function (state, force) + { + var blend = state.blend; + if (blend.enabled !== undefined) + { + this.updateBlendEnabled(state, force); + } + if (blend.color !== undefined) + { + this.updateBlendColor(state, force); + } + if (blend.equation !== undefined) + { + this.updateBlendEquation(state, force); + } + if (blend.func !== undefined) + { + this.updateBlendFunc(state, force); + } + }, + + /** + * Updates the blend color. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBlendColor + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBlendColor: function (state, force) + { + var color = state.blend.color; + var r = color[0]; + var g = color[1]; + var b = color[2]; + var a = color[3]; + + var different = r !== this.state.blend.color[0] || + g !== this.state.blend.color[1] || + b !== this.state.blend.color[2] || + a !== this.state.blend.color[3]; + + if (different) + { + this.state.blend.color = [ r, g, b, a ]; + } + if (different || force) + { + this.renderer.gl.blendColor(r, g, b, a); + } + }, + + /** + * Updates the blend enabled state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBlendEnabled + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBlendEnabled: function (state, force) + { + var enabled = state.blend.enabled; + + var different = enabled !== this.state.blend.enabled; + + if (different) + { + this.state.blend.enabled = enabled; + } + if (different || force) + { + var gl = this.renderer.gl; + if (enabled) + { + gl.enable(gl.BLEND); + } + else + { + gl.disable(gl.BLEND); + } + } + }, + + /** + * Updates the blend equation state. + * + * Equations are always treated as separate. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBlendEquation + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBlendEquation: function (state, force) + { + var equation = state.blend.equation; + + var different = equation[0] !== this.state.blend.equation[0] || + equation[1] !== this.state.blend.equation[1]; + + if (different) + { + this.state.blend.equation = [ equation[0], equation[1] ]; + } + if (different || force) + { + this.renderer.gl.blendEquationSeparate(equation[0], equation[1]); + } + }, + + /** + * Updates the blend function state. + * + * Functions are always treated as separate. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateBlendFunc + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateBlendFunc: function (state, force) + { + var func = state.blend.func; + + var different = + func[0] !== this.state.blend.func[0] || + func[1] !== this.state.blend.func[1] || + func[2] !== this.state.blend.func[2] || + func[3] !== this.state.blend.func[3]; + + if (different) + { + this.state.blend.func = [ func[0], func[1], func[2], func[3] ]; + } + if (different || force) + { + this.renderer.gl.blendFuncSeparate(func[0], func[1], func[2], func[3]); + } + }, + + /** + * Updates the color clear value. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateColorClearValue + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateColorClearValue: function (state, force) + { + var colorClearValue = state.colorClearValue; + var r = colorClearValue[0]; + var g = colorClearValue[1]; + var b = colorClearValue[2]; + var a = colorClearValue[3]; + + var different = r !== this.state.colorClearValue[0] || + g !== this.state.colorClearValue[1] || + b !== this.state.colorClearValue[2] || + a !== this.state.colorClearValue[3]; + + if (different) + { + this.state.colorClearValue = [ r, g, b, a ]; + } + + if (different || force) + { + this.renderer.gl.clearColor(r, g, b, a); + } + }, + + /** + * Updates the color writemask. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateColorWritemask + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateColorWritemask: function (state, force) + { + var colorWritemask = state.colorWritemask; + var r = colorWritemask[0]; + var g = colorWritemask[1]; + var b = colorWritemask[2]; + var a = colorWritemask[3]; + + var different = r !== this.state.colorWritemask[0] || + g !== this.state.colorWritemask[1] || + b !== this.state.colorWritemask[2] || + a !== this.state.colorWritemask[3]; + + if (different) + { + this.state.colorWritemask = [ r, g, b, a ]; + } + if (different || force) + { + this.renderer.gl.colorMask(r, g, b, a); + } + }, + + /** + * Updates the cull face state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateCullFace + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateCullFace: function (state, force) + { + var cullFace = !!state.cullFace; + + var different = cullFace !== this.state.cullFace; + + if (different) + { + this.state.cullFace = cullFace; + } + if (different || force) + { + var gl = this.renderer.gl; + if (cullFace) + { + gl.enable(gl.CULL_FACE); + } + else + { + gl.disable(gl.CULL_FACE); + } + } + }, + + /** + * Updates the depth test state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateDepthTest + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateDepthTest: function (state, force) + { + var depthTest = !!state.depthTest; + + var different = depthTest !== this.state.depthTest; + + if (different) + { + this.state.depthTest = depthTest; + } + if (different || force) + { + var gl = this.renderer.gl; + if (depthTest) + { + gl.enable(gl.DEPTH_TEST); + } + else + { + gl.disable(gl.DEPTH_TEST); + } + } + }, + + /** + * Updates the scissor state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateScissor + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateScissor: function (state, force) + { + var scissor = state.scissor; + if (scissor.enable !== undefined) + { + this.updateScissorEnabled(state, force); + } + if (scissor.box !== undefined) + { + this.updateScissorBox(state, force); + } + }, + + /** + * Updates the scissor enabled state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateScissorEnabled + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateScissorEnabled: function (state, force) + { + var enable = state.scissor.enable; + + var different = enable !== this.state.scissor.enable; + + if (different) + { + this.state.scissor.enable = enable; + } + if (different || force) + { + var gl = this.renderer.gl; + if (enable) + { + gl.enable(gl.SCISSOR_TEST); + } + else + { + gl.disable(gl.SCISSOR_TEST); + } + } + }, + + /** + * Updates the scissor box state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateScissorBox + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateScissorBox: function (state, force) + { + var scissorBox = state.scissor.box; + var x = scissorBox[0]; + var y = scissorBox[1]; + var width = scissorBox[2]; + var height = scissorBox[3]; + + var different = x !== this.state.scissor.box[0] || + y !== this.state.scissor.box[1] || + width !== this.state.scissor.box[2] || + height !== this.state.scissor.box[3]; + + if (different) + { + this.state.scissor.box = [ x, y, width, height ]; + } + if (different || force) + { + this.renderer.gl.scissor( + x, + y, + width, + height + ); + } + }, + + /** + * Updates the stencil state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateStencil + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateStencil: function (state, force) + { + var stencil = state.stencil; + if (stencil.clear !== undefined) + { + this.updateStencilClear(state, force); + } + if (stencil.enabled !== undefined) + { + this.updateStencilEnabled(state, force); + } + if (stencil.func !== undefined) + { + this.updateStencilFunc(state, force); + } + if (stencil.op !== undefined) + { + this.updateStencilOp(state, force); + } + }, + + /** + * Updates the stencil clear state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateStencilClear + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateStencilClear: function (state, force) + { + var clear = state.stencil.clear; + + var different = clear !== this.state.stencil.clear; + + if (different) + { + this.state.stencil.clear = clear; + } + if (different || force) + { + this.renderer.gl.clearStencil(clear); + } + }, + + /** + * Updates the stencil enabled state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateStencilEnabled + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateStencilEnabled: function (state, force) + { + var enabled = state.stencil.enabled; + + var different = enabled !== this.state.stencil.enabled; + + if (different) + { + this.state.stencil.enabled = enabled; + } + if (different || force) + { + var gl = this.renderer.gl; + if (enabled) + { + gl.enable(gl.STENCIL_TEST); + } + else + { + gl.disable(gl.STENCIL_TEST); + } + } + }, + + /** + * Updates the stencil function state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateStencilFunc + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateStencilFunc: function (state, force) + { + var func = state.stencil.func; + + var different = func.func !== this.state.stencil.func.func || + func.ref !== this.state.stencil.func.ref || + func.mask !== this.state.stencil.func.mask; + + if (different) + { + this.state.stencil.func = { func: func.func, ref: func.ref, mask: func.mask }; + } + if (different || force) + { + var gl = this.renderer.gl; + gl.stencilFunc(func.func, func.ref, func.mask); + } + }, + + /** + * Updates the stencil operation state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateStencilOp + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateStencilOp: function (state, force) + { + var op = state.stencil.op; + + var different = op.fail !== this.state.stencil.op.fail || + op.zfail !== this.state.stencil.op.zfail || + op.zpass !== this.state.stencil.op.zpass; + + if (different) + { + this.state.stencil.op = { fail: op.fail, zfail: op.zfail, zpass: op.zpass }; + } + if (different || force) + { + var gl = this.renderer.gl; + gl.stencilOp(op.fail, op.zfail, op.zpass); + } + }, + + /** + * Updates the texturing state, which takes effect when creating a texture. + * This includes `flipY` and `premultiplyAlpha`. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateTexturing + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateTexturing: function (state, force) + { + var texturing = state.texturing; + if (texturing.flipY !== undefined) + { + this.updateTexturingFlipY(state, force); + } + if (texturing.premultiplyAlpha !== undefined) + { + this.updateTexturingPremultiplyAlpha(state, force); + } + }, + + /** + * Updates the texture flipY state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateTexturingFlipY + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateTexturingFlipY: function (state, force) + { + var flipY = state.texturing.flipY; + + var different = flipY !== this.state.texturing.flipY; + + if (different) + { + this.state.texturing.flipY = flipY; + } + if (different || force) + { + var gl = this.renderer.gl; + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + } + }, + + /** + * Updates the texture premultiplyAlpha state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateTexturingPremultiplyAlpha + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateTexturingPremultiplyAlpha: function (state, force) + { + var premultiplyAlpha = state.texturing.premultiplyAlpha; + + var different = premultiplyAlpha !== this.state.texturing.premultiplyAlpha; + + if (different) + { + this.state.texturing.premultiplyAlpha = premultiplyAlpha; + } + if (different || force) + { + var gl = this.renderer.gl; + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + } + }, + + /** + * Updates the vertex array object state. + * + * Note that the VAO is automatically affected by + * bindings of `elementArrayBuffer` and any attribute settings, + * as written in WebGL. When binding the VAO, ensure that other + * bindings come before or after, as you intend. + * When using `update`, the VAO is set first by default. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateVAO + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateVAO: function (state, force) + { + var vao = state.vao; + + var different = vao !== this.state.vao; + + if (different) + { + this.state.vao = vao; + } + if (different || force) + { + var extVAO = this.renderer.vaoExtension; + + if (vao) + { + extVAO.bindVertexArrayOES(vao.vertexArrayObject); + } + else + { + extVAO.bindVertexArrayOES(null); + } + } + }, + + /** + * Updates the viewport state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLGlobalWrapper#updateViewport + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} state - The state to set. + * @param {boolean} [force=false] - If `true`, the state will be set regardless of the current state. + */ + updateViewport: function (state, force) + { + var viewport = state.viewport; + var x = viewport[0]; + var y = viewport[1]; + var width = viewport[2]; + var height = viewport[3]; + + var different = x !== this.state.viewport[0] || + y !== this.state.viewport[1] || + width !== this.state.viewport[2] || + height !== this.state.viewport[3]; + + if (different) + { + this.state.viewport = [ x, y, width, height ]; + } + if (different || force) + { + this.renderer.gl.viewport(x, y, width, height); + } + } +}); + +module.exports = WebGLGlobalWrapper; + + +/***/ }), + +/***/ 1482: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Map = __webpack_require__(90330); +var Class = __webpack_require__(83419); + +function isDifferent (a, b) +{ + if (a === b) + { + return false; + } + if (Number.isNaN(a) || a === undefined) + { + if (Number.isNaN(b) || b === undefined) + { + return false; + } + } + return true; +} + +/** + * @classdesc + * Wrapper for a WebGL program, containing all the information that was used to create it. + * + * A WebGLProgram should never be exposed outside the WebGLRenderer, so the WebGLRenderer + * can handle context loss and other events without other systems having to be aware of it. + * Always use WebGLProgramWrapper instead. + * + * @class WebGLProgramWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. + * @param {string} vertexSource - The vertex shader source code as a string. + * @param {string} fragmentShader - The fragment shader source code as a string. + */ +var WebGLProgramWrapper = new Class({ + + initialize: + + function WebGLProgramWrapper (renderer, vertexSource, fragmentSource) + { + /** + * The WebGLRenderer instance that owns this wrapper. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The WebGLProgram being wrapped by this class. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#webGLProgram + * @type {?WebGLProgram} + * @default null + * @since 3.80.0 + */ + this.webGLProgram = null; + + /** + * Whether this program is currently being compiled. + * This will always be false, unless parallel shader compilation + * is enabled via `config.render.skipUnreadyShaders`. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#compiling + * @type {boolean} + * @default false + * @readonly + * @since 4.0.0 + */ + this.compiling = false; + + /** + * The time at which the compilation of this program started. + * This is used to track the time taken to compile the program. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#_compileStartTime + * @type {number} + * @private + * @since 4.0.0 + */ + this._compileStartTime = 0; + + /** + * The time taken to compile this program, in milliseconds. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#compileTimeMs + * @type {number} + * @readonly + * @since 4.0.0 + */ + this.compileTimeMs = 0; + + /** + * The WebGL state necessary to bind this program. + * + * This is used internally to accelerate state changes. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#glState + * @type {Phaser.Types.Renderer.WebGL.WebGLGlobalParameters} + * @since 4.0.0 + */ + this.glState = { bindings: { program: this } }; + + /** + * The vertex shader source code as a string. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#vertexSource + * @type {string} + * @since 3.80.0 + */ + this.vertexSource = vertexSource; + + /** + * The fragment shader source code as a string. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#fragmentSource + * @type {string} + * @since 3.80.0 + */ + this.fragmentSource = fragmentSource; + + /** + * The vertex shader object. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#_vertexShader + * @type {WebGLShader} + * @default null + * @private + * @since 4.0.0 + */ + this._vertexShader = null; + + /** + * The fragment shader object. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#_fragmentShader + * @type {WebGLShader} + * @default null + * @private + * @since 4.0.0 + */ + this._fragmentShader = null; + + /** + * The attribute state of this program. + * + * These represent the actual state in WebGL, and are only updated when + * the program is used to draw. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#glAttributes + * @type {Array<{ location: GLint, name: string, size: number, type: GLenum }>} + * @since 4.0.0 + */ + this.glAttributes = []; + + /** + * Map of attribute names to their indexes in `glAttributes`. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#glAttributeNames + * @type {Map} + * @since 4.0.0 + */ + this.glAttributeNames = new Map(); + + /** + * The buffer which this program is using for its attributes. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#glAttributeBuffer + * @type {?WebGLBuffer} + * @default null + * @since 4.0.0 + */ + this.glAttributeBuffer = null; + + /** + * The uniform state of this program. + * + * These represent the actual state in WebGL, and are only updated when + * the program is used to draw. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#glUniforms + * @type {Map} + * @since 4.0.0 + */ + this.glUniforms = new Map(); + + /** + * Requests to update the uniform state. + * Set a request by name to a new value. + * These are only processed when the program is used to draw. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#uniformRequests + * @type {Map} + * @since 4.0.0 + */ + this.uniformRequests = new Map(); + + this.createResource(); + }, + + /** + * Creates a WebGLProgram from the given vertex and fragment shaders. + * + * This is called automatically by the constructor. It may also be + * called again if the WebGLProgram needs re-creating. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#createResource + * @throws {Error} If the shaders failed to compile or link. + * @since 3.80.0 + */ + createResource: function () + { + var renderer = this.renderer; + var gl = renderer.gl; + + // Ensure that there is no vertex buffer associated with this program, + // so that the attributes are reset. + this.glAttributeBuffer = null; + + if (gl.isContextLost()) + { + // GL state can't be updated right now. + // `createResource` will run when the context is restored. + return; + } + + this.compiling = true; + this._compileStartTime = performance.now(); + + // Unbind current program before creating a new one. + // Otherwise, the old program will stay in use, + // and cause errors. + if (renderer.glWrapper.state.bindings.program === this) + { + renderer.glWrapper.updateBindingsProgram({ + bindings: { program: null } + }); + } + + var program = gl.createProgram(); + + this.webGLProgram = program; + + var vs = gl.createShader(gl.VERTEX_SHADER); + var fs = gl.createShader(gl.FRAGMENT_SHADER); + + this._vertexShader = vs; + this._fragmentShader = fs; + + gl.shaderSource(vs, this.vertexSource); + gl.shaderSource(fs, this.fragmentSource); + + gl.compileShader(vs); + gl.compileShader(fs); + + gl.attachShader(program, vs); + gl.attachShader(program, fs); + + gl.linkProgram(program); + + if (!renderer.game.config.skipUnreadyShaders) + { + this._completeProgram(); + } + }, + + /** + * Poll shader compilation status, and complete the program if it is ready. + * This is only called if `skipUnreadyShaders` is enabled + * and the KHR_parallel_shader_compile extension is available. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#checkParallelCompile + * @since 4.0.0 + */ + checkParallelCompile: function () + { + var renderer = this.renderer; + var gl = renderer.gl; + var ext = renderer.parallelShaderCompileExtension; + + if (!ext || !gl.getProgramParameter(this.webGLProgram, ext.COMPLETION_STATUS_KHR)) + { + return; + } + + this._completeProgram(); + }, + + /** + * Complete the program after the shaders have compiled. + * This checks the status of the shaders and the program, + * and throws an error if they failed to compile. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#_completeProgram + * @private + * @since 4.0.0 + */ + _completeProgram: function () + { + var program = this.webGLProgram; + var renderer = this.renderer; + var gl = renderer.gl; + var vs = this._vertexShader; + var fs = this._fragmentShader; + + var failed = 'Shader failed:\n'; + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) + { + if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) + { + console.log(this.vertexSource); + throw new Error('Vertex ' + failed + gl.getShaderInfoLog(vs)); + } + + if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) + { + console.log(this.fragmentSource); + throw new Error('Fragment ' + failed + gl.getShaderInfoLog(fs)); + } + console.log(this.vertexSource, this.fragmentSource); + throw new Error('Link Shader failed:' + gl.getProgramInfoLog(program)); + } + + this._setupAttributesAndUniforms(); + + this.compileTimeMs = performance.now() - this._compileStartTime; + this.compiling = false; + }, + + /** + * Set up the attributes and uniforms for this program. + * This is called after the program is created or re-created. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#_setupAttributesAndUniforms + * @private + * @since 4.0.0 + */ + _setupAttributesAndUniforms: function () + { + var program = this.webGLProgram; + var renderer = this.renderer; + var gl = renderer.gl; + var _this = this; + + // Extract attributes. + this.glAttributeNames.clear(); + this.glAttributes.length = 0; + var attributeCount = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); + + for (var index = 0; index < attributeCount; index++) + { + var attribute = gl.getActiveAttrib(program, index); + var location = gl.getAttribLocation(program, attribute.name); + + this.glAttributeNames.set(attribute.name, index); + this.glAttributes[index] = { + location: location, + name: attribute.name, + size: attribute.size, + type: attribute.type + }; + } + + // Send the old uniforms to the request map, + // so they are recreated with the new program. + this.glUniforms.each(function (name, uniform) + { + if (!_this.uniformRequests.has(name)) + { + _this.uniformRequests.set(name, uniform.value); + } + }); + + this.glUniforms.clear(); + var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + + for (index = 0; index < uniformCount; index++) + { + var uniform = gl.getActiveUniform(program, index); + var setter = renderer.shaderSetters.constants[uniform.type]; + + var initialValue = 0; + var terms = uniform.size * setter.size; + if (terms > 1) + { + initialValue = setter.baseType === gl.FLOAT + ? new Float32Array(terms) + : new Int32Array(terms); + } + + this.glUniforms.set(uniform.name, { + location: gl.getUniformLocation(program, uniform.name), + size: uniform.size, + type: uniform.type, + value: initialValue + }); + } + }, + + /** + * Set a uniform value for this WebGLProgram. + * + * This method doesn't set the WebGL value directly. + * Instead, it adds a request to the `uniformRequests` map. + * These requests are processed when the program is used to draw. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#setUniform + * @since 4.0.0 + * @param {string} name - The name of the uniform. + * @param {number|number[]|Int32Array|Float32Array} value - The value to set. + */ + setUniform: function (name, value) + { + this.uniformRequests.set(name, value); + }, + + /** + * Set this program as the active program in the WebGL context. + * + * This will also update the uniform state. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#bind + * @since 4.0.0 + */ + bind: function () + { + this.renderer.glWrapper.updateBindingsProgram(this.glState); + + this.uniformRequests.each(this._processUniformRequest.bind(this)); + + this.uniformRequests.clear(); + }, + + /** + * Process a request to update a uniform value. + * + * Requests are stored in the `uniformRequests` map, + * and only bound with this method when the program is used to draw. + * This ensures that the WebGL state is only updated when necessary. + * + * This method works from the description of uniforms provided by WebGL. + * It will only update uniforms that exist, in the fields that exist + * on those uniforms. If requests for invalid uniforms or fields are made, + * they are ignored. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#_processUniformRequest + * @since 4.0.0 + * @private + * @param {string} name - The name of the uniform. + * @param {number|number[]|Int32Array|Float32Array} value - The value to set. + */ + _processUniformRequest: function (name, value) + { + var renderer = this.renderer; + var gl = renderer.gl; + var uniform = this.glUniforms.get(name); + + if (!uniform) { return; } + + var uniformValue = uniform.value; + + // Update stored values if they are different. + if (uniformValue.length) + { + var different = false; + for (var i = 0; i < uniformValue.length; i++) + { + if (isDifferent(uniformValue[i], value[i])) + { + different = true; + uniformValue[i] = value[i]; + } + } + if (!different) { return; } + } + else + { + if (!isDifferent(uniformValue, value)) { return; } + uniformValue = value; + uniform.value = value; + } + + // Get info about the uniform. + var location = uniform.location; + var type = uniform.type; + var size = uniform.size; + var setter = renderer.shaderSetters.constants[type]; + + // Set the value. + if (setter.isMatrix) + { + setter.set.call(gl, location, false, uniformValue); + } + else if (size > 1) + { + setter.setV.call(gl, location, uniformValue); + } + else + { + switch (setter.size) + { + case 1: + setter.set.call(gl, location, value); + break; + case 2: + setter.set.call(gl, location, value[0], value[1]); + break; + case 3: + setter.set.call(gl, location, value[0], value[1], value[2]); + break; + case 4: + setter.set.call(gl, location, value[0], value[1], value[2], value[3]); + break; + } + } + }, + + /** + * Remove this WebGLProgram from the GL context. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper#destroy + * @since 3.80.0 + */ + destroy: function () + { + if (!this.webGLProgram) + { + return; + } + + var gl = this.renderer.gl; + if (!gl.isContextLost()) + { + if (this._vertexShader) + { + gl.deleteShader(this._vertexShader); + } + if (this._fragmentShader) + { + gl.deleteShader(this._fragmentShader); + } + gl.deleteProgram(this.webGLProgram); + + for (var i = 0; i < this.glAttributes.length; i++) + { + gl.disableVertexAttribArray(this.glAttributes[i].location); + } + this.glAttributes.length = 0; + + this.glUniforms.clear(); + } + + this.glAttributeBuffer = null; + this.glAttributeNames.clear(); + this.uniformRequests.clear(); + this._vertexShader = null; + this._fragmentShader = null; + this.webGLProgram = null; + this.renderer = null; + } +}); + +module.exports = WebGLProgramWrapper; + + +/***/ }), + +/***/ 86272: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * This class stores data necessary for setting WebGL shader uniforms + * and attributes. Most of it is static. Its purpose as a class is to + * load the WebGL functions provided by the rendering context. + * + * @class WebGLShaderSetterWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this WebGLShaderSetterWrapper. + */ +var WebGLShaderSetterWrapper = new Class({ + initialize: function WebGLShaderSetterWrapper (renderer) + { + var gl = renderer.gl; + + /** + * Map of GL Constants to their setter functions and relevant data sizes. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLShaderSetterWrapper#constants + * @type {Phaser.Types.Renderer.WebGL.Wrappers.ShaderSetterConstants} + * @since 4.0.0 + * @readonly + */ + this.constants = { + 0x1404: { + constant: gl.INT, + baseType: gl.INT, + size: 1, + bytes: 4, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x8B53: { + constant: gl.INT_VEC2, + baseType: gl.INT, + size: 2, + bytes: 4, + set: gl.uniform2i, + setV: gl.uniform2iv, + isMatrix: false + }, + 0x8B54: { + constant: gl.INT_VEC3, + baseType: gl.INT, + size: 3, + bytes: 4, + set: gl.uniform3i, + setV: gl.uniform3iv, + isMatrix: false + }, + 0x8B55: { + constant: gl.INT_VEC4, + baseType: gl.INT, + size: 4, + bytes: 4, + set: gl.uniform4i, + setV: gl.uniform4iv, + isMatrix: false + }, + 0x1406: { + constant: gl.FLOAT, + baseType: gl.FLOAT, + size: 1, + bytes: 4, + set: gl.uniform1f, + setV: gl.uniform1fv, + isMatrix: false + }, + 0x8B50: { + constant: gl.FLOAT_VEC2, + baseType: gl.FLOAT, + size: 2, + bytes: 4, + set: gl.uniform2f, + setV: gl.uniform2fv, + isMatrix: false + }, + 0x8B51: { + constant: gl.FLOAT_VEC3, + baseType: gl.FLOAT, + size: 3, + bytes: 4, + set: gl.uniform3f, + setV: gl.uniform3fv, + isMatrix: false + }, + 0x8B52: { + constant: gl.FLOAT_VEC4, + baseType: gl.FLOAT, + size: 4, + bytes: 4, + set: gl.uniform4f, + setV: gl.uniform4fv, + isMatrix: false + }, + 0x1405: { + constant: gl.UNSIGNED_INT, + baseType: gl.UNSIGNED_INT, + size: 1, + bytes: 4, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x1400: { + constant: gl.BYTE, + baseType: gl.BYTE, + size: 1, + bytes: 1, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x1401: { + constant: gl.UNSIGNED_BYTE, + baseType: gl.UNSIGNED_BYTE, + size: 1, + bytes: 1, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x1402: { + constant: gl.SHORT, + baseType: gl.SHORT, + size: 1, + bytes: 2, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x1403: { + constant: gl.UNSIGNED_SHORT, + baseType: gl.UNSIGNED_SHORT, + size: 1, + bytes: 2, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x8B56: { + constant: gl.BOOL, + baseType: gl.BOOL, + size: 1, + bytes: 4, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x8B57: { + constant: gl.BOOL_VEC2, + baseType: gl.BOOL, + size: 2, + bytes: 4, + set: gl.uniform2i, + setV: gl.uniform2iv, + isMatrix: false + }, + 0x8B58: { + constant: gl.BOOL_VEC3, + baseType: gl.BOOL, + size: 3, + bytes: 4, + set: gl.uniform3i, + setV: gl.uniform3iv, + isMatrix: false + }, + 0x8B59: { + constant: gl.BOOL_VEC4, + baseType: gl.BOOL, + size: 4, + bytes: 4, + set: gl.uniform4i, + setV: gl.uniform4iv, + isMatrix: false + }, + 0x8B5A: { + constant: gl.FLOAT_MAT2, + baseType: gl.FLOAT, + size: 4, + bytes: 4, + set: gl.uniformMatrix2fv, + setV: gl.uniformMatrix2fv, + isMatrix: true + }, + 0x8B5B: { + constant: gl.FLOAT_MAT3, + baseType: gl.FLOAT, + size: 9, + bytes: 4, + set: gl.uniformMatrix3fv, + setV: gl.uniformMatrix3fv, + isMatrix: true + }, + 0x8B5C: { + constant: gl.FLOAT_MAT4, + baseType: gl.FLOAT, + size: 16, + bytes: 4, + set: gl.uniformMatrix4fv, + setV: gl.uniformMatrix4fv, + isMatrix: true + }, + 0x8B5E: { + constant: gl.SAMPLER_2D, + baseType: gl.INT, + size: 1, + bytes: 4, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + }, + 0x8B60: { + constant: gl.SAMPLER_CUBE, + baseType: gl.INT, + size: 1, + bytes: 4, + set: gl.uniform1i, + setV: gl.uniform1iv, + isMatrix: false + } + }; + } +}); + +module.exports = WebGLShaderSetterWrapper; + + +/***/ }), + +/***/ 13760: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * A wrapper for the WebGLRenderingContext's texture units. + * It tracks which textures are bound to which units, and provides + * binding utilities. + * + * @class WebGLTextureUnitsWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. + */ +var WebGLTextureUnitsWrapper = new Class({ + + initialize: + + function WebGLTextureUnitsWrapper (renderer) + { + /** + * The WebGLRenderer instance that owns this wrapper. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The list of texture units available to the WebGLRenderingContext. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#units + * @type {Array} + * @since 4.0.0 + */ + this.units = []; + + /** + * List of the indexes of available texture units. + * Used in setting uniforms. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#unitIndices + * @type {number[]} + * @since 4.0.0 + */ + this.unitIndices = []; + + this.init(); + }, + + /** + * Initializes the texture units to `null`. The active texture unit + * will be 0 after this runs. + * + * This populates every texture unit with a 1x1 texture. + * This stops WebGL errors on MacOS. + * These textures are not wrapped, and are not intended to be used, + * so the texture units are recorded as null. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#init + * @since 4.0.0 + */ + init: function () + { + var gl = this.renderer.gl; + + this.units.length = 0; + this.unitIndices.length = 0; + + // Create a reusable 1x1 texture for all units. + var tempTexture = gl.createTexture(); + for (var unit = this.renderer.maxTextures - 1; unit >= 0; unit--) + { + // Leave the units undefined, so they can be set to null. + this.units[unit] = undefined; + this.renderer.glWrapper.updateBindingsActiveTexture({ + bindings: + { + activeTexture: unit + } + }); + gl.bindTexture(gl.TEXTURE_2D, tempTexture); + + // Enumerate the texture units. + this.unitIndices[unit] = unit; + } + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([ 0, 0, 255, 255 ])); + }, + + /** + * Binds a texture to a texture unit. + * + * This will change the active texture unit to the given unit, + * unless `forceActive` is false. + * + * This should be the only way to bind a texture to a unit. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#bind + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper|null} texture - The texture to bind, or null to unbind the unit. + * @param {number} unit - The texture unit to bind the texture to. + * @param {boolean} [force=false] - If true, it will bind the texture even if it is already bound. + * @param {boolean} [forceActive=true] - If true, it will change the active texture unit to the given unit even if it is already active. Otherwise, it will only change the active texture unit if it is not already active. + */ + bind: function (texture, unit, force, forceActive) + { + var needsBind = this.units[unit] !== texture; + if (force || (forceActive !== false) || needsBind) + { + this.renderer.glWrapper.updateBindingsActiveTexture({ + bindings: + { + activeTexture: unit + } + }, force); + } + if (!needsBind && !force) { return; } + this.units[unit] = texture; + var glTexture = texture ? texture.webGLTexture : null; + var gl = this.renderer.gl; + gl.bindTexture(gl.TEXTURE_2D, glTexture); + }, + + /** + * Set specific texture units to specific textures. + * + * The active texture unit may change to accommodate the bindings. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#bindUnits + * @since 4.0.0 + * @param {Array} textures - The textures to bind. Null values will be unbound. Undefined values will be skipped. + * @param {boolean} [force=false] - If true, it will bind all textures, even if they are already bound. + */ + bindUnits: function (textures, force) + { + var length = Math.min(textures.length, this.renderer.maxTextures); + for (var i = length - 1; i >= 0; i--) + { + if (textures[i] !== undefined) + { + this.bind(textures[i], i, force, false); + } + } + }, + + /** + * Unbinds all textures from all texture units. + * This will change the active texture unit to 0. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureUnitsWrapper#unbindAllUnits + * @since 4.0.0 + */ + unbindAllUnits: function () + { + for (var i = this.units.length - 1; i >= 0; i--) + { + this.bind(null, i, true, false); + } + } +}); + +module.exports = WebGLTextureUnitsWrapper; + + +/***/ }), + +/***/ 82751: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var IsSizePowerOfTwo = __webpack_require__(50030); + +/** + * @classdesc + * Wrapper for a WebGL texture, containing all the information that was used + * to create it. + * + * A WebGLTexture should never be exposed outside the WebGLRenderer, + * so the WebGLRenderer can handle context loss and other events + * without other systems having to be aware of it. + * Always use WebGLTextureWrapper instead. + * + * @class WebGLTextureWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 3.80.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. + * @param {number} mipLevel - Mip level of the texture. + * @param {number} minFilter - Filtering of the texture. + * @param {number} magFilter - Filtering of the texture. + * @param {number} wrapT - Wrapping mode of the texture. + * @param {number} wrapS - Wrapping mode of the texture. + * @param {number} format - Which format does the texture use. + * @param {?object} pixels - pixel data. + * @param {number} width - Width of the texture in pixels. + * @param {number} height - Height of the texture in pixels. + * @param {boolean} [pma=true] - Does the texture have premultiplied alpha? + * @param {boolean} [forceSize=false] - If `true` it will use the width and height passed to this method, regardless of the pixels dimension. + * @param {boolean} [flipY=true] - Sets the `UNPACK_FLIP_Y_WEBGL` flag the WebGL Texture uses during upload. + */ +var WebGLTextureWrapper = new Class({ + + initialize: + + function WebGLTextureWrapper (renderer, mipLevel, minFilter, magFilter, wrapT, wrapS, format, pixels, width, height, pma, forceSize, flipY) + { + if (flipY === undefined) { flipY = true; } + + /** + * The WebGLRenderer this WebGLTexture belongs to. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The WebGLTexture that this wrapper is wrapping. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#webGLTexture + * @type {?WebGLTexture} + * @default null + * @since 3.80.0 + */ + this.webGLTexture = null; + + /** + * Whether this is used as a RenderTexture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#isRenderTexture + * @type {boolean} + * @default false + * @since 3.80.0 + */ + this.isRenderTexture = false; + + /** + * Mip level of the texture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#mipLevel + * @type {number} + * @since 3.80.0 + */ + this.mipLevel = mipLevel; + + /** + * Filtering of the texture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#minFilter + * @type {number} + * @since 3.80.0 + */ + this.minFilter = minFilter; + + /** + * Filtering of the texture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#magFilter + * @type {number} + * @since 3.80.0 + */ + this.magFilter = magFilter; + + /** + * Wrapping mode of the texture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#wrapT + * @type {number} + * @since 3.80.0 + */ + this.wrapT = wrapT; + + /** + * Wrapping mode of the texture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#wrapS + * @type {number} + * @since 3.80.0 + */ + this.wrapS = wrapS; + + /** + * Which format does the texture use. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#format + * @type {number} + * @since 3.80.0 + */ + this.format = format; + + /** + * Pixel data. This is the source data used to create the WebGLTexture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#pixels + * @type {?object} + * @since 3.80.0 + */ + this.pixels = pixels; + + /** + * Width of the texture in pixels. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#width + * @type {number} + * @since 3.80.0 + */ + this.width = width; + + /** + * Height of the texture in pixels. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#height + * @type {number} + * @since 3.80.0 + */ + this.height = height; + + /** + * Does the texture have premultiplied alpha? + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#pma + * @type {boolean} + * @since 3.80.0 + */ + this.pma = (pma === undefined || pma === null) ? true : pma; + + /** + * Whether to use the width and height properties, regardless of pixel dimensions. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#forceSize + * @type {boolean} + * @since 3.80.0 + */ + this.forceSize = !!forceSize; + + /** + * Sets the `UNPACK_FLIP_Y_WEBGL` flag the WebGL Texture uses during upload. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#flipY + * @type {boolean} + * @since 3.80.0 + */ + this.flipY = !!flipY; + + /** + * Metadata for the SpectorJS tool, set if debug is enabled. + * You should set this via the `spectorMetadata` property, + * which will update the `__SPECTOR_Metadata` property on the WebGLTexture. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#__SPECTOR_Metadata + * @type {object} + * @private + * @since 3.80.0 + */ + // eslint-disable-next-line camelcase + this.__SPECTOR_Metadata = {}; + + /** + * The texture unit this texture will be bound to in the current + * rendering batch. + * + * This should be set by the batcher. It is a quick way to tell whether + * this texture has been included in the batch. If it is -1, it has not. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#batchUnit + * @type {number} + * @since 4.0.0 + * @default -1 + */ + this.batchUnit = -1; + + this.createResource(); + }, + + /** + * Creates a WebGLTexture from the given parameters. + * + * This is called automatically by the constructor. It may also be + * called again if the WebGLTexture needs re-creating. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#createResource + * @since 3.80.0 + */ + createResource: function () + { + var gl = this.renderer.gl; + + if (gl.isContextLost()) + { + // GL state can't be updated right now. + // `createResource` will run when the context is restored. + return; + } + + if (this.pixels instanceof WebGLTextureWrapper) + { + // Use the source texture directly. + this.webGLTexture = this.pixels.webGLTexture; + return; + } + + var texture = gl.createTexture(); + + // Set Spector metadata. + // eslint-disable-next-line camelcase + texture.__SPECTOR_Metadata = this.__SPECTOR_Metadata; + + // Assign the texture to our wrapper. + this.webGLTexture = texture; + + this._processTexture(); + }, + + /** + * Resizes the WebGLTexture to the new dimensions. + * This will destroy the contents of the texture. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#resize + * @since 4.0.0 + * @param {number} width - The new width of the WebGLTexture. + * @param {number} height - The new height of the WebGLTexture. + */ + resize: function (width, height) + { + if (this.width === width && this.height === height) + { + return; + } + + this.width = width; + this.height = height; + + this._processTexture(); + }, + + /** + * Updates the WebGLTexture from an updated source. + * + * This should only be used when the source is a Canvas or Video element. + * + * Because textures usually change into something complex and unique, + * this method forces all properties to update without checking. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#update + * @since 3.80.0 + * + * @param {?object} source - The source to update the WebGLTexture with. + * @param {number} width - The new width of the WebGLTexture. + * @param {number} height - The new height of the WebGLTexture. + * @param {boolean} flipY - Should the WebGLTexture set `UNPACK_MULTIPLY_FLIP_Y`? + * @param {number} wrapS - The new wrapping mode for the WebGLTexture. + * @param {number} wrapT - The new wrapping mode for the WebGLTexture. + * @param {number} minFilter - The new minification filter for the WebGLTexture. + * @param {number} magFilter - The new magnification filter for the WebGLTexture. + * @param {number} format - The new format for the WebGLTexture. + */ + update: function (source, width, height, flipY, wrapS, wrapT, minFilter, magFilter, format) + { + if (width === 0 || height === 0) + { + return; + } + + // Assume that the source might change. + this.pixels = source; + this.width = width; + this.height = height; + this.flipY = flipY; + this.wrapS = wrapS; + this.wrapT = wrapT; + this.minFilter = minFilter; + this.magFilter = magFilter; + this.format = format; + + this._processTexture(); + }, + + /** + * Set all parameters of this WebGLTexture per the stored values. + * + * @function Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#_processTexture + * @protected + * @since 4.0.0 + * @ignore + */ + _processTexture: function () + { + var gl = this.renderer.gl; + + this.renderer.glTextureUnits.bind(this, 0); + this.renderer.glWrapper.updateTexturing({ + texturing: + { + flipY: this.flipY, + premultiplyAlpha: this.pma + } + }); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.magFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.wrapS); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.wrapT); + + var pixels = this.pixels; + var mipLevel = this.mipLevel; + var width = this.width; + var height = this.height; + var format = this.format; + + var generateMipmap = false; + + if (pixels === null || pixels === undefined) + { + gl.texImage2D(gl.TEXTURE_2D, mipLevel, format, width, height, 0, format, gl.UNSIGNED_BYTE, null); + + generateMipmap = IsSizePowerOfTwo(width, height); + } + else if (pixels.compressed) + { + width = pixels.width; + height = pixels.height; + generateMipmap = pixels.generateMipmap; + + for (var i = 0; i < pixels.mipmaps.length; i++) + { + gl.compressedTexImage2D(gl.TEXTURE_2D, i, pixels.internalFormat, pixels.mipmaps[i].width, pixels.mipmaps[i].height, 0, pixels.mipmaps[i].data); + } + } + else if (pixels instanceof Uint8Array) + { + gl.texImage2D(gl.TEXTURE_2D, mipLevel, format, width, height, 0, format, gl.UNSIGNED_BYTE, pixels); + + generateMipmap = IsSizePowerOfTwo(width, height); + } + else + { + if (!this.forceSize) + { + width = pixels.width; + height = pixels.height; + } + + gl.texImage2D(gl.TEXTURE_2D, mipLevel, format, format, gl.UNSIGNED_BYTE, pixels); + + generateMipmap = IsSizePowerOfTwo(width, height); + } + + if (generateMipmap) + { + gl.generateMipmap(gl.TEXTURE_2D); + } + }, + + /** + * The `__SPECTOR_Metadata` property of the `WebGLTexture`, + * used to add extra data to the debug SpectorJS integration. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#spectorMetadata + * @type {object} + * @since 3.80.0 + */ + spectorMetadata: { + + get: function () + { + return this.__SPECTOR_Metadata; + }, + + set: function (value) + { + // eslint-disable-next-line camelcase + this.__SPECTOR_Metadata = value; + + // eslint-disable-next-line camelcase + this.webGLTexture.__SPECTOR_Metadata = value; + } + }, + + /** + * Deletes the WebGLTexture from the GPU, if it has not been already. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper#destroy + * @since 3.80.0 + */ + destroy: function () + { + if (this.webGLTexture === null) + { + return; + } + + if (!(this.pixels instanceof WebGLTextureWrapper)) + { + // Do not delete a texture that belongs to another wrapper. + this.renderer.gl.deleteTexture(this.webGLTexture); + } + + this.pixels = null; + this.webGLTexture = null; + this.renderer = null; + } +}); + +module.exports = WebGLTextureWrapper; + + +/***/ }), + +/***/ 85788: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * Wrapper for a WebGL Vertex Array Object (VAO). + * + * A WebGLVertexArrayObject should never be exposed outside the WebGLRenderer, + * so the WebGLRenderer can handle context loss and other events without other + * systems having to be aware of it. Always use WebGLVAOWrapper instead. + * + * @class WebGLVAOWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The shader program that this VAO is associated with. + * @param {?Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} indexBuffer - The index buffer used in this VAO, if any. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper[]} attributeBufferLayouts - The vertex buffers containing attribute data for this VAO, alongside the relevant attribute layout. + */ +var WebGLVAOWrapper = new Class({ + initialize: function WebGLVAOWrapper (renderer, program, indexBuffer, attributeBufferLayouts) + { + /** + * The WebGLRenderer instance that owns this wrapper. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The shader program that this VAO is associated with. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#program + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} + * @since 4.0.0 + */ + this.program = program; + + /** + * The WebGLVertexArrayObject being wrapped by this class. + * + * This property could change at any time. + * Therefore, you should never store a reference to this value. + * It should only be passed directly to the WebGL API for drawing. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#vertexArrayObject + * @type {?WebGLVertexArrayObject} + * @default null + * @since 4.0.0 + */ + this.vertexArrayObject = null; + + /** + * The element array buffer used in this VAO, if any. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#indexBuffer + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @default null + * @since 4.0.0 + */ + this.indexBuffer = indexBuffer; + + /** + * The vertex buffers containing attribute data for this VAO, + * alongside the relevant attribute layout. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#attributeBufferLayouts + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper[]} + * @since 4.0.0 + */ + this.attributeBufferLayouts = attributeBufferLayouts; + + /** + * The state object used to bind this VAO. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#glState + * @type {object} + * @since 4.0.0 + */ + this.glState = { + vao: this + }; + + this.createResource(); + }, + + /** + * Creates a new WebGLVertexArrayObject. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#createResource + * @since 4.0.0 + */ + createResource: function () + { + var gl = this.renderer.gl; + var extVAO = this.renderer.vaoExtension; + var extInstance = this.renderer.instancedArraysExtension; + + if (!extVAO) + { + throw new Error('WebGLVertexArrayObject not supported by this browser'); + } + + if (!extInstance) + { + throw new Error('ANGLE_instanced_arrays extension not supported by this browser'); + } + + this.vertexArrayObject = extVAO.createVertexArrayOES(); + + this.bind(); + + if (this.indexBuffer) + { + this.indexBuffer.bind(); + } + + var program = this.program; + var glAttributes = program.glAttributes; + var glAttributeNames = program.glAttributeNames; + + for (var i = 0; i < this.attributeBufferLayouts.length; i++) + { + var attributeBufferLayout = this.attributeBufferLayouts[i]; + + attributeBufferLayout.buffer.bind(); + var stride = attributeBufferLayout.layout.stride; + var instanceDivisor = attributeBufferLayout.layout.instanceDivisor; + + for (var j = 0; j < attributeBufferLayout.layout.layout.length; j++) + { + var layout = attributeBufferLayout.layout.layout[j]; + + // Connect attribute locations from program. + var attributeIndex = glAttributeNames.get(layout.name); + if (attributeIndex === undefined) + { + // This attribute is not used in the shader, so skip it. + continue; + } + var attributeInfo = glAttributes[attributeIndex]; + layout.location = attributeInfo.location; + + // Create attribute pointers. + + var location = layout.location; + + var bytes = layout.bytes || 4; + var columns = layout.columns || 1; + var normalized = layout.normalized; + var offset = layout.offset; + var size = layout.size; + var type = layout.type; + + for (var column = 0; column < columns; column++) + { + gl.enableVertexAttribArray(location + column); + + gl.vertexAttribPointer( + location + column, + size, + type, + normalized, + stride, + offset + bytes * column * size + ); + + if (!isNaN(instanceDivisor)) + { + extInstance.vertexAttribDivisorANGLE( + location + column, + instanceDivisor + ); + } + } + } + } + + // Finalize VAO. + this.renderer.glWrapper.updateVAO({ + vao: null + }); + + // Force unbind buffers, as they may have been unbound by the VAO + // without syncing state management. + this.renderer.glWrapper.updateBindings({ + bindings: { + arrayBuffer: null, + elementArrayBuffer: null + } + }); + }, + + /** + * Binds this WebGLVAOWrapper to the current WebGLRenderingContext. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#bind + * @since 4.0.0 + */ + bind: function () + { + this.renderer.glWrapper.updateVAO(this.glState); + }, + + /** + * Destroys this WebGLVAOWrapper and removes all associated resources. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#destroy + * @since 4.0.0 + */ + destroy: function () + { + var extVAO = this.renderer.vaoExtension; + + if (this.vertexArrayObject) + { + extVAO.deleteVertexArrayOES(this.vertexArrayObject); + this.vertexArrayObject = null; + } + + this.indexBuffer = null; + this.attributeBufferLayouts = null; + this.glState = null; + this.renderer = null; + } +}); + +module.exports = WebGLVAOWrapper; + + +/***/ }), + +/***/ 40952: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * Wrapper for a vertex buffer layout. + * This contains the buffer itself, the attribute layout information, + * and the ArrayBuffer and associate views that the layout is based on. + * + * @class WebGLVertexBufferLayoutWrapper + * @memberof Phaser.Renderer.WebGL.Wrappers + * @constructor + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The program that this layout is associated with. + * @param {Partial} layout - The layout of the buffer. At construction, this should be incomplete. The stride and per-attribute location, bytes, and offset will be filled in during construction. This will mutate the object. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} [buffer] - The buffer that this layout should use. If not provided, a new buffer will be created. If the buffer is too small, an exception is thrown. + * @throws {Error} If the buffer is too small for the layout. + */ +var WebGLVertexBufferLayoutWrapper = new Class({ + initialize: function WebGLVertexBufferLayoutWrapper (renderer, layout, buffer) + { + /** + * The WebGLRenderer instance that owns this wrapper. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#renderer + * @type {Phaser.Renderer.WebGL.WebGLRenderer} + * @since 4.0.0 + */ + this.renderer = renderer; + + /** + * The layout of the buffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#layout + * @type {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout} + * @since 4.0.0 + */ + this.layout = layout; + + // Fill in the layout with the stride + // and per-attribute bytes and offset. + this.completeLayout(layout); + + var bufferSize = layout.stride * layout.count; + if (buffer && buffer.byteLength < bufferSize) + { + throw new Error('Buffer too small for layout'); + } + + /** + * The WebGLBuffer that this layout is based on. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#buffer + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} + * @since 4.0.0 + */ + this.buffer = buffer || renderer.createVertexBuffer(new ArrayBuffer(bufferSize), layout.usage); + }, + + /** + * Complete the layout of the provided attribute buffer layout. + * This will fill in the stride, byte counts, and offsets. + * In addition, it will convert any GLenums specified as strings + * to their numeric values. + * This mutates the layout. + * + * The order of attributes within the layout forms the order of the buffer. + * + * @method Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#completeLayout + * @since 4.0.0 + * @param {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout} attributeBufferLayout - The layout to complete. + */ + completeLayout: function (attributeBufferLayout) + { + var gl = this.renderer.gl; + var layout = attributeBufferLayout.layout; + var constants = this.renderer.shaderSetters.constants; + + if (typeof attributeBufferLayout.usage === 'string') + { + attributeBufferLayout.usage = gl[attributeBufferLayout.usage]; + } + + var offset = 0; + + for (var i = 0; i < layout.length; i++) + { + var attribute = layout[i]; + var size = attribute.size; + var columns = attribute.columns || 1; + + // First, append the current offset. + attribute.offset = offset; + + // Convert the type to a GLenum if it is a string. + if (typeof attribute.type === 'string') + { + attribute.type = gl[attribute.type]; + } + + var typeData = constants[attribute.type]; + var baseSize = typeData.size; + var baseBytes = typeData.bytes; + + // Append the bytes per attribute element. + attribute.bytes = baseBytes; + + offset += size * columns * baseBytes * baseSize; + } + + // Now that we know the total stride, we can set it. + attributeBufferLayout.stride = offset; + } +}); + +module.exports = WebGLVertexBufferLayoutWrapper; + + +/***/ }), + +/***/ 31884: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Renderer.WebGL.Wrappers + */ + +var Wrappers = { + WebGLGlobalWrapper: __webpack_require__(37959), + WebGLBufferWrapper: __webpack_require__(26128), + WebGLProgramWrapper: __webpack_require__(1482), + WebGLShaderSetterWrapper: __webpack_require__(86272), + WebGLTextureWrapper: __webpack_require__(82751), + WebGLTextureUnitsWrapper: __webpack_require__(13760), + WebGLFramebufferWrapper: __webpack_require__(84387), + WebGLVAOWrapper: __webpack_require__(85788), + WebGLVertexBufferLayoutWrapper: __webpack_require__(40952) +}; + +module.exports = Wrappers; + + +/***/ }), + +/***/ 76531: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(13560); +var Class = __webpack_require__(83419); +var Clamp = __webpack_require__(45319); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(97480); +var GameEvents = __webpack_require__(8443); +var GetInnerHeight = __webpack_require__(57811); +var GetTarget = __webpack_require__(74403); +var GetScreenOrientation = __webpack_require__(45818); +var NOOP = __webpack_require__(29747); +var Rectangle = __webpack_require__(87841); +var Size = __webpack_require__(86555); +var SnapFloor = __webpack_require__(56583); +var Vector2 = __webpack_require__(26099); +var Camera = __webpack_require__(38058); + +/** + * @classdesc + * The Scale Manager handles the scaling, resizing and alignment of the game canvas. + * + * The way scaling is handled is by setting the game canvas to a fixed size, which is defined in the + * game configuration. You also define the parent container in the game config. If no parent is given, + * it will default to using the document body. The Scale Manager will then look at the available space + * within the _parent_ and scale the canvas accordingly. Scaling is handled by setting the canvas CSS + * width and height properties, leaving the width and height of the canvas element itself untouched. + * Scaling is therefore achieved by keeping the core canvas the same size and 'stretching' + * it via its CSS properties. This gives the same result and speed as using the `transform-scale` CSS + * property, without the need for browser prefix handling. + * + * The calculations for the scale are heavily influenced by the bounding parent size, which is the computed + * dimensions of the canvas's parent. The CSS rules of the parent element play an important role in the + * operation of the Scale Manager. For example, if the parent has no defined width or height, then actions + * like auto-centering will fail to achieve the required result. The Scale Manager works in tandem with the + * CSS you set-up on the page hosting your game, rather than taking control of it. + * + * #### Parent and Display canvas containment guidelines: + * + * - Style the Parent element (of the game canvas) to control the Parent size and thus the games size and layout. + * + * - The Parent element's CSS styles should _effectively_ apply maximum (and minimum) bounding behavior. + * + * - The Parent element should _not_ apply a padding as this is not accounted for. + * If a padding is required apply it to the Parent's parent or apply a margin to the Parent. + * If you need to add a border, margin or any other CSS around your game container, then use a parent element and + * apply the CSS to this instead, otherwise you'll be constantly resizing the shape of the game container. + * + * - The Display canvas layout CSS styles (i.e. margins, size) should not be altered / specified as + * they may be updated by the Scale Manager. + * + * #### Scale Modes + * + * The way the scaling is handled is determined by the `scaleMode` property. The default is `NONE`, + * which prevents Phaser from scaling or touching the canvas, or its parent, at all. In this mode, you are + * responsible for all scaling. The other scaling modes afford you automatic scaling. + * + * If you wish to scale your game so that it always fits into the available space within the parent, you + * should use the scale mode `FIT`. Look at the documentation for other scale modes to see what options are + * available. Here is a basic config showing how to set this scale mode: + * + * ```javascript + * scale: { + * parent: 'yourgamediv', + * mode: Phaser.Scale.FIT, + * width: 800, + * height: 600 + * } + * ``` + * + * Place the `scale` config object within your game config. + * + * If you wish for the canvas to be resized directly, so that the canvas itself fills the available space + * (i.e. it isn't scaled, it's resized) then use the `RESIZE` scale mode. This will give you a 1:1 mapping + * of canvas pixels to game size. In this mode CSS isn't used to scale the canvas, it's literally adjusted + * to fill all available space within the parent. You should be extremely careful about the size of the + * canvas you're creating when doing this, as the larger the area, the more work the GPU has to do and it's + * very easy to hit fill-rate limits quickly. + * + * For complex, custom-scaling requirements, you should probably consider using the `RESIZE` scale mode, + * with your own limitations in place re: canvas dimensions and managing the scaling with the game scenes + * yourself. For the vast majority of games, however, the `FIT` mode is likely to be the most used. + * + * Please appreciate that the Scale Manager cannot perform miracles. All it does is scale your game canvas + * as best it can, based on what it can infer from its surrounding area. There are all kinds of environments + * where it's up to you to guide and help the canvas position itself, especially when built into rendering + * frameworks like React and Vue. If your page requires meta tags to prevent user scaling gestures, or such + * like, then it's up to you to ensure they are present in the html. + * + * #### Centering + * + * You can also have the game canvas automatically centered. Again, this relies heavily on the parent being + * properly configured and styled, as the centering offsets are based entirely on the available space + * within the parent element. Centering is disabled by default, or can be applied horizontally, vertically, + * or both. Here's an example: + * + * ```javascript + * scale: { + * parent: 'yourgamediv', + * autoCenter: Phaser.Scale.CENTER_BOTH, + * width: 800, + * height: 600 + * } + * ``` + * + * #### Fullscreen API + * + * If the browser supports it, you can send your game into fullscreen mode. In this mode, the game will fill + * the entire display, removing all browser UI and anything else present on the screen. It will remain in this + * mode until your game either disables it, or until the user tabs out or presses ESCape if on desktop. It's a + * great way to achieve a desktop-game like experience from the browser, but it does require a modern browser + * to handle it. Some mobile browsers also support this. + * + * @class ScaleManager + * @memberof Phaser.Scale + * @extends Phaser.Events.EventEmitter + * @constructor + * @since 3.16.0 + * + * @param {Phaser.Game} game - A reference to the Phaser.Game instance. + */ +var ScaleManager = new Class({ + + Extends: EventEmitter, + + initialize: + + function ScaleManager (game) + { + EventEmitter.call(this); + + /** + * A reference to the Phaser.Game instance. + * + * @name Phaser.Scale.ScaleManager#game + * @type {Phaser.Game} + * @readonly + * @since 3.15.0 + */ + this.game = game; + + /** + * A reference to the HTML Canvas Element that Phaser uses to render the game. + * + * @name Phaser.Scale.ScaleManager#canvas + * @type {HTMLCanvasElement} + * @since 3.16.0 + */ + this.canvas; + + /** + * The DOM bounds of the canvas element. + * + * @name Phaser.Scale.ScaleManager#canvasBounds + * @type {Phaser.Geom.Rectangle} + * @since 3.16.0 + */ + this.canvasBounds = new Rectangle(); + + /** + * The parent object of the Canvas. Often a div, or the browser window, or nothing in non-browser environments. + * + * This is set in the Game Config as the `parent` property. If undefined (or just not present), it will default + * to use the document body. If specifically set to `null` Phaser will ignore all parent operations. + * + * @name Phaser.Scale.ScaleManager#parent + * @type {?any} + * @since 3.16.0 + */ + this.parent = null; + + /** + * Is the parent element the browser window? + * + * @name Phaser.Scale.ScaleManager#parentIsWindow + * @type {boolean} + * @since 3.16.0 + */ + this.parentIsWindow = false; + + /** + * The Parent Size component. + * + * @name Phaser.Scale.ScaleManager#parentSize + * @type {Phaser.Structs.Size} + * @since 3.16.0 + */ + this.parentSize = new Size(); + + /** + * The Game Size component. + * + * The un-modified game size, as requested in the game config (the raw width / height), + * as used for world bounds, cameras, etc + * + * @name Phaser.Scale.ScaleManager#gameSize + * @type {Phaser.Structs.Size} + * @since 3.16.0 + */ + this.gameSize = new Size(); + + /** + * The Base Size component. + * + * The modified game size, which is the auto-rounded gameSize, used to set the canvas width and height + * (but not the CSS style) + * + * @name Phaser.Scale.ScaleManager#baseSize + * @type {Phaser.Structs.Size} + * @since 3.16.0 + */ + this.baseSize = new Size(); + + /** + * The Display Size component. + * + * The size used for the canvas style, factoring in the scale mode, parent and other values. + * + * @name Phaser.Scale.ScaleManager#displaySize + * @type {Phaser.Structs.Size} + * @since 3.16.0 + */ + this.displaySize = new Size(); + + /** + * The game scale mode. + * + * @name Phaser.Scale.ScaleManager#scaleMode + * @type {Phaser.Scale.ScaleModeType} + * @since 3.16.0 + */ + this.scaleMode = CONST.SCALE_MODE.NONE; + + /** + * The game zoom factor. + * + * This value allows you to multiply your games base size by the given zoom factor. + * This is then used when calculating the display size, even in `NONE` situations. + * If you don't want Phaser to touch the canvas style at all, this value should be 1. + * + * Can also be set to `MAX_ZOOM` in which case the zoom value will be derived based + * on the game size and available space within the parent. + * + * @name Phaser.Scale.ScaleManager#zoom + * @type {number} + * @since 3.16.0 + */ + this.zoom = 1; + + /** + * Internal flag set when the game zoom factor is modified. + * + * @name Phaser.Scale.ScaleManager#_resetZoom + * @type {boolean} + * @readonly + * @since 3.19.0 + */ + this._resetZoom = false; + + /** + * The scale factor between the baseSize and the canvasBounds. + * + * @name Phaser.Scale.ScaleManager#displayScale + * @type {Phaser.Math.Vector2} + * @since 3.16.0 + */ + this.displayScale = new Vector2(1, 1); + + /** + * If set, the canvas sizes will be automatically passed through Math.floor. + * This results in rounded pixel display values, which is important for performance on legacy + * and low powered devices, but at the cost of not achieving a 'perfect' fit in some browser windows. + * + * @name Phaser.Scale.ScaleManager#autoRound + * @type {boolean} + * @since 3.16.0 + */ + this.autoRound = false; + + /** + * Automatically center the canvas within the parent? The different centering modes are: + * + * 1. No centering. + * 2. Center both horizontally and vertically. + * 3. Center horizontally. + * 4. Center vertically. + * + * Please be aware that in order to center the game canvas, you must have specified a parent + * that has a size set, or the canvas parent is the document.body. + * + * @name Phaser.Scale.ScaleManager#autoCenter + * @type {Phaser.Scale.CenterType} + * @since 3.16.0 + */ + this.autoCenter = CONST.CENTER.NO_CENTER; + + /** + * The current device orientation. + * + * Orientation events are dispatched via the Device Orientation API, typically only on mobile browsers. + * + * @name Phaser.Scale.ScaleManager#orientation + * @type {Phaser.Scale.OrientationType} + * @since 3.16.0 + */ + this.orientation = CONST.ORIENTATION.LANDSCAPE; + + /** + * A reference to the Device.Fullscreen object. + * + * @name Phaser.Scale.ScaleManager#fullscreen + * @type {Phaser.Device.Fullscreen} + * @since 3.16.0 + */ + this.fullscreen; + + /** + * The DOM Element which is sent into fullscreen mode. + * + * @name Phaser.Scale.ScaleManager#fullscreenTarget + * @type {?any} + * @since 3.16.0 + */ + this.fullscreenTarget = null; + + /** + * Did Phaser create the fullscreen target div, or was it provided in the game config? + * + * @name Phaser.Scale.ScaleManager#_createdFullscreenTarget + * @type {boolean} + * @private + * @since 3.16.0 + */ + this._createdFullscreenTarget = false; + + /** + * The dirty state of the Scale Manager. + * Set if there is a change between the parent size and the current size. + * + * @name Phaser.Scale.ScaleManager#dirty + * @type {boolean} + * @since 3.16.0 + */ + this.dirty = false; + + /** + * How many milliseconds should elapse before checking if the browser size has changed? + * + * Most modern browsers dispatch a 'resize' event, which the Scale Manager will listen for. + * However, older browsers fail to do this, or do it consistently, so we fall back to a + * more traditional 'size check' based on a time interval. You can control how often it is + * checked here. + * + * @name Phaser.Scale.ScaleManager#resizeInterval + * @type {number} + * @since 3.16.0 + */ + this.resizeInterval = 500; + + /** + * Internal size interval tracker. + * + * @name Phaser.Scale.ScaleManager#_lastCheck + * @type {number} + * @private + * @since 3.16.0 + */ + this._lastCheck = 0; + + /** + * Internal flag to check orientation state. + * + * @name Phaser.Scale.ScaleManager#_checkOrientation + * @type {boolean} + * @private + * @since 3.16.0 + */ + this._checkOrientation = false; + + /** + * Internal object containing our defined event listeners. + * + * @name Phaser.Scale.ScaleManager#domlisteners + * @type {object} + * @private + * @since 3.16.0 + */ + this.domlisteners = { + + orientationChange: NOOP, + windowResize: NOOP, + fullScreenChange: NOOP, + fullScreenError: NOOP + + }; + }, + + /** + * Called _before_ the canvas object is created and added to the DOM. + * + * @method Phaser.Scale.ScaleManager#preBoot + * @protected + * @listens Phaser.Core.Events#BOOT + * @since 3.16.0 + */ + preBoot: function () + { + // Parse the config to get the scaling values we need + this.parseConfig(this.game.config); + + this.game.events.once(GameEvents.BOOT, this.boot, this); + }, + + /** + * The Boot handler is called by Phaser.Game when it first starts up. + * The renderer is available by now and the canvas has been added to the DOM. + * + * @method Phaser.Scale.ScaleManager#boot + * @protected + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + */ + boot: function () + { + var game = this.game; + + this.canvas = game.canvas; + + this.fullscreen = game.device.fullscreen; + + var scaleMode = this.scaleMode; + + if (scaleMode !== CONST.SCALE_MODE.RESIZE && scaleMode !== CONST.SCALE_MODE.EXPAND) + { + this.displaySize.setAspectMode(scaleMode); + } + + if (scaleMode === CONST.SCALE_MODE.NONE) + { + this.resize(this.width, this.height); + } + else + { + this.getParentBounds(); + + // Only set the parent bounds if the parent has an actual size + if (this.parentSize.width > 0 && this.parentSize.height > 0) + { + this.displaySize.setParent(this.parentSize); + } + + this.refresh(); + } + + game.events.on(GameEvents.PRE_STEP, this.step, this); + game.events.once(GameEvents.READY, this.refresh, this); + game.events.once(GameEvents.DESTROY, this.destroy, this); + + this.startListeners(); + }, + + /** + * Parses the game configuration to set-up the scale defaults. + * + * @method Phaser.Scale.ScaleManager#parseConfig + * @protected + * @since 3.16.0 + * + * @param {Phaser.Types.Core.GameConfig} config - The Game configuration object. + */ + parseConfig: function (config) + { + // Get the parent element, if any + this.getParent(config); + + // Get the size of the parent element + // This can often set a height of zero (especially for un-styled divs) + this.getParentBounds(); + + var width = config.width; + var height = config.height; + var scaleMode = config.scaleMode; + var zoom = config.zoom; + var autoRound = config.autoRound; + + // If width = '100%', or similar value + if (typeof width === 'string') + { + // Does width have a % character at the end? If not, we use it as a numeric value. + if (width.substr(-1) !== '%') + { + width = parseInt(width, 10); + } + else + { + // If we have a parent with a width, we'll work it out from that + var parentWidth = this.parentSize.width; + + if (parentWidth === 0) + { + parentWidth = window.innerWidth; + } + + var parentScaleX = parseInt(width, 10) / 100; + + width = Math.floor(parentWidth * parentScaleX); + } + + } + + // If height = '100%', or similar value + if (typeof height === 'string') + { + // Does height have a % character at the end? If not, we use it as a numeric value. + if (height.substr(-1) !== '%') + { + height = parseInt(height, 10); + } + else + { + // If we have a parent with a height, we'll work it out from that + var parentHeight = this.parentSize.height; + + if (parentHeight === 0) + { + parentHeight = window.innerHeight; + } + + var parentScaleY = parseInt(height, 10) / 100; + + height = Math.floor(parentHeight * parentScaleY); + } + } + + this.scaleMode = scaleMode; + + this.autoRound = autoRound; + + this.autoCenter = config.autoCenter; + + this.resizeInterval = config.resizeInterval; + + if (autoRound) + { + width = Math.floor(width); + height = Math.floor(height); + } + + // The un-modified game size, as requested in the game config (the raw width / height) as used for world bounds, etc + this.gameSize.setSize(width, height); + + if (zoom === CONST.ZOOM.MAX_ZOOM) + { + zoom = this.getMaxZoom(); + } + + this.zoom = zoom; + + if (zoom !== 1) + { + this._resetZoom = true; + } + + // The modified game size + this.baseSize.setSize(width, height); + + if (autoRound) + { + this.baseSize.width = Math.floor(this.baseSize.width); + this.baseSize.height = Math.floor(this.baseSize.height); + } + + if (config.minWidth > 0) + { + this.displaySize.setMin(config.minWidth * zoom, config.minHeight * zoom); + } + + if (config.maxWidth > 0) + { + this.displaySize.setMax(config.maxWidth * zoom, config.maxHeight * zoom); + } + + // The size used for the canvas style, factoring in the scale mode and parent and zoom value + // We just use the w/h here as this is what sets the aspect ratio (which doesn't then change) + this.displaySize.setSize(width, height); + + if (config.snapWidth > 0 || config.snapHeight > 0) + { + this.displaySize.setSnap(config.snapWidth, config.snapHeight); + } + + this.orientation = GetScreenOrientation(width, height); + }, + + /** + * Determines the parent element of the game canvas, if any, based on the game configuration. + * + * @method Phaser.Scale.ScaleManager#getParent + * @since 3.16.0 + * + * @param {Phaser.Types.Core.GameConfig} config - The Game configuration object. + */ + getParent: function (config) + { + var parent = config.parent; + + if (parent === null) + { + // User is responsible for managing the parent + return; + } + + this.parent = GetTarget(parent); + this.parentIsWindow = (this.parent === document.body); + + if (config.expandParent && config.scaleMode !== CONST.SCALE_MODE.NONE) + { + var DOMRect = this.parent.getBoundingClientRect(); + + if (this.parentIsWindow || DOMRect.height === 0) + { + document.documentElement.style.height = '100%'; + document.body.style.height = '100%'; + + DOMRect = this.parent.getBoundingClientRect(); + + // The parent STILL has no height, clearly no CSS + // has been set on it even though we fixed the body :( + if (!this.parentIsWindow && DOMRect.height === 0) + { + this.parent.style.overflow = 'hidden'; + this.parent.style.width = '100%'; + this.parent.style.height = '100%'; + } + } + } + + // And now get the fullscreenTarget + if (config.fullscreenTarget && !this.fullscreenTarget) + { + this.fullscreenTarget = GetTarget(config.fullscreenTarget); + } + }, + + /** + * Calculates the size of the parent bounds and updates the `parentSize` + * properties, only if the canvas has a dom parent. + * + * @method Phaser.Scale.ScaleManager#getParentBounds + * @since 3.16.0 + * + * @return {boolean} `true` if the parent bounds have changed size or position, otherwise `false`. + */ + getParentBounds: function () + { + if (!this.parent) + { + return false; + } + + var parentSize = this.parentSize; + + // Ref. http://msdn.microsoft.com/en-us/library/hh781509(v=vs.85).aspx for getBoundingClientRect + + // The returned value is a DOMRect object which is the smallest rectangle which contains the entire element, + // including its padding and border-width. The left, top, right, bottom, x, y, width, and height properties + // describe the position and size of the overall rectangle in pixels. Properties other than width and height + // are relative to the top-left of the viewport. + + var DOMRect = this.parent.getBoundingClientRect(); + + if (this.parentIsWindow && this.game.device.os.iOS) + { + DOMRect.height = GetInnerHeight(true); + } + + var newWidth = DOMRect.width; + var newHeight = DOMRect.height; + + if (parentSize.width !== newWidth || parentSize.height !== newHeight) + { + parentSize.setSize(newWidth, newHeight); + + return true; + } + else if (this.canvas) + { + var canvasBounds = this.canvasBounds; + var canvasRect = this.canvas.getBoundingClientRect(); + + if (canvasRect.x !== canvasBounds.x || canvasRect.y !== canvasBounds.y) + { + return true; + } + } + + return false; + }, + + /** + * Attempts to lock the orientation of the web browser using the Screen Orientation API. + * + * This API is only available on modern mobile browsers. + * See https://developer.mozilla.org/en-US/docs/Web/API/Screen/lockOrientation for details. + * + * @method Phaser.Scale.ScaleManager#lockOrientation + * @since 3.16.0 + * + * @param {string} orientation - The orientation you'd like to lock the browser in. Should be an API string such as 'landscape', 'landscape-primary', 'portrait', etc. + * + * @return {boolean} `true` if the orientation was successfully locked, otherwise `false`. + */ + lockOrientation: function (orientation) + { + var lock = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation; + + if (lock) + { + return lock.call(screen, orientation); + } + + return false; + }, + + /** + * This method will set the size of the Parent Size component, which is used in scaling + * and centering calculations. You only need to call this method if you have explicitly + * disabled the use of a parent in your game config, but still wish to take advantage of + * other Scale Manager features. + * + * @method Phaser.Scale.ScaleManager#setParentSize + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {number} width - The new width of the parent. + * @param {number} height - The new height of the parent. + * + * @return {this} The Scale Manager instance. + */ + setParentSize: function (width, height) + { + this.parentSize.setSize(width, height); + + return this.refresh(); + }, + + /** + * This method will set a new size for your game. + * + * It should only be used if you're looking to change the base size of your game and are using + * one of the Scale Manager scaling modes, i.e. `FIT`. If you're using `NONE` and wish to + * change the game and canvas size directly, then please use the `resize` method instead. + * + * @method Phaser.Scale.ScaleManager#setGameSize + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {number} width - The new width of the game. + * @param {number} height - The new height of the game. + * + * @return {this} The Scale Manager instance. + */ + setGameSize: function (width, height) + { + var autoRound = this.autoRound; + + if (autoRound) + { + width = Math.floor(width); + height = Math.floor(height); + } + + var previousWidth = this.width; + var previousHeight = this.height; + + // The un-modified game size, as requested in the game config (the raw width / height) as used for world bounds, etc + this.gameSize.resize(width, height); + + // The modified game size + this.baseSize.resize(width, height); + + if (autoRound) + { + this.baseSize.width = Math.floor(this.baseSize.width); + this.baseSize.height = Math.floor(this.baseSize.height); + } + + // The size used for the canvas style, factoring in the scale mode and parent and zoom value + // Update the aspect ratio + this.displaySize.setAspectRatio(width / height); + + this.canvas.width = this.baseSize.width; + this.canvas.height = this.baseSize.height; + + return this.refresh(previousWidth, previousHeight); + }, + + /** + * Call this to modify the size of the Phaser canvas element directly. + * You should only use this if you are using the `NONE` scale mode, + * it will update all internal components completely. + * + * If all you want to do is change the size of the parent, see the `setParentSize` method. + * + * If all you want is to change the base size of the game, but still have the Scale Manager + * manage all the scaling (i.e. you're **not** using `NONE`), then see the `setGameSize` method. + * + * This method will set the `gameSize`, `baseSize` and `displaySize` components to the given + * dimensions. It will then resize the canvas width and height to the values given, by + * directly setting the properties. Finally, if you have set the Scale Manager zoom value + * to anything other than 1 (the default), it will set the canvas CSS width and height to + * be the given size multiplied by the zoom factor (the canvas pixel size remains untouched). + * + * If you have enabled `autoCenter`, it is then passed to the `updateCenter` method and + * the margins are set, allowing the canvas to be centered based on its parent element + * alone. Finally, the `displayScale` is adjusted and the RESIZE event dispatched. + * + * @method Phaser.Scale.ScaleManager#resize + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {number} width - The new width of the game. + * @param {number} height - The new height of the game. + * + * @return {this} The Scale Manager instance. + */ + resize: function (width, height) + { + var zoom = this.zoom; + var autoRound = this.autoRound; + + if (autoRound) + { + width = Math.floor(width); + height = Math.floor(height); + } + + var previousWidth = this.width; + var previousHeight = this.height; + + // The un-modified game size, as requested in the game config (the raw width / height) as used for world bounds, etc + this.gameSize.resize(width, height); + + // The modified game size + this.baseSize.resize(width, height); + + if (autoRound) + { + this.baseSize.width = Math.floor(this.baseSize.width); + this.baseSize.height = Math.floor(this.baseSize.height); + } + + // The size used for the canvas style, factoring in the scale mode and parent and zoom value + // We just use the w/h here as this is what sets the aspect ratio (which doesn't then change) + this.displaySize.setSize((width * zoom), (height * zoom)); + + this.canvas.width = this.baseSize.width; + this.canvas.height = this.baseSize.height; + + var style = this.canvas.style; + + var styleWidth = width * zoom; + var styleHeight = height * zoom; + + if (autoRound) + { + styleWidth = Math.floor(styleWidth); + styleHeight = Math.floor(styleHeight); + } + + if (styleWidth !== width || styleHeight !== height) + { + style.width = styleWidth + 'px'; + style.height = styleHeight + 'px'; + } + + return this.refresh(previousWidth, previousHeight); + }, + + /** + * Sets the zoom value of the Scale Manager. + * + * @method Phaser.Scale.ScaleManager#setZoom + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {number} value - The new zoom value of the game. + * + * @return {this} The Scale Manager instance. + */ + setZoom: function (value) + { + this.zoom = value; + this._resetZoom = true; + + return this.refresh(); + }, + + /** + * Sets the zoom to be the maximum possible based on the _current_ parent size. + * + * @method Phaser.Scale.ScaleManager#setMaxZoom + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @return {this} The Scale Manager instance. + */ + setMaxZoom: function () + { + this.zoom = this.getMaxZoom(); + this._resetZoom = true; + + return this.refresh(); + }, + + /** + * By setting a Snap value, when the browser size is modified, its dimensions will automatically + * be snapped to the nearest grid slice, using floor. For example, if you have snap value of 16, + * and the width changes to 68, then it will snap down to 64 (the closest multiple of 16 when floored) + * + * This mode is best used with the `FIT` scale mode. + * + * Call this method with no arguments to reset the snap values. + * + * Calling this method automatically invokes `ScaleManager.refresh` which emits a `RESIZE` event. + * + * @method Phaser.Scale.ScaleManager#setSnap + * @fires Phaser.Scale.Events#RESIZE + * @since 3.80.0 + * + * @param {number} [snapWidth=0] - The amount to snap the width to. If you don't want to snap the width, pass a value of zero. + * @param {number} [snapHeight=snapWidth] - The amount to snap the height to. If not provided it will use the `snapWidth` value. If you don't want to snap the height, pass a value of zero. + * + * @return {this} The Scale Manager instance. + */ + setSnap: function (snapWidth, snapHeight) + { + if (snapWidth === undefined) { snapWidth = 0; } + if (snapHeight === undefined) { snapHeight = snapWidth; } + + this.displaySize.setSnap(snapWidth, snapHeight); + + return this.refresh(); + }, + + /** + * Refreshes the internal scale values, bounds sizes and orientation checks. + * + * Once finished, dispatches the resize event. + * + * This is called automatically by the Scale Manager when the browser window size changes, + * as long as it is using a Scale Mode other than 'NONE'. + * + * @method Phaser.Scale.ScaleManager#refresh + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {number} [previousWidth] - The previous width of the game. Only set if the gameSize has changed. + * @param {number} [previousHeight] - The previous height of the game. Only set if the gameSize has changed. + * + * @return {this} The Scale Manager instance. + */ + refresh: function (previousWidth, previousHeight) + { + if (previousWidth === undefined) { previousWidth = this.width; } + if (previousHeight === undefined) { previousHeight = this.height; } + + this.updateScale(); + this.updateBounds(); + this.updateOrientation(); + + this.displayScale.set(this.baseSize.width / this.canvasBounds.width, this.baseSize.height / this.canvasBounds.height); + + var domContainer = this.game.domContainer; + + if (domContainer) + { + this.baseSize.setCSS(domContainer); + + var canvasStyle = this.canvas.style; + var domStyle = domContainer.style; + + domStyle.transform = 'scale(' + this.displaySize.width / this.baseSize.width + ',' + this.displaySize.height / this.baseSize.height + ')'; + + domStyle.marginLeft = canvasStyle.marginLeft; + domStyle.marginTop = canvasStyle.marginTop; + } + + this.emit(Events.RESIZE, this.gameSize, this.baseSize, this.displaySize, previousWidth, previousHeight); + + return this; + }, + + /** + * Internal method that checks the current screen orientation, only if the internal check flag is set. + * + * If the orientation has changed it updates the orientation property and then dispatches the orientation change event. + * + * @method Phaser.Scale.ScaleManager#updateOrientation + * @fires Phaser.Scale.Events#ORIENTATION_CHANGE + * @since 3.16.0 + */ + updateOrientation: function () + { + if (this._checkOrientation) + { + this._checkOrientation = false; + + var newOrientation = GetScreenOrientation(this.width, this.height); + + if (newOrientation !== this.orientation) + { + this.orientation = newOrientation; + + this.emit(Events.ORIENTATION_CHANGE, newOrientation); + } + } + }, + + /** + * Internal method that manages updating the size components based on the scale mode. + * + * @method Phaser.Scale.ScaleManager#updateScale + * @since 3.16.0 + */ + updateScale: function () + { + var style = this.canvas.style; + + var width = this.gameSize.width; + var height = this.gameSize.height; + + var styleWidth; + var styleHeight; + + var zoom = this.zoom; + var autoRound = this.autoRound; + + if (this.scaleMode === CONST.SCALE_MODE.NONE) + { + // No scale + this.displaySize.setSize((width * zoom), (height * zoom)); + + styleWidth = this.displaySize.width; + styleHeight = this.displaySize.height; + + if (autoRound) + { + styleWidth = Math.floor(styleWidth); + styleHeight = Math.floor(styleHeight); + } + + if (this._resetZoom) + { + style.width = styleWidth + 'px'; + style.height = styleHeight + 'px'; + + this._resetZoom = false; + } + } + else if (this.scaleMode === CONST.SCALE_MODE.RESIZE) + { + // Resize to match parent + + // This will constrain using min/max + this.displaySize.setSize(this.parentSize.width, this.parentSize.height); + + this.gameSize.setSize(this.displaySize.width, this.displaySize.height); + + this.baseSize.setSize(this.displaySize.width, this.displaySize.height); + + styleWidth = this.displaySize.width; + styleHeight = this.displaySize.height; + + if (autoRound) + { + styleWidth = Math.floor(styleWidth); + styleHeight = Math.floor(styleHeight); + } + + this.canvas.width = styleWidth; + this.canvas.height = styleHeight; + } + else if (this.scaleMode === CONST.SCALE_MODE.EXPAND) + { + // Expand canvas size to fit game size's width or height + + var baseWidth = this.game.config.width; + var baseHeight = this.game.config.height; + + var windowWidth = this.parentSize.width; + var windowHeight = this.parentSize.height; + + var scaleX = windowWidth / baseWidth; + var scaleY = windowHeight / baseHeight; + + var canvasWidth; + var canvasHeight; + + if (scaleX < scaleY) + { + canvasWidth = baseWidth; + canvasHeight = (scaleX !== 0)? windowHeight / scaleX : baseHeight; + } + else + { + canvasWidth = (scaleY !== 0)? windowWidth / scaleY : baseWidth; + canvasHeight = baseHeight; + } + + var clampedCanvasWidth = Clamp(canvasWidth, this.displaySize.minWidth, this.displaySize.maxWidth); + var clampedCanvasHeight = Clamp(canvasHeight, this.displaySize.minHeight, this.displaySize.maxHeight); + + this.baseSize.setSize(clampedCanvasWidth, clampedCanvasHeight); + + this.gameSize.setSize(clampedCanvasWidth, clampedCanvasHeight); + + if (autoRound) + { + clampedCanvasWidth = Math.floor(clampedCanvasWidth); + clampedCanvasHeight = Math.floor(clampedCanvasHeight); + } + + this.canvas.width = clampedCanvasWidth; + this.canvas.height = clampedCanvasHeight; + + // Resize to match parent, like RESIZE mode + var clampedWindowWidth = windowWidth * (clampedCanvasWidth / canvasWidth); + var clampedWindowHeight = windowHeight * (clampedCanvasHeight / canvasHeight); + this.displaySize.setSize(clampedWindowWidth, clampedWindowHeight); + + styleWidth = this.displaySize.width; + styleHeight = this.displaySize.height; + + if (autoRound) + { + styleWidth = Math.floor(styleWidth); + styleHeight = Math.floor(styleHeight); + } + + style.width = styleWidth + 'px'; + style.height = styleHeight + 'px'; + + } + else + { + // All other scale modes + this.displaySize.setSize(this.parentSize.width, this.parentSize.height); + + styleWidth = this.displaySize.width; + styleHeight = this.displaySize.height; + + if (autoRound) + { + styleWidth = Math.floor(styleWidth); + styleHeight = Math.floor(styleHeight); + } + + style.width = styleWidth + 'px'; + style.height = styleHeight + 'px'; + } + + // Update the parentSize in case the canvas / style change modified it + this.getParentBounds(); + + // Finally, update the centering + this.updateCenter(); + }, + + /** + * Calculates and returns the largest possible zoom factor, based on the current + * parent and game sizes. If the parent has no dimensions (i.e. an unstyled div), + * or is smaller than the un-zoomed game, then this will return a value of 1 (no zoom) + * + * @method Phaser.Scale.ScaleManager#getMaxZoom + * @since 3.16.0 + * + * @return {number} The maximum possible zoom factor. At a minimum this value is always at least 1. + */ + getMaxZoom: function () + { + var zoomH = SnapFloor(this.parentSize.width, this.gameSize.width, 0, true); + var zoomV = SnapFloor(this.parentSize.height, this.gameSize.height, 0, true); + + return Math.max(Math.min(zoomH, zoomV), 1); + }, + + /** + * Calculates and updates the canvas CSS style in order to center it within the + * bounds of its parent. If you have explicitly set parent to be `null` in your + * game config then this method will likely give incorrect results unless you have called the + * `setParentSize` method first. + * + * It works by modifying the canvas CSS `marginLeft` and `marginTop` properties. + * + * If they have already been set by your own style sheet, or code, this will overwrite them. + * + * To prevent the Scale Manager from centering the canvas, either do not set the + * `autoCenter` property in your game config, or make sure it is set to `NO_CENTER`. + * + * @method Phaser.Scale.ScaleManager#updateCenter + * @since 3.16.0 + */ + updateCenter: function () + { + var autoCenter = this.autoCenter; + + if (autoCenter === CONST.CENTER.NO_CENTER) + { + return; + } + + var canvas = this.canvas; + + var style = canvas.style; + + var bounds = canvas.getBoundingClientRect(); + + var width = bounds.width; + var height = bounds.height; + + var offsetX = Math.floor((this.parentSize.width - width) / 2); + var offsetY = Math.floor((this.parentSize.height - height) / 2); + + if (autoCenter === CONST.CENTER.CENTER_HORIZONTALLY) + { + offsetY = 0; + } + else if (autoCenter === CONST.CENTER.CENTER_VERTICALLY) + { + offsetX = 0; + } + + style.marginLeft = offsetX + 'px'; + style.marginTop = offsetY + 'px'; + }, + + /** + * Updates the `canvasBounds` rectangle to match the bounding client rectangle of the + * canvas element being used to track input events. + * + * @method Phaser.Scale.ScaleManager#updateBounds + * @since 3.16.0 + */ + updateBounds: function () + { + var bounds = this.canvasBounds; + var clientRect = this.canvas.getBoundingClientRect(); + + bounds.x = clientRect.left + (window.pageXOffset || 0) - (document.documentElement.clientLeft || 0); + bounds.y = clientRect.top + (window.pageYOffset || 0) - (document.documentElement.clientTop || 0); + bounds.width = clientRect.width; + bounds.height = clientRect.height; + }, + + /** + * Transforms the pageX value into the scaled coordinate space of the Scale Manager. + * + * @method Phaser.Scale.ScaleManager#transformX + * @since 3.16.0 + * + * @param {number} pageX - The DOM pageX value. + * + * @return {number} The translated value. + */ + transformX: function (pageX) + { + return (pageX - this.canvasBounds.left) * this.displayScale.x; + }, + + /** + * Transforms the pageY value into the scaled coordinate space of the Scale Manager. + * + * @method Phaser.Scale.ScaleManager#transformY + * @since 3.16.0 + * + * @param {number} pageY - The DOM pageY value. + * + * @return {number} The translated value. + */ + transformY: function (pageY) + { + return (pageY - this.canvasBounds.top) * this.displayScale.y; + }, + + /** + * Sends a request to the browser to ask it to go in to full screen mode, using the {@link https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API Fullscreen API}. + * + * If the browser does not support this, a `FULLSCREEN_UNSUPPORTED` event will be emitted. + * + * This method _must_ be called from a `pointerup` user-input gesture (**not** `pointerdown`). You cannot launch + * games fullscreen without this, as most browsers block it. Games within an iframe will also be blocked + * from fullscreen unless the iframe has the `allowfullscreen` attribute. + * + * On touch devices, such as Android and iOS Safari, you should always use `pointerup` and NOT `pointerdown`, + * otherwise the request will fail unless the document in which your game is embedded has already received + * some form of touch input, which you cannot guarantee. Activating fullscreen via `pointerup` circumvents + * this issue. + * + * Performing an action that navigates to another page, or opens another tab, will automatically cancel + * fullscreen mode, as will the user pressing the ESC key. To cancel fullscreen mode directly from your game, + * i.e. by clicking an icon, call the `stopFullscreen` method. + * + * A browser can only send one DOM element into fullscreen. You can control which element this is by + * setting the `fullscreenTarget` property in your game config, or changing the property in the Scale Manager. + * Note that the game canvas _must_ be a child of the target. If you do not give a target, Phaser will + * automatically create a blank `
      ` element and move the canvas into it, before going fullscreen. + * When it leaves fullscreen, the div will be removed. + * + * @method Phaser.Scale.ScaleManager#startFullscreen + * @fires Phaser.Scale.Events#ENTER_FULLSCREEN + * @fires Phaser.Scale.Events#FULLSCREEN_FAILED + * @fires Phaser.Scale.Events#FULLSCREEN_UNSUPPORTED + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {object} [fullscreenOptions] - The FullscreenOptions dictionary is used to provide configuration options when entering full screen. + */ + startFullscreen: function (fullscreenOptions) + { + if (fullscreenOptions === undefined) { fullscreenOptions = { navigationUI: 'hide' }; } + + var fullscreen = this.fullscreen; + + if (!fullscreen.available) + { + this.emit(Events.FULLSCREEN_UNSUPPORTED); + + return; + } + + if (!fullscreen.active) + { + var fsTarget = this.getFullscreenTarget(); + + if (fullscreen.keyboard) + { + fsTarget[fullscreen.request](Element.ALLOW_KEYBOARD_INPUT); + } + else + { + fsTarget[fullscreen.request](fullscreenOptions); + } + } + }, + + /** + * The browser has successfully entered fullscreen mode. + * + * @method Phaser.Scale.ScaleManager#fullscreenSuccessHandler + * @private + * @fires Phaser.Scale.Events#ENTER_FULLSCREEN + * @fires Phaser.Scale.Events#RESIZE + * @since 3.17.0 + */ + fullscreenSuccessHandler: function () + { + this.getParentBounds(); + + this.refresh(); + + this.emit(Events.ENTER_FULLSCREEN); + }, + + /** + * The browser failed to enter fullscreen mode. + * + * @method Phaser.Scale.ScaleManager#fullscreenErrorHandler + * @private + * @fires Phaser.Scale.Events#FULLSCREEN_FAILED + * @fires Phaser.Scale.Events#RESIZE + * @since 3.17.0 + * + * @param {any} error - The DOM error event. + */ + fullscreenErrorHandler: function (error) + { + this.removeFullscreenTarget(); + + this.emit(Events.FULLSCREEN_FAILED, error); + }, + + /** + * An internal method that gets the target element that is used when entering fullscreen mode. + * + * @method Phaser.Scale.ScaleManager#getFullscreenTarget + * @since 3.16.0 + * + * @return {object} The fullscreen target element. + */ + getFullscreenTarget: function () + { + if (!this.fullscreenTarget) + { + var fsTarget = document.createElement('div'); + + fsTarget.style.margin = '0'; + fsTarget.style.padding = '0'; + fsTarget.style.width = '100%'; + fsTarget.style.height = '100%'; + + this.fullscreenTarget = fsTarget; + + this._createdFullscreenTarget = true; + } + + if (this._createdFullscreenTarget) + { + var canvasParent = this.canvas.parentNode; + + canvasParent.insertBefore(this.fullscreenTarget, this.canvas); + + this.fullscreenTarget.appendChild(this.canvas); + } + + return this.fullscreenTarget; + }, + + /** + * Removes the fullscreen target that was added to the DOM. + * + * @method Phaser.Scale.ScaleManager#removeFullscreenTarget + * @since 3.17.0 + */ + removeFullscreenTarget: function () + { + if (this._createdFullscreenTarget) + { + var fsTarget = this.fullscreenTarget; + + if (fsTarget && fsTarget.parentNode) + { + var parent = fsTarget.parentNode; + + parent.insertBefore(this.canvas, fsTarget); + + parent.removeChild(fsTarget); + } + } + }, + + /** + * Calling this method will cancel fullscreen mode, if the browser has entered it. + * + * @method Phaser.Scale.ScaleManager#stopFullscreen + * @fires Phaser.Scale.Events#FULLSCREEN_UNSUPPORTED + * @since 3.16.0 + */ + stopFullscreen: function () + { + var fullscreen = this.fullscreen; + + if (!fullscreen.available) + { + this.emit(Events.FULLSCREEN_UNSUPPORTED); + + return false; + } + + if (fullscreen.active) + { + document[fullscreen.cancel](); + } + + this.removeFullscreenTarget(); + }, + + /** + * The browser has successfully left fullscreen mode. + * + * @method Phaser.Scale.ScaleManager#leaveFullScreenSuccessHandler + * @fires Phaser.Scale.Events#LEAVE_FULLSCREEN + * @since 3.85.0 + */ + leaveFullScreenSuccessHandler: function () + { + // Get the parent size again as it will have changed + this.getParentBounds(); + + this.emit(Events.LEAVE_FULLSCREEN); + + this.refresh(); + }, + + /** + * Toggles the fullscreen mode. If already in fullscreen, calling this will cancel it. + * If not in fullscreen, this will request the browser to enter fullscreen mode. + * + * If the browser does not support this, a `FULLSCREEN_UNSUPPORTED` event will be emitted. + * + * This method _must_ be called from a user-input gesture, such as `pointerdown`. You cannot launch + * games fullscreen without this, as most browsers block it. Games within an iframe will also be blocked + * from fullscreen unless the iframe has the `allowfullscreen` attribute. + * + * @method Phaser.Scale.ScaleManager#toggleFullscreen + * @fires Phaser.Scale.Events#ENTER_FULLSCREEN + * @fires Phaser.Scale.Events#LEAVE_FULLSCREEN + * @fires Phaser.Scale.Events#FULLSCREEN_UNSUPPORTED + * @fires Phaser.Scale.Events#RESIZE + * @since 3.16.0 + * + * @param {object} [fullscreenOptions] - The FullscreenOptions dictionary is used to provide configuration options when entering full screen. + */ + toggleFullscreen: function (fullscreenOptions) + { + if (this.fullscreen.active) + { + this.stopFullscreen(); + } + else + { + this.startFullscreen(fullscreenOptions); + } + }, + + /** + * An internal method that starts the different DOM event listeners running. + * + * @method Phaser.Scale.ScaleManager#startListeners + * @since 3.16.0 + */ + startListeners: function () + { + var _this = this; + var listeners = this.domlisteners; + + listeners.orientationChange = function () + { + _this.updateBounds(); + + _this._checkOrientation = true; + _this.dirty = true; + + _this.refresh(); + }; + + listeners.windowResize = function () + { + _this.updateBounds(); + + _this.dirty = true; + }; + + // Only dispatched on mobile devices + if (screen.orientation && screen.orientation.addEventListener) + { + screen.orientation.addEventListener('change', listeners.orientationChange, false); + } + else + { + window.addEventListener('orientationchange', listeners.orientationChange, false); + } + + window.addEventListener('resize', listeners.windowResize, false); + + if (this.fullscreen.available) + { + listeners.fullScreenChange = function (event) + { + return _this.onFullScreenChange(event); + }; + + listeners.fullScreenError = function (event) + { + return _this.onFullScreenError(event); + }; + + var vendors = [ 'webkit', 'moz', '' ]; + + vendors.forEach(function (prefix) + { + document.addEventListener(prefix + 'fullscreenchange', listeners.fullScreenChange, false); + document.addEventListener(prefix + 'fullscreenerror', listeners.fullScreenError, false); + }); + + // MS Specific + document.addEventListener('MSFullscreenChange', listeners.fullScreenChange, false); + document.addEventListener('MSFullscreenError', listeners.fullScreenError, false); + } + }, + + /** + * Triggered when a fullscreenchange event is dispatched by the DOM. + * + * @method Phaser.Scale.ScaleManager#onFullScreenChange + * @protected + * @since 3.16.0 + */ + onFullScreenChange: function () + { + if (document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement || document.mozFullScreenElement) + { + this.fullscreenSuccessHandler(); + } + else + { + // They pressed ESC while in fullscreen mode + this.stopFullscreen(); + this.leaveFullScreenSuccessHandler(); + } + }, + + /** + * Triggered when a fullscreenerror event is dispatched by the DOM. + * + * @method Phaser.Scale.ScaleManager#onFullScreenError + * @since 3.16.0 + */ + onFullScreenError: function () + { + this.removeFullscreenTarget(); + }, + + /** + * Get Rectange of visible area. + * + * @method Phaser.Scale.ScaleManager#getViewPort + * @since 3.60.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The camera this viewport is respond upon. + * @param {Phaser.Geom.Rectangle} [out] - The Rectangle of visible area. + * + * @return {Phaser.Geom.Rectangle} The Rectangle of visible area. + */ + getViewPort: function (camera, out) + { + if (!(camera instanceof Camera)) + { + out = camera; + camera = undefined; + } + + if (out === undefined) + { + out = new Rectangle(); + } + + var baseSize = this.baseSize; + var parentSize = this.parentSize; + var canvasBounds = this.canvasBounds; + var displayScale = this.displayScale; + + var x = (canvasBounds.x >= 0) ? 0 : -(canvasBounds.x * displayScale.x); + + var y = (canvasBounds.y >= 0) ? 0 : -(canvasBounds.y * displayScale.y); + + var width; + if (parentSize.width >= canvasBounds.width) + { + width = baseSize.width; + } + else + { + width = baseSize.width - (canvasBounds.width - parentSize.width) * displayScale.x; + } + + var height; + if (parentSize.height >= canvasBounds.height) + { + height = baseSize.height; + } + else + { + height = baseSize.height - (canvasBounds.height - parentSize.height) * displayScale.y; + } + + out.setTo(x, y, width, height); + + if (camera) + { + out.width /= camera.zoomX; + out.height /= camera.zoomY; + out.centerX = camera.centerX + camera.scrollX; + out.centerY = camera.centerY + camera.scrollY; + } + + return out; + }, + + /** + * Internal method, called automatically by the game step. + * Monitors the elapsed time and resize interval to see if a parent bounds check needs to take place. + * + * @method Phaser.Scale.ScaleManager#step + * @since 3.16.0 + * + * @param {number} time - The time value from the most recent Game step. Typically a high-resolution timer value, or Date.now(). + * @param {number} delta - The delta value since the last frame. This is smoothed to avoid delta spikes by the TimeStep class. + */ + step: function (time, delta) + { + if (!this.parent) + { + return; + } + + this._lastCheck += delta; + + if (this.dirty || this._lastCheck > this.resizeInterval) + { + // Returns true if the parent bounds have changed size + if (this.getParentBounds()) + { + this.refresh(); + } + + this.dirty = false; + this._lastCheck = 0; + } + }, + + /** + * Stops all DOM event listeners. + * + * @method Phaser.Scale.ScaleManager#stopListeners + * @since 3.16.0 + */ + stopListeners: function () + { + var listeners = this.domlisteners; + + if (screen.orientation && screen.orientation.addEventListener) + { + screen.orientation.removeEventListener('change', listeners.orientationChange, false); + } + else + { + window.removeEventListener('orientationchange', listeners.orientationChange, false); + } + + window.removeEventListener('resize', listeners.windowResize, false); + + var vendors = [ 'webkit', 'moz', '' ]; + + vendors.forEach(function (prefix) + { + document.removeEventListener(prefix + 'fullscreenchange', listeners.fullScreenChange, false); + document.removeEventListener(prefix + 'fullscreenerror', listeners.fullScreenError, false); + }); + + // MS Specific + document.removeEventListener('MSFullscreenChange', listeners.fullScreenChange, false); + document.removeEventListener('MSFullscreenError', listeners.fullScreenError, false); + }, + + /** + * Destroys this Scale Manager, releasing all references to external resources. + * Once destroyed, the Scale Manager cannot be used again. + * + * @method Phaser.Scale.ScaleManager#destroy + * @since 3.16.0 + */ + destroy: function () + { + this.removeAllListeners(); + + this.stopListeners(); + + this.game = null; + this.canvas = null; + this.canvasBounds = null; + this.parent = null; + this.fullscreenTarget = null; + + this.parentSize.destroy(); + this.gameSize.destroy(); + this.baseSize.destroy(); + this.displaySize.destroy(); + }, + + /** + * Is the browser currently in fullscreen mode or not? + * + * @name Phaser.Scale.ScaleManager#isFullscreen + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + isFullscreen: { + + get: function () + { + return this.fullscreen.active; + } + + }, + + /** + * The game width. + * + * This is typically the size given in the game configuration. + * + * @name Phaser.Scale.ScaleManager#width + * @type {number} + * @readonly + * @since 3.16.0 + */ + width: { + + get: function () + { + return this.gameSize.width; + } + + }, + + /** + * The game height. + * + * This is typically the size given in the game configuration. + * + * @name Phaser.Scale.ScaleManager#height + * @type {number} + * @readonly + * @since 3.16.0 + */ + height: { + + get: function () + { + return this.gameSize.height; + } + + }, + + /** + * Is the device in a portrait orientation as reported by the Orientation API? + * This value is usually only available on mobile devices. + * + * @name Phaser.Scale.ScaleManager#isPortrait + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + isPortrait: { + + get: function () + { + return (this.orientation === CONST.ORIENTATION.PORTRAIT); + } + + }, + + /** + * Is the device in a landscape orientation as reported by the Orientation API? + * This value is usually only available on mobile devices. + * + * @name Phaser.Scale.ScaleManager#isLandscape + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + isLandscape: { + + get: function () + { + return (this.orientation === CONST.ORIENTATION.LANDSCAPE); + } + + }, + + /** + * Are the game dimensions portrait? (i.e. taller than they are wide) + * + * This is different to the device itself being in a portrait orientation. + * + * @name Phaser.Scale.ScaleManager#isGamePortrait + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + isGamePortrait: { + + get: function () + { + return (this.height > this.width); + } + + }, + + /** + * Are the game dimensions landscape? (i.e. wider than they are tall) + * + * This is different to the device itself being in a landscape orientation. + * + * @name Phaser.Scale.ScaleManager#isGameLandscape + * @type {boolean} + * @readonly + * @since 3.16.0 + */ + isGameLandscape: { + + get: function () + { + return (this.width > this.height); + } + + } + +}); + +module.exports = ScaleManager; + + +/***/ }), + +/***/ 64743: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Scale Manager constants for centering the game canvas. + * + * @namespace Phaser.Scale.Center + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +/** + * Phaser Scale Manager constants for centering the game canvas. + * + * To find out what each mode does please see [Phaser.Scale.Center]{@link Phaser.Scale.Center}. + * + * @typedef {Phaser.Scale.Center} Phaser.Scale.CenterType + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +module.exports = { + + /** + * The game canvas is not centered within the parent by Phaser. + * You can still center it yourself via CSS. + * + * @name Phaser.Scale.Center.NO_CENTER + * @type {number} + * @const + * @since 3.16.0 + */ + NO_CENTER: 0, + + /** + * The game canvas is centered both horizontally and vertically within the parent. + * To do this, the parent has to have a bounds that can be calculated and not be empty. + * + * Centering is achieved by setting the margin left and top properties of the + * game canvas, and does not factor in any other CSS styles you may have applied. + * + * @name Phaser.Scale.Center.CENTER_BOTH + * @type {number} + * @const + * @since 3.16.0 + */ + CENTER_BOTH: 1, + + /** + * The game canvas is centered horizontally within the parent. + * To do this, the parent has to have a bounds that can be calculated and not be empty. + * + * Centering is achieved by setting the margin left and top properties of the + * game canvas, and does not factor in any other CSS styles you may have applied. + * + * @name Phaser.Scale.Center.CENTER_HORIZONTALLY + * @type {number} + * @const + * @since 3.16.0 + */ + CENTER_HORIZONTALLY: 2, + + /** + * The game canvas is centered both vertically within the parent. + * To do this, the parent has to have a bounds that can be calculated and not be empty. + * + * Centering is achieved by setting the margin left and top properties of the + * game canvas, and does not factor in any other CSS styles you may have applied. + * + * @name Phaser.Scale.Center.CENTER_VERTICALLY + * @type {number} + * @const + * @since 3.16.0 + */ + CENTER_VERTICALLY: 3 + +}; + + +/***/ }), + +/***/ 39218: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Scale Manager constants for orientation. + * + * @namespace Phaser.Scale.Orientation + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +/** + * Phaser Scale Manager constants for orientation. + * + * To find out what each mode does please see [Phaser.Scale.Orientation]{@link Phaser.Scale.Orientation}. + * + * @typedef {Phaser.Scale.Orientation} Phaser.Scale.OrientationType + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +module.exports = { + + /** + * The primary landscape orientation. + * + * @name Phaser.Scale.Orientation.LANDSCAPE + * @type {string} + * @const + * @since 3.16.0 + */ + LANDSCAPE: 'landscape-primary', + + /** + * The secondary landscape orientation. + * + * @name Phaser.Scale.Orientation.LANDSCAPE_SECONDARY + * @type {string} + * @const + * @since 3.85.0 + */ + LANDSCAPE_SECONDARY: 'landscape-secondary', + + /** + * The primary portrait orientation. + * + * @name Phaser.Scale.Orientation.PORTRAIT + * @type {string} + * @const + * @since 3.16.0 + */ + PORTRAIT: 'portrait-primary', + + /** + * The secondary portrait orientation. + * + * @name Phaser.Scale.Orientation.PORTRAIT_SECONDARY + * @type {string} + * @const + * @since 3.16.0 + */ + PORTRAIT_SECONDARY: 'portrait-secondary' + +}; + + +/***/ }), + +/***/ 81050: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Scale Manager constants for the different scale modes available. + * + * @namespace Phaser.Scale.ScaleModes + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +/** + * Phaser Scale Manager constants for the different scale modes available. + * + * To find out what each mode does please see [Phaser.Scale.ScaleModes]{@link Phaser.Scale.ScaleModes}. + * + * @typedef {Phaser.Scale.ScaleModes} Phaser.Scale.ScaleModeType + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +module.exports = { + + /** + * No scaling happens at all. The canvas is set to the size given in the game config and Phaser doesn't change it + * again from that point on. If you change the canvas size, either via CSS, or directly via code, then you need + * to call the Scale Managers `resize` method to give the new dimensions, or input events will stop working. + * + * @name Phaser.Scale.ScaleModes.NONE + * @type {number} + * @const + * @since 3.16.0 + */ + NONE: 0, + + /** + * The height is automatically adjusted based on the width. + * + * @name Phaser.Scale.ScaleModes.WIDTH_CONTROLS_HEIGHT + * @type {number} + * @const + * @since 3.16.0 + */ + WIDTH_CONTROLS_HEIGHT: 1, + + /** + * The width is automatically adjusted based on the height. + * + * @name Phaser.Scale.ScaleModes.HEIGHT_CONTROLS_WIDTH + * @type {number} + * @const + * @since 3.16.0 + */ + HEIGHT_CONTROLS_WIDTH: 2, + + /** + * The width and height are automatically adjusted to fit inside the given target area, + * while keeping the aspect ratio. Depending on the aspect ratio there may be some space + * inside the area which is not covered. + * + * @name Phaser.Scale.ScaleModes.FIT + * @type {number} + * @const + * @since 3.16.0 + */ + FIT: 3, + + /** + * The width and height are automatically adjusted to make the size cover the entire target + * area while keeping the aspect ratio. This may extend further out than the target size. + * + * @name Phaser.Scale.ScaleModes.ENVELOP + * @type {number} + * @const + * @since 3.16.0 + */ + ENVELOP: 4, + + /** + * The Canvas is resized to fit all available _parent_ space, regardless of aspect ratio. + * + * @name Phaser.Scale.ScaleModes.RESIZE + * @type {number} + * @const + * @since 3.16.0 + */ + RESIZE: 5, + + /** + * The Canvas's visible area is resized to fit all available _parent_ space like RESIZE mode, + * and scale canvas size to fit inside the visible area like FIT mode. + * + * @name Phaser.Scale.ScaleModes.EXPAND + * @type {number} + * @const + * @since 3.80.0 + */ + EXPAND: 6 + +}; + + +/***/ }), + +/***/ 80805: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Scale Manager constants for zoom modes. + * + * @namespace Phaser.Scale.Zoom + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +/** + * Phaser Scale Manager constants for zoom modes. + * + * To find out what each mode does please see [Phaser.Scale.Zoom]{@link Phaser.Scale.Zoom}. + * + * @typedef {Phaser.Scale.Zoom} Phaser.Scale.ZoomType + * @memberof Phaser.Scale + * @since 3.16.0 + */ + +module.exports = { + + /** + * The game canvas will not be zoomed by Phaser. + * + * @name Phaser.Scale.Zoom.NO_ZOOM + * @type {number} + * @const + * @since 3.16.0 + */ + NO_ZOOM: 1, + + /** + * The game canvas will be 2x zoomed by Phaser. + * + * @name Phaser.Scale.Zoom.ZOOM_2X + * @type {number} + * @const + * @since 3.16.0 + */ + ZOOM_2X: 2, + + /** + * The game canvas will be 4x zoomed by Phaser. + * + * @name Phaser.Scale.Zoom.ZOOM_4X + * @type {number} + * @const + * @since 3.16.0 + */ + ZOOM_4X: 4, + + /** + * Calculate the zoom value based on the maximum multiplied game size that will + * fit into the parent, or browser window if no parent is set. + * + * @name Phaser.Scale.Zoom.MAX_ZOOM + * @type {number} + * @const + * @since 3.16.0 + */ + MAX_ZOOM: -1 + +}; + + +/***/ }), + +/***/ 13560: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = { + + CENTER: __webpack_require__(64743), + ORIENTATION: __webpack_require__(39218), + SCALE_MODE: __webpack_require__(81050), + ZOOM: __webpack_require__(80805) + +}; + +module.exports = CONST; + + +/***/ }), + +/***/ 56139: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scale Manager has successfully entered fullscreen mode. + * + * @event Phaser.Scale.Events#ENTER_FULLSCREEN + * @type {string} + * @since 3.16.1 + */ +module.exports = 'enterfullscreen'; + + +/***/ }), + +/***/ 2336: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scale Manager tried to enter fullscreen mode but failed. + * + * @event Phaser.Scale.Events#FULLSCREEN_FAILED + * @type {string} + * @since 3.17.0 + */ +module.exports = 'fullscreenfailed'; + + +/***/ }), + +/***/ 47412: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scale Manager tried to enter fullscreen mode, but it is unsupported by the browser. + * + * @event Phaser.Scale.Events#FULLSCREEN_UNSUPPORTED + * @type {string} + * @since 3.16.1 + */ +module.exports = 'fullscreenunsupported'; + + +/***/ }), + +/***/ 51452: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scale Manager was in fullscreen mode, but has since left, either directly via game code, + * or via a user gestured, such as pressing the ESC key. + * + * @event Phaser.Scale.Events#LEAVE_FULLSCREEN + * @type {string} + * @since 3.16.1 + */ +module.exports = 'leavefullscreen'; + + +/***/ }), + +/***/ 20666: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scale Manager Orientation Change Event. + * + * This event is dispatched whenever the Scale Manager detects an orientation change event from the browser. + * + * @event Phaser.Scale.Events#ORIENTATION_CHANGE + * @type {string} + * @since 3.16.1 + * + * @param {string} orientation - The new orientation value. Either `Phaser.Scale.Orientation.LANDSCAPE` or `Phaser.Scale.Orientation.PORTRAIT`. + */ +module.exports = 'orientationchange'; + + +/***/ }), + +/***/ 47945: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scale Manager Resize Event. + * + * This event is dispatched whenever the Scale Manager detects a resize event from the browser. + * It sends three parameters to the callback, each of them being Size components. You can read + * the `width`, `height`, `aspectRatio` and other properties of these components to help with + * scaling your own game content. + * + * @event Phaser.Scale.Events#RESIZE + * @type {string} + * @since 3.16.1 + * + * @param {Phaser.Structs.Size} gameSize - A reference to the Game Size component. This is the un-scaled size of your game canvas. + * @param {Phaser.Structs.Size} baseSize - A reference to the Base Size component. This is the game size. + * @param {Phaser.Structs.Size} displaySize - A reference to the Display Size component. This is the scaled canvas size, after applying zoom and scale mode. + * @param {number} previousWidth - If the `gameSize` has changed, this value contains its previous width, otherwise it contains the current width. + * @param {number} previousHeight - If the `gameSize` has changed, this value contains its previous height, otherwise it contains the current height. + */ +module.exports = 'resize'; + + +/***/ }), + +/***/ 97480: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Scale.Events + */ + +module.exports = { + + ENTER_FULLSCREEN: __webpack_require__(56139), + FULLSCREEN_FAILED: __webpack_require__(2336), + FULLSCREEN_UNSUPPORTED: __webpack_require__(47412), + LEAVE_FULLSCREEN: __webpack_require__(51452), + ORIENTATION_CHANGE: __webpack_require__(20666), + RESIZE: __webpack_require__(47945) + +}; + + +/***/ }), + +/***/ 93364: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Extend = __webpack_require__(79291); +var CONST = __webpack_require__(13560); + +/** + * @namespace Phaser.Scale + * + * @borrows Phaser.Scale.Center.NO_CENTER as NO_CENTER + * @borrows Phaser.Scale.Center.CENTER_BOTH as CENTER_BOTH + * @borrows Phaser.Scale.Center.CENTER_HORIZONTALLY as CENTER_HORIZONTALLY + * @borrows Phaser.Scale.Center.CENTER_VERTICALLY as CENTER_VERTICALLY + * + * @borrows Phaser.Scale.Orientation.LANDSCAPE as LANDSCAPE + * @borrows Phaser.Scale.Orientation.PORTRAIT as PORTRAIT + * + * @borrows Phaser.Scale.ScaleModes.NONE as NONE + * @borrows Phaser.Scale.ScaleModes.WIDTH_CONTROLS_HEIGHT as WIDTH_CONTROLS_HEIGHT + * @borrows Phaser.Scale.ScaleModes.HEIGHT_CONTROLS_WIDTH as HEIGHT_CONTROLS_WIDTH + * @borrows Phaser.Scale.ScaleModes.FIT as FIT + * @borrows Phaser.Scale.ScaleModes.ENVELOP as ENVELOP + * @borrows Phaser.Scale.ScaleModes.RESIZE as RESIZE + * @borrows Phaser.Scale.ScaleModes.EXPAND as EXPAND + * + * @borrows Phaser.Scale.Zoom.NO_ZOOM as NO_ZOOM + * @borrows Phaser.Scale.Zoom.ZOOM_2X as ZOOM_2X + * @borrows Phaser.Scale.Zoom.ZOOM_4X as ZOOM_4X + * @borrows Phaser.Scale.Zoom.MAX_ZOOM as MAX_ZOOM + */ + +var Scale = { + + Center: __webpack_require__(64743), + Events: __webpack_require__(97480), + Orientation: __webpack_require__(39218), + ScaleManager: __webpack_require__(76531), + ScaleModes: __webpack_require__(81050), + Zoom: __webpack_require__(80805) + +}; + +Scale = Extend(false, Scale, CONST.CENTER); +Scale = Extend(false, Scale, CONST.ORIENTATION); +Scale = Extend(false, Scale, CONST.SCALE_MODE); +Scale = Extend(false, Scale, CONST.ZOOM); + +module.exports = Scale; + + +/***/ }), + +/***/ 27397: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); +var UppercaseFirst = __webpack_require__(35355); + +/** + * Builds an array of which physics plugins should be activated for the given Scene. + * + * @function Phaser.Scenes.GetPhysicsPlugins + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - The scene system to get the physics systems of. + * + * @return {array} An array of Physics systems to start for this Scene. + */ +var GetPhysicsPlugins = function (sys) +{ + var defaultSystem = sys.game.config.defaultPhysicsSystem; + var sceneSystems = GetFastValue(sys.settings, 'physics', false); + + if (!defaultSystem && !sceneSystems) + { + // No default physics system or systems in this scene + return; + } + + // Let's build the systems array + var output = []; + + if (defaultSystem) + { + output.push(UppercaseFirst(defaultSystem + 'Physics')); + } + + if (sceneSystems) + { + for (var key in sceneSystems) + { + key = UppercaseFirst(key.concat('Physics')); + + if (output.indexOf(key) === -1) + { + output.push(key); + } + } + } + + // An array of Physics systems to start for this Scene + return output; +}; + +module.exports = GetPhysicsPlugins; + + +/***/ }), + +/***/ 52106: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); + +/** + * Builds an array of which plugins (not including physics plugins) should be activated for the given Scene. + * + * @function Phaser.Scenes.GetScenePlugins + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - The Scene Systems object to check for plugins. + * + * @return {array} An array of all plugins which should be activated, either the default ones or the ones configured in the Scene Systems object. + */ +var GetScenePlugins = function (sys) +{ + var defaultPlugins = sys.plugins.getDefaultScenePlugins(); + + var scenePlugins = GetFastValue(sys.settings, 'plugins', false); + + // Scene Plugins always override Default Plugins + if (Array.isArray(scenePlugins)) + { + return scenePlugins; + } + else if (defaultPlugins) + { + return defaultPlugins; + } + else + { + // No default plugins or plugins in this scene + return []; + } +}; + +module.exports = GetScenePlugins; + + +/***/ }), + +/***/ 87033: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// These properties get injected into the Scene and map to local systems +// The map value is the property that is injected into the Scene, the key is the Scene.Systems reference. +// These defaults can be modified via the Scene config object +// var config = { +// map: { +// add: 'makeStuff', +// load: 'loader' +// } +// }; + +var InjectionMap = { + + game: 'game', + renderer: 'renderer', + + anims: 'anims', + cache: 'cache', + plugins: 'plugins', + registry: 'registry', + scale: 'scale', + sound: 'sound', + textures: 'textures', + + events: 'events', + cameras: 'cameras', + add: 'add', + make: 'make', + scenePlugin: 'scene', + displayList: 'children', + lights: 'lights', + + data: 'data', + input: 'input', + load: 'load', + time: 'time', + tweens: 'tweens', + + arcadePhysics: 'physics', + matterPhysics: 'matter' + +}; + +module.exports = InjectionMap; + + +/***/ }), + +/***/ 97482: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Systems = __webpack_require__(2368); + +/** + * @classdesc + * A base Phaser.Scene class which can be extended for your own use. + * + * You can also define the optional methods {@link Phaser.Types.Scenes.SceneInitCallback init()}, {@link Phaser.Types.Scenes.ScenePreloadCallback preload()}, and {@link Phaser.Types.Scenes.SceneCreateCallback create()}. + * + * @class Scene + * @memberof Phaser + * @constructor + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Scenes.SettingsConfig)} [config] - The scene key or scene specific configuration settings. + */ +var Scene = new Class({ + + initialize: + + function Scene (config) + { + /** + * The Scene Systems. You must never overwrite this property, or all hell will break loose. + * + * @name Phaser.Scene#sys + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.sys = new Systems(this, config); + + /** + * A reference to the Phaser.Game instance. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game; + + /** + * A reference to the global Animation Manager. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#anims + * @type {Phaser.Animations.AnimationManager} + * @since 3.0.0 + */ + this.anims; + + /** + * A reference to the global Cache. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#cache + * @type {Phaser.Cache.CacheManager} + * @since 3.0.0 + */ + this.cache; + + /** + * A reference to the global Data Manager. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#registry + * @type {Phaser.Data.DataManager} + * @since 3.0.0 + */ + this.registry; + + /** + * A reference to the Sound Manager. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#sound + * @type {(Phaser.Sound.NoAudioSoundManager|Phaser.Sound.HTML5AudioSoundManager|Phaser.Sound.WebAudioSoundManager)} + * @since 3.0.0 + */ + this.sound; + + /** + * A reference to the Texture Manager. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#textures + * @type {Phaser.Textures.TextureManager} + * @since 3.0.0 + */ + this.textures; + + /** + * A Scene specific Event Emitter. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events; + + /** + * The Scene Camera Manager. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#cameras + * @type {Phaser.Cameras.Scene2D.CameraManager} + * @since 3.0.0 + */ + this.cameras; + + /** + * The Scene Game Object Factory. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#add + * @type {Phaser.GameObjects.GameObjectFactory} + * @since 3.0.0 + */ + this.add; + + /** + * The Scene Game Object Creator. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#make + * @type {Phaser.GameObjects.GameObjectCreator} + * @since 3.0.0 + */ + this.make; + + /** + * A reference to the Scene Manager Plugin. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#scene + * @type {Phaser.Scenes.ScenePlugin} + * @since 3.0.0 + */ + this.scene; + + /** + * The Game Object Display List belonging to this Scene. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#children + * @type {Phaser.GameObjects.DisplayList} + * @since 3.0.0 + */ + this.children; + + /** + * The Scene Lights Manager Plugin. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#lights + * @type {Phaser.GameObjects.LightsManager} + * @since 3.0.0 + */ + this.lights; + + /** + * A Scene specific Data Manager Plugin. + * + * See the `registry` property for the global Data Manager. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#data + * @type {Phaser.Data.DataManager} + * @since 3.0.0 + */ + this.data; + + /** + * The Scene Input Manager Plugin. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#input + * @type {Phaser.Input.InputPlugin} + * @since 3.0.0 + */ + this.input; + + /** + * The Scene Loader Plugin. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#load + * @type {Phaser.Loader.LoaderPlugin} + * @since 3.0.0 + */ + this.load; + + /** + * The Scene Time and Clock Plugin. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#time + * @type {Phaser.Time.Clock} + * @since 3.0.0 + */ + this.time; + + /** + * The Scene Tween Manager Plugin. + * + * This property will only be available if defined in the Scene Injection Map and the plugin is installed. + * + * @name Phaser.Scene#tweens + * @type {Phaser.Tweens.TweenManager} + * @since 3.0.0 + */ + this.tweens; + + /** + * The Scene Arcade Physics Plugin. + * + * This property will only be available if defined in the Scene Injection Map, the plugin is installed and configured. + * + * @name Phaser.Scene#physics + * @type {Phaser.Physics.Arcade.ArcadePhysics} + * @since 3.0.0 + */ + this.physics; + + /** + * The Scene Matter Physics Plugin. + * + * This property will only be available if defined in the Scene Injection Map, the plugin is installed and configured. + * + * @name Phaser.Scene#matter + * @type {Phaser.Physics.Matter.MatterPhysics} + * @since 3.0.0 + */ + this.matter; + + /** + * A reference to the global Scale Manager. + * + * This property will only be available if defined in the Scene Injection Map. + * + * @name Phaser.Scene#scale + * @type {Phaser.Scale.ScaleManager} + * @since 3.16.2 + */ + this.scale; + + /** + * A reference to the global Plugin Manager. + * + * The Plugin Manager is a global system that allows plugins to register themselves with it, and can then install + * those plugins into Scenes as required. + * + * @name Phaser.Scene#plugins + * @type {Phaser.Plugins.PluginManager} + * @since 3.0.0 + */ + this.plugins; + + /** + * A reference to the renderer instance Phaser is using, either Canvas Renderer or WebGL Renderer. + * + * @name Phaser.Scene#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.50.0 + */ + this.renderer; + }, + + /** + * This method should be overridden by your own Scenes. + * + * This method is called once per game step while the scene is running. + * + * @method Phaser.Scene#update + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + update: function () + { + } + +}); + +module.exports = Scene; + + +/***/ }), + +/***/ 60903: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(89993); +var Events = __webpack_require__(44594); +var GameEvents = __webpack_require__(8443); +var GetValue = __webpack_require__(35154); +var LoaderEvents = __webpack_require__(54899); +var NOOP = __webpack_require__(29747); +var Scene = __webpack_require__(97482); +var Systems = __webpack_require__(2368); + +/** + * @classdesc + * The Scene Manager. + * + * The Scene Manager is a Game level system, responsible for creating, processing and updating all of the + * Scenes in a Game instance. + * + * You should not usually interact directly with the Scene Manager at all. Instead, you should use + * the Scene Plugin, which is available from every Scene in your game via the `this.scene` property. + * + * Using methods in this Scene Manager directly will break queued operations and can cause runtime + * errors. Instead, go via the Scene Plugin. Every feature this Scene Manager provides is also + * available via the Scene Plugin. + * + * @class SceneManager + * @memberof Phaser.Scenes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Phaser.Game instance this Scene Manager belongs to. + * @param {object} sceneConfig - Scene specific configuration settings. + */ +var SceneManager = new Class({ + + initialize: + + function SceneManager (game, sceneConfig) + { + /** + * The Game that this SceneManager belongs to. + * + * @name Phaser.Scenes.SceneManager#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game = game; + + /** + * An object that maps the keys to the scene so we can quickly get a scene from a key without iteration. + * + * @name Phaser.Scenes.SceneManager#keys + * @type {Record} + * @since 3.0.0 + */ + this.keys = {}; + + /** + * The array in which all of the scenes are kept. + * + * @name Phaser.Scenes.SceneManager#scenes + * @type {Phaser.Scene[]} + * @since 3.0.0 + */ + this.scenes = []; + + /** + * Scenes pending to be added are stored in here until the manager has time to add it. + * + * @name Phaser.Scenes.SceneManager#_pending + * @type {array} + * @private + * @since 3.0.0 + */ + this._pending = []; + + /** + * An array of scenes waiting to be started once the game has booted. + * + * @name Phaser.Scenes.SceneManager#_start + * @type {array} + * @private + * @since 3.0.0 + */ + this._start = []; + + /** + * An operations queue, because we don't manipulate the scenes array during processing. + * + * @name Phaser.Scenes.SceneManager#_queue + * @type {array} + * @private + * @since 3.0.0 + */ + this._queue = []; + + /** + * Boot time data to merge. + * + * @name Phaser.Scenes.SceneManager#_data + * @type {object} + * @private + * @since 3.4.0 + */ + this._data = {}; + + /** + * Is the Scene Manager actively processing the Scenes list? + * + * @name Phaser.Scenes.SceneManager#isProcessing + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isProcessing = false; + + /** + * Has the Scene Manager properly started? + * + * @name Phaser.Scenes.SceneManager#isBooted + * @type {boolean} + * @default false + * @readonly + * @since 3.4.0 + */ + this.isBooted = false; + + /** + * Do any of the Cameras in any of the Scenes require a custom viewport? + * If not we can skip scissor tests. + * + * @name Phaser.Scenes.SceneManager#customViewports + * @type {number} + * @default 0 + * @since 3.12.0 + */ + this.customViewports = 0; + + /** + * This system Scene is created during `bootQueue` and is a default + * empty Scene that lives outside of the Scene list, but can be used + * by plugins and managers that need access to a live Scene, without + * being tied to one. + * + * @name Phaser.Scenes.SceneManager#systemScene + * @type {Phaser.Scene} + * @since 3.60.0 + */ + this.systemScene; + + if (sceneConfig) + { + if (!Array.isArray(sceneConfig)) + { + sceneConfig = [ sceneConfig ]; + } + + for (var i = 0; i < sceneConfig.length; i++) + { + // The i === 0 part just autostarts the first Scene given (unless it says otherwise in its config) + this._pending.push({ + key: 'default', + scene: sceneConfig[i], + autoStart: (i === 0), + data: {} + }); + } + } + + game.events.once(GameEvents.READY, this.bootQueue, this); + }, + + /** + * Internal first-time Scene boot handler. + * + * @method Phaser.Scenes.SceneManager#bootQueue + * @private + * @fires Phaser.Core.Events#SYSTEM_READY + * @since 3.2.0 + */ + bootQueue: function () + { + if (this.isBooted) + { + return; + } + + // Create the system Scene + this.systemScene = this.createSceneFromInstance('__SYSTEM', new Scene()); + + this.game.events.emit(GameEvents.SYSTEM_READY, this.systemScene, this); + + var i; + var entry; + var key; + var sceneConfig; + + for (i = 0; i < this._pending.length; i++) + { + entry = this._pending[i]; + + key = entry.key; + sceneConfig = entry.scene; + + var newScene; + + if (sceneConfig instanceof Scene) + { + newScene = this.createSceneFromInstance(key, sceneConfig); + } + else if (typeof sceneConfig === 'object') + { + newScene = this.createSceneFromObject(key, sceneConfig); + } + else if (typeof sceneConfig === 'function') + { + newScene = this.createSceneFromFunction(key, sceneConfig); + } + + // Replace key in case the scene changed it + key = newScene.sys.settings.key; + + this.keys[key] = newScene; + + this.scenes.push(newScene); + + // Any data to inject? + if (this._data[key]) + { + newScene.sys.settings.data = this._data[key].data; + + if (this._data[key].autoStart) + { + entry.autoStart = true; + } + } + + if (entry.autoStart || newScene.sys.settings.active) + { + this._start.push(key); + } + } + + // Clear the pending lists + this._pending.length = 0; + + this._data = {}; + + this.isBooted = true; + + // _start might have been populated by the above + for (i = 0; i < this._start.length; i++) + { + entry = this._start[i]; + + this.start(entry); + } + + this._start.length = 0; + }, + + /** + * Process the Scene operations queue. + * + * @method Phaser.Scenes.SceneManager#processQueue + * @since 3.0.0 + */ + processQueue: function () + { + var pendingLength = this._pending.length; + var queueLength = this._queue.length; + + if (pendingLength === 0 && queueLength === 0) + { + return; + } + + var i; + var entry; + + if (pendingLength) + { + for (i = 0; i < pendingLength; i++) + { + entry = this._pending[i]; + + this.add(entry.key, entry.scene, entry.autoStart, entry.data); + } + + // _start might have been populated by this.add + for (i = 0; i < this._start.length; i++) + { + entry = this._start[i]; + + this.start(entry); + } + + // Clear the pending lists + this._start.length = 0; + this._pending.length = 0; + } + + for (i = 0; i < this._queue.length; i++) + { + entry = this._queue[i]; + + this[entry.op](entry.keyA, entry.keyB, entry.data); + } + + this._queue.length = 0; + }, + + /** + * Adds a new Scene into the SceneManager. + * You must give each Scene a unique key by which you'll identify it. + * + * The `sceneConfig` can be: + * + * * A `Phaser.Scene` object, or an object that extends it. + * * A plain JavaScript object + * * A JavaScript ES6 Class that extends `Phaser.Scene` + * * A JavaScript ES5 prototype based Class + * * A JavaScript function + * + * If a function is given then a new Scene will be created by calling it. + * + * @method Phaser.Scenes.SceneManager#add + * @since 3.0.0 + * + * @param {string} key - A unique key used to reference the Scene, i.e. `MainMenu` or `Level1`. + * @param {(Phaser.Types.Scenes.SceneType)} sceneConfig - The config for the Scene + * @param {boolean} [autoStart=false] - If `true` the Scene will be started immediately after being added. + * @param {object} [data] - Optional data object. This will be set as `Scene.settings.data` and passed to `Scene.init`, and `Scene.create`. + * + * @return {?Phaser.Scene} The added Scene, if it was added immediately, otherwise `null`. + */ + add: function (key, sceneConfig, autoStart, data) + { + if (autoStart === undefined) { autoStart = false; } + if (data === undefined) { data = {}; } + + // If processing or not booted then put scene into a holding pattern + if (this.isProcessing || !this.isBooted) + { + this._pending.push({ + key: key, + scene: sceneConfig, + autoStart: autoStart, + data: data + }); + + if (!this.isBooted) + { + this._data[key] = { data: data }; + } + + return null; + } + + key = this.getKey(key, sceneConfig); + + var newScene; + + if (sceneConfig instanceof Scene) + { + newScene = this.createSceneFromInstance(key, sceneConfig); + } + else if (typeof sceneConfig === 'object') + { + sceneConfig.key = key; + + newScene = this.createSceneFromObject(key, sceneConfig); + } + else if (typeof sceneConfig === 'function') + { + newScene = this.createSceneFromFunction(key, sceneConfig); + } + + // Any data to inject? + newScene.sys.settings.data = data; + + // Replace key in case the scene changed it + key = newScene.sys.settings.key; + + this.keys[key] = newScene; + + this.scenes.push(newScene); + + if (autoStart || newScene.sys.settings.active) + { + if (this._pending.length) + { + this._start.push(key); + } + else + { + this.start(key); + } + } + + return newScene; + }, + + /** + * Removes a Scene from the SceneManager. + * + * The Scene is removed from the local scenes array, it's key is cleared from the keys + * cache and Scene.Systems.destroy is then called on it. + * + * If the SceneManager is processing the Scenes when this method is called it will + * queue the operation for the next update sequence. + * + * @method Phaser.Scenes.SceneManager#remove + * @since 3.2.0 + * + * @param {string} key - A unique key used to reference the Scene, i.e. `MainMenu` or `Level1`. + * + * @return {this} This Scene Manager instance. + */ + remove: function (key) + { + if (this.isProcessing) + { + return this.queueOp('remove', key); + } + + var sceneToRemove = this.getScene(key); + + if (!sceneToRemove || sceneToRemove.sys.isTransitioning()) + { + return this; + } + + var index = this.scenes.indexOf(sceneToRemove); + var sceneKey = sceneToRemove.sys.settings.key; + + if (index > -1) + { + delete this.keys[sceneKey]; + this.scenes.splice(index, 1); + + if (this._start.indexOf(sceneKey) > -1) + { + index = this._start.indexOf(sceneKey); + this._start.splice(index, 1); + } + + sceneToRemove.sys.destroy(); + } + + return this; + }, + + /** + * Boot the given Scene. + * + * @method Phaser.Scenes.SceneManager#bootScene + * @private + * @fires Phaser.Scenes.Events#TRANSITION_INIT + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to boot. + */ + bootScene: function (scene) + { + var sys = scene.sys; + var settings = sys.settings; + + sys.sceneUpdate = NOOP; + + if (scene.init) + { + scene.init.call(scene, settings.data); + + settings.status = CONST.INIT; + + if (settings.isTransition) + { + sys.events.emit(Events.TRANSITION_INIT, settings.transitionFrom, settings.transitionDuration); + } + } + + var loader; + + if (sys.load) + { + loader = sys.load; + + loader.reset(); + } + + if (loader && scene.preload) + { + scene.preload.call(scene); + + settings.status = CONST.LOADING; + + // Start the loader going as we have something in the queue + loader.once(LoaderEvents.COMPLETE, this.loadComplete, this); + + loader.start(); + } + else + { + // No preload? Then there was nothing to load either + this.create(scene); + } + }, + + /** + * Handles load completion for a Scene's Loader. + * + * Starts the Scene that the Loader belongs to. + * + * @method Phaser.Scenes.SceneManager#loadComplete + * @private + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - The loader that has completed loading. + */ + loadComplete: function (loader) + { + this.create(loader.scene); + }, + + /** + * Handle payload completion for a Scene. + * + * @method Phaser.Scenes.SceneManager#payloadComplete + * @private + * @since 3.0.0 + * + * @param {Phaser.Loader.LoaderPlugin} loader - The loader that has completed loading its Scene's payload. + */ + payloadComplete: function (loader) + { + this.bootScene(loader.scene); + }, + + /** + * Updates the Scenes. + * + * @method Phaser.Scenes.SceneManager#update + * @since 3.0.0 + * + * @param {number} time - Time elapsed. + * @param {number} delta - Delta time from the last update. + */ + update: function (time, delta) + { + this.processQueue(); + + this.isProcessing = true; + + // Loop through the active scenes in reverse order + for (var i = this.scenes.length - 1; i >= 0; i--) + { + var sys = this.scenes[i].sys; + + if (sys.settings.status > CONST.START && sys.settings.status <= CONST.RUNNING) + { + sys.step(time, delta); + } + + if (sys.scenePlugin && sys.scenePlugin._target) + { + sys.scenePlugin.step(time, delta); + } + } + }, + + /** + * Renders the Scenes. + * + * @method Phaser.Scenes.SceneManager#render + * @since 3.0.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The renderer to use. + */ + render: function (renderer) + { + // Loop through the scenes in forward order + for (var i = 0; i < this.scenes.length; i++) + { + var sys = this.scenes[i].sys; + + if (sys.settings.visible && sys.settings.status >= CONST.LOADING && sys.settings.status < CONST.SLEEPING) + { + sys.render(renderer); + } + } + + this.isProcessing = false; + }, + + /** + * Calls the given Scene's {@link Phaser.Scene#create} method and updates its status. + * + * @method Phaser.Scenes.SceneManager#create + * @private + * @fires Phaser.Scenes.Events#CREATE + * @fires Phaser.Scenes.Events#TRANSITION_INIT + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to create. + */ + create: function (scene) + { + var sys = scene.sys; + var settings = sys.settings; + + if (scene.create) + { + settings.status = CONST.CREATING; + + scene.create.call(scene, settings.data); + + if (settings.status === CONST.DESTROYED) + { + return; + } + } + + if (settings.isTransition) + { + sys.events.emit(Events.TRANSITION_START, settings.transitionFrom, settings.transitionDuration); + } + + // If the Scene has an update function we'll set it now, otherwise it'll remain as NOOP + if (scene.update) + { + sys.sceneUpdate = scene.update; + } + + settings.status = CONST.RUNNING; + + sys.events.emit(Events.CREATE, scene); + }, + + /** + * Creates and initializes a Scene from a function. + * + * @method Phaser.Scenes.SceneManager#createSceneFromFunction + * @private + * @since 3.0.0 + * + * @param {string} key - The key of the Scene. + * @param {function} scene - The function to create the Scene from. + * + * @return {Phaser.Scene} The created Scene. + */ + createSceneFromFunction: function (key, scene) + { + var newScene = new scene(); + + if (newScene instanceof Scene) + { + var configKey = newScene.sys.settings.key; + + if (configKey !== '') + { + key = configKey; + } + + if (this.keys.hasOwnProperty(key)) + { + throw new Error('Cannot add Scene with duplicate key: ' + key); + } + + return this.createSceneFromInstance(key, newScene); + } + else + { + newScene.sys = new Systems(newScene); + + newScene.sys.settings.key = key; + + newScene.sys.init(this.game); + + return newScene; + } + }, + + /** + * Creates and initializes a Scene instance. + * + * @method Phaser.Scenes.SceneManager#createSceneFromInstance + * @private + * @since 3.0.0 + * + * @param {string} key - The key of the Scene. + * @param {Phaser.Scene} newScene - The Scene instance. + * + * @return {Phaser.Scene} The created Scene. + */ + createSceneFromInstance: function (key, newScene) + { + var configKey = newScene.sys.settings.key; + + if (configKey === '') + { + newScene.sys.settings.key = key; + } + + newScene.sys.init(this.game); + + return newScene; + }, + + /** + * Creates and initializes a Scene from an Object definition. + * + * @method Phaser.Scenes.SceneManager#createSceneFromObject + * @private + * @since 3.0.0 + * + * @param {string} key - The key of the Scene. + * @param {(string|Phaser.Types.Scenes.SettingsConfig|Phaser.Types.Scenes.CreateSceneFromObjectConfig)} sceneConfig - The Scene config. + * + * @return {Phaser.Scene} The created Scene. + */ + createSceneFromObject: function (key, sceneConfig) + { + var newScene = new Scene(sceneConfig); + + var configKey = newScene.sys.settings.key; + + if (configKey !== '') + { + key = configKey; + } + else + { + newScene.sys.settings.key = key; + } + + newScene.sys.init(this.game); + + // Extract callbacks + + var defaults = [ 'init', 'preload', 'create', 'update', 'render' ]; + + for (var i = 0; i < defaults.length; i++) + { + var sceneCallback = GetValue(sceneConfig, defaults[i], null); + + if (sceneCallback) + { + newScene[defaults[i]] = sceneCallback; + } + } + + // Now let's move across any other functions or properties that may exist in the extend object: + + /* + scene: { + preload: preload, + create: create, + extend: { + hello: 1, + test: 'atari', + addImage: addImage + } + } + */ + + if (sceneConfig.hasOwnProperty('extend')) + { + for (var propertyKey in sceneConfig.extend) + { + if (!sceneConfig.extend.hasOwnProperty(propertyKey)) + { + continue; + } + + var value = sceneConfig.extend[propertyKey]; + + if (propertyKey === 'data' && newScene.hasOwnProperty('data') && typeof value === 'object') + { + // Populate the DataManager + newScene.data.merge(value); + } + else if (propertyKey !== 'sys') + { + newScene[propertyKey] = value; + } + } + } + + return newScene; + }, + + /** + * Retrieves the key of a Scene from a Scene config. + * + * @method Phaser.Scenes.SceneManager#getKey + * @private + * @since 3.0.0 + * + * @param {string} key - The key to check in the Scene config. + * @param {(Phaser.Scene|Phaser.Types.Scenes.SettingsConfig|function)} sceneConfig - The Scene config. + * + * @return {string} The Scene key. + */ + getKey: function (key, sceneConfig) + { + if (!key) { key = 'default'; } + + if (typeof sceneConfig === 'function') + { + return key; + } + else if (sceneConfig instanceof Scene) + { + key = sceneConfig.sys.settings.key; + } + else if (typeof sceneConfig === 'object' && sceneConfig.hasOwnProperty('key')) + { + key = sceneConfig.key; + } + + // By this point it's either 'default' or extracted from the Scene + + if (this.keys.hasOwnProperty(key)) + { + throw new Error('Cannot add Scene with duplicate key: ' + key); + } + else + { + return key; + } + }, + + /** + * Returns an array of all the current Scenes being managed by this Scene Manager. + * + * You can filter the output by the active state of the Scene and choose to have + * the array returned in normal or reversed order. + * + * @method Phaser.Scenes.SceneManager#getScenes + * @since 3.16.0 + * + * @generic {Phaser.Scene[]} T - [$return] + * @genericUse {T} - [$return] + * + * @param {boolean} [isActive=true] - Only include Scene's that are currently active? + * @param {boolean} [inReverse=false] - Return the array of Scenes in reverse? + * + * @return {Phaser.Scene[]} An array containing all of the Scenes in the Scene Manager. + */ + getScenes: function (isActive, inReverse) + { + if (isActive === undefined) { isActive = true; } + if (inReverse === undefined) { inReverse = false; } + + var out = []; + var scenes = this.scenes; + + for (var i = 0; i < scenes.length; i++) + { + var scene = scenes[i]; + + if (scene && (!isActive || (isActive && scene.sys.isActive()))) + { + out.push(scene); + } + } + + return (inReverse) ? out.reverse() : out; + }, + + /** + * Retrieves a Scene based on the given key. + * + * If an actual Scene is passed to this method, it can be used to check if + * its currently within the Scene Manager, or not. + * + * @method Phaser.Scenes.SceneManager#getScene + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * @genericUse {T} - [$return] + * + * @param {(string|Phaser.Scene)} key - The key of the Scene to retrieve. + * + * @return {?Phaser.Scene} The Scene, or `null` if no matching Scene was found. + */ + getScene: function (key) + { + if (typeof key === 'string') + { + if (this.keys[key]) + { + return this.keys[key]; + } + } + else + { + for (var i = 0; i < this.scenes.length; i++) + { + if (key === this.scenes[i]) + { + return key; + } + } + } + + return null; + }, + + /** + * Determines whether a Scene is running. + * + * @method Phaser.Scenes.SceneManager#isActive + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to check. + * + * @return {boolean} Whether the Scene is running, or `null` if no matching Scene was found. + */ + isActive: function (key) + { + var scene = this.getScene(key); + + if (scene) + { + return scene.sys.isActive(); + } + + return null; + }, + + /** + * Determines whether a Scene is paused. + * + * @method Phaser.Scenes.SceneManager#isPaused + * @since 3.17.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to check. + * + * @return {boolean} Whether the Scene is paused, or `null` if no matching Scene was found. + */ + isPaused: function (key) + { + var scene = this.getScene(key); + + if (scene) + { + return scene.sys.isPaused(); + } + + return null; + }, + + /** + * Determines whether a Scene is visible. + * + * @method Phaser.Scenes.SceneManager#isVisible + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to check. + * + * @return {boolean} Whether the Scene is visible, or `null` if no matching Scene was found. + */ + isVisible: function (key) + { + var scene = this.getScene(key); + + if (scene) + { + return scene.sys.isVisible(); + } + + return null; + }, + + /** + * Determines whether a Scene is sleeping. + * + * @method Phaser.Scenes.SceneManager#isSleeping + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to check. + * + * @return {boolean} Whether the Scene is sleeping, or `null` if no matching Scene was found. + */ + isSleeping: function (key) + { + var scene = this.getScene(key); + + if (scene) + { + return scene.sys.isSleeping(); + } + + return null; + }, + + /** + * Pauses the given Scene. + * + * @method Phaser.Scenes.SceneManager#pause + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to pause. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted by its pause event. + * + * @return {this} This Scene Manager instance. + */ + pause: function (key, data) + { + var scene = this.getScene(key); + + if (scene) + { + scene.sys.pause(data); + } + + return this; + }, + + /** + * Resumes the given Scene. + * + * @method Phaser.Scenes.SceneManager#resume + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to resume. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted by its resume event. + * + * @return {this} This Scene Manager instance. + */ + resume: function (key, data) + { + var scene = this.getScene(key); + + if (scene) + { + scene.sys.resume(data); + } + + return this; + }, + + /** + * Puts the given Scene to sleep. + * + * @method Phaser.Scenes.SceneManager#sleep + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to put to sleep. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted by its sleep event. + * + * @return {this} This Scene Manager instance. + */ + sleep: function (key, data) + { + var scene = this.getScene(key); + + if (scene && !scene.sys.isTransitioning()) + { + scene.sys.sleep(data); + } + + return this; + }, + + /** + * Awakens the given Scene. + * + * @method Phaser.Scenes.SceneManager#wake + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to wake up. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted by its wake event. + * + * @return {this} This Scene Manager instance. + */ + wake: function (key, data) + { + var scene = this.getScene(key); + + if (scene) + { + scene.sys.wake(data); + } + + return this; + }, + + /** + * Runs the given Scene. + * + * If the given Scene is paused, it will resume it. If sleeping, it will wake it. + * If not running at all, it will be started. + * + * Use this if you wish to open a modal Scene by calling `pause` on the current + * Scene, then `run` on the modal Scene. + * + * @method Phaser.Scenes.SceneManager#run + * @since 3.10.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to run. + * @param {object} [data] - A data object that will be passed to the Scene on start, wake, or resume. + * + * @return {this} This Scene Manager instance. + */ + run: function (key, data) + { + var scene = this.getScene(key); + + if (!scene) + { + for (var i = 0; i < this._pending.length; i++) + { + if (this._pending[i].key === key) + { + this.queueOp('start', key, data); + break; + } + } + return this; + } + + if (scene.sys.isSleeping()) + { + // Sleeping? + scene.sys.wake(data); + } + else if (scene.sys.isPaused()) + { + // Paused? + scene.sys.resume(data); + } + else + { + // Not actually running? + this.start(key, data); + } + }, + + /** + * Starts the given Scene, if it is not starting, loading, or creating. + * + * If the Scene is running, paused, or sleeping, it will be shutdown and then started. + * + * @method Phaser.Scenes.SceneManager#start + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to start. + * @param {object} [data] - Optional data object to pass to `Scene.Settings` and `Scene.init`, and `Scene.create`. + * + * @return {this} This Scene Manager instance. + */ + start: function (key, data) + { + // If the Scene Manager is not running, then put the Scene into a holding pattern + if (!this.isBooted) + { + this._data[key] = { + autoStart: true, + data: data + }; + + return this; + } + + var scene = this.getScene(key); + + if (!scene) + { + console.warn('Scene key not found: ' + key); + return this; + } + + var sys = scene.sys; + var status = sys.settings.status; + + // If the scene is already started but not yet running, + // let it continue. + if (status >= CONST.START && status <= CONST.CREATING) + { + return this; + } + + // If the Scene is already running, paused, or sleeping, + // close it down before starting it again. + else if (status >= CONST.RUNNING && status <= CONST.SLEEPING) + { + sys.shutdown(); + + sys.sceneUpdate = NOOP; + + sys.start(data); + } + + // If the Scene is INIT or SHUTDOWN, + // start it directly. + else + { + sys.sceneUpdate = NOOP; + + sys.start(data); + + var loader; + + if (sys.load) + { + loader = sys.load; + } + + // Files payload? + if (loader && sys.settings.hasOwnProperty('pack')) + { + loader.reset(); + + if (loader.addPack({ payload: sys.settings.pack })) + { + sys.settings.status = CONST.LOADING; + + loader.once(LoaderEvents.COMPLETE, this.payloadComplete, this); + + loader.start(); + + return this; + } + } + } + + this.bootScene(scene); + + return this; + }, + + /** + * Stops the given Scene. + * + * @method Phaser.Scenes.SceneManager#stop + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to stop. + * @param {object} [data] - Optional data object to pass to Scene.shutdown. + * + * @return {this} This Scene Manager instance. + */ + stop: function (key, data) + { + var scene = this.getScene(key); + + if (scene && !scene.sys.isTransitioning() && scene.sys.settings.status !== CONST.SHUTDOWN) + { + var loader = scene.sys.load; + + if (loader) + { + loader.off(LoaderEvents.COMPLETE, this.loadComplete, this); + loader.off(LoaderEvents.COMPLETE, this.payloadComplete, this); + } + + scene.sys.shutdown(data); + } + + return this; + }, + + /** + * Sleeps one one Scene and starts the other. + * + * @method Phaser.Scenes.SceneManager#switch + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [from,to] + * + * @param {(string|Phaser.Scene)} from - The Scene to sleep. + * @param {(string|Phaser.Scene)} to - The Scene to start. + * @param {object} [data] - Optional data object to pass to `Scene.Settings` and `Scene.init`, and `Scene.create`. It is only passed when the scene starts for the first time. + * + * @return {this} This Scene Manager instance. + */ + switch: function (from, to, data) + { + var sceneA = this.getScene(from); + var sceneB = this.getScene(to); + + if (sceneA && sceneB && sceneA !== sceneB) + { + this.sleep(from); + + if (this.isSleeping(to)) + { + this.wake(to, data); + } + else + { + this.start(to, data); + } + } + + return this; + }, + + /** + * Retrieves a Scene by numeric index. + * + * @method Phaser.Scenes.SceneManager#getAt + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {T} - [$return] + * + * @param {number} index - The index of the Scene to retrieve. + * + * @return {(Phaser.Scene|undefined)} The Scene. + */ + getAt: function (index) + { + return this.scenes[index]; + }, + + /** + * Retrieves the numeric index of a Scene. + * + * @method Phaser.Scenes.SceneManager#getIndex + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The key of the Scene. + * + * @return {number} The index of the Scene. + */ + getIndex: function (key) + { + var scene = this.getScene(key); + + return this.scenes.indexOf(scene); + }, + + /** + * Brings a Scene to the top of the Scenes list. + * + * This means it will render above all other Scenes. + * + * @method Phaser.Scenes.SceneManager#bringToTop + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to move. + * + * @return {this} This Scene Manager instance. + */ + bringToTop: function (key) + { + if (this.isProcessing) + { + return this.queueOp('bringToTop', key); + } + + var index = this.getIndex(key); + var scenes = this.scenes; + + if (index !== -1 && index < scenes.length) + { + var scene = this.getScene(key); + + scenes.splice(index, 1); + scenes.push(scene); + } + + return this; + }, + + /** + * Sends a Scene to the back of the Scenes list. + * + * This means it will render below all other Scenes. + * + * @method Phaser.Scenes.SceneManager#sendToBack + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to move. + * + * @return {this} This Scene Manager instance. + */ + sendToBack: function (key) + { + if (this.isProcessing) + { + return this.queueOp('sendToBack', key); + } + + var index = this.getIndex(key); + + if (index !== -1 && index > 0) + { + var scene = this.getScene(key); + + this.scenes.splice(index, 1); + this.scenes.unshift(scene); + } + + return this; + }, + + /** + * Moves a Scene down one position in the Scenes list. + * + * @method Phaser.Scenes.SceneManager#moveDown + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to move. + * + * @return {this} This Scene Manager instance. + */ + moveDown: function (key) + { + if (this.isProcessing) + { + return this.queueOp('moveDown', key); + } + + var indexA = this.getIndex(key); + + if (indexA > 0) + { + var indexB = indexA - 1; + var sceneA = this.getScene(key); + var sceneB = this.getAt(indexB); + + this.scenes[indexA] = sceneB; + this.scenes[indexB] = sceneA; + } + + return this; + }, + + /** + * Moves a Scene up one position in the Scenes list. + * + * @method Phaser.Scenes.SceneManager#moveUp + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to move. + * + * @return {this} This Scene Manager instance. + */ + moveUp: function (key) + { + if (this.isProcessing) + { + return this.queueOp('moveUp', key); + } + + var indexA = this.getIndex(key); + + if (indexA < this.scenes.length - 1) + { + var indexB = indexA + 1; + var sceneA = this.getScene(key); + var sceneB = this.getAt(indexB); + + this.scenes[indexA] = sceneB; + this.scenes[indexB] = sceneA; + } + + return this; + }, + + /** + * Moves a Scene so it is immediately above another Scene in the Scenes list. + * If the Scene is already above the other, it isn't moved. + * + * This means it will render over the top of the other Scene. + * + * @method Phaser.Scenes.SceneManager#moveAbove + * @since 3.2.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [keyA,keyB] + * + * @param {(string|Phaser.Scene)} keyA - The Scene that Scene B will be moved above. + * @param {(string|Phaser.Scene)} keyB - The Scene to be moved. + * + * @return {this} This Scene Manager instance. + */ + moveAbove: function (keyA, keyB) + { + if (keyA === keyB) + { + return this; + } + + if (this.isProcessing) + { + return this.queueOp('moveAbove', keyA, keyB); + } + + var indexA = this.getIndex(keyA); + var indexB = this.getIndex(keyB); + + if (indexA !== -1 && indexB !== -1 && indexB < indexA) + { + var tempScene = this.getAt(indexB); + + // Remove + this.scenes.splice(indexB, 1); + + // Add in new location + this.scenes.splice(indexA + (indexB > indexA), 0, tempScene); + } + + return this; + }, + + /** + * Moves a Scene so it is immediately below another Scene in the Scenes list. + * If the Scene is already below the other, it isn't moved. + * + * This means it will render behind the other Scene. + * + * @method Phaser.Scenes.SceneManager#moveBelow + * @since 3.2.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [keyA,keyB] + * + * @param {(string|Phaser.Scene)} keyA - The Scene that Scene B will be moved below. + * @param {(string|Phaser.Scene)} keyB - The Scene to be moved. + * + * @return {this} This Scene Manager instance. + */ + moveBelow: function (keyA, keyB) + { + if (keyA === keyB) + { + return this; + } + + if (this.isProcessing) + { + return this.queueOp('moveBelow', keyA, keyB); + } + + var indexA = this.getIndex(keyA); + var indexB = this.getIndex(keyB); + + if (indexA !== -1 && indexB !== -1 && indexB > indexA) + { + var tempScene = this.getAt(indexB); + + // Remove + this.scenes.splice(indexB, 1); + + if (indexA === 0) + { + this.scenes.unshift(tempScene); + } + else + { + // Add in new location + this.scenes.splice(indexA - (indexB < indexA), 0, tempScene); + } + } + + return this; + }, + + /** + * Queue a Scene operation for the next update. + * + * @method Phaser.Scenes.SceneManager#queueOp + * @private + * @since 3.0.0 + * + * @param {string} op - The operation to perform. + * @param {(string|Phaser.Scene)} keyA - Scene A. + * @param {(any|string|Phaser.Scene)} [keyB] - Scene B, or a data object. + * @param {any} [data] - Optional data object to pass. + * + * @return {this} This Scene Manager instance. + */ + queueOp: function (op, keyA, keyB, data) + { + this._queue.push({ op: op, keyA: keyA, keyB: keyB, data: data }); + + return this; + }, + + /** + * Swaps the positions of two Scenes in the Scenes list. + * + * @method Phaser.Scenes.SceneManager#swapPosition + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [keyA,keyB] + * + * @param {(string|Phaser.Scene)} keyA - The first Scene to swap. + * @param {(string|Phaser.Scene)} keyB - The second Scene to swap. + * + * @return {this} This Scene Manager instance. + */ + swapPosition: function (keyA, keyB) + { + if (keyA === keyB) + { + return this; + } + + if (this.isProcessing) + { + return this.queueOp('swapPosition', keyA, keyB); + } + + var indexA = this.getIndex(keyA); + var indexB = this.getIndex(keyB); + + if (indexA !== indexB && indexA !== -1 && indexB !== -1) + { + var tempScene = this.getAt(indexA); + + this.scenes[indexA] = this.scenes[indexB]; + this.scenes[indexB] = tempScene; + } + + return this; + }, + + /** + * Dumps debug information about each Scene to the developer console. + * + * @method Phaser.Scenes.SceneManager#dump + * @since 3.2.0 + */ + dump: function () + { + var out = []; + var map = [ 'pending', 'init', 'start', 'loading', 'creating', 'running', 'paused', 'sleeping', 'shutdown', 'destroyed' ]; + + for (var i = 0; i < this.scenes.length; i++) + { + var sys = this.scenes[i].sys; + + var key = (sys.settings.visible && (sys.settings.status === CONST.RUNNING || sys.settings.status === CONST.PAUSED)) ? '[*] ' : '[-] '; + key += sys.settings.key + ' (' + map[sys.settings.status] + ')'; + + out.push(key); + } + + console.log(out.join('\n')); + }, + + /** + * Destroy this Scene Manager and all of its systems. + * + * This process cannot be reversed. + * + * This method is called automatically when a Phaser Game instance is destroyed. + * + * @method Phaser.Scenes.SceneManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + for (var i = 0; i < this.scenes.length; i++) + { + var sys = this.scenes[i].sys; + + sys.destroy(); + } + + this.systemScene.sys.destroy(); + + this.update = NOOP; + + this.scenes = []; + + this._pending = []; + this._start = []; + this._queue = []; + + this.game = null; + this.systemScene = null; + } + +}); + +module.exports = SceneManager; + + +/***/ }), + +/***/ 52209: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(44594); +var GetFastValue = __webpack_require__(95540); +var PluginCache = __webpack_require__(37277); + +/** + * @classdesc + * The Scene Plugin is the main interface to the Scene Manager and allows you to control + * any Scene running in your game. You should always use this plugin. By default, it is + * mapped to the Scene property `this.scene`. Meaning, from within a Scene, you can call + * methods such as `this.scene.start()`. + * + * Note that nearly all methods in this class are run on a queue-basis and not + * immediately. For example, calling `this.scene.launch('SceneB')` will try to + * launch SceneB when the Scene Manager next updates, which is at the start of the game + * step. All operations are queued and run in the order in which they are invoked here. + * + * @class ScenePlugin + * @memberof Phaser.Scenes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that this ScenePlugin belongs to. + */ +var ScenePlugin = new Class({ + + initialize: + + function ScenePlugin (scene) + { + /** + * The Scene that this ScenePlugin belongs to. + * + * @name Phaser.Scenes.ScenePlugin#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The Scene Systems instance of the Scene that this ScenePlugin belongs to. + * + * @name Phaser.Scenes.ScenePlugin#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * The settings of the Scene this ScenePlugin belongs to. + * + * @name Phaser.Scenes.ScenePlugin#settings + * @type {Phaser.Types.Scenes.SettingsObject} + * @since 3.0.0 + */ + this.settings = scene.sys.settings; + + /** + * The key of the Scene this ScenePlugin belongs to. + * + * @name Phaser.Scenes.ScenePlugin#key + * @type {string} + * @since 3.0.0 + */ + this.key = scene.sys.settings.key; + + /** + * The Game's SceneManager. + * + * @name Phaser.Scenes.ScenePlugin#manager + * @type {Phaser.Scenes.SceneManager} + * @since 3.0.0 + */ + this.manager = scene.sys.game.scene; + + /** + * If this Scene is currently transitioning to another, this holds + * the current percentage of the transition progress, between 0 and 1. + * + * @name Phaser.Scenes.ScenePlugin#transitionProgress + * @type {number} + * @since 3.5.0 + */ + this.transitionProgress = 0; + + /** + * Transition elapsed timer. + * + * @name Phaser.Scenes.ScenePlugin#_elapsed + * @type {number} + * @private + * @since 3.5.0 + */ + this._elapsed = 0; + + /** + * Transition elapsed timer. + * + * @name Phaser.Scenes.ScenePlugin#_target + * @type {?Phaser.Scene} + * @private + * @since 3.5.0 + */ + this._target = null; + + /** + * Transition duration. + * + * @name Phaser.Scenes.ScenePlugin#_duration + * @type {number} + * @private + * @since 3.5.0 + */ + this._duration = 0; + + /** + * Transition callback. + * + * @name Phaser.Scenes.ScenePlugin#_onUpdate + * @type {function} + * @private + * @since 3.5.0 + */ + this._onUpdate; + + /** + * Transition callback scope. + * + * @name Phaser.Scenes.ScenePlugin#_onUpdateScope + * @type {object} + * @private + * @since 3.5.0 + */ + this._onUpdateScope; + + /** + * Will this Scene sleep (true) after the transition, or stop (false) + * + * @name Phaser.Scenes.ScenePlugin#_willSleep + * @type {boolean} + * @private + * @since 3.5.0 + */ + this._willSleep = false; + + /** + * Will this Scene be removed from the Scene Manager after the transition completes? + * + * @name Phaser.Scenes.ScenePlugin#_willRemove + * @type {boolean} + * @private + * @since 3.5.0 + */ + this._willRemove = false; + + scene.sys.events.once(Events.BOOT, this.boot, this); + scene.sys.events.on(Events.START, this.pluginStart, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Scenes.ScenePlugin#boot + * @private + * @since 3.0.0 + */ + boot: function () + { + this.systems.events.once(Events.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Scenes.ScenePlugin#pluginStart + * @private + * @since 3.5.0 + */ + pluginStart: function () + { + this._target = null; + + this.systems.events.once(Events.SHUTDOWN, this.shutdown, this); + }, + + /** + * Shutdown this Scene and run the given one. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#start + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to start. + * @param {object} [data] - The Scene data. If no value is given it will not overwrite any previous data that may exist. + * + * @return {this} This Scene Plugin instance. + */ + start: function (key, data) + { + if (key === undefined) { key = this.key; } + + this.manager.queueOp('stop', this.key); + this.manager.queueOp('start', key, data); + + return this; + }, + + /** + * Restarts this Scene. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#restart + * @since 3.4.0 + * + * @param {object} [data] - The Scene data. If no value is given it will not overwrite any previous data that may exist. + * + * @return {this} This Scene Plugin instance. + */ + restart: function (data) + { + var key = this.key; + + this.manager.queueOp('stop', key); + this.manager.queueOp('start', key, data); + + return this; + }, + + /** + * This will start a transition from the current Scene to the target Scene given. + * + * The target Scene cannot be the same as the current Scene. + * + * The transition will last for the duration specified in milliseconds. + * + * You can have the target Scene moved above or below this one in the display list. + * + * You can specify an update callback. This callback will be invoked _every frame_ for the duration + * of the transition. + * + * This Scene can either be sent to sleep at the end of the transition, or stopped. The default is to stop. + * + * There are also 5 transition related events: This scene will emit the event `transitionout` when + * the transition begins, which is typically the frame after calling this method. + * + * The target Scene will emit the event `transitioninit` when that Scene's `init` method is called. + * It will then emit the event `transitionstart` when its `create` method is called. + * If the Scene was sleeping and has been woken up, it will emit the event `transitionwake` instead of these two, + * as the Scenes `init` and `create` methods are not invoked when a Scene wakes up. + * + * When the duration of the transition has elapsed it will emit the event `transitioncomplete`. + * These events are cleared of all listeners when the Scene shuts down, but not if it is sent to sleep. + * + * It's important to understand that the duration of the transition begins the moment you call this method. + * If the Scene you are transitioning to includes delayed processes, such as waiting for files to load, the + * time still counts down even while that is happening. If the game itself pauses, or something else causes + * this Scenes update loop to stop, then the transition will also pause for that duration. There are + * checks in place to prevent you accidentally stopping a transitioning Scene but if you've got code to + * override this understand that until the target Scene completes it might never be unlocked for input events. + * + * @method Phaser.Scenes.ScenePlugin#transition + * @fires Phaser.Scenes.Events#TRANSITION_OUT + * @since 3.5.0 + * + * @param {Phaser.Types.Scenes.SceneTransitionConfig} config - The transition configuration object. + * + * @return {boolean} `true` is the transition was started, otherwise `false`. + */ + transition: function (config) + { + if (config === undefined) { config = {}; } + + var key = GetFastValue(config, 'target', false); + + var target = this.manager.getScene(key); + + if (!key || !this.checkValidTransition(target)) + { + return false; + } + + var duration = GetFastValue(config, 'duration', 1000); + + this._elapsed = 0; + this._target = target; + this._duration = duration; + this._willSleep = GetFastValue(config, 'sleep', false); + this._willRemove = GetFastValue(config, 'remove', false); + + var callback = GetFastValue(config, 'onUpdate', null); + + if (callback) + { + this._onUpdate = callback; + this._onUpdateScope = GetFastValue(config, 'onUpdateScope', this.scene); + } + + var allowInput = GetFastValue(config, 'allowInput', false); + + this.settings.transitionAllowInput = allowInput; + + var targetSettings = target.sys.settings; + + targetSettings.isTransition = true; + targetSettings.transitionFrom = this.scene; + targetSettings.transitionDuration = duration; + targetSettings.transitionAllowInput = allowInput; + + if (GetFastValue(config, 'moveAbove', false)) + { + this.manager.moveAbove(this.key, key); + } + else if (GetFastValue(config, 'moveBelow', false)) + { + this.manager.moveBelow(this.key, key); + } + + if (target.sys.isSleeping()) + { + target.sys.wake(GetFastValue(config, 'data')); + } + else + { + this.manager.start(key, GetFastValue(config, 'data')); + } + + var onStartCallback = GetFastValue(config, 'onStart', null); + + var onStartScope = GetFastValue(config, 'onStartScope', this.scene); + + if (onStartCallback) + { + onStartCallback.call(onStartScope, this.scene, target, duration); + } + + this.systems.events.emit(Events.TRANSITION_OUT, target, duration); + + return true; + }, + + /** + * Checks to see if this Scene can transition to the target Scene or not. + * + * @method Phaser.Scenes.ScenePlugin#checkValidTransition + * @private + * @since 3.5.0 + * + * @param {Phaser.Scene} target - The Scene to test against. + * + * @return {boolean} `true` if this Scene can transition, otherwise `false`. + */ + checkValidTransition: function (target) + { + // Not a valid target if it doesn't exist, isn't active or is already transitioning in or out + if (!target || target.sys.isActive() || target.sys.isTransitioning() || target === this.scene || this.systems.isTransitioning()) + { + return false; + } + + return true; + }, + + /** + * A single game step. This is only called if the parent Scene is transitioning + * out to another Scene. + * + * @method Phaser.Scenes.ScenePlugin#step + * @private + * @since 3.5.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + step: function (time, delta) + { + this._elapsed += delta; + + this.transitionProgress = Clamp(this._elapsed / this._duration, 0, 1); + + if (this._onUpdate) + { + this._onUpdate.call(this._onUpdateScope, this.transitionProgress); + } + + if (this._elapsed >= this._duration) + { + this.transitionComplete(); + } + }, + + /** + * Called by `step` when the transition out of this scene to another is over. + * + * @method Phaser.Scenes.ScenePlugin#transitionComplete + * @private + * @fires Phaser.Scenes.Events#TRANSITION_COMPLETE + * @since 3.5.0 + */ + transitionComplete: function () + { + var targetSys = this._target.sys; + var targetSettings = this._target.sys.settings; + + // Notify target scene + targetSys.events.emit(Events.TRANSITION_COMPLETE, this.scene); + + // Clear target scene settings + targetSettings.isTransition = false; + targetSettings.transitionFrom = null; + + // Clear local settings + this._duration = 0; + this._target = null; + this._onUpdate = null; + this._onUpdateScope = null; + + // Now everything is clear we can handle what happens to this Scene + if (this._willRemove) + { + this.manager.remove(this.key); + } + else if (this._willSleep) + { + this.systems.sleep(); + } + else + { + this.manager.stop(this.key); + } + }, + + /** + * Add the Scene into the Scene Manager and start it if 'autoStart' is true or the Scene config 'active' property is set. + * + * @method Phaser.Scenes.ScenePlugin#add + * @since 3.0.0 + * + * @param {string} key - A unique key used to reference the Scene, i.e. `MainMenu` or `Level1`. + * @param {(Phaser.Types.Scenes.SceneType)} sceneConfig - The config for the Scene + * @param {boolean} [autoStart=false] - If `true` the Scene will be started immediately after being added. + * @param {object} [data] - Optional data object. This will be set as `Scene.settings.data` and passed to `Scene.init`, and `Scene.create`. + * + * @return {?Phaser.Scene} The added Scene, if it was added immediately, otherwise `null`. + */ + add: function (key, sceneConfig, autoStart, data) + { + return this.manager.add(key, sceneConfig, autoStart, data); + }, + + /** + * Launch the given Scene and run it in parallel with this one. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#launch + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to launch. + * @param {object} [data] - The Scene data. + * + * @return {this} This Scene Plugin instance. + */ + launch: function (key, data) + { + if (key && key !== this.key) + { + this.manager.queueOp('start', key, data); + } + + return this; + }, + + /** + * Runs the given Scene, but does not change the state of this Scene. + * + * This will happen at the next Scene Manager update, not immediately. + * + * If the given Scene is paused, it will resume it. If sleeping, it will wake it. + * If not running at all, it will be started. + * + * Use this if you wish to open a modal Scene by calling `pause` on the current + * Scene, then `run` on the modal Scene. + * + * @method Phaser.Scenes.ScenePlugin#run + * @since 3.10.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to run. + * @param {object} [data] - A data object that will be passed to the Scene and emitted in its ready, wake, or resume events. + * + * @return {this} This Scene Plugin instance. + */ + run: function (key, data) + { + if (key && key !== this.key) + { + this.manager.queueOp('run', key, data); + } + + return this; + }, + + /** + * Pause the Scene - this stops the update step from happening but it still renders. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#pause + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to pause. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted in its pause event. + * + * @return {this} This Scene Plugin instance. + */ + pause: function (key, data) + { + if (key === undefined) { key = this.key; } + + this.manager.queueOp('pause', key, data); + + return this; + }, + + /** + * Resume the Scene - starts the update loop again. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#resume + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to resume. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted in its resume event. + * + * @return {this} This Scene Plugin instance. + */ + resume: function (key, data) + { + if (key === undefined) { key = this.key; } + + this.manager.queueOp('resume', key, data); + + return this; + }, + + /** + * Makes the Scene sleep (no update, no render) but doesn't shutdown. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#sleep + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to put to sleep. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted in its sleep event. + * + * @return {this} This Scene Plugin instance. + */ + sleep: function (key, data) + { + if (key === undefined) { key = this.key; } + + this.manager.queueOp('sleep', key, data); + + return this; + }, + + /** + * Makes the Scene wake-up (starts update and render) + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#wake + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to wake up. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted in its wake event. + * + * @return {this} This Scene Plugin instance. + */ + wake: function (key, data) + { + if (key === undefined) { key = this.key; } + + this.manager.queueOp('wake', key, data); + + return this; + }, + + /** + * Makes this Scene sleep then starts the Scene given. + * + * This will happen at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#switch + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to start. + * @param {any} [data] - Optional data object to pass to either the Scene `wake` or `start` method. + * + * @return {this} This Scene Plugin instance. + */ + switch: function (key, data) + { + if (key !== this.key) + { + this.manager.queueOp('switch', this.key, key, data); + } + + return this; + }, + + /** + * Shutdown the Scene, clearing display list, timers, etc. + * + * This happens at the next Scene Manager update, not immediately. + * + * @method Phaser.Scenes.ScenePlugin#stop + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to stop. + * @param {any} [data] - Optional data object to pass to Scene.Systems.shutdown. + * + * @return {this} This Scene Plugin instance. + */ + stop: function (key, data) + { + if (key === undefined) { key = this.key; } + + this.manager.queueOp('stop', key, data); + + return this; + }, + + /** + * Sets the active state of the given Scene. + * + * @method Phaser.Scenes.ScenePlugin#setActive + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {boolean} value - If `true` the Scene will be resumed. If `false` it will be paused. + * @param {(string|Phaser.Scene)} [key] - The Scene to set the active state of. + * @param {object} [data] - An optional data object that will be passed to the Scene and emitted with its events. + * + * @return {this} This Scene Plugin instance. + */ + setActive: function (value, key, data) + { + if (key === undefined) { key = this.key; } + + var scene = this.manager.getScene(key); + + if (scene) + { + scene.sys.setActive(value, data); + } + + return this; + }, + + /** + * Sets the visible state of the given Scene. + * + * @method Phaser.Scenes.ScenePlugin#setVisible + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {boolean} value - The visible value. + * @param {(string|Phaser.Scene)} [key] - The Scene to set the visible state for. + * + * @return {this} This Scene Plugin instance. + */ + setVisible: function (value, key) + { + if (key === undefined) { key = this.key; } + + var scene = this.manager.getScene(key); + + if (scene) + { + scene.sys.setVisible(value); + } + + return this; + }, + + /** + * Checks if the given Scene is sleeping or not? + * + * @method Phaser.Scenes.ScenePlugin#isSleeping + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to check. + * + * @return {boolean} Whether the Scene is sleeping, or `null` if no matching Scene was found. + */ + isSleeping: function (key) + { + if (key === undefined) { key = this.key; } + + return this.manager.isSleeping(key); + }, + + /** + * Checks if the given Scene is running or not? + * + * @method Phaser.Scenes.ScenePlugin#isActive + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to check. + * + * @return {boolean} Whether the Scene is running, or `null` if no matching Scene was found. + */ + isActive: function (key) + { + if (key === undefined) { key = this.key; } + + return this.manager.isActive(key); + }, + + /** + * Checks if the given Scene is paused or not? + * + * @method Phaser.Scenes.ScenePlugin#isPaused + * @since 3.17.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to check. + * + * @return {boolean} Whether the Scene is paused, or `null` if no matching Scene was found. + */ + isPaused: function (key) + { + if (key === undefined) { key = this.key; } + + return this.manager.isPaused(key); + }, + + /** + * Checks if the given Scene is visible or not? + * + * @method Phaser.Scenes.ScenePlugin#isVisible + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to check. + * + * @return {boolean} Whether the Scene is visible, or `null` if no matching Scene was found. + */ + isVisible: function (key) + { + if (key === undefined) { key = this.key; } + + return this.manager.isVisible(key); + }, + + /** + * Swaps the position of two scenes in the Scenes list. + * + * This controls the order in which they are rendered and updated. + * + * @method Phaser.Scenes.ScenePlugin#swapPosition + * @since 3.2.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [keyA,keyB] + * + * @param {(string|Phaser.Scene)} keyA - The first Scene to swap. + * @param {(string|Phaser.Scene)} [keyB] - The second Scene to swap. If none is given it defaults to this Scene. + * + * @return {this} This Scene Plugin instance. + */ + swapPosition: function (keyA, keyB) + { + if (keyB === undefined) { keyB = this.key; } + + if (keyA !== keyB) + { + this.manager.swapPosition(keyA, keyB); + } + + return this; + }, + + /** + * Moves a Scene so it is immediately above another Scene in the Scenes list. + * If the Scene is already above the other, it isn't moved. + * + * This means it will render over the top of the other Scene. + * + * @method Phaser.Scenes.ScenePlugin#moveAbove + * @since 3.2.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [keyA,keyB] + * + * @param {(string|Phaser.Scene)} keyA - The Scene that Scene B will be moved to be above. + * @param {(string|Phaser.Scene)} [keyB] - The Scene to be moved. If none is given it defaults to this Scene. + * + * @return {this} This Scene Plugin instance. + */ + moveAbove: function (keyA, keyB) + { + if (keyB === undefined) { keyB = this.key; } + + if (keyA !== keyB) + { + this.manager.moveAbove(keyA, keyB); + } + + return this; + }, + + /** + * Moves a Scene so it is immediately below another Scene in the Scenes list. + * If the Scene is already below the other, it isn't moved. + * + * This means it will render behind the other Scene. + * + * @method Phaser.Scenes.ScenePlugin#moveBelow + * @since 3.2.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [keyA,keyB] + * + * @param {(string|Phaser.Scene)} keyA - The Scene that Scene B will be moved to be below. + * @param {(string|Phaser.Scene)} [keyB] - The Scene to be moved. If none is given it defaults to this Scene. + * + * @return {this} This Scene Plugin instance. + */ + moveBelow: function (keyA, keyB) + { + if (keyB === undefined) { keyB = this.key; } + + if (keyA !== keyB) + { + this.manager.moveBelow(keyA, keyB); + } + + return this; + }, + + /** + * Removes a Scene from the SceneManager. + * + * The Scene is removed from the local scenes array, it's key is cleared from the keys + * cache and Scene.Systems.destroy is then called on it. + * + * If the SceneManager is processing the Scenes when this method is called it will + * queue the operation for the next update sequence. + * + * @method Phaser.Scenes.ScenePlugin#remove + * @since 3.2.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to be removed. + * + * @return {this} This Scene Plugin instance. + */ + remove: function (key) + { + if (key === undefined) { key = this.key; } + + this.manager.remove(key); + + return this; + }, + + /** + * Moves a Scene up one position in the Scenes list. + * + * @method Phaser.Scenes.ScenePlugin#moveUp + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to move. + * + * @return {this} This Scene Plugin instance. + */ + moveUp: function (key) + { + if (key === undefined) { key = this.key; } + + this.manager.moveUp(key); + + return this; + }, + + /** + * Moves a Scene down one position in the Scenes list. + * + * @method Phaser.Scenes.ScenePlugin#moveDown + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to move. + * + * @return {this} This Scene Plugin instance. + */ + moveDown: function (key) + { + if (key === undefined) { key = this.key; } + + this.manager.moveDown(key); + + return this; + }, + + /** + * Brings a Scene to the top of the Scenes list. + * + * This means it will render above all other Scenes. + * + * @method Phaser.Scenes.ScenePlugin#bringToTop + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to move. + * + * @return {this} This Scene Plugin instance. + */ + bringToTop: function (key) + { + if (key === undefined) { key = this.key; } + + this.manager.bringToTop(key); + + return this; + }, + + /** + * Sends a Scene to the back of the Scenes list. + * + * This means it will render below all other Scenes. + * + * @method Phaser.Scenes.ScenePlugin#sendToBack + * @since 3.0.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to move. + * + * @return {this} This Scene Plugin instance. + */ + sendToBack: function (key) + { + if (key === undefined) { key = this.key; } + + this.manager.sendToBack(key); + + return this; + }, + + /** + * Retrieves a Scene based on the given key. + * + * If an actual Scene is passed to this method, it can be used to check if + * its currently within the Scene Manager, or not. + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * @genericUse {T} - [$return] + * + * @method Phaser.Scenes.ScenePlugin#get + * @since 3.0.0 + * + * @param {(string|Phaser.Scene)} key - The Scene to retrieve. + * + * @return {Phaser.Scene} The Scene. + */ + get: function (key) + { + return this.manager.getScene(key); + }, + + /** + * Return the status of the Scene. + * + * @method Phaser.Scenes.ScenePlugin#getStatus + * @since 3.60.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} key - The Scene to get the status from. + * + * @return {number} The Scene status. This maps to the `Phaser.Scene` constants, such as `Phaser.Scene.LOADING`. + */ + getStatus: function (key) + { + var scene = this.manager.getScene(key); + + if (scene) + { + return scene.sys.getStatus(); + } + }, + + /** + * Retrieves the numeric index of a Scene in the Scenes list. + * + * @method Phaser.Scenes.ScenePlugin#getIndex + * @since 3.7.0 + * + * @generic {Phaser.Scene} T + * @genericUse {(T|string)} - [key] + * + * @param {(string|Phaser.Scene)} [key] - The Scene to get the index of. + * + * @return {number} The index of the Scene. + */ + getIndex: function (key) + { + if (key === undefined) { key = this.key; } + + return this.manager.getIndex(key); + }, + + /** + * The Scene that owns this plugin is shutting down. + * + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Scenes.ScenePlugin#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + var eventEmitter = this.systems.events; + + eventEmitter.off(Events.SHUTDOWN, this.shutdown, this); + eventEmitter.off(Events.TRANSITION_OUT); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Scenes.ScenePlugin#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.scene.sys.events.off(Events.START, this.start, this); + + this.scene = null; + this.systems = null; + this.settings = null; + this.manager = null; + } + +}); + +PluginCache.register('ScenePlugin', ScenePlugin, 'scenePlugin'); + +module.exports = ScenePlugin; + + +/***/ }), + +/***/ 55681: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(89993); +var GetValue = __webpack_require__(35154); +var Merge = __webpack_require__(46975); +var InjectionMap = __webpack_require__(87033); + +/** + * @namespace Phaser.Scenes.Settings + */ + +var Settings = { + + /** + * Takes a Scene configuration object and returns a fully formed System Settings object. + * + * @function Phaser.Scenes.Settings.create + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Scenes.SettingsConfig)} config - The Scene configuration object used to create this Scene Settings. + * + * @return {Phaser.Types.Scenes.SettingsObject} The Scene Settings object created as a result of the config and default settings. + */ + create: function (config) + { + if (typeof config === 'string') + { + config = { key: config }; + } + else if (config === undefined) + { + // Pass the 'hasOwnProperty' checks + config = {}; + } + + return { + + status: CONST.PENDING, + + key: GetValue(config, 'key', ''), + active: GetValue(config, 'active', false), + visible: GetValue(config, 'visible', true), + + isBooted: false, + + isTransition: false, + transitionFrom: null, + transitionDuration: 0, + transitionAllowInput: true, + + // Loader payload array + + data: {}, + + pack: GetValue(config, 'pack', false), + + // Cameras + + cameras: GetValue(config, 'cameras', null), + + // Scene Property Injection Map + + map: GetValue(config, 'map', Merge(InjectionMap, GetValue(config, 'mapAdd', {}))), + + // Physics + + physics: GetValue(config, 'physics', {}), + + // Loader + + loader: GetValue(config, 'loader', {}), + + // Plugins + + plugins: GetValue(config, 'plugins', false), + + // Input + + input: GetValue(config, 'input', {}) + + }; + } + +}; + +module.exports = Settings; + + +/***/ }), + +/***/ 2368: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(89993); +var DefaultPlugins = __webpack_require__(42363); +var Events = __webpack_require__(44594); +var GetPhysicsPlugins = __webpack_require__(27397); +var GetScenePlugins = __webpack_require__(52106); +var NOOP = __webpack_require__(29747); +var Settings = __webpack_require__(55681); + +/** + * @classdesc + * The Scene Systems class. + * + * This class is available from within a Scene under the property `sys`. + * It is responsible for managing all of the plugins a Scene has running, including the display list, and + * handling the update step and renderer. It also contains references to global systems belonging to Game. + * + * @class Systems + * @memberof Phaser.Scenes + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene that owns this Systems instance. + * @param {(string|Phaser.Types.Scenes.SettingsConfig)} config - Scene specific configuration settings. + */ +var Systems = new Class({ + + initialize: + + function Systems (scene, config) + { + /** + * A reference to the Scene that these Systems belong to. + * + * @name Phaser.Scenes.Systems#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * A reference to the Phaser Game instance. + * + * @name Phaser.Scenes.Systems#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game; + + /** + * A reference to either the Canvas or WebGL Renderer that this Game is using. + * + * @name Phaser.Scenes.Systems#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.17.0 + */ + this.renderer; + + /** + * The Scene Configuration object, as passed in when creating the Scene. + * + * @name Phaser.Scenes.Systems#config + * @type {(string|Phaser.Types.Scenes.SettingsConfig)} + * @since 3.0.0 + */ + this.config = config; + + /** + * The Scene Settings. This is the parsed output based on the Scene configuration. + * + * @name Phaser.Scenes.Systems#settings + * @type {Phaser.Types.Scenes.SettingsObject} + * @since 3.0.0 + */ + this.settings = Settings.create(config); + + /** + * A handy reference to the Scene canvas / context. + * + * @name Phaser.Scenes.Systems#canvas + * @type {HTMLCanvasElement} + * @since 3.0.0 + */ + this.canvas; + + /** + * A reference to the Canvas Rendering Context being used by the renderer. + * + * @name Phaser.Scenes.Systems#context + * @type {CanvasRenderingContext2D} + * @since 3.0.0 + */ + this.context; + + // Global Systems - these are single-instance global managers that belong to Game + + /** + * A reference to the global Animations Manager. + * + * In the default set-up you can access this from within a Scene via the `this.anims` property. + * + * @name Phaser.Scenes.Systems#anims + * @type {Phaser.Animations.AnimationManager} + * @since 3.0.0 + */ + this.anims; + + /** + * A reference to the global Cache. The Cache stores all files brought in to Phaser via + * the Loader, with the exception of images. Images are stored in the Texture Manager. + * + * In the default set-up you can access this from within a Scene via the `this.cache` property. + * + * @name Phaser.Scenes.Systems#cache + * @type {Phaser.Cache.CacheManager} + * @since 3.0.0 + */ + this.cache; + + /** + * A reference to the global Plugins Manager. + * + * In the default set-up you can access this from within a Scene via the `this.plugins` property. + * + * @name Phaser.Scenes.Systems#plugins + * @type {Phaser.Plugins.PluginManager} + * @since 3.0.0 + */ + this.plugins; + + /** + * A reference to the global registry. This is a game-wide instance of the Data Manager, allowing + * you to exchange data between Scenes via a universal and shared point. + * + * In the default set-up you can access this from within a Scene via the `this.registry` property. + * + * @name Phaser.Scenes.Systems#registry + * @type {Phaser.Data.DataManager} + * @since 3.0.0 + */ + this.registry; + + /** + * A reference to the global Scale Manager. + * + * In the default set-up you can access this from within a Scene via the `this.scale` property. + * + * @name Phaser.Scenes.Systems#scale + * @type {Phaser.Scale.ScaleManager} + * @since 3.15.0 + */ + this.scale; + + /** + * A reference to the global Sound Manager. + * + * In the default set-up you can access this from within a Scene via the `this.sound` property. + * + * @name Phaser.Scenes.Systems#sound + * @type {(Phaser.Sound.NoAudioSoundManager|Phaser.Sound.HTML5AudioSoundManager|Phaser.Sound.WebAudioSoundManager)} + * @since 3.0.0 + */ + this.sound; + + /** + * A reference to the global Texture Manager. + * + * In the default set-up you can access this from within a Scene via the `this.textures` property. + * + * @name Phaser.Scenes.Systems#textures + * @type {Phaser.Textures.TextureManager} + * @since 3.0.0 + */ + this.textures; + + // Core Plugins - these are non-optional Scene plugins, needed by lots of the other systems + + /** + * A reference to the Scene's Game Object Factory. + * + * Use this to quickly and easily create new Game Objects. + * + * In the default set-up you can access this from within a Scene via the `this.add` property. + * + * @name Phaser.Scenes.Systems#add + * @type {Phaser.GameObjects.GameObjectFactory} + * @since 3.0.0 + */ + this.add; + + /** + * A reference to the Scene's Camera Manager. + * + * Use this to manipulate and create Cameras for this specific Scene. + * + * In the default set-up you can access this from within a Scene via the `this.cameras` property. + * + * @name Phaser.Scenes.Systems#cameras + * @type {Phaser.Cameras.Scene2D.CameraManager} + * @since 3.0.0 + */ + this.cameras; + + /** + * A reference to the Scene's Display List. + * + * Use this to organize the children contained in the display list. + * + * In the default set-up you can access this from within a Scene via the `this.children` property. + * + * @name Phaser.Scenes.Systems#displayList + * @type {Phaser.GameObjects.DisplayList} + * @since 3.0.0 + */ + this.displayList; + + /** + * A reference to the Scene's Event Manager. + * + * Use this to listen for Scene specific events, such as `pause` and `shutdown`. + * + * In the default set-up you can access this from within a Scene via the `this.events` property. + * + * @name Phaser.Scenes.Systems#events + * @type {Phaser.Events.EventEmitter} + * @since 3.0.0 + */ + this.events; + + /** + * A reference to the Scene's Game Object Creator. + * + * Use this to quickly and easily create new Game Objects. The difference between this and the + * Game Object Factory, is that the Creator just creates and returns Game Object instances, it + * doesn't then add them to the Display List or Update List. + * + * In the default set-up you can access this from within a Scene via the `this.make` property. + * + * @name Phaser.Scenes.Systems#make + * @type {Phaser.GameObjects.GameObjectCreator} + * @since 3.0.0 + */ + this.make; + + /** + * A reference to the Scene Manager Plugin. + * + * Use this to manipulate both this and other Scenes in your game. For example, to launch a parallel Scene, + * or pause or resume a Scene, or switch from this Scene to another. + * + * In the default set-up you can access this from within a Scene via the `this.scene` property. + * + * @name Phaser.Scenes.Systems#scenePlugin + * @type {Phaser.Scenes.ScenePlugin} + * @since 3.0.0 + */ + this.scenePlugin; + + /** + * A reference to the Scene's Update List. + * + * Use this to organize the children contained in the update list. + * + * The Update List is responsible for managing children that need their `preUpdate` methods called, + * in order to process internal components - such as Sprites with Animations. + * + * In the default set-up there is no reference to this from within the Scene itself. + * + * @name Phaser.Scenes.Systems#updateList + * @type {Phaser.GameObjects.UpdateList} + * @since 3.0.0 + */ + this.updateList; + + /** + * The Scene Update function. + * + * This starts out as NOOP during init, preload and create, and at the end of create + * it swaps to be whatever the Scene.update function is. + * + * @name Phaser.Scenes.Systems#sceneUpdate + * @type {function} + * @private + * @since 3.10.0 + */ + this.sceneUpdate = NOOP; + }, + + /** + * This method is called only once by the Scene Manager when the Scene is instantiated. + * It is responsible for setting up all of the Scene plugins and references. + * It should never be called directly. + * + * @method Phaser.Scenes.Systems#init + * @protected + * @fires Phaser.Scenes.Events#BOOT + * @since 3.0.0 + * + * @param {Phaser.Game} game - A reference to the Phaser Game instance. + */ + init: function (game) + { + this.settings.status = CONST.INIT; + + // This will get replaced by the SceneManager with the actual update function, if it exists, once create is over. + this.sceneUpdate = NOOP; + + this.game = game; + this.renderer = game.renderer; + + this.canvas = game.canvas; + this.context = game.context; + + var pluginManager = game.plugins; + + this.plugins = pluginManager; + + pluginManager.addToScene(this, DefaultPlugins.Global, [ DefaultPlugins.CoreScene, GetScenePlugins(this), GetPhysicsPlugins(this) ]); + + this.events.emit(Events.BOOT, this); + + this.settings.isBooted = true; + }, + + /** + * A single game step. Called automatically by the Scene Manager as a result of a Request Animation + * Frame or Set Timeout call to the main Game instance. + * + * @method Phaser.Scenes.Systems#step + * @fires Phaser.Scenes.Events#PRE_UPDATE + * @fires Phaser.Scenes.Events#UPDATE + * @fires Phaser.Scenes.Events#POST_UPDATE + * @since 3.0.0 + * + * @param {number} time - The time value from the most recent Game step. Typically a high-resolution timer value, or Date.now(). + * @param {number} delta - The delta value since the last frame. This is smoothed to avoid delta spikes by the TimeStep class. + */ + step: function (time, delta) + { + var events = this.events; + + events.emit(Events.PRE_UPDATE, time, delta); + + events.emit(Events.UPDATE, time, delta); + + this.sceneUpdate.call(this.scene, time, delta); + + events.emit(Events.POST_UPDATE, time, delta); + }, + + /** + * Called automatically by the Scene Manager. + * Instructs the Scene to render itself via its Camera Manager to the renderer given. + * + * @method Phaser.Scenes.Systems#render + * @fires Phaser.Scenes.Events#PRE_RENDER + * @fires Phaser.Scenes.Events#RENDER + * @since 3.0.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The renderer that invoked the render call. + */ + render: function (renderer) + { + var displayList = this.displayList; + + displayList.depthSort(); + + this.events.emit(Events.PRE_RENDER, renderer); + + this.cameras.render(renderer, displayList); + + this.events.emit(Events.RENDER, renderer); + }, + + /** + * Force a sort of the display list on the next render. + * + * @method Phaser.Scenes.Systems#queueDepthSort + * @since 3.0.0 + */ + queueDepthSort: function () + { + this.displayList.queueDepthSort(); + }, + + /** + * Immediately sorts the display list if the flag is set. + * + * @method Phaser.Scenes.Systems#depthSort + * @since 3.0.0 + */ + depthSort: function () + { + this.displayList.depthSort(); + }, + + /** + * Pause this Scene. + * + * A paused Scene still renders, it just doesn't run any of its update handlers or systems. + * + * @method Phaser.Scenes.Systems#pause + * @fires Phaser.Scenes.Events#PAUSE + * @since 3.0.0 + * + * @param {object} [data] - A data object that will be passed in the 'pause' event. + * + * @return {Phaser.Scenes.Systems} This Systems object. + */ + pause: function (data) + { + var settings = this.settings; + var status = this.getStatus(); + + if (status !== CONST.CREATING && status !== CONST.RUNNING) + { + console.warn('Cannot pause non-running Scene', settings.key); + } + else if (this.settings.active) + { + settings.status = CONST.PAUSED; + + settings.active = false; + + this.events.emit(Events.PAUSE, this, data); + } + + return this; + }, + + /** + * Resume this Scene from a paused state. + * + * @method Phaser.Scenes.Systems#resume + * @fires Phaser.Scenes.Events#RESUME + * @since 3.0.0 + * + * @param {object} [data] - A data object that will be passed in the 'resume' event. + * + * @return {Phaser.Scenes.Systems} This Systems object. + */ + resume: function (data) + { + var events = this.events; + var settings = this.settings; + + if (!this.settings.active) + { + settings.status = CONST.RUNNING; + + settings.active = true; + + events.emit(Events.RESUME, this, data); + } + + return this; + }, + + /** + * Send this Scene to sleep. + * + * A sleeping Scene doesn't run its update step or render anything, but it also isn't shut down + * or has any of its systems or children removed, meaning it can be re-activated at any point and + * will carry on from where it left off. It also keeps everything in memory and events and callbacks + * from other Scenes may still invoke changes within it, so be careful what is left active. + * + * @method Phaser.Scenes.Systems#sleep + * @fires Phaser.Scenes.Events#SLEEP + * @since 3.0.0 + * + * @param {object} [data] - A data object that will be passed in the 'sleep' event. + * + * @return {Phaser.Scenes.Systems} This Systems object. + */ + sleep: function (data) + { + var settings = this.settings; + var status = this.getStatus(); + + if (status !== CONST.CREATING && status !== CONST.RUNNING) + { + console.warn('Cannot sleep non-running Scene', settings.key); + } + else + { + settings.status = CONST.SLEEPING; + + settings.active = false; + settings.visible = false; + + this.events.emit(Events.SLEEP, this, data); + } + + return this; + }, + + /** + * Wake-up this Scene if it was previously asleep. + * + * @method Phaser.Scenes.Systems#wake + * @fires Phaser.Scenes.Events#WAKE + * @since 3.0.0 + * + * @param {object} [data] - A data object that will be passed in the 'wake' event. + * + * @return {Phaser.Scenes.Systems} This Systems object. + */ + wake: function (data) + { + var events = this.events; + var settings = this.settings; + + settings.status = CONST.RUNNING; + + settings.active = true; + settings.visible = true; + + events.emit(Events.WAKE, this, data); + + if (settings.isTransition) + { + events.emit(Events.TRANSITION_WAKE, settings.transitionFrom, settings.transitionDuration); + } + + return this; + }, + + /** + * Returns any data that was sent to this Scene by another Scene. + * + * The data is also passed to `Scene.init` and in various Scene events, but + * you can access it at any point via this method. + * + * @method Phaser.Scenes.Systems#getData + * @since 3.22.0 + * + * @return {any} The Scene Data. + */ + getData: function () + { + return this.settings.data; + }, + + /** + * Returns the current status of this Scene. + * + * @method Phaser.Scenes.Systems#getStatus + * @since 3.60.0 + * + * @return {number} The status of this Scene. One of the `Phaser.Scene` constants. + */ + getStatus: function () + { + return this.settings.status; + }, + + /** + * Can this Scene receive Input events? + * + * @method Phaser.Scenes.Systems#canInput + * @since 3.60.0 + * + * @return {boolean} `true` if this Scene can receive Input events. + */ + canInput: function () + { + var status = this.settings.status; + + return (status > CONST.PENDING && status <= CONST.RUNNING); + }, + + /** + * Is this Scene sleeping? + * + * @method Phaser.Scenes.Systems#isSleeping + * @since 3.0.0 + * + * @return {boolean} `true` if this Scene is asleep, otherwise `false`. + */ + isSleeping: function () + { + return (this.settings.status === CONST.SLEEPING); + }, + + /** + * Is this Scene running? + * + * @method Phaser.Scenes.Systems#isActive + * @since 3.0.0 + * + * @return {boolean} `true` if this Scene is running, otherwise `false`. + */ + isActive: function () + { + return (this.settings.status === CONST.RUNNING); + }, + + /** + * Is this Scene paused? + * + * @method Phaser.Scenes.Systems#isPaused + * @since 3.13.0 + * + * @return {boolean} `true` if this Scene is paused, otherwise `false`. + */ + isPaused: function () + { + return (this.settings.status === CONST.PAUSED); + }, + + /** + * Is this Scene currently transitioning out to, or in from another Scene? + * + * @method Phaser.Scenes.Systems#isTransitioning + * @since 3.5.0 + * + * @return {boolean} `true` if this Scene is currently transitioning, otherwise `false`. + */ + isTransitioning: function () + { + return (this.settings.isTransition || this.scenePlugin._target !== null); + }, + + /** + * Is this Scene currently transitioning out from itself to another Scene? + * + * @method Phaser.Scenes.Systems#isTransitionOut + * @since 3.5.0 + * + * @return {boolean} `true` if this Scene is in transition to another Scene, otherwise `false`. + */ + isTransitionOut: function () + { + return (this.scenePlugin._target !== null && this.scenePlugin._duration > 0); + }, + + /** + * Is this Scene currently transitioning in from another Scene? + * + * @method Phaser.Scenes.Systems#isTransitionIn + * @since 3.5.0 + * + * @return {boolean} `true` if this Scene is transitioning in from another Scene, otherwise `false`. + */ + isTransitionIn: function () + { + return (this.settings.isTransition); + }, + + /** + * Is this Scene visible and rendering? + * + * @method Phaser.Scenes.Systems#isVisible + * @since 3.0.0 + * + * @return {boolean} `true` if this Scene is visible, otherwise `false`. + */ + isVisible: function () + { + return this.settings.visible; + }, + + /** + * Sets the visible state of this Scene. + * An invisible Scene will not render, but will still process updates. + * + * @method Phaser.Scenes.Systems#setVisible + * @since 3.0.0 + * + * @param {boolean} value - `true` to render this Scene, otherwise `false`. + * + * @return {Phaser.Scenes.Systems} This Systems object. + */ + setVisible: function (value) + { + this.settings.visible = value; + + return this; + }, + + /** + * Set the active state of this Scene. + * + * An active Scene will run its core update loop. + * + * @method Phaser.Scenes.Systems#setActive + * @since 3.0.0 + * + * @param {boolean} value - If `true` the Scene will be resumed, if previously paused. If `false` it will be paused. + * @param {object} [data] - A data object that will be passed in the 'resume' or 'pause' events. + * + * @return {Phaser.Scenes.Systems} This Systems object. + */ + setActive: function (value, data) + { + if (value) + { + return this.resume(data); + } + else + { + return this.pause(data); + } + }, + + /** + * Start this Scene running and rendering. + * Called automatically by the SceneManager. + * + * @method Phaser.Scenes.Systems#start + * @fires Phaser.Scenes.Events#START + * @fires Phaser.Scenes.Events#READY + * @since 3.0.0 + * + * @param {object} data - Optional data object that may have been passed to this Scene from another. + */ + start: function (data) + { + var events = this.events; + var settings = this.settings; + + if (data) + { + settings.data = data; + } + + settings.status = CONST.START; + + settings.active = true; + settings.visible = true; + + // For plugins to listen out for + events.emit(Events.START, this); + + // For user-land code to listen out for + events.emit(Events.READY, this, data); + }, + + /** + * Shutdown this Scene and send a shutdown event to all of its systems. + * A Scene that has been shutdown will not run its update loop or render, but it does + * not destroy any of its plugins or references. It is put into hibernation for later use. + * If you don't ever plan to use this Scene again, then it should be destroyed instead + * to free-up resources. + * + * @method Phaser.Scenes.Systems#shutdown + * @fires Phaser.Scenes.Events#SHUTDOWN + * @since 3.0.0 + * + * @param {object} [data] - A data object that will be passed in the 'shutdown' event. + */ + shutdown: function (data) + { + var events = this.events; + var settings = this.settings; + + events.off(Events.TRANSITION_INIT); + events.off(Events.TRANSITION_START); + events.off(Events.TRANSITION_COMPLETE); + events.off(Events.TRANSITION_OUT); + + settings.status = CONST.SHUTDOWN; + + settings.active = false; + settings.visible = false; + + events.emit(Events.SHUTDOWN, this, data); + }, + + /** + * Destroy this Scene and send a destroy event to all of its systems. + * A destroyed Scene cannot be restarted. + * You should not call this directly, instead use `SceneManager.remove`. + * + * @method Phaser.Scenes.Systems#destroy + * @private + * @fires Phaser.Scenes.Events#DESTROY + * @since 3.0.0 + */ + destroy: function () + { + var events = this.events; + var settings = this.settings; + + settings.status = CONST.DESTROYED; + + settings.active = false; + settings.visible = false; + + events.emit(Events.DESTROY, this); + + events.removeAllListeners(); + + var props = [ 'scene', 'game', 'anims', 'cache', 'plugins', 'registry', 'sound', 'textures', 'add', 'camera', 'displayList', 'events', 'make', 'scenePlugin', 'updateList' ]; + + for (var i = 0; i < props.length; i++) + { + this[props[i]] = null; + } + } + +}); + +module.exports = Systems; + + +/***/ }), + +/***/ 89993: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Scene consts. + * + * @ignore + */ + +var CONST = { + + /** + * Scene state. + * + * @name Phaser.Scenes.PENDING + * @readonly + * @type {number} + * @since 3.0.0 + */ + PENDING: 0, + + /** + * Scene state. + * + * @name Phaser.Scenes.INIT + * @readonly + * @type {number} + * @since 3.0.0 + */ + INIT: 1, + + /** + * Scene state. + * + * @name Phaser.Scenes.START + * @readonly + * @type {number} + * @since 3.0.0 + */ + START: 2, + + /** + * Scene state. + * + * @name Phaser.Scenes.LOADING + * @readonly + * @type {number} + * @since 3.0.0 + */ + LOADING: 3, + + /** + * Scene state. + * + * @name Phaser.Scenes.CREATING + * @readonly + * @type {number} + * @since 3.0.0 + */ + CREATING: 4, + + /** + * Scene state. + * + * @name Phaser.Scenes.RUNNING + * @readonly + * @type {number} + * @since 3.0.0 + */ + RUNNING: 5, + + /** + * Scene state. + * + * @name Phaser.Scenes.PAUSED + * @readonly + * @type {number} + * @since 3.0.0 + */ + PAUSED: 6, + + /** + * Scene state. + * + * @name Phaser.Scenes.SLEEPING + * @readonly + * @type {number} + * @since 3.0.0 + */ + SLEEPING: 7, + + /** + * Scene state. + * + * @name Phaser.Scenes.SHUTDOWN + * @readonly + * @type {number} + * @since 3.0.0 + */ + SHUTDOWN: 8, + + /** + * Scene state. + * + * @name Phaser.Scenes.DESTROYED + * @readonly + * @type {number} + * @since 3.0.0 + */ + DESTROYED: 9 + +}; + +module.exports = CONST; + + +/***/ }), + +/***/ 69830: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Added to Scene Event. + * + * This event is dispatched when a Game Object is added to a Scene. + * + * Listen for it from a Scene using `this.events.on('addedtoscene', listener)`. + * + * @event Phaser.Scenes.Events#ADDED_TO_SCENE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the Scene. + * @param {Phaser.Scene} scene - The Scene to which the Game Object was added. + */ +module.exports = 'addedtoscene'; + + +/***/ }), + +/***/ 7919: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Boot Event. + * + * This event is dispatched by a Scene during the Scene Systems boot process. Primarily used by Scene Plugins. + * + * Listen to it from a Scene using `this.events.on('boot', listener)`. + * + * @event Phaser.Scenes.Events#BOOT + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + */ +module.exports = 'boot'; + + +/***/ }), + +/***/ 46763: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Create Event. + * + * This event is dispatched by a Scene after it has been created by the Scene Manager. + * + * If a Scene has a `create` method then this event is emitted _after_ that has run. + * + * If there is a transition, this event will be fired after the `TRANSITION_START` event. + * + * Listen to it from a Scene using `this.events.on('create', listener)`. + * + * @event Phaser.Scenes.Events#CREATE + * @type {string} + * @since 3.17.0 + * + * @param {Phaser.Scene} scene - A reference to the Scene that emitted this event. + */ +module.exports = 'create'; + + +/***/ }), + +/***/ 11763: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Destroy Event. + * + * This event is dispatched by a Scene during the Scene Systems destroy process. + * + * Listen to it from a Scene using `this.events.on('destroy', listener)`. + * + * You should destroy any resources that may be in use by your Scene in this event handler. + * + * @event Phaser.Scenes.Events#DESTROY + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + */ +module.exports = 'destroy'; + + +/***/ }), + +/***/ 71555: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Pause Event. + * + * This event is dispatched by a Scene when it is paused, either directly via the `pause` method, or as an + * action from another Scene. + * + * Listen to it from a Scene using `this.events.on('pause', listener)`. + * + * @event Phaser.Scenes.Events#PAUSE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + * @param {any} [data] - An optional data object that was passed to this Scene when it was paused. + */ +module.exports = 'pause'; + + +/***/ }), + +/***/ 36735: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Post Update Event. + * + * This event is dispatched by a Scene during the main game loop step. + * + * The event flow for a single step of a Scene is as follows: + * + * 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE} + * 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE} + * 3. The `Scene.update` method is called, if it exists + * 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE} + * 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER} + * 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER} + * + * Listen to it from a Scene using `this.events.on('postupdate', listener)`. + * + * A Scene will only run its step if it is active. + * + * @event Phaser.Scenes.Events#POST_UPDATE + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'postupdate'; + + +/***/ }), + +/***/ 3809: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2021 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Pre-Render Event. + * + * This event is dispatched by a Scene during the main game loop step. + * + * The event flow for a single step of a Scene is as follows: + * + * 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE} + * 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE} + * 3. The `Scene.update` method is called, if it exists + * 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE} + * 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER} + * 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER} + * + * Listen to this event from a Scene using `this.events.on('prerender', listener)`. + * + * A Scene will only render if it is visible. + * + * This event is dispatched after the Scene Display List is sorted and before the Scene is rendered. + * + * @event Phaser.Scenes.Events#PRE_RENDER + * @type {string} + * @since 3.53.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The renderer that rendered the Scene. + */ +module.exports = 'prerender'; + + +/***/ }), + +/***/ 90716: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Pre Update Event. + * + * This event is dispatched by a Scene during the main game loop step. + * + * The event flow for a single step of a Scene is as follows: + * + * 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE} + * 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE} + * 3. The `Scene.update` method is called, if it exists + * 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE} + * 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER} + * 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER} + * + * Listen to it from a Scene using `this.events.on('preupdate', listener)`. + * + * A Scene will only run its step if it is active. + * + * @event Phaser.Scenes.Events#PRE_UPDATE + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'preupdate'; + + +/***/ }), + +/***/ 58262: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Ready Event. + * + * This event is dispatched by a Scene during the Scene Systems start process. + * By this point in the process the Scene is now fully active and rendering. + * This event is meant for your game code to use, as all plugins have responded to the earlier 'start' event. + * + * Listen to it from a Scene using `this.events.on('ready', listener)`. + * + * @event Phaser.Scenes.Events#READY + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + * @param {any} [data] - An optional data object that was passed to this Scene when it was started. + */ +module.exports = 'ready'; + + +/***/ }), + +/***/ 91633: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Game Object Removed from Scene Event. + * + * This event is dispatched when a Game Object is removed from a Scene. + * + * Listen for it from a Scene using `this.events.on('removedfromscene', listener)`. + * + * @event Phaser.Scenes.Events#REMOVED_FROM_SCENE + * @type {string} + * @since 3.50.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the Scene. + * @param {Phaser.Scene} scene - The Scene from which the Game Object was removed. + */ +module.exports = 'removedfromscene'; + + +/***/ }), + +/***/ 10319: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Render Event. + * + * This event is dispatched by a Scene during the main game loop step. + * + * The event flow for a single step of a Scene is as follows: + * + * 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE} + * 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE} + * 3. The `Scene.update` method is called, if it exists + * 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE} + * 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER} + * 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER} + * + * Listen to it from a Scene using `this.events.on('render', listener)`. + * + * A Scene will only render if it is visible. + * + * By the time this event is dispatched, the Scene will have already been rendered. + * + * @event Phaser.Scenes.Events#RENDER + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The renderer that rendered the Scene. + */ +module.exports = 'render'; + + +/***/ }), + +/***/ 87132: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Resume Event. + * + * This event is dispatched by a Scene when it is resumed from a paused state, either directly via the `resume` method, + * or as an action from another Scene. + * + * Listen to it from a Scene using `this.events.on('resume', listener)`. + * + * @event Phaser.Scenes.Events#RESUME + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + * @param {any} [data] - An optional data object that was passed to this Scene when it was resumed. + */ +module.exports = 'resume'; + + +/***/ }), + +/***/ 81961: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Shutdown Event. + * + * This event is dispatched by a Scene during the Scene Systems shutdown process. + * + * Listen to it from a Scene using `this.events.on('shutdown', listener)`. + * + * You should free-up any resources that may be in use by your Scene in this event handler, on the understanding + * that the Scene may, at any time, become active again. A shutdown Scene is not 'destroyed', it's simply not + * currently active. Use the [DESTROY]{@linkcode Phaser.Scenes.Events#event:DESTROY} event to completely clear resources. + * + * @event Phaser.Scenes.Events#SHUTDOWN + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + * @param {any} [data] - An optional data object that was passed to this Scene when it was shutdown. + */ +module.exports = 'shutdown'; + + +/***/ }), + +/***/ 90194: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Sleep Event. + * + * This event is dispatched by a Scene when it is sent to sleep, either directly via the `sleep` method, + * or as an action from another Scene. + * + * Listen to it from a Scene using `this.events.on('sleep', listener)`. + * + * @event Phaser.Scenes.Events#SLEEP + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + * @param {any} [data] - An optional data object that was passed to this Scene when it was sent to sleep. + */ +module.exports = 'sleep'; + + +/***/ }), + +/***/ 6265: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Start Event. + * + * This event is dispatched by a Scene during the Scene Systems start process. Primarily used by Scene Plugins. + * + * Listen to it from a Scene using `this.events.on('start', listener)`. + * + * @event Phaser.Scenes.Events#START + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + */ +module.exports = 'start'; + + +/***/ }), + +/***/ 33178: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Transition Complete Event. + * + * This event is dispatched by the Target Scene of a transition. + * + * It happens when the transition process has completed. This occurs when the duration timer equals or exceeds the duration + * of the transition. + * + * Listen to it from a Scene using `this.events.on('transitioncomplete', listener)`. + * + * The Scene Transition event flow is as follows: + * + * 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event. + * 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method. + * 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ... + * 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to. + * 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes. + * + * @event Phaser.Scenes.Events#TRANSITION_COMPLETE + * @type {string} + * @since 3.5.0 + * + * @param {Phaser.Scene} scene -The Scene on which the transitioned completed. + */ +module.exports = 'transitioncomplete'; + + +/***/ }), + +/***/ 43063: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Transition Init Event. + * + * This event is dispatched by the Target Scene of a transition. + * + * It happens immediately after the `Scene.init` method is called. If the Scene does not have an `init` method, + * this event is not dispatched. + * + * Listen to it from a Scene using `this.events.on('transitioninit', listener)`. + * + * The Scene Transition event flow is as follows: + * + * 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event. + * 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method. + * 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ... + * 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to. + * 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes. + * + * @event Phaser.Scenes.Events#TRANSITION_INIT + * @type {string} + * @since 3.5.0 + * + * @param {Phaser.Scene} from - A reference to the Scene that is being transitioned from. + * @param {number} duration - The duration of the transition in ms. + */ +module.exports = 'transitioninit'; + + +/***/ }), + +/***/ 11259: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Transition Out Event. + * + * This event is dispatched by a Scene when it initiates a transition to another Scene. + * + * Listen to it from a Scene using `this.events.on('transitionout', listener)`. + * + * The Scene Transition event flow is as follows: + * + * 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event. + * 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method. + * 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ... + * 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to. + * 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes. + * + * @event Phaser.Scenes.Events#TRANSITION_OUT + * @type {string} + * @since 3.5.0 + * + * @param {Phaser.Scene} target - A reference to the Scene that is being transitioned to. + * @param {number} duration - The duration of the transition in ms. + */ +module.exports = 'transitionout'; + + +/***/ }), + +/***/ 61611: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Transition Start Event. + * + * This event is dispatched by the Target Scene of a transition, only if that Scene was not asleep. + * + * It happens immediately after the `Scene.create` method is called. If the Scene does not have a `create` method, + * this event is dispatched anyway. + * + * If the Target Scene was sleeping then the [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} event is + * dispatched instead of this event. + * + * Listen to it from a Scene using `this.events.on('transitionstart', listener)`. + * + * The Scene Transition event flow is as follows: + * + * 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event. + * 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method. + * 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ... + * 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to. + * 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes. + * + * @event Phaser.Scenes.Events#TRANSITION_START + * @type {string} + * @since 3.5.0 + * + * @param {Phaser.Scene} from - A reference to the Scene that is being transitioned from. + * @param {number} duration - The duration of the transition in ms. + */ +module.exports = 'transitionstart'; + + +/***/ }), + +/***/ 45209: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Transition Wake Event. + * + * This event is dispatched by the Target Scene of a transition, only if that Scene was asleep before + * the transition began. If the Scene was not asleep the [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} event is dispatched instead. + * + * Listen to it from a Scene using `this.events.on('transitionwake', listener)`. + * + * The Scene Transition event flow is as follows: + * + * 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event. + * 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method. + * 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ... + * 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to. + * 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes. + * + * @event Phaser.Scenes.Events#TRANSITION_WAKE + * @type {string} + * @since 3.5.0 + * + * @param {Phaser.Scene} from - A reference to the Scene that is being transitioned from. + * @param {number} duration - The duration of the transition in ms. + */ +module.exports = 'transitionwake'; + + +/***/ }), + +/***/ 22966: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Update Event. + * + * This event is dispatched by a Scene during the main game loop step. + * + * The event flow for a single step of a Scene is as follows: + * + * 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE} + * 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE} + * 3. The `Scene.update` method is called, if it exists and the Scene is in a Running state, otherwise this is skipped. + * 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE} + * 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER} + * 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER} + * + * Listen to it from a Scene using `this.events.on('update', listener)`. + * + * A Scene will only run its step if it is active. + * + * @event Phaser.Scenes.Events#UPDATE + * @type {string} + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ +module.exports = 'update'; + + +/***/ }), + +/***/ 21747: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Scene Systems Wake Event. + * + * This event is dispatched by a Scene when it is woken from sleep, either directly via the `wake` method, + * or as an action from another Scene. + * + * Listen to it from a Scene using `this.events.on('wake', listener)`. + * + * @event Phaser.Scenes.Events#WAKE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event. + * @param {any} [data] - An optional data object that was passed to this Scene when it was woken up. + */ +module.exports = 'wake'; + + +/***/ }), + +/***/ 44594: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Scenes.Events + */ + +module.exports = { + + ADDED_TO_SCENE: __webpack_require__(69830), + BOOT: __webpack_require__(7919), + CREATE: __webpack_require__(46763), + DESTROY: __webpack_require__(11763), + PAUSE: __webpack_require__(71555), + POST_UPDATE: __webpack_require__(36735), + PRE_RENDER: __webpack_require__(3809), + PRE_UPDATE: __webpack_require__(90716), + READY: __webpack_require__(58262), + REMOVED_FROM_SCENE: __webpack_require__(91633), + RENDER: __webpack_require__(10319), + RESUME: __webpack_require__(87132), + SHUTDOWN: __webpack_require__(81961), + SLEEP: __webpack_require__(90194), + START: __webpack_require__(6265), + TRANSITION_COMPLETE: __webpack_require__(33178), + TRANSITION_INIT: __webpack_require__(43063), + TRANSITION_OUT: __webpack_require__(11259), + TRANSITION_START: __webpack_require__(61611), + TRANSITION_WAKE: __webpack_require__(45209), + UPDATE: __webpack_require__(22966), + WAKE: __webpack_require__(21747) + +}; + + +/***/ }), + +/***/ 62194: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(89993); +var Extend = __webpack_require__(79291); + +/** + * @namespace Phaser.Scenes + */ + +var Scene = { + + Events: __webpack_require__(44594), + GetPhysicsPlugins: __webpack_require__(27397), + GetScenePlugins: __webpack_require__(52106), + SceneManager: __webpack_require__(60903), + ScenePlugin: __webpack_require__(52209), + Settings: __webpack_require__(55681), + Systems: __webpack_require__(2368) + +}; + +// Merge in the consts +Scene = Extend(false, Scene, CONST); + +module.exports = Scene; + + +/***/ }), + +/***/ 30341: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(14463); +var Extend = __webpack_require__(79291); +var NOOP = __webpack_require__(29747); + +/** + * @classdesc + * Class containing all the shared state and behavior of a sound object, independent of the implementation. + * + * @class BaseSound + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} manager - Reference to the current sound manager instance. + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + */ +var BaseSound = new Class({ + + Extends: EventEmitter, + + initialize: + + function BaseSound (manager, key, config) + { + EventEmitter.call(this); + + /** + * Local reference to the sound manager. + * + * @name Phaser.Sound.BaseSound#manager + * @type {Phaser.Sound.BaseSoundManager} + * @since 3.0.0 + */ + this.manager = manager; + + /** + * Asset key for the sound. + * + * @name Phaser.Sound.BaseSound#key + * @type {string} + * @readonly + * @since 3.0.0 + */ + this.key = key; + + /** + * Flag indicating if sound is currently playing. + * + * @name Phaser.Sound.BaseSound#isPlaying + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isPlaying = false; + + /** + * Flag indicating if sound is currently paused. + * + * @name Phaser.Sound.BaseSound#isPaused + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isPaused = false; + + /** + * A property that holds the value of sound's actual playback rate, + * after its rate and detune values has been combined with global + * rate and detune values. + * + * @name Phaser.Sound.BaseSound#totalRate + * @type {number} + * @default 1 + * @readonly + * @since 3.0.0 + */ + this.totalRate = 1; + + /** + * A value representing the duration, in seconds. + * It could be total sound duration or a marker duration. + * + * @name Phaser.Sound.BaseSound#duration + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.duration = this.duration || 0; + + /** + * The total duration of the sound in seconds. + * + * @name Phaser.Sound.BaseSound#totalDuration + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.totalDuration = this.totalDuration || 0; + + /** + * A config object used to store default sound settings' values. + * Default values will be set by properties' setters. + * + * @name Phaser.Sound.BaseSound#config + * @type {Phaser.Types.Sound.SoundConfig} + * @private + * @since 3.0.0 + */ + this.config = { + + mute: false, + volume: 1, + rate: 1, + detune: 0, + seek: 0, + loop: false, + delay: 0, + pan: 0 + + }; + + /** + * Reference to the currently used config. + * It could be default config or marker config. + * + * @name Phaser.Sound.BaseSound#currentConfig + * @type {Phaser.Types.Sound.SoundConfig} + * @private + * @since 3.0.0 + */ + this.currentConfig = this.config; + + this.config = Extend(this.config, config); + + /** + * Object containing markers definitions. + * + * @name Phaser.Sound.BaseSound#markers + * @type {Object.} + * @default {} + * @readonly + * @since 3.0.0 + */ + this.markers = {}; + + /** + * Currently playing marker. + * 'null' if whole sound is playing. + * + * @name Phaser.Sound.BaseSound#currentMarker + * @type {Phaser.Types.Sound.SoundMarker} + * @default null + * @readonly + * @since 3.0.0 + */ + this.currentMarker = null; + + /** + * Flag indicating if destroy method was called on this sound. + * + * @name Phaser.Sound.BaseSound#pendingRemove + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.pendingRemove = false; + }, + + /** + * Adds a marker into the current sound. A marker is represented by name, start time, duration, and optionally config object. + * This allows you to bundle multiple sounds together into a single audio file and use markers to jump between them for playback. + * + * @method Phaser.Sound.BaseSound#addMarker + * @since 3.0.0 + * + * @param {Phaser.Types.Sound.SoundMarker} marker - Marker object. + * + * @return {boolean} Whether the marker was added successfully. + */ + addMarker: function (marker) + { + if (!marker || !marker.name || typeof marker.name !== 'string') + { + return false; + } + + if (this.markers[marker.name]) + { + // eslint-disable-next-line no-console + console.error('addMarker ' + marker.name + ' already exists in Sound'); + + return false; + } + + marker = Extend(true, { + name: '', + start: 0, + duration: this.totalDuration - (marker.start || 0), + config: { + mute: false, + volume: 1, + rate: 1, + detune: 0, + seek: 0, + loop: false, + delay: 0, + pan: 0 + } + }, marker); + + this.markers[marker.name] = marker; + + return true; + }, + + /** + * Updates previously added marker. + * + * @method Phaser.Sound.BaseSound#updateMarker + * @since 3.0.0 + * + * @param {Phaser.Types.Sound.SoundMarker} marker - Marker object with updated values. + * + * @return {boolean} Whether the marker was updated successfully. + */ + updateMarker: function (marker) + { + if (!marker || !marker.name || typeof marker.name !== 'string') + { + return false; + } + + if (!this.markers[marker.name]) + { + // eslint-disable-next-line no-console + console.warn('Audio Marker: ' + marker.name + ' missing in Sound: ' + this.key); + + return false; + } + + this.markers[marker.name] = Extend(true, this.markers[marker.name], marker); + + return true; + }, + + /** + * Removes a marker from the sound. + * + * @method Phaser.Sound.BaseSound#removeMarker + * @since 3.0.0 + * + * @param {string} markerName - The name of the marker to remove. + * + * @return {?Phaser.Types.Sound.SoundMarker} Removed marker object or 'null' if there was no marker with provided name. + */ + removeMarker: function (markerName) + { + var marker = this.markers[markerName]; + + if (!marker) + { + return null; + } + + this.markers[markerName] = null; + + return marker; + }, + + /** + * Play this sound, or a marked section of it. + * + * It always plays the sound from the start. If you want to start playback from a specific time + * you can set 'seek' setting of the config object, provided to this call, to that value. + * + * @method Phaser.Sound.BaseSound#play + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Sound.SoundConfig)} [markerName=''] - If you want to play a marker then provide the marker name here. Alternatively, this parameter can be a SoundConfig object. + * @param {Phaser.Types.Sound.SoundConfig} [config] - Optional sound config object to be applied to this marker or entire sound if no marker name is provided. It gets memorized for future plays of current section of the sound. + * + * @return {boolean} Whether the sound started playing successfully. + */ + play: function (markerName, config) + { + if (markerName === undefined) { markerName = ''; } + + if (typeof markerName === 'object') + { + config = markerName; + markerName = ''; + } + + if (typeof markerName !== 'string') + { + return false; + } + + if (!markerName) + { + this.currentMarker = null; + this.currentConfig = this.config; + this.duration = this.totalDuration; + } + else + { + if (!this.markers[markerName]) + { + // eslint-disable-next-line no-console + console.warn('Marker: ' + markerName + ' missing in Sound: ' + this.key); + + return false; + } + + this.currentMarker = this.markers[markerName]; + this.currentConfig = this.currentMarker.config; + this.duration = this.currentMarker.duration; + } + + this.resetConfig(); + + this.currentConfig = Extend(this.currentConfig, config); + + this.isPlaying = true; + this.isPaused = false; + + return true; + }, + + /** + * Pauses the sound. This only works if the sound is currently playing. + * + * You can inspect the `isPlaying` and `isPaused` properties to check the state. + * + * @method Phaser.Sound.BaseSound#pause + * @since 3.0.0 + * + * @return {boolean} Whether the sound was paused successfully. + */ + pause: function () + { + if (this.isPaused || !this.isPlaying) + { + return false; + } + + this.isPlaying = false; + this.isPaused = true; + + return true; + }, + + /** + * Resumes the sound. This only works if the sound is paused and not already playing. + * + * You can inspect the `isPlaying` and `isPaused` properties to check the state. + * + * @method Phaser.Sound.BaseSound#resume + * @since 3.0.0 + * + * @return {boolean} Whether the sound was resumed successfully. + */ + resume: function () + { + if (!this.isPaused || this.isPlaying) + { + return false; + } + + this.isPlaying = true; + this.isPaused = false; + + return true; + }, + + /** + * Stop playing this sound. + * + * @method Phaser.Sound.BaseSound#stop + * @since 3.0.0 + * + * @return {boolean} Whether the sound was stopped successfully. + */ + stop: function () + { + if (!this.isPaused && !this.isPlaying) + { + return false; + } + + this.isPlaying = false; + this.isPaused = false; + + this.resetConfig(); + + return true; + }, + + /** + * Method used internally for applying config values to some of the sound properties. + * + * @method Phaser.Sound.BaseSound#applyConfig + * @since 3.0.0 + */ + applyConfig: function () + { + this.mute = this.currentConfig.mute; + this.volume = this.currentConfig.volume; + this.rate = this.currentConfig.rate; + this.detune = this.currentConfig.detune; + this.loop = this.currentConfig.loop; + this.pan = this.currentConfig.pan; + }, + + /** + * Method used internally for resetting values of some of the config properties. + * + * @method Phaser.Sound.BaseSound#resetConfig + * @since 3.0.0 + */ + resetConfig: function () + { + this.currentConfig.seek = 0; + this.currentConfig.delay = 0; + }, + + /** + * Update method called automatically by sound manager on every game step. + * + * @method Phaser.Sound.BaseSound#update + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time elapsed since the last frame. + */ + update: NOOP, + + /** + * Method used internally to calculate total playback rate of the sound. + * + * @method Phaser.Sound.BaseSound#calculateRate + * @since 3.0.0 + */ + calculateRate: function () + { + var cent = 1.0005777895065548; // Math.pow(2, 1/1200); + var totalDetune = this.currentConfig.detune + this.manager.detune; + var detuneRate = Math.pow(cent, totalDetune); + + this.totalRate = this.currentConfig.rate * this.manager.rate * detuneRate; + }, + + /** + * Destroys this sound and all associated events and marks it for removal from the sound manager. + * + * @method Phaser.Sound.BaseSound#destroy + * @fires Phaser.Sound.Events#DESTROY + * @since 3.0.0 + */ + destroy: function () + { + if (this.pendingRemove) + { + return; + } + + this.stop(); + + this.emit(Events.DESTROY, this); + + this.removeAllListeners(); + + this.pendingRemove = true; + + this.manager = null; + this.config = null; + this.currentConfig = null; + this.markers = null; + this.currentMarker = null; + } + +}); + +module.exports = BaseSound; + + +/***/ }), + +/***/ 85034: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Clone = __webpack_require__(41786); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(14463); +var GameEvents = __webpack_require__(8443); +var GetAll = __webpack_require__(46710); +var GetFirst = __webpack_require__(58731); +var NOOP = __webpack_require__(29747); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * Base class for other Sound Manager classes. + * + * @class BaseSoundManager + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - Reference to the current game instance. + * + * @see Phaser.Sound.HTML5AudioSoundManager + * @see Phaser.Sound.NoAudioSoundManager + * @see Phaser.Sound.WebAudioSoundManager + */ +var BaseSoundManager = new Class({ + + Extends: EventEmitter, + + initialize: + + function BaseSoundManager (game) + { + EventEmitter.call(this); + + /** + * Local reference to game. + * + * @name Phaser.Sound.BaseSoundManager#game + * @type {Phaser.Game} + * @readonly + * @since 3.0.0 + */ + this.game = game; + + /** + * Local reference to the JSON Cache, as used by Audio Sprites. + * + * @name Phaser.Sound.BaseSoundManager#jsonCache + * @type {Phaser.Cache.BaseCache} + * @readonly + * @since 3.7.0 + */ + this.jsonCache = game.cache.json; + + /** + * An array containing all added sounds. + * + * @name Phaser.Sound.BaseSoundManager#sounds + * @type {Phaser.Sound.BaseSound[]} + * @default [] + * @private + * @since 3.0.0 + */ + this.sounds = []; + + /** + * Global mute setting. + * + * @name Phaser.Sound.BaseSoundManager#mute + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.mute = false; + + /** + * Global volume setting. + * + * @name Phaser.Sound.BaseSoundManager#volume + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.volume = 1; + + /** + * Flag indicating if sounds should be paused when game looses focus, + * for instance when user switches to another tab/program/app. + * + * @name Phaser.Sound.BaseSoundManager#pauseOnBlur + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.pauseOnBlur = true; + + /** + * Property that actually holds the value of global playback rate. + * + * @name Phaser.Sound.BaseSoundManager#_rate + * @type {number} + * @private + * @default 1 + * @since 3.0.0 + */ + this._rate = 1; + + /** + * Property that actually holds the value of global detune. + * + * @name Phaser.Sound.BaseSoundManager#_detune + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._detune = 0; + + /** + * Mobile devices require sounds to be triggered from an explicit user action, + * such as a tap, before any sound can be loaded/played on a web page. + * Set to true if the audio system is currently locked awaiting user interaction. + * + * @name Phaser.Sound.BaseSoundManager#locked + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + this.locked = this.locked || false; + + /** + * Flag used internally for handling when the audio system + * has been unlocked, if there ever was a need for it. + * + * @name Phaser.Sound.BaseSoundManager#unlocked + * @type {boolean} + * @default false + * @private + * @since 3.0.0 + */ + this.unlocked = false; + + /** + * Flag used to track if the game has lost focus. + * + * @name Phaser.Sound.BaseSoundManager#gameLostFocus + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.gameLostFocus = false; + + /** + * The Spatial Audio listener position. + * + * Only available with WebAudio. + * + * You can modify the x/y properties of this Vec2 directly to + * adjust the listener position within the game world. + * + * @name Phaser.Sound.BaseSoundManager#listenerPosition + * @type {Phaser.Math.Vector2} + * @since 3.60.0 + */ + this.listenerPosition = new Vector2(); + + var ee = game.events; + + ee.on(GameEvents.BLUR, this.onGameBlur, this); + ee.on(GameEvents.FOCUS, this.onGameFocus, this); + ee.on(GameEvents.PRE_STEP, this.update, this); + ee.once(GameEvents.DESTROY, this.destroy, this); + }, + + /** + * Adds a new sound into the sound manager. + * + * @method Phaser.Sound.BaseSoundManager#add + * @override + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {Phaser.Sound.BaseSound} The new sound instance. + */ + add: NOOP, + + /** + * Adds a new audio sprite sound into the sound manager. + * Audio Sprites are a combination of audio files and a JSON configuration. + * The JSON follows the format of that created by https://github.com/tonistiigi/audiosprite + * + * @method Phaser.Sound.BaseSoundManager#addAudioSprite + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {(Phaser.Sound.NoAudioSound|Phaser.Sound.HTML5AudioSound|Phaser.Sound.WebAudioSound)} The new audio sprite sound instance. + */ + addAudioSprite: function (key, config) + { + if (config === undefined) { config = {}; } + + var sound = this.add(key, config); + + sound.spritemap = this.jsonCache.get(key).spritemap; + + for (var markerName in sound.spritemap) + { + if (!sound.spritemap.hasOwnProperty(markerName)) + { + continue; + } + + var markerConfig = Clone(config); + + var marker = sound.spritemap[markerName]; + + markerConfig.loop = (marker.hasOwnProperty('loop')) ? marker.loop : false; + + sound.addMarker({ + name: markerName, + start: marker.start, + duration: marker.end - marker.start, + config: markerConfig + }); + } + + return sound; + }, + + /** + * Gets the first sound in this Sound Manager that matches the given key. + * If none can be found it returns `null`. + * + * @method Phaser.Sound.BaseSoundManager#get + * @since 3.23.0 + * + * @generic {Phaser.Sound.BaseSound} T + * @genericUse {T} - [$return] + * + * @param {string} key - Sound asset key. + * + * @return {?Phaser.Sound.BaseSound} - The sound, or null. + */ + get: function (key) + { + return GetFirst(this.sounds, 'key', key); + }, + + /** + * Gets all sounds in this Sound Manager. + * + * You can optionally specify a key, in which case only Sound instances that match the given key + * will be returned. + * + * @method Phaser.Sound.BaseSoundManager#getAll + * @since 3.23.0 + * + * @generic {Phaser.Sound.BaseSound} T + * @genericUse {T[]} - [$return] + * + * @param {string} [key] - Optional asset key. If given, only Sound instances with this key will be returned. + * + * @return {Phaser.Sound.BaseSound[]} - The sounds, or an empty array. + */ + getAll: function (key) + { + if (key) + { + return GetAll(this.sounds, 'key', key); + } + else + { + return GetAll(this.sounds); + } + }, + + /** + * Returns all sounds from this Sound Manager that are currently + * playing. That is, Sound instances that have their `isPlaying` + * property set to `true`. + * + * @method Phaser.Sound.BaseSoundManager#getAllPlaying + * @since 3.60.0 + * + * @generic {Phaser.Sound.BaseSound} T + * @genericUse {T[]} - [$return] + * + * @return {Phaser.Sound.BaseSound[]} - All currently playing sounds, or an empty array. + */ + getAllPlaying: function () + { + return GetAll(this.sounds, 'isPlaying', true); + }, + + /** + * Adds a new sound to the sound manager and plays it. + * + * The sound will be automatically removed (destroyed) once playback ends. + * + * This lets you play a new sound on the fly without the need to keep a reference to it. + * + * @method Phaser.Sound.BaseSoundManager#play + * @listens Phaser.Sound.Events#COMPLETE + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {(Phaser.Types.Sound.SoundConfig|Phaser.Types.Sound.SoundMarker)} [extra] - An optional additional object containing settings to be applied to the sound. It could be either config or marker object. + * + * @return {boolean} Whether the sound started playing successfully. + */ + play: function (key, extra) + { + var sound = this.add(key); + + sound.once(Events.COMPLETE, sound.destroy, sound); + + if (extra) + { + if (extra.name) + { + sound.addMarker(extra); + + return sound.play(extra.name); + } + else + { + return sound.play(extra); + } + } + else + { + return sound.play(); + } + }, + + /** + * Adds a new audio sprite sound to the sound manager and plays it. + * The sprite will be automatically removed (destroyed) once playback ends. + * This lets you play a new sound on the fly without the need to keep a reference to it. + * + * @method Phaser.Sound.BaseSoundManager#playAudioSprite + * @listens Phaser.Sound.Events#COMPLETE + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {string} spriteName - The name of the sound sprite to play. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {boolean} Whether the audio sprite sound started playing successfully. + */ + playAudioSprite: function (key, spriteName, config) + { + var sound = this.addAudioSprite(key); + + sound.once(Events.COMPLETE, sound.destroy, sound); + + return sound.play(spriteName, config); + }, + + /** + * Removes a sound from the sound manager. + * The removed sound is destroyed before removal. + * + * @method Phaser.Sound.BaseSoundManager#remove + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSound} sound - The sound object to remove. + * + * @return {boolean} True if the sound was removed successfully, otherwise false. + */ + remove: function (sound) + { + var index = this.sounds.indexOf(sound); + + if (index !== -1) + { + sound.destroy(); + + this.sounds.splice(index, 1); + + return true; + } + + return false; + }, + + /** + * Removes all sounds from the manager, destroying the sounds. + * + * @method Phaser.Sound.BaseSoundManager#removeAll + * @since 3.23.0 + */ + removeAll: function () + { + this.sounds.forEach(function (sound) + { + sound.destroy(); + }); + + this.sounds.length = 0; + }, + + /** + * Removes all sounds from the sound manager that have an asset key matching the given value. + * The removed sounds are destroyed before removal. + * + * @method Phaser.Sound.BaseSoundManager#removeByKey + * @since 3.0.0 + * + * @param {string} key - The key to match when removing sound objects. + * + * @return {number} The number of matching sound objects that were removed. + */ + removeByKey: function (key) + { + var removed = 0; + + for (var i = this.sounds.length - 1; i >= 0; i--) + { + var sound = this.sounds[i]; + + if (sound.key === key) + { + sound.destroy(); + + this.sounds.splice(i, 1); + + removed++; + } + } + + return removed; + }, + + /** + * Pauses all the sounds in the game. + * + * @method Phaser.Sound.BaseSoundManager#pauseAll + * @fires Phaser.Sound.Events#PAUSE_ALL + * @since 3.0.0 + */ + pauseAll: function () + { + this.forEachActiveSound(function (sound) + { + sound.pause(); + }); + + this.emit(Events.PAUSE_ALL, this); + }, + + /** + * Resumes all the sounds in the game. + * + * @method Phaser.Sound.BaseSoundManager#resumeAll + * @fires Phaser.Sound.Events#RESUME_ALL + * @since 3.0.0 + */ + resumeAll: function () + { + this.forEachActiveSound(function (sound) + { + sound.resume(); + }); + + this.emit(Events.RESUME_ALL, this); + }, + + /** + * Sets the X and Y position of the Spatial Audio listener on this Web Audios context. + * + * If you call this method with no parameters it will default to the center-point of + * the game canvas. Depending on the type of game you're making, you may need to call + * this method constantly to reset the listener position as the camera scrolls. + * + * Calling this method does nothing on HTML5Audio. + * + * @method Phaser.Sound.BaseSoundManager#setListenerPosition + * @since 3.60.0 + * + * @param {number} [x] - The x position of the Spatial Audio listener. + * @param {number} [y] - The y position of the Spatial Audio listener. + */ + setListenerPosition: NOOP, + + /** + * Stops all the sounds in the game. + * + * @method Phaser.Sound.BaseSoundManager#stopAll + * @fires Phaser.Sound.Events#STOP_ALL + * @since 3.0.0 + */ + stopAll: function () + { + this.forEachActiveSound(function (sound) + { + sound.stop(); + }); + + this.emit(Events.STOP_ALL, this); + }, + + /** + * Stops any sounds matching the given key. + * + * @method Phaser.Sound.BaseSoundManager#stopByKey + * @since 3.23.0 + * + * @param {string} key - Sound asset key. + * + * @return {number} - How many sounds were stopped. + */ + stopByKey: function (key) + { + var stopped = 0; + + this.getAll(key).forEach(function (sound) + { + if (sound.stop()) { stopped++; } + }); + + return stopped; + }, + + /** + * When a key is given, returns true if any sound with that key is playing. + * + * When no key is given, returns true if any sound is playing. + * + * @method Phaser.Sound.BaseSoundManager#isPlaying + * @since 3.85.0 + * + * @param {?string} key - Sound asset key. + * + * @return {boolean} - Per the key argument, true if any matching sound is playing, otherwise false. + */ + isPlaying: function (key) + { + var sounds = this.sounds; + var i = sounds.length - 1; + var sound; + + if (key === undefined) + { + for (; i >= 0; i--) + { + sound = this.sounds[i]; + + if (sound.isPlaying) + { + return true; + } + } + } + else + { + for (; i >= 0; i--) + { + sound = this.sounds[i]; + + if (sound.key === key && sound.isPlaying) + { + return true; + } + } + } + + return false; + }, + + /** + * Method used internally for unlocking audio playback on devices that + * require user interaction before any sound can be played on a web page. + * + * Read more about how this issue is handled here in [this article](https://medium.com/@pgoloskokovic/unlocking-web-audio-the-smarter-way-8858218c0e09). + * + * @method Phaser.Sound.BaseSoundManager#unlock + * @override + * @protected + * @since 3.0.0 + */ + unlock: NOOP, + + /** + * Method used internally for pausing sound manager if + * Phaser.Sound.BaseSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.BaseSoundManager#onBlur + * @override + * @protected + * @since 3.0.0 + */ + onBlur: NOOP, + + /** + * Method used internally for resuming sound manager if + * Phaser.Sound.BaseSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.BaseSoundManager#onFocus + * @override + * @protected + * @since 3.0.0 + */ + onFocus: NOOP, + + /** + * Internal handler for Phaser.Core.Events#BLUR. + * + * @method Phaser.Sound.BaseSoundManager#onGameBlur + * @private + * @since 3.23.0 + */ + onGameBlur: function () + { + this.gameLostFocus = true; + + if (this.pauseOnBlur) + { + this.onBlur(); + } + }, + + /** + * Internal handler for Phaser.Core.Events#FOCUS. + * + * @method Phaser.Sound.BaseSoundManager#onGameFocus + * @private + * @since 3.23.0 + */ + onGameFocus: function () + { + this.gameLostFocus = false; + + if (this.pauseOnBlur) + { + this.onFocus(); + } + }, + + /** + * Update method called on every game step. + * Removes destroyed sounds and updates every active sound in the game. + * + * @method Phaser.Sound.BaseSoundManager#update + * @protected + * @fires Phaser.Sound.Events#UNLOCKED + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time elapsed since the last frame. + */ + update: function (time, delta) + { + if (this.unlocked) + { + this.unlocked = false; + this.locked = false; + + this.emit(Events.UNLOCKED, this); + } + + for (var i = this.sounds.length - 1; i >= 0; i--) + { + if (this.sounds[i].pendingRemove) + { + this.sounds.splice(i, 1); + } + } + + this.sounds.forEach(function (sound) + { + sound.update(time, delta); + }); + }, + + /** + * Destroys all the sounds in the game and all associated events. + * + * @method Phaser.Sound.BaseSoundManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.game.events.off(GameEvents.BLUR, this.onGameBlur, this); + this.game.events.off(GameEvents.FOCUS, this.onGameFocus, this); + this.game.events.off(GameEvents.PRE_STEP, this.update, this); + + this.removeAllListeners(); + + this.removeAll(); + + this.sounds.length = 0; + this.sounds = null; + this.listenerPosition = null; + this.game = null; + }, + + /** + * Method used internally for iterating only over active sounds and skipping sounds that are marked for removal. + * + * @method Phaser.Sound.BaseSoundManager#forEachActiveSound + * @private + * @since 3.0.0 + * + * @param {Phaser.Types.Sound.EachActiveSoundCallback} callback - Callback function. (manager: Phaser.Sound.BaseSoundManager, sound: Phaser.Sound.BaseSound, index: number, sounds: Phaser.Manager.BaseSound[]) => void + * @param {*} [scope] - Callback context. + */ + forEachActiveSound: function (callback, scope) + { + var _this = this; + + this.sounds.forEach(function (sound, index) + { + if (sound && !sound.pendingRemove) + { + callback.call(scope || _this, sound, index, _this.sounds); + } + }); + }, + + /** + * Sets the global playback rate at which all the sounds will be played. + * + * For example, a value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @method Phaser.Sound.BaseSoundManager#setRate + * @fires Phaser.Sound.Events#GLOBAL_RATE + * @since 3.3.0 + * + * @param {number} value - Global playback rate at which all the sounds will be played. + * + * @return {this} This Sound Manager. + */ + setRate: function (value) + { + this.rate = value; + + return this; + }, + + /** + * Global playback rate at which all the sounds will be played. + * Value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audio's playback speed. + * + * @name Phaser.Sound.BaseSoundManager#rate + * @type {number} + * @default 1 + * @since 3.0.0 + */ + rate: { + + get: function () + { + return this._rate; + }, + + set: function (value) + { + this._rate = value; + + this.forEachActiveSound(function (sound) + { + sound.calculateRate(); + }); + + this.emit(Events.GLOBAL_RATE, this, value); + } + + }, + + /** + * Sets the global detuning of all sounds in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @method Phaser.Sound.BaseSoundManager#setDetune + * @fires Phaser.Sound.Events#GLOBAL_DETUNE + * @since 3.3.0 + * + * @param {number} value - The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @return {this} This Sound Manager. + */ + setDetune: function (value) + { + this.detune = value; + + return this; + }, + + /** + * Global detuning of all sounds in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @name Phaser.Sound.BaseSoundManager#detune + * @type {number} + * @default 0 + * @since 3.0.0 + */ + detune: { + + get: function () + { + return this._detune; + }, + + set: function (value) + { + this._detune = value; + + this.forEachActiveSound(function (sound) + { + sound.calculateRate(); + }); + + this.emit(Events.GLOBAL_DETUNE, this, value); + } + + } + +}); + +module.exports = BaseSoundManager; + + +/***/ }), + +/***/ 14747: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var HTML5AudioSoundManager = __webpack_require__(33684); +var NoAudioSoundManager = __webpack_require__(25960); +var WebAudioSoundManager = __webpack_require__(57490); + +/** + * Creates a Web Audio, HTML5 Audio or No Audio Sound Manager based on config and device settings. + * + * Be aware of https://developers.google.com/web/updates/2017/09/autoplay-policy-changes + * + * @function Phaser.Sound.SoundManagerCreator + * @since 3.0.0 + * + * @param {Phaser.Game} game - Reference to the current game instance. + * + * @return {(Phaser.Sound.HTML5AudioSoundManager|Phaser.Sound.WebAudioSoundManager|Phaser.Sound.NoAudioSoundManager)} The Sound Manager instance that was created. + */ +var SoundManagerCreator = { + + create: function (game) + { + var audioConfig = game.config.audio; + var deviceAudio = game.device.audio; + + if (audioConfig.noAudio || (!deviceAudio.webAudio && !deviceAudio.audioData)) + { + return new NoAudioSoundManager(game); + } + + if (deviceAudio.webAudio && !audioConfig.disableWebAudio) + { + return new WebAudioSoundManager(game); + } + + return new HTML5AudioSoundManager(game); + } + +}; + +module.exports = SoundManagerCreator; + + +/***/ }), + +/***/ 19723: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Complete Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they complete playback. + * + * Listen to it from a Sound instance using `Sound.on('complete', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('complete', listener); + * music.play(); + * ``` + * + * @event Phaser.Sound.Events#COMPLETE + * @type {string} + * @since 3.16.1 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'complete'; + + +/***/ }), + +/***/ 98882: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Audio Data Decoded All Event. + * + * This event is dispatched by the Web Audio Sound Manager as a result of calling the `decodeAudio` method, + * once all files passed to the method have been decoded (or errored). + * + * Use `Phaser.Sound.Events#DECODED` to listen for single sounds being decoded, and `DECODED_ALL` to + * listen for them all completing. + * + * Listen to it from the Sound Manager in a Scene using `this.sound.on('decodedall', listener)`, i.e.: + * + * ```javascript + * this.sound.once('decodedall', handler); + * this.sound.decodeAudio([ audioFiles ]); + * ``` + * + * @event Phaser.Sound.Events#DECODED_ALL + * @type {string} + * @since 3.18.0 + */ +module.exports = 'decodedall'; + + +/***/ }), + +/***/ 57506: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Audio Data Decoded Event. + * + * This event is dispatched by the Web Audio Sound Manager as a result of calling the `decodeAudio` method. + * + * Listen to it from the Sound Manager in a Scene using `this.sound.on('decoded', listener)`, i.e.: + * + * ```javascript + * this.sound.on('decoded', handler); + * this.sound.decodeAudio(key, audioData); + * ``` + * + * @event Phaser.Sound.Events#DECODED + * @type {string} + * @since 3.18.0 + * + * @param {string} key - The key of the audio file that was decoded and added to the audio cache. + */ +module.exports = 'decoded'; + + +/***/ }), + +/***/ 73146: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Destroy Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they are destroyed, either + * directly or via a Sound Manager. + * + * Listen to it from a Sound instance using `Sound.on('destroy', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('destroy', listener); + * music.destroy(); + * ``` + * + * @event Phaser.Sound.Events#DESTROY + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'destroy'; + + +/***/ }), + +/***/ 11305: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Detune Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their detune value changes. + * + * Listen to it from a Sound instance using `Sound.on('detune', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('detune', listener); + * music.play(); + * music.setDetune(200); + * ``` + * + * @event Phaser.Sound.Events#DETUNE + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {number} detune - The new detune value of the Sound. + */ +module.exports = 'detune'; + + +/***/ }), + +/***/ 40577: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Manager Global Detune Event. + * + * This event is dispatched by the Base Sound Manager, or more typically, an instance of the Web Audio Sound Manager, + * or the HTML5 Audio Manager. It is dispatched when the `detune` property of the Sound Manager is changed, which globally + * adjusts the detuning of all active sounds. + * + * Listen to it from a Scene using: `this.sound.on('rate', listener)`. + * + * @event Phaser.Sound.Events#GLOBAL_DETUNE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} soundManager - A reference to the sound manager that emitted the event. + * @param {number} detune - The updated detune value. + */ +module.exports = 'detune'; + + +/***/ }), + +/***/ 30333: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Manager Global Mute Event. + * + * This event is dispatched by the Sound Manager when its `mute` property is changed, either directly + * or via the `setMute` method. This changes the mute state of all active sounds. + * + * Listen to it from a Scene using: `this.sound.on('mute', listener)`. + * + * @event Phaser.Sound.Events#GLOBAL_MUTE + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSoundManager|Phaser.Sound.HTML5AudioSoundManager)} soundManager - A reference to the Sound Manager that emitted the event. + * @param {boolean} mute - The mute value. `true` if the Sound Manager is now muted, otherwise `false`. + */ +module.exports = 'mute'; + + +/***/ }), + +/***/ 20394: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Manager Global Rate Event. + * + * This event is dispatched by the Base Sound Manager, or more typically, an instance of the Web Audio Sound Manager, + * or the HTML5 Audio Manager. It is dispatched when the `rate` property of the Sound Manager is changed, which globally + * adjusts the playback rate of all active sounds. + * + * Listen to it from a Scene using: `this.sound.on('rate', listener)`. + * + * @event Phaser.Sound.Events#GLOBAL_RATE + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} soundManager - A reference to the sound manager that emitted the event. + * @param {number} rate - The updated rate value. + */ +module.exports = 'rate'; + + +/***/ }), + +/***/ 21802: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Manager Global Volume Event. + * + * This event is dispatched by the Sound Manager when its `volume` property is changed, either directly + * or via the `setVolume` method. This changes the volume of all active sounds. + * + * Listen to it from a Scene using: `this.sound.on('volume', listener)`. + * + * @event Phaser.Sound.Events#GLOBAL_VOLUME + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSoundManager|Phaser.Sound.HTML5AudioSoundManager)} soundManager - A reference to the sound manager that emitted the event. + * @param {number} volume - The new global volume of the Sound Manager. + */ +module.exports = 'volume'; + + +/***/ }), + +/***/ 1299: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Looped Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they loop during playback. + * + * Listen to it from a Sound instance using `Sound.on('looped', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('looped', listener); + * music.setLoop(true); + * music.play(); + * ``` + * + * This is not to be confused with the [LOOP]{@linkcode Phaser.Sound.Events#event:LOOP} event, which only emits when the loop state of a Sound is changed. + * + * @event Phaser.Sound.Events#LOOPED + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'looped'; + + +/***/ }), + +/***/ 99190: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Loop Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their loop state is changed. + * + * Listen to it from a Sound instance using `Sound.on('loop', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('loop', listener); + * music.setLoop(true); + * ``` + * + * This is not to be confused with the [LOOPED]{@linkcode Phaser.Sound.Events#event:LOOPED} event, which emits each time a Sound loops during playback. + * + * @event Phaser.Sound.Events#LOOP + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {boolean} loop - The new loop value. `true` if the Sound will loop, otherwise `false`. + */ +module.exports = 'loop'; + + +/***/ }), + +/***/ 97125: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Mute Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their mute state changes. + * + * Listen to it from a Sound instance using `Sound.on('mute', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('mute', listener); + * music.play(); + * music.setMute(true); + * ``` + * + * @event Phaser.Sound.Events#MUTE + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {boolean} mute - The mute value. `true` if the Sound is now muted, otherwise `false`. + */ +module.exports = 'mute'; + + +/***/ }), + +/***/ 89259: +/***/ ((module) => { + +/** + * @author pi-kei + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Pan Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their pan changes. + * + * Listen to it from a Sound instance using `Sound.on('pan', listener)`, i.e.: + * + * ```javascript + * var sound = this.sound.add('key'); + * sound.on('pan', listener); + * sound.play(); + * sound.setPan(0.5); + * ``` + * + * @event Phaser.Sound.Events#PAN + * @type {string} + * @since 3.50.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {number} pan - The new pan of the Sound. + */ +module.exports = 'pan'; + + +/***/ }), + +/***/ 79986: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Pause All Sounds Event. + * + * This event is dispatched by the Base Sound Manager, or more typically, an instance of the Web Audio Sound Manager, + * or the HTML5 Audio Manager. It is dispatched when the `pauseAll` method is invoked and after all current Sounds + * have been paused. + * + * Listen to it from a Scene using: `this.sound.on('pauseall', listener)`. + * + * @event Phaser.Sound.Events#PAUSE_ALL + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} soundManager - A reference to the sound manager that emitted the event. + */ +module.exports = 'pauseall'; + + +/***/ }), + +/***/ 17586: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Pause Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they are paused. + * + * Listen to it from a Sound instance using `Sound.on('pause', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('pause', listener); + * music.play(); + * music.pause(); + * ``` + * + * @event Phaser.Sound.Events#PAUSE + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'pause'; + + +/***/ }), + +/***/ 19618: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Play Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they are played. + * + * Listen to it from a Sound instance using `Sound.on('play', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('play', listener); + * music.play(); + * ``` + * + * @event Phaser.Sound.Events#PLAY + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'play'; + + +/***/ }), + +/***/ 42306: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Rate Change Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their rate changes. + * + * Listen to it from a Sound instance using `Sound.on('rate', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('rate', listener); + * music.play(); + * music.setRate(0.5); + * ``` + * + * @event Phaser.Sound.Events#RATE + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {number} rate - The new rate of the Sound. + */ +module.exports = 'rate'; + + +/***/ }), + +/***/ 10387: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Resume All Sounds Event. + * + * This event is dispatched by the Base Sound Manager, or more typically, an instance of the Web Audio Sound Manager, + * or the HTML5 Audio Manager. It is dispatched when the `resumeAll` method is invoked and after all current Sounds + * have been resumed. + * + * Listen to it from a Scene using: `this.sound.on('resumeall', listener)`. + * + * @event Phaser.Sound.Events#RESUME_ALL + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} soundManager - A reference to the sound manager that emitted the event. + */ +module.exports = 'resumeall'; + + +/***/ }), + +/***/ 48959: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Resume Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they are resumed from a paused state. + * + * Listen to it from a Sound instance using `Sound.on('resume', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('resume', listener); + * music.play(); + * music.pause(); + * music.resume(); + * ``` + * + * @event Phaser.Sound.Events#RESUME + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'resume'; + + +/***/ }), + +/***/ 9960: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Seek Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they are seeked to a new position. + * + * Listen to it from a Sound instance using `Sound.on('seek', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('seek', listener); + * music.play(); + * music.setSeek(5000); + * ``` + * + * @event Phaser.Sound.Events#SEEK + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {number} detune - The new detune value of the Sound. + */ +module.exports = 'seek'; + + +/***/ }), + +/***/ 19180: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Stop All Sounds Event. + * + * This event is dispatched by the Base Sound Manager, or more typically, an instance of the Web Audio Sound Manager, + * or the HTML5 Audio Manager. It is dispatched when the `stopAll` method is invoked and after all current Sounds + * have been stopped. + * + * Listen to it from a Scene using: `this.sound.on('stopall', listener)`. + * + * @event Phaser.Sound.Events#STOP_ALL + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} soundManager - A reference to the sound manager that emitted the event. + */ +module.exports = 'stopall'; + + +/***/ }), + +/***/ 98328: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Stop Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when they are stopped. + * + * Listen to it from a Sound instance using `Sound.on('stop', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('stop', listener); + * music.play(); + * music.stop(); + * ``` + * + * @event Phaser.Sound.Events#STOP + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + */ +module.exports = 'stop'; + + +/***/ }), + +/***/ 50401: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Manager Unlocked Event. + * + * This event is dispatched by the Base Sound Manager, or more typically, an instance of the Web Audio Sound Manager, + * or the HTML5 Audio Manager. It is dispatched during the update loop when the Sound Manager becomes unlocked. For + * Web Audio this is on the first user gesture on the page. + * + * Listen to it from a Scene using: `this.sound.on('unlocked', listener)`. + * + * @event Phaser.Sound.Events#UNLOCKED + * @type {string} + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSoundManager} soundManager - A reference to the sound manager that emitted the event. + */ +module.exports = 'unlocked'; + + +/***/ }), + +/***/ 52498: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Sound Volume Event. + * + * This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their volume changes. + * + * Listen to it from a Sound instance using `Sound.on('volume', listener)`, i.e.: + * + * ```javascript + * var music = this.sound.add('key'); + * music.on('volume', listener); + * music.play(); + * music.setVolume(0.5); + * ``` + * + * @event Phaser.Sound.Events#VOLUME + * @type {string} + * @since 3.0.0 + * + * @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event. + * @param {number} volume - The new volume of the Sound. + */ +module.exports = 'volume'; + + +/***/ }), + +/***/ 14463: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Sound.Events + */ + +module.exports = { + + COMPLETE: __webpack_require__(19723), + DECODED: __webpack_require__(57506), + DECODED_ALL: __webpack_require__(98882), + DESTROY: __webpack_require__(73146), + DETUNE: __webpack_require__(11305), + GLOBAL_DETUNE: __webpack_require__(40577), + GLOBAL_MUTE: __webpack_require__(30333), + GLOBAL_RATE: __webpack_require__(20394), + GLOBAL_VOLUME: __webpack_require__(21802), + LOOP: __webpack_require__(99190), + LOOPED: __webpack_require__(1299), + MUTE: __webpack_require__(97125), + PAN: __webpack_require__(89259), + PAUSE_ALL: __webpack_require__(79986), + PAUSE: __webpack_require__(17586), + PLAY: __webpack_require__(19618), + RATE: __webpack_require__(42306), + RESUME_ALL: __webpack_require__(10387), + RESUME: __webpack_require__(48959), + SEEK: __webpack_require__(9960), + STOP_ALL: __webpack_require__(19180), + STOP: __webpack_require__(98328), + UNLOCKED: __webpack_require__(50401), + VOLUME: __webpack_require__(52498) + +}; + + +/***/ }), + +/***/ 64895: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseSound = __webpack_require__(30341); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(14463); +var Clamp = __webpack_require__(45319); + +/** + * @classdesc + * HTML5 Audio implementation of the sound. + * + * @class HTML5AudioSound + * @extends Phaser.Sound.BaseSound + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Sound.HTML5AudioSoundManager} manager - Reference to the current sound manager instance. + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config={}] - An optional config object containing default sound settings. + */ +var HTML5AudioSound = new Class({ + + Extends: BaseSound, + + initialize: + + function HTML5AudioSound (manager, key, config) + { + if (config === undefined) { config = {}; } + + /** + * An array containing all HTML5 Audio tags that could be used for individual + * sound playback. Number of instances depends on the config value passed + * to the `Loader#audio` method call, default is 1. + * + * @name Phaser.Sound.HTML5AudioSound#tags + * @type {HTMLAudioElement[]} + * @since 3.0.0 + */ + this.tags = manager.game.cache.audio.get(key); + + if (!this.tags) + { + throw new Error('No cached audio asset with key "' + key); + } + + /** + * Reference to an HTML5 Audio tag used for playing sound. + * + * @name Phaser.Sound.HTML5AudioSound#audio + * @type {HTMLAudioElement} + * @default null + * @since 3.0.0 + */ + this.audio = null; + + /** + * Timestamp as generated by the Request Animation Frame or SetTimeout + * representing the time at which the delayed sound playback should start. + * Set to 0 if sound playback is not delayed. + * + * @name Phaser.Sound.HTML5AudioSound#startTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.startTime = 0; + + /** + * Audio tag's playback position recorded on previous + * update method call. Set to 0 if sound is not playing. + * + * @name Phaser.Sound.HTML5AudioSound#previousTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.previousTime = 0; + + this.duration = this.tags[0].duration; + + this.totalDuration = this.tags[0].duration; + + BaseSound.call(this, manager, key, config); + }, + + /** + * Play this sound, or a marked section of it. + * + * It always plays the sound from the start. If you want to start playback from a specific time + * you can set 'seek' setting of the config object, provided to this call, to that value. + * + * If you want to play the same sound simultaneously, then you need to create another instance + * of it and play that Sound. For HTML5 Audio this also requires creating multiple audio instances + * when loading the audio files. + * + * @method Phaser.Sound.HTML5AudioSound#play + * @fires Phaser.Sound.Events#PLAY + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Sound.SoundConfig)} [markerName=''] - If you want to play a marker then provide the marker name here. Alternatively, this parameter can be a SoundConfig object. + * @param {Phaser.Types.Sound.SoundConfig} [config] - Optional sound config object to be applied to this marker or entire sound if no marker name is provided. It gets memorized for future plays of current section of the sound. + * + * @return {boolean} Whether the sound started playing successfully. + */ + play: function (markerName, config) + { + if (this.manager.isLocked(this, 'play', [ markerName, config ])) + { + return false; + } + + if (!BaseSound.prototype.play.call(this, markerName, config)) + { + return false; + } + + // \/\/\/ isPlaying = true, isPaused = false \/\/\/ + if (!this.pickAndPlayAudioTag()) + { + return false; + } + + this.emit(Events.PLAY, this); + + return true; + }, + + /** + * Pauses the sound. + * + * @method Phaser.Sound.HTML5AudioSound#pause + * @fires Phaser.Sound.Events#PAUSE + * @since 3.0.0 + * + * @return {boolean} Whether the sound was paused successfully. + */ + pause: function () + { + if (this.manager.isLocked(this, 'pause')) + { + return false; + } + + if (this.startTime > 0) + { + return false; + } + + if (!BaseSound.prototype.pause.call(this)) + { + return false; + } + + // \/\/\/ isPlaying = false, isPaused = true \/\/\/ + this.currentConfig.seek = this.audio.currentTime - (this.currentMarker ? this.currentMarker.start : 0); + + this.stopAndReleaseAudioTag(); + + this.emit(Events.PAUSE, this); + + return true; + }, + + /** + * Resumes the sound. + * + * @method Phaser.Sound.HTML5AudioSound#resume + * @fires Phaser.Sound.Events#RESUME + * @since 3.0.0 + * + * @return {boolean} Whether the sound was resumed successfully. + */ + resume: function () + { + if (this.manager.isLocked(this, 'resume')) + { + return false; + } + + if (this.startTime > 0) + { + return false; + } + + if (!BaseSound.prototype.resume.call(this)) + { + return false; + } + + // \/\/\/ isPlaying = true, isPaused = false \/\/\/ + if (!this.pickAndPlayAudioTag()) + { + return false; + } + + this.emit(Events.RESUME, this); + + return true; + }, + + /** + * Stop playing this sound. + * + * @method Phaser.Sound.HTML5AudioSound#stop + * @fires Phaser.Sound.Events#STOP + * @since 3.0.0 + * + * @return {boolean} Whether the sound was stopped successfully. + */ + stop: function () + { + if (this.manager.isLocked(this, 'stop')) + { + return false; + } + + if (!BaseSound.prototype.stop.call(this)) + { + return false; + } + + // \/\/\/ isPlaying = false, isPaused = false \/\/\/ + this.stopAndReleaseAudioTag(); + + this.emit(Events.STOP, this); + + return true; + }, + + /** + * This method is used internally to pick and play the next available audio tag. + * + * @method Phaser.Sound.HTML5AudioSound#pickAndPlayAudioTag + * @since 3.0.0 + * + * @return {boolean} Whether the sound was assigned an audio tag successfully. + */ + pickAndPlayAudioTag: function () + { + if (!this.pickAudioTag()) + { + this.reset(); + + return false; + } + + var seek = this.currentConfig.seek; + var delay = this.currentConfig.delay; + var offset = (this.currentMarker ? this.currentMarker.start : 0) + seek; + + this.previousTime = offset; + this.audio.currentTime = offset; + this.applyConfig(); + + if (delay === 0) + { + this.startTime = 0; + + if (this.audio.paused) + { + this.playCatchPromise(); + } + } + else + { + this.startTime = window.performance.now() + delay * 1000; + + if (!this.audio.paused) + { + this.audio.pause(); + } + } + + this.resetConfig(); + + return true; + }, + + /** + * This method performs the audio tag pooling logic. It first looks for + * unused audio tag to assign to this sound object. If there are no unused + * audio tags, based on HTML5AudioSoundManager#override property value, it + * looks for sound with most advanced playback and hijacks its audio tag or + * does nothing. + * + * @method Phaser.Sound.HTML5AudioSound#pickAudioTag + * @since 3.0.0 + * + * @return {boolean} Whether the sound was assigned an audio tag successfully. + */ + pickAudioTag: function () + { + if (this.audio) + { + return true; + } + + for (var i = 0; i < this.tags.length; i++) + { + var audio = this.tags[i]; + + if (audio.dataset.used === 'false') + { + audio.dataset.used = 'true'; + this.audio = audio; + return true; + } + } + + if (!this.manager.override) + { + return false; + } + + var otherSounds = []; + + this.manager.forEachActiveSound(function (sound) + { + if (sound.key === this.key && sound.audio) + { + otherSounds.push(sound); + } + }, this); + + otherSounds.sort(function (a1, a2) + { + if (a1.loop === a2.loop) + { + // sort by progress + return (a2.seek / a2.duration) - (a1.seek / a1.duration); + } + return a1.loop ? 1 : -1; + }); + + var selectedSound = otherSounds[0]; + + this.audio = selectedSound.audio; + + selectedSound.reset(); + selectedSound.audio = null; + selectedSound.startTime = 0; + selectedSound.previousTime = 0; + + return true; + }, + + /** + * Method used for playing audio tag and catching possible exceptions + * thrown from rejected Promise returned from play method call. + * + * @method Phaser.Sound.HTML5AudioSound#playCatchPromise + * @since 3.0.0 + */ + playCatchPromise: function () + { + var playPromise = this.audio.play(); + + if (playPromise) + { + // eslint-disable-next-line no-unused-vars + playPromise.catch(function (reason) + { + console.warn(reason); + }); + } + }, + + /** + * This method is used internally to stop and release the current audio tag. + * + * @method Phaser.Sound.HTML5AudioSound#stopAndReleaseAudioTag + * @since 3.0.0 + */ + stopAndReleaseAudioTag: function () + { + this.startTime = 0; + this.previousTime = 0; + + if (this.audio) + { + this.audio.pause(); + this.audio.dataset.used = 'false'; + this.audio = null; + } + }, + + /** + * Method used internally to reset sound state, usually when stopping sound + * or when hijacking audio tag from another sound. + * + * @method Phaser.Sound.HTML5AudioSound#reset + * @since 3.0.0 + */ + reset: function () + { + BaseSound.prototype.stop.call(this); + }, + + /** + * Method used internally by sound manager for pausing sound if + * Phaser.Sound.HTML5AudioSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.HTML5AudioSound#onBlur + * @since 3.0.0 + */ + onBlur: function () + { + this.isPlaying = false; + this.isPaused = true; + + this.currentConfig.seek = this.audio.currentTime - (this.currentMarker ? this.currentMarker.start : 0); + + this.currentConfig.delay = Math.max(0, (this.startTime - window.performance.now()) / 1000); + + this.stopAndReleaseAudioTag(); + }, + + /** + * Method used internally by sound manager for resuming sound if + * Phaser.Sound.HTML5AudioSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.HTML5AudioSound#onFocus + * @since 3.0.0 + */ + onFocus: function () + { + this.isPlaying = true; + this.isPaused = false; + this.pickAndPlayAudioTag(); + }, + + /** + * Update method called automatically by sound manager on every game step. + * + * @method Phaser.Sound.HTML5AudioSound#update + * @fires Phaser.Sound.Events#COMPLETE + * @fires Phaser.Sound.Events#LOOPED + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + */ + update: function (time) + { + if (!this.isPlaying) + { + return; + } + + // handling delayed playback + if (this.startTime > 0) + { + if (this.startTime < time - this.manager.audioPlayDelay) + { + this.audio.currentTime += Math.max(0, time - this.startTime) / 1000; + this.startTime = 0; + this.previousTime = this.audio.currentTime; + this.playCatchPromise(); + } + + return; + } + + // handle looping and ending + var startTime = this.currentMarker ? this.currentMarker.start : 0; + var endTime = startTime + this.duration; + var currentTime = this.audio.currentTime; + + if (this.currentConfig.loop) + { + if (currentTime >= endTime - this.manager.loopEndOffset) + { + this.audio.currentTime = startTime + Math.max(0, currentTime - endTime); + currentTime = this.audio.currentTime; + } + else if (currentTime < startTime) + { + this.audio.currentTime += startTime; + currentTime = this.audio.currentTime; + } + + if (currentTime < this.previousTime) + { + this.emit(Events.LOOPED, this); + } + } + else if (currentTime >= endTime) + { + this.reset(); + + this.stopAndReleaseAudioTag(); + + this.emit(Events.COMPLETE, this); + + return; + } + + this.previousTime = currentTime; + }, + + /** + * Calls Phaser.Sound.BaseSound#destroy method + * and cleans up all HTML5 Audio related stuff. + * + * @method Phaser.Sound.HTML5AudioSound#destroy + * @since 3.0.0 + */ + destroy: function () + { + BaseSound.prototype.destroy.call(this); + + this.tags = null; + + if (this.audio) + { + this.stopAndReleaseAudioTag(); + } + }, + + /** + * This method is used internally to update the mute setting of this sound. + * + * @method Phaser.Sound.HTML5AudioSound#updateMute + * @since 3.0.0 + */ + updateMute: function () + { + if (this.audio) + { + this.audio.muted = this.currentConfig.mute || this.manager.mute; + } + }, + + /** + * This method is used internally to update the volume of this sound. + * + * @method Phaser.Sound.HTML5AudioSound#updateVolume + * @since 3.0.0 + */ + updateVolume: function () + { + if (this.audio) + { + this.audio.volume = Clamp(this.currentConfig.volume * this.manager.volume, 0, 1); + } + }, + + /** + * This method is used internally to update the playback rate of this sound. + * + * @method Phaser.Sound.HTML5AudioSound#calculateRate + * @since 3.0.0 + */ + calculateRate: function () + { + BaseSound.prototype.calculateRate.call(this); + + if (this.audio) + { + this.audio.playbackRate = this.totalRate; + } + }, + + /** + * Boolean indicating whether the sound is muted or not. + * Gets or sets the muted state of this sound. + * + * @name Phaser.Sound.HTML5AudioSound#mute + * @type {boolean} + * @default false + * @fires Phaser.Sound.Events#MUTE + * @since 3.0.0 + */ + mute: { + + get: function () + { + return this.currentConfig.mute; + }, + + set: function (value) + { + this.currentConfig.mute = value; + + if (this.manager.isLocked(this, 'mute', value)) + { + return; + } + + this.updateMute(); + + this.emit(Events.MUTE, this, value); + } + }, + + /** + * Sets the muted state of this Sound. + * + * @method Phaser.Sound.HTML5AudioSound#setMute + * @fires Phaser.Sound.Events#MUTE + * @since 3.4.0 + * + * @param {boolean} value - `true` to mute this sound, `false` to unmute it. + * + * @return {this} This Sound instance. + */ + setMute: function (value) + { + this.mute = value; + + return this; + }, + + /** + * Gets or sets the volume of this sound, a value between 0 (silence) and 1 (full volume). + * + * @name Phaser.Sound.HTML5AudioSound#volume + * @type {number} + * @default 1 + * @fires Phaser.Sound.Events#VOLUME + * @since 3.0.0 + */ + volume: { + + get: function () + { + return this.currentConfig.volume; + }, + + set: function (value) + { + this.currentConfig.volume = value; + + if (this.manager.isLocked(this, 'volume', value)) + { + return; + } + + this.updateVolume(); + + this.emit(Events.VOLUME, this, value); + } + }, + + /** + * Sets the volume of this Sound. + * + * @method Phaser.Sound.HTML5AudioSound#setVolume + * @fires Phaser.Sound.Events#VOLUME + * @since 3.4.0 + * + * @param {number} value - The volume of the sound. + * + * @return {this} This Sound instance. + */ + setVolume: function (value) + { + this.volume = value; + + return this; + }, + + /** + * Rate at which this Sound will be played. + * Value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @name Phaser.Sound.HTML5AudioSound#rate + * @type {number} + * @default 1 + * @fires Phaser.Sound.Events#RATE + * @since 3.0.0 + */ + rate: { + + get: function () + { + return this.currentConfig.rate; + }, + + set: function (value) + { + this.currentConfig.rate = value; + + if (this.manager.isLocked(this, Events.RATE, value)) + { + return; + } + else + { + this.calculateRate(); + + this.emit(Events.RATE, this, value); + } + } + + }, + + /** + * Sets the playback rate of this Sound. + * + * For example, a value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @method Phaser.Sound.HTML5AudioSound#setRate + * @fires Phaser.Sound.Events#RATE + * @since 3.3.0 + * + * @param {number} value - The playback rate at of this Sound. + * + * @return {this} This Sound instance. + */ + setRate: function (value) + { + this.rate = value; + + return this; + }, + + /** + * The detune value of this Sound, given in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @name Phaser.Sound.HTML5AudioSound#detune + * @type {number} + * @default 0 + * @fires Phaser.Sound.Events#DETUNE + * @since 3.0.0 + */ + detune: { + + get: function () + { + return this.currentConfig.detune; + }, + + set: function (value) + { + this.currentConfig.detune = value; + + if (this.manager.isLocked(this, Events.DETUNE, value)) + { + return; + } + else + { + this.calculateRate(); + + this.emit(Events.DETUNE, this, value); + } + } + + }, + + /** + * Sets the detune value of this Sound, given in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @method Phaser.Sound.HTML5AudioSound#setDetune + * @fires Phaser.Sound.Events#DETUNE + * @since 3.3.0 + * + * @param {number} value - The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @return {this} This Sound instance. + */ + setDetune: function (value) + { + this.detune = value; + + return this; + }, + + /** + * Property representing the position of playback for this sound, in seconds. + * Setting it to a specific value moves current playback to that position. + * The value given is clamped to the range 0 to current marker duration. + * Setting seek of a stopped sound has no effect. + * + * @name Phaser.Sound.HTML5AudioSound#seek + * @type {number} + * @fires Phaser.Sound.Events#SEEK + * @since 3.0.0 + */ + seek: { + + get: function () + { + if (this.isPlaying) + { + return this.audio.currentTime - (this.currentMarker ? this.currentMarker.start : 0); + } + else if (this.isPaused) + { + return this.currentConfig.seek; + } + else + { + return 0; + } + }, + + set: function (value) + { + if (this.manager.isLocked(this, 'seek', value)) + { + return; + } + + if (this.startTime > 0) + { + return; + } + + if (this.isPlaying || this.isPaused) + { + value = Math.min(Math.max(0, value), this.duration); + + if (this.isPlaying) + { + this.previousTime = value; + this.audio.currentTime = value; + } + else if (this.isPaused) + { + this.currentConfig.seek = value; + } + + this.emit(Events.SEEK, this, value); + } + } + }, + + /** + * Seeks to a specific point in this sound. + * + * @method Phaser.Sound.HTML5AudioSound#setSeek + * @fires Phaser.Sound.Events#SEEK + * @since 3.4.0 + * + * @param {number} value - The point in the sound to seek to. + * + * @return {this} This Sound instance. + */ + setSeek: function (value) + { + this.seek = value; + + return this; + }, + + /** + * Flag indicating whether or not the sound or current sound marker will loop. + * + * @name Phaser.Sound.HTML5AudioSound#loop + * @type {boolean} + * @default false + * @fires Phaser.Sound.Events#LOOP + * @since 3.0.0 + */ + loop: { + + get: function () + { + return this.currentConfig.loop; + }, + + set: function (value) + { + this.currentConfig.loop = value; + + if (this.manager.isLocked(this, 'loop', value)) + { + return; + } + + if (this.audio) + { + this.audio.loop = value; + } + + this.emit(Events.LOOP, this, value); + } + + }, + + /** + * Sets the loop state of this Sound. + * + * @method Phaser.Sound.HTML5AudioSound#setLoop + * @fires Phaser.Sound.Events#LOOP + * @since 3.4.0 + * + * @param {boolean} value - `true` to loop this sound, `false` to not loop it. + * + * @return {Phaser.Sound.HTML5AudioSound} This Sound instance. + */ + setLoop: function (value) + { + this.loop = value; + + return this; + }, + + /** + * Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan). + * + * Has no audible effect on HTML5 Audio Sound, but still generates the PAN Event. + * + * @name Phaser.Sound.HTML5AudioSound#pan + * @type {number} + * @default 0 + * @fires Phaser.Sound.Events#PAN + * @since 3.50.0 + */ + pan: { + + get: function () + { + return this.currentConfig.pan; + }, + + set: function (value) + { + this.currentConfig.pan = value; + + this.emit(Events.PAN, this, value); + } + }, + + /** + * Sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan). + * + * Has no audible effect on HTML5 Audio Sound, but still generates the PAN Event. + * + * @method Phaser.Sound.HTML5AudioSound#setPan + * @fires Phaser.Sound.Events#PAN + * @since 3.50.0 + * + * @param {number} value - The pan of the sound. A value between -1 (full left pan) and 1 (full right pan). + * + * @return {this} This Sound instance. + */ + setPan: function (value) + { + this.pan = value; + + return this; + } + +}); + +module.exports = HTML5AudioSound; + + +/***/ }), + +/***/ 33684: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseSoundManager = __webpack_require__(85034); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(14463); +var HTML5AudioSound = __webpack_require__(64895); + +/** + * HTML5 Audio implementation of the Sound Manager. + * + * To play multiple instances of the same HTML5 Audio sound, you need to provide an `instances` value when + * loading the sound with the Loader: + * + * ```javascript + * this.load.audio('explosion', 'explosion.mp3', { + * instances: 2 + * }); + * ``` + * + * Not all browsers can play all audio formats. + * + * There is a good guide to what's supported: [Cross-browser audio basics: Audio codec support](https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery/Cross-browser_audio_basics#Audio_Codec_Support). + * + * @class HTML5AudioSoundManager + * @extends Phaser.Sound.BaseSoundManager + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - Reference to the current game instance. + */ +var HTML5AudioSoundManager = new Class({ + + Extends: BaseSoundManager, + + initialize: + + function HTML5AudioSoundManager (game) + { + /** + * Flag indicating whether if there are no idle instances of HTML5 Audio tag, + * for any particular sound, if one of the used tags should be hijacked and used + * for succeeding playback or if succeeding Phaser.Sound.HTML5AudioSound#play + * call should be ignored. + * + * @name Phaser.Sound.HTML5AudioSoundManager#override + * @type {boolean} + * @default true + * @since 3.0.0 + */ + this.override = true; + + /** + * Value representing time difference, in seconds, between calling + * play method on an audio tag and when it actually starts playing. + * It is used to achieve more accurate delayed sound playback. + * + * You might need to tweak this value to get the desired results + * since audio play delay varies depending on the browser/platform. + * + * @name Phaser.Sound.HTML5AudioSoundManager#audioPlayDelay + * @type {number} + * @default 0.1 + * @since 3.0.0 + */ + this.audioPlayDelay = 0.1; + + /** + * A value by which we should offset the loop end marker of the + * looping sound to compensate for lag, caused by changing audio + * tag playback position, in order to achieve gapless looping. + * + * You might need to tweak this value to get the desired results + * since loop lag varies depending on the browser/platform. + * + * @name Phaser.Sound.HTML5AudioSoundManager#loopEndOffset + * @type {number} + * @default 0.05 + * @since 3.0.0 + */ + this.loopEndOffset = 0.05; + + /** + * An array for keeping track of all the sounds + * that were paused when game lost focus. + * + * @name Phaser.Sound.HTML5AudioSoundManager#onBlurPausedSounds + * @type {Phaser.Sound.HTML5AudioSound[]} + * @private + * @default [] + * @since 3.0.0 + */ + this.onBlurPausedSounds = []; + + this.locked = 'ontouchstart' in window; + + /** + * A queue of all actions performed on sound objects while audio was locked. + * Once the audio gets unlocked, after an explicit user interaction, + * all actions will be performed in chronological order. + * Array of object types: { sound: Phaser.Sound.HTML5AudioSound, name: string, value?: * } + * + * @name Phaser.Sound.HTML5AudioSoundManager#lockedActionsQueue + * @type {array} + * @private + * @since 3.0.0 + */ + this.lockedActionsQueue = this.locked ? [] : null; + + /** + * Property that actually holds the value of global mute + * for HTML5 Audio sound manager implementation. + * + * @name Phaser.Sound.HTML5AudioSoundManager#_mute + * @type {boolean} + * @private + * @default false + * @since 3.0.0 + */ + this._mute = false; + + /** + * Property that actually holds the value of global volume + * for HTML5 Audio sound manager implementation. + * + * @name Phaser.Sound.HTML5AudioSoundManager#_volume + * @type {boolean} + * @private + * @default 1 + * @since 3.0.0 + */ + this._volume = 1; + + BaseSoundManager.call(this, game); + }, + + /** + * Adds a new sound into the sound manager. + * + * @method Phaser.Sound.HTML5AudioSoundManager#add + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {Phaser.Sound.HTML5AudioSound} The new sound instance. + */ + add: function (key, config) + { + var sound = new HTML5AudioSound(this, key, config); + + this.sounds.push(sound); + + return sound; + }, + + /** + * Unlocks HTML5 Audio loading and playback on mobile + * devices on the initial explicit user interaction. + * + * @method Phaser.Sound.HTML5AudioSoundManager#unlock + * @since 3.0.0 + */ + unlock: function () + { + this.locked = false; + + var _this = this; + + this.game.cache.audio.entries.each(function (key, tags) + { + for (var i = 0; i < tags.length; i++) + { + if (tags[i].dataset.locked === 'true') + { + _this.locked = true; + + return false; + } + } + + return true; + }); + + if (!this.locked) + { + return; + } + + var moved = false; + + var detectMove = function () + { + moved = true; + }; + + var unlock = function () + { + if (moved) + { + moved = false; + return; + } + + document.body.removeEventListener('touchmove', detectMove); + document.body.removeEventListener('touchend', unlock); + + var lockedTags = []; + + _this.game.cache.audio.entries.each(function (key, tags) + { + for (var i = 0; i < tags.length; i++) + { + var tag = tags[i]; + + if (tag.dataset.locked === 'true') + { + lockedTags.push(tag); + } + } + + return true; + }); + + if (lockedTags.length === 0) + { + return; + } + + var lastTag = lockedTags[lockedTags.length - 1]; + + lastTag.oncanplaythrough = function () + { + lastTag.oncanplaythrough = null; + + lockedTags.forEach(function (tag) + { + tag.dataset.locked = 'false'; + }); + + _this.unlocked = true; + }; + + lockedTags.forEach(function (tag) + { + tag.load(); + }); + }; + + this.once(Events.UNLOCKED, function () + { + this.forEachActiveSound(function (sound) + { + if (sound.currentMarker === null && sound.duration === 0) + { + sound.duration = sound.tags[0].duration; + } + + sound.totalDuration = sound.tags[0].duration; + }); + + while (this.lockedActionsQueue.length) + { + var lockedAction = this.lockedActionsQueue.shift(); + + if (lockedAction.sound[lockedAction.prop].apply) + { + lockedAction.sound[lockedAction.prop].apply(lockedAction.sound, lockedAction.value || []); + } + else + { + lockedAction.sound[lockedAction.prop] = lockedAction.value; + } + } + + }, this); + + document.body.addEventListener('touchmove', detectMove, false); + document.body.addEventListener('touchend', unlock, false); + }, + + /** + * Method used internally for pausing sound manager if + * Phaser.Sound.HTML5AudioSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.HTML5AudioSoundManager#onBlur + * @protected + * @since 3.0.0 + */ + onBlur: function () + { + this.forEachActiveSound(function (sound) + { + if (sound.isPlaying) + { + this.onBlurPausedSounds.push(sound); + sound.onBlur(); + } + }); + }, + + /** + * Method used internally for resuming sound manager if + * Phaser.Sound.HTML5AudioSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.HTML5AudioSoundManager#onFocus + * @protected + * @since 3.0.0 + */ + onFocus: function () + { + this.onBlurPausedSounds.forEach(function (sound) + { + sound.onFocus(); + }); + + this.onBlurPausedSounds.length = 0; + }, + + /** + * Calls Phaser.Sound.BaseSoundManager#destroy method + * and cleans up all HTML5 Audio related stuff. + * + * @method Phaser.Sound.HTML5AudioSoundManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + BaseSoundManager.prototype.destroy.call(this); + + this.onBlurPausedSounds.length = 0; + this.onBlurPausedSounds = null; + }, + + /** + * Method used internally by Phaser.Sound.HTML5AudioSound class methods and property setters + * to check if sound manager is locked and then either perform action immediately or queue it + * to be performed once the sound manager gets unlocked. + * + * @method Phaser.Sound.HTML5AudioSoundManager#isLocked + * @protected + * @since 3.0.0 + * + * @param {Phaser.Sound.HTML5AudioSound} sound - Sound object on which to perform queued action. + * @param {string} prop - Name of the method to be called or property to be assigned a value to. + * @param {*} [value] - An optional parameter that either holds an array of arguments to be passed to the method call or value to be set to the property. + * + * @return {boolean} Whether the sound manager is locked. + */ + isLocked: function (sound, prop, value) + { + if (sound.tags[0].dataset.locked === 'true') + { + this.lockedActionsQueue.push({ + sound: sound, + prop: prop, + value: value + }); + + return true; + } + + return false; + }, + + /** + * Sets the muted state of all this Sound Manager. + * + * @method Phaser.Sound.HTML5AudioSoundManager#setMute + * @fires Phaser.Sound.Events#GLOBAL_MUTE + * @since 3.3.0 + * + * @param {boolean} value - `true` to mute all sounds, `false` to unmute them. + * + * @return {Phaser.Sound.HTML5AudioSoundManager} This Sound Manager. + */ + setMute: function (value) + { + this.mute = value; + + return this; + }, + + /** + * @name Phaser.Sound.HTML5AudioSoundManager#mute + * @type {boolean} + * @fires Phaser.Sound.Events#GLOBAL_MUTE + * @since 3.0.0 + */ + mute: { + + get: function () + { + return this._mute; + }, + + set: function (value) + { + this._mute = value; + + this.forEachActiveSound(function (sound) + { + sound.updateMute(); + }); + + this.emit(Events.GLOBAL_MUTE, this, value); + } + + }, + + /** + * Sets the volume of this Sound Manager. + * + * @method Phaser.Sound.HTML5AudioSoundManager#setVolume + * @fires Phaser.Sound.Events#GLOBAL_VOLUME + * @since 3.3.0 + * + * @param {number} value - The global volume of this Sound Manager. + * + * @return {Phaser.Sound.HTML5AudioSoundManager} This Sound Manager. + */ + setVolume: function (value) + { + this.volume = value; + + return this; + }, + + /** + * @name Phaser.Sound.HTML5AudioSoundManager#volume + * @type {number} + * @fires Phaser.Sound.Events#GLOBAL_VOLUME + * @since 3.0.0 + */ + volume: { + + get: function () + { + return this._volume; + }, + + set: function (value) + { + this._volume = value; + + this.forEachActiveSound(function (sound) + { + sound.updateVolume(); + }); + + this.emit(Events.GLOBAL_VOLUME, this, value); + } + + } + +}); + +module.exports = HTML5AudioSoundManager; + + +/***/ }), + +/***/ 23717: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Sound + */ + +module.exports = { + + SoundManagerCreator: __webpack_require__(14747), + + Events: __webpack_require__(14463), + + BaseSound: __webpack_require__(30341), + BaseSoundManager: __webpack_require__(85034), + + WebAudioSound: __webpack_require__(71741), + WebAudioSoundManager: __webpack_require__(57490), + + HTML5AudioSound: __webpack_require__(64895), + HTML5AudioSoundManager: __webpack_require__(33684), + + NoAudioSound: __webpack_require__(4603), + NoAudioSoundManager: __webpack_require__(25960) + +}; + + +/***/ }), + +/***/ 4603: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseSound = __webpack_require__(30341); +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Extend = __webpack_require__(79291); +var NOOP = __webpack_require__(29747); + +var returnFalse = function () +{ + return false; +}; + +var returnNull = function () +{ + return null; +}; + +var returnThis = function () +{ + return this; +}; + +/** + * @classdesc + * No audio implementation of the sound. It is used if audio has been + * disabled in the game config or the device doesn't support any audio. + * + * It represents a graceful degradation of sound logic that provides + * minimal functionality and prevents Phaser projects that use audio from + * breaking on devices that don't support any audio playback technologies. + * + * @class NoAudioSound + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Sound.NoAudioSoundManager} manager - Reference to the current sound manager instance. + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config={}] - An optional config object containing default sound settings. + */ +var NoAudioSound = new Class({ + + Extends: EventEmitter, + + initialize: + + function NoAudioSound (manager, key, config) + { + if (config === void 0) { config = {}; } + + EventEmitter.call(this); + + /** + * Local reference to the sound manager. + * + * @name Phaser.Sound.NoAudioSound#manager + * @type {Phaser.Sound.BaseSoundManager} + * @since 3.0.0 + */ + this.manager = manager; + + /** + * Asset key for the sound. + * + * @name Phaser.Sound.NoAudioSound#key + * @type {string} + * @readonly + * @since 3.0.0 + */ + this.key = key; + + /** + * Flag indicating if sound is currently playing. + * + * @name Phaser.Sound.NoAudioSound#isPlaying + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isPlaying = false; + + /** + * Flag indicating if sound is currently paused. + * + * @name Phaser.Sound.NoAudioSound#isPaused + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.isPaused = false; + + /** + * A property that holds the value of sound's actual playback rate, + * after its rate and detune values has been combined with global + * rate and detune values. + * + * @name Phaser.Sound.NoAudioSound#totalRate + * @type {number} + * @default 1 + * @readonly + * @since 3.0.0 + */ + this.totalRate = 1; + + /** + * A value representing the duration, in seconds. + * It could be total sound duration or a marker duration. + * + * @name Phaser.Sound.NoAudioSound#duration + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.duration = 0; + + /** + * The total duration of the sound in seconds. + * + * @name Phaser.Sound.NoAudioSound#totalDuration + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.totalDuration = 0; + + /** + * A config object used to store default sound settings' values. + * Default values will be set by properties' setters. + * + * @name Phaser.Sound.NoAudioSound#config + * @type {Phaser.Types.Sound.SoundConfig} + * @since 3.0.0 + */ + this.config = Extend({ + mute: false, + volume: 1, + rate: 1, + detune: 0, + seek: 0, + loop: false, + delay: 0, + pan: 0 + }, config); + + /** + * Reference to the currently used config. + * It could be default config or marker config. + * + * @name Phaser.Sound.NoAudioSound#currentConfig + * @type {Phaser.Types.Sound.SoundConfig} + * @since 3.0.0 + */ + this.currentConfig = this.config; + + /** + * Boolean indicating whether the sound is muted or not. + * Gets or sets the muted state of this sound. + * + * @name Phaser.Sound.NoAudioSound#mute + * @type {boolean} + * @default false + * @fires Phaser.Sound.Events#MUTE + * @since 3.0.0 + */ + this.mute = false; + + /** + * Gets or sets the volume of this sound, a value between 0 (silence) and 1 (full volume). + * + * @name Phaser.Sound.NoAudioSound#volume + * @type {number} + * @default 1 + * @fires Phaser.Sound.Events#VOLUME + * @since 3.0.0 + */ + this.volume = 1; + + /** + * Rate at which this Sound will be played. + * Value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @name Phaser.Sound.NoAudioSound#rate + * @type {number} + * @default 1 + * @fires Phaser.Sound.Events#RATE + * @since 3.0.0 + */ + this.rate = 1; + + /** + * The detune value of this Sound, given in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @name Phaser.Sound.NoAudioSound#detune + * @type {number} + * @default 0 + * @fires Phaser.Sound.Events#DETUNE + * @since 3.0.0 + */ + this.detune = 0; + + /** + * Property representing the position of playback for this sound, in seconds. + * Setting it to a specific value moves current playback to that position. + * The value given is clamped to the range 0 to current marker duration. + * Setting seek of a stopped sound has no effect. + * + * @name Phaser.Sound.NoAudioSound#seek + * @type {number} + * @fires Phaser.Sound.Events#SEEK + * @since 3.0.0 + */ + this.seek = 0; + + /** + * Flag indicating whether or not the sound or current sound marker will loop. + * + * @name Phaser.Sound.NoAudioSound#loop + * @type {boolean} + * @default false + * @fires Phaser.Sound.Events#LOOP + * @since 3.0.0 + */ + this.loop = false; + + /** + * Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan). + * + * Always returns zero on iOS / Safari as it doesn't support the stereo panner node. + * + * @name Phaser.Sound.NoAudioSound#pan + * @type {number} + * @default 0 + * @fires Phaser.Sound.Events#PAN + * @since 3.50.0 + */ + this.pan = 0; + + /** + * Object containing markers definitions. + * + * @name Phaser.Sound.NoAudioSound#markers + * @type {Object.} + * @default {} + * @readonly + * @since 3.0.0 + */ + this.markers = {}; + + /** + * Currently playing marker. + * 'null' if whole sound is playing. + * + * @name Phaser.Sound.NoAudioSound#currentMarker + * @type {Phaser.Types.Sound.SoundMarker} + * @default null + * @readonly + * @since 3.0.0 + */ + this.currentMarker = null; + + /** + * Flag indicating if destroy method was called on this sound. + * + * @name Phaser.Sound.NoAudioSound#pendingRemove + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.pendingRemove = false; + }, + + /** + * @method Phaser.Sound.NoAudioSound#addMarker + * @since 3.0.0 + * + * @param {Phaser.Types.Sound.SoundMarker} marker - Marker object. + * + * @return {boolean} false + */ + addMarker: returnFalse, + + /** + * @method Phaser.Sound.NoAudioSound#updateMarker + * @since 3.0.0 + * + * @param {Phaser.Types.Sound.SoundMarker} marker - Marker object with updated values. + * + * @return {boolean} false + */ + updateMarker: returnFalse, + + /** + * @method Phaser.Sound.NoAudioSound#removeMarker + * @since 3.0.0 + * + * @param {string} markerName - The name of the marker to remove. + * + * @return {null} null + */ + removeMarker: returnNull, + + /** + * @method Phaser.Sound.NoAudioSound#play + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Sound.SoundConfig)} [markerName=''] - If you want to play a marker then provide the marker name here. Alternatively, this parameter can be a SoundConfig object. + * @param {Phaser.Types.Sound.SoundConfig} [config] - Optional sound config object to be applied to this marker or entire sound if no marker name is provided. It gets memorized for future plays of current section of the sound. + * + * @return {boolean} false + */ + play: returnFalse, + + /** + * @method Phaser.Sound.NoAudioSound#pause + * @since 3.0.0 + * + * @return {boolean} false + */ + pause: returnFalse, + + /** + * Resumes the sound. + * + * @method Phaser.Sound.NoAudioSound#resume + * @since 3.0.0 + * + * @return {boolean} false + */ + resume: returnFalse, + + /** + * Stop playing this sound. + * + * @method Phaser.Sound.NoAudioSound#stop + * @since 3.0.0 + * + * @return {boolean} false + */ + stop: returnFalse, + + /** + * Sets the muted state of this Sound. + * + * @method Phaser.Sound.NoAudioSound#setMute + * @since 3.4.0 + * + * @param {boolean} value - `true` to mute this sound, `false` to unmute it. + * + * @return {this} This Sound instance. + */ + setMute: returnThis, + + /** + * Sets the volume of this Sound. + * + * @method Phaser.Sound.NoAudioSound#setVolume + * @since 3.4.0 + * + * @param {number} value - The volume of the sound. + * + * @return {this} This Sound instance. + */ + setVolume: returnThis, + + /** + * Sets the playback rate of this Sound. + * + * For example, a value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @method Phaser.Sound.NoAudioSound#setRate + * @since 3.3.0 + * + * @param {number} value - The playback rate at of this Sound. + * + * @return {this} This Sound instance. + */ + setRate: returnThis, + + /** + * Sets the detune value of this Sound, given in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @method Phaser.Sound.NoAudioSound#setDetune + * @since 3.3.0 + * + * @param {number} value - The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @return {this} This Sound instance. + */ + setDetune: returnThis, + + /** + * Seeks to a specific point in this sound. + * + * @method Phaser.Sound.NoAudioSound#setSeek + * @since 3.4.0 + * + * @param {number} value - The point in the sound to seek to. + * + * @return {this} This Sound instance. + */ + setSeek: returnThis, + + /** + * Sets the loop state of this Sound. + * + * @method Phaser.Sound.NoAudioSound#setLoop + * @since 3.4.0 + * + * @param {boolean} value - `true` to loop this sound, `false` to not loop it. + * + * @return {this} This Sound instance. + */ + setLoop: returnThis, + + /** + * Sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan). + * + * Note: iOS / Safari doesn't support the stereo panner node. + * + * @method Phaser.Sound.NoAudioSound#setPan + * @since 3.50.0 + * + * @param {number} value - The pan of the sound. A value between -1 (full left pan) and 1 (full right pan). + * + * @return {this} This Sound instance. + */ + setPan: returnThis, + + /** + * Method used internally for applying config values to some of the sound properties. + * + * @method Phaser.Sound.NoAudioSound#applyConfig + * @since 3.0.0 + */ + applyConfig: returnNull, + + /** + * Method used internally for resetting values of some of the config properties. + * + * @method Phaser.Sound.NoAudioSound#resetConfig + * @since 3.0.0 + */ + resetConfig: returnNull, + + /** + * Update method called automatically by sound manager on every game step. + * + * @method Phaser.Sound.NoAudioSound#update + * @override + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time elapsed since the last frame. + */ + update: NOOP, + + /** + * Method used internally to calculate total playback rate of the sound. + * + * @method Phaser.Sound.NoAudioSound#calculateRate + * @since 3.0.0 + */ + calculateRate: returnNull, + + /** + * Destroys this sound and all associated events and marks it for removal from the sound manager. + * + * @method Phaser.Sound.NoAudioSound#destroy + * @fires Phaser.Sound.Events#DESTROY + * @since 3.0.0 + */ + destroy: function () + { + BaseSound.prototype.destroy.call(this); + } + +}); + +module.exports = NoAudioSound; + + +/***/ }), + +/***/ 25960: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseSoundManager = __webpack_require__(85034); +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var NoAudioSound = __webpack_require__(4603); +var NOOP = __webpack_require__(29747); + +/** + * @classdesc + * No-audio implementation of the Sound Manager. It is used if audio has been + * disabled in the game config or the device doesn't support any audio. + * + * It represents a graceful degradation of Sound Manager logic that provides + * minimal functionality and prevents Phaser projects that use audio from + * breaking on devices that don't support any audio playback technologies. + * + * @class NoAudioSoundManager + * @extends Phaser.Sound.BaseSoundManager + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - Reference to the current game instance. + */ +var NoAudioSoundManager = new Class({ + + Extends: EventEmitter, + + initialize: + + function NoAudioSoundManager (game) + { + EventEmitter.call(this); + + this.game = game; + this.sounds = []; + this.mute = false; + this.volume = 1; + this.rate = 1; + this.detune = 0; + this.pauseOnBlur = true; + this.locked = false; + }, + + /** + * Adds a new sound into the sound manager. + * + * @method Phaser.Sound.NoAudioSoundManager#add + * @since 3.60.0 + * + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {Phaser.Sound.NoAudioSound} The new sound instance. + */ + add: function (key, config) + { + var sound = new NoAudioSound(this, key, config); + + this.sounds.push(sound); + + return sound; + }, + + /** + * Adds a new audio sprite sound into the sound manager. + * Audio Sprites are a combination of audio files and a JSON configuration. + * The JSON follows the format of that created by https://github.com/tonistiigi/audiosprite + * + * @method Phaser.Sound.NoAudioSoundManager#addAudioSprite + * @since 3.60.0 + * + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {Phaser.Sound.NoAudioSound} The new audio sprite sound instance. + */ + addAudioSprite: function (key, config) + { + var sound = this.add(key, config); + + sound.spritemap = {}; + + return sound; + }, + + /** + * Gets the first sound in the manager matching the given key, if any. + * + * @method Phaser.Sound.NoAudioSoundManager#get + * @since 3.23.0 + * + * @generic {Phaser.Sound.BaseSound} T + * @genericUse {T} - [$return] + * + * @param {string} key - Sound asset key. + * + * @return {?Phaser.Sound.BaseSound} - The sound, or null. + */ + get: function (key) + { + return BaseSoundManager.prototype.get.call(this, key); + }, + + /** + * Gets any sounds in the manager matching the given key. + * + * @method Phaser.Sound.NoAudioSoundManager#getAll + * @since 3.23.0 + * + * @generic {Phaser.Sound.BaseSound} T + * @genericUse {T[]} - [$return] + * + * @param {string} key - Sound asset key. + * + * @return {Phaser.Sound.BaseSound[]} - The sounds, or an empty array. + */ + getAll: function (key) + { + return BaseSoundManager.prototype.getAll.call(this, key); + }, + + /** + * This method does nothing but return 'false' for the No Audio Sound Manager, to maintain + * compatibility with the other Sound Managers. + * + * @method Phaser.Sound.NoAudioSoundManager#play + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {(Phaser.Types.Sound.SoundConfig|Phaser.Types.Sound.SoundMarker)} [extra] - An optional additional object containing settings to be applied to the sound. It could be either config or marker object. + * + * @return {boolean} Always 'false' for the No Audio Sound Manager. + */ + // eslint-disable-next-line no-unused-vars + play: function (key, extra) + { + return false; + }, + + /** + * This method does nothing but return 'false' for the No Audio Sound Manager, to maintain + * compatibility with the other Sound Managers. + * + * @method Phaser.Sound.NoAudioSoundManager#playAudioSprite + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {string} spriteName - The name of the sound sprite to play. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {boolean} Always 'false' for the No Audio Sound Manager. + */ + // eslint-disable-next-line no-unused-vars + playAudioSprite: function (key, spriteName, config) + { + return false; + }, + + /** + * Removes a sound from the sound manager. + * The removed sound is destroyed before removal. + * + * @method Phaser.Sound.NoAudioSoundManager#remove + * @since 3.0.0 + * + * @param {Phaser.Sound.BaseSound} sound - The sound object to remove. + * + * @return {boolean} True if the sound was removed successfully, otherwise false. + */ + remove: function (sound) + { + return BaseSoundManager.prototype.remove.call(this, sound); + }, + + /** + * Removes all sounds from the manager, destroying the sounds. + * + * @method Phaser.Sound.NoAudioSoundManager#removeAll + * @since 3.23.0 + */ + removeAll: function () + { + return BaseSoundManager.prototype.removeAll.call(this); + }, + + /** + * Removes all sounds from the sound manager that have an asset key matching the given value. + * The removed sounds are destroyed before removal. + * + * @method Phaser.Sound.NoAudioSoundManager#removeByKey + * @since 3.0.0 + * + * @param {string} key - The key to match when removing sound objects. + * + * @return {number} The number of matching sound objects that were removed. + */ + removeByKey: function (key) + { + return BaseSoundManager.prototype.removeByKey.call(this, key); + }, + + /** + * Stops any sounds matching the given key. + * + * @method Phaser.Sound.NoAudioSoundManager#stopByKey + * @since 3.23.0 + * + * @param {string} key - Sound asset key. + * + * @return {number} - How many sounds were stopped. + */ + stopByKey: function (key) + { + return BaseSoundManager.prototype.stopByKey.call(this, key); + }, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#onBlur + * @since 3.0.0 + */ + onBlur: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#onFocus + * @since 3.0.0 + */ + onFocus: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#onGameBlur + * @since 3.0.0 + */ + onGameBlur: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#onGameFocus + * @since 3.0.0 + */ + onGameFocus: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#pauseAll + * @since 3.0.0 + */ + pauseAll: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#resumeAll + * @since 3.0.0 + */ + resumeAll: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#stopAll + * @since 3.0.0 + */ + stopAll: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#update + * @since 3.0.0 + */ + update: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#setRate + * @since 3.0.0 + * + * @return {this} This Sound Manager. + */ + setRate: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#setDetune + * @since 3.0.0 + * + * @return {this} This Sound Manager. + */ + setDetune: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#setMute + * @since 3.0.0 + */ + setMute: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#setVolume + * @since 3.0.0 + */ + setVolume: NOOP, + + /** + * Empty function for the No Audio Sound Manager. + * + * @method Phaser.Sound.NoAudioSoundManager#unlock + * @since 3.0.0 + */ + unlock: NOOP, + + /** + * Method used internally for iterating only over active sounds and skipping sounds that are marked for removal. + * + * @method Phaser.Sound.NoAudioSoundManager#forEachActiveSound + * @private + * @since 3.0.0 + * + * @param {Phaser.Types.Sound.EachActiveSoundCallback} callback - Callback function. (manager: Phaser.Sound.BaseSoundManager, sound: Phaser.Sound.BaseSound, index: number, sounds: Phaser.Manager.BaseSound[]) => void + * @param {*} [scope] - Callback context. + */ + forEachActiveSound: function (callbackfn, scope) + { + BaseSoundManager.prototype.forEachActiveSound.call(this, callbackfn, scope); + }, + + /** + * Destroys all the sounds in the game and all associated events. + * + * @method Phaser.Sound.NoAudioSoundManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + BaseSoundManager.prototype.destroy.call(this); + } + +}); + +module.exports = NoAudioSoundManager; + + +/***/ }), + +/***/ 71741: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseSound = __webpack_require__(30341); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(14463); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * Web Audio API implementation of the sound. + * + * @class WebAudioSound + * @extends Phaser.Sound.BaseSound + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Sound.WebAudioSoundManager} manager - Reference to the WebAudio Sound Manager that owns this Sound instance. + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config={}] - An optional config object containing default sound settings. + */ +var WebAudioSound = new Class({ + + Extends: BaseSound, + + initialize: + + function WebAudioSound (manager, key, config) + { + if (config === undefined) { config = {}; } + + /** + * Audio buffer containing decoded data of the audio asset to be played. + * + * @name Phaser.Sound.WebAudioSound#audioBuffer + * @type {AudioBuffer} + * @since 3.0.0 + */ + this.audioBuffer = manager.game.cache.audio.get(key); + + if (!this.audioBuffer) + { + throw new Error('Audio key "' + key + '" not found in cache'); + } + + /** + * A reference to an audio source node used for playing back audio from + * audio data stored in Phaser.Sound.WebAudioSound#audioBuffer. + * + * @name Phaser.Sound.WebAudioSound#source + * @type {AudioBufferSourceNode} + * @default null + * @since 3.0.0 + */ + this.source = null; + + /** + * A reference to a second audio source used for gapless looped playback. + * + * @name Phaser.Sound.WebAudioSound#loopSource + * @type {AudioBufferSourceNode} + * @default null + * @since 3.0.0 + */ + this.loopSource = null; + + /** + * Gain node responsible for controlling this sound's muting. + * + * @name Phaser.Sound.WebAudioSound#muteNode + * @type {GainNode} + * @since 3.0.0 + */ + this.muteNode = manager.context.createGain(); + + /** + * Gain node responsible for controlling this sound's volume. + * + * @name Phaser.Sound.WebAudioSound#volumeNode + * @type {GainNode} + * @since 3.0.0 + */ + this.volumeNode = manager.context.createGain(); + + /** + * Panner node responsible for controlling this sound's pan. + * + * Doesn't work on iOS / Safari. + * + * @name Phaser.Sound.WebAudioSound#pannerNode + * @type {StereoPannerNode} + * @since 3.50.0 + */ + this.pannerNode = null; + + /** + * The Stereo Spatial Panner node. + * + * @name Phaser.Sound.WebAudioSound#spatialNode + * @type {PannerNode} + * @since 3.60.0 + */ + this.spatialNode = null; + + /** + * If the Spatial Panner node has been set to track a vector or + * Game Object, this retains a reference to it. + * + * @name Phaser.Sound.WebAudioSound#spatialSource + * @type {Phaser.Types.Math.Vector2Like} + * @since 3.60.0 + */ + this.spatialSource = null; + + /** + * The time at which the sound should have started playback from the beginning. + * + * Treat this property as read-only. + * + * Based on `BaseAudioContext.currentTime` value. + * + * @name Phaser.Sound.WebAudioSound#playTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.playTime = 0; + + /** + * The time at which the sound source should have actually started playback. + * + * Treat this property as read-only. + * + * Based on `BaseAudioContext.currentTime` value. + * + * @name Phaser.Sound.WebAudioSound#startTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.startTime = 0; + + /** + * The time at which the sound loop source should actually start playback. + * + * Based on `BaseAudioContext.currentTime` value. + * + * @name Phaser.Sound.WebAudioSound#loopTime + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.loopTime = 0; + + /** + * An array where we keep track of all rate updates during playback. + * + * Treat this property as read-only. + * + * Array of object types: `{ time: number, rate: number }` + * + * @name Phaser.Sound.WebAudioSound#rateUpdates + * @type {array} + * @default [] + * @since 3.0.0 + */ + this.rateUpdates = []; + + /** + * Used for keeping track when sound source playback has ended + * so its state can be updated accordingly. + * + * @name Phaser.Sound.WebAudioSound#hasEnded + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.hasEnded = false; + + /** + * Used for keeping track when sound source has looped + * so its state can be updated accordingly. + * + * @name Phaser.Sound.WebAudioSound#hasLooped + * @type {boolean} + * @readonly + * @default false + * @since 3.0.0 + */ + this.hasLooped = false; + + this.muteNode.connect(this.volumeNode); + + if (manager.context.createPanner) + { + this.spatialNode = manager.context.createPanner(); + + this.volumeNode.connect(this.spatialNode); + } + + if (manager.context.createStereoPanner) + { + this.pannerNode = manager.context.createStereoPanner(); + + if (manager.context.createPanner) + { + this.spatialNode.connect(this.pannerNode); + } + else + { + this.volumeNode.connect(this.pannerNode); + } + + this.pannerNode.connect(manager.destination); + } + else if (manager.context.createPanner) + { + this.spatialNode.connect(manager.destination); + } + else + { + this.volumeNode.connect(manager.destination); + } + + this.duration = this.audioBuffer.duration; + + this.totalDuration = this.audioBuffer.duration; + + BaseSound.call(this, manager, key, config); + }, + + /** + * Play this sound, or a marked section of it. + * + * It always plays the sound from the start. If you want to start playback from a specific time + * you can set 'seek' setting of the config object, provided to this call, to that value. + * + * If you want to play the same sound simultaneously, then you need to create another instance + * of it and play that Sound. + * + * @method Phaser.Sound.WebAudioSound#play + * @fires Phaser.Sound.Events#PLAY + * @since 3.0.0 + * + * @param {(string|Phaser.Types.Sound.SoundConfig)} [markerName=''] - If you want to play a marker then provide the marker name here. Alternatively, this parameter can be a SoundConfig object. + * @param {Phaser.Types.Sound.SoundConfig} [config] - Optional sound config object to be applied to this marker or entire sound if no marker name is provided. It gets memorized for future plays of current section of the sound. + * + * @return {boolean} Whether the sound started playing successfully. + */ + play: function (markerName, config) + { + if (!BaseSound.prototype.play.call(this, markerName, config)) + { + return false; + } + + // \/\/\/ isPlaying = true, isPaused = false \/\/\/ + this.stopAndRemoveBufferSource(); + this.createAndStartBufferSource(); + + this.emit(Events.PLAY, this); + + return true; + }, + + /** + * Pauses the sound. + * + * @method Phaser.Sound.WebAudioSound#pause + * @fires Phaser.Sound.Events#PAUSE + * @since 3.0.0 + * + * @return {boolean} Whether the sound was paused successfully. + */ + pause: function () + { + if (this.manager.context.currentTime < this.startTime) + { + return false; + } + + if (!BaseSound.prototype.pause.call(this)) + { + return false; + } + + // \/\/\/ isPlaying = false, isPaused = true \/\/\/ + this.currentConfig.seek = this.getCurrentTime(); // Equivalent to setting paused time + this.stopAndRemoveBufferSource(); + + this.emit(Events.PAUSE, this); + + return true; + }, + + /** + * Resumes the sound. + * + * @method Phaser.Sound.WebAudioSound#resume + * @fires Phaser.Sound.Events#RESUME + * @since 3.0.0 + * + * @return {boolean} Whether the sound was resumed successfully. + */ + resume: function () + { + if (this.manager.context.currentTime < this.startTime) + { + return false; + } + + if (!BaseSound.prototype.resume.call(this)) + { + return false; + } + + // \/\/\/ isPlaying = true, isPaused = false \/\/\/ + this.createAndStartBufferSource(); + + this.emit(Events.RESUME, this); + + return true; + }, + + /** + * Stop playing this sound. + * + * @method Phaser.Sound.WebAudioSound#stop + * @fires Phaser.Sound.Events#STOP + * @since 3.0.0 + * + * @return {boolean} Whether the sound was stopped successfully. + */ + stop: function () + { + if (!BaseSound.prototype.stop.call(this)) + { + return false; + } + + // \/\/\/ isPlaying = false, isPaused = false \/\/\/ + this.stopAndRemoveBufferSource(); + + this.emit(Events.STOP, this); + + return true; + }, + + /** + * Used internally. + * + * @method Phaser.Sound.WebAudioSound#createAndStartBufferSource + * @private + * @since 3.0.0 + */ + createAndStartBufferSource: function () + { + var seek = this.currentConfig.seek; + var delay = this.currentConfig.delay; + var when = this.manager.context.currentTime + delay; + var offset = (this.currentMarker ? this.currentMarker.start : 0) + seek; + var duration = this.duration - seek; + + this.playTime = when - seek; + this.startTime = when; + this.source = this.createBufferSource(); + + this.applyConfig(); + + this.source.start(Math.max(0, when), Math.max(0, offset), Math.max(0, duration)); + + this.resetConfig(); + }, + + /** + * This method is only used internally and it creates a looping buffer source. + * + * @method Phaser.Sound.WebAudioSound#createAndStartLoopBufferSource + * @since 3.0.0 + */ + createAndStartLoopBufferSource: function () + { + var when = this.getLoopTime(); + var offset = this.currentMarker ? this.currentMarker.start : 0; + var duration = this.duration; + + this.loopTime = when; + this.loopSource = this.createBufferSource(); + this.loopSource.playbackRate.setValueAtTime(this.totalRate, 0); + this.loopSource.start(Math.max(0, when), Math.max(0, offset), Math.max(0, duration)); + }, + + /** + * This method is only used internally and it creates a buffer source. + * + * @method Phaser.Sound.WebAudioSound#createBufferSource + * @since 3.0.0 + * + * @return {AudioBufferSourceNode} + */ + createBufferSource: function () + { + var _this = this; + var source = this.manager.context.createBufferSource(); + + source.buffer = this.audioBuffer; + + source.connect(this.muteNode); + + source.onended = function (ev) + { + var target = ev.target; + + if (target === _this.source || target === _this.loopSource) + { + // sound ended + if (_this.currentConfig.loop) + { + _this.hasLooped = true; + } + else + { + _this.hasEnded = true; + } + } + + // else was stopped + }; + + return source; + }, + + /** + * This method is only used internally and it stops and removes a buffer source. + * + * @method Phaser.Sound.WebAudioSound#stopAndRemoveBufferSource + * @since 3.0.0 + */ + stopAndRemoveBufferSource: function () + { + if (this.source) + { + var tempSource = this.source; + + this.source = null; + + tempSource.stop(); + tempSource.disconnect(); + } + + this.playTime = 0; + this.startTime = 0; + this.hasEnded = false; + + this.stopAndRemoveLoopBufferSource(); + }, + + /** + * This method is only used internally and it stops and removes a looping buffer source. + * + * @method Phaser.Sound.WebAudioSound#stopAndRemoveLoopBufferSource + * @since 3.0.0 + */ + stopAndRemoveLoopBufferSource: function () + { + if (this.loopSource) + { + this.loopSource.stop(); + this.loopSource.disconnect(); + this.loopSource = null; + } + + this.loopTime = 0; + }, + + /** + * Method used internally for applying config values to some of the sound properties. + * + * @method Phaser.Sound.WebAudioSound#applyConfig + * @since 3.0.0 + */ + applyConfig: function () + { + this.rateUpdates.length = 0; + + this.rateUpdates.push({ + time: 0, + rate: 1 + }); + + var source = this.currentConfig.source; + + if (source && this.manager.context.createPanner) + { + var node = this.spatialNode; + + node.panningModel = GetFastValue(source, 'panningModel', 'equalpower'); + node.distanceModel = GetFastValue(source, 'distanceModel', 'inverse'); + node.orientationX.value = GetFastValue(source, 'orientationX', 0); + node.orientationY.value = GetFastValue(source, 'orientationY', 0); + node.orientationZ.value = GetFastValue(source, 'orientationZ', -1); + node.refDistance = GetFastValue(source, 'refDistance', 1); + node.maxDistance = GetFastValue(source, 'maxDistance', 10000); + node.rolloffFactor = GetFastValue(source, 'rolloffFactor', 1); + node.coneInnerAngle = GetFastValue(source, 'coneInnerAngle', 360); + node.coneOuterAngle = GetFastValue(source, 'coneOuterAngle', 0); + node.coneOuterGain = GetFastValue(source, 'coneOuterGain', 0); + + this.spatialSource = GetFastValue(source, 'follow', null); + + if (!this.spatialSource) + { + node.positionX.value = GetFastValue(source, 'x', 0); + node.positionY.value = GetFastValue(source, 'y', 0); + node.positionZ.value = GetFastValue(source, 'z', 0); + } + } + + BaseSound.prototype.applyConfig.call(this); + }, + + /** + * Sets the x position of this Sound in Spatial Audio space. + * + * This only has any effect if the sound was created with a SpatialSoundConfig object. + * + * Also see the `WebAudioSoundManager.setListenerPosition` method. + * + * If you find that the sound becomes too quiet, too quickly, as it moves away from + * the listener, then try different `refDistance` property values when configuring + * the spatial sound. + * + * @name Phaser.Sound.WebAudioSound#x + * @type {number} + * @since 3.60.0 + */ + x: { + + get: function () + { + if (this.spatialNode) + { + return this.spatialNode.positionX; + } + else + { + return 0; + } + }, + + set: function (value) + { + if (this.spatialNode) + { + this.spatialNode.positionX.value = value; + } + } + }, + + /** + * Sets the y position of this Sound in Spatial Audio space. + * + * This only has any effect if the sound was created with a SpatialSoundConfig object. + * + * Also see the `WebAudioSoundManager.setListenerPosition` method. + * + * If you find that the sound becomes too quiet, too quickly, as it moves away from + * the listener, then try different `refDistance` property values when configuring + * the spatial sound. + * + * @name Phaser.Sound.WebAudioSound#y + * @type {number} + * @since 3.60.0 + */ + y: { + + get: function () + { + if (this.spatialNode) + { + return this.spatialNode.positionY; + } + else + { + return 0; + } + }, + + set: function (value) + { + if (this.spatialNode) + { + this.spatialNode.positionY.value = value; + } + } + }, + + /** + * Update method called automatically by sound manager on every game step. + * + * @method Phaser.Sound.WebAudioSound#update + * @fires Phaser.Sound.Events#COMPLETE + * @fires Phaser.Sound.Events#LOOPED + * @since 3.0.0 + */ + update: function () + { + if (this.isPlaying && this.spatialSource) + { + var x = GetFastValue(this.spatialSource, 'x', null); + var y = GetFastValue(this.spatialSource, 'y', null); + + if (x && x !== this._spatialx) + { + this._spatialx = this.spatialNode.positionX.value = x; + } + if (y && y !== this._spatialy) + { + this._spatialy = this.spatialNode.positionY.value = y; + } + } + + if (this.hasEnded) + { + BaseSound.prototype.stop.call(this); + + this.stopAndRemoveBufferSource(); + + this.emit(Events.COMPLETE, this); + } + else if (this.hasLooped) + { + this.hasLooped = false; + this.source = this.loopSource; + this.loopSource = null; + this.playTime = this.startTime = this.loopTime; + this.rateUpdates.length = 0; + + this.rateUpdates.push({ + time: 0, + rate: this.totalRate + }); + + this.createAndStartLoopBufferSource(); + + this.emit(Events.LOOPED, this); + } + }, + + /** + * Calls Phaser.Sound.BaseSound#destroy method + * and cleans up all Web Audio API related stuff. + * + * @method Phaser.Sound.WebAudioSound#destroy + * @since 3.0.0 + */ + destroy: function () + { + if (this.pendingRemove) + { + return; + } + + BaseSound.prototype.destroy.call(this); + + this.audioBuffer = null; + this.stopAndRemoveBufferSource(); + this.muteNode.disconnect(); + this.muteNode = null; + this.volumeNode.disconnect(); + this.volumeNode = null; + + if (this.pannerNode) + { + this.pannerNode.disconnect(); + this.pannerNode = null; + } + + if (this.spatialNode) + { + this.spatialNode.disconnect(); + this.spatialNode = null; + this.spatialSource = null; + } + + this.rateUpdates.length = 0; + this.rateUpdates = null; + }, + + /** + * Method used internally to calculate total playback rate of the sound. + * + * @method Phaser.Sound.WebAudioSound#calculateRate + * @since 3.0.0 + */ + calculateRate: function () + { + BaseSound.prototype.calculateRate.call(this); + + var now = this.manager.context.currentTime; + + if (this.source && typeof this.totalRate === 'number') + { + this.source.playbackRate.setValueAtTime(this.totalRate, now); + } + + if (this.isPlaying) + { + this.rateUpdates.push({ + time: Math.max(this.startTime, now) - this.playTime, + rate: this.totalRate + }); + + if (this.loopSource) + { + this.stopAndRemoveLoopBufferSource(); + this.createAndStartLoopBufferSource(); + } + } + }, + + /** + * Method used internally for calculating current playback time of a playing sound. + * + * @method Phaser.Sound.WebAudioSound#getCurrentTime + * @since 3.0.0 + */ + getCurrentTime: function () + { + var currentTime = 0; + + for (var i = 0; i < this.rateUpdates.length; i++) + { + var nextTime = 0; + + if (i < this.rateUpdates.length - 1) + { + nextTime = this.rateUpdates[i + 1].time; + } + else + { + nextTime = this.manager.context.currentTime - this.playTime; + } + + currentTime += (nextTime - this.rateUpdates[i].time) * this.rateUpdates[i].rate; + } + + return currentTime; + }, + + /** + * Method used internally for calculating the time + * at witch the loop source should start playing. + * + * @method Phaser.Sound.WebAudioSound#getLoopTime + * @since 3.0.0 + */ + getLoopTime: function () + { + var lastRateUpdateCurrentTime = 0; + + for (var i = 0; i < this.rateUpdates.length - 1; i++) + { + lastRateUpdateCurrentTime += (this.rateUpdates[i + 1].time - this.rateUpdates[i].time) * this.rateUpdates[i].rate; + } + + var lastRateUpdate = this.rateUpdates[this.rateUpdates.length - 1]; + + return this.playTime + lastRateUpdate.time + (this.duration - lastRateUpdateCurrentTime) / lastRateUpdate.rate; + }, + + /** + * Rate at which this Sound will be played. + * Value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @name Phaser.Sound.WebAudioSound#rate + * @type {number} + * @default 1 + * @fires Phaser.Sound.Events#RATE + * @since 3.0.0 + */ + rate: { + + get: function () + { + return this.currentConfig.rate; + }, + + set: function (value) + { + this.currentConfig.rate = value; + + this.calculateRate(); + + this.emit(Events.RATE, this, value); + } + + }, + + /** + * Sets the playback rate of this Sound. + * + * For example, a value of 1.0 plays the audio at full speed, 0.5 plays the audio at half speed + * and 2.0 doubles the audios playback speed. + * + * @method Phaser.Sound.WebAudioSound#setRate + * @fires Phaser.Sound.Events#RATE + * @since 3.3.0 + * + * @param {number} value - The playback rate at of this Sound. + * + * @return {this} This Sound instance. + */ + setRate: function (value) + { + this.rate = value; + + return this; + }, + + /** + * The detune value of this Sound, given in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @name Phaser.Sound.WebAudioSound#detune + * @type {number} + * @default 0 + * @fires Phaser.Sound.Events#DETUNE + * @since 3.0.0 + */ + detune: { + + get: function () + { + return this.currentConfig.detune; + }, + + set: function (value) + { + this.currentConfig.detune = value; + + this.calculateRate(); + + this.emit(Events.DETUNE, this, value); + } + + }, + + /** + * Sets the detune value of this Sound, given in [cents](https://en.wikipedia.org/wiki/Cent_%28music%29). + * The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @method Phaser.Sound.WebAudioSound#setDetune + * @fires Phaser.Sound.Events#DETUNE + * @since 3.3.0 + * + * @param {number} value - The range of the value is -1200 to 1200, but we recommend setting it to [50](https://en.wikipedia.org/wiki/50_Cent). + * + * @return {this} This Sound instance. + */ + setDetune: function (value) + { + this.detune = value; + + return this; + }, + + /** + * Boolean indicating whether the sound is muted or not. + * Gets or sets the muted state of this sound. + * + * @name Phaser.Sound.WebAudioSound#mute + * @type {boolean} + * @default false + * @fires Phaser.Sound.Events#MUTE + * @since 3.0.0 + */ + mute: { + + get: function () + { + return (this.muteNode.gain.value === 0); + }, + + set: function (value) + { + this.currentConfig.mute = value; + this.muteNode.gain.setValueAtTime(value ? 0 : 1, 0); + + this.emit(Events.MUTE, this, value); + } + + }, + + /** + * Sets the muted state of this Sound. + * + * @method Phaser.Sound.WebAudioSound#setMute + * @fires Phaser.Sound.Events#MUTE + * @since 3.4.0 + * + * @param {boolean} value - `true` to mute this sound, `false` to unmute it. + * + * @return {this} This Sound instance. + */ + setMute: function (value) + { + this.mute = value; + + return this; + }, + + /** + * Gets or sets the volume of this sound, a value between 0 (silence) and 1 (full volume). + * + * @name Phaser.Sound.WebAudioSound#volume + * @type {number} + * @default 1 + * @fires Phaser.Sound.Events#VOLUME + * @since 3.0.0 + */ + volume: { + + get: function () + { + return this.volumeNode.gain.value; + }, + + set: function (value) + { + this.currentConfig.volume = value; + this.volumeNode.gain.setValueAtTime(value, 0); + + this.emit(Events.VOLUME, this, value); + } + }, + + /** + * Sets the volume of this Sound. + * + * @method Phaser.Sound.WebAudioSound#setVolume + * @fires Phaser.Sound.Events#VOLUME + * @since 3.4.0 + * + * @param {number} value - The volume of the sound. + * + * @return {this} This Sound instance. + */ + setVolume: function (value) + { + this.volume = value; + + return this; + }, + + /** + * Property representing the position of playback for this sound, in seconds. + * Setting it to a specific value moves current playback to that position. + * The value given is clamped to the range 0 to current marker duration. + * Setting seek of a stopped sound has no effect. + * + * @name Phaser.Sound.WebAudioSound#seek + * @type {number} + * @fires Phaser.Sound.Events#SEEK + * @since 3.0.0 + */ + seek: { + + get: function () + { + if (this.isPlaying) + { + if (this.manager.context.currentTime < this.startTime) + { + return this.startTime - this.playTime; + } + + return this.getCurrentTime(); + } + else if (this.isPaused) + { + return this.currentConfig.seek; + } + else + { + return 0; + } + }, + + set: function (value) + { + if (this.manager.context.currentTime < this.startTime) + { + return; + } + + if (this.isPlaying || this.isPaused) + { + value = Math.min(Math.max(0, value), this.duration); + + this.currentConfig.seek = value; + + if (this.isPlaying) + { + this.stopAndRemoveBufferSource(); + this.createAndStartBufferSource(); + } + + this.emit(Events.SEEK, this, value); + } + } + }, + + /** + * Seeks to a specific point in this sound. + * + * @method Phaser.Sound.WebAudioSound#setSeek + * @fires Phaser.Sound.Events#SEEK + * @since 3.4.0 + * + * @param {number} value - The point in the sound to seek to. + * + * @return {this} This Sound instance. + */ + setSeek: function (value) + { + this.seek = value; + + return this; + }, + + /** + * Flag indicating whether or not the sound or current sound marker will loop. + * + * @name Phaser.Sound.WebAudioSound#loop + * @type {boolean} + * @default false + * @fires Phaser.Sound.Events#LOOP + * @since 3.0.0 + */ + loop: { + + get: function () + { + return this.currentConfig.loop; + }, + + set: function (value) + { + this.currentConfig.loop = value; + + if (this.isPlaying) + { + this.stopAndRemoveLoopBufferSource(); + + if (value) + { + this.createAndStartLoopBufferSource(); + } + } + + this.emit(Events.LOOP, this, value); + } + }, + + /** + * Sets the loop state of this Sound. + * + * @method Phaser.Sound.WebAudioSound#setLoop + * @fires Phaser.Sound.Events#LOOP + * @since 3.4.0 + * + * @param {boolean} value - `true` to loop this sound, `false` to not loop it. + * + * @return {this} This Sound instance. + */ + setLoop: function (value) + { + this.loop = value; + + return this; + }, + + /** + * Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan). + * + * Always returns zero on iOS / Safari as it doesn't support the stereo panner node. + * + * @name Phaser.Sound.WebAudioSound#pan + * @type {number} + * @default 0 + * @fires Phaser.Sound.Events#PAN + * @since 3.50.0 + */ + pan: { + + get: function () + { + if (this.pannerNode) + { + return this.pannerNode.pan.value; + } + else + { + return 0; + } + }, + + set: function (value) + { + this.currentConfig.pan = value; + + if (this.pannerNode) + { + this.pannerNode.pan.setValueAtTime(value, this.manager.context.currentTime); + } + + this.emit(Events.PAN, this, value); + } + }, + + /** + * Sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan). + * + * Note: iOS / Safari doesn't support the stereo panner node. + * + * @method Phaser.Sound.WebAudioSound#setPan + * @fires Phaser.Sound.Events#PAN + * @since 3.50.0 + * + * @param {number} value - The pan of the sound. A value between -1 (full left pan) and 1 (full right pan). + * + * @return {this} This Sound instance. + */ + setPan: function (value) + { + this.pan = value; + + return this; + } + +}); + +module.exports = WebAudioSound; + + +/***/ }), + +/***/ 57490: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Pavle Goloskokovic (http://prunegames.com) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Base64ToArrayBuffer = __webpack_require__(53134); +var BaseSoundManager = __webpack_require__(85034); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(14463); +var GameEvents = __webpack_require__(8443); +var WebAudioSound = __webpack_require__(71741); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * Web Audio API implementation of the Sound Manager. + * + * Not all browsers can play all audio formats. + * + * There is a good guide to what's supported: [Cross-browser audio basics: Audio codec support](https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery/Cross-browser_audio_basics#Audio_Codec_Support). + * + * @class WebAudioSoundManager + * @extends Phaser.Sound.BaseSoundManager + * @memberof Phaser.Sound + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - Reference to the current game instance. + */ +var WebAudioSoundManager = new Class({ + + Extends: BaseSoundManager, + + initialize: + + function WebAudioSoundManager (game) + { + /** + * The AudioContext being used for playback. + * + * @name Phaser.Sound.WebAudioSoundManager#context + * @type {AudioContext} + * @since 3.0.0 + */ + this.context = this.createAudioContext(game); + + /** + * Gain node responsible for controlling global muting. + * + * @name Phaser.Sound.WebAudioSoundManager#masterMuteNode + * @type {GainNode} + * @since 3.0.0 + */ + this.masterMuteNode = this.context.createGain(); + + /** + * Gain node responsible for controlling global volume. + * + * @name Phaser.Sound.WebAudioSoundManager#masterVolumeNode + * @type {GainNode} + * @since 3.0.0 + */ + this.masterVolumeNode = this.context.createGain(); + + this.masterMuteNode.connect(this.masterVolumeNode); + + this.masterVolumeNode.connect(this.context.destination); + + /** + * Destination node for connecting individual sounds to. + * + * @name Phaser.Sound.WebAudioSoundManager#destination + * @type {AudioNode} + * @since 3.0.0 + */ + this.destination = this.masterMuteNode; + + this.locked = this.context.state === 'suspended'; + + BaseSoundManager.call(this, game); + + if (this.locked) + { + if (game.isBooted) + { + this.unlock(); + } + else + { + game.events.once(GameEvents.BOOT, this.unlock, this); + } + } + + game.events.on(GameEvents.VISIBLE, this.onGameVisible, this); + }, + + /** + * Internal handler for Phaser.Core.Events#VISIBLE. + * + * Needed to handle resuming audio on iOS17/iOS18+ if you hide the browser, press + * the home button, etc. See https://github.com/phaserjs/phaser/issues/6829 + * + * @method Phaser.Sound.WebAudioSoundManager#onGameVisible + * @private + * @since 3.88.0 + */ + onGameVisible: function () + { + var context = this.context; + + // setTimeout to avoid weird audio artifacts (thanks Apple) + window.setTimeout(function () { + + if (context) + { + context.suspend(); + context.resume(); + } + + }, 100); + }, + + /** + * Method responsible for instantiating and returning AudioContext instance. + * If an instance of an AudioContext class was provided through the game config, + * that instance will be returned instead. This can come in handy if you are reloading + * a Phaser game on a page that never properly refreshes (such as in an SPA project) + * and you want to reuse already instantiated AudioContext. + * + * @method Phaser.Sound.WebAudioSoundManager#createAudioContext + * @since 3.0.0 + * + * @param {Phaser.Game} game - Reference to the current game instance. + * + * @return {AudioContext} The AudioContext instance to be used for playback. + */ + createAudioContext: function (game) + { + var audioConfig = game.config.audio; + + if (audioConfig.context) + { + audioConfig.context.resume(); + + return audioConfig.context; + } + + if (window.hasOwnProperty('AudioContext')) + { + return new AudioContext(); + } + else if (window.hasOwnProperty('webkitAudioContext')) + { + return new window.webkitAudioContext(); + } + }, + + /** + * This method takes a new AudioContext reference and then sets + * this Sound Manager to use that context for all playback. + * + * As part of this call it also disconnects the master mute and volume + * nodes and then re-creates them on the new given context. + * + * @method Phaser.Sound.WebAudioSoundManager#setAudioContext + * @since 3.21.0 + * + * @param {AudioContext} context - Reference to an already created AudioContext instance. + * + * @return {this} The WebAudioSoundManager instance. + */ + setAudioContext: function (context) + { + if (this.context) + { + this.context.close(); + } + + if (this.masterMuteNode) + { + this.masterMuteNode.disconnect(); + } + + if (this.masterVolumeNode) + { + this.masterVolumeNode.disconnect(); + } + + this.context = context; + + this.masterMuteNode = context.createGain(); + this.masterVolumeNode = context.createGain(); + + this.masterMuteNode.connect(this.masterVolumeNode); + this.masterVolumeNode.connect(context.destination); + + this.destination = this.masterMuteNode; + + return this; + }, + + /** + * Adds a new sound into the sound manager. + * + * @method Phaser.Sound.WebAudioSoundManager#add + * @since 3.0.0 + * + * @param {string} key - Asset key for the sound. + * @param {Phaser.Types.Sound.SoundConfig} [config] - An optional config object containing default sound settings. + * + * @return {Phaser.Sound.WebAudioSound} The new sound instance. + */ + add: function (key, config) + { + var sound = new WebAudioSound(this, key, config); + + this.sounds.push(sound); + + return sound; + }, + + /** + * Decode audio data into a format ready for playback via Web Audio. + * + * The audio data can be a base64 encoded string, an audio media-type data uri, or an ArrayBuffer instance. + * + * The `audioKey` is the key that will be used to save the decoded audio to the audio cache. + * + * Instead of passing a single entry you can instead pass an array of `Phaser.Types.Sound.DecodeAudioConfig` + * objects as the first and only argument. + * + * Decoding is an async process, so be sure to listen for the events to know when decoding has completed. + * + * Once the audio has decoded it can be added to the Sound Manager or played via its key. + * + * @method Phaser.Sound.WebAudioSoundManager#decodeAudio + * @fires Phaser.Sound.Events#DECODED + * @fires Phaser.Sound.Events#DECODED_ALL + * @since 3.18.0 + * + * @param {(Phaser.Types.Sound.DecodeAudioConfig[]|string)} [audioKey] - The string-based key to be used to reference the decoded audio in the audio cache, or an array of audio config objects. + * @param {(ArrayBuffer|string)} [audioData] - The audio data, either a base64 encoded string, an audio media-type data uri, or an ArrayBuffer instance. + */ + decodeAudio: function (audioKey, audioData) + { + var audioFiles; + + if (!Array.isArray(audioKey)) + { + audioFiles = [ { key: audioKey, data: audioData } ]; + } + else + { + audioFiles = audioKey; + } + + var cache = this.game.cache.audio; + var remaining = audioFiles.length; + + for (var i = 0; i < audioFiles.length; i++) + { + var entry = audioFiles[i]; + + var key = entry.key; + var data = entry.data; + + if (typeof data === 'string') + { + data = Base64ToArrayBuffer(data); + } + + var success = function (key, audioBuffer) + { + cache.add(key, audioBuffer); + + this.emit(Events.DECODED, key); + + remaining--; + + if (remaining === 0) + { + this.emit(Events.DECODED_ALL); + } + }.bind(this, key); + + var failure = function (key, error) + { + // eslint-disable-next-line no-console + console.error('Error decoding audio: ' + key + ' - ', error ? error.message : ''); + + remaining--; + + if (remaining === 0) + { + this.emit(Events.DECODED_ALL); + } + }.bind(this, key); + + this.context.decodeAudioData(data, success, failure); + } + }, + + /** + * Sets the X and Y position of the Spatial Audio listener on this Web Audios context. + * + * If you call this method with no parameters it will default to the center-point of + * the game canvas. Depending on the type of game you're making, you may need to call + * this method constantly to reset the listener position as the camera scrolls. + * + * Calling this method does nothing on HTML5Audio. + * + * @method Phaser.Sound.WebAudioSoundManager#setListenerPosition + * @since 3.60.0 + * + * @param {number} [x] - The x position of the Spatial Audio listener. + * @param {number} [y] - The y position of the Spatial Audio listener. + */ + setListenerPosition: function (x, y) + { + if (x === undefined) { x = this.game.scale.width / 2; } + if (y === undefined) { y = this.game.scale.height / 2; } + + this.listenerPosition.set(x, y); + + return this; + }, + + /** + * Unlocks Web Audio API on the initial input event. + * + * Read more about how this issue is handled here in [this article](https://medium.com/@pgoloskokovic/unlocking-web-audio-the-smarter-way-8858218c0e09). + * + * @method Phaser.Sound.WebAudioSoundManager#unlock + * @since 3.0.0 + */ + unlock: function () + { + var _this = this; + + var body = document.body; + + var unlockHandler = function unlockHandler () + { + if (_this.context && body) + { + var bodyRemove = body.removeEventListener.bind(body); + + _this.context.resume().then(function () + { + bodyRemove('touchstart', unlockHandler); + bodyRemove('touchend', unlockHandler); + bodyRemove('mousedown', unlockHandler); + bodyRemove('mouseup', unlockHandler); + bodyRemove('keydown', unlockHandler); + + _this.unlocked = true; + + }, function () + { + bodyRemove('touchstart', unlockHandler); + bodyRemove('touchend', unlockHandler); + bodyRemove('mousedown', unlockHandler); + bodyRemove('mouseup', unlockHandler); + bodyRemove('keydown', unlockHandler); + }); + } + }; + + if (body) + { + body.addEventListener('touchstart', unlockHandler, false); + body.addEventListener('touchend', unlockHandler, false); + body.addEventListener('mousedown', unlockHandler, false); + body.addEventListener('mouseup', unlockHandler, false); + body.addEventListener('keydown', unlockHandler, false); + } + }, + + /** + * Method used internally for pausing sound manager if + * Phaser.Sound.WebAudioSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.WebAudioSoundManager#onBlur + * @protected + * @since 3.0.0 + */ + onBlur: function () + { + if (!this.locked) + { + this.context.suspend(); + } + }, + + /** + * Method used internally for resuming sound manager if + * Phaser.Sound.WebAudioSoundManager#pauseOnBlur is set to true. + * + * @method Phaser.Sound.WebAudioSoundManager#onFocus + * @protected + * @since 3.0.0 + */ + onFocus: function () + { + var context = this.context; + + if (context && !this.locked && (context.state === 'suspended' || context.state === 'interrupted')) + { + context.resume(); + } + }, + + /** + * Update method called on every game step. + * + * Removes destroyed sounds and updates every active sound in the game. + * + * @method Phaser.Sound.WebAudioSoundManager#update + * @protected + * @fires Phaser.Sound.Events#UNLOCKED + * @since 3.0.0 + * + * @param {number} time - The current timestamp as generated by the Request Animation Frame or SetTimeout. + * @param {number} delta - The delta time elapsed since the last frame. + */ + update: function (time, delta) + { + var listener = this.context.listener; + + if (listener && listener.positionX !== undefined) + { + var x = GetFastValue(this.listenerPosition, 'x', null); + var y = GetFastValue(this.listenerPosition, 'y', null); + + if (x && x !== this._spatialx) + { + this._spatialx = listener.positionX.value = x; + } + if (y && y !== this._spatialy) + { + this._spatialy = listener.positionY.value = y; + } + } + + BaseSoundManager.prototype.update.call(this, time, delta); + + // Resume interrupted audio on iOS only if the game has focus + if (!this.gameLostFocus) + { + this.onFocus(); + } + }, + + /** + * Calls Phaser.Sound.BaseSoundManager#destroy method + * and cleans up all Web Audio API related stuff. + * + * @method Phaser.Sound.WebAudioSoundManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.destination = null; + this.masterVolumeNode.disconnect(); + this.masterVolumeNode = null; + this.masterMuteNode.disconnect(); + this.masterMuteNode = null; + + if (this.game.config.audio.context) + { + this.context.suspend(); + } + else + { + var _this = this; + + this.context.close().then(function () + { + _this.context = null; + }); + } + + this.game.events.off(GameEvents.VISIBLE, this.onGameVisible, this); + + BaseSoundManager.prototype.destroy.call(this); + }, + + /** + * Sets the muted state of all this Sound Manager. + * + * @method Phaser.Sound.WebAudioSoundManager#setMute + * @fires Phaser.Sound.Events#GLOBAL_MUTE + * @since 3.3.0 + * + * @param {boolean} value - `true` to mute all sounds, `false` to unmute them. + * + * @return {Phaser.Sound.WebAudioSoundManager} This Sound Manager. + */ + setMute: function (value) + { + this.mute = value; + + return this; + }, + + /** + * @name Phaser.Sound.WebAudioSoundManager#mute + * @type {boolean} + * @fires Phaser.Sound.Events#GLOBAL_MUTE + * @since 3.0.0 + */ + mute: { + + get: function () + { + return (this.masterMuteNode.gain.value === 0); + }, + + set: function (value) + { + this.masterMuteNode.gain.setValueAtTime(value ? 0 : 1, 0); + + this.emit(Events.GLOBAL_MUTE, this, value); + } + + }, + + /** + * Sets the volume of this Sound Manager. + * + * @method Phaser.Sound.WebAudioSoundManager#setVolume + * @fires Phaser.Sound.Events#GLOBAL_VOLUME + * @since 3.3.0 + * + * @param {number} value - The global volume of this Sound Manager. + * + * @return {Phaser.Sound.WebAudioSoundManager} This Sound Manager. + */ + setVolume: function (value) + { + this.volume = value; + + return this; + }, + + /** + * @name Phaser.Sound.WebAudioSoundManager#volume + * @type {number} + * @fires Phaser.Sound.Events#GLOBAL_VOLUME + * @since 3.0.0 + */ + volume: { + + get: function () + { + return this.masterVolumeNode.gain.value; + }, + + set: function (value) + { + this.masterVolumeNode.gain.setValueAtTime(value, 0); + + this.emit(Events.GLOBAL_VOLUME, this, value); + } + + } + +}); + +module.exports = WebAudioSoundManager; + + +/***/ }), + +/***/ 73162: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayUtils = __webpack_require__(37105); +var Class = __webpack_require__(83419); +var NOOP = __webpack_require__(29747); +var StableSort = __webpack_require__(19186); + +/** + * @callback EachListCallback + * + * @param {I} item - The item which is currently being processed. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + */ + +/** + * @classdesc + * List is a generic implementation of an ordered list which contains utility methods for retrieving, manipulating, and iterating items. + * + * @class List + * @memberof Phaser.Structs + * @constructor + * @since 3.0.0 + * + * @generic T + * + * @param {*} parent - The parent of this list. + */ +var List = new Class({ + + initialize: + + function List (parent) + { + /** + * The parent of this list. + * + * @name Phaser.Structs.List#parent + * @type {*} + * @since 3.0.0 + */ + this.parent = parent; + + /** + * The objects that belong to this collection. + * + * @genericUse {T[]} - [$type] + * + * @name Phaser.Structs.List#list + * @type {Array.<*>} + * @default [] + * @since 3.0.0 + */ + this.list = []; + + /** + * The index of the current element. + * + * This is used internally when iterating through the list with the {@link #first}, {@link #last}, {@link #get}, and {@link #previous} properties. + * + * @name Phaser.Structs.List#position + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.position = 0; + + /** + * A callback that is invoked every time a child is added to this list. + * + * @name Phaser.Structs.List#addCallback + * @type {function} + * @since 3.4.0 + */ + this.addCallback = NOOP; + + /** + * A callback that is invoked every time a child is removed from this list. + * + * @name Phaser.Structs.List#removeCallback + * @type {function} + * @since 3.4.0 + */ + this.removeCallback = NOOP; + + /** + * The property key to sort by. + * + * @name Phaser.Structs.List#_sortKey + * @type {string} + * @since 3.4.0 + */ + this._sortKey = ''; + }, + + /** + * Adds the given item to the end of the list. Each item must be unique. + * + * @method Phaser.Structs.List#add + * @since 3.0.0 + * + * @param {*|Array.<*>} child - The item, or array of items, to add to the list. + * @param {boolean} [skipCallback=false] - Skip calling the List.addCallback if this child is added successfully. + * + * @return {*} The list's underlying array. + */ + add: function (child, skipCallback) + { + if (skipCallback) + { + return ArrayUtils.Add(this.list, child); + } + else + { + return ArrayUtils.Add(this.list, child, 0, this.addCallback, this); + } + }, + + /** + * Adds an item to list, starting at a specified index. Each item must be unique within the list. + * + * @method Phaser.Structs.List#addAt + * @since 3.0.0 + * + * @genericUse {(T|T[])} - [child,$return] + * + * @param {*} child - The item, or array of items, to add to the list. + * @param {number} [index=0] - The index in the list at which the element(s) will be inserted. + * @param {boolean} [skipCallback=false] - Skip calling the List.addCallback if this child is added successfully. + * + * @return {*} The List's underlying array. + */ + addAt: function (child, index, skipCallback) + { + if (skipCallback) + { + return ArrayUtils.AddAt(this.list, child, index); + } + else + { + return ArrayUtils.AddAt(this.list, child, index, 0, this.addCallback, this); + } + }, + + /** + * Retrieves the item at a given position inside the List. + * + * @method Phaser.Structs.List#getAt + * @since 3.0.0 + * + * @genericUse {T} - [$return] + * + * @param {number} index - The index of the item. + * + * @return {*} The retrieved item, or `undefined` if it's outside the List's bounds. + */ + getAt: function (index) + { + return this.list[index]; + }, + + /** + * Locates an item within the List and returns its index. + * + * @method Phaser.Structs.List#getIndex + * @since 3.0.0 + * + * @genericUse {T} - [child] + * + * @param {*} child - The item to locate. + * + * @return {number} The index of the item within the List, or -1 if it's not in the List. + */ + getIndex: function (child) + { + // Return -1 if given child isn't a child of this display list + return this.list.indexOf(child); + }, + + /** + * Sort the contents of this List so the items are in order based on the given property. + * For example, `sort('alpha')` would sort the List contents based on the value of their `alpha` property. + * + * @method Phaser.Structs.List#sort + * @since 3.0.0 + * + * @genericUse {T[]} - [children,$return] + * + * @param {string} property - The property to lexically sort by. + * @param {function} [handler] - Provide your own custom handler function. Will receive 2 children which it should compare and return a boolean. + * + * @return {Phaser.Structs.List} This List object. + */ + sort: function (property, handler) + { + if (!property) + { + return this; + } + + if (handler === undefined) + { + handler = function (childA, childB) + { + return childA[property] - childB[property]; + }; + } + + StableSort(this.list, handler); + + return this; + }, + + /** + * Searches for the first instance of a child with its `name` + * property matching the given argument. Should more than one child have + * the same name only the first is returned. + * + * @method Phaser.Structs.List#getByName + * @since 3.0.0 + * + * @genericUse {T | null} - [$return] + * + * @param {string} name - The name to search for. + * + * @return {?*} The first child with a matching name, or null if none were found. + */ + getByName: function (name) + { + return ArrayUtils.GetFirst(this.list, 'name', name); + }, + + /** + * Returns a random child from the group. + * + * @method Phaser.Structs.List#getRandom + * @since 3.0.0 + * + * @genericUse {T | null} - [$return] + * + * @param {number} [startIndex=0] - Offset from the front of the group (lowest child). + * @param {number} [length=(to top)] - Restriction on the number of values you want to randomly select from. + * + * @return {?*} A random child of this Group. + */ + getRandom: function (startIndex, length) + { + return ArrayUtils.GetRandom(this.list, startIndex, length); + }, + + /** + * Returns the first element in a given part of the List which matches a specific criterion. + * + * @method Phaser.Structs.List#getFirst + * @since 3.0.0 + * + * @genericUse {T | null} - [$return] + * + * @param {string} property - The name of the property to test or a falsey value to have no criterion. + * @param {*} value - The value to test the `property` against, or `undefined` to allow any value and only check for existence. + * @param {number} [startIndex=0] - The position in the List to start the search at. + * @param {number} [endIndex] - The position in the List to optionally stop the search at. It won't be checked. + * + * @return {?*} The first item which matches the given criterion, or `null` if no such item exists. + */ + getFirst: function (property, value, startIndex, endIndex) + { + return ArrayUtils.GetFirst(this.list, property, value, startIndex, endIndex); + }, + + /** + * Returns all children in this List. + * + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('parent')` would return only children that have a property called `parent`. + * + * You can also specify a value to compare the property to: + * + * `getAll('visible', true)` would return only children that have their visible property set to `true`. + * + * Optionally you can specify a start and end index. For example if this List had 100 children, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 children in the List. + * + * @method Phaser.Structs.List#getAll + * @since 3.0.0 + * + * @genericUse {T[]} - [$return] + * + * @param {string} [property] - An optional property to test against the value argument. + * @param {any} [value] - If property is set then Child.property must strictly equal this value to be included in the results. + * @param {number} [startIndex] - The first child index to start the search from. + * @param {number} [endIndex] - The last child index to search up until. + * + * @return {Array.<*>} All items of the List which match the given criterion, if any. + */ + getAll: function (property, value, startIndex, endIndex) + { + return ArrayUtils.GetAll(this.list, property, value, startIndex, endIndex); + }, + + /** + * Returns the total number of items in the List which have a property matching the given value. + * + * @method Phaser.Structs.List#count + * @since 3.0.0 + * + * @genericUse {T} - [value] + * + * @param {string} property - The property to test on each item. + * @param {*} value - The value to test the property against. + * + * @return {number} The total number of matching elements. + */ + count: function (property, value) + { + return ArrayUtils.CountAllMatching(this.list, property, value); + }, + + /** + * Swaps the positions of two items in the list. + * + * @method Phaser.Structs.List#swap + * @since 3.0.0 + * + * @genericUse {T} - [child1,child2] + * + * @param {*} child1 - The first item to swap. + * @param {*} child2 - The second item to swap. + */ + swap: function (child1, child2) + { + ArrayUtils.Swap(this.list, child1, child2); + }, + + /** + * Moves an item in the List to a new position. + * + * @method Phaser.Structs.List#moveTo + * @since 3.0.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*} child - The item to move. + * @param {number} index - Moves an item in the List to a new position. + * + * @return {*} The item that was moved. + */ + moveTo: function (child, index) + { + return ArrayUtils.MoveTo(this.list, child, index); + }, + + /** + * Moves an item above another one in the List. + * If the given item is already above the other, it isn't moved. + * Above means toward the end of the List. + * + * @method Phaser.Structs.List#moveAbove + * @since 3.55.0 + * + * @genericUse {T} - [child1,child2] + * + * @param {*} child1 - The element to move above base element. + * @param {*} child2 - The base element. + */ + moveAbove: function (child1, child2) + { + return ArrayUtils.MoveAbove(this.list, child1, child2); + }, + + /** + * Moves an item below another one in the List. + * If the given item is already below the other, it isn't moved. + * Below means toward the start of the List. + * + * @method Phaser.Structs.List#moveBelow + * @since 3.55.0 + * + * @genericUse {T} - [child1,child2] + * + * @param {*} child1 - The element to move below base element. + * @param {*} child2 - The base element. + */ + moveBelow: function (child1, child2) + { + return ArrayUtils.MoveBelow(this.list, child1, child2); + }, + + /** + * Removes one or many items from the List. + * + * @method Phaser.Structs.List#remove + * @since 3.0.0 + * + * @param {*} child - The item, or array of items, to remove. + * @param {boolean} [skipCallback=false] - Skip calling the List.removeCallback. + * + * @return {*} The item, or array of items, which were successfully removed from the List. + */ + remove: function (child, skipCallback) + { + if (skipCallback) + { + return ArrayUtils.Remove(this.list, child); + } + else + { + return ArrayUtils.Remove(this.list, child, this.removeCallback, this); + } + }, + + /** + * Removes the item at the given position in the List. + * + * @method Phaser.Structs.List#removeAt + * @since 3.0.0 + * + * @genericUse {T} - [$return] + * + * @param {number} index - The position to remove the item from. + * @param {boolean} [skipCallback=false] - Skip calling the List.removeCallback. + * + * @return {*} The item that was removed. + */ + removeAt: function (index, skipCallback) + { + if (skipCallback) + { + return ArrayUtils.RemoveAt(this.list, index); + } + else + { + return ArrayUtils.RemoveAt(this.list, index, this.removeCallback, this); + } + }, + + /** + * Removes the items within the given range in the List. + * + * @method Phaser.Structs.List#removeBetween + * @since 3.0.0 + * + * @genericUse {T[]} - [$return] + * + * @param {number} [startIndex=0] - The index to start removing from. + * @param {number} [endIndex] - The position to stop removing at. The item at this position won't be removed. + * @param {boolean} [skipCallback=false] - Skip calling the List.removeCallback. + * + * @return {Array.<*>} An array of the items which were removed. + */ + removeBetween: function (startIndex, endIndex, skipCallback) + { + if (skipCallback) + { + return ArrayUtils.RemoveBetween(this.list, startIndex, endIndex); + } + else + { + return ArrayUtils.RemoveBetween(this.list, startIndex, endIndex, this.removeCallback, this); + } + }, + + /** + * Removes all the items. + * + * @method Phaser.Structs.List#removeAll + * @since 3.0.0 + * + * @param {boolean} [skipCallback=false] - Skip calling the List.removeCallback. + * + * @return {this} This List object. + */ + removeAll: function (skipCallback) + { + var i = this.list.length; + + while (i--) + { + this.remove(this.list[i], skipCallback); + } + + return this; + }, + + /** + * Brings the given child to the top of this List. + * + * @method Phaser.Structs.List#bringToTop + * @since 3.0.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*} child - The item to bring to the top of the List. + * + * @return {*} The item which was moved. + */ + bringToTop: function (child) + { + return ArrayUtils.BringToTop(this.list, child); + }, + + /** + * Sends the given child to the bottom of this List. + * + * @method Phaser.Structs.List#sendToBack + * @since 3.0.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*} child - The item to send to the back of the list. + * + * @return {*} The item which was moved. + */ + sendToBack: function (child) + { + return ArrayUtils.SendToBack(this.list, child); + }, + + /** + * Moves the given child up one place in this group unless it's already at the top. + * + * @method Phaser.Structs.List#moveUp + * @since 3.0.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*} child - The item to move up. + * + * @return {*} The item which was moved. + */ + moveUp: function (child) + { + ArrayUtils.MoveUp(this.list, child); + + return child; + }, + + /** + * Moves the given child down one place in this group unless it's already at the bottom. + * + * @method Phaser.Structs.List#moveDown + * @since 3.0.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*} child - The item to move down. + * + * @return {*} The item which was moved. + */ + moveDown: function (child) + { + ArrayUtils.MoveDown(this.list, child); + + return child; + }, + + /** + * Reverses the order of all children in this List. + * + * @method Phaser.Structs.List#reverse + * @since 3.0.0 + * + * @genericUse {Phaser.Structs.List.} - [$return] + * + * @return {Phaser.Structs.List} This List object. + */ + reverse: function () + { + this.list.reverse(); + + return this; + }, + + /** + * Shuffles the items in the list. + * + * @method Phaser.Structs.List#shuffle + * @since 3.0.0 + * + * @genericUse {Phaser.Structs.List.} - [$return] + * + * @return {Phaser.Structs.List} This List object. + */ + shuffle: function () + { + ArrayUtils.Shuffle(this.list); + + return this; + }, + + /** + * Replaces a child of this List with the given newChild. The newChild cannot be a member of this List. + * + * @method Phaser.Structs.List#replace + * @since 3.0.0 + * + * @genericUse {T} - [oldChild,newChild,$return] + * + * @param {*} oldChild - The child in this List that will be replaced. + * @param {*} newChild - The child to be inserted into this List. + * + * @return {*} Returns the oldChild that was replaced within this group. + */ + replace: function (oldChild, newChild) + { + return ArrayUtils.Replace(this.list, oldChild, newChild); + }, + + /** + * Checks if an item exists within the List. + * + * @method Phaser.Structs.List#exists + * @since 3.0.0 + * + * @genericUse {T} - [child] + * + * @param {*} child - The item to check for the existence of. + * + * @return {boolean} `true` if the item is found in the list, otherwise `false`. + */ + exists: function (child) + { + return (this.list.indexOf(child) > -1); + }, + + /** + * Sets the property `key` to the given value on all members of this List. + * + * @method Phaser.Structs.List#setAll + * @since 3.0.0 + * + * @genericUse {T} - [value] + * + * @param {string} property - The name of the property to set. + * @param {*} value - The value to set the property to. + * @param {number} [startIndex] - The first child index to start the search from. + * @param {number} [endIndex] - The last child index to search up until. + */ + setAll: function (property, value, startIndex, endIndex) + { + ArrayUtils.SetAll(this.list, property, value, startIndex, endIndex); + + return this; + }, + + /** + * Passes all children to the given callback. + * + * @method Phaser.Structs.List#each + * @since 3.0.0 + * + * @genericUse {EachListCallback.} - [callback] + * + * @param {EachListCallback} callback - The function to call. + * @param {*} [context] - Value to use as `this` when executing callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + */ + each: function (callback, context) + { + var args = [ null ]; + + for (var i = 2; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < this.list.length; i++) + { + args[0] = this.list[i]; + + callback.apply(context, args); + } + }, + + /** + * Clears the List and recreates its internal array. + * + * @method Phaser.Structs.List#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + this.removeAll(); + + this.list = []; + }, + + /** + * Destroys this List. + * + * @method Phaser.Structs.List#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.removeAll(); + + this.parent = null; + this.addCallback = null; + this.removeCallback = null; + }, + + /** + * The number of items inside the List. + * + * @name Phaser.Structs.List#length + * @type {number} + * @readonly + * @since 3.0.0 + */ + length: { + + get: function () + { + return this.list.length; + } + + }, + + /** + * The first item in the List or `null` for an empty List. + * + * @name Phaser.Structs.List#first + * @genericUse {T} - [$type] + * @type {*} + * @readonly + * @since 3.0.0 + */ + first: { + + get: function () + { + this.position = 0; + + if (this.list.length > 0) + { + return this.list[0]; + } + else + { + return null; + } + } + + }, + + /** + * The last item in the List, or `null` for an empty List. + * + * @name Phaser.Structs.List#last + * @genericUse {T} - [$type] + * @type {*} + * @readonly + * @since 3.0.0 + */ + last: { + + get: function () + { + if (this.list.length > 0) + { + this.position = this.list.length - 1; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * The next item in the List, or `null` if the entire List has been traversed. + * + * This property can be read successively after reading {@link #first} or manually setting the {@link #position} to iterate the List. + * + * @name Phaser.Structs.List#next + * @genericUse {T} - [$type] + * @type {*} + * @readonly + * @since 3.0.0 + */ + next: { + + get: function () + { + if (this.position < this.list.length) + { + this.position++; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * The previous item in the List, or `null` if the entire List has been traversed. + * + * This property can be read successively after reading {@link #last} or manually setting the {@link #position} to iterate the List backwards. + * + * @name Phaser.Structs.List#previous + * @genericUse {T} - [$type] + * @type {*} + * @readonly + * @since 3.0.0 + */ + previous: { + + get: function () + { + if (this.position > 0) + { + this.position--; + + return this.list[this.position]; + } + else + { + return null; + } + } + + } + +}); + +module.exports = List; + + +/***/ }), + +/***/ 90330: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @callback EachMapCallback + * + * @param {string} key - The key of the Map entry. + * @param {E} entry - The value of the Map entry. + * + * @return {?boolean} The callback result. + */ + +/** + * @classdesc + * The keys of a Map can be arbitrary values. + * + * ```javascript + * var map = new Map([ + * [ 1, 'one' ], + * [ 2, 'two' ], + * [ 3, 'three' ] + * ]); + * ``` + * + * @class Map + * @memberof Phaser.Structs + * @constructor + * @since 3.0.0 + * + * @generic K + * @generic V + * @genericUse {V[]} - [elements] + * + * @param {Array.<*>} elements - An optional array of key-value pairs to populate this Map with. + */ +var Map = new Class({ + + initialize: + + function Map (elements) + { + /** + * The entries in this Map. + * + * @genericUse {Object.} - [$type] + * + * @name Phaser.Structs.Map#entries + * @type {Object.} + * @default {} + * @since 3.0.0 + */ + this.entries = {}; + + /** + * The number of key / value pairs in this Map. + * + * @name Phaser.Structs.Map#size + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.size = 0; + + this.setAll(elements); + }, + + /** + * Adds all the elements in the given array to this Map. + * + * If the element already exists, the value will be skipped. + * + * @method Phaser.Structs.Map#setAll + * @since 3.70.0 + * + * @generic K + * @generic V + * @genericUse {V[]} - [elements] + * + * @param {Array.<*>} elements - An array of key-value pairs to populate this Map with. + * + * @return {this} This Map object. + */ + setAll: function (elements) + { + if (Array.isArray(elements)) + { + for (var i = 0; i < elements.length; i++) + { + this.set(elements[i][0], elements[i][1]); + } + } + + return this; + }, + + /** + * Adds an element with a specified `key` and `value` to this Map. + * + * If the `key` already exists, the value will be replaced. + * + * If you wish to add multiple elements in a single call, use the `setAll` method instead. + * + * @method Phaser.Structs.Map#set + * @since 3.0.0 + * + * @genericUse {K} - [key] + * @genericUse {V} - [value] + * @genericUse {Phaser.Structs.Map.} - [$return] + * + * @param {string} key - The key of the element to be added to this Map. + * @param {*} value - The value of the element to be added to this Map. + * + * @return {this} This Map object. + */ + set: function (key, value) + { + if (!this.has(key)) + { + this.size++; + } + + this.entries[key] = value; + + return this; + }, + + /** + * Returns the value associated to the `key`, or `undefined` if there is none. + * + * @method Phaser.Structs.Map#get + * @since 3.0.0 + * + * @genericUse {K} - [key] + * @genericUse {V} - [$return] + * + * @param {string} key - The key of the element to return from the `Map` object. + * + * @return {*} The element associated with the specified key or `undefined` if the key can't be found in this Map object. + */ + get: function (key) + { + if (this.has(key)) + { + return this.entries[key]; + } + }, + + /** + * Returns an `Array` of all the values stored in this Map. + * + * @method Phaser.Structs.Map#getArray + * @since 3.0.0 + * + * @genericUse {V[]} - [$return] + * + * @return {Array.<*>} An array of the values stored in this Map. + */ + getArray: function () + { + var output = []; + var entries = this.entries; + + for (var key in entries) + { + output.push(entries[key]); + } + + return output; + }, + + /** + * Returns a boolean indicating whether an element with the specified key exists or not. + * + * @method Phaser.Structs.Map#has + * @since 3.0.0 + * + * @genericUse {K} - [key] + * + * @param {string} key - The key of the element to test for presence of in this Map. + * + * @return {boolean} Returns `true` if an element with the specified key exists in this Map, otherwise `false`. + */ + has: function (key) + { + return (this.entries.hasOwnProperty(key)); + }, + + /** + * Delete the specified element from this Map. + * + * @method Phaser.Structs.Map#delete + * @since 3.0.0 + * + * @genericUse {K} - [key] + * @genericUse {Phaser.Structs.Map.} - [$return] + * + * @param {string} key - The key of the element to delete from this Map. + * + * @return {this} This Map object. + */ + delete: function (key) + { + if (this.has(key)) + { + delete this.entries[key]; + this.size--; + } + + return this; + }, + + /** + * Delete all entries from this Map. + * + * @method Phaser.Structs.Map#clear + * @since 3.0.0 + * + * @genericUse {Phaser.Structs.Map.} - [$return] + * + * @return {this} This Map object. + */ + clear: function () + { + Object.keys(this.entries).forEach(function (prop) + { + delete this.entries[prop]; + + }, this); + + this.size = 0; + + return this; + }, + + /** + * Returns all entries keys in this Map. + * + * @method Phaser.Structs.Map#keys + * @since 3.0.0 + * + * @genericUse {K[]} - [$return] + * + * @return {string[]} Array containing entries' keys. + */ + keys: function () + { + return Object.keys(this.entries); + }, + + /** + * Returns an `Array` of all entries. + * + * @method Phaser.Structs.Map#values + * @since 3.0.0 + * + * @genericUse {V[]} - [$return] + * + * @return {Array.<*>} An `Array` of entries. + */ + values: function () + { + var output = []; + var entries = this.entries; + + for (var key in entries) + { + output.push(entries[key]); + } + + return output; + }, + + /** + * Dumps the contents of this Map to the console via `console.group`. + * + * @method Phaser.Structs.Map#dump + * @since 3.0.0 + */ + dump: function () + { + var entries = this.entries; + + // eslint-disable-next-line no-console + console.group('Map'); + + for (var key in entries) + { + console.log(key, entries[key]); + } + + // eslint-disable-next-line no-console + console.groupEnd(); + }, + + /** + * Iterates through all entries in this Map, passing each one to the given callback. + * + * If the callback returns `false`, the iteration will break. + * + * @method Phaser.Structs.Map#each + * @since 3.0.0 + * + * @genericUse {EachMapCallback.} - [callback] + * @genericUse {Phaser.Structs.Map.} - [$return] + * + * @param {EachMapCallback} callback - The callback which will receive the keys and entries held in this Map. + * + * @return {this} This Map object. + */ + each: function (callback) + { + var entries = this.entries; + + for (var key in entries) + { + if (callback(key, entries[key]) === false) + { + break; + } + } + + return this; + }, + + /** + * Returns `true` if the value exists within this Map. Otherwise, returns `false`. + * + * @method Phaser.Structs.Map#contains + * @since 3.0.0 + * + * @genericUse {V} - [value] + * + * @param {*} value - The value to search for. + * + * @return {boolean} `true` if the value is found, otherwise `false`. + */ + contains: function (value) + { + var entries = this.entries; + + for (var key in entries) + { + if (entries[key] === value) + { + return true; + } + } + + return false; + }, + + /** + * Merges all new keys from the given Map into this one. + * If it encounters a key that already exists it will be skipped unless override is set to `true`. + * + * @method Phaser.Structs.Map#merge + * @since 3.0.0 + * + * @genericUse {Phaser.Structs.Map.} - [map,$return] + * + * @param {Phaser.Structs.Map} map - The Map to merge in to this Map. + * @param {boolean} [override=false] - Set to `true` to replace values in this Map with those from the source map, or `false` to skip them. + * + * @return {this} This Map object. + */ + merge: function (map, override) + { + if (override === undefined) { override = false; } + + var local = this.entries; + var source = map.entries; + + for (var key in source) + { + if (local.hasOwnProperty(key) && override) + { + local[key] = source[key]; + } + else + { + this.set(key, source[key]); + } + } + + return this; + } + +}); + +module.exports = Map; + + +/***/ }), + +/***/ 25774: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(82348); + +/** + * @classdesc + * A Process Queue maintains three internal lists. + * + * The `pending` list is a selection of items which are due to be made 'active' in the next update. + * The `active` list is a selection of items which are considered active and should be updated. + * The `destroy` list is a selection of items that were active and are awaiting being destroyed in the next update. + * + * When new items are added to a Process Queue they are put in the pending list, rather than being added + * immediately the active list. Equally, items that are removed are put into the destroy list, rather than + * being destroyed immediately. This allows the Process Queue to carefully process each item at a specific, fixed + * time, rather than at the time of the request from the API. + * + * @class ProcessQueue + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Structs + * @constructor + * @since 3.0.0 + * + * @generic T + */ +var ProcessQueue = new Class({ + + Extends: EventEmitter, + + initialize: + + function ProcessQueue () + { + EventEmitter.call(this); + + /** + * The `pending` list is a selection of items which are due to be made 'active' in the next update. + * + * @genericUse {T[]} - [$type] + * + * @name Phaser.Structs.ProcessQueue#_pending + * @type {Array.<*>} + * @private + * @default [] + * @since 3.0.0 + */ + this._pending = []; + + /** + * The `active` list is a selection of items which are considered active and should be updated. + * + * @genericUse {T[]} - [$type] + * + * @name Phaser.Structs.ProcessQueue#_active + * @type {Array.<*>} + * @private + * @default [] + * @since 3.0.0 + */ + this._active = []; + + /** + * The `destroy` list is a selection of items that were active and are awaiting being destroyed in the next update. + * + * @genericUse {T[]} - [$type] + * + * @name Phaser.Structs.ProcessQueue#_destroy + * @type {Array.<*>} + * @private + * @default [] + * @since 3.0.0 + */ + this._destroy = []; + + /** + * The total number of items awaiting processing. + * + * @name Phaser.Structs.ProcessQueue#_toProcess + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._toProcess = 0; + + /** + * If `true` only unique objects will be allowed in the queue. + * + * @name Phaser.Structs.ProcessQueue#checkQueue + * @type {boolean} + * @since 3.50.0 + */ + this.checkQueue = false; + }, + + /** + * Checks the given item to see if it is already active within this Process Queue. + * + * @method Phaser.Structs.ProcessQueue#isActive + * @since 3.60.0 + * + * @genericUse {T} - [item] + * @genericUse {Phaser.Structs.ProcessQueue.} - [$return] + * + * @param {*} item - The item to check. + * + * @return {boolean} `true` if the item is active, otherwise `false`. + */ + isActive: function (item) + { + return (this._active.indexOf(item) > -1); + }, + + /** + * Checks the given item to see if it is already pending addition to this Process Queue. + * + * @method Phaser.Structs.ProcessQueue#isPending + * @since 3.60.0 + * + * @genericUse {T} - [item] + * @genericUse {Phaser.Structs.ProcessQueue.} - [$return] + * + * @param {*} item - The item to check. + * + * @return {boolean} `true` if the item is pending insertion, otherwise `false`. + */ + isPending: function (item) + { + return (this._toProcess > 0 && this._pending.indexOf(item) > -1); + }, + + /** + * Checks the given item to see if it is already pending destruction from this Process Queue. + * + * @method Phaser.Structs.ProcessQueue#isDestroying + * @since 3.60.0 + * + * @genericUse {T} - [item] + * @genericUse {Phaser.Structs.ProcessQueue.} - [$return] + * + * @param {*} item - The item to check. + * + * @return {boolean} `true` if the item is pending destruction, otherwise `false`. + */ + isDestroying: function (item) + { + return (this._destroy.indexOf(item) > -1); + }, + + /** + * Adds a new item to the Process Queue. + * + * The item is added to the pending list and made active in the next update. + * + * @method Phaser.Structs.ProcessQueue#add + * @since 3.0.0 + * + * @genericUse {T} - [item] + * @genericUse {Phaser.Structs.ProcessQueue.} - [$return] + * + * @param {*} item - The item to add to the queue. + * + * @return {*} The item that was added. + */ + add: function (item) + { + // Don't add if already active or pending, but DO add if active AND in the destroy list + if (this.checkQueue && (this.isActive(item) && !this.isDestroying(item)) || this.isPending(item)) + { + return item; + } + + this._pending.push(item); + + this._toProcess++; + + return item; + }, + + /** + * Removes an item from the Process Queue. + * + * The item is added to the 'destroy' list and is fully removed in the next update. + * + * @method Phaser.Structs.ProcessQueue#remove + * @since 3.0.0 + * + * @genericUse {T} - [item] + * @genericUse {Phaser.Structs.ProcessQueue.} - [$return] + * + * @param {*} item - The item to be removed from the queue. + * + * @return {*} The item that was removed. + */ + remove: function (item) + { + // Check if it's in the _pending list + if (this.isPending(item)) + { + var pending = this._pending; + + var idx = pending.indexOf(item); + + if (idx !== -1) + { + // Remove directly, no need to wait for an update loop + pending.splice(idx, 1); + } + } + else if (this.isActive(item)) + { + // Item is actively running? Queue it for deletion + this._destroy.push(item); + + this._toProcess++; + } + + // If neither of the above conditions pass, then the item is either already in the destroy list, + // or isn't pending or active, so cannot be removed anyway + + return item; + }, + + /** + * Removes all active items from this Process Queue. + * + * All the items are marked as 'pending destroy' and fully removed in the next update. + * + * @method Phaser.Structs.ProcessQueue#removeAll + * @since 3.20.0 + * + * @return {this} This Process Queue object. + */ + removeAll: function () + { + var list = this._active; + var destroy = this._destroy; + var i = list.length; + + while (i--) + { + destroy.push(list[i]); + + this._toProcess++; + } + + return this; + }, + + /** + * Update this queue. First it will process any items awaiting destruction, and remove them. + * + * Then it will check to see if there are any items pending insertion, and move them to an + * active state. Finally, it will return a list of active items for further processing. + * + * @method Phaser.Structs.ProcessQueue#update + * @since 3.0.0 + * + * @genericUse {T[]} - [$return] + * + * @return {Array.<*>} A list of active items. + */ + update: function () + { + if (this._toProcess === 0) + { + // Quick bail + return this._active; + } + + var list = this._destroy; + var active = this._active; + var i; + var item; + + // Clear the 'destroy' list + for (i = 0; i < list.length; i++) + { + item = list[i]; + + // Remove from the 'active' array + var idx = active.indexOf(item); + + if (idx !== -1) + { + active.splice(idx, 1); + + this.emit(Events.PROCESS_QUEUE_REMOVE, item); + } + } + + list.length = 0; + + // Process the pending addition list + // This stops callbacks and out of sync events from populating the active array mid-way during an update + + list = this._pending; + + for (i = 0; i < list.length; i++) + { + item = list[i]; + + if (!this.checkQueue || (this.checkQueue && active.indexOf(item) === -1)) + { + active.push(item); + + this.emit(Events.PROCESS_QUEUE_ADD, item); + } + } + + list.length = 0; + + this._toProcess = 0; + + // The owner of this queue can now safely do whatever it needs to with the active list + return active; + }, + + /** + * Returns the current list of active items. + * + * This method returns a reference to the active list array, not a copy of it. + * Therefore, be careful to not modify this array outside of the ProcessQueue. + * + * @method Phaser.Structs.ProcessQueue#getActive + * @since 3.0.0 + * + * @genericUse {T[]} - [$return] + * + * @return {Array.<*>} A list of active items. + */ + getActive: function () + { + return this._active; + }, + + /** + * The number of entries in the active list. + * + * @name Phaser.Structs.ProcessQueue#length + * @type {number} + * @readonly + * @since 3.20.0 + */ + length: { + + get: function () + { + return this._active.length; + } + + }, + + /** + * Immediately destroys this process queue, clearing all of its internal arrays and resetting the process totals. + * + * @method Phaser.Structs.ProcessQueue#destroy + * @since 3.0.0 + */ + destroy: function () + { + this._toProcess = 0; + + this._pending = []; + this._active = []; + this._destroy = []; + } + +}); + +module.exports = ProcessQueue; + + +/***/ }), + +/***/ 59542: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Vladimir Agafonkin + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var quickselect = __webpack_require__(43886); + +/** + * @classdesc + * RBush is a high-performance JavaScript library for 2D spatial indexing of points and rectangles. + * It's based on an optimized R-tree data structure with bulk insertion support. + * + * Spatial index is a special data structure for points and rectangles that allows you to perform queries like + * "all items within this bounding box" very efficiently (e.g. hundreds of times faster than looping over all items). + * + * This version of RBush uses a fixed min/max accessor structure of `[ '.left', '.top', '.right', '.bottom' ]`. + * This is to avoid the eval like function creation that the original library used, which caused CSP policy violations. + * + * rbush is forked from https://github.com/mourner/rbush by Vladimir Agafonkin + * + * @class RTree + * @memberof Phaser.Structs + * @constructor + * @since 3.0.0 + */ + +function rbush (maxEntries) +{ + var format = [ '.left', '.top', '.right', '.bottom' ]; + + if (!(this instanceof rbush)) return new rbush(maxEntries, format); + + // max entries in a node is 9 by default; min node fill is 40% for best performance + this._maxEntries = Math.max(4, maxEntries || 9); + this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4)); + + this.clear(); +} + +rbush.prototype = { + + all: function () + { + return this._all(this.data, []); + }, + + search: function (bbox) + { + var node = this.data, + result = [], + toBBox = this.toBBox; + + if (!intersects(bbox, node)) return result; + + var nodesToSearch = [], + i, len, child, childBBox; + + while (node) { + for (i = 0, len = node.children.length; i < len; i++) { + + child = node.children[i]; + childBBox = node.leaf ? toBBox(child) : child; + + if (intersects(bbox, childBBox)) { + if (node.leaf) result.push(child); + else if (contains(bbox, childBBox)) this._all(child, result); + else nodesToSearch.push(child); + } + } + node = nodesToSearch.pop(); + } + + return result; + }, + + collides: function (bbox) + { + var node = this.data, + toBBox = this.toBBox; + + if (!intersects(bbox, node)) return false; + + var nodesToSearch = [], + i, len, child, childBBox; + + while (node) { + for (i = 0, len = node.children.length; i < len; i++) { + + child = node.children[i]; + childBBox = node.leaf ? toBBox(child) : child; + + if (intersects(bbox, childBBox)) { + if (node.leaf || contains(bbox, childBBox)) return true; + nodesToSearch.push(child); + } + } + node = nodesToSearch.pop(); + } + + return false; + }, + + load: function (data) + { + if (!(data && data.length)) return this; + + if (data.length < this._minEntries) { + for (var i = 0, len = data.length; i < len; i++) { + this.insert(data[i]); + } + return this; + } + + // recursively build the tree with the given data from scratch using OMT algorithm + var node = this._build(data.slice(), 0, data.length - 1, 0); + + if (!this.data.children.length) { + // save as is if tree is empty + this.data = node; + + } else if (this.data.height === node.height) { + // split root if trees have the same height + this._splitRoot(this.data, node); + + } else { + if (this.data.height < node.height) { + // swap trees if inserted one is bigger + var tmpNode = this.data; + this.data = node; + node = tmpNode; + } + + // insert the small tree into the large tree at appropriate level + this._insert(node, this.data.height - node.height - 1, true); + } + + return this; + }, + + insert: function (item) + { + if (item) this._insert(item, this.data.height - 1); + return this; + }, + + clear: function () + { + this.data = createNode([]); + return this; + }, + + remove: function (item, equalsFn) + { + if (!item) return this; + + var node = this.data, + bbox = this.toBBox(item), + path = [], + indexes = [], + i, parent, index, goingUp; + + // depth-first iterative tree traversal + while (node || path.length) { + + if (!node) { // go up + node = path.pop(); + parent = path[path.length - 1]; + i = indexes.pop(); + goingUp = true; + } + + if (node.leaf) { // check current node + index = findItem(item, node.children, equalsFn); + + if (index !== -1) { + // item found, remove the item and condense tree upwards + node.children.splice(index, 1); + path.push(node); + this._condense(path); + return this; + } + } + + if (!goingUp && !node.leaf && contains(node, bbox)) { // go down + path.push(node); + indexes.push(i); + i = 0; + parent = node; + node = node.children[0]; + + } else if (parent) { // go right + i++; + node = parent.children[i]; + goingUp = false; + + } else node = null; // nothing found + } + + return this; + }, + + toBBox: function (item) { return item; }, + + compareMinX: compareNodeMinX, + compareMinY: compareNodeMinY, + + toJSON: function () { return this.data; }, + + fromJSON: function (data) + { + this.data = data; + return this; + }, + + _all: function (node, result) + { + var nodesToSearch = []; + while (node) { + if (node.leaf) result.push.apply(result, node.children); + else nodesToSearch.push.apply(nodesToSearch, node.children); + + node = nodesToSearch.pop(); + } + return result; + }, + + _build: function (items, left, right, height) + { + var N = right - left + 1, + M = this._maxEntries, + node; + + if (N <= M) { + // reached leaf level; return leaf + node = createNode(items.slice(left, right + 1)); + calcBBox(node, this.toBBox); + return node; + } + + if (!height) { + // target height of the bulk-loaded tree + height = Math.ceil(Math.log(N) / Math.log(M)); + + // target number of root entries to maximize storage utilization + M = Math.ceil(N / Math.pow(M, height - 1)); + } + + node = createNode([]); + node.leaf = false; + node.height = height; + + // split the items into M mostly square tiles + + var N2 = Math.ceil(N / M), + N1 = N2 * Math.ceil(Math.sqrt(M)), + i, j, right2, right3; + + multiSelect(items, left, right, N1, this.compareMinX); + + for (i = left; i <= right; i += N1) { + + right2 = Math.min(i + N1 - 1, right); + + multiSelect(items, i, right2, N2, this.compareMinY); + + for (j = i; j <= right2; j += N2) { + + right3 = Math.min(j + N2 - 1, right2); + + // pack each entry recursively + node.children.push(this._build(items, j, right3, height - 1)); + } + } + + calcBBox(node, this.toBBox); + + return node; + }, + + _chooseSubtree: function (bbox, node, level, path) + { + var i, len, child, targetNode, area, enlargement, minArea, minEnlargement; + + while (true) { + path.push(node); + + if (node.leaf || path.length - 1 === level) break; + + minArea = minEnlargement = Infinity; + + for (i = 0, len = node.children.length; i < len; i++) { + child = node.children[i]; + area = bboxArea(child); + enlargement = enlargedArea(bbox, child) - area; + + // choose entry with the least area enlargement + if (enlargement < minEnlargement) { + minEnlargement = enlargement; + minArea = area < minArea ? area : minArea; + targetNode = child; + + } else if (enlargement === minEnlargement) { + // otherwise choose one with the smallest area + if (area < minArea) { + minArea = area; + targetNode = child; + } + } + } + + node = targetNode || node.children[0]; + } + + return node; + }, + + _insert: function (item, level, isNode) + { + var toBBox = this.toBBox, + bbox = isNode ? item : toBBox(item), + insertPath = []; + + // find the best node for accommodating the item, saving all nodes along the path too + var node = this._chooseSubtree(bbox, this.data, level, insertPath); + + // put the item into the node + node.children.push(item); + extend(node, bbox); + + // split on node overflow; propagate upwards if necessary + while (level >= 0) { + if (insertPath[level].children.length > this._maxEntries) { + this._split(insertPath, level); + level--; + } else break; + } + + // adjust bboxes along the insertion path + this._adjustParentBBoxes(bbox, insertPath, level); + }, + + // split overflowed node into two + _split: function (insertPath, level) + { + var node = insertPath[level], + M = node.children.length, + m = this._minEntries; + + this._chooseSplitAxis(node, m, M); + + var splitIndex = this._chooseSplitIndex(node, m, M); + + var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex)); + newNode.height = node.height; + newNode.leaf = node.leaf; + + calcBBox(node, this.toBBox); + calcBBox(newNode, this.toBBox); + + if (level) insertPath[level - 1].children.push(newNode); + else this._splitRoot(node, newNode); + }, + + _splitRoot: function (node, newNode) + { + // split root node + this.data = createNode([node, newNode]); + this.data.height = node.height + 1; + this.data.leaf = false; + calcBBox(this.data, this.toBBox); + }, + + _chooseSplitIndex: function (node, m, M) + { + var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index; + + minOverlap = minArea = Infinity; + + for (i = m; i <= M - m; i++) { + bbox1 = distBBox(node, 0, i, this.toBBox); + bbox2 = distBBox(node, i, M, this.toBBox); + + overlap = intersectionArea(bbox1, bbox2); + area = bboxArea(bbox1) + bboxArea(bbox2); + + // choose distribution with minimum overlap + if (overlap < minOverlap) { + minOverlap = overlap; + index = i; + + minArea = area < minArea ? area : minArea; + + } else if (overlap === minOverlap) { + // otherwise choose distribution with minimum area + if (area < minArea) { + minArea = area; + index = i; + } + } + } + + return index; + }, + + // sorts node children by the best axis for split + _chooseSplitAxis: function (node, m, M) + { + var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX, + compareMinY = node.leaf ? this.compareMinY : compareNodeMinY, + xMargin = this._allDistMargin(node, m, M, compareMinX), + yMargin = this._allDistMargin(node, m, M, compareMinY); + + // if total distributions margin value is minimal for x, sort by minX, + // otherwise it's already sorted by minY + if (xMargin < yMargin) node.children.sort(compareMinX); + }, + + // total margin of all possible split distributions where each node is at least m full + _allDistMargin: function (node, m, M, compare) + { + node.children.sort(compare); + + var toBBox = this.toBBox, + leftBBox = distBBox(node, 0, m, toBBox), + rightBBox = distBBox(node, M - m, M, toBBox), + margin = bboxMargin(leftBBox) + bboxMargin(rightBBox), + i, child; + + for (i = m; i < M - m; i++) { + child = node.children[i]; + extend(leftBBox, node.leaf ? toBBox(child) : child); + margin += bboxMargin(leftBBox); + } + + for (i = M - m - 1; i >= m; i--) { + child = node.children[i]; + extend(rightBBox, node.leaf ? toBBox(child) : child); + margin += bboxMargin(rightBBox); + } + + return margin; + }, + + _adjustParentBBoxes: function (bbox, path, level) + { + // adjust bboxes along the given tree path + for (var i = level; i >= 0; i--) { + extend(path[i], bbox); + } + }, + + _condense: function (path) + { + // go through the path, removing empty nodes and updating bboxes + for (var i = path.length - 1, siblings; i >= 0; i--) { + if (path[i].children.length === 0) { + if (i > 0) { + siblings = path[i - 1].children; + siblings.splice(siblings.indexOf(path[i]), 1); + + } else this.clear(); + + } else calcBBox(path[i], this.toBBox); + } + }, + + compareMinX: function (a, b) + { + return a.left - b.left; + }, + + compareMinY: function (a, b) + { + return a.top - b.top; + }, + + toBBox: function (a) + { + return { + minX: a.left, + minY: a.top, + maxX: a.right, + maxY: a.bottom + }; + } +}; + +function findItem (item, items, equalsFn) +{ + if (!equalsFn) return items.indexOf(item); + + for (var i = 0; i < items.length; i++) { + if (equalsFn(item, items[i])) return i; + } + return -1; +} + +// calculate node's bbox from bboxes of its children +function calcBBox (node, toBBox) +{ + distBBox(node, 0, node.children.length, toBBox, node); +} + +// min bounding rectangle of node children from k to p-1 +function distBBox (node, k, p, toBBox, destNode) +{ + if (!destNode) destNode = createNode(null); + destNode.minX = Infinity; + destNode.minY = Infinity; + destNode.maxX = -Infinity; + destNode.maxY = -Infinity; + + for (var i = k, child; i < p; i++) { + child = node.children[i]; + extend(destNode, node.leaf ? toBBox(child) : child); + } + + return destNode; +} + +function extend (a, b) +{ + a.minX = Math.min(a.minX, b.minX); + a.minY = Math.min(a.minY, b.minY); + a.maxX = Math.max(a.maxX, b.maxX); + a.maxY = Math.max(a.maxY, b.maxY); + return a; +} + +function compareNodeMinX (a, b) { return a.minX - b.minX; } +function compareNodeMinY (a, b) { return a.minY - b.minY; } + +function bboxArea (a) { return (a.maxX - a.minX) * (a.maxY - a.minY); } +function bboxMargin (a) { return (a.maxX - a.minX) + (a.maxY - a.minY); } + +function enlargedArea (a, b) +{ + return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * + (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY)); +} + +function intersectionArea (a, b) +{ + var minX = Math.max(a.minX, b.minX), + minY = Math.max(a.minY, b.minY), + maxX = Math.min(a.maxX, b.maxX), + maxY = Math.min(a.maxY, b.maxY); + + return Math.max(0, maxX - minX) * + Math.max(0, maxY - minY); +} + +function contains (a, b) +{ + return a.minX <= b.minX && + a.minY <= b.minY && + b.maxX <= a.maxX && + b.maxY <= a.maxY; +} + +function intersects (a, b) +{ + return b.minX <= a.maxX && + b.minY <= a.maxY && + b.maxX >= a.minX && + b.maxY >= a.minY; +} + +function createNode (children) +{ + return { + children: children, + height: 1, + leaf: true, + minX: Infinity, + minY: Infinity, + maxX: -Infinity, + maxY: -Infinity + }; +} + +// sort an array so that items come in groups of n unsorted items, with groups sorted between each other; +// combines selection algorithm with binary divide & conquer approach + +function multiSelect (arr, left, right, n, compare) +{ + var stack = [left, right], + mid; + + while (stack.length) + { + right = stack.pop(); + left = stack.pop(); + + if (right - left <= n) continue; + + mid = left + Math.ceil((right - left) / n / 2) * n; + quickselect(arr, mid, left, right, compare); + + stack.push(left, mid, mid, right); + } +} + +module.exports = rbush; + + +/***/ }), + +/***/ 86555: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var SnapFloor = __webpack_require__(56583); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * The Size component allows you to set `width` and `height` properties and define the relationship between them. + * + * The component can automatically maintain the aspect ratios between the two values, and clamp them + * to a defined min-max range. You can also control the dominant axis. When dimensions are given to the Size component + * that would cause it to exceed its min-max range, the dimensions are adjusted based on the dominant axis. + * + * @class Size + * @memberof Phaser.Structs + * @constructor + * @since 3.16.0 + * + * @param {number} [width=0] - The width of the Size component. + * @param {number} [height=width] - The height of the Size component. If not given, it will use the `width`. + * @param {number} [aspectMode=0] - The aspect mode of the Size component. Defaults to 0, no mode. + * @param {any} [parent=null] - The parent of this Size component. Can be any object with public `width` and `height` properties. Dimensions are clamped to keep them within the parent bounds where possible. + */ +var Size = new Class({ + + initialize: + + function Size (width, height, aspectMode, parent) + { + if (width === undefined) { width = 0; } + if (height === undefined) { height = width; } + if (aspectMode === undefined) { aspectMode = 0; } + if (parent === undefined) { parent = null; } + + /** + * Internal width value. + * + * @name Phaser.Structs.Size#_width + * @type {number} + * @private + * @since 3.16.0 + */ + this._width = width; + + /** + * Internal height value. + * + * @name Phaser.Structs.Size#_height + * @type {number} + * @private + * @since 3.16.0 + */ + this._height = height; + + /** + * Internal parent reference. + * + * @name Phaser.Structs.Size#_parent + * @type {any} + * @private + * @since 3.16.0 + */ + this._parent = parent; + + /** + * The aspect mode this Size component will use when calculating its dimensions. + * This property is read-only. To change it use the `setAspectMode` method. + * + * @name Phaser.Structs.Size#aspectMode + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.aspectMode = aspectMode; + + /** + * The proportional relationship between the width and height. + * + * This property is read-only and is updated automatically when either the `width` or `height` properties are changed, + * depending on the aspect mode. + * + * @name Phaser.Structs.Size#aspectRatio + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.aspectRatio = (height === 0) ? 1 : width / height; + + /** + * The minimum allowed width. + * Cannot be less than zero. + * This value is read-only. To change it see the `setMin` method. + * + * @name Phaser.Structs.Size#minWidth + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.minWidth = 0; + + /** + * The minimum allowed height. + * Cannot be less than zero. + * This value is read-only. To change it see the `setMin` method. + * + * @name Phaser.Structs.Size#minHeight + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.minHeight = 0; + + /** + * The maximum allowed width. + * This value is read-only. To change it see the `setMax` method. + * + * @name Phaser.Structs.Size#maxWidth + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.maxWidth = Number.MAX_VALUE; + + /** + * The maximum allowed height. + * This value is read-only. To change it see the `setMax` method. + * + * @name Phaser.Structs.Size#maxHeight + * @type {number} + * @readonly + * @since 3.16.0 + */ + this.maxHeight = Number.MAX_VALUE; + + /** + * A Vector2 containing the horizontal and vertical snap values, which the width and height are snapped to during resizing. + * + * By default this is disabled. + * + * This property is read-only. To change it see the `setSnap` method. + * + * @name Phaser.Structs.Size#snapTo + * @type {Phaser.Math.Vector2} + * @readonly + * @since 3.16.0 + */ + this.snapTo = new Vector2(); + }, + + /** + * Sets the aspect mode of this Size component. + * + * The aspect mode controls what happens when you modify the `width` or `height` properties, or call `setSize`. + * + * It can be a number from 0 to 4, or a Size constant: + * + * 0. NONE = Do not make the size fit the aspect ratio. Change the ratio when the size changes. + * 1. WIDTH_CONTROLS_HEIGHT = The height is automatically adjusted based on the width. + * 2. HEIGHT_CONTROLS_WIDTH = The width is automatically adjusted based on the height. + * 3. FIT = The width and height are automatically adjusted to fit inside the given target area, while keeping the aspect ratio. Depending on the aspect ratio there may be some space inside the area which is not covered. + * 4. ENVELOP = The width and height are automatically adjusted to make the size cover the entire target area while keeping the aspect ratio. This may extend further out than the target size. + * + * Calling this method automatically recalculates the `width` and the `height`, if required. + * + * @method Phaser.Structs.Size#setAspectMode + * @since 3.16.0 + * + * @param {number} [value=0] - The aspect mode value. + * + * @return {this} This Size component instance. + */ + setAspectMode: function (value) + { + if (value === undefined) { value = 0; } + + this.aspectMode = value; + + return this.setSize(this._width, this._height); + }, + + /** + * By setting snap values, when this Size component is modified its dimensions will automatically + * be snapped to the nearest grid slice, using floor. For example, if you have snap value of 16, + * and the width changes to 68, then it will snap down to 64 (the closest multiple of 16 when floored) + * + * Note that snapping takes place before adjustments by the parent, or the min / max settings. If these + * values are not multiples of the given snap values, then this can result in un-snapped dimensions. + * + * Call this method with no arguments to reset the snap values. + * + * Calling this method automatically recalculates the `width` and the `height`, if required. + * + * @method Phaser.Structs.Size#setSnap + * @since 3.16.0 + * + * @param {number} [snapWidth=0] - The amount to snap the width to. If you don't want to snap the width, pass a value of zero. + * @param {number} [snapHeight=snapWidth] - The amount to snap the height to. If not provided it will use the `snapWidth` value. If you don't want to snap the height, pass a value of zero. + * + * @return {this} This Size component instance. + */ + setSnap: function (snapWidth, snapHeight) + { + if (snapWidth === undefined) { snapWidth = 0; } + if (snapHeight === undefined) { snapHeight = snapWidth; } + + this.snapTo.set(snapWidth, snapHeight); + + return this.setSize(this._width, this._height); + }, + + /** + * Sets, or clears, the parent of this Size component. + * + * To clear the parent call this method with no arguments. + * + * The parent influences the maximum extents to which this Size component can expand, + * based on the aspect mode: + * + * NONE - The parent clamps both the width and height. + * WIDTH_CONTROLS_HEIGHT - The parent clamps just the width. + * HEIGHT_CONTROLS_WIDTH - The parent clamps just the height. + * FIT - The parent clamps whichever axis is required to ensure the size fits within it. + * ENVELOP - The parent is used to ensure the size fully envelops the parent. + * + * Calling this method automatically calls `setSize`. + * + * @method Phaser.Structs.Size#setParent + * @since 3.16.0 + * + * @param {any} [parent] - Sets the parent of this Size component. Don't provide a value to clear an existing parent. + * + * @return {this} This Size component instance. + */ + setParent: function (parent) + { + this._parent = parent; + + return this.setSize(this._width, this._height); + }, + + /** + * Set the minimum width and height values this Size component will allow. + * + * The minimum values can never be below zero, or greater than the maximum values. + * + * Setting this will automatically adjust both the `width` and `height` properties to ensure they are within range. + * + * Note that based on the aspect mode, and if this Size component has a parent set or not, the minimums set here + * _can_ be exceed in some situations. + * + * @method Phaser.Structs.Size#setMin + * @since 3.16.0 + * + * @param {number} [width=0] - The minimum allowed width of the Size component. + * @param {number} [height=width] - The minimum allowed height of the Size component. If not given, it will use the `width`. + * + * @return {this} This Size component instance. + */ + setMin: function (width, height) + { + if (width === undefined) { width = 0; } + if (height === undefined) { height = width; } + + this.minWidth = Clamp(width, 0, this.maxWidth); + this.minHeight = Clamp(height, 0, this.maxHeight); + + return this.setSize(this._width, this._height); + }, + + /** + * Set the maximum width and height values this Size component will allow. + * + * Setting this will automatically adjust both the `width` and `height` properties to ensure they are within range. + * + * Note that based on the aspect mode, and if this Size component has a parent set or not, the maximums set here + * _can_ be exceed in some situations. + * + * @method Phaser.Structs.Size#setMax + * @since 3.16.0 + * + * @param {number} [width=Number.MAX_VALUE] - The maximum allowed width of the Size component. + * @param {number} [height=width] - The maximum allowed height of the Size component. If not given, it will use the `width`. + * + * @return {this} This Size component instance. + */ + setMax: function (width, height) + { + if (width === undefined) { width = Number.MAX_VALUE; } + if (height === undefined) { height = width; } + + this.maxWidth = Clamp(width, this.minWidth, Number.MAX_VALUE); + this.maxHeight = Clamp(height, this.minHeight, Number.MAX_VALUE); + + return this.setSize(this._width, this._height); + }, + + /** + * Sets the width and height of this Size component based on the aspect mode. + * + * If the aspect mode is 'none' then calling this method will change the aspect ratio, otherwise the current + * aspect ratio is honored across all other modes. + * + * If snapTo values have been set then the given width and height are snapped first, prior to any further + * adjustment via min/max values, or a parent. + * + * If minimum and/or maximum dimensions have been specified, the values given to this method will be clamped into + * that range prior to adjustment, but may still exceed them depending on the aspect mode. + * + * If this Size component has a parent set, and the aspect mode is `fit` or `envelop`, then the given sizes will + * be clamped to the range specified by the parent. + * + * @method Phaser.Structs.Size#setSize + * @since 3.16.0 + * + * @param {number} [width=0] - The new width of the Size component. + * @param {number} [height=width] - The new height of the Size component. If not given, it will use the `width`. + * + * @return {this} This Size component instance. + */ + setSize: function (width, height) + { + if (width === undefined) { width = 0; } + if (height === undefined) { height = width; } + + switch (this.aspectMode) + { + case Size.NONE: + this._width = this.getNewWidth(SnapFloor(width, this.snapTo.x)); + this._height = this.getNewHeight(SnapFloor(height, this.snapTo.y)); + this.aspectRatio = (this._height === 0) ? 1 : this._width / this._height; + break; + + case Size.WIDTH_CONTROLS_HEIGHT: + this._width = this.getNewWidth(SnapFloor(width, this.snapTo.x)); + this._height = this.getNewHeight(this._width * (1 / this.aspectRatio), false); + break; + + case Size.HEIGHT_CONTROLS_WIDTH: + this._height = this.getNewHeight(SnapFloor(height, this.snapTo.y)); + this._width = this.getNewWidth(this._height * this.aspectRatio, false); + break; + + case Size.FIT: + this.constrain(width, height, true); + break; + + case Size.ENVELOP: + this.constrain(width, height, false); + break; + } + + return this; + }, + + /** + * Sets a new aspect ratio, overriding what was there previously. + * + * It then calls `setSize` immediately using the current dimensions. + * + * @method Phaser.Structs.Size#setAspectRatio + * @since 3.16.0 + * + * @param {number} ratio - The new aspect ratio. + * + * @return {this} This Size component instance. + */ + setAspectRatio: function (ratio) + { + this.aspectRatio = ratio; + + return this.setSize(this._width, this._height); + }, + + /** + * Sets a new width and height for this Size component and updates the aspect ratio based on them. + * + * It _doesn't_ change the `aspectMode` and still factors in size limits such as the min max and parent bounds. + * + * @method Phaser.Structs.Size#resize + * @since 3.16.0 + * + * @param {number} width - The new width of the Size component. + * @param {number} [height=width] - The new height of the Size component. If not given, it will use the `width`. + * + * @return {this} This Size component instance. + */ + resize: function (width, height) + { + this._width = this.getNewWidth(SnapFloor(width, this.snapTo.x)); + this._height = this.getNewHeight(SnapFloor(height, this.snapTo.y)); + this.aspectRatio = (this._height === 0) ? 1 : this._width / this._height; + + return this; + }, + + /** + * Takes a new width and passes it through the min/max clamp and then checks it doesn't exceed the parent width. + * + * @method Phaser.Structs.Size#getNewWidth + * @since 3.16.0 + * + * @param {number} value - The value to clamp and check. + * @param {boolean} [checkParent=true] - Check the given value against the parent, if set. + * + * @return {number} The modified width value. + */ + getNewWidth: function (value, checkParent) + { + if (checkParent === undefined) { checkParent = true; } + + value = Clamp(value, this.minWidth, this.maxWidth); + + if (checkParent && this._parent && value > this._parent.width) + { + value = Math.max(this.minWidth, this._parent.width); + } + + return value; + }, + + /** + * Takes a new height and passes it through the min/max clamp and then checks it doesn't exceed the parent height. + * + * @method Phaser.Structs.Size#getNewHeight + * @since 3.16.0 + * + * @param {number} value - The value to clamp and check. + * @param {boolean} [checkParent=true] - Check the given value against the parent, if set. + * + * @return {number} The modified height value. + */ + getNewHeight: function (value, checkParent) + { + if (checkParent === undefined) { checkParent = true; } + + value = Clamp(value, this.minHeight, this.maxHeight); + + if (checkParent && this._parent && value > this._parent.height) + { + value = Math.max(this.minHeight, this._parent.height); + } + + return value; + }, + + /** + * The current `width` and `height` are adjusted to fit inside the given dimensions, while keeping the aspect ratio. + * + * If `fit` is true there may be some space inside the target area which is not covered if its aspect ratio differs. + * If `fit` is false the size may extend further out than the target area if the aspect ratios differ. + * + * If this Size component has a parent set, then the width and height passed to this method will be clamped so + * it cannot exceed that of the parent. + * + * @method Phaser.Structs.Size#constrain + * @since 3.16.0 + * + * @param {number} [width=0] - The new width of the Size component. + * @param {number} [height] - The new height of the Size component. If not given, it will use the width value. + * @param {boolean} [fit=true] - Perform a `fit` (true) constraint, or an `envelop` (false) constraint. + * + * @return {this} This Size component instance. + */ + constrain: function (width, height, fit) + { + if (width === undefined) { width = 0; } + if (height === undefined) { height = width; } + if (fit === undefined) { fit = true; } + + width = this.getNewWidth(width); + height = this.getNewHeight(height); + + var snap = this.snapTo; + var newRatio = (height === 0) ? 1 : width / height; + + if ((fit && this.aspectRatio > newRatio) || (!fit && this.aspectRatio < newRatio)) + { + // We need to change the height to fit the width + + width = SnapFloor(width, snap.x); + + height = width / this.aspectRatio; + + if (snap.y > 0) + { + height = SnapFloor(height, snap.y); + + // Reduce the width accordingly + width = height * this.aspectRatio; + } + } + else if ((fit && this.aspectRatio < newRatio) || (!fit && this.aspectRatio > newRatio)) + { + // We need to change the width to fit the height + + height = SnapFloor(height, snap.y); + + width = height * this.aspectRatio; + + if (snap.x > 0) + { + width = SnapFloor(width, snap.x); + + // Reduce the height accordingly + height = width * (1 / this.aspectRatio); + } + } + + this._width = width; + this._height = height; + + return this; + }, + + /** + * The current `width` and `height` are adjusted to fit inside the given dimensions, while keeping the aspect ratio. + * + * There may be some space inside the target area which is not covered if its aspect ratio differs. + * + * If this Size component has a parent set, then the width and height passed to this method will be clamped so + * it cannot exceed that of the parent. + * + * @method Phaser.Structs.Size#fitTo + * @since 3.16.0 + * + * @param {number} [width=0] - The new width of the Size component. + * @param {number} [height] - The new height of the Size component. If not given, it will use the width value. + * + * @return {this} This Size component instance. + */ + fitTo: function (width, height) + { + return this.constrain(width, height, true); + }, + + /** + * The current `width` and `height` are adjusted so that they fully envelope the given dimensions, while keeping the aspect ratio. + * + * The size may extend further out than the target area if the aspect ratios differ. + * + * If this Size component has a parent set, then the values are clamped so that it never exceeds the parent + * on the longest axis. + * + * @method Phaser.Structs.Size#envelop + * @since 3.16.0 + * + * @param {number} [width=0] - The new width of the Size component. + * @param {number} [height] - The new height of the Size component. If not given, it will use the width value. + * + * @return {this} This Size component instance. + */ + envelop: function (width, height) + { + return this.constrain(width, height, false); + }, + + /** + * Sets the width of this Size component. + * + * Depending on the aspect mode, changing the width may also update the height and aspect ratio. + * + * @method Phaser.Structs.Size#setWidth + * @since 3.16.0 + * + * @param {number} width - The new width of the Size component. + * + * @return {this} This Size component instance. + */ + setWidth: function (value) + { + return this.setSize(value, this._height); + }, + + /** + * Sets the height of this Size component. + * + * Depending on the aspect mode, changing the height may also update the width and aspect ratio. + * + * @method Phaser.Structs.Size#setHeight + * @since 3.16.0 + * + * @param {number} height - The new height of the Size component. + * + * @return {this} This Size component instance. + */ + setHeight: function (value) + { + return this.setSize(this._width, value); + }, + + /** + * Returns a string representation of this Size component. + * + * @method Phaser.Structs.Size#toString + * @since 3.16.0 + * + * @return {string} A string representation of this Size component. + */ + toString: function () + { + return '[{ Size (width=' + this._width + ' height=' + this._height + ' aspectRatio=' + this.aspectRatio + ' aspectMode=' + this.aspectMode + ') }]'; + }, + + /** + * Sets the values of this Size component to the `element.style.width` and `height` + * properties of the given DOM Element. The properties are set as `px` values. + * + * @method Phaser.Structs.Size#setCSS + * @since 3.17.0 + * + * @param {HTMLElement} element - The DOM Element to set the CSS style on. + */ + setCSS: function (element) + { + if (element && element.style) + { + element.style.width = this._width + 'px'; + element.style.height = this._height + 'px'; + } + }, + + /** + * Copies the aspect mode, aspect ratio, width and height from this Size component + * to the given Size component. Note that the parent, if set, is not copied across. + * + * @method Phaser.Structs.Size#copy + * @since 3.16.0 + * + * @param {Phaser.Structs.Size} destination - The Size component to copy the values to. + * + * @return {Phaser.Structs.Size} The updated destination Size component. + */ + copy: function (destination) + { + destination.setAspectMode(this.aspectMode); + + destination.aspectRatio = this.aspectRatio; + + return destination.setSize(this.width, this.height); + }, + + /** + * Destroys this Size component. + * + * This clears the local properties and any parent object, if set. + * + * A destroyed Size component cannot be re-used. + * + * @method Phaser.Structs.Size#destroy + * @since 3.16.0 + */ + destroy: function () + { + this._parent = null; + this.snapTo = null; + }, + + /** + * The width of this Size component. + * + * This value is clamped to the range specified by `minWidth` and `maxWidth`, if enabled. + * + * A width can never be less than zero. + * + * Changing this value will automatically update the `height` if the aspect ratio lock is enabled. + * You can also use the `setWidth` and `getWidth` methods. + * + * @name Phaser.Structs.Size#width + * @type {number} + * @since 3.16.0 + */ + width: { + + get: function () + { + return this._width; + }, + + set: function (value) + { + this.setSize(value, this._height); + } + + }, + + /** + * The height of this Size component. + * + * This value is clamped to the range specified by `minHeight` and `maxHeight`, if enabled. + * + * A height can never be less than zero. + * + * Changing this value will automatically update the `width` if the aspect ratio lock is enabled. + * You can also use the `setHeight` and `getHeight` methods. + * + * @name Phaser.Structs.Size#height + * @type {number} + * @since 3.16.0 + */ + height: { + + get: function () + { + return this._height; + }, + + set: function (value) + { + this.setSize(this._width, value); + } + + } + +}); + +/** + * Do not make the size fit the aspect ratio. Change the ratio when the size changes. + * + * @name Phaser.Structs.Size.NONE + * @constant + * @type {number} + * @since 3.16.0 + */ +Size.NONE = 0; + +/** + * The height is automatically adjusted based on the width. + * + * @name Phaser.Structs.Size.WIDTH_CONTROLS_HEIGHT + * @constant + * @type {number} + * @since 3.16.0 + */ +Size.WIDTH_CONTROLS_HEIGHT = 1; + +/** + * The width is automatically adjusted based on the height. + * + * @name Phaser.Structs.Size.HEIGHT_CONTROLS_WIDTH + * @constant + * @type {number} + * @since 3.16.0 + */ +Size.HEIGHT_CONTROLS_WIDTH = 2; + +/** + * The width and height are automatically adjusted to fit inside the given target area, while keeping the aspect ratio. Depending on the aspect ratio there may be some space inside the area which is not covered. + * + * @name Phaser.Structs.Size.FIT + * @constant + * @type {number} + * @since 3.16.0 + */ +Size.FIT = 3; + +/** + * The width and height are automatically adjusted to make the size cover the entire target area while keeping the aspect ratio. This may extend further out than the target size. + * + * @name Phaser.Structs.Size.ENVELOP + * @constant + * @type {number} + * @since 3.16.0 + */ +Size.ENVELOP = 4; + +module.exports = Size; + + +/***/ }), + +/***/ 15238: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Process Queue Add Event. + * + * This event is dispatched by a Process Queue when a new item is successfully moved to its active list. + * + * You will most commonly see this used by a Scene's Update List when a new Game Object has been added. + * + * In that instance, listen to this event from within a Scene using: `this.sys.updateList.on('add', listener)`. + * + * @event Phaser.Structs.Events#PROCESS_QUEUE_ADD + * @type {string} + * @since 3.20.0 + * + * @param {*} item - The item that was added to the Process Queue. + */ +module.exports = 'add'; + + +/***/ }), + +/***/ 56187: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Process Queue Remove Event. + * + * This event is dispatched by a Process Queue when a new item is successfully removed from its active list. + * + * You will most commonly see this used by a Scene's Update List when a Game Object has been removed. + * + * In that instance, listen to this event from within a Scene using: `this.sys.updateList.on('remove', listener)`. + * + * @event Phaser.Structs.Events#PROCESS_QUEUE_REMOVE + * @type {string} + * @since 3.20.0 + * + * @param {*} item - The item that was removed from the Process Queue. + */ +module.exports = 'remove'; + + +/***/ }), + +/***/ 82348: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Structs.Events + */ + +module.exports = { + + PROCESS_QUEUE_ADD: __webpack_require__(15238), + PROCESS_QUEUE_REMOVE: __webpack_require__(56187) + +}; + + +/***/ }), + +/***/ 41392: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Structs + */ + +module.exports = { + + Events: __webpack_require__(82348), + List: __webpack_require__(73162), + Map: __webpack_require__(90330), + ProcessQueue: __webpack_require__(25774), + RTree: __webpack_require__(59542), + Size: __webpack_require__(86555) + +}; + + +/***/ }), + +/***/ 57382: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Clamp = __webpack_require__(45319); +var Color = __webpack_require__(40987); +var CONST = __webpack_require__(8054); +var IsSizePowerOfTwo = __webpack_require__(50030); +var Texture = __webpack_require__(79237); + +/** + * @classdesc + * A Canvas Texture is a special kind of Texture that is backed by an HTML Canvas Element as its source. + * + * You can use the properties of this texture to draw to the canvas element directly, using all of the standard + * canvas operations available in the browser. Any Game Object can be given this texture and will render with it. + * + * Note: When running under WebGL the Canvas Texture needs to re-generate its base WebGLTexture and reupload it to + * the GPU every time you modify it, otherwise the changes you make to this texture will not be visible. To do this + * you should call `CanvasTexture.refresh()` once you are finished with your changes to the canvas. Try and keep + * this to a minimum, especially on large canvas sizes, or you may inadvertently thrash the GPU by constantly uploading + * texture data to it. This restriction does not apply if using the Canvas Renderer. + * + * It starts with only one frame that covers the whole of the canvas. You can add further frames, that specify + * sections of the canvas using the `add` method. + * + * Should you need to resize the canvas use the `setSize` method so that it accurately updates all of the underlying + * texture data as well. Forgetting to do this (i.e. by changing the canvas size directly from your code) could cause + * graphical errors. + * + * @class CanvasTexture + * @extends Phaser.Textures.Texture + * @memberof Phaser.Textures + * @constructor + * @since 3.7.0 + * + * @param {Phaser.Textures.TextureManager} manager - A reference to the Texture Manager this Texture belongs to. + * @param {string} key - The unique string-based key of this Texture. + * @param {HTMLCanvasElement} source - The canvas element that is used as the base of this texture. + * @param {number} width - The width of the canvas. + * @param {number} height - The height of the canvas. + */ +var CanvasTexture = new Class({ + + Extends: Texture, + + initialize: + + function CanvasTexture (manager, key, source, width, height) + { + Texture.call(this, manager, key, source, width, height); + + this.add('__BASE', 0, 0, 0, width, height); + + /** + * A reference to the Texture Source of this Canvas. + * + * @name Phaser.Textures.CanvasTexture#_source + * @type {Phaser.Textures.TextureSource} + * @private + * @since 3.7.0 + */ + this._source = this.frames['__BASE'].source; + + /** + * The source Canvas Element. + * + * @name Phaser.Textures.CanvasTexture#canvas + * @readonly + * @type {HTMLCanvasElement} + * @since 3.7.0 + */ + this.canvas = this._source.image; + + /** + * The 2D Canvas Rendering Context. + * + * @name Phaser.Textures.CanvasTexture#context + * @readonly + * @type {CanvasRenderingContext2D} + * @since 3.7.0 + */ + this.context = this.canvas.getContext('2d', { willReadFrequently: true }); + + /** + * The width of the Canvas. + * This property is read-only, if you wish to change it use the `setSize` method. + * + * @name Phaser.Textures.CanvasTexture#width + * @readonly + * @type {number} + * @since 3.7.0 + */ + this.width = width; + + /** + * The height of the Canvas. + * This property is read-only, if you wish to change it use the `setSize` method. + * + * @name Phaser.Textures.CanvasTexture#height + * @readonly + * @type {number} + * @since 3.7.0 + */ + this.height = height; + + /** + * The context image data. + * Use the `update` method to populate this when the canvas changes. + * + * @name Phaser.Textures.CanvasTexture#imageData + * @type {ImageData} + * @since 3.13.0 + */ + this.imageData = this.context.getImageData(0, 0, width, height); + + /** + * A Uint8ClampedArray view into the `buffer`. + * Use the `update` method to populate this when the canvas changes. + * Note that this is unavailable in some browsers, such as Epic Browser, due to their security restrictions. + * + * @name Phaser.Textures.CanvasTexture#data + * @type {Uint8ClampedArray} + * @since 3.13.0 + */ + this.data = null; + + if (this.imageData) + { + this.data = this.imageData.data; + } + + /** + * An Uint32Array view into the `buffer`. + * + * @name Phaser.Textures.CanvasTexture#pixels + * @type {Uint32Array} + * @since 3.13.0 + */ + this.pixels = null; + + /** + * An ArrayBuffer the same size as the context ImageData. + * + * @name Phaser.Textures.CanvasTexture#buffer + * @type {ArrayBuffer} + * @since 3.13.0 + */ + this.buffer; + + if (this.data) + { + if (this.imageData.data.buffer) + { + this.buffer = this.imageData.data.buffer; + this.pixels = new Uint32Array(this.buffer); + } + else if (window.ArrayBuffer) + { + this.buffer = new ArrayBuffer(this.imageData.data.length); + this.pixels = new Uint32Array(this.buffer); + } + else + { + this.pixels = this.imageData.data; + } + } + }, + + /** + * This re-creates the `imageData` from the current context. + * It then re-builds the ArrayBuffer, the `data` Uint8ClampedArray reference and the `pixels` Int32Array. + * + * Warning: This is a very expensive operation, so use it sparingly. + * + * @method Phaser.Textures.CanvasTexture#update + * @since 3.13.0 + * + * @return {Phaser.Textures.CanvasTexture} This CanvasTexture. + */ + update: function () + { + this.imageData = this.context.getImageData(0, 0, this.width, this.height); + + this.data = this.imageData.data; + + if (this.imageData.data.buffer) + { + this.buffer = this.imageData.data.buffer; + this.pixels = new Uint32Array(this.buffer); + } + else if (window.ArrayBuffer) + { + this.buffer = new ArrayBuffer(this.imageData.data.length); + this.pixels = new Uint32Array(this.buffer); + } + else + { + this.pixels = this.imageData.data; + } + + if (this.manager.game.config.renderType === CONST.WEBGL) + { + this.refresh(); + } + + return this; + }, + + /** + * Draws the given Image or Canvas element to this CanvasTexture, then updates the internal + * ImageData buffer and arrays. + * + * @method Phaser.Textures.CanvasTexture#draw + * @since 3.13.0 + * + * @param {number} x - The x coordinate to draw the source at. + * @param {number} y - The y coordinate to draw the source at. + * @param {(HTMLImageElement|HTMLCanvasElement)} source - The element to draw to this canvas. + * @param {boolean} [update=true] - Update the internal ImageData buffer and arrays. + * + * @return {Phaser.Textures.CanvasTexture} This CanvasTexture. + */ + draw: function (x, y, source, update) + { + if (update === undefined) { update = true; } + + this.context.drawImage(source, x, y); + + if (update) + { + this.update(); + } + + return this; + }, + + /** + * Draws the given texture frame to this CanvasTexture, then updates the internal + * ImageData buffer and arrays. + * + * @method Phaser.Textures.CanvasTexture#drawFrame + * @since 3.16.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} [frame] - The string-based name, or integer based index, of the Frame to get from the Texture. + * @param {number} [x=0] - The x coordinate to draw the source at. + * @param {number} [y=0] - The y coordinate to draw the source at. + * @param {boolean} [update=true] - Update the internal ImageData buffer and arrays. + * + * @return {Phaser.Textures.CanvasTexture} This CanvasTexture. + */ + drawFrame: function (key, frame, x, y, update) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (update === undefined) { update = true; } + + var textureFrame = this.manager.getFrame(key, frame); + + if (textureFrame) + { + var cd = textureFrame.canvasData; + + var width = textureFrame.cutWidth; + var height = textureFrame.cutHeight; + var res = textureFrame.source.resolution; + + this.context.drawImage( + textureFrame.source.image, + cd.x, cd.y, + width, + height, + x, y, + width / res, + height / res + ); + + if (update) + { + this.update(); + } + } + + return this; + }, + + /** + * Sets a pixel in the CanvasTexture to the given color and alpha values. + * + * This is an expensive operation to run in large quantities, so use sparingly. + * + * @method Phaser.Textures.CanvasTexture#setPixel + * @since 3.16.0 + * + * @param {number} x - The x coordinate of the pixel to get. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} y - The y coordinate of the pixel to get. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} red - The red color value. A number between 0 and 255. + * @param {number} green - The green color value. A number between 0 and 255. + * @param {number} blue - The blue color value. A number between 0 and 255. + * @param {number} [alpha=255] - The alpha value. A number between 0 and 255. + * + * @return {this} This CanvasTexture. + */ + setPixel: function (x, y, red, green, blue, alpha) + { + if (alpha === undefined) { alpha = 255; } + + x = Math.abs(Math.floor(x)); + y = Math.abs(Math.floor(y)); + + var index = this.getIndex(x, y); + + if (index > -1) + { + var imageData = this.context.getImageData(x, y, 1, 1); + + imageData.data[0] = red; + imageData.data[1] = green; + imageData.data[2] = blue; + imageData.data[3] = alpha; + + this.context.putImageData(imageData, x, y); + } + + return this; + }, + + /** + * Puts the ImageData into the context of this CanvasTexture at the given coordinates. + * + * @method Phaser.Textures.CanvasTexture#putData + * @since 3.16.0 + * + * @param {ImageData} imageData - The ImageData to put at the given location. + * @param {number} x - The x coordinate to put the imageData. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} y - The y coordinate to put the imageData. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} [dirtyX=0] - Horizontal position (x coordinate) of the top-left corner from which the image data will be extracted. + * @param {number} [dirtyY=0] - Vertical position (x coordinate) of the top-left corner from which the image data will be extracted. + * @param {number} [dirtyWidth] - Width of the rectangle to be painted. Defaults to the width of the image data. + * @param {number} [dirtyHeight] - Height of the rectangle to be painted. Defaults to the height of the image data. + * + * @return {this} This CanvasTexture. + */ + putData: function (imageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) + { + if (dirtyX === undefined) { dirtyX = 0; } + if (dirtyY === undefined) { dirtyY = 0; } + if (dirtyWidth === undefined) { dirtyWidth = imageData.width; } + if (dirtyHeight === undefined) { dirtyHeight = imageData.height; } + + this.context.putImageData(imageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight); + + return this; + }, + + /** + * Gets an ImageData region from this CanvasTexture from the position and size specified. + * You can write this back using `CanvasTexture.putData`, or manipulate it. + * + * @method Phaser.Textures.CanvasTexture#getData + * @since 3.16.0 + * + * @param {number} x - The x coordinate of the top-left of the area to get the ImageData from. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} y - The y coordinate of the top-left of the area to get the ImageData from. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} width - The width of the rectangle from which the ImageData will be extracted. Positive values are to the right, and negative to the left. + * @param {number} height - The height of the rectangle from which the ImageData will be extracted. Positive values are down, and negative are up. + * + * @return {ImageData} The ImageData extracted from this CanvasTexture. + */ + getData: function (x, y, width, height) + { + x = Clamp(Math.floor(x), 0, this.width - 1); + y = Clamp(Math.floor(y), 0, this.height - 1); + width = Clamp(width, 1, this.width - x); + height = Clamp(height, 1, this.height - y); + + var imageData = this.context.getImageData(x, y, width, height); + + return imageData; + }, + + /** + * Get the color of a specific pixel from this texture and store it in a Color object. + * + * If you have drawn anything to this CanvasTexture since it was created you must call `CanvasTexture.update` to refresh the array buffer, + * otherwise this may return out of date color values, or worse - throw a run-time error as it tries to access an array element that doesn't exist. + * + * @method Phaser.Textures.CanvasTexture#getPixel + * @since 3.13.0 + * + * @param {number} x - The x coordinate of the pixel to get. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} y - The y coordinate of the pixel to get. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {Phaser.Display.Color} [out] - A Color object to store the pixel values in. If not provided a new Color object will be created. + * + * @return {Phaser.Display.Color} An object with the red, green, blue and alpha values set in the r, g, b and a properties. + */ + getPixel: function (x, y, out) + { + if (!out) + { + out = new Color(); + } + + var index = this.getIndex(x, y); + + if (index > -1) + { + var data = this.data; + + var r = data[index + 0]; + var g = data[index + 1]; + var b = data[index + 2]; + var a = data[index + 3]; + + out.setTo(r, g, b, a); + } + + return out; + }, + + /** + * Returns an array containing all of the pixels in the given region. + * + * If the requested region extends outside the bounds of this CanvasTexture, + * the region is truncated to fit. + * + * If you have drawn anything to this CanvasTexture since it was created you must call `CanvasTexture.update` to refresh the array buffer, + * otherwise this may return out of date color values, or worse - throw a run-time error as it tries to access an array element that doesn't exist. + * + * @method Phaser.Textures.CanvasTexture#getPixels + * @since 3.16.0 + * + * @param {number} [x=0] - The x coordinate of the top-left of the region. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} [y=0] - The y coordinate of the top-left of the region. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} [width] - The width of the region to get. Must be an integer. Defaults to the canvas width if not given. + * @param {number} [height] - The height of the region to get. Must be an integer. If not given will be set to the `width`. + * + * @return {Phaser.Types.Textures.PixelConfig[][]} A 2d array of Pixel objects. + */ + getPixels: function (x, y, width, height) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.width; } + if (height === undefined) { height = width; } + + x = Math.abs(Math.round(x)); + y = Math.abs(Math.round(y)); + + var left = Clamp(x, 0, this.width); + var right = Clamp(x + width, 0, this.width); + var top = Clamp(y, 0, this.height); + var bottom = Clamp(y + height, 0, this.height); + + var pixel = new Color(); + + var out = []; + + for (var py = top; py < bottom; py++) + { + var row = []; + + for (var px = left; px < right; px++) + { + pixel = this.getPixel(px, py, pixel); + + row.push({ x: px, y: py, color: pixel.color, alpha: pixel.alphaGL }); + } + + out.push(row); + } + + return out; + }, + + /** + * Returns the Image Data index for the given pixel in this CanvasTexture. + * + * The index can be used to read directly from the `this.data` array. + * + * The index points to the red value in the array. The subsequent 3 indexes + * point to green, blue and alpha respectively. + * + * @method Phaser.Textures.CanvasTexture#getIndex + * @since 3.16.0 + * + * @param {number} x - The x coordinate of the pixel to get. Must lay within the dimensions of this CanvasTexture and be an integer. + * @param {number} y - The y coordinate of the pixel to get. Must lay within the dimensions of this CanvasTexture and be an integer. + * + * @return {number} + */ + getIndex: function (x, y) + { + x = Math.abs(Math.round(x)); + y = Math.abs(Math.round(y)); + + if (x < this.width && y < this.height) + { + return (x + y * this.width) * 4; + } + else + { + return -1; + } + }, + + /** + * This should be called manually if you are running under WebGL. + * It will refresh the WebGLTexture from the Canvas source. Only call this if you know that the + * canvas has changed, as there is a significant GPU texture allocation cost involved in doing so. + * + * @method Phaser.Textures.CanvasTexture#refresh + * @since 3.7.0 + * + * @return {Phaser.Textures.CanvasTexture} This CanvasTexture. + */ + refresh: function () + { + this._source.update(); + + return this; + }, + + /** + * Gets the Canvas Element. + * + * @method Phaser.Textures.CanvasTexture#getCanvas + * @since 3.7.0 + * + * @return {HTMLCanvasElement} The Canvas DOM element this texture is using. + */ + getCanvas: function () + { + return this.canvas; + }, + + /** + * Gets the 2D Canvas Rendering Context. + * + * @method Phaser.Textures.CanvasTexture#getContext + * @since 3.7.0 + * + * @return {CanvasRenderingContext2D} The Canvas Rendering Context this texture is using. + */ + getContext: function () + { + return this.context; + }, + + /** + * Clears the given region of this Canvas Texture, resetting it back to transparent. + * If no region is given, the whole Canvas Texture is cleared. + * + * @method Phaser.Textures.CanvasTexture#clear + * @since 3.7.0 + * + * @param {number} [x=0] - The x coordinate of the top-left of the region to clear. + * @param {number} [y=0] - The y coordinate of the top-left of the region to clear. + * @param {number} [width] - The width of the region. + * @param {number} [height] - The height of the region. + * @param {boolean} [update=true] - Update the internal ImageData buffer and arrays. + * + * @return {Phaser.Textures.CanvasTexture} The Canvas Texture. + */ + clear: function (x, y, width, height, update) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.width; } + if (height === undefined) { height = this.height; } + if (update === undefined) { update = true; } + + this.context.clearRect(x, y, width, height); + + if (update) + { + this.update(); + } + + return this; + }, + + /** + * Changes the size of this Canvas Texture. + * + * @method Phaser.Textures.CanvasTexture#setSize + * @since 3.7.0 + * + * @param {number} width - The new width of the Canvas. + * @param {number} [height] - The new height of the Canvas. If not given it will use the width as the height. + * + * @return {Phaser.Textures.CanvasTexture} The Canvas Texture. + */ + setSize: function (width, height) + { + if (height === undefined) { height = width; } + + if (width !== this.width || height !== this.height) + { + // Update the Canvas + this.canvas.width = width; + this.canvas.height = height; + + // Update the Texture Source + this._source.width = width; + this._source.height = height; + this._source.isPowerOf2 = IsSizePowerOfTwo(width, height); + + // Update the Frame + this.frames['__BASE'].setSize(width, height, 0, 0); + + // Update this + this.width = width; + this.height = height; + + this.refresh(); + } + + return this; + }, + + /** + * Destroys this Texture and releases references to its sources and frames. + * + * @method Phaser.Textures.CanvasTexture#destroy + * @since 3.16.0 + */ + destroy: function () + { + Texture.prototype.destroy.call(this); + + this._source = null; + this.canvas = null; + this.context = null; + this.imageData = null; + this.data = null; + this.pixels = null; + this.buffer = null; + } + +}); + +module.exports = CanvasTexture; + + +/***/ }), + +/***/ 81320: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BlendModes = __webpack_require__(10312); +var Camera = __webpack_require__(38058); +var CanvasPool = __webpack_require__(27919); +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(8054); +var DrawingContext = __webpack_require__(87774); +var Frame = __webpack_require__(4327); +var GetFastValue = __webpack_require__(95540); +var Texture = __webpack_require__(79237); +var Utils = __webpack_require__(70554); +var DynamicTextureCommands = __webpack_require__(42538); +var TransformMatrix = __webpack_require__(61340); + +/** + * @classdesc + * A Dynamic Texture is a special texture that allows you to draw textures, frames and most kind of + * Game Objects directly to it. + * + * You can take many complex objects and draw them to this one texture, which can then be used as the + * base texture for other Game Objects, such as Sprites. Should you then update this texture, all + * Game Objects using it will instantly be updated as well, reflecting the changes immediately. + * + * It's a powerful way to generate dynamic textures at run-time that are WebGL friendly and don't invoke + * expensive GPU uploads on each change. + * + * ```js + * const t = this.textures.addDynamicTexture('player', 64, 128); + * // draw objects to t + * this.add.sprite(x, y, 'player'); + * this.render(); + * ``` + * + * Because this is a standard Texture within Phaser, you can add frames to it, meaning you can use it + * to generate sprite sheets, texture atlases or tile sets. + * + * Under WebGL1, a FrameBuffer, which is what this Dynamic Texture uses internally, cannot be anti-aliased. + * This means that when drawing objects such as Shapes or Graphics instances to this texture, they may appear + * to be drawn with no aliasing around the edges. This is a technical limitation of WebGL1. To get around it, + * create your shape as a texture in an art package, then draw that to this texture. + * + * In the event that the WebGL context is lost, this DynamicTexture will + * lose its contents. Once context is restored (signalled by the `restorewebgl` + * event), you can choose to redraw the contents of the DynamicTexture. + * You are responsible for the redrawing logic. + * + * @class DynamicTexture + * @extends Phaser.Textures.Texture + * @memberof Phaser.Textures + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Textures.TextureManager} manager - A reference to the Texture Manager this Texture belongs to. + * @param {string} key - The unique string-based key of this Texture. + * @param {number} [width=256] - The width of this Dymamic Texture in pixels. Defaults to 256 x 256. + * @param {number} [height=256] - The height of this Dymamic Texture in pixels. Defaults to 256 x 256. + * @param {boolean} [forceEven=true] - Force the given width and height to be rounded to even values. This significantly improves the rendering quality. Set to false if you know you need an odd sized texture. + */ +var DynamicTexture = new Class({ + + Extends: Texture, + + initialize: + + function DynamicTexture (manager, key, width, height, forceEven) + { + if (width === undefined) { width = 256; } + if (height === undefined) { height = 256; } + if (forceEven === undefined) { forceEven = true; } + + /** + * The internal data type of this object. + * + * @name Phaser.Textures.DynamicTexture#type + * @type {string} + * @readonly + * @since 3.60.0 + */ + this.type = 'DynamicTexture'; + + var renderer = manager.game.renderer; + + var isCanvas = (renderer && renderer.type === CONST.CANVAS); + + var source = (isCanvas) ? CanvasPool.create2D(this, width, height) : [ this ]; + + Texture.call(this, manager, key, source, width, height); + + this.add('__BASE', 0, 0, 0, width, height); + + /** + * A reference to either the Canvas or WebGL Renderer that the Game instance is using. + * + * @name Phaser.Textures.DynamicTexture#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.2.0 + */ + this.renderer = renderer; + + /** + * The width of this Dynamic Texture. + * + * Treat this property as read-only. Use the `setSize` method to change the size. + * + * @name Phaser.Textures.DynamicTexture#width + * @type {number} + * @since 3.60.0 + */ + this.width = -1; + + /** + * The height of this Dynamic Texture. + * + * Treat this property as read-only. Use the `setSize` method to change the size. + * + * @name Phaser.Textures.DynamicTexture#height + * @type {number} + * @since 3.60.0 + */ + this.height = -1; + + /** + * An array of commands that are used to draw to this Dynamic Texture. + * This is flushed by the `render` method. + * The `clear` method will also clear this array, then store itself. + * + * @name Phaser.Textures.DynamicTexture#commandBuffer + * @type {array} + * @since 4.0.0 + */ + this.commandBuffer = []; + + /** + * A reference to the Rendering Context belonging to the Canvas Element this Dynamic Texture is drawing to. + * + * @name Phaser.Textures.DynamicTexture#canvas + * @type {HTMLCanvasElement} + * @since 3.2.0 + */ + this.canvas = (isCanvas) ? source : null; + + /** + * The 2D Canvas Rendering Context. + * + * @name Phaser.Textures.DynamicTexture#context + * @readonly + * @type {CanvasRenderingContext2D} + * @since 3.7.0 + */ + this.context = (isCanvas) ? source.getContext('2d', { willReadFrequently: true }) : null; + + /** + * An internal Camera that can be used to move around this Dynamic Texture. + * + * Control it just like you would any Scene Camera. The difference is that it only impacts + * the placement of **Game Objects** (not textures) that you then draw to this texture. + * + * You can scroll, zoom and rotate this Camera. + * + * @name Phaser.Textures.DynamicTexture#camera + * @type {Phaser.Cameras.Scene2D.Camera} + * @since 3.12.0 + */ + this.camera = new Camera(0, 0, width, height).setScene(manager.game.scene.systemScene, false); + + /** + * The drawing context of this Dynamic Texture. + * This contains the framebuffer that the Dynamic Texture is drawing to. + * + * @name Phaser.Textures.DynamicTexture#drawingContext + * @type {Phaser.Renderer.WebGL.DrawingContext} + * @since 4.0.0 + */ + this.drawingContext = isCanvas ? null : new DrawingContext(renderer, { + width: width, + height: height, + camera: this.camera, + autoClear: false + }); + + if (!isCanvas) + { + var frame = this.get(); + frame.source.glTexture = this.drawingContext.texture; + } + + this.setSize(width, height, forceEven); + }, + + /** + * Resizes this Dynamic Texture to the new dimensions given. + * + * In WebGL it will destroy and then re-create the frame buffer being used by this Dynamic Texture. + * In Canvas it will resize the underlying canvas DOM element. + * + * Both approaches will erase everything currently drawn to this texture. + * + * If the dimensions given are the same as those already being used, calling this method will do nothing. + * + * @method Phaser.Textures.DynamicTexture#setSize + * @since 3.10.0 + * + * @param {number} width - The new width of this Dynamic Texture. + * @param {number} [height=width] - The new height of this Dynamic Texture. If not specified, will be set the same as the `width`. + * @param {boolean} [forceEven=true] - Force the given width and height to be rounded to even values. This significantly improves the rendering quality. Set to false if you know you need an odd sized texture. + * + * @return {this} This Dynamic Texture. + */ + setSize: function (width, height, forceEven) + { + if (height === undefined) { height = width; } + if (forceEven === undefined) { forceEven = true; } + + if (forceEven) + { + width = Math.floor(width); + height = Math.floor(height); + + if (width % 2 !== 0) + { + width++; + } + + if (height % 2 !== 0) + { + height++; + } + } + + var frame = this.get(); + var source = frame.source; + + if (width !== this.width || height !== this.height) + { + if (this.canvas) + { + this.canvas.width = width; + this.canvas.height = height; + } + + var drawingContext = this.drawingContext; + + if (drawingContext && (drawingContext.width !== width || drawingContext.height !== height)) + { + drawingContext.resize(width, height); + } + + this.camera.setSize(width, height); + + source.width = width; + source.height = height; + + frame.setSize(width, height); + + this.width = width; + this.height = height; + } + else + { + // Resize the frame + var baseFrame = this.getSourceImage(); + + if (frame.cutX + width > baseFrame.width) + { + width = baseFrame.width - frame.cutX; + } + + if (frame.cutY + height > baseFrame.height) + { + height = baseFrame.height - frame.cutY; + } + + frame.setSize(width, height, frame.cutX, frame.cutY); + } + + return this; + }, + + /** + * Render the buffered drawing commands to this Dynamic Texture. + * You must do this in order to see anything drawn to it. + * + * @method Phaser.Textures.DynamicTexture#render + * @since 4.0.0 + * @return {this} This Dynamic Texture instance. + */ + render: function () + { + if (this.commandBuffer.length === 0) + { + return; + } + + this.camera.preRender(); + + if (this.renderer.type === CONST.WEBGL) + { + this._renderWebGL(); + } + if (this.renderer.type === CONST.CANVAS) + { + this._renderCanvas(); + } + + return this; + }, + + /** + * Render the DynamicTexture using the WebGL render system. + * + * @method Phaser.Textures.DynamicTexture#_renderWebGL + * @since 4.0.0 + * @private + */ + _renderWebGL: function () + { + this.renderer.renderNodes.getNode('DynamicTextureHandler').run(this); + }, + + /** + * Render the DynamicTexture using the Canvas render system. + * + * @method Phaser.Textures.DynamicTexture#_renderCanvas + * @since 4.0.0 + * @private + */ + _renderCanvas: function () + { + var camera = this.camera; + var context = this.context; + var renderer = this.renderer; + var textureManager = this.manager; + + renderer.setContext(context); + + // Big list of reused variables. + var alpha, blendMode, blendModePrev, frame, height, key, originX, originY, rotation, scaleX, scaleY, tint, width, x, y; + + // Traverse commands. + var commandBuffer = this.commandBuffer; + var commandBufferLength = commandBuffer.length; + var preserveBuffer = false; + var eraseMode = false; + + for (var index = 0; index < commandBufferLength; index++) + { + var command = commandBuffer[index]; + + switch (command) + { + case DynamicTextureCommands.CLEAR: + { + x = commandBuffer[++index]; + y = commandBuffer[++index]; + width = commandBuffer[++index]; + height = commandBuffer[++index]; + + if (x !== undefined && y !== undefined && width !== undefined && height !== undefined) + { + context.clearRect(x, y, width, height); + } + else + { + context.save(); + context.setTransform(1, 0, 0, 1, 0, 0); + context.clearRect(0, 0, this.width, this.height); + context.restore(); + } + break; + } + + case DynamicTextureCommands.FILL: + { + var color = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + width = commandBuffer[++index]; + height = commandBuffer[++index]; + + alpha = (color >> 24 & 0xFF) / 255; + var r = (color >> 16 & 0xFF); + var g = (color >> 8 & 0xFF); + var b = (color & 0xFF); + + context.save(); + context.globalCompositeOperation = 'source-over'; + context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')'; + context.fillRect(x, y, width, height); + context.restore(); + + break; + } + + case DynamicTextureCommands.STAMP: + { + key = commandBuffer[++index]; + frame = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + alpha = commandBuffer[++index]; + tint = commandBuffer[++index]; + rotation = commandBuffer[++index]; + scaleX = commandBuffer[++index]; + scaleY = commandBuffer[++index]; + originX = commandBuffer[++index]; + originY = commandBuffer[++index]; + blendMode = commandBuffer[++index]; + + if (eraseMode) + { + blendMode = BlendModes.ERASE; + } + + var stamp = textureManager.resetStamp(alpha, tint); + + stamp.setPosition(x, y) + .setRotation(rotation) + .setScale(scaleX, scaleY) + .setTexture(key, frame) + .setOrigin(originX, originY) + .setBlendMode(blendMode); + + stamp.renderCanvas(renderer, stamp, camera, null); + + break; + } + + case DynamicTextureCommands.REPEAT: + { + key = commandBuffer[++index]; + frame = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + alpha = commandBuffer[++index]; + tint = commandBuffer[++index]; + rotation = commandBuffer[++index]; + scaleX = commandBuffer[++index]; + scaleY = commandBuffer[++index]; + originX = commandBuffer[++index]; + originY = commandBuffer[++index]; + blendMode = commandBuffer[++index]; + + width = commandBuffer[++index]; + height = commandBuffer[++index]; + var tilePositionX = commandBuffer[++index]; + var tilePositionY = commandBuffer[++index]; + var tileRotation = commandBuffer[++index]; + var tileScaleX = commandBuffer[++index]; + var tileScaleY = commandBuffer[++index]; + + if (eraseMode) + { + blendMode = BlendModes.ERASE; + } + + var repeat = textureManager.resetTileSprite(alpha, tint); + + repeat.setPosition(x, y) + .setRotation(rotation) + .setScale(scaleX, scaleY) + .setTexture(key, frame) + .setSize(width, height) + .setOrigin(originX, originY) + .setBlendMode(blendMode) + .setTilePosition(tilePositionX, tilePositionY) + .setTileRotation(tileRotation) + .setTileScale(tileScaleX, tileScaleY); + + repeat.renderCanvas(renderer, repeat, camera, null); + + break; + } + + case DynamicTextureCommands.DRAW: + { + var object = commandBuffer[++index]; + x = commandBuffer[++index]; + y = commandBuffer[++index]; + + if (x !== undefined) + { + var prevX = object.x; + object.x = x; + } + + if (y !== undefined) + { + var prevY = object.y; + object.y = y; + } + + if (eraseMode) + { + blendModePrev = object.blendMode; + object.blendMode = BlendModes.ERASE; + } + + object.renderCanvas(renderer, object, camera, null); + + if (x !== undefined) + { + object.x = prevX; + } + + if (y !== undefined) + { + object.y = prevY; + } + + if (eraseMode) + { + object.blendMode = blendModePrev; + } + + break; + } + + case DynamicTextureCommands.SET_ERASE: + { + eraseMode = !!commandBuffer[++index]; + break; + } + + case DynamicTextureCommands.PRESERVE: + { + preserveBuffer = commandBuffer[++index]; + break; + } + + case DynamicTextureCommands.CALLBACK: + { + var callback = commandBuffer[++index]; + callback(); + break; + } + + case DynamicTextureCommands.CAPTURE: + { + object = commandBuffer[++index]; + var config = commandBuffer[++index]; + + var cacheConfig = this.startCapture(object, config); + object.renderCanvas( + renderer, + object, + config.camera || camera, + cacheConfig.transform + ); + this.finishCapture(object, cacheConfig); + break; + } + } + } + + if (!preserveBuffer) + { + commandBuffer.length = 0; + } + + // Finish rendering. + renderer.setContext(); + }, + + /** + * Fills this Dynamic Texture with the given color. + * + * By default it will fill the entire texture, however you can set it to fill a specific + * rectangular area by using the x, y, width and height arguments. + * + * The color should be given in hex format, i.e. 0xff0000 for red, 0x00ff00 for green, etc. + * + * @method Phaser.Textures.DynamicTexture#fill + * @since 3.2.0 + * + * @param {number} rgb - The color to fill this Dynamic Texture with, such as 0xff0000 for red. + * @param {number} [alpha=1] - The alpha value used by the fill. + * @param {number} [x=0] - The left coordinate of the fill rectangle. + * @param {number} [y=0] - The top coordinate of the fill rectangle. + * @param {number} [width=this.width] - The width of the fill rectangle. + * @param {number} [height=this.height] - The height of the fill rectangle. + * + * @return {this} This Dynamic Texture instance. + */ + fill: function (rgb, alpha, x, y, width, height) + { + if (alpha === undefined) { alpha = 1; } + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.width; } + if (height === undefined) { height = this.height; } + + var r = (rgb >> 16 & 0xFF); + var g = (rgb >> 8 & 0xFF); + var b = (rgb & 0xFF); + var color = Utils.getTintFromFloats(r / 255, g / 255, b / 255, alpha); + + this.commandBuffer.push( + DynamicTextureCommands.FILL, + color, + x, y, + width, height + ); + + return this; + }, + + /** + * Clears a portion or everything from this Dynamic Texture by erasing it and resetting it back to + * a blank, transparent, texture. To clear an area, specify the `x`, `y`, `width` and `height`. + * + * @method Phaser.Textures.DynamicTexture#clear + * @since 3.2.0 + * + * @param {number} [x=0] - The left coordinate of the fill rectangle. + * @param {number} [y=0] - The top coordinate of the fill rectangle. + * @param {number} [width=this.width] - The width of the fill rectangle. + * @param {number} [height=this.height] - The height of the fill rectangle. + * + * @return {this} This Dynamic Texture instance. + */ + clear: function (x, y, width, height) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.width; } + if (height === undefined) { height = this.height; } + + this.commandBuffer.push(DynamicTextureCommands.CLEAR, x, y, width, height); + + return this; + }, + + /** + * Takes the given texture key and frame and then stamps it at the given + * x and y coordinates. You can use the optional 'config' argument to provide + * lots more options about how the stamp is applied, including the alpha, + * tint, angle, scale and origin. + * + * By default, the frame will stamp on the x/y coordinates based on its center. + * + * If you wish to stamp from the top-left, set the config `originX` and + * `originY` properties both to zero. + * + * This method ignores the `camera` property of the Dynamic Texture. + * + * @method Phaser.Textures.DynamicTexture#stamp + * @since 3.60.0 + * + * @param {string} key - The key of the texture to be used, as stored in the Texture Manager. + * @param {(string|number)} [frame] - The name or index of the frame within the Texture. Set to `null` to skip this argument if not required. + * @param {number} [x=0] - The x position to draw the frame at. + * @param {number} [y=0] - The y position to draw the frame at. + * @param {Phaser.Types.Textures.StampConfig} [config] - The stamp configuration object, allowing you to set the alpha, tint, angle, scale and origin of the stamp. + * + * @return {this} This Dynamic Texture instance. + */ + stamp: function (key, frame, x, y, config) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + var alpha = GetFastValue(config, 'alpha', 1); + var tint = GetFastValue(config, 'tint', 0xffffff); + var angle = GetFastValue(config, 'angle', 0); + var rotation = GetFastValue(config, 'rotation', 0); + var scale = GetFastValue(config, 'scale', 1); + var scaleX = GetFastValue(config, 'scaleX', scale); + var scaleY = GetFastValue(config, 'scaleY', scale); + var originX = GetFastValue(config, 'originX', 0.5); + var originY = GetFastValue(config, 'originY', 0.5); + var blendMode = GetFastValue(config, 'blendMode', 0); + + if (angle !== 0) + { + rotation = angle * Math.PI / 180; + } + + this.commandBuffer.push( + DynamicTextureCommands.STAMP, + key, frame, + x, y, + alpha, tint, rotation, scaleX, scaleY, originX, originY, blendMode + ); + + return this; + }, + + /** + * Draws the given object, or an array of objects, to this Dynamic Texture using a blend mode of ERASE. + * This has the effect of erasing any filled pixels present in the objects from this texture. + * + * This method uses the `draw` method internally, + * and the parameters behave the same way. + * + * @method Phaser.Textures.DynamicTexture#erase + * @since 3.16.0 + * + * @param {any} entries - Any renderable Game Object, or Group, Container, Display List, Render Texture, Texture Frame, or an array of any of these. + * @param {number} [x=0] - The x position to draw the Frame at, or the offset applied to the object. + * @param {number} [y=0] - The y position to draw the Frame at, or the offset applied to the object. + * @param {number} [alpha=1] - The alpha value. Only used when drawing Texture Frames to this texture. Game Objects use their own alpha. + * @param {number} [tint=0xffffff] - The tint color value. Only used when drawing Texture Frames to this texture. Game Objects use their own tint. WebGL only. + * + * @return {this} This Dynamic Texture instance. + */ + erase: function (entries, x, y, alpha, tint) + { + var commandBuffer = this.commandBuffer; + var commandBufferLength = commandBuffer.length; + if ( + commandBuffer[commandBufferLength - 2] === DynamicTextureCommands.SET_ERASE && + !commandBuffer[commandBufferLength - 1] + ) + { + // The last command finished an ERASE operation, + // so we can just extend it. + commandBuffer.length -= 2; + } + else + { + commandBuffer.push(DynamicTextureCommands.SET_ERASE, true); + } + + this.draw(entries, x, y, alpha, tint); + + commandBuffer.push(DynamicTextureCommands.SET_ERASE, false); + + return this; + }, + + /** + * Draws the given object, or an array of objects, to this Dynamic Texture. + * + * It can accept any of the following: + * + * * Any renderable Game Object, such as a Sprite, Text, Graphics or TileSprite. + * * Tilemap Layers. + * * A Group. The contents of which will be iterated and drawn in turn. + * * A Container. The contents of which will be iterated fully, and drawn in turn. + * * A Scene Display List. Pass in `Scene.children` to draw the whole list. + * * Another Dynamic Texture, or a Render Texture. + * * A Texture Frame instance. + * * A string. This is used to look-up the texture from the Texture Manager. + * + * Note 1: You cannot draw a Dynamic Texture to itself. + * + * Note 2: GameObjects will use the camera, while textures and frames will not. + * Textures and frames are drawn using the `stamp` method. + * + * If passing in a Group or Container it will only draw children that return `true` + * when their `willRender()` method is called. I.e. a Container with 10 children, + * 5 of which have `visible=false` will only draw the 5 visible ones. + * + * If passing in an array of Game Objects it will draw them all, regardless if + * they pass a `willRender` check or not. + * + * You can pass in a string in which case it will look for a texture in the Texture + * Manager matching that string, and draw the base frame. If you need to specify + * exactly which frame to draw then use the method `drawFrame` instead. + * + * You can pass in the `x` and `y` coordinates to draw the objects at. The use of + * the coordinates differ based on what objects are being drawn. If the object is + * a Group, Container or Display List, the coordinates are _added_ to the positions + * of the children. For all other types of object, the coordinates are exact. + * For textures and frames, the `x` and `y` values are the middle of the texture. + * + * The `alpha` and `tint` values are only used by Texture Frames. + * Game Objects use their own alpha and tint values when being drawn. + * + * @method Phaser.Textures.DynamicTexture#draw + * @since 3.2.0 + * + * @param {any} entries - Any renderable Game Object, or Group, Container, Display List, other Render Texture, Texture Frame or an array of any of these. + * @param {number} [x=0] - The x position to draw the Frame at, or the offset applied to the object. + * @param {number} [y=0] - The y position to draw the Frame at, or the offset applied to the object. + * @param {number} [alpha=1] - The alpha value. Only used when drawing Texture Frames to this texture. Game Objects use their own alpha. + * @param {number} [tint=0xffffff] - The tint color value. Only used when drawing Texture Frames to this texture. Game Objects use their own tint. WebGL only. + * + * @return {this} This Dynamic Texture instance. + */ + draw: function (entries, x, y, alpha, tint) + { + if (!Array.isArray(entries)) + { + entries = [ entries ]; + } + + var len = entries.length; + + for (var i = 0; i < len; i++) + { + var entry = entries[i]; + + if (!entry || entry === this) + { + continue; + } + + if (entry.renderWebGL || entry.renderCanvas) + { + // Game Objects + this.commandBuffer.push(DynamicTextureCommands.DRAW, entry, x, y); + } + else if (entry.isParent || entry.list) + { + // Groups / Display Lists + var children = entry.getChildren(); + + for (var c = 0; c < children.length; c++) + { + var child = children[c]; + if (child.willRender(this.camera)) + { + this.draw(child, child.x + x || 0, child.y + y || 0); + } + } + } + else if (typeof entry === 'string') + { + // Texture key + this.stamp(entry, null, x, y, { alpha: alpha, tint: tint }); + } + else if (entry instanceof Frame) + { + // Texture Frame instance + this.stamp(entry.texture.key, entry, x, y, { alpha: alpha, tint: tint }); + } + else if (Array.isArray(entry)) + { + // Another Array + this.draw(entry, x, y, alpha, tint); + } + } + + return this; + }, + + /** + * Draws the given object to this Dynamic Texture. + * This allows you to draw the object as it appears in the game world, + * or with various parameter overrides in the config. + * + * @method Phaser.Textures.DynamicTexture#capture + * @since 4.0.0 + * + * @param {Phaser.GameObjects.GameObject} entry - Any renderable GameObject. + * @param {Phaser.Types.Textures.CaptureConfig} config - The configuration object for the capture. + * + * @return {this} This Dynamic Texture instance. + */ + capture: function (entry, config) + { + if (!config) { config = {}; } + + this.commandBuffer.push(DynamicTextureCommands.CAPTURE, entry, config); + + return this; + }, + + /** + * Prepares an object to be rendered using the `capture` method. + * This method is called automatically during rendering. + * Do not call it directly. + * + * @method Phaser.Textures.DynamicTexture#startCapture + * @since 4.0.0 + * + * @param {Phaser.GameObjects.GameObject} entry - The object to set up for capture. + * @param {Phaser.Types.Textures.CaptureConfig} config - The configuration object for the capture. + * + * @return {Phaser.Types.Textures.CaptureConfig} A configuration object containing the appropriate parent transform in `transform`, and the cached object properties in any fields that were overridden. + */ + startCapture: function (entry, config) + { + var cacheConfig = {}; + + // Compute the parent transform. + var parentTransform = undefined; + if (config.transform instanceof TransformMatrix) + { + parentTransform = config.transform; + } + else if (config.transform === 'world' && entry.parentContainer) + { + parentTransform = new TransformMatrix(); + var tempMatrix = new TransformMatrix(); + var parent = entry.parentContainer; + while (parent) + { + tempMatrix.applyITRS(parent.x, parent.y, parent.rotation, parent.scaleX, parent.scaleY); + parentTransform.multiply(tempMatrix); + parent = parent.parentContainer; + } + } + if (parentTransform) + { + cacheConfig.transform = parentTransform; + } + + if (config.camera) + { + // Ensure that parent transform exists. + if (!parentTransform) + { + parentTransform = new TransformMatrix(); + } + + // Ensure that camera transforms are applied. + config.camera.matrixExternal.multiply(parentTransform, parentTransform); + } + + // Cache and override the object properties. + if (config.x !== undefined) + { + cacheConfig.x = entry.x; + entry.x = config.x; + } + if (config.y !== undefined) + { + cacheConfig.y = entry.y; + entry.y = config.y; + } + if (config.rotation !== undefined) + { + cacheConfig.rotation = entry.rotation; + entry.rotation = config.rotation; + } + else if (config.angle !== undefined) + { + // Only apply angle if rotation is not defined. + cacheConfig.rotation = entry.rotation; + entry.angle = config.angle; + } + if (config.scaleX !== undefined) + { + cacheConfig.scaleX = entry.scaleX; + entry.scaleX = config.scaleX; + } + if (config.scaleY !== undefined) + { + cacheConfig.scaleY = entry.scaleY; + entry.scaleY = config.scaleY; + } + if (config.originX !== undefined) + { + cacheConfig.originX = entry.originX; + entry.originX = config.originX; + } + if (config.originY !== undefined) + { + cacheConfig.originY = entry.originY; + entry.originY = config.originY; + } + if (config.alpha !== undefined) + { + cacheConfig.alpha = entry.alpha; + entry.alpha = config.alpha; + } + if (config.tint !== undefined) + { + cacheConfig.tint = entry.tint; + entry.tint = config.tint; + } + if (config.blendMode !== undefined) + { + cacheConfig.blendMode = entry.blendMode; + entry.blendMode = config.blendMode; + } + + return cacheConfig; + }, + + /** + * Restores the object properties that were overridden during the `capture` method. + * This method is called automatically during rendering. + * Do not call it directly. + * + * @method Phaser.Textures.DynamicTexture#finishCapture + * @since 4.0.0 + * + * @param {Phaser.GameObjects.GameObject} entry - The GameObject to restore the properties on. + * @param {Phaser.Types.Textures.CaptureConfig} cacheConfig - The cached properties to restore. + */ + finishCapture: function (entry, cacheConfig) + { + // Restore the object properties. + if (cacheConfig.x !== undefined) + { + entry.x = cacheConfig.x; + } + if (cacheConfig.y !== undefined) + { + entry.y = cacheConfig.y; + } + if (cacheConfig.rotation !== undefined) + { + entry.rotation = cacheConfig.rotation; + } + if (cacheConfig.scaleX !== undefined) + { + entry.scaleX = cacheConfig.scaleX; + } + if (cacheConfig.scaleY !== undefined) + { + entry.scaleY = cacheConfig.scaleY; + } + if (cacheConfig.originX !== undefined) + { + entry.originX = cacheConfig.originX; + } + if (cacheConfig.originY !== undefined) + { + entry.originY = cacheConfig.originY; + } + if (cacheConfig.alpha !== undefined) + { + entry.alpha = cacheConfig.alpha; + } + if (cacheConfig.tint !== undefined) + { + entry.tint = cacheConfig.tint; + } + if (cacheConfig.blendMode !== undefined) + { + entry.blendMode = cacheConfig.blendMode; + } + }, + + /** + * Takes the given Texture Frame and draws it to this Dynamic Texture as a fill pattern, + * i.e. in a grid-layout based on the frame dimensions. + * It uses a `TileSprite` internally to draw the frame repeatedly. + * + * Textures are referenced by their string-based keys, as stored in the Texture Manager. + * + * You can optionally provide a position, width, height, alpha and tint value to apply to + * the frames before they are drawn. The position controls the top-left where the repeating + * fill will start from. The width and height control the size of the filled area. + * + * The position can be negative if required, but the dimensions cannot. + * + * This method respects the camera settings of the Dynamic Texture. + * + * @method Phaser.Textures.DynamicTexture#repeat + * @since 3.60.0 + * + * @param {string} key - The key of the texture to be used, as stored in the Texture Manager. + * @param {(string|number)} [frame] - The name or index of the frame within the Texture. Set to `null` to skip this argument if not required. + * @param {number} [x=0] - The x position to start drawing the frames from (can be negative to offset). + * @param {number} [y=0] - The y position to start drawing the frames from (can be negative to offset). + * @param {number} [width=this.width] - The width of the area to repeat the frame within. Defaults to the width of this Dynamic Texture. + * @param {number} [height=this.height] - The height of the area to repeat the frame within. Defaults to the height of this Dynamic Texture. + * @param {Phaser.Types.GameObjects.TileSprite.TileSpriteConfig} [config] - The configuration object for the TileSprite which repeats the texture, allowing you to set further properties on it. + * + * @return {this} This Dynamic Texture instance. + */ + repeat: function (key, frame, x, y, width, height, config) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.width; } + if (height === undefined) { height = this.height; } + + var alpha = GetFastValue(config, 'alpha', 1); + var tint = GetFastValue(config, 'tint', 0xffffff); + var angle = GetFastValue(config, 'angle', 0); + var rotation = GetFastValue(config, 'rotation', 0); + var scale = GetFastValue(config, 'scale', 1); + var scaleX = GetFastValue(config, 'scaleX', scale); + var scaleY = GetFastValue(config, 'scaleY', scale); + var originX = GetFastValue(config, 'originX', 0); + var originY = GetFastValue(config, 'originY', 0); + var blendMode = GetFastValue(config, 'blendMode', 0); + + if (angle !== 0) + { + rotation = angle * Math.PI / 180; + } + + var tilePositionX = GetFastValue(config, 'tilePositionX', 0); + var tilePositionY = GetFastValue(config, 'tilePositionY', 0); + var tileRotation = GetFastValue(config, 'tileRotation', 0); + var tileScaleX = GetFastValue(config, 'tileScaleX', 1); + var tileScaleY = GetFastValue(config, 'tileScaleY', 1); + + this.commandBuffer.push( + DynamicTextureCommands.REPEAT, + key, frame, + x, y, + alpha, tint, rotation, scaleX, scaleY, originX, originY, blendMode, + width, height, + tilePositionX, tilePositionY, tileRotation, tileScaleX, tileScaleY + ); + + return this; + }, + + /** + * Sets the preserve flag for this Dynamic Texture. + * Ordinarily, after each render, the command buffer is cleared. + * When this flag is set to `true`, the command buffer is preserved between renders. + * This makes it possible to repeat the same drawing commands on each render. + * + * Make sure to call `clear()` at the start if you don't want to accumulate + * drawing detail over the top of itself. + * + * @method Phaser.Textures.DynamicTexture#preserve + * @since 4.0.0 + * @param {boolean} preserve - Whether to preserve the command buffer after rendering. + * @returns {this} This Dynamic Texture instance. + */ + preserve: function (preserve) + { + this.commandBuffer.push(DynamicTextureCommands.PRESERVE, preserve); + + return this; + }, + + /** + * Adds a callback to run during the render process. + * This callback runs as a step in the command buffer. + * It can be used to set up conditions for the next draw step. + * + * Note that this will only execute after `render()` is called. + * + * @method Phaser.Textures.DynamicTexture#callback + * @since 4.0.0 + * @param {Function} callback - A callback function to run during the render process. + * @returns {this} This Dynamic Texture instance. + */ + callback: function (callback) + { + this.commandBuffer.push(DynamicTextureCommands.CALLBACK, callback); + + return this; + }, + + /** + * Takes a snapshot of the given area of this Dynamic Texture. + * + * The snapshot is taken immediately, but the results are returned via the given callback. + * + * To capture the whole Dynamic Texture see the `snapshot` method. + * To capture just a specific pixel, see the `snapshotPixel` method. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer + * into an ArrayBufferView. It then parses this, copying the contents to a temporary Canvas and finally + * creating an Image object from it, which is the image returned to the callback provided. + * + * All in all, this is a computationally expensive and blocking process, which gets more expensive + * the larger the resolution this Dynamic Texture has, so please be careful how you employ this in your game. + * + * @method Phaser.Textures.DynamicTexture#snapshotArea + * @since 3.19.0 + * + * @param {number} x - The x coordinate to grab from. + * @param {number} y - The y coordinate to grab from. + * @param {number} width - The width of the area to grab. + * @param {number} height - The height of the area to grab. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This Dynamic Texture instance. + */ + snapshotArea: function (x, y, width, height, callback, type, encoderOptions) + { + if (this.drawingContext) + { + this.renderer.snapshotFramebuffer(this.drawingContext.framebuffer, this.width, this.height, callback, false, x, y, width, height, type, encoderOptions); + } + else + { + this.renderer.snapshotCanvas(this.canvas, callback, false, x, y, width, height, type, encoderOptions); + } + + return this; + }, + + /** + * Takes a snapshot of the whole of this Dynamic Texture. + * + * The snapshot is taken immediately, but the results are returned via the given callback. + * + * To capture a portion of this Dynamic Texture see the `snapshotArea` method. + * To capture just a specific pixel, see the `snapshotPixel` method. + * + * Snapshots work by using the WebGL `readPixels` feature to grab every pixel from the frame buffer + * into an ArrayBufferView. It then parses this, copying the contents to a temporary Canvas and finally + * creating an Image object from it, which is the image returned to the callback provided. + * + * All in all, this is a computationally expensive and blocking process, which gets more expensive + * the larger the resolution this Dynamic Texture has, so please be careful how you employ this in your game. + * + * @method Phaser.Textures.DynamicTexture#snapshot + * @since 3.19.0 + * + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot image is created. + * @param {string} [type='image/png'] - The format of the image to create, usually `image/png` or `image/jpeg`. + * @param {number} [encoderOptions=0.92] - The image quality, between 0 and 1. Used for image formats with lossy compression, such as `image/jpeg`. + * + * @return {this} This Dynamic Texture instance. + */ + snapshot: function (callback, type, encoderOptions) + { + return this.snapshotArea(0, 0, this.width, this.height, callback, type, encoderOptions); + }, + + /** + * Takes a snapshot of the given pixel from this Dynamic Texture. + * + * The snapshot is taken immediately, but the results are returned via the given callback. + * + * To capture the whole Dynamic Texture see the `snapshot` method. + * To capture a portion of this Dynamic Texture see the `snapshotArea` method. + * + * Unlike the two other snapshot methods, this one will send your callback a `Color` object + * containing the color data for the requested pixel. It doesn't need to create an internal + * Canvas or Image object, so is a lot faster to execute, using less memory than the other snapshot methods. + * + * @method Phaser.Textures.DynamicTexture#snapshotPixel + * @since 3.19.0 + * + * @param {number} x - The x coordinate of the pixel to get. + * @param {number} y - The y coordinate of the pixel to get. + * @param {Phaser.Types.Renderer.Snapshot.SnapshotCallback} callback - The Function to invoke after the snapshot pixel data is extracted. + * + * @return {this} This Dynamic Texture instance. + */ + snapshotPixel: function (x, y, callback) + { + return this.snapshotArea(x, y, 1, 1, callback, 'pixel'); + }, + + /** + * Returns the underlying WebGLTextureWrapper, if not running in Canvas mode. + * + * @method Phaser.Textures.DynamicTexture#getWebGLTexture + * @since 3.60.0 + * + * @return {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The underlying WebGLTextureWrapper, if not running in Canvas mode. + */ + getWebGLTexture: function () + { + if (this.drawingContext) + { + return this.drawingContext.texture; + } + }, + + /** + * Sets this Dynamic Texture onto the TextureManager.Stamp + * and then calls its render method. + * + * @method Phaser.Textures.DynamicTexture#renderWebGL + * @since 3.60.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ + renderWebGL: function (renderer, src, camera, parentMatrix) + { + var stamp = this.manager.resetStamp(); + + stamp.setTexture(this); + stamp.setOrigin(0); + + stamp.renderWebGLStep(renderer, stamp, camera, parentMatrix); + }, + + /** + * This is a NOOP method. Bitmap Masks are not supported by the Canvas Renderer. + * + * @method Phaser.Textures.DynamicTexture#renderCanvas + * @since 3.60.0 + * + * @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The Canvas Renderer which would be rendered to. + * @param {Phaser.GameObjects.GameObject} mask - The masked Game Object which would be rendered. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to render to. + */ + renderCanvas: function () + { + // NOOP + }, + + /** + * Destroys this Texture and releases references to its sources and frames. + * + * @method Phaser.Textures.DynamicTexture#destroy + * @since 3.60.0 + */ + destroy: function () + { + var stamp = this.manager.stamp; + + if (stamp && stamp.texture === this) + { + this.manager.resetStamp(); + } + + Texture.prototype.destroy.call(this); + + CanvasPool.remove(this.canvas); + + if (this.drawingContext) + { + this.drawingContext.destroy(); + } + + this.camera.destroy(); + + this.canvas = null; + this.context = null; + this.renderer = null; + } + +}); + +module.exports = DynamicTexture; + + +/***/ }), + +/***/ 42538: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +module.exports = { + + CLEAR: 0, + FILL: 1, + STAMP: 2, + REPEAT: 3, + DRAW: 4, + SET_ERASE: 5, + PRESERVE: 6, + CALLBACK: 7, + CAPTURE: 8 + +}; + + +/***/ }), + +/***/ 4327: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Clamp = __webpack_require__(45319); +var Extend = __webpack_require__(79291); + +/** + * @classdesc + * A Frame is a section of a Texture. + * + * @class Frame + * @memberof Phaser.Textures + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture this Frame is a part of. + * @param {(number|string)} name - The name of this Frame. The name is unique within the Texture. + * @param {number} sourceIndex - The index of the TextureSource that this Frame is a part of. + * @param {number} x - The x coordinate of the top-left of this Frame. + * @param {number} y - The y coordinate of the top-left of this Frame. + * @param {number} width - The width of this Frame. + * @param {number} height - The height of this Frame. + */ +var Frame = new Class({ + + initialize: + + function Frame (texture, name, sourceIndex, x, y, width, height) + { + /** + * The Texture this Frame is a part of. + * + * @name Phaser.Textures.Frame#texture + * @type {Phaser.Textures.Texture} + * @since 3.0.0 + */ + this.texture = texture; + + /** + * The name of this Frame. + * The name is unique within the Texture. + * + * @name Phaser.Textures.Frame#name + * @type {string} + * @since 3.0.0 + */ + this.name = name; + + /** + * The TextureSource this Frame is part of. + * + * @name Phaser.Textures.Frame#source + * @type {Phaser.Textures.TextureSource} + * @since 3.0.0 + */ + this.source = texture.source[sourceIndex]; + + /** + * The index of the TextureSource in the Texture sources array. + * + * @name Phaser.Textures.Frame#sourceIndex + * @type {number} + * @since 3.0.0 + */ + this.sourceIndex = sourceIndex; + + /** + * X position within the source image to cut from. + * + * @name Phaser.Textures.Frame#cutX + * @type {number} + * @since 3.0.0 + */ + this.cutX; + + /** + * Y position within the source image to cut from. + * + * @name Phaser.Textures.Frame#cutY + * @type {number} + * @since 3.0.0 + */ + this.cutY; + + /** + * The width of the area in the source image to cut. + * + * @name Phaser.Textures.Frame#cutWidth + * @type {number} + * @since 3.0.0 + */ + this.cutWidth; + + /** + * The height of the area in the source image to cut. + * + * @name Phaser.Textures.Frame#cutHeight + * @type {number} + * @since 3.0.0 + */ + this.cutHeight; + + /** + * The X rendering offset of this Frame, taking trim into account. + * + * @name Phaser.Textures.Frame#x + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.x = 0; + + /** + * The Y rendering offset of this Frame, taking trim into account. + * + * @name Phaser.Textures.Frame#y + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.y = 0; + + /** + * The rendering width of this Frame, taking trim into account. + * + * @name Phaser.Textures.Frame#width + * @type {number} + * @since 3.0.0 + */ + this.width; + + /** + * The rendering height of this Frame, taking trim into account. + * + * @name Phaser.Textures.Frame#height + * @type {number} + * @since 3.0.0 + */ + this.height; + + /** + * Half the width, floored. + * Precalculated for the renderer. + * + * @name Phaser.Textures.Frame#halfWidth + * @type {number} + * @since 3.0.0 + */ + this.halfWidth; + + /** + * Half the height, floored. + * Precalculated for the renderer. + * + * @name Phaser.Textures.Frame#halfHeight + * @type {number} + * @since 3.0.0 + */ + this.halfHeight; + + /** + * The x center of this frame, floored. + * + * @name Phaser.Textures.Frame#centerX + * @type {number} + * @since 3.0.0 + */ + this.centerX; + + /** + * The y center of this frame, floored. + * + * @name Phaser.Textures.Frame#centerY + * @type {number} + * @since 3.0.0 + */ + this.centerY; + + /** + * The horizontal pivot point of this Frame. + * + * @name Phaser.Textures.Frame#pivotX + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.pivotX = 0; + + /** + * The vertical pivot point of this Frame. + * + * @name Phaser.Textures.Frame#pivotY + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.pivotY = 0; + + /** + * Does this Frame have a custom pivot point? + * + * @name Phaser.Textures.Frame#customPivot + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.customPivot = false; + + /** + * **CURRENTLY UNSUPPORTED** + * + * Is this frame is rotated or not in the Texture? + * Rotation allows you to use rotated frames in texture atlas packing. + * It has nothing to do with Sprite rotation. + * + * @name Phaser.Textures.Frame#rotated + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.rotated = false; + + /** + * Over-rides the Renderer setting. + * -1 = use Renderer Setting + * 0 = No rounding + * 1 = Round + * + * @name Phaser.Textures.Frame#autoRound + * @type {number} + * @default -1 + * @since 3.0.0 + */ + this.autoRound = -1; + + /** + * Any Frame specific custom data can be stored here. + * + * @name Phaser.Textures.Frame#customData + * @type {object} + * @since 3.0.0 + */ + this.customData = {}; + + /** + * WebGL UV u0 value. + * + * @name Phaser.Textures.Frame#u0 + * @type {number} + * @default 0 + * @since 3.11.0 + */ + this.u0 = 0; + + /** + * WebGL UV v0 value. + * + * @name Phaser.Textures.Frame#v0 + * @type {number} + * @default 0 + * @since 3.11.0 + */ + this.v0 = 0; + + /** + * WebGL UV u1 value. + * + * @name Phaser.Textures.Frame#u1 + * @type {number} + * @default 0 + * @since 3.11.0 + */ + this.u1 = 0; + + /** + * WebGL UV v1 value. + * + * @name Phaser.Textures.Frame#v1 + * @type {number} + * @default 0 + * @since 3.11.0 + */ + this.v1 = 0; + + /** + * The un-modified source frame, trim and UV data. + * + * @name Phaser.Textures.Frame#data + * @type {object} + * @private + * @since 3.0.0 + */ + this.data = { + cut: { + x: 0, + y: 0, + w: 0, + h: 0, + r: 0, + b: 0 + }, + trim: false, + sourceSize: { + w: 0, + h: 0 + }, + spriteSourceSize: { + x: 0, + y: 0, + w: 0, + h: 0, + r: 0, + b: 0 + }, + radius: 0, + drawImage: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + is3Slice: false, + scale9: false, + scale9Borders: { + x: 0, + y: 0, + w: 0, + h: 0 + } + }; + + this.setSize(width, height, x, y); + }, + + /** + * Sets the x and y position within the source image to cut from. + * + * @method Phaser.Textures.Frame#setCutPosition + * @since 3.85.0 + * + * @param {number} [x=0] - X position within the source image to cut from. + * @param {number} [y=0] - Y position within the source image to cut from. + * + * @return {this} This Frame object. + */ + setCutPosition: function (x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + this.cutX = x; + this.cutY = y; + + return this.updateUVs(); + }, + + /** + * Sets the width, and height of the area in the source image to cut. + * + * @method Phaser.Textures.Frame#setCutSize + * @since 3.85.0 + * + * @param {number} width - The width of the area in the source image to cut. + * @param {number} height - The height of the area in the source image to cut. + * + * @return {this} This Frame object. + */ + setCutSize: function (width, height) + { + this.cutWidth = width; + this.cutHeight = height; + + return this.updateUVs(); + }, + + /** + * Sets the width, height, x and y of this Frame. + * + * This is called automatically by the constructor + * and should rarely be changed on-the-fly. + * + * @method Phaser.Textures.Frame#setSize + * @since 3.7.0 + * + * @param {number} width - The width of the frame before being trimmed. + * @param {number} height - The height of the frame before being trimmed. + * @param {number} [x=0] - The x coordinate of the top-left of this Frame. + * @param {number} [y=0] - The y coordinate of the top-left of this Frame. + * + * @return {this} This Frame object. + */ + setSize: function (width, height, x, y) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + this.setCutPosition(x, y); + this.setCutSize(width, height); + + this.width = width; + this.height = height; + + this.halfWidth = Math.floor(width * 0.5); + this.halfHeight = Math.floor(height * 0.5); + + this.centerX = Math.floor(width / 2); + this.centerY = Math.floor(height / 2); + + var data = this.data; + var cut = data.cut; + + cut.x = x; + cut.y = y; + cut.w = width; + cut.h = height; + cut.r = x + width; + cut.b = y + height; + + data.sourceSize.w = width; + data.sourceSize.h = height; + + data.spriteSourceSize.w = width; + data.spriteSourceSize.h = height; + + data.radius = 0.5 * Math.sqrt(width * width + height * height); + + var drawImage = data.drawImage; + + drawImage.x = x; + drawImage.y = y; + drawImage.width = width; + drawImage.height = height; + + return this.updateUVs(); + }, + + /** + * If the frame was trimmed when added to the Texture Atlas, this records the trim and source data. + * + * @method Phaser.Textures.Frame#setTrim + * @since 3.0.0 + * + * @param {number} actualWidth - The width of the frame before being trimmed. + * @param {number} actualHeight - The height of the frame before being trimmed. + * @param {number} destX - The destination X position of the trimmed frame for display. + * @param {number} destY - The destination Y position of the trimmed frame for display. + * @param {number} destWidth - The destination width of the trimmed frame for display. + * @param {number} destHeight - The destination height of the trimmed frame for display. + * + * @return {this} This Frame object. + */ + setTrim: function (actualWidth, actualHeight, destX, destY, destWidth, destHeight) + { + var data = this.data; + var ss = data.spriteSourceSize; + + // Store actual values + + data.trim = true; + + data.sourceSize.w = actualWidth; + data.sourceSize.h = actualHeight; + + ss.x = destX; + ss.y = destY; + ss.w = destWidth; + ss.h = destHeight; + ss.r = destX + destWidth; + ss.b = destY + destHeight; + + // Adjust properties + this.x = destX; + this.y = destY; + + this.width = destWidth; + this.height = destHeight; + + this.halfWidth = destWidth * 0.5; + this.halfHeight = destHeight * 0.5; + + this.centerX = Math.floor(destWidth / 2); + this.centerY = Math.floor(destHeight / 2); + + return this.updateUVs(); + }, + + /** + * Sets the scale9 center rectangle values. + * + * Scale9 is a feature of Texture Packer, allowing you to define a nine-slice scaling grid. + * + * This is set automatically by the JSONArray and JSONHash parsers. + * + * @method Phaser.Textures.Frame#setScale9 + * @since 3.70.0 + * + * @param {number} x - The left coordinate of the center scale9 rectangle. + * @param {number} y - The top coordinate of the center scale9 rectangle. + * @param {number} width - The width of the center scale9 rectangle. + * @param {number} height - The height coordinate of the center scale9 rectangle. + * + * @return {this} This Frame object. + */ + setScale9: function (x, y, width, height) + { + var data = this.data; + + data.scale9 = true; + data.is3Slice = (y === 0 && height === this.height); + + data.scale9Borders.x = x; + data.scale9Borders.y = y; + data.scale9Borders.w = width; + data.scale9Borders.h = height; + + return this; + }, + + /** + * Takes a crop data object and, based on the rectangular region given, calculates the + * required UV coordinates in order to crop this Frame for WebGL and Canvas rendering. + * + * The crop size as well as coordinates can not exceed the the size of the frame. + * + * This is called directly by the Game Object Texture Components `setCrop` method. + * Please use that method to crop a Game Object. + * + * @method Phaser.Textures.Frame#setCropUVs + * @since 3.11.0 + * + * @param {object} crop - The crop data object. This is the `GameObject._crop` property. + * @param {number} x - The x coordinate to start the crop from. Cannot be negative or exceed the Frame width. + * @param {number} y - The y coordinate to start the crop from. Cannot be negative or exceed the Frame height. + * @param {number} width - The width of the crop rectangle. Cannot exceed the Frame width. + * @param {number} height - The height of the crop rectangle. Cannot exceed the Frame height. + * @param {boolean} flipX - Does the parent Game Object have flipX set? + * @param {boolean} flipY - Does the parent Game Object have flipY set? + * + * @return {object} The updated crop data object. + */ + setCropUVs: function (crop, x, y, width, height, flipX, flipY) + { + // Clamp the input values + + var cx = this.cutX; + var cy = this.cutY; + var cw = this.cutWidth; + var ch = this.cutHeight; + var rw = this.realWidth; + var rh = this.realHeight; + + x = Clamp(x, 0, rw); + y = Clamp(y, 0, rh); + + width = Clamp(width, 0, rw - x); + height = Clamp(height, 0, rh - y); + + var ox = cx + x; + var oy = cy + y; + var ow = width; + var oh = height; + + var data = this.data; + + if (data.trim) + { + var ss = data.spriteSourceSize; + + // Need to check for intersection between the cut area and the crop area + // If there is none, we set UV to be empty, otherwise set it to be the intersection area + + width = Clamp(width, 0, ss.x + cw - x); + height = Clamp(height, 0, ss.y + ch - y); + + var cropRight = x + width; + var cropBottom = y + height; + + var intersects = !(ss.r < x || ss.b < y || ss.x > cropRight || ss.y > cropBottom); + + if (intersects) + { + var ix = Math.max(ss.x, x); + var iy = Math.max(ss.y, y); + var iw = Math.min(ss.r, cropRight) - ix; + var ih = Math.min(ss.b, cropBottom) - iy; + + ow = iw; + oh = ih; + + if (flipX) + { + ox = cx + (cw - (ix - ss.x) - iw); + } + else + { + ox = cx + (ix - ss.x); + } + + if (flipY) + { + oy = cy + (ch - (iy - ss.y) - ih); + } + else + { + oy = cy + (iy - ss.y); + } + + x = ix; + y = iy; + + width = iw; + height = ih; + } + else + { + ox = 0; + oy = 0; + ow = 0; + oh = 0; + } + } + else + { + if (flipX) + { + ox = cx + (cw - x - width); + } + + if (flipY) + { + oy = cy + (ch - y - height); + } + } + + var tw = this.source.width; + var th = this.source.height; + + // Map the given coordinates into UV space, clamping to the 0-1 range. + + crop.u0 = Math.max(0, ox / tw); + crop.v0 = 1 - Math.max(0, oy / th); + crop.u1 = Math.min(1, (ox + ow) / tw); + crop.v1 = 1 - Math.min(1, (oy + oh) / th); + + crop.x = x; + crop.y = y; + + crop.cx = ox; + crop.cy = oy; + crop.cw = ow; + crop.ch = oh; + + crop.width = width; + crop.height = height; + + crop.flipX = flipX; + crop.flipY = flipY; + + return crop; + }, + + /** + * Takes a crop data object and recalculates the UVs based on the dimensions inside the crop object. + * Called automatically by `setFrame`. + * + * @method Phaser.Textures.Frame#updateCropUVs + * @since 3.11.0 + * + * @param {object} crop - The crop data object. This is the `GameObject._crop` property. + * @param {boolean} flipX - Does the parent Game Object have flipX set? + * @param {boolean} flipY - Does the parent Game Object have flipY set? + * + * @return {object} The updated crop data object. + */ + updateCropUVs: function (crop, flipX, flipY) + { + return this.setCropUVs(crop, crop.x, crop.y, crop.width, crop.height, flipX, flipY); + }, + + /** + * Directly sets the canvas and WebGL UV data for this frame. + * + * Use this if you need to override the values that are generated automatically + * when the Frame is created. + * + * @method Phaser.Textures.Frame#setUVs + * @since 3.50.0 + * + * @param {number} width - Width of this frame for the Canvas data. + * @param {number} height - Height of this frame for the Canvas data. + * @param {number} u0 - UV u0 value. + * @param {number} v0 - UV v0 value. + * @param {number} u1 - UV u1 value. + * @param {number} v1 - UV v1 value. + * + * @return {this} This Frame object. + */ + setUVs: function (width, height, u0, v0, u1, v1) + { + // Canvas data + + var cd = this.data.drawImage; + + cd.width = width; + cd.height = height; + + // WebGL data + + this.u0 = u0; + this.v0 = v0; + + this.u1 = u1; + this.v1 = v1; + + return this; + }, + + /** + * Updates the internal WebGL UV cache and the drawImage cache. + * + * @method Phaser.Textures.Frame#updateUVs + * @since 3.0.0 + * + * @return {this} This Frame object. + */ + updateUVs: function () + { + var cx = this.cutX; + var cy = this.cutY; + var cw = this.cutWidth; + var ch = this.cutHeight; + + // Canvas data + + var cd = this.data.drawImage; + + cd.width = cw; + cd.height = ch; + + // WebGL data + + var tw = this.source.width; + var th = this.source.height; + + this.u0 = cx / tw; + this.v0 = 1 - cy / th; + + this.u1 = (cx + cw) / tw; + this.v1 = 1 - (cy + ch) / th; + + return this; + }, + + /** + * Updates the internal WebGL UV cache. + * + * @method Phaser.Textures.Frame#updateUVsInverted + * @since 3.0.0 + * + * @return {this} This Frame object. + */ + updateUVsInverted: function () + { + var tw = this.source.width; + var th = this.source.height; + + this.u0 = (this.cutX + this.cutHeight) / tw; + this.v0 = 1 - this.cutY / th; + + this.u1 = this.cutX / tw; + this.v1 = 1 - (this.cutY + this.cutWidth) / th; + + return this; + }, + + /** + * Clones this Frame into a new Frame object. + * + * @method Phaser.Textures.Frame#clone + * @since 3.0.0 + * + * @return {Phaser.Textures.Frame} A clone of this Frame. + */ + clone: function () + { + var clone = new Frame(this.texture, this.name, this.sourceIndex); + + clone.cutX = this.cutX; + clone.cutY = this.cutY; + clone.cutWidth = this.cutWidth; + clone.cutHeight = this.cutHeight; + + clone.x = this.x; + clone.y = this.y; + + clone.width = this.width; + clone.height = this.height; + + clone.halfWidth = this.halfWidth; + clone.halfHeight = this.halfHeight; + + clone.centerX = this.centerX; + clone.centerY = this.centerY; + + clone.rotated = this.rotated; + + clone.data = Extend(true, clone.data, this.data); + + clone.updateUVs(); + + return clone; + }, + + /** + * Destroys this Frame by nulling its reference to the parent Texture and and data objects. + * + * @method Phaser.Textures.Frame#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.texture = null; + this.source = null; + this.customData = null; + this.data = null; + }, + + /** + * A reference to the Texture Source WebGL Texture that this Frame is using. + * + * @name Phaser.Textures.Frame#glTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @readonly + * @since 3.11.0 + */ + glTexture: { + + get: function () + { + return this.source.glTexture; + } + }, + + /** + * The width of the Frame in its un-trimmed, un-padded state, as prepared in the art package, + * before being packed. + * + * @name Phaser.Textures.Frame#realWidth + * @type {number} + * @readonly + * @since 3.0.0 + */ + realWidth: { + + get: function () + { + return this.data.sourceSize.w; + } + + }, + + /** + * The height of the Frame in its un-trimmed, un-padded state, as prepared in the art package, + * before being packed. + * + * @name Phaser.Textures.Frame#realHeight + * @type {number} + * @readonly + * @since 3.0.0 + */ + realHeight: { + + get: function () + { + return this.data.sourceSize.h; + } + + }, + + /** + * The radius of the Frame (derived from sqrt(w * w + h * h) / 2) + * + * @name Phaser.Textures.Frame#radius + * @type {number} + * @readonly + * @since 3.0.0 + */ + radius: { + + get: function () + { + return this.data.radius; + } + + }, + + /** + * Is the Frame trimmed or not? + * + * @name Phaser.Textures.Frame#trimmed + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + trimmed: { + + get: function () + { + return this.data.trim; + } + + }, + + /** + * Does the Frame have scale9 border data? + * + * @name Phaser.Textures.Frame#scale9 + * @type {boolean} + * @readonly + * @since 3.70.0 + */ + scale9: { + + get: function () + { + return this.data.scale9; + } + + }, + + /** + * If the Frame has scale9 border data, is it 3-slice or 9-slice data? + * + * @name Phaser.Textures.Frame#is3Slice + * @type {boolean} + * @readonly + * @since 3.70.0 + */ + is3Slice: { + + get: function () + { + return this.data.is3Slice; + } + + }, + + /** + * The Canvas drawImage data object. + * + * @name Phaser.Textures.Frame#canvasData + * @type {object} + * @readonly + * @since 3.0.0 + */ + canvasData: { + + get: function () + { + return this.data.drawImage; + } + + } + +}); + +module.exports = Frame; + + +/***/ }), + +/***/ 79237: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Frame = __webpack_require__(4327); +var TextureSource = __webpack_require__(11876); + +var TEXTURE_MISSING_ERROR = 'Texture "%s" has no frame "%s"'; + +/** + * @classdesc + * A Texture consists of a source, usually an Image from the Cache, and a collection of Frames. + * The Frames represent the different areas of the Texture. For example a texture atlas + * may have many Frames, one for each element within the atlas. Where-as a single image would have + * just one frame, that encompasses the whole image. + * + * Every Texture, no matter where it comes from, always has at least 1 frame called the `__BASE` frame. + * This frame represents the entirety of the source image. + * + * Textures are managed by the global TextureManager. This is a singleton class that is + * responsible for creating and delivering Textures and their corresponding Frames to Game Objects. + * + * Sprites and other Game Objects get the texture data they need from the TextureManager. + * + * @class Texture + * @memberof Phaser.Textures + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Textures.TextureManager} manager - A reference to the Texture Manager this Texture belongs to. + * @param {string} key - The unique string-based key of this Texture. + * @param {(HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]|Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper)} source - An array of sources that are used to create the texture. Usually Images, but can also be a Canvas. + * @param {number} [width] - The width of the Texture. This is optional and automatically derived from the source images. + * @param {number} [height] - The height of the Texture. This is optional and automatically derived from the source images. + */ +var Texture = new Class({ + + initialize: + + function Texture (manager, key, source, width, height) + { + if (!Array.isArray(source)) + { + source = [ source ]; + } + + /** + * A reference to the Texture Manager this Texture belongs to. + * + * @name Phaser.Textures.Texture#manager + * @type {Phaser.Textures.TextureManager} + * @since 3.0.0 + */ + this.manager = manager; + + /** + * The unique string-based key of this Texture. + * + * @name Phaser.Textures.Texture#key + * @type {string} + * @since 3.0.0 + */ + this.key = key; + + /** + * An array of TextureSource instances. + * These are unique to this Texture and contain the actual Image (or Canvas) data. + * + * @name Phaser.Textures.Texture#source + * @type {Phaser.Textures.TextureSource[]} + * @since 3.0.0 + */ + this.source = []; + + /** + * An array of TextureSource data instances. + * Used to store additional data images, such as normal maps or specular maps. + * + * @name Phaser.Textures.Texture#dataSource + * @type {array} + * @since 3.0.0 + */ + this.dataSource = []; + + /** + * A key-value object pair associating the unique Frame keys with the Frames objects. + * + * @name Phaser.Textures.Texture#frames + * @type {object} + * @since 3.0.0 + */ + this.frames = {}; + + /** + * Any additional data that was set in the source JSON (if any), + * or any extra data you'd like to store relating to this texture + * + * @name Phaser.Textures.Texture#customData + * @type {object} + * @since 3.0.0 + */ + this.customData = {}; + + /** + * The name of the first frame of the Texture. + * + * @name Phaser.Textures.Texture#firstFrame + * @type {string} + * @since 3.0.0 + */ + this.firstFrame = '__BASE'; + + /** + * The total number of Frames in this Texture, including the `__BASE` frame. + * + * A Texture will always contain at least 1 frame because every Texture contains a `__BASE` frame by default, + * in addition to any extra frames that have been added to it, such as when parsing a Sprite Sheet or Texture Atlas. + * + * @name Phaser.Textures.Texture#frameTotal + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.frameTotal = 0; + + /** + * Whether shaders using this texture should use special filtering code. + * This relies on shader support. + * + * If `null`, the game default will be used. + * + * @name Phaser.Textures.Texture#smoothPixelArt + * @type {?boolean} + * @default null + * @since 4.0.0 + */ + this.smoothPixelArt = null; + + // Load the Sources + for (var i = 0; i < source.length; i++) + { + this.source.push(new TextureSource(this, source[i], width, height)); + } + }, + + /** + * Adds a new Frame to this Texture. + * + * A Frame is a rectangular region of a TextureSource with a unique index or string-based key. + * + * The name given must be unique within this Texture. If it already exists, this method will return `null`. + * + * @method Phaser.Textures.Texture#add + * @since 3.0.0 + * + * @param {(number|string)} name - The name of this Frame. The name is unique within the Texture. + * @param {number} sourceIndex - The index of the TextureSource that this Frame is a part of. + * @param {number} x - The x coordinate of the top-left of this Frame. + * @param {number} y - The y coordinate of the top-left of this Frame. + * @param {number} width - The width of this Frame. + * @param {number} height - The height of this Frame. + * + * @return {?Phaser.Textures.Frame} The Frame that was added to this Texture, or `null` if the given name already exists. + */ + add: function (name, sourceIndex, x, y, width, height) + { + if (this.has(name)) + { + return null; + } + + var frame = new Frame(this, name, sourceIndex, x, y, width, height); + + this.frames[name] = frame; + + // Set the first frame of the Texture (other than __BASE) + // This is used to ensure we don't spam the display with entire + // atlases of sprite sheets, but instead just the first frame of them + // should the dev incorrectly specify the frame index + if (this.firstFrame === '__BASE') + { + this.firstFrame = name; + } + + this.frameTotal++; + + return frame; + }, + + /** + * Removes the given Frame from this Texture. The Frame is destroyed immediately. + * + * Any Game Objects using this Frame should stop using it _before_ you remove it, + * as it does not happen automatically. + * + * @method Phaser.Textures.Texture#remove + * @since 3.19.0 + * + * @param {string} name - The key of the Frame to remove. + * + * @return {boolean} True if a Frame with the matching key was removed from this Texture. + */ + remove: function (name) + { + if (this.has(name)) + { + var frame = this.get(name); + + frame.destroy(); + + delete this.frames[name]; + + return true; + } + + return false; + }, + + /** + * Checks to see if a Frame matching the given key exists within this Texture. + * + * @method Phaser.Textures.Texture#has + * @since 3.0.0 + * + * @param {string} name - The key of the Frame to check for. + * + * @return {boolean} True if a Frame with the matching key exists in this Texture. + */ + has: function (name) + { + return this.frames.hasOwnProperty(name); + }, + + /** + * Gets a Frame from this Texture based on either the key or the index of the Frame. + * + * In a Texture Atlas Frames are typically referenced by a key. + * In a Sprite Sheet Frames are referenced by an index. + * Passing no value for the name returns the base texture. + * + * @method Phaser.Textures.Texture#get + * @since 3.0.0 + * + * @param {(string|number)} [name] - The string-based name, or integer based index, of the Frame to get from this Texture. + * + * @return {Phaser.Textures.Frame} The Texture Frame. + */ + get: function (name) + { + // null, undefined, empty string, zero + if (!name) + { + name = this.firstFrame; + } + + var frame = this.frames[name]; + + if (!frame) + { + console.warn(TEXTURE_MISSING_ERROR, this.key, name); + + frame = this.frames[this.firstFrame]; + } + + return frame; + }, + + /** + * Takes the given TextureSource and returns the index of it within this Texture. + * If it's not in this Texture, it returns -1. + * Unless this Texture has multiple TextureSources, such as with a multi-atlas, this + * method will always return zero or -1. + * + * @method Phaser.Textures.Texture#getTextureSourceIndex + * @since 3.0.0 + * + * @param {Phaser.Textures.TextureSource} source - The TextureSource to check. + * + * @return {number} The index of the TextureSource within this Texture, or -1 if not in this Texture. + */ + getTextureSourceIndex: function (source) + { + for (var i = 0; i < this.source.length; i++) + { + if (this.source[i] === source) + { + return i; + } + } + + return -1; + }, + + /** + * Returns an array of all the Frames in the given TextureSource. + * + * @method Phaser.Textures.Texture#getFramesFromTextureSource + * @since 3.0.0 + * + * @param {number} sourceIndex - The index of the TextureSource to get the Frames from. + * @param {boolean} [includeBase=false] - Include the `__BASE` Frame in the output array? + * + * @return {Phaser.Textures.Frame[]} An array of Texture Frames. + */ + getFramesFromTextureSource: function (sourceIndex, includeBase) + { + if (includeBase === undefined) { includeBase = false; } + + var out = []; + + for (var frameName in this.frames) + { + if (frameName === '__BASE' && !includeBase) + { + continue; + } + + var frame = this.frames[frameName]; + + if (frame.sourceIndex === sourceIndex) + { + out.push(frame); + } + } + + return out; + }, + + /** + * Based on the given Texture Source Index, this method will get all of the Frames using + * that source and then work out the bounds that they encompass, returning them in an object. + * + * This is useful if this Texture is, for example, a sprite sheet within an Atlas, and you + * need to know the total bounds of the sprite sheet. + * + * @method Phaser.Textures.Texture#getFrameBounds + * @since 3.80.0 + * + * @param {number} [sourceIndex=0] - The index of the TextureSource to get the Frame bounds from. + * + * @return {Phaser.Types.Math.RectangleLike} An object containing the bounds of the Frames using the given Texture Source Index. + */ + getFrameBounds: function (sourceIndex) + { + if (sourceIndex === undefined) { sourceIndex = 0; } + + var frames = this.getFramesFromTextureSource(sourceIndex, true); + + var baseFrame = frames[0]; + + var minX = baseFrame.cutX; + var minY = baseFrame.cutY; + var maxX = baseFrame.cutX + baseFrame.cutWidth; + var maxY = baseFrame.cutY + baseFrame.cutHeight; + + for (var i = 1; i < frames.length; i++) + { + var frame = frames[i]; + + if (frame.cutX < minX) + { + minX = frame.cutX; + } + + if (frame.cutY < minY) + { + minY = frame.cutY; + } + + if (frame.cutX + frame.cutWidth > maxX) + { + maxX = frame.cutX + frame.cutWidth; + } + + if (frame.cutY + frame.cutHeight > maxY) + { + maxY = frame.cutY + frame.cutHeight; + } + } + + return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }; + }, + + /** + * Returns an array with all of the names of the Frames in this Texture. + * + * Useful if you want to randomly assign a Frame to a Game Object, as you can + * pick a random element from the returned array. + * + * @method Phaser.Textures.Texture#getFrameNames + * @since 3.0.0 + * + * @param {boolean} [includeBase=false] - Include the `__BASE` Frame in the output array? + * + * @return {string[]} An array of all Frame names in this Texture. + */ + getFrameNames: function (includeBase) + { + if (includeBase === undefined) { includeBase = false; } + + var out = Object.keys(this.frames); + + if (!includeBase) + { + var idx = out.indexOf('__BASE'); + + if (idx !== -1) + { + out.splice(idx, 1); + } + } + + return out; + }, + + /** + * Given a Frame name, return the source image it uses to render with. + * + * This will return the actual DOM Image or Canvas element. + * + * @method Phaser.Textures.Texture#getSourceImage + * @since 3.0.0 + * + * @param {(string|number)} [name] - The string-based name, or integer based index, of the Frame to get from this Texture. + * + * @return {(HTMLImageElement|HTMLCanvasElement|Phaser.GameObjects.RenderTexture)} The DOM Image, Canvas Element or Render Texture. + */ + getSourceImage: function (name) + { + if (name === undefined || name === null || this.frameTotal === 1) + { + name = '__BASE'; + } + + var frame = this.frames[name]; + + if (frame) + { + return frame.source.image; + } + else + { + console.warn(TEXTURE_MISSING_ERROR, this.key, name); + + return this.frames['__BASE'].source.image; + } + }, + + /** + * Given a Frame name, return the data source image it uses to render with. + * You can use this to get the normal map for an image for example. + * + * This will return the actual DOM Image. + * + * @method Phaser.Textures.Texture#getDataSourceImage + * @since 3.7.0 + * + * @param {(string|number)} [name] - The string-based name, or integer based index, of the Frame to get from this Texture. + * + * @return {(HTMLImageElement|HTMLCanvasElement)} The DOM Image or Canvas Element. + */ + getDataSourceImage: function (name) + { + if (name === undefined || name === null || this.frameTotal === 1) + { + name = '__BASE'; + } + + var frame = this.frames[name]; + var idx; + + if (!frame) + { + console.warn(TEXTURE_MISSING_ERROR, this.key, name); + + idx = this.frames['__BASE'].sourceIndex; + } + else + { + idx = frame.sourceIndex; + } + + return this.dataSource[idx].image; + }, + + /** + * Adds a data source image to this Texture. + * + * An example of a data source image would be a normal map, where all of the Frames for this Texture + * equally apply to the normal map. + * + * @method Phaser.Textures.Texture#setDataSource + * @since 3.0.0 + * + * @param {(HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[])} data - The source image. + */ + setDataSource: function (data) + { + if (!Array.isArray(data)) + { + data = [ data ]; + } + + for (var i = 0; i < data.length; i++) + { + var source = this.source[i]; + + this.dataSource.push(new TextureSource(this, data[i], source.width, source.height)); + } + }, + + /** + * Sets the Filter Mode for this Texture. + * + * The mode can be either Linear, the default, or Nearest. + * + * For pixel-art you should use Nearest. + * + * The mode applies to the entire Texture, not just a specific Frame of it. + * + * @method Phaser.Textures.Texture#setFilter + * @since 3.0.0 + * + * @param {Phaser.Textures.FilterMode} filterMode - The Filter Mode. + */ + setFilter: function (filterMode) + { + var i; + + for (i = 0; i < this.source.length; i++) + { + this.source[i].setFilter(filterMode); + } + + for (i = 0; i < this.dataSource.length; i++) + { + this.dataSource[i].setFilter(filterMode); + } + }, + + /** + * Set the `smoothPixelArt` property for this Texture. + * If `true`, it will also run `setFilter(Phaser.Textures.FilterMode.LINEAR)` + * to enable the necessary linear filtering. + * If `false`, it will not change the filter mode, as it doesn't know + * the previous state, nor is it necessary to change it. + * + * @method Phaser.Textures.Texture#setSmoothPixelArt + * @since 4.0.0 + * @param {boolean|null} value - The value of the smoothPixelArt property. + */ + setSmoothPixelArt: function (value) + { + this.smoothPixelArt = value; + + if (value) + { + this.setFilter(Phaser.Textures.FilterMode.LINEAR); + } + }, + + /** + * Destroys this Texture and releases references to its sources and frames. + * + * @method Phaser.Textures.Texture#destroy + * @since 3.0.0 + */ + destroy: function () + { + var i; + var source = this.source; + var dataSource = this.dataSource; + + for (i = 0; i < source.length; i++) + { + if (source[i]) + { + source[i].destroy(); + } + } + + for (i = 0; i < dataSource.length; i++) + { + if (dataSource[i]) + { + dataSource[i].destroy(); + } + } + + for (var frameName in this.frames) + { + var frame = this.frames[frameName]; + + if (frame) + { + frame.destroy(); + } + } + + this.source = []; + this.dataSource = []; + this.frames = {}; + + this.manager.removeKey(this.key); + + this.manager = null; + } + +}); + +module.exports = Texture; + + +/***/ }), + +/***/ 17130: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasPool = __webpack_require__(27919); +var CanvasTexture = __webpack_require__(57382); +var Class = __webpack_require__(83419); +var Color = __webpack_require__(40987); +var CONST = __webpack_require__(8054); +var DynamicTexture = __webpack_require__(81320); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(69442); +var Frame = __webpack_require__(4327); +var GameEvents = __webpack_require__(8443); +var GetValue = __webpack_require__(35154); +var ImageGameObject = __webpack_require__(88571); +var IsPlainObject = __webpack_require__(41212); +var Parser = __webpack_require__(61309); +var Rectangle = __webpack_require__(87841); +var Texture = __webpack_require__(79237); +var TileSpriteGameObject = __webpack_require__(20839); + +/** + * @callback EachTextureCallback + * + * @param {Phaser.Textures.Texture} texture - Each texture in Texture Manager. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + */ + +/** + * @classdesc + * When Phaser boots it will create an instance of this Texture Manager class. + * + * It is a global manager that handles all textures in your game. You can access it from within + * a Scene via the `this.textures` property. + * + * Its role is as a manager for all textures that your game uses. It can create, update and remove + * textures globally, as well as parse texture data from external files, such as sprite sheets + * and texture atlases. + * + * Sprites and other texture-based Game Objects get their texture data directly from this class. + * + * @class TextureManager + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Textures + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Game} game - The Phaser.Game instance this Texture Manager belongs to. + */ +var TextureManager = new Class({ + + Extends: EventEmitter, + + initialize: + + function TextureManager (game) + { + EventEmitter.call(this); + + /** + * The Game that the Texture Manager belongs to. + * + * A game will only ever have one instance of a Texture Manager. + * + * @name Phaser.Textures.TextureManager#game + * @type {Phaser.Game} + * @since 3.0.0 + */ + this.game = game; + + /** + * The internal name of this manager. + * + * @name Phaser.Textures.TextureManager#name + * @type {string} + * @readonly + * @since 3.0.0 + */ + this.name = 'TextureManager'; + + /** + * This object contains all Textures that belong to this Texture Manager. + * + * Textures are identified by string-based keys, which are used as the property + * within this object. Therefore, you can access any texture directly from this + * object without any iteration. + * + * You should not typically modify this object directly, but instead use the + * methods provided by the Texture Manager to add and remove entries from it. + * + * @name Phaser.Textures.TextureManager#list + * @type {object} + * @default {} + * @since 3.0.0 + */ + this.list = {}; + + /** + * The temporary canvas element used to save the pixel data of an arbitrary texture + * during the `TextureManager.getPixel` and `getPixelAlpha` methods. + * + * @name Phaser.Textures.TextureManager#_tempCanvas + * @type {HTMLCanvasElement} + * @private + * @since 3.0.0 + */ + this._tempCanvas = CanvasPool.create2D(this); + + /** + * The 2d context of the `_tempCanvas` element. + * + * @name Phaser.Textures.TextureManager#_tempContext + * @type {CanvasRenderingContext2D} + * @private + * @since 3.0.0 + */ + this._tempContext = this._tempCanvas.getContext('2d', { willReadFrequently: true }); + + /** + * An internal tracking value used for emitting the 'READY' event after all of + * the managers in the game have booted. + * + * @name Phaser.Textures.TextureManager#_pending + * @type {number} + * @private + * @default 0 + * @since 3.0.0 + */ + this._pending = 0; + + /** + * An Image Game Object that belongs to this Texture Manager. + * + * Used as a drawing stamp within Dynamic Textures. + * + * This is not part of the display list and doesn't render. + * + * Prior to v4.0.0, this was of the type `Phaser.GameObjects.Image`. + * + * @name Phaser.Textures.TextureManager#stamp + * @type {Phaser.GameObjects.Stamp} + * @readonly + * @since 3.60.0 + */ + this.stamp; + + /** + * The crop Rectangle as used by the Stamp when it needs to crop itself. + * + * @name Phaser.Textures.TextureManager#stampCrop + * @type {Phaser.Geom.Rectangle} + * @since 3.60.0 + */ + this.stampCrop = new Rectangle(); + + /** + * A TileSprite Game Object that belongs to this Texture Manager. + * + * Used for repeated drawing within Dynamic Textures. + * + * This is not part of the display list and doesn't render. + * + * @name Phaser.Textures.TextureManager#tileSprite + * @type {Phaser.GameObjects.TileSprite} + * @readonly + * @since 4.0.0 + */ + this.tileSprite; + + /** + * If this flag is `true` then the Texture Manager will never emit any + * warnings to the console log that report missing textures. + * + * @name Phaser.Textures.TextureManager#silentWarnings + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.silentWarnings = false; + + game.events.once(GameEvents.BOOT, this.boot, this); + }, + + /** + * The Boot Handler called by Phaser.Game when it first starts up. + * + * @method Phaser.Textures.TextureManager#boot + * @private + * @since 3.0.0 + */ + boot: function () + { + this._pending = 3; + + this.on(Events.LOAD, this.updatePending, this); + this.on(Events.ERROR, this.updatePending, this); + + var config = this.game.config; + + if (config.defaultImage !== null) + { + this.addBase64('__DEFAULT', config.defaultImage); + } + + if (config.missingImage !== null) + { + this.addBase64('__MISSING', config.missingImage); + } + + if (config.whiteImage !== null) + { + this.addBase64('__WHITE', config.whiteImage); + } + + if (this.game.renderer && this.game.renderer.gl) + { + this.addUint8Array('__NORMAL', new Uint8Array([ 127, 127, 255, 255 ]), 1, 1); + } + + this.game.events.once(GameEvents.DESTROY, this.destroy, this); + + this.game.events.once(GameEvents.SYSTEM_READY, function (scene) + { + this.stamp = new ImageGameObject(scene).setOrigin(0); + this.tileSprite = new TileSpriteGameObject(scene, 0, 0, 256, 256, '__WHITE').setOrigin(0); + + }, this); + }, + + /** + * After 'onload' or 'onerror' invoked twice, emit 'ready' event. + * + * @method Phaser.Textures.TextureManager#updatePending + * @private + * @since 3.0.0 + */ + updatePending: function () + { + this._pending--; + + if (this._pending === 0) + { + this.off(Events.LOAD); + this.off(Events.ERROR); + + this.emit(Events.READY); + } + }, + + /** + * Checks the given texture key and throws a console.warn if the key is already in use, then returns false. + * + * If you wish to avoid the console.warn then use `TextureManager.exists` instead. + * + * @method Phaser.Textures.TextureManager#checkKey + * @since 3.7.0 + * + * @param {string} key - The texture key to check. + * + * @return {boolean} `true` if it's safe to use the texture key, otherwise `false`. + */ + checkKey: function (key) + { + if (!key || typeof key !== 'string' || this.exists(key)) + { + if (!this.silentWarnings) + { + // eslint-disable-next-line no-console + console.error('Texture key already in use: ' + key); + } + + return false; + } + + return true; + }, + + /** + * Removes a Texture from the Texture Manager and destroys it. This will immediately + * clear all references to it from the Texture Manager, and if it has one, destroy its + * WebGLTexture. This will emit a `removetexture` event. + * + * Note: If you have any Game Objects still using this texture they will start throwing + * errors the next time they try to render. Make sure that removing the texture is the final + * step when clearing down to avoid this. + * + * @method Phaser.Textures.TextureManager#remove + * @fires Phaser.Textures.Events#REMOVE + * @since 3.7.0 + * + * @param {(string|Phaser.Textures.Texture)} key - The key of the Texture to remove, or a reference to it. + * + * @return {Phaser.Textures.TextureManager} The Texture Manager. + */ + remove: function (key) + { + if (typeof key === 'string') + { + if (this.exists(key)) + { + key = this.get(key); + } + else + { + if (!this.silentWarnings) + { + console.warn('No texture found matching key: ' + key); + } + + return this; + } + } + + // By this point key should be a Texture, if not, the following fails anyway + var textureKey = key.key; + + if (this.list.hasOwnProperty(textureKey)) + { + key.destroy(); + + this.emit(Events.REMOVE, textureKey); + this.emit(Events.REMOVE_KEY + textureKey); + } + + return this; + }, + + /** + * Removes a key from the Texture Manager but does not destroy the Texture that was using the key. + * + * @method Phaser.Textures.TextureManager#removeKey + * @since 3.17.0 + * + * @param {string} key - The key to remove from the texture list. + * + * @return {Phaser.Textures.TextureManager} The Texture Manager. + */ + removeKey: function (key) + { + if (this.list.hasOwnProperty(key)) + { + delete this.list[key]; + } + + return this; + }, + + /** + * Adds a new Texture to the Texture Manager created from the given Base64 encoded data. + * + * It works by creating an `Image` DOM object, then setting the `src` attribute to + * the given base64 encoded data. As a result, the process is asynchronous by its nature, + * so be sure to listen for the events this method dispatches before using the texture. + * + * @method Phaser.Textures.TextureManager#addBase64 + * @fires Phaser.Textures.Events#ADD + * @fires Phaser.Textures.Events#ERROR + * @fires Phaser.Textures.Events#LOAD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {*} data - The Base64 encoded data. + * + * @return {this} This Texture Manager instance. + */ + addBase64: function (key, data) + { + if (this.checkKey(key)) + { + var _this = this; + + var image = new Image(); + + image.onerror = function () + { + _this.emit(Events.ERROR, key); + }; + + image.onload = function () + { + var texture = _this.create(key, image); + + if (!texture) + { + return; + } + + Parser.Image(texture, 0); + + _this.emit(Events.ADD, key, texture); + _this.emit(Events.ADD_KEY + key, texture); + _this.emit(Events.LOAD, key, texture); + }; + + image.src = data; + } + + return this; + }, + + /** + * Gets an existing texture frame and converts it into a base64 encoded image and returns the base64 data. + * + * You can also provide the image type and encoder options. + * + * This will only work with bitmap based texture frames, such as those created from Texture Atlases. + * It will not work with GL Texture objects, such as Shaders, or Render Textures. For those please + * see the WebGL Snapshot function instead. + * + * @method Phaser.Textures.TextureManager#getBase64 + * @since 3.12.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} [frame] - The string-based name, or integer based index, of the Frame to get from the Texture. + * @param {string} [type='image/png'] - A DOMString indicating the image format. The default format type is image/png. + * @param {number} [encoderOptions=0.92] - A Number between 0 and 1 indicating the image quality to use for image formats that use lossy compression such as image/jpeg and image/webp. If this argument is anything else, the default value for image quality is used. The default value is 0.92. Other arguments are ignored. + * + * @return {string} The base64 encoded data, or an empty string if the texture frame could not be found. + */ + getBase64: function (key, frame, type, encoderOptions) + { + if (type === undefined) { type = 'image/png'; } + if (encoderOptions === undefined) { encoderOptions = 0.92; } + + var data = ''; + + var textureFrame = this.getFrame(key, frame); + + if (textureFrame && (textureFrame.source.isRenderTexture || textureFrame.source.isGLTexture)) + { + if (!this.silentWarnings) + { + console.warn('Cannot getBase64 from WebGL Texture'); + } + } + else if (textureFrame) + { + var cd = textureFrame.canvasData; + + var canvas = CanvasPool.create2D(this, cd.width, cd.height); + var ctx = canvas.getContext('2d', { willReadFrequently: true }); + + if (cd.width > 0 && cd.height > 0) + { + ctx.drawImage( + textureFrame.source.image, + cd.x, + cd.y, + cd.width, + cd.height, + 0, + 0, + cd.width, + cd.height + ); + } + + data = canvas.toDataURL(type, encoderOptions); + + CanvasPool.remove(canvas); + } + + return data; + }, + + /** + * Adds a new Texture to the Texture Manager created from the given Image element. + * + * @method Phaser.Textures.TextureManager#addImage + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {HTMLImageElement} source - The source Image element. + * @param {HTMLImageElement|HTMLCanvasElement} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addImage: function (key, source, dataSource) + { + var texture = null; + + if (this.checkKey(key)) + { + texture = this.create(key, source); + + Parser.Image(texture, 0); + + if (dataSource) + { + texture.setDataSource(dataSource); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Takes a WebGLTextureWrapper and creates a Phaser Texture from it, which is added to the Texture Manager using the given key. + * + * This allows you to then use the Texture as a normal texture for texture based Game Objects like Sprites. + * + * This is a WebGL only feature. + * + * Prior to Phaser 3.80.0, this method took a bare `WebGLTexture` + * as the `glTexture` parameter. You must now wrap the `WebGLTexture` in a + * `WebGLTextureWrapper` instance before passing it to this method. + * + * @method Phaser.Textures.TextureManager#addGLTexture + * @fires Phaser.Textures.Events#ADD + * @since 3.19.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} glTexture - The source Render Texture. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addGLTexture: function (key, glTexture) + { + var texture = null; + + if (this.checkKey(key)) + { + var width = glTexture.width; + var height = glTexture.height; + + texture = this.create(key, glTexture, width, height); + + texture.add('__BASE', 0, 0, 0, width, height); + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Compressed Texture to this Texture Manager. + * + * The texture should typically have been loaded via the `CompressedTextureFile` loader, + * in order to prepare the correct data object this method requires. + * + * You can optionally also pass atlas data to this method, in which case a texture atlas + * will be generated from the given compressed texture, combined with the atlas data. + * + * @method Phaser.Textures.TextureManager#addCompressedTexture + * @fires Phaser.Textures.Events#ADD + * @since 3.60.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {Phaser.Types.Textures.CompressedTextureData} textureData - The Compressed Texture data object. + * @param {object} [atlasData] - Optional Texture Atlas data. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addCompressedTexture: function (key, textureData, atlasData) + { + var texture = null; + + if (this.checkKey(key)) + { + texture = this.create(key, textureData); + + texture.add('__BASE', 0, 0, 0, textureData.width, textureData.height); + + if (atlasData) + { + var parse = function (texture, sourceIndex, atlasData) + { + if (Array.isArray(atlasData.textures) || Array.isArray(atlasData.frames)) + { + Parser.JSONArray(texture, sourceIndex, atlasData); + } + else + { + Parser.JSONHash(texture, sourceIndex, atlasData); + } + }; + if (Array.isArray(atlasData)) + { + for (var i = 0; i < atlasData.length; i++) + { + parse(texture, i, atlasData[i]); + } + } + else + { + parse(texture, 0, atlasData); + } + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Render Texture to the Texture Manager using the given key. + * This allows you to then use the Render Texture as a normal texture for texture based Game Objects like Sprites. + * + * @method Phaser.Textures.TextureManager#addRenderTexture + * @fires Phaser.Textures.Events#ADD + * @since 3.12.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {Phaser.GameObjects.RenderTexture} renderTexture - The source Render Texture. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addRenderTexture: function (key, renderTexture) + { + var texture = null; + + if (this.checkKey(key)) + { + texture = this.create(key, renderTexture); + + texture.add('__BASE', 0, 0, 0, renderTexture.width, renderTexture.height); + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Creates a new Texture using a blank Canvas element of the size given. + * + * Canvas elements are automatically pooled and calling this method will + * extract a free canvas from the CanvasPool, or create one if none are available. + * + * @method Phaser.Textures.TextureManager#createCanvas + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {number} [width=256] - The width of the Canvas element. + * @param {number} [height=256] - The height of the Canvas element. + * + * @return {?Phaser.Textures.CanvasTexture} The Canvas Texture that was created, or `null` if the key is already in use. + */ + createCanvas: function (key, width, height) + { + if (width === undefined) { width = 256; } + if (height === undefined) { height = 256; } + + if (this.checkKey(key)) + { + var canvas = CanvasPool.create(this, width, height, CONST.CANVAS, true); + + return this.addCanvas(key, canvas); + } + + return null; + }, + + /** + * Creates a new Canvas Texture object from an existing Canvas element + * and adds it to this Texture Manager, unless `skipCache` is true. + * + * @method Phaser.Textures.TextureManager#addCanvas + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {HTMLCanvasElement} source - The Canvas element to form the base of the new Texture. + * @param {boolean} [skipCache=false] - Skip adding this Texture into the Cache? + * + * @return {?Phaser.Textures.CanvasTexture} The Canvas Texture that was created, or `null` if the key is already in use. + */ + addCanvas: function (key, source, skipCache) + { + if (skipCache === undefined) { skipCache = false; } + + var texture = null; + + if (skipCache) + { + texture = new CanvasTexture(this, key, source, source.width, source.height); + } + else if (this.checkKey(key)) + { + texture = new CanvasTexture(this, key, source, source.width, source.height); + + this.list[key] = texture; + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Creates a Dynamic Texture instance and adds itself to this Texture Manager. + * + * A Dynamic Texture is a special texture that allows you to draw textures, frames and most kind of + * Game Objects directly to it. + * + * You can take many complex objects and draw them to this one texture, which can then be used as the + * base texture for other Game Objects, such as Sprites. Should you then update this texture, all + * Game Objects using it will instantly be updated as well, reflecting the changes immediately. + * + * It's a powerful way to generate dynamic textures at run-time that are WebGL friendly and don't invoke + * expensive GPU uploads on each change. + * + * See the methods available on the `DynamicTexture` class for more details. + * + * Optionally, you can also pass a Dynamic Texture instance to this method to have + * it added to the Texture Manager. + * + * @method Phaser.Textures.TextureManager#addDynamicTexture + * @fires Phaser.Textures.Events#ADD + * @since 3.60.0 + * + * @param {(string|Phaser.Textures.DynamicTexture)} key - The string-based key of this Texture. Must be unique within the Texture Manager. Or, a DynamicTexture instance. + * @param {number} [width=256] - The width of this Dynamic Texture in pixels. Defaults to 256 x 256. Ignored if an instance is passed as the key. + * @param {number} [height=256] - The height of this Dynamic Texture in pixels. Defaults to 256 x 256. Ignored if an instance is passed as the key. + * + * @return {?Phaser.Textures.DynamicTexture} The Dynamic Texture that was created, or `null` if the key is already in use. + */ + addDynamicTexture: function (key, width, height) + { + var texture = null; + + if (typeof(key) === 'string' && !this.exists(key)) + { + texture = new DynamicTexture(this, key, width, height); + } + else + { + texture = key; + key = texture.key; + } + + if (this.checkKey(key)) + { + this.list[key] = texture; + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + else + { + texture = null; + } + + return texture; + }, + + /** + * Adds a Texture Atlas to this Texture Manager. + * + * In Phaser terminology, a Texture Atlas is a combination of an atlas image and a JSON data file, + * such as those exported by applications like Texture Packer. + * + * It can accept either JSON Array or JSON Hash formats, as exported by Texture Packer and similar software. + * + * As of Phaser 3.60 you can use this method to add a atlas data to an existing Phaser Texture. + * + * @method Phaser.Textures.TextureManager#addAtlas + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(HTMLImageElement|HTMLImageElement[]|Phaser.Textures.Texture)} source - The source Image element/s, or a Phaser Texture. + * @param {(object|object[])} data - The Texture Atlas data/s. + * @param {HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addAtlas: function (key, source, data, dataSource) + { + // New Texture Packer format? + if (Array.isArray(data.textures) || Array.isArray(data.frames)) + { + return this.addAtlasJSONArray(key, source, data, dataSource); + } + else + { + return this.addAtlasJSONHash(key, source, data, dataSource); + } + }, + + /** + * Adds a Texture Atlas to this Texture Manager. + * + * In Phaser terminology, a Texture Atlas is a combination of an atlas image and a JSON data file, + * such as those exported by applications like Texture Packer. + * + * The frame data of the atlas must be stored in an Array within the JSON. + * + * This is known as a JSON Array in software such as Texture Packer. + * + * As of Phaser 3.60 you can use this method to add a atlas data to an existing Phaser Texture. + * + * @method Phaser.Textures.TextureManager#addAtlasJSONArray + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(HTMLImageElement|HTMLImageElement[]|Phaser.Textures.Texture)} source - The source Image element/s, or a Phaser Texture. + * @param {(object|object[])} data - The Texture Atlas data/s. + * @param {HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addAtlasJSONArray: function (key, source, data, dataSource) + { + var texture = null; + + if (source instanceof Texture) + { + key = source.key; + texture = source; + } + else if (this.checkKey(key)) + { + texture = this.create(key, source); + } + + if (texture) + { + // Multi-Atlas? + if (Array.isArray(data)) + { + var singleAtlasFile = (data.length === 1); // multi-pack with one atlas file for all images + + // !! Assumes the textures are in the same order in the source array as in the json data !! + for (var i = 0; i < texture.source.length; i++) + { + var atlasData = singleAtlasFile ? data[0] : data[i]; + + Parser.JSONArray(texture, i, atlasData); + } + } + else + { + Parser.JSONArray(texture, 0, data); + } + + if (dataSource) + { + texture.setDataSource(dataSource); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Texture Atlas to this Texture Manager. + * + * In Phaser terminology, a Texture Atlas is a combination of an atlas image and a JSON data file, + * such as those exported by applications like Texture Packer. + * + * The frame data of the atlas must be stored in an Object within the JSON. + * + * This is known as a JSON Hash in software such as Texture Packer. + * + * As of Phaser 3.60 you can use this method to add a atlas data to an existing Phaser Texture. + * + * @method Phaser.Textures.TextureManager#addAtlasJSONHash + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(HTMLImageElement|HTMLImageElement[]|Phaser.Textures.Texture)} source - The source Image element/s, or a Phaser Texture. + * @param {(object|object[])} data - The Texture Atlas data/s. + * @param {HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addAtlasJSONHash: function (key, source, data, dataSource) + { + var texture = null; + + if (source instanceof Texture) + { + key = source.key; + texture = source; + } + else if (this.checkKey(key)) + { + texture = this.create(key, source); + } + + if (texture) + { + if (Array.isArray(data)) + { + for (var i = 0; i < data.length; i++) + { + Parser.JSONHash(texture, i, data[i]); + } + } + else + { + Parser.JSONHash(texture, 0, data); + } + + if (dataSource) + { + texture.setDataSource(dataSource); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Texture Atlas to this Texture Manager. + * + * In Phaser terminology, a Texture Atlas is a combination of an atlas image and a data file, + * such as those exported by applications like Texture Packer. + * + * The frame data of the atlas must be stored in an XML file. + * + * As of Phaser 3.60 you can use this method to add a atlas data to an existing Phaser Texture. + * + * @method Phaser.Textures.TextureManager#addAtlasXML + * @fires Phaser.Textures.Events#ADD + * @since 3.7.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(HTMLImageElement|Phaser.Textures.Texture)} source - The source Image element, or a Phaser Texture. + * @param {object} data - The Texture Atlas XML data. + * @param {HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addAtlasXML: function (key, source, data, dataSource) + { + var texture = null; + + if (source instanceof Texture) + { + key = source.key; + texture = source; + } + else if (this.checkKey(key)) + { + texture = this.create(key, source); + } + + if (texture) + { + Parser.AtlasXML(texture, 0, data); + + if (dataSource) + { + texture.setDataSource(dataSource); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Unity Texture Atlas to this Texture Manager. + * + * In Phaser terminology, a Texture Atlas is a combination of an atlas image and a data file, + * such as those exported by applications like Texture Packer or Unity. + * + * The frame data of the atlas must be stored in a Unity YAML file. + * + * As of Phaser 3.60 you can use this method to add a atlas data to an existing Phaser Texture. + * + * @method Phaser.Textures.TextureManager#addUnityAtlas + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {HTMLImageElement} source - The source Image element. + * @param {object} data - The Texture Atlas data. + * @param {HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addUnityAtlas: function (key, source, data, dataSource) + { + var texture = null; + + if (source instanceof Texture) + { + key = source.key; + texture = source; + } + else if (this.checkKey(key)) + { + texture = this.create(key, source); + } + + if (texture) + { + Parser.UnityYAML(texture, 0, data); + + if (dataSource) + { + texture.setDataSource(dataSource); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Sprite Sheet to this Texture Manager. + * + * In Phaser terminology a Sprite Sheet is a texture containing different frames, but each frame is the exact + * same size and cannot be trimmed or rotated. This is different to a Texture Atlas, created by tools such as + * Texture Packer, and more akin with the fixed-frame exports you get from apps like Aseprite or old arcade + * games. + * + * As of Phaser 3.60 you can use this method to add a sprite sheet to an existing Phaser Texture. + * + * @method Phaser.Textures.TextureManager#addSpriteSheet + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. Give an empty string if you provide a Phaser Texture as the 2nd argument. + * @param {(HTMLImageElement|Phaser.Textures.Texture)} source - The source Image element, or a Phaser Texture. + * @param {Phaser.Types.Textures.SpriteSheetConfig} config - The configuration object for this Sprite Sheet. + * @param {HTMLImageElement|HTMLCanvasElement} [dataSource] - An optional data Image element. + * + * @return {?Phaser.Textures.Texture} The Texture that was created or updated, or `null` if the key is already in use. + */ + addSpriteSheet: function (key, source, config, dataSource) + { + var texture = null; + + if (source instanceof Texture) + { + key = source.key; + texture = source; + } + else if (this.checkKey(key)) + { + texture = this.create(key, source); + } + + if (texture) + { + var width = texture.source[0].width; + var height = texture.source[0].height; + + Parser.SpriteSheet(texture, 0, 0, 0, width, height, config); + + if (dataSource) + { + texture.setDataSource(dataSource); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + } + + return texture; + }, + + /** + * Adds a Sprite Sheet to this Texture Manager, where the Sprite Sheet exists as a Frame within a Texture Atlas. + * + * In Phaser terminology a Sprite Sheet is a texture containing different frames, but each frame is the exact + * same size and cannot be trimmed or rotated. + * + * @method Phaser.Textures.TextureManager#addSpriteSheetFromAtlas + * @fires Phaser.Textures.Events#ADD + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {Phaser.Types.Textures.SpriteSheetFromAtlasConfig} config - The configuration object for this Sprite Sheet. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addSpriteSheetFromAtlas: function (key, config) + { + if (!this.checkKey(key)) + { + return null; + } + + var atlasKey = GetValue(config, 'atlas', null); + var atlasFrame = GetValue(config, 'frame', null); + + if (!atlasKey || !atlasFrame) + { + return; + } + + var atlas = this.get(atlasKey); + var sheet = atlas.get(atlasFrame); + + if (sheet) + { + var source = sheet.source.image; + if (!source) + { + source = sheet.source.glTexture; + } + var texture = this.create(key, source); + + if (sheet.trimmed) + { + // If trimmed we need to help the parser adjust + Parser.SpriteSheetFromAtlas(texture, sheet, config); + } + else + { + Parser.SpriteSheet(texture, 0, sheet.cutX, sheet.cutY, sheet.cutWidth, sheet.cutHeight, config); + } + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + + return texture; + } + }, + + /** + * Creates a texture from an array of colour data. + * + * This is only available in WebGL mode. + * + * If the dimensions provided are powers of two, the resulting texture + * will be automatically set to wrap by the WebGL Renderer. + * + * @method Phaser.Textures.TextureManager#addUint8Array + * @fires Phaser.Textures.Events#ADD + * @since 3.80.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {Uint8Array} data - The color data for the texture. + * @param {number} width - The width of the texture. + * @param {number} height - The height of the texture. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + addUint8Array: function (key, data, width, height) + { + if ( + !this.checkKey(key) || + data.length / 4 !== width * height + ) + { + return null; + } + + var texture = this.create(key, data, width, height); + + texture.add('__BASE', 0, 0, 0, width, height); + + this.emit(Events.ADD, key, texture); + this.emit(Events.ADD_KEY + key, texture); + + return texture; + }, + + /** + * Creates a new Texture using the given source and dimensions. + * + * @method Phaser.Textures.TextureManager#create + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(HTMLImageElement|HTMLCanvasElement|HTMLImageElement[]|HTMLCanvasElement[]|Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper)} source - An array of sources that are used to create the texture. Usually Images, but can also be a Canvas. + * @param {number} [width] - The width of the Texture. This is optional and automatically derived from the source images. + * @param {number} [height] - The height of the Texture. This is optional and automatically derived from the source images. + * + * @return {?Phaser.Textures.Texture} The Texture that was created, or `null` if the key is already in use. + */ + create: function (key, source, width, height) + { + var texture = null; + + if (this.checkKey(key)) + { + texture = new Texture(this, key, source, width, height); + + this.list[key] = texture; + } + + return texture; + }, + + /** + * Checks the given key to see if a Texture using it exists within this Texture Manager. + * + * @method Phaser.Textures.TextureManager#exists + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * + * @return {boolean} Returns `true` if a Texture matching the given key exists in this Texture Manager. + */ + exists: function (key) + { + return (this.list.hasOwnProperty(key)); + }, + + /** + * Returns a Texture from the Texture Manager that matches the given key. + * + * If the key is `undefined` it will return the `__DEFAULT` Texture. + * + * If the key is an instance of a Texture, it will return the instance. + * + * If the key is an instance of a Frame, it will return the frames parent Texture instance. + * + * Finally, if the key is given, but not found, and not a Texture or Frame instance, it will return the `__MISSING` Texture. + * + * @method Phaser.Textures.TextureManager#get + * @since 3.0.0 + * + * @param {(string|Phaser.Textures.Texture|Phaser.Textures.Frame)} key - The unique string-based key of the Texture, or a Texture, or Frame instance. + * + * @return {Phaser.Textures.Texture} The Texture matching the given key. + */ + get: function (key) + { + if (key === undefined) { key = '__DEFAULT'; } + + if (this.list[key]) + { + return this.list[key]; + } + else if (key instanceof Texture) + { + return key; + } + else if (key instanceof Frame) + { + return key.texture; + } + else + { + return this.list['__MISSING']; + } + }, + + /** + * Takes a Texture key and Frame name and returns a clone of that Frame if found. + * + * @method Phaser.Textures.TextureManager#cloneFrame + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} frame - The string or index of the Frame to be cloned. + * + * @return {Phaser.Textures.Frame} A Clone of the given Frame. + */ + cloneFrame: function (key, frame) + { + if (this.list[key]) + { + return this.list[key].get(frame).clone(); + } + }, + + /** + * Takes a Texture key and Frame name and returns a reference to that Frame, if found. + * + * @method Phaser.Textures.TextureManager#getFrame + * @since 3.0.0 + * + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} [frame] - The string-based name, or integer based index, of the Frame to get from the Texture. + * + * @return {Phaser.Textures.Frame} A Texture Frame object. + */ + getFrame: function (key, frame) + { + if (this.list[key]) + { + return this.list[key].get(frame); + } + }, + + /** + * Parses the 'key' parameter and returns a Texture Frame instance. + * + * It can accept the following formats: + * + * 1) A string + * 2) An array where the elements are: [ key, [frame] ] + * 3) An object with the properties: { key, [frame] } + * 4) A Texture instance - which returns the default frame from the Texture + * 5) A Frame instance - returns itself + * + * @method Phaser.Textures.TextureManager#parseFrame + * @since 3.60.0 + * + * @param {(string|array|object|Phaser.Textures.Texture|Phaser.Textures.Frame)} key - The key to be parsed. + * + * @return {Phaser.Textures.Frame} A Texture Frame object, if found, or undefined if not. + */ + parseFrame: function (key) + { + if (!key) + { + return undefined; + } + else if (typeof key === 'string') + { + return this.getFrame(key); + } + else if (Array.isArray(key) && key.length === 2) + { + return this.getFrame(key[0], key[1]); + } + else if (IsPlainObject(key)) + { + return this.getFrame(key.key, key.frame); + } + else if (key instanceof Texture) + { + return key.get(); + } + else if (key instanceof Frame) + { + return key; + } + }, + + /** + * Returns an array with all of the keys of all Textures in this Texture Manager. + * The output array will exclude the `__DEFAULT`, `__MISSING`, `__WHITE`, and `__NORMAL` keys. + * + * @method Phaser.Textures.TextureManager#getTextureKeys + * @since 3.0.0 + * + * @return {string[]} An array containing all of the Texture keys stored in this Texture Manager. + */ + getTextureKeys: function () + { + var output = []; + + for (var key in this.list) + { + if (key !== '__DEFAULT' && key !== '__MISSING' && key !== '__WHITE' && key !== '__NORMAL') + { + output.push(key); + } + } + + return output; + }, + + /** + * Given a Texture and an `x` and `y` coordinate this method will return a new + * Color object that has been populated with the color and alpha values of the pixel + * at that location in the Texture. + * + * @method Phaser.Textures.TextureManager#getPixel + * @since 3.0.0 + * + * @param {number} x - The x coordinate of the pixel within the Texture. + * @param {number} y - The y coordinate of the pixel within the Texture. + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} [frame] - The string or index of the Frame. + * + * @return {?Phaser.Display.Color} A Color object populated with the color values of the requested pixel, + * or `null` if the coordinates were out of bounds. + */ + getPixel: function (x, y, key, frame) + { + var textureFrame = this.getFrame(key, frame); + + if (textureFrame) + { + var source = textureFrame.source; + var image = source.image; + if (!(source.isCanvas || source.isVideo || image instanceof HTMLImageElement)) + { + console.warn('TextureManager.getPixelAlpha: The texture source must be Image, Canvas, or Video'); + return null; + } + + // Adjust for trim (if not trimmed x and y are just zero) + x -= textureFrame.x; + y -= textureFrame.y; + + var data = textureFrame.data.cut; + + x += data.x; + y += data.y; + + if (x >= data.x && x < data.r && y >= data.y && y < data.b) + { + var ctx = this._tempContext; + + ctx.clearRect(0, 0, 1, 1); + ctx.drawImage(image, x, y, 1, 1, 0, 0, 1, 1); + + var rgb = ctx.getImageData(0, 0, 1, 1); + + return new Color(rgb.data[0], rgb.data[1], rgb.data[2], rgb.data[3]); + } + } + + return null; + }, + + /** + * Given a Texture and an `x` and `y` coordinate this method will return a value between 0 and 255 + * corresponding to the alpha value of the pixel at that location in the Texture. If the coordinate + * is out of bounds it will return null. + * + * @method Phaser.Textures.TextureManager#getPixelAlpha + * @since 3.10.0 + * + * @param {number} x - The x coordinate of the pixel within the Texture. + * @param {number} y - The y coordinate of the pixel within the Texture. + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} [frame] - The string or index of the Frame. + * + * @return {number} A value between 0 and 255, or `null` if the coordinates were out of bounds. + */ + getPixelAlpha: function (x, y, key, frame) + { + var textureFrame = this.getFrame(key, frame); + + if (textureFrame) + { + var source = textureFrame.source; + var image = source.image; + if (!(source.isCanvas || source.isVideo || image instanceof HTMLImageElement)) + { + console.warn('TextureManager.getPixelAlpha: The texture source must be Image, Canvas, or Video'); + return null; + } + + // Adjust for trim (if not trimmed x and y are just zero) + x -= textureFrame.x; + y -= textureFrame.y; + + var data = textureFrame.data.cut; + + x += data.x; + y += data.y; + + if (x >= data.x && x < data.r && y >= data.y && y < data.b) + { + var ctx = this._tempContext; + + ctx.clearRect(0, 0, 1, 1); + ctx.drawImage(image, x, y, 1, 1, 0, 0, 1, 1); + + var rgb = ctx.getImageData(0, 0, 1, 1); + + return rgb.data[3]; + } + } + + return null; + }, + + /** + * Sets the given Game Objects `texture` and `frame` properties so that it uses + * the Texture and Frame specified in the `key` and `frame` arguments to this method. + * + * @method Phaser.Textures.TextureManager#setTexture + * @since 3.0.0 + * + * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object the texture would be set on. + * @param {string} key - The unique string-based key of the Texture. + * @param {(string|number)} [frame] - The string or index of the Frame. + * + * @return {Phaser.GameObjects.GameObject} The Game Object the texture was set on. + */ + setTexture: function (gameObject, key, frame) + { + if (this.list[key]) + { + gameObject.texture = this.list[key]; + gameObject.frame = gameObject.texture.get(frame); + } + + return gameObject; + }, + + /** + * Changes the key being used by a Texture to the new key provided. + * + * The old key is removed, allowing it to be re-used. + * + * Game Objects are linked to Textures by a reference to the Texture object, so + * all existing references will be retained. + * + * @method Phaser.Textures.TextureManager#renameTexture + * @since 3.12.0 + * + * @param {string} currentKey - The current string-based key of the Texture you wish to rename. + * @param {string} newKey - The new unique string-based key to use for the Texture. + * + * @return {boolean} `true` if the Texture key was successfully renamed, otherwise `false`. + */ + renameTexture: function (currentKey, newKey) + { + var texture = this.get(currentKey); + + if (texture && currentKey !== newKey) + { + texture.key = newKey; + + this.list[newKey] = texture; + + delete this.list[currentKey]; + + return true; + } + + return false; + }, + + /** + * Passes all Textures to the given callback. + * + * @method Phaser.Textures.TextureManager#each + * @since 3.0.0 + * + * @param {EachTextureCallback} callback - The callback function to be sent the Textures. + * @param {object} scope - The value to use as `this` when executing the callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + */ + each: function (callback, scope) + { + var args = [ null ]; + + for (var i = 1; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (var texture in this.list) + { + args[0] = this.list[texture]; + + callback.apply(scope, args); + } + }, + + /** + * Resets the internal Stamp object, ready for drawing and returns it. + * + * @method Phaser.Textures.TextureManager#resetStamp + * @since 3.60.0 + * + * @param {number} [alpha=1] - The alpha to use. + * @param {number} [tint=0xffffff] - WebGL only. The tint color to use. + * + * @return {Phaser.GameObjects.Image} A reference to the Stamp Game Object. + */ + resetStamp: function (alpha, tint) + { + if (alpha === undefined) { alpha = 1; } + if (tint === undefined) { tint = 0xffffff; } + + var stamp = this.stamp; + + stamp.setCrop(); + stamp.setPosition(0); + stamp.setAngle(0); + stamp.setScale(1); + stamp.setAlpha(alpha); + stamp.setTint(tint); + stamp.setTexture('__WHITE'); + + return stamp; + }, + + /** + * Resets the internal Tile Sprite object, ready for drawing, and returns it. + * + * @method Phaser.Textures.TextureManager#resetTileSprite + * @since 4.0.0 + * + * @param {number} [alpha=1] - The alpha to use. + * @param {number} [tint=0xffffff] - WebGL only. The tint color to use. + * + * @return {Phaser.GameObjects.TileSprite} A reference to the Tile Sprite Game Object. + */ + resetTileSprite: function (alpha, tint) + { + if (alpha === undefined) { alpha = 1; } + if (tint === undefined) { tint = 0xffffff; } + + var tileSprite = this.tileSprite; + + tileSprite.setCrop(); + tileSprite.setPosition(0); + tileSprite.setAngle(0); + tileSprite.setScale(1); + tileSprite.setAlpha(alpha); + tileSprite.setTint(tint); + tileSprite.setTexture('__WHITE'); + + return tileSprite; + }, + + /** + * Destroys the Texture Manager and all Textures stored within it. + * + * @method Phaser.Textures.TextureManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + for (var texture in this.list) + { + this.list[texture].destroy(); + } + + this.list = {}; + + this.stamp.destroy(); + + this.game = null; + this.stamp = null; + + CanvasPool.remove(this._tempCanvas); + } + +}); + +module.exports = TextureManager; + + +/***/ }), + +/***/ 11876: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CanvasPool = __webpack_require__(27919); +var Class = __webpack_require__(83419); +var IsSizePowerOfTwo = __webpack_require__(50030); +var ScaleModes = __webpack_require__(29795); +var WebGLTextureWrapper = __webpack_require__(82751); + +/** + * @classdesc + * A Texture Source is the encapsulation of the actual source data for a Texture. + * + * This is typically an Image Element, loaded from the file system or network, a Canvas Element or a Video Element. + * + * A Texture can contain multiple Texture Sources, which only happens when a multi-atlas is loaded. + * + * @class TextureSource + * @memberof Phaser.Textures + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture this TextureSource belongs to. + * @param {(HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|Phaser.GameObjects.RenderTexture|Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper|Phaser.Types.Textures.CompressedTextureData|Phaser.Textures.DynamicTexture)} source - The source image data. + * @param {number} [width] - Optional width of the source image. If not given it's derived from the source itself. + * @param {number} [height] - Optional height of the source image. If not given it's derived from the source itself. + * @param {boolean} [flipY=true] - Sets the `UNPACK_FLIP_Y_WEBGL` flag the WebGL Texture uses during upload. + */ +var TextureSource = new Class({ + + initialize: + + function TextureSource (texture, source, width, height, flipY) + { + if (flipY === undefined) { flipY = true; } + + var game = texture.manager.game; + + /** + * A reference to the Canvas or WebGL Renderer. + * + * @name Phaser.Textures.TextureSource#renderer + * @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} + * @since 3.7.0 + */ + this.renderer = game.renderer; + + /** + * The Texture this TextureSource instance belongs to. + * + * @name Phaser.Textures.TextureSource#texture + * @type {Phaser.Textures.Texture} + * @since 3.0.0 + */ + this.texture = texture; + + /** + * The source of the image data. + * + * This is either an Image Element, a Canvas Element, a Video Element, a RenderTexture or a WebGLTextureWrapper. + * + * In Phaser 3.60 and above it can also be a Compressed Texture data object. + * + * @name Phaser.Textures.TextureSource#source + * @type {(HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|Phaser.GameObjects.RenderTexture|Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper|Phaser.Types.Textures.CompressedTextureData|Phaser.Textures.DynamicTexture)} + * @since 3.12.0 + */ + this.source = source; + + /** + * The image data. + * + * This is either an Image element, Canvas element, Video Element, or Uint8Array. + * + * @name Phaser.Textures.TextureSource#image + * @type {(HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|Uint8Array)} + * @since 3.0.0 + */ + this.image = (source.compressed) ? null : source; + + /** + * Holds the compressed textured algorithm, or `null` if it's not a compressed texture. + * + * Prior to Phaser 3.60 this value always held `null`. + * + * @name Phaser.Textures.TextureSource#compressionAlgorithm + * @type {number} + * @default null + * @since 3.0.0 + */ + this.compressionAlgorithm = (source.compressed) ? source.format : null; + + /** + * The resolution of the source image. + * + * @name Phaser.Textures.TextureSource#resolution + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.resolution = 1; + + /** + * The width of the source image. If not specified in the constructor it will check + * the `naturalWidth` and then `width` properties of the source image. + * + * @name Phaser.Textures.TextureSource#width + * @type {number} + * @since 3.0.0 + */ + this.width = width || source.naturalWidth || source.videoWidth || source.width || 0; + + /** + * The height of the source image. If not specified in the constructor it will check + * the `naturalHeight` and then `height` properties of the source image. + * + * @name Phaser.Textures.TextureSource#height + * @type {number} + * @since 3.0.0 + */ + this.height = height || source.naturalHeight || source.videoHeight || source.height || 0; + + /** + * The Scale Mode the image will use when rendering. + * Either Linear or Nearest. + * + * @name Phaser.Textures.TextureSource#scaleMode + * @type {number} + * @since 3.0.0 + */ + this.scaleMode = ScaleModes.DEFAULT; + + /** + * Is the source image a Canvas Element? + * + * @name Phaser.Textures.TextureSource#isCanvas + * @type {boolean} + * @since 3.0.0 + */ + this.isCanvas = (source instanceof HTMLCanvasElement); + + /** + * Is the source image a Video Element? + * + * @name Phaser.Textures.TextureSource#isVideo + * @type {boolean} + * @since 3.20.0 + */ + this.isVideo = (window.hasOwnProperty('HTMLVideoElement') && source instanceof HTMLVideoElement); + + /** + * Is the source image a Render Texture? + * + * @name Phaser.Textures.TextureSource#isRenderTexture + * @type {boolean} + * @since 3.12.0 + */ + this.isRenderTexture = (source.type === 'RenderTexture' || source.type === 'DynamicTexture'); + + /** + * Is the source image a WebGLTextureWrapper? + * + * @name Phaser.Textures.TextureSource#isGLTexture + * @type {boolean} + * @since 3.19.0 + */ + this.isGLTexture = source instanceof WebGLTextureWrapper; + + /** + * Are the source image dimensions a power of two? + * + * @name Phaser.Textures.TextureSource#isPowerOf2 + * @type {boolean} + * @since 3.0.0 + */ + this.isPowerOf2 = IsSizePowerOfTwo(this.width, this.height); + + /** + * The wrapped WebGL Texture of the source image. + * If this TextureSource is driven from a WebGLTexture already, + * then this wrapper contains a reference to that WebGLTexture. + * + * @name Phaser.Textures.TextureSource#glTexture + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @default null + * @since 3.0.0 + */ + this.glTexture = null; + + /** + * Sets the `UNPACK_FLIP_Y_WEBGL` flag the WebGL Texture uses during upload. + * + * @name Phaser.Textures.TextureSource#flipY + * @type {boolean} + * @since 3.20.0 + */ + this.flipY = flipY; + + this.init(game); + }, + + /** + * Creates a WebGL Texture, if required, and sets the Texture filter mode. + * + * @method Phaser.Textures.TextureSource#init + * @since 3.0.0 + * + * @param {Phaser.Game} game - A reference to the Phaser Game instance. + */ + init: function (game) + { + var renderer = this.renderer; + + if (renderer) + { + var source = this.source; + + if (renderer.gl) + { + var image = this.image; + var flipY = this.flipY; + var width = this.width; + var height = this.height; + var scaleMode = this.scaleMode; + + if (this.isCanvas) + { + this.glTexture = renderer.createCanvasTexture(image, false, flipY); + } + else if (this.isVideo) + { + this.glTexture = renderer.createVideoTexture(image, false, flipY); + } + else if (this.isRenderTexture) + { + this.glTexture = renderer.createTextureFromSource(null, width, height, scaleMode, undefined, flipY); + } + else if (this.isGLTexture) + { + this.glTexture = source; + } + else if (this.compressionAlgorithm) + { + this.glTexture = renderer.createTextureFromSource(source, undefined, undefined, scaleMode, undefined, flipY); + } + else if (source instanceof Uint8Array) + { + this.glTexture = renderer.createUint8ArrayTexture(source, width, height, scaleMode, undefined, flipY); + } + else + { + this.glTexture = renderer.createTextureFromSource(image, width, height, scaleMode, undefined, flipY); + } + + if (false) + {} + } + else if (this.isRenderTexture) + { + this.image = source.canvas; + } + } + + if (!game.config.antialias) + { + this.setFilter(1); + } + }, + + /** + * Sets the Filter Mode for this Texture. + * + * The mode can be either Linear, the default, or Nearest. + * + * For pixel-art you should use Nearest. + * + * @method Phaser.Textures.TextureSource#setFilter + * @since 3.0.0 + * + * @param {Phaser.Textures.FilterMode} filterMode - The Filter Mode. + */ + setFilter: function (filterMode) + { + if (this.renderer && this.renderer.gl) + { + this.renderer.setTextureFilter(this.glTexture, filterMode); + } + + this.scaleMode = filterMode; + }, + + /** + * Sets the `UNPACK_FLIP_Y_WEBGL` flag for the WebGL Texture during texture upload. + * + * @method Phaser.Textures.TextureSource#setFlipY + * @since 3.20.0 + * + * @param {boolean} [value=true] - Should the WebGL Texture be flipped on the Y axis on texture upload or not? + */ + setFlipY: function (value) + { + if (value === undefined) { value = true; } + + if (value === this.flipY) { return this; } + + this.flipY = value; + this.update(); + + return this; + }, + + /** + * If this TextureSource is backed by a Canvas and is running under WebGL, + * it updates the WebGLTexture using the canvas data. + * + * @method Phaser.Textures.TextureSource#update + * @since 3.7.0 + */ + update: function () + { + var renderer = this.renderer; + var image = this.image; + var flipY = this.flipY; + var gl = renderer.gl; + + if (gl) + { + var textureWrapper = this.glTexture; + if (this.isCanvas) + { + renderer.updateCanvasTexture(image, textureWrapper, flipY); + } + else if (this.isVideo) + { + renderer.updateVideoTexture(image, textureWrapper, flipY); + } + else + { + textureWrapper.update( + image, + this.width, + this.height, + flipY, + textureWrapper.wrapS, + textureWrapper.wrapT, + textureWrapper.magFilter, + textureWrapper.minFilter, + textureWrapper.format + ); + } + } + }, + + /** + * Updates the dimensions of this Texture Source. + * This is called automatically by game systems which manage textures, + * such as Text, which renders to a dedicated canvas that changes size. + * + * @method Phaser.Textures.TextureSource#updateSize + * @since 4.0.0 + * @param {number} width - The new width of the source image. + * @param {number} height - The new height of the source image. + */ + updateSize: function (width, height) + { + if (this.width === width && this.height === height) + { + return; + } + this.width = width; + this.height = height; + this.isPowerOf2 = IsSizePowerOfTwo(width, height); + }, + + /** + * Destroys this Texture Source and nulls the references. + * + * @method Phaser.Textures.TextureSource#destroy + * @since 3.0.0 + */ + destroy: function () + { + if (this.glTexture) + { + this.renderer.deleteTexture(this.glTexture); + } + + if (this.isCanvas) + { + CanvasPool.remove(this.image); + } + + this.renderer = null; + this.texture = null; + this.source = null; + this.image = null; + this.glTexture = null; + } + +}); + +module.exports = TextureSource; + + +/***/ }), + +/***/ 19673: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Filter Types. + * + * @namespace Phaser.Textures.FilterMode + * @memberof Phaser.Textures + * @since 3.0.0 + */ +var CONST = { + + /** + * Linear filter type. + * + * @name Phaser.Textures.FilterMode.LINEAR + * @type {number} + * @const + * @since 3.0.0 + */ + LINEAR: 0, + + /** + * Nearest neighbor filter type. + * + * @name Phaser.Textures.FilterMode.NEAREST + * @type {number} + * @const + * @since 3.0.0 + */ + NEAREST: 1 + +}; + +module.exports = CONST; + + +/***/ }), + +/***/ 44538: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Texture Add Event. + * + * This event is dispatched by the Texture Manager when a texture is added to it. + * + * Listen to this event from within a Scene using: `this.textures.on('addtexture', listener)`. + * + * @event Phaser.Textures.Events#ADD + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the Texture that was added to the Texture Manager. + * @param {Phaser.Textures.Texture} texture - A reference to the Texture that was added to the Texture Manager. + */ +module.exports = 'addtexture'; + + +/***/ }), + +/***/ 63486: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Texture Add Key Event. + * + * This event is dispatched by the Texture Manager when a texture with the given key is added to it. + * + * Listen to this event from within a Scene using: `this.textures.on('addtexture-key', listener)`. + * + * @event Phaser.Textures.Events#ADD_KEY + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.Textures.Texture} texture - A reference to the Texture that was added to the Texture Manager. + */ +module.exports = 'addtexture-'; + + +/***/ }), + +/***/ 94851: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Texture Load Error Event. + * + * This event is dispatched by the Texture Manager when a texture it requested to load failed. + * This only happens when base64 encoded textures fail. All other texture types are loaded via the Loader Plugin. + * + * Listen to this event from within a Scene using: `this.textures.on('onerror', listener)`. + * + * @event Phaser.Textures.Events#ERROR + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the Texture that failed to load into the Texture Manager. + */ +module.exports = 'onerror'; + + +/***/ }), + +/***/ 29099: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Texture Load Event. + * + * This event is dispatched by the Texture Manager when a texture has finished loading on it. + * This only happens for base64 encoded textures. All other texture types are loaded via the Loader Plugin. + * + * Listen to this event from within a Scene using: `this.textures.on('onload', listener)`. + * + * This event is dispatched after the [ADD]{@linkcode Phaser.Textures.Events#event:ADD} event. + * + * @event Phaser.Textures.Events#LOAD + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the Texture that was loaded by the Texture Manager. + * @param {Phaser.Textures.Texture} texture - A reference to the Texture that was loaded by the Texture Manager. + */ +module.exports = 'onload'; + + +/***/ }), + +/***/ 8678: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * This internal event signifies that the Texture Manager is now ready and the Game can continue booting. + * + * When a Phaser Game instance is booting for the first time, the Texture Manager has to wait on a couple of non-blocking + * async events before it's fully ready to carry on. When those complete the Texture Manager emits this event via the Game + * instance, which tells the Game to carry on booting. + * + * @event Phaser.Textures.Events#READY + * @type {string} + * @since 3.16.1 + */ +module.exports = 'ready'; + + +/***/ }), + +/***/ 86415: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Texture Remove Event. + * + * This event is dispatched by the Texture Manager when a texture is removed from it. + * + * Listen to this event from within a Scene using: `this.textures.on('removetexture', listener)`. + * + * If you have any Game Objects still using the removed texture, they will start throwing + * errors the next time they try to render. Be sure to clear all use of the texture in this event handler. + * + * @event Phaser.Textures.Events#REMOVE + * @type {string} + * @since 3.0.0 + * + * @param {string} key - The key of the Texture that was removed from the Texture Manager. + */ +module.exports = 'removetexture'; + + +/***/ }), + +/***/ 30879: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Texture Remove Key Event. + * + * This event is dispatched by the Texture Manager when a texture with the given key is removed from it. + * + * Listen to this event from within a Scene using: `this.textures.on('removetexture-key', listener)`. + * + * If you have any Game Objects still using the removed texture, they will start throwing + * errors the next time they try to render. Be sure to clear all use of the texture in this event handler. + * + * @event Phaser.Textures.Events#REMOVE_KEY + * @type {string} + * @since 3.60.0 + */ +module.exports = 'removetexture-'; + + +/***/ }), + +/***/ 69442: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Textures.Events + */ + +module.exports = { + + ADD: __webpack_require__(44538), + ADD_KEY: __webpack_require__(63486), + ERROR: __webpack_require__(94851), + LOAD: __webpack_require__(29099), + READY: __webpack_require__(8678), + REMOVE: __webpack_require__(86415), + REMOVE_KEY: __webpack_require__(30879) + +}; + + +/***/ }), + +/***/ 27458: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Extend = __webpack_require__(79291); +var FilterMode = __webpack_require__(19673); + +/** + * @namespace Phaser.Textures + */ + +/** + * Linear filter type. + * + * @name Phaser.Textures.LINEAR + * @type {number} + * @const + * @since 3.0.0 + */ + +/** + * Nearest Neighbor filter type. + * + * @name Phaser.Textures.NEAREST + * @type {number} + * @const + * @since 3.0.0 + */ + +var Textures = { + + CanvasTexture: __webpack_require__(57382), + DynamicTexture: __webpack_require__(81320), + Events: __webpack_require__(69442), + FilterMode: FilterMode, + Frame: __webpack_require__(4327), + Parsers: __webpack_require__(61309), + Texture: __webpack_require__(79237), + TextureManager: __webpack_require__(17130), + TextureSource: __webpack_require__(11876) + +}; + +Textures = Extend(false, Textures, FilterMode); + +module.exports = Textures; + + +/***/ }), + +/***/ 89905: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Parses an XML Texture Atlas object and adds all the Frames into a Texture. + * + * @function Phaser.Textures.Parsers.AtlasXML + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.7.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * @param {*} xml - The XML data. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var AtlasXML = function (texture, sourceIndex, xml) +{ + // Malformed? + if (!xml.getElementsByTagName('TextureAtlas')) + { + console.warn('Invalid Texture Atlas XML given'); + return; + } + + // Add in a __BASE entry (for the entire atlas) + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + // By this stage frames is a fully parsed array + var frames = xml.getElementsByTagName('SubTexture'); + + var newFrame; + + for (var i = 0; i < frames.length; i++) + { + var frame = frames[i].attributes; + + var name = frame.name.value; + var x = parseInt(frame.x.value, 10); + var y = parseInt(frame.y.value, 10); + var width = parseInt(frame.width.value, 10); + var height = parseInt(frame.height.value, 10); + + // The frame values are the exact coordinates to cut the frame out of the atlas from + newFrame = texture.add(name, sourceIndex, x, y, width, height); + + // These are the original (non-trimmed) sprite values + if (frame.frameX) + { + var frameX = Math.abs(parseInt(frame.frameX.value, 10)); + var frameY = Math.abs(parseInt(frame.frameY.value, 10)); + var frameWidth = parseInt(frame.frameWidth.value, 10); + var frameHeight = parseInt(frame.frameHeight.value, 10); + + newFrame.setTrim( + width, + height, + frameX, + frameY, + frameWidth, + frameHeight + ); + } + } + + return texture; +}; + +module.exports = AtlasXML; + + +/***/ }), + +/***/ 72893: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Adds a Canvas Element to a Texture. + * + * @function Phaser.Textures.Parsers.Canvas + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var Canvas = function (texture, sourceIndex) +{ + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + return texture; +}; + +module.exports = Canvas; + + +/***/ }), + +/***/ 4832: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Adds an Image Element to a Texture. + * + * @function Phaser.Textures.Parsers.Image + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var Image = function (texture, sourceIndex) +{ + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + return texture; +}; + +module.exports = Image; + + +/***/ }), + +/***/ 78566: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clone = __webpack_require__(41786); + +/** + * Parses a Texture Atlas JSON Array and adds the Frames to the Texture. + * JSON format expected to match that defined by Texture Packer, with the frames property containing an array of Frames. + * + * @function Phaser.Textures.Parsers.JSONArray + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * @param {object} json - The JSON data. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var JSONArray = function (texture, sourceIndex, json) +{ + // Malformed? + if (!json['frames'] && !json['textures']) + { + console.warn('Invalid Texture Atlas JSON Array'); + return; + } + + // Add in a __BASE entry (for the entire atlas) + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + // By this stage frames is a fully parsed array + var frames = (Array.isArray(json.textures)) ? json.textures[sourceIndex].frames : json.frames; + + var newFrame; + + for (var i = 0; i < frames.length; i++) + { + var src = frames[i]; + + // The frame values are the exact coordinates to cut the frame out of the atlas from + newFrame = texture.add(src.filename, sourceIndex, src.frame.x, src.frame.y, src.frame.w, src.frame.h); + + if (!newFrame) + { + console.warn('Invalid atlas json, frame already exists: ' + src.filename); + + continue; + } + + // These are the original (non-trimmed) sprite values + if (src.trimmed) + { + newFrame.setTrim( + src.sourceSize.w, + src.sourceSize.h, + src.spriteSourceSize.x, + src.spriteSourceSize.y, + src.spriteSourceSize.w, + src.spriteSourceSize.h + ); + } + + if (src.rotated) + { + newFrame.rotated = true; + newFrame.updateUVsInverted(); + } + + var pivot = src.anchor || src.pivot; + + if (pivot) + { + newFrame.customPivot = true; + newFrame.pivotX = pivot.x; + newFrame.pivotY = pivot.y; + } + + if (src.scale9Borders) + { + newFrame.setScale9( + src.scale9Borders.x, + src.scale9Borders.y, + src.scale9Borders.w, + src.scale9Borders.h + ); + } + + // Copy over any extra data + newFrame.customData = Clone(src); + } + + // Copy over any additional data that was in the JSON to Texture.customData + for (var dataKey in json) + { + if (dataKey === 'frames') + { + continue; + } + + if (Array.isArray(json[dataKey])) + { + texture.customData[dataKey] = json[dataKey].slice(0); + } + else + { + texture.customData[dataKey] = json[dataKey]; + } + } + + return texture; +}; + +module.exports = JSONArray; + + +/***/ }), + +/***/ 39711: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clone = __webpack_require__(41786); + +/** + * Parses a Texture Atlas JSON Hash and adds the Frames to the Texture. + * JSON format expected to match that defined by Texture Packer, with the frames property containing an object of Frames. + * + * @function Phaser.Textures.Parsers.JSONHash + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * @param {object} json - The JSON data. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var JSONHash = function (texture, sourceIndex, json) +{ + // Malformed? + if (!json['frames']) + { + console.warn('Invalid Texture Atlas JSON Hash given, missing \'frames\' Object'); + return; + } + + // Add in a __BASE entry (for the entire atlas) + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + // By this stage frames is a fully parsed Object + var frames = json.frames; + var newFrame; + + for (var key in frames) + { + if (!frames.hasOwnProperty(key)) + { + continue; + } + + var src = frames[key]; + + // The frame values are the exact coordinates to cut the frame out of the atlas from + newFrame = texture.add(key, sourceIndex, src.frame.x, src.frame.y, src.frame.w, src.frame.h); + + if (!newFrame) + { + console.warn('Invalid atlas json, frame already exists: ' + key); + + continue; + } + + // These are the original (non-trimmed) sprite values + if (src.trimmed) + { + newFrame.setTrim( + src.sourceSize.w, + src.sourceSize.h, + src.spriteSourceSize.x, + src.spriteSourceSize.y, + src.spriteSourceSize.w, + src.spriteSourceSize.h + ); + } + + if (src.rotated) + { + newFrame.rotated = true; + newFrame.updateUVsInverted(); + } + + var pivot = src.anchor || src.pivot; + + if (pivot) + { + newFrame.customPivot = true; + newFrame.pivotX = pivot.x; + newFrame.pivotY = pivot.y; + } + + if (src.scale9Borders) + { + newFrame.setScale9( + src.scale9Borders.x, + src.scale9Borders.y, + src.scale9Borders.w, + src.scale9Borders.h + ); + } + + // Copy over any extra data + newFrame.customData = Clone(src); + } + + // Copy over any additional data that was in the JSON to Texture.customData + for (var dataKey in json) + { + if (dataKey === 'frames') + { + continue; + } + + if (Array.isArray(json[dataKey])) + { + texture.customData[dataKey] = json[dataKey].slice(0); + } + else + { + texture.customData[dataKey] = json[dataKey]; + } + } + + return texture; +}; + +module.exports = JSONHash; + + +/***/ }), + +/***/ 31403: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2021 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Parses a KTX format Compressed Texture file and generates texture data suitable for WebGL from it. + * + * @function Phaser.Textures.Parsers.KTXParser + * @memberof Phaser.Textures.Parsers + * @since 3.60.0 + * + * @param {ArrayBuffer} data - The data object created by the Compressed Texture File Loader. + * + * @return {Phaser.Types.Textures.CompressedTextureData} The Compressed Texture data. + */ +var KTXParser = function (data) +{ + var idCheck = [ 0xab, 0x4b, 0x54, 0x58, 0x20, 0x31, 0x31, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a ]; + + var i; + var id = new Uint8Array(data, 0, 12); + + for (i = 0; i < id.length; i++) + { + if (id[i] !== idCheck[i]) + { + console.warn('KTXParser - Invalid file format'); + + return; + } + } + + var size = Uint32Array.BYTES_PER_ELEMENT; + + var head = new DataView(data, 12, 13 * size); + + var littleEndian = (head.getUint32(0, true) === 0x04030201); + + var glType = head.getUint32(1 * size, littleEndian); + + if (glType !== 0) + { + console.warn('KTXParser - Only compressed formats supported'); + + return; + } + + var internalFormat = head.getUint32(4 * size, littleEndian); + var width = head.getUint32(6 * size, littleEndian); + var height = head.getUint32(7 * size, littleEndian); + + var mipmapLevels = Math.max(1, head.getUint32(11 * size, littleEndian)); + + var bytesOfKeyValueData = head.getUint32(12 * size, littleEndian); + + var mipmaps = new Array(mipmapLevels); + + var offset = 12 + 13 * 4 + bytesOfKeyValueData; + var levelWidth = width; + var levelHeight = height; + + for (i = 0; i < mipmapLevels; i++) + { + var levelSize = new Int32Array(data, offset, 1)[0]; + + // levelSize field + offset += 4; + + mipmaps[i] = { + data: new Uint8Array(data, offset, levelSize), + width: levelWidth, + height: levelHeight + }; + + // add padding for odd sized image + // offset += 3 - ((levelSize + 3) % 4); + + levelWidth = Math.max(1, levelWidth >> 1); + levelHeight = Math.max(1, levelHeight >> 1); + + offset += levelSize; + } + + return { + mipmaps: mipmaps, + width: width, + height: height, + internalFormat: internalFormat, + compressed: true, + generateMipmap: false + }; +}; + +module.exports = KTXParser; + + +/***/ }), + +/***/ 82038: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2021 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @ignore + */ +function GetSize (width, height, x, y, dx, dy, mult) +{ + if (mult === undefined) { mult = 16; } + + return Math.floor((width + x) / dx) * Math.floor((height + y) / dy) * mult; +} + +/** + * @ignore + */ +function PVRTC2bppSize (width, height) +{ + width = Math.max(width, 16); + height = Math.max(height, 8); + + return width * height / 4; +} + +/** + * @ignore + */ +function PVRTC4bppSize (width, height) +{ + width = Math.max(width, 8); + height = Math.max(height, 8); + + return width * height / 2; +} + +/** + * @ignore + */ +function BPTCSize (width, height) +{ + return Math.ceil(width / 4) * Math.ceil(height / 4) * 16; +} + +/** + * @ignore + */ +function DXTEtcSmallSize (width, height) +{ + return GetSize(width, height, 3, 3, 4, 4, 8); +} + +/** + * @ignore + */ +function DXTEtcAstcBigSize (width, height) +{ + return GetSize(width, height, 3, 3, 4, 4); +} + +/** + * @ignore + */ +function ATC5x4Size (width, height) +{ + return GetSize(width, height, 4, 3, 5, 4); +} + +/** + * @ignore + */ +function ATC5x5Size (width, height) +{ + return GetSize(width, height, 4, 4, 5, 5); +} + +/** + * @ignore + */ +function ATC6x5Size (width, height) +{ + return GetSize(width, height, 5, 4, 6, 5); +} + +/** + * @ignore + */ +function ATC6x6Size (width, height) +{ + return GetSize(width, height, 5, 5, 6, 6); +} + +/** + * @ignore + */ +function ATC8x5Size (width, height) +{ + return GetSize(width, height, 7, 4, 8, 5); +} + +/** + * @ignore + */ +function ATC8x6Size (width, height) +{ + return GetSize(width, height, 7, 5, 8, 6); +} + +/** + * @ignore + */ +function ATC8x8Size (width, height) +{ + return GetSize(width, height, 7, 7, 8, 8); +} + +/** + * @ignore + */ +function ATC10x5Size (width, height) +{ + return GetSize(width, height, 9, 4, 10, 5); +} + +/** + * @ignore + */ +function ATC10x6Size (width, height) +{ + return GetSize(width, height, 9, 5, 10, 6); +} + +/** + * @ignore + */ +function ATC10x8Size (width, height) +{ + return GetSize(width, height, 9, 7, 10, 8); +} + +/** + * @ignore + */ +function ATC10x10Size (width, height) +{ + return GetSize(width, height, 9, 9, 10, 10); +} + +/** + * @ignore + */ +function ATC12x10Size (width, height) +{ + return GetSize(width, height, 11, 9, 12, 10); +} + +/** + * @ignore + */ +function ATC12x12Size (width, height) +{ + return GetSize(width, height, 11, 11, 12, 12); +} + +/* + * 0: COMPRESSED_RGB_PVRTC_2BPPV1_IMG + * 1: COMPRESSED_RGBA_PVRTC_2BPPV1_IMG + * 2: COMPRESSED_RGB_PVRTC_4BPPV1_IMG + * 3: COMPRESSED_RGBA_PVRTC_4BPPV1_IMG + * 6: COMPRESSED_RGB_ETC1 + * 7: COMPRESSED_RGB_S3TC_DXT1_EXT or COMPRESSED_SRGB_S3TC_DXT1_EXT + * 8: COMPRESSED_RGBA_S3TC_DXT1_EXT or COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + * 9: COMPRESSED_RGBA_S3TC_DXT3_EXT or COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + * 11: COMPRESSED_RGBA_S3TC_DXT5_EXT or COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT + * 14: COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT or COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT + * 15: COMPRESSED_RGBA_BPTC_UNORM_EXT or COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT + * 22: COMPRESSED_RGB8_ETC2 or COMPRESSED_SRGB8_ETC2 + * 23: COMPRESSED_RGBA8_ETC2_EAC or COMPRESSED_SRGB8_ALPHA8_ETC2_EAC + * 24: COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 or COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 + * 25: COMPRESSED_R11_EAC + * 26: COMPRESSED_RG11_EAC + * 27: COMPRESSED_RGBA_ASTC_4x4_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR + * 28: COMPRESSED_RGBA_ASTC_5x4_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR + * 29: COMPRESSED_RGBA_ASTC_5x5_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR + * 30: COMPRESSED_RGBA_ASTC_6x5_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR + * 31: COMPRESSED_RGBA_ASTC_6x6_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR + * 32: COMPRESSED_RGBA_ASTC_8x5_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR + * 33: COMPRESSED_RGBA_ASTC_8x6_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR + * 34: COMPRESSED_RGBA_ASTC_8x8_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR + * 35: COMPRESSED_RGBA_ASTC_10x5_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR + * 36: COMPRESSED_RGBA_ASTC_10x6_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR + * 37: COMPRESSED_RGBA_ASTC_10x8_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR + * 38: COMPRESSED_RGBA_ASTC_10x10_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR + * 39: COMPRESSED_RGBA_ASTC_12x10_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR + * 40: COMPRESSED_RGBA_ASTC_12x12_KHR or COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR + */ + +/** + * @ignore + */ +var FORMATS = { + 0: { sizeFunc: PVRTC2bppSize, glFormat: [ 0x8C01 ] }, + 1: { sizeFunc: PVRTC2bppSize, glFormat: [ 0x8C03 ] }, + 2: { sizeFunc: PVRTC4bppSize, glFormat: [ 0x8C00 ] }, + 3: { sizeFunc: PVRTC4bppSize, glFormat: [ 0x8C02 ] }, + 6: { sizeFunc: DXTEtcSmallSize , glFormat: [ 0x8D64 ] }, + 7: { sizeFunc: DXTEtcSmallSize, glFormat: [ 0x83F0, 0x8C4C ] }, + 8: { sizeFunc: DXTEtcAstcBigSize, glFormat: [ 0x83F1, 0x8C4D ] }, + 9: { sizeFunc: DXTEtcAstcBigSize, glFormat: [ 0x83F2, 0x8C4E ] }, + 11: { sizeFunc: DXTEtcAstcBigSize, glFormat: [ 0x83F3, 0x8C4F ] }, + 14: { sizeFunc: BPTCSize, glFormat: [ 0x8E8E, 0x8E8F ] }, + 15: { sizeFunc: BPTCSize, glFormat: [ 0x8E8C, 0x8E8D ] }, + 22: { sizeFunc: DXTEtcSmallSize , glFormat: [ 0x9274, 0x9275 ] }, + 23: { sizeFunc: DXTEtcAstcBigSize, glFormat: [ 0x9278, 0x9279 ] }, + 24: { sizeFunc: DXTEtcSmallSize, glFormat: [ 0x9276, 0x9277 ] }, + 25: { sizeFunc: DXTEtcSmallSize, glFormat: [ 0x9270 ] }, + 26: { sizeFunc: DXTEtcAstcBigSize, glFormat: [ 0x9272 ] }, + 27: { sizeFunc: DXTEtcAstcBigSize, glFormat: [ 0x93B0, 0x93D0 ] }, + 28: { sizeFunc: ATC5x4Size, glFormat: [ 0x93B1, 0x93D1 ] }, + 29: { sizeFunc: ATC5x5Size, glFormat: [ 0x93B2, 0x93D2 ] }, + 30: { sizeFunc: ATC6x5Size, glFormat: [ 0x93B3, 0x93D3 ] }, + 31: { sizeFunc: ATC6x6Size, glFormat: [ 0x93B4, 0x93D4 ] }, + 32: { sizeFunc: ATC8x5Size, glFormat: [ 0x93B5, 0x93D5 ] }, + 33: { sizeFunc: ATC8x6Size, glFormat: [ 0x93B6, 0x93D6 ] }, + 34: { sizeFunc: ATC8x8Size, glFormat: [ 0x93B7, 0x93D7 ] }, + 35: { sizeFunc: ATC10x5Size, glFormat: [ 0x93B8, 0x93D8 ] }, + 36: { sizeFunc: ATC10x6Size, glFormat: [ 0x93B9, 0x93D9 ] }, + 37: { sizeFunc: ATC10x8Size, glFormat: [ 0x93BA, 0x93DA ] }, + 38: { sizeFunc: ATC10x10Size, glFormat: [ 0x93BB, 0x93DB ] }, + 39: { sizeFunc: ATC12x10Size, glFormat: [ 0x93BC, 0x93DC ] }, + 40: { sizeFunc: ATC12x12Size, glFormat: [ 0x93BD, 0x93DD ] } +}; + +/** + * Parses a PVR format Compressed Texture file and generates texture data suitable for WebGL from it. + * + * @function Phaser.Textures.Parsers.PVRParser + * @memberof Phaser.Textures.Parsers + * @since 3.60.0 + * + * @param {ArrayBuffer} data - The data object created by the Compressed Texture File Loader. + * + * @return {Phaser.Types.Textures.CompressedTextureData} The Compressed Texture data. + */ +var PVRParser = function (data) +{ + var header = new Uint32Array(data, 0, 13); + + // VERSION + var version = header[0]; + var versionMatch = version === 0x03525650; + + // PIXEL_FORMAT_INDEX + var pvrFormat = versionMatch ? header[2] : header[3]; + + // Colour Space + var colorSpace = header[4]; + + var internalFormat = FORMATS[pvrFormat].glFormat[colorSpace]; + var sizeFunction = FORMATS[pvrFormat].sizeFunc; + + // MIPMAPCOUNT_INDEX + var mipmapLevels = header[11]; + + // WIDTH_INDEX + var width = header[7]; + + // HEIGHT_INDEX + var height = header[6]; + + // HEADER_SIZE + METADATA_SIZE_INDEX + var dataOffset = 52 + header[12]; + + var image = new Uint8Array(data, dataOffset); + + var mipmaps = new Array(mipmapLevels); + + var offset = 0; + var levelWidth = width; + var levelHeight = height; + + for (var i = 0; i < mipmapLevels; i++) + { + var levelSize = sizeFunction(levelWidth, levelHeight); + + mipmaps[i] = { + data: new Uint8Array(image.buffer, image.byteOffset + offset, levelSize), + width: levelWidth, + height: levelHeight + }; + + levelWidth = Math.max(1, levelWidth >> 1); + levelHeight = Math.max(1, levelHeight >> 1); + + offset += levelSize; + } + + return { + mipmaps: mipmaps, + width: width, + height: height, + internalFormat: internalFormat, + compressed: true, + generateMipmap: false + }; +}; + +module.exports = PVRParser; + + +/***/ }), + +/***/ 75549: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); + +/** + * Parses a Sprite Sheet and adds the Frames to the Texture. + * + * In Phaser terminology a Sprite Sheet is a texture containing different frames, but each frame is the exact + * same size and cannot be trimmed or rotated. + * + * @function Phaser.Textures.Parsers.SpriteSheet + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * @param {number} x - The top-left coordinate of the Sprite Sheet. Defaults to zero. Used when extracting sheets from atlases. + * @param {number} y - The top-left coordinate of the Sprite Sheet. Defaults to zero. Used when extracting sheets from atlases. + * @param {number} width - The width of the source image. + * @param {number} height - The height of the source image. + * @param {object} config - An object describing how to parse the Sprite Sheet. + * @param {number} config.frameWidth - Width in pixels of a single frame in the sprite sheet. + * @param {number} [config.frameHeight] - Height in pixels of a single frame in the sprite sheet. Defaults to frameWidth if not provided. + * @param {number} [config.startFrame=0] - The frame to start extracting from. Defaults to zero. + * @param {number} [config.endFrame=-1] - The frame to finish extracting at. Defaults to -1, which means 'all frames'. + * @param {number} [config.margin=0] - If the frames have been drawn with a margin, specify the amount here. + * @param {number} [config.spacing=0] - If the frames have been drawn with spacing between them, specify the amount here. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var SpriteSheet = function (texture, sourceIndex, x, y, width, height, config) +{ + var frameWidth = GetFastValue(config, 'frameWidth', null); + var frameHeight = GetFastValue(config, 'frameHeight', frameWidth); + + // If missing we can't proceed + if (frameWidth === null) + { + throw new Error('TextureManager.SpriteSheet: Invalid frameWidth given.'); + } + + // Add in a __BASE entry (for the entire atlas) + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + var startFrame = GetFastValue(config, 'startFrame', 0); + var endFrame = GetFastValue(config, 'endFrame', -1); + var margin = GetFastValue(config, 'margin', 0); + var spacing = GetFastValue(config, 'spacing', 0); + + var row = Math.floor((width - margin + spacing) / (frameWidth + spacing)); + var column = Math.floor((height - margin + spacing) / (frameHeight + spacing)); + var total = row * column; + + if (total === 0) + { + console.warn('SpriteSheet frame dimensions will result in zero frames for texture:', texture.key); + } + + if (startFrame > total || startFrame < -total) + { + startFrame = 0; + } + + if (startFrame < 0) + { + // Allow negative skipframes. + startFrame = total + startFrame; + } + + if (endFrame === -1 || endFrame > total || endFrame < startFrame) + { + endFrame = total; + } + + var fx = margin; + var fy = margin; + var ax = 0; + var ay = 0; + var c = 0; + + for (var i = 0; i < total; i++) + { + ax = 0; + ay = 0; + + var w = fx + frameWidth; + var h = fy + frameHeight; + + if (w > width) + { + ax = w - width; + } + + if (h > height) + { + ay = h - height; + } + + if (i >= startFrame && i <= endFrame) + { + texture.add(c, sourceIndex, x + fx, y + fy, frameWidth - ax, frameHeight - ay); + + c++; + } + + fx += frameWidth + spacing; + + if (fx + frameWidth > width) + { + fx = margin; + fy += frameHeight + spacing; + } + } + + return texture; +}; + +module.exports = SpriteSheet; + + +/***/ }), + +/***/ 47534: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); + +/** + * Parses a Sprite Sheet and adds the Frames to the Texture, where the Sprite Sheet is stored as a frame within an Atlas. + * + * In Phaser terminology a Sprite Sheet is a texture containing different frames, but each frame is the exact + * same size and cannot be trimmed or rotated. + * + * @function Phaser.Textures.Parsers.SpriteSheetFromAtlas + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {Phaser.Textures.Frame} frame - The Frame that contains the Sprite Sheet. + * @param {object} config - An object describing how to parse the Sprite Sheet. + * @param {number} config.frameWidth - Width in pixels of a single frame in the sprite sheet. + * @param {number} [config.frameHeight] - Height in pixels of a single frame in the sprite sheet. Defaults to frameWidth if not provided. + * @param {number} [config.startFrame=0] - Index of the start frame in the sprite sheet + * @param {number} [config.endFrame=-1] - Index of the end frame in the sprite sheet. -1 mean all the rest of the frames + * @param {number} [config.margin=0] - If the frames have been drawn with a margin, specify the amount here. + * @param {number} [config.spacing=0] - If the frames have been drawn with spacing between them, specify the amount here. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var SpriteSheetFromAtlas = function (texture, frame, config) +{ + var frameWidth = GetFastValue(config, 'frameWidth', null); + var frameHeight = GetFastValue(config, 'frameHeight', frameWidth); + + // If missing we can't proceed + if (!frameWidth) + { + throw new Error('TextureManager.SpriteSheetFromAtlas: Invalid frameWidth given.'); + } + + // Add in a __BASE entry (for the entire atlas frame) + var source = texture.source[0]; + texture.add('__BASE', 0, 0, 0, source.width, source.height); + + var startFrame = GetFastValue(config, 'startFrame', 0); + var endFrame = GetFastValue(config, 'endFrame', -1); + var margin = GetFastValue(config, 'margin', 0); + var spacing = GetFastValue(config, 'spacing', 0); + + var x = frame.cutX; + var y = frame.cutY; + + var cutWidth = frame.cutWidth; + var cutHeight = frame.cutHeight; + var sheetWidth = frame.realWidth; + var sheetHeight = frame.realHeight; + + var row = Math.floor((sheetWidth - margin + spacing) / (frameWidth + spacing)); + var column = Math.floor((sheetHeight - margin + spacing) / (frameHeight + spacing)); + var total = row * column; + + // trim offsets + + var leftPad = frame.x; + var leftWidth = frameWidth - leftPad; + + var rightWidth = frameWidth - ((sheetWidth - cutWidth) - leftPad); + + var topPad = frame.y; + var topHeight = frameHeight - topPad; + + var bottomHeight = frameHeight - ((sheetHeight - cutHeight) - topPad); + + if (startFrame > total || startFrame < -total) + { + startFrame = 0; + } + + if (startFrame < 0) + { + // Allow negative skipframes. + startFrame = total + startFrame; + } + + if (endFrame !== -1) + { + total = startFrame + (endFrame + 1); + } + + var sheetFrame; + var frameX = margin; + var frameY = margin; + var frameIndex = 0; + var sourceIndex = 0; + + for (var sheetY = 0; sheetY < column; sheetY++) + { + var topRow = (sheetY === 0); + var bottomRow = (sheetY === column - 1); + + for (var sheetX = 0; sheetX < row; sheetX++) + { + var leftRow = (sheetX === 0); + var rightRow = (sheetX === row - 1); + + sheetFrame = texture.add(frameIndex, sourceIndex, x + frameX, y + frameY, frameWidth, frameHeight); + + if (leftRow || topRow || rightRow || bottomRow) + { + var destX = (leftRow) ? leftPad : 0; + var destY = (topRow) ? topPad : 0; + + var trimWidth = 0; + var trimHeight = 0; + + if (leftRow) + { + trimWidth += (frameWidth - leftWidth); + } + + if (rightRow) + { + trimWidth += (frameWidth - rightWidth); + } + + if (topRow) + { + trimHeight += (frameHeight - topHeight); + } + + if (bottomRow) + { + trimHeight += (frameHeight - bottomHeight); + } + + var destWidth = frameWidth - trimWidth; + var destHeight = frameHeight - trimHeight; + + sheetFrame.cutWidth = destWidth; + sheetFrame.cutHeight = destHeight; + + sheetFrame.setTrim(frameWidth, frameHeight, destX, destY, destWidth, destHeight); + } + + frameX += spacing; + + if (leftRow) + { + frameX += leftWidth; + } + else if (rightRow) + { + frameX += rightWidth; + } + else + { + frameX += frameWidth; + } + + frameIndex++; + } + + frameX = margin; + frameY += spacing; + + if (topRow) + { + frameY += topHeight; + } + else if (bottomRow) + { + frameY += bottomHeight; + } + else + { + frameY += frameHeight; + } + } + + return texture; +}; + +module.exports = SpriteSheetFromAtlas; + + +/***/ }), + +/***/ 86147: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var imageHeight = 0; + +/** + * @function addFrame + * @private + * @since 3.0.0 + */ +var addFrame = function (texture, sourceIndex, name, frame) +{ + // The frame values are the exact coordinates to cut the frame out of the atlas from + + var y = imageHeight - frame.y - frame.height; + + texture.add(name, sourceIndex, frame.x, y, frame.width, frame.height); + + // These are the original (non-trimmed) sprite values + /* + if (src.trimmed) + { + newFrame.setTrim( + src.sourceSize.w, + src.sourceSize.h, + src.spriteSourceSize.x, + src.spriteSourceSize.y, + src.spriteSourceSize.w, + src.spriteSourceSize.h + ); + } + */ +}; + +/** + * Parses a Unity YAML File and creates Frames in the Texture. + * For more details about Sprite Meta Data see https://docs.unity3d.com/ScriptReference/SpriteMetaData.html + * + * @function Phaser.Textures.Parsers.UnityYAML + * @memberof Phaser.Textures.Parsers + * @private + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. + * @param {number} sourceIndex - The index of the TextureSource. + * @param {object} yaml - The YAML data. + * + * @return {Phaser.Textures.Texture} The Texture modified by this parser. + */ +var UnityYAML = function (texture, sourceIndex, yaml) +{ + // Add in a __BASE entry (for the entire atlas) + var source = texture.source[sourceIndex]; + + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); + + imageHeight = source.height; + + var data = yaml.split('\n'); + + var lineRegExp = /^[ ]*(- )*(\w+)+[: ]+(.*)/; + + var prevSprite = ''; + var currentSprite = ''; + var rect = { x: 0, y: 0, width: 0, height: 0 }; + + // var pivot = { x: 0, y: 0 }; + // var border = { x: 0, y: 0, z: 0, w: 0 }; + + for (var i = 0; i < data.length; i++) + { + var results = data[i].match(lineRegExp); + + if (!results) + { + continue; + } + + var isList = (results[1] === '- '); + var key = results[2]; + var value = results[3]; + + if (isList) + { + if (currentSprite !== prevSprite) + { + addFrame(texture, sourceIndex, currentSprite, rect); + + prevSprite = currentSprite; + } + + rect = { x: 0, y: 0, width: 0, height: 0 }; + } + + if (key === 'name') + { + // Start new list + currentSprite = value; + continue; + } + + switch (key) + { + case 'x': + case 'y': + case 'width': + case 'height': + rect[key] = parseInt(value, 10); + break; + + // case 'pivot': + // pivot = eval('var obj = ' + value); + // break; + + // case 'border': + // border = eval('var obj = ' + value); + // break; + } + } + + if (currentSprite !== prevSprite) + { + addFrame(texture, sourceIndex, currentSprite, rect); + } + + return texture; +}; + +module.exports = UnityYAML; + +/* +Example data: + +TextureImporter: + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + spriteSheet: + sprites: + - name: asteroids_0 + rect: + serializedVersion: 2 + x: 5 + y: 328 + width: 65 + height: 82 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + - name: asteroids_1 + rect: + serializedVersion: 2 + x: 80 + y: 322 + width: 53 + height: 88 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + spritePackingTag: Asteroids +*/ + + +/***/ }), + +/***/ 55222: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Ben Richards + * @copyright 2024 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var IsSizePowerOfTwo = __webpack_require__(50030); + +/** + * Verify whether the given compressed texture data is valid. + * + * Compare the dimensions of each mip layer to the rules for that + * specific format. + * + * Mip layer size is assumed to have been calculated correctly during parsing. + * + * @function Phaser.Textures.Parsers.verifyCompressedTexture + * @param {Phaser.Types.Textures.CompressedTextureData} data - The compressed texture data to verify. + * @since 3.80.0 + * @returns {boolean} Whether the compressed texture data is valid. + */ +var verifyCompressedTexture = function (data) +{ + // Check that mipmaps are power-of-two sized. + // WebGL does not allow non-power-of-two textures for mip levels above 0. + var mipmaps = data.mipmaps; + for (var level = 1; level < mipmaps.length; level++) + { + var width = mipmaps[level].width; + var height = mipmaps[level].height; + if (!IsSizePowerOfTwo(width, height)) + { + console.warn('Mip level ' + level + ' is not a power-of-two size: ' + width + 'x' + height); + return false; + } + } + + // Check specific format requirements. + var checker = formatCheckers[data.internalFormat]; + if (!checker) + { + console.warn('No format checker found for internal format ' + data.internalFormat + '. Assuming valid.'); + return true; + } + return checker(data); +}; + +/** + * @ignore + */ +function check4x4 (data) +{ + var mipmaps = data.mipmaps; + for (var level = 0; level < mipmaps.length; level++) + { + var width = mipmaps[level].width; + var height = mipmaps[level].height; + if ((width << level) % 4 !== 0 || (height << level) % 4 !== 0) + { + console.warn('BPTC, RGTC, and S3TC dimensions must be a multiple of 4 pixels, and each successive mip level must be half the size of the previous level, rounded down. Mip level ' + level + ' is ' + width + 'x' + height); + return false; + } + } + return true; +} + +/** + * @ignore + */ +function checkAlways () +{ + // WEBGL_compressed_texture_astc + // WEBGL_compressed_texture_etc + // WEBGL_compressed_texture_etc1 + + // ASTC, ETC, and ETC1 + // only require data be provided in arrays of specific size, + // which are already set by the parser. + return true; +} + +function checkPVRTC (data) +{ + // WEBGL_compressed_texture_pvrtc + + var mipmaps = data.mipmaps; + var baseLevel = mipmaps[0]; + if (!IsSizePowerOfTwo(baseLevel.width, baseLevel.height)) + { + console.warn('PVRTC base dimensions must be power of two. Base level is ' + baseLevel.width + 'x' + baseLevel.height); + return false; + } + + // Other mip levels have already been checked for power-of-two size. + return true; +} + +/** + * @ignore + */ +function checkS3TCSRGB (data) +{ + // WEBGL_compressed_texture_s3tc_srgb + + var mipmaps = data.mipmaps; + var baseLevel = mipmaps[0]; + if (baseLevel.width % 4 !== 0 || baseLevel.height % 4 !== 0) + { + console.warn('S3TC SRGB base dimensions must be a multiple of 4 pixels. Base level is ' + baseLevel.width + 'x' + baseLevel.height + ' pixels'); + return false; + } + + // Mip levels above 0 must be 0, 1, 2, or a multiple of 4 pixels. + // However, as WebGL mip levels must all be power-of-two sized, + // this is already covered by the power-of-two check. + + return true; +} + +var formatCheckers = { + // ETC internal formats: + + // COMPRESSED_R11_EAC + 0x9270: checkAlways, + + // COMPRESSED_SIGNED_R11_EAC + 0x9271: checkAlways, + + // COMPRESSED_RG11_EAC + 0x9272: checkAlways, + + // COMPRESSED_SIGNED_RG11_EAC + 0x9273: checkAlways, + + // COMPRESSED_RGB8_ETC2 + 0x9274: checkAlways, + + // COMPRESSED_SRGB8_ETC2 + 0x9275: checkAlways, + + // COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 + 0x9276: checkAlways, + + // COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 + 0x9277: checkAlways, + + // COMPRESSED_RGBA8_ETC2_EAC + 0x9278: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ETC2_EAC + 0x9279: checkAlways, + + // ETC1 internal formats: + + // COMPRESSED_RGB_ETC1_WEBGL + 0x8D64: checkAlways, + + // ATC internal formats: + // COMPRESSED_RGB_ATC_WEBGL + // COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL + // COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL + // These formats are no longer supported in WebGL. + // They have no special restrictions on size, so if they were decoded, + // they are already valid. + // We'll show a warning for no format checker found. + + // ASTC internal formats: + + // COMPRESSED_RGBA_ASTC_4x4_KHR + 0x93B0: checkAlways, + + // COMPRESSED_RGBA_ASTC_5x4_KHR + 0x93B1: checkAlways, + + // COMPRESSED_RGBA_ASTC_5x5_KHR + 0x93B2: checkAlways, + + // COMPRESSED_RGBA_ASTC_6x5_KHR + 0x93B3: checkAlways, + + // COMPRESSED_RGBA_ASTC_6x6_KHR + 0x93B4: checkAlways, + + // COMPRESSED_RGBA_ASTC_8x5_KHR + 0x93B5: checkAlways, + + // COMPRESSED_RGBA_ASTC_8x6_KHR + 0x93B6: checkAlways, + + // COMPRESSED_RGBA_ASTC_8x8_KHR + 0x93B7: checkAlways, + + // COMPRESSED_RGBA_ASTC_10x5_KHR + 0x93B8: checkAlways, + + // COMPRESSED_RGBA_ASTC_10x6_KHR + 0x93B9: checkAlways, + + // COMPRESSED_RGBA_ASTC_10x8_KHR + 0x93BA: checkAlways, + + // COMPRESSED_RGBA_ASTC_10x10_KHR + 0x93BB: checkAlways, + + // COMPRESSED_RGBA_ASTC_12x10_KHR + 0x93BC: checkAlways, + + // COMPRESSED_RGBA_ASTC_12x12_KHR + 0x93BD: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR + 0x93D0: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR + 0x93D1: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR + 0x93D2: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR + 0x93D3: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR + 0x93D4: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR + 0x93D5: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR + 0x93D6: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR + 0x93D7: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR + 0x93D8: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR + 0x93D9: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR + 0x93DA: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR + 0x93DB: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR + 0x93DC: checkAlways, + + // COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR + 0x93DD: checkAlways, + + // BPTC internal formats: + + // COMPRESSED_RGBA_BPTC_UNORM_EXT + 0x8E8C: check4x4, + + // COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT + 0x8E8D: check4x4, + + // COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT + 0x8E8E: check4x4, + + // COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT + 0x8E8F: check4x4, + + // RGTC internal formats: + + // COMPRESSED_RED_RGTC1 + 0x8DBB: check4x4, + + // COMPRESSED_SIGNED_RED_RGTC1 + 0x8DBC: check4x4, + + // COMPRESSED_RG_RGTC2 + 0x8DBD: check4x4, + + // COMPRESSED_SIGNED_RG_RGTC2 + 0x8DBE: check4x4, + + // PVRTC internal formats: + + // COMPRESSED_RGB_PVRTC_4BPPV1_IMG + 0x8C00: checkPVRTC, + + // COMPRESSED_RGB_PVRTC_2BPPV1_IMG + 0x8C01: checkPVRTC, + + // COMPRESSED_RGBA_PVRTC_4BPPV1_IMG + 0x8C02: checkPVRTC, + + // COMPRESSED_RGBA_PVRTC_2BPPV1_IMG + 0x8C03: checkPVRTC, + + // S3TC internal formats: + + // COMPRESSED_RGB_S3TC_DXT1_EXT + 0x83F0: check4x4, + + // COMPRESSED_RGBA_S3TC_DXT1_EXT + 0x83F1: check4x4, + + // COMPRESSED_RGBA_S3TC_DXT3_EXT + 0x83F2: check4x4, + + // COMPRESSED_RGBA_S3TC_DXT5_EXT + 0x83F3: check4x4, + + // S3TCSRGB internal formats: + + // COMPRESSED_SRGB_S3TC_DXT1_EXT + 0x8C4C: checkS3TCSRGB, + + // COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + 0x8C4D: checkS3TCSRGB, + + // COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + 0x8C4E: checkS3TCSRGB, + + // COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT + 0x8C4F: checkS3TCSRGB +}; + +module.exports = verifyCompressedTexture; + + +/***/ }), + +/***/ 61309: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Textures.Parsers + */ + +module.exports = { + + AtlasXML: __webpack_require__(89905), + Canvas: __webpack_require__(72893), + Image: __webpack_require__(4832), + JSONArray: __webpack_require__(78566), + JSONHash: __webpack_require__(39711), + KTXParser: __webpack_require__(31403), + PVRParser: __webpack_require__(82038), + SpriteSheet: __webpack_require__(75549), + SpriteSheetFromAtlas: __webpack_require__(47534), + UnityYAML: __webpack_require__(86147) + +}; + + +/***/ }), + +/***/ 80341: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tilemaps.Formats + */ + +module.exports = { + + /** + * CSV Map Type + * + * @name Phaser.Tilemaps.Formats.CSV + * @type {number} + * @since 3.0.0 + */ + CSV: 0, + + /** + * Tiled JSON Map Type + * + * @name Phaser.Tilemaps.Formats.TILED_JSON + * @type {number} + * @since 3.0.0 + */ + TILED_JSON: 1, + + /** + * 2D Array Map Type + * + * @name Phaser.Tilemaps.Formats.ARRAY_2D + * @type {number} + * @since 3.0.0 + */ + ARRAY_2D: 2, + + /** + * Weltmeister (Impact.js) Map Type + * + * @name Phaser.Tilemaps.Formats.WELTMEISTER + * @type {number} + * @since 3.0.0 + */ + WELTMEISTER: 3 + +}; + + +/***/ }), + +/***/ 16536: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * An Image Collection is a special Tile Set containing multiple images, with no slicing into each image. + * + * Image Collections are normally created automatically when Tiled data is loaded. + * + * @class ImageCollection + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @param {string} name - The name of the image collection in the map data. + * @param {number} firstgid - The first image index this image collection contains. + * @param {number} [width=32] - Width of widest image (in pixels). + * @param {number} [height=32] - Height of tallest image (in pixels). + * @param {number} [margin=0] - The margin around all images in the collection (in pixels). + * @param {number} [spacing=0] - The spacing between each image in the collection (in pixels). + * @param {object} [properties={}] - Custom Image Collection properties. + */ +var ImageCollection = new Class({ + + initialize: + + function ImageCollection (name, firstgid, width, height, margin, spacing, properties) + { + if (width === undefined || width <= 0) { width = 32; } + if (height === undefined || height <= 0) { height = 32; } + if (margin === undefined) { margin = 0; } + if (spacing === undefined) { spacing = 0; } + + /** + * The name of the Image Collection. + * + * @name Phaser.Tilemaps.ImageCollection#name + * @type {string} + * @since 3.0.0 + */ + this.name = name; + + /** + * The Tiled firstgid value. + * This is the starting index of the first image index this Image Collection contains. + * + * @name Phaser.Tilemaps.ImageCollection#firstgid + * @type {number} + * @since 3.0.0 + */ + this.firstgid = firstgid | 0; + + /** + * The width of the widest image (in pixels). + * + * @name Phaser.Tilemaps.ImageCollection#imageWidth + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.imageWidth = width | 0; + + /** + * The height of the tallest image (in pixels). + * + * @name Phaser.Tilemaps.ImageCollection#imageHeight + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.imageHeight = height | 0; + + /** + * The margin around the images in the collection (in pixels). + * Use `setSpacing` to change. + * + * @name Phaser.Tilemaps.ImageCollection#imageMarge + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.imageMargin = margin | 0; + + /** + * The spacing between each image in the collection (in pixels). + * Use `setSpacing` to change. + * + * @name Phaser.Tilemaps.ImageCollection#imageSpacing + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.imageSpacing = spacing | 0; + + /** + * Image Collection-specific properties that are typically defined in the Tiled editor. + * + * @name Phaser.Tilemaps.ImageCollection#properties + * @type {object} + * @since 3.0.0 + */ + this.properties = properties || {}; + + /** + * The cached images that are a part of this collection. + * + * @name Phaser.Tilemaps.ImageCollection#images + * @type {array} + * @readonly + * @since 3.0.0 + */ + this.images = []; + + /** + * The total number of images in the image collection. + * + * @name Phaser.Tilemaps.ImageCollection#total + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.total = 0; + }, + + /** + * Returns true if and only if this image collection contains the given image index. + * + * @method Phaser.Tilemaps.ImageCollection#containsImageIndex + * @since 3.0.0 + * + * @param {number} imageIndex - The image index to search for. + * + * @return {boolean} True if this Image Collection contains the given index. + */ + containsImageIndex: function (imageIndex) + { + return (imageIndex >= this.firstgid && imageIndex < (this.firstgid + this.total)); + }, + + /** + * Add an image to this Image Collection. + * + * @method Phaser.Tilemaps.ImageCollection#addImage + * @since 3.0.0 + * + * @param {number} gid - The gid of the image in the Image Collection. + * @param {string} image - The the key of the image in the Image Collection and in the cache. + * @param {number} width - The width of the image in the Image Collection. + * @param {number} height - The height of the image in the Image Collection. + * + * @return {Phaser.Tilemaps.ImageCollection} This ImageCollection object. + */ + addImage: function (gid, image, width, height) + { + this.images.push({ gid: gid, image: image, width: width, height: height }); + this.total++; + + return this; + } + +}); + +module.exports = ImageCollection; + + +/***/ }), + +/***/ 27462: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2021 Photon Storm Ltd. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); + +/** + * @classdesc + * The ObjectHelper helps tie objects with `gids` into the tileset + * that sits behind them. + * + * @class ObjectHelper + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Tilemaps.Tileset[]} tilesets - The backing tileset data. + */ +var ObjectHelper = new Class({ + + initialize: + + function ObjectHelper (tilesets) + { + /** + * The Tile GIDs array. + * + * @name Phaser.Tilemaps.ObjectHelper#gids + * @type {array} + * @since 3.60.0 + */ + this.gids = []; + + if (tilesets !== undefined) + { + for (var t = 0; t < tilesets.length; ++t) + { + var tileset = tilesets[t]; + + for (var i = 0; i < tileset.total; ++i) + { + this.gids[tileset.firstgid + i] = tileset; + } + } + } + + /** + * The Tile GIDs array. + * + * @name Phaser.Tilemaps.ObjectHelper#_gids + * @type {array} + * @private + * @since 3.60.0 + */ + this._gids = this.gids; + }, + + /** + * Enabled if the object helper reaches in to tilesets for data. + * Disabled if it only uses data directly on a gid object. + * + * @name Phaser.Tilemaps.ObjectHelper#enabled + * @type {boolean} + * @since 3.60.0 + */ + enabled: { + + get: function () + { + return !!this.gids; + }, + + set: function (v) + { + this.gids = v ? this._gids : undefined; + } + + }, + + /** + * Gets the Tiled `type` field value from the object or the `gid` behind it. + * + * @method Phaser.Tilemaps.ObjectHelper#getTypeIncludingTile + * @since 3.60.0 + * + * @param {Phaser.Types.Tilemaps.TiledObject} obj - The Tiled object to investigate. + * + * @return {?string} The `type` of the object, the tile behind the `gid` of the object, or `undefined`. + */ + getTypeIncludingTile: function (obj) + { + if (obj.type !== undefined && obj.type !== '') + { + return obj.type; + } + + if (!this.gids || obj.gid === undefined) + { + return undefined; + } + + var tileset = this.gids[obj.gid]; + + if (!tileset) + { + return undefined; + } + + var tileData = tileset.getTileData(obj.gid); + + if (!tileData) + { + return undefined; + } + + return tileData.type; + }, + + /** + * Sets the sprite texture data as specified (usually in a config) or, failing that, + * as specified in the `gid` of the object being loaded (if any). + * + * This fallback will only work if the tileset was loaded as a spritesheet matching + * the geometry of sprites fed into tiled, so that, for example: "tile id #`3`"" within + * the tileset is the same as texture frame `3` from the image of the tileset. + * + * @method Phaser.Tilemaps.ObjectHelper#setTextureAndFrame + * @since 3.60.0 + * + * @param {Phaser.GameObjects.GameObject} sprite - The Game Object to modify. + * @param {string|Phaser.Textures.Texture} [key] - The texture key to set (or else the `obj.gid`'s tile is used if available). + * @param {string|number|Phaser.Textures.Frame} [frame] - The frames key to set (or else the `obj.gid`'s tile is used if available). + * @param {Phaser.Types.Tilemaps.TiledObject} [obj] - The Tiled object for fallback. + */ + setTextureAndFrame: function (sprite, key, frame, obj) + { + if ((key === null) && this.gids && obj.gid !== undefined) + { + var tileset = this.gids[obj.gid]; + + if (tileset) + { + if (key === null && tileset.image !== undefined) + { + key = tileset.image.key; + } + + if (frame === null) + { + // This relies on the tileset texture *also* having been loaded as a spritesheet. This isn't guaranteed! + frame = obj.gid - tileset.firstgid; + } + + // If we can't satisfy the request, probably best to null it out rather than set a whole spritesheet or something. + if (!sprite.scene.textures.getFrame(key, frame)) + { + key = null; + frame = null; + } + } + } + + sprite.setTexture(key, frame); + }, + + /** + * Sets the `sprite.data` field from the tiled properties on the object and its tile (if any). + * + * @method Phaser.Tilemaps.ObjectHelper#setPropertiesFromTiledObject + * @since 3.60.0 + * + * @param {Phaser.GameObjects.GameObject} sprite + * @param {Phaser.Types.Tilemaps.TiledObject} obj + */ + setPropertiesFromTiledObject: function (sprite, obj) + { + if (this.gids !== undefined && obj.gid !== undefined) + { + var tileset = this.gids[obj.gid]; + + if (tileset !== undefined) + { + this.setFromJSON(sprite, tileset.getTileProperties(obj.gid)); + } + } + + this.setFromJSON(sprite, obj.properties); + }, + + /** + * Sets the sprite data from the JSON object. + * + * @method Phaser.Tilemaps.ObjectHelper#setFromJSON + * @since 3.60.0 + * @private + * + * @param {Phaser.GameObjects.GameObject} sprite - The object for which to populate `data`. + * @param {(Object.|Object[])} properties - The properties to set in either JSON object format or else a list of objects with `name` and `value` fields. + */ + setFromJSON: function (sprite, properties) + { + if (!properties) + { + return; + } + + if (Array.isArray(properties)) + { + for (var i = 0; i < properties.length; i++) + { + var prop = properties[i]; + + if (sprite[prop.name] !== undefined) + { + sprite[prop.name] = prop.value; + } + else + { + sprite.setData(prop.name, prop.value); + } + } + + return; + } + + for (var key in properties) + { + if (sprite[key] !== undefined) + { + sprite[key] = properties[key]; + } + else + { + sprite.setData(key, properties[key]); + } + } + } +}); + +module.exports = ObjectHelper; + + +/***/ }), + +/***/ 31989: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Formats = __webpack_require__(80341); +var MapData = __webpack_require__(87010); +var Parse = __webpack_require__(46177); +var Tilemap = __webpack_require__(49075); + +/** + * Create a Tilemap from the given key or data. If neither is given, make a blank Tilemap. When + * loading from CSV or a 2D array, you should specify the tileWidth & tileHeight. When parsing from + * a map from Tiled, the tileWidth, tileHeight, width & height will be pulled from the map data. For + * an empty map, you should specify tileWidth, tileHeight, width & height. + * + * @function Phaser.Tilemaps.ParseToTilemap + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Tilemap belongs. + * @param {string} [key] - The key in the Phaser cache that corresponds to the loaded tilemap data. + * @param {number} [tileWidth=32] - The width of a tile in pixels. + * @param {number} [tileHeight=32] - The height of a tile in pixels. + * @param {number} [width=10] - The width of the map in tiles. + * @param {number} [height=10] - The height of the map in tiles. + * @param {number[][]} [data] - Instead of loading from the cache, you can also load directly from + * a 2D array of tile indexes. + * @param {boolean} [insertNull=false] - Controls how empty tiles, tiles with an index of -1, in the + * map data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {Phaser.Tilemaps.Tilemap} + */ +var ParseToTilemap = function (scene, key, tileWidth, tileHeight, width, height, data, insertNull) +{ + if (tileWidth === undefined) { tileWidth = 32; } + if (tileHeight === undefined) { tileHeight = 32; } + if (width === undefined) { width = 10; } + if (height === undefined) { height = 10; } + if (insertNull === undefined) { insertNull = false; } + + var mapData = null; + + if (Array.isArray(data)) + { + var name = key !== undefined ? key : 'map'; + mapData = Parse(name, Formats.ARRAY_2D, data, tileWidth, tileHeight, insertNull); + } + else if (key !== undefined) + { + var tilemapData = scene.cache.tilemap.get(key); + + if (!tilemapData) + { + console.warn('No map data found for key ' + key); + } + else + { + mapData = Parse(key, tilemapData.format, tilemapData.data, tileWidth, tileHeight, insertNull); + } + } + + if (mapData === null) + { + mapData = new MapData({ + tileWidth: tileWidth, + tileHeight: tileHeight, + width: width, + height: height + }); + } + + return new Tilemap(scene, mapData); +}; + +module.exports = ParseToTilemap; + + +/***/ }), + +/***/ 23029: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Components = __webpack_require__(31401); +var CONST = __webpack_require__(91907); +var DeepCopy = __webpack_require__(62644); +var Rectangle = __webpack_require__(93232); + +/** + * @classdesc + * A Tile is a representation of a single tile within the Tilemap. This is a lightweight data + * representation, so its position information is stored without factoring in scroll, layer + * scale or layer position. + * + * @class Tile + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @extends Phaser.GameObjects.Components.AlphaSingle + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.Visible + * + * @param {Phaser.Tilemaps.LayerData} layer - The LayerData object in the Tilemap that this tile belongs to. + * @param {number} index - The unique index of this tile within the map. + * @param {number} x - The x coordinate of this tile in tile coordinates. + * @param {number} y - The y coordinate of this tile in tile coordinates. + * @param {number} width - Width of the tile in pixels. + * @param {number} height - Height of the tile in pixels. + * @param {number} baseWidth - The base width a tile in the map (in pixels). Tiled maps support + * multiple tileset sizes within one map, but they are still placed at intervals of the base + * tile width. + * @param {number} baseHeight - The base height of the tile in pixels (in pixels). Tiled maps + * support multiple tileset sizes within one map, but they are still placed at intervals of the + * base tile height. + */ +var Tile = new Class({ + + Mixins: [ + Components.AlphaSingle, + Components.Flip, + Components.Visible + ], + + initialize: + + function Tile (layer, index, x, y, width, height, baseWidth, baseHeight) + { + /** + * The LayerData in the Tilemap data that this tile belongs to. + * + * @name Phaser.Tilemaps.Tile#layer + * @type {Phaser.Tilemaps.LayerData} + * @since 3.0.0 + */ + this.layer = layer; + + /** + * The index of this tile within the map data corresponding to the tileset, or -1 if this + * represents a blank tile. + * + * @name Phaser.Tilemaps.Tile#index + * @type {number} + * @since 3.0.0 + */ + this.index = index; + + /** + * The x map coordinate of this tile in tile units. + * + * @name Phaser.Tilemaps.Tile#x + * @type {number} + * @since 3.0.0 + */ + this.x = x; + + /** + * The y map coordinate of this tile in tile units. + * + * @name Phaser.Tilemaps.Tile#y + * @type {number} + * @since 3.0.0 + */ + this.y = y; + + /** + * The width of the tile in pixels. + * + * @name Phaser.Tilemaps.Tile#width + * @type {number} + * @since 3.0.0 + */ + this.width = width; + + /** + * The height of the tile in pixels. + * + * @name Phaser.Tilemaps.Tile#height + * @type {number} + * @since 3.0.0 + */ + this.height = height; + + /** + * The right of the tile in pixels. + * + * Set in the `updatePixelXY` method. + * + * @name Phaser.Tilemaps.Tile#right + * @type {number} + * @since 3.50.0 + */ + this.right; + + /** + * The bottom of the tile in pixels. + * + * Set in the `updatePixelXY` method. + * + * @name Phaser.Tilemaps.Tile#bottom + * @type {number} + * @since 3.50.0 + */ + this.bottom; + + /** + * The maps base width of a tile in pixels. Tiled maps support multiple tileset sizes + * within one map, but they are still placed at intervals of the base tile size. + * + * @name Phaser.Tilemaps.Tile#baseWidth + * @type {number} + * @since 3.0.0 + */ + this.baseWidth = (baseWidth !== undefined) ? baseWidth : width; + + /** + * The maps base height of a tile in pixels. Tiled maps support multiple tileset sizes + * within one map, but they are still placed at intervals of the base tile size. + * + * @name Phaser.Tilemaps.Tile#baseHeight + * @type {number} + * @since 3.0.0 + */ + this.baseHeight = (baseHeight !== undefined) ? baseHeight : height; + + /** + * The x coordinate of the top left of this tile in pixels. This is relative to the top left + * of the layer this tile is being rendered within. This property does NOT factor in camera + * scroll, layer scale or layer position. + * + * @name Phaser.Tilemaps.Tile#pixelX + * @type {number} + * @since 3.0.0 + */ + this.pixelX = 0; + + /** + * The y coordinate of the top left of this tile in pixels. This is relative to the top left + * of the layer this tile is being rendered within. This property does NOT factor in camera + * scroll, layer scale or layer position. + * + * @name Phaser.Tilemaps.Tile#pixelY + * @type {number} + * @since 3.0.0 + */ + this.pixelY = 0; + + this.updatePixelXY(); + + /** + * Tile specific properties. These usually come from Tiled. + * + * @name Phaser.Tilemaps.Tile#properties + * @type {any} + * @since 3.0.0 + */ + this.properties = {}; + + /** + * The rotation angle of this tile. + * + * @name Phaser.Tilemaps.Tile#rotation + * @type {number} + * @since 3.0.0 + */ + this.rotation = 0; + + /** + * Whether the tile should collide with any object on the left side. + * + * This property is used by Arcade Physics only, however, you can also use it + * in your own checks. + * + * @name Phaser.Tilemaps.Tile#collideLeft + * @type {boolean} + * @since 3.0.0 + */ + this.collideLeft = false; + + /** + * Whether the tile should collide with any object on the right side. + * + * This property is used by Arcade Physics only, however, you can also use it + * in your own checks. + * + * @name Phaser.Tilemaps.Tile#collideRight + * @type {boolean} + * @since 3.0.0 + */ + this.collideRight = false; + + /** + * Whether the tile should collide with any object on the top side. + * + * This property is used by Arcade Physics only, however, you can also use it + * in your own checks. + * + * @name Phaser.Tilemaps.Tile#collideUp + * @type {boolean} + * @since 3.0.0 + */ + this.collideUp = false; + + /** + * Whether the tile should collide with any object on the bottom side. + * + * This property is used by Arcade Physics only, however, you can also use it + * in your own checks. + * + * @name Phaser.Tilemaps.Tile#collideDown + * @type {boolean} + * @since 3.0.0 + */ + this.collideDown = false; + + /** + * Whether the tiles left edge is interesting for collisions. + * + * @name Phaser.Tilemaps.Tile#faceLeft + * @type {boolean} + * @since 3.0.0 + */ + this.faceLeft = false; + + /** + * Whether the tiles right edge is interesting for collisions. + * + * @name Phaser.Tilemaps.Tile#faceRight + * @type {boolean} + * @since 3.0.0 + */ + this.faceRight = false; + + /** + * Whether the tiles top edge is interesting for collisions. + * + * @name Phaser.Tilemaps.Tile#faceTop + * @type {boolean} + * @since 3.0.0 + */ + this.faceTop = false; + + /** + * Whether the tiles bottom edge is interesting for collisions. + * + * @name Phaser.Tilemaps.Tile#faceBottom + * @type {boolean} + * @since 3.0.0 + */ + this.faceBottom = false; + + /** + * Tile collision callback. + * + * @name Phaser.Tilemaps.Tile#collisionCallback + * @type {function} + * @since 3.0.0 + */ + this.collisionCallback = undefined; + + /** + * The context in which the collision callback will be called. + * + * @name Phaser.Tilemaps.Tile#collisionCallbackContext + * @type {object} + * @since 3.0.0 + */ + this.collisionCallbackContext = this; + + /** + * The tint to apply to this tile. Note: tint is currently a single color value instead of + * the 4 corner tint component on other GameObjects. + * + * @name Phaser.Tilemaps.Tile#tint + * @type {number} + * @default + * @since 3.0.0 + */ + this.tint = 0xffffff; + + /** + * The tint fill mode. + * + * `false` = An additive tint (the default), where vertices colors are blended with the texture. + * `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha. + * + * @name Phaser.Tilemaps.Tile#tintFill + * @type {boolean} + * @default + * @since 3.70.0 + */ + this.tintFill = false; + + /** + * An empty object where physics-engine specific information (e.g. bodies) may be stored. + * + * @name Phaser.Tilemaps.Tile#physics + * @type {object} + * @since 3.0.0 + */ + this.physics = {}; + }, + + /** + * Check if the given x and y world coordinates are within this Tile. This does not factor in + * camera scroll, layer scale or layer position. + * + * @method Phaser.Tilemaps.Tile#containsPoint + * @since 3.0.0 + * + * @param {number} x - The x coordinate to test. + * @param {number} y - The y coordinate to test. + * + * @return {boolean} True if the coordinates are within this Tile, otherwise false. + */ + containsPoint: function (x, y) + { + return !(x < this.pixelX || y < this.pixelY || x > this.right || y > this.bottom); + }, + + /** + * Copies the tile data and properties from the given Tile to this Tile. This copies everything + * except for position and interesting face calculations. + * + * @method Phaser.Tilemaps.Tile#copy + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.Tile} tile - The tile to copy from. + * + * @return {this} This Tile object instance. + */ + copy: function (tile) + { + this.index = tile.index; + this.alpha = tile.alpha; + this.properties = DeepCopy(tile.properties); + this.visible = tile.visible; + this.setFlip(tile.flipX, tile.flipY); + this.tint = tile.tint; + this.rotation = tile.rotation; + this.collideUp = tile.collideUp; + this.collideDown = tile.collideDown; + this.collideLeft = tile.collideLeft; + this.collideRight = tile.collideRight; + this.collisionCallback = tile.collisionCallback; + this.collisionCallbackContext = tile.collisionCallbackContext; + + return this; + }, + + /** + * The collision group for this Tile, defined within the Tileset. This returns a reference to + * the collision group stored within the Tileset, so any modification of the returned object + * will impact all tiles that have the same index as this tile. + * + * @method Phaser.Tilemaps.Tile#getCollisionGroup + * @since 3.0.0 + * + * @return {?object} The collision group for this Tile, as defined in the Tileset, or `null` if no group was defined. + */ + getCollisionGroup: function () + { + return this.tileset ? this.tileset.getTileCollisionGroup(this.index) : null; + }, + + /** + * The tile data for this Tile, defined within the Tileset. This typically contains Tiled + * collision data, tile animations and terrain information. This returns a reference to the tile + * data stored within the Tileset, so any modification of the returned object will impact all + * tiles that have the same index as this tile. + * + * @method Phaser.Tilemaps.Tile#getTileData + * @since 3.0.0 + * + * @return {?object} The tile data for this Tile, as defined in the Tileset, or `null` if no data was defined. + */ + getTileData: function () + { + return this.tileset ? this.tileset.getTileData(this.index) : null; + }, + + /** + * Gets the world X position of the left side of the tile, factoring in the layers position, + * scale and scroll. + * + * @method Phaser.Tilemaps.Tile#getLeft + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * + * @return {number} The left (x) value of this tile. + */ + getLeft: function (camera) + { + var tilemapLayer = this.tilemapLayer; + + if (tilemapLayer) + { + var point = tilemapLayer.tileToWorldXY(this.x, this.y, undefined, camera); + + return point.x; + } + + return this.x * this.baseWidth; + }, + + /** + * Gets the world X position of the right side of the tile, factoring in the layer's position, + * scale and scroll. + * + * @method Phaser.Tilemaps.Tile#getRight + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * + * @return {number} The right (x) value of this tile. + */ + getRight: function (camera) + { + var tilemapLayer = this.tilemapLayer; + + return (tilemapLayer) ? this.getLeft(camera) + this.width * tilemapLayer.scaleX : this.getLeft(camera) + this.width; + }, + + /** + * Gets the world Y position of the top side of the tile, factoring in the layer's position, + * scale and scroll. + * + * @method Phaser.Tilemaps.Tile#getTop + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * + * @return {number} The top (y) value of this tile. + */ + getTop: function (camera) + { + var tilemapLayer = this.tilemapLayer; + + // Tiled places tiles on a grid of baseWidth x baseHeight. The origin for a tile in grid + // units is the bottom left, so the y coordinate needs to be adjusted by the difference + // between the base size and this tile's size. + if (tilemapLayer) + { + var point = tilemapLayer.tileToWorldXY(this.x, this.y, undefined, camera); + + return point.y; + } + + return this.y * this.baseWidth - (this.height - this.baseHeight); + }, + + /** + * Gets the world Y position of the bottom side of the tile, factoring in the layer's position, + * scale and scroll. + + * @method Phaser.Tilemaps.Tile#getBottom + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * + * @return {number} The bottom (y) value of this tile. + */ + getBottom: function (camera) + { + var tilemapLayer = this.tilemapLayer; + + return tilemapLayer + ? this.getTop(camera) + this.height * tilemapLayer.scaleY + : this.getTop(camera) + this.height; + }, + + /** + * Gets the world rectangle bounding box for the tile, factoring in the layers position, + * scale and scroll. + * + * @method Phaser.Tilemaps.Tile#getBounds + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * @param {Phaser.Geom.Rectangle} [output] - Optional Rectangle object to store the results in. + * + * @return {(Phaser.Geom.Rectangle|object)} The bounds of this Tile. + */ + getBounds: function (camera, output) + { + if (output === undefined) { output = new Rectangle(); } + + output.x = this.getLeft(camera); + output.y = this.getTop(camera); + output.width = this.getRight(camera) - output.x; + output.height = this.getBottom(camera) - output.y; + + return output; + }, + + /** + * Gets the world X position of the center of the tile, factoring in the layer's position, + * scale and scroll. + * + * @method Phaser.Tilemaps.Tile#getCenterX + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * + * @return {number} The center x position of this Tile. + */ + getCenterX: function (camera) + { + return (this.getLeft(camera) + this.getRight(camera)) / 2; + }, + + /** + * Gets the world Y position of the center of the tile, factoring in the layer's position, + * scale and scroll. + * + * @method Phaser.Tilemaps.Tile#getCenterY + * @since 3.0.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use to perform the check. + * + * @return {number} The center y position of this Tile. + */ + getCenterY: function (camera) + { + return (this.getTop(camera) + this.getBottom(camera)) / 2; + }, + + /** + * Check for intersection with this tile. This does not factor in camera scroll, layer scale or + * layer position. + * + * @method Phaser.Tilemaps.Tile#intersects + * @since 3.0.0 + * + * @param {number} x - The x axis in pixels. + * @param {number} y - The y axis in pixels. + * @param {number} right - The right point. + * @param {number} bottom - The bottom point. + * + * @return {boolean} `true` if the Tile intersects with the given dimensions, otherwise `false`. + */ + intersects: function (x, y, right, bottom) + { + return !( + right <= this.pixelX || bottom <= this.pixelY || + x >= this.right || y >= this.bottom + ); + }, + + /** + * Checks if the tile is interesting. + * + * @method Phaser.Tilemaps.Tile#isInteresting + * @since 3.0.0 + * + * @param {boolean} collides - If true, will consider the tile interesting if it collides on any side. + * @param {boolean} faces - If true, will consider the tile interesting if it has an interesting face. + * + * @return {boolean} True if the Tile is interesting, otherwise false. + */ + isInteresting: function (collides, faces) + { + if (collides && faces) + { + return (this.canCollide || this.hasInterestingFace); + } + else if (collides) + { + return this.collides; + } + else if (faces) + { + return this.hasInterestingFace; + } + + return false; + }, + + /** + * Reset collision status flags. + * + * @method Phaser.Tilemaps.Tile#resetCollision + * @since 3.0.0 + * + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate interesting faces for this tile and its neighbors. + * + * @return {this} This Tile object instance. + */ + resetCollision: function (recalculateFaces) + { + if (recalculateFaces === undefined) { recalculateFaces = true; } + + this.collideLeft = false; + this.collideRight = false; + this.collideUp = false; + this.collideDown = false; + + this.faceTop = false; + this.faceBottom = false; + this.faceLeft = false; + this.faceRight = false; + + if (recalculateFaces) + { + var tilemapLayer = this.tilemapLayer; + + if (tilemapLayer) + { + this.tilemapLayer.calculateFacesAt(this.x, this.y); + } + } + + return this; + }, + + /** + * Reset faces. + * + * @method Phaser.Tilemaps.Tile#resetFaces + * @since 3.0.0 + * + * @return {this} This Tile object instance. + */ + resetFaces: function () + { + this.faceTop = false; + this.faceBottom = false; + this.faceLeft = false; + this.faceRight = false; + + return this; + }, + + /** + * Sets the collision flags for each side of this tile and updates the interesting faces list. + * + * @method Phaser.Tilemaps.Tile#setCollision + * @since 3.0.0 + * + * @param {boolean} left - Indicating collide with any object on the left. + * @param {boolean} [right] - Indicating collide with any object on the right. + * @param {boolean} [up] - Indicating collide with any object on the top. + * @param {boolean} [down] - Indicating collide with any object on the bottom. + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate interesting faces for this tile and its neighbors. + * + * @return {this} This Tile object instance. + */ + setCollision: function (left, right, up, down, recalculateFaces) + { + if (right === undefined) { right = left; } + if (up === undefined) { up = left; } + if (down === undefined) { down = left; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + this.collideLeft = left; + this.collideRight = right; + this.collideUp = up; + this.collideDown = down; + + this.faceLeft = left; + this.faceRight = right; + this.faceTop = up; + this.faceBottom = down; + + if (recalculateFaces) + { + var tilemapLayer = this.tilemapLayer; + + if (tilemapLayer) + { + this.tilemapLayer.calculateFacesAt(this.x, this.y); + } + } + + return this; + }, + + /** + * Set a callback to be called when this tile is hit by an object. The callback must true for + * collision processing to take place. + * + * @method Phaser.Tilemaps.Tile#setCollisionCallback + * @since 3.0.0 + * + * @param {function} callback - Callback function. + * @param {object} context - Callback will be called within this context. + * + * @return {this} This Tile object instance. + */ + setCollisionCallback: function (callback, context) + { + if (callback === null) + { + this.collisionCallback = undefined; + this.collisionCallbackContext = undefined; + } + else + { + this.collisionCallback = callback; + this.collisionCallbackContext = context; + } + + return this; + }, + + /** + * Sets the size of the tile and updates its pixelX and pixelY. + * + * @method Phaser.Tilemaps.Tile#setSize + * @since 3.0.0 + * + * @param {number} tileWidth - The width of the tile in pixels. + * @param {number} tileHeight - The height of the tile in pixels. + * @param {number} baseWidth - The base width a tile in the map (in pixels). + * @param {number} baseHeight - The base height of the tile in pixels (in pixels). + * + * @return {this} This Tile object instance. + */ + setSize: function (tileWidth, tileHeight, baseWidth, baseHeight) + { + if (tileWidth !== undefined) { this.width = tileWidth; } + if (tileHeight !== undefined) { this.height = tileHeight; } + if (baseWidth !== undefined) { this.baseWidth = baseWidth; } + if (baseHeight !== undefined) { this.baseHeight = baseHeight; } + + this.updatePixelXY(); + + return this; + }, + + /** + * Used internally. Updates the tiles world XY position based on the current tile size. + * + * @method Phaser.Tilemaps.Tile#updatePixelXY + * @since 3.0.0 + * + * @return {this} This Tile object instance. + */ + updatePixelXY: function () + { + var orientation = this.layer.orientation; + + if (orientation === CONST.ORTHOGONAL) + { + // In orthogonal mode, Tiled places tiles on a grid of baseWidth x baseHeight. The origin for a tile is the + // bottom left, while the Phaser renderer assumes the origin is the top left. The y + // coordinate needs to be adjusted by the difference. + + this.pixelX = this.x * this.baseWidth; + this.pixelY = this.y * this.baseHeight; + } + else if (orientation === CONST.ISOMETRIC) + { + // Reminder: For the tilemap to be centered we have to move the image to the right with the camera! + // This is crucial for wordtotile, tiletoworld to work. + + this.pixelX = (this.x - this.y) * this.baseWidth * 0.5; + this.pixelY = (this.x + this.y) * this.baseHeight * 0.5; + } + else if (orientation === CONST.STAGGERED) + { + this.pixelX = this.x * this.baseWidth + this.y % 2 * (this.baseWidth / 2); + this.pixelY = this.y * (this.baseHeight / 2); + } + else if (orientation === CONST.HEXAGONAL) + { + var staggerAxis = this.layer.staggerAxis; + var staggerIndex = this.layer.staggerIndex; + var len = this.layer.hexSideLength; + var rowWidth; + var rowHeight; + + if (staggerAxis === 'y') + { + rowHeight = ((this.baseHeight - len) / 2 + len); + + if (staggerIndex === 'odd') + { + this.pixelX = this.x * this.baseWidth + this.y % 2 * (this.baseWidth / 2); + } + else + { + this.pixelX = this.x * this.baseWidth - this.y % 2 * (this.baseWidth / 2); + } + + this.pixelY = this.y * rowHeight; + } + else if (staggerAxis === 'x') + { + rowWidth = ((this.baseWidth - len) / 2 + len); + + this.pixelX = this.x * rowWidth; + + if (staggerIndex === 'odd') + { + this.pixelY = this.y * this.baseHeight + this.x % 2 * (this.baseHeight / 2); + } + else + { + this.pixelY = this.y * this.baseHeight - this.x % 2 * (this.baseHeight / 2); + } + } + } + + this.right = this.pixelX + this.baseWidth; + this.bottom = this.pixelY + this.baseHeight; + + return this; + }, + + /** + * Clean up memory. + * + * @method Phaser.Tilemaps.Tile#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.collisionCallback = undefined; + this.collisionCallbackContext = undefined; + this.properties = undefined; + }, + + /** + * True if this tile can collide on any of its faces or has a collision callback set. + * + * @name Phaser.Tilemaps.Tile#canCollide + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + canCollide: { + + get: function () + { + return (this.collideLeft || this.collideRight || this.collideUp || this.collideDown || (this.collisionCallback !== undefined)); + } + + }, + + /** + * True if this tile can collide on any of its faces. + * + * @name Phaser.Tilemaps.Tile#collides + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + collides: { + + get: function () + { + return (this.collideLeft || this.collideRight || this.collideUp || this.collideDown); + } + + }, + + /** + * True if this tile has any interesting faces. + * + * @name Phaser.Tilemaps.Tile#hasInterestingFace + * @type {boolean} + * @readonly + * @since 3.0.0 + */ + hasInterestingFace: { + + get: function () + { + return (this.faceTop || this.faceBottom || this.faceLeft || this.faceRight); + } + + }, + + /** + * The tileset that contains this Tile. This is null if accessed from a LayerData instance + * before the tile is placed in a TilemapLayer, or if the tile has an index that doesn't correspond + * to any of the maps tilesets. + * + * @name Phaser.Tilemaps.Tile#tileset + * @type {?Phaser.Tilemaps.Tileset} + * @readonly + * @since 3.0.0 + */ + tileset: { + + get: function () + { + var tilemapLayer = this.layer.tilemapLayer; + + if (tilemapLayer) + { + var tileset = tilemapLayer.gidMap[this.index]; + + if (tileset) + { + return tileset; + } + } + + return null; + } + + }, + + /** + * The tilemap layer that contains this Tile. This will only return null if accessed from a + * LayerData instance before the tile is placed within a TilemapLayer. + * + * @name Phaser.Tilemaps.Tile#tilemapLayer + * @type {?Phaser.Tilemaps.TilemapLayer} + * @readonly + * @since 3.0.0 + */ + tilemapLayer: { + + get: function () + { + return this.layer.tilemapLayer; + } + + }, + + /** + * The tilemap that contains this Tile. This will only return null if accessed from a LayerData + * instance before the tile is placed within a TilemapLayer. + * + * @name Phaser.Tilemaps.Tile#tilemap + * @type {?Phaser.Tilemaps.Tilemap} + * @readonly + * @since 3.0.0 + */ + tilemap: { + + get: function () + { + var tilemapLayer = this.tilemapLayer; + + return tilemapLayer ? tilemapLayer.tilemap : null; + } + + } + +}); + +module.exports = Tile; + + +/***/ }), + +/***/ 49075: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BuildTilesetIndex = __webpack_require__(84101); +var Class = __webpack_require__(83419); +var DegToRad = __webpack_require__(39506); +var Formats = __webpack_require__(80341); +var GetFastValue = __webpack_require__(95540); +var LayerData = __webpack_require__(14977); +var ObjectHelper = __webpack_require__(27462); +var ORIENTATION = __webpack_require__(91907); +var Rotate = __webpack_require__(36305); +var SpliceOne = __webpack_require__(19133); +var Sprite = __webpack_require__(68287); +var Tile = __webpack_require__(23029); +var TilemapComponents = __webpack_require__(81086); +var TilemapLayerBase = __webpack_require__(44731); +var TilemapGPULayer = __webpack_require__(53180); +var TilemapLayer = __webpack_require__(20442); +var Tileset = __webpack_require__(33629); + +/** + * A predicate, to test each element of the array. + * + * @callback TilemapFilterCallback + * + * @param {Phaser.GameObjects.GameObject} value - An object found in the filtered area. + * @param {number} index - The index of the object within the array. + * @param {Phaser.GameObjects.GameObject[]} array - An array of all the objects found. + * + * @return {boolean} A value that coerces to `true` to keep the element, or to `false` otherwise. + */ + +/** + * @callback TilemapFindCallback + * + * @param {Phaser.GameObjects.GameObject} value - An object found. + * @param {number} index - The index of the object within the array. + * @param {Phaser.GameObjects.GameObject[]} array - An array of all the objects found. + * + * @return {boolean} `true` if the callback should be invoked, otherwise `false`. + */ + +/** + * @classdesc + * A Tilemap is a container for Tilemap data. This isn't a display object, rather, it holds data + * about the map and allows you to add tilesets and tilemap layers to it. A map can have one or + * more tilemap layers, which are the display objects that actually render the tiles. + * + * The Tilemap data can be parsed from a Tiled JSON file, a CSV file or a 2D array. Tiled is a free + * software package specifically for creating tile maps, and is available from: + * http://www.mapeditor.org + * + * As of Phaser 3.50.0 the Tilemap API now supports the following types of map: + * + * 1) Orthogonal + * 2) Isometric + * 3) Hexagonal + * 4) Staggered + * + * Prior to this release, only orthogonal maps were supported. + * + * Another large change in 3.50 was the consolidation of Tilemap Layers. Previously, you created + * either a Static or Dynamic Tilemap Layer. However, as of 3.50 the features of both have been + * merged and the API simplified, so now there is just the single `TilemapLayer` class. + * + * A Tilemap has handy methods for getting and manipulating the tiles within a layer, allowing + * you to build or modify the tilemap data at runtime. + * + * Note that all Tilemaps use a base tile size to calculate dimensions from, but that a + * TilemapLayer may have its own unique tile size that overrides this. + * + * As of Phaser 3.21.0, if your tilemap includes layer groups (a feature of Tiled 1.2.0+) these + * will be traversed and the following properties will impact children: + * + * - Opacity (blended with parent) and visibility (parent overrides child) + * - Vertical and horizontal offset + * + * The grouping hierarchy is not preserved and all layers will be flattened into a single array. + * + * Group layers are parsed during Tilemap construction but are discarded after parsing so dynamic + * layers will NOT continue to be affected by a parent. + * + * To avoid duplicate layer names, a layer that is a child of a group layer will have its parent + * group name prepended with a '/'. For example, consider a group called 'ParentGroup' with a + * child called 'Layer 1'. In the Tilemap object, 'Layer 1' will have the name + * 'ParentGroup/Layer 1'. + * + * The Phaser Tiled Parser does **not** support the 'Collection of Images' feature for a Tileset. + * You must ensure all of your tiles are contained in a single tileset image file (per layer) + * and have this 'embedded' in the exported Tiled JSON map data. + * + * @class Tilemap + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Tilemap belongs. + * @param {Phaser.Tilemaps.MapData} mapData - A MapData instance containing Tilemap data. + */ +var Tilemap = new Class({ + + initialize: + + function Tilemap (scene, mapData) + { + /** + * @name Phaser.Tilemaps.Tilemap#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The base width of a tile in pixels. Note that individual layers may have a different tile + * width. + * + * @name Phaser.Tilemaps.Tilemap#tileWidth + * @type {number} + * @since 3.0.0 + */ + this.tileWidth = mapData.tileWidth; + + /** + * The base height of a tile in pixels. Note that individual layers may have a different + * tile height. + * + * @name Phaser.Tilemaps.Tilemap#tileHeight + * @type {number} + * @since 3.0.0 + */ + this.tileHeight = mapData.tileHeight; + + /** + * The width of the map (in tiles). + * + * @name Phaser.Tilemaps.Tilemap#width + * @type {number} + * @since 3.0.0 + */ + this.width = mapData.width; + + /** + * The height of the map (in tiles). + * + * @name Phaser.Tilemaps.Tilemap#height + * @type {number} + * @since 3.0.0 + */ + this.height = mapData.height; + + /** + * The orientation of the map data (as specified in Tiled), usually 'orthogonal'. + * + * @name Phaser.Tilemaps.Tilemap#orientation + * @type {string} + * @since 3.0.0 + */ + this.orientation = mapData.orientation; + + /** + * The render (draw) order of the map data (as specified in Tiled), usually 'right-down'. + * + * The draw orders are: + * + * right-down + * left-down + * right-up + * left-up + * + * This can be changed via the `setRenderOrder` method. + * + * @name Phaser.Tilemaps.Tilemap#renderOrder + * @type {string} + * @since 3.12.0 + */ + this.renderOrder = mapData.renderOrder; + + /** + * The format of the map data. + * + * @name Phaser.Tilemaps.Tilemap#format + * @type {number} + * @since 3.0.0 + */ + this.format = mapData.format; + + /** + * The version of the map data (as specified in Tiled, usually 1). + * + * @name Phaser.Tilemaps.Tilemap#version + * @type {number} + * @since 3.0.0 + */ + this.version = mapData.version; + + /** + * Map specific properties as specified in Tiled. + * + * Depending on the version of Tiled and the JSON export used, this will be either + * an object or an array of objects. For Tiled 1.2.0+ maps, it will be an array. + * + * @name Phaser.Tilemaps.Tilemap#properties + * @type {object|object[]} + * @since 3.0.0 + */ + this.properties = mapData.properties; + + /** + * The width of the map in pixels based on width * tileWidth. + * + * @name Phaser.Tilemaps.Tilemap#widthInPixels + * @type {number} + * @since 3.0.0 + */ + this.widthInPixels = mapData.widthInPixels; + + /** + * The height of the map in pixels based on height * tileHeight. + * + * @name Phaser.Tilemaps.Tilemap#heightInPixels + * @type {number} + * @since 3.0.0 + */ + this.heightInPixels = mapData.heightInPixels; + + /** + * A collection of Images, as parsed from Tiled map data. + * + * @name Phaser.Tilemaps.Tilemap#imageCollections + * @type {Phaser.Tilemaps.ImageCollection[]} + * @since 3.0.0 + */ + this.imageCollections = mapData.imageCollections; + + /** + * An array of Tiled Image Layers. + * + * @name Phaser.Tilemaps.Tilemap#images + * @type {array} + * @since 3.0.0 + */ + this.images = mapData.images; + + /** + * An array of Tilemap layer data. + * + * @name Phaser.Tilemaps.Tilemap#layers + * @type {Phaser.Tilemaps.LayerData[]} + * @since 3.0.0 + */ + this.layers = mapData.layers; + + /** + * Master list of tiles -> x, y, index in tileset. + * + * @name Phaser.Tilemaps.Tilemap#tiles + * @type {array} + * @since 3.60.0 + * @see Phaser.Tilemaps.Parsers.Tiled.BuildTilesetIndex + */ + this.tiles = mapData.tiles; + + /** + * An array of Tilesets used in the map. + * + * @name Phaser.Tilemaps.Tilemap#tilesets + * @type {Phaser.Tilemaps.Tileset[]} + * @since 3.0.0 + */ + this.tilesets = mapData.tilesets; + + /** + * An array of ObjectLayer instances parsed from Tiled object layers. + * + * @name Phaser.Tilemaps.Tilemap#objects + * @type {Phaser.Tilemaps.ObjectLayer[]} + * @since 3.0.0 + */ + this.objects = mapData.objects; + + /** + * The index of the currently selected LayerData object. + * + * @name Phaser.Tilemaps.Tilemap#currentLayerIndex + * @type {number} + * @since 3.0.0 + */ + this.currentLayerIndex = 0; + + /** + * The length of the horizontal sides of the hexagon. + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.Tilemap#hexSideLength + * @type {number} + * @since 3.50.0 + */ + this.hexSideLength = mapData.hexSideLength; + + var orientation = this.orientation; + + /** + * Functions used to handle world to tile, and tile to world, conversion. + * Cached here for internal use by public methods such as `worldToTileXY`, etc. + * + * @name Phaser.Tilemaps.Tilemap#_convert + * @private + * @type {object} + * @since 3.50.0 + */ + this._convert = { + WorldToTileXY: TilemapComponents.GetWorldToTileXYFunction(orientation), + WorldToTileX: TilemapComponents.GetWorldToTileXFunction(orientation), + WorldToTileY: TilemapComponents.GetWorldToTileYFunction(orientation), + TileToWorldXY: TilemapComponents.GetTileToWorldXYFunction(orientation), + TileToWorldX: TilemapComponents.GetTileToWorldXFunction(orientation), + TileToWorldY: TilemapComponents.GetTileToWorldYFunction(orientation), + GetTileCorners: TilemapComponents.GetTileCornersFunction(orientation) + }; + }, + + /** + * Sets the rendering (draw) order of the tiles in this map. + * + * The default is 'right-down', meaning it will order the tiles starting from the top-left, + * drawing to the right and then moving down to the next row. + * + * The draw orders are: + * + * 0 = right-down + * 1 = left-down + * 2 = right-up + * 3 = left-up + * + * Setting the render order does not change the tiles or how they are stored in the layer, + * it purely impacts the order in which they are rendered. + * + * You can provide either an integer (0 to 3), or the string version of the order. + * + * Calling this method _after_ creating Tilemap Layers will **not** automatically + * update them to use the new render order. If you call this method after creating layers, use their + * own `setRenderOrder` methods to change them as needed. + * + * @method Phaser.Tilemaps.Tilemap#setRenderOrder + * @since 3.12.0 + * + * @param {(number|string)} renderOrder - The render (draw) order value. Either an integer between 0 and 3, or a string: 'right-down', 'left-down', 'right-up' or 'left-up'. + * + * @return {this} This Tilemap object. + */ + setRenderOrder: function (renderOrder) + { + var orders = [ 'right-down', 'left-down', 'right-up', 'left-up' ]; + + if (typeof renderOrder === 'number') + { + renderOrder = orders[renderOrder]; + } + + if (orders.indexOf(renderOrder) > -1) + { + this.renderOrder = renderOrder; + } + + return this; + }, + + /** + * Adds an image to the map to be used as a tileset. A single map may use multiple tilesets. + * Note that the tileset name can be found in the JSON file exported from Tiled, or in the Tiled + * editor. + * + * @method Phaser.Tilemaps.Tilemap#addTilesetImage + * @since 3.0.0 + * + * @param {string} tilesetName - The name of the tileset as specified in the map data. + * @param {string} [key] - The key of the Phaser.Cache image used for this tileset. If + * `undefined` or `null` it will look for an image with a key matching the tilesetName parameter. + * @param {number} [tileWidth] - The width of the tile (in pixels) in the Tileset Image. If not + * given it will default to the map's tileWidth value, or the tileWidth specified in the Tiled + * JSON file. + * @param {number} [tileHeight] - The height of the tiles (in pixels) in the Tileset Image. If + * not given it will default to the map's tileHeight value, or the tileHeight specified in the + * Tiled JSON file. + * @param {number} [tileMargin] - The margin around the tiles in the sheet (in pixels). If not + * specified, it will default to 0 or the value specified in the Tiled JSON file. + * @param {number} [tileSpacing] - The spacing between each the tile in the sheet (in pixels). + * If not specified, it will default to 0 or the value specified in the Tiled JSON file. + * @param {number} [gid=0] - If adding multiple tilesets to a blank map, specify the starting + * GID this set will use here. + * @param {object} [tileOffset={x: 0, y: 0}] - Tile texture drawing offset. + * If not specified, it will default to {0, 0} + * + * @return {?Phaser.Tilemaps.Tileset} Returns the Tileset object that was created or updated, or null if it + * failed. + */ + addTilesetImage: function (tilesetName, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid, tileOffset) + { + if (tilesetName === undefined) { return null; } + if (key === undefined || key === null) { key = tilesetName; } + + var textureManager = this.scene.sys.textures; + + if (!textureManager.exists(key)) + { + console.warn('Texture key "%s" not found', key); + return null; + } + + var texture = textureManager.get(key); + + var index = this.getTilesetIndex(tilesetName); + + if (index === null && this.format === Formats.TILED_JSON) + { + console.warn('Tilemap has no tileset "%s". Its tilesets are %o', tilesetName, this.tilesets); + return null; + } + + var tileset = this.tilesets[ index ]; + + if (tileset) + { + if (tileWidth || tileHeight) + { + tileset.setTileSize(tileWidth, tileHeight); + } + + if (tileMargin || tileSpacing) + { + tileset.setSpacing(tileMargin, tileSpacing); + } + + tileset.setImage(texture); + + return tileset; + } + + if (tileWidth === undefined) { tileWidth = this.tileWidth; } + if (tileHeight === undefined) { tileHeight = this.tileHeight; } + if (tileMargin === undefined) { tileMargin = 0; } + if (tileSpacing === undefined) { tileSpacing = 0; } + if (gid === undefined) { gid = 0; } + if (tileOffset === undefined) { tileOffset = { x: 0, y: 0 }; } + + tileset = new Tileset(tilesetName, gid, tileWidth, tileHeight, tileMargin, tileSpacing, undefined, undefined, tileOffset); + + tileset.setImage(texture); + + this.tilesets.push(tileset); + + this.tiles = BuildTilesetIndex(this); + + return tileset; + }, + + /** + * Copies the tiles in the source rectangular area to a new destination (all specified in tile + * coordinates) within the layer. This copies all tile properties & recalculates collision + * information in the destination region. + * + * If no layer specified, the map's current layer is used. This cannot be applied to StaticTilemapLayers. + * + * @method Phaser.Tilemaps.Tilemap#copy + * @since 3.0.0 + * + * @param {number} srcTileX - The x coordinate of the area to copy from, in tiles, not pixels. + * @param {number} srcTileY - The y coordinate of the area to copy from, in tiles, not pixels. + * @param {number} width - The width of the area to copy, in tiles, not pixels. + * @param {number} height - The height of the area to copy, in tiles, not pixels. + * @param {number} destTileX - The x coordinate of the area to copy to, in tiles, not pixels. + * @param {number} destTileY - The y coordinate of the area to copy to, in tiles, not pixels. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + copy: function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer) + { + layer = this.getLayer(layer); + + if (layer !== null) + { + TilemapComponents.Copy( + srcTileX, srcTileY, + width, height, + destTileX, destTileY, + recalculateFaces, layer + ); + + return this; + } + else + { + return null; + } + }, + + /** + * Creates a new and empty Tilemap Layer. The currently selected layer in the map is set to this new layer. + * + * Prior to v3.50.0 this method was called `createBlankDynamicLayer`. + * + * @method Phaser.Tilemaps.Tilemap#createBlankLayer + * @since 3.0.0 + * + * @param {string} name - The name of this layer. Must be unique within the map. + * @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object. + * @param {number} [x=0] - The world x position where the top left of this layer will be placed. + * @param {number} [y=0] - The world y position where the top left of this layer will be placed. + * @param {number} [width] - The width of the layer in tiles. If not specified, it will default to the map's width. + * @param {number} [height] - The height of the layer in tiles. If not specified, it will default to the map's height. + * @param {number} [tileWidth] - The width of the tiles the layer uses for calculations. If not specified, it will default to the map's tileWidth. + * @param {number} [tileHeight] - The height of the tiles the layer uses for calculations. If not specified, it will default to the map's tileHeight. + * + * @return {?Phaser.Tilemaps.TilemapLayer} Returns the new layer that was created, or `null` if it failed. + */ + createBlankLayer: function (name, tileset, x, y, width, height, tileWidth, tileHeight) + { + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + if (width === undefined) { width = this.width; } + if (height === undefined) { height = this.height; } + if (tileWidth === undefined) { tileWidth = this.tileWidth; } + if (tileHeight === undefined) { tileHeight = this.tileHeight; } + + var index = this.getLayerIndex(name); + + if (index !== null) + { + console.warn('Invalid Tilemap Layer ID: ' + name); + return null; + } + + var layerData = new LayerData({ + name: name, + tileWidth: tileWidth, + tileHeight: tileHeight, + width: width, + height: height, + orientation: this.orientation, + hexSideLength: this.hexSideLength + }); + + var row; + + for (var tileY = 0; tileY < height; tileY++) + { + row = []; + + for (var tileX = 0; tileX < width; tileX++) + { + row.push(new Tile(layerData, -1, tileX, tileY, tileWidth, tileHeight, this.tileWidth, this.tileHeight)); + } + + layerData.data.push(row); + } + + this.layers.push(layerData); + + this.currentLayerIndex = this.layers.length - 1; + + var layer = new TilemapLayer(this.scene, this, this.currentLayerIndex, tileset, x, y); + + layer.setRenderOrder(this.renderOrder); + + this.scene.sys.displayList.add(layer); + + return layer; + }, + + /** + * Creates a new Tilemap Layer that renders the LayerData associated with the given + * `layerID`. The currently selected layer in the map is set to this new layer. + * + * The `layerID` is important. If you've created your map in Tiled then you can get this by + * looking in Tiled and looking at the layer name. Or you can open the JSON file it exports and + * look at the layers[].name value. Either way it must match. + * + * Prior to v3.50.0 this method was called `createDynamicLayer`. + * + * @method Phaser.Tilemaps.Tilemap#createLayer + * @since 3.0.0 + * + * @param {(number|string)} layerID - The layer array index value, or if a string is given, the layer name from Tiled. + * @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object. + * @param {number} [x=0] - The x position to place the layer in the world. If not specified, it will default to the layer offset from Tiled or 0. + * @param {number} [y=0] - The y position to place the layer in the world. If not specified, it will default to the layer offset from Tiled or 0. + * @param {boolean} [gpu=false] - Create a TilemapGPULayer instead of a TilemapLayer. This option is WebGL-only. A TilemapGPULayer is less flexible, but can be much faster. + * + * @return {?Phaser.Tilemaps.TilemapLayer|?Phaser.Tilemaps.TilemapGPULayer} Returns the new layer was created, or null if it failed. + */ + createLayer: function (layerID, tileset, x, y, gpu) + { + var index = this.getLayerIndex(layerID); + + if (index === null) + { + console.warn('Invalid Tilemap Layer ID: ' + layerID); + + if (typeof layerID === 'string') + { + console.warn('Valid tilelayer names: %o', this.getTileLayerNames()); + } + + return null; + } + + var layerData = this.layers[ index ]; + + // Check for an associated tilemap layer + if (layerData.tilemapLayer) + { + console.warn('Tilemap Layer ID already exists:' + layerID); + return null; + } + + this.currentLayerIndex = index; + + // Default the x/y position to match Tiled layer offset, if it exists. + + if (x === undefined) + { + x = layerData.x; + } + + if (y === undefined) + { + y = layerData.y; + } + + var layer; + + if (gpu) + { + layer = new TilemapGPULayer(this.scene, this, index, tileset, x, y); + } + else + { + layer = new TilemapLayer(this.scene, this, index, tileset, x, y); + + layer.setRenderOrder(this.renderOrder); + } + + + this.scene.sys.displayList.add(layer); + + return layer; + }, + + /** + * This method will iterate through all of the objects defined in a Tiled Object Layer and then + * convert the matching results into Phaser Game Objects (by default, Sprites) + * + * Objects are matched on one of 4 criteria: The Object ID, the Object GID, the Object Name, or the Object Type. + * + * Within Tiled, Object IDs are unique per Object. Object GIDs, however, are shared by all objects + * using the same image. Finally, Object Names and Types are strings and the same name can be used on multiple + * Objects in Tiled, they do not have to be unique; Names are specific to Objects while Types can be inherited + * from Object GIDs using the same image. + * + * You set the configuration parameter accordingly, based on which type of criteria you wish + * to match against. For example, to convert all items on an Object Layer with a `gid` of 26: + * + * ```javascript + * createFromObjects(layerName, { + * gid: 26 + * }); + * ``` + * + * Or, to convert objects with the name 'bonus': + * + * ```javascript + * createFromObjects(layerName, { + * name: 'bonus' + * }); + * ``` + * + * Or, to convert an object with a specific id: + * + * ```javascript + * createFromObjects(layerName, { + * id: 9 + * }); + * ``` + * + * You should only specify either `id`, `gid`, `name`, `type`, or none of them. Do not add more than + * one criteria to your config. If you do not specify any criteria, then _all_ objects in the + * Object Layer will be converted. + * + * By default this method will convert Objects into {@link Phaser.GameObjects.Sprite} instances, but you can override + * this by providing your own class type: + * + * ```javascript + * createFromObjects(layerName, { + * gid: 26, + * classType: Coin + * }); + * ``` + * + * This will convert all Objects with a gid of 26 into your custom `Coin` class. You can pass + * any class type here, but it _must_ extend {@link Phaser.GameObjects.GameObject} as its base class. + * Your class will always be passed 1 parameter: `scene`, which is a reference to either the Scene + * specified in the config object or, if not given, the Scene to which this Tilemap belongs. The + * class must have {@link Phaser.GameObjects.Components.Transform#setPosition setPosition} and + * {@link Phaser.GameObjects.Components.Texture#setTexture setTexture} methods. + * + * This method will set the following Tiled Object properties on the new Game Object: + * + * - `flippedHorizontal` as `flipX` + * - `flippedVertical` as `flipY` + * - `height` as `displayHeight` + * - `name` + * - `rotation` + * - `visible` + * - `width` as `displayWidth` + * - `x`, adjusted for origin + * - `y`, adjusted for origin + * + * Additionally, this method will set Tiled Object custom properties + * + * - on the Game Object, if it has the same property name and a value that isn't `undefined`; or + * - on the Game Object's {@link Phaser.GameObjects.GameObject#data data store} otherwise. + * + * For example, a Tiled Object with custom properties `{ alpha: 0.5, gold: 1 }` will be created as a Game + * Object with an `alpha` value of 0.5 and a `data.values.gold` value of 1. + * + * When `useTileset` is `true` (the default), Tile Objects will inherit the texture and any tile properties + * from the tileset, and the local tile ID will be used as the texture frame. For the frame selection to work + * you need to load the tileset texture as a spritesheet so its frame names match the local tile IDs. + * + * For instance, a tileset tile + * + * ``` + * { id: 3, type: 'treadmill', speed: 4 } + * ``` + * + * with gid 19 and an object + * + * ``` + * { id: 7, gid: 19, speed: 5, rotation: 90 } + * ``` + * + * will be interpreted as + * + * ``` + * { id: 7, gid: 19, speed: 5, rotation: 90, type: 'treadmill', texture: '[the tileset texture]', frame: 3 } + * ``` + * + * You can suppress this behavior by setting the boolean `ignoreTileset` for each `config` that should ignore + * object gid tilesets. + * + * You can set a `container` property in the config. If given, the new Game Object will be added to + * the Container or Layer instance instead of the Scene. + * + * You can set named texture-`key` and texture-`frame` properties, which will be set on the new Game Object. + * + * Finally, you can provide an array of config objects, to convert multiple types of object in + * a single call: + * + * ```javascript + * createFromObjects(layerName, [ + * { + * gid: 26, + * classType: Coin + * }, + * { + * id: 9, + * classType: BossMonster + * }, + * { + * name: 'lava', + * classType: LavaTile + * }, + * { + * type: 'endzone', + * classType: Phaser.GameObjects.Zone + * } + * ]); + * ``` + * + * The signature of this method changed significantly in v3.60.0. Prior to this, it did not take config objects. + * + * @method Phaser.Tilemaps.Tilemap#createFromObjects + * @since 3.0.0 + * + * @param {string} objectLayerName - The name of the Tiled object layer to create the Game Objects from. + * @param {Phaser.Types.Tilemaps.CreateFromObjectLayerConfig|Phaser.Types.Tilemaps.CreateFromObjectLayerConfig[]} config - A CreateFromObjects configuration object, or an array of them. + * @param {boolean} [useTileset=true] - True if objects that set gids should also search the underlying tile for properties and data. + * + * @return {Phaser.GameObjects.GameObject[]} An array containing the Game Objects that were created. Empty if invalid object layer, or no matching id/gid/name was found. + */ + createFromObjects: function (objectLayerName, config, useTileset) + { + if (useTileset === undefined) { useTileset = true; } + + var results = []; + + var objectLayer = this.getObjectLayer(objectLayerName); + + if (!objectLayer) + { + console.warn('createFromObjects: Invalid objectLayerName given: ' + objectLayerName); + + return results; + } + + var objectHelper = new ObjectHelper(useTileset ? this.tilesets : undefined); + + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var objects = objectLayer.objects; + + for (var c = 0; c < config.length; c++) + { + var singleConfig = config[ c ]; + + var id = GetFastValue(singleConfig, 'id', null); + var gid = GetFastValue(singleConfig, 'gid', null); + var name = GetFastValue(singleConfig, 'name', null); + var type = GetFastValue(singleConfig, 'type', null); + objectHelper.enabled = !GetFastValue(singleConfig, 'ignoreTileset', null); + + var obj; + var toConvert = []; + + // Sweep to get all the objects we want to convert in this pass + for (var s = 0; s < objects.length; s++) + { + obj = objects[ s ]; + + if ( + (id === null && gid === null && name === null && type === null) || + (id !== null && obj.id === id) || + (gid !== null && obj.gid === gid) || + (name !== null && obj.name === name) || + (type !== null && objectHelper.getTypeIncludingTile(obj) === type) + ) + { + toConvert.push(obj); + } + } + + // Now let's convert them ... + + var classType = GetFastValue(singleConfig, 'classType', Sprite); + var scene = GetFastValue(singleConfig, 'scene', this.scene); + var container = GetFastValue(singleConfig, 'container', null); + var texture = GetFastValue(singleConfig, 'key', null); + var frame = GetFastValue(singleConfig, 'frame', null); + + for (var i = 0; i < toConvert.length; i++) + { + obj = toConvert[ i ]; + + var sprite = new classType(scene); + + sprite.setName(obj.name); + sprite.setPosition(obj.x, obj.y); + objectHelper.setTextureAndFrame(sprite, texture, frame, obj); + + if (obj.width) + { + sprite.displayWidth = obj.width; + } + + if (obj.height) + { + sprite.displayHeight = obj.height; + } + + if (this.orientation === ORIENTATION.ISOMETRIC) + { + var isometricRatio = this.tileWidth / this.tileHeight; + var isometricPosition = { + x: sprite.x - sprite.y, + y: (sprite.x + sprite.y) / isometricRatio + }; + + sprite.x = isometricPosition.x; + sprite.y = isometricPosition.y; + } + + // Origin is (0, 1) for tile objects or (0, 0) for other objects in Tiled, so find the offset that matches the Sprites origin. + // Do not offset objects with zero dimensions (e.g. points). + var offset = { + x: sprite.originX * obj.width, + y: (sprite.originY - (obj.gid ? 1 : 0)) * obj.height + }; + + // If the object is rotated, then the origin offset also needs to be rotated. + if (obj.rotation) + { + var angle = DegToRad(obj.rotation); + + Rotate(offset, angle); + + sprite.rotation = angle; + } + + sprite.x += offset.x; + sprite.y += offset.y; + + if (obj.flippedHorizontal !== undefined || obj.flippedVertical !== undefined) + { + sprite.setFlip(obj.flippedHorizontal, obj.flippedVertical); + } + + if (!obj.visible) + { + sprite.visible = false; + } + + objectHelper.setPropertiesFromTiledObject(sprite, obj); + + if (container) + { + container.add(sprite); + } + else + { + scene.add.existing(sprite); + } + + results.push(sprite); + } + } + + return results; + }, + + /** + * Creates a Sprite for every tile matching the given tile indexes in the layer. You can + * optionally specify if each tile will be replaced with a new tile after the Sprite has been + * created. Set this value to -1 if you want to just remove the tile after conversion. + * + * This is useful if you want to lay down special tiles in a level that are converted to + * Sprites, but want to replace the tile itself with a floor tile or similar once converted. + * + * The following features were added in Phaser v3.80: + * + * By default, Phaser Sprites have their origin set to 0.5 x 0.5. If you don't specify a new + * origin in the spriteConfig, then it will adjust the sprite positions by half the tile size, + * to position them accurately on the map. + * + * When the Sprite is created it will copy the following properties from the tile: + * + * 'rotation', 'flipX', 'flipY', 'alpha', 'visible' and 'tint'. + * + * The spriteConfig also has a special property called `useSpriteSheet`. If this is set to + * `true` and you have loaded the tileset as a sprite sheet (not an image), then it will + * set the Sprite key and frame to match the sprite texture and tile index. + * + * @method Phaser.Tilemaps.Tilemap#createFromTiles + * @since 3.0.0 + * + * @param {(number|array)} indexes - The tile index, or array of indexes, to create Sprites from. + * @param {?(number|array)} replacements - The tile index, or array of indexes, to change a converted + * tile to. Set to `null` to leave the tiles unchanged. If an array is given, it is assumed to be a + * one-to-one mapping with the indexes array. + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} [spriteConfig] - The config object to pass into the Sprite creator (i.e. scene.make.sprite). + * @param {Phaser.Scene} [scene] - The Scene to create the Sprites within. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.GameObjects.Sprite[]} Returns an array of Tiles, or null if the layer given was invalid. + */ + createFromTiles: function (indexes, replacements, spriteConfig, scene, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.CreateFromTiles(indexes, replacements, spriteConfig, scene, camera, layer); + }, + + /** + * Sets the tiles in the given rectangular area (in tile coordinates) of the layer with the + * specified index. Tiles will be set to collide if the given index is a colliding index. + * Collision information in the region will be recalculated. + * + * If no layer specified, the map's current layer is used. + * This cannot be applied to StaticTilemapLayers. + * + * @method Phaser.Tilemaps.Tilemap#fill + * @since 3.0.0 + * + * @param {number} index - The tile index to fill the area with. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + fill: function (index, tileX, tileY, width, height, recalculateFaces, layer) + { + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.Fill(index, tileX, tileY, width, height, recalculateFaces, layer); + + return this; + }, + + /** + * For each object in the given object layer, run the given filter callback function. Any + * objects that pass the filter test (i.e. where the callback returns true) will be returned in a + * new array. Similar to Array.prototype.Filter in vanilla JS. + * + * @method Phaser.Tilemaps.Tilemap#filterObjects + * @since 3.0.0 + * + * @param {(Phaser.Tilemaps.ObjectLayer|string)} objectLayer - The name of an object layer (from Tiled) or an ObjectLayer instance. + * @param {TilemapFilterCallback} callback - The callback. Each object in the given area will be passed to this callback as the first and only parameter. + * @param {object} [context] - The context under which the callback should be run. + * + * @return {?Phaser.Types.Tilemaps.TiledObject[]} An array of object that match the search, or null if the objectLayer given was invalid. + */ + filterObjects: function (objectLayer, callback, context) + { + if (typeof objectLayer === 'string') + { + var name = objectLayer; + + objectLayer = this.getObjectLayer(objectLayer); + + if (!objectLayer) + { + console.warn('No object layer found with the name: ' + name); + return null; + } + } + + return objectLayer.objects.filter(callback, context); + }, + + /** + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * filter callback function. Any tiles that pass the filter test (i.e. where the callback returns + * true) will returned as a new array. Similar to Array.prototype.Filter in vanilla JS. + * If no layer specified, the map's current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#filterTiles + * @since 3.0.0 + * + * @param {function} callback - The callback. Each tile in the given area will be passed to this + * callback as the first and only parameter. The callback should return true for tiles that pass the + * filter. + * @param {object} [context] - The context under which the callback should be run. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile[]} Returns an array of Tiles, or null if the layer given was invalid. + */ + filterTiles: function (callback, context, tileX, tileY, width, height, filteringOptions, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.FilterTiles(callback, context, tileX, tileY, width, height, filteringOptions, layer); + }, + + /** + * Searches the entire map layer for the first tile matching the given index, then returns that Tile + * object. If no match is found, it returns null. The search starts from the top-left tile and + * continues horizontally until it hits the end of the row, then it drops down to the next column. + * If the reverse boolean is true, it scans starting from the bottom-right corner traveling up to + * the top-left. + * If no layer specified, the map's current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#findByIndex + * @since 3.0.0 + * + * @param {number} index - The tile index value to search for. + * @param {number} [skip=0] - The number of times to skip a matching tile before returning. + * @param {boolean} [reverse=false] - If true it will scan the layer in reverse, starting at the bottom-right. Otherwise it scans from the top-left. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tiles, or null if the layer given was invalid. + */ + findByIndex: function (findIndex, skip, reverse, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.FindByIndex(findIndex, skip, reverse, layer); + }, + + /** + * Find the first object in the given object layer that satisfies the provided testing function. + * I.e. finds the first object for which `callback` returns true. Similar to + * Array.prototype.find in vanilla JS. + * + * @method Phaser.Tilemaps.Tilemap#findObject + * @since 3.0.0 + * + * @param {(Phaser.Tilemaps.ObjectLayer|string)} objectLayer - The name of an object layer (from Tiled) or an ObjectLayer instance. + * @param {TilemapFindCallback} callback - The callback. Each object in the given area will be passed to this callback as the first and only parameter. + * @param {object} [context] - The context under which the callback should be run. + * + * @return {?Phaser.Types.Tilemaps.TiledObject} An object that matches the search, or null if no object found. + */ + findObject: function (objectLayer, callback, context) + { + if (typeof objectLayer === 'string') + { + var name = objectLayer; + + objectLayer = this.getObjectLayer(objectLayer); + + if (!objectLayer) + { + console.warn('No object layer found with the name: ' + name); + return null; + } + } + + return objectLayer.objects.find(callback, context) || null; + }, + + /** + * Find the first tile in the given rectangular area (in tile coordinates) of the layer that + * satisfies the provided testing function. I.e. finds the first tile for which `callback` returns + * true. Similar to Array.prototype.find in vanilla JS. + * If no layer specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#findTile + * @since 3.0.0 + * + * @param {FindTileCallback} callback - The callback. Each tile in the given area will be passed to this callback as the first and only parameter. + * @param {object} [context] - The context under which the callback should be run. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The Tile layer to run the search on. If not provided will use the current layer. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tiles, or null if the layer given was invalid. + */ + findTile: function (callback, context, tileX, tileY, width, height, filteringOptions, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.FindTile(callback, context, tileX, tileY, width, height, filteringOptions, layer); + }, + + /** + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * callback. Similar to Array.prototype.forEach in vanilla JS. + * + * If no layer specified, the map's current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#forEachTile + * @since 3.0.0 + * + * @param {EachTileCallback} callback - The callback. Each tile in the given area will be passed to this callback as the first and only parameter. + * @param {object} [context] - The context under which the callback should be run. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The Tile layer to run the search on. If not provided will use the current layer. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + forEachTile: function (callback, context, tileX, tileY, width, height, filteringOptions, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.ForEachTile(callback, context, tileX, tileY, width, height, filteringOptions, layer); + + return this; + }, + + /** + * Gets the image layer index based on its name. + * + * @method Phaser.Tilemaps.Tilemap#getImageIndex + * @since 3.0.0 + * + * @param {string} name - The name of the image to get. + * + * @return {number} The index of the image in this tilemap, or null if not found. + */ + getImageIndex: function (name) + { + return this.getIndex(this.images, name); + }, + + /** + * Return a list of all valid imagelayer names loaded in this Tilemap. + * + * @method Phaser.Tilemaps.Tilemap#getImageLayerNames + * @since 3.21.0 + * + * @return {string[]} Array of valid imagelayer names / IDs loaded into this Tilemap. + */ + getImageLayerNames: function () + { + if (!this.images || !Array.isArray(this.images)) + { + return []; + } + + return this.images.map(function (image) + { + return image.name; + }); + }, + + /** + * Internally used. Returns the index of the object in one of the Tilemaps arrays whose name + * property matches the given `name`. + * + * @method Phaser.Tilemaps.Tilemap#getIndex + * @since 3.0.0 + * + * @param {array} location - The Tilemap array to search. + * @param {string} name - The name of the array element to get. + * + * @return {number} The index of the element in the array, or null if not found. + */ + getIndex: function (location, name) + { + for (var i = 0; i < location.length; i++) + { + if (location[ i ].name === name) + { + return i; + } + } + + return null; + }, + + /** + * Gets the LayerData from `this.layers` that is associated with the given `layer`, or null if the layer is invalid. + * + * @method Phaser.Tilemaps.Tilemap#getLayer + * @since 3.0.0 + * + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The name of the layer from Tiled, the index of the layer in the map or Tilemap Layer. If not given will default to the maps current layer index. + * + * @return {?Phaser.Tilemaps.LayerData} The corresponding `LayerData` within `this.layers`, or null. + */ + getLayer: function (layer) + { + var index = this.getLayerIndex(layer); + + return (index !== null) ? this.layers[ index ] : null; + }, + + /** + * Gets the ObjectLayer from `this.objects` that has the given `name`, or null if no ObjectLayer is found with that name. + * + * @method Phaser.Tilemaps.Tilemap#getObjectLayer + * @since 3.0.0 + * + * @param {string} [name] - The name of the object layer from Tiled. + * + * @return {?Phaser.Tilemaps.ObjectLayer} The corresponding `ObjectLayer` within `this.objects`, or null. + */ + getObjectLayer: function (name) + { + var index = this.getIndex(this.objects, name); + + return (index !== null) ? this.objects[ index ] : null; + }, + + /** + * Return a list of all valid objectgroup names loaded in this Tilemap. + * + * @method Phaser.Tilemaps.Tilemap#getObjectLayerNames + * @since 3.21.0 + * + * @return {string[]} Array of valid objectgroup names / IDs loaded into this Tilemap. + */ + getObjectLayerNames: function () + { + if (!this.objects || !Array.isArray(this.objects)) + { + return []; + } + + return this.objects.map(function (object) + { + return object.name; + }); + }, + + /** + * Gets the LayerData index of the given `layer` within this.layers, or null if an invalid + * `layer` is given. + * + * @method Phaser.Tilemaps.Tilemap#getLayerIndex + * @since 3.0.0 + * + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The name of the layer from Tiled, the index of the layer in the map or a Tilemap Layer. If not given will default to the map's current layer index. + * + * @return {number} The LayerData index within this.layers. + */ + getLayerIndex: function (layer) + { + if (layer === undefined) + { + return this.currentLayerIndex; + } + else if (typeof layer === 'string') + { + return this.getLayerIndexByName(layer); + } + else if (typeof layer === 'number' && layer < this.layers.length) + { + return layer; + } + else if (layer instanceof TilemapLayerBase && layer.tilemap === this) + { + return layer.layerIndex; + } + else + { + return null; + } + }, + + /** + * Gets the index of the LayerData within this.layers that has the given `name`, or null if an + * invalid `name` is given. + * + * @method Phaser.Tilemaps.Tilemap#getLayerIndexByName + * @since 3.0.0 + * + * @param {string} name - The name of the layer to get. + * + * @return {number} The LayerData index within this.layers. + */ + getLayerIndexByName: function (name) + { + return this.getIndex(this.layers, name); + }, + + /** + * Gets a tile at the given tile coordinates from the given layer. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#getTileAt + * @since 3.0.0 + * + * @param {number} tileX - X position to get the tile from (given in tile units, not pixels). + * @param {number} tileY - Y position to get the tile from (given in tile units, not pixels). + * @param {boolean} [nonNull=false] - For empty tiles, return a Tile object with an index of -1 instead of null. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tile, or null if the layer given was invalid. + */ + getTileAt: function (tileX, tileY, nonNull, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.GetTileAt(tileX, tileY, nonNull, layer); + }, + + /** + * Gets a tile at the given world coordinates from the given layer. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#getTileAtWorldXY + * @since 3.0.0 + * + * @param {number} worldX - X position to get the tile from (given in pixels) + * @param {number} worldY - Y position to get the tile from (given in pixels) + * @param {boolean} [nonNull=false] - For empty tiles, return a Tile object with an index of -1 instead of null. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tile, or null if the layer given was invalid. + */ + getTileAtWorldXY: function (worldX, worldY, nonNull, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.GetTileAtWorldXY(worldX, worldY, nonNull, camera, layer); + }, + + /** + * Return a list of all valid tilelayer names loaded in this Tilemap. + * + * @method Phaser.Tilemaps.Tilemap#getTileLayerNames + * @since 3.21.0 + * + * @return {string[]} Array of valid tilelayer names / IDs loaded into this Tilemap. + */ + getTileLayerNames: function () + { + if (!this.layers || !Array.isArray(this.layers)) + { + return []; + } + + return this.layers.map(function (layer) + { + return layer.name; + }); + }, + + /** + * Gets the tiles in the given rectangular area (in tile coordinates) of the layer. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#getTilesWithin + * @since 3.0.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile[]} Returns an array of Tiles, or null if the layer given was invalid. + */ + getTilesWithin: function (tileX, tileY, width, height, filteringOptions, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer); + }, + + /** + * Gets the tiles that overlap with the given shape in the given layer. The shape must be a Circle, + * Line, Rectangle or Triangle. The shape should be in world coordinates. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#getTilesWithinShape + * @since 3.0.0 + * + * @param {(Phaser.Geom.Circle|Phaser.Geom.Line|Phaser.Geom.Rectangle|Phaser.Geom.Triangle)} shape - A shape in world (pixel) coordinates + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when factoring in which tiles to return. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile[]} Returns an array of Tiles, or null if the layer given was invalid. + */ + getTilesWithinShape: function (shape, filteringOptions, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.GetTilesWithinShape(shape, filteringOptions, camera, layer); + }, + + /** + * Gets the tiles in the given rectangular area (in world coordinates) of the layer. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#getTilesWithinWorldXY + * @since 3.0.0 + * + * @param {number} worldX - The world x coordinate for the top-left of the area. + * @param {number} worldY - The world y coordinate for the top-left of the area. + * @param {number} width - The width of the area. + * @param {number} height - The height of the area. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when factoring in which tiles to return. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile[]} Returns an array of Tiles, or null if the layer given was invalid. + */ + getTilesWithinWorldXY: function (worldX, worldY, width, height, filteringOptions, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.GetTilesWithinWorldXY(worldX, worldY, width, height, filteringOptions, camera, layer); + }, + + /** + * Gets the Tileset that has the given `name`, or null if an invalid `name` is given. + * + * @method Phaser.Tilemaps.Tilemap#getTileset + * @since 3.14.0 + * + * @param {string} name - The name of the Tileset to get. + * + * @return {?Phaser.Tilemaps.Tileset} The Tileset, or `null` if no matching named tileset was found. + */ + getTileset: function (name) + { + var index = this.getIndex(this.tilesets, name); + + return (index !== null) ? this.tilesets[ index ] : null; + }, + + /** + * Gets the index of the Tileset within this.tilesets that has the given `name`, or null if an + * invalid `name` is given. + * + * @method Phaser.Tilemaps.Tilemap#getTilesetIndex + * @since 3.0.0 + * + * @param {string} name - The name of the Tileset to get. + * + * @return {number} The Tileset index within this.tilesets. + */ + getTilesetIndex: function (name) + { + return this.getIndex(this.tilesets, name); + }, + + /** + * Checks if there is a tile at the given location (in tile coordinates) in the given layer. Returns + * false if there is no tile or if the tile at that location has an index of -1. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#hasTileAt + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?boolean} Returns a boolean, or null if the layer given was invalid. + */ + hasTileAt: function (tileX, tileY, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.HasTileAt(tileX, tileY, layer); + }, + + /** + * Checks if there is a tile at the given location (in world coordinates) in the given layer. Returns + * false if there is no tile or if the tile at that location has an index of -1. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#hasTileAtWorldXY + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when factoring in which tiles to return. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?boolean} Returns a boolean, or null if the layer given was invalid. + */ + hasTileAtWorldXY: function (worldX, worldY, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.HasTileAtWorldXY(worldX, worldY, camera, layer); + }, + + /** + * The LayerData object that is currently selected in the map. You can set this property using + * any type supported by setLayer. + * + * @name Phaser.Tilemaps.Tilemap#layer + * @type {Phaser.Tilemaps.LayerData} + * @since 3.0.0 + */ + layer: { + get: function () + { + return this.layers[ this.currentLayerIndex ]; + }, + + set: function (layer) + { + this.setLayer(layer); + } + }, + + /** + * Puts a tile at the given tile coordinates in the specified layer. You can pass in either an index + * or a Tile object. If you pass in a Tile, all attributes will be copied over to the specified + * location. If you pass in an index, only the index at the specified location will be changed. + * Collision information will be recalculated at the specified location. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#putTileAt + * @since 3.0.0 + * + * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object. + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} [recalculateFaces] - `true` if the faces data should be recalculated. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tile, or null if the layer given was invalid or the coordinates were out of bounds. + */ + putTileAt: function (tile, tileX, tileY, recalculateFaces, layer) + { + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.PutTileAt(tile, tileX, tileY, recalculateFaces, layer); + }, + + /** + * Puts a tile at the given world coordinates (pixels) in the specified layer. You can pass in either + * an index or a Tile object. If you pass in a Tile, all attributes will be copied over to the + * specified location. If you pass in an index, only the index at the specified location will be + * changed. Collision information will be recalculated at the specified location. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#putTileAtWorldXY + * @since 3.0.0 + * + * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object. + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {boolean} [recalculateFaces] - `true` if the faces data should be recalculated. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tile, or null if the layer given was invalid. + */ + putTileAtWorldXY: function (tile, worldX, worldY, recalculateFaces, camera, layer) + { + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.PutTileAtWorldXY(tile, worldX, worldY, recalculateFaces, camera, layer); + }, + + /** + * Puts an array of tiles or a 2D array of tiles at the given tile coordinates in the specified + * layer. The array can be composed of either tile indexes or Tile objects. If you pass in a Tile, + * all attributes will be copied over to the specified location. If you pass in an index, only the + * index at the specified location will be changed. Collision information will be recalculated + * within the region tiles were changed. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#putTilesAt + * @since 3.0.0 + * + * @param {(number[]|number[][]|Phaser.Tilemaps.Tile[]|Phaser.Tilemaps.Tile[][])} tile - A row (array) or grid (2D array) of Tiles or tile indexes to place. + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} [recalculateFaces] - `true` if the faces data should be recalculated. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + putTilesAt: function (tilesArray, tileX, tileY, recalculateFaces, layer) + { + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.PutTilesAt(tilesArray, tileX, tileY, recalculateFaces, layer); + + return this; + }, + + /** + * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the + * specified layer. Each tile will receive a new index. If an array of indexes is passed in, then + * those will be used for randomly assigning new tile indexes. If an array is not provided, the + * indexes found within the region (excluding -1) will be used for randomly assigning new tile + * indexes. This method only modifies tile indexes and does not change collision information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#randomize + * @since 3.0.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {number[]} [indexes] - An array of indexes to randomly draw from during randomization. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + randomize: function (tileX, tileY, width, height, indexes, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.Randomize(tileX, tileY, width, height, indexes, layer); + + return this; + }, + + /** + * Calculates interesting faces at the given tile coordinates of the specified layer. Interesting + * faces are used internally for optimizing collisions against tiles. This method is mostly used + * internally to optimize recalculating faces when only one tile has been changed. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#calculateFacesAt + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + calculateFacesAt: function (tileX, tileY, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.CalculateFacesAt(tileX, tileY, layer); + + return this; + }, + + /** + * Calculates interesting faces within the rectangular area specified (in tile coordinates) of the + * layer. Interesting faces are used internally for optimizing collisions against tiles. This method + * is mostly used internally. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#calculateFacesWithin + * @since 3.0.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + calculateFacesWithin: function (tileX, tileY, width, height, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.CalculateFacesWithin(tileX, tileY, width, height, layer); + + return this; + }, + + /** + * Removes the given TilemapLayer from this Tilemap without destroying it. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#removeLayer + * @since 3.17.0 + * + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to be removed. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + removeLayer: function (layer) + { + var index = this.getLayerIndex(layer); + + if (index !== null) + { + SpliceOne(this.layers, index); + + for (var i = index; i < this.layers.length; i++) + { + if (this.layers[ i ].tilemapLayer) + { + this.layers[ i ].tilemapLayer.layerIndex--; + } + } + + if (this.currentLayerIndex === index) + { + this.currentLayerIndex = 0; + } + + return this; + } + else + { + return null; + } + }, + + /** + * Destroys the given TilemapLayer and removes it from this Tilemap. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#destroyLayer + * @since 3.17.0 + * + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to be destroyed. + * + * @return {?Phaser.Tilemaps.Tilemap} Returns this, or null if the layer given was invalid. + */ + destroyLayer: function (layer) + { + var index = this.getLayerIndex(layer); + + if (index !== null) + { + layer = this.layers[ index ]; + + layer.tilemapLayer.destroy(); + + SpliceOne(this.layers, index); + + if (this.currentLayerIndex === index) + { + this.currentLayerIndex = 0; + } + + return this; + } + else + { + return null; + } + }, + + /** + * Removes all Tilemap Layers from this Tilemap and calls `destroy` on each of them. + * + * @method Phaser.Tilemaps.Tilemap#removeAllLayers + * @since 3.0.0 + * + * @return {this} This Tilemap object. + */ + removeAllLayers: function () + { + var layers = this.layers; + + for (var i = 0; i < layers.length; i++) + { + if (layers[ i ].tilemapLayer) + { + layers[ i ].tilemapLayer.destroy(false); + } + } + + layers.length = 0; + + this.currentLayerIndex = 0; + + return this; + }, + + /** + * Removes the given Tile, or an array of Tiles, from the layer to which they belong, + * and optionally recalculates the collision information. + * + * @method Phaser.Tilemaps.Tilemap#removeTile + * @since 3.17.0 + * + * @param {(Phaser.Tilemaps.Tile|Phaser.Tilemaps.Tile[])} tiles - The Tile to remove, or an array of Tiles. + * @param {number} [replaceIndex=-1] - After removing the Tile, insert a brand new Tile into its location with the given index. Leave as -1 to just remove the tile. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * + * @return {Phaser.Tilemaps.Tile[]} Returns an array of Tiles that were removed. + */ + removeTile: function (tiles, replaceIndex, recalculateFaces) + { + if (replaceIndex === undefined) { replaceIndex = -1; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + var removed = []; + + if (!Array.isArray(tiles)) + { + tiles = [ tiles ]; + } + + for (var i = 0; i < tiles.length; i++) + { + var tile = tiles[ i ]; + + removed.push(this.removeTileAt(tile.x, tile.y, true, recalculateFaces, tile.tilemapLayer)); + + if (replaceIndex > -1) + { + this.putTileAt(replaceIndex, tile.x, tile.y, recalculateFaces, tile.tilemapLayer); + } + } + + return removed; + }, + + /** + * Removes the tile at the given tile coordinates in the specified layer and updates the layers collision information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#removeTileAt + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} [replaceWithNull] - If `true` (the default), this will replace the tile at the specified location with null instead of a Tile with an index of -1. + * @param {boolean} [recalculateFaces] - If `true` (the default), the faces data will be recalculated. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns the Tile that was removed, or null if the layer given was invalid. + */ + removeTileAt: function (tileX, tileY, replaceWithNull, recalculateFaces, layer) + { + if (replaceWithNull === undefined) { replaceWithNull = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.RemoveTileAt(tileX, tileY, replaceWithNull, recalculateFaces, layer); + }, + + /** + * Removes the tile at the given world coordinates in the specified layer and updates the layers collision information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#removeTileAtWorldXY + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {boolean} [replaceWithNull] - If `true` (the default), this will replace the tile at the specified location with null instead of a Tile with an index of -1. + * @param {boolean} [recalculateFaces] - If `true` (the default), the faces data will be recalculated. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tile} Returns a Tile, or null if the layer given was invalid. + */ + removeTileAtWorldXY: function (worldX, worldY, replaceWithNull, recalculateFaces, camera, layer) + { + if (replaceWithNull === undefined) { replaceWithNull = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return TilemapComponents.RemoveTileAtWorldXY(worldX, worldY, replaceWithNull, recalculateFaces, camera, layer); + }, + + /** + * Draws a debug representation of the layer to the given Graphics object. This is helpful when you want to + * get a quick idea of which of your tiles are colliding and which have interesting faces. The tiles + * are drawn starting at (0, 0) in the Graphics, allowing you to place the debug representation + * wherever you want on the screen. + * + * If no layer is specified, the maps current layer is used. + * + * **Note:** This method currently only works with orthogonal tilemap layers. + * + * @method Phaser.Tilemaps.Tilemap#renderDebug + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Graphics} graphics - The target Graphics object to draw upon. + * @param {Phaser.Types.Tilemaps.StyleConfig} [styleConfig] - An object specifying the colors to use for the debug drawing. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + renderDebug: function (graphics, styleConfig, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + if (this.orientation === ORIENTATION.ORTHOGONAL) + { + TilemapComponents.RenderDebug(graphics, styleConfig, layer); + } + + return this; + }, + + /** + * Draws a debug representation of all layers within this Tilemap to the given Graphics object. + * + * This is helpful when you want to get a quick idea of which of your tiles are colliding and which + * have interesting faces. The tiles are drawn starting at (0, 0) in the Graphics, allowing you to + * place the debug representation wherever you want on the screen. + * + * @method Phaser.Tilemaps.Tilemap#renderDebugFull + * @since 3.17.0 + * + * @param {Phaser.GameObjects.Graphics} graphics - The target Graphics object to draw upon. + * @param {Phaser.Types.Tilemaps.StyleConfig} [styleConfig] - An object specifying the colors to use for the debug drawing. + * + * @return {this} This Tilemap instance. + */ + renderDebugFull: function (graphics, styleConfig) + { + var layers = this.layers; + + for (var i = 0; i < layers.length; i++) + { + TilemapComponents.RenderDebug(graphics, styleConfig, layers[ i ]); + } + + return this; + }, + + /** + * Scans the given rectangular area (given in tile coordinates) for tiles with an index matching + * `findIndex` and updates their index to match `newIndex`. This only modifies the index and does + * not change collision information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#replaceByIndex + * @since 3.0.0 + * + * @param {number} findIndex - The index of the tile to search for. + * @param {number} newIndex - The index of the tile to replace it with. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + replaceByIndex: function (findIndex, newIndex, tileX, tileY, width, height, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.ReplaceByIndex(findIndex, newIndex, tileX, tileY, width, height, layer); + + return this; + }, + + /** + * Sets collision on the given tile or tiles within a layer by index. You can pass in either a + * single numeric index or an array of indexes: [2, 3, 15, 20]. The `collides` parameter controls if + * collision will be enabled (true) or disabled (false). + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setCollision + * @since 3.0.0 + * + * @param {(number|array)} indexes - Either a single tile index, or an array of tile indexes. + * @param {boolean} [collides] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces] - Whether or not to recalculate the tile faces after the update. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to false if no tiles have been placed for significant performance boost. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setCollision: function (indexes, collides, recalculateFaces, layer, updateLayer) + { + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + if (updateLayer === undefined) { updateLayer = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetCollision(indexes, collides, recalculateFaces, layer, updateLayer); + + return this; + }, + + /** + * Sets collision on a range of tiles in a layer whose index is between the specified `start` and + * `stop` (inclusive). Calling this with a start value of 10 and a stop value of 14 would set + * collision for tiles 10, 11, 12, 13 and 14. The `collides` parameter controls if collision will be + * enabled (true) or disabled (false). + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setCollisionBetween + * @since 3.0.0 + * + * @param {number} start - The first index of the tile to be set for collision. + * @param {number} stop - The last index of the tile to be set for collision. + * @param {boolean} [collides] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces] - Whether or not to recalculate the tile faces after the update. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setCollisionBetween: function (start, stop, collides, recalculateFaces, layer) + { + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetCollisionBetween(start, stop, collides, recalculateFaces, layer); + + return this; + }, + + /** + * Sets collision on the tiles within a layer by checking tile properties. If a tile has a property + * that matches the given properties object, its collision flag will be set. The `collides` + * parameter controls if collision will be enabled (true) or disabled (false). Passing in + * `{ collides: true }` would update the collision flag on any tiles with a "collides" property that + * has a value of true. Any tile that doesn't have "collides" set to true will be ignored. You can + * also use an array of values, e.g. `{ types: ["stone", "lava", "sand" ] }`. If a tile has a + * "types" property that matches any of those values, its collision flag will be updated. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setCollisionByProperty + * @since 3.0.0 + * + * @param {object} properties - An object with tile properties and corresponding values that should be checked. + * @param {boolean} [collides] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces] - Whether or not to recalculate the tile faces after the update. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setCollisionByProperty: function (properties, collides, recalculateFaces, layer) + { + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetCollisionByProperty(properties, collides, recalculateFaces, layer); + + return this; + }, + + /** + * Sets collision on all tiles in the given layer, except for tiles that have an index specified in + * the given array. The `collides` parameter controls if collision will be enabled (true) or + * disabled (false). Tile indexes not currently in the layer are not affected. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setCollisionByExclusion + * @since 3.0.0 + * + * @param {number[]} indexes - An array of the tile indexes to not be counted for collision. + * @param {boolean} [collides] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces] - Whether or not to recalculate the tile faces after the update. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setCollisionByExclusion: function (indexes, collides, recalculateFaces, layer) + { + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetCollisionByExclusion(indexes, collides, recalculateFaces, layer); + + return this; + }, + + /** + * Sets collision on the tiles within a layer by checking each tiles collision group data + * (typically defined in Tiled within the tileset collision editor). If any objects are found within + * a tiles collision group, the tiles colliding information will be set. The `collides` parameter + * controls if collision will be enabled (true) or disabled (false). + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setCollisionFromCollisionGroup + * @since 3.0.0 + * + * @param {boolean} [collides] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces] - Whether or not to recalculate the tile faces after the update. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setCollisionFromCollisionGroup: function (collides, recalculateFaces, layer) + { + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetCollisionFromCollisionGroup(collides, recalculateFaces, layer); + + return this; + }, + + /** + * Sets a global collision callback for the given tile index within the layer. This will affect all + * tiles on this layer that have the same index. If a callback is already set for the tile index it + * will be replaced. Set the callback to null to remove it. If you want to set a callback for a tile + * at a specific location on the map then see `setTileLocationCallback`. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setTileIndexCallback + * @since 3.0.0 + * + * @param {(number|number[])} indexes - Either a single tile index, or an array of tile indexes to have a collision callback set for. All values should be integers. + * @param {function} callback - The callback that will be invoked when the tile is collided with. + * @param {object} callbackContext - The context under which the callback is called. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setTileIndexCallback: function (indexes, callback, callbackContext, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetTileIndexCallback(indexes, callback, callbackContext, layer); + + return this; + }, + + /** + * Sets a collision callback for the given rectangular area (in tile coordinates) within the layer. + * If a callback is already set for the tile index it will be replaced. Set the callback to null to + * remove it. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#setTileLocationCallback + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {function} callback - The callback that will be invoked when the tile is collided with. + * @param {object} [callbackContext] - The context under which the callback is called. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + setTileLocationCallback: function (tileX, tileY, width, height, callback, callbackContext, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SetTileLocationCallback(tileX, tileY, width, height, callback, callbackContext, layer); + + return this; + }, + + /** + * Sets the current layer to the LayerData associated with `layer`. + * + * @method Phaser.Tilemaps.Tilemap#setLayer + * @since 3.0.0 + * + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The name of the layer from Tiled, the index of the layer in the map or a TilemapLayer. If not given will default to the maps current layer index. + * + * @return {this} This Tilemap object. + */ + setLayer: function (layer) + { + var index = this.getLayerIndex(layer); + + if (index !== null) + { + this.currentLayerIndex = index; + } + + return this; + }, + + /** + * Sets the base tile size for the map. Note: this does not necessarily match the tileWidth and + * tileHeight for all layers. This also updates the base size on all tiles across all layers. + * + * @method Phaser.Tilemaps.Tilemap#setBaseTileSize + * @since 3.0.0 + * + * @param {number} tileWidth - The width of the tiles the map uses for calculations. + * @param {number} tileHeight - The height of the tiles the map uses for calculations. + * + * @return {this} This Tilemap object. + */ + setBaseTileSize: function (tileWidth, tileHeight) + { + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.widthInPixels = this.width * tileWidth; + this.heightInPixels = this.height * tileHeight; + + // Update the base tile size on all layers & tiles + for (var i = 0; i < this.layers.length; i++) + { + this.layers[ i ].baseTileWidth = tileWidth; + this.layers[ i ].baseTileHeight = tileHeight; + + var mapData = this.layers[ i ].data; + var mapWidth = this.layers[ i ].width; + var mapHeight = this.layers[ i ].height; + + for (var row = 0; row < mapHeight; row++) + { + for (var col = 0; col < mapWidth; col++) + { + var tile = mapData[ row ][ col ]; + + if (tile !== null) + { + tile.setSize(undefined, undefined, tileWidth, tileHeight); + } + } + } + } + + return this; + }, + + /** + * Sets the tile size for a specific `layer`. Note: this does not necessarily match the maps + * tileWidth and tileHeight for all layers. This will set the tile size for the layer and any + * tiles the layer has. + * + * @method Phaser.Tilemaps.Tilemap#setLayerTileSize + * @since 3.0.0 + * + * @param {number} tileWidth - The width of the tiles (in pixels) in the layer. + * @param {number} tileHeight - The height of the tiles (in pixels) in the layer. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The name of the layer from Tiled, the index of the layer in the map or a TilemapLayer. If not given will default to the maps current layer index. + * + * @return {this} This Tilemap object. + */ + setLayerTileSize: function (tileWidth, tileHeight, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return this; } + + layer.tileWidth = tileWidth; + layer.tileHeight = tileHeight; + + var mapData = layer.data; + var mapWidth = layer.width; + var mapHeight = layer.height; + + for (var row = 0; row < mapHeight; row++) + { + for (var col = 0; col < mapWidth; col++) + { + var tile = mapData[ row ][ col ]; + + if (tile !== null) + { + tile.setSize(tileWidth, tileHeight); + } + } + } + + return this; + }, + + /** + * Shuffles the tiles in a rectangular region (specified in tile coordinates) within the given + * layer. It will only randomize the tiles in that area, so if they're all the same nothing will + * appear to have changed! This method only modifies tile indexes and does not change collision + * information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#shuffle + * @since 3.0.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + shuffle: function (tileX, tileY, width, height, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.Shuffle(tileX, tileY, width, height, layer); + + return this; + }, + + /** + * Scans the given rectangular area (given in tile coordinates) for tiles with an index matching + * `indexA` and swaps then with `indexB`. This only modifies the index and does not change collision + * information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#swapByIndex + * @since 3.0.0 + * + * @param {number} tileA - First tile index. + * @param {number} tileB - Second tile index. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + swapByIndex: function (indexA, indexB, tileX, tileY, width, height, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.SwapByIndex(indexA, indexB, tileX, tileY, width, height, layer); + + return this; + }, + + /** + * Converts from tile X coordinates (tile units) to world X coordinates (pixels), factoring in the + * layers position, scale and scroll. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#tileToWorldX + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?number} Returns a number, or null if the layer given was invalid. + */ + tileToWorldX: function (tileX, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.TileToWorldX(tileX, camera, layer); + }, + + /** + * Converts from tile Y coordinates (tile units) to world Y coordinates (pixels), factoring in the + * layers position, scale and scroll. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#tileToWorldY + * @since 3.0.0 + * + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?number} Returns a number, or null if the layer given was invalid. + */ + tileToWorldY: function (tileY, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.TileToWorldY(tileY, camera, layer); + }, + + /** + * Converts from tile XY coordinates (tile units) to world XY coordinates (pixels), factoring in the + * layers position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#tileToWorldXY + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Math.Vector2} [vec2] - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Math.Vector2} Returns a Vector2, or null if the layer given was invalid. + */ + tileToWorldXY: function (tileX, tileY, vec2, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.TileToWorldXY(tileX, tileY, vec2, camera, layer); + }, + + /** + * Returns an array of Vector2s where each entry corresponds to the corner of the requested tile. + * + * The `tileX` and `tileY` parameters are in tile coordinates, not world coordinates. + * + * The corner coordinates are in world space, having factored in TilemapLayer scale, position + * and the camera, if given. + * + * The size of the array will vary based on the orientation of the map. For example an + * orthographic map will return an array of 4 vectors, where-as a hexagonal map will, + * of course, return an array of 6 corner vectors. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#getTileCorners + * @since 3.60.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Math.Vector2[]} Returns an array of Vector2s, or null if the layer given was invalid. + */ + getTileCorners: function (tileX, tileY, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.GetTileCorners(tileX, tileY, camera, layer); + }, + + /** + * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the + * specified layer. Each tile will receive a new index. New indexes are drawn from the given + * weightedIndexes array. An example weighted array: + * + * [ + * { index: 6, weight: 4 }, // Probability of index 6 is 4 / 8 + * { index: 7, weight: 2 }, // Probability of index 7 would be 2 / 8 + * { index: 8, weight: 1.5 }, // Probability of index 8 would be 1.5 / 8 + * { index: 26, weight: 0.5 } // Probability of index 27 would be 0.5 / 8 + * ] + * + * The probability of any index being picked is (the indexs weight) / (sum of all weights). This + * method only modifies tile indexes and does not change collision information. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#weightedRandomize + * @since 3.0.0 + * + * @param {object[]} weightedIndexes - An array of objects to randomly draw from during randomization. They should be in the form: { index: 0, weight: 4 } or { index: [0, 1], weight: 4 } if you wish to draw from multiple tile indexes. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Tilemaps.Tilemap} Return this Tilemap object, or null if the layer given was invalid. + */ + weightedRandomize: function (weightedIndexes, tileX, tileY, width, height, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + TilemapComponents.WeightedRandomize(tileX, tileY, width, height, weightedIndexes, layer); + + return this; + }, + + /** + * Converts from world X coordinates (pixels) to tile X coordinates (tile units), factoring in the + * layers position, scale and scroll. + * + * If no layer is specified, the maps current layer is used. + * + * You cannot call this method for Isometric or Hexagonal tilemaps as they require + * both `worldX` and `worldY` values to determine the correct tile, instead you + * should use the `worldToTileXY` method. + * + * @method Phaser.Tilemaps.Tilemap#worldToTileX + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {boolean} [snapToFloor] - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?number} Returns a number, or null if the layer given was invalid. + */ + worldToTileX: function (worldX, snapToFloor, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.WorldToTileX(worldX, snapToFloor, camera, layer); + }, + + /** + * Converts from world Y coordinates (pixels) to tile Y coordinates (tile units), factoring in the + * layers position, scale and scroll. + * + * If no layer is specified, the maps current layer is used. + * + * You cannot call this method for Isometric or Hexagonal tilemaps as they require + * both `worldX` and `worldY` values to determine the correct tile, instead you + * should use the `worldToTileXY` method. + * + * @method Phaser.Tilemaps.Tilemap#worldToTileY + * @since 3.0.0 + * + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} [snapToFloor] - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?number} Returns a number, or null if the layer given was invalid. + */ + worldToTileY: function (worldY, snapToFloor, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.WorldToTileY(worldY, snapToFloor, camera, layer); + }, + + /** + * Converts from world XY coordinates (pixels) to tile XY coordinates (tile units), factoring in the + * layers position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * If no layer is specified, the maps current layer is used. + * + * @method Phaser.Tilemaps.Tilemap#worldToTileXY + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} [snapToFloor] - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Math.Vector2} [vec2] - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * @param {(string|number|Phaser.Tilemaps.TilemapLayer)} [layer] - The tile layer to use. If not given the current layer is used. + * + * @return {?Phaser.Math.Vector2} Returns a vec2, or null if the layer given was invalid. + */ + worldToTileXY: function (worldX, worldY, snapToFloor, vec2, camera, layer) + { + layer = this.getLayer(layer); + + if (layer === null) { return null; } + + return this._convert.WorldToTileXY(worldX, worldY, snapToFloor, vec2, camera, layer); + }, + + /** + * Removes all layer data from this Tilemap and nulls the scene reference. This will destroy any + * TilemapLayers that have been created. + * + * @method Phaser.Tilemaps.Tilemap#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.removeAllLayers(); + + this.tiles.length = 0; + this.tilesets.length = 0; + this.objects.length = 0; + + this.scene = null; + } + +}); + +module.exports = Tilemap; + + +/***/ }), + +/***/ 45939: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectCreator = __webpack_require__(44603); +var ParseToTilemap = __webpack_require__(31989); + +/** + * Creates a Tilemap from the given key or data, or creates a blank Tilemap if no key/data provided. + * When loading from CSV or a 2D array, you should specify the tileWidth & tileHeight. When parsing + * from a map from Tiled, the tileWidth, tileHeight, width & height will be pulled from the map + * data. For an empty map, you should specify tileWidth, tileHeight, width & height. + * + * @method Phaser.GameObjects.GameObjectCreator#tilemap + * @since 3.0.0 + * + * @param {Phaser.Types.Tilemaps.TilemapConfig} [config] - The config options for the Tilemap. + * + * @return {Phaser.Tilemaps.Tilemap} + */ +GameObjectCreator.register('tilemap', function (config) +{ + // Defaults are applied in ParseToTilemap + var c = (config !== undefined) ? config : {}; + + return ParseToTilemap( + this.scene, + c.key, + c.tileWidth, + c.tileHeight, + c.width, + c.height, + c.data, + c.insertNull + ); +}); + + +/***/ }), + +/***/ 46029: +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GameObjectFactory = __webpack_require__(39429); +var ParseToTilemap = __webpack_require__(31989); + +/** + * Creates a Tilemap from the given key or data, or creates a blank Tilemap if no key/data provided. + * When loading from CSV or a 2D array, you should specify the tileWidth & tileHeight. When parsing + * from a map from Tiled, the tileWidth, tileHeight, width & height will be pulled from the map + * data. For an empty map, you should specify tileWidth, tileHeight, width & height. + * + * @method Phaser.GameObjects.GameObjectFactory#tilemap + * @since 3.0.0 + * + * @param {string} [key] - The key in the Phaser cache that corresponds to the loaded tilemap data. + * @param {number} [tileWidth=32] - The width of a tile in pixels. Pass in `null` to leave as the + * default. + * @param {number} [tileHeight=32] - The height of a tile in pixels. Pass in `null` to leave as the + * default. + * @param {number} [width=10] - The width of the map in tiles. Pass in `null` to leave as the + * default. + * @param {number} [height=10] - The height of the map in tiles. Pass in `null` to leave as the + * default. + * @param {number[][]} [data] - Instead of loading from the cache, you can also load directly from + * a 2D array of tile indexes. Pass in `null` for no data. + * @param {boolean} [insertNull=false] - Controls how empty tiles, tiles with an index of -1, in the + * map data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {Phaser.Tilemaps.Tilemap} + */ +GameObjectFactory.register('tilemap', function (key, tileWidth, tileHeight, width, height, data, insertNull) +{ + // Allow users to specify null to indicate that they want the default value, since null is + // shorter & more legible than undefined. Convert null to undefined to allow ParseToTilemap + // defaults to take effect. + + if (key === null) { key = undefined; } + if (tileWidth === null) { tileWidth = undefined; } + if (tileHeight === null) { tileHeight = undefined; } + if (width === null) { width = undefined; } + if (height === null) { height = undefined; } + + return ParseToTilemap(this.scene, key, tileWidth, tileHeight, width, height, data, insertNull); +}); + +// When registering a factory function 'this' refers to the GameObjectFactory context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory +// this.displayList - a reference to the Display List the Scene owns +// this.updateList - a reference to the Update List the Scene owns + + +/***/ }), + +/***/ 53180: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultTilemapGPULayerNodes = __webpack_require__(67743); +var Class = __webpack_require__(83419); +var TilemapLayerBase = __webpack_require__(44731); +var TilemapGPULayerRender = __webpack_require__(57912); + +/** + * @classdesc + * A TilemapGPULayer is a special kind of Game Object that renders LayerData from a Tilemap. + * Unlike the more flexible TilemapLayer, this object uses a single Tileset + * and is optimized for speed and quality over flexibility. + * Use it for high-performance rendering of tilemaps which don't update + * their contents. It still supports tile animation and flip. + * + * Performance of this layer can be highly variable. + * It is almost entirely GPU-bound, so it will free up CPU resources + * for other game code (the CPU usually does much more work than the GPU in games). + * It has a fixed cost per pixel on screen, whether there is anything in that + * tile or not. + * In general, it suffers no performance loss when many tiles are visible, + * which can make it superior to TilemapLayer. + * However, while it can be many times faster on desktop devices, + * mobile devices may struggle due to fillrate and texture sampling issues. + * You may want to check `game.device.os.desktop`, + * and review whether you want to improve CPU performance, + * before deciding to use this layer. + * + * Create a TilemapGPULayer by adding the `gpu` flag to a call to + * `Tilemap.createLayer()`. This will return a TilemapGPULayer instance. + * + * This layer has the following abilities and restrictions: + * + * - Use a single tileset, with a single texture image. + * - Maximum tilemap size of 4096x4096 tiles. + * - Maximum of 2^23 (8388608) unique tile IDs. + * - Tiles may be flipped. + * - Tiles may be animated. + * - Animation data limit of 8388608 entries (each animation or each frame of animation uses one entry). + * - Orthographic tilemaps only. + * + * The layer renders via a special shader. + * This uses a texture containing the layer tile data, and a second texture + * containing any tile animations. The shader then renders the tiles + * as a single quad. Because it doesn't have to compute individual tiles + * on the CPU, this is much faster than a TilemapLayer. + * However, because it treats tiles as a single orthographic grid, + * it is not suitable for use with isometric or hexagonal tilemaps, + * or other types of tilemap that require different rendering methods. + * + * If the tileset image uses NEAREST minfiltering, the shader will render + * sharp edged pixels. Otherwise, it assumes LINEAR filtering. + * The shader will automatically render smooth borders between tiles + * in LINEAR mode, with no seams or bleeding, for perfect results. + * A regular TilemapLayer cannot render smooth borders like this, + * creating sharp seams between tiles. + * + * The layer can be edited, but it will not update automatically. + * Regenerate the layer tile data texture by calling `generateLayerDataTexture`. + * + * @class TilemapGPULayer + * @extends Phaser.Tilemaps.TilemapLayerBase + * @memberof Phaser.Tilemaps + * @constructor + * @since 4.0.0 + * + * @param {Phaser.Scene} scene - The Scene to which this TilemapGPULayer belongs. + * @param {Phaser.Tilemaps.Tilemap} tilemap - The Tilemap this layer is a part of. + * @param {number} layerIndex - The index of the LayerData associated with this layer. + * @param {(string|Phaser.Tilemaps.Tileset)} tileset - The tileset used to render the tiles in this layer. Can be a string or a Tileset object. + * @param {number} [x] - The world x position where the top left of this layer will be placed. + * @param {number} [y] - The world y position where the top left of this layer will be placed. + */ +var TilemapGPULayer = new Class({ + Extends: TilemapLayerBase, + + Mixins: [ + TilemapGPULayerRender + ], + + initialize: function TilemapGPULayer (scene, tilemap, layerIndex, tileset, x, y) + { + TilemapLayerBase.call(this, 'TilemapGPULayer', scene, tilemap, layerIndex, x, y); + + /** + * The `Tileset` associated with this layer. + * + * Unlike a `TilemapLayer`, this object can only have one tileset, + * because the renderer is optimized for a single texture. + * + * @name Phaser.Tilemaps.TilemapGPULayer#tileset + * @type {Phaser.Tilemaps.Tileset} + * @since 3.50.0 + */ + this.tileset = null; + + /** + * A texture containing the tile data for this game object. + * Each texel describes a single tile in the layer. + * + * Each texel is stored as a 32-bit value, encoded thus: + * + * - 1 bit: Horizontal flip flag. + * - 1 bit: Vertical flip flag. + * - 1 bit: Animation flag. + * - 1 bit: Unused. + * - 28 bits: Tile index. + * + * @name Phaser.Tilemaps.TilemapGPULayer#layerDataTexture + * @type {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @since 4.0.0 + */ + this.layerDataTexture = null; + + this.setTileset(tileset); + + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.Tilemaps.TilemapGPULayer#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultTilemapGPULayerNodes; + } + }, + + /** + * Populates data structures to render this tilemap layer. + * + * @method Phaser.Tilemaps.TilemapGPULayer#setTileset + * @private + * @since 4.0.0 + * + * @param {(string|Phaser.Tilemaps.Tileset)} tileset - The tileset used to render this layer. Can be a string or a Tileset object. + */ + setTileset: function (tileset) + { + if (typeof tileset === 'string') + { + tileset = this.tilemap.getTileset(tileset); + } + + this.tileset = tileset; + + // Convert layer into a data texture. + this.generateLayerDataTexture(); + }, + + /** + * Generate the data textures for this game object. + * This method is called internally by `setTileset`. + * + * @method Phaser.Tilemaps.TilemapGPULayer#generateLayerDataTexture + * @since 4.0.0 + */ + generateLayerDataTexture: function () + { + var layer = this.layer; + var tileset = this.tileset; + var firstgid = tileset.firstgid; + var renderer = this.scene.renderer; + + // Get or initialize the animation data texture in the Tileset. + var indexToAnimMap = tileset.getAnimationDataIndexMap(renderer); + + // Generate the layer map. + var u32 = new Uint32Array(layer.width * layer.height); + for (var y = 0; y < layer.height; y++) + { + for (var x = 0; x < layer.width; x++) + { + var tile = layer.data[y][x]; + + var index = tile.index - firstgid; + + var flipX = tile.flipX; + var flipY = tile.flipY; + var animated = false; + + if (indexToAnimMap.has(index)) + { + // This tile is part of an animation. + index = indexToAnimMap.get(index); + animated = true; + } + + // Set flip flags. + if (flipX) + { + index |= 0x80000000; + } + if (flipY) + { + index |= 0x40000000; + } + if (animated) + { + index |= 0x20000000; + } + if (tile.index === -1) + { + // Set the fourth bit to 1 to indicate an empty tile. + index = 0x10000000; + } + + u32[y * layer.width + x] = index; + } + } + + // Create or update the tile data texture. + if (this.layerDataTexture) + { + this.layerDataTexture.destroy(); + } + var u8 = new Uint8Array(u32.buffer); + this.layerDataTexture = renderer.createUint8ArrayTexture(u8, layer.width, layer.height, false, true); + } +}); + +module.exports = TilemapGPULayer; + + +/***/ }), + +/***/ 57912: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(6736); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 6736: +/***/ ((module) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.Tilemaps.TilemapLayer#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.Tilemaps.TilemapLayer} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested + */ +var TilemapLayerWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + + submitterNode.run( + drawingContext, + src, + parentMatrix + ); +}; + +module.exports = TilemapLayerWebGLRenderer; + + +/***/ }), + +/***/ 20442: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DefaultTilemapLayerNodes = __webpack_require__(79317); +var Class = __webpack_require__(83419); +var TilemapComponents = __webpack_require__(81086); +var TilemapLayerRender = __webpack_require__(19218); +var TilemapLayerBase = __webpack_require__(44731); + +/** + * @classdesc + * A Tilemap Layer is a Game Object that renders LayerData from a Tilemap when used in combination + * with one, or more, Tilesets. + * + * A TilemapLayer can be placed inside a Container, but its physics + * will work as though it was placed directly in the world. + * This is rarely what you want. + * + * @class TilemapLayer + * @extends Phaser.Tilemaps.TilemapLayerBase + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.50.0 + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. + * @param {Phaser.Tilemaps.Tilemap} tilemap - The Tilemap this layer is a part of. + * @param {number} layerIndex - The index of the LayerData associated with this layer. + * @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object. + * @param {number} [x=0] - The world x position where the top left of this layer will be placed. + * @param {number} [y=0] - The world y position where the top left of this layer will be placed. + */ +var TilemapLayer = new Class({ + + Extends: TilemapLayerBase, + + Mixins: [ + TilemapLayerRender + ], + + initialize: + + function TilemapLayer (scene, tilemap, layerIndex, tileset, x, y) + { + TilemapLayerBase.call(this, 'TilemapLayer', scene, tilemap, layerIndex, x, y); + + /** + * An array of `Tileset` objects associated with this layer. + * + * @name Phaser.Tilemaps.TilemapLayer#tileset + * @type {Phaser.Tilemaps.Tileset[]} + * @since 3.50.0 + */ + this.tileset = []; + + /** + * The total number of tiles drawn by the renderer in the last frame. + * + * @name Phaser.Tilemaps.TilemapLayer#tilesDrawn + * @type {number} + * @readonly + * @since 3.50.0 + */ + this.tilesDrawn = 0; + + /** + * The total number of tiles in this layer. Updated every frame. + * + * @name Phaser.Tilemaps.TilemapLayer#tilesTotal + * @type {number} + * @readonly + * @since 3.50.0 + */ + this.tilesTotal = this.layer.width * this.layer.height; + + /** + * Used internally during rendering. This holds the tiles that are visible within the Camera. + * + * @name Phaser.Tilemaps.TilemapLayer#culledTiles + * @type {Phaser.Tilemaps.Tile[]} + * @since 3.50.0 + */ + this.culledTiles = []; + + /** + * You can control if the camera should cull tiles on this layer before rendering them or not. + * + * By default the camera will try to cull the tiles in this layer, to avoid over-drawing to the renderer. + * + * However, there are some instances when you may wish to disable this, and toggling this flag allows + * you to do so. Also see `setSkipCull` for a chainable method that does the same thing. + * + * @name Phaser.Tilemaps.TilemapLayer#skipCull + * @type {boolean} + * @since 3.50.0 + */ + this.skipCull = false; + + /** + * The amount of extra tiles to add into the cull rectangle when calculating its horizontal size. + * + * See the method `setCullPadding` for more details. + * + * @name Phaser.Tilemaps.TilemapLayer#cullPaddingX + * @type {number} + * @default 1 + * @since 3.50.0 + */ + this.cullPaddingX = 1; + + /** + * The amount of extra tiles to add into the cull rectangle when calculating its vertical size. + * + * See the method `setCullPadding` for more details. + * + * @name Phaser.Tilemaps.TilemapLayer#cullPaddingY + * @type {number} + * @default 1 + * @since 3.50.0 + */ + this.cullPaddingY = 1; + + /** + * The callback that is invoked when the tiles are culled. + * + * It will call a different function based on the map orientation: + * + * Orthogonal (the default) is `TilemapComponents.CullTiles` + * Isometric is `TilemapComponents.IsometricCullTiles` + * Hexagonal is `TilemapComponents.HexagonalCullTiles` + * Staggered is `TilemapComponents.StaggeredCullTiles` + * + * However, you can override this to call any function you like. + * + * It will be sent 4 arguments: + * + * 1. The Phaser.Tilemaps.LayerData object for this Layer + * 2. The Camera that is culling the layer. You can check its `dirty` property to see if it has changed since the last cull. + * 3. A reference to the `culledTiles` array, which should be used to store the tiles you want rendered. + * 4. The Render Order constant. + * + * See the `TilemapComponents.CullTiles` source code for details on implementing your own culling system. + * + * @name Phaser.Tilemaps.TilemapLayer#cullCallback + * @type {function} + * @since 3.50.0 + */ + this.cullCallback = TilemapComponents.GetCullTilesFunction(this.layer.orientation); + + /** + * The rendering (draw) order of the tiles in this layer. + * + * The default is 0 which is 'right-down', meaning it will draw the tiles starting from the top-left, + * drawing to the right and then moving down to the next row. + * + * The draw orders are: + * + * 0 = right-down + * 1 = left-down + * 2 = right-up + * 3 = left-up + * + * This can be changed via the `setRenderOrder` method. + * + * @name Phaser.Tilemaps.TilemapLayer#_renderOrder + * @type {number} + * @default 0 + * @private + * @since 3.50.0 + */ + this._renderOrder = 0; + + this.setTilesets(tileset); + + this.initRenderNodes(this._defaultRenderNodesMap); + }, + + /** + * The default render nodes for this Game Object. + * + * @name Phaser.Tilemaps.TilemapLayer#_defaultRenderNodesMap + * @type {Map} + * @private + * @webglOnly + * @readonly + * @since 4.0.0 + */ + _defaultRenderNodesMap: { + get: function () + { + return DefaultTilemapLayerNodes; + } + }, + + /** + * Populates the internal `tileset` array with the Tileset references this Layer requires for rendering. + * + * @method Phaser.Tilemaps.TilemapLayer#setTilesets + * @private + * @since 3.50.0 + * + * @param {(string|string[]|Phaser.Tilemaps.Tileset|Phaser.Tilemaps.Tileset[])} tileset - The tileset, or an array of tilesets, used to render this layer. Can be a string or a Tileset object. + */ + setTilesets: function (tilesets) + { + var gidMap = []; + var setList = []; + var map = this.tilemap; + + if (!Array.isArray(tilesets)) + { + tilesets = [ tilesets ]; + } + + for (var i = 0; i < tilesets.length; i++) + { + var tileset = tilesets[i]; + + if (typeof tileset === 'string') + { + tileset = map.getTileset(tileset); + } + + if (tileset) + { + setList.push(tileset); + + var s = tileset.firstgid; + + for (var t = 0; t < tileset.total; t++) + { + gidMap[s + t] = tileset; + } + } + } + + this.gidMap = gidMap; + this.tileset = setList; + }, + + /** + * Sets the rendering (draw) order of the tiles in this layer. + * + * The default is 'right-down', meaning it will order the tiles starting from the top-left, + * drawing to the right and then moving down to the next row. + * + * The draw orders are: + * + * 0 = right-down + * 1 = left-down + * 2 = right-up + * 3 = left-up + * + * Setting the render order does not change the tiles or how they are stored in the layer, + * it purely impacts the order in which they are rendered. + * + * You can provide either an integer (0 to 3), or the string version of the order. + * + * @method Phaser.Tilemaps.TilemapLayer#setRenderOrder + * @since 3.50.0 + * + * @param {(number|string)} renderOrder - The render (draw) order value. Either an integer between 0 and 3, or a string: 'right-down', 'left-down', 'right-up' or 'left-up'. + * + * @return {this} This Tilemap Layer object. + */ + setRenderOrder: function (renderOrder) + { + var orders = [ 'right-down', 'left-down', 'right-up', 'left-up' ]; + + if (typeof renderOrder === 'string') + { + renderOrder = orders.indexOf(renderOrder); + } + + if (renderOrder >= 0 && renderOrder < 4) + { + this._renderOrder = renderOrder; + } + + return this; + }, + + /** + * Returns the tiles in the given layer that are within the cameras viewport. + * This is used internally during rendering. + * + * @method Phaser.Tilemaps.TilemapLayer#cull + * @since 3.50.0 + * + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to run the cull check against. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects to render. + */ + cull: function (camera) + { + return this.cullCallback(this.layer, camera, this.culledTiles, this._renderOrder); + }, + + /** + * You can control if the Cameras should cull tiles before rendering them or not. + * + * By default the camera will try to cull the tiles in this layer, to avoid over-drawing to the renderer. + * + * However, there are some instances when you may wish to disable this. + * + * @method Phaser.Tilemaps.TilemapLayer#setSkipCull + * @since 3.50.0 + * + * @param {boolean} [value=true] - Set to `true` to stop culling tiles. Set to `false` to enable culling again. + * + * @return {this} This Tilemap Layer object. + */ + setSkipCull: function (value) + { + if (value === undefined) { value = true; } + + this.skipCull = value; + + return this; + }, + + /** + * When a Camera culls the tiles in this layer it does so using its view into the world, building up a + * rectangle inside which the tiles must exist or they will be culled. Sometimes you may need to expand the size + * of this 'cull rectangle', especially if you plan on rotating the Camera viewing the layer. Do so + * by providing the padding values. The values given are in tiles, not pixels. So if the tile width was 32px + * and you set `paddingX` to be 4, it would add 32px x 4 to the cull rectangle (adjusted for scale) + * + * @method Phaser.Tilemaps.TilemapLayer#setCullPadding + * @since 3.50.0 + * + * @param {number} [paddingX=1] - The amount of extra horizontal tiles to add to the cull check padding. + * @param {number} [paddingY=1] - The amount of extra vertical tiles to add to the cull check padding. + * + * @return {this} This Tilemap Layer object. + */ + setCullPadding: function (paddingX, paddingY) + { + if (paddingX === undefined) { paddingX = 1; } + if (paddingY === undefined) { paddingY = 1; } + + this.cullPaddingX = paddingX; + this.cullPaddingY = paddingY; + + return this; + }, + + /** + * Sets an additive tint on each Tile within the given area. + * + * The tint works by taking the pixel color values from the tileset texture, and then + * multiplying it by the color value of the tint. + * + * If no area values are given then all tiles will be tinted to the given color. + * + * To remove a tint call this method with either no parameters, or by passing white `0xffffff` as the tint color. + * + * If a tile already has a tint set then calling this method will override that. + * + * @method Phaser.Tilemaps.TilemapLayer#setTint + * @webglOnly + * @since 3.60.0 + * + * @param {number} [tint=0xffffff] - The tint color being applied to each tile within the region. Given as a hex value, i.e. `0xff0000` for red. Set to white (`0xffffff`) to reset the tint. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * + * @return {this} This Tilemap Layer object. + */ + setTint: function (tint, tileX, tileY, width, height, filteringOptions) + { + if (tint === undefined) { tint = 0xffffff; } + + var tintTile = function (tile) + { + tile.tint = tint; + tile.tintFill = false; + }; + + return this.forEachTile(tintTile, this, tileX, tileY, width, height, filteringOptions); + }, + + /** + * Sets a fill-based tint on each Tile within the given area. + * + * Unlike an additive tint, a fill-tint literally replaces the pixel colors from the texture + * with those in the tint. + * + * If no area values are given then all tiles will be tinted to the given color. + * + * To remove a tint call this method with either no parameters, or by passing white `0xffffff` as the tint color. + * + * If a tile already has a tint set then calling this method will override that. + * + * @method Phaser.Tilemaps.TilemapLayer#setTintFill + * @webglOnly + * @since 3.70.0 + * + * @param {number} [tint=0xffffff] - The tint color being applied to each tile within the region. Given as a hex value, i.e. `0xff0000` for red. Set to white (`0xffffff`) to reset the tint. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * + * @return {this} This Tilemap Layer object. + */ + setTintFill: function (tint, tileX, tileY, width, height, filteringOptions) + { + if (tint === undefined) { tint = 0xffffff; } + + var tintTile = function (tile) + { + tile.tint = tint; + tile.tintFill = true; + }; + + return this.forEachTile(tintTile, this, tileX, tileY, width, height, filteringOptions); + }, + + destroy: function (removeFromTilemap) + { + this.culledTiles.length = 0; + this.cullCallback = null; + + TilemapLayerBase.prototype.destroy.call(this, removeFromTilemap); + } +}); + +module.exports = TilemapLayer; + + +/***/ }), + +/***/ 44731: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Benjamin D. Richards + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CollisionComponent = __webpack_require__(78389); +var Components = __webpack_require__(31401); +var GameObject = __webpack_require__(95643); +var TilemapComponents = __webpack_require__(81086); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A TilemapLayer is a Game Object that renders LayerData from a Tilemap + * when used in combination with one, or more, Tilesets. + * This is a generic base class that is extended by the TilemapLayer classes. + * It is not used directly and should not be instantiated. + * + * @see Phaser.Tilemaps.TilemapLayer + * @see Phaser.Tilemaps.TilemapGPULayer + * + * @class TilemapLayerBase + * @extends Phaser.GameObjects.GameObject + * @memberof Phaser.Tilemaps + * @constructor + * @since 4.0.0 + * + * @extends Phaser.GameObjects.Components.Alpha + * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize + * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.ElapseTimer + * @extends Phaser.GameObjects.Components.Flip + * @extends Phaser.GameObjects.Components.GetBounds + * @extends Phaser.GameObjects.Components.Lighting + * @extends Phaser.GameObjects.Components.Mask + * @extends Phaser.GameObjects.Components.Origin + * @extends Phaser.GameObjects.Components.RenderNodes + * @extends Phaser.GameObjects.Components.ScrollFactor + * @extends Phaser.GameObjects.Components.Transform + * @extends Phaser.GameObjects.Components.Visible + * @extends Phaser.Physics.Arcade.Components.Collision + * + * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. + * @param {Phaser.Tilemaps.Tilemap} tilemap - The Tilemap this layer is a part of. + * @param {number} layerIndex - The index of the LayerData associated with this layer. + * @param {number} [x=0] - The world x position where the top left of this layer will be placed. + * @param {number} [y=0] - The world y position where the top left of this layer will be placed. + */ +var TilemapLayerBase = new Class({ + + Extends: GameObject, + + Mixins: [ + Components.Alpha, + Components.BlendMode, + Components.ComputedSize, + Components.Depth, + Components.ElapseTimer, + Components.Flip, + Components.GetBounds, + Components.Lighting, + Components.Mask, + Components.Origin, + Components.RenderNodes, + Components.Transform, + Components.Visible, + Components.ScrollFactor, + CollisionComponent + ], + + initialize: + + function TilemapLayerBase (type, scene, tilemap, layerIndex, x, y) + { + GameObject.call(this, scene, type); + + /** + * Used internally by physics system to perform fast type checks. + * + * @name Phaser.Tilemaps.TilemapLayerBase#isTilemap + * @type {boolean} + * @readonly + * @since 3.50.0 + */ + this.isTilemap = true; + + /** + * The Tilemap that this layer is a part of. + * + * @name Phaser.Tilemaps.TilemapLayerBase#tilemap + * @type {Phaser.Tilemaps.Tilemap} + * @since 3.50.0 + */ + this.tilemap = tilemap; + + /** + * The index of the LayerData associated with this layer. + * + * @name Phaser.Tilemaps.TilemapLayerBase#layerIndex + * @type {number} + * @since 3.50.0 + */ + this.layerIndex = layerIndex; + + /** + * The LayerData associated with this layer. LayerData can only be associated with one + * tilemap layer. + * + * @name Phaser.Tilemaps.TilemapLayerBase#layer + * @type {Phaser.Tilemaps.LayerData} + * @since 3.50.0 + */ + this.layer = tilemap.layers[layerIndex]; + + // Link the LayerData with this static tilemap layer + this.layer.tilemapLayer = this; + + /** + * An array holding the mapping between the tile indexes and the tileset they belong to. + * + * @name Phaser.Tilemaps.TilemapLayerBase#gidMap + * @type {Phaser.Tilemaps.Tileset[]} + * @since 3.50.0 + */ + this.gidMap = []; + + /** + * A temporary Vector2 used in the tile coordinate methods. + * + * @name Phaser.Tilemaps.TilemapLayerBase#tempVec + * @type {Phaser.Math.Vector2} + * @private + * @since 3.60.0 + */ + this.tempVec = new Vector2(); + + /** + * The Tilemap Layer Collision Category. + * + * This is exclusively used by the Arcade Physics system. + * + * This can be set to any valid collision bitfield value. + * + * See the `setCollisionCategory` method for more details. + * + * @name Phaser.Tilemaps.TilemapLayerBase#collisionCategory + * @type {number} + * @since 3.70.0 + */ + this.collisionCategory = 0x0001; + + /** + * The Tilemap Layer Collision Mask. + * + * This is exclusively used by the Arcade Physics system. + * + * See the `setCollidesWith` method for more details. + * + * @name Phaser.Tilemaps.TilemapLayerBase#collisionMask + * @type {number} + * @since 3.70.0 + */ + this.collisionMask = 1; + + /** + * The horizontal origin of this Tilemap Layer. + * + * @name Phaser.Tilemaps.TilemapLayerBase#originX + * @type {number} + * @default 0 + * @readOnly + * @since 3.0.0 + */ + + /** + * The vertical origin of this Tilemap Layer. + * + * @name Phaser.Tilemaps.TilemapLayerBase#originY + * @type {number} + * @default 0 + * @readOnly + * @since 3.0.0 + */ + + /** + * The horizontal display origin of this Tilemap Layer. + * + * @name Phaser.Tilemaps.TilemapLayerBase#displayOriginX + * @type {number} + * @default 0 + * @readOnly + * @since 3.0.0 + */ + + /** + * The vertical display origin of this Tilemap Layer. + * + * @name Phaser.Tilemaps.TilemapLayerBase#displayOriginY + * @type {number} + * @default 0 + * @readOnly + * @since 3.0.0 + */ + + this.setAlpha(this.layer.alpha); + this.setPosition(x, y); + this.setOrigin(0, 0); + this.setSize(tilemap.tileWidth * this.layer.width, tilemap.tileHeight * this.layer.height); + }, + + // Overrides Game Object method + addedToScene: function () + { + this.scene.sys.updateList.add(this); + }, + + // Overrides Game Object method + removedFromScene: function () + { + this.scene.sys.updateList.remove(this); + }, + + preUpdate: function (time, delta) + { + this.updateTimer(time, delta); + }, + + /** + * Calculates interesting faces at the given tile coordinates of the specified layer. Interesting + * faces are used internally for optimizing collisions against tiles. This method is mostly used + * internally to optimize recalculating faces when only one tile has been changed. + * + * @method Phaser.Tilemaps.TilemapLayerBase#calculateFacesAt + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate. + * @param {number} tileY - The y coordinate. + * + * @return {this} This Tilemap Layer object. + */ + calculateFacesAt: function (tileX, tileY) + { + TilemapComponents.CalculateFacesAt(tileX, tileY, this.layer); + + return this; + }, + + /** + * Calculates interesting faces within the rectangular area specified (in tile coordinates) of the + * layer. Interesting faces are used internally for optimizing collisions against tiles. This method + * is mostly used internally. + * + * @method Phaser.Tilemaps.TilemapLayerBase#calculateFacesWithin + * @since 3.50.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * + * @return {this} This Tilemap Layer object. + */ + calculateFacesWithin: function (tileX, tileY, width, height) + { + TilemapComponents.CalculateFacesWithin(tileX, tileY, width, height, this.layer); + + return this; + }, + + /** + * Creates a Sprite for every object matching the given tile indexes in the layer. You can + * optionally specify if each tile will be replaced with a new tile after the Sprite has been + * created. This is useful if you want to lay down special tiles in a level that are converted to + * Sprites, but want to replace the tile itself with a floor tile or similar once converted. + * + * @method Phaser.Tilemaps.TilemapLayerBase#createFromTiles + * @since 3.50.0 + * + * @param {(number|array)} indexes - The tile index, or array of indexes, to create Sprites from. + * @param {?(number|array)} replacements - The tile index, or array of indexes, to change a converted + * tile to. Set to `null` to leave the tiles unchanged. If an array is given, it is assumed to be a + * one-to-one mapping with the indexes array. + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} [spriteConfig] - The config object to pass into the Sprite creator (i.e. + * scene.make.sprite). + * @param {Phaser.Scene} [scene] - The Scene to create the Sprites within. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when determining the world XY + * + * @return {Phaser.GameObjects.Sprite[]} An array of the Sprites that were created. + */ + createFromTiles: function (indexes, replacements, spriteConfig, scene, camera) + { + return TilemapComponents.CreateFromTiles(indexes, replacements, spriteConfig, scene, camera, this.layer); + }, + + /** + * Copies the tiles in the source rectangular area to a new destination (all specified in tile + * coordinates) within the layer. This copies all tile properties & recalculates collision + * information in the destination region. + * + * @method Phaser.Tilemaps.TilemapLayerBase#copy + * @since 3.50.0 + * + * @param {number} srcTileX - The x coordinate of the area to copy from, in tiles, not pixels. + * @param {number} srcTileY - The y coordinate of the area to copy from, in tiles, not pixels. + * @param {number} width - The width of the area to copy, in tiles, not pixels. + * @param {number} height - The height of the area to copy, in tiles, not pixels. + * @param {number} destTileX - The x coordinate of the area to copy to, in tiles, not pixels. + * @param {number} destTileY - The y coordinate of the area to copy to, in tiles, not pixels. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * + * @return {this} This Tilemap Layer object. + */ + copy: function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces) + { + TilemapComponents.Copy(srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, this.layer); + + return this; + }, + + /** + * Sets the tiles in the given rectangular area (in tile coordinates) of the layer with the + * specified index. Tiles will be set to collide if the given index is a colliding index. + * Collision information in the region will be recalculated. + * + * @method Phaser.Tilemaps.TilemapLayerBase#fill + * @since 3.50.0 + * + * @param {number} index - The tile index to fill the area with. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * + * @return {this} This Tilemap Layer object. + */ + fill: function (index, tileX, tileY, width, height, recalculateFaces) + { + TilemapComponents.Fill(index, tileX, tileY, width, height, recalculateFaces, this.layer); + + return this; + }, + + /** + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * filter callback function. Any tiles that pass the filter test (i.e. where the callback returns + * true) will returned as a new array. Similar to Array.prototype.Filter in vanilla JS. + * + * @method Phaser.Tilemaps.TilemapLayerBase#filterTiles + * @since 3.50.0 + * + * @param {function} callback - The callback. Each tile in the given area will be passed to this + * callback as the first and only parameter. The callback should return true for tiles that pass the + * filter. + * @param {object} [context] - The context under which the callback should be run. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects. + */ + filterTiles: function (callback, context, tileX, tileY, width, height, filteringOptions) + { + return TilemapComponents.FilterTiles(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); + }, + + /** + * Searches the entire map layer for the first tile matching the given index, then returns that Tile + * object. If no match is found, it returns null. The search starts from the top-left tile and + * continues horizontally until it hits the end of the row, then it drops down to the next column. + * If the reverse boolean is true, it scans starting from the bottom-right corner traveling up to + * the top-left. + * + * @method Phaser.Tilemaps.TilemapLayerBase#findByIndex + * @since 3.50.0 + * + * @param {number} index - The tile index value to search for. + * @param {number} [skip=0] - The number of times to skip a matching tile before returning. + * @param {boolean} [reverse=false] - If true it will scan the layer in reverse, starting at the bottom-right. Otherwise it scans from the top-left. + * + * @return {Phaser.Tilemaps.Tile} The first matching Tile object. + */ + findByIndex: function (findIndex, skip, reverse) + { + return TilemapComponents.FindByIndex(findIndex, skip, reverse, this.layer); + }, + + /** + * Find the first tile in the given rectangular area (in tile coordinates) of the layer that + * satisfies the provided testing function. I.e. finds the first tile for which `callback` returns + * true. Similar to Array.prototype.find in vanilla JS. + * + * @method Phaser.Tilemaps.TilemapLayerBase#findTile + * @since 3.50.0 + * + * @param {FindTileCallback} callback - The callback. Each tile in the given area will be passed to this callback as the first and only parameter. + * @param {object} [context] - The context under which the callback should be run. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * + * @return {?Phaser.Tilemaps.Tile} The first Tile found at the given location. + */ + findTile: function (callback, context, tileX, tileY, width, height, filteringOptions) + { + return TilemapComponents.FindTile(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); + }, + + /** + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * callback. Similar to Array.prototype.forEach in vanilla JS. + * + * @method Phaser.Tilemaps.TilemapLayerBase#forEachTile + * @since 3.50.0 + * + * @param {EachTileCallback} callback - The callback. Each tile in the given area will be passed to this callback as the first and only parameter. + * @param {object} [context] - The context, or scope, under which the callback should be run. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area to search. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * + * @return {this} This Tilemap Layer object. + */ + forEachTile: function (callback, context, tileX, tileY, width, height, filteringOptions) + { + TilemapComponents.ForEachTile(callback, context, tileX, tileY, width, height, filteringOptions, this.layer); + + return this; + }, + + /** + * Gets a tile at the given tile coordinates from the given layer. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getTileAt + * @since 3.50.0 + * + * @param {number} tileX - X position to get the tile from (given in tile units, not pixels). + * @param {number} tileY - Y position to get the tile from (given in tile units, not pixels). + * @param {boolean} [nonNull=false] - For empty tiles, return a Tile object with an index of -1 instead of null. + * + * @return {Phaser.Tilemaps.Tile} The Tile at the given coordinates or null if no tile was found or the coordinates were invalid. + */ + getTileAt: function (tileX, tileY, nonNull) + { + return TilemapComponents.GetTileAt(tileX, tileY, nonNull, this.layer); + }, + + /** + * Gets a tile at the given world coordinates from the given layer. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getTileAtWorldXY + * @since 3.50.0 + * + * @param {number} worldX - X position to get the tile from (given in pixels) + * @param {number} worldY - Y position to get the tile from (given in pixels) + * @param {boolean} [nonNull=false] - For empty tiles, return a Tile object with an index of -1 instead of null. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {Phaser.Tilemaps.Tile} The tile at the given coordinates or null if no tile was found or the coordinates were invalid. + */ + getTileAtWorldXY: function (worldX, worldY, nonNull, camera) + { + return TilemapComponents.GetTileAtWorldXY(worldX, worldY, nonNull, camera, this.layer); + }, + + /** + * Gets a tile at the given world coordinates from the given isometric layer. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getIsoTileAtWorldXY + * @since 3.60.0 + * + * @param {number} worldX - X position to get the tile from (given in pixels) + * @param {number} worldY - Y position to get the tile from (given in pixels) + * @param {boolean} [originTop=true] - Which is the active face of the isometric tile? The top (default, true), or the base? (false) + * @param {boolean} [nonNull=false] - For empty tiles, return a Tile object with an index of -1 instead of null. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {Phaser.Tilemaps.Tile} The tile at the given coordinates or null if no tile was found or the coordinates were invalid. + */ + getIsoTileAtWorldXY: function (worldX, worldY, originTop, nonNull, camera) + { + if (originTop === undefined) { originTop = true; } + + var point = this.tempVec; + + TilemapComponents.IsometricWorldToTileXY(worldX, worldY, true, point, camera, this.layer, originTop); + + return this.getTileAt(point.x, point.y, nonNull); + }, + + /** + * Gets the tiles in the given rectangular area (in tile coordinates) of the layer. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getTilesWithin + * @since 3.50.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects found within the area. + */ + getTilesWithin: function (tileX, tileY, width, height, filteringOptions) + { + return TilemapComponents.GetTilesWithin(tileX, tileY, width, height, filteringOptions, this.layer); + }, + + /** + * Gets the tiles that overlap with the given shape in the given layer. The shape must be a Circle, + * Line, Rectangle or Triangle. The shape should be in world coordinates. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getTilesWithinShape + * @since 3.50.0 + * + * @param {(Phaser.Geom.Circle|Phaser.Geom.Line|Phaser.Geom.Rectangle|Phaser.Geom.Triangle)} shape - A shape in world (pixel) coordinates + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when factoring in which tiles to return. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects found within the shape. + */ + getTilesWithinShape: function (shape, filteringOptions, camera) + { + return TilemapComponents.GetTilesWithinShape(shape, filteringOptions, camera, this.layer); + }, + + /** + * Gets the tiles in the given rectangular area (in world coordinates) of the layer. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getTilesWithinWorldXY + * @since 3.50.0 + * + * @param {number} worldX - The world x coordinate for the top-left of the area. + * @param {number} worldY - The world y coordinate for the top-left of the area. + * @param {number} width - The width of the area. + * @param {number} height - The height of the area. + * @param {Phaser.Types.Tilemaps.FilteringOptions} [filteringOptions] - Optional filters to apply when getting the tiles. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when factoring in which tiles to return. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects found within the area. + */ + getTilesWithinWorldXY: function (worldX, worldY, width, height, filteringOptions, camera) + { + return TilemapComponents.GetTilesWithinWorldXY(worldX, worldY, width, height, filteringOptions, camera, this.layer); + }, + + /** + * Checks if there is a tile at the given location (in tile coordinates) in the given layer. Returns + * false if there is no tile or if the tile at that location has an index of -1. + * + * @method Phaser.Tilemaps.TilemapLayerBase#hasTileAt + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * + * @return {boolean} `true` if a tile was found at the given location, otherwise `false`. + */ + hasTileAt: function (tileX, tileY) + { + return TilemapComponents.HasTileAt(tileX, tileY, this.layer); + }, + + /** + * Checks if there is a tile at the given location (in world coordinates) in the given layer. Returns + * false if there is no tile or if the tile at that location has an index of -1. + * + * @method Phaser.Tilemaps.TilemapLayerBase#hasTileAtWorldXY + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when factoring in which tiles to return. + * + * @return {boolean} `true` if a tile was found at the given location, otherwise `false`. + */ + hasTileAtWorldXY: function (worldX, worldY, camera) + { + return TilemapComponents.HasTileAtWorldXY(worldX, worldY, camera, this.layer); + }, + + /** + * Puts a tile at the given tile coordinates in the specified layer. You can pass in either an index + * or a Tile object. If you pass in a Tile, all attributes will be copied over to the specified + * location. If you pass in an index, only the index at the specified location will be changed. + * Collision information will be recalculated at the specified location. + * + * @method Phaser.Tilemaps.TilemapLayerBase#putTileAt + * @since 3.50.0 + * + * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object. + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was inserted at the given coordinates. + */ + putTileAt: function (tile, tileX, tileY, recalculateFaces) + { + return TilemapComponents.PutTileAt(tile, tileX, tileY, recalculateFaces, this.layer); + }, + + /** + * Puts a tile at the given world coordinates (pixels) in the specified layer. You can pass in either + * an index or a Tile object. If you pass in a Tile, all attributes will be copied over to the + * specified location. If you pass in an index, only the index at the specified location will be + * changed. Collision information will be recalculated at the specified location. + * + * @method Phaser.Tilemaps.TilemapLayerBase#putTileAtWorldXY + * @since 3.50.0 + * + * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object. + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {boolean} [recalculateFaces] - `true` if the faces data should be recalculated. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was inserted at the given coordinates. + */ + putTileAtWorldXY: function (tile, worldX, worldY, recalculateFaces, camera) + { + return TilemapComponents.PutTileAtWorldXY(tile, worldX, worldY, recalculateFaces, camera, this.layer); + }, + + /** + * Puts an array of tiles or a 2D array of tiles at the given tile coordinates in the specified + * layer. The array can be composed of either tile indexes or Tile objects. If you pass in a Tile, + * all attributes will be copied over to the specified location. If you pass in an index, only the + * index at the specified location will be changed. Collision information will be recalculated + * within the region tiles were changed. + * + * @method Phaser.Tilemaps.TilemapLayerBase#putTilesAt + * @since 3.50.0 + * + * @param {(number[]|number[][]|Phaser.Tilemaps.Tile[]|Phaser.Tilemaps.Tile[][])} tile - A row (array) or grid (2D array) of Tiles or tile indexes to place. + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * + * @return {this} This Tilemap Layer object. + */ + putTilesAt: function (tilesArray, tileX, tileY, recalculateFaces) + { + TilemapComponents.PutTilesAt(tilesArray, tileX, tileY, recalculateFaces, this.layer); + + return this; + }, + + /** + * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the + * specified layer. Each tile will receive a new index. If an array of indexes is passed in, then + * those will be used for randomly assigning new tile indexes. If an array is not provided, the + * indexes found within the region (excluding -1) will be used for randomly assigning new tile + * indexes. This method only modifies tile indexes and does not change collision information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#randomize + * @since 3.50.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {number[]} [indexes] - An array of indexes to randomly draw from during randomization. + * + * @return {this} This Tilemap Layer object. + */ + randomize: function (tileX, tileY, width, height, indexes) + { + TilemapComponents.Randomize(tileX, tileY, width, height, indexes, this.layer); + + return this; + }, + + /** + * Removes the tile at the given tile coordinates in the specified layer and updates the layers + * collision information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#removeTileAt + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} [replaceWithNull=true] - If true, this will replace the tile at the specified location with null instead of a Tile with an index of -1. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * + * @return {Phaser.Tilemaps.Tile} A Tile object. + */ + removeTileAt: function (tileX, tileY, replaceWithNull, recalculateFaces) + { + return TilemapComponents.RemoveTileAt(tileX, tileY, replaceWithNull, recalculateFaces, this.layer); + }, + + /** + * Removes the tile at the given world coordinates in the specified layer and updates the layers + * collision information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#removeTileAtWorldXY + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {boolean} [replaceWithNull=true] - If true, this will replace the tile at the specified location with null instead of a Tile with an index of -1. + * @param {boolean} [recalculateFaces=true] - `true` if the faces data should be recalculated. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was removed from the given location. + */ + removeTileAtWorldXY: function (worldX, worldY, replaceWithNull, recalculateFaces, camera) + { + return TilemapComponents.RemoveTileAtWorldXY(worldX, worldY, replaceWithNull, recalculateFaces, camera, this.layer); + }, + + /** + * Draws a debug representation of the layer to the given Graphics. This is helpful when you want to + * get a quick idea of which of your tiles are colliding and which have interesting faces. The tiles + * are drawn starting at (0, 0) in the Graphics, allowing you to place the debug representation + * wherever you want on the screen. + * + * @method Phaser.Tilemaps.TilemapLayerBase#renderDebug + * @since 3.50.0 + * + * @param {Phaser.GameObjects.Graphics} graphics - The target Graphics object to draw upon. + * @param {Phaser.Types.Tilemaps.StyleConfig} [styleConfig] - An object specifying the colors to use for the debug drawing. + * + * @return {this} This Tilemap Layer object. + */ + renderDebug: function (graphics, styleConfig) + { + TilemapComponents.RenderDebug(graphics, styleConfig, this.layer); + + return this; + }, + + /** + * Scans the given rectangular area (given in tile coordinates) for tiles with an index matching + * `findIndex` and updates their index to match `newIndex`. This only modifies the index and does + * not change collision information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#replaceByIndex + * @since 3.50.0 + * + * @param {number} findIndex - The index of the tile to search for. + * @param {number} newIndex - The index of the tile to replace it with. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * + * @return {this} This Tilemap Layer object. + */ + replaceByIndex: function (findIndex, newIndex, tileX, tileY, width, height) + { + TilemapComponents.ReplaceByIndex(findIndex, newIndex, tileX, tileY, width, height, this.layer); + + return this; + }, + + /** + * Sets collision on the given tile or tiles within a layer by index. You can pass in either a + * single numeric index or an array of indexes: [2, 3, 15, 20]. The `collides` parameter controls if + * collision will be enabled (true) or disabled (false). + * + * @method Phaser.Tilemaps.TilemapLayerBase#setCollision + * @since 3.50.0 + * + * @param {(number|array)} indexes - Either a single tile index, or an array of tile indexes. + * @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the update. + * @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to false if no tiles have been placed for significant performance boost. + * + * @return {this} This Tilemap Layer object. + */ + setCollision: function (indexes, collides, recalculateFaces, updateLayer) + { + TilemapComponents.SetCollision(indexes, collides, recalculateFaces, this.layer, updateLayer); + + return this; + }, + + /** + * Sets collision on a range of tiles in a layer whose index is between the specified `start` and + * `stop` (inclusive). Calling this with a start value of 10 and a stop value of 14 would set + * collision for tiles 10, 11, 12, 13 and 14. The `collides` parameter controls if collision will be + * enabled (true) or disabled (false). + * + * @method Phaser.Tilemaps.TilemapLayerBase#setCollisionBetween + * @since 3.50.0 + * + * @param {number} start - The first index of the tile to be set for collision. + * @param {number} stop - The last index of the tile to be set for collision. + * @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the update. + * + * @return {this} This Tilemap Layer object. + */ + setCollisionBetween: function (start, stop, collides, recalculateFaces) + { + TilemapComponents.SetCollisionBetween(start, stop, collides, recalculateFaces, this.layer); + + return this; + }, + + /** + * Sets collision on the tiles within a layer by checking tile properties. If a tile has a property + * that matches the given properties object, its collision flag will be set. The `collides` + * parameter controls if collision will be enabled (true) or disabled (false). Passing in + * `{ collides: true }` would update the collision flag on any tiles with a "collides" property that + * has a value of true. Any tile that doesn't have "collides" set to true will be ignored. You can + * also use an array of values, e.g. `{ types: ["stone", "lava", "sand" ] }`. If a tile has a + * "types" property that matches any of those values, its collision flag will be updated. + * + * @method Phaser.Tilemaps.TilemapLayerBase#setCollisionByProperty + * @since 3.50.0 + * + * @param {object} properties - An object with tile properties and corresponding values that should be checked. + * @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the update. + * + * @return {this} This Tilemap Layer object. + */ + setCollisionByProperty: function (properties, collides, recalculateFaces) + { + TilemapComponents.SetCollisionByProperty(properties, collides, recalculateFaces, this.layer); + + return this; + }, + + /** + * Sets collision on all tiles in the given layer, except for tiles that have an index specified in + * the given array. The `collides` parameter controls if collision will be enabled (true) or + * disabled (false). Tile indexes not currently in the layer are not affected. + * + * @method Phaser.Tilemaps.TilemapLayerBase#setCollisionByExclusion + * @since 3.50.0 + * + * @param {number[]} indexes - An array of the tile indexes to not be counted for collision. + * @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the update. + * + * @return {this} This Tilemap Layer object. + */ + setCollisionByExclusion: function (indexes, collides, recalculateFaces) + { + TilemapComponents.SetCollisionByExclusion(indexes, collides, recalculateFaces, this.layer); + + return this; + }, + + /** + * Sets collision on the tiles within a layer by checking each tiles collision group data + * (typically defined in Tiled within the tileset collision editor). If any objects are found within + * a tiles collision group, the tile's colliding information will be set. The `collides` parameter + * controls if collision will be enabled (true) or disabled (false). + * + * @method Phaser.Tilemaps.TilemapLayerBase#setCollisionFromCollisionGroup + * @since 3.50.0 + * + * @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision. + * @param {boolean} [recalculateFaces=true] - Whether or not to recalculate the tile faces after the update. + * + * @return {this} This Tilemap Layer object. + */ + setCollisionFromCollisionGroup: function (collides, recalculateFaces) + { + TilemapComponents.SetCollisionFromCollisionGroup(collides, recalculateFaces, this.layer); + + return this; + }, + + /** + * Sets a global collision callback for the given tile index within the layer. This will affect all + * tiles on this layer that have the same index. If a callback is already set for the tile index it + * will be replaced. Set the callback to null to remove it. If you want to set a callback for a tile + * at a specific location on the map then see setTileLocationCallback. + * + * @method Phaser.Tilemaps.TilemapLayerBase#setTileIndexCallback + * @since 3.50.0 + * + * @param {(number|number[])} indexes - Either a single tile index, or an array of tile indexes to have a collision callback set for. + * @param {function} callback - The callback that will be invoked when the tile is collided with. + * @param {object} callbackContext - The context under which the callback is called. + * + * @return {this} This Tilemap Layer object. + */ + setTileIndexCallback: function (indexes, callback, callbackContext) + { + TilemapComponents.SetTileIndexCallback(indexes, callback, callbackContext, this.layer); + + return this; + }, + + /** + * Sets a collision callback for the given rectangular area (in tile coordinates) within the layer. + * If a callback is already set for the tile index it will be replaced. Set the callback to null to + * remove it. + * + * @method Phaser.Tilemaps.TilemapLayerBase#setTileLocationCallback + * @since 3.50.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * @param {function} [callback] - The callback that will be invoked when the tile is collided with. + * @param {object} [callbackContext] - The context, or scope, under which the callback is invoked. + * + * @return {this} This Tilemap Layer object. + */ + setTileLocationCallback: function (tileX, tileY, width, height, callback, callbackContext) + { + TilemapComponents.SetTileLocationCallback(tileX, tileY, width, height, callback, callbackContext, this.layer); + + return this; + }, + + /** + * Shuffles the tiles in a rectangular region (specified in tile coordinates) within the given + * layer. It will only randomize the tiles in that area, so if they're all the same nothing will + * appear to have changed! This method only modifies tile indexes and does not change collision + * information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#shuffle + * @since 3.50.0 + * + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * + * @return {this} This Tilemap Layer object. + */ + shuffle: function (tileX, tileY, width, height) + { + TilemapComponents.Shuffle(tileX, tileY, width, height, this.layer); + + return this; + }, + + /** + * Scans the given rectangular area (given in tile coordinates) for tiles with an index matching + * `indexA` and swaps then with `indexB`. This only modifies the index and does not change collision + * information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#swapByIndex + * @since 3.50.0 + * + * @param {number} tileA - First tile index. + * @param {number} tileB - Second tile index. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * + * @return {this} This Tilemap Layer object. + */ + swapByIndex: function (indexA, indexB, tileX, tileY, width, height) + { + TilemapComponents.SwapByIndex(indexA, indexB, tileX, tileY, width, height, this.layer); + + return this; + }, + + /** + * Converts from tile X coordinates (tile units) to world X coordinates (pixels), factoring in the + * layers position, scale and scroll. + * + * @method Phaser.Tilemaps.TilemapLayerBase#tileToWorldX + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {number} The Tile X coordinate converted to pixels. + */ + tileToWorldX: function (tileX, camera) + { + return this.tilemap.tileToWorldX(tileX, camera, this); + }, + + /** + * Converts from tile Y coordinates (tile units) to world Y coordinates (pixels), factoring in the + * layers position, scale and scroll. + * + * @method Phaser.Tilemaps.TilemapLayerBase#tileToWorldY + * @since 3.50.0 + * + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {number} The Tile Y coordinate converted to pixels. + */ + tileToWorldY: function (tileY, camera) + { + return this.tilemap.tileToWorldY(tileY, camera, this); + }, + + /** + * Converts from tile XY coordinates (tile units) to world XY coordinates (pixels), factoring in the + * layers position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @method Phaser.Tilemaps.TilemapLayerBase#tileToWorldXY + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Math.Vector2} [point] - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {Phaser.Math.Vector2} A Vector2 containing the world coordinates of the Tile. + */ + tileToWorldXY: function (tileX, tileY, point, camera) + { + return this.tilemap.tileToWorldXY(tileX, tileY, point, camera, this); + }, + + /** + * Returns an array of Vector2s where each entry corresponds to the corner of the requested tile. + * + * The `tileX` and `tileY` parameters are in tile coordinates, not world coordinates. + * + * The corner coordinates are in world space, having factored in TilemapLayer scale, position + * and the camera, if given. + * + * The size of the array will vary based on the orientation of the map. For example an + * orthographic map will return an array of 4 vectors, where-as a hexagonal map will, + * of course, return an array of 6 corner vectors. + * + * @method Phaser.Tilemaps.TilemapLayerBase#getTileCorners + * @since 3.60.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {?Phaser.Math.Vector2[]} Returns an array of Vector2s, or null if the layer given was invalid. + */ + getTileCorners: function (tileX, tileY, camera) + { + return this.tilemap.getTileCorners(tileX, tileY, camera, this); + }, + + /** + * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the + * specified layer. Each tile will receive a new index. New indexes are drawn from the given + * weightedIndexes array. An example weighted array: + * + * [ + * { index: 6, weight: 4 }, // Probability of index 6 is 4 / 8 + * { index: 7, weight: 2 }, // Probability of index 7 would be 2 / 8 + * { index: 8, weight: 1.5 }, // Probability of index 8 would be 1.5 / 8 + * { index: 26, weight: 0.5 } // Probability of index 27 would be 0.5 / 8 + * ] + * + * The probability of any index being choose is (the index's weight) / (sum of all weights). This + * method only modifies tile indexes and does not change collision information. + * + * @method Phaser.Tilemaps.TilemapLayerBase#weightedRandomize + * @since 3.50.0 + * + * @param {object[]} weightedIndexes - An array of objects to randomly draw from during randomization. They should be in the form: { index: 0, weight: 4 } or { index: [0, 1], weight: 4 } if you wish to draw from multiple tile indexes. + * @param {number} [tileX] - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [tileY] - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} [width] - How many tiles wide from the `tileX` index the area will be. + * @param {number} [height] - How many tiles tall from the `tileY` index the area will be. + * + * @return {this} This Tilemap Layer object. + */ + weightedRandomize: function (weightedIndexes, tileX, tileY, width, height) + { + TilemapComponents.WeightedRandomize(tileX, tileY, width, height, weightedIndexes, this.layer); + + return this; + }, + + /** + * Converts from world X coordinates (pixels) to tile X coordinates (tile units), factoring in the + * layers position, scale and scroll. + * + * You cannot call this method for Isometric or Hexagonal tilemaps as they require + * both `worldX` and `worldY` values to determine the correct tile, instead you + * should use the `worldToTileXY` method. + * + * @method Phaser.Tilemaps.TilemapLayerBase#worldToTileX + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {boolean} [snapToFloor] - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {number} The tile X coordinate based on the world value. + */ + worldToTileX: function (worldX, snapToFloor, camera) + { + return this.tilemap.worldToTileX(worldX, snapToFloor, camera, this); + }, + + /** + * Converts from world Y coordinates (pixels) to tile Y coordinates (tile units), factoring in the + * layers position, scale and scroll. + * + * You cannot call this method for Isometric or Hexagonal tilemaps as they require + * both `worldX` and `worldY` values to determine the correct tile, instead you + * should use the `worldToTileXY` method. + * + * @method Phaser.Tilemaps.TilemapLayerBase#worldToTileY + * @since 3.50.0 + * + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} [snapToFloor] - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {number} The tile Y coordinate based on the world value. + */ + worldToTileY: function (worldY, snapToFloor, camera) + { + return this.tilemap.worldToTileY(worldY, snapToFloor, camera, this); + }, + + /** + * Converts from world XY coordinates (pixels) to tile XY coordinates (tile units), factoring in the + * layers position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @method Phaser.Tilemaps.TilemapLayerBase#worldToTileXY + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} [snapToFloor] - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Math.Vector2} [point] - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to use when calculating the tile index from the world values. + * + * @return {Phaser.Math.Vector2} A Vector2 containing the tile coordinates of the world values. + */ + worldToTileXY: function (worldX, worldY, snapToFloor, point, camera) + { + return this.tilemap.worldToTileXY(worldX, worldY, snapToFloor, point, camera, this); + }, + + /** + * Destroys this TilemapLayer and removes its link to the associated LayerData. + * + * @method Phaser.Tilemaps.TilemapLayerBase#destroy + * @since 3.50.0 + * + * @param {boolean} [removeFromTilemap=true] - Remove this layer from the parent Tilemap? + */ + destroy: function (removeFromTilemap) + { + if (removeFromTilemap === undefined) { removeFromTilemap = true; } + + if (!this.tilemap) + { + // Abort, we've already been destroyed + return; + } + + // Uninstall this layer only if it is still installed on the LayerData object + if (this.layer.tilemapLayer === this) + { + this.layer.tilemapLayer = undefined; + } + + if (removeFromTilemap) + { + this.tilemap.removeLayer(this); + } + + this.tilemap = undefined; + this.layer = undefined; + + this.gidMap = []; + this.tileset = []; + + GameObject.prototype.destroy.call(this); + } + +}); + +module.exports = TilemapLayerBase; + + +/***/ }), + +/***/ 16153: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TransformMatrix = __webpack_require__(61340); + +var camMatrix = new TransformMatrix(); +var layerMatrix = new TransformMatrix(); +var calcMatrix = new TransformMatrix(); + +/** + * Renders this Game Object with the Canvas Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.Tilemaps.TilemapLayer#renderCanvas + * @since 3.50.0 + * @private + * + * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer. + * @param {Phaser.Tilemaps.TilemapLayer} src - The Game Object being rendered in this call. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested + */ +var TilemapLayerCanvasRenderer = function (renderer, src, camera, parentMatrix) +{ + var renderTiles = src.cull(camera); + + var tileCount = renderTiles.length; + var alpha = camera.alpha * src.alpha; + + if (tileCount === 0 || alpha <= 0) + { + return; + } + + layerMatrix.applyITRS(src.x, src.y, src.rotation, src.scaleX, src.scaleY); + + var ctx = renderer.currentContext; + var gidMap = src.gidMap; + + ctx.save(); + + camMatrix.copyWithScrollFactorFrom( + camera.matrixCombined, + camera.scrollX, camera.scrollY, + src.scrollFactorX, src.scrollFactorY + ); + + if (parentMatrix) + { + camMatrix.multiply(parentMatrix); + } + + camMatrix.multiply(layerMatrix, calcMatrix); + + calcMatrix.setToContext(ctx); + + if (!renderer.antialias || src.scaleX > 1 || src.scaleY > 1) + { + ctx.imageSmoothingEnabled = false; + } + + for (var i = 0; i < tileCount; i++) + { + var tile = renderTiles[i]; + + var tileset = gidMap[tile.index]; + + if (!tileset) + { + continue; + } + + var image = tileset.image.getSourceImage(); + + var tileTexCoords = tileset.getTileTextureCoordinates(tile.index); + var tileWidth = tileset.tileWidth; + var tileHeight = tileset.tileHeight; + + if (tileTexCoords === null || tileWidth === 0 || tileHeight === 0) + { + continue; + } + + var halfWidth = tileWidth * 0.5; + var halfHeight = tileHeight * 0.5; + + tileTexCoords.x += tileset.tileOffset.x; + tileTexCoords.y += tileset.tileOffset.y; + + ctx.save(); + + ctx.translate(tile.pixelX + halfWidth, tile.pixelY + halfHeight); + + if (tile.rotation !== 0) + { + ctx.rotate(tile.rotation); + } + + if (tile.flipX || tile.flipY) + { + ctx.scale((tile.flipX) ? -1 : 1, (tile.flipY) ? -1 : 1); + } + + ctx.globalAlpha = alpha * tile.alpha; + + ctx.drawImage( + image, + tileTexCoords.x, tileTexCoords.y, + tileWidth , tileHeight, + -halfWidth, -halfHeight, + tileWidth, tileHeight + ); + + ctx.restore(); + } + + ctx.restore(); +}; + +module.exports = TilemapLayerCanvasRenderer; + + +/***/ }), + +/***/ 19218: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var NOOP = __webpack_require__(29747); +var renderWebGL = NOOP; +var renderCanvas = NOOP; + +if (true) +{ + renderWebGL = __webpack_require__(99558); +} + +if (true) +{ + renderCanvas = __webpack_require__(16153); +} + +module.exports = { + + renderWebGL: renderWebGL, + renderCanvas: renderCanvas + +}; + + +/***/ }), + +/***/ 99558: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Utils = __webpack_require__(70554); + +var getTint = Utils.getTintAppendFloatAlpha; + +var texturerData = { + frame: { + source: { + glTexture: null + } + }, + uvSource: { + u0: 0, + v0: 0, + u1: 1, + v1: 1 + }, + frameWidth: 0, + frameHeight: 0 +}; + +var tinterData = { + tintFill: 0, + tintTopLeft: 0, + tintTopRight: 0, + tintBottomLeft: 0, + tintBottomRight: 0 +}; + +/** + * Renders this Game Object with the WebGL Renderer to the given Camera. + * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera. + * This method should not be called directly. It is a utility function of the Render module. + * + * @method Phaser.Tilemaps.TilemapLayer#renderWebGL + * @since 3.0.0 + * @private + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer. + * @param {Phaser.Tilemaps.TilemapLayer} src - The Game Object being rendered in this call. + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The current drawing context. + * @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - This transform matrix is defined if the game object is nested + */ +var TilemapLayerWebGLRenderer = function (renderer, src, drawingContext, parentMatrix) +{ + var camera = drawingContext.camera; + var renderTiles = src.cull(camera); + + var tileCount = renderTiles.length; + var alpha = src.alpha; + + if (tileCount === 0 || alpha <= 0) + { + return; + } + + var gidMap = src.gidMap; + + var submitterNode = src.customRenderNodes.Submitter || src.defaultRenderNodes.Submitter; + var transformerNode = src.customRenderNodes.Transformer || src.defaultRenderNodes.Transformer; + + var timeElapsed = src.timeElapsed; + + for (var i = 0; i < tileCount; i++) + { + var tile = renderTiles[i]; + + var tileset = gidMap[tile.index]; + + if (!tileset) + { + continue; + } + + var tileIndex = tileset.getAnimatedTileId(tile.index, timeElapsed); + + if (tileIndex === null) + { + continue; + } + + var tileTexCoords = tileset.getTileTextureCoordinates(tileIndex); + var tileWidth = tileset.tileWidth; + var tileHeight = tileset.tileHeight; + + if (!tileTexCoords || tileWidth === 0 || tileHeight === 0) + { + continue; + } + + var texture = tileset.glTexture; + + var frameWidth = tileWidth; + var frameHeight = tileHeight; + + var frameX = tileTexCoords.x; + var frameY = tileTexCoords.y; + + var tint = getTint(tile.tint, alpha * tile.alpha); + + texturerData.frame.source.glTexture = tileset.glTexture; + texturerData.frameWidth = frameWidth; + texturerData.frameHeight = frameHeight; + texturerData.uvSource.u0 = frameX / texture.width; + texturerData.uvSource.v0 = 1 - (frameY + frameHeight) / texture.height; + texturerData.uvSource.u1 = (frameX + frameWidth) / texture.width; + texturerData.uvSource.v1 = 1 - frameY / texture.height; + + tinterData.tintFill = tile.tintFill; + tinterData.tintTopLeft = tint; + tinterData.tintTopRight = tint; + tinterData.tintBottomLeft = tint; + tinterData.tintBottomRight = tint; + + submitterNode.run( + drawingContext, + src, + parentMatrix, + tile, + texturerData, + transformerNode, + tinterData + ); + } +}; + +module.exports = TilemapLayerWebGLRenderer; + + +/***/ }), + +/***/ 33629: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Vector2 = __webpack_require__(26099); + +/** + * @classdesc + * A Tileset is a combination of a single image containing the tiles and a container for data about + * each tile. + * + * @class Tileset + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @param {string} name - The name of the tileset in the map data. + * @param {number} firstgid - The first tile index this tileset contains. + * @param {number} [tileWidth=32] - Width of each tile (in pixels). + * @param {number} [tileHeight=32] - Height of each tile (in pixels). + * @param {number} [tileMargin=0] - The margin around all tiles in the sheet (in pixels). + * @param {number} [tileSpacing=0] - The spacing between each tile in the sheet (in pixels). + * @param {object} [tileProperties={}] - Custom properties defined per tile in the Tileset. + * These typically are custom properties created in Tiled when editing a tileset. + * @param {object} [tileData={}] - Data stored per tile. These typically are created in Tiled when editing a tileset, e.g. from Tiled's tile collision editor or terrain editor. + * @param {object} [tileOffset={x: 0, y: 0}] - Tile texture drawing offset. + */ +var Tileset = new Class({ + + initialize: + + function Tileset (name, firstgid, tileWidth, tileHeight, tileMargin, tileSpacing, tileProperties, tileData, tileOffset) + { + if (tileWidth === undefined || tileWidth <= 0) { tileWidth = 32; } + if (tileHeight === undefined || tileHeight <= 0) { tileHeight = 32; } + if (tileMargin === undefined) { tileMargin = 0; } + if (tileSpacing === undefined) { tileSpacing = 0; } + if (tileProperties === undefined) { tileProperties = {}; } + if (tileData === undefined) { tileData = {}; } + + /** + * The name of the Tileset. + * + * @name Phaser.Tilemaps.Tileset#name + * @type {string} + * @since 3.0.0 + */ + this.name = name; + + /** + * The starting index of the first tile index this Tileset contains. + * + * @name Phaser.Tilemaps.Tileset#firstgid + * @type {number} + * @since 3.0.0 + */ + this.firstgid = firstgid; + + /** + * The width of each tile (in pixels). Use setTileSize to change. + * + * @name Phaser.Tilemaps.Tileset#tileWidth + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.tileWidth = tileWidth; + + /** + * The height of each tile (in pixels). Use setTileSize to change. + * + * @name Phaser.Tilemaps.Tileset#tileHeight + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.tileHeight = tileHeight; + + /** + * The margin around the tiles in the sheet (in pixels). Use `setSpacing` to change. + * + * @name Phaser.Tilemaps.Tileset#tileMargin + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.tileMargin = tileMargin; + + /** + * The spacing between each the tile in the sheet (in pixels). Use `setSpacing` to change. + * + * @name Phaser.Tilemaps.Tileset#tileSpacing + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.tileSpacing = tileSpacing; + + /** + * Tileset-specific properties per tile that are typically defined in the Tiled editor in the + * Tileset editor. + * + * @name Phaser.Tilemaps.Tileset#tileProperties + * @type {object} + * @since 3.0.0 + */ + this.tileProperties = tileProperties; + + /** + * Tileset-specific data per tile that are typically defined in the Tiled editor, e.g. within + * the Tileset collision editor. This is where collision objects and terrain are stored. + * + * @name Phaser.Tilemaps.Tileset#tileData + * @type {object} + * @since 3.0.0 + */ + this.tileData = tileData; + + /** + * Controls the drawing offset from the tile origin. + * Defaults to 0x0, no offset. + * + * @name Phaser.Tilemaps.Tileset#tileOffset + * @type {Phaser.Math.Vector2} + * @since 3.60.0 + */ + this.tileOffset = new Vector2(); + + if (tileOffset !== undefined) + { + this.tileOffset.set(tileOffset.x, tileOffset.y); + } + + /** + * The cached image that contains the individual tiles. Use setImage to set. + * + * @name Phaser.Tilemaps.Tileset#image + * @type {?Phaser.Textures.Texture} + * @readonly + * @since 3.0.0 + */ + this.image = null; + + /** + * The gl texture used by the WebGL renderer. + * + * @name Phaser.Tilemaps.Tileset#glTexture + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @readonly + * @since 3.11.0 + */ + this.glTexture = null; + + /** + * The number of tile rows in the the tileset. + * + * @name Phaser.Tilemaps.Tileset#rows + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.rows = 0; + + /** + * The number of tile columns in the tileset. + * + * @name Phaser.Tilemaps.Tileset#columns + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.columns = 0; + + /** + * The total number of tiles in the tileset. + * + * @name Phaser.Tilemaps.Tileset#total + * @type {number} + * @readonly + * @since 3.0.0 + */ + this.total = 0; + + /** + * The look-up table to specific tile image texture coordinates (UV in pixels). Each element + * contains the coordinates for a tile in an object of the form {x, y}. + * + * @name Phaser.Tilemaps.Tileset#texCoordinates + * @type {object[]} + * @readonly + * @since 3.0.0 + */ + this.texCoordinates = []; + + /** + * The number of frames above which a tile is considered to have + * many animation frames. This is used to optimize rendering. + * If a tile has fewer frames than this, frames are searched using + * a linear search. If a tile has more, frames are searched using + * a binary search. + * + * @name Phaser.Tilemaps.Tileset#animationSearchThreshold + * @type {number} + * @since 4.0.0 + * @default 64 + */ + this.animationSearchThreshold = 64; + + /** + * The maximum length of any animation in this tileset, in frames. + * This is used internally to optimize rendering. + * It is updated when `createAnimationDataTexture` is called. + * + * @name Phaser.Tilemaps.Tileset#maxAnimationLength + * @type {number} + * @readonly + * @since 4.0.0 + */ + this.maxAnimationLength = 0; + + /** + * The texture containing the animation data for this tileset, if any. + * This is used by `TilemapGPULayer` to animate tiles. + * + * This will be created when `createAnimationDataTexture` is called. + * Once created, it will be updated when `updateTileData` is called. + * + * Each texel stores a 32-bit number. + * The first set of texels consists of pairs of numbers, + * describing the total duration and starting index of an animation. + * The second set of texels are the targets of these indices, also in pairs, + * describing the duration and actual index of each frame in the animation. + * + * @name Phaser.Tilemaps.Tileset#_animationDataTexture + * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} + * @private + */ + this._animationDataTexture = null; + + /** + * The map from tile index to animation data index. + * This is used to quickly find the animation data for a tile. + * This is created when `createAnimationDataTexture` is called. + * Once created, it will be updated when `updateTileData` is called. + * + * @name Phaser.Tilemaps.Tileset#_animationDataIndexMap + * @type {?Map} + * @private + */ + this._animationDataIndexMap = null; + }, + + /** + * Get a tiles properties that are stored in the Tileset. Returns null if tile index is not + * contained in this Tileset. This is typically defined in Tiled under the Tileset editor. + * + * @method Phaser.Tilemaps.Tileset#getTileProperties + * @since 3.0.0 + * + * @param {number} tileIndex - The unique id of the tile across all tilesets in the map. + * + * @return {?(object|undefined)} + */ + getTileProperties: function (tileIndex) + { + if (!this.containsTileIndex(tileIndex)) { return null; } + + return this.tileProperties[tileIndex - this.firstgid]; + }, + + /** + * Get a tile's data that is stored in the Tileset. Returns null if tile index is not contained + * in this Tileset. This is typically defined in Tiled and will contain both Tileset collision + * info and terrain mapping. + * + * @method Phaser.Tilemaps.Tileset#getTileData + * @since 3.0.0 + * + * @param {number} tileIndex - The unique id of the tile across all tilesets in the map. + * + * @return {?object|undefined} + */ + getTileData: function (tileIndex) + { + if (!this.containsTileIndex(tileIndex)) { return null; } + + return this.tileData[tileIndex - this.firstgid]; + }, + + /** + * Get a tile's collision group that is stored in the Tileset. Returns null if tile index is not + * contained in this Tileset. This is typically defined within Tiled's tileset collision editor. + * + * @method Phaser.Tilemaps.Tileset#getTileCollisionGroup + * @since 3.0.0 + * + * @param {number} tileIndex - The unique id of the tile across all tilesets in the map. + * + * @return {?object} + */ + getTileCollisionGroup: function (tileIndex) + { + var data = this.getTileData(tileIndex); + + return (data && data.objectgroup) ? data.objectgroup : null; + }, + + /** + * Returns true if and only if this Tileset contains the given tile index. + * + * @method Phaser.Tilemaps.Tileset#containsTileIndex + * @since 3.0.0 + * + * @param {number} tileIndex - The unique id of the tile across all tilesets in the map. + * + * @return {boolean} + */ + containsTileIndex: function (tileIndex) + { + return ( + tileIndex >= this.firstgid && + tileIndex < (this.firstgid + this.total) + ); + }, + + /** + * Returns the ID of the tile to use, given a base tile and time, + * according to the tile's animation properties. + * + * If the tile is not animated, this method returns the base tile ID. + * + * @method Phaser.Tilemaps.Tileset#getAnimatedTileId + * @since 4.0.0 + * @param {number} tileIndex - The unique id of the tile across all tilesets in the map. + * @param {number} milliseconds - The current time in milliseconds. + * @return {?number} The tile ID to use, or null if the tile is not contained in this tileset. + */ + getAnimatedTileId: function (tileIndex, milliseconds) + { + if (!this.containsTileIndex(tileIndex)) { return null; } + + var animData = this.getTileData(tileIndex); + + if (!(animData && animData.animation)) { return tileIndex; } + + milliseconds = milliseconds % animData.animationDuration; + var anim = animData.animation; + var frame = null; + + // Binary search. + + var low = 0; + var high = anim.length - 1; + var mid = 0; + var startTime = 0; + + while (low <= high) + { + mid = (low + high) >>> 1; + frame = anim[mid]; + startTime = frame.startTime; + + if (startTime <= milliseconds && startTime + frame.duration > milliseconds) + { + return frame.tileid + this.firstgid; + } + + if (startTime < milliseconds) + { + low = mid + 1; + } + else + { + high = mid - 1; + } + } + + return null; + }, + + /** + * Returns the texture coordinates (UV in pixels) in the Tileset image for the given tile index. + * Returns null if tile index is not contained in this Tileset. + * + * @method Phaser.Tilemaps.Tileset#getTileTextureCoordinates + * @since 3.0.0 + * + * @param {number} tileIndex - The unique id of the tile across all tilesets in the map. + * + * @return {?object} Object in the form { x, y } representing the top-left UV coordinate + * within the Tileset image. + */ + getTileTextureCoordinates: function (tileIndex) + { + if (!this.containsTileIndex(tileIndex)) { return null; } + + return this.texCoordinates[tileIndex - this.firstgid]; + }, + + /** + * Sets the image associated with this Tileset and updates the tile data (rows, columns, etc.). + * + * @method Phaser.Tilemaps.Tileset#setImage + * @since 3.0.0 + * + * @param {Phaser.Textures.Texture} texture - The image that contains the tiles. + * + * @return {Phaser.Tilemaps.Tileset} This Tileset object. + */ + setImage: function (texture) + { + this.image = texture; + + var frame = texture.get(); + + var bounds = texture.getFrameBounds(); + + this.glTexture = frame.source.glTexture; + + if (frame.width > bounds.width || frame.height > bounds.height) + { + this.updateTileData(frame.width, frame.height); + } + else + { + this.updateTileData(bounds.width, bounds.height, bounds.x, bounds.y); + } + + return this; + }, + + /** + * Sets the tile width & height and updates the tile data (rows, columns, etc.). + * + * @method Phaser.Tilemaps.Tileset#setTileSize + * @since 3.0.0 + * + * @param {number} [tileWidth] - The width of a tile in pixels. + * @param {number} [tileHeight] - The height of a tile in pixels. + * + * @return {Phaser.Tilemaps.Tileset} This Tileset object. + */ + setTileSize: function (tileWidth, tileHeight) + { + if (tileWidth !== undefined) { this.tileWidth = tileWidth; } + if (tileHeight !== undefined) { this.tileHeight = tileHeight; } + + if (this.image) + { + this.updateTileData(this.image.source[0].width, this.image.source[0].height); + } + + return this; + }, + + /** + * Sets the tile margin and spacing and updates the tile data (rows, columns, etc.). + * + * @method Phaser.Tilemaps.Tileset#setSpacing + * @since 3.0.0 + * + * @param {number} [margin] - The margin around the tiles in the sheet (in pixels). + * @param {number} [spacing] - The spacing between the tiles in the sheet (in pixels). + * + * @return {Phaser.Tilemaps.Tileset} This Tileset object. + */ + setSpacing: function (margin, spacing) + { + if (margin !== undefined) { this.tileMargin = margin; } + if (spacing !== undefined) { this.tileSpacing = spacing; } + + if (this.image) + { + this.updateTileData(this.image.source[0].width, this.image.source[0].height); + } + + return this; + }, + + /** + * Updates tile texture coordinates and tileset data. + * + * @method Phaser.Tilemaps.Tileset#updateTileData + * @since 3.0.0 + * + * @param {number} imageWidth - The (expected) width of the image to slice. + * @param {number} imageHeight - The (expected) height of the image to slice. + * @param {number} [offsetX=0] - The x offset in the source texture where the tileset starts. + * @param {number} [offsetY=0] - The y offset in the source texture where the tileset starts. + * + * @return {Phaser.Tilemaps.Tileset} This Tileset object. + */ + updateTileData: function (imageWidth, imageHeight, offsetX, offsetY) + { + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + var rowCount = (imageHeight - this.tileMargin * 2 + this.tileSpacing) / (this.tileHeight + this.tileSpacing); + var colCount = (imageWidth - this.tileMargin * 2 + this.tileSpacing) / (this.tileWidth + this.tileSpacing); + + if (rowCount % 1 !== 0 || colCount % 1 !== 0) + { + console.warn('Image tile area not tile size multiple in: ' + this.name); + } + + // In Tiled a tileset image that is not an even multiple of the tile dimensions is truncated + // - hence the floor when calculating the rows/columns. + rowCount = Math.floor(rowCount); + colCount = Math.floor(colCount); + + this.rows = rowCount; + this.columns = colCount; + + // In Tiled, "empty" spaces in a tileset count as tiles and hence count towards the gid + this.total = rowCount * colCount; + + this.texCoordinates.length = 0; + + var tx = this.tileMargin + offsetX; + var ty = this.tileMargin + offsetY; + + for (var y = 0; y < this.rows; y++) + { + for (var x = 0; x < this.columns; x++) + { + this.texCoordinates.push({ x: tx, y: ty }); + tx += this.tileWidth + this.tileSpacing; + } + + tx = this.tileMargin + offsetX; + ty += this.tileHeight + this.tileSpacing; + } + + // Update the animation data texture. + if (this._animationDataTexture) + { + this.createAnimationDataTexture(); + } + + return this; + }, + + /** + * Get or create the texture containing the animation data for this tileset. + * This is used by `TilemapGPULayer` to animate tiles. + * + * @method Phaser.Tilemaps.Tileset#getAnimationDataTexture + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer to use. + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The animation data texture. + */ + getAnimationDataTexture: function (renderer) + { + if (!this._animationDataTexture) + { + this.createAnimationDataTexture(renderer); + } + + return this._animationDataTexture; + }, + + /** + * Get or create the map from tile index to animation data index. + * This is used by `TilemapGPULayer` to animate tiles. + * + * @method Phaser.Tilemaps.Tileset#getAnimationDataIndexMap + * @since 4.0.0 + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer to use. + * @return {Map} The map from tile index to animation data index. + */ + getAnimationDataIndexMap: function (renderer) + { + if (!this._animationDataIndexMap) + { + this.createAnimationDataTexture(renderer); + } + + return this._animationDataIndexMap; + }, + + /** + * Creates a new WebGLTexture for the tileset's animation data. + * + * @method Phaser.Tilemaps.Tileset#createAnimationDataTexture + * @since 4.0.0 + * + * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The renderer to use. + * + * @return {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper} The new WebGLTexture. + */ + createAnimationDataTexture: function (renderer) + { + var tileData = this.tileData; + var total = this.total; + + var animations = []; + var animFrames = []; + var indexToAnimMap = new Map(); + + var maxLength = 0; + + for (var i = 0; i < total; i++) + { + var tileDatum = tileData[i]; + + if (tileDatum && tileDatum.animation) + { + var animation = tileDatum.animation; + var animationDuration = tileDatum.animationDuration; + + // This index maps to an animation, not a single tile. + indexToAnimMap.set(i, animations.length); + + // This animation points to a run of frames. + animations.push([ animationDuration, animFrames.length ]); + + // The run of frames stores the duration and the actual index. + for (var j = 0; j < animation.length; j++) + { + var frame = animation[j]; + animFrames.push([ frame.duration, frame.tileid ]); + } + + // Store the maximum length of any animation. + maxLength = Math.max(maxLength, animation.length); + } + } + + var totalTuples = animations.length + animFrames.length; + + if (totalTuples > 4096 * 4096 / 2) + { + throw new Error('Tileset.animationDataTexture: too many animations - total number of animations plus animation frames is max 8388608, got ' + (totalTuples)); + } + + var size = totalTuples * 2; + var width = Math.min(size, 4096); + var height = Math.ceil(size / 4096); + + var u32 = new Uint32Array(width * height); + var offset = 0; + + var animLen = animations.length; + + for (i = 0; i < animLen; i++) + { + animation = animations[i]; + var duration = animation[0]; + var index = animation[1]; + u32[offset++] = duration; + + // Store the index as an offset from the start of the animation frames. + // Double the index to account for the 2x 32-bit values per entry. + u32[offset++] = (index + animLen) * 2; + } + + for (i = 0; i < animFrames.length; i++) + { + frame = animFrames[i]; + var frameDuration = frame[0]; + var frameIndex = frame[1]; + u32[offset++] = frameDuration; + u32[offset++] = frameIndex; + } + + // Create or update the animation data texture. + if (this.animationDataTexture) + { + this.animationDataTexture.destroy(); + } + + var u8 = new Uint8Array(u32.buffer); + this._animationDataTexture = renderer.createUint8ArrayTexture(u8, width, height, false, true); + this._animationDataIndexMap = indexToAnimMap; + this.maxAnimationLength = maxLength; + } + +}); + +module.exports = Tileset; + + +/***/ }), + +/***/ 72023: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTileAt = __webpack_require__(7423); + +/** + * Calculates interesting faces at the given tile coordinates of the specified layer. Interesting + * faces are used internally for optimizing collisions against tiles. This method is mostly used + * internally to optimize recalculating faces when only one tile has been changed. + * + * @function Phaser.Tilemaps.Components.CalculateFacesAt + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate. + * @param {number} tileY - The y coordinate. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var CalculateFacesAt = function (tileX, tileY, layer) +{ + var tile = GetTileAt(tileX, tileY, true, layer); + var above = GetTileAt(tileX, tileY - 1, true, layer); + var below = GetTileAt(tileX, tileY + 1, true, layer); + var left = GetTileAt(tileX - 1, tileY, true, layer); + var right = GetTileAt(tileX + 1, tileY, true, layer); + var tileCollides = tile && tile.collides; + + // Assume the changed tile has all interesting edges + if (tileCollides) + { + tile.faceTop = true; + tile.faceBottom = true; + tile.faceLeft = true; + tile.faceRight = true; + } + + // Reset edges that are shared between tile and its neighbors + if (above && above.collides) + { + if (tileCollides) + { + tile.faceTop = false; + } + + above.faceBottom = !tileCollides; + } + + if (below && below.collides) + { + if (tileCollides) + { + tile.faceBottom = false; + } + + below.faceTop = !tileCollides; + } + + if (left && left.collides) + { + if (tileCollides) + { + tile.faceLeft = false; + } + + left.faceRight = !tileCollides; + } + + if (right && right.collides) + { + if (tileCollides) + { + tile.faceRight = false; + } + + right.faceLeft = !tileCollides; + } + + if (tile && !tile.collides) + { + tile.resetFaces(); + } + + return tile; +}; + +module.exports = CalculateFacesAt; + + +/***/ }), + +/***/ 42573: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTileAt = __webpack_require__(7423); +var GetTilesWithin = __webpack_require__(7386); + +/** + * Calculates interesting faces within the rectangular area specified (in tile coordinates) of the + * layer. Interesting faces are used internally for optimizing collisions against tiles. This method + * is mostly used internally. + * + * @function Phaser.Tilemaps.Components.CalculateFacesWithin + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var CalculateFacesWithin = function (tileX, tileY, width, height, layer) +{ + var above = null; + var below = null; + var left = null; + var right = null; + + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + for (var i = 0; i < tiles.length; i++) + { + var tile = tiles[i]; + + if (tile) + { + if (tile.collides) + { + above = GetTileAt(tile.x, tile.y - 1, true, layer); + below = GetTileAt(tile.x, tile.y + 1, true, layer); + left = GetTileAt(tile.x - 1, tile.y, true, layer); + right = GetTileAt(tile.x + 1, tile.y, true, layer); + + tile.faceTop = (above && above.collides) ? false : true; + tile.faceBottom = (below && below.collides) ? false : true; + tile.faceLeft = (left && left.collides) ? false : true; + tile.faceRight = (right && right.collides) ? false : true; + } + else + { + tile.resetFaces(); + } + } + } +}; + +module.exports = CalculateFacesWithin; + + +/***/ }), + +/***/ 33528: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +var point = new Vector2(); + +/** + * Checks if the given tile coordinate is within the isometric layer bounds, or not. + * + * @function Phaser.Tilemaps.Components.CheckIsoBounds + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to check against. + * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera to run the cull check against. + * + * @return {boolean} Returns `true` if the coordinates are within the iso bounds. + */ +var CheckIsoBounds = function (tileX, tileY, layer, camera) +{ + var tilemapLayer = layer.tilemapLayer; + + var cullPaddingX = tilemapLayer.cullPaddingX; + var cullPaddingY = tilemapLayer.cullPaddingY; + + var pos = tilemapLayer.tilemap.tileToWorldXY(tileX, tileY, point, camera, tilemapLayer); + + // we always subtract 1/2 of the tile's height/width to make the culling distance start from the center of the tiles. + return pos.x > camera.worldView.x + tilemapLayer.scaleX * layer.tileWidth * (-cullPaddingX - 0.5) + && pos.x < camera.worldView.right + tilemapLayer.scaleX * layer.tileWidth * (cullPaddingX - 0.5) + && pos.y > camera.worldView.y + tilemapLayer.scaleY * layer.tileHeight * (-cullPaddingY - 1.0) + && pos.y < camera.worldView.bottom + tilemapLayer.scaleY * layer.tileHeight * (cullPaddingY - 0.5); +}; + +module.exports = CheckIsoBounds; + + +/***/ }), + +/***/ 1785: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CalculateFacesWithin = __webpack_require__(42573); +var GetTilesWithin = __webpack_require__(7386); +var IsInLayerBounds = __webpack_require__(62991); +var Tile = __webpack_require__(23029); + +/** + * Copies the tiles in the source rectangular area to a new destination (all specified in tile + * coordinates) within the layer. This copies all tile properties and recalculates collision + * information in the destination region. + * + * @function Phaser.Tilemaps.Components.Copy + * @since 3.0.0 + * + * @param {number} srcTileX - The x coordinate of the area to copy from, in tiles, not pixels. + * @param {number} srcTileY - The y coordinate of the area to copy from, in tiles, not pixels. + * @param {number} width - The width of the area to copy, in tiles, not pixels. + * @param {number} height - The height of the area to copy, in tiles, not pixels. + * @param {number} destTileX - The x coordinate of the area to copy to, in tiles, not pixels. + * @param {number} destTileY - The y coordinate of the area to copy to, in tiles, not pixels. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var Copy = function (srcTileX, srcTileY, width, height, destTileX, destTileY, recalculateFaces, layer) +{ + if (recalculateFaces === undefined) { recalculateFaces = true; } + + // Returns an array of Tile references + var srcTiles = GetTilesWithin(srcTileX, srcTileY, width, height, null, layer); + + // Create a new array of fresh Tile objects + var copyTiles = []; + + srcTiles.forEach(function (tile) + { + var newTile = new Tile( + tile.layer, + tile.index, + tile.x, + tile.y, + tile.width, + tile.height, + tile.baseWidth, + tile.baseHeight + ); + + newTile.copy(tile); + + copyTiles.push(newTile); + }); + + var offsetX = destTileX - srcTileX; + var offsetY = destTileY - srcTileY; + + for (var i = 0; i < copyTiles.length; i++) + { + var copy = copyTiles[i]; + var tileX = copy.x + offsetX; + var tileY = copy.y + offsetY; + + if (IsInLayerBounds(tileX, tileY, layer)) + { + if (layer.data[tileY][tileX]) + { + copy.x = tileX; + copy.y = tileY; + copy.updatePixelXY(); + + layer.data[tileY][tileX] = copy; + } + } + } + + if (recalculateFaces) + { + // Recalculate the faces within the destination area and neighboring tiles + CalculateFacesWithin(destTileX - 1, destTileY - 1, width + 2, height + 2, layer); + } + + srcTiles.length = 0; + copyTiles.length = 0; +}; + +module.exports = Copy; + + +/***/ }), + +/***/ 78419: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var DeepCopy = __webpack_require__(62644); +var GetTilesWithin = __webpack_require__(7386); +var ReplaceByIndex = __webpack_require__(27987); + +/** + * Creates a Sprite for every object matching the given tile indexes in the layer. You can + * optionally specify if each tile will be replaced with a new tile after the Sprite has been + * created. This is useful if you want to lay down special tiles in a level that are converted to + * Sprites, but want to replace the tile itself with a floor tile or similar once converted. + * + * @function Phaser.Tilemaps.Components.CreateFromTiles + * @since 3.0.0 + * + * @param {(number|number[])} indexes - The tile index, or array of indexes, to create Sprites from. + * @param {?(number|number[])} replacements - The tile index, or array of indexes, to change a converted tile to. Set to `null` to leave the tiles unchanged. If an array is given, it is assumed to be a one-to-one mapping with the indexes array. + * @param {Phaser.Types.GameObjects.Sprite.SpriteConfig} spriteConfig - The config object to pass into the Sprite creator (i.e. scene.make.sprite). + * @param {Phaser.Scene} scene - The Scene to create the Sprites within. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when determining the world XY + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.GameObjects.Sprite[]} An array of the Sprites that were created. + */ +var CreateFromTiles = function (indexes, replacements, spriteConfig, scene, camera, layer) +{ + if (!spriteConfig) { spriteConfig = {}; } + + if (!Array.isArray(indexes)) + { + indexes = [ indexes ]; + } + + var tilemapLayer = layer.tilemapLayer; + + if (!scene) { scene = tilemapLayer.scene; } + if (!camera) { camera = scene.cameras.main; } + + var layerWidth = layer.width; + var layerHeight = layer.height; + + var tiles = GetTilesWithin(0, 0, layerWidth, layerHeight, null, layer); + var sprites = []; + var i; + + var mergeExtras = function (config, tile, properties) + { + for (var i = 0; i < properties.length; i++) + { + var property = properties[i]; + + if (!config.hasOwnProperty(property)) + { + config[property] = tile[property]; + } + } + }; + + for (i = 0; i < tiles.length; i++) + { + var tile = tiles[i]; + var config = DeepCopy(spriteConfig); + + if (indexes.indexOf(tile.index) !== -1) + { + var point = tilemapLayer.tileToWorldXY(tile.x, tile.y, undefined, camera,layer); + + config.x = point.x; + config.y = point.y; + + mergeExtras(config, tile, [ 'rotation', 'flipX', 'flipY', 'alpha', 'visible', 'tint' ]); + + if (!config.hasOwnProperty('origin')) + { + config.x += tile.width * 0.5; + config.y += tile.height * 0.5; + } + + if (config.hasOwnProperty('useSpriteSheet')) + { + config.key = tile.tileset.image; + config.frame = tile.index - 1; + } + + sprites.push(scene.make.sprite(config)); + } + } + + if (Array.isArray(replacements)) + { + // Assume 1 to 1 mapping with indexes array + for (i = 0; i < indexes.length; i++) + { + ReplaceByIndex(indexes[i], replacements[i], 0, 0, layerWidth, layerHeight, layer); + } + } + else if (replacements !== null) + { + // Assume 1 replacement for all types of tile given + for (i = 0; i < indexes.length; i++) + { + ReplaceByIndex(indexes[i], replacements, 0, 0, layerWidth, layerHeight, layer); + } + } + + return sprites; +}; + +module.exports = CreateFromTiles; + + +/***/ }), + +/***/ 19545: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Rectangle = __webpack_require__(87841); +var SnapCeil = __webpack_require__(63448); +var SnapFloor = __webpack_require__(56583); + +var bounds = new Rectangle(); + +/** + * Returns the bounds in the given orthogonal layer that are within the cameras viewport. + * This is used internally by the cull tiles function. + * + * @function Phaser.Tilemaps.Components.CullBounds + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * + * @return {Phaser.Geom.Rectangle} A rectangle containing the culled bounds. If you wish to retain this object, clone it, as it's recycled internally. + */ +var CullBounds = function (layer, camera) +{ + var tilemap = layer.tilemapLayer.tilemap; + var tilemapLayer = layer.tilemapLayer; + + // We need to use the tile sizes defined for the map as a whole, not the layer, + // in order to calculate the bounds correctly. As different sized tiles may be + // placed on the grid and we cannot trust layer.baseTileWidth to give us the true size. + var tileW = Math.floor(tilemap.tileWidth * tilemapLayer.scaleX); + var tileH = Math.floor(tilemap.tileHeight * tilemapLayer.scaleY); + + var boundsLeft = SnapFloor(camera.worldView.x - tilemapLayer.x, tileW, 0, true) - tilemapLayer.cullPaddingX; + var boundsRight = SnapCeil(camera.worldView.right - tilemapLayer.x, tileW, 0, true) + tilemapLayer.cullPaddingX; + + var boundsTop = SnapFloor(camera.worldView.y - tilemapLayer.y, tileH, 0, true) - tilemapLayer.cullPaddingY; + var boundsBottom = SnapCeil(camera.worldView.bottom - tilemapLayer.y, tileH, 0, true) + tilemapLayer.cullPaddingY; + + return bounds.setTo( + boundsLeft, + boundsTop, + (boundsRight - boundsLeft), + (boundsBottom - boundsTop) + ); +}; + +module.exports = CullBounds; + + +/***/ }), + +/***/ 30003: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CullBounds = __webpack_require__(19545); +var RunCull = __webpack_require__(32483); + +/** + * Returns the tiles in the given layer that are within the cameras viewport. This is used internally. + * + * @function Phaser.Tilemaps.Components.CullTiles + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * @param {array} [outputArray] - An optional array to store the Tile objects within. + * @param {number} [renderOrder=0] - The rendering order constant. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects. + */ +var CullTiles = function (layer, camera, outputArray, renderOrder) +{ + if (outputArray === undefined) { outputArray = []; } + if (renderOrder === undefined) { renderOrder = 0; } + + outputArray.length = 0; + + var tilemapLayer = layer.tilemapLayer; + + // Camera world view bounds, snapped for scaled tile size + // Cull Padding values are given in tiles, not pixels + var bounds = CullBounds(layer, camera); + + if (tilemapLayer.skipCull || tilemapLayer.scrollFactorX !== 1 || tilemapLayer.scrollFactorY !== 1) + { + bounds.left = 0; + bounds.right = layer.width; + bounds.top = 0; + bounds.bottom = layer.height; + } + + RunCull(layer, bounds, renderOrder, outputArray); + + return outputArray; +}; + +module.exports = CullTiles; + + +/***/ }), + +/***/ 35137: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); +var CalculateFacesWithin = __webpack_require__(42573); +var SetTileCollision = __webpack_require__(20576); + +/** + * Sets the tiles in the given rectangular area (in tile coordinates) of the layer with the + * specified index. Tiles will be set to collide if the given index is a colliding index. + * Collision information in the region will be recalculated. + * + * @function Phaser.Tilemaps.Components.Fill + * @since 3.0.0 + * + * @param {number} index - The tile index to fill the area with. + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Tilemaps.LayerData} layer - The tile layer to use. If not given the current layer is used. + */ +var Fill = function (index, tileX, tileY, width, height, recalculateFaces, layer) +{ + var doesIndexCollide = (layer.collideIndexes.indexOf(index) !== -1); + + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + for (var i = 0; i < tiles.length; i++) + { + tiles[i].index = index; + + SetTileCollision(tiles[i], doesIndexCollide); + } + + if (recalculateFaces) + { + // Recalculate the faces within the area and neighboring tiles + CalculateFacesWithin(tileX - 1, tileY - 1, width + 2, height + 2, layer); + } +}; + +module.exports = Fill; + + +/***/ }), + +/***/ 40253: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); + +/** + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * filter callback function. Any tiles that pass the filter test (i.e. where the callback returns + * true) will returned as a new array. Similar to Array.prototype.Filter in vanilla JS. + * + * @function Phaser.Tilemaps.Components.FilterTiles + * @since 3.0.0 + * + * @param {function} callback - The callback. Each tile in the given area will be passed to this + * callback as the first and only parameter. The callback should return true for tiles that pass the + * filter. + * @param {object} context - The context under which the callback should be run. + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} filteringOptions - Optional filters to apply when getting the tiles. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile[]} The filtered array of Tiles. + */ +var FilterTiles = function (callback, context, tileX, tileY, width, height, filteringOptions, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer); + + return tiles.filter(callback, context); +}; + +module.exports = FilterTiles; + + +/***/ }), + +/***/ 52692: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Searches the entire map layer for the first tile matching the given index, then returns that Tile + * object. If no match is found, it returns null. The search starts from the top-left tile and + * continues horizontally until it hits the end of the row, then it drops down to the next column. + * If the reverse boolean is true, it scans starting from the bottom-right corner traveling up to + * the top-left. + * + * @function Phaser.Tilemaps.Components.FindByIndex + * @since 3.0.0 + * + * @param {number} index - The tile index value to search for. + * @param {number} skip - The number of times to skip a matching tile before returning. + * @param {boolean} reverse - If true it will scan the layer in reverse, starting at the bottom-right. Otherwise it scans from the top-left. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {?Phaser.Tilemaps.Tile} The first (or n skipped) tile with the matching index. + */ +var FindByIndex = function (findIndex, skip, reverse, layer) +{ + if (skip === undefined) { skip = 0; } + if (reverse === undefined) { reverse = false; } + + var count = 0; + var tx; + var ty; + var tile; + + if (reverse) + { + for (ty = layer.height - 1; ty >= 0; ty--) + { + for (tx = layer.width - 1; tx >= 0; tx--) + { + tile = layer.data[ty][tx]; + if (tile && tile.index === findIndex) + { + if (count === skip) + { + return tile; + } + else + { + count += 1; + } + } + } + } + } + else + { + for (ty = 0; ty < layer.height; ty++) + { + for (tx = 0; tx < layer.width; tx++) + { + tile = layer.data[ty][tx]; + if (tile && tile.index === findIndex) + { + if (count === skip) + { + return tile; + } + else + { + count += 1; + } + } + } + } + } + + return null; +}; + +module.exports = FindByIndex; + + +/***/ }), + +/***/ 66151: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); + +/** + * @callback FindTileCallback + * + * @param {Phaser.Tilemaps.Tile} value - The Tile. + * @param {number} index - The index of the tile. + * @param {Phaser.Tilemaps.Tile[]} array - An array of Tile objects. + * + * @return {boolean} Return `true` if the callback should run, otherwise `false`. + */ + +/** + * Find the first tile in the given rectangular area (in tile coordinates) of the layer that + * satisfies the provided testing function. I.e. finds the first tile for which `callback` returns + * true. Similar to Array.prototype.find in vanilla JS. + * + * @function Phaser.Tilemaps.Components.FindTile + * @since 3.0.0 + * + * @param {FindTileCallback} callback - The callback. Each tile in the given area will be passed to this callback as the first and only parameter. + * @param {object} context - The context under which the callback should be run. + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} filteringOptions - Optional filters to apply when getting the tiles. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {?Phaser.Tilemaps.Tile} A Tile that matches the search, or null if no Tile found + */ +var FindTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer); + + return tiles.find(callback, context) || null; +}; + +module.exports = FindTile; + + +/***/ }), + +/***/ 97560: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); + +/** + * @callback EachTileCallback + * + * @param {Phaser.Tilemaps.Tile} value - The Tile. + * @param {number} index - The index of the tile. + * @param {Phaser.Tilemaps.Tile[]} array - An array of Tile objects. + */ + +/** + * For each tile in the given rectangular area (in tile coordinates) of the layer, run the given + * callback. Similar to Array.prototype.forEach in vanilla JS. + * + * @function Phaser.Tilemaps.Components.ForEachTile + * @since 3.0.0 + * + * @param {EachTileCallback} callback - The callback. Each tile in the given area will be passed to this callback as the first and only parameter. + * @param {object} context - The context under which the callback should be run. + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area to filter. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} filteringOptions - Optional filters to apply when getting the tiles. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var ForEachTile = function (callback, context, tileX, tileY, width, height, filteringOptions, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, filteringOptions, layer); + + tiles.forEach(callback, context); +}; + +module.exports = ForEachTile; + + +/***/ }), + +/***/ 43305: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var CullTiles = __webpack_require__(30003); +var HexagonalCullTiles = __webpack_require__(9474); +var IsometricCullTiles = __webpack_require__(14018); +var NOOP = __webpack_require__(29747); +var StaggeredCullTiles = __webpack_require__(54503); + +/** + * Gets the correct function to use to cull tiles, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetCullTilesFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to cull tiles for the given map type. + */ +var GetCullTilesFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return CullTiles; + } + else if (orientation === CONST.HEXAGONAL) + { + return HexagonalCullTiles; + } + else if (orientation === CONST.STAGGERED) + { + return StaggeredCullTiles; + } + else if (orientation === CONST.ISOMETRIC) + { + return IsometricCullTiles; + } + else + { + return NOOP; + } +}; + +module.exports = GetCullTilesFunction; + + +/***/ }), + +/***/ 7423: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var IsInLayerBounds = __webpack_require__(62991); + +/** + * Gets a tile at the given tile coordinates from the given layer. + * + * @function Phaser.Tilemaps.Components.GetTileAt + * @since 3.0.0 + * + * @param {number} tileX - X position to get the tile from (given in tile units, not pixels). + * @param {number} tileY - Y position to get the tile from (given in tile units, not pixels). + * @param {boolean} nonNull - For empty tiles, return a Tile object with an index of -1 instead of null. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile} The tile at the given coordinates or null if no tile was found or the coordinates were invalid. + */ +var GetTileAt = function (tileX, tileY, nonNull, layer) +{ + if (IsInLayerBounds(tileX, tileY, layer)) + { + var tile = layer.data[tileY][tileX] || null; + + if (!tile) + { + return null; + } + else if (tile.index === -1) + { + return nonNull ? tile : null; + } + else + { + return tile; + } + } + else + { + return null; + } +}; + +module.exports = GetTileAt; + + +/***/ }), + +/***/ 60540: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTileAt = __webpack_require__(7423); +var Vector2 = __webpack_require__(26099); + +var point = new Vector2(); + +/** + * Gets a tile at the given world coordinates from the given layer. + * + * @function Phaser.Tilemaps.Components.GetTileAtWorldXY + * @since 3.0.0 + * + * @param {number} worldX - X position to get the tile from (given in pixels) + * @param {number} worldY - Y position to get the tile from (given in pixels) + * @param {boolean} nonNull - For empty tiles, return a Tile object with an index of -1 instead of null. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile} The tile at the given coordinates or null if no tile was found or the coordinates were invalid. + */ +var GetTileAtWorldXY = function (worldX, worldY, nonNull, camera, layer) +{ + layer.tilemapLayer.worldToTileXY(worldX, worldY, true, point, camera); + + return GetTileAt(point.x, point.y, nonNull, layer); +}; + +module.exports = GetTileAtWorldXY; + + +/***/ }), + +/***/ 55826: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Gets the corners of the Tile as an array of Vector2s. + * + * @function Phaser.Tilemaps.Components.GetTileCorners + * @since 3.60.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2s corresponding to the world XY location of each tile corner. + */ +var GetTileCorners = function (tileX, tileY, camera, layer) +{ + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + var worldX = 0; + var worldY = 0; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + worldX = tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX); + worldY = (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileWidth *= tilemapLayer.scaleX; + tileHeight *= tilemapLayer.scaleY; + } + + var x = worldX + tileX * tileWidth; + var y = worldY + tileY * tileHeight; + + // Top Left + // Top Right + // Bottom Right + // Bottom Left + + return [ + new Vector2(x, y), + new Vector2(x + tileWidth, y), + new Vector2(x + tileWidth, y + tileHeight), + new Vector2(x, y + tileHeight) + ]; +}; + +module.exports = GetTileCorners; + + +/***/ }), + +/***/ 11758: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var HexagonalGetTileCorners = __webpack_require__(27229); +var NOOP = __webpack_require__(29747); +var GetTileCorners = __webpack_require__(55826); + +/** + * Gets the correct function to use to get the tile corners, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetTileCornersFunction + * @since 3.60.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetTileCornersFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return GetTileCorners; + } + else if (orientation === CONST.ISOMETRIC) + { + return NOOP; + } + else if (orientation === CONST.HEXAGONAL) + { + return HexagonalGetTileCorners; + } + else if (orientation === CONST.STAGGERED) + { + return NOOP; + } + else + { + return NOOP; + } +}; + +module.exports = GetTileCornersFunction; + + +/***/ }), + +/***/ 39167: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var NOOP = __webpack_require__(29747); +var TileToWorldX = __webpack_require__(97281); + +/** + * Gets the correct function to use to translate tiles, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetTileToWorldXFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetTileToWorldXFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return TileToWorldX; + } + else + { + return NOOP; + } +}; + +module.exports = GetTileToWorldXFunction; + + +/***/ }), + +/***/ 62000: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var HexagonalTileToWorldXY = __webpack_require__(19951); +var IsometricTileToWorldXY = __webpack_require__(14127); +var NOOP = __webpack_require__(29747); +var StaggeredTileToWorldXY = __webpack_require__(97202); +var TileToWorldXY = __webpack_require__(70326); + +/** + * Gets the correct function to use to translate tiles, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetTileToWorldXYFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetTileToWorldXYFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return TileToWorldXY; + } + else if (orientation === CONST.ISOMETRIC) + { + return IsometricTileToWorldXY; + } + else if (orientation === CONST.HEXAGONAL) + { + return HexagonalTileToWorldXY; + } + else if (orientation === CONST.STAGGERED) + { + return StaggeredTileToWorldXY; + } + else + { + return NOOP; + } +}; + +module.exports = GetTileToWorldXYFunction; + + +/***/ }), + +/***/ 5984: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var NOOP = __webpack_require__(29747); +var StaggeredTileToWorldY = __webpack_require__(28054); +var TileToWorldY = __webpack_require__(29650); + +/** + * Gets the correct function to use to translate tiles, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetTileToWorldYFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetTileToWorldYFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return TileToWorldY; + } + else if (orientation === CONST.STAGGERED) + { + return StaggeredTileToWorldY; + } + else + { + return NOOP; + } +}; + +module.exports = GetTileToWorldYFunction; + + +/***/ }), + +/***/ 7386: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); + +/** + * Gets the tiles in the given rectangular area (in tile coordinates) of the layer. + * + * This returns an array with references to the Tile instances in, so be aware of + * modifying them directly. + * + * @function Phaser.Tilemaps.Components.GetTilesWithin + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Types.Tilemaps.FilteringOptions} filteringOptions - Optional filters to apply when getting the tiles. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile[]} Array of Tile objects. + */ +var GetTilesWithin = function (tileX, tileY, width, height, filteringOptions, layer) +{ + if (tileX === undefined) { tileX = 0; } + if (tileY === undefined) { tileY = 0; } + if (width === undefined) { width = layer.width; } + if (height === undefined) { height = layer.height; } + if (!filteringOptions) { filteringOptions = {}; } + + var isNotEmpty = GetFastValue(filteringOptions, 'isNotEmpty', false); + var isColliding = GetFastValue(filteringOptions, 'isColliding', false); + var hasInterestingFace = GetFastValue(filteringOptions, 'hasInterestingFace', false); + + // Clip x, y to top left of map, while shrinking width/height to match. + if (tileX < 0) + { + width += tileX; + tileX = 0; + } + + if (tileY < 0) + { + height += tileY; + tileY = 0; + } + + // Clip width and height to bottom right of map. + if (tileX + width > layer.width) + { + width = Math.max(layer.width - tileX, 0); + } + + if (tileY + height > layer.height) + { + height = Math.max(layer.height - tileY, 0); + } + + var results = []; + + for (var ty = tileY; ty < tileY + height; ty++) + { + for (var tx = tileX; tx < tileX + width; tx++) + { + var tile = layer.data[ty][tx]; + + if (tile !== null) + { + if (isNotEmpty && tile.index === -1) + { + continue; + } + + if (isColliding && !tile.collides) + { + continue; + } + + if (hasInterestingFace && !tile.hasInterestingFace) + { + continue; + } + + results.push(tile); + } + } + } + + return results; +}; + +module.exports = GetTilesWithin; + + +/***/ }), + +/***/ 91141: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Geom = __webpack_require__(55738); +var GetTilesWithin = __webpack_require__(7386); +var Intersects = __webpack_require__(91865); +var NOOP = __webpack_require__(29747); +var Vector2 = __webpack_require__(26099); +var CONST = __webpack_require__(91907); + +var TriangleToRectangle = function (triangle, rect) +{ + return Intersects.RectangleToTriangle(rect, triangle); +}; + +var point = new Vector2(); +var pointStart = new Vector2(); +var pointEnd = new Vector2(); + +/** + * Gets the tiles that overlap with the given shape in the given layer. The shape must be a Circle, + * Line, Rectangle or Triangle. The shape should be in world coordinates. + * + * **Note:** This method currently only works with orthogonal tilemap layers. + * + * @function Phaser.Tilemaps.Components.GetTilesWithinShape + * @since 3.0.0 + * + * @param {(Phaser.Geom.Circle|Phaser.Geom.Line|Phaser.Geom.Rectangle|Phaser.Geom.Triangle)} shape - A shape in world (pixel) coordinates + * @param {Phaser.Types.Tilemaps.FilteringOptions} filteringOptions - Optional filters to apply when getting the tiles. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile[]} Array of Tile objects. + */ +var GetTilesWithinShape = function (shape, filteringOptions, camera, layer) +{ + if (layer.orientation !== CONST.ORTHOGONAL) + { + console.warn('GetTilesWithinShape only works with orthogonal tilemaps'); + return []; + } + + if (shape === undefined) { return []; } + + // intersectTest is a function with parameters: shape, rect + var intersectTest = NOOP; + + if (shape instanceof Geom.Circle) + { + intersectTest = Intersects.CircleToRectangle; + } + else if (shape instanceof Geom.Rectangle) + { + intersectTest = Intersects.RectangleToRectangle; + } + else if (shape instanceof Geom.Triangle) + { + intersectTest = TriangleToRectangle; + } + else if (shape instanceof Geom.Line) + { + intersectTest = Intersects.LineToRectangle; + } + + // Top left corner of the shapes's bounding box, rounded down to include partial tiles + layer.tilemapLayer.worldToTileXY(shape.left, shape.top, true, pointStart, camera); + + var xStart = pointStart.x; + var yStart = pointStart.y; + + // Bottom right corner of the shapes's bounding box, rounded up to include partial tiles + layer.tilemapLayer.worldToTileXY(shape.right, shape.bottom, false, pointEnd, camera); + + var xEnd = Math.ceil(pointEnd.x); + var yEnd = Math.ceil(pointEnd.y); + + // Tiles within bounding rectangle of shape. Bounds are forced to be at least 1 x 1 tile in size + // to grab tiles for shapes that don't have a height or width (e.g. a horizontal line). + var width = Math.max(xEnd - xStart, 1); + var height = Math.max(yEnd - yStart, 1); + + var tiles = GetTilesWithin(xStart, yStart, width, height, filteringOptions, layer); + + var tileWidth = layer.tileWidth; + var tileHeight = layer.tileHeight; + + if (layer.tilemapLayer) + { + tileWidth *= layer.tilemapLayer.scaleX; + tileHeight *= layer.tilemapLayer.scaleY; + } + + var results = []; + var tileRect = new Geom.Rectangle(0, 0, tileWidth, tileHeight); + + for (var i = 0; i < tiles.length; i++) + { + var tile = tiles[i]; + + layer.tilemapLayer.tileToWorldXY(tile.x, tile.y, point, camera); + + tileRect.x = point.x; + tileRect.y = point.y; + + if (intersectTest(shape, tileRect)) + { + results.push(tile); + } + } + + return results; +}; + +module.exports = GetTilesWithinShape; + + +/***/ }), + +/***/ 96523: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); +var Vector2 = __webpack_require__(26099); + +var pointStart = new Vector2(); +var pointEnd = new Vector2(); + +/** + * Gets the tiles in the given rectangular area (in world coordinates) of the layer. + * + * @function Phaser.Tilemaps.Components.GetTilesWithinWorldXY + * @since 3.0.0 + * + * @param {number} worldX - The world x coordinate for the top-left of the area. + * @param {number} worldY - The world y coordinate for the top-left of the area. + * @param {number} width - The width of the area. + * @param {number} height - The height of the area. + * @param {Phaser.Types.Tilemaps.FilteringOptions} filteringOptions - Optional filters to apply when getting the tiles. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when factoring in which tiles to return. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile[]} Array of Tile objects. + */ +var GetTilesWithinWorldXY = function (worldX, worldY, width, height, filteringOptions, camera, layer) +{ + var worldToTileXY = layer.tilemapLayer.tilemap._convert.WorldToTileXY; + + // Top left corner of the rect, rounded down to include partial tiles + worldToTileXY(worldX, worldY, true, pointStart, camera, layer); + + var xStart = pointStart.x; + var yStart = pointStart.y; + + // Bottom right corner of the rect, rounded up to include partial tiles + worldToTileXY(worldX + width, worldY + height, false, pointEnd, camera, layer); + + var xEnd = Math.ceil(pointEnd.x); + var yEnd = Math.ceil(pointEnd.y); + + return GetTilesWithin(xStart, yStart, xEnd - xStart, yEnd - yStart, filteringOptions, layer); +}; + +module.exports = GetTilesWithinWorldXY; + + +/***/ }), + +/***/ 96113: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var NULL = __webpack_require__(20242); +var WorldToTileX = __webpack_require__(10095); + +/** + * Gets the correct function to use to translate tiles, based on the map orientation. + * + * Only orthogonal maps support this feature. + * + * @function Phaser.Tilemaps.Components.GetWorldToTileXFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetWorldToTileXFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return WorldToTileX; + } + else + { + return NULL; + } +}; + +module.exports = GetWorldToTileXFunction; + + +/***/ }), + +/***/ 16926: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var HexagonalWorldToTileXY = __webpack_require__(86625); +var IsometricWorldToTileXY = __webpack_require__(96897); +var NOOP = __webpack_require__(29747); +var StaggeredWorldToTileXY = __webpack_require__(15108); +var WorldToTileXY = __webpack_require__(85896); + +/** + * Gets the correct function to use to translate tiles, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetWorldToTileXYFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetWorldToTileXYFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return WorldToTileXY; + } + else if (orientation === CONST.ISOMETRIC) + { + return IsometricWorldToTileXY; + } + else if (orientation === CONST.HEXAGONAL) + { + return HexagonalWorldToTileXY; + } + else if (orientation === CONST.STAGGERED) + { + return StaggeredWorldToTileXY; + } + else + { + return NOOP; + } +}; + +module.exports = GetWorldToTileXYFunction; + + +/***/ }), + +/***/ 55762: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); +var NULL = __webpack_require__(20242); +var StaggeredWorldToTileY = __webpack_require__(51900); +var WorldToTileY = __webpack_require__(63288); + +/** + * Gets the correct function to use to translate tiles, based on the map orientation. + * + * @function Phaser.Tilemaps.Components.GetWorldToTileYFunction + * @since 3.50.0 + * + * @param {number} orientation - The Tilemap orientation constant. + * + * @return {function} The function to use to translate tiles for the given map type. + */ +var GetWorldToTileYFunction = function (orientation) +{ + if (orientation === CONST.ORTHOGONAL) + { + return WorldToTileY; + } + else if (orientation === CONST.STAGGERED) + { + return StaggeredWorldToTileY; + } + else + { + return NULL; + } +}; + +module.exports = GetWorldToTileYFunction; + + +/***/ }), + +/***/ 45091: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var IsInLayerBounds = __webpack_require__(62991); + +/** + * Checks if there is a tile at the given location (in tile coordinates) in the given layer. Returns + * false if there is no tile or if the tile at that location has an index of -1. + * + * @function Phaser.Tilemaps.Components.HasTileAt + * @since 3.0.0 + * + * @param {number} tileX - X position to get the tile from (given in tile units, not pixels). + * @param {number} tileY - Y position to get the tile from (given in tile units, not pixels). + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {?boolean} Returns a boolean, or null if the layer given was invalid. + */ +var HasTileAt = function (tileX, tileY, layer) +{ + if (IsInLayerBounds(tileX, tileY, layer)) + { + var tile = layer.data[tileY][tileX]; + + return (tile !== null && tile.index > -1); + } + else + { + return false; + } +}; + +module.exports = HasTileAt; + + +/***/ }), + +/***/ 24152: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var HasTileAt = __webpack_require__(45091); +var Vector2 = __webpack_require__(26099); + +var point = new Vector2(); + +/** + * Checks if there is a tile at the given location (in world coordinates) in the given layer. Returns + * false if there is no tile or if the tile at that location has an index of -1. + * + * @function Phaser.Tilemaps.Components.HasTileAtWorldXY + * @since 3.0.0 + * + * @param {number} worldX - The X coordinate of the world position. + * @param {number} worldY - The Y coordinate of the world position. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when factoring in which tiles to return. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {?boolean} Returns a boolean, or null if the layer given was invalid. + */ +var HasTileAtWorldXY = function (worldX, worldY, camera, layer) +{ + layer.tilemapLayer.worldToTileXY(worldX, worldY, true, point, camera); + + var tileX = point.x; + var tileY = point.y; + + return HasTileAt(tileX, tileY, layer); +}; + +module.exports = HasTileAtWorldXY; + + +/***/ }), + +/***/ 90454: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SnapCeil = __webpack_require__(63448); +var SnapFloor = __webpack_require__(56583); + +/** + * Returns the bounds in the given layer that are within the camera's viewport. + * This is used internally by the cull tiles function. + * + * @function Phaser.Tilemaps.Components.HexagonalCullBounds + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * + * @return {object} An object containing the `left`, `right`, `top` and `bottom` bounds. + */ +var HexagonalCullBounds = function (layer, camera) +{ + var tilemap = layer.tilemapLayer.tilemap; + var tilemapLayer = layer.tilemapLayer; + + // We need to use the tile sizes defined for the map as a whole, not the layer, + // in order to calculate the bounds correctly. As different sized tiles may be + // placed on the grid and we cannot trust layer.baseTileWidth to give us the true size. + var tileW = Math.floor(tilemap.tileWidth * tilemapLayer.scaleX); + var tileH = Math.floor(tilemap.tileHeight * tilemapLayer.scaleY); + + var len = layer.hexSideLength; + + var boundsLeft; + var boundsRight; + var boundsTop; + var boundsBottom; + + if (layer.staggerAxis === 'y') + { + var rowH = ((tileH - len) / 2 + len); + + boundsLeft = SnapFloor(camera.worldView.x - tilemapLayer.x, tileW, 0, true) - tilemapLayer.cullPaddingX; + boundsRight = SnapCeil(camera.worldView.right - tilemapLayer.x, tileW, 0, true) + tilemapLayer.cullPaddingX; + + boundsTop = SnapFloor(camera.worldView.y - tilemapLayer.y, rowH, 0, true) - tilemapLayer.cullPaddingY; + boundsBottom = SnapCeil(camera.worldView.bottom - tilemapLayer.y, rowH, 0, true) + tilemapLayer.cullPaddingY; + } + else + { + var rowW = ((tileW - len) / 2 + len); + + boundsLeft = SnapFloor(camera.worldView.x - tilemapLayer.x, rowW, 0, true) - tilemapLayer.cullPaddingX; + boundsRight = SnapCeil(camera.worldView.right - tilemapLayer.x, rowW, 0, true) + tilemapLayer.cullPaddingX; + + boundsTop = SnapFloor(camera.worldView.y - tilemapLayer.y, tileH, 0, true) - tilemapLayer.cullPaddingY; + boundsBottom = SnapCeil(camera.worldView.bottom - tilemapLayer.y, tileH, 0, true) + tilemapLayer.cullPaddingY; + } + + return { + left: boundsLeft, + right: boundsRight, + top: boundsTop, + bottom: boundsBottom + }; +}; + +module.exports = HexagonalCullBounds; + + +/***/ }), + +/***/ 9474: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CullBounds = __webpack_require__(90454); +var RunCull = __webpack_require__(32483); + +/** + * Returns the tiles in the given layer that are within the cameras viewport. This is used internally. + * + * @function Phaser.Tilemaps.Components.HexagonalCullTiles + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * @param {array} [outputArray] - An optional array to store the Tile objects within. + * @param {number} [renderOrder=0] - The rendering order constant. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects. + */ +var HexagonalCullTiles = function (layer, camera, outputArray, renderOrder) +{ + if (outputArray === undefined) { outputArray = []; } + if (renderOrder === undefined) { renderOrder = 0; } + + outputArray.length = 0; + + var tilemapLayer = layer.tilemapLayer; + + // Camera world view bounds, snapped for scaled tile size + // Cull Padding values are given in tiles, not pixels + + var bounds = CullBounds(layer, camera); + + if (tilemapLayer.skipCull && tilemapLayer.scrollFactorX === 1 && tilemapLayer.scrollFactorY === 1) + { + bounds.left = 0; + bounds.right = layer.width; + bounds.top = 0; + bounds.bottom = layer.height; + } + + RunCull(layer, bounds, renderOrder, outputArray); + + return outputArray; +}; + +module.exports = HexagonalCullTiles; + + +/***/ }), + +/***/ 27229: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var HexagonalTileToWorldXY = __webpack_require__(19951); +var Vector2 = __webpack_require__(26099); + +var tempVec = new Vector2(); + +/** + * Gets the corners of the Hexagonal Tile as an array of Vector2s. + * + * @function Phaser.Tilemaps.Components.HexagonalGetTileCorners + * @since 3.60.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2[]} An array of Vector2s corresponding to the world XY location of each tile corner. + */ +var HexagonalGetTileCorners = function (tileX, tileY, camera, layer) +{ + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + if (tilemapLayer) + { + tileWidth *= tilemapLayer.scaleX; + tileHeight *= tilemapLayer.scaleY; + } + + // Sets the center of the tile into tempVec + var center = HexagonalTileToWorldXY(tileX, tileY, tempVec, camera, layer); + + var corners = []; + + // Hard-coded orientation values for Pointy-Top Hexagons only + var b0 = 0.5773502691896257; // Math.sqrt(3) / 3 + + var hexWidth; + var hexHeight; + + if (layer.staggerAxis === 'y') + { + hexWidth = b0 * tileWidth; + hexHeight = tileHeight / 2; + } + else + { + hexWidth = tileWidth / 2; + hexHeight = b0 * tileHeight; + } + + for (var i = 0; i < 6; i++) + { + var angle = 2 * Math.PI * (0.5 - i) / 6; + + corners.push(new Vector2(center.x + (hexWidth * Math.cos(angle)), center.y + (hexHeight * Math.sin(angle)))); + } + + return corners; +}; + +module.exports = HexagonalGetTileCorners; + + +/***/ }), + +/***/ 19951: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from hexagonal tile XY coordinates (tile units) to world XY coordinates (pixels), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.HexagonalTileToWorldXY + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in world coordinates. + */ +var HexagonalTileToWorldXY = function (tileX, tileY, point, camera, layer) +{ + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + var worldX = 0; + var worldY = 0; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + worldX = tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX); + worldY = tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY); + + tileWidth *= tilemapLayer.scaleX; + tileHeight *= tilemapLayer.scaleY; + } + + // Hard-coded orientation values for Pointy-Top Hexagons only + + // origin + var tileWidthHalf = tileWidth / 2; + var tileHeightHalf = tileHeight / 2; + + var x; + var y; + var staggerAxis = layer.staggerAxis; + var staggerIndex = layer.staggerIndex; + + if (staggerAxis === 'y') + { + x = worldX + (tileWidth * tileX) + tileWidth; + y = worldY + ((1.5 * tileY) * tileHeightHalf) + tileHeightHalf; + + if (tileY % 2 === 0) + { + if (staggerIndex === 'odd') + { + x -= tileWidthHalf; + } + else + { + x += tileWidthHalf; + } + } + } + else if ((staggerAxis === 'x') && (staggerIndex === 'odd')) + { + x = worldX + ((1.5 * tileX) * tileWidthHalf) + tileWidthHalf; + y = worldY + (tileHeight * tileX) + tileHeight; + + if (tileX % 2 === 0) + { + if (staggerIndex === 'odd') + { + y -= tileHeightHalf; + } + else + { + y += tileHeightHalf; + } + } + } + + return point.set(x, y); +}; + +module.exports = HexagonalTileToWorldXY; + + +/***/ }), + +/***/ 86625: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from world XY coordinates (pixels) to hexagonal tile XY coordinates (tile units), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.HexagonalWorldToTileXY + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinates down to the nearest integer. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in tile units. + */ +var HexagonalWorldToTileXY = function (worldX, worldY, snapToFloor, point, camera, layer) +{ + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's vertical scroll + + worldX = worldX - (tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX)); + worldY = worldY - (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileWidth *= tilemapLayer.scaleX; + tileHeight *= tilemapLayer.scaleY; + } + + // Hard-coded orientation values for Pointy-Top Hexagons only + var b0 = 0.5773502691896257; // Math.sqrt(3) / 3 + var b1 = -0.3333333333333333; // -1 / 3 + var b2 = 0; + var b3 = 0.6666666666666666; // 2 / 3 + + // origin + var tileWidthHalf = tileWidth / 2; + var tileHeightHalf = tileHeight / 2; + + var px; + var py; + var q; + var r; + var s; + + // size + if (layer.staggerAxis === 'y') + { + // x = b0 * tileWidth + // y = tileHeightHalf + px = (worldX - tileWidthHalf) / (b0 * tileWidth); + py = (worldY - tileHeightHalf) / tileHeightHalf; + + q = b0 * px + b1 * py; + r = b2 * px + b3 * py; + } + else + { + // x = tileWidthHalf + // y = b0 * tileHeight + px = (worldX - tileWidthHalf) / tileWidthHalf; + py = (worldY - tileHeightHalf) / (b0 * tileHeight); + + q = b1 * px + b0 * py; + r = b3 * px + b2 * py; + } + + s = -q - r; + + var qi = Math.round(q); + var ri = Math.round(r); + var si = Math.round(s); + + var qDiff = Math.abs(qi - q); + var rDiff = Math.abs(ri - r); + var sDiff = Math.abs(si - s); + + if (qDiff > rDiff && qDiff > sDiff) + { + qi = -ri - si; + } + else if (rDiff > sDiff) + { + ri = -qi - si; + } + + var x; + var y = ri; + + if (layer.staggerIndex === 'odd') + { + x = (y % 2 === 0) ? (ri / 2) + qi : (ri / 2) + qi - 0.5; + } + else + { + x = (y % 2 === 0) ? (ri / 2) + qi : (ri / 2) + qi + 0.5; + } + + return point.set(x, y); +}; + +module.exports = HexagonalWorldToTileXY; + + +/***/ }), + +/***/ 62991: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if the given tile coordinates are within the bounds of the layer. + * + * @function Phaser.Tilemaps.Components.IsInLayerBounds + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {boolean} `true` if the tile coordinates are within the bounds of the layer, otherwise `false`. + */ +var IsInLayerBounds = function (tileX, tileY, layer) +{ + return (tileX >= 0 && tileX < layer.width && tileY >= 0 && tileY < layer.height); +}; + +module.exports = IsInLayerBounds; + + +/***/ }), + +/***/ 14018: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CheckIsoBounds = __webpack_require__(33528); + +/** + * Returns the tiles in the given layer that are within the cameras viewport. This is used internally. + * + * @function Phaser.Tilemaps.Components.IsometricCullTiles + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * @param {array} [outputArray] - An optional array to store the Tile objects within. + * @param {number} [renderOrder=0] - The rendering order constant. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects. + */ +var IsometricCullTiles = function (layer, camera, outputArray, renderOrder) +{ + if (outputArray === undefined) { outputArray = []; } + if (renderOrder === undefined) { renderOrder = 0; } + + outputArray.length = 0; + + var tilemapLayer = layer.tilemapLayer; + + var mapData = layer.data; + var mapWidth = layer.width; + var mapHeight = layer.height; + var skipCull = tilemapLayer.skipCull; + + var drawLeft = 0; + var drawRight = mapWidth; + var drawTop = 0; + var drawBottom = mapHeight; + + var x; + var y; + var tile; + + if (renderOrder === 0) + { + // right-down + + for (y = drawTop; y < drawBottom; y++) + { + for (x = drawLeft; x < drawRight; x++) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + if (!skipCull && !CheckIsoBounds(x, y, layer, camera)) + { + continue; + } + + outputArray.push(tile); + } + } + } + else if (renderOrder === 1) + { + // left-down + + for (y = drawTop; y < drawBottom; y++) + { + for (x = drawRight; x >= drawLeft; x--) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + if (!skipCull && !CheckIsoBounds(x, y, layer, camera)) + { + continue; + } + + outputArray.push(tile); + } + } + } + else if (renderOrder === 2) + { + // right-up + + for (y = drawBottom; y >= drawTop; y--) + { + for (x = drawLeft; x < drawRight; x++) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + if (!skipCull && !CheckIsoBounds(x, y, layer, camera)) + { + continue; + } + + outputArray.push(tile); + } + } + } + else if (renderOrder === 3) + { + // left-up + + for (y = drawBottom; y >= drawTop; y--) + { + for (x = drawRight; x >= drawLeft; x--) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + if (!skipCull && !CheckIsoBounds(x, y, layer, camera)) + { + continue; + } + + outputArray.push(tile); + } + } + } + + tilemapLayer.tilesDrawn = outputArray.length; + tilemapLayer.tilesTotal = mapWidth * mapHeight; + + return outputArray; +}; + +module.exports = IsometricCullTiles; + + +/***/ }), + +/***/ 14127: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from isometric tile XY coordinates (tile units) to world XY coordinates (pixels), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.IsometricTileToWorldXY + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in world coordinates. + */ +var IsometricTileToWorldXY = function (tileX, tileY, point, camera, layer) +{ + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + var layerWorldX = 0; + var layerWorldY = 0; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + layerWorldX = tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX); + + tileWidth *= tilemapLayer.scaleX; + + layerWorldY = (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + } + + var x = layerWorldX + (tileX - tileY) * (tileWidth / 2); + var y = layerWorldY + (tileX + tileY) * (tileHeight / 2); + + return point.set(x, y); +}; + +module.exports = IsometricTileToWorldXY; + + +/***/ }), + +/***/ 96897: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from world XY coordinates (pixels) to isometric tile XY coordinates (tile units), factoring in the + * layers position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.IsometricWorldToTileXY + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {boolean} [originTop=true] - Which is the active face of the isometric tile? The top (default, true), or the base? (false) + * + * @return {Phaser.Math.Vector2} The XY location in tile units. + */ +var IsometricWorldToTileXY = function (worldX, worldY, snapToFloor, point, camera, layer, originTop) +{ + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's vertical scroll + + worldY = worldY - (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's horizontal scroll + + worldX = worldX - (tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX)); + + tileWidth *= tilemapLayer.scaleX; + } + + var tileWidthHalf = tileWidth / 2; + var tileHeightHalf = tileHeight / 2; + + worldX = worldX - tileWidthHalf; + + if (!originTop) + { + worldY = worldY - tileHeight; + } + + var x = 0.5 * (worldX / tileWidthHalf + worldY / tileHeightHalf); + var y = 0.5 * (-worldX / tileWidthHalf + worldY / tileHeightHalf); + + if (snapToFloor) + { + x = Math.floor(x); + y = Math.floor(y); + } + + return point.set(x, y); +}; + +module.exports = IsometricWorldToTileXY; + + +/***/ }), + +/***/ 71558: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Tile = __webpack_require__(23029); +var IsInLayerBounds = __webpack_require__(62991); +var CalculateFacesAt = __webpack_require__(72023); +var SetTileCollision = __webpack_require__(20576); + +/** + * Puts a tile at the given tile coordinates in the specified layer. You can pass in either an index + * or a Tile object. If you pass in a Tile, all attributes will be copied over to the specified + * location. If you pass in an index, only the index at the specified location will be changed. + * Collision information will be recalculated at the specified location. + * + * @function Phaser.Tilemaps.Components.PutTileAt + * @since 3.0.0 + * + * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object. + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was created or added to this map. + */ +var PutTileAt = function (tile, tileX, tileY, recalculateFaces, layer) +{ + if (recalculateFaces === undefined) { recalculateFaces = true; } + + if (!IsInLayerBounds(tileX, tileY, layer)) + { + return null; + } + + var index; + var oldTile = layer.data[tileY][tileX]; + var oldTileCollides = oldTile && oldTile.collides; + + if (tile instanceof Tile) + { + if (layer.data[tileY][tileX] === null) + { + layer.data[tileY][tileX] = new Tile(layer, tile.index, tileX, tileY, layer.tileWidth, layer.tileHeight); + } + + layer.data[tileY][tileX].copy(tile); + } + else + { + index = tile; + + if (layer.data[tileY][tileX] === null) + { + layer.data[tileY][tileX] = new Tile(layer, index, tileX, tileY, layer.tileWidth, layer.tileHeight); + } + else + { + layer.data[tileY][tileX].index = index; + } + } + + // Updating colliding flag on the new tile + var newTile = layer.data[tileY][tileX]; + var collides = layer.collideIndexes.indexOf(newTile.index) !== -1; + + index = tile instanceof Tile ? tile.index : tile; + + if (index === -1) + { + newTile.width = layer.tileWidth; + newTile.height = layer.tileHeight; + } + else + { + var tilemap = layer.tilemapLayer.tilemap; + var tiles = tilemap.tiles; + var sid = tiles[index][2]; + var set = tilemap.tilesets[sid]; + + newTile.width = set.tileWidth; + newTile.height = set.tileHeight; + } + + SetTileCollision(newTile, collides); + + // Recalculate faces only if the colliding flag at (tileX, tileY) has changed + if (recalculateFaces && (oldTileCollides !== newTile.collides)) + { + CalculateFacesAt(tileX, tileY, layer); + } + + return newTile; +}; + +module.exports = PutTileAt; + + +/***/ }), + +/***/ 26303: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var PutTileAt = __webpack_require__(71558); +var Vector2 = __webpack_require__(26099); + +var point = new Vector2(); + +/** + * Puts a tile at the given world coordinates (pixels) in the specified layer. You can pass in either + * an index or a Tile object. If you pass in a Tile, all attributes will be copied over to the + * specified location. If you pass in an index, only the index at the specified location will be + * changed. Collision information will be recalculated at the specified location. + * + * @function Phaser.Tilemaps.Components.PutTileAtWorldXY + * @since 3.0.0 + * + * @param {(number|Phaser.Tilemaps.Tile)} tile - The index of this tile to set or a Tile object. + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was created or added to this map. + */ +var PutTileAtWorldXY = function (tile, worldX, worldY, recalculateFaces, camera, layer) +{ + layer.tilemapLayer.worldToTileXY(worldX, worldY, true, point, camera, layer); + + return PutTileAt(tile, point.x, point.y, recalculateFaces, layer); +}; + +module.exports = PutTileAtWorldXY; + + +/***/ }), + +/***/ 14051: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CalculateFacesWithin = __webpack_require__(42573); +var PutTileAt = __webpack_require__(71558); + +/** + * Puts an array of tiles or a 2D array of tiles at the given tile coordinates in the specified + * layer. The array can be composed of either tile indexes or Tile objects. If you pass in a Tile, + * all attributes will be copied over to the specified location. If you pass in an index, only the + * index at the specified location will be changed. Collision information will be recalculated + * within the region tiles were changed. + * + * @function Phaser.Tilemaps.Components.PutTilesAt + * @since 3.0.0 + * + * @param {(number[]|number[][]|Phaser.Tilemaps.Tile[]|Phaser.Tilemaps.Tile[][])} tile - A row (array) or grid (2D array) of Tiles or tile indexes to place. + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var PutTilesAt = function (tilesArray, tileX, tileY, recalculateFaces, layer) +{ + if (recalculateFaces === undefined) { recalculateFaces = true; } + + if (!Array.isArray(tilesArray)) + { + return null; + } + + // Force the input array to be a 2D array + if (!Array.isArray(tilesArray[0])) + { + tilesArray = [ tilesArray ]; + } + + var height = tilesArray.length; + var width = tilesArray[0].length; + + for (var ty = 0; ty < height; ty++) + { + for (var tx = 0; tx < width; tx++) + { + var tile = tilesArray[ty][tx]; + + PutTileAt(tile, tileX + tx, tileY + ty, false, layer); + } + } + + if (recalculateFaces) + { + // Recalculate the faces within the destination area and neighboring tiles + CalculateFacesWithin(tileX - 1, tileY - 1, width + 2, height + 2, layer); + } +}; + +module.exports = PutTilesAt; + + +/***/ }), + +/***/ 77389: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); +var GetRandom = __webpack_require__(26546); + +/** + * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the + * specified layer. Each tile will receive a new index. If an array of indexes is passed in, then + * those will be used for randomly assigning new tile indexes. If an array is not provided, the + * indexes found within the region (excluding -1) will be used for randomly assigning new tile + * indexes. This method only modifies tile indexes and does not change collision information. + * + * @function Phaser.Tilemaps.Components.Randomize + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {number[]} indexes - An array of indexes to randomly draw from during randomization. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var Randomize = function (tileX, tileY, width, height, indexes, layer) +{ + var i; + var tiles = GetTilesWithin(tileX, tileY, width, height, {}, layer); + + // If no indices are given, then find all the unique indexes within the specified region + if (!indexes) + { + indexes = []; + + for (i = 0; i < tiles.length; i++) + { + if (indexes.indexOf(tiles[i].index) === -1) + { + indexes.push(tiles[i].index); + } + } + } + + for (i = 0; i < tiles.length; i++) + { + tiles[i].index = GetRandom(indexes); + } +}; + +module.exports = Randomize; + + +/***/ }), + +/***/ 63557: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Tile = __webpack_require__(23029); +var IsInLayerBounds = __webpack_require__(62991); +var CalculateFacesAt = __webpack_require__(72023); + +/** + * Removes the tile at the given tile coordinates in the specified layer and updates the layer's + * collision information. + * + * @function Phaser.Tilemaps.Components.RemoveTileAt + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate. + * @param {number} tileY - The y coordinate. + * @param {boolean} replaceWithNull - If true, this will replace the tile at the specified location with null instead of a Tile with an index of -1. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was removed. + */ +var RemoveTileAt = function (tileX, tileY, replaceWithNull, recalculateFaces, layer) +{ + if (replaceWithNull === undefined) { replaceWithNull = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + if (!IsInLayerBounds(tileX, tileY, layer)) + { + return null; + } + + var tile = layer.data[tileY][tileX]; + + if (!tile) + { + return null; + } + else + { + layer.data[tileY][tileX] = (replaceWithNull) ? null : new Tile(layer, -1, tileX, tileY, layer.tileWidth, layer.tileHeight); + } + + // Recalculate faces only if the removed tile was a colliding tile + if (recalculateFaces && tile && tile.collides) + { + CalculateFacesAt(tileX, tileY, layer); + } + + return tile; +}; + +module.exports = RemoveTileAt; + + +/***/ }), + +/***/ 94178: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RemoveTileAt = __webpack_require__(63557); +var Vector2 = __webpack_require__(26099); + +var point = new Vector2(); + +/** + * Removes the tile at the given world coordinates in the specified layer and updates the layer's + * collision information. + * + * @function Phaser.Tilemaps.Components.RemoveTileAtWorldXY + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate, in pixels. + * @param {number} worldY - The y coordinate, in pixels. + * @param {boolean} replaceWithNull - If true, this will replace the tile at the specified location with null instead of a Tile with an index of -1. + * @param {boolean} recalculateFaces - `true` if the faces data should be recalculated. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Tilemaps.Tile} The Tile object that was removed. + */ +var RemoveTileAtWorldXY = function (worldX, worldY, replaceWithNull, recalculateFaces, camera, layer) +{ + layer.tilemapLayer.worldToTileXY(worldX, worldY, true, point, camera, layer); + + return RemoveTileAt(point.x, point.y, replaceWithNull, recalculateFaces, layer); +}; + +module.exports = RemoveTileAtWorldXY; + + +/***/ }), + +/***/ 15533: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); +var Color = __webpack_require__(3956); + +var defaultTileColor = new Color(105, 210, 231, 150); +var defaultCollidingTileColor = new Color(243, 134, 48, 200); +var defaultFaceColor = new Color(40, 39, 37, 150); + +/** + * Draws a debug representation of the layer to the given Graphics. This is helpful when you want to + * get a quick idea of which of your tiles are colliding and which have interesting faces. The tiles + * are drawn starting at (0, 0) in the Graphics, allowing you to place the debug representation + * wherever you want on the screen. + * + * @function Phaser.Tilemaps.Components.RenderDebug + * @since 3.0.0 + * + * @param {Phaser.GameObjects.Graphics} graphics - The target Graphics object to draw upon. + * @param {Phaser.Types.Tilemaps.DebugStyleOptions} styleConfig - An object specifying the colors to use for the debug drawing. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var RenderDebug = function (graphics, styleConfig, layer) +{ + if (styleConfig === undefined) { styleConfig = {}; } + + // Default colors without needlessly creating Color objects + var tileColor = (styleConfig.tileColor !== undefined) ? styleConfig.tileColor : defaultTileColor; + var collidingTileColor = (styleConfig.collidingTileColor !== undefined) ? styleConfig.collidingTileColor : defaultCollidingTileColor; + var faceColor = (styleConfig.faceColor !== undefined) ? styleConfig.faceColor : defaultFaceColor; + + var tiles = GetTilesWithin(0, 0, layer.width, layer.height, null, layer); + + graphics.translateCanvas(layer.tilemapLayer.x, layer.tilemapLayer.y); + graphics.scaleCanvas(layer.tilemapLayer.scaleX, layer.tilemapLayer.scaleY); + + for (var i = 0; i < tiles.length; i++) + { + var tile = tiles[i]; + + var offset = tile.tileset ? tile.tileset.tileOffset : { x: 0, y: 0 }; + var tw = tile.width; + var th = tile.height; + var x = tile.pixelX - offset.x; + var y = tile.pixelY - offset.y; + + var color = tile.collides ? collidingTileColor : tileColor; + + if (color !== null) + { + graphics.fillStyle(color.color, color.alpha / 255); + graphics.fillRect(x, y, tw, th); + } + + // Inset the face line to prevent neighboring tile's lines from overlapping + x += 1; + y += 1; + tw -= 2; + th -= 2; + + if (faceColor !== null) + { + graphics.lineStyle(1, faceColor.color, faceColor.alpha / 255); + + if (tile.faceTop) { graphics.lineBetween(x, y, x + tw, y); } + if (tile.faceRight) { graphics.lineBetween(x + tw, y, x + tw, y + th); } + if (tile.faceBottom) { graphics.lineBetween(x, y + th, x + tw, y + th); } + if (tile.faceLeft) { graphics.lineBetween(x, y, x, y + th); } + } + } +}; + +module.exports = RenderDebug; + +/** + +function Orientation(f0, f1, f2, f3, b0, b1, b2, b3, start_angle) { + return {f0: f0, f1: f1, f2: f2, f3: f3, b0: b0, b1: b1, b2: b2, b3: b3, start_angle: start_angle}; +} + +function Layout(orientation, size, origin) { + return {orientation: orientation, size: size, origin: origin}; +} + +function Hex(q, r, s) { + return {q: q, r: r, s: s}; +} + +function hex_round(h) +{ + var qi = Math.round(h.q); + var ri = Math.round(h.r); + var si = Math.round(h.s); + var q_diff = Math.abs(qi - h.q); + var r_diff = Math.abs(ri - h.r); + var s_diff = Math.abs(si - h.s); + if (q_diff > r_diff && q_diff > s_diff) + { + qi = -ri - si; + } + else + if (r_diff > s_diff) + { + ri = -qi - si; + } + else + { + si = -qi - ri; + } + return Hex(qi, ri, si); +} + +var layout_pointy = Orientation(Math.sqrt(3.0), Math.sqrt(3.0) / 2.0, 0.0, 3.0 / 2.0, Math.sqrt(3.0) / 3.0, -1.0 / 3.0, 0.0, 2.0 / 3.0, 0.5); + +function OffsetCoord(col, row) { + return {col: col, row: row}; +} + +var EVEN = 1; +var ODD = -1; + +function roffset_from_cube(offset, h) +{ + var col = h.q + (h.r + offset * (h.r & 1)) / 2; + var row = h.r; + return OffsetCoord(col, row); +} + +function roffset_to_cube(offset, h) +{ + var q = h.col - (h.row + offset * (h.row & 1)) / 2; + var r = h.row; + var s = -q - r; + return Hex(q, r, s); +} + +function hex_to_pixel(layout, h) +{ + var M = layout.orientation; + var size = layout.size; + var origin = layout.origin; + var x = (M.f0 * h.q + M.f1 * h.r) * size.x; + var y = (M.f2 * h.q + M.f3 * h.r) * size.y; + return new Vector2(x + origin.x, y + origin.y); +} + +function hex_corner_offset(layout, corner) +{ + var M = layout.orientation; + var size = layout.size; + var angle = 2.0 * Math.PI * (M.start_angle - corner) / 6.0; + return new Vector2(size.x * Math.cos(angle), size.y * Math.sin(angle)); +} + +function polygon_corners(layout, h) +{ + var corners = []; + var center = hex_to_pixel(layout, h); + for (var i = 0; i < 6; i++) + { + var offset = hex_corner_offset(layout, i); + corners.push(new Vector2(center.x + offset.x, center.y + offset.y)); + } + return corners; +} + +var layout = Layout(layout_pointy, new Vector2(tileHeight/2, tileWidth/2), new Vector2(tileWidth/2, tileWidth/2)); + +for (var q = 0; q <= 9; q++) +{ + for (var r = 0; r <= 9; r++) + { + var h = Hex(q, r, -q - r); // cubed + // var hr = hex_round(h); + // var o = roffset_from_cube(ODD, hr); + // var b = roffset_to_cube(ODD, o); + + var c = polygon_corners(layout, h); + + if (q === 0 && r === 0) + { + console.log(c); + } + + g.beginPath(); + g.moveTo(Math.floor(c[0].x), Math.floor(c[0].y)); + + for (var i = 1; i < c.length; i++) + { + g.lineTo(Math.floor(c[i].x), Math.floor(c[i].y)); + } + + g.closePath(); + g.strokePath(); + } +} + + var c = polygon_corners(layout, hr); + + g.beginPath(); + g.moveTo(Math.floor(c[0].x), Math.floor(c[0].y)); + + for (var i = 1; i < c.length; i++) + { + g.lineTo(Math.floor(c[i].x), Math.floor(c[i].y)); + } + + g.closePath(); + g.fillPath(); + + // g.scene.add.text(c[3].x + 2, c[3].y + 6, `${hr.q} x ${hr.r}`); + g.scene.add.text(c[3].x + 2, c[3].y + 6, `${x} x ${y}`); + + +*/ + + +/***/ }), + +/***/ 27987: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); + +/** + * Scans the given rectangular area (given in tile coordinates) for tiles with an index matching + * `findIndex` and updates their index to match `newIndex`. This only modifies the index and does + * not change collision information. + * + * @function Phaser.Tilemaps.Components.ReplaceByIndex + * @since 3.0.0 + * + * @param {number} findIndex - The index of the tile to search for. + * @param {number} newIndex - The index of the tile to replace it with. + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var ReplaceByIndex = function (findIndex, newIndex, tileX, tileY, width, height, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + for (var i = 0; i < tiles.length; i++) + { + if (tiles[i] && tiles[i].index === findIndex) + { + tiles[i].index = newIndex; + } + } +}; + +module.exports = ReplaceByIndex; + + +/***/ }), + +/***/ 32483: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns the tiles in the given layer that are within the cameras viewport. This is used internally. + * + * @function Phaser.Tilemaps.Components.RunCull + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {object} bounds - An object containing the `left`, `right`, `top` and `bottom` bounds. + * @param {number} renderOrder - The rendering order constant. + * @param {array} outputArray - The array to store the Tile objects within. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects. + */ +var RunCull = function (layer, bounds, renderOrder, outputArray) +{ + var mapData = layer.data; + var mapWidth = layer.width; + var mapHeight = layer.height; + + var tilemapLayer = layer.tilemapLayer; + + var drawLeft = Math.max(0, bounds.left); + var drawRight = Math.min(mapWidth, bounds.right); + var drawTop = Math.max(0, bounds.top); + var drawBottom = Math.min(mapHeight, bounds.bottom); + + var x; + var y; + var tile; + + if (renderOrder === 0) + { + // right-down + + for (y = drawTop; y < drawBottom; y++) + { + for (x = drawLeft; mapData[y] && x < drawRight; x++) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + outputArray.push(tile); + } + } + } + else if (renderOrder === 1) + { + // left-down + + for (y = drawTop; y < drawBottom; y++) + { + for (x = drawRight; mapData[y] && x >= drawLeft; x--) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + outputArray.push(tile); + } + } + } + else if (renderOrder === 2) + { + // right-up + + for (y = drawBottom; y >= drawTop; y--) + { + for (x = drawLeft; mapData[y] && x < drawRight; x++) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + outputArray.push(tile); + } + } + } + else if (renderOrder === 3) + { + // left-up + + for (y = drawBottom; y >= drawTop; y--) + { + for (x = drawRight; mapData[y] && x >= drawLeft; x--) + { + tile = mapData[y][x]; + + if (!tile || tile.index === -1 || !tile.visible || tile.alpha === 0) + { + continue; + } + + outputArray.push(tile); + } + } + } + + tilemapLayer.tilesDrawn = outputArray.length; + tilemapLayer.tilesTotal = mapWidth * mapHeight; + + return outputArray; +}; + +module.exports = RunCull; + + +/***/ }), + +/***/ 57068: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTileCollision = __webpack_require__(20576); +var CalculateFacesWithin = __webpack_require__(42573); +var SetLayerCollisionIndex = __webpack_require__(9589); + +/** + * Sets collision on the given tile or tiles within a layer by index. You can pass in either a + * single numeric index or an array of indexes: [2, 3, 15, 20]. The `collides` parameter controls if + * collision will be enabled (true) or disabled (false). + * + * @function Phaser.Tilemaps.Components.SetCollision + * @since 3.0.0 + * + * @param {(number|array)} indexes - Either a single tile index, or an array of tile indexes. + * @param {boolean} collides - If true it will enable collision. If false it will clear collision. + * @param {boolean} recalculateFaces - Whether or not to recalculate the tile faces after the update. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to false if no tiles have been placed for significant performance boost. + */ +var SetCollision = function (indexes, collides, recalculateFaces, layer, updateLayer) +{ + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + if (updateLayer === undefined) { updateLayer = true; } + + if (!Array.isArray(indexes)) + { + indexes = [ indexes ]; + } + + // Update the array of colliding indexes + for (var i = 0; i < indexes.length; i++) + { + SetLayerCollisionIndex(indexes[i], collides, layer); + } + + // Update the tiles + if (updateLayer) + { + for (var ty = 0; ty < layer.height; ty++) + { + for (var tx = 0; tx < layer.width; tx++) + { + var tile = layer.data[ty][tx]; + + if (tile && indexes.indexOf(tile.index) !== -1) + { + SetTileCollision(tile, collides); + } + } + } + } + + if (recalculateFaces) + { + CalculateFacesWithin(0, 0, layer.width, layer.height, layer); + } +}; + +module.exports = SetCollision; + + +/***/ }), + +/***/ 37266: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTileCollision = __webpack_require__(20576); +var CalculateFacesWithin = __webpack_require__(42573); +var SetLayerCollisionIndex = __webpack_require__(9589); + +/** + * Sets collision on a range of tiles in a layer whose index is between the specified `start` and + * `stop` (inclusive). Calling this with a start value of 10 and a stop value of 14 would set + * collision for tiles 10, 11, 12, 13 and 14. The `collides` parameter controls if collision will be + * enabled (true) or disabled (false). + * + * @function Phaser.Tilemaps.Components.SetCollisionBetween + * @since 3.0.0 + * + * @param {number} start - The first index of the tile to be set for collision. + * @param {number} stop - The last index of the tile to be set for collision. + * @param {boolean} collides - If true it will enable collision. If false it will clear collision. + * @param {boolean} recalculateFaces - Whether or not to recalculate the tile faces after the update. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {boolean} [updateLayer=true] - If true, updates the current tiles on the layer. Set to false if no tiles have been placed for significant performance boost. + */ +var SetCollisionBetween = function (start, stop, collides, recalculateFaces, layer, updateLayer) +{ + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + if (updateLayer === undefined) { updateLayer = true; } + + if (start > stop) + { + return; + } + + // Update the array of colliding indexes + for (var index = start; index <= stop; index++) + { + SetLayerCollisionIndex(index, collides, layer); + } + + // Update the tiles + if (updateLayer) + { + for (var ty = 0; ty < layer.height; ty++) + { + for (var tx = 0; tx < layer.width; tx++) + { + var tile = layer.data[ty][tx]; + + if (tile) + { + if (tile.index >= start && tile.index <= stop) + { + SetTileCollision(tile, collides); + } + } + } + } + } + + if (recalculateFaces) + { + CalculateFacesWithin(0, 0, layer.width, layer.height, layer); + } +}; + +module.exports = SetCollisionBetween; + + +/***/ }), + +/***/ 75661: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTileCollision = __webpack_require__(20576); +var CalculateFacesWithin = __webpack_require__(42573); +var SetLayerCollisionIndex = __webpack_require__(9589); + +/** + * Sets collision on all tiles in the given layer, except for tiles that have an index specified in + * the given array. The `collides` parameter controls if collision will be enabled (true) or + * disabled (false). Tile indexes not currently in the layer are not affected. + * + * @function Phaser.Tilemaps.Components.SetCollisionByExclusion + * @since 3.0.0 + * + * @param {number[]} indexes - An array of the tile indexes to not be counted for collision. + * @param {boolean} collides - If true it will enable collision. If false it will clear collision. + * @param {boolean} recalculateFaces - Whether or not to recalculate the tile faces after the update. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SetCollisionByExclusion = function (indexes, collides, recalculateFaces, layer) +{ + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + if (!Array.isArray(indexes)) + { + indexes = [ indexes ]; + } + + // Note: this only updates layer.collideIndexes for tile indexes found currently in the layer + for (var ty = 0; ty < layer.height; ty++) + { + for (var tx = 0; tx < layer.width; tx++) + { + var tile = layer.data[ty][tx]; + + if (tile && indexes.indexOf(tile.index) === -1) + { + SetTileCollision(tile, collides); + SetLayerCollisionIndex(tile.index, collides, layer); + } + } + } + + if (recalculateFaces) + { + CalculateFacesWithin(0, 0, layer.width, layer.height, layer); + } +}; + +module.exports = SetCollisionByExclusion; + + +/***/ }), + +/***/ 64740: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTileCollision = __webpack_require__(20576); +var CalculateFacesWithin = __webpack_require__(42573); +var HasValue = __webpack_require__(97022); + +/** + * Sets collision on the tiles within a layer by checking tile properties. If a tile has a property + * that matches the given properties object, its collision flag will be set. The `collides` + * parameter controls if collision will be enabled (true) or disabled (false). Passing in + * `{ collides: true }` would update the collision flag on any tiles with a "collides" property that + * has a value of true. Any tile that doesn't have "collides" set to true will be ignored. You can + * also use an array of values, e.g. `{ types: ["stone", "lava", "sand" ] }`. If a tile has a + * "types" property that matches any of those values, its collision flag will be updated. + * + * @function Phaser.Tilemaps.Components.SetCollisionByProperty + * @since 3.0.0 + * + * @param {object} properties - An object with tile properties and corresponding values that should be checked. + * @param {boolean} collides - If true it will enable collision. If false it will clear collision. + * @param {boolean} recalculateFaces - Whether or not to recalculate the tile faces after the update. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SetCollisionByProperty = function (properties, collides, recalculateFaces, layer) +{ + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + for (var ty = 0; ty < layer.height; ty++) + { + for (var tx = 0; tx < layer.width; tx++) + { + var tile = layer.data[ty][tx]; + + if (!tile) { continue; } + + for (var property in properties) + { + if (!HasValue(tile.properties, property)) { continue; } + + var values = properties[property]; + + if (!Array.isArray(values)) + { + values = [ values ]; + } + + for (var i = 0; i < values.length; i++) + { + if (tile.properties[property] === values[i]) + { + SetTileCollision(tile, collides); + } + } + } + } + } + + if (recalculateFaces) + { + CalculateFacesWithin(0, 0, layer.width, layer.height, layer); + } +}; + +module.exports = SetCollisionByProperty; + + +/***/ }), + +/***/ 63307: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SetTileCollision = __webpack_require__(20576); +var CalculateFacesWithin = __webpack_require__(42573); + +/** + * Sets collision on the tiles within a layer by checking each tile's collision group data + * (typically defined in Tiled within the tileset collision editor). If any objects are found within + * a tile's collision group, the tile's colliding information will be set. The `collides` parameter + * controls if collision will be enabled (true) or disabled (false). + * + * @function Phaser.Tilemaps.Components.SetCollisionFromCollisionGroup + * @since 3.0.0 + * + * @param {boolean} collides - If true it will enable collision. If false it will clear collision. + * @param {boolean} recalculateFaces - Whether or not to recalculate the tile faces after the update. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SetCollisionFromCollisionGroup = function (collides, recalculateFaces, layer) +{ + if (collides === undefined) { collides = true; } + if (recalculateFaces === undefined) { recalculateFaces = true; } + + for (var ty = 0; ty < layer.height; ty++) + { + for (var tx = 0; tx < layer.width; tx++) + { + var tile = layer.data[ty][tx]; + + if (!tile) { continue; } + + var collisionGroup = tile.getCollisionGroup(); + + // It's possible in Tiled to have a collision group without any shapes, e.g. create a + // shape and then delete the shape. + if (collisionGroup && collisionGroup.objects && collisionGroup.objects.length > 0) + { + SetTileCollision(tile, collides); + } + } + } + + if (recalculateFaces) + { + CalculateFacesWithin(0, 0, layer.width, layer.height, layer); + } +}; + +module.exports = SetCollisionFromCollisionGroup; + + +/***/ }), + +/***/ 9589: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Internally used method to keep track of the tile indexes that collide within a layer. This + * updates LayerData.collideIndexes to either contain or not contain the given `tileIndex`. + * + * @function Phaser.Tilemaps.Components.SetLayerCollisionIndex + * @since 3.0.0 + * + * @param {number} tileIndex - The tile index to set the collision boolean for. + * @param {boolean} collides - Should the tile index collide or not? + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SetLayerCollisionIndex = function (tileIndex, collides, layer) +{ + var loc = layer.collideIndexes.indexOf(tileIndex); + + if (collides && loc === -1) + { + layer.collideIndexes.push(tileIndex); + } + else if (!collides && loc !== -1) + { + layer.collideIndexes.splice(loc, 1); + } +}; + +module.exports = SetLayerCollisionIndex; + + +/***/ }), + +/***/ 20576: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Internally used method to set the colliding state of a tile. This does not recalculate + * interesting faces. + * + * @function Phaser.Tilemaps.Components.SetTileCollision + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.Tile} tile - The Tile to set the collision on. + * @param {boolean} [collides=true] - Should the tile index collide or not? + */ +var SetTileCollision = function (tile, collides) +{ + if (collides) + { + tile.setCollision(true, true, true, true, false); + } + else + { + tile.resetCollision(false); + } +}; + +module.exports = SetTileCollision; + + +/***/ }), + +/***/ 79583: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sets a global collision callback for the given tile index within the layer. This will affect all + * tiles on this layer that have the same index. If a callback is already set for the tile index it + * will be replaced. Set the callback to null to remove it. If you want to set a callback for a tile + * at a specific location on the map then see setTileLocationCallback. + * + * @function Phaser.Tilemaps.Components.SetTileIndexCallback + * @since 3.0.0 + * + * @param {(number|array)} indexes - Either a single tile index, or an array of tile indexes to have a collision callback set for. + * @param {function} callback - The callback that will be invoked when the tile is collided with. + * @param {object} callbackContext - The context under which the callback is called. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SetTileIndexCallback = function (indexes, callback, callbackContext, layer) +{ + if (typeof indexes === 'number') + { + layer.callbacks[indexes] = (callback !== null) + ? { callback: callback, callbackContext: callbackContext } + : undefined; + } + else + { + for (var i = 0, len = indexes.length; i < len; i++) + { + layer.callbacks[indexes[i]] = (callback !== null) + ? { callback: callback, callbackContext: callbackContext } + : undefined; + } + } +}; + +module.exports = SetTileIndexCallback; + + +/***/ }), + +/***/ 93254: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); + +/** + * Sets a collision callback for the given rectangular area (in tile coordinates) within the layer. + * If a callback is already set for the tile index it will be replaced. Set the callback to null to + * remove it. + * + * @function Phaser.Tilemaps.Components.SetTileLocationCallback + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {function} callback - The callback that will be invoked when the tile is collided with. + * @param {object} callbackContext - The context under which the callback is called. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SetTileLocationCallback = function (tileX, tileY, width, height, callback, callbackContext, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + for (var i = 0; i < tiles.length; i++) + { + tiles[i].setCollisionCallback(callback, callbackContext); + } +}; + +module.exports = SetTileLocationCallback; + + +/***/ }), + +/***/ 32903: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); +var ShuffleArray = __webpack_require__(33680); + +/** + * Shuffles the tiles in a rectangular region (specified in tile coordinates) within the given + * layer. It will only randomize the tiles in that area, so if they're all the same nothing will + * appear to have changed! This method only modifies tile indexes and does not change collision + * information. + * + * @function Phaser.Tilemaps.Components.Shuffle + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var Shuffle = function (tileX, tileY, width, height, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + var indexes = tiles.map(function (tile) { return tile.index; }); + + ShuffleArray(indexes); + + for (var i = 0; i < tiles.length; i++) + { + tiles[i].index = indexes[i]; + } +}; + +module.exports = Shuffle; + + +/***/ }), + +/***/ 61325: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SnapCeil = __webpack_require__(63448); +var SnapFloor = __webpack_require__(56583); + +/** + * Returns the bounds in the given layer that are within the camera's viewport. + * This is used internally by the cull tiles function. + * + * @function Phaser.Tilemaps.Components.StaggeredCullBounds + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * + * @return {object} An object containing the `left`, `right`, `top` and `bottom` bounds. + */ +var StaggeredCullBounds = function (layer, camera) +{ + var tilemap = layer.tilemapLayer.tilemap; + var tilemapLayer = layer.tilemapLayer; + + // We need to use the tile sizes defined for the map as a whole, not the layer, + // in order to calculate the bounds correctly. As different sized tiles may be + // placed on the grid and we cannot trust layer.baseTileWidth to give us the true size. + var tileW = Math.floor(tilemap.tileWidth * tilemapLayer.scaleX); + var tileH = Math.floor(tilemap.tileHeight * tilemapLayer.scaleY); + + var boundsLeft = SnapFloor(camera.worldView.x - tilemapLayer.x, tileW, 0, true) - tilemapLayer.cullPaddingX; + var boundsRight = SnapCeil(camera.worldView.right - tilemapLayer.x, tileW, 0, true) + tilemapLayer.cullPaddingX; + + var boundsTop = SnapFloor(camera.worldView.y - tilemapLayer.y, tileH / 2, 0, true) - tilemapLayer.cullPaddingY; + var boundsBottom = SnapCeil(camera.worldView.bottom - tilemapLayer.y, tileH / 2, 0, true) + tilemapLayer.cullPaddingY; + + return { + left: boundsLeft, + right: boundsRight, + top: boundsTop, + bottom: boundsBottom + }; +}; + +module.exports = StaggeredCullBounds; + + +/***/ }), + +/***/ 54503: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CullBounds = __webpack_require__(61325); +var RunCull = __webpack_require__(32483); + +/** + * Returns the tiles in the given layer that are within the cameras viewport. This is used internally. + * + * @function Phaser.Tilemaps.Components.StaggeredCullTiles + * @since 3.50.0 + * + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to run the cull check against. + * @param {array} [outputArray] - An optional array to store the Tile objects within. + * @param {number} [renderOrder=0] - The rendering order constant. + * + * @return {Phaser.Tilemaps.Tile[]} An array of Tile objects. + */ +var StaggeredCullTiles = function (layer, camera, outputArray, renderOrder) +{ + if (outputArray === undefined) { outputArray = []; } + if (renderOrder === undefined) { renderOrder = 0; } + + outputArray.length = 0; + + var tilemapLayer = layer.tilemapLayer; + + // Camera world view bounds, snapped for scaled tile size + // Cull Padding values are given in tiles, not pixels + + var bounds = CullBounds(layer, camera); + + if (tilemapLayer.skipCull && tilemapLayer.scrollFactorX === 1 && tilemapLayer.scrollFactorY === 1) + { + bounds.left = 0; + bounds.right = layer.width; + bounds.top = 0; + bounds.bottom = layer.height; + } + + RunCull(layer, bounds, renderOrder, outputArray); + + return outputArray; +}; + +module.exports = StaggeredCullTiles; + + +/***/ }), + +/***/ 97202: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from staggered tile XY coordinates (tile units) to world XY coordinates (pixels), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.StaggeredTileToWorldXY + * @since 3.50.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in world coordinates. + */ +var StaggeredTileToWorldXY = function (tileX, tileY, point, camera, layer) +{ + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + var layerWorldX = 0; + var layerWorldY = 0; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + layerWorldX = tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX); + + tileWidth *= tilemapLayer.scaleX; + + layerWorldY = (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + } + + var x = layerWorldX + tileX * tileWidth + tileY % 2 * (tileWidth / 2); + var y = layerWorldY + tileY * (tileHeight / 2); + + return point.set(x, y); +}; + +module.exports = StaggeredTileToWorldXY; + + +/***/ }), + +/***/ 28054: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts from staggered tile Y coordinates (tile units) to world Y coordinates (pixels), factoring in the + * layers position, scale and scroll. + * + * @function Phaser.Tilemaps.Components.StaggeredTileToWorldY + * @since 3.50.0 + * + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {number} The Y location in world coordinates. + */ +var StaggeredTileToWorldY = function (tileY, camera, layer) +{ + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + var layerWorldY = 0; + + if (tilemapLayer) + { + if (camera === undefined) { camera = tilemapLayer.scene.cameras.main; } + + layerWorldY = (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + } + + return layerWorldY + tileY * (tileHeight / 2) + tileHeight; +}; + +module.exports = StaggeredTileToWorldY; + + +/***/ }), + +/***/ 15108: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from world XY coordinates (pixels) to staggered tile XY coordinates (tile units), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.StaggeredWorldToTileXY + * @since 3.50.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in tile units. + */ +var StaggeredWorldToTileXY = function (worldX, worldY, snapToFloor, point, camera, layer) +{ + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's vertical scroll + + worldY = worldY - (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's horizontal scroll + + worldX = worldX - (tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX)); + + tileWidth *= tilemapLayer.scaleX; + } + + var y = (snapToFloor) ? Math.floor((worldY / (tileHeight / 2))) : (worldY / (tileHeight / 2)); + var x = (snapToFloor) ? Math.floor((worldX + (y % 2) * 0.5 * tileWidth) / tileWidth) : (worldX + (y % 2) * 0.5 * tileWidth) / tileWidth; + + return point.set(x, y); +}; + +module.exports = StaggeredWorldToTileXY; + + +/***/ }), + +/***/ 51900: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts from world Y coordinates (pixels) to staggered tile Y coordinates (tile units), factoring in the + * layers position, scale and scroll. + * + * @function Phaser.Tilemaps.Components.StaggeredWorldToTileY + * @since 3.50.0 + * + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {number} The Y location in tile units. + */ +var StaggeredWorldToTileY = function (worldY, snapToFloor, camera, layer) +{ + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's vertical scroll + + worldY = worldY - (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + } + + return (snapToFloor) ? Math.floor(worldY / (tileHeight / 2)) : worldY / (tileHeight / 2); +}; + +module.exports = StaggeredWorldToTileY; + + +/***/ }), + +/***/ 86560: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); + +/** + * Scans the given rectangular area (given in tile coordinates) for tiles with an index matching + * `indexA` and swaps then with `indexB`. This only modifies the index and does not change collision + * information. + * + * @function Phaser.Tilemaps.Components.SwapByIndex + * @since 3.0.0 + * + * @param {number} tileA - First tile index. + * @param {number} tileB - Second tile index. + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var SwapByIndex = function (indexA, indexB, tileX, tileY, width, height, layer) +{ + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + for (var i = 0; i < tiles.length; i++) + { + if (tiles[i]) + { + if (tiles[i].index === indexA) + { + tiles[i].index = indexB; + } + else if (tiles[i].index === indexB) + { + tiles[i].index = indexA; + } + } + } +}; + +module.exports = SwapByIndex; + + +/***/ }), + +/***/ 97281: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts from tile X coordinates (tile units) to world X coordinates (pixels), factoring in the + * layer's position, scale and scroll. + * + * @function Phaser.Tilemaps.Components.TileToWorldX + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {number} + */ +var TileToWorldX = function (tileX, camera, layer) +{ + var tileWidth = layer.baseTileWidth; + var tilemapLayer = layer.tilemapLayer; + var layerWorldX = 0; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + layerWorldX = tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX); + + tileWidth *= tilemapLayer.scaleX; + } + + return layerWorldX + tileX * tileWidth; +}; + +module.exports = TileToWorldX; + + +/***/ }), + +/***/ 70326: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var TileToWorldX = __webpack_require__(97281); +var TileToWorldY = __webpack_require__(29650); +var Vector2 = __webpack_require__(26099); + +/** + * Converts from tile XY coordinates (tile units) to world XY coordinates (pixels), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.TileToWorldXY + * @since 3.0.0 + * + * @param {number} tileX - The x coordinate, in tiles, not pixels. + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in world coordinates. + */ +var TileToWorldXY = function (tileX, tileY, point, camera, layer) +{ + if (!point) { point = new Vector2(0, 0); } + + point.x = TileToWorldX(tileX, camera, layer); + point.y = TileToWorldY(tileY, camera, layer); + + return point; +}; + +module.exports = TileToWorldXY; + + +/***/ }), + +/***/ 29650: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Converts from tile Y coordinates (tile units) to world Y coordinates (pixels), factoring in the + * layer's position, scale and scroll. + * + * @function Phaser.Tilemaps.Components.TileToWorldY + * @since 3.0.0 + * + * @param {number} tileY - The y coordinate, in tiles, not pixels. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {number} The Y location in world coordinates. + */ +var TileToWorldY = function (tileY, camera, layer) +{ + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + var layerWorldY = 0; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + layerWorldY = (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileHeight *= tilemapLayer.scaleY; + } + + return layerWorldY + tileY * tileHeight; +}; + +module.exports = TileToWorldY; + + +/***/ }), + +/***/ 77366: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetTilesWithin = __webpack_require__(7386); +var MATH = __webpack_require__(75508); + +/** + * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the + * specified layer. Each tile will receive a new index. New indexes are drawn from the given + * weightedIndexes array. An example weighted array: + * + * [ + * { index: 6, weight: 4 }, // Probability of index 6 is 4 / 8 + * { index: 7, weight: 2 }, // Probability of index 7 would be 2 / 8 + * { index: 8, weight: 1.5 }, // Probability of index 8 would be 1.5 / 8 + * { index: 26, weight: 0.5 } // Probability of index 27 would be 0.5 / 8 + * ] + * + * The probability of any index being choose is (the index's weight) / (sum of all weights). This + * method only modifies tile indexes and does not change collision information. + * + * @function Phaser.Tilemaps.Components.WeightedRandomize + * @since 3.0.0 + * + * @param {number} tileX - The left most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} tileY - The top most tile index (in tile coordinates) to use as the origin of the area. + * @param {number} width - How many tiles wide from the `tileX` index the area will be. + * @param {number} height - How many tiles tall from the `tileY` index the area will be. + * @param {object[]} weightedIndexes - An array of objects to randomly draw from during + * randomization. They should be in the form: { index: 0, weight: 4 } or + * { index: [0, 1], weight: 4 } if you wish to draw from multiple tile indexes. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + */ +var WeightedRandomize = function (tileX, tileY, width, height, weightedIndexes, layer) +{ + if (!weightedIndexes) { return; } + + var i; + var tiles = GetTilesWithin(tileX, tileY, width, height, null, layer); + + var weightTotal = 0; + + for (i = 0; i < weightedIndexes.length; i++) + { + weightTotal += weightedIndexes[i].weight; + } + + if (weightTotal <= 0) { return; } + + for (i = 0; i < tiles.length; i++) + { + var rand = MATH.RND.frac() * weightTotal; + var sum = 0; + var randomIndex = -1; + + for (var j = 0; j < weightedIndexes.length; j++) + { + sum += weightedIndexes[j].weight; + + if (rand <= sum) + { + var chosen = weightedIndexes[j].index; + + randomIndex = Array.isArray(chosen) + ? chosen[Math.floor(MATH.RND.frac() * chosen.length)] + : chosen; + break; + } + } + + tiles[i].index = randomIndex; + } +}; + +module.exports = WeightedRandomize; + + +/***/ }), + +/***/ 10095: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var WorldToTileXY = __webpack_require__(85896); +var Vector2 = __webpack_require__(26099); + +var tempVec = new Vector2(); + +/** + * Converts from world X coordinates (pixels) to tile X coordinates (tile units), factoring in the + * layer's position, scale and scroll. + * + * @function Phaser.Tilemaps.Components.WorldToTileX + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinate down to the nearest integer. + * @param {?Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {number} The X location in tile units. + */ +var WorldToTileX = function (worldX, snapToFloor, camera, layer) +{ + WorldToTileXY(worldX, 0, snapToFloor, tempVec, camera, layer); + + return tempVec.x; +}; + +module.exports = WorldToTileX; + + +/***/ }), + +/***/ 85896: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Vector2 = __webpack_require__(26099); + +/** + * Converts from world XY coordinates (pixels) to tile XY coordinates (tile units), factoring in the + * layer's position, scale and scroll. This will return a new Vector2 object or update the given + * `point` object. + * + * @function Phaser.Tilemaps.Components.WorldToTileXY + * @since 3.0.0 + * + * @param {number} worldX - The x coordinate to be converted, in pixels, not tiles. + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinate down to the nearest integer. + * @param {Phaser.Math.Vector2} point - A Vector2 to store the coordinates in. If not given a new Vector2 is created. + * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {Phaser.Math.Vector2} The XY location in tile units. + */ +var WorldToTileXY = function (worldX, worldY, snapToFloor, point, camera, layer) +{ + if (snapToFloor === undefined) { snapToFloor = true; } + if (!point) { point = new Vector2(); } + + var tileWidth = layer.baseTileWidth; + var tileHeight = layer.baseTileHeight; + var tilemapLayer = layer.tilemapLayer; + + if (tilemapLayer) + { + if (!camera) { camera = tilemapLayer.scene.cameras.main; } + + // Find the world position relative to the static or dynamic layer's top left origin, + // factoring in the camera's horizontal scroll + worldX = worldX - (tilemapLayer.x + camera.scrollX * (1 - tilemapLayer.scrollFactorX)); + worldY = worldY - (tilemapLayer.y + camera.scrollY * (1 - tilemapLayer.scrollFactorY)); + + tileWidth *= tilemapLayer.scaleX; + tileHeight *= tilemapLayer.scaleY; + } + + var x = worldX / tileWidth; + var y = worldY / tileHeight; + + if (snapToFloor) + { + x = Math.floor(x); + y = Math.floor(y); + } + + return point.set(x, y); +}; + +module.exports = WorldToTileXY; + + +/***/ }), + +/***/ 63288: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var WorldToTileXY = __webpack_require__(85896); +var Vector2 = __webpack_require__(26099); + +var tempVec = new Vector2(); + +/** + * Converts from world Y coordinates (pixels) to tile Y coordinates (tile units), factoring in the + * layer's position, scale and scroll. + * + * @function Phaser.Tilemaps.Components.WorldToTileY + * @since 3.0.0 + * + * @param {number} worldY - The y coordinate to be converted, in pixels, not tiles. + * @param {boolean} snapToFloor - Whether or not to round the tile coordinate down to the nearest integer. + * @param {?Phaser.Cameras.Scene2D.Camera} camera - The Camera to use when calculating the tile index from the world values. + * @param {Phaser.Tilemaps.LayerData} layer - The Tilemap Layer to act upon. + * + * @return {number} The Y location in tile units. + */ +var WorldToTileY = function (worldY, snapToFloor, camera, layer) +{ + WorldToTileXY(0, worldY, snapToFloor, tempVec, camera, layer); + + return tempVec.y; +}; + +module.exports = WorldToTileY; + + +/***/ }), + +/***/ 81086: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tilemaps.Components + */ + +module.exports = { + + CalculateFacesAt: __webpack_require__(72023), + CalculateFacesWithin: __webpack_require__(42573), + CheckIsoBounds: __webpack_require__(33528), + Copy: __webpack_require__(1785), + CreateFromTiles: __webpack_require__(78419), + CullBounds: __webpack_require__(19545), + CullTiles: __webpack_require__(30003), + Fill: __webpack_require__(35137), + FilterTiles: __webpack_require__(40253), + FindByIndex: __webpack_require__(52692), + FindTile: __webpack_require__(66151), + ForEachTile: __webpack_require__(97560), + GetCullTilesFunction: __webpack_require__(43305), + GetTileAt: __webpack_require__(7423), + GetTileAtWorldXY: __webpack_require__(60540), + GetTileCorners: __webpack_require__(55826), + GetTileCornersFunction: __webpack_require__(11758), + GetTilesWithin: __webpack_require__(7386), + GetTilesWithinShape: __webpack_require__(91141), + GetTilesWithinWorldXY: __webpack_require__(96523), + GetTileToWorldXFunction: __webpack_require__(39167), + GetTileToWorldXYFunction: __webpack_require__(62000), + GetTileToWorldYFunction: __webpack_require__(5984), + GetWorldToTileXFunction: __webpack_require__(96113), + GetWorldToTileXYFunction: __webpack_require__(16926), + GetWorldToTileYFunction: __webpack_require__(55762), + HasTileAt: __webpack_require__(45091), + HasTileAtWorldXY: __webpack_require__(24152), + HexagonalCullBounds: __webpack_require__(90454), + HexagonalCullTiles: __webpack_require__(9474), + HexagonalGetTileCorners: __webpack_require__(27229), + HexagonalTileToWorldXY: __webpack_require__(19951), + HexagonalWorldToTileXY: __webpack_require__(86625), + IsInLayerBounds: __webpack_require__(62991), + IsometricCullTiles: __webpack_require__(14018), + IsometricTileToWorldXY: __webpack_require__(14127), + IsometricWorldToTileXY: __webpack_require__(96897), + PutTileAt: __webpack_require__(71558), + PutTileAtWorldXY: __webpack_require__(26303), + PutTilesAt: __webpack_require__(14051), + Randomize: __webpack_require__(77389), + RemoveTileAt: __webpack_require__(63557), + RemoveTileAtWorldXY: __webpack_require__(94178), + RenderDebug: __webpack_require__(15533), + ReplaceByIndex: __webpack_require__(27987), + RunCull: __webpack_require__(32483), + SetCollision: __webpack_require__(57068), + SetCollisionBetween: __webpack_require__(37266), + SetCollisionByExclusion: __webpack_require__(75661), + SetCollisionByProperty: __webpack_require__(64740), + SetCollisionFromCollisionGroup: __webpack_require__(63307), + SetLayerCollisionIndex: __webpack_require__(9589), + SetTileCollision: __webpack_require__(20576), + SetTileIndexCallback: __webpack_require__(79583), + SetTileLocationCallback: __webpack_require__(93254), + Shuffle: __webpack_require__(32903), + StaggeredCullBounds: __webpack_require__(61325), + StaggeredCullTiles: __webpack_require__(54503), + StaggeredTileToWorldXY: __webpack_require__(97202), + StaggeredTileToWorldY: __webpack_require__(28054), + StaggeredWorldToTileXY: __webpack_require__(15108), + StaggeredWorldToTileY: __webpack_require__(51900), + SwapByIndex: __webpack_require__(86560), + TileToWorldX: __webpack_require__(97281), + TileToWorldXY: __webpack_require__(70326), + TileToWorldY: __webpack_require__(29650), + WeightedRandomize: __webpack_require__(77366), + WorldToTileX: __webpack_require__(10095), + WorldToTileXY: __webpack_require__(85896), + WorldToTileY: __webpack_require__(63288) + +}; + + +/***/ }), + +/***/ 91907: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Tilemap constants for orientation. + * + * @namespace Phaser.Tilemaps.Orientation + * @memberof Phaser.Tilemaps + * @since 3.50.0 + */ + +/** + * Phaser Tilemap constants for orientation. + * + * To find out what each mode does please see [Phaser.Tilemaps.Orientation]{@link Phaser.Tilemaps.Orientation}. + * + * @typedef {Phaser.Tilemaps.Orientation} Phaser.Tilemaps.OrientationType + * @memberof Phaser.Tilemaps + * @since 3.50.0 + */ + +module.exports = { + + /** + * Orthogonal Tilemap orientation constant. + * + * @name Phaser.Tilemaps.Orientation.ORTHOGONAL + * @type {number} + * @const + * @since 3.50.0 + */ + ORTHOGONAL: 0, + + /** + * Isometric Tilemap orientation constant. + * + * @name Phaser.Tilemaps.Orientation.ISOMETRIC + * @type {number} + * @const + * @since 3.50.0 + */ + ISOMETRIC: 1, + + /** + * Staggered Tilemap orientation constant. + * + * @name Phaser.Tilemaps.Orientation.STAGGERED + * @type {number} + * @const + * @since 3.50.0 + */ + STAGGERED: 2, + + /** + * Hexagonal Tilemap orientation constant. + * + * @name Phaser.Tilemaps.Orientation.HEXAGONAL + * @type {number} + * @const + * @since 3.50.0 + */ + HEXAGONAL: 3 + +}; + + +/***/ }), + +/***/ 21829: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = { + + ORIENTATION: __webpack_require__(91907) + +}; + +module.exports = CONST; + + +/***/ }), + +/***/ 62501: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Extend = __webpack_require__(79291); +var CONST = __webpack_require__(21829); + +/** + * @namespace Phaser.Tilemaps + * + * @borrows Phaser.Tilemaps.Orientation.ORTHOGONAL as ORTHOGONAL + * @borrows Phaser.Tilemaps.Orientation.ISOMETRIC as ISOMETRIC + * @borrows Phaser.Tilemaps.Orientation.STAGGERED as STAGGERED + * @borrows Phaser.Tilemaps.Orientation.HEXAGONAL as HEXAGONAL + */ + +var Tilemaps = { + + Components: __webpack_require__(81086), + Parsers: __webpack_require__(57442), + + Formats: __webpack_require__(80341), + ImageCollection: __webpack_require__(16536), + ParseToTilemap: __webpack_require__(31989), + Tile: __webpack_require__(23029), + Tilemap: __webpack_require__(49075), + TilemapCreator: __webpack_require__(45939), + TilemapFactory: __webpack_require__(46029), + Tileset: __webpack_require__(33629), + TilemapLayerBase: __webpack_require__(44731), + TilemapLayer: __webpack_require__(20442), + TilemapGPULayer: __webpack_require__(53180), + Orientation: __webpack_require__(91907), + + LayerData: __webpack_require__(14977), + MapData: __webpack_require__(87010), + ObjectLayer: __webpack_require__(48700) + +}; + +Tilemaps = Extend(false, Tilemaps, CONST.ORIENTATION); + +module.exports = Tilemaps; + + +/***/ }), + +/***/ 14977: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(91907); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * A class for representing data about about a layer in a map. Maps are parsed from CSV, Tiled, + * etc. into this format. Tilemap and TilemapLayer objects have a reference + * to this data and use it to look up and perform operations on tiles. + * + * @class LayerData + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Tilemaps.LayerDataConfig} [config] - The Layer Data configuration object. + */ +var LayerData = new Class({ + + initialize: + + function LayerData (config) + { + if (config === undefined) { config = {}; } + + /** + * The name of the layer, if specified in Tiled. + * + * @name Phaser.Tilemaps.LayerData#name + * @type {string} + * @since 3.0.0 + */ + this.name = GetFastValue(config, 'name', 'layer'); + + /** + * The id of the layer, as specified in the map data. + * + * Note: This is not the index of the layer in the map data, but its actual ID in Tiled. + * + * @name Phaser.Tilemaps.LayerData#id + * @type {number} + * @since 3.70.0 + */ + this.id = GetFastValue(config, 'id', 0); + + /** + * The x offset of where to draw from the top left. + * + * @name Phaser.Tilemaps.LayerData#x + * @type {number} + * @since 3.0.0 + */ + this.x = GetFastValue(config, 'x', 0); + + /** + * The y offset of where to draw from the top left. + * + * @name Phaser.Tilemaps.LayerData#y + * @type {number} + * @since 3.0.0 + */ + this.y = GetFastValue(config, 'y', 0); + + /** + * The width of the layer in tiles. + * + * @name Phaser.Tilemaps.LayerData#width + * @type {number} + * @since 3.0.0 + */ + this.width = GetFastValue(config, 'width', 0); + + /** + * The height of the layer in tiles. + * + * @name Phaser.Tilemaps.LayerData#height + * @type {number} + * @since 3.0.0 + */ + this.height = GetFastValue(config, 'height', 0); + + /** + * The pixel width of the tiles. + * + * @name Phaser.Tilemaps.LayerData#tileWidth + * @type {number} + * @since 3.0.0 + */ + this.tileWidth = GetFastValue(config, 'tileWidth', 0); + + /** + * The pixel height of the tiles. + * + * @name Phaser.Tilemaps.LayerData#tileHeight + * @type {number} + * @since 3.0.0 + */ + this.tileHeight = GetFastValue(config, 'tileHeight', 0); + + /** + * The base tile width. + * + * @name Phaser.Tilemaps.LayerData#baseTileWidth + * @type {number} + * @since 3.0.0 + */ + this.baseTileWidth = GetFastValue(config, 'baseTileWidth', this.tileWidth); + + /** + * The base tile height. + * + * @name Phaser.Tilemaps.LayerData#baseTileHeight + * @type {number} + * @since 3.0.0 + */ + this.baseTileHeight = GetFastValue(config, 'baseTileHeight', this.tileHeight); + + /** + * The layers orientation, necessary to be able to determine a tiles pixelX and pixelY as well as the layers width and height. + * + * @name Phaser.Tilemaps.LayerData#orientation + * @type {Phaser.Tilemaps.OrientationType} + * @since 3.50.0 + */ + this.orientation = GetFastValue(config, 'orientation', CONST.ORTHOGONAL); + + /** + * The width in pixels of the entire layer. + * + * @name Phaser.Tilemaps.LayerData#widthInPixels + * @type {number} + * @since 3.0.0 + */ + this.widthInPixels = GetFastValue(config, 'widthInPixels', this.width * this.baseTileWidth); + + /** + * The height in pixels of the entire layer. + * + * @name Phaser.Tilemaps.LayerData#heightInPixels + * @type {number} + * @since 3.0.0 + */ + this.heightInPixels = GetFastValue(config, 'heightInPixels', this.height * this.baseTileHeight); + + /** + * The alpha value of the layer. + * + * @name Phaser.Tilemaps.LayerData#alpha + * @type {number} + * @since 3.0.0 + */ + this.alpha = GetFastValue(config, 'alpha', 1); + + /** + * Is the layer visible or not? + * + * @name Phaser.Tilemaps.LayerData#visible + * @type {boolean} + * @since 3.0.0 + */ + this.visible = GetFastValue(config, 'visible', true); + + /** + * Layer specific properties (can be specified in Tiled) + * + * @name Phaser.Tilemaps.LayerData#properties + * @type {object[]} + * @since 3.0.0 + */ + this.properties = GetFastValue(config, 'properties', []); + + /** + * Tile ID index map. + * + * @name Phaser.Tilemaps.LayerData#indexes + * @type {array} + * @since 3.0.0 + */ + this.indexes = GetFastValue(config, 'indexes', []); + + /** + * Tile Collision ID index map. + * + * @name Phaser.Tilemaps.LayerData#collideIndexes + * @type {array} + * @since 3.0.0 + */ + this.collideIndexes = GetFastValue(config, 'collideIndexes', []); + + /** + * An array of callbacks. + * + * @name Phaser.Tilemaps.LayerData#callbacks + * @type {array} + * @since 3.0.0 + */ + this.callbacks = GetFastValue(config, 'callbacks', []); + + /** + * An array of physics bodies. + * + * @name Phaser.Tilemaps.LayerData#bodies + * @type {array} + * @since 3.0.0 + */ + this.bodies = GetFastValue(config, 'bodies', []); + + /** + * An array of the tile data indexes. + * + * @name Phaser.Tilemaps.LayerData#data + * @type {Phaser.Tilemaps.Tile[][]} + * @since 3.0.0 + */ + this.data = GetFastValue(config, 'data', []); + + /** + * A reference to the Tilemap layer that owns this data. + * + * @name Phaser.Tilemaps.LayerData#tilemapLayer + * @type {Phaser.Tilemaps.TilemapLayer} + * @since 3.0.0 + */ + this.tilemapLayer = GetFastValue(config, 'tilemapLayer', null); + + /** + * The length of the horizontal sides of the hexagon. + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.LayerData#hexSideLength + * @type {number} + * @since 3.50.0 + */ + this.hexSideLength = GetFastValue(config, 'hexSideLength', 0); + + /** + * The Stagger Axis as defined in Tiled. + * + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.LayerData#staggerAxis + * @type {string} + * @since 3.60.0 + */ + this.staggerAxis = GetFastValue(config, 'staggerAxis', 'y'); + + /** + * The Stagger Index as defined in Tiled. + * + * Either 'odd' or 'even'. + * + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.LayerData#staggerIndex + * @type {string} + * @since 3.60.0 + */ + this.staggerIndex = GetFastValue(config, 'staggerIndex', 'odd'); + } + +}); + +module.exports = LayerData; + + +/***/ }), + +/***/ 87010: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var CONST = __webpack_require__(91907); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * A class for representing data about a map. Maps are parsed from CSV, Tiled, etc. into this + * format. A Tilemap object get a copy of this data and then unpacks the needed properties into + * itself. + * + * @class MapData + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Tilemaps.MapDataConfig} [config] - The Map configuration object. + */ +var MapData = new Class({ + + initialize: + + function MapData (config) + { + if (config === undefined) { config = {}; } + + /** + * The key in the Phaser cache that corresponds to the loaded tilemap data. + * + * @name Phaser.Tilemaps.MapData#name + * @type {string} + * @since 3.0.0 + */ + this.name = GetFastValue(config, 'name', 'map'); + + /** + * The width of the entire tilemap. + * + * @name Phaser.Tilemaps.MapData#width + * @type {number} + * @since 3.0.0 + */ + this.width = GetFastValue(config, 'width', 0); + + /** + * The height of the entire tilemap. + * + * @name Phaser.Tilemaps.MapData#height + * @type {number} + * @since 3.0.0 + */ + this.height = GetFastValue(config, 'height', 0); + + /** + * If the map is infinite or not. + * + * @name Phaser.Tilemaps.MapData#infinite + * @type {boolean} + * @since 3.17.0 + */ + this.infinite = GetFastValue(config, 'infinite', false); + + /** + * The width of the tiles. + * + * @name Phaser.Tilemaps.MapData#tileWidth + * @type {number} + * @since 3.0.0 + */ + this.tileWidth = GetFastValue(config, 'tileWidth', 0); + + /** + * The height of the tiles. + * + * @name Phaser.Tilemaps.MapData#tileHeight + * @type {number} + * @since 3.0.0 + */ + this.tileHeight = GetFastValue(config, 'tileHeight', 0); + + /** + * The width in pixels of the entire tilemap. + * + * @name Phaser.Tilemaps.MapData#widthInPixels + * @type {number} + * @since 3.0.0 + */ + this.widthInPixels = GetFastValue(config, 'widthInPixels', this.width * this.tileWidth); + + /** + * The height in pixels of the entire tilemap. + * + * @name Phaser.Tilemaps.MapData#heightInPixels + * @type {number} + * @since 3.0.0 + */ + this.heightInPixels = GetFastValue(config, 'heightInPixels', this.height * this.tileHeight); + + /** + * The format of the map data. + * + * @name Phaser.Tilemaps.MapData#format + * @type {number} + * @since 3.0.0 + */ + this.format = GetFastValue(config, 'format', null); + + /** + * The orientation of the map data (i.e. orthogonal, isometric, hexagonal), default 'orthogonal'. + * + * @name Phaser.Tilemaps.MapData#orientation + * @type {Phaser.Tilemaps.OrientationType} + * @since 3.50.0 + */ + this.orientation = GetFastValue(config, 'orientation', CONST.ORTHOGONAL); + + /** + * Determines the draw order of tilemap. Default is right-down + * + * 0, or 'right-down' + * 1, or 'left-down' + * 2, or 'right-up' + * 3, or 'left-up' + * + * @name Phaser.Tilemaps.MapData#renderOrder + * @type {string} + * @since 3.12.0 + */ + this.renderOrder = GetFastValue(config, 'renderOrder', 'right-down'); + + /** + * The version of the map data (as specified in Tiled). + * + * @name Phaser.Tilemaps.MapData#version + * @type {string} + * @since 3.0.0 + */ + this.version = GetFastValue(config, 'version', '1'); + + /** + * Map specific properties (can be specified in Tiled) + * + * @name Phaser.Tilemaps.MapData#properties + * @type {object} + * @since 3.0.0 + */ + this.properties = GetFastValue(config, 'properties', {}); + + /** + * An array with all the layers configured to the MapData. + * + * @name Phaser.Tilemaps.MapData#layers + * @type {(Phaser.Tilemaps.LayerData[]|Phaser.Tilemaps.ObjectLayer)} + * @since 3.0.0 + */ + this.layers = GetFastValue(config, 'layers', []); + + /** + * An array of Tiled Image Layers. + * + * @name Phaser.Tilemaps.MapData#images + * @type {array} + * @since 3.0.0 + */ + this.images = GetFastValue(config, 'images', []); + + /** + * An object of Tiled Object Layers. + * + * @name Phaser.Tilemaps.MapData#objects + * @type {Phaser.Types.Tilemaps.ObjectLayerConfig[]} + * @since 3.0.0 + */ + this.objects = GetFastValue(config, 'objects', []); + + // Because Tiled can sometimes create an empty object if you don't populate it, not an empty array + if (!Array.isArray(this.objects)) + { + this.objects = []; + } + + /** + * An object of collision data. Must be created as physics object or will return undefined. + * + * @name Phaser.Tilemaps.MapData#collision + * @type {object} + * @since 3.0.0 + */ + this.collision = GetFastValue(config, 'collision', {}); + + /** + * An array of Tilesets. + * + * @name Phaser.Tilemaps.MapData#tilesets + * @type {Phaser.Tilemaps.Tileset[]} + * @since 3.0.0 + */ + this.tilesets = GetFastValue(config, 'tilesets', []); + + /** + * The collection of images the map uses(specified in Tiled) + * + * @name Phaser.Tilemaps.MapData#imageCollections + * @type {array} + * @since 3.0.0 + */ + this.imageCollections = GetFastValue(config, 'imageCollections', []); + + /** + * An array of tile instances. + * + * @name Phaser.Tilemaps.MapData#tiles + * @type {array} + * @since 3.0.0 + */ + this.tiles = GetFastValue(config, 'tiles', []); + + /** + * The length of the horizontal sides of the hexagon. + * + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.MapData#hexSideLength + * @type {number} + * @since 3.50.0 + */ + this.hexSideLength = GetFastValue(config, 'hexSideLength', 0); + + /** + * The Stagger Axis as defined in Tiled. + * + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.MapData#staggerAxis + * @type {string} + * @since 3.60.0 + */ + this.staggerAxis = GetFastValue(config, 'staggerAxis', 'y'); + + /** + * The Stagger Index as defined in Tiled. + * + * Either 'odd' or 'even'. + * + * Only used for hexagonal orientation Tilemaps. + * + * @name Phaser.Tilemaps.MapData#staggerIndex + * @type {string} + * @since 3.60.0 + */ + this.staggerIndex = GetFastValue(config, 'staggerIndex', 'odd'); + } + +}); + +module.exports = MapData; + + +/***/ }), + +/***/ 48700: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * A class for representing a Tiled object layer in a map. This mirrors the structure of a Tiled + * object layer, except: + * - "x" & "y" properties are ignored since these cannot be changed in Tiled. + * - "offsetx" & "offsety" are applied to the individual object coordinates directly, so they + * are ignored as well. + * - "draworder" is ignored. + * + * @class ObjectLayer + * @memberof Phaser.Tilemaps + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Tilemaps.ObjectLayerConfig} [config] - The data for the layer from the Tiled JSON object. + */ +var ObjectLayer = new Class({ + + initialize: + + function ObjectLayer (config) + { + if (config === undefined) { config = {}; } + + /** + * The name of the Object Layer. + * + * @name Phaser.Tilemaps.ObjectLayer#name + * @type {string} + * @since 3.0.0 + */ + this.name = GetFastValue(config, 'name', 'object layer'); + + /** + * The id of the object layer, as specified in the map data. + * + * @name Phaser.Tilemaps.ObjectLayer#id + * @type {number} + * @since 3.70.0 + */ + this.id = GetFastValue(config, 'id', 0); + + /** + * The opacity of the layer, between 0 and 1. + * + * @name Phaser.Tilemaps.ObjectLayer#opacity + * @type {number} + * @since 3.0.0 + */ + this.opacity = GetFastValue(config, 'opacity', 1); + + /** + * The custom properties defined on the Object Layer, keyed by their name. + * + * @name Phaser.Tilemaps.ObjectLayer#properties + * @type {object} + * @since 3.0.0 + */ + this.properties = GetFastValue(config, 'properties', {}); + + /** + * The type of each custom property defined on the Object Layer, keyed by its name. + * + * @name Phaser.Tilemaps.ObjectLayer#propertyTypes + * @type {object} + * @since 3.0.0 + */ + this.propertyTypes = GetFastValue(config, 'propertytypes', {}); + + /** + * The type of the layer, which should be `objectgroup`. + * + * @name Phaser.Tilemaps.ObjectLayer#type + * @type {string} + * @since 3.0.0 + */ + this.type = GetFastValue(config, 'type', 'objectgroup'); + + /** + * Whether the layer is shown (`true`) or hidden (`false`). + * + * @name Phaser.Tilemaps.ObjectLayer#visible + * @type {boolean} + * @since 3.0.0 + */ + this.visible = GetFastValue(config, 'visible', true); + + /** + * An array of all objects on this Object Layer. + * + * Each Tiled object corresponds to a JavaScript object in this array. It has an `id` (unique), + * `name` (as assigned in Tiled), `type` (as assigned in Tiled), `rotation` (in clockwise degrees), + * `properties` (if any), `visible` state (`true` if visible, `false` otherwise), + * `x` and `y` coordinates (in pixels, relative to the tilemap), and a `width` and `height` (in pixels). + * + * An object tile has a `gid` property (GID of the represented tile), a `flippedHorizontal` property, + * a `flippedVertical` property, and `flippedAntiDiagonal` property. + * The {@link http://docs.mapeditor.org/en/latest/reference/tmx-map-format/|Tiled documentation} contains + * information on flipping and rotation. + * + * Polylines have a `polyline` property, which is an array of objects corresponding to points, + * where each point has an `x` property and a `y` property. Polygons have an identically structured + * array in their `polygon` property. Text objects have a `text` property with the text's properties. + * + * Rectangles and ellipses have a `rectangle` or `ellipse` property set to `true`. + * + * @name Phaser.Tilemaps.ObjectLayer#objects + * @type {Phaser.Types.Tilemaps.TiledObject[]} + * @since 3.0.0 + */ + this.objects = GetFastValue(config, 'objects', []); + + // Because Tiled can sometimes create an empty object if you don't populate it, not an empty array + if (!Array.isArray(this.objects)) + { + this.objects = []; + } + } + +}); + +module.exports = ObjectLayer; + + +/***/ }), + +/***/ 6641: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CONST = __webpack_require__(91907); + +/** + * Get the Tilemap orientation from the given string. + * + * @function Phaser.Tilemaps.Parsers.FromOrientationString + * @since 3.50.0 + * + * @param {string} [orientation] - The orientation type as a string. + * + * @return {Phaser.Tilemaps.OrientationType} The Tilemap Orientation type. + */ +var FromOrientationString = function (orientation) +{ + orientation = orientation.toLowerCase(); + + if (orientation === 'isometric') + { + return CONST.ISOMETRIC; + } + else if (orientation === 'staggered') + { + return CONST.STAGGERED; + } + else if (orientation === 'hexagonal') + { + return CONST.HEXAGONAL; + } + else + { + return CONST.ORTHOGONAL; + } +}; + +module.exports = FromOrientationString; + + +/***/ }), + +/***/ 46177: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Formats = __webpack_require__(80341); +var Parse2DArray = __webpack_require__(2342); +var ParseCSV = __webpack_require__(82593); +var ParseJSONTiled = __webpack_require__(46594); +var ParseWeltmeister = __webpack_require__(87021); + +/** + * Parses raw data of a given Tilemap format into a new MapData object. If no recognized data format + * is found, returns `null`. When loading from CSV or a 2D array, you should specify the tileWidth & + * tileHeight. When parsing from a map from Tiled, the tileWidth & tileHeight will be pulled from + * the map data. + * + * @function Phaser.Tilemaps.Parsers.Parse + * @since 3.0.0 + * + * @param {string} name - The name of the tilemap, used to set the name on the MapData. + * @param {number} mapFormat - See ../Formats.js. + * @param {(number[][]|string|object)} data - 2D array, CSV string or Tiled JSON object. + * @param {number} tileWidth - The width of a tile in pixels. Required for 2D array and CSV, but + * ignored for Tiled JSON. + * @param {number} tileHeight - The height of a tile in pixels. Required for 2D array and CSV, but + * ignored for Tiled JSON. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {Phaser.Tilemaps.MapData} The created `MapData` object. + */ +var Parse = function (name, mapFormat, data, tileWidth, tileHeight, insertNull) +{ + var newMap; + + switch (mapFormat) + { + case (Formats.ARRAY_2D): + newMap = Parse2DArray(name, data, tileWidth, tileHeight, insertNull); + break; + case (Formats.CSV): + newMap = ParseCSV(name, data, tileWidth, tileHeight, insertNull); + break; + case (Formats.TILED_JSON): + newMap = ParseJSONTiled(name, data, insertNull); + break; + case (Formats.WELTMEISTER): + newMap = ParseWeltmeister(name, data, insertNull); + break; + default: + console.warn('Unrecognized tilemap data format: ' + mapFormat); + newMap = null; + } + + return newMap; +}; + +module.exports = Parse; + + +/***/ }), + +/***/ 2342: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Formats = __webpack_require__(80341); +var LayerData = __webpack_require__(14977); +var MapData = __webpack_require__(87010); +var Tile = __webpack_require__(23029); + +/** + * Parses a 2D array of tile indexes into a new MapData object with a single layer. + * + * @function Phaser.Tilemaps.Parsers.Parse2DArray + * @since 3.0.0 + * + * @param {string} name - The name of the tilemap, used to set the name on the MapData. + * @param {number[][]} data - 2D array, CSV string or Tiled JSON object. + * @param {number} tileWidth - The width of a tile in pixels. + * @param {number} tileHeight - The height of a tile in pixels. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {Phaser.Tilemaps.MapData} The MapData object. + */ +var Parse2DArray = function (name, data, tileWidth, tileHeight, insertNull) +{ + var layerData = new LayerData({ + tileWidth: tileWidth, + tileHeight: tileHeight + }); + + var mapData = new MapData({ + name: name, + tileWidth: tileWidth, + tileHeight: tileHeight, + format: Formats.ARRAY_2D, + layers: [ layerData ] + }); + + var tiles = []; + var height = data.length; + var width = 0; + + for (var y = 0; y < data.length; y++) + { + tiles[y] = []; + var row = data[y]; + + for (var x = 0; x < row.length; x++) + { + var tileIndex = parseInt(row[x], 10); + + if (isNaN(tileIndex) || tileIndex === -1) + { + tiles[y][x] = insertNull + ? null + : new Tile(layerData, -1, x, y, tileWidth, tileHeight); + } + else + { + tiles[y][x] = new Tile(layerData, tileIndex, x, y, tileWidth, tileHeight); + } + } + + if (width === 0) + { + width = row.length; + } + } + + mapData.width = layerData.width = width; + mapData.height = layerData.height = height; + mapData.widthInPixels = layerData.widthInPixels = width * tileWidth; + mapData.heightInPixels = layerData.heightInPixels = height * tileHeight; + layerData.data = tiles; + + return mapData; +}; + +module.exports = Parse2DArray; + + +/***/ }), + +/***/ 82593: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Formats = __webpack_require__(80341); +var Parse2DArray = __webpack_require__(2342); + +/** + * Parses a CSV string of tile indexes into a new MapData object with a single layer. + * + * @function Phaser.Tilemaps.Parsers.ParseCSV + * @since 3.0.0 + * + * @param {string} name - The name of the tilemap, used to set the name on the MapData. + * @param {string} data - CSV string of tile indexes. + * @param {number} tileWidth - The width of a tile in pixels. + * @param {number} tileHeight - The height of a tile in pixels. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {Phaser.Tilemaps.MapData} The resulting MapData object. + */ +var ParseCSV = function (name, data, tileWidth, tileHeight, insertNull) +{ + var array2D = data + .trim() + .split('\n') + .map(function (row) { return row.split(','); }); + + var map = Parse2DArray(name, array2D, tileWidth, tileHeight, insertNull); + map.format = Formats.CSV; + + return map; +}; + +module.exports = ParseCSV; + + +/***/ }), + +/***/ 6656: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var LayerData = __webpack_require__(14977); +var Tile = __webpack_require__(23029); + +/** + * Parses all tilemap layers in an Impact JSON object into new LayerData objects. + * + * @function Phaser.Tilemaps.Parsers.Impact.ParseTileLayers + * @since 3.0.0 + * + * @param {object} json - The Impact JSON object. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled (see {@link Phaser.Tilemaps.Parsers.Tiled.ParseJSONTiled}). + * + * @return {Phaser.Tilemaps.LayerData[]} - An array of LayerData objects, one for each entry in + * json.layers with the type 'tilelayer'. + */ +var ParseTileLayers = function (json, insertNull) +{ + var tileLayers = []; + + for (var i = 0; i < json.layer.length; i++) + { + var layer = json.layer[i]; + + var layerData = new LayerData({ + name: layer.name, + width: layer.width, + height: layer.height, + tileWidth: layer.tilesize, + tileHeight: layer.tilesize, + visible: layer.visible === 1 + }); + + var row = []; + var tileGrid = []; + + // Loop through the data field in the JSON. This is a 2D array containing the tile indexes, + // one after the other. The indexes are relative to the tileset that contains the tile. + for (var y = 0; y < layer.data.length; y++) + { + for (var x = 0; x < layer.data[y].length; x++) + { + // In Weltmeister, 0 = no tile, but the Tilemap API expects -1 = no tile. + var index = layer.data[y][x] - 1; + + var tile; + + if (index > -1) + { + tile = new Tile(layerData, index, x, y, layer.tilesize, layer.tilesize); + } + else + { + tile = insertNull + ? null + : new Tile(layerData, -1, x, y, layer.tilesize, layer.tilesize); + } + + row.push(tile); + } + + tileGrid.push(row); + row = []; + } + + layerData.data = tileGrid; + + tileLayers.push(layerData); + } + + return tileLayers; +}; + +module.exports = ParseTileLayers; + + +/***/ }), + +/***/ 96483: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Tileset = __webpack_require__(33629); + +/** + * Tilesets and Image Collections + * + * @function Phaser.Tilemaps.Parsers.Impact.ParseTilesets + * @since 3.0.0 + * + * @param {object} json - The Impact JSON data. + * + * @return {array} An array of Tilesets. + */ +var ParseTilesets = function (json) +{ + var tilesets = []; + var tilesetsNames = []; + + for (var i = 0; i < json.layer.length; i++) + { + var layer = json.layer[i]; + + // A relative filepath to the source image (within Weltmeister) is used for the name + var tilesetName = layer.tilesetName; + + // Only add unique tilesets that have a valid name. Collision layers will have a blank name. + if (tilesetName !== '' && tilesetsNames.indexOf(tilesetName) === -1) + { + tilesetsNames.push(tilesetName); + + // Tiles are stored with an ID relative to the tileset, rather than a globally unique ID + // across all tilesets. Also, tilesets in Weltmeister have no margin or padding. + tilesets.push(new Tileset(tilesetName, 0, layer.tilesize, layer.tilesize, 0, 0)); + } + } + + return tilesets; +}; + +module.exports = ParseTilesets; + + +/***/ }), + +/***/ 87021: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Formats = __webpack_require__(80341); +var MapData = __webpack_require__(87010); +var ParseTileLayers = __webpack_require__(6656); +var ParseTilesets = __webpack_require__(96483); + +/** + * Parses a Weltmeister JSON object into a new MapData object. + * + * @function Phaser.Tilemaps.Parsers.Impact.ParseWeltmeister + * @since 3.0.0 + * + * @param {string} name - The name of the tilemap, used to set the name on the MapData. + * @param {object} json - The Weltmeister JSON object. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {?Phaser.Tilemaps.MapData} The created MapData object, or `null` if the data can't be parsed. + */ +var ParseWeltmeister = function (name, json, insertNull) +{ + if (json.layer.length === 0) + { + console.warn('No layers found in the Weltmeister map: ' + name); + return null; + } + + var width = 0; + var height = 0; + + for (var i = 0; i < json.layer.length; i++) + { + if (json.layer[i].width > width) { width = json.layer[i].width; } + if (json.layer[i].height > height) { height = json.layer[i].height; } + } + + var mapData = new MapData({ + width: width, + height: height, + name: name, + tileWidth: json.layer[0].tilesize, + tileHeight: json.layer[0].tilesize, + format: Formats.WELTMEISTER + }); + + mapData.layers = ParseTileLayers(json, insertNull); + mapData.tilesets = ParseTilesets(json); + + return mapData; +}; + +module.exports = ParseWeltmeister; + + +/***/ }), + +/***/ 52833: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tilemaps.Parsers.Impact + */ + +module.exports = { + + ParseTileLayers: __webpack_require__(6656), + ParseTilesets: __webpack_require__(96483), + ParseWeltmeister: __webpack_require__(87021) + +}; + + +/***/ }), + +/***/ 57442: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tilemaps.Parsers + */ + +module.exports = { + + FromOrientationString: __webpack_require__(6641), + Parse: __webpack_require__(46177), + Parse2DArray: __webpack_require__(2342), + ParseCSV: __webpack_require__(82593), + + Impact: __webpack_require__(52833), + Tiled: __webpack_require__(96761) + +}; + + +/***/ }), + +/***/ 51233: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Extend = __webpack_require__(79291); + +/** + * Copy properties from tileset to tiles. + * + * @function Phaser.Tilemaps.Parsers.Tiled.AssignTileProperties + * @since 3.0.0 + * + * @param {Phaser.Tilemaps.MapData} mapData - The Map Data object. + */ +var AssignTileProperties = function (mapData) +{ + var layerData; + var tile; + var sid; + var set; + var row; + + // go through each of the map data layers + for (var i = 0; i < mapData.layers.length; i++) + { + layerData = mapData.layers[i]; + + set = null; + + // rows of tiles + for (var j = 0; j < layerData.data.length; j++) + { + row = layerData.data[j]; + + // individual tiles + for (var k = 0; k < row.length; k++) + { + tile = row[k]; + + if (tile === null || tile.index < 0) + { + continue; + } + + // find the relevant tileset + sid = mapData.tiles[tile.index][2]; + set = mapData.tilesets[sid]; + + // Ensure that a tile's size matches its tileset + tile.width = set.tileWidth; + tile.height = set.tileHeight; + + // if that tile type has any properties, add them to the tile object + if (set.tileProperties && set.tileProperties[tile.index - set.firstgid]) + { + tile.properties = Extend( + tile.properties, set.tileProperties[tile.index - set.firstgid] + ); + } + } + } + } +}; + +module.exports = AssignTileProperties; + + +/***/ }), + +/***/ 41868: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Decode base-64 encoded data, for example as exported by Tiled. + * + * @function Phaser.Tilemaps.Parsers.Tiled.Base64Decode + * @since 3.0.0 + * + * @param {object} data - Base-64 encoded data to decode. + * + * @return {array} Array containing the decoded bytes. + */ +var Base64Decode = function (data) +{ + var binaryString = window.atob(data); + var len = binaryString.length; + var bytes = new Array(len / 4); + + // Interpret binaryString as an array of bytes representing little-endian encoded uint32 values. + for (var i = 0; i < len; i += 4) + { + bytes[i / 4] = ( + binaryString.charCodeAt(i) | + binaryString.charCodeAt(i + 1) << 8 | + binaryString.charCodeAt(i + 2) << 16 | + binaryString.charCodeAt(i + 3) << 24 + ) >>> 0; + } + + return bytes; +}; + +module.exports = Base64Decode; + + +/***/ }), + +/***/ 84101: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Tileset = __webpack_require__(33629); + +/** + * Master list of tiles -> x, y, index in tileset. + * + * @function Phaser.Tilemaps.Parsers.Tiled.BuildTilesetIndex + * @since 3.0.0 + * + * @param {(Phaser.Tilemaps.MapData|Phaser.Tilemaps.Tilemap)} mapData - The Map Data object. + * + * @return {array} An array of Tileset objects. + */ +var BuildTilesetIndex = function (mapData) +{ + var i; + var set; + var tiles = []; + + for (i = 0; i < mapData.imageCollections.length; i++) + { + var collection = mapData.imageCollections[i]; + var images = collection.images; + + for (var j = 0; j < images.length; j++) + { + var image = images[j]; + var offset = { + x: 0, + y: image.height - mapData.tileHeight + }; + + set = new Tileset(image.image, image.gid, image.width, image.height, 0, 0, undefined, undefined, offset); + + set.updateTileData(image.width, image.height); + + mapData.tilesets.push(set); + } + } + + for (i = 0; i < mapData.tilesets.length; i++) + { + set = mapData.tilesets[i]; + + var x = set.tileMargin; + var y = set.tileMargin; + + var count = 0; + var countX = 0; + var countY = 0; + + for (var t = set.firstgid; t < set.firstgid + set.total; t++) + { + // Can add extra properties here as needed + tiles[t] = [ x, y, i ]; + + x += set.tileWidth + set.tileSpacing; + + count++; + + if (count === set.total) + { + break; + } + + countX++; + + if (countX === set.columns) + { + x = set.tileMargin; + y += set.tileHeight + set.tileSpacing; + + countX = 0; + countY++; + + if (countY === set.rows) + { + break; + } + } + } + } + + return tiles; +}; + +module.exports = BuildTilesetIndex; + + +/***/ }), + +/***/ 79677: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Seth Berrier + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); + +/** + * Parse a Tiled group layer and create a state object for inheriting. + * + * @function Phaser.Tilemaps.Parsers.Tiled.CreateGroupLayer + * @since 3.21.0 + * + * @param {object} json - The Tiled JSON object. + * @param {object} [group] - The current group layer from the Tiled JSON file. + * @param {object} [parentState] - The state of the parent group (if any). + * + * @return {object} A group state object with proper values for updating children layers. + */ +var CreateGroupLayer = function (json, group, parentState) +{ + if (!group) + { + // Return a default group state object + return { + i: 0, // Current layer array iterator + layers: json.layers, // Current array of layers + // Values inherited from parent group + name: '', + opacity: 1, + visible: true, + x: 0, + y: 0 + }; + } + + // Compute group layer x, y + var layerX = group.x + GetFastValue(group, 'startx', 0) * json.tilewidth + GetFastValue(group, 'offsetx', 0); + var layerY = group.y + GetFastValue(group, 'starty', 0) * json.tileheight + GetFastValue(group, 'offsety', 0); + + // Compute next state inherited from group + return { + i: 0, + layers: group.layers, + name: parentState.name + group.name + '/', + opacity: parentState.opacity * group.opacity, + visible: parentState.visible && group.visible, + x: parentState.x + layerX, + y: parentState.y + layerY + }; +}; + +module.exports = CreateGroupLayer; + + +/***/ }), + +/***/ 29920: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var FLIPPED_HORIZONTAL = 0x80000000; +var FLIPPED_VERTICAL = 0x40000000; +var FLIPPED_ANTI_DIAGONAL = 0x20000000; // Top-right is swapped with bottom-left corners + +/** + * See Tiled documentation on tile flipping: + * http://docs.mapeditor.org/en/latest/reference/tmx-map-format/ + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseGID + * @since 3.0.0 + * + * @param {number} gid - A Tiled GID. + * + * @return {Phaser.Types.Tilemaps.GIDData} The GID Data. + */ +var ParseGID = function (gid) +{ + var flippedHorizontal = Boolean(gid & FLIPPED_HORIZONTAL); + var flippedVertical = Boolean(gid & FLIPPED_VERTICAL); + var flippedAntiDiagonal = Boolean(gid & FLIPPED_ANTI_DIAGONAL); + gid = gid & ~(FLIPPED_HORIZONTAL | FLIPPED_VERTICAL | FLIPPED_ANTI_DIAGONAL); + + // Parse the flip flags into something Phaser can use + var rotation = 0; + var flipped = false; + + if (flippedHorizontal && flippedVertical && flippedAntiDiagonal) + { + rotation = Math.PI / 2; + flipped = true; + } + else if (flippedHorizontal && flippedVertical && !flippedAntiDiagonal) + { + rotation = Math.PI; + flipped = false; + } + else if (flippedHorizontal && !flippedVertical && flippedAntiDiagonal) + { + rotation = Math.PI / 2; + flipped = false; + } + else if (flippedHorizontal && !flippedVertical && !flippedAntiDiagonal) + { + rotation = 0; + flipped = true; + } + else if (!flippedHorizontal && flippedVertical && flippedAntiDiagonal) + { + rotation = 3 * Math.PI / 2; + flipped = false; + } + else if (!flippedHorizontal && flippedVertical && !flippedAntiDiagonal) + { + rotation = Math.PI; + flipped = true; + } + else if (!flippedHorizontal && !flippedVertical && flippedAntiDiagonal) + { + rotation = 3 * Math.PI / 2; + flipped = true; + } + else if (!flippedHorizontal && !flippedVertical && !flippedAntiDiagonal) + { + rotation = 0; + flipped = false; + } + + return { + gid: gid, + flippedHorizontal: flippedHorizontal, + flippedVertical: flippedVertical, + flippedAntiDiagonal: flippedAntiDiagonal, + rotation: rotation, + flipped: flipped + }; +}; + +module.exports = ParseGID; + + +/***/ }), + +/***/ 12635: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); +var CreateGroupLayer = __webpack_require__(79677); + +/** + * Parses a Tiled JSON object into an array of objects with details about the image layers. + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseImageLayers + * @since 3.0.0 + * + * @param {object} json - The Tiled JSON object. + * + * @return {array} Array of objects that include critical info about the map's image layers + */ +var ParseImageLayers = function (json) +{ + var images = []; + + // State inherited from a parent group + var groupStack = []; + var curGroupState = CreateGroupLayer(json); + + while (curGroupState.i < curGroupState.layers.length || groupStack.length > 0) + { + if (curGroupState.i >= curGroupState.layers.length) + { + // Ensure recursion stack is not empty first + if (groupStack.length < 1) + { + console.warn( + 'TilemapParser.parseTiledJSON - Invalid layer group hierarchy' + ); + break; + } + + // Return to previous recursive state + curGroupState = groupStack.pop(); + continue; + } + + // Get current layer and advance iterator + var curi = curGroupState.layers[curGroupState.i]; + curGroupState.i++; + + if (curi.type !== 'imagelayer') + { + if (curi.type === 'group') + { + // Compute next state inherited from group + var nextGroupState = CreateGroupLayer(json, curi, curGroupState); + + // Preserve current state before recursing + groupStack.push(curGroupState); + curGroupState = nextGroupState; + } + + // Skip this layer OR 'recurse' (iterative style) into the group + continue; + } + + var layerOffsetX = GetFastValue(curi, 'offsetx', 0) + GetFastValue(curi, 'startx', 0); + var layerOffsetY = GetFastValue(curi, 'offsety', 0) + GetFastValue(curi, 'starty', 0); + images.push({ + name: (curGroupState.name + curi.name), + image: curi.image, + x: (curGroupState.x + layerOffsetX + curi.x), + y: (curGroupState.y + layerOffsetY + curi.y), + alpha: (curGroupState.opacity * curi.opacity), + visible: (curGroupState.visible && curi.visible), + properties: GetFastValue(curi, 'properties', {}) + }); + } + + return images; +}; + +module.exports = ParseImageLayers; + + +/***/ }), + +/***/ 46594: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var AssignTileProperties = __webpack_require__(51233); +var BuildTilesetIndex = __webpack_require__(84101); +var CONST = __webpack_require__(91907); +var DeepCopy = __webpack_require__(62644); +var Formats = __webpack_require__(80341); +var FromOrientationString = __webpack_require__(6641); +var MapData = __webpack_require__(87010); +var ParseImageLayers = __webpack_require__(12635); +var ParseObjectLayers = __webpack_require__(22611); +var ParseTileLayers = __webpack_require__(28200); +var ParseTilesets = __webpack_require__(24619); + +/** + * Parses a Tiled JSON object into a new MapData object. + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseJSONTiled + * @since 3.0.0 + * + * @param {string} name - The name of the tilemap, used to set the name on the MapData. + * @param {object} source - The original Tiled JSON object. This is deep copied by this function. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled. If `true`, empty locations will get a value of `null`. If `false`, empty + * location will get a Tile object with an index of -1. If you've a large sparsely populated map and + * the tile data doesn't need to change then setting this value to `true` will help with memory + * consumption. However if your map is small or you need to update the tiles dynamically, then leave + * the default value set. + * + * @return {?Phaser.Tilemaps.MapData} The created MapData object, or `null` if the data can't be parsed. + */ +var ParseJSONTiled = function (name, source, insertNull) +{ + var json = DeepCopy(source); + + // Map data will consist of: layers, objects, images, tilesets, sizes + var mapData = new MapData({ + width: json.width, + height: json.height, + name: name, + tileWidth: json.tilewidth, + tileHeight: json.tileheight, + orientation: FromOrientationString(json.orientation), + format: Formats.TILED_JSON, + version: json.version, + properties: json.properties, + renderOrder: json.renderorder, + infinite: json.infinite + }); + + if (mapData.orientation === CONST.HEXAGONAL) + { + mapData.hexSideLength = json.hexsidelength; + mapData.staggerAxis = json.staggeraxis; + mapData.staggerIndex = json.staggerindex; + + if (mapData.staggerAxis === 'y') + { + var triangleHeight = (mapData.tileHeight - mapData.hexSideLength) / 2; + mapData.widthInPixels = mapData.tileWidth * (mapData.width + 0.5); + mapData.heightInPixels = mapData.height * (mapData.hexSideLength + triangleHeight) + triangleHeight; + } + else + { + var triangleWidth = (mapData.tileWidth - mapData.hexSideLength) / 2; + mapData.widthInPixels = mapData.width * (mapData.hexSideLength + triangleWidth) + triangleWidth; + mapData.heightInPixels = mapData.tileHeight * (mapData.height + 0.5); + } + } + + mapData.layers = ParseTileLayers(json, insertNull); + mapData.images = ParseImageLayers(json); + + var sets = ParseTilesets(json); + + mapData.tilesets = sets.tilesets; + mapData.imageCollections = sets.imageCollections; + + mapData.objects = ParseObjectLayers(json); + + mapData.tiles = BuildTilesetIndex(mapData); + + AssignTileProperties(mapData); + + return mapData; +}; + +module.exports = ParseJSONTiled; + + +/***/ }), + +/***/ 52205: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Pick = __webpack_require__(18254); +var ParseGID = __webpack_require__(29920); + +var copyPoints = function (p) { return { x: p.x, y: p.y }; }; + +var commonObjectProps = [ 'id', 'name', 'type', 'rotation', 'properties', 'visible', 'x', 'y', 'width', 'height' ]; + +/** + * Convert a Tiled object to an internal parsed object normalising and copying properties over, while applying optional x and y offsets. The parsed object will always have the properties `id`, `name`, `type`, `rotation`, `properties`, `visible`, `x`, `y`, `width` and `height`. Other properties will be added according to the object type (such as text, polyline, gid etc.) + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseObject + * @since 3.0.0 + * + * @param {object} tiledObject - Tiled object to convert to an internal parsed object normalising and copying properties over. + * @param {number} [offsetX=0] - Optional additional offset to apply to the object's x property. Defaults to 0. + * @param {number} [offsetY=0] - Optional additional offset to apply to the object's y property. Defaults to 0. + * + * @return {object} The parsed object containing properties read from the Tiled object according to it's type with x and y values updated according to the given offsets. + */ +var ParseObject = function (tiledObject, offsetX, offsetY) +{ + if (offsetX === undefined) { offsetX = 0; } + if (offsetY === undefined) { offsetY = 0; } + + var parsedObject = Pick(tiledObject, commonObjectProps); + + parsedObject.x += offsetX; + parsedObject.y += offsetY; + + if (tiledObject.gid) + { + // Object tiles + var gidInfo = ParseGID(tiledObject.gid); + parsedObject.gid = gidInfo.gid; + parsedObject.flippedHorizontal = gidInfo.flippedHorizontal; + parsedObject.flippedVertical = gidInfo.flippedVertical; + parsedObject.flippedAntiDiagonal = gidInfo.flippedAntiDiagonal; + } + else if (tiledObject.polyline) + { + parsedObject.polyline = tiledObject.polyline.map(copyPoints); + } + else if (tiledObject.polygon) + { + parsedObject.polygon = tiledObject.polygon.map(copyPoints); + } + else if (tiledObject.ellipse) + { + parsedObject.ellipse = tiledObject.ellipse; + } + else if (tiledObject.text) + { + parsedObject.text = tiledObject.text; + } + else if (tiledObject.point) + { + parsedObject.point = true; + } + else + { + // Otherwise, assume it is a rectangle + parsedObject.rectangle = true; + } + + return parsedObject; +}; + +module.exports = ParseObject; + + +/***/ }), + +/***/ 22611: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetFastValue = __webpack_require__(95540); +var ParseObject = __webpack_require__(52205); +var ObjectLayer = __webpack_require__(48700); +var CreateGroupLayer = __webpack_require__(79677); + +/** + * Parses a Tiled JSON object into an array of ObjectLayer objects. + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseObjectLayers + * @since 3.0.0 + * + * @param {object} json - The Tiled JSON object. + * + * @return {array} An array of all object layers in the tilemap as `ObjectLayer`s. + */ +var ParseObjectLayers = function (json) +{ + var objectLayers = []; + + // State inherited from a parent group + var groupStack = []; + var curGroupState = CreateGroupLayer(json); + + while (curGroupState.i < curGroupState.layers.length || groupStack.length > 0) + { + if (curGroupState.i >= curGroupState.layers.length) + { + // Ensure recursion stack is not empty first + if (groupStack.length < 1) + { + console.warn( + 'TilemapParser.parseTiledJSON - Invalid layer group hierarchy' + ); + break; + } + + // Return to previous recursive state + curGroupState = groupStack.pop(); + continue; + } + + // Get current layer and advance iterator + var curo = curGroupState.layers[curGroupState.i]; + curGroupState.i++; + + // Modify inherited properties + curo.opacity *= curGroupState.opacity; + curo.visible = curGroupState.visible && curo.visible; + + if (curo.type !== 'objectgroup') + { + if (curo.type === 'group') + { + // Compute next state inherited from group + var nextGroupState = CreateGroupLayer(json, curo, curGroupState); + + // Preserve current state before recursing + groupStack.push(curGroupState); + curGroupState = nextGroupState; + } + + // Skip this layer OR 'recurse' (iterative style) into the group + continue; + } + + curo.name = curGroupState.name + curo.name; + var offsetX = curGroupState.x + GetFastValue(curo, 'startx', 0) + GetFastValue(curo, 'offsetx', 0); + var offsetY = curGroupState.y + GetFastValue(curo, 'starty', 0) + GetFastValue(curo, 'offsety', 0); + + var objects = []; + for (var j = 0; j < curo.objects.length; j++) + { + var parsedObject = ParseObject(curo.objects[j], offsetX, offsetY); + + objects.push(parsedObject); + } + + var objectLayer = new ObjectLayer(curo); + objectLayer.objects = objects; + + objectLayers.push(objectLayer); + } + + return objectLayers; +}; + +module.exports = ParseObjectLayers; + + +/***/ }), + +/***/ 28200: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Base64Decode = __webpack_require__(41868); +var CONST = __webpack_require__(91907); +var CreateGroupLayer = __webpack_require__(79677); +var FromOrientationString = __webpack_require__(6641); +var GetFastValue = __webpack_require__(95540); +var LayerData = __webpack_require__(14977); +var ParseGID = __webpack_require__(29920); +var Tile = __webpack_require__(23029); + +/** + * Parses all tilemap layers in a Tiled JSON object into new LayerData objects. + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseTileLayers + * @since 3.0.0 + * + * @param {object} json - The Tiled JSON object. + * @param {boolean} insertNull - Controls how empty tiles, tiles with an index of -1, in the map + * data are handled (see {@link Phaser.Tilemaps.Parsers.Tiled.ParseJSONTiled}). + * + * @return {Phaser.Tilemaps.LayerData[]} - An array of LayerData objects, one for each entry in + * json.layers with the type 'tilelayer'. + */ +var ParseTileLayers = function (json, insertNull) +{ + var infiniteMap = GetFastValue(json, 'infinite', false); + var tileLayers = []; + + // State inherited from a parent group + var groupStack = []; + var curGroupState = CreateGroupLayer(json); + + while (curGroupState.i < curGroupState.layers.length || groupStack.length > 0) + { + if (curGroupState.i >= curGroupState.layers.length) + { + // Ensure recursion stack is not empty first + if (groupStack.length < 1) + { + console.warn( + 'TilemapParser.parseTiledJSON - Invalid layer group hierarchy' + ); + break; + } + + // Return to previous recursive state + curGroupState = groupStack.pop(); + continue; + } + + var curl = curGroupState.layers[curGroupState.i]; + curGroupState.i++; + + if (curl.type !== 'tilelayer') + { + if (curl.type === 'group') + { + // Compute next state inherited from group + var nextGroupState = CreateGroupLayer(json, curl, curGroupState); + + // Preserve current state before recursing + groupStack.push(curGroupState); + curGroupState = nextGroupState; + } + + // Skip this layer OR 'recurse' (iterative style) into the group + continue; + } + + // Base64 decode data if necessary. NOTE: uncompressed base64 only. + if (curl.compression) + { + console.warn( + 'TilemapParser.parseTiledJSON - Layer compression is unsupported, skipping layer \'' + + curl.name + '\'' + ); + continue; + } + else if (curl.encoding && curl.encoding === 'base64') + { + // Chunks for an infinite map + if (curl.chunks) + { + for (var i = 0; i < curl.chunks.length; i++) + { + curl.chunks[i].data = Base64Decode(curl.chunks[i].data); + } + } + + // Non-infinite map data + if (curl.data) + { + curl.data = Base64Decode(curl.data); + } + + delete curl.encoding; // Allow the same map to be parsed multiple times + } + + // This is an array containing the tile indexes, one after the other. -1 = no tile, + // everything else = the tile index (starting at 1 for Tiled, 0 for CSV) If the map + // contains multiple tilesets then the indexes are relative to that which the set starts + // from. Need to set which tileset in the cache = which tileset in the JSON, if you do this + // manually it means you can use the same map data but a new tileset. + + var layerData; + var gidInfo; + var tile; + var blankTile; + var triangleHeight; + var triangleWidth; + + var output = []; + var x = 0; + + if (infiniteMap) + { + var layerOffsetX = (GetFastValue(curl, 'startx', 0) + curl.x); + var layerOffsetY = (GetFastValue(curl, 'starty', 0) + curl.y); + + layerData = new LayerData({ + name: (curGroupState.name + curl.name), + id: curl.id, + x: (curGroupState.x + GetFastValue(curl, 'offsetx', 0) + layerOffsetX * json.tilewidth), + y: (curGroupState.y + GetFastValue(curl, 'offsety', 0) + layerOffsetY * json.tileheight), + width: curl.width, + height: curl.height, + tileWidth: json.tilewidth, + tileHeight: json.tileheight, + alpha: (curGroupState.opacity * curl.opacity), + visible: (curGroupState.visible && curl.visible), + properties: GetFastValue(curl, 'properties', []), + orientation: FromOrientationString(json.orientation) + }); + + if (layerData.orientation === CONST.HEXAGONAL) + { + layerData.hexSideLength = json.hexsidelength; + layerData.staggerAxis = json.staggeraxis; + layerData.staggerIndex = json.staggerindex; + + if (layerData.staggerAxis === 'y') + { + triangleHeight = (layerData.tileHeight - layerData.hexSideLength) / 2; + layerData.widthInPixels = layerData.tileWidth * (layerData.width + 0.5); + layerData.heightInPixels = layerData.height * (layerData.hexSideLength + triangleHeight) + triangleHeight; + } + else + { + triangleWidth = (layerData.tileWidth - layerData.hexSideLength) / 2; + layerData.widthInPixels = layerData.width * (layerData.hexSideLength + triangleWidth) + triangleWidth; + layerData.heightInPixels = layerData.tileHeight * (layerData.height + 0.5); + } + } + + for (var c = 0; c < curl.height; c++) + { + output[c] = [ null ]; + + for (var j = 0; j < curl.width; j++) + { + output[c][j] = null; + } + } + + for (c = 0, len = curl.chunks.length; c < len; c++) + { + var chunk = curl.chunks[c]; + + var offsetX = (chunk.x - layerOffsetX); + var offsetY = (chunk.y - layerOffsetY); + + var y = 0; + + for (var t = 0, len2 = chunk.data.length; t < len2; t++) + { + var newOffsetX = x + offsetX; + var newOffsetY = y + offsetY; + + gidInfo = ParseGID(chunk.data[t]); + + // index, x, y, width, height + if (gidInfo.gid > 0) + { + tile = new Tile(layerData, gidInfo.gid, newOffsetX, newOffsetY, json.tilewidth, json.tileheight); + + // Turning Tiled's FlippedHorizontal, FlippedVertical and FlippedAntiDiagonal + // propeties into flipX, flipY and rotation + tile.rotation = gidInfo.rotation; + tile.flipX = gidInfo.flipped; + + output[newOffsetY][newOffsetX] = tile; + } + else + { + blankTile = insertNull + ? null + : new Tile(layerData, -1, newOffsetX, newOffsetY, json.tilewidth, json.tileheight); + + output[newOffsetY][newOffsetX] = blankTile; + } + + x++; + + if (x === chunk.width) + { + y++; + x = 0; + } + } + } + } + else + { + layerData = new LayerData({ + name: (curGroupState.name + curl.name), + id: curl.id, + x: (curGroupState.x + GetFastValue(curl, 'offsetx', 0) + curl.x), + y: (curGroupState.y + GetFastValue(curl, 'offsety', 0) + curl.y), + width: curl.width, + height: curl.height, + tileWidth: json.tilewidth, + tileHeight: json.tileheight, + alpha: (curGroupState.opacity * curl.opacity), + visible: (curGroupState.visible && curl.visible), + properties: GetFastValue(curl, 'properties', []), + orientation: FromOrientationString(json.orientation) + }); + + if (layerData.orientation === CONST.HEXAGONAL) + { + layerData.hexSideLength = json.hexsidelength; + layerData.staggerAxis = json.staggeraxis; + layerData.staggerIndex = json.staggerindex; + + if (layerData.staggerAxis === 'y') + { + triangleHeight = (layerData.tileHeight - layerData.hexSideLength) / 2; + layerData.widthInPixels = layerData.tileWidth * (layerData.width + 0.5); + layerData.heightInPixels = layerData.height * (layerData.hexSideLength + triangleHeight) + triangleHeight; + } + else + { + triangleWidth = (layerData.tileWidth - layerData.hexSideLength) / 2; + layerData.widthInPixels = layerData.width * (layerData.hexSideLength + triangleWidth) + triangleWidth; + layerData.heightInPixels = layerData.tileHeight * (layerData.height + 0.5); + } + } + var row = []; + + // Loop through the data field in the JSON. + for (var k = 0, len = curl.data.length; k < len; k++) + { + gidInfo = ParseGID(curl.data[k]); + + // index, x, y, width, height + if (gidInfo.gid > 0) + { + tile = new Tile(layerData, gidInfo.gid, x, output.length, json.tilewidth, json.tileheight); + + // Turning Tiled's FlippedHorizontal, FlippedVertical and FlippedAntiDiagonal + // propeties into flipX, flipY and rotation + tile.rotation = gidInfo.rotation; + tile.flipX = gidInfo.flipped; + + row.push(tile); + } + else + { + blankTile = insertNull + ? null + : new Tile(layerData, -1, x, output.length, json.tilewidth, json.tileheight); + row.push(blankTile); + } + + x++; + + if (x === curl.width) + { + output.push(row); + x = 0; + row = []; + } + } + } + + layerData.data = output; + tileLayers.push(layerData); + } + + return tileLayers; +}; + +module.exports = ParseTileLayers; + + +/***/ }), + +/***/ 24619: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Tileset = __webpack_require__(33629); +var ImageCollection = __webpack_require__(16536); +var ParseObject = __webpack_require__(52205); +var ParseWangsets = __webpack_require__(57880); + +/** + * Tilesets and Image Collections. + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseTilesets + * @since 3.0.0 + * + * @param {object} json - The Tiled JSON data. + * + * @return {object} An object containing the tileset and image collection data. + */ +var ParseTilesets = function (json) +{ + var tilesets = []; + var imageCollections = []; + var lastSet = null; + var stringID; + + for (var i = 0; i < json.tilesets.length; i++) + { + // name, firstgid, width, height, margin, spacing, properties + var set = json.tilesets[i]; + + if (set.source) + { + console.warn('External tilesets unsupported. Use Embed Tileset and re-export'); + } + else if (set.image) + { + var newSet = new Tileset(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing, undefined, undefined, set.tileoffset); + + if (json.version > 1) + { + var datas = undefined; + var props = undefined; + + if (Array.isArray(set.tiles)) + { + datas = datas || {}; + props = props || {}; + + // Tiled 1.2+ + for (var t = 0; t < set.tiles.length; t++) + { + var tile = set.tiles[t]; + + // Convert tileproperties. + if (tile.properties) + { + var newPropData = {}; + + tile.properties.forEach(function (propData) + { + newPropData[propData['name']] = propData['value']; + }); + + props[tile.id] = newPropData; + } + + // Convert objectgroup + if (tile.objectgroup) + { + (datas[tile.id] || (datas[tile.id] = {})).objectgroup = tile.objectgroup; + + if (tile.objectgroup.objects) + { + var parsedObjects2 = tile.objectgroup.objects.map(function (obj) + { + return ParseObject(obj); + }); + + datas[tile.id].objectgroup.objects = parsedObjects2; + } + } + + // Copy animation data + if (tile.animation) + { + (datas[tile.id] || (datas[tile.id] = {})).animation = tile.animation; + } + + // Copy tile `type` field + // (see https://doc.mapeditor.org/en/latest/manual/custom-properties/#typed-tiles). + if (tile.type) + { + (datas[tile.id] || (datas[tile.id] = {})).type = tile.type; + } + } + + // Sum up animation length. + for (var tid in datas) + { + var animData = datas[tid].animation; + + if (animData) + { + var animTime = 0; + + for (var j = 0; j < animData.length; j++) + { + animData[j].startTime = animTime; + animTime += animData[j].duration; + } + + datas[tid].animationDuration = animTime; + } + } + } + + if (Array.isArray(set.wangsets)) + { + datas = datas || {}; + props = props || {}; + + ParseWangsets(set.wangsets, datas); + } + + if (datas) // Implies also props is set. + { + newSet.tileData = datas; + newSet.tileProperties = props; + } + } + else + { + // Tiled 1 + + // Properties stored per-tile in object with string indexes starting at "0" + if (set.tileproperties) + { + newSet.tileProperties = set.tileproperties; + } + + // Object & terrain shapes stored per-tile in object with string indexes starting at "0" + if (set.tiles) + { + newSet.tileData = set.tiles; + + // Parse the objects into Phaser format to match handling of other Tiled objects + for (stringID in newSet.tileData) + { + var objectGroup = newSet.tileData[stringID].objectgroup; + + if (objectGroup && objectGroup.objects) + { + var parsedObjects1 = objectGroup.objects.map(function (obj) + { + return ParseObject(obj); + }); + + newSet.tileData[stringID].objectgroup.objects = parsedObjects1; + } + } + } + } + + // For a normal sliced tileset the row/count/size information is computed when updated. + // This is done (again) after the image is set. + newSet.updateTileData(set.imagewidth, set.imageheight); + + tilesets.push(newSet); + } + else + { + var newCollection = new ImageCollection(set.name, set.firstgid, set.tilewidth, set.tileheight, set.margin, set.spacing, set.properties); + + var maxId = 0; + + for (t = 0; t < set.tiles.length; t++) + { + tile = set.tiles[t]; + + var image = tile.image; + var tileId = parseInt(tile.id, 10); + var gid = set.firstgid + tileId; + var width = tile.imagewidth; + var height = tile.imageheight; + newCollection.addImage(gid, image, width, height); + + maxId = Math.max(tileId, maxId); + } + + newCollection.maxId = maxId; + + imageCollections.push(newCollection); + } + + // We've got a new Tileset, so set the lastgid into the previous one + if (lastSet) + { + lastSet.lastgid = set.firstgid - 1; + } + + lastSet = set; + } + + return { tilesets: tilesets, imageCollections: imageCollections }; +}; + +module.exports = ParseTilesets; + + +/***/ }), + +/***/ 57880: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Parses out the Wangset information from Tiled 1.1.5+ map data, if present. + * + * Since a given tile can be in more than one wangset, the resulting properties + * are nested. `tile.data.wangid[someWangsetName]` will return the array-based wang id in + * this implementation. + * + * Note that we're not guaranteed that there will be any 'normal' tiles if the only + * thing in the tilset are wangtile definitions, so this has to be parsed separately. + * + * See https://doc.mapeditor.org/en/latest/manual/using-wang-tiles/ for more information. + * + * @function Phaser.Tilemaps.Parsers.Tiled.ParseWangsets + * @since 3.53.0 + * + * @param {Array.} wangsets - The array of wangset objects (parsed from JSON) + * @param {object} datas - The field into which to put wangset data from Tiled. + * + * @return {object} An object containing the tileset and image collection data. + */ +var ParseWangsets = function (wangsets, datas) +{ + for (var w = 0; w < wangsets.length; w++) + { + var wangset = wangsets[w]; + var identifier = w; + + if (wangset.name && wangset.name !== '') + { + identifier = wangset.name; + } + + if (Array.isArray(wangset.wangtiles) && wangset.wangtiles.length > 0) + { + var edgeColors = {}; + var cornerColors = {}; + + var c; + var color; + var colorIndex; + + // Tiled before v2020.09.09 + if (Array.isArray(wangset.edgecolors)) + { + for (c = 0; c < wangset.edgecolors.length; c++) + { + colorIndex = 1 + c; + color = wangset.edgecolors[c]; + + if (color.name !== '') + { + edgeColors[colorIndex] = color.name; + } + } + } + + if (Array.isArray(wangset.cornercolors)) + { + for (c = 0; c < wangset.cornercolors.length; c++) + { + colorIndex = 1 + c; + color = wangset.cornercolors[c]; + + if (color.name !== '') + { + cornerColors[colorIndex] = color.name; + } + } + } + + // Tiled after v2020.09.09 + if (Array.isArray(wangset.colors)) + { + for (c = 0; c < wangset.colors.length; c++) + { + color = wangset.colors[c]; + colorIndex = 1 + c; + + if (color.name !== '') + { + edgeColors[colorIndex] = cornerColors[colorIndex] = color.name; + } + } + } + + // The wangid layout is north, northeast, east, southeast, etc. + var idLayout = [ + edgeColors, cornerColors, edgeColors, cornerColors, + edgeColors, cornerColors, edgeColors, cornerColors + ]; + + for (var t = 0; t < wangset.wangtiles.length; t++) + { + var wangtile = wangset.wangtiles[t]; + + var obj = (datas[wangtile.tileid] || (datas[wangtile.tileid] = {})); + + obj = (obj.wangid || (obj.wangid = {})); + + var wangid = []; + + for (var i = 0; i < Math.min(idLayout.length, wangtile.wangid.length); i++) + { + color = wangtile.wangid[i]; + + if (color === 0) + { + wangid.push(undefined); + continue; + } + + var renamed = idLayout[i][color]; + + if (renamed !== undefined) + { + wangid.push(renamed); + continue; + } + + wangid.push(color); + } + + obj[identifier] = wangid; + } + } + } +}; + +module.exports = ParseWangsets; + + +/***/ }), + +/***/ 96761: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tilemaps.Parsers.Tiled + */ + +module.exports = { + + AssignTileProperties: __webpack_require__(51233), + Base64Decode: __webpack_require__(41868), + BuildTilesetIndex: __webpack_require__(84101), + CreateGroupLayer: __webpack_require__(79677), + ParseGID: __webpack_require__(29920), + ParseImageLayers: __webpack_require__(12635), + ParseJSONTiled: __webpack_require__(46594), + ParseObject: __webpack_require__(52205), + ParseObjectLayers: __webpack_require__(22611), + ParseTileLayers: __webpack_require__(28200), + ParseTilesets: __webpack_require__(24619) + +}; + + +/***/ }), + +/***/ 33385: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); +var TimerEvent = __webpack_require__(94880); +var Remove = __webpack_require__(72905); + +/** + * @classdesc + * The Clock is a Scene plugin which creates and updates Timer Events for its Scene. + * + * @class Clock + * @memberof Phaser.Time + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene which owns this Clock. + */ +var Clock = new Class({ + + initialize: + + function Clock (scene) + { + /** + * The Scene which owns this Clock. + * + * @name Phaser.Time.Clock#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The Scene Systems object of the Scene which owns this Clock. + * + * @name Phaser.Time.Clock#systems + * @type {Phaser.Scenes.Systems} + * @since 3.0.0 + */ + this.systems = scene.sys; + + /** + * The current time of the Clock, in milliseconds. + * + * If accessed externally, this is equivalent to the `time` parameter normally passed to a Scene's `update` method. + * + * @name Phaser.Time.Clock#now + * @type {number} + * @since 3.0.0 + */ + this.now = 0; + + /** + * The time the Clock (and Scene) started, in milliseconds. + * + * This can be compared to the `time` parameter passed to a Scene's `update` method. + * + * @name Phaser.Time.Clock#startTime + * @type {number} + * @since 3.60.0 + */ + this.startTime = 0; + + /** + * The scale of the Clock's time delta. + * + * The time delta is the time elapsed between two consecutive frames and influences the speed of time for this Clock and anything which uses it, such as its Timer Events. Values higher than 1 increase the speed of time, while values smaller than 1 decrease it. A value of 0 freezes time and is effectively equivalent to pausing the Clock. + * + * @name Phaser.Time.Clock#timeScale + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.timeScale = 1; + + /** + * Whether the Clock is paused (`true`) or active (`false`). + * + * When paused, the Clock will not update any of its Timer Events, thus freezing time. + * + * @name Phaser.Time.Clock#paused + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.paused = false; + + /** + * An array of all Timer Events whose delays haven't expired - these are actively updating Timer Events. + * + * @name Phaser.Time.Clock#_active + * @type {Phaser.Time.TimerEvent[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._active = []; + + /** + * An array of all Timer Events which will be added to the Clock at the start of the next frame. + * + * @name Phaser.Time.Clock#_pendingInsertion + * @type {Phaser.Time.TimerEvent[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._pendingInsertion = []; + + /** + * An array of all Timer Events which will be removed from the Clock at the start of the next frame. + * + * @name Phaser.Time.Clock#_pendingRemoval + * @type {Phaser.Time.TimerEvent[]} + * @private + * @default [] + * @since 3.0.0 + */ + this._pendingRemoval = []; + + scene.sys.events.once(SceneEvents.BOOT, this.boot, this); + scene.sys.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Time.Clock#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + // Sync with the TimeStep + this.now = this.systems.game.loop.time; + + this.systems.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Time.Clock#start + * @private + * @since 3.5.0 + */ + start: function () + { + this.startTime = this.systems.game.loop.time; + + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.PRE_UPDATE, this.preUpdate, this); + eventEmitter.on(SceneEvents.UPDATE, this.update, this); + eventEmitter.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Creates a Timer Event and adds it to this Clock at the start of the next frame. + * + * You can pass in either a `TimerEventConfig` object, from with a new `TimerEvent` will + * be created, or you can pass in a `TimerEvent` instance. + * + * If passing an instance please make sure that this instance hasn't been used before. + * If it has ever entered a 'completed' state then it will no longer be suitable to + * run again. + * + * Also, if the `TimerEvent` instance is being used by _another_ Clock (in another Scene) + * it will still be updated by that Clock as well, so be careful when using this feature. + * + * @method Phaser.Time.Clock#addEvent + * @since 3.0.0 + * + * @param {(Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig)} config - The configuration for the Timer Event, or an existing Timer Event object. + * + * @return {Phaser.Time.TimerEvent} The Timer Event which was created, or passed in. + */ + addEvent: function (config) + { + var event; + + if (config instanceof TimerEvent) + { + event = config; + + this.removeEvent(event); + + event.elapsed = event.startAt; + event.hasDispatched = false; + event.repeatCount = (event.repeat === -1 || event.loop) ? 999999999999 : event.repeat; + + if (event.delay <= 0 && event.repeatCount > 0) + { + throw new Error('TimerEvent infinite loop created via zero delay'); + } + } + else + { + event = new TimerEvent(config); + } + + this._pendingInsertion.push(event); + + return event; + }, + + /** + * Creates a Timer Event and adds it to the Clock at the start of the frame. + * + * This is a shortcut for {@link #addEvent} which can be shorter and is compatible with the syntax of the GreenSock Animation Platform (GSAP). + * + * @method Phaser.Time.Clock#delayedCall + * @since 3.0.0 + * + * @param {number} delay - The delay of the function call, in milliseconds. + * @param {function} callback - The function to call after the delay expires. + * @param {Array.<*>} [args] - The arguments to call the function with. + * @param {*} [callbackScope] - The scope (`this` object) to call the function with. + * + * @return {Phaser.Time.TimerEvent} The Timer Event which was created. + */ + delayedCall: function (delay, callback, args, callbackScope) + { + return this.addEvent({ delay: delay, callback: callback, args: args, callbackScope: callbackScope }); + }, + + /** + * Clears and recreates the array of pending Timer Events. + * + * @method Phaser.Time.Clock#clearPendingEvents + * @since 3.0.0 + * + * @return {this} - This Clock instance. + */ + clearPendingEvents: function () + { + this._pendingInsertion = []; + + return this; + }, + + /** + * Removes the given Timer Event, or an array of Timer Events, from this Clock. + * + * The events are removed from all internal lists (active, pending and removal), + * freeing the event up to be re-used. + * + * @method Phaser.Time.Clock#removeEvent + * @since 3.50.0 + * + * @param {(Phaser.Time.TimerEvent | Phaser.Time.TimerEvent[])} events - The Timer Event, or an array of Timer Events, to remove from this Clock. + * + * @return {this} - This Clock instance. + */ + removeEvent: function (events) + { + if (!Array.isArray(events)) + { + events = [ events ]; + } + + for (var i = 0; i < events.length; i++) + { + var event = events[i]; + + Remove(this._pendingRemoval, event); + Remove(this._pendingInsertion, event); + Remove(this._active, event); + } + + return this; + }, + + /** + * Schedules all active Timer Events for removal at the start of the frame. + * + * @method Phaser.Time.Clock#removeAllEvents + * @since 3.0.0 + * + * @return {this} - This Clock instance. + */ + removeAllEvents: function () + { + this._pendingRemoval = this._pendingRemoval.concat(this._active); + + return this; + }, + + /** + * Updates the arrays of active and pending Timer Events. Called at the start of the frame. + * + * @method Phaser.Time.Clock#preUpdate + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + preUpdate: function () + { + var toRemove = this._pendingRemoval.length; + var toInsert = this._pendingInsertion.length; + + if (toRemove === 0 && toInsert === 0) + { + // Quick bail + return; + } + + var i; + var event; + + // Delete old events + for (i = 0; i < toRemove; i++) + { + event = this._pendingRemoval[i]; + + var index = this._active.indexOf(event); + + if (index > -1) + { + this._active.splice(index, 1); + } + + // Pool them? + event.destroy(); + } + + for (i = 0; i < toInsert; i++) + { + event = this._pendingInsertion[i]; + + this._active.push(event); + } + + // Clear the lists + this._pendingRemoval.length = 0; + this._pendingInsertion.length = 0; + }, + + /** + * Updates the Clock's internal time and all of its Timer Events. + * + * @method Phaser.Time.Clock#update + * @since 3.0.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + update: function (time, delta) + { + this.now = time; + + if (this.paused) + { + return; + } + + delta *= this.timeScale; + + for (var i = 0; i < this._active.length; i++) + { + var event = this._active[i]; + + if (event.paused) + { + continue; + } + + // Use delta time to increase elapsed. + // Avoids needing to adjust for pause / resume. + // Automatically smoothed by TimeStep class. + // In testing accurate to +- 1ms! + event.elapsed += delta * event.timeScale; + + if (event.elapsed >= event.delay) + { + var remainder = event.elapsed - event.delay; + + // Limit it, in case it's checked in the callback + event.elapsed = event.delay; + + // Process the event + if (!event.hasDispatched && event.callback) + { + event.hasDispatched = true; + event.callback.apply(event.callbackScope, event.args); + } + + if (event.repeatCount > 0) + { + event.repeatCount--; + + // Very short delay + if (remainder >= event.delay) + { + while ((remainder >= event.delay) && (event.repeatCount > 0)) + { + if (event.callback) + { + event.callback.apply(event.callbackScope, event.args); + } + + remainder -= event.delay; + event.repeatCount--; + } + } + + event.elapsed = remainder; + event.hasDispatched = false; + } + else if (event.hasDispatched) + { + this._pendingRemoval.push(event); + } + } + } + }, + + /** + * The Scene that owns this plugin is shutting down. + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Time.Clock#shutdown + * @private + * @since 3.0.0 + */ + shutdown: function () + { + var i; + + for (i = 0; i < this._pendingInsertion.length; i++) + { + this._pendingInsertion[i].destroy(); + } + + for (i = 0; i < this._active.length; i++) + { + this._active[i].destroy(); + } + + for (i = 0; i < this._pendingRemoval.length; i++) + { + this._pendingRemoval[i].destroy(); + } + + this._active.length = 0; + this._pendingRemoval.length = 0; + this._pendingInsertion.length = 0; + + var eventEmitter = this.systems.events; + + eventEmitter.off(SceneEvents.PRE_UPDATE, this.preUpdate, this); + eventEmitter.off(SceneEvents.UPDATE, this.update, this); + eventEmitter.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Time.Clock#destroy + * @private + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.scene.sys.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.systems = null; + } + +}); + +PluginCache.register('Clock', Clock, 'time'); + +module.exports = Clock; + + +/***/ }), + +/***/ 96120: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var GameObjectFactory = __webpack_require__(39429); +var GetFastValue = __webpack_require__(95540); +var SceneEvents = __webpack_require__(44594); +var Events = __webpack_require__(89809); + +/** + * @classdesc + * A Timeline is a way to schedule events to happen at specific times in the future. + * + * You can think of it as an event sequencer for your game, allowing you to schedule the + * running of callbacks, events and other actions at specific times in the future. + * + * A Timeline is a Scene level system, meaning you can have as many Timelines as you like, each + * belonging to a different Scene. You can also have multiple Timelines running at the same time. + * + * If the Scene is paused, the Timeline will also pause. If the Scene is destroyed, the Timeline + * will be automatically destroyed. However, you can control the Timeline directly, pausing, + * resuming and stopping it at any time. + * + * Create an instance of a Timeline via the Game Object Factory: + * + * ```js + * const timeline = this.add.timeline(); + * ``` + * + * The Timeline always starts paused. You must call `play` on it to start it running. + * + * You can also pass in a configuration object on creation, or an array of them: + * + * ```js + * const timeline = this.add.timeline({ + * at: 1000, + * run: () => { + * this.add.sprite(400, 300, 'logo'); + * } + * }); + * + * timeline.play(); + * ``` + * + * In this example we sequence a few different events: + * + * ```js + * const timeline = this.add.timeline([ + * { + * at: 1000, + * run: () => { this.logo = this.add.sprite(400, 300, 'logo'); }, + * sound: 'TitleMusic' + * }, + * { + * at: 2500, + * tween: { + * targets: this.logo, + * y: 600, + * yoyo: true + * }, + * sound: 'Explode' + * }, + * { + * at: 8000, + * event: 'HURRY_PLAYER', + * target: this.background, + * set: { + * tint: 0xff0000 + * } + * } + * ]); + * + * timeline.play(); + * ``` + * + * The Timeline can also be looped with the repeat method: + * ```js + * timeline.repeat().play(); + * ``` + * + * There are lots of options available to you via the configuration object. See the + * {@link Phaser.Types.Time.TimelineEventConfig} typedef for more details. + * + * @class Timeline + * @extends Phaser.Events.EventEmitter + * @memberof Phaser.Time + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Scene} scene - The Scene which owns this Timeline. + * @param {Phaser.Types.Time.TimelineEventConfig|Phaser.Types.Time.TimelineEventConfig[]} [config] - The configuration object for this Timeline Event, or an array of them. + */ +var Timeline = new Class({ + + Extends: EventEmitter, + + initialize: + + function Timeline (scene, config) + { + EventEmitter.call(this); + + /** + * The Scene to which this Timeline belongs. + * + * @name Phaser.Time.Timeline#scene + * @type {Phaser.Scene} + * @since 3.60.0 + */ + this.scene = scene; + + /** + * A reference to the Scene Systems. + * + * @name Phaser.Time.Timeline#systems + * @type {Phaser.Scenes.Systems} + * @since 3.60.0 + */ + this.systems = scene.sys; + + /** + * The elapsed time counter. + * + * Treat this as read-only. + * + * @name Phaser.Time.Timeline#elapsed + * @type {number} + * @since 3.60.0 + */ + this.elapsed = 0; + + /** + * The Timeline's delta time scale. + * + * Values higher than 1 increase the speed of time, while values smaller than 1 decrease it. + * A value of 0 freezes time and is effectively equivalent to pausing the Timeline. + * + * This doesn't affect the delta time scale of any Tweens created by the Timeline. + * You will have to set the `timeScale` of each Tween or the Tween Manager if you want them to match. + * + * @name Phaser.Time.Timeline#timeScale + * @type {number} + * @default + * @since 3.85.0 + */ + this.timeScale = 1; + + /** + * Whether the Timeline is running (`true`) or active (`false`). + * + * When paused, the Timeline will not run any of its actions. + * + * By default a Timeline is always paused and should be started by + * calling the `Timeline.play` method. + * + * You can use the `Timeline.pause` and `Timeline.resume` methods to control + * this value in a chainable way. + * + * @name Phaser.Time.Timeline#paused + * @type {boolean} + * @default true + * @since 3.60.0 + */ + this.paused = true; + + /** + * Whether the Timeline is complete (`true`) or not (`false`). + * + * A Timeline is considered complete when all of its events have been run. + * + * If you wish to reset a Timeline after it has completed, you can do so + * by calling the `Timeline.reset` method. + * + * You can also use the `Timeline.stop` method to stop a running Timeline, + * at any point, without resetting it. + * + * @name Phaser.Time.Timeline#complete + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.complete = false; + + /** + * The total number of events that have been run. + * + * This value is reset to zero if the Timeline is restarted. + * + * Treat this as read-only. + * + * @name Phaser.Time.Timeline#totalComplete + * @type {number} + * @since 3.60.0 + */ + this.totalComplete = 0; + + /** + * The number of times this timeline should loop. + * + * If this value is -1 or any negative number this Timeline will not stop. + * + * @name Phaser.Time.Timeline#loop + * @type {number} + * @since 3.80.0 + */ + this.loop = 0; + + /** + * The number of times this Timeline has looped. + * + * This value is incremented each loop if looping is enabled. + * + * @name Phaser.Time.Timeline#iteration + * @type {number} + * @since 3.80.0 + */ + this.iteration = 0; + + /** + * An array of all the Timeline Events. + * + * @name Phaser.Time.Timeline#events + * @type {Phaser.Types.Time.TimelineEvent[]} + * @since 3.60.0 + */ + this.events = []; + + var eventEmitter = this.systems.events; + + eventEmitter.on(SceneEvents.PRE_UPDATE, this.preUpdate, this); + eventEmitter.on(SceneEvents.UPDATE, this.update, this); + eventEmitter.once(SceneEvents.SHUTDOWN, this.destroy, this); + + if (config) + { + this.add(config); + } + }, + + /** + * Updates the elapsed time counter, if this Timeline is not paused. + * + * @method Phaser.Time.Timeline#preUpdate + * @since 3.60.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + preUpdate: function (time, delta) + { + if (this.paused) + { + return; + } + + this.elapsed += delta * this.timeScale; + }, + + /** + * Called automatically by the Scene update step. + * + * Iterates through all of the Timeline Events and checks to see if they should be run. + * + * If they should be run, then the `TimelineEvent.action` callback is invoked. + * + * If the `TimelineEvent.once` property is `true` then the event is removed from the Timeline. + * + * If the `TimelineEvent.event` property is set then the Timeline emits that event. + * + * If the `TimelineEvent.run` property is set then the Timeline invokes that method. + * + * If the `TimelineEvent.loop` property is set then the Timeline invokes that method when repeated. + * + * If the `TimelineEvent.target` property is set then the Timeline invokes the `run` method on that target. + * + * @method Phaser.Time.Timeline#update + * @fires Phaser.Time.Events#COMPLETE + * @since 3.60.0 + * + * @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout. + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + update: function () + { + if (this.paused || this.complete) + { + return; + } + + var i; + var events = this.events; + var removeSweep = false; + var sys = this.systems; + var target; + + for (i = 0; i < events.length; i++) + { + var event = events[i]; + + if (!event.complete && event.time <= this.elapsed) + { + event.complete = true; + + this.totalComplete++; + + target = (event.target) ? event.target : this; + + if (event.if) + { + if (!event.if.call(target, event)) + { + continue; + } + } + + if (event.once) + { + removeSweep = true; + } + + if (event.set && event.target) + { + // set is an object of key value pairs, apply them to target + for (var key in event.set) + { + event.target[key] = event.set[key]; + } + } + + if (this.iteration) + { + event.repeat++; + } + + if (event.loop && event.repeat) + { + event.loop.call(target); + } + + if (event.tween) + { + event.tweenInstance = sys.tweens.add(event.tween); + } + + if (event.sound) + { + if (typeof event.sound === 'string') + { + sys.sound.play(event.sound); + } + else + { + sys.sound.play(event.sound.key, event.sound.config); + } + } + + if (event.event) + { + this.emit(event.event, target); + } + + if (event.run) + { + event.run.call(target); + } + + if (event.stop) + { + this.stop(); + } + } + } + + if (removeSweep) + { + for (i = 0; i < events.length; i++) + { + if (events[i].complete && events[i].once) + { + events.splice(i, 1); + + i--; + } + } + } + + // It may be greater than the length if events have been removed + if (this.totalComplete >= events.length) + { + if (this.loop !== 0 && (this.loop === -1 || this.loop > this.iteration)) + { + this.iteration++; + + this.reset(true); + } + else + { + this.complete = true; + } + } + + if (this.complete) + { + this.emit(Events.COMPLETE, this); + } + }, + + /** + * Starts this Timeline running. + * + * If the Timeline is already running and the `fromStart` parameter is `true`, + * then calling this method will reset the Timeline events as incomplete. + * + * If you wish to resume a paused Timeline, then use the `Timeline.resume` method instead. + * + * @method Phaser.Time.Timeline#play + * @since 3.60.0 + * + * @param {boolean} [fromStart=true] - Reset this Timeline back to the start before playing. + * + * @return {this} This Timeline instance. + */ + play: function (fromStart) + { + if (fromStart === undefined) { fromStart = true; } + + this.paused = false; + this.complete = false; + this.totalComplete = 0; + + if (fromStart) + { + this.reset(); + } + + return this; + }, + + /** + * Pauses this Timeline. + * + * To resume it again, call the `Timeline.resume` method or set the `Timeline.paused` property to `false`. + * + * If the Timeline is paused while processing the current game step, then it + * will carry on with all events that are due to run during that step and pause + * from the next game step. + * + * Note that if any Tweens have been started prior to calling this method, they will **not** be paused as well. + * + * @method Phaser.Time.Timeline#pause + * @since 3.60.0 + * + * @return {this} This Timeline instance. + */ + pause: function () + { + this.paused = true; + + var events = this.events; + + for (var i = 0; i < events.length; i++) + { + var event = events[i]; + + if (event.tweenInstance) + { + event.tweenInstance.paused = true; + } + } + + return this; + }, + + /** + * Repeats this Timeline. + * + * If the value for `amount` is positive, the Timeline will repeat that many additional times. + * For example a value of 1 will actually run this Timeline twice. + * + * Depending on the value given, `false` is 0 and `true`, undefined and negative numbers are infinite. + * + * If this Timeline had any events set to `once` that have already been removed, + * they will **not** be repeated each loop. + * + * @method Phaser.Time.Timeline#repeat + * @since 3.80.0 + * + * @param {number|boolean} [amount=-1] - Amount of times to repeat, if `true` or negative it will be infinite. + * + * @return {this} This Timeline instance. + */ + repeat: function (amount) + { + if (amount === undefined || amount === true) { amount = -1; } + if (amount === false) { amount = 0; } + + this.loop = amount; + + return this; + }, + + /** + * Resumes this Timeline from a paused state. + * + * The Timeline will carry on from where it left off. + * + * If you need to reset the Timeline to the start, then call the `Timeline.reset` method. + * + * @method Phaser.Time.Timeline#resume + * @since 3.60.0 + * + * @return {this} This Timeline instance. + */ + resume: function () + { + this.paused = false; + + var events = this.events; + + for (var i = 0; i < events.length; i++) + { + var event = events[i]; + + if (event.tweenInstance) + { + event.tweenInstance.paused = false; + } + } + + return this; + }, + + /** + * Stops this Timeline. + * + * This will set the `paused` and `complete` properties to `true`. + * + * If you wish to reset the Timeline to the start, then call the `Timeline.reset` method. + * + * @method Phaser.Time.Timeline#stop + * @since 3.60.0 + * + * @return {this} This Timeline instance. + */ + stop: function () + { + this.paused = true; + this.complete = true; + + return this; + }, + + /** + * Resets this Timeline back to the start. + * + * This will set the elapsed time to zero and set all events to be incomplete. + * + * If the Timeline had any events that were set to `once` that have already + * been removed, they will **not** be present again after calling this method. + * + * If the Timeline isn't currently running (i.e. it's paused or complete) then + * calling this method resets those states, the same as calling `Timeline.play(true)`. + * + * Any Tweens that were currently running by this Timeline will be stopped. + * + * @method Phaser.Time.Timeline#reset + * @since 3.60.0 + * + * @param {boolean} [loop=false] - Set to true if you do not want to reset the loop counters. + * + * @return {this} This Timeline instance. + */ + reset: function (loop) + { + if (loop === undefined) { loop = false; } + + this.elapsed = 0; + + if (!loop) + { + this.iteration = 0; + } + + var events = this.events; + + for (var i = 0; i < events.length; i++) + { + var event = events[i]; + + event.complete = false; + + if (!loop) + { + event.repeat = 0; + } + + if (event.tweenInstance) + { + event.tweenInstance.stop(); + } + } + + return this.play(false); + }, + + /** + * Adds one or more events to this Timeline. + * + * You can pass in a single configuration object, or an array of them: + * + * ```js + * const timeline = this.add.timeline({ + * at: 1000, + * run: () => { + * this.add.sprite(400, 300, 'logo'); + * } + * }); + * ``` + * + * @method Phaser.Time.Timeline#add + * @since 3.60.0 + * + * @param {Phaser.Types.Time.TimelineEventConfig|Phaser.Types.Time.TimelineEventConfig[]} config - The configuration object for this Timeline Event, or an array of them. + * + * @return {this} This Timeline instance. + */ + add: function (config) + { + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var events = this.events; + var prevTime = 0; + + if (events.length > 0) + { + prevTime = events[events.length - 1].time; + } + + for (var i = 0; i < config.length; i++) + { + var entry = config[i]; + + // Start at the exact time given, based on elapsed time (i.e. x ms from the start of the Timeline) + var startTime = GetFastValue(entry, 'at', 0); + + // Start in x ms from whatever the current elapsed time is (i.e. x ms from now) + var offsetTime = GetFastValue(entry, 'in', null); + + if (offsetTime !== null) + { + startTime = this.elapsed + offsetTime; + } + + // Start in x ms from whatever the previous event's start time was (i.e. x ms after the previous event) + var fromTime = GetFastValue(entry, 'from', null); + + if (fromTime !== null) + { + startTime = prevTime + fromTime; + } + + events.push({ + complete: false, + time: startTime, + repeat: 0, + if: GetFastValue(entry, 'if', null), + run: GetFastValue(entry, 'run', null), + loop: GetFastValue(entry, 'loop', null), + event: GetFastValue(entry, 'event', null), + target: GetFastValue(entry, 'target', null), + set: GetFastValue(entry, 'set', null), + tween: GetFastValue(entry, 'tween', null), + sound: GetFastValue(entry, 'sound', null), + once: GetFastValue(entry, 'once', false), + stop: GetFastValue(entry, 'stop', false) + }); + + prevTime = startTime; + } + + this.complete = false; + + return this; + }, + + /** + * Removes all events from this Timeline, resets the elapsed time to zero + * and pauses the Timeline. + * + * Any Tweens that were currently running as a result of this Timeline will be stopped. + * + * @method Phaser.Time.Timeline#clear + * @since 3.60.0 + * + * @return {this} This Timeline instance. + */ + clear: function () + { + var events = this.events; + + for (var i = 0; i < events.length; i++) + { + var event = events[i]; + + if (event.tweenInstance) + { + event.tweenInstance.stop(); + } + } + + events = []; + + this.elapsed = 0; + this.paused = true; + + return this; + }, + + /** + * Returns `true` if this Timeline is currently playing. + * + * A Timeline is playing if it is not paused or not complete. + * + * @method Phaser.Time.Timeline#isPlaying + * @since 3.60.0 + * + * @return {boolean} `true` if this Timeline is playing, otherwise `false`. + */ + isPlaying: function () + { + return (!this.paused && !this.complete); + }, + + /** + * Returns a number between 0 and 1 representing the progress of this Timeline. + * + * A value of 0 means the Timeline has just started, 0.5 means it's half way through, + * and 1 means it's complete. + * + * If the Timeline has no events, or all events have been removed, this will return 1. + * + * If the Timeline is paused, this will return the progress value at the time it was paused. + * + * Note that the value returned is based on the number of events that have been completed, + * not the 'duration' of the events (as this is unknown to the Timeline). + * + * @method Phaser.Time.Timeline#getProgress + * @since 3.60.0 + * + * @return {number} A number between 0 and 1 representing the progress of this Timeline. + */ + getProgress: function () + { + var total = Math.min(this.totalComplete, this.events.length); + + return total / this.events.length; + }, + + /** + * Destroys this Timeline. + * + * This will remove all events from the Timeline and stop it from processing. + * + * Any Tweens that were currently running as a result of this Timeline will be stopped. + * + * This method is called automatically when the Scene shuts down, but you may + * also call it directly should you need to destroy the Timeline earlier. + * + * @method Phaser.Time.Timeline#destroy + * @since 3.60.0 + */ + destroy: function () + { + var eventEmitter = this.systems.events; + + eventEmitter.off(SceneEvents.PRE_UPDATE, this.preUpdate, this); + eventEmitter.off(SceneEvents.UPDATE, this.update, this); + eventEmitter.off(SceneEvents.SHUTDOWN, this.destroy, this); + + this.clear(); + + this.scene = null; + this.systems = null; + } + +}); + +/** + * A Timeline is a way to schedule events to happen at specific times in the future. + * + * You can think of it as an event sequencer for your game, allowing you to schedule the + * running of callbacks, events and other actions at specific times in the future. + * + * A Timeline is a Scene level system, meaning you can have as many Timelines as you like, each + * belonging to a different Scene. You can also have multiple Timelines running at the same time. + * + * If the Scene is paused, the Timeline will also pause. If the Scene is destroyed, the Timeline + * will be automatically destroyed. However, you can control the Timeline directly, pausing, + * resuming and stopping it at any time. + * + * Create an instance of a Timeline via the Game Object Factory: + * + * ```js + * const timeline = this.add.timeline(); + * ``` + * + * The Timeline always starts paused. You must call `play` on it to start it running. + * + * You can also pass in a configuration object on creation, or an array of them: + * + * ```js + * const timeline = this.add.timeline({ + * at: 1000, + * run: () => { + * this.add.sprite(400, 300, 'logo'); + * } + * }); + * + * timeline.play(); + * ``` + * + * In this example we sequence a few different events: + * + * ```js + * const timeline = this.add.timeline([ + * { + * at: 1000, + * run: () => { this.logo = this.add.sprite(400, 300, 'logo'); }, + * sound: 'TitleMusic' + * }, + * { + * at: 2500, + * tween: { + * targets: this.logo, + * y: 600, + * yoyo: true + * }, + * sound: 'Explode' + * }, + * { + * at: 8000, + * event: 'HURRY_PLAYER', + * target: this.background, + * set: { + * tint: 0xff0000 + * } + * } + * ]); + * + * timeline.play(); + * ``` + * + * The Timeline can also be looped with the repeat method: + * ```js + * timeline.repeat().play(); + * ``` + * + * There are lots of options available to you via the configuration object. See the + * {@link Phaser.Types.Time.TimelineEventConfig} typedef for more details. + * + * @method Phaser.GameObjects.GameObjectFactory#timeline + * @since 3.60.0 + * + * @param {Phaser.Types.Time.TimelineEventConfig|Phaser.Types.Time.TimelineEventConfig[]} config - The configuration object for this Timeline Event, or an array of them. + * + * @return {Phaser.Time.Timeline} The Timeline that was created. + */ +GameObjectFactory.register('timeline', function (config) +{ + return new Timeline(this.scene, config); +}); + +module.exports = Timeline; + + +/***/ }), + +/***/ 94880: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var GetFastValue = __webpack_require__(95540); + +/** + * @classdesc + * A Timer Event represents a delayed function call. It's managed by a Scene's {@link Clock} and will call its function after a set amount of time has passed. The Timer Event can optionally repeat - i.e. call its function multiple times before finishing, or loop indefinitely. + * + * Because it's managed by a Clock, a Timer Event is based on game time, will be affected by its Clock's time scale, and will pause if its Clock pauses. + * + * @class TimerEvent + * @memberof Phaser.Time + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Types.Time.TimerEventConfig} config - The configuration for the Timer Event, including its delay and callback. + */ +var TimerEvent = new Class({ + + initialize: + + function TimerEvent (config) + { + /** + * The delay in ms at which this TimerEvent fires. + * + * @name Phaser.Time.TimerEvent#delay + * @type {number} + * @default 0 + * @readonly + * @since 3.0.0 + */ + this.delay = 0; + + /** + * The total number of times this TimerEvent will repeat before finishing. + * + * @name Phaser.Time.TimerEvent#repeat + * @type {number} + * @default 0 + * @readonly + * @since 3.0.0 + */ + this.repeat = 0; + + /** + * If repeating this contains the current repeat count. + * + * @name Phaser.Time.TimerEvent#repeatCount + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.repeatCount = 0; + + /** + * True if this TimerEvent loops, otherwise false. + * + * @name Phaser.Time.TimerEvent#loop + * @type {boolean} + * @default false + * @readonly + * @since 3.0.0 + */ + this.loop = false; + + /** + * The callback that will be called when the TimerEvent occurs. + * + * @name Phaser.Time.TimerEvent#callback + * @type {function} + * @since 3.0.0 + */ + this.callback; + + /** + * The scope in which the callback will be called. + * + * @name Phaser.Time.TimerEvent#callbackScope + * @type {object} + * @since 3.0.0 + */ + this.callbackScope; + + /** + * Additional arguments to be passed to the callback. + * + * @name Phaser.Time.TimerEvent#args + * @type {array} + * @since 3.0.0 + */ + this.args; + + /** + * Scale the time causing this TimerEvent to update. + * + * @name Phaser.Time.TimerEvent#timeScale + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.timeScale = 1; + + /** + * Start this many MS into the elapsed (useful if you want a long duration with repeat, but for the first loop to fire quickly) + * + * @name Phaser.Time.TimerEvent#startAt + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.startAt = 0; + + /** + * The time in milliseconds which has elapsed since the Timer Event's creation. + * + * This value is local for the Timer Event and is relative to its Clock. As such, it's influenced by the Clock's time scale and paused state, the Timer Event's initial {@link #startAt} property, and the Timer Event's {@link #timeScale} and {@link #paused} state. + * + * @name Phaser.Time.TimerEvent#elapsed + * @type {number} + * @default 0 + * @since 3.0.0 + */ + this.elapsed = 0; + + /** + * Whether or not this timer is paused. + * + * @name Phaser.Time.TimerEvent#paused + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.paused = false; + + /** + * Whether the Timer Event's function has been called. + * + * When the Timer Event fires, this property will be set to `true` before the callback function is invoked and will be reset immediately afterward if the Timer Event should repeat. The value of this property does not directly influence whether the Timer Event will be removed from its Clock, but can prevent it from firing. + * + * @name Phaser.Time.TimerEvent#hasDispatched + * @type {boolean} + * @default false + * @since 3.0.0 + */ + this.hasDispatched = false; + + this.reset(config); + }, + + /** + * Completely reinitializes the Timer Event, regardless of its current state, according to a configuration object. + * + * @method Phaser.Time.TimerEvent#reset + * @since 3.0.0 + * + * @param {Phaser.Types.Time.TimerEventConfig} config - The new state for the Timer Event. + * + * @return {Phaser.Time.TimerEvent} This TimerEvent object. + */ + reset: function (config) + { + this.delay = GetFastValue(config, 'delay', 0); + + // Can also be set to -1 for an infinite loop (same as setting loop: true) + this.repeat = GetFastValue(config, 'repeat', 0); + + this.loop = GetFastValue(config, 'loop', false); + + this.callback = GetFastValue(config, 'callback', undefined); + + this.callbackScope = GetFastValue(config, 'callbackScope', this); + + this.args = GetFastValue(config, 'args', []); + + this.timeScale = GetFastValue(config, 'timeScale', 1); + + this.startAt = GetFastValue(config, 'startAt', 0); + + this.paused = GetFastValue(config, 'paused', false); + + this.elapsed = this.startAt; + this.hasDispatched = false; + this.repeatCount = (this.repeat === -1 || this.loop) ? 999999999999 : this.repeat; + + if (this.delay <= 0 && this.repeatCount > 0) + { + throw new Error('TimerEvent infinite loop created via zero delay'); + } + + return this; + }, + + /** + * Gets the progress of the current iteration, not factoring in repeats. + * + * @method Phaser.Time.TimerEvent#getProgress + * @since 3.0.0 + * + * @return {number} A number between 0 and 1 representing the current progress. + */ + getProgress: function () + { + return (this.elapsed / this.delay); + }, + + /** + * Gets the progress of the timer overall, factoring in repeats. + * + * @method Phaser.Time.TimerEvent#getOverallProgress + * @since 3.0.0 + * + * @return {number} The overall progress of the Timer Event, between 0 and 1. + */ + getOverallProgress: function () + { + if (this.repeat > 0) + { + var totalDuration = this.delay + (this.delay * this.repeat); + var totalElapsed = this.elapsed + (this.delay * (this.repeat - this.repeatCount)); + + return (totalElapsed / totalDuration); + } + else + { + return this.getProgress(); + } + }, + + /** + * Returns the number of times this Timer Event will repeat before finishing. + * + * This should not be confused with the number of times the Timer Event will fire before finishing. A return value of 0 doesn't indicate that the Timer Event has finished running - it indicates that it will not repeat after the next time it fires. + * + * @method Phaser.Time.TimerEvent#getRepeatCount + * @since 3.0.0 + * + * @return {number} How many times the Timer Event will repeat. + */ + getRepeatCount: function () + { + return this.repeatCount; + }, + + /** + * Returns the local elapsed time for the current iteration of the Timer Event. + * + * @method Phaser.Time.TimerEvent#getElapsed + * @since 3.0.0 + * + * @return {number} The local elapsed time in milliseconds. + */ + getElapsed: function () + { + return this.elapsed; + }, + + /** + * Returns the local elapsed time for the current iteration of the Timer Event in seconds. + * + * @method Phaser.Time.TimerEvent#getElapsedSeconds + * @since 3.0.0 + * + * @return {number} The local elapsed time in seconds. + */ + getElapsedSeconds: function () + { + return this.elapsed * 0.001; + }, + + /** + * Returns the time interval until the next iteration of the Timer Event. + * + * @method Phaser.Time.TimerEvent#getRemaining + * @since 3.50.0 + * + * @return {number} The time interval in milliseconds. + */ + getRemaining: function () + { + return this.delay - this.elapsed; + }, + + /** + * Returns the time interval until the next iteration of the Timer Event in seconds. + * + * @method Phaser.Time.TimerEvent#getRemainingSeconds + * @since 3.50.0 + * + * @return {number} The time interval in seconds. + */ + getRemainingSeconds: function () + { + return this.getRemaining() * 0.001; + }, + + /** + * Returns the time interval until the last iteration of the Timer Event. + * + * @method Phaser.Time.TimerEvent#getOverallRemaining + * @since 3.50.0 + * + * @return {number} The time interval in milliseconds. + */ + getOverallRemaining: function () + { + return this.delay * (1 + this.repeatCount) - this.elapsed; + }, + + /** + * Returns the time interval until the last iteration of the Timer Event in seconds. + * + * @method Phaser.Time.TimerEvent#getOverallRemainingSeconds + * @since 3.50.0 + * + * @return {number} The time interval in seconds. + */ + getOverallRemainingSeconds: function () + { + return this.getOverallRemaining() * 0.001; + }, + + /** + * Forces the Timer Event to immediately expire, thus scheduling its removal in the next frame. + * + * @method Phaser.Time.TimerEvent#remove + * @since 3.0.0 + * + * @param {boolean} [dispatchCallback=false] - If `true`, the function of the Timer Event will be called before its removal. + */ + remove: function (dispatchCallback) + { + if (dispatchCallback === undefined) { dispatchCallback = false; } + + this.elapsed = this.delay; + + this.hasDispatched = !dispatchCallback; + + this.repeatCount = 0; + }, + + /** + * Destroys all object references in the Timer Event, i.e. its callback, scope, and arguments. + * + * Normally, this method is only called by the Clock when it shuts down. As such, it doesn't stop the Timer Event. If called manually, the Timer Event will still be updated by the Clock, but it won't do anything when it fires. + * + * @method Phaser.Time.TimerEvent#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.callback = undefined; + this.callbackScope = undefined; + this.args = []; + } + +}); + +module.exports = TimerEvent; + + +/***/ }), + +/***/ 35945: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Timeline Complete Event. + * + * This event is dispatched by timeline when all timeline events complete. + * + * Listen to it from a Timeline instance using `Timeline.on('complete', listener)`, i.e.: + * + * ```javascript + * const timeline = this.add.timeline(); + * timeline.on('complete', listener); + * timeline.play(); + * ``` + * + * @event Phaser.Time.Events#COMPLETE + * @type {string} + * @since 3.70.0 + * + * @param {Phaser.Time.Timeline} timeline - A reference to the Timeline that emitted the event. + */ +module.exports = 'complete'; + + +/***/ }), + +/***/ 89809: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Time.Events + */ + +module.exports = { + + COMPLETE: __webpack_require__(35945) + +}; + + +/***/ }), + +/***/ 90291: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Time + */ + +module.exports = { + + Clock: __webpack_require__(33385), + Events: __webpack_require__(89809), + Timeline: __webpack_require__(96120), + TimerEvent: __webpack_require__(94880) + +}; + + +/***/ }), + +/***/ 40382: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayRemove = __webpack_require__(72905); +var Class = __webpack_require__(83419); +var Flatten = __webpack_require__(43491); +var NumberTweenBuilder = __webpack_require__(88032); +var PluginCache = __webpack_require__(37277); +var SceneEvents = __webpack_require__(44594); +var StaggerBuilder = __webpack_require__(93109); +var Tween = __webpack_require__(8462); +var TweenBuilder = __webpack_require__(8357); +var TweenChain = __webpack_require__(43960); +var TweenChainBuilder = __webpack_require__(26012); + +/** + * @classdesc + * The Tween Manager is a default Scene Plugin which controls and updates Tweens. + * + * A tween is a way to alter one or more properties of a target object over a defined period of time. + * + * Tweens are created by calling the `add` method and passing in the configuration object. + * + * ```js + * const logo = this.add.image(100, 100, 'logo'); + * + * this.tweens.add({ + * targets: logo, + * x: 600, + * ease: 'Power1', + * duration: 2000 + * }); + * ``` + * + * See the `TweenBuilderConfig` for all of the options you have available. + * + * Playback will start immediately unless the tween has been configured to be paused. + * + * Please note that a Tween will not manipulate any target property that begins with an underscore. + * + * Tweens are designed to be 'fire-and-forget'. They automatically destroy themselves once playback + * is complete, to free-up memory and resources. If you wish to keep a tween after playback, i.e. to + * play it again at a later time, then you should set the `persist` property to `true` in the config. + * However, doing so means it's entirely up to _you_ to destroy the tween when you're finished with it, + * otherwise it will linger in memory forever. + * + * If you wish to chain Tweens together for sequential playback, see the `TweenManager.chain` method. + * + * @class TweenManager + * @memberof Phaser.Tweens + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Scene} scene - The Scene which owns this Tween Manager. + */ +var TweenManager = new Class({ + + initialize: + + function TweenManager (scene) + { + /** + * The Scene which owns this Tween Manager. + * + * @name Phaser.Tweens.TweenManager#scene + * @type {Phaser.Scene} + * @since 3.0.0 + */ + this.scene = scene; + + /** + * The Scene Systems Event Emitter. + * + * @name Phaser.Tweens.TweenManager#events + * @type {Phaser.Events.EventEmitter} + * @since 3.60.0 + */ + this.events = scene.sys.events; + + /** + * The time scale of the Tween Manager. + * + * This value scales the time delta between two frames, thus influencing the speed of time for all Tweens owned by this Tween Manager. + * + * @name Phaser.Tweens.TweenManager#timeScale + * @type {number} + * @default 1 + * @since 3.0.0 + */ + this.timeScale = 1; + + /** + * This toggles the updating state of this Tween Manager. + * + * Setting `paused` to `true` (or calling the `pauseAll` method) will + * stop this Tween Manager from updating any of its tweens, including + * newly created ones. Set back to `false` to resume playback. + * + * @name Phaser.Tweens.TweenManager#paused + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.paused = false; + + /** + * Is this Tween Manager currently processing the tweens as part of + * its 'update' loop? This is set to 'true' at the start of 'update' + * and reset to 'false' at the end of the function. Allows you to trap + * Tween Manager status during tween callbacks. + * + * @name Phaser.Tweens.TweenManager#processing + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.processing = false; + + /** + * An array of Tweens which are actively being processed by the Tween Manager. + * + * @name Phaser.Tweens.TweenManager#tweens + * @type {Phaser.Tweens.Tween[]} + * @since 3.60.0 + */ + this.tweens = []; + + /** + * The time the Tween Manager was updated. + * + * @name Phaser.Tweens.TweenManager#time + * @type {number} + * @since 3.60.0 + */ + this.time = 0; + + /** + * The time the Tween Manager was started. + * + * @name Phaser.Tweens.TweenManager#startTime + * @type {number} + * @since 3.60.0 + */ + this.startTime = 0; + + /** + * The time the Tween Manager should next update. + * + * @name Phaser.Tweens.TweenManager#nextTime + * @type {number} + * @since 3.60.0 + */ + this.nextTime = 0; + + /** + * The time the Tween Manager previously updated. + * + * @name Phaser.Tweens.TweenManager#prevTime + * @type {number} + * @since 3.60.0 + */ + this.prevTime = 0; + + /** + * The maximum amount of time, in milliseconds, the browser can + * lag for, before lag smoothing is applied. + * + * See the `TweenManager.setLagSmooth` method for further details. + * + * @name Phaser.Tweens.TweenManager#maxLag + * @type {number} + * @default 500 + * @since 3.60.0 + */ + this.maxLag = 500; + + /** + * The amount of time, in milliseconds, that is used to set the + * delta when lag smoothing is applied. + * + * See the `TweenManager.setLagSmooth` method for further details. + * + * @name Phaser.Tweens.TweenManager#lagSkip + * @type {number} + * @default 33 + * @since 3.60.0 + */ + this.lagSkip = 33; + + /** + * An internal value that holds the fps rate. + * + * @name Phaser.Tweens.TweenManager#gap + * @type {number} + * @since 3.60.0 + */ + this.gap = 1000 / 240; + + this.events.once(SceneEvents.BOOT, this.boot, this); + this.events.on(SceneEvents.START, this.start, this); + }, + + /** + * This method is called automatically, only once, when the Scene is first created. + * Do not invoke it directly. + * + * @method Phaser.Tweens.TweenManager#boot + * @private + * @since 3.5.1 + */ + boot: function () + { + this.events.once(SceneEvents.DESTROY, this.destroy, this); + }, + + /** + * This method is called automatically by the Scene when it is starting up. + * It is responsible for creating local systems, properties and listening for Scene events. + * Do not invoke it directly. + * + * @method Phaser.Tweens.TweenManager#start + * @private + * @since 3.5.0 + */ + start: function () + { + this.timeScale = 1; + this.paused = false; + + this.startTime = Date.now(); + this.prevTime = this.startTime; + this.nextTime = this.gap; + + this.events.on(SceneEvents.UPDATE, this.update, this); + this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * Create a Tween and return it, but does not add it to this Tween Manager. + * + * Please note that a Tween will not manipulate any target property that begins with an underscore. + * + * In order to play this tween, you'll need to add it to a Tween Manager via + * the `TweenManager.existing` method. + * + * You can optionally pass an **array** of Tween Configuration objects to this method and it will create + * one Tween per entry in the array. If an array is given, an array of tweens is returned. + * + * @method Phaser.Tweens.TweenManager#create + * @since 3.0.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig|Phaser.Types.Tweens.TweenBuilderConfig[]|object|object[]} config - A Tween Configuration object. Or an array of Tween Configuration objects. + * + * @return {Phaser.Tweens.Tween|Phaser.Tweens.Tween[]} The created Tween, or an array of Tweens if an array of tween configs was provided. + */ + create: function (config) + { + if (!Array.isArray(config)) + { + config = [ config ]; + } + + var result = []; + + for (var i = 0; i < config.length; i++) + { + var tween = config[i]; + + if (tween instanceof Tween || tween instanceof TweenChain) + { + // Allow them to send an array of mixed instances and configs + result.push(tween); + } + else if (Array.isArray(tween.tweens)) + { + result.push(TweenChainBuilder(this, tween)); + } + else + { + result.push(TweenBuilder(this, tween)); + } + } + + return (result.length === 1) ? result[0] : result; + }, + + /** + * Create a Tween and add it to this Tween Manager by passing a Tween Configuration object. + * + * Example, run from within a Scene: + * + * ```js + * const logo = this.add.image(100, 100, 'logo'); + * + * this.tweens.add({ + * targets: logo, + * x: 600, + * ease: 'Power1', + * duration: 2000 + * }); + * ``` + * + * See the `TweenBuilderConfig` for all of the options you have available. + * + * Playback will start immediately unless the tween has been configured to be paused. + * + * Please note that a Tween will not manipulate any target property that begins with an underscore. + * + * Tweens are designed to be 'fire-and-forget'. They automatically destroy themselves once playback + * is complete, to free-up memory and resources. If you wish to keep a tween after playback, i.e. to + * play it again at a later time, then you should set the `persist` property to `true` in the config. + * However, doing so means it's entirely up to _you_ to destroy the tween when you're finished with it, + * otherwise it will linger in memory forever. + * + * If you wish to chain Tweens together for sequential playback, see the `TweenManager.chain` method. + * + * @method Phaser.Tweens.TweenManager#add + * @since 3.0.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig|Phaser.Types.Tweens.TweenChainBuilderConfig|Phaser.Tweens.Tween|Phaser.Tweens.TweenChain} config - A Tween Configuration object, or a Tween or TweenChain instance. + * + * @return {Phaser.Tweens.Tween} The created Tween. + */ + add: function (config) + { + var tween = config; + var tweens = this.tweens; + + if (tween instanceof Tween || tween instanceof TweenChain) + { + tweens.push(tween.reset()); + } + else + { + if (Array.isArray(tween.tweens)) + { + tween = TweenChainBuilder(this, tween); + } + else + { + tween = TweenBuilder(this, tween); + } + + tweens.push(tween.reset()); + } + + return tween; + }, + + /** + * Create multiple Tweens and add them all to this Tween Manager, by passing an array of Tween Configuration objects. + * + * See the `TweenBuilderConfig` for all of the options you have available. + * + * Playback will start immediately unless the tweens have been configured to be paused. + * + * Please note that a Tween will not manipulate any target property that begins with an underscore. + * + * Tweens are designed to be 'fire-and-forget'. They automatically destroy themselves once playback + * is complete, to free-up memory and resources. If you wish to keep a tween after playback, i.e. to + * play it again at a later time, then you should set the `persist` property to `true` in the config. + * However, doing so means it's entirely up to _you_ to destroy the tween when you're finished with it, + * otherwise it will linger in memory forever. + * + * If you wish to chain Tweens together for sequential playback, see the `TweenManager.chain` method. + * + * @method Phaser.Tweens.TweenManager#addMultiple + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig[]|object[]} configs - An array of Tween Configuration objects. + * + * @return {Phaser.Tweens.Tween[]} An array of created Tweens. + */ + addMultiple: function (configs) + { + var tween; + var result = []; + var tweens = this.tweens; + + for (var i = 0; i < configs.length; i++) + { + tween = configs[i]; + + if (tween instanceof Tween || tween instanceof TweenChain) + { + tweens.push(tween.reset()); + } + else + { + if (Array.isArray(tween.tweens)) + { + tween = TweenChainBuilder(this, tween); + } + else + { + tween = TweenBuilder(this, tween); + } + + tweens.push(tween.reset()); + } + + result.push(tween); + } + + return result; + }, + + /** + * Create a sequence of Tweens, chained to one-another, and add them to this Tween Manager. + * + * The tweens are played in order, from start to finish. You can optionally set the chain + * to repeat as many times as you like. Once the chain has finished playing, or repeating if set, + * all tweens in the chain will be destroyed automatically. To override this, set the `persist` + * argument to 'true'. + * + * Playback will start immediately unless the _first_ Tween has been configured to be paused. + * + * Please note that Tweens will not manipulate any target property that begins with an underscore. + * + * @method Phaser.Tweens.TweenManager#chain + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.TweenChainBuilderConfig|object} tweens - A Tween Chain configuration object. + * + * @return {Phaser.Tweens.TweenChain} The Tween Chain instance. + */ + chain: function (config) + { + var chain = TweenChainBuilder(this, config); + + this.tweens.push(chain.init()); + + return chain; + }, + + /** + * Returns an array containing this Tween and all Tweens chained to it, + * in the order in which they will be played. + * + * If there are no chained Tweens an empty array is returned. + * + * @method Phaser.Tweens.TweenManager#getChainedTweens + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween to return the chain from. + * + * @return {Phaser.Tweens.Tween[]} An array of the chained tweens, or an empty array if there aren't any. + */ + getChainedTweens: function (tween) + { + return tween.getChainedTweens(); + }, + + /** + * Check to see if the given Tween instance exists within this Tween Manager. + * + * Will return `true` as long as the Tween is being processed by this Tween Manager. + * + * Will return `false` if not present, or has a state of `REMOVED` or `DESTROYED`. + * + * @method Phaser.Tweens.TweenManager#has + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween instance to check. + * + * @return {boolean} `true` if the Tween exists within this Tween Manager, otherwise `false`. + */ + has: function (tween) + { + return (this.tweens.indexOf(tween) > -1); + }, + + /** + * Add an existing Tween to this Tween Manager. + * + * Playback will start immediately unless the tween has been configured to be paused. + * + * @method Phaser.Tweens.TweenManager#existing + * @since 3.0.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween to add. + * + * @return {this} This Tween Manager instance. + */ + existing: function (tween) + { + if (!this.has(tween)) + { + this.tweens.push(tween.reset()); + } + + return this; + }, + + /** + * Create a Number Tween and add it to the active Tween list. + * + * A Number Tween is a special kind of tween that doesn't have a target. Instead, + * it allows you to tween between 2 numeric values. The default values are + * `0` and `1`, but you can change them via the `from` and `to` properties. + * + * You can get the current tweened value via the `Tween.getValue()` method. + * + * Playback will start immediately unless the tween has been configured to be paused. + * + * Please note that a Tween will not manipulate any target property that begins with an underscore. + * + * @method Phaser.Tweens.TweenManager#addCounter + * @since 3.0.0 + * + * @param {Phaser.Types.Tweens.NumberTweenBuilderConfig} config - The configuration object for the Number Tween. + * + * @return {Phaser.Tweens.Tween} The created Number Tween. + */ + addCounter: function (config) + { + var tween = NumberTweenBuilder(this, config); + + this.tweens.push(tween.reset()); + + return tween; + }, + + /** + * Creates a Stagger function to be used by a Tween property. + * + * The stagger function will allow you to stagger changes to the value of the property across all targets of the tween. + * + * This is only worth using if the tween has multiple targets. + * + * The following will stagger the delay by 100ms across all targets of the tween, causing them to scale down to 0.2 + * over the duration specified: + * + * ```javascript + * this.tweens.add({ + * targets: [ ... ], + * scale: 0.2, + * ease: 'linear', + * duration: 1000, + * delay: this.tweens.stagger(100) + * }); + * ``` + * + * The following will stagger the delay by 500ms across all targets of the tween using a 10 x 6 grid, staggering + * from the center out, using a cubic ease. + * + * ```javascript + * this.tweens.add({ + * targets: [ ... ], + * scale: 0.2, + * ease: 'linear', + * duration: 1000, + * delay: this.tweens.stagger(500, { grid: [ 10, 6 ], from: 'center', ease: 'cubic.out' }) + * }); + * ``` + * + * @method Phaser.Tweens.TweenManager#stagger + * @since 3.19.0 + * + * @param {(number|number[])} value - The amount to stagger by, or an array containing two elements representing the min and max values to stagger between. + * @param {Phaser.Types.Tweens.StaggerConfig} config - The configuration object for the Stagger function. + * + * @return {function} The stagger function. + */ + stagger: function (value, options) + { + return StaggerBuilder(value, options); + }, + + /** + * Set the limits that are used when a browser encounters lag, or delays that cause the elapsed + * time between two frames to exceed the expected amount. If this occurs, the Tween Manager will + * act as if the 'skip' amount of times has passed, in order to maintain strict tween sequencing. + * + * This is enabled by default with the values 500ms for the lag limit and 33ms for the skip. + * + * You should not set these to low values, as it won't give time for the browser to ever + * catch-up with itself and reclaim sync. + * + * Call this method with no arguments to disable smoothing. + * + * Call it with the arguments `500` and `33` to reset to the defaults. + * + * @method Phaser.Tweens.TweenManager#setLagSmooth + * @since 3.60.0 + * + * @param {number} [limit=0] - If the browser exceeds this amount, in milliseconds, it will act as if the 'skip' amount has elapsed instead. + * @param {number} [skip=0] - The amount, in milliseconds, to use as the step delta should the browser lag beyond the 'limit'. + * + * @return {this} This Tween Manager instance. + */ + setLagSmooth: function (limit, skip) + { + if (limit === undefined) { limit = 1 / 1e-8; } + if (skip === undefined) { skip = 0; } + + this.maxLag = limit; + this.lagSkip = Math.min(skip, this.maxLag); + + return this; + }, + + /** + * Limits the Tween system to run at a particular frame rate. + * + * You should not set this _above_ the frequency of the browser, + * but instead can use it to throttle the frame rate lower, should + * you need to in certain situations. + * + * @method Phaser.Tweens.TweenManager#setFps + * @since 3.60.0 + * + * @param {number} [fps=240] - The frame rate to tick at. + * + * @return {this} This Tween Manager instance. + */ + setFps: function (fps) + { + if (fps === undefined) { fps = 240; } + + this.gap = 1000 / fps; + this.nextTime = this.time * 1000 + this.gap; + + return this; + }, + + /** + * Internal method that calculates the delta value, along with the other timing values, + * and returns the new delta. + * + * You should not typically call this method directly. + * + * @method Phaser.Tweens.TweenManager#getDelta + * @since 3.60.0 + * + * @param {boolean} [tick=false] - Is this a manual tick, or an automated tick? + * + * @return {number} The new delta value. + */ + getDelta: function (tick) + { + var elapsed = Date.now() - this.prevTime; + + if (elapsed > this.maxLag) + { + this.startTime += elapsed - this.lagSkip; + } + + this.prevTime += elapsed; + + var time = this.prevTime - this.startTime; + var overlap = time - this.nextTime; + var delta = time - this.time * 1000; + + if (overlap > 0 || tick) + { + time /= 1000; + this.time = time; + this.nextTime += overlap + (overlap >= this.gap ? 4 : this.gap - overlap); + } + else + { + delta = 0; + } + + return delta; + }, + + /** + * Manually advance the Tween system by one step. + * + * This will update all Tweens even if the Tween Manager is currently + * paused. + * + * @method Phaser.Tweens.TweenManager#tick + * @since 3.60.0 + * + * @return {this} This Tween Manager instance. + */ + tick: function () + { + this.step(true); + + return this; + }, + + /** + * Internal update handler. + * + * Calls `TweenManager.step` as long as the Tween Manager has not + * been paused. + * + * @method Phaser.Tweens.TweenManager#update + * @since 3.0.0 + */ + update: function () + { + if (!this.paused) + { + this.step(false); + } + }, + + /** + * Updates all Tweens belonging to this Tween Manager. + * + * Called automatically by `update` and `tick`. + * + * @method Phaser.Tweens.TweenManager#step + * @since 3.60.0 + * + * @param {boolean} [tick=false] - Is this a manual tick, or an automated tick? + */ + step: function (tick) + { + if (tick === undefined) { tick = false; } + + var delta = this.getDelta(tick); + + if (delta <= 0) + { + // If we've got a negative delta, skip this step + return; + } + + this.processing = true; + + var i; + var tween; + var toDestroy = []; + var list = this.tweens; + + // By not caching the length we can immediately update tweens added + // this frame (such as chained tweens) + for (i = 0; i < list.length; i++) + { + tween = list[i]; + + // If Tween.update returns 'true' then it means it has completed, + // so move it to the destroy list + if (tween.update(delta)) + { + toDestroy.push(tween); + } + } + + // Clean-up the 'toDestroy' list + var count = toDestroy.length; + + if (count && list.length > 0) + { + for (i = 0; i < count; i++) + { + tween = toDestroy[i]; + + var idx = list.indexOf(tween); + + if (idx > -1 && (tween.isPendingRemove() || tween.isDestroyed())) + { + list.splice(idx, 1); + + tween.destroy(); + } + } + + toDestroy.length = 0; + } + + this.processing = false; + }, + + /** + * Removes the given Tween from this Tween Manager, even if it hasn't started + * playback yet. If this method is called while the Tween Manager is processing + * an update loop, then the tween will be flagged for removal at the start of + * the next frame. Otherwise, it is removed immediately. + * + * The removed tween is _not_ destroyed. It is just removed from this Tween Manager. + * + * @method Phaser.Tweens.TweenManager#remove + * @since 3.17.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween to be removed. + * + * @return {this} This Tween Manager instance. + */ + remove: function (tween) + { + if (this.processing) + { + // Remove it on the next frame + tween.setPendingRemoveState(); + } + else + { + // Remove it immediately + ArrayRemove(this.tweens, tween); + + tween.setRemovedState(); + } + + return this; + }, + + /** + * Resets the given Tween. + * + * If the Tween does not belong to this Tween Manager, it will first be added. + * + * Then it will seek to position 0 and playback will start on the next frame. + * + * @method Phaser.Tweens.TweenManager#reset + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween to be reset. + * + * @return {this} This Tween Manager instance. + */ + reset: function (tween) + { + this.existing(tween); + + tween.seek(); + + tween.setActiveState(); + + return this; + }, + + /** + * Checks if a Tween is active and adds it to the Tween Manager at the start of the frame if it isn't. + * + * @method Phaser.Tweens.TweenManager#makeActive + * @since 3.0.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween to check. + * + * @return {this} This Tween Manager instance. + */ + makeActive: function (tween) + { + this.existing(tween); + + tween.setActiveState(); + + return this; + }, + + /** + * Passes all Tweens to the given callback. + * + * @method Phaser.Tweens.TweenManager#each + * @since 3.0.0 + * + * @param {function} callback - The function to call. + * @param {object} [scope] - The scope (`this` object) to call the function with. + * @param {...*} [args] - The arguments to pass into the function. Its first argument will always be the Tween currently being iterated. + * + * @return {this} This Tween Manager instance. + */ + each: function (callback, scope) + { + var i; + var args = [ null ]; + + for (i = 1; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + this.tweens.forEach(function (tween) + { + args[0] = tween; + + callback.apply(scope, args); + }); + + return this; + }, + + /** + * Returns an array containing references to all Tweens in this Tween Manager. + * + * It is safe to mutate the returned array. However, acting upon any of the Tweens + * within it, will adjust those stored in this Tween Manager, as they are passed + * by reference and not cloned. + * + * If you wish to get tweens for a specific target, see `getTweensOf`. + * + * @method Phaser.Tweens.TweenManager#getTweens + * @since 3.0.0 + * + * @return {Phaser.Tweens.Tween[]} A new array containing references to all Tweens. + */ + getTweens: function () + { + return this.tweens.slice(); + }, + + /** + * Returns an array of all Tweens in the Tween Manager which affect the given target, or array of targets. + * + * It's possible for this method to return tweens that are about to be removed from + * the Tween Manager. You should check the state of the returned tween before acting + * upon it. + * + * @method Phaser.Tweens.TweenManager#getTweensOf + * @since 3.0.0 + * + * @param {(object|object[])} target - The target to look for. Provide an array to look for multiple targets. + * + * @return {Phaser.Tweens.Tween[]} A new array containing all Tweens which affect the given target(s). + */ + getTweensOf: function (target) + { + var output = []; + var list = this.tweens; + + if (!Array.isArray(target)) + { + target = [ target ]; + } + else + { + target = Flatten(target); + } + + var targetLen = target.length; + + for (var i = 0; i < list.length; i++) + { + var tween = list[i]; + + for (var t = 0; t < targetLen; t++) + { + if (!tween.isDestroyed() && tween.hasTarget(target[t])) + { + output.push(tween); + } + } + } + + return output; + }, + + /** + * Returns the scale of the time delta for all Tweens owned by this Tween Manager. + * + * @method Phaser.Tweens.TweenManager#getGlobalTimeScale + * @since 3.0.0 + * + * @return {number} The scale of the time delta, usually 1. + */ + getGlobalTimeScale: function () + { + return this.timeScale; + }, + + /** + * Sets a new scale of the time delta for this Tween Manager. + * + * The time delta is the time elapsed between two consecutive frames and influences the speed of time for this Tween Manager and all Tweens it owns. Values higher than 1 increase the speed of time, while values smaller than 1 decrease it. A value of 0 freezes time and is effectively equivalent to pausing all Tweens. + * + * @method Phaser.Tweens.TweenManager#setGlobalTimeScale + * @since 3.0.0 + * + * @param {number} value - The new scale of the time delta, where 1 is the normal speed. + * + * @return {this} This Tween Manager instance. + */ + setGlobalTimeScale: function (value) + { + this.timeScale = value; + + return this; + }, + + /** + * Checks if the given object is being affected by a _playing_ Tween. + * + * If the Tween is paused, this method will return false. + * + * @method Phaser.Tweens.TweenManager#isTweening + * @since 3.0.0 + * + * @param {object} target - The object to check if a tween is active for it, or not. + * + * @return {boolean} Returns `true` if a tween is active on the given target, otherwise `false`. + */ + isTweening: function (target) + { + var list = this.tweens; + var tween; + + for (var i = 0; i < list.length; i++) + { + tween = list[i]; + + if (tween.isPlaying() && tween.hasTarget(target)) + { + return true; + } + } + + return false; + }, + + /** + * Destroys all Tweens in this Tween Manager. + * + * The tweens will erase all references to any targets they hold + * and be stopped immediately. + * + * If this method is called while the Tween Manager is running its + * update process, then the tweens will be removed at the start of + * the next frame. Outside of this, they are removed immediately. + * + * @method Phaser.Tweens.TweenManager#killAll + * @since 3.0.0 + * + * @return {this} This Tween Manager instance. + */ + killAll: function () + { + var tweens = (this.processing) ? this.getTweens() : this.tweens; + + for (var i = 0; i < tweens.length; i++) + { + tweens[i].destroy(); + } + + if (!this.processing) + { + tweens.length = 0; + } + + return this; + }, + + /** + * Stops all Tweens which affect the given target or array of targets. + * + * The tweens will erase all references to any targets they hold + * and be stopped immediately. + * + * If this method is called while the Tween Manager is running its + * update process, then the tweens will be removed at the start of + * the next frame. Outside of this, they are removed immediately. + * + * @see {@link #getTweensOf} + * + * @method Phaser.Tweens.TweenManager#killTweensOf + * @since 3.0.0 + * + * @param {(object|array)} target - The target to kill the tweens of. Provide an array to use multiple targets. + * + * @return {this} This Tween Manager instance. + */ + killTweensOf: function (target) + { + var tweens = this.getTweensOf(target); + + for (var i = 0; i < tweens.length; i++) + { + tweens[i].destroy(); + } + + return this; + }, + + /** + * Pauses this Tween Manager. No Tweens will update while paused. + * + * This includes tweens created after this method was called. + * + * See `TweenManager#resumeAll` to resume the playback. + * + * As of Phaser 3.60 you can also toggle the boolean property `TweenManager.paused`. + * + * @method Phaser.Tweens.TweenManager#pauseAll + * @since 3.0.0 + * + * @return {this} This Tween Manager instance. + */ + pauseAll: function () + { + this.paused = true; + + return this; + }, + + /** + * Resumes playback of this Tween Manager. + * + * All active Tweens will continue updating. + * + * See `TweenManager#pauseAll` to pause the playback. + * + * As of Phaser 3.60 you can also toggle the boolean property `TweenManager.paused`. + * + * @method Phaser.Tweens.TweenManager#resumeAll + * @since 3.0.0 + * + * @return {this} This Tween Manager instance. + */ + resumeAll: function () + { + this.paused = false; + + return this; + }, + + /** + * The Scene that owns this plugin is shutting down. + * + * We need to kill and reset all internal properties as well as stop listening to Scene events. + * + * @method Phaser.Tweens.TweenManager#shutdown + * @since 3.0.0 + */ + shutdown: function () + { + this.killAll(); + + this.tweens = []; + + this.events.off(SceneEvents.UPDATE, this.update, this); + this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this); + }, + + /** + * The Scene that owns this plugin is being destroyed. + * We need to shutdown and then kill off all external references. + * + * @method Phaser.Tweens.TweenManager#destroy + * @since 3.0.0 + */ + destroy: function () + { + this.shutdown(); + + this.events.off(SceneEvents.START, this.start, this); + + this.scene = null; + this.events = null; + } + +}); + +PluginCache.register('TweenManager', TweenManager, 'tweens'); + +module.exports = TweenManager; + + +/***/ }), + +/***/ 57355: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Retrieves the value of the given key from an object. + * + * @function Phaser.Tweens.Builders.GetBoolean + * @since 3.0.0 + * + * @param {object} source - The object to retrieve the value from. + * @param {string} key - The key to look for in the `source` object. + * @param {boolean} defaultValue - The default value to return if the `key` doesn't exist or if no `source` object is provided. + * + * @return {boolean} The retrieved value. + */ +var GetBoolean = function (source, key, defaultValue) +{ + if (!source) + { + return defaultValue; + } + else if (source.hasOwnProperty(key)) + { + return source[key]; + } + else + { + return defaultValue; + } +}; + +module.exports = GetBoolean; + + +/***/ }), + +/***/ 6113: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var EaseMap = __webpack_require__(62640); +var UppercaseFirst = __webpack_require__(35355); + +/** + * This internal function is used to return the correct ease function for a Tween. + * + * It can take a variety of input, including an EaseMap based string, or a custom function. + * + * @function Phaser.Tweens.Builders.GetEaseFunction + * @since 3.0.0 + * + * @param {(string|function)} ease - The ease to find. This can be either a string from the EaseMap, or a custom function. + * @param {number[]} [easeParams] - An optional array of ease parameters to go with the ease. + * + * @return {function} The ease function. + */ +var GetEaseFunction = function (ease, easeParams) +{ + // Default ease function + var easeFunction = EaseMap.Power0; + + // Prepare ease function + if (typeof ease === 'string') + { + // String based look-up + + // 1) They specified it correctly + if (EaseMap.hasOwnProperty(ease)) + { + easeFunction = EaseMap[ease]; + } + else + { + // Do some string manipulation to try and find it + var direction = ''; + + if (ease.indexOf('.')) + { + // quad.in = Quad.easeIn + // quad.out = Quad.easeOut + // quad.inout = Quad.easeInOut + + direction = ease.substring(ease.indexOf('.') + 1); + + var directionLower = direction.toLowerCase(); + + if (directionLower === 'in') + { + direction = 'easeIn'; + } + else if (directionLower === 'out') + { + direction = 'easeOut'; + } + else if (directionLower === 'inout') + { + direction = 'easeInOut'; + } + } + + ease = UppercaseFirst(ease.substring(0, ease.indexOf('.') + 1) + direction); + + if (EaseMap.hasOwnProperty(ease)) + { + easeFunction = EaseMap[ease]; + } + } + } + else if (typeof ease === 'function') + { + // Custom function + easeFunction = ease; + } + + // No custom ease parameters? + if (!easeParams) + { + // Return ease function + return easeFunction; + } + + var cloneParams = easeParams.slice(0); + + cloneParams.unshift(0); + + // Return ease function with custom ease parameters + return function (v) + { + cloneParams[0] = v; + + return easeFunction.apply(this, cloneParams); + }; +}; + +module.exports = GetEaseFunction; + + +/***/ }), + +/***/ 91389: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Bezier = __webpack_require__(89318); +var CatmullRom = __webpack_require__(77259); +var Linear = __webpack_require__(28392); + +var FuncMap = { + bezier: Bezier, + catmull: CatmullRom, + catmullrom: CatmullRom, + linear: Linear +}; + +/** + * This internal function is used to return the correct interpolation function for a Tween. + * + * It can take a variety of input, including a string, or a custom function. + * + * @function Phaser.Tweens.Builders.GetInterpolationFunction + * @since 3.60.0 + * + * @param {(string|function|null)} interpolation - The interpolation function to find. This can be either a string, or a custom function, or null. + * + * @return {?function} The interpolation function to use, or `null`. + */ +var GetInterpolationFunction = function (interpolation) +{ + if (interpolation === null) + { + return null; + } + + // Default interpolation function + var interpolationFunction = FuncMap.linear; + + // Prepare interpolation function + if (typeof interpolation === 'string') + { + // String based look-up + + // 1) They specified it correctly + if (FuncMap.hasOwnProperty(interpolation)) + { + interpolationFunction = FuncMap[interpolation]; + } + } + else if (typeof interpolation === 'function') + { + // Custom function + interpolationFunction = interpolation; + } + + // Return interpolation function + return interpolationFunction; +}; + +module.exports = GetInterpolationFunction; + + +/***/ }), + +/***/ 55292: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Internal function used by the Tween Builder to create a function that will return + * the given value from the source. + * + * @function Phaser.Tweens.Builders.GetNewValue + * @since 3.0.0 + * + * @param {any} source - The source object to get the value from. + * @param {string} key - The property to get from the source. + * @param {any} defaultValue - A default value to return should the source not have the property set. + * + * @return {function} A function which, when called, will return the property value from the source. + */ +var GetNewValue = function (source, key, defaultValue) +{ + var valueCallback; + + if (source.hasOwnProperty(key)) + { + var t = typeof(source[key]); + + if (t === 'function') + { + valueCallback = function (target, targetKey, value, targetIndex, totalTargets, tween) + { + return source[key](target, targetKey, value, targetIndex, totalTargets, tween); + }; + } + else + { + valueCallback = function () + { + return source[key]; + }; + } + } + else if (typeof defaultValue === 'function') + { + valueCallback = defaultValue; + } + else + { + valueCallback = function () + { + return defaultValue; + }; + } + + return valueCallback; +}; + +module.exports = GetNewValue; + + +/***/ }), + +/***/ 82985: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RESERVED = __webpack_require__(81076); + +/** + * Internal function used by the Tween Builder to return an array of properties + * that the Tween will be operating on. It takes a tween configuration object + * and then checks that none of the `props` entries start with an underscore, or that + * none of the direct properties are on the Reserved list. + * + * @function Phaser.Tweens.Builders.GetProps + * @since 3.0.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig} config - The configuration object of the Tween to get the properties from. + * + * @return {string[]} An array of all the properties the tween will operate on. + */ +var GetProps = function (config) +{ + var key; + var keys = []; + + // First see if we have a props object + + if (config.hasOwnProperty('props')) + { + for (key in config.props) + { + // Skip any property that starts with an underscore + if (key.substring(0, 1) !== '_') + { + keys.push({ key: key, value: config.props[key] }); + } + } + } + else + { + for (key in config) + { + // Skip any property that is in the ReservedProps list or that starts with an underscore + if (RESERVED.indexOf(key) === -1 && key.substring(0, 1) !== '_') + { + keys.push({ key: key, value: config[key] }); + } + } + } + + return keys; +}; + +module.exports = GetProps; + + +/***/ }), + +/***/ 62329: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetValue = __webpack_require__(35154); + +/** + * Extracts an array of targets from a Tween configuration object. + * + * The targets will be looked for in a `targets` property. If it's a function, its return value will be used as the result. + * + * @function Phaser.Tweens.Builders.GetTargets + * @since 3.0.0 + * + * @param {object} config - The configuration object to use. + * + * @return {array} An array of targets (may contain only one element), or `null` if no targets were specified. + */ +var GetTargets = function (config) +{ + var targets = GetValue(config, 'targets', null); + + if (targets === null) + { + return targets; + } + + if (typeof targets === 'function') + { + targets = targets.call(); + } + + if (!Array.isArray(targets)) + { + targets = [ targets ]; + } + + return targets; +}; + +module.exports = GetTargets; + + +/***/ }), + +/***/ 17777: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Between = __webpack_require__(30976); +var FloatBetween = __webpack_require__(99472); + +/** + * @ignore + */ +function hasGetActive (def) +{ + return (!!def.getActive && typeof def.getActive === 'function'); +} + +/** + * @ignore + */ +function hasGetStart (def) +{ + return (!!def.getStart && typeof def.getStart === 'function'); +} + +/** + * @ignore + */ +function hasGetEnd (def) +{ + return (!!def.getEnd && typeof def.getEnd === 'function'); +} + +/** + * @ignore + */ +function hasGetters (def) +{ + return hasGetStart(def) || hasGetEnd(def) || hasGetActive(def); +} + +/** + * Returns `getActive`, `getStart` and `getEnd` functions for a TweenData based on a target property and end value. + * + * `getActive` if not null, is invoked _immediately_ as soon as the TweenData is running, and is set on the target property. + * `getEnd` is invoked once any start delays have expired and returns what the value should tween to. + * `getStart` is invoked when the tween reaches the end and needs to either repeat or yoyo, it returns the value to go back to. + * + * If the end value is a number, it will be treated as an absolute value and the property will be tweened to it. + * A string can be provided to specify a relative end value which consists of an operation + * (`+=` to add to the current value, `-=` to subtract from the current value, `*=` to multiply the current + * value, or `/=` to divide the current value) followed by its operand. + * + * A function can be provided to allow greater control over the end value; it will receive the target + * object being tweened, the name of the property being tweened, and the current value of the property + * as its arguments and must return a value. + * + * If both the starting and the ending values need to be controlled, an object with `getStart` and `getEnd` + * callbacks, which will receive the same arguments, can be provided instead. If an object with a `value` + * property is provided, the property will be used as the effective value under the same rules described here. + * + * @function Phaser.Tweens.Builders.GetValueOp + * @since 3.0.0 + * + * @param {string} key - The name of the property to modify. + * @param {*} propertyValue - The ending value of the property, as described above. + * + * @return {function} An array of functions, `getActive`, `getStart` and `getEnd`, which return the starting and the ending value of the property based on the provided value. + */ +var GetValueOp = function (key, propertyValue) +{ + var callbacks; + + // The returned value sets what the property will be at the END of the Tween (usually called at the start of the Tween) + var getEnd = function (target, key, value) { return value; }; + + // The returned value sets what the property will be at the START of the Tween (usually called at the end of the Tween) + var getStart = function (target, key, value) { return value; }; + + // What to set the property to the moment the TweenData is invoked + var getActive = null; + + var t = typeof(propertyValue); + + if (t === 'number') + { + // props: { + // x: 400, + // y: 300 + // } + + getEnd = function () + { + return propertyValue; + }; + } + else if (Array.isArray(propertyValue)) + { + // props: { + // x: [ 400, 300, 200 ], + // y: [ 10, 500, 10 ] + // } + + getStart = function () + { + return propertyValue[0]; + }; + + getEnd = function () + { + return propertyValue[propertyValue.length - 1]; + }; + } + else if (t === 'string') + { + // props: { + // x: '+=400', + // y: '-=300', + // z: '*=2', + // w: '/=2', + // p: 'random(10, 100)' - random float + // p: 'int(10, 100)' - random int + // } + + var op = propertyValue.toLowerCase(); + var isRandom = (op.substring(0, 6) === 'random'); + var isInt = (op.substring(0, 3) === 'int'); + + if (isRandom || isInt) + { + // random(0.5, 3.45) + // int(10, 100) + var brace1 = op.indexOf('('); + var brace2 = op.indexOf(')'); + var comma = op.indexOf(','); + + if (brace1 && brace2 && comma) + { + var value1 = parseFloat(op.substring(brace1 + 1, comma)); + var value2 = parseFloat(op.substring(comma + 1, brace2)); + + if (isRandom) + { + getEnd = function () + { + return FloatBetween(value1, value2); + }; + } + else + { + getEnd = function () + { + return Between(value1, value2); + }; + } + } + else + { + throw new Error('invalid random() format'); + } + } + else + { + op = op[0]; + var num = parseFloat(propertyValue.substr(2)); + + switch (op) + { + case '+': + getEnd = function (target, key, value) + { + return value + num; + }; + break; + + case '-': + getEnd = function (target, key, value) + { + return value - num; + }; + break; + + case '*': + getEnd = function (target, key, value) + { + return value * num; + }; + break; + + case '/': + getEnd = function (target, key, value) + { + return value / num; + }; + break; + + default: + getEnd = function () + { + return parseFloat(propertyValue); + }; + } + } + } + else if (t === 'function') + { + // The same as setting just the getEnd function and no getStart + + // props: { + // x: function (target, key, value, targetIndex, totalTargets, tween, tweenData) { return value + 50); }, + // } + + getEnd = propertyValue; + } + else if (t === 'object') + { + if (hasGetters(propertyValue)) + { + /* + x: { + // Called the moment Tween is active. The returned value sets the property on the target immediately. + getActive: function (target, key, value, targetIndex, totalTargets, tween, tweenData) + { + return value; + }, + + // Called at the start of the Tween. The returned value sets what the property will be at the END of the Tween. + getEnd: function (target, key, value, targetIndex, totalTargets, tween, tweenData) + { + return value; + }, + + // Called at the end of the Tween. The returned value sets what the property will be at the START of the Tween. + getStart: function (target, key, value, targetIndex, totalTargets, tween, tweenData) + { + return value; + } + } + */ + + if (hasGetActive(propertyValue)) + { + getActive = propertyValue.getActive; + } + + if (hasGetEnd(propertyValue)) + { + getEnd = propertyValue.getEnd; + } + + if (hasGetStart(propertyValue)) + { + getStart = propertyValue.getStart; + } + } + else if (propertyValue.hasOwnProperty('value')) + { + // 'value' may still be a string, function or a number + // props: { + // x: { value: 400, ... }, + // y: { value: 300, ... } + // } + + callbacks = GetValueOp(key, propertyValue.value); + } + else + { + // 'from' and 'to' may still be a string, function or a number + // props: { + // x: { from: 400, to: 600 }, + // y: { from: 300, to: 500 } + // } + + // Same as above, but the 'start' value is set immediately on the target + // props: { + // x: { start: 400, to: 600 }, + // y: { start: 300, to: 500 } + // } + + // 'start' value is set immediately, then it goes 'from' to 'to' during the tween + // props: { + // x: { start: 200, from: 400, to: 600 }, + // y: { start: 300, from: 300, to: 500 } + // } + + var hasTo = propertyValue.hasOwnProperty('to'); + var hasFrom = propertyValue.hasOwnProperty('from'); + var hasStart = propertyValue.hasOwnProperty('start'); + + if (hasTo && (hasFrom || hasStart)) + { + callbacks = GetValueOp(key, propertyValue.to); + + if (hasStart) + { + var startCallbacks = GetValueOp(key, propertyValue.start); + + callbacks.getActive = startCallbacks.getEnd; + } + + if (hasFrom) + { + var fromCallbacks = GetValueOp(key, propertyValue.from); + + callbacks.getStart = fromCallbacks.getEnd; + } + } + } + } + + // If callback not set by the else if block above then set it here and return it + if (!callbacks) + { + callbacks = { + getActive: getActive, + getEnd: getEnd, + getStart: getStart + }; + } + + return callbacks; +}; + +module.exports = GetValueOp; + + +/***/ }), + +/***/ 88032: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseTween = __webpack_require__(70402); +var Defaults = __webpack_require__(69902); +var GetAdvancedValue = __webpack_require__(23568); +var GetBoolean = __webpack_require__(57355); +var GetEaseFunction = __webpack_require__(6113); +var GetFastValue = __webpack_require__(95540); +var GetNewValue = __webpack_require__(55292); +var GetValue = __webpack_require__(35154); +var GetValueOp = __webpack_require__(17777); +var MergeRight = __webpack_require__(269); +var Tween = __webpack_require__(8462); + +/** + * Creates a new Number Tween. + * + * @function Phaser.Tweens.Builders.NumberTweenBuilder + * @since 3.0.0 + * + * @param {Phaser.Tweens.TweenManager} parent - The owner of the new Tween. + * @param {Phaser.Types.Tweens.NumberTweenBuilderConfig} config - Configuration for the new Tween. + * @param {Phaser.Types.Tweens.TweenConfigDefaults} defaults - Tween configuration defaults. + * + * @return {Phaser.Tweens.Tween} The new tween. + */ +var NumberTweenBuilder = function (parent, config, defaults) +{ + if (config instanceof Tween) + { + config.parent = parent; + + return config; + } + + if (defaults === undefined) + { + defaults = Defaults; + } + else + { + defaults = MergeRight(Defaults, defaults); + } + + // var tween = this.tweens.addCounter({ + // from: 100, + // to: 200, + // ... (normal tween properties) + // }) + // + // Then use it in your game via: + // + // tween.getValue() + + var from = GetFastValue(config, 'from', 0); + var to = GetFastValue(config, 'to', 1); + + var targets = [ { value: from } ]; + + var delay = GetFastValue(config, 'delay', defaults.delay); + var easeParams = GetFastValue(config, 'easeParams', defaults.easeParams); + var ease = GetFastValue(config, 'ease', defaults.ease); + + var ops = GetValueOp('value', to); + + var tween = new Tween(parent, targets); + + var tweenData = tween.add( + 0, + 'value', + ops.getEnd, + ops.getStart, + ops.getActive, + GetEaseFunction(GetFastValue(config, 'ease', ease), GetFastValue(config, 'easeParams', easeParams)), + GetNewValue(config, 'delay', delay), + GetFastValue(config, 'duration', defaults.duration), + GetBoolean(config, 'yoyo', defaults.yoyo), + GetFastValue(config, 'hold', defaults.hold), + GetFastValue(config, 'repeat', defaults.repeat), + GetFastValue(config, 'repeatDelay', defaults.repeatDelay), + false, + false + ); + + tweenData.start = from; + tweenData.current = from; + + tween.completeDelay = GetAdvancedValue(config, 'completeDelay', 0); + tween.loop = Math.round(GetAdvancedValue(config, 'loop', 0)); + tween.loopDelay = Math.round(GetAdvancedValue(config, 'loopDelay', 0)); + tween.paused = GetBoolean(config, 'paused', false); + tween.persist = GetBoolean(config, 'persist', false); + tween.isNumberTween = true; + + // Set the Callbacks + tween.callbackScope = GetValue(config, 'callbackScope', tween); + + var callbacks = BaseTween.TYPES; + + for (var i = 0; i < callbacks.length; i++) + { + var type = callbacks[i]; + + var callback = GetValue(config, type, false); + + if (callback) + { + var callbackParams = GetValue(config, type + 'Params', []); + + tween.setCallback(type, callback, callbackParams); + } + } + + return tween; +}; + +module.exports = NumberTweenBuilder; + + +/***/ }), + +/***/ 93109: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetEaseFunction = __webpack_require__(6113); +var GetValue = __webpack_require__(35154); +var MATH_CONST = __webpack_require__(36383); + +/** + * Creates a Stagger function to be used by a Tween property. + * + * The stagger function will allow you to stagger changes to the value of the property across all targets of the tween. + * + * This is only worth using if the tween has multiple targets. + * + * The following will stagger the delay by 100ms across all targets of the tween, causing them to scale down to 0.2 + * over the duration specified: + * + * ```javascript + * this.tweens.add({ + * targets: [ ... ], + * scale: 0.2, + * ease: 'linear', + * duration: 1000, + * delay: this.tweens.stagger(100) + * }); + * ``` + * + * The following will stagger the delay by 500ms across all targets of the tween using a 10 x 6 grid, staggering + * from the center out, using a cubic ease. + * + * ```javascript + * this.tweens.add({ + * targets: [ ... ], + * scale: 0.2, + * ease: 'linear', + * duration: 1000, + * delay: this.tweens.stagger(500, { grid: [ 10, 6 ], from: 'center', ease: 'cubic.out' }) + * }); + * ``` + * + * @function Phaser.Tweens.Builders.StaggerBuilder + * @since 3.19.0 + * + * @param {(number|number[])} value - The amount to stagger by, or an array containing two elements representing the min and max values to stagger between. + * @param {Phaser.Types.Tweens.StaggerConfig} [config] - A Stagger Configuration object. + * + * @return {function} The stagger function. + */ +var StaggerBuilder = function (value, options) +{ + if (options === undefined) { options = {}; } + + var result; + + var start = GetValue(options, 'start', 0); + var ease = GetValue(options, 'ease', null); + var grid = GetValue(options, 'grid', null); + + var from = GetValue(options, 'from', 0); + + var fromFirst = (from === 'first'); + var fromCenter = (from === 'center'); + var fromLast = (from === 'last'); + var fromValue = (typeof(from) === 'number'); + + var isRange = (Array.isArray(value)); + var value1 = (isRange) ? parseFloat(value[0]) : parseFloat(value); + var value2 = (isRange) ? parseFloat(value[1]) : 0; + var maxValue = Math.max(value1, value2); + + if (isRange) + { + start += value1; + } + + if (grid) + { + // Pre-calc the grid to save doing it for every TweenData update + var gridWidth = grid[0]; + var gridHeight = grid[1]; + + var fromX = 0; + var fromY = 0; + + var distanceX = 0; + var distanceY = 0; + + var gridValues = []; + + if (fromLast) + { + fromX = gridWidth - 1; + fromY = gridHeight - 1; + } + else if (fromValue) + { + fromX = from % gridWidth; + fromY = Math.floor(from / gridWidth); + } + else if (fromCenter) + { + fromX = (gridWidth - 1) / 2; + fromY = (gridHeight - 1) / 2; + } + + var gridMax = MATH_CONST.MIN_SAFE_INTEGER; + + for (var toY = 0; toY < gridHeight; toY++) + { + gridValues[toY] = []; + + for (var toX = 0; toX < gridWidth; toX++) + { + distanceX = fromX - toX; + distanceY = fromY - toY; + + var dist = Math.sqrt(distanceX * distanceX + distanceY * distanceY); + + if (dist > gridMax) + { + gridMax = dist; + } + + gridValues[toY][toX] = dist; + } + } + } + + var easeFunction = (ease) ? GetEaseFunction(ease) : null; + + if (grid) + { + result = function (target, key, value, index) + { + var gridSpace = 0; + var toX = index % gridWidth; + var toY = Math.floor(index / gridWidth); + + if (toX >= 0 && toX < gridWidth && toY >= 0 && toY < gridHeight) + { + gridSpace = gridValues[toY][toX]; + } + + var output; + + if (isRange) + { + var diff = (value2 - value1); + + if (easeFunction) + { + output = ((gridSpace / gridMax) * diff) * easeFunction(gridSpace / gridMax); + } + else + { + output = (gridSpace / gridMax) * diff; + } + } + else if (easeFunction) + { + output = (gridSpace * value1) * easeFunction(gridSpace / gridMax); + } + else + { + output = gridSpace * value1; + } + + return output + start; + }; + } + else + { + result = function (target, key, value, index, total) + { + // zero offset + total--; + + var fromIndex; + + if (fromFirst) + { + fromIndex = index; + } + else if (fromCenter) + { + fromIndex = Math.abs((total / 2) - index); + } + else if (fromLast) + { + fromIndex = total - index; + } + else if (fromValue) + { + fromIndex = Math.abs(from - index); + } + + var output; + + if (isRange) + { + var spacing; + + if (fromCenter) + { + spacing = ((value2 - value1) / total) * (fromIndex * 2); + } + else + { + spacing = ((value2 - value1) / total) * fromIndex; + } + + if (easeFunction) + { + output = spacing * easeFunction(fromIndex / total); + } + else + { + output = spacing; + } + } + else if (easeFunction) + { + output = (total * maxValue) * easeFunction(fromIndex / total); + } + else + { + output = fromIndex * value1; + } + + return output + start; + }; + } + + return result; +}; + +module.exports = StaggerBuilder; + + +/***/ }), + +/***/ 8357: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseTween = __webpack_require__(70402); +var Defaults = __webpack_require__(69902); +var GetAdvancedValue = __webpack_require__(23568); +var GetBoolean = __webpack_require__(57355); +var GetEaseFunction = __webpack_require__(6113); +var GetFastValue = __webpack_require__(95540); +var GetInterpolationFunction = __webpack_require__(91389); +var GetNewValue = __webpack_require__(55292); +var GetProps = __webpack_require__(82985); +var GetTargets = __webpack_require__(62329); +var GetValue = __webpack_require__(35154); +var GetValueOp = __webpack_require__(17777); +var MergeRight = __webpack_require__(269); +var Tween = __webpack_require__(8462); + +/** + * Creates a new Tween. + * + * @function Phaser.Tweens.Builders.TweenBuilder + * @since 3.0.0 + * + * @param {Phaser.Tweens.TweenManager} parent - The owner of the new Tween. + * @param {Phaser.Types.Tweens.TweenBuilderConfig|object} config - Configuration for the new Tween. + * @param {Phaser.Types.Tweens.TweenConfigDefaults} defaults - Tween configuration defaults. + * + * @return {Phaser.Tweens.Tween} The new tween. + */ +var TweenBuilder = function (parent, config, defaults) +{ + if (config instanceof Tween) + { + config.parent = parent; + + return config; + } + + if (defaults === undefined) + { + defaults = Defaults; + } + else + { + defaults = MergeRight(Defaults, defaults); + } + + // Create arrays of the Targets and the Properties. This Targets array should not be manipulated outside of this Tween. + var targets = GetTargets(config); + + if (!targets && defaults.targets) + { + targets = defaults.targets; + } + + var props = GetProps(config); + + // Default Tween values + + var delay = GetFastValue(config, 'delay', defaults.delay); + var duration = GetFastValue(config, 'duration', defaults.duration); + var easeParams = GetFastValue(config, 'easeParams', defaults.easeParams); + var ease = GetFastValue(config, 'ease', defaults.ease); + var hold = GetFastValue(config, 'hold', defaults.hold); + var repeat = GetFastValue(config, 'repeat', defaults.repeat); + var repeatDelay = GetFastValue(config, 'repeatDelay', defaults.repeatDelay); + var yoyo = GetBoolean(config, 'yoyo', defaults.yoyo); + var flipX = GetBoolean(config, 'flipX', defaults.flipX); + var flipY = GetBoolean(config, 'flipY', defaults.flipY); + var interpolation = GetFastValue(config, 'interpolation', defaults.interpolation); + + var addTarget = function (tween, targetIndex, key, value) + { + if (key === 'texture') + { + var texture = value; + var frame = undefined; + + if (Array.isArray(value)) + { + texture = value[0]; + frame = value[1]; + } + else if (value.hasOwnProperty('value')) + { + texture = value.value; + + if (Array.isArray(value.value)) + { + texture = value.value[0]; + frame = value.value[1]; + } + else if (typeof value.value === 'string') + { + texture = value.value; + } + } + else if (typeof value === 'string') + { + texture = value; + } + + tween.addFrame( + targetIndex, + texture, + frame, + GetNewValue(value, 'delay', delay), + GetFastValue(value, 'duration', duration), + GetFastValue(value, 'hold', hold), + GetFastValue(value, 'repeat', repeat), + GetFastValue(value, 'repeatDelay', repeatDelay), + GetBoolean(value, 'flipX', flipX), + GetBoolean(value, 'flipY', flipY) + ); + } + else + { + var ops = GetValueOp(key, value); + + var interpolationFunc = GetInterpolationFunction(GetFastValue(value, 'interpolation', interpolation)); + + tween.add( + targetIndex, + key, + ops.getEnd, + ops.getStart, + ops.getActive, + GetEaseFunction(GetFastValue(value, 'ease', ease), GetFastValue(value, 'easeParams', easeParams)), + GetNewValue(value, 'delay', delay), + GetFastValue(value, 'duration', duration), + GetBoolean(value, 'yoyo', yoyo), + GetFastValue(value, 'hold', hold), + GetFastValue(value, 'repeat', repeat), + GetFastValue(value, 'repeatDelay', repeatDelay), + GetBoolean(value, 'flipX', flipX), + GetBoolean(value, 'flipY', flipY), + interpolationFunc, + (interpolationFunc) ? value : null + ); + } + }; + + var tween = new Tween(parent, targets); + + // Loop through every property defined in the Tween, i.e.: props { x, y, alpha } + for (var p = 0; p < props.length; p++) + { + var key = props[p].key; + var value = props[p].value; + + // Create 1 TweenData per target, per property + for (var targetIndex = 0; targetIndex < targets.length; targetIndex++) + { + // Special-case for scale short-cut: + if (key === 'scale' && !targets[targetIndex].hasOwnProperty('scale')) + { + addTarget(tween, targetIndex, 'scaleX', value); + addTarget(tween, targetIndex, 'scaleY', value); + } + else + { + addTarget(tween, targetIndex, key, value); + } + } + } + + tween.completeDelay = GetAdvancedValue(config, 'completeDelay', 0); + tween.loop = Math.round(GetAdvancedValue(config, 'loop', 0)); + tween.loopDelay = Math.round(GetAdvancedValue(config, 'loopDelay', 0)); + tween.paused = GetBoolean(config, 'paused', false); + tween.persist = GetBoolean(config, 'persist', false); + + // Set the Callbacks + tween.callbackScope = GetFastValue(config, 'callbackScope', tween); + + var callbacks = BaseTween.TYPES; + + for (var i = 0; i < callbacks.length; i++) + { + var type = callbacks[i]; + + var callback = GetValue(config, type, false); + + if (callback) + { + var callbackParams = GetValue(config, type + 'Params', []); + + tween.setCallback(type, callback, callbackParams); + } + } + + return tween; +}; + +module.exports = TweenBuilder; + + +/***/ }), + +/***/ 26012: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseTween = __webpack_require__(70402); +var GetAdvancedValue = __webpack_require__(23568); +var GetBoolean = __webpack_require__(57355); +var GetTargets = __webpack_require__(62329); +var GetValue = __webpack_require__(35154); +var TweenBuilder = __webpack_require__(8357); +var TweenChain = __webpack_require__(43960); + +/** + * Creates a new Tween Chain instance. + * + * @function Phaser.Tweens.Builders.TweenChainBuilder + * @since 3.60.0 + * + * @param {Phaser.Tweens.TweenManager} parent - The owner of the new Tween. + * @param {Phaser.Types.Tweens.TweenChainBuilderConfig|object} config - Configuration for the new Tween. + * + * @return {Phaser.Tweens.TweenChain} The new Tween Chain. + */ +var TweenChainBuilder = function (parent, config) +{ + if (config instanceof TweenChain) + { + config.parent = parent; + + return config; + } + + // Default TweenChain values + + var chain = new TweenChain(parent); + + chain.startDelay = GetValue(config, 'delay', 0); + chain.completeDelay = GetAdvancedValue(config, 'completeDelay', 0); + chain.loop = Math.round(GetAdvancedValue(config, 'loop', GetValue(config, 'repeat', 0))); + chain.loopDelay = Math.round(GetAdvancedValue(config, 'loopDelay', GetValue(config, 'repeatDelay', 0))); + chain.paused = GetBoolean(config, 'paused', false); + chain.persist = GetBoolean(config, 'persist', false); + + // Set the Callbacks + chain.callbackScope = GetValue(config, 'callbackScope', chain); + + var i; + var callbacks = BaseTween.TYPES; + + for (i = 0; i < callbacks.length; i++) + { + var type = callbacks[i]; + + var callback = GetValue(config, type, false); + + if (callback) + { + var callbackParams = GetValue(config, type + 'Params', []); + + chain.setCallback(type, callback, callbackParams); + } + } + + // Add in the Tweens + var tweens = GetValue(config, 'tweens', null); + + if (Array.isArray(tweens)) + { + var chainedTweens = []; + + var targets = GetTargets(config); + var defaults = undefined; + + if (targets) + { + defaults = { targets: targets }; + } + + for (i = 0; i < tweens.length; i++) + { + chainedTweens.push(TweenBuilder(chain, tweens[i], defaults)); + } + + chain.add(chainedTweens); + } + + return chain; +}; + +module.exports = TweenChainBuilder; + + +/***/ }), + +/***/ 30231: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tweens.Builders + */ + +module.exports = { + + GetBoolean: __webpack_require__(57355), + GetEaseFunction: __webpack_require__(6113), + GetInterpolationFunction: __webpack_require__(91389), + GetNewValue: __webpack_require__(55292), + GetProps: __webpack_require__(82985), + GetTargets: __webpack_require__(62329), + GetValueOp: __webpack_require__(17777), + NumberTweenBuilder: __webpack_require__(88032), + StaggerBuilder: __webpack_require__(93109), + TweenBuilder: __webpack_require__(8357) + +}; + + +/***/ }), + +/***/ 73685: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Active Event. + * + * This event is dispatched by a Tween when it becomes active within the Tween Manager. + * + * An 'active' Tween is one that is now progressing, although it may not yet be updating + * any target properties, due to settings such as `delay`. If you need an event for when + * the Tween starts actually updating its first property, see `TWEEN_START`. + * + * Listen to it from a Tween instance using `Tween.on('active', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.create({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000 + * }); + * tween.on('active', listener); + * this.tweens.existing(tween); + * ``` + * + * Note that this event is usually dispatched already by the time you call `this.tweens.add()`, and is + * meant for use with `tweens.create()` and/or `tweens.existing()`. + * + * @event Phaser.Tweens.Events#TWEEN_ACTIVE + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {(any|any[])} targets - The targets of the Tween. If this Tween has multiple targets this will be an array of the targets. + */ +module.exports = 'active'; + + +/***/ }), + +/***/ 98540: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Complete Event. + * + * This event is dispatched by a Tween when it completes playback entirely, factoring in repeats and loops. + * + * If the Tween has been set to loop or repeat infinitely, this event will not be dispatched + * unless the `Tween.stop` method is called. + * + * If a Tween has a `completeDelay` set, this event will fire after that delay expires. + * + * Listen to it from a Tween instance using `Tween.on('complete', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000 + * }); + * tween.on('complete', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_COMPLETE + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {(any|any[])} targets - The targets of the Tween. If this Tween has multiple targets this will be an array of the targets. + */ +module.exports = 'complete'; + + +/***/ }), + +/***/ 67233: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Loop Event. + * + * This event is dispatched by a Tween when it loops. + * + * This event will only be dispatched if the Tween has a loop count set. + * + * If a Tween has a `loopDelay` set, this event will fire after that delay expires. + * + * The difference between `loop` and `repeat` is that `repeat` is a property setting, + * where-as `loop` applies to the entire Tween. + * + * Listen to it from a Tween instance using `Tween.on('loop', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000, + * loop: 6 + * }); + * tween.on('loop', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_LOOP + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {(any|any[])} targets - The targets of the Tween. If this Tween has multiple targets this will be an array of the targets. + */ +module.exports = 'loop'; + + +/***/ }), + +/***/ 2859: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Pause Event. + * + * This event is dispatched by a Tween when it is paused. + * + * Listen to it from a Tween instance using `Tween.on('pause', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * ease: 'Power1', + * duration: 3000, + * x: 600 + * }); + * tween.on('pause', listener); + * // At some point later ... + * tween.pause(); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_PAUSE + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + */ +module.exports = 'pause'; + + +/***/ }), + +/***/ 98336: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Repeat Event. + * + * This event is dispatched by a Tween when one of the properties it is tweening repeats. + * + * This event will only be dispatched if the Tween has a property with a repeat count set. + * + * If a Tween has a `repeatDelay` set, this event will fire after that delay expires. + * + * The difference between `loop` and `repeat` is that `repeat` is a property setting, + * where-as `loop` applies to the entire Tween. + * + * Listen to it from a Tween instance using `Tween.on('repeat', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000, + * repeat: 4 + * }); + * tween.on('repeat', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_REPEAT + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {string} key - The property on the target that has just repeated, i.e. `x` or `scaleY`, or whatever property you are tweening. + * @param {any} target - The target object that was repeated. Usually a Game Object, but can be of any type. + * @param {number} current - The current value of the property being set on the target. + * @param {number} previous - The previous value of the property being set on the target. + */ +module.exports = 'repeat'; + + +/***/ }), + +/***/ 25764: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Resume Event. + * + * This event is dispatched by a Tween when it is resumed from a paused state. + * + * Listen to it from a Tween instance using `Tween.on('resume', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * ease: 'Power1', + * duration: 3000, + * x: 600 + * }); + * tween.on('resume', listener); + * // At some point later ... + * tween.resume(); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_RESUME + * @type {string} + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + */ +module.exports = 'resume'; + + +/***/ }), + +/***/ 32193: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Start Event. + * + * This event is dispatched by a Tween when it starts tweening its first property. + * + * A Tween will only emit this event once, as it can only start once. + * + * If a Tween has a `delay` set, this event will fire after that delay expires. + * + * Listen to it from a Tween instance using `Tween.on('start', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000 + * }); + * tween.on('start', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_START + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {(any|any[])} targets - The targets of the Tween. If this Tween has multiple targets this will be an array of the targets. + */ +module.exports = 'start'; + + +/***/ }), + +/***/ 84371: +/***/ ((module) => { + +/** + * @author samme + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Stop Event. + * + * This event is dispatched by a Tween when it is stopped. + * + * Listen to it from a Tween instance using `Tween.on('stop', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000 + * }); + * tween.on('stop', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_STOP + * @type {string} + * @since 3.24.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {(any|any[])} targets - The targets of the Tween. If this Tween has multiple targets this will be an array of the targets. + */ +module.exports = 'stop'; + + +/***/ }), + +/***/ 70766: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Update Event. + * + * This event is dispatched by a Tween every time it updates _any_ of the properties it is tweening. + * + * A Tween that is changing 3 properties of a target will emit this event 3 times per change, once per property. + * + * **Note:** This is a very high frequency event and may be dispatched multiple times, every single frame. + * + * Listen to it from a Tween instance using `Tween.on('update', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000, + * }); + * tween.on('update', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_UPDATE + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {string} key - The property on the target that has just updated, i.e. `x` or `scaleY`, or whatever property you are tweening. + * @param {any} target - The target object that was updated. Usually a Game Object, but can be of any type. + * @param {number} current - The current value of the property that was tweened. + * @param {number} previous - The previous value of the property that was tweened, prior to this update. + */ +module.exports = 'update'; + + +/***/ }), + +/***/ 55659: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * The Tween Yoyo Event. + * + * This event is dispatched by a Tween whenever a property it is tweening yoyos. + * + * This event will only be dispatched if the Tween has a property with `yoyo` set. + * + * If the Tween has a `hold` value, this event is dispatched when the hold expires. + * + * This event is dispatched for every property, and for every target, that yoyos. + * For example, if a Tween was updating 2 properties and had 10 targets, this event + * would be dispatched 20 times (twice per target). So be careful how you use it! + * + * Listen to it from a Tween instance using `Tween.on('yoyo', listener)`, i.e.: + * + * ```javascript + * var tween = this.tweens.add({ + * targets: image, + * x: 500, + * ease: 'Power1', + * duration: 3000, + * yoyo: true + * }); + * tween.on('yoyo', listener); + * ``` + * + * @event Phaser.Tweens.Events#TWEEN_YOYO + * @type {string} + * @since 3.19.0 + * + * @param {Phaser.Tweens.Tween} tween - A reference to the Tween instance that emitted the event. + * @param {string} key - The property on the target that has just yoyo'd, i.e. `x` or `scaleY`, or whatever property you are tweening. + * @param {any} target - The target object that was yoyo'd. Usually a Game Object, but can be of any type. + * @param {number} current - The current value of the property being set on the target. + * @param {number} previous - The previous value of the property being set on the target. + */ +module.exports = 'yoyo'; + + +/***/ }), + +/***/ 842: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tweens.Events + */ + +module.exports = { + + TWEEN_ACTIVE: __webpack_require__(73685), + TWEEN_COMPLETE: __webpack_require__(98540), + TWEEN_LOOP: __webpack_require__(67233), + TWEEN_PAUSE: __webpack_require__(2859), + TWEEN_RESUME: __webpack_require__(25764), + TWEEN_REPEAT: __webpack_require__(98336), + TWEEN_START: __webpack_require__(32193), + TWEEN_STOP: __webpack_require__(84371), + TWEEN_UPDATE: __webpack_require__(70766), + TWEEN_YOYO: __webpack_require__(55659) + +}; + + +/***/ }), + +/***/ 43066: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Tweens + */ + +var Tweens = { + + States: __webpack_require__(86353), + + Builders: __webpack_require__(30231), + Events: __webpack_require__(842), + + TweenManager: __webpack_require__(40382), + Tween: __webpack_require__(8462), + TweenData: __webpack_require__(48177), + TweenFrameData: __webpack_require__(42220), + + BaseTween: __webpack_require__(70402), + TweenChain: __webpack_require__(43960) +}; + +module.exports = Tweens; + + +/***/ }), + +/***/ 70402: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var EventEmitter = __webpack_require__(50792); +var Events = __webpack_require__(842); +var TWEEN_CONST = __webpack_require__(86353); + +/** + * @classdesc + * As the name implies, this is the base Tween class that both the Tween and TweenChain + * inherit from. It contains shared properties and methods common to both types of Tween. + * + * Typically you would never instantiate this class directly, although you could certainly + * use it to create your own variation of Tweens from. + * + * @class BaseTween + * @memberof Phaser.Tweens + * @extends Phaser.Events.EventEmitter + * @constructor + * @since 3.60.0 + * + * @param {(Phaser.Tweens.TweenManager|Phaser.Tweens.TweenChain)} parent - A reference to the Tween Manager, or Tween Chain, that owns this Tween. + */ +var BaseTween = new Class({ + + Extends: EventEmitter, + + initialize: + + function BaseTween (parent) + { + EventEmitter.call(this); + + /** + * A reference to the Tween Manager, or Tween Chain, that owns this Tween. + * + * @name Phaser.Tweens.BaseTween#parent + * @type {(Phaser.Tweens.TweenManager|Phaser.Tweens.TweenChain)} + * @since 3.60.0 + */ + this.parent = parent; + + /** + * The main data array. For a Tween, this contains all of the `TweenData` objects, each + * containing a unique property and target that is being tweened. + * + * For a TweenChain, this contains an array of `Tween` instances, which are being played + * through in sequence. + * + * @name Phaser.Tweens.BaseTween#data + * @type {(Phaser.Tweens.TweenData[]|Phaser.Tweens.Tween[])} + * @since 3.60.0 + */ + this.data = []; + + /** + * The cached size of the data array. + * + * @name Phaser.Tweens.BaseTween#totalData + * @type {number} + * @since 3.60.0 + */ + this.totalData = 0; + + /** + * The time in milliseconds before the 'onStart' event fires. + * + * For a Tween, this is the shortest `delay` value across all of the TweenDatas it owns. + * For a TweenChain, it is whatever delay value was given in the configuration. + * + * @name Phaser.Tweens.BaseTween#startDelay + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.startDelay = 0; + + /** + * Has this Tween started playback yet? + * + * This boolean is toggled when the Tween leaves the 'start delayed' state and begins running. + * + * @name Phaser.Tweens.BaseTween#hasStarted + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.hasStarted = false; + + /** + * Scales the time applied to this Tween. A value of 1 runs in real-time. A value of 0.5 runs 50% slower, and so on. + * + * The value isn't used when calculating total duration of the tween, it's a run-time delta adjustment only. + * + * This value is multiplied by the `TweenManager.timeScale`. + * + * @name Phaser.Tweens.BaseTween#timeScale + * @type {number} + * @default 1 + * @since 3.60.0 + */ + this.timeScale = 1; + + /** + * The number of times this Tween will loop. + * + * Can be -1 for an infinite loop, zero for none, or a positive integer. + * + * Typically this is set in the configuration object, but can also be set directly + * as long as this Tween is paused and hasn't started playback. + * + * When enabled it will play through ALL Tweens again. + * + * Use TweenData.repeat to loop a single element. + * + * @name Phaser.Tweens.BaseTween#loop + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.loop = 0; + + /** + * The time in milliseconds before the Tween loops. + * + * Only used if `loop` is > 0. + * + * @name Phaser.Tweens.BaseTween#loopDelay + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.loopDelay = 0; + + /** + * Internal counter recording how many loops are left to run. + * + * @name Phaser.Tweens.BaseTween#loopCounter + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.loopCounter = 0; + + /** + * The time in milliseconds before the 'onComplete' event fires. + * + * This never fires if `loop = -1` as it never completes because it has been + * set to loop forever. + * + * @name Phaser.Tweens.BaseTween#completeDelay + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.completeDelay = 0; + + /** + * An internal countdown timer (used by loopDelay and completeDelay) + * + * @name Phaser.Tweens.BaseTween#countdown + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.countdown = 0; + + /** + * The current state of the Tween. + * + * @name Phaser.Tweens.BaseTween#state + * @type {Phaser.Tweens.StateType} + * @since 3.60.0 + */ + this.state = TWEEN_CONST.PENDING; + + /** + * Is the Tween currently paused? + * + * A paused Tween needs to be started with the `play` method, or resumed with the `resume` method. + * + * This property can be toggled at runtime if required. + * + * @name Phaser.Tweens.BaseTween#paused + * @type {boolean} + * @default false + * @since 3.60.0 + */ + this.paused = false; + + /** + * An object containing the different Tween callback functions. + * + * You can either set these in the Tween config, or by calling the `Tween.setCallback` method. + * + * The types available are: + * + * `onActive` - When the Tween is first created it moves to an 'active' state when added to the Tween Manager. 'Active' does not mean 'playing'. + * `onStart` - When the Tween starts playing after a delayed or paused state. This will happen at the same time as `onActive` if the tween has no delay and isn't paused. + * `onLoop` - When a Tween loops, if it has been set to do so. This happens _after_ the `loopDelay` expires, if set. + * `onComplete` - When the Tween finishes playback fully. Never invoked if the Tween is set to repeat infinitely. + * `onStop` - Invoked only if the `Tween.stop` method is called. + * `onPause` - Invoked only if the `Tween.pause` method is called. Not invoked if the Tween Manager is paused. + * `onResume` - Invoked only if the `Tween.resume` method is called. Not invoked if the Tween Manager is resumed. + * + * The following types are also available and are invoked on a `TweenData` level - that is per-object, per-property, being tweened. + * + * `onYoyo` - When a TweenData starts a yoyo. This happens _after_ the `hold` delay expires, if set. + * `onRepeat` - When a TweenData repeats playback. This happens _after_ the `repeatDelay` expires, if set. + * `onUpdate` - When a TweenData updates a property on a source target during playback. + * + * @name Phaser.Tweens.BaseTween#callbacks + * @type {Phaser.Types.Tweens.TweenCallbacks} + * @since 3.60.0 + */ + this.callbacks = { + onActive: null, + onComplete: null, + onLoop: null, + onPause: null, + onRepeat: null, + onResume: null, + onStart: null, + onStop: null, + onUpdate: null, + onYoyo: null + }; + + /** + * The scope (or context) in which all of the callbacks are invoked. + * + * This defaults to be this Tween, but you can override this property + * to set it to whatever object you require. + * + * @name Phaser.Tweens.BaseTween#callbackScope + * @type {any} + * @since 3.60.0 + */ + this.callbackScope; + + /** + * Will this Tween persist after playback? A Tween that persists will _not_ be destroyed by the + * Tween Manager, or when calling `Tween.stop`, and can be re-played as required. You can either + * set this property when creating the tween in the tween config, or set it _prior_ to playback. + * + * However, it's up to you to ensure you destroy persistent tweens when you are finished with them, + * or they will retain references you may no longer require and waste memory. + * + * By default, `Tweens` are set to _not_ persist, so they are automatically cleaned-up by + * the Tween Manager. + * + * @name Phaser.Tweens.BaseTween#persist + * @type {boolean} + * @since 3.60.0 + */ + this.persist = false; + }, + + /** + * Sets the value of the time scale applied to this Tween. A value of 1 runs in real-time. + * A value of 0.5 runs 50% slower, and so on. + * + * The value isn't used when calculating total duration of the tween, it's a run-time delta adjustment only. + * + * This value is multiplied by the `TweenManager.timeScale`. + * + * @method Phaser.Tweens.BaseTween#setTimeScale + * @since 3.60.0 + * + * @param {number} value - The time scale value to set. + * + * @return {this} This Tween instance. + */ + setTimeScale: function (value) + { + this.timeScale = value; + + return this; + }, + + /** + * Gets the value of the time scale applied to this Tween. A value of 1 runs in real-time. + * A value of 0.5 runs 50% slower, and so on. + * + * @method Phaser.Tweens.BaseTween#getTimeScale + * @since 3.60.0 + * + * @return {number} The value of the time scale applied to this Tween. + */ + getTimeScale: function () + { + return this.timeScale; + }, + + /** + * Checks if this Tween is currently playing. + * + * If this Tween is paused, or not active, this method will return false. + * + * @method Phaser.Tweens.BaseTween#isPlaying + * @since 3.60.0 + * + * @return {boolean} `true` if the Tween is playing, otherwise `false`. + */ + isPlaying: function () + { + return (!this.paused && this.isActive()); + }, + + /** + * Checks if the Tween is currently paused. + * + * This is the same as inspecting the `BaseTween.paused` property directly. + * + * @method Phaser.Tweens.BaseTween#isPaused + * @since 3.60.0 + * + * @return {boolean} `true` if the Tween is paused, otherwise `false`. + */ + isPaused: function () + { + return this.paused; + }, + + /** + * Pauses the Tween immediately. Use `resume` to continue playback. + * + * You can also toggle the `Tween.paused` boolean property, but doing so will not trigger the PAUSE event. + * + * @method Phaser.Tweens.BaseTween#pause + * @fires Phaser.Tweens.Events#TWEEN_PAUSE + * @since 3.60.0 + * + * @return {this} This Tween instance. + */ + pause: function () + { + if (!this.paused) + { + this.paused = true; + + this.dispatchEvent(Events.TWEEN_PAUSE, 'onPause'); + } + + return this; + }, + + /** + * Resumes the playback of a previously paused Tween. + * + * You can also toggle the `Tween.paused` boolean property, but doing so will not trigger the RESUME event. + * + * @method Phaser.Tweens.BaseTween#resume + * @fires Phaser.Tweens.Events#TWEEN_RESUME + * @since 3.60.0 + * + * @return {this} This Tween instance. + */ + resume: function () + { + if (this.paused) + { + this.paused = false; + + this.dispatchEvent(Events.TWEEN_RESUME, 'onResume'); + } + + return this; + }, + + /** + * Internal method that makes this Tween active within the TweenManager + * and emits the onActive event and callback. + * + * @method Phaser.Tweens.BaseTween#makeActive + * @fires Phaser.Tweens.Events#TWEEN_ACTIVE + * @since 3.60.0 + */ + makeActive: function () + { + this.parent.makeActive(this); + + this.dispatchEvent(Events.TWEEN_ACTIVE, 'onActive'); + }, + + /** + * Internal method that handles this tween completing and emitting the onComplete event + * and callback. + * + * @method Phaser.Tweens.BaseTween#onCompleteHandler + * @since 3.60.0 + */ + onCompleteHandler: function () + { + this.setPendingRemoveState(); + + this.dispatchEvent(Events.TWEEN_COMPLETE, 'onComplete'); + }, + + /** + * Flags the Tween as being complete, whatever stage of progress it is at. + * + * If an `onComplete` callback has been defined it will automatically invoke it, unless a `delay` + * argument is provided, in which case the Tween will delay for that period of time before calling the callback. + * + * If you don't need a delay or don't have an `onComplete` callback then call `Tween.stop` instead. + * + * @method Phaser.Tweens.BaseTween#complete + * @fires Phaser.Tweens.Events#TWEEN_COMPLETE + * @since 3.2.0 + * + * @param {number} [delay=0] - The time to wait before invoking the complete callback. If zero it will fire immediately. + * + * @return {this} This Tween instance. + */ + complete: function (delay) + { + if (delay === undefined) { delay = 0; } + + if (delay) + { + this.setCompleteDelayState(); + + this.countdown = delay; + } + else + { + this.onCompleteHandler(); + } + + return this; + }, + + /** + * Flags the Tween as being complete only once the current loop has finished. + * + * This is a useful way to stop an infinitely looping tween once a complete cycle is over, + * rather than abruptly. + * + * If you don't have a loop then call `Tween.stop` instead. + * + * @method Phaser.Tweens.BaseTween#completeAfterLoop + * @fires Phaser.Tweens.Events#TWEEN_COMPLETE + * @since 3.60.0 + * + * @param {number} [loops=0] - The number of loops that should finish before this tween completes. Zero means complete just the current loop. + * + * @return {this} This Tween instance. + */ + completeAfterLoop: function (loops) + { + if (loops === undefined) { loops = 0; } + + if (this.loopCounter > loops) + { + this.loopCounter = loops; + } + + return this; + }, + + /** + * Immediately removes this Tween from the TweenManager and all of its internal arrays, + * no matter what stage it is at. Then sets the tween state to `REMOVED`. + * + * You should dispose of your reference to this tween after calling this method, to + * free it from memory. If you no longer require it, call `Tween.destroy()` on it. + * + * @method Phaser.Tweens.BaseTween#remove + * @since 3.60.0 + * + * @return {this} This Tween instance. + */ + remove: function () + { + if (this.parent) + { + this.parent.remove(this); + } + + return this; + }, + + /** + * Stops the Tween immediately, whatever stage of progress it is at. + * + * If not a part of a Tween Chain it is also flagged for removal by the Tween Manager. + * + * If an `onStop` callback has been defined it will automatically invoke it. + * + * The Tween will be removed during the next game frame, but should be considered 'destroyed' from this point on. + * + * Typically, you cannot play a Tween that has been stopped. If you just wish to pause the tween, not destroy it, + * then call the `pause` method instead and use `resume` to continue playback. If you wish to restart the Tween, + * use the `restart` or `seek` methods. + * + * @method Phaser.Tweens.BaseTween#stop + * @fires Phaser.Tweens.Events#TWEEN_STOP + * @since 3.60.0 + * + * @return {this} This Tween instance. + */ + stop: function () + { + if (this.parent && !this.isRemoved() && !this.isPendingRemove() && !this.isDestroyed()) + { + this.dispatchEvent(Events.TWEEN_STOP, 'onStop'); + + this.setPendingRemoveState(); + } + + return this; + }, + + /** + * Internal method that handles the processing of the loop delay countdown timer and + * the dispatch of related events. Called automatically by `Tween.update`. + * + * @method Phaser.Tweens.BaseTween#updateLoopCountdown + * @since 3.60.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + updateLoopCountdown: function (delta) + { + this.countdown -= delta; + + if (this.countdown <= 0) + { + this.setActiveState(); + + this.dispatchEvent(Events.TWEEN_LOOP, 'onLoop'); + } + }, + + /** + * Internal method that handles the processing of the start delay countdown timer and + * the dispatch of related events. Called automatically by `Tween.update`. + * + * @method Phaser.Tweens.BaseTween#updateStartCountdown + * @since 3.60.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + updateStartCountdown: function (delta) + { + this.countdown -= delta; + + if (this.countdown <= 0) + { + this.hasStarted = true; + + this.setActiveState(); + + this.dispatchEvent(Events.TWEEN_START, 'onStart'); + + // Reset the delta so we always start progress from zero + delta = 0; + } + + return delta; + }, + + /** + * Internal method that handles the processing of the complete delay countdown timer and + * the dispatch of related events. Called automatically by `Tween.update`. + * + * @method Phaser.Tweens.BaseTween#updateCompleteDelay + * @since 3.60.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + */ + updateCompleteDelay: function (delta) + { + this.countdown -= delta; + + if (this.countdown <= 0) + { + this.onCompleteHandler(); + } + }, + + /** + * Sets an event based callback to be invoked during playback. + * + * Calling this method will replace a previously set callback for the given type, if any exists. + * + * The types available are: + * + * `onActive` - When the Tween is first created it moves to an 'active' state when added to the Tween Manager. 'Active' does not mean 'playing'. + * `onStart` - When the Tween starts playing after a delayed or paused state. This will happen at the same time as `onActive` if the tween has no delay and isn't paused. + * `onLoop` - When a Tween loops, if it has been set to do so. This happens _after_ the `loopDelay` expires, if set. + * `onComplete` - When the Tween finishes playback fully. Never invoked if the Tween is set to repeat infinitely. + * `onStop` - Invoked only if the `Tween.stop` method is called. + * `onPause` - Invoked only if the `Tween.pause` method is called. Not invoked if the Tween Manager is paused. + * `onResume` - Invoked only if the `Tween.resume` method is called. Not invoked if the Tween Manager is resumed. + * + * The following types are also available and are invoked on a `TweenData` level - that is per-object, per-property, being tweened. + * + * `onYoyo` - When a TweenData starts a yoyo. This happens _after_ the `hold` delay expires, if set. + * `onRepeat` - When a TweenData repeats playback. This happens _after_ the `repeatDelay` expires, if set. + * `onUpdate` - When a TweenData updates a property on a source target during playback. + * + * @method Phaser.Tweens.BaseTween#setCallback + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.TweenCallbackTypes} type - The type of callback to set. One of: `onActive`, `onComplete`, `onLoop`, `onPause`, `onRepeat`, `onResume`, `onStart`, `onStop`, `onUpdate` or `onYoyo`. + * @param {function} callback - Your callback that will be invoked. + * @param {array} [params] - The parameters to pass to the callback. Pass an empty array if you don't want to define any, but do wish to set the scope. + * + * @return {this} This Tween instance. + */ + setCallback: function (type, callback, params) + { + if (params === undefined) { params = []; } + + if (this.callbacks.hasOwnProperty(type)) + { + this.callbacks[type] = { func: callback, params: params }; + } + + return this; + }, + + /** + * Sets this Tween state to PENDING. + * + * @method Phaser.Tweens.BaseTween#setPendingState + * @since 3.60.0 + */ + setPendingState: function () + { + this.state = TWEEN_CONST.PENDING; + }, + + /** + * Sets this Tween state to ACTIVE. + * + * @method Phaser.Tweens.BaseTween#setActiveState + * @since 3.60.0 + */ + setActiveState: function () + { + this.state = TWEEN_CONST.ACTIVE; + + this.hasStarted = false; + }, + + /** + * Sets this Tween state to LOOP_DELAY. + * + * @method Phaser.Tweens.BaseTween#setLoopDelayState + * @since 3.60.0 + */ + setLoopDelayState: function () + { + this.state = TWEEN_CONST.LOOP_DELAY; + }, + + /** + * Sets this Tween state to COMPLETE_DELAY. + * + * @method Phaser.Tweens.BaseTween#setCompleteDelayState + * @since 3.60.0 + */ + setCompleteDelayState: function () + { + this.state = TWEEN_CONST.COMPLETE_DELAY; + }, + + /** + * Sets this Tween state to START_DELAY. + * + * @method Phaser.Tweens.BaseTween#setStartDelayState + * @since 3.60.0 + */ + setStartDelayState: function () + { + this.state = TWEEN_CONST.START_DELAY; + + this.countdown = this.startDelay; + + this.hasStarted = false; + }, + + /** + * Sets this Tween state to PENDING_REMOVE. + * + * @method Phaser.Tweens.BaseTween#setPendingRemoveState + * @since 3.60.0 + */ + setPendingRemoveState: function () + { + this.state = TWEEN_CONST.PENDING_REMOVE; + }, + + /** + * Sets this Tween state to REMOVED. + * + * @method Phaser.Tweens.BaseTween#setRemovedState + * @since 3.60.0 + */ + setRemovedState: function () + { + this.state = TWEEN_CONST.REMOVED; + }, + + /** + * Sets this Tween state to FINISHED. + * + * @method Phaser.Tweens.BaseTween#setFinishedState + * @since 3.60.0 + */ + setFinishedState: function () + { + this.state = TWEEN_CONST.FINISHED; + }, + + /** + * Sets this Tween state to DESTROYED. + * + * @method Phaser.Tweens.BaseTween#setDestroyedState + * @since 3.60.0 + */ + setDestroyedState: function () + { + this.state = TWEEN_CONST.DESTROYED; + }, + + /** + * Returns `true` if this Tween has a _current_ state of PENDING, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isPending + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of PENDING, otherwise `false`. + */ + isPending: function () + { + return (this.state === TWEEN_CONST.PENDING); + }, + + /** + * Returns `true` if this Tween has a _current_ state of ACTIVE, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isActive + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of ACTIVE, otherwise `false`. + */ + isActive: function () + { + return (this.state === TWEEN_CONST.ACTIVE); + }, + + /** + * Returns `true` if this Tween has a _current_ state of LOOP_DELAY, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isLoopDelayed + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of LOOP_DELAY, otherwise `false`. + */ + isLoopDelayed: function () + { + return (this.state === TWEEN_CONST.LOOP_DELAY); + }, + + /** + * Returns `true` if this Tween has a _current_ state of COMPLETE_DELAY, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isCompleteDelayed + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of COMPLETE_DELAY, otherwise `false`. + */ + isCompleteDelayed: function () + { + return (this.state === TWEEN_CONST.COMPLETE_DELAY); + }, + + /** + * Returns `true` if this Tween has a _current_ state of START_DELAY, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isStartDelayed + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of START_DELAY, otherwise `false`. + */ + isStartDelayed: function () + { + return (this.state === TWEEN_CONST.START_DELAY); + }, + + /** + * Returns `true` if this Tween has a _current_ state of PENDING_REMOVE, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isPendingRemove + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of PENDING_REMOVE, otherwise `false`. + */ + isPendingRemove: function () + { + return (this.state === TWEEN_CONST.PENDING_REMOVE); + }, + + /** + * Returns `true` if this Tween has a _current_ state of REMOVED, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isRemoved + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of REMOVED, otherwise `false`. + */ + isRemoved: function () + { + return (this.state === TWEEN_CONST.REMOVED); + }, + + /** + * Returns `true` if this Tween has a _current_ state of FINISHED, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isFinished + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of FINISHED, otherwise `false`. + */ + isFinished: function () + { + return (this.state === TWEEN_CONST.FINISHED); + }, + + /** + * Returns `true` if this Tween has a _current_ state of DESTROYED, otherwise `false`. + * + * @method Phaser.Tweens.BaseTween#isDestroyed + * @since 3.60.0 + * + * @return {boolean} `true` if this Tween has a _current_ state of DESTROYED, otherwise `false`. + */ + isDestroyed: function () + { + return (this.state === TWEEN_CONST.DESTROYED); + }, + + /** + * Handles the destroy process of this Tween, clearing out the + * Tween Data and resetting the targets. A Tween that has been + * destroyed cannot ever be played or used again. + * + * @method Phaser.Tweens.BaseTween#destroy + * @since 3.60.0 + */ + destroy: function () + { + if (this.data) + { + this.data.forEach(function (tweenData) + { + tweenData.destroy(); + }); + } + + this.removeAllListeners(); + + this.callbacks = null; + this.data = null; + this.parent = null; + + this.setDestroyedState(); + } + +}); + +BaseTween.TYPES = [ + 'onActive', + 'onComplete', + 'onLoop', + 'onPause', + 'onRepeat', + 'onResume', + 'onStart', + 'onStop', + 'onUpdate', + 'onYoyo' +]; + +module.exports = BaseTween; + + +/***/ }), + +/***/ 95042: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Class = __webpack_require__(83419); +var Events = __webpack_require__(842); +var TWEEN_CONST = __webpack_require__(86353); + +/** + * @classdesc + * BaseTweenData is the class that the TweenData and TweenFrameData classes + * extend from. You should not typically instantiate this class directly, but instead + * use it to form your own tween data classes from, should you require it. + * + * Prior to Phaser 3.60 the TweenData was just an object, but was refactored to a class, + * to make it responsible for its own state and updating. + * + * @class BaseTweenData + * @memberof Phaser.Tweens + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The tween this TweenData instance belongs to. + * @param {number} targetIndex - The target index within the Tween targets array. + * @param {string} key - The property of the target to tween. + * @param {Phaser.Types.Tweens.GetEndCallback} getEnd - What the property will be at the END of the Tween. + * @param {Phaser.Types.Tweens.GetStartCallback} getStart - What the property will be at the START of the Tween. + * @param {?Phaser.Types.Tweens.GetActiveCallback} getActive - If not null, is invoked _immediately_ as soon as the TweenData is running, and is set on the target property. + * @param {function} ease - The ease function this tween uses. + * @param {function} delay - Function that returns the time in milliseconds before tween will start. + * @param {number} duration - The duration of the tween in milliseconds. + * @param {boolean} yoyo - Determines whether the tween should return back to its start value after hold has expired. + * @param {number} hold - Function that returns the time in milliseconds the tween will pause before repeating or returning to its starting value if yoyo is set to true. + * @param {number} repeat - Function that returns the number of times to repeat the tween. The tween will always run once regardless, so a repeat value of '1' will play the tween twice. + * @param {number} repeatDelay - Function that returns the time in milliseconds before the repeat will start. + * @param {boolean} flipX - Should toggleFlipX be called when yoyo or repeat happens? + * @param {boolean} flipY - Should toggleFlipY be called when yoyo or repeat happens? + * @param {?function} interpolation - The interpolation function to be used for arrays of data. Defaults to 'null'. + * @param {?number[]} interpolationData - The array of interpolation data to be set. Defaults to 'null'. + */ +var BaseTweenData = new Class({ + + initialize: + + function BaseTweenData (tween, targetIndex, delay, duration, yoyo, hold, repeat, repeatDelay, flipX, flipY) + { + /** + * A reference to the Tween that this TweenData instance belongs to. + * + * @name Phaser.Tweens.BaseTweenData#tween + * @type {Phaser.Tweens.Tween} + * @since 3.60.0 + */ + this.tween = tween; + + /** + * The index of the target within the Tween `targets` array. + * + * @name Phaser.Tweens.BaseTweenData#targetIndex + * @type {number} + * @since 3.60.0 + */ + this.targetIndex = targetIndex; + + /** + * The duration of the tween in milliseconds, excluding any time required + * for yoyo or repeats. A tween can never have a duration of zero, so this + * will be set to 0.01 if the value is incorrectly less than or equal to zero. + * + * @name Phaser.Tweens.BaseTweenData#duration + * @type {number} + * @since 3.60.0 + */ + this.duration = (duration <= 0) ? 0.01 : duration; + + /** + * The total calculated duration, in milliseconds, of this TweenData. + * Factoring in the duration, repeats, delays and yoyos. + * + * @name Phaser.Tweens.BaseTweenData#totalDuration + * @type {number} + * @since 3.60.0 + */ + this.totalDuration = 0; + + /** + * The time, in milliseconds, before this tween will start playing. + * + * This value is generated by the `getDelay` function. + * + * @name Phaser.Tweens.BaseTweenData#delay + * @type {number} + * @since 3.60.0 + */ + this.delay = 0; + + /** + * This function returns the value to be used for `TweenData.delay`. + * + * @name Phaser.Tweens.BaseTweenData#getDelay + * @type {function} + * @since 3.60.0 + */ + this.getDelay = delay; + + /** + * Will the Tween ease back to its starting values, after reaching the end + * and any `hold` value that may be set? + * + * @name Phaser.Tweens.BaseTweenData#yoyo + * @type {boolean} + * @since 3.60.0 + */ + this.yoyo = yoyo; + + /** + * The time, in milliseconds, before this tween will start a yoyo to repeat. + * + * @name Phaser.Tweens.BaseTweenData#hold + * @type {number} + * @since 3.60.0 + */ + this.hold = hold; + + /** + * The number of times this tween will repeat. + * + * The tween will always run once regardless of this value, + * so a repeat value of '1' will play the tween twice: I.e. the original + * play-through and then it repeats that once (1). + * + * If this value is set to -1 this tween will repeat forever. + * + * @name Phaser.Tweens.BaseTweenData#repeat + * @type {number} + * @since 3.60.0 + */ + this.repeat = repeat; + + /** + * The time, in milliseconds, before the repeat will start. + * + * @name Phaser.Tweens.BaseTweenData#repeatDelay + * @type {number} + * @since 3.60.0 + */ + this.repeatDelay = repeatDelay; + + /** + * How many repeats are left to run? + * + * @name Phaser.Tweens.BaseTweenData#repeatCounter + * @type {number} + * @since 3.60.0 + */ + this.repeatCounter = 0; + + /** + * If `true` this Tween will call `toggleFlipX` on the Tween target + * whenever it yoyo's or repeats. It will only be called if the target + * has a function matching this name, like most Phaser GameObjects do. + * + * @name Phaser.Tweens.BaseTweenData#flipX + * @type {boolean} + * @since 3.60.0 + */ + this.flipX = flipX; + + /** + * If `true` this Tween will call `toggleFlipY` on the Tween target + * whenever it yoyo's or repeats. It will only be called if the target + * has a function matching this name, like most Phaser GameObjects do. + * + * @name Phaser.Tweens.BaseTweenData#flipY + * @type {boolean} + * @since 3.60.0 + */ + this.flipY = flipY; + + /** + * A value between 0 and 1 holding the progress of this TweenData. + * + * @name Phaser.Tweens.BaseTweenData#progress + * @type {number} + * @since 3.60.0 + */ + this.progress = 0; + + /** + * The amount of time, in milliseconds, that has elapsed since this + * TweenData was made active. + * + * @name Phaser.Tweens.BaseTweenData#elapsed + * @type {number} + * @since 3.60.0 + */ + this.elapsed = 0; + + /** + * The state of this TweenData. + * + * @name Phaser.Tweens.BaseTweenData#state + * @type {Phaser.Tweens.StateType} + * @since 3.60.0 + */ + this.state = 0; + + /** + * Is this Tween Data currently waiting for a countdown to elapse, or not? + * + * @name Phaser.Tweens.BaseTweenData#isCountdown + * @type {boolean} + * @since 3.60.0 + */ + this.isCountdown = false; + }, + + /** + * Returns a reference to the target object belonging to this TweenData. + * + * @method Phaser.Tweens.BaseTweenData#getTarget + * @since 3.60.0 + * + * @return {object} The target object. Can be any JavaScript object, but is typically a Game Object. + */ + getTarget: function () + { + return this.tween.targets[this.targetIndex]; + }, + + /** + * Sets this TweenData's target object property to be the given value. + * + * @method Phaser.Tweens.BaseTweenData#setTargetValue + * @since 3.60.0 + * + * @param {number} [value] - The value to set on the target. If not given, sets it to the last `current` value. + */ + setTargetValue: function (value) + { + if (value === undefined) { value = this.current; } + + this.tween.targets[this.targetIndex][this.key] = value; + }, + + /** + * Sets this TweenData state to CREATED. + * + * @method Phaser.Tweens.BaseTweenData#setCreatedState + * @since 3.60.0 + */ + setCreatedState: function () + { + this.state = TWEEN_CONST.CREATED; + this.isCountdown = false; + }, + + /** + * Sets this TweenData state to DELAY. + * + * @method Phaser.Tweens.BaseTweenData#setDelayState + * @since 3.60.0 + */ + setDelayState: function () + { + this.state = TWEEN_CONST.DELAY; + this.isCountdown = true; + }, + + /** + * Sets this TweenData state to PENDING_RENDER. + * + * @method Phaser.Tweens.BaseTweenData#setPendingRenderState + * @since 3.60.0 + */ + setPendingRenderState: function () + { + this.state = TWEEN_CONST.PENDING_RENDER; + this.isCountdown = false; + }, + + /** + * Sets this TweenData state to PLAYING_FORWARD. + * + * @method Phaser.Tweens.BaseTweenData#setPlayingForwardState + * @since 3.60.0 + */ + setPlayingForwardState: function () + { + this.state = TWEEN_CONST.PLAYING_FORWARD; + this.isCountdown = false; + }, + + /** + * Sets this TweenData state to PLAYING_BACKWARD. + * + * @method Phaser.Tweens.BaseTweenData#setPlayingBackwardState + * @since 3.60.0 + */ + setPlayingBackwardState: function () + { + this.state = TWEEN_CONST.PLAYING_BACKWARD; + this.isCountdown = false; + }, + + /** + * Sets this TweenData state to HOLD_DELAY. + * + * @method Phaser.Tweens.BaseTweenData#setHoldState + * @since 3.60.0 + */ + setHoldState: function () + { + this.state = TWEEN_CONST.HOLD_DELAY; + this.isCountdown = true; + }, + + /** + * Sets this TweenData state to REPEAT_DELAY. + * + * @method Phaser.Tweens.BaseTweenData#setRepeatState + * @since 3.60.0 + */ + setRepeatState: function () + { + this.state = TWEEN_CONST.REPEAT_DELAY; + this.isCountdown = true; + }, + + /** + * Sets this TweenData state to COMPLETE. + * + * @method Phaser.Tweens.BaseTweenData#setCompleteState + * @since 3.60.0 + */ + setCompleteState: function () + { + this.state = TWEEN_CONST.COMPLETE; + this.isCountdown = false; + }, + + /** + * Returns `true` if this TweenData has a _current_ state of CREATED, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isCreated + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of CREATED, otherwise `false`. + */ + isCreated: function () + { + return (this.state === TWEEN_CONST.CREATED); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of DELAY, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isDelayed + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of DELAY, otherwise `false`. + */ + isDelayed: function () + { + return (this.state === TWEEN_CONST.DELAY); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of PENDING_RENDER, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isPendingRender + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of PENDING_RENDER, otherwise `false`. + */ + isPendingRender: function () + { + return (this.state === TWEEN_CONST.PENDING_RENDER); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of PLAYING_FORWARD, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isPlayingForward + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of PLAYING_FORWARD, otherwise `false`. + */ + isPlayingForward: function () + { + return (this.state === TWEEN_CONST.PLAYING_FORWARD); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of PLAYING_BACKWARD, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isPlayingBackward + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of PLAYING_BACKWARD, otherwise `false`. + */ + isPlayingBackward: function () + { + return (this.state === TWEEN_CONST.PLAYING_BACKWARD); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of HOLD_DELAY, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isHolding + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of HOLD_DELAY, otherwise `false`. + */ + isHolding: function () + { + return (this.state === TWEEN_CONST.HOLD_DELAY); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of REPEAT_DELAY, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isRepeating + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of REPEAT_DELAY, otherwise `false`. + */ + isRepeating: function () + { + return (this.state === TWEEN_CONST.REPEAT_DELAY); + }, + + /** + * Returns `true` if this TweenData has a _current_ state of COMPLETE, otherwise `false`. + * + * @method Phaser.Tweens.BaseTweenData#isComplete + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenData has a _current_ state of COMPLETE, otherwise `false`. + */ + isComplete: function () + { + return (this.state === TWEEN_CONST.COMPLETE); + }, + + /** + * Internal method used as part of the playback process that checks if this + * TweenData should yoyo, repeat, or has completed. + * + * @method Phaser.Tweens.BaseTweenData#setStateFromEnd + * @fires Phaser.Tweens.Events#TWEEN_REPEAT + * @fires Phaser.Tweens.Events#TWEEN_YOYO + * @since 3.60.0 + * + * @param {number} diff - Any extra time that needs to be accounted for in the elapsed and progress values. + */ + setStateFromEnd: function (diff) + { + if (this.yoyo) + { + this.onRepeat(diff, true, true); + } + else if (this.repeatCounter > 0) + { + this.onRepeat(diff, true, false); + } + else + { + this.setCompleteState(); + } + }, + + /** + * Internal method used as part of the playback process that checks if this + * TweenData should repeat or has completed. + * + * @method Phaser.Tweens.BaseTweenData#setStateFromStart + * @fires Phaser.Tweens.Events#TWEEN_REPEAT + * @since 3.60.0 + * + * @param {number} diff - Any extra time that needs to be accounted for in the elapsed and progress values. + */ + setStateFromStart: function (diff) + { + if (this.repeatCounter > 0) + { + this.onRepeat(diff, false); + } + else + { + this.setCompleteState(); + } + }, + + /** + * Internal method that resets this Tween Data entirely, including the progress and elapsed values. + * + * Called automatically by the parent Tween. Should not be called directly. + * + * @method Phaser.Tweens.BaseTweenData#reset + * @since 3.60.0 + */ + reset: function () + { + var tween = this.tween; + var totalTargets = tween.totalTargets; + + var targetIndex = this.targetIndex; + var target = tween.targets[targetIndex]; + var key = this.key; + + this.progress = 0; + this.elapsed = 0; + + // Function signature: target, key, value, index, total, tween + + this.delay = this.getDelay(target, key, 0, targetIndex, totalTargets, tween); + + this.repeatCounter = (this.repeat === -1) ? TWEEN_CONST.MAX : this.repeat; + + this.setPendingRenderState(); + + // calcDuration: + + // Set t1 (duration + hold + yoyo) + var t1 = this.duration + this.hold; + + if (this.yoyo) + { + t1 += this.duration; + } + + // Set t2 (repeatDelay + duration + hold + yoyo) + var t2 = t1 + this.repeatDelay; + + // Total Duration + this.totalDuration = this.delay + t1; + + if (this.repeat === -1) + { + this.totalDuration += (t2 * TWEEN_CONST.MAX); + tween.isInfinite = true; + } + else if (this.repeat > 0) + { + this.totalDuration += (t2 * this.repeat); + } + + if (this.totalDuration > tween.duration) + { + // Set the longest duration in the parent Tween + tween.duration = this.totalDuration; + } + + if (this.delay < tween.startDelay) + { + tween.startDelay = this.delay; + } + + if (this.delay > 0) + { + this.elapsed = this.delay; + + this.setDelayState(); + } + }, + + /** + * Internal method that handles repeating or yoyo'ing this TweenData. + * + * Called automatically by `setStateFromStart` and `setStateFromEnd`. + * + * @method Phaser.Tweens.BaseTweenData#onRepeat + * @fires Phaser.Tweens.Events#TWEEN_REPEAT + * @fires Phaser.Tweens.Events#TWEEN_YOYO + * @since 3.60.0 + * + * @param {number} diff - Any extra time that needs to be accounted for in the elapsed and progress values. + * @param {boolean} setStart - Set the TweenData start values? + * @param {boolean} isYoyo - Is this call a Yoyo check? + */ + onRepeat: function (diff, setStart, isYoyo) + { + var tween = this.tween; + var totalTargets = tween.totalTargets; + + var targetIndex = this.targetIndex; + var target = tween.targets[targetIndex]; + var key = this.key; + + var isTweenData = (key !== 'texture'); + + // Account for any extra time we got from the previous frame + this.elapsed = diff; + this.progress = diff / this.duration; + + if (this.flipX) + { + target.toggleFlipX(); + } + + if (this.flipY) + { + target.toggleFlipY(); + } + + if (isTweenData && (setStart || isYoyo)) + { + this.start = this.getStartValue(target, key, this.start, targetIndex, totalTargets, tween); + } + + if (isYoyo) + { + this.setPlayingBackwardState(); + + this.dispatchEvent(Events.TWEEN_YOYO, 'onYoyo'); + + return; + } + + this.repeatCounter--; + + // Custom + if (isTweenData) + { + this.end = this.getEndValue(target, key, this.start, targetIndex, totalTargets, tween); + } + + // Delay? + if (this.repeatDelay > 0) + { + this.elapsed = this.repeatDelay - diff; + + if (isTweenData) + { + this.current = this.start; + + target[key] = this.current; + } + + this.setRepeatState(); + } + else + { + this.setPlayingForwardState(); + + this.dispatchEvent(Events.TWEEN_REPEAT, 'onRepeat'); + } + }, + + /** + * Immediately destroys this TweenData, nulling of all its references. + * + * @method Phaser.Tweens.BaseTweenData#destroy + * @since 3.60.0 + */ + destroy: function () + { + this.tween = null; + this.getDelay = null; + this.setCompleteState(); + } + +}); + +module.exports = BaseTweenData; + + +/***/ }), + +/***/ 69902: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @typedef {object} Phaser.Types.Tweens.TweenConfigDefaults + * @since 3.0.0 + * + * @property {(object|object[])} targets - The object, or an array of objects, to run the tween on. + * @property {number} [delay=0] - The number of milliseconds to delay before the tween will start. + * @property {number} [duration=1000] - The duration of the tween in milliseconds. + * @property {string} [ease='Power0'] - The easing equation to use for the tween. + * @property {array} [easeParams] - Optional easing parameters. + * @property {number} [hold=0] - The number of milliseconds to hold the tween for before yoyo'ing. + * @property {number} [repeat=0] - The number of times to repeat the tween. + * @property {number} [repeatDelay=0] - The number of milliseconds to pause before a tween will repeat. + * @property {boolean} [yoyo=false] - Should the tween complete, then reverse the values incrementally to get back to the starting tween values? The reverse tweening will also take `duration` milliseconds to complete. + * @property {boolean} [flipX=false] - Horizontally flip the target of the Tween when it completes (before it yoyos, if set to do so). Only works for targets that support the `flipX` property. + * @property {boolean} [flipY=false] - Vertically flip the target of the Tween when it completes (before it yoyos, if set to do so). Only works for targets that support the `flipY` property. + * @property {boolean} [persist=false] - Retain the tween within the Tween Manager, even after playback completes? + * @property {function} [interpolation=null] - The interpolation function to use for array-based tween values. + */ + +var TWEEN_DEFAULTS = { + targets: null, + delay: 0, + duration: 1000, + ease: 'Power0', + easeParams: null, + hold: 0, + repeat: 0, + repeatDelay: 0, + yoyo: false, + flipX: false, + flipY: false, + persist: false, + interpolation: null +}; + +module.exports = TWEEN_DEFAULTS; + + +/***/ }), + +/***/ 81076: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// RESERVED properties that a Tween config object uses + +// completeDelay: The time the tween will wait before the onComplete event is dispatched once it has completed +// delay: The time the tween will wait before it first starts +// duration: The duration of the tween +// ease: The ease function used by the tween +// easeParams: The parameters to go with the ease function (if any) +// flipX: flip X the GameObject on tween end +// flipY: flip Y the GameObject on tween end +// hold: The time the tween will pause before running a yoyo +// loop: The time the tween will pause before starting either a yoyo or returning to the start for a repeat +// loopDelay: +// paused: Does the tween start in a paused state, or playing? +// props: The properties being tweened by the tween +// repeat: The number of times the tween will repeat itself (a value of 1 means the tween will play twice, as it repeated once) +// repeatDelay: The time the tween will pause for before starting a repeat. The tween holds in the start state. +// targets: The targets the tween is updating. +// yoyo: boolean - Does the tween reverse itself (yoyo) when it reaches the end? + +module.exports = [ + 'callbackScope', + 'completeDelay', + 'delay', + 'duration', + 'ease', + 'easeParams', + 'flipX', + 'flipY', + 'hold', + 'interpolation', + 'loop', + 'loopDelay', + 'onActive', + 'onActiveParams', + 'onComplete', + 'onCompleteParams', + 'onLoop', + 'onLoopParams', + 'onPause', + 'onPauseParams', + 'onRepeat', + 'onRepeatParams', + 'onResume', + 'onResumeParams', + 'onStart', + 'onStartParams', + 'onStop', + 'onStopParams', + 'onUpdate', + 'onUpdateParams', + 'onYoyo', + 'onYoyoParams', + 'paused', + 'persist', + 'props', + 'repeat', + 'repeatDelay', + 'targets', + 'yoyo' +]; + + +/***/ }), + +/***/ 8462: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseTween = __webpack_require__(70402); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(842); +var GameObjectCreator = __webpack_require__(44603); +var GameObjectFactory = __webpack_require__(39429); +var MATH_CONST = __webpack_require__(36383); +var TWEEN_CONST = __webpack_require__(86353); +var TweenData = __webpack_require__(48177); +var TweenFrameData = __webpack_require__(42220); + +/** + * @classdesc + * A Tween is able to manipulate the properties of one or more objects to any given value, based + * on a duration and type of ease. They are rarely instantiated directly and instead should be + * created via the TweenManager. + * + * Please note that a Tween will not manipulate any property that begins with an underscore. + * + * @class Tween + * @memberof Phaser.Tweens + * @extends Phaser.Tweens.BaseTween + * @constructor + * @since 3.0.0 + * + * @param {Phaser.Tweens.TweenManager} parent - A reference to the Tween Manager that owns this Tween. + * @param {object[]} targets - An array of targets to be tweened. This array should not be manipulated outside of this Tween. + */ +var Tween = new Class({ + + Extends: BaseTween, + + initialize: + + function Tween (parent, targets) + { + BaseTween.call(this, parent); + + /** + * An array of references to the target/s this Tween is operating on. + * + * This array should not be manipulated outside of this Tween. + * + * @name Phaser.Tweens.Tween#targets + * @type {object[]} + * @since 3.0.0 + */ + this.targets = targets; + + /** + * Cached target total. + * + * Used internally and should be treated as read-only. + * + * This is not necessarily the same as the data total. + * + * @name Phaser.Tweens.Tween#totalTargets + * @type {number} + * @since 3.0.0 + */ + this.totalTargets = targets.length; + + /** + * Is this Tween currently seeking? + * + * This boolean is toggled in the `Tween.seek` method. + * + * When a tween is seeking, by default it will not dispatch any events or callbacks. + * + * @name Phaser.Tweens.Tween#isSeeking + * @type {boolean} + * @readonly + * @since 3.19.0 + */ + this.isSeeking = false; + + /** + * Does this Tween loop or repeat infinitely? + * + * @name Phaser.Tweens.Tween#isInfinite + * @type {boolean} + * @readonly + * @since 3.60.0 + */ + this.isInfinite = false; + + /** + * Elapsed time in milliseconds of this run through of the Tween. + * + * @name Phaser.Tweens.Tween#elapsed + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.elapsed = 0; + + /** + * Total elapsed time in milliseconds of the entire Tween, including looping. + * + * @name Phaser.Tweens.Tween#totalElapsed + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.totalElapsed = 0; + + /** + * Time in milliseconds for the whole Tween to play through once, excluding loop amounts and loop delays. + * + * This value is set in the `Tween.initTweenData` method and is zero before that point. + * + * @name Phaser.Tweens.Tween#duration + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.duration = 0; + + /** + * Value between 0 and 1. The amount of progress through the Tween, excluding loops. + * + * @name Phaser.Tweens.Tween#progress + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.progress = 0; + + /** + * Time in milliseconds it takes for the Tween to complete a full playthrough (including looping) + * + * For an infinite Tween, this value is a very large integer. + * + * @name Phaser.Tweens.Tween#totalDuration + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.totalDuration = 0; + + /** + * The amount of progress that has been made through the entire Tween, including looping. + * + * A value between 0 and 1. + * + * @name Phaser.Tweens.Tween#totalProgress + * @type {number} + * @default 0 + * @since 3.60.0 + */ + this.totalProgress = 0; + + /** + * Is this Tween a Number Tween? Number Tweens are a special kind of tween that don't have a target. + * + * @name Phaser.Tweens.Tween#isNumberTween + * @type {boolean} + * @default false + * @since 3.88.0 + */ + this.isNumberTween = false; + }, + + /** + * Adds a new TweenData to this Tween. Typically, this method is called + * automatically by the TweenBuilder, however you can also invoke it + * yourself. + * + * @method Phaser.Tweens.Tween#add + * @since 3.60.0 + * + * @param {number} targetIndex - The target index within the Tween targets array. + * @param {string} key - The property of the target to tween. + * @param {Phaser.Types.Tweens.GetEndCallback} getEnd - What the property will be at the END of the Tween. + * @param {Phaser.Types.Tweens.GetStartCallback} getStart - What the property will be at the START of the Tween. + * @param {?Phaser.Types.Tweens.GetActiveCallback} getActive - If not null, is invoked _immediately_ as soon as the TweenData is running, and is set on the target property. + * @param {function} ease - The ease function this tween uses. + * @param {function} delay - Function that returns the time in milliseconds before tween will start. + * @param {number} duration - The duration of the tween in milliseconds. + * @param {boolean} yoyo - Determines whether the tween should return back to its start value after hold has expired. + * @param {number} hold - Function that returns the time in milliseconds the tween will pause before repeating or returning to its starting value if yoyo is set to true. + * @param {number} repeat - Function that returns the number of times to repeat the tween. The tween will always run once regardless, so a repeat value of '1' will play the tween twice. + * @param {number} repeatDelay - Function that returns the time in milliseconds before the repeat will start. + * @param {boolean} flipX - Should toggleFlipX be called when yoyo or repeat happens? + * @param {boolean} flipY - Should toggleFlipY be called when yoyo or repeat happens? + * @param {?function} interpolation - The interpolation function to be used for arrays of data. Defaults to 'null'. + * @param {?number[]} interpolationData - The array of interpolation data to be set. Defaults to 'null'. + * + * @return {Phaser.Tweens.TweenData} The TweenData instance that was added. + */ + add: function (targetIndex, key, getEnd, getStart, getActive, ease, delay, duration, yoyo, hold, repeat, repeatDelay, flipX, flipY, interpolation, interpolationData) + { + var tweenData = new TweenData(this, targetIndex, key, getEnd, getStart, getActive, ease, delay, duration, yoyo, hold, repeat, repeatDelay, flipX, flipY, interpolation, interpolationData); + + this.totalData = this.data.push(tweenData); + + return tweenData; + }, + + /** + * Adds a new TweenFrameData to this Tween. Typically, this method is called + * automatically by the TweenBuilder, however you can also invoke it + * yourself. + * + * @method Phaser.Tweens.Tween#addFrame + * @since 3.60.0 + * + * @param {number} targetIndex - The target index within the Tween targets array. + * @param {string} texture - The texture to set on the target at the end of the tween. + * @param {string|number} frame - The texture frame to set on the target at the end of the tween. + * @param {function} delay - Function that returns the time in milliseconds before tween will start. + * @param {number} duration - The duration of the tween in milliseconds. + * @param {number} hold - Function that returns the time in milliseconds the tween will pause before repeating or returning to its starting value if yoyo is set to true. + * @param {number} repeat - Function that returns the number of times to repeat the tween. The tween will always run once regardless, so a repeat value of '1' will play the tween twice. + * @param {number} repeatDelay - Function that returns the time in milliseconds before the repeat will start. + * @param {boolean} flipX - Should toggleFlipX be called when yoyo or repeat happens? + * @param {boolean} flipY - Should toggleFlipY be called when yoyo or repeat happens? + * + * @return {Phaser.Tweens.TweenFrameData} The TweenFrameData instance that was added. + */ + addFrame: function (targetIndex, texture, frame, delay, duration, hold, repeat, repeatDelay, flipX, flipY) + { + var tweenData = new TweenFrameData(this, targetIndex, texture, frame, delay, duration, hold, repeat, repeatDelay, flipX, flipY); + + this.totalData = this.data.push(tweenData); + + return tweenData; + }, + + /** + * Returns the current value of the specified Tween Data. + * + * If this Tween has been destroyed, it will return `null`. + * + * @method Phaser.Tweens.Tween#getValue + * @since 3.0.0 + * + * @param {number} [index=0] - The Tween Data to return the value from. + * + * @return {number} The value of the requested Tween Data, or `null` if this Tween has been destroyed. + */ + getValue: function (index) + { + if (index === undefined) { index = 0; } + + var value = null; + + if (this.data) + { + value = this.data[index].current; + } + + return value; + }, + + /** + * See if this Tween is currently acting upon the given target. + * + * @method Phaser.Tweens.Tween#hasTarget + * @since 3.0.0 + * + * @param {object} target - The target to check against this Tween. + * + * @return {boolean} `true` if the given target is a target of this Tween, otherwise `false`. + */ + hasTarget: function (target) + { + return (this.targets && this.targets.indexOf(target) !== -1); + }, + + /** + * Updates the 'end' value of the given property across all matching targets, as long + * as this Tween is currently playing (either forwards or backwards). + * + * Calling this does not adjust the duration of the Tween, or the current progress. + * + * You can optionally tell it to set the 'start' value to be the current value. + * + * If this Tween is in any other state other than playing then calling this method has no effect. + * + * Additionally, if the Tween repeats, is reset, or is seeked, it will revert to the original + * starting and ending values. + * + * @method Phaser.Tweens.Tween#updateTo + * @since 3.0.0 + * + * @param {string} key - The property to set the new value for. You cannot update the 'texture' property via this method. + * @param {number} value - The new value of the property. + * @param {boolean} [startToCurrent=false] - Should this change set the start value to be the current value? + * + * @return {this} This Tween instance. + */ + updateTo: function (key, value, startToCurrent) + { + if (startToCurrent === undefined) { startToCurrent = false; } + + if (key !== 'texture') + { + for (var i = 0; i < this.totalData; i++) + { + var tweenData = this.data[i]; + + if (tweenData.key === key && (tweenData.isPlayingForward() || tweenData.isPlayingBackward())) + { + tweenData.end = value; + + if (startToCurrent) + { + tweenData.start = tweenData.current; + } + } + } + } + + return this; + }, + + /** + * Restarts the Tween from the beginning. + * + * If the Tween has already finished and been destroyed, restarting it will throw an error. + * + * If you wish to restart the Tween from a specific point, use the `Tween.seek` method instead. + * + * @method Phaser.Tweens.Tween#restart + * @since 3.0.0 + * + * @return {this} This Tween instance. + */ + restart: function () + { + switch (this.state) + { + case TWEEN_CONST.REMOVED: + case TWEEN_CONST.FINISHED: + this.seek(); + this.parent.makeActive(this); + break; + + case TWEEN_CONST.PENDING: + case TWEEN_CONST.PENDING_REMOVE: + this.parent.reset(this); + break; + + case TWEEN_CONST.DESTROYED: + console.warn('Cannot restart destroyed Tween', this); + break; + + default: + this.seek(); + break; + } + + this.paused = false; + this.hasStarted = false; + + return this; + }, + + /** + * Internal method that advances to the next state of the Tween during playback. + * + * @method Phaser.Tweens.Tween#nextState + * @fires Phaser.Tweens.Events#TWEEN_COMPLETE + * @fires Phaser.Tweens.Events#TWEEN_LOOP + * @since 3.0.0 + * + * @return {boolean} `true` if this Tween has completed, otherwise `false`. + */ + nextState: function () + { + if (this.loopCounter > 0) + { + this.elapsed = 0; + this.progress = 0; + this.loopCounter--; + + this.initTweenData(true); + + if (this.loopDelay > 0) + { + this.countdown = this.loopDelay; + + this.setLoopDelayState(); + } + else + { + this.setActiveState(); + + this.dispatchEvent(Events.TWEEN_LOOP, 'onLoop'); + } + } + else if (this.completeDelay > 0) + { + this.countdown = this.completeDelay; + + this.setCompleteDelayState(); + } + else + { + this.onCompleteHandler(); + + return true; + } + + return false; + }, + + /** + * Internal method that handles this tween completing and starting + * the next tween in the chain, if any. + * + * @method Phaser.Tweens.Tween#onCompleteHandler + * @since 3.60.0 + */ + onCompleteHandler: function () + { + this.progress = 1; + this.totalProgress = 1; + + BaseTween.prototype.onCompleteHandler.call(this); + }, + + /** + * Starts a Tween playing. + * + * You only need to call this method if you have configured the tween to be paused on creation. + * + * If the Tween is already playing, calling this method again will have no effect. If you wish to + * restart the Tween, use `Tween.restart` instead. + * + * Calling this method after the Tween has completed will start the Tween playing again from the beginning. + * This is the same as calling `Tween.seek(0)` and then `Tween.play()`. + * + * @method Phaser.Tweens.Tween#play + * @since 3.0.0 + * + * @return {this} This Tween instance. + */ + play: function () + { + if (this.isDestroyed()) + { + console.warn('Cannot play destroyed Tween', this); + + return this; + } + + if (this.isPendingRemove() || this.isFinished()) + { + this.seek(); + } + + this.paused = false; + + this.setActiveState(); + + return this; + }, + + /** + * Seeks to a specific point in the Tween. + * + * The given amount is a value in milliseconds that represents how far into the Tween + * you wish to seek, based on the start of the Tween. + * + * Note that the seek amount takes the entire duration of the Tween into account, including delays, loops and repeats. + * For example, a Tween that lasts for 2 seconds, but that loops 3 times, would have a total duration of 6 seconds, + * so seeking to 3000 ms would seek to the Tweens half-way point based on its _entire_ duration. + * + * Prior to Phaser 3.60 this value was given as a number between 0 and 1 and didn't + * work for Tweens had an infinite repeat. This new method works for all Tweens. + * + * Seeking works by resetting the Tween to its initial values and then iterating through the Tween at `delta` + * jumps per step. The longer the Tween, the longer this can take. If you need more precision you can + * reduce the delta value. If you need a faster seek, you can increase it. When the Tween is + * reset it will refresh the starting and ending values. If these are coming from a dynamic function, + * or a random array, it will be called for each seek. + * + * While seeking the Tween will _not_ emit any of its events or callbacks unless + * the 3rd parameter is set to `true`. + * + * If this Tween is paused, seeking will not change this fact. It will advance the Tween + * to the desired point and then pause it again. + * + * @method Phaser.Tweens.Tween#seek + * @since 3.0.0 + * + * @param {number} [amount=0] - The number of milliseconds to seek into the Tween from the beginning. + * @param {number} [delta=16.6] - The size of each step when seeking through the Tween. A higher value completes faster but at the cost of less precision. + * @param {boolean} [emit=false] - While seeking, should the Tween emit any of its events or callbacks? The default is 'false', i.e. to seek silently. + * + * @return {this} This Tween instance. + */ + seek: function (amount, delta, emit) + { + if (amount === undefined) { amount = 0; } + if (delta === undefined) { delta = 16.6; } + if (emit === undefined) { emit = false; } + + if (this.isDestroyed()) + { + console.warn('Cannot seek destroyed Tween', this); + + return this; + } + + if (!emit) + { + this.isSeeking = true; + } + + this.reset(true); + + this.initTweenData(true); + + this.setActiveState(); + + this.dispatchEvent(Events.TWEEN_ACTIVE, 'onActive'); + + var isPaused = this.paused; + + this.paused = false; + + if (amount > 0) + { + var iterations = Math.floor(amount / delta); + var remainder = amount - (iterations * delta); + + for (var i = 0; i < iterations; i++) + { + this.update(delta); + } + + if (remainder > 0) + { + this.update(remainder); + } + } + + this.paused = isPaused; + + this.isSeeking = false; + + return this; + }, + + /** + * Initialises all of the Tween Data and Tween values. + * + * This is called automatically and should not typically be invoked directly. + * + * @method Phaser.Tweens.Tween#initTweenData + * @since 3.60.0 + * + * @param {boolean} [isSeeking=false] - Is the Tween Data being reset as part of a seek? + */ + initTweenData: function (isSeeking) + { + if (isSeeking === undefined) { isSeeking = false; } + + // These two values are updated directly during TweenData.reset: + this.duration = 0; + this.startDelay = MATH_CONST.MAX_SAFE_INTEGER; + + var data = this.data; + + for (var i = 0; i < this.totalData; i++) + { + data[i].reset(isSeeking); + } + + // Clamp duration to ensure we never divide by zero + this.duration = Math.max(this.duration, 0.01); + + var duration = this.duration; + var completeDelay = this.completeDelay; + var loopCounter = this.loopCounter; + var loopDelay = this.loopDelay; + + if (loopCounter > 0) + { + this.totalDuration = duration + completeDelay + ((duration + loopDelay) * loopCounter); + } + else + { + this.totalDuration = duration + completeDelay; + } + }, + + /** + * Resets this Tween ready for another play-through. + * + * This is called automatically from the Tween Manager, or from the parent TweenChain, + * and should not typically be invoked directly. + * + * If you wish to restart this Tween, use the `Tween.restart` or `Tween.seek` methods instead. + * + * @method Phaser.Tweens.Tween#reset + * @fires Phaser.Tweens.Events#TWEEN_ACTIVE + * @since 3.60.0 + * + * @param {boolean} [skipInit=false] - Skip resetting the TweenData and Active State? + * + * @return {this} This Tween instance. + */ + reset: function (skipInit) + { + if (skipInit === undefined) { skipInit = false; } + + this.elapsed = 0; + this.totalElapsed = 0; + this.progress = 0; + this.totalProgress = 0; + this.loopCounter = this.loop; + + if (this.loop === -1) + { + this.isInfinite = true; + this.loopCounter = TWEEN_CONST.MAX; + } + + if (!skipInit) + { + this.initTweenData(); + + this.setActiveState(); + + this.dispatchEvent(Events.TWEEN_ACTIVE, 'onActive'); + } + + return this; + }, + + /** + * Internal method that advances the Tween based on the time values. + * + * @method Phaser.Tweens.Tween#update + * @fires Phaser.Tweens.Events#TWEEN_COMPLETE + * @fires Phaser.Tweens.Events#TWEEN_LOOP + * @fires Phaser.Tweens.Events#TWEEN_START + * @since 3.0.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + * + * @return {boolean} Returns `true` if this Tween has finished and should be removed from the Tween Manager, otherwise returns `false`. + */ + update: function (delta) + { + if (this.isPendingRemove() || this.isDestroyed()) + { + if (this.persist) + { + this.setFinishedState(); + + return false; + } + + return true; + } + else if (this.paused || this.isFinished()) + { + return false; + } + + delta *= this.timeScale * this.parent.timeScale; + + if (this.isLoopDelayed()) + { + this.updateLoopCountdown(delta); + + return false; + } + else if (this.isCompleteDelayed()) + { + this.updateCompleteDelay(delta); + + return false; + } + else if (!this.hasStarted) + { + this.startDelay -= delta; + + if (this.startDelay <= 0) + { + this.hasStarted = true; + + this.dispatchEvent(Events.TWEEN_START, 'onStart'); + + // Reset the delta so we always start progress from zero + delta = 0; + } + } + + var stillRunning = false; + + if (this.isActive()) + { + var data = this.data; + + for (var i = 0; i < this.totalData; i++) + { + if (data[i].update(delta)) + { + stillRunning = true; + } + } + } + + this.elapsed += delta; + this.progress = Math.min(this.elapsed / this.duration, 1); + + this.totalElapsed += delta; + this.totalProgress = Math.min(this.totalElapsed / this.totalDuration, 1); + + // Anything still running? If not, we're done + if (!stillRunning) + { + // This calls onCompleteHandler if this tween is over + this.nextState(); + } + + // if nextState called onCompleteHandler then we're ready to be removed, unless we persist + var remove = this.isPendingRemove(); + + if (remove && this.persist) + { + this.setFinishedState(); + + remove = false; + } + + return remove; + }, + + /** + * Moves this Tween forward by the given amount of milliseconds. + * + * It will only advance through the current loop of the Tween. For example, if the + * Tween is set to repeat or yoyo, it can only fast forward through a single + * section of the sequence. Use `Tween.seek` for more complex playhead control. + * + * If the Tween is paused or has already finished, calling this will have no effect. + * + * @method Phaser.Tweens.Tween#forward + * @since 3.60.0 + * + * @param {number} ms - The number of milliseconds to advance this Tween by. + * + * @return {this} This Tween instance. + */ + forward: function (ms) + { + this.update(ms); + + return this; + }, + + /** + * Moves this Tween backward by the given amount of milliseconds. + * + * It will only rewind through the current loop of the Tween. For example, if the + * Tween is set to repeat or yoyo, it can only fast forward through a single + * section of the sequence. Use `Tween.seek` for more complex playhead control. + * + * If the Tween is paused or has already finished, calling this will have no effect. + * + * @method Phaser.Tweens.Tween#rewind + * @since 3.60.0 + * + * @param {number} ms - The number of milliseconds to rewind this Tween by. + * + * @return {this} This Tween instance. + */ + rewind: function (ms) + { + this.update(-ms); + + return this; + }, + + /** + * Internal method that will emit a Tween based Event and invoke the given callback. + * + * @method Phaser.Tweens.Tween#dispatchEvent + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.Event} event - The Event to be dispatched. + * @param {Phaser.Types.Tweens.TweenCallbackTypes} [callback] - The name of the callback to be invoked. Can be `null` or `undefined` to skip invocation. + */ + dispatchEvent: function (event, callback) + { + if (!this.isSeeking) + { + this.emit(event, this, this.targets); + + if (!this.callbacks) + { + return; + } + + var handler = this.callbacks[callback]; + + if (handler) + { + handler.func.apply(this.callbackScope, [ this, this.targets ].concat(handler.params)); + } + } + }, + + /** + * Handles the destroy process of this Tween, clearing out the + * Tween Data and resetting the targets. A Tween that has been + * destroyed cannot ever be played or used again. + * + * @method Phaser.Tweens.Tween#destroy + * @since 3.60.0 + */ + destroy: function () + { + BaseTween.prototype.destroy.call(this); + + this.targets = null; + } + +}); + +/** + * Creates a new Tween object. + * + * Note: This method will only be available if Tweens have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#tween + * @since 3.0.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig|Phaser.Types.Tweens.TweenChainBuilderConfig|Phaser.Tweens.Tween|Phaser.Tweens.TweenChain} config - A Tween Configuration object, or a Tween or TweenChain instance. + * + * @return {Phaser.Tweens.Tween} The Tween that was created. + */ +GameObjectFactory.register('tween', function (config) +{ + return this.scene.sys.tweens.add(config); +}); + +/** + * Creates a new Tween object and returns it. + * + * Note: This method will only be available if Tweens have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#tween + * @since 3.0.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig|Phaser.Types.Tweens.TweenChainBuilderConfig|Phaser.Tweens.Tween|Phaser.Tweens.TweenChain} config - A Tween Configuration object, or a Tween or TweenChain instance. + * + * @return {Phaser.Tweens.Tween} The Tween that was created. + */ +GameObjectCreator.register('tween', function (config) +{ + return this.scene.sys.tweens.create(config); +}); + +module.exports = Tween; + + +/***/ }), + +/***/ 43960: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var ArrayRemove = __webpack_require__(72905); +var BaseTween = __webpack_require__(70402); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(842); +var GameObjectCreator = __webpack_require__(44603); +var GameObjectFactory = __webpack_require__(39429); +var TWEEN_CONST = __webpack_require__(86353); + +/** + * @classdesc + * A TweenChain is a special type of Tween that allows you to create a sequence of Tweens, chained to one-another, + * and add them to the Tween Manager. + * + * The tweens are played in order, from start to finish. You can optionally set the chain + * to repeat as many times as you like. Once the chain has finished playing, or repeating if set, + * all tweens in the chain will be destroyed automatically. To override this, set the 'persist' + * argument to 'true'. + * + * Playback will start immediately unless the _first_ Tween has been configured to be paused. + * + * Please note that Tweens will not manipulate any target property that begins with an underscore. + * + * @class TweenChain + * @memberof Phaser.Tweens + * @extends Phaser.Tweens.BaseTween + * @constructor + * @since 3.60.0 + * + * @param {(Phaser.Tweens.TweenManager|Phaser.Tweens.TweenChain)} parent - A reference to the Tween Manager, or TweenChain, that owns this TweenChain. + */ +var TweenChain = new Class({ + + Extends: BaseTween, + + initialize: + + function TweenChain (parent) + { + BaseTween.call(this, parent); + + /** + * A reference to the Tween that this TweenChain is currently playing. + * + * @name Phaser.Tweens.TweenChain#currentTween + * @type {Phaser.Tweens.Tween} + * @since 3.60.0 + */ + this.currentTween = null; + + /** + * A reference to the data array index of the currently playing tween. + * + * @name Phaser.Tweens.TweenChain#currentIndex + * @type {number} + * @since 3.60.0 + */ + this.currentIndex = 0; + }, + + /** + * Prepares this TweenChain for playback. + * + * Called automatically by the TweenManager. Should not be called directly. + * + * @method Phaser.Tweens.TweenChain#init + * @fires Phaser.Tweens.Events#TWEEN_ACTIVE + * @since 3.60.0 + * + * @return {this} This TweenChain instance. + */ + init: function () + { + this.loopCounter = (this.loop === -1) ? TWEEN_CONST.MAX : this.loop; + + this.setCurrentTween(0); + + if (this.startDelay > 0 && !this.isStartDelayed()) + { + this.setStartDelayState(); + } + else + { + this.setActiveState(); + } + + return this; + }, + + /** + * Create a sequence of Tweens, chained to one-another, and add them to this Tween Manager. + * + * The tweens are played in order, from start to finish. You can optionally set the chain + * to repeat as many times as you like. Once the chain has finished playing, or repeating if set, + * all tweens in the chain will be destroyed automatically. To override this, set the 'persist' + * argument to 'true'. + * + * Playback will start immediately unless the _first_ Tween has been configured to be paused. + * + * Please note that Tweens will not manipulate any target property that begins with an underscore. + * + * @method Phaser.Tweens.TweenChain#add + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig[]|object[]} tweens - An array of Tween configuration objects for the Tweens in this chain. + * + * @return {this} This TweenChain instance. + */ + add: function (tweens) + { + var newTweens = this.parent.create(tweens); + + if (!Array.isArray(newTweens)) + { + newTweens = [ newTweens ]; + } + + var data = this.data; + + for (var i = 0; i < newTweens.length; i++) + { + var tween = newTweens[i]; + + tween.parent = this; + + data.push(tween.reset()); + } + + this.totalData = data.length; + + return this; + }, + + /** + * Removes the given Tween from this Tween Chain. + * + * The removed tween is _not_ destroyed. It is just removed from this Tween Chain. + * + * If the given Tween is currently playing then the chain will automatically move + * to the next tween in the chain. If there are no more tweens, this chain will complete. + * + * @method Phaser.Tweens.TweenChain#remove + * @since 3.60.0 + * @override + * + * @param {Phaser.Tweens.Tween} tween - The Tween to be removed. + * + * @return {this} This Tween Chain instance. + */ + remove: function (tween) + { + // Remove it immediately + ArrayRemove(this.data, tween); + + tween.setRemovedState(); + + if (tween === this.currentTween) + { + this.nextTween(); + } + + this.totalData = this.data.length; + + return this; + }, + + /** + * See if any of the tweens in this Tween Chain is currently acting upon the given target. + * + * @method Phaser.Tweens.TweenChain#hasTarget + * @since 3.60.0 + * + * @param {object} target - The target to check against this TweenChain. + * + * @return {boolean} `true` if the given target is a target of this TweenChain, otherwise `false`. + */ + hasTarget: function (target) + { + var data = this.data; + + for (var i = 0; i < this.totalData; i++) + { + if (data[i].hasTarget(target)) + { + return true; + } + } + + return false; + }, + + /** + * Restarts the TweenChain from the beginning. + * + * If this TweenChain was configured to have a loop, or start delay, those + * are reset to their initial values as well. It will also dispatch the + * `onActive` callback and event again. + * + * @method Phaser.Tweens.TweenChain#restart + * @since 3.60.0 + * + * @return {this} This TweenChain instance. + */ + restart: function () + { + if (this.isDestroyed()) + { + console.warn('Cannot restart destroyed TweenChain', this); + + return this; + } + + if (this.isRemoved()) + { + this.parent.makeActive(this); + } + + this.resetTweens(); + + this.paused = false; + + return this.init(); + }, + + /** + * Resets the given Tween. + * + * It will seek to position 0 and playback will start on the next frame. + * + * @method Phaser.Tweens.TweenChain#reset + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The Tween to be reset. + * + * @return {this} This TweenChain instance. + */ + reset: function (tween) + { + tween.seek(); + + tween.setActiveState(); + + return this; + }, + + /** + * Re-initialises the given Tween and sets it to the Active state. + * + * @method Phaser.Tweens.TweenChain#makeActive + * @since 3.60.0 + * @override + * + * @param {Phaser.Tweens.Tween} tween - The Tween to check. + * + * @return {this} This TweenChain instance. + */ + makeActive: function (tween) + { + tween.reset(); + + tween.setActiveState(); + + return this; + }, + + /** + * Internal method that advances to the next state of the TweenChain playback. + * + * @method Phaser.Tweens.TweenChain#nextState + * @fires Phaser.Tweens.Events#TWEEN_COMPLETE + * @fires Phaser.Tweens.Events#TWEEN_LOOP + * @since 3.60.0 + * + * @return {boolean} `true` if this TweenChain has completed, otherwise `false`. + */ + nextState: function () + { + if (this.loopCounter > 0) + { + this.loopCounter--; + + this.resetTweens(); + + if (this.loopDelay > 0) + { + this.countdown = this.loopDelay; + + this.setLoopDelayState(); + } + else + { + this.setActiveState(); + + this.dispatchEvent(Events.TWEEN_LOOP, 'onLoop'); + } + } + else if (this.completeDelay > 0) + { + this.countdown = this.completeDelay; + + this.setCompleteDelayState(); + } + else + { + this.onCompleteHandler(); + + return true; + } + + return false; + }, + + /** + * Starts this TweenChain playing. + * + * You only need to call this method if you have configured this TweenChain to be paused on creation. + * + * If the TweenChain is already playing, calling this method again will have no effect. If you wish to + * restart the chain, use `TweenChain.restart` instead. + * + * Calling this method after the TweenChain has completed will start the chain playing again from the beginning. + * + * @method Phaser.Tweens.TweenChain#play + * @since 3.60.0 + * + * @return {this} This TweenChain instance. + */ + play: function () + { + if (this.isDestroyed()) + { + console.warn('Cannot play destroyed TweenChain', this); + + return this; + } + + if (this.isPendingRemove() || this.isPending()) + { + this.resetTweens(); + } + + this.paused = false; + + if (this.startDelay > 0 && !this.isStartDelayed()) + { + this.setStartDelayState(); + } + else + { + this.setActiveState(); + } + + return this; + }, + + /** + * Internal method that resets all of the Tweens and the current index pointer. + * + * @method Phaser.Tweens.TweenChain#resetTweens + * @since 3.60.0 + */ + resetTweens: function () + { + var data = this.data; + var total = this.totalData; + + for (var i = 0; i < total; i++) + { + data[i].reset(false); + } + + this.setCurrentTween(0); + }, + + /** + * Internal method that advances the TweenChain based on the time values. + * + * @method Phaser.Tweens.TweenChain#update + * @fires Phaser.Tweens.Events#TWEEN_COMPLETE + * @fires Phaser.Tweens.Events#TWEEN_LOOP + * @fires Phaser.Tweens.Events#TWEEN_START + * @since 3.60.0 + * + * @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate. + * + * @return {boolean} Returns `true` if this TweenChain has finished and should be removed from the Tween Manager, otherwise returns `false`. + */ + update: function (delta) + { + if (this.isPendingRemove() || this.isDestroyed()) + { + if (this.persist) + { + this.setFinishedState(); + + return false; + } + + return true; + } + else if (this.isFinished() || this.paused) + { + return false; + } + + // The TweenChain.timeScale is applied within Tween.update, so doesn't need including here + delta *= this.parent.timeScale; + + if (this.isLoopDelayed()) + { + this.updateLoopCountdown(delta); + + return false; + } + else if (this.isCompleteDelayed()) + { + this.updateCompleteDelay(delta); + + return false; + } + else if (!this.hasStarted) + { + this.startDelay -= delta; + + if (this.startDelay <= 0) + { + this.hasStarted = true; + + this.dispatchEvent(Events.TWEEN_START, 'onStart'); + + // Reset the delta so we always start progress from zero + delta = 0; + } + } + + var remove = false; + + if (this.isActive() && this.currentTween) + { + if (this.currentTween.update(delta)) + { + // This tween has finished playback, so move to the next one + if (this.nextTween()) + { + this.nextState(); + } + } + + // If nextState called onCompleteHandler then it is ready to be removed, unless persist is set to true + remove = this.isPendingRemove(); + + if (remove && this.persist) + { + this.setFinishedState(); + + remove = false; + } + } + + return remove; + }, + + /** + * Immediately advances to the next Tween in the chain. + * + * This is typically called internally, but can be used if you need to + * advance playback for some reason. + * + * @method Phaser.Tweens.TweenChain#nextTween + * @since 3.60.0 + * + * @return {boolean} `true` if there are no more Tweens in the chain, otherwise `false`. + */ + nextTween: function () + { + this.currentIndex++; + + if (this.currentIndex === this.totalData) + { + return true; + } + else + { + this.setCurrentTween(this.currentIndex); + } + + return false; + }, + + /** + * Sets the current active Tween to the given index, based on its + * entry in the TweenChain data array. + * + * @method Phaser.Tweens.TweenChain#setCurrentTween + * @since 3.60.0 + * + * @param {number} index - The index of the Tween to be made current. + */ + setCurrentTween: function (index) + { + this.currentIndex = index; + + this.currentTween = this.data[index]; + + this.currentTween.setActiveState(); + }, + + /** + * Internal method that will emit a TweenChain based Event and invoke the given callback. + * + * @method Phaser.Tweens.TweenChain#dispatchEvent + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.Event} event - The Event to be dispatched. + * @param {Phaser.Types.Tweens.TweenCallbackTypes} [callback] - The name of the callback to be invoked. Can be `null` or `undefined` to skip invocation. + */ + dispatchEvent: function (event, callback) + { + this.emit(event, this); + + var handler = this.callbacks[callback]; + + if (handler) + { + handler.func.apply(this.callbackScope, [ this ].concat(handler.params)); + } + }, + + /** + * Immediately destroys this TweenChain, nulling of all its references. + * + * @method Phaser.Tweens.TweenChain#destroy + * @since 3.60.0 + */ + destroy: function () + { + BaseTween.prototype.destroy.call(this); + + this.currentTween = null; + } + +}); + +/** + * Creates a new TweenChain object and adds it to the Tween Manager. + * + * Note: This method will only be available if Tweens have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectFactory#tweenchain + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig|object} config - The TweenChain configuration. + * + * @return {Phaser.Tweens.TweenChain} The TweenChain that was created. + */ +GameObjectFactory.register('tweenchain', function (config) +{ + return this.scene.sys.tweens.chain(config); +}); + +/** + * Creates a new TweenChain object and returns it, without adding it to the Tween Manager. + * + * Note: This method will only be available if Tweens have been built into Phaser. + * + * @method Phaser.GameObjects.GameObjectCreator#tweenchain + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.TweenBuilderConfig|object} config - The TweenChain configuration. + * + * @return {Phaser.Tweens.TweenChain} The TweenChain that was created. + */ +GameObjectCreator.register('tweenchain', function (config) +{ + return this.scene.sys.tweens.create(config); +}); + +module.exports = TweenChain; + + +/***/ }), + +/***/ 48177: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseTweenData = __webpack_require__(95042); +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(842); + +/** + * @classdesc + * The TweenData is a class that contains a single target and property that is being tweened. + * + * Tweens create TweenData instances when they are created, with one TweenData instance per + * target, per property. A Tween can own multiple TweenData instances, but a TweenData only + * ever belongs to a single Tween. + * + * You should not typically create these yourself, but rather use the TweenBuilder, + * or the `Tween.add` method. + * + * Prior to Phaser 3.60 the TweenData was just an object, but was refactored to a class, + * to make it responsible for its own state and updating. + * + * @class TweenData + * @memberof Phaser.Tweens + * @extends Phaser.Tweens.BaseTweenData + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The tween this TweenData instance belongs to. + * @param {number} targetIndex - The target index within the Tween targets array. + * @param {string} key - The property of the target to tween. + * @param {Phaser.Types.Tweens.GetEndCallback} getEnd - What the property will be at the END of the Tween. + * @param {Phaser.Types.Tweens.GetStartCallback} getStart - What the property will be at the START of the Tween. + * @param {?Phaser.Types.Tweens.GetActiveCallback} getActive - If not null, is invoked _immediately_ as soon as the TweenData is running, and is set on the target property. + * @param {function} ease - The ease function this tween uses. + * @param {function} delay - Function that returns the time in milliseconds before tween will start. + * @param {number} duration - The duration of the tween in milliseconds. + * @param {boolean} yoyo - Determines whether the tween should return back to its start value after hold has expired. + * @param {number} hold - Function that returns the time in milliseconds the tween will pause before repeating or returning to its starting value if yoyo is set to true. + * @param {number} repeat - Function that returns the number of times to repeat the tween. The tween will always run once regardless, so a repeat value of '1' will play the tween twice. + * @param {number} repeatDelay - Function that returns the time in milliseconds before the repeat will start. + * @param {boolean} flipX - Should toggleFlipX be called when yoyo or repeat happens? + * @param {boolean} flipY - Should toggleFlipY be called when yoyo or repeat happens? + * @param {?function} interpolation - The interpolation function to be used for arrays of data. Defaults to 'null'. + * @param {?number[]} interpolationData - The array of interpolation data to be set. Defaults to 'null'. + */ +var TweenData = new Class({ + + Extends: BaseTweenData, + + initialize: + + function TweenData (tween, targetIndex, key, getEnd, getStart, getActive, ease, delay, duration, yoyo, hold, repeat, repeatDelay, flipX, flipY, interpolation, interpolationData) + { + BaseTweenData.call(this, tween, targetIndex, delay, duration, yoyo, hold, repeat, repeatDelay, flipX, flipY); + + /** + * The property of the target to be tweened. + * + * @name Phaser.Tweens.TweenData#key + * @type {string} + * @readonly + * @since 3.60.0 + */ + this.key = key; + + /** + * A function that returns what to set the target property to, + * the moment the TweenData is invoked. + * + * This is called when this TweenData is initialised or reset. + * + * @name Phaser.Tweens.TweenData#getActiveValue + * @type {?Phaser.Types.Tweens.GetActiveCallback} + * @since 3.60.0 + */ + this.getActiveValue = getActive; + + /** + * A function that returns what to set the target property to + * at the end of the tween. + * + * This is called when the tween starts playing, after any initial + * start delay, or if the tween is reset, or is set to repeat. + * + * @name Phaser.Tweens.TweenData#getEndValue + * @type {Phaser.Types.Tweens.GetEndCallback} + * @since 3.60.0 + */ + this.getEndValue = getEnd; + + /** + * A function that returns what to set the target property to + * at the start of the tween. + * + * This is called when the tween starts playing, after any initial + * start delay, or if the tween is reset, or is set to repeat. + * + * @name Phaser.Tweens.TweenData#getStartValue + * @type {Phaser.Types.Tweens.GetStartCallback} + * @since 3.60.0 + */ + this.getStartValue = getStart; + + /** + * The ease function this Tween uses to calculate the target value. + * + * @name Phaser.Tweens.TweenData#ease + * @type {function} + * @since 3.60.0 + */ + this.ease = ease; + + /** + * The targets starting value, as returned by `getStartValue`. + * + * @name Phaser.Tweens.TweenData#start + * @type {number} + * @since 3.60.0 + */ + this.start = 0; + + /** + * The target value from the previous step. + * + * @name Phaser.Tweens.TweenData#previous + * @type {number} + * @since 3.60.0 + */ + this.previous = 0; + + /** + * The targets current value, as recorded in the most recent step. + * + * @name Phaser.Tweens.TweenData#current + * @type {number} + * @since 3.60.0 + */ + this.current = 0; + + /** + * The targets ending value, as returned by `getEndValue`. + * + * @name Phaser.Tweens.TweenData#end + * @type {number} + * @since 3.60.0 + */ + this.end = 0; + + /** + * The interpolation function to be used for arrays of data. + * + * @name Phaser.Tweens.TweenData#interpolation + * @type {?function} + * @default null + * @since 3.60.0 + */ + this.interpolation = interpolation; + + /** + * The array of data to interpolate, if interpolation is being used. + * + * @name Phaser.Tweens.TweenData#interpolationData + * @type {?number[]} + * @since 3.60.0 + */ + this.interpolationData = interpolationData; + }, + + /** + * Internal method that resets this Tween Data entirely, including the progress and elapsed values. + * + * Called automatically by the parent Tween. Should not be called directly. + * + * @method Phaser.Tweens.TweenData#reset + * @since 3.60.0 + * + * @param {boolean} [isSeeking=false] - Is the Tween Data being reset as part of a Tween seek? + */ + reset: function (isSeeking) + { + BaseTweenData.prototype.reset.call(this); + + var target = this.tween.targets[this.targetIndex]; + var key = this.key; + + if (isSeeking) + { + target[key] = this.start; + } + + this.start = 0; + this.previous = 0; + this.current = 0; + this.end = 0; + + if (this.getActiveValue) + { + target[key] = this.getActiveValue(target, key, 0); + } + }, + + /** + * Internal method that advances this TweenData based on the delta value given. + * + * @method Phaser.Tweens.TweenData#update + * @fires Phaser.Tweens.Events#TWEEN_UPDATE + * @fires Phaser.Tweens.Events#TWEEN_REPEAT + * @since 3.60.0 + * + * @param {number} delta - The elapsed delta time in ms. + * + * @return {boolean} `true` if this TweenData is still playing, or `false` if it has finished entirely. + */ + update: function (delta) + { + var tween = this.tween; + var totalTargets = tween.totalTargets; + + var targetIndex = this.targetIndex; + var target = tween.targets[targetIndex]; + var key = this.key; + + // Bail out if we don't have a target to act upon + if (!target) + { + this.setCompleteState(); + + return false; + } + + if (this.isCountdown) + { + this.elapsed -= delta; + + if (this.elapsed <= 0) + { + this.elapsed = 0; + + delta = 0; + + if (this.isDelayed()) + { + this.setPendingRenderState(); + } + else if (this.isRepeating()) + { + this.setPlayingForwardState(); + + this.dispatchEvent(Events.TWEEN_REPEAT, 'onRepeat'); + } + else if (this.isHolding()) + { + this.setStateFromEnd(0); + } + } + } + + // All of the above have the ability to change the state, so put this in its own check + + if (this.isPendingRender()) + { + this.start = this.getStartValue(target, key, target[key], targetIndex, totalTargets, tween); + + this.end = this.getEndValue(target, key, this.start, targetIndex, totalTargets, tween); + + this.current = this.start; + + target[key] = this.start; + + this.setPlayingForwardState(); + + return true; + } + + var forward = this.isPlayingForward(); + var backward = this.isPlayingBackward(); + + if (forward || backward) + { + var elapsed = this.elapsed; + var duration = this.duration; + var diff = 0; + var complete = false; + + elapsed += delta; + + if (elapsed >= duration) + { + diff = elapsed - duration; + elapsed = duration; + complete = true; + } + else if (elapsed < 0) + { + elapsed = 0; + } + + var progress = Clamp(elapsed / duration, 0, 1); + + this.elapsed = elapsed; + this.progress = progress; + this.previous = this.current; + + if (!forward) + { + progress = 1 - progress; + } + + var v = this.ease(progress); + + if (this.interpolation) + { + this.current = this.interpolation(this.interpolationData, v); + } + else + { + this.current = this.start + ((this.end - this.start) * v); + } + + target[key] = this.current; + + if (complete) + { + if (forward) + { + if (tween.isNumberTween) + { + this.current = this.end; + target[key] = this.current; + } + + if (this.hold > 0) + { + this.elapsed = this.hold; + + this.setHoldState(); + } + else + { + this.setStateFromEnd(diff); + } + } + else + { + if (tween.isNumberTween) + { + this.current = this.start; + target[key] = this.current; + } + + this.setStateFromStart(diff); + } + } + + this.dispatchEvent(Events.TWEEN_UPDATE, 'onUpdate'); + } + + // Return TRUE if this TweenData still playing, otherwise FALSE + return !this.isComplete(); + }, + + /** + * Internal method that will emit a TweenData based Event on the + * parent Tween and also invoke the given callback, if provided. + * + * @method Phaser.Tweens.TweenData#dispatchEvent + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.Event} event - The Event to be dispatched. + * @param {Phaser.Types.Tweens.TweenCallbackTypes} [callback] - The name of the callback to be invoked. Can be `null` or `undefined` to skip invocation. + */ + dispatchEvent: function (event, callback) + { + var tween = this.tween; + + if (!tween.isSeeking) + { + var target = tween.targets[this.targetIndex]; + var key = this.key; + + var current = this.current; + var previous = this.previous; + + tween.emit(event, tween, key, target, current, previous); + + var handler = tween.callbacks[callback]; + + if (handler) + { + handler.func.apply(tween.callbackScope, [ tween, target, key, current, previous ].concat(handler.params)); + } + } + }, + + /** + * Immediately destroys this TweenData, nulling of all its references. + * + * @method Phaser.Tweens.TweenData#destroy + * @since 3.60.0 + */ + destroy: function () + { + BaseTweenData.prototype.destroy.call(this); + + this.getActiveValue = null; + this.getEndValue = null; + this.getStartValue = null; + this.ease = null; + } + +}); + +module.exports = TweenData; + + +/***/ }), + +/***/ 42220: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var BaseTweenData = __webpack_require__(95042); +var Clamp = __webpack_require__(45319); +var Class = __webpack_require__(83419); +var Events = __webpack_require__(842); + +/** + * @classdesc + * The TweenFrameData is a class that contains a single target that will change the texture frame + * at the conclusion of the Tween. + * + * TweenFrameData instances are typically created by the TweenBuilder automatically, when it + * detects the presence of a 'texture' property as the key being tweened. + * + * A Tween can own multiple TweenFrameData instances, but a TweenFrameData only + * ever belongs to a single Tween. + * + * You should not typically create these yourself, but rather use the TweenBuilder, + * or the `Tween.addFrame` method. + * + * @class TweenFrameData + * @memberof Phaser.Tweens + * @extends Phaser.Tweens.BaseTweenData + * @constructor + * @since 3.60.0 + * + * @param {Phaser.Tweens.Tween} tween - The tween this TweenData instance belongs to. + * @param {number} targetIndex - The target index within the Tween targets array. + * @param {string} texture - The texture key to set at the end of this tween. + * @param {(string|number)} frame - The texture frame to set at the end of this tween. + * @param {function} delay - Function that returns the time in milliseconds before tween will start. + * @param {number} duration - The duration of the tween in milliseconds. + * @param {number} hold - Function that returns the time in milliseconds the tween will pause before repeating or returning to its starting value if yoyo is set to true. + * @param {number} repeat - Function that returns the number of times to repeat the tween. The tween will always run once regardless, so a repeat value of '1' will play the tween twice. + * @param {number} repeatDelay - Function that returns the time in milliseconds before the repeat will start. + * @param {boolean} flipX - Should toggleFlipX be called when yoyo or repeat happens? + * @param {boolean} flipY - Should toggleFlipY be called when yoyo or repeat happens? + */ +var TweenFrameData = new Class({ + + Extends: BaseTweenData, + + initialize: + + function TweenFrameData (tween, targetIndex, texture, frame, delay, duration, hold, repeat, repeatDelay, flipX, flipY) + { + BaseTweenData.call(this, tween, targetIndex, delay, duration, false, hold, repeat, repeatDelay, flipX, flipY); + + /** + * The property of the target to be tweened. + * + * Always 'texture' for a TweenFrameData object. + * + * @name Phaser.Tweens.TweenFrameData#key + * @type {string} + * @readonly + * @since 3.60.0 + */ + this.key = 'texture'; + + /** + * The texture to be set at the start of the tween. + * + * @name Phaser.Tweens.TweenFrameData#startTexture + * @type {string} + * @since 3.60.0 + */ + this.startTexture = null; + + /** + * The texture to be set at the end of the tween. + * + * @name Phaser.Tweens.TweenFrameData#endTexture + * @type {string} + * @since 3.60.0 + */ + this.endTexture = texture; + + /** + * The frame to be set at the start of the tween. + * + * @name Phaser.Tweens.TweenFrameData#startFrame + * @type {(string|number)} + * @since 3.60.0 + */ + this.startFrame = null; + + /** + * The frame to be set at the end of the tween. + * + * @name Phaser.Tweens.TweenFrameData#endFrame + * @type {(string|number)} + * @since 3.60.0 + */ + this.endFrame = frame; + + /** + * Will the Tween ease back to its starting values, after reaching the end + * and any `hold` value that may be set? + * + * @name Phaser.Tweens.TweenFrameData#yoyo + * @type {boolean} + * @since 3.60.0 + */ + this.yoyo = (repeat !== 0) ? true : false; + }, + + /** + * Internal method that resets this Tween Data entirely, including the progress and elapsed values. + * + * Called automatically by the parent Tween. Should not be called directly. + * + * @method Phaser.Tweens.TweenFrameData#reset + * @since 3.60.0 + * + * @param {boolean} [isSeeking=false] - Is the Tween Data being reset as part of a Tween seek? + */ + reset: function (isSeeking) + { + BaseTweenData.prototype.reset.call(this); + + var target = this.tween.targets[this.targetIndex]; + + if (!this.startTexture) + { + this.startTexture = target.texture.key; + this.startFrame = target.frame.name; + } + + if (isSeeking) + { + target.setTexture(this.startTexture, this.startFrame); + } + }, + + /** + * Internal method that advances this TweenData based on the delta value given. + * + * @method Phaser.Tweens.TweenFrameData#update + * @fires Phaser.Tweens.Events#TWEEN_UPDATE + * @fires Phaser.Tweens.Events#TWEEN_REPEAT + * @since 3.60.0 + * + * @param {number} delta - The elapsed delta time in ms. + * + * @return {boolean} `true` if this TweenData is still playing, or `false` if it has finished entirely. + */ + update: function (delta) + { + var tween = this.tween; + var targetIndex = this.targetIndex; + var target = tween.targets[targetIndex]; + + // Bail out if we don't have a target to act upon + if (!target) + { + this.setCompleteState(); + + return false; + } + + if (this.isCountdown) + { + this.elapsed -= delta; + + if (this.elapsed <= 0) + { + this.elapsed = 0; + + delta = 0; + + if (this.isDelayed()) + { + this.setPendingRenderState(); + } + else if (this.isRepeating()) + { + this.setPlayingForwardState(); + + this.dispatchEvent(Events.TWEEN_REPEAT, 'onRepeat'); + } + else if (this.isHolding()) + { + this.setStateFromEnd(0); + } + } + } + + // All of the above have the ability to change the state, so put this in its own check + + if (this.isPendingRender()) + { + if (this.startTexture) + { + target.setTexture(this.startTexture, this.startFrame); + } + + this.setPlayingForwardState(); + + return true; + } + + var forward = this.isPlayingForward(); + var backward = this.isPlayingBackward(); + + if (forward || backward) + { + var elapsed = this.elapsed; + var duration = this.duration; + var diff = 0; + var complete = false; + + elapsed += delta; + + if (elapsed >= duration) + { + diff = elapsed - duration; + elapsed = duration; + complete = true; + } + else if (elapsed < 0) + { + elapsed = 0; + } + + var progress = Clamp(elapsed / duration, 0, 1); + + this.elapsed = elapsed; + this.progress = progress; + + if (complete) + { + if (forward) + { + target.setTexture(this.endTexture, this.endFrame); + + if (this.hold > 0) + { + this.elapsed = this.hold; + + this.setHoldState(); + } + else + { + this.setStateFromEnd(diff); + } + } + else + { + target.setTexture(this.startTexture, this.startFrame); + + this.setStateFromStart(diff); + } + } + + this.dispatchEvent(Events.TWEEN_UPDATE, 'onUpdate'); + } + + // Return TRUE if this TweenData still playing, otherwise FALSE + return !this.isComplete(); + }, + + /** + * Internal method that will emit a TweenData based Event on the + * parent Tween and also invoke the given callback, if provided. + * + * @method Phaser.Tweens.TweenFrameData#dispatchEvent + * @since 3.60.0 + * + * @param {Phaser.Types.Tweens.Event} event - The Event to be dispatched. + * @param {Phaser.Types.Tweens.TweenCallbackTypes} [callback] - The name of the callback to be invoked. Can be `null` or `undefined` to skip invocation. + */ + dispatchEvent: function (event, callback) + { + var tween = this.tween; + + if (!tween.isSeeking) + { + var target = tween.targets[this.targetIndex]; + var key = this.key; + + tween.emit(event, tween, key, target); + + var handler = tween.callbacks[callback]; + + if (handler) + { + handler.func.apply(tween.callbackScope, [ tween, target, key ].concat(handler.params)); + } + } + }, + + /** + * Immediately destroys this TweenData, nulling of all its references. + * + * @method Phaser.Tweens.TweenFrameData#destroy + * @since 3.60.0 + */ + destroy: function () + { + BaseTweenData.prototype.destroy.call(this); + + this.startTexture = null; + this.endTexture = null; + this.startFrame = null; + this.endFrame = null; + } + +}); + +module.exports = TweenFrameData; + + +/***/ }), + +/***/ 86353: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Phaser Tween States. + * + * @namespace Phaser.Tweens.States + * @memberof Phaser.Tweens + * @since 3.60.0 + */ + +/** + * Phaser Tween state constants. + * + * @typedef {Phaser.Tweens.States} Phaser.Tweens.StateType + * @memberof Phaser.Tweens + * @since 3.60.0 + */ + +var TWEEN_CONST = { + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.CREATED + * @type {number} + * @const + * @since 3.0.0 + */ + CREATED: 0, + + // 1 used to be INIT prior to 3.60 + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.DELAY + * @type {number} + * @const + * @since 3.0.0 + */ + DELAY: 2, + + // 3 used to be OFFSET_DELAY prior to 3.60 + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.PENDING_RENDER + * @type {number} + * @const + * @since 3.0.0 + */ + PENDING_RENDER: 4, + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.PLAYING_FORWARD + * @type {number} + * @const + * @since 3.0.0 + */ + PLAYING_FORWARD: 5, + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.PLAYING_BACKWARD + * @type {number} + * @const + * @since 3.0.0 + */ + PLAYING_BACKWARD: 6, + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.HOLD_DELAY + * @type {number} + * @const + * @since 3.0.0 + */ + HOLD_DELAY: 7, + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.REPEAT_DELAY + * @type {number} + * @const + * @since 3.0.0 + */ + REPEAT_DELAY: 8, + + /** + * TweenData state. + * + * @name Phaser.Tweens.States.COMPLETE + * @type {number} + * @const + * @since 3.0.0 + */ + COMPLETE: 9, + + // Tween specific (starts from 20 to cleanly allow extra TweenData consts in the future) + + /** + * Tween state. The Tween has been created but has not yet been added to the Tween Manager. + * + * @name Phaser.Tweens.States.PENDING + * @type {number} + * @const + * @since 3.0.0 + */ + PENDING: 20, + + /** + * Tween state. The Tween is active within the Tween Manager. This means it is either playing, + * or was playing and is currently paused, but in both cases it's still being processed by + * the Tween Manager, so is considered 'active'. + * + * @name Phaser.Tweens.States.ACTIVE + * @type {number} + * @const + * @since 3.0.0 + */ + ACTIVE: 21, + + /** + * Tween state. The Tween is waiting for a loop countdown to elapse. + * + * @name Phaser.Tweens.States.LOOP_DELAY + * @type {number} + * @const + * @since 3.0.0 + */ + LOOP_DELAY: 22, + + /** + * Tween state. The Tween is waiting for a complete delay to elapse. + * + * @name Phaser.Tweens.States.COMPLETE_DELAY + * @type {number} + * @const + * @since 3.0.0 + */ + COMPLETE_DELAY: 23, + + /** + * Tween state. The Tween is waiting for a starting delay to elapse. + * + * @name Phaser.Tweens.States.START_DELAY + * @type {number} + * @const + * @since 3.0.0 + */ + START_DELAY: 24, + + /** + * Tween state. The Tween has finished playback and is waiting to be removed from the Tween Manager. + * + * @name Phaser.Tweens.States.PENDING_REMOVE + * @type {number} + * @const + * @since 3.0.0 + */ + PENDING_REMOVE: 25, + + /** + * Tween state. The Tween has been removed from the Tween Manager. + * + * @name Phaser.Tweens.States.REMOVED + * @type {number} + * @const + * @since 3.0.0 + */ + REMOVED: 26, + + /** + * Tween state. The Tween has finished playback but was flagged as 'persistent' during creation, + * so will not be automatically removed by the Tween Manager. + * + * @name Phaser.Tweens.States.FINISHED + * @type {number} + * @const + * @since 3.60.0 + */ + FINISHED: 27, + + /** + * Tween state. The Tween has been destroyed and can no longer be played by a Tween Manager. + * + * @name Phaser.Tweens.States.DESTROYED + * @type {number} + * @const + * @since 3.60.0 + */ + DESTROYED: 28, + + /** + * A large integer value used for 'infinite' style countdowns. + * + * Similar use-case to Number.MAX_SAFE_INTEGER but we cannot use that because it's not + * supported on IE. + * + * @name Phaser.Tweens.States.MAX + * @type {number} + * @const + * @since 3.60.0 + */ + MAX: 999999999999 + +}; + +module.exports = TWEEN_CONST; + + +/***/ }), + +/***/ 83419: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +// Taken from klasse by mattdesl https://github.com/mattdesl/klasse + +function hasGetterOrSetter (def) +{ + return (!!def.get && typeof def.get === 'function') || (!!def.set && typeof def.set === 'function'); +} + +function getProperty (definition, k, isClassDescriptor) +{ + // This may be a lightweight object, OR it might be a property that was defined previously. + + // For simple class descriptors we can just assume its NOT previously defined. + var def = (isClassDescriptor) ? definition[k] : Object.getOwnPropertyDescriptor(definition, k); + + if (!isClassDescriptor && def.value && typeof def.value === 'object') + { + def = def.value; + } + + // This might be a regular property, or it may be a getter/setter the user defined in a class. + if (def && hasGetterOrSetter(def)) + { + if (typeof def.enumerable === 'undefined') + { + def.enumerable = true; + } + + if (typeof def.configurable === 'undefined') + { + def.configurable = true; + } + + return def; + } + else + { + return false; + } +} + +function hasNonConfigurable (obj, k) +{ + var prop = Object.getOwnPropertyDescriptor(obj, k); + + if (!prop) + { + return false; + } + + if (prop.value && typeof prop.value === 'object') + { + prop = prop.value; + } + + if (prop.configurable === false) + { + return true; + } + + return false; +} + +/** + * Extends the given `myClass` object's prototype with the properties of `definition`. + * + * @function extend + * @ignore + * @param {Object} ctor The constructor object to mix into. + * @param {Object} definition A dictionary of functions for the class. + * @param {boolean} isClassDescriptor Is the definition a class descriptor? + * @param {Object} [extend] The parent constructor object. + */ +function extend (ctor, definition, isClassDescriptor, extend) +{ + for (var k in definition) + { + if (!definition.hasOwnProperty(k)) + { + continue; + } + + var def = getProperty(definition, k, isClassDescriptor); + + if (def !== false) + { + // If Extends is used, we will check its prototype to see if the final variable exists. + + var parent = extend || ctor; + + if (hasNonConfigurable(parent.prototype, k)) + { + // Just skip the final property + if (Class.ignoreFinals) + { + continue; + } + + // We cannot re-define a property that is configurable=false. + // So we will consider them final and throw an error. This is by + // default so it is clear to the developer what is happening. + // You can set ignoreFinals to true if you need to extend a class + // which has configurable=false; it will simply not re-define final properties. + throw new Error('cannot override final property \'' + k + '\', set Class.ignoreFinals = true to skip'); + } + + Object.defineProperty(ctor.prototype, k, def); + } + else + { + ctor.prototype[k] = definition[k]; + } + } +} + +/** + * Applies the given `mixins` to the prototype of `myClass`. + * + * @function mixin + * @ignore + * @param {Object} myClass The constructor object to mix into. + * @param {Object|Array} mixins The mixins to apply to the constructor. + */ +function mixin (myClass, mixins) +{ + if (!mixins) + { + return; + } + + if (!Array.isArray(mixins)) + { + mixins = [ mixins ]; + } + + for (var i = 0; i < mixins.length; i++) + { + extend(myClass, mixins[i].prototype || mixins[i]); + } +} + +/** + * Creates a new class with the given descriptor. + * The constructor, defined by the name `initialize`, + * is an optional function. If unspecified, an anonymous + * function will be used which calls the parent class (if + * one exists). + * + * You can also use `Extends` and `Mixins` to provide subclassing + * and inheritance. + * + * @class Phaser.Class + * @constructor + * @param {Object} definition a dictionary of functions for the class + * @example + * + * var MyClass = new Phaser.Class({ + * + * initialize: function() { + * this.foo = 2.0; + * }, + * + * bar: function() { + * return this.foo + 5; + * } + * }); + */ +function Class (definition) +{ + if (!definition) + { + definition = {}; + } + + // The variable name here dictates what we see in Chrome debugger + var initialize; + var Extends; + + if (definition.initialize) + { + if (typeof definition.initialize !== 'function') + { + throw new Error('initialize must be a function'); + } + + initialize = definition.initialize; + + // Usually we should avoid 'delete' in V8 at all costs. + // However, its unlikely to make any performance difference + // here since we only call this on class creation (i.e. not object creation). + delete definition.initialize; + } + else if (definition.Extends) + { + var base = definition.Extends; + + initialize = function () + { + base.apply(this, arguments); + }; + } + else + { + initialize = function () {}; + } + + if (definition.Extends) + { + initialize.prototype = Object.create(definition.Extends.prototype); + initialize.prototype.constructor = initialize; + + // For getOwnPropertyDescriptor to work, we need to act directly on the Extends (or Mixin) + + Extends = definition.Extends; + + delete definition.Extends; + } + else + { + initialize.prototype.constructor = initialize; + } + + // Grab the mixins, if they are specified... + var mixins = null; + + if (definition.Mixins) + { + mixins = definition.Mixins; + delete definition.Mixins; + } + + // First, mixin if we can. + mixin(initialize, mixins); + + // Now we grab the actual definition which defines the overrides. + extend(initialize, definition, true, Extends); + + return initialize; +} + +Class.extend = extend; +Class.mixin = mixin; +Class.ignoreFinals = false; + +module.exports = Class; + + +/***/ }), + +/***/ 29747: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * A NOOP (No Operation) callback function. + * + * Used internally by Phaser when it's more expensive to determine if a callback exists + * than it is to just invoke an empty function. + * + * @function Phaser.Utils.NOOP + * @since 3.0.0 + */ +var NOOP = function () +{ + // NOOP +}; + +module.exports = NOOP; + + +/***/ }), + +/***/ 20242: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * A NULL OP callback function. + * + * This function always returns `null`. + * + * Used internally by Phaser when it's more expensive to determine if a callback exists + * than it is to just invoke an empty function. + * + * @function Phaser.Utils.NULL + * @since 3.60.0 + */ +var NULL = function () +{ + return null; +}; + +module.exports = NULL; + + +/***/ }), + +/***/ 71146: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Adds the given item, or array of items, to the array. + * + * Each item must be unique within the array. + * + * The array is modified in-place and returned. + * + * You can optionally specify a limit to the maximum size of the array. If the quantity of items being + * added will take the array length over this limit, it will stop adding once the limit is reached. + * + * You can optionally specify a callback to be invoked for each item successfully added to the array. + * + * @function Phaser.Utils.Array.Add + * @since 3.4.0 + * + * @param {array} array - The array to be added to. + * @param {any|any[]} item - The item, or array of items, to add to the array. Each item must be unique within the array. + * @param {number} [limit] - Optional limit which caps the size of the array. + * @param {function} [callback] - A callback to be invoked for each item successfully added to the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {array} The input array. + */ +var Add = function (array, item, limit, callback, context) +{ + if (context === undefined) { context = array; } + + if (limit > 0) + { + var remaining = limit - array.length; + + // There's nothing more we can do here, the array is full + if (remaining <= 0) + { + return null; + } + } + + // Fast path to avoid array mutation and iteration + if (!Array.isArray(item)) + { + if (array.indexOf(item) === -1) + { + array.push(item); + + if (callback) + { + callback.call(context, item); + } + + return item; + } + else + { + return null; + } + } + + // If we got this far, we have an array of items to insert + + // Ensure all the items are unique + var itemLength = item.length - 1; + + while (itemLength >= 0) + { + if (array.indexOf(item[itemLength]) !== -1) + { + // Already exists in array, so remove it + item.splice(itemLength, 1); + } + + itemLength--; + } + + // Anything left? + itemLength = item.length; + + if (itemLength === 0) + { + return null; + } + + if (limit > 0 && itemLength > remaining) + { + item.splice(remaining); + + itemLength = remaining; + } + + for (var i = 0; i < itemLength; i++) + { + var entry = item[i]; + + array.push(entry); + + if (callback) + { + callback.call(context, entry); + } + } + + return item; +}; + +module.exports = Add; + + +/***/ }), + +/***/ 51067: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Adds the given item, or array of items, to the array starting at the index specified. + * + * Each item must be unique within the array. + * + * Existing elements in the array are shifted up. + * + * The array is modified in-place and returned. + * + * You can optionally specify a limit to the maximum size of the array. If the quantity of items being + * added will take the array length over this limit, it will stop adding once the limit is reached. + * + * You can optionally specify a callback to be invoked for each item successfully added to the array. + * + * @function Phaser.Utils.Array.AddAt + * @since 3.4.0 + * + * @param {array} array - The array to be added to. + * @param {any|any[]} item - The item, or array of items, to add to the array. + * @param {number} [index=0] - The index in the array where the item will be inserted. + * @param {number} [limit] - Optional limit which caps the size of the array. + * @param {function} [callback] - A callback to be invoked for each item successfully added to the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {array} The input array. + */ +var AddAt = function (array, item, index, limit, callback, context) +{ + if (index === undefined) { index = 0; } + if (context === undefined) { context = array; } + + if (limit > 0) + { + var remaining = limit - array.length; + + // There's nothing more we can do here, the array is full + if (remaining <= 0) + { + return null; + } + } + + // Fast path to avoid array mutation and iteration + if (!Array.isArray(item)) + { + if (array.indexOf(item) === -1) + { + array.splice(index, 0, item); + + if (callback) + { + callback.call(context, item); + } + + return item; + } + else + { + return null; + } + } + + // If we got this far, we have an array of items to insert + + // Ensure all the items are unique + var itemLength = item.length - 1; + + while (itemLength >= 0) + { + if (array.indexOf(item[itemLength]) !== -1) + { + // Already exists in array, so remove it + item.pop(); + } + + itemLength--; + } + + // Anything left? + itemLength = item.length; + + if (itemLength === 0) + { + return null; + } + + // Truncate to the limit + if (limit > 0 && itemLength > remaining) + { + item.splice(remaining); + + itemLength = remaining; + } + + for (var i = itemLength - 1; i >= 0; i--) + { + var entry = item[i]; + + array.splice(index, 0, entry); + + if (callback) + { + callback.call(context, entry); + } + } + + return item; +}; + +module.exports = AddAt; + + +/***/ }), + +/***/ 66905: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the given element to the top of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.BringToTop + * @since 3.4.0 + * + * @param {array} array - The array. + * @param {*} item - The element to move. + * + * @return {*} The element that was moved. + */ +var BringToTop = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex !== -1 && currentIndex < array.length) + { + array.splice(currentIndex, 1); + array.push(item); + } + + return item; +}; + +module.exports = BringToTop; + + +/***/ }), + +/***/ 21612: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SafeRange = __webpack_require__(82011); + +/** + * Returns the total number of elements in the array which have a property matching the given value. + * + * @function Phaser.Utils.Array.CountAllMatching + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} property - The property to test on each array element. + * @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {number} [startIndex] - An optional start index to search from. + * @param {number} [endIndex] - An optional end index to search to. + * + * @return {number} The total number of elements with properties matching the given value. + */ +var CountAllMatching = function (array, property, value, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + var total = 0; + + if (SafeRange(array, startIndex, endIndex)) + { + for (var i = startIndex; i < endIndex; i++) + { + var child = array[i]; + + if (child[property] === value) + { + total++; + } + } + } + + return total; +}; + +module.exports = CountAllMatching; + + +/***/ }), + +/***/ 95428: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Passes each element in the array to the given callback. + * + * @function Phaser.Utils.Array.Each + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {function} callback - A callback to be invoked for each item in the array. + * @param {object} context - The context in which the callback is invoked. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the current array item. + * + * @return {array} The input array. + */ +var Each = function (array, callback, context) +{ + var i; + var args = [ null ]; + + for (i = 3; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < array.length; i++) + { + args[0] = array[i]; + + callback.apply(context, args); + } + + return array; +}; + +module.exports = Each; + + +/***/ }), + +/***/ 36914: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SafeRange = __webpack_require__(82011); + +/** + * Passes each element in the array, between the start and end indexes, to the given callback. + * + * @function Phaser.Utils.Array.EachInRange + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {function} callback - A callback to be invoked for each item in the array. + * @param {object} context - The context in which the callback is invoked. + * @param {number} startIndex - The start index to search from. + * @param {number} endIndex - The end index to search to. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {array} The input array. + */ +var EachInRange = function (array, callback, context, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + if (SafeRange(array, startIndex, endIndex)) + { + var i; + var args = [ null ]; + + for (i = 5; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = startIndex; i < endIndex; i++) + { + args[0] = array[i]; + + callback.apply(context, args); + } + } + + return array; +}; + +module.exports = EachInRange; + + +/***/ }), + +/***/ 81957: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Searches a pre-sorted array for the closet value to the given number. + * + * If the `key` argument is given it will assume the array contains objects that all have the required `key` property name, + * and will check for the closest value of those to the given number. + * + * @function Phaser.Utils.Array.FindClosestInSorted + * @since 3.0.0 + * + * @param {number} value - The value to search for in the array. + * @param {array} array - The array to search, which must be sorted. + * @param {string} [key] - An optional property key. If specified the array elements property will be checked against value. + * + * @return {(number|any)} The nearest value found in the array, or if a `key` was given, the nearest object with the matching property value. + */ +var FindClosestInSorted = function (value, array, key) +{ + if (!array.length) + { + return NaN; + } + else if (array.length === 1) + { + return array[0]; + } + + var i = 1; + var low; + var high; + + if (key) + { + if (value < array[0][key]) + { + return array[0]; + } + + while (array[i][key] < value) + { + i++; + } + } + else + { + while (array[i] < value) + { + i++; + } + } + + if (i > array.length) + { + i = array.length; + } + + if (key) + { + low = array[i - 1][key]; + high = array[i][key]; + + return ((high - value) <= (value - low)) ? array[i] : array[i - 1]; + } + else + { + low = array[i - 1]; + high = array[i]; + + return ((high - value) <= (value - low)) ? high : low; + } +}; + +module.exports = FindClosestInSorted; + + +/***/ }), + +/***/ 43491: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes an array and flattens it, returning a shallow-copy flattened array. + * + * @function Phaser.Utils.Array.Flatten + * @since 3.60.0 + * + * @param {array} array - The array to flatten. + * @param {array} [output] - An array to hold the results in. + * + * @return {array} The flattened output array. + */ +var Flatten = function (array, output) +{ + if (output === undefined) { output = []; } + + for (var i = 0; i < array.length; i++) + { + if (Array.isArray(array[i])) + { + Flatten(array[i], output); + } + else + { + output.push(array[i]); + } + } + + return output; +}; + +module.exports = Flatten; + + +/***/ }), + +/***/ 46710: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SafeRange = __webpack_require__(82011); + +/** + * Returns all elements in the array. + * + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('visible', true)` would return only elements that have their visible property set. + * + * Optionally you can specify a start and end index. For example if the array had 100 elements, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 elements. + * + * @function Phaser.Utils.Array.GetAll + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} [property] - The property to test on each array element. + * @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {number} [startIndex] - An optional start index to search from. + * @param {number} [endIndex] - An optional end index to search to. + * + * @return {array} All matching elements from the array. + */ +var GetAll = function (array, property, value, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + var output = []; + + if (SafeRange(array, startIndex, endIndex)) + { + for (var i = startIndex; i < endIndex; i++) + { + var child = array[i]; + + if (!property || + (property && value === undefined && child.hasOwnProperty(property)) || + (property && value !== undefined && child[property] === value)) + { + output.push(child); + } + } + } + + return output; +}; + +module.exports = GetAll; + + +/***/ }), + +/***/ 58731: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SafeRange = __webpack_require__(82011); + +/** + * Returns the first element in the array. + * + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('visible', true)` would return the first element that had its `visible` property set. + * + * Optionally you can specify a start and end index. For example if the array had 100 elements, + * and you set `startIndex` to 0 and `endIndex` to 50, it would search only the first 50 elements. + * + * You can also specify a negative `startIndex`, such as `-1`, which would start the search at the end of the array + * + * @function Phaser.Utils.Array.GetFirst + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} [property] - The property to test on each array element. + * @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {number} [startIndex=0] - An optional start index to search from. You can also set `startIndex` to -1 to start the search from the end of the array. + * @param {number} [endIndex=array.length] - An optional end index to search up to (but not included) + * + * @return {?object} The first matching element from the array, or `null` if no element could be found in the range given. + */ +var GetFirst = function (array, property, value, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + if (startIndex !== -1) + { + if (SafeRange(array, startIndex, endIndex)) + { + for (var i = startIndex; i < endIndex; i++) + { + var child = array[i]; + + if (!property || + (property && value === undefined && child.hasOwnProperty(property)) || + (property && value !== undefined && child[property] === value)) + { + return child; + } + } + } + } + else + { + if (SafeRange(array, 0, endIndex)) + { + for (var i = endIndex; i >= 0; i--) + { + var child = array[i]; + + if (!property || + (property && value === undefined && child.hasOwnProperty(property)) || + (property && value !== undefined && child[property] === value)) + { + return child; + } + } + } + } + + return null; +}; + +module.exports = GetFirst; + + +/***/ }), + +/***/ 26546: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Returns a Random element from the array. + * + * @function Phaser.Utils.Array.GetRandom + * @since 3.0.0 + * + * @generic T + * @genericUse {T[]} - [array] + * @genericUse {T} - [$return] + * + * @param {T[]} array - The array to select the random entry from. + * @param {number} [startIndex=0] - An optional start index. + * @param {number} [length=array.length] - An optional length, the total number of elements (from the startIndex) to choose from. + * + * @return {T} A random element from the array, or `null` if no element could be found in the range given. + */ +var GetRandom = function (array, startIndex, length) +{ + if (startIndex === undefined) { startIndex = 0; } + if (length === undefined) { length = array.length; } + + var randomIndex = startIndex + Math.floor(Math.random() * length); + + return (array[randomIndex] === undefined) ? null : array[randomIndex]; +}; + +module.exports = GetRandom; + + +/***/ }), + +/***/ 85835: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the given array element above another one in the array. + * If the given element is already above the other, it isn't moved. + * Above means toward the end of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveAbove + * @since 3.55.0 + * + * @param {array} array - The input array. + * @param {*} item1 - The element to move above base element. + * @param {*} item2 - The base element. + * + * + * @return {array} The input array. + */ +var MoveAbove = function (array, item1, item2) +{ + if (item1 === item2) + { + return array; + } + + var currentIndex = array.indexOf(item1); + var baseIndex = array.indexOf(item2); + + if (currentIndex < 0 || baseIndex < 0) + { + throw new Error('Supplied items must be elements of the same array'); + } + + if (currentIndex > baseIndex) + { + // item1 is already above item2 + return array; + } + + // Remove item1 from its current position + array.splice(currentIndex, 1); + + // Recalculate baseIndex after removal + baseIndex = array.indexOf(item2); + + // Insert item1 immediately after item2 + array.splice(baseIndex + 1, 0, item1); + + return array; +}; + +module.exports = MoveAbove; + + +/***/ }), + +/***/ 83371: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the given array element below another one in the array. + * If the given element is already below the other, it isn't moved. + * Below means toward the start of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveBelow + * @since 3.55.0 + * + * @param {array} array - The input array. + * @param {*} item1 - The element to move below base element. + * @param {*} item2 - The base element. + * + * + * @return {array} The input array. + */ +var MoveBelow = function (array, item1, item2) +{ + if (item1 === item2) + { + return array; + } + + var currentIndex = array.indexOf(item1); + var baseIndex = array.indexOf(item2); + + if (currentIndex < 0 || baseIndex < 0) + { + throw new Error('Supplied items must be elements of the same array'); + } + + if (currentIndex < baseIndex) + { + // item1 is already below item2 + return array; + } + + // Remove + array.splice(currentIndex, 1); + + // Add in new location + if (baseIndex === 0) + { + array.unshift(item1); + } + else + { + array.splice(baseIndex, 0, item1); + } + + return array; +}; + +module.exports = MoveBelow; + + +/***/ }), + +/***/ 70864: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the given array element down one place in the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveDown + * @since 3.4.0 + * + * @param {array} array - The input array. + * @param {*} item - The element to move down the array. + * + * @return {array} The input array. + */ +var MoveDown = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex > 0) + { + var item2 = array[currentIndex - 1]; + + var index2 = array.indexOf(item2); + + array[currentIndex] = item2; + array[index2] = item; + } + + return array; +}; + +module.exports = MoveDown; + + +/***/ }), + +/***/ 69693: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves an element in an array to a new position within the same array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveTo + * @since 3.4.0 + * + * @param {array} array - The array. + * @param {*} item - The element to move. + * @param {number} index - The new index that the element will be moved to. + * + * @return {*} The element that was moved. + */ +var MoveTo = function (array, item, index) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex === -1 || index < 0 || index >= array.length) + { + throw new Error('Supplied index out of bounds'); + } + + if (currentIndex !== index) + { + // Remove + array.splice(currentIndex, 1); + + // Add in new location + array.splice(index, 0, item); + } + + return item; +}; + +module.exports = MoveTo; + + +/***/ }), + +/***/ 40853: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the given array element up one place in the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveUp + * @since 3.4.0 + * + * @param {array} array - The input array. + * @param {*} item - The element to move up the array. + * + * @return {array} The input array. + */ +var MoveUp = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex !== -1 && currentIndex < array.length - 1) + { + // The element one above `item` in the array + var item2 = array[currentIndex + 1]; + var index2 = array.indexOf(item2); + + array[currentIndex] = item2; + array[index2] = item; + } + + return array; +}; + +module.exports = MoveUp; + + +/***/ }), + +/***/ 20283: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Create an array representing the range of numbers (usually integers), between, and inclusive of, + * the given `start` and `end` arguments. For example: + * + * `var array = Phaser.Utils.Array.NumberArray(2, 4); // array = [2, 3, 4]` + * `var array = Phaser.Utils.Array.NumberArray(0, 9); // array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]` + * `var array = Phaser.Utils.Array.NumberArray(8, 2); // array = [8, 7, 6, 5, 4, 3, 2]` + * + * This is equivalent to `Phaser.Utils.Array.NumberArrayStep(start, end, 1)`. + * + * You can optionally provide a prefix and / or suffix string. If given the array will contain + * strings, not integers. For example: + * + * `var array = Phaser.Utils.Array.NumberArray(1, 4, 'Level '); // array = ["Level 1", "Level 2", "Level 3", "Level 4"]` + * `var array = Phaser.Utils.Array.NumberArray(5, 7, 'HD-', '.png'); // array = ["HD-5.png", "HD-6.png", "HD-7.png"]` + * + * @function Phaser.Utils.Array.NumberArray + * @since 3.0.0 + * + * @param {number} start - The minimum value the array starts with. + * @param {number} end - The maximum value the array contains. + * @param {string} [prefix] - Optional prefix to place before the number. If provided the array will contain strings, not integers. + * @param {string} [suffix] - Optional suffix to place after the number. If provided the array will contain strings, not integers. + * + * @return {(number[]|string[])} The array of number values, or strings if a prefix or suffix was provided. + */ +var NumberArray = function (start, end, prefix, suffix) +{ + var result = []; + + var i; + var asString = false; + + if (prefix || suffix) + { + asString = true; + + if (!prefix) + { + prefix = ''; + } + + if (!suffix) + { + suffix = ''; + } + } + + if (end < start) + { + for (i = start; i >= end; i--) + { + if (asString) + { + result.push(prefix + i.toString() + suffix); + } + else + { + result.push(i); + } + } + } + else + { + for (i = start; i <= end; i++) + { + if (asString) + { + result.push(prefix + i.toString() + suffix); + } + else + { + result.push(i); + } + } + } + + return result; +}; + +module.exports = NumberArray; + + +/***/ }), + +/***/ 593: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RoundAwayFromZero = __webpack_require__(2284); + +/** + * Create an array of numbers (positive and/or negative) progressing from `start` + * up to but not including `end` by advancing by `step`. + * + * If `start` is less than `end` a zero-length range is created unless a negative `step` is specified. + * + * Certain values for `start` and `end` (eg. NaN/undefined/null) are currently coerced to 0; + * for forward compatibility make sure to pass in actual numbers. + * + * @example + * NumberArrayStep(4); + * // => [0, 1, 2, 3] + * + * NumberArrayStep(1, 5); + * // => [1, 2, 3, 4] + * + * NumberArrayStep(0, 20, 5); + * // => [0, 5, 10, 15] + * + * NumberArrayStep(0, -4, -1); + * // => [0, -1, -2, -3] + * + * NumberArrayStep(1, 4, 0); + * // => [1, 1, 1] + * + * NumberArrayStep(0); + * // => [] + * + * @function Phaser.Utils.Array.NumberArrayStep + * @since 3.0.0 + * + * @param {number} [start=0] - The start of the range. + * @param {number} [end=null] - The end of the range. + * @param {number} [step=1] - The value to increment or decrement by. + * + * @return {number[]} The array of number values. + */ +var NumberArrayStep = function (start, end, step) +{ + if (start === undefined) { start = 0; } + if (end === undefined) { end = null; } + if (step === undefined) { step = 1; } + + if (end === null) + { + end = start; + start = 0; + } + + var result = []; + + var total = Math.max(RoundAwayFromZero((end - start) / (step || 1)), 0); + + for (var i = 0; i < total; i++) + { + result.push(start); + start += step; + } + + return result; +}; + +module.exports = NumberArrayStep; + + +/***/ }), + +/***/ 43886: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @ignore + */ +function swap (arr, i, j) +{ + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; +} + +/** + * @ignore + */ +function defaultCompare (a, b) +{ + return a < b ? -1 : a > b ? 1 : 0; +} + +/** + * A [Floyd-Rivest](https://en.wikipedia.org/wiki/Floyd%E2%80%93Rivest_algorithm) quick selection algorithm. + * + * Rearranges the array items so that all items in the [left, k] range are smaller than all items in [k, right]; + * The k-th element will have the (k - left + 1)th smallest value in [left, right]. + * + * The array is modified in-place. + * + * Based on code by [Vladimir Agafonkin](https://www.npmjs.com/~mourner) + * + * @function Phaser.Utils.Array.QuickSelect + * @since 3.0.0 + * + * @param {array} arr - The array to sort. + * @param {number} k - The k-th element index. + * @param {number} [left=0] - The index of the left part of the range. + * @param {number} [right] - The index of the right part of the range. + * @param {function} [compare] - An optional comparison function. Is passed two elements and should return 0, 1 or -1. + */ +var QuickSelect = function (arr, k, left, right, compare) +{ + if (left === undefined) { left = 0; } + if (right === undefined) { right = arr.length - 1; } + if (compare === undefined) { compare = defaultCompare; } + + while (right > left) + { + if (right - left > 600) + { + var n = right - left + 1; + var m = k - left + 1; + var z = Math.log(n); + var s = 0.5 * Math.exp(2 * z / 3); + var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1); + var newLeft = Math.max(left, Math.floor(k - m * s / n + sd)); + var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd)); + + QuickSelect(arr, k, newLeft, newRight, compare); + } + + var t = arr[k]; + var i = left; + var j = right; + + swap(arr, left, k); + + if (compare(arr[right], t) > 0) + { + swap(arr, left, right); + } + + while (i < j) + { + swap(arr, i, j); + + i++; + j--; + + while (compare(arr[i], t) < 0) + { + i++; + } + + while (compare(arr[j], t) > 0) + { + j--; + } + } + + if (compare(arr[left], t) === 0) + { + swap(arr, left, j); + } + else + { + j++; + swap(arr, j, right); + } + + if (j <= k) + { + left = j + 1; + } + + if (k <= j) + { + right = j - 1; + } + } +}; + +module.exports = QuickSelect; + + +/***/ }), + +/***/ 88492: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetValue = __webpack_require__(35154); +var Shuffle = __webpack_require__(33680); + +var BuildChunk = function (a, b, qty) +{ + var out = []; + + for (var aIndex = 0; aIndex < a.length; aIndex++) + { + for (var bIndex = 0; bIndex < b.length; bIndex++) + { + for (var i = 0; i < qty; i++) + { + out.push({ a: a[aIndex], b: b[bIndex] }); + } + } + } + + return out; +}; + +/** + * Creates an array populated with a range of values, based on the given arguments and configuration object. + * + * Range ([a,b,c], [1,2,3]) = + * a1, a2, a3, b1, b2, b3, c1, c2, c3 + * + * Range ([a,b], [1,2,3], qty = 3) = + * a1, a1, a1, a2, a2, a2, a3, a3, a3, b1, b1, b1, b2, b2, b2, b3, b3, b3 + * + * Range ([a,b,c], [1,2,3], repeat x1) = + * a1, a2, a3, b1, b2, b3, c1, c2, c3, a1, a2, a3, b1, b2, b3, c1, c2, c3 + * + * Range ([a,b], [1,2], repeat -1 = endless, max = 14) = + * Maybe if max is set then repeat goes to -1 automatically? + * a1, a2, b1, b2, a1, a2, b1, b2, a1, a2, b1, b2, a1, a2 (capped at 14 elements) + * + * Range ([a], [1,2,3,4,5], random = true) = + * a4, a1, a5, a2, a3 + * + * Range ([a, b], [1,2,3], random = true) = + * b3, a2, a1, b1, a3, b2 + * + * Range ([a, b, c], [1,2,3], randomB = true) = + * a3, a1, a2, b2, b3, b1, c1, c3, c2 + * + * Range ([a], [1,2,3,4,5], yoyo = true) = + * a1, a2, a3, a4, a5, a5, a4, a3, a2, a1 + * + * Range ([a, b], [1,2,3], yoyo = true) = + * a1, a2, a3, b1, b2, b3, b3, b2, b1, a3, a2, a1 + * + * @function Phaser.Utils.Array.Range + * @since 3.0.0 + * + * @param {array} a - The first array of range elements. + * @param {array} b - The second array of range elements. + * @param {object} [options] - A range configuration object. Can contain: repeat, random, randomB, yoyo, max, qty. + * + * @return {array} An array of arranged elements. + */ +var Range = function (a, b, options) +{ + var max = GetValue(options, 'max', 0); + var qty = GetValue(options, 'qty', 1); + var random = GetValue(options, 'random', false); + var randomB = GetValue(options, 'randomB', false); + var repeat = GetValue(options, 'repeat', 0); + var yoyo = GetValue(options, 'yoyo', false); + + var out = []; + + if (randomB) + { + Shuffle(b); + } + + // Endless repeat, so limit by max + if (repeat === -1) + { + if (max === 0) + { + repeat = 0; + } + else + { + // Work out how many repeats we need + var total = (a.length * b.length) * qty; + + if (yoyo) + { + total *= 2; + } + + repeat = Math.ceil(max / total); + } + } + + for (var i = 0; i <= repeat; i++) + { + var chunk = BuildChunk(a, b, qty); + + if (random) + { + Shuffle(chunk); + } + + out = out.concat(chunk); + + if (yoyo) + { + chunk.reverse(); + + out = out.concat(chunk); + } + } + + if (max) + { + out.splice(max); + } + + return out; +}; + +module.exports = Range; + + +/***/ }), + +/***/ 72905: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SpliceOne = __webpack_require__(19133); + +/** + * Removes the given item, or array of items, from the array. + * + * The array is modified in-place. + * + * You can optionally specify a callback to be invoked for each item successfully removed from the array. + * + * @function Phaser.Utils.Array.Remove + * @since 3.4.0 + * + * @param {array} array - The array to be modified. + * @param {*|Array.<*>} item - The item, or array of items, to be removed from the array. + * @param {function} [callback] - A callback to be invoked for each item successfully removed from the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {*|Array.<*>} The item, or array of items, that were successfully removed from the array. + */ +var Remove = function (array, item, callback, context) +{ + if (context === undefined) { context = array; } + + var index; + + // Fast path to avoid array mutation and iteration + if (!Array.isArray(item)) + { + index = array.indexOf(item); + + if (index !== -1) + { + SpliceOne(array, index); + + if (callback) + { + callback.call(context, item); + } + + return item; + } + else + { + return null; + } + } + + // If we got this far, we have an array of items to remove + + var itemLength = item.length - 1; + var removed = []; + + while (itemLength >= 0) + { + var entry = item[itemLength]; + + index = array.indexOf(entry); + + if (index !== -1) + { + SpliceOne(array, index); + + removed.push(entry); + + if (callback) + { + callback.call(context, entry); + } + } + + itemLength--; + } + + return removed; +}; + +module.exports = Remove; + + +/***/ }), + +/***/ 60248: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SpliceOne = __webpack_require__(19133); + +/** + * Removes the item from the given position in the array. + * + * The array is modified in-place. + * + * You can optionally specify a callback to be invoked for the item if it is successfully removed from the array. + * + * @function Phaser.Utils.Array.RemoveAt + * @since 3.4.0 + * + * @param {array} array - The array to be modified. + * @param {number} index - The array index to remove the item from. The index must be in bounds or it will throw an error. + * @param {function} [callback] - A callback to be invoked for the item removed from the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {*} The item that was removed. + */ +var RemoveAt = function (array, index, callback, context) +{ + if (context === undefined) { context = array; } + + if (index < 0 || index > array.length - 1) + { + throw new Error('Index out of bounds'); + } + + var item = SpliceOne(array, index); + + if (callback) + { + callback.call(context, item); + } + + return item; +}; + +module.exports = RemoveAt; + + +/***/ }), + +/***/ 81409: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SafeRange = __webpack_require__(82011); + +/** + * Removes the item within the given range in the array. + * + * The array is modified in-place. + * + * You can optionally specify a callback to be invoked for the item/s successfully removed from the array. + * + * @function Phaser.Utils.Array.RemoveBetween + * @since 3.4.0 + * + * @param {array} array - The array to be modified. + * @param {number} startIndex - The start index to remove from. + * @param {number} endIndex - The end index to remove to. + * @param {function} [callback] - A callback to be invoked for the item removed from the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {Array.<*>} An array of items that were removed. + */ +var RemoveBetween = function (array, startIndex, endIndex, callback, context) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + if (context === undefined) { context = array; } + + if (SafeRange(array, startIndex, endIndex)) + { + var size = endIndex - startIndex; + + var removed = array.splice(startIndex, size); + + if (callback) + { + for (var i = 0; i < removed.length; i++) + { + var entry = removed[i]; + + callback.call(context, entry); + } + } + + return removed; + } + else + { + return []; + } +}; + +module.exports = RemoveBetween; + + +/***/ }), + +/***/ 31856: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SpliceOne = __webpack_require__(19133); + +/** + * Removes a random object from the given array and returns it. + * Will return null if there are no array items that fall within the specified range or if there is no item for the randomly chosen index. + * + * @function Phaser.Utils.Array.RemoveRandomElement + * @since 3.0.0 + * + * @param {array} array - The array to removed a random element from. + * @param {number} [start=0] - The array index to start the search from. + * @param {number} [length=array.length] - Optional restriction on the number of elements to randomly select from. + * + * @return {object} The random element that was removed, or `null` if there were no array elements that fell within the given range. + */ +var RemoveRandomElement = function (array, start, length) +{ + if (start === undefined) { start = 0; } + if (length === undefined) { length = array.length; } + + var randomIndex = start + Math.floor(Math.random() * length); + + return SpliceOne(array, randomIndex); +}; + +module.exports = RemoveRandomElement; + + +/***/ }), + +/***/ 42169: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Replaces an element of the array with the new element. + * The new element cannot already be a member of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.Replace + * @since 3.4.0 + * + * @param {array} array - The array to search within. + * @param {*} oldChild - The element in the array that will be replaced. + * @param {*} newChild - The element to be inserted into the array at the position of `oldChild`. + * + * @return {boolean} Returns true if the oldChild was successfully replaced, otherwise returns false. + */ +var Replace = function (array, oldChild, newChild) +{ + var index1 = array.indexOf(oldChild); + var index2 = array.indexOf(newChild); + + if (index1 !== -1 && index2 === -1) + { + array[index1] = newChild; + + return true; + } + else + { + return false; + } +}; + +module.exports = Replace; + + +/***/ }), + +/***/ 86003: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the element at the start of the array to the end, shifting all items in the process. + * The "rotation" happens to the left. + * + * @function Phaser.Utils.Array.RotateLeft + * @since 3.0.0 + * + * @param {array} array - The array to shift to the left. This array is modified in place. + * @param {number} [total=1] - The number of times to shift the array. + * + * @return {*} The most recently shifted element. + */ +var RotateLeft = function (array, total) +{ + if (total === undefined) { total = 1; } + + var element = null; + + for (var i = 0; i < total; i++) + { + element = array.shift(); + array.push(element); + } + + return element; +}; + +module.exports = RotateLeft; + + +/***/ }), + +/***/ 49498: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the element at the end of the array to the start, shifting all items in the process. + * The "rotation" happens to the right. + * + * @function Phaser.Utils.Array.RotateRight + * @since 3.0.0 + * + * @param {array} array - The array to shift to the right. This array is modified in place. + * @param {number} [total=1] - The number of times to shift the array. + * + * @return {*} The most recently shifted element. + */ +var RotateRight = function (array, total) +{ + if (total === undefined) { total = 1; } + + var element = null; + + for (var i = 0; i < total; i++) + { + element = array.pop(); + array.unshift(element); + } + + return element; +}; + +module.exports = RotateRight; + + +/***/ }), + +/***/ 82011: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Tests if the start and end indexes are a safe range for the given array. + * + * @function Phaser.Utils.Array.SafeRange + * @since 3.4.0 + * + * @param {array} array - The array to check. + * @param {number} startIndex - The start index. + * @param {number} endIndex - The end index. + * @param {boolean} [throwError=false] - Throw an error if the range is out of bounds. + * + * @return {boolean} True if the range is safe, otherwise false. + */ +var SafeRange = function (array, startIndex, endIndex, throwError) +{ + var len = array.length; + + if (startIndex < 0 || + startIndex >= len || + startIndex >= endIndex || + endIndex > len) + { + if (throwError) + { + throw new Error('Range Error: Values outside acceptable range'); + } + + return false; + } + else + { + return true; + } +}; + +module.exports = SafeRange; + + +/***/ }), + +/***/ 89545: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Moves the given element to the bottom of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.SendToBack + * @since 3.4.0 + * + * @param {array} array - The array. + * @param {*} item - The element to move. + * + * @return {*} The element that was moved. + */ +var SendToBack = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex !== -1 && currentIndex > 0) + { + array.splice(currentIndex, 1); + array.unshift(item); + } + + return item; +}; + +module.exports = SendToBack; + + +/***/ }), + +/***/ 17810: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var SafeRange = __webpack_require__(82011); + +/** + * Scans the array for elements with the given property. If found, the property is set to the `value`. + * + * For example: `SetAll('visible', true)` would set all elements that have a `visible` property to `false`. + * + * Optionally you can specify a start and end index. For example if the array had 100 elements, + * and you set `startIndex` to 0 and `endIndex` to 50, it would update only the first 50 elements. + * + * @function Phaser.Utils.Array.SetAll + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} property - The property to test for on each array element. + * @param {*} value - The value to set the property to. + * @param {number} [startIndex] - An optional start index to search from. + * @param {number} [endIndex] - An optional end index to search to. + * + * @return {array} The input array. + */ +var SetAll = function (array, property, value, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + if (SafeRange(array, startIndex, endIndex)) + { + for (var i = startIndex; i < endIndex; i++) + { + var entry = array[i]; + + if (entry.hasOwnProperty(property)) + { + entry[property] = value; + } + } + } + + return array; +}; + +module.exports = SetAll; + + +/***/ }), + +/***/ 33680: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Shuffles the contents of the given array using the Fisher-Yates implementation. + * + * The original array is modified directly and returned. + * + * @function Phaser.Utils.Array.Shuffle + * @since 3.0.0 + * + * @generic T + * @genericUse {T[]} - [array,$return] + * + * @param {T[]} array - The array to shuffle. This array is modified in place. + * + * @return {T[]} The shuffled array. + */ +var Shuffle = function (array) +{ + for (var i = array.length - 1; i > 0; i--) + { + var j = Math.floor(Math.random() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + return array; +}; + +module.exports = Shuffle; + + +/***/ }), + +/***/ 90126: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes the given array and runs a numeric sort on it, ignoring any non-digits that + * may be in the entries. + * + * You should only run this on arrays containing strings. + * + * @function Phaser.Utils.Array.SortByDigits + * @since 3.50.0 + * + * @param {string[]} array - The input array of strings. + * + * @return {string[]} The sorted input array. + */ +var SortByDigits = function (array) +{ + var re = /\D/g; + + array.sort(function (a, b) + { + return (parseInt(a.replace(re, ''), 10) - parseInt(b.replace(re, ''), 10)); + }); + + return array; +}; + +module.exports = SortByDigits; + + +/***/ }), + +/***/ 19133: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Removes a single item from an array and returns it without creating gc, like the native splice does. + * Based on code by Mike Reinstein. + * + * @function Phaser.Utils.Array.SpliceOne + * @since 3.0.0 + * + * @param {array} array - The array to splice from. + * @param {number} index - The index of the item which should be spliced. + * + * @return {*} The item which was spliced (removed). + */ +var SpliceOne = function (array, index) +{ + if (index >= array.length) + { + return; + } + + var len = array.length - 1; + + var item = array[index]; + + for (var i = index; i < len; i++) + { + array[i] = array[i + 1]; + } + + array.length = len; + + return item; +}; + +module.exports = SpliceOne; + + +/***/ }), + +/***/ 19186: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @author Angry Bytes (and contributors) + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Device = __webpack_require__(82264); + +/** + * The comparator function. + * + * @ignore + * + * @param {*} a - The first item to test. + * @param {*} b - The second itemt to test. + * + * @return {boolean} True if they localCompare, otherwise false. + */ +function Compare (a, b) +{ + return String(a).localeCompare(b); +} + +/** + * Process the array contents. + * + * @ignore + * + * @param {array} array - The array to process. + * @param {function} compare - The comparison function. + * + * @return {array} - The processed array. + */ +function Process (array, compare) +{ + // Short-circuit when there's nothing to sort. + var len = array.length; + + if (len <= 1) + { + return array; + } + + // Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc. + // Chunks are the size of the left or right hand in merge sort. + // Stop when the left-hand covers all of the array. + var buffer = new Array(len); + + for (var chk = 1; chk < len; chk *= 2) + { + RunPass(array, compare, chk, buffer); + + var tmp = array; + + array = buffer; + + buffer = tmp; + } + + return array; +} + +/** + * Run a single pass with the given chunk size. + * + * @ignore + * + * @param {array} arr - The array to run the pass on. + * @param {function} comp - The comparison function. + * @param {number} chk - The number of iterations. + * @param {array} result - The array to store the result in. + */ +function RunPass (arr, comp, chk, result) +{ + var len = arr.length; + var i = 0; + + // Step size / double chunk size. + var dbl = chk * 2; + + // Bounds of the left and right chunks. + var l, r, e; + + // Iterators over the left and right chunk. + var li, ri; + + // Iterate over pairs of chunks. + for (l = 0; l < len; l += dbl) + { + r = l + chk; + e = r + chk; + + if (r > len) + { + r = len; + } + + if (e > len) + { + e = len; + } + + // Iterate both chunks in parallel. + li = l; + ri = r; + + while (true) + { + // Compare the chunks. + if (li < r && ri < e) + { + // This works for a regular `sort()` compatible comparator, + // but also for a simple comparator like: `a > b` + if (comp(arr[li], arr[ri]) <= 0) + { + result[i++] = arr[li++]; + } + else + { + result[i++] = arr[ri++]; + } + } + else if (li < r) + { + // Nothing to compare, just flush what's left. + result[i++] = arr[li++]; + } + else if (ri < e) + { + result[i++] = arr[ri++]; + } + else + { + // Both iterators are at the chunk ends. + break; + } + } + } +} + +/** + * An in-place stable array sort, because `Array#sort()` is not guaranteed stable. + * + * This is an implementation of merge sort, without recursion. + * + * Function based on the Two-Screen/stable sort 0.1.8 from https://github.com/Two-Screen/stable + * + * @function Phaser.Utils.Array.StableSort + * @since 3.0.0 + * + * @param {array} array - The input array to be sorted. + * @param {function} [compare] - The comparison function. + * + * @return {array} The sorted result. + */ +var StableSort = function (array, compare) +{ + if (compare === undefined) { compare = Compare; } + + // Short-circuit when there's nothing to sort. + if (!array || array.length < 2) + { + return array; + } + + if (Device.features.stableSort) + { + return array.sort(compare); + } + + var result = Process(array, compare); + + // This simply copies back if the result isn't in the original array, which happens on an odd number of passes. + if (result !== array) + { + RunPass(result, null, array.length, array); + } + + return array; +}; + +module.exports = StableSort; + + +/***/ }), + +/***/ 25630: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Swaps the position of two elements in the given array. + * The elements must exist in the same array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.Swap + * @since 3.4.0 + * + * @param {array} array - The input array. + * @param {*} item1 - The first element to swap. + * @param {*} item2 - The second element to swap. + * + * @return {array} The input array. + */ +var Swap = function (array, item1, item2) +{ + if (item1 === item2) + { + return array; + } + + var index1 = array.indexOf(item1); + var index2 = array.indexOf(item2); + + if (index1 < 0 || index2 < 0) + { + throw new Error('Supplied items must be elements of the same array'); + } + + array[index1] = item2; + array[index2] = item1; + + return array; +}; + +module.exports = Swap; + + +/***/ }), + +/***/ 37105: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils.Array + */ + +module.exports = { + + Matrix: __webpack_require__(54915), + + Add: __webpack_require__(71146), + AddAt: __webpack_require__(51067), + BringToTop: __webpack_require__(66905), + CountAllMatching: __webpack_require__(21612), + Each: __webpack_require__(95428), + EachInRange: __webpack_require__(36914), + FindClosestInSorted: __webpack_require__(81957), + Flatten: __webpack_require__(43491), + GetAll: __webpack_require__(46710), + GetFirst: __webpack_require__(58731), + GetRandom: __webpack_require__(26546), + MoveDown: __webpack_require__(70864), + MoveTo: __webpack_require__(69693), + MoveUp: __webpack_require__(40853), + MoveAbove: __webpack_require__(85835), + MoveBelow: __webpack_require__(83371), + NumberArray: __webpack_require__(20283), + NumberArrayStep: __webpack_require__(593), + QuickSelect: __webpack_require__(43886), + Range: __webpack_require__(88492), + Remove: __webpack_require__(72905), + RemoveAt: __webpack_require__(60248), + RemoveBetween: __webpack_require__(81409), + RemoveRandomElement: __webpack_require__(31856), + Replace: __webpack_require__(42169), + RotateLeft: __webpack_require__(86003), + RotateRight: __webpack_require__(49498), + SafeRange: __webpack_require__(82011), + SendToBack: __webpack_require__(89545), + SetAll: __webpack_require__(17810), + Shuffle: __webpack_require__(33680), + SortByDigits: __webpack_require__(90126), + SpliceOne: __webpack_require__(19133), + StableSort: __webpack_require__(19186), + Swap: __webpack_require__(25630) + +}; + + +/***/ }), + +/***/ 86922: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Checks if an array can be used as a matrix. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.CheckMatrix + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix] + * + * @param {T[][]} [matrix] - The array to check. + * + * @return {boolean} `true` if the given `matrix` array is a valid matrix. + */ +var CheckMatrix = function (matrix) +{ + if (!Array.isArray(matrix) || !Array.isArray(matrix[0])) + { + return false; + } + + // How long is the first row? + var size = matrix[0].length; + + // Validate the rest of the rows are the same length + for (var i = 1; i < matrix.length; i++) + { + if (matrix[i].length !== size) + { + return false; + } + } + + return true; +}; + +module.exports = CheckMatrix; + + +/***/ }), + +/***/ 63362: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Pad = __webpack_require__(41836); +var CheckMatrix = __webpack_require__(86922); + +/** + * Generates a string (which you can pass to console.log) from the given Array Matrix. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.MatrixToString + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix] + * + * @param {T[][]} [matrix] - A 2-dimensional array. + * + * @return {string} A string representing the matrix. + */ +var MatrixToString = function (matrix) +{ + var str = ''; + + if (!CheckMatrix(matrix)) + { + return str; + } + + for (var r = 0; r < matrix.length; r++) + { + for (var c = 0; c < matrix[r].length; c++) + { + var cell = matrix[r][c].toString(); + + if (cell !== 'undefined') + { + str += Pad(cell, 2); + } + else + { + str += '?'; + } + + if (c < matrix[r].length - 1) + { + str += ' |'; + } + } + + if (r < matrix.length - 1) + { + str += '\n'; + + for (var i = 0; i < matrix[r].length; i++) + { + str += '---'; + + if (i < matrix[r].length - 1) + { + str += '+'; + } + } + + str += '\n'; + } + + } + + return str; +}; + +module.exports = MatrixToString; + + +/***/ }), + +/***/ 92598: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Reverses the columns in the given Array Matrix. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.ReverseColumns + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array matrix to reverse the columns for. + * + * @return {T[][]} The column reversed matrix. + */ +var ReverseColumns = function (matrix) +{ + return matrix.reverse(); +}; + +module.exports = ReverseColumns; + + +/***/ }), + +/***/ 21224: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Reverses the rows in the given Array Matrix. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.ReverseRows + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array matrix to reverse the rows for. + * + * @return {T[][]} The column reversed matrix. + */ +var ReverseRows = function (matrix) +{ + for (var i = 0; i < matrix.length; i++) + { + matrix[i].reverse(); + } + + return matrix; +}; + +module.exports = ReverseRows; + + +/***/ }), + +/***/ 98717: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateMatrix = __webpack_require__(37829); + +/** + * Rotates the array matrix 180 degrees. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.Rotate180 + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array to rotate. + * + * @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix. + */ +var Rotate180 = function (matrix) +{ + return RotateMatrix(matrix, 180); +}; + +module.exports = Rotate180; + + +/***/ }), + +/***/ 44657: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateMatrix = __webpack_require__(37829); + +/** + * Rotates the array matrix to the left (or 90 degrees) + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.RotateLeft + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array to rotate. + * @param {number} [amount=1] - The number of times to rotate the matrix. + * + * @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix. + */ +var RotateLeft = function (matrix, amount) +{ + if (amount === undefined) { amount = 1; } + + for (var i = 0; i < amount; i++) + { + matrix = RotateMatrix(matrix, 90); + } + + return matrix; +}; + +module.exports = RotateLeft; + + +/***/ }), + +/***/ 37829: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var CheckMatrix = __webpack_require__(86922); +var TransposeMatrix = __webpack_require__(2429); + +/** + * Rotates the array matrix based on the given rotation value. + * + * The value can be given in degrees: 90, -90, 270, -270 or 180, + * or a string command: `rotateLeft`, `rotateRight` or `rotate180`. + * + * Based on the routine from {@link http://jsfiddle.net/MrPolywhirl/NH42z/}. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.RotateMatrix + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array to rotate. + * @param {(number|string)} [direction=90] - The amount to rotate the matrix by. + * + * @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix. + */ +var RotateMatrix = function (matrix, direction) +{ + if (direction === undefined) { direction = 90; } + + if (!CheckMatrix(matrix)) + { + return null; + } + + if (typeof direction !== 'string') + { + direction = ((direction % 360) + 360) % 360; + } + + if (direction === 90 || direction === -270 || direction === 'rotateLeft') + { + matrix = TransposeMatrix(matrix); + matrix.reverse(); + } + else if (direction === -90 || direction === 270 || direction === 'rotateRight') + { + matrix.reverse(); + matrix = TransposeMatrix(matrix); + } + else if (Math.abs(direction) === 180 || direction === 'rotate180') + { + for (var i = 0; i < matrix.length; i++) + { + matrix[i].reverse(); + } + + matrix.reverse(); + } + + return matrix; +}; + +module.exports = RotateMatrix; + + +/***/ }), + +/***/ 92632: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateMatrix = __webpack_require__(37829); + +/** + * Rotates the array matrix to the left (or -90 degrees) + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.RotateRight + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array to rotate. + * @param {number} [amount=1] - The number of times to rotate the matrix. + * + * @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix. + */ +var RotateRight = function (matrix, amount) +{ + if (amount === undefined) { amount = 1; } + + for (var i = 0; i < amount; i++) + { + matrix = RotateMatrix(matrix, -90); + } + + return matrix; +}; + +module.exports = RotateRight; + + +/***/ }), + +/***/ 69512: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var RotateLeft = __webpack_require__(86003); +var RotateRight = __webpack_require__(49498); + +/** + * Translates the given Array Matrix by shifting each column and row the + * amount specified. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.Translate + * @since 3.50.0 + * + * @generic T + * @genericUse {T[][]} - [matrix,$return] + * + * @param {T[][]} [matrix] - The array matrix to translate. + * @param {number} [x=0] - The amount to horizontally translate the matrix by. + * @param {number} [y=0] - The amount to vertically translate the matrix by. + * + * @return {T[][]} The translated matrix. + */ +var TranslateMatrix = function (matrix, x, y) +{ + if (x === undefined) { x = 0; } + if (y === undefined) { y = 0; } + + // Vertical translation + + if (y !== 0) + { + if (y < 0) + { + // Shift Up + RotateLeft(matrix, Math.abs(y)); + } + else + { + // Shift Down + RotateRight(matrix, y); + } + } + + // Horizontal translation + + if (x !== 0) + { + for (var i = 0; i < matrix.length; i++) + { + var row = matrix[i]; + + if (x < 0) + { + RotateLeft(row, Math.abs(x)); + } + else + { + RotateRight(row, x); + } + } + } + + return matrix; +}; + +module.exports = TranslateMatrix; + + +/***/ }), + +/***/ 2429: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Transposes the elements of the given matrix (array of arrays). + * + * The transpose of a matrix is a new matrix whose rows are the columns of the original. + * + * A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows) + * have the same length. There must be at least two rows. This is an example matrix: + * + * ``` + * [ + * [ 1, 1, 1, 1, 1, 1 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 2, 0, 1, 2, 0, 4 ], + * [ 2, 0, 3, 4, 0, 4 ], + * [ 2, 0, 0, 0, 0, 4 ], + * [ 3, 3, 3, 3, 3, 3 ] + * ] + * ``` + * + * @function Phaser.Utils.Array.Matrix.TransposeMatrix + * @since 3.0.0 + * + * @generic T + * @genericUse {T[][]} - [array,$return] + * + * @param {T[][]} [array] - The array matrix to transpose. + * + * @return {T[][]} A new array matrix which is a transposed version of the given array. + */ +var TransposeMatrix = function (array) +{ + var sourceRowCount = array.length; + var sourceColCount = array[0].length; + + var result = new Array(sourceColCount); + + for (var i = 0; i < sourceColCount; i++) + { + result[i] = new Array(sourceRowCount); + + for (var j = sourceRowCount - 1; j > -1; j--) + { + result[i][j] = array[j][i]; + } + } + + return result; +}; + +module.exports = TransposeMatrix; + + +/***/ }), + +/***/ 54915: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils.Array.Matrix + */ + +module.exports = { + + CheckMatrix: __webpack_require__(86922), + MatrixToString: __webpack_require__(63362), + ReverseColumns: __webpack_require__(92598), + ReverseRows: __webpack_require__(21224), + Rotate180: __webpack_require__(98717), + RotateLeft: __webpack_require__(44657), + RotateMatrix: __webpack_require__(37829), + RotateRight: __webpack_require__(92632), + Translate: __webpack_require__(69512), + TransposeMatrix: __webpack_require__(2429) + +}; + + +/***/ }), + +/***/ 71334: +/***/ ((module) => { + +/** + * @author Niklas von Hertzen (https://github.com/niklasvh/base64-arraybuffer) + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +/** + * Converts an ArrayBuffer into a base64 string. + * + * The resulting string can optionally be a data uri if the `mediaType` argument is provided. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs for more details. + * + * @function Phaser.Utils.Base64.ArrayBufferToBase64 + * @since 3.18.0 + * + * @param {ArrayBuffer} arrayBuffer - The Array Buffer to encode. + * @param {string} [mediaType] - An optional media type, i.e. `audio/ogg` or `image/jpeg`. If included the resulting string will be a data URI. + * + * @return {string} The base64 encoded Array Buffer. + */ +var ArrayBufferToBase64 = function (arrayBuffer, mediaType) +{ + var bytes = new Uint8Array(arrayBuffer); + var len = bytes.length; + + var base64 = (mediaType) ? 'data:' + mediaType + ';base64,' : ''; + + for (var i = 0; i < len; i += 3) + { + base64 += chars[bytes[i] >> 2]; + base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; + base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; + base64 += chars[bytes[i + 2] & 63]; + } + + if ((len % 3) === 2) + { + base64 = base64.substring(0, base64.length - 1) + '='; + } + else if (len % 3 === 1) + { + base64 = base64.substring(0, base64.length - 2) + '=='; + } + + return base64; +}; + +module.exports = ArrayBufferToBase64; + + +/***/ }), + +/***/ 53134: +/***/ ((module) => { + +/** + * @author Niklas von Hertzen (https://github.com/niklasvh/base64-arraybuffer) + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +// Use a lookup table to find the index. +var lookup = new Uint8Array(256); + +for (var i = 0; i < chars.length; i++) +{ + lookup[chars.charCodeAt(i)] = i; +} + +/** + * Converts a base64 string, either with or without a data uri, into an Array Buffer. + * + * @function Phaser.Utils.Base64.Base64ToArrayBuffer + * @since 3.18.0 + * + * @param {string} base64 - The base64 string to be decoded. Can optionally contain a data URI header, which will be stripped out prior to decoding. + * + * @return {ArrayBuffer} An ArrayBuffer decoded from the base64 data. + */ +var Base64ToArrayBuffer = function (base64) +{ + // Is it a data uri? if so, strip the header away + base64 = base64.substr(base64.indexOf(',') + 1); + + var len = base64.length; + var bufferLength = len * 0.75; + var p = 0; + var encoded1; + var encoded2; + var encoded3; + var encoded4; + + if (base64[len - 1] === '=') + { + bufferLength--; + + if (base64[len - 2] === '=') + { + bufferLength--; + } + } + + var arrayBuffer = new ArrayBuffer(bufferLength); + var bytes = new Uint8Array(arrayBuffer); + + for (var i = 0; i < len; i += 4) + { + encoded1 = lookup[base64.charCodeAt(i)]; + encoded2 = lookup[base64.charCodeAt(i + 1)]; + encoded3 = lookup[base64.charCodeAt(i + 2)]; + encoded4 = lookup[base64.charCodeAt(i + 3)]; + + bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); + bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); + bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); + } + + return arrayBuffer; +}; + +module.exports = Base64ToArrayBuffer; + + +/***/ }), + +/***/ 65839: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils.Base64 + */ + +module.exports = { + + ArrayBufferToBase64: __webpack_require__(71334), + Base64ToArrayBuffer: __webpack_require__(53134) + +}; + + +/***/ }), + +/***/ 91799: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils + */ + +module.exports = { + + Array: __webpack_require__(37105), + Base64: __webpack_require__(65839), + Objects: __webpack_require__(1183), + String: __webpack_require__(31749), + NOOP: __webpack_require__(29747), + NULL: __webpack_require__(20242) + +}; + + +/***/ }), + +/***/ 41786: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Shallow Object Clone. Will not clone nested objects. + * + * @function Phaser.Utils.Objects.Clone + * @since 3.0.0 + * + * @param {object} obj - The object to clone. + * + * @return {object} A new object with the same properties as the input object. + */ +var Clone = function (obj) +{ + var clone = {}; + + for (var key in obj) + { + if (Array.isArray(obj[key])) + { + clone[key] = obj[key].slice(0); + } + else + { + clone[key] = obj[key]; + } + } + + return clone; +}; + +module.exports = Clone; + + +/***/ }), + +/***/ 62644: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Deep Copy the given object or array. + * + * @function Phaser.Utils.Objects.DeepCopy + * @since 3.50.0 + * + * @param {object} obj - The object to deep copy. + * + * @return {object} A deep copy of the original object. + */ +var DeepCopy = function (inObject) +{ + var outObject; + var value; + var key; + + if (typeof inObject !== 'object' || inObject === null) + { + // inObject is not an object + return inObject; + } + + // Create an array or object to hold the values + outObject = Array.isArray(inObject) ? [] : {}; + + for (key in inObject) + { + value = inObject[key]; + + // Recursively (deep) copy for nested objects, including arrays + outObject[key] = DeepCopy(value); + } + + return outObject; +}; + +module.exports = DeepCopy; + + +/***/ }), + +/***/ 79291: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var IsPlainObject = __webpack_require__(41212); + +// @param {boolean} deep - Perform a deep copy? +// @param {object} target - The target object to copy to. +// @return {object} The extended object. + +/** + * This is a slightly modified version of http://api.jquery.com/jQuery.extend/ + * + * @function Phaser.Utils.Objects.Extend + * @since 3.0.0 + * + * @param {...*} [args] - The objects that will be mixed. + * + * @return {object} The extended object. + */ +var Extend = function () +{ + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if (typeof target === 'boolean') + { + deep = target; + target = arguments[1] || {}; + + // skip the boolean and the target + i = 2; + } + + // extend Phaser if only one argument is passed + if (length === i) + { + target = this; + --i; + } + + for (; i < length; i++) + { + // Only deal with non-null/undefined values + if ((options = arguments[i]) != null) + { + // Extend the base object + for (name in options) + { + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target === copy) + { + continue; + } + + // Recurse if we're merging plain objects or arrays + if (deep && copy && (IsPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) + { + if (copyIsArray) + { + copyIsArray = false; + clone = src && Array.isArray(src) ? src : []; + } + else + { + clone = src && IsPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[name] = Extend(deep, clone, copy); + + // Don't bring in undefined values + } + else if (copy !== undefined) + { + target[name] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +module.exports = Extend; + + +/***/ }), + +/***/ 23568: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var MATH = __webpack_require__(75508); +var GetValue = __webpack_require__(35154); + +/** + * Retrieves a value from an object. Allows for more advanced selection options, including: + * + * Allowed types: + * + * Explicit: + * { + * x: 4 + * } + * + * From function + * { + * x: function () + * } + * + * Randomly pick one element from the array + * { + * x: [a, b, c, d, e, f] + * } + * + * Random integer between min and max: + * { + * x: { randInt: [min, max] } + * } + * + * Random float between min and max: + * { + * x: { randFloat: [min, max] } + * } + * + * + * @function Phaser.Utils.Objects.GetAdvancedValue + * @since 3.0.0 + * + * @param {object} source - The object to retrieve the value from. + * @param {string} key - The name of the property to retrieve from the object. If a property is nested, the names of its preceding properties should be separated by a dot (`.`) - `banner.hideBanner` would return the value of the `hideBanner` property from the object stored in the `banner` property of the `source` object. + * @param {*} defaultValue - The value to return if the `key` isn't found in the `source` object. + * + * @return {*} The value of the requested key. + */ +var GetAdvancedValue = function (source, key, defaultValue) +{ + var value = GetValue(source, key, null); + + if (value === null) + { + return defaultValue; + } + else if (Array.isArray(value)) + { + return MATH.RND.pick(value); + } + else if (typeof value === 'object') + { + if (value.hasOwnProperty('randInt')) + { + return MATH.RND.integerInRange(value.randInt[0], value.randInt[1]); + } + else if (value.hasOwnProperty('randFloat')) + { + return MATH.RND.realInRange(value.randFloat[0], value.randFloat[1]); + } + } + else if (typeof value === 'function') + { + return value(key); + } + + return value; +}; + +module.exports = GetAdvancedValue; + + +/***/ }), + +/***/ 95540: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Finds the key within the top level of the {@link source} object, or returns {@link defaultValue} + * + * @function Phaser.Utils.Objects.GetFastValue + * @since 3.0.0 + * + * @param {object} source - The object to search + * @param {string} key - The key for the property on source. Must exist at the top level of the source object (no periods) + * @param {*} [defaultValue] - The default value to use if the key does not exist. + * + * @return {*} The value if found; otherwise, defaultValue (null if none provided) + */ +var GetFastValue = function (source, key, defaultValue) +{ + var t = typeof(source); + + if (!source || t === 'number' || t === 'string') + { + return defaultValue; + } + else if (source.hasOwnProperty(key) && source[key] !== undefined) + { + return source[key]; + } + else + { + return defaultValue; + } +}; + +module.exports = GetFastValue; + + +/***/ }), + +/***/ 82840: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var GetValue = __webpack_require__(35154); +var Clamp = __webpack_require__(45319); + +/** + * Retrieves and clamps a numerical value from an object. + * + * @function Phaser.Utils.Objects.GetMinMaxValue + * @since 3.0.0 + * + * @param {object} source - The object to retrieve the value from. + * @param {string} key - The name of the property to retrieve from the object. If a property is nested, the names of its preceding properties should be separated by a dot (`.`). + * @param {number} min - The minimum value which can be returned. + * @param {number} max - The maximum value which can be returned. + * @param {number} defaultValue - The value to return if the property doesn't exist. It's also constrained to the given bounds. + * + * @return {number} The clamped value from the `source` object. + */ +var GetMinMaxValue = function (source, key, min, max, defaultValue) +{ + if (defaultValue === undefined) { defaultValue = min; } + + var value = GetValue(source, key, defaultValue); + + return Clamp(value, min, max); +}; + +module.exports = GetMinMaxValue; + + +/***/ }), + +/***/ 35154: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Retrieves a value from an object, or an alternative object, falling to a back-up default value if not found. + * + * The key is a string, which can be split based on the use of the period character. + * + * For example: + * + * ```javascript + * const source = { + * lives: 3, + * render: { + * screen: { + * width: 1024 + * } + * } + * } + * + * const lives = GetValue(source, 'lives', 1); + * const width = GetValue(source, 'render.screen.width', 800); + * const height = GetValue(source, 'render.screen.height', 600); + * ``` + * + * In the code above, `lives` will be 3 because it's defined at the top level of `source`. + * The `width` value will be 1024 because it can be found inside the `render.screen` object. + * The `height` value will be 600, the default value, because it is missing from the `render.screen` object. + * + * @function Phaser.Utils.Objects.GetValue + * @since 3.0.0 + * + * @param {object} source - The primary object to try to retrieve the value from. If not found in here, `altSource` is checked. + * @param {string} key - The name of the property to retrieve from the object. If a property is nested, the names of its preceding properties should be separated by a dot (`.`) - `banner.hideBanner` would return the value of the `hideBanner` property from the object stored in the `banner` property of the `source` object. + * @param {*} defaultValue - The value to return if the `key` isn't found in the `source` object. + * @param {object} [altSource] - An alternative object to retrieve the value from. If the property exists in `source` then `altSource` will not be used. + * + * @return {*} The value of the requested key. + */ +var GetValue = function (source, key, defaultValue, altSource) +{ + if ((!source && !altSource) || typeof source === 'number') + { + return defaultValue; + } + else if (source && source.hasOwnProperty(key)) + { + return source[key]; + } + else if (altSource && altSource.hasOwnProperty(key)) + { + return altSource[key]; + } + else if (key.indexOf('.') !== -1) + { + var keys = key.split('.'); + var parentA = source; + var parentB = altSource; + var valueA = defaultValue; + var valueB = defaultValue; + var valueAFound = true; + var valueBFound = true; + + // Use for loop here so we can break early + for (var i = 0; i < keys.length; i++) + { + if (parentA && parentA.hasOwnProperty(keys[i])) + { + // Yes parentA has a key property, let's carry on down + valueA = parentA[keys[i]]; + parentA = parentA[keys[i]]; + } + else + { + valueAFound = false; + } + + if (parentB && parentB.hasOwnProperty(keys[i])) + { + // Yes parentB has a key property, let's carry on down + valueB = parentB[keys[i]]; + parentB = parentB[keys[i]]; + } + else + { + valueBFound = false; + } + } + + if (valueAFound) + { + return valueA; + } + else if (valueBFound) + { + return valueB; + } + else + { + return defaultValue; + } + } + else + { + return defaultValue; + } +}; + +module.exports = GetValue; + + +/***/ }), + +/***/ 69036: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Verifies that an object contains all requested keys + * + * @function Phaser.Utils.Objects.HasAll + * @since 3.0.0 + * + * @param {object} source - an object on which to check for key existence + * @param {string[]} keys - an array of keys to ensure the source object contains + * + * @return {boolean} true if the source object contains all keys, false otherwise. + */ +var HasAll = function (source, keys) +{ + for (var i = 0; i < keys.length; i++) + { + if (!source.hasOwnProperty(keys[i])) + { + return false; + } + } + + return true; +}; + +module.exports = HasAll; + + +/***/ }), + +/***/ 1985: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Verifies that an object contains at least one of the requested keys + * + * @function Phaser.Utils.Objects.HasAny + * @since 3.0.0 + * + * @param {object} source - an object on which to check for key existence + * @param {string[]} keys - an array of keys to search the object for + * + * @return {boolean} true if the source object contains at least one of the keys, false otherwise + */ +var HasAny = function (source, keys) +{ + for (var i = 0; i < keys.length; i++) + { + if (source.hasOwnProperty(keys[i])) + { + return true; + } + } + + return false; +}; + +module.exports = HasAny; + + +/***/ }), + +/***/ 97022: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Determine whether the source object has a property with the specified key. + * + * @function Phaser.Utils.Objects.HasValue + * @since 3.0.0 + * + * @param {object} source - The source object to be checked. + * @param {string} key - The property to check for within the object + * + * @return {boolean} `true` if the provided `key` exists on the `source` object, otherwise `false`. + */ +var HasValue = function (source, key) +{ + return (source.hasOwnProperty(key)); +}; + +module.exports = HasValue; + + +/***/ }), + +/***/ 41212: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * This is a slightly modified version of jQuery.isPlainObject. + * A plain object is an object whose internal class property is [object Object]. + * + * @function Phaser.Utils.Objects.IsPlainObject + * @since 3.0.0 + * + * @param {object} obj - The object to inspect. + * + * @return {boolean} `true` if the object is plain, otherwise `false`. + */ +var IsPlainObject = function (obj) +{ + // Not plain objects: + // - Any object or value whose internal [[Class]] property is not "[object Object]" + // - DOM nodes + // - window + if (!obj || typeof(obj) !== 'object' || obj.nodeType || obj === obj.window) + { + return false; + } + + // Support: Firefox <20 + // The try/catch suppresses exceptions thrown when attempting to access + // the "constructor" property of certain host objects, ie. |window.location| + // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 + try + { + if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) + { + return false; + } + } + catch (e) + { + return false; + } + + // If the function hasn't returned already, we're confident that + // |obj| is a plain object, created by {} or constructed with new Object + return true; +}; + +module.exports = IsPlainObject; + + +/***/ }), + +/***/ 46975: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clone = __webpack_require__(41786); + +/** + * Creates a new Object using all values from obj1 and obj2. + * If a value exists in both obj1 and obj2, the value in obj1 is used. + * + * This is only a shallow copy. Deeply nested objects are not cloned, so be sure to only use this + * function on shallow objects. + * + * @function Phaser.Utils.Objects.Merge + * @since 3.0.0 + * + * @param {object} obj1 - The first object. + * @param {object} obj2 - The second object. + * + * @return {object} A new object containing the union of obj1's and obj2's properties. + */ +var Merge = function (obj1, obj2) +{ + var clone = Clone(obj1); + + for (var key in obj2) + { + if (!clone.hasOwnProperty(key)) + { + clone[key] = obj2[key]; + } + } + + return clone; +}; + +module.exports = Merge; + + +/***/ }), + +/***/ 269: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var Clone = __webpack_require__(41786); + +/** + * Creates a new Object using all values from obj1. + * + * Then scans obj2. If a property is found in obj2 that *also* exists in obj1, the value from obj2 is used, otherwise the property is skipped. + * + * @function Phaser.Utils.Objects.MergeRight + * @since 3.0.0 + * + * @param {object} obj1 - The first object to merge. + * @param {object} obj2 - The second object to merge. Keys from this object which also exist in `obj1` will be copied to `obj1`. + * + * @return {object} The merged object. `obj1` and `obj2` are not modified. + */ +var MergeRight = function (obj1, obj2) +{ + var clone = Clone(obj1); + + for (var key in obj2) + { + if (clone.hasOwnProperty(key)) + { + clone[key] = obj2[key]; + } + } + + return clone; +}; + +module.exports = MergeRight; + + +/***/ }), + +/***/ 18254: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +var HasValue = __webpack_require__(97022); + +/** + * Returns a new object that only contains the `keys` that were found on the object provided. + * If no `keys` are found, an empty object is returned. + * + * @function Phaser.Utils.Objects.Pick + * @since 3.18.0 + * + * @param {object} object - The object to pick the provided keys from. + * @param {array} keys - An array of properties to retrieve from the provided object. + * + * @return {object} A new object that only contains the `keys` that were found on the provided object. If no `keys` were found, an empty object will be returned. + */ +var Pick = function (object, keys) +{ + var obj = {}; + + for (var i = 0; i < keys.length; i++) + { + var key = keys[i]; + + if (HasValue(object, key)) + { + obj[key] = object[key]; + } + } + + return obj; +}; + +module.exports = Pick; + + +/***/ }), + +/***/ 61622: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Sets a value in an object, allowing for dot notation to control the depth of the property. + * + * For example: + * + * ```javascript + * var data = { + * world: { + * position: { + * x: 200, + * y: 100 + * } + * } + * }; + * + * SetValue(data, 'world.position.y', 300); + * + * console.log(data.world.position.y); // 300 + * ``` + * + * @function Phaser.Utils.Objects.SetValue + * @since 3.17.0 + * + * @param {object} source - The object to set the value in. + * @param {string} key - The name of the property in the object. If a property is nested, the names of its preceding properties should be separated by a dot (`.`) + * @param {any} value - The value to set into the property, if found in the source object. + * + * @return {boolean} `true` if the property key was valid and the value was set, otherwise `false`. + */ +var SetValue = function (source, key, value) +{ + if (!source || typeof source === 'number') + { + return false; + } + else if (source.hasOwnProperty(key)) + { + source[key] = value; + + return true; + } + else if (key.indexOf('.') !== -1) + { + var keys = key.split('.'); + var parent = source; + var prev = source; + + // Use for loop here so we can break early + for (var i = 0; i < keys.length; i++) + { + if (parent.hasOwnProperty(keys[i])) + { + // Yes it has a key property, let's carry on down + prev = parent; + parent = parent[keys[i]]; + } + else + { + return false; + } + } + + prev[keys[keys.length - 1]] = value; + + return true; + } + + return false; +}; + +module.exports = SetValue; + + +/***/ }), + +/***/ 1183: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils.Objects + */ + +module.exports = { + + Clone: __webpack_require__(41786), + DeepCopy: __webpack_require__(62644), + Extend: __webpack_require__(79291), + GetAdvancedValue: __webpack_require__(23568), + GetFastValue: __webpack_require__(95540), + GetMinMaxValue: __webpack_require__(82840), + GetValue: __webpack_require__(35154), + HasAll: __webpack_require__(69036), + HasAny: __webpack_require__(1985), + HasValue: __webpack_require__(97022), + IsPlainObject: __webpack_require__(41212), + Merge: __webpack_require__(46975), + MergeRight: __webpack_require__(269), + Pick: __webpack_require__(18254), + SetValue: __webpack_require__(61622) + +}; + + +/***/ }), + +/***/ 27902: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes a string and replaces instances of markers with values in the given array. + * The markers take the form of `%1`, `%2`, etc. I.e.: + * + * `Format("The %1 is worth %2 gold", [ 'Sword', 500 ])` + * + * @function Phaser.Utils.String.Format + * @since 3.0.0 + * + * @param {string} string - The string containing the replacement markers. + * @param {array} values - An array containing values that will replace the markers. If no value exists an empty string is inserted instead. + * + * @return {string} The string containing replaced values. + */ +var Format = function (string, values) +{ + return string.replace(/%([0-9]+)/g, function (s, n) + { + return values[Number(n) - 1]; + }); +}; + +module.exports = Format; + + +/***/ }), + +/***/ 41836: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes the given string and pads it out, to the length required, using the character + * specified. For example if you need a string to be 6 characters long, you can call: + * + * `pad('bob', 6, '-', 2)` + * + * This would return: `bob---` as it has padded it out to 6 characters, using the `-` on the right. + * + * You can also use it to pad numbers (they are always returned as strings): + * + * `pad(512, 6, '0', 1)` + * + * Would return: `000512` with the string padded to the left. + * + * If you don't specify a direction it'll pad to both sides: + * + * `pad('c64', 7, '*')` + * + * Would return: `**c64**` + * + * @function Phaser.Utils.String.Pad + * @since 3.0.0 + * + * @param {string|number|object} str - The target string. `toString()` will be called on the string, which means you can also pass in common data types like numbers. + * @param {number} [len=0] - The number of characters to be added. + * @param {string} [pad=" "] - The string to pad it out with (defaults to a space). + * @param {number} [dir=3] - The direction dir = 1 (left), 2 (right), 3 (both). + * + * @return {string} The padded string. + */ +var Pad = function (str, len, pad, dir) +{ + if (len === undefined) { len = 0; } + if (pad === undefined) { pad = ' '; } + if (dir === undefined) { dir = 3; } + + str = str.toString(); + + var padlen = 0; + + if (len + 1 >= str.length) + { + switch (dir) + { + case 1: + str = new Array(len + 1 - str.length).join(pad) + str; + break; + + case 3: + var right = Math.ceil((padlen = len - str.length) / 2); + var left = padlen - right; + str = new Array(left + 1).join(pad) + str + new Array(right + 1).join(pad); + break; + + default: + str = str + new Array(len + 1 - str.length).join(pad); + break; + } + } + + return str; +}; + +module.exports = Pad; + + +/***/ }), + +/***/ 33628: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes a string and removes the character at the given index. + * + * The index is zero based. + * + * @function Phaser.Utils.String.RemoveAt + * @since 3.50.0 + * + * @param {string} string - The string to be worked on. + * @param {number} index - The index of the character to be removed. This value is zero-based. + * + * @return {string} The modified string. + */ +var RemoveAt = function (string, index) +{ + if (index === 0) + { + return string.slice(1); + } + else + { + return string.slice(0, index) + string.slice(index + 1); + } +}; + +module.exports = RemoveAt; + + +/***/ }), + +/***/ 27671: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Takes the given string and reverses it, returning the reversed string. + * For example if given the string `Atari 520ST` it would return `TS025 iratA`. + * + * @function Phaser.Utils.String.Reverse + * @since 3.0.0 + * + * @param {string} string - The string to be reversed. + * + * @return {string} The reversed string. + */ +var Reverse = function (string) +{ + return string.split('').reverse().join(''); +}; + +module.exports = Reverse; + + +/***/ }), + +/***/ 45650: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Creates and returns an RFC4122 version 4 compliant UUID. + * + * The string is in the form: `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx` where each `x` is replaced with a random + * hexadecimal digit from 0 to f, and `y` is replaced with a random hexadecimal digit from 8 to b. + * + * @function Phaser.Utils.String.UUID + * @since 3.12.0 + * + * @return {string} The UUID string. + */ +var UUID = function () +{ + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) + { + var r = Math.random() * 16 | 0; + var v = (c === 'x') ? r : (r & 0x3 | 0x8); + + return v.toString(16); + }); +}; + +module.exports = UUID; + + +/***/ }), + +/***/ 35355: +/***/ ((module) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * Capitalizes the first letter of a string if there is one. + * @example + * UppercaseFirst('abc'); + * // returns 'Abc' + * @example + * UppercaseFirst('the happy family'); + * // returns 'The happy family' + * @example + * UppercaseFirst(''); + * // returns '' + * + * @function Phaser.Utils.String.UppercaseFirst + * @since 3.0.0 + * + * @param {string} str - The string to capitalize. + * + * @return {string} A new string, same as the first, but with the first letter capitalized. + */ +var UppercaseFirst = function (str) +{ + return str && str[0].toUpperCase() + str.slice(1); +}; + +module.exports = UppercaseFirst; + + +/***/ }), + +/***/ 31749: +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** + * @author Richard Davey + * @copyright 2013-2025 Phaser Studio Inc. + * @license {@link https://opensource.org/licenses/MIT|MIT License} + */ + +/** + * @namespace Phaser.Utils.String + */ + +module.exports = { + + Format: __webpack_require__(27902), + Pad: __webpack_require__(41836), + RemoveAt: __webpack_require__(33628), + Reverse: __webpack_require__(27671), + UppercaseFirst: __webpack_require__(35355), + UUID: __webpack_require__(45650) + +}; + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __webpack_require__(85454); +/******/ +/******/ return __webpack_exports__; +/******/ })() +; +}); \ No newline at end of file diff --git a/spine-ts/spine-phaser-v4/example/assets/raptor-pma.atlas b/spine-ts/spine-phaser-v4/example/assets/raptor-pma.atlas new file mode 100644 index 000000000..456015eaf --- /dev/null +++ b/spine-ts/spine-phaser-v4/example/assets/raptor-pma.atlas @@ -0,0 +1,94 @@ +raptor-pma.png + size: 1024, 512 + filter: Linear, Linear + pma: true + scale: 0.5 +back-arm + bounds: 895, 295, 46, 25 +back-bracer + bounds: 992, 216, 39, 28 + rotate: 90 +back-hand + bounds: 594, 58, 36, 34 +back-knee + bounds: 729, 86, 49, 67 + rotate: 90 +back-thigh + bounds: 379, 2, 39, 24 +eyes-open + bounds: 902, 194, 47, 45 + rotate: 90 +front-arm + bounds: 945, 306, 48, 26 +front-bracer + bounds: 949, 197, 41, 29 +front-hand + bounds: 949, 266, 41, 38 +front-open-hand + bounds: 875, 148, 43, 44 +front-thigh + bounds: 793, 171, 57, 29 + rotate: 90 +gun + bounds: 379, 28, 107, 103 + rotate: 90 +gun-nohand + bounds: 487, 87, 105, 102 +head + bounds: 807, 361, 136, 149 +lower-leg + bounds: 827, 195, 73, 98 +mouth-grind + bounds: 920, 145, 47, 30 + rotate: 90 +mouth-smile + bounds: 992, 257, 47, 30 + rotate: 90 +neck + bounds: 359, 114, 18, 21 +raptor-back-arm + bounds: 653, 142, 82, 86 +raptor-body + bounds: 2, 277, 632, 233 +raptor-front-arm + bounds: 484, 4, 81, 102 + rotate: 90 +raptor-front-leg + bounds: 2, 18, 191, 257 +raptor-hindleg-back + bounds: 636, 295, 169, 215 +raptor-horn + bounds: 195, 22, 182, 80 +raptor-horn-back + bounds: 945, 334, 176, 77 + rotate: 90 +raptor-jaw + bounds: 359, 137, 126, 138 +raptor-jaw-tooth + bounds: 895, 322, 37, 48 + rotate: 90 +raptor-mouth-inside + bounds: 949, 228, 36, 41 + rotate: 90 +raptor-saddle-strap-back + bounds: 653, 86, 54, 74 + rotate: 90 +raptor-saddle-strap-front + bounds: 594, 94, 57, 95 +raptor-saddle-w-shadow + bounds: 195, 104, 162, 171 +raptor-tail-shadow + bounds: 636, 230, 189, 63 +raptor-tongue + bounds: 807, 295, 86, 64 +stirrup-back + bounds: 952, 151, 44, 35 + rotate: 90 +stirrup-front + bounds: 902, 243, 45, 50 +stirrup-strap + bounds: 824, 147, 49, 46 +torso + bounds: 737, 137, 54, 91 +visor + bounds: 487, 191, 131, 84 diff --git a/spine-ts/spine-phaser-v4/example/assets/raptor-pma.png b/spine-ts/spine-phaser-v4/example/assets/raptor-pma.png new file mode 100644 index 0000000000000000000000000000000000000000..2f3c0edd2830cb7feb2887a9546be6bfb281084b GIT binary patch literal 418814 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%0D0JNMARgVHq39hWfjYqGlU2m2*Tf6%Mo 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 z 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%0DW?uvCG~nN2 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 z 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ýTdbM+|aRdwWsDzu?nV( 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
    1. -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

      bu^#(ZMSMnnbvgx$vB>a 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 z zbelfuI0ZasuZZJA8Ua>07;EEmWDvcM=hHYG+kLh%WC#%(rGKKbC<<(W0b`6IGUT0e z)VH@#&j?y9mJ0xcjm^!?t5+^xxoZb_bjKMqm)=}#{@Bl+dEg)X(8fLg;Ty~41E-B4 zLVyj^RP?)Ko)DnGCi$m^c?A-Q#TE!)gWwhf$eq4D0U^PH5Eyv*L~-_~&Qp2mdAIk4 zJ@zL;*zrgJfCn#Ky7b03J@zK=yaPn^&N}a$V?^}cd3N3zQy3s3Ypvy`&hI;`KkwN) z=Nl0KYpq;lI>b6q{KQVDG(=q?Kmms-2eRVd(QHP7&wf#gdRjq2hC!o=iNsQ~A(O&` zu}>>R3l@#ou4sKtaZsu)f*~7$1EE7nEeiuzjMQW^wqc_l%c#DOqQyN9z;ISSpz{4Q z-lMC~QjZ|>ge$;Fqt4#xH0?P7&{%+VuNX@HSt*A;`zTD6TPDsXdwvdOXkI;cEpmB3_=9(%u{ zw4Y5(GPZEj;2j1IKZrxudz`RV+7>84FH~9?;=z~OTLVx#6O(J8 zhZf6+Ist&|uB*KzxiN;?MBf-PhKP!CQIgOH008jpxxXK+Vh9oud*`Vz#nmfUuT-nm z>Tc?O_~RZdpL()5_3!@FsRw@ft>vljeW+NPO)@|TP_|*-5*Zvb81UU1AXjOzN)2!$ zBLX0TT_CuEfPnzK0RjW3sDOR;^ak2^*F$FG?O&?5-&cX({*C|u9)9@YhcDcF@4XBF z?3@Ebh8eh_^s`4Ia-9o+_r9*G$~)`os;<2AuCD94uB*Be0!%h0LJDa+2o&4DL<>~| z7$A5-k?Mswlm%83WRZ%hxy5hHqGb++9y63OkYXz%!ayB(K&lN{S|te4{6@GhP;-qE z=-g(M6(kB*-N`^YQRK~3UvfzyPS6Q+AVR)68p1Yl;2{hlPge4esGjgayyuTAS;aLd zw_{b+gWCF~0W+&0!sR`>}RYotn={{2G9ek$yp_-w=vkQy>l*j>(~|LMPhf z*DFl4p?c9#wcRw-V2bzJq`e|qGso9tz#O&?oe{O96J$tUJs;b+=Ip^xS zu46kH+2h3h1RfT?qz6`Rl!yqC*vgdpDnxzhT6J2jvU5XeE>;MXc zUIO%6bmrz4;X#Zj-5hZ=spmxa1Otm0%{c**Dh34KKX&gh?jw%+z_cV}Dj-fo2&1ZH zN{GjBTt$J}Njz8)Vmfrvb`^K%)&G1*1U&7DgRJ zlpuPIN~^XmYOV>R_bRURoB&2ZuD2U9Vq&Rw3`Xzcfo-LD(a#1YCcs*4pF7OD0(T&j zNY&LD5%TT(kG$GH(^i(?du z1c{U1Mb?EKTt2I4&{oc+cwPJMq#z+J08weLO6d9^m|YW$2Z-D|bn!eC_qwfWN9$pi zC?~Cu%37ydd@4z!?D?1a1`^EBb)EEB2q(aIm5n66w@#E+{ z-QBJ0`b4V9-wDShv;3i_%F{po^JgFa@19(2zUhoHP$Kq%ey0q#RR1RN_w1qdlUJn0 zWf`-r_5%Vlfinhtfej!)O=|!f0CE7E1Ym®-_pj}}jT#cqFWpZ(R>EdX%o(MKPB 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

      8yfK?D%!32hdZf_K;)*C3-9-4CMpLCyp2K~dE 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

      >} zj|`Y&387PBMq`E$1)!uZXNY5ZWh17tI{TvEhDMbNB-vSVJQ?+tFbD+|utb9~Mvyh8 zaiX|PrCUgmsI1wLdArD_mhTy=|AGPl#7(!pCrI<|Xgx62>)7D18+t{x@&IoNX{sIG zzsQ&`fT{H>>NQfY<~j<0FpJ%lxyaX1km+yJqJHPC|aalg%`%N|)!(w^_F3Ya$p1XME#xsxq8u{{A*JStNm3Q8L@7w;) z&e;pMk9KzfcebkAVLSp~mW`t%WMv6R1c(405SH@=%ohuwqeJkA`_H}j(4YQq%fp)w zn4kuKVz+m8cCtLnJ$VWuMjFEvmpNqG@}`k%2m{`GUq4DMB_>eFR*4s0dr;dn0O`J& zSi~`k74f8*+Mp2$ga9o+2&3Nvq@IXD7bOq4Q0vwJ8>}^KGG1rqCw0bh=_3>m4FeMkVCMh7bnmzZpO6QN7{cfGq5>-rwNW#tE zk`WD>@>}4^27p%TGb~2Z5U_LTx`Jxf3Ym27!E2ee*Y|)U*z=rj1aKUOjgbNlG+9YP zI+6M;$DeUA5#`3fK}@AGi6sTBay zV_=By04Xdde*K)X{^|9Pi>5k|Ut7$TQ|;e1aZfF=`$^szAK>tAawv)WK1X-#o_sIS(fE_o;#O0 zPeh)*7eM8hP6XsQ3#SGP7K_EASglsK+Vj(Y-FffZzvaps-}3bcfW=}4zAT_zEdeV6 zIrwsg`PR@&Yosm^RYiQX^q{bchUJy#klOf*7jBcK2(QnwmSXL~2Lm}Zmo`34NiCl@K@Ydx2^ ze)2$1YD@3u^68rC>YZ4}QVbo9T7J@N%o^|4N8_i&&#dDCprNM}J!>h@kK&{e&KhLT z02xh>taSqUrY6hN0McMh0O@rPkYKQ?JdG=6i}HI{CP@Gv zm?=yj*9qXBatqH<#f!1+sWzjE*Af5+BsXLDEIrrF*el&e+k5(!oFj|fnD@I?XSJuD6n zfsPJgfBLA{1%LoB;m$_!atX%)Ass3uU zTxm@?Z%Dfbp)wVusK6sN<(WT3UTOZrLef><1Pq04GC8&ACz6PsSiY0RkTA^wMdE;r z4H2O4Ojnn3_?Ph|C}^uFG-VX%_Tu=&bYasOr)b}uqv$~aZ)LG6MI~BAubiYStOyw3 zUXN=wqpUMp6OcNuk--$Sk*%mS^3n$-d>>M1ts?eIO!-l& zY>jCmDUt$ET=1>pT(UR7@Q-kP&2$ea1wFA@sU~{e=P;UJu4zU{32@M&NTX9-5`3@tO@cZ|HrJwNk{$+{)F}qk zNUeRs)GAK$5NEuJs8*VPl3p@wTG*a(0@K%r%TTCi59fnEt*(@j*|8T*DAm=5fHF0s z`99QmU9p4dB6poILj_6hd;HkfMFI>L&^dg;lBe%2SOjm;VNF5mIR7hiYpw>X!98*f!te`^b1 zJO=O{T#cN8_Z2&!D8NsqP|T*Vn$KarwMC2h(NnYMpZKMA&_wGx2a4Bp|Kl92?U%{FGV};YbYq;d@T!R-H=DJFlqU<9OGo-+{LP%AFZRUAC~jGqd3X zXL-v*#AG{$J}@%nL<9c1x(Qlf(fS@i9IARgF@4_Z2DmR}#ggx#Xxc)LEHG;jQ~+X9 z{0$_K3yLgD1=PL3x(J?C>UJqw&s-ryu?0 z)ok+Yrk{8IRd;{GxmUjKedF8Cg3Ge%Ga9kFb5-MC#{o7|+tp+WWwC^nFJXzWI(X#% zpPxSV*$<~aC*u#n-rnBcc$AMC-FVadXU;i7z>H1*n+M33Ww|P<7x0^(MPqob1q+a9 zYT^t*KD@yK)xH;pz&h%XX7~gV6}6Hv$OuBdAcPM1fG(O|gQ{neuH4+X4n!VmjGkjW zB?$^)in4jb4GV+K#4~WlT0k|K1OJY4@)vw}#iM~lq0oXWfXO1Pm4WcaMCb;G6lsJ0 zUDEzEjqQy?T`G;ggVBm-pP2j;W z4h_~b<_Uq)Avu^TQIw6X-62EbA|j2Q zO!Jhxf8Vqm6w|*HMW2l436o%AnryG`X-2cr$NI5+SJrt5)}ghdB8Skv3l8u;kUuNq zz>d>wlOmsr&2cwdGd7*nTX)4KpsT!5d6Zc=p#~xE3n>WUP=Gb@i8K`zf73GFt;SY) z4uWZ_0m$%sJx+GOXcN>X@hCL@#B}A_nxKKVnnbTRR#anDh?<5H&xiziV90aE*Gdf( z3+iSGRJ8W>N;Awf>7ss>Cat7^y!zhe5R}HdNi%T9-WN{iH99|lI#3Ms`tdzWk^cdL zE|skt`+7Di>t>m}&`JU7==4^$()1nPdvwl?@;rAfQ@Qzfgv>eTeObwQYdLV$!ytI? z{bI3L+yVejeX5kb;l1zwM>}WEy%rGxx3>YuV}P;%Y7F`6iTr9Y19T3qKk@LtSxgQe z-y1dNSgD-TWy$Oi}51OwD%}RqHyXib*q7&0s9OC zII;mj3UbP|`&pZMg-?Rry-P3=wAes#E}X&E!qoJB4SA4N%%-OK*khO}_Y2FMPowd# zLv1GxvTxWNld}JSh#It_OHUG*TsOWi?M)-nhpdKD@!tUnzKJNc6v$Wy@d=u-o+%Fr zuN~>ZL0W2n3Q7{FYml*DYVs&Zq?}j)JEnkqYx>OY9j7_oQDIr=GiEbN z(TX30$Uk9t#3@Qmy;>(y#CDKA6B^sdy1$4;hRb9v>q&D_6gMjMy2G&ck2U{bnD6rE zrRr@Q>i3pw<$(J5$nKl0`@4e4zS@wKBpNBEu zw_YdxI&=Fg-u2oq`m+DQ<=F_b9AK0K}Z*%Z9@#kEK8|H;*C^7N*k zdE4bXzvRNJ@BV6+k1AO~J@uzm0aTQLSyox_c@M>no8XB6$-{CsfqZ%di=)G5_8-0f zL#rMTq6GlTvMk5j+uK=|Wz7`UWiCT>m}hy`JQ2;!nAIBo)oQg`6-7b5Y|Se;qU)Pn zX(JmJq)AC_meEY=!<7T0hmkKFPN9*5(7v{fR*kTsvfIhYcl~%#XX=5ip&tJ{$4ve@ zhfxTSM~?DU3lht|WzBH4QKE?I!eD{q5pqEcSo_&7jLk{`1qza`Zw?SeYIPd|1axOo z-Y;;bma$x^>9^JFB=p%hl4x%%Fm2M`19ersz=yvXLnt{x|A?qS{noke?jrGy@WSd`-jW zHe5d`FhP~mo=S^}3OF@n`X3y-V)|z_tegr?QnsKpt1{zRZA7i-st3rh==8D)PiBlu z8I}PW#6_^R{vLl?z7B|JO@he)qSrePJJKsUm+bwy4~E%P8w(<6My)5fIN^!BN55x4 z@GJyIe64*3Tc-f!palf$FU(%o<3T&X4p7QfD5zV6^S`XGL~|JJ#;F=WTyrOGP^W-C z;o6P;dzdi03*6le8D@}jl#m(dY&{`S;LHS8=Y@vZ@jAlOS1h)Iq_v}ZeyR0Tp+q#M z1}v$7n^@bO0%D>vv}@|)j^^(o&#d9=4uJ(ifb`8!ye^~+girtZ?>9{4Zk-Hkc=>xB z@xr+PysrNc7#JlfS!|9Nf1t1K{HAUv%L$Z~WS9v<2CC4B#BVXarc4;L8GF zIs;lPpgcSR@*X@96bMkxXOJysu-w1#_zMqy`bVfNrh@c4-rSK)+5K=r1hx>g;Xfb#IG^AB2TCon!U z?CXk%3c2)3qJuScN29nwg}#M}1};T;vrz1z6Q#&F%$Uk>CM6D>=4ca}z{E}Lewd*1 zqXL!;Wdsb->$XN}8clBK=lvOS5=ep$%0!lWzH6jqSMM(}rzp~wLsC#}qrrYf*RlK5Uy? z!oVs0X*T~u&Y_Nvi>C--T(z*s#O^GH^f&!-D}!YkI`P&_CEFW-nGZg zh6i=wE$jMLdR*JA@x>i#Aig!yZDhV>SyoH|!1-)8E6cKkTdz}joxAf@f9dWoe%}u{ zmyKa-3t(@ry2GbafW-ppv>QMK@MQ^$$q_83M>k)3{Imaev6wxz>F17icJI1$_nZDk zKHkD?G_D?-ECcW!(EG}JU{wH+2LOa(Jgz{A!vk=$iNCpj;}h2(d*EMK#6}eWaL&2i zy}dp1-XjoXS)OIm2#?+WMNt;TYPD(~T+LOPP0G8QT}07UP$MDJ*7HSGL(Sr7K>|IR zk3GumLPa4poBQ_lTG|^!!=0c2lEd^ z&CI8#XkAM?I=Fe~1pv^?)yiuK{-)+!8si~#?zLjYG9yDPhAVh4jG7QgfD2}9R^aOq zgEE+C6i`N%CcHqvqLy;nr4rMXGRy+b3exnk%AYw~h%_-nYkH)|K3dIBuW6pqbaJCI z*({_1py2=JhPw;oePP#WOdhSjZg0P?i|*8xeJSf_%PEM-BD(6jjP8*PCc4 zA@_l%c1bkrL+(2?h7T4P!EZsEV(|7%~+Sj=*@sz~* zj{BVs76qd-TQld1Ea%T1V_nDF-}JV>mv8N4c|NK> z0A1Daw{2RtN)UNi6)Pwg3z&I7yZO{(zcP8@ncwdHj{FaKmSwwpdwXpbWtFHWrqk4> z#rx)^AW)j)uy3LTnG-*8YJ1ZpM+pHUCWL2q%6OJwW1|3NLt&o7&GtfC6xJwz0Mypn zc~90RrlPG3J#-8O^okjwOe8R=-p%x0D~4;9f|Ob4%|5nWUo%BReX9m&`53%O(-l%Gz>AV8qff5&S=F`Z6s31D`Sy{ zfB=0zW3iE(;Zm%zN%~k6F6EpqwW+MZ4Gc2n@vwq1Fqo?wVf+3jb?sg2+-V5|7%H(O z#a9KCmsaIr3))bkii3L@iNg+*|@^AcZyp`ge~GNw?|)*F2_ zF$%XPaRRZY%YW0;k^1jRR3ZYw(41oe@Rmk;u4$+=AgL$bGLkB2*G*ufZIdnTYiCHf zT9&4H@6&~BV-(S}JEyG4gg899Z)zaT^z}H;&3ZKZb zJaY_SYvd=5EW16%COyMBH=Rsw0RX4+LidI*dH)aG{<=4R3*?!@3m57Md)d9ai(1zwz`VKXdchCw}HQpYF?IcIBS8epi-{cC+zT^}IEvbPbL~)B+G?=Af9* z!Ovz;%w~r#J^ZKt$Kvqj1M2|*d7f`=Z*5mMSLQO2U*95eO-exh;58H!UdT0tPsXPA zo$-%j6q#m14XDMcNUgmz_29@|Fg0r%Qbv7e+JC5XI;CE|8$?wNaaW9m=2D!}6HnD@ z%37=Y>YDH@%d+Zw_$X7910TW0VN$RVf=aym9IxGM@q2`|wuF_h8vhI24rS}@_ z38&-@M`mKewck3YW+M`qh$_>4)>x|sU50U2E1BZi##YLQ;h@i-HJkp5ia(3PzK0MJ zd^2q-8Z{p>8c`Id@C))r)n!H(ch-l!!GAp$}Iwkc$0%zJ3KDb{b zo>!-s`Hrd)|yURlfI zGzKywBRQzs)%p}LSE6Kt_V{&A1Mj`(a^=wdKYmqg0EZN4_@M^6p?yZ$Az=M`Szbi} zP~*Q-|E_C)wi>zu^X!;TCKI^zI`P+?Z~nr+efPV*;`?!LZwt?!1IQe}Y6-BvU)?Ou z0l0AVFhAS}U#zY@|InxZ>2fxCVzUrE{M$ofYN&pH2^?jbLGF#Jm{|0 z#G{`b(W!RByK%Lp6%; zbV&_xP)+E4T`U{Qr-GF%In0$6BF8G&k*~; z6EC454q^f=4RUgl)R$JHNBmgRg-r_ezR6vm!*riX8Nitt=u#^M_@}?%keQw#1iqTX4jB9{~L%_RD0f3<~ zt7M#;q|br|KB1iyW|^c#y6}`=OHWeFagF~Z*f0d-ITll54VDH!qGlkY8Ty6CfvwrG z*42=7y%&QXh)jCx<4DkDq?5kI?w|xnWZM2M zuAkGCT9%i>5b&{)$Otx6Q!ht#IlCvq+7-L|Biaje=?32;F#>yq2TKqm8;aM|Csb+B zC3qBr`VO@xkh9Yo6K~!t@S!3$%<1|WX^g?Sd3XdwHWK4J%Uc#f{d-yFGBO5aWl%?AH-uSlvauMU~61KxMkTQlgrr=6w4V* z_h0(NwMQTLabFfk$32dnGw0uY=E^I+biA`yMgG+fCbZ>M_1^>lOCW&B5l~se;nk;q z@8J2Tf3uiPdnE_~0I;>ay}dQw8oS2)ufEX%5vhJ;vL^qs1^~*UD4Lu~?pP_O_Eb-i zs^-rJ1s7jrn*a5h863wIvMeLf{PN#-4qc0)*2gOg@`&9~uY{6q;8=1;VEAE7-GG@5 z%GnWT5_F6S3W(_ZyOYv{*zWGgOaNVa3T*i&3@j8;Md|g)Gm2<0GiE2zK6j4goja}i z84Bb;RyJ&+=pu`t^Tzd{!GRm)J2H1hIJhIfd9kdh?xu$49uL2T9PTw0oC#e(wPyiS_f#-7&P#`Ge zT>b^?=-Q=8W8z%kz-KYy1oV6%l2gecYzk#^j|{XrZUo>u0D*oH9frsvtBv?Qr9RWZ zDE>{o6S6YFh~z|;+QeZ$%LEe)Lryg+S4n*61CF$ADAtj)wUmF4R5LC=i=S$3->#?U z5#TA4Efjf`7Bz|~(7Oew!-+f?42Q7RVctJM*9}a;+Gi(V+aR5M=Xv>tc)$vr}p@qb6K9{om7AgErk)G z_v9Nk@oYYyQ!q5V^*Y8*=w9{q_x$H?{)(^raopRz2p2B`j&h*o66o*{kO(l#0J7@u zu*If5O!u!txhl%}(ZLaB+4jYelKy!s8_>|BQV);6%n`1XGZ0Ty`% zyH%xbfI$e|G=rM}G+bdhd$>04U0`+}av%<$0dFEX#n$pwydOV+!brsPx`1 zm&>IueaY!Aoy$F|Wst*(^)%TzCvV;makRDYa^a4fC}Qr)2r_TJNhE0EH)Mvi-eeQ- zs6)P}cAf(UV?5kUd+vdYC`9lFPK$`>*HvFVfUnTHkG?;Rt$aTkZedLB@Lz*}` z;YN@KfRL&CZ=ESpSbVbyD5Zz%T2vbLPX80nf57KJ1vu4@oeU5$#oFj;KZsg2L+2T>HcN)1mfkG@yPfe{R=03T`$6V)6z+m*rW5 zTz3OJPu_b^3X6h>=;-L^*pud4FMuo`@80v5zUuGa^W|UjgLLN1IXH7$)nL!(0LvA? zcnmli0WDWR%O!yKZ4l~mb_DZ-{r{i6HxJe=yXwQ%+WVaEyVD!{b@%H@Pd%vBt+~}2 z8<0Q~1~CbXB$kn}F(w3;V*)k-6T1oiSo_=6exMfyMyZB4zC~RSEVXZZ`)AV$ceQT(7!FP3C*L77p)j2zKnC)ZcFy!g+hfXx# zo_f!l%fNu9HPz_#VHh;)t&4#PHMi+TCDhLGVzeWRBG>cx3m39Ub^qV74%!4Jgc7)r zNMpE(>oi}vIHe}PDg7DKrIsNyC=ssWUGJk)x#$o%QN!~!$LX&j%W{fvpt z_JSB#u}+D^797gB8JNlsY3^0lO{OT+3iBb*aEvr&{DgXS5aF-@UFT!rnJgow>L%eM z04vH7f{A|yz{yR6S3MVa$n!XKZfV5zlG<**-(nC0hrxOmA1eyYHzmOUP>kf{zopm? zxwSrI1IF>EQL0b|sEW1qEWJa-u4>0Ynj9JZ#?fj2<-_u+j` z?nN3OtVie4Q`mv)Sw`?fc=r z*0xUE_`3Ih=zqTH4R8I=>#|s*wP|y4mdoZs6&An|KwUS{f6jRiDX126*gpRZ03w*8 zET)^s&RRP;POgS4&pz?1hXeqY*WdN}ziG?qdNG-TEeb#d_N|voaQl1Uh+uZ*`3EjN z{-s}E?(aT%AOK)}eSO^)Md4Xsy<@*4+nQK-s%BMH6*=diedv5V9*DRO3JPZvnZI=l zUk_t56Fh^w!Q_oTFCvN2-g+YrsaL{a6$u?rO_OooF%l?p!Im^0A1NZWrrN^QEC*2g}ZN*v75~U8Df`P^CG_IyOhkVFr+*2ETN3l|* z3b?|w6%=DbF267tV>+$DAEo zu!E_2CdN-1ttHom!RSs&*^T2DwK%WTq%zAoiM}6Cr)eN1B=@by!Hke zI74CpgNgfPQhJbx4o*PtY^BC<9D9i@~xs6Wq0KM_2K&~3IR?_=^F#Tsg>rL_^ z7KF--035>$?HYPz&kT(KW2KlC(dRu|r0<4!QW>^Af;F}?4QvL6)<8Q{Bo<}qVTb*_ zy}hrr@CTn?U32RzzxJLF{MBDNar@oxUQVo~a?;!mRo%G$TMJZGK=V1!{vKf49+D%d zt0nARIuGC+l+$%UW5L=2ZCS2CQJlT}#3R3SC@%m4y6(=`{4HzCV?YGO+8VGP7Ki|9 zAfWjS>ct#rxq!=$KKvUO9{u94kaLTb0RU@^SzBLUx7OOCD2i_JZ*4GrCZKNumdnMm zs;bJz0QOFr22<|j$g-6oh<-Du7GTk062>(34K6q8YaSdU9PkZ~G879cwMIkUq^LpP z+L$T^KF9}OGs@z~AlLi*e^lwoV$seO>A)lmq1Qmjnt=9rQ%x0Lko~m_;u8Z6YzWR{ z&<$c|?xZ@jCW}$Au_$OaD$_E#VbjRziDVkc8B%VOhmpnHP=ne?>(_UKIwK%KJFD znU%~QSyG1dvE;bJkcx0I-q#1B2TR$FPnv%_DAMg`E zb-GKVqP=8skSYL^n)d_baHEKp8gd2KHo2=oNrmj^JXnNPFPYIL0We@XchJv<2K!i@ zL?(N{K3V|)$VoC%pw-xB!p8_<3y#W%Hkz2p=3X`>%Q&oB|4mP=FMU3v2tNv;3QrGqDiQ|uUJ0g4c`f)DT0CZ^`$jP>17?OgM1w~$2|Q>MsY<+7pwdIe zlr^=+$>xqUFlB5iKw`ZadggP+pCq4yG1od10jIJ&MojxxG5j0LJV0SArwtv@bGS8q za<@)|(Q%sGh7y38oa}3Bs%B)D^0G!g~%W|#x((fvDP-G z>qJ#mRrC4$D*(U>U*+c3HMiXN?(cc^cYM#!U-PQhzn{ut(-{PE%ZBFf9Ju{`p#6P- zz1>FdUpwHODd!w4XZt`^1!!!uZkQ&f&lZhN-&%|N+m{~LIsf!W4|=SoC^v6>^}Rn> zOxHJ?vdDp*Ou63+Eax+*=X0RChUXvp{4YKGr+@OZW2gTS00026v9+~jjWw>F$QbU* zOpcr*=NiC{nj6s(1=MvDPN018Dj_g21@AIygG2zPuV-c<{X-E(*L1LnpuO`&t9fvH zPXp34tE@Q>3OiwT=YmKN0)qyvu|`I7ft=t8`mBFVpEs%-8*2Kz7`1H{AV9v@I$^Y^ zY06^&Lek+eWOg8Qs5M34h6&CsX+@(F>ohb44mJ=)#|#?1zcsRn-NNI^Vd!bqzgY*` zMiW<1f!#3;G6vHbMawqi+CFk3cqG&QBgztoM1J^~_gm%n^G$n*_4A8=kn^w#omwr> z26C!Hw1I^8MQ=JPU9fe}5H0G7#r?6ErSv%t3nUrcisF7%wYLEWqC|957MEfu=Sk{}GYz@~tAg{Om=+EKGRmHi0?cyPV+ge9?@yV6#J~YY?f1_W&pOxi+9^;Q z6~?2shm)*Pl9C!q8WFB~jnjK4^)f}pH;AvB#7smfVdzRq%>az9&l#uMGZoaO+#9H4 zOzG)H^2E>x6T^H`RQh~J>?I}(8MCib0*uu5zEn&r2v(c6?|?{5(1%@8F5It2{@=`q zb;U#}2BKH!=@)2NL?*Dru%_n#9})sH`LtwiUeR> zZUip<2zsV9e@3w-0xVi$Wmq3ny_V>YExdODe2hbY*f%n{N zk!~V_dOm|{z7NhhFy4?45z5H~Oi_BU3g$akp1$y6fy+_k6#ZOiEK& zutf=`EW3GC4FJ{t9#CCDU02&rfBHZE)a>%b&#dwu5d**&W2V#T)FaJhQ8d|ZQw^PuZRpxLahap z%z-XT(9#un1Q|C}N$9W4*qFA&#?+zzK9(}``$m8(@rFWSano&@;buVM-%+KzCGqvu z8)K=j*CN_dMdlI5{H2SBqx~A9`;TT)WUh-wsf?PRvCYzeGya(3m6YNYBUwPG|KtoH z9I&?>N`wg6J0azl(|#ecfC|9}N-zl^<#i#iI|p4Ab1n|@4W87DSyaj>Qq6`IO@xe< zGFo8^I)y%!^{p}?2JXQz+H|d8T_tH?l;1#(8KvzV2}4bOBS1=~!zZ4Z38@hp@GM(F zq&Pr=g`vr*a6rli8E^zf0>YSKiC_{OCXk*x7^QLW{k>1w0JV8%4Ie+P>~r{Y&VfDY z36lIgO1g=RM$;H3e5f+C&Ke<=(AIy=&x11F5E^@do8}EkM$~#rtUrFZ6$8{EsQVI+I-$y#f@kzdDHan6yeoo81U)>vZ;YY@>`W4*Cpzt0k&LF1fr&_>+O z=d<}@u~@(g2`+!$z9w78uf6Hb@BAyT`rvo}+)Z!$y1!N)J8^SeFRh~*-2Mz`J_Fj> z0k^Z$IQ}~aKz)y3gzmXsEMUI74dht?#sHXR@?Vsb=D!I5kl^CukNn#9b5H&L2(M!G z>*P(he)F}jc-6N)pn+(HHcPe0J6d{Oj^U`e3JA5TT>0FOvyNH{4IL=Y(v$X4jk;1Tr# zQ&Q^KrBRIzWf8eT<1dRb8lmabqyXARPX}=HJ}5YFHJAj4onEF2iLt+0j3HDJg{FmL>(PG-H&rhEbioWA4Or@l~&bf3|=rQn{HX&e|tK~XmAyK@i`@8zc@ zDIbR+EpTqF2hF`dch6{4a7l3%6lg8Y1P2`MHI_v8X+|K2I1qsfnW)C0`*UczJ$8bP z1151}*O)Q!g{VZfC7bc6S?G<(u+v`)n0rMj!(q>#3K9)8cLCcXI==>`Nf~eMuHnT*)9+I|1!9J#_;Ym6~v`{kT- z9bnaJ{(BZd|M`fB=Cj#s@f8VxK0QBq`sQ2S{+_?_st zkhn3PL?w-n4OFLG(8dP(DRZA-0PJ;>ROGe@_WJvhSuC9@}4yv9w~ag)MP7Vz?6#VA)!aiMc`31CBXz0 zId1|5t2E*x^`h~)NALGl2?2Vju(G13oU>~ucqf-iuh(G*nG z**bq7##{^y41%mF6`(dz4jR@dYgsSk!}HXXI03~tQB3kRLyMl0&mb~$(rzjSI)xmx zrd6ZnAEE)H5tA#Ey%&X#2crlR%LIo3O7Z9hI|m>Qn%P|)Ob=5D7}|8Iy{}Tof&-wB z)-=+XMqFrW!X^bHa9X9e4}czc70#u+N43m&5A1WeE|QT2=FD-NDW7w9vCRQX&~dk6 z3MtWjW_D}xH6L!@mc@+sk~fGL9!1%3xBctYbyWia8Eb7(mZk5dyd=&Pws5X?rhPqQjU@oE z?D^W++1;tDs`^U1-=2PBisLt(d&A4$`Tife^PB(DPhb1$H~z(9YwN75E9;gEpxHjS zy*+TVS)=o>D}cI*^uylH91M`ahY9Lx0n6E}S*A=w$46_ylqF22Qz*&_SX+2<1}t{B zAA9agpZ}NpS1x|?Kmf+^lXu?-$+%LFlxqWB=z!pWZzOk{wa?`J_)$qP!8KOlal42z>IM11us`I^n7wERakBqEE4hCm}dc(B>v*AYyLRsZ&Hr zggC!Fm`qB29SxSrhn)sVW&sJa%v|X^XgoKvY0fbNR;J)5j+$1WrVUXv$2R&o?QrsE zpMoSyAqUoIYmQd%^4}+*&TnR@dH0gD5#SiX!axrUNn%2{2knSQwD_twXW|O zq@RvtxCMhvwwHR~fxMI#WIkZCp%W3gx~h$_##n31vMhV|v}VJ#-Yl@LYitLx)b>^Y z01g1IT)K3LzC!=U>G6{{UH6(dec+D2@WG$F^_}nkd#7%F<=2**Tc-)h&|(H|J_9$K zgIg||NWZ#jX#NBtaL;+o%x&LQ6;!R!9@?U#;+vv?ax#UYn1E@Ue@70899?+q;op4f zflvNC)%Afq8g6*)TmI|o-}u(Awd?C(&;Tu$4GW>J!8r%jd=K1m4tp1#`{c8qx&Np4 zE}s9RgS?N`9-hsOjScd;)7CtOTBm>Ci1UZ6u3b&!T4TUwvuT=KQs<@tvdaom4<2x1 z!6EaJPA}ay`f}36H?VGU&RoHvTc}Jhc?Tv*2wX`C$dRM&_t^1y-9IR_{O0qKlb{F) zvqH(1;HDx)>toO$h;{9cxA6{W;u?YJj-p8#3a?=09APSRT*pBCquoui=lXPc-M5)Hb&_yEj=4s;s%IdLRwD+MaQq$*x{eL16%@9nZ7jZ8q9 zE?RYSm;Pzkb-$X~=n&8;_i-oviL@S0k=M`&AQeT-qxPKV_DI$DL)mi(($c}Pdxh!b z6Q(m+^gv6;G;Zq>Ncf}h+Q&0%LGx-6OaVx(LyB=;DElDrQQHw<&yrhr6oM2ff6504VkQyNzGG4d=H%78l-w$weOkgI1U9I1;ju8+X^GmaZEhdx6glqee z4O0OPQu_-afOK-?cDA>-;m_k2qL~~&dBd5zUiTMnefPKg$nEd@i$8w$4R8C<=9%m7 zLSxs_5K>)%o6o^5mO#q|P+bAJy4CnM^#0b^v@cqyt6{qPt6nalS}wr38jLN#76qU! zy2!txD4XWrKXT5&-lgZic;T^!K62&h$NtSh^#7BMt#h}(^Bez{t#h}o8)Kl}-UV7# z;K+e<4(jC+++q&({@#UWKKF^Az4+)u{{n#AkpKV)02`Z|n?OX)Q@~pKId38zxo%;t zs=Dgv*#72j8`WOxZo0qvhAor`P~-!kPCgjrEOsAO*oHxbp9vOqYP0JD1~%Umj4>We zKqc8gL#atA?mIw&Iqypvy_lyk4ZR7x4jPF9L0#81*FE)%50L*k=bU3ghRz(NlR~s$ z3n&F`z)A>xFoI2v2IfOjyOzv5?kj!L&SMf87n`s)_0p!CTzk)(85|K$m;?b-n*6v4 zT{f>g9JP!x_ZsV>jUyt6Rs{w|6|IM8s#kfPl$j>L(WV<{|Bz$4_gM{33{$D5>$6nq`xE9+b6c zOdKbrfDgGIDYAxCgE}a85Nqy1o9x3r524(F^k;9yhmeDgsKup?ShH!Q>ETg-<@N#^ z*mp3)8cF_kH2s!_pPAw`6ZNJ^2mQdNmprE#B3h-e=9bSpzYSI@`*001M{T~e~3 z#UT$p7gF93(fhUGg@}NT7%F|-luG^Y0RswIRxHH|m{GL^Ke{!9NiKQ)je*PpP^-K8 zfnO^Zk?)-_kzEDggf4M|R3qh3Vu4XQL27S|L2L?NkENh>=aJFp{3~_Wu>~56qAZG{ zDA1ts6k9aL*w%}zFT$x~784+NP+)I&clXZ;0|4!G?c~<=H@^PbSKaf0Ti^YyKYH7H zzV*Mk;f?owcPVyT>(`U7-PU#3up@fult`&z#7|V^V`?0mW$>2hd=)-PkiqF|L%a(f4t>Q z@A%m>cfamF1cZ8b531cAXlU`xF}dX&>iKN{!Xsb&)#twO>3`y?<&}e;*a!e9ilUgV zt*v#YQLPDuwZ`&zH)?$W$dRj-4L^a1sIKc80KodmHFrPth8CTXOG{Z7CU0_MLW#PG z1qOv_AO(?hoXSpZF1V*g0r6u&;r1EO0lNphXAd~}@F{fJUe^Ys6@c-CE}X8l&I^Xe z{&-ISjwooxfgFwGpUWe}eR=}|Pd$iY5E%kWBkBcEB6`MXx>J-p7;wTLif9_rlSYh( zky9cPMrmWGZaKYbDvByORmo{-2d1xTj{2a1&cT}Jm2}Q4MC%<1kdUDLALjM>{c5r) z1$t8(e;=bJkVlMh3LVA>i42!w ziEMZrXnsc@M^fKS3hXx$M7hcUNz$uCI@gQq&F@<|71r+czF{${(PkIBnPTCzr_Oal z41Jmkeqt@aC&%gu6w$+~NnZ-68UQ_2gH7>aBCn+p>v@#vuCR3mL4V2 z#ze}uyFp%CqxaIB{)6*jVIz{RJ5R5&EK6!>#n?)NEla!VJvD$l(-#r2uBvKpZ*TAa ze*gd)JDF~+pE`5L@mp@Y@7h=0^TAv0d-o5W`Ci^YpcMTU(r< zx+-Y7K&q>D%D)7vY9LoPjeoUlrv5}7CfE%6N|l_FCXS?t0sVx>15jL%?bMXIU;xTM<8hK z=ekCNhP(uTY5FnH1IETDp7xJ`;M&GE(wIgY5<~AifWQ|o_WS)pWUw(Y4E3la839a7 zYueA`i{uWC>$JJp70^bw({@NNFlw$c_2-DLpZIqhJ1gS)jW*Qy_sI**^$2wTy%m9x z3u=EIjX=f2V+>dTY$Mm#N`tV1b24S7WnF}1#xZwjnmXnfLW4#}(u^-Zp+6V}9yP!u z1#}Ed8OOeV=vkpp1WDVF6I%R(HuVQ#0UQKu7(11@8UO=9I-X7|_Qq0LVE~vKQ*5QO z=w(qG#)x6yH;}x)B$%mqhD42ne9fGHL9Q`Y-J~&$hUM=qravYJA~KUM9)YGkucR3K zNfd>YB3~N0<^ToCfJU5=6?rqPux>&keoo%Esb^dIP{caRSmLt!vq)jXlK@8|n(zt$ z>`{K1h_M*n!<5*UK(JlhS9)Cc@9u`xJU_+YTCmXxFCE^coI@94+&!&BTt3so~LLa z#f#?PNr|-j2y!sR<045tuEe0kdm|~*HY1FwL+A*jTi)^g*T42nA3A;OE8nwm=K8zJ_04NcQLZ%}eQiVE zwq{V*Ky7>H|%}(4-_+7-t=j57C$(mNAgk zz7G^~V;cXX8vn~=i<|+Ylh=O)a3b~KWQVk?TCBid(dNA4C zXdqxw4Wd-YUtd49q;I?A61 zaG?OlKOhI_y2`>uQSy?^PN zJ6`pT$8J3Lmi5!u++MD4p0Q=Qfq(@7AbD#uV(SoM+t@qkQ;Qu??OHIv0WiJ|8q-AS z34=dwV1&lBllE3N;3Wdqfc2FBq6A~G0}cq9>3qFhxXVvHcK_2~_~bvGZD0Q4L8kv} z$4}jL^XuRC-9kf5-BMgj8NB3LF67Kbi)1L!|AeGpeio)+|}Q7uZ?Nf z?v(dOVhxB+otDQvX6l_W$btkT38mg1O*&yEw}!EEN0~-hqcF2JE0R;C=u$9YP4tMJ61IN2yZ7d@pvHua3n zIK#%an>hCrMu5bWzGK6ox_n@+$ z)gBN<>W2}UcvJ>g(YnvLF{nwI6mwWf;|G=u5!7y4%2MKc;WacUC97e23{Wa9YG|(y z&u_>k<;Cr5U-j-Ey7A5L{Qk3V zc-!|~|C)Qh>&z=&`+;LOo_p)siPPtb_03bZDA&=Nq8-VjZ}f?LBk%kEzM*e=sixTn z|8vd(I6p1-fI!>88v|$yFt+IA039@p0Eh-`!$606F$Y)IfUVBIC`%}c5{hyH#@KeP zU^}IA;Fb&6KL7M*zWj-g{-f>lPyKrUs1I`PsIC{++Ka_tq!ui8wl6*R z;Aj8Ym+$|*zqS4JWB(S2>Z7_|DgZE)JWzFrd2uT4RkbCW8nSB?e744t)$@{D52kaHL$W{SwK(=YNNb?kMbtSt>#8LP1`IU{Z7#Mr?@K#EW=|1h9}qSu7G@VtmS{TRl^wH$Du}&_=$& z7h=fL;9@DJLZO9DG6phKGzls}0Qyi|EDSIZaz<_uvrXBA zQyc40<9igQcL#0Ouhx4H7NY|`2rC^M_Cgp+G?!xl7CH4r#jSa@bD&Q`VIXfF+v!&W zZldu{#X1X!7q*z3w-}1Yt0kO5@O*_%Owx zTW5L7i7*0G@5`Zc%X}L+ON_6Tk*A2#{E$k4$GmYVJLlObK4He_3pm4yZ_WLC2)KE&V9Sj>EuzCOZ$*%O>c6L?qpP837XCiW1>*GW8?NSb=~9v?xIqj>gc z#=NPuKx43kPV;)quwiSa*1So*`|yN5!L|_Vv|J}ZVIw4+={2w{A@P8O)Q1%Me*8@L zeh(%Gp0dy55+J`ObJCe47@eoox(>`2CywW;C@iu1xbDx4y zz+|EhlgtDYJg@!WuxnvCv%3BHqWz+_Z)lqh#MaOo0Ki&f>$eb2Z2#4T@s_uoBz*XzDz#t zZ)L)evpy-)^lWT?nH+Eadr3fN;@49B`vni%pX->eZ5d*>hi{4Z9sy{C@+x}^btq6jjKyDUm_M2<}Bw&~h0Xbk{8UB!q- zJA7E#0@@kTQ5Hp%rXQva&V<1NpMs}0o=m2vb)2DK{R7;7KF?PI;ldhitem}oCX_{Z z3R-9C*DMyE1rV9m^cg+CJq3aSy`xL@2tpTs$C{Tet})oeDLK8Ba*Z%<(bM~4qale@ zV`i$HYtn}(k}0QQt*9okQI8!>>(emZU<>)V%}p#36i0DXKT~dEGuo6a!$wF=RUkvj zUv;v-a?^bX03v5(2g<3a$wQ;yoy@J`W?E)uVkwTPLqV^FHR7QYl75NidQD6gK7%Xq$;S zk9Q}tr5S<%?vo8?w_gLwC^Jq;R`cAWrn4Q8BqUFrb3ChGIFJ^_^Cs>q7_ooJJrUV@ zpISGxy}~Ga9A)<~ik=?K09?_%Hz2jaOf;}*>F2@y$K(w;!^0df&i$hTpAFIE%0vzh zFO)jKkiUeyPOSOIfGrH88K^@{82=f0+<0K-$?kFI;{y$v!WPzh zu5|-SA~MFBHUkh`?P|aOk|Q_U-{1F!>o02KUrx5Jx$`yezvUh8`@yqseEVPBy8fnn zinaA)P}c}ea(uJ6SPNiG_or#jn+CoAV|*?jfHeTt0u%*cQ8d5bB0bP2l>)bK#9;M6 zw(*({J3vIR)^<{WdNFUz^{OQpYr)t?=ij;eqv8G>K(0v;AOdi81$DKopZ>z9e&fl{ z|M7qCs^z7_p3iDNJHP$xlOK8hOMm*$o`2+le}3iZ$9{Xczx()6PW=Y~fc1@yjiM-v zE)(7Bm%4@2bPu#^0Ri7sN~%3y40!YFb@YDYB1bMq59HLiFkU0v2J{D1If)1KAhv<#KFPJ{A zksoiWFd>!=+#egpx!MwwmanN4>ZC>k>XXF4I5AVi$(t!K73`*;V#`ixRz;RPGMX*q za&?tLB|Z-n{X8ktgUH}%#3ndYz^A5;*@&bO`ukO42M@~{82es1nrAe{92xHif~wB1 zQ3L?7f($Zl$19&F<(`pQ&XSdrnsA2TY$Oa1|Moe3TvS|x<-1lqQu;FE*=ob?| zQUCx<$Pvr{h=WSTHz~1ESwqMXU>gL<4uCY`d6f}doc24^EJeu+BPjF9Ym#7EU=mzG zO;sLEbcYZCx$naOi|cALl!jh|a{GZcL5`yOLjGK;0Z9RhA=A+a<6}%Wg=l*HdV*=1syp6%%HkDNhh7Ih01An#moi!zg9%SDv@X zC#hwH;s^s;DTn3fKbG6}_lZ2o>NDVL)~-gPND|cpO5&=D+BgZQC8EDkuuxFB-#D#4 z|JsRRR$}sxtx7m-J`959G0@% z+T04iA+^aCbvIR3XyYuT4!NNqclrdyecn^vdL$A9P{1$J#u^*u42Q;k;q=c@3@(7D zkdQA_JBC54)uF_M3J}qD8l%2h_7r_>RN60CBq9PKz@Gc2yY-#uHf)0a-%NXr8WX@i zE+lmE?lo5gezD?tsho+SX-|>qcD3m|C`f(;BIFR;k&R?_0}`bbCL?A@E!s!`4O-NV z7IlRyXiifTWvR&yoOeY-HpEn*0WcypbzFspKBV&<6Z?3SMfYJm11Q(z%YPGvXYM$R zWOirTH&mBI!Gm=uFdhtym-L2W0gnO7#FIB@TgNR1hNPe{uDz(iP9 zjF@P00`ov^n#Crnp&P!5)&v?EnTG@MVngeZ28e30h*6`SF~pQ76jm@i9R~o!tc9bZ z7F~^~Q}sTMz!3?cLvMuXeLmD@1|fF#Co%1h_i7B1J1CikCYvbPAX5tHPRQ&q_pB<+ zOrZ_Uy8LtI3Gw<;YZeFAH%cX}jPxX;1dzzz%qKb#i&Nx7s+=*RiD>GA(UCJjRN_iO z10{S-D!ezk8nl^mVaHDG*0S`o;qT>eU!qYgD;-v&{+O9371!fqB&X?n6{B2JnV{9j zZ(=Zv>{9@s*Z)gEh)dOo$QolBrZu7|Y*AQafgx@DyK}h-!zT9ZC=Y50|reaIjAZy&H>gAkQ^WpSnud> z3`mEs&M1)DCC53amvdOo_T6)j{ONCf`4b=gq5aDj?uS34Un&4#t+kWMWCDO-i=yaU z{jIU&oHOm;TY$>|Akc54rHe5lR4#f@uJ%;TmNdL1`>S ziV+rpuJeqTB?)RO93cJ@6U}Xk9W_+IA_t`8#5vj27);r4%Hwm)4+ezpUWd!Yl&;6IV_6tVjl(mR2BtE_zQ2 zePLt+HfC*Ov16;OUt`v_gEaqHHb~bvq!|*Jpy(SV!#!?-^gDwy_HySVj+7hWr6MjG zmttsdrm^Hm+r>q)hm-&&&mn|v_7r^nVTv~mq*y@WST#A1{G5hmyQkP$oxwA|pM15NnB6f6ho8-ptE&&ox|yAiKupU=l%}_ zWZLuKTgIFr`KBMc{@%BL``Vf7Zni~HKvf~tb)&KO6L>&q zGV*-0-p22lMh<{Q0a%uR)_^IC&aAJo)ol&b{Aml)?DL+8>|Hfd``PkSEM!WZ~ z)Hw1)iWPtFD5md64FDVjxX_v*EwdUF7La6#3>jU)NZ$)O#0jFnDV)YnBeg=$dxvmR zWrk`zd~gy-)pfEsQpV90t^E05Mu0<&9wxvB&RW7u<~Z`oK>_@7&x_Wu(h5!cLB58W zM5tb`u-T<<`6Okt(jo*gU{?W+U87Pgts(isVb`QpOaL{;qxJ(Z(y%lH^Oe0X%4z3O zatNLD5KY^d^mR-y;bM|Z5Qdd0u!=JVH8u$Grj1`U;hdibUNAJ)OT`@ukThqUi9`F= zP!yxG7MV=#sj_SokBcsj(EB=ZMgUMy^Acl{CCx}hY_%8I^F}=2?N>o zvpIGgWm%TCeO8UNwi|PG^#69h>{ud1+uK*R6I8pa)BKm^`t@)5nh)Rnj`#i0wXePR zeRjIG0acA|xd5t~<{#TBdq>f?ZBuOxn6d=4MN8|q;iSLQ{sTa@Y$yNAu1Rk^1KR1o z2~I5lVQ2W~Dg4L{OWW5&R|B}V`Dec$ngzCCfX8V)LggHgYnuPr&gGpaKljH!^Vp|8 z_M^-F-6vP^G(U6mxmWz)|MgoB-TD6S_&ZO0_LG0Gd;Xb6Uy=X-BI4%O))qJN^NUme z0QKw_S2q~|U4z*+p;plHJvh)sN;>APABOf-;I@k3(sYL2;edSTRFP70yZ^C6+BUz0>sm`m>p6HnlX4Ri^%_ zX=G-qc&O%oz{dfF+dC-UEByo!0fgBXWDFF|$jHzfP(ztG#iROKB>_NlWd}7?A=mIr zurAyQ(`y_bkQn6VfCfWHfUsdF(daWtVerh$^r9XtqePT*Ff|U6A^8e*x|8?(Du$0DzsY9lPmk z-uvA*f896ym&b3q^}QMCz#heF0*6?SG*AHxR6&%L-a*Q=clpWdyA{$Z*y$IcVm;4u}XAyF0L$?a|() z3lBZ|Cx7@;&wTMyKkJr@i>n5j-Ez-czy7wbdC!L?)9ISM>z)rj`LW;o7uDX*#g`la zP);V3$)ud1K|`*~p6d--n5i8QQSHck<8`JT((RrYt;VB}B%*{gR5_l^BFHJP&&3Sg zJ)2|T4}BM(K4F)Op+{w7C*%;w;M1+1UKMUY zTxwujCsB=Dr$!C+J|za)a|p>zs|831h*O}t99E&T8fvzr-j5dup=JuhW+hd;4pQGm z61kx2reJ^BbmNLfQ9_+jQ`l;!h`Tbx-v$qOZ zVKmM9i&!)zlV}1kn^t0RNT%bEp&h4bL&~sDPAip$J+)s`BAr7`?TKOpHAaL{{ccc^ zQ^n_rRD(R}43C1f6dgam*HaPB(dVORT}^>?L1UTSmvB_7POzVP_Jo`^Gs8$s==t?H z$lk|ch|NOcb3rnpiy|KuZCb7Y%}F4gGr5TIwiT9FuPExgPV`M-!4w6UqHO-HESoTT0sD&xAf>n8~*o<|5^XKL=7;}zPJBg_fQc9;3@*n-)4_tow(SJqG%@1-ecg{ca_&wkLoj+U?;H5=9J$CMnd!P8|zy04{asU7k z(Z=THrZLtaYs9QE#um1)wy+XaLMw@65Dj!jydRPB&g6#xF z%3!K+OHJCa^-}0q7D8t$HDdC!YXwONgit_33pQAxHA_+Jb0#{pLUEp&fbl3t&3Gsm zYnGe*qcX7vB_lkg9}irAvNVbro_H$isFfD2sQtI)g;+@#@7_9%Y zu^4FDLh7?9{yEEGL`0V~)YBTYgWR8#(|E7I{7F6UNnk}|MWtRZV+4qqY3-QlKdkT> zUx?;kyb$Foi`lrXx+MIJ#0D%Vp*eXpgK41-tk;nFMEIw1O5SDzhqrN z3CH}@TVSHwJ`ms93gNz+!Q`!5$kP*3LO{HA^3Jw70jn_kv9R-}MbY zaP2+!eXlX)O|V!Zw1fsM3NVurOj&|03b2zBY*B(OCxB%MP!s^3_TNqXTk5~DO`~4B zMxPJZ(EbqsYHFKucAeVNtNGbxCg^o!D4@FFw(H~rwm>B{J^k<#pS}Nodg8Mm|B>1D^3iR<|X>a7KTnb(D9-$a7+z+3tF(ke|}*4D9uTpN9l#xz2VJfn8$y($n;yU z5t?xS8Zn(JjA-!`B*`L(qQE+~1fr-g<5{_uDc)%f!_9!B^r_rgQXBCwUMAjrxU_)O zSy%LVlMPWqZ!GQ~NEHJEpacKA5%e>)=*|oyHG#DbAV_z0Oo9<0WF0xcWo+|**a_M} zx?6$HDI|Ngs|zC0)89QZ8WRx^XZdCzdeD`zpoO;*!sp9R$eZ>g2WTuN6iN z5AD5@jd~P&7M#Keu44xlb{6!_OVqA*`&StND36`E>Bg^n|35f=*Xuu2OxA9&Xc5tXDGIRDDHLmK zP)sIJPA5=KCSWHMz;X&?Es%%#D7+OA4OmmOaeM`sV$%GvMWeN^9Y9?Jfa^35zBxyt zX7V4Wfdn*bBXFkxy7SAn2N8Tf1O(1iP*+Q+77Li~Y{Pu-%B5!?`rN;I;gl5e1A3}pEhHO-){#|4_DR4Y(Cr7u+ux-f>w!JwkksC@#yIdhfWSnM2&e}GWbQY$ zUJT6n*QYlq+T0FY=v_D1=0ZwSg+Z~Gni^s*2Ys+1#AM?E15;B>Iin9uBgPc!sfnv* zu9u@u6O1w>kA6n#(&VHEGZXT`7_SVa@j#B*1C!9J4FC)=0S^5}d}69;)U_h!2+qZr zMo)TdL=2^CYEAR=pFMN$kBFFr zsIg+N*RkRdG*^EVpg%Efbp-xK$HIL9;^rQNxm@_H2rnNIA(&&|pDqV6HBep2@>?5E|dVQmMdz2R!& zH3k7eAsywQ!_YpOGP~56EUMQ<*H?hbGU@vTgR;iucM2*4HJ!net}DZ+Zj4gSWIUjk z688{5zZQ0IZaa|dQ`NAm&Ase*u~;sE0T)C>byZcf{n`H2#5r$#=QsSrYhHEFf3mi9 z@&;=y*m4TRbOOc3I!xB4u(7rV8yoAev9S(zZ4Kst;2Pi(h+Ke%8$>Y1f-$z!@iX)u z0I`t_Slisfbp_yGqx}&>1VGp|?&P66X6n}tLBX_10X{mAsEz#-RXULa*G>Iva75th z3aa@&EEhA_IseS(cAtOd50?A84<6NtUG7{tKRI>H&8Kg>^WKxkwkA(~=1)Gd^URYE zz2pD@TQpw{jl~$#>dQM*KA=_;-fP{-)sD!~vZ|`6_zMjFSfgx>1?FTgQOuwaQ}R3g z1c{sIM5rnQ0FeE~zrJf(3&?Wz`e}LHffXHK(8anigg%Hl2~lION%M>f5^kiuA3$hi z=!+;WjnF_3etx=z4bxKBRi>}V^kTqFhEjC8?#UO~w34-tR;zz#;BDg})@_nc9SS7BThQLINWPe`F2q@xuDD=P3{ zK*6j~WFG^R=p4)%csYo|U4LB!%sBP;2?FDuMbLa%Ug*hxqCvzQXrN3$wN)jo8`xgn zSQ1g_zRyjPx!e)b-aFi@L81TW8AlOzhpT#)XzOPV0H(yhQzDHAHGq-TL7+$>Lwz}* z23GRa0@biM0qm*H{2DvNdmFKMNK(BPD3W(}^m8RL6{Sg@sGFneDYGwQW`~r_6cbI> z!_I`aqV8L!Yt;L1Srfnl27S|k*c$)& z=c*{m!oQa_#yIDkX%omo<_}<(8UO^lySuy9vRYoPweHx<@BF5lzUJ$HczXQAjpbwt z#dHnIwKdq<+<#f*p}~w%9XdH6;q6iVLT|0L9SDGce&Wy3HNNqBY7Vv!qIcXhj8fzqcn$<~rUz}D zp~S`cLd~=1J5$9V0U-Rlw*Gp(Q9t?NfC&LNh%v^RFlE8V0)?oqAeTnkHuTvVqFB+5 zYk<7Ff@c;`G;M<*elO4jDg^`u#*7d()+ij4Q4|s&&kv_@2{@dj)9;EC3RE2ZgTG0$ zry#OT&I5J*8XUktPmMRs6m6?a(o=xYLH~Q~MB*p_09pay8S}y*{1QInC3n?{Z( zz=tT+pv|5^oy2g4R;m%gjK4*6Uj@%%_{oMEhh*ec!XISJIiP|3cG*!u#!rEUSWN@c zC@I>}5{&}28lOS ziisVI`3t{qFph5%2{y{UA^n03bC?G)c@2JFxo8wL+!Wjtn)zjxr8g2dhNP@1u`bB{ zUSU1)23Gob$c7pRH11>BcG@~C|I0V-U0uep!-OfHF&M>g`xzG|fRQl(R{%5*NCnk% zB;~uTZp`qH0z*L(j@+J&tFo+=C{jIcu#c0KY#I5?`bMHp62mTD+;l@yb{?DV!!%R= z+BGxP!Zv+MBTqKQ7;9_?0L1Kt#t?9^SS+fls;+7UE_Zvu4CsvS%>^+!*N5Y2yEY`3v~2+mba zWS?^YRC^D%cGOROxId|;N*S_b(sne%jRaZ}c_D??Y zk^%tMHr6*x_hk*TrrlU${nXt@`qga|AOb*LyV^IV-UOr3J5gBdF@wLraDy3nbUCKr zuX*S|55m#ZH?hWAYg(YfH^UG}1XyNnr1!!Q`3|NP*e_z4#mL9*^^2_O(LCoImo-Qe zGw7z(Z0%@G38hY|Z}<&zMucHaI|MrYv~f`jqLH!-L|}n@z3BL5=4vznp*&R#7586$H*Sq|X9aZs0TF%VHDbJ$a_mzeag zVq|t0lfcw#4}lIV0U4Qdx$=7?QY8A63yNT`gSwg@RbRAPL?Pyl;3VsT-$zMl6)FuS zdw-#w&wYNCp&;n-V?8fSG=XG=bK=~AFva7=dI~Iz?*mM-M2OLi$1s%+^Ob&PF%!Xt zY4gMp&A-~7oZ+<(i1@s*;3_FzDJrdBy8ov@0kIFN%q0#~c7Qz_EGvyGBy{QOdL<0(u25j29on@;F;0wuQk06AoK}nVeJh-P}g-$K3U9501S2zfRE+kdxRgTHWA_o z)w20I^5%bi^ZJ*6RUaBXV~ZoT1JICcCuY;3Hhp_RAi-M3N+6(W2|#3L+m|2PdG6`|*VWaP zqdeD_ANj(^&)$3A2e(e0K6Bga-te}E|KQ*K+WwVG=U*}a006*rx;E|G%jR_1!WRC4 zt7})gx~^Lxi)qyT{gmHYYr93fMnHv^C87Dy zoo+vHvBl^!67?=OeVkt}Ymi2G{=9O76KEGTU<{B5%}pWRvS96~tJpC=aBzBpqYFEx z@=6xyIT!O(lR$?k2veJyVW3kW8Bok;I`)VxG7?$SBqRwS9D#=-wInm-Fvay@i~CMdTqann*aE5G7EQ+EiY~crd z#G)Qu>j~zZbI#R{*KGUy`}_3~GXT)q$qo0t=O3PV?Y-YI**s=XoIDA)o;?FMTzeXp zXyBRseYmhchpMjO*xCf9Xkeo(VPiT0M1a$q8*uvA2Dp}e@0z;}z%;adY!le{ZsB$K zR979=gw!_p{w8tIFajI_)()ty0jjE{^i%Wy)e_ud(YW|8<_(C@QTf~VGo}Y6c%Tyk zODbr7#uR1q`>uxB<>w#Ye)h?K$ zW>}%9#U#oZF&q1Kn|g@YJMxQMN9hZ|2#RuIp=3KGje}s2D>TG5bjW|&V7srzyLetuxnGqobu+s38n!zi}lAZ zqpVU5{}{0DMPdCXCgnM>B*hwvuBS9V%S`vBVR24+6}tZODYC(^&<;T=OzZ=ZSAg0y z=_xu!ta*@n?gu18#Ql0Y*<2zTIMpmF>z=$JLGc;ElGB4nO!j7}V(D&l-%G zEvQN#^DI%bi7=-HRd;Li!B3;_a>qoOE_Nl_GqAEp^=01&FGs)!uf zR@UrV({wL6SS%Kc{k^?C;z?_VU-r!DyI%Kgx4rkp7PF#xS}!Gi{FF^9`fJ@)S}Kl$ZfZgmMq`n7-lnTOY| zyYcRGcisK!v$vdk`Ne0Se*C$I9{9vd0stT)nog(F&Ih1Hy1HZl0&3zE4BAG?Vu^sL zO#%puBn0nLN-RshbD<}q#z3&A(uYkovY0s@mxH~okf1f`Yrf&9{~on#f%j-}F>Qly zIu}oXfRf~!Ew+#%*SAORp_HALc#04tkkzEVIWcKZWm|iB29TqytG?9LhVCWCKdd3W z4zN!W0M*5nUtdZ!Qruini$xoOK5H4^pwRnLlsH_mcwV(CrHpY|3ILFlTE02+&yY+` z$WSJ8pEun!9h`2zN@G7p+kX`AeHb~y%6X zka^bG2&pu9N5RnxpkZJFH+Y{ZIrKP&S;UG|$k6X&W<=Ty@gT8iU9!LmAb~22O8lLa zXhXX7`WTG`W3u<9I$1WDis==0`xs7t^@dj-RahS>&xwyC zQ{)N25;tU`M~E|xOv%C9%1h82YuvM0De0>UKVPSt!!TO|x(io_TV1K!U6Khi_t%VaCQ#iS~ z4(pQwmaSA^S=F*uXiWY*Re!MnH=BW*&w&<8p!V->F>f0Esxj$<79=27cRK&pQ4x$S z0H2mkaxoO;83f9>R{lj}FW`VH^+(|`Bdzr5Vrz5GJ$eKuEVY#l##+;|!b)BQsm znP(Mvo=D*t z4ZbJGI1X57ntB5uuNgwYg5bxUZNw7#er^&JHmBp885&{aLz%+CsAhrb!dgSc9gm9~ zISn3LB&N;*Df&D)$tPt>15uVQo3<%M`H*|R#_UKH=$OeMU$wwKY+-*GKY>Gm2Zu!r zBnai%99k6ISYyYL&l#-XYk_*}KaN?DbCV7X%tB3Qs&Udx08^2Hpn(aifHewqYt-EP z0U!dn)&L#m6IEK-yp>q9VY1Iw&h$*~n}IivIOoLpvD&i+qYUFPa=On(%4Y7@QKlUJajTQUQR}U@O==R5fhR7O=fPhb#MYsGNgERm1LV344nQ zCWVDbVPSJp!p7PJj;~Jv5utK5Eb1DjWeMwL0n6G!y|)L|_7$Mn9O|7NaI<}&*$k+v z!7XO()PLy*ip^x6Lwscc#o9XH`UaS_b-=YX!1Z;&asoIh0c`KgXXKLh*EKl_O%KmUopPj!9OA{XoV?8^S7iktP z;&Z?I+rRSS0{{RpnM^0%<>Vs?vSx=BGi}# zdP6~jh~!fPy6pPqA(HfU=!`YkX2+)VHuyKT5HLj07h~2M>nHx9pRR9;QHyl+M^_G;ifz2Zdq9e?MGPL%9R7Nu)G|9g{SY z2CFE^sJI&JAbGBj>OC>>e|tKAbJF-Au&Gb` z6fNmB#hI{>FdYtLvh7gRzrJakb?(PO1mydM)-MoEQ560|bZTps6y|f(ybr*Y%U3Q} zM`i$sc=K!TdGB5C|BfH8Y&m`Xt+&9*V_WcvC(pyh*&JN$fGP*es)G5lY2arq2vF4y z=Cy;J77W;3EMa@TfK!|6fB;Zf3)UcPObT$0;KceAPOeX&a5ZdSya>yk9hg1)G}YVN zQ19*{I0Cm^fHAgl;4jODy6+7ItpzhF!LF@?nNDG{wFUOrRy*l00m}klI%yhyq9!iT zIiT6RY4E)XAQ2NJc*6qMeV?3z+4*Oo+TUBAf8>E*zVgiD|N3e-;X6-0`pM0+FMH<= zFFSYc^tsz!vHkSpUwH0I4}Rvw2LPs%UIO5C{s3UTw!h7_q?W>8Etku>sw>w{o_Th> z-zbc=);A}{7*p4E?f)((B-B1soYF=F#5MGWL3$oU;Kyd#htq5It+kee2c8uW_;W?m zd4t3z{}?qz7$A$CsYkcTB6H9s;1Po<7gs(qiV6~?$d&~*u*JzRS9oIQ0+{yRD7r3S znlZj0scySo2kMP9Gh0{HhyCI%!5V2uzRAnT%u=d?(T&ZiZvlxyxY zW{=v000&x9%uI4~8RDr%fCdWOt38xE3J~CGHU6tiXNL|NGX*UkVuGF2$&P6LDM=sC zFaeaJGF6C^bm!0*D&6yoQDR2QlOi%Pl?IsNmo(}NusGKoa|V?B@gQG&#NHR!*{e&U|$ymwaCuibRbBcLJda%m#PXc_(-AAjwcD5NiEMtjHOT$S$ z0e4Z*C-&0OJOs~m<_&d{y?EMfgpN7%3IJt)h^EepzlCNhCxHyg04^yL+8iJxcR>{U z7>;Dl$YT$^Dtd%LJMT%q3pwfLpFhy1htG~tj6F4=0~F&&kaEie!!H8y1^}u?$KDTu zjKY`zmF3X0M7h5NrtX1cJu7N6PO*^j;Vi;0Ja1u27DT4w22Lo6o}9bOQH3{w!RcFS=&gIRZxnuHD5Qw4|`Nq$r>$4NRljRrZNaJQuZ8tfr(o;k z2{?A*IIJBz2Ia;En5`|q^>r|7Q-E^PJV6G5d@NwAdj{tK77L*Hyzv$2;sL2^`hCP4 z5H(%_h(L7>%k9gs*x9D-XP@|uCqDb}A0~J8rvGfQa~B_e;6I$X`%QoS)^oR%H@^Cw zcYN-5{-6J2vA?(dq5=TrWHOmd%89jwHO3mB24IV#uq~Pl+whB@7%;&=<0Y-noP0A*Q}z^C5;P&?-uXX4)VGl=wH-v_3n_Y-(vdb1Gy zGr<%-1OT)?BBa5Z&gjFr(0GrcxRTza1|pa_aCP^&Bup38MbEUX3x2#li!?NM0rEP3 zzF-bz+sXx-Z*aX6Dgr9yt~v!Blcf#A5q@!@jDgND#fE^4j&~FtP-8O)fFLV@NQ}b5 z%@fq=LYA_e(9}ggqc9g%*1?aQoLx=*|6!VcwaHq=z+VBhV8CP$S3F)`XdS#!Nkrsn zY={Ub%z#Hh0=lG-iYZBujzPgh$1wR;H(5%Wfa=dADur@vGNl*xIcjybX=f)Y*9;H2 z`VVQ+Dbwgv24K>`uF!2FnnWgiOyrtD2{2T?86G%bHFs>|)(ox581s9>hJd6tRDILY z>yC{wkq#38km;j!SM!KbBQ*Iu*~2J%YibAqg2@q0V#R$G=;pP?Zw$3RR}(0vg;9Ml z#-vX+twOFcMq-m>?=f((Td$Y|G>Q7N3{`YZ6m=P*MfBlv49_&?och zJw$>XvDqMrG@bBcT0hK-J{O9i8HIW*WeBJFEBUxU9!K7>mfJeID9aLnpcPJ=E2yz|X(fB(JT{K5aq*`j#awWs0X z3s>ODE4!U-m_dZ9F%na+YI{F-G$31A*qSybffHN6-jyrx^pj7)BM&_SU;4s>uzm3& zEC``q&Y?62XK%R)&YZgiPThC|Y@Ip*x88gMoH=zIj-NaUYtt#LZ*IV3GKGBrsEvV& zT>FSNm&7?S*{^DV`2w)68!B~OdFmMu`6<6o6!$ZXz89(Y_h5G6Ihb9!_{Aqa{qY~0 z?_PNTUZAh#{_gonY3aIGzV_W)Cr@r}oIZ2Y7e4yCzxJX60JU>&eSKryyWx96x~B#i zYb`a1ibFsEV@v}80CCjWvjoBiw8_Ne50R73mI=cTXX0o?Vr1tqv~q7iXH+BASS@gdR) z(V_>D&q5El^b1~3g#sl%I5t#)bktg==-?4DsBGGjCyALxoHEpAkkmP~p^Ei#CedtQ zW)gsjqDOV*=U|KC4o*S55@SAe44Z)|I;Slw292o+=qiOVB>*Aq-dWXK;IPR6hiQ&g zyT(;tPm5nlOh$N5_>N?g4SJc9etihi6weGG$F;o~ z#!hN#H|BoB0bd0e(Dvt=e@UaxH6nszwGx;lr)9Y&Tx$xoPcGNoQE{6id{}U-&&naC zGur)~ltzty{n&>`?n+WJ(`Uo8b-*WBL?C-Qo=yVKB=$bJhDZay;MrzOhOV(vCi$^; zx|!)%rjza@1F8Evv-b==f7&ySh{1#-d%Y47rIhgk0ELx9!lNL(*RhM9h5`8w#=@i| zlR-z`5SUyHU zoF!$_C;WRN5EyGLv>-$Wnzepu{*3t^gPe2LTHCOzts&sxR6Prv(TZn@*mJ8!??Iyk>OgU>$wJk-uX-8R|It7i}ajBob)X?wG< z7yyG%7z5TCST2`f>k6)1xBw4+@gaER(Z}K9g-cK(!CGnIx^uU{xw~Egx8Hs%oVnpF zoH(`x*ZhCXy?Lx{*LffI`_|g$oIAaFARj4`B1KUmsmYcVYw#?`acU$5>cXf~v~^;{ zc2S`AKkXj{iU2igpa>eEMNtDa(mF<+{?`U^lh#$7#$#>SspZ;|Y+0l@NF*QMbnm;v z8TMZ5>mPfqz1Q%qefGKUK9Waxdc5!6dxkx%^?kqZH|*^~R~i+7xAu>5@8|^gPfl>} z@E8Y+1y*&9#x$)W*=ssnb5D%cE5KM#-Slis8zQAKZKE*2`b{ zmHjtf`IUD%lJEAbU;o#apLzaAuD$Plk3RCu2cN(B^4I>qyRX0U=kFQ-pp;VEJKH;b zGtJS&(d+mDg08BH2xOY3X&Td5V@yYbajx;9j38WiIM55GH21Js?(*k@DSPOsA8Odc z^Z`HhjyB%VaL*yXsR3SCT!o89D1`{iFNwm{EfOhpK5!-t7r&6|$jL&g0`SDUjw0EV zCF)j7J4&)>Rj-~v8%t^P<`@|o98v(I2@)gl7En|&5Q^CsEXU9dY|1uif=d(jlD067 z%Nv>&@W5+PX=4~NXUpRFK&j4lNVlJv{P|4tvF3c?gmqwADxvwCOvp-2;=@W0IO|1` z)qChnB%IU@5T0zreL z5`c=Fc<5lPY-SC!YLoSW3Jt*6wPl?r!dQSIy&s1h*fV$f?%MZ^yVScTeNXcF%+~(& zUMzf;@LtY=ep<^cOQW5Uxb4$AubaSQ!n55-s7=QJZxT}?yY`ZLk5aE9v6kSqlA#hX z+3VwnV=;<8APIPY#A!Y?iVkbnF?W|_gvaaXULgQk7=U#(Zm^!Go(%opLrD??%u#>O zB=u&0z4+!&5ekV~$_ey2sNZ8CA%2982=Ga1j?LV%XjNP9cX8rGS}WZ$0NiuxN-GcY zx%faIo9@@ux?a^MCnqO30|4OJPkhG@eELWK)_-#S%9Y8z`3iq|>n`R^17j_$A2=xj z>$v&%Q*$T`^@X{B!u|M?Q>a zpMDZgUA=_EhB2=VUcY-Ex9%O{?YjrKd2oo6#S)9U#>$xXy%lKy<`&b?x9KHRuKmG4-zw#IVfUSM_)c^Dj zvbMhc@?ZYRlb`;+pSXVQN_F|U7ry(ezwyuiQL|h=wD+Rd{lMHmJ=CsIpkgW34TX8>`TR%9nmu+ z(g_1QFd>%&fWxXpJU)T;KRz!lNQxqLzMm+nB$c3)YcCZ8(v*x6-7wbB1xFQpDTR1V z!OH=aAEMb3BQjgf3m4IOh{z9+*zAm6EvOBoA{YGSH%1K?EvhN+pgO2{#P|q_#IHrR(6}v~`n{PsANhsD|hYjoe)H6@<&lsP1NvJ^iC^+TI>rn2aGR8zUj_WMNGfKk*j?M@T4m)}| z3leZR^?WD~2pCFW&4kREVET~_rH}xqsX=1N%r9f>6xPVlNHFSAx;}-1_-w!$VB;UgbCX$)Sz zbAbK%0*$e-Y+KYp1o%7A`{1KPJaYXiZan>deDd2q zimQ)3iplm4CbJptELOO6yuh8q6MX%(n^>MK&@5MI8VkeLRV7Yx;wJpm_G%z%ljmV= zr{kwKL;*xC6QT2@^`He?5VuBxN>?CNfwTgY0&z?GU*6xx;^6M$_RC-Wm3!ZM`B&@3 z$?E{@yHQ^*4iDZ~HRi(OFMj+p7cO5uueWwDzWl}C{b%nA05F+MCbQXerk!(t+vs}- zO`tOf^znMu+PX0fvt^}7d1|uP;Ix!?f+NDP^;DO@2f+7~NK9(dMWV~N@3e7>SfJ7w zA3qpQ+daY;Xudpv&}#7!80J{!B(AR*p9dB;zIYMyD4$IXm!yrPM{`wV90X8L^$Mu^ zo+9Xt20O^Y`!xtnf86X-GKB_tH-88dM#+UXj8}=jhsNGS!N zq_-b(%BOWX2abD@?PU)yT0>Ba1qM?cOCQWl;N}f)JNoYza^>j$5kJ(Gf z=61zfV}mAcET~B%*OoEhujC0cmXVaNVJv!6P#~WRfh{Q-4WaQ_zyw3&-k$$FXA*>% z4H>(Sk326)ofhxu;F8fG53XOO>2EUC7eJ0tKye5Hq@OMMeHNHdn|j#f%$}Ip#qQjf zfW&b|mW+}XKVIuXRz=Lv2({`I#F;`cf6RfGG6R5v$$aLyl1=tyE>L`689H1YGX0e8dDJN-#b$$Rn~WQ%)9GBox2iC@+;{lqMae&0LJGlML~K zMm917>yX(#Ph6TN(7IgVB!-IwZKT?;`G=r`#DL561Q=}5C@OlsS2S0U6)u5?%lrqT`=hw#?Nlof8!a{*cfwTcd*Zgsf z{b_!#B*Vd4sY=LL8E{BXW5tptb;uA=YNAvy=sd028^&t>rGFbi)gR;hAF*TtIUG9^ zF^Go5q3^plxa0s3DGv#_csC1Cm&sa?dTFEpRf+yjr9EljK9{aBC9!ux2Bc@Fh5L13 z&12ynmt*>d7ydC#ddm15`&^+ln&daah4noJO4BteG&U8@3d3tNB9|TDpsk=W9)C-w0qVY_PKMI6XEsa1#TUl;O_APyORpLRfRpRF$H6_tg$_*aPR0Oa4Ge&i=?zxE((wU zc1mSGp@i0L<6mhv@n?`RZMmaS=;CXxbxVJ%zLIb;SAOo?7D%x?{ESl^WUNqy(; znNre(;!G82g1MoJ>a_mWHH5uphXVS$<&sI4vDUJq^z<&Gw$t{7z61G&$cT*;<3-g* zo(6qXVII+k!KSTq9!*S#!pv;hjkO$KhXgDr6%0{&LzKo4xaSst2GM!Cq%|&4_aMb5 z72NTMD|g~xksm62S)v3=?^QB-EPQ@WUA{w>#n3qz!BjX4+Wu)9qD`NB42}6gKOc|y ze5W}k@^n6JERyVu3|vVXHeq`9py!hX%4p87k&Ph3`)@EJEMS18lO```ikeyKSHHAD zPmRge0WVylyAO~(ct8pxHUbIINTp*|0$7He&xh8%1k~W6iFh*k#~KMv$^Z+&lAZ-P zd{2o}%MEWVq-LgLsQQDfgy32Y_S!JvCyl|&*Hc1HXQm=+C8AqrQ%BWLd52gmk$jAj zCMKSwav=f}iC2sS6qT;QF5yXN)G0B<9rCykV=oiayfB?$9iSAla!Lq!(eP0;QB=8C z&VXbny_dtOI8Nb{lY+C7q#{_%^14?5gGz>yEU?CCpnm9^YL2h>Q|?9Cu?e0iXXNI- z_2ICuXCzprsMZ3dsa2`GAoLXI854a2V6nn-QKM$AO!ADiu-e{s6I_q?fBx7pg|yCenRlRLLwYIZKXc;f>f zd|~JE)$3-pJo(n2ed%}JaR$J2I-O2uvzhA5OBm#)G?h;Q0HNw8IN+wK8*8j-nx?VL z?6vh_L)}e$oDV>T?g`Ujn^EZEJkWF@=ohWnvmly+`z;RUMkx=|a zriY1cDy6uu(}brWLio8pWeG`Wb5mb{38F15AU)EzL2de(WT8%$t#lHy%2V(Nv63y8bz7 z5LlWhZt%84$xwPd79;2aQ@|mnQ0O6$YnUl&LUNyvp01k3&ILwaq4_70`>}k_a0I~6 zx+b*{VJfY6ESA^ux+76pvo)hQf#Zb!9W?0$U?3~Nlg4_m;bP_?c1)46a+BKH7lc5^ci;4-_iMht@Th>ymPY_QsIK=dWuX0B&Pe5$BdMA;=cRSyL97Sxg5= zhA5N)d<^B7wj8gJg?q65z6#gLWEjH5eT$2Mq7WjxOZ!h~;70?7jy^#v95zMgZ%7Im zzGruQWFUjZiz4??0V%C?2m~Ny=?36}Qd(7&uC&&=ef>86kA2dYR+=4qx~g;qCj~gX zfB$~o4{S31pG<%FKltgtryqUl)34px$I)`-ntyi2em&)1RgN<6QUD0tn(i%^Xl~y| zbL$qG<0D*s@(Dcs+y}6I@e+<1cy<2}^{RobEy%VXf2tIwmBOPtTiBgc-Ib!0#zeRH z$-HUWPMZ)I4?0$WH}&&Z8L6I;zzk&>Wa9)HV(ugbV1{XGG|M^a!vieu-iBGs!OT3F z&ZZY{yzjd&KKj(Zap`@}{Lsb6-~aiGk3IS6y{nIW#5T=*d3^shFuxm;0KWH)ul@do z7eDp4_3rN0`#${9PyOX@e&K&v9v>aNV*r4^!FG0cci9^2mow!w<*l}yp_Nuqb8OlN zC+2+YGcmQ+Dw|gK27^6U9fE$cH>&Fqc4scARB!0#8~JeQ4770>1<%LNRc$O8bKRKP_bb?A5CZxA|phQ@9wEkCB&x5)`9a_>K9=!ekDDB=hyk1~5F(&+n< z!QhY~6i1uARKTY)hY%cr5H%xB>AWuk()gUDkH)4VmTopdhb zJx)lt-?+$ckdHqnU>6G-dTF{T!INAnd`HA{g>orQBu(K|+V4rK&=5&F*)WPUZ9LL- zgT2A)h{i9iyvNFg);03H;m@xFs=2ERsJP~K=EC7|1|tOZC9oyBRtSPoqY9}0YE%>} zviLYEcQOO%B*kl1@W)6$lN!0Mq_Q7IE>oa^DK$ds^@j41QNVa2byx>}rIUWi|F0XU zCE!pxH6Oeegj$Tn?^Bl|5ld0PA^TA!@vS+VC0T2t!IC1$uOhAU)B1=Dv5h=%uSx*t z7~^3tTaM#uIa(JHNCG%HU;Xec2-MO_hm3&8@UL4doKwB?Q)>r`ibyL>-MImDRaH7j zb3nitKG@&iw+}%7fB*9z`P7Sl^T&Vw?qa!pxL9Ikgyvrl11Bdi z_x53q4xzNhlg~egOOM^ak*@Ii;T(78OVG-IOzYaO08B`s(h57%2`)@3Y)>Yrv;s4* ze=^70_m6SBYOrGKruyzOQ!VhoL1AM9aDcf|Jti{DE@mL9O6 z?mfiO-#s`YV`jZ6Sh~)J=}p!e>z}Tws!A)Zs!26rYi(6k6+j55{&13G<0S+Dn!2v< z@9*!Qw$`X7li6o}{3riwd-3|W@6Q)lG^RhBx}W@$Qr#cruTRs!9v-22;|(;22iU%P z6_0%2Y3yFSh&d_To-f<7$XHNg-DDo92$*UG&5WH%g-6b9qiziD9G>9q`$xFHSmN%< zylwsoU9;~u59ixT@5B6aeCyw-? zQO#zkW-};KP+CJ(8cMZ)s_6{6nvkmW-nmB}|86$M%n$DVg*DCbI}HLHe(TjgzWCvf z|6BUPrK^uT{p?3>{@MTgFOKir`sO#~-cBh?Z!Ln>MYRvH*r;3#aSc zL1zU5h=xyTHuAb6@C<>DL363(@1dfXCHBmKOLw}?@#xoyj~lO%(ZmLU;FOxpYjnv- zG{|FE4;!;gMomnUW8D?wlpWX9)xC5bazblIlH4-nvr^8p9~ZGE$)f1=x6~RSs4&?a zSRW*Bn4z_8oVN;P`)TyO3@6T6K**-K$&^|EZ#nT9D1kyHyJ^1=Q_ID~nZf*o z9)ur^TOI(0llwAt(dUv0-vg|bnIUMwq*K0FD6bEaVMO_!kAb@MY4fP$KB85M0;Gbp zBleOa!~kJDA;%h)T?xPrWs@nb28sExbZvz7a>#m28Llb-qk2Y7IJkly|?+eiY|tz=a^Ni0eo#Y}he}XX0?V}ds zX`H0r>Oq1QEDFt6N(~%InZW}{J{7ECOZs4`&X6N)&ellYM^jQ^D$WB|LNJ1r8o~nqOi*Y~bL17Qc6zhW*SO4FmunqM8ckQ6x<9&YJBo zq@zVaeh?R@lpBKy#%v+IIbPF1yoL&Eqf~=|OnJ$lWTb2Y1IC@}{X`xv5Rk`+l6-%a z{22=7g%q6^%JkOa^k10zue%m`fJHKDZ5m{t$gzM$`O60KsLT*oV24P1nY8!EW@+iU zP-3)O?zT?(WH+T(3$n4iF^VN3DI6#H*kFLZotl!;5R+(x1Z=IwKXPQ3Qx48LDux2T z5zag|%5o`;VEnE79V!)7f&_-LhMHu*qk=nsww?>X#Gv;=0r*EjR@M&mII7Jykq>4G zFRs>YhjARS9uP?(LjMiRqUTC5JXBr8cFS0`;ZQD+1N+y~TI<*!ooCQ5G)v$T9-ZRwlhzYc0ELUD;wMXo1^^q!fclgU@dIZz?cSRvB3Q8H?g{R z8+KKLw1(0eP#S77fu7B}W?xUHE!d%bM4(SP=nW8=4M4QLxPR}Jqg!vDxe4Ex$I0!R zU%T|7kN&{9>o=aV>3TE%~s0fKy&wHg;SB@-7)%vn@oUsOcW1*0UCD3O#ghDADNMqkY)^QWKw zm)wTaVodts^3;$=y`B`?6s2Jlz!2V~;K)$;xL6x&Mp!a`+ob4zkcs};)_%0P@!#0v zoJ`N8Q8_|zAT7#IA(0RZ%tEZyn5H*t6s7l+xXmMr&*%@df0dV0Y zbs*#WL9e4Y&RB?m6C%?_Kc^c)ZA`l_(5=I3ugK6kgZqjK?22{k0}I#c5U6(M_i2_J z9xqfp^xgvRAL%)yW`-RYkQ%*7`$c9-97PbuN0)>sLsdGK$zH>S8)6d>s4R6D2LfcW zr-GkB3UF=mdh0+Siq_;UBtyZX31%cO$gimwsA6Pk9FoVBU)%j4FG$!*2QDZK>8S9&qv*nb8R(tD zz1+kfyO#bxnZWf=UcswepAjZ|c?q@Bm0m6ui^Y6?Dh9w~FMRy3UH{Av{H&U7onJMk zZJLz=Y2}((W^H8s_IBIwYYkOZ?W8{(<#68#C|!XRfi1((;t_OAt)cG}fC32HJlQV|m=Gy;T6`Kp4M_?I)L(L(@D66XMQbFQTublM)oo zGTi(0egT|LTwND58sTMrrC=(0~PzdkFM;sMOit z7tuNZW~6AJe2S5~c}x03A7>&V;90XR6q8(N983QuMUJJ0dMp{tCDW3$z|Kl#!B>J4 zS~1pW08_9cL!j5hT#?xDa-uoqf>SjjnrO>nl$8UN-qxb3dz9@-d#AH*vc7-OU#`(8~zpb@d=HZ(}q3t{>c76o?QE%)1hQQ@V1cX+ha@)b;rz% z_wm8NKqSwZrfhMF^9F* znn7U8mbBJwN*d$f;NYNXnr71_b+WZ{aqo#|K6~NApZHP3tXyP)YyK6K0|8VuX{r3y zz%G|C`vz8;+lVkUDa6LxrOE1Z(_B77t9Pj+rs4HCFq?UsL2$1GHHPh z&lu=0GQfi&*7o-H&hG9m6G$tqn3=U!T6d^bNTKWVG>vJDG1ef^&4g1S z|2vkgTe8~;ddLb$7ptN8kd}VmI`!v>t9OJa(ux#F5xbZ_zZfZ}_4l!b0Y5N1Cf@8X zro*E%!3!JsPU{c`93*+8DFVq380kN+<&X;Azb?365c|n{W;_&9p@Qj7h;*irDxR_w zJJ5q@3=KL-4&Wf2VW{CRO?pEo)zXw-(obWcsTw<_P-`^qgUy%_gGYs^Hfd{CBCQk& zB{W9nxxn(simNs3iTL^u_g`eVm&w3F(4v3eN|>C}(7ql@0zw`31`LeQCuEeY zOQ7~+ATeajo-@*HfzCgF(45cOoGPC7+xaMu>ay znsb*8W-_x>B*1k`hmDF4;dQxduX`_z(t6YRbcLTKnefM-m$I5GN~%d>$0$S0@z>X@ayhFH=4~IzDRZy54lnI`{ZfpS=2QpZUq{tB*X_nfz%D zHLcpHKdnI1t=0>mZeWg&VeZ~*!GQ}Gp)OtmcNS*Oq0hy}j!Z8jkn$;3)Ee_s%?f*Kw`K{l;yZ7ML!M$5oKlWFCe0ys~ zv-6jpdhP%DzaN+dFbV*$*4hgfFJ4p*v9gw}HP(21&iV-|Gn321BuC{p#u#g@rOsjB z*mN4=?yi2?eeCR>W;^$~qNbYf4NTPs5-5x!0AICTmnE;9R0g5R-JpMDU0YXK74HhmvCv z6ak|hc=jfPU7tgsYSKQu2U*ogsg(k$)}69-L5tYWrf%xHckkXkjqGsy+9NMK^2zV| z89m$HBM?+oLC+?w;azK?4>g&9=L^`wBbdWOU^0Qeb`7+(-S+$bWv#n=xsyD2Ib^SH z4gdj0Z|>J!!whI9C;(cu=UKTa0UHChHfY@YMYT2i(;!l?^AoK0_t6|4pgz10HJM_1 z@e=g*4yc;Adcd|#yps+%1feq!glqm0q#txY(@tMuRx6m*3TzE-z5JE`X}*8wOYdfx zcyjBluU~!f+kO<6u3oQp_MW=)l`s8^<-xtzA36YFj4@kVv#rh<-?Fu)F@9q1?=;Kc z#xzE^k?vjN$ktjFpo<~eY&~^8aKB6`Qc)9GY#iK>J^G#2#6#(pui%OJDw>WXqoGpj z6_7Nwq_jftp4cshiWIez|J>cTZ}M|mzqANNXrybdBhQ6o)Ay!-QoJ8ImPJfg>;VV= zTpkcepFdy#YWfDbz{WxM`@^6$-Z4NG2}GBh$l#Han()l_Cw1 zAk1kOyN+5IM&e|&y5QJ`*HibY{P_(F6VY68y<%8oVkFF+QsaNx>Hj+F?bs&21PGit zGvExJBiBuWA(%dK;hKX;1ukhVg9uKk$sM|nDNaNVovAy}E-@M-;kw>LR*^Z?Cu?`M z4iuymDBPD^V&Dh{m_wBEl1W{}zL7x7a9t`C^AJoRC5<vp9a)l^N~ncfJ`_UXoL-mxQ8coN-!GB_252T zM_hL~`y8GT!wCeC8EZbC>0IjXbz4>3|28y3zvFZNCWvS{*?R1)Kly`y{Lle_76h}n3HF14= zmuahYrL8f>=jwKcIfUGe?GqurFeYc#VwPR{7^eQ;oyXPQsVTggkCJfNKRpSp-Y zv{a*jCg&&mx~eJ&S<&s&1k|~}@jucUxnt0J8zcZiIFCsx^pNfzu2SJ-zn}1P{~p{! z@;*qX`Us+M`l105!r6fvkvBk(w1zT(&f&yw2!c!_MS{JPD%?3y0RqkGhCM=u&w_a% zN5MLU>6J)Riw%0D0)z&1?JT*p3r@~MEQQkdB~71yuVGUWX^lH{+-c@c*_@7{MQ+;Q zW29bm=z1zO`a@dr2Q_nx;li_H0${+cnnq+@7lE5Zo7>ktG&pT%$zVwU!b*)&Y9yD@ z-hD%|=6nwVCL#oxf*64jY&50k7+guOp~6Iug=V_sYMmzvP_|xSfWF*=eYqQZB&SGn zzcCOi2C11(3_qpDxfDl6r?~Ie0<1;W0gW?C9O3IAP0A^q^hHr&JsVA8VNhr8E$i7+ zDP7O%iqDi2gmCP|bItSUstr9+I8;jCzKI>2fv z0RThBlo^;dw0;DO*J<`e7S;nQfc<>ReHUvaE@nGT;Qm8Rx{lo&|N{6kW9 zR_8S&1IVdiqG%S|cWnr>s={?pb*vZ3S1bAS0$3I@a76?p@!IN!ir#!YWOSsAS692w zW?Qq#bUKwH1v?2YDXJ=6Rn??wWz1kjpu2bO-f0unHhWZCJD1Ks{h_~l;pykTkF>D244T^fOlGn`C(Q`*V_ zylEjR;f8F12So~C>ze-+n$;4fUSWQ4_iJzc`ImkH%r)NS$MLNtKh32$hX z&_d(QEpYxP5L>o!<~?Vo9MVSXDfnIE?-z=oIr0s&Qq3OQEs#IVe z7)`JOBM=S%0Kakf1T5QW;WLz0cHKf`IFb~!Dw)DXKuWT>Q@8l5NWYXWZrK8ze4WM@ zQh~x;G901=wCE=g>}wuI$r!KXD4x8Zuy|ePX6`pPib%{7Ep1#QsR|}aESRPZzduf) zc!ZOhhzQrkrXky)(`nSE8Ozu}GQp+E$Ur&(hSC&H(MXJ81w1edz&R+M1py$`{?WP| z^8r2c5M7f-fM^mcfP`Y4QrSx9p%T9^7ijm1r8t#R6^8WhCA~Zi>gY*09vlYV%OHy| z^`tcu!J)> z*0HIE{11jeK}s4&*@%{8Gq`{ai9kju8wE0Az+7T}Q8uY8#p&6UH6VUQ%0QiTuMMSn zV*uOq`AIN^^qvVJ^Rkn*2#mYTG%h@kUIyR>F~#*aI94UiyfhhK2mF@q*E=vP`bXQTq%Kl)2-QV*hj(NL#zTH@kfeORZS|Tl_nz6u8+{||7mjcf2Au8MV)N8 z?U@M2M@L7eF#w#NyYTpp&wT#pwk}_NQfUpn)kfg8A!G)M2+f;sfpi6Z?J8(CgS8fH zZAZuN8~*-Je*$|@fVj8z^Y#r2gvz#m6M%DDGi*;Mm{t{bx2E{OqgU|Ag*`lV?GkQW zJdd~ck6@juL_xvUE36jBsE_tx*@6i!wr>Jk*KPA(wFZBvD$t|?CKJ$X+Wxm|`bjIt zB4_~(%0lJ1PZ($#nB@Ytu3_pG%xY=wz4p>Sx&PMd{~O*554KHJO|D(~@JByK(;01F zy7JtcU;OP~J|&T9JOID|E?>EP#iPecYwaEU;hpD|QpQ*VYI)-zMNLyTtJP}NG))t_ z*meuFD}JqIi-5-8$Ju~G^efl6aT4RvPwEj&wL|@VH!U}&)$6#MuDcoiblQn`yqmvr z(SfbBg%BF@grGnOYLK6}yJP^5(EAN6jT*_^og*E7kJ|T>fdqM%=zRi`t_E^bxe!Iz zOFhEl2+~Cx`!-FsmhR!QO3gv@3 z?xz{<16l|PIHJMHbgxGwDZ{%kIZKOU%C!Hvi*M1LJ24%Nule{G7EL5ao>wUaBl9jv zntL%fdyLPA@cwwf?6Y_+u6bQbrdlC*I%*Oq{2UT9xwOa*MmVC>VJPNqV`fhx9h3He zvF9PxjE@1k(sfK`eK;UKS#wiRM1`@nA}Gz`o;)O5N_GEn%>a^EAy{*d_s54KMoO3v z!zt^`>w1IdRY5c9-;`|ZNrUH4V$+dOw{Uoz2c#Vwa(j_G|BqoCW&2xU=umoo4tz*B ztqT*sfYA&!0r(Q9`2o8sUY9t#*K^}ZMRNL77%}bSwc+OoWQtjQXz+6^re$z<9g6j* zxYjVFl7kY1KV*_Y&SbbK-9LeOwU0Ot@|^*}*xEP#-7w4jtoDON*XUSgRs?Fz&s!70 z4$!mK`sX-4K0ZE;0pQk^YahJ!(NF$6TUV}L*RyHc{CD>)U=NSL#y~%I16FBRW7@{Q zF=&&{lZL;W_&Z+&*Yp!&R)B}zNGojX3Kw^_@XRBZ@zEzA#bcMweU?0@&q)SLhtRNI(M$6@)Ln(Q>e)V&^l=JwcFDb z?0f;#HL$9I)e5|-0c%9qik)8oF~c?uY~AYqO})a=?VEq})?a+-?={QCTX>H=miOm2Gg743vTZL^W4&9vwZ{4; znUqr2THBb$H1(=(j5QQA|0*iFeDB9yT!wc{ZWT3ctVU=)6Gnw}o1xPJg`06FQ*i7i z0%0=o4j3LSY_Hdp7R1)tFl;`GX7f>k=uHY$s@e8316PE{^uHEqk0#YgGwtbyIVuTG zOa9dOPoi8Ejjx0vSc((M%?H(>jeN=Rzr6Xzr8|*|^stfR2=5H6 zajGA)W^%#gGeL(?qNCFQa5c2P46$8AhkbEPA<_5^iPWVe0O@NCMG{>(oCt?zxfIkV zG4PL!8G^z@oz|R-aH1Z9`y`Fm)6bt6S@Ied2d!DVhwev}X3LA8B{07gYpCJJB%uBO#)u-APr^v`mvtq@#kdC|^`Ol$3# z)YiQQTWfv2+!?29t*vEyu)n`=Pay%=y7I_#k9_KTermF_v!$vEN^8IxkXFFq5ipxU zUA+cNs%!qeX&z-eMs%&^jJ!a%-y12Z1p#t0mYP*rvhi_~`iN*Z$<{Bn zpB&x3^#14m=JunH-9TMq=gOncz43>?`43O?9`zh{jgPE}PE9KF87g4}f6TDDp% z?dk4BpnA1h`3b&{5AvW`Hqnj4)5rd+jWu`(i%A$FU-0aZ+rIkZa zp(M+YSOx3ca0jM*;f9mR7ozu1(ecUjYe6}iI=tuZ;kgs=*y(x%l&k?*#xP5YQyK68 zGa%L@N~VBgHI!!o1keWQ5^I?ik)aaBv43tY?NsECKoEn z5R$2j$o3G5XIj%t@H)1NRLqQxrW^?dZhG=r04J!hMorg05Lco3WvnmaBrT}A-794tnuVHgtDUwSNhV4EV4KTpQ7oF%|SCWf4u z>q?IQ()2tWfJoA~)JQpef2rSsILS{x%LexakGNOUMpun8)9pQ4IXfTaYncYvjN{hq zy!jUa3JGK#kQz$IDvO#dNRc?3nj@2PcKbo<;}EbqBm=<|s4vC3rtCQy!LlkbrAVk$ zO0`5dtcp#jX`Fm0b{ZouDQ*k;cJNkJRTVP{ywPEMIK6aOYpttlQdL@O24h-HDso1D z-J0yx&R(M2G|l~kgM-ryEG|C#!Vh2h@JIies-{ytan%3C5;!@50ie!b0H`Hv!Cns1P9YS#fqXDG|Ti36Fc6Y(m1b}Mg29mL%**lYdWl}&AQpRpbaKxC%V7qQm=O!xVitudyLL<32S zP{B(`1$`Wu0tBz^9fwIQ+&T+uj)Ff# z00%{6VhY&N zIFZp#JAg^}oc;L;Bl#%S^sU`gX*9i7`g}BEVl%XPjcLkBm{v>1W>W0dSx^2qZRR)q zMI^deNSe(77E69S0*{D}9l(PV)`+s18UhxkU?O`ab&M`d%V@yxt>h!XB{%SN4G!0? zM2`z8iYjbA1!e(8`bms67Na6ao6Bp~z20C-PH^mpqW);)dqz=bK73rtUJI0;$90+X z>Eut+J3~%_h?0f|QXt~VDi<4#==v5W^O-5xz}guz5hHGG_xwKcH*a*3)D3qX+klQ< zp1yOOW{}>O0jNK!K~0%@10VqpfLqzMnMhZ700bNxGfK&NI0o>O5)lR`_eoktFY5!T zEV{Q0HnYIUDw*-g@0p7KKJ?lsF(eDXzw{g|?jI~mFa`EN{Ig(rh{1j)XVbbZHOcNx zFi8XvDVXxNLqgqa0J`SgMVJReKpWKWT31?Ey3)=!t!Dvrsd<6#hN2LsyL0>Y?d4*z zI88Zm{>f*)^YRNH{}DZ%Xd(p|13O=Uw`NcmE&xikMt_ZI|2QCktp%Bu60e+GplAKH zZ`iFi?V3bAGN2Sek%HD5x|()=e~Y@omAxHIrxkcU$7|ns1r;;idgWC#ixb><>Tx{r z{>Nc=cd&i#JnCwKhC5cAGb3#M)X5nWa$SQLi}vr;s{MX+dG^f>Li61o+;WnK8n$VG zrh#o5nAHl)qx(1C{>GR8+mm~@fB(HS{r8V%esb{m=RW^4{s2!Wv&%QX^!va1@BjdJ zWOsLWcL74BD@_5GHqn*VosPxj9J>bJYv0>601_s_=;Hc%XIg5b>nz)J6IGEbZ=dBr zPG=uBv0ehuneHi4+NA(=H>$=4{YpfJW&i@FQ1}e~v zA(1hV&|t?vL@@nGDbLZAI0lmPE|k4^P0h=0^%50xkQLz9oI(>e2#O5oe%D24iq~+GmXVs0$r@AvOG*CYw?eWc=?O?GGrKiY3!^DLS&$sMyeqH)<@~y;h}Cu>|ZXT{9tbgbRQLNs^)s zr-PiDqY5&XO^~}(Crt&~b7%SMCw~P{$~P??xyOP1@%rC4H66o?5l5#9jji&vPI8_H zn{Ba4roy_CUw=dKdaA&%kX`(_2=jW+9lS)33TvWtt?)pqLXq_lrcb47Q&Lx9K(19X?CXwe;4>96gu}W# z^|gs>FEv=7be=1&rf&zI0aMnmX%2AkeWzzU>#BXU41g95Pz37Y(S<9{7-JTT#p3?K z!2t`&Uh5ueI@`PQ;ZOXHi_d=ebGn)+FtwPpp@4# z_=25bNe6r_ia4eO1%_%}0hnPKs2hvj=>)4)jpLIOn3E%zJGU{f8?5FhIREG)c>i-B zz_mxNLeHkyU#@V}STxr9z6&s>PayD9|GIA9yD@-|{ZqP24T#wx0fWKE05SvCv=jf8 zoBY=+nB@Y^VsUckwXgl^op1cbfAd~&{+Ay0$?=`{efIM|r?+=zuol~wu0Hd|AN;Fd zGOOiAY=w;gfNC<6X0)oEHGVU2~pKsvVr&<}iSxCa4_E z#1Vog^*4$)3draqY`LC_R;RL*2_l1`XoIzPJUS#KzqPrO1iCh6x=GerqG)uH}hXvnhZR3roO zg$0R@$gvq21^9jH3q%EsKlj%sVH!%o|Ar=a>GUH?v=D>IIG;`>#WH8qHb&@b9G-J8 zA(5Jcp{W@}7ifx22MeFQqyGzrMy2z->7;xJfGDyIHqeru>C}Iyx!oixK+qsZ_fA2! zkrwDuI)_NpFX^cZ+S8J8TFIy>owkzDB&OaZEV^!^+rdj3^3*ScqsCWe0ZG6Bhk9ng z9FC;sX8@oWWXGhZJt-<_%><7MjUElKLQ2w~tocs9CV_P^h8@9$X{e6r82%Oo4%*n^T1i#w+H4k4dhMij;sEO?tama1C6X?9AF95G=zBgwYOWU=8p?ZN93$v~ z3t!*o`yR!{j*-=3`+oiOzpARLO&4pu1eEImS|5ORxTxJ=kX`H<2((--m*!Ln02d#- z`0NWmbndBVKB>4JSX!;2X0x^dZVb3?sqcNfUwfLARtP3k?YFI)!fPFH=s5rb0CHsI z?n+s$pqC4*?%cx3(GhU}0MA^#gew=$;o6f=LZ3T_dTWNO7tiDFe1Y4?bG&`LfHBq) z!`lfx{OPh5sGAnB;8wfenz(DYMz5DIxcMS^&cFZTKa;hvO%1zhBmZo@f?Y0QOl=O{ zeD!~S`=u}ceY0A;iTCV-?fDx|erET5@BdKiC~4LF&dqNee)E+-e0U510DF7q_LQgF zTWgUxt+TbZ|Gu%z%uUlY#uyVC@gcdfvJEK4IXfoY$n1T*s0uj1&hP2SI zFhxLz4>VDp@sm$WeeN!Ik{I&&o>AKuFK5!S*N3|*MR+8!VDvV^YbR>4#sRHS)j zQ-@Sr+4~vzvU1%;K`5xG@Tzovip`Ci&e7FmNfh*I0t7;3W>@l z#hk5~=&sXx_e_VNa4IDXh?`qdmMioYkt^M#Ew(cYB9jD9i&FZP z3e5NhqaTC&DUC=jCLM_~WQJ!ClhTSh1Hg8rZiWB4^4&;iYiNx%J;2r)f?I2>XFWGf z(;OWh9-f8)U{=eciywUc2hTt8%y&W&SgF<}ztU~<-!x!j`{v&_{=QYBmLb5l|Gv|z z02KTTRDb6*O*<2spMV!9pt{EO^SiL~IUc`$71ys{#kW2840bME#NAbc+p8MiJUqh9 zqhq{u_W<|i%a%D{4B!m^I$(iYe*!elq)@AN@?TBbd%+qf6KD+#MKO=hWVHr%wS-wM zVOPtJ1z?S_N4IbO@xhy~{@#FXWL5-&{EV*@2cA@wONG_AlYK%x<(Y&snp3L-B8k||hb`r|;Fkj2ok4T7jh z@02Px^c)q(oTLmydBIW+t>7Zv7yUWnJ~%ZSXnbgmMlX8aOdpM$%@FCb^Ms33shys4 zu~`WN7bo~-TI0q0AnB{WhbCH5$UK8M>#@m5?4Gp`ktRzTOXSm&(YQ|5akKZDzVBKpu4*)n) z2YDt#Qv*#CtCK~eBnvjCqxzd=>mOk28nBF`ySM)I`0mX=+5grz{s-IC`|ouCVE5XM z=dV2fvA<4L)kYXDm#a7b=(qpjLuCNys;XvNTU*9j8zNejYm&92&|7P*aTCKYD+Y09B7t@i_G%09T`25 z#N!ecNIYQFlhXO5Ntw+&5`<|(q=!3Yos>AzqqNxrDHVCrG)F2p)=g&D713v1 zEb0e1ti;Swz2o1jw6;z2S)j;zX9rwaHD=~E>R?4Z4*@&s}5HQ4< z$cT!-AP;~B5qKfEb!UZdkh|VW>)OJQ3i5z#a=&hU>fQ$x!L^~}jN<1F%^1gA$4Pp` zkVzP=xkkn|QzalOb_ACvzntw29J>Gt_fMIhg00F%jNqP^)K7~bd14?5ePMp0uL<7Ly<7(=A!;NHD^%_->r z05Ca!@y69peEQ$szW&&=G^qfK*5I#;`a?I-C#`y2JODP<*A!i5Id?RA1-1-ctzZ`m zz%;FNsHt&bcN>?lU&B*3uH%F6dkjxJat+g}LRD#0T0s%vYd7!Wr8@_B`OZETmcg*? zbAwt&g5RB#0|0#EZ~6&8EVm4S+O&uuW|r`_%XRl$y<;n4!0KuDtp$f9)3@DgdCAQj_U) z>f`>ji?;~PENWv60_}K<1{l*cb>p8SnkKvFXvgA~eI$-jT7^@85^hKj3iL)eZu%Z- zIRm#&Kdts`04p`4!GhrtyEImh0zIB>11h7R?>qgzKXzPzXdzOArfJ+ok@TqmzR2i{ zna~?RIpi~5z?^}T0|`?0fk#heoqp?~kmkTjn{ccj%$Db7{D2af}y6Z=kSPO+nO6kH+H@WakXAGvmKY=#@Jks?@t??<4 zn!~Y;d1=x-wBC*dZ`L&!5mmdB>C4yqAfqX!Xk|VM+38FG{-K5snJ)n6&1_=E2*EV1 z`+Y}yM9Ie^X&hBl2T(DPU1C6l*MQ2*Z3n>PLQ|Yl`%CO12<#)3`jQCODWCD$uSPtX z)UcN7i10jbVt^~l72{o=Mwkg_%$b3YrxK4Rl{D<(TCP%`hUD7e#Hl?6)ufstjx%(T zk6p~EqH^Oe!}Xy&Ac`mL-iJ%vN``)&31NT_cCuP$0ti?8x9nt6aU8Cb1Gr%)0IU|v z#qsg+@oDJ)o&oU4r@#O2ZeO|f7%>BN18y3poA*sNL22DiEF0q@{n$;|RgmTFbo5%a z{dcnh8-r>x!E|dIv+ZrX_{>vy?ui??w7ZS%*$kCZST+`~?jPZs`-j*+S>WdVW86GE z!BNv-X)J1Mduo*Xqm*MJcnLz&v}^_2rxj4sHvZ%!49YPT+S8_b(?4dAi}^EktM_kC zj$uxYVe3`zBR~WwjmggL6a47R<&E!!5&0@Y2^Skpo^sjEB%E}i}+ z?x*!3O^C9|bu_UmJbVN$x#qXe*>FpcH!4gP3+2K)+t1 z&9fOG#kjd7fPifv0TQX9UltSObV!JdPSzWwWx48EF{LPTh91bq_AayeX3NMOxdmt8 zbXqPnGSUXsX;l-jK++_K$4A;6c}?+wf-ac@$7=}g*CFsjL3zT0i#DW5uh1-|i3p*~ zZ)q|>1C9MA+FUw?c9IHHVT_1eIulxDA)Vn&*#HH{ zP=c6IN2!E79a?j~RY|`;;5o4_M||jY$3|~q1k<2v1yl2?0q}|oUI^uekFzx=lxwi$ zGG5Tnc8zGn^crSgq||B2m@%LFF{CLVZFt`fovU=s+GIjJmeIq3GkEE$8j8hKfeC{I zPK#HQz}y&WMmU(rv*@zV$;6W5HZNJJ>PRWhSdG8>G{t&@RGDH1vZ)eC!+ zIB+R21wwFc=x5}{T^=5hyT8-;ZE1+qU(1{&Yx%FW*4k74!+VE9J^FK40&33V@+ev+Yb2x|p zw)tjb+Nr*4{JD=cZ+}|3=3iHUQlM&r-E(`mdhtB=cD8VNcN@ksF7IyRPv5wOZ{0t{ zYj^f>^LU9{Cv)7NuW+zfVO2L^%UIM6Dy#;&MMO>0G~NWTMYW6#A6+pLAnB@*N1dAP<&!FZ6Io6R85Jx5U6P+KEx7Bc`)Iu+ znV=Jy1jSR^ptmM`92l%v+dAEa&3ZIlcJc*p?%_o9oSMft`vf&)rWP^)Iv^s59Yi+e z<8t1&Uju^I2_sdaVl^x(1S7vtn;xRJ`3tI~&>x^bBB%CJ=slVkA!Ss#&`3~dfZ~Zq z31%u6IaHXul^SMoTAoP)kWZI{%~LK4bC_V%G%by-8aZhnJ7LTxSpz>mkbRB<3*)qm zfo!sUM$v(>$=w-b$PV}|aG~j@z%iMm_`4L$ahHt>?$6Luf|DHiqL0Q9^>@gVBAV3Z z@p8z~!6-YP6G#4%55v&?Kx;r7Nlt`h>NWJ)a~8yi#xpTrrNG-H1hGko*(z1fV>Huc z4R>-rQ|kA?b4OrC0c3?pjNj~53B65H14g72;KV>q`VcIx>nf8SmCa~l)C!FAW z@FHa3M*d0Ylct8*8mjX(qma3r4a6*`X3ze2w4?pE=HspFze`28N-5?00_*x1pAK+* ze0+S`>-540KJ-1;KK7kIrYu)v43snbYlHgQ14pjyVFtMJ?*0Mw#MAzj0#_3!186_` z&ZNRbYpfcJqg9Q!4o~pL{bL;04Hm{amOgjM0LC(wj%Bbi28w`%`Hd_z?vz((jIYF~rv`xQhK+I6OLbbh(YHJ&MYYQ})Kvfl# z(k=7AS~cC-d+O-+o4>U>zW<|9z*10`gzHkmFCv&{|J74(4W`2D4 zp)vrbv-aVQ^|Y>Z=eBQ+)w;-c9`-Vv!jKV+IvfG%V3y5NX0F{Uh(;;4ABOz*5S1i}l&L@onyOPRX^9o|D-8 zFP0gGvcs?@8e;cw_p#!LHXdl&$2;3|T$dEjefb*B-|N``xnuW=@+AN4*ek`fjs!Fp znHPz%u!R0|R)6*kQ%SNjX5So&C!~Q0#F*Wb4CMqP8tUcwwyIwjlfGZ97$$xM{md4;{)nMKy6)e zZ!-Y4F23(OzyIg1+;{|+_I7c1{{XN2*029}4;=v5JAdx{bUK|@RaN<$j~(p=URUpE ziPp097me{hm48bzfg$D-j zub(fS~V(c&Q!`)&y1od)2E7?dzf3EFi2AB zZcK5G<9R4G&hZ;B;=}_PRA8iR5H6jwLLrrH)Im}-pAr-pD=R4d;uteOsp;d9la+Vs z5jyUl4H$sj+rmwLAZhId`f-16Ak$Q)RM3n*nF1|qXw7M~6iVI!BMRdPhYjrx3#<_q z3vr6x*SbW2Y*`Yd7fAN1X#GkUNYdJYLJS`Z4P<2E85~y`oTU^aCP-#lL7Z$UJ!D;T zj&;#%!F`<-%7q&=T#Ls5LmVc_3^7d#hLy$hT<~uQC0A)3f@GR1x2hC4jw6!eb-HHB zYd~nTT2Q$#ISz*)h3H-BrbA&e&w`=j7~n>32IY80K;DwpfqpeifdzG$U&RzkLkZDQYp2c0u#$@Xpt~F`?@ze7lP& zk0hr3zdNHk*TXoba>%9)5=N@YWTIRwSx?qbO8Ehyi&Iymh@9m3U;j>B?ID-~c>P$n7$nW2 zZ~D7uPri=ma|r-plNi5n3Khx_!rc0B2}-9AX`!#8MKaHPl{^vh9B9i*kxHZdQvZSQ zI#6jsg5X^c=W-y6<_nu)FWvB-4Tz)^!lb@$M>-d6NL0j(^%0xb^ifbefL$kS3c-E3 z1WHNOOk|o9ya%M({XoLff7am*HQX^t$g*BH$?F>z7Uo;Szeka&)aC%frW*dS?2&a- zmWNsF(OJ_{qr$wOprupEkp54QUF1_hAOf`nqfDs@9yHdHet!fzWFv?0!URm3)D6*% z$Glb_+c`j69~l!$Lh~QF$xHO_2;gAxI8zYum_E16tdZqLnc?Kfgbfjd3uCkrxk3c! zB+X^C)(*J!2bs~yT3%>w!(%9bYNZJ)1ZwoU26)IH01415X|5?*%UL|Ol;u>U>_TJ> zVQaSBr5d3mFH7%rMW+RYvv@c`wo541mDO~7F2 zs)8qRSFUuOC=J7mt!afv&+p>>S1#b<_7*0U2Ac-;$pUu1>>T~MX<(bW*ZN!AB@}=G z4T7hD7}KC$F0eehkJbGHD7H}51mxZmO{YLrbrFZ1S)kVK)L$u(Qm{5K{Z|?Us&0Ml zPk!mWYy`M-`P%bOe)jwS&Z9T3gB0QId-w6mZ-3zz>*K>)4;27VTI=%{E?m%BYi4HU z-0#Uz_rYN0%rK0Lv@oVIZIh`~=%}m0$v`-DN*d+%_hMJPuo-9pf*v{V+&crO+fJ(< zG`%ug$Z1V#n8K%mYvk|&9c|kkD*3~Wk!juDn$wDoMHxqTTq8Igi#_>^nB&UB28VO#I07O^9vJ; z(ngrR(@d{lp!l+6loJ{-MQD6lG*IM3i;%677$S~A-%CZvCc0cnBfbe0a-GyfWNs7~ z9botpO0n(Om4On@}PFO|hePRm7*FqjhZfT>)hCl=%@qpp*}0q0GPB?kZq$$vl< zqUcU@eGX0SqDi*^qD9lQ1f)#0{Gq98X*vpFJu1<<(<(RvWz&6UfJ!em*OKg^kj#S2 z$TbI4X&`DXi|gtr&783V#C>AmeT85Tq*%cKEDxD%DZnmewTBXoxXD+v>DnmD7()h# zkNnG?JDk3QDQPo1pMwI3RRYM$z!wN>pmiS6FiPiv3XSB00M48239>;jN5?sxRFB!) zsLSBStU8^!7x0#T$jMZC^1+Qe6C{v%I>j%^c{f=X%C za`=@-B8gDhaSaZmALvxNYJJ2jUHSMwH|R9hSmj=$O+agX#27%mTrQ7~j*m`T8ccW3 zU4Qi3Klc;c7q2`O@7HenUsZtC?H^Y~Xl7_4RK{Y`G^o5oKN0L?3N@KRPp7D=2~?#) zNxvdG_fB6EQxOxFkUcP`&Kl2!#zWV>O_vX=-WoLcZ@7w#_ z;SKewy1J`pbxSRw)_?$k1PEim0m3pk7&9z+VH}jK1aQa#JcYrD6PslxPC}f7IB~*q z?3kssk`=HqQw+jbfCLhn5mKvBOKNqi)LqrxRrTskcQ|{0`Qz+;&bOy??tMe6)atiZ zt?I7#-o59ZVejwzeZS!XE^cjLq!garJHWx-A?AliFlfvOt!+&In7IKTtOac2ThKKA z%>>L^i`n5m_OCyS<=!4(>W1P!o;1z z(dMIVCM`1)Gi%jANv5uA%gk*wohw?6qrC*1rZ6M%Kd++rK98=cVA9Wt0bsZgI3&+c z{oTJQrG)^#L8`2=#>xkJ1;eCvIxd>&7AX`fj{lkLf+06s$6RPLVV(3rrXr;I&>%JB z@*FIj+!ie!;gs@;QYL##-FG8;Z?q@@gWM!cM)XidlNc}FA#)(yAi4=ro;`w0Gfxrt zQJN$r*Eor)iCX-OzBqshq~TRya3*wj5wMfXOOJEg<5_2Vy*Qi}6`JtD4DU6-g2961 z1XGy4hMre#PHvGe`OKaa2CvNbd{0NEcFo!P0Ou(G`dU|RR$RBf31PP|+ z8un!R9(%_K53W{ev&Qw8gBxU6dz@LDR@rZ;5WCw>W7n9*_xe=Cjp&LK*j(+|G9?6+ zyfX}@K`#SZr9qBNH4({Nk@ZCA+YS1R83`ydxrCARpf5oAInM2AltnrHb8b0~Mn*2; zwIpXKumODBUt8BlH;xisVDSrw!!<=(DOKr8vy()Vk16+SjXQo**R`Lx)pcFZ=JWY+ zBLH_Ec=^}d{;DtebCd1!ceSU^Id`xkkgmYGvCpfRn?IJJ>)Pjq!&KV+X{P5&Yk7^@ z6ai)ntu&_N5l9j4KEI7GyYEiC>1Fre_4i%EYwx)OuetknY)!^ET-3OHV-KIXwu?tD zKZDt##{Rs9wFcJIuxz0$Lo-1$pczo4pwVglnHgre!2EC@i^Buhx`wVsjibNPXama} zV}W!9RaH&%PYP^p?FqHa0Bqym*s#}Yc(GJ{u(yBZ(GUF$z~)v304}}awSVE|U->m( zf8X7AVlt|5`SMfvlehiy&zSk_#+d>D##%d_PNvi8bV}}~Rx-B66)x6O%#>D5EJoAN za|3qSuJqt?>E!7(Qd<+y%x(DadTM{GAwq}9i#R{+k_#YB1^q)Q(+b2Q8cPqn6aa#{ znUpUwV>f7+0qGYYrvNeMJxk>Z&~J*0k5I#%n=0jujGA-Qpdo1y!kOkFqCyr5Jt`G{ zNf9FqlyW)d#l|?DtRX0vIBIC}<}|rtZ_qV7iO5O;?9Lk^)lLR9`$4)b^;6_p^Bb9a zouSFD!2~##6L(M4+i5m-ryAS$ydwc&C4Z8xH)LFdI>fM<4~_nU=N>~(dkTypW3bu# z{I3B%t$V+5RE%d6B6_Bj&j>%g6110>I8)L5dgp^l7iDZ@~b>;M(@r^z&R9e^!P zqKFb@is>c;%#oFhBr~yeA)rB-#X}{Y6mUrxu@1g7R}32t)lz|D@PQ#&Z!$S7Gzui4 zRh9;THZlN2kL)17HwR#bWFTbNLWm6o1HT#-`dAd$He85`4VS!}g((Lf6@6x#D}#Nf z02Hq0UDKUDjt2l@ou;UkTpM`IoV%6{7Q{A|*XIy83?Ye}OcKR}3`QB;5^F+F?SYIm zkt3j-#DI))b*HFh6)8fIB}0(@0LU^2(Zzpzu4-Jf$>KXm0YNM0)Y=XH8|i;%S}16@ z*0S~Hnhrft))=#UWA{eATrQ8h*KFQ>|LZQj?v39wnrv)0U2gM)F%hV$fKdg_z=#=@ zF&LSK>JK7Vtx#7LOjW_Erjc$iXm08AlW~QSR@fMiaA{{7w{34=dospYD{M_i*c^{> z$JP|Dy>t@Uhj_2WjtA5WmBQ_yq+G^*N3KQ&kav1Kp|X@TWV z@x~VOo4b!*{rHFf@vU4!-v5TL{cBtIzx0*o&hOyHjhndg^fUa4xBb%JW@}dVjyM(o zz|5?5r8l=Wx7r8OA!W5O#_Q}G?Y>r(QmTu|U`X*ioY@?SiM)6H?+`dI2e;f#pV$-6 zyN6I}(v@Ttv>Ms&?>3v$#q$w?w9<`?z_OJ(BU>mYIYRteW5WoA?=;>nLXd6X6A

      qM+8ACNcnPO1x9`G6`PF~txwr84kP zzu$;DHh9pb^+aH^@MXz#U=)MO3Ha`6hj?H2dytnDwx(kdEg6wXEV2n64C~^<*wt1l zLvaqDS3)kUoueqpxT%zJn^dG^=OZ3z0Q75#Ezu-ttw-P6W99e=Tl*tQYqnN#dV*P1f+~SGpLigvw}?I zsFDu*;&rT;u6I96N@=Z0qyazx0KqW`e-tHN&suA>ZbH#?RaF%E2mlOHTKUNIE+()! z=gZ|{d9Z)5Z;d(jc3gKJMewg1FB-}ZOcc^Q5D_b0mT;%ygM7F8lI6V42eJmuPDV48Ya0|aAg zV~sW5G*5YrOcIshTYV2zHVB^;%}?0i$26jo9)5JoS`=#sLrUp{v@o+`vB zY%c1LvH%A%bUyi7x%ef@YygNHiA(L6FSI>Lbu0AcJGK*wl)iVT2E z>O;Z~DH<>i8;YG21e9qqxqCNYPG!$aG+mD-iL$v5>Jzcw4XtT$ZIFwvZI3#8jG5%0 zXdOx;EzvR|sBj&E=Q|faT%cj6U^E431+*q8nv(_$?QOhU$SLT@AlwV|*1 zTVv@K1O-b8Rx3A-LGHj{H#czN$b7tc&!)dnN>`)GoBk0g(v_|hp>g|Xuxpswx>{?c zZ(P5A{Um$I&I2!h)5V9sg2{IPi7|^l? ziRRmpv0>R_xmaK}pTTO4>ih+a##3mep@=}E3TnCmnoOX!wxKqspwXzg(@YJ!zYm_x z!Han_;fHAca}Xgnaf7z5aphwl{HI4Zo_+7F+W()w=Ycof|5bnHuUMrpyLJup#R6A9 z@v+~%`jPkj{PO|;7;Ek3=Emk|G#-&6FvyxJ#yxoY6__Sorb+d+5|g6J53IpGpF|{kW_x}(dpmMPtuhbr)ynl86PEeLh^V5 z7k7BO!LZrS7Sx%{t7cKrDqInfH+hX{-s%(r9~=n<%?E54+8Be{m-o zrV=t9$MBJi(v!v3F`Iv6wUZ%w9!FPFE`dP4hNOQLeHTJ{8G78=hl<^y+4bkFG0GU~ ztO5d@#)Rf`26za$%~=5|D}CTKViPISI_A32TeZPnmw9mN08s{bie(EZFc?-nE}83& z=&3HfZwbI!`STZO+quRmHq_(dy-F)zueH~LXx*ot<}7C+-pe8gK>GB&2WE$Ux+s25 zvi7=&!0z>9Vm*u$&l*W`LfI!EPMUIb_!983DOiN}~0AMN9X_ zDmr!Q^YU2ZwQx-NUCesS9$&%;?XPKCAA+1LAegB4)O&^BLys>+%rY7RCfd4P0%#cn zO%JO1v0>+LMIsX0@z&d@O^OTzDTuxF&tM|~h<%p0t@m}C)Pg_`=Vp{@G#ZbTR+^fh zZ2BUt^{A?<=JhKr2UyCz_j0*h-rU{YJ;`2k@zr1YZ5Qu<*;kK7;|UQtExdE=w}NeJ zZTkr=5tdrP5;57oz}y%tti`;xI5!>R?sHq%99MYg_VX~7u~^hN zn$Md?zg`0KImj4LZ4l{WP@5X2uCV~aZcL#zx1qPTpp|NVM{Cez0!*i%=@>K~H^&LU z&gbBRL)e2uaJ>YYQL!A}b+mtq?q$o35n;XLPrv)O|08SagIl$ZdEjfl@yB;w{_t07 zt-#jeXg0@FA9&Y4yZM<<{_gVv0Dzgdch2pM#-nlbI5aN&vgvLccOv4JuI7v`mi5xR z?)wJ2YvejTxb@Tj_TjbdYX%W&?H$=95_Hr4hLO-NfJ!TBvpaN1iav^ zv$+4C*sVC;)Hv%oP-t=`7!Wy~Q-o9J@^Dd_POUKc56z7zQJ2z+g{efEk%@*x))2fjrh7vWhu^+dM2I7I{KFzw?r!(H(=4^F9BGy+SkH5l$o5y$F`DJ zLS`M!v9e0p5Q9@wZe;Z*tWb{wZd_Sg@%ZExffb*1`fXM5wib zb+%{`Go%3k6geEAi2)>MwdMmsYs_V(5`;_Q02vHB@Gvt?CPm8t96T4R~P#u#IbF>=7}b^g*- z9eK@0#OfgYP0*(nvSk>JjczG?)$gn6sot*i2C$0tb4FqKGC_(!j%2jQyO9g2?$YI zMXoTW!gP^)K(`^*QSVeP;|^T}yCg8NrfWWBBJbjRfQHth6{27J;xCW;Jhay_*DUlk zVr!VVt(qq;@2&i2Oj%A8QL00;Hcsws&aeW43F1Ke-Le8Ax;$kX{LthVoOtA9K0CKE zv5dS&G*aApG3BY*TmY`Jz`VGxRG(i(WTu>({HEt4-PeYUNiiUYOQPTk_m=9}Ut+K= zZmx5Ygxtdvpn>UsE{!M)I!c*H;hb@iDZpXUi?~0ykamUdeou4yxQ!Z&E z1@AaYyC5O42~9TxRc`w`aOql&&sSV$Qj{nn<4egKev0??(q(Th?kD-$^&ep7YBU

      --1BRNw$h$Dh<2232bgaSEFtlQ3{qAP}D>hDn~mY0_r8~ z;UVn)A+TIFR&$V3{*+`K;{IW!RZGN|yz%RQ{Nlr}`*#7x zV*dbaE%u*%`lC<0^Edy_+V{&z4rDQ(&oAD7`|S|TA36OC6qHBd+DJQN41*i}zqQuX zb?q4Y$~qptR$4XGdvg804QcTX2e5u=ZKucGMQx+)K%Gv>8x{J^A{x7Et+n47tTndF z^K*N?aPn*@J=}d>Zvf~Qo;K~EVG%T*2x0FjEevx-n`b)26NNx8A8q(y5&@!fhqeHS zoBy1qJv}ZKVF@``YRXJ^IE#K~)4j1NKr_ubcI>|ptBXc6H^DR96?>i^Qb-xc9 zNQ#Mb{nt_@>slx6DmDT|y>MFem;6E6X=Y{;&bi`Q94p6Bu!U=-ND=3B$T?3EX{r_( zoT`{2D^258n%b@Q+~my9PLe>8ODEv0*yn&ZAqCyg|(e}07D*-8F9{Qswml@=$vrT&^9)trTBS>0o}FO zSrLptl4~YBRUG@c{hSV&h=I|T{x3>qr99zZuz4kx;pD^Zz9!@WRaI30qpGT^jTIya zuNQ9jNCv}NYoEP(_3Fv?d!@H7-SfJ0_dNL3)p&9N^%6Xv1G6LWatW?o>>e}hsDc@d zz{)lFN{c32b=rS~J^;#nPm_XD4FDh#Ebjxtx4i-dsRNi! zp+;k1I%z6w)p!g*D?kz0n(&DwG$6oi277qukW!I(rd0DsYW_JI{QCd^Q#S^IrbazG z+XWuK)l5?Ck99 z=t@_%jlZb0_IdZwB0(Tn%hs62j?oxnNJRBDzpr%=<0q)`|9OA(Rw)P6s~7h0Xz;KN$m93Kdkc43+ABBfk!uM~T;y;f$Rg_d3gPO}{)DQvPE z(4&(^1hXZfXDayuBwBrM+!OtrbRaG@1c`x+X#BliF{UTx%nM6MdN2V*N9CsoJx?~T zOyiFpv$JDq;s>ax)T5h?Un2xJDA~1G+)FJW;K3yamnVz`U$|u&jFWVcTqLZn2Oyk8 zhHw^*?pglM=^pgipRl3n@3Fy(TvOh6jssdOrRzkGVV4}Wsji=TpW%{@A&sZb%aO`V4sgypD+Ze7Fik#xalNaYS$XFz;0pXMy-(ED zVuYMsxLyL*0;VyzW38J%lL>e_?V5e1z)FEC2LiOFe{Q-fKmcmO&Rh@EP1%VV zWDL}74z-v=E$e3L-vur-rh|%rY6KpQz~|0^CR5OO4Au&)96&&A8c92)_xb3s7FZha zY}U~IeM?6K(p3X5Xbsf0V*+qIVQl`g7Hn-J7qAxQ=!mcW$she6H!gqb7jMPpUya7w zul|mI|5qnFw>=1;@j@Vl!)Km)T{Z`v3X68%kW%ueV-`vZD3 zAwTVtMOL6G?V>EHMR(Gafa6a8S8e9GXHs{XGKA*?2v|2$`fPgt=b`_PCVeLc0Al^? zD$}}BTwK%$_Zg1$Jzv~+Z40l-835rVfEp*!rQCaO#nbX6X4OB3Vh=ejUC3zyXYt>R ze)$42;0tHK;NE698wmy~Ma~A4=Psm&WcGaQfWAsnNX~)0|1L^7Q!dhlWo%#2oUAbI zrVLo1B=8(X^K}&e@OVm2_VGPVvYzS!*rju;Sq z8%KLj^{^NFjx>Df*gt}b&ru%`t1|a?wic3mc;J(fG7l4QqreF4^K0P@(3D+|SM<*C z^?E8vAYlsaYk!;Q|9yTLg!!Oqjl#o3E^Do|maS*@LKp)!3V)@l(P-36{u_BPMe&T< zv7X6Aq+4t4Y&M%69Uh%%@~p>`a~B_a)wgb(zx|6w(~UdeXQWjHTUD^rDOgwFjg4mF z?;3h2-8BEC+Gf8s|C6ZzphlBV4QSwVLWsGc_a7ZOhkpYY17&SD@z)v{Rp9X$JQ=%V z(LmKS{#MDk8MmDQTkaZpV}Qk?`Fpu+r~NdUfT{{$+x)yS!73M50_;2yU>mOhUM?}e zdF}F(?|;XSn&tf2&vhNE$I}Z$q}j3oks6;n|G;a${V)H@xjXOwO47}I9nE<$kN(PA z|I%#txyO$6J|{*c6shg)bK6R3<>@tzIfkRC%SFXC;I(W1jkQ+!# zpOtU+BlEqskr(4>%T^Q`6w>F~$pt49QXdnjbfrOP^gCYj<1#$i$sLrWMheYO`xGSx zWSmZg+U$CjHSJS^&EPi&)gqIYL$kl;by^Bj>#$mGg1j$-c2Ol|#1xeNdx0X{YjQ-{ z!V(es9|I?=(C>nL;sWYVS(yO^?*7ODHHE4;nPLQV%Wysu(vUfDoaGJzjievzJI4I;B(2as?b!HT;F?j z%tMoCz~9g_l{4*3*n}~# z%AH4cb{%#g6GgQQtpJ+FO?S@Ja0oo5o*_*R;K>8JX`+VeF|_1pq!BjoRFs-2$KsJ0 zmHwV?Yd*`ikqE0GqLEq?@kaiub)`E$E^4B{Me38a#8f4le0XMg!~U2aX!Uwru+-tt!;eaV-9 z?T=5+-}cZQU-Y^+KlJtA_OsLT7hej3U|=wwdjC8B(NiCK*FQQo&~Va&wQPA~V`F1f zRTa5-z#w}wK>M0z)mm#8^|FTJzQ~DZm)$9x?}aHITeikp+fnL0ji#G4E9dZUg}G0# zk%^UBCJ=bwAh*a!DZRDEdhbA~161BeAkcOS^AT6CN;+b^7^$d`^sIr`6e06+jnszI-VtQIzMfA)<5t$950WK5M}OM47ZkNe!7hPmHL&G)Kn zPXTxt0ua`bE6AyNXV@DtRdNkh)cofswGk39ko16LVwp*jmyA7OR))m%mkP~hWTqC& z5Rfu-kTmkr^sF_ZNzMglC(S9vn^%yT6rcP9s$i9;_ltW`kz9z~ zY4;wD&7_-+0oBgg-yJhC93!AH0&J%F@;*ag2-xDTNOWE$ps1?0%6P|INykbXS4%HLcoeM?>9JQU15TM zoQeLeXrW&$_>Vc&eX;3Zj|FfdKw+K6FOocYT~<8h?AH8DoLFX(j7;R%ae=j>VQDly z&6=4;%!O5M;NGaP6M$%aQ%@YT`9ooPibAqOu1W0Hf6Cyapxk|xGhL+Q9$+C|vz$&J zMHFtKB_dK8&o&-RrU(oJ9g{F%j%D6Ap2P-bzhY%CG3|oa2@Hz6`!$}V_f2^H2A_Lg zxd%K?!G^B+&n117*NkvCqi{w`LELaIjUcn$755Pe`_L@Ih2kTKYPsC{kzq2$wO!Z5 zcJX$c@vA7Z3o>;A7pCy?K8XDva?|;kC5a@dLL_eF7!R3qP@351fFaH#WUT^}wn<|i zBx>0#iei>b`!h0?%-7;X;n|8Ktz+T5EFtTE^67clYM*NoxdKFONnW zn|GbR|7Cw>vVGxxySdS7{Ym-eKQsAvQGXr?Xra=?UzDIoLDvR)u|Tz4Vrnfm6rq|< zuzg_%w6%$9a}%4}TR7rIe!z+v&Ao5(-5*xU8DT{(CT=?4Zi&`5LIMw7SO)54Gxc9A zoJpX(X+;`ZzS1#Y~z*<*4|< zbfhI`4K@9%c^I6u`8};Pg0lt$K9^sg*Ny**V8FTnQbL*FSW5j~c+h{k==+ zI1!*B3sKj!vD6}$DBO|Dx{O*~#S3NSrv4ZS8moMdS733_fSiF=Sx+7KF0UuEWdsqk z;UIrCmH}lOC<@~9&6KWK7tB zIGhD+h|rvfLv-sKJ20OZ(1(aVq7EaRg}T`ll%e7&K~(9{{xVv1J6N z*Br8hgfU=jupJ+duZ?|@Slg9~Vz?b%Dy>LsO^!9tGI)hoSj)6%*}b6M-J83!!^6{P zKt@tJBkD(1W3$K#-Lg(P#qnC zObyM9$;K2fec&Fbtu5Sl=j}MRwSkLUo4EblCYBbM*G=kx15_NqpjwCjs8|9TzC@QQ zV4F!jh??&k+vxwDb3ZQ^@LmT{;?d(c(ACEnHgX2LT=Fv?`_S)y<^%8i;d*}b)U8xv zJ@?oj|H61<>(bVxdta~Iry>Ak?fkRvf9KCU`nF&E59|q>|5E_~0AR6LEY4rJ?Sj|8 zE2lM=k!ha#ZmhLSM{{YW%xsM@CZy=7q;m1U+v>ywHC@s++eTKRj_$p^VV{gu%jq|z z5L{BY0UMM6>L*jD)rNnW?0@RW?ShN$~-@r)H*{Y$Td zHJKJe4fBc^Xv!Ff&V6n|j{$~K&Uc`j@FI~sD-#m}O1rFO3Qe+2{Ei0J$K((ZP04A1`9P^T zUc_SH7<|k{7H7^I_koe6seWlq%t>T2*E45)*VT5ECMva`15^UlD8sa&(i++W_~#mW zd2VxSYTwX+djPgAFZX*oT2TPcZVv z+ilI=66xDx)~;Y@X1;#y+BI`R`oI4=ch`MiweymP{?z1-yB_4K0Xc<@YoKa_YPrN{zJM|eD1sf2LEBrv#s)AR1BzfQW2`kExVVE?-*pj} z&TT?h3RiazI#WR+Kr2|)(eu0J-}uQ`H?cR)&A+aJWeu_hFcxeKz!r8sPaR18>vESS zr?hJP3#t*=T7KrEAN+&QeBk&0#{A&sM{c=#irHR!{7-)E>LVZc=d-;VpWb`=$#*{U z@ejZC(ck!mw_JPtPkz18NSypjpU$x|Z*FaEjjF0bxa)xc)TTCm!>WxjTrX>Kw0YA6 z0)_dxbe{2m4qB(d)iY!}h|6NePI#WIoLCBV^HP(X*=%Jt~cPu$K|6rQr zHiuXy5H|cM>Y)?Rqy0CPm>7oBda+pxpaZc!RT}ce?7H`D;(t|9-PS|WoXYyBOQ4GiOLCbyjU3iJbQ#U?%e_aVTlAkpbt6IFBoebIm@01mnPs5SMB<#z>u zU=<&Yg6zCK_a(Ey;t(YR$aCV(AKo#XfS38Wyqtt6iLorz0t1Y!LG$I@T9`?mC=Em? zW~m5(r}b5eYENXmHG*p#OjX#$2X-KxtWSe$t4OK9ufsMGnl+b?)}92Ve0O)av!o(*Esu3?c<4YRvZ*i-#sE4I?yfH2G zeg?{e9*VDj^3nG^@!q%p)ZvY1-*GFKRc0}}vG??6-nD!A@!#FQ`q>Y#HH*`H{Zjz| z6cL?2fByVvG#a5x#b~KA#%*dA3^vwSH<4#+tf@^MPR-l6M{1($I^MO<1CV;IZgD5! z6%fYh_<#<-um$fUObAJlvd-L(9XP;|BY%g$tH2?YoWY+r0BI)&t&?cFx@fI+10FP= z-^&%^NwbO?{j>@7)PI#oSi5Gm)e z$~D1G4rdJ%+r|*jSSV|utO3<^)4ni+wL(4JK)o@A9Z!I2Fd0=a*5cB+ zO-!l^=f)$LmN0f9T$AW~3@8qL48y!X_nAARCozy06sUA_D(U+87psWAX*W6bu>&JG0*y$w~L zh)6kCOh4Tw0vY4R_->M~wbrdhvyHcF8tt}8E=0+(6RV^325#<5Cf(e;yA}NaMD}jy3OypKMRlR0ur0z`6AT|?J! z-6mqypXW^Dy3z;p#=NET@6CiGU?P6LW#)ZA-w%F=l07#(hh4*^q9`#L57?OirwuA+ zqyuvIp^V=IXV$|~vQF7_jf-9!xwyULeIn{U_W<>XCdW!PVm$x?4X{VT*XL;8*mYTYnGhks5;=x%i*-1sd3ypT4#2$b)eyq}3H<9Sg?|EqeEZfFMOtt3P zL?E`-Ub%AR%5t$dwaKoUZk)UD@>hMsxx4OrO+)f;Rt&8aDy2Ydp_et3o1A+aUBwpU z)7G^Hh)`D*Y*m3r72M&2v}%=Yt$!ag4(AJuD-AGk&(0PqMYwS|!-t=G7ISNwQ~;ov z;=4(|(-}8_fU&LXKdb@OrlI@0%=<>`FVX?H`FV1her{z0wk0Bxk1tdTysYiDPd@UV zs~`EmzqtOHPyBPXcK(8B;o+y2FGjaBcr5L2a04m&Tib!;vsH41;Fw07iZvE z=R;tPHE|P9s^J=Va}Q&!^|~G0AqQWRO8E59@(L`JVFnrTPHcSJh}6e#M=pYEWB zz`Z}GiSqPzI>_T@F<~STH`PD6D>DF&81Z;^F7dgs@=a>UF-jJr>|A$JxPobzeYDn{YXx_dyZsuCk;DQ{WtpR#` z2xLPR02OgPm}%g0)bijM3!qD`x#u3Rjt9Uf3Z!}Q^j{UDPWu}7G7!&@iB2*R0OEX> z04gb!-2LjzvH@t$b-c5fWG=Ku>tDrGu!v97fiz;WVFv zNbFROQz|zZfv1a;0*H}XYv9<`$;z?Jn;~H%L2iymySm&*YjfN3G^F3%8#iv8W*xD4 z*S)X4`%Av+yEe|>b{_!i-OQ^|nrDT=?7hWV8)HB= zb@TJy1g18AcnYm6=+PKvu{?U_(GUIBm5;vvUq1KvqyGyVbMQi_sdmm^xcvuy@JD|7 zC;rw?|J=9#`S1CUU-|H>Uw`Aq^=F@X=E~(&?x|A)08Cxi+vm=mtDFyjcFn$DxEj<@ zIj2lg#u~e+BN!P+RsW2{*~2Y8Dx%QZh&_-qsYx8S2k7fm%o>ghfwZ)XDfV16u%UbbDOj9| z22beu;|;4dH;kxd6y?9hW;E+k*@q?%#{mw8m=3hY`;-ffFTAfW=;nWbjj{?7z(`~7 z`Wkf0PXF;8(u*FYm z4$fTbSl)pi1H+^lE&y$makXEUjnMyd-REUd^TkHbiSA!41jwaLw7;LmI;23U>H#Xl zflCY|LCAr_M2Hdy%Rw!tgi}9Sc_Ou@eqNZ|S_WvPo36kO;}of`4{7Rb-^VDW)MCDv z@7=t4^E9{SYBb)s;}x&@=E>&vB?YR$Y*keet2TO%Km@CGdjl|ufca1!-EH;EAgx>c zh?t=qDoX@RM-|R*PI2$~ZHz}1-gEgXo;y6ke7A1aB$_b2UkAw{$G3YeZTj24z68! z`wOM{*IHNK_1)k5!{7gwAN;B9?d_d&=XP#;#VcR+W#9NsfA-Crn_K5T`jJ0+_YfmM zpXLE=ZEbB;RaNQM{6aKDu1NFB4`Ym}Yg60S05GO_H7J{Qu9{%s0sx8}=`F{)JKsek zvl&>i*?J>Cc7TAF4z#`mB4*Drvo*%}MNn5&C8GsZ2F(tPTBKQ&HyCuff4O*fiw=>s z&6A@Ymney~aVOYXZh?Z%u%qBp1U-fk_z`1M(6eK6+(!Oc_N& z-;bKVu952E@;LHCLZW4+?Bu>A50IaM3L5nkSQ#>-bv;HDVw*JJu7;rkfKZOjLoq`> z0P#gmd&x9WrU`^QXdbec-%&C>A}|gml+GapFp*~qL6}H}sX|yG2`3(el;jf~?$sb_ z9lMr*oWGQiS1>xm>>P*@1e_1}v*e6A<+CSEH93k^^~qf2JU_; zs;a7XVjr0S7$$i-LMDLtT`Djb!oo!* zIyVSk%42ESv&PqP%2%#BX!WAM3bOwUsD|6=nWx?dvJdd5xl3fE$A>N^n8Nh>t} z=@h@<1`;>U1J`{hwhaYSyQD!C)FA}e0`(Xm_B8*o5n$hh{FI)#<4pC3SRX3>tn0)N z#_?o1U?F36mpxAceD{*Oc>nF15S1G4^+Z<2`*2Bz9RM|@`>vI8QUBhO7-n|O8n58H zL2Ep}NyDEx<_Min^y2M)9f1UhCbx;XAr;d1BGbHd|DfzTgs9ex4W&!o2kjiY=N!jt z8uzeu>&S1pK$%JJK0R~WHa)Kl`zN7F+ihHLolg_aWrL~U7 zqp5d*SV)vomDBYQ7{)fxqDM!$l`MoT0P7lfANfatv%YFIQZfBV>hHUSM^WBvC~x}X ze=)bQNMjVa1$*Qag7zND0XSUbB7lJ7Xt16xDxN%)P3AX}>TIpb(`KMAN% z@>eJ|`rPw69Jzzb^r4^ul_0Y)Lq?=+?$U+I`sTF8u`K-uy6LYPG)1G_b5fW*2TX~K z27eV_iPD5sK8Jxxan$gquN_J+C^PVh_xcVHpyC?dn$XD%_{c=Kbg%jJC?pjB3=W3DI46@f(sZE$mDJ8}ABuKt1v$GK(;dGs>?K&`Ac@S1W=;eeIal+;=)?Lh;rmG;rszGv}F0k+0MDaF>>WnI?? z`}_N+<^C_fF1_Z<{_Mu3yB?fupTEQaY^4aQb?RzvdQx4Z@9qqiPmw2PxSgH}P~#Ca z6v!nDOh+SZj2pfGq|&%@bcFq*8S446Y1Ug+0kzY9c*;LBz{WNIojia6P~ABF!;rCqr%oC5DIRIdcF{AN#JQ|Hg)M{m# z%kQWEmD0*G^Riyn(nVAZ!?|`&{La{)EQ3{$>Dx5WU31PsgpQ}{#FObX3MX{bRc*YW z4VvrDV}OH&-9PZwnSe+M0o-CCJp&-J>ZJz1=!zUr*9e_g0NY&DP)BW|>?Y!U4T{;Z z!dNSrm$_@zrXqMJ)OMq63>mqlx^>_R_vFeJBlvpsxT{vAlx#lf!@?Q5A7@Q)IFsF+ zQc{N-fmAPeX4C3|RAH6O-_I9a|4`wHQ;G)_H!j zF}TsWQOQ)A+o@c&zt2R0<*dH_Lg2p$dcZY_AeWrIM;DbtFd#@Hg z^|i@P_Dks%nKTXbuz0eKV`fqwXuT1ofg}@P?;*rlAS4G!1fBz>=)?fgKrX+M)F`Rb zSR^>5zy&Aq$P@rDT)gk8VSg6ck2n;eigXmIZpDK8i6qyl};x!%M zW*HgDODIRR9LH^@=GH#`55WTqLD!Y{lMDaTAVmyHFUJr{6N&+P<{8bN(JEMXVIDYv$#JX05=^=#Tx~LLCc$Jy76&z8a07EI})U z>A1o@J6pK8wSoDv#%FhLV)yU}cCl;?`r7-&H}h-)CO{Yc=T4_(kkkJw>i`2&gO z^W%|oG2UnP%vNXaAva*l%-+b* z%M`q;r-u<5f`fa&O>I)I0@wbxx_>Y-1}6!qEu;Oq(1iX?pFlE$HrM#)ny1daA0pG2 zqU>fxN@*osgM)N~WFrX6gmxp1r4vcEZ=bvEaAC{wcuo8OOTtWmz;{ls6lv3>Bmu{8 zm`_!K>o@es!~ZV-y31t&}S|UiqhupB=dWirLqBR>Mg^tJ9d?ufrBthYG&Rdlf;2o^1I+bHr$G z>0317$!XwR9)SRD8c*U^lbd3ffg2eK91b@WNgZ-Sfu>{)&w;b8_R-3qiFa^=o+z}tosBU%({@L`#)!pTmVJxLypmui^=N+TM`BU2g9VW{!#%b z(g6#h!+w6Bck<9ERyhXH0uL(WWiaJ>C0}PymaWkzg~@}s3EL?Xdr6rXOUX(_?6nmg zPZEP&F#UsM!Af+&^$DCj(`e$&wbm_j3qYkS-Sh@d`s>Kf{yLi4)I>!4dwYBJa=AQ< zZF+KU=bnx8x81jS$DJ?d_8#-ieG?4G1P}wPT=TD-iy1rZeRpFvr$lRLHG)NBL)NSp#5zT+{Aj{|ErF1=UMu_Gdf&zp)|~&@@wj*S;wS5HxJ< z5yl&vP)egd*hf7(!ojmw4zGOleZO$!;~)MX_O4$3)fbT7A6o0`FMQYc{_qd{;E(+D z#>VCr`GkgUZAF`57p2bLe#fPI-}#QW|MKfC)+|X&UH;^;Q~#biW@?ecLSB$Yi83 z^K%Whn|wF)esGuhnHEq!nnX_1kz}fJP(-J$`zo7_Dvv!VRz&k1Pafihk+Yj|r_Rb1 z>hWkKNN5o8JAMMjC>TBoV5Nvo_hjkD5rn}sfIuiB|CF8dcQG>PbqmgInzw#4E#*oaA&b%yS1?1xKvXOT^YycE=>)9Ol0ysrI zGL-~0N=ytHancf_z{-hq>_hj@%1-yC$$xY%{J$w_tQn;TW&InH$jHbG!rg@`!+c3u zp)!8X4ZboBb}Apq%Pg{tsz^2(4~M9i`kpnOwNzrCWF2 z`)X233yoP5|JO$U`Ol+7voE$TrO*m#stTLq3AU#rkhRzvS0FGJb&X|hV2x8pc*8!Q z+|D+&mjdFf)H zBJ&Z>=sLS16x3<(RA>ShEiPVCphRIQweo)IAJRT;8?{HpS*|c`A(hW$mcO4V9zBIr z6&6R8p;5MGDk>OPWC|{XCNnK?fP$=oA%TJ1q$sp!D7e}V6e!s#crIEim_%>{4umxP zY@?nnK)6Upq!J}L12&wr(WRck4FkXcAJd%h^O+HFV#wu1`hVs@rorYPeeUeOh?W}C zOqzhoP-064X(XnM{b?iN6A-Lph4qvXN{g}$S0*(C;1E1Wa;`h6R0@jUN4kl=6w-V{5zQ%fs2#+!nw`J8jwvf;p}}HGheb` zhdUxEcM57j@q9|z1A6X>@-rW%F{MU?seyJ5&`^pLyLj*p@Da_wR+^mlU+{T}UFuoK z9O@Fr7K_DVF`v)RsmnqqrA27|FZonSH^W45TlXo%i^QZJMM&ENGBSh&f*SHje$Y4AP0-%A3# z2_Rd5R1+5n0vQVer&=jx zTN;{c_}v1ooa3go*0wH~US|_6j@cqyXn#7LzIF8anEKx6ew5b$32MGX<^h0OmtD99 z8(oZ@i04D>+D{-~MRukhEF5eVNza0SSs)|!+F~M-G(>r)IeM9QM@`UHNrh^QZVEt% zcymFpB%>I^UpQ+)C)M3WIEaJ6$co;RRFMutZ#0L$nB={Sjo~YLO2}tW(CM=bmFQvMq;^Q*i_R!Jy*6Hc;)`&O zttBI5!%Z<2=RQGDx8@m^c~A%>jlDxgN&i~V_vKkU-ElNt06rDW5B9WDEdt=LuXaEH zwY^6d&F!VX)>>=ox;{KSJY1d;{T~2SRgEvc?2Fzwx#R9vjHa8nd0M`YSnnDHr_p!h zX5~J2)A(}}7QhUpG`6=kK_F~TMtI5Xw_$ra!PdqGHl}0j9nP^oU&69&_5IZOOhFj~ zs%!9a*)apqW|%v$pi2fIW+?Umjs@x(W;R2;e-n$nUCeG=!~RpB*}eYcCw}qSPk!_t z?mqRzzhJhD7h1XX#jpFaH~sie{N10sbZ6)G&*(sv=9CGDk>%gr6SuXseg6IL{eypV z<>{wBeWn0_f7rLSwzhPotCk6)q}aWAu#BlqGb^_d3xKkyAh&TIAsTOmF5VbxVm(ku zS!d*^Nzz-O%dJ-}#VcoIrNk!5%uFKMPwKn6MqjILgAd(e{i50~LW!;^E*dB}uX15# zF|7{}ez#eK?x`tlOac-4lO-UEoJg2jfdt*Iy| z^tflDPJ>M{6{nmi81u-i-%_)(N^?$yCh9Cr1z95cg-EGeods|@!|oTqN+*{GbfSHx zWASq&>91-)5`d^#qk_zZqUUgkovfSZmz5wW4`u#Cjk-p=Zh5q}o z1Tf~LwZ>%`#!8X$-@};8?YTibT@MYP2E0G02PBevmS9LzPNI;$2B+Ef1*S+2IN~_P zrwH_y)}DO*6+H6^<;c>BT$Z+k&zd5-dg!9m9mAX%$_L#GjZCM1UzyS z{3JR$h*2z?E9V&tofI{xRR)p<;>4^14B&=dQhtNLcT36FY1zij^wC8DXbAwuMjuCq zhlgk3{@?aQb-lRw@aw)=EsmbO^zw&aUt3E`^iAaH_pa$z)HH+I{jCVlN?|k_gGgaC znPNO1V{3DYm)w3EMwNzPhOrh;UEjlVHxIEi#?kr#_Mez7)O-$FEP%QOSvVg6?v9}a z3>ZpqX{<4@W(hl+VYzn`%l$np4-Zfu9oVDm&tAUv#3$Z*c>S68-n@GG|9c_n{r%TH z_uTi=|Ke}|{eSw>mp$~FAaYYq{vG{aFlB-?M{4&zrT6x3UVqOY{{Gv}900J^+O4gv zEv1!a>jfa)v{@-qzWMJ`0@zaES{@Z-Z8Ppz1kMWpfx#Uo6O#BL4;^zknZ|U@E(JQ$ zc;V;_0Nbm;@ggP{DZkixGefCAQW8yUbQA68=%fneC>lt)1QA(ltY;|6f+F6yB1;U!&iGoj>{}KEfYXw z8p2i52TCsX@i|Uizq<);5F0Eq0LtebQLTX1STeYGGjVOwR5my9M%ECQLpEAi46+2! zq#qAQriQsFPmU!w66lMfgb|tSWfL2uYrbS8h$fArsO9o=K!cJuDn?zV6nD-V>QMkh zhU-kK7as<_Qi^%N3@Fg^<25oKgyjIKn8lEbyo*7pz|B7gJr&mhX>_RyQcem1BQaHq zYqgTzA4y~1pZXJn5{cJFfi;`Frj&uX!7Pt`RuTt^jy#bhQGjQ{10M=S|uY0h+ zzkk;C#U1y(qubQ7#K zECIE#*q<$6EMtGMz`<;R=WZTgzF30Uf@=dZjTxX?E+8C%ErTo9MAysZvYq}DQHYE+UZ@D%KO1^Ytn&|}@e<}!g8In}d&vyQHvt}O zFxCSA{&gAvBHhd-1)YU)p|#ewhBA(FWPSw6=Ck@yJtz!y3f;4EFm%sqIS!XjemSkM&FZ}-4qqbDCp^j9MUo1qTUA% z;23@aL(kr6vJHyVUJ3B{;#~OT#M)n$(@*cX?z6>(&(A82UK;6}fpH6F#o4t!c~6SI zM~OE?Y_!+HT;I|?L|OS071kGyK&jFIMw%?=CgGAXlT7yqo@Ek=4f$BVl*tfJ z%;UN$uCD`slxUI6ffBJVK{teCoA-nAx_%GzCCZU7nIHhrI=_|%0BB?gss%Sx+j+^9 zF^)_i_io<2xm+yHoUVRw?b#=9yX&5ZUh;~EzogpO+@2c?3kAar#TFHSN)ajmBLXx7 z6)B9A!bGV?`_I5R4NNq_Sm3a(akQwhH(TInvBYe?#KGYacs^^4{FY0QwNP~pumLlH zxB&pjtH9ZUo!*~~g*7$IVu9uS2#cep@i+4s%yQAl0f?Zg3QAWXQXr+qqm9jbXS>%v zI@{a*q^*~`FQnQ^DW(6?_x*=|{X4(=%|BFCql(!to7B4G`CY7oVq@bNsXlD}Y;JAs zyzMuC?X7!zH?N;50001^@pwF$PN!Nc&2oiTO38>h%gn|Ye=rB3b0ZB#R^^5Kqpy`9my(B%~QcAgxu%iVzKaY+e+$4P2bW zOV$P#ri+v-Kzwv#ZbL6jkEj?sNNHj~4mJ0(h2ZycxcM-nATEBmAO$!Tz;2*1>MK${ z-vEGBw9GGlt$v<4evm1Z`pW;O+;l&Fy^JAN_<|HQt{l*c5itZx-~nai2DHMn(KnIi zo|DChWB|xoiewE^V>Z&zgnnIT{&hfrAvVHkP5-mac5dy>CA}oS3rftuNVR4_Qg+y} zx6n0m$^F(%@I$$P3e0nJ*HBI#!)wd2cVJM{^~v8<&QC|C;beRisL<#a&3SV_6E{xL zwaQcTxu3Tt7?sEzD-wEpn#vQNI|`%#D)Q_Lj?33@2{^Bk=(u1&AsR_u0cZ>Fg|P07 z*%^Hl_b#2NW3HBxlT>7e5qm)l11@=SSI$?X%s2|Yta3GF36#w-e8P2+fJ|I-d<~j9 zIlShHzm|OG)`KfFNA#-ZK*kaIWO0XcFu*XznCD~q4*>Oic5t}2d+m+~9{SRqJMVg^ zCZdhe2%}Mj!@7CI6bKVd&_oz(g|Q;+j4O4(dO5a)=;Ag zG#Wuw6{s4)4geTy?dImjCTXo<*($BI)|Cz$Y|Ao7mzy-c z))dg|gF5^`H`*G&MfZhH?`clETU4?|Rj35ZEqbaal0|8ywF5KS$#hE-Lxga0vGHgZ zB#$;aFvB;nDfkdh54_Qce_M9hqhZ4?nrMeu`tOIXrIz~;)^77qX>5xB@4lweovToi z(M?aVLKg8*!x~S~xVI>zVhRE>EQ0KmCVD|GX!2>r={*hTE6;KQpFf^kx83KS`(;(o zW@w)#Y8Ag$6_57_I)|&t#G~M=0 z76NG*Q%IoMY&M(EX3v{meZF_|nTe+Q6<_gH-&~DGQ^SPYHm5KEj@ZI5u&50zH~M?6 z6lzDnHq59RH!{@Bm@RA6%O&c?0%N5>TthL#EEnLq29`_Ib?sdG0b>kc8K$mbYlG!{ z4qGp=I6A~~HbcFb!`5{Z`v(^311g9iL`xRtHVFVq>1sT^fB(wmcOUIud;bfiq&jzQ z=eD2xssHL9KlIQSz1HJO9jxb^{R6|&j5HwG+M3_cx}r~g>ajom&bRoQz2etRZHbh zQw!wvkrNv41HhSfD@DUQIRR&#_eEio0R@K4ulkDoBTVwz(@lk0DsX}~CL zs3<>e1FzGV>hl?y5v~eatbI=Wz5n9$|1>T_I_d{yzfBn+Etc)%=960X{)b21$xD&?W)_K_jkz;OV8<1!6OG~AN`0A3EpYXBn@Ddzho zi9B%bsJB@xWt^{aPbSBnyUz>vRo^|JB2b@lO?D4Du@2BmnaMp$dvH93&OJ+!^lpf$ zfWqe)GA>kd3Lbk#i1VZhUIeAaU0Tdbz#wOihl1Zgmjc0obj813P`BpJf5v0Q!vt-P zMMg5v_(X96#G-et5sh$`yBHrO2TnsJkW1FaENZbK;5H9lI%ogDoVzjm?otjqYPC-( zXqd;AIgvKFqgPrfndSw6+axjY;laT{n|k&c0)pmrj7_59my4593c9MGtBOAT z_$NR12k-oyUq5pIfUUJvRaN8ZWU7=_^b@ zu$#|}m0Cs*PFSC65E%`Yip$*eLT)%QSm41BSq=x+LKJWE-#IE+;y)CeG~B0YS$@LK|im}|0+|+7r%}- z0bZqPr5I!_=>3yoyN`8~(KH9^QVb&IK%vro(bKqcz;p_qX9&}*?E13;u-4c01re$R zP;*rWv=Cb&ghFl)glOIjt#K3(kLA9}p-T)yWC8m`1^=Ko*jV z%`1TmQUa=4(_2FjcMn6-}pqw({)t@Lt;jfY;8+v z5a}R`lXb5f1WEe702I8kH5296$#Xd?;ovMl*D(@eFd(V*f_jd#U`m+QB^ksd*cl+m zbPxZ&4&0E}UirE|G86T6dtEQ<*=#oBGj#vYeJ$p*qpMGR>XC2wj_>~dd+)e7J-@Yq zxwT-oZCgcPQm}67Z8;fojVzXkNpBVI3#{ zYeBY=1(2y5P^GG%v<4{!(i)^Rl+qxrWQJyw5@5S{!N!!q0-(`+|K^jsmmmN27XqpC zfd^mq@L&I%KlMLdxNzI;-X)ZXnvV`{qyXM9ku#}FKF5yRd|@bEL07tc{6F=HkAL*{ ze&@IT)tLhTaAtp7+uPgZ&Fee>AhdH}%OJGIe{Dm`%0r-45~vs`LChZ@q8H2$j|(<;;dKB*Q*00}bQ zEIeRP7iZ5SGG0sp9}Wz4gZ(D}060mS>AN3dlU-U7Y*PiAGe^d}5(uY=QG+NYBi5Uj zBmk?(@8T)>I*hh13*McZToWC9RtmJ{oUNlMlmcW@29yNwWs{gN2vQC~(#S_s@-RwS zI?Gdb*gzR0XGBR!>1Pb7_(QUs?7dm|c^QX?oa^2QbBbf!h14>m|D9*aJP1tr44fho-XVWXUe}Pb*SdSK6m~IcNK}7M?HWi^Y8Y zIdQDt-`%~wscHTdU;B06sI=Cq(s=NW+cB$a%$If3$SVbC4XQ>!Re`GtRw-De8%@4a zP)Y;30Od+(cK$}ut%GLxi8Ok@<5K|~Ox6uQMy zv=N*wm%T)7imqxcq)?Go(RNr`rDd%uEx@U@wOp=-RZ`H16Eez>Bnc^*kYhwfW=3Sh zH@)}nJ-h$7_nf=WKKtBz-}iknd>Qf9g3OHgzW46E@7{Cv{_WpT0zl;|AXkB_DuDSM zu&U~YzpTKb0fVM)Y;6H(EP%BDMFBV(0~WT9Aiy{k6*R@l zET`KK?dMv{T3h_ckG}rrpZ)CTyvP_tV`8GQbJ2{}_xNeQ;Qa!O0c#5|27?Iz5y59~ z|MbWH_OIXj7v}^3Am`l5^2+jPJRTcsEh3K=TbV z-^0)tgK+hfCQ(Bul3p(_9Yd|P{z*4{B0&BjCnE1YY!WRP0+%_&n*<<7QMF^@#ZkLZ znOc_=C<}rj$S2Y4vvS2qyiIYf8U~Obkx>0VYDTK*?H!!YDYohMB!0ckNqw z2v8sUq<0;YCb*g84a)3?I|YIxZz4e(C+@nQ+1IjZ6Up=4Qt3&FY0kYDs?Rk7DRKpD zj3hM>O=B3!x->SRBfuz~!XS0BdMM4f&j75^8k{a->XhCDV`_xdi^>mxi~?R@7Km)0 z2~f?cH51s_v%xm)>&A6Av#>%;A*@l*Ygluf7bX1VFX` zXDy&Dz>Ft=lO@2(1ke^uHlPI@jQ~a?a0a0SsCE3?Q^462V0#OUb6|+TR23K^u!vxd z1yhXb-}S5AXar_?32-z9Gnus8V$;}TqkKjppsE6@DsZm$6!1SoL;zJ;oO$s6_s=%Y z+_|6YuCM&c=f3zye)M%ev$C?hT+{wry+0y=7sZpZ(n_~f#G3N&VM%PwDB;#mef%Fj z@OOXp&T|3)007v+7Avc3tJa`F0&3|@-l5hJIp^e*JDAj&8e?N?dCL|6uFHn3He5#Z zX~r};gCoB%nEL6qe$jDW-|iQtW@UjSE`@J=jz~ej&47YT8XfY*E2goDNk_9_wQ&iO z1rO2mfJg47S*niJvaJt+V=MulaKO)7mIg+nrS{GlSaHM5Jq zkpw+2XYhx;lQqh_jBAKIp8&AWHIS$d-}cDEswzg znrcn&ypwZ^R%~TI=mJN2KVyLAn;ZZ2(dxU*Fbbn;hK4xK;TsIb3o0!LCqA&*;>vkAU;=u1l z1!g(`+4fnb$Z=in$2lXw{CDN|O3Ahdl&6 zr(Pf1;lm&(7E0 zKA+8|U;N@-chmCP)mLBt_#0Oylj88w7_MGhfyW&=1lJut00-7qV5`2~&3Txbnr|&2 z8ldSEXf~}G0c8cF@uZFtEJk3h0gDz4A{aDaOwANPYXOU*siP|}lL?sR<(lem5WrOc zRS8hJ`rlmzxYZvf~c|2lzh*8HbPbuGL9@Q45YJs2i|+m0Dz(>ij~#1Rbm?< zU;xG1h0a(*&N)E9s;a86UwTm{YvPFNHCIw*Aa?VOC;1$W^@#=gR4k5H$xrz~IMn8@x7HYF6AevAOrkw78PmYz{d%Spxyd!C z`bq4Z-k-~kmCnOw?(SGgrqi91$g;;005GHh&H(_qCI*C50CNqOaL3R6Y}8N<@PnWp zIT7u^U{W>fTj076X}WXFmYrzr_iDO-E}t1s`=^1d3shX&+fpRY$dFF$^1eY$W+1fq zY4c$8NJZ*Rw?mpswDRL)UzH|0+~>UUaF`;g0KzitIr@uDWUt z2~g}i(H!a-N)$x^%80y3KEMV($@e1SO1VT56T{$qlb!P}>5crA88McNIDGIGKTAQQ=iZQEC7t^G{+%v2F8S(*E z)JU^y2ClW%7DZvLu?PspTFW*eG3*1}-rCwK%d$M5`}@h`$L{(3=Wf64qnb%z5O6#OGa3g?KRQ=O1y-(Z_UC0i@po128_+oahpXu* zG&C@ugLCD4xD0T(aXR4d%yqnqtR&8V%N12qP4?s|J@6WpfM- zv3R;T&Zk{)Fhg}7Iw_3RN<6FAAUE_tFLJBy^*>m$t4W z#_;yK^2rL#Klum5MIE$Sel0VX8N^5fKuq$F#k48f+(^Xiq<1A{iUZBzIY;LQMf;nr z9z8&knJnfemNGV`>vOtX$Oqk@4B@8*n(du7=d?g7!G$axhzy>5dIrHl?&B8=0I*XK zq%ZzX)jewfSKlO(715f>Q&OBRnpHo5Hmv~wi9xFJvpSoMcJ+N|IpSTD)gg?RALYir3kMXAFKNLmxcC0IE8h`@n$?0~>kO*N?Ee&01;r966PWd z<8@eJ+J@_w-VZW$0hy#&0#p7CoFhk$T;ud-S|PHh{ab6TvA!;5Q#V31NUm~aS(aN{ z+gs<_08o2vo;rE_!TayM`>rp3@wi)CyY8wZmmMCD3OjQSM%I8UOSt#JN8sei)3Cj< z3FT}GBP19Z1Zxng%GLUPSG)3i>JcFV+D6CU_zA$M2tYvOlu|p}0hA@!dF>J4%Cgq> z2c18)RO1FP@ErwJH9KIox&FYhPk-bs<#g-8{XG4@@d-EG%!Y?ynjhh+9XmBPPXF1q zr;cT;-to5o^z$c99KY|J0RUB5mP<=ZOQX?fWUaAitu2f-1`WE(Rh~N@YuAx2fgTa} z8$jJxVlyUoiOYTK7|PokDFcW>3S+o5!7nV{Z8e(AH#D$z%#O`u*kJ1unl|6D+dgFr zJR`H@BN}^a`oi`0Deb;NV4FqWMFxBEw1K3#lBd*Xb&Eh+1QkRK0o_SiQtwc1ZhWJm zAX`y?Cbv0ZuK4xd4q7~rhR$oBkSUgAgG3$756a08vf4xH_twv_B^IBqbrjJ1th?Q5 z!*elD`ghyZ$*gg0Oof`xlRXb|@{V#cH2?zh>t?5Zc)z!=CIE$?{TZ&!({hFMOpllV19AF^P^ngf^$x*81)ZW)V za;ltjawO$B14VX{_100M>NG?Um8ui9=UG{+F*AMc0?1|rJ%8AMjVs7b0MFrl+WT0bW~xB?-aiI||xiV-i|I62OWBt*GzW9aP?tb8S`GNQU&8I$h{GkJ%U*A4T z#Rxw8z=N={HHGa4tC+be=*b-s6xIMb2d;_n^JxOL&Z?O%S_@b-|7+v}u5v)rY2DaX zHKiY`3ZR@rRhCVQLrv0O9WCgZf3~9d<|!}d07Ni7ee%u+@A%ZeCs%Fn$2#n*zxr!l z_Fdoe{r_q-8jS!0vke*}xpwLw1uY@J6m=tSty=c-t!ry*bMp^>??3<2`udqu=L`Vw zkLb$U>Y8`Pv`th-<(zY_a=}P1M4r?erK{}^opa7f=vEz6&$%>52>;ibH zsEkhAYDMh{k>Fk%pQOCX!!f;gR!a-s8pyICp3X>tn`XP0lCD5Gowa;zY zDvl(3M3WOlj`#`y%VYbb9zMuDlPNs}nWI z4@8xl&$rIpeb)!K&zwG4+2V@gvZG&l|D&hjw&!!0l@-jZ3aY9C z=Lo81N)HCWSOb1m>YIO4G^qjBfH4Rb4NzGERLxkoX_II^1Dco3)Zb70tG40im#n_= zfvQ#}aO%Fh-gWApJO5;#PX8zW_6=|P^(WkP)6Kp_;KdI@&A70}fOAxXExrY1t(CF0 zM??FFkvb2%FfHN)7(v;l3}QpUh@OPe zG+v*Ohnx}vN@goRPtEWqc2U(cTD46(7bPThTp%>NYOc4~cu6$=TA|)K#b(#gh-_fY zqyQvSAH`foR+Mq!g^A&g1U2NwE4Xif(mY55IFw>yQ8~=MZTtat++1C(lYSg*Jlb); zD0U^HGIIXxLrvIlZ0GVMNKkjDrnQ(}2`4P^in82~?jQv5L_ zWge4>>Hv^X>_>?NGQ*^Z0gaA0-KHkd>Ms+V;!$yj8Y?_>qel13B;rml*AE}To=XQhS$>}<~ccMQb0dIP$GzlN8V+@W>b$g z1xf^pzd_8HWyizW9bV?w1(1nU1JlTkLC69?N(3YWw&^>(5xA-I?68&LGVg67GCm?4 z0A|zabT*sKfG*6e`q{>r2gXY)S6=B z{qOpl_rK@Q`7xXm004++Wp#CRR1^i;!kWg&F4{MnEY(_TQ#a97|eqaX*wnB~e-QbaQ&C8;su*TS}8MF{j8~RM*V;#e@S0ake%ACdPMpl{j+N zMDqddqKWBbLKwPmc>!iKvxQNPYU<}VHHN50EQn`4eU6ROe{!DO?h1)f$~HekOdi1Gh+4kB~a4o z97)MwBiZwK`VpHR1E;=csN<1lT-*Dzj6MVoCM0VQGwOrL)H!bqjgp%dp$Xt2@G0(T#i{#_Y15@SCHD*P=Ub;^#)4rzLpbK92G=CPVL%p{iW7LS&+-AJwU!9T$8!5Yq?GVt!_3{@-oBtI>MMti zJnoujJo|qJTTF0VN65LV1ZV1I9vg}|V%zXDrAIySFD%%i00RKlG+=-+0XRiKAV+|N z0MjWzId7(sRGS7C7I0~)jtlh7Y*p0*L{opho6mu&IS>(SoH+J@2X6c5FOYLH*k`ZF zWU~D4e(Gm`^ZFZZcw!8^wVMd%ch$BE2xw|-1QDSakL&Ag>g!rRXSEc=G~bi&Sjw_2 z|M(C8>#yGV`On>Y&H(_wXe=!)EqUjEYGMieL*_Nw{)e4&uAI;3RaI3reaBj_q2mtu z&N(Mk@D!t~(peP-m>OYklum1Wg3ua>#4e|4lhWwE!r~5zF-g4f8kEyw|NAD)AWWxw zv}u}t5)}QGUdQ86e7p%`R|JH#We&)~+-P(|{_o8(@Slr{k0^SutAK7L7G2t2jUB*$ zP=X*DWiMm#leqnpLhr|(31a88s$)`013-$t$xGiveP5F2FLLMpp-o<&oBVE@G_62Z z8}bg|iIjW3E6NNyqVVLj4l?@ToiwOi{9YvGycoo6yxuk}HC@07qly3lq$g}21BhV zYeWfHa1BoEzTZA88XLn?O-&@pCi}Xt|AudQ&3As!kJ)B?FIDE);2(al&-MZ^7GY&| z1rA?vIT&kUJQ+bz6i|#Tj79|%g@vW1F%+YsVPzm}Y;K(XkH7iLKe@hs=FxM{0B9bh z<&~8cTNFi`$qQ(WF;%1U2i|N}RaI54a#d9YgjPgrK+x#7IrJLZD$(Dt7-r@*5)lNU zGwLd)(oKNW4AwR?7Eq$DxuPm5YB*{e);h>i961OOy{~Wd8*c{ix-3zY6TAKr?#@ku zG*1OtIY?OmM&Da^(JcRB$V3|XN&Hbpz3_V4xQ=O*gJCs9N6+pL++-3O>p?}vawLtOWJe?P-mN|Ita z)`8vVLi^U2E)Zzw=kL^iAm<%$KGq7}2*~}JYltPlN{as9oADxRgp#IFCILX)%19$P z5D{t;5=PcQX{NZkgfRm~%V<7XQ)Cz$q%_jq><-G_kFq&L0rr{9F-Gfxyt=4+4Ep9e zVpeGH+QIsvWO5IkwID>sb=ssKp_Ptetc>>qF)>u2%(Il3_~kOdL{lFRR6x=9TN8b{ z2fE~N%nxLOY>P*BlL}hssR4*mavDeRDe_V-#Z^;1F!I7`V>nE7jOzE(oU0t3p)sb> z02rtn<-~xSGdId|UT&zZ4$_j`aI3lPj*V?BMfU^i-ZGDH#WGr;J|DQ}I%Wr(sPydIvgrAmBV{4*A8e`g?b04al(1K_a5jIyJp_Qe{j%%nGX=H9xhscQYyQY zz9*q^!~s*_EK^ZN_40{I4k*aQ4~jwp2Tu94Fr^{Ug7StWw%MR?0`6o%?8D}tL{pgj zSx*y(7cooVTwaGRHd5@jf`dE(x~7ntHM#U5pq^>wkY;%i03k68%}6HpYU)1pxVu1~ zT!Y><$?aR`E~MuT#Z;d<^6GP1c@&^Pdai9VmA`%n(tk$+0oo3SEE?CFZ9_&Hqk%W1 zc>^fEH+`uJL++oPoQ^kA+=GY6C6YnP#PQ0+0-mfOzim_jVge)l6HsN>DJ&7e%#E?1(^;9@9ZefSD%kNSG&DYitaJFk|VUfk)$0oVXkmg!Cl#95S(V z1|i*h8>@fFuo+@+0n^G?vffe@0eEd~ZUT#@W+cRNhg9B+L7o7N9#J)%BLBeflvPd09;j-)%uwSUhv|t{n|}3S5{>OU~H|y z54VSpr^9GG9dzpm;K~YI<)Esnn%q*kx}mL2B5LzLSNjWKS%TZ#1h=sPZhZr2x*c@> zSbL<@AOJa_at>}b1vi_*bmR0F?*H^hes=xA``@=8>#=7%<5|!9fq(f!KVi@mbxVru zaxyOjHq~tyJ%Gl*Xn6@%4;^YA4}fxBHpA5#1c>~GiJ&aY^7r2MpMUMsw|?>?@>uM- z-H8!bS5{UqEJ(GXM$pz^EoP`(oxBN%=&G`E%yjG+$61@z%f9 z_ZZYDVNr9PYpZyeS3uNu z&%mTv&Y?w7(}27h=3q7tBS{~CHiZZE>yW!o6!}0GXpB96F*2rdC-1fa*RD$<$90D&OMg;WJM-EWg#ze3+{^J82)5>H#hf7^zizrlP8WII%uBx{1<-xgO8lDuB-sOKVkp?Q0UVeuJ(&VbwA0;t=)=zrj$IwB~i+c4i;2Uk^F_uu;ApL+PN&%S-X z52?y`CM`ieWNer;{c2$*&5gyP6Ka>+s*I2?{N!Z?pJY0n)a$xO0*MpQ#d zzXIa%h~&tD;ucF$Crgl0mf{OhU+d-^#U{w#moM8gM;9UwgBF>s5oX=DfHIQ^RN{tW zgT*c;L29_CryF2aQ?Hd5`P6_`{{>3Y0Q8vsX@CNDejcd6MPGrqubTfo&_-Vj41lib z>|QlhdjW7z0=TyRB0FtbbH-%3Uxu87rU4;n5SXXLi!vvgMd|Z<;po59_g3Q(J1E{= z&sTE4Wg7iq=Q}*^ukXIrGw2DVJGXy`oS;WbojHbjB?V)n=1orB2Rx?)B(@QXENC&a zPbBZPNDN39z#dKA<7ixvPVbO1{Xj7cCJm@b8cd2)4y0jW#I8td5YQa@lZh~N$_ja8 z96KRG5Z0L2EuQ%&yzELF??S0ouW<4;2kZbBW^Mu#Kyyom< zh2);XmdV>xhKXb*evSfjM&6szz{v>Tf*6EACAyi%Y6rG3IRYZ8syZ&s7-MX3{cnr~ z00cq%z8iqg*Rzfdiu}E|y*=Ho%Ce+=lu&g1-h1wP{tI64{L8Po_J-pRJpyiPTIs4SrkVg(3+3>0!l!Ig8EZ?A(R znm%~Pt-p2b_J8~Z0C4-UMw?6~%ddUykNwOQS6q3Gt16&|!r%6?)J&%-1S5D>ge?kK zJ$Mkt%gfOgW^HZ0=v>XdaFqk+e54||-+SAC`HlCz_uYS?_T=aCw$40%RVlZA>}R&CC~;%xuLsmqI!awS3t6!p4gzAOS*d z5dlU2#~bZfqlJN$&_o<0d9*Q=lmsB*k~~zop=ldp?X{4y#{Iw6(hGPv7%S(M@lQD%sJC3?gIc8ksS;LllB69=$_(Zw#kK|jXrCtL7_%#&rhgLWa^Ki?FKgOmkm1y z!DXbGw7JXy(7}pGQoWm+A^_l;vw0UgVt@m^M(0WI!Paz6G9_atbqEvMoaByrboG$r z+Z&7r8F|e(=6d^%y)?&okp`z}G@lNVY4TBNwuj2yp1S_Wa*M!B=rCdQ|6&50q&)~f zkaH|rFQLk3T>oXw4XhqBzRnk{7pOJlNg4sF;1NcHA(sIrIY7e)jPcOQFu#B>KWrm9 zh38dG_b&JuB*=!lb=JpZv*dcgfGCG!A*DcRH`s`-#q&p%Ozs--tJt?(U_k}EjEee zkxa2Rutk%hXL`@C5wOTA$uxjW5wkC+|2w2hUo4vcAqHz&Q-A{}s5GFlTBLF16kF70 zK8fCzneD0I1r9c}Q=8%ifF`Zz->c?-=skNj@9QBxIIuu$;w~^hl?IPHIDSZ2UU~Dk zXfn+vxttT;`t!srLG>OWU=(W*F6Sm{q>M0aMaEF3%)XX0j$OoLk}^ht&_}8l8Sr7R z=U^V2GRIO2ow|!kB0<(uB%$$RYAz`Jim3DWm86gi=!lxeoedSF7ewwmk)8tDFe(8* zm_8oGWZrjWycUqPSL+MKq!~Q!uW{$Mk<8O1ELW}0mWdW7x<)1#Z~LFM&A8VOOhWC_ z_<+TAV*N8Nv-Y&C1jCpP5Z9f}*@b(t5u5WtnDee`&0l!Rf4eIgY{9Jh?*n5fuz~?+ z)7f;oy}iAkrvLtR;(`0`x$^3xk9*>m+;R(n9aXM^`D_kuHm^Q%4) z;jeto^S+jdu&T(9RFb)Wpi$3B=lo^uWW7-P)R%IeCfumzt0dGid@JmghXR=}u2)R+PWwt!Go zgR&JSxu{~xLvBLIHewKzJ`#Fy9^;bG8-)u$2LSS09syS{MU*Fj`f5dgz3@Q2aPopg z7AHx3Onj|8;wd*^&2&heC^B|~2V`;unm2jOHXqV7t0NN}MD!p39eom?&Xr{2oG=u4 zqo7dvQHvN8jSFUUZCwrm+>1amB%*7jX`T1c<`bK@?XK8DTp%DYEa^m@ z>h9pXC1sP1_Z!sX1X%=IT#xRg^p&%HCGF3^7_v?pI^%Nl)wU9&8V+5fNEqO~j;Sb)`W>V++eY#X^Fab8bGL&u7!=bU!w!o9kyz zub(>k;8jNsPp*IBlb%u(qhewU*xud-s2mWQhRTfGVZFry!atjofX3v`ZEOK;ZGoH5 zy;)gJZ%0#03;=;#Ra4pLbC^%Jz|H67eYbw(ryjWNqi+U)YQGO`Uj6Ft`mvjyaMM%D zdD$5LQM4%3w0-9((INWJjtVHoV}K?Fz%M(_xf%dyK!d7b4b01V`G@cL-T&|h@A#d6 zPeks50RUW8RaIG*YX{a2)aG-3V`~;egQlF%=U#K~oO5WQ?CwR<`Kub6KP7MQagFk$m4c8^viq6c<3tTcibE>#>Y^N#%>zb#|i*2^t&ac zaWI*PNi8${Y&8FQrcV3@$)rv;<3pQyZZ6ue$`<*ZbNM|FZT>Z1nnm3Fck^?5eZKko z8`6vwO)DK4Hi6c!1*vHO@zj`k-U#N4Di9Eo7hC}CBksx%3VV#R z7kjUjLH)ZS$QkSnF)XAGP(Qw=DMh~TGf@RMDDffj4W%E9L~@S?c#I@KLe`fB>c!ML z81|7P&hXTqhZr#MdUQT1@4T-W{l7J^B#@5&agEl-{7LzOYUs+EWux5p{QC>_b6_(x z!y`5Xlb}lk)?|ID8bd!|7zF=bB0s36W>=!J8z*|<|A1{uSFHpH-+^<^8APm{a~ta$ z>pZ4=zr7whe(c_R?!NoJ%da~6xW`?8!;NRQX2sgl5?C~V&Orr@$zM3dG#JhB24*?~ z*xrU}HU*qafDoFjdlL);sVaf03g+8eP;PHPHJ@(Y{jtCO;Ro;d)Nec%5}%DR_J@Ax zwQo9n=fu1y4(tgJvW9)YWB48+!|6mVq)^LYtXlf2-Z1LqvQ z|9$Uy=P$hFO|P3yr(0debY3I?uBxi>WNBipwSa(xfMr!x5sFAa4QU8nBMI z!a@?vnP;~|RPfrwckO9EaGL=l4wbbw58BsFmwDqedJP?R75qL3dleUfI0TrS|kd1A8J zgNW$LHA_-&FAs{O`B6_(ZEbDMwzs$U`yO)o;fLuSw*(6LvuIaIS5fH6Q-1voE50+y@hKxGBx_7;@0EpYQ0Oiw?0@0}lb z&$pbq@2)?8EN#m#d)fc=nyaop`nakr0jO>E$<>qp+7}>Z2AIOaWOccX3TzkxOfX)j5KtxoGMx)8n(h>myde#k#?5JY^0lkLZ zRjzUk3m`6RC>Y3@Ofe%-LSt+|?WoiE$!qm6Y5@5p7$OrFqtZ2FW5ATo&zt{9dO$2A zf=&9lOL4of>Zo?qIr%A9R0tvDCnj+~i)Up7LqyM>P-1OJytFb~Gq>YA2dB7cdVkbh zi6wo$E0QcTtv4OH(9lD@PNwWE`#eq*K(*-73Ki6}{Tu;Tia*L0I*U(;;VkLGbDtGN zWQ++AQ)6+*P0u3cdHb0KFl53BGHoM~qsZn2&T6Uzi3VSF<<^>bIsMNuWY|NOZ4e$K z-Vuw&2KLDhq~>=K?}@W^j*uAmgGQrI05FlCT*MM_NueP)yk_;SePr`!OD*J+y9 zlXjo+c)j>ugqRW;iaMiw7l4ULAfvo9KY!BdNzZQe^nZR|#KWQ3L^b+8gI3$blXHFt zu!O5{-$uR=MErheeYqg2A=`S9;^!e;FU{FsXYPdSXILQ_Ij%!w&>deF2tHfJT8oiP z!;vx8fM7+`Cfd$zZ*6W>RaHF}_L14v=A(Ci>f`UZ_nt4_Hyy9uGG1A`d@>#(ID+Zs zCRnU#`&d-~(-}a}px1_W;2c0z0Zykto11{s8DLe`bQ@QJo6W$@W>C(y>;FxsvlDmT z_Pcj|=zZV0_2?tFKE`l)I&k3Nk+1lQ=ez{S849NVj)4Fz_20inlL-_>;nxW;#?*co zRR#0e49a;4^VuBA`J6s?`)5A&#vgy(_ul=*yY3irK=yoHiK?oqrKP1MpG;@0v0f5j zg;S?r9G!E{RaF(Eb&wj&c}f*qTyq;-M0?9_u+(86mrkbj&7PE*G>HiT3KYCHC6Vzz zD1ZyUV1^7=HQET!8f#(`7Yf(Vu#8uE?e&dO7#k`Ss_b=DwEtld4d0nbb@rn0kgwbvl3pHdlC~*U71eE53 zq)gW^s9oBSDL8}tJWh-l&Ho(i5? z_4P50kyT->MPm)}RmVFfvU`~bXu7?+{p=^MxbmuNZ@m7-rx-Mamp}OEKXL>Z zTE@Ceo-D64j~qn^A^_DOz`TOlbml(#kq`d;8-L>U-*e~Z@A&l43USe)-O~EK!8zPjC0QEW-nadM2W78a+Di0o7yv862G#g1PACuk)s8Ad+L$?h+2|*9%2s;dH zIPFT0;1QX(naOodmyF6}hkq6&kb^+(JDPMD5U->bhaJCzJxv@g(6nnmkD2m$h^#)# z&Jb?H(bW_>NpDYq4(~>!Xh);~M0s5siFYm`95QcYAzwl89VQyDu4lN_5~t;38`}b2W}0 zlV>7^O=6TANhDDnr11C1t^pjBlz_m1b4}!a8G}Dm(xs%aBOiQ3Mukzm1}qL)0F%+V z*KyOKX$@W;kY&K7`wptZxyG1LQ53~!JhIkW3_bvWH6Tz=)vz(YBm&yr z+S)4jS@hq~*L-W^;p3nC2CAjS=z-$II zn*vo8xUvFr6;$&QTvgT0zjH9(T(8z2I{x`DeCT~YeE+9E@-v%{Jov%Kg5E#(D$8>I zH-Gc~ci#Tl&-|k!N0%MB>}X+&F(MeCI?ANJh3ngVyflH)WGo2ewf6!MK~*_AapJ_o zzyG%X^6S6!);GWI*s%xhUgUVr8vtO7qF7p9TK011Cp51HKrYW@sb-(g2qe35J8FUg3n3(yjDVBFoBV7`LtWD^ZyA{(IK-p`p7s5Hv5&^3|t0WjA9%gs40m=Pdq z(12-x;f0RY=Oj%#owgd~7jl$f7~pfUljdzF-?f_Oy~7(u{mx~k>K=S&7XuJ5sjkx4C;L(oOPI=7Ok$FW%IEjw z#B29)?|lx)n_m!daVbj-A+>OmAP6R)9G~}UAh3SzxS<6o`8#LIw1NrJ*96`#&dIgJW537abRokE%Bz_svby38fQfD)Jl5+g|~Ki~F1 zxokkP0}@W9>Os|l6UY?*@jVKJqKYCOn$C{XT5F9p)>vz;Ev(`1&&(Hnfz5l__HQ5#4jo-Jg5^ z```Cx?|IL=|L^zz^X5|0?Do4&$ zWhEUxYvx3|$cDHRanZeQC)K8F(g5y$>JtZmZNBI;2O?xr-&`T@;w-4&od$48oDfD0 zy!;H)P@dX}yI;goGe91r(*7(U^%Z>F6M=}lag2Yjcv6q4MpL8XOXQht%G5EXHsbuX zX1S}WMWLyW&To&*(6DDRoBO#|=GSK8;sE+8sPRL?nv)!*U#4kerd3S!+8D+B1;=O@ zWZ2%RQ(naJ`&?$J?^WZ!7gKmS`PL#Vp~vl?gu&C~l!&HGPdpCv@kg zF}@H0q`f|#A<~mBa4lyr*f+IK;_x!EKK;C723^E(QxaFwbr>kOXMkj`Wf%{MpNm{` zg|VOZOiEt>E$S9_8w1(1-l(6MW3nkAktVa0*H;bS0$~i&7gf8L>pO11715kJzZX(QzabQJx(Wm?6CBuGs~| zJAQH1F{!;#HH^;Pu&IGIuU)N4ziW#8U;J~&6AoGi10}VvZS?olw`tCfxqL zwzjsm;IT#j&u-Dvjnnr%a`!*|~~MybLane>i)a_X5*n_pP8un$W&foi_l0h-fyQPK)t) zY^|-2gB*DzHcavxaFT?03Apyi$D-6BC(&dvns|D{f$X*_-Ck1!)JMQ*C@&^XsEKJU z%4vX}ZBOc=2Tbo3Yo21ZL;HTIYi!VQv5hdMT*U_+(e*PlLA}^xQ<5DNo~A>G8P8-W zGDak&U`rSQq5w;#$2}9PMJJ*-kjkI?xiq~Xb&gg&26hQr=$-=zLmN^Q_vQXRzPjS|7QJ>|9uaY5FRBeZs?A-TRp0hA6zQ!s!^+6zM>8Vi z6-S5D{*Z`Skj$|Kzu27uq@?~_8<#fZ`$Q#DxQ#^yMa~&h(ueNB8WTbVSA|T2OEFXV zASzDwF-YCT*y0g}{h)~O_=#fsQ2jm41TX%KwAs}LR_*-_1Pb6LL53ieO)?=U@!=v- z$7;rc6g|U^G#@HiZ}U1h%n}3b!S4qY{eN&fWB`n52LHwuwkT{-_b1KgTVvbbtFMn| z0Zg~Ix6Ao_ez7&NM6TRkfAsG4hmL*xo=(qpi4}R}A-v0LA{grpT>bTq$WOj>45i3pX7h5ijSdRs9aS zCTZNeCLHm`0|dfEFjcQ(R7hZBq8N_1nf61Mc~28>0s)aVX&!0-JhfsUP!?8Mt!IwD zuL3BU4PHzy6Jq~>LWE?3Ku@+ec1+h7>t6>n{z}?G+_ZsiP?-5M%Eedi;jyP6f&O>9 zrP^!R=H1Mje1W^;W9hiJcJ;n}$Gl*pkIcCoyY90@derrK*bj=FttPhT8SOld9NnMb zVwlvZ_vfN10bTd{(1v~|pS$oeYLskc--7{0c)S_G1k$8z%peD6`<}lc&oK@GKn67K zxCiSH3}h9=rp$oqo}0WEX1P7xtfaJwS7i_yn9uhV_KwIRQQJQ=Npe$=K8PWV_eP?~ z{XTBQWA7zTD@VoP89;CR5mEy~%JLwLh{i^x4(0$w?!EXF-#KzEqZAc(3$h^-KPTa# z5V38E;6`zE zQY@lUkT2NY38#6;DMaVB3zRWvh)pCVRSB61nKTlNW(U#2WFj*j$V^2Rj`3npK%7@9 z!3Dq^!konWg}i#5E(wW#OQ(8vxdrnLHcR1?J_{XJLEG$ejWy;9Cvm`}=t(0#gbolu zJ0FcgsKzSwOwYI{0di+{g{laBQHMPq14A1-nQ09f+4wTUpdlM*KqwOE(HB7LqCGsSds&g9E+mwmHT422uKJ*0{=daTynn5 zbT%4fsP!_b{x_|;H73I;Ir-<$jQ0fK&A+kMdO1N|_1EcR-gv~zkzz!a*#1GeA$>@n$Qoa)m9d@hEQ-iPz@i#&mqcnzeuk@{Cg!GZIIX5Ywka zhzr4_B-NyQC^TJ-XL+W0qHQOeQ*kuelvr(bVCk}mT8J)0%GxqcMIxU`!8 zxS@~fT9AoRl$)w-n*6`GL{m=+ph7K8oHxL-z>-LL2bB&o5rS%=A!Hgujq0QUQA{CB zQwM-W=Xl18YU-yoXPRqzXQ7xs=OOHb{Qa6Q8h3+;=cbNbO^SbRj4_4=fC$h77M!n! z4?9e#>gSXqnUmJktCEON94d27ISJDym>rtlAppSO=C1<~yHK0LuRm{kuq_O0n1r3k_^nJ&> z0?RV%PA{WCp>GdigLD~1`U!9@K2Bqmsg(FEsDe=w$p2J=<<=(~iHp;RcY^G^-Sx2M8jHKM`z z{JCkh-wO?fNX)t;Xh95bP+SKNMu`O8f2;;)0FAXacoa3vVq?&dBZmyE@we)9I-OQk zRb6T+&jZk2ueK&@%6{o}VFLihSTmU{O+2mMZ{(&i1EfZmq(nQ4stHhQ@W(TSd4rFNo{1L#ktz^!k#@jj4xDDDZDKBIxDh%x1J85{xUq?( zVH6^ZFakpKMY!DzoU0sp`i?)H1b4yt(Hv(@_ANa}MwGd|mnA*fATFl*)eA2+o1 zj6%78XxC3UnIR|KWv;3+wtA#^y*5IYx2rz?F=Qj-5WI#vGZa{qnCC#tuk)ex-&7qvff;K_mYzwJL9N4T# z6C~;=umeRk084QtWdsn=TS4z&O8yHT1jv+1*4e zp6zSX%R<`2bz#v1gD6@Sll=-6=Y2V$#~ec}Y0PCV3aV=riUgqO8D-2c>;M3y-CES> z3eY##p!B7GB;Q*Uos7V}gQEMi2W-yy-XyGv4rxYm9%0%6sGIS%*o}VOl>0N>1Asin zE{==DXwR?xszJmtV`%zi)E{S~a%w#a1_C6235gn&BJ*Z`MWyL+pZ5i*ks=x=r$Ip)dpvOoL`P7r>{+<0^9dSJFpX`oC}Z<2c4RL$jq1 zARugRZf;(h{-2vyVR7<=!z)kyfvb+Z{*7kx)2}h(@A;C-Jn0E%+?6-3yDOetnJ0Y% z*q6U#G=Ax2m#sejxS_rsr3P9nmINAfb%(= z10qq{MOJUHaWGQK|GYa%fHEc~dSi+i3U#a)%;^rJCfZ9WIv0A1HXdNE`6&X73bHJY zQ@I{tGv_n}*oi?ZP*`vf#FDvg8W%oSIRXY{GKw5YuP!Hd1{b9 z(f)jmwHA`$5Jvt3rlE1Vz(Q#DMbGeT>c}Plz*<|_h=I^Zlri8lb>HEfbK6^6TbHK) zXZN+XR9yDls}FtS8?L(it#72_&0klny!i6UU18VO(5$S0U0DIMv;;UBfhh{SY+hdR zg3(bS{zyJVORh4tjt*)-FdZg7FYy1jo8$Fi6 zc5g*S{jYWJ1i`FBDN0;}szzuc^BRPK#!G!}^*VJ9aM1gyi3HdaXwzMA$}XBBYFlc! zlgqE==y$y6Q}p{rrDCJnVYEoAh~Nn{Nz<#-&eG@;C*lFq*d$h}F^WkhtFZ=~GKD*K zOwEx|S!uvzk7SV}HXJRUX%X%Io=yq-8u>1HLvBLOjhvMGCHEZ0hIQ22K%r(Xm@{OQ z_gVwGb)7p6qSxlXgWmf*gG^x(aY_;JB=!HvF((hS;;tQ@1%pG`B0Fm6_F=KLCRs7&tNalVaUA&UF(9f?q{d$JV_;be$xqc(lp6uL^ip~+TP1pQvMxPlRWCovQIz` z&Vc9vP5HisLI$D5A}VN0d@f?`abCZ@fXsumH9P`Ca6r9;VvWp4&w(5gD6)ZgjrLoF zHSy;lB&^7tzn?|B|sx5dMyXHGtqf zwmc}Xy|uMZ< zj{#ZYFB$__6o8Wn;AjNnvKrsw?2}$m!nZtgW%(@A z3hXFp^5ur4O(K|CPOf27oqwYZh13ZqDjCtT_{%nGIfg<YppGcqG;Rzko)cU6f!^jvDR4UoSROk(@X98-o3_!S$X{0TmzNQ+jts%T`VYo_VT#|-Z>p-QT8&Sm zk&l|*Ci<`Le3L~#mszh->Gi7zyZ@xo@>bAG;d!3`mf@XB0Q)Ewek|i(xOl4*G!590RS35)C<*`T+<@4z$AzML&7&M5J!tb>#qK z#Q0GLA=>eQ*k7>+)NBVMGHQ|3L?!G5ef9M%Id5eE5H-8nzLVU`2z&}{SWTthm#IiA zFAKng-RYUDO;4HikV@BSiVcPl&{$(*BS8dDZ3jh;pql9gUl@as90Rn`gRJ=v!#QdK zwj3 zpe)PMAmU`QGyy~;=Nz+2Yhqbi8hQ-?xQYTTr$JH~Rk%fxDM5cBOyRkKiCFA~IU0|7 zY5m($s#v~BBBj{Ip2ol=*2eC^iSvvr;3<+tX zm~9{&CCLGqh9F);xrY@*(XD5@3&smT`+qjy|7<1%3<4T^j-fBEbI-0{Bgq;<87CG^ z)_MI{gj(18XicRi0qX;r7Xn9ibKN2~lx9E-S=JkLNgfp)c(i%2WFJ0wKt)fV+h_Yg z70gK>GtZ6wc_e<$AawkGaw8^T&Z0Bfz~&3@M&?fL9k z@EddqsC*CUm(aK%5~unbe*Ju%$D{<5zcthE9Ra(*5gt+9f?EW@d=RLi3WJDKBqrhW z$z%Qlob%H|BIhbc08m(K5fRUvK683|dwcs*>%P0!)dwa|_+PF)^4hmveZ_D8s9pZC zr&sv2)urW$U0nscx(YZR@7?}28i83}1~Zw!GTO;g=I$xqzOwq7Z#a7B)y3NA;Qdu~ z@5Zb;bqN4C4=<0dtsOXUz8X}7r@Xs zDL~w#P&Un3d7*14i`333dTKNULmjC*rZ`>tT*|;*S{xS&KpZWm>kI?hGjS89}(<~A-Q0%s#Z;;{k(WX;>o;W_Ly(V*)%ckBhxNxJVcM5QQV zwq5L)o;Z^v!|(bb;F~-y4d5naP1wnIK+u!ks(_Tz*iQpFspo@J5FiDOQy?7kfM$>X z0cs!%rhua)zwI*C9Ce$IYh^Ca}qU5gDOMMkXqIUOYewZK$=@T4T9fvW}xi zwANVD7}G%%=iKf(v9mtA%X&O+ba0QN`VBhbB%#sV%YhlNlfVdU0gTfF;%5WIbw^ER z+S);5lq1mq58kkkl&D|ZND^$**oSv!5!tS3PP~tUt6X*Z^y$-Z$^36eufpK?6}KGy zSKoPX^#}glWc6qN#SC9@ZDp<~io)8})p}ZQEx_5>!Vv>20LNpn&e@|=clnFw@S>Nm zt$ynbSFAks&@~5c{-=jGKJr*+1=tJifE+nGbm-8bTHEhjW6>EG%AU^aoNE^eKx)vv zI-|ZZk_n3VnkK{>*>FFI&j9RZ@~O_?NwbeigUJ`D{3Kl4P*CLKf^emkn@7D^^9D{t z@MQ~r0*%Uy0eMdK^pZtDB08zN(c?6DO-o52(+G0LerzWUzq%8xEe$l%UkZSK7Mo&%#~hKuzTlCTDUjCj{WIo8Zn~u!;YH26uK6`t zmP#tE2`W(~g40K#?iLu5v6q@8L7T$##rr{~fk`viMdPD1L@*#qZpbtJSOWmg*Ew`g zOossmd;L8TgHTb8=gkAWF%3D+gU@-&bl!u?IxnZ(nDN3fOcFzT47#X*ZpQG?8xALH zPiTVjfCp)ExZGsD13<)HFf)Ho>9vNz9J@kF0Eo#tkej+HEhleY6aR&5A`Gfjepyq+ z2?3}PDMEo`8q-;xZ{KETrPs=c2tq!shYof_k|q!aNeHRT)DZ+*J)?j)6z${f&*&Tv zF2lg+x`Y`JrVNV^It?u=BCVZ`cwzJZ$zD!DK^&fC0)p+WtxJyb3%-u5jj#QIuekDm z|MhP_{F^`c)uV5J-c!x94{y&8S$hZ(m+Hp9L)*XS`F?q#pPqX{0W6I{9C^CxF_Y&}K|11~rLU}a@xWjvWoJYt6oHIyPA=bTFvW(`e; zFOtS53a}NCn}nE#LLZx)7!1R6a@5sO#03EgAb=8NJI+)US*;=6AT|ipiukaID#yb& z3eGt2C~o5ZEn;KR4Nd0EwjY!$SfUBNq|&M9-csSStcQ+yOA9ApN)uP%4ZZ0Z*$h?ONdJSy!a}%{3g`1*$YfWB*+2%jb93TkBf^3~J+OcHr6KzVhpPJ|0 zHr;0vL>T)1L!1Aurh6zrxajfAcsg%-MniPq4D6TSz4Qg>l0GCX95IZ}nc8y1TxFbT zO>O71j{W`tf)Uil{bICkg?fq`B?B-mx3ZV@nVDw(PBr`Ox@QF|Aq5{144UrYO%E^~ zQ}APN2NI3AuNk%JKJp2UNc@RdQcW}O9q3btr8W%oQ|$KTqFS#7rVaYKHE8Hrkd~ij zx9fE52NkD8NrP-u*XdA0E5Lwn$f;om=#kvIhYzqc1K^-eli~%8X+X()VEC@cx!?ol zTmJfbH$Y4TkN`S@+OV@3M*7b~W6XR$o6qOv{8Id1|7&%5bosTb;~ReXt1kODzxv%r zfBDqs!OkwhxH5h%_ z0WeoAgBeZC(Hq8>f8BErzVKf>W$jxIV{z@>k5u=T25J5niW0m48307q7S;q>jCwMu4m{jq6Qe&+Ri;_XZV_3YwAmeuVbwRMnFrJ`i0%|3_$T!?DK>x^_VWTuh zY1S&Fz6IW4xK=C?MDhr>NJARfEooxIbe*xLKS@XspN~B9CgWBd10byFQ>fCwSP{Ir zSR_iR3lxwIKd>q65UMh1CWH$(qW4YBc9NyO@XE@I)CH%7z0<@@WK#|hkbsoD2;$9= z__QN4B_dH+cj^#T=je>Ipu@phJKw${I5q!^@5fG1ATdbv#UGqg$)Zt`=L-NBGBMX0{tKzFOif^S4*J0!BmxNYec*ZMD8Rg~*f!quP{;?@ zJTy#q%1h)4-!{R~pLgvsS?S#3*9QkmyCicEaytBQ;>^2<19A$8m(|B-0B{@%a0mze z95`S)YAuzL9=%8NEgEZ3^M&Hqq5+$|Av9^mkYVzU-8F+?QTm3LH?f?;9;Zar!!c@1 z1zX)arO~gAw-!ZTFQ#$P%_N`83UZ*Jukkbwtdy|@sLLimjUa?1Dv--eC<1JJ>OpoO z*6h^&9TnQg324wb=iJuj=4N%t{IByhvS#VI*RFl-FTV2n|M-?~ zJ@}@tfAPT=UH-*qaK#wKagH3E<(&01vO#ae@eV+0o@AFMQhQ`QQEQ1K;;$*IoAF zdymcTJ+@ii=ZN1`Kp0$&zOl7+xGbrMC1+}xrmg)A`GPLy*6&K0J9 z^T0?$N1c;d5{~C``XHT*wYp|cjk1ygu=|aHX<-LX<1*(U8yihN(;0oJOpViKL>8DB zU7#*wtLQtC4YQ_)Rg4Bn8fD3hZPf%ZqhTE|Aq&pRygekSJ zQDRmlmrELyrqwARA?%xl0WGg}^B@mI=hw1l5q$0H!IgG61{eboS{;U|fn)=$U~`>} z!d8v1aXS!*zn{A9_Wx~~d=iKJT#>S-V5Wci={%jX~c*T49R zD}Lqm-+ASa-tx4S8<&==F)l459y|=VvBN>Y7Iv}8`0`vG1iWkga@=aHOxqc1o)i(fMek0)85in~<0Y{hBTpeox zmzDuXBY>*JrR8e;q^GQ1|LU(k_^NNbe)W|HS5_bQg;Vn{tZ$bmF9861_;OWMp)qDW znN0km=3M2xNe2k?zB*0?qh`Ay2%y&-d1TOpZJ-_g*9*BdrdfzwG7F{s%v_dW9=l(wkYiP9Ng8uI~Gm4NL1cqL0^Bin)q`e9mqBRumd*J zV%Q}&SM$I(wUK900gwkC=ug!F0X`b3dNJr90jRFDZzfhYoxYxq-VCy1!*6abE>QE%9x#6ToZ zBW<1bQ6Erb5}~5lI-gj@qV!~=Uk`eyqxr|i?Dh>o2}PFeAZ?YxamK(SSq#x>;*10D`gB8s@`c5RiO7 z;bX*ELvZ@^qo=*!*rith;EFH5;lK-C`_ilaw_knL6~FdPFFEki$35x5RmBLcId}+g z?GWJdO5W7Z7{JjOaIy@zyb7?g0_M;b6wjW3y=DfqMc__?*AoI`utW=fJEUnB7jg~& zDzGW_~{r?5q32UZ@9F6h*PLyu56THO@H)&bct1ZyY&{ zvBtyv-uT2-uJTkVPdN|BUc&}xr*bVAV2v@F13@LhaA;KcLaHA|Bw5C!_5ar4V zl5WPFPI;4II-Pk_t|3oxYCyUmt=#8UAzWlO*Cfo;54Aw!X5ry*w_{7A^>DFtasXEV6N#O(ui=NgwZOa znxaR>p}FO2gbwWaI6PQg_I z&H3HPc)DGz#pxPG{c;WAXF^#oj#$0}3A-^5dV>JEyI5YN>?dJb*X&^!8IfY*rDPPK z)lUTWv@*nuc?|J;M{M&Ck^5ZXf%IK>O zUOrhftE-4>2b!keEav846oAF31_H(-Fb5sjCznv%Y@u480-dZ^1lOotnxP3eueomi z-2s5363mTr7{9y#`^*aPnk9g>1GV&^aDXrcsx|=1b%1IMpjrp2Hh{`?0Ga~OJVGD= z4dC)h&00Xf1FN+9+?(xlU-RN4ul|}ZJ@Qg?IKJc9_Gik9|KcS8U~vFoG#Zuj`Fwe4 zvJ}iy7#+(alD;ycV35+Z=gogZ6Wakm4Q0r0YBiFJf%elNeSiQ>ia>0#A~j7Ep~LE= zZV~OCDB9ai+F(Ml7gNKwAH_ih3q_0q6FcF0s#dgVQ{r*nHf9(%7IOX?;+9euR=(&P z7QI5=y;X@Slh?PGDlDcS(DA*fO_87xX6zr5Mo%{QeI5Wq8~iS+XtarH5q^8n_$TMv zVFHPnMnLldNWL3ZOlT%~sOsVe{GFI^VJ0pRgtXKEmUiUp6=pien^&*B*MN4_+%FSPoUFz2XN2z%H<8m= z1pollWXsD*x?!mUqFT!d$D(u?$t+D-pvZs-V>IA7)Vj>OAiQ5QfQzFIjp`i(8A*^~ zDFPlOpv=#9`@AsbYIN^FVrJMTf3*w-KMV|ew3iCkUk(8`?`*C`IWOmDPME-ADLYTT25*rRjy4&Cj!hA z>Fq)o-GqSSG2qH7n588wCZpoUBjxok`?95P{Ep{c{@u^MdG)yuoT7*BdwBYVO8~$Q zUgdl~ud1pt#+cD~JVsB;X^=M_4MtT}wLp+-djFWBgN;ncQw90d(bEIGc^p(RjKfJ>d}0Put|V2K^}ZI>QFKo7;U>t?ve@bG>QVRkG=9Y4s?PU2)7jjD|(e8Z-v^e3^L=Fjsnvnrwu0 zor^mX&IXVsuK8y!jdeyD=iCGEg_vydch(vk*Qvs6T4N~$GiYdQYw@|BH4)1X#MD1| zKx2qIj@!m0b}>kQeZ6hkhy>@T?hG3iaibTo^Z9&!u}A;CHz>-#En1gyub)IhqZu{C4k8ifO9}a1?IX6>XT#&cI7JMBZPqpIAAIXiQeWRLZl*ixrb8>(PSi0m zFIuz!&?#=9YaYeVN^`b$)1=hUj4jp)-9G5yVkcakx(ui_Czvbjc+=ETEMZ4ugna7} z;E#TNVp<_BP>d0OZ{@zg0s4PgiS_|OtudX-`98aj;#~j$I{>vwNG35R$WCM-gaX4GSm$0I}MTgl<+Y4AM7&15v6;R;Cfj-TzrRg61zWcoXh# z&=!&UEMn|8Bu!#J#W3Zy=okL+F7k7WcmOPZ4Jh&T0G2v~tl5lzh9GTXa7PdrW&n(w zcLfSI9Wd{Up=>Z5cx{r1O=WGt9-voCR`K)rK+9+Q5@mc%qCZDafr!L(HHs-zuDSC4 zrSAF05Zez-RO3M+jpE>IY+y%nluWut-LOfxk07i8jHY+AXpC`;Q3`D056sQKJq|RU zel8g$9PG(0+87K3<4PkoCZvHtHmd12fq5#l{;|{%NCkO?9#Y@)Vm}RT+Gm141Fz*x zd>_fEMLBe9&<)=c5Fj`g6u^PuYpk)xTD!5nzJ9Se{~LqFq_C?`Ik5a?Z~kXj|JIwn zX8hx~e5t*u09T+vz{$AL#!vK~e}@wjt^4-f&Q_KA`=KhUGP5$P>fC#KFx@kk(VWKZd(Wv; zOXmN7|F?)1h!9ZBAe_~L@683WcV(at0@$pzaewk@;w-Qjosnf>f1-?u*cqhH=s zUpz79#Gq9uyafP^9$=PbdwYvLvec=zkz)s4tQU!@(v`89oecos!n%GGV1I!L<5rSc z^p5+m3k-0?>6>~nV(3rB6HVrD(;4=95}jpEilVarKL#d5j?ZNhxF#|ky4{Zm@(Q&P z`XdvO3D3P#T*-juI^3iw{z-cp>(I0>s%sA$$Rz9#6hM(Fc4{JH&nr95!jsm}fc}rb zASqdR6Q)zIgH(f|VmF+;Q;^~i>NCkRWb%<2H%gNRGtA1v2nyuvPx4>)g{06$MSi{~@iKCHYBYWpCnJsCUNVwkHAT-;R5hhZ20zF2< z;FX~0G@k~}jq8OZ0lhF5B|H@08{U|)^X&ly9`ItMr+E(=T54)XfzLklql*1=?j|RQ zmnzUiNVcYw^`1kJy2+2G+gN%##9h@pZ>tWdpoHAekGSl7usoW4H08%N1@t4CDM+7k zE~Ws0)<*YzvFao!3D${}NhAi$gSklni}?$60Ez_c35uRu7i?-7z|DZsN{YMIK`{~2 zYPnn*t@WFs@mGq9TYJURAG>|@Q~%Z7C;q#iQH!7b_BFnRzML!lhXS4v__+co*N}@d zG-(X=w0@UGJ-BgOT1eBVn@V6zL&z|8Cd=TW054|1*&62F8l+dCMG49oeCq)G>>bel z0;Cv?v0L}LKrI^(!1nr5HSeKK^G5)xL4o!j6nN~0mKF^F-YWSZ1Ge7>fOVSm4(8qVqV@Fvk}2J^nQB70|3StQxvnJ$n)GfZ`QON zVpd8C5gDzuh^gKCokReOo>~N!S+P>ATHTau64Imzm^L!B4*;aJPDA%JMRJA1W;E8M zrHX$zPRMTNssDOTBQr83n?lWW8_d(=gVnXlyrJXLg@4#*@a}3l7 znzq!02chgC(Nl@OZ{BZ+DPn#YGoS05Lb7GZ6`~KAb+B3*U7z0Bt&_l=hr~v_Q#OA*@r5pLV*BiufpQ{u#+%qu?_6r%f2gxzy z^ct1{FOwk<+k4-@A7JWpc-8xgyfmaq>DX|x;^4-panSsF)APjVkwk;qk4qi))QKfI zAfe?)!jHsK&SPMlo4`U2ydOK4*31r`A)ZG(X(#xu0iQbwccQ22DZLln7iS@)>cMnv z7qDF%#+lu%I1o^@QGv~eanlKs9h(DAv;ak0`$+`e@7GDLp8%=Yi0fFm?b=<1r3mW|gUo2(((QR&NISf06Ot`)=?5k-z-5JOAZ>tQP;t zU&t1J;eAHEYwzG-rWOn0d5FNa ze`gYJbkn$Nw9PwNPWFQbKv@E23tAB9AcuPU4e)zzgKr&xa)r=GNi6Oq2IR5~oD2;z z&0-NU19W}7wMN7t23?%P9N!1lE6{cWInPl2>K5z2w?Xw81*#U{*&J#SPf6TaMZ~G0HB!I&Goi212^}bA_%Q-4in$>`Gi4NzTf2thO(R~j9l_!3RCmRen~Yo>Z{AT4U33C^`Dp=#LeO^NBvB_rfFky zx`HW2RYycxFcfJxrSj|1;m4-mI~MUnPRB7oB8)tA3x@Fb*mc(*VTVj9o@vB;!Id8* zn}UR{H3|}ijEjK&8lBGXYVH-g4lxSrL;zuzhU+TL{dGtAJx-ec%di0+7K31FV?QRj z7@o*Zi+CJ*regq@BqoTxh_MmSBQ*_Ae@5{mcB3(C?le{q10~XNt#T=rKsaKU6nUGt z*8Te};({O4J^qAN5KA+mC~%W@cj4516@bJsKqI7qQ!nAC|GG^(~J(Ex6)>>J4mR0RVRZ)d!?}u{H%h5U!NK_X4o#3_jD;&J2wabAEPqCXcc6|9hS} z`tJ8Gif{fe-hStQ`k5;KD<3V@_r5KkJ(DjMiWdtIcTWDq49*LXDWG3aC_lM@d0`D+ zY(WPAZP$P{^`#(!G>MNSfYEl+E|AK=7=ct$|5poi)BK~E*gMJYKve<9$Drf;T@%iL zddJ(qcaOlg4?#uV4S^ipk-&lnP1uxuZM#C54*auB1X#v_nD*xh0x30Qxq+OXK~7FU zRR#UU6}G>y#r78s%vWY$nS+a>K5zC$Wd_e?$dpn~3qAFnYx(vcQ`wJy+cQUh{3XKI z=QrlJkIy$Rz6AgTU%INQ*@ua!^tF&NKxQMmyx#-gIt82A~9gRL-PeElF)0?gW{yq-uv_@j!~+e zEc6)n(<|T-;7CW=?lxbV(9m`7;Xd{K=_*|8-33-g3LJ@S{!`BNl%h5In%+5&fDi-J z+RIk>6ilA3rKyT!dm*@w5dpK}{t13T%2A5tFr737$h5|h(Pl#sHzpDf4jMCU>^1Fe z)F(N90K-k11e1|T*E9B-ZFHgtBHG;;ntItu`eaJ!2xL)J!m=SJZ9 z@$}w9A`y&z@FI*Wq)G2Jijr|?|$Fm-kdg7yh?q#@-Na&}gm?SX17e`z44t{Z*fc6$Z zQGjpX28bcdp6`IS&NNRlw@H3ZETI8J8+Q!?2;c_1a2GV$mN3WXkOwD_^#Yb+z)i%7&>-`$vE=>!rqqCCM=Z*(#;FlFx3&nY=crh#=eO}0xHe3xnd!<($v za76AAL@4uaLmw929Hn)`o8kyYkfNxOU%wd-r3vi1aeMj7BC*f98yF)k;3rO`W~`~E zM8O@Ka?zys-mOs@G|(JaPj)ri+od_biYeaX=>9*ovBv8h7r4vxf9x2idJ0ShI#W|& ziA){ElXHpF_fg!%-(mWt_GAB?P|w-k9~#i;y5gJq(v{Z%pf8=95}hkf^A}bvH1rIo zpoJko)RlE4(j>xIJ3n@>zt)A*@@Qg_-EtDgWDkHH8aaE}@h$_zNHm5yG8M2H^qq09 zQ@_|ry5~s|lQ$6T)LOb|r@$<)^SbZvDdI^r+ku#qkP(;3iGREeQ$ids03YdgavI^Y z*2Jl#!t2vA6`Ei7u0dmv==vCOlu;>Y{rsHkqbwVkm{iNW=s*~8WCq*yX1(2RxB4;C z{y%+t?}NAJ`7=NLfoJ~PpQ+T({>A;HfA9S~f7jyRu;AH@NU5D8{AwUTK`wIW&k^*e z3`DO%hZW3r1HCSxPnW=^1TAJQ?Op_}&fb9l>Sp`i1IY0is#osAY)U`_YHtp8;}Cpw zSjX_Grr9>q-njO*66^ZcdNX$#{<;h#XR=Qq73ljJ029o~1X+%=VpD5iuE~C>_q%fVCzyi798S0Z2`0!^!Fp z{WJDDZj_;C*yKzl5XLOV3bT>vnY)vwrwl>tQ*5#k$PtF3uP9PT_gwOW%@|`*O#|QC zg{B+59uWuszW)NnY5Mj#i%Bke&kUhgEbr3rhXrd?=HbX?+G7?UfEaO`mq_DpoBcLc zG!j`9!Z(z-r#WW6wnNcB73rZJDcDmRztr>oumOWdDFNUc2^?G%SQ%^Nr~KS?02egm znUeZ@YWnRx|D4!2K=DMG)N|*viIRq9DLGj%RrQ-SPR5qVNks-gNWA`F;P=vM~+nIbSJ2kX)YMG6;`4^*& z8x<*S&VsZlH6b8kKa*|zW5bTngNXtoyn1M^IO=N?{GR_ACA#NJdoJPCzrE`ey+%e- zW{wmyXAI;Oy(`vG4qAIJD+Tt91iQM|f)fDX^%Bi>K07-*dt9dfMb7(w?A^D1@-N*u z{HuSBivR4RoBSisarW%&;4q^s8=m%0+dP^FgCSeS_OlgMpWLE4t3ZVTnGIkx%%%dA zYU%ytY~!Y^nnwE+a=wBXfae9&otscc`=Hqj0)p9U=*qy9#%cbotG}+N`i+MGnm_do zLr#0>O!Vpkh3M^HI4GOw%GoPfqp&%=^TWHO%Mvt2s??4i5Zk- zDDonEx-w7ykqv+NOj_@ZSQY_BL;uy>B@u2iDSaqpNDE~1WJ%!@>(NDeAKDg8J;_3@&L z+(vdtADw9UV&}sxh&TWZ!rhg_$xwK#?({!0S-;M4-&m0^4htdl7l=AJxUq+0Q}2K& zLIGGXh4LCZhA?`u2f#(HiCq^w&27Xjy#G8(pLr0OgpzCcG_h%)+8{+U$wyv@c6hI` z=KneyyCFbz44iqZ#lPJ1e$}7d1suBUu}ozFc#h-=z!gc8x~7hZ()cL~G!8#YG$&c;!Kw4=secEYIMjdV z_}CfT8KaG5954~B*Xy-;#I^skTpfJd?Snt|m-cV`2Y;33fBkzl^zF9}ZX9IuIrD6` z^R$2L%ZR|#=4$|EsJ;s5&l>0#H^5wgJwo->*8pvx4i|NaY3iwe_2O$V_fB9+4O%R~ zHx5C23-DqNDDECou2ToxIW0L9{|0mGKmct(#s>tf3nAInz;w^Pe)$CEg;znDLiME; zw!c=Q`Yi?Xbp@3zz)Hbc^@8Wj!Txrw+=*(RfTG|V*=+yAr|b8B6vapH&Sy_PSn&F| z)URnH+czBmU|9e+ZXDfUl__c(eQ_w`)?Csw3xfOL`m`v2!bwB~o7d_YgEYD##~Ier zu3P}3H;D`#%p-axH%2aKFKSv+uPO0$RBd!gpkoX-l6b*I5iLCR;$5sUP5N_kFB*&n zD1s7c^uwmnr5qxRR!ivf)3I#Ricg6YCEes#ya=PwLM?Hiu^2#i!rU<%(2H5~WDgT2 zI9D}SbEPh0N!gr`k=Wh6i&E-xbtz<)cr1|qwUY$+5`KUrpy8Mjwyk?WSEN)E8pb&$ zj<2Q51}?^whz8wt%AW#7hh8VjsJN!aJ@y)@XK|Wj$^T4aQ~pQI2jGpO-@n!d{F1-| zB@%D0axcc>Mk!cVXh2FeC5|r1PKrjkUC!5q!syh%P}Qp!V%qizukWReOaxhC*9(Ce zuSC2^CW8_YL%}dc7X(T%)jCSK`1?}tUW3HW75C05ISp{vWCEeoOxo8CnHaV8RM%d$ zy8gf@&y}aSH2Tofz^i3F&!x@-DgKQ4n2a%E5JcrkPdX?L2;v*=*?rEM6}rdGj>(`a z!)Q(RoXNjibNT}%#q1?bNfHQy^Luu*+dBF?DHiUvtU-i261?>UbC|>RpfFQLSNh`o z{QQvweF1*&vqvAfvsb+BXP>$C-~5g2@IU{-{lgzT%!_@@=R~{2^-Zlu8fX6+05G;L z0%aK(8T371{i!AN*94pi)Z6!AzWy4jUw;ker889bj)9_?%HKFdcJ~R;ya44{d#tK^ z-ePcWccV6BPtIyEfECwepLO&%-5(G^AD_dVEKz;xHOTTDYHx<>vny;!`E0(Jo2L1<9ivi8wavea2e^xnVuh9##^h3cx{S~!&@zZ5K`RUB zUrN{cJk~gHV3rnqHqu?3d1~eIOzv5P=I!DjqgoA90QqMP`shyCptTPYUr|J*ZtD z`qwfQjVRVMbKqxXAWZ^0fCzMn3HmM*;maETU1gg5xX1vm!e|&{N<1tOV#+Zm3-@aR zb7%q(+LMk1t8XfblA~s2>GKF;d_xI zJ>NkJKzmGql%tJicZN2ufw!d-*z={bJY&U58i1z0YKo24`t0=d)M)d_Y5(usT)g{7 zpS$&M|NCn8(|>kx^obwk{Xc#HEtuwwjxun!; zfBeZaIgx>A7IkBcp#)XVEmZriv(5rKLTOD+&@kYn>`nyibl%3V^jOnLtVY}!M!lSWTaV6$q=sk+zxr-jDx-*qv5EtkHNsXtJPm_1)?*20ptMkJ8(i{44T&O)J z=W1J z2wQ--2F}e@)r|_H8|MYL4H@v$2Ko0XWFH1d8K@85LiXOfP`3_1`wLK}>CVY@Y8!hmIJ0j_Te1-Tn1bi$TG5G zxy?N~b3wSlF7544Q4ruV`vDX4v*2gnUD3O~ZBu>E{SVzPKK13}UwqR50PEFyRm_SR zt4!4oXS1k?2r;p^3#gN&%3QA_t!sB{T1s#iCZC!N4`Gy`k$|OB^E&q-cVv zf+-d?<08;XDHT45u^76c2~1nWIE`4hL0UN#MPq0t7l*ycJtYeTa-Cr#UI;Fuf+kF- zCBk+X&RwQn0eO|FoJ7oz`je;u`gS5-ZwLg~srZXb=3{Jx80ZpSmvr%)VvM+Ehv~rN z7(md6Z2WT^^I(k?>qr*QCP0Khz>xW$Yc%OxuMo`G4c?kIjoYOG zy$(A5;|2h{-k)cRTmnVjv=oBGF{QBs^eZr3`G5oGa7d z&tB!Z!M6#VeIX8*4WSPN zdu&c$$VE=tOiM9ufF-Mshv#tL-BS{LdG~A7+*yExXF>P7jp?+LTHwno`+Kq*wdWs) zWiHe{S?+uK4Sj3H*1GT8_vOF}r(Z|-&mXg5OX6@Fbvvo2sOJIs^{NGZTysXnia=0` zl?4=9DRJvZz_f0@9<_a^$kqOj-rWE5AAV)|-D?qu(O@GWtwCAVHLJ`q9{r^Hp>4jq zt6fX#EfCOpF*?7)fO@||{v$J}50v1$3VdUZ>;un0-Pi+EP1U!Lmiw5i=E_?rrk8pZ z0szLDT}p=uhyb$OK$ctRSB_!sodHz|wJ4zW3#hlfS9Znv1Nw~H?I|z4QO)vIc>V z8~^|SO0g5}UO&|fwJ z(-jNCCgS13_cH@7`>_HgRfL2N{}hSuqXf(2vK>M{_U^Tg#@7`BabUxJJ&w3$OQL`_1C52Jp$&Z%B8|zA!IZ=b)A0HvCSv|`8J~#7 z^!k!`|6Tn9QukSEa=A-GkxB}AYeN6VI1jtf^soAQH1hM8Jtxw}ZTjDhM{kl7&lXSZ z>BWXc*lF-w_!0jMy`&IAIC&mQ_PEM(H|5+TjFJm{U2IoI13>50=AU)|I0V7KEIif` zfFHrng%jX-bY80Y?0z`(9_WmU38|>U&|k{FpJitnCr;VQPhhn0 zo^qROA1okG-|vD1HNb4dl?3?alkNbG`qEA3?w8c`J#qos>Aw4UiAXtSfYJ>0+Mg8@ zL=So-2IE8(eWrFNmGvt4gp*~Q7j|ACM zH=%AHfp6~D)cO`vYZd}$i!#Ivp6~6?)u$gLCt?z1gLb~^gpO|{^s}`wAlig zLiYBjpzhuT@9%+UIjG3MnF1Zm!25GxmP7O!{FH|JKn7+7b8J9Dt;WO!0J`#)yq(Ls z6uLk_m~Iw5+hqwN!uGgk`J1YO3M^DiF%%{L7Lz@9Fplq!m%@Z9EY z<8F*GT5C5pg}Jf!w2JUsKo_?^G3gAzJCD90b zwDdNiVfu_j#^eXrs4E_9`lb|Ek!jae?9ba@A8>1)GEoeTCR5FMNE;ZMq9Kwr;2+lz zB|mZw1BYbSq)|diNifCdW_n}aucuo~O+8alhL^o$fl1_~qI$;$VM^mRwJ98P?Wd&H zcKGKW#peD|0z!7x^AFuaLk-tu8vmhVNJT@Y@583yNvsjY;A{ro_$w-w3!ciEH4lp>4w_JH4OJ3a}R^FbWRW5NEm`>h0ZyMxx+P zd?Ml3A0a~%twEmlnn;S6QA^~R>2&?>RH>G(QWq`bH1VNygFKHQf}5V;4v5_2U}mmU zvs@NM$82z$Z3?6fF*$4}xnY|lKyHK~0vTxt2DEj0Q@^)N57$u8(f4EId319mx+7`= z#qE0%({j07mStJu5%iZSa^Cxa`RvEvgY11O%fML%$`sa>#z|RXQT?6W_lfK9!;uy?OsSV z8$gJ_62v^)mWBPQPy~&`e>d?*rGfPZ=G7CJlM9F#n9~*1;R5QZC!n6X1zOB%?S9q( z5KJIdn+8&*fO!sH6cAH^7JzyVpr=bv&X5ZRRUH+_wv8?L0YDsS06<9+Zx0AI24=a0 zIX|!4P_03E4q5C$iX4>@XaPR0%TN8&^X32XreXkSt#zK~`FuW`xBBu1jIs-_ZA!hk zu_pG9S#fI`XpFJZEDZsQl*&}5l(KYmrIc!2Nu7J$0t=n~E7W(j)}mhCsU*e@p(8)X z6U2JWS*O|RHiDSZiaVhft0x4qBBsbgXao0PP=!24MI2>8%nRB zU|L6!GPcM1a3)@{bH+i$VK}V=#nW6~KmV90h*s{y<3p0cA-SpR zV_=O9T`54<=u<1}6E89_UXQfKeN72h%U1nEY)5mJ>hET6E2Wg@-PHja9A0CmO>CJA zPU=E?AGbaN>@#AT?^jh-Z8n>YuBLRuZ@e#NQa^Nb@DuOens3UBS=*4SECVSk^-VEy5EetfwD;1bBM5s1CGoZOm9r;-YYFOK~ zs)AWAYhQxRraqRU0MF;(`5cBBWz*E^^%|ea@Y}z1a`C?#BbT~gA5jJXP*zpNOgvlc zE#TyQiil`!G}>HJ?k48O7$zdsEHpMg&}zjzLy~5RkQVrKZ6^%stWatfthTA{?f?C$ zWoK~a$EAdZda35lMOaP5FlK5&CIdy9yIEO~BVMp}(uJ5ojU<}F)TZR28W!<(Vsc{i zac_znHji!5<7>=@;tFXf|9r;=>-8Gn^%_Cv&(O3zeh<*j&7gY`d4Tduh-mLax}KdJ zIP_Em=7h1ULKA56VFebA33H|=c5Q%DEQS(}T_#sMPu~I-0Hy#_6W0IwDPm76*t(T9wC&6_BA5(yos{$ww1AL*t8Qfi;X=LvjI}S=ov;w_(|Fy-7 z4W!7vlH9w;Oz^J3dnWd--NYEJ39<}$H&6n^O@SCb!^=0%?Ex&_%SDW0V}1+HV4z!% zBT#U!G3?g}?wT5ljvQNa`hc>Ll*394V0G#45~Z=b8vnqTC<4L_MI^iTtUDZ{#PG>? z^+&@rH4YZU9ItfAyy>uUKrW(N5n*rJY zsGx3D$iF26%>;DHK*bKg;ZOUi2CmxIrYr~c_drTPmMfUEGe}j{jXyKg!2x)&02M`j z?unp9pqm${)+_wsLH7Kwuh#!~z13%LDgeMX`iF;yhazYYSeNZ(YK@XH#zpg$Vr6OL zmI%a3DNhGRM8;WYOoIm61=wh#Ys^=KSuwiEi@vtnF`p54%Z%-*0VUo;?Ry*gxZCnj z5y2w`xVwNxuztAgiYe1dkA6MSAhgVl39iD?A}coWZKN1s`$!%%=kI7!J{Rp=h+SUe z>ALEAjc#PBkZgKK8b`NaBgZ6iP#-^VO;g3x^yxB<(AKFh2N*cNUh(b5>P2FhqF_Zt zJ~K3;l>y*rXE*RzffslMj25avAs#wj(-kJfLkSd9-Qlki2RPJ7U8lzVjr>K|kPdRy zbCY)8zxwBLUBAZw>==*~g1oL#D-D3E@yRSDS1EBD)l0;7Ue!+{)@1vprbq&&$=8dV z&-7YO(Y2dmYj@C?yM})5dSnv%c859`ov{0f4-uc10X9-<&!XP_0imR!tiX-1b7}7N zOiCMZBK2J3Sxa^IWp;uj+c5;ygH#?002<#sFTB@W|ENwv+8XV7b&~YcX&ja-6aHA0K)!k4KmabhxVAY)_Qqy zabdL9ctpQ8TYd3?+3dsLUg7&xmVubj$>PPmKJ|DV1Vg~-#RV>wOKdl5kP&2idr$}a z;G={3UYyTBc?Ogk)Ra!d1llW6e4k+UXZDf3Cj&qGEcn(<@X<5i{ilI!4$cojvnN5> zO;COa$__!r6X4lh(CjwA1*o_Unm^h6`vGWn8=NibYsj-&7flRmIR5R;W&~7enEPii zUwREt3^`kY4(3qL-38q^03Yo`7Bj#Sp4|yQTi*fdP3>C)LD#6H0S#!LLme%k?%sep zP*Atm$iI6ZRFsfcE0E5b4U523M=#pupAPrIdwbxUHz4aZ^sBGItX7cq8oXH4Y>fH5 zHf;i1G(b7c4*gV&!{}*CrBSyrCvGIQ#P`t$3IQyBx zJ{2n+l@~@CrI2d!B6EUSaHPONv^jBgV+4PLqG+0d3ofAd?{W9ruvMZCH;D0rUE>3dH9xB8T2Q;J2U<4eRTEq`ccqdJRlg)B^s^2TvLvITQ z_(@&YA#*ND6pCR3GIU?aHQg)Gsnv)d0Hw}Ttmq9~vZw06hrz>XQ`sr6aUCE4E+uVx z{J*X;Wqv(95X4Iq@%6(o^EH3!9oZWr;OW>J;qQ4aOW$8%OwiEMHLL?;i7~_HPGF;t zInb5Ijx!0ohv#gBk;JKU9{F$*nf%Al4~p$uk+cGzjVL|<7EO1MK^aN!_uOM|q@CP& z$fX81F|)l;L+{>Sy&7cz%%dq@3@wur-ZSK7nG3`R27(>gsZ;&9+xq@;8D#CWy@~J( zY5Xl1&^%XJmSqj^pIs)2rI(WfVo9(k5-Wx)6;-TSfV*Ya)@}k;1`Njl(Q*$~%jI(O z2s;0VU*GfG6CeMME&WmAdOB~L{}#V-;_z5yV8tkAGi=vuR9a)XT;jpYFGI8e8$ot- z2tGOlKXJ4E-J$^RuaW(Lp!g9+_U$*pHxEHKo&g`+0;!^&_Co`D4VW#YI)Ru9QmyOh zKTQ37vw=X@%{{65`%*#7rvBe%3(5{^96-$hF@R{GtYD7MAg?_DDxmu3_hG)afx4Xm zWd**q2i{+RX1NQH)!qTzF&Db#za4BMF#G7h4#l91Ye_)HK&HUCs(l3Z_rQlUWbc|G zdtV8@&7fm|)>N|^h`#3R0i@=fzH2c@HxeI^KwrNXAjUB& zn@@-AH`$@~65fW_@sn&59+E0$ppk7SI4N^O=YxjwisXoWWJ)IPV z4HF8nDaLU$5a~7Kq?~H<2Aeu(LyjgkB>v4(3d5+a_I^nKA!DEpJ8X)OQtUE!C^cD* z05YS;z}@L}`Bz}Y%jM=lG1r6%sUB$fFpfWUP%rEfL>;9-IQ*L5x(!8$B` z9RrLa{}`B(Yp|2-gZ{3Jp1EAO{sa@(>jL~Rl19?s?T3H^@lsVhV4OfHkTkW|?#g1A z>>UzWOWmnAH9}zud;;2mL?}s!4jtMm4!*>LlYT}NOW$$-8dwe@5+zFk=n^x`ONm2V z27`o#(23?hZVnw>z4jo)D|%fCKpIFLfwgSU#ENZ$9ePH&`$I?juRA3#y0P&BAoqMn zJh#M%abJ{eN`QTaTjTHMTnj|0Ol6tMn3=cRa=TnEm+}Z2|Ak*qlX~|1iGRXkDJ=ld zVm{)G*_uXBDHO9A@>v0`D+mbZ4^FT;KgaU^F=)F1pPhqmZZP}!Gsr(WgL?l0eD@}( z$ZNVi>$+i=5@I$0<$zuRY5^DxRIBFwD~LX?-(7D2vuzst5@NQH@(d`?fN~9#=YTFD zdIga!WW5AV&R|Z@A+Wrw@kPIHScBg0w{GghtrKj2l9ZKc#=aYKfCeU09TmO9Q!dRyh%y3vdM&3Y{6iZ5Smt-2T})-! z4^5?lafl412Tb|guJ+x1Hl0V9q{pvM3KfvODV zMaJfL*5I`Q78=-`LzWxB7*Jk-7e}=ufpc(iRDbsDsAeFjS>s2bK%`nf0+2Keg@z%3 zP8!gf{BaHxd!X4KFsuJddkd)d-a`Ie&!YO$3t0c!9{?B2#_vEu-MCR}`~xp`C;bds z&`$oX(|r?%iOu;Le&rzh$Dcb{{^pw&0I(py;o;$7t@+ocMFZPKqF!*Vw#YW;?E=zh z`HhVPY|;U&gRFs|jumWx0Iju{`c>?TXsjfF(8h;_jlZie@9P)QYy4ZcaxXGRoLC}v za!=8@r@Q#}wAx`)o1DN=FJn1G_}QbjLDHLjx5&HaBc;y_k!+4cx%G~_VQf&MagiMg zs9g)Z>nd_%I#AaK0M~dNu4NMs=uau>WIPNGP$CX5mJl#SXFyZwr4h>LP{IHWFd)JP zJPOua^L0smmLVXC6FD={D9(hj;x3cB%TDeuGkqS5fZOHRXy6MEAu-_fp3uJ@Aj6oy z!s`RJ2x11Wy|uwk4oBAfewuloevMe7$&L;B*ohIx@qPSQF9+fw1tO0~%VZ$JcF4OR z=C=@)7mTpVVmFzaaL{S)nL{RyFeJ)bpH@^(hos3OR5 z`6mLqMuF`D$;gVLZ8miQO1T%r2y9P&y5rdh)T z?NULRXOMde`VS2B3tOls_ds(E+H8Q$5`+ri8AxTIY_I<9tZu}4b{DMXpnM-x+yKp= z0;_#cegLSV1_p`)5a%FPwS;0e2h9&aSq37mf4{g1DvluK1~~r`NWF^fzZ4J@cs_?Z zJgmW)$RN%#HcUhR51W5GsM>DU__?zDTQ4j(pLVC!;YdY7D>Pr+S6AReZY{vUH>LJHr(IR5R zM!TgNhLE=AItPc8E#Ga`X{v)5y>O!1sKla3acbk22n90y-*#F(mNX^rY3`_&vh8QE6+OcPM%p9wKe1g=Z zer)PKX!aO3_#+kcPEn635atTg?OlO}SiI?FeG7(wuIn(&yXxwR3V(#2IyZ_vSrZmW2mV68twC^2Z^z8x`)5P_7+R3Axn}3R|ze5rt_p@*$>NFY& z7u*0*)>(KiBZ)Sa^DWT`z(5w|#K!gHhu$C~IHnX37y=^!Lo!_Z-LBXUX>7eDk%5OR z4@Dww)@2lU4gSFT)sv}s9t2%o=U+F1Z|ui3?SwHaWe?RR9iHpbhs2x@k(cuznZaosRBIG}er;IUnVAyIn0;%jyx0{fm9Q z>-NF7{)w&pIaUg+lt<1GhaDwOR=rDdBF8_8l|oh&$o3e;I|TU?1-7p&v3=*0WYD)P2t=&_#~wa~0%k0-6InuK=xqtpd#t!Lxk;6)4*W z5!Zl)*#IQ9bO8d$ra5i_saR|=y#@tVO50Pp9l%@s%Z1Zo#m;6+l4XW){{=uAn?uFCU@4vYj09xzqX0u^t zo-gJLZrxMsNxZa^c*pFa`57A%Yny9s2||`W)EERd>zXmfpaB)!&7#tkhJ)m~(S8Dd z=IlnHM5q3aAy?ENpf_#oBgyRVNbw3GV&E5d&!(iaJAyprIE#VW=CXS&3JOk;=K$PB zYLZ7Uqr^0{w*lJKED7+^S#0na*eB^7^miLOU;QpRckSEQw!kD0N z(ljvby6OmYQfyQewrd*S$DGpP9?qL8I{yNrWe2WwNmAY;+#T?T8?{(a}SG@M_ zbm1~x$rCm>e|9IEkjy7>P0f!X$`jGcD05LyX<~ZL@ECD<@*F z=fC7P?89qIJpIX=zrYQnqCiUFz9&=odBQc315iU^QiCuF%46wMW9rwO>tJ8UeTy-sX6B-0e^_a*jR~w1!s=SE9bDOSD3Hy1z20m#8$1Tu zfBW^J=WhJKN4NZ=te8k~ztOZ;p1hPmuaR!u=k51%jr^Gkvu}M8G|vELl&_s*`LzdF zz4#JVFTRNUh`_w5Dg8VH^s=6mXZyABUw#u@+yoVOLB$<#aa1P*%x*Q$nSwca0CRE* zS#2QqHmH72qx>ZU{b_=nGMH2s2^e{zU8#O^pM#-5=LGWwp!&lKRB2GL0_7UGcmUER zz^l6PM+xE#QZ^n1<$Vwtkg7nm2D1Ut8iX~Zx?ckZQ~=o_aIu1%z5+RY3D}&0W^>T~ z0qEceIQ=@Rf5D(C^B)*NJ0>+!gE0V=Kx)4_Pz1&5Hf=OCv;5N|{^c*cdj95?0JvX^ zy}i9$)s7DW0t3*E2Y_3BdZ=n`9LjJ^PPpmPbt4ym8}&jUDv)Y(f)+2a z_XvTg9l+MB-m4N>w|3rxf@2cL!-u?m_~G4qNNC!_y__fQ0TT5*2=8+aSb&ne_Y+Zu zgU`J<8hU9X?$GM}-4dXai^iU{(AS7ZrJ6n%??MuA7^9x|lnbtS4A4|P=^Jg6^NfWI z3|2}p)&J)X#$0JDw~`HZ>NJpN8r_Ve+vmap04}4V1xL{OJ{b4Cs7d{9CAA=3>1wrH zF0Dt{qc%m{oUI%Fy#@r{~f$k7NKeGoZVI>>Y>TMGm!Bzz{*N2(n_7 z_qW)VTa@cFa8BT?mI4qF%<7Af>J+F>KvFe&e_eOHoI^?ttV@`amw?j~n0p%4ZyJ>U z43ID6z)Ar^5F(hSr*j*9TSz)_XYEboJ-I@lwSs(=q5n|BoGyXc5`;6zW(8Sa)P4i9 z2B8G72C)J02EewC5j3m%*rfvT9%%kHKyM+-2awmk0+h>Ic5!e7+CKypGmvZ`$FHIK zR1Vpw;Oy4y2P3AQ{!7PVa4kzi*|OFZmYa?KoA*xt(+At~)wckE=E2_E-`@uaD$6oU zvJfLiH->!mG#b>#_%#UttXLUq3;u4x%#)>})rZqb? z6_GBkFQKvC9!NGyVYartf4JBDi&tERpMxe|uNbJ7`V8*1;~l`7D0q=*PKJPlUF0r1 zg9MkHre4*5;PrYYALcP$^_ryoTdo4Yq<&5YC&&Fn9C0LUF`70aDJQ*HzXaHv+CU%X zJrG9Zg%O8i5}(wu_uTzsEIIc*nqk6aV@_SBSJ+*~n%9u^mR_elGGPbj46p`T`KDv2 zoJt59`aDi>G`ZKujf?CWW#v|NArH_+HB7wp+gth~sn6FSuBIn0bcUt=% zh~lymJL|3X%cb$V?{6D%YtGl1XrpBiw9SxZ=qgrlWfOMj#@v_))Bjdr}{MEFPm1t36Mgh*|8kNOW547p>FzwMxz z$pA9TK?fPKTl)ZK5Fu<|yukY9Q*6#JpcVzx{HXQ^Fe|_;f$9`6OOQSTHuqreeHF62 z4|(u4=-)d=`CAIrKNFZQ6KJE7Fsd|vP}>N`(m>lK!xFf;r4GZP39HXtn^LK(Ya3 z3pqK4{!{_1;CarAjrWs|wm_~IKmgoWe}Hnk#Tusk1*L!P)r-wn-U0xcW;@HWEYI^? zDOT-b&^XbH5d#t77D0p%6RRxC*qVsA&a8Ifau!-+v@tEkzV364)!hfWe|S##%|aU( zxkm5gaS@uX>&8Dev*>vd41fm|Q18d+dlGSkM=(+Ko%*Fm zQD+zaYa49xCJAnqy2K`-5k>^26o5Mv;ndT;U)I3s8m4JO4(_qZ$cP5LH;r?CerRIl z-Alc5Ou!hG-#)7mm*b%Z+eEUOW0}w~qe2QbkBKI|Hya8WHdAE^!STdcAu=%CmxSJT z3ea%XCiT+V_rL>WS72w#)Ox7dodQZc%CUh{&&}w+O=UCf$`p!3yTux>6eBHkf$zO; zFB2X@LqL4EFF62n7$bV=b$QBt+rBrqd)-*$9|HxW4R;_3@S+kUH3aRz&gub@k;Ib0 zL;+6=PraJSl~vXKU=s-!81}hC9C$UC?|b8#_{H|>utD!T@rN~Fm|o*nB3+tPm{1d6 zi~7L0D?Rn1siQHLzPFPPq;LmVxaYS4HDVEizSXq*JN0vATo!Hs6d(rZHQTwZ*~xvL z?FY5PId4E^0RV#aYEB=x8@)bm`b2^)48%i_QVbFJcnpNpKMS)SYq|1mr-5Z2T&n9 zybE4DQ%C;kEzGN513gTBZjb$MdlQ<%gizv!Lt=$Z83> z_ch4+6xf`D=5x^AAu!(qR9>S60zkGPy{yl))~G(skQ38_Fs6z5Yta|4`6oDha)gHH z+vO4$jOE{#@^8O(v3cPw0KmDW=d;<28z*?5-eVU%Cet+Y?BtYMDiW-#zhwou`qG+Iw{405OTJ*}6gori>z4Cx`v0b3%PODp}RsiiYVniVI% zHmd*h40ilD!lA}-INP{>H4_vs5^08dg-?&E5ldrmvU?Nm@nh8g%cTpv{(VHKQ4c`@ zPTYHA&!2mKIg&iFOExqO7-xnjk4BgRz3&IwQs4C$lmu^r$pzA^$4Q(ajW~6ve-C#PZtP%E8A=6c=-)jis1bWiF$ty}qxjO($UV}ld&QgFBe)M; z001_&uc^09!z_@-n7j2ox1DRmBg@KTjfik3?(ZnmwoZ4}3Pau8xX3A3uMPGK$JkeKZ80dKmr&e&<3>~S{;T4HQxj8 z7vTLFc$PtLE9iS?&?mH zd^nuSscqyfL!r4%m>Ar|8Afm==eL_1-To{x$O*&z0ib`sz9rN%2cVnJg67WwNKksm!S?^%LRR$+Xe=nx2RU1IgDU~B z$L~f2o{%~F2dMtHduML}0PUBqsw$rqvs!;d1S6eGD1mg-*t>bD5>UmZZTO7=fsBZV z(FP9fs9pG)f5$-ckI*S~hiP)MIBU^f4yu-T*=#o{W@giTc4Lg8#$>P0KIkH3JX(HY z)9f9qw|@|l^tu3)K%^nLwH*GPR*dBkAsgJgEViHq}qXu)SW* zf2znGntqNp72$*^)kI&SFdo;+Q-m4N2c*IYM&DRcqEuL~2uV=mDKT-Q$e&5)F~U@c z0XTtm!{9oztLDGf1&crVO6YjUrh~D9J|+`FFrmGShQIe-sq^>-GU$6fk73fe81V<_ zu>eNE!d*Za38ZK7Jodi4D-Eo5>#|G))Q0^t=t>|}Z@Ucaawe_a-m}!10h8mnPLcRN z+R@8J0{8#ku_WU55PQ5HZy<*^YICrgrQ;yB`VY4GX;Z zX6irycfW0iIE@#U1!5Y{ffkf7V%+!Q)|;Sa0O+c!R?FoQkKvaP@MFd7-&s`VFw3*v z1(tT=>`(T{X<^wl(gVN;3iOO1+sgrF7%g@4Z?zUx2~s(@n1c!ho)_S~0;be}XqX2T zwx9nZsu%8I`vpM$@EOS0jzDKMzn-$J`=b;nQ|;fuRR1?%D8Nr9>9qgoMTFH2Ix~=E zK%N0g)qjc{$Z|k&?ODJIC}+UwU66hcuquG_mmv>62f6ql$Tx^?_$@sUr`l}rikMga*R%8gezn!7ZvgD{DtJhJLq%r-I7L{zI14Lw6&5>_XX0*}97~?jl{fySm zebrku6V(7B4Jt(o+-@Sy?gpA@u>C0mQ@DZ08oG@){;`2Zln?YMl|);H4PptGzJ>6o-1`Q z`R5%R;Kelr9G&J9M11Z(jTmK7pnvq6?s#FJk_N<@Rhg)bo>b^ZqO_t30L}zuOcJpB zeM0Hu-o*rMf{)1L2Gx1rSPplps7Hd;B2$~)#|Qw38?cT`d{W@=6gkWo^B^?3jDbx< z*NP$_l;;rNq|%Hv{MTjbx9c@Y-H-jBOGg`~mua zo=BuW*+v^ge(YfDhk)KS=}Pcmm}N7$Y%*4l?Lr-spc|34Yy-FHcfZQ*c6)w)evZdX z``SJwg?*K0)@VMk_iGwfYn}&g8h>dt^})SY5VCJ7z_U8L-XN>v^qj$f zE;ry}uXg??1{8x23aG;za#3RWPfoD<_4}wk^8nQ=r=Z)nkv;n~)ZJU)#R9lkwp00f z`p49HYHozL_7=k1>&ufLyVAXOh5al>)o8ie43 zeem7e$UgXf(BT29&pwaxS3Zx;FF%j!Gp8uN{|V6DXF&4i`(_!3u)()+9?EGR@Bl0KF}7Jjd$qo?iTq+tOSb$a*XR001cRJXcwk zN#oX!#^IcpSsE}P8W9uF?4@l8I~UU0U%TC+()jY8KG@*tJ`)U-T_=`1Ig$@t(_Q>DrWlTf?>nWbysqaoMH~J` zJi}KxhAGm4v4npmTv)h_OJ&6(`D|Gm}97q^^qg^JKhCcOvyy|l_4g41&EYUa7Yl>h$pVS^UbK9zIShnw+6O4a<6F?xbwA+qD}*T zDISk1YQVh9HAI9_+75(#*ELE>Cx_N!Zth`;#3RRRxIRlpM!-6Wyl=Rcck$AcTx(k; zj+c<-bpFHyF``(p=Rx5Or^z#U?Bf265C}>sC62^F8d*S_c+jp1^>sNvKR=k^KUPU}HdN(89(C&UB73~C7gJxidBnx?#{ucgth=_HIP zp^ANgRSPgcG|alh_IK7WXBtKXt9$og&d#891wK4LcJ~hGaKC;bEg&YaQjLKhw}}GO zOztg1fSaZsnf+egFbPyM^=}${Q2l${HT-1F0gD{!ZO=fx{aHW+`pYk%`n}&r`TSQv zN

      X=r7w$|Bv?5&#g(SIdh^iD*H|(!583(=X7q04 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

      t9IZhBI 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%0DiSmiC7bopq?q`f4N*1J3u*xWzCXj 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

      vW|Xkt$J41eM|;cMU?}yFI`PVDc|eIU$?rc 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

      )RKV;9)pWA1?%4pYFLxH}@U!AXLz53W52II-Aw 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 literal 0 HcmV?d00001 diff --git a/spine-ts/spine-phaser-v4/example/assets/snowglobe-pma_2.png b/spine-ts/spine-phaser-v4/example/assets/snowglobe-pma_2.png new file mode 100644 index 0000000000000000000000000000000000000000..2a86f7d0c679a036c4d13935df6c7f36ab29153d GIT binary patch literal 803281 zcmZ6y1yEdD6E%7U_YepUK>|TSaJLx<4grEou;A_xbOwSZSP1SAT!XtOcyK4UyF1MM zy!ZZ_d%st8s?MpJI(2sM?p|wk_nt5nB^g{Sax4Gypg3<=il~}ms~R5ts=?Y9bN0|{ zI+T>eU3HmGChE6z;d|5rh~uOD-z(Ze6h|2pK!fpruT0Q!xOhyB+?O+Wqn*QYc$|Kh zwjze{SNy7;9Wy3i22eqV`Jd0dHF*93z-QcXRE~4|`!0l9y<29*Rwg_oXn~6d zpCj}2J<`@KUieY3={?!MxLC(pHd#i&mQb#%Ti#aGPohbQJ z#DBPLou6x2_#!xIbHRIeQ6Un8KULiWV>{k8`%nYTWB@#X!1+tZjc2fNxN~=rs{H)& zA3nh=oUUz)*fK(iW>UZa8{h>#auF@}eDa|J9I=5^bl^Ln^7a*I;ukW^570&j7_I+z zoe87X7iI&y7b#OuaGD*eRXyc?Rch)5kMd9Mh)7~`KA&qt5H?wuw?1so%oy5dBsU(M zoSY2rr=>j%FH}__D(XhB4_))mj@9$e+TrGBA>6Hq0_q+@iT+~@LxZ>(Lu3Go3^-)R zMr!BDk(vDDd219KU`!6dK&3&!pzVjL)DdE;#H$*lem>>|KAu~}t`F;=1K~M!UspdV zb^%=+=bCM?UR{O@hG?+08oYm^1s??$wid!NT|Rr+IO*$KS5yi28}>GM))V1dIz@#} z9ziWy2}Mwg3h`ZTr7*sP`*mMYs|nwUQ%0dXi7-52Kiqg4-<1F?YXQqoKt@Elu}P^m z{-uF@TR1o`I6<+;!?7RDk(gEm@~p_f~VABBvxn4mVBp)S{NhWWg_R)I--@byTmZ-&U@ihdAE-MyeCXWW?) z0DNe0r(9wawUG2MZQQbU@W2dV+xdmt!#IHKFR(1;JGw@f-*~`QPL>ZC9KaGNxW}}Z z<$fJY1RxGBLzF>YbS-=E8I7@eUv<&&*%tv0H;Uq0i6XiLl`0}_@ ztfi9%HqHjKe4Ho0nmi7?hKF``$|LG@J<=pc4cFy?>+iNb`eD$X%JUk6aeZVOqFbGt zw%A)ghJKA=fFH+>lnEK){tBcB)B}JY05nCKQ#D+BP;MXXjFw{Ppa$3r(x3!-m7d3x zzSbjAj)2kNM7jUZ2FXPI(q0<#dI%;G6?M>7E!KA+lRjEAF@gF{M^YWlaSPv3E1O6z zoj@425kx@AyHlMobB6i|*Zh|Hru2hz5|6pFv@3cH6~mGV5tT`xh=JyHo0b*a(EGF4 zz2IK&Tf(kh54aTzyvqHPM6S5KyeX6^aD)guRW)=~yLw_z5R8_&4Ga_I}vuAW@!&4)^%){^tK`m^#exK&mU^%yab zyjbqBq_&bKlGF4igW=r6$8e#F6!1d<^ziB;S0l`ZKgk!yuH)o1!Eg46+2~pz@gJFT zvFHOiA}=aXiyOj)M1{7PbmTeeP0z3)j9?TIAciQ z(6KlkeFGfPm_NG@)mUm;C#l9HOb)2uzlpETz&c#zf$a<3%&*@})KH^H&rKuBvCo&c z9s@?(S-(JwMQ#TgF9^u(iC3H(9voY&e4;B9ki`LL&wZmcQF6fGNuj^_g}>g53w$~A z|B}G=uwV2D=M8xcA1fDHJ*FNL9R#gvMFf&BG3MYX`J3os0@PDMSgAHEWvUk%w{66? zD5ocW@~-0&M3C0$^kV1*l>Q9sln)dWeBu@W!=McYmid50kqMzniV5=IyW3Oiz>;S0 z(t%b0nCQ|frK7pV?dZjhofR?c_Cn=9IUoIk8}OpESPN2!_wlNK-K*E9;I9a1Z*6Sr}=SkAEXzYhQb09)9mZ0??-Fx%9nV#&m2xCQo#rzpgs^^ zBKEk>^*96T)Wmb_or8K_Lm=N%B$Z|8q3)mBo zTY|2Dk`jl1`qdJPqHz%3FZ3aYVMd1`B#I$(bdCl8A?4mITtKO?&iLc?cbmIA=qzve zsCMX7tMuBXaGe9x;spj@Mt0A4$zwgxvaNpJaKqs=BhS;x=$CgEW>>Zb_(nzWDlbHt zO2#+L=w`*sEAEKkMl)f+$1KZj``aLCtUf>4iWVzoq6r6m1BwnWj0puKVN7YHNkW5l z131MX{}}mi^o*dvEJzjDb!+#J;wSg`$-_O3Dfy}YG+mio9nGHU`B5H$gQ8@@mg|7_ z-I6QA{D(IlTZUJN`~a`4cQ83L2w#jttL*UeH>Z$R>8irRIV=ECJt8#0ZcQcMOVLQ= z|C^KQGx&?G3>0(%hAJ9e-a6YGwBP@CH#*TEzbdE7_Ku*_mNmE7vH0Ad*ESE6k{te2 zd0&NmU>45r;9S4}Y+{YvZM~J+e4oP;sC+KHX|ZWia5xMdErQ!AJIZiin%HAwckFD{ zco%Q@c-#AM!alr`$VxRFY)ZEgi*7y#b7M26^uD*`S&IUR1*8+cm zjV6Q_Al6`+F5BJne)WAqgVrm8W~O$h-5;E?>v{-|h};p>xlSiQu)c1XPT)BJGoL32 zk#Z=kvd6Ldf}p;;GF+VLb{pZ0&UbFdJgp+G~2E^vl_Ws0;g zVV(ysRIH^D&^Zk29(R4soS%OAK^ZRPvTz|p&ja5T=mDyD|CLZX6c6Y22g$z0SB9#tH)Q|GaDVgfq90C6rzE~cL*qUwRNU+3d zE7o?3H}&XCalTXK2j$HzriQm+h}xs#6m!t>1MuU+h zaUKXdd)P*da4IQ&g4Kjj{;%!KqyVsD+T?3kzGdesK+QwCmvrd*Jk_!e>PP-Op-8u0 zb%UIxqofmVsfqdn;vlO0?MBWZW~mgZ*FlyMsGhS+Oiz2OOy)xbz@OoX($X5rTiE^JEA?J=Uq+79F zD7v`*KU~4`WSK{p4SW#PCS9}iYP961`^##%xxtK!Kf@W%fM4-2iSsssZ4)&$o!JL> zpq>bDr`{3bdi>z>p8h?}NPrlDgrUV6u+~`yeFA} zFevxB*Klr&nftAY-JPFTeT@e2-W}C}mXD%-toscKZKeQ8PgMp{dKJS40hMw+TTEHO zx&NT8CBT}g89&g|JF7W=A;_VUimMe8{DZ)Qi&e#D;t0m!LfB*?_8yHKk z6jUpLxnH|9+O#jhwr$7s^+65z$Ozo;aURxFSL5YAaE}`D0F{)0=do^N&wnzB2OyRP z0{bxvw5N6T4y~@SeC}fwEO74BssThC}3cw|=BA zLFrU~E6VjmTwo}C#cePBu4?gir2Oga`AisFo3~jV3{WXp8e^`J#Lw7wx^4@nzb>qogl*@A zxsQcYRt1EPm-gQi6swaR>ecRceyy=E)TGckrL0?Qi&Vu5PkB%c?Pbx3e=6Uw5l1o` zcgvDLRX5}+|DtBpOzSDlMBzmVudN3xNpq4-Bf(P?d21$j*SYw;9_NqK68`X1&kpb1 zFPhCc4ztO7xA7%@I&L5Pu)PvWJ$1~C)>FT_Q8<)EmDLw`JpSyJP}VxMNA~_m-Fv#J zrj;9anu2HHG*s~4!(oYkEQRA&X^}RNqKh&wYZJ$?HfD}*GyZBk%R^i$U`r5ZROzx7re<-?jLpYPqADC?`FL6!U<_6(7GuzC(z_0a#X}WC}94h&wKm$ zfcJH$d5gEpTejo+L!{hfYdN}Q%o}L&#yd9i)#3qx+8CL!l`&dPgO&S}5#8r?xv|6j z2Cf6eton^7tA?J3#rE)puNPbIO$6oT~cgJMR(B+O! z#{XV}NM)BojQw=}n{j^4Q4W(|7deOZ1Bu}GS4)Si26xXr`Wmkq6s8f-!&TlRC+Xpj zA-v7|Zsx-yaf7cjXmi8Oo+Nwzx2ZL5;w@j~-=FeA z@ArM9pz!eKO>R1zHvhdwX9l5sm_7^P_(?mPMmvjEd*MWT*;EIMM!T!1Q7ZCRg3wB% zY<#9IfKF2y2frJ}g%-SlZ?7}xD$g)}ftKc6s)h8?ys%kPgVu52Fe_Z=UA`#WYJm%q zDR?V)4$WgWiTYAA?aawybk~r}8actSyfRpK2!BI5$nm=*ZdEs{MWXlQg|zQ6m-ok; zz0y`G_WVJno`Y^pG8x?axxctV2}N$-J|Mg4ac;Q$3^IqLho5 zcK}=QYR6SbdIDiW4SfL#} z99HNQ8VAG?1U@s$>x?DHb{LRM-HT=0cGZ1yEABmBwOaC2g57HkaeaM?&E}I-_EDv$ zNb!l=e)zVH8OpYe22NH0fQuH(?F+{lM>2O@emT7f@W0hiixx2uMc>jbDb|M`#u9WW zTe6&@Vz{NjONJ{$FCI7ym0oevOrGpkSVzpIF2AP$x#ue33=|b$f{gP;QB}zYITQ?9 z5G6zV6U0wtl-WsOT+=$$w`r4A>4<6RQiQ5R(wj`0+rH6MXNf}Ni$u{kS`@jr4Ws+( zqFm=rt0;dVW}Fvb9T2n_?d@;l#Tj@fe3#1knlJ7;N)ktW`%@??27_OiJrPhA$gq}V zgiKp`5AK|Zh3zDTL7&p4i!CVY+L@k*lPugWDm!)Y#1+KT@d`7^@w}FcG&EF~g3Xl< z`)QHLJ3kcrZK0v}GfRrcrkDK`=&i2A@OgbpC=LcwC=-{Fs7%bI;_oyvVQ5fgvY^p$ zBI8WIaL+ZL3MMJf3Fckq&%64BvN?4-)nhy&F!dg=7W^LPM&eUceLv{I-BnZ!K{3Pn zts^RUyTuU5wHvRM($d9FTsqsc>TaU2LjP}BDPskUtaNN3jC6*)`Yl^61_Z~m#Xi&d zQWX=pVtQ>Y8KG(CK`@yS4OD9l4n`sdcGA&*tR&kw=ro=LBy3Y% zD@Nz9w!Yf0npZV}B&_8(-G}GoLFn|q-A&j@reMz6ixzB6Z(V=fp8tu_JDBvdKJ>ym z?rA&Dx48}Zh0=@i2qf@%O4Z%l9tz915u&WWM&stW^Q()Tr=$>;7q7iIb7PB5#)ze-Ad?2y$jg(}>Q;e8(v;_d%Ao^CvFKvVX`=hrEPyn`DmA zMQftce-JLkkqxTr2gzEm=kkF_zoQ?eW{@({=u`imw$Z{Tn#w~DPbu*FC>bzkuUdGAXfG@O6#LY#^e?$awgUwk=zd+5 zf2ykd>~iNn`DRF&wWv2k;G^oscLM{H`UD>37Sv%8sHv4RYQulZv7U)X~{%0nV-tbEKzG8z}OGShQ zrHo1b0OpI>N?i7)Lro1#l~l`o_Z^K;YG!))@Vf?6`ygQbii8VkETrHpHC!*&v$Z9( zX&g<7yipk9*zZ}&&D~PY%X=wHd98+>O0-!jv}Gb~xBMX{PQ;R%mMkLiah4;x6ZX*% zV`JhZ{_d_8iYfW0qnz)b%#kRdV7y^-XSp2f zDO!N?a;YrjJrV zclS*hAcloO9JgThJ*(8Ho47Ps@Cg9II?D=0S zYBySbs1_~p$T)3P?G@s|2l}TkOaYn&p(~yPQ9?iY^Wq-*++`t5wkOE3jT$g>;{fDH zeXqsA{h!l0&q~$c;d0C*b^=>tiyH&OF*_#%)g^7BvxC2%#(f1E3Y1?mtur8W@QqHa zu;J1kA0WE#qRDZ01t;sSw#e3UNsMnEckVwseoT=3~$2`=KtW#iu2k2Ej9gn%e8Tu_1zfqQvmUi8ULYBJASjxju z@6+d!;laD!hd@bI!?pZfO}mfcHJzR!0-h>+{}TNufDj3tjEzTaufFXl>uNVK=K-mc}d5b#Kux|ayw$unPz=Y;WAhgAg)nY;bVq74|WaidF12sAb zge7Vtc7U*8B?+~X5aGnNiL=sHu%P(1galI)>JzoBowH&0KAEpKD>C;@b1%n%X=9#g zON?M5Qo%NKU3lPsczj}hvASNo_V=lTaN$E3ciet`B;C1-C376Z_reNvGdg>L z5c4*=(x;0&mB+RAe$~7|Atph_&9pZ6Odcn@!5B)Qr0NIClKzwE#gUv=Pw`)0@Bxcf zq?<*8QPFaSO&#CF{GRr>1d1dj5CK+O9(1SQb^vSoOuPWKTtuL|%vx@M_QFeXf&u3t z9vqwM(Zt)!LR+Nk-`x{q5nFA|6Z7DlyY=s+0k!2Gh&VEuY;D70eJ{7S1r*9m@+TL{hUZox@Q&{EuQQ*Hj$!OUPd(kB-eIEUQ7Kk z0l-QQzF*S{$ra#BkoDL>5tsAFdlCN#6lVz1Tlp_ojN;>z^xO*oKkShy|%bhY%C@(qM-VNG}(@bE!Q@vm>91neCo{0;$Q| z3%SqUd3*7ZYrAc-*I!_Ll|K*R3{2zL@l@spOj%YBVz3n>u8_C$5Eh-~`wigl9JZ?Zmu+m19WzDJewJ9alFfY1n3%W9*Z>61)i!l-41Nvf11-ls zbE-nW6f;lo9xB3%DskJ}IBXbuaYyh;G6@JagQ+={ti!UL)l%Hsl zN)i+?dS9Y%%lR{opp5h|phy}6em3qOrr&r#(M;_J@x4F(q6l|>cy9(2n5d(qDY3yb z!WwY6|qR>j)mC#mHcr8@uw` zJ*wMjh>`$E!h=F~7ce<2zd!y*By+?rc-nhu!cAeT;DR@0dDd*HXUEQxHgoahZ)NLey{^>; z?&xpzKy~LwOXNx7gYx zLGil(j*w6T`1HG}D_!pLRI}-4Bw9~m$W^n1-`mf1TV8xb@WNi@vT-?(6&_^znLw+v zUIGH$@56fzVo}d654glMbHCj+jv0x5&Z#WP#79xRp^_~^$Uw9 z+ZnJ>y=x+wf5c0Y1yC?$x8$&Bua~PuAR*rvsF%m3mT;Q?uvOTuWd};F^4ZsmM~#lE zO=0{Hhhc721AB}i$i%~`#5OBPcHoyz2QWg2#8jnVa3KF^*)IBljPkEgX|V6}UlLe8VKJRlV-FxkX4S zBt>Ir--rRb&L3q-bQwx|5dHv_4c@>syig96qnfsxp`&{T=2Z^woJnq9Q8(->Sd}84|aCq@@*k&?1mf=v9~DPMt$A zH8x*4!vFg4VmK(q!TFf2mhC}{M1L>i5P#g%L%62u+d;7U@(UT@z+CJcS1kQbvL%|6xS8GpVdXS4y?3o7Y}&JYtITjjR3HLVGT9rp&oBXwRSzhepyymY#oOS1 zUBDTcZqGBCaTo|q8GqvD4nE<(MWOwNXKBzWfX_^L&#zKkYn4y+}B(aX>KZM-NV=`wR9WnMjRw&MSSi^}j;;}IBR{HgAhu{42 z!2A9yHBNfP=8b!<&@=R>iAr*HD5UYTrIEdJ09JtTG<^3@ZYj{G1a-b|oCZf3(ReZ$ z5hF2;-MLBmt9-v(cY3-|bPu+yt6_d2Rc$x0u!N|dV2@@?AY*WG+<9B3l}GQ3P{%MT z>3r_*N)`Fd5%`CA{PcLLF>wWM2LSjSsb@=WfT7+ije^x*(p{H0== zeQ=!uYSw7fky6%S1RL{}vh+5m^j3KHr)nvhPpa15xpNz;pOuPv@5a@fgkWIdD(F!j zI>N;)*mruWZcEe{|Je1o2}MQNzvpQ;`~g5 z6>#Y7k*Wq{2qBa|4@Jr#c&rr{LJS@L=_*F&a{$%RQQ!5;)O@*Vf2ss1#jOpi>39)~ zz8#oy>+@`MDVMqzG080cvo0blav^44ttM2_n6seir5pW?FMZ`>#^s1Oh{!JhnnXTbtzihu~qL_Z2YK z46V|5fPz z;YHi{oF@YM@K{g2Gi=`X=}s(kAHCQX>lkAJbk5ZYTmV_PH$kWDxjmHsEtnS#7BDu= zVhGt>30FUw_#&Xh1yq&u7W7~?3)0E(iGPualB?7{&3&Z$T8`P}U<@_3(yNO1p+#*J zCEAJd!1p{$*!;=9XQjo?sR9Jnqo|NVF4RFCQ-tBB?L>bel`}0byrl*j z1!8Zn=&hqH-#|hhesMA1MaBAOE)vE^!9P{INq`;fV>oDvUPGRX;j4)96_cu%hhv>` zx3DBe=D)<2yz)IbS`zj)8h(NO{KK;$l>ssadku{Ud=0YfMX<)?(~!b%6)Fn7C!)W( z5@*g1E^B4PFlkKgt^ch~vOt+Xc^Ilc%r6qnviYzPV}FRu%XVq4ANPF--)!o~{?hj8 z42U^#s`*_>-9*lhw*n`qXj=1Hv_j>R0bnFOd8XnFo&oJ*OR&yegmZ&1 zlp|>g7jIdS%_QqIx0%CYA(R;S?^J1Ng619=cY=j>BJt?;EnfDi$Ob|`aOJ3hHtUe0 zOT1v94K$Um5j$ijeEK62{`McX%kjuf)XjUvQGSTxj93ZE-9P>Hymx`KZPywx(O6sN zm29-M#P6P?B|_1ZU{7hj8)aAQlzCvZ)!?>G{pAK33xMgQcHZTc!&e}l;5&BM^&lw? z>L+rx zg6P_~oA&&@;omvM#8xiO+4w2TWvrz#s=<=R1xo~OY|Q!X^(+_4sNlCe&0=7Jv1XK{ zgy~{V|L6q7mwU0oo)fu+m(jskmL26dNY>h6*IRjf1``b$ud!|!Fh-jY;x6vP%3@a` zS&3;gM%l~&ZWA8FEe*h z|7cBT95h($hkl-tGhF+!Panb%0of5b{%)!vBW6(vh1zdB;hzICSd9SFLWI-ehv*23 z!RN)u$ZH=L_awN!F8&x|gfwgBJM||6MInC9J@HNMqQ_?lK!U}+usU4jgOp$5qMUo_M{!8Lzdws77;DqYFli7+I13T;o5683E0v@#eKhXFd~e60A5H4Qb`C-ROJkXJX!c z+K(K_)x**-n2|OL@(OpMD##CNJ(ZQd?A4?H* zec>zngyLAVUrlM(n2JvY`dhpwuc(!%>c5}#DkDO|1Dx)K{-&u2E;7yM?^NmEyMVji zW;o*gPX>RV2HH%N=D7xb#TV>a7U3TAsGD#w6|p7LQ+YwhZjEiw&^Ot1-)$Gu$M^-Qe zf4kVtH`0*(i>zGT5?dF@_wJpOfF^O(LO$4lo-sONtN$ zrrjxhaTH))%M@&~F-IKAcz|7p>$>Y4W=AQP?jSRG34sUgrxdTtB#;~CDiY|35G=nk zK>PxUk(luodpp=gw*jZ?eiv1IIIP$u&SZ(k*4zx2!uUKX_#xtBFWW7fk1Fn<$3Ll- z?$3wN5AUrftlmYLo8YQWT;T*xya3+2&}qXe>h3Y>`-EJZ*+KA&~b8AOKG3V3EcQXfUkIaguD* zw#K(%p0eIO8d5;CZ6ib#lqnDYqJ}iF#!W~|+?g4u3B!Md@gNfvs$85Y@Kolt8&wEA z94uU8@6IxNDnBCS96OPbGaq{`P6jgO`hKxU0Fj?1=pv7h9Z8bHe1c zHGH0!z1bG;3pWcdtb1uS_m@3Vf2@?0Y@zo(dWW}%B+uc)^J3L|aAELLve5BI%Im70 z3&?5#nbKj?!XtYr&{-bQh9@xb?+GPwSfSILp+IkgWq#KSo;g}fuVvVa`3>LQx9ExG zhXel^vZq3jX(HG3BlTP3xy544o4{^FFg{$#u_&?f4=~j!J7gF=pc3X4{}!uv-Dgf7 z9~1PBQX;Vy?M$qjU&uF zmIV$r)cPA5-;4mJCoq`xiz@^9m?YTaIbQ-onxQVl=Tcx+w%xW)?Ag=A!9Z7A2p73h zE;9XBB;ETxsnC*ru&)^Hnd=RG3e1uaqJ>VMyRrMVESl>jWRS*osXXskRBsW&n?39> zw4XfNw&#zWLVW{mqK2147o8Ak8S}SQ)b|&g8GcvnwSO)alqCb?HFQ6Gev9W{ zv!D>)z+;=w|DeCKGcHhr-B!9jxhRYIno5TP5s$qq5n6T!h;`Vu#}NEO(fp-U~vCDx4D=q5V@07=uo= z7OQsmla7!uSG~g`03ZHE8%uyPt1R~IP`FwA&ihQ~KYdR%L6*it+E*1Qs@$-=rc2c* zBz0fJ8~|kFg3NFVdT!oj${-cp!%PRM*M;FX^q^T>WOX8Rf9mZ)zzmHE*&qLd^g99K zFP0gh-+d)MTlw7mtvm2}06c$!k#sfRPu2@s66w#4i6B#G(J7cooYCim+wEX!(gNm_ zen1876U$wcq_aN{L}d%}5zPBBRECR-K$%9e1+_4xrqUqjvmlyPZ8H3qv=gxsl^mzk zpVut;TOWF!V6}&)%fRCPJrp*Kg$xP(m|@nK;Amem(Q>F?J$6EmSI*AzB@UUI#=#`n|A$hW2x|siF~UwN++5mSfeF z<=Y1elT9qJ<maBwqi>?d@syuAa8Hb;p*{FcLv;Q3v%cZujRu3V$u&4grmBbv%z zxfR2#acN>NP~L5IaGcludRMO|Kl=F93a0=murXi_$=M+=DC1mQ8i=5cs{DN08yM#F zDG&K?e>;o^n3xcgu$--JdF7gicv=mjuX?EL*{pM&G+1#eqN7Q{f^28~Ml~Y{6bHnk zL;ccjp8$DQRvivHng;rr%c;eez=xzEIt^3^Q*p@GHaT2@_NY#71>JY;?>kv+N=`l7 zRLFe>Y>HnT`Kj6M$SkVrou=?>k+dLc;#NGCRLFd;(!8=)@9jGZls~J|gvaVLT&lq}=_Rm;%-IW_qCu(;eE^ST1|G*e_9|A2JWXkm9 z1tuSEX|OxN#JYowP4~|BzaSuu)$+i$7>(WRN6FeQfIjcuQEB^dUlc(zUp$0_gh~56 zx0&)fjS&O?#ph4Iuipu9Hr7j6)pTns(@4^&f=b*ky%Ra>$5_*Y6%~lX}#mXU=zNG8Y@obp(=(_yzFcbgd zVx&*(hqyVL_ai-AVwG=QOedf(p6#A4hd31Bv~0!2br^c<6e9G8t8B`fCU!jM8{Bt- zC`$Wl25_#%;(|TQl1>>E>Rl>sCHc&%sr4BDX@dxE-~!CQsyj+?(dve#%x+{7QKKUc zUs&Bj32>OssC=jndkPjirYBKjhsdt-F}m>YmGnHGgo-e6VBV@VA%cz9eG$8!6Kmg2 z{JEg7hdiUGtEnSb9kobN^*|mLQNl#>Hb+NCh~8I4lhb8f2NyQKPk-^N2QNJgTo7e^ zbn)GBXl~}Yza;T`C>IzmY_@FC5OSzkDXGL{=VTf8NP)p_GMF!tM&B^`Kkd{cU)0g- zy3AAgocUs{R>WUCu)khlo<-kN&GY(Oc{wg(QOfw^zZ0S1ZeGezJCa z{x0{pSkdJIcXF3vahm^n)TLyM!9x4ch22>pp|lRIOxsp{T8pflEYLB#_96@=&zYXf zgxTiFSGnWwsdZpBHDrjWitl?bvZJ5QiL1T>z%QoHzlbsQh3?{i4c&0s2Nz;6j6pmixudyv#+> z;k(IeU9;J}sgy-*KB2fh9HW-jSa?b3rE&4!14j9&ApD+Dw)sng{-g$sWejN~b896* zwD64p@ZN$}Td~-~zF^EbwD%L@11}W~#y9{03JDO*qX+209pARb3lWlE{9@o~jXDvi z6XVFLYU0!){MN>#;g68S|GA4w8`W_i$rF=*x~=)W@3;dVp5Li{%R`&5RKtBGtv&l0 zX)y;!V$4k|$HjahN}J-+tFg4>#CyEHf?mmOi@M(}>nl+^Cb4%vF?n?*c-m%X?vmC# zZ9fgZKMCILrEVVFLp*@2)6L%X54+=P+d6G;JgawaLkSEJM`7hky5L*%OgZ}2Qtq5O*&fw}UA6(oDW!Ti1$uLeVJkH(; z6_1Gm)T1KYS|OqWyk;$j6PKv>GA(v znIYsij8)O?0)1F2FCK8zuzkiWtB;lEo)oYlhEeDgT!4wCf+ zX_*&m9Ou;jrmZ4ePY7i_b5{(m`^T0;mQ;1_E4H*ZUQzWc1d|uGn~?qh`crd+S5WBW zjJc}abeiWz^LK_sb!cXk^CZYBD-jYEP;;b_bN8>Y06mfr(dw>)1oJ&O<>RT=OR0Lq z4kaV{ht^t=dkYeQnrSUk-f1D6Ax8~pTc8S8OK{}!GB(~<(}t&C5AKH_QaygP^7UXm z8;tCfBF1@Qmi!Y5FYu`(evCOzE>W=WVUW_zq?><10x!M z-nXx?i7A5MnD=8;i(pyF7=pbX8T@OY;(!}zDN)fb?~(@8_j5)Ie=ct zj|-RoOgwm}B#<>y{*nzJ(~Qk^MxTkXLW9N_IrrwLP z84C2Mqliu_0g2;v3Fa)8dR2LmqyI0*dZ8xBkSG+>O|rZl+X+OLBAy{C4fg+G>Z<~x zjH0b)h5?37=`QIKq+#fm7Nn7ulx~JbK^h6^25F=_q&r1gy1QZK=f;2UeK{}R4KNh@x{)2i z&U`nMMrk_TY_oavj|Dg`cDKCBX4x-Es!e5oZf@(E_;t@!HSb(3wC$=^1x%o> zoj>3N++{jFojtDl%se_a@4sqn+xdsF>NOVbUL_uQo~Mk$wjH15VeQi}lcs^N-&mCS zFJP55hXP>G0f>lJJ@gl-Qe1I9;R&L;%7GI2C~#{hJGngNc7z7&QyoRnC_`KrUg*9<-}+9OmG91o=GQcHAyig!$3AYNs=8w=WlZxl z#mGgXJjzU_W)LAP(=NHn-`D*va7CR8etelRe4k%rROa$-R!=0>MQoMx(0yXuAFP>z zAZK-wd@&7zAKbx6CbgrjX){Y)TNI?C@|f0*U!`!wR4E%ezOP&f%5T&KUP?)8O>a|$_SE`HioV_|*|hzq`t z&xCyN3TBHjH;trV#1-6GYTo?KB%Z)j^grA*8L{?*-m~>f_>_j z@F&di=oDj@4P^rn8qJQq z*;1k_k4{T(Q^XpN7CnYC(vM%Vn?>KR_gVEe7MqrK6JCpByY@}nsuL@BC&X1ko5?>P zd=^kOD2~#z7Qb5mx3Sp!JsCi%?@^^UAj|fToeNJO*a5)%>W<+UG2wBgGt}8)WF;s0 zpx4W-DJi&MIw<2$h>Q#Fc#ETbmhD5O!$LDVAvIb`ICufRNbL5C{RBLFo{x?FH#r2@ zm3AtbTfLde%~cDqFkRntDqC0!aILu6X}q~wb}_2=kzMiG^v&r8ycGUXhcp)Nz!MLMKfp)Fb3|Fr5-R62e9uU83Ja|~X z{yE`pKa!htfFI}*c~Mxh7(Cwb8P^PQ?7#W&hOP(lPwq#Y0{0SkhUA2S+sWD4rAbG? z@ge7jjw8latD?r^jI70AYs&vh0p9OP0cmJCOdtjRnqx>0VE5}O0}}M~#`>QGIZkTP z!(karaNJ4PEFhQYL6H;6d!VL+Era`8gRVC82%d3#N06XPG&-;~|5wiS;_?C#JU=_k z>9L}W@ZO(xGBT;?u!=Wh-v~WZk>Qroquzbyx@sG#WKK4Is835<(l1tk{ZO@8Vf=N= zT6NRVxPXfI=lAn!n92(KmMjCCgu;dw#w9T+H1rgPZSyL0;X8nm^f2LC@D<|VS#uwu zDBHDs@mxL|n0tb--)&`vYvCxI-pSX*;ka9Q1UUK(L^#2Ky_g|ns->8vGjsBCc z!{{a5Y+Uwx=4gDrKV7}~%Esj_Yob;WOXcBc%LHFqk5${h<;t*?`ePr0nRIsw=o<>f zS4UX=ww<(L-;3Mj?6CTM@uTefhczDlI`975*XKt6-8q@Xj{+r(SaKL??OET^WORx- z>#T5n`C}!r8oH^8j^6GbKk(0#_SiP63KFqzl(GJ!;O^^0N1rX6m$I@AUa9%KKcUIa z-tf|0LHqAZ%-X}$#(di-_xk{|{pqS$vi`hYv4(NI)6IZi+rSqA#QFkDSJE@8`T0pX z^WevtKJ{JSobi3VWxp@S#{`YuaH^2)%LBA{*Ws%~+>VpVcBQ*m3;dQ6pL-$3F2&m3 zHC#Ee)P>~oXogpy1UKIY(s);4xMHqSPOI-b)3-6}Xq`2ic6Gk+jng8}rweJb%{B8l zcuf{6sB64-SisO!XKkuC+ESVFo#FTBdo8Izx+HE=#(YMHVbd<|E)56VXvr_UCC)`Z z>9sSXgdP1mV6W$}LJRV-ZN&>|M&y_q)Kp~S;g7!?aHyhUw@I$4R6~b zL^4rtKP{`YdcHVVRJHk|Fd$DSLk~0*Qwfi>*tHl4*4Ax1uZoe zZyJx(tE!BR#rT&NzgeUF=e6Sl#8AFSEc-2U4 zBP5ZLdkf>v;2;>Uv_7RN05KV`sEO0Nzc0H?Zbzc|G6QUVtF3(%&_#uTw3) ziIHzLr1xz1CfTIjtry{W>RVOjlPcLW%3XcBsq3cZ z?(RP4pSvowc0aDjT3V2x^m5>X)>#M(;V0Uxp1E?re&e5uPANd=y4MC$ar9&0Hk~fd z?|7jg|M^_}NJcn287Xcc;EGF+P~~gDx;QR)wHMWA)MrNYBrzl;J2?UI`Xb{ky(#Jg zG>pf|+H{QxJCP>`$lR(|_s;us%h|x`$zi~w~C^PoeW&e&-#$NqRL$dwGUk z!o}U;h&o_7^`RKQ7}f4O*)_pt>Kn~4HXlCoy^IZV8H~6 zBrm;qrYmyQxpUbD!k)Cn%J1|t`_5P`_vbDSzI!Fk@^v?xPS9V@>LQGQ3haP->|c&- zaa^aHK%|`}nj{Tdw=6qZsc?F^Tvk|*N-s)}pkQUxPWn45%iO!XdLtuwhs+$QuQk!w_DDqDaCm&ovQUS}0n8 z^p$dBUmBL{$HxcpCz)0R_Dl|bDz`N0Tilby6M@r84B^krmVZfQP~O{=){QH@TD|U< zy3ICP&Fnn;lT=fn+^Z)yVr#ZQG7bL8Eb+s2?l)5j){`vw%DlNFGWy&r;fi#d=f}nPf{pT_XV#T+G{G*tU$CAhS(uiw9P4d}iqRyg?%6P6E^(RXXA1S@ zhG+YIFKW`W@}>F!l2b>S)iWa+ji44ffaUa-%{@m|ckB+;{dGd0^Lht$rnwCHl`Yq-d2>%RK-7 zapJLRZ_LE`<2=d19M6UCYAj9=W>c2+JxInWb9{JQrwApE*cX;MOZg7 z(+YKRUe56WmoUSr15y_e)HsfvX6)L}Yp`@2-ooR0?36jJ(>vR|VM@TrHMC<4U(JGd zDw~gu+L64B(t7R+WdKBK3h6NbC{ay67BM{VrmF?}3xRUXjnbKegWPB$p=1PucjilBA=U9>B5iyYKwxt3kgSiV`wjOm{#FQ#d!N7tAoZ5WrpYNfzu{_OQj#|RI_8;k&Xi)`Ns#bNp42d1mG}0wj4g< zjz{xGjXvTL8noqMB0_~0XTpz}iw`gj+7yeyf=_m=A~v3Dal}u3kH&YF+i{wbTb(@F zOkRu`Yn1k9T;Iq$f4L0_q>wzo*uaGRlq&m2oROfT+QV!*@zhjSXU=>qta4Eb8eB3# zL%ZMPO1M>{=*iRoY;$ZKm2CB|fcsa{d-3Z^VaV76>Y9Q_@ZDd4vl%}L%Jj5(pYNqG zrq`x#C^_Ezy3!wEeJ@l@MbI?7zvl|J7vFgJ;c0R%Fi`&Cv&yc2?Fh9txzf%=I}P}R zHzr=Tm+YX8AS;wma@|MiX2OU#bp>-m*-+>kYup+Laq+pMDiY{UjT2}!1HJ#iS3m|0 zT_rM%$+OTrR8c)$HKneS>=``xW8*Hix(3%HZp^@4}syqq(H`4;e-=tCy zdGV@hAH|KN&Q69Gv%lS_yI>~rY~#DdmdG41uBtIjueSU+e%<1u%@-AWz4(>0FAIc- z`-C_!LIZ(eB1w0GMkF+8M`ktpd! z5~V^<^m(CY4#hXU{#*(sSzH}(!k@b!TB-FEx+~av`M)3ByQCYULOoDqD9YjQ?R578 zBjfEy!cbrCyRVGt-v16S#HhUuJa2s`PL(Lz|ID%zQ2+4{lGpU37%LXx{itCot63ch zz@2Kj_#+CTt*H=_YFCPgT!K}sPI5b{Hs1CnlLV38xxock2n*|#30 zHwM+n-82Yd1Q$Jk4^ubXfu&^u9Bj!%s|mk$@(x8_Vfc)X}a z;tQR7+Ii$@abue_G6Ns9&X6w%-HGA{D0^xa*@iIL_16Ng`WJ4?g?Ds}D@2dpzru4~ z$Kec)KB>H#{{7s1T_yVS(Sex4#BbY{9KAT}7w2toQ1=zAaN}s`@GEiqC7(xH5p6Ik z5fFk36X;!_H$mO*Vmj>lBpw$X{?0%)rqj9J6Fv>h?`#~|8{V3E-?-tK*~C=;d6mCx z>Ge~4mRe%!*#9IkS^#z*(78KPg%!c;T`12-M}GrzJug>e?hU<~BP-+rK{_wt3qL_{)2Odn9)Tl&`Vmvw-5qwe#KSio`A6-(s+by?k;v`g{X zH3Sc(xe-30YY><^oQ~6tpmCG-AI`n3AK1hbHU6Q1g;z!J>*RHg zdHFnJRoEuLWeq}CP(XW?^aU`*O9Cdj-SS9W&z25{6xzgX$!XBpYC6#mnARJ8^V$Dy-j>XC)){NUtXyiRcmr1E%>p5)Tcm;byVTr%JN<0o^k zgtyjtp384b)V0I|pd#H}*Y<=q1B)&_=rRlE$Kl&$&6@z8U6Mh5qPZ2 zQDvS<&M}R8^(McW(x5}EaWmJBm0rZj{`)Rfclh`h$DQiRA66Z9&i|43l6W}hYBmh8 zuXx#|N3z_fzk0SIo@TQ)wA!#IVhf zYl-Q)1=yxrVE<*XnL&N;KAWbU#6m(eSMNu)*`WiwkcEa9DWFr_-KFX*ng@CZo;{`| zh-DbQW%yrY>`a3~bLLr~)vQYw`uJ*aimwYSVV4AeY(yW=26T~R+OMF(Dvvljd|?&~ zN*|iq`uUw9wfe;0XZH0A;K6w8QjfAu8T}=^;bKk2e=|*{tjmjP2|E_EI zI4DZ~b8tp!-R!XBs{z=9}hdzc>=79?-+Ipn$p}y!}0pJbDZ+jYfEN()6RTj*De8T0Cq}aAtwrp6g zIVJ)rDyWi+1aveoO!>22d(LN4a)Gw>`rXd6>sl?f^vZ|=KCTx>Fd(Arbi1Cx}fXY0q=&t#DPSO6@-A)tm%hr?hQHAPv~JX*OyOBfw}=C{O3K z<3iWu^)=IH^b4w@&X3mer)~SEa;Na)ft>~kFL!tQyYT+eyOpu#{jm!>ON-sABI=gM z!^9t_PqkwF9@$p<-t@@^`g%1tZD}00ejyKz?txX7bJHg?Z#iY{*4%~tzt!8M$vw;i z$1wrJHy}<-slRUJD(-a1G2i0M09Ke@j%ctc9F;wQW(|)n(#Fi0*9`Z1kLKk2OeE$v zkU?hH*$8Y)F&c&D!2M$K7k`~=TYw3)8RI`|wEr&Ds@KrL5H3qgW2T5VSS!&m{)doC zxI79F7WV?t9y?ss{Ia#f5gIQE^O4^bZCh_F$gXUJBgw)LWU&9hC9=*B4F-7+Qi0X$t$LD3bkCgt#MUP)SJvbhg?OMN5 z3kzk67e=km(k13lQFbSu>qmFnFCWVd4`qk0iyeGa4hxBle$ZZ^rtNyf1!UUPzX3wW zgnk;o)-^}QjYksI!~_TTK95Z|IL*l+KI=}lxf8nwxHE4ayi+WmxEtx{=wyV{-+1c| zUpE&~Jb$*(QjZ%yTUB{V&#*76XM`OK^n>S_N=eHg#e4%(ev^=lBcxRPQE_&Ohd zf(TkeK?L9iA#k0F~bFBHI_ZKNyy3^1mP;u@#52g z^o6$lr}FX$vGq3ZCOWBXo3zDBOFNT`1H^~VJIdmYR+rBVndoBJ!uYr(`7vT*pC@Le zJ)eugkG`i(=k$d}22~E@YEDItuAGKB1B)r7?&*bT6>pZP?!Jo&)CdVQUCj;;R+6{N zxx1|mSk1_-DGqS9T(!CH9jX36c`wO?Gf0*|U_fJo6)I9HhuITPU%B%n+d!_q@CkPu zlg64#PZc%B6=q{GABh+DkF0A&9w>!LlZv`A5sun215OFL?Shc43jb|t+()rg`2XzB ze*!*k!0b}i7$N5zUpuimCO9Ja%$Z_+@HLPbOOB!ue)$fxK74ZG`6`m18Au{oGpf(b z&0+n!*O4cfH9sc=t*k00_Z3=1K15syJ7Q8e@WErM*f{2fC3iXVnDfJ z+~AURx=#dtjt@E@g7+qsJ+k$=X3IoU|JRw*Z|QwO-rsgEMGQ0AESb_Sx!oYIKP<=h z9{yJZt)R#6wkJ;F1v1!x2ZcbyK&)EfJ3VNyGnN&LW|i{z(@66@ZblS@AUxAg5i&XN zD@U6{MEUs(r7;@%R-*zT;cu!Q5I#&=foy0O6AcAK_8kobK*3kLX)i6)Lh^Hz%nBXf z$!(!e_{Bzs(%6t319rpXsOzboFXS0g0mDfEyeyDY8gESs9{1m2yT;7{=ac8bo^B;N z;J7K|0$4QI&?in`j5$dtFC?Reu)KO;KuG&Cnx*rIpetDuv^r z;|wgLGDJ~oTAtM6<1%j_yA60J?Fx)*GjeovdzdBQvK4JfBkHxx64(Y$Xf#gQCl$m# zOuyjiCbK1FobKXM75CZ=#6;}0c*d-G9u^-a(lv7r^j_gqL*0Y7^MnsM+ubD{OktMgo6C8$>_QiUvV!$A*yMA6els_w@kW!yuTC~ zZ@@v=jR5|>Ir>~>ctD3)z+w(XOhWDJH@Nz;fT!tH;yv&0WVTW;W>1YA*4joC0xnpS%a253KXVu)8)3Lcf2ac}UY1 zcP5OH&u10_R{NAc8K+|n*AstQo0>bM354O=5WJ#IgXPy?Y|8>_6gN6H(Kb3S!HJgo zKKtkIZ^EXNDu+_85pxLD4D1*9N$@LwvJC7U zU7e&XIgB2_MA7K8wzY+r_Yb^M&=YyHQ2(@-(!TK+rRLY|`=y9fUl>dOEryK83`=sR zyYS;)$eQogYu!#q$4BV}^+usUZbSef#$9TrNjkzo)MtvV^>TjF$EMOSMi1wf8OCQ@ z?t2l6V($j3?%PWOo$MngiIG81Q8OgaojaMe1fN@(`oiI%zQllr} z%!4)e%&^3(>0!(uea+Xx>E46U@jnRd|Bf*TY`_dqg0Ok3A zA25l~P^dq`q)^(Qc&bZV=u*Z#l5tYOmQdyCYL-B-rNxl|KtjP3)R_xo=*xKvN^~IZ zw0VW=23zuYO+iB?YompuPspKH#Cdc>Zr&(TXy@q4hS&jQi%|SHa}VqJ!8N#T96s4Y ziG^}Eh-k8;Ku(-z2DDZEA>|G*O+NQDL7!$+CRk6;;ZA5;S>z`+OUY2~{>x7eCu3pE9;ecrzVW6Z?4h$p+ zJWD_l{0*>ng}H=uRTRRmL`_}s0Chm}6=;hZ3auEo7I0m51W4Qh{6LCZ4vdt2N@1|s z^6I*S2qx;hKh|!2cjMDS)W>*Bizd#p26d^XPb6eI+;-S4nm$4}doG z4>2wkKxVK0;c2%pMH1|G|JmvwgJ7m~cY_(RVwtOv0YacRg&7(C(1P+BP~{KOWBgut z=D^Q!bu?bw-B4#@A6qXl_ggMZiT`XSub18&MtTj((hoI!63J!Bz2J)=od87aA2{`j zyB_jHF5i+8-3*D)?W-5l(fHv6tv>;)Tz1CASpZTkrf=(mD(3)??7V{(o*vFYj?svHBHzdI}iJG+*N?pP; z`W-TLF?pbtgAASY3?1x3u3lP+eqdk!+=!Z}<#YP($gO@R$Io}7Q`cv^Nx(}{}NLgrAcEM;^51$$K_%M{GA^(vz4|Y|#V;4r{)U@hrqG zC>gl2ggG&ZP?`d7^U1r78_Mh@EzUI(=T)zwc?<%M`kP>7g!$Ng)q{M#9$!T+E%#Sh zS^K*>*DfQRC%KBNNzcxw+Iu4$#9bPR4!2vv2}eQ7?Tv*l7w=*hPsm@~x4rJkUm3qF z#xH;q7ND{SJS6BLu*)X6y zU#Dz1PxyT&s~my;I;P2MHU%Cd1sN7D0R2xOy=XI&l{9BmL%Y6fFhC1tFZwouH}Em- z66huMvY&~rUT&Y2){CR#wc4)^;(|J^G2Br5BDTrwm^^^@Y^fo{VjrLE~@%drkO2)&mk@0nBdY3iMg4_vh!7butc~W9bT!#dmOve(` z=D>aA^tt4bQ{?<&M?*E}fU)WdYui6Yv$MPi&*?twc?(nd^KkqSSNit0|{BVCI zfcQesKCV#wwXuB5IX70H1)IgZ_C$?f{(kN}8}&~AHg6`o@doq2m%G)IEV3xbj0Ao1 zryz7e3m@TiA`y+W)nz$gG7NvtvD6z*0|-E1EWtEMaJG+fV_!qkk8!wx!~~3oT(h6n+@wO{mdmEyyCl6*_x+7= zCtIk`G*m`xx!u(W7PtJC2)2sEz>y620M(0mR>-LWa+BiNgmW@aQ)|OjxPspcBFBB# z?E_Y*2HWs<&A}*^)ZS-3J@ufq+WlQt54`=-Ixy_Xl!Es^u_OgJ!f^<34#Q>09B$V$ zejHYS3Lz$B_n0VsK~-pi=6qyRciKDRkGW;tn@R9IA)jN_@zKTx!TE`WPnfLP1u=qaU(QpmLq0lc8|7vmHkM{& zUVdRu4`OIM?;(g0^PIT|A|5^A06K$>p2ZGC>35%M-f3r0yHoHl;h2SHg5bFs5{CSo z^qX`MffG11k%n-rS3t7Qf+Rp$5>^*qTCkATOFJi7TrN@+1yq*(UefG9Cgd}T<6G;7 zWVS>DYpbfNmXq<`cA2k}hP4;byPbz20&X}Q#)&7VNc5S&h0i%cVp!eF83m1ds|JDB zQ}O}lD*_K5{{Ki<%k%ahw#$y+UE^S7HLd=v-20$8T0+wKk7iHI2*3<*{sGhaFk}x< zsFO$l$*{jPT|yn8`q-%gs6AXPLFpOyx+oFznv>`QNX)Ic%>x*w+juZOP|}>FiAE@+ zy!$QX8`!+KAQ9#gr(klr2=ITx>_6n>Kj?m*2Ev)06!hAYkwsnNx-Nh3f+=Og?IXT} zaW|-;YH-1ZMf1@nL?DR-Igy)$yKm+IjY3GTL4}|15|Mn~~afN?l+#YMVQIt&kq-B6(g-_{t!yx@djwup{b9LH{`y<{p zKFus;PRACN2zX~3G<#RAWwfnTzON9dWceq{wG#|Ja5j?2) z6L4jGD4qotIf!Wwq-A488Pyx?%?y8LcUhNYCaCFnOE4}p_) zv#MZ(ewXR+Wu`;n#m+FrmzZyzdMk}`aJE_kd zJ|CQeg`0ftY!PDGRceg8lc%sqTZoWhah_EbpU<|#188OjRU-#KPL*JR#3j(Xzl-#4 zA$dP>umRqYa_i0dd>J^4`Cv$zS-#38F`O{+<^KbCR$2fR5_3GT+4uq}Wu*2%ymTXHR{vW_P<~Q$#DyDJ8;=0&CPNsBX?@ds zOBk$)S4vFh^>=C`B8H*9x|vjJ6z2Lcvh(LQz$W&2lkk?>C;Z0gs{iA;!@!66ek3s{ z)7zvc!qG<-{^4$68Xn}%^Ei{1eSz`WMyd3gvPv~qqLkfH>oU?mx zyAsys%e?dJu@wAXw1{F{<_7fW4h69Q@-cz9OUg|%bTBSCO;$))W-AA0>xaa zPOOGc=&A-D_&L9jd$NHWYLe@3gHG&OaZqQMFifvPsokaUMWz^1BydI(%W$b-bNPc3 z_qYb%fDm8QvmH)YKelPzD`+Ta$h?cx$Xi&U*7WoDTc;n6j!sP|=|A~y85p4dWvY33 z4{-sHr8H-ag%!(o-199jn{}LNF8)!NGfsSy2VpZ32W8z+oX4L0NZAqaEjCnuiRK%Ft@%hge ztJK{;?6rVBjkOM6L7P?GO}BXh)VH6s1o1V>+W~8 z5yB*T%hnsBnV<7q6WLFty2OYR8>E=ISYa}S&j8pvSjj3@52Y4t^%ig4o4n~Y)I=0u z>gH*WT)I9Pgp7r&dBfFi)J#C>r}0)v9mt>v)JH0~hqk!Ue1JTI{ZQkQQR0m8SyZdW z=GlJ8_i-+vDaFYD9AcFHKXDivrjUiZEbwhq7C+QHxcA*_TABe+fg-UrJ4hx%1?|iN z0(f6B=C6N*^kCS{Mnt#LJ}6qJ`+Be|oeto|aGPwZ`U#1Fw>EAb^q%)4w(!out3O(w z-2};AK?0d9R}VTAZaAooJ_6a_hNaIt@u~v5Ute&B9=IJUaZ)W!{jPD*JUC$^Xy#5} z|HeP}Y@J8Hic{YXpjr}g>;&9rP+1=>jGdnbwszdoGg4tn^olgz++=0lV(vfudwwUztcv~w_-Dqq?4SzgckVjkt8-0|&plUUkTB4|_-Hb!M_$6O6m9$oj1`qKZ zIOYfM>h7f_6TRoOhz;M;K46^aUSJ-9~}|H#}^Z0E{7q zBy5W`W&4igSwgecW}v`yzj<*~*`n=Vk@mqBP?dc2W5x*Hv<^doHFPHYfv=)7D()k? z`F@IG)76wnpA3*z&v&Ji9C0;PoOMP^7njCHl>285qi-@uK_Ea*XE_^;;2ocEH7prT zHhUqgKFzpRTU%k@XdiIz`fwAg^FNyKVd-TkN_y%Nm8-BuA0|-&7@`k;VPcIYp%qzz zz7+f$ZlxW^{?=gm`@BzYENkThC(dcbJXMFQ{ZaZO6I0-k#+SD^#BAa9iL2+t2>+g+ z#*gE#wPq^KtHIJ50V;+p|*^LLRF#95Ykb-pzqEd?;#rQFt#(crNQYQAEj zF@&~JQStK*(PpB=)x^%>!yEw#8Vw}9c}aB^_Do@N!>jp)Wp5G;HUE#QTAiKn1+cGu zGDnhV{K~($pjp94)Goae+Np#Zxp{#dB(zSz2nfYBu77*WBGgfRI#E>8`0Q;3cL6h7 z(^9evZDBR>uW^|fgp`fjVtg6kacx548(6$BOA!D$#n;ei?0l92ei1I7%vb&hbprM{ z7nmX#E#drDEIE75((yQ%UFz@^l$q}2^T1TLS}AEC1yh+Vn2lr~E^dF(g$?!D1UQ1# zb)g|xvB%kI61cUE?=!rT8t=y3uAWcqZz+|sN zF)OS>wlpe9<7}6NB+S3Y@sXCw%V`8GECwPXL6IXD4Txddom>ZAk$obfB8IS3HkM=U zTGkPFwER50SRh1q@-oUj+Zn+KW7|5ef8hf;j}Ka&EbpIws=ZiRYPsL3Y6x#YrbPeP z{ZLLba`GP{J@tO(8FHD9oAx92uiTToe(uP=n%Mv#k2qxs?aGA%6 zPaR=2O*r>?@vBv?rX2ifp#5NvJ1DDy{%eXZMiZ%ojMy}8hMT)mGF)8&uf>Ew;NI}< zn;ezi<{Ma}fNKd9qQRtv5~{IGnL?w7k1c2S{=+u_L@!4V_KpBb*cpKRYA4blGcDV{ zuI9G=)jRnQ;wEw7MdajDv(2oj(noi~cym zCNK}-9}c_`QYlO7w(m+p&s7UN;$dukBI)x7|K3w<3isJOeWUmRI#BV*O7n_^We>TYa-4ei*iEG zw7*2GGED0*EX+t#Tq+#~s2d%)fVS%cCA91^gcT-$Lz9X4fQ*|W4h$j#Ld(&anSoVF zl1<{(Wf(nJv#xo}mg@K->q0OPI`a<<>!xA%CflCCJ$QtjKr?(}DeHf$=!v%=0O-JJ zqVTe6E^?LQ`3};bvoCC_0+5HKj$rJ+KRrKV03R77A?MfkKj~;lpYrg(TR~ko*vE*{ zGfA4`V`zOY;jjCaJ5EZXV3)S{CB~y1oZa@SCtM%XD9Q~a8p+dS;J8WuWrOVE8 zZ~HAfuiv0K@WVez>hs(j)Hqs{)O4WULXrzK5uIWG6-^?qsG55Q8Wx}?4iZ;D6;IxC z4H$AInd;6rpn5gnz+shPqM(T>U`}i6Qkb>i$c{ZGXF3U2*&A3iX zmB?;+mqs%*@(bHg*y)Zh-3T2`ciOVv(+2IIw@p{@Mqv;1W+ zOOKg*Fuk#U%}LpBz0gZ!!3YkbU_pI@CC5scj`{$Eordf* z!)yVm8eP$)$$gT5R2vu;lErdPoH)~qCz=H_g|+Th?cLhLPs&#DK*ZLp+7C%}@r=j! zWq~%w-qg=WW8^U_)s?A=rQV2reWaZt>m1SA6mgdo0j}&-pEZG)E1WVFrBkY-)4yju zmUl@fZCUayD1+0l6mUGPa$zk`!(!+PG8R9zEx;7&e<9y2n{DEea)A|q;w?aWB^zT9 z9nO|33Onc-AXo^@1KrtU{fXfLw6a(uTa4!1-JE6~!gu@k19A4=c*6hJ8shUE7odb( zO`pxuAv^O6GoE-7e|Z?YG07ejIH#h|UoVRu zr?RsgA2Snk$eqNT+#%$%Y?C7bAl`TQj7bkb!9s>Z~%ji9OclJetsgFiM3x-R%Pv~3zuo$b7N z7Iu)d9u`gIs#lcUPhi1%U$l`q3*>N%z$P|nrNA7lA~jf&7yl%mI{iAhO9 z+%~~bFn0fFyfk5}T)9!1yZAo#MCh=14X+@Ow}QVC_br}kv#t@U@hZic7C7j)ZzWB% zAM&q>n_t&PVfE6qkF=OMkI`{!vEX8cn4H7rjn0g4%CN|HtafPUY@m(0APj!Mh=QOu zMrlsNX|T5J+2qSah!&_?;Zj+o9Fp@o+isw2h8_#@g9a;d(@%^zs}emZ>7}lNF!!k- zT(#9B5K*+TV&ZGzctR9GWt?(%l5D3Yh{(@w-}jcMt{aBxbJ_Cx#O8|7rQtGbf0=7eFi@%)DETSl9$H-{|o==icQLfYhor@}&oIM#2_E4188& zBBanjYW?hYMChIl|ItqsZZ}|Snw}@L?)eMePUKPE*_iXz7j)bq@!&>9AjJlPmxB1 zeU#*RmTOcxYm>q!(fAshY~O!y1N3cGpq>&u29wyPPeJE~vyxaxxRIq62$T3f=^kMK zpL^XeA104_nG+hc7w2Ksz5uI*ub(mfq6z=ry#>8SvR{HN(w`>_7_zRIgW556BA#%v zFdMnip{!rPj$k6>jy{sPMu{Qhlk|~FwQP+mzNGMd1U}#K8i$3(NOO3>2iMQ6>TAze zU_?6dcXL`0xlY1%>H|@Iq%7)+$So;ow6L08>k{3%-zKgd@qL;;i*yOiRofWMbZi<` zmIF~>m#ld#UPmUY$*}hn9+4=-FPcjn^0-J!}$(}i}|yeyQrV8yLU&? zPN3RWE%^69%y~!|)xC?^f$d)}Wrg6-k2YO$_D5$XkTXXS?483)4ne9q=r z3xBy9iUOxUV7-mTky~qja~CehY2JG^1`~k3C9gjK<%(kE2?zlMRm-l2ZR~BE^pWv6 zrS=3DMg^YP{GJ9fq*5t{YpmODr-Yir$?iG@cOxp$fFCjAO?S?Ws|Hgi2y8{u^L$;R z>u}kn6Sw?o&N@(HY%wD~kUz$KPF$8ezu_J@m-F%)Jn*!0VeU9B%aPUiF}J_^bm944 z2Mup*@>M`b@c~{gn7E8k&B)rEnUDp)whoUkA2^b#)aa*dj=9J7sRn8&&(g?dMi$lz0D)mbIAy9Y{t2z>)CDdlqB1g+&z%h8 zx(916o&tg&JjAWn{s<;uUSnJcwl9Jxs`=Tlaqp|J-E~YbjqN58 znOobw5g;2E;%~#K75#jpxD-T4%BE@%RfN{~iu+zAw4;o+$9+aO@sYupg=e1IlI3wktH*X&7X|y7pgW1hF_G4eXx> zav?w1lx#`(e&OuAwMY*jvl)~Kp&%s~;J$1l|7`E2J9`X!qxb*OX1wOM_>;*WAA zokXr?t;i%`gRZQx0rUhfuu>~RR;KwS&|iF1q@#gDsk0c8!*u;9&joN7NoOXWMw8zl zHXcDK)Wd^8G98N1ji|hjB$2t4uertP2uM_3FPjr$tc#A!;M$Pm{p-FgZBb;r+NGb( zGl0oSG!w3c%F98-kSpFqB!`bok3@{k5cr63b@r|gWZs3|jfWUd$j=+K&ku=m`E_hR zh;!5ab`ZK8>gsVv3)1I^dY^CE@iq2ea#$VfZHrD%T}ZdLJF|OiQt zzBt9S5L=kXC3))o);gk}TfhMZsP<1ewxmHT5B}-d%zIA>X^nwt^CW?}_ix{mH$p~@ z(1Dr_Y3U{ZC+qc2PZ80KS*Xp%i2tx+63~w-uq~ZyyP`F@s*<>+j%T0kV8Jh%fhk%` z{+gAe$<|W#X|g#tqgp@Ym-m!QCSYOLu!OK10$l4@>tawF^AO;X2jJrhZLkPRihH%E z(pt-iMefVb6^dw5Y-e;g9B)R9DPM%oW#SR2g5vvU33duutoovFu&$E2iki(s zjiffEg7w3;+*=VhCb5aJNZeH>z!^oorB9!scqK{cWrB1EfTo z9lc-KYj57XCpvBg|3h8=>A%oVSCw(CJ6XImAGSLvovYDf=NS?-6>rG%4B#826iVyz ziHz>NP)7s2@^yYk*UfO^u zWLoQtfdTV5z3$M;=N`Z7)_17EFMu2m=p>58bHd0ydZM3PM+dzpKE01+ z(O}7{jk&-EoXKM$>#q(*CP}%0pgvNNs3?1Ihm=$m*<2#&T4v0e>e}$PY-tIi>Q{Kj zvrta+{>DG4IP$XK*Cl}0jf@q^z_AH_hVgZ`YCK}{`%62KBNC9;!~y_W%y-6&{e1ttyU>`KZl}ca ze!u(pz12L5@%QAH=Hfb}>w}zkP%+@b0LWrU$>_nu`$w>T_*;r|Qj1M-z;7H$Lbjeo zYsnP#tOuF5A3*Dexa-A><=B#8t3|Kvgx!w7)c8h}-AmPa1; zEoG@%AD37^@1S2qnBT{VCg9T2rtrLdB9+Tjbyw3?_ykPAKIdS2%N)42g7jF8^Y9E3 zs|ZpBQ{O}e24vDVrt?XtC@V3_KN$(i2m}bJ0J;qVDWBs0q`2$V2=bVxT!yvu^f;cv zdyY@<+4>4zP()U3_!5(Zzuo4sTyw)apUP;;kv^Yxo62Db5AqtRP>zB>bS&C=aV z@eJgL`LF$2qW*B#aVXcfjE}3Jf_RxvzTa?8@G?CPz5|mZ|1;mmqTi_AX;9_8#}?oK z3mBx?2JAzWi{x^~UxHp!xHqt>#JIyHYawX=-riNeD#z6;pQ=;m#;X{~7OW1enNTo)8kt4tMq=BDX!Z`;RTmhMLn5>q zo2KSQRvL)3llUp5$i|)y&!0_?zInquk647Qy$ieKtkget@TD`c!20krTKa^06Km~7CYU*A?C;8NQS(d|>I z_!R@(hR_48eTpH?+Jl@d$}~Ljl?*j_XXYQHkT$7u*7Q2iJ=7#w2$|YZFZhcFNDg zmV)LyS#RfthRm_&hljldd>KB?$P#-sY-dFIRcAu*hC$y2K$9jJAJ3>~YESd&E$$2Q ziZWo$+qG8wr9w77a#-C*J6v)lml9eiqwfhloy5fLc*%0TFYLs*e6@Cy7a0??f~YEu z4g3f@yuI_Ud)x#$WMrb2;p$J@WS4D7MkO=!d9z>id>ZYJx4p3PprLd0!}dDSFI1fV zKGtT~FT?lW;UBwzaDODqaXO`KehKL$$uk?~E+ zwd80)T@aiSE^F#NyrNg!v>C3!!ZN)lc|z&LOYM5*4&UgVA^ z&QNh=W_cEVJyh;gVO`c*@CcKVhF;KR>JaG9aqUXh#{bSl_ycMD9nKzhA=s(vX7cbS z1jMnnOx8mo#M$>y>S229S9R4+xr^_7c2AtEFP{{X>+vM$r z)dNn!IEq}18>{A<5r$P&tT$alL+UIp%l?@fOXdoW+lr^hDM6k4=1w`C6A!J*MHwnLi2qKqC+kSobF_1|~4rPy^Bw0r9O@ZhYWsRwr4?AW`q$hshVIW{co z9R#m!;hdEdeSFh2{`#mR-p;eC_oeDerjV>k;Iw|BW5AsR9GX?W&&ao5!v~6prww4A zXY`i5fUTDYUT*BKFiXl?ljB7V+8=+nwR@#OM@zb4WmS=O5puw(j|9AWBldPb0Iht~ zo7EN(c)FE8Q?QYpY!YMLVZ;NqQ|p?T2C{SXC(%2C(ww7ZFFG$vNt+LL_SPh4Vxw9=pG3+U-IA7c$@@Hoi*ke;FX(((oG?O6O+`%~>)JTgK@9W%&Y9 zdxhX%5#Ykni|8`*@)XlC*#pL!1g<%yWimD-Ra#u>wUpZ)E6!2>u8mkQ-ARQR`;PTl zwy+NNSkptt{FY^QEG)<-5ITV(cLQMX?Jie4*Xf~L-a2{}m07*L&Hhqdd*aEUq#sVG{%W?qn%1?vk!Dw**$#Jk2}}<0x8g zL$dqHA4RF3y#6U2nfNT4qw78w5X7Z)k8LMHvQ5@ItIB)-rnTmB9;r`d4V`0+2Cw)- znsl=imdj_aXR-?|XTl8q-@+Xio2D!ze-Sj#i*Q4AYSHRhQjLM5O?O#3s22Pbb8Kq& zaGgTMQqY0Q!-8Kq#-rP>>Z_49-WTh-S#N@ROY5axlOJha&pG!sy-)RnkjGTd2yY+B zJp;DzWP|8;Ih3xHWWS6`q{Xuua3@h)y#07q7#R|2(QyFrMg;lp^kXrev*pd#DP?A; z`PsKkmp|~IKR-6rIK0ks>B;rFRlFU>t_7uM1fizHsbE}>RgIJ;=2>_^7x;dhJf)b# zqoD6PMh{%*)zK-==}Wg;+vwGs(wo+k(N%XW-Rfy-Z|3c;e5~B%H+*4pOnYM8CCi+- zV40w$oS#A~24;?+!wj-sF9upl}&)>Xpgd8sq>_Q%FRI43VTX6S~l?fRrDSAf-jZN4t>Y@i<> zb0%OC6cDieVdl+CeNSjs?MQ6rSf1;V5|ts#v&4h)mP*Xd?CmiX_8cC#w+2B5*us~y z0xx#(otI?%Dvhzz#fF8?Gh{sZfhR{dPIYoJ3)sH(@fH6?FApoR9|2iM4$TMG`3H?7 zYk}H4%Yr3mj*gB zO$|m!Qfg?3{QUJ@e4V*#M84|H8}wL5@@gw=cOU;)apk5jIq0HS~xQ42PU z_f~7gY|8W3H|51i9>>P3tG9|GiU?%T`OLJrf3vBAn?R29ycE4O#-{@61;YJqs(xoNV z1)S|LDqz~T>*Rg+X3!k7*!}H9b*IbWjZsYM7n5PDVXnyLpe37+*+uU+Ed7PG6Pxyz zYRvrtj&$JY3&V2%o&65F*yoL=gTgGc)mRzN{i%P1gB#GQDyTFok|ig%bhGB>duB8l zW46`8TA0N1(xB0d8rY9}VfNXbo{vVX2dyKhLU7pFFoQPK!o z?CLA*R7s%XC-&F8L!8H6vnzkRk94rRXO=;*P<+W%)G)t>u#;o6&0*)^XzT4#8;s1^ z7l;jX-8JA%!>r^#fo)WJAMLC8El#dr*8AnNZf{lZEE)Ax)Q!2{MGI0MJ%pb*zZkUJ zsx{gQ>p49&1YI{>-ICceIy{RUP)mbP!D5nL#K6zDEsv%%+AM=+Sg4l;EAP!g15$c2X2~)Z!n6>=Go5qLB*Xtf9 zI8_qb8#SEVz=>oCY>{f#F}z!3iO~!_x^mNnbw%`y=OQNa|2g^pyk$ZtoR&ClqoaT0 z#8MJj)@(H|R3=Q@OFnR~+Hs+@z>&9~J8N$J_oDXaDP6n!kRNjZ?sA_iM__)P_f!s8a3u8ATzLuc} zw(GAtho|JdHpDiw{a&_3>~M95_BQ2?uDAyv%;l<=uqVog&cCn59mHcK$ZmwYl5U?R zeQD@Ef0h}B(LED4s15^E*xlQbJUeSDNR46;NZH`%PQ23+sE*B0-Jp}T>&3vMok>Mx zY`Fr4JkT1upO$%)vYMb*ofe@!%j&;#y;*VY6yFJL&}da4q{ z+NX|rKhJvk2txX29%+k8K0uo&cyU86Ive(uMH=FS@#-$vS({q0shl|U3hUDd4F;?hbQ#fK|v~lij^aHb4NJ``O zM)BrmXe@IU(@NW$%%!$BEQ)iUyjilZnF8#Busuy&A5QiW)|mD6@zT12B(hB6(O>R+ zyL^b*vhL%-+0C>58`_(!tEvNjlFV{%)||O8M-GTwyfnC(~WUfoX-m2fE>Ig-Iq%N z#<`zrzLE38Zp<_(dIX?mF^Ki5@|(l6nMKx@hv=1*6#T4~1(8gjH6Qrn2uP3*Mboic zU43Ipmuvc;gnUg!{3|U;spKbAkPbfkLORWP@q;;8?-txB7 zEiB?dGV8jb?nv?GdR4aZv`qb*IyqCmPh4yFhl%08xs1+jF!wgZR-#E(L*V(^HD|0G zVh(}~JpFt}3@$cx-?Uy|jJ6&Nm1BZdZe_8nx-F-UioV!H-Jq>`bZEJT9oAj^4>m0o zvt zk|&yXf-!l2)k$lTjFL*wtU%(ah>F(QIc$0|F`tmqv&5&0T zGkrr|-n{q4Ul(&|dYN_osg6bN^t1Dd{|0Qe8hbU`ayT71zEm> z3iLn|nJ{|7pF9(?EPHpk|IZ&scek``PV!2w1Y!Fz>bPr)%NcTh4d!y5kG)J{4dr&z zzm-B3(PN)KdY`4Lv)pvuDEh88Dc;WGD_*SlD`GFP$QIVXVa8SO(Stib_huV*ciJA= zon$taH?y&WC=`a={&k+i?x!feD!)`jMQX04{=&b5g1Pk;q+C6+T=DvoDZH(A)!ct~ z{1@wQ>;F)$e}NZ9wc=Wq!k}zR8Cl#W4DL9|7h#r<%}U#;e)3D7Dpd9G?Q5d;MC`Yt zRv*;Cx3-bl$Kz#bfqN5C^#@s>YvY7_wpUJ1hwsuw`3Etf;|`>SH&3yhk+$>G3@+2aLhjki;2LcpU zrTs4*>fQ)iM%#LNI(oLsn7@5%ZtA?KFA&t)(9+UU)6ybunp)a7+K29kI5;^u4WJLx zrQNL{mX?-|kh{;_`twFuQbIza*2~MwNG^+#uKw!T}&=m(aqhf#1`TcO->#O(^+>z%kL&&e<=nyNny4brLFyyw%?FB(Rd ztE@+zobQ%{ljHO4R;#MirP=GA>mDCDeU*1I89I`+b#=Jg<-g0yh@{zuI&H)lbS~z2 zEK!J^o}L~LnbZOJD8fs?eI7%6VxBPyJClM5r?*wOTft(Okk@x>e_?;&_&9a>^n*{i!=W?bt?w*_WIcgvPd3gM)L04YHEnT3B1_fbPPFf>i?{n=B`n;gTQr8hQ z`>XhW$-y}@@T_v0)))_LUaIV2N{}lx%e9jTdWVi?B!lHp-$Wl1yndlAzTHz zcs^dlEDb|Qc_LU;b`7U=0;oSKR|2$Zh$8ouj?FQI>|72j+ifqRvJ=JbONcpcLfYZ; zZ5Lj`^W_OzI*Yr~Y|0NAVtd@a@@)1??Os`w;GnD}l6#XEhhXOoMbu$K6dbC3L@0S~ z+#LaT{YM18Y@^u2hI3dLNj$c{g@BSH4=+mqE7U8ZSUyUu8Rnc%`tyHpf;{jf&FlB$ z``&}w32h?n23#k1BDH9Gw-#k(WkE|H|3Z#$8_qdOS#@|4Ywlh(N*?77Y;WvlnID=p zo_)IC@BJ)LJ|l)V$I(=|i~~Xk)t+xwv9g{P#H&vmi&@Y&QW8;I56Gh>%Wh|xXA*=nX3yl0@&enV0VED!6o5zKBQRH)9qGuvx8@1&3@ z{;ny^?Diqb9acAbn3)>PMe(H5p;a`6x9z1MU0oue)7U40Ihn2KUjy)t5@i3gIcD^n zjDGWc@WaDHhvKl6fK!h6wu583WysE*gyE*!+uP$k#~p~B`XVA42pqsW@7@36ygr_S zs4^5|NxW@^y5d|ZM5ZqTD%VcGli+K`WlffP5-IeN-?bE@A8ca=)HtqX95jC9t=nyC zofK-3`?|u>Fo$67@Z!)AnF6lxvTpw|BDMH?o)Z%sa>f@yy9|KS>=Tetm)EOd{4%e!ZLOva;vPTEqE~+z9oMp})Z?`vbjh zp&=0Sv{IX=Dj78pZpCz%PT8px=w)eduQfz=o{Wl~XA1lH{W%>kFE5#9tkF5ae=$)L z@E`jp19loI7a)_d;tI>~j=p&FVO#ZN`Fg=eBI65tIUQl+E$6i#um{lX*L;cto?%r$zd0tA zF!AP}yOlJ6@wAbo%4MX4vPr#3DZj$0X8t9H$$)>QVe}7WzdU3OMDk>(rK+l>s-dMy zsQvlV%9CyrVGBK%5{>iTgy*qeDgk=09u10YV-uveY4QeXS8(_QUV8TT*DB(?o}5<4 zIn|`(izDy2!~#WqocbMAv);^lW-Qk&m3k90dO2MnSR2R@n~WRRi4PO64gk9LDtT@9R|M%#6LFQ3w}(G_eF^>g5*}Na`h&b5^FuYD zKP`&*wd;eZxQadjN41V6cQzm4L17Xlq{{d4Q&dXDT)NTu!CkKB_u~O6@vnC0YOjdnts_&&JX-HWLi@H6b7=nDOwYv z3G^y0-u(7D=;&|%#)tJkjwt}8@g6N>=!Tu?R{^3C1z&djpI?F@S?FuGtRIi#w1vuF zF8IzO---m;0U^=lq#AS+zQCrIF=9R9555Y4%f+Dfz4B>OazN=fT*!`L0jI**PY(x|e8X#G^PLHI@YAL2PSaYTXc z9qu+$y|=g-N_}h)%Qw52`dHR_Di9hD3K!LM$^9TM%8+fv&z+U>c$=3k#^fKiWO_=%A6G~Yio->J<5dD?l_9CS(v zZ)&@B8*N8npt?tb%oefUcHC>5u)M%<;2P6CdQ+e5Sw&(Wg{KNqbX&LVS0bVI4Wkau z57#nOf$Z_>Jr;kn{!pl9ZQp#er=U>y4n+%%#W@9MqX?cy0SWF`dV&UmTG&~6wZKJu z?F}X+Veg2i=%i$E&O-P@DG}Uo9E{wluhpku_kaw}BwD{?F+`4S@VO~V1ckxGzLIJ1 zl*mX@-We*tTq5MZ%dgc zO+i(PYGM{CVBU=cZ$p(+EsQC4>8q)$x^Lj+lHqFB`%nUGWV_O*Tos9;ns$^Ml`u4k zJ%B;mrURgWT6ZE;bDxAN-~;QwS&sq29`lWz0n)9^&@=E4WF9NVm}1|gzXZz`FIyTUnu#iXpD;4yS^wm{PM&*gC%gYiGMxwIZsZe z(a(7(WnjuRa+n^!82Lp>h$nZvsC*{)|FfCrDyfu!HmC?8Y;k#cIk`lhaEEG*3w>g@ zvN|^x$AAJ$*F(LMzx=wD1;TiE59W)`Fg<`WA&ZT2;E^{G^F5;L3m62NWY}T1&{bU~%5rFp>e#^wmK@8zCpVRx`3CQ-tR} zi5)QZDCiQ)`B+(5{5YjG!0DIYp;>? zw(~OCkAosK0ryI*MD6G61-`z()*2s(JK`{vC@7q=RU z_{S)RZfcKa07P*uL_0FmECw%Qi{XvJvrE7(-Z`N5aa;96MZU3ZYX*k`Tv5@COz}Vx zW*Y!Mj@+4W#Cb=qNZZckeNCKRBP_|cM2-_N@CmPidgc`^dq{XrMglkGHpbJn$A-2KImy^vNO28plo^rdY#|@4n zbC4tej1Ve+(RgGeq5K$EqyFNpZcR8QwRuLGYh0Cv!;To{Gb9(jUUMD{yGz~@efj7| z54(9sm7D(PmsG+-FE@xpsSWOyU&?{MyXnsdb#uAwI?bF+|6i`f z57hg|0vtt9o(Q#TfUb7Vr%?^WFp)@eKhX@GZ6r9~KM5w?cj@U_qTrs_&N=q{B+>R9 zmx(gwUGG;0spTDm8KDnqkgwQ@YhoAX(s~*5=>=HVMGs~mZR|iwh4+c4x3Re@U zDzMfvhNUw~fsc!s*__Y+W)rQQ<3`0Zg2e2CNub-pTw65X8~>8=BvM^ZnA(RtI}1f; zkiHMD2{$qy+p&m_tbMf6J4MbVoW!-}`dM5>knHSra5eoQnQBjn31e_;cIJn$2<}hD zq!K#qTX*R;BW$J%JYrSJ^8@?)0WXq(zYZ7=I0ECBh$G&7-hQtiihJ-cb^DjXjks^& zP%#?EiLdDt%ccRRw)l5;;xO{w zq8`w8`TZY?wGT@Ea~$V?KIZR>jv0M{!T~ejH5tSza{L|Rug|ssk9W8P1>NtVpFDeh zk|q1HD0nH%<~v|;jqH`ugYD3-!U!q41lonE!A~TzKLK|fB|#Tsd~p=N3xkr}qFG*G zHTKmXvBy$6;(n`u;UpfHvOJ`|=L0YGZBICtXCwr?elZ?rh&_EdSHe5Ru>hG@R&ReF zp`)nWh7Q#Jjc?=`*1A>kKD)MDf6VDEh)^2jK&yB5v=s1Vfzc*SF9bJ6HT1ko4qR$L ztw;W|uNh5X&?T;74|6^P6hesS@uL@6KreDWw+Elx?fU?i9J zt7d5X5FiZKEl~)WtKh`d&&Z;qkVtb>B+drM3HHYUg%+QMopMPKNK8+ReSQ6hK96L` z(&OWotXme9n-Jb1ua)-~LWb=l#l=F|>?egkXhpx*Nr1W8nnkuQFMo_3WDR}I0(Al$ zWu5Iv&!{yEvJ+yZi7Cqs`7Y1_Ljcj>cL60{N(8x9vNoTU`|gv3x^=3cY;0}LeOV4c zGh!B_ra&=wkRI`#1!B$Dx)z{Hx~*L)I+6G=!9296zfj+Sw>f-3BIKu4LP{MT!GL>0 zR{Wc=q=|c;iAI59dZgM`j~{TS_un`e(tzv_RG0))mMeSxU2LBIFT<_1KgZgv7S#kB z&7uP-)h5a=#J09Rx-*}F50Fbe!nC}^xW)uu9!oa_b7=L#Wr6Q<`+X7s6R8BNoqh1N zx7Jq-swdPM#D3ql0LAFgrL+@A4JSzvgsmQJ`0n*$Gb*WeQlPB=dSjKPhEo7o0gy^Q z_?*sU44N-EI5O1alv~k=0{)RCpnMlA(pISc#mK)3OmD{%MM)^EpJq*jQE24w`N}qq zN~in|8qp<7#?hxxD*LXpN;|W3b)#L;UKa~viPi>!f(FGas+kFi>{NK~Yx}SF=%`ob;^Q z7=*~XHnda|{nj$=S-Af3!B*pC0sb@Ya>G>a{{Z$s{UK=~P=kZY?i`a#x zqOGc_Nx;H9P**APw$<^S&;teM`013ay!uk-IXZH&Tr-c~%gH24o~D6Vo>BAmAoN!?4a)vV7!u+oHYTXK;EjLDy3P?EG52D~~ZdY*~n^GRLCr{wmhV4g_-c~%Y-ex8nf25OTvDk^Y*0|SgM4FlYSxe714&X*&Qe6)o zEeMTVY`Ci&w??nc)(t2bNJM1@g?RW};+&J|#qRDVu=Vx2zRET~F|z$Y3Cg<$HR`-> zdnvm1DEn2XAo(@4p&)J#OXh}O&bIQKNG_{70bIn&vA_rF#O3_@#;h)1^Llu|0w$Bm zk?R8y=i(9b{%O0-kkqKnzIEr{lL!M)w6yo^%oKzZ8UOkZ`S?$W>K|H%`fDY3U+ej* zHuMwpcKE3DsOnDKQ-se?eZ&fk-crHc-#3l|Z71qjXksGR0AU@DUjfha5AfdOJ|wgl zKPr53A#g=K?_a&tYNk}>V2b-eXbY45@I)i9aOiFRKL0Llx&Pz|lH>L;`uiA%MW^#G z5^Vws5+%p^I*}8tG@zWpX(%gua)zl7DRPSgUlavjb2Jx(H{;AJG65P78Io`9weD}>(90%ie za?w^+%Zqd$VL0<{f2)6hTJj%&5GW~#FmTc99)Wx;ASDYVu1Gn zZ<_o1$Dn2K*0a}9Hl=hZE%m_R!$ymj*?5|wDIoFWAHSf2(Up`c8V#t0g&!2&mMC?C zM(WA^{RMs@DTHC!fBk3wIR$3zoQtEf$BhTVs4Sx-!ut5=%BY#k(z1I+k4oRRM_wgA z=%$TRHJ9IB1oxD9tGlqWmj7O)TFT1HGP{T1{>Yl$@3*0<`jYz*f~9>aV8XbPM^U7A z$nh7n+)Q#k{QAxElsJQ`NGnwU^iDY} zPUW6qv==)W3rqx3xJ*BVMJh8Z06$n93A9&{a~6qU8|tv9M(4gYMioNrw84=mIl8?Y zGD2k1Ht&m%FVlkMHx(LHDl-j_l`l@(KKq1si00HluRa^Li#U*O{}PgnDSNRtw5w_rp5@?-Iv78gp_(oScMcqP|>)2<(1Z!TD{P?x@(r+ zxQbWM!_`$4Njg&>rMrUE9Fv<5_ejQ@a$rzdO$dRH zhp}|d0JZ)Mi8QI+i!}sIWnb=P1vOV3-%mR(T2d;KCvlc3y)buf<;@Ej$Awc58B$HZ zS7zY>cm$LcqUNcC(zKP?g$)1WUH(@`$hE2eg+0xUH~Q@8a2LJ!?fhFSG7B6@xJwsR zh5M&ljMDk$f$bxML)@2^Rq~xy)2_cr#*$>m*|u3HW(>vrm12bK&cVl?C;RGGfFwP= zfGMz(qI@4du20T5i|6&Bry*RskcB24nQ;wIb%?c-UAF&~B;SqK>TN}LH>HxNsZLWy z=VhUH^KOnwg*LVY4>dm*9yldhq?bniQngP>;RQauZ8kEoZf#{8-(2ln)&#sx+692J zInoim|MHt4E`@Vr^fv?Gi0m{HM?aKEuCEiaVpR2h45lOZ_!K7}B{j1y1qwJNX>^Y= zyWAqmRVpJFv+7o%cC>dq3p9LFzp*~=Pah6eSNyOi?OYNTDWhy9yTGGBli;1axGC{l zbE*p1MC8ceHX(<;>2yp|BbHuLu$5EA#t@rSbM~QM)qHg0vSJ9k%-43| zYWnsFG{iXte)d=3t+B(J`Y%6)P2ztyipl+X=Uj1wwAMCyVLDO7pzCg4L6&#q(A)y5GM8v9;_@l441p2CSf+&O2gK?`ZB%r%0p%W$n}|OydY~f ztpy9t>@@$AUiU}1!7t8>je(0F&BeH+915vA$$VJ?%6cB>hnwq1!(fqS%kPuC%J~DX z0}%K%&vT{Yxtg`m5;OX^qWSw~&&XJAHmqZ#tN9p)V8bkEvI&Um&wC2mu7E* zTtkqG#O=LfE2c1Vfpx+b>0k{O=X?!16iiU0Y!*@S=NX*(wh>MnzLfxQGWj6r zGiS8WDWR$oVf;03&AbL&+BzCXMOjJ2dH?=6BIBbW*NdVUHKo6_coYyyqLBU%GOu2x zmfDc@1$=CMBS`mkwEX`j1N#Bq%8HU0#x%yXdl%fIfu~?zC%7|C4N-!=0?VI#LH{oC z?zRJ&(nhLud}8QSG%geawr#<^6#s&Iq1+lv>J|!>3jb@%uMqdld;iaLX1S?n18H3i zI7c*;tIg5RCxhmp<*zih8u+;-$=ge}8)J9U1>l@*um3CpAbz$amx#Fv_-HD!_Et$s zZc`IaL#9cLUNA+=cg0Af;_ur~0`^hZrNYaSbj+(E(-#k!<&1o`QkW+-PoM=Ny6a1FvItBOqPPf!y2`&=|7KBr!?Z-*(ljxs}wDatf(`fwoqK0!b z_4T3Ay~au>idmxXfZlW<`UT|#j2NNTH-YZ@Cbzhsc$mEa1p`NO3SeoH=8XJ+V@?M4 zp~^9E7Es|g=@UH;dw$DthB3N%K#o!LE+SG6pO$)SU?Apbyp!UhF{Ss7$Dr_<%vnWX zh47;X{XDaUlLzMIzixjJlg~;d=&UO_^gDLliuBrRf|^?`p80?fekP{T^Sn0Pr)-8@ z3~YHnC_q5?c!AB|qO8_`&(go{<#XmA(+C9OE?}McHZ-rikH9vw$UWg`aoO(N^Q z8w!({x?X3*ZQ0RJA-#5ckfsje2GVo*7kvJK-dGwM9F=ttCzRMTmweXx42E0rOnja| zGlWBu408nx;LrXxEMT{Hh-scKVs{t~A=0UJBt!w)_Ww$xDT8`wp=u3xvkLxn@9;>| z8Ut|BM;@O%?;}!R3~%MGpkQf1NQ)>*-p(+^{o1{&q>Vwnw{!>&wB4-}iDJ%cGaMO_ zQSs}hGQ>u8)z{!db>?CgN5gw6g#3Owl}Az|VeEZ-0dR(} zfPLcOlCdQLoyz{S(*!~qKllLuF?lskGILtjJq)i3=%fKSxgL zihf6`dVUwB2D5u$Z56591v{hhgxL0#Q9Im<&3EzuZYiLes+y{bN=v@si|ArgLDs+i zFSgSMums9|YJ?=z0`YvGyEM7lct1d^*{5_j|Mg=3hv7}3jAN035O;UO4-K1pAN+cm z>ELlc%J)9VQ0gkG4pI+Q>N2scL65Say?CNN&!%U;m|1@H!8e7fTQ}vOr^%&PdS+4e z-}DX0za8EWN;7(;T;jCu`Dnh9TdCsnZqZRKgf*_RY!P*8lMW<}0_PV0c<%AU2>{Gh0`GbTQhkl)^vN)h(1O0#a%{zQJ_DGPN) zOcS4gda46)aQ3PJdAF}UXj=>UqZKCH%eb`Ime*;Rk-h@VAlBG5!ICaU@lYS-`vrx8 zu85!rc9*y>WOBSDb)n>n4TfV8oETfJCtrI>5?vyMnWkG8M@)Y&-?dX>$!i! zUH6`|_v`Gldj7Jp2ozp}S!7pGs0rDQ?f-B>S%afZkn2DI=u7T`cd9vc*jE(#^-lRp z$@ILcNOUKPJf-RUICl6$f+mrT9>QxeRm1787}^z*76!aNX(AABmw0VXA7Sv`?9@%Y zx2+!}>5th&q8$ROM#;wq8H;|0(Y1T4S{~uQUKjC15WdHgG6nwST?m_-?424&PUjPF`FfUqATRRe`U1Qy1 zOA?q{YSQ>^lH4gJI!QblAREfcy6XKCg*#Pw4sQ8F>?O8PN673QFo}E-X4d<0^tMrF zK2aF`HigY$yxVV~RU*6E8R$;&oflFHU|2rutbez7{K*CgA;E#@3XIgh_6Y|eIkh1? zo&y%K`kXN^F2Wj&b`BKZ0GNEg0a==jn% z=OGXUHt<$-{7j=>o-;3`+488cq@W-k5coI$y7NnujwOUD;K_STCsxJG*$mw4v~NDW z=&R1wjlLfY(7UcLRo^OfMkq&|5RoJ42aR2!wsYhMClh|+3#(3)5~OXSxhsAIH(Ur(-@V}sP|tZ4Fft#eo}ajFQC{W(x6a{Eps0wQq7ShmYky59I%$5l`VT)6!;T znvJ!WBkF%u?X*Jw$?)u66sFADKZOV6r9VjxCcoi7Z3-JSNV&8|SmS3)8Jpza%yYWh ze&VGDBnPK7t}f`#w67Hb!gJFLtT$RFT>=Cneoq*>=13#LiW$|-7|dpN!h>u`XR<{# zZ+os|Ycs|f1imG^KwVp$fT!=vviX<}MfeSoS&3%ilh z(9MZd{Hu73Kl4ZV0&|I7b0$Twit722BPs{PgvIhcB$476nqR(cMvEDZbveT-iKL`Y zQ8izr{z^`)CFxU8FjG`)kLY+MmiXh4zjOO0=Tfv~Q6JCggufPztkxHVHFgaiNbQvy zdGwXwRsNJAKKzI=*b9A0bo(|lM+^Nv!itG29oh_-!Ad?ECkMX9gArwJrXSb@4hJ`3L%(-v+Qh1)*N7 zYL7nq^f$Y0wit;X8xupy)Y>2I>&gjdAW1=`IIG8k5NE6R>5_SL?tkH)_9}%k2&&l~d;`BrB z&TILBz!gAWOxkrDnPm&x06gS>zb$qBkm6*Y527f*<=VZep?}TlhMxQnm(Ee#CPrt^BE(QR0s|IBePeCV7b~(^kf$!z2|H zAu|+4a1MdHcOVf6;Ti@77D#ga#?gCy;++3G7r6D{20Fhzt>yR_MX%U9G}Xk`owppI zBdEkihpPU-Dg1w2<9||=8y#WbKN2I@-93QzX?b$8W|F6)qeBvaVwT9UgGVL@%LrUV z1T;Yf?$0LUYe7IvH-z4>S0aRl<~5(fDBgsdTh~#UET6>{ykzd}FS_*y@ivL%wq_aadHb zf5{l zf>(|bT{Gh}oGL`*hRp=7 zaqH3S`?onSy?IgKHky_ZvWQ;Xb4Sf+-bx4*u)7Pqy~XLjTUc0Fc|jZBztKTVVREJK zOr^JeT>byQx*KzJMS;W|CY?;l`oO0b=JPPQk!|J36a#6{dDIN{3N>#31*ezYn?Ah0^A{M_Qr*eB6|SihueI7733P75PS!LNwd? zIPNm~C7AJV!jBXeJU0obrTk`E;YcBVj=EnNum$01LgI9$f_Q^USK^yR1DswG3d;Oh z$L; z990*V>yt#P8Qp%O$BR|(pjpG_M>L@ZOdkl@8p4q1ue!z?{q|7526lh^fI?fS1aJrP zC0*sn-y!c?|Ak7?~WJ4T?a3y`GfmC^6p-4U}ux<_okBP><;D9t46}2xjn@|Hx@24kBA#jgc zokJz(ewJU@^=-Y~OZl@Zs$aZ=V8L_)$nTiX$CZq0Fmc#y54En2$(I{7Vj7zv@yFeF zHgXYJNhJgwv=7pSXi~NQRRaVJVG*kQD0EhT=o9j4aN-v}tXybQg)@HON+ySRmCV|S z;BnX4ApQTG**$-kZKe8B>*=>PEWeTn2b|(K_HE|*dfO76Z*Y2R-3^vAD+qd=4Jw+H zWD*Vk>O_55#TNsWTGTlK@*mws8OCn}p!6aB1H_&PoOCL1HKC$T3C?_AGLXKkpTikw z_8JLh)rBdt1I}9!{FV+tq`xAO7zLl}2>;k1ZEOAF87iM4e2f{+tPdHCS$|gt4E!2G zBq^1^r|11Om+rSvKaLl%Wf)_)2GTFMZ`B}mb8uqOTqVsgHCqVHt6%3bUPR@l<%ocl zcYmXfoAL%>*|L$%728zZ4hEb7Z%IgEiX=V=g$5-)$lYALUTjg1wu1`1`XwcaJ)_Vi zBMmT;-k}Zydu&1uv4IzO21K-J80!)tTOYu%Ba0TYd$p*ec=_Z1)lreyxTk%JqUmN&FTbvP zaMI)S;=%&&N8`%&`mMRig77nQsq!FypSDSVSIu3d*N@7wdl_DsO_qY>r9BM2=kc!l zC+We>0HLoHu97@&^&3X7MPZU4K>Bd8X?N+Xr=)&E)E@4vLc!yOI*%10xSyW#2wC>%eb=~jMv|2R!nqk{ z;TXfBl;q!!*9lR9v_BV|)u_d*4&CEvTX#p?Moxx{HGo?f4)zU&JxeKii3=aNM4s9w z8U$U&-J-J!X`xf|G48=j`KyP7mrWrj*nyU43i6QJkSu3%DEJL8L;XwnX4-^1$ou`A zeQ#P`$Oc{AdQQ)hh8vNzQc(WmMYo1yc`WsIupouf%!+E+F&GsMRH?P?%URX$E+j|B zPP+iG$4#78z;g~T#TKIeCqJB1NNPz6lrtJZ{2YIJbsOBHukW9=d*l^I&OVgwq4~dNxHD0%|9)X%@b+s~|+$0l<)aW}Fe23^%OH&WxR!{}3k_1TM0*AAeRBr#Th}sCxo5 z!Bro}EdeFkPClZ2*?yT?#cRZVZkM9oORD&r-sQvug~uMu?epKZ;BUlstwgBQhJQDV z*8M5uM-@n!@$k&`i|-1(524s>V+~obL`0RukxPSFs`kKqfOUyId(Q8Rn4*V*&zq0* zhvaU*!pQH=w@h`v!!-SYnnE`T@ZiKz>~9DeNISgyNWRsqeeA*M_VBAaFhF@%Tslzn zZXZ&#=O{IkZntIjlk(#Pp=W?-D0PbEL!VnNR(dFf^6;dv)phMij+qoReU5l5EH!3M zwWuf%BZX-4}qWRb? z;{Iz3#C!3`s;f~^li`DJ3wYR;;AU1Ia#?(D$wi;a`6;4SBroBcn~D)}QHnG#vBY!% zGeIeJgbui;Vtef^n|`bTi}BBgtu*52P4V2| zjh@rFCSlX3jd=d)r*^OIr&!LcJnUn;pRFbHoMf*2Da#RF-KPj8H6Fo1ep?LBL)#O1 z;#AqQ2EkvR?G8E~{n%Ol2U!t+kCIz$p>_TFQ?x@ky|gnXpo_4*%Be%k2|~v&R5$%+ z{mk(eRNb{DU%|1{bsNVCEen$}lBj;^c+-uaCO{pmRudpZ3kQuY#vZnWqU0d?hLVN% zG_OUYMweeUE6qh80T2f@@yZLiWn~H8l>V?)5UEBMx~Z|xewoxT&opK2Unw`jadkHZ ze}CO3`CB3Z!mocl=286Kd3bgw5M0KNm75yMhLd|KLDb45mR>uY@x?= zpoRi%3Uhz|UW*);?;8#SHMIS?V0+>8A9gtx51279m}^Z#6i z^R7FAsOun0M~@dy>~H7czu5_IuNLq3&1I-7&cEZ>7S zR(dn<4l$Scl^3X?m5btKx&aXMBc;wTTmQr);W9k`EllvzYcOxjyY&_GbD|=~P2x)= zyO7Ol#J1$sFXc}ufhJIIA4Wo`7i$t7rzCo>W=34#qQlHu`DB{a#S`)a-KskMx`)8j zGu8Jy4aX=E7-Ln}u^vHn936D$h_U%3mi{b!vLv@EQq#?6L{z;X_wZ9_?h;QtwE~Jg ze3@=$3R5NY3;KQ}{@z;!iq6P8|1~e}Bkb?aAWa=FJ5^|b4jvV~QZWNa5pf04y`FqD zLHR?fr*C8@KL1Y0cii>Xu^$Sug}PMqGdMDvZh3l$X6es70Gz$rkje1w8|k{hBtRk` zRT(oPZsuOHp@T;_2MA+Xe_F9WRYGV0PLSL985i2~1rbGIH~^ebDcg;8`v|@SAt3vr z(9z_76+cT8TPxBFCjKK)_4?`Z9Ia)#PvE?Y}oM^)eSj{1SI;S^H16bM=#K z;_f=P4)#Az6Te!S-CYhA;5|M{KzIxu^zOrvO*ww~o1Wdie7&Umxqj(Cced>yI{H6r zaq4;`I?6QpUgj6a`qN7bTJvI>ppqTf!Wt*ft_r(vs9>*YPJhx(Ol-8+|Lw3IR&OQB z;W%^_P#*?gO7~(HW&^tY#(Gd$;X{TJzBCMbV`Td)ej6F%pGG|7;Fx==9zQ=Hh{{D` zMp`Jb5+NdpCt8euBL{k&wdGHO1z%mjt`o750Tr?m*$mTiARhVRjJOn;5%a)&VLRbh zOSK*z`LVrS0LdZ3!p>oZcPKA^7tDru^8tkmPXTNHHk=HUV|*#GXC$-o+Q?!YTITK- zFkCnZd;)1`z&#a~+8iRtT8piB$e_BaCAMh6q}jTk5Al}n0hCSH~v+ip0iEzvn#(;)*3x`n$IHilihH&f!6ec84%7r;1oPh`C zu_1Xj-4en2XV2rCryPE8%XDIli?i_-_|X#May48NasHr5}v^m z39TO3ow;aV1K^QJbR@Rc(Nm((Z;J?OPrgGRhw->jEQh&3-0ZSkC8*$B+-`ET?TY0L zrhqNjNA7n(|21_B!@3}E#jdEr08yS|G5H7q{f{MxaCdp;S3tBZHFY&kp`XmisM1@{(`IW2bJ_-MW=th}Th*ns?`Me3!;9+4eXJmY3r{=XU`KXH zND}&2a>DrO2@7-;JHcH*0c1XD&LEp+wi-ks@O!JF z;7^EQ%XqW&n0l0+qX#9i@GHZ>=Q|C7>?3(~Gm({NMUHgX|6K^%$RMASPmK=#wzjq}T!OK{DtwZR ziPto6TNcZ#H+11%3@Vx1N6T-*d~7>J(c0fdLwMI^_}C&$MGE1)?b5SG_`bQ5^u{So zO2eCYYp$#(3-5;8dcDZugQqiNf{S*{X51StL^Kq?xxBo$C?AJS91-N$HjDDGmk>a( zm#yO~!C2xv9w;d8(ZO_Gn_v$(0n5Y~o^1xpk4WB2noE(z;Xduj`&2oN#5$TN3xs;V zCe_x&z*&; zWju`~Vv4cn0LD=>-O=^n@Oufx>3iBO!f|aM-x?iJvq?edVu zp-#lX6IbPU=|?U(PK1cyuZ4OYk)gSD431*s*KH=}^#|K;)No$b*dX3NG&qJVkd@7+ z7Vo;nj>%9F@MzF0Vmo$4kKokXpjI-v1r<7(F(T?P_)Wa%51QGwGg63>gbG#zQggh? zP24ZD&xC|Tqb13lmH+-5@eARfRy#7Fr`7nMx)q%8RY5#5riDn|A3KBWZMA_nmsWw?>uW{PlQ6`=cRi2Ls+T9?L?y z=A;~|yTEQyh44iRJ(TIEM2ZxNH#3JAnTn;dO~}xWuOEawS{&u(tFJ4XQ(R z!pxdf)LP}{!tmIH;FC^hQV!;0mshF99Yu*Wvw!OzTtMt#w&=SIwdxyk%fBQMi(6Yflv+jkUG zKvZ^g?)UKe)kp4`k56EiepI3?vx1n&zK2btB9myyQQIFcK*NNKyr9eZbI!JS)vKd0 z+QDQqyj7Udp?V_c!+GkPux3~*BI{RLD~%0o5$~7+>1U$Wwhvh?kZgdqjGM7`xFgxfE}LZIb<2FPPW#1$?&skk&o6;b96=p@&+yEWc`xU^ zY1TT?$NV2`4vf(Ms@B~5aiFOp!-$&I)0w!!UPiWq!eyDaF~Uq@ts0DS^H1}H;OEO# zi)3tc`$7+?TRW^X+>h~;bNHFejhVSEd3`k+j&-N$GG>?7R*19RKSIfh+ z`yWGWF{z>e@&ez!4rx`n6yQ+F!e2>$8yy{unf|lCdwHEWef{-|)R@5IY-*V;c6&%& zZeeZD-wPpiOd7FW6c(Vs2R(n5ncZ7>J+IFak|d)QtF+V7jCU7;TgE`4W|*{8cyX^K zOAb^P!*DHJg&&5+U(@wuGD79x*W+G+7b@V)UfWsxT6@Sz zSRWd0%Jh8T)st;nQ9%BT1YY5Ow7O$kv5PxO;DxIE#NZ+dEq=xTfds5~;$)`MeAvR7 z2)C5Z5OZlz!h+_{y`I(cG1Dse2UAF;GD8?E0rW&}w2bkFHX|f_a)uK(WdS)f_ejI} z;KHc6+kPhTBH^4Ibo^9hmzfetjSN> z0)rgR#$s%iXd6oeVf|{nI4o`U0>qKH)EQ-kP92Mewi>0+{oXjRwAtzkv`^<){CXLt zY$DpGVz>Wpx);FoEdVYRQSjim%qD!>PuXBU?d}FqLd0D@aYFT~CVdY-=3x+NrS8R> zElgK`@(*|JxH-3-8%+fWn8l69a_Q!>Fyf80>$9h$>)v!#4C_Wnm7=e-)G=mY<#(Th zdm0{WqJCT9@(#TQyOnU^#e~a&QI=&XG3~5*eTmhIdL|710$Q#)+P5WT7JBG?S-$OG;t-$?f z^5sd=B(;=UEi-SSocVAnCH<`}wB%tF_I#yEV|P7MH;GYfOFWQ5@t_S>rEfV||8ezQ zlWu{iHC%gThJUl@?Pyxmf=PvRI+IhQzy?m|v^|w}7bH{7fzG!^*674Knzn`}3-;U5 z);DpM(3#jtxzM5%K_h#Bn^dy01z27TU;p6+NF=>$Qe5vl3z@DOnKrXhhPQ2tC|+*9 z=O^UqjTMR9ZXO9-%>73a^H!0If4Pc%sbpt9E<8yWc4@ahnhV_EuO|h4n|y1!Lj6~C zje4!EuAA(?ZpYhqJ52xkgZEUfP*ZbLQ^^LEZ4+q^ifyl+(_CbHqx0DxIW>6SE`X1C zE29O|e{6NOv{4UXUd+FD2fbb&`x{+Cd~3uan=k`KeFZra3brH6c~OsTH*Q29DcN(W zZ4|*k#ng;31GGeS3)r1!xZ&Cyxoc@@#&G>sAPi$ye2KLn`2#2{i&|hFHZw8HSknd} z@U=ptQwqmV!@UqkQPgL!+c_Mcv~i&p5v3@+0pO27KBudI45EFxdRP*|j~bQ_KU1N$ zXAFdi1k*W19v9E}U-pHf{Aj|40(O@%?5vPJ-L@Z6<-2|-1%mNr9QBvKE+H2ZkK`hIJ6-8kTjl#1Bu zZAQg^W8xh=v6iY5B7U}5^bjd0vPgF1btG|f<|L;z#FAejpjQ$!h7^)}DIVK5X+Yz2 z3#k0MKR@_75J_$|?AZd-P*=R_jo8_!5*JH#o=N}kC5QJYf7JUX8jW4>M||1}p^qoAbzf8>UUnT{QSuSr$Ja zrpXJ_PYAU2Fpgia5q4_%ehD0~rh>}WByP2oM=Pzol)qPNtd5j<`k-{QH}#iR_)ta0 zJe|$7+;CKP$4q_j)dWInc75NU-K1{6C>48)DF2o>nW0daf@B-@-0n{MOZ-QpR_f73 z8=cl#mSDc{R+LI@5DrgZ7i1+~8-;Y_(u_inOcxHp zPvtlirxsz?pg+D&9?|?hJ|-4dXuu|oU9U~-r>f^8xiVOlDZogoWIo<(8Ig&gL^Uw^yC{}unr`&Pp=bj zUcLDmn)+_Ys~x%gH@~SVxd@SILFnA*<{K6QH-t*Yn};Tc(2xL`DkL3ROcJ_jUO>Ca zPD4_w1gUrq(OSjThndu;3nz^tThrEO_E%>)h24idOETYIrtlcMaH%i}oYFT>;n_+A zBbytzUa_6Va$&Mqf#LI^+n!53jp!)larGfofn@t(k6SH2`&GUaU6D9Z0W1)_q{!71{8qWWa#G&(V^5Tp-OXC zu&-^C&Ki%e&H@S~SopI6ca&OvKqscusXhCh%W-Y7$M|TF}ZqZs)#9W$icOFr7E+VM<3UxW&AJi|+KoCuG zYU-Rt@4By*Y$~5uEub`PnDQ7T@2e*BGbc<3MoRQo+c;lohd<&n7*pz6y=xdEqj<)q z3z+v^62zC!$hoxn@sXCC`HW~a2pYpDe{yVO(>>928QSfQC!EDSbL?5bf{dDaYXbMl zqa7{#)y~uV5sVd+07&LAy@v!*M8ClXD;#NO_HG<7?3~lukVl7WkU?yuWSFv<@poNoT&*oXz|iqqp+8bN#~2BrvF2cH`bQc zmX_88g~Z-?MNk$!P3o0RU0+T74Y&;!{wKNg%&i9Bui&@2yU|8rl$_q3&Lwo>QlGp8 zo&F>8T=#NCz5lNLUH;kh55&uP$^6NA0rSAw58O568`iC<90iTDCY*#+rem)Ku-4r6 zV%tm4JR_strDO#T$?UZ+SkN@*_SrlnGrOBhkI;Fpg(7;ikpV2*le}*0h?)rKZ$>El zNFT<&PG&s$m3H~ld+fyW8J0P^cdmV;aZA;BSxBEjJ~i^>?o%m;2*kzZmLo)r!AAxl zy(dL6L+Pw3Dm{4zY#NlPk<~l0*AF4J-akt~>IpGZk3&{f z&gmn)J3P(26>96t?tSlj5@#&_eWN0PRP)gCmqZzDkvP{QAnhY6WNBbyV;e9!7mC*X zxdIwRwUj^-`0Xi(p7kLpyvi37W8xzB^bWnu|#TRJ}L~W#*OLRHJwV~Bh z;eIsR963(fc9KdAnq#9V`t8Z1j6t6_zf$KnSzFR)*el#K#!d5!VcXzGGs85|92Yn( zq(&yI6AP1NP?7zg=h%x9U^pscw}GT@(UN7W^ZE5!s zx7vao&mx)_l3?skR~`7;?uP}1Eo$Y==%nQ<87CBW$ecGWxYrE8`m#yOr>2%U-n6*mwLqcbsYZ3F;h4qAU z$~^@^(Zl5IC`{!(FKQvFX7@y42egSh5{-;B`c$JVd-OBrHtr!oKL7-(up0x-pckb) zA}AF`qM6h7_?csGZSePPsLfL+_zMw3V;(V#J%+9_%w`Gok@6=I+px!awE9T-)PWc@ ziRlmd>b5BMapT7bLL{?!pwi9_B2og}nD`2m0hA?^j$+I{u7Z#{mKv~(x^X+=lxN

      } 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

    2. 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 @P0?*l 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

      N4sYFF+CH^m!}j^+cfzG5){oL1A>r{t{)b5 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∓B^8>Vr;v#2Q($WX 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